News:

MFG's Character of the Month: September 2026 Voting

Main Menu

FighterZ Style Vanish

Started by Hypersayia, September 21, 2025, 10:02:32 PM

Previous topic - Next topic

Hypersayia

So, I'm trying my hand at... well, a Dragon Ball FighterZ style vanish.

Here be what I've got so far:

;---------------------------------------------------------------------------
;Vanish
[Statedef 340]
type = S
movetype = A
physics = N
anim = 340
ctrl = 0
velset = 0,0
sprpriority = 2
facep2 = 1
poweradd = -1000

[State 340, Vanish Freeze]
type = SuperPause
trigger1 = Time = 0
time = 20
movetime = 20
p2defmul = 1
darken = 0
anim = -1

[State 340, Set Var] ;Cooldown. Resets on landing.
type = VarSet
trigger1 = 1
var(31) = 1

[State 340, ChangeState Into Kick]
type = ChangeState
trigger1 = Time = 20
value = 345

[State 340, PlaySnd]
type = PlaySnd
trigger1 = animelem = 2
value = S6,18

;Vanish Kick
[Statedef 345]
type = A
movetype = A
physics = S
anim = 345
ctrl = 0
velset = 0,0
sprpriority = 2
facep2 = 1

[State 345, Position Behind Opponent]
type = PosSet
trigger1 = Time = 0
x = enemy, pos x - (enemy, facing * (enemy,const(size.ground.front) + 20))
y = enemy, pos y - (enemy,const(size.height) * 0.5)


[State 345, Stop Opponent Proximity]
type = TargetBind
trigger1 = Time < 5
trigger1 = P2BodyDist X < 40
trigger1 = P2BodyDist Y = [-30,30]
trigger1 = EnemyNear, statetype != L
pos = -P2Dist X, -(P2Dist Y - (enemy,const(size.height) * 0.5))
time = 1

[State 345, Face Opponent]
type = Turn
trigger1 = Time = 0
trigger1 = facing != enemy, facing

[State 345, HitDef]
type = HitDef
trigger1 = AnimElem = 3
attr = S, NA
damage = 60,20
guardflag = MA
hitflag = MAF
priority = 4, Hit
pausetime = 20,20
sparkno = 0
sparkxy = -10, -30
hitsound = S2,4
guardsound = S3,0
ground.type = High
ground.hittime = 25
ground.slidetime = 35
ground.velocity = -6, -1
air.velocity = -6, -1
fall = 1
envshake.time = 10
envshake.ampl = 8 ;
p2stateno = 5400 ;A custom knockback state
p2facing = 1
fall.envshake.ampl = id

[State 345, Knockback set]
type = VarSet
trigger1 = MoveHit = 1
var(10) = 2 ;What defines some of the logic of the custom knockback state

[State 345, ForceKnockbackVar]
type = VarSet
trigger1 = AnimElem = 3
var(10) = 2
ignorehitpause = 1

[State 345, Calculate Distance to Ground]
type = VarSet
trigger1 = Time >= 0
var(50) = (pos y + const(size.height))

[State 345, Change to Falling State]
type = ChangeState
trigger1 = AnimTime = 0
trigger1 = var(50) <= 10
value = 50
ctrl = 1

[State 345, Change to Landing State]
type = ChangeState
trigger1 = AnimTime = 0
trigger1 = var(50) > 10
value = 52
ctrl = 1
;---------------------------------------------------------------------------


So this is probably a bit of a weird thing in that MUGEN, at least the version I use, it works fine. But... I'm trying my hand at translating the character to Ikemen. Which has slightly different logic in how it handles two characters trying to take up the same space.

Here's the short version, when trying to use the Vanish while the opponent is up against the edge of the stage, the character doesn't appear behind the opponent. Instead, they appear in front. What I want is, in the previously mentioned event, for the opponent to be pushed to give the character space to appear where they should be.

Hypersayia

So, I figured it out meself.

Short version: Use a Helper.

Long version:


[State 345, Check if Opponent is Against Wall]
type = VarSet
trigger1 = Time = 0
var(2) = (enemy, BackEdgeBodyDist <= 20) || (enemy, FrontEdgeBodyDist <= 20)

[State 345, Create Push Helper]
type = Helper
trigger1 = Time = 1 && var(2)
helpertype = projectile
stateno = 346
id = 346
postype = p2
pos = 0,0

;---------------------------------------------------------------------------
;Vanish Push
[Statedef 346]
type = A
movetype = A
physics = N
anim = 346 ;Litterally just a hitbox
facing = 1

[State 346, Invisible Push HitDef]
type = HitDef
trigger1 = Time = 0
attr = SCA, AP
damage = 0, 0
guardflag = M
hitflag = MAF
pausetime = 0,0
sparkno = -1
hitsound = -1
guardsound = -1
ground.type = High
ground.hittime = 0
ground.slidetime = 1
ground.velocity = -2, 0
air.velocity = -2, 0
fall = 0

[State 346, Destroy Self]
type = DestroySelf
trigger1 = Time = 3

Tabris666

it would be more easy to make it in other way like using the common1.cns for it (not the way i will do it) but will work at the end having those fights in the style of dragon ball with any character is great, the timing is hard to get since will need a precise timing.
i did it and it worked great, the timing i have is from spraking zero and once two punches at same timing clash the characters will teleport randomly causing effect on screen and showing in different parts randomly, in the purest dragon ball fight style.
Maybe this could help you get a hint

--=============================================
-- Dragon Ball FighterZ System for M.U.G.E.N (Lua)
--=============================================

local config = {
    -- Ki Gauge System
    KI_MAX = 7,                  -- Maximum ki bars
    KI_GAIN_HIT = 0.5,           -- Ki gained per hit
    KI_GAIN_BLOCK = 0.25,        -- Ki gained when blocked
    KI_GAIN_IDLE = 0.02,         -- Passive ki gain
   
    -- Sparking Blast
    SPARKING_COST = 3,           -- Ki cost to activate
    SPARKING_DURATION = 420,     -- 7 seconds at 60fps
    SPARKING_HEAL_RATE = 0.002,  -- Health regen per frame
   
    -- Vanishing
    VANISH_COST = 1,             -- Ki cost for vanish
    VANISH_INVINCIBILITY = 15,   -- Invincibility frames
   
    -- Assist System
    ASSIST_COOLDOWN = 300,       -- 5 seconds cooldown
    ASSIST_TYPES = {
        "A", "B", "C"            -- Standard DBFZ assist types
    },
   
    -- Dragon Rush
    DR_PIXEL_THRESHOLD = 50,     -- Distance for dragon rush
    DR_HITSTUN = 40,             -- Hitstun on successful DR
   
    -- Super Dash
    SD_ARMOR_STARTUP = 10,       -- Armor startup frames
    SD_HOMING_STRENGTH = 0.1,    -- Tracking adjustment
   
    -- Z Change (Tag)
    ZCHANGE_COOLDOWN = 180,      -- 3 seconds cooldown
    ZCHANGE_INVINCIBILITY = 20,  -- Invincibility on tag
   
    -- Limit Break
    LIMIT_DURATION = 480,        -- 8 seconds duration
    LIMIT_DMG_BONUS = 1.25       -- Damage multiplier
}

local players = {
    [1] = {
        ki = 0,                  -- Current ki bars
        team = {},               -- Team members
        active = 1,              -- Current fighter index
        sparking = {
            active = false,
            timer = 0
        },
        assists = {
            cooldown = {0, 0, 0} -- Cooldown for each assist
        },
        limit = {
            active = false,
            timer = 0
        },
        vanish = {
            active = false,
            timer = 0
        },
        state = {}
    },
    [2] = {
        ki = 0,
        team = {},
        active = 1,
        sparking = {
            active = false,
            timer = 0
        },
        assists = {
            cooldown = {0, 0, 0}
        },
        limit = {
            active = false,
            timer = 0
        },
        vanish = {
            active = false,
            timer = 0
        },
        state = {}
    }
}

-- Helper functions
local function GetPlayer(id)
    return players[id]
end

local function GetActiveChar(id)
    local ply = GetPlayer(id)
    return ply.team[ply.active]
end

local function AddKi(player_id, amount)
    local ply = GetPlayer(id)
    ply.ki = math.min(ply.ki + amount, config.KI_MAX)
end

-- Ki Management
local function UpdateKi()
    for id = 1, 2 do
        local ply = GetPlayer(id)
       
        -- Passive ki gain
        if ply.state == "neutral" then
            AddKi(id, config.KI_GAIN_IDLE)
        end
    end
end

-- Sparking Blast
local function ActivateSparking(player_id)
    local ply = GetPlayer(player_id)
   
    if ply.ki >= config.SPARKING_COST and not ply.sparking.active then
        ply.ki = ply.ki - config.SPARKING_COST
        ply.sparking.active = true
        ply.sparking.timer = config.SPARKING_DURATION
       
        -- Visual effect
        CreateEffect(player_id, "SparkingBlast")
        return true
    end
    return false
end

-- Vanish Mechanic (Instant Air Dash + Attack)
local function PerformVanish(player_id)
    local ply = GetPlayer(player_id)
   
    if ply.ki >= config.VANISH_COST then
        ply.ki = ply.ki - config.VANISH_COST
        ply.vanish.active = true
        ply.vanish.timer = config.VANISH_INVINCIBILITY
       
        -- Position teleport
        local opponent = GetPlayer(player_id == 1 and 2 or 1)
        SetPos(player_id, opponent.pos.x + (100 * opponent.facing), opponent.pos.y + 50)
       
        -- Attack automatically comes out
        ChangeState(player_id, "VanishAttack")
        return true
    end
    return false
end

-- Dragon Rush (Universal Overhead)
local function PerformDragonRush(player_id)
    local ply = GetPlayer(player_id)
    local opp = GetPlayer(player_id == 1 and 2 or 1)
   
    -- Check distance
    if DistanceBetween(player_id, opp.id) <= config.DR_PIXEL_THRESHOLD then
        ChangeState(player_id, "DragonRush")
        return true
    end
    return false
end

-- Super Dash (Homing Attack)
local function PerformSuperDash(player_id)
    local ply = GetPlayer(player_id)
   
    -- Check opponent exists
    if GetPlayer(player_id == 1 and 2 or 1) then
        ChangeState(player_id, "SuperDash")
        return true
    end
    return false
end

-- Assist Calls
local function CallAssist(player_id, assist_type)
    local ply = GetPlayer(player_id)
    local index = (assist_type == "A" and 1) or (assist_type == "B" and 2) or 3
   
    if ply.assists.cooldown[index] <= 0 then
        ply.assists.cooldown[index] = config.ASSIST_COOLDOWN
       
        -- Spawn helper (MUGEN's projectile system)
        CreateHelper(player_id, "Assist"..assist_type, {
            pos = "back",
            anim = "Assist"..assist_type,
            damage = 50,
            hitstun = 30
        })
        return true
    end
    return false
end

-- Z Change (Tag Mechanic)
local function PerformZChange(player_id, direction)
    local ply = GetPlayer(player_id)
   
    if ply.zchange_cooldown <= 0 and #ply.team > 1 then
        local new_char = (ply.active % #ply.team) + 1  -- Simple cycling
       
        -- Switch character
        ply.active = new_char
        ply.zchange_cooldown = config.ZCHANGE_COOLDOWN
       
        -- Invincibility
        SetInvincible(player_id, config.ZCHANGE_INVINCIBILITY)
       
        -- Position swap
        ChangeState(player_id, "ZChange"..(direction == "forward" and "In" or "Out"))
        return true
    end
    return false
end

-- Limit Break (Last Character Power Up)
local function CheckLimitBreak(player_id)
    local ply = GetPlayer(player_id)
   
    if #ply.team == 1 and not ply.limit.active then  -- Last character
        ply.limit.active = true
        ply.limit.timer = config.LIMIT_DURATION
       
        -- Visual effect
        CreateEffect(player_id, "LimitAura")
        return true
    end
    return false
end

-- Combo Handling
local function DetectAutoCombo(player_id, input_sequence)
    -- Simple auto-combo detector
    if input_sequence == "L,L,L" then
        ChangeState(player_id, "AutoCombo1")
        return true
    elseif input_sequence == "L,L,M,H" then
        ChangeState(player_id, "AutoCombo2")
        return true
    end
    return false
end

-- Dynamic Camera
local function UpdateDBCamera()
    local p1 = GetPlayer(1)
    local p2 = GetPlayer(2)
   
    -- Calculate midpoint
    local mid_x = (p1.state.pos.x + p2.state.pos.x) / 2
    local mid_y = (p1.state.pos.y + p2.state.pos.y) / 2
   
    -- Zoom based on distance
    local distance = math.abs(p1.state.pos.x - p2.state.pos.x)
    local zoom = Clamp(1.0 - (distance / 1500), 0.7, 1.5)
   
    -- Update camera
    SetCameraPos(mid_x, mid_y)
    SetCameraZoom(zoom)
end

-- Main Update Loop
local function UpdateDBFZSystem()
    UpdateKi()
    UpdateDBCamera()
   
    for id = 1, 2 do
        local ply = GetPlayer(id)
       
        -- Update Sparking
        if ply.sparking.active then
            ply.sparking.timer = ply.sparking.timer - 1
            if ply.sparking.timer <= 0 then
                ply.sparking.active = false
            else
                -- Health regen
                local char = GetActiveChar(id)
                char.health = math.min(char.health + config.SPARKING_HEAL_RATE * char.max_health, char.max_health)
            end
        end
       
        -- Update Limit Break
        if ply.limit.active then
            ply.limit.timer = ply.limit.timer - 1
            if ply.limit.timer <= 0 then
                ply.limit.active = false
            end
        end
       
        -- Update Vanish
        if ply.vanish.active then
            ply.vanish.timer = ply.vanish.timer - 1
            if ply.vanish.timer <= 0 then
                ply.vanish.active = false
            end
        end
       
        -- Update Assist Cooldowns
        for i = 1, 3 do
            if ply.assists.cooldown > 0 then
                ply.assists.cooldown = ply.assists.cooldown - 1
            end
        end
       
        -- Update Z Change Cooldown
        if ply.zchange_cooldown > 0 then
            ply.zchange_cooldown = ply.zchange_cooldown - 1
        end
       
        -- Auto Limit Break check
        if #ply.team == 1 and not ply.limit.active then
            CheckLimitBreak(id)
        end
    end
end

-- Input Handling
local function HandleDBFZInput(player_id, input)
    local ply = GetPlayer(player_id)
   
    -- Sparking Blast
    if input == "A1+A2" then  -- Assists 1+2
        ActivateSparking(player_id)
   
    -- Vanish
    elseif input == "H+S" then  -- Heavy + Special
        PerformVanish(player_id)
   
    -- Dragon Rush
    elseif input == "L+M" then  -- Light + Medium forwards
        PerformDragonRush(player_id)
   
    -- Super Dash
    elseif input == "H" and ply.state.pos.y > 0 then  -- Heavy in air
        PerformSuperDash(player_id)
   
    -- Assists
    elseif input == "A1" then
        CallAssist(player_id, "A")
    elseif input == "A2" then
        CallAssist(player_id, "B")
    elseif input == "A3" then
        CallAssist(player_id, "C")
   
    -- Z Change
    elseif input == "B1+B2" then  -- Back + Assist
        PerformZChange(player_id, "back")
    elseif input == "F1+F2" then  -- Forward + Assist
        PerformZChange(player_id, "forward")
    end
   
    -- Auto-combo detection
    DetectAutoCombo(player_id, input)
end

-- Initialization
local function InitializeDBFZSystem(team1, team2)
    -- Set up teams
    players[1].team = team1 or {"Goku", "Vegeta", "Gohan"}
    players[2].team = team2 or {"Frieza", "Cell", "MajinBuu"}
   
    -- Set starting ki
    players[1].ki = 0
    players[2].ki = 0
   
    -- Set up hooks
    AddHook("GameTick", UpdateDBFZSystem)
   
    print("DBFZ System Initialized")
end

return {
    Init = InitializeDBFZSystem,
    HandleInput = HandleDBFZInput,
    GetPlayer = GetPlayer,
    config = config
}
"Thousands of humans falling over like dominoes... ahhh... that sight was so beautiful! I thought my brain was gonna melt..!"