local World = Object:extend() local maputils = require "scenes.battlesystem.utils" local Map = require "scenes.battlesystem.map" local Cursor = require "scenes.battlesystem.cursor" local TweenManager = require "game.modules.tweenmanager" local POSITIONS = { {x = 3, y = 4}, {x = 2, y = 2}, {x = 2, y = 6}, } local gui = require "game.modules.gui" -- INIT FUNCTIONS -- Initialize the battle world function World:new(scene, battlefile) self.scene = scene self.assets = scene.assets self.obj = require "scenes.battlesystem.actors" self.actors = {} self.globalID = 0 self.turns = {} self.turns.current = 1 self.turns.number = 0 self.turns.isFinished = true self.turns.changeBattler = true self.battlers = {} self.actionlist = {} self.BattlerCursor = self.turns.current self.heroNumber = 0 self.ennNumber = 0 self.playerHUDPosition = -64 self.map = Map(self, "city") self.cursor = Cursor(self) self.tweens = TweenManager(self) self:resetActiveGrid() self:resetEffectGrid() self:initHeroes() self:initEnnemies() self:initHUD() self.isBattleActive = false end function World:initHeroes(battlefile) for i, hero in ipairs(game.characters.team) do self:addHero(POSITIONS[i].x, POSITIONS[i].y, hero, i) end end function World:initEnnemies(battlefile) self:addEnnemy(10, 3, "motobug") self:addEnnemy(10, 5, "motobug") end function World:registerActor(actor) self.globalID = self.globalID + 1 table.insert(self.actors, actor) actor.id = self.globalID end function World:destroyActor(actorToDestroy) for i, actor in ipairs(self.actors) do if actor == actorToDestroy then table.remove(self.actors, i) end end end -- INFO FUNCTIONS -- Get info from the world function World:caseIsEmpty(x, y) local isEmpty = true for i, actor in ipairs(self.actors) do if (actor.x == x) and (actor.y == y) then isEmpty = false else isEmpty = true end end return isEmpty end function World:getActorInCase(x, y) for i, actor in ipairs(self.actors) do if (actor.x == x) and (actor.y == y) then core.debug:print("cbs/world", "one actor found in case <" .. x .. ";" .. y .. ">") return actor end end return nil end -- BATTLER FUNCTIONS -- Handle the actual battle participants function World:addHero(x, y, id) self.heroNumber = self.heroNumber + 1 local hero = self.obj.Hero(self, x, y, id, self.heroNumber) table.insert(self.battlers, hero) end function World:addEnnemy(x, y, id) self.ennNumber = self.ennNumber + 1 local enn = self.obj.Ennemy(self, x, y, id, self.ennNumber) table.insert(self.battlers, enn) end function World:destroyBattler(actorToDestroy) -- remove the actor from the battler liste for i, actor in ipairs(self.battlers) do if actor == actorToDestroy then table.remove(self.battlers, i) end end -- Also remove all actions related to the actor for i, action in ipairs(self.actionlist) do if action.actor == actorToDestroy then table.remove(self.actionlist, i) end end end function World:generateActionList() self.actionlist = {} for i,v in ipairs(self.battlers) do for i=1, v.actionPerTurn do local action = {} action.actor = v action.number = i table.insert(self.actionlist, action) end end end function World:countHeroes() local count = 0 for i, battler in ipairs(self.battlers) do if (battler.isHero) then count = count + 1 end end return count end function World:countEnnemies() local count = 0 for i, battler in ipairs(self.battlers) do if (battler.isEnnemy) then count = count + 1 end end return count end function World:getPlayerHUDPosition() return self.playerHUDPosition end -- UPDATE FUNCTION -- Update all actors function World:update(dt) for i, actor in ipairs(self.actors) do actor:update(dt) end if (self.isBattleActive) then self:updateTurns(dt) end self.cursor:update(dt) self.tweens:update(dt) self.map:update(dt) end function World:moveBattleCursor(dt) local cursorSpeed = 16 if (self.turns.current == 1) then cursorSpeed = 16 * 4 end if math.abs(self.BattlerCursor - self.turns.current) > (cursorSpeed * dt) then self.BattlerCursor = self.BattlerCursor - utils.math.sign(self.BattlerCursor - self.turns.current) * cursorSpeed * dt else self.BattlerCursor = self.turns.current end end -- TURNS FUNCTIONS -- Handle everything related to the turn system function World:startBattle() self.isBattleActive = true self.tweens:newTween(0, 0.4, {playerHUDPosition = 36}, 'inCubic') end function World:recalculateTurns() self:generateActionList() table.sort(self.actionlist, maputils.sortBattlers) end function World:updateTurns(dt) if (self.turns.changeBattler) then self:switchActiveBattler( ) end end function World:switchActiveBattler() if (self:countEnnemies()==0) then self:finishBattle() else if (self.turns.isFinished) or (self.turns.current >= #self.actionlist) then self:switchToNextTurn() else self.turns.current = self.turns.current + 1 core.debug:print("cbs/world", "switching to action number " .. self.turns.current) end self:selectNextAction() self.turns.changeBattler = false self.tweens:newTween(0, 0.2, {BattlerCursor = self.turns.current}, 'inCubic') end end function World:switchToNextTurn() core.debug:print("cbs/world", "turn finished") self.turns.current = 1 self.turns.isFinished = false self.turns.number = self.turns.number + 1 self:recalculateTurns() end function World:selectNextAction() if (self.actionlist[self.turns.current].actor.isDestroyed == true) then self:switchActiveBattler() else self.actionlist[self.turns.current].actor:setActive() end end function World:finishBattle() self.isBattleActive = false self.tweens:newTween(0, 0.4, {playerHUDPosition = -64}, 'inCubic') self.actionlist = {} self.scene:finishBattle() end function World:sendSignalToCurrentBattler(signal) self.actionlist[self.turns.current].actor:receiveSignal(signal) end -- ACTIVEGRID FUNCTIONS -- Help to handle the activeGrid system function World:resetActiveGrid() self.activeGrid = maputils.newFullMap() end function World:setActiveGrid(ox, oy, shape, size, direction) self.activeGrid = maputils.maskToMap(ox, oy, shape, size, direction) end function World:setActiveGridFromGrid(grid) self.activeGrid = grid end function World:resetEffectGrid() self.effectGrid = maputils.newEmptyMap() end function World:setEffectGrid(ox, oy, shape, size, direction) self.effectGrid = maputils.maskToMap(ox, oy, shape, size, direction) end -- DRAW FUNCTION -- Draw the world function World:draw() self.map:draw(self.activeGrid, self.effectGrid) self.cursor:drawBottom() self:drawShadows() self:drawActors() self.cursor:drawTop() self:drawHUD() end function World:drawActors() for i, actor in ipairs(self.actors) do actor:draw() end end function World:drawShadows() for i, actor in ipairs(self.actors) do actor:drawShadow() end end function World:initHUD() self.frame = gui.newBorder(424, 30, 4) end function World:drawHUD() for i, battler in ipairs(self.battlers) do battler:drawHUD() end for i, action in ipairs(self.actionlist) do action.actor:drawIcon(4 + (i-1)*(20), 6) end local cursorx = self.BattlerCursor * 20 - 6 if #self.actionlist > 0 then self.assets.images["menucursor"]:draw(cursorx, 26, math.rad(-90), 1, 1, 4, 8) end local x, y = 362, 3 love.graphics.draw(self.frame, 424, 20, 0, -1, -1) self.assets.images["hudturn"]:draw(x, y) self.assets.fonts["hudnbrs"]:set() local turnnbr = self.turns.number if (turnnbr < 10) then turnnbr = "0" .. turnnbr end love.graphics.print(turnnbr, x + 33, y + 1) end return World