of     1   

WoolHat
#228301963Friday, December 01, 2017 9:19 PM GMT

I'm trying to make a custom Humanoid class. If you're going to tell me that classes/metatables are useless, that's nice; I'd still like to test this out for myself. Things in this setup work fine, with the exception being: When I call the method :GetChildren(), which then indexes ModuleScript object's table of properties, I get the error saying that ":" was not used, but "." was. I'd like to find out why this error is appearing, and if there's a way to fix it. local Humanoid = {} local HumanoidData = { Name = "Humanoid", CameraOffset = Vector3.new(0,0,0), Health = 100, MaxHealth = 100, JumpPower = 50, WalkSpeed = 16, Jump = false, TakeDamage = function(self,Damage) self.Health = self.Health - Damage end } do local CustomProperties = setmetatable(HumanoidData, {__index=script}) --If property isn't in HumanoidData, look through ModuleScript Humanoid = setmetatable({},{__index=CustomProperties}) --If property isn't in {}, look through CustomProperties end print(Humanoid.Archivable)--Prints the ModuleScript's True archivable value Humanoid:TakeDamage(5)--Successfully decrements the health by 5 Humanoid:GetChildren()--"Expected ':' not '.' calling member function GetChildren" return Humanoid
cntkillme
#228303943Friday, December 01, 2017 10:12 PM GMT

The problem is your fake humanoid object is being propogated as the “self” to the real GetChildren method. So it ends up doing script.GetChildren(fakeHumamoid) and since it isn’t an actual instance Roblox just spits out that error since self isn’t an instance. To solve this you’d have to do something like __index = function(self, key) local value = CustomProperties[key] if type(value) == “function” then return function(_, ..,) return value(realHumanoid, ...) end end end You should probably have it fallback to the real humanoid instead of script but oh well.
WoolHat
#228315658Saturday, December 02, 2017 4:23 AM GMT

I edited it to follow your recommended code, but it still yields the same error. Question before I paste the new code: How would it be able to search the the script object before searching through the table of properties? setmetatable takes only table arguments, as opposed to objects. Updated code: local Humanoid = {} local HumanoidData = { Name = "Humanoid", Health = 100, MaxHealth = 100, JumpPower = 50, WalkSpeed = 16, Jump = false, TakeDamage = function(self,Damage) self.Health = self.Health - Damage end } do local ModuleProperties = setmetatable({ },{__index = script}) Humanoid = setmetatable(HumanoidData,{ __index = function(self, key) local ModuleProperty = ModuleProperties[key] if type(ModuleProperty) == "function" then return function(_,...) return ModuleProperty(HumanoidData,...) end end end }) end print(Humanoid.Archivable)--Prints the ModuleScript's True archivable value Humanoid:TakeDamage(5)--Successfully decrements the health by 5 Humanoid:GetChildren()--"Expected ':' not '.' calling member function GetChildren" return Humanoid
cntkillme
#228315830Saturday, December 02, 2017 4:30 AM GMT

No you implemented it wrong, you're still passing a FAKE OBJECT to a REAL ROBLOX METHOD. Read what I put. If you want to index script first, create an object to force __index to fire then just index the script first (with pcall in the case the member doesn't exist).
WoolHat
#228365484Sunday, December 03, 2017 5:25 AM GMT

Did it! Here's my resulting code, for anyone who may take use of it later on. If there are any recommendations/issues you find, I'd like to know so I can try to fix them. local Humanoid = {} local HumanoidData = { Name = "Humanoid", Health = 100, MaxHealth = 100, JumpPower = 50, WalkSpeed = 16, Jump = false, TakeDamage = function(self,Damage) self.Health = self.Health - Damage end } do setmetatable(HumanoidData,{ --Checks for properties in the fake humanoid __index = function(self,key)--Function only runs after HumanoidData turns out to not have any results error(key.." is not a valid member of Humanoid") end }) Humanoid = setmetatable({},{ __index = function(self, key) local ModulePropertyFound,ModuleProperty = pcall(function() return script[key] end) if ModulePropertyFound or ModulePropertyFound then if type(ModuleProperty) == "function" then --Check for methods of the fake humanoid return function(_,...) return ModuleProperty(script,...) --pass arguments appropriately end else return ModuleProperty end else local HumanoidProperty = HumanoidData[key] return HumanoidProperty end end }) end print(Humanoid.Parent)--Prints the ModuleScript's True archivable value print(Humanoid.Health) Humanoid:TakeDamage(5)--Successfully decrements the health by 5 print(Humanoid.Health) print(unpack(Humanoid:GetChildren()))--Prints all children of the modulescript/fake humanoid print(Humanoid.Jump) print(Humanoid.yy) return Humanoid
Dollar500
#228365579Sunday, December 03, 2017 5:28 AM GMT

So, what exactly is this for? Humanoids are already part of roblox...
WoolHat
#228365874Sunday, December 03, 2017 5:39 AM GMT

Well, the Humanoids are conflicting with me for a certain project I'm working on. So I'm creating my own humanoid, with its own properties. All this code is in a ModuleScript called "Humanoid", which would go in a character model in place of a regular Humanoid. When the module is required, it returns a table that acts as a Humanoid, with all of the properties that I want it to have. In the code I put above, the humanoid has explicit properties of Humanoid.Health, Humanoid.Jump. But I can also use function default to the ModuleScript, like Humanoid:GetChildren(). Tl;dr when I need to rewrite every new Humanoid function, I'll give up
Dollar500
#228365931Sunday, December 03, 2017 5:41 AM GMT

Makes sense
gskw
#228370663Sunday, December 03, 2017 8:42 AM GMT

You should totally use the BaseLib/LiteLib from a project of Crescent Code whose name can't be posted on Roblox (Norse god). It will help you do this.

    of     1