bruju.lua 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. local bruju = {}
  2. function bruju:spawn()
  3. -- noop
  4. end
  5. function bruju:idle()
  6. if self:runIfFeared() then return end
  7. if self.target or self:distanceToPoint(self.destination.x, self.destination.y) > 0 then
  8. self.state = 'move'
  9. return
  10. else
  11. local closest = self:closest('enemy')
  12. if closest and not closest.dead and self:distanceTo(closest) <= self.config.aggroRange then
  13. self.target = closest
  14. self.state = 'move'
  15. return
  16. end
  17. end
  18. self.animation:set('idle')
  19. end
  20. function bruju:move()
  21. if self.target and self.target.isEnemy and self.target.dead then
  22. self.destination.x = self.position.x
  23. self.destination.y = self.position.y
  24. self.target = nil
  25. self.state = 'idle'
  26. end
  27. if self:runIfFeared() then return end
  28. if self.target then
  29. local distance = self:distanceTo(self.target)
  30. if distance <= self.config.radius + self.target.config.radius then
  31. if self.target.isEnemy then
  32. self.state = 'attack'
  33. self.attacking = self.target
  34. return
  35. elseif util.isa(self.target, app.shruju.object) then
  36. self:pickupShruju(self.target)
  37. self.state = 'idle'
  38. return
  39. else
  40. self.state = 'idle'
  41. return
  42. end
  43. else
  44. local speed = math.min(self:getBaseSpeed() * lib.tick.rate, distance)
  45. self:moveTowards(self.target, speed)
  46. self.animation:set('walk')
  47. end
  48. else
  49. local distance = self:distanceToPoint(self.destination.x, self.destination.y)
  50. if distance > 0 then
  51. local speed = math.min(self:getBaseSpeed() * lib.tick.rate, distance)
  52. self:moveTowardsPoint(self.destination.x, self.destination.y, speed)
  53. self.animation:set('walk')
  54. else
  55. self.state = 'idle'
  56. end
  57. end
  58. end
  59. function bruju:attack()
  60. if not self.attacking or self.attacking.dead then
  61. self.state = 'idle'
  62. self.attacking = nil
  63. lib.quilt.remove(self.attackCooldown)
  64. self.attackCooldown = nil
  65. return
  66. end
  67. if self:runIfFeared() then
  68. self.state = 'move'
  69. self.animation:set('walk')
  70. return
  71. end
  72. if not self.attackCooldown then
  73. self.animation:set('attack')
  74. self.attackCooldown = lib.quilt.add(function()
  75. coroutine.yield(self.config.attackSpeed)
  76. self.attackCooldown = nil
  77. self.attacking = nil
  78. self.state = 'idle'
  79. end)
  80. elseif self.animation.active ~= self.animation.states.attack and self:distanceTo(self.attacking) > self.config.radius * 2 + self.attacking.config.radius then
  81. self.state = 'move'
  82. self.target = self.attacking
  83. self.attacking = nil
  84. lib.quilt.remove(self.attackCooldown)
  85. self.attackCooldown = nil
  86. end
  87. end
  88. function bruju:onAttack()
  89. if self.attacking then
  90. self.attacking:hurt(self.config.damage, self)
  91. if self.attacking.dead then
  92. self.destination.x = self.position.x
  93. self.destination.y = self.position.y
  94. end
  95. self.animation:set('idle')
  96. end
  97. end
  98. function bruju:draw()
  99. local image = app.art.shadow
  100. local scale = 60 / image:getWidth()
  101. g.white(70)
  102. g.draw(image, self.position.x, self.position.y, 0, scale, scale / 1.5, image:getWidth() / 2, image:getHeight() / 2)
  103. self:drawRing(40, 200, 40)
  104. if self.state == 'move' or self.state == 'attack' then
  105. g.setLineWidth(2)
  106. local alpha = 1 + math.sin(lib.tick.index * lib.tick.rate * 5) / 2
  107. if self.state == 'attack' or self.target then
  108. g.setColor(200, 40, 40, 20 + 60 * alpha)
  109. else
  110. g.setColor(40, 200, 40, 20 + 60 * alpha)
  111. end
  112. local x, y
  113. if self.target then
  114. x, y = self.target.position.x, self.target.position.y
  115. else
  116. x, y = self.destination.x, self.destination.y
  117. end
  118. g.line(self.position.x, self.position.y, x, y)
  119. g.setLineWidth(1)
  120. end
  121. self.animation:tick(lib.tick.delta)
  122. if util.timeSince(self.lastHurt) < self.config.damageFlashDuration then
  123. self.animation:draw(self.position.x, self.position.y)
  124. app.shaders.colorize:send('color', { 1, 1, 1, 1 - util.timeSince(self.lastHurt) / self.config.damageFlashDuration })
  125. g.setShader(app.shaders.colorize)
  126. self.animation:draw(self.position.x, self.position.y)
  127. g.setShader()
  128. elseif not self:isInvincible() then-- or util.round(util.timeSince(self.lastHurt) * 4) % 2 == 0 then
  129. self.animation:draw(self.position.x, self.position.y)
  130. else
  131. self.animation:draw(self.position.x, self.position.y)
  132. app.shaders.colorize:send('color', { 1, 0, 0, 1 * (1 - util.timeSince(self.lastHurt) / self.config.hurtGrace) })
  133. g.setShader(app.shaders.colorize)
  134. self.animation:draw(self.position.x, self.position.y)
  135. g.setShader()
  136. end
  137. self:drawBuffs()
  138. return -self.position.y
  139. end
  140. return bruju