game.lua 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. Game = class()
  2. function Game:load(user, options, info)
  3. self.options = options
  4. if self.options.textureSmoothing then
  5. data.media.graphics.juju:setMipmapFilter('linear', 1)
  6. data.media.graphics.map.forest:setMipmapFilter('linear', 1)
  7. data.media.graphics.map.forestSpirit:setMipmapFilter('linear', 1)
  8. data.media.graphics.atlas.hud:setMipmapFilter('linear', 1)
  9. data.media.graphics.hud.clockBlue:setMipmapFilter('linear', 1)
  10. data.media.graphics.hud.clockBronze:setMipmapFilter('linear', 1)
  11. data.media.graphics.hud.clockSilver:setMipmapFilter('linear', 1)
  12. data.media.graphics.hud.clockGold:setMipmapFilter('linear', 1)
  13. end
  14. self.user = user
  15. self.id = 1
  16. self.mode = info.mode
  17. self.biome = info.biome
  18. self.paused = false
  19. self.ded = false
  20. self.timer = 0
  21. self.event = Event()
  22. self.view = View()
  23. self.map = Map()
  24. self.players = Players()
  25. self.player = ctx.players:add(1)
  26. self.shrujus = Shrujus()
  27. self.hud = Hud()
  28. self.upgrades = Upgrades
  29. self.shrines = Manager()
  30. self.shrine = self.shrines:add(Shrine, {x = ctx.map.width / 2, team = 1})
  31. self.units = Units()
  32. self.spells = Spells()
  33. self.particles = Particles()
  34. self.target = Target()
  35. self.sound = Sound(self.options)
  36. self.effects = Effects()
  37. self.jujus = Jujus()
  38. self.achievements = Achievements(self.user)
  39. self.tutorial = Tutorial(info.tutorial, info.destination)
  40. Upgrades.clear()
  41. self.event:on('shrine.dead', function(data)
  42. self.youlose = ctx.sound:play('youlose')
  43. ctx.sound:play('death')
  44. self.ded = true
  45. self:distribute()
  46. end)
  47. self.backgroundSound = self.sound:loop(self.biome)
  48. love.keyboard.setKeyRepeat(false)
  49. if self.options.mute then self.sound:mute() end
  50. end
  51. function Game:update()
  52. if self.hud.upgrades.active or self.paused or self.ded then
  53. self.hud:update()
  54. if self.ded and self.effects:get('deathblur') then self.effects:get('deathblur'):update() end
  55. self.players:paused()
  56. self.units:paused()
  57. self.spells:paused()
  58. self.particles:update()
  59. self.tutorial:update()
  60. return
  61. end
  62. self.timer = self.timer + 1
  63. ls.framerate = self.options.powersave and (love.system.getPowerInfo() == 'battery' and 30 or 60) or -1
  64. self.players:update()
  65. self.units:update()
  66. self.shrines:update()
  67. self.jujus:update()
  68. self.spells:update()
  69. self.map:update()
  70. self.view:update()
  71. self.hud:update()
  72. self.effects:update()
  73. self.shrujus:update()
  74. self.tutorial:update()
  75. end
  76. function Game:unload()
  77. self.backgroundSound:stop()
  78. if self.youlose then self.youlose:stop() end
  79. end
  80. function Game:draw()
  81. self.view:draw()
  82. end
  83. function Game:resize()
  84. self.hud:resize()
  85. self.view:resize()
  86. self.effects:resize()
  87. end
  88. function Game:keypressed(key)
  89. if not self.ded then
  90. if key == 'p' or (key == 'escape' and not self.hud:menuActive()) then self.paused = not self.paused
  91. elseif key == 'm' then
  92. -- self.options.mute = not self.options.mute
  93. self.sound:mute()
  94. end
  95. end
  96. self.hud:keypressed(key)
  97. self.players:keypressed(key)
  98. self.tutorial:keypressed(key)
  99. end
  100. function Game:keyreleased(...)
  101. self.hud:keyreleased(...)
  102. end
  103. function Game:mousepressed(...)
  104. self.hud:mousepressed(...)
  105. end
  106. function Game:mousereleased(...)
  107. self.hud:mousereleased(...)
  108. end
  109. function Game:mousemoved(...)
  110. self.hud:mousemoved(...)
  111. end
  112. function Game:gamepadpressed(gamepad, button)
  113. print('Game:gamepadpressed', gamepad, button)
  114. if button == 'start' or button == 'guide' then self.paused = not self.paused end
  115. self.hud:gamepadpressed(gamepad, button)
  116. self.players:gamepadpressed(gamepad, button)
  117. end
  118. function Game:gamepadaxis(...)
  119. self.players:gamepadaxis(...)
  120. end
  121. function Game:distribute()
  122. local function tableRandom(t)
  123. return t[love.math.random(1, #t)]
  124. end
  125. -- So the hud can draw them
  126. self.rewards = {runes = {}, medals = {}, minions = {}, hats = {}, highscore = false}
  127. local time = math.floor(self.timer * ls.tickrate)
  128. if self.mode == 'campaign' then
  129. local bronze = time >= config.medals.bronze
  130. local silver = time >= config.medals.silver
  131. local gold = time >= config.medals.gold
  132. -- Distribute medals
  133. if bronze and not ctx.user.campaign.medals[self.biome].bronze then
  134. table.insert(self.rewards.medals, 'bronze')
  135. self.user.campaign.medals[self.biome].bronze = true
  136. end
  137. if silver and not ctx.user.campaign.medals[self.biome].silver then
  138. local nextMinions = {forest = 'xuju', cavern = 'kuju', tundra = 'thuju'}
  139. if nextMinions[self.biome] then
  140. table.insert(self.rewards.minions, nextMinions[self.biome])
  141. end
  142. table.insert(self.rewards.medals, 'silver')
  143. self.user.campaign.medals[self.biome].silver = true
  144. end
  145. if gold and not ctx.user.campaign.medals[self.biome].gold then
  146. table.insert(self.rewards.medals, 'gold')
  147. self.user.campaign.medals[self.biome].gold = true
  148. local hatPool = table.copy(config.hats)
  149. for i = 1, #config.hats do
  150. local index = love.math.random(1, #hatPool)
  151. if table.has(self.user.hats, hatPool[index]) then
  152. table.remove(hatPool, i)
  153. else
  154. local hat = hatPool[index]
  155. table.insert(self.rewards.hats, hat)
  156. table.insert(self.user.hats, hat)
  157. self.user.campaign.hatHistory[self.biome] = hat
  158. break
  159. end
  160. if #hatPool == 0 then break end
  161. end
  162. end
  163. -- Distribute runes
  164. local runeCount = 0
  165. if bronze then runeCount = runeCount + 1 end
  166. if silver and love.math.random() < .3 then runeCount = runeCount + 1 end
  167. if gold and love.math.random() < .2 then runeCount = runeCount + 1 end
  168. for i = 1, runeCount do
  169. -- Basics
  170. local rune = {}
  171. local maxLevel = config.runes.maxLevels[self.biome]
  172. local mu = 0
  173. if gold then mu = maxLevel
  174. elseif silver then mu = maxLevel * .8
  175. elseif bronze then mu = maxLevel * .5 end
  176. local runeLevel = math.clamp(love.math.randomNormal(10, mu), 1, 100)
  177. -- Generate prefix
  178. local prefixes = config.runes.prefixes
  179. local prefixLevel = math.clamp(runeLevel + love.math.random(-4, 4), 0, 100)
  180. local prefix = prefixes[1 + lume.round((prefixLevel / 100) * (#prefixes - 1))]
  181. rune.name = prefix .. ' Rune'
  182. -- Generate bonuses
  183. local r = love.math.random()
  184. if r < .33 then
  185. -- Attributes
  186. rune.attributes = {}
  187. local attribute = tableRandom(config.attributes.list)
  188. local attributeLevels = math.max(lume.round((runeLevel / 100) * 8), 1)
  189. local attributeLevelsDistributed = 0
  190. local attributesDistributed = {attribute}
  191. while attributeLevelsDistributed < attributeLevels do
  192. local amount = love.math.random(1, attributeLevels - attributeLevelsDistributed)
  193. rune.attributes[attribute] = (rune.attributes[attribute] or 0) + amount
  194. attributeLevelsDistributed = attributeLevelsDistributed + amount
  195. if #attributesDistributed < 2 and love.math.random() < .4 then
  196. attribute = tableRandom(config.attributes.list)
  197. if not table.has(attributesDistributed, attribute) then
  198. table.insert(attributesDistributed, attribute)
  199. end
  200. end
  201. end
  202. table.sort(attributesDistributed)
  203. rune.name = rune.name .. ' of ' .. tableRandom(config.runes.suffixes.attributes[table.concat(attributesDistributed)])
  204. elseif r < .67 then
  205. -- Stat bonuses
  206. local stats = config.runes.stats
  207. local stat = stats[love.math.random(1, #stats)]
  208. local min, max = unpack(config.runes.statRanges[stat])
  209. local mu, sigma = lume.lerp(min, max, runeLevel / 100), (max - min) / 10
  210. local amount = math.clamp(love.math.randomNormal(sigma, mu), min, max)
  211. rune.stats = {[stat] = amount}
  212. rune.name = rune.name .. ' of ' .. tableRandom(config.runes.suffixes.stats[stat])
  213. else
  214. -- Ability bonuses
  215. local unit = tableRandom(table.keys(config.runes.abilities))
  216. if self.mode == 'campaign' and love.math.random() < .5 then unit = config.biomes[ctx.biome].minion end
  217. local ability = tableRandom(table.keys(config.runes.abilities[unit]))
  218. local stat = tableRandom(table.keys(config.runes.abilities[unit][ability]))
  219. local min, max = unpack(config.runes.abilities[unit][ability][stat])
  220. local mu, sigma = lume.lerp(min, max, runeLevel / 100), (max - min) / 10
  221. local amount = math.clamp(love.math.randomNormal(sigma, mu), min, max)
  222. rune.unit = unit
  223. rune.abilities = {[ability] = {[stat] = amount}}
  224. rune.name = rune.name .. ' of ' .. tableRandom(config.runes.suffixes.abilities[ability])
  225. end
  226. -- Generate appearance
  227. rune.color = tableRandom(table.keys(config.runes.colors))
  228. rune.image = love.math.random(1, config.runes.imageCount)
  229. rune.background = runeLevel < 30 and 'broken' or 'normal'
  230. -- Add to account
  231. if table.count(ctx.user.runes.stash) < 32 then
  232. for i = 1, 32 do
  233. if not self.user.runes.stash[i] then
  234. self.user.runes.stash[i] = rune
  235. table.insert(self.rewards.runes, rune)
  236. break
  237. end
  238. end
  239. end
  240. end
  241. end
  242. -- Calculate highscores
  243. if self.mode == 'survival' and time > self.user.survival.bestTime then
  244. self.user.survival.bestTime = time
  245. self.rewards.highscore = true
  246. end
  247. saveUser(self.user)
  248. end