Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --!strict
- --!optimize 2
- --[[
- This Lua script is designed for Roblox while basing a mini shooting game off of a shotgun (considered to be an XM1014). Russia's role of "Roulette" is reserved for two individual players (as well as a player and NPC). The contestants take turns at either shooting themselves or pointing the gun towards the other player. The code does declare a class "Buckshoot" that does care for all the game logic; the set-up of the game, managing ammo, shooting, updating the GUI, and when it’s over. Each time a new instance from the new function is created for a new game, it gives the two players no ammo and sets the AI default health to 100. The StartGame function chooses a random player; the original player is set as the owner. The original player is set before giving 1 to five real bullets, then the rest of the ten available bullets are filled with blanks. When the two players are real users (and not AI), and the script makes some extensions in their GUI, the names of the players are shown through PlayerGui and a remote event is sent to change the camera view with client-side visuals. Some RemoteEvents that the game servers include are StartEvent, SHOOT EVENT, and InitEvent for coordinating mission behavior between server and client. A 3D copy of the weapon is kept in game space and can be referenced through a specific position.
- The AddAmmo and RemoveAmmo functions, as well as the SmartRemoveAmmo function, dynamically control the ammo during gameplay. When the bullet is “shot,” the system checks the existence of the bullet and performs the necessary actions: inflicting damage, executing a visual effect, and seamlessly ending the game if required. Other services in Roblox are used, including TweenService and Debris, for animation and deletion of game objects. Overall, the script is a chance based, suspenseful shooting game with tactical elements mingled in.
- ]]
- local Buckshoot = {}
- Buckshoot.__index = function(self, key)
- return Buckshoot[key]
- end
- Buckshoot.__newindex = function(t, k, v)
- if k == "Owner" then print("Old Value:", v) end
- return rawset(t, k, v)
- end
- --// Export Type
- export type Plr = Player | "AI"
- export type AmmoType = "Real" | "Blank"
- export type ShootType = "Ennemy" | "Himself"
- export type AmmoTable = {
- ["Real"]: number,
- ["Blank"]: number,
- }
- export type AIstats = {
- ["Health"]: number,
- }
- export type BuckshootClass = {
- Players: {Plr},
- Owner: Player?,
- Ammo: AmmoTable,
- AIstats: AIstats,
- AI: boolean,
- new: (Player1: Plr, Player2: Plr, Owner: Player?) -> BuckshootClass,
- EndGame: (self: BuckshootClass) -> (),
- StartGame: (self: BuckshootClass) -> (),
- AddAmmo: (self: BuckshootClass, type: AmmoType, amount: number) -> (),
- RemoveAmmo: (self: BuckshootClass, type: AmmoType, amount: number) -> (),
- GetRandomPlayer: (self: BuckshootClass) -> Plr,
- GetRealPlayer: (self: BuckshootClass) -> (Player, number),
- ShootEvent: (self: BuckshootClass, Type: ShootType) -> (),
- SmartRemoveAmmo: (self: BuckshootClass, mode: string) -> AmmoType?,
- GetEnnemy: (self: BuckshootClass) -> Plr,
- }
- --// Service:
- local ReplicatedStorage = game:GetService("ReplicatedStorage")
- local TweenService = game:GetService("TweenService")
- local Debris = game:GetService("Debris")
- --// RemoteEvent
- local StartEvent = ReplicatedStorage.StartEvent
- local ShootEvent = ReplicatedStorage.ShootEvent
- local InitEvent = ReplicatedStorage.InitPlayerEvent
- --// Model Variable
- local ShotgunModel = workspace.table.Gun["Meshes/XM1014"]
- local BasePosition = CFrame.new(-3.49698067, 3.09959221, -19.2551651, 0, 0.707106948, 0.707106948, -1, 0, 0, 0, -0.707106948, 0.707106948)
- --// Player Stats
- local RevHealth = 100/3 -- is for 3 life for the player
- --// Func New
- function Buckshoot.new(Player1: Player, Player2: Player, Owner: Player?): BuckshootClass
- local self = setmetatable({}, Buckshoot) :: BuckshootClass
- self.Players = {Player1, Player2}
- self.Owner = Owner or nil
- self.AI = false
- self.Ammo = {["Real"] = 0, ["Blank"] = 0}
- self.AIstats = {["Health"] = 100}
- return self
- end
- --// Func StartGame
- function Buckshoot:StartGame()
- --// Init of the game
- --// Creating Stats
- self.Owner = self.Owner or self:GetRandomPlayer()
- self:AddAmmo("Real", math.random(1, 5))
- self:AddAmmo("Blank", 10-self.Ammo.Real)
- if not (self.Players[1] == "AI" or self.Players[2] == "AI") then
- --// Visual Effect
- local Players = self.Players :: {Player}
- for i, player in ipairs(Players) do
- local targetGui1 = player.PlayerGui:FindFirstChild("PlrGui1")
- local targetGui2 = player.PlayerGui:FindFirstChild("PlrGui2")
- if targetGui1 and targetGui2 then
- targetGui1.TextLabel.Text = player.Name
- targetGui2.TextLabel.Text = Players[i % #Players + 1].Name
- end
- end
- StartEvent:FireAllClients(true) --\\ Camera Setup (why allClient? because the server is limited to 2 player)
- end
- local index = table.find(self.Players, "AI")
- if index then
- local AIplayer = self.Players[index] :: string
- local RealPlayer: Player, IndexPlr: number = self:GetRealPlayer()
- --// Visual Effect
- RealPlayer.PlayerGui["PlrGui"..IndexPlr].TextLabel.Text = RealPlayer.Name
- RealPlayer.PlayerGui["PlrGui"..index].TextLabel.Text = AIplayer
- local textLab = workspace.table.AmmoGui.SurfaceGui.BillboardGui.TextLabel
- textLab.Text = "Real Bullets: " .. self.Ammo.Real .. "\nBlank Bullets: " .. self.Ammo.Blank
- task.spawn(function()
- task.wait(5)
- textLab.Text = ""
- end)
- StartEvent:FireClient(RealPlayer, true) --\\ Camera Setup
- end
- task.wait(.5)
- if self.Owner == "AI" then
- self:ShootEvent()
- end
- --print("Le jeu commence! Propri�taire: " .. self.Owner.Name)
- end
- --// Func EndGame
- function Buckshoot:EndGame()
- local Players = self.Players :: {Plr}
- for i, player in ipairs(Players) do
- if player ~= "AI" then
- local Humanoid = player.Character.Humanoid :: Humanoid
- local PlayerGui = player.PlayerGui :: PlayerGui
- if Humanoid.Health == 0 then continue end
- -- Reset Camera:
- StartEvent:FireClient(player, false)
- --Reset PlrGui:
- local targetGui1 = PlayerGui:FindFirstChild("PlrGui1").TextLabel :: TextLabel
- local targetGui2 = PlayerGui:FindFirstChild("PlrGui2").TextLabel :: TextLabel
- if targetGui1 and targetGui2 then
- targetGui1.Text = ""
- targetGui2.Text = ""
- end
- --Reset Player's stat
- Humanoid.WalkSpeed = 16
- Humanoid.JumpPower = 50
- Humanoid.Health = 100
- -- Reset ProximityPrompt:
- for _, Proximity: ProximityPrompt in workspace.table.Players:GetDescendants() do
- if Proximity:IsA("ProximityPrompt") then
- Proximity.Enabled = true
- end
- end
- end
- end
- ShotgunModel.CFrame = BasePosition -- just incase the shotgun won't be at his basePosition
- end
- --// Func ShootEvent
- function Buckshoot:ShootEvent(Type: ShootType)
- local AI = self.AI :: boolean
- local UpPosition = BasePosition + Vector3.new(0, 5, 0)
- local index = table.find(self.Players, "AI") :: number
- local AIplayer = self.Players[index] :: string
- local Owner = self.Owner :: Player | string
- local OwnerHumanoid: Humanoid?
- local OwnerHead = Owner.Character and Owner.Character:FindFirstChild("Head")
- local Ennemy = self:GetEnnemy()
- local EnnemyHumanoid: Humanoid?
- local TweenInf = TweenInfo.new(0.5, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut)
- TweenService:Create(ShotgunModel, TweenInf, {CFrame = UpPosition}):Play()
- task.wait(1)
- local highlight = Instance.new("Highlight", ShotgunModel)
- highlight.Adornee = ShotgunModel
- highlight.OutlineColor = Color3.fromRGB(255, 255, 255)
- highlight.FillTransparency = 1
- if Type == "Ennemy" then
- local lookAt = CFrame.new(ShotgunModel.Position, OwnerHead.Position * Vector3.new(-1, 1, 1))
- TweenService:Create(ShotgunModel, TweenInf, {CFrame = lookAt}):Play()
- task.wait(1)
- local removedBullet = self:SmartRemoveAmmo("any")
- if removedBullet then
- local isReal = removedBullet == "Real"
- highlight.FillColor = isReal and Color3.new(1, 0, 0) or Color3.new(0.635294, 0.635294, 0.635294)
- highlight.FillTransparency = 0
- if isReal then
- EnnemyHumanoid = self:GetEnnemy().Character.Humanoid
- EnnemyHumanoid:TakeDamage(RevHealth)
- end
- end
- elseif Type == "Himself" then
- local lookAt = CFrame.new(ShotgunModel.Position, OwnerHead.Position)
- TweenService:Create(ShotgunModel, TweenInf, {CFrame = lookAt}):Play()
- task.wait(1)
- local removedBullet = self:SmartRemoveAmmo("any")
- if removedBullet then
- local isReal = removedBullet == "Real"
- highlight.FillColor = isReal and Color3.new(1, 0, 0) or Color3.new(0.635294, 0.635294, 0.635294)
- highlight.FillTransparency = 0
- if isReal then
- OwnerHumanoid = Owner.Character.Humanoid
- OwnerHumanoid:TakeDamage(RevHealth)
- end
- end
- end
- if AI and Owner == "AI" then
- local aiChoice: ShootType = (math.random(1, 2) == 1 and "Ennemy" or "Himself") :: ShootType
- local target = self:GetEnnemy().Character["Head"].Position :: Vector3
- local targetPosition = aiChoice == "Ennemy" and target or target * Vector3.new(-1, 1, 1)
- local lookAt = CFrame.new(ShotgunModel.Position, targetPosition)
- TweenService:Create(ShotgunModel, TweenInf, {CFrame = lookAt}):Play()
- task.wait(1)
- local removedBullet = self:SmartRemoveAmmo("any")
- local EnnemyHumanoid = Ennemy.Character.Humanoid :: Humanoid
- if removedBullet then
- local isReal = removedBullet == "Real"
- highlight.FillColor = isReal and Color3.new(1, 0, 0) or Color3.new(0.635294, 0.635294, 0.635294)
- highlight.FillTransparency = 0
- if isReal then
- if aiChoice == "Ennemy" then
- EnnemyHumanoid:TakeDamage(RevHealth)
- elseif aiChoice == "Himself" then
- self.AIstats.Health -= RevHealth
- end
- end
- end
- end
- Debris:AddItem(highlight, .5)
- TweenService:Create(ShotgunModel, TweenInf, {CFrame = BasePosition}):Play()
- self.Owner = Ennemy
- -- Check if one of the player die
- if not self.AI then
- if (OwnerHumanoid and OwnerHumanoid.Health == 0) or
- (EnnemyHumanoid and EnnemyHumanoid.Health == 0) then
- self:EndGame()
- return
- end
- elseif self.AI then
- local realPlayer, _ = self:GetRealPlayer()
- if (self.AIstats.Health <= 0) or
- (realPlayer.Character.Humanoid.Health == 0) then
- self:EndGame()
- return
- end
- end
- if self.Owner == "AI" then
- task.wait(1)
- self:ShootEvent()
- elseif self.Owner ~= "AI" then
- InitEvent:FireClient(self.Owner, self.Owner) -- make the Ennemy play
- end
- end
- function Buckshoot:AddAmmo(type: AmmoType, amount: number)
- assert(amount >= 0, "Amount must be non-negative")
- self.Ammo[type] = math.min(10, self.Ammo[type] :: number + amount)
- print(string.format("Ajout� %d munitions %s (Total: %d)", amount, type, self.Ammo[type]))
- end
- function Buckshoot:RemoveAmmo(type: AmmoType, amount: number)
- assert(amount >= 0, "Amount must be non-negative")
- self.Ammo[type] = math.max(0, self.Ammo[type] :: number - amount)
- print(string.format("Retir� %d munitions %s (Total: %d)", amount, type, self.Ammo[type]))
- end
- --// Func SmartRemoveAmmo
- function Buckshoot:SmartRemoveAmmo(mode: string): AmmoType?
- --// mode: "real", "blank", "any"
- local realAmmo = self.Ammo["Real"]
- local blankAmmo = self.Ammo["Blank"]
- local canRemoveReal = realAmmo > 0
- local canRemoveBlank = blankAmmo > 0
- if mode == "Real" and canRemoveBlank then
- self:RemoveAmmo("Blank", 1)
- return "Blank"
- elseif mode == "Blank" and canRemoveReal then
- self:RemoveAmmo("Real", 1)
- return "Real"
- elseif mode == "any" then
- local Options = {}
- if canRemoveReal then
- table.insert(Options, "Real")
- end
- if canRemoveBlank then
- table.insert(Options, "Blank")
- end
- if #Options > 0 then
- local Chosen = Options[math.random(1, #Options)] :: AmmoType
- self:RemoveAmmo(Chosen, 1)
- return Chosen
- end
- end
- -- Nil = no more ammo
- return nil
- end
- function Buckshoot:GetEnnemy(): Plr
- for _, p in pairs(self.Players) do
- if p ~= self.Owner then
- return p
- end
- end
- return self.Players[1] -- for error: Not all codepaths return 'Player'
- end
- function Buckshoot:GetRandomPlayer(): Plr
- return self.Players[math.random(1, 2)]
- end
- function Buckshoot:GetRealPlayer(): (Player, number)
- for _, p in ipairs(self.Players) do
- if p ~= "AI" then
- return p, _
- end
- end
- return self.Players[1], 0 -- for error: Not all codepaths return 'Player'
- end
- return Buckshoot
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement