rem blaztap, by marcus
rem yep, the code is an experimental mess.

import "Raycaster.lib"
import "Keycodes.lib"
import "Speed.lib"
import "Math.lib"

constant:
	SKY_IMG 0
	PISTOL_IMG 1
	SOLDIER_ONE_BASE_IMG 100

	BARREL_ANIM_IMG_0	20
	BARREL_ANIM_IMG_1	21
	BARREL_ANIM_IMG_2	22
	BARREL_ANIM_IMG_3	23

	rem items, values from rc editor.
	TREASURE_1_ITEM	1
	TREASURE_2_ITEM	2
	TREASURE_3_ITEM	3
	LIFE_1_ITEM			4
	LIFE_2_ITEM			5
	KEY_ITEM				6
	GUN_2_ITEM			7
	GUN_3_ITEM			8
	AMO_ITEM				9
	BARREL_ITEM			10

	rem texture indexes.
	EXIT_SWITCH_OFF 	16
	EXIT_SWITCH_ON		17

	EXIT_DOOR_LOCKED		11
	EXIT_DOOR_UNLOCKED	12

	MAX_PBULLETS	16
	BULLET_TYPE		0
	BULLET_X			0
	BULLET_Z			1
	BULLET_DX		2
	BULLET_DZ		3

	MAX_ANIMS				16
	ANIM_IMG					0
	ANIM_END_IMG			1
	ANIM_FRAME_COUNTER 	2
	ANIM_OBJ_KEEP			3
	ANIM_X					0
	ANIM_Z					1
	ANIM_SIZE				2

	MAX_ENEMIES				32
	ENEMY_TYPE				0
	ENEMY_FRAME				1
	ENEMY_FRAME_COUNTER	2
	ENEMY_STATE				3
	ENEMY_TIMER				4
	ENEMY_STAMINA			5
	ENEMY_X					0
	ENEMY_Z					1
	ENEMY_ANGLE				2

	ENEMY_NOTHING			0
	ENEMY_MOVING			1
	ENEMY_HIT				2
	ENEMY_CHASING			3
	ENEMY_ATTACKING		4

visible:
	rem on screen message.
	vMessage$
	vMessageTimer
	vMessageR
	vMessageG
	vMessageB

	rem screen flash thing.
	vScreenR
	vScreenG
	vScreenB
	vScreenA

	rem player bullets. use two arrays, int and float, instead of
	rem objects for java compability.
	vPBullets[MAX_PBULLETS][1]
	vPBulletsF#[MAX_PBULLETS][4]
	vPBulletCounter

	rem animations.
	vAnims[MAX_ANIMS][4]
	vAnimsF#[MAX_ANIMS][3]
	vAnimCounter

	rem enemies.
	vEnemies[MAX_ENEMIES][6]
	vEnemiesF#[MAX_ENEMIES][3]

	rem player.
	vPlayerX#
	vPlayerZ#
	vPlayerAngle#

	rem gun.
	vGunBobAngle#
	vGunOffsetX#
	vGunWantedOffsetX#
	vGunTimer
	vGunFrame

	vKeys
	vLevel
	vUseSky
	vLevelCompleted

hidden:


rem create font 0, "courier new", 16
rem save font 0, "assets/courier.txt", "assets/courier.bmp"

set window 0, 0, 320, 240, false, 2
set redraw off

proc LoadAssets

proc RC_InitView 60.0, width(primary), height(primary)
proc RC_SetClearScreen false

vLevel = 1

do
	if not LoadLevel() then end

	shouldDraw = true

	do
		if keydown(VK_ESC, true) then end

		if not vLevelCompleted
			proc RC_Update 1.0
			proc UpdatePlayer
			proc UpdateEnemies
			proc UpdatePlayerBullets
			proc UpdateAnimations
		endif

		rem message timer.
		vMessageTimer = max(vMessageTimer - 1, 0)

		rem screen flash.
		if vScreenA > 0
			vScreenA = vScreenA - 16
		endif

		rem draw?
		if shouldDraw
			set color 0, 0, 0
			cls
			if vUseSky
				set color 255, 255, 255
				x = int(vPlayerAngle*320.0/60.0)%320
				draw image SKY_IMG, -x, 0
				draw image SKY_IMG, -x + 320, 0
			endif

			proc RC_Render vPlayerX, vPlayerZ, vPlayerAngle
			set color 255, 255, 255
			draw image PISTOL_IMG, (width(primary) - width(PISTOL_IMG))/2 + int(vGunOffsetX), 240 - height(PISTOL_IMG) + int(abs#(sin(vGunBobAngle)*8.0)), vGunFrame

			if vScreenA > 0
				set color vScreenR, vScreenG, vScreenB, vScreenA
				cls
			endif

			if vMessageTimer > 0
				set caret width(primary)/2, 108
				set color vMessageR, vMessageG, vMessageB
				center vMessage
			endif
			redraw
		endif

		shouldDraw = SPD_HoldFrameDraw(60)
	until vLevelCompleted = true and vMessageTimer = 0

	vLevel = vLevel + 1
loop

procedure LoadAssets()
	load font 0, "assets/courier.txt", "assets/courier.bmp"

	load image SKY_IMG, "assets/night_sky.bmp"
	load image PISTOL_IMG, "assets/pistol.bmp"
	set image grid PISTOL_IMG, 2, 1
	set image colorkey PISTOL_IMG, 152, 0, 136

	load image BARREL_ANIM_IMG_0, "assets/barrel_anim_0.bmp"
	load image BARREL_ANIM_IMG_1, "assets/barrel_anim_1.bmp"
	load image BARREL_ANIM_IMG_2, "assets/barrel_anim_2.bmp"
	load image BARREL_ANIM_IMG_3, "assets/barrel_anim_3.bmp"
	set image colorkey BARREL_ANIM_IMG_0, 152, 0, 136
	set image colorkey BARREL_ANIM_IMG_1, 152, 0, 136
	set image colorkey BARREL_ANIM_IMG_2, 152, 0, 136
	set image colorkey BARREL_ANIM_IMG_3, 152, 0, 136

	rem load soldier 1 images.
	for i = 0 to 45
		load image SOLDIER_ONE_BASE_IMG + i, "assets/" + str$(54 + i) + ".bmp"
		set image colorkey SOLDIER_ONE_BASE_IMG + i, 152, 0, 136
	next
endproc

function LoadLevel()
	flags[][] = RC_LoadMap("assets/level" + str$(vLevel) + ".txt")
	if sizeof(flags) = 0 then return false

	if vLevel = 1
		vUseSky = true
	else
		vUseSky = false
	endif

	enemy = 0
	for i = 0 to sizeof(flags, 0) - 1
		if flags[i][RC_FLAG] = 1
			vEnemies[enemy][ENEMY_TYPE] = SOLDIER_ONE_BASE_IMG
			vEnemies[enemy][ENEMY_FRAME] = 0
			vEnemies[enemy][ENEMY_FRAME_COUNTER] = 0
			vEnemies[enemy][ENEMY_TIMER] = 60
			vEnemies[enemy][ENEMY_STAMINA] = 3
			vEnemiesF[enemy][ENEMY_X] = float(flags[i][RC_X]) + 0.5
			vEnemiesF[enemy][ENEMY_Z] = float(flags[i][RC_Z]) + 0.5
			vEnemiesF[enemy][ENEMY_ANGLE] = float(((enemy%4)*90)%360)
			if rnd(2) = 0
				vEnemies[enemy][ENEMY_STATE] = ENEMY_MOVING
			else
				vEnemies[enemy][ENEMY_STATE] = ENEMY_NOTHING
			endif
			proc RC_AddObject 200 + enemy, SOLDIER_ONE_BASE_IMG, vEnemiesF[enemy][ENEMY_X], vEnemiesF[enemy][ENEMY_Z], 0.0, 0.75, -1, -1
			enemy = enemy + 1
		endif
	next

	vPlayerX# = float(flags[0][RC_X]) + 0.5
	vPlayerZ# = float(flags[0][RC_Z]) + 0.5

	vPlayerAngle# = float(flags[0][RC_ANGLE])

	vGunBobAngle# = 0.0
	vGunOffsetX# = 0.0
	vGunWantedOffsetX# = 0.0
	vGunTimer = 0
	vGunFrame = 0

	vMessage = ""
	vMessageTimer = 0

	vScreenR = 0
	vScreenG = 0
	vScreenB = 0
	vScreenA = 0

	vLevelCompleted = false
	vKeys = 0

	return true
endfunc

procedure UpdatePlayer()
	vGunWantedOffsetX = 0.0
	if keydown(VK_LEFT)
		vPlayerAngle = vPlayerAngle - 2.0
		vGunWantedOffsetX = -16.0
	endif
	if keydown(VK_RIGHT) 
		vPlayerAngle = vPlayerAngle + 2.0
		vGunWantedOffsetX = 16.0
	endif
	vGunOffsetX = 0.9*vGunOffsetX + 0.1*vGunWantedOffsetX
	if vPlayerAngle < 0.0 then vPlayerAngle = vPlayerAngle + 360.0
	if vPlayerAngle >= 360.0 then vPlayerAngle = vPlayerAngle - 360.0
	if keydown(VK_UP)
		pos#[] = RC_Move(0.4, vPlayerX, vPlayerZ, cos(vPlayerAngle)*0.04, sin(vPlayerAngle)*0.04)
		vPlayerX = pos[RC_X]
		vPlayerZ = pos[RC_Z]
		vGunBobAngle = vGunBobAngle + 4.0
	endif
	if keydown(VK_DOWN)
		pos#[] = RC_Move(0.4, vPlayerX, vPlayerZ, -cos(vPlayerAngle)*0.04, -sin(vPlayerAngle)*0.04)
		vPlayerX = pos[RC_X]
		vPlayerZ = pos[RC_Z]
		vGunBobAngle = vGunBobAngle - 4.0
	endif

	if keydown(VK_SPACE, true)
		fpos[] = RC_FacingPos(vPlayerX, vPlayerZ, vPlayerAngle)
		rem unused exit switch?
		wall = RC_GetWall(fpos[RC_X], fpos[RC_Z])
		if wall = EXIT_SWITCH_OFF
			rem change wall image to used exit switch image.
			proc RC_SetWall fpos[RC_X], fpos[RC_Z], RC_GetImage(EXIT_SWITCH_ON)
			rem flag + 100 tells where destination (exit door) is located.
			flag = RC_GetFlag(fpos[RC_X], fpos[RC_Z]) + 100
			fpos[] = GetFlagPos(flag)
			rem open exit by changing the image.
			proc RC_SetWall fpos[0], fpos[1], RC_GetImage(RC_GetWall(fpos[0], fpos[1]) + 1)
			
			proc DisplayMessage "Exit unlocked!", true
		elseif wall = EXIT_SWITCH_ON
			proc DisplayMessage "Go find the exit!", false
		rem exit level.
		elseif wall = EXIT_DOOR_UNLOCKED and vLevelCompleted = false
			proc DisplayMessage "Level completed!", true
			vLevelCompleted = true
		elseif wall = EXIT_DOOR_LOCKED
			proc DisplayMessage "The exit is locked!", false
		rem door.
		elseif RC_GetDoor(fpos[RC_X], fpos[RC_Z])
			rem locked?
			if RC_GetFlag(fpos[RC_X], fpos[RC_Z])
				if vKeys > 0
					vKeys = vKeys - 1
					proc RC_OpenDoor fpos[RC_X], fpos[RC_Z]
					proc DisplayMessage "You used a key!", true
				else
					proc DisplayMessage "You don't have a key!", false
				endif
			else
				proc RC_OpenDoor fpos[RC_X], fpos[RC_Z]
			endif
		endif
	endif

	if vGunTimer = 0
		if keydown(VK_CTRL, true)
			vGunTimer = 60
			vGunFrame = 1
			proc AddPlayerBullet 1, vPlayerX, vPlayerZ, cos(vPlayerAngle)*0.2, sin(vPlayerAngle)*0.2
		endif
	else
		vGunTimer = vGunTimer - 1
		if vGunTimer < 50 then vGunFrame = 0
	endif

	rem pick something up?
	item = RC_GetItem(int(vPlayerX), int(vPlayerZ))
	if item >= TREASURE_1_ITEM and item <= AMO_ITEM
		proc FlashScreen 255, 255, 0
		if item = TREASURE_1_ITEM
		elseif item = TREASURE_2_ITEM
		elseif item = TREASURE_3_ITEM
		elseif item = LIFE_1_ITEM
		elseif item = LIFE_2_ITEM
		elseif item = KEY_ITEM
			vKeys = vKeys + 1
			proc DisplayMessage "You found a key!", true
		elseif item = GUN_2_ITEM
		elseif item = GUN_3_ITEM
		elseif item = AMO_ITEM
		endif
		proc RC_RemoveItem int(vPlayerX), int(vPlayerZ)
	endif
endproc

function GetFlagPos[](flag)
	pos[]
	for z = 0 to RC_GetMapHeight() - 1
		for x = 0 to RC_GetMapWidth() - 1
			if RC_GetFlag(x, z) = flag
				pos[] = [x, z]
				break
			endif
		next
	next
	return pos
endfunc

procedure DisplayMessage(msg$, good)
	vMessage = msg
	vMessageTimer = 120
	if good
		vMessageR = 0
		vMessageG = 200
		vMessageB = 0
	else
		vMessageR = 200
		vMessageG = 0
		vMessageB = 0
	endif
endproc

procedure AddPlayerBullet(type, x#, z#, dx#, dz#)
	vPBullets[vPBulletCounter][BULLET_TYPE] = type
	vPBulletsF[vPBulletCounter][BULLET_X] = x
	vPBulletsF[vPBulletCounter][BULLET_Z] = z
	vPBulletsF[vPBulletCounter][BULLET_DX] = dx
	vPBulletsF[vPBulletCounter][BULLET_DZ] = dz
	vPBulletCounter = (vPBulletCounter + 1)%MAX_PBULLETS
endproc

procedure UpdatePlayerBullets()
	for i = 0 to MAX_PBULLETS - 1
		if vPBullets[i][BULLET_TYPE] > 0
			vPBulletsF[i][BULLET_X] = vPBulletsF[i][BULLET_X] + vPBulletsF[i][BULLET_DX]
			vPBulletsF[i][BULLET_Z] = vPBulletsF[i][BULLET_Z] + vPBulletsF[i][BULLET_DZ]
			x = int(vPBulletsF[i][BULLET_X])
			z = int(vPBulletsF[i][BULLET_Z])
			rem an obstacle (wall or item) at current position?
			if RC_ObstacleAt(x, z)
				vPBullets[i][BULLET_TYPE] = 0
				item = RC_GetItem(x, z)
				rem barrel?
				if item = BARREL_ITEM
					proc RC_RemoveItem x, z
					proc AddAnimation float(x) + 0.5, float(z) + 0.5, BARREL_ANIM_IMG_0, BARREL_ANIM_IMG_3, 0.75, false
				endif
			else
				rem check for collisions with enemies.
				px# = vPBulletsF[i][BULLET_X]
				pz# = vPBulletsF[i][BULLET_Z]
				hit = false
				for j = 0 to MAX_ENEMIES - 1
					if vEnemies[j][ENEMY_TYPE] > 0
						dx# = vEnemiesF[j][ENEMY_X] - px
						dz# = vEnemiesF[j][ENEMY_Z] - pz
						if dx*dx + dz*dz < 0.1
							proc EnemyHit j, 1
							hit = true
						endif
					endif
				next
				if hit then vPBullets[i][BULLET_TYPE] = 0
			endif 
		endif
	next
endproc

procedure AddAnimation(x#, z#, startImage, endImage, size#, objKeep)
	vAnims[vAnimCounter][ANIM_IMG] = startImage
	vAnims[vAnimCounter][ANIM_END_IMG] = endImage
	vAnims[vAnimCounter][ANIM_FRAME_COUNTER] = 0
	vAnims[vAnimCounter][ANIM_OBJ_KEEP] = objKeep
	vAnimsF[vAnimCounter][ANIM_X] = x
	vAnimsF[vAnimCounter][ANIM_Z] = z
	vAnimsF[vAnimCounter][ANIM_SIZE] = size
	
	proc RC_AddObject 100 + vAnimCounter, startImage, x, z, 0.0, size, -1, -1
	vAnimCounter = (vAnimCounter + 1)%MAX_ANIMS
endproc

procedure UpdateAnimations()
	for i = 0 to MAX_ANIMS - 1
		if vAnims[i][ANIM_IMG] > 0
			vAnims[i][ANIM_FRAME_COUNTER] = (vAnims[i][ANIM_FRAME_COUNTER] + 1)%8
			if vAnims[i][ANIM_FRAME_COUNTER] = 0
				vAnims[i][ANIM_IMG] = vAnims[i][ANIM_IMG] + 1
				if vAnims[i][ANIM_IMG] > vAnims[i][ANIM_END_IMG]
					vAnims[i][ANIM_IMG] = 0
					proc RC_RemoveObject 100 + i
					if vAnims[i][ANIM_OBJ_KEEP] > 0
						proc RC_AddObject vAnims[i][ANIM_OBJ_KEEP], vAnims[i][ANIM_END_IMG], vAnimsF[i][ANIM_X], vAnimsF[i][ANIM_Z], 0.0, vAnimsF[i][ANIM_SIZE], -1, -1 
					endif
				else
					proc RC_SetObjectImage 100 + i, vAnims[i][ANIM_IMG]
				endif 
			endif 
		endif
	next
endproc

procedure UpdateEnemies()
	for i = 0 to MAX_ENEMIES - 1
		if vEnemies[i][ENEMY_TYPE] > 0
			rem do different stuff pending on enemy's state.
			state = vEnemies[i][ENEMY_STATE]
			if state = ENEMY_MOVING
				vEnemies[i][ENEMY_FRAME_COUNTER] = (vEnemies[i][ENEMY_FRAME_COUNTER] + 1)%8
				if vEnemies[i][ENEMY_FRAME_COUNTER] = 0
					vEnemies[i][ENEMY_FRAME] = vEnemies[i][ENEMY_FRAME] + 1
					if vEnemies[i][ENEMY_FRAME] > 4 then vEnemies[i][ENEMY_FRAME] = 1
				endif

				dx# = cos(vEnemiesF[i][ENEMY_ANGLE])*0.015
				dz# = sin(vEnemiesF[i][ENEMY_ANGLE])*0.015
				pos#[] = RC_Move(0.2, vEnemiesF[i][ENEMY_X], vEnemiesF[i][ENEMY_Z], dx, dz)
				info[] = RC_GetCollisionInfo()

				if info[RC_WEST] or info[RC_EAST] or info[RC_SOUTH] or info[RC_NORTH]
					if rnd(2) = 0
						vEnemiesF[i][ENEMY_ANGLE] = float(int(vEnemiesF[i][ENEMY_ANGLE]) + 90)
					else
						vEnemiesF[i][ENEMY_ANGLE] = float(int(vEnemiesF[i][ENEMY_ANGLE]) - 90)
					endif	
					if vEnemiesF[i][ENEMY_ANGLE] < 0.0 then vEnemiesF[i][ENEMY_ANGLE] = vEnemiesF[i][ENEMY_ANGLE] + 360.0
					if vEnemiesF[i][ENEMY_ANGLE] > 360.0 then vEnemiesF[i][ENEMY_ANGLE] = vEnemiesF[i][ENEMY_ANGLE] - 360.0 
					vEnemies[i][ENEMY_TIMER] = 30
					vEnemies[i][ENEMY_STATE] = ENEMY_NOTHING
				endif
				
				vEnemiesF[i][ENEMY_X] = pos[RC_X]
				vEnemiesF[i][ENEMY_Z] = pos[RC_Z]

				rem see player?
				vEnemies[i][ENEMY_TIMER] = vEnemies[i][ENEMY_TIMER] - 1 
				if vEnemies[i][ENEMY_TIMER] <= 0
					vEnemies[i][ENEMY_TIMER] = 60
					if EnemyCanSeePlayer(i, 45.0)
						proc EnemyStartChase i, 20
					endif
				endif
			elseif state = ENEMY_NOTHING
				vEnemies[i][ENEMY_FRAME] = 0
				vEnemies[i][ENEMY_TIMER] = vEnemies[i][ENEMY_TIMER] - 1
				if vEnemies[i][ENEMY_TIMER] <= 0
					vEnemies[i][ENEMY_STATE] = ENEMY_MOVING
					vEnemies[i][ENEMY_FRAME] = 1
					vEnemies[i][ENEMY_FRAME_COUNTER] = 0
					vEnemies[i][ENEMY_TIMER] = 20
				endif
			elseif state = ENEMY_HIT
				vEnemies[i][ENEMY_TIMER] = vEnemies[i][ENEMY_TIMER] - 1
				if vEnemies[i][ENEMY_TIMER] <= 0
					proc EnemyStartChase i, 20
				endif
			elseif state = ENEMY_CHASING
				vEnemies[i][ENEMY_FRAME_COUNTER] = (vEnemies[i][ENEMY_FRAME_COUNTER] + 1)%6
				if vEnemies[i][ENEMY_FRAME_COUNTER] = 0
					vEnemies[i][ENEMY_FRAME] = vEnemies[i][ENEMY_FRAME] + 1
					if vEnemies[i][ENEMY_FRAME] > 4 then vEnemies[i][ENEMY_FRAME] = 1
				endif

				dx# = cos(vEnemiesF[i][ENEMY_ANGLE])*0.025
				dz# = sin(vEnemiesF[i][ENEMY_ANGLE])*0.025
				pos#[] = RC_Move(0.2, vEnemiesF[i][ENEMY_X], vEnemiesF[i][ENEMY_Z], dx, dz)
				info[] = RC_GetCollisionInfo()

				vEnemies[i][ENEMY_TIMER] = vEnemies[i][ENEMY_TIMER] - 1

				vEnemiesF[i][ENEMY_X] = pos[RC_X]
				vEnemiesF[i][ENEMY_Z] = pos[RC_Z]
				
				if info[RC_WEST] or info[RC_EAST] or info[RC_SOUTH] or info[RC_NORTH] or vEnemies[i][ENEMY_TIMER] <= 0
					if RC_Visible(vPlayerX, vPlayerZ, vEnemiesF[i][ENEMY_X], vEnemiesF[i][ENEMY_Z])
						vEnemiesF[i][ENEMY_ANGLE] = AngleToF(vEnemiesF[i][ENEMY_X], vEnemiesF[i][ENEMY_Z], vPlayerX, vPlayerZ)
               	if vEnemies[i][ENEMY_TIMER] <= 0
							vEnemies[i][ENEMY_TIMER] = 40
							vEnemies[i][ENEMY_STATE] = ENEMY_ATTACKING
							vEnemies[i][ENEMY_FRAME] = 44
						endif
					else
						vEnemies[i][ENEMY_STATE] = ENEMY_NOTHING
						vEnemiesF[i][ENEMY_ANGLE] = float(rnd(4)*90)
						vEnemies[i][ENEMY_TIMER] = 60
					endif
				endif
				
			elseif state = ENEMY_ATTACKING
				vEnemies[i][ENEMY_TIMER] = vEnemies[i][ENEMY_TIMER] - 1
				if vEnemies[i][ENEMY_TIMER] = 20
					vEnemies[i][ENEMY_FRAME] = 45
					rem player hit?
					if rnd(2) = 0 and RC_Visible(vPlayerX, vPlayerZ, vEnemiesF[i][ENEMY_X], vEnemiesF[i][ENEMY_Z])
						proc FlashScreen 255, 0, 0
					endif
				endif
				if vEnemies[i][ENEMY_TIMER] <= 0
					if RC_Visible(vPlayerX, vPlayerZ, vEnemiesF[i][ENEMY_X], vEnemiesF[i][ENEMY_Z])
						proc EnemyStartChase i, 120
					else
						vEnemies[i][ENEMY_STATE] = ENEMY_NOTHING
						vEnemiesF[i][ENEMY_ANGLE] = float(rnd(4)*90)
						vEnemies[i][ENEMY_TIMER] = 60
					endif
				endif
			endif

			proc RC_SetObjectPos 200 + i, vEnemiesF[i][ENEMY_X], vEnemiesF[i][ENEMY_Z], 0.0

			if vEnemies[i][ENEMY_STATE] = ENEMY_MOVING or vEnemies[i][ENEMY_STATE] = ENEMY_NOTHING or vEnemies[i][ENEMY_STATE] = ENEMY_CHASING
				rem finding the correct image to use depending on the
				rem enemies direction and the player's position might
				rem seem trivial. but it depends a lot on the setup
				rem of the graphics.
				dx# = vEnemiesF[i][ENEMY_X] - vPlayerX
				dz# = vEnemiesF[i][ENEMY_Z] - vPlayerZ
				k# = 1.0/sqr(dx*dx + dz*dz)
				dx = dx*k
				dz = dz*k
				if dz < 0.0
					a# = 360.0 - acos(dx)
				else
					a# = acos(dx)
				endif
				a = a - vEnemiesF[i][ENEMY_ANGLE] + 180.0 - 22.5
				if a >= 360.0 then a = a - 360.0
				if a < 0.0 then a = a + 360.0

				proc RC_SetObjectImage 200 + i, vEnemies[i][ENEMY_TYPE] + 7 - int(a)*8/360 + vEnemies[i][ENEMY_FRAME]*8
			else
				proc RC_SetObjectImage 200 + i, vEnemies[i][ENEMY_TYPE] + vEnemies[i][ENEMY_FRAME]
			endif

		endif
	next
endproc

procedure EnemyHit(enemy, strength)
	vEnemies[enemy][ENEMY_STAMINA] = vEnemies[enemy][ENEMY_STAMINA] - strength
	if vEnemies[enemy][ENEMY_STAMINA] <= 0
		proc AddAnimation vEnemiesF[enemy][ENEMY_X], vEnemiesF[enemy][ENEMY_Z], vEnemies[enemy][ENEMY_TYPE] + 40, vEnemies[enemy][ENEMY_TYPE] + 43, 0.75, 200 + enemy
		vEnemies[enemy][ENEMY_TYPE] = 0
		proc RC_RemoveObject 200 + enemy
	else
		vEnemies[enemy][ENEMY_STATE] = ENEMY_HIT
		vEnemies[enemy][ENEMY_TIMER] = 20
		vEnemies[enemy][ENEMY_FRAME] = 40	
	endif
endproc

procedure EnemyStartChase(enemy, timer)
	vEnemies[enemy][ENEMY_STATE] = ENEMY_CHASING
	vEnemies[enemy][ENEMY_FRAME] = 1
	vEnemies[enemy][ENEMY_TIMER] = timer
	vEnemies[enemy][ENEMY_FRAME_COUNTER] = 0
	vEnemiesF[enemy][ENEMY_ANGLE] = AngleToF(vEnemiesF[enemy][ENEMY_X], vEnemiesF[enemy][ENEMY_Z], vPlayerX, vPlayerZ)					
endproc

function EnemyCanSeePlayer(enemy, fov#)
	dx# = vPlayerX - vEnemiesF[enemy][ENEMY_X]
	dz# = vPlayerZ - vEnemiesF[enemy][ENEMY_Z]
	if dx*dx + dz*dz < 16.0
		if RC_Visible(vPlayerX, vPlayerZ, vEnemiesF[enemy][ENEMY_X], vEnemiesF[enemy][ENEMY_Z])
			u#[] = [dx, dz]
			v#[] = [cos(vEnemiesF[enemy][ENEMY_ANGLE]), sin(vEnemiesF[enemy][ENEMY_ANGLE])]
			rem if V_AngleBetween(u, v) < fov*0.5
			rem	return true
			rem endif
			proc V_Normalize u
			proc V_Normalize v
			d# = V_Dot(u, v)
			d = max#(d, -1.0)
			d = min#(d, 1.0)
			if acos(d) < fov*0.5
				return true
			endif
		endif
	endif
	return false
endfunc

procedure FlashScreen(r, g, b)
	vScreenR = r
	vScreenG = g
	vScreenB = b
	vScreenA = 255
endproc

procedure ERROR(msg$)
	set color 0, 0, 0
	cls
	set color 255, 255, 255
	set caret 0, 0
	wln msg$
	redraw
	wait keydown
	end
endproc