Files
tactical-shooter/client/weapons/data/weapon_registry.gd
T
shawn e7299b17e9 Phase 7: netfox + godot-jolt stack upgrade
Stack installed:
- netfox v1.35.3 (core + extras + noray + internals)
- godot-jolt v0.16.0-stable

Architecture:
- Server: ENet transport (works headless, no netfox deps)
- Client/Editor: netfox rollback (RollbackSynchronizer, TickInterpolator)

New/modified:
- docs/migration-netfox-plan.md — migration architecture
- scripts/network/network_manager.gd — netfox-aware ENet fallback
- scripts/network/player.gd — clean base player
- client/characters/player_netfox.gd — rollback player w/ WeaponManager
- client/characters/input/player_net_input.gd — BaseNetInput subclass
- client/characters/character/fps_character_controller.gd — netfox input feed
- client/weapons/ — weapon data, registry, TacticalWeaponHitscan, WeaponManager
- client/scripts/round_replicator.gd — client-side round state bridge
- server/scripts/round_manager.gd — improved state machine
- server/scripts/plugin_api/plugin_manager.gd — refined plugin system
- config: enemy_tag, ally_tag for meatball targeting

Removed: old C++ SimulationServer GDExtension (replaced by netfox rollback)
2026-07-02 17:39:22 -04:00

176 lines
4.2 KiB
GDScript

## WeaponRegistry — central registry of all weapon definitions.
##
## All weapon data is defined here as static constants. Systems that need
## weapon stats (WeaponManager, BuyMenu, RoundManager) reference this.
##
## To add a new weapon: create a WeaponData resource in client/weapons/data/
## and register it in the ALL array below.
extends Node
class_name WeaponRegistry
# Define all weapons as convenient static getters
static var KNIFE: WeaponData:
get: return _knife
static var GLOCK: WeaponData:
get: return _glock
static var USP: WeaponData:
get: return _usp
static var AK47: WeaponData:
get: return _ak47
static var M4A1: WeaponData:
get: return _m4a1
static var AWP: WeaponData:
get: return _awp
# Weapon ID constants
const ID_KNIFE: int = 0
const ID_GLOCK: int = 1
const ID_USP: int = 2
const ID_AK47: int = 3
const ID_M4A1: int = 4
const ID_AWP: int = 5
## Array of all weapons for iteration
static var ALL: Array[WeaponData] = []
## Map of weapon_id → WeaponData for fast lookup
static var BY_ID: Dictionary = {}
## Static initializer
static func _static_init() -> void:
ALL = [_knife, _glock, _usp, _ak47, _m4a1, _awp]
for w in ALL:
BY_ID[w.weapon_id] = w
# ---------------------------------------------------------------------------
# Weapon definitions
# ---------------------------------------------------------------------------
static var _knife: WeaponData = _make_weapon_data({
weapon_id = ID_KNIFE,
weapon_name = "Knife",
slot = 0,
damage = 34,
fire_mode = WeaponData.FireMode.MELEE,
fire_rate = 0.0,
magazine_size = 0,
reserve_size = 0,
move_speed_multiplier = 1.0,
price = 0,
kill_reward = 1500,
armor_penetration = 0.0,
max_distance = 3.0,
})
static var _glock: WeaponData = _make_weapon_data({
weapon_id = ID_GLOCK,
weapon_name = "Glock-18",
slot = 1,
damage = 25,
fire_rate = 6.0,
magazine_size = 20,
reserve_size = 120,
recoil_per_shot = 0.4,
move_speed_multiplier = 0.86,
price = 200,
kill_reward = 300,
armor_penetration = 0.35,
team = 0, # Terrorist default
})
static var _usp: WeaponData = _make_weapon_data({
weapon_id = ID_USP,
weapon_name = "USP-S",
slot = 1,
damage = 28,
fire_rate = 5.0,
magazine_size = 12,
reserve_size = 24,
recoil_per_shot = 0.3,
move_speed_multiplier = 0.86,
price = 200,
kill_reward = 300,
armor_penetration = 0.50,
team = 1, # CT default
})
static var _ak47: WeaponData = _make_weapon_data({
weapon_id = ID_AK47,
weapon_name = "AK-47",
slot = 3,
damage = 36,
fire_mode = WeaponData.FireMode.AUTO,
fire_rate = 10.0,
magazine_size = 30,
reserve_size = 90,
recoil_per_shot = 0.8,
recoil_recovery = 6.0,
spread_walking = 3.0,
spread_sprinting = 8.0,
move_speed_multiplier = 0.78,
price = 2700,
kill_reward = 300,
armor_penetration = 0.77,
team = 0,
})
static var _m4a1: WeaponData = _make_weapon_data({
weapon_id = ID_M4A1,
weapon_name = "M4A1-S",
slot = 3,
damage = 33,
fire_mode = WeaponData.FireMode.AUTO,
fire_rate = 10.0,
magazine_size = 25,
reserve_size = 75,
recoil_per_shot = 0.7,
recoil_recovery = 7.0,
spread_walking = 2.5,
spread_sprinting = 7.0,
move_speed_multiplier = 0.78,
price = 2900,
kill_reward = 300,
armor_penetration = 0.77,
team = 1,
})
static var _awp: WeaponData = _make_weapon_data({
weapon_id = ID_AWP,
weapon_name = "AWP",
slot = 4,
damage = 115,
fire_rate = 1.5,
magazine_size = 10,
reserve_size = 30,
recoil_per_shot = 4.0,
recoil_recovery = 1.0,
spread_idle = 0.0,
spread_walking = 10.0,
spread_sprinting = 20.0,
move_speed_multiplier = 0.57,
price = 4750,
kill_reward = 100,
armor_penetration = 0.87,
max_distance = 2000.0,
headshot_multiplier = 5.0, # AWP one-shots through armor
})
# ---------------------------------------------------------------------------
# Factory
# ---------------------------------------------------------------------------
static func _make_weapon_data(dict: Dictionary) -> WeaponData:
var w := WeaponData.new()
for key in dict:
w.set(key, dict[key])
return w
## Look up a weapon by its ID.
static func get_by_id(id: int) -> WeaponData:
return BY_ID.get(id, _knife)
## Get the default weapon for a team (0=T, 1=CT).
static func get_default_weapon(team_id: int) -> WeaponData:
return _glock if team_id == 0 else _usp