#include <amxmodx>
#include <amxmisc>
#include <engine>

/* Configuration */

//-----------------------------------
//Only activate one of these two.

#define XMAS
//#define EASTER

//-----------------------------------
//Define-error handling

#assert !( (defined XMAS) && (defined EASTER) ) "It isn't possible that Xmas and Easter are on the same day!"
#assert !( (!defined XMAS) && (!defined EASTER) ) "You must enable Xmas or Easter."

//-----------------------------------
//Comment this if you are not using cstrike (there won't be rewards for picking up a present)

#define USING_CTRIKE

#if defined USING_CTRIKE
	#include <cstrike>
#endif

//-----------------------------------
//Maximums

#define MAX_SPAWNLOCATIONS 64
#define TOTAL_COLORS 10
#define EASTER_MAX_MODELS 5
#define XMAS_MAX_MODELS 2
//-----------------------------------

/* End configuration */

#pragma semicolon 1

new gcvar_removePresents;
new gcvar_presentAmount;

new g_orginFilePath[256];

new Float:g_spawnOrigins[MAX_SPAWNLOCATIONS][3];
new g_totalOrigins;

new Float:colors[TOTAL_COLORS][3] = {
	{95.0, 200.0, 255.0},
	{0.0, 150.0, 255.0},
	{180.0, 255.0, 175.0},
	{0.0, 155.0, 0.0},
	{255.0, 255.0, 255.0},
	{255.0, 190.0, 90.0},
	{222.0, 110.0, 0.0},
	{192.0, 192.0, 192.0},
	{190.0, 100.0, 10.0},
	{0.0, 0.0, 0.0}
};

//----------------------------------------------------------------------------
//							Init
//----------------------------------------------------------------------------
public plugin_init()
{
	register_plugin("presentsSpawner", "0.5", "MaximusBrood");
	register_dictionary("presentsspawner.txt");	
	
	//Commands
	register_clcmd("amx_addpresentspawnpoint", "cmd_addSpawn", ADMIN_RCON, "- add a spawnpoint at your current location");
	register_clcmd("amx_spawnpresent", "cmd_spawnPresent", ADMIN_RCON, "- Spawns an egg with money in it");
	register_clcmd("amx_removepresents", "cmd_removePresents", ADMIN_RCON, "- Remove all presents from the map");
	register_clcmd("say", "cmd_say");
	
	//Cvars
	gcvar_removePresents = register_cvar("sv_removepresents", "1");
	gcvar_presentAmount = register_cvar("sv_presentamount", "3");
	register_cvar("presentsSpawner_version", "1.0", FCVAR_SERVER);
	
	//Events
	register_logevent("event_roundStart", 2, "1=Round_Start");
	register_touch("maximusbroodPresent", "player", "event_presentTouch");
		
	//Get the path to the origin file
	new filepath[256];
	get_datadir(filepath, 255);
	
	new mapname[32];
	get_mapname(mapname, 31);
	
	format(g_orginFilePath, 255, "%s/presents/%s.ini", filepath, mapname);
	
	//Load the locations
	loadData();
}

public plugin_precache()
{
#if defined EASTER
	for(new a = 1; a <= EASTER_MAX_MODELS; ++a)
		formatPrecache_model("models/easteregg%d.mdl", a);
#endif

#if defined XMAS
	for(new a = 1; a <= XMAS_MAX_MODELS; ++a)
		formatPrecache_model("models/xmaspresent%d.mdl", a);
#endif

	return PLUGIN_CONTINUE;
}


//----------------------------------------------------------------------------
//								File reading
//----------------------------------------------------------------------------

loadData()
{
	g_totalOrigins = 0;
	
	//Note that we won't throw any errormessages when no presents are found
	new buffer[128];
	new strX[12], strY[12], strZ[12];
	if( file_exists(g_orginFilePath) )  
	{
		new readPointer = fopen(g_orginFilePath, "rt");
		
		if(!readPointer)
			return;
			
		while( !feof(readPointer) )
		{
			fgets(readPointer, buffer, 127);
			
			if(buffer[0] == ';' || !buffer[0])
				continue;
				
			parse(buffer, strX, 11, strY, 11, strZ, 11);
			
			g_spawnOrigins[g_totalOrigins][0] = float(str_to_num(strX));
			g_spawnOrigins[g_totalOrigins][1] = float(str_to_num(strY));
			g_spawnOrigins[g_totalOrigins][2] = float(str_to_num(strZ));
			
			++g_totalOrigins;
		}
		
		fclose(readPointer);
	}
}

//----------------------------------------------------------------------------
//								Commands
//----------------------------------------------------------------------------

public cmd_addSpawn(id, level, cid)
{
	if (!cmd_access(id, level, cid, 1))
		return PLUGIN_HANDLED;
		
	//Check for too many spawns
	if(g_totalOrigins >= MAX_SPAWNLOCATIONS)
	{
		printChatAndConsole(id, "[presentsSpawner] %L", id, "MAXSPAWNS_REACHED", MAX_SPAWNLOCATIONS);
		return PLUGIN_CONTINUE;
	}
	
	//Get the current origin
	new Float:currentOrigin[3];
	entity_get_vector(id, EV_VEC_origin, currentOrigin);
	
	//Open the file for writing, write the origin and close up
	new writePointer = fopen(g_orginFilePath, "at");
	
	if(writePointer)
	{
		server_print("Writing, coords are {%f, %f, %f} or {%d, %d, %d}", currentOrigin[0], currentOrigin[1], currentOrigin[2], floatround(currentOrigin[0]), floatround(currentOrigin[1]), floatround(currentOrigin[2]));
		
		fprintf(writePointer, "%d %d %d^n", floatround(currentOrigin[0]), floatround(currentOrigin[1]), floatround(currentOrigin[2]) );
	
		fclose(writePointer);
		
		//Notify the user
		printChatAndConsole(id, "[presentsSpawner] %L", id, "ADD_SUCCESS");
	
		//Reload spawnpoints
		loadData();
	} else
		printChatAndConsole(id, "Failed to add!");
	
	return PLUGIN_CONTINUE;
}

public cmd_spawnPresent(id, level, cid)
{
	if (!cmd_access(id, level, cid, 1))
		return PLUGIN_HANDLED;
		
	//Get the player's origin
	new Float:playerOrigin[3];
	entity_get_vector(id, EV_VEC_origin, playerOrigin);
	
	//Pack the origin
	new packedOrigin[3];
	FVecIVec(playerOrigin, packedOrigin);
	
	set_task(2.5, "spawnPresent", _, packedOrigin, 3);
	
	//Don't display a message to the user, gets irritating	
	return PLUGIN_HANDLED;
}

public cmd_removePresents(id, level, cid)
{
	if (!cmd_access(id, level, cid, 1))
		return PLUGIN_CONTINUE;
		
	removePresents();
	
	printChatAndConsole(id, "[presentsSpawner] %L", id, "REMOVED_ALL");
	
	return PLUGIN_CONTINUE;
}

//----------------------------------------------------------------------------
//								Events
//----------------------------------------------------------------------------

public event_roundStart()
{
	//Check if there are spawnlocations to drop to
	if(g_totalOrigins < 0)
		return PLUGIN_CONTINUE;
		
	//Remove all eggs if requested
	if(get_pcvar_num(gcvar_removePresents) == 1)
		removePresents();
		
	//Get the amount of eggs to drop
	new eggAmount = get_pcvar_num(gcvar_presentAmount);
	
	//Plant the presents ^_-
	new currentOrigin[3];
	for(new a = 0; a < g_totalOrigins; ++a)
	{
		//Pack the origin
		FVecIVec(g_spawnOrigins[a], currentOrigin);
		
		for(new b = 0; b < eggAmount; ++b)
		{
			spawnPresent(currentOrigin);
		}
	}
	
	return PLUGIN_CONTINUE;
}

public event_presentTouch(pTouched, pToucher)
{
	//Error checking
	if(!is_valid_ent(pToucher) || !is_valid_ent(pTouched) || !is_user_connected(pToucher))
		return PLUGIN_HANDLED;
		
#if defined USING_CTRIKE
	
	//Money handling for CS
	new randomMoney = random_num(50, 500);
	
	cs_set_user_money(pToucher, (cs_get_user_money(pToucher) + randomMoney), 1);
	
	#if defined EASTER
		client_print(pToucher, print_chat, "[presentsSpawner] %L", pToucher, "EASTEREGG_TOUCH_CSTRIKE", randomMoney);
	#endif
	
	#if defined XMAS
		client_print(pToucher, print_chat, "[presentsSpawner] %L", pToucher, "XMASPRESENT_TOUCH_CSTRIKE", randomMoney);
	#endif
	
#else

	#if defined EASTER
		client_print(pToucher, print_chat, "[presentsSpawner] %L", pToucher, "EASTEREGG_TOUCH");
	#endif
	
	#if defined XMAS
		client_print(pToucher, print_chat, "[presentsSpawner] %L", pToucher, "XMASPRESENT_TOUCH");
	#endif
	
#endif

	//Removed the egg
	remove_entity(pTouched);
	
	return PLUGIN_HANDLED;
}

//----------------------------------------------------------------------------
//								Main Functions
//----------------------------------------------------------------------------

public spawnPresent(packedOrigin[3])
{
	//Unpack the origin
	new Float:origin[3];
	IVecFVec(packedOrigin, origin);
	
	//Create entity and set origin and velocity
	new entity;
	entity = create_entity("info_target");
	
	entity_set_origin(entity, origin);
	
	new Float:velocity[3];
	velocity[0] = (random_float(0.0, 256.0) - 128.0);
	velocity[1] = (random_float(0.0, 256.0) - 128.0);
	velocity[2] = (random_float(0.0, 300.0) + 75.0);
		
	entity_set_vector(entity, EV_VEC_velocity, velocity );
	
	//Set a random model
	static modelName[64];
	
#if defined EASTER
	formatex(modelName, 63, "models/easteregg%d.mdl", random_num(1, EASTER_MAX_MODELS));
#endif

#if defined XMAS
	formatex(modelName, 63, "models/xmaspresent%d.mdl", random_num(1, XMAS_MAX_MODELS));
#endif

	entity_set_model(entity, modelName);
	
	//Color (75% chance)
	if(random_num(1, 4) > 2)
	{
		//Special effect (25% chance)
		if(random_num(1, 4) == 1)
			entity_set_int(entity, EV_INT_renderfx, kRenderFxHologram);
			
		entity_set_vector(entity, EV_VEC_rendercolor, colors[random(TOTAL_COLORS)] );
			
		entity_set_int(entity, EV_INT_renderfx, kRenderFxGlowShell);
		entity_set_float(entity, EV_FL_renderamt, 1000.0);
		entity_set_int(entity, EV_INT_rendermode, kRenderTransAlpha);
	}
	
	//The rest of the properties
	entity_set_string(entity, EV_SZ_classname, "maximusbroodPresent");
	entity_set_int(entity, EV_INT_effects, 32);
	entity_set_int(entity, EV_INT_solid, SOLID_TRIGGER);
	entity_set_int(entity, EV_INT_movetype, MOVETYPE_TOSS);
	
	return PLUGIN_CONTINUE;
}

removePresents()
{
	new currentEntity;

	while ( (currentEntity = find_ent_by_class(currentEntity, "maximusbroodPresent")) != 0)
	{
		remove_entity(currentEntity);
	}
}

//----------------------------------------------------------------------------
//								Helpers
//----------------------------------------------------------------------------

printChatAndConsole(id, text[], ...)
{
	static buffer[128];
	
	vformat(buffer, 127, text, 3);
	
	client_print(id, print_chat, "%s", buffer);
	client_print(id, print_console, "%s", buffer);
}

formatPrecache_model(name[], ...)
{
	static buffer[256];
	
	vformat(buffer, 255, name, 2);
	
	precache_model(buffer);
}
