Files
wnsrc/lua/pac3/core/client/parts/script.lua
lifestorm 94063e4369 Upload
2024-08-04 22:55:00 +03:00

421 lines
7.4 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 BUILDER, PART = pac.PartTemplate("base")
PART.ClassName = "script"
PART.ThinkTime = 0
PART.Group = 'advanced'
PART.Icon = 'icon16/page_white_gear.png'
BUILDER:StartStorableVars()
BUILDER:GetSet("Code", "")
BUILDER:EndStorableVars()
local blacklist = {
"do",
"end",
"function",
"repeat",
"while",
}
local lib =
{
math = {
pi = math.pi,
random = math.random,
abs = math.abs,
acos = math.acos,
asin = math.asin,
atan = math.atan,
atan2 = math.atan2,
ceil = math.ceil,
cos = math.cos,
cosh = math.cosh,
deg = math.deg,
exp = math.exp,
floor = math.floor,
frexp = math.frexp,
ldexp = math.ldexp,
log = math.log,
log10 = math.log10,
max = math.max,
min = math.min,
rad = math.rad,
sin = math.sin,
sinh = math.sinh,
sqrt = math.sqrt,
tanh = math.tanh,
tan = math.tan,
clamp = math.Clamp,
randomx = math.Rand,
},
string = {
find = string.find,
}
}
local function translate_xyz(x, y, z, T, def)
if T == "Vector" then
def.x = x or def.x
def.y = y or def.y
def.z = z or def.z
return def
elseif T == "Angle" then
def.p = x or def.p
def.y = y or def.y
def.r = z or def.r
return def
elseif T == "number" then
return tonumber(x) or def -- inf protection here
elseif T == "string" then
return tostring(x)
end
end
local function translate_value(val, T)
if T == "Vector" then
return val.x, val.y, val.z
elseif T == "Angle" then
return val.p, val.y, val.r
elseif T == "number" or T == "string" then
return val
end
end
local function CreateDummies(parts)
local obj = {
SetProperty = function(_, key, x, y, z)
if not key then return end
for _, v in pairs(parts) do
if v:IsValid() and v.StorableVars[key] then
local def = v[key]
local val = translate_xyz(x ,y, z, type(def), def)
v["Set" .. key](v, val)
end
end
end,
EventHide = function(_, b)
for _, v in pairs(parts) do
if v:IsValid() then
v:SetEventTrigger(self, not not b)
end
end
end,
EventShow = function(_, b)
for _, v in pairs(parts) do
if v:IsValid() then
v:SetEventTrigger(self, not b)
end
end
end
}
return obj
end
local function CreateDummy(part, store, self)
if not part or not part:IsValid() then return end
if part.dummy_part then return part.dummy_part end
store.parts[part.UniqueID] = {}
local META =
{
SetProperty = function(_, key, x, y, z)
if key and part.StorableVars[key] then
local def = part[key]
local val = translate_xyz(x ,y, z, type(def), def)
part["Set" .. key](part, val)
end
end,
GetProperty = function(_, key)
if key and part.StorableVars[key] then
local val = part["Get" .. key](part)
if val then
local x, y, z = translate_value(val, type(val))
if x then
return x, y, z
end
end
end
end,
EventHide = function(_, b)
part:SetEventTrigger(self, not not b)
end,
EventShow = function(_, b)
part:SetEventTrigger(self, not b)
end,
GetChildren = function()
return CreateDummies(part:GetChildren(), self)
end,
}
local obj = setmetatable(
{},
{
__index = function(_, key)
if not part:IsValid() then return end
if store.parts[part.UniqueID][key] then
return store.parts[part.UniqueID][key]
end
return META[key]
end,
__newindex = function(_, key, val)
if not part:IsValid() then return end
store.parts[part.UniqueID][key] = val
end,
}
)
part.dummy_part = obj
return obj
end
local function get_entity(part)
local ent = part:GetRootPart():GetOwner()
return ent == pac.LocalPlayer:GetViewModel() and pac.LocalPlayer or ent
end
function PART:CompileCode()
local code = self.Code
for _, word in pairs(blacklist) do
if code:find("[%p%s]" .. word) or code:find(word .. "[%p%s]") then
return false, string.format("illegal characters used %q", word)
end
end
local func = CompileString(code, "SCRIPT_ENV", false)
if isstring(func) then
return false, func
end
local store = {globals = {}, parts = {}}
local extra_lib =
{
print = function(...)
if self:GetPlayerOwner() == pac.LocalPlayer then
print(...)
local str = ""
local count = select("#", ...)
for i = 1, count do
str = str .. tostring(select(i, ...))
if i ~= count then
str = str .. ", "
end
end
self.script_printing = str
end
end,
owner = {
GetFOV = function()
local ent = get_entity(self)
if ent:IsValid() then
return ent:GetFOV()
end
end,
GetHealth = function()
local ent = get_entity(self)
if ent:IsValid() then
return ent:Health()
end
end,
},
parts = {
GetParent = function(level)
level = level or 1
local parent = self
for _ = 1, math.Clamp(level, 1, 30) do
parent = parent:GetParent()
end
return CreateDummy(parent, store, self)
end,
FindMultiple = function(str)
local parts = {}
for _, part in pairs(pac.GetParts()) do
if
part:GetPlayerOwner() == self:GetPlayerOwner() and
pac.StringFind(part:GetName(), str)
then
table.insert(parts, part)
end
end
return CreateDummies(parts, self)
end,
FindMultipleWithProperty = function()
local parts = {}
for key, part in pairs(pac.GetParts()) do
if
part:GetPlayerOwner() == self:GetPlayerOwner() and
part.StorableVars[key] and
part["Get" .. key] and part["Get" .. key]()
then
table.insert(parts, part)
end
end
return CreateDummies(parts, self)
end,
Find = function(str)
for _, part in pairs(pac.GetParts()) do
if
part:GetPlayerOwner() == self:GetPlayerOwner() and
(part.UniqueID == str or part:GetName() == str)
then
return CreateDummy(part, store, self)
end
end
end,
}
}
local env = {}
env.__index = function(_, key)
if key == "this" or key == "self" then
return CreateDummy(self, store, self)
end
if key == "T" or key == "TIME" then
return RealTime()
end
if key == "CT" or key == "CURTIME" then
return CurTime()
end
if lib[key] then
return lib[key]
end
if extra_lib[key] then
return extra_lib[key]
end
if store[key] then
return store[key]
end
end
env.__newindex = function(_, key, val)
store[key] = val
end
self.valid_functions = {
SetProperty = "m",
GetProperty = "m",
GetChildren = "m",
EventHide = "m",
EventShow = "m",
self = "e",
this = "e",
T = "e",
TIME = "e",
CT = "e",
CURTIME = "e"
}
local function scan(tbl)
for key, val in pairs(tbl) do
self.valid_functions[key] = val
if istable(val) then
scan(val)
end
end
end
scan(lib)
scan(extra_lib)
setfenv(func, setmetatable({}, env))
return true, func
end
function PART:ShouldHighlight(str)
return self.valid_functions and self.valid_functions[str]
end
function PART:SetCode(code)
self.Code = code
local ok, func = self:CompileCode()
if ok then
self.func = func
self:SetError()
else
self:SetError(func)
self.func = nil
end
end
function PART:OnThink()
if self.func then
local ok, err = pcall(self.func)
if not ok then
self:SetError(err)
self.func = nil
else
self:SetError()
end
end
end
concommand.Add("pac_register_script_part", function()
BUILDER:Register()
end)