2025-09-05 22:23:41 +08:00
|
|
|
@tool
|
|
|
|
|
extends PanelContainer
|
|
|
|
|
class_name Weapon
|
|
|
|
|
|
2025-09-21 13:34:51 +08:00
|
|
|
@export var avatarTexture: Texture2D = null
|
2025-09-05 22:23:41 +08:00
|
|
|
@export var displayName: String = "未命名饲料"
|
|
|
|
|
@export var quality: WeaponName.Quality = WeaponName.Quality.COMMON
|
|
|
|
|
@export var typeTopic: WeaponName.TypeTopic = WeaponName.TypeTopic.IMPACT
|
2025-09-20 07:01:17 +08:00
|
|
|
@export var soulLevel: int = 1
|
2025-09-20 17:23:57 +08:00
|
|
|
@export var costBeachball: int = 500
|
2025-09-05 22:23:41 +08:00
|
|
|
@export var store: Dictionary = {
|
|
|
|
|
"atk": 10
|
|
|
|
|
}
|
2025-09-06 16:11:59 +08:00
|
|
|
@export var storeType: Dictionary = {
|
2025-09-17 22:25:27 +08:00
|
|
|
"atk": FieldStore.DataType.INTEGER
|
2025-09-06 16:11:59 +08:00
|
|
|
}
|
2025-09-05 22:23:41 +08:00
|
|
|
@export var descriptionTemplate: String = "造成$atk点伤害。"
|
|
|
|
|
@export var needEnergy: float = 0
|
|
|
|
|
@export var cooldown: float = 100
|
2025-09-06 08:17:10 +08:00
|
|
|
@export var debugRebuild: bool = false
|
2025-09-06 11:14:02 +08:00
|
|
|
@export var level: int = 0
|
2025-09-05 22:23:41 +08:00
|
|
|
|
|
|
|
|
@onready var avatarRect: TextureRect = $"%avatar"
|
|
|
|
|
@onready var nameLabel: WeaponName = $"%name"
|
|
|
|
|
@onready var energyLabel: Label = $"%energy"
|
2025-09-06 11:14:02 +08:00
|
|
|
@onready var beachballLabel: Label = $"%beachball"
|
2025-09-20 07:01:17 +08:00
|
|
|
@onready var soulLabel: Label = $"%soul"
|
2025-09-05 22:23:41 +08:00
|
|
|
@onready var descriptionLabel: RichTextLabel = $"%description"
|
2025-09-20 07:01:17 +08:00
|
|
|
@onready var updateBtn: Button = $"%updateBtn"
|
|
|
|
|
@onready var extractBtn: Button = $"%extractBtn"
|
|
|
|
|
@onready var inlayBtn: Button = $"%inlayBtn"
|
2025-09-06 08:50:37 +08:00
|
|
|
@onready var sounds: Node2D = $"%sounds"
|
2025-09-21 21:58:57 +08:00
|
|
|
@onready var moveLeftBtn: Button = $"%moveleft"
|
|
|
|
|
@onready var moveRightBtn: Button = $"%moveright"
|
2025-09-05 22:23:41 +08:00
|
|
|
|
2025-09-06 15:24:50 +08:00
|
|
|
var cooldownTimer: CooldownTimer = null
|
2025-09-06 11:14:02 +08:00
|
|
|
var originalStore: Dictionary = {}
|
2025-09-06 07:40:21 +08:00
|
|
|
|
2025-09-05 22:23:41 +08:00
|
|
|
func _ready():
|
2025-09-06 15:24:50 +08:00
|
|
|
cooldownTimer = CooldownTimer.new()
|
|
|
|
|
cooldownTimer.cooldown = cooldown
|
2025-09-06 11:14:02 +08:00
|
|
|
originalStore = store
|
2025-09-20 07:01:17 +08:00
|
|
|
updateBtn.pressed.connect(
|
2025-09-05 22:23:41 +08:00
|
|
|
func():
|
|
|
|
|
apply(UIState.player)
|
|
|
|
|
)
|
2025-09-20 07:01:17 +08:00
|
|
|
extractBtn.pressed.connect(
|
|
|
|
|
func():
|
2025-09-20 07:03:55 +08:00
|
|
|
if soulLevel > WeaponName.SoulLevel.NORMALIZE:
|
|
|
|
|
UIState.player.getItem({
|
|
|
|
|
ItemStore.ItemType.SOUL: soulLevel
|
|
|
|
|
})
|
|
|
|
|
soulLevel -= 1
|
2025-09-20 07:08:18 +08:00
|
|
|
updateStore(level, UIState.player)
|
2025-09-20 07:03:55 +08:00
|
|
|
rebuildInfo()
|
2025-09-20 07:01:17 +08:00
|
|
|
)
|
|
|
|
|
inlayBtn.pressed.connect(
|
|
|
|
|
func():
|
2025-09-20 07:08:18 +08:00
|
|
|
if soulLevel < WeaponName.SoulLevel.INFINITY:
|
2025-09-20 07:01:17 +08:00
|
|
|
if UIState.player.useItem({
|
|
|
|
|
ItemStore.ItemType.SOUL: soulLevel
|
|
|
|
|
}):
|
|
|
|
|
soulLevel += 1
|
2025-09-20 07:08:18 +08:00
|
|
|
updateStore(level, UIState.player)
|
2025-09-20 07:01:17 +08:00
|
|
|
rebuildInfo()
|
|
|
|
|
)
|
2025-09-21 21:58:57 +08:00
|
|
|
moveLeftBtn.pressed.connect(
|
|
|
|
|
func():
|
|
|
|
|
var myIndex = get_index()
|
|
|
|
|
var leftIndex = max(myIndex - 1, 0)
|
|
|
|
|
get_parent().move_child(self, leftIndex)
|
|
|
|
|
ArrayTool.swap(UIState.player.weapons, myIndex, leftIndex)
|
|
|
|
|
UIState.player.rebuildWeaponIcons()
|
|
|
|
|
)
|
|
|
|
|
moveRightBtn.pressed.connect(
|
|
|
|
|
func():
|
|
|
|
|
var myIndex = get_index()
|
|
|
|
|
var rightIndex = min(myIndex + 1, get_parent().get_child_count() - 1)
|
|
|
|
|
get_parent().move_child(self, rightIndex)
|
2025-09-21 21:59:14 +08:00
|
|
|
ArrayTool.swap(UIState.player.weapons, myIndex, rightIndex)
|
|
|
|
|
UIState.player.rebuildWeaponIcons()
|
2025-09-21 21:58:57 +08:00
|
|
|
)
|
2025-09-06 08:50:37 +08:00
|
|
|
for i in sounds.get_children():
|
|
|
|
|
i.process_mode = ProcessMode.PROCESS_MODE_ALWAYS
|
2025-09-05 22:23:41 +08:00
|
|
|
rebuildInfo()
|
2025-09-06 08:17:10 +08:00
|
|
|
debugRebuild = false # 只能在编辑器里打开
|
|
|
|
|
func _physics_process(_delta):
|
|
|
|
|
if debugRebuild:
|
|
|
|
|
rebuildInfo()
|
2025-09-05 22:23:41 +08:00
|
|
|
|
|
|
|
|
func allHad(entity: EntityBase) -> bool:
|
2025-09-06 11:14:02 +08:00
|
|
|
return entity.inventory[ItemStore.ItemType.BEACHBALL] >= costBeachball
|
2025-09-05 22:23:41 +08:00
|
|
|
func apply(entity: EntityBase):
|
|
|
|
|
var allHave = allHad(entity)
|
|
|
|
|
if allHave:
|
2025-09-06 11:59:24 +08:00
|
|
|
level += 1
|
2025-09-06 11:14:02 +08:00
|
|
|
entity.inventory[ItemStore.ItemType.BEACHBALL] -= costBeachball
|
2025-09-20 07:08:18 +08:00
|
|
|
updateStore(level, entity)
|
2025-09-09 22:32:07 +08:00
|
|
|
costBeachball = floor(GameRule.weaponUpdateCost * costBeachball)
|
2025-09-06 11:59:24 +08:00
|
|
|
rebuildInfo()
|
2025-09-05 22:23:41 +08:00
|
|
|
return allHave
|
2025-09-20 07:08:18 +08:00
|
|
|
func updateStore(to: int, entity: EntityBase):
|
|
|
|
|
store = update(to, originalStore.duplicate(), entity)
|
2025-09-05 22:23:41 +08:00
|
|
|
func multipiler() -> float:
|
|
|
|
|
if is_instance_valid(UIState.player):
|
|
|
|
|
return 1 - UIState.player.fields.get(FieldStore.Entity.PRICE_REDUCTION)
|
|
|
|
|
else:
|
|
|
|
|
return 1
|
|
|
|
|
func rebuildInfo():
|
|
|
|
|
avatarRect.texture = avatarTexture
|
|
|
|
|
nameLabel.displayName = displayName
|
|
|
|
|
nameLabel.quality = quality
|
|
|
|
|
nameLabel.typeTopic = typeTopic
|
2025-09-19 22:21:32 +08:00
|
|
|
nameLabel.soulLevel = soulLevel
|
2025-09-06 11:59:24 +08:00
|
|
|
nameLabel.level = level
|
2025-09-05 22:23:41 +08:00
|
|
|
energyLabel.text = "%.1f" % needEnergy
|
2025-09-06 11:14:02 +08:00
|
|
|
beachballLabel.text = str(costBeachball)
|
2025-09-20 07:01:17 +08:00
|
|
|
soulLabel.text = str(soulLevel)
|
2025-09-06 08:17:10 +08:00
|
|
|
descriptionLabel.text = buildDescription()
|
2025-09-20 17:23:30 +08:00
|
|
|
func formatValue(value: Variant, type: FieldStore.DataType) -> String:
|
|
|
|
|
if type == FieldStore.DataType.VALUE:
|
|
|
|
|
return "%.2f" % value
|
|
|
|
|
elif type == FieldStore.DataType.INTEGER:
|
|
|
|
|
return "%d" % value
|
|
|
|
|
elif type == FieldStore.DataType.PERCENT:
|
|
|
|
|
return ("%d" % (value * 100)) + "%"
|
|
|
|
|
elif type == FieldStore.DataType.ANGLE:
|
|
|
|
|
return "%.1f°" % value
|
|
|
|
|
else:
|
|
|
|
|
return str(value)
|
2025-09-06 11:14:02 +08:00
|
|
|
func buildDescription() -> String:
|
2025-09-20 17:23:30 +08:00
|
|
|
var current = store
|
|
|
|
|
var next = update(level + 1, originalStore.duplicate(), UIState.player)
|
2025-09-05 22:23:41 +08:00
|
|
|
var result = descriptionTemplate
|
|
|
|
|
for key in store.keys():
|
2025-09-20 17:23:30 +08:00
|
|
|
var data = current[key]
|
|
|
|
|
var nextData = next[key]
|
2025-09-06 16:11:59 +08:00
|
|
|
var type = storeType.get(key, FieldStore.DataType.VALUE)
|
2025-09-20 17:23:30 +08:00
|
|
|
data = formatValue(data, type)
|
|
|
|
|
nextData = formatValue(nextData, type)
|
|
|
|
|
result = result.replace("$" + key, "[color=cyan]%s[/color]→[color=yellow]%s[/color]" % [data, nextData])
|
2025-09-06 07:40:21 +08:00
|
|
|
return "[center]%s[/center]" % result
|
2025-09-05 22:23:41 +08:00
|
|
|
func readStore(key: String, default: Variant = null):
|
|
|
|
|
return store.get(key, default)
|
2025-09-06 08:50:37 +08:00
|
|
|
func playSound(sound: String):
|
|
|
|
|
var body = sounds.get_node_or_null(sound)
|
|
|
|
|
if body is AudioStreamPlayer2D:
|
|
|
|
|
var cloned = body.duplicate() as AudioStreamPlayer2D
|
|
|
|
|
add_child(cloned)
|
|
|
|
|
cloned.play()
|
|
|
|
|
await cloned.finished
|
|
|
|
|
cloned.queue_free()
|
|
|
|
|
func tryAttack(entity: EntityBase):
|
|
|
|
|
if cooldownTimer.start():
|
|
|
|
|
if entity.useEnergy(needEnergy):
|
2025-09-13 19:55:51 +08:00
|
|
|
return await attack(entity)
|
2025-09-05 22:23:41 +08:00
|
|
|
|
|
|
|
|
# 抽象
|
2025-09-06 11:14:02 +08:00
|
|
|
func update(_to: int, origin: Dictionary, _entity: EntityBase):
|
|
|
|
|
return origin
|
2025-09-05 22:23:41 +08:00
|
|
|
func attack(_entity: EntityBase):
|
|
|
|
|
pass
|