2
0

game.lua 9.3 KB

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