diff --git a/sonic-radiance.love/assets/sprites/gfx/hit.lua b/sonic-radiance.love/assets/sprites/gfx/hit.lua new file mode 100644 index 0000000..522cd88 --- /dev/null +++ b/sonic-radiance.love/assets/sprites/gfx/hit.lua @@ -0,0 +1,18 @@ +return { + metadata = { + height = 32, + width = 32, + defaultAnim = "default", + ox = 16, + oy = 32, + }, + animations = { + ["default"] = { + startAt = 1, + endAt = 5, + loop = 1, + speed = 15, + pauseAtEnd = false, + }, + } +} diff --git a/sonic-radiance.love/assets/sprites/gfx/hit.png b/sonic-radiance.love/assets/sprites/gfx/hit.png new file mode 100644 index 0000000..6b0bcf9 Binary files /dev/null and b/sonic-radiance.love/assets/sprites/gfx/hit.png differ diff --git a/sonic-radiance.love/datas/gamedata/skills/attack.lua b/sonic-radiance.love/datas/gamedata/skills/attack.lua new file mode 100644 index 0000000..0ffcbff --- /dev/null +++ b/sonic-radiance.love/datas/gamedata/skills/attack.lua @@ -0,0 +1,53 @@ +-- A basic file describing the basic attack, in order to make it customizable one +-- day ? + +-- Also serve as a tutoriel for how to create a file attack and choregraphy + +return { + name = "Attack", -- unused for this attack, but still usefull sometimes + cost = 00, -- the pp cost of the attack. Will be ignored if it's set + -- as character default attack + + target = nil, -- which area can be selected as a target with the cursor. + -- if not nil : {ox, oy, shape, size, affectedByDirection} + + targetNumber = 1, -- how many ennemy you can target with the attack. + + effectArea = {1, 0, "point", 1, true}, -- which area is affected by the attack + -- if not nil : {ox, oy, shape, size, affectedByDirection} + + choregraphy = { -- the main attack choregraphy + {'setAnimation', 'hit1', true}, + {'addGFX', 'hitGFX', 0.75, 0, true, false}, + {'sendDamage', 33, 100, false, false}, + {'setAnimation', 'hit2', true}, + {'addGFX', 'hitGFX', 0.75, 0, true, false}, + {'sendDamage', 33, 100, false, false}, + {'setAnimation', 'hit3', true}, + {'addGFX', 'hitGFX', 0.75, 0, true, false}, + {'sendDamage', 33, 100, false, false}, + {'setAnimation', 'idle', false}, + {'wait', 0.5} + }, + + onContact = { -- if the attack move and touch multiple ennemies, you can add + -- specific effect when you touch the ennemy. + }, +} + +--[[ + CHOREGRAPHY POSSIBLE EFFECTS +-- "wait" :: Simply wait before doing the next command +-- :: {"wait", duration} + +-- "setAnimation" :: Change the animation of the battler +-- {"setAnimation", animation, blockProcess} + +-- "addGFX" :: Show a GFX relatively to the target position +-- :: (player if target is nil) +-- :: {"addGFX", "gfxname", x, y, affectedByDirection, blockProcess} + +-- "sendDamage" :: Send Damage on the whole target Area +-- :: +-- :: {"sendDamage", damageEffect, accuracy, isSpecial, isAerial} +]] diff --git a/sonic-radiance.love/scenes/battlesystem/actors/gfx.lua b/sonic-radiance.love/scenes/battlesystem/actors/gfx.lua new file mode 100644 index 0000000..acdec2f --- /dev/null +++ b/sonic-radiance.love/scenes/battlesystem/actors/gfx.lua @@ -0,0 +1,29 @@ +local Parent = require("scenes.battlesystem.actors.parent") +local GFX = Parent:extend() + +function GFX:new(world, x, y, z, spritename, creator, blockProcess) + local width, height = world.assets.sprites[spritename]:getDimensions() + + GFX.super.new(self, world, x, y, z) + self:setSprite(spritename, width/2, height, true) + self:cloneSprite() + self.creator = creator + self.blockProcess = blockProcess or false + + self.direction = 1 +end + +function GFX:animationEnded(animation) + core.debug:print("gfx", 'Current animation "' .. animation .. '" have ended, destroying gfx') + self:destroy() +end + +function GFX:draw() + self:drawSprite() +end + +function GFX:drawShadow() + +end + +return GFX diff --git a/sonic-radiance.love/scenes/battlesystem/actors/hero.lua b/sonic-radiance.love/scenes/battlesystem/actors/hero.lua index 792dcf5..acfdee1 100644 --- a/sonic-radiance.love/scenes/battlesystem/actors/hero.lua +++ b/sonic-radiance.love/scenes/battlesystem/actors/hero.lua @@ -24,6 +24,7 @@ function Hero:new(world, x, y, charid, charnumber) self.actionPerTurn = game.characters.list[self.charid].turns self:initSprite() + self:initChoregraphySystem() end -- INFO FUNCTIONS @@ -58,6 +59,11 @@ function Hero:update(dt) Hero.super.update(self, dt) self.keys = self.scene:getKeys(1) + + if (self.isChoregraphyActive) then + self:updateChoregraphy() + end + if (self.currentAction == "moving") then self:updateMoving(dt) elseif (self.currentAction == "selectAttack") then @@ -148,7 +154,8 @@ function Hero:receiveSignal(action_type, id) self.turnAction = "defend" self:switchActiveBattler( ) elseif (action_type == "attack") then - self:changeAnimation("hit1") + --self:changeAnimation("hit1") + self:startChoregraphy("attack") else self:switchActiveBattler( ) end @@ -163,6 +170,8 @@ end function Hero:timerResponse(timer) if timer == "switchActiveBattler" then self.world:switchActiveBattler() + elseif timer == "wait" then + self.choregraphy.changeAction = true end end @@ -183,6 +192,101 @@ function Hero:switchActiveBattler() self.tweens:newTimer(0.15, "switchActiveBattler") end +-- CHOREGRAPHY FUNCTIONS +-- All functions related to the choregraphy system + +function Hero:initChoregraphySystem() + self.choregraphy = {} + self.choregraphy.current = 0 + self.choregraphy.isFinished = false + self.choregraphy.changeAction = true + self.choregraphy.data = {} + self.choregraphy.effectArea = nil + self.choregraphy.dx = self.x + self.choregraphy.dy = self.y + self.choregraphy.blockedBy = "" + + self.isChoregraphyActive = false +end + +function Hero:startChoregraphy(skill, dx, dy) + local skill = require("datas.gamedata.skills." .. skill) + self.choregraphy.current = 0 + self.choregraphy.isFinished = false + self.choregraphy.changeAction = true + self.choregraphy.data = skill.choregraphy + self.choregraphy.effectArea = skill.effectArea + self.choregraphy.dx = dx or self.x + self.choregraphy.dy = dy or self.y + + self.isChoregraphyActive = true +end + +function Hero:updateChoregraphy(dt) + if (self.choregraphy.changeAction) then + self:switchAction() + end +end + +function Hero:switchAction() + self.choregraphy.current = self.choregraphy.current + 1 + local nextAction = self.choregraphy.data[self.choregraphy.current] + if nextAction == nil then + self.isChoregraphyActive = false + self:switchActiveBattler() + else + self:doChoregraphyAction(nextAction) + end +end + +function Hero:doChoregraphyAction(choregraphyAction) + local type = choregraphyAction[1] or "unknown" + self.choregraphy.changeAction = true + + if type == "wait" then + local duration = choregraphyAction[2] or 1 + self:wait(duration) + elseif type == "setAnimation" then + local animation = choregraphyAction[2] + local blockProcess = choregraphyAction[3] + self:changeAnimation(animation) + if (blockProcess) then + self.choregraphy.blockedBy = animation + self.choregraphy.changeAction = false + end + elseif type == "sendDamage" then + local xx = self.x + self.direction + local yy = self.y + local power = choregraphyAction[2] + local accuracy = choregraphyAction[3] + local isSpecial = choregraphyAction[4] + local isAerial = choregraphyAction[5] + self:sendDamage(xx, yy, power, accuracy, isSpecial, isAerial) + elseif type == "addGFX" then + local sprite = choregraphyAction[2] + local dx = choregraphyAction[3] + local dy = choregraphyAction[4] + local affectedByDirection = choregraphyAction[5] + if (affectedByDirection) then + dx = dx * self.direction + end + local blockProcess = choregraphyAction[6] + + local x = self.x + local y = self.y + local z = 0 + + self.world.obj.GFX(self.world, x + dx, y + dy, z, sprite, self, blockProcess) + else + core.debug:warning("cbs/hero", "unknown action type " .. type) + end +end + +function Hero:wait(time) + self.tweens:newTimer(time, "wait") + self.choregraphy.changeAction = false +end + -- SPRITE FUNCTIONS -- Handle the hero sprite @@ -195,17 +299,9 @@ function Hero:initSprite() end function Hero:animationEnded(animation) - if (animation == "hit1") then - self:sendDamage(self.x + self.direction, self.y, 33, 100, false, false) - self:changeAnimation("hit2") - elseif (animation == "hit2") then - self:sendDamage(self.x + self.direction, self.y, 33, 100, false, false) - self:changeAnimation("hit3") - elseif (animation == "hit3") then - self:sendDamage(self.x + self.direction, self.y, 33, 100, false, false) - core.debug:print("cbs/hero", "normal combo finished, switching actor") - self:changeAnimation("idle") - self:switchActiveBattler( ) + if (animation == self.choregraphy.blockedBy) then + self.choregraphy.blockedBy = "" + self.choregraphy.changeAction = true end end diff --git a/sonic-radiance.love/scenes/battlesystem/actors/init.lua b/sonic-radiance.love/scenes/battlesystem/actors/init.lua index 72dcf74..5d7066d 100644 --- a/sonic-radiance.love/scenes/battlesystem/actors/init.lua +++ b/sonic-radiance.love/scenes/battlesystem/actors/init.lua @@ -4,5 +4,6 @@ local baseURI = "scenes.battlesystem.actors." entities.Hero = require(baseURI .. "hero") entities.Ennemy = require(baseURI .. "ennemy") +entities.GFX = require(baseURI .. "gfx") return entities diff --git a/sonic-radiance.love/scenes/battlesystem/actors/parent.lua b/sonic-radiance.love/scenes/battlesystem/actors/parent.lua index 646b41b..0ae9d8f 100644 --- a/sonic-radiance.love/scenes/battlesystem/actors/parent.lua +++ b/sonic-radiance.love/scenes/battlesystem/actors/parent.lua @@ -28,7 +28,7 @@ function Parent:new(world, x, y, z) self.isDestroyed = false self.tweens = TweenManager(self) - + self:setSprite() self:register() end diff --git a/sonic-radiance.love/scenes/battlesystem/assets.lua b/sonic-radiance.love/scenes/battlesystem/assets.lua index 62db59f..4664ec5 100644 --- a/sonic-radiance.love/scenes/battlesystem/assets.lua +++ b/sonic-radiance.love/scenes/battlesystem/assets.lua @@ -6,7 +6,8 @@ return { {"borders", "assets/backgrounds/borders"}, }, ["sprites"] = { - {"cursorground", "assets/gui/cursor/ground"} + {"cursorground", "assets/gui/cursor/ground"}, + {"hitGFX", "assets/sprites/gfx/hit"}, }, ["textures"] = { {"menucursor", "assets/gui/cursor-menulist.png"},