define IDLE 0
define CHASE 1
define SEARCH 2
define GOTO 3
define HACK 4

define POINTI 7394

actor POINTI
sizeat 32 32
ifcount 1 killit
enda

gamevar spr_xvel 0 2
gamevar spr_yvel 0 2
gamevar spr_zvel 0 2
gamevar spr_flags 0 2
gamevar hitspr_ceilHit 0 2
gamevar hitspr_floorHit 0 2
gamevar hitspr_moveHit 0 2


gamevar ref_dx 0 2
gamevar ref_dy 0 2
gamevar ref_vx 0 2
gamevar ref_vy 0 2
gamevar ref_wall 0 2
gamevar ref_fract 0 2

//static void ReflectVector( short *dx, short *dy, int nWall, int nFraction )
state ReflectVector

	// get wall vector
	getwall[ref_wall].x r2
	getwall[ref_wall].y r3
	getwall[ref_wall].point2 r4
	getwall[r4].x r5
	getwall[r4].y r6
	subvarvar r5 r2
	subvarvar r6 r3
			
	// get reflect angle
	getangle tmp r5 r6
	getangle tmp2 ref_dx ref_dy
	shiftvarl tmp 1
	subvarvar tmp tmp2
	andvar tmp 2047
	
	// calc reflect vector
	cos ref_vx tmp
	ifvarl ref_dx 0
		mulvar ref_dx -1
	mulvarvar ref_vx ref_dx
	ifvarg ref_fract 0
		mulscale ref_vx ref_vx ref_fract 16
	shiftvarr ref_vx 14
	
	sin ref_vy tmp
	ifvarl ref_dy 0
		mulvar ref_dy -1
	mulvarvar ref_vy ref_dy
	ifvarg ref_fract 0
		mulscale ref_vy ref_vy ref_fract 16
	shiftvarr ref_vy 14
	
	setvarvar ref_dx ref_vx
	setvarvar ref_dy ref_vy
	
ends

gamevar nTile 0 2
gamevar tilesizy 0 2
gamevar bottom 0 2
gamevar top 0 2

gamevar md_floordist 0 2
gamevar md_ceildist 0 2
gamevar md_clipdist 0 2
gamevar md_nsector 0 2
gamevar md_ztop 0 2
gamevar md_zbot 0 2
gamevar md_ocstat 0 2
gamevar md_nwall 0 2
gamevar md_ceilz 0 2
gamevar md_ceilhit 0 2
gamevar md_floorz 0 2
gamevar md_floorhit 0 2
gamevar md_falldamage 0 2

state GetSpriteExtents

	setvarvar md_ztop sprite[THISACTOR].z
	setvarvar md_zbot sprite[THISACTOR].z
	
	getactor[THISACTOR].cstat tmp
	andvar tmp 0x0030
	ifvarand tmp 0x0020 nullop else {
		getactor[THISACTOR].picnum nTile
		getactor[THISACTOR].yrepeat yrepeat
		setvarvar tilesizy tiledata[nTile].ysize
		setvarvar yoffset tiledata[nTile].yoffset
		
		setvarvar bottom tilesizy
		divvar tilesizy 2
		setvarvar top tilesizy
		addvarvar tilesizy yoffset
		subvarvar bottom tilesizy
		shiftvarl yrepeat 2
		mulvarvar bottom yrepeat
		addvarvar md_zbot bottom
		
		addvarvar top yoffset
		mulvarvar top yrepeat
		subvarvar md_ztop top
	}
	
	//md_ztop -= ((picanm[nTile] >> 16) & 255 + tilesizy[nTile] / 2) * (pSprite.yrepeat << 2);
	//md_zbot += (tilesizy[nTile] - (tilesizy[nTile] / 2 + (picanm[nTile] >> 16) & 255)) * (pSprite.yrepeat << 2);

ends

gamevar clip_x 0 2
gamevar clip_y 0 2
gamevar clip_z 0 2
gamevar clip_sect 0 2
gamevar clip_dx 0 2
gamevar clip_dy 0 2
gamevar md_return 0 2
gamevar spr_height 0 2

state MoveDude

	setvar md_return 0
	setvar hitspr_ceilHit 0
	setvar hitspr_floorHit 0
	setvar hitspr_moveHit 0
	
	state GetSpriteExtents
	//setvarvar md_ztop
	//setvarvar md_zbot
	
	getactor[THISACTOR].cstat md_ocstat
	cstator 257
	
	setvarvar clip_dx spr_xvel
	shiftvarr clip_dx 12
	shiftvarl clip_dx 14
	
	setvarvar clip_dy spr_yvel
	shiftvarr clip_dy 12
	shiftvarl clip_dy 14

	setvarvar md_floordist md_zbot
	subvarvar md_floordist sprite[THISACTOR].z
	divvarvar md_floordist 4
	setvarvar md_ceildist sprite[THISACTOR].z
	subvarvar md_ceildist md_ztop
	divvarvar md_ceildist 4
	setvarvar md_clipdist sprite[THISACTOR].clipdist
	shiftvarl md_clipdist 2
	
	getactor[THISACTOR].x clip_x
	getactor[THISACTOR].y clip_y
	getactor[THISACTOR].z clip_z
	getactor[THISACTOR].sectnum clip_sect
	clipmove hitspr_moveHit clip_x clip_y clip_z clip_sect clip_dx clip_dy md_clipdist md_floordist md_ceildist CLIPMASK0 
	
	ifvare clip_sect -1 {
		setvarvar clip_x sprite[THISACTOR].x
		setvarvar clip_y sprite[THISACTOR].y
		setvarvar clip_z sprite[THISACTOR].z
		setvarvar clip_sect sprite[THISACTOR].sectnum
	}
	
	ifvarg clip_sect 0 ifvarvarn clip_sect sprite[THISACTOR].sectnum 
		changespritesect THISACTOR clip_sect
	
	setactor[THISACTOR].x clip_x
	setactor[THISACTOR].y clip_y
	setactor[THISACTOR].z clip_z
	setactor[THISACTOR].cstat md_ocstat

	setvarvar tmp hitspr_moveHit
	andvar tmp 57344
	ifvare tmp 32768 {
		setvarvar md_nwall hitspr_moveHit
		andvar md_nwall 0x1FFF

		ifvarn wall[md_nwall].nextsector -1 {
			ifvarvarg sector[wall[md_nwall].nextsector].floorz md_ztop {
				setvarvar ref_dx spr_xvel
				setvarvar ref_dy spr_yvel
				setvarvar ref_wall md_nwall
				setvar ref_fract 0
				state ReflectVector
				setvarvar spr_xvel ref_dx
				setvarvar spr_yvel ref_dy
				//ReflectVector(&pSprite->xvel, &pSprite->yvel, nWall, 0);
			} 
			ifvarvarl sector[wall[md_nwall].nextsector].ceilingz md_zbot {
				setvarvar ref_dx spr_xvel
				setvarvar ref_dy spr_yvel
				setvarvar ref_wall md_nwall
				setvar ref_fract 0
				state ReflectVector
				setvarvar spr_xvel ref_dx
				setvarvar spr_yvel ref_dy
				//ReflectVector(&pSprite->xvel, &pSprite->yvel, nWall, 0);
			}
		} else {
			setvarvar ref_dx spr_xvel
			setvarvar ref_dy spr_yvel
			setvarvar ref_wall md_nwall
			setvar ref_fract 0x4000
			state ReflectVector
			setvarvar spr_xvel ref_dx
			setvarvar spr_yvel ref_dy
			//ReflectVector(&pSprite->xvel, &pSprite->yvel, nWall, 0x4000);

			mulscale spr_zvel spr_zvel 0xC000 16
			//pSprite->zvel = (short)mulscale16(pSprite->zvel, 0xC000);
		}
	}
	
	ifvarn spr_zvel 0 {
		getactor[THISACTOR].z clip_z
		setvarvar tmp spr_zvel
		shiftvarr tmp 8
		addvarvar clip_z tmp	
		setactor[THISACTOR].z clip_z
	}
		
	getzrange sprite[THISACTOR].x sprite[THISACTOR].y sprite[THISACTOR].z sprite[THISACTOR].sectnum md_ceilz md_ceilhit md_floorz md_floorhit md_clipdist CLIPMASK0
	
	state GetSpriteExtents
	
	ifvarand spr_flags 0x0002 {
		ifvarvarl md_zbot md_floorz {
			getactor[THISACTOR].z clip_z
			addvarvar clip_z 455
			setactor[THISACTOR].z clip_z //pSprite->z += 4 * 58254 / 2 >> 8;
			addvar spr_zvel 58254 //sprZVel[xvel] += 58254;
		} 
	}
	
	state GetSpriteExtents
	
	ifvarvarg md_floorz md_zbot {
		setvarvar hitspr_floorHit 0
		ifvarand spr_flags 0x0002
			orvar spr_flags 0x0004
	} else {
		setvarvar hitspr_floorHit md_floorhit
		subvarvar md_floorz md_zbot
		addvarvar md_floorz sprite[THISACTOR].z
		setactor[THISACTOR].z md_floorz
		
		setvarvar tmp spr_zvel
		ifvarl tmp 0
			mulvar tmp -1
		ifvarg tmp 65535 {
			orvar spr_flags 0x0004
		} else {
			setvar spr_zvel 0;
		}
	}
	
	ifvarvarl md_ceilz md_ztop {
		setvarvar hitspr_floorHit 0 
	} else {
		setvarvar hitspr_floorHit md_ceilhit
		
		subvarvar md_ceilz md_ztop
		ifvarg md_ceilz 0 {
			addvarvar md_ceilz sprite[THISACTOR].z
			setactor[THISACTOR].z md_ceilz
		}
		
		ifvarl spr_zvel 0 ifvarand spr_flags 4 {
			mulvar spr_zvel -1
			shiftvarr spr_zvel 3
		}
	}
	
	state GetSpriteExtents
	
	setvarvar tmp md_floorz
	subvarvar tmp md_zbot
	ifvarg tmp 0 {
		shiftvarr tmp 8
		setvarvar spr_height tmp
	}
	
	ifvarn spr_xvel 0 {
		ifvarl spr_height 256 {
			setvar tmp 10752
			ifvarn spr_height 0 {
				mulscale RETURN spr_height 10752 8
				subvarvar tmp RETURN
			}
			
			setvarvar tmp2 spr_xvel
			addvarvar tmp2 0x8000
			mulscale RETURN tmp tmp2 16
			subvarvar spr_xvel RETURN
			
			setvarvar tmp3 spr_xvel
			addvarvar tmp3 spr_yvel
			ifvarl tmp3 4096 {
				setvar spr_xvel 0
				setvar spr_yvel 0
			}		
		}
	}
	
	ifvarn spr_yvel 0 {
		ifvarl spr_height 256 {
			setvar tmp 10752
			ifvarn spr_height 0 {
				mulscale RETURN spr_height 10752 8
				subvarvar tmp RETURN
			}
			
			setvarvar tmp2 spr_yvel
			addvarvar tmp2 0x8000
			mulscale RETURN tmp tmp2 16
			subvarvar spr_yvel RETURN
			
			setvarvar tmp3 spr_xvel
			addvarvar tmp3 spr_yvel
			ifvarl tmp3 4096 {
				setvar spr_xvel 0
				setvar spr_yvel 0
			}		
		}
	}
	
	
	/*
	ifvarand spr_flags 0x0002 { //old code fixme
		ifvarvarl md_zbot md_floorz {
			getactor[THISACTOR].z clip_z
			addvarvar clip_z 88 //kGravity * kFrameTicks * kFrameTicks / 2
			setactor[THISACTOR].z clip_z
			addvar spr_zvel 44 //kGravity * kFrameTicks
			orvar spr_flags 0x0004
		}
	}
	
	
	// hit floor?
	subvar md_floorz 1
	ifvarvarg md_zbot md_floorz {

		setvarvar hitspr_floorHit md_floorhit

		subvarvar md_floorz md_zbot
		addvarvar md_floorz sprite[THISACTOR].z
		setactor[THISACTOR].z md_floorz
		
		ifvarand spr_flags 0x0004 {
		
			mulscale md_falldamage spr_zvel spr_zvel 16
			mulscale md_falldamage md_falldamage md_falldamage 1
			ifvarg md_falldamage 320 {
				//damage
			}
			
			mulscale spr_xvel spr_xvel 0xC000 16
			mulscale spr_yvel spr_yvel 0xC000 16
			mulscale spr_zvel -spr_zvel 0x2000 16
	
			ifvarg spr_zvel -96 {
				setvar spr_zvel 0
				xorvar spr_flags 0x0004
			}
			setvar md_return 1
		}
		setvar spr_zvel 0
	}
	
	ifvare md_return 0 {
		ifvarn spr_xvel 0 {
			// air drag
			mulscale RETURN spr_xvel 0x0100 16
			subvarvar spr_xvel RETURN
			mulscale RETURN spr_yvel 0x0100 16
			subvarvar spr_yvel RETURN
			ifvarand spr_flags 4 nullop else {
				// movement drag
				mulscale RETURN spr_xvel 0x2800 16
				subvarvar spr_xvel RETURN
				mulscale RETURN spr_yvel 0x2800 16
				subvarvar spr_yvel RETURN
			}
		} else
		ifvarn spr_yvel 0 {
			// air drag
			mulscale RETURN spr_xvel 0x0100 16
			subvarvar spr_xvel RETURN
			mulscale RETURN spr_yvel 0x0100 16
			subvarvar spr_yvel RETURN
			
			ifvarand spr_flags 4 nullop else {
				// movement drag
				mulscale RETURN spr_xvel 0x2800 16
				subvarvar spr_xvel RETURN
				mulscale RETURN spr_yvel 0x2800 16
				subvarvar spr_yvel RETURN
			}
		}
	}
	*/
	
ends


gamevar bl_spriteid 0 2
gamevar bl_z 0 2
gamevar bl_dx 0 2
gamevar bl_dy 0 2
gamevar bl_dz 0 2
gamevar bl_clipmask 0 2

gamevar hitscan_return 0 2

gamevar hs_x 0 2
gamevar hs_y 0 2
gamevar hs_sect 0 2
gamevar hs_oldcstat 0 2
gamevar hs_ceilz 0 2
gamevar hs_floorz 0 2

/*
	setvarvar bl_spriteid THISACTOR
	setvarvar bl_z player[THISACTOR].posz
	cos bl_dx player[THISACTOR].ang
	sin bl_dy player[THISACTOR].ang
	getplayer[THISACTOR].horiz bl_dz
	subvar bl_dz 100
	mulvar bl_dz -128
	setvarvar bl_clipmask 4294901808

	state HitScan
	
	addlogvar hitscan_return
*/

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

	ifvare bl_dx 0 ifvare bl_dy 0 
		addlogvar bl_dx
	
	getactor[bl_spriteid].x hs_x
	getactor[bl_spriteid].y hs_y
	getactor[bl_spriteid].sectnum hs_sect
	getactor[bl_spriteid].cstat hs_oldcstat
	ifvarand sprite[bl_spriteid].cstat 256 {
		getactor[bl_spriteid].cstat tmp
		xorvar tmp 256
		setactor[bl_spriteid].cstat tmp
	}
	mulvar bl_dz 16
	
	
	
	hitscan hs_x hs_y bl_z hs_sect bl_dx bl_dy bl_dz HITSECTOR HITWALL HITSPRITE HITX HITY HITZ bl_clipmask
	setactor[bl_spriteid].cstat hs_oldcstat

	setvar hitscan_return -1
	
	ifvarg HITSPRITE -1 {
		setvar hitscan_return 3
	} else
	ifvarg HITWALL -1 {
		ifvare wall[HITWALL].nextsector -1
			setvar hitscan_return 0
		else {
			getceilzofslope wall[HITWALL].nextsector HITX HITY hs_ceilz
			getflorzofslope wall[HITWALL].nextsector HITX HITY hs_floorz
			
			ifvarvare HITZ hs_ceilz
				setvar hitscan_return 0
			else
			ifvarvare HITZ hs_floorz
				setvar hitscan_return 0
			else
			ifvarvarg HITZ hs_floorz
				setvar hitscan_return 0
			else
			ifvarvarl HITZ hs_ceilz
				setvar hitscan_return 0
			else
				setvar hitscan_return 4
		}
	} else
	ifvarg HITSECTOR -1 {
		ifvarvarg HITZ bl_z
			setvar hitscan_return 2
		else setvar hitscan_return 1
	}
ends

gamevar ins_x 0 2
gamevar ins_y 0 2
gamevar ins_sectnum -1 2
gamevar ins_return 0 2

gamevar ins_cnt 0 2
gamevar ins_wallid 0 2
gamevar ins_point2 0 2
gamevar ins_i 0 2
gamevar ins_sx 0 2
gamevar ins_x1 0 2
gamevar ins_x2 0 2
gamevar ins_sy 0 2
gamevar ins_y1 0 2
gamevar ins_y2 0 2

//int inside(int x, int y, short sectnum)
state inside

	ifvarg ins_sectnum -1 ifvarl ins_sectnum 4096 {
	
		setvar ins_cnt 0
		getsector[ins_sectnum].wallptr ins_wallid
		getsector[ins_sectnum].wallnum ins_i
		
		whilevarvarn ins_i 0 {
			getwall[ins_wallid].y ins_y1
			subvarvar ins_y1 ins_y 					//y1 = wal.y-y
			getwall[ins_wallid].point2 ins_point2
			getwall[ins_point2].y ins_y2
			subvarvar ins_y2 ins_y 					//y2 = wall[wal.point2].y-y;
			
			setvarvar ins_sy ins_y1
			xorvarvar ins_sy ins_y2 				//if ((y1^y2) < 0)
			ifvarl ins_sy 0 {
			
				getwall[ins_wallid].x ins_x1
				subvarvar ins_x1 ins_x 				//x1 = wal.x-x
				getwall[ins_wallid].point2 ins_point2
				getwall[ins_point2].x ins_x2
				subvarvar ins_x2 ins_x 				//x2 = wall[wal.point2].x-x;
			
				setvarvar ins_sx ins_x1
				xorvarvar ins_sx ins_x2 			//if ((x1^x2) >= 0)
				
				ifvarvarg ins_sx 0 {
					xorvarvar ins_cnt ins_x1		//cnt ^= x1;
				} else ifvarvare ins_sx 0 {
					xorvarvar ins_cnt ins_x1		//cnt ^= x1;
				} else {
					mulvarvar ins_x1 ins_y2
					mulvarvar ins_x2 ins_y1
					subvarvar ins_x1 ins_x2
					xorvarvar ins_x1 ins_y2
					xorvarvar ins_cnt ins_x1		//cnt ^= (x1*y2-x2*y1)^y2;
				}
			}

			addvar ins_wallid 1
			subvar ins_i 1
		}
		andvar ins_cnt 0x7FFFFFFF
		shiftvarr ins_cnt 30
		setvarvar ins_return ins_cnt

	} else setvar ins_return -1

ends

gamevar fs_x 0 2
gamevar fs_y 0 2
gamevar fs_z 0 2
gamevar fs_nsector 0 2

gamevar fs_i 0 2
gamevar fs_wallid 0 2
gamevar fs_nextsec 0 2

gamevar fs_return 0 2
gamevar fs_retsect 0 2

//BOOL FindSector(int x, int y, int z, short *nSector)
state FindSector

	setvar fs_return 0
	setvar fs_retsect -1
	
	setvarvar ins_x fs_x
	setvarvar ins_y fs_y
	setvarvar ins_sectnum fs_nsector
	state inside
	
	ifvarg ins_return 0 {
		getceilzofslope fs_nsector fs_x fs_y hs_ceilz
		getflorzofslope fs_nsector fs_x fs_y hs_floorz
		
		ifvarvare fs_z hs_ceilz {
			setvar fs_return 1
			setvarvar fs_retsect fs_nsector
		}
		else ifvarvarg fs_z hs_ceilz {
			setvar fs_return 1
			setvarvar fs_retsect fs_nsector
		}
		else ifvarvare fs_z hs_floorz {
			setvar fs_return 1
			setvarvar fs_retsect fs_nsector
		}
		else ifvarvarl fs_z hs_floorz {
			setvar fs_return 1
			setvarvar fs_retsect fs_nsector
		}
	} else {
		getsector[fs_nsector].wallptr fs_wallid
		getsector[fs_nsector].wallnum fs_i
		whilevarvarn fs_i 0 {
			getwall[fs_wallid].nextsector fs_nextsec
			ifvarg fs_nextsec 0 {
				setvarvar ins_x fs_x
				setvarvar ins_y fs_y
				setvarvar ins_sectnum fs_nextsec
				state inside
				
				ifvarg ins_return 0 {
					getceilzofslope fs_nsector fs_x fs_y hs_ceilz
					getflorzofslope fs_nsector fs_x fs_y hs_floorz
					
					ifvarvare fs_z hs_ceilz {
						setvar fs_return 1
						setvarvar fs_retsect fs_nextsec
					}
					else ifvarvarg fs_z hs_ceilz {
						setvar fs_return 1
						setvarvar fs_retsect fs_nextsec
					}
					else ifvarvare fs_z hs_floorz {
						setvar fs_return 1
						setvarvar fs_retsect fs_nextsec
					}
					else ifvarvarl fs_z hs_floorz {
						setvar fs_return 1
						setvarvar fs_retsect fs_nextsec
					}
				}
				
			}
			
			addvar fs_wallid 1
			subvar fs_i 1
		}
		
		ifvare fs_return 0 {
			setvar fs_i 0
			whilevarvarn fs_i NUMSECTORS {
				setvarvar ins_x fs_x
				setvarvar ins_y fs_y
				setvarvar ins_sectnum fs_i
				state inside
				
				ifvarg ins_return 0 {
					getceilzofslope fs_nsector fs_x fs_y hs_ceilz
					getflorzofslope fs_nsector fs_x fs_y hs_floorz
					
					ifvarvare fs_z hs_ceilz {
						setvar fs_return 1
						setvarvar fs_retsect fs_i
					}
					else ifvarvarg fs_z hs_ceilz {
						setvar fs_return 1
						setvarvar fs_retsect fs_i
					}
					else ifvarvare fs_z hs_floorz {
						setvar fs_return 1
						setvarvar fs_retsect fs_i
					}
					else ifvarvarl fs_z hs_floorz {
						setvar fs_return 1
						setvarvar fs_retsect fs_i
					}
				}
				addvar fs_i 1
			}
		}
	}
ends

gamevar cm_x 0 2
gamevar cm_y 0 2
gamevar cm_z 0 2
gamevar cm_nsprite 0 2
gamevar cm_ntarget 0 2
gamevar cm_ang 0 2
gamevar cm_dist 0 2

gamevar cm_tmpx 0 2
gamevar cm_tmpy 0 2
gamevar cm_nsector 0 2
gamevar cm_zbot 0 2

gamevar cm_hitdist 0 2
gamevar cm_clipdist 0 2

gamevar cm_return 0 2

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

	setvar cm_return -1
	
	getactor[cm_nsprite].x cm_x
	getactor[cm_nsprite].y cm_y
	getactor[cm_nsprite].z cm_z
	
	state GetSpriteExtents
	setvarvar cm_zbot md_zbot

	setvarvar bl_spriteid cm_nsprite
	setvarvar bl_z cm_z
	cos bl_dx cm_ang
	sin bl_dy cm_ang
	setvarvar bl_dz 0
	setvarvar bl_clipmask CLIPMASK0
	
	mulscale bl_dx cm_dist bl_dx 14
	mulscale bl_dy cm_dist bl_dy 14

	state HitScan

	setvarvar cm_tmpx cm_x
	setvarvar cm_tmpy cm_y
	subvarvar cm_tmpx HITX
	subvarvar cm_tmpy HITY
	mulvarvar cm_tmpx cm_tmpx
	mulvarvar cm_tmpy cm_tmpy
	addvarvar cm_tmpx cm_tmpy
	sqrt cm_tmpx cm_hitdist

	getactor[cm_nsprite].clipdist cm_clipdist
	shiftvarl cm_clipdist 2
	subvarvar cm_hitdist cm_clipdist
	
	ifvarvarl cm_hitdist cm_dist {
		// okay to be blocked by target
		ifvarg HITSPRITE -1 {
			ifvarvare HITSPRITE cm_ntarget {
				setvar cm_return 1
			} else
			setvar cm_return 0
		} else setvar cm_return 0
	}

	ifvare cm_return -1 {

		addvarvar cm_x bl_dx
		addvarvar cm_y bl_dy

		getactor[cm_nsprite].sectnum cm_nsector
		ifvarg cm_nsector -1 {
		
			setvarvar fs_x cm_x
			setvarvar fs_y cm_y
			setvarvar fs_z cm_z
			setvarvar fs_nsector cm_nsector

			state FindSector
			
			setvarvar cm_nsector fs_retsect

			ifvare fs_return 0 {
				setvar cm_return 0
			}
			else {
				getflorzofslope cm_nsector cm_x cm_y hs_floorz
				
				switch sprite[THISACTOR].picnum
				case FATRAT
				case BUTCHER
				case HELLDOG
				case SPIDER
				case BOSSSPIDER
				case CERBERUS
				case CIVILIAN
					ifvare sector[cm_nsector].lotag 1 { //water
						setvar cm_return 0
					}
				break
				endswitch

				ifvare cm_return -1 {
					// this should go into the dude table and be time relative
					subvarvar hs_floorz cm_zbot

					ifvarg hs_floorz 8191 {
						setvar cm_return 0
					}
					else setvar cm_return 1
				}
			}	
		}
	}
	
ends


// enemy ai code

gamevar ai_ang 0 2
gamevar ai_goalang 0 2
gamevar ai_speed 0 2
gamevar ai_mass 0 2
gamevar ai_angspeed 0 2
gamevar ai_dodgedir 0 2
gamevar ai_target 0 2
gamevar ai_targetx 0 2
gamevar ai_targety 0 2
gamevar ai_targetz 0 2
gamevar ai_state 0 2
gamevar ai_statetime 0 2
gamevar ai_think 0 2
gamevar ai_move 0 2
gamevar ai_next 0 2
gamevar ai_ticks 0 2
gamevar ai_aistate 0 2
gamevar ai_alertchance 0 2
gamevar ai_seedist 0 2
gamevar ai_heardist 0 2
gamevar ai_eyeheight 0 2
gamevar ai_periphery 0 2
gamevar ai_statetimer 0 2


gamevar aicd_dang 0 2
gamevar aicd_sin 0 2
gamevar aicd_cos 0 2
gamevar aicd_vel 0 2
gamevar aicd_avoidist 0 2
gamevar aicd_tmp 0 2
gamevar aicd_turnTo 0 2

gamevar aicd_var1 0 2
gamevar aicd_ang1 0 2

gamevar aicd_var2 0 2
gamevar aicd_ang2 0 2

gamevar aicd_var3 0 2
gamevar aicd_ang3 0 2

gamevar aicd_var4 0 2
gamevar aicd_ang4 0 2

gamevar aicd_var5 0 2
gamevar aicd_ang5 0 2

gamevar aicd_var6 0 2
gamevar aicd_ang6 0 2

gamevar aicd_var7 0 2
gamevar aicd_ang7 0 2

state aiChooseDirection

	//int dang = ((kAngle180 + ang - pSprite->ang) & kAngleMask) - kAngle180;
	
	setvarvar aicd_dang 1024
	addvarvar aicd_dang ai_ang
	subvarvar aicd_dang sprite[THISACTOR].ang
	andvar aicd_dang 2047
	subvarvar aicd_dang 1024

	//avoidDist = frontSpeed * kTimerRate >> 4;
	setvarvar aicd_avoidist ai_speed
	mulvarvar aicd_avoidist 120
	shiftvarr aicd_avoidist 4
	
	//int turnTo = kAngle60;
	//if (dang < 0 )
	//	turnTo = -turnTo;
	
	setvar aicd_turnTo 341
	ifvarl aicd_dang 0
		mulvar aicd_turnTo -1

	setvarvar cm_nsprite THISACTOR
	setvarvar cm_ntarget ai_target
	setvarvar cm_dist aicd_avoidist
	
	// clear movement toward target?
	setvarvar aicd_ang1 sprite[THISACTOR].ang
	addvarvar aicd_ang1 aicd_dang
	setvarvar cm_ang aicd_ang1
	state CanMove								
	setvarvar aicd_var1 cm_return				//pSprite->ang + dang
	
	// clear movement partially toward target?
	setvarvar aicd_ang2 sprite[THISACTOR].ang
	setvarvar aicd_tmp aicd_dang
	divvarvar aicd_tmp 2
	addvarvar aicd_ang2 aicd_tmp
	setvarvar cm_ang aicd_ang2
	state CanMove
	setvarvar aicd_var2 cm_return				//pSprite->ang + dang / 2
	
	// try turning in target direction
	setvarvar aicd_ang3 sprite[THISACTOR].ang
	addvarvar aicd_ang3 aicd_turnTo
	setvarvar cm_ang aicd_ang3
	state CanMove
	setvarvar aicd_var3 cm_return				//pSprite->ang + turnTo
	
	// clear movement straight?
	setvarvar aicd_ang4 sprite[THISACTOR].ang
	setvarvar cm_ang aicd_ang4
	state CanMove
	setvarvar aicd_var4 cm_return				//pSprite->ang
	
	// try turning away
	setvarvar aicd_ang5 sprite[THISACTOR].ang
	subvarvar aicd_ang5 aicd_turnTo
	setvarvar cm_ang aicd_ang5
	state CanMove
	setvarvar aicd_var5 cm_return				//pSprite->ang - turnTo
	
	// just turn around
	setvarvar aicd_ang6 sprite[THISACTOR].ang
	addvarvar aicd_ang6 1024
	setvarvar cm_ang aicd_ang6		
	state CanMove	
	setvarvar aicd_var6 cm_return				//pSprite->ang + kAngle180
	
	/*
	setvarvar aicd_ang7 sprite[THISACTOR].ang
	subvarvar aicd_ang7 aicd_tmp
	setvarvar cm_ang aicd_ang7
	state CanMove
	setvarvar aicd_var7 cm_return				//pSprite->ang - dang / 2
	andvar aicd_var7 2047
	*/

	ifvarg aicd_var1 0 setvarvar ai_goalang aicd_ang1 else
	ifvarg aicd_var2 0 setvarvar ai_goalang aicd_ang2 else
	ifvarg aicd_var3 0 setvarvar ai_goalang aicd_ang3 else
	ifvarg aicd_var4 0 setvarvar ai_goalang aicd_ang4 else
	ifvarg aicd_var5 0 setvarvar ai_goalang aicd_ang5 else
		setvarvar ai_goalang aicd_ang6
	andvar ai_goalang 2047

	// choose dodge direction
	setvar ai_dodgedir 1
	ifrnd 128
		setvar ai_dodgedir -1

	setvarvar cm_ang sprite[THISACTOR].ang
	setvarvar aicd_tmp ai_dodgedir
	mulvar aicd_tmp 512
	addvarvar cm_ang aicd_tmp
	setvarvar cm_dist 512
	
	state CanMove
	
	ifvare cm_return 0 {
		mulvar ai_dodgedir -1
		setvarvar cm_ang sprite[THISACTOR].ang
		setvarvar aicd_tmp ai_dodgedir
		mulvar aicd_tmp 512
		addvarvar cm_ang aicd_tmp
		
		state CanMove

		ifvare cm_return 0 {
			setvar ai_dodgedir 0
		}
	}

ends

gamevar aimt_maxturn 0 2
gamevar aimt_dang 0 2
gamevar aimt_tmp 0 2
gamevar aimt_savedang 0 2

state aiMoveTurn

	setvarvar aimt_maxturn ai_angspeed
	mulvarvar aimt_maxturn 4
	shiftvarr aimt_maxturn 4

	setvarvar aimt_dang 1024
	addvarvar aimt_dang ai_goalang
	subvarvar aimt_dang sprite[THISACTOR].ang
	andvar aimt_dang 2047
	subvarvar aimt_dang 1024	
	setvarvar aimt_savedang aimt_dang

	ifvarvarg aimt_dang aimt_maxturn
		setvarvar aimt_dang aimt_maxturn	
		
	setvarvar aimt_tmp aimt_maxturn
	mulvar aimt_tmp -1
	ifvarvarl aimt_dang aimt_tmp
		setvarvar aimt_dang aimt_tmp
			
	getactor[THISACTOR].ang aimt_tmp
	addvarvar aimt_tmp aimt_dang
	andvar aimt_tmp 2047
	setactor[THISACTOR].ang aimt_tmp
	
	setvarvar aimt_dang aimt_savedang

ends

gamevar aimf_maxturn 0 2
gamevar aimf_dang 0 2
gamevar aimf_tmp 0 2
gamevar aimf_sin 0 2
gamevar aimf_cos 0 2

gamevar aimf_vx 0 2
gamevar aimf_vy 0 2

state aiMoveForward

	state aiMoveTurn

	ifvarl aimt_dang 0
		mulvar aimt_dang -1

	ifvarl aimt_dang 342 {
		cos aimf_cos sprite[THISACTOR].ang
		sin aimf_sin sprite[THISACTOR].ang
		
		mulscale aimf_vx aimf_cos ai_speed 14
		mulscale aimf_vy aimf_sin ai_speed 14
		
		addvarvar spr_xvel aimf_vx
		addvarvar spr_yvel aimf_vy
	}

ends

gamevar aiad_dx 0 2
gamevar aiad_dy 0 2

state aiActivateDude

	ifvare ai_state 0 {
		// this doesn't take into account sprites triggered w/o a target location....
		setvarvar aiad_dx ai_targetx
		subvarvar aiad_dx sprite[THISACTOR].x
		setvarvar aiad_dy ai_targety
		subvarvar aiad_dy sprite[THISACTOR].y

		getangle ai_ang aiad_dx aiad_dy
		
		state aiChooseDirection
		setvar ai_state 1
	}
	
	ifvare ai_target -1 {
		setvar ai_aistate SEARCH
		//aiNewState(pSprite, pXSprite, &zombieASearch);
		//state thinkSearch / aiMoveForward
	} else {
		setvar ai_aistate CHASE
		//aiNewState(pSprite, pXSprite, &zombieAChase);
		//state thinkChase / aiMoveForward
	}
	
ends


gamevar aitt_plx 0 2
gamevar aitt_ply 0 2
gamevar aitt_plz 0 2
gamevar aitt_plsec 0 2
gamevar aitt_dist 0 2
gamevar aitt_eyeabovez 0 2
gamevar aitt_tmp 0 2
gamevar aitt_nangle 0 2
gamevar aitt_losangle 0 2
gamevar aitt_dx 0 2
gamevar aitt_dy 0 2
gamevar aitt_return 0 2

state aiThinkTarget

	//if ( !Chance(pDudeInfo->alertChance) ) return;
	setvar aitt_return 0
	
	// skip this player if the he owns the dude or is invisible
	ifvarvarn THISACTOR PLAYERID ifvarg sprite[PLAYERID].extra 0 ifvarn actorvar[PLAYERID].invisible 1 {
		getplayer[THISACTOR].posx aitt_plx
		getplayer[THISACTOR].posy aitt_ply
		getplayer[THISACTOR].posz aitt_plz
		getplayer[THISACTOR].cursectnum aitt_plsec
		
		ldist aitt_dist THISACTOR PLAYERID
		
		ifvarvarl aitt_dist ai_seedist {
			setvarvar aitt_eyeabovez ai_eyeheight
			setvarvar aitt_tmp sprite[THISACTOR].yrepeat
			shiftvarl aitt_tmp 2
			mulvarvar aitt_eyeabovez aitt_tmp
			
			// is there a line of sight to the player?
			setvarvar aitt_tmp sprite[THISACTOR].z
			subvarvar aitt_tmp aitt_eyeabovez
			cansee aitt_plx aitt_ply aitt_plz aitt_plsec sprite[THISACTOR].x sprite[THISACTOR].y aitt_tmp sprite[THISACTOR].sectnum see
			
			ifvare see 1 {
				setvarvar aitt_dx aitt_plx
				subvarvar aitt_dx sprite[THISACTOR].x
				setvarvar aitt_dy aitt_ply
				subvarvar aitt_dy sprite[THISACTOR].y
		
				getangle aitt_nangle aitt_dx aitt_dy
				
				setvarvar aitt_losangle 1024
				addvarvar aitt_losangle aitt_nangle
				subvarvar aitt_losangle sprite[THISACTOR].ang
				andvar aitt_losangle 2047
				subvarvar aitt_losangle 1024
				
				ifvarl aitt_losangle 0
					mulvar aitt_losangle -1
				
				ifvarvarl aitt_losangle ai_periphery {
				
					setvarvar ai_target PLAYERID
					setvarvar ai_targetx sprite[ai_target].x
					setvarvar ai_targety sprite[ai_target].y
					setvarvar ai_targetz sprite[ai_target].z
					
					state aiActivateDude
					setvar aitt_return 1
				}
			}
		} 
		
		ifvare aitt_return 0 {
			ifvarvarl aitt_dist ai_heardist {
				setvarvar aitt_eyeabovez ai_eyeheight
				setvarvar aitt_tmp sprite[THISACTOR].yrepeat
				shiftvarl aitt_tmp 2
				mulvarvar aitt_eyeabovez aitt_tmp
				
				// is there a line of sight to the player?
				setvarvar aitt_tmp sprite[THISACTOR].z
				subvarvar aitt_tmp aitt_eyeabovez
				cansee aitt_plx aitt_ply aitt_plz aitt_plsec sprite[THISACTOR].x sprite[THISACTOR].y aitt_tmp sprite[THISACTOR].sectnum see
				
				ifvare see 1 {
					setvarvar ai_target -1
					setvarvar ai_targetx aitt_plx
					setvarvar ai_targety aitt_ply
					setvarvar ai_targetz aitt_plz
	
					state aiActivateDude
				}
			}
		}
	}
			
ends

gamevar cs_x 0 2
gamevar cs_y 0 2
gamevar cs_z 0 2


gamevar cs_dist2 0 2
gamevar cs_dx2 0 2
gamevar cs_dy2 0 2
gamevar cs_dz2 0 2
gamevar cs_area 0 2
gamevar cs_force 0 2
gamevar cs_impulse 0 2
gamevar cs_ticks 450 2

//static void ConcussSprite( int nSource, int nSprite, int x, int y, int z, 4 )
state ConcussSprite

	//int dx = pSprite->x - x;
	//int dy = pSprite->y - y;
	//int dz = (pSprite->z - z) >> 4;
	getactor[THISACTOR].x x
	subvarvar x cs_x
	setvarvar cs_x x
	getactor[THISACTOR].y y
	subvarvar y cs_y
	setvarvar cs_y y
	getactor[THISACTOR].z z
	subvarvar z cs_z
	setvarvar cs_z z
	shiftvarr cs_z 4
	
	//dist2 = &off_40000 + dyy * dyy + dxx * dxx + dzz * dzz;
	setvarvar cs_dist2 cs_x
	mulvarvar cs_dist2 cs_dist2
	
	setvarvar cs_dy2 cs_y
	mulvarvar cs_dy2 cs_dy2
	addvarvar cs_dist2 cs_dy2
	
	setvarvar cs_dz2 cs_z
	mulvarvar cs_dz2 cs_dz2
	addvarvar cs_dist2 cs_dz2
	
	addvarvar cs_dist2 4194304 //262144

	//int area = tilesizy[nTile] * pSprite->xrepeat * tilesizx[nTile] * pSprite->yrepeat >> 1;
	getactor[THISACTOR].picnum picnum
	setvarvar cs_area tiledata[picnum].xsize
	mulvarvar cs_area sprite[THISACTOR].xrepeat
	mulvarvar cs_area tiledata[picnum].ysize
	mulvarvar cs_area sprite[THISACTOR].yrepeat
	shiftvarr cs_area 1

	//int force = ticks * &off_40000 / dist2;

	setvarvar cs_force 4194304 //262144
	mulvarvar cs_force cs_ticks
	divvarvar cs_force cs_dist2
	
	ifvarand spr_flags 1 ifvarn ai_mass 0 {
		//int impulse = area * force / mass; 
			
		setvarvar cs_impulse cs_force
		
		mulvarvar cs_impulse cs_area
		divvarvar cs_impulse ai_mass

		//dx = mulscale16(impulse, dx);
		//dy = mulscale16(impulse, dy);
		//dz = mulscale16(impulse, dz);

		mulscale cs_x cs_impulse cs_x 16
		mulscale cs_y cs_impulse cs_y 16
		mulscale cs_z cs_impulse cs_z 16
		
		addvarvar spr_xvel cs_x
		addvarvar spr_yvel cs_y
		addvarvar spr_zvel cs_z
	}

ends








