mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-16 21:33:46 +03:00
276 lines
7.9 KiB
Lua
276 lines
7.9 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/
|
||
|
|
--]]
|
||
|
|
|
||
|
|
if (SERVER) then
|
||
|
|
function SaveLadders()
|
||
|
|
file.CreateDir("ladders");
|
||
|
|
file.CreateDir("ladders/ladders");
|
||
|
|
file.CreateDir("ladders/dismounts");
|
||
|
|
local ladders = ents.FindByClass("func_useableladder");
|
||
|
|
local buffer = {};
|
||
|
|
|
||
|
|
for _, v in pairs(ladders) do
|
||
|
|
if (v:GetName():lower():find("zladder") and v:GetNWBool("saved", false)) then
|
||
|
|
local index = #buffer + 1;
|
||
|
|
|
||
|
|
buffer[index] = {
|
||
|
|
origin = v:GetPos(),
|
||
|
|
angles = v:GetAngles(),
|
||
|
|
point0 = v:GetSaveTable().point0,
|
||
|
|
point1 = v:GetSaveTable().point1,
|
||
|
|
propTable = v.propTable,
|
||
|
|
model = v.model,
|
||
|
|
normal = v.normal
|
||
|
|
};
|
||
|
|
end;
|
||
|
|
end;
|
||
|
|
|
||
|
|
if (buffer and table.Count(buffer) > 0) then
|
||
|
|
local JSONData = util.TableToJSON(buffer);
|
||
|
|
|
||
|
|
file.Write("ladders/ladders/" .. game.GetMap() .. ".txt", JSONData);
|
||
|
|
else
|
||
|
|
file.Delete("ladders/ladders/" .. game.GetMap() .. ".txt");
|
||
|
|
end;
|
||
|
|
end;
|
||
|
|
|
||
|
|
function SaveDismounts()
|
||
|
|
file.CreateDir("ladders");
|
||
|
|
file.CreateDir("ladders/ladders");
|
||
|
|
file.CreateDir("ladders/dismounts");
|
||
|
|
local buffer = {};
|
||
|
|
|
||
|
|
for k, v in pairs(ents.FindByClass("func_useableladder")) do
|
||
|
|
if (v:GetNWBool("saved", false) and v:GetName():lower():find("zladder")) then
|
||
|
|
for _, dismount in pairs(ents.FindInSphere(v:GetPos() + v:GetSaveTable().point0, 200)) do
|
||
|
|
if (IsValid(dismount) and dismount:GetClass() == "info_ladder_dismount" and dismount:GetName():lower():find("zdismount") and !dismount.saved) then
|
||
|
|
buffer[#buffer + 1] = dismount:GetPos();
|
||
|
|
dismount.saved = true;
|
||
|
|
end;
|
||
|
|
end;
|
||
|
|
|
||
|
|
for _, dismount in pairs(ents.FindInSphere(v:GetPos() + v:GetSaveTable().point1, 200)) do
|
||
|
|
if (IsValid(dismount) and dismount:GetClass() == "info_ladder_dismount" and dismount:GetName():lower():find("zdismount") and !dismount.saved) then
|
||
|
|
buffer[#buffer + 1] = dismount:GetPos();
|
||
|
|
dismount.saved = true;
|
||
|
|
end;
|
||
|
|
end;
|
||
|
|
end;
|
||
|
|
end;
|
||
|
|
|
||
|
|
for k, v in pairs(ents.FindByClass("info_ladder_dismount")) do
|
||
|
|
v.saved = nil;
|
||
|
|
end;
|
||
|
|
|
||
|
|
if (buffer and table.Count(buffer) > 0) then
|
||
|
|
local JSONData = util.TableToJSON(buffer);
|
||
|
|
|
||
|
|
file.Write("ladders/dismounts/" .. game.GetMap() .. ".txt", JSONData);
|
||
|
|
else
|
||
|
|
file.Delete("ladders/dismounts/" .. game.GetMap() .. ".txt");
|
||
|
|
end;
|
||
|
|
end;
|
||
|
|
|
||
|
|
function LoadLadders()
|
||
|
|
if (!file.Exists("ladders/ladders/" .. game.GetMap() .. ".txt", "DATA")) then return; end;
|
||
|
|
|
||
|
|
local buffer = file.Read("ladders/ladders/" .. game.GetMap() .. ".txt", false);
|
||
|
|
|
||
|
|
if (buffer:len() > 1) then
|
||
|
|
buffer = util.JSONToTable(buffer);
|
||
|
|
|
||
|
|
if (!buffer) then return; end;
|
||
|
|
|
||
|
|
for _, data in pairs(buffer) do
|
||
|
|
if (!data.propTable) then continue; end;
|
||
|
|
|
||
|
|
local ladder = ents.Create("func_useableladder");
|
||
|
|
ladder:SetPos(data.origin);
|
||
|
|
ladder:SetAngles(data.angles);
|
||
|
|
ladder:SetKeyValue("point0", tostring(data.origin + data.point0));
|
||
|
|
ladder:SetKeyValue("point1", tostring(data.origin + data.point1));
|
||
|
|
ladder:SetKeyValue("targetname", "zladder_" .. ladder:EntIndex());
|
||
|
|
ladder:Spawn();
|
||
|
|
ladder:SetNWBool("saved", true);
|
||
|
|
ladder.model = data.model;
|
||
|
|
ladder.props = {};
|
||
|
|
ladder.propTable = {};
|
||
|
|
|
||
|
|
for _, info in pairs(data.propTable) do
|
||
|
|
local ladderProp = ents.Create("prop_physics");
|
||
|
|
ladderProp:SetPos(info.origin);
|
||
|
|
ladderProp:SetAngles(info.angles);
|
||
|
|
ladderProp:SetModel(data.model);
|
||
|
|
ladderProp:Spawn();
|
||
|
|
ladderProp:DeleteOnRemove(ladder);
|
||
|
|
ladderProp:GetPhysicsObject():EnableMotion(false);
|
||
|
|
ladderProp:PhysicsDestroy();
|
||
|
|
ladderProp.ladder = ladder;
|
||
|
|
ladderProp:SetNWEntity("ladder", ladder);
|
||
|
|
ladderProp:DrawShadow(false);
|
||
|
|
ladderProp:SetCollisionGroup(COLLISION_GROUP_WORLD);
|
||
|
|
|
||
|
|
table.insert(ladder.propTable, {
|
||
|
|
origin = info.origin,
|
||
|
|
angles = info.angles
|
||
|
|
});
|
||
|
|
|
||
|
|
table.insert(ladder.props, ladderProp);
|
||
|
|
end;
|
||
|
|
|
||
|
|
ladder:CallOnRemove("cleanup", function(ladder)
|
||
|
|
if (!ladder.props) then return; end;
|
||
|
|
|
||
|
|
for k, v in pairs(ladder.props) do
|
||
|
|
SafeRemoveEntity(v);
|
||
|
|
end;
|
||
|
|
end);
|
||
|
|
|
||
|
|
if (!ladder.model or !ladder.propTable or !ladder.props) then
|
||
|
|
SafeRemoveEntity(ladder);
|
||
|
|
end;
|
||
|
|
end;
|
||
|
|
end;
|
||
|
|
end;
|
||
|
|
|
||
|
|
function LoadDismounts()
|
||
|
|
if (!file.Exists("ladders/dismounts/" .. game.GetMap() .. ".txt", "DATA")) then return; end;
|
||
|
|
|
||
|
|
local buffer = file.Read("ladders/dismounts/" .. game.GetMap() .. ".txt", false);
|
||
|
|
|
||
|
|
if (buffer:len() > 1) then
|
||
|
|
buffer = util.JSONToTable(buffer);
|
||
|
|
|
||
|
|
if (!buffer) then return; end;
|
||
|
|
|
||
|
|
for _, pos in pairs(buffer) do
|
||
|
|
local dismount = ents.Create("info_ladder_dismount");
|
||
|
|
|
||
|
|
if (!IsValid(dismount)) then continue; end;
|
||
|
|
|
||
|
|
dismount:SetPos(pos);
|
||
|
|
dismount:Spawn();
|
||
|
|
dismount:SetName("zdismount_" .. dismount:EntIndex());
|
||
|
|
end;
|
||
|
|
|
||
|
|
for k, v in pairs(ents.FindByClass("func_useableladder")) do
|
||
|
|
if (IsValid(v) and v:GetName():lower():find("zladder_")) then
|
||
|
|
-- CFuncLadder::Activate, so dismount points for ladders are updated.
|
||
|
|
v:Activate();
|
||
|
|
|
||
|
|
for _, dismount in pairs(ents.FindInSphere(v:GetPos() + v:GetSaveTable().point0, 120)) do
|
||
|
|
if (IsValid(dismount) and dismount:GetClass() == "info_ladder_dismount" and dismount:GetName():lower():find("zdismount") and !IsValid(dismount:GetParent())) then
|
||
|
|
dismount:SetParent(v);
|
||
|
|
end;
|
||
|
|
end;
|
||
|
|
|
||
|
|
for _, dismount in pairs(ents.FindInSphere(v:GetPos() + v:GetSaveTable().point1, 120)) do
|
||
|
|
if (IsValid(dismount) and dismount:GetClass() == "info_ladder_dismount" and dismount:GetName():lower():find("zdismount") and !IsValid(dismount:GetParent())) then
|
||
|
|
dismount:SetParent(v);
|
||
|
|
end;
|
||
|
|
end;
|
||
|
|
end;
|
||
|
|
end;
|
||
|
|
end;
|
||
|
|
end;
|
||
|
|
|
||
|
|
timer.Create("ladder_SaveData", 180, 0, function()
|
||
|
|
file.CreateDir("ladders");
|
||
|
|
file.CreateDir("ladders/ladders");
|
||
|
|
file.CreateDir("ladders/dismounts");
|
||
|
|
|
||
|
|
SaveLadders();
|
||
|
|
SaveDismounts();
|
||
|
|
end);
|
||
|
|
|
||
|
|
hook.Add("InitPostEntity", "zladder_SaveLadders", function()
|
||
|
|
timer.Simple(5, function()
|
||
|
|
local win, msg = pcall(LoadLadders);
|
||
|
|
if (!win) then
|
||
|
|
ErrorNoHalt("[LADDER TOOL] Something happened while loading ladders!")
|
||
|
|
print(msg);
|
||
|
|
end;
|
||
|
|
|
||
|
|
local win, msg = pcall(LoadDismounts);
|
||
|
|
if (!win) then
|
||
|
|
ErrorNoHalt("[LADDER TOOL] Something happened while loading dismounts!")
|
||
|
|
print(msg);
|
||
|
|
end;
|
||
|
|
end);
|
||
|
|
end);
|
||
|
|
end;
|
||
|
|
|
||
|
|
hook.Add("FindUseEntity", "zladder", function(player, ent)
|
||
|
|
if (IsValid(ent) and IsValid(ent.ladder)) then
|
||
|
|
return false;
|
||
|
|
end;
|
||
|
|
end);
|
||
|
|
|
||
|
|
properties.Add("ladder_persist", {
|
||
|
|
MenuLabel = "Save Ladder",
|
||
|
|
MenuIcon = "icon16/disk.png",
|
||
|
|
Order = 1,
|
||
|
|
|
||
|
|
Filter = function(self, ent, player)
|
||
|
|
if (!IsValid(ent)) then return false; end;
|
||
|
|
if (!player:IsSuperAdmin()) then return false; end;
|
||
|
|
if (ent:GetClass() != "prop_physics") then return false; end;
|
||
|
|
if (!IsValid(ent:GetNWEntity("ladder", nil))) then return false; end;
|
||
|
|
|
||
|
|
return !ent:GetNWEntity("ladder", nil):GetNWBool("saved", false);
|
||
|
|
end,
|
||
|
|
|
||
|
|
Action = function(self, ent)
|
||
|
|
self:MsgStart();
|
||
|
|
net.WriteEntity(ent);
|
||
|
|
self:MsgEnd();
|
||
|
|
end,
|
||
|
|
|
||
|
|
Receive = function(self, length, player)
|
||
|
|
local ent = net.ReadEntity();
|
||
|
|
|
||
|
|
if (!self:Filter(ent, player)) then return; end;
|
||
|
|
|
||
|
|
ent.ladder:SetNWBool("saved", true);
|
||
|
|
SaveLadders();
|
||
|
|
SaveDismounts();
|
||
|
|
end,
|
||
|
|
});
|
||
|
|
|
||
|
|
properties.Add("ladder_persist_end", {
|
||
|
|
MenuLabel = "Un-Save Ladder",
|
||
|
|
MenuIcon = "icon16/arrow_undo.png",
|
||
|
|
Order = 1,
|
||
|
|
|
||
|
|
Filter = function(self, ent, player)
|
||
|
|
if (!IsValid(ent)) then return false; end;
|
||
|
|
if (!player:IsSuperAdmin()) then return false; end;
|
||
|
|
if (ent:GetClass() != "prop_physics") then return false; end;
|
||
|
|
if (!IsValid(ent:GetNWEntity("ladder", nil))) then return false; end;
|
||
|
|
|
||
|
|
return ent:GetNWEntity("ladder", nil):GetNWBool("saved", false);
|
||
|
|
end,
|
||
|
|
|
||
|
|
Action = function(self, ent)
|
||
|
|
self:MsgStart();
|
||
|
|
net.WriteEntity(ent);
|
||
|
|
self:MsgEnd();
|
||
|
|
end,
|
||
|
|
|
||
|
|
Receive = function(self, length, player)
|
||
|
|
local ent = net.ReadEntity();
|
||
|
|
|
||
|
|
if (!self:Filter(ent, player)) then return; end;
|
||
|
|
|
||
|
|
ent.ladder:SetNWBool("saved", false);
|
||
|
|
SaveLadders();
|
||
|
|
SaveDismounts();
|
||
|
|
end,
|
||
|
|
});
|