I accept everyone’s opinion! Be tough on me, so I can take into account what I need to improve.
--SUPERCLASS GUN
type Gun = {
name: string,
tool: Tool,
damage: number,
ammunition: number,
max_ammunition: number,
player: Player,
reloadTime: number,
reloadState: boolean,
equippedState: boolean
}
local ContextActionService = game:GetService("ContextActionService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
--On ReplicatedStorage
local Contents = ReplicatedStorage.Contents
local Events = ReplicatedStorage.Events
--On Contents
local Enums = require(Contents.Enums.Enums)
--On Events
local gunEvent = Events.GunEvent
--Function
local function getInstanceByShootRayCast(self: Gun, mousePosition: Vector3): Instance
local shootPart = self.tool.Shoot:: BasePart
local direction = (mousePosition - shootPart.Position).Unit*300
local result = workspace:Raycast(shootPart.Position, direction)
if result then
return result.Instance
end
end
local function takeDamage(instance: Instance, damage: number)
local humanoid = instance.Parent:FindFirstChild("Humanoid"):: Humanoid
if humanoid then
humanoid:TakeDamage(damage)
end
end
--Abstract Class
local Gun = {}
function Gun:extends(otherClass): self
self.__index = self
return setmetatable(otherClass, self)
end
function Gun:onEquipped()
if self:isEquipped() then return end
self.equippedState = true
gunEvent:FireClient(self.player, Enums.GunEvent.Equipped, self.name, self.ammunition, self.max_ammunition)
end
function Gun:onUnequipped()
if not self:isEquipped() then return end
self.equippedState = false
gunEvent:FireClient(self.player, Enums.GunEvent.Unequipped)
end
function Gun:shoot(mousePosition: Vector3) -- PRESS MOUSEBUTTON1CLICK
if self:isReload() then return end
if mousePosition and self.ammunition > 0 then
local instance = getInstanceByShootRayCast(self, mousePosition)
self.ammunition -= 1
if instance then
takeDamage(instance, self.damage)
end
gunEvent:FireClient(self.player, Enums.GunEvent.Shoot, self.ammunition, self.max_ammunition)
gunEvent:FireClient(self.player, Enums.GunEvent.Animation)
end
print(self.ammunition)
end
function Gun:reload() --PRESS R
if self:isReload() then return end
if self.ammunition < self.max_ammunition then
self.reloadState = true
print("In Reloading...")
task.wait(self.reloadTime)
print("Reload !")
self.ammunition = self.max_ammunition
self.reloadState = false
gunEvent:FireClient(self.player, Enums.GunEvent.Reload, self.ammunition, self.max_ammunition)
else -- TEMPORAIRE !!!
print("You cant reload !")
end
end
function Gun:isEquipped(): boolean
return self.equippedState
end
function Gun:isReload(): boolean
if not self:isEquipped() then return end
return self.reloadState
end
export type self = typeof(Gun:extends(...))
return Gun
--SUB CLASS PISTOLET
local ServerStorage = game:GetService("ServerStorage")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Contents = ServerStorage.Contents
local Package = ReplicatedStorage.Package
local Gun = require(Contents.Gun.Gun)
local Guns = Package.Guns
local subGun = {}
function subGun.new(player: Player)
local self = setmetatable({}, {
__index = Gun
})
self.name = script.Name
self.tool = Guns:FindFirstChild(script.Name):Clone()
self.damage = 10
self.ammunition = 24
self.max_ammunition = 24
self.player = player
self.reloadTime = 2.25
self.reloadState = false
self.equippedState = false
Gun:extends(self)
return self
end
return subGun
--Enums module
local Enums = {
GunEvent = {
Mouse = "Mouse",
Shoot = "Shoot",
Reload = "Reload",
Animation = "Animation",
Equipped = "Equipped",
Unequipped = "Unequipped"
},
GunAction = {
ShootAction = "ShootAction",
ReloadAction = "ReloadAction"
},
}
export type Enums = typeof(Enums)
return Enums
SCRIPT GUN SERVER
local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerContents = ServerStorage.Contents
local ReplicatedContents = ReplicatedStorage.Contents
local Guns = ServerContents.Gun.Guns
local Events = ReplicatedStorage.Events
local Player = require(ServerContents.Player.Player)
local Enums = require(ReplicatedContents.Enums.Enums)
local gunEvent = Events.GunEvent
local currentGunObject = nil
local function onGunEvent(player: Player, action: string, arg)
if action == Enums.GunEvent.Shoot then
currentGunObject:shoot(arg)
elseif action == Enums.GunEvent.Reload then
currentGunObject:reload()
end
end
--Players.PlayerAdded:Connect(onPlayerAdded)
gunEvent.OnServerEvent:Connect(onGunEvent)
Client GUN
if not game:IsLoaded() then game.Loaded:Wait() end
local ContextActionService = game:GetService("ContextActionService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Contents = ReplicatedStorage.Contents
local Events = ReplicatedStorage.Events
local Package = ReplicatedStorage.Package
local Enums = require(Contents.Enums.Enums)
local Guns = Package.Guns
local gunEvent = Events.GunEvent
local player = game.Players.LocalPlayer
local playerGui = player.PlayerGui
local mouse = player:GetMouse()
local character = player.Character
local humanoid = character.Humanoid:: Humanoid
local animator = humanoid.Animator:: Animator
local container = playerGui.PlayerGui.Container
local gunFrame = container.Gun
local viewPortFrame = gunFrame.ViewportFrame
local gunName = gunFrame.GunName
local ammunitionText = gunFrame.Ammunition
local viewPortCamera = Instance.new("Camera")
local shootAnimation = script.Shoot
local canPlayAnimation = true
viewPortCamera.Parent = viewPortFrame
local function playAnimation(animation: Animation, waitAnimationCompleted: boolean?)
if not canPlayAnimation then return end
local animationTrack = animator:LoadAnimation(animation):: AnimationTrack
animationTrack.Priority = Enum.AnimationPriority.Action
animationTrack:Play()
canPlayAnimation = false
if waitAnimationCompleted then
animationTrack.Stopped:Wait()
animationTrack:Stop()
end
canPlayAnimation = true
end
local function getMousePosition()
return mouse.Hit.Position
end
local function setViewPortFrame(handle)
viewPortCamera.CFrame = CFrame.new(Vector3.zero) * CFrame.Angles(0, 0, 0)
handle.CFrame = CFrame.new(Vector3.zero) * CFrame.Angles(0, math.rad(90), 0)
viewPortCamera.CameraSubject = handle
end
local function setGunName(name: string)
gunName.Text = name
end
local function setGunAmmunition(ammunition: number, maxAmmunition: number)
ammunitionText.Text = ammunition.."/"..maxAmmunition
end
local function onShoot(actionName, userInputState)
if userInputState == Enum.UserInputState.Begin and actionName == Enums.GunAction.ShootAction then
gunEvent:FireServer(Enums.GunEvent.Shoot, getMousePosition())
end
end
local function onReload(actionName, userInputState)
if userInputState == Enum.UserInputState.Begin and actionName == Enums.GunAction.ReloadAction then
gunEvent:FireServer(Enums.GunEvent.Reload)
end
end
local function setGunInfo(name: string, ammunition: number, maxAmmunition: number)
local gunTool = Guns:FindFirstChild(name)
if not gunTool then return end
local cloneHandle = gunTool:FindFirstChild("Handle"):Clone():: BasePart
gunFrame.Visible = true
cloneHandle.Parent = viewPortFrame
setViewPortFrame(cloneHandle)
setGunName(name)
setGunAmmunition(ammunition, maxAmmunition)
end
local function removeGunInfo()
local handle = viewPortFrame:FindFirstChild("Handle")
gunFrame.Visible = false
viewPortCamera.CameraSubject = nil
gunName.Text = "NIL"
ammunitionText.Text = "NIL"
if handle then
handle:Destroy()
end
end
local function setBindsAction()
ContextActionService:BindAction(Enums.GunAction.ShootAction, onShoot, true, Enum.UserInputType.MouseButton1)
ContextActionService:BindAction(Enums.GunAction.ReloadAction, onReload, true, Enum.KeyCode.R)
end
local function removeBindsAction()
ContextActionService:UnbindAction(Enums.GunAction.ShootAction)
ContextActionService:UnbindAction(Enums.GunAction.ReloadAction)
end
gunEvent.OnClientEvent:Connect(function(action, ...)
if action == Enums.GunEvent.Animation then
playAnimation(shootAnimation, true)
elseif action == Enums.GunEvent.Equipped then
print(...)
setGunInfo(...)
setBindsAction()
elseif action == Enums.GunEvent.Unequipped then
removeGunInfo()
removeBindsAction()
elseif action == Enums.GunEvent.Shoot or action == Enums.GunEvent.Reload then
setGunAmmunition(...)
end
end)