gamevar ai_tsprpicnum 0 2
onevent EVENT_ANIMATESPRITES
	gettspr[THISACTOR].tsprpicnum ai_tsprpicnum
endevent

gamevar ai_hitwall 0 2
gamevar ai_hitsprite 0 2
gamevar ai_hitsector 0 2
gamevar ai_hitx 0 2
gamevar ai_hity 0 2
gamevar ai_hitz 0 2


/*
	ain1 = x1
	ain2 = y1
	ain3 = x2
	ain4 = y2
*/
state qdist
	subvarvar ain3 ain1 //dx
	subvarvar ain4 ain2 //dy
	
	ifvarl ain3 0 mulvar ain3 -1 //abs(dx)
	ifvarl ain4 0 mulvar ain4 -1 //abs(dy)
	
	ifvarvarg ain3 ain4 {
		mulvar ain4 3
		shiftvarr ain4 3
	} else {
		mulvar ain3 3
		shiftvarr ain3 3
	}
	
	setvarvar RETURN ain3
	addvarvar RETURN ain4
ends

gamevar ztop 0 0
gamevar zbot 0 0

/*
	USING:
		tmp
		tmp2
		tmp3
		picnum
		yrepeat
		yoffset
*/

state GetSpriteExtents

	setvarvar ztop sprite[THISACTOR].z
	setvarvar zbot sprite[THISACTOR].z

	getactor[THISACTOR].cstat tmp
	andvar tmp 0x0030

	ifvarn tmp 32 {
		setvarvar picnum ai_tsprpicnum
		getactor[THISACTOR].yrepeat yrepeat
		setvarvar tmp tiledata[picnum].ysize
		setvarvar yoffset tiledata[picnum].yoffset

		setvarvar tmp2 tmp
		divvar tmp 2
		setvarvar tmp3 tmp
		addvarvar tmp yoffset
		subvarvar tmp2 tmp
		shiftvarl yrepeat 2
		mulvarvar tmp2 yrepeat
		addvarvar zbot tmp2

		addvarvar tmp3 yoffset
		mulvarvar tmp3 yrepeat
		subvarvar ztop tmp3
	}
	
ends

/*
	USING:
		x
		x2
		y
		y2
		tmp
		wallid
		wallnum
*/
//int inside(int x, int y, short sectnum)
state inside
	ifvarg ain3 -1 ifvarl ain3 4096 {
		setvar RETURN 0
		getsector[ain3].wallptr wallid
		getsector[ain3].wallnum wallnum
		whilevarvarn wallnum 0 {
			getwall[wallid].y y
			subvarvar y ain2 					//y1 = wal.y-y
			getwall[wallid].point2 wallid2
			getwall[wallid2].y y2
			subvarvar y2 ain2 					//y2 = wall[wal.point2].y-y;
			
			setvarvar tmp y
			xorvarvar tmp y2 					//if ((y1^y2) < 0)
			ifvarl tmp 0 {
			
				getwall[wallid].x x
				subvarvar x ain1 				//x1 = wal.x-x
				getwall[wallid].point2 wallid2
				getwall[wallid2].x x2
				subvarvar x2 ain1 				//x2 = wall[wal.point2].x-x;
			
				setvarvar tmp x
				xorvarvar tmp x2 				//if ((x1^x2) >= 0)
				
				ifvarvarg tmp 0 {
					xorvarvar RETURN x			//cnt ^= x1;
				} else ifvarvare tmp 0 {
					xorvarvar RETURN x			//cnt ^= x1;
				} else {
					mulvarvar x y2
					mulvarvar x2 y
					subvarvar x x2
					xorvarvar x y2
					xorvarvar RETURN x			//cnt ^= (x1*y2-x2*y1)^y2;
				}
			}
			addvar wallid 1
			subvar wallnum 1
		}
		andvar RETURN 0x7FFFFFFF
		shiftvarr RETURN 30
	} else setvar RETURN -1
ends

gamevar RSECTOR 0 0

/*
	ain1 fs_x
	ain2 fs_y
	ain3 fs_z
	ain4 fs_nsector
	
	USING:
		tmp2
		wallid
		wallnum
		sector_z1
		sector_z2
*/
//BOOL FindSector(int x, int y, int z, short *nSector)
state FindSector

	setvar RETURN 0
	setvar RSECTOR -1
	
	updatesectorz ain1 ain2 ain3 RSECTOR
	ifvarg RSECTOR -1
		setvar RETURN 1
	/*
	setvarvar ain3 ain4
	state inside
	
	ifvarg RETURN 0 {
		getceilzofslope ain4 ain1 ain2 sector_z1
		getflorzofslope ain4 ain1 ain2 sector_z2
		
		ifvarvare ain3 sector_z1 {
			setvar RETURN 1
			setvarvar RSECTOR ain4
		}
		else ifvarvarg ain3 sector_z1 {
			setvar RETURN 1
			setvarvar RSECTOR ain4
		}
		else ifvarvare ain3 sector_z2 {
			setvar RETURN 1
			setvarvar RSECTOR ain4
		}
		else ifvarvarl ain3 sector_z2 {
			setvar RETURN 1
			setvarvar RSECTOR ain4
		}
	} else {
		getsector[ain4].wallptr wallptr
		getsector[ain4].wallnum tmp2
		whilevarvarn tmp2 0 {
			ifvarg wall[wallptr].nextsector -1 {
				setvarvar ain3 wall[wallptr].nextsector
				state inside
				
				ifvarg RETURN 0 {
					getceilzofslope ain4 ain1 ain2 sector_z1
					getflorzofslope ain4 ain1 ain2 sector_z2
					
					ifvarvare ain3 sector_z1 {
						setvar RETURN 1
						setvarvar RSECTOR wall[wallptr].nextsector
					}
					else ifvarvarg ain3 sector_z1 {
						setvar RETURN 1
						setvarvar RSECTOR wall[wallptr].nextsector
					}
					else ifvarvare ain3 sector_z2 {
						setvar RETURN 1
						setvarvar RSECTOR wall[wallptr].nextsector
					}
					else ifvarvarl ain3 sector_z2 {
						setvar RETURN 1
						setvarvar RSECTOR wall[wallptr].nextsector
					}
				}
			}
			
			addvar wallptr 1
			subvar tmp2 1
		}
		
		ifvare RETURN 0 {
			setvar tmp2 0
			whilevarvarn tmp2 NUMSECTORS {

				setvarvar ain3 tmp2
				state inside

				
				ifvarg RETURN 0 {
					getceilzofslope ain4 ain1 ain2 sector_z1
					getflorzofslope ain4 ain1 ain2 sector_z2
					
					ifvarvare ain3 sector_z1 {
						setvar RETURN 1
						setvarvar RSECTOR tmp2
					}
					else ifvarvarg ain3 sector_z1 {
						setvar RETURN 1
						setvarvar RSECTOR tmp2
					}
					else ifvarvare ain3 sector_z2 {
						setvar RETURN 1
						setvarvar RSECTOR tmp2
					}
					else ifvarvarl ain3 sector_z2 {
						setvar RETURN 1
						setvarvar RSECTOR tmp2
					}
				}
				addvar tmp2 1
			}
		}
	}
	*/
ends

/*
	setvarvar ain1 THISACTOR
	setvarvar ain2 player[THISACTOR].posz
	cos ain3 player[THISACTOR].ang
	sin ain4 player[THISACTOR].ang
	getplayer[THISACTOR].horiz ain5
	subvar ain5 100
	mulvar ain5 -128
	setvarvar ain6 4294901808

	state HitScan
	

	
	USING:
		x
		y
		sectnum
		tmp
		tmp2
		sector_z1
		sector_z2
*/

//int HitScan( int nSprite, int z, int dx, int dy, int dz, int clipmask)
state HitScan

	ifvare ain3 0 ifvare ain4 0 
		addlogvar ain3
	
	getactor[ain1].x x
	getactor[ain1].y y
	getactor[ain1].sectnum sectnum
	getactor[ain1].cstat tmp2
	ifvarand sprite[ain1].cstat 256 {
		getactor[ain1].cstat tmp
		xorvar tmp 256
		setactor[ain1].cstat tmp
	}
	shiftvarl ain5 4
	
	hitscan x y ain2 sectnum ain3 ain4 ain5 ai_hitsector ai_hitwall ai_hitsprite ai_hitx ai_hity ai_hitz ain6
	setactor[ain1].cstat tmp2

	setvar RETURN -1
	
	ifvarg ai_hitsprite -1 {
		setvar RETURN 3
	} else
	ifvarg ai_hitwall -1 {
		ifvare wall[ai_hitwall].nextsector -1
			setvar RETURN 0
		else {
			getceilzofslope wall[ai_hitwall].nextsector ai_hitx ai_hity sector_z1
			getflorzofslope wall[ai_hitwall].nextsector ai_hitx ai_hity sector_z2
			
			ifvarvare ai_hitz sector_z1
				setvar RETURN 0
			else
			ifvarvare ai_hitz sector_z2
				setvar RETURN 0
			else
			ifvarvarg ai_hitz sector_z2
				setvar RETURN 0
			else
			ifvarvarl ai_hitz sector_z1
				setvar RETURN 0
			else
				setvar RETURN 4
		}
	} else
	ifvarg ai_hitsector -1 {
		ifvarvarg ai_hitz ain2
			setvar RETURN 2
		else setvar RETURN 1
	}
ends

/*
	ain1 - nSprite
	ain2 - nTarget
	ain3 - ang
	ain4 - dist
	
	USING:
		x
		y
		z
		sectnum
		tmp
		tmp2
		mycos
		mysin
		xydist
		sector_z1
*/

//BOOL CanMove( int nSprite, int nTarget, int ang, int dist )
state CanMove

	getactor[ain1].x x
	getactor[ain1].y y
	getactor[ain1].z z
	getactor[ain1].sectnum sectnum

	cos mycos ain3
	sin mysin ain3
	mulscale mycos ain4 mycos 14
	mulscale mysin ain4 mysin 14
	
	getactor[ain1].cstat tmp2
	ifvarand sprite[ain1].cstat 256 {
		getactor[ain1].cstat tmp
		xorvar tmp 256
		setactor[ain1].cstat tmp
	}
	hitscan x y z sectnum mycos mysin 0 ai_hitsector ai_hitwall ai_hitsprite ai_hitx ai_hity ai_hitz CLIPMASK0
	setactor[ain1].cstat tmp2

	setvar RETURN -1
	
	subvarvar x ai_hitx //dx
	subvarvar y ai_hity //dy
	
	ifvarl x 0 mulvar x -1 //abs(dx)
	ifvarl y 0 mulvar y -1 //abs(dy)
	ifvarvarg x y {
		mulvar y 3
		shiftvarr y 3
	} else {
		mulvar x 3
		shiftvarr x 3
	}
	setvarvar xydist x
	addvarvar xydist y

	getactor[ain1].clipdist DIST
	shiftvarl DIST 2
	subvarvar xydist DIST

	ifvarvarl xydist ain4 {
		// okay to be blocked by target
		ifvarg ai_hitsprite -1 ifvarvare ai_hitsprite ain2 
			setvar RETURN 1
		else
			setvar RETURN 0
	}

	ifvare RETURN -1 {
		getactor[ain1].x x
		getactor[ain1].y y
		addvarvar x mycos
		addvarvar y mysin

		getactor[ain1].sectnum sectnum
		ifvarg sectnum -1 {
			state saveregisters
			setvarvar ain1 x
			setvarvar ain2 y
			setvarvar ain3 z
			setvarvar ain4 sectnum
			state FindSector
			state loadregisters
			setvarvar sectnum RSECTOR
			ifvarn RETURN 0
			{
				setvar RETURN -1
				getactor[ain1].x x
				getactor[ain1].y y
				getflorzofslope sectnum x y sector_z1
				
				switch sprite[THISACTOR].picnum
				case FATRAT
				case BUTCHER
				case HELLDOG
				case SPIDER
				case BOSSSPIDER
				case CERBERUS
				case CIVILIAN
					ifvare sector[sectnum].lotag 1 { //water
						setvar RETURN 0
					}
				break
				endswitch

				ifvare RETURN -1 {
					// this should go into the dude table and be time relative
					state GetSpriteExtents
					subvarvar sector_z1 zbot

					ifvarg sector_z1 8191 {
						setvar RETURN 0
					}
					else setvar RETURN 1
				}
			}	
		}
	}
	
ends