//Wallrun and walljump by Appleblurt, modified by Trystan

//SILVER: ughahhghhhhhhh ok let's get started
//i REALLY hated wallrunning the first time i played this, it felt so unresponsive and inconsistent and it was slow
//as ALL hell.

//it was a cool novelty, i guess? but that's all it was! a novelty! nothing i could ever consider actually using!!!
//what i personally would do is make it a lot faster. emphasise horizontal traversal, make it a wallRUN instead of a
//wallCLIMB. i understand that this strays away from lost world's design philosophy but...lost world was rated poorly
//for a REASON lol
//SNONI: STINKY CODE XXDXDXDXDXDXDDXDXDXDDXDXDXXDXDXDDXDXXDD

addHook("ThinkFrame", do
	for player in players.iterate
		if (player.mo and player.mo.skin == "hypermetal")
			
			//if not (player.atwall)
				player.atwall = 0
			//end
			if not (player.cling)
				player.cling = false
			end
			if player.mo.wallrun == nil // too lazy to rename it check!
				player.mo.wallrun = 0
			end
			if not (player.clingprev)
				player.clingprev = false
			end
			if player.playerstate == PST_DEAD return end
			if player.mo.wallrun == 3*TICRATE return end
			if (player.mo) //Fixes spectating, and possibly other things
				//Finding walls (not FOFs)
				local wall = R_PointInSubsector(player.mo.x+FixedMul(48*FRACUNIT, cos(player.mo.angle)), player.mo.y+FixedMul(48*FRACUNIT, sin(player.mo.angle))).sector
				local fheight = wall.floorheight
				local cheight = wall.ceilingheight

				if wall.f_slope then
					fheight = P_GetZAt(wall.f_slope, player.mo.x + player.mo.momx, player.mo.y + player.mo.momy)
				end
				if wall.c_slope then
					cheight = P_GetZAt(wall.c_slope, player.mo.x + player.mo.momx, player.mo.y + player.mo.momy)
				end
				
				if (fheight > player.mo.z) or ((cheight <= player.mo.height+player.mo.z) and not (fheight == cheight)/* and (wall.ceilingpic == "F_SKY1")*/) //This last bit seems to be broken...
					player.atwall = 1
				end
				//FOFs can be walls too, so lets check for those
				for wall in wall.ffloors()
					if (player.mo.z <= wall.topheight) and (player.mo.height+player.mo.z > wall.bottomheight)
						and(wall.flags & FF_BLOCKPLAYER) //Don't want the player to cling to water. That would be stupid
						player.atwall = $1 + 1
					end		
				end
				if(player.atwall <= 0)
					if (player.cling)
						player.pflags = $1&~PF_JUMPED
						player.mo.state = S_PLAY_SPRING
					end
					player.cling = false
				end	
				if (P_IsObjectOnGround(player.mo))
					player.cling = false
				end	
				//This allows sonic to thok away from a wall. You can remove this if you dont want your character to do this.
				//Lazy checks
				if (player.powers[pw_carry] == CR_NONE)
				and not (player.pflags & PF_THOKKED) 
				and not (player.charability2 == CA2_MULTIABILITY)
					//If you're clinging to a wall
					if (player.cling)
					and (player.cmd.buttons & BT_CUSTOM1)
						if (player.powers[pw_underwater])
							P_SetObjectMomZ(player.mo, 10*FRACUNIT)
						else
							P_SetObjectMomZ(player.mo, 15*FRACUNIT)
						end
						S_StartSound(player.mo, sfx_jump)
						player.cling = false
						if (player.charability2 == CA2_SPINDASH)
							player.mo.state = S_PLAY_SPRING //L
						else
							player.mo.state = S_PLAY_SPRING //P
						end
						player.jumping = false
						P_InstaThrust(player.mo, player.mo.angle, player.actionspd/3) //Devided by 3 for sonic, but you can remove this for your character
						player.mo.angle = R_PointToAngle2(0, 0, player.mo.momx, player.mo.momy)
					end
					if (player.mo and player.mo.valid) and P_IsObjectOnGround(player.mo)
					player.wallruntimer = 105
					end
					if player.cling == true
						and not player.powers[pw_super]
		                player.wallruntimer = $-1
	                end
					//Cling onto a wall
					if (player.atwall > 0)					
					and (((player.mo.momz < -2*FRACUNIT+1) and not (player.mo.flags2 & MF2_OBJECTFLIP)) or ((player.mo.momz > 2*FRACUNIT-1) and (player.mo.flags2 & MF2_OBJECTFLIP)))
					and (player.wallruntimer > 0)
					and not (player.exiting)	
					and (player.pflags & PF_JUMPDOWN)
					    P_SetObjectMomZ(player.mo, 4  *FRACUNIT)
						P_SpawnGhostMobj(player.mo)
						player.mo.state = S_PLAY_CLIMB //F
						player.cling = true
						if (player.clingprev == false)
							S_StartSound(player.mo,sfx_s3k4a)
						end
						if not (S_SoundPlaying(player.mo,sfx_s3k7e))
							S_StartSound(player.mo, sfx_s3k7e)
						end
					end
				end
				//Movement fix
				if (player.cling)
					player.normalspeed = 0
				else 
					player.normalspeed = 36*FRACUNIT
				end
				player.clingprev = player.cling		
				end
				if player.mo.skin == "hypermetal"
				and player.mo.state == S_PLAY_CLIMB
				    player.mo.wallrun = 35*TICRATE
					if not player.powers[pw_super]
						P_SetObjectMomZ(player.mo, 6*FRACUNIT)
					else
						P_SetObjectMomZ(player.mo, 12*FRACUNIT)
					end
					local ghost = P_SpawnGhostMobj(player.mo)
					ghost.colorized = true
				end
				if player.mo.wallrun == 3*TICRATE
				and player.mo.skin == "hypermetal"
					player.mo.state = S_PLAY_SPRING
					player.cling = 0
					player.pflags = $1|PF_THOKKED
				end
				if player.mo.state == S_PLAY_CLIMB
				and player.mo.wallrun == 3*TICRATE
				and (player.pflags & PF_JUMPDOWN)
				player.mo.state = S_PLAY_SPRING
				player.pflags = $1|PF_THOKKED
				player.mo.wallrun = 35*TICRATE
			end		
		end
	end
end)