Залив
This commit is contained in:
220
lua/includes/modules/mw_math.lua
Normal file
220
lua/includes/modules/mw_math.lua
Normal file
@@ -0,0 +1,220 @@
|
||||
AddCSLuaFile()
|
||||
module("mw_math", package.seeall)
|
||||
|
||||
--globals
|
||||
--ik zero_vector and zero_angle exist, i'm just making sure i'm managing my own
|
||||
mw_math.ZeroVector = Vector(0, 0, 0)
|
||||
mw_math.ZeroAngle = Angle(0, 0, 0)
|
||||
|
||||
local cachedSquareRoots = {}
|
||||
|
||||
function mw_math.SquareRoot(val)
|
||||
val = math.floor(val)
|
||||
cachedSquareRoots[val] = cachedSquareRoots[val] || math.sqrt(val)
|
||||
return cachedSquareRoots[val]
|
||||
end
|
||||
|
||||
function mw_math.CosineInterp(rate, current, target)
|
||||
rate = (1 - math.cos(rate * math.pi)) * 0.5
|
||||
return current * (1 - rate) + target * rate
|
||||
end
|
||||
|
||||
--lerp
|
||||
local clamp = math.Clamp
|
||||
local lerp = Lerp
|
||||
|
||||
function mw_math.SafeLerp(rate, current, target)
|
||||
--[[if (math.abs(current - target) < 0.001) then
|
||||
return target
|
||||
end
|
||||
|
||||
return Lerp(math.Clamp(rate, 0, 1), current, target)]]
|
||||
|
||||
return lerp(clamp(rate, 0, 1), current, target)
|
||||
end
|
||||
|
||||
function mw_math.SafeLerpVector(rate, current, target)
|
||||
current.x = SafeLerp(rate, current.x, target.x)
|
||||
current.y = SafeLerp(rate, current.y, target.y)
|
||||
current.z = SafeLerp(rate, current.z, target.z)
|
||||
end
|
||||
|
||||
function mw_math.SafeLerpAngle(rate, current, target)
|
||||
current.p = SafeLerp(rate, current.p, target.p)
|
||||
current.y = SafeLerp(rate, current.y, target.y)
|
||||
current.r = SafeLerp(rate, current.r, target.r)
|
||||
end
|
||||
|
||||
--add and mul
|
||||
function mw_math.VectorAddAndMul(current, add, mul)
|
||||
current.x = current.x + (add.x * mul)
|
||||
current.y = current.y + (add.y * mul)
|
||||
current.z = current.z + (add.z * mul)
|
||||
end
|
||||
|
||||
function mw_math.AngleAddAndMul(current, add, mul)
|
||||
current.p = current.p + (add.p * mul)
|
||||
current.y = current.y + (add.y * mul)
|
||||
current.r = current.r + (add.r * mul)
|
||||
end
|
||||
|
||||
--spring
|
||||
function mw_math.CreateSpring(springConstant, wobbleConstant)
|
||||
local spring = {
|
||||
target = 0,
|
||||
lerp = 0,
|
||||
vel = 0,
|
||||
sc = springConstant,
|
||||
wc = wobbleConstant,
|
||||
|
||||
SetTarget = function(spring, target)
|
||||
spring.target = target
|
||||
end,
|
||||
|
||||
Decay = function(spring, springConstant, wobbleConstant)
|
||||
spring.lerp, spring.vel = mw_math.NumberDecay(spring.target, spring.lerp, spring.vel, spring.sc || springConstant, spring.wc || wobbleConstant)
|
||||
end,
|
||||
|
||||
GetValue = function(spring)
|
||||
return spring.lerp
|
||||
end
|
||||
}
|
||||
|
||||
return spring
|
||||
end
|
||||
|
||||
function mw_math.CreateVectorSpring(springConstant, wobbleConstant)
|
||||
local spring = {
|
||||
target = Vector(),
|
||||
lerp = Vector(),
|
||||
vel = Vector(),
|
||||
sc = springConstant,
|
||||
wc = wobbleConstant,
|
||||
|
||||
SetTarget = function(spring, target)
|
||||
spring.target = target
|
||||
end,
|
||||
|
||||
Decay = function(spring, springConstant, wobbleConstant)
|
||||
mw_math.VectorDecay(spring.target, spring.lerp, spring.vel, spring.sc || springConstant, spring.wc || wobbleConstant)
|
||||
end,
|
||||
|
||||
GetValue = function(spring)
|
||||
return spring.lerp
|
||||
end
|
||||
}
|
||||
|
||||
return spring
|
||||
end
|
||||
|
||||
function mw_math.CreateAngleSpring(springConstant, wobbleConstant)
|
||||
local spring = {
|
||||
target = Angle(),
|
||||
lerp = Angle(),
|
||||
vel = Angle(),
|
||||
sc = springConstant,
|
||||
wc = wobbleConstant,
|
||||
|
||||
SetTarget = function(spring, target)
|
||||
spring.target = target
|
||||
end,
|
||||
|
||||
Decay = function(spring, springConstant, wobbleConstant)
|
||||
mw_math.AngleDecay(spring.target, spring.lerp, spring.vel, spring.sc || springConstant, spring.wc || wobbleConstant)
|
||||
end,
|
||||
|
||||
GetValue = function(spring)
|
||||
return spring.lerp
|
||||
end
|
||||
}
|
||||
|
||||
return spring
|
||||
end
|
||||
|
||||
function mw_math.DecaySprings(...)
|
||||
--[[for _, s in pairs({...}) do
|
||||
s:Decay()
|
||||
end]]
|
||||
local args = {...}
|
||||
for s = 1, #args do
|
||||
args[s]:Decay()
|
||||
end
|
||||
end
|
||||
|
||||
local realFrameTime = RealFrameTime
|
||||
local gcVec = Vector()
|
||||
local gcVecForce = Vector()
|
||||
function mw_math.VectorDecay(target, lerp, vel, springConstant, wobbleConstant)
|
||||
gcVec.x = (target.x - lerp.x) * springConstant
|
||||
gcVec.y = (target.y - lerp.y) * springConstant
|
||||
gcVec.z = (target.z - lerp.z) * springConstant
|
||||
|
||||
local sq = SquareRoot(springConstant)
|
||||
|
||||
gcVecForce.x = (-vel.x * wobbleConstant) * sq
|
||||
gcVecForce.y = (-vel.y * wobbleConstant) * sq
|
||||
gcVecForce.z = (-vel.z * wobbleConstant) * sq
|
||||
|
||||
gcVec.x = gcVec.x + gcVecForce.x
|
||||
gcVec.y = gcVec.y + gcVecForce.y
|
||||
gcVec.z = gcVec.z + gcVecForce.z
|
||||
|
||||
local rft = realFrameTime()
|
||||
VectorAddAndMul(vel, gcVec, rft)
|
||||
VectorAddAndMul(lerp, vel, rft)
|
||||
end
|
||||
|
||||
local gcAng = Angle()
|
||||
local gcAngForce = Angle()
|
||||
function mw_math.AngleDecay(target, lerp, vel, springConstant, wobbleConstant)
|
||||
gcAng.p = (target.p - lerp.p) * springConstant
|
||||
gcAng.y = (target.y - lerp.y) * springConstant
|
||||
gcAng.r = (target.r - lerp.r) * springConstant
|
||||
|
||||
local sq = SquareRoot(springConstant)
|
||||
|
||||
gcAngForce.p = (-vel.p * wobbleConstant) * sq
|
||||
gcAngForce.y = (-vel.y * wobbleConstant) * sq
|
||||
gcAngForce.r = (-vel.r * wobbleConstant) * sq
|
||||
|
||||
gcAng.p = gcAng.p + gcAngForce.p
|
||||
gcAng.y = gcAng.y + gcAngForce.y
|
||||
gcAng.r = gcAng.r + gcAngForce.r
|
||||
|
||||
local rft = realFrameTime()
|
||||
AngleAddAndMul(vel, gcAng, rft)
|
||||
AngleAddAndMul(lerp, vel, rft)
|
||||
end
|
||||
|
||||
function mw_math.NumberDecay(target, lerp, vel, springConstant, wobbleConstant)
|
||||
local currentToTarget = (target - lerp) * springConstant
|
||||
local dampingForce = (-vel * wobbleConstant) * SquareRoot(springConstant)
|
||||
|
||||
currentToTarget = currentToTarget + dampingForce
|
||||
|
||||
local rft = realFrameTime()
|
||||
vel = vel + (currentToTarget * rft)
|
||||
lerp = lerp + (vel * rft)
|
||||
|
||||
return lerp, vel
|
||||
end
|
||||
|
||||
--bool to number
|
||||
local boolToNumber = {[false] = 0, [true] = 1}
|
||||
function mw_math.btn(bool)
|
||||
return boolToNumber[bool]
|
||||
end
|
||||
|
||||
local direction = {[false] = -1, [true] = 1}
|
||||
local minmax = {[false] = math.max, [true] = math.min}
|
||||
function mw_math.Approach(current, target, rate)
|
||||
local what = current < target
|
||||
rate = rate * direction[what]
|
||||
return minmax[what](current + rate, -target, target)
|
||||
end
|
||||
|
||||
local angleDifference = math.AngleDifference
|
||||
function mw_math.ApproachAngle(current, target, rate)
|
||||
local diff = angleDifference(target, current)
|
||||
return mw_math.Approach(current, current + diff, rate)
|
||||
end
|
||||
392
lua/includes/modules/mw_utils.lua
Normal file
392
lua/includes/modules/mw_utils.lua
Normal file
@@ -0,0 +1,392 @@
|
||||
AddCSLuaFile()
|
||||
module("mw_utils", package.seeall)
|
||||
|
||||
local cachedBones = {}
|
||||
|
||||
function mw_utils.LookupBoneCached(ent, boneName)
|
||||
local model = ent:GetModel()
|
||||
|
||||
if (model == nil) then
|
||||
return nil
|
||||
end
|
||||
|
||||
cachedBones[model] = cachedBones[model] || {}
|
||||
cachedBones[model][boneName] = cachedBones[model][boneName] || ent:LookupBone(boneName)
|
||||
|
||||
return cachedBones[model][boneName]
|
||||
end
|
||||
|
||||
local cachedAttachments = {}
|
||||
|
||||
function mw_utils.LookupAttachmentCached(ent, attName)
|
||||
local model = ent:GetModel()
|
||||
|
||||
if (model == nil) then
|
||||
return nil
|
||||
end
|
||||
|
||||
cachedAttachments[model] = cachedAttachments[model] || {}
|
||||
cachedAttachments[model][attName] = cachedAttachments[model][attName] || ent:LookupAttachment(attName)
|
||||
|
||||
return cachedAttachments[model][attName] > 0 && cachedAttachments[model][attName] || nil
|
||||
end
|
||||
|
||||
local function recmatch(table1, table2)
|
||||
for k, v in pairs(table2) do
|
||||
if (table1[k] == nil) then
|
||||
return false
|
||||
end
|
||||
|
||||
if (istable(v)) then
|
||||
if (!recmatch(table1[k], v)) then
|
||||
return false
|
||||
end
|
||||
else
|
||||
if (v != table1[k]) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
for k, v in pairs(table1) do
|
||||
if (table2[k] == nil) then
|
||||
return false
|
||||
end
|
||||
|
||||
if (istable(v)) then
|
||||
if (!recmatch(table2[k], v)) then
|
||||
return false
|
||||
end
|
||||
else
|
||||
if (v != table2[k]) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
function mw_utils.CheckMatchingTables(table1, table2)
|
||||
return recmatch(table1, table2)
|
||||
end
|
||||
|
||||
function mw_utils.CheckMatchingBones(model1, model2)
|
||||
for b = 0, model1:GetBoneCount(), 1 do
|
||||
if (mw_utils.LookupBoneCached(model2, model1:GetBoneName(b))) != nil then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
function mw_utils.IsAttachmentBasedOn(current, base)
|
||||
while current != nil do
|
||||
if (current == base) then
|
||||
return true
|
||||
end
|
||||
|
||||
if (MW_ATTS[current] == nil) then
|
||||
return false
|
||||
end
|
||||
|
||||
current = MW_ATTS[current].Base
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
local function requireAttachment(ent, attName)
|
||||
ent.m_AttachmentRequests = ent.m_AttachmentRequests || {}
|
||||
ent.m_AttachmentDeliveries = ent.m_AttachmentDeliveries || {}
|
||||
|
||||
local attId = mw_utils.LookupAttachmentCached(ent, attName)
|
||||
|
||||
if (ent.m_AttachmentRequests[attId] == nil) then
|
||||
ent.m_AttachmentRequests[attId] = Matrix()
|
||||
|
||||
timer.Simple(0, function()
|
||||
if (!IsValid(ent)) then
|
||||
return
|
||||
end
|
||||
|
||||
local attData = ent:GetAttachment(attId)
|
||||
|
||||
local computeMatrix = Matrix()
|
||||
computeMatrix:SetTranslation(attData.Pos)
|
||||
computeMatrix:SetAngles(attData.Ang)
|
||||
|
||||
local worldMatrix = ent:GetBoneMatrix(0)
|
||||
|
||||
computeMatrix = worldMatrix:GetInverse() * computeMatrix
|
||||
ent.m_AttachmentRequests[attId] = computeMatrix
|
||||
end)
|
||||
|
||||
ent.m_AttachmentDeliveries[attId] = {Pos = Vector(), Ang = Angle()}
|
||||
end
|
||||
|
||||
if (!ent.m_bFastAttachment) then
|
||||
if (ent.OnBuildFastAttachments == nil) then
|
||||
ent.OnBuildFastAttachments = function() end --to avoid if
|
||||
end
|
||||
|
||||
ent:AddCallback("BuildBonePositions", function(ent, numbones)
|
||||
local matrix = ent:GetBoneMatrix(0)
|
||||
|
||||
if (matrix == nil) then
|
||||
return
|
||||
end
|
||||
|
||||
for attId, localMat in pairs(ent.m_AttachmentRequests) do
|
||||
local newMatrix = matrix * localMat
|
||||
|
||||
ent.m_AttachmentDeliveries[attId].Pos = newMatrix:GetTranslation()
|
||||
ent.m_AttachmentDeliveries[attId].Ang = newMatrix:GetAngles()
|
||||
ent:OnBuildFastAttachments()
|
||||
end
|
||||
end)
|
||||
|
||||
ent.m_bFastAttachment = true
|
||||
end
|
||||
end
|
||||
|
||||
--this is only really good for static props
|
||||
--it calculates local offset from root bone, so if the attachment isn't parented to that (or not static), it won't return
|
||||
--good values
|
||||
function mw_utils.GetFastAttachment(ent, attName)
|
||||
requireAttachment(ent, attName)
|
||||
return ent.m_AttachmentDeliveries[mw_utils.LookupAttachmentCached(ent, attName)]
|
||||
end
|
||||
|
||||
local function isInjectorLoadingConversions(inj)
|
||||
if (!istable(inj.Attachment)) then
|
||||
if (MW_ATTS[inj.Attachment] != nil) then
|
||||
return mw_utils.IsAttachmentBasedOn(inj.Attachment, "att_conversion")
|
||||
end
|
||||
else
|
||||
for i, injatt in pairs(inj.Attachment) do
|
||||
if (MW_ATTS[injatt] != nil) then
|
||||
if (mw_utils.IsAttachmentBasedOn(injatt, "att_conversion")) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
function mw_utils.LoadInjectors(swep)
|
||||
if (swep.Customization == nil) then
|
||||
mw_utils.ErrorPrint("LoadInjectors: Customization is nil! Are you loading before it?")
|
||||
return
|
||||
end
|
||||
|
||||
local swepClass = string.GetFileFromFilename(swep.Folder)
|
||||
|
||||
for className, inj in SortedPairs(MW_ATT_INJECTORS) do
|
||||
if (inj.SWEPs != nil && table.HasValue(inj.SWEPs, swepClass)) then
|
||||
local slot = isInjectorLoadingConversions(inj) && SLOT_CONVERSIONS || math.max(inj.Slot, SLOT_CONVERSIONS + 1)
|
||||
swep.Customization[slot] = swep.Customization[slot] || {}
|
||||
|
||||
if (!istable(inj.Attachment)) then
|
||||
if (MW_ATTS[inj.Attachment] != nil && !table.HasValue(swep.Customization[slot], inj.Attachment)) then
|
||||
table.insert(swep.Customization[slot], inj.Attachment)
|
||||
end
|
||||
else
|
||||
for i, injatt in pairs(inj.Attachment) do
|
||||
if (MW_ATTS[injatt] != nil && !table.HasValue(swep.Customization[slot], injatt)) then
|
||||
table.insert(swep.Customization[slot], injatt)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--https://gist.github.com/jrus/3197011
|
||||
local random = math.random
|
||||
local function uuid()
|
||||
local template ='xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'
|
||||
return string.gsub(template, '[xy]', function (c)
|
||||
local v = (c == 'x') and random(0, 0xf) or random(8, 0xb)
|
||||
return string.format('%x', v)
|
||||
end)
|
||||
end
|
||||
|
||||
function mw_utils.DevPrint(message)
|
||||
if (GetConVar("developer"):GetInt() > 0 && CLIENT) then
|
||||
MsgC(Color(120, 220, 100, 255), "MW Base: ", Color(255, 255, 255, 255), message.."\n")
|
||||
end
|
||||
end
|
||||
|
||||
function mw_utils.ErrorPrint(message)
|
||||
if (GetConVar("developer"):GetInt() > 0 && CLIENT) then
|
||||
MsgC(Color(220, 40, 80, 255), "MW Base ERROR: ", Color(255, 235, 235, 255), message.."\n")
|
||||
end
|
||||
end
|
||||
|
||||
function mw_utils.LoadPreset(weapon, preset)
|
||||
for slot, atts in SortedPairs(weapon.Customization) do
|
||||
local index = 1
|
||||
|
||||
for i, att in SortedPairs(atts) do
|
||||
if (table.HasValue(preset.Attachments, att)) then
|
||||
index = i
|
||||
end
|
||||
end
|
||||
|
||||
if (!weapon:HasAttachment(weapon.Customization[slot][index])) then --just sending what we need
|
||||
if (CLIENT) then
|
||||
mw_utils.SendAttachmentToServer(weapon, slot, index)
|
||||
else
|
||||
weapon:CreateAttachmentEntity(weapon.Customization[slot][index])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function mw_utils.ReloadAttachment(attachmentClass)
|
||||
if (GetConVar("sv_cheats"):GetInt() > 0 && GetConVar("developer"):GetInt() > 0) then
|
||||
local currentClass = attachmentClass
|
||||
while (currentClass != nil) do
|
||||
local folder = MW_ATTS[currentClass].Folder
|
||||
MW_ATTS[currentClass] = nil
|
||||
LoadAttachment(folder, currentClass..".lua") --mw_loader
|
||||
currentClass = MW_ATTS[currentClass].Base
|
||||
end
|
||||
|
||||
currentClass = attachmentClass
|
||||
while (currentClass != nil) do
|
||||
DoAttachmentInheritance(MW_ATTS[currentClass]) --mw_loader
|
||||
currentClass = MW_ATTS[currentClass].Base
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if (CLIENT) then
|
||||
--used to reparent ents after a fullupdate
|
||||
local FullUpdateEntities = {}
|
||||
|
||||
function mw_utils.DealWithFullUpdate(ent)
|
||||
FullUpdateEntities[ent] = true
|
||||
end
|
||||
|
||||
hook.Add("PreRender", "mw_utilsFullUpdatePreRender", function()
|
||||
for ent, _ in pairs(FullUpdateEntities) do
|
||||
if (!IsValid(ent)) then
|
||||
FullUpdateEntities[ent] = nil
|
||||
continue
|
||||
end
|
||||
|
||||
local fullUpdateParent = ent:GetInternalVariable("m_hNetworkMoveParent")
|
||||
|
||||
if (!IsValid(ent:GetParent()) && IsValid(fullUpdateParent)) then
|
||||
ent:SetParent(fullUpdateParent)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
function mw_utils.SendAttachmentToServer(weapon, slot, index)
|
||||
net.Start("mgbase_customize_att")
|
||||
net.WriteInt(slot, 32)
|
||||
net.WriteInt(index, 32)
|
||||
net.WriteEntity(weapon)
|
||||
net.SendToServer()
|
||||
end
|
||||
|
||||
local function saveFavs()
|
||||
file.CreateDir("mwbase")
|
||||
file.Write("mwbase/favorites.json", util.TableToJSON(MW_FAVORITES))
|
||||
end
|
||||
|
||||
function mw_utils.FavoriteAsset(swepClass, assetClass)
|
||||
MW_FAVORITES[swepClass] = MW_FAVORITES[swepClass] || {}
|
||||
|
||||
if (!table.HasValue(MW_FAVORITES[swepClass], assetClass)) then
|
||||
table.insert(MW_FAVORITES[swepClass], assetClass)
|
||||
saveFavs()
|
||||
end
|
||||
end
|
||||
|
||||
function mw_utils.UnfavoriteAsset(swepClass, assetClass)
|
||||
if (MW_FAVORITES[swepClass] == nil || !table.HasValue(MW_FAVORITES[swepClass], assetClass)) then
|
||||
return
|
||||
end
|
||||
|
||||
table.RemoveByValue(MW_FAVORITES[swepClass], assetClass)
|
||||
|
||||
if (#MW_FAVORITES[swepClass] <= 0) then
|
||||
MW_FAVORITES[swepClass] = nil
|
||||
end
|
||||
|
||||
saveFavs()
|
||||
end
|
||||
|
||||
function mw_utils.IsAssetFavorite(swepClass, assetClass)
|
||||
return MW_FAVORITES[swepClass] != nil && table.HasValue(MW_FAVORITES[swepClass], assetClass)
|
||||
end
|
||||
|
||||
function mw_utils.GetPresetsForSWEP(swepClass)
|
||||
local presets = {}
|
||||
|
||||
for _, preset in pairs(MW_PRESETS) do
|
||||
if (preset.SWEP == swepClass) then
|
||||
presets[#presets + 1] = table.Copy(preset)
|
||||
end
|
||||
end
|
||||
|
||||
return presets
|
||||
end
|
||||
|
||||
function mw_utils.SavePreset(swepClass, name, attachmentList)
|
||||
local fileName = uuid()
|
||||
local preset = {
|
||||
SWEP = swepClass,
|
||||
Name = name,
|
||||
Attachments = attachmentList
|
||||
}
|
||||
|
||||
file.CreateDir("mwbase/presets")
|
||||
file.Write("mwbase/presets/" .. fileName .. ".json", util.TableToJSON(preset, true))
|
||||
|
||||
preset.ClassName = fileName
|
||||
preset._bUserGenerated = true
|
||||
|
||||
MW_PRESETS[fileName] = table.Copy(preset)
|
||||
end
|
||||
|
||||
function mw_utils.RemovePreset(className)
|
||||
local pathAndName = "mwbase/presets/"..className..".json"
|
||||
|
||||
if (file.Exists(pathAndName, "DATA")) then
|
||||
file.Delete(pathAndName)
|
||||
MW_PRESETS[className] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function mw_utils.CompileFile(f)
|
||||
local content = file.Read(f, "LUA")
|
||||
|
||||
if (content != nil) then
|
||||
AddCSLuaFile(f)
|
||||
|
||||
if (string.find(content, "AddCSLuaFile")) then
|
||||
mw_utils.DevPrint("safeInclude: Don't run AddCSLuaFile! This is already done for you ("..f..")")
|
||||
end
|
||||
|
||||
local incl = CompileString(content, "MWBaseSafeInclude_"..f, false)--RunString(content, "MWBaseSafeInclude", false)
|
||||
|
||||
if (isstring(incl)) then
|
||||
mw_utils.ErrorPrint("safeInclude: "..f.." errored! Stack trace below")
|
||||
mw_utils.ErrorPrint("... "..incl)
|
||||
return false, incl
|
||||
end
|
||||
|
||||
incl()
|
||||
return true, "no error"
|
||||
end
|
||||
|
||||
mw_utils.ErrorPrint("safeInclude: missing file "..f.."!")
|
||||
return false, "missing file"
|
||||
end
|
||||
Reference in New Issue
Block a user