// ---------------------------------------------------------------
// BubbleMod
// 
// AUTHOR
//        Tyler Lund <halflife@bubblemod.org>
//
// LICENSE                                                            
//                                                                    
//        Permission is granted to anyone to use this  software  for  
//        any purpose on any computer system, and to redistribute it  
//        in any way, subject to the following restrictions:          
//                                                                    
//        1. The author is not responsible for the  consequences  of  
//           use of this software, no matter how awful, even if they  
//           arise from defects in it.                                
//        2. The origin of this software must not be misrepresented,  
//           either by explicit claim or by omission.                 
//        3. Altered  versions  must  be plainly marked as such, and  
//           must  not  be  misrepresented  (by  explicit  claim  or  
//           omission) as being the original software.                
//        3a. It would be nice if I got  a  copy  of  your  improved  
//            version  sent to halflife@bubblemod.org. 
//        4. This notice must not be removed or altered.              
//                                                                    
// ---------------------------------------------------------------

#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "weapons.h"
#include "player.h"
#include "skill.h"
#include "items.h"
#include "gamerules.h"
#include "BMOD_rune.h"
#include "BMOD_messaging.h"
#include "BMOD_player.h"

#define RUNE_MODEL "models/w_oxygen.mdl"

extern DLL_GLOBAL BOOL		g_runes_learn;
extern cvar_t	bm_runemask;

void CRune::Spawn( void )
{
	Precache();
	// SET_MODEL(ENT(pev), RUNE_MODEL);
	pev->movetype = MOVETYPE_BOUNCE;
	pev->solid = SOLID_TRIGGER;
	pev->classname = MAKE_STRING("rune");

	pev->renderfx |= kRenderFxGlowShell;
	pev->rendercolor = m_vRuneColor;
	pev->renderamt = 50; 

	m_randomize = FALSE;
	
	UTIL_SetOrigin( pev, pev->origin );
	UTIL_SetSize(pev, Vector(-16, -16, 0), Vector(16, 16, 16));
	SetTouch(RuneTouch);

	pev->effects |= EF_NODRAW;
	SetThink ( Materialize );
	pev->nextthink = gpGlobals->time + RANDOM_FLOAT(.5, 2); 	

	if (DROP_TO_FLOOR(ENT(pev)) == 0)
	{
		ALERT(at_error, "Item %s fell out of level at %f,%f,%f", STRING( pev->classname ), pev->origin.x, pev->origin.y, pev->origin.z);
		UTIL_Remove( this );
		return;
	}
}

void CRune::RuneTouch( CBaseEntity *pOther )
{

	// if it's not a player, just bounce
	if ( !pOther->IsPlayer() )
	{

		if (!pev->velocity)
			return;

		TraceResult tr;
		UTIL_TraceLine( pev->origin, pev->origin - Vector(0,0,10), ignore_monsters, edict(), &tr );

		if ( tr.flFraction < 1.0 )
		{
			// add a bit of static friction
			pev->velocity = pev->velocity * 0.5;
		}
		return;
	}


	CBasePlayer *pPlayer = (CBasePlayer *)pOther;

	if (!pPlayer->BMOD_IsASpawn() && MyTouch( pPlayer ))
	{
		pPlayer->pev->rendermode = kRenderNormal;
		pPlayer->pev->renderfx = kRenderFxGlowShell;
		pPlayer->pev->rendercolor = m_vRuneColor;  
        pPlayer->pev->renderamt = 10;  // glow shell distance from entity

		SetTouch( NULL );
		Respawn(); 
	}
}

CBaseEntity* CRune::Respawn( void )
{
	pev->effects |= EF_NODRAW;

	if (m_randomize)
		SetThink ( MaterializeRandom );
	else
		SetThink ( Materialize );

	return this;
}

void CRune::MaterializeRandom ( void )
{
	// Make sure at least one rune type is allowed
	if (!((int)bm_runemask.value & 63)) 
	{
		UTIL_Remove( this );
		return;
	}

	CBaseEntity *NewRune = NULL;
	int rand = 1;

	for (int i = 0;  i < RANDOM_LONG(3,10); i++) 
	{
		do {
			rand *= 2;
			if (rand > 63)
				rand = 1;
		} while (!(rand & (int)bm_runemask.value)); 
	}

	if      (rand == RUNE_CROWBAR) 
		NewRune = CBaseEntity::Create("item_CrowbarRune", pev->origin, Vector (0,0,0), NULL );
	else if (rand == RUNE_GRENADE) 
		NewRune = CBaseEntity::Create("item_GrenadeRune", pev->origin, Vector (0,0,0), NULL );
	else if (rand == RUNE_357) 
		NewRune = CBaseEntity::Create("item_357Rune", pev->origin, Vector (0,0,0), NULL );
	else if (rand == RUNE_HEALTH) 
		NewRune = CBaseEntity::Create("item_HealthRune", pev->origin, Vector (0,0,0), NULL );
	else if (rand == RUNE_BATTERY) 
		NewRune = CBaseEntity::Create("item_BatteryRune", pev->origin, Vector (0,0,0), NULL );
	else if (rand == RUNE_SHOTGUN) 
		NewRune = CBaseEntity::Create("item_ShotgunRune", pev->origin, Vector (0,0,0), NULL );

	((CRune *)NewRune)->m_randomize = TRUE;
	UTIL_Remove( this );
}

void CRune::Materialize( void )
{
	// Pool of random spawn points.
	static Vector spawnPoints[200];

	// Populate the random spawn point pool.
	if (!g_runes_learn) {
		g_runes_learn = TRUE;
		CBaseEntity *pSpot = NULL;
		for ( int i = 0; i < 200; i++ ) {
			do 
				pSpot = UTIL_FindEntityInSphere( pSpot, Vector(0,0,0), 4096 );
			while (pSpot==NULL || 
				!(
					!strcmp(STRING(pSpot->pev->classname), "info_player_deathmatch") |
					!strncmp(STRING(pSpot->pev->classname), "weapon_", 7) |
					!strncmp(STRING(pSpot->pev->classname), "ammo_", 5)
				));
			spawnPoints[i] = pSpot->pev->origin;
		}

	}

	if ( pev->effects & EF_NODRAW )
	{
		pev->angles.x = 0;
		pev->angles.z = 0;
		pev->origin = spawnPoints[RANDOM_LONG(0, 199)];

		pev->velocity.x = RANDOM_FLOAT( .5, 2 );
		if (RANDOM_LONG(0,1))
			pev->velocity.x = pev->velocity.x * -1;

		pev->velocity.y = RANDOM_FLOAT( .5, 2 );
		if (RANDOM_LONG(0,1))
			pev->velocity.y = pev->velocity.y * -1;

		pev->velocity.z = RANDOM_FLOAT( .5, 2 );
		pev->avelocity.y = RANDOM_FLOAT( 0, 100 );
		pev->velocity = pev->velocity.Normalize() * 300;

		// changing from invisible state to visible.
		EMIT_SOUND_DYN( ENT(pev), CHAN_WEAPON, "items/suitchargeok1.wav", 1, ATTN_NORM, 0, 150 );
		pev->effects &= ~EF_NODRAW;
		pev->effects |= EF_MUZZLEFLASH;

		SetTouch( RuneTouch );
	}
	// EMIT_SOUND_DYN( ENT(pev), CHAN_WEAPON, "buttons/blip2.wav", 1, ATTN_NORM, 0, 150 );
	pev->nextthink = gpGlobals->time + 2;
}

void CRune::Precache( void )
{
	PRECACHE_MODEL (RUNE_MODEL);
	PRECACHE_SOUND ("buttons/blip2.wav");
}

LINK_ENTITY_TO_CLASS( item_rune, CRune );

////////////////////////////////////////////////
//  Crowbar rune
////////////////////////////////////////////////
#define CROWBARRUNE_MODEL "models/w_crowbar.mdl"
class CCrowbarRune : public CRune
{
	void Spawn ( void )
	{
		m_vRuneColor = Vector(255,20,20);
		SET_MODEL(ENT(pev), CROWBARRUNE_MODEL);
		CRune::Spawn();

	}
	void Precache( void )
	{
		PRECACHE_MODEL (CROWBARRUNE_MODEL);
	}
	BOOL MyTouch (CBasePlayer *pPlayer ) 
	{ 
		// One rune at a time folks.
		if (!pPlayer->m_RuneFlags)
		{
			float time = max(1, CVAR_GET_FLOAT("bm_rune_cbar_t"));
			float respawn = max(1, CVAR_GET_FLOAT("bm_rune_cbar_r"));

			//RuneMsg( pPlayer, MSG_RUNE_CROWBAR, m_vRuneColor, time - .5);
			PrintMessage( pPlayer, BMOD_CHAN_RUNE, m_vRuneColor, Vector (.1, time - .5, .1), "SUPER CROWBAR\nIncreased crowbar damage / infinite throws.");

			EMIT_SOUND( pPlayer->edict(), CHAN_ITEM, "items/gunpickup2.wav", 1, ATTN_NORM ); 
			pPlayer->m_RuneFlags = RUNE_CROWBAR;
			pPlayer->m_RuneTime = gpGlobals->time + time;
			pev->nextthink = gpGlobals->time + respawn;
			return TRUE; 
		}
		else
			return FALSE;
	}
};
LINK_ENTITY_TO_CLASS( item_CrowbarRune, CCrowbarRune );

////////////////////////////////////////////////
//  Grenade rune
////////////////////////////////////////////////
#define GRENADERUNE_MODEL "models/w_grenade.mdl"
class CGrenadeRune : public CRune
{
	void Spawn ( void )
	{
		m_vRuneColor = Vector(255,128,0);
		SET_MODEL(ENT(pev), GRENADERUNE_MODEL);
		CRune::Spawn();
	}
	void Precache( void )
	{
		PRECACHE_MODEL (GRENADERUNE_MODEL);
	}
	BOOL MyTouch (CBasePlayer *pPlayer ) 
	{ 
		// One rune at a time folks.
		if (!pPlayer->m_RuneFlags)
		{
			float time = max(1, CVAR_GET_FLOAT("bm_rune_gren_t"));
			float respawn = max(1, CVAR_GET_FLOAT("bm_rune_gren_r"));

			PrintMessage( pPlayer, BMOD_CHAN_RUNE, m_vRuneColor, Vector (.1, time - .5, .1), "MEGA GRENADE\nIncreased hand grenade damage.");
			EMIT_SOUND( pPlayer->edict(), CHAN_ITEM, "items/gunpickup2.wav", 1, ATTN_NORM ); 
			pPlayer->m_RuneFlags = RUNE_GRENADE;
			pPlayer->m_RuneTime = gpGlobals->time + time;
			pev->nextthink = gpGlobals->time + respawn;
			return TRUE; 
		}
		else
			return FALSE;
	}
};
LINK_ENTITY_TO_CLASS( item_GrenadeRune, CGrenadeRune );


////////////////////////////////////////////////
//  Health rune
////////////////////////////////////////////////
#define HEALTHRUNE_MODEL "models/w_medkit.mdl"
class CHealthRune : public CRune
{
	void Spawn ( void )
	{
		m_vRuneColor = Vector(20,255,20);
		SET_MODEL(ENT(pev), HEALTHRUNE_MODEL);
		CRune::Spawn();
	}
	void Precache( void )
	{
		PRECACHE_MODEL (HEALTHRUNE_MODEL);
	}
	BOOL MyTouch (CBasePlayer *pPlayer ) 
	{ 
		// One rune at a time folks.
		if (!pPlayer->m_RuneFlags)
		{
			float time = max(1, CVAR_GET_FLOAT("bm_rune_health_t"));
			float respawn = max(1, CVAR_GET_FLOAT("bm_rune_health_r"));
			PrintMessage( pPlayer, BMOD_CHAN_RUNE, m_vRuneColor, Vector (.1, time - .5, .1), "DOUBLE HEALTH PICKUPS\nMed packs / machines give 2X health. Fast Heal on Bubble Gun.");

			EMIT_SOUND( pPlayer->edict(), CHAN_ITEM, "items/gunpickup2.wav", 1, ATTN_NORM ); 
			pPlayer->m_RuneFlags = RUNE_HEALTH;
			pPlayer->m_RuneTime = gpGlobals->time + time;
			pev->nextthink = gpGlobals->time + respawn;
			return TRUE; 
		}
		else
			return FALSE;
	}
};
LINK_ENTITY_TO_CLASS( item_HealthRune, CHealthRune );

////////////////////////////////////////////////
//  Battery rune
////////////////////////////////////////////////
#define BATTERYRUNE_MODEL "models/w_battery.mdl"
class CBatteryRune : public CRune
{
	void Spawn ( void )
	{
		m_vRuneColor = Vector(0,255,255);
		SET_MODEL(ENT(pev), BATTERYRUNE_MODEL);
		CRune::Spawn();
	}
	void Precache( void )
	{
		PRECACHE_MODEL (BATTERYRUNE_MODEL);
	}
	BOOL MyTouch (CBasePlayer *pPlayer ) 
	{ 
		// One rune at a time folks.
		if (!pPlayer->m_RuneFlags)
		{
			float time = max(1, CVAR_GET_FLOAT("bm_rune_armor_t"));
			float respawn = max(1, CVAR_GET_FLOAT("bm_rune_armor_r"));

			PrintMessage( pPlayer, BMOD_CHAN_RUNE, m_vRuneColor, Vector (.1, time - .5, .1), "DOUBLE ARMOR PICKUPS\nArmor batteries / machines give 2X armor. Bubble Gun gives armor.");
			EMIT_SOUND( pPlayer->edict(), CHAN_ITEM, "items/gunpickup2.wav", 1, ATTN_NORM ); 
			pPlayer->m_RuneFlags = RUNE_BATTERY;
			pPlayer->m_RuneTime = gpGlobals->time + time;
			pev->nextthink = gpGlobals->time + respawn;
			return TRUE; 
		}
		else
			return FALSE;
	}
};
LINK_ENTITY_TO_CLASS( item_BatteryRune, CBatteryRune );

////////////////////////////////////////////////
//  357 rune
////////////////////////////////////////////////
#define _357RUNE_MODEL "models/w_357.mdl"
class C357Rune : public CRune
{
	void Spawn ( void )
	{
		m_vRuneColor = Vector(250,20,250);
		SET_MODEL(ENT(pev), _357RUNE_MODEL);
		CRune::Spawn();
	}
	void Precache( void )
	{
		PRECACHE_MODEL (_357RUNE_MODEL);
	}
	BOOL MyTouch (CBasePlayer *pPlayer ) 
	{ 
		// One rune at a time folks.
		if (!pPlayer->m_RuneFlags)
		{
			float time = max(1, CVAR_GET_FLOAT("bm_rune_357_t"));
			float respawn = max(1, CVAR_GET_FLOAT("bm_rune_357_r"));

			PrintMessage( pPlayer, BMOD_CHAN_RUNE, m_vRuneColor, Vector (.1, time - .5, .1), "SUPER MAGNUM\nIncreased magnum damage.");
			EMIT_SOUND( pPlayer->edict(), CHAN_ITEM, "items/gunpickup2.wav", 1, ATTN_NORM ); 
			pPlayer->m_RuneFlags = RUNE_357;
			pPlayer->m_RuneTime = gpGlobals->time + time;
			pev->nextthink = gpGlobals->time + respawn;
			return TRUE; 
		}
		else
			return FALSE;
	}
};
LINK_ENTITY_TO_CLASS( item_357Rune, C357Rune );

////////////////////////////////////////////////
//  Shotgun rune
////////////////////////////////////////////////
#define SHOTGUNRUNE_MODEL "models/w_shotgun.mdl"
class CShotgunRune : public CRune
{
	void Spawn ( void )
	{
		m_vRuneColor = Vector(20,20,255);
		SET_MODEL(ENT(pev), SHOTGUNRUNE_MODEL);
		CRune::Spawn();
	}
	void Precache( void )
	{
		PRECACHE_MODEL (SHOTGUNRUNE_MODEL);
	}
	BOOL MyTouch (CBasePlayer *pPlayer ) 
	{ 
		// One rune at a time folks.
		if (!pPlayer->m_RuneFlags)
		{
			float time = max(1, CVAR_GET_FLOAT("bm_rune_shotty_t"));
			float respawn = max(1, CVAR_GET_FLOAT("bm_rune_shotty_r"));

			PrintMessage( pPlayer, BMOD_CHAN_RUNE, m_vRuneColor, Vector (.1, time - .5, .1), "SUPER SHOTGUN\nIncreased shotgun speed / fast reload.");
			EMIT_SOUND( pPlayer->edict(), CHAN_ITEM, "items/gunpickup2.wav", 1, ATTN_NORM ); 
			pPlayer->m_RuneFlags = RUNE_SHOTGUN;
			pPlayer->m_RuneTime = gpGlobals->time + time;
			pev->nextthink = gpGlobals->time + respawn;
			return TRUE; 
		}
		else
			return FALSE;
	}
};
LINK_ENTITY_TO_CLASS( item_ShotgunRune, CShotgunRune );
