Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
38 changes: 19 additions & 19 deletions lua/acf/server/sv_acfbase.lua
Original file line number Diff line number Diff line change
Expand Up @@ -111,24 +111,24 @@ function ACF_Activate( Entity , Recalc )
end
end

local IGNORED_CLASSES = {
gmod_ghost = true,
prop_ragdoll = true,
ace_debris = true,
sent_prop2mesh = true,
}

function ACF_Check( Entity )

if not IsValid(Entity) then return false end

local physobj = Entity:GetPhysicsObject()
local IGNORED_CLASSES = {
gmod_ghost = true,
prop_ragdoll = true,
ace_debris = true,
sent_prop2mesh = true,
}
function ACF_Check( Entity )
if not IsValid(Entity) then return false end
local physobj = Entity:GetPhysicsObject()
if not ( physobj:IsValid() and (physobj:GetMass() or 0) > 0 and not Entity:IsWorld() and not Entity:IsWeapon() ) then return false end

local Class = Entity:GetClass()
if IGNORED_CLASSES[Class] or ( Class ~= "func_breakable" and string.find( Class , "func_" )) then return false end
if Entity.Exploding then return false end

local Class = Entity:GetClass()
if IGNORED_CLASSES[Class] or (ACF.TraceFilter and ACF.TraceFilter[Class]) or ( Class ~= "func_breakable" and string.find( Class , "func_" )) then return false end
if Entity.Exploding then return false end
if not Entity.ACF or (Entity.ACF and isnumber(Entity.ACF.Material)) then
ACF_Activate( Entity )
elseif Entity.ACF.Mass ~= physobj:GetMass() or (not IsValid(Entity.ACF.PhysObj) or Entity.ACF.PhysObj ~= physobj) then
Expand Down Expand Up @@ -211,8 +211,8 @@ function ACF_CalcDamage( Entity , Energy , FrArea , Angle , Type) --y=-5/16x + b
damageMult = ACF.HPDamageMult
end

-- RHA Penetration
local maxPenetration = ACE_CalcPenetration(Energy, FrArea)
-- RHA Penetration
local maxPenetration = ACE_CalcPenetration(Energy, FrArea)

-- Projectile caliber. Messy, function signature
local caliber = 20 * (FrArea ^ (1 / ACF.PenAreaMod) / 3.1416) ^ 0.5
Expand Down Expand Up @@ -839,4 +839,4 @@ function chatMessageGlobal( message, color) --Like chatMessagePly but it just go
chatMessagePly( ply , message, color)
end
end
]]--
]]--
8 changes: 4 additions & 4 deletions lua/acf/server/sv_acfdamage.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
ACE.Spall = {}
ACE.CurSpallIndex = 0
ACE.SpallMax = 250

-- optimization; reuse tables for ballistics traces
local TraceRes = {}
local TraceInit = { output = TraceRes }
Expand Down Expand Up @@ -635,7 +635,7 @@ function ACF_Spall_HESH( HitPos, HitVec, Filter, HEFiller, Caliber, Armour, Infl
local Velocityfactor = 0.12
local Max_Spall_Vel = 7000
local MassFactor = 6

local Max_Spalls = 128

-- print("HE: " .. HEFiller)
Expand All @@ -654,8 +654,8 @@ function ACF_Spall_HESH( HitPos, HitVec, Filter, HEFiller, Caliber, Armour, Infl
SpallWeight = SpallWeight * MassFactor
local SpallArea = 4 * (TotalWeight / SpallWeight)
local SpallEnergy = ACF_Kinetic(SpallVel, SpallWeight, Max_Spall_Vel)
-- print("AR: " .. SpallArea)

-- print("AR: " .. SpallArea)

-- print("TW: " .. TotalWeight)

Expand Down
10 changes: 6 additions & 4 deletions lua/acf/server/sv_pointshandling.lua
Original file line number Diff line number Diff line change
Expand Up @@ -713,13 +713,14 @@ ACE_CalcContraptionArmor = function(ent)
end
end

local ignoredArmor = {
acf_gun = true,
acf_rack = true,
local ignoredArmor = table.Copy(ACF.TraceFilter or {})
table.Merge(ignoredArmor, {
acf_gun = false,
acf_rack = false,
ace_crewseat_gunner = true,
ace_crewseat_loader = true,
ace_crewseat_driver = true
}
})

-- Build an orthonormal basis from a direction.
local function basisFromDir(dir)
Expand Down Expand Up @@ -1186,3 +1187,4 @@ function ACE_EnsureArmor(con, baseEnt, force)
end

_G.ACE_EnsureArmor = ACE_EnsureArmor

186 changes: 74 additions & 112 deletions lua/acf/shared/sh_ace_functions.lua
Original file line number Diff line number Diff line change
Expand Up @@ -870,102 +870,6 @@ function ACE_SafeRound1(value)
return math.Round(ACE_SafeNonNegative(value), 1)
end

do
-- Ensure all ACE/ACF traces respect ACF.TraceFilter, even when a local filter
-- is missing or incomplete in a specific trace call site.
if util and not ACE._TraceFilterWrapped then
local RawTraceLine = util.TraceLine
local RawTraceHull = util.TraceHull
local RawQuickTrace = util.QuickTrace
local RawLegacyTraceLine = util.LegacyTraceLine

local function shouldIgnoreByClass(ent)
if not IsValid(ent) then return false end

local class = ent:GetClass()
if not class or class == "" then return false end

local ignored = ACF and ACF.TraceFilter
return ignored and ignored[class] or false
end

local function normalizeFilter(filter)
if isfunction(filter) then
return function(ent)
if shouldIgnoreByClass(ent) then return true end
return filter(ent)
end
end

if IsValid(filter) then
return function(ent)
if shouldIgnoreByClass(ent) then return true end
return ent == filter
end
end

if istable(filter) then
local lookup = {}
for _, item in pairs(filter) do
if IsValid(item) then
lookup[item] = true
end
end

return function(ent)
if shouldIgnoreByClass(ent) then return true end
return lookup[ent] or false
end
end

return function(ent)
return shouldIgnoreByClass(ent)
end
end

if isfunction(RawTraceLine) then
util.TraceLine = function(traceData)
if not istable(traceData) then
return RawTraceLine(traceData)
end

traceData.filter = normalizeFilter(traceData.filter)
return RawTraceLine(traceData)
end
end

if isfunction(RawTraceHull) then
util.TraceHull = function(traceData)
if not istable(traceData) then
return RawTraceHull(traceData)
end

traceData.filter = normalizeFilter(traceData.filter)
return RawTraceHull(traceData)
end
end

if isfunction(RawQuickTrace) then
util.QuickTrace = function(startPos, delta, filter)
return RawQuickTrace(startPos, delta, normalizeFilter(filter))
end
end

if isfunction(RawLegacyTraceLine) then
util.LegacyTraceLine = function(traceData)
if not istable(traceData) then
return RawLegacyTraceLine(traceData)
end

traceData.filter = normalizeFilter(traceData.filter)
return RawLegacyTraceLine(traceData)
end
end

ACE._TraceFilterWrapped = true
end
end

function ACE_FormatDetailLabel(ent)
if not ACE_IsEnt(ent) then return "Unknown" end

Expand Down Expand Up @@ -1006,10 +910,55 @@ end
function ACE_GetMissileGuidanceFactor(guidanceValue)
local factors = ACE.MissileGuidanceFactors or {}
local fallback = tonumber(factors.Dumb) or 1
local name = ACE_GetConfigurableName(guidanceValue, "Dumb")
local factor = tonumber(factors[name]) or fallback

return math.max(factor, 0)
local function normalizeName(name)
if type(name) ~= "string" or name == "" then return nil end
return (name:gsub("%s+", "_"):gsub("%-", "_"))
end

local function resolveFactorFromName(name)
name = normalizeName(name)
if not name then return nil end

local direct = tonumber(factors[name])
if direct then return direct end

local lower = string.lower(name)
for key, value in pairs(factors) do
if string.lower(tostring(key)) == lower then
return tonumber(value)
end
end

return nil
end

-- Direct string forms, including configurable "Name:arg=val".
if type(guidanceValue) == "string" then
local name = ACE_GetConfigurableName(guidanceValue, "Dumb")
local factor = resolveFactorFromName(name) or resolveFactorFromName(guidanceValue) or fallback
return math.max(factor, 0)
end

-- Configurable/table forms used at runtime by missile entities.
if istable(guidanceValue) then
local candidates = {
guidanceValue.Name,
guidanceValue.name,
guidanceValue.ClassName,
guidanceValue.class,
guidanceValue.GuidanceName,
guidanceValue.Guidance,
guidanceValue.Type
}

for _, candidate in ipairs(candidates) do
local factor = resolveFactorFromName(candidate)
if factor then return math.max(factor, 0) end
end
end

return math.max(fallback, 0)
end

-- Resolve the gun class string for ammo bullet data.
Expand Down Expand Up @@ -1124,6 +1073,14 @@ function ACE_IsATGMCostAmmo(bdata)
return ACE_GetAmmoGunClass(bdata) == "ATGM"
end

-- Resolve guidance scaling used by missile point/threat math.
local function ACE_GetAmmoGuidancePenFactor(bdata)
if not bdata or not ACE_IsAmmoMissileType(bdata) then return 1 end
-- Guidance should act as an upward threat modifier in pen-space, not make
-- missiles artificially cheap when using low-end guidance packages.
return math.max(ACE_GetMissileGuidanceFactor(bdata.Data7), 1)
end

-- Calculate per-missile legacy points (manufacturing-cost basis), including guidance.
function ACE_CalcMissileLegacyRoundCost(bdata)
if not istable(bdata) then return 0 end
Expand Down Expand Up @@ -1152,8 +1109,12 @@ function ACE_CalcMissileLegacyRoundCost(bdata)
end

basePts = math.max(basePts, minBase)

-- Guidance is already applied in missile threat/penetration scaling for ATGM perf points.
return math.max(basePts, 0)
end

-- Non-ATGM missile racks still use legacy pointcost, so guidance is applied here.
return math.max(basePts, 0) * factor
end

Expand Down Expand Up @@ -1186,7 +1147,8 @@ function ACE_GetRofThreatFactor(rps, cfg)
local kneeRpm = tonumber(cfg.RofKneeRpm) or 0
if kneeRpm <= 0 then return 0 end

local rpm = rpsValue * 60
local minRpm = tonumber(cfg.MinRofRpm) or 0
local rpm = math.max(rpsValue * 60, minRpm)
return rpm / (rpm + kneeRpm)
end

Expand All @@ -1210,12 +1172,12 @@ function ACE_GetReadyRackCap(calMm)
end

-- Calculate per-round points (no RPS factors) for ammo allocation weighting.
function ACE_GetAmmoRoundPoints(bdata)
if not bdata then return 0 end
local maxPen = ACE_GetAmmoMaxPen(bdata)
local blastMass = ACE_GetAmmoBlastMass(bdata)
if maxPen <= 0 and blastMass <= 0 then return 0 end
function ACE_GetAmmoRoundPoints(bdata)
if not bdata then return 0 end

local maxPen = ACE_GetAmmoMaxPen(bdata) * ACE_GetAmmoGuidancePenFactor(bdata)
local blastMass = ACE_GetAmmoBlastMass(bdata)
if maxPen <= 0 and blastMass <= 0 then return 0 end

local calMm = ACE_GetAmmoCaliberMm(bdata)
if calMm <= 0 then return 0 end
Expand Down Expand Up @@ -1259,12 +1221,12 @@ function ACE_GetAmmoRoundPoints(bdata)
end

-- Calculate threat weight for ready-rack allocation.
function ACE_GetAmmoThreatWeight(bdata)
if not bdata then return 0 end
local maxPen = ACE_GetAmmoMaxPen(bdata)
local blastMass = ACE_GetAmmoBlastMass(bdata)
if maxPen <= 0 and blastMass <= 0 then return 0 end
function ACE_GetAmmoThreatWeight(bdata)
if not bdata then return 0 end

local maxPen = ACE_GetAmmoMaxPen(bdata) * ACE_GetAmmoGuidancePenFactor(bdata)
local blastMass = ACE_GetAmmoBlastMass(bdata)
if maxPen <= 0 and blastMass <= 0 then return 0 end

local cfg = ACE.AmmoCostConfig or {}
local refBlast = cfg.RefBlastMass or 0
Expand Down
Loading