-- Persona Support --
if not srb2p return end

-- Stats
charStats["morshu"] = {
	name = "Morshu",
	basehp = 68,
	basesp = 45,
	persona = "rubyn",
	melee_natk = "morshu_atk1",
	melee_satk = "morshu_atk2",
	supercolor_start = SKINCOLOR_SUPERGOLD1,
	atk = 35,
	acc = 85,
	crit = 7,
	wep = "hands_01",
	weptype = WPT_PSYGLOVES,
	anim_stand = {SPR_PLAY, A, 8, "SPR2_STND"},
	anim_stand_hurt = {SPR_PLAY, A, 1, "SPR2_STND"},
	anim_stand_bored = {SPR_PLAY, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, 8, "SPR2_WAIT"},
	anim_guard = {SPR_PLAY, D, 1, "SPR2_RUN_"},
	anim_move = {SPR_PLAY, A, B, C, D, E, F, 2, "SPR2_WALK"},
	anim_run = {SPR_PLAY, A, B, C, D, E, F, 2, "SPR2_RUN_"},
	anim_atk = {SPR_PLAY, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, 2, "SPR2_ROLL"},
	anim_aoa_end = {SPR_PLAY, Z, Y, X, W, V, U, T, S, R, Q, P, O, N, M, L, K, J, I, H, G, F, E, D, C, B, A, 2, "SPR2_ROLL"},
	anim_hurt = {SPR_PLAY, A, 35, "SPR2_PAIN"},
	anim_getdown = {SPR_PLAY, C, 1, "SPR2_PAIN"},
	anim_downloop = {SPR_PLAY, C, 1, "SPR2_PAIN"},
	anim_getup = {SPR_PLAY, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, 1, "SPR2_ROLL"},
	anim_death = {SPR_PLAY, A, 30, "SPR2_DEAD"},
	anim_revive = {SPR_PLAY, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, 1, "SPR2_ROLL"},
	anim_evoker = {SPR_PLAY, Q, 1, "SPR2_DASH"},
	vfx_summon = {"sfx_morsum"},
    vfx_skill = {"sfx_morskl"},
    vfx_item = {"sfx_morsum", "sfx_morskl", "sfx_morcrt"},
    vfx_die = {"sfx_morhel"},
    vfx_heal = {"sfx_morhel"},
    vfx_healself = {"sfx_morhsf"},
    vfx_kill = {"sfx_morcrt"},
    vfx_1more = {"sfx_morhsf"},
    vfx_crit = {"sfx_morcrt"},
    vfx_aoaask = {"sfx_morsum"},
    vfx_aoado = {"sfx_moraoa"},
    vfx_aoarelent = {"sfx_morskl"},
    vfx_miss = {"sfx_morhel"},
    vfx_dodge = {"sfx_mordod"},
    vfx_win = {"sfx_morwin"},
    vfx_levelup = {"sfx_morcrt", "sfx_morhsf"},
	icon = "ICO_MORS",
	hudbust = "H_MORBAR",
	hudaoa = "H_MORAOA",
	aoa_quote = "Come back when \nyou're a little \nMMMMM... skilled!",
	hudcutin = "MORS_A",
	tip = "A utility character with barriers, Patra, and Recarm skills. Use lamp oil to make way for his bombs which can dish out a lot of damage. His melee attack can also replenish his SP and give you more Emerald Power, but it's slow.",
}

-- Persona
personaList["rubyn"] = {
	name = "Rubyn",
	arcana = ARCANA_FORTUNE,
	sprite = SPR_RUBY,
	startframe = 0,
	anim_idle = {SPR_RUBY, A, 10},
	anim_atk = {SPR_RUBY, B, C, D, E, E, E, E, 2},
	strength = 4,
	magic = 10,
	endurance = 9,
	luck = 11,
	agility = 6,
	weak = ATK_CURSE,
	resist = ATK_FIRE|ATK_BLESS,
	skills = {
		{"bomb_1", 1}, {"lamp_oil_1", 4},
		{"rope_1", 6}, {"kouha", 11},
		{"patra", 14}, {"makarakarn", 18},
		{"tetrakarn", 20}, {"recarm", 22},
		
		{"bomb_2", 26, "bomb_1"}, {"lamp_oil_2", 29, "lamp_oil_1"},
		{"rope_2", 32, "rope_1"}, {"kouga", 37, "kouha"},
		{"me patra", 40, "patra"}, {"samarecarm", 45, "recarm"},
		
		{"bomb_3", 48, "bomb_2"}, {"rope_3", 53, "rope_2"},
		{"kougaon", 62, "kouga"}, {"tetraja", 65, "makarakarn"},
		{"trisagion", 69}, {"samsara", 72},
		{"doublakarn", 85, "tetrakarn"},
	},
}

-- Normal Melee Attack
attackDefs["morshu_atk1"] = {
	name = "Pickpocket",
	type = ATK_PIERCE,
	power = 35,
	accuracy = 85,
	critical = 7, -- was 7
	target = TGT_ENEMY,
	cost = CST_HP,
	cost = 0,
	desc = "A fierce spin kick\n that robs enemies.",
	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]
				local atarget = hittargets[1]
				if timer == 1
					ANIM_set(mo, mo.anim_run, true)
					mo.reachedtarget = false	-- yeah we can use variables here that you like it or not :^)

					local cx = target.x + 168*cos(target.angle + ANG1*20)
					local cy = target.y + 168*sin(target.angle + ANG1*20)
					CAM_goto(server.P_BattleStatus[mo.battlen].cam, cx, cy, target.z + FRACUNIT*30, 70*FRACUNIT)
					CAM_angle(server.P_BattleStatus[mo.battlen].cam, R_PointToAngle2(cx, cy, target.x, target.y))
					S_StartSound(mo, sfx_zoom)
				end

				if not mo.reachedtarget
					mo.angle = R_PointToAngle2(mo.x, mo.y, target.x, target.y)
					P_InstaThrust(mo, mo.angle, FRACUNIT*36)
					if R_PointToDist2(mo.x, mo.y, target.x, target.y) < FRACUNIT*36
						ANIM_set(mo, mo.anim_atk, true)
						P_StartQuake(FRACUNIT*8, 4)
						mo.reachedtarget = true
						P_InstaThrust(mo, mo.angle, -FRACUNIT*6)
						mo.momz = 7*FRACUNIT
						playSound(mo.battlen, sfx_phys)
						for i = 1, 2
							createSplat(mo)
						end
					end
				else

					if P_IsObjectOnGround(mo)
					and not mo.momz
					and not mo.damagetime
						mo.damagetime = 1
						mo.momz = FRACUNIT
						P_InstaThrust(mo, mo.angle, FRACUNIT*90)
						S_StartSound(mo, sfx_spin)

					elseif mo.damagetime
						local trail = P_SpawnMobj(mo.x, mo.y, mo.z, MT_DUMMY)
						trail.color = mo.color
						mo.damagetime = $+1
						if mo.damagetime == 2
							damageObject(atarget)
							damageSP(atarget, 10)
							P_StartQuake(FRACUNIT*7, 4)
							playSound(mo.battlen, sfx_phys)
							for i = 1, 2
								createSplat(mo)
							end
						end
						if mo.damagetime == 10
						and atarget ~= mo
							mo.atk_attacker = mo
							damageSP(mo, -10)
							playSound(mo.battlen, sfx_heal)
							fillEmeraldGauge(mo, 20, true)
							playSound(mo.battlen, sfx_buff2)
						elseif mo.damagetime == 50
							mo.reachedtarget = nil
							mo.damagetime = nil
							return true
						end
					end
				end
			end,
	critanim = 	function(mo, targets, hittargets, timer)
					local target = targets[1]
					local atarget = hittargets[1]
					if timer == 1
						ANIM_set(mo, mo.anim_run, true)
						mo.reachedtarget = false	-- yeah we can use variables here that you like it or not :^)

						local cx = target.x + 168*cos(target.angle + ANG1*20)
						local cy = target.y + 168*sin(target.angle + ANG1*20)
						CAM_goto(server.P_BattleStatus[mo.battlen].cam, cx, cy, target.z + FRACUNIT*30, 70*FRACUNIT)
						CAM_angle(server.P_BattleStatus[mo.battlen].cam, R_PointToAngle2(cx, cy, target.x, target.y))
						S_StartSound(mo, sfx_zoom)
					end

					if not mo.reachedtarget
						mo.angle = R_PointToAngle2(mo.x, mo.y, target.x, target.y)
						P_InstaThrust(mo, mo.angle, FRACUNIT*36)
						if R_PointToDist2(mo.x, mo.y, target.x, target.y) < FRACUNIT*36
							ANIM_set(mo, mo.anim_atk, true)
							P_StartQuake(FRACUNIT*8, 4)
							mo.reachedtarget = true
							P_InstaThrust(mo, mo.angle, -FRACUNIT*7)
							mo.momz = 8*FRACUNIT
							playSound(mo.battlen, sfx_phys)
							for i = 1, 2
								createSplat(mo)
							end
						end
					else
						if P_IsObjectOnGround(mo)
						and not mo.momz
						and not mo.damagetime
							-- move camera instantly
							local cam = server.P_BattleStatus[mo.battlen].cam

							local cx = mo.x + 128*cos(mo.angle - ANG1*25)
							local cy = mo.y + 128*sin(mo.angle - ANG1*25)
							P_TeleportMove(cam, cx, cy, mo.z + FRACUNIT*16)
							server.P_BattleStatus[mo.battlen].cam.angle = R_PointToAngle2(cam.x, cam.y, mo.x, mo.y)

							-- now make it zoom out a little
							CAM_goto(cam, cam.x-24*cos(cam.angle), cam.y-24*sin(cam.angle), cam.z+FRACUNIT*5, 1*FRACUNIT)

							-- setup sonic
							mo.damagetime = 1
							mo.momx, mo.momy, mo.momz = 0, 0, 0 -- stop momentum, start spindash
							ANIM_set(mo, mo.anim_special1, true)
							S_StartSound(mo, sfx_spndsh)
						elseif mo.damagetime
							mo.damagetime = $+1
							-- rev animation
							if mo.damagetime == 13 or mo.damagetime == 21 or mo.damagetime == 28
								--local revSounds = {sfx_sncsd1, sfx_sncsd2, sfx_sncsd3}

								mo.rev = $ and $+1 or 1
								S_StartSound(mo, sfx_spndsh)
								-- at 3rd rev speed up use the faster spindash anim
								ANIM_set(mo, mo.rev == 3 and mo.anim_special2 or mo.anim_special1, true)
							end
							-- start spindash
							if mo.damagetime >= 35
								if mo.damagetime == 35 -- nyoom
									-- camera
									local cx = target.x + 512*cos(target.angle + ANG1*20)
									local cy = target.y + 512*sin(target.angle + ANG1*20)
									CAM_goto(server.P_BattleStatus[mo.battlen].cam, cx, cy, target.z + FRACUNIT*30, 128*FRACUNIT)
									CAM_angle(server.P_BattleStatus[mo.battlen].cam, R_PointToAngle2(cx, cy, target.x, target.y), ANG1*16)

									-- sonic
									S_StartSound(mo, sfx_zoom)
									P_InstaThrust(mo, mo.angle, FRACUNIT*120)
									ANIM_set(mo, mo.anim_atk, true)
								else
									local trail = P_SpawnMobj(mo.x, mo.y, mo.z, MT_DUMMY)
									trail.color = mo.color
									if mo.damagetime == 36
										damageObject(atarget)
										damageSP(atarget, 20)
										P_SetObjectMomZ(atarget, 5*FRACUNIT)
										P_StartQuake(FRACUNIT*12, 7)
										playSound(mo.battlen, sfx_phys)
										for i = 1, 4
											createSplat(mo)
										end
									end
									if mo.damagetime == 40
									and atarget ~= mo
										mo.atk_attacker = mo
										damageSP(mo, -20)
										playSound(mo.battlen, sfx_heal)
										fillEmeraldGauge(mo, 40, true)
										playSound(mo.battlen, sfx_buff2)
									elseif mo.damagetime == 85
										mo.rev = nil
										mo.reachedtarget = nil
										mo.damagetime = nil
										return true
									end
								end
							end
						end
					end
				end,
}

-- Custom Skills
attackDefs["bomb_1"] = {
	name = "Bomb I",
	type = ATK_FIRE,
	power = 140,
	accuracy = 90,
	costtype = CST_SP,
	cost = 20,
	status = COND_BURN,
	statuschance = 5,
	desc = "50 points of fire dmg \nto all enemies. \nMay inflict burn.",
	target = TGT_ALLENEMIES,
	anim = function(mo, targets, hittargets, timer)
		if timer == 1
			playSound(mo.battlen, sfx_bmbitm)
		end
		for k,e in ipairs(hittargets)
			local target = e
			local time = timer - 10*(k-1)
			if time == 10
			or time == 14
				local boom = P_SpawnMobj(target.x+P_RandomRange(-20, 20)*FRACUNIT, target.y+P_RandomRange(-20, 20)*FRACUNIT, target.z+P_RandomRange(-20, 20)*FRACUNIT, MT_BOSSEXPLODE)
				boom.scale = FRACUNIT*3
				boom.state = S_QUICKBOOM1
				playSound(mo.battlen, sfx_fire1)
			elseif time == 30
				local boom = P_SpawnMobj(target.x, target.y, target.z+20*FRACUNIT, MT_BOSSEXPLODE)
				boom.scale = FRACUNIT*4
				boom.state = S_PFIRE1
				playSound(mo.battlen, sfx_fire2)
				playSound(mo.battlen, sfx_fire1)
				damageObject(target, 50)

				localquake(mo.battlen, FRACUNIT*32, 8)

				for i = 1, 8
					local smoke = P_SpawnMobj(boom.x, boom.y, boom.z, MT_SMOKE)
					smoke.scale = FRACUNIT*6
					smoke.momx = P_RandomRange(-5, 5)*FRACUNIT
					smoke.momy = P_RandomRange(-5, 5)*FRACUNIT
					smoke.momz = P_RandomRange(3, 6)*FRACUNIT
				end

				local sm = P_SpawnMobj(target.x, target.y, target.z, MT_SMOLDERING)
				sm.fuse = TICRATE/2
				sm.scale = target.scale*3/2
			end
		end

		if timer == 71 + (#targets-1)*10
			return true
		end
	end,
}

attackDefs["lamp_oil_1"] = {
	name = "Lamp Oil I",
	type = ATK_SUPPORT,
	costtype = CST_SP,
	cost = 5,
	desc = "Lower an enemy's Fire \nresistance to average \nfor 3 turns.",
	target = TGT_ENEMY,
	debuff = true,

	anim = function(mo, targets, hittargets, timer)
		if timer == 1
			playSound(mo.battlen, sfx_lmpoil)
		end
		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_LIME

			elseif time == 5+2*TICRATE
				buffStat(target, ATK_FIRE, -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_LIME
					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["rope_1"] = {
	name = "Rope I",
	type = ATK_BLESS,
	power = 100,
	accuracy = 25,
	costtype = CST_SP,
	instakill = true,	-- the enemy is instantly killed without its health being displayed
	luckbased = true,	-- use luck instead of agility
	cost = 10,
	desc = "YEET that enemy outta \nthere! (Low chance)",
	target = TGT_ENEMY,
	anim = function(mo, targets, hittargets, timer)
		if timer == 1
			playSound(mo.battlen, sfx_ropitm)
		end
		local target = hittargets[1]

		if timer == 10
			local x = target.x + 48*cos(target.angle)
			local y = target.y + 48*sin(target.angle)
			playSound(mo.battlen, sfx_ropego)
			target.mudo_dum = P_SpawnMobj(x, y, target.z + FRACUNIT*32, MT_DUMMY)
			target.mudo_dum.state = S_INVISIBLE
			target.mudo_dum.tics = -1
			target.mudo_dum.angle = target.angle

		elseif timer == 25

			local m = P_SpawnMobj(target.mudo_dum.x, target.mudo_dum.y, target.z + FRACUNIT*32, MT_DUMMY)
			m.sprite = SPR_ROPE
			m.frame = A|FF_PAPERSPRITE
			m.angle = target.angle + ANG1*90
			m.tics = -1
			m.scale = FRACUNIT*3/2
			target.mudo = m

			m = P_SpawnMobj(target.mudo_dum.x, target.mudo_dum.y, target.z + FRACUNIT*32, MT_DUMMY)
			m.sprite = SPR_ROPE
			m.frame = A|FF_PAPERSPRITE
			m.angle = mo.angle + ANG1*90
			m.destscale = FRACUNIT*8
			m.scalespeed = FRACUNIT/6
			m.tics = 8

			m = P_SpawnMobj(target.mudo_dum.x, target.mudo_dum.y, target.z + FRACUNIT*32, MT_DUMMY)
			m.sprite = SPR_ROPE
			m.frame = B|FF_TRANS30|FF_PAPERSPRITE
			m.angle = mo.angle + ANG1*90
			m.destscale = FRACUNIT*8
			m.scalespeed = FRACUNIT/6
			m.tics = 8

		elseif timer == 50
			target.mudo.destscale = 1
			target.mudo.tics = 20
		elseif timer == 70
			damageObject(target)
			target.mudo = nil
			P_RemoveMobj(target.mudo_dum)
			target.mudo_dum = nil
		elseif timer == 110
			return true
		end
	end,
}

attackDefs["bomb_2"] = {
	name = "Bomb II",
	type = ATK_FIRE,
	power = 140,
	accuracy = 90,
	costtype = CST_SP,
	cost = 20,
	status = COND_BURN,
	statuschance = 10,
	desc = "100 points of fire dmg \nto all enemies. \nMay inflict burn.",
	target = TGT_ALLENEMIES,
	anim = function(mo, targets, hittargets, timer)
		if timer == 1
			playSound(mo.battlen, sfx_bmbitm)
		end
		for k,e in ipairs(hittargets)
			local target = e
			local time = timer - 10*(k-1)
			if time == 10
			or time == 14
				local boom = P_SpawnMobj(target.x+P_RandomRange(-20, 20)*FRACUNIT, target.y+P_RandomRange(-20, 20)*FRACUNIT, target.z+P_RandomRange(-20, 20)*FRACUNIT, MT_BOSSEXPLODE)
				boom.scale = FRACUNIT*3
				boom.state = S_QUICKBOOM1
				playSound(mo.battlen, sfx_fire1)
			elseif time == 30
				local boom = P_SpawnMobj(target.x, target.y, target.z+20*FRACUNIT, MT_BOSSEXPLODE)
				boom.scale = FRACUNIT*4
				boom.state = S_PFIRE1
				playSound(mo.battlen, sfx_fire2)
				playSound(mo.battlen, sfx_fire1)
				damageObject(target, 100)

				localquake(mo.battlen, FRACUNIT*32, 8)

				for i = 1, 8
					local smoke = P_SpawnMobj(boom.x, boom.y, boom.z, MT_SMOKE)
					smoke.scale = FRACUNIT*6
					smoke.momx = P_RandomRange(-5, 5)*FRACUNIT
					smoke.momy = P_RandomRange(-5, 5)*FRACUNIT
					smoke.momz = P_RandomRange(3, 6)*FRACUNIT
				end

				local sm = P_SpawnMobj(target.x, target.y, target.z, MT_SMOLDERING)
				sm.fuse = TICRATE/2
				sm.scale = target.scale*3/2
			end
		end

		if timer == 71 + (#targets-1)*10
			return true
		end
	end,
}

attackDefs["lamp_oil_2"] = {
	name = "Lamp Oil II",
	type = ATK_SUPPORT,
	costtype = CST_SP,
	cost = 5,
	desc = "Lower all enemies's Fire \nresistance to average \nfor 3 turns.",
	target = TGT_ALLENEMIES,
	debuff = true,

	anim = function(mo, targets, hittargets, timer)
		if timer == 1
			playSound(mo.battlen, sfx_lmpoil)
		end
		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_LIME

			elseif time == 5+2*TICRATE
				buffStat(target, ATK_FIRE, -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_LIME
					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["rope_2"] = {
	name = "Rope II",
	type = ATK_BLESS,
	power = 100,
	accuracy = 50,
	costtype = CST_SP,
	instakill = true,	-- the enemy is instantly killed without its health being displayed
	luckbased = true,	-- use luck instead of agility
	cost = 10,
	desc = "YEET that enemy outta \nthere! (Medium chance)",
	target = TGT_ENEMY,
	anim = function(mo, targets, hittargets, timer)
		if timer == 1
			playSound(mo.battlen, sfx_ropitm)
		end
		local target = hittargets[1]

		if timer == 10
			local x = target.x + 48*cos(target.angle)
			local y = target.y + 48*sin(target.angle)
			playSound(mo.battlen, sfx_ropego)
			target.mudo_dum = P_SpawnMobj(x, y, target.z + FRACUNIT*32, MT_DUMMY)
			target.mudo_dum.state = S_INVISIBLE
			target.mudo_dum.tics = -1
			target.mudo_dum.angle = target.angle

		elseif timer == 25

			local m = P_SpawnMobj(target.mudo_dum.x, target.mudo_dum.y, target.z + FRACUNIT*32, MT_DUMMY)
			m.sprite = SPR_ROPE
			m.frame = A|FF_PAPERSPRITE
			m.angle = target.angle + ANG1*90
			m.tics = -1
			m.scale = FRACUNIT*3/2
			target.mudo = m

			m = P_SpawnMobj(target.mudo_dum.x, target.mudo_dum.y, target.z + FRACUNIT*32, MT_DUMMY)
			m.sprite = SPR_ROPE
			m.frame = A|FF_PAPERSPRITE
			m.angle = mo.angle + ANG1*90
			m.destscale = FRACUNIT*8
			m.scalespeed = FRACUNIT/6
			m.tics = 8

			m = P_SpawnMobj(target.mudo_dum.x, target.mudo_dum.y, target.z + FRACUNIT*32, MT_DUMMY)
			m.sprite = SPR_ROPE
			m.frame = B|FF_TRANS30|FF_PAPERSPRITE
			m.angle = mo.angle + ANG1*90
			m.destscale = FRACUNIT*8
			m.scalespeed = FRACUNIT/6
			m.tics = 8

		elseif timer == 50
			target.mudo.destscale = 1
			target.mudo.tics = 20
		elseif timer == 70
			damageObject(target)
			target.mudo = nil
			P_RemoveMobj(target.mudo_dum)
			target.mudo_dum = nil
		elseif timer == 110
			return true
		end
	end,
}

attackDefs["bomb_3"] = {
	name = "Bomb III",
	type = ATK_FIRE,
	power = 140,
	accuracy = 90,
	costtype = CST_SP,
	cost = 20,
	status = COND_BURN,
	statuschance = 20,
	desc = "200 points of fire dmg \nto all enemies. \nMay inflict burn.",
	target = TGT_ALLENEMIES,
	anim = function(mo, targets, hittargets, timer)
		if timer == 1
			playSound(mo.battlen, sfx_bmbitm)
		end
		for k,e in ipairs(hittargets)
			local target = e
			local time = timer - 10*(k-1)
			if time == 10
			or time == 14
				local boom = P_SpawnMobj(target.x+P_RandomRange(-20, 20)*FRACUNIT, target.y+P_RandomRange(-20, 20)*FRACUNIT, target.z+P_RandomRange(-20, 20)*FRACUNIT, MT_BOSSEXPLODE)
				boom.scale = FRACUNIT*3
				boom.state = S_QUICKBOOM1
				playSound(mo.battlen, sfx_fire1)
			elseif time == 30
				local boom = P_SpawnMobj(target.x, target.y, target.z+20*FRACUNIT, MT_BOSSEXPLODE)
				boom.scale = FRACUNIT*4
				boom.state = S_PFIRE1
				playSound(mo.battlen, sfx_fire2)
				playSound(mo.battlen, sfx_fire1)
				damageObject(target, 200)

				localquake(mo.battlen, FRACUNIT*32, 8)

				for i = 1, 8
					local smoke = P_SpawnMobj(boom.x, boom.y, boom.z, MT_SMOKE)
					smoke.scale = FRACUNIT*6
					smoke.momx = P_RandomRange(-5, 5)*FRACUNIT
					smoke.momy = P_RandomRange(-5, 5)*FRACUNIT
					smoke.momz = P_RandomRange(3, 6)*FRACUNIT
				end

				local sm = P_SpawnMobj(target.x, target.y, target.z, MT_SMOLDERING)
				sm.fuse = TICRATE/2
				sm.scale = target.scale*3/2
			end
		end

		if timer == 71 + (#targets-1)*10
			return true
		end
	end,
}

attackDefs["rope_3"] = {
	name = "Rope III",
	type = ATK_BLESS,
	power = 100,
	accuracy = 75,
	costtype = CST_SP,
	instakill = true,	-- the enemy is instantly killed without its health being displayed
	luckbased = true,	-- use luck instead of agility
	cost = 10,
	desc = "YEET that enemy outta \nthere! (High chance)",
	target = TGT_ENEMY,
	anim = function(mo, targets, hittargets, timer)
		if timer == 1
			playSound(mo.battlen, sfx_ropitm)
		end
		local target = hittargets[1]

		if timer == 10
			local x = target.x + 48*cos(target.angle)
			local y = target.y + 48*sin(target.angle)
			playSound(mo.battlen, sfx_ropego)
			target.mudo_dum = P_SpawnMobj(x, y, target.z + FRACUNIT*32, MT_DUMMY)
			target.mudo_dum.state = S_INVISIBLE
			target.mudo_dum.tics = -1
			target.mudo_dum.angle = target.angle

		elseif timer == 25

			local m = P_SpawnMobj(target.mudo_dum.x, target.mudo_dum.y, target.z + FRACUNIT*32, MT_DUMMY)
			m.sprite = SPR_ROPE
			m.frame = A|FF_PAPERSPRITE
			m.angle = target.angle + ANG1*90
			m.tics = -1
			m.scale = FRACUNIT*3/2
			target.mudo = m

			m = P_SpawnMobj(target.mudo_dum.x, target.mudo_dum.y, target.z + FRACUNIT*32, MT_DUMMY)
			m.sprite = SPR_ROPE
			m.frame = A|FF_PAPERSPRITE
			m.angle = mo.angle + ANG1*90
			m.destscale = FRACUNIT*8
			m.scalespeed = FRACUNIT/6
			m.tics = 8

			m = P_SpawnMobj(target.mudo_dum.x, target.mudo_dum.y, target.z + FRACUNIT*32, MT_DUMMY)
			m.sprite = SPR_ROPE
			m.frame = B|FF_TRANS30|FF_PAPERSPRITE
			m.angle = mo.angle + ANG1*90
			m.destscale = FRACUNIT*8
			m.scalespeed = FRACUNIT/6
			m.tics = 8

		elseif timer == 50
			target.mudo.destscale = 1
			target.mudo.tics = 20
		elseif timer == 70
			damageObject(target)
			target.mudo = nil
			P_RemoveMobj(target.mudo_dum)
			target.mudo_dum = nil
		elseif timer == 110
			return true
		end
	end,
}

attackDefs["doublakarn"] = {
	name = "Doublakarn",
	type = ATK_SUPPORT,
	costtype = CST_SP,
	cost = 48,
	target = TGT_ALLALLIES,
	desc = "Give a barrier that repels \nmagic and physical attacks \nto all allies",
	superbuff = true,
	anim = 	function(mo, targets, hittargets, timer)

				for i = 1, #targets
					local target = hittargets[i]
					local t = timer - (i-1)*6

					if t >= 10 and t <= 40
						if leveltime%2 == 0
							local s = P_SpawnMobj(target.x, target.y, target.z, MT_DUMMY)
							s.sprite = SPR_MAGN
							s.tics = 1
						end
					elseif t == 41
						local thok = P_SpawnMobj(target.x, target.y, target.z+5*FRACUNIT, MT_DUMMY)
						thok.state = S_INVISIBLE
						thok.tics = 1
						A_OldRingExplode(thok, MT_SUPERSPARK)
						playSound(mo.battlen, sfx_mirror)

						BTL_logMessage(targets[1].battlen, target.name.." has\na barrier")

						target.makarakarn = true
						target.tetrakarn = true
					end
				end

				if timer == 60 + (#hittargets-1)*6
					return true
				end

			end,

}

-- Super Melee Attack
attackDefs["morshu_atk2"] = {
	name = "Super Pickpocket",
	type = ATK_ALMIGHTY,
	power = 35,
	accuracy = 85,
	critical = 7, -- was 7
	target = TGT_ENEMY,
	cost = CST_HP,
	cost = 0,
	desc = "A fiercer spin kick\n that robs enemies more.",
	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]
				local atarget = hittargets[1]
				if timer == 1
					ANIM_set(mo, mo.anim_run, true)
					mo.reachedtarget = false	-- yeah we can use variables here that you like it or not :^)

					local cx = target.x + 168*cos(target.angle + ANG1*20)
					local cy = target.y + 168*sin(target.angle + ANG1*20)
					CAM_goto(server.P_BattleStatus[mo.battlen].cam, cx, cy, target.z + FRACUNIT*30, 70*FRACUNIT)
					CAM_angle(server.P_BattleStatus[mo.battlen].cam, R_PointToAngle2(cx, cy, target.x, target.y))
					S_StartSound(mo, sfx_zoom)
				end

				if not mo.reachedtarget
					mo.angle = R_PointToAngle2(mo.x, mo.y, target.x, target.y)
					P_InstaThrust(mo, mo.angle, FRACUNIT*36)
					if R_PointToDist2(mo.x, mo.y, target.x, target.y) < FRACUNIT*36
						ANIM_set(mo, mo.anim_atk, true)
						P_StartQuake(FRACUNIT*8, 4)
						mo.reachedtarget = true
						P_InstaThrust(mo, mo.angle, -FRACUNIT*6)
						mo.momz = 7*FRACUNIT
						playSound(mo.battlen, sfx_phys)
						for i = 1, 2
							createSplat(mo)
						end
					end
				else

					if P_IsObjectOnGround(mo)
					and not mo.momz
					and not mo.damagetime
						mo.damagetime = 1
						mo.momz = FRACUNIT
						P_InstaThrust(mo, mo.angle, FRACUNIT*90)
						S_StartSound(mo, sfx_spin)

					elseif mo.damagetime
						local trail = P_SpawnMobj(mo.x, mo.y, mo.z, MT_DUMMY)
						trail.color = mo.color
						mo.damagetime = $+1
						if mo.damagetime == 2
							damageObject(atarget)
							damageSP(atarget, 20)
							P_StartQuake(FRACUNIT*7, 4)
							playSound(mo.battlen, sfx_phys)
							for i = 1, 2
								createSplat(mo)
							end
						end
						if mo.damagetime == 10
						and atarget ~= mo
							mo.atk_attacker = mo
							damageSP(mo, -20)
							playSound(mo.battlen, sfx_heal)
							fillEmeraldGauge(mo, 40, true)
							playSound(mo.battlen, sfx_buff2)
						elseif mo.damagetime == 50
							mo.reachedtarget = nil
							mo.damagetime = nil
							return true
						end
					end
				end
			end,
	critanim = 	function(mo, targets, hittargets, timer)
					local target = targets[1]
					local atarget = hittargets[1]
					if timer == 1
						ANIM_set(mo, mo.anim_run, true)
						mo.reachedtarget = false	-- yeah we can use variables here that you like it or not :^)

						local cx = target.x + 168*cos(target.angle + ANG1*20)
						local cy = target.y + 168*sin(target.angle + ANG1*20)
						CAM_goto(server.P_BattleStatus[mo.battlen].cam, cx, cy, target.z + FRACUNIT*30, 70*FRACUNIT)
						CAM_angle(server.P_BattleStatus[mo.battlen].cam, R_PointToAngle2(cx, cy, target.x, target.y))
						S_StartSound(mo, sfx_zoom)
					end

					if not mo.reachedtarget
						mo.angle = R_PointToAngle2(mo.x, mo.y, target.x, target.y)
						P_InstaThrust(mo, mo.angle, FRACUNIT*36)
						if R_PointToDist2(mo.x, mo.y, target.x, target.y) < FRACUNIT*36
							ANIM_set(mo, mo.anim_atk, true)
							P_StartQuake(FRACUNIT*8, 4)
							mo.reachedtarget = true
							P_InstaThrust(mo, mo.angle, -FRACUNIT*7)
							mo.momz = 8*FRACUNIT
							playSound(mo.battlen, sfx_phys)
							for i = 1, 2
								createSplat(mo)
							end
						end
					else
						if P_IsObjectOnGround(mo)
						and not mo.momz
						and not mo.damagetime
							-- move camera instantly
							local cam = server.P_BattleStatus[mo.battlen].cam

							local cx = mo.x + 128*cos(mo.angle - ANG1*25)
							local cy = mo.y + 128*sin(mo.angle - ANG1*25)
							P_TeleportMove(cam, cx, cy, mo.z + FRACUNIT*16)
							server.P_BattleStatus[mo.battlen].cam.angle = R_PointToAngle2(cam.x, cam.y, mo.x, mo.y)

							-- now make it zoom out a little
							CAM_goto(cam, cam.x-24*cos(cam.angle), cam.y-24*sin(cam.angle), cam.z+FRACUNIT*5, 1*FRACUNIT)

							-- setup sonic
							mo.damagetime = 1
							mo.momx, mo.momy, mo.momz = 0, 0, 0 -- stop momentum, start spindash
							ANIM_set(mo, mo.anim_special1, true)
							S_StartSound(mo, sfx_spndsh)
						elseif mo.damagetime
							mo.damagetime = $+1
							-- rev animation
							if mo.damagetime == 13 or mo.damagetime == 21 or mo.damagetime == 28
								--local revSounds = {sfx_sncsd1, sfx_sncsd2, sfx_sncsd3}

								mo.rev = $ and $+1 or 1
								S_StartSound(mo, sfx_spndsh)
								-- at 3rd rev speed up use the faster spindash anim
								ANIM_set(mo, mo.rev == 3 and mo.anim_special2 or mo.anim_special1, true)
							end
							-- start spindash
							if mo.damagetime >= 35
								if mo.damagetime == 35 -- nyoom
									-- camera
									local cx = target.x + 512*cos(target.angle + ANG1*20)
									local cy = target.y + 512*sin(target.angle + ANG1*20)
									CAM_goto(server.P_BattleStatus[mo.battlen].cam, cx, cy, target.z + FRACUNIT*30, 128*FRACUNIT)
									CAM_angle(server.P_BattleStatus[mo.battlen].cam, R_PointToAngle2(cx, cy, target.x, target.y), ANG1*16)

									-- sonic
									S_StartSound(mo, sfx_zoom)
									P_InstaThrust(mo, mo.angle, FRACUNIT*120)
									ANIM_set(mo, mo.anim_atk, true)
								else
									local trail = P_SpawnMobj(mo.x, mo.y, mo.z, MT_DUMMY)
									trail.color = mo.color
									if mo.damagetime == 36
										damageObject(atarget)
										damageSP(atarget, 40)
										P_SetObjectMomZ(atarget, 5*FRACUNIT)
										P_StartQuake(FRACUNIT*12, 7)
										playSound(mo.battlen, sfx_phys)
										for i = 1, 4
											createSplat(mo)
										end
									end
									if mo.damagetime == 40
									and atarget ~= mo
										mo.atk_attacker = mo
										damageSP(mo, -40)
										playSound(mo.battlen, sfx_heal)
										fillEmeraldGauge(mo, 80, true)
										playSound(mo.battlen, sfx_buff2)
									elseif mo.damagetime == 85
										mo.rev = nil
										mo.reachedtarget = nil
										mo.damagetime = nil
										return true
									end
								end
							end
						end
					end
				end,
}

-- Weapons
weaponsList["hands_01"] = {
	name = "Magic Hands",
	type = WPT_PSYGLOVES,
	rarity = 1,
	element = ATK_PIERCE,
	atk = 300,
	desc = "A pair of magician's gloves \nthat somehow ended up in Morshu's \nLost and Found bin.",
	slot = "expel boost",
}

weaponsList["heated hands"] = {
	name = "Heated Hands",
	type = WPT_PSYGLOVES,
	rarity = 3,
	element = ATK_FIRE,
	atk = 900,
	desc = "A pair of magician's gloves \nthat gives more burn for \nfire-based tricks.",
	ma = 1,
	lu = 1,
	slot = "burn boost",
}

weaponsList["luminous hands"] = {
	name = "Luminous Hands",
	type = WPT_PSYGLOVES,
	rarity = 5,
	element = ATK_BLESS,
	atk = 1500,
	desc = "A pair of magician's gloves \nthat shines more brightly when \nthe spotlight is on.",
	ma = 3,
	lu = 3,
	slot = "bless boost",
}

-- Velvet Shop
table.insert(shopList["velvet_shop_mp1"].weapons, {makeWeapon("hands_01", 10), 800, nil, 4})
table.insert(shopList["velvet_shop_mp1"].weapons, {makeWeapon("heated hands"), 4000, 3})
table.insert(shopList["velvet_shop_mp1"].weapons, {makeWeapon("luminous hands"), 12500, 6})

-- Void Shop
table.insert(shopList["void_shop"].weapons, {makeWeapon("hands_01", 10), 700, nil, 6})
table.insert(shopList["void_shop"].weapons, {makeWeapon("heated hands"), 1500, 6, 12})
table.insert(shopList["void_shop"].weapons, {makeWeapon("luminous hands"), 2000, 12})

-- Vision Quest Stuff
enemyList["ganon"] = {
	name = "Ganon",
	skillchance = 100,
	level = 99,
	hp = 9999,
	sp = 9999,
	strength = 1,
	magic = 50,
	endurance = 99,
	agility = 1,
	luck = 50,
	melee_natk = "slash_1",
	thinker = generalEnemyThinker,
	weak = ATK_BLESS,
	resist = ATK_SLASH|ATK_STRIKE|ATK_PIERCE|ATK_FIRE|ATK_ICE|ATK_WIND|ATK_ELEC|ATK_PSY|ATK_NUCLEAR|ATK_ALMIGHTY,
	repel = ATK_CURSE,
	noroguerandom = true,
	noroguebuff = true,
	anim_stand = {SPR_GANO, A, 8},
	anim_hurt = {SPR_GANO, B, 35},
	anim_evoker = {SPR_GANO, C, 8},
	anim_getdown = {SPR_GANO, D, 1},
	anim_downloop = {SPR_GANO, D, 1},
	anim_death = {SPR_GANO, E, 30},
    vfx_skill = {"sfx_ganywd", "sfx_ganymd"},
    vfx_hurt = {"sfx_ganhrt"},
    vfx_hurtx = {"sfx_ganhrt", "sfx_ganwek", "sfx_ganmss", "sfx_gannoo"},
    vfx_die = {"sfx_gandie"},
    vfx_kill = {"sfx_ganpit", "sfx_gankll"},
    vfx_1more = {"sfx_ganpit", "sfx_ganchn"},
    vfx_miss = {"sfx_ganmss"},
    vfx_dodge = {"sfx_gandod"},
	skills = {"maeigaon", "curse boost", "mamudoon", "death boost", "evil smile", "hex boost", "life leech", "spirit leech"},
}

BTL_challengebtllist[#BTL_challengebtllist+1] = {
	name = "The GREATEST in Koridai",
	description = {"Ganon has invaded Tartarus for some", "reason. Stop him at once...", "or else you will die! (Morshu required)"},
	level = 99,
	music = "BATKAN",
	time = TICRATE*3000,
	items = {{"hyperring", 5}, {"soul food", 5}, {"super1up", 5}, {"patra gem", 5}, {"homunculus", 5}},
	subpersonas = {},
	waves = {
		{"ganon"}
	},
}