TypeDefinitions
Shared Luau type definitions used across Vetra and VetraNet.
These are imported for type annotations only, there is no runtime cost. You generally do not need to require this module directly.
Types
CastTrajectory
interface CastTrajectory {StartTime: number--
Runtime.TotalRuntime when this segment began.
EndTime: number--
Runtime.TotalRuntime when closed; -1 while active.
}Represents one continuous parabolic arc of a projectile's flight path.
A new segment is appended to Runtime.Trajectories on every bounce or
mid-flight kinematic change via the Set* / Add* methods on VetraCast.
EndTime of -1 indicates the segment is still active.
BulletSnapshot
interface BulletSnapshot {Id: number--
Unique identifier.
Speed: number--
Initial speed in studs/second.
Alive: boolean--
Whether the cast is still being simulated.
Lifetime: number--
Seconds of simulated time elapsed since creation.
PathLength: number--
True accumulated path distance (bounces included).
DistanceTraveled: number--
Alias for PathLength (API compatibility).
}Read-only snapshot of a BulletContext's state at a point in time. Returned by BulletContext:GetSnapshot.
BulletContextConfig
interface BulletContextConfig {Speed: number--
Required. Initial speed in studs/second.
RaycastParams: RaycastParams?--
Optional per-bullet raycast filter. Takes priority over Behavior.RaycastParams when set. Default: nil
SolverData: any?--
Internal, used by the solver to attach lifecycle hooks. Do not set from weapon code.
}Configuration table passed to BulletContext.new.
SpeedProfile
interface SpeedProfile {DragCoefficient: number?--
Drag coefficient override for this regime.
NormalPerturbation: number?--
Bounce noise override for this regime.
MaterialRestitution: {[Enum.Material]: number}?--
Per-material restitution overrides.
Restitution: number?--
Base restitution override for this regime.
}
Per-speed-regime behavior overrides. Assigned to SupersonicProfile or
SubsonicProfile on a VetraBehavior. The solver blends in the matching
profile's values when the bullet crosses the speed of sound (343 studs/s).
All fields are optional. Omitted fields continue using the base behavior values.
VetraBehavior
interface VetraBehavior {Acceleration: Vector3?--
Extra acceleration on top of gravity (e.g. rocket thrust). Default: Vector3.zero
MaxDistance: number?--
Max flight distance in studs. Default: 500
MaxSpeed: number?--
Speed ceiling; bullet terminates if exceeded. Default: math.huge
MinSpeed: number?--
Termination speed threshold in studs/sec. Default: 1
RaycastParams: RaycastParams?--
Raycast filter. Used if BulletContext.RaycastParams is not set, before falling back to an empty RaycastParams.new(). Default: nil
Gravity: Vector3?--
Gravitational acceleration (negative Y = downward). Default: workspace gravity downward.
CastFunction: ((RaycastParams) → RaycastResult?)?--
Custom cast function (serial solver only). Default: nil
BulletMass: number?--
Bullet mass for penetration and impact-force calculations. Default: 0
DragCoefficient: number?--
Drag coefficient. 0 = no drag. Default: 0
DragSegmentInterval: number?--
Seconds between drag + Magnus recalculation steps. Default: 0.05
CustomMachTable: {{number}}?--
Custom Mach→Cd table pairs when DragModel = "Custom".
WindResponse: number?--
Multiplier on the solver's wind vector (Vetra:SetWind). 1.0 = full effect, 0.0 = immune. Default: 1.0
SpeedThresholds: {number}?--
Sorted list of speeds (studs/s) that fire OnSpeedThresholdCrossed. Default: {}
SupersonicProfile: SpeedProfile?--
Behavior overrides when bullet speed is >= 343 studs/s. Default: nil
SubsonicProfile: SpeedProfile?--
Behavior overrides when bullet speed is < 343 studs/s. Default: nil
SpinVector: Vector3?--
Spin axis (direction) x angular velocity (magnitude, rad/s). Vector3.zero = disabled. Default: Vector3.zero
MagnusCoefficient: number?--
Magnus lift coefficient. Typical range: 0.00005–0.001. 0 = disabled. Default: 0
SpinDecayRate: number?--
Rate at which SpinVector magnitude decreases per second. 0 = no decay. Default: 0
GyroDriftRate: number?--
Lateral drift acceleration magnitude in studs/s². nil = disabled. Default: nil
GyroDriftAxis: Vector3?--
Reference axis for drift direction. nil = world UP (right-hand rifling). Default: nil
TumbleSpeedThreshold: number?--
Speed below which tumbling begins. nil = disabled. Default: nil
TumbleDragMultiplier: number?--
Drag multiplied by this factor while tumbling. Default: 3.0
TumbleLateralStrength: number?--
Chaotic lateral acceleration magnitude in studs/s². Default: 0
TumbleOnPierce: boolean?--
Begin tumbling on first pierce regardless of speed. Default: false
TumbleRecoverySpeed: number?--
Speed above which tumbling ends. nil = tumble is permanent. Default: nil
HomingPositionProvider: ((vel: Vector3) → Vector3?)?--
Called every frame for target position. Return nil to disengage. Default: nil
CanHomeFunction: CanHomeCallback?--
Gate callback; return false to disengage. Default: nil
HomingStrength: number?--
Steering force in degrees/second. Default: 90
HomingMaxDuration: number?--
Max seconds of active homing before OnHomingDisengaged fires. Default: 3
HomingAcquisitionRadius: number?--
Min target distance in studs to engage. 0 = engage immediately on fire. Default: 0
TrajectoryPositionProvider: ((elapsed: number) → Vector3?)?--
Override bullet position each frame with a sampled curve. Return nil to end the override and terminate. Default: nil
CanPierceFunction: CanPierceCallback?--
Pierce gate; return true to pierce. Default: nil
MaxPierceCount: number?--
Lifetime pierce limit. Default: 3
PierceSpeedThreshold: number?--
Min speed to attempt pierce (studs/s). Default: 50
PierceSpeedRetention: number?--
Speed fraction kept per pierce [0,1]. Default: 0.8
PierceNormalBias: number?--
Min approach angle for pierce [0,1]. 1.0 = all angles, 0.0 = perpendicular only. Default: 1.0
PierceDepth: number?--
Max wall thickness per pierce in studs. 0 = no per-pierce depth limit. Default: 0
PierceForce: number?--
Total momentum force budget for penetration. 0 = disabled. Default: 0
PierceThicknessLimit: number?--
Hard cap on wall thickness for the exit-point raycast in studs. Default: 500
FragmentOnPierce: boolean?--
Spawn fragment child bullets when a pierce occurs. Default: false
FragmentCount: number?--
Number of fragments to spawn per pierce. Default: 3
FragmentDeviation: number?--
Angular half-angle spread of the fragment cone in degrees. Default: 15
CanBounceFunction: CanBounceCallback?--
Bounce gate; return true to bounce. Default: nil
MaxBounces: number?--
Lifetime bounce limit. Default: 5
BounceSpeedThreshold: number?--
Min speed to attempt bounce (studs/s). Default: 20
Restitution: number?--
Energy retention per bounce [0,1]. Default: 0.7
MaterialRestitution: {[Enum.Material]: number}?--
Per-material multipliers, combined with Restitution. Default: {}
NormalPerturbation: number?--
Random surface-normal noise for rough surfaces. 0 = clean reflection. Default: 0.0
ResetPierceOnBounce: boolean?--
Reset pierce state after each confirmed bounce. Default: false
HighFidelitySegmentSize: number?--
Sub-segment length in studs (starting value). Default: 0.5
HighFidelityFrameBudget: number?--
Millisecond budget per cast per frame for sub-segment raycasts. Default: 4
AdaptiveScaleFactor: number?--
Adaptive sizing multiplier, must be > 1. Default: 1.5
MinSegmentSize: number?--
Hard floor for adaptive segment size (studs). Default: 0.1
MaxBouncesPerFrame: number?--
Per-frame bounce cap across all sub-segments. Default: 10
CornerTimeThreshold: number?--
Min seconds between bounces (Pass 1). Default: 0.002
CornerPositionHistorySize: number?--
Bounce position history size, positive integer (Pass 3 & 4). Default: 4
CornerDisplacementThreshold: number?--
Min bounce separation in studs (Pass 3). Default: 0.5
CornerEMAAlpha: number?--
EMA smoothing factor for velocity direction (0,1) (Pass 2). Default: 0.4
CornerEMAThreshold: number?--
EMA oscillation threshold (Pass 2). Must be > |1 - 2·alpha|. Default: 0.25
CornerMinProgressPerBounce: number?--
Min studs of progress per bounce over history (Pass 4). 0 disables Pass 4. Default: 0.3
LODDistance: number?--
Studs from the LOD origin beyond which this bullet steps at reduced frequency. 0 = always full frequency. Default: 0
CosmeticBulletContainer: Instance?--
Parent for the cosmetic object. Defaults to workspace. Default: nil
CosmeticBulletProvider: ((context: BulletContext) → Instance?)?--
Provider function; takes priority over Template. Default: nil
AutoDeleteCosmeticBullet: boolean?--
When true, the cosmetic Instance is destroyed automatically on termination. Set to false to manage cleanup yourself. Default: true
BatchTravel: boolean?--
Include this cast in OnTravelBatch instead of firing individual OnTravel events. Default: false
WindResponse: number?--
Multiplier on the solver's wind vector. 1.0 = fully affected, 0.0 = immune. Default: 1.0
VisualizeCasts: boolean?--
Enable trajectory visualizer for this cast. Default: false
}Complete configuration for a projectile cast. All fields are optional — any omitted field falls back to a safe built-in default.
Prefer constructing this via BehaviorBuilder rather than by hand to get
typed setters, build-time validation, and a frozen result. For fields not
exposed by the builder (drag, Magnus, homing config, tumble, etc.), pass a
raw table or a table that inherits from a built behavior via __index.
Physics
Aerodynamic Drag
Wind
Supersonic / Subsonic Profiles
Magnus Effect
Gyroscopic Drift
Tumble
Homing
Trajectory Provider
Pierce
Fragmentation
Bounce
High Fidelity
Corner Trap Detection
LOD
Cosmetic
Batch Travel
Wind Sensitivity
Debug
DragModel
type DragModel = "Linear" | "Quadratic" | "Exponential" | "G1" | "G2" | "G3" | "G4" | "G5" | "G6" | "G7" | "G8" | "GL" | "Custom"Drag model used to compute aerodynamic deceleration each DragSegmentInterval.
Analytic models:
"Linear", deceleration ∝ speed."Quadratic", deceleration ∝ speed² (default). Most physically accurate for subsonic bullets."Exponential", deceleration ∝ eˢᵖᵉᵉᵈ. Models exotic high-drag shapes.
G-series empirical models (Mach-indexed Cd lookup tables):
"G1", flat-base spitzer; general-purpose standard."G2", Aberdeen J projectile; large-caliber / atypical shapes."G5", boat-tail spitzer; mid-range rifles."G6", semi-spitzer flat-base; shotgun slugs."G7", long boat-tail; modern long-range / sniper standard."G8", flat-base semi-spitzer; hollow points / pistols."GL", lead round ball; cannons / muskets / buckshot.
User-supplied:
"Custom", requiresCustomMachTable = { {mach, cd}, ... }in the behavior.
NetworkMode
type NetworkMode = "ClientAuthoritative" | "ServerAuthority" | "SharedAuthority"Authority mode that controls which side may call :Fire() on a VetraNet handle.
"ClientAuthoritative", clients send fire requests; server validates. (Default)"ServerAuthority", only server code may initiate bullets; client fire requests are silently dropped."SharedAuthority", both client and server may fire; client requests go through validation, server calls bypass it.
Pass via NetworkConfig.Mode. Prefer Vetra.Enums.NetworkMode over raw strings.
TerminationReason
type TerminationReason = "hit" | "distance" | "speed" | "corner_trap" | "manual"
The reason a cast was terminated. Passed as the second argument to
OnPreTermination signal handlers.
"hit", bullet struck a surface and was not pierced or bounced."distance",MaxDistancewas reached."speed", speed dropped belowMinSpeedor exceededMaxSpeed."corner_trap", corner-trap detection terminated the cast."manual",Terminate()was called explicitly, or the solver was destroyed.
NetworkConfig
interface NetworkConfig {MaxOriginTolerance: number?--
Max studs between client-reported and server-reconstructed fire origin. Default: 15
MaxConcurrentPerPlayer: number?--
Maximum in-flight bullets per player at any time. Default: 20
TokensPerSecond: number?--
Token-bucket refill rate for fire-rate limiting. Default: 10
BurstLimit: number?--
Maximum burst tokens. Must be >= TokensPerSecond. Default: 20
DriftThreshold: number?--
Studs of positional drift before cosmetic correction begins. Default: 2
CorrectionRate: number?--
Lerp speed for cosmetic drift correction in studs/second. Default: 8
LatencyBuffer: number?--
Extra seconds to delay local cosmetic spawn. 0 = use measured RTT automatically. Default: 0
ReplicateState: boolean?--
Broadcast bullet state every Heartbeat to all clients for cosmetic correction. Default: true
Mode: NetworkMode?--
Authority mode. Controls which side may call :Fire(). Default: "ClientAuthoritative"
}
Optional configuration table passed to VetraNet.new() as the third argument.
All fields are optional, unset fields fall back to built-in defaults.
SpatialPartitionConfig
interface SpatialPartitionConfig {HotRadius: number?--
Studs radius around an interest point for HOT tier (full-frequency simulation). Default: 150
WarmRadius: number?--
Studs radius for WARM tier (must be >= HotRadius). Default: 400
FallbackTier: string?--
Tier for bullets outside all warm radii. "HOT", "WARM", or "COLD". Default: "HOT"
UpdateInterval: number?--
Frames between spatial grid rebuilds. Default: 3
}
Optional configuration for the LOD spatial partition system. Passed as
SpatialPartition inside the FactoryConfig to Vetra.new() or
Vetra.newParallel().