add towers / effects
This commit is contained in:
1 parent
3626379b23
commit
6000889ebf
3 files changed
+154
-2
No files matched your search
@@ -0,0 +1,42 @@
|
|||||||
|
local Tower = {}
|
||||||
|
Tower.__index = Tower
|
||||||
|
|
||||||
|
function Tower:new(model, position, range, damage, fireRate, effect)
|
||||||
|
local self = setmetatable({}, Tower)
|
||||||
|
self.model = model:Clone()
|
||||||
|
self.model.Position = position
|
||||||
|
self.model.Anchored = true
|
||||||
|
self.model.Parent = workspace
|
||||||
|
self.range = range
|
||||||
|
self.damage = damage
|
||||||
|
self.fireRate = fireRate or 1 -- shots per second
|
||||||
|
self.effect = effect -- set of params for effect
|
||||||
|
self.lastFire = 0
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
function Tower:canAttack(enemy)
|
||||||
|
if not enemy.alive or not enemy.model or not enemy.model.PrimaryPart then return false end
|
||||||
|
local dist = (self.model.Position - enemy.model.PrimaryPart.Position).Magnitude
|
||||||
|
return dist <= self.range
|
||||||
|
end
|
||||||
|
|
||||||
|
function Tower:attack(enemies, dt)
|
||||||
|
self.lastFire = self.lastFire + dt
|
||||||
|
if self.lastFire >= (1 / self.fireRate) then
|
||||||
|
for _, enemy in ipairs(enemies) do
|
||||||
|
if self:canAttack(enemy) then
|
||||||
|
enemy:damage(self.damage)
|
||||||
|
|
||||||
|
if self.effect then
|
||||||
|
enemy:applyEffect(self.effect.name, self.effect.params)
|
||||||
|
end
|
||||||
|
|
||||||
|
self.lastFire = 0
|
||||||
|
break -- Only attack one enemy per fire
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return Tower
|
||||||
+35
-1
@@ -7,12 +7,45 @@ function TrackEnemy:new(model, name, health, speed)
|
|||||||
self.model = model
|
self.model = model
|
||||||
self.name = name
|
self.name = name
|
||||||
self.health = health
|
self.health = health
|
||||||
|
self.baseSpeed = speed
|
||||||
self.speed = speed
|
self.speed = speed
|
||||||
self.alive = true
|
self.alive = true
|
||||||
self.currentWaypoint = 1
|
self.currentWaypoint = 1
|
||||||
|
self.effects = {}
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function TrackEnemy:applyEffect(effectName, params)
|
||||||
|
self.effects[effectName] = {
|
||||||
|
duration = params.duration,
|
||||||
|
tick = params.tick,
|
||||||
|
value = params.value,
|
||||||
|
elapsed = 0
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
function TrackEnemy:updateEffects(dt)
|
||||||
|
for name, effect in pairs(self.effects) do
|
||||||
|
effect.elapsed = effect.elapsed + dt
|
||||||
|
if name == "burn" and effect.tick then
|
||||||
|
if effect.elapsed >= effect.tick then
|
||||||
|
self:damage(effect.value)
|
||||||
|
effect.elapsed = effect.elapsed - effect.tick
|
||||||
|
end
|
||||||
|
elseif name == "slow" then
|
||||||
|
self.speed = self.baseSpeed * effect.value
|
||||||
|
elseif name == "freeze" then
|
||||||
|
self.speed = 0
|
||||||
|
end
|
||||||
|
|
||||||
|
effect.duration = effect.duration - dt
|
||||||
|
if effect.duration <= 0 then
|
||||||
|
self.effects[name] = nil
|
||||||
|
self.speed = self.baseSpeed
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function TrackEnemy:damage(amount)
|
function TrackEnemy:damage(amount)
|
||||||
self.health = self.health - amount
|
self.health = self.health - amount
|
||||||
if self.health <= 0 then
|
if self.health <= 0 then
|
||||||
@@ -28,7 +61,8 @@ function TrackEnemy:die()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Trackenemy:moveToWaypoints(waypoints, dt)
|
function TrackEnemy:moveToWaypoints(waypoints, dt)
|
||||||
|
self:updateEffects(dt)
|
||||||
if not self.currentWaypoint then self.currentWaypoint = 1 end
|
if not self.currentWaypoint then self.currentWaypoint = 1 end
|
||||||
local target = waypoints[self.currentWaypoint]
|
local target = waypoints[self.currentWaypoint]
|
||||||
if target then
|
if target then
|
||||||
|
|||||||
+77
-1
@@ -1,5 +1,41 @@
|
|||||||
local RunService = game:GetService("RunService")
|
local RunService = game:GetService("RunService")
|
||||||
|
local Tower = require(script.Parent.Tower)
|
||||||
local Waves = require(script.Parent.Waves)
|
local Waves = require(script.Parent.Waves)
|
||||||
|
|
||||||
|
local towerTypes = {
|
||||||
|
{
|
||||||
|
name = "Basic",
|
||||||
|
model = workspace.BasicTowerModel,
|
||||||
|
range = 20,
|
||||||
|
damage = 10,
|
||||||
|
fireRate = 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name = "Slow",
|
||||||
|
model = workspace.SlowTowerModel,
|
||||||
|
range = 15,
|
||||||
|
damage = 5,
|
||||||
|
fireRate = 0.5,
|
||||||
|
effect = {name = "slow", params = {duration = 2, value = 0.5}}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name = "Fire",
|
||||||
|
model = workspace.FireTowerModel,
|
||||||
|
range = 18,
|
||||||
|
damage = 8,
|
||||||
|
fireRate = 1,
|
||||||
|
effect = {name = "burn", params = {duration = 3, tick = 1, value = 2}}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name = "Freeze",
|
||||||
|
model = workspace.FreezeTowerModel,
|
||||||
|
range = 12,
|
||||||
|
damage = 0,
|
||||||
|
fireRate = 0.5,
|
||||||
|
effect = {name = "freeze", params = {duration = 1}}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
local waypoints = { -- Fill with your waypoint Parts
|
local waypoints = { -- Fill with your waypoint Parts
|
||||||
workspace.Waypoint1,
|
workspace.Waypoint1,
|
||||||
workspace.Waypoint2,
|
workspace.Waypoint2,
|
||||||
@@ -7,8 +43,13 @@ local waypoints = { -- Fill with your waypoint Parts
|
|||||||
-- etc.
|
-- etc.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
local selectedTowerType = towerTypes[1]
|
||||||
local enemies = {} -- Table to hold TrackEnemy objects
|
local enemies = {} -- Table to hold TrackEnemy objects
|
||||||
|
local towers = {}
|
||||||
|
|
||||||
|
function selectTowerType(index)
|
||||||
|
selectedTowerType = towerTypes[index]
|
||||||
|
end
|
||||||
|
|
||||||
local function spawnWave(waveData)
|
local function spawnWave(waveData)
|
||||||
coroutine.wrap(function()
|
coroutine.wrap(function()
|
||||||
@@ -17,6 +58,7 @@ local function spawnWave(waveData)
|
|||||||
local enemyModel = group.model:Clone()
|
local enemyModel = group.model:Clone()
|
||||||
enemyModel.Parent = workspace
|
enemyModel.Parent = workspace
|
||||||
local enemy = TrackEnemy:new(enemyModel, group.name, group.health, group.speed)
|
local enemy = TrackEnemy:new(enemyModel, group.name, group.health, group.speed)
|
||||||
|
table.insert(enemies, enemy)
|
||||||
end
|
end
|
||||||
|
|
||||||
if group.delay and group.delay > 0 then
|
if group.delay and group.delay > 0 then
|
||||||
@@ -28,6 +70,40 @@ end
|
|||||||
|
|
||||||
spawnWave(Waves[1])
|
spawnWave(Waves[1])
|
||||||
|
|
||||||
|
local function isOnTrack(position)
|
||||||
|
for _, waypoint in ipairs(waypoints) do
|
||||||
|
if (waypoint.Position - position).Magnitude < 5 then -- 5 studs
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
UserInputService.InputBegan:Connect(function (input, gameProcessed)
|
||||||
|
if gameProcessed then return end
|
||||||
|
if input.UserInputType == Enum.UserInputType.MouseButton1 then
|
||||||
|
local mouse = game.Players.LocalPlayer():GetMouse()
|
||||||
|
local position = mouse.Hit.p
|
||||||
|
if not isOnTrack(position) then
|
||||||
|
local tower = Tower:new(
|
||||||
|
selectedTowerType.model,
|
||||||
|
position,
|
||||||
|
selectedTowerType.range,
|
||||||
|
selectedTowerType.damage,
|
||||||
|
selectedTowerType.fireRate,
|
||||||
|
selectedTowerType.effect
|
||||||
|
)
|
||||||
|
table.insert(towers, tower)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
RunService.Heartbeat:Connect(function(dt)
|
||||||
|
for _, tower in ipairs(towers) do
|
||||||
|
tower:attack(enemies, dt)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
RunService.Heartbeat:Connect(function(dt)
|
RunService.Heartbeat:Connect(function(dt)
|
||||||
for i, enemy in ipairs(enemies) do
|
for i, enemy in ipairs(enemies) do
|
||||||
if enemy.alive then
|
if enemy.alive then
|
||||||
|
|||||||
Reference in new issue
Block a user