So basically I am new to using OOP and I am running into an issue where the self variables I’m defining in my constructor function are being forgotten in other methods.
This is my first time writing my own OOP class, however I have used classes made by other developers in the past and I just don’t know where I’m going wrong. I’ve compared my class to others but I can’t figure out why mine is forgetting variables.
The variable I’m specifically having a problem with right now is the self.Type variable, however this is an issue with every single self variable I try to define in the constructor. self.Type stores the name of the type of gun being used. It is supposed to use that to find the config settings for that specific gun in another module I’m using to store config data.
Here is some snippets of my code (this isn’t the whole script just what is necessary to see):
local Gun = {}
Gun.__index = Gun
function Gun.new(player, gunType)
local self = setmetatable({}, Gun)
self.Owner = player
self.Type = gunType
print(self.Type) -- correctly prints what it's supposed to here which is "AK-47"
self.CurrentMode = 1
return self
end
function Gun:Fire(player, mousePos, tool)
local origin = tool.Handle.FirePoint.WorldPosition
local dir = (mousePos - origin).Unit
print(self.Type, GunConfig[self.Type]) -- prints "nil, nil" here
self.Caster:Fire(origin, dir, GunConfig[self.Type].BulletVelocity, self.CastBehavior)
end
The line where I’m getting the error is the last one and specifically where it says:
GunConfig[self.Type].BulletVelocity
This is the error I get:
Btw, the “self.Caster” was also originally defined in the constructor function and it didn’t recognize it but when I moved it to the :Init() function it started working. Hopefully that maybe helps anyone trying to figure out my problem.
Maybe I’m missing something very obvious but like I said I am still new to this so any help would be greatly appreciated!
(also I hope I used my OOP terminology in the correct context lol, feel free to correct any terminology mistakes)
Edit: Since it will probably help I’ll just put the entire module here at the bottom
--//Services
local rep = game:GetService("ReplicatedStorage")
local debris = game:GetService("Debris")
--//References
local modules = rep.Modules
local dataModules = modules.Data
local mainModules = modules.Main
local remotes = rep.Remotes
--//Modules
local GunConfig = require(dataModules.GunConfig)
local FastCast = require(mainModules.FastCastRedux)
--//Remotes
local fireRE = remotes.Weapons.Fire
FastCast.VisualizeCasts = false
--//Class
local Gun = {}
Gun.__index = Gun
local function CreateBulletsFolder()
local bulletsFolder = workspace:FindFirstChild("BulletFolder")
or Instance.new("Folder", workspace)
bulletsFolder.Name = "BulletFolder"
return bulletsFolder
end
function Gun.new(player, gunType)
local self = setmetatable({}, Gun)
self.Owner = player
self.Type = gunType
print(self.Type)
self.CurrentMode = 1
return self
end
function Gun:Init()
self.Caster = FastCast.new()
self.BulletFolder = CreateBulletsFolder()
self.CosmeticBullet = self:CreateBulletTemplate()
self.CastParams = self:CreateCastParams()
self.CastBehavior = self:CreateCastBehavior()
self:MakeConnections()
end
function Gun:CreateBulletTemplate()
local bulletTemplate = Instance.new("Part")
bulletTemplate.Anchored = true
bulletTemplate.CanCollide = false
bulletTemplate.Shape = "Ball"
bulletTemplate.Size = Vector3.new(1, 1, 1)
bulletTemplate.Material = Enum.Material.SmoothPlastic
return bulletTemplate
end
function Gun:CreateCastParams()
local castParams = RaycastParams.new()
castParams.FilterType = Enum.RaycastFilterType.Blacklist
castParams.IgnoreWater = true
return castParams
end
function Gun:CreateCastBehavior()
local castBehavior = FastCast.newBehavior()
castBehavior.RaycastParams = self.CastParams
castBehavior.Acceleration = Vector3.new(0, -workspace.Gravity, 0)
castBehavior.AutoIgnoreContainer = false
castBehavior.CosmeticBulletContainer = self.BulletFolder
castBehavior.CosmeticBulletTemplate = self.CosmeticBullet
return castBehavior
end
function Gun:ToggleFireMode()
local modes = GunConfig[self.Type].FireMode
self.CurrentMode += 1
if self.CurrentMode > #modes then
self.CurrentMode = 1
end
return modes[self.CurrentMode]
end
function Gun:SimulateProjectile(cast, lastPoint, dir, length, velocity, bullet)
if bullet then
local bulletLength = bullet.Size.Z/2
local offset = CFrame.new(0, 0, -(length - bulletLength))
bullet.CFrame = CFrame.lookAt(lastPoint, lastPoint + dir):ToWorldSpace(offset)
end
end
function Gun:OnHit(cast, result, velocity, bullet)
local hit = result.Instance
local character = hit:FindFirstAncestorWhichIsA("Model")
if character and character:FindFirstChild("Humanoid") then
character.Humanoid:TakeDamage(10)
end
debris:AddItem(bullet, 2)
end
function Gun:Fire(player, mousePos, tool)
local origin = tool.Handle.FirePoint.WorldPosition
local dir = (mousePos - origin).Unit
print(self.Type, GunConfig[self.Type])
self.Caster:Fire(origin, dir, GunConfig[self.Type].BulletVelocity, self.CastBehavior)
end
function Gun:FilterInstances(tool)
self.CastParams.FilterDescendantsInstances = {tool.Parent, self.BulletFolder}
end
function Gun:MakeConnections()
fireRE.OnServerEvent:Connect(function(player, mousePos, tool)
self:Fire(player, mousePos, tool)
end)
self.Caster.LengthChanged:Connect(function(cast, lastPoint, dir, length, velocity, bullet)
self:SimulateProjectile(cast, lastPoint, dir, length, velocity, bullet)
end)
self.Caster.RayHit:Connect(function(cast, result, velocity, bullet)
self:OnHit(cast, result, velocity, bullet)
end)
end
return Gun