-- SRB2 Persona Support for Cacee

if not srb2p return end

freeslot("SPR_MATA", "SPR_CEFS", "SPR_CEMT", "SPR_CEMD", "sfx_cegun", "sfx_cstar", "sfx_cethmp", "sfx_ceoops", "sfx_cetmad", "sfx_cevops")

for i = 1, 4
	freeslot("sfx_cora"..i)
	freeslot("sfx_cednc"..i)
end

for i = 1, 5
	freeslot("sfx_cejab"..i)
end

for i = 1, 3
	freeslot("sfx_cewht"..i)
end

for i = 1, 1
	freeslot("sfx_cesmb"..i)
end

for i = 1, 1
	freeslot("sfx_cetng"..i)
end

for i = 1, 3
	freeslot("S_DRIBBON_1_"..i)
end
states[S_DRIBBON_1_1] = {SPR_SLSH, A|FF_FULLBRIGHT|TR_TRANS70, 2, nil, 0, 0, S_DRIBBON_1_2}
states[S_DRIBBON_1_2] = {SPR_SLSH, B|FF_FULLBRIGHT|TR_TRANS70, 2, nil, 0, 0, S_DRIBBON_1_3}
states[S_DRIBBON_1_3] = {SPR_SLSH, C|FF_FULLBRIGHT|TR_TRANS70, 3, nil, 0, 0, S_NULL}

for i = 1, 4
	freeslot("S_DRIBBON_2_"..i)
end
states[S_DRIBBON_2_1] = {SPR_SLSH, D|FF_FULLBRIGHT|TR_TRANS70, 2, nil, 0, 0, S_DRIBBON_2_2}
states[S_DRIBBON_2_2] = {SPR_SLSH, E|FF_FULLBRIGHT|TR_TRANS70, 2, nil, 0, 0, S_DRIBBON_2_3}
states[S_DRIBBON_2_3] = {SPR_SLSH, F|FF_FULLBRIGHT|TR_TRANS70, 2, nil, 0, 0, S_DRIBBON_2_4}
states[S_DRIBBON_2_4] = {SPR_SLSH, G|FF_FULLBRIGHT|TR_TRANS70, 3, nil, 0, 0, S_NULL}

if not T_CaceeSongs
	rawset(_G, "T_CaceeSongs", {})
end

do
	local ogSongs = {
		samba = {sfx_cesmb1},
		tango = {sfx_cetng1}
	}
	
	for k,v in pairs(ogSongs)
		for i = 1, #v
			T_CaceeSongs[k] = v
		end
	end
end

function A_TearFall(mo)
	mo.momz = -3*FRACUNIT/2
end

for i = 1, 4
	freeslot("S_CETEAR"..i)
end
states[S_CETEAR1] = {SPR_CEMT, A|TR_TRANS30, 1, nil, 0, 0, S_CETEAR2}
states[S_CETEAR2] = {SPR_CEMT, A|TR_TRANS30, 10, A_TearFall, 0, 0, S_CETEAR3}
states[S_CETEAR3] = {SPR_CEMT, A|TR_TRANS50, 1, nil, 0, 0, S_CETEAR4}
states[S_CETEAR4] = {SPR_CEMT, A|TR_TRANS80, 1, nil, 0, 0, S_NULL}

for i = 1, 4
	freeslot("S_CEMAD"..i)
end
states[S_CEMAD1] = {SPR_CEMD, A|TR_TRANS30, 2, nil, 0, 0, S_CEMAD2}
states[S_CEMAD2] = {SPR_CEMD, B|TR_TRANS30, 2, nil, 0, 0, S_CEMAD3}
states[S_CEMAD3] = {SPR_CEMD, C|TR_TRANS30, 2, nil, 0, 0, S_CEMAD4}
states[S_CEMAD4] = {SPR_CEMD, D|TR_TRANS30, 2, nil, 0, 0, S_CEMAD1}

function A_FireworkExplode(mo)
	local pattern = P_RandomRange(1, 5)
	local grid
	mo.stars = {}
	
	if pattern == 1 //face
		grid = {{0, 18, SKINCOLOR_EMERALD},
				{-11, 16, SKINCOLOR_EMERALD},
				{-19, 9, SKINCOLOR_EMERALD},
				{-21, 0, SKINCOLOR_EMERALD},
				{0, -18, SKINCOLOR_EMERALD},
				{-11, -16, SKINCOLOR_EMERALD},
				{-19, -9, SKINCOLOR_EMERALD},
				{11, 16, SKINCOLOR_EMERALD},
				{19, 9, SKINCOLOR_EMERALD},
				{21, 0, SKINCOLOR_EMERALD},
				{11, -16, SKINCOLOR_EMERALD},
				{19, -9, SKINCOLOR_EMERALD},
				{-26, 10, SKINCOLOR_EMERALD},
				{-33, 14, SKINCOLOR_EMERALD},
				{-39, 21, SKINCOLOR_EMERALD},
				{-39, 31, SKINCOLOR_EMERALD},
				{-30, 35, SKINCOLOR_EMERALD},
				{-23, 29, SKINCOLOR_ROSY},
				{-17, 22, SKINCOLOR_EMERALD},
				{26, 10, SKINCOLOR_EMERALD},
				{33, 14, SKINCOLOR_EMERALD},
				{39, 21, SKINCOLOR_EMERALD},
				{39, 31, SKINCOLOR_EMERALD},
				{30, 35, SKINCOLOR_EMERALD},
				{23, 29, SKINCOLOR_EMERALD},
				{17, 22, SKINCOLOR_EMERALD},
				{-6, -23, SKINCOLOR_CRIMSON},
				{-19, -18, SKINCOLOR_CRIMSON},
				{6, -23, SKINCOLOR_CRIMSON},
				{19, -18, SKINCOLOR_CRIMSON},
				{-8, 8, SKINCOLOR_WHITE},
				{-12, 5, SKINCOLOR_WHITE},
				{-4, 5, SKINCOLOR_WHITE},
				{8, 8, SKINCOLOR_WHITE},
				{12, 5, SKINCOLOR_WHITE},
				{4, 5, SKINCOLOR_WHITE},
				{-7, -7, SKINCOLOR_WHITE},
				{7, -7, SKINCOLOR_WHITE},
				{0, -10, SKINCOLOR_WHITE}}
	elseif pattern == 2 //taco
		grid = {{-1, -19, SKINCOLOR_SUNSET},
				{6, -14, SKINCOLOR_SUNSET},
				{13, -9, SKINCOLOR_SUNSET},
				{20, -4, SKINCOLOR_SUNSET},
				{27, 1, SKINCOLOR_SUNSET},
				{25, 9, SKINCOLOR_SUNSET},
				{17, 15, SKINCOLOR_SUNSET},
				{7, 16, SKINCOLOR_SUNSET},
				{-2, 12, SKINCOLOR_SUNSET},
				{-10, 5, SKINCOLOR_SUNSET},
				{-15, -3, SKINCOLOR_SUNSET},
				{-16, -12, SKINCOLOR_SUNSET},
				{-17, -21, SKINCOLOR_SUNSET},
				{-15, -29, SKINCOLOR_SUNSET},
				{-8, -24, SKINCOLOR_SUNSET},
				{-24, -30, SKINCOLOR_SUNSET},
				{-33, -24, SKINCOLOR_SUNSET},
				{-33, -15, SKINCOLOR_BRONZE},
				{-25, -12, SKINCOLOR_BRONZE},
				{-26, -21, SKINCOLOR_BRONZE},
				{-31, -7, SKINCOLOR_EMERALD},
				{-24, -3, SKINCOLOR_EMERALD},
				{-30, 3, SKINCOLOR_CRIMSON},
				{-22, 5, SKINCOLOR_EMERALD},
				{-24, 13, SKINCOLOR_EMERALD},
				{-16, 12, SKINCOLOR_CRIMSON},
				{-16, 20, SKINCOLOR_EMERALD},
				{-8, 18, SKINCOLOR_EMERALD},
				{-8, 26, SKINCOLOR_CRIMSON},
				{0, 21, SKINCOLOR_EMERALD},
				{1, 29, SKINCOLOR_EMERALD},
				{8, 23, SKINCOLOR_CRIMSON},
				{15, 29, SKINCOLOR_EMERALD},
				{18, 22, SKINCOLOR_EMERALD},
				{25, 15, SKINCOLOR_CRIMSON}}
	elseif pattern == 3 //sombrero
		grid = {
				{-4, 0, SKINCOLOR_EMERALD},
				{4, 5, SKINCOLOR_CRIMSON},
				{-10, -7, SKINCOLOR_CRIMSON},
				{-17, 0, SKINCOLOR_SUNSET},
				{-13, 8, SKINCOLOR_SUNSET},
				{-5, 10, SKINCOLOR_SUNSET},
				{-2, -8, SKINCOLOR_SUNSET},
				{5, -2, SKINCOLOR_SUNSET},
				{12, 4, SKINCOLOR_EMERALD},
				{19, 10, SKINCOLOR_SUNSET},
				{27, 9, SKINCOLOR_SUNSET},
				{26, 2, SKINCOLOR_SUNSET},
				{19, -4, SKINCOLOR_EMERALD},
				{12, -10, SKINCOLOR_SUNSET},
				{5, -16, SKINCOLOR_SUNSET},
				{-2, -22, SKINCOLOR_EMERALD},
				{-9, -28, SKINCOLOR_SUNSET},
				{-17, -28, SKINCOLOR_SUNSET},
				{-16, -20, SKINCOLOR_SUNSET},
				{-9, -14, SKINCOLOR_EMERALD},
				{-9, -21, SKINCOLOR_CRIMSON},
				{-2, -15, SKINCOLOR_WHITE},
				{5, -9, SKINCOLOR_CRIMSON},
				{12, -3, SKINCOLOR_WHITE},
				{19, 3, SKINCOLOR_CRIMSON}}
	elseif pattern == 4 //maracas
		grid = {
				{0, 5, SKINCOLOR_SUNSET},
				{5, 0, SKINCOLOR_SUNSET},
				{-3, -3, SKINCOLOR_SUNSET},
				{-9, -9, SKINCOLOR_SUNSET},
				{-15, -15, SKINCOLOR_SUNSET},
				{-3, -15, SKINCOLOR_SUNSET},
				{3, -21, SKINCOLOR_SUNSET},
				{-12, -1, SKINCOLOR_SUNSET},
				{-17, -6, SKINCOLOR_SUNSET},
				{4, 19, SKINCOLOR_SUNSET},
				{11, 13, SKINCOLOR_SUNSET},
				{19, 6, SKINCOLOR_SUNSET},
				{17, 26, SKINCOLOR_SUNSET},
				{23, 20, SKINCOLOR_SUNSET},
				{-16, 13, SKINCOLOR_SUNSET},
				{-23, 7, SKINCOLOR_SUNSET},
				{-31, 0, SKINCOLOR_SUNSET},
				{-29, 20, SKINCOLOR_SUNSET},
				{-35, 14, SKINCOLOR_SUNSET},
				{-1, 12, SKINCOLOR_EMERALD},
				{7, 8, SKINCOLOR_EMERALD},
				{12, 1, SKINCOLOR_EMERALD},
				{-11, 6, SKINCOLOR_CRIMSON},
				{-19, 2, SKINCOLOR_CRIMSON},
				{-24, -5, SKINCOLOR_CRIMSON},
				{10, 25, SKINCOLOR_CRIMSON},
				{16, 18, SKINCOLOR_CRIMSON},
				{24, 13, SKINCOLOR_CRIMSON},
				{-22, 19, SKINCOLOR_EMERALD},
				{-28, 12, SKINCOLOR_EMERALD},
				{-36, 7, SKINCOLOR_EMERALD}}
	elseif pattern == 5 //fist
		grid = {
				{-22, 0, SKINCOLOR_CRIMSON},
				{-22, 8, SKINCOLOR_CRIMSON},
				{-21, 16, SKINCOLOR_CRIMSON},
				{-16, 23, SKINCOLOR_CRIMSON},
				{-9, 29, SKINCOLOR_CRIMSON},
				{0, 30, SKINCOLOR_CRIMSON},
				{9, 29, SKINCOLOR_CRIMSON},
				{16, 23, SKINCOLOR_CRIMSON},
				{21, 16, SKINCOLOR_CRIMSON},
				{18, 8, SKINCOLOR_CRIMSON},
				{11, 2, SKINCOLOR_CRIMSON},
				{9, -6, SKINCOLOR_CRIMSON},
				{18, -15, SKINCOLOR_CRIMSON},
				{25, -9, SKINCOLOR_CRIMSON},
				{28, -1, SKINCOLOR_CRIMSON},
				{25, 6, SKINCOLOR_CRIMSON},
				{-21, -8, SKINCOLOR_CRIMSON},
				{-17, -15, SKINCOLOR_CRIMSON},
				{-21, -22, SKINCOLOR_WHITE},
				{-13, -22, SKINCOLOR_PUREBLACK},
				{-5, -22, SKINCOLOR_PUREBLACK},
				{3, -22, SKINCOLOR_WHITE},
				{11, -22, SKINCOLOR_PUREBLACK},
				{19, -22, SKINCOLOR_PUREBLACK},
				{27, -22, SKINCOLOR_WHITE},
				{3, -29, SKINCOLOR_ROSY},
				{15, -29, SKINCOLOR_EMERALD},
				{-9, -29, SKINCOLOR_EMERALD},
				{8, -36, SKINCOLOR_EMERALD},
				{-2, -36, SKINCOLOR_EMERALD}}
	end
	
	playSound(mo.source.battlen, sfx_cannon)
	
	local x, y, z
	local hang = mo.cam.angle - ANG1*90
	local vang
	
	for i = 1, #grid
		x = grid[i][1]*cos(hang)
		y = grid[i][1]*sin(hang)
		
		local spark = P_SpawnMobj(mo.x + x, mo.y + y, mo.z + grid[i][2]*FRACUNIT, MT_NIGHTSPARKLE)
		spark.colorized = true
		spark.color = grid[i][3]
		spark.scale = FRACUNIT*2
		spark.tics = 70
		
		spark.momx = (spark.x - mo.x)/5
		spark.momy = (spark.y - mo.y)/5
		spark.momz = (spark.z - mo.z)/5
		
		mo.stars[#mo.stars+1] = spark
	end
	
	mo.flags2 = MF2_DONTDRAW
end

function A_FireworkStop(mo)
	if mo and mo.stars
		for i = 1, #mo.stars
			local m = mo.stars[i]
			
			if m and m.valid
				P_InstaThrust(m, 0, 0)
				m.momz = -FRACUNIT/8
			end
		end
	end
end

for i = 1, 5
	freeslot("S_DFRWORK_"..i)
end
states[S_DFRWORK_1] = {SPR_CEEMT, D|FF_FULLBRIGHT, 10, nil, 0, 0, S_DFRWORK_2}
states[S_DFRWORK_2] = {SPR_CEEMT, D|FF_FULLBRIGHT, 5, nil, 0, 0, S_DFRWORK_3}
states[S_DFRWORK_3] = {SPR_CEEMT, D|FF_FULLBRIGHT, 1, A_FireworkExplode, 0, 0, S_DFRWORK_4}
states[S_DFRWORK_4] = {SPR_CEEMT, D|FF_FULLBRIGHT, 5, nil, 0, 0, S_DFRWORK_5}
states[S_DFRWORK_5] = {SPR_CEEMT, D|FF_FULLBRIGHT, 1, A_FireworkStop, 0, 0, S_NULL}

local jabsounds = {sfx_cejab1, sfx_cejab2, sfx_cejab3, sfx_cejab4, sfx_cejab5}
local dancesounds = {sfx_cednc1, sfx_cednc2, sfx_cednc3, sfx_cednc4}
local caceewhat = {sfx_cewht1, sfx_cewht2, sfx_cewht3}
-- Define our base character's stats!
charStats["cacee"] = {

	-- GENERAL

	name = "Cacee",			-- This is only for bots / enemies
	basehp = 70,			-- base HP for level 1
	basesp = 30,
	persona = "ca-matador",
	persona_pvp = "ca-matador",
	melee_natk = "cacee_atk1",	-- normal melee attack

	supercolor_start = SKINCOLOR_SUPERRED1,

	atk = 35,
	acc = 999,
	crit = 2,
	
	wep = "cbg_01",
	weptype = WPT_KNUCKLES,
	-- ANIMS
	-- Anims are built like this:
	-- {SPR_SPRITE, frame1, frame2, frame3, ... , duration between each frame}

	anim_stand = 		{SPR_PLAY, A, 8, "SPR2_STND"},		-- standing
	anim_stand_hurt =	{SPR_PLAY, A, 1, "SPR2_STND"},		-- standing (low HP)
	anim_stand_bored =	{SPR_PLAY, A, B, C, D, E, F, G, H, 10, "SPR2_WAIT"},	-- standing (rare anim)
	anim_guard = 		{SPR_PLAY, A, 1, "SPR2_EDGE"},		-- guarding
	anim_move =			{SPR_PLAY, A, B, C, D, E, F, G, H, 2, "SPR2_WALK"},		-- moving
	anim_run =			{SPR_PLAY, A, B, C, D, 2, "SPR2_RUN_"},	-- guess what
	anim_atk =			{SPR_PLAY, A, B, C, D, 2, "SPR2_MLEE"},	-- attacking
	anim_aoa_end =		{SPR_PLAY, A, B, 2, "SPR2_FALL"},	-- jumping out of all-out attack
	anim_hurt =			{SPR_PLAY, A, 35, "SPR2_PAIN"},		-- taking damage
	anim_getdown =		{SPR_PLAY, A, 1, "SPR2_PAIN"},		-- knocked down from weakness / crit
	anim_downloop =		{SPR_PLAY, A, 1, "SPR2_PAIN"},		-- is down
	anim_getup =		{SPR_PLAY, A, B, C, D, 1, "SPR2_ROLL"},		-- gets up from down
	anim_death =		{SPR_PLAY, A, 30, "SPR2_DEAD"},		-- dies
	anim_revive =		{SPR_PLAY, A, B, C, D, 1, "SPR2_ROLL"},		-- gets revived
	anim_evoker =		{SPR_PLAY, A, 2, "SPR2_TWIN"},	-- uses evoker
	anim_evoker_shoot = {SPR_PLAY, B, A, 2, "SPR2_TWIN"},
	
	anim_stand_super = {SPR_PLAY, A, B, C, D, 2, "SPR2_STND"},
	anim_stand_bored_super = {SPR_PLAY, A, B, C, D, 2, "SPR2_STND"},
	anim_run_super = {SPR_PLAY, A, B, 2, "SPR2_RUN_"},

	anim_special1 = {SPR_PLAY, A, B, 2, "SPR2_GLID"}, -- hammer prep
	anim_special2 = {SPR_PLAY, A, 2, "SPR2_MLEL"}, -- hammer swing
	anim_special3 = {SPR_PLAY, A, B, C, D, 1, "SPR2_MLEE"}, -- left jab
	anim_special4 = {SPR_PLAY, A, B, C, D, 1, "SPR2_FIRE"}, -- right jab
	anim_special5 = {SPR_PLAY, C, 1, "SPR2_TWIN"}, -- rising upper
	anim_special6 = {SPR_PLAY, A, 1, "SPR2_SPNG"}, -- jumping up
	anim_special7 = {SPR_PLAY, A, 1, "SPR2_CLMB"}, -- neutral special
	anim_special8 = {SPR_PLAY, A, 1, "SPR2_MLEE"}, -- grab
	
	vfx_summon = {"sfx_cepers", "sfx_cego"},	-- Summoning Persona to use a Skill
	vfx_skill = {"sfx_ceskl1", "sfx_ceskl2", "sfx_ceskl3"},		-- Used a Skill
	vfx_item = {"sfx_ceitem"},		-- Used an item
	vfx_hurt = {"sfx_ceoof", "sfx_ceouch"},		-- Sustained damage
	vfx_hurtx = {"sfx_ceyow", "sfx_cehey"},		-- Sustained heavy damage / Critical hit / Weakness
	vfx_tartarus_spikepit = {"sfx_ceptf1", "sfx_ceptf2"},
	vfx_tartarus_pit = {"sfx_ceptf1", "sfx_ceptf2"},
	vfx_die = {"sfx_ceptf1", "sfx_ceptf2", "sfx_cedead"},		-- Death
	vfx_heal = {"sfx_cehel1", "sfx_cehel3"},		-- Healed by teammate
	vfx_healself = {"sfx_cehel2", "sfx_cehel3"},	-- Healed self
	vfx_kill = {"sfx_cenmed"},		-- Killed an enemy
	vfx_1more = {"sfx_cecut", "sfx_cehit", "sfx_cenmed"},		-- Performed 1more
	vfx_crit = {"sfx_cecrit", "sfx_ceskl1"},		-- Cut-in for Weakness/Critical Hit
	vfx_aoaask = {"sfx_cecnfm"},	-- Ask to All-Out Attack
	vfx_aoado = {"sfx_ceallo"},		-- Performing All-Out Attack
	vfx_aoarelent = {"sfx_cenoal"},	-- Relenting from All-Out Attack
	vfx_miss = {"sfx_cemiss", "sfx_cenowy", "sfx_ceoof"},		-- Missed attack
	vfx_dodge = {"sfx_ceddge", "sfx_ceno", "sfx_ceglot"},		-- Dodged enemy attack
	vfx_win = {"sfx_cewin1", "sfx_cewin2"},		-- Battle won
	vfx_levelup = {"sfx_celvl"},	-- Level Up!

	icon = "ICO_CACE",	-- icon for net select and other menus
	hudbust = "H_CACEBAR",			-- patch to draw on the stat hud
	hudbustlayer = "",		-- transparent patch to draw for status conditions
	hudaoa = "H_CACEAOA",	-- patch for all out attack hud
	aoa_quote = "All enemies are \ndown ese, shall \nwe dogpile?",
	hudcutin = "CACE_A",	-- cut in
	hudspr = "CACE",	-- sprite prefix since hud can't retrieve it. yikes

	tip = "A sneaky little devil with a thorny hide that specializes in Strike skills. She has the special ability to combo her moves, and can build a passive buff by dodging. Careful, though! While her agility is good, her defense is not.",
}

VFX_freeslotC("cacee")

local function caceecircle(mobj, mobjtype, amount, ns, zoffset, scale, keepmom, color, vertical, vertangle)
	local i = 0	while i < amount
		local fa = i*(ANGLE_180/(amount/2))
		local mo = P_SpawnMobjFromMobj(mobj,0,0,zoffset,mobjtype)
		if mo and mo.valid
			local height = mo.height
			mo.scale = scale
			mo.target = mobj
			if mobj.eflags&MFE_VERTICALFLIP
				mo.z = $-(mo.height-height)
			end
			if mobjtype == MT_MINECARTSPARK
				mo.fuse = TICRATE
			end
			if color
				mo.color = color
				mo.colorized = true
			end
			if mo.type == MT_THOK
				mo.colorized = false
				mo.fuse = mo.tics
			end
			if vertical
				mo.momz = FixedMul(sin(fa),ns)
				P_InstaThrust(mo, vertangle+ANGLE_90,
				FixedMul(cos(fa),ns))
			else
				mo.momx = FixedMul(sin(fa),ns)
				mo.momy = FixedMul(cos(fa),ns)
			end
			if keepmom
				mo.momx = $+mobj.momx
				mo.momy = $+mobj.momy
				mo.momz = $+mobj.momz
			end
		end
		i = $+1
	end
end

attackDefs["cacee_atk1"] = {
	name = "Spike Rush",
	type = ATK_STRIKE,
	power = 45,
	accuracy = 85,
	critical = 7,
	target = TGT_ENEMY,
	cost = CST_HP,
	cost = 0,
	desc = "A strong left jab.",
	norandom = true,
	norogue = true,
	nometronome = true,
	noenemycast = true,
	anim_norepel = true,	-- do not bounce back our ANIMATION
	physical = true,	-- don't play the summoning anim for phys attacks, duh
	anim = 	function(mo, targets, hittargets, timer)
		local target = targets[1]
		if timer == 1
			ANIM_set(mo, mo.anim_special1, true)
			playSound(mo.battlen, sfx_cepun3)
			
			local rand = P_RandomRange(1, 10)
			if rand <= 5
				playSound(mo.battlen, jabsounds[rand])
			end
			
			P_SpawnParaloop(mo.x, mo.y, mo.z,
			mo.radius*4, 8, MT_DUST, ANGLE_90, nil, true)

			-- fake A_LobShot:
			mo.angle = R_PointToAngle2(mo.x, mo.y, target.x, target.y)

			local z = mo.z
			local hit = P_SpawnMobj(target.x & (64*FRACUNIT -1), target.y & (64*FRACUNIT -1), target.subsector.sector.floorheight, MT_NULL)
			hit.tics = 20

			local dist = P_AproxDistance(target.x - mo.x, target.y - mo.y)
			local horizontal = dist / 20
			local vertical = FixedMul((gravity*20)/2, mo.scale)

			mo.momx = FixedMul(horizontal, cos(mo.angle))
			mo.momy = FixedMul(horizontal, sin(mo.angle))
			mo.momz = vertical


			-- move camera to an interresting spot

			local an = target.angle + 45*ANG1

			local cx = target.x + 384*cos(an)
			local cy = target.y + 384*sin(an)

			CAM_goto(server.P_BattleStatus[mo.battlen].cam, cx, cy, server.P_BattleStatus[mo.battlen].cam.z, 70*FRACUNIT)
			CAM_angle(server.P_BattleStatus[mo.battlen].cam, R_PointToAngle2(cx, cy, target.x, target.y), ANG1*4)
			--CAM_aiming(server.P_BattleStatus[mo.battlen].cam, -ANG1*10, ANG1)
		
		elseif timer < 20 and timer%2
			local ghost = P_SpawnGhostMobj(mo)
			ghost.colorized = true
			ghost.color = SKINCOLOR_FLAME

		elseif timer == 20
			damageObject(hittargets[1])
			
			mo.spikerush = true
			
			ANIM_set(mo, mo.anim_special2, true)
			P_InstaThrust(mo, 0, 0)

			for i = 1, 8
				local h = P_SpawnMobj(target.x, target.y, target.z, MT_DUMMY)
				h.state = S_SSPK1
				h.fuse = TICRATE
				P_InstaThrust(h, (360/8 *i)*ANG1, FRACUNIT*32)

				if i%2
					createSplat(mo)
				end
			end

			localquake(mo.battlen, FRACUNIT*30, 8)
			playSound(mo.battlen, sfx_cepun4)
			playSound(mo.battlen, sfx_cehit1)
			
			local boom = P_SpawnMobjFromMobj(target, 0, 0, target.height/2, MT_DUMMY)
			boom.state = S_CACEE_HIT1

			for i = 1, 16
				local h = P_SpawnMobj(target.x, target.y, target.z, MT_DUMMY)
				h.state = S_SSPK1
				h.fuse = TICRATE
				h.momx = P_RandomRange(-24, 24)*FRACUNIT
				h.momy = P_RandomRange(-24, 24)*FRACUNIT
				h.momz = P_RandomRange(2, 24)*FRACUNIT
			end
			
			local ghost = P_SpawnGhostMobj(mo)
			ghost.colorized = true
			ghost.color = SKINCOLOR_FLAME
			ghost.destscale = $*16
			
		elseif timer == TICRATE*2
			if mo.cacee and mo.cacee.combo and mo.spikerush and mo.cacee.charisma
				mo.cacee.roll[#mo.cacee.roll+1] = "Spike Rush"
			end
			
			return true
		end
	end,
}

attackDefs["c-double rush"] = {
	name = "Double Rush",
	type = ATK_STRIKE,
	power = 300,
	accuracy = 90,
	costtype = CST_HPPERCENT,
	cost = 13,
	critical = 1,
	hits = 2,
	anim_norepel = true,
	norandom = true,
	norogue = true,
	nometronome = true,
	noenemycast = true,
	desc = "Medium Strike damage to \none enemy 2x. Lowers DEF\nif comboed from Spike Rush.",
	target = TGT_ENEMY,
	anim = function(mo, targets, hittargets, timer)
		local target = hittargets[1]

		if timer == 10
			mo.flags = $|MF_NOCLIPHEIGHT|MF_NOGRAVITY
			mo.momx = (target.x - mo.x)/30
			mo.momy = (target.y - mo.y)/30
			playSound(mo.battlen, sfx_zoom)
			ANIM_set(mo, mo.anim_run, true)
		elseif timer == 20
			mo.momx = (target.x - mo.x)/10
			mo.momy = (target.y - mo.y)/10
			playSound(mo.battlen, sfx_cepun1)
			ANIM_set(mo, mo.anim_special3)
			
			local rand = P_RandomRange(1, 10)
			if rand <= 5
				playSound(mo.battlen, jabsounds[rand])
			end
			
			local an = target.angle + 45*ANG1

			local cx = target.x + 384*cos(an)
			local cy = target.y + 384*sin(an)
			CAM_goto(server.P_BattleStatus[mo.battlen].cam, cx, cy, server.P_BattleStatus[mo.battlen].cam.z, 70*FRACUNIT)
			CAM_angle(server.P_BattleStatus[mo.battlen].cam, R_PointToAngle2(cx, cy, target.x, target.y), ANG1*4)
		elseif timer > 20 and timer < 30
			local ghost = P_SpawnGhostMobj(mo)
			ghost.colorized = true
			ghost.color = SKINCOLOR_CRIMSON
		elseif timer == 30
			playSound(mo.battlen, sfx_cehit1)
			mo.flags = $ - MF_NOCLIPHEIGHT - MF_NOGRAVITY
			mo.momx = -$
			mo.momy = -$
			
			local boom = P_SpawnMobjFromMobj(target, 0, 0, target.height/2, MT_DUMMY)
			boom.state = S_CACEE_HIT1

			for i = 1, 16
				local h = P_SpawnMobj(target.x, target.y, target.z, MT_DUMMY)
				h.state = S_SSPK1
				h.fuse = TICRATE
				h.momx = P_RandomRange(-24, 24)*FRACUNIT
				h.momy = P_RandomRange(-24, 24)*FRACUNIT
				h.momz = P_RandomRange(2, 24)*FRACUNIT
			end
			
			damageObject(target)
			
			local d = P_SpawnMobj(target.x, target.y, target.z+128*FRACUNIT, MT_THOK)
			d.sprite = SPR_THMP
			d.frame = A|FF_FULLBRIGHT
			d.scale = FRACUNIT/4
			d.destscale = FRACUNIT*3
			d.scalespeed = FRACUNIT/8
			d.fuse = TICRATE-10
			d.tics = d.fuse
			d.momz = FRACUNIT*2
			d.momx = P_RandomRange(0, FRACUNIT-1)*P_RandomRange(-8, 8)
			d.momy = P_RandomRange(0, FRACUNIT-1)*P_RandomRange(-8, 8)
			d.color = SKINCOLOR_RED
		elseif timer == 35
			mo.momx = (target.x - mo.x)/10
			mo.momy = (target.y - mo.y)/10
			playSound(mo.battlen, sfx_cepun2)
			ANIM_set(mo, mo.anim_special4)
		elseif timer > 35 and timer < 40
			local ghost = P_SpawnGhostMobj(mo)
			ghost.colorized = true
			ghost.color = SKINCOLOR_CRIMSON
		elseif timer == 45
			playSound(mo.battlen, sfx_cehit3)
			
			local boom = P_SpawnMobjFromMobj(target, 0, 0, target.height/2, MT_DUMMY)
			boom.state = S_CACEE_HIT1

			for i = 1, 16
				local h = P_SpawnMobj(target.x, target.y, target.z, MT_DUMMY)
				h.state = S_SSPK1
				h.fuse = TICRATE
				h.momx = P_RandomRange(-24, 24)*FRACUNIT
				h.momy = P_RandomRange(-24, 24)*FRACUNIT
				h.momz = P_RandomRange(2, 24)*FRACUNIT
			end
			
			damageObject(target)
			
			if mo.spikerush
			and target.damagestate ~= DMG_MISS		-- make sure we landed the attack
			and target.damagestate ~= DMG_BLOCK
			and target.damagestate ~= DMG_DRAIN
				buffStat(target, "def", -BUFFSTEP)	-- negative values lower a stat
				playSound(mo.battlen, sfx_s3k8c)
				local dbuff = P_SpawnMobj(target.x, target.y, target.z+target.height, MT_DUMMY)
				dbuff.state = S_DBUFF1
				dbuff.color = SKINCOLOR_LAVENDER
				dbuff.scale = FRACUNIT*5/2
			end
			
			local d = P_SpawnMobj(target.x, target.y, target.z+128*FRACUNIT, MT_THOK)
			d.sprite = SPR_THMP
			d.frame = B|FF_FULLBRIGHT
			d.scale = FRACUNIT/4
			d.destscale = FRACUNIT*3
			d.scalespeed = FRACUNIT/8
			d.fuse = TICRATE-10
			d.tics = d.fuse
			d.momz = FRACUNIT*2
			d.momx = P_RandomRange(0, FRACUNIT-1)*P_RandomRange(-8, 8)
			d.momy = P_RandomRange(0, FRACUNIT-1)*P_RandomRange(-8, 8)
			d.color = SKINCOLOR_RED
		elseif timer == 65
			mo.spikerush = false
			
			if mo.cacee and mo.cacee.combo and mo.cacee.charisma >= 1
				mo.cacee.roll[#mo.cacee.roll+1] = "Double Rush"
				mo.cacee.combo[1] = 3
			end
			
			return true
		end
	end,
}

attackDefs["red capote"] = {
	name = "Red Capote",
	type = ATK_SUPPORT,
	costtype = CST_SP,
	cost = 1,
	desc = "Raise your agility by 3\nstages. Because who needs\nbalance?",
	target = TGT_CASTER,
	buff = true,
	norepel = true,
	nocast = 	function(targets, n)	-- we can't cast this skill if this function returns true
					local target = targets[n]
					if target.buffs["agi"][2] >= 9
						BTL_logMessage(targets[1].battlen, "Limit reached!")
						return true
					end
				end,
	anim = function(mo, targets, hittargets, timer)
		local target = hittargets[1]

		if timer == 20
		or timer == 50
		or timer == 80
			playSound(mo.battlen, sfx_buff)
			buffStat(target, "agi")
			
			if timer == 80
				BTL_logMessage(targets[1].battlen, "Vete a la mierda.")
				mo.flags = MF_NOGRAVITY
				mo.momz = FRACUNIT/16
			end
			
			for i = 1,16
				local dust = P_SpawnMobj(target.x, target.y, target.z, MT_DUMMY)
				dust.angle = ANGLE_90 + ANG1* (22*(i-1))
				dust.state = S_CDUST1
				P_InstaThrust(dust, dust.angle, 30*FRACUNIT)
				dust.color = SKINCOLOR_GREEN
				dust.scale = FRACUNIT*2
			end

		elseif (timer > 20 and timer <= 40)
		or (timer > 50 and timer <= 70)
		or (timer > 80 and timer <= 100)
			mo.momz = 3*$/2

			if leveltime%2 == 0
				for i = 1,16

					local thok = P_SpawnMobj(target.x+P_RandomRange(-70, 70)*FRACUNIT, target.y+P_RandomRange(-70, 70)*FRACUNIT, target.z+P_RandomRange(0, 50)*FRACUNIT, MT_DUMMY)
					thok.state = S_CDUST1
					thok.momz = P_RandomRange(3, 10)*FRACUNIT
					thok.color = SKINCOLOR_GREEN
					thok.tics = P_RandomRange(10, 35)
					thok.scale = FRACUNIT*3/2
				end
			end

			local thok = P_SpawnMobj(target.x+P_RandomRange(-70, 70)*FRACUNIT, target.y+P_RandomRange(-70, 70)*FRACUNIT, target.z+P_RandomRange(0, 50)*FRACUNIT, MT_DUMMY)
			thok.sprite = SPR_SUMN
			thok.frame = F|FF_FULLBRIGHT|TR_TRANS50
			thok.momz = P_RandomRange(6, 16)*FRACUNIT
			thok.color = SKINCOLOR_GREEN
			thok.tics = P_RandomRange(10, 35)
		elseif timer == 120
			return true
		end
	end,
}

attackDefs["c-desert fury"] = {
	name = "Desert Fury",
	type = ATK_STRIKE,
	power = 500,
	accuracy = 90,
	costtype = CST_HPPERCENT,
	cost = 20,
	critical = 2,
	hits = 3,
	norandom = true,
	norogue = true,
	nometronome = true,
	noenemycast = true,
	desc = "Medium Strike damage to one\nenemy 3x. 50% of damage is\nspread to other enemies.",
	target = TGT_ENEMY,
	anim = function(mo, targets, hittargets, timer)
		local target = hittargets[1]

		if timer == 10
			mo.flags = $|MF_NOCLIPHEIGHT|MF_NOGRAVITY
			mo.momx = (target.x - mo.x)/30
			mo.momy = (target.y - mo.y)/30
			playSound(mo.battlen, sfx_zoom)
			ANIM_set(mo, mo.anim_run, true)
			
			local damage = 0
			local btl = server.P_BattleStatus[mo.battlen]
			for i = 1, #server.P_BattleStatus[mo.battlen].dmg_hits[target.dmg_index]
				if type(btl.dmg_hits[target.dmg_index][i]) == "number"
					damage = $ + btl.dmg_hits[target.dmg_index][i]
				end
			end
			mo.spreaddamage = damage
		elseif timer == 20
			mo.momx = (target.x - mo.x)/10
			mo.momy = (target.y - mo.y)/10
			playSound(mo.battlen, sfx_cepun1)
			ANIM_set(mo, mo.anim_special3)
			
			local an = target.angle + 45*ANG1

			local cx = target.x + 384*cos(an)
			local cy = target.y + 384*sin(an)
			CAM_goto(server.P_BattleStatus[mo.battlen].cam, cx, cy, server.P_BattleStatus[mo.battlen].cam.z, 70*FRACUNIT)
			CAM_angle(server.P_BattleStatus[mo.battlen].cam, R_PointToAngle2(cx, cy, target.x, target.y), ANG1*4)
			
			local rand = P_RandomRange(1, 10)
			if rand <= 5
				playSound(mo.battlen, jabsounds[rand])
			end
		elseif timer > 20 and timer < 30
			local ghost = P_SpawnGhostMobj(mo)
			ghost.colorized = true
			ghost.color = SKINCOLOR_CRIMSON
		elseif timer == 30
			playSound(mo.battlen, sfx_cehit1)
			mo.flags = $ - MF_NOCLIPHEIGHT - MF_NOGRAVITY
			mo.momx = -$
			mo.momy = -$
			
			local boom = P_SpawnMobjFromMobj(target, 0, 0, target.height/2, MT_DUMMY)
			boom.state = S_CACEE_HIT1

			for i = 1, 16
				local h = P_SpawnMobj(target.x, target.y, target.z, MT_DUMMY)
				h.state = S_SSPK1
				h.fuse = TICRATE
				h.momx = P_RandomRange(-24, 24)*FRACUNIT
				h.momy = P_RandomRange(-24, 24)*FRACUNIT
				h.momz = P_RandomRange(2, 24)*FRACUNIT
			end
			
			damageObject(target)
			
			local d = P_SpawnMobj(target.x, target.y, target.z+128*FRACUNIT, MT_THOK)
			d.sprite = SPR_THMP
			d.frame = A|FF_FULLBRIGHT
			d.scale = FRACUNIT/4
			d.destscale = FRACUNIT*3
			d.scalespeed = FRACUNIT/8
			d.fuse = TICRATE-10
			d.tics = d.fuse
			d.momz = FRACUNIT*2
			d.momx = P_RandomRange(0, FRACUNIT-1)*P_RandomRange(-8, 8)
			d.momy = P_RandomRange(0, FRACUNIT-1)*P_RandomRange(-8, 8)
			d.color = SKINCOLOR_RED
		elseif timer == 35
			mo.momx = (target.x - mo.x)/10
			mo.momy = (target.y - mo.y)/10
			playSound(mo.battlen, sfx_cepun2)
			ANIM_set(mo, mo.anim_special4)
		elseif (timer > 35 and timer < 40) or (timer > 50 and timer < 55)
			local ghost = P_SpawnGhostMobj(mo)
			ghost.colorized = true
			ghost.color = ((timer > 50) and SKINCOLOR_SUPERGOLD2 or SKINCOLOR_CRIMSON)
		elseif timer == 45
			playSound(mo.battlen, sfx_cehit3)
			
			local boom = P_SpawnMobjFromMobj(target, 0, 0, target.height/2, MT_DUMMY)
			boom.state = S_CACEE_HIT1

			for i = 1, 16
				local h = P_SpawnMobj(target.x, target.y, target.z, MT_DUMMY)
				h.state = S_SSPK1
				h.fuse = TICRATE
				h.momx = P_RandomRange(-24, 24)*FRACUNIT
				h.momy = P_RandomRange(-24, 24)*FRACUNIT
				h.momz = P_RandomRange(2, 24)*FRACUNIT
			end
			
			damageObject(target)
			
			local d = P_SpawnMobj(target.x, target.y, target.z+128*FRACUNIT, MT_THOK)
			d.sprite = SPR_THMP
			d.frame = A|FF_FULLBRIGHT
			d.scale = FRACUNIT/4
			d.destscale = FRACUNIT*3
			d.scalespeed = FRACUNIT/8
			d.fuse = TICRATE-10
			d.tics = d.fuse
			d.momz = FRACUNIT*2
			d.momx = P_RandomRange(0, FRACUNIT-1)*P_RandomRange(-8, 8)
			d.momy = P_RandomRange(0, FRACUNIT-1)*P_RandomRange(-8, 8)
			d.color = SKINCOLOR_RED
			
			mo.momx = -3*$/2
			mo.momy = -3*$/2
		elseif timer == 50
			ANIM_set(mo, mo.anim_special1, true)
			playSound(mo.battlen, sfx_cepun3)
			
			P_SpawnParaloop(mo.x, mo.y, mo.z,
			mo.radius*4, 8, MT_DUST, ANGLE_90, nil, true)

			-- fake A_LobShot:
			mo.angle = R_PointToAngle2(mo.x, mo.y, target.x, target.y)

			local z = mo.z
			local hit = P_SpawnMobj(target.x & (64*FRACUNIT -1), target.y & (64*FRACUNIT -1), target.subsector.sector.floorheight, MT_NULL)
			hit.tics = 20

			local dist = P_AproxDistance(target.x - mo.x, target.y - mo.y)
			local horizontal = dist / 10
			local vertical = FixedMul((gravity*10)/2, mo.scale)

			mo.momx = FixedMul(horizontal, cos(mo.angle))
			mo.momy = FixedMul(horizontal, sin(mo.angle))
			mo.momz = vertical
		elseif timer == 60
			damageObject(target)
			playSound(mo.battlen, sfx_cepun4)
			localquake(mo.battlen, FRACUNIT*30, 8)
			
			local d = P_SpawnMobj(target.x, target.y, target.z+128*FRACUNIT, MT_THOK)
			d.sprite = SPR_THMP
			d.frame = B|FF_FULLBRIGHT
			d.scale = FRACUNIT/4
			d.destscale = FRACUNIT*3
			d.scalespeed = FRACUNIT/8
			d.fuse = TICRATE-10
			d.tics = d.fuse
			d.momz = FRACUNIT*2
			d.momx = P_RandomRange(0, FRACUNIT-1)*P_RandomRange(-8, 8)
			d.momy = P_RandomRange(0, FRACUNIT-1)*P_RandomRange(-8, 8)
			d.color = SKINCOLOR_SUPERGOLD2
			
			caceecircle(mo, MT_SUPERSPARK, 16, 32*mo.scale, 0, mo.scale, false, 0, false, mo.angle)
			caceecircle(mo, MT_MINECARTSPARK, 8, 8*mo.scale, 0, mo.scale/4, false, 0, false, mo.angle)
			
			local thok = P_SpawnMobjFromMobj(mo,0,0,0,MT_THOK)
			thok.state = S_CACEE_HIT1
			thok.flags2 = $|MF2_SPLAT
			thok.scale = $*2
			thok.blendmode = AST_ADD
			
			local ghost = P_SpawnGhostMobj(mo)
			ghost.colorized = true
			ghost.color = SKINCOLOR_SUPERGOLD2
			ghost.destscale = $*16
		elseif timer == 70
			if type(mo.spreaddamage) == "number"
				if #target.allies > 1
					playSound(mo.battlen, sfx_ceboom)
				end
				
				for i = 1, #target.allies
					local targ = target.allies[i]
					if targ == target continue end

					for i = 1, 16
						local h = P_SpawnMobj(targ.x, targ.y, targ.z, MT_DUMMY)
						h.state = S_SSPK1
						h.fuse = TICRATE
						h.momx = P_RandomRange(-24, 24)*FRACUNIT
						h.momy = P_RandomRange(-24, 24)*FRACUNIT
						h.momz = P_RandomRange(2, 24)*FRACUNIT
					end
					
					targ.momz = FixedMul((gravity*15)/2, mo.scale)
					
					damageObject(targ, mo.spreaddamage/2)
				end
			end
		elseif timer == 100
			if mo.cacee and mo.cacee.combo and mo.cacee.charisma >= 1
				mo.cacee.combo[1] = 0
				mo.cacee.roll[#mo.cacee.roll+1] = "Desert Fury"
				if mo.cacee.charisma >= 3 then mo.cacee.combo[4] = 2 end
			end
			
			return true
		end
	end,
}

attackDefs["c-desert torment"] = {
	name = "Tormenta del Desierto",
	type = ATK_STRIKE,
	power = 900,
	accuracy = 90,
	costtype = CST_HPPERCENT,
	cost = 20,
	critical = 3,
	hits = 3,
	norandom = true,
	norogue = true,
	nometronome = true,
	noenemycast = true,
	desc = "Heavy Strike damage to one\nenemy 3x. 60% of damage is\nspread to other enemies.",
	target = TGT_ENEMY,
	anim = function(mo, targets, hittargets, timer)
		local color = SKINCOLOR_TEAL
		local target = hittargets[1]
		local cam = server.P_BattleStatus[mo.battlen].cam
		
		if timer == 1
			mo.columns = {}
			local damage = 0
			local btl = server.P_BattleStatus[mo.battlen]
			for i = 1, #server.P_BattleStatus[mo.battlen].dmg_hits[target.dmg_index]
				if type(btl.dmg_hits[target.dmg_index][i]) == "number"
					damage = $ + btl.dmg_hits[target.dmg_index][i]
				end
			end
			mo.spreaddamage = damage
		elseif timer == 10
			ANIM_set(mo, mo.anim_guard)
			mo.angle = R_PointToAngle2(mo.x, mo.y, target.x, target.y)
			mo.ogpos = {mo.x, mo.y, mo.z}
			target.ogpos = {target.x, target.y, target.z}
			cam.ogpos = {cam.x, cam.y, cam.z, cam.angle}
			mo.flags = $|MF_NOGRAVITY|MF_NOCLIPHEIGHT
		elseif timer == 20
			mo.colorized = true
			mo.ghost = P_SpawnGhostMobj(mo)
			mo.ghost.fuse = 15
			mo.frame = $|TR_TRANS50
			playSound(mo.battlen, sfx_wind1)
			playSound(mo.battlen, sfx_thok)
			
			P_InstaThrust(mo.ghost, mo.angle + ANGLE_90, FRACUNIT*4)
			P_InstaThrust(mo, mo.angle - ANGLE_90, FRACUNIT*4)
			
			for i = 1, 8
				local g = P_SpawnMobj(target.x, target.y, target.z + P_RandomRange(0, 60)*FRACUNIT, MT_GARU)
				g.target = target
				g.angle = FixedAngle(P_RandomRange(1, 360)*FRACUNIT)
				if i == 1 or i == 8
					g.jizzcolor = true
				end
				if i%2
					g.invertrotation = true
				end
				g.dist = P_RandomRange(45, 90)
				g.tics = 5
			end
			
			local an = target.angle + 45*ANG1

			local cx = target.x + 384*cos(an)
			local cy = target.y + 384*sin(an)
			CAM_goto(cam, cx, cy, cam.z, 35*FRACUNIT)
			CAM_angle(cam, R_PointToAngle2(cx, cy, target.x, target.y), ANG1*4)
		elseif timer == 25
			local dest = P_SpawnMobj(target.x + 60*cos(mo.angle), target.y + 60*sin(mo.angle), target.z, MT_DUMMY)
			dest.scale = S_INVISIBLE
			P_TeleportMove(mo, dest.x + 22*cos(mo.angle + ANGLE_90), dest.y + 22*sin(mo.angle + ANGLE_90), mo.z)
			P_TeleportMove(mo.ghost, dest.x + 22*cos(mo.angle - ANGLE_90), dest.y + 22*sin(mo.angle - ANGLE_90), mo.z)
			
			P_InstaThrust(mo, mo.angle - ANGLE_90, FRACUNIT*4)
			P_InstaThrust(mo, mo.angle + ANGLE_90, FRACUNIT*4)
		elseif timer == 30
			mo.angle = R_PointToAngle2(mo.x, mo.y, target.x, target.y)
			P_InstaThrust(mo, mo.angle, 0)
			
			mo.frame = $& ~TR_TRANS50
			mo.colorized = false
			
			playSound(mo.battlen, sfx_cepun1)
			P_InstaThrust(mo, mo.angle, FRACUNIT*6)
			ANIM_set(mo, mo.anim_special3)
		elseif timer > 30 and timer < 40
			local ghost = P_SpawnGhostMobj(mo)
			ghost.colorized = true
			ghost.color = SKINCOLOR_RED
			ghost.frame = $|FF_FULLBRIGHT
		elseif timer == 40
			target.flags = $|MF_NOGRAVITY|MF_NOCLIPHEIGHT
			damageObject(target)
			local ang = R_PointToAngle2(target.x, target.y, mo.ogpos[1], mo.ogpos[2])
			local dist = R_PointToDist2(target.x, target.y, mo.ogpos[1], mo.ogpos[2])
			P_InstaThrust(target, ang, dist/30)
			
			localquake(mo.battlen, FRACUNIT*15, 5)

			caceecircle(mo, MT_DUST, 16, 16*mo.scale, 0, mo.scale, false, 0, false, mo.angle)
			
			playSound(mo.battlen, sfx_cehit1)
			
			local boom = P_SpawnMobjFromMobj(target, 0, 0, target.height/2, MT_DUMMY)
			boom.state = S_CACEE_HIT1
			
			local d = P_SpawnMobj(target.x, target.y, target.z+128*FRACUNIT, MT_THOK)
			d.sprite = SPR_THMP
			d.frame = A|FF_FULLBRIGHT
			d.scale = FRACUNIT/4
			d.destscale = FRACUNIT*3
			d.scalespeed = FRACUNIT/8
			d.fuse = TICRATE-10
			d.tics = d.fuse
			d.momz = FRACUNIT*2
			d.momx = P_RandomRange(0, FRACUNIT-1)*P_RandomRange(-8, 8)
			d.momy = P_RandomRange(0, FRACUNIT-1)*P_RandomRange(-8, 8)
			d.color = SKINCOLOR_RED
		elseif timer == 45
			ANIM_set(mo, mo.anim_guard)
		elseif timer == 50
			mo.colorized = true
			mo.ghost = P_SpawnGhostMobj(mo)
			mo.ghost.fuse = 15
			mo.frame = $|TR_TRANS50
			playSound(mo.battlen, sfx_wind1)
			playSound(mo.battlen, sfx_thok)
			
			P_InstaThrust(mo.ghost, mo.angle + ANGLE_90, FRACUNIT*4)
			P_InstaThrust(mo, mo.angle - ANGLE_90, FRACUNIT*4)
			
			for i = 1, 8
				local g = P_SpawnMobj(target.x, target.y, target.z + P_RandomRange(0, 60)*FRACUNIT, MT_GARU)
				g.target = target
				g.angle = FixedAngle(P_RandomRange(1, 360)*FRACUNIT)
				if i == 1 or i == 8
					g.jizzcolor = true
				end
				if i%2
					g.invertrotation = true
				end
				g.dist = P_RandomRange(45, 90)
				g.tics = 5
			end
			
			CAM_goto(cam, cam.ogpos[1], cam.ogpos[2], cam.ogpos[3], 35*FRACUNIT)
			CAM_angle(cam, cam.ogpos[4], ANG1*4)
		elseif timer == 55
			P_TeleportMove(mo, mo.ogpos[1], mo.ogpos[2], mo.z)
			mo.angle = R_PointToAngle2(mo.x, mo.y, target.x, target.y)
			
			P_TeleportMove(mo.ghost, mo.x + 22*cos(mo.angle + ANGLE_90), mo.y + 22*sin(mo.angle + ANGLE_90), mo.z)
			P_TeleportMove(mo, mo.x + 22*cos(mo.angle - ANGLE_90), mo.y + 22*sin(mo.angle - ANGLE_90), mo.z)
			
			P_InstaThrust(mo, mo.angle - ANGLE_90, FRACUNIT*4)
			P_InstaThrust(mo, mo.angle + ANGLE_90, FRACUNIT*4)
		elseif timer == 60
			P_InstaThrust(mo, mo.angle, 0)
			
			mo.frame = $& ~TR_TRANS50
			mo.colorized = false
			
			mo.flags = $|MF_NOGRAVITY|MF_NOCLIPHEIGHT
		elseif timer == 65
			ANIM_set(mo, mo.anim_special5, true)
			damageObject(target)
			localquake(mo.battlen, FRACUNIT*20, 10)
			mo.flags = $ & ~MF_NOGRAVITY
			mo.flags = $ & ~MF_NOCLIPHEIGHT
			mo.momz = mo.scale*5
			
			local dist = R_PointToDist2(target.x, target.y, target.ogpos[1], target.ogpos[2])
			P_InstaThrust(target, mo.angle, dist/50)
			target.flags = $ & ~MF_NOGRAVITY
			target.flags = $ & ~MF_NOCLIPHEIGHT
			target.momz = 20*target.scale

			caceecircle(mo, MT_DUST, 16, 16*mo.scale, 0, mo.scale, false, 0, false, mo.angle)
			playSound(mo.battlen, sfx_ceuppr)
			
			playSound(mo.battlen, sfx_cehit3)
			
			local boom = P_SpawnMobjFromMobj(target, 0, 0, target.height/2, MT_DUMMY)
			boom.state = S_CACEE_HIT1
			
			local d = P_SpawnMobj(target.x, target.y, target.z+128*FRACUNIT, MT_THOK)
			d.sprite = SPR_THMP
			d.frame = A|FF_FULLBRIGHT
			d.scale = FRACUNIT/4
			d.destscale = FRACUNIT*3
			d.scalespeed = FRACUNIT/8
			d.fuse = TICRATE-10
			d.tics = d.fuse
			d.momz = FRACUNIT*2
			d.momx = P_RandomRange(0, FRACUNIT-1)*P_RandomRange(-8, 8)
			d.momy = P_RandomRange(0, FRACUNIT-1)*P_RandomRange(-8, 8)
			d.color = SKINCOLOR_RED
			
			local rand = P_RandomRange(1, 10)
			if rand <= 5
				playSound(mo.battlen, jabsounds[rand])
			elseif rand == 6
				playSound(mo.battlen, sfx_ceshok)
			end
		elseif timer == 75
			ANIM_set(mo, mo.anim_guard, true)
		elseif timer == 85
			local dist = R_PointToDist2(mo.x, mo.y, target.ogpos[1], target.ogpos[2])
			P_InstaThrust(mo, mo.angle, dist/21)
			mo.momz = mo.scale*50
			
			local thok = P_SpawnMobjFromMobj(mo,0,0,0,MT_THOK)
			thok.state = S_CACEE_HIT1
			thok.flags2 = $|MF2_SPLAT
			thok.scale = $*2
			thok.blendmode = AST_ADD
			
			ANIM_set(mo, mo.anim_special6)
			localquake(mo.battlen, FRACUNIT*30, 5)
			playSound(mo.battlen, sfx_s3k90)
			playSound(mo.battlen, sfx_sprong)
			
			local rand = P_RandomRange(1, 10)
			if rand <= 5
				playSound(mo.battlen, jabsounds[rand])
			end
			
			for i = 1,16
				local dust = P_SpawnMobj(mo.x, mo.y, mo.z, MT_DUMMY)
				dust.angle = ANG1*(ANGLE_22h*(i-1))
				dust.destscale = FRACUNIT*5
				dust.state = S_AOADUST1
				dust.frame = A|FF_FULLBRIGHT
				P_InstaThrust(dust, dust.angle, 20*FRACUNIT)
			end
		elseif timer > 85 and timer < 95
			local ghost = P_SpawnGhostMobj(mo)
			ghost.color = SKINCOLOR_SUPERGOLD2
			ghost.colorized = true
			ghost.frame = $|FF_FULLBRIGHT
			
			caceecircle(mo, MT_SUPERSPARK, 16, 32*mo.scale, 0, mo.scale, false, 0, false, mo.angle)
			caceecircle(mo, MT_MINECARTSPARK, 8, 8*mo.scale, 0, mo.scale/4, false, 0, false, mo.angle)
			
			cam.z = $ + 8*FRACUNIT
		elseif timer == 95
			P_InstaThrust(mo, 0, 0)
			mo.momz = 0
			ANIM_set(mo, mo.anim_special2)
			playSound(mo.battlen, sfx_s3k4e)
			for i = 1, #server.P_BattleStatus[mo.battlen].fighters
				for i = 1, #server.playerlist[mo.battlen]
					if server.playerlist[mo.battlen][i]
						P_FlashPal(server.playerlist[mo.battlen][i], 4, 15)
					end
				end
			end
			
			local dist = R_PointToDist2(target.x, target.y, target.ogpos[1], target.ogpos[2])
			P_InstaThrust(target, mo.angle, dist/5)
			target.momz = (target.floorz - target.z)/5
			
			caceecircle(mo, MT_SUPERSPARK, 16, 16*mo.scale, 0, mo.scale, false, 0, false, mo.angle)
			
			playSound(mo.battlen, sfx_cehit3)
			
			local boom = P_SpawnMobjFromMobj(target, 0, 0, target.height/2, MT_DUMMY)
			boom.state = S_CACEE_HIT1
			boom.scale = $*5
			
			local d = P_SpawnMobj(target.x, target.y, target.z+128*FRACUNIT, MT_THOK)
			d.sprite = SPR_THMP
			d.frame = B|FF_FULLBRIGHT
			d.scale = FRACUNIT/4
			d.destscale = FRACUNIT*3
			d.scalespeed = FRACUNIT/8
			d.fuse = TICRATE-10
			d.tics = d.fuse
			d.momz = FRACUNIT*2
			d.momx = P_RandomRange(0, FRACUNIT-1)*P_RandomRange(-8, 8)
			d.momy = P_RandomRange(0, FRACUNIT-1)*P_RandomRange(-8, 8)
			d.color = SKINCOLOR_SUPERGOLD2
			
			local rand = P_RandomRange(1, 10)
			if rand <= 5
				playSound(mo.battlen, jabsounds[rand])
			elseif rand == 6
				playSound(mo.battlen, sfx_ceshok)
			end
		elseif timer > 95 and timer < 100
			local ghost = P_SpawnGhostMobj(target)
			ghost.colorized = true
			ghost.color = SKINCOLOR_GREY
			
			cam.z = $ - 6*FRACUNIT
		elseif timer == 100
			damageObject(target)
			P_InstaThrust(target, 0, 0)
			mo.fangle = (R_PointToAngle(target.x, target.y)) + ANG1*180
			mo.fdist = 96
			mo.columns = {}
			
			local a = mo.fangle - ANG1*80
			DoExplosion(target)
			playSound(mo.battlen, sfx_s3k4e)
			
			local thok = P_SpawnMobjFromMobj(mo,0,0,0,MT_THOK)
			thok.state = S_CACEE_HIT1
			thok.flags2 = $|MF2_SPLAT
			thok.scale = $*10
			thok.blendmode = AST_ADD
			localquake(mo.battlen, FRACUNIT*20, 10)
			
			for i = 1,16
				local dust = P_SpawnMobj(mo.x, mo.y, mo.z, MT_DUMMY)
				dust.angle = ANG1*(ANGLE_22h*(i-1))
				dust.destscale = FRACUNIT*5
				dust.state = S_AOADUST1
				dust.frame = A|FF_FULLBRIGHT
				P_InstaThrust(dust, dust.angle, 20*FRACUNIT)
			end

			for i = 1, 16
				local m = P_SpawnMobj(target.x, target.y, target.z, MT_DUMMY)
				P_InstaThrust(m, a, FRACUNIT*48)
				mo.columns[#mo.columns+1] = m
				m.state = S_INVISIBLE
				m.tics = TICRATE
				a = $+ ANG1*10
			end
		elseif timer == 115
			if type(mo.spreaddamage) == "number"
				if #target.allies > 1
					playSound(mo.battlen, sfx_ceboom)
				end
				
				for i = 1, #target.allies
					local targ = target.allies[i]
					if targ == target continue end

					DoExplosion(targ)
					
					targ.momz = FixedMul((gravity*15)/2, mo.scale)
					
					damageObject(targ, 6*mo.spreaddamage/10)
				end
			end
		end
		
		if timer > 95 and P_IsObjectOnGround(mo) and not mo.done
			mo.done = true
			ANIM_set(mo, mo.anim_special6, true)
			playSound(mo.battlen, sfx_s220)

			mo.angle = R_PointToAngle2(mo.x, mo.y, mo.ogpos[1], mo.ogpos[2])

			local dist = P_AproxDistance(mo.ogpos[1] - mo.x, mo.ogpos[2] - mo.y)
			local horizontal = dist / TICRATE
			local vertical = FixedMul((gravity*TICRATE)/2, mo.scale)

			mo.momx = FixedMul(horizontal, cos(mo.angle))
			mo.momy = FixedMul(horizontal, sin(mo.angle))
			mo.momz = vertical
		elseif timer > 95 and P_IsObjectOnGround(mo) and mo.done
			ANIM_set(mo, mo.anim_stand)
			mo.angle = R_PointToAngle2(mo.x, mo.y, target.x, target.y)
			P_InstaThrust(mo, 0, 0)
		end
		
		local j = #mo.columns
		while j

			local m = mo.columns[j]
			if not m or not m.valid
				j = $-1
				continue
			end

			for i = 1, 5
				local boom = P_SpawnMobj(m.x + P_RandomRange(-48, 48)*FRACUNIT, m.y + P_RandomRange(-48, 48)*FRACUNIT, m.z, MT_DUMMY)
				boom.state = S_QUICKBOOM1
				boom.momz = P_RandomRange(0, 48)*FRACUNIT
				boom.scale = FRACUNIT*3/2
			end
			localquake(mo.battlen, FRACUNIT*8, 1)

			if timer <= 140
				local an = (mo.fangle + (j-1)*120)*ANG1
				P_TeleportMove(m, target.x + mo.fdist*cos(an), target.y + mo.fdist*sin(an), target.z)
			end

			j = $-1

		end
		
		if timer == 200
			mo.columns = nil
			mo.fangle = nil
			mo.fdist = nil
			mo.ogpos = nil
			mo.done = nil
			target.ogpos = nil
			cam.ogpos = nil
			
			if mo.cacee and mo.cacee.combo
				mo.cacee.combo[1] = 0
				mo.cacee.roll[#mo.cacee.roll+1] = "Tormenta del Desierto"
				if mo.cacee.charisma >= 4 then mo.cacee.combo[5] = 2 end
			end
			
			return true
		end
	end,
}

local dupecheck = function(atk)
	local dupe = true
	local rand = 0
	while dupe
		dupe = false
		rand = P_RandomRange(1,5)
		
		for i = 1, #atk
			if rand == atk[i][1]
				dupe = true
			end
		end
	end
	
	return rand
end

attackDefs["c-felona finale"] = {
	name = "Felona Finale",
	type = ATK_STRIKE,
	power = 1500,
	accuracy = 90,
	costtype = CST_HPPERCENT,
	cost = 20,
	critical = 3,
	hits = 6,
	norandom = true,
	norogue = true,
	nometronome = true,
	noenemycast = true,
	desc = "Damage based on current dodge\nstacks. Combo and 2 dodge stacks\nare consumed. 75% damage spread.",
	target = TGT_ENEMY,
	anim = function(mo, targets, hittargets, timer)
		local target = hittargets[1]
		local cam = server.P_BattleStatus[mo.battlen].cam
		local stacks = mo.cacee and mo.cacee.dstacks or 3
		//local stacks = 5
		if mo.felonadone then mo.felonadone = $ + 1 end
		if mo.hitground then mo.hitground = $ + 1 end

		if timer == 1
			mo.felona_attacks = {}
			mo.columns = {}
			mo.ghosts = {0, 0, 0, 0, 0}
			mo.angle = R_PointToAngle2(mo.x, mo.y, target.x, target.y)
			cam.ogpos = {cam.x, cam.y, cam.z, cam.angle}
			
			local damage = 0
			local btl = server.P_BattleStatus[mo.battlen]
			for i = 1, #server.P_BattleStatus[mo.battlen].dmg_hits[target.dmg_index]
				if type(btl.dmg_hits[target.dmg_index][i]) == "number"
					damage = $ + btl.dmg_hits[target.dmg_index][i]
				end
			end
			mo.spreaddamage = damage
		elseif timer == 15
			playSound(mo.battlen, sfx_s3ka3)
		elseif timer > 20 and timer < 70
			ANIM_set(mo, mo.anim_guard)
			
			if timer%8 == 0
				local ghost = P_SpawnGhostMobj(mo)
				ghost.destscale = FRACUNIT*3
				ghost.colorized = true
				ghost.color = SKINCOLOR_FLAME
				ghost.frame = $|FF_FULLBRIGHT
				ghost.scalespeed = FRACUNIT/8
				playSound(mo.battlen, sfx_s3kc2s) // that's a funny sfx name
			end
		elseif timer == 70
			ANIM_set(mo, mo.anim_special6)
			playSound(mo.battlen, sfx_sprong)
			mo.momz = FRACUNIT*30
			mo.flags = $|MF_NOGRAVITY
			
			local thok = P_SpawnMobjFromMobj(mo,0,0,0,MT_THOK)
			thok.state = S_CACEE_HIT1
			thok.flags2 = $|MF2_SPLAT
			thok.scale = $*4
			thok.blendmode = AST_ADD
			
			localquake(mo.battlen, FRACUNIT*20, 10)
			
			local rand = P_RandomRange(1, 10)
			if rand <= 5
				playSound(mo.battlen, jabsounds[rand])
			end
			
			for i = 1,16
				local dust = P_SpawnMobj(mo.x, mo.y, mo.z, MT_DUMMY)
				dust.angle = ANG1*(ANGLE_22h*(i-1))
				dust.destscale = FRACUNIT*5
				dust.state = S_AOADUST1
				dust.frame = A|FF_FULLBRIGHT
				P_InstaThrust(dust, dust.angle, 20*FRACUNIT)
			end
		elseif timer == 73
			mo.colorized = true
			for i = 1, stacks
				local ghost = P_SpawnGhostMobj(mo)
				ghost.fuse = 12
				ANIM_set(ghost, mo.anim_aoa_end)
				ghost.angle = mo.angle + i*ANG1*(360/stacks)
				P_InstaThrust(ghost, ghost.angle, FRACUNIT*4)
				ghost.flags = $ & ~MF_NOGRAVITY
			end
			mo.frame = $|TR_TRANS50
			
			if not stacks then mo.felonadone = 40 end
		elseif timer == 75
			local an = target.angle + 45*ANG1

			local cx = target.x + 384*cos(an)
			local cy = target.y + 384*sin(an)
			CAM_goto(cam, cx, cy, cam.z, 35*FRACUNIT)
			CAM_angle(cam, R_PointToAngle2(cx, cy, target.x, target.y), ANG1*4)
		elseif timer == 80
			mo.frame = $ & ~TR_TRANS50
			
			if not mo.felonadone
				mo.felona_attacks[#mo.felona_attacks+1] = {P_RandomRange(1,5), 1}
				
			end
			
			if stacks <= 1
				mo.felonadone = 1
			end
		elseif timer == 100 and not mo.felonadone
			mo.felona_attacks[#mo.felona_attacks+1] = {dupecheck(mo.felona_attacks), 1}
			
			if stacks <= 2
				mo.felonadone = 1
			end
		elseif timer == 120 and not mo.felonadone
			mo.felona_attacks[#mo.felona_attacks+1] = {dupecheck(mo.felona_attacks), 1}
			
			if stacks <= 3
				mo.felonadone = 1
			end
		elseif timer == 140 and not mo.felonadone
			mo.felona_attacks[#mo.felona_attacks+1] = {dupecheck(mo.felona_attacks), 1}
			
			if stacks <= 4
				mo.felonadone = 1
			end
		elseif timer == 160 and not mo.felonadone
			mo.felona_attacks[#mo.felona_attacks+1] = {dupecheck(mo.felona_attacks), 1}
			
			mo.felonadone = 1
		end
		
		if mo.felonadone
			local time = mo.felonadone
			
			if time == 60
				P_TeleportMove(mo, target.x, target.y, mo.z)
				mo.colorized = false
				ANIM_set(mo, mo.anim_special2)
				
				mo.momz = -FRACUNIT*60
				mo.flags = $ & ~MF_NOGRAVITY
				
				CAM_goto(cam, cam.ogpos[1], cam.ogpos[2], cam.ogpos[3], 35*FRACUNIT)
				CAM_angle(cam, cam.ogpos[4], ANG1*4)
			elseif time > 60 and not mo.hitground
				if P_IsObjectOnGround(mo)
					mo.hitground = 1
					
					damageObject(target)
					mo.fangle = (R_PointToAngle(target.x, target.y)) + ANG1*180
					mo.fdist = 96
					mo.columns = {}
					
					local a = mo.fangle - ANG1*80
					DoExplosion(target)
					playSound(mo.battlen, sfx_s3k4e)
					
					local thok = P_SpawnMobjFromMobj(mo,0,0,0,MT_THOK)
					thok.state = S_CACEE_HIT1
					thok.flags2 = $|MF2_SPLAT
					thok.scale = $*10
					thok.blendmode = AST_ADD
					localquake(mo.battlen, FRACUNIT*20, 10)
					
					for i = 1,16
						local dust = P_SpawnMobj(mo.x, mo.y, mo.z, MT_DUMMY)
						dust.angle = ANG1*(ANGLE_22h*(i-1))
						dust.destscale = FRACUNIT*5
						dust.state = S_AOADUST1
						dust.frame = A|FF_FULLBRIGHT
						P_InstaThrust(dust, dust.angle, 20*FRACUNIT)
					end

					for i = 1, 16
						local m = P_SpawnMobj(target.x, target.y, target.z, MT_DUMMY)
						P_InstaThrust(m, a, FRACUNIT*48)
						mo.columns[#mo.columns+1] = m
						m.state = S_INVISIBLE
						m.tics = TICRATE
						a = $+ ANG1*10
					end
				else
					local ghost = P_SpawnGhostMobj(mo)
					ghost.colorized = true
					ghost.frame = $|FF_FULLBRIGHT
					ghost.color = SKINCOLOR_FLAME
					
					caceecircle(mo, MT_SUPERSPARK, 16, 32*mo.scale, 0, mo.scale, false, 0, false, mo.angle)
					caceecircle(mo, MT_MINECARTSPARK, 8, 8*mo.scale, 0, mo.scale/4, false, 0, false, mo.angle)
				end
			end
		end
		
		if mo.hitground
			local time = mo.hitground
			if time == 15
				playSound(mo.battlen, sfx_crumbl)
				for j = 1, 16
					local rock = P_SpawnMobj(target.x, target.y, target.floorz, MT_FALLINGROCK)
					rock.scale = FRACUNIT
					P_InstaThrust(rock, mo.angle + ANGLE_22h*j, FRACUNIT*15)
					rock.momz = FRACUNIT*5
					rock.fuse = TICRATE/2
				end
				
				for i = 1,16
					local dust = P_SpawnMobj(mo.x, mo.y, mo.z, MT_DUMMY)
					dust.angle = ANGLE_90 + ANG1* (ANGLE_11hh*(i-1))
					dust.destscale = FRACUNIT*10
					dust.scale = FRACUNIT
					dust.state = S_AOADUST1
					dust.frame = A|FF_FULLBRIGHT|TR_TRANS60
					P_InstaThrust(dust, dust.angle, 20*FRACUNIT)
				end
				
			elseif time == 22
				if mo.spreaddamage > 0
					if #target.allies > 1
						playSound(mo.battlen, sfx_ceboom)
					end
					
					for i = 1, #target.allies
						local targ = target.allies[i]
						if targ == target continue end

						DoExplosion(targ)
						
						targ.momz = FixedMul((gravity*15)/2, mo.scale)
						
						damageObject(targ, 3*mo.spreaddamage/4)
					end
				end
			elseif time == 30
				playSound(mo.battlen, sfx_crumbl)
				for j = 1, 16
					local rock = P_SpawnMobj(target.x + 70*cos(target.angle + i*ANGLE_22h), target.y + 70*sin(target.angle + i*ANGLE_22h), target.floorz, MT_FALLINGROCK)
					rock.scale = 3*FRACUNIT/2
					P_InstaThrust(rock, mo.angle + ANGLE_22h*j, FRACUNIT*20)
					rock.momz = FRACUNIT*8
					rock.fuse = TICRATE/2
				end
			elseif time == 45
				playSound(mo.battlen, sfx_s1b9)
				for j = 1, 16
					local rock = P_SpawnMobj(target.x + 140*cos(target.angle + i*ANGLE_22h), target.y + 140*sin(target.angle + i*ANGLE_22h), target.floorz, MT_FALLINGROCK)
					rock.scale = 2*FRACUNIT
					P_InstaThrust(rock, mo.angle + ANGLE_22h*j, FRACUNIT*30)
					rock.momz = FRACUNIT*12
					rock.fuse = TICRATE/2
				end
			elseif time == 70
				mo.felonadone = nil
				mo.felona_attacks = nil
				mo.hitground = nil
				mo.ghosts = nil
				mo.columns = nil
				mo.fangle = nil
				mo.fdist = nil
				cam.ogpos = nil
				
				if mo.cacee and mo.cacee.combo
					mo.cacee.combo[1] = 0
					mo.cacee.combo[2] = 0
					mo.cacee.combo[3] = 0
					mo.cacee.combo[4] = 0
					mo.cacee.combo[5] = 0
					mo.cacee.dstacks = max(0, $ - 2)
					mo.cacee.roll[#mo.cacee.roll+1] = "Felona Finale"
				end
				
				return true
			end
		end
		
		local j = #mo.felona_attacks
		while j
			local m = mo.felona_attacks[j]
			if not m or m[2] > 60
				j = $-1
				continue
			end
			
			local time = m[2]
			local index = m[1]
			if not mo.ghosts[index]
				mo.ghosts[index] = P_SpawnGhostMobj(mo)
				mo.ghosts[index].fuse = 60
				mo.ghosts[index].angle = P_RandomRange(1,359)*ANG1
			end
			local ghost = mo.ghosts[index]

			if index == 1
				if time == 1
					ghost.fists = {}
					P_TeleportMove(ghost, target.x + 200*cos(P_RandomRange(1, 359)*ANG1), target.y + 200*sin(P_RandomRange(1, 359)*ANG1), target.z)
					ghost.angle = R_PointToAngle2(ghost.x, ghost.y, target.x, target.y)
				elseif time == 5
					local dist = R_PointToDist2(ghost.x, ghost.y, target.x, target.y)
					P_InstaThrust(ghost, ghost.angle, dist/12)
					ANIM_set(ghost, mo.anim_run, true)
				elseif time == 14
					P_InstaThrust(ghost, ghost.angle, 0)
					localquake(mo.battlen, FRACUNIT*30, 5)
					playSound(mo.battlen, sfx_ceboom)
					
					local boom = P_SpawnMobjFromMobj(target, 0, 0, target.height, MT_DUMMY)
					boom.state = S_CACEE_HIT1

					for i = 1, 16
						local h = P_SpawnMobj(target.x, target.y, target.z, MT_DUMMY)
						h.state = S_SSPK1
						h.fuse = TICRATE
						h.momx = P_RandomRange(-24, 24)*FRACUNIT
						h.momy = P_RandomRange(-24, 24)*FRACUNIT
						h.momz = P_RandomRange(2, 24)*FRACUNIT
					end
					
					local d = P_SpawnMobj(target.x, target.y, target.z+128*FRACUNIT, MT_THOK)
					d.sprite = SPR_THMP
					d.frame = A|FF_FULLBRIGHT
					d.scale = FRACUNIT/4
					d.destscale = FRACUNIT*3
					d.scalespeed = FRACUNIT/8
					d.fuse = TICRATE-10
					d.tics = d.fuse
					d.momz = FRACUNIT*2
					d.momx = P_RandomRange(0, FRACUNIT-1)*P_RandomRange(-8, 8)
					d.momy = P_RandomRange(0, FRACUNIT-1)*P_RandomRange(-8, 8)
					d.color = SKINCOLOR_RED
				elseif time == 15
					playSound(mo.battlen, sfx_megi6)
					local s = P_SpawnMobj(ghost.x, ghost.y, ghost.z + ghost.height, MT_DUMMY)
					s.color = SKINCOLOR_WHITE
					s.state = S_MEGISTAR1
					s.scale = FRACUNIT/4
				elseif time == 25
					localquake(mo.battlen, FRACUNIT*20, 60)
					ANIM_set(ghost, mo.anim_guard, true)
					
					if (P_RandomRange(1,10) == 10 or mo.name == "\x4A\x6F\x74\x61\x72\x6F") and mo.name ~= "\x44\x49\x4F"
						playSound(mo.battlen, (P_RandomRange(0,1) and sfx_cora1 or sfx_cora2))
					elseif P_RandomRange(1,10) == 9 or mo.name == "\x44\x49\x4F"
						playSound(mo.battlen, (P_RandomRange(0,1) and sfx_cora3 or sfx_cora4))
					end
				elseif time > 25 and time <= 50
					local rd = P_RandomRange(0,1) and -1 or 1
					local ang = (R_PointToAngle2(ghost.x, ghost.y, target.x, target.y) + rd*ANGLE_90 + P_RandomRange(-10, 10)*ANG1)
					local fist = P_SpawnMobj(ghost.x + (P_RandomRange(10, 50)*cos(ang)),
											 ghost.y + (P_RandomRange(10, 50)*sin(ang)),
											 ghost.z + P_RandomRange(10, 60)*FRACUNIT, MT_DUMMY)
					fist.angle = R_PointToAngle2(fist.x, fist.y, target.x, target.y)
					fist.tics = 6
					fist.sprite = SPR_CEFS
					fist.colorized = true
					fist.frame = A|TR_TRANS60
					fist.momx = (target.x - fist.x)/4
					fist.momy = (target.y - fist.y)/4
					fist.scale = 5*FRACUNIT/4
					ghost.fists[#ghost.fists+1] = fist
					
					if time%2 == 0	
						local boom = P_SpawnMobjFromMobj(target, P_RandomRange(-20, 20)*FRACUNIT, P_RandomRange(-20, 20)*FRACUNIT, target.height + P_RandomRange(-20, 20)*FRACUNIT, MT_DUMMY)
						boom.state = S_CACEE_HIT1
						boom.scale = FRACUNIT/4
					end
					
					if time%8 == 0
						playSound(mo.battlen, sfx_hit)
					end
					
					local h = P_SpawnMobj(target.x, target.y, target.z, MT_DUMMY)
					h.state = S_SSPK1
					h.fuse = TICRATE
					h.momx = P_RandomRange(-24, 24)*FRACUNIT
					h.momy = P_RandomRange(-24, 24)*FRACUNIT
					h.momz = P_RandomRange(2, 24)*FRACUNIT
				elseif time == 57
					local ang = R_PointToAngle2(ghost.x, ghost.y, target.x, target.y)
					ANIM_set(ghost, mo.anim_special4)
					P_InstaThrust(ghost, ang, 20*FRACUNIT)
					
					local rand = P_RandomRange(1, 10)
					if rand <= 5
						playSound(mo.battlen, jabsounds[rand])
					end
				elseif time == 60
					damageObject(target)
					localquake(mo.battlen, FRACUNIT*30, 5)
					playSound(mo.battlen, sfx_ceboom)
					
					local boom = P_SpawnMobjFromMobj(target, 0, 0, target.height, MT_DUMMY)
					boom.state = S_CACEE_HIT1

					for i = 1, 16
						local h = P_SpawnMobj(target.x, target.y, target.z, MT_DUMMY)
						h.state = S_SSPK1
						h.fuse = TICRATE
						h.momx = P_RandomRange(-24, 24)*FRACUNIT
						h.momy = P_RandomRange(-24, 24)*FRACUNIT
						h.momz = P_RandomRange(2, 24)*FRACUNIT
					end
					
					local d = P_SpawnMobj(target.x, target.y, target.z+128*FRACUNIT, MT_THOK)
					d.sprite = SPR_THMP
					d.frame = B|FF_FULLBRIGHT|TR_TRANS50
					d.scale = FRACUNIT/4
					d.destscale = FRACUNIT*3
					d.scalespeed = FRACUNIT/8
					d.fuse = TICRATE-10
					d.tics = d.fuse
					d.momz = FRACUNIT*2
					d.momx = P_RandomRange(0, FRACUNIT-1)*P_RandomRange(-8, 8)
					d.momy = P_RandomRange(0, FRACUNIT-1)*P_RandomRange(-8, 8)
					d.color = SKINCOLOR_RED
				end
				
				for i = 1, #ghost.fists
					local fist = ghost.fists[i]
					if fist and fist.valid
						local ghost = P_SpawnGhostMobj(fist)
						ghost.colorized = true
						ghost.color = SKINCOLOR_SUPERGOLD2
						ghost.frame = A|TR_TRANS40|FF_FULLBRIGHT
						ghost.destscale = 1
						ghost.scalespeed = FRACUNIT/6
					end
				end
				
				m[2] = $ + 1
			elseif index == 2
				if time == 1
					ANIM_set(ghost, mo.anim_aoa_guard, true)
					P_TeleportMove(ghost, target.x + 200*cos(P_RandomRange(1, 359)*ANG1), target.y + 200*sin(P_RandomRange(1, 359)*ANG1), target.z)
					ghost.angle = R_PointToAngle2(ghost.x, ghost.y, target.x, target.y)
				elseif time >= 10 and time <= 20 and time%5 == 0
					local ghost2 = P_SpawnGhostMobj(ghost)
					ghost2.tics = 10
					ghost2.colorized = true
					ghost2.color = SKINCOLOR_SUPERGOLD2
					ghost2.destscale = FRACUNIT*2
				elseif time == 40
					ghost.flags = $|MF_NOCLIPHEIGHT|MF_NOGRAVITY
					ghost.momx = (target.x - ghost.x)/10
					ghost.momy = (target.y - ghost.y)/10
					playSound(mo.battlen, sfx_zoom)
					ANIM_set(ghost, mo.anim_run, true)
					
					local rand = P_RandomRange(1, 10)
					if rand <= 5
						playSound(mo.battlen, jabsounds[rand])
					end
				elseif time > 40 and time < 50
					local ghost2 = P_SpawnGhostMobj(ghost)
					ghost2.tics = 10
					ghost2.colorized = true
					ghost2.color = SKINCOLOR_RED
					
					if time == 45
						ANIM_set(ghost, mo.anim_special4, true)
					end
				elseif time == 50
					ghost.flags = $ & ~MF_NOCLIPHEIGHT
					ghost.flags = $ & ~MF_NOGRAVITY
					damageObject(target)
					localquake(mo.battlen, FRACUNIT*30, 5)
					playSound(mo.battlen, sfx_ceboom)
					
					local boom = P_SpawnMobjFromMobj(target, 0, 0, target.height, MT_DUMMY)
					boom.state = S_CACEE_HIT1

					for i = 1, 16
						local h = P_SpawnMobj(target.x, target.y, target.z, MT_DUMMY)
						h.state = S_SSPK1
						h.fuse = TICRATE
						h.momx = P_RandomRange(-24, 24)*FRACUNIT
						h.momy = P_RandomRange(-24, 24)*FRACUNIT
						h.momz = P_RandomRange(2, 24)*FRACUNIT
					end
					
					local d = P_SpawnMobj(target.x, target.y, target.z+128*FRACUNIT, MT_THOK)
					d.sprite = SPR_THMP
					d.frame = A|FF_FULLBRIGHT|TR_TRANS50
					d.scale = FRACUNIT/4
					d.destscale = FRACUNIT*3
					d.scalespeed = FRACUNIT/8
					d.fuse = TICRATE-10
					d.tics = d.fuse
					d.momz = FRACUNIT*2
					d.momx = P_RandomRange(0, FRACUNIT-1)*P_RandomRange(-8, 8)
					d.momy = P_RandomRange(0, FRACUNIT-1)*P_RandomRange(-8, 8)
					d.color = SKINCOLOR_RED
				end
				
				m[2] = $ + 1
			elseif index == 3
				if time == 1
					ANIM_set(ghost, mo.anim_stand, true)
					ghost.frame = $|TR_TRANS50
					P_TeleportMove(ghost, target.x + 130*cos(P_RandomRange(1, 359)*ANG1), target.y + 130*sin(P_RandomRange(1, 359)*ANG1), target.z)
					ghost.angle = R_PointToAngle2(ghost.x, ghost.y, target.x, target.y)
				elseif time == 15
					playSound(mo.battlen, sfx_s3k4c)
					ANIM_set(ghost, mo.anim_special7)
					ghost.frame = $|TR_TRANS50
				elseif time >= 27 and time <= 47 and time%5 == 2
					for i = 1, 15
						P_SpawnMobj(ghost.x + ((target.x - ghost.x)*i)/15, ghost.y + ((target.y - ghost.y)*i)/15, ghost.z + ghost.height/2, MT_SPARK)
					end
					
					playSound(mo.battlen, sfx_cegun)
					playSound(mo.battlen, sfx_rail1)
					
					local bang = P_SpawnMobj(ghost.x, ghost.y, ghost.z + ghost.height/2, MT_DUMMY)
					bang.state = S_QUICKBOOM1
					P_InstaThrust(ghost, ghost.angle + ANGLE_180, FRACUNIT*5)
				elseif time >= 30 and time <= 50 and time%5 == 0

					for i = 1, 32
						local smoke = P_SpawnMobj(target.x + P_RandomRange(-48, 48)*FRACUNIT, target.y + P_RandomRange(-48, 48)*FRACUNIT, target.z + P_RandomRange(0, 128)*FRACUNIT, MT_SMOKE)
						smoke.scale = FRACUNIT*4
						smoke.momz = P_RandomRange(3, 10)*FRACUNIT
					end
					
					if time == 50
						damageObject(target)
					end
					
					localquake(mo.battlen, FRACUNIT*17, 20)
					local smol = P_SpawnMobj(target.x, target.y, target.z, MT_SMOLDERING)
					smol.fuse = TICRATE*2
					smol.scale = FRACUNIT*3
					
					P_SpawnGhostMobj(ghost)
					P_TeleportMove(ghost, target.x + 130*cos(P_RandomRange(1, 359)*ANG1), target.y + 130*sin(P_RandomRange(1, 359)*ANG1), target.z)
					ghost.angle = R_PointToAngle2(ghost.x, ghost.y, target.x, target.y)
				end
				
				m[2] = $ + 1
			elseif index == 4
				if time == 1
					ANIM_set(ghost, mo.anim_guard, true)
					ghost.frame = $|TR_TRANS50
					P_TeleportMove(ghost, target.x + 50*cos(P_RandomRange(1, 359)*ANG1), target.y + 50*sin(P_RandomRange(1, 359)*ANG1), target.z)
					ghost.angle = R_PointToAngle2(ghost.x, ghost.y, target.x, target.y)
				elseif time == 20
					ANIM_set(ghost, mo.anim_special5, true)
					damageObject(hittargets[1])
					P_InstaThrust(ghost, 0, 0)
					ghost.momz = 12*FRACUNIT
					localquake(mo.battlen, FRACUNIT*20, 10)

					caceecircle(ghost, MT_DUST, 16, 16*ghost.scale, 0, ghost.scale, false, 0, false, ghost.angle)
					playSound(mo.battlen, sfx_ceuppr)
					
					playSound(mo.battlen, sfx_cehit3)
					
					local boom = P_SpawnMobjFromMobj(target, 0, 0, target.height/2, MT_DUMMY)
					boom.state = S_CACEE_HIT1
					
					local d = P_SpawnMobj(target.x, target.y, target.z+128*FRACUNIT, MT_THOK)
					d.sprite = SPR_THMP
					d.frame = A|FF_FULLBRIGHT
					d.scale = FRACUNIT/4
					d.destscale = FRACUNIT*3
					d.scalespeed = FRACUNIT/8
					d.fuse = TICRATE-10
					d.tics = d.fuse
					d.momz = FRACUNIT*2
					d.momx = P_RandomRange(0, FRACUNIT-1)*P_RandomRange(-8, 8)
					d.momy = P_RandomRange(0, FRACUNIT-1)*P_RandomRange(-8, 8)
					d.color = SKINCOLOR_RED
					
					local rand = P_RandomRange(1, 10)
					if rand <= 5
						playSound(mo.battlen, jabsounds[rand])
					elseif rand == 6
						playSound(mo.battlen, sfx_ceshok)
					end
				elseif time >= 20 and time < 55
					local speed = max(1, min(8, ghost.momz/2/ghost.scale))
					ghost.angle = $+(ANGLE_11hh * speed)
					
					local ghost = P_SpawnGhostMobj(ghost)
					ghost.colorized = true
					ghost.color = SKINCOLOR_ROSY
				elseif time == 55
					ANIM_set(ghost, mo.anim_aoa_end, true)
				end
				
				m[2] = $ + 1
			elseif index == 5
				if time == 1
					ANIM_set(ghost, mo.anim_guard, true)
					ghost.frame = $|TR_TRANS50
					P_TeleportMove(ghost, target.x + 130*cos(P_RandomRange(1, 359)*ANG1), target.y + 130*sin(P_RandomRange(1, 359)*ANG1), target.z)
					ghost.angle = R_PointToAngle2(ghost.x, ghost.y, target.x, target.y)
				elseif time == 10
					ghost.momx = (target.x - ghost.x)/10
					ghost.momy = (target.y - ghost.y)/10
					playSound(mo.battlen, sfx_cepun1)
					ANIM_set(ghost, mo.anim_special3)
					
					local rand = P_RandomRange(1, 10)
					if rand <= 5
						playSound(mo.battlen, jabsounds[rand])
					end
				elseif time > 10 and time < 20
					local ghost = P_SpawnGhostMobj(ghost)
					ghost.colorized = true
					ghost.color = SKINCOLOR_CRIMSON
				elseif time == 20
					playSound(mo.battlen, sfx_cehit1)
					ghost.flags = $ - MF_NOCLIPHEIGHT - MF_NOGRAVITY
					ghost.momx = -$
					ghost.momy = -$
					
					local boom = P_SpawnMobjFromMobj(target, 0, 0, target.height/2, MT_DUMMY)
					boom.state = S_CACEE_HIT1

					for i = 1, 16
						local h = P_SpawnMobj(target.x, target.y, target.z, MT_DUMMY)
						h.state = S_SSPK1
						h.fuse = TICRATE
						h.momx = P_RandomRange(-24, 24)*FRACUNIT
						h.momy = P_RandomRange(-24, 24)*FRACUNIT
						h.momz = P_RandomRange(2, 24)*FRACUNIT
					end
				elseif time == 25
					ghost.momx = (target.x - ghost.x)/10
					ghost.momy = (target.y - ghost.y)/10
					playSound(mo.battlen, sfx_cepun2)
					ANIM_set(ghost, mo.anim_special4)
				elseif (time > 25 and time < 30) or (time > 40 and time < 45)
					local ghost = P_SpawnGhostMobj(ghost)
					ghost.colorized = true
					ghost.color = ((time > 40) and SKINCOLOR_SUPERGOLD2 or SKINCOLOR_CRIMSON)
				elseif time == 35
					playSound(mo.battlen, sfx_cehit3)
					
					local boom = P_SpawnMobjFromMobj(target, 0, 0, target.height/2, MT_DUMMY)
					boom.state = S_CACEE_HIT1

					for i = 1, 16
						local h = P_SpawnMobj(target.x, target.y, target.z, MT_DUMMY)
						h.state = S_SSPK1
						h.fuse = TICRATE
						h.momx = P_RandomRange(-24, 24)*FRACUNIT
						h.momy = P_RandomRange(-24, 24)*FRACUNIT
						h.momz = P_RandomRange(2, 24)*FRACUNIT
					end
					
					ghost.momx = -3*$/2
					ghost.momy = -3*$/2
				elseif time == 40
					ANIM_set(ghost, mo.anim_special1, true)
					playSound(mo.battlen, sfx_cepun3)
					
					P_SpawnParaloop(ghost.x, ghost.y, ghost.z,
					ghost.radius*4, 8, MT_DUST, ANGLE_90, nil, true)

					-- fake A_LobShot:
					ghost.angle = R_PointToAngle2(mo.x, mo.y, target.x, target.y)

					local z = ghost.z
					local hit = P_SpawnMobj(target.x & (64*FRACUNIT -1), target.y & (64*FRACUNIT -1), target.subsector.sector.floorheight, MT_NULL)
					hit.tics = 20

					local dist = P_AproxDistance(target.x - ghost.x, target.y - ghost.y)
					local horizontal = dist / 10
					local vertical = FixedMul((gravity*10)/2, ghost.scale)

					ghost.momx = FixedMul(horizontal, cos(ghost.angle))
					ghost.momy = FixedMul(horizontal, sin(ghost.angle))
					ghost.momz = vertical
				elseif time == 50
					damageObject(target)
					playSound(mo.battlen, sfx_cepun4)
					localquake(mo.battlen, FRACUNIT*30, 8)
					
					caceecircle(ghost, MT_SUPERSPARK, 16, 32*ghost.scale, 0, ghost.scale, false, 0, false, ghost.angle)
					caceecircle(ghost, MT_MINECARTSPARK, 8, 8*ghost.scale, 0, ghost.scale/4, false, 0, false, ghost.angle)
					
					local thok = P_SpawnMobjFromMobj(ghost,0,0,0,MT_THOK)
					thok.state = S_CACEE_HIT1
					thok.flags2 = $|MF2_SPLAT
					thok.scale = $*2
					thok.blendmode = AST_ADD
					
					local ghost = P_SpawnGhostMobj(ghost)
					ghost.colorized = true
					ghost.color = SKINCOLOR_SUPERGOLD2
					ghost.destscale = $*16
				end
				
				m[2] = $ + 1
			end

			j = $-1
		end
		
		local j = #mo.columns
		while j

			local m = mo.columns[j]
			if not m or not m.valid
				j = $-1
				continue
			end

			for i = 1, 5
				local boom = P_SpawnMobj(m.x + P_RandomRange(-48, 48)*FRACUNIT, m.y + P_RandomRange(-48, 48)*FRACUNIT, m.z, MT_DUMMY)
				boom.state = S_QUICKBOOM1
				boom.momz = P_RandomRange(0, 48)*FRACUNIT
				boom.scale = FRACUNIT*3/2
			end
			localquake(mo.battlen, FRACUNIT*8, 1)

			if timer <= 140
				local an = (mo.fangle + (j-1)*120)*ANG1
				P_TeleportMove(m, target.x + mo.fdist*cos(an), target.y + mo.fdist*sin(an), target.z)
			end

			j = $-1

		end
	end,
}

attackDefs["c-rising upper"] = {
	name = "Rising Upper",
	type = ATK_STRIKE,
	power = 200,
	accuracy = 95,
	costtype = CST_HPPERCENT,
	cost = 9,
	critical = 4,
	norandom = true,
	norogue = true,
	nometronome = true,
	noenemycast = true,
	desc = "Medium Strike dmg to one\nenemy.",
	target = TGT_ENEMY,
	anim = function(mo, targets, hittargets, timer)
		local target = targets[1]
		if timer == 1
			mo.ogpos = {mo.x, mo.y}
			
			ANIM_set(mo, mo.anim_special6, true)
			playSound(mo.battlen, sfx_s220)

			-- fake A_LobShot:
			mo.angle = R_PointToAngle2(mo.x, mo.y, target.x, target.y)

			local z = mo.z
			local hit = P_SpawnMobj(target.x & (64*FRACUNIT -1), target.y & (64*FRACUNIT -1), target.subsector.sector.floorheight, MT_NULL)
			hit.tics = TICRATE

			local dist = P_AproxDistance(target.x - mo.x, target.y - mo.y)
			local horizontal = dist / TICRATE
			local vertical = FixedMul((gravity*TICRATE)/2, mo.scale)

			mo.momx = FixedMul(horizontal, cos(mo.angle))
			mo.momy = FixedMul(horizontal, sin(mo.angle))
			mo.momz = vertical


			-- move camera to an interresting spot

			local an = target.angle + 45*ANG1

			local cx = target.x + 384*cos(an)
			local cy = target.y + 384*sin(an)

			CAM_goto(server.P_BattleStatus[mo.battlen].cam, cx, cy, server.P_BattleStatus[mo.battlen].cam.z, 70*FRACUNIT)
			CAM_angle(server.P_BattleStatus[mo.battlen].cam, R_PointToAngle2(cx, cy, target.x, target.y), ANG1*4)
			--CAM_aiming(server.P_BattleStatus[mo.battlen].cam, -ANG1*10, ANG1)

		elseif timer == 18
			ANIM_set(mo, mo.anim_aoa_end, true)

		elseif timer == TICRATE
			ANIM_set(mo, mo.anim_special5, true)
			damageObject(hittargets[1])
			P_InstaThrust(mo, 0, 0)
			mo.momz = 12*FRACUNIT
			target.momz = 5*mo.momz/4
			localquake(mo.battlen, FRACUNIT*20, 10)

			caceecircle(mo, MT_DUST, 16, 16*mo.scale, 0, mo.scale, false, 0, false, mo.angle)
			playSound(mo.battlen, sfx_ceuppr)
			
			playSound(mo.battlen, sfx_cehit3)
			
			local boom = P_SpawnMobjFromMobj(target, 0, 0, target.height/2, MT_DUMMY)
			boom.state = S_CACEE_HIT1
			
			local d = P_SpawnMobj(target.x, target.y, target.z+128*FRACUNIT, MT_THOK)
			d.sprite = SPR_THMP
			d.frame = A|FF_FULLBRIGHT
			d.scale = FRACUNIT/4
			d.destscale = FRACUNIT*3
			d.scalespeed = FRACUNIT/8
			d.fuse = TICRATE-10
			d.tics = d.fuse
			d.momz = FRACUNIT*2
			d.momx = P_RandomRange(0, FRACUNIT-1)*P_RandomRange(-8, 8)
			d.momy = P_RandomRange(0, FRACUNIT-1)*P_RandomRange(-8, 8)
			d.color = SKINCOLOR_RED
			
			local rand = P_RandomRange(1, 10)
			if rand <= 5
				playSound(mo.battlen, jabsounds[rand])
			elseif rand == 6
				playSound(mo.battlen, sfx_ceshok)
			end
		elseif timer >= TICRATE and timer < 70
			local speed = max(1, min(8, mo.momz/2/mo.scale))
			mo.angle = $+(ANGLE_11hh * speed)
			
			local ghost = P_SpawnGhostMobj(mo)
			ghost.colorized = true
			ghost.color = SKINCOLOR_ROSY
		elseif timer == 70
			ANIM_set(mo, mo.anim_aoa_end, true)
		elseif timer == 130
			if mo.cacee and mo.cacee.combo
				mo.cacee.roll[#mo.cacee.roll+1] = "Rising Upper"
				if mo.cacee.charisma >= 2 then mo.cacee.combo[2] = 3 end
			end
			
			if mo.cacee and mo.cacee.combo and mo.cacee.combo[1]
				local strs = {"atk", "mag", "def", "agi", "crit"}
				
				for j = 1, #strs
					local s = strs[j]
					if target.buffs[s][1] > 0
						target.buffs[s][1] = 0
						target.buffs[s][2] = 0
					end
				end
			end
			mo.done = nil
			mo.ogpos = nil
			
			return true
		end
		
		if timer > TICRATE and P_IsObjectOnGround(mo) and not mo.done
			ANIM_set(mo, mo.anim_stand, true)
			mo.done = true
			
			ANIM_set(mo, mo.anim_special6, true)
			playSound(mo.battlen, sfx_s220)

			-- fake A_LobShot:
			mo.angle = R_PointToAngle2(mo.x, mo.y, mo.ogpos[1], mo.ogpos[2])

			local z = mo.z
			local hit = P_SpawnMobj(mo.ogpos[1] & (64*FRACUNIT -1), mo.ogpos[2] & (64*FRACUNIT -1), mo.subsector.sector.floorheight, MT_NULL)
			hit.tics = TICRATE

			local dist = P_AproxDistance(mo.ogpos[1] - mo.x, mo.ogpos[2] - mo.y)
			local horizontal = dist / TICRATE
			local vertical = FixedMul((gravity*TICRATE)/2, mo.scale)

			mo.momx = FixedMul(horizontal, cos(mo.angle))
			mo.momy = FixedMul(horizontal, sin(mo.angle))
			mo.momz = vertical
		end
	end,
}

attackDefs["c-rising sun"] = {
	name = "Sol Naciente",
	type = ATK_STRIKE,
	power = 700,
	accuracy = 95,
	costtype = CST_HPPERCENT,
	cost = 18,
	critical = 10,
	hits = 2,
	norandom = true,
	norogue = true,
	nometronome = true,
	noenemycast = true,
	desc = "Heavy Strike dmg to one\nenemy 2x. High critical rate.",
	target = TGT_ENEMY,
	anim = function(mo, targets, hittargets, timer)
		local target = targets[1]
		if timer == 1
			mo.ogpos = {mo.x, mo.y}
			
			ANIM_set(mo, mo.anim_special6, true)
			playSound(mo.battlen, sfx_s220)

			-- fake A_LobShot:
			mo.angle = R_PointToAngle2(mo.x, mo.y, target.x, target.y)

			local z = mo.z
			local hit = P_SpawnMobj(target.x & (64*FRACUNIT -1), target.y & (64*FRACUNIT -1), target.subsector.sector.floorheight, MT_NULL)
			hit.tics = TICRATE

			local dist = P_AproxDistance(target.x - mo.x, target.y - mo.y)
			local horizontal = dist / TICRATE
			local vertical = FixedMul((gravity*TICRATE)/2, mo.scale)

			mo.momx = FixedMul(horizontal, cos(mo.angle))
			mo.momy = FixedMul(horizontal, sin(mo.angle))
			mo.momz = vertical


			-- move camera to an interresting spot

			local an = target.angle + 45*ANG1

			local cx = target.x + 384*cos(an)
			local cy = target.y + 384*sin(an)

			CAM_goto(server.P_BattleStatus[mo.battlen].cam, cx, cy, server.P_BattleStatus[mo.battlen].cam.z, 70*FRACUNIT)
			CAM_angle(server.P_BattleStatus[mo.battlen].cam, R_PointToAngle2(cx, cy, target.x, target.y), ANG1*4)
			--CAM_aiming(server.P_BattleStatus[mo.battlen].cam, -ANG1*10, ANG1)
			
			local rand = P_RandomRange(1, 10)
			if rand <= 5
				playSound(mo.battlen, jabsounds[rand])
			end

		elseif timer == 18
			ANIM_set(mo, mo.anim_aoa_end, true)

		elseif timer == TICRATE
			P_InstaThrust(mo, 0, 0)
			ANIM_set(mo, mo.anim_special2, true)
			damageObject(target)
			playSound(mo.battlen, sfx_cepun4)
			localquake(mo.battlen, FRACUNIT*35, 10)
			
			local d = P_SpawnMobj(target.x, target.y, target.z+128*FRACUNIT, MT_THOK)
			d.sprite = SPR_THMP
			d.frame = B|FF_FULLBRIGHT
			d.scale = FRACUNIT/4
			d.destscale = FRACUNIT*3
			d.scalespeed = FRACUNIT/8
			d.fuse = TICRATE-10
			d.tics = d.fuse
			d.momz = FRACUNIT*2
			d.momx = P_RandomRange(0, FRACUNIT-1)*P_RandomRange(-8, 8)
			d.momy = P_RandomRange(0, FRACUNIT-1)*P_RandomRange(-8, 8)
			d.color = SKINCOLOR_RED
			
			caceecircle(mo, MT_SUPERSPARK, 16, 32*mo.scale, 0, mo.scale, false, 0, false, mo.angle)
			caceecircle(mo, MT_MINECARTSPARK, 8, 8*mo.scale, 0, mo.scale/4, false, 0, false, mo.angle)
			
			local thok = P_SpawnMobjFromMobj(mo,0,0,0,MT_THOK)
			thok.state = S_CACEE_HIT1
			thok.flags2 = $|MF2_SPLAT
			thok.scale = $*2
			thok.blendmode = AST_ADD
			
		elseif timer > TICRATE and timer < 50 and timer%4 == 0
			local ghost = P_SpawnGhostMobj(mo)
			ghost.destscale = mo.scale*2
			ghost.colorized = true
			ghost.color = SKINCOLOR_SUPERGOLD2
			ghost.tics = 3
		elseif timer == 50
			ANIM_set(mo, mo.anim_special5, true)
			damageObject(hittargets[1])
			P_InstaThrust(mo, 0, 0)
			mo.momz = 15*FRACUNIT
			mo.flags = $|MF_NOGRAVITY
			target.momz = 5*mo.momz/4
			localquake(mo.battlen, FRACUNIT*20, 10)

			for i = 1,32
				local dust = P_SpawnMobj(mo.x, mo.y, mo.z+mo.height/5, MT_SMOKE)
				dust.angle = ANGLE_90 + ANG1* (11*(i-1))
				dust.destscale = FRACUNIT*10
				P_InstaThrust(dust, dust.angle, 20*FRACUNIT)
			end
			playSound(mo.battlen, sfx_blzhvr)
			
			local boom = P_SpawnMobjFromMobj(target, 0, 0, target.height/2, MT_DUMMY)
			boom.state = S_CACEE_HIT1
			
			local d = P_SpawnMobj(target.x, target.y, target.z+128*FRACUNIT, MT_THOK)
			d.sprite = SPR_THMP
			d.frame = A|FF_FULLBRIGHT
			d.scale = FRACUNIT/4
			d.destscale = FRACUNIT*3
			d.scalespeed = FRACUNIT/8
			d.fuse = TICRATE-10
			d.tics = d.fuse
			d.momz = FRACUNIT*2
			d.momx = P_RandomRange(0, FRACUNIT-1)*P_RandomRange(-8, 8)
			d.momy = P_RandomRange(0, FRACUNIT-1)*P_RandomRange(-8, 8)
			d.color = SKINCOLOR_RED
			
			local rand = P_RandomRange(1, 10)
			if rand <= 5
				playSound(mo.battlen, jabsounds[rand])
			elseif rand == 6
				playSound(mo.battlen, sfx_ceshok)
			end
		elseif timer >= 50 and timer < 70
			mo.color = SKINCOLOR_FLAME
			mo.colorized = true
			local speed = max(1, min(8, mo.momz/2/mo.scale))
			mo.angle = $+(ANGLE_11hh * speed)
			
			local ghost = P_SpawnGhostMobj(mo)
			ghost.colorized = true
			ghost.color = SKINCOLOR_SUPERGOLD2
			
			if timer%3 == 0
				local truc = P_SpawnMobj(mo.x, mo.y, mo.z, MT_BOSSEXPLODE)
				truc.scale = FRACUNIT
				truc.destscale = FRACUNIT*2
				truc.state = S_LESS_QUICKBOOM1
				truc.momz = -FRACUNIT
				if i < 2	-- cool sound effect
					local mobj = P_SpawnMobj(mo.x, mo.y, mo.z, MT_THOK)
					mobj.state = S_INVISIBLE
					mobj.tics = TICRATE*10
					S_StartSound(mobj, sfx_bgxpld)
				end
				
				local dust = P_SpawnMobj(mo.x, mo.y, mo.z, MT_SMOKE)
				dust.destscale = FRACUNIT*4
				dust.tics = 30
				dust.momz = -FRACUNIT
			end
		elseif timer == 70
			ANIM_set(mo, mo.anim_aoa_end, true)
			mo.flags = $ & ~MF_NOGRAVITY
			mo.colorized = false
			P_TeleportMove(mo, mo.ogpos[1], mo.ogpos[2], mo.z)
		elseif timer == 110
			if mo.cacee and mo.cacee.combo
				mo.cacee.combo[2] = 0
				mo.cacee.roll[#mo.cacee.roll+1] = "Sol Naciente"
			end
			
			if mo.cacee and mo.cacee.combo and mo.cacee.combo[1]
				local strs = {"atk", "mag", "def", "agi", "crit"}
				
				for j = 1, #strs
					local s = strs[j]
					if target.buffs[s][1] > 0
						target.buffs[s][1] = 0
						target.buffs[s][2] = 0
					end
				end
			end
			
			mo.ogpos = nil
			return true
		end
	end,
}

attackDefs["c-la revolucion"] = { -- this move singlehandedly killed my motivation to work on this mod for a month and a half
	name = "La Revolucion",
	type = ATK_STRIKE,
	power = 1400,
	accuracy = 95,
	costtype = CST_HPPERCENT,
	cost = 30,
	critical = 15,
	hits = 2,
	anim_norepel = true,
	norandom = true,
	norogue = true,
	nometronome = true,
	noenemycast = true,
	desc = "Severe Strike dmg to one\nenemy 2x. High critical rate.",
	target = TGT_ENEMY,
	anim = function(mo, targets, hittargets, timer)
		local target = hittargets[1]
		local time = 0
		local time2 = 0
		local cam = server.P_BattleStatus[mo.battlen].cam
		
		if mo.revoready
			time = timer - mo.revoready
		end
		
		if mo.hitground
			time2 = time - mo.hitground
		end
		
		if timer == 1
			mo.columns = {}
			
			cam.ogpos = {cam.x, cam.y, cam.z + 10*FRACUNIT}
		elseif timer == 15
			ANIM_set(mo, mo.anim_guard)
			caceecircle(mo, MT_SUPERSPARK, 16, 32*mo.scale, 0, mo.scale, false, 0, false, mo.angle)
			caceecircle(mo, MT_MINECARTSPARK, 8, 8*mo.scale, 0, mo.scale/4, false, 0, false, mo.angle)
			
			local thok = P_SpawnMobjFromMobj(mo,0,0,0,MT_THOK)
			thok.state = S_CACEE_HIT1
			thok.flags2 = $|MF2_SPLAT
			thok.scale = $*2
			thok.blendmode = AST_ADD
			
			local ghost = P_SpawnGhostMobj(mo)
			ghost.destscale = FRACUNIT*2
			ghost.scalespeed = FRACUNIT/2
			ghost.colorized = true
			ghost.color = SKINCOLOR_SUPERGOLD2
		elseif timer == 20
			ANIM_set(mo, mo.anim_special6)
			mo.momz = FRACUNIT*20
			localquake(mo.battlen, FRACUNIT*30, 5)
			playSound(mo.battlen, sfx_s3k90)
			playSound(mo.battlen, sfx_sprong)
			
			local rand = P_RandomRange(1, 10)
			if rand <= 5
				playSound(mo.battlen, jabsounds[rand])
			end
			
			for i = 1,16
				local dust = P_SpawnMobj(mo.x, mo.y, mo.z, MT_DUMMY)
				dust.angle = ANG1*(ANGLE_22h*(i-1))
				dust.destscale = FRACUNIT*5
				dust.state = S_AOADUST1
				dust.frame = A|FF_FULLBRIGHT
				P_InstaThrust(dust, dust.angle, 20*FRACUNIT)
			end
		elseif timer > 20 and timer < 60
			cam.z = $ + 8*FRACUNIT
		elseif timer == 60
			ANIM_set(mo, mo.anim_special1)
			
			mo.momx = (target.x - mo.x)/10
			mo.momy = (target.y - mo.y)/10
			mo.momz = (target.z - mo.z)/10
			
			-- move camera to an interresting spot

			local an = target.angle + 45*ANG1

			local cx = target.x + 384*cos(an)
			local cy = target.y + 384*sin(an)

			CAM_goto(cam, cx, cy, cam.z - (cam.z - cam.ogpos[3]), 20*FRACUNIT)
			CAM_angle(cam, R_PointToAngle2(cx, cy, target.x, target.y), ANG1*4)
		elseif timer == 70
			mo.momx = 0
			mo.momy = 0
			playSound(mo.battlen, sfx_zio3)
			
			for j = 1, 16
				local rock = P_SpawnMobj(mo.x, mo.y, mo.floorz, MT_FALLINGROCK)
				rock.scale = FRACUNIT
				P_InstaThrust(rock, mo.angle + ANGLE_22h*j, FRACUNIT*20)
				rock.momz = FRACUNIT*5
				rock.fuse = TICRATE/2
			end
			
			for i = 1,16
				local dust = P_SpawnMobj(mo.x, mo.y, mo.z, MT_DUMMY)
				dust.angle = ANGLE_90 + ANG1* (ANGLE_11hh*(i-1))
				dust.destscale = FRACUNIT*10
				dust.scale = FRACUNIT
				dust.state = S_AOADUST1
				dust.frame = A|FF_FULLBRIGHT|TR_TRANS60
				P_InstaThrust(dust, dust.angle, 20*FRACUNIT)
			end
			
			target.momz = FRACUNIT*20
		elseif timer == 75
			ANIM_set(mo, mo.anim_guard)
			local ghost = P_SpawnGhostMobj(mo)
			ghost.destscale = FRACUNIT*2
			ghost.scalespeed = FRACUNIT/2
			ghost.colorized = true
			ghost.color = SKINCOLOR_SUPERGOLD2
		elseif timer == 80
			mo.momz = FRACUNIT*35
			ANIM_set(mo, mo.anim_special5)
			localquake(mo.battlen, FRACUNIT*30, 5)
			playSound(mo.battlen, sfx_s3k90)
			playSound(mo.battlen, sfx_sprong)
			
			for i = 1,16
				local dust = P_SpawnMobj(mo.x, mo.y, mo.z, MT_DUMMY)
				dust.angle = ANG1*(ANGLE_22h*(i-1))
				dust.destscale = FRACUNIT*5
				dust.state = S_AOADUST1
				dust.frame = A|FF_FULLBRIGHT
				P_InstaThrust(dust, dust.angle, 20*FRACUNIT)
			end
		elseif timer > 80 and timer < 90
			local speed = max(1, min(8, mo.momz/2/mo.scale))
			mo.angle = $+(ANGLE_11hh * speed)
			cam.z = $ + 25*FRACUNIT
			
			local ghost = P_SpawnGhostMobj(mo)
			ghost.colorized = true
			ghost.color = SKINCOLOR_SUPERSKY2
		elseif timer == 90
			playSound(mo.battlen, sfx_zio3)
			mo.momz = 0
			cam.topz = cam.z
			for i = 0, 8 do
				local size = FixedMul(mo.scale, 320*FRACUNIT)
				local a = ((360/16)*i)*ANG1
				local part = P_SpawnMobj(mo.x + size>>FRACBITS*cos(a), mo.y + size>>FRACBITS*sin(a), mo.z - 110*FRACUNIT, MT_THOK)
				part.state = S_KSPARK1
				part.scale = FRACUNIT
				part.color = SKINCOLOR_CYAN
				local l = P_SpawnMobj(mo.x, mo.y, mo.z - 130*FRACUNIT, MT_THOK)
				l.rollangle = 180*ANG1
				l.state = S_KLIT1 + P_RandomRange(0, 5)
				l.angle = P_RandomRange(0, 359)*ANG1
				l.fuse = P_RandomRange(10, 40)
				l.scale = mo.scale
				l.color = SKINCOLOR_CYAN
			end
			target.momz = FRACUNIT*40
			target.flags = $|MF_NOGRAVITY
			damageObject(target)
			ANIM_set(mo, mo.anim_aoa_end, true)
		elseif timer > 90 and timer < 110
			cam.z = $ - (cam.topz - cam.ogpos[3])/20
			
			if timer == 100
				local rand = P_RandomRange(1,10)
				
				if rand <= 4
					playSound(mo.battlen, dancesounds[rand])
				end
			end
		elseif timer == 170
			target.momz = 0
		end
		
		//Target flight handling
		
		if ((timer > 110 and P_IsObjectOnGround(mo)) or timer == 150) and not mo.revoready
			mo.revoready = timer
			ANIM_set(mo, mo.anim_stand)
		end
		
		if mo.revoready and timer > 110
			if time == 5
				ANIM_set(mo, mo.anim_guard)
				caceecircle(mo, MT_SUPERSPARK, 16, 32*mo.scale, 0, mo.scale, false, 0, false, mo.angle)
				caceecircle(mo, MT_MINECARTSPARK, 8, 8*mo.scale, 0, mo.scale/4, false, 0, false, mo.angle)
				
				local thok = P_SpawnMobjFromMobj(mo,0,0,0,MT_THOK)
				thok.state = S_CACEE_HIT1
				thok.flags2 = $|MF2_SPLAT
				thok.scale = $*2
				thok.blendmode = AST_ADD
				
				local ghost = P_SpawnGhostMobj(mo)
				ghost.destscale = FRACUNIT*2
				ghost.scalespeed = FRACUNIT/2
				ghost.colorized = true
				ghost.color = SKINCOLOR_SUPERGOLD2
			elseif time == 10
				ANIM_set(mo, mo.anim_special6)
				mo.momz = mo.scale*60
				DoExplosion(mo)
				localquake(mo.battlen, FRACUNIT*45, 10)
				playSound(mo.battlen, sfx_brakrx)
				
				for i = 1,16
					local dust = P_SpawnMobj(mo.x, mo.y, mo.z, MT_DUMMY)
					dust.angle = ANG1*(ANGLE_22h*(i-1))
					dust.destscale = FRACUNIT*5
					dust.state = S_AOADUST1
					dust.frame = A|FF_FULLBRIGHT
					P_InstaThrust(dust, dust.angle, 20*FRACUNIT)
				end
				
				CAM_goto(cam, cam.ogpos[1], cam.ogpos[2], cam.ogpos[3], 20*FRACUNIT)
			elseif time > 10 and time < 35
				if timer%3 == 0
					local truc = P_SpawnMobj(mo.x, mo.y, mo.z, MT_BOSSEXPLODE)
					truc.scale = FRACUNIT
					truc.destscale = FRACUNIT*2
					truc.state = S_LESS_QUICKBOOM1
					truc.momz = -FRACUNIT
					if i < 2	-- cool sound effect
						local mobj = P_SpawnMobj(mo.x, mo.y, mo.z, MT_THOK)
						mobj.state = S_INVISIBLE
						mobj.tics = TICRATE*10
						S_StartSound(mobj, sfx_bgxpld)
					end
					
					local dust = P_SpawnMobj(mo.x, mo.y, mo.z, MT_SMOKE)
					dust.destscale = FRACUNIT*4
					dust.tics = 30
					dust.momz = -FRACUNIT
				end
				
				CAM_angle(cam, R_PointToAngle(target.x, target.y), ANG1*4)
			elseif time == 35
				playSound(mo.battlen, sfx_s3k4a)
			elseif time == 40
				playSound(mo.battlen, sfx_cstar)
			elseif time == 50
				ANIM_set(mo, mo.anim_special1)
				mo.momz = -mo.scale*80
				target.flags = $ & ~MF_NOGRAVITY
				target.momz = -mo.scale*80
			elseif time > 50 and time < 90
				local ghost = P_SpawnGhostMobj(mo)
				ghost.colorized = true
				ghost.color = SKINCOLOR_RED
			end
			
			if (time == 90 or (time > 50 and P_IsObjectOnGround(mo))) and not mo.hitground
				mo.fangle = (R_PointToAngle(target.x, target.y)) + ANG1*180
				mo.fdist = 96
				mo.columns = {}
				mo.hitground = time
				damageObject(target)

				local a = mo.fangle - ANG1*80
				DoExplosion(target)
				playSound(mo.battlen, sfx_s3k4e)
				
				local thok = P_SpawnMobjFromMobj(mo,0,0,0,MT_THOK)
				thok.state = S_CACEE_HIT1
				thok.flags2 = $|MF2_SPLAT
				thok.scale = $*5
				thok.blendmode = AST_ADD
				localquake(mo.battlen, FRACUNIT*10, 10)
				
				for i = 1,16
					local dust = P_SpawnMobj(mo.x, mo.y, mo.z, MT_DUMMY)
					dust.angle = ANG1*(ANGLE_22h*(i-1))
					dust.destscale = FRACUNIT*5
					dust.state = S_AOADUST1
					dust.frame = A|FF_FULLBRIGHT
					P_InstaThrust(dust, dust.angle, 20*FRACUNIT)
				end

				for i = 1, 16
					local m = P_SpawnMobj(target.x, target.y, target.z, MT_DUMMY)
					P_InstaThrust(m, a, FRACUNIT*48)
					mo.columns[#mo.columns+1] = m
					m.state = S_INVISIBLE
					m.tics = TICRATE
					a = $+ ANG1*10
				end
			end
		end
		
		if mo.time2
			if time2 >= 1
				mo.fangle = $ + min(14, ((timer-31)/4))
				mo.fdist = $ + 3
			end
		end
		
		local j = #mo.columns
		while j

			local m = mo.columns[j]
			if not m or not m.valid
				j = $-1
				continue
			end

			for i = 1, 5
				local boom = P_SpawnMobj(m.x + P_RandomRange(-48, 48)*FRACUNIT, m.y + P_RandomRange(-48, 48)*FRACUNIT, m.z, MT_DUMMY)
				boom.state = S_QUICKBOOM1
				boom.momz = P_RandomRange(0, 48)*FRACUNIT
				boom.scale = FRACUNIT*3/2
			end
			localquake(mo.battlen, FRACUNIT*8, 1)

			if timer <= 140
				local an = (mo.fangle + (j-1)*120)*ANG1
				P_TeleportMove(m, target.x + mo.fdist*cos(an), target.y + mo.fdist*sin(an), target.z)
			end

			j = $-1

		end
		
		//Clean up and add to roll

		if time2 == 40
			mo.revoready = nil
			mo.hitground = nil
			mo.fangle = nil
			mo.columns = nil
			mo.fdist = nil
			cam.topz = nil
			cam.ogpos = nil
			
			if mo.cacee and mo.cacee.combo
				mo.cacee.roll[#mo.cacee.roll+1] = "La Revolucion"
				mo.cacee.combo[2] = 0
			end
			
			return true
		end
	end,
}

attackDefs["c-bullet fist"] = {
	name = "Bullet Fist",
	type = ATK_STRIKE,
	power = 120,
	accuracy = 85,
	costtype = CST_HPPERCENT,
	cost = 6,
	critical = 10,
	norandom = true,
	norogue = true,
	nometronome = true,
	noenemycast = true,
	desc = "Light Strike dmg to one\nenemy. High crit rate.",
	target = TGT_ENEMY,
	anim = function(mo, targets, hittargets, timer)
		local target = hittargets[1]

		if timer >= 10 and timer <= 20 and timer%5 == 0
			ANIM_set(mo, mo.anim_aoa_guard, true)
			playSound(mo.battlen, sfx_spndsh)
			local ghost = P_SpawnGhostMobj(mo)
			ghost.tics = 10
			ghost.colorized = true
			ghost.color = SKINCOLOR_SUPERGOLD2
			ghost.destscale = FRACUNIT*2
		elseif timer == 40
			mo.flags = $|MF_NOCLIPHEIGHT|MF_NOGRAVITY
			mo.momx = (target.x - mo.x)/10
			mo.momy = (target.y - mo.y)/10
			playSound(mo.battlen, sfx_zoom)
			ANIM_set(mo, mo.anim_run, true)
			
			local rand = P_RandomRange(1, 10)
			if rand <= 5
				playSound(mo.battlen, jabsounds[rand])
			end
		elseif timer > 40 and timer < 50
			local ghost = P_SpawnGhostMobj(mo)
			ghost.tics = 10
			ghost.colorized = true
			ghost.color = SKINCOLOR_RED
			
			if timer == 45
				ANIM_set(mo, mo.anim_special4, true)
			end
		elseif timer == 50
			mo.flags = $ & ~MF_NOCLIPHEIGHT
			mo.flags = $ & ~MF_NOGRAVITY
			damageObject(target)
			localquake(mo.battlen, FRACUNIT*30, 5)
			playSound(mo.battlen, sfx_ceboom)
			
			local boom = P_SpawnMobjFromMobj(target, 0, 0, target.height, MT_DUMMY)
			boom.state = S_CACEE_HIT1

			for i = 1, 16
				local h = P_SpawnMobj(target.x, target.y, target.z, MT_DUMMY)
				h.state = S_SSPK1
				h.fuse = TICRATE
				h.momx = P_RandomRange(-24, 24)*FRACUNIT
				h.momy = P_RandomRange(-24, 24)*FRACUNIT
				h.momz = P_RandomRange(2, 24)*FRACUNIT
			end
			
			local d = P_SpawnMobj(target.x, target.y, target.z+128*FRACUNIT, MT_THOK)
			d.sprite = SPR_THMP
			d.frame = A|FF_FULLBRIGHT
			d.scale = FRACUNIT/4
			d.destscale = FRACUNIT*3
			d.scalespeed = FRACUNIT/8
			d.fuse = TICRATE-10
			d.tics = d.fuse
			d.momz = FRACUNIT*2
			d.momx = P_RandomRange(0, FRACUNIT-1)*P_RandomRange(-8, 8)
			d.momy = P_RandomRange(0, FRACUNIT-1)*P_RandomRange(-8, 8)
			d.color = SKINCOLOR_RED
		elseif timer == 70
			if mo.cacee and mo.cacee.combo
				mo.cacee.roll[#mo.cacee.roll+1] = "Bullet Fist"
				if mo.cacee.charisma >= 2 then mo.cacee.combo[3] = 3 end
			end
			
			return true
		end
	end,
}

attackDefs["c-bullet feast"] = {
	name = "Fiesta de Espinas",
	type = ATK_STRIKE,
	power = 600,
	accuracy = 100,
	costtype = CST_HPPERCENT,
	cost = 12,
	critical = 20,
	hits = 3,
	norandom = true,
	norogue = true,
	nometronome = true,
	noenemycast = true,
	desc = "Medium Strike dmg to one\nenemy several times.\nVery high crit rate.",
	target = TGT_ENEMY,
	anim = function(mo, targets, hittargets, timer)
		local target = hittargets[1]
		
		if timer == 1
			mo.fists = {}
		elseif timer == 20
			ANIM_set(mo, mo.anim_aoa_guard, true)
			playSound(mo.battlen, sfx_spndsh)
			local ghost = P_SpawnGhostMobj(mo)
			ghost.tics = 10
			ghost.colorized = true
			ghost.color = SKINCOLOR_SUPERGOLD2
			ghost.destscale = FRACUNIT*2
		elseif timer == 30
			local an = target.angle + 45*ANG1

			local cx = target.x + 384*cos(an)
			local cy = target.y + 384*sin(an)
			CAM_goto(server.P_BattleStatus[mo.battlen].cam, cx, cy, server.P_BattleStatus[mo.battlen].cam.z, 70*FRACUNIT)
			CAM_angle(server.P_BattleStatus[mo.battlen].cam, R_PointToAngle2(cx, cy, target.x, target.y), ANG1*4)
		elseif timer == 40
			mo.angle = R_PointToAngle2(mo.x, mo.y, target.x, target.y)
			mo.flags = $|MF_NOCLIPHEIGHT|MF_NOGRAVITY
			mo.momx = (target.x - mo.x)/11
			mo.momy = (target.y - mo.y)/11
			playSound(mo.battlen, sfx_zoom)
			ANIM_set(mo, mo.anim_run, true)
		elseif timer > 40 and timer < 48
			local ghost = P_SpawnGhostMobj(mo)
			ghost.tics = 10
			ghost.colorized = true
			ghost.color = SKINCOLOR_RED
			
			if timer == 45
				ANIM_set(mo, mo.anim_special4, true)
			end
		elseif timer == 49
			P_InstaThrust(mo, mo.angle, 0)
			damageObject(target)
			localquake(mo.battlen, FRACUNIT*30, 5)
			playSound(mo.battlen, sfx_ceboom)
			
			local boom = P_SpawnMobjFromMobj(target, 0, 0, target.height, MT_DUMMY)
			boom.state = S_CACEE_HIT1

			for i = 1, 16
				local h = P_SpawnMobj(target.x, target.y, target.z, MT_DUMMY)
				h.state = S_SSPK1
				h.fuse = TICRATE
				h.momx = P_RandomRange(-24, 24)*FRACUNIT
				h.momy = P_RandomRange(-24, 24)*FRACUNIT
				h.momz = P_RandomRange(2, 24)*FRACUNIT
			end
			
			local d = P_SpawnMobj(target.x, target.y, target.z+128*FRACUNIT, MT_THOK)
			d.sprite = SPR_THMP
			d.frame = A|FF_FULLBRIGHT
			d.scale = FRACUNIT/4
			d.destscale = FRACUNIT*3
			d.scalespeed = FRACUNIT/8
			d.fuse = TICRATE-10
			d.tics = d.fuse
			d.momz = FRACUNIT*2
			d.momx = P_RandomRange(0, FRACUNIT-1)*P_RandomRange(-8, 8)
			d.momy = P_RandomRange(0, FRACUNIT-1)*P_RandomRange(-8, 8)
			d.color = SKINCOLOR_RED
		elseif timer == 50
			playSound(mo.battlen, sfx_megi6)
			local s = P_SpawnMobj(mo.x, mo.y, mo.z + mo.height, MT_DUMMY)
			s.color = SKINCOLOR_WHITE
			s.state = S_MEGISTAR1
			s.scale = FRACUNIT/4
		elseif timer == 60
			localquake(mo.battlen, FRACUNIT*20, 60)
			ANIM_set(mo, mo.anim_guard, true)
			
			if (P_RandomRange(1,10) == 10 or mo.name == "\x4A\x6F\x74\x61\x72\x6F") and mo.name ~= "\x44\x49\x4F"
				playSound(mo.battlen, (P_RandomRange(0,1) and sfx_cora1 or sfx_cora2))
			elseif P_RandomRange(1,10) == 9 or mo.name == "\x44\x49\x4F"
				playSound(mo.battlen, (P_RandomRange(0,1) and sfx_cora3 or sfx_cora4))
			end
		elseif timer >= 61 and timer <= 120
			local dmg
			if server.P_BattleStatus[mo.battlen].dmg_hits[target.dmg_index][2] and type(server.P_BattleStatus[mo.battlen].dmg_hits[target.dmg_index][2]) == "number"
				dmg = server.P_BattleStatus[mo.battlen].dmg_hits[target.dmg_index][2]/6
			end
			
			local rd = P_RandomRange(0,1) and -1 or 1
			local ang = (R_PointToAngle2(mo.x, mo.y, target.x, target.y) + rd*ANGLE_90 + P_RandomRange(-10, 10)*ANG1)
			local fist = P_SpawnMobj(mo.x + (P_RandomRange(10, 50)*cos(ang)),
									 mo.y + (P_RandomRange(10, 50)*sin(ang)),
									 mo.z + P_RandomRange(10, 60)*FRACUNIT, MT_DUMMY)
			fist.angle = R_PointToAngle2(fist.x, fist.y, target.x, target.y)
			fist.tics = 6
			fist.sprite = SPR_CEFS
			fist.colorized = true
			fist.frame = A|TR_TRANS20
			fist.momx = (target.x - fist.x)/4
			fist.momy = (target.y - fist.y)/4
			fist.scale = 5*FRACUNIT/4
			mo.fists[#mo.fists+1] = fist
			
			if timer%2 == 0	
				local boom = P_SpawnMobjFromMobj(target, P_RandomRange(-20, 20)*FRACUNIT, P_RandomRange(-20, 20)*FRACUNIT, target.height + P_RandomRange(-20, 20)*FRACUNIT, MT_DUMMY)
				boom.state = S_CACEE_HIT1
				boom.scale = FRACUNIT/4
			end
			
			if timer%4 == 0
				playSound(mo.battlen, sfx_hit)
			end
			
			if timer%10 == 0 and dmg
				damageObject(target, dmg)
				local boom = P_SpawnMobjFromMobj(target, 0, 0, target.height, MT_DUMMY)
				boom.state = S_CACEE_HIT1
				playSound(mo.battlen, sfx_cehit1)
			end
			
			local h = P_SpawnMobj(target.x, target.y, target.z, MT_DUMMY)
			h.state = S_SSPK1
			h.fuse = TICRATE
			h.momx = P_RandomRange(-24, 24)*FRACUNIT
			h.momy = P_RandomRange(-24, 24)*FRACUNIT
			h.momz = P_RandomRange(2, 24)*FRACUNIT
		elseif timer == 127
			local ang = R_PointToAngle2(mo.x, mo.y, target.x, target.y)
			ANIM_set(mo, mo.anim_special4)
			P_InstaThrust(mo, ang, 20*FRACUNIT)
			
			local rand = P_RandomRange(1, 10)
			if rand <= 5
				playSound(mo.battlen, jabsounds[rand])
			end
		elseif timer == 130
			damageObject(target)
			localquake(mo.battlen, FRACUNIT*30, 5)
			playSound(mo.battlen, sfx_ceboom)
			mo.flags = $ & ~MF_NOCLIPHEIGHT
			mo.flags = $ & ~MF_NOGRAVITY
			
			local boom = P_SpawnMobjFromMobj(target, 0, 0, target.height, MT_DUMMY)
			boom.state = S_CACEE_HIT1

			for i = 1, 16
				local h = P_SpawnMobj(target.x, target.y, target.z, MT_DUMMY)
				h.state = S_SSPK1
				h.fuse = TICRATE
				h.momx = P_RandomRange(-24, 24)*FRACUNIT
				h.momy = P_RandomRange(-24, 24)*FRACUNIT
				h.momz = P_RandomRange(2, 24)*FRACUNIT
			end
			
			local d = P_SpawnMobj(target.x, target.y, target.z+128*FRACUNIT, MT_THOK)
			d.sprite = SPR_THMP
			d.frame = B|FF_FULLBRIGHT
			d.scale = FRACUNIT/4
			d.destscale = FRACUNIT*3
			d.scalespeed = FRACUNIT/8
			d.fuse = TICRATE-10
			d.tics = d.fuse
			d.momz = FRACUNIT*2
			d.momx = P_RandomRange(0, FRACUNIT-1)*P_RandomRange(-8, 8)
			d.momy = P_RandomRange(0, FRACUNIT-1)*P_RandomRange(-8, 8)
			d.color = SKINCOLOR_RED
		elseif timer == 170
			mo.fists = nil
			
			if mo.cacee and mo.cacee.combo
				mo.cacee.roll[#mo.cacee.roll+1] = "Fiesta de Espinas"
				mo.cacee.combo[3] = 0
			end
			
			return true
		end
		
		for i = 1, #mo.fists
			local fist = mo.fists[i]
			if fist and fist.valid
				local ghost = P_SpawnGhostMobj(fist)
				ghost.colorized = true
				ghost.color = SKINCOLOR_SUPERGOLD2
				ghost.frame = A|TR_TRANS40|FF_FULLBRIGHT
				ghost.destscale = 1
				ghost.scalespeed = FRACUNIT/6
			end
		end
	end,
}

attackDefs["c-bandita rebellion"] = {
	name = "Rebelion de Bandita",
	type = ATK_STRIKE,
	power = 1300,
	accuracy = 100,
	costtype = CST_HPPERCENT,
	cost = 24,
	critical = 40,
	hits = 6,
	norandom = true,
	norogue = true,
	nometronome = true,
	noenemycast = true,
	desc = "Medium Strike dmg to one\nenemy many, many times.\nAbsurd crit rate.",
	target = TGT_ENEMY,
	anim = function(mo, targets, hittargets, timer)
		local target = hittargets[1]
		local btl = server.P_BattleStatus[mo.battlen]
		local cam = btl.cam
		
		if timer == 1
			mo.fists = {}
			mo.angle = R_PointToAngle2(mo.x, mo.y, target.x, target.y)
		elseif timer == 20
			ANIM_set(mo, mo.anim_aoa_guard, true)
			playSound(mo.battlen, sfx_spndsh)
			local ghost = P_SpawnGhostMobj(mo)
			ghost.tics = 10
			ghost.colorized = true
			ghost.color = SKINCOLOR_SUPERGOLD2
			ghost.destscale = FRACUNIT*2
		elseif timer == 30
			local an = R_PointToAngle2(target.x, target.y, mo.x, mo.y) + ANGLE_45

			local cx = target.x + 224*cos(an)
			local cy = target.y + 224*sin(an)
			CAM_goto(cam, cx, cy, cam.z - 30*FRACUNIT, 70*FRACUNIT)
			CAM_angle(cam, R_PointToAngle2(cx, cy, target.x, target.y), ANG1*4)
		elseif timer == 40
			mo.flags = $|MF_NOCLIPHEIGHT|MF_NOGRAVITY
			mo.momx = (target.x - mo.x)/11
			mo.momy = (target.y - mo.y)/11
			playSound(mo.battlen, sfx_zoom)
			ANIM_set(mo, mo.anim_run, true)
		elseif timer > 40 and timer < 48
			local ghost = P_SpawnGhostMobj(mo)
			ghost.tics = 10
			ghost.colorized = true
			ghost.color = SKINCOLOR_RED
			
			if timer == 45
				ANIM_set(mo, mo.anim_special4, true)
			end
		elseif timer == 49
			P_InstaThrust(mo, mo.angle, 0)
			damageObject(target)
			localquake(mo.battlen, FRACUNIT*30, 5)
			playSound(mo.battlen, sfx_ceboom)
			
			local boom = P_SpawnMobjFromMobj(target, 0, 0, target.height, MT_DUMMY)
			boom.state = S_CACEE_HIT1

			for i = 1, 16
				local h = P_SpawnMobj(target.x, target.y, target.z, MT_DUMMY)
				h.state = S_SSPK1
				h.fuse = TICRATE
				h.momx = P_RandomRange(-24, 24)*FRACUNIT
				h.momy = P_RandomRange(-24, 24)*FRACUNIT
				h.momz = P_RandomRange(2, 24)*FRACUNIT
			end
			
			local d = P_SpawnMobj(target.x, target.y, target.z+128*FRACUNIT, MT_THOK)
			d.sprite = SPR_THMP
			d.frame = A|FF_FULLBRIGHT
			d.scale = FRACUNIT/4
			d.destscale = FRACUNIT*3
			d.scalespeed = FRACUNIT/8
			d.fuse = TICRATE-10
			d.tics = d.fuse
			d.momz = FRACUNIT*2
			d.momx = P_RandomRange(0, FRACUNIT-1)*P_RandomRange(-8, 8)
			d.momy = P_RandomRange(0, FRACUNIT-1)*P_RandomRange(-8, 8)
			d.color = SKINCOLOR_RED
		elseif timer == 50
			playSound(mo.battlen, sfx_megi6)
			local s = P_SpawnMobj(mo.x, mo.y, mo.z + mo.height, MT_DUMMY)
			s.color = SKINCOLOR_WHITE
			s.state = S_MEGISTAR1
			s.scale = FRACUNIT/4
		elseif timer == 60
			localquake(mo.battlen, FRACUNIT*20, 60)
			ANIM_set(mo, mo.anim_guard, true)
			
			if (P_RandomRange(1,10) == 10 or mo.name == "\x4A\x6F\x74\x61\x72\x6F") and mo.name ~= "\x44\x49\x4F"
				playSound(mo.battlen, (P_RandomRange(0,1) and sfx_cora1 or sfx_cora2))
			elseif P_RandomRange(1,10) == 9 or mo.name == "\x44\x49\x4F"
				playSound(mo.battlen, (P_RandomRange(0,1) and sfx_cora3 or sfx_cora4))
			end
		elseif timer >= 61 and timer <= 120
			local dmg
			
			if server.P_BattleStatus[mo.battlen].dmg_hits[target.dmg_index][2] and type(server.P_BattleStatus[mo.battlen].dmg_hits[target.dmg_index][2]) == "number"
				dmg = server.P_BattleStatus[mo.battlen].dmg_hits[target.dmg_index][2]/6
			end
			
			local rd = P_RandomRange(0,1) and -1 or 1
			local ang = (R_PointToAngle2(mo.x, mo.y, target.x, target.y) + rd*ANGLE_90 + P_RandomRange(-10, 10)*ANG1)
			local fist = P_SpawnMobj(mo.x + (P_RandomRange(10, 50)*cos(ang)),
									 mo.y + (P_RandomRange(10, 50)*sin(ang)),
									 mo.z + P_RandomRange(10, 60)*FRACUNIT, MT_DUMMY)
			fist.angle = R_PointToAngle2(fist.x, fist.y, target.x, target.y)
			fist.tics = 6
			fist.sprite = SPR_CEFS
			fist.colorized = true
			fist.frame = A|TR_TRANS20
			fist.momx = (target.x - fist.x)/4
			fist.momy = (target.y - fist.y)/4
			fist.scale = 5*FRACUNIT/4
			mo.fists[#mo.fists+1] = fist
			
			if timer%2 == 0	
				local boom = P_SpawnMobjFromMobj(target, P_RandomRange(-20, 20)*FRACUNIT, P_RandomRange(-20, 20)*FRACUNIT, target.height + P_RandomRange(-20, 20)*FRACUNIT, MT_DUMMY)
				boom.state = S_CACEE_HIT1
				boom.scale = FRACUNIT/4
			end
			
			if timer%4 == 0
				playSound(mo.battlen, sfx_hit)
			end
			
			if timer%10 == 0 and dmg
				damageObject(target, dmg)
				local boom = P_SpawnMobjFromMobj(target, 0, 0, target.height, MT_DUMMY)
				boom.state = S_CACEE_HIT1
				playSound(mo.battlen, sfx_cehit1)
			end
			
			local h = P_SpawnMobj(target.x, target.y, target.z, MT_DUMMY)
			h.state = S_SSPK1
			h.fuse = TICRATE
			h.momx = P_RandomRange(-24, 24)*FRACUNIT
			h.momy = P_RandomRange(-24, 24)*FRACUNIT
			h.momz = P_RandomRange(2, 24)*FRACUNIT
		elseif timer == 127
			damageObject(target)
			mo.flags = $ & ~MF_NOCLIPHEIGHT
			mo.flags = $ & ~MF_NOGRAVITY
			target.momz = 6*FRACUNIT
			playSound(mo.battlen, sfx_cepun4)
			localquake(mo.battlen, FRACUNIT*30, 8)
			
			local d = P_SpawnMobj(target.x, target.y, target.z+128*FRACUNIT, MT_THOK)
			d.sprite = SPR_THMP
			d.frame = B|FF_FULLBRIGHT
			d.scale = FRACUNIT/4
			d.destscale = FRACUNIT*3
			d.scalespeed = FRACUNIT/8
			d.fuse = TICRATE-10
			d.tics = d.fuse
			d.momz = FRACUNIT*2
			d.momx = P_RandomRange(0, FRACUNIT-1)*P_RandomRange(-8, 8)
			d.momy = P_RandomRange(0, FRACUNIT-1)*P_RandomRange(-8, 8)
			d.color = SKINCOLOR_SUPERGOLD2
			
			caceecircle(mo, MT_SUPERSPARK, 16, 32*mo.scale, 0, mo.scale, false, 0, false, mo.angle)
			caceecircle(mo, MT_MINECARTSPARK, 8, 8*mo.scale, 0, mo.scale/4, false, 0, false, mo.angle)
			
			local thok = P_SpawnMobjFromMobj(mo,0,0,0,MT_THOK)
			thok.state = S_CACEE_HIT1
			thok.flags2 = $|MF2_SPLAT
			thok.scale = $*2
			thok.blendmode = AST_ADD
			
			local ghost = P_SpawnGhostMobj(mo)
			ghost.colorized = true
			ghost.color = SKINCOLOR_SUPERGOLD2
			ghost.destscale = $*16
		elseif timer == 135
			ANIM_set(mo, mo.anim_special5, true)
			P_InstaThrust(mo, 0, 0)
			mo.momz = 16*FRACUNIT
			target.momz = FixedMul(target.scale, mo.momz)
			localquake(mo.battlen, FRACUNIT*20, 10)

			caceecircle(mo, MT_DUST, 16, 16*mo.scale, 0, mo.scale, false, 0, false, mo.angle)
			playSound(mo.battlen, sfx_ceuppr)
			
			local rand = P_RandomRange(1, 10)
			if rand <= 5
				playSound(mo.battlen, jabsounds[rand])
			elseif rand == 6
				playSound(mo.battlen, sfx_ceshok)
			end
			
			local boom = P_SpawnMobjFromMobj(target, 0, 0, target.height/2, MT_DUMMY)
			boom.state = S_CACEE_HIT1
		elseif timer > 135 and timer < 170
			if timer >= 140 and timer <= 160 and timer%10 == 0
				local dmg
				
				if server.P_BattleStatus[mo.battlen].dmg_hits[target.dmg_index][4] and type(server.P_BattleStatus[mo.battlen].dmg_hits[target.dmg_index][4]) == "number"
					dmg = server.P_BattleStatus[mo.battlen].dmg_hits[target.dmg_index][4]/3
				end
				
				if dmg
					damageObject(target, dmg)
					playSound(mo.battlen, sfx_hit)
				end
			end
			
			local speed = max(1, min(8, mo.momz/2/mo.scale))
			mo.angle = $+(ANGLE_11hh * speed)
			
			local ghost = P_SpawnGhostMobj(mo)
			ghost.colorized = true
			ghost.color = SKINCOLOR_SUPERGOLD2
		elseif timer == 175
			local ang = R_PointToAngle2(mo.x, mo.y, target.x, target.y)
			mo.angle = ang
			playSound(mo.battlen, sfx_cepun3)
			ANIM_set(mo, mo.anim_special4)
			mo.momx = (target.x - mo.x)/6
			mo.momy = (target.y - mo.y)/6
		elseif timer > 175 and timer < 180
			local ghost = P_SpawnGhostMobj(mo)
			ghost.colorized = true
			ghost.color = SKINCOLOR_SUPERGOLD2
			ghost.destscale = $*16
		elseif timer == 180
			playSound(mo.battlen, sfx_s3k9c)
			for i = 1, #btl.fighters
				for i = 1, #server.playerlist[mo.battlen]
					if server.playerlist[mo.battlen][i]
						P_FlashPal(server.playerlist[mo.battlen][i], 1, 15)
						S_PauseMusic(server.playerlist[mo.battlen][i])
					end
				end
			end
			
			local an = R_PointToAngle2(target.x, target.y, mo.x, mo.y) + ANGLE_45

			local cx = target.x + 600*cos(an)
			local cy = target.y + 600*sin(an)
			CAM_goto(cam, cx, cy, cam.z, 50*FRACUNIT)
		elseif timer > 180 and timer < 195
			for i = 1, #btl.fighters
				local t = btl.fighters[i]
				
				if t and t.valid
					P_InstaThrust(t, t.angle, 0)
					t.momz = 0
				end
			end
		elseif timer == 195
			for i = 1, #server.playerlist[mo.battlen]
				if server.playerlist[mo.battlen][i]
					S_ResumeMusic(server.playerlist[mo.battlen][i])
				end
			end
			
			local ang = R_PointToAngle2(mo.x, mo.y, target.x, target.y)
			
			damageObject(target)
			localquake(mo.battlen, FRACUNIT*40, 10)
			playSound(mo.battlen, sfx_s3k4e)
			
			local boom = P_SpawnMobjFromMobj(target, 0, 0, target.height, MT_DUMMY)
			boom.state = S_CACEE_HIT1
			boom.scale = $*2
			DoExplosion(target)
			P_InstaThrust(target, ang, target.scale*20)
			target.momz = target.scale*10
			ANIM_set(target, target.anim_hurt)
			P_InstaThrust(mo, ang + ANGLE_180, mo.scale*20)
			mo.momz = mo.scale*10
			ANIM_set(mo, mo.anim_hurt)

			for i = 1, 16
				local h = P_SpawnMobj(target.x, target.y, target.z, MT_DUMMY)
				h.state = S_SSPK1
				h.fuse = TICRATE
				h.momx = P_RandomRange(-24, 24)*FRACUNIT
				h.momy = P_RandomRange(-24, 24)*FRACUNIT
				h.momz = P_RandomRange(2, 24)*FRACUNIT
			end
			
			local d = P_SpawnMobj(target.x, target.y, target.z+128*FRACUNIT, MT_THOK)
			d.sprite = SPR_THMP
			d.frame = B|FF_FULLBRIGHT
			d.scale = FRACUNIT/4
			d.destscale = FRACUNIT*3
			d.scalespeed = FRACUNIT/8
			d.fuse = TICRATE-10
			d.tics = d.fuse
			d.momz = FRACUNIT*2
			d.momx = P_RandomRange(0, FRACUNIT-1)*P_RandomRange(-8, 8)
			d.momy = P_RandomRange(0, FRACUNIT-1)*P_RandomRange(-8, 8)
			d.color = SKINCOLOR_RED
		elseif timer == 250
			mo.fists = nil
			
			if mo.cacee and mo.cacee.combo
				mo.cacee.roll[#mo.cacee.roll+1] = "Rebelion de Bandita"
				mo.cacee.combo[3] = 0
			end
			
			return true
		end
		
		if timer > 137 and timer < 250
			cam.z = $ + mo.momz
		end
		
		for i = 1, #mo.fists
			local fist = mo.fists[i]
			if fist and fist.valid
				local ghost = P_SpawnGhostMobj(fist)
				ghost.colorized = true
				ghost.color = SKINCOLOR_SUPERGOLD2
				ghost.frame = A|TR_TRANS40|FF_FULLBRIGHT
				ghost.destscale = 1
				ghost.scalespeed = FRACUNIT/6
			end
		end
	end,
}

attackDefs["c-bandita heat"] = {
	name = "Bandita's Heat",
	type = ATK_FIRE,
	power = 100,
	accuracy = 95,
	costtype = CST_SP,
	cost = 5,
	critical = 5,
	norandom = true,
	norogue = true,
	nometronome = true,
	noenemycast = true,
	desc = "Light Fire dmg to one enemy. Extends\ncombo based on dodge stacks.\nDoubles effect on a critical hit.",
	target = TGT_ENEMY,
	anim = function(mo, targets, hittargets, timer)
		local target = hittargets[1]
		
		if timer == 20
			playSound(mo.battlen, sfx_s3k4c)
			ANIM_set(mo, mo.anim_special7)
			mo.angle = R_PointToAngle2(mo.x, mo.y, target.x, target.y)
		elseif timer == 32
			for i = 1, 15
				P_SpawnMobj(mo.x + ((target.x - mo.x)*i)/15, mo.y + ((target.y - mo.y)*i)/15, mo.z + mo.height/2, MT_SPARK)
			end
			
			playSound(mo.battlen, sfx_cegun)
			playSound(mo.battlen, sfx_rail1)
			
			local bang = P_SpawnMobj(mo.x, mo.y, mo.z + mo.height/2, MT_DUMMY)
			bang.state = S_QUICKBOOM1
			P_InstaThrust(mo, mo.angle + ANGLE_180, FRACUNIT*5)
		elseif timer == 35

			for i = 1, 32
				local smoke = P_SpawnMobj(target.x + P_RandomRange(-48, 48)*FRACUNIT, target.y + P_RandomRange(-48, 48)*FRACUNIT, target.z + P_RandomRange(0, 128)*FRACUNIT, MT_SMOKE)
				smoke.scale = FRACUNIT*4
				smoke.momz = P_RandomRange(3, 10)*FRACUNIT
			end

			damageObject(target)
			localquake(mo.battlen, FRACUNIT*17, 20)
			local smol = P_SpawnMobj(target.x, target.y, target.z, MT_SMOLDERING)
			smol.fuse = TICRATE*2
			smol.scale = FRACUNIT*3

		elseif timer == 60
			if mo.cacee and mo.cacee.combo
				mo.cacee.roll[#mo.cacee.roll+1] = "Bandita's Heat"
				if target.damagestate == DMG_CRITICAL or target.damagestate == DMG_WEAK or target.damagestate == DMG_TECHNICAL
					mo.cacee.heat = min(max($, mo.cacee.dstacks*2+1), 6)
				elseif not (target.damagestate == DMG_MISS or target.damagestate == DMG_BLOCK
				or target.damagestate == DMG_REPEL or target.damagestate == DMG_DRAIN)
					mo.cacee.heat = min(max($, mo.cacee.dstacks+1), 6)
				end
			end
			
			return true
		end
	end,
}

attackDefs["c-bandita heat 2"] = {
	name = "Bandita's Heat II",
	type = ATK_FIRE,
	power = 200,
	accuracy = 95,
	costtype = CST_SP,
	cost = 10,
	critical = 10,
	norandom = true,
	norogue = true,
	nometronome = true,
	noenemycast = true,
	desc = "Medium Fire dmg to one enemy. Extends\ncombo based on dodge stacks.\nDoubles effect on a critical hit.",
	target = TGT_ENEMY,
	anim = function(mo, targets, hittargets, timer)
		local target = hittargets[1]
		
		if timer == 20
			playSound(mo.battlen, sfx_s3k4c)
			ANIM_set(mo, mo.anim_special7)
			mo.angle = R_PointToAngle2(mo.x, mo.y, target.x, target.y)
		elseif timer == 32
			for i = 1, 15
				P_SpawnMobj(mo.x + ((target.x - mo.x)*i)/15, mo.y + ((target.y - mo.y)*i)/15, mo.z + mo.height/2, MT_SPARK)
			end
			
			playSound(mo.battlen, sfx_cegun)
			playSound(mo.battlen, sfx_rail1)
			
			local bang = P_SpawnMobj(mo.x, mo.y, mo.z + mo.height/2, MT_DUMMY)
			bang.state = S_QUICKBOOM1
			P_InstaThrust(mo, mo.angle + ANGLE_180, FRACUNIT*5)
		elseif timer == 35

			for i = 1, 32
				local smoke = P_SpawnMobj(target.x + P_RandomRange(-48, 48)*FRACUNIT, target.y + P_RandomRange(-48, 48)*FRACUNIT, target.z + P_RandomRange(0, 128)*FRACUNIT, MT_SMOKE)
				smoke.scale = FRACUNIT*4
				smoke.momz = P_RandomRange(3, 10)*FRACUNIT
			end

			damageObject(target)
			localquake(mo.battlen, FRACUNIT*17, 20)
			local smol = P_SpawnMobj(target.x, target.y, target.z, MT_SMOLDERING)
			smol.fuse = TICRATE*2
			smol.scale = FRACUNIT*3

		elseif timer == 60
			if mo.cacee and mo.cacee.combo
				mo.cacee.roll[#mo.cacee.roll+1] = "Bandita's Heat"
				if target.damagestate == DMG_CRITICAL or target.damagestate == DMG_WEAK or target.damagestate == DMG_TECHNICAL
					mo.cacee.heat = max($, mo.cacee.dstacks*2+1)
				elseif not (target.damagestate == DMG_MISS or target.damagestate == DMG_BLOCK
				or target.damagestate == DMG_REPEL or target.damagestate == DMG_DRAIN)
					mo.cacee.heat = max($, mo.cacee.dstacks+1)
				end
			end
			
			return true
		end
	end,
}

attackDefs["c-detoxify"] = {
	name = "Detoxify",
	dekunda = true,
	type = ATK_SUPPORT,
	costtype = CST_SP,
	cost = 14,
	norandom = true,
	norogue = true,
	nometronome = true,
	noenemycast = true,
	desc = "Remove your debuffs and\nraises agility.",
	target = TGT_CASTER,
	anim = function(mo, targets, hittargets, timer)
		local target = hittargets[1]
		local strs = {"atk", "mag", "def", "agi", "crit"}
		local colors = {SKINCOLOR_ORANGE, SKINCOLOR_LAVENDER, SKINCOLOR_EMERALD, SKINCOLOR_YELLOW}

		if timer == 20
			playSound(mo.battlen, sfx_status)
			for j = 1, 16
				local orb = P_SpawnMobj(target.x, target.y, target.z, MT_DUMMY)
				orb.momx = P_RandomRange(-16, 16)<<FRACBITS
				orb.momy = P_RandomRange(-16, 16)<<FRACBITS
				orb.momz = P_RandomRange(-16, 16)<<FRACBITS
				orb.destscale = 0
				orb.frame = A
				orb.color = colors[P_RandomRange(1, #colors)]
			end
			
			for j = 1, #strs
				local s = strs[j]
				if target.buffs[s][1] < 0
					target.buffs[s][1] = 0
					target.buffs[s][2] = 0
				end
			end
			BTL_logMessage(targets[1].battlen, "Stat decreases nullified")
		elseif timer == 40
			playSound(mo.battlen, sfx_buff)
			buffStat(target, "agi")
			for i = 1,16
				local dust = P_SpawnMobj(target.x, target.y, target.z, MT_DUMMY)
				dust.angle = ANGLE_90 + ANG1* (22*(i-1))
				dust.state = S_CDUST1
				P_InstaThrust(dust, dust.angle, 30*FRACUNIT)
				dust.color = SKINCOLOR_GREEN
				dust.scale = FRACUNIT*2
			end

		elseif timer > 40 and timer <= 70

			if leveltime%2 == 0
				for i = 1,16

					local thok = P_SpawnMobj(target.x+P_RandomRange(-70, 70)*FRACUNIT, target.y+P_RandomRange(-70, 70)*FRACUNIT, target.z+P_RandomRange(0, 50)*FRACUNIT, MT_DUMMY)
					thok.state = S_CDUST1
					thok.momz = P_RandomRange(3, 10)*FRACUNIT
					thok.color = SKINCOLOR_GREEN
					thok.tics = P_RandomRange(10, 35)
					thok.scale = FRACUNIT*3/2
				end
			end

			local thok = P_SpawnMobj(target.x+P_RandomRange(-70, 70)*FRACUNIT, target.y+P_RandomRange(-70, 70)*FRACUNIT, target.z+P_RandomRange(0, 50)*FRACUNIT, MT_DUMMY)
			thok.sprite = SPR_SUMN
			thok.frame = F|FF_FULLBRIGHT|TR_TRANS50
			thok.momz = P_RandomRange(6, 16)*FRACUNIT
			thok.color = SKINCOLOR_GREEN
			thok.tics = P_RandomRange(10, 35)
		elseif timer == 90
			return true
		end
	end,
}

attackDefs["c-quick step"] = {
	name = "Quick Step",
	type = ATK_SUPPORT,
	costtype = CST_SP,
	cost = 5,
	desc = "Doubles own agility for 1 turn and gives\na dodge stack. Grants one extra stack of\nagility at critical health.",
	target = TGT_CASTER,
	buff = true,
	norepel = true,
	norandom = true,
	norogue = true,
	nometronome = true,
	noenemycast = true,
	anim = function(mo, targets, hittargets, timer)
		local target = hittargets[1]

		if timer == 20
			if mo.cacee and mo.cacee.combo
				mo.cacee.quickstep = 2
			end
			
			mo.colorized = true
			mo.ghost = P_SpawnGhostMobj(mo)
			mo.ghost.fuse = 61
			mo.frame = $|TR_TRANS60
			mo.fast = FRACUNIT
			mo.moveangle = mo.angle + ANGLE_90
			playSound(mo.battlen, sfx_wind1)
			
			for i = 1, 8
				local g = P_SpawnMobj(target.x, target.y, target.z + P_RandomRange(0, 60)*FRACUNIT, MT_GARU)
				g.target = target
				g.angle = FixedAngle(P_RandomRange(1, 360)*FRACUNIT)
				if i == 1 or i == 8
					g.jizzcolor = true
				end
				if i%2
					g.invertrotation = true
				end
				g.dist = P_RandomRange(45, 90)
				g.tics = 60
			end
		elseif timer > 20 and timer <= 80
			if timer%2 == 0
				P_InstaThrust(mo.ghost, mo.moveangle, mo.fast)
				mo.moveangle = $ + ANGLE_180
				P_InstaThrust(mo, mo.moveangle, mo.fast)
				
				if timer < 50
					mo.fast = $ + FRACUNIT
				else
					mo.fast = $ - FRACUNIT
				end
				
				if timer == 24 -- I hate this but I can't think of a better way to do it
				or timer == 32
				or timer == 38
				or timer == 42
				or timer == 46
				or timer == 48
				or timer == 50
				or timer == 52
				or timer == 54
				or timer == 58
				or timer == 62
				or timer == 68
				or timer == 76
					playSound(mo.battlen, sfx_thok)
				end
			end
		elseif timer == 81
			mo.frame = $ & ~TR_TRANS60
			mo.colorized = false
			playSound(mo.battlen, sfx_ceuppr)
			BTL_logMessage(targets[1].battlen, mo.name+" takes an evasive stance.")
			
			for i = 1, 32
				local g = P_SpawnMobj(target.x, target.y, target.z, MT_DUMMY)
				g.scale = FRACUNIT/2
				g.destscale = 1
				g.color = SKINCOLOR_EMERALD
				g.frame = A
				if i%2 then g.color = SKINCOLOR_WHITE end
				g.momx = P_RandomRange(-15, 15)*FRACUNIT
				g.momy = P_RandomRange(-15, 15)*FRACUNIT
				g.momz = P_RandomRange(-15, 15)*FRACUNIT
			end
		elseif timer == 100
			if mo.hp <= mo.maxhp/4
				playSound(mo.battlen, sfx_buff)
				for i = 1,16
					local dust = P_SpawnMobj(target.x, target.y, target.z, MT_DUMMY)
					dust.angle = ANGLE_90 + ANG1* (22*(i-1))
					dust.state = S_CDUST1
					P_InstaThrust(dust, dust.angle, 30*FRACUNIT)
					dust.color = SKINCOLOR_GREEN
					dust.scale = FRACUNIT*2
				end
				
				buffStat(target, "agi")
			else
				if mo.cacee and mo.cacee.combo
					mo.cacee.roll[#mo.cacee.roll+1] = "Quick Step"
				end
				
				mo.fast = nil
				mo.moveangle = nil
				mo.ghost = nil
				
				if mo.cacee and mo.cacee.charisma and mo.cacee.dstacks < mo.cacee.charisma
					local ghost = P_SpawnGhostMobj(mo)
					ghost.scalespeed = FRACUNIT/4
					ghost.destscale = FRACUNIT*2
					ghost.tics = 3
					
					playSound(mo.battlen, sfx_ceuppr)
					mo.cacee.dstacks = $ + 1
				end
				
				return true
			end
		elseif timer > 100 and timer < 130
			if leveltime%2 == 0
				for i = 1,16

					local thok = P_SpawnMobj(target.x+P_RandomRange(-70, 70)*FRACUNIT, target.y+P_RandomRange(-70, 70)*FRACUNIT, target.z+P_RandomRange(0, 50)*FRACUNIT, MT_DUMMY)
					thok.state = S_CDUST1
					thok.momz = P_RandomRange(3, 10)*FRACUNIT
					thok.color = SKINCOLOR_GREEN
					thok.tics = P_RandomRange(10, 35)
					thok.scale = FRACUNIT*3/2
				end
			end

			local thok = P_SpawnMobj(target.x+P_RandomRange(-70, 70)*FRACUNIT, target.y+P_RandomRange(-70, 70)*FRACUNIT, target.z+P_RandomRange(0, 50)*FRACUNIT, MT_DUMMY)
			thok.sprite = SPR_SUMN
			thok.frame = F|FF_FULLBRIGHT|TR_TRANS50
			thok.momz = P_RandomRange(6, 16)*FRACUNIT
			thok.color = SKINCOLOR_GREEN
			thok.tics = P_RandomRange(10, 35)
		elseif timer == 140
			if mo.cacee and mo.cacee.combo
				mo.cacee.roll[#mo.cacee.roll+1] = "Quick Step"
			end
			
			if mo.cacee and mo.cacee.charisma and mo.cacee.dstacks < mo.cacee.charisma
				local ghost = P_SpawnGhostMobj(mo)
				ghost.scalespeed = FRACUNIT/4
				ghost.destscale = FRACUNIT*2
				ghost.tics = 3
				
				playSound(mo.battlen, sfx_ceuppr)
				mo.cacee.dstacks = $ + 1
			end
			
			return true
		end
	end,
}

local c_danceribbons = function(interval, timer, mo, target, colors)
	if timer%interval == 0
		local s = P_SpawnMobj(mo.x + P_RandomRange(-150, 150)*FRACUNIT, mo.y + P_RandomRange(-150, 150)*FRACUNIT, mo.z + P_RandomRange(0, 120)*FRACUNIT, MT_DUMMY)
		s.state = S_DRIBBON_1_1
		s.color = colors[P_RandomRange(1, #colors)]
		s.scale = 3*FRACUNIT/2
		s.rollangle = P_RandomRange(1, 360)*ANG1
		
		P_InstaThrust(s, P_RandomRange(1, 360)*ANG1, 2*FRACUNIT)
		
	elseif timer%interval == interval/2
		local s = P_SpawnMobj(target.x + P_RandomRange(-150, 150)*FRACUNIT, target.y + P_RandomRange(-150, 150)*FRACUNIT, target.z + P_RandomRange(0, 120)*FRACUNIT, MT_DUMMY)
		s.state = S_DRIBBON_2_1
		s.color = colors[P_RandomRange(1, #colors)]
		s.scale = 3*FRACUNIT/2
		s.rollangle = P_RandomRange(1, 360)*ANG1
		
		P_InstaThrust(s, P_RandomRange(1, 360)*ANG1, 2*FRACUNIT)
	end
end

attackDefs["c-taru tango"] = {
	name = "Taru-Tango",
	type = ATK_SUPPORT,
	costtype = CST_SP,
	cost = 24,
	desc = "Raise yours and a partner's physical\nattack by 1-2 stages. Draws enemy's attention\nfor 1 turn. Clears status effects.",
	target = TGT_ALLY,
	buff = true,
	norandom = true,
	norogue = true,
	nometronome = true,
	noenemycast = true,
	nocast = 	function(targets, n, mo)	-- we can't cast this skill if this function returns true
					local target = targets[n]
					if target == mo
						BTL_logMessage(targets[1].battlen, "You can't partner with yourself!")
						return true
					end
				end,
	anim = function(mo, targets, hittargets, timer)
		local target = hittargets[1]
		local btl = server.P_BattleStatus[mo.battlen]
		local cam = btl.cam
		local avgx, avgy = 0, 0
		for i = 1, #btl.fighters
			avgx = $ + btl.fighters[i].x/FRACUNIT
			avgy = $ + btl.fighters[i].y/FRACUNIT
		end
		avgx = ($/#btl.fighters)*FRACUNIT
		avgy = ($/#btl.fighters)*FRACUNIT
		
		local colors = {SKINCOLOR_RED, SKINCOLOR_CRIMSON, SKINCOLOR_FLAME, SKINCOLOR_SUNSET, SKINCOLOR_ORANGE, SKINCOLOR_APRICOT}
		
		if timer == 1
			for i = 1, #server.P_BattleStatus[mo.battlen].fighters
				for i = 1, #server.playerlist[mo.battlen]
					if server.playerlist[mo.battlen][i]
						S_FadeMusic(0, MUSICRATE*2, server.playerlist[mo.battlen][i])
					end
				end
			end
			
			mo.dancestate = P_RandomRange(1, 7)
		elseif timer == 20
			local an = (R_PointToAngle2(mo.x, mo.y, avgx, avgy) + R_PointToAngle2(target.x, target.y, avgx, avgy))/2
			local space = 10
			mo.angle = R_PointToAngle2(mo.x, mo.y, avgx + space*cos(an + ANGLE_90), avgy + space*sin(an + ANGLE_90))
			target.angle = R_PointToAngle2(target.x, target.y, avgx + space*cos(an - ANGLE_90), avgy + space*sin(an - ANGLE_90))
			ANIM_set(mo, mo.anim_run, true)
			ANIM_set(target, target.anim_run, true)
			mo.flags = $|MF_NOGRAVITY|MF_NOCLIPHEIGHT
			target.flags = $|MF_NOGRAVITY|MF_NOCLIPHEIGHT
			
			P_InstaThrust(mo, mo.angle, R_PointToDist2(mo.x, mo.y, avgx + space*cos(an + ANGLE_90), avgy + space*sin(an + ANGLE_90))/20)
			P_InstaThrust(target, target.angle, R_PointToDist2(target.x, target.y, avgx + space*cos(an - ANGLE_90), avgy + space*cos(an - ANGLE_90))/20)
		elseif timer == 30
			local an = (mo.angle + target.angle)/2 + ANGLE_45
			
			local cx = avgx - 280*cos(an)
			local cy = avgy - 280*sin(an)

			CAM_goto(cam, cx, cy, cam.z, 20*FRACUNIT)
			CAM_angle(cam, an, ANG1*4)
			
			playSound(mo.battlen, dancesounds[P_RandomRange(1, #dancesounds)])
		elseif timer == 40
			ANIM_set(mo, mo.anim_stand, true)
			ANIM_set(target, target.anim_stand, true)
			mo.flags = $ - MF_NOGRAVITY - MF_NOCLIPHEIGHT
			target.flags = $ - MF_NOGRAVITY - MF_NOCLIPHEIGHT
			P_InstaThrust(mo, 0, 0)
			P_InstaThrust(target, 0, 0)
			mo.momz = 3*mo.scale
			
			mo.angle = R_PointToAngle2(mo.x, mo.y, target.x, target.y)
			target.angle = mo.angle + ANGLE_180
		elseif timer == 59
			playSound(mo.battlen, T_CaceeSongs.tango[P_RandomRange(1, #T_CaceeSongs.tango)])
		end
		
		if timer == 60 or timer == 90
			if timer == 60
				mo.angle = $ - ANGLE_45
				target.angle = $ + ANGLE_45
			end
			
			ANIM_set(mo, mo.anim_move, true)
			ANIM_set(target, target.anim_move, true)
		elseif timer > 60 and timer < 75
		or timer > 90 and timer < 105
			P_InstaThrust(mo, mo.angle - ANGLE_45, (timer%30)*FRACUNIT/4)
			P_InstaThrust(target, target.angle + ANGLE_45, (timer%30)*FRACUNIT/4)
		elseif timer == 75 or timer == 105
			ANIM_set(mo, mo.anim_stand)
			ANIM_set(target, target.anim_stand)
			
			P_InstaThrust(mo, 0, 0)
			P_InstaThrust(target, 0, 0)
			playSound(mo.battlen, sfx_s3k4c)
			for m = 0, 1
				local point
				if m then point = mo else point = target end
				
				for i = 1, 4
					local spark = P_SpawnMobj(point.x, point.y, point.z, MT_NIGHTSPARKLE)
					spark.angle = i*ANGLE_22h
					spark.tics = 10
					spark.momz = P_RandomRange(2,6)*FRACUNIT
					P_InstaThrust(spark, P_RandomRange(1,360)*ANG1, FRACUNIT*8)
				end
			end
		elseif timer == 110
			mo.angle = $ + ANGLE_45
			target.angle = $ - ANGLE_45
			ANIM_set(mo, mo.anim_special8, true)
			ANIM_set(target, target.anim_aoa_end, true)
			playSound(mo.battlen, sfx_s3k47)
		elseif timer > 110 and timer <= 140
			mo.angle = $ + ANG1*12
			P_TeleportMove(target, mo.x + 20*cos(mo.angle), mo.y + 20*sin(mo.angle), mo.z + 5*FRACUNIT)
			target.angle = mo.angle + ANGLE_180
		elseif timer == 141
			ANIM_set(mo, mo.anim_stand, true)
			playSound(mo.battlen, sfx_cethmp)
			
			for m = 0, 1
				local point
				if m then point = mo else point = target end
				
				for i = 1, 8
					local spark = P_SpawnMobj(point.x, point.y, point.z, MT_NIGHTSPARKLE)
					spark.angle = i*ANGLE_22h
					spark.tics = 10
					spark.momz = P_RandomRange(2,6)*FRACUNIT
					P_InstaThrust(spark, P_RandomRange(1,360)*ANG1, FRACUNIT*8)
				end
			end
		elseif timer == 150 or timer == 180
			if timer == 150
				mo.angle = $ + ANGLE_45
				target.angle = $ - ANGLE_45
			end
			
			ANIM_set(mo, mo.anim_move, true)
			ANIM_set(target, target.anim_move, true)
		elseif timer > 150 and timer < 165
		or timer > 180 and timer < 195
			P_InstaThrust(mo, mo.angle + ANGLE_45, (timer%30)*FRACUNIT/4)
			P_InstaThrust(target, target.angle - ANGLE_45, (timer%30)*FRACUNIT/4)
		elseif timer == 165 or timer == 195
			ANIM_set(mo, mo.anim_stand)
			ANIM_set(target, target.anim_stand)
			
			P_InstaThrust(mo, 0, 0)
			P_InstaThrust(target, 0, 0)
			playSound(mo.battlen, sfx_s3k4c)
			for m = 0, 1
				local point
				if m then point = mo else point = target end
				
				for i = 1, 4
					local spark = P_SpawnMobj(point.x, point.y, point.z, MT_NIGHTSPARKLE)
					spark.angle = i*ANGLE_22h
					spark.tics = 10
					spark.momz = P_RandomRange(2,6)*FRACUNIT
					P_InstaThrust(spark, P_RandomRange(1,360)*ANG1, FRACUNIT*8)
				end
			end
		end
		
		if mo.dancestate < 7
			if timer == 200
				mo.angle = $ - ANGLE_45
				target.angle = $ + ANGLE_45
				ANIM_set(mo, mo.anim_special8, true)
				ANIM_set(target, target.anim_aoa_end, true)
				playSound(mo.battlen, sfx_s3k47)
			elseif timer > 200 and timer < 250
				mo.angle = $ + ANG1*(timer - 200)
				
				if timer == 225
					for i = 1, 8
						local g = P_SpawnMobj(target.x, target.y, target.z + P_RandomRange(0, 60)*FRACUNIT, MT_GARU)
						g.target = target
						g.angle = FixedAngle(P_RandomRange(1, 360)*FRACUNIT)
						if i == 1 or i == 8
							g.jizzcolor = true
						end
						if i%2
							g.invertrotation = true
						end
						g.dist = P_RandomRange(45, 90)
						g.tics = 25
					end
					
					playSound(mo.battlen, sfx_wind1)
				end
				
				P_TeleportMove(target, mo.x + 25*cos(mo.angle), mo.y + 25*sin(mo.angle), mo.z + ((timer - 200)*FRACUNIT)/2)
				target.angle = mo.angle + ANGLE_180
			elseif timer == 250
				target.momz = target.scale*16
				mo.momz = mo.scale*4
				playSound(mo.battlen, sfx_thok)
				
				ANIM_set(mo, mo.anim_special5)
			elseif timer > 250 and timer < 305
				target.angle = $ - ANG1*(timer-305)
				P_TeleportMove(target, mo.x + (2*(timer - 240))*cos(target.angle), mo.y + (2*(timer - 240))*sin(target.angle), target.z)
				
				if P_IsObjectOnGround(mo) and not mo.landed
					ANIM_set(mo, mo.anim_stand_bored, true)
					
					local firework = P_SpawnMobj(avgx, avgy, mo.z, MT_DUMMY)
					firework.state = S_DFRWORK_1
					firework.cam = cam
					firework.source = mo
					firework.momz = 10*FRACUNIT
					
					mo.landed = true
				end
			end
			
			if timer > 250 and P_IsObjectOnGround(target) and not target.landed
				target.angle = R_PointToAngle2(target.x, target.y, mo.x, mo.y)
				local mad = P_SpawnMobj(target.x, target.y, target.z + target.height + 10*FRACUNIT, MT_DUMMY)
				mad.state = S_CEMAD1
				mad.scale = 3*FRACUNIT/2
				mad.fuse = 60
				ANIM_set(target, target.anim_guard)
				caceecircle(target, MT_DUST, 16, 8*target.scale, 0, target.scale, false, 0, false, mo.angle)
				playSound(mo.battlen, sfx_s3k4c)
				
				target.landed = 1
			end
			
			if target.landed == 10
				target.momz = target.scale*4
				playSound(mo.battlen, sfx_cetmad)
			end
			
			if target.landed then target.landed = $ + 1 end
		else
			if timer == 200
				mo.angle = $ - ANGLE_45
				target.angle = $ + ANGLE_45
				ANIM_set(mo, mo.anim_special8, true)
				ANIM_set(target, target.anim_aoa_end, true)
				playSound(mo.battlen, sfx_s3k47)
			elseif timer > 200 and timer < 240
				mo.angle = $ + ANG1*(timer - 200)
				
				P_TeleportMove(target, mo.x + 25*cos(mo.angle), mo.y + 25*sin(mo.angle), mo.z + ((timer - 200)*FRACUNIT)/2)
				target.angle = mo.angle + ANGLE_180
			elseif timer == 240
				target.momz = target.scale*12
				P_InstaThrust(target, mo.angle + ANGLE_45, 30*target.scale)
				playSound(mo.battlen, sfx_zoom)
				playSound(mo.battlen, sfx_cevops)
				
				ANIM_set(mo, mo.anim_hurt)
				ANIM_set(target, target.anim_hurt, true)
			elseif timer == 260
				ANIM_set(mo, mo.anim_stand)
				mo.angle = R_PointToAngle2(mo.x, mo.y, target.x, target.y)
				
				if target.skin and target.skin == "cacee"
					playSound(mo.battlen, sfx_ceptf1)
				elseif target.skin and charStats[target.skin] and charStats[target.skin].vfx_die
					playSound(mo.battlen, _G[charStats[target.skin].vfx_die[P_RandomRange(1, #charStats[target.skin].vfx_die)]])
				end
			elseif timer == 280
				local tear = P_SpawnMobj(mo.x - 10*cos(cam.angle), mo.y - 10*sin(cam.angle), mo.z + mo.height, MT_DUMMY)
				tear.state = S_CETEAR1
				playSound(mo.battlen, sfx_ceoops)
			end
		end
		
		if timer >= 30 and timer < 380
			for i = 1, #mo.enemies
				local m = mo.enemies[i]
				if not m or not m.valid
					continue
				end
				
				m.frame = $|TR_TRANS70
			end
		end
		
		if timer >= 70 and timer <= 250
			if timer <= 150
				c_danceribbons(30, timer, mo, target, colors)
			elseif timer > 150 and timer <= 180
				c_danceribbons(24, timer, mo, target, colors)
			elseif timer > 180 and timer <= 210
				c_danceribbons(18, timer, mo, target, colors)
			elseif timer > 210
				c_danceribbons(12, timer, mo, target, colors)
			end
			
			summonAura(mo, colors[P_RandomRange(1, #colors)])
			summonAura(target, colors[P_RandomRange(1, #colors)])
		end
		
		if timer == 320
			playSound(mo.battlen, sfx_buff)
			if mo.dancestate <= 6
				buffStat(target, "atk", 50)
			else
				buffStat(target, "atk")
			end
			cureStatus(target)
			
			for i = 1,16
				local dust = P_SpawnMobj(target.x, target.y, target.z, MT_DUMMY)
				dust.angle = ANGLE_90 + ANG1* (22*(i-1))
				dust.state = S_CDUST1
				P_InstaThrust(dust, dust.angle, 30*FRACUNIT)
				dust.color = SKINCOLOR_ORANGE
				dust.scale = FRACUNIT*2
			end
			
			for i = 1, #server.P_BattleStatus[mo.battlen].fighters
				for i = 1, #server.playerlist[mo.battlen]
					if server.playerlist[mo.battlen][i]
						S_FadeMusic(100, MUSICRATE*2, server.playerlist[mo.battlen][i])
					end
				end
			end
		elseif timer == 335
			playSound(mo.battlen, sfx_buff)
			if mo.dancestate <= 6
				buffStat(mo, "atk", 50)
			else
				buffStat(mo, "atk")
			end
			if mo.cacee and mo.cacee.combo
				mo.cacee.taunt = true
			end
			cureStatus(mo)
			
			for i = 1,16
				local dust = P_SpawnMobj(mo.x, mo.y, mo.z, MT_DUMMY)
				dust.angle = ANGLE_90 + ANG1* (22*(i-1))
				dust.state = S_CDUST1
				P_InstaThrust(dust, dust.angle, 30*FRACUNIT)
				dust.color = SKINCOLOR_ORANGE
				dust.scale = FRACUNIT*2
			end
		end

		if timer > 320 and timer <= 350

			if leveltime%2 == 0
				for i = 1,16

					local thok = P_SpawnMobj(target.x+P_RandomRange(-70, 70)*FRACUNIT, target.y+P_RandomRange(-70, 70)*FRACUNIT, target.z+P_RandomRange(0, 50)*FRACUNIT, MT_DUMMY)
					thok.state = S_CDUST1
					thok.momz = P_RandomRange(3, 10)*FRACUNIT
					thok.color = SKINCOLOR_ORANGE
					thok.tics = P_RandomRange(10, 35)
					thok.scale = FRACUNIT*3/2
				end
			end

			for i = 1, 8
				local thok = P_SpawnMobj(target.x+P_RandomRange(-70, 70)*FRACUNIT, target.y+P_RandomRange(-70, 70)*FRACUNIT, target.z+P_RandomRange(0, 50)*FRACUNIT, MT_DUMMY)
				thok.sprite = SPR_SUMN
				thok.frame = F|FF_FULLBRIGHT|TR_TRANS50
				thok.momz = P_RandomRange(6, 16)*FRACUNIT
				thok.color = SKINCOLOR_ORANGE
				thok.tics = P_RandomRange(10, 35)
			end
		end
		
		if timer > 335 and timer <= 365

			if leveltime%2 == 0
				for i = 1,16

					local thok = P_SpawnMobj(mo.x+P_RandomRange(-70, 70)*FRACUNIT, mo.y+P_RandomRange(-70, 70)*FRACUNIT, mo.z+P_RandomRange(0, 50)*FRACUNIT, MT_DUMMY)
					thok.state = S_CDUST1
					thok.momz = P_RandomRange(3, 10)*FRACUNIT
					thok.color = SKINCOLOR_ORANGE
					thok.tics = P_RandomRange(10, 35)
					thok.scale = FRACUNIT*3/2
				end
			end

			for i = 1, 8
				local thok = P_SpawnMobj(mo.x+P_RandomRange(-70, 70)*FRACUNIT, mo.y+P_RandomRange(-70, 70)*FRACUNIT, mo.z+P_RandomRange(0, 50)*FRACUNIT, MT_DUMMY)
				thok.sprite = SPR_SUMN
				thok.frame = F|FF_FULLBRIGHT|TR_TRANS50
				thok.momz = P_RandomRange(6, 16)*FRACUNIT
				thok.color = SKINCOLOR_ORANGE
				thok.tics = P_RandomRange(10, 35)
			end
		elseif timer == 380
			mo.landed = nil
			target.landed = nil
			
			if mo.cacee and mo.cacee.combo
				mo.cacee.roll[#mo.cacee.roll+1] = "Taru Tango"
			end
			
			return true
		end
	end,
}

attackDefs["c-suku samba"] = {
	name = "Suku-Samba",
	type = ATK_SUPPORT,
	costtype = CST_SP,
	cost = 24,
	desc = "Raise yours and a partner's agility by\n1-2 stages. Draws enemy's attention for\n1 turn. Clears status effects.",
	target = TGT_ALLY,
	buff = true,
	norandom = true,
	norogue = true,
	nometronome = true,
	noenemycast = true,
	nocast = 	function(targets, n, mo)
					local target = targets[n]
					if target == mo
						BTL_logMessage(targets[1].battlen, "You can't partner with yourself!")
						return true
					end
				end,
	anim = function(mo, targets, hittargets, timer)
		local target = hittargets[1]
		local btl = server.P_BattleStatus[mo.battlen]
		local cam = btl.cam
		local interval = ANG60
		local avgx, avgy = 0, 0
		for i = 1, #btl.fighters
			avgx = $ + btl.fighters[i].x/FRACUNIT
			avgy = $ + btl.fighters[i].y/FRACUNIT
		end
		avgx = ($/#btl.fighters)*FRACUNIT
		avgy = ($/#btl.fighters)*FRACUNIT
		
		local colors = {SKINCOLOR_GREEN, SKINCOLOR_EMERALD, SKINCOLOR_SEAFOAM, SKINCOLOR_AQUA}
		
		if timer == 1
			for i = 1, #server.P_BattleStatus[mo.battlen].fighters
				for i = 1, #server.playerlist[mo.battlen]
					if server.playerlist[mo.battlen][i]
						S_FadeMusic(0, MUSICRATE*2, server.playerlist[mo.battlen][i])
					end
				end
			end
			
			mo.dancestate = P_RandomRange(1, 7)
		elseif timer == 20
			local an = (R_PointToAngle2(mo.x, mo.y, avgx, avgy) + R_PointToAngle2(target.x, target.y, avgx, avgy))/2
			local space = 25
			mo.angle = R_PointToAngle2(mo.x, mo.y, avgx + space*cos(an + ANGLE_90), avgy + space*sin(an + ANGLE_90))
			target.angle = R_PointToAngle2(target.x, target.y, avgx + space*cos(an - ANGLE_90), avgy + space*sin(an - ANGLE_90))
			ANIM_set(mo, mo.anim_run, true)
			ANIM_set(target, target.anim_run, true)
			mo.flags = $|MF_NOGRAVITY|MF_NOCLIPHEIGHT
			target.flags = $|MF_NOGRAVITY|MF_NOCLIPHEIGHT
			
			P_InstaThrust(mo, mo.angle, R_PointToDist2(mo.x, mo.y, avgx + space*cos(an + ANGLE_90), avgy + space*sin(an + ANGLE_90))/20)
			P_InstaThrust(target, target.angle, R_PointToDist2(target.x, target.y, avgx + space*cos(an - ANGLE_90), avgy + space*cos(an - ANGLE_90))/20)
		elseif timer == 30
			local an = (mo.angle + target.angle)/2
			
			local cx = avgx - 280*cos(an)
			local cy = avgy - 280*sin(an)

			CAM_goto(cam, cx, cy, cam.z, 20*FRACUNIT)
			CAM_angle(cam, an, ANG1*4)
			
			playSound(mo.battlen, dancesounds[P_RandomRange(1, #dancesounds)])
		elseif timer == 40
			ANIM_set(mo, mo.anim_stand, true)
			ANIM_set(target, target.anim_stand, true)
			mo.flags = $ - MF_NOGRAVITY - MF_NOCLIPHEIGHT
			target.flags = $ - MF_NOGRAVITY - MF_NOCLIPHEIGHT
			P_InstaThrust(mo, 0, 0)
			P_InstaThrust(target, 0, 0)
			mo.momz = 3*mo.scale
			
			mo.angle = R_PointToAngle2(mo.x, mo.y, target.x, target.y) - ANGLE_90
			target.angle = mo.angle
		elseif timer == 59
			playSound(mo.battlen, T_CaceeSongs.samba[P_RandomRange(1, #T_CaceeSongs.samba)])
		end
		
		if mo.dancestate <= 6
			if timer == 60
			or timer == 80
			or timer == 220
				local an = mo.angle + ANGLE_90
				P_InstaThrust(mo, an, mo.scale*8)
				P_InstaThrust(target, an, target.scale*8)
				ANIM_set(mo, mo.anim_move, true)
				ANIM_set(target, target.anim_move, true)
				
				mo.angle = $ + interval
				target.angle = $ + interval
			elseif timer == 70 or timer == 90 or timer == 170 or timer == 240
				ANIM_set(mo, mo.anim_stand, true)
				ANIM_set(target, target.anim_stand, true)
				
				mo.angle = $ - interval
				target.angle = $ - interval
			elseif timer == 100 or timer == 180 or timer == 281
				mo.momz = mo.scale*4
				target.momz = target.scale*4
				playSound(mo.battlen, sfx_ngjump)
				
				ANIM_set(mo, mo.anim_aoa_end, true)
				ANIM_set(target, target.anim_aoa_end, true)
			elseif (timer > 100 and timer <= 120)
			or (timer > 180 and timer <= 200)
			or (timer > 240 and timer <= 260)
				mo.angle = $ + ANG1*18
				target.angle = $ + ANG1*18
				
				if timer == 120 or timer == 200
					ANIM_set(mo, mo.anim_stand, true)
					ANIM_set(target, target.anim_stand, true)
					playSound(mo.battlen, sfx_s3k4c)
					
					for m = 0, 1
						local point
						if m then point = mo else point = target end
						
						for i = 1, 4
							local spark = P_SpawnMobj(point.x, point.y, point.z, MT_NIGHTSPARKLE)
							spark.angle = i*ANGLE_22h
							spark.tics = 10
							spark.momz = P_RandomRange(2,6)*FRACUNIT
							P_InstaThrust(spark, P_RandomRange(1,360)*ANG1, FRACUNIT*8)
						end
					end
				end
			elseif (timer > 260 and timer <= 280)
				mo.angle = $ + ANG1*36
				target.angle = $ + ANG1*36
			elseif timer >= 140 and timer <= 160 and timer%10 == 0
				local an = mo.angle - ANGLE_90
				P_InstaThrust(mo, an, mo.scale*8)
				P_InstaThrust(target, an, target.scale*8)
				ANIM_set(mo, mo.anim_move, true)
				ANIM_set(target, target.anim_move, true)
				
				if timer ~= 150
					mo.angle = $ + interval
					target.angle = $ + interval
				else
					mo.angle = $ - interval
					target.angle = $ - interval
				end
			elseif ((timer > 60 and timer < 100) or (timer > 140 and timer < 180)) and timer%5 == 0
				if timer%20 < 10
					mo.angle = $ - interval
					target.angle = $ - interval
				else
					mo.angle = $ + interval
					target.angle = $ + interval
				end
			end
		elseif mo.dancestate == 7
			if timer == 60
			or timer == 80
			or timer == 220
				local an = mo.angle + ANGLE_90
				if timer == 220
					P_InstaThrust(mo, an, mo.scale*10)
				else
					P_InstaThrust(mo, an, mo.scale*8)
				end
				P_InstaThrust(target, an, target.scale*8)
				ANIM_set(mo, mo.anim_move, true)
				ANIM_set(target, target.anim_move, true)
				
				mo.angle = $ + interval
				target.angle = $ + interval
			elseif timer == 230
				target.momz = target.scale*4
				P_InstaThrust(target, 0, 0)
			elseif timer == 250
				P_InstaThrust(mo, mo.angle - ANGLE_90, mo.scale*2)
				ANIM_set(mo, mo.anim_hurt)
				P_InstaThrust(target, target.angle + ANGLE_90, mo.scale*4)
				
				if target.skin ~= "cacee"
					target.momz = target.scale*8
					playSound(mo.battlen, sfx_spkdth)
				else
					playSound(mo.battlen, sfx_s3k7b)
				end
				ANIM_set(target, target.anim_hurt, true)
			elseif timer == 270
				ANIM_set(mo, mo.anim_stand)
				mo.angle = R_PointToAngle2(mo.x, mo.y, target.x, target.y)
			elseif timer == 280
				local tear = P_SpawnMobj(mo.x - 10*cos(cam.angle), mo.y - 10*sin(cam.angle), mo.z + mo.height, MT_DUMMY)
				tear.state = S_CETEAR1
				playSound(mo.battlen, sfx_ceoops)
			elseif timer == 70 or timer == 90 or timer == 170
				ANIM_set(mo, mo.anim_stand, true)
				ANIM_set(target, target.anim_stand, true)
				
				mo.angle = $ - interval
				target.angle = $ - interval
			elseif timer == 100 or timer == 180
				mo.momz = mo.scale*4
				target.momz = target.scale*4
				playSound(mo.battlen, sfx_ngjump)
				
				ANIM_set(mo, mo.anim_aoa_end, true)
				ANIM_set(target, target.anim_aoa_end, true)
			elseif (timer > 100 and timer <= 120)
			or (timer > 180 and timer <= 200)
				mo.angle = $ + ANG1*18
				target.angle = $ + ANG1*18
				
				if timer == 120 or timer == 200
					ANIM_set(mo, mo.anim_stand, true)
					ANIM_set(target, target.anim_stand, true)
					playSound(mo.battlen, sfx_s3k4c)
					
					for m = 0, 1
						local point
						if m then point = mo else point = target end
						
						for i = 1, 4
							local spark = P_SpawnMobj(point.x, point.y, point.z, MT_NIGHTSPARKLE)
							spark.angle = i*ANGLE_22h
							spark.tics = 10
							spark.momz = P_RandomRange(2,6)*FRACUNIT
							P_InstaThrust(spark, P_RandomRange(1,360)*ANG1, FRACUNIT*8)
						end
					end
				end
			elseif timer >= 140 and timer <= 160 and timer%10 == 0
				local an = mo.angle - ANGLE_90
				P_InstaThrust(mo, an, mo.scale*8)
				P_InstaThrust(target, an, target.scale*8)
				ANIM_set(mo, mo.anim_move, true)
				ANIM_set(target, target.anim_move, true)
				
				if timer ~= 150
					mo.angle = $ + interval
					target.angle = $ + interval
				else
					mo.angle = $ - interval
					target.angle = $ - interval
				end
			elseif ((timer > 60 and timer < 100) or (timer > 140 and timer < 180)) and timer%5 == 0
				if timer%20 < 10
					mo.angle = $ - interval
					target.angle = $ - interval
				else
					mo.angle = $ + interval
					target.angle = $ + interval
				end
			end
		end
		
		if timer == 300
			if mo.dancestate <= 6
				ANIM_set(mo, mo.anim_stand_bored, true)
				if target.anim_stand_bored
					ANIM_set(target, target.anim_stand_bored, true)
				else
					ANIM_set(target, target.anim_stand, true)
				end
			
				playSound(mo.battlen, sfx_s3k4c)
				playSound(mo.battlen, sfx_cethmp)
		
				for m = 0, 1
					local point
					if m then point = mo else point = target end
					
					for i = 1, 8
						local spark = P_SpawnMobj(point.x, point.y, point.z, MT_NIGHTSPARKLE)
						spark.angle = i*ANGLE_22h
						spark.tics = 10
						spark.momz = P_RandomRange(2,6)*FRACUNIT
						P_InstaThrust(spark, P_RandomRange(1,360)*ANG1, FRACUNIT*8)
					end
				end
			end
			
			playSound(mo.battlen, sfx_buff)
			if mo.dancestate <= 6
				buffStat(target, "agi", 50)
			else
				buffStat(target, "agi")
			end
			cureStatus(target)
			for i = 1,16
				local dust = P_SpawnMobj(target.x, target.y, target.z, MT_DUMMY)
				dust.angle = ANGLE_90 + ANG1* (22*(i-1))
				dust.state = S_CDUST1
				P_InstaThrust(dust, dust.angle, 30*FRACUNIT)
				dust.color = SKINCOLOR_GREEN
				dust.scale = FRACUNIT*2
			end
			
			if mo.dancestate <= 6
				local firework = P_SpawnMobj(avgx, avgy, mo.z, MT_DUMMY)
				firework.state = S_DFRWORK_1
				firework.cam = cam
				firework.source = mo
				firework.momz = 10*FRACUNIT
			end
			
			for i = 1, #server.P_BattleStatus[mo.battlen].fighters
				for i = 1, #server.playerlist[mo.battlen]
					if server.playerlist[mo.battlen][i]
						S_FadeMusic(100, MUSICRATE*2, server.playerlist[mo.battlen][i])
					end
				end
			end
		elseif timer == 315
			playSound(mo.battlen, sfx_buff)
			if mo.dancestate <= 6
				buffStat(mo, "agi", 50)
			else
				buffStat(mo, "agi")
			end
			if mo.cacee and mo.cacee.combo
				mo.cacee.taunt = true
			end
			
			cureStatus(mo)
			for i = 1,16
				local dust = P_SpawnMobj(mo.x, mo.y, mo.z, MT_DUMMY)
				dust.angle = ANGLE_90 + ANG1* (22*(i-1))
				dust.state = S_CDUST1
				P_InstaThrust(dust, dust.angle, 30*FRACUNIT)
				dust.color = SKINCOLOR_GREEN
				dust.scale = FRACUNIT*2
			end
		end
		
		if timer >= 30 and timer < 380
			for i = 1, #mo.enemies
				local m = mo.enemies[i]
				if not m or not m.valid
					continue
				end
				
				m.frame = $|TR_TRANS70
			end
		end
		
		if timer >= 70 and timer <= 290
			if timer <= 150
				c_danceribbons(30, timer, mo, target, colors)
			elseif timer > 150 and timer <= 180
				c_danceribbons(24, timer, mo, target, colors)
			elseif timer > 180 and timer <= 210
				c_danceribbons(18, timer, mo, target, colors)
			elseif timer > 210
				c_danceribbons(12, timer, mo, target, colors)
			end
			
			summonAura(mo, colors[P_RandomRange(1, #colors)])
			summonAura(target, colors[P_RandomRange(1, #colors)])
		end

		if timer > 300 and timer <= 330

			if leveltime%2 == 0
				for i = 1,16

					local thok = P_SpawnMobj(target.x+P_RandomRange(-70, 70)*FRACUNIT, target.y+P_RandomRange(-70, 70)*FRACUNIT, target.z+P_RandomRange(0, 50)*FRACUNIT, MT_DUMMY)
					thok.state = S_CDUST1
					thok.momz = P_RandomRange(3, 10)*FRACUNIT
					thok.color = SKINCOLOR_GREEN
					thok.tics = P_RandomRange(10, 35)
					thok.scale = FRACUNIT*3/2
				end
			end

			local thok = P_SpawnMobj(target.x+P_RandomRange(-70, 70)*FRACUNIT, target.y+P_RandomRange(-70, 70)*FRACUNIT, target.z+P_RandomRange(0, 50)*FRACUNIT, MT_DUMMY)
			thok.sprite = SPR_SUMN
			thok.frame = F|FF_FULLBRIGHT|TR_TRANS50
			thok.momz = P_RandomRange(6, 16)*FRACUNIT
			thok.color = SKINCOLOR_GREEN
			thok.tics = P_RandomRange(10, 35)
		end
		
		if timer > 315 and timer <= 345

			if leveltime%2 == 0
				for i = 1,16

					local thok = P_SpawnMobj(mo.x+P_RandomRange(-70, 70)*FRACUNIT, mo.y+P_RandomRange(-70, 70)*FRACUNIT, mo.z+P_RandomRange(0, 50)*FRACUNIT, MT_DUMMY)
					thok.state = S_CDUST1
					thok.momz = P_RandomRange(3, 10)*FRACUNIT
					thok.color = SKINCOLOR_GREEN
					thok.tics = P_RandomRange(10, 35)
					thok.scale = FRACUNIT*3/2
				end
			end

			local thok = P_SpawnMobj(mo.x+P_RandomRange(-70, 70)*FRACUNIT, mo.y+P_RandomRange(-70, 70)*FRACUNIT, mo.z+P_RandomRange(0, 50)*FRACUNIT, MT_DUMMY)
			thok.sprite = SPR_SUMN
			thok.frame = F|FF_FULLBRIGHT|TR_TRANS50
			thok.momz = P_RandomRange(6, 16)*FRACUNIT
			thok.color = SKINCOLOR_GREEN
			thok.tics = P_RandomRange(10, 35)
		elseif timer == 380
			mo.dancestate = nil
			
			if mo.cacee and mo.cacee.combo
				mo.cacee.roll[#mo.cacee.roll+1] = "Suku Samba"
			end
			
			return true
		end
	end,
}

attackDefs["c-criminal charisma 1"] = {
	name = "Criminal Charisma",
	type = ATK_PASSIVE,
	costtype = CST_SP,
	cost = 0,
	norandom = true,
	norogue = true,
	nometronome = true,
	noenemycast = true,
	desc = "Enables the use of combo attacks.\nDodging increases strength and\nagility. (2 stack cap.)",
	target = TGT_ENEMY,
	anim = function(mo, targets, hittargets, timer)
		return true
	end,
}

attackDefs["c-criminal charisma 2"] = {
	name = "Criminal Charisma II",
	type = ATK_PASSIVE,
	costtype = CST_SP,
	cost = 0,
	norandom = true,
	norogue = true,
	nometronome = true,
	noenemycast = true,
	desc = "Enables further combo attacks.\nDodging increases strength and\nagility. (3 stack cap.)",
	target = TGT_ENEMY,
	anim = function(mo, targets, hittargets, timer)
		return true
	end,
}

attackDefs["c-criminal charisma 3"] = {
	name = "Criminal Charisma III",
	type = ATK_PASSIVE,
	costtype = CST_SP,
	cost = 0,
	norandom = true,
	norogue = true,
	nometronome = true,
	noenemycast = true,
	desc = "Enables even further combo attacks.\nDodging increases strength and\nagility. (4 stack cap.)",
	target = TGT_ENEMY,
	anim = function(mo, targets, hittargets, timer)
		return true
	end,
}

attackDefs["c-criminal charisma 4"] = {
	name = "Criminal Charisma IV",
	type = ATK_PASSIVE,
	costtype = CST_SP,
	cost = 0,
	norandom = true,
	norogue = true,
	nometronome = true,
	noenemycast = true,
	desc = "Enables all combo attacks.\Dodging increases strength and\nagility. (5 stack cap.)",
	target = TGT_ENEMY,
	anim = function(mo, targets, hittargets, timer)
		return true
	end,
}

attackDefs["c-tough thorns"] = {
	name = "Tough Thorns",
	type = ATK_PASSIVE,
	costtype = CST_SP,
	cost = 0,
	norandom = true,
	norogue = true,
	nometronome = true,
	noenemycast = true,
	desc = "Thorns damage is boosted\nby 10%.",
	target = TGT_ENEMY,
	anim = function(mo, targets, hittargets, timer)
		return true
	end,
}

attackDefs["c-hooked thorns"] = {
	name = "Hooked Thorns",
	type = ATK_PASSIVE,
	costtype = CST_SP,
	cost = 0,
	norandom = true,
	norogue = true,
	nometronome = true,
	noenemycast = true,
	desc = "Thorns damage is boosted\nby 15%.",
	target = TGT_ENEMY,
	anim = function(mo, targets, hittargets, timer)
		return true
	end,
}

attackDefs["c-iron thorns"] = {
	name = "Iron Thorns",
	type = ATK_PASSIVE,
	costtype = CST_SP,
	cost = 0,
	norandom = true,
	norogue = true,
	nometronome = true,
	noenemycast = true,
	desc = "Thorns damage is boosted\nby 20%.",
	target = TGT_ENEMY,
	anim = function(mo, targets, hittargets, timer)
		return true
	end,
}

attackDefs["c-shatter"] = {
	name = "Shatter",
	type = ATK_SUPPORT,
	costtype = CST_SP,
	cost = 15,
	norandom = true,
	norogue = true,
	nometronome = true,
	noenemycast = true,
	desc = "Lower all enemies' Strike \nresistanceto average \nfor 3 turns.",
	target = TGT_ALLENEMIES,
	debuff = true,

	anim = function(mo, targets, hittargets, timer)

		for i = 1, #hittargets
			local target = hittargets[i]

			local time = timer - (i-1)*6

			if time == 20
				playSound(mo.battlen, sfx_debuff)
				local orb = P_SpawnMobj(target.x, target.y, target.z, MT_DUMMY)
				orb.sprite = SPR_DBUF
				orb.frame = A|TR_TRANS30
				orb.scale = FRACUNIT*2
				orb.scalespeed = FRACUNIT/32
				orb.destscale = FRACUNIT/6
				orb.tics = 2*TICRATE-15
				orb.color = SKINCOLOR_RED

			elseif time == 5+2*TICRATE
				buffStat(target, ATK_STRIKE, -1)	-- negative values lower a stat
				playSound(mo.battlen, sfx_bufu6)
				for i = 1, 64
					local m = P_SpawnMobj(target.x, target.y, target.z, MT_DUMMY)
					m.sprite = SPR_THOK
					m.frame = A
					m.tics = TICRATE
					m.fuse = TICRATE
					m.destscale = 1
					m.color = SKINCOLOR_ORANGE
					m.flags = MF_NOCLIPTHING|MF_NOCLIPHEIGHT
					m.momx = P_RandomRange(-64, 64)*FRACUNIT
					m.momy = P_RandomRange(-64, 64)*FRACUNIT
					m.momz = P_RandomRange(0, 64)*FRACUNIT
				end
			end
		end

		if timer == TICRATE*3 + (#hittargets-1)
			return true
		end
	end,
}

attackDefs["sound test"] = {
	name = "Sound Test",
	type = ATK_SUPPORT,
	costtype = CST_SP,
	cost = 15,
	norandom = true,
	norogue = true,
	nometronome = true,
	noenemycast = true,
	desc = "because reasons.",
	target = TGT_ALLY,

	anim = function(mo, targets, hittargets, timer)
		
		local m = charStats["cacee"]
		
		local banks = {m.vfx_summon, m.vfx_skill, m.vfx_item, m.vfx_hurt, m.vfx_hurtx, 
		m.vfx_die, m.vfx_heal, m.vfx_healself, m.vfx_kill, m.vfx_1more,
		m.vfx_crit, m.vfx_aoaask, m.vfx_aoado, m.vfx_aoarelent, m.vfx_miss, m.vfx_dodge, m.vfx_win, m.vfx_levelup}

		local sounds = {}
		
		for i = 1, #banks
			for j = 1, #banks[i]
				sounds[#sounds+1] = banks[i][j]
			end
		end
		
		if timer%20 == 0
			print(sounds[(timer/20)])
			if not _G[sounds[(timer/20)]]
				print("Error found at " + sounds[(timer/20)])
			end
			playSound(mo.battlen, _G[sounds[(timer/20)]])
		end
		
		if timer == 20*(#sounds+1)
			print("Done.")
			return true
		end
	end,
}

personaList["ca-matador"] = {
	-- GENERAL
	name = "Matador",
	arcana = ARCANA_CHARIOT,

	-- STATS (at level 10. so we can have some precision, y'see)

	sprite = SPR_MATA,
	anim_idle = 	{SPR_MATA, A, B, C, D, E, F, 4},
	anim_atk = 		{SPR_MATA, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, X, X, X, X, 2},
	startframe = 0,

	strength = 10,
	magic = 7,
	endurance = 6,
	luck = 4,
	agility = 12,
	weak = bionis and ATK_WIND|ATK_POISON or ATK_WIND,
	resist = bionis and ATK_FIRE|ATK_STRIKE|ATK_EARTH or ATK_FIRE|ATK_STRIKE,
	drain = bionis and ATK_WATER or 0,
	skills = {
				
				//{"c-double rush", 1}, {"c-desert fury", 1}, {"c-desert torment", 1}, {"c-felona finale", 1},
				//{"c-rising upper", 1}, {"c-rising sun", 1}, {"c-la revolucion", 1},
				//{"c-bullet fist", 1}, {"c-bullet feast", 1}, {"c-bandita rebellion", 1},
				//{"c-suku samba", 1}, {"c-taru tango", 1}, {"c-detoxify", 1}, {"c-quick step", 1},
				//{"c-bandita heat", 1}, {"c-bandita heat 2", 1},
				
				
				{"lunge", 1}, {"c-double rush", 4}, {"tarukaja", 7}, {"sukukaja", 8},
				{"c-criminal charisma 1", 12}, {"c-bandita heat", 16},
				{"kill rush", 21}, {"c-tough thorns", 24, "kill rush"}, {"c-rising upper", 26},
				{"c-bullet fist", 28, "lunge"}, {"c-suku samba", 32, "sukukaja"},

				{"hard knuckle", 35, "c-tough thorns"}, {"c-hooked thorns", 38, "hard knuckle"},
				{"swift strike", 40, "c-hooked thorns"},
				{"c-criminal charisma 2", 42, "c-criminal charisma 1"}, {"c-taru tango", 45, "tarukaja"},
				{"c-bandita heat 2", 48, "c-bandita heat"}, {"c-shatter", 49, "c-suku samba"},

				{"c-quick step", 53, "c-shatter"},
				{"iron fist", 55, "c-bullet fist"}, {"c-criminal charisma 3", 57, "c-criminal charisma 2"},
				{"c-detoxify", 59, "c-taru tango"}, {"c-iron thorns", 61, "iron fist"}, {"gigantic fist", 63, "swift strike"},
				{"masukukaja", 65, "c-quick step"}, {"c-criminal charisma 4", 68, "c-criminal charisma 3"},
				{"megaton raid", 72, "gigantic fist"}, {"god hand", 77, "megaton raid"},
				{"c-quick step", 80, "c-detoxify"}
		},
	--skills = hacklist,
}