/*
Author: DRON
Site: http://dron.deeprosoft.com/
*/
#include "stdafx.h"

string work_dir;

ENG_DYNAMIC_FUNC

IEngineCore	*pEngineCore;
IRender *pRender;
IRender2D *pRender2D;
IRender3D *pRender3D;
IInput *pInput;

uint counter = 0;

float px, py,/*Player X and Y coord*/ pa /*Player Angle*/;

int mw = 20, mh = 20; //size of current map
int map_fc = 0; //dtermines type of floor and ceiling
int cur_level = 0;

IBitmapFont *pFont;
ITexture *pBG, *pHUD, *pPistol, *pShotgun, *pFloor[2], *pCilling[2], *pWall[10], *pSprite[12], *pIskry, *pSoldier, *pBlood, *pDemon;
IMesh *pBox;

ISoundSample *pDemonPain, *pDemonShoot, *pDemonDie, *pSoldierPain, *pSoldierShoot, *pSoldierDie[2], *pSndPistol, *pSndShotgun, *pPain, *pDie,
	*pShotgunPickup, *pMedkit, *pSndLevel[3], *pSndScript[4], *pSndKill[8], *pSndEnding;

bool game = false;

int health = 100, pistol_ammo = 20, shotgun_ammo = 0;
float shot_anim = 0.f;
int red_screen = 0;

//1 - 10 - Walls
//11 - 20 - Sprites
//21 - shotgun 22 - medkit 23 - soldier 24 - demon
//90 - 94 - script speach
//99 - player respawn 100 - next level

const char map1[20][20] = {
	1 , 8 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
	1 , 99, 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 8 , 100, 0, 23, 0 , 0 , 0 , 23, 0 , 1 ,
	1 , 0 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 1 ,
	1 , 0 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 1 ,
	3 , 91, 15, 3 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 1 ,
	3 , 0 , 13, 3 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 1 ,
	3 , 0 , 3 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 1 ,
	3 , 0 , 3 , 0 , 0 , 6 , 6 , 6 , 6 , 6 , 6 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 1 ,
	3 , 0 , 3 , 0 , 0 , 6 , 0 , 16, 0 , 16, 6 , 0 , 2 , 2 , 2 , 2 , 2 , 9 , 0 , 1 ,
	3 , 0 , 3 , 3 , 3 , 6 , 16, 0 , 16, 0 , 6 , 0 , 2 , 0 , 23, 0 , 2 , 0 , 0 , 1 ,
	3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 3 , 0 , 2 , 0 , 0 , 0 , 0 , 0 , 0 , 1 ,
	3 , 0 , 0 , 0 , 0 , 0 , 92, 0 , 0 , 91, 3 , 0 , 2 , 22, 9 , 0 , 2 , 0, 0 , 1 ,
	3 , 0 , 12, 0 , 0 , 0 , 12, 0 , 0 , 0 , 3 , 0 , 2 , 0 , 0 , 0 , 2 , 23, 0 , 1 ,
	3 , 0 , 0 , 0 , 90, 0 , 0 , 0 , 0 , 0 , 3 , 0 , 2 , 0 , 23, 0 , 2 , 0 , 0 , 1 ,
	3 , 0 , 0 , 90, 14, 90, 0 , 0 , 0 , 0 , 3 , 0 , 2 , 2 , 2 , 2 , 2 , 0 , 0 , 1 ,
	3 , 0 , 0 , 0 , 90, 0 , 0 , 0 , 0 , 0 , 3 , 0 , 2 , 0 , 0 , 0 , 0 , 0 , 0 , 1 ,
	3 , 0 , 12, 0 , 0 , 0 , 12, 0 , 0 , 0 , 3 , 7 , 7 , 0 , 0 , 0 , 0 , 0 , 0 , 1 ,
	3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 92, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 ,
	3 , 13, 0 , 0 , 0 , 91, 0 , 0 , 0 , 15, 3 , 7 , 7 , 0 , 0 , 0 , 0 , 0 , 0 , 1 ,
	3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 0 , 2 , 1 , 1 , 1 , 1 , 1 , 1 , 1 
};

const char map2[20][20] = {
	1 , 8 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 9 , 9 , 9 , 9 , 9 , 9 , 7 , 7 , 1 , 1 , 1 ,
	1 ,100, 1 , 0 , 0 , 0 , 0 , 0 , 0 , 9 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 99, 8 ,
	5 , 23, 5 , 0 , 0 , 0 , 0 , 0 , 0 , 9 , 0 , 0 , 0 , 0 , 0 , 7 , 7 , 1 , 1 , 1 ,
	5 , 0 , 5 , 0 , 0 , 0 , 0 , 0 , 0 , 9 , 0 , 0 , 0 , 0 , 0 , 9 , 0 , 0 , 0 , 0 ,
	5 , 0 , 5 , 0 , 0 , 0 , 0 , 0 , 0 , 9 , 23, 7 , 23, 0 , 0 , 9 , 9 , 9 , 9 , 9 ,
	5 , 0 , 5 , 0 , 0 , 0 , 0 , 0 , 0 , 9 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 23, 9 ,
	5 , 0 , 5 , 0 , 0 , 0 , 0 , 0 , 0 , 9 , 23, 0 , 0 , 0 , 7 , 22, 0 , 7 , 0 , 9 ,
	7 , 0 , 7 , 0 , 0 , 0 , 0 , 0 , 0 , 9 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 9 ,
	10, 0 , 10, 10, 10, 7 , 5 , 5 , 7 , 9 , 0 , 7 , 0 , 0 , 0 , 0 , 23, 0 , 0 , 9 ,
	10, 0 , 0 , 0 , 0 , 10, 16, 18, 10, 9 , 0 , 0 , 0 , 23, 0 , 0 , 0 , 0 , 0 , 9 ,
	10, 0 , 0 , 0 , 0 , 10, 0 , 0 , 10, 9 , 9 , 9 , 9 , 9 , 9 , 9 , 9 , 7 , 0 , 7 ,
	10, 0 , 0 , 23, 0 , 10, 0 , 0 , 10, 10, 10, 10, 0 , 0 , 0 , 0 , 0 , 10, 0 , 10,
	10, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 9 , 0 , 10, 0 , 0 , 0 , 0 , 0 , 10, 21, 10,
	10, 0 , 0 , 0 , 0 , 0 , 23, 23, 9 , 9 , 0 , 10, 0 , 0 , 0 , 0 , 0 , 10, 0 , 10,
	7 , 0 , 0 , 7 , 7 , 9 , 0 , 0 , 9 , 0 , 0 , 7 , 10, 10, 10, 10, 10, 10, 0 , 10,
	9 , 23, 0 , 9 , 18, 9 , 0 , 0 , 9 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 10,
	9 , 0 , 0 , 9 , 22, 9 , 0 , 0 , 9 , 0 , 9,  7 , 0 , 0 , 23, 0 , 0 , 0 , 0 , 10,
	9 , 16, 19, 9 , 0 , 0 , 0 , 0 , 9 , 23, 9 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 10,
	9 , 5 , 5 , 9 , 23, 0 , 0 , 0 , 0 , 0 , 9 , 0 , 0 , 0 , 0 , 0 , 23, 0 , 0 , 10,
	0 , 0 , 0 , 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10
};

const char map3[20][20] = {
	1 , 1 , 1 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 0 , 0 , 5 , 5 , 5 , 5 , 5 , 7 , 1 , 1 ,
	8 , 99, 0 , 23, 93, 20, 20, 22, 20, 7 , 4 , 4 , 5 , 22, 0 , 0 , 0 , 0 ,100, 8 ,
	1 , 1 , 1 , 5 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 4 , 5 , 0 , 0 , 0 , 0 , 7 , 1 , 1 ,
	0 , 0 , 0 , 5 , 0 , 0 , 0 , 93, 0 , 0 , 0 , 4 , 5 , 0 , 0 , 23, 0 , 0 , 0 , 5 ,
	0 , 0 , 0 , 5 , 20 ,0 , 20, 21, 20, 7 , 0 , 4 , 5 , 0 , 0 , 0 , 0 , 0 , 0 , 5 ,
	4 , 4 , 9 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 0 , 5 , 5 , 0 , 0 , 0 , 0 , 23, 0 , 5 ,
	4 , 0 , 0 , 0 , 0 , 19, 5 , 0 , 0 , 5 , 17, 5 , 5 , 23, 0 , 11, 24, 0 , 0 , 5 ,
	4 , 0 , 9 , 5 , 0 , 23, 5 , 0 , 0 , 9 , 23, 9 , 5 , 0 , 0 , 0 , 0 , 0 , 0 , 5 ,
	4 , 17, 4 , 5 , 0 , 0 , 9 , 4 , 4 , 4 , 0 , 4 , 5 , 0 , 0 , 0 , 0 , 0 , 0 , 5 ,
	4 , 0 , 4 , 5 , 0 , 0 , 0 , 0 , 17, 23, 0 , 4 , 5 , 11, 0 , 0 , 17, 0 , 0 , 5 ,
	9 , 23, 9 , 5 , 23, 0 , 9 , 4 , 4 , 4 , 4 , 4 , 5 , 0 , 23, 0 , 0 , 0 , 0 , 5 ,
	6 , 23, 6 , 5 , 0 , 23, 5 , 5 , 5 , 5 , 5 , 5 , 5 , 0 , 0 , 0 , 0 , 0 , 0 , 5 ,
	6 , 0 , 6 , 5 , 0 , 93, 5 , 22, 0 , 0 , 0 , 0 , 11, 0 , 0 , 0 , 0 , 11, 0 , 5 ,
	6 , 0 , 6 , 5 , 20, 20, 5 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 5 ,
	6 , 0 , 6 , 5 , 5 , 5 , 5 , 0 , 0 , 0 , 17, 0 , 23, 0 , 0 , 11, 0 , 0 , 0 , 5 ,
	6 , 0 , 6 , 5 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 5 ,
	6 , 0 , 6 , 7 , 0 , 0 , 0 , 0 , 21, 0 , 0 , 0 , 0 , 11, 0 , 0 , 0 , 0 , 0 , 5 ,
	6 , 23, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 23, 0 , 17, 0 , 5 ,
	6 , 16, 22, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 23, 0 , 0 , 0 , 0 , 0 , 22, 5 ,
	6 , 6 , 6 , 7 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 
};

const char map4[20][20] = {
	0 , 0 , 0 , 0 , 4 , 4 , 9 , 4 , 4 , 4 , 4 , 9 , 4 , 5 , 5 , 5 , 5 , 0 , 0 , 0 ,
	0 , 0 , 0 , 1 , 7 , 0 , 0 , 0 , 6 , 23, 0 , 6 , 20, 23, 6 , 22, 5 , 0 , 0 , 0 ,
	0 , 0 , 0 , 8 , 99, 21, 7 , 0 , 17, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 5 , 0 , 0 , 0 ,
	0 , 0 , 0 , 1 , 7 , 0 , 0 , 0 , 18, 6 , 23, 0 , 6 , 23, 0 , 0 , 5 , 0 , 0 , 0 ,
	0 , 0 , 0 , 0 , 4 , 4 , 9 , 4 , 4 , 4 , 4 , 9 , 4 , 5 , 11, 0 , 5 , 0 , 0 , 0 ,
	0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 5 , 0 , 0 , 5 , 0 , 0 , 0 ,
	0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 5 , 0 , 11, 5 , 0 , 0 , 0 ,
	0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 5 , 0 , 23, 5 , 0 , 0 , 0 ,
	0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 9 , 0 , 0 , 9 , 0 , 0 , 0 ,
	0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 10, 11, 17, 10, 0 , 0 , 0 ,
	0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 10, 23, 0 , 10, 0 , 0 , 0 ,
	0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 10, 0 , 0 , 10, 0 , 0 , 0 ,
	0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 10, 2 , 0 , 10, 0 , 0 , 0 ,
	0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 10, 20, 0 , 10, 0 , 0 , 0 ,
	0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 10, 0 , 24, 10, 0 , 0 , 0 ,
	0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 10, 0 , 2 , 10, 0 , 0 , 0 ,
	0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 9 , 10, 0 , 0 , 10, 0 , 0 , 0 ,
	0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 13, 0 , 0 , 0 , 0 , 23, 23, 10, 0 , 0 , 0 ,
	0 , 0 , 0 , 0 , 0 , 0 , 0 , 8 ,100, 24, 0 , 0 , 0 , 0 , 0 , 19, 10, 0 , 0 , 0 ,
	0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 9 , 10, 10, 10, 10, 0 , 0 , 0 ,
};

const char map5[20][20] = {
	1 , 1 , 1 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 ,
	8 , 99, 0 , 0 , 21, 92, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 23, 0 , 0 , 0 , 0 , 13, 3 ,
	1 , 1 , 1 , 3 , 3 , 0 , 0 , 0 , 0 , 0 , 23, 0 , 0 , 0 , 0 , 14, 0 , 0 , 0 , 3 ,
	0 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 90, 0 , 0 , 22, 0 , 23, 0 , 0 , 0 , 0 , 0 , 3 ,
	0 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 3 , 0 , 0 , 21, 0 , 22, 0 , 0 , 3 ,
	0 , 0 , 0 , 0 , 3 , 0 , 22, 3 , 23 , 12, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 12, 0 , 3 ,
	0 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 16, 0 , 0 , 0 , 0 , 0 , 0, 0 , 3 ,
	0 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 16, 0 , 23, 0 , 0 , 0 , 3 ,
	0 , 0 , 0 , 0 , 3 , 0 , 90, 14, 0 , 0 , 0 , 90, 16, 0 , 0 , 21, 0 , 3 , 0 , 3 ,
	0 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 0 , 0 , 15, 22, 16, 23, 0 , 15, 0 , 24, 0 , 3 ,
	0 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 21, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 3 ,
	0 , 0 , 0 , 0 , 3 , 0 , 0 , 3 , 0 , 0 , 0 , 16, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 3 ,
	0 , 0 , 0 , 0 , 3 , 22, 15, 0 , 23, 0 , 0 , 0 , 0 , 0 , 16, 23, 0 , 0 , 0 , 3 ,
	0 , 0 , 0 , 0 , 3 , 0 , 0 , 0 , 0 , 12, 0 , 23, 0 , 22, 0 , 0 , 23, 12, 23, 3 ,
	0 , 0 , 0 , 0 , 3 , 0 , 23, 0 , 0 , 0 , 0 , 91, 0 , 16, 0 , 0 , 0 , 0 , 0 , 3 ,
	0 , 0 , 0 , 0 , 3 , 13, 0 , 0 , 22, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 24, 3 ,
	0 , 0 , 0 , 0 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 7 , 0 , 7 ,
	0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 1 ,
	0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 ,100, 1 ,
	0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 8 , 1 
};

const char map6[20][20] = {
	1 , 1 , 1 , 9 , 3 , 3 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
	8 , 99, 0 , 0 , 0 , 13, 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
	1 , 1 , 1 , 9 , 0 , 3 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
	0 , 0 , 0 , 3 , 0 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
	0 , 0 , 0 , 3 , 0 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
	0 , 0 , 3 , 3 , 0 , 3 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
	0 , 0 , 3 , 16, 0 , 16, 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
	0 , 0 , 3 , 16, 0 , 16, 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
	0 , 0 , 3 , 16, 0 , 16, 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
	0 , 0 , 3 , 16, 0 , 16, 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
	0 , 0 , 3 , 16, 0 , 16, 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
	0 , 0 , 3 , 16, 0 , 16, 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
	0 , 0 , 3 , 16, 0 , 16, 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
	0 , 0 , 3 , 16, 24, 16, 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
	0 , 0 , 3 , 16, 92, 16, 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
	0 , 0 , 3 , 16, 0 , 16, 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
	0 , 0 , 3 , 16, 0 , 16, 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
	0 , 0 , 3 , 16,100, 16, 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
	0 , 0 , 3 , 13, 14, 13, 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
	0 , 0 , 3 , 3 , 3 , 3 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
};

char cur_map[20][20];

struct TIskry
{
	float x, y, anim;
};

vector<TIskry> iskry;

struct TBlood
{
	float x, y, z, angle;
};

vector<TBlood> blood;

enum ENEMY_TYPE {SOLDIER, DEMON};
enum STATE {WALK, ATACK, DEAD, SHOOT};

struct TEnemy
{
	ENEMY_TYPE type;
	STATE state;

	float x, y, anim, angle;
	int health, shotwait;
};

vector<TEnemy> enemy;

TMatrixStack transform(MatrixIdentity());

string IntToStr(int val)
{
	char res[16];
	sprintf(res, "%d", val);
	return string(res);
}

void LoadMap(int map)
{
	iskry.clear();
	enemy.clear();
	blood.clear();

	px = 15, py = 15, pa = 0.f;
	shot_anim = 0.f;
	pistol_ammo += 60;

	mw = -1;
	mh = -1;

	if(map == 1)
	{
		pa = 90.f;
		mw = 20;
		mh = 20;
		map_fc = 0;

		for(int i = 0; i < mw; i++)
			for(int j = 0; j < mh; j++)
				cur_map[i][j] = map1[i][j];
		pSndLevel[0]->Play();
	}
	else
	if(map == 2)
	{
		mw = 20;
		mh = 20;
		pa = 180.f;
		map_fc = 0;
		for(int i = 0; i < mw; i++)
			for(int j = 0; j < mh; j++)
				cur_map[i][j] = map2[i][j];
		pSndLevel[1]->Play();
	}
	else
	if(map == 3)
	{
		mw = 20;
		mh = 20;
		map_fc = 1;
		for(int i = 0; i < mw; i++)
			for(int j = 0; j < mh; j++)
				cur_map[i][j] = map3[i][j];
		pSndLevel[2]->Play();
	}
	else
	if(map == 4)
	{
		mw = 20;
		mh = 20;
		map_fc = 1;
		for(int i = 0; i < mw; i++)
			for(int j = 0; j < mh; j++)
				cur_map[i][j] = map4[i][j];
		pSndLevel[2]->Play();
	}
	else
	if(map == 5)
	{
		mw = 20;
		mh = 20;
		map_fc = 0;
		for(int i = 0; i < mw; i++)
			for(int j = 0; j < mh; j++)
				cur_map[i][j] = map5[i][j];
		pSndLevel[1]->Play();
	}
	else
	if(map == 6)
	{
		mw = 20;
		mh = 20;
		map_fc = 0;
		for(int i = 0; i < mw; i++)
			for(int j = 0; j < mh; j++)
				cur_map[i][j] = map6[i][j];
		pSndLevel[0]->Play();
	}

	if(mh == -1 || mw == -1)//we have out of maps :)
	{
			game = false;
			pSndEnding->Play();
			pBG->Free();
			IResourceManager *p_res_man;
			pEngineCore->GetSubSystem(ESS_RESOURCE_MANAGER, (IEngineSubSystem *&)p_res_man);
			p_res_man->Load(RESOURCE_PATH("bg_ending.bmp"),(IEngBaseObj *&)pBG, TLF_FILTERING_NONE);
			return;
	}

	for(int i = 0; i < mw; i++)
	for(int j = 0; j < mh; j++)
	{
		if(cur_map[i][j] == 23)
		{
			TEnemy t;
			t.type = SOLDIER;
			t.x = i*10;
			t.y = j*10;
			t.anim = 0.f;
			t.angle = rand()%360;
			t.health = 100;
			t.shotwait = 20;
			t.state = WALK;
			enemy.push_back(t);
			cur_map[i][j] = 0;
		}
		else
			if(cur_map[i][j] == 24)
			{
				TEnemy t;
				t.type = DEMON;
				t.x = i*10;
				t.y = j*10;
				t.anim = 0.f;
				t.angle = rand()%360;
				if(cur_level == 6)
					t.health = 300;
				else
					t.health = 200;
				t.shotwait = 20;
				t.state = ATACK;
				enemy.push_back(t);
				cur_map[i][j] = 0;
			}
			else
				if(cur_map[i][j] == 99)
				{
					px = i*10;
					py = j*10;
					cur_map[i][j] = 0;
				}
	}
}

bool TraceBullet(float x, float y, float a, bool only_trace = false)
{
	float bx = x + sin(TORAD(a))*3.f, by = y + cos(TORAD(a))*3.f;//Not to collide with shooter

	while(sqrt((bx-x)*(bx-x)+(by-y)*(by-y)) < mw*mh)
	{
		bx += sin(TORAD(a))*0.1;
		by += cos(TORAD(a))*0.1;

		for(int i = 0; i < mw; i++)
			for(int j = 0; j < mh; j++)
				if((cur_map[i][j] != 0 && cur_map[i][j] < 90/*Scripts starts from 90*/ && cur_map[i][j] != 21/*shotgun*/ && cur_map[i][j] != 22/*medikit*/&& cur_map[i][j] != 17/*silling babe*/ && cur_map[i][j] != 100/*next level zone*/) && ( cur_map[i][j] > 10 ? TRectF(i*10 - 2, j*10 - 2, 4, 4).PointInRect(TPoint2(bx, by)) : TRectF(i*10 - 5, j*10 - 5, 10, 10).PointInRect(TPoint2(bx, by))))
				{
					if(!only_trace)
					{
						TIskry t;
						t.x = bx - sin(TORAD(a))*0.5;
						t.y = by - cos(TORAD(a))*0.5;
						t.anim = 0.f;
						iskry.push_back(t);
					}
					return false;
				}

		if(!only_trace)
		for(int i = 0; i < enemy.size(); i++)
			if(enemy[i].state != DEAD && TRectF(enemy[i].x - 2, enemy[i].y - 2, 4, 4).PointInRect(TPoint2(bx, by)))
			{
				TBlood t;
				t.x = bx - sin(TORAD(a))*0.5;
				t.y = by - cos(TORAD(a))*0.5;
				t.z = -6.5;
				t.angle = rand()%360;
				blood.push_back(t);

				enemy[i].health -= 20;

				if(enemy[i].health > 0)
				{
					if(enemy[i].type == SOLDIER)
						pSoldierPain->Play();
					else
						if(enemy[i].type == DEMON)
							pDemonPain->Play();
				}
				else
				{
					if(rand()%5 == 2)
						pSndKill[rand()%8]->Play();
					else
					{
						if(enemy[i].type == DEMON)
							pDemonDie->Play();
						else
							if(enemy[i].type == SOLDIER)
								pSoldierDie[rand()%2]->Play();
					}
				}

				if(rand()%2 == 1 && enemy[i].state != SHOOT) enemy[i].state = ATACK;

				return false;
			}

		if(health > 0 && TRectF(px - 2, py - 2, 4, 4).PointInRect(TPoint2(bx, by)))
		{
			if(!only_trace)
			{
				TBlood t;
				t.x = bx - sin(TORAD(a))*0.5;
				t.y = by - cos(TORAD(a))*0.5;
				t.z = -6.5;
				t.angle = rand()%360;
				blood.push_back(t);

				red_screen = 150;

				health -= 10;

				if(health > 0)
					pPain->Play();
				else
					pDie->Play();
			}

			return true;
		}
	}

	return false;
}

bool TestMapCollisionBox(float x, float y, bool player = false)
{
	for(int i = 0; i < mw; i++)
		for(int j = 0; j < mh; j++)
			if(cur_map[i][j] != 0 &&( cur_map[i][j] > 10 ? TRectF(i*10 - 2, j*10 - 2, 4, 4).IntersectRect(TRectF(x - 2.5, y - 2.5, 5, 5)) : TRectF(i*10 - 5, j*10 - 5, 10, 10).IntersectRect(TRectF(x - 2.5, y - 2.5, 5, 5))))
			{
				if(cur_map[i][j] == 100 && player)
				{
					cur_level++;
					LoadMap(cur_level);
				}

				if(cur_map[i][j] == 17) return false;

				if(cur_map[i][j] == 21)
				{
					if(player)
					{
						pShotgunPickup->Play();
						cur_map[i][j] = 0;
						shotgun_ammo += 20;
					}
					return false;
				}

				if(cur_map[i][j] >= 90 && cur_map[i][j] < 94 && player)
				{
					pSndScript[cur_map[i][j] - 90]->Play();
					cur_map[i][j] = 0;
				}

				if(cur_map[i][j] == 22)
				{
					if(player && health < 100)
					{
						cur_map[i][j] = 0;
						health += 50;
						if(health > 100) health = 100;
						pMedkit->Play();
					}
					return false;
				}

				return true;
			}

	return false;
}

void DrawMap()
{
	transform.Push();

	transform.Mult2(MatrixScale(TPoint3(10.f, 10.f, 10.f)));

	for(int i = 0; i < mw; i++)
		for(int j = 0; j < mh; j++)
		{
			transform.Push();

			transform.Mult2(MatrixTranslate(TPoint3(-i, -j, 0.f)));
			
			if(cur_map[i][j] <= 10 && cur_map[i][j] != 0)
			{
				transform.Mult2(MatrixTranslate(TPoint3(0.f, 0.f, -0.5)));
				if(cur_map[i][j] == 4 || cur_map[i][j] == 5 || cur_map[i][j] == 6 || cur_map[i][j] == 7)
				{
					transform.Mult2(MatrixTranslate(TPoint3(0.f, 0.f, -0.5)));
					transform.Mult2(MatrixScale(TPoint3(1.f, 1.f, 2.f)));
				}
				pWall[cur_map[i][j] - 1]->Bind();
				pRender3D->SetMatrix(transform.Top(), false);
				pBox->Draw();

				if(!(cur_map[i][j] == 4 || cur_map[i][j] == 5 || cur_map[i][j] == 6 || cur_map[i][j] == 7))
				{
					transform.Mult2(MatrixTranslate(TPoint3(0.f, 0.f, -1.f)));
					pRender3D->SetMatrix(transform.Top(), false);
					if(cur_map[i][j] == 8) pWall[0]->Bind();
					pBox->Draw();
				}
			}
			else
			{
				if(cur_map[i][j] <= 22 && cur_map[i][j] != 0)
				{
					pRender3D->ToggleAlphaTest(true);
					transform.Push();
					transform.Mult2(MatrixTranslate(TPoint3(0.f, 0.f, -0.5)));
					TMatrix mat_scale = MatrixIdentity(), mat_translate = MatrixIdentity(); uint frame = 0;
					switch(cur_map[i][j] - 11)
					{
						case 0: mat_translate = MatrixTranslate(TPoint3(0, 0, -0.25)); mat_scale = MatrixScale(TPoint3(7.5f, 15.f, 1.f)); break;
						case 1: mat_translate = MatrixTranslate(TPoint3(0, 0, -0.75)); mat_scale = MatrixScale(TPoint3(7.5f, 15.f, 1.f)); frame = 1+(counter/5)%4; break;
						case 2: mat_translate = MatrixTranslate(TPoint3(0, 0, -0.5)); mat_scale = MatrixScale(TPoint3(10.f, 20.f, 1.f)); frame = 1+(counter/5)%3; break;
						case 3: mat_translate = MatrixTranslate(TPoint3(0, 0, -0.5)); mat_scale = MatrixScale(TPoint3(5.f, 10.f, 1.f)); frame = 1+(counter/10)%10; break;
						case 4: mat_translate = MatrixTranslate(TPoint3(0, 0, 0)); mat_scale = MatrixScale(TPoint3(5.f, 10.f, 1.f)); frame = 1+(counter/10)%2; break;
						case 5: mat_translate = MatrixTranslate(TPoint3(0, 0, 0)); mat_scale = MatrixScale(TPoint3(5.f, 10.f, 1.f)); frame = 1+(counter/5)%6; break;
						case 6: mat_translate = MatrixTranslate(TPoint3(0, 0, -0.75)); mat_scale = MatrixScale(TPoint3(7.5f, 15.f, 1.f)); break;
						case 7: mat_translate = MatrixTranslate(TPoint3(0, 0, 0.f)); mat_scale = MatrixScale(TPoint3(5.f, 10.f, 1.f)); break;
						case 8: mat_translate = MatrixTranslate(TPoint3(0, 0, 0.15)); mat_scale = MatrixScale(TPoint3(7.5, 7.5, 1.f)); break;
						case 9: mat_translate = MatrixTranslate(TPoint3(0, 0, 0)); mat_scale = MatrixScale(TPoint3(7.5, 15.f, 1.f)); frame = 1+(counter/20)%3; break;
						case 10: mat_translate = MatrixTranslate(TPoint3(0.f, 0.f, 0.2)); mat_scale = MatrixScale(TPoint3(10.f, 5.f, 1.f)); break;
						case 11: mat_translate = MatrixTranslate(TPoint3(0.f, 0.f, 0.38)); mat_scale = MatrixScale(TPoint3(5.f, 2.5f, 1.f)); break;
						
						default:
							 mat_scale = MatrixScale(TPoint3(10.f, 10.f, 10.f));
					}

					transform.Mult2(mat_translate);

					pRender3D->SetMatrix(mat_scale*MatrixBillboard(transform.Top()), false);

					pSprite[cur_map[i][j] - 11]->Draw3D(frame);
					transform.Pop();
					pRender3D->ToggleAlphaTest(false);
				}

				if(cur_map[i][j] == 12 || cur_map[i][j] == 14)
				{
					transform.Push();
					pRender3D->SetMatrix(transform.Top(), false);
					transform.Mult2(MatrixTranslate(TPoint3(0.f, 0.f, -0.5)));
					pFloor[map_fc]->Bind();
					pBox->Draw();
					transform.Pop();
				}

				pRender3D->SetMatrix(transform.Top(), false);
				pFloor[map_fc]->Draw3D();
				transform.Mult2(MatrixTranslate(TPoint3(0.f, 0.f, -2.f)));
				pRender3D->SetMatrix(transform.Top(), false);
				pCilling[map_fc]->Draw3D();
			}

			transform.Pop();
		}

		transform.Pop();
}

void CALLBACK Init(void *pParametr)
{
	pEngineCore->GetSubSystem(ESS_RENDER, (IEngineSubSystem *&)pRender);
	pRender->GetRender2D(pRender2D);
	pRender->GetRender3D(pRender3D);
	pRender3D->SetPerspective(90.f, 0.05, 1000.f);
	pRender2D->SetResolutionCorrection(640, 480, false);

	pEngineCore->GetSubSystem(ESS_INPUT, (IEngineSubSystem *&)pInput);
	pInput->Configure((E_INPUT_CONFIGURATION_FLAGS)(ICF_HIDE_CURSOR | ICF_CURSOR_BEYOND_SCREEN | ICF_EXCLUSIVE));

	IResourceManager *p_res_man;
	pEngineCore->GetSubSystem(ESS_RESOURCE_MANAGER, (IEngineSubSystem *&)p_res_man);

	IMusic *p_music;
	p_res_man->Load((work_dir+"\\music.mp3").c_str(),(IEngBaseObj *&)p_music);
	p_music->Play();
	p_music->SetVolume(60);

	p_res_man->Load(RESOURCE_PATH("pistol_shot.wav"),(IEngBaseObj *&)pSndPistol);
	p_res_man->Load(RESOURCE_PATH("shotgun_shot.wav"),(IEngBaseObj *&)pSndShotgun);
	p_res_man->Load(RESOURCE_PATH("pain.wav"),(IEngBaseObj *&)pPain);
	p_res_man->Load(RESOURCE_PATH("pdeath.wav"),(IEngBaseObj *&)pDie);
	p_res_man->Load(RESOURCE_PATH("shotgun_pickup.wav"),(IEngBaseObj *&)pShotgunPickup);
	p_res_man->Load(RESOURCE_PATH("medkit.wav"),(IEngBaseObj *&)pMedkit);

	p_res_man->Load(RESOURCE_PATH("soldier_pain.wav"),(IEngBaseObj *&)pSoldierPain);
	p_res_man->Load(RESOURCE_PATH("soldier_shoot.wav"),(IEngBaseObj *&)pSoldierShoot);
	p_res_man->Load(RESOURCE_PATH("ending.wav"),(IEngBaseObj *&)pSndEnding);
	
	for(int i =0; i < 2; i++)
		p_res_man->Load(RESOURCE_PATH("soldier_death" + IntToStr(i)+ ".wav"),(IEngBaseObj *&)pSoldierDie[i]);

	for(int i =0; i < 3; i++)
		p_res_man->Load(RESOURCE_PATH("level_" + IntToStr(i)+ ".wav"),(IEngBaseObj *&)pSndLevel[i]);

	for(int i =0; i < 4; i++)
		p_res_man->Load(RESOURCE_PATH("script_" + IntToStr(i)+ ".wav"),(IEngBaseObj *&)pSndScript[i]);

	for(int i =0; i < 8; i++)
		p_res_man->Load(RESOURCE_PATH("kill_" + IntToStr(i)+ ".wav"),(IEngBaseObj *&)pSndKill[i]);

	p_res_man->Load(RESOURCE_PATH("demon_pain.wav"),(IEngBaseObj *&)pDemonPain);
	p_res_man->Load(RESOURCE_PATH("demon_die.wav"),(IEngBaseObj *&)pDemonDie);
	p_res_man->Load(RESOURCE_PATH("demon_shoot.wav"),(IEngBaseObj *&)pDemonShoot);

	const E_TEXTURE_LOAD_FLAGS load_flags = TLF_FILTERING_NONE;

	p_res_man->GetDefaultResource(EOT_MESH, (IEngBaseObj *&)pBox);
	p_res_man->Load(RESOURCE_PATH("font.dft"),(IEngBaseObj *&)pFont);
	p_res_man->Load(RESOURCE_PATH("bg.bmp"),(IEngBaseObj *&)pBG, load_flags);
	p_res_man->Load(RESOURCE_PATH("hud.bmp"),(IEngBaseObj *&)pHUD, load_flags);
	p_res_man->Load(RESOURCE_PATH("pistol.png"),(IEngBaseObj *&)pPistol, load_flags);
	pPistol->SetFrameSize(90, 128);
	p_res_man->Load(RESOURCE_PATH("shotgun.png"),(IEngBaseObj *&)pShotgun, load_flags);
	pShotgun->SetFrameSize(161, 196);
	p_res_man->Load(RESOURCE_PATH("iskry.png"),(IEngBaseObj *&)pIskry, load_flags);
	pIskry->SetFrameSize(14, 16);
	p_res_man->Load(RESOURCE_PATH("soldier.png"),(IEngBaseObj *&)pSoldier, load_flags);
	pSoldier->SetFrameSize(59, 64);
	p_res_man->Load(RESOURCE_PATH("demon.png"),(IEngBaseObj *&)pDemon, load_flags);
	pDemon->SetFrameSize(64, 64);

	p_res_man->Load(RESOURCE_PATH("blood.png"),(IEngBaseObj *&)pBlood, load_flags);
	
	p_res_man->Load(RESOURCE_PATH("shotgun_sprite.png"),(IEngBaseObj *&)pSprite[10], load_flags);
	p_res_man->Load(RESOURCE_PATH("medkit.png"),(IEngBaseObj *&)pSprite[11], load_flags);

	for(int i = 0; i < 2; i++)
	{
		p_res_man->Load(RESOURCE_PATH("floor"+IntToStr(i)+".bmp"),(IEngBaseObj *&)pFloor[i], (uint)(load_flags | TLF_GENERATE_MIPMAPS));
		p_res_man->Load(RESOURCE_PATH("cilling"+IntToStr(i)+".bmp"),(IEngBaseObj *&)pCilling[i], (uint)(load_flags | TLF_GENERATE_MIPMAPS));
	}

	for(int i = 0; i < 10; i++)
	{
		p_res_man->Load(RESOURCE_PATH("wall"+IntToStr(i)+".bmp"),(IEngBaseObj *&)pWall[i], (uint)(load_flags | TLF_GENERATE_MIPMAPS));
		p_res_man->Load(RESOURCE_PATH("sprite"+IntToStr(i)+".png"),(IEngBaseObj *&)pSprite[i], load_flags);
	}

	pSprite[1]->SetFrameSize(44, 128);
	pSprite[2]->SetFrameSize(56, 192);
	pSprite[3]->SetFrameSize(48, 94);
	pSprite[4]->SetFrameSize(35, 92);
	pSprite[5]->SetFrameSize(73, 110);
	pSprite[9]->SetFrameSize(74, 113);
}

void CALLBACK Process(void *pParametr)
{
	bool key;

	pInput->GetKey(KEY_ESCAPE, key);
	if(key) pEngineCore->QuitEngine();

	if(game)
	{
		static int prev_tick = GetTickCount();

		if(red_screen > 0)
			red_screen--;

		if(pistol_ammo < 10 && GetTickCount() - prev_tick > 2000)
		{
			prev_tick = GetTickCount();
			pistol_ammo ++;
		}

		int k = 0;
		while(k < iskry.size())
		{
			iskry[k].anim += 0.25;
			if((int)iskry[k].anim == 3)
				iskry.erase(iskry.begin() + k);
			else
				k++;
		}

		k = 0;
		while(k < blood.size())
		{
			if(blood[k].z <= 1.5)
				blood[k].z += 0.5;
			k++;
		}

		//Enemy AI
		k = 0;
		while(k < enemy.size())
		{
			if(enemy[k].state != DEAD && enemy[k].health <= 0)
			{
				enemy[k].state = DEAD;

				if(enemy[k].type == SOLDIER)
				{
					if(enemy[k].health <= -40)
						enemy[k].anim = 42;
					else
						enemy[k].anim = 37;
				}
				else
					if(enemy[k].type == DEMON)
						enemy[k].anim = 7;
			}
			else
				if(enemy[k].state == SHOOT)
				{
					enemy[k].anim += 0.20;

					if(((enemy[k].type == SOLDIER && (int)enemy[k].anim == 35) || (enemy[k].type == DEMON && (int)enemy[k].anim == 5))&& enemy[k].shotwait >= 20)
					{
						if(enemy[k].type == DEMON)
							pDemonShoot->Play();
						else
							if(enemy[k].type == SOLDIER)
								pSoldierShoot->Play();

						enemy[k].shotwait = 0;
						if(enemy[k].type == DEMON)
							TraceBullet(enemy[k].x, enemy[k].y, enemy[k].angle - 2.f + rand()%4);
						else
							TraceBullet(enemy[k].x, enemy[k].y, enemy[k].angle - 10.f + rand()%20);
					}

					enemy[k].shotwait++;

					if((enemy[k].type == SOLDIER && (int)enemy[k].anim == 36) || (enemy[k].type == DEMON && (int)enemy[k].anim == 7))
					{
						enemy[k].anim = 1;
						enemy[k].state = ATACK;
						continue;
					}
				}
				else
					if(enemy[k].state == WALK || enemy[k].state == ATACK)
					{
						if(enemy[k].state == ATACK || enemy[k].state == SHOOT)
						{
							enemy[k].angle = -TODEG(atan2(py - enemy[k].y, px - enemy[k].x)) + (health > 0 ? 90.f : -90.f);

							if(sqrt((px-enemy[k].x)*(px-enemy[k].x)+(py-enemy[k].y)*(py-enemy[k].y)) < (enemy[k].type == SOLDIER ? 75.f :(cur_level == 6 ? 250.f : 100.f)) && TraceBullet(enemy[k].x, enemy[k].y, enemy[k].angle, true))
							{
								enemy[k].state = SHOOT;
								if(enemy[k].type == SOLDIER)
									enemy[k].anim = 34;
								else
									if(enemy[k].type == DEMON)
										enemy[k].anim = 4;
								continue;
							}
						}

						if(enemy[k].state == WALK && rand()%100 == 50 && sqrt((px-enemy[k].x)*(px-enemy[k].x)+(py-enemy[k].y)*(py-enemy[k].y)) < (cur_level == 6 ? 250.f : 100.f)) enemy[k].state = ATACK;
						
						float	dx = sin(TORAD(enemy[k].angle))*0.2,
								dy = cos(TORAD(enemy[k].angle))*0.2;

						if(!TestMapCollisionBox(enemy[k].x+dx, enemy[k].y))
							enemy[k].x += dx;
						else
						{
							enemy[k].state = WALK;
							enemy[k].angle = rand()%360;
						}

						if(!TestMapCollisionBox(enemy[k].x, enemy[k].y + dy))
							enemy[k].y += dy;
						else
						{
							enemy[k].state = WALK;
							enemy[k].angle = rand()%360;
						}

							enemy[k].anim += 0.15;
							if((int)enemy[k].anim == 4) enemy[k].anim = 0.f;
					}
					else
						if(enemy[k].state == DEAD)
						{
							enemy[k].anim += 0.15;

							if(enemy[k].type == SOLDIER)
							{
								if((int)enemy[k].anim == 41) enemy[k].anim = 41;
								if((int)enemy[k].anim == 50) enemy[k].anim = 50;
							}
							else
								if(enemy[k].type == DEMON)
									if((int)enemy[k].anim == 15) enemy[k].anim = 15;
						}

			k++;
		}
		// end of AI :)

		
		if(health > 0)//Player Controls
		{
			pInput->GetKey(KEY_W, key);
			if(key)
			{
				float dx = sin(TORAD(pa))*0.3,
				dy = cos(TORAD(pa))*0.3;

				if(!TestMapCollisionBox(px+dx, py, true))
					px += dx;
			
				if(!TestMapCollisionBox(px, py + dy, true))
					py += dy;
			}

			pInput->GetKey(KEY_S, key);
			if(key)
			{
				float dx = sin(TORAD(pa+180))*0.3,
				dy = cos(TORAD(pa+180))*0.3;

				if(!TestMapCollisionBox(px+dx, py, true))
					px += dx;
			
				if(!TestMapCollisionBox(px, py + dy, true))
					py += dy;
			}

			pInput->GetKey(KEY_A, key);
			if(key)
			{
				float dx = sin(TORAD(pa+90))*0.3,
				dy = cos(TORAD(pa+90))*0.3;

				if(!TestMapCollisionBox(px+dx, py, true))
					px += dx;
			
				if(!TestMapCollisionBox(px, py + dy, true))
					py += dy;
			}

			pInput->GetKey(KEY_D, key);
			if(key)
			{
				float dx = sin(TORAD(pa-90))*0.3,
				dy = cos(TORAD(pa-90))*0.3;

				if(!TestMapCollisionBox(px+dx, py, true))
					px += dx;
			
				if(!TestMapCollisionBox(px, py + dy, true))
					py += dy;
			}

			TMouseStates ms;
			pInput->GetMouseStates(ms);

			pa -= ms.iDeltaX/4.f;

			if(pa < 0) pa = 360 + pa;
			if(pa > 360) pa = pa - 360;

			if((int)shot_anim != 0)
			{
				if(shotgun_ammo == 0)
				{
					shot_anim += 0.25;
					if((int)shot_anim == 3)
						shot_anim = -2.f;
				}
				else
				{
					shot_anim += 0.15;
					if((int)shot_anim == 7)
						shot_anim = -2.f;

				}
			}

			if(ms.bLeftButton && (int)shot_anim == 0)
			{
				if(shotgun_ammo == 0)
				{
					if(pistol_ammo > 0)
					{
						shot_anim = 1.f;
						pistol_ammo--;
						TraceBullet(px, py, pa);
						pSndPistol->Play();
					}
				}
				else
				{
					if(shotgun_ammo > 0)
					{
						shot_anim = 1.f;
						shotgun_ammo--;
						for(int i = 0; i < 8; i++)
							TraceBullet(px, py, pa - 7.5 + rand()%15);
						pSndShotgun->Play();
					}
				}
			}
		}
		else
		{
			pInput->GetKey(KEY_SPACE, key);
			if(key)
			{
				health = 100, pistol_ammo = 10, shotgun_ammo = 0;
				red_screen = 0;
				LoadMap(cur_level);
			}
		}

	}
	else
	{
		pInput->GetKey(KEY_SPACE, key);
		if(key)
		{
			game = true;
			health = 100, pistol_ammo = 10, shotgun_ammo = 0;
			red_screen = 0;
			cur_level = 1;
			LoadMap(cur_level);
		}
	}

	counter++;
}

void CALLBACK Render(void *pParametr)
{
	if(game)
	{

		transform.Set(MatrixIdentity());

		transform.Mult2(MatrixRotate(90.f, TPoint3(1.f, 0.f, 0.f)));
		transform.Mult2(MatrixRotate(pa, TPoint3(0.f, 0.f, 1.f)));
		transform.Mult2(MatrixTranslate(TPoint3(px, py, health > 0 ? 7.f : 0.3)));
	
		DrawMap();

		pRender3D->ToggleAlphaTest(true);

		for(int i = 0; i < iskry.size(); i++)
		{
			transform.Push();
			transform.Mult2(MatrixTranslate(TPoint3(-iskry[i].x, -iskry[i].y, -6.5)));
			pRender3D->SetMatrix(MatrixScale(TPoint3(2.5, 2.5, 1.f))*MatrixBillboard(transform.Top()), false);
			pIskry->Draw3D(1 + (int)iskry[i].anim);
			transform.Pop();
		}

		for(int i = 0; i < blood.size(); i++)
		{
			transform.Push();
			if(blood[i].z > 1.5)
			{
				transform.Mult2(MatrixTranslate(TPoint3(-blood[i].x, -blood[i].y, -0.1)));
				transform.Mult2(MatrixScale(TPoint3(2.5, 2.5, 2.5)));
				pRender3D->SetMatrix(transform.Top(), false);
			}
			else
			{
				transform.Mult2(MatrixTranslate(TPoint3(-blood[i].x, -blood[i].y, blood[i].z)));
				pRender3D->SetMatrix(MatrixScale(TPoint3(2.5, 2.5, 1.f))*MatrixBillboard(transform.Top()), false);
			}
			
			pBlood->Draw3D(0);
			transform.Pop();
		}

		for(int i = 0; i < enemy.size(); i++)
		{
			transform.Push();
			
			if(enemy[i].type == SOLDIER)
			{
				transform.Mult2(MatrixTranslate(TPoint3(-enemy[i].x, -enemy[i].y, -5)));
				pRender3D->SetMatrix(MatrixScale(TPoint3(10.f, 10.f, 1.f))*MatrixBillboard(transform.Top()), false);
				
				if(enemy[i].state == WALK || enemy[i].state == ATACK)
				{
					float angle = enemy[i].angle - pa;
					
					if(angle > 360) angle -= 360;
					if(angle < 0) angle += 360;

					int state = 0;

					if(angle >= 360 - 22.5 || angle <= 0 + 22.5) state = 4;
					if(angle >= 45 - 22.5 && angle <= 45 + 22.5) state = 3;
					if(angle >= 90 - 22.5 && angle <= 90 + 22.5) state = 2;
					if(angle >= 135 - 22.5 && angle <= 135 + 22.5) state = 1;
					if(angle >= 180 - 22.5 && angle <= 180 + 22.5) state = 0;
					if(angle >= 225 - 22.5 && angle <= 225 + 22.5) state = 7;
					if(angle >= 270 - 22.5 && angle <= 270 + 22.5) state = 6;
					if(angle >= 315 - 22.5 && angle <= 315 + 22.5) state = 5;

					pSoldier->Draw3D(1 + (int)enemy[i].anim * 8 + state);
				}
				else
					if(enemy[i].state == DEAD || enemy[i].state == SHOOT)
						pSoldier->Draw3D((int)enemy[i].anim);

			}
			else
				if(enemy[i].type == DEMON)
				{
					if(cur_level == 6)//Draw boss
					{
						pRender3D->SetColor(TColor4(0, 255, 0, 255));
						transform.Mult2(MatrixTranslate(TPoint3(-enemy[i].x, -enemy[i].y, -7.5)));
						pRender3D->SetMatrix(MatrixScale(TPoint3(10.f, 15.f, 1.f))*MatrixBillboard(transform.Top()), false);
						pDemon->Draw3D(1 + (int)enemy[i].anim);
						pRender3D->SetColor(TColor4(255, 255, 255, 255));
					}
					else
					{
						transform.Mult2(MatrixTranslate(TPoint3(-enemy[i].x, -enemy[i].y, -5)));
						pRender3D->SetMatrix(MatrixScale(TPoint3(10.f, 10.f, 1.f))*MatrixBillboard(transform.Top()), false);
						pDemon->Draw3D(1 + (int)enemy[i].anim);
					}
				}

			transform.Pop();
		}

		pRender3D->ToggleAlphaTest(false);

		pRender2D->Begin2D();
		
		if(red_screen > 0)
			pRender2D->DrawRect(TRectF(0, 0, 640, 480), TColor4(255, 0, 0, red_screen), PF_FILL);

		pHUD->Draw2DSimple(0, 480 - 32);	
		pFont->Draw2D(60, 480 - 34, IntToStr(health).c_str(), TColor4(255, 0, 0, 255));
		
		if(health > 0)
		{
			if(shotgun_ammo == 0)
			{
				pPistol->Draw2D(350 + cos(px/2)*10.f, 261 + sin(py/2)*10.f, 90*2, 128*2, 0.f, (int)shot_anim < 0 ? 0 : shot_anim); 
				pFont->Draw2D(10 , 480 - 34, IntToStr(pistol_ammo).c_str(), TColor4(255, 0, 0, 255));
			}
			else
			{
				pShotgun->Draw2D(320 + cos(px/2)*10.f, 101 + sin(py/2)*10.f, 161*2, 196*2, 0.f, (int)shot_anim < 0 ? 0 : shot_anim); 
				pFont->Draw2D(10, 480 - 34, IntToStr(shotgun_ammo).c_str(), TColor4(255, 0, 0, 255));
			}
		}
		else
			pFont->Draw2D(200, 300, "Press \"Space\" to restart level!", TColor4(0, 0, 0, 255));

		pRender2D->End2D();
	}
	else
	{
		pRender2D->Begin2D();
		pBG->Draw2D(0, 0, 640, 480);
		if(cur_level == 0) pSprite[2]->Draw2D(640-56*2,50,56*2,192*2,0.f,(counter/5)%3);
		pRender2D->End2D();
	}
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
	if(GetEngine(DLL_PATH,pEngineCore))
	{
		char txt[255];
		GetModuleFileName(NULL, txt, 255);
		work_dir = string(txt);
		int idx = 0;
	
		for(int i = 0; i < work_dir.length(); i ++)
			if(work_dir[i] == '\\') idx = i;

		work_dir.erase(idx, work_dir.length() - idx);

		if(SUCCEEDED(pEngineCore->InitializeEngine(NULL, APP_CAPTION, TEngWindow(1024, 768, MessageBox(NULL,"Run in fullscreen?", "Screen",MB_YESNO|MB_ICONQUESTION)==IDYES))))
		{
			pEngineCore->AddProcedure(EPT_INIT,	&Init);
			pEngineCore->AddProcedure(EPT_PROCESS, &Process);
			pEngineCore->AddProcedure(EPT_RENDER, &Render);
			pEngineCore->StartEngine();
		}
		FreeEngine();
	}
	else MessageBox(NULL,"Couldn't load \""DLL_PATH"\"!", APP_CAPTION, MB_OK | MB_ICONERROR | MB_SETFOREGROUND);
	return 0;
}