CVExtra -- Super Module Script (DEVELOPMENT FORUM)


  • In inspiration from https://devforum.roblox.com/t/remove-duplicates-from-a-model-or-workspace/250858

    I decided to make a new function, "CleanDuplicates()"

    It is WIP, but it has led me to make another function, which has also been implemented into "getProperties()"

    That function is "IsInstance". No, it isn't supposed to work like "typeof(Instance) == "Instance" ", not in the slightest.

    It checks if a given string, is a valid instance classname. (Does not account for Base-Classes like "BasePart" and other related classes)

    Code:

    IsInstance = function(instance) -- WIP
    		local result = {false,nil}
    		
    		if (typeof(instance) == "Instance") then
    			result = {true,instance}
    		elseif (typeof(instance) == "string") then
    			local found = false
    			local realinstance
    			
    			if (instance == "DataModel" or instance == "game" or instance == "Game") then
    				realinstance = game
    				found = true
    			else
    				local istcreate = pcall(function()
    					realinstance = Instance.new(instance)
    				end)
    				if istcreate then
    					found = true
    				else
    					realinstance = nil
    					local datachild = {}
    					for _,v in pairs(game:GetChildren()) do
    						local isproperchild = pcall(function()
    							if v.ClassName == instance then
    								realinstance = v
    								found = true
    							else
    								datachild[#datachild+1] = v
    							end
    						end)
    						if (found == true) then
    							break
    						end
    					end
    					if (found == false) then
    						for _,gameobj in pairs(datachild) do
    							local isproperchildren = pcall(function()
    								for _,obj in pairs(gameobj:GetDescendants()) do
    									if obj.ClassName == instance then
    										realinstance = obj
    										found = true
    										break
    									end
    								end
    							end)
    							if (found == true) then
    								break
    							end
    						end
    					end
    				end
    			end
    			result = {found,realinstance}
    		end
    		
    		return unpack(result)
    	end,
    

    First it checks if the given variable is an instance, if so, returns "true" and the instance.

    If it isn't an instance and it's a string, it pcalls Instance.new() on the string. It returns "true" and the instance if successful.

    If that isn't successful, it then checks if the given string is the ClassName of a child of game. If it is, returns "true" and the instance.

    Otherwise, if THAT'S not successful, it adds all the children to a table called "datachild". Which the script then loops over, calling :GetDescendants() on all the game's children. If it is successful, it returns "true" and the instance.

    If that's not successful, well, it just returns "false" and "nil" because it didn't find it!

    Additional note: Due to Roblox securities, the script won't be able to search through EVERY child of game, but will do to the best of its ability.


  • "IsInstance()" has thus been added to "getProperties()", to support strings for "getProperties()".


  • @Cvieyra2test There's a simpler way to go about that; a way I came up with was with the following

    local InstanceCache = {} -- So that it doesn't need to keep checking over and over; just save the result in a dictionary. :thinking:'
    
    if InstanceCache['Part'] then
    	return true
    else
    	local IsInstance, InstanceCreated = pcall(Instance.new, 'Part')
    	
    	if IsInstance and InstanceCreated then
    		InstanceCache['Part'] = true
    	end
    	
    	return InstanceCache['Part']
    end
    

  • @TheAlphaStigma Yes, was thinking that, as doing what I did, wouldn't consider locked instances. I might attempt to do such in conjunction with getProperties(). Creating a table with the properties and their values, getting it to print the results in a table fashion and then copying it.

    Or, in an odd fashion, creating a "getRawProperties()" and "getProperties()".

    "getRawProperties()" doing the current purpose of "getProperties()" whilst "getProperties()" utilizes what you mention.

    (Although, I'd think via terminology it'd be incorrect)


  • Critique Disclaimer:

    Since it seems evident it needs to be explained. Do not expect me to take 100% of your criticism like you are a prophet. I will evidently evaluate/criticise your own criticism, relating it to the purpose of the thing getting criticised on.

    If it doesn't match with what I'm going for, I will not use the criticism stated. This also includes if the criticism in question, is also explained and elaborated.
    For example, many tell me to use "local" variables, but never truly elaborate to why, except stating readability or that it'd continue on throughout the entire scope (which, in the situation it is mostly stated in, is what I want it to do).

    And I don't "take no criticism", I take criticism, evaluate it and figure out ways to apply it, if I can't, I say I can't. This is not being "stubborn", this is figuring out how the criticism applies to the situation and not being spoon-fed criticism.

    I will be honest, the only thing I spoon-feed is math-stuff, since that is my weakest point when it comes to coding. However, I plan to get to learning more math later on.


  • @Cvieyra2test

    For example, many tell me to use "local" variables, but never truly elaborate to why, except stating readability or that it'd continue on throughout the entire scope (which, in the situation it is mostly stated in, is what I want it to do).

    • Lexically scoped (they're only accessible to scope declared in)

    • More efficient

    • Added to stack

    • Faster to access (good for if you're writing time critical code)

    • Smaller-to-no risk for name collisions

    • They don't make codebase a mess

    Bye


  • @Cvieyra2test Although there's been constant explanations why to use local variables, I'll give my go.

    1. If you don't use local variables for their scopes, variables will be rewritten.

    For example, image if a player were to increase their cash every 1 second. The following'll overwrite.

    function GiveCash(Player)
         Cash = Instance.new('Cash')
         Cash.Name = 'Cash'
         Cash.Parent = Player
         while true do
              wait(1)
              Cash.Value = Cash.Value + 1
         end
    end
    

    If another player were to join, it'd increase his double, then for the next, triple, etc.

    1. Memory Leaks (three links in one, depending where you click ;) ) will occur.

    Put simply; if it doesn't end somewhere, memory's going to build.

    .

    Off-topic; you completely disregarded what I'd stated previously. Stop. Pushing. It. On. Posting what you just did completely stabbed what I'd said before.

    TL;DR It's over. Quit beating at a dead horse. Don't even bother responding to this part of my post. Move on.


  • @sjr04alt It's faster to access?

    @TheAlphaStigma Well I'd never use it in a function like that, so I definitely know about that. I didn't see that much of a point to adding local's when given this example.

    function GiveCash(Player)
         Cash = Instance.new('Cash')
         Cash.Name = 'Cash'
         Cash.Parent = Player
         while true do
              wait(1)
              Cash.Value = Cash.Value + 1
         end
    end
    

    Also, I do know about it being local to the scope itself, which wasn't the purpose of what I had stated, it was in the global scope of the module script.

    Thank you for providing the links. Now I do see more to why I should. As to better memory management.

    Off-topic: I don't get how I have disregarded anything you have said? As though I will state, it's not a learning experience until I have understood how it applies to what I'm doing, thus why I criticise the criticism. It's something that is simply required.

    I do not see how the "example" had a lot of fluff? The pcalls were used purposefully as to avoid security checks. It may seem like an "if" statement mess.


  • @Cvieyra2test here's a tip

    use

    pcall(fn, ...);
    

    rather than

    pcall(function(...)
        fn(...);
    end, ...);
    

    So use pcall(Instance.new, className);

    If pcall returns true as first return, everything else after the first return is the returns of the function.

    Here's an example:

    local success, object = pcall(Instance.new, "Part");
    

  • @sjr04alt I've seen a familiar format before, so that actually works like that? Thank you for the tip.

    Dang wiki never tells you anythin'

    Been also trying to find a function that'd print out red text without ending the program flow.

    assert(), error(), TestService:Error() are all I found, when I wrap them in a pcall, it doesn't print out anything. But then again, it is pcall and it catches errors...


  • @Cvieyra2test, the wiki is trash. I never recommend to learn anything from it. Its only use is finding out the name of a method you forgot. Maybe you should study Lua5.1 in more depth.

    pcall(func, ...)
    

    should be a commonly known fact.


  • @Phlegethon5778 I cannot disagree, that wiki is quite trash, I never go to it for scripting help. But as you stated, rather to figure out that function I forgot.

    But now it doesn't even teach ya about base, global functions aaaa

    But I'll take your word for it to look up the Lua 5.1


  • @Cvieyra2test, I recommend the reference manual. It's helped me immensely. Some parts are confusing and hard to understand, and you'd probably never encounter most of them on Roblox, so you can ignore those parts.


  • Chapter two is probably going to be the most helpful to you.


  • @Cvieyra2test @Phlegethon5778

    Roblox Wiki for learning the Roblox API

    Lua official site for learning Lua

    I didn't know you can use string patterns to get information about the date. For example, os.date("%x") returns the date in string format MM/DD/YYYY.

    In string patterns %x is a hexadecimal. The wiki doesn't document that you can use this for os.date


  • Questions:

    How do I create a function like pairs() ? (I wish to make a function that can iterate through a userdata/table's metatable)

    Nevermind about the above, this article (https://www.lua.org/pil/7.3.html) just helped with that

    How do I convert the PlaybackSpeed property of Sound instances to musical notes?


  • @Cvieyra2test you don't, use playbackloudness instead lol


  • @Cvieyra2test You could use Game Hero's Midi Player as a reference. :p


  • @Fifkee reee that's how I'd do cool visual things like https://www.roblox.com/games/187659887/Audio-Visualizer

    @TheAlphaStigma Ooo thanks!

    The idea of me getting these notes 'n stuff is to create something actually similar to it.

    With PlayAudio, I plan to make a lengthy piece of audio that contains numerous instruments. And then, with those instruments, create something that people can make audio with. However I will certainly look into this Midi player for definite reference in both note definition and how I'd have my thing work out as well. I'm curious how they managed to do it on Studio, since you can't modify noises that are played in Roblox Studio, unless you can?


  • @Cvieyra2test

    How do I create a function like pairs() ? (I wish to make a function that can iterate through a userdata/table's metatable)

    pairs doesn't actually do much work other than return. It is literally written as

    function pairs(t)
        return next, t, nil
    end
    

    So when pairs is called on each iteration it's really next doing all the work.

    With this knowledge in mind you can get the metatable like this

    local function traverseMetatable(object)
        local mt = getmetatable(object);
    
        if (rawequal(type(mt), "table")) then --// there is a metatable
            return next, mt, nil;
        end
    end
    
Log in to reply
 

Looks like your connection to Scripting Helpers was lost, please wait while we try to reconnect.