Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local Players = game:GetService("Players")
- local RunService = game:GetService("RunService")
- local HttpService = game:GetService("HttpService")
- local ReplicatedStorage = game:GetService("ReplicatedStorage")
- local ServerScriptService = game:GetService("ServerScriptService")
- local IS_SERVER = RunService:IsServer()
- local Signal = require(ReplicatedStorage.Libs.Signal)
- local Trove = require(ReplicatedStorage.Libs.Trove)
- local DamageManager = require(ReplicatedStorage.Modules.DamageManager)
- local ProjectileTypes = require(script.ProjectileTypes)
- local ProjectileManager = {}
- ProjectileManager.MaxHitTimeDifference = 0.3
- ProjectileManager.MaxHitPositionDifference = 10
- ProjectileManager.ProjectileAdded = Signal.new()
- ProjectileManager.ProjectileHits = {}
- ProjectileManager.Projectiles = {}
- function ProjectileManager.CreateId()
- return HttpService:GenerateGUID(false)
- end
- -- the projectile properties can be different from a projectile to projectile
- -- but they all most of the times have a few things in common
- -- such as StartTime, StartCFrame or TargetPosition
- function ProjectileManager.CreateProjectile(projectileProperties)
- if not projectileProperties.Id then
- projectileProperties.Id = ProjectileManager.CreateId()
- end
- if ProjectileManager.Projectiles[projectileProperties.Id] then
- return nil
- end
- local projectileClass = ProjectileTypes[projectileProperties.Type]
- local projectile = projectileClass.new(projectileProperties)
- projectile.Removing:Connect(function()
- ProjectileManager.Projectiles[projectileProperties.Id] = nil
- end)
- projectile.Hit:Connect(function(hit)
- if IS_SERVER then
- if projectileProperties.Shooter then
- ProjectileManager.ProjectileHits[projectileProperties.Id] = {
- Hit = hit,
- HitTime = workspace:GetServerTimeNow(),
- HitPosition = projectile.Position,
- Properties = projectileProperties,
- }
- end
- elseif projectileProperties.Shooter == Players.LocalPlayer then
- script.ProjectileHit:FireServer(
- projectileProperties.Id,
- projectile.Position,
- workspace:GetServerTimeNow(),
- hit
- )
- end
- end)
- ProjectileManager.ProjectileAdded:Fire(projectile)
- ProjectileManager.Projectiles[projectileProperties.Id] = projectile
- if IS_SERVER then
- script.ProjectileCreated:FireAllClients(projectileProperties)
- end
- return projectile
- end
- if IS_SERVER then
- script.GetProjectiles.OnServerInvoke = function(player)
- local projectilesProperties = {}
- for _, projectile in ProjectileManager.Projectiles do
- table.insert(projectilesProperties, projectile.Properties)
- end
- return projectilesProperties
- end
- script.ProjectileHit.OnServerEvent:Connect(function(player, id, hitPosition, hitTime, hit)
- local hitData = ProjectileManager.ProjectileHits[id]
- if
- not hitData
- or hitData.Properties.Shooter ~= player
- or hitData.Hit ~= hit
- then
- return
- end
- local timeDifference = math.abs(hitData.HitTime - hitTime)
- if timeDifference > ProjectileManager.MaxHitTimeDifference then
- return
- end
- local positionDifference = (hitPosition - hitData.HitPosition).Magnitude
- if positionDifference > ProjectileManager.MaxHitPositionDifference then
- return
- end
- DamageManager.ApplyDamage(
- hitData.Properties.Damage,
- hit,
- player
- )
- end)
- else
- script.ProjectileCreated.OnClientEvent:Connect(ProjectileManager.CreateProjectile)
- end
- return ProjectileManager
- local RunService = game:GetService("RunService")
- local ReplicatedStorage = game:GetService("ReplicatedStorage")
- local Signal = require(ReplicatedStorage.Libs.Signal)
- local Trove = require(ReplicatedStorage.Libs.Trove)
- local IS_CLIENT = RunService:IsClient()
- local Bullet = {}
- Bullet.__index = Bullet
- local function createInstance()
- local instance = script.BulletTemplate:Clone()
- instance.Name = "sigma"
- instance.Parent = workspace
- return instance
- end
- function Bullet.new(projectileProperties)
- local self = setmetatable({}, Bullet)
- self.Properties = projectileProperties
- self.Position = projectileProperties.StartPosition
- self.StartTime = projectileProperties.StartTime or workspace:GetServerTimeNow()
- self.Params = projectileProperties.Params or RaycastParams.new()
- self.Speed = projectileProperties.Speed or 50
- if IS_CLIENT then
- self.Instance = createInstance()
- end
- self.Hit = Signal.new()
- self.Removing = Signal.new()
- self.Removing:Connect(function()
- self.Instance:Destroy()
- end)
- local distance =
- (projectileProperties.StartPosition
- - projectileProperties.TargetPosition).Magnitude
- self.Lifetime = distance / self.Speed
- return self
- end
- function Bullet:Update(_deltaTime)
- local timePassed = workspace:GetServerTimeNow() - self.StartTime
- local timePercentage = timePassed / self.Lifetime
- if timePercentage > 1 then
- self.Removing:Fire()
- return
- end
- local lastPosition = self.Position
- local currentPosition = self.Properties.StartPosition:Lerp(self.Properties.TargetPosition, timePercentage)
- local direction = currentPosition - lastPosition
- local result = workspace:Raycast(
- lastPosition,
- direction,
- self.Params
- )
- if result then
- self.Position = result.Position
- self.Hit:Fire(result.Instance)
- self.Removing:Fire()
- return
- end
- self.Position = lastPosition
- if self.Instance then
- self.Instance.Position = self.Position
- end
- end
- return Bullet
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement