mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-17 21:53:46 +03:00
591 lines
17 KiB
Lua
591 lines
17 KiB
Lua
|
|
--[[
|
||
|
|
| This file was obtained through the combined efforts
|
||
|
|
| of Madbluntz & Plymouth Antiquarian Society.
|
||
|
|
|
|
||
|
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||
|
|
| Maloy, DrPepper10 @ RIP, Atle!
|
||
|
|
|
|
||
|
|
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||
|
|
--]]
|
||
|
|
|
||
|
|
local bones = {
|
||
|
|
["pelvis"] = "valvebiped.bip01_pelvis",
|
||
|
|
["spine"] = "valvebiped.bip01_spine",
|
||
|
|
["spine 2"] = "valvebiped.bip01_spine1",
|
||
|
|
["spine 3"] = "valvebiped.bip01_spine2",
|
||
|
|
["spine 4"] = "valvebiped.bip01_spine4",
|
||
|
|
["neck"] = "valvebiped.bip01_neck1",
|
||
|
|
["head"] = "valvebiped.bip01_head1",
|
||
|
|
["right clavicle"] = "valvebiped.bip01_r_clavicle",
|
||
|
|
["right upper arm"] = "valvebiped.bip01_r_upperarm",
|
||
|
|
["right upperarm"] = "valvebiped.bip01_r_upperarm",
|
||
|
|
["right forearm"] = "valvebiped.bip01_r_forearm",
|
||
|
|
["right hand"] = "valvebiped.bip01_r_hand",
|
||
|
|
["left clavicle"] = "valvebiped.bip01_l_clavicle",
|
||
|
|
["left upper arm"] = "valvebiped.bip01_l_upperarm",
|
||
|
|
["left upperarm"] = "valvebiped.bip01_l_upperarm",
|
||
|
|
["left forearm"] = "valvebiped.bip01_l_forearm",
|
||
|
|
["left hand"] = "valvebiped.bip01_l_hand",
|
||
|
|
["right thigh"] = "valvebiped.bip01_r_thigh",
|
||
|
|
["right calf"] = "valvebiped.bip01_r_calf",
|
||
|
|
["right foot"] = "valvebiped.bip01_r_foot",
|
||
|
|
["right toe"] = "valvebiped.bip01_r_toe0",
|
||
|
|
["left thigh"] = "valvebiped.bip01_l_thigh",
|
||
|
|
["left calf"] = "valvebiped.bip01_l_calf",
|
||
|
|
["left foot"] = "valvebiped.bip01_l_foot",
|
||
|
|
["left toe"] = "valvebiped.bip01_l_toe0",
|
||
|
|
}
|
||
|
|
|
||
|
|
local function translate_bone(bone)
|
||
|
|
if bones[bone] then return bones[bone] end
|
||
|
|
if not bone.lower then debug.Trace() return "" end
|
||
|
|
bone = bone:lower()
|
||
|
|
for key, val in pairs(bones) do
|
||
|
|
if bone == val then
|
||
|
|
return key
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
return bone
|
||
|
|
end
|
||
|
|
|
||
|
|
function pacx.ConvertPAC2Config(data, name)
|
||
|
|
local _out = {}
|
||
|
|
|
||
|
|
local base = pac.CreatePart("group")
|
||
|
|
base:SetName(name or "pac2 outfit")
|
||
|
|
|
||
|
|
for key, data in pairs(data.parts) do
|
||
|
|
if data.sprite.Enabled then
|
||
|
|
local part = pac.CreatePart("sprite")
|
||
|
|
part:SetParent(base)
|
||
|
|
part.pac2_part = data
|
||
|
|
part:SetName(data.name .. " sprite")
|
||
|
|
|
||
|
|
part:SetBone(translate_bone(data.bone))
|
||
|
|
|
||
|
|
part:SetColor(Vector(data.sprite.color.r, data.sprite.color.g, data.sprite.color.b))
|
||
|
|
part:SetAlpha(data.sprite.color.a / 255)
|
||
|
|
|
||
|
|
part:SetPosition(data.offset*1)
|
||
|
|
part:SetAngles(data.angles*1)
|
||
|
|
--part:SetAngleVelocity(Angle(data.anglevelocity.p, -data.anglevelocity.r, data.anglevelocity.y)*0.5)
|
||
|
|
|
||
|
|
part:SetMaterial(data.sprite.material)
|
||
|
|
part:SetSizeX(data.sprite.x)
|
||
|
|
part:SetSizeY(data.sprite.y)
|
||
|
|
part:SetEyeAngles(data.eyeangles)
|
||
|
|
if data.weaponclass and data.weaponclass ~= "" then
|
||
|
|
local part_ = pac.CreatePart("event")
|
||
|
|
part_:SetName(part.Name .. " weapon class")
|
||
|
|
part_:SetParent(part)
|
||
|
|
part_:SetEvent("weapon_class")
|
||
|
|
part_:SetOperator("find simple")
|
||
|
|
part_:SetInvert(true)
|
||
|
|
part_:SetArguments(data.weaponclass .. "@@" .. (data.hideweaponclass and "1" or "0"))
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
if data.light.Enabled then
|
||
|
|
local part = pac.CreatePart("light")
|
||
|
|
part:SetParent(base)
|
||
|
|
part.pac2_part = data
|
||
|
|
part:SetName(data.name .. " light")
|
||
|
|
|
||
|
|
part:SetBone(translate_bone(data.bone))
|
||
|
|
|
||
|
|
part:SetColor(Vector(data.light.r, data.light.g, data.light.b))
|
||
|
|
|
||
|
|
part:SetPosition(data.offset*1)
|
||
|
|
part:SetAngles(data.angles*1)
|
||
|
|
--part:SetAngleVelocity(Angle(data.anglevelocity.p, -data.anglevelocity.r, data.anglevelocity.y)*0.5)
|
||
|
|
|
||
|
|
part:SetBrightness(data.light.Brightness)
|
||
|
|
part:SetSize(data.light.Size)
|
||
|
|
|
||
|
|
if data.weaponclass and data.weaponclass ~= "" then
|
||
|
|
local part_ = pac.CreatePart("event")
|
||
|
|
part_:SetName(part.Name .. " weapon class")
|
||
|
|
part_:SetParent(part)
|
||
|
|
part_:SetEvent("weapon_class")
|
||
|
|
part_:SetOperator("find simple")
|
||
|
|
part_:SetInvert(true)
|
||
|
|
part_:SetArguments(data.weaponclass .. "@@" .. (data.hideweaponclass and "1" or "0"))
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
if data.text.Enabled then
|
||
|
|
local part = pac.CreatePart("text")
|
||
|
|
part:SetParent(base)
|
||
|
|
part.pac2_part = data
|
||
|
|
part:SetName(data.name .. " text")
|
||
|
|
|
||
|
|
part:SetBone(translate_bone(data.bone))
|
||
|
|
|
||
|
|
part:SetColor(Vector(data.text.color.r, data.text.color.g, data.text.color.b))
|
||
|
|
part:SetAlpha(data.text.color.a / 255)
|
||
|
|
|
||
|
|
part:SetColor(Vector(data.text.outlinecolor.r, data.text.outlinecolor.g, data.text.outlinecolor.b))
|
||
|
|
part:SetAlpha(data.text.outlinecolor.a / 255)
|
||
|
|
|
||
|
|
part:SetPosition(data.offset*1)
|
||
|
|
part:SetAngles(data.angles*1)
|
||
|
|
--part:SetAngleVelocity(Angle(data.anglevelocity.p, -data.anglevelocity.r, data.anglevelocity.y)*0.5)
|
||
|
|
|
||
|
|
part:SetOutline(data.text.outline)
|
||
|
|
part:SetText(data.text.text)
|
||
|
|
part:SetFont(data.text.font)
|
||
|
|
part:SetSize(data.text.size)
|
||
|
|
part:SetEyeAngles(data.eyeangles)
|
||
|
|
if data.weaponclass and data.weaponclass ~= "" then
|
||
|
|
local part_ = pac.CreatePart("event")
|
||
|
|
part_:SetName(part.Name .. " weapon class")
|
||
|
|
part_:SetParent(part)
|
||
|
|
part_:SetEvent("weapon_class")
|
||
|
|
part_:SetOperator("find simple")
|
||
|
|
part_:SetInvert(true)
|
||
|
|
part_:SetArguments(data.weaponclass .. "@@" .. (data.hideweaponclass and "1" or "0"))
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
if data.trail.Enabled then
|
||
|
|
local part = pac.CreatePart("trail")
|
||
|
|
part:SetParent(base)
|
||
|
|
part.pac2_part = data
|
||
|
|
part:SetName(data.name .. " trail")
|
||
|
|
part:SetBone(translate_bone(data.bone))
|
||
|
|
|
||
|
|
part:SetPosition(data.offset*1)
|
||
|
|
part:SetAngles(data.angles*1)
|
||
|
|
--part:SetAngleVelocity(Angle(data.anglevelocity.p, -data.anglevelocity.r, data.anglevelocity.y)*0.5)
|
||
|
|
|
||
|
|
part:SetStartSize(data.trail.startsize)
|
||
|
|
|
||
|
|
part:SetStartColor(Vector(data.trail.color.r, data.trail.color.g, data.trail.color.b))
|
||
|
|
part:SetEndColor(Vector(data.trail.color.r, data.trail.color.g, data.trail.color.b))
|
||
|
|
|
||
|
|
part:SetStartAlpha(data.trail.color.a/255)
|
||
|
|
part:SetEndAlpha(data.trail.color.a/255)
|
||
|
|
|
||
|
|
part:SetSpacing(0)
|
||
|
|
|
||
|
|
part:SetMaterial(data.trail.material)
|
||
|
|
part:SetLength(data.trail.length)
|
||
|
|
if data.weaponclass and data.weaponclass ~= "" then
|
||
|
|
local part_ = pac.CreatePart("event")
|
||
|
|
part_:SetName(part.Name .. " weapon class")
|
||
|
|
part_:SetParent(part)
|
||
|
|
part_:SetEvent("weapon_class")
|
||
|
|
part_:SetOperator("find simple")
|
||
|
|
part_:SetInvert(true)
|
||
|
|
part_:SetArguments(data.weaponclass .. "@@" .. (data.hideweaponclass and "1" or "0"))
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
if true or data.color.a ~= 0 and data.size ~= 0 and data.scale ~= vector_origin or data.effect.Enabled then
|
||
|
|
local part = pac.CreatePart("model")
|
||
|
|
part:SetParent(base)
|
||
|
|
part.pac2_part = data
|
||
|
|
part:SetName(data.name .. " model")
|
||
|
|
part:SetBone(translate_bone(data.bone))
|
||
|
|
|
||
|
|
part:SetMaterial(data.material)
|
||
|
|
|
||
|
|
part:SetColor(Vector(data.color.r, data.color.g, data.color.b))
|
||
|
|
part:SetAlpha(data.color.a / 255)
|
||
|
|
|
||
|
|
part:SetModel(data.model)
|
||
|
|
part:SetSize(data.size)
|
||
|
|
part:SetScale(data.scale*1)
|
||
|
|
|
||
|
|
part:SetPosition(data.offset*1)
|
||
|
|
part:SetAngles(data.angles*1)
|
||
|
|
--part:SetAngleVelocity(Angle(data.anglevelocity.p, -data.anglevelocity.r, data.anglevelocity.y)*0.5)
|
||
|
|
|
||
|
|
part:SetInvert(data.mirrored)
|
||
|
|
part:SetFullbright(data.fullbright)
|
||
|
|
part:SetEyeAngles(data.eyeangles)
|
||
|
|
|
||
|
|
if data.effect.Enabled then
|
||
|
|
local part2 = pac.CreatePart("effect")
|
||
|
|
part2:SetName(data.name .. " effect")
|
||
|
|
part2:SetParent(part)
|
||
|
|
part2:SetBone(translate_bone(data.bone))
|
||
|
|
|
||
|
|
part2:SetLoop(data.effect.loop)
|
||
|
|
part2:SetRate(data.effect.rate)
|
||
|
|
part2:SetEffect(data.effect.effect)
|
||
|
|
if data.weaponclass and data.weaponclass ~= "" then
|
||
|
|
local part_ = pac.CreatePart("event")
|
||
|
|
part_:SetName(part2.Name .. " weapon class")
|
||
|
|
part_:SetParent(part2)
|
||
|
|
part_:SetEvent("weapon_class")
|
||
|
|
part_:SetOperator("find simple")
|
||
|
|
part_:SetInvert(true)
|
||
|
|
part_:SetArguments(data.weaponclass .. "@@" .. (data.hideweaponclass and "1" or "0"))
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
if data.clip.Enabled then
|
||
|
|
local part2 = part:CreatePart("clip")
|
||
|
|
part2:SetName(data.name .. " clip")
|
||
|
|
if data.clip.bone and data.clip.bone ~= "" then
|
||
|
|
part2:SetBone(data.clip.bone)
|
||
|
|
end
|
||
|
|
part2:SetParent(part)
|
||
|
|
part2:SetPosition(data.clip.angles:Forward() * data.clip.distance)
|
||
|
|
part2:SetAngles(data.clip.angles*-1)
|
||
|
|
end
|
||
|
|
|
||
|
|
if data.animation.Enabled then
|
||
|
|
local part2 = part:CreatePart("animation")
|
||
|
|
part2:SetParent(part)
|
||
|
|
part2:SetName(data.name .. " animation")
|
||
|
|
part2:SetSequenceName(data.animation.sequence or "")
|
||
|
|
part2:SetRate(data.animation.rate)
|
||
|
|
part2:SetMin(data.animation.min)
|
||
|
|
part2:SetMax(data.animation.max)
|
||
|
|
part2:SetOffset(data.animation.offset)
|
||
|
|
part2:SetPingPongLoop(data.animation.loopmode)
|
||
|
|
part:AddChild(part2)
|
||
|
|
end
|
||
|
|
|
||
|
|
if data.modelbones.Enabled then
|
||
|
|
part:SetBoneMerge(data.modelbones.merge)
|
||
|
|
part.pac2_modelbone = data.modelbones.redirectparent
|
||
|
|
|
||
|
|
for key, bone in pairs(data.modelbones.bones) do
|
||
|
|
bone.size = tonumber(bone.size)
|
||
|
|
if
|
||
|
|
bone.scale == Vector(1,1,1) and
|
||
|
|
bone.angles == Vector(0,0,0) and
|
||
|
|
bone.offset == Vector(0,0,0) and
|
||
|
|
bone.size == 1
|
||
|
|
then goto CONTINUE end
|
||
|
|
|
||
|
|
local part2 = pac.CreatePart("bone")
|
||
|
|
part2:SetName("model bone " .. part:GetName() .. " " .. key)
|
||
|
|
part2:SetParent(part)
|
||
|
|
part2:SetBone(part:GetOwner():GetBoneName(key))
|
||
|
|
|
||
|
|
part2:SetScale(bone.scale*1)
|
||
|
|
part2:SetAngles(bone.angles*1)
|
||
|
|
part2:SetPosition(bone.offset*1)
|
||
|
|
|
||
|
|
part2:SetSize(bone.size)
|
||
|
|
::CONTINUE::
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
if data.weaponclass and data.weaponclass ~= "" then
|
||
|
|
local part_ = pac.CreatePart("event")
|
||
|
|
part_:SetName(part.Name .. " weapon class")
|
||
|
|
part_:SetParent(part)
|
||
|
|
part_:SetEvent("weapon_class")
|
||
|
|
part_:SetOperator("find simple")
|
||
|
|
part_:SetInvert(true)
|
||
|
|
part_:SetArguments(data.weaponclass .. "@@" .. (data.hideweaponclass and "1" or "0"))
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
local part = pac.CreatePart("entity")
|
||
|
|
part:SetParent(base)
|
||
|
|
part:SetName("player")
|
||
|
|
|
||
|
|
part:SetColor(Vector(data.player_color.r, data.player_color.g, data.player_color.b))
|
||
|
|
part:SetAlpha(data.player_color.a/255)
|
||
|
|
part:SetMaterial(data.player_material)
|
||
|
|
part:SetScale(data.overall_scale*1)
|
||
|
|
part:SetDrawWeapon(data.drawwep)
|
||
|
|
|
||
|
|
for bone, data in pairs(data.bones) do
|
||
|
|
local part_ = pac.CreatePart("bone")
|
||
|
|
part_:SetParent(part)
|
||
|
|
part_:SetName(bone .. " bone")
|
||
|
|
part_:SetBone(translate_bone(bone))
|
||
|
|
part_:SetSize(tonumber(data.size))
|
||
|
|
part_:SetScale(data.scale*1)
|
||
|
|
part_:SetPosition(data.offset*1)
|
||
|
|
part_:SetAngles(data.angles*1)
|
||
|
|
end
|
||
|
|
|
||
|
|
for key, part in pairs(pac.GetLocalParts()) do
|
||
|
|
if part.pac2_part and part.pac2_part.parent and part.pac2_part.parent ~= "none" then
|
||
|
|
for key, parent in pairs(pac.GetLocalParts()) do
|
||
|
|
if parent:GetName() == (part.pac2_part.parent .. " model") then
|
||
|
|
part:SetParent(parent)
|
||
|
|
if parent.pac2_modelbone then
|
||
|
|
part:SetBone(translate_bone(parent.pac2_modelbone))
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
-- hacks
|
||
|
|
|
||
|
|
for key, part in pairs(pac.GetLocalParts()) do
|
||
|
|
part:SetParent(part:GetParent())
|
||
|
|
end
|
||
|
|
|
||
|
|
return base
|
||
|
|
end
|
||
|
|
|
||
|
|
local glon = {}
|
||
|
|
|
||
|
|
do
|
||
|
|
local function Read(reader, rtabs)
|
||
|
|
local t, pos = reader:Peek()
|
||
|
|
if not t then
|
||
|
|
error(string.format("Expected type ID at %s! (Got EOF)",
|
||
|
|
pos))
|
||
|
|
else
|
||
|
|
local dt = decode_types[string.byte(t)]
|
||
|
|
if not dt then
|
||
|
|
error(string.format("Unknown type ID, %s!",
|
||
|
|
string.byte(t)))
|
||
|
|
else
|
||
|
|
return dt(reader, rtabs or {0})
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
local decode_types
|
||
|
|
decode_types = {
|
||
|
|
-- \2\6omg\1\6omgavalue\1\1
|
||
|
|
[2 ] = function(reader, rtabs) -- table
|
||
|
|
local t, c, pos = {}, reader:Next()
|
||
|
|
rtabs[#rtabs+1] = t
|
||
|
|
local stage = false
|
||
|
|
local key
|
||
|
|
while true do
|
||
|
|
c, pos = reader:Peek()
|
||
|
|
if c == "\1" then
|
||
|
|
if stage then
|
||
|
|
error(string.format("Expected value to match key at %s! (Got EO Table)",
|
||
|
|
pos))
|
||
|
|
else
|
||
|
|
reader:Next()
|
||
|
|
return t
|
||
|
|
end
|
||
|
|
else
|
||
|
|
if stage then
|
||
|
|
t[key] = Read(reader, rtabs)
|
||
|
|
else
|
||
|
|
key = Read(reader, rtabs)
|
||
|
|
end
|
||
|
|
stage = not stage
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end,
|
||
|
|
[3 ] = function(reader, rtabs) -- array
|
||
|
|
local t, i, c, pos = {}, 1, reader:Next()
|
||
|
|
rtabs[#rtabs+1] = t
|
||
|
|
while true do
|
||
|
|
c, pos = reader:Peek()
|
||
|
|
if c == "\1" then
|
||
|
|
reader:Next()
|
||
|
|
return t
|
||
|
|
else
|
||
|
|
t[i] = Read(reader, rtabs)
|
||
|
|
i = i+1
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end,
|
||
|
|
[4 ] = function(reader) -- false boolean
|
||
|
|
reader:Next()
|
||
|
|
return false
|
||
|
|
end,
|
||
|
|
[5 ] = function(reader) -- true boolean
|
||
|
|
reader:Next()
|
||
|
|
return true
|
||
|
|
end,
|
||
|
|
[6 ] = function(reader) -- number
|
||
|
|
local s, c, pos, e = "", reader:Next()
|
||
|
|
while true do
|
||
|
|
c = reader:Next()
|
||
|
|
if not c then
|
||
|
|
error(string.format("Expected \1 to end number at %s! (Got EOF!)",
|
||
|
|
pos))
|
||
|
|
elseif c == "\1" then
|
||
|
|
break
|
||
|
|
else
|
||
|
|
s = s..c
|
||
|
|
end
|
||
|
|
end
|
||
|
|
if s == "" then s = "0" end
|
||
|
|
local n = tonumber(s)
|
||
|
|
if not n then
|
||
|
|
error(string.format("Invalid number at %s! (%q)",
|
||
|
|
pos, s))
|
||
|
|
end
|
||
|
|
return n
|
||
|
|
end,
|
||
|
|
[7 ] = function(reader) -- string
|
||
|
|
local s, c, pos, e = "", reader:Next()
|
||
|
|
while true do
|
||
|
|
c = reader:Next()
|
||
|
|
if not c then
|
||
|
|
error(string.format("Expected unescaped \1 to end string at position %s! (Got EOF)",
|
||
|
|
pos))
|
||
|
|
elseif e then
|
||
|
|
if c == "\3" then
|
||
|
|
s = s.."\0"
|
||
|
|
else
|
||
|
|
s = s..c
|
||
|
|
end
|
||
|
|
e = false
|
||
|
|
elseif c == "\2" then
|
||
|
|
e = true
|
||
|
|
elseif c == "\1" then
|
||
|
|
s = string.gsub(s, "\4", "\"") -- unescape quotes
|
||
|
|
return s
|
||
|
|
else
|
||
|
|
s = s..c
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end,
|
||
|
|
[8 ] = function(reader) -- Vector
|
||
|
|
local x = decode_types[6](reader)
|
||
|
|
reader:StepBack()
|
||
|
|
local y = decode_types[6](reader)
|
||
|
|
reader:StepBack()
|
||
|
|
local z = decode_types[6](reader)
|
||
|
|
return Vector(x, y, z)
|
||
|
|
end,
|
||
|
|
[9 ] = function(reader) -- Angle
|
||
|
|
local p = decode_types[6](reader)
|
||
|
|
reader:StepBack()
|
||
|
|
local y = decode_types[6](reader)
|
||
|
|
reader:StepBack()
|
||
|
|
local r = decode_types[6](reader)
|
||
|
|
return Angle(p, y, r)
|
||
|
|
end,
|
||
|
|
[13 ] = function(reader) -- ConVar
|
||
|
|
return GetConVar(decode_types[7](reader))
|
||
|
|
end,
|
||
|
|
[15 ] = function(reader) -- Color
|
||
|
|
local r = decode_types[6](reader)
|
||
|
|
reader:StepBack()
|
||
|
|
local g = decode_types[6](reader)
|
||
|
|
reader:StepBack()
|
||
|
|
local b = decode_types[6](reader)
|
||
|
|
reader:StepBack()
|
||
|
|
local a = decode_types[6](reader)
|
||
|
|
return Color(r, g, b, a)
|
||
|
|
end,
|
||
|
|
[253] = function(reader) -- -math.huge
|
||
|
|
reader:Next()
|
||
|
|
return -math.huge
|
||
|
|
end,
|
||
|
|
[254] = function(reader) -- math.huge
|
||
|
|
reader:Next()
|
||
|
|
return math.huge
|
||
|
|
end,
|
||
|
|
[255] = function(reader, rtabs) -- Reference
|
||
|
|
return rtabs[decode_types[6](reader) - 1]
|
||
|
|
end,
|
||
|
|
}
|
||
|
|
local reader_meta = {}
|
||
|
|
reader_meta.__index = reader_meta
|
||
|
|
function reader_meta:Next()
|
||
|
|
self.i = self.i+1
|
||
|
|
self.c = string.sub(self.s, self.i, self.i)
|
||
|
|
if self.c == "" then self.c = nil end
|
||
|
|
self.p = string.sub(self.s, self.i+1, self.i+1)
|
||
|
|
if self.p == "" then self.p = nil end
|
||
|
|
return self.c, self.i
|
||
|
|
end
|
||
|
|
function reader_meta:StepBack()
|
||
|
|
self.i = self.i-1
|
||
|
|
self.c = string.sub(self.s, self.i, self.i)
|
||
|
|
if self.c == "" then self.c = nil end
|
||
|
|
self.p = string.sub(self.s, self.i+1, self.i+1)
|
||
|
|
if self.p == "" then self.p = nil end
|
||
|
|
return self.c, self.i
|
||
|
|
end
|
||
|
|
function reader_meta:Peek()
|
||
|
|
return self.p, self.i+1
|
||
|
|
end
|
||
|
|
function glon.decode(data)
|
||
|
|
if data == nil then
|
||
|
|
return nil
|
||
|
|
elseif not isstring(data) then
|
||
|
|
error(string.format("Expected string to decode! (Got type %s)",
|
||
|
|
type(data)
|
||
|
|
))
|
||
|
|
elseif data:len() == 0 then
|
||
|
|
return nil
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
return Read(setmetatable({
|
||
|
|
s = data,
|
||
|
|
i = 0,
|
||
|
|
c = string.sub(data, 0, 0),
|
||
|
|
p = string.sub(data, 1, 1),
|
||
|
|
}, reader_meta), {})
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
concommand.Add("pac_convert_pac2_outfits", function()
|
||
|
|
if not file.IsDir("pac2_outfits", "DATA") then
|
||
|
|
pac.Message("garrysmod/data/pac2_outfits/ does not exist")
|
||
|
|
return
|
||
|
|
end
|
||
|
|
|
||
|
|
local folders = select(2, file.Find("pac2_outfits/*", "DATA"))
|
||
|
|
|
||
|
|
if #folders == 0 then
|
||
|
|
pac.Message("garrysmod/data/pac2_outfits/ is empty")
|
||
|
|
return
|
||
|
|
end
|
||
|
|
|
||
|
|
for _, uniqueid in ipairs(folders) do
|
||
|
|
local owner_nick = file.Read("pac2_outfits/" .. uniqueid .. "/__owner.txt", "DATA")
|
||
|
|
|
||
|
|
if not owner_nick then
|
||
|
|
owner_nick = pac.LocalPlayer:Nick()
|
||
|
|
pac.Message("garrysmod/data/pac2_outfits/" .. uniqueid .. "/__owner.txt does not exist (it contains the player nickname) defaulting to " .. owner_nick)
|
||
|
|
end
|
||
|
|
|
||
|
|
local folders = select(2, file.Find("pac2_outfits/" .. uniqueid .. "/*", "DATA"))
|
||
|
|
|
||
|
|
if #folders == 0 then
|
||
|
|
pac.Message("garrysmod/data/pac2_outfits/" .. uniqueid .. "/ is empty")
|
||
|
|
return
|
||
|
|
end
|
||
|
|
|
||
|
|
for _, folder_name in ipairs(folders) do
|
||
|
|
local name = file.Read("pac2_outfits/" .. uniqueid .. "/" .. folder_name .. "/name.txt", "DATA")
|
||
|
|
local data = file.Read("pac2_outfits/" .. uniqueid .. "/" .. folder_name .. "/outfit.txt", "DATA")
|
||
|
|
|
||
|
|
if not name then
|
||
|
|
pac.Message("garrysmod/data/pac2_outfits/" .. uniqueid .. "/" .. folder_name .. "/name.txt does not exist. defaulting to: " .. folder_name)
|
||
|
|
end
|
||
|
|
|
||
|
|
if data then
|
||
|
|
pace.ClearParts()
|
||
|
|
|
||
|
|
local ok, res = pcall(function() pacx.ConvertPAC2Config(glon.decode(data), name) end)
|
||
|
|
if ok then
|
||
|
|
file.CreateDir("pac3/pac2_outfits/")
|
||
|
|
file.CreateDir("pac3/pac2_outfits/" .. uniqueid .. "/")
|
||
|
|
|
||
|
|
pace.SaveParts("pac2_outfits/" .. uniqueid .. "/" .. folder_name)
|
||
|
|
else
|
||
|
|
pac.Message("garrysmod/data/pac2_outfits/" .. uniqueid .. "/" .. folder_name .. "(" .. name .. ") failed to convert : " .. res)
|
||
|
|
end
|
||
|
|
else
|
||
|
|
pac.Message("garrysmod/data/pac2_outfits/" .. uniqueid .. "/" .. folder_name .. "/data.txt does not exist. this file contains the outfit data")
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
pace.ClearParts()
|
||
|
|
|
||
|
|
pac.Message("pac2 outfits are stored under pac > load > pac2_outfits in the editor")
|
||
|
|
pac.Message("you may need to restart the editor to see them")
|
||
|
|
end)
|