freeslot(
"S_PLAY_CASSANDRA_EGGMOBILELASERSWEEP",
"S_PLAY_CASSANDRA_EGGMOBILELASERSALVO",
"S_PLAY_CASSANDRA_BRAKSHIELD",
"S_PLAY_CASSANDRA_BRAKSNIPE",
"S_PLAY_CASSANDRA_BRAKFLAMETHROWER",
"S_PLAY_CASSANDRA_BRAKBOMB",
"S_PLAY_CASSANDRA_BRAKMINE"
)

states[S_PLAY_CASSANDRA_EGGMOBILELASERSWEEP] = {
	sprite = SPR_PLAY_TRNSF,
	frame = FF_FULLBRIGHT|F,
	tics = 2*TICRATE,
	action = A_Boss1Laser,
	var1 = MT_LASER,
	var2 = 4,
	nextstate = S_PLAY_FALL
}
states[S_PLAY_CASSANDRA_EGGMOBILELASERSALVO] = {
	sprite = SPR_PLAY_TRNSF,
	frame = FF_FULLBRIGHT|F,
	tics = 2*TICRATE,
	action = A_Boss1Laser,
	var1 = MT_LASER,
	var2 = 2,
	nextstate = S_PLAY_FALL
}

addHook("PlayerThink", function(player)
	if player.mo and player.mo.valid then
	
		if player.mo.skin ~= "cassandra_b" then
			return
		end
		
		if player.mo.egglasercooldown == nil then
			player.mo.egglasercooldown = 0
		end
		
		if player.mo.egglasercooldown > 0 then
			if (leveltime%TICRATE) then
				player.mo.egglasercooldown = $ - 1*TICRATE
			end
		end
		
		if player.mo.firingmahlazor == nil then
			player.mo.firingmahlazor = 0
		end
		
		if player.mo.firingmahlazor > 0 then
			if (leveltime%TICRATE) then
				player.mo.firingmahlazor = $ - 1*TICRATE
			end
		end
		
		if player.mo.copy == MT_EGGMOBILE then --Egg Mobile
			if player.mo.copyduration == 1 then
				print("You copied the Egg Mobile! Press and hold C1 to enter flight mode! While in flight mode, press and hold Jump to ascend or Spin to descend!","While out of flight mode, press C2 to shoot a simple laser. While in flight mode, press C2 to initiate a sweeping laser attack!","While out of flight mode, press C3 to conjure a spikeball. While in flight mode, press C3 to initiate a big sweeping laser attack!")
			end
			if player.custom1down > 1
			and player.mo.energy >= 5*FRACUNIT
			and P_IsObjectOnGround(player.mo) == false then
				player.pflags = $&~PF_JUMPED --prevent air actions and shield actions during Buzz flight
			end
			if player.custom1down > 1
			and ((player.cmd.buttons & BT_JUMP == 0 and player.cmd.buttons & BT_SPIN == 0)
			or (player.cmd.buttons & BT_JUMP >= 1 and player.cmd.buttons & BT_SPIN >= 1)) --if neither or both of Jump and Spin are being held
			and player.mo.energy >= 5*FRACUNIT then --if the player has energy
				player.mo.flags = $1|MF_NOGRAVITY --player flies like the Egg Mobile
				if not (leveltime%TICRATE) then
					player.mo.energy = $ - 5*FRACUNIT
				end
				P_SetObjectMomZ(player.mo, 0, false) --player hovers in the air
				player.mo.copypoweruse = 1 --prevent energy recharge during flight
			end
			if player.custom1down > 1
			and player.cmd.buttons & BT_JUMP >= 1
			and player.cmd.buttons & BT_SPIN == 0 --if Jump is being held, but Spin is not
			and player.mo.energy >= 5*FRACUNIT then --if the player has energy
				player.mo.flags = $1|MF_NOGRAVITY --player flies like the Egg Mobile
				if not (leveltime%TICRATE) then
					player.mo.energy = $ - 5*FRACUNIT
				end
				P_SetObjectMomZ(player.mo, 5*FRACUNIT, false) --player slowly ascends
				player.mo.copypoweruse = 1 --prevent energy recharge during flight
			end
			if player.custom1down > 1
			and player.cmd.buttons & BT_JUMP == 0
			and player.cmd.buttons & BT_SPIN >= 1 --if Spin is being held, but Jump is not
			and player.mo.energy >= 5*FRACUNIT then --if the player has energy
				player.mo.flags = $1|MF_NOGRAVITY --player flies like the Egg Mobile
				if not (leveltime%TICRATE) then
					player.mo.energy = $ - 5*FRACUNIT
				end
				P_SetObjectMomZ(player.mo, -5*FRACUNIT, false) --player slowly descends
				player.mo.copypoweruse = 1 --prevent energy recharge during flight
			end
			if (player.custom1down == 0 or player.mo.energy < 5*FRACUNIT)
			and player.mo.firingmahlazor == 0 then
				player.mo.flags = $&~MF_NOGRAVITY --stop flying
				player.mo.copypoweruse = 0 --allow energy to recharge while not flying
				if P_IsObjectOnGround(player.mo) == false then
					player.pflags = $1|PF_JUMPED --re-enable air and shield actions if they haven't been used (PF_THOKKED is *not* removed)
				end
			end
			if player.custom2down == 1
			and player.custom1down == 0
			and player.mo.energy >= 7*FRACUNIT/4
			and player.mo.egglasercooldown == 0 then
				player.mo.energy = $ - 7*FRACUNIT/4
				local egglaser = P_SpawnPlayerMissile(player.mo, MT_LASER, 0)
				player.mo.egglasercooldown = 3*TICRATE/4
			end
			if player.custom2down == 1
			and player.custom1down > 1
			and player.mo.energy >= 25*FRACUNIT/2
			and P_IsObjectOnGround(player.mo) == false
			and player.mo.egglasercooldown == 0 then
				player.mo.energy = $ - 25*FRACUNIT/2
				player.mo.state = S_PLAY_CASSANDRA_EGGMOBILELASERSWEEP
				player.mo.firingmahlazor = 2*TICRATE
				player.mo.egglasercooldown = 2*TICRATE
			end
			if player.custom3down == 1
			and player.custom1down == 0
			and player.mo.energy >= 10*FRACUNIT then
				player.mo.energy = $ - 10*FRACUNIT
				local spikemine = P_SpawnMobjFromMobj(player.mo, P_RandomRange(-3000, 3000)*FRACUNIT, P_RandomRange(-3000, 3000)*FRACUNIT, P_RandomRange(-3000, 3000)*FRACUNIT, MT_SPIKEBALL)
			end
			if player.custom3down == 1
			and player.custom1down > 1
			and player.mo.energy >= 25*FRACUNIT
			and P_IsObjectOnGround(player.mo) == false
			and player.mo.egglasercooldown == 0 then
				player.mo.energy = $ - 25*FRACUNIT
				player.mo.state = S_PLAY_CASSANDRA_EGGMOBILELASERSALVO
				player.mo.firingmahlazor = 2*TICRATE
				player.mo.egglasercooldown = 2*TICRATE
			end
			if player.mo.firingmahlazor > 0 then
				player.mo.flags = $1|MF_NOGRAVITY
				player.mo.flags2 = $1|MF2_FIRING
				player.mo.copypoweruse = 1
				P_SetObjectMomZ(player.mo, 0, false)
				player.pflags = $1|PF_FULLSTASIS --can't move during big laser attacks
			end
			if player.mo.firingmahlazor > 0
			and P_PlayerInPain(player) == true --if the player gets hurt while firing the big laser
				player.mo.firingmahlazor = 0 --immediately stop
			end
			if player.mo.firingmahlazor == 0 then
				player.mo.flags2 = $&~MF2_FIRING
			end
		end
		
		if player.mo.copy ~= MT_EGGMOBILE then
			player.mo.egglasercooldown = 0
			player.mo.firingmahlazor = 0
		end
		
		if player.mo.copy == MT_EGGMOBILE2 then --Egg Slimer
			if player.mo.copyduration == 1 then
				print("You copied the Egg Slimer! Press and hold C1 to spray damaging goop haphazardly!")
			end
			if player.custom1down > 1
			and player.mo.energy >= 6*FRACUNIT then
				if player.custom1down == 2 then
					player.mo.energy = $ - 6*FRACUNIT
				end
				if player.custom1down > 40 then
					if not (leveltime%TICRATE) then
						player.mo.energy = $ - 6*FRACUNIT
					end
				end
				player.mo.copypoweruse = 1
				if (player.custom1down%9) then
					local cassandrasgoop = P_SpawnMobjFromMobj(player.mo, P_RandomRange(-7, 7)*FRACUNIT, P_RandomRange(-7, 7)*FRACUNIT, P_RandomRange(6, 11)*FRACUNIT, MT_GOOP) --spawn goop at random locations around Cassandra
					cassandrasgoop.target = player.mo --assign the goop to Cassandra so it doesn't hurt her
					P_SetObjectMomZ(cassandrasgoop, P_RandomRange(5, 12)*FRACUNIT, false) --flinging the goop to random heights
					P_InstaThrust(cassandrasgoop, P_RandomRange(0, 360), P_RandomRange(-8, 8)*FRACUNIT) --flinging the goop a random distance away in a random direction)
					A_SetObjectFlags(cassandrasgoop, 32768, 0) --declaring that the goop is a missile so that it can hurt enemies (and removing the PF_PAIN flag so it doesn't hurt the player)
				end
			end
			if player.custom1down == 0
			or player.mo.energy < 6*FRACUNIT then
				player.mo.copypoweruse = 1
			end
		end
		
		if player.mo.seaeggmissilecooldown == nil then
			player.mo.seaeggmissilecooldown = 0
		end
		
		if player.mo.seaeggmissilecooldown > 0 then
			if (leveltime%TICRATE) then
				player.mo.seaeggmissilecooldown = $ - 1
			end
		end
		
		if player.mo.seaeggshockwavecooldown == nil then
			player.mo.seaeggshockwavecooldown = 0
		end
		
		if player.mo.seaeggshockwavecooldown > 0 then
			if (leveltime%TICRATE) then
				player.mo.seaeggshockwavecooldown = $ - 1
			end
		end
		
		if player.mo.copy == MT_EGGMOBILE3 then --Sea Egg
			if player.mo.copyduration == 1 then
				print("You copied the Sea Egg! Press C1 to shoot missiles! Hold C1 to create a clone! Press C2 to conjure an electric ring! Press C3 to dive into tunnels or emerge onto the surface!")
			end
			if player.custom1down == 1
			and player.custom3down == 0
			and player.mo.energy >= 6*FRACUNIT
			and player.mo.seaeggmissilecooldown == 0 then
				player.mo.energy = $ - 6*FRACUNIT
				local cassandrastorpedo1 = P_SpawnPlayerMissile(player.mo, MT_TORPEDO, 0)
				cassandrastorpedo1.target = player.mo
				local cassandrastorpedo2 = P_SpawnPlayerMissile(player.mo, MT_TORPEDO2, 0)
				cassandrastorpedo2.target = player.mo
				player.mo.seaeggmissilecooldown = 9*TICRATE/7
			end
			if player.custom2down == 1
			and player.custom3down == 0
			and player.mo.energy >= 18*FRACUNIT
			and player.mo.seaeggshockwavecooldown == 0 then
				player.mo.energy = $ - 18*FRACUNIT
				local degree
				for degree = 1,360 do
					local cassandrasshockwave = P_SPMAngle(player.mo, MT_SHOCKWAVE, (player.mo.angle + degree*ANG1), 0, 0) --fire 360 shockwave projectiles in every direction
					cassandrasshockwave.target = player.mo
					//A_SetObjectFlags(cassandrasshockwave, 32768, 0) --declaring that the shockwave is a missile so that it can hurt enemies (and removing the PF_PAIN flag so it doesn't hurt the player)
				end
				player.mo.seaeggshockwavecooldown = 5*TICRATE/2
			end
			if player.custom3down == 1
			and player.mo.energy >= 5*FRACUNIT
			and player.mo.copypowerjump == 0 then
			//and ((player.mo.floorrover and player.mo.floorrover.valid) or (player.mo.ceilingrover and player.mo.ceilingrover.valid)) then --if the player is in the same sector as a (tangible) FOF
				if ((player.mo.floorrover and player.mo.floorrover.valid) and not (player.mo.ceilingrover and player.mo.ceilingrover.valid)) then --if there is an FOF below the player, but not above
					//if then --if the FOF is tangible
						player.mo.energy = $ - 5*FRACUNIT
						P_MoveOrigin(player.mo, (player.mo.x + 0), (player.mo.y + 0), (player.mo.z - (player.mo.floorrover.bottomheight - 20*FRACUNIT))) --move below the FOF
						player.mo.copypowerjump = 1
					//end
				elseif ((player.mo.ceilingrover and player.mo.ceilingrover.valid) and not (player.mo.floorrover and player.mo.floorrover.valid)) then --if there is an FOF above the player, but not below
					//if then --if the FOF is tangible
						player.mo.energy = $ - 5*FRACUNIT
						P_MoveOrigin(player.mo, (player.mo.x + 0), (player.mo.y + 0), (player.mo.z + (player.mo.ceilingrover.topheight + 20*FRACUNIT))) --move above the FOF
						player.mo.copypowerjump = 1
					//end
				elseif ((player.mo.floorrover and player.mo.floorrover.valid) and (player.mo.ceilingrover and player.mo.ceilingrover.valid)) then --if there is an FOF below the player and an FOF above
					if P_IsObjectOnGround(player.mo) == true then --if the player is standing on the FOF beneath them
						//if then --if the FOF is tangible
							player.mo.energy = $ - 5*FRACUNIT
							P_MoveOrigin(player.mo, (player.mo.x + 0), (player.mo.y + 0), (player.mo.z - (player.mo.floorrover.bottomheight - 20*FRACUNIT))) --move below the FOF underneath
							player.mo.copypowerjump = 1
						//else
							//return
						//end
					else
						//if then --if the FOF is tangible
							player.mo.energy = $ - 5*FRACUNIT
							P_MoveOrigin(player.mo, (player.mo.x + 0), (player.mo.y + 0), (player.mo.z + (player.mo.ceilingrover.topheight + 20*FRACUNIT))) --move above the FOF overhead
							player.mo.copypowerjump = 1
						//else
							//return
						//end
					end
				end
				if player.custom3down > 8*TICRATE
				and player.custom1down == 1
				and player.mo.energy >= 10*FRACUNIT then
					player.mo.energy = $ - 10*FRACUNIT
					P_MoveOrigin(player.mo, (player.mo.x + 0), (player.mo.y + 0), (player.mo.z - 50*FRACUNIT)) --failsafe against getting stuck in the ceiling
				end
				if player.custom3down > 8*TICRATE
				and player.custom2down == 1
				and player.mo.energy >= 10*FRACUNIT then
					player.mo.energy = $ - 10*FRACUNIT
					P_MoveOrigin(player.mo, (player.mo.x + 0), (player.mo.y + 0), (player.mo.z + 50*FRACUNIT)) --failsafe against getting stuck in the floor
				end
			end
		end
		
		if player.mo.cagedown == nil then
			player.mo.cagedown = 0
		end
		
		if player.mo.copy == MT_EGGMOBILE4 then --Egg Colosseum
			if player.mo.copyduration == 1 then
				print("You copied the Egg Colosseum! You have four maces that you'll be swinging around at all times! Press and hold C1 to speed up your maces! Press C2 to reverse your maces' direction! Press and hold C3 to bunker down with your cage!")
			end
			if player.custom3down > 1
			and player.mo.energy >= 35*FRACUNIT/2 then
				P_ResetPlayer(player)
				if not (leveltime%TICRATE) then
					player.mo.energy = $ - 35*FRACUNIT/2
				end
				player.pflags = $1|PF_FULLSTASIS
				player.mo.copypoweruse = 1
				player.mo.cagedown = 1
			else
				player.mo.cagedown = 0
			end
			if (player.custom1down == 0 and player.custom3down == 0)
			or (player.mo.energy < 5*FRACUNIT
			or (player.custom3down > 1 and player.mo.energy < 35*FRACUNIT/2)) then
				player.mo.copypoweruse = 0
			end
		end
		
		if player.mo.fangabilitytoggle == nil then
			player.mo.fangabilitytoggle = 0
		end
		
		if player.mo.fangabilitytogglecooldown == nil then
			player.mo.fangabilitytogglecooldown = 0
		end
		
		if player.mo.fangabilitytogglecooldown > 0 then
			if (leveltime%TICRATE) then
				player.mo.fangabilitytogglecooldown = $ - 1
			end
		end
		
		if player.mo.fangbombcooldown == nil then
			player.mo.fangbombcooldown = 0
		end
		
		if player.mo.fangbombcooldown > 0 then
			if (leveltime%TICRATE) then
				player.mo.fangbombcooldown = $ - 1
			end
		end
		
		if player.mo.copy == MT_FANG then
			if player.mo.copyduration == 1 then
				print("You copied Fang! Press C1 to switch between Cassandra's double-jump and spindash and Fang's bounce and corks! Press C2 to drop a bomb! Press C3 to lob a bomb! Press C2 and C3 together to throw a bomb shower!")
			end
			if player.custom1down == 1
			and player.mo.fangabilitytoggle == 0
			and player.mo.fangabilitytogglecooldown == 0
			and player.mo.energy >= 1*FRACUNIT then
				player.mo.fangabilitytoggle = 1
				player.mo.fangabilitytogglecooldown = 1*TICRATE/6
			end
			if ((player.custom1down == 1
			and player.mo.fangabilitytogglecooldown == 0)
			or (player.mo.energy < 1*FRACUNIT))
			and player.mo.fangabilitytoggle == 1 then
				player.mo.fangabilitytoggle = 0
				player.mo.fangabilitytogglecooldown = 1*TICRATE/6
			end
			if player.mo.fangabilitytoggle == 1 then
				player.charability = CA_BOUNCE
				player.charability2 = CA2_GUNSLINGER
				player.revitem = MT_CORK
				player.jumpfactor = skins["fang"].jumpfactor --increase to Fang's jump height
				player.mo.copypoweruse = 1
				if not (leveltime%TICRATE) then
					player.mo.energy = $ - 1*FRACUNIT/8
				end
				if player.mo.state == S_PLAY_BOUNCE_LANDING then
					if player.mo.tics == 2 then
						player.mo.energy = $ - 1*FRACUNIT --drain energy upon landing from a bounce
					end
				end
				if player.mo.state == S_PLAY_FIRE then
					if player.mo.tics == 1 then
						player.mo.energy = $ - 1*FRACUNIT --drain energy upon shooting a cork
					end
				end
			else
				player.charability = skins[player.skin].ability
				player.charability2 = skins[player.skin].ability2
				player.revitem = skins[player.skin].revitem
				player.jumpfactor = skins[player.skin].jumpfactor
				player.mo.copypoweruse = 0
			end
			if player.custom2down == 1
			and player.custom3down == 0
			and player.mo.energy >= 4*FRACUNIT
			and player.mo.fangbombcooldown == 0 then
				player.mo.energy = $ - 4*FRACUNIT
				local cassandrasfangbomb = P_SpawnMobjFromMobj(player.mo, 0, 0, 0, MT_FBOMB) --drop a bomb where the player is
				cassandrasfangbomb.target = player.mo --set the bomb's target to the player so it doesn't hurt them
				player.mo.fangbombcooldown = 5*TICRATE/6
			end
			if player.custom3down == 1
			and player.custom2down == 0
			and player.mo.energy >= 5*FRACUNIT
			and player.mo.fangbombcooldown == 0 then
				player.mo.energy = $ - 5*FRACUNIT
				local cassandrasfangbomb = P_SpawnPlayerMissile(player.mo, MT_FBOMB, 0) --throw a bomb
				cassandrasfangbomb.target = player.mo
				P_SetObjectMomZ(cassandrasfangbomb, 8*FRACUNIT, true)
				P_InstaThrust(cassandrasfangbomb, player.mo.angle, 16*FRACUNIT)
				player.mo.fangbombcooldown = 1*TICRATE
			end
			if player.custom2down == 1
			and player.custom3down == 1
			and player.mo.energy >= 30*FRACUNIT
			and player.mo.fangbombcooldown == 0 then
				player.mo.energy = $ - 30*FRACUNIT
				local cassandrasfangbomb1 = P_SPMAngle(player.mo, MT_FBOMB, player.mo.angle, 1, 0) --high-throw multiple bombs
				cassandrasfangbomb1.target = player.mo
				P_SetObjectMomZ(cassandrasfangbomb1, 15*FRACUNIT, true)
				P_InstaThrust(cassandrasfangbomb1, player.mo.angle, 5*FRACUNIT)
				local cassandrasfangbomb2 = P_SPMAngle(player.mo, MT_FBOMB, (player.mo.angle+45), 1, 0)
				cassandrasfangbomb2.target = player.mo
				P_SetObjectMomZ(cassandrasfangbomb2, 15*FRACUNIT, true)
				P_InstaThrust(cassandrasfangbomb2, (player.mo.angle+(45*ANG1)), 5*FRACUNIT)
				local cassandrasfangbomb3 = P_SPMAngle(player.mo, MT_FBOMB, (player.mo.angle+90), 1, 0)
				cassandrasfangbomb3.target = player.mo
				P_SetObjectMomZ(cassandrasfangbomb3, 15*FRACUNIT, true)
				P_InstaThrust(cassandrasfangbomb3, (player.mo.angle+(90*ANG1)), 5*FRACUNIT)
				local cassandrasfangbomb4 = P_SPMAngle(player.mo, MT_FBOMB, (player.mo.angle+135), 1, 0)
				cassandrasfangbomb4.target = player.mo
				P_SetObjectMomZ(cassandrasfangbomb4, 15*FRACUNIT, true)
				P_InstaThrust(cassandrasfangbomb4, (player.mo.angle+(135*ANG1)), 5*FRACUNIT)
				local cassandrasfangbomb5 = P_SPMAngle(player.mo, MT_FBOMB, (player.mo.angle+180), 1, 0)
				cassandrasfangbomb5.target = player.mo
				P_SetObjectMomZ(cassandrasfangbomb5, 15*FRACUNIT, true)
				P_InstaThrust(cassandrasfangbomb5, (player.mo.angle+(180*ANG1)), 5*FRACUNIT)
				local cassandrasfangbomb6 = P_SPMAngle(player.mo, MT_FBOMB, (player.mo.angle+225), 1, 0)
				cassandrasfangbomb6.target = player.mo
				P_SetObjectMomZ(cassandrasfangbomb6, 15*FRACUNIT, true)
				P_InstaThrust(cassandrasfangbomb6, (player.mo.angle+(225*ANG1)), 5*FRACUNIT)
				local cassandrasfangbomb7 = P_SPMAngle(player.mo, MT_FBOMB, (player.mo.angle+270), 1, 0)
				cassandrasfangbomb7.target = player.mo
				P_SetObjectMomZ(cassandrasfangbomb7, 15*FRACUNIT, true)
				P_InstaThrust(cassandrasfangbomb7, (player.mo.angle+(270*ANG1)), 5*FRACUNIT)
				local cassandrasfangbomb8 = P_SPMAngle(player.mo, MT_FBOMB, (player.mo.angle+315), 1, 0)
				cassandrasfangbomb8.target = player.mo
				P_SetObjectMomZ(cassandrasfangbomb8, 15*FRACUNIT, true)
				P_InstaThrust(cassandrasfangbomb8, (player.mo.angle+(315*ANG1)), 5*FRACUNIT)
				player.mo.fangbombcooldown = 3*TICRATE
			end
		end
		
		if player.mo.copy ~= MT_FANG then
			player.mo.fangabilitytoggle = 0
			player.mo.fangabilitytogglecooldown = 0
			player.mo.fangbombcooldown = 0
		end
		
		if player.mo.brakshieldcharge == nil then
			player.mo.brakshieldcharge = 0
		end
		
		if player.mo.braksnipeprep == nil then
			player.mo.braksnipeprep = 0
		end
		
		if player.braksnipetarget == nil then
			player.braksnipetarget = 0
		end
		
		if player.mo.brakmissilecooldown == nil then
			player.mo.brakmissilecooldown = 0
		end
		
		if player.mo.brakmissilecooldown > 0 then
			if (leveltime%TICRATE) then
				player.mo.brakmissilecooldown = $ - 1
			end
		end
		
		if player.mo.copy == MT_CYBRAKDEMON or player.mo.copy == MT_BLACKEGGMAN then --Brak Eggman
			if player.mo.copyduration == 1 then
				print("You copied Brak Eggman! You are a walking arsenal!","Press and hold C1 by itself to shoot flames! Press C2 by itself to fire a napalm bomb! Press and hold C1 and C2 to fire immobilizing goop! Press and hold C3 by itself to prepare a sniper shot! Press Fire by itself to shoot a missile! Press Fire while holding C3 to shoot a faster and more explosive missile!","You'll also get a Lightning Shield every so often if you don't already have one!","You're evenly matched with Dr. Eggman... now cut loose and show him the folly of his warmongering ways!")
				if player.powers[pw_shield] == 0 then
					if player.mo.energy >= 20*FRACUNIT then
						player.mo.energy = $ - 20*FRACUNIT
						player.powers[pw_shield] = SH_THUNDERCOIN|SH_PROTECTFIRE
						//A_CustomPower(player.mo, 3, 4098) --Lightning Shield
						print("Lightning Shield generated! (And it protects against fire, too!)")
					else
						player.mo.brakshieldcharge = 1
					end
				end
			end
			if player.powers[pw_shield] == 0 then
				if player.mo.brakshieldcharge == 1
				and player.mo.energy >= 20*FRACUNIT then
					player.mo.energy = $ - 20*FRACUNIT
					player.powers[pw_shield] = SH_THUNDERCOIN|SH_PROTECTFIRE
					//A_CustomPower(player.mo, 3, 4098) --Lightning Shield
					print("Lightning Shield generated! (And it protects against fire, too!)")
					player.mo.brakshieldcharge = 0
					player.extrahit = 25*TICRATE
				end
			end
			if player.powers[pw_shield] == SH_THUNDERCOIN|SH_PROTECTFIRE then
				player.followitem = MT_CYBRAKDEMON_ELECTRIC_BARRIER --visibly show the electric barrier on Cassandra's model
				player.mo.brakshieldcharge = 0
			else
				player.followitem = skins[player.skin].followitem
			end
			if player.extrahit == 1
			and player.mo.brakshieldcharge == 0 then
				player.mo.brakshieldcharge = 1
			end
			if player.extrahit == 0
			and player.mo.brakshieldcharge == 0 then
				if player.powers[pw_shield] == 0
				and player.mo.copyduration > 1 then
					player.extrahit = 25*TICRATE
				elseif player.powers[pw_shield] > 0 then
					player.mo.brakshieldcharge = 1
				end
			end
			if player.custom1down > 1
			and player.custom2down == 0
			and player.mo.energy >= 5*FRACUNIT then
				if player.custom1down == 2 then
					player.mo.energy = $ - 5*FRACUNIT
				end
				if player.custom1down > 40 then
					if not (leveltime%TICRATE) then
						player.mo.energy = $ - 5*FRACUNIT
					end
				end
				if (player.custom1down%5) then
					local brakflame = P_SpawnPlayerMissile(player.mo, MT_CYBRAKDEMON_FLAMESHOT, 0) --flamethrower
					brakflame.target = player.mo
				end
				if brakflame and brakflame.valid then --if the player is shooting flames
					player.mo.copypoweruse = 1
				elseif player.mo.braksnipeprep == 0 then --if the player isn't sniping
					player.mo.copypoweruse = 0
				end
			end
			if player.custom2down == 1
			and player.custom1down == 0
			and player.mo.energy >= 35*FRACUNIT/2
			and player.mo.brakmissilecooldown == 0 then
				player.mo.energy = $ - 35*FRACUNIT/2
				local brakbomb = P_SpawnPlayerMissile(player.mo, MT_CYBRAKDEMON_NAPALM_BOMB_LARGE, 0) --spawn a napalm bomb
				P_SetObjectMomZ(brakbomb, 6*FRACUNIT, true) --give the napalm bomb a bit more height so it actually covers some distance
				player.mo.brakmissilecooldown = 11*TICRATE/5
			end
			if player.custom3down == 1
			//and player.mo.braksnipeprep == 0
			and player.firedown == 0
			and player.mo.energy >= 10*FRACUNIT then
				player.braksnipetarget = P_LookForEnemies(player, false, true) --find a sniping target
				//player.braksnipetarget = A_FindTarget(player.mo, ((MF_SHOOTABLE)), 0)
				if (player.braksnipetarget and player.braksnipetarget.valid) then --if a target was found
					if P_CheckSight(player.mo, player.braksnipetarget) == true then --if the player has line of sight
						player.mo.braksnipeprep = $ + 1 --start preparing the sniper shot
						//print("Locked on to "..player.braksnipetarget.."! Keep them in your sights to deal guaranteed damage!")
						print("Locked on to the target! Keep them in your sights to deal guaranteed damage!")
						S_StartSound(player.mo, sfx_s3k9d, nil)
						local reticule = P_SpawnMobjFromMobj(player.braksnipetarget, 0, 0, (player.braksnipetarget.height / 2), MT_CYBRAKDEMON_TARGET_RETICULE)
						reticule.target = player.braksnipetarget
						player.mo.energy = $ - 1*FRACUNIT
					end
				end
			end
			if player.custom3down == 0 then
				player.mo.braksnipeprep = 0 --reset snipe if C3 is released
			end
			if player.custom3down > 1
			and player.firedown == 0
			and player.mo.braksnipeprep >= 1
			//and player.custom3down == player.mo.braksnipeprep
			//and player.custom3down =< 5*TICRATE
			and player.mo.braksnipeprep < 5*TICRATE
			and player.mo.energy >= (9*FRACUNIT - (((player.mo.braksnipeprep*TICRATE)*FRACUNIT/4)>>TICRATE)) then
				if (player.braksnipetarget and player.braksnipetarget.valid) then
				//and (reticule and reticule.valid) then
					if P_CheckSight(player.mo, player.braksnipetarget) == true then --if the player maintains line of sight
						player.mo.braksnipeprep = $ + 1
						player.mo.copypoweruse = 1
						A_CapeChase(reticule, (player.braksnipetarget.height / 2)+0, 0+0)
						if player.mo.braksnipeprep == 1*TICRATE or player.mo.braksnipeprep == 2*TICRATE or player.mo.braksnipeprep == 3*TICRATE or player.mo.braksnipeprep == 4*TICRATE then
							player.mo.energy = $ - 1*FRACUNIT/4
							S_StartSound(player.mo, sfx_s3k9d, nil)
							print("Lock-on maintained!")
						end
					else --if line of sight is broken
						player.mo.braksnipeprep = 0
						player.mo.copypoweruse = 0
						player.braksnipetarget = 0
						print("You broke line of sight! Your sniper shot is ruined!")
						if (reticule and reticule.valid) then
							P_KillMobj(reticule, nil, nil)
						end
					end
				else
					print("...Wait, did you just destroy the target before shooting it?!")
					player.mo.braksnipeprep = 0
					player.mo.copypoweruse = 0
					player.braksnipetarget = 0
					if reticule and reticule.valid then
						P_KillMobj(reticule, nil, nil)
					else
						print("WHAT? How did you screw up that badly...?!?")
					end
					
				end
			end
			if player.custom3down >= 5*TICRATE
			and player.firedown == 0
			and player.mo.braksnipeprep == 5*TICRATE
			and player.mo.energy >= 8*FRACUNIT then
				if (player.braksnipetarget and player.braksnipetarget.valid) then
				//and (reticule and reticule.valid) then
					if P_CheckSight(player.mo, player.braksnipetarget) == true then --if the player maintains line of sight
						P_DamageMobj(player.braksnipetarget, reticule, player.mo, 2) --snipe the target
						S_StartSound(player.mo, s3kb4, nil)
						//print(player.braksnipetarget.." successfully sniped!")
						print("Target successfully sniped!")
						player.mo.copypoweruse = 0
						player.mo.braksnipeprep = 0
						player.braksnipetarget = 0
						player.mo.energy = $ - 8*FRACUNIT --energy cost imposed after resetting braksnipeprep and braksnipetarget to avoid instantly draining energy to less than 8
						if (reticule and reticule.valid) then
							P_KillMobj(reticule, nil, nil)
						end
					else --if line of sight is broken
						player.mo.braksnipeprep = 0
						player.mo.copypoweruse = 0
						player.braksnipetarget = 0
						print("You broke line of sight! Your sniper shot is ruined!")
						if (reticule and reticule.valid) then
							P_KillMobj(reticule, nil, nil)
						end
					end
				else
					print("...Wait, did you just destroy the target before shooting it?!")
					player.mo.braksnipeprep = 0
					player.mo.copypoweruse = 0
					player.braksnipetarget = 0
					if reticule and reticule.valid then
						P_KillMobj(reticule, nil, nil)
					else
						print("WHAT? How did you screw up that badly...?!?")
					end
				end
			end
			if player.mo.braksnipeprep > 0
			and player.firedown == 1 then
				player.mo.braksnipeprep = 0 --cancel sniping
				player.mo.copypoweruse = 0
				player.braksnipetarget = 0
				print("You can't snipe with a bazooka!")
				if reticule and reticule.valid then
					P_KillMobj(reticule, nil, nil)
				end
			end
			if player.custom3down > 1
			and player.mo.braksnipeprep == 0 then --if the sniper shot has succeeded or failed
				player.mo.copypoweruse = 0 --resume energy regeneration
			end
			if player.firedown == 1
			and player.custom3down == 0
			and (G_RingSlingerGametype() == false or ((player.powers[pw_infinityring] == 0 and player.powers[pw_automaticring] == 0 and player.powers[pw_bouncering] == 0 and player.powers[pw_scatterring] == 0 and player.powers[pw_grenadering] == 0 and player.powers[pw_explosionring] == 0 and player.powers[pw_railring] == 0) or player.rings == 0)) --and the player can't shoot any Ringslinger rings
			and player.mo.energy >= 25*FRACUNIT/2
			and player.mo.brakmissilecooldown == 0 then
				player.mo.energy = $ - 25*FRACUNIT/2
				P_SpawnPlayerMissile(player.mo, MT_BLACKEGGMAN_MISSILE, 0)
				player.mo.brakmissilecooldown = 3*TICRATE/4
			end
			if player.custom1down > 1
			and player.custom2down > 1
			and player.custom1down > player.custom2down
			and player.mo.energy >= 1*FRACUNIT then
				if player.custom2down == 2 then
					player.mo.energy = $ - 1*FRACUNIT
				end
				if player.custom2down > 40 then
					if not (leveltime%TICRATE) then
						player.mo.energy = $ - 1*FRACUNIT
					end
				end
				if (player.custom1down%5) then
					local brakgoop = P_SpawnPlayerMissile(player.mo, MT_BLACKEGGMAN_GOOPFIRE, 0) --goop spray
					brakgoop.target = player.mo
				end
				if brakgoop and brakgoop.valid then --if the player is firing goop
					player.mo.copypoweruse = 1
				elseif player.mo.braksnipeprep == 0 then --if the player isn't sniping
					player.mo.copypoweruse = 0
				end
			end
			if player.custom3down > 1
			and player.firedown == 1
			and player.custom3down > player.firedown
			and (G_RingSlingerGametype() == false or ((player.powers[pw_infinityring] == 0 and player.powers[pw_automaticring] == 0 and player.powers[pw_bouncering] == 0 and player.powers[pw_scatterring] == 0 and player.powers[pw_grenadering] == 0 and player.powers[pw_explosionring] == 0 and player.powers[pw_railring] == 0) or player.rings == 0)) --and the player can't shoot any Ringslinger rings
			and player.mo.energy >= 15*FRACUNIT
			and player.mo.brakmissilecooldown == 0 then
				player.mo.energy = $ - 15*FRACUNIT
				P_SpawnPlayerMissile(player.mo, MT_CYBRAKDEMON_MISSILE, 0)
				player.mo.brakmissilecooldown = 3*TICRATE/2
			end
			if player.custom1down == 0
			and player.custom3down == 0 then
				player.mo.copypoweruse = 0 --allow energy to regenerate if the player isn't spraying flames or goop or preparing to snipe
			end
		end
		
		if player.mo.copy ~= MT_CYBRAKDEMON and player.mo.copy ~= MT_BLACKEGGMAN then
			player.mo.braksnipeprep = 0
			player.mo.brakshieldcharge = 0
			player.braksnipetarget = 0
		end
	end
end)

addHook("PlayerThink", function(player)
	if player.mo and player.mo.valid then
	
		if player.powers[pw_shield] == SH_THUNDERCOIN|SH_PROTECTFIRE --For anyone who somehow gets a combined Lightning and Flame shield
		and P_IsObjectOnGround(player.mo) == false
		and (player.pflags & PF_JUMPED) --Player must have jumped
		and player.cmd.buttons & BT_SPIN == 1 --Shield action
		and not (player.pflags & PF_THOKKED)
		and not (player.pflags & PF_SHIELDABILITY) --Can only be used if shield action is not expended
		and not (player.charflags & SF_NOSHIELDABILITY) then --Player must be able to use shield actions
			P_SetObjectMomZ(player.mo, player.jumpfactor*FRACUNIT, true) --Lightning Shield double-jump
			S_StartSound(player.mo, sfx_s3k45, nil)
			player.pflags = $1|PF_THOKKED
			player.pflags = $1|PF_SHIELDABILITY
		end
	end
end)

addHook("ShouldDamage", function(target, inflictor, source, damage, damagetype)
	if target.player.mo and target.player.mo.valid then
	
		if target.player.mo.skin ~= "cassandra_b" then
			return
		end
		
		if target.player.mo.copy == MT_EGGMOBILE2 then
			if inflictor == MT_GOOP
			and source == target.player.mo then
				return false --making sure that Cassandra isn't harmed by her own goop
			end
		end
		
		if target.player.mo.copy == MT_EGGMOBILE3 then
			if target.player.mo.seaeggshockwavecooldown > 3*TICRATE/4
			and damagetype == DMG_ELECTRIC then
				return false
			end
			if inflictor == MT_SHOCKWAVE
			and source == target.player.mo then
				return false --making sure that Cassandra isn't harmed by her own shockwave
			end
		end
		
		if target.player.mo.copy == MT_EGGMOBILE4 then
			if target.player.mo.cagedown == 1 then
				return false
			end
		end
		
		if target.player.mo.copy == MT_CYBRAKDEMON or target.player.mo.copy == MT_BLACKEGGMAN then
			if inflictor == MT_CYBRAKDEMON_FLAMESHOT
			and source == target.player.mo then
				return false --making sure that the player doesn't get burned by their own fire
			end
		end
	end
end, MT_PLAYER)

addHook("MobjMoveCollide", function(spikemine, thing)
	if spikemine and spikemine.valid then
		if (thing.flags & MF_ENEMY) or (thing.flags & MF_BOSS) then
			P_DamageMobj(thing, spikemine, player.mo, 1) --damage enemies that run into spikeballs Cassandra summons
		end
	end
end, MT_SPIKEBALL)

addHook("MobjMoveCollide", function(cassandrasshockwave, thing)
	if cassandrasshockwave and cassandrasshockwave.valid
	and thing and thing.valid
	and thing == cassandrasshockwave.target then
		return false --don't let Cassandra even be touched by her own shockwave, just to be extra-sure that it doesn't hurt her
	end
end, MT_SHOCKWAVE)

addHook("MobjMoveCollide", function(brakflame, thing)
	if brakflame and brakflame.valid
	and thing and thing.valid
	and thing == brakflame.target then
		return false --don't let Cassandra even be touched by her own flames, just to be extra-sure that they don't hurt her
	end
end, MT_CYBRAKDEMON_FLAMESHOT)

addHook("MobjThinker", function(mobj)
	if mobj and mobj. valid then
		if (mobj.flags & MF_ENEMY) or (mobj.flags & MF_BOSS) then
			if mobj.gummedup == nil then
				mobj.gummedup = 0
			end
			
			if mobj.gummedup > 0 then
				if not (leveltime%TICRATE) then
					mobj.gummedup = $ - 1
				end
			end
			
			mobj.friction = $ - (mobj.gummedup*FRACUNIT)/256 --slow down a gummed-up enemy
			if P_IsObjectOnGround(mobj) == false then
				if mobj.momz ~= 0 or mobj.momy ~= 0 then
					P_Thrust(mobj, mobj.angle, (-mobj.gummedup*FRACUNIT/16)) --slow down airborne enemies
				end
				if not (mobj.flags & MF_NOGRAVITY) then
					P_SetObjectMomZ(mobj, (-mobj.gummedup*FRACUNIT/16), true) --force jumping enemies down towards the ground
				end
			end
		end
	end
end, MT_NULL)

addHook("MobjMoveCollide", function (brakgoop, thing)
	if brakgoop and brakgoop.valid
	and thing and thing.valid then
		if thing == brakgoop.target then
			return false
		end
		
		if (thing.flags & MF_ENEMY) or (thing.flags & MF_BOSS) then
			thing.gummedup = $ + 2
			if thing.tics > 0 then
				thing.tics = $ + 4 --delay target's next action
			end
			thing.movecount = $ + 4 --delay target's next action
			thing.reactiontime = $ + 4 --delay target's next action
			thing.threshold = $ + 4 --delay target's next action
		end
	end
end, MT_BLACKEGGMAN_GOOPFIRE)