Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
84 commits
Select commit Hold shift + click to select a range
99d8290
Remove old autogen menu terribleness
marchc1 Jun 8, 2026
f98cc4c
Lets try a little inversion of control-ish here to ease conversion
marchc1 Jun 8, 2026
5dc4053
Switch entities to use the new names
marchc1 Jun 8, 2026
9edbba2
Start autoreg v2, new classes
marchc1 Jun 8, 2026
2e75c50
New class fields
marchc1 Jun 8, 2026
851075e
Fix a couple mistakes I made porting
marchc1 Jun 8, 2026
dd0ed1f
Serialization library attempt 1
marchc1 Jun 9, 2026
59d2e23
Convert baseplate types
marchc1 Jun 9, 2026
5d5c659
Further plumbing
marchc1 Jun 9, 2026
0297115
Start working on updating
marchc1 Jun 9, 2026
c1ceeca
Get baseplates pseudo-working
marchc1 Jun 9, 2026
e2beb7c
Baseplate menu autogen attempts + general fixups
marchc1 Jun 9, 2026
e03f4ed
Try wrapping up V2 so V1 can be converted over
marchc1 Jun 9, 2026
02919b8
Try converting autoloaders + new backwards compat system
marchc1 Jun 9, 2026
f7b3a02
Fix missing AutoRegisterV1 call removal
marchc1 Jun 14, 2026
28df3f8
Try converting ground loaders
marchc1 Jun 14, 2026
c17b450
Move baseplate compat
marchc1 Jun 14, 2026
b8d8f4c
Convert waterjets over to autoreg v2
marchc1 Jun 14, 2026
c117bdf
Some changes to the class system
marchc1 Jun 14, 2026
06b0667
Add auto IsACFX flag, name preparations from arg
marchc1 Jun 14, 2026
a19e6c7
Adjust serialization slightly for new ID storage
marchc1 Jun 15, 2026
e5b5a9a
Convert piledrivers to autoreg v2
marchc1 Jun 16, 2026
371e159
Old yeller autoreg V1 (finally)
marchc1 Jun 16, 2026
da7cf73
baseweapon
marchc1 Jun 16, 2026
3a128f9
Fix piledriver menu issue
marchc1 Jun 16, 2026
1ee8f5d
Fix IsACFX conventions
marchc1 Jun 16, 2026
7536ce0
Convert supply crates over to autoreg v2
marchc1 Jun 16, 2026
74e74e0
Move ent compat around a bit, change ACE compat
marchc1 Jun 17, 2026
3ae4d23
Move ACE conversion to compatibility patches
marchc1 Jun 17, 2026
47fa559
Merge branch 'dev' into class-rework-try-4
marchc1 Jun 17, 2026
b952785
Fix linter issues
marchc1 Jun 17, 2026
e242bbc
Convert sensors/radars to autoregv2 + new
marchc1 Jun 17, 2026
88e1889
Convert turrets to autoregv2 + new classes
marchc1 Jun 17, 2026
ff20584
WIP fuel tank conversion
thecraftianman Jun 18, 2026
94267af
Revert "WIP fuel tank conversion"
marchc1 Jun 21, 2026
296ef22
Reorganize turret menu a bit
marchc1 Jun 21, 2026
1f7d6bc
Rework temporal panels slightly
marchc1 Jun 22, 2026
af5cd9d
Move acf_opticalcomputer compat to patches
marchc1 Jun 22, 2026
533de63
Try adding serialization vector/angle again
marchc1 Jun 22, 2026
235f342
Ammo, fuel conversion, supply fixes
marchc1 Jun 22, 2026
ebbf000
Start converting guns to new class system
marchc1 Jun 22, 2026
d447ad5
Add baseweapon
marchc1 Jun 22, 2026
bffb51b
Start missile conversion, add WeaponEquals
marchc1 Jun 22, 2026
e043dea
Get all base classes for missiles converted FIX NOTE
marchc1 Jun 22, 2026
7e717fe
Convert missile classes to new classes
marchc1 Jun 22, 2026
de1ad74
Convert names of guidances
marchc1 Jun 22, 2026
1af82f0
Try converting guidance to new classes
marchc1 Jun 22, 2026
40a0c84
Convert fuzes
marchc1 Jun 22, 2026
b33c67a
Add Guidance/Fuze to BaseMissile
marchc1 Jun 22, 2026
c009134
Remove legacy fuze/guidance registration (forgot)
marchc1 Jun 22, 2026
80c5e1d
Make linter happy again
marchc1 Jun 22, 2026
5ccbce5
cONVERT AMMO TO CLASSES (UNTESTED)
marchc1 Jun 22, 2026
df29dfa
Remove last uses of AddArguments in ammo
marchc1 Jun 22, 2026
fdfc2e9
Start converting more type names
marchc1 Jun 23, 2026
8e9e35d
Ammunition type fixes
marchc1 Jun 23, 2026
b48593c
Slight class system changes
marchc1 Jun 23, 2026
637766f
Flattened hierarchy optimization
marchc1 Jun 23, 2026
e3cc88c
Further fixes
marchc1 Jun 23, 2026
0adb200
Update cannon.lua
marchc1 Jun 23, 2026
f74bf5a
Update lightautocannon.lua
marchc1 Jun 23, 2026
ae43c2e
Another mistake...
marchc1 Jun 23, 2026
87aa762
Fix some class issues
marchc1 Jun 23, 2026
0dcc73c
Cleanup AmmoTypes consumers
marchc1 Jun 23, 2026
73a4a3f
Cleanup most weapon consumers, new class fns
marchc1 Jun 23, 2026
11e27c7
More weapon changes
marchc1 Jun 23, 2026
d0030e9
Try making this ballistics piece a little less confusing
marchc1 Jun 23, 2026
3613a79
Start removing weaponry sources, further bulletdata changes
marchc1 Jun 23, 2026
e7ef4d4
Remove ACF.FindWeaponrySource
marchc1 Jun 23, 2026
73493ea
Rework GetWeaponBlacklist around new classes
marchc1 Jun 23, 2026
29cf11c
Fix remaining old gun shortnames -> newclass FQN
marchc1 Jun 23, 2026
ae6169e
I lied now i fixed all the shortnames
marchc1 Jun 23, 2026
c84d0b1
Move menu fields in ammo classes higher
marchc1 Jun 23, 2026
1162cb6
Some more work on removing destiny (none of this works right)
marchc1 Jun 23, 2026
3adf229
New ammo functions
marchc1 Jun 23, 2026
245ba53
Further ammo conversion
marchc1 Jun 23, 2026
3ead8bb
WIP GetWeaponValue conversion (fixme)
marchc1 Jun 24, 2026
c8e58fd
Wow this is gonna be broken as hell
marchc1 Jun 24, 2026
62d545c
Try porting guns to autoreg v2 (miserably failing)
marchc1 Jun 24, 2026
849fd9c
Fix quite a few problems with the weapon menu
marchc1 Jun 24, 2026
a5f0815
New field menu experiments
marchc1 Jun 24, 2026
4787c5b
Split apart that file
marchc1 Jun 24, 2026
af497e1
lets rethink menus here
marchc1 Jun 24, 2026
0558948
Start separating ACF panels
marchc1 Jun 24, 2026
21d8c25
remove datavars
marchc1 Jun 24, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions ARCHITECTURE_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ lua/acf/entities/ammo_types/
-- Becomes table structure
ACF.Core.Utilities
ACF.Damage
ACF.Entities.AmmoTypes
```

**Keep the root table clean:**
Expand Down Expand Up @@ -103,7 +102,7 @@ end
local Ammo = AmmoTypes.Register("HE", "APHE") -- Second arg is base class

function Ammo:OnLoaded()
Ammo.BaseClass.OnLoaded(self) -- Call parent
BASE.OnLoaded(self) -- Call parent

self.Name = "High Explosive"
self.Description = "Explodes on impact."
Expand Down
15 changes: 7 additions & 8 deletions lua/acf/ballistics/ballistics_sv.lua
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ local IndexLimit = 2000
local SkyGraceZone = 100
local FlightTr = { start = true, endpos = true, filter = true, mask = true }
local GlobalFilter = ACF.GlobalFilter
local AmmoTypes = ACF.Classes.AmmoTypes

-- This will create, or update, the tracer effect on the clientside
function Ballistics.BulletClient(Bullet, Type, Hit, HitPos)
Expand Down Expand Up @@ -164,11 +163,11 @@ function Ballistics.CreateBullet(BulletData)
EventViewer.AppendEvent(GetEventViewerName(Index), "Ballistics.CreateBullet", Bullet)
end

Bullet.TypeDef = ACF.Classes.GetSubtypeByName("ACF.Ammunition.BaseAmmo", Bullet.AmmoType)

-- TODO: Make bullets use a metatable instead
function Bullet:GetPenetration()
local Ammo = AmmoTypes.Get(Bullet.Type)

return Ammo:GetPenetration(self)
return Bullet.TypeDef:GetPenetration(self)
end

if not next(Bullets) then
Expand Down Expand Up @@ -298,7 +297,7 @@ function Ballistics.DoBulletsFlight(Bullet)

Ballistics.BulletClient(Bullet, "Update", 1, Bullet.Pos)

AmmoTypes.Get(Bullet.Type):OnFlightEnd(Bullet, traceRes)
Bullet.TypeDef:OnFlightEnd(Bullet, traceRes)
if EventViewer.Enabled() then
EventViewer.AppendEvent(GetEventViewerName(Bullet.Index), "Ballistics.DoBulletsFlight.Fuze")
end
Expand Down Expand Up @@ -335,7 +334,7 @@ function Ballistics.DoBulletsFlight(Bullet)

local Type = Ballistics.GetImpactType(traceRes, Entity)

Ballistics.OnImpact(Bullet, traceRes, AmmoTypes.Get(Bullet.Type), Type)
Ballistics.OnImpact(Bullet, traceRes, Bullet.TypeDef, Type)
end
end
end
Expand Down Expand Up @@ -492,8 +491,8 @@ do -- Terminal ballistics --------------------------
Ballistics.CreateBullet({
Caliber = FragSize,
Diameter = FragSize,
-- Id = Bullet.Id,
Type = "AP",
-- WeaponType = Bullet.WeaponType,
Type = "ACF.Ammunition.AP",
Owner = Bullet.Owner,
Entity = Bullet.Entity,
-- Crate = Bullet.Crate,
Expand Down
32 changes: 32 additions & 0 deletions lua/acf/compatibility/ace/crew.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
local ACEConversionLUT = {}
ACEConversionLUT.ace_crewseat_driver = {
CrewType = "Driver"
}

ACEConversionLUT.ace_crewseat_gunner = {
CrewType = "Gunner"
}

ACEConversionLUT.ace_crewseat_loader = {
CrewType = "Loader"
}

local ACEModelConversion = {}
ACEModelConversion.Sitting = "Sitting_Large"
ACEModelConversion["Sitting Alt"] = "Sitting_Large"
ACEModelConversion.Standing = "Standing_Large"
-- todo
ACEModelConversion.Jeep = "Standing_Large"
ACEModelConversion.Airboat = "Standing_Large"

local function ConvertACEData(Data, ConvData)
Data.Class = "acf_crew"
Data.CrewTypeID = ConvData.CrewType
Data.CrewModelID = ACEModelConversion[Data.ModelType]

Data.ModelType = nil
end

for Class, ConvData in pairs(ACEConversionLUT) do
ACF.Classes.Entities.RegisterCompatPatch(Class, -100000, function(Data) return ConvertACEData(Data, ConvData) end)
end
5 changes: 5 additions & 0 deletions lua/acf/compatibility/ace/sensors.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
ACF.Classes.Entities.RegisterCompatPatch("ace_trackingradar", -100000, function(Data) Data.Class = "acf_radar" end)
ACF.Classes.Entities.RegisterCompatPatch("ace_searchradar", -100000, function(Data) Data.Class = "acf_radar" end)

ACF.Classes.Entities.RegisterCompatPatch("ace_rwr_dir", -100000, function(Data) Data.Class = "acf_receiver" end)
ACF.Classes.Entities.RegisterCompatPatch("ace_rwr_sphere", -100000, function(Data) Data.Class = "acf_receiver" end)
28 changes: 28 additions & 0 deletions lua/acf/compatibility/acf3/ammo.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
local GetType = ACF.Classes.GetTypeByName

-- Translates a legacy shape short ID ("Box"/"Cylinder") into a ContainerShapes class FQN.
local function ShapeFQN(ID)
local FQN = "ACF.ContainerShapes." .. tostring(ID)

return GetType(FQN) and FQN or "ACF.ContainerShapes.Box"
end


-- This was for the autoregisterv2 conversion
ACF.Classes.Entities.RegisterCompatPatch("acf_ammo", 2026062101, function(Data)
if Data.ACF_UserData then return end

local WeaponTypeInstance = {Type = Data.Weapon, Data = {}}
local AmmoTypeInstance = {Type = Data.AmmoType, Data = {}}

Data.ACF_UserData = {
Weapon = WeaponTypeInstance,
Caliber = Data.Caliber,
AmmoType = AmmoTypeInstance,
AmmoStage = Data.AmmoStage,
Shape = ShapeFQN(Data.AmmoShape or "Box"),
CrateProjectilesX = Data.CrateProjectilesX,
CrateProjectilesY = Data.CrateProjectilesY,
CrateProjectilesZ = Data.CrateProjectilesZ,
}
end)
15 changes: 15 additions & 0 deletions lua/acf/compatibility/acf3/autoloaders.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
ACF.Classes.Entities.RegisterCompatPatch("acf_autoloader", 2026060901, function(Data)
local EntityMods = Data.EntityMods
if not EntityMods then return end

local ACF_UserData = Data.ACF_UserData
if not ACF_UserData then return end

if EntityMods.ACFGun and ACF_UserData.Gun == nil then
ACF_UserData.Gun = EntityMods.ACFGun[1]
end

if EntityMods.ACFAmmoCrates and ACF_UserData.AmmoCrates == nil then
ACF_UserData.AmmoCrates = table.Copy(EntityMods.ACFAmmoCrates)
end
end)
29 changes: 29 additions & 0 deletions lua/acf/compatibility/acf3/baseplates.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
ACF.Classes.Entities.RegisterCompatPatch("acf_baseplate", 2026060901, function(Data)
local ACF_UserData = Data.ACF_UserData
if not ACF_UserData then return end

-- Patch pre-new class system
if type(ACF_UserData.BaseplateType) == "string" then
local OldBaseplateTypeString = ACF_UserData.BaseplateType
local Type = ACF.Classes.GetTypeByName("ACF.Baseplates." .. OldBaseplateTypeString)
if not Type then
Type = ACF.Classes.GetTypeByName("ACF.Baseplates.GroundVehicle")
end

local BpData = {}
ACF_UserData.BaseplateType = {
Type = ACF.Classes.GetTypeName(Type),
Data = BpData
}

if OldBaseplateTypeString == "Aircraft" then
BpData.GForceTicks = ACF_UserData.GForceTicks
ACF_UserData.GForceTicks = nil
end

if OldBaseplateTypeString == "Recreational" then
BpData.ExplodeOnCollisions = ACF_UserData.ExplodeOnCollisions
ACF_UserData.ExplodeOnCollisions = nil
end
end
end)
75 changes: 75 additions & 0 deletions lua/acf/compatibility/acf3/cannon_oldmodels.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
local OldModels = {
["models/tankgun/tankgun_100mm.mdl"] = true,
["models/tankgun/tankgun_120mm.mdl"] = true,
["models/tankgun/tankgun_140mm.mdl"] = true,
["models/tankgun/tankgun_170mm.mdl"] = true,
["models/tankgun/tankgun_37mm.mdl"] = true,
["models/tankgun/tankgun_50mm.mdl"] = true,
["models/tankgun/tankgun_75mm.mdl"] = true,
}

-- Bodygroup porting information
-- First table defines the bodygroup from the old model
-- Second table defines the index of of a specific body
-- Third can be either a table, defining the values that need to be applied into the new model
-- or "false", if there's no equivalent in the new model
local PortingData = {
-- Muzzlebrakes
[1] = {
[1] = false,
[2] = false,
[3] = { [8] = 5 },
[4] = { [8] = 1 },
[5] = false,
[6] = { [8] = 3 },
[7] = false,
[8] = false,
[9] = { [7] = 4 },
[10] = { [8] = 2 },
[11] = { [8] = 4 },
},
-- Bore evacuators
[2] = {
[1] = false,
[2] = false,
[3] = false,
[4] = { [9] = 1 },
[5] = { [9] = 2 },
[6] = { [9] = 3 },
},
}

-- patch ID from https://github.com/ACF-Team/ACF-3/commit/cadf24dc5a0fa78df21f81600692c1ee7887a390
ACF.Classes.Entities.RegisterCompatPatch("acf_gun", 2021111301, function(Data)
local Model = Data.Model

if not (Model and OldModels[Model]) then return end

local Bodygroups = Data.BodyG
local Result = {}

if Bodygroups then
for Index, Value in pairs(Bodygroups) do
local OldData = PortingData[Index]

if not OldData then continue end

local NewData = OldData[Value]

if NewData then
for NewIndex, NewValue in pairs(NewData) do
Result[NewIndex] = NewValue or nil
end
end

Bodygroups[Index] = nil
end
end

-- Applying cosmetic features to make it look like the old model
Result[1] = 1
Result[4] = 1
Result[5] = 2

Data.BodyG = Result
end)
3 changes: 3 additions & 0 deletions lua/acf/compatibility/acf3/computers.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
ACF.Classes.Entities.RegisterCompatPatch("acf_opticalcomputer", 2026062101, function(Data)
Data.Class = "acf_computer"
end)
55 changes: 55 additions & 0 deletions lua/acf/compatibility/acf3/fueltanks.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
local GetType = ACF.Classes.GetTypeByName

-- Translates a legacy shape short ID ("Box"/"Sphere"/"Cylinder") into a ContainerShapes class FQN.
local function ShapeFQN(ID)
local FQN = "ACF.ContainerShapes." .. tostring(ID)

return GetType(FQN) and FQN or "ACF.ContainerShapes.Box"
end

-- Migrates legacy ACF-3 / ACE fuel tanks onto the AutoRegisterV2 serialized field set. This is where
-- all the historical size/shape encodings are normalised into FuelSizeX/Y/Z + the Shape class field;
-- FuelType is left as-is (the entity's ACF_OnVerifyClientData resolves the short id into a class).
ACF.Classes.Entities.RegisterCompatPatch("acf_fueltank", 2026062101, function(Data)
if Data.ACF_UserData then return end

local Old = Data.Data or {}
local FuelTank = Old.FuelTank or Data.FuelTank
local Size = Old.Size or Data.Size
local SizeId = Old.SizeId or Data.SizeId
local ShapeID = Old.FuelShape or Data.FuelShape
local SX = Old.FuelSizeX or Data.FuelSizeX
local SY = Old.FuelSizeY or Data.FuelSizeY
local SZ = Old.FuelSizeZ or Data.FuelSizeZ

-- Only derive size when it wasn't already saved per-axis (FuelSizeX/Y/Z).
if not (SX and SY and SZ) then
if isvector(SizeId) or isvector(Size) then
-- Size saved as a Size/SizeId vector; shape encoded in the FuelTank group id.
local S = isvector(SizeId) and SizeId or Size
SX, SY, SZ = S[1], S[2], S[3]

if isstring(FuelTank) then
ShapeID = FuelTank == "Drum" and "Cylinder" or "Box"
end
elseif isstring(FuelTank) and string.StartsWith(FuelTank, "Tank_") then
-- Pre-scalable boxes. X and Y are swapped on purpose to match old tank models.
local TankSize = string.Split(string.TrimLeft(FuelTank, "Tank_"), "x")
SX = (tonumber(TankSize[2]) or 2.4) * 10
SY = (tonumber(TankSize[1]) or 2.4) * 10
SZ = (tonumber(TankSize[3]) or 2.4) * 10
elseif FuelTank == "Fuel_Drum" then
-- Pre-scalable fuel drums.
ShapeID = "Cylinder"
SX, SY, SZ = 28, 28, 45
end
end

Data.ACF_UserData = {
FuelType = Old.FuelType or Data.FuelType,
Shape = ShapeFQN(ShapeID or "Box"),
FuelSizeX = SX,
FuelSizeY = SY,
FuelSizeZ = SZ,
}
end)
14 changes: 14 additions & 0 deletions lua/acf/compatibility/acf3/piledrivers.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
ACF.Classes.Entities.RegisterCompatPatch("acf_piledriver", 2026061501, function(Data)
local UD = Data.ACF_UserData
if not UD then return end
if type(UD.Weapon) == "table" and UD.Weapon.Type then return end -- Already V2

local OldId = UD.Id or Data.Id or (isstring(UD.Weapon) and UD.Weapon) or ""
local Caliber = tonumber(UD.Caliber)
or tonumber(string.match(tostring(OldId), "%d+"))
or 100

UD.Weapon = { Type = "ACF.Piledrivers.Piledriver", Data = { Caliber = Caliber } }
UD.Caliber = nil
UD.Id = nil
end)
53 changes: 53 additions & 0 deletions lua/acf/compatibility/acf3/sensors.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
local Classes = ACF.Classes
local Entities = Classes.Entities

local Defaults = {
acf_radar = "ACF.Sensors.Radar.Targeting.SmallDirectional",
acf_receiver = "ACF.Sensors.Receiver.Warning.Laser",
}

local IDMap

local function BuildIDMap()
local Map = {}

for _, Class in pairs(Classes.GetSubtypes("ACF.Sensors.Sensor")) do
if Class.ID and not next(Classes.GetChildren(Class)) then
Map[Class.ID] = Classes.GetTypeName(Class)
end
end

return Map
end

local function Convert(Data, ClassName, DefaultOverride)
local UD = Data.ACF_UserData
if type(UD) == "table" and type(UD.Sensor) == "table" and UD.Sensor.Type then return end -- Already V2

if not IDMap then IDMap = BuildIDMap() end

local Old =
(UD and (UD.Radar or UD.Receiver or UD.Sensor or UD.Id)) or
Data.Radar or Data.Receiver or Data.Sensor or Data.Id

if not Old and type(Data.Data) == "table" then
local D = Data.Data
Old = D.Radar or D.Receiver or D.Sensor or D.Id
end

local FQN = (isstring(Old) and IDMap[Old]) or DefaultOverride or Defaults[ClassName]

UD = UD or {}
UD.Sensor = { Type = FQN, Data = {} }
UD.Radar, UD.Receiver, UD.Id = nil, nil, nil

Data.ACF_UserData = UD
end

Entities.RegisterCompatPatch("acf_radar", 2026061601, function(Data) Convert(Data, "acf_radar") end)
Entities.RegisterCompatPatch("acf_receiver", 2026061601, function(Data) Convert(Data, "acf_receiver") end)

Entities.RegisterCompatPatch("acf_missileradar", 2026061601, function(Data)
Data.Class = "acf_radar"
Convert(Data, "acf_radar", "ACF.Sensors.Radar.Missile.SmallDirectional")
end)
Loading
Loading