1
1
mirror of https://github.com/Rundll86/Dog-Lynx-And-HCN.git synced 2026-05-27 22:41:56 +08:00
Files
Dog-Lynx-And-HCN/scripts/Structs/Weapon.gd
T
fallingshrimp c413744dbf feat(武器): 添加武器描述和彩蛋文本
为多个武器添加了彩蛋文本(tease)和来源信息(sources),包括GrassWall、Hetun、Tree、BigLaser、Cogwheel、Bow、DaoStatue和HXD。同时更新了武器描述和部分属性:
- 为BigLaser更新显示名称为"金法阵"并修改描述
- 为DaoStatue增加攻击力从30到50
- 更新HXD的描述文本
- 在Weapon.gd中添加teaseLabel的显示/隐藏逻辑
- 在Rooster.tscn中更换默认武器为DaoStatue
2026-04-04 13:32:15 +08:00

201 lines
6.5 KiB
GDScript
Raw 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.
@tool
extends PanelContainer
class_name Weapon
@export var avatarTexture: Texture2D = null
@export var displayName: String = "未命名武器"
@export var quality: WeaponName.Quality = WeaponName.Quality.COMMON
@export var typeTopic: WeaponName.TypeTopic = WeaponName.TypeTopic.IMPACT
@export var soulLevel: int = 1
@export var costBeachball: int = 500
@export var chargable: bool = false
@export var oneShoot: bool = false
@export var store: Dictionary = {
"atk": 10
}
@export var storeType: Dictionary = {
"atk": FieldStore.DataType.INTEGER
}
@export_multiline var descriptionTemplate: String = "造成$atk点伤害。"
@export var sources: Array[String] = []
@export var tease: String = ""
@export var needEnergy: float = 0
@export var cooldown: float = 100
@export var debugRebuild: bool = false
@export var level: int = 0
@onready var avatarRect: TextureRect = $"%avatar"
@onready var nameLabel: WeaponName = $"%name"
@onready var sourceLabel: Label = $"%source"
@onready var teaseLabel: Label = $"%tease"
@onready var energyLabel: Label = $"%energy"
@onready var beachball: ItemShow = $"%beachball"
@onready var soul: ItemShow = $"%soul"
@onready var descriptionLabel: RichTextLabel = $"%description"
@onready var updateBtn: Button = $"%updateBtn"
@onready var extractBtn: Button = $"%extractBtn"
@onready var inlayBtn: Button = $"%inlayBtn"
@onready var sounds: Node2D = $"%sounds"
@onready var moveLeftBtn: Button = $"%moveleft"
@onready var moveRightBtn: Button = $"%moveright"
var cooldownTimer: CooldownTimer = null
var originalStore: Dictionary = {}
var chargedTime: float = 0
var attackSpeed: float = 1
func _ready():
cooldownTimer = CooldownTimer.new()
cooldownTimer.cooldown = cooldown
originalStore = store
updateBtn.pressed.connect(
func():
apply(UIState.player)
)
extractBtn.pressed.connect(
func():
if soulLevel > WeaponName.SoulLevel.NORMALIZE:
UIState.player.getItem({
ItemStore.ItemType.SOUL: soulLevel - 1
})
soulLevel -= 1
updateStore(level, UIState.player)
rebuildInfo()
)
inlayBtn.pressed.connect(
func():
if soulLevel < WeaponName.SoulLevel.INFINITY:
if UIState.player.useItem({
ItemStore.ItemType.SOUL: soulLevel
}):
soulLevel += 1
updateStore(level, UIState.player)
rebuildInfo()
)
moveLeftBtn.pressed.connect(
func():
if get_parent():
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():
if get_parent():
var myIndex = get_index()
var rightIndex = min(myIndex + 1, get_parent().get_child_count() - 1)
get_parent().move_child(self , rightIndex)
ArrayTool.swap(UIState.player.weapons, myIndex, rightIndex)
UIState.player.rebuildWeaponIcons()
)
for i in sounds.get_children():
i.process_mode = ProcessMode.PROCESS_MODE_ALWAYS
rebuildInfo()
debugRebuild = false # 只能在编辑器里打开
func _physics_process(_delta):
if debugRebuild:
rebuildInfo()
func canUpdate():
return UIState.player.hasItem({ItemStore.ItemType.BEACHBALL: costBeachball})
func canInlay():
return UIState.player.hasItem({ItemStore.ItemType.SOUL: soulLevel})
func apply(entity: EntityBase) -> bool:
if canUpdate():
level += 1
entity.inventory[ItemStore.ItemType.BEACHBALL] -= costBeachball
updateStore(level, entity)
costBeachball = floor(GameRule.weaponUpdateCost * costBeachball)
rebuildInfo(true)
return true
return false
func updateStore(to: int, entity: EntityBase):
store = update(to, originalStore.duplicate(), entity)
func multipiler() -> float:
if is_instance_valid(UIState.player):
return 1 - UIState.player.fields.get(FieldStore.Entity.PRICE_REDUCTION)
else:
return 1
func rebuildInfo(showNext: bool = false):
avatarRect.texture = avatarTexture
nameLabel.displayName = displayName
nameLabel.quality = quality
nameLabel.typeTopic = typeTopic
nameLabel.soulLevel = soulLevel
nameLabel.level = level
sourceLabel.text = " × ".join(sources)
if len(tease) > 0:
teaseLabel.text = "%s" % tease
teaseLabel.show()
else:
teaseLabel.hide()
energyLabel.text = "%.1f" % needEnergy
beachball.count = costBeachball
soul.count = soulLevel
if is_instance_valid(UIState.player):
beachball.enough = canUpdate()
soul.enough = canInlay()
descriptionLabel.text = buildDescription(showNext && (canUpdate() || canInlay()))
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 ("%.1f" % (value * 100)) + "%"
elif type == FieldStore.DataType.ANGLE:
return "%.1f°" % value
elif type == FieldStore.DataType.FREQUENCY:
return "%.1fHz" % value
else:
return str(value)
func buildDescription(showNext: bool = false) -> String:
var current = store
var next = update(level + 1, originalStore.duplicate(), UIState.player)
var result = descriptionTemplate
for key in store.keys():
var data = current[key]
var nextData = next[key]
var type = storeType.get(key, FieldStore.DataType.VALUE)
data = formatValue(data, type)
nextData = formatValue(nextData, type)
var text
if showNext:
text = "[color=cyan]%s[/color]→[color=yellow]%s[/color]" % [data, nextData]
else:
text = "[color=cyan]%s[/color]" % data
result = result.replace("$" + key, text)
return "[center]%s[/center]" % result
func readStore(key: String, default: Variant = null):
return store.get(key, default)
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 canAttackBy(entity: EntityBase):
cooldownTimer.speedScale = entity.fields.get(FieldStore.Entity.ATTACK_SPEED) * attackSpeed
return cooldownTimer.isCooldowned() and entity.isEnergyEnough(needEnergy) and checkAttack(entity)
func tryAttack(entity: EntityBase):
if canAttackBy(entity):
var result = await attack(entity)
if result:
cooldownTimer.start()
entity.useEnergy(needEnergy)
return result
func charged(base: float, percent: float):
return base * sqrt(1 + chargedTime / 15 * percent)
# 抽象
func update(_to: int, origin: Dictionary, _entity: EntityBase):
return origin
func checkAttack(_entity: EntityBase) -> bool:
return true
func attack(_entity: EntityBase):
pass