/*
	--CODE TODO
	-[done]afterimages. not pt, antone blast :)
	-[done]wavedashing lol (nick wants this)
	-fix up hammer blast hitbox (uughghhh)
	-[done]combo stuff (ghiugdjk)
	-erm, death messages
	-[done]make sure stuff slike clutch works in nonfriendly w/o ff
	-[done]hide hud in specialstages
	-[done]alt yellow for combo meter
	-do hud styles like modernsonic and toggling like mrce
	-[done]add sunstroke. already got the texasarea net
	-[done]port hud stuff to customhud
	-give spikeballs a deathstate
	-make freezing actually kill you
	-freeze combo while finished in pizza time
	-[done]movecollide for springs to keep momentum (booster boost)
	-[done]stupid thinkframe for detecting PF_SLIDING
	
*/



//from clairebun
local function L_ZCollide(mo1,mo2)
	if mo1.z > mo2.height+mo2.z then return false end
	if mo2.z > mo1.height+mo1.z then return false end
	return true
end
local function collide2(me,mob)
	if me.z > (mob.height*2)+mob.z then return false end
	if mob.z > me.height+me.z then return false end
	return true
end
//lazy
local function spawnragthing(tm,t)
	SpawnRagThing(tm,t)
end
local function LaunchTargetFromInflictor(type,target,inflictor,basespeed,speedadd)
	if (string.lower(type) == "instathrust") or type == 1
		P_InstaThrust(target, R_PointToAngle2(inflictor.x, inflictor.y, target.x, target.y), basespeed+(speedadd))
	else
		P_Thrust(target, R_PointToAngle2(inflictor.x, inflictor.y, target.x, target.y), basespeed+(speedadd))
	end
end


addHook("PlayerThink", function(p)
	if not p
	or not p.valid
		return
	end
	
	if not p.takistable
		TakisInitTable(p)
		return
	end
	
	if not p.takistable.io.loaded
		TakisLoadStuff(p)
	end
	
	if ((p.mo) and (p.mo.valid))
		local me = p.mo
		local takis = p.takistable
		
		if (not p.exiting)
		and takis.camerascale
			p.camerascale = takis.camerascale
			takis.camerascale = nil
		end
		
		TakisButtonStuff(p,takis)
		TakisBooleans(p,me,takis,TAKIS_SKIN)
		//more accurate speed thing
		takis.accspeed = FixedDiv(abs(FixedHypot(p.rmomx,p.rmomy)), me.scale)
		takis.gravflip = P_MobjFlip(me)
		
		if me.skin == TAKIS_SKIN
		
			//if something youre looking for isnt here, theres a good
			//chance that its in shorts!
			TakisDoShorts(p,me,takis)
			
			//forced strafe
			if takis.io.nostrafe == 0
			and (takis.notCarried)
			and not (p.pflags & PF_SPINNING)
			
				p.drawangle = me.angle
			end
			
			takis.afterimaging = 0
			takis.applyfriction = true
			
			//add ffoxD's FFDMomentum here because its awesome
			if (p.cmd.forwardmove or p.cmd.sidemove)
			and FixedDiv(p.normalspeed,me.scale) <= takis.accspeed
			and me.friction < FU
				me.friction = FU
			end
			
			if me.friction > 29*FU/32
				if not (leveltime % 4)
				and takis.onGround
				and not p.powers[pw_sneakers]
					me.friction = $-(FU/50)
				end
			end
			
			//spin specials
			if takis.use > 0
				
				//clutch
				if takis.use == 1
				and takis.onGround
				and not takis.taunttime
				and me.health
				and (me.state ~= S_PLAY_GASP)
				and (takis.notCarried)
				and (me.sprite2 ~= SPR2_PAIN)
				and not PSO
				and not (takis.yeahed)
				and (p.realtime > 0)
					S_StartSoundAtVolume(me,sfx_clutch,255/2)
					if not takis.clutchingtime
						S_StartSoundAtVolume(me,sfx_cltch2,255/2)
					end
					
					p.pflags = $ &~PF_SPINNING
					takis.clutchingtime = 1
					//print(takis.clutchtime)
					
					local thrust = FixedMul(FixedMul( (4*FU), (takis.clutchcombo*FU)/2 ),me.scale)
					
					//not too fast, now
					if thrust >= 13*me.scale
						thrust = 13*me.scale
					end
					
					//clutch boost
					if (takis.clutchtime > 0)
						if (takis.clutchtime <= 11)
							//if takis.clutchcombo > 1
							
								takis.clutchcombo = $+1
								takis.clutchcombotime = 2*TR
								
								S_StartSoundAtVolume(me,sfx_kc5b,255/3)
								
								//effect
								local ghost = P_SpawnGhostMobj(me)
								ghost.scale = 3*me.scale/2
								ghost.destscale = FixedMul(me.scale,2)
								ghost.colorized = true
								ghost.frame = $|TR_TRANS10
								ghost.blendmode = AST_ADD
								for i = 0, 4 do
									P_SpawnSkidDust(p,25*me.scale)
								end
								
								P_Thrust(me,p.drawangle,3*me.scale/2)
								thrust = $+(3*me.scale/2)+(me.scale)
							//end
						//dont thrust too early, now!
						elseif takis.clutchtime > 16
							
							takis.clutchcombo = 0
							takis.clutchcombotime = 0
							thrust = me.scale/5
							
						end
					end
					
					for i = 0, 10 do
						P_SpawnSkidDust(p,15*me.scale)
					end
					
					if p.powers[pw_sneakers]
						thrust = $*9/5
					end
					
					if p.gotflag
						thrust = $/2
					end
					
					local  ang = (p.cmd.angleturn << 16) + R_PointToAngle2(0, 0, p.cmd.forwardmove << 16, -p.cmd.sidemove << 16)
					
					P_Thrust(me,/*p.drawangle*/ang,thrust)
					
					if takis.accspeed < skins[me.skin].runspeed
						P_Thrust(me,p.drawangle,FixedMul(skins[me.skin].runspeed-takis.accspeed,me.scale))
					end
					
					//TODO replace with clutchstart
					me.state = S_PLAY_RUN
					P_MovePlayer(p)
					takis.clutchtime = 23
					
				end
				
				//hammer blast
				if takis.use == (TR/4)
				and not takis.onGround
				and not takis.hammerblastdown
				and me.state ~= S_PLAY_PAIN
				and me.health
				and (takis.notCarried)
				and not takis.wavedashcapable
					S_StartSoundAtVolume(me,sfx_airham,3*255/5)
					takis.hammerblastdown = 1
					p.pflags = $|PF_THOKKED
					takis.thokked = true
					P_DoJump(p,false)
					//todo: replace with vanilla melee states!
					me.state = S_PLAY_MELEE
					me.tics = -1
					//P_SetObjectMomZ(me,-9*FU)
				end
				
				//wavedash
				if takis.c3 == 1
				and takis.use < 13
				and takis.wavedashcapable
					p.pflags = $ &~(PF_JUMPED)
					P_SetObjectMomZ(me,-8*FRACUNIT)
					local ang = (p.cmd.angleturn << 16) + R_PointToAngle2(0, 0, p.cmd.forwardmove << 16, -p.cmd.sidemove << 16)
					S_StartSoundAtVolume(me,sfx_takdiv,255/4)
					P_Thrust(me,ang,14*me.scale)
				end
				
				
			end
			
			//c1 specials
			if takis.c1 > 0
				
				//dive
				//not to be confused with soap's dive!
				//mario dive
				if takis.c1 == 1
				and not takis.onGround
				and not (takis.dived)
				and (takis.notCarried)
				and me.state ~= S_PLAY_PAIN
				and me.health
				and not takis.hammerblastdown
				and not PSO
				
					takis.hammerblastjumped = 0
				
					local ang = (p.cmd.angleturn << 16) + R_PointToAngle2(0, 0, p.cmd.forwardmove << 16, -p.cmd.sidemove << 16)
					S_StartSound(me,sfx_takdiv)
					
					//im not sure if this actually does anything
					//but it seems to work so im leaving it
					if ((me.flags2 & MF2_TWOD)
					or (twodlevel))
						if (p.cmd.sidemove > 0)
							ang = p.drawangle
						elseif (p.cmd.sidemove < 0)
							ang = InvAngle(p.drawangle)
						end
					end
					
					P_InstaThrust(me,ang,FixedMul(20*FU+(3*takis.accspeed/5),me.scale))
					
					p.drawangle = ang
					CreateWindRing(p,me)

					p.pflags = $|PF_THOKKED &~(PF_JUMPED)
					takis.dived = true
					takis.thokked = true
					
					me.state = S_PLAY_FLOAT_RUN
					P_SetObjectMomZ(me,7*FU)
				end
				
			end
			
			//taunts lol!!
			if ((takis.tossflag > 0) and ((takis.c2 > 0) or (takis.c3 > 0)))
			and takis.onGround
			and p.panim == PA_IDLE
			and takis.taunttime == 0
			and not takis.yeahed
				if ((takis.c2) and (not takis.c3))
					takis.taunttime = 24
					takis.tauntid = 1
					S_StartAntonOw(me)
				elseif ((takis.c3) and (not takis.c2))
					takis.taunttime = 12
					takis.tauntid = 2
					takis.tauntspecial = P_RandomChance(FRACUNIT/10)
					S_StartSound(me,sfx_tawhip)
				end
			end
			
			//c2 specials
			if takis.c2 > 0
			
				//slide
				if takis.c2 == 1
				and takis.onGround
				and not (p.pflags & PF_SPINNING)
				and takis.taunttime == 0
				and not takis.yeahed
				and (p.realtime > 0)
					S_StartSound(me,sfx_eeugh)
					P_InstaThrust(me,p.drawangle,20*FU+FixedMul(3*takis.accspeed/5,me.scale))
					me.state = S_PLAY_TAKIS_SLIDE
					p.pflags = $|PF_SPINNING
					P_MovePlayer(p)
					if not ((p.cmd.forwardmove) and (p.cmd.sidemove))
					and takis.accspeed < 13*FU
						takis.slidetime = max(1,$)
						P_InstaThrust(me,p.drawangle,15*FU)
					end
					
				end
				
				//shield ability
				//team new
				if takis.c2 == 1
				and not takis.onGround
				and not (p.pflags & (PF_SHIELDABILITY|PF_THOKKED))
				and (p.pflags & PF_JUMPED)
				and p.powers[pw_shield] ~= SH_NONE
					TakisTeamNewShields(p)
				end
				
			end
			
			//c3 specials
			if (takis.c3 > 0)
				
				if takis.c3 == 1
					if (P_RandomChance(10))
						P_DamageMobj(me,nil,nil,1,DMG_INSTAKILL)
					end
					if P_RandomChance(1)
					and (takis.isSinglePlayer)
						G_ExitLevel()
					end
					if P_RandomChance(FU/70)
						if takis.HUD.funny.tics == 0
							S_StartSound(nil,sfx_jumpsc,p)
							takis.HUD.funny.tics = 3*TR
							takis.HUD.funny.y = 400*FU
							takis.HUD.funny.alsofunny = P_RandomChance(FU/10)
						end
					end
				end
			end
			
			if takis.taunttime > 0
				takis.stasistic = 1
				
				
				//taunt anims
				if me.health
					if takis.tauntid == 1
						me.state = S_PLAY_PAIN
					elseif takis.tauntid == 2
						if not takis.tauntspecial
							me.state = S_PLAY_TAKIS_SMUGASSGRIN
						else
							me.state = S_PLAY_TAKIS_SMUGASSGRIN2
						end
						if me.tics == -1
							me.tics = 12
						end
					end
				end
				takis.taunttime = $-1
			else
				takis.tauntid = 0
				if me.state == S_PLAY_TAKIS_SMUGASSGRIN
				or me.state == S_PLAY_TAKIS_SMUGASSGRIN2
					me.tics = 1
				end
			end
			
			//stuff to do while in pain
			if takis.inPain
				takis.hammerblastjumped = 0
			end
			if me.sprite2 == SPR2_PAIN
				me.frame = (leveltime%4)/2
			end


			
			if (p.pflags & PF_JUMPED) and not (takis.thokked)
			and me.state == S_PLAY_JUMP
				takis.thokked = false
				takis.dived = false
				takis.jumptime = $+1
			else
				takis.jumptime = 0
			end
			if takis.jumptime > 0
				if takis.jumptime < 11
				and p.pflags & PF_JUMPDOWN
					takis.wavedashcapable = true
				else
					takis.wavedashcapable = false
				end
			else
				takis.wavedashcapable = false
			end
			
			//hammerblast stuff
			if takis.hammerblastdown
				p.charflags = $ &~SF_RUNONWATER
				
				takis.hammerblastjumped = 0
				if takis.hammerblastdown == 1
					P_SetObjectMomZ(me,12*FU)
					takis.hammerblastwentdown = false
				end
				
				takis.thokked,takis.dived = true,true
				
				if me.momz < (8*me.scale)*takis.gravflip
				or takis.hammerblastwentdown == true
					
					local x = cos(p.drawangle)
					local y = sin(p.drawangle)
					
					if takis.hammerblastwentdown == false
						takis.hammerblasthitbox = P_SpawnMobjFromMobj(me,32*x,32*y,0,MT_TAKIS_HAMMERHITBOX)
						takis.hammerblasthitbox.parent = me
						//takis.hammerblasthitbox.flags2 = $|MF2_DONTDRAW
					end
					
					me.momz = $-((3*me.scale/2)*takis.gravflip)		
					takis.hammerblastwentdown = true

				end
				
				if takis.hammerblasthitbox
				and takis.hammerblasthitbox.valid
					local x = cos(p.drawangle)
					local y = sin(p.drawangle)
					
					P_MoveOrigin(takis.hammerblasthitbox,me.x+(32*x)+me.momx,me.y+(32*y)+me.momy,me.z-(3*me.height/2))
				end
				
			/*	local dist = 15*me.scale
				searchBlockmap("objects", TakisHammerSearch, me,
					me.x-dist, me.x+dist,
					me.y-dist, me.y+dist
				)
			*/	
				takis.hammerblastdown = $+1
				
				//cancel conds.
				if not (takis.notCarried)
					
					if ((takis.hammerblasthitbox) and (takis.hammerblasthitbox.valid))
						P_RemoveMobj(takis.hammerblasthitbox)
						takis.hammerblasthitbox = nil
					end
					takis.hammerblastdown = 0
					
				elseif me.eflags & MFE_SPRUNG
					if ((takis.hammerblasthitbox) and (takis.hammerblasthitbox.valid))
						P_RemoveMobj(takis.hammerblasthitbox)
						takis.hammerblasthitbox = nil
					end
					takis.hammerblastdown = 0

					S_StartSound(me, sfx_sprong)
					if (me.momz*takis.gravflip) > 0
						me.momz = 3*abs($)/2
					elseif (me.momz*takis.gravflip) < 0
						me.momz = 3*(-abs($))/2
					end
					
					me.momx = 4*$/3
					me.momy = 6*$/3
					me.state = S_PLAY_SPRING
					p.pflags = $ &~(PF_JUMPED|PF_THOKKED)
					takis.thokked = false
					takis.dived = false
					
				elseif not me.health
				or takis.inPain
				or not (takis.notCarried)
				
					if ((takis.hammerblasthitbox) and (takis.hammerblasthitbox.valid))
						P_RemoveMobj(takis.hammerblasthitbox)
						takis.hammerblasthitbox = nil
					end
					takis.hammerblastdown = 0
					
				end
				
				takis.dontlanddust = true
				if takis.onGround
					me.state = S_PLAY_MELEE_FINISH
					if ((takis.hammerblasthitbox) and (takis.hammerblasthitbox.valid))
						P_RemoveMobj(takis.hammerblasthitbox)
						takis.hammerblasthitbox = nil
					end
					
					//dust effect
					if not (me.eflags & MFE_TOUCHWATER)
						for i = 0, 16
							local mt = MT_SPINDUST
							if me.eflags & MFE_UNDERWATER
								mt = MT_MEDIUMBUBBLE
							end

							local radius = me.scale*16
							local fa = (i*ANGLE_22h)
							local x = cos(me.angle)
							local y = sin(me.angle)
							local dust = P_SpawnMobjFromMobj(me,25*x,25*y,0,mt)
							dust.momx = FixedMul(sin(fa),radius)
							dust.momy = FixedMul(cos(fa),radius)
							dust.destscale = dust.scale/2
						end
					end
	
					S_StartSoundAtVolume(me, sfx_pstop,4*255/5)
					DoQuake(p,me.scale*16,10,37*me.scale)
					TakisBreakAndBust(p,me)
					
					//holding jump while landing? boost us up!
					if takis.jump > 0
					and me.health
						takis.hammerblastjumped = 1
						P_DoJump(p,false)
						me.state = S_PLAY_ROLL
						me.momz =  (7*$/4)+((takis.hammerblastdown*takis.gravflip/6)*me.scale)
						if (takis.inGoop)
							me.momz = $+( 22*me.scale + ((takis.hammerblastdown*takis.gravflip/8)*me.scale))*takis.gravflip
						end
						S_StartSoundAtVolume(me,sfx_kc52,180)
					
					//holding spin while landing? boost us forward!
					elseif (takis.use > 0)
					and me.health
						S_StartSound(me,sfx_cltch2)
						
						//snap to ground
						local posz = me.floorz
						
						if (takis.gravflip == -1)
							posz = me.ceilingz
						end
						me.z = posz
						 
						
						me.state = S_PLAY_RUN
						
						takis.clutchingtime = 0
						takis.glowyeffects = takis.hammerblastdown/3
						
						local ang = (p.cmd.angleturn << 16) + R_PointToAngle2(0, 0, p.cmd.forwardmove << 16, -p.cmd.sidemove << 16)
						
						local thrust = (10*me.scale)+((takis.hammerblastdown*takis.gravflip*me.scale)/2)
						if (p.powers[pw_sneakers])
							thrust = $*9/5
						end
						
						P_Thrust(me,ang,thrust)
						
						//effect
						local ghost = P_SpawnGhostMobj(me)
						ghost.scale = 3*me.scale/2
						ghost.destscale = FixedMul(me.scale,2)
						ghost.colorized = true
						ghost.frame = $|TR_TRANS10
						ghost.blendmode = AST_ADD
						for i = 0, 4 do
							P_SpawnSkidDust(p,25*me.scale)
						end
						
					end
					
					takis.hammerblastdown = 0
				end
				
			end
			
			if takis.hammerblastjumped
				if not (takis.hammerblastjumped % 6)
					S_StartSoundAtVolume(me,sfx_airham,3*255/5)
				end
				takis.hammerblastjumped = $+1
				if takis.hammerblastjumped == (6*7)
					takis.hammerblastjumped = 0
				end
			end
			
			if takis.clutchingtime 
				takis.clutchingtime= $+1
				takis.afterimaging = 1
				p.charflags = $|SF_CANBUSTWALLS
				
				if (takis.accspeed >= skins[TAKIS_SKIN].normalspeed)
					p.charflags = $|SF_RUNONWATER
				else
					p.charflags = $ &~SF_RUNONWATER
				end
				
				if not (p.pflags & PF_SPINNING)
					TakisCreateAfterimage(p,me)
				end
				
				p.runspeed = takis.accspeed-me.scale		

			else
				p.charflags = $ &~(SF_CANBUSTWALLS|SF_RUNONWATER)
				p.runspeed = 58*me.scale			
			end
			
			//stuff to do while grounded
			if takis.onGround
				if (p.pflags & PF_SHIELDABILITY)
				and (p.powers[pw_shield] == SH_BUBBLEWRAP)
					P_DoBubbleBounce(p)					
				end
				
				takis.inFakePain = false
				
				if not P_CheckDeathPitCollide(me)
					takis.timesdeathpitted = 0
				end
				if p.pflags & PF_SPINNING
				and takis.accspeed >= 10*FU
				and (me.state == S_PLAY_TAKIS_SLIDE)
					P_SpawnSkidDust(p,8*me.scale+( FixedMul(takis.accspeed-(10*FU),me.scale)*4/5 ),sfx_s3k64)
					if takis.accspeed >= 40*FU
						P_SpawnSkidDust(p,3*me.scale+( FixedMul(takis.accspeed-(10*FU),me.scale)*3/5 ))
					end
					P_ButteredSlope(me)
					takis.clutchingtime = $-2
				end
				takis.dived = false
				if takis.hammerblastjumped >= 3
					takis.hammerblastjumped = 0
				end
				if not ((me.eflags & MFE_TOUCHWATER) and not ((me.eflags & MFE_UNDERWATER) or (P_IsObjectInGoop(me))))
					takis.lastgroundedpos = {me.x,me.y,me.z}
				end
				takis.thokked = false
				//footsteps
				if me.state == S_PLAY_WALK
					if ((me.frame == A) or (me.frame == E))
						if not takis.steppedthisframe
							S_StartSound(me,P_RandomRange(sfx_takst1,sfx_takst3))
							takis.steppedthisframe = true
						end
					else
						takis.steppedthisframe = false
					end
				else
					takis.steppedthisframe = false
				end
				if me.eflags & MFE_JUSTHITFLOOR
				and not P_CheckDeathPitCollide(me)
				and me.health
					S_StartSound(me,sfx_takst4)
					if (takis.dontlanddust == false)
						for i = 0, 8
							local mt = MT_SPINDUST
							if me.eflags & MFE_UNDERWATER
								mt = MT_MEDIUMBUBBLE
							end
							local radius = me.scale*16
							local fa = (i*ANGLE_45)
							local dust = P_SpawnMobjFromMobj(me,0,0,0,mt)
							local mz = takis.prevmomz/10
							dust.momx = FixedMul(FixedMul(sin(fa),radius),mz)
							dust.momy = FixedMul(FixedMul(cos(fa),radius),mz)
							dust.destscale = dust.scale/2
						end
					end
				end
			end
			takis.prevmomz = me.momz
			
			if takis.hurtfreeze > 0
				me.momx,me.momy,me.momz = 0,0,0
				p.powers[pw_flashing] = 3
				if takis.hurtfreeze <= TR
					if not (leveltime % 2)
						me.flags2 = $|MF2_DONTDRAW
					else
						me.flags2 = $ &~MF2_DONTDRAW
					end
				end
				
				if takis.hurtfreeze == TR
					local x
					local y
					local z
					x,y,z = unpack(takis.lastgroundedpos)
					P_SetOrigin(me,x,y,z+(me.height*takis.gravflip))
				end
				
				if takis.hurtfreeze == 1
					takis.fakeflashing = flashingtics
				end
				
				takis.hurtfreeze = $-1
			end
			
			if takis.beingcrushed
				me.spriteyscale = FU/3
				me.spritexscale = FU*3
				
				//keep increasing this until it reaches
				//2*TR, kill if then
				takis.timescrushed = $+1
				
				//used to reset crushed
				takis.crushtime = TR
			else
				if not takis.crushtime
					DoTakisSquashAndStretch(p,me,takis)
				else
					local div = (takis.crushtime/8)
					div = max(1,$)
					me.spriteyscale = FU/div
					me.spritexscale = FU*div
				end
			end
			
			takis.beingcrushed = false
			
			//are we dead?
			if (not me.health)
			or (p.playerstate ~= PST_LIVE)
				
				if ((takis.body) and (takis.body.valid))
					P_MoveOrigin(takis.body,me.x,me.y,me.z)
				end
				
				TakisResetAliments(takis)
				takis.wentfast = 0
				
				//death thinker and anims are called in 
				//TakisDoShorts
				
				takis.heartcards = 0
				takis.hammerblastjumped = 0
				takis.taunttime = 0
				
				if S_SoundPlaying(me,skins[TAKIS_SKIN].soundsid[SKSPLDET3])
					S_StopSoundByID(me,skins[TAKIS_SKIN].soundsid[SKSPLDET3])
					me.sprite2 = SPR2_TDED
					for i = 1, 6
						A_BossScream(me,1,MT_SONIC3KBOSSEXPLODE)
					end
					S_StartSound(me,sfx_tkapow)
					DoQuake(p,me.scale*8,10,8*me.scale)
					takis.altdisfx = 3
				elseif S_SoundPlaying(me,skins[TAKIS_SKIN].soundsid[SKSPLDET4])
					S_StopSoundByID(me,skins[TAKIS_SKIN].soundsid[SKSPLDET4])
					me.sprite2 = SPR2_DRWN
					S_StartSound(me,sfx_takoww)
					takis.altdisfx = 4
				end
				
			elseif p.playerstate == PST_LIVE
				takis.deathanim = 0
				takis.altdisfx = 0
				takis.saveddmgt = 0
				takis.stoprolling = false
			end
			
			//heal cards
			if takis.heartcardpieces >= 7
				TakisHealPlayer(p,me,takis,1)
				S_StartSound(nil, sfx_takhel, p)
				takis.heartcardpieces = 0
			end
			
			//hiiii nick :))
			if ((PizzaTime) and (PizzaTime.PizzaTime))
			and not (p.pt_mode.pizzaface)
				takis.HUD.timer.int = {90-(13*6)+75+15, (62-6)+4+8}	
			end
			
			//handle combo stuff here
			if takis.combo.time ~= 0
				if not (takis.notCarried)
				or ((p.pflags & PF_STASIS) and not (takis.taunttime and takis.tauntid))
				or (takis.hurtfreeze ~= 0)
					takis.combo.frozen = true
				else
					takis.combo.time = $-1
					takis.combo.frozen = false
				end
				
				if takis.combo.time > TAKIS_MAX_COMBOTIME	
					takis.combo.time = TAKIS_MAX_COMBOTIME
				end
				
				takis.combo.outrotics = 0
				
				takis.combo.verylevel = takis.combo.count/(#TAKIS_COMBO_RANKS*TAKIS_COMBO_UP)
				
				if takis.combo.time <= TAKIS_MAX_COMBOTIME/4
					takis.HUD.combo.meter.shake = (P_RandomFixed())*3/2
				elseif takis.combo.time <= TAKIS_MAX_COMBOTIME/2
					takis.HUD.combo.meter.shake = P_RandomFixed()
				else
					if takis.HUD.combo.meter.shake > 0
						takis.HUD.combo.meter.shake = $-3
					else
						takis.HUD.combo.meter.shake = 0
					end
				end
			else
				takis.combo.frozen = false
				if takis.HUD.combo.meter.shake > 0
					takis.HUD.combo.meter.shake = $-3
				else
					takis.HUD.combo.meter.shake = 0
				end
				
				if takis.combo.count
					takis.combo.count = 0
					S_StartSound(nil,sfx_kc59,p)
					takis.combo.outrotics = 7*TR/5
				end
				
				if takis.combo.time < 0
					takis.combo.time = 0
				end
				
				takis.combo.verylevel = 0
				takis.combo.rank = 1
			end
			
			if not (takis.notCarried)
				takis.thokked,takis.dived = false,false
				takis.inFakePain = false
				if not (takis.inwaterslide)
					takis.afterimaging = false
				end
			end
			
			//this is actually stupid
			if p.exiting > 0
				takis.combo.time = 0
				
				if not takis.setmusic
				and (p.pflags & PF_FINISHED)
					S_ChangeMusic("_ABCLR", false, p)
					takis.setmusic = true
					takis.yeahwait = (2*TR)+(TR/2)+5
				end

			
				if takis.yeahwait == 0
				and (p.powers[pw_carry] ~= CR_NIGHTSMODE)
				//and (p.pflags & PF_FINISHED)
					
					if not takis.yeahed
						if p.panim == PA_IDLE
						and ((takis.onGround) or P_CheckDeathPitCollide(me))
						and takis.yeahwait == 0
							if not takis.camerascale
								takis.camerascale = p.camerascale
								p.camerascale = 28221
							end
							S_StartSound(me,sfx_tayeah)
							takis.yeahed = true
						end
					end
				end
			else		
				takis.yeahed = false
				takis.setmusic = false
				takis.yeahwait = 0
			end
			
			/*
			if takis.io.nostrafe == 0
			and (p.powers[pw_carry] ~= CR_NIGHTSMODE)
				if ((me.momx) and (me.momy))
					p.drawangle = R_PointToAngle2(0,0, me.momx,me.momy)
				end
			end
			*/
			takis.dontlanddust = false
			takis.prevspeed = takis.accspeed
		end

	end
	
end)

addHook("PlayerSpawn", function(p)
	if p.takistable
		local takis = p.takistable
		
		takis.heartcards = TAKIS_MAX_HEARTCARDS
		takis.heartcardpieces = 0
		
		takis.taunttime = 0
		takis.tauntid = 0
		
		takis.clutchingtime = 0
		
		takis.yeahed = false
		takis.yeahwait = 0
		
		takis.thokked, takis.dived = false,false
		
		takis.combo.time = 0
		
		takis.wentfast = 0
		TakisResetAliments(takis)
		
		if ((takis.body) and (takis.body.valid))
			P_KillMobj(takis.body)
			takis.body = 0
		end
		
		if ((p.mo) and (p.mo.valid))
			takis.lastgroundedpos = {p.mo.x,p.mo.y,p.mo.z}
		end
	end
end)

addHook("PlayerCanDamage", function(player, mobj)
	if not player.mo 
	or not player.mo.valid 
		return
	end
	
	if player.mo and player.mo.valid and player.mo.skin == TAKIS_SKIN
		//basically if we can do the pt afterimages
		if not player.takistable
			return
		end
		
		local me = player.mo
		
		if player.takistable.afterimaging
			
			if L_ZCollide(me,mobj)
			and (mobj.flags & MF_ENEMY)
			//and (mobj.type ~= MT_ROSY)
			and (mobj.type ~= MT_SHELL)
				
				//prevent killing blow sound from mobjs way above/below us
				
				local bam = P_SpawnMobjFromMobj(mobj,0,0,0,MT_TNTDUST)
				bam.state = mobjinfo[MT_MINECART].deathstate 
				
				//P_KillMobj(mobj, me, me) //actually kill the thing. looking at you, lance-a-bots!
				
				spawnragthing(mobj,me)
				return true
				
			end
			
		end
	end
end)

addHook("MobjDamage", function(mo,inf,sor,_,dmgt)
	if not mo
	or not mo.valid
		return
	end
	
	if mo.player.takistable.inFakePain
		return true
	end

	if ((mo.player.powers[pw_flashing])
	and (mo.player.powers[pw_carry] == CR_NIGHTSMODE))
		return
	end

	if mo.player.deadtimer > 10
		return
	end
	
	if mo.skin ~= TAKIS_SKIN
		return
	end

	//BUT!!
	if mo.player.takistable.accspeed >= 60*FU
	and mo.player.takistable.afterimaging
		return true
	end
	
	if mo.health
	or ((mo.player.takistable.heartcards)
	or ((mo.player.takistable.heartcards == 0) and (p.rings)))
		S_StartAntonOw(mo)
	end

	if mo.player.powers[pw_carry] == CR_NIGHTSMODE
		return
	end
	
	if dmgt == DMG_FIRE
		TakisResetAliments(mo.player.takistable,"freezing")
	end
	
	if mo.player.takistable.heartcards > 0
	and (mo.player.powers[pw_shield] == SH_NONE)
	
	if not P_IsObjectOnGround(mo)
	and mo.player.powers[pw_carry] == 0
		mo.player.takistable.hurtfreeze = TR*2
		/*
		local x,y,z = unpack(mo.player.takistable.lastgroundedpos)
		local ang = R_PointToAngle2(mo.x,mo.y, x,y)
		P_Thrust(mo,ang,FixedHypot(x,y))
		P_SetObjectMomZ(mo,mo,z-z)
		*/
		mo.player.powers[pw_flashing] = 3*TR/5
		mo.player.takistable.ticsforpain = TR*2
	end		
	
	
	mo.player.powers[pw_flashing] = TR
	mo.player.takistable.ticsforpain = TR
	S_StartSound(mo,sfx_shldls)
	if (dmgt & DMG_SPIKE)
		S_StartSound(mo,sfx_spkdth)
	end
	TakisHealPlayer(mo.player,mo,mo.player.takistable,3)
	mo.player.timeshit = $+1
	
	if P_IsObjectOnGround(mo)
		if inf
		and inf.valid
			local ang = R_PointToAngle2(mo.x,mo.y, inf.x, inf.y)
			P_InstaThrust(mo,ang,-9*mo.scale)
		end
		P_SetObjectMomZ(mo,14*mo.scale)
	end
	mo.state = S_PLAY_PAIN
	mo.player.takistable.inFakePain = true
	return true
	
	end
	
end,MT_PLAYER)

addHook("MobjDamage", function(tar,inf,src)
	if not tar
	or not tar.valid
		return
	end
	
	if not src
	or not src.valid
		return
	end
	
	if src.player
	and src.skin == TAKIS_SKIN
	and src.player.takistable.combo.time
		for i = 0,2
			TakisGiveCombo(src.player,src.player.takistable,false,false)
		end
	end
end,MT_PLAYER)	
//enemy knockback
local function stopmom(takis,me,ang)
	if takis.accspeed < (6*skins[TAKIS_SKIN].normalspeed/5)
	and (me.player.powers[pw_invulnerability] == 0)
		me.momx,me.momy = 0,0
		P_SetObjectMomZ(me,6*me.scale)
		P_Thrust(me,ang,-6*me.scale)
	end
end

local function knockbacklolll(t,tm)
	if not t
	or not t.valid
		return
	end
	
	if not tm
	or not tm.valid
		return
	end
	
	if not L_ZCollide(t,tm)
		return
	end
	
	local p = t.player
	local takis = p.takistable
	local me = p.mo
	
	//BUT.....
	if t.skin ~= TAKIS_SKIN
		return
	end

	if tm.parent == t
		return false
	end
	
	local takis = t.player.takistable
	
	local ff = CV_FindVar("friendlyfire").value

	//is this a player we're running into?
	if tm.type == MT_PLAYER
		if t.skin == TAKIS_SKIN
			if (tm.player.takistable.accspeed < 60*FU)
				//are we both afterimaging?
				if ((takis.afterimaging) and (tm.player.takistable.afterimaging))
					//heartcard priority
					if takis.heartcards > tm.player.takistable.heartcards
						if CanPlayerHurtPlayer(p,tm.player)
							local ang = R_PointToAngle2(t.x,t.y, tm.x,tm.y)
							stopmom(takis,me,ang)
							
							P_DamageMobj(tm,t,t)

							local bam = P_SpawnMobjFromMobj(tm,0,0,0,MT_TNTDUST)
							bam.state = mobjinfo[MT_MINECART].deathstate  

							S_StartSound(tm,sfx_smack)
							
							ang = R_PointToAngle2(tm.x,tm.y, t.x,t.y)
							if tm.health
								P_Thrust(tm,ang,-6*me.scale)
								P_MovePlayer(tm.player)
							end
						end
					//port priority
					//melee reference !!
					elseif #p < #tm.player
						if CanPlayerHurtPlayer(p,tm.player)
							local ang = R_PointToAngle2(t.x,t.y, tm.x,tm.y)
							stopmom(takis,me,ang)
							
							P_DamageMobj(tm,t,t)

							local bam = P_SpawnMobjFromMobj(tm,0,0,0,MT_TNTDUST)
							bam.state = mobjinfo[MT_MINECART].deathstate  

							S_StartSound(tm,sfx_smack)
							
							ang = R_PointToAngle2(tm.x,tm.y, t.x,t.y)	
							if tm.health
								P_Thrust(tm,ang,-6*me.scale)
								P_MovePlayer(tm.player)
							end
						end
					end
				elseif (takis.afterimaging)
				
					if CanPlayerHurtPlayer(p,tm.player)
						local ang = R_PointToAngle2(t.x,t.y, tm.x,tm.y)
						stopmom(takis,me,ang)
						
						P_DamageMobj(tm,t,t)

						local bam = P_SpawnMobjFromMobj(tm,0,0,0,MT_TNTDUST)
						bam.state = mobjinfo[MT_MINECART].deathstate  

						S_StartSound(tm,sfx_smack)
						
						ang = R_PointToAngle2(tm.x,tm.y, t.x,t.y)		
						if tm.health
							P_Thrust(tm,ang,-6*me.scale)
							P_MovePlayer(tm.player)
						end
					end
					
				end
			//going fast turns the other person into mush
			else
				
				//are we both afterimaging?
				if ((takis.afterimaging) and (t.player.takistable.afterimaging))
					
					//we have to be going faster than the other guy
					if takis.accspeed > tm.player.takistable.accspeed
					and CanPlayerHurtPlayer(p,tm.player)
						local bam = P_SpawnMobjFromMobj(tm,0,0,0,MT_TNTDUST)
						bam.state = mobjinfo[MT_MINECART].deathstate  

						S_StartSound(t,sfx_bsnipe)
						
						P_KillMobj(tm,t,t)
						
						LaunchTargetFromInflictor(1,t,tm,63*t.scale,takis.accspeed/5)
						P_MovePlayer(tm.player)
						
					end
				
				elseif (takis.afterimaging)
					if CanPlayerHurtPlayer(p,tm.player)
					
						local bam = P_SpawnMobjFromMobj(tm,0,0,0,MT_TNTDUST)
						bam.state = mobjinfo[MT_MINECART].deathstate  

						S_StartSound(t,sfx_bsnipe)
						
						P_KillMobj(tm,t,t)
						
						LaunchTargetFromInflictor(1,t,tm,63*t.scale,takis.accspeed/5)
						P_MovePlayer(tm.player)
					
					end
				end
				
			end
		end
		return
	end
	
	if tm.flags & (MF_ENEMY|MF_BOSS|MF_SHOOTABLE)
		if takis.afterimaging
		or p.pflags & PF_SPINNING
			local ang = R_PointToAngle2(t.x,t.y, tm.x,tm.y)
			stopmom(takis,me,ang)
			
			if not (p.pflags & PF_SPINNING)
				S_StartSound(tm,sfx_smack)
				local bam = P_SpawnMobjFromMobj(tm,0,0,0,MT_TNTDUST)
				bam.state = mobjinfo[MT_MINECART].deathstate 
				
				
				spawnragthing(tm,t)
			end
			
		end
		
	end
	
end

addHook("ShouldDamage", function(mo,inf,sor,dmg,dmgt)
	if not mo
	or not mo.valid
		return
	end
	
	if mo.skin ~= TAKIS_SKIN
		return
	end
	
	if mo.player.deadtimer > 10
		return
	end
	
	//quit camping, crawla!
	if mo.player.takistable.hurtfreeze
	or mo.player.takistable.inFakePain
		return false
	end
	
	if dmgt == DMG_DEATHPIT
		if mo.player.exiting then return end
		if TAKIS_NET.inspecialstage then return end
		if mo.player.takistable.timesdeathpitted > 5
			mo.player.takistable.saveddmgt = DMG_DEATHPIT
			return true
		end
		if mo.player.takistable.heartcards ~= 0
			if mo.player.powers[pw_flashing] == 0
				TakisHealPlayer(mo.player,mo,mo.player.takistable,3)
				mo.player.timeshit  = $+1
				S_StartAntonOw(mo)
			end
			
			mo.player.takistable.timesdeathpitted = $+1
			mo.player.takistable.hammerblastdown = 0
			if ((mo.player.takistable.hammerblasthitbox) and (mo.player.takistable.hammerblasthitbox.valid))
				P_RemoveMobj(mo.player.takistable.hammerblasthitbox)
				mo.player.takistable.hammerblasthitbox = nil
			end
			
			P_SetObjectMomZ(mo,abs(mo.player.takistable.prevmomz)*mo.player.takistable.timesdeathpitted)
			mo.state = S_PLAY_ROLL
			mo.player.pflags = $|PF_JUMPED &~(PF_THOKKED|PF_SPINNING)
			mo.player.takistable.thokked = false
			mo.player.takistable.dived = false
			mo.player.takistable.fakeflashing = flashingtics
			mo.player.takistable.HUD.statusface.painfacetic = 3*TR
			
			return false
		end
		
	elseif dmgt == DMG_CRUSHED
		if mo.player.takistable.timescrushed < TR
			mo.player.takistable.beingcrushed = true
			return false
		end
	elseif mo.player.takistable.hurtfreeze
		//crawla quit camping bruh
		return false
	end
	
end,MT_PLAYER)

local function KillSpike(spike, plmo)
    if not (plmo and plmo.valid and plmo.skin == TAKIS_SKIN) then return end
    if plmo.type ~= MT_PLAYER then return end
    if plmo.z + plmo.height < spike.z or (spike.z + (spike.height+(spike.height/2))) < plmo.z then return end

    local player = plmo.player
	
    if player.takistable.afterimaging
	or player.powers[pw_invulnerability]
	and L_ZCollide(spike,plmo)
		P_KillMobj(spike, plmo, plmo)
    end
end

addHook("MobjCollide", KillSpike, MT_SPIKE)
addHook("MobjCollide", KillSpike, MT_WALLSPIKE)
addHook("MobjCollide", KillSpike, MT_SPIKEBALL)
addHook("MobjCollide", KillSpike, MT_BOMBSPHERE)

local function hammerhitbox(t,tm)
	if not t
	or not t.valid
		return
	end
	
	if not tm
	or not tm.valid
		return
	end
	
	if tm == t.parent
		return
	end
	
	if not collide2(t,tm)
		return
	end
	
	if tm.type == MT_PLAYER
		
		if CanPlayerHurtPlayer(t.parent.player,tm.player)
			P_DamageMobj(tm,t,t.parent)
		end
	else
		
		if ((tm.type == MT_SPIKE) or (tm.type == MT_WALLSPIKE) or 
		(tm.type == MT_SPIKEBALL) or (tm.type == MT_BOMBSPHERE))
			P_KillMobj(tm,t,t.parent)
		end
		
		if tm.flags & (MF_ENEMY|MF_BOSS)
		or tm.flags & MF_MONITOR
			CONS_Printf(t.parent.player,"kill")
			P_DamageMobj(tm,t,t.parent)
			P_SetObjectMomZ(t.parent,14*t.parent.scale)
		end
		
	end
end

local function hammerhitbox2(tm,t)
	hammerhitbox(tm,t)
end

addHook("MobjCollide",hammerhitbox,MT_TAKIS_HAMMERHITBOX)
addHook("MobjMoveCollide",hammerhitbox2,MT_TAKIS_HAMMERHITBOX)

local function givecardpieces(_, _, source)
	if source
	and source.valid
	and source.player
	
		if not source
		or not source.valid
			return
		end
		
		if source
		and source.skin == TAKIS_SKIN
		and source.player
		and source.player.valid
			if source.player.takistable.heartcards ~= TAKIS_MAX_HEARTCARDS
			
				source.player.takistable.heartcardpieces = $+1
			
			end
			
			if source.player.takistable.combo.time
				TakisGiveCombo(source.player,source.player.takistable,false)
			end
			
		end
		
		
	end
end

addHook("MobjDeath", givecardpieces, MT_RING)
addHook("MobjDeath", givecardpieces, MT_COIN)
//thing died by takis
local function diedbytakis(mo,inf,sor)
	
	if not sor
	or not sor.valid
		return
	end
	
	if sor.skin ~= TAKIS_SKIN
		return
	end
	
	if mo.flags & MF_MONITOR
		if mo.type ~= MT_EGGMAN_BOX
			if mo.type == MT_1UP_BOX
			or mo.type == MT_SCORE10K_BOX
				TakisHealPlayer(sor.player,sor,sor.player.takistable,2)
			end
			if mo.type == MT_RING_BOX
				TakisHealPlayer(sor.player,sor,sor.player.takistable,1)
			end
			TakisGiveCombo(sor.player,sor.player.takistable,true)
			sor.player.takistable.HUD.statusface.happyfacetic = 3*TR/2
		end
	end
	
	if sor.player
	and sor.player.takistable
		
		if sor.player.takistable.dived
		or sor.player.takistable.thokked
			sor.player.takistable.dived = false
			sor.player.takistable.thokked = false
			sor.player.pflags = $ &~PF_THOKKED
		end
	
		if ((mo.flags & MF_ENEMY) or (mo.flags & MF_BOSS))
		or mo.type == MT_PLAYER
		or mo.type == MT_SPIKE
		or mo.type == MT_WALLSPIKE
		or mo.type == MT_SPIKEBALL
		or mo.type == MT_BOMBSPHERE
			if not mo.health
				TakisGiveCombo(sor.player,sor.player.takistable,true)
			end
			
			if mo.type == MT_PLAYER
			or (mo.flags & MF_BOSS)
			and (not mo.health)
				sor.player.takistable.HUD.statusface.evilgrintic = 2*TR
			end
		
		end
		
	end

end

addHook("MobjDeath", diedbytakis)
addHook("MobjDamage", diedbytakis)

//takis died by thing
addHook("MobjDeath", function(mo,_,_,dmgt)
	if mo.skin ~= TAKIS_SKIN
		return
	end
	
	if (mo.player.takistable.heartcards > 0)
		mo.player.takistable.HUD.heartcards.shake = $+TAKIS_HEARTCARDS_SHAKETIME
	end
	
	mo.player.takistable.combo.time = 0
	mo.player.takistable.saveddmgt = dmgt
end,MT_PLAYER)
addHook("AbilitySpecial", function(p)
	if p.takistable.thokked
		return true
	end
	
	if p.mo.skin ~= TAKIS_SKIN then return end
	
	local me = p.mo
	local takis = p.takistable
	
	S_StopSoundByID(me,skins[TAKIS_SKIN].soundsid[SKSJUMP])
//	P_DoJump(p,true)
	takis.thokked = true
	takis.hammerblastjumped = 0
	
	S_StartSoundAtVolume(me,sfx_takdjm,4*255/5)

	for i = 0, 7
		local mt = MT_SPINDUST
		if me.eflags & MFE_UNDERWATER
			mt = MT_MEDIUMBUBBLE
		end

		local radius = me.scale*16
		local fa = (i*ANGLE_45)
		local dust = P_SpawnMobjFromMobj(me,0,0,0,mt)
		dust.momx = FixedMul(sin(fa),radius)
		dust.momy = FixedMul(cos(fa),radius)
		dust.momz = -(abs(me.momz)*takis.gravflip)/2
		dust.scale = FixedDiv(me.scale,3*FRACUNIT/4)
		dust.destscale = dust.scale/3
	end
	
	P_SetObjectMomZ(p.mo,15*FU,true)
	p.mo.state = S_PLAY_JUMP
	p.pflags = $|PF_JUMPED & ~PF_SPINNING & ~PF_JUMPDOWN & ~PF_THOKKED & ~PF_STARTDASH
end)

//takis moved into a thing
//this should be used as the main movecollide hook from now on
addHook("MobjMoveCollide",function(tm,t)
	if not (tm.player or ((t) and (t.valid)))
		return
	end
	
	if (tm.skin ~= TAKIS_SKIN)
		return
	end
	
	local p = tm.player
	local takis = p.takistable
	
	if takis
		
		knockbacklolll(tm,t)
		
		//destroy these stupid doors
		if ((t.type == MT_SALOONDOOR) or (t.type == MT_SALOONDOORCENTER))
			if ((t.valid) and (t.health) and not (t.flags & MF_NOCLIP))
			and (takis.afterimaging)
				S_StartSound(t,sfx_wbreak)
				S_StartSound(t,sfx_s3k59)

				local bam = P_SpawnMobjFromMobj(t,0,0,0,MT_TNTDUST)
				bam.state = mobjinfo[MT_MINECART].deathstate 
				
				if (t.type == MT_SALOONDOOR)
					t.flags = $|MF_NOCLIP
					TakisGiveCombo(p,takis,true)
					P_KillMobj(t, tm, tm)
				//waht !??
				elseif (t.type == MT_SALOONDOORCENTER)
					t.flags = $|MF_NOCLIP
				end
				
				return false
			end
		//springs keep our momentum!
		//only horizontal springs
		elseif (t.flags & MF_SPRING)
		and L_ZCollide(t,tm)
			if ((mobjinfo[t.type].mass == 0) and (mobjinfo[t.type].damage > 0))
				P_InstaThrust(tm,t.angle,takis.prevspeed+mobjinfo[t.type].damage)
				tm.angle,p.drawangle = t.angle,t.angle
				tm.eflags = $|MFE_SPRUNG
				takis.fakesprung = true
				
				S_StartSound(t,mobjinfo[t.type].painsound)
				t.state = mobjinfo[t.type].raisestate
				return false
			end
		end
	end
end,MT_PLAYER)