User:JulienDethurens/Scripts/Heading code: Difference between revisions

From Legacy Roblox Wiki
Jump to navigationJump to search
Updated.
>JulienDethurens
>JulienDethurens
(Updated.)
 
Line 17: Line 17:
*InsertService
*InsertService


{{code|linenumbers=true|=
{{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, Instance types, Enum types, Enum, Color3, BrickColor, Vector2, Vector3, CFrame/CoordinateFrame, UDim, UDim2, RBXScriptSignal, Axes, Faces, Ray.
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|linenumbers=true|=
{{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|linenumbers=true|=
{{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>arg_num</var>, <var>func_name</var>, <var>optional</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_num  || number || The of the arg. Used in the error message.
| arg_name  || string || The name of the argument.
|-
|-
| func_name || string  || The name of the function. Used in the error message.
| optional  || boolean || Whether the argument can be nil or not.
|-
| optional  || boolean || Whether the argument is optional or not. If {{true}}, the value {{nil}} will also be accepted.
|}
|}


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.
 
bad argument #arg_num to func_name (data_type expected, got [the type of the argument, found with the get_type function]).


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|linenumbers=true|=
{{code|=
local function verify_arg(value, data_type, arg_num, func_name, optional)
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 same types as the is_a function.
-- 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 argument #2 to 'verify_arg' (string expected, got " .. type(data_type) .. ")", 2) end
if type(data_type) ~= 'string' then error("bad 'data_type' argument (string expected, got " .. get_type(data_type) .. ")", 2) end
if tonumber(arg_num) then
if type(arg_name) ~= 'string' then error("bad 'arg_name' argument (string expected, got " .. get_type(arg_name) .. ")") end
arg_num = tonumber(arg_num)
else
error("bad argument #3 to 'verify_arg' (number expected, got " .. type(arg_num) .. ")")
end
if type(func_name) ~= 'string' then error("bad argument #4 to 'verify_arg' (string expected, got " .. type(func_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 argument #" .. arg_num .. " to " .. func_name .. " (" .. data_type .. " expected, got " .. get_type(value) .. ")", 3)
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|linenumbers=true|=
{{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|linenumbers=true|=
{{code|=
local function modify(instance, t)
local function modify(instance, t)
verify_arg(instance, 'Instance', 1, "modify")
instance = verify_arg(instance, 'Instance', "instance")
verify_arg(t, 'table', 2, "modify")
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>object</var>, <var>func</var>) ==
== call_on_descendants(<var>instance</var>, <var>func</var>) ==


{| class="wikitable"
{| class="wikitable"
|+ Parameters
|+ Parameters
! Name   !! Type    !! Description
! Name     !! Type    !! Description
|-
|-
| object || Instance || The object you want to call a function on all the descendants of.
| 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.
| 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>object</var>, including <var>object</var> itself.
This function calls <var>func</var> on all the descendants of <var>instance</var>, including <var>instance</var> itself.


{{code|linenumbers=true|=
{{code|=
local function call_on_descendants(object, func)
local function call_on_descendants(instance, func)
-- Calls 'func' on 'object' and all its descendants, with the object or descendant as argument.
-- Calls 'func' on 'instance' and all its descendants, with the instance or descendant as argument.
verify_arg(object, 'Instance', 1, "func")
instance = verify_arg(instance, 'Instance', "instance")
verify_arg(func, 'function', 2, "func")
func = verify_arg(func, 'function', "func")
func(object)
func(instance)
for _, child in next, object:GetChildren() do
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>object</var>, <var>class_name</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
|-
|-
| object    || Instance || The object of which you want to find an ancestor.
| 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>object</var> of type <var>class_name</var> in ascending order.
This function returns the nearest ancestor of <var>instance</var> of type <var>class_name</var> in ascending order.


{{code|linenumbers=true|=
{{code|=
local function get_nearest_ancestor(object, class_name)
local function get_nearest_ancestor(instance, class_name)
-- Returns the nearest ancestor of a certain object which is of a certain type.
-- Returns the nearest ancestor of a certain instance which is of a certain type.
local ancestor = object
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:
}}
}}


== The Code ==
== get_character(<var>descendant</var>) ==


This is the entirety of the code:
{| 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|linenumbers=true|=
{| 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


local function verify_arg(value, data_type, arg_num, func_name, optional)
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 same types as the is_a function.
-- 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 argument #2 to 'verify_arg' (string expected, got " .. type(data_type) .. ")", 2) end
if type(data_type) ~= 'string' then error("bad 'data_type' argument (string expected, got " .. get_type(data_type) .. ")", 2) end
if tonumber(arg_num) then
if type(arg_name) ~= 'string' then error("bad 'arg_name' argument (string expected, got " .. get_type(arg_name) .. ")") end
arg_num = tonumber(arg_num)
else
error("bad argument #3 to 'verify_arg' (number expected, got " .. type(arg_num) .. ")")
end
if type(func_name) ~= 'string' then error("bad argument #4 to 'verify_arg' (string expected, got " .. type(func_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 argument #" .. arg_num .. " to " .. func_name .. " (" .. data_type .. " expected, got " .. get_type(value) .. ")", 3)
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', 1, "modify")
instance = verify_arg(instance, 'Instance', "instance")
verify_arg(t, 'table', 2, "modify")
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(object, func)
local function call_on_descendants(instance, func)
-- Calls 'func' on 'object' and all its descendants, with the object or descendant as argument.
-- Calls 'func' on 'instance' and all its descendants, with the instance or descendant as argument.
verify_arg(object, 'Instance', 1, "func")
instance = verify_arg(instance, 'Instance', "instance")
verify_arg(func, 'function', 2, "func")
func = verify_arg(func, 'function', "func")
func(object)
func(instance)
for _, child in next, object:GetChildren() do
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(object, class_name)
local function get_nearest_ancestor(instance, class_name)
-- Returns the nearest ancestor of a certain object which is of a certain type.
-- Returns the nearest ancestor of a certain instance which is of a certain type.
local ancestor = object
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
}}
}}
Anonymous user

Navigation menu