robot.lua 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. local PlayerRobot = extend(app.player.server)
  2. function PlayerRobot:activate()
  3. app.playerServer.activate(self)
  4. self.username = 'robot'
  5. self.state = 'navigating'
  6. self.dirTimer = 0
  7. self.direction = 0
  8. self.directionOffset = 0
  9. self.w, self.a, self.s, self.d = false, false, false, false
  10. self.mx, self.my, self.ml = 0, 0, false
  11. self.backwards = love.math.random() * 2 * math.pi
  12. self.checkBehind = 5 + love.math.random(3)
  13. self.sleep = love.math.random() * 2
  14. self.target = nil
  15. end
  16. function PlayerRobot:logic()
  17. self.sleep = timer.rot(self.sleep)
  18. if self.sleep > 0 then return end
  19. self.checkBehind = timer.rot(self.checkBehind)
  20. if self.checkBehind == 0 then self.checkBehind = 5 + love.math.random(3) end
  21. if self.state == 'navigating' then
  22. self.dirTimer = timer.rot(self.dirTimer)
  23. if self.dirTimer == 0 then
  24. local directions = {}
  25. for i = math.pi / 4, math.pi * 2, math.pi / 4 do
  26. table.insert(directions, {i, self:rateDirection(i)})
  27. end
  28. table.sort(directions, function(a, b) return a[2] > b[2] end)
  29. local entry = directions[1]
  30. if entry[1] == 2 * math.pi then entry[1] = 0 end
  31. local dx = math.cos(entry[1])
  32. if math.abs(dx) < .5 then dx = 0 end
  33. local dy = math.sin(entry[1])
  34. if math.abs(dy) < .5 then dy = 0 end
  35. self.direction = entry[1]
  36. self.w = dy < 0
  37. self.a = dx < 0
  38. self.s = dy > 0
  39. self.d = dx > 0
  40. self.dirTimer = 1 + love.math.random() * 1
  41. self.backwards = math.pi + entry[1]
  42. end
  43. local sign = 1
  44. if self.checkBehind < .3 then sign = -1 end
  45. self.directionOffset = --[[self.directionOffset + ]](love.math.noise(tick / 200 + self.id) * 2 - 1) * math.pi
  46. self.mx = math.lerp(self.mx, self.x + math.dx(100 * sign, self.direction + self.directionOffset), math.min(4 * tickRate, 1))
  47. self.my = math.lerp(self.my, self.y + math.dy(100 * sign, self.direction + self.directionOffset), math.min(4 * tickRate, 1))
  48. self.ml = false
  49. ctx.players:each(function(p)
  50. if p.team == self.team then return end
  51. if math.distance(p.x, p.y, self.x, self.y) > 800 then return end
  52. if math.abs(math.anglediff(self.angle, math.direction(self.x, self.y, p.x, p.y))) > math.pi / 2 then return end
  53. if ctx.collision:lineTest(self.x, self.y, p.x, p.y, {tag = 'wall'}) then return end
  54. --self.state = 'combat'
  55. self.target = p
  56. end)
  57. elseif self.state == 'combat' then
  58. self.mx = self.target.x
  59. self.my = self.target.y
  60. self.ml = true
  61. if self.target.ded then
  62. self.state = 'navigating'
  63. end
  64. end
  65. self:trace({
  66. tick = tick,
  67. w = self.w,
  68. a = self.a,
  69. s = self.s,
  70. d = self.d,
  71. x = self.mx,
  72. y = self.my,
  73. l = self.ml
  74. }, 0)
  75. end
  76. function PlayerRobot:rateDirection(dir)
  77. local visionRadius = 1000
  78. local tooClose = 250
  79. local hit, d = ctx.collision:lineTest(self.x, self.y, self.x + math.dx(visionRadius, dir), self.y + math.dy(visionRadius, dir), {tag = 'wall', first = true})
  80. local hit2, d2 = ctx.collision:lineTest(self.x, self.y, self.x + math.dx(visionRadius, dir), self.y + math.dy(visionRadius,dir), {tag = 'teamwall', fn = function(w) return w.team ~= self.team end, first = true})
  81. if not hit and hit2 then d = d2 end
  82. if hit and hit2 and d2 < d then d = d2 end
  83. local distanceScore = ((hit and d or visionRadius) / visionRadius)
  84. local directionScore = math.abs(math.anglediff(dir, self.backwards or dir)) / math.pi
  85. score = distanceScore * .6 + directionScore * .4
  86. score = score - .2 + love.math.random() * .4
  87. if d <= tooClose then distanceScore = distanceScore - (.1 + (1 - (d / tooClose))) end
  88. score = math.clamp(score, 0, 1)
  89. return score
  90. end
  91. return PlayerRobot