| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164 |
- local Spell = class()
- function Spell:mirrorOwner()
- self.x, self.y, self.angle = self.owner.x, self.owner.y, self.owner.angle
- end
- function Spell:move(length, options)
- options = options or {}
- local x, y, angle = options.x or self.x, options.y or self.y, options.angle or self.angle
- self.x, self.y = x + math.dx(length, angle), y + math.dy(length, angle)
- end
- function Spell:movePlayerTo(player, x, y)
- player.x, player.y = x, y
- if player.inputs then
- table.insert(player.inputs, {
- tick = tick + 1,
- reposition = {
- x = player.x,
- y = player.y
- }
- })
- end
- end
- function Spell:movePlayer(player, length, options)
- options = options or {}
- local angle = options.angle or self.angle
- return Spell.movePlayerTo(self, player, player.x + math.dx(length, angle), player.y + math.dy(length, angle))
- end
- function Spell:moveOwnerTo(x, y)
- return Spell.movePlayerTo(self, self.owner, x, y)
- end
- function Spell:moveOwner(length, options)
- return Spell.movePlayer(self, self.owner, length, options)
- end
- function Spell:distanceTo(object, options)
- options = options or {}
- local x, y = options.x or self.x, options.y or self.y
- return math.distance(x, y, object.x, object.y)
- end
- function Spell:wallDistance(range)
- local x2, y2 = self.x + math.dx(range, self.angle), self.y + math.dy(range, self.angle)
- local wall, distance = ctx.collision:lineTest(self.x, self.y, x2, y2, {tag = 'wall', first = true})
- return wall and distance or range
- end
- function Spell:resolveCircle(x, y, r, options)
- options = options or {}
- local ox, oy = x, y
- local angle = options.angle or self.angle
- local sign = 1
- local distance = 0
- local function move() x, y = ox + math.dx(distance * sign, angle), oy + math.dy(distance * sign, angle) end
- while ctx.collision:circleTest(x, y, self.owner.radius, {tag = 'wall'}) or not math.inside(x, y, 0, 0, ctx.map.width, ctx.map.height) do
- sign = -sign
- if sign == 1 then distance = distance + 10 end
- move()
- end
- if distance > 0 or sign == -1 then
- repeat
- distance = distance - 1
- move()
- until ctx.collision:circleTest(x, y, self.owner.radius, {tag = 'wall'})
- distance = distance + 1
- move()
- end
- return x, y
- end
- function Spell:rot(fn)
- self.timer = self.timer - tickRate
- if self.timer <= 0 then
- f.exe(fn)
- ctx.spells:deactivate(self)
- return true
- end
- end
- function Spell:die()
- return ctx.spells:deactivate(self)
- end
- function Spell:enemiesInRadius(options)
- options = options or {}
- local x, y, r = options.x or self.x, options.y or self.y, options.radius or self.radius
- local function isEnemy(p) return p.team ~= self.owner.team end
- return ctx.collision:circleTest(x, y, r, {tag = 'player', fn = isEnemy, all = true})
- end
- function Spell:enemiesInLine(distance, options)
- options = options or {}
- local x, y, angle, all = options.x or self.x, options.y or self.y, options.angle or self.angle, options.all or false
- local x2, y2 = self.x + math.dx(distance, self.angle), self.y + math.dy(distance, self.angle)
- local function isEnemy(p) return p.team ~= self.owner.team end
- return select(1, ctx.collision:lineTest(x, y, x2, y2, {tag = 'player', fn = isEnemy, first = not all, all = all}))
- end
- function Spell:damage(enemies, amount)
- if not enemies then return end
- if enemies.id then enemies = {enemies} end
- amount = f.val(amount)
- table.each(enemies, function(enemy)
- ctx.net:emit(app.net.events.damage, {id = enemy.id, from = self.owner.id, amount = amount(enemy), tick = tick})
- end)
- end
- function Spell:damageInLine(distance, amount, options)
- Spell.damage(self, Spell.enemiesInLine(self, distance, options), amount)
- end
- function Spell:damageInRadius(amount, options)
- Spell.damage(self, Spell.enemiesInRadius(self, options), amount)
- end
- function Spell:lerpInit(vars)
- self._prev = {}
- if not vars then vars = {'x', 'y'} end
- for i = 1, #vars do self._prev[vars[i]] = 0 end
- end
- function Spell:lerpUpdate()
- table.each(self._prev, function(_, k) self._prev[k] = self[k] end)
- end
- function Spell:lerpGet(...)
- local res = {}
- local args = {...}
- if #args == 0 then args = {'x', 'y'} end
- table.each(args, function(x)
- table.insert(res, math.lerp(self._prev[x], self[x], tickDelta / tickRate))
- end)
- return unpack(res)
- end
- function Spell:drawCircle(how, options)
- options = options or {}
- love.graphics.circle(how, options.x or self.x, options.y or self.y, options.radius or self.radius)
- end
- function Spell:drawImage(options)
- options = options or {}
- local image = self.image or options.image
- local x, y, a, s = self.x or options.x, self.y or options.y, self.angle or options.angle, self.scale or options.scale
- local ax, ay = self.anchorx or options.anchorx, self.anchory or options.anchory
- love.graphics.draw(image, x, y, a, s, s, ax, ay)
- end
- function Spell:playSound(sound, options)
- options = options or {}
- options.x = options.x or self.x
- options.y = options.y or self.y
- ctx.event:emit('sound.play', table.merge({sound = sound}, options))
- end
- return Spell
|