mirror of
https://github.com/Rundll86/Dog-Lynx-And-HCN.git
synced 2026-06-04 10:47:13 +08:00
feat: 添加武器升华系统及相关UI组件
实现武器升华功能,包括: - 新增SublimateOption类处理升华选项 - 添加SublimateOptionHandler UI组件 - 在武器卡片中集成升华界面 - 重构武器描述生成逻辑 - 新增钻石资源消耗机制 - 优化UI布局和样式 - 修复多处类型引用错误
This commit is contained in:
@@ -25,7 +25,7 @@ func beforeOpen(_args: Array = []):
|
||||
for feed in ComponentManager.feeds:
|
||||
var card = feed.instantiate() as Feed
|
||||
card.freeToBuy = true
|
||||
if card.topic == FeedName.Topic.WEAPON:
|
||||
if card.topic == CategoryStore.Topic.WEAPON:
|
||||
if weaponCounted < OutGameStorage.maxInitialWeaponCount:
|
||||
initialWeaponSelection.add_child(card)
|
||||
card.selected.connect(
|
||||
|
||||
@@ -3,17 +3,33 @@ extends Weapon
|
||||
|
||||
func sublimateOptions() -> Array[SublimateOption]:
|
||||
return [
|
||||
SublimateOption.new("健体·阳", "格挡次数+1", func(w: Weapon, _e): w.addStoreExtra("count", 1)),
|
||||
SublimateOption.new("健体·阴", "气力上限+1", func(w: Weapon, _e): w.addStoreExtra("max", 1)),
|
||||
SublimateOption.new("引气入体", "乾坤剑伤害+6", func(w: Weapon, _e): w.addStoreExtra("atk", 6)),
|
||||
SublimateOption.new("引气入体", "乾坤剑伤害+6",
|
||||
func(w: Weapon, _e): w.addStoreExtra("atk", 6),
|
||||
1,
|
||||
CategoryStore.Quality.COMMON
|
||||
),
|
||||
SublimateOption.new("健体·阳", "格挡次数+1",
|
||||
func(w: Weapon, _e): w.addStoreExtra("count", 1),
|
||||
1,
|
||||
CategoryStore.Quality.LEGENDARY
|
||||
),
|
||||
SublimateOption.new("健体·阴", "气力上限+1",
|
||||
func(w: Weapon, _e): w.addStoreExtra("max", 1),
|
||||
1,
|
||||
CategoryStore.Quality.EPIC
|
||||
),
|
||||
SublimateOption.new("献祭", "乾坤剑伤害-8,但弹反概率+4%",
|
||||
func(w: Weapon, _e):
|
||||
w.addStoreExtra("atk", -10)
|
||||
w.addStoreExtra("rate", 0.05),
|
||||
1,
|
||||
CategoryStore.Quality.RARE
|
||||
),
|
||||
SublimateOption.new("亏心", "扣除你的所有幸运,每点幸运增加1%弹反概率",
|
||||
func(w: Weapon, e: EntityBase):
|
||||
w.addStoreExtra("rate", e.fields[FieldStore.Entity.LUCK_VALUE]),
|
||||
1,
|
||||
CategoryStore.Quality.WASTE
|
||||
),
|
||||
]
|
||||
func update(to: int, origin: Dictionary, _entity: EntityBase):
|
||||
|
||||
@@ -7,7 +7,7 @@ enum ComposeMode {
|
||||
}
|
||||
|
||||
@export var targetFields: Array[FieldStore.Entity] = []
|
||||
@export var targetTopics: Array[FeedName.Topic] = []
|
||||
@export var targetTopics: Array[CategoryStore.Topic] = []
|
||||
@export var composeMode: ComposeMode = ComposeMode.ALL
|
||||
@export var clickToRefresh: bool = false
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
@tool
|
||||
extends HBoxContainer
|
||||
|
||||
@export var targetTopics: Array[FeedName.Topic] = []
|
||||
@export var targetTopics: Array[CategoryStore.Topic] = []
|
||||
@export var clickToRefresh: bool = false
|
||||
|
||||
var lastState: bool = false
|
||||
|
||||
@@ -68,7 +68,7 @@ var inventory = {
|
||||
ItemStore.ItemType.BEACHBALL: 0,
|
||||
ItemStore.ItemType.SOUL: 0,
|
||||
ItemStore.ItemType.CRYSTAL: 0,
|
||||
ItemStore.ItemType.DIAMOND: 0
|
||||
ItemStore.ItemType.DIAMOND: 10
|
||||
}
|
||||
var inventoryMax = {
|
||||
ItemStore.ItemType.BASEBALL: INF, # 无限
|
||||
|
||||
@@ -2,80 +2,60 @@
|
||||
extends HBoxContainer
|
||||
class_name FeedName
|
||||
|
||||
enum Quality {
|
||||
WASTE,
|
||||
COMMON,
|
||||
RARE,
|
||||
EPIC,
|
||||
LEGENDARY,
|
||||
}
|
||||
enum Topic {
|
||||
SURVIVAL,
|
||||
ENERGY,
|
||||
BULLET,
|
||||
SPEED,
|
||||
DAMAGE,
|
||||
PROBABILITY,
|
||||
FEED,
|
||||
DROP,
|
||||
WEAPON,
|
||||
SUMMON,
|
||||
}
|
||||
|
||||
@export var displayName: String = "未命名饲料"
|
||||
@export var quality: Quality = Quality.COMMON
|
||||
@export var topic: Topic = Topic.SURVIVAL
|
||||
@export var quality: CategoryStore.Quality = CategoryStore.Quality.COMMON
|
||||
@export var topic: CategoryStore.Topic = CategoryStore.Topic.SURVIVAL
|
||||
@export var qualityColorMap = {
|
||||
Quality.WASTE: Color(),
|
||||
Quality.COMMON: Color(),
|
||||
Quality.RARE: Color(),
|
||||
Quality.EPIC: Color(),
|
||||
Quality.LEGENDARY: Color()
|
||||
CategoryStore.Quality.WASTE: Color(),
|
||||
CategoryStore.Quality.COMMON: Color(),
|
||||
CategoryStore.Quality.RARE: Color(),
|
||||
CategoryStore.Quality.EPIC: Color(),
|
||||
CategoryStore.Quality.LEGENDARY: Color()
|
||||
}
|
||||
@export var qualityNameMap = {
|
||||
Quality.WASTE: "常见",
|
||||
Quality.COMMON: "普通",
|
||||
Quality.RARE: "稀有",
|
||||
Quality.EPIC: "史诗",
|
||||
Quality.LEGENDARY: "传说"
|
||||
CategoryStore.Quality.WASTE: "常见",
|
||||
CategoryStore.Quality.COMMON: "普通",
|
||||
CategoryStore.Quality.RARE: "稀有",
|
||||
CategoryStore.Quality.EPIC: "史诗",
|
||||
CategoryStore.Quality.LEGENDARY: "传说"
|
||||
}
|
||||
@export var qualityRandomWeight = {
|
||||
Quality.WASTE: 20,
|
||||
Quality.COMMON: 100,
|
||||
Quality.RARE: 30,
|
||||
Quality.EPIC: 10,
|
||||
Quality.LEGENDARY: 5
|
||||
CategoryStore.Quality.WASTE: 20,
|
||||
CategoryStore.Quality.COMMON: 100,
|
||||
CategoryStore.Quality.RARE: 30,
|
||||
CategoryStore.Quality.EPIC: 10,
|
||||
CategoryStore.Quality.LEGENDARY: 5
|
||||
}
|
||||
@export var luckInfluence = {
|
||||
Quality.WASTE: - 0.5,
|
||||
Quality.COMMON: - 1,
|
||||
Quality.RARE: 0,
|
||||
Quality.EPIC: 1,
|
||||
Quality.LEGENDARY: 2,
|
||||
CategoryStore.Quality.WASTE: - 0.5,
|
||||
CategoryStore.Quality.COMMON: - 1,
|
||||
CategoryStore.Quality.RARE: 0,
|
||||
CategoryStore.Quality.EPIC: 1,
|
||||
CategoryStore.Quality.LEGENDARY: 2,
|
||||
}
|
||||
@export var topicNameMap = {
|
||||
Topic.SURVIVAL: "生存",
|
||||
Topic.ENERGY: "能量",
|
||||
Topic.BULLET: "子弹",
|
||||
Topic.SPEED: "速度",
|
||||
Topic.DAMAGE: "伤害",
|
||||
Topic.PROBABILITY: "幸运",
|
||||
Topic.FEED: "饲料",
|
||||
Topic.DROP: "掉落物",
|
||||
Topic.WEAPON: "武器",
|
||||
Topic.SUMMON: "召唤",
|
||||
CategoryStore.Topic.SURVIVAL: "生存",
|
||||
CategoryStore.Topic.ENERGY: "能量",
|
||||
CategoryStore.Topic.BULLET: "子弹",
|
||||
CategoryStore.Topic.SPEED: "速度",
|
||||
CategoryStore.Topic.DAMAGE: "伤害",
|
||||
CategoryStore.Topic.PROBABILITY: "幸运",
|
||||
CategoryStore.Topic.FEED: "饲料",
|
||||
CategoryStore.Topic.DROP: "掉落物",
|
||||
CategoryStore.Topic.WEAPON: "武器",
|
||||
CategoryStore.Topic.SUMMON: "召唤",
|
||||
}
|
||||
@export var topicColorMap = {
|
||||
Topic.SURVIVAL: Color(),
|
||||
Topic.ENERGY: Color(),
|
||||
Topic.BULLET: Color(),
|
||||
Topic.SPEED: Color(),
|
||||
Topic.DAMAGE: Color(),
|
||||
Topic.PROBABILITY: Color(),
|
||||
Topic.FEED: Color(),
|
||||
Topic.DROP: Color(),
|
||||
Topic.WEAPON: Color(),
|
||||
Topic.SUMMON: Color(),
|
||||
CategoryStore.Topic.SURVIVAL: Color(),
|
||||
CategoryStore.Topic.ENERGY: Color(),
|
||||
CategoryStore.Topic.BULLET: Color(),
|
||||
CategoryStore.Topic.SPEED: Color(),
|
||||
CategoryStore.Topic.DAMAGE: Color(),
|
||||
CategoryStore.Topic.PROBABILITY: Color(),
|
||||
CategoryStore.Topic.FEED: Color(),
|
||||
CategoryStore.Topic.DROP: Color(),
|
||||
CategoryStore.Topic.WEAPON: Color(),
|
||||
CategoryStore.Topic.SUMMON: Color(),
|
||||
}
|
||||
|
||||
@onready var qualityLabel: Label = $"%quality"
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
@tool
|
||||
extends Control
|
||||
class_name SublimateOptionHandler
|
||||
|
||||
signal apply()
|
||||
|
||||
@onready var nameLabel: Label = $%name
|
||||
@onready var applyBtn: Button = $%applyBtn
|
||||
@onready var costItemShow: ItemShow = $%costItem
|
||||
|
||||
var use: SublimateOption;
|
||||
|
||||
func _ready():
|
||||
nameLabel.label_settings = nameLabel.label_settings.duplicate()
|
||||
applyBtn.pressed.connect(
|
||||
func():
|
||||
if UIState.player.useItem({ItemStore.ItemType.DIAMOND: use.cost}):
|
||||
apply.emit()
|
||||
else:
|
||||
UIState.showTip("钻石数量不足!", TipBox.MessageType.ERROR)
|
||||
)
|
||||
rebuildInfo()
|
||||
|
||||
func rebuildInfo():
|
||||
if is_instance_valid(use):
|
||||
nameLabel.label_settings.font_color = CategoryStore.qualityColorMap[use.quality]
|
||||
nameLabel.label_settings.outline_color = CategoryStore.qualityColorMap[use.quality]
|
||||
nameLabel.text = use.displayName
|
||||
applyBtn.text = use.description
|
||||
costItemShow.count = use.cost
|
||||
@@ -0,0 +1 @@
|
||||
uid://qpx600iiwgae
|
||||
@@ -0,0 +1,13 @@
|
||||
@tool
|
||||
extends Button
|
||||
class_name TextSwitchButton
|
||||
|
||||
@export var pressedText: String = "已按下"
|
||||
@export var unpressedText: String = "未按下"
|
||||
|
||||
func _ready():
|
||||
updateText()
|
||||
toggled.connect(updateText)
|
||||
|
||||
func updateText():
|
||||
text = [unpressedText, pressedText][int(button_pressed)]
|
||||
@@ -0,0 +1 @@
|
||||
uid://5r8mvbag4m0q
|
||||
@@ -6,8 +6,8 @@ signal selected(applied: bool)
|
||||
|
||||
@export var avatarTexture: Texture2D = null
|
||||
@export var displayName: String = "未命名饲料"
|
||||
@export var quality: FeedName.Quality = FeedName.Quality.COMMON
|
||||
@export var topic: FeedName.Topic = FeedName.Topic.SURVIVAL
|
||||
@export var quality: CategoryStore.Quality = CategoryStore.Quality.COMMON
|
||||
@export var topic: CategoryStore.Topic = CategoryStore.Topic.SURVIVAL
|
||||
@export var fields: Array[FieldStore.Entity] = []
|
||||
@export var fieldValues: Array[float] = []
|
||||
@export var weapons: Array[PackedScene] = []
|
||||
|
||||
@@ -1,15 +1,21 @@
|
||||
class_name SublimateOption
|
||||
|
||||
signal applied()
|
||||
|
||||
var displayName: String = "升华"
|
||||
var description: String = "描述"
|
||||
var executor: Callable = func(_weapon: Weapon, _entity: EntityBase): return
|
||||
var cost: int = 1
|
||||
var quality: CategoryStore.Quality = CategoryStore.Quality.COMMON
|
||||
|
||||
func _init(displayNames: String, descriptions: String, executors: Callable):
|
||||
func _init(displayNames: String, descriptions: String, executors: Callable, costs: int, qualities: CategoryStore.Quality):
|
||||
displayName = displayNames
|
||||
description = descriptions
|
||||
executor = executors
|
||||
cost = costs
|
||||
quality = qualities
|
||||
|
||||
func apply(entity: EntityBase, index: int):
|
||||
var weapon = entity.weapons[index]
|
||||
if weapon is Weapon:
|
||||
executor.call(weapon, entity)
|
||||
func apply(entity: EntityBase, weapon: Weapon):
|
||||
cost += 1
|
||||
executor.call(weapon, entity)
|
||||
applied.emit()
|
||||
|
||||
@@ -48,6 +48,8 @@ enum EmitType {
|
||||
@onready var extractBtn: Button = $%extractBtn
|
||||
@onready var inlayBtn: Button = $%inlayBtn
|
||||
|
||||
@onready var sublimateOptionsBox: Control = $%sublimateOptions
|
||||
|
||||
var cooldownTimer: CooldownTimer = null
|
||||
var originalStore: Dictionary = {}
|
||||
var chargedTime: float = 0
|
||||
@@ -55,6 +57,7 @@ var attackSpeed: float = 1
|
||||
var looping: bool = false
|
||||
var autoUpdate: bool = false
|
||||
var storeExtra: Dictionary = {}
|
||||
var sublimateOptionsStored: Array[SublimateOption] = []
|
||||
|
||||
func _ready():
|
||||
cooldownTimer = CooldownTimer.new()
|
||||
@@ -126,6 +129,7 @@ func _ready():
|
||||
for i in sounds.get_children():
|
||||
i.process_mode = ProcessMode.PROCESS_MODE_ALWAYS
|
||||
debugRebuild = false # 只能在编辑器里打开
|
||||
rebuildInfo()
|
||||
func _physics_process(_delta):
|
||||
if debugRebuild:
|
||||
rebuildInfo()
|
||||
@@ -153,6 +157,10 @@ func multipiler() -> float:
|
||||
else:
|
||||
return 1
|
||||
func rebuildInfo(showNext: bool = false):
|
||||
rebuildBaseInfo()
|
||||
rebuildDescription(showNext)
|
||||
rebuildSublimateOptions(showNext)
|
||||
func rebuildBaseInfo():
|
||||
avatarRect.texture = avatarTexture
|
||||
nameLabel.displayName = displayName
|
||||
nameLabel.quality = quality
|
||||
@@ -171,7 +179,6 @@ func rebuildInfo(showNext: bool = false):
|
||||
if is_instance_valid(UIState.player):
|
||||
beachball.enough = canUpdate(UIState.player)
|
||||
soul.enough = canInlay()
|
||||
descriptionLabel.text = buildDescription(showNext && (canUpdate(UIState.player) || canInlay()))
|
||||
func formatValue(value: Variant, type: FieldStore.DataType) -> String:
|
||||
if type == FieldStore.DataType.VALUE:
|
||||
return "%.2f" % value
|
||||
@@ -186,11 +193,10 @@ func formatValue(value: Variant, type: FieldStore.DataType) -> String:
|
||||
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 data = readStore(key)
|
||||
var nextData = next[key]
|
||||
var type = storeType.get(key, FieldStore.DataType.VALUE)
|
||||
data = formatValue(data, type)
|
||||
@@ -202,6 +208,24 @@ func buildDescription(showNext: bool = false) -> String:
|
||||
text = "[color=cyan]%s[/color]" % data
|
||||
result = result.replace("$" + key, text)
|
||||
return result
|
||||
func rebuildDescription(showNext: bool):
|
||||
descriptionLabel.text = buildDescription(showNext && (canUpdate(UIState.player) || canInlay()))
|
||||
func rebuildSublimateOptions(showNext: bool):
|
||||
for i in sublimateOptionsBox.get_children():
|
||||
sublimateOptionsBox.remove_child(i)
|
||||
for sublimate in getSublimateOptions():
|
||||
var instance = ComponentManager.getUIComponent("SublimateOption").instantiate() as SublimateOptionHandler
|
||||
instance.use = sublimate
|
||||
instance.apply.connect(
|
||||
func():
|
||||
sublimate.apply(UIState.player, self )
|
||||
rebuildBaseInfo()
|
||||
rebuildDescription(showNext)
|
||||
instance.rebuildInfo()
|
||||
disruptSublimateOptions()
|
||||
)
|
||||
sublimateOptionsBox.add_child(instance)
|
||||
disruptSublimateOptions()
|
||||
func readStore(key: String):
|
||||
return store.get(key, 0) + readStoreExtra(key)
|
||||
func playSound(sound: String):
|
||||
@@ -246,8 +270,23 @@ func addStoreExtra(key: String, value: float):
|
||||
if !storeExtra.has(key):
|
||||
storeExtra[key] = 0
|
||||
storeExtra[key] += value
|
||||
storeExtra[key] = clamp(storeExtra[key], 0, INF)
|
||||
func readStoreExtra(key: String):
|
||||
return storeExtra.get(key, 0)
|
||||
func getSublimateOptions() -> Array[SublimateOption]:
|
||||
if len(sublimateOptionsStored) == 0:
|
||||
sublimateOptionsStored = sublimateOptions()
|
||||
return sublimateOptionsStored
|
||||
func disruptSublimateOptions():
|
||||
var children = sublimateOptionsBox.get_children()
|
||||
children.shuffle()
|
||||
for index in len(children):
|
||||
sublimateOptionsBox.remove_child(children[index])
|
||||
for index in len(children):
|
||||
var child = children[index]
|
||||
if child is SublimateOptionHandler:
|
||||
child.visible = index < 3
|
||||
sublimateOptionsBox.add_child(child)
|
||||
|
||||
# 抽象
|
||||
func sublimateOptions() -> Array[SublimateOption]:
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
class_name CategoryStore
|
||||
|
||||
enum Quality {
|
||||
WASTE,
|
||||
COMMON,
|
||||
RARE,
|
||||
EPIC,
|
||||
LEGENDARY,
|
||||
}
|
||||
enum Topic {
|
||||
SURVIVAL,
|
||||
ENERGY,
|
||||
BULLET,
|
||||
SPEED,
|
||||
DAMAGE,
|
||||
PROBABILITY,
|
||||
FEED,
|
||||
DROP,
|
||||
WEAPON,
|
||||
SUMMON,
|
||||
}
|
||||
|
||||
static var qualityColorMap = {
|
||||
Quality.WASTE: Color("808080"),
|
||||
Quality.COMMON: Color("ffffff"),
|
||||
Quality.RARE: Color("007eff"),
|
||||
Quality.EPIC: Color("8100ff"),
|
||||
Quality.LEGENDARY: Color("ff7100"),
|
||||
}
|
||||
static var qualityNameMap = {
|
||||
Quality.WASTE: "常见",
|
||||
Quality.COMMON: "普通",
|
||||
Quality.RARE: "稀有",
|
||||
Quality.EPIC: "史诗",
|
||||
Quality.LEGENDARY: "传说"
|
||||
}
|
||||
static var qualityRandomWeight = {
|
||||
Quality.WASTE: 20,
|
||||
Quality.COMMON: 100,
|
||||
Quality.RARE: 30,
|
||||
Quality.EPIC: 10,
|
||||
Quality.LEGENDARY: 5
|
||||
}
|
||||
static var luckInfluence = {
|
||||
Quality.WASTE: - 0.5,
|
||||
Quality.COMMON: - 1,
|
||||
Quality.RARE: 0,
|
||||
Quality.EPIC: 1,
|
||||
Quality.LEGENDARY: 2,
|
||||
}
|
||||
static var topicNameMap = {
|
||||
Topic.SURVIVAL: "生存",
|
||||
Topic.ENERGY: "能量",
|
||||
Topic.BULLET: "子弹",
|
||||
Topic.SPEED: "速度",
|
||||
Topic.DAMAGE: "伤害",
|
||||
Topic.PROBABILITY: "幸运",
|
||||
Topic.FEED: "饲料",
|
||||
Topic.DROP: "掉落物",
|
||||
Topic.WEAPON: "武器",
|
||||
Topic.SUMMON: "召唤",
|
||||
}
|
||||
static var topicColorMap = {
|
||||
Topic.SURVIVAL: Color("ff0095"),
|
||||
Topic.ENERGY: Color("00aeff"),
|
||||
Topic.BULLET: Color("995900"),
|
||||
Topic.SPEED: Color("995900"),
|
||||
Topic.DAMAGE: Color("c070ff"),
|
||||
Topic.PROBABILITY: Color("ff6c00"),
|
||||
Topic.FEED: Color("ffffff"),
|
||||
Topic.DROP: Color("737373"),
|
||||
Topic.WEAPON: Color("ffd000"),
|
||||
Topic.SUMMON: Color("00ff9b"),
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://cekdcml1yb4g8
|
||||
Reference in New Issue
Block a user