WoolHat
|
  |
| Joined: 19 May 2013 |
| Total Posts: 1873 |
|
|
| 01 Dec 2017 03:19 PM |
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 |
|
|
| Report Abuse |
|
|
cntkillme
|
  |
| Joined: 07 Apr 2008 |
| Total Posts: 44956 |
|
|
| 01 Dec 2017 04:12 PM |
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. |
|
|
| Report Abuse |
|
|
WoolHat
|
  |
| Joined: 19 May 2013 |
| Total Posts: 1873 |
|
|
| 01 Dec 2017 10:23 PM |
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 |
|
|
| Report Abuse |
|
|
cntkillme
|
  |
| Joined: 07 Apr 2008 |
| Total Posts: 44956 |
|
|
| 01 Dec 2017 10:30 PM |
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). |
|
|
| Report Abuse |
|
|
WoolHat
|
  |
| Joined: 19 May 2013 |
| Total Posts: 1873 |
|
|
| 02 Dec 2017 11:25 PM |
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 |
|
|
| Report Abuse |
|
|
Dollar500
|
  |
| Joined: 12 Jan 2013 |
| Total Posts: 504 |
|
|
| 02 Dec 2017 11:28 PM |
| So, what exactly is this for? Humanoids are already part of roblox... |
|
|
| Report Abuse |
|
|
WoolHat
|
  |
| Joined: 19 May 2013 |
| Total Posts: 1873 |
|
|
| 02 Dec 2017 11:39 PM |
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 |
|
|
| Report Abuse |
|
|
Dollar500
|
  |
| Joined: 12 Jan 2013 |
| Total Posts: 504 |
|
| |
|
gskw
|
  |
| Joined: 05 Jan 2013 |
| Total Posts: 1364 |
|
|
| 03 Dec 2017 02:42 AM |
| 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. |
|
|
| Report Abuse |
|
|