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)
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
## WeaponData — resource containing all stats for a weapon.
|
||||
##
|
||||
## Used by the weapon system to configure damage, fire rate, recoil,
|
||||
## economy pricing, and team restrictions.
|
||||
##
|
||||
## This is a pure Resource (no Node dependency) so it loads clean
|
||||
## in both client and server contexts.
|
||||
|
||||
extends Resource
|
||||
class_name WeaponData
|
||||
|
||||
enum FireMode { SEMI, AUTO, MELEE }
|
||||
|
||||
# Identification
|
||||
@export var weapon_id: int = 0
|
||||
@export var weapon_name: String = ""
|
||||
@export var slot: int = 0 # 0=melee, 1=pistol, 2=SMG, 3=rifle, 4=sniper
|
||||
|
||||
# Damage
|
||||
@export var damage: int = 30
|
||||
@export var headshot_multiplier: float = 2.0
|
||||
@export var chest_multiplier: float = 1.0
|
||||
@export var waist_multiplier: float = 0.75
|
||||
@export var leg_multiplier: float = 0.5
|
||||
@export var armor_penetration: float = 0.5 # 0.0-1.0, % damage through armor
|
||||
|
||||
# Firing
|
||||
@export var fire_mode: FireMode = FireMode.SEMI
|
||||
@export var fire_rate: float = 10.0 # rounds per second
|
||||
@export var reload_time: float = 2.0 # seconds
|
||||
@export var max_distance: float = 1000.0
|
||||
|
||||
# Magazine
|
||||
@export var magazine_size: int = 30
|
||||
@export var reserve_size: int = 90
|
||||
|
||||
# Recoil & Spread
|
||||
@export var recoil_per_shot: float = 0.5 # degrees
|
||||
@export var recoil_recovery: float = 8.0 # degrees/sec
|
||||
@export var spread_idle: float = 0.0 # degrees while standing still
|
||||
@export var spread_walking: float = 2.0 # degrees while moving
|
||||
@export var spread_sprinting: float = 6.0 # degrees while sprinting
|
||||
|
||||
# Movement
|
||||
@export var move_speed_multiplier: float = 1.0 # multiplier on base move speed
|
||||
@export var aim_speed_multiplier: float = 0.5 # move speed while aiming
|
||||
|
||||
# Economy
|
||||
@export var price: int = 0
|
||||
@export var kill_reward: int = 300
|
||||
@export var team: int = -1 # -1=both, 0=T, 1=CT
|
||||
@@ -0,0 +1,175 @@
|
||||
## 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
|
||||
Reference in New Issue
Block a user