Portable Half-Life SDK. GoldSource and Xash3D. Crossplatform.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

444 lines
13 KiB

// ---------------------------------------------------------------
// 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( &CRune::RuneTouch );
pev->effects |= EF_NODRAW;
SetThink( &CRune::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( &CRune::MaterializeRandom );
else
SetThink( &CRune::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( &CRune::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 );