User:JulienDethurens/Scripts/Heading code: Difference between revisions
>JulienDethurens |
>JulienDethurens Updated. |
||
Line 17: | Line 17: | ||
*InsertService | *InsertService | ||
{{code | {{code|= | ||
local Players = Game:GetService('Players') | local Players = Game:GetService('Players') | ||
local StarterPack = Game:GetService('StarterPack') | local StarterPack = Game:GetService('StarterPack') | ||
Line 27: | Line 27: | ||
local InsertService = Game:GetService('InsertService') | local InsertService = Game:GetService('InsertService') | ||
local Terrain = Workspace.Terrain | local Terrain = Workspace.Terrain | ||
local verify_arg -- Since other functions defined before need to use it, this needs to be defined here. | |||
}} | }} | ||
Line 42: | Line 44: | ||
This function returns {{true}} if <var>value</var> is of type <var>data_type</var>. Otherwise, it returns {{false}}. | This function returns {{true}} if <var>value</var> is of type <var>data_type</var>. Otherwise, it returns {{false}}. | ||
It supports the following types: Lua types | It supports the following types: | ||
*all the Lua types (recognized by the Lua type function) | |||
*all the Instance types (recognized by the [[IsA]] method | |||
*all the Enum types | |||
*Enum (the enum object itself, accessed through the Enum variable | |||
*Color3 | |||
*BrickColor | |||
*Vector2 | |||
*Vector3 | |||
*CFrame/CoordinateFrame (both names are recognized by the function) | |||
*UDim | |||
*UDim2 | |||
*RBXScriptSignal (the real name of events) | |||
*Axes | |||
*Faces | |||
*Ray | |||
Just as a note, you can't use a "fake" value to make it return {{true}} with a value that is similar to a real value of the correct data type. If it says that the value is of the correct data type, then the value <strong>is</strong> of the correct data type. | Just as a note, you can't use a "fake" value to make it return {{true}} with a value that is similar to a real value of the correct data type. If it says that the value is of the correct data type, then the value <strong>is</strong> of the correct data type. | ||
{{code | {{code|= | ||
local function is_a(value, data_type) | local function is_a(value, data_type) | ||
-- Supported types: Lua types, Instance types, Enum types, Enum, Color3, BrickColor, Vector2, Vector3, CFrame/CoordinateFrame, UDim, UDim2, RBXScriptSignal, Axes, Faces, Ray | -- Supported types: Lua types, Instance types, Enum types, Enum, Color3, BrickColor, Vector2, Vector3, CFrame/CoordinateFrame, UDim, UDim2, RBXScriptSignal, Axes, Faces, Ray | ||
Line 55: | Line 72: | ||
-- Here is a nice collection of bad practices, ugly hacks, and other things you should never use, but that you don't have the choice of using, because of ROBLOX's lack of an official way to distinguish data types: | -- Here is a nice collection of bad practices, ugly hacks, and other things you should never use, but that you don't have the choice of using, because of ROBLOX's lack of an official way to distinguish data types: | ||
data_type = verify_arg(data_type, 'string', "data_type") | |||
if type(value) == data_type then return true end -- Lua types | if type(value) == data_type then return true end -- Lua types | ||
if pcall(function() assert(Game.IsA(value, data_type)) end) then return true end -- Instance types | if pcall(function() assert(Game.IsA(value, data_type)) end) then return true end -- Instance types | ||
Line 85: | Line 103: | ||
if _ and connection then | if _ and connection then | ||
connection:disconnect() | connection:disconnect() | ||
return true | |||
end | |||
end | |||
return false | |||
end | |||
}} | |||
== cpp_is_a(<var>value</var>, <var>data_type</var>) == | |||
{| class="wikitable" | |||
|+ Parameters | |||
! Name !! Type !! Description | |||
|- | |||
| value || || The value you want to check the type of. | |||
|- | |||
| data_type || string || The type you want to check if the value is of. | |||
|} | |||
This function is like the is_a function, but is used with the C++ types used by ROBLOX methods and properties. It should be used to know if a certain value would be accepted by a method or a property. | |||
It supports the following types: | |||
*int | |||
*double | |||
*bool | |||
*string | |||
*float | |||
{{code|= | |||
local function cpp_is_a(value, data_type) | |||
-- Same as is_a, but for methods and properties. Only supports basic types. | |||
-- Supports: int, double, bool, string, float | |||
-- Note: this function should be used to know if it is safe to send an argument to a method or a property, as it will also return true for values that will be automatically coerced by ROBLOX. | |||
data_type = verify_arg(data_type, 'string', "data_type") | |||
if data_type == 'int' then | |||
if pcall(function() Instance.new('IntValue').Value = value end) then | |||
return true | |||
end | |||
elseif data_type == 'double' then | |||
if pcall(function() Instance.new('NumberValue').Value = value end) then | |||
return true | |||
end | |||
elseif data_type == 'bool' then | |||
if pcall(function() Instance.new('BoolValue').Value = value end) then | |||
return true | |||
end | |||
elseif data_type == 'string' then | |||
if pcall(function() Instance.new('StringValue').Value = value end) then | |||
return true | |||
end | |||
elseif data_type == 'float' then | |||
if pcall(function() Instance.new('ClickDetector').MaxActivationDistance = value end) then | |||
return true | return true | ||
end | end | ||
Line 96: | Line 166: | ||
{| class="wikitable" | {| class="wikitable" | ||
|+ Parameters | |+ Parameters | ||
! Name !! Type !! Description | ! Name !! Type !! Description | ||
|- | |- | ||
|value || || The value you want to get the type of. | | value || || The value you want to get the type of. | ||
|} | |} | ||
This function returns the most specific type it can get for a certain value. It supports all the types supported by the '''is_a''' function. | This function returns the most specific type it can get for a certain value. It supports all the types supported by the '''is_a''' function. | ||
{{code | {{code|= | ||
local function get_type(value) | local function get_type(value) | ||
-- Returns the most specific type it can return. Supports the same types as the is_a function, except the enum types. | -- Returns the most specific type it can return. Supports the same types as the is_a function, except the enum types. | ||
Line 124: | Line 194: | ||
}} | }} | ||
== verify_arg(<var>value</var>, <var>data_type</var>, <var> | == verify_arg(<var>value</var>, <var>data_type</var>, <var>arg_name</var>, <var>optional</var>) == | ||
{| class="wikitable" | {| class="wikitable" | ||
Line 134: | Line 204: | ||
| data_type || string || The data type the value should be of. | | data_type || string || The data type the value should be of. | ||
|- | |- | ||
| | | arg_name || string || The name of the argument. | ||
|- | |- | ||
| optional || boolean || Whether the argument can be nil or not. | |||
| optional || boolean || Whether the argument | |||
|} | |} | ||
This function will check if <var>value</var> is of type <var>data_type</var>. If not, it will print an error message | This function will check if <var>value</var> is of type <var>data_type</var>. If not, it will print an error message relating to the type. | ||
Use it in functions that receive arguments to check if arguments are of the correct type. Using this function can make debugging <strong>a lot</strong> easier (trust me, that's from experience). | Use it in functions that receive arguments to check if arguments are of the correct type. Using this function can make debugging <strong>a lot</strong> easier (trust me, that's from experience). | ||
{{code | {{code|= | ||
function verify_arg(value, data_type, arg_name, optional) | |||
-- Makes the function that called the calling function error, with an error message relating to a wrong type. Supports the | -- Makes the function that called the calling function error, with an error message relating to a wrong type. Supports all the types supported by the is_a and the cpp_is_a functions. | ||
-- Also supports coercion for the number and string types. | -- Also supports coercion for the number and string types. | ||
-- Returns the value, as it might be automatically converted if a coercion has been done. | -- Returns the value, as it might be automatically converted if a coercion has been done. | ||
if type(data_type) ~= 'string' then error("bad | if type(data_type) ~= 'string' then error("bad 'data_type' argument (string expected, got " .. get_type(data_type) .. ")", 2) end | ||
if | if type(arg_name) ~= 'string' then error("bad 'arg_name' argument (string expected, got " .. get_type(arg_name) .. ")") end | ||
if optional and value == nil then | if optional and value == nil then | ||
return value | return value | ||
elseif is_a(value, data_type) then | elseif type(value) == data_type then | ||
return value | |||
elseif is_a(value, data_type) or cpp_is_a(value, data_type) then | |||
return value | return value | ||
elseif data_type == 'number' and tonumber(value) then | elseif data_type == 'number' and tonumber(value) then | ||
Line 169: | Line 232: | ||
return tostring(value) | return tostring(value) | ||
else | else | ||
error("bad | error("bad '" .. arg_name .. "'" .. (optional and " optional" or "") .. " argument (" .. data_type .. " expected, got " .. get_type(value) .. ")", 3) | ||
end | end | ||
end | end | ||
Line 187: | Line 250: | ||
This function allows you to edit the properties and the hierarchy of a certain object. Because I am too lazy to explain exactly how it works, and because you already have the code anyways, I will only give you an example: | This function allows you to edit the properties and the hierarchy of a certain object. Because I am too lazy to explain exactly how it works, and because you already have the code anyways, I will only give you an example: | ||
{{code | {{code|= | ||
local part = modify(Instance.new('Part'), { | local part = modify(Instance.new('Part'), { | ||
Name = "Wall"; | Name = "Wall"; | ||
Position = Vector3.new(10, 50, 10); | Position = Vector3.new(10, 50, 10); | ||
with (Instance.new('Fire') | with (Instance.new('Fire'), { | ||
Heat = 10; | Heat = 10; | ||
Size = 50; | Size = 50; | ||
}; | }); | ||
}) | }) | ||
}} | }} | ||
Line 200: | Line 263: | ||
That code creates a part, sets its name to "Wall", sets its position to a certain Vector3, creates a Fire object in it, sets some of the properties of that Fire object, and stores the part in the <var>part</var> variable. | That code creates a part, sets its name to "Wall", sets its position to a certain Vector3, creates a Fire object in it, sets some of the properties of that Fire object, and stores the part in the <var>part</var> variable. | ||
{{code | {{code|= | ||
local function modify(instance, t) | local function modify(instance, t) | ||
verify_arg(instance, 'Instance' | instance = verify_arg(instance, 'Instance', "instance") | ||
verify_arg(t, 'table' | t = verify_arg(t, 'table', "t") | ||
for key, value in next, t do | for key, value in next, t do | ||
if type(key) == 'number' then | if type(key) == 'number' then | ||
Line 215: | Line 278: | ||
}} | }} | ||
== call_on_descendants(<var> | == call_on_descendants(<var>instance</var>, <var>func</var>) == | ||
{| class="wikitable" | {| class="wikitable" | ||
|+ Parameters | |+ Parameters | ||
! Name | ! Name !! Type !! Description | ||
|- | |- | ||
| | | instance || Instance || The object you want to call a function on all the descendants of. | ||
|- | |- | ||
| func | | func || function || The function you want to call on all the descendants of the object. | ||
|} | |} | ||
This function calls <var>func</var> on all the descendants of <var> | This function calls <var>func</var> on all the descendants of <var>instance</var>, including <var>instance</var> itself. | ||
{{code | {{code|= | ||
local function call_on_descendants( | local function call_on_descendants(instance, func) | ||
-- Calls 'func' on ' | -- Calls 'func' on 'instance' and all its descendants, with the instance or descendant as argument. | ||
verify_arg( | instance = verify_arg(instance, 'Instance', "instance") | ||
verify_arg(func, 'function' | func = verify_arg(func, 'function', "func") | ||
func( | func(instance) | ||
for _, child in next, | for _, child in next, instance:GetChildren() do | ||
call_on_descendants(child, func) | call_on_descendants(child, func) | ||
end | end | ||
Line 240: | Line 303: | ||
}} | }} | ||
== get_nearest_ancestor(<var> | == get_nearest_ancestor(<var>instance</var>, <var>class_name</var>) == | ||
{| class="wikitable" | {| class="wikitable" | ||
Line 246: | Line 309: | ||
! Name !! Type !! Description | ! Name !! Type !! Description | ||
|- | |- | ||
| | | instance || Instance || The object of which you want to find an ancestor. | ||
|- | |- | ||
| class_name || string || The class name of the ancestor you want to find. | | class_name || string || The class name of the ancestor you want to find. | ||
|} | |} | ||
This function returns the nearest ancestor of <var> | This function returns the nearest ancestor of <var>instance</var> of type <var>class_name</var> in ascending order. | ||
{{code | {{code|= | ||
local function get_nearest_ancestor( | local function get_nearest_ancestor(instance, class_name) | ||
-- Returns the nearest ancestor of a certain | -- Returns the nearest ancestor of a certain instance which is of a certain type. | ||
local ancestor = | instance = verify_arg(instance, 'Instance', "instance") | ||
class_name = verify_arg(class_name, 'string', "class_name") | |||
local ancestor = instance | |||
repeat | repeat | ||
ancestor = ancestor.Parent | ancestor = ancestor.Parent | ||
Line 267: | Line 332: | ||
}} | }} | ||
== | == get_character(<var>descendant</var>) == | ||
This is | {| class="wikitable" | ||
|+ Parameters | |||
! Name !! Type !! Description | |||
|- | |||
| descendant || Instance || The descendant of the character you want to get. | |||
|} | |||
This function returns the character a descendant is a part of. | |||
{{code|= | |||
local function get_character(descendant) | |||
-- Returns a character from one of its descendants. | |||
descendant = verify_arg(descendant, 'Instance', "descendant") | |||
local character = descendant | |||
repeat | |||
if character.Parent then | |||
character = character.Parent | |||
else | |||
return nil | |||
end | |||
until Players:GetPlayerFromCharacter(character) | |||
return character | |||
end | |||
}} | |||
== show_message(<var>text</var>, <var>lifetime</var>) == | |||
{{code| | {| class="wikitable" | ||
|+ Parameters | |||
! Name !! Type !! Description | |||
|- | |||
| text || string || The text you want to show in the message. | |||
|- | |||
| lifetime || number || The time, in seconds, during which the message must be displayed. | |||
|} | |||
This function shows a message and removes it after a certain time. | |||
{{code|= | |||
local function show_message(text, lifetime) | |||
-- Shows a message for a certain time, which is set to be 3 seconds by default. | |||
text = verify_arg(text, 'string', "text") | |||
lifetime = verify_arg(lifetime, 'number', "lifetime") | |||
local message = Instance.new('Message') | |||
message.Text = text | |||
Debris:AddItem(message, lifetime or 3) | |||
end | |||
}} | |||
== show_hint(<var>text</var>, <var>lifetime</var>) == | |||
{| class="wikitable" | |||
|+ Parameters | |||
! Name !! Type !! Description | |||
|- | |||
| text || string || The text you want to show in the hint. | |||
|- | |||
| lifetime || number || The time, in seconds, during which the hint must be displayed. | |||
|} | |||
This function shows a hint and removes it after a certain time. | |||
{{code|= | |||
local function show_hint(text, lifetime) | |||
-- Shows a hint for a certain time, which is set to be 3 seconds by default. | |||
text = verify_arg(text, 'string', "text") | |||
lifetime = verify_arg(lifetime, 'number', "lifetime") | |||
local hint = Instance.new('Hint') | |||
hint.Text = text | |||
Debris:AddItem(hint, lifetime or 3) | |||
end | |||
}} | |||
== Entire code == | |||
Here is the whole code: | |||
{{code|= | |||
local Players = Game:GetService('Players') | local Players = Game:GetService('Players') | ||
local StarterPack = Game:GetService('StarterPack') | local StarterPack = Game:GetService('StarterPack') | ||
Line 281: | Line 421: | ||
local InsertService = Game:GetService('InsertService') | local InsertService = Game:GetService('InsertService') | ||
local Terrain = Workspace.Terrain | local Terrain = Workspace.Terrain | ||
local verify_arg -- Since other functions defined before need to use it, this needs to be defined here. | |||
local function is_a(value, data_type) | local function is_a(value, data_type) | ||
Line 290: | Line 432: | ||
-- Here is a nice collection of bad practices, ugly hacks, and other things you should never use, but that you don't have the choice of using, because of ROBLOX's lack of an official way to distinguish data types: | -- Here is a nice collection of bad practices, ugly hacks, and other things you should never use, but that you don't have the choice of using, because of ROBLOX's lack of an official way to distinguish data types: | ||
data_type = verify_arg(data_type, 'string', "data_type") | |||
if type(value) == data_type then return true end -- Lua types | if type(value) == data_type then return true end -- Lua types | ||
if pcall(function() assert(Game.IsA(value, data_type)) end) then return true end -- Instance types | if pcall(function() assert(Game.IsA(value, data_type)) end) then return true end -- Instance types | ||
Line 320: | Line 463: | ||
if _ and connection then | if _ and connection then | ||
connection:disconnect() | connection:disconnect() | ||
return true | |||
end | |||
end | |||
return false | |||
end | |||
local function cpp_is_a(value, data_type) | |||
-- Same as is_a, but for methods and properties. Only supports basic types. | |||
-- Supports: int, double, bool, string, float | |||
-- Note: this function should be used to know if it is safe to send an argument to a method or a property, as it will also return true for values that will be automatically coerced by ROBLOX. | |||
data_type = verify_arg(data_type, 'string', "data_type") | |||
if data_type == 'int' then | |||
if pcall(function() Instance.new('IntValue').Value = value end) then | |||
return true | |||
end | |||
elseif data_type == 'double' then | |||
if pcall(function() Instance.new('NumberValue').Value = value end) then | |||
return true | |||
end | |||
elseif data_type == 'bool' then | |||
if pcall(function() Instance.new('BoolValue').Value = value end) then | |||
return true | |||
end | |||
elseif data_type == 'string' then | |||
if pcall(function() Instance.new('StringValue').Value = value end) then | |||
return true | |||
end | |||
elseif data_type == 'float' then | |||
if pcall(function() Instance.new('ClickDetector').MaxActivationDistance = value end) then | |||
return true | return true | ||
end | end | ||
Line 345: | Line 517: | ||
end | end | ||
function verify_arg(value, data_type, arg_name, optional) | |||
-- Makes the function that called the calling function error, with an error message relating to a wrong type. Supports the | -- Makes the function that called the calling function error, with an error message relating to a wrong type. Supports all the types supported by the is_a and the cpp_is_a functions. | ||
-- Also supports coercion for the number and string types. | -- Also supports coercion for the number and string types. | ||
-- Returns the value, as it might be automatically converted if a coercion has been done. | -- Returns the value, as it might be automatically converted if a coercion has been done. | ||
if type(data_type) ~= 'string' then error("bad | if type(data_type) ~= 'string' then error("bad 'data_type' argument (string expected, got " .. get_type(data_type) .. ")", 2) end | ||
if | if type(arg_name) ~= 'string' then error("bad 'arg_name' argument (string expected, got " .. get_type(arg_name) .. ")") end | ||
if optional and value == nil then | if optional and value == nil then | ||
return value | return value | ||
elseif is_a(value, data_type) then | elseif type(value) == data_type then | ||
return value | |||
elseif is_a(value, data_type) or cpp_is_a(value, data_type) then | |||
return value | return value | ||
elseif data_type == 'number' and tonumber(value) then | elseif data_type == 'number' and tonumber(value) then | ||
Line 366: | Line 535: | ||
return tostring(value) | return tostring(value) | ||
else | else | ||
error("bad | error("bad '" .. arg_name .. "'" .. (optional and " optional" or "") .. " argument (" .. data_type .. " expected, got " .. get_type(value) .. ")", 3) | ||
end | end | ||
end | end | ||
local function modify(instance, t) | local function modify(instance, t) | ||
verify_arg(instance, 'Instance' | instance = verify_arg(instance, 'Instance', "instance") | ||
verify_arg(t, 'table' | t = verify_arg(t, 'table', "t") | ||
for key, value in next, t do | for key, value in next, t do | ||
if type(key) == 'number' then | if type(key) == 'number' then | ||
Line 383: | Line 552: | ||
end | end | ||
local function call_on_descendants( | local function call_on_descendants(instance, func) | ||
-- Calls 'func' on ' | -- Calls 'func' on 'instance' and all its descendants, with the instance or descendant as argument. | ||
verify_arg( | instance = verify_arg(instance, 'Instance', "instance") | ||
verify_arg(func, 'function' | func = verify_arg(func, 'function', "func") | ||
func( | func(instance) | ||
for _, child in next, | for _, child in next, instance:GetChildren() do | ||
call_on_descendants(child, func) | call_on_descendants(child, func) | ||
end | end | ||
end | end | ||
local function get_nearest_ancestor( | local function get_nearest_ancestor(instance, class_name) | ||
-- Returns the nearest ancestor of a certain | -- Returns the nearest ancestor of a certain instance which is of a certain type. | ||
local ancestor = | instance = verify_arg(instance, 'Instance', "instance") | ||
class_name = verify_arg(class_name, 'string', "class_name") | |||
local ancestor = instance | |||
repeat | repeat | ||
ancestor = ancestor.Parent | ancestor = ancestor.Parent | ||
Line 403: | Line 574: | ||
until ancestor:IsA(class_name) | until ancestor:IsA(class_name) | ||
return ancestor | return ancestor | ||
end | |||
local function get_character(descendant) | |||
-- Returns a character from one of its descendants. | |||
descendant = verify_arg(descendant, 'Instance', "descendant") | |||
local character = descendant | |||
repeat | |||
if character.Parent then | |||
character = character.Parent | |||
else | |||
return nil | |||
end | |||
until Players:GetPlayerFromCharacter(character) | |||
return character | |||
end | |||
local function show_message(text, lifetime) | |||
-- Shows a message for a certain time, which is set to be 3 seconds by default. | |||
text = verify_arg(text, 'string', "text") | |||
lifetime = verify_arg(lifetime, 'number', "lifetime") | |||
local message = Instance.new('Message') | |||
message.Text = text | |||
Debris:AddItem(message, lifetime or 3) | |||
end | |||
local function show_hint(text, lifetime) | |||
-- Shows a hint for a certain time, which is set to be 3 seconds by default. | |||
text = verify_arg(text, 'string', "text") | |||
lifetime = verify_arg(lifetime, 'number', "lifetime") | |||
local hint = Instance.new('Hint') | |||
hint.Text = text | |||
Debris:AddItem(hint, lifetime or 3) | |||
end | end | ||
}} | }} |
Latest revision as of 00:37, 25 April 2012
This is code I often put at the top of my code (that's why this page is called "Heading code", btw).
It contains many useful functions, many that I designed for making libraries easier to create.
Variables
The code creates a variable that makes accessing the Terrain object easier, that variable is called "Terrain".
It also creates many variables for some services that I commonly use:
- Players
- StarterPack
- StarterGui
- Lighting
- Debris
- Teams
- BadgeService
- InsertService
local Players = Game:GetService('Players')
local StarterPack = Game:GetService('StarterPack')
local StarterGui = Game:GetService('StarterGui')
local Lighting = Game:GetService('Lighting')
local Debris = Game:GetService('Debris')
local Teams = Game:GetService('Teams')
local BadgeService = Game:GetService('BadgeService')
local InsertService = Game:GetService('InsertService')
local Terrain = Workspace.Terrain
local verify_arg -- Since other functions defined before need to use it, this needs to be defined here.
is_a(value, data_type)
Name | Type | Description |
---|---|---|
value | The value you want to check the type of. | |
data_type | string | The type you want to check for. |
This function returns true if value is of type data_type. Otherwise, it returns false.
It supports the following types:
- all the Lua types (recognized by the Lua type function)
- all the Instance types (recognized by the IsA method
- all the Enum types
- Enum (the enum object itself, accessed through the Enum variable
- Color3
- BrickColor
- Vector2
- Vector3
- CFrame/CoordinateFrame (both names are recognized by the function)
- UDim
- UDim2
- RBXScriptSignal (the real name of events)
- Axes
- Faces
- Ray
Just as a note, you can't use a "fake" value to make it return true with a value that is similar to a real value of the correct data type. If it says that the value is of the correct data type, then the value is of the correct data type.
local function is_a(value, data_type)
-- Supported types: Lua types, Instance types, Enum types, Enum, Color3, BrickColor, Vector2, Vector3, CFrame/CoordinateFrame, UDim, UDim2, RBXScriptSignal, Axes, Faces, Ray
-- Will return false if the type is not supported, even though the value might be of that type.
-- This function can not be fooled by a fake value. If it says the value is a ClickDetector, then it IS a ClickDetector.
-- This function uses a variety of ugly hacks that were found by JulienDethurens.
-- I wish ROBLOX just provided an official way to do this, I wouldn't have to use lots of unrealiable ways to get the info I need... :/
-- Here is a nice collection of bad practices, ugly hacks, and other things you should never use, but that you don't have the choice of using, because of ROBLOX's lack of an official way to distinguish data types:
data_type = verify_arg(data_type, 'string', "data_type")
if type(value) == data_type then return true end -- Lua types
if pcall(function() assert(Game.IsA(value, data_type)) end) then return true end -- Instance types
if pcall(function() assert(Enum[data_type]) end) then -- Enum types
for _, enum in next, Enum[data_type]:GetEnumItems() do
if value == enum then
return true
end
end
elseif pcall(Enum.Material.GetEnumItems, value) then
for _, enum in next, value:GetEnumItems() do
if value == enum then
return true
end
end
end
if data_type == 'Color3' and pcall(function() Instance.new('Color3Value').Value = value end) then return true -- Color3
elseif data_type == 'BrickColor' and pcall(function() Instance.new('BrickColorValue').Value = value end) then return true -- BrickColor
elseif data_type == 'Vector2' and pcall(function() return Vector2.new() + value end) then return true -- Vector2
elseif data_type == 'Vector3' and pcall(function() Instance.new('Vector3Value').Value = value end) then return true -- Vector3
elseif (data_type == 'CFrame' or data_type == 'CoordinateFrame') and pcall(function() Instance.new('CFrameValue').Value = value end) then return true -- CFrame
elseif data_type == 'UDim' and pcall(function() return UDim.new() + value end) then return true -- UDim
elseif data_type == 'UDim2' and pcall(function() Instance.new('Frame').Position = value end) then return true -- UDim2
elseif data_type == 'Ray' and pcall(function() Ray.new(Vector3.new(), Vector3.new()).Distance(value, Vector3.new()) end) then return true -- Ray
elseif data_type == 'Axes' and pcall(function() Instance.new('ArcHandles').Axes = value end) then return true -- Axes
elseif data_type == 'Faces' and pcall(function() Instance.new('Handles').Faces = value end) then return true -- Faces
elseif data_type == 'Enum' and pcall(Enum.Material.GetEnumItems, value) then return true -- Enum
elseif data_type == 'RBXScriptSignal' then
local _, connection = pcall(function() return Game.AllowedGearTypeChanged.connect(value) end)
if _ and connection then
connection:disconnect()
return true
end
end
return false
end
cpp_is_a(value, data_type)
Name | Type | Description |
---|---|---|
value | The value you want to check the type of. | |
data_type | string | The type you want to check if the value is of. |
This function is like the is_a function, but is used with the C++ types used by ROBLOX methods and properties. It should be used to know if a certain value would be accepted by a method or a property.
It supports the following types:
- int
- double
- bool
- string
- float
local function cpp_is_a(value, data_type)
-- Same as is_a, but for methods and properties. Only supports basic types.
-- Supports: int, double, bool, string, float
-- Note: this function should be used to know if it is safe to send an argument to a method or a property, as it will also return true for values that will be automatically coerced by ROBLOX.
data_type = verify_arg(data_type, 'string', "data_type")
if data_type == 'int' then
if pcall(function() Instance.new('IntValue').Value = value end) then
return true
end
elseif data_type == 'double' then
if pcall(function() Instance.new('NumberValue').Value = value end) then
return true
end
elseif data_type == 'bool' then
if pcall(function() Instance.new('BoolValue').Value = value end) then
return true
end
elseif data_type == 'string' then
if pcall(function() Instance.new('StringValue').Value = value end) then
return true
end
elseif data_type == 'float' then
if pcall(function() Instance.new('ClickDetector').MaxActivationDistance = value end) then
return true
end
end
return false
end
get_type(value)
Name | Type | Description |
---|---|---|
value | The value you want to get the type of. |
This function returns the most specific type it can get for a certain value. It supports all the types supported by the is_a function.
local function get_type(value)
-- Returns the most specific type it can return. Supports the same types as the is_a function, except the enum types.
if is_a(value, 'Instance') then return value.ClassName
elseif is_a(value, 'Enum') then return 'Enum'
elseif is_a(value, 'Color3') then return 'Color3'
elseif is_a(value, 'BrickColor') then return 'BrickColor'
elseif is_a(value, 'Vector2') then return 'Vector2'
elseif is_a(value, 'Vector3') then return 'Vector3'
elseif is_a(value, 'CFrame') then return 'CFrame'
elseif is_a(value, 'UDim') then return 'UDim'
elseif is_a(value, 'UDim2') then return 'UDim2'
elseif is_a(value, 'Ray') then return 'Ray'
elseif is_a(value, 'Axes') then return 'Axes'
elseif is_a(value, 'Faces') then return 'Faces'
elseif is_a(value, 'RBXScriptSignal') then return 'RBXScriptSignal'
else return type(value)
end
end
verify_arg(value, data_type, arg_name, optional)
Name | Type | Description |
---|---|---|
value | The value you want the verify the type of. | |
data_type | string | The data type the value should be of. |
arg_name | string | The name of the argument. |
optional | boolean | Whether the argument can be nil or not. |
This function will check if value is of type data_type. If not, it will print an error message relating to the type.
Use it in functions that receive arguments to check if arguments are of the correct type. Using this function can make debugging a lot easier (trust me, that's from experience).
function verify_arg(value, data_type, arg_name, optional)
-- Makes the function that called the calling function error, with an error message relating to a wrong type. Supports all the types supported by the is_a and the cpp_is_a functions.
-- Also supports coercion for the number and string types.
-- Returns the value, as it might be automatically converted if a coercion has been done.
if type(data_type) ~= 'string' then error("bad 'data_type' argument (string expected, got " .. get_type(data_type) .. ")", 2) end
if type(arg_name) ~= 'string' then error("bad 'arg_name' argument (string expected, got " .. get_type(arg_name) .. ")") end
if optional and value == nil then
return value
elseif type(value) == data_type then
return value
elseif is_a(value, data_type) or cpp_is_a(value, data_type) then
return value
elseif data_type == 'number' and tonumber(value) then
return tonumber(value)
elseif data_type == 'string' and type(value) == 'number' then
return tostring(value)
else
error("bad '" .. arg_name .. "'" .. (optional and " optional" or "") .. " argument (" .. data_type .. " expected, got " .. get_type(value) .. ")", 3)
end
end
modify(instance, t)
Name | Type | Description |
---|---|---|
instance | Instance | The instance you want to edit. |
t | table | The changes you want to make to instance. |
This function allows you to edit the properties and the hierarchy of a certain object. Because I am too lazy to explain exactly how it works, and because you already have the code anyways, I will only give you an example:
local part = modify(Instance.new('Part'), {
Name = "Wall";
Position = Vector3.new(10, 50, 10);
with (Instance.new('Fire'), {
Heat = 10;
Size = 50;
});
})
That code creates a part, sets its name to "Wall", sets its position to a certain Vector3, creates a Fire object in it, sets some of the properties of that Fire object, and stores the part in the part variable.
local function modify(instance, t)
instance = verify_arg(instance, 'Instance', "instance")
t = verify_arg(t, 'table', "t")
for key, value in next, t do
if type(key) == 'number' then
value.Parent = instance
else
instance[key] = value
end
end
return instance
end
call_on_descendants(instance, func)
Name | Type | Description |
---|---|---|
instance | Instance | The object you want to call a function on all the descendants of. |
func | function | The function you want to call on all the descendants of the object. |
This function calls func on all the descendants of instance, including instance itself.
local function call_on_descendants(instance, func)
-- Calls 'func' on 'instance' and all its descendants, with the instance or descendant as argument.
instance = verify_arg(instance, 'Instance', "instance")
func = verify_arg(func, 'function', "func")
func(instance)
for _, child in next, instance:GetChildren() do
call_on_descendants(child, func)
end
end
get_nearest_ancestor(instance, class_name)
Name | Type | Description |
---|---|---|
instance | Instance | The object of which you want to find an ancestor. |
class_name | string | The class name of the ancestor you want to find. |
This function returns the nearest ancestor of instance of type class_name in ascending order.
local function get_nearest_ancestor(instance, class_name)
-- Returns the nearest ancestor of a certain instance which is of a certain type.
instance = verify_arg(instance, 'Instance', "instance")
class_name = verify_arg(class_name, 'string', "class_name")
local ancestor = instance
repeat
ancestor = ancestor.Parent
if ancestor == nil then
return nil
end
until ancestor:IsA(class_name)
return ancestor
end
get_character(descendant)
Name | Type | Description |
---|---|---|
descendant | Instance | The descendant of the character you want to get. |
This function returns the character a descendant is a part of.
local function get_character(descendant)
-- Returns a character from one of its descendants.
descendant = verify_arg(descendant, 'Instance', "descendant")
local character = descendant
repeat
if character.Parent then
character = character.Parent
else
return nil
end
until Players:GetPlayerFromCharacter(character)
return character
end
show_message(text, lifetime)
Name | Type | Description |
---|---|---|
text | string | The text you want to show in the message. |
lifetime | number | The time, in seconds, during which the message must be displayed. |
This function shows a message and removes it after a certain time.
local function show_message(text, lifetime)
-- Shows a message for a certain time, which is set to be 3 seconds by default.
text = verify_arg(text, 'string', "text")
lifetime = verify_arg(lifetime, 'number', "lifetime")
local message = Instance.new('Message')
message.Text = text
Debris:AddItem(message, lifetime or 3)
end
show_hint(text, lifetime)
Name | Type | Description |
---|---|---|
text | string | The text you want to show in the hint. |
lifetime | number | The time, in seconds, during which the hint must be displayed. |
This function shows a hint and removes it after a certain time.
local function show_hint(text, lifetime)
-- Shows a hint for a certain time, which is set to be 3 seconds by default.
text = verify_arg(text, 'string', "text")
lifetime = verify_arg(lifetime, 'number', "lifetime")
local hint = Instance.new('Hint')
hint.Text = text
Debris:AddItem(hint, lifetime or 3)
end
Entire code
Here is the whole code:
local Players = Game:GetService('Players')
local StarterPack = Game:GetService('StarterPack')
local StarterGui = Game:GetService('StarterGui')
local Lighting = Game:GetService('Lighting')
local Debris = Game:GetService('Debris')
local Teams = Game:GetService('Teams')
local BadgeService = Game:GetService('BadgeService')
local InsertService = Game:GetService('InsertService')
local Terrain = Workspace.Terrain
local verify_arg -- Since other functions defined before need to use it, this needs to be defined here.
local function is_a(value, data_type)
-- Supported types: Lua types, Instance types, Enum types, Enum, Color3, BrickColor, Vector2, Vector3, CFrame/CoordinateFrame, UDim, UDim2, RBXScriptSignal, Axes, Faces, Ray
-- Will return false if the type is not supported, even though the value might be of that type.
-- This function can not be fooled by a fake value. If it says the value is a ClickDetector, then it IS a ClickDetector.
-- This function uses a variety of ugly hacks that were found by JulienDethurens.
-- I wish ROBLOX just provided an official way to do this, I wouldn't have to use lots of unrealiable ways to get the info I need... :/
-- Here is a nice collection of bad practices, ugly hacks, and other things you should never use, but that you don't have the choice of using, because of ROBLOX's lack of an official way to distinguish data types:
data_type = verify_arg(data_type, 'string', "data_type")
if type(value) == data_type then return true end -- Lua types
if pcall(function() assert(Game.IsA(value, data_type)) end) then return true end -- Instance types
if pcall(function() assert(Enum[data_type]) end) then -- Enum types
for _, enum in next, Enum[data_type]:GetEnumItems() do
if value == enum then
return true
end
end
elseif pcall(Enum.Material.GetEnumItems, value) then
for _, enum in next, value:GetEnumItems() do
if value == enum then
return true
end
end
end
if data_type == 'Color3' and pcall(function() Instance.new('Color3Value').Value = value end) then return true -- Color3
elseif data_type == 'BrickColor' and pcall(function() Instance.new('BrickColorValue').Value = value end) then return true -- BrickColor
elseif data_type == 'Vector2' and pcall(function() return Vector2.new() + value end) then return true -- Vector2
elseif data_type == 'Vector3' and pcall(function() Instance.new('Vector3Value').Value = value end) then return true -- Vector3
elseif (data_type == 'CFrame' or data_type == 'CoordinateFrame') and pcall(function() Instance.new('CFrameValue').Value = value end) then return true -- CFrame
elseif data_type == 'UDim' and pcall(function() return UDim.new() + value end) then return true -- UDim
elseif data_type == 'UDim2' and pcall(function() Instance.new('Frame').Position = value end) then return true -- UDim2
elseif data_type == 'Ray' and pcall(function() Ray.new(Vector3.new(), Vector3.new()).Distance(value, Vector3.new()) end) then return true -- Ray
elseif data_type == 'Axes' and pcall(function() Instance.new('ArcHandles').Axes = value end) then return true -- Axes
elseif data_type == 'Faces' and pcall(function() Instance.new('Handles').Faces = value end) then return true -- Faces
elseif data_type == 'Enum' and pcall(Enum.Material.GetEnumItems, value) then return true -- Enum
elseif data_type == 'RBXScriptSignal' then
local _, connection = pcall(function() return Game.AllowedGearTypeChanged.connect(value) end)
if _ and connection then
connection:disconnect()
return true
end
end
return false
end
local function cpp_is_a(value, data_type)
-- Same as is_a, but for methods and properties. Only supports basic types.
-- Supports: int, double, bool, string, float
-- Note: this function should be used to know if it is safe to send an argument to a method or a property, as it will also return true for values that will be automatically coerced by ROBLOX.
data_type = verify_arg(data_type, 'string', "data_type")
if data_type == 'int' then
if pcall(function() Instance.new('IntValue').Value = value end) then
return true
end
elseif data_type == 'double' then
if pcall(function() Instance.new('NumberValue').Value = value end) then
return true
end
elseif data_type == 'bool' then
if pcall(function() Instance.new('BoolValue').Value = value end) then
return true
end
elseif data_type == 'string' then
if pcall(function() Instance.new('StringValue').Value = value end) then
return true
end
elseif data_type == 'float' then
if pcall(function() Instance.new('ClickDetector').MaxActivationDistance = value end) then
return true
end
end
return false
end
local function get_type(value)
-- Returns the most specific type it can return. Supports the same types as the is_a function, except the enum types.
if is_a(value, 'Instance') then return value.ClassName
elseif is_a(value, 'Enum') then return 'Enum'
elseif is_a(value, 'Color3') then return 'Color3'
elseif is_a(value, 'BrickColor') then return 'BrickColor'
elseif is_a(value, 'Vector2') then return 'Vector2'
elseif is_a(value, 'Vector3') then return 'Vector3'
elseif is_a(value, 'CFrame') then return 'CFrame'
elseif is_a(value, 'UDim') then return 'UDim'
elseif is_a(value, 'UDim2') then return 'UDim2'
elseif is_a(value, 'Ray') then return 'Ray'
elseif is_a(value, 'Axes') then return 'Axes'
elseif is_a(value, 'Faces') then return 'Faces'
elseif is_a(value, 'RBXScriptSignal') then return 'RBXScriptSignal'
else return type(value)
end
end
function verify_arg(value, data_type, arg_name, optional)
-- Makes the function that called the calling function error, with an error message relating to a wrong type. Supports all the types supported by the is_a and the cpp_is_a functions.
-- Also supports coercion for the number and string types.
-- Returns the value, as it might be automatically converted if a coercion has been done.
if type(data_type) ~= 'string' then error("bad 'data_type' argument (string expected, got " .. get_type(data_type) .. ")", 2) end
if type(arg_name) ~= 'string' then error("bad 'arg_name' argument (string expected, got " .. get_type(arg_name) .. ")") end
if optional and value == nil then
return value
elseif type(value) == data_type then
return value
elseif is_a(value, data_type) or cpp_is_a(value, data_type) then
return value
elseif data_type == 'number' and tonumber(value) then
return tonumber(value)
elseif data_type == 'string' and type(value) == 'number' then
return tostring(value)
else
error("bad '" .. arg_name .. "'" .. (optional and " optional" or "") .. " argument (" .. data_type .. " expected, got " .. get_type(value) .. ")", 3)
end
end
local function modify(instance, t)
instance = verify_arg(instance, 'Instance', "instance")
t = verify_arg(t, 'table', "t")
for key, value in next, t do
if type(key) == 'number' then
value.Parent = instance
else
instance[key] = value
end
end
return instance
end
local function call_on_descendants(instance, func)
-- Calls 'func' on 'instance' and all its descendants, with the instance or descendant as argument.
instance = verify_arg(instance, 'Instance', "instance")
func = verify_arg(func, 'function', "func")
func(instance)
for _, child in next, instance:GetChildren() do
call_on_descendants(child, func)
end
end
local function get_nearest_ancestor(instance, class_name)
-- Returns the nearest ancestor of a certain instance which is of a certain type.
instance = verify_arg(instance, 'Instance', "instance")
class_name = verify_arg(class_name, 'string', "class_name")
local ancestor = instance
repeat
ancestor = ancestor.Parent
if ancestor == nil then
return nil
end
until ancestor:IsA(class_name)
return ancestor
end
local function get_character(descendant)
-- Returns a character from one of its descendants.
descendant = verify_arg(descendant, 'Instance', "descendant")
local character = descendant
repeat
if character.Parent then
character = character.Parent
else
return nil
end
until Players:GetPlayerFromCharacter(character)
return character
end
local function show_message(text, lifetime)
-- Shows a message for a certain time, which is set to be 3 seconds by default.
text = verify_arg(text, 'string', "text")
lifetime = verify_arg(lifetime, 'number', "lifetime")
local message = Instance.new('Message')
message.Text = text
Debris:AddItem(message, lifetime or 3)
end
local function show_hint(text, lifetime)
-- Shows a hint for a certain time, which is set to be 3 seconds by default.
text = verify_arg(text, 'string', "text")
lifetime = verify_arg(lifetime, 'number', "lifetime")
local hint = Instance.new('Hint')
hint.Text = text
Debris:AddItem(hint, lifetime or 3)
end