Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --[[
- dl library V0.5
- MrNicNac/StefanBashkir/DrMathematica
- -- Raw log:
- **************** DetermineROBLOXType ****************
- :: Parameters ::
- *UnknownType (?)
- => Determines the 'type' of the value given. If it's a Lua type, it returns type(UnknownType).
- Else, it will determine if it is a Lua type. Only distinguishable checks are available.
- ||| Object,CFrame,Vector3,Vector2,BrickColor,Color3 |||
- RETURNS: string
- **************** ConcatTable ****************
- :: Parameters ::
- *Table (table)
- ToAppend (string/number/bool)
- Func (function)
- => Works similar to table.concat. However, allows yout pass a function to evaluate the concatenation before it happens.
- It has this form
- Func(index,value, lengthOfOriginalTable)
- ::::: Where index is the position of the current value becing concatenated, and value is that actual value.
- If you use Func, you should input "" for ToAppend.
- RETURNS: string
- **************** GetDescendants ****************
- :: Parameters ::
- *Instance (object)
- => Returns a table of all children and descendants (literally everything inside) Instance.
- RETURNS: table
- **************** FindValueInTable ****************
- :: Parameters ::
- *Table (table)
- *Value (lua data)
- Recurse (bool)
- => Searches through a table to find a value. Will return true or false. If Recurse is set to true, will search inside
- all tables included in Table as well as inside their tables, and their tables, and so on..
- RETURNS: bool
- **************** GetByClass ****************
- :: Parameters ::
- *SearchInObject (object)
- *ClassName (string)
- AllowSuperClasses (bool)
- ExcludedNames (table)
- ExcludedClasses (table)
- => Searches through the entire SearchInObject (descendants as well) for the needed ClassName. If AllowSuperClasses is
- true, it will use IsA instead of .ClassName. If either of the last two parameters are set, it will exclude the given
- values of either names or classes in the tables.
- RETURNS: table
- **************** FormatRegion3 ****************
- :: Parameters ::
- *V31 (vector3)
- *V32 (vector3)
- => Returns a correctly-formatted Region3 value. Normally, you'd have to find the max and min x/y/z values of each v3
- and build a Region3 afterwards.
- **************** GetSurfaceClosestToPoint ****************
- :: Parameters ::
- *Part (object)
- *Point (vector3)
- => Uses simple relational math to find which surface on the given part the given point is closest to (or on).
- RETURNS: enum
- **************** GetFaceDirections ****************
- :: Parameters ::
- *Part (object)
- => Returns directions similar to how lookVector works on a part's CFrame. However, gives you ease of access to all
- 'directional' vectors of a part. DOES NOT HANDLE CASE OF ODD SHAPES (i.e. wedge) Gives up,down,left,right,front,
- back vectors.
- RETURNS: table
- **************** SearchCuboidArea ****************
- :: Parameters ::
- *Center (vector3)
- *CubicRadius (scalar number)
- IgnoreObjects (table)[of userdata]
- IgnoreNames (table)[of strings]
- IgnoreClasses (table)[of strings]
- VisuallyShowCubicSearchArea (bool)
- => Searches a cube area for any objects. Will correctly ignore any provided object userdata, names, or classes.
- RETURNS: table
- **************** InstantWeld ****************
- :: Parameters ::
- *MainPart (object)
- *LegacyPart (object)
- => Welds two parts together at their location exactly at the time of the function call. Basically, they will stay in the
- same place they were before the call, but will now be welded through a 'Weld' joint. Will return the weld that it
- creates.
- RETURNS: object
- **************** ForEach ****************
- :: Parameters ::
- *SearchableItem (object/table/string);
- FunctionToExecute (func)
- => Will loop through the object or table given and fire 'FunctionToExecute' on each one with the i,v arguments (index/value).
- If given a string, it will loop through each character of that string and fire 'FunctionToExecute' with i,v arguments.
- The 'i' when using a string indicates the position of the character, and 'v' is the literal character.
- RETURNS: 0
- **************** Tokenize ****************
- :: Parameters ::
- *String (string/object)
- *Token (string)
- => Splits a string into parts using the token as a delimiter. Returns a table of the split string.
- RETURNS: table
- **************** AngleBetweenVectors ****************
- :: Parameters ::
- *v1 (vector3/vector2)
- *v2 (vector3/vector2)
- => Returns the angle (in radians) between the given two vectors.
- RETURNS: number (radians)
- **************** PointDesiredAngleAt ****************
- :: Parameters ::
- *Motor (object)
- *LookAt (vector3/object)
- DoNotAutomaticallySetAngle (bool)
- => Sets the DesiredAngle property of the given motor to the correct angle in order to be facing the LookAt argument.
- In addition, will return the angle. If DoNotAutomaticallySetAngle is set, will not set the angle for you; it will just
- return the angle to satisfy the angle looking at LookAt.
- Keep in mind that, if you are testing this, you must remove the Animate script from your character.
- RETURNS: number (radians)
- **************** Shuffle ****************
- :: Parameters ::
- *Table (table)
- => Randomizes the order of the elements in the table. Returns the shuffled table.
- RETURNS: table
- --]]
- dl = { -- Do not make local, or else it cannot reference itself from within
- ['TestValue'] = true;
- ['DetermineROBLOXType'] = function(UnknownType)
- if (type(UnknownType) == "userdata") then
- -- If it's a userdata, we have a loose-typed value and it must be determined using tests.
- -- Get the value of the return from __tostring metamethod
- local Food = tostring(UnknownType)
- -- First test if it is an object
- if (pcall(function() local X = UnknownType.GetFullName end)) then
- -- It passed the first test of being an object
- -- Next is to test it against Lua data type (which, in ROBLOX, return nil for indexing this)
- if (UnknownType.GetFullName ~= nil)then
- return "object"
- end
- else
- -- This 'Food' is not an object
- -- It must be another ROBLOX datatype
- if (Food:find(".-,.-,.-,.-,.-,.-,.-,.-,.-,.-,.-,.-")) then
- return "cframe"
- elseif (Food:find(".-,.-,.-")) then
- -- Only a Vector3 has this format
- return "vector3"
- elseif (Food:find(".-,.-")) then
- -- A Vector3 and Vector2 have this format, but we checked for a Vector3 first. So if this format occurs
- -- after the Vector3 check, then it is a Vector2
- return "vector2"
- elseif (pcall(function() local X = UnknownType.Color end)) then
- return "brickcolor";
- elseif (pcall(function() local X = UnknownType.r end)) and (pcall(function() local X = UnknownType.g end)) then
- return "color3";
- else
- return "userdata", "unknown";
- --error("dl: Unsupported Data Type");
- end
- end
- else
- return type(UnknownType);
- end
- end;
- ['ConcatTable'] = function(TableToConcat, append, Func)
- -- Calls tostring, unlike table.concat. 'Func' passes the string being concatenated and the index that the string is
- -- from the given table.
- -- However, table.concat is always going to be faster
- if (type(TableToConcat) ~= "table") then
- error("dl: ConcatTable requires a table as first argument. Received: " .. type(TableToConcat));
- end
- local _ = "";
- if not (append) then
- append = "";
- end
- for i,v in pairs(TableToConcat) do
- local V = tostring(v)
- local ToAppend;
- if (Func) then
- if (type(Func) == "function") then
- ToAppend = Func(i, V, #TableToConcat);
- _ = _ .. ToAppend
- else
- error("dl: Third argument to concat must be a function or nil");
- end
- else
- _ = _ .. V .. (i < #TableToConcat and append or "")
- end
- end
- return _;
- end;
- ['GetDescendants'] = function(instance)
- local All = {}
- if (dl.DetermineROBLOXType(instance) ~= "object") then
- error("dl: getdescendants requires an object");
- end
- local function Get(parent)
- for i,v in pairs(parent:GetChildren()) do
- if (#v:GetChildren() > 0) then
- Get(v);
- end
- table.insert(All, v)
- end
- end
- Get(instance);
- return All;
- end;
- ['FindValueInTable'] = function(Table, Value, Recurse)
- if not (Recurse) then
- Recurse = false;
- end
- if (type(Recurse) ~= "boolean") then
- error("dl: third argument of FindValueInTable must be a boolean. Received: " .. type(Recurse));
- end
- local Recurse = (Recurse ~= nil) and Recurse or false;
- local item;
- local function Search(_t)
- for i,v in pairs(_t) do
- if (item) then break end
- if (type(v) == "table") and (Recurse) and (v ~= Value) then
- Search(v)
- elseif (v == Value) then
- item = v;
- end
- end
- end
- Search(Table)
- if (item) then
- return true;
- end
- return false;
- end;
- ['GetByClass'] = function(Parent, className, AllowSuperClass, ExcludedNames, ExcludedClasses)
- -- This function is expensive as hell
- if not (Parent) then
- error("dl: GetByClass's first argument must not be nil.")
- end
- if (dl.DetermineROBLOXType(Parent) ~= "object") then
- error("dl: GetByClass's first argument must be an object.")
- end
- if not (ExcludedNames) then
- ExcludedNames = {};
- end
- if not (ExcludedClasses) then
- ExcludedClasses = {};
- end
- if (type(ExcludedNames) ~= "table") then
- error("dl: GetByClass requires its fourth argument to be a table or nil");
- end
- if (type(ExcludedClasses) ~= "table") then
- error("dl: GetByClass requires its fifth argument to be a table or nil");
- end
- local Collection = {};
- local GameObjects = dl.GetDescendants(Parent);
- for i,v in pairs(GameObjects) do
- if (AllowSuperClass) then
- if v:IsA(className) then
- if not (dl.FindValueInTable(ExcludedNames, v.Name)) and not (dl.FindValueInTable(ExcludedClasses, v.className)) then
- table.insert(Collection, v)
- end
- end
- else
- if (v.className == className) then
- if not (dl.FindValueInTable(ExcludedNames, v.Name)) and not (dl.FindValueInTable(ExcludedClasses, v.className)) then
- table.insert(Collection, v)
- end
- end
- end
- end
- return Collection;
- end;
- ['FormatRegion3'] = function(v3,_v3)
- if (v3.x == _v3.x) or (v3.y == _v3.y) or (v3.z == _v3.z) then
- error("GetFormattedRegion3 cannot format a Region3 given these coordinates. One or more of the x,y or z values is equal to that of the opposite argument.");
- end
- return Region3.new(
- Vector3.new(
- math.min(v3.x, _v3.x),
- math.min(v3.y,_v3.y),
- math.min(v3.z,_v3.z)
- ),
- Vector3.new(
- math.max(v3.x, _v3.x),
- math.max(v3.y,_v3.y),
- math.max(v3.z,_v3.z)
- )
- )
- end;
- ['GetSurfaceClosestToPoint'] = function(part, pos)
- if (dl.DetermineROBLOXType(part) ~= "object") then
- error("dl: GetSurfaceClosestToPoint requires an object.");
- end
- local _, count = tostring(pos):gsub(",",",");
- if (dl.DetermineROBLOXType(part) ~= "vector3") then
- error("dl: Argument 2 for GetSurfaceClosestToPoint must be a Vector3.");
- end
- local rel = part.CFrame:pointToObjectSpace(pos)
- if (math.abs(rel.Z) > math.abs(rel.Y)) and (math.abs(rel.Z) > math.abs(rel.X)) then
- if (rel.Z > 0) then
- return Enum.NormalId.Back
- else
- return Enum.NormalId.Front
- end
- elseif (math.abs(rel.Y) > math.abs(rel.Z)) and (math.abs(rel.Y) > math.abs(rel.X)) then
- if (rel.Y > 0) then
- return Enum.NormalId.Top
- else
- return Enum.NormalId.Bottom
- end
- elseif (math.abs(rel.X) > math.abs(rel.Z) and math.abs(rel.X) > math.abs(rel.Y)) then
- if (rel.X > 0) then
- return Enum.NormalId.Right
- else
- return Enum.NormalId.Left
- end
- end
- end;
- ['GetFaceDirections'] = function(instance)
- local directions = {};
- if (dl.DetermineROBLOXType(instance) ~= "object") then
- error("dl: GetFaceDirections requires an object.");
- end
- local matrix = instance.CFrame;
- directions['up'] =
- matrix:vectorToWorldSpace( Vector3.new(0,1,0) );
- directions['down'] =
- matrix:vectorToWorldSpace( Vector3.new(0,-1,0) );
- directions['left'] =
- matrix:vectorToWorldSpace( Vector3.new(-1,0,0) );
- directions['right'] =
- matrix:vectorToWorldSpace( Vector3.new(1,0,0) );
- directions['front'] =
- matrix.lookVector;
- directions['back'] =
- -matrix.lookVector;
- return directions;
- end;
- ['SearchCuboidArea'] = function(Center, CubicRadius, IgnoreObjects, IgnoreNames, IgnoreClasses, Visualize)
- if (dl.DetermineROBLOXType(Center) ~= "vector3") then
- error("dl: First argument of SearchCuboidArea must be a Vector3.");
- end
- if (type(CubicRadius) ~= "number") then
- error("dl: Second argument of SearchCuboidArea must be a number.");
- end
- if not (IgnoreObjects) then
- IgnoreObjects = {};
- end
- if not (IgnoreNames) then
- IgnoreNames = {};
- end
- if not (IgnoreClasses) then
- IgnoreClasses = {};
- end
- if (not type(IgnoreObjects)=="table") or (not type(IgnoreNames)=="table") or (not type(IgnoreClasses)=="table") then
- error("dl: All ignore tables of SearchCuboidArea must either be nil or of type 'table'");
- end
- local SearchVolume = ((CubicRadius*2)^3);
- if (SearchVolume > 99999) then
- print("dl: SearchCuboidArea was given a CubicRadius that exceeds the maximum volume for Region3 set by ROBLOX. Automatically downsizing to fit under 100,000");
- CubicRadius = 23.20775;
- end
- local Corner1 = Center + Vector3.new(CubicRadius,CubicRadius,CubicRadius);
- local Corner2 = Center - Vector3.new(CubicRadius,CubicRadius,CubicRadius);
- local Region3 = dl.FormatRegion3(
- Corner1, Corner2
- )
- local FinalCollection = {}
- local Parts = workspace:FindPartsInRegion3WithIgnoreList(Region3, IgnoreObjects);
- -- Check for parts with ignored names or classes
- for i,v in pairs(Parts) do
- if (not dl.FindValueInTable(IgnoreNames, v.Name)) and (not dl.FindValueInTable(IgnoreClasses, v.ClassName)) then
- table.insert(FinalCollection, v);
- end
- end
- if (Visualize) then
- local Template = Instance.new("Part");
- Template.FormFactor = "Custom";
- Template.Size = Vector3.new(0.01,0.01,CubicRadius * 2);
- Template.Anchored = true;
- Template.Name = "dl_Library:::VisualStrut";
- Template.BrickColor = BrickColor.Yellow();
- local Template2 = Template:Clone();
- Template2.Size = Vector3.new(CubicRadius*2, 0.01,0.01);
- local Template3 = Template:Clone();
- Template3.Size = Vector3.new(0.01, CubicRadius*2,0.01);
- -- Do X sides first
- local X1 = Template:Clone();
- X1.Position = Center + Vector3.new(CubicRadius,CubicRadius,0);
- X1.Parent = workspace
- local X2 = Template:Clone();
- X2.Position = Center + Vector3.new(-CubicRadius,CubicRadius,0);
- X2.Parent = workspace
- local X3 = Template:Clone();
- X3.Position = Center + Vector3.new(-CubicRadius,-CubicRadius,0);
- X3.Parent = workspace
- local X4 = Template:Clone();
- X4.Position = Center + Vector3.new(CubicRadius,-CubicRadius,0);
- X4.Parent = workspace
- -- Do Z sides second
- local X1 = Template2:Clone();
- X1.Position = Center + Vector3.new(0,CubicRadius,CubicRadius);
- X1.Parent = workspace
- local X2 = Template2:Clone();
- X2.Position = Center + Vector3.new(0,CubicRadius,-CubicRadius);
- X2.Parent = workspace
- local X3 = Template2:Clone();
- X3.Position = Center + Vector3.new(0,-CubicRadius,-CubicRadius);
- X3.Parent = workspace
- local X4 = Template2:Clone();
- X4.Position = Center + Vector3.new(0,-CubicRadius,CubicRadius);
- X4.Parent = workspace
- -- Do Y sides Last
- local X1 = Template3:Clone();
- X1.Position = Center + Vector3.new(CubicRadius,0,CubicRadius);
- X1.Parent = workspace
- local X2 = Template3:Clone();
- X2.Position = Center + Vector3.new(CubicRadius,0,-CubicRadius);
- X2.Parent = workspace
- local X3 = Template3:Clone();
- X3.Position = Center + Vector3.new(-CubicRadius,0,-CubicRadius);
- X3.Parent = workspace
- local X4 = Template3:Clone();
- X4.Position = Center + Vector3.new(-CubicRadius,0,CubicRadius);
- X4.Parent = workspace
- local X1,X2,X3,X4 = nil,nil,nil,nil
- end
- return FinalCollection;
- end;
- ['InstantWeld'] = function(Part1, Part2)
- if (dl.DetermineROBLOXType(Part1) ~= "object") and (dl.DetermineROBLOXType(Part2) ~= "object") then
- error("dl: InstantWeld's two arguments must both be objects.");
- end
- local W = Instance.new("Weld")
- W.C1 = Part2.CFrame:toObjectSpace(Part1.CFrame);
- W.Part0 = Part1;
- W.Part1 = Part2;
- W.Parent = game.JointsService;
- return W
- end;
- ['ForEach'] = function(Parent, Exe)
- local SearchTable = {};
- local Option = 0;
- if (dl.DetermineROBLOXType(Parent) == "object") then
- SearchTable = Parent:GetChildren()
- Option = 1;
- elseif (dl.DetermineROBLOXType(Parent) == "table") then
- SearchTable = Parent;
- Option = 1;
- elseif (dl.DetermineROBLOXType(Parent) == "string") then
- Option = 2;
- else
- error("dl: ForEach requires its argument to be a ROBLOX object, table, or string.");
- end
- if (Option == 1) then
- for i,v in pairs(SearchTable) do
- Exe(i,v);
- end
- elseif (Option == 2) then
- for position, character in Parent:gmatch("()(.)") do
- Exe(position, character);
- end
- end
- return 0;
- end;
- ['Tokenize'] = function(String, Token)
- local Collection = {};
- local IS = ""; -- holds current string after each tokenizing. Used to return the last string with no tokens.
- if (dl.DetermineROBLOXType(String) ~= "string") and (dl.DetermineROBLOXType(String) ~= "object") then
- error("dl Tokenize's first argument expects a string or object. Given: " .. dl.DetermineROBLOXType(String));
- end
- local String = tostring(String); -- handle case of ROBLOX object
- if (dl.DetermineROBLOXType(Token) ~= "string") then
- error("dl: Tokenize's second argument must be a string.");
- end
- IS = String;
- local OriginalString = String;
- for Group, Position in String:gmatch("(.-)" .. Token .. "()") do
- table.insert(Collection, Group);
- String = OriginalString:sub(Position);
- end
- if (String:len() > 0) then
- table.insert(Collection, String);
- end
- return Collection;
- end;
- ['AngleBetweenVectors'] = function(v1,v2)
- local Type1,Type2 = dl.DetermineROBLOXType(v1), dl.DetermineROBLOXType(v2)
- if (Type1 ~= "vector3") or (Type2 ~= "vector3") then
- if (Type1 ~= "vector2") or (Type2 ~= "vector2") then
- error("dl: AngleBetweenVectors requires both arguments to be a Vector3 or Vector2");
- end
- end
- if (Type1 ~= Type2) then
- error("dl: AngleBetweenVectors requires that both arguments be the same type of vector.");
- end
- local DotProduct;
- if (Type1 == "vector3") then
- DotProduct = v1:Dot(v2);
- else
- -- Vector2 doesn't have the .Dot function for some reason :|
- DotProduct = ( v1.x * v2.x + v1.y * v2.y );
- end
- return math.acos(DotProduct/(v1.magnitude*v2.magnitude));
- end;
- ['PointDesiredAngleAt'] = function(Motor, LookAt, DoNotLiveAdjustJoint)
- if (dl.DetermineROBLOXType(Motor) ~= "object") or not (pcall(function() local X = Motor.DesiredAngle end)) then
- error("dl: PointDesiredAngleAt requires the first argument be an object with a DesiredAngle property.");
- end
- if (dl.DetermineROBLOXType(LookAt) ~= "object") and (dl.DetermineROBLOXType(LookAt) ~= "vector3") then
- error("dl: PointDesiredAngleAt requires the second argument to be an object or a vector3");
- end
- if (dl.DetermineROBLOXType(LookAt) == "object") then
- LookAt = LookAt.Position;
- end
- local Variance = (LookAt - Motor.Part0.Position)['unit'];
- local Variance_Delimiter = Vector3.new(Variance.X,Variance.Y,0);
- local Theta = dl['AngleBetweenVectors'](Vector3.new(0,-1,0), Variance_Delimiter);
- if (not DoNotLiveAdjustJoint) then
- Motor.DesiredAngle = Theta;
- end
- return Theta;
- end;
- ['Shuffle'] = function(Table)
- -- Uses Yates shuffling algorithm
- math.random(); math.randomseed(tick()); math.random();
- local n, order, res = #Table, {}, {};
- for i=1,n do
- order[i] = { rnd = math.random(), idx = i }
- end
- table.sort(order, function(a,b) return a.rnd < b.rnd end)
- for i=1,n do
- res[i] = Table[order[i].idx]
- end
- return res
- end;
- -- Ray cast 360 degrees from a point?
- -- Ray cast in an arc for cone of sight?
- }
- return dl
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement