925236118/alphaagent/godot-weapon-system

Claude Code and agent skill by 925236118/alphaagent

Trust tier 3
  • community
Source check pending

Checking that the SKILL.md file is still in the repository.

Godot 4武器切换系统,支持武器类型枚举、武器基类设计、多种切换逻辑、输入绑定和锁定机制。

Install

npx vskill@latest install 925236118/alphaagent/godot-weapon-system

SKILL.md

Godot 4 武器切换系统

完整的武器管理系统,支持多类型武器、快速切换、冷却锁定、输入绑定。

何时使用此技能

  • 实现玩家武器切换
  • 近战/远程武器系统
  • 武器冷却与锁定
  • 武器类型分类管理

武器类型枚举

gdscript
# weapon_type.gd
class_name WeaponType
extends RefCounted
## 武器类型枚举
enum Type {
NONE = -1,
SWORD = 0, # 近战 - 剑
AXE = 1, # 近战 - 斧
HAMMER = 2, # 近战 - 锤
BOW = 3, # 远程 - 弓
CROSSBOW = 4, # 远程 - 弩
STAFF = 5, # 法杖
SHIELD = 6, # 盾牌
THROWING = 7, # 投掷武器
}
## 类型名称映射
const TYPE_NAMES: Dictionary = {
Type.SWORD: "剑",
Type.AXE: "斧",
Type.HAMMER: "锤",
Type.BOW: "弓",
Type.CROSSBOW: "弩",
Type.STAFF: "法杖",
Type.SHIELD: "盾牌",
Type.THROWING: "投掷武器"
}
## 获取类型名称
static func get_name(type: Type) -> String:
return TYPE_NAMES.get(type, "未知")
## 是否是近战武器
static func is_melee(type: Type) -> bool:
return type in [Type.SWORD, Type.AXE, Type.HAMMER, Type.SHIELD]
## 是否是远程武器
static func is_ranged(type: Type) -> bool:
return type in [Type.BOW, Type.CROSSBOW, Type.STAFF, Type.THROWING]

武器基类设计

WeaponData 武器数据资源
gdscript
# weapon_data.gd
class_name WeaponData
extends Resource
## 武器唯一标识符
@export var id: StringName
## 武器名称
@export var weapon_name: String
## 武器类型
@export var weapon_type: WeaponType.Type = WeaponType.Type.SWORD
## 武器 Prefab 场景
@export var weapon_scene: PackedScene
## 武器图标(用于UI)
@export var icon: Texture2D
## 基础属性
@export var base_damage: int = 10
@export var attack_speed: float = 1.0
@export var attack_range: float = 1.0
## 冷却时间
@export var cooldown: float = 0.5
## 是否需要弹药
@export var needs_ammo: bool = false
@export var max_ammo: int = 0
@export var ammo_type: StringName = &""
## 特殊属性
@export var can_block: bool = false
@export var block_ratio: float = 0.5
## 动画
@export var attack_animation: StringName = &"attack"
@export var idle_animation: StringName = &"idle"
## 获取武器类型名称
func get_type_name() -> String:
return WeaponType.get_name(weapon_type)
## 是否是近战武器
func is_melee() -> bool:
return WeaponType.is_melee(weapon_type)
## 是否是远程武器
func is_ranged() -> bool:
return WeaponType.is_ranged(weapon_type)
Weapon 基类
gdscript
# weapon.gd
class_name Weapon
extends Node2D
## 信号:攻击开始
signal attack_started
## 信号:攻击结束
signal attack_finished
## 信号:攻击命中
signal attack_hit(target: Node)
## 信号:弹药变化
signal ammo_changed(current: int, max: int)
@export var weapon_data: WeaponData
var _owner: CharacterBody2D
var _current_ammo: int
var _cooldown_timer: float = 0.0
var _is_attacking: bool = false
func _ready() -> void:
_owner = get_owner() as CharacterBody2D
if weapon_data and weapon_data.needs_ammo:
_current_ammo = weapon_data.max_ammo
ammo_changed.emit(_current_ammo, weapon_data.max_ammo)
func _process(delta: float) -> void:
if _cooldown_timer > 0:
_cooldown_timer -= delta
func _physics_process(delta: float) -> void:
pass
## 使用武器攻击
func attack() -> bool:
if not can_attack():
return false
if weapon_data.needs_ammo and _current_ammo <= 0:
return false
_is_attacking = true
_start_attack()
attack_started.emit()
if weapon_data.needs_ammo:
_current_ammo -= 1
ammo_changed.emit(_current_ammo, weapon_data.max_ammo)
# 重置冷却
_cooldown_timer = weapon_data.cooldown
return true
func _start_attack() -> void:
# 播放攻击动画
if _owner.has_method("play_animation"):
_owner.play_animation(weapon_data.attack_animation)
func _end_attack() -> void:
_is_attacking = false
attack_finished.emit()
## 停止攻击
func stop_attack() -> void:
_is_attacking = false
_end_attack()
## 是否可以攻击
func can_attack() -> bool:
if _is_attacking:
return false
if _cooldown_timer > 0:
return false
return true
## 获取剩余冷却时间
func get_cooldown_remaining() -> float:
return maxf(_cooldown_timer, 0.0)
## 装填弹药
func reload(amount: int = 0) -> void:
if not weapon_data.needs_ammo:
return
if amount <= 0:
_current_ammo = weapon_data.max_ammo
else:
_current_ammo = mini(_current_ammo + amount, weapon_data.max_ammo)
ammo_changed.emit(_current_ammo, weapon_data.max_ammo)
## 命中处理(供Hitbox调用)
func on_hit(target: Node) -> void:
attack_hit.emit(target)
具体武器实现
gdscript
# sword.gd
class_name Sword
extends Weapon
@export var slash_effect_scene: PackedScene
func _start_attack() -> void:
super._start_attack()
# 生成斩击特效
if slash_effect_scene:
var effect := slash_effect_scene.instantiate()
get_tree().current_scene.add_child(effect)
effect.global_position = global_position
effect.rotation = _owner.rotation
func on_hit(target: Node) -> void:
if target.has_method("take_damage"):
target.take_damage(weapon_data.base_damage)
# 击退效果
if target.has_method("apply_knockback"):
var direction := (target.global_position - _owner.global_position).normalized()
target.apply_knockback(direction, 200.0)
gdscript
# bow.gd
class_name Bow
extends Weapon
@export var arrow_scene: PackedScene
@export var arrow_spawn_offset: Vector2 = Vector2(30, 0)
func _start_attack() -> void:
super._start_attack()
# 发射箭矢
if arrow_scene:
var arrow := arrow_scene.instantiate()
get_tree().current_scene.add_child(arrow)
var spawn_pos := global_position + arrow_spawn_offset.rotated(global_rotation)
arrow.initialize(spawn_pos, _owner.rotation, weapon_data.base_damage)

切换逻辑

WeaponSwitcher 武器切换器
gdscript
# weapon_switcher.gd
class_name WeaponSwitcher
extends Node
## 信号:武器切换
signal weapon_switched(from_weapon: Weapon, to_weapon: Weapon)
## 信号:武器被锁定
signal weapon_locked(weapon_type: WeaponType.Type, unlock_time: float)
## 信号:切换冷却开始
signal switch_cooldown_started(duration: float)
@export var weapon_slots: Array[WeaponData] = []
@export var max_secondary_weapons: int = 2
## 当前激活的武器索引
var current_weapon_index: int = -1
## 当前武器引用
var current_weapon: Weapon = null
## 武器节点字典
var _weapon_nodes: Dictionary = {}
## 切换冷却
var _switch_cooldown: float = 0.3
var _is_locked: bool = false
var _lock_until: float = 0.0
## 武器类型到索引的映射
var _type_to_index: Dictionary = {}
func _ready() -> void:
_initialize_weapons()
func _process(delta: float) -> void:
_update_cooldown(delta)
_update_lock(delta)
func _update_cooldown(delta: float) -> void:
if _switch_cooldown > 0:
_switch_cooldown -= delta
func _update_lock(delta: float) -> void:
if _is_locked and Time.get_ticks_msec() / 1000.0 >= _lock_until:
_is_locked = false
func _initialize_weapons() -> void:
# 创建所有武器节点
for i in weapon_slots.size():
var data: WeaponData = weapon_slots[i]
if data.weapon_scene == null:
continue
var weapon: Weapon = data.weapon_scene.instantiate()
weapon.weapon_data = data
weapon.set_process(false)
weapon.visible = false
add_child(weapon)
_weapon_nodes[i] = weapon
# 建立类型映射
_type_to_index[data.weapon_type] = i
# 默认装备第一把武器
if weapon_slots.size() > 0:
_equip_weapon(0)
## 切换到指定索引的武器
func switch_to_index(index: int) -> bool:
if index < 0 or index >= weapon_slots.size():
return false
if index == current_weapon_index:
return true
if not can_switch():
return false
_switch_cooldown = 0.3
switch_cooldown_started.emit(_switch_cooldown)
var previous := current_weapon
_unequip_current()
_equip_weapon(index)
weapon_switched.emit(previous, current_weapon)
return true
## 切换到指定类型
func switch_to_type(weapon_type: WeaponType.Type) -> bool:
if _type_to_index.has(weapon_type):
return switch_to_index(_type_to_index[weapon_type])
return false
## 切换到下一把武器(循环)
func switch_to_next() -> bool:
if weapon_slots.size() <= 1:
return false
var next_index := (current_weapon_index + 1) % weapon_slots.size()
return switch_to_index(next_index)
## 切换到上一把武器(循环)
func switch_to_previous() -> bool:
if weapon_slots.size() <= 1:
return false
var prev_index := (current_weapon_index - 1 + weapon_slots.size()) % weapon_slots.size()
return switch_to_index(prev_index)
## 卸下当前武器
func _unequip_current() -> void:
if current_weapon != null:
current_weapon.set_process(false)
current_weapon.visible = false
current_weapon.stop_attack()
## 装备武器
func _equip_weapon(index: int) -> void:
current_weapon_index = index
current_weapon = _weapon_nodes.get(index)
if current_weapon != null:
current_weapon.visible = true
current_weapon.set_process(true)
## 是否可以切换
func can_switch() -> bool:
if _switch_cooldown > 0:
return false
if _is_locked:
return false
if current_weapon != null and current_weapon._is_attacking:
return false
return true
## 锁定特定类型武器
func lock_weapon_type(weapon_type: WeaponType.Type, duration: float) -> void:
_is_locked = true
_lock_until = Time.get_ticks_msec() / 1000.0 + duration
weapon_locked.emit(weapon_type, duration)
## 解锁武器类型
func unlock_weapon_type(weapon_type: WeaponType.Type) -> void:
_is_locked = false
## 获取当前武器数据
func get_current_weapon_data() -> WeaponData:
if current_weapon_index >= 0 and current_weapon_index < weapon_slots.size():
return weapon_slots[current_weapon_index]
return null
## 获取当前武器类型
func get_current_weapon_type() -> WeaponType.Type:
var data := get_current_weapon_data()
if data != null:
return data.weapon_type
return WeaponType.Type.NONE
## 添加武器到槽位
func add_weapon(data: WeaponData) -> bool:
if weapon_slots.size() >= max_secondary_weapons + 1:
return false
weapon_slots.append(data)
var index := weapon_slots.size() - 1
var weapon: Weapon = data.weapon_scene.instantiate()
weapon.weapon_data = data
weapon.set_process(false)
weapon.visible = false
add_child(weapon)
_weapon_nodes[index] = weapon
_type_to_index[data.weapon_type] = index
return true
## 移除武器
func remove_weapon(index: int) -> bool:
if index < 0 or index >= weapon_slots.size():
return false
# 如果是当前武器,切换到另一把
if index == current_weapon_index:
var next_index := (index + 1) % weapon_slots.size()
if next_index != index:
switch_to_index(next_index)
else:
_unequip_current()
current_weapon_index = -1
current_weapon = null
weapon_slots.remove_at(index)
_weapon_nodes.erase(index)
return true

输入绑定

输入映射配置
gdscript
# weapon_input_handler.gd
class_name WeaponInputHandler
extends Node
@export var weapon_switcher: WeaponSwitcher
## 输入映射名称
const INPUT_SLOT_1 := "weapon_slot_1"
const INPUT_SLOT_2 := "weapon_slot_2"
const INPUT_SLOT_3 := "weapon_slot_3"
const INPUT_SLOT_4 := "weapon_slot_4"
const INPUT_SLOT_5 := "weapon_slot_5"
const INPUT_NEXT_WEAPON := "next_weapon"
const INPUT_PREV_WEAPON := "prev_weapon"
const INPUT_ATTACK := "attack"
const INPUT_BLOCK := "block"
const INPUT_RELOAD := "reload"
func _ready() -> void:
_setup_input_actions()

This is the start of the file. Read the full SKILL.md on GitHub.

Security

  • Security scanPassed, 95 of 100Pattern checks on the skill's files.
  • Model reviewPassed

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
103
Repository forks
14
7-day trend score
23

Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/925236118/alphaagent/godot-weapon-system/badge)](https://verified-skill.com/skills/925236118/alphaagent/godot-weapon-system)

Something wrong with this skill or its page? Tell us.