Created
October 18, 2020 03:33
-
-
Save GermanAizek/b3f965b91096420fc2ff5e750a965fb3 to your computer and use it in GitHub Desktop.
nutscript plugin Area
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local PLUGIN = PLUGIN | |
PLUGIN.name = "Area" | |
PLUGIN.author = "Black Tea" | |
PLUGIN.desc = "Allows you to set area." | |
PLUGIN.areaTable = PLUGIN.areaTable or {} | |
nut.area = nut.area or {} | |
ALWAYS_RAISED["nut_areahelper"] = true | |
nut.config.add("areaFontSize", 26, "The size of the font of Area Display.", | |
function(oldValue, newValue) | |
if (CLIENT) then | |
hook.Run("LoadFonts", nut.config.get("font")) | |
end | |
end, | |
{data = {min = 1, max = 128}, | |
category = "areaPlugin" | |
}) | |
nut.config.add("areaDispSpeed", 20, "The Appearance Speed of Area Display.", nil, { | |
data = {min = 1, max = 40}, | |
category = "areaPlugin" | |
}) | |
local playerMeta = FindMetaTable("Player") | |
local PLUGIN = PLUGIN | |
if (SERVER) then | |
function nut.area.getArea(areaID) | |
return PLUGIN.areaTable[areaID] | |
end | |
function nut.area.getAllArea() | |
return PLUGIN.areaTable | |
end | |
-- This is for single check (ex: area items, checking area in commands) | |
function playerMeta:isInArea(areaID) | |
local areaData = nut.area.getArea(areaID) | |
if (!areaData) then | |
return false, "Area you specified is not valid." | |
end | |
local char = self:getChar() | |
if (!char) then | |
return false, "Your character is not valid." | |
end | |
local clientPos = self:GetPos() + self:OBBCenter() | |
return clientPos:WithinAABox(areaData.minVector, areaData.maxVector), areaData | |
end | |
-- This is for continous check (ex: checking gas area whatever.) | |
function playerMeta:getArea() | |
return self.curArea | |
end | |
function PLUGIN:saveAreas() | |
self:setData(self.areaTable) | |
end | |
function PLUGIN:LoadData() | |
self.areaTable = self:getData() or {} | |
end | |
function PLUGIN:PlayerLoadedChar(client, character, lastChar) | |
client.curArea = nil | |
end | |
function PLUGIN:PlayerDeath(client) | |
client.curArea = nil | |
end | |
function PLUGIN:EntityTakeDamage( client, dmg ) | |
if client:IsPlayer() and client.curArea then | |
local areaData = table.Copy(nut.area.getArea(client.curArea)) | |
if areaData.isSafe and client:isInArea(client.curArea) then | |
dmg:ScaleDamage(0) | |
end | |
end | |
end | |
function PLUGIN:PlayerSpawn(client) | |
client.curArea = nil | |
end | |
-- gets two vector and gives min and max vector for Vector:WithinAA(min, max) | |
local function sortVector(vector1, vector2) | |
local minVector = Vector(0, 0, 0) | |
local maxVector = Vector(0, 0, 0) | |
for i = 1, 3 do | |
if (vector1[i] >= vector2[i]) then | |
maxVector[i] = vector1[i] | |
minVector[i] = vector2[i] | |
else | |
maxVector[i] = vector2[i] | |
minVector[i] = vector1[i] | |
end | |
end | |
return minVector, maxVector | |
end | |
-- add area. | |
function nut.area.addArea(name, vector1, vector2, isSafe) | |
if (!name or !vector1 or !vector2) then | |
return false, "Required arguments are not provided." | |
end | |
local minVector, maxVector = sortVector(vector1, vector2) | |
table.insert(PLUGIN.areaTable, { | |
name = name, | |
minVector = minVector, | |
maxVector = maxVector, | |
isSafe = isSafe or 0, | |
}) | |
PLUGIN:saveAreas() | |
end | |
-- Timer instead of heavy think. | |
timer.Create("nutAreaController", 0.33, 0, function() | |
for k, v in ipairs(player.GetAll()) do | |
local char = v:getChar() | |
if (char and v:Alive()) then | |
local area = v:getArea() | |
for id, areaData in pairs(nut.area.getAllArea()) do | |
local clientPos = v:GetPos() + v:OBBCenter() | |
if (clientPos:WithinAABox(areaData.minVector, areaData.maxVector)) then | |
if (area != id) then | |
v.curArea = id | |
hook.Run("OnPlayerAreaChanged", v, id) | |
end | |
end | |
end | |
end | |
end | |
end) | |
-- If area is changed, set display Area's Name to the client's screen. | |
function PLUGIN:OnPlayerAreaChanged(client, areaID) | |
local areaData = nut.area.getArea(areaID) | |
netstream.Start(client, "displayAreaText", tostring(areaData.name)) | |
end | |
netstream.Hook("areaEdit", function(client, areaID, editData) | |
-- Only Admin can edit the area. | |
if (!client:IsAdmin()) then | |
return false | |
end | |
-- If area is valid, merge editData to areaData. | |
local areaData = table.Copy(nut.area.getArea(areaID)) | |
if (areaData) then | |
client:notifyLocalized("areaModified", areaID) | |
PLUGIN.areaTable[areaID] = table.Merge(areaData, editData) | |
PLUGIN:saveAreas() | |
end | |
end) | |
netstream.Hook("areaTeleport", function(client, areaID, editData) | |
-- Only Admin can do this. | |
if (!client:IsAdmin()) then | |
return false | |
end | |
-- If area is valid, merge editData to areaData. | |
local areaData = table.Copy(nut.area.getArea(areaID)) | |
if (areaData) then | |
local min, max = areaData.maxVector, areaData.minVector | |
client:SetPos(min + (max - min)/2) | |
end | |
end) | |
netstream.Hook("toggleSafe", function(client, areaID, editData) | |
-- Only Admin can edit the area. | |
if (!client:IsAdmin()) then | |
return false | |
end | |
local areaData = table.Copy(nut.area.getArea(areaID)) | |
if (areaData) then | |
PLUGIN.areaTable[areaID].isSafe = !PLUGIN.areaTable[areaID].isSafe | |
PLUGIN:saveAreas() | |
end | |
end) | |
netstream.Hook("areaAdd", function(client, name, vector1, vector2, isSafe) | |
-- Only Admin can edit the area. | |
if (!client:IsAdmin() or !vector1 or !vector2 or !name) then | |
return false | |
end | |
nut.area.addArea(name, vector1, vector2, isSafe or 0) | |
end) | |
netstream.Hook("areaRemove", function(client, areaID, editData) | |
-- Only Admin can edit the area. | |
if (!client:IsAdmin()) then | |
return false | |
end | |
-- If area is valid, merge editData to areaData. | |
local areaData = table.Copy(nut.area.getArea(areaID)) | |
if (areaData) then | |
client:notifyLocalized("areaRemoved", areaID) | |
PLUGIN.areaTable[areaID] = nil | |
PLUGIN:saveAreas() | |
end | |
end) | |
else | |
netstream.Hook("displayPosition", function(pos) | |
local emitter = ParticleEmitter( pos ) | |
local bling = emitter:Add( "sprites/glow04_noz", pos ) | |
bling:SetVelocity( Vector( 0, 0, 1 ) ) | |
bling:SetDieTime(10) | |
bling:SetStartAlpha(255) | |
bling:SetEndAlpha(255) | |
bling:SetStartSize(64) | |
bling:SetEndSize(64) | |
bling:SetColor(255,186,50) | |
bling:SetAirResistance(300) | |
end) | |
-- area Manager. | |
local function addAreaPanel(frame) | |
local panel = frame:Add("DPanel") | |
panel:SetTall(30) | |
frame:AddItem(panel) | |
end | |
function nut.area.openAreaManager() | |
local frame = vgui.Create("DFrame") | |
frame:SetSize(400, 300) | |
frame:Center() | |
frame:MakePopup() | |
frame:SetTitle("Area Manager") | |
frame.menu = frame:Add("PanelList") | |
frame.menu:Dock(FILL) | |
frame.menu:DockMargin(5, 5, 5, 5) | |
frame.menu:SetSpacing(2) | |
frame.menu:SetPadding(2) | |
frame.menu:EnableVerticalScrollbar() | |
addAreaPanel(frame.menu) | |
end | |
netstream.Hook("areaManager", function() | |
--nut.area.openAreaManager() | |
end) | |
function PLUGIN:LoadFonts(font) | |
timer.Simple(0, function() | |
surface.CreateFont("nutAreaDisplay", { | |
font = font, | |
size = ScreenScale(nut.config.get("areaFontSize")), | |
weight = 500, | |
shadow = true, | |
}) | |
end) | |
end | |
-- draw matrix string. | |
-- slow as fuck I guess? | |
local function drawMatrixString(str, font, x, y, scale, angle, color) | |
surface.SetFont(font) | |
local tx, ty = surface.GetTextSize(str) | |
local matrix = Matrix() | |
matrix:Translate(Vector(x, y, 1)) | |
matrix:Rotate(angle or Angle(0, 0, 0)) | |
matrix:Scale(scale) | |
cam.PushModelMatrix(matrix) | |
surface.SetTextPos(2, 2) | |
surface.SetTextColor(color or color_white) | |
surface.DrawText(str) | |
cam.PopModelMatrix() | |
end | |
-- configureable values. | |
local speed = 0 | |
local targetScale = 0 | |
local dispString = "" | |
local tickSound = "UI/buttonrollover.wav" | |
local dieTime = 5 | |
-- non configureable values. | |
-- local scale = 0 | |
local scale = 0 | |
local flipTable = {} | |
local powTime = RealTime()*speed | |
local curChar = 0 | |
local mathsin = math.sin | |
local mathcos = math.cos | |
local dieTrigger = false | |
local dieTimer = RealTime() | |
local dieAlpha = 0 | |
local ft, w, h, dsx, dsy | |
function displayScrText(str, time) | |
speed = nut.config.get("areaDispSpeed") | |
targetScale = 1 | |
dispString = str | |
dieTime = time or 5 | |
scale = targetScale * .5 | |
flipTable = {} | |
powTime = RealTime()*speed | |
curChar = 0 | |
dieTrigger = false | |
dieTimer = RealTime() | |
dieAlpha = 255 | |
end | |
netstream.Hook("displayAreaText", function(str) | |
displayScrText(str) | |
end) | |
function PLUGIN:HUDPaint() | |
-- values | |
if ((hook.Run("CanDisplayArea") == false) or (dieTrigger and dieTimer < RealTime() and dieAlpha <= 1)) then | |
return | |
end | |
ft = FrameTime() | |
w, h = ScrW(), ScrH() | |
dsx, dsy = 0 | |
local strEnd = string.utf8len(dispString) | |
local rTime = RealTime() | |
surface.SetFont("Default") | |
local sx, sy = surface.GetTextSize(dispString) | |
-- Number of characters to display. | |
local maxDisplay = math.Round(rTime*speed - powTime) | |
-- resize if it's too big. | |
while (sx and sx*targetScale > w*.8) do | |
targetScale = targetScale * .9 | |
end | |
-- scale lerp | |
scale = Lerp(ft*1, scale, targetScale) | |
--scale = targetScale | |
-- change event | |
if (maxDisplay != curChar and curChar < strEnd) then | |
curChar = maxDisplay | |
if (string.utf8sub(dispString, curChar, curChar) != " ") then | |
LocalPlayer():EmitSound(tickSound, 100, math.random(190, 200)) | |
end | |
end | |
-- draw recursive | |
for i = 1, math.min(maxDisplay, strEnd) do | |
-- character scale/color lerp | |
flipTable[i] = flipTable[i] or {} | |
flipTable[i][1] = flipTable[i][1] or .1 | |
--flipTable[i][1] = flipTable[i][1] or targetScale*3 | |
flipTable[i][2] = flipTable[i][2] or 0 | |
flipTable[i][1] = Lerp(ft*4, flipTable[i][1], scale) | |
flipTable[i][2] = Lerp(ft*4, flipTable[i][2], 255) | |
-- draw character. | |
local char = string.utf8sub(dispString, i, i) | |
local tx, ty = surface.GetTextSize(char) | |
drawMatrixString(char, | |
"zonaStalkerTitle", | |
math.Round(w/2 + dsx - (sx or 0)*scale/2), | |
math.Round(h/3*1 - (sy or 0)*scale/2), | |
Vector(Format("%.2f", flipTable[i][1]), Format("%.2f", scale), 1), | |
nil, | |
Color(255, 255, 255, | |
(dieTrigger and dieTimer < RealTime()) and dieAlpha or flipTable[i][2]) | |
) | |
-- next | |
dsx = dsx + tx*scale | |
end | |
if (maxDisplay >= strEnd) then | |
if (dieTrigger != true) then | |
dieTrigger = true | |
dieTimer = RealTime() + 2 | |
else | |
if (dieTimer < RealTime()) then | |
dieAlpha = Lerp(ft*4, dieAlpha, 0) | |
end | |
end | |
end | |
end | |
end | |
nut.command.add("areaadd", { | |
adminOnly = true, | |
syntax = "<string name>", | |
onRun = function(client, arguments) | |
local name = table.concat(arguments, " ") or "Area" | |
local pos = client:GetEyeTraceNoCursor().HitPos | |
if (!client:getNetVar("areaMin")) then | |
if (!name) then | |
nut.util.Notify(nut.lang.Get("missing_arg", 1), client) | |
return | |
end | |
netstream.Start(client, "displayPosition", pos) | |
client:setNetVar("areaMin", pos, client) | |
client:setNetVar("areaName", name, client) | |
return "@areaCommand" | |
else | |
local min = client:getNetVar("areaMin") | |
local max = pos | |
local name = client:getNetVar("areaName") | |
netstream.Start(client, "displayPosition", pos) | |
client:setNetVar("areaMin", nil, client) | |
client:setNetVar("areaName", nil, client) | |
nut.area.addArea(name, min, max) | |
return "@areaAdded", name | |
end | |
end | |
}) | |
nut.command.add("arearemove", { | |
adminOnly = true, | |
onRun = function(client, arguments) | |
local areaID = client:getArea() | |
if (!areaID) then | |
return | |
end | |
local areaData = nut.area.getArea(areaID) | |
if (areaData) then | |
table.remove(PLUGIN.areaTable, areaID) | |
PLUGIN:saveAreas() | |
return "@areaRemoved", areaData.name | |
end | |
end | |
}) | |
nut.command.add("areachange", { | |
adminOnly = true, | |
syntax = "<string name>", | |
onRun = function(client, arguments) | |
local name = table.concat(arguments, " ") or "Area" | |
local areaID = client:getArea() | |
if (!areaID) then | |
return | |
end | |
local areaData = nut.area.getArea(areaID) | |
if (areaData) then | |
areaData.name = name | |
PLUGIN:saveAreas() | |
return "@areaChanged", name, areaData.name | |
end | |
end | |
}) | |
nut.command.add("areamanager", { | |
adminOnly = true, | |
onRun = function(client, arguments) | |
if (client:Alive()) then | |
netstream.Start(client, "nutAreaManager", nut.area.getAllArea()) | |
end | |
end | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment