Upload missing files.

This commit is contained in:
Night Owl 2017-01-09 03:11:40 +05:00
parent 2ad83a9ada
commit 7235d2435f
27 changed files with 5942 additions and 0 deletions

View File

@ -0,0 +1,82 @@
// ---------------------------------------------------------------
// Camera Point Entity
//
// 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 "monsters.h"
#include "weapons.h"
#include "nodes.h"
#include "player.h"
#include "gamerules.h"
#include "effects.h"
#include "BMOD_CameraPoint.h"
#include "shake.h"
LINK_ENTITY_TO_CLASS( campoint, CCamPoint );
void CCamPoint::Precache( void )
{
}
void CCamPoint::Spawn( void )
{
pev->movetype = MOVETYPE_NOCLIP;
pev->solid = SOLID_NOT; // Remove model & collisions
pev->renderamt = 0; // The engine won't draw this model if this
// is set to 0 and blending is on
pev->rendermode = kRenderTransTexture;
SetThink ( Think );
pev->nextthink = gpGlobals->time + 0.1;
}
void CCamPoint::Think( void )
{
// If we have no owner, our owner is not in type mode,
// our owner is not connected, our owner is invisible,
// or our owner is a defuct player, remove ourselves.
if (!m_pOwner
|| !m_pOwner->m_bIsConnected
|| !m_pOwner->m_bTypeMode
|| m_pOwner->pev->effects & EF_NODRAW
|| (STRING(m_pOwner->pev->netname)[0] == 0)
) {
// UTIL_ClientPrintAll( HUD_PRINTTALK, "<SERVER> Camera point destroyed.\n");
UTIL_Remove( this );
pev->nextthink = gpGlobals->time + .1;
return;
}
pev->origin = m_pOwner->pev->origin + Vector(0,0,40),
pev->angles = Vector(m_pOwner->pev->angles.x + 22,
m_pOwner->pev->angles.y + 180,
0),
// Wait until it's time to think again.
pev->nextthink = gpGlobals->time + 0.01;
}

View File

@ -0,0 +1,40 @@
// ---------------------------------------------------------------
// Zap Rift Entity
//
// 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.
//
// ---------------------------------------------------------------
#ifndef C_CAM_POINT
#define C_CAM_POINT
class CCamPoint : public CPointEntity
{
public:
void Spawn( void );
void Precache( void );
void EXPORT Think( void );
CBasePlayer *m_pOwner;
};
#endif

View File

@ -0,0 +1,123 @@
// ---------------------------------------------------------------
// 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 "monsters.h"
#include "weapons.h"
#include "nodes.h"
#include "player.h"
#include "effects.h"
#include "gamerules.h"
#include "BMOD_boxmarker.h"
LINK_ENTITY_TO_CLASS( boxmarker, CBoxMarker );
void CBoxMarker :: Spawn( void )
{
pev->classname = MAKE_STRING("boxmarker");
pev->movetype = MOVETYPE_FLY;
pev->solid = SOLID_NOT;
SetThink( PowerupThink );
pev->nextthink = gpGlobals->time + RANDOM_FLOAT(.1, 1);
m_vecExtents = Vector (16, 16, 16);
m_beamsFired = 0;
}
void CBoxMarker :: PowerupThink( void )
{
Vector vecStart, vecEnd;
pev->nextthink = gpGlobals->time + RANDOM_FLOAT(.1, .5);
switch (m_beamsFired)
{
case 0:
vecStart = pev->origin + Vector(m_vecExtents.x * 1 , m_vecExtents.y * 1, m_vecExtents.z * 1);
vecEnd = pev->origin + Vector(m_vecExtents.x * -1 , m_vecExtents.y * 1, m_vecExtents.z * 1);
break;
case 1:
vecStart = pev->origin + Vector(m_vecExtents.x * -1 , m_vecExtents.y * 1, m_vecExtents.z * 1);
vecEnd = pev->origin + Vector(m_vecExtents.x * -1 , m_vecExtents.y * -1, m_vecExtents.z * 1);
break;
case 2:
vecStart = pev->origin + Vector(m_vecExtents.x * -1 , m_vecExtents.y * -1, m_vecExtents.z * 1);
vecEnd = pev->origin + Vector(m_vecExtents.x * 1 , m_vecExtents.y * -1, m_vecExtents.z * 1);
break;
case 3:
vecStart = pev->origin + Vector(m_vecExtents.x * 1 , m_vecExtents.y * -1, m_vecExtents.z * 1);
vecEnd = pev->origin + Vector(m_vecExtents.x * 1 , m_vecExtents.y * 1, m_vecExtents.z * 1);
break;
case 4:
vecStart = pev->origin + Vector(m_vecExtents.x * 1 , m_vecExtents.y * 1, m_vecExtents.z * 1);
vecEnd = pev->origin + Vector(m_vecExtents.x * 1 , m_vecExtents.y * 1, m_vecExtents.z * -1);
break;
case 5:
vecStart = pev->origin + Vector(m_vecExtents.x * -1 , m_vecExtents.y * 1, m_vecExtents.z * 1);
vecEnd = pev->origin + Vector(m_vecExtents.x * -1 , m_vecExtents.y * 1, m_vecExtents.z * -1);
break;
case 6:
vecStart = pev->origin + Vector(m_vecExtents.x * -1 , m_vecExtents.y * -1, m_vecExtents.z * 1);
vecEnd = pev->origin + Vector(m_vecExtents.x * -1 , m_vecExtents.y * -1, m_vecExtents.z * -1);
break;
case 7:
vecStart = pev->origin + Vector(m_vecExtents.x * 1 , m_vecExtents.y * -1, m_vecExtents.z * 1);
vecEnd = pev->origin + Vector(m_vecExtents.x * 1 , m_vecExtents.y * -1, m_vecExtents.z * -1);
break;
case 8:
vecStart = pev->origin + Vector(m_vecExtents.x * 1 , m_vecExtents.y * 1, m_vecExtents.z * -1);
vecEnd = pev->origin + Vector(m_vecExtents.x * -1 , m_vecExtents.y * 1, m_vecExtents.z * -1);
break;
case 9:
vecStart = pev->origin + Vector(m_vecExtents.x * -1 , m_vecExtents.y * 1, m_vecExtents.z * -1);
vecEnd = pev->origin + Vector(m_vecExtents.x * -1 , m_vecExtents.y * -1, m_vecExtents.z * -1);
break;
case 10:
vecStart = pev->origin + Vector(m_vecExtents.x * -1 , m_vecExtents.y * -1, m_vecExtents.z * -1);
vecEnd = pev->origin + Vector(m_vecExtents.x * 1 , m_vecExtents.y * -1, m_vecExtents.z * -1);
break;
case 11:
vecStart = pev->origin + Vector(m_vecExtents.x * 1 , m_vecExtents.y * -1, m_vecExtents.z * -1);
vecEnd = pev->origin + Vector(m_vecExtents.x * 1 , m_vecExtents.y * 1, m_vecExtents.z * -1);
SetThink(NULL);
break;
}
m_pBeam[m_beamsFired] = CBeam::BeamCreate( g_pModelNameLaser, 10 );
m_pBeam[m_beamsFired]->PointsInit( vecStart, vecEnd );
m_pBeam[m_beamsFired]->SetColor( 0, 255, 0 );
m_pBeam[m_beamsFired]->SetScrollRate( 255 );
m_pBeam[m_beamsFired]->SetBrightness( 64 );
m_beamsFired++;
}

View File

@ -0,0 +1,47 @@
// ---------------------------------------------------------------
// 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.
//
// ---------------------------------------------------------------
#ifndef MY_BOX_MARKER
#define MY_BOX_MARKER
#include "effects.h"
class CBoxMarker : public CPointEntity
{
public:
void Spawn( void );
void EXPORT PowerupThink( void );
void Killed( void );
Vector m_vecExtents;
private:
int m_beamsFired;
CBeam *m_pBeam[12];
};
#endif

View File

@ -0,0 +1,61 @@
// ---------------------------------------------------------------
// 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.
//
// ---------------------------------------------------------------
// Global BubbleMod Constants
#ifndef BMOD_CONSTANTS_H
#define BMOD_CONSTANTS_H
// ---------------------------------------------------------------
// Branch customizations
// Information in the next three constants will be used for servers
// running your mod on the BubbleWatch pages on bubblemod.org. Fill
// these in with the information you would like to appear on that page.
//
// If you do NOT want servers running your branch to appear on the
// BubbleWatch page, simply set BMOD_VERSION below to "", or run your
// server with no master server reporting.
// Fill this in with the title of your bubblemod branch
#define BMOD_BRANCH_NAME "Custom Bubblemod"
// The version of your branch
#define BMOD_BRANCH_VERSION "1.0.0"
// The URL of the website describing your branch
#define BMOD_BRANCH_URL "http://www.bubblemod.org"
// End branch customizations
// ---------------------------------------------------------------
#define BMOD_VERSION "2.2.3a"
#ifdef _WIN32
#define BMOD_PLATFORM "WIN32"
#else
#define BMOD_PLATFORM "Linux"
#endif
#endif

View File

@ -0,0 +1,939 @@
/***
*
* Copyright (c) 1999, 2000 Valve LLC. All rights reserved.
*
* This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved.
*
* Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC.
*
****/
#if !defined( OEM_BUILD ) && !defined( HLDEMO_BUILD )
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "player.h"
#include "monsters.h"
#include "weapons.h"
#include "nodes.h"
#include "effects.h"
#include "customentity.h"
#include "gamerules.h"
#include "shake.h"
#include "BMOD_messaging.h"
#define EGON_PRIMARY_VOLUME 450
#define EGON_BEAM_SPRITE "sprites/xbeam1.spr"
#define EGON_FLARE_SPRITE "sprites/XSpark1.spr"
#define EGON_SOUND_OFF "weapons/egon_off1.wav"
#define EGON_SOUND_RUN "weapons/egon_run3.wav"
#define EGON_SOUND_STARTUP "weapons/egon_windup2.wav"
#define BUBB_SOUND_OFF "debris/flesh5.wav"
#define BUBB_SOUND_RUN "debris/flesh5.wav"
#define BUBB_SOUND_STARTUP "debris/flesh6.wav"
#define HEAL_SOUND_OFF "debris/beamstart7.wav"
#define EGON_SWITCH_NARROW_TIME 0.75 // Time it takes to switch fire modes
#define EGON_SWITCH_WIDE_TIME 1.5
#define BUBBLE_HEAL_RADIUS 64
#define BUBBLE_HEAL_AMT 70
extern cvar_t bm_gluon_mod;
extern cvar_t bm_thrust;
enum egon_e {
EGON_IDLE1 = 0,
EGON_FIDGET1,
EGON_ALTFIREON,
EGON_ALTFIRECYCLE,
EGON_ALTFIREOFF,
EGON_FIRE1,
EGON_FIRE2,
EGON_FIRE3,
EGON_FIRE4,
EGON_DRAW,
EGON_HOLSTER
};
class CEgon : public CBasePlayerWeapon
{
public:
int Save( CSave &save );
int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
void Spawn( void );
void Precache( void );
int iItemSlot( void ) { return 4; }
int GetItemInfo(ItemInfo *p);
int AddToPlayer( CBasePlayer *pPlayer );
BOOL Deploy( void );
void Holster( int skiplocal = 0 );
void CreateEffect( void );
void UpdateEffect( const Vector &startPoint, const Vector &endPoint, float timeBlend );
void DestroyEffect( void );
void EndBubbleAttack( void );
void EndAttack( void );
void BubbleAttack( void );
void Attack( void );
void PrimaryAttack( void );
void SecondaryAttack( void );
void WeaponIdle( void );
static int g_fireAnims1[];
static int g_fireAnims2[];
float m_flAmmoUseTime;// since we use < 1 point of ammo per update, we subtract ammo on a timer.
float GetPulseInterval( void );
float GetDischargeInterval( void );
void Fire( const Vector &vecOrigSrc, const Vector &vecDir );
void BubbleFire( const Vector &vecOrigSrc, const Vector &vecDir );
void FireHeal( void );
BOOL HasAmmo( void )
{
if (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0)
return FALSE;
return TRUE;
}
void UseAmmo( int count )
{
if ( m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] >= count )
m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] -= count;
else
m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] = 0;
}
enum EGON_FIRESTATE { FIRE_OFF, FIRE_CHARGE };
enum EGON_FIREMODE { FIRE_NARROW, FIRE_WIDE};
private:
float m_shootTime;
CBeam *m_pBeam;
CBeam *m_pNoise;
CSprite *m_pSprite;
EGON_FIRESTATE m_fireState;
EGON_FIREMODE m_fireMode;
float m_shakeTime;
BOOL m_deployed;
float m_bubbletime;
float m_healAmmoUsed;
float m_healAmmoUseTime;
unsigned short m_usEgonFire;
unsigned short m_usEgonStop;
};
LINK_ENTITY_TO_CLASS( weapon_egon, CEgon );
int CEgon::g_fireAnims1[] = { EGON_FIRE1, EGON_FIRE2, EGON_FIRE3, EGON_FIRE4 };
int CEgon::g_fireAnims2[] = { EGON_ALTFIRECYCLE };
TYPEDESCRIPTION CEgon::m_SaveData[] =
{
DEFINE_FIELD( CEgon, m_pBeam, FIELD_CLASSPTR ),
DEFINE_FIELD( CEgon, m_pNoise, FIELD_CLASSPTR ),
DEFINE_FIELD( CEgon, m_pSprite, FIELD_CLASSPTR ),
DEFINE_FIELD( CEgon, m_shootTime, FIELD_TIME ),
DEFINE_FIELD( CEgon, m_fireState, FIELD_INTEGER ),
DEFINE_FIELD( CEgon, m_fireMode, FIELD_INTEGER ),
DEFINE_FIELD( CEgon, m_shakeTime, FIELD_TIME ),
DEFINE_FIELD( CEgon, m_flAmmoUseTime, FIELD_TIME ),
};
IMPLEMENT_SAVERESTORE( CEgon, CBasePlayerWeapon );
void CEgon::Spawn( )
{
pev->classname = MAKE_STRING("weapon_egon");
Precache( );
m_iId = WEAPON_EGON;
SET_MODEL(ENT(pev), "models/w_egon.mdl");
m_iDefaultAmmo = EGON_DEFAULT_GIVE;
FallInit();// get ready to fall down.
}
void CEgon::Precache( void )
{
PRECACHE_MODEL("models/w_egon.mdl");
PRECACHE_MODEL("models/v_egon.mdl");
PRECACHE_MODEL("models/p_egon.mdl");
PRECACHE_MODEL("models/w_9mmclip.mdl");
PRECACHE_SOUND("items/9mmclip1.wav");
PRECACHE_SOUND( EGON_SOUND_OFF );
PRECACHE_SOUND( EGON_SOUND_RUN );
PRECACHE_SOUND( EGON_SOUND_STARTUP );
PRECACHE_SOUND( BUBB_SOUND_OFF );
PRECACHE_SOUND( BUBB_SOUND_RUN );
PRECACHE_SOUND( BUBB_SOUND_STARTUP );
PRECACHE_SOUND( HEAL_SOUND_OFF );
PRECACHE_MODEL( EGON_BEAM_SPRITE );
PRECACHE_MODEL( EGON_FLARE_SPRITE );
PRECACHE_SOUND ("weapons/357_cock1.wav");
m_usEgonFire = PRECACHE_EVENT ( 1, "events/egon_fire.sc" );
m_usEgonStop = PRECACHE_EVENT ( 1, "events/egon_stop.sc" );
}
BOOL CEgon::Deploy( void )
{
if (bm_gluon_mod.value) {
PrintMessage( m_pPlayer, BMOD_CHAN_WEAPON, Vector (20,250,20), Vector (1, 4, 2), "BUBBLE GUN\nPRIMARY FIRE: Breathe bubbles underwater.\nSECONDARY FIRE: Hold down 5 seconds for area effect healing.");
}
m_deployed = FALSE;
return DefaultDeploy( "models/v_egon.mdl", "models/p_egon.mdl", EGON_DRAW, "egon" );
}
int CEgon::AddToPlayer( CBasePlayer *pPlayer )
{
if ( CBasePlayerWeapon::AddToPlayer( pPlayer ) )
{
MESSAGE_BEGIN( MSG_ONE, gmsgWeapPickup, NULL, pPlayer->pev );
WRITE_BYTE( m_iId );
MESSAGE_END();
return TRUE;
}
return FALSE;
}
void CEgon::Holster( int skiplocal /* = 0 */ )
{
m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.5;
// m_flTimeWeaponIdle = gpGlobals->time + UTIL_RandomFloat ( 10, 15 );
SendWeaponAnim( EGON_HOLSTER );
if ( m_fireState != FIRE_OFF ) {
if (bm_gluon_mod.value)
EndBubbleAttack();
else
EndAttack();
}
}
int CEgon::GetItemInfo(ItemInfo *p)
{
p->pszName = STRING(pev->classname);
p->pszAmmo1 = "uranium";
p->iMaxAmmo1 = URANIUM_MAX_CARRY;
p->pszAmmo2 = NULL;
p->iMaxAmmo2 = -1;
p->iMaxClip = WEAPON_NOCLIP;
p->iSlot = 3;
p->iPosition = 2;
p->iId = m_iId = WEAPON_EGON;
p->iFlags = 0;
p->iWeight = EGON_WEIGHT;
return 1;
}
//#define EGON_PULSE_INTERVAL 0.25
//#define EGON_DISCHARGE_INTERVAL 0.5
#define EGON_PULSE_INTERVAL 0.1
#define EGON_DISCHARGE_INTERVAL 0.1
float CEgon::GetPulseInterval( void )
{
if ( g_pGameRules->IsMultiplayer() )
{
return 0.1;
}
return EGON_PULSE_INTERVAL;
}
float CEgon::GetDischargeInterval( void )
{
if ( g_pGameRules->IsMultiplayer() )
{
return 0.1;
}
return EGON_DISCHARGE_INTERVAL;
}
void CEgon::BubbleAttack( void )
{
UTIL_MakeVectors( m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle );
Vector vecAiming = gpGlobals->v_forward;
Vector vecSrc = m_pPlayer->GetGunPosition( );
switch( m_fireState )
{
case FIRE_OFF:
{
if ( !HasAmmo() )
{
m_flNextPrimaryAttack = gpGlobals->time + 0.25;
if (m_flNextSecondaryAttack <= gpGlobals->time)
m_flNextSecondaryAttack = gpGlobals->time + 0.25;
PlayEmptySound( );
return;
}
m_flAmmoUseTime = gpGlobals->time;// start using ammo ASAP.
SendWeaponAnim( g_fireAnims1[ RANDOM_LONG(0,ARRAYSIZE(g_fireAnims1)-1) ] );
m_shakeTime = 0;
m_pPlayer->m_iWeaponVolume = EGON_PRIMARY_VOLUME;
m_flTimeWeaponIdle = gpGlobals->time + 0.1;
// m_shootTime = gpGlobals->time + 2;
m_shootTime = gpGlobals->time + .2;
if ( m_fireMode == FIRE_WIDE )
{
EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_WEAPON, BUBB_SOUND_STARTUP, 0.98, ATTN_NORM, 0, 125 );
}
else
{
EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_WEAPON, BUBB_SOUND_STARTUP, 0.9, ATTN_NORM, 0, 80 );
m_healAmmoUsed = 0;
m_healAmmoUseTime = -1;
}
pev->dmgtime = gpGlobals->time + GetPulseInterval();
m_fireState = FIRE_CHARGE;
}
break;
case FIRE_CHARGE:
{
if ( m_fireMode == FIRE_WIDE )
BubbleFire( vecSrc, vecAiming );
else
FireHeal();
m_pPlayer->m_iWeaponVolume = EGON_PRIMARY_VOLUME;
if ( m_shootTime != 0 && gpGlobals->time > m_shootTime )
{
if ( m_fireMode == FIRE_WIDE )
{
EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_STATIC, BUBB_SOUND_RUN, 0.98, ATTN_NORM, 0, 100 + RANDOM_LONG(0, 100) );
}
else
{
EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_STATIC, BUBB_SOUND_RUN, 0.9, ATTN_NORM, 0, 50 + (m_healAmmoUsed * 2) );
}
m_shootTime += (.1 + RANDOM_FLOAT(0,.1));
}
if ( !HasAmmo() )
{
EndBubbleAttack();
m_fireState = FIRE_OFF;
m_flNextPrimaryAttack = gpGlobals->time + 1.0;
if (m_flNextSecondaryAttack <= gpGlobals->time)
m_flNextSecondaryAttack = gpGlobals->time + 1.0;
}
}
break;
}
}
void CEgon::PrimaryAttack( void )
{
if (bm_gluon_mod.value) {
m_fireMode = FIRE_WIDE;
BubbleAttack();
}
else {
m_fireMode = FIRE_WIDE;
Attack();
}
}
void CEgon::SecondaryAttack( void )
{
if (bm_gluon_mod.value) {
m_fireMode = FIRE_NARROW;
BubbleAttack();
}
else {
}
}
// ***********************************
// Eggplant's Bubble Gun
// ***********************************
void CEgon::BubbleFire( const Vector &vecOrigSrc, const Vector &vecDir )
{
if (!(m_bubbletime <= gpGlobals->time))
return;
m_bubbletime = gpGlobals->time + .05;
UTIL_MakeVectors( m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle );
m_pPlayer->pev->velocity = m_pPlayer->pev->velocity - gpGlobals->v_forward * bm_thrust.value;
TraceResult tr;
// Give player air!
m_pPlayer->pev->air_finished = gpGlobals->time + 12;
// First determine where the bubble will appear. It will appear in a random location
// from the barrel of the gun to +128 units from the barrel.
Vector tmpSrcMin = vecOrigSrc + gpGlobals->v_up * -8 + gpGlobals->v_right * 3;
Vector tmpSrcMax = tmpSrcMin + gpGlobals->v_forward * RANDOM_LONG(32, 128);
// We dont want to be able to shoot through walls or people, so trace the line from the barrel to the
// bubble point and make sure nothing is in the way.
UTIL_TraceLine(tmpSrcMin, tmpSrcMax, dont_ignore_monsters, ENT(pev), &tr);
if (tr.fStartSolid)
return;
Vector tmpSrc1 = tmpSrcMin + gpGlobals->v_forward * 32;
Vector tmpSrc2 = tr.vecEndPos;
// Now trace from the bubble point up 256 units to see where the bubble should pop.
Vector vecDest = tmpSrc2 + Vector ( 0, 0, 1 ) * 256;
UTIL_TraceLine(tmpSrc2, vecDest, ignore_monsters, ENT(pev), &tr);
float flHeight = tr.vecEndPos.z - tmpSrc2.z;
// Tell the client about the new bubble.
// MESSAGE_BEGIN( MSG_PAS, SVC_TEMPENTITY, tmpSrc );
// WRITE_BYTE( TE_BUBBLES );
// WRITE_COORD( vecMin.x ); // mins
// WRITE_COORD( vecMin.y );
// WRITE_COORD( vecMin.z );
// WRITE_COORD( vecMax.x ); // maxz
// WRITE_COORD( vecMax.y );
// WRITE_COORD( vecMax.z );
// WRITE_COORD( flHeight ); // height
// WRITE_SHORT( g_sModelIndexBubbles );
// WRITE_BYTE( 3 ); // count
// WRITE_COORD( 8 ); // speed
// MESSAGE_END();
MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY );
WRITE_BYTE( TE_BUBBLETRAIL );
WRITE_COORD( tmpSrc1.x ); // mins
WRITE_COORD( tmpSrc1.y );
WRITE_COORD( tmpSrc1.z );
WRITE_COORD( tmpSrc2.x ); // maxz
WRITE_COORD( tmpSrc2.y );
WRITE_COORD( tmpSrc2.z );
WRITE_COORD( flHeight ); // height
WRITE_SHORT( g_sModelIndexBubbles );
WRITE_BYTE( 5 ); // count
WRITE_COORD( 8 ); // speed
MESSAGE_END();
}
void CEgon::FireHeal( void ) {
// Only do this every once in a while to save bandwidth.
if (!(m_bubbletime <= gpGlobals->time))
return;
m_bubbletime = gpGlobals->time + .1;
Vector vecOrigSrc = m_pPlayer->GetGunPosition( );
int bubbleRadius = 1;
int numBubbles = 1;
int bubbleSpeed = 8;
if (m_healAmmoUseTime <= gpGlobals->time) {
m_healAmmoUseTime = gpGlobals->time +.5;
UseAmmo(5);
m_healAmmoUsed += 5;
// Runes halve the ammo needed.
int healTime = 50;
if (m_pPlayer->m_RuneFlags == RUNE_BATTERY ||
m_pPlayer->m_RuneFlags == RUNE_HEALTH) {
healTime /= 2;
}
if (m_healAmmoUsed >= healTime) {
// Heal all players within a radius.
CBaseEntity *pEntity = NULL;
// Find all the players inside the radius. Heal them, and make the screen flash.
while ((pEntity = UTIL_FindEntityInSphere( pEntity, vecOrigSrc, BUBBLE_HEAL_RADIUS )) != NULL)
{
if (pEntity->IsPlayer())
if (m_pPlayer->m_RuneFlags == RUNE_BATTERY) {
pEntity->pev->armorvalue += BUBBLE_HEAL_AMT;
if (pEntity->pev->armorvalue > 100)
pEntity->pev->armorvalue = 100;
}
else {
pEntity->TakeHealth(BUBBLE_HEAL_AMT, DMG_GENERIC);
}
UTIL_ScreenFade( pEntity, Vector(0,128,255), 2, 0.5, 200, FFADE_IN );
}
// Make a big bubble cloud.
bubbleRadius = BUBBLE_HEAL_RADIUS;
numBubbles = 1000;
bubbleSpeed = -8;
// Turn off the bubble gun.
EndBubbleAttack();
// Make sure they can't do this again for a while.
m_flNextSecondaryAttack = gpGlobals->time + 30;
// Make a sound effect.
EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_STATIC, HEAL_SOUND_OFF, 0.98, ATTN_NORM, 0, 100);
}
}
// Make bubble(s)
TraceResult tr;
Vector vecDest = vecOrigSrc + Vector ( 0, 0, 1 ) * 256;
UTIL_TraceLine(vecOrigSrc, vecDest, ignore_monsters, ENT(pev), &tr);
float flHeight = tr.vecEndPos.z - vecOrigSrc.z;
// Tell the client about the new bubble.
MESSAGE_BEGIN( MSG_PAS, SVC_TEMPENTITY, vecOrigSrc );
WRITE_BYTE( TE_BUBBLES );
WRITE_COORD( vecOrigSrc.x - bubbleRadius ); // mins
WRITE_COORD( vecOrigSrc.y - bubbleRadius );
WRITE_COORD( vecOrigSrc.z - bubbleRadius );
WRITE_COORD( vecOrigSrc.x + bubbleRadius ); // maxz
WRITE_COORD( vecOrigSrc.y + bubbleRadius );
WRITE_COORD( vecOrigSrc.z + bubbleRadius );
WRITE_COORD( flHeight ); // height
WRITE_SHORT( g_sModelIndexBubbles );
WRITE_BYTE( numBubbles ); // count
WRITE_COORD( bubbleSpeed ); // speed
MESSAGE_END();
}
void CEgon::UpdateEffect( const Vector &startPoint, const Vector &endPoint, float timeBlend )
{
if ( !m_pBeam )
{
CreateEffect();
}
m_pBeam->SetStartPos( endPoint );
m_pBeam->SetBrightness( 255 - (timeBlend*180) );
m_pBeam->SetWidth( 40 - (timeBlend*20) );
if ( m_fireMode == FIRE_WIDE )
m_pBeam->SetColor( 30 + (25*timeBlend), 30 + (30*timeBlend), 64 + 80*fabs(sin(gpGlobals->time*10)) );
else
m_pBeam->SetColor( 60 + (25*timeBlend), 120 + (30*timeBlend), 64 + 80*fabs(sin(gpGlobals->time*10)) );
UTIL_SetOrigin( m_pSprite->pev, endPoint );
m_pSprite->pev->frame += 8 * gpGlobals->frametime;
if ( m_pSprite->pev->frame > m_pSprite->Frames() )
m_pSprite->pev->frame = 0;
m_pNoise->SetStartPos( endPoint );
}
void CEgon::CreateEffect( void )
{
DestroyEffect();
m_pBeam = CBeam::BeamCreate( EGON_BEAM_SPRITE, 40 );
m_pBeam->PointEntInit( pev->origin, m_pPlayer->entindex() );
m_pBeam->SetFlags( BEAM_FSINE );
m_pBeam->SetEndAttachment( 1 );
m_pBeam->pev->spawnflags |= SF_BEAM_TEMPORARY; // Flag these to be destroyed on save/restore or level transition
m_pNoise = CBeam::BeamCreate( EGON_BEAM_SPRITE, 55 );
m_pNoise->PointEntInit( pev->origin, m_pPlayer->entindex() );
m_pNoise->SetScrollRate( 25 );
m_pNoise->SetBrightness( 100 );
m_pNoise->SetEndAttachment( 1 );
m_pNoise->pev->spawnflags |= SF_BEAM_TEMPORARY;
m_pSprite = CSprite::SpriteCreate( EGON_FLARE_SPRITE, pev->origin, FALSE );
m_pSprite->pev->scale = 1.0;
m_pSprite->SetTransparency( kRenderGlow, 255, 255, 255, 255, kRenderFxNoDissipation );
m_pSprite->pev->spawnflags |= SF_SPRITE_TEMPORARY;
if ( m_fireMode == FIRE_WIDE )
{
m_pBeam->SetScrollRate( 50 );
m_pBeam->SetNoise( 20 );
m_pNoise->SetColor( 50, 50, 255 );
m_pNoise->SetNoise( 8 );
}
else
{
m_pBeam->SetScrollRate( 110 );
m_pBeam->SetNoise( 5 );
m_pNoise->SetColor( 80, 120, 255 );
m_pNoise->SetNoise( 2 );
}
}
void CEgon::DestroyEffect( void )
{
if ( m_pBeam )
{
UTIL_Remove( m_pBeam );
m_pBeam = NULL;
}
if ( m_pNoise )
{
UTIL_Remove( m_pNoise );
m_pNoise = NULL;
}
if ( m_pSprite )
{
if ( m_fireMode == FIRE_WIDE )
m_pSprite->Expand( 10, 500 );
else
UTIL_Remove( m_pSprite );
m_pSprite = NULL;
}
}
void CEgon::WeaponIdle( void )
{
ResetEmptySound( );
if ( m_flTimeWeaponIdle > gpGlobals->time )
return;
if ( m_fireState != FIRE_OFF ) {
if (bm_gluon_mod.value)
EndBubbleAttack();
else
EndAttack();
}
int iAnim;
float flRand = RANDOM_FLOAT(0,1);
if ( flRand <= 0.5 )
{
iAnim = EGON_IDLE1;
m_flTimeWeaponIdle = gpGlobals->time + RANDOM_FLOAT(10,15);
}
else
{
iAnim = EGON_FIDGET1;
m_flTimeWeaponIdle = gpGlobals->time + 3;
}
SendWeaponAnim( iAnim );
m_deployed = TRUE;
}
void CEgon::EndBubbleAttack( void )
{
STOP_SOUND( ENT(m_pPlayer->pev), CHAN_STATIC, BUBB_SOUND_RUN );
EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_WEAPON, BUBB_SOUND_OFF, 0.98, ATTN_NORM, 0, 100);
m_fireState = FIRE_OFF;
m_flTimeWeaponIdle = gpGlobals->time + 2.0;
m_flNextPrimaryAttack = gpGlobals->time + 0.5;
// m_flNextSecondaryAttack = gpGlobals->time + 30;
DestroyEffect();
}
void CEgon::EndAttack( void )
{
STOP_SOUND( ENT(m_pPlayer->pev), CHAN_STATIC, EGON_SOUND_RUN );
EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_WEAPON, EGON_SOUND_OFF, 0.98, ATTN_NORM, 0, 100);
m_fireState = FIRE_OFF;
m_flTimeWeaponIdle = gpGlobals->time + 2.0;
m_flNextPrimaryAttack = gpGlobals->time + 0.5;
// m_flNextSecondaryAttack = gpGlobals->time + 30;
DestroyEffect();
}
void CEgon::Attack( void )
{
// don't fire underwater
if ( m_pPlayer->pev->waterlevel == 3 )
{
if ( m_fireState != FIRE_OFF || m_pBeam )
{
EndAttack();
}
else
{
PlayEmptySound( );
}
return;
}
UTIL_MakeVectors( m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle );
Vector vecAiming = gpGlobals->v_forward;
Vector vecSrc = m_pPlayer->GetGunPosition( );
int flags;
#if defined( CLIENT_WEAPONS )
flags = FEV_NOTHOST;
#else
flags = 0;
#endif
switch( m_fireState )
{
case FIRE_OFF:
{
if ( !HasAmmo() )
{
m_flNextPrimaryAttack = m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.25;
PlayEmptySound( );
return;
}
m_flAmmoUseTime = gpGlobals->time;// start using ammo ASAP.
PLAYBACK_EVENT_FULL( flags, m_pPlayer->edict(), m_usEgonFire, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, m_fireState, m_fireMode, 1, 0 );
m_shakeTime = 0;
m_pPlayer->m_iWeaponVolume = EGON_PRIMARY_VOLUME;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 0.1;
pev->fuser1 = UTIL_WeaponTimeBase() + 2;
m_shootTime = gpGlobals->time +2;
if ( m_fireMode == FIRE_WIDE )
{
EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_WEAPON, EGON_SOUND_STARTUP, 0.98, ATTN_NORM, 0, 125 );
}
else
{
EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_WEAPON, EGON_SOUND_STARTUP, 0.9, ATTN_NORM, 0, 80 );
}
pev->dmgtime = gpGlobals->time + GetPulseInterval();
m_fireState = FIRE_CHARGE;
}
break;
case FIRE_CHARGE:
{
Fire( vecSrc, vecAiming );
m_pPlayer->m_iWeaponVolume = EGON_PRIMARY_VOLUME;
if ( m_shootTime != 0 && gpGlobals->time > m_shootTime )
{
EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_STATIC, EGON_SOUND_RUN, 0.98, ATTN_NORM, 0, 125 );
m_shootTime = 0;
}
//if ( pev->fuser1 <= UTIL_WeaponTimeBase() )
//{
// PLAYBACK_EVENT_FULL( flags, m_pPlayer->edict(), m_usEgonFire, 0, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, m_fireState, m_fireMode, 0, 0 );
// pev->fuser1 = 1000;
// }
if ( !HasAmmo() )
{
EndAttack();
m_flNextPrimaryAttack = m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 1.0;
}
}
break;
}
}
void CEgon::Fire( const Vector &vecOrigSrc, const Vector &vecDir )
{
Vector vecDest = vecOrigSrc + vecDir * 2048;
edict_t *pentIgnore;
TraceResult tr;
pentIgnore = m_pPlayer->edict();
Vector tmpSrc = vecOrigSrc + gpGlobals->v_up * -8 + gpGlobals->v_right * 3;
// ALERT( at_console, "." );
UTIL_TraceLine( vecOrigSrc, vecDest, dont_ignore_monsters, pentIgnore, &tr );
if (tr.fAllSolid)
return;
#ifndef CLIENT_DLL
CBaseEntity *pEntity = CBaseEntity::Instance(tr.pHit);
if (pEntity == NULL)
return;
if ( g_pGameRules->IsMultiplayer() )
{
if ( m_pSprite && pEntity->pev->takedamage )
{
m_pSprite->pev->effects &= ~EF_NODRAW;
}
else if ( m_pSprite )
{
m_pSprite->pev->effects |= EF_NODRAW;
}
}
#endif
float timedist;
switch ( m_fireMode )
{
case FIRE_NARROW:
#ifndef CLIENT_DLL
if ( pev->dmgtime < gpGlobals->time )
{
// Narrow mode only does damage to the entity it hits
ClearMultiDamage();
if (pEntity->pev->takedamage)
{
pEntity->TraceAttack( m_pPlayer->pev, gSkillData.plrDmgEgonNarrow, vecDir, &tr, DMG_ENERGYBEAM );
}
ApplyMultiDamage(m_pPlayer->pev, m_pPlayer->pev);
if ( g_pGameRules->IsMultiplayer() )
{
// multiplayer uses 1 ammo every 1/10th second
if ( gpGlobals->time >= m_flAmmoUseTime )
{
UseAmmo( 1 );
m_flAmmoUseTime = gpGlobals->time + 0.1;
}
}
else
{
// single player, use 3 ammo/second
if ( gpGlobals->time >= m_flAmmoUseTime )
{
UseAmmo( 1 );
m_flAmmoUseTime = gpGlobals->time + 0.166;
}
}
pev->dmgtime = gpGlobals->time + GetPulseInterval();
}
#endif
timedist = ( pev->dmgtime - gpGlobals->time ) / GetPulseInterval();
break;
case FIRE_WIDE:
#ifndef CLIENT_DLL
if ( pev->dmgtime < gpGlobals->time )
{
// wide mode does damage to the ent, and radius damage
ClearMultiDamage();
if (pEntity->pev->takedamage)
{
pEntity->TraceAttack( m_pPlayer->pev, gSkillData.plrDmgEgonWide, vecDir, &tr, DMG_ENERGYBEAM | DMG_ALWAYSGIB);
}
ApplyMultiDamage(m_pPlayer->pev, m_pPlayer->pev);
if ( g_pGameRules->IsMultiplayer() )
{
// radius damage a little more potent in multiplayer.
::RadiusDamage( tr.vecEndPos, pev, m_pPlayer->pev, gSkillData.plrDmgEgonWide/4, 128, CLASS_NONE, DMG_ENERGYBEAM | DMG_BLAST | DMG_ALWAYSGIB );
}
if ( !m_pPlayer->IsAlive() )
return;
if ( g_pGameRules->IsMultiplayer() )
{
//multiplayer uses 5 ammo/second
if ( gpGlobals->time >= m_flAmmoUseTime )
{
UseAmmo( 1 );
m_flAmmoUseTime = gpGlobals->time + 0.2;
}
}
else
{
// Wide mode uses 10 charges per second in single player
if ( gpGlobals->time >= m_flAmmoUseTime )
{
UseAmmo( 1 );
m_flAmmoUseTime = gpGlobals->time + 0.1;
}
}
pev->dmgtime = gpGlobals->time + GetDischargeInterval();
if ( m_shakeTime < gpGlobals->time )
{
UTIL_ScreenShake( tr.vecEndPos, 5.0, 150.0, 0.75, 250.0 );
m_shakeTime = gpGlobals->time + 1.5;
}
}
#endif
timedist = ( pev->dmgtime - gpGlobals->time ) / GetDischargeInterval();
break;
}
if ( timedist < 0 )
timedist = 0;
else if ( timedist > 1 )
timedist = 1;
timedist = 1-timedist;
UpdateEffect( tmpSrc, tr.vecEndPos, timedist );
}
class CEgonAmmo : public CBasePlayerAmmo
{
void Spawn( void )
{
pev->classname = MAKE_STRING("ammo_egonclip");
Precache( );
SET_MODEL(ENT(pev), "models/w_chainammo.mdl");
CBasePlayerAmmo::Spawn( );
}
void Precache( void )
{
PRECACHE_MODEL ("models/w_chainammo.mdl");
PRECACHE_SOUND("items/9mmclip1.wav");
}
BOOL AddAmmo( CBaseEntity *pOther )
{
if (pOther->GiveAmmo( AMMO_URANIUMBOX_GIVE, "uranium", URANIUM_MAX_CARRY ) != -1)
{
EMIT_SOUND(ENT(pev), CHAN_ITEM, "items/9mmclip1.wav", 1, ATTN_NORM);
return TRUE;
}
return FALSE;
}
};
LINK_ENTITY_TO_CLASS( ammo_egonclip, CEgonAmmo );
#endif

View File

@ -0,0 +1,187 @@
// ---------------------------------------------------------------
// 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 "monsters.h"
#include "weapons.h"
#include "nodes.h"
#include "player.h"
#include "gamerules.h"
#include "BMOD_flyingcrowbar.h"
LINK_ENTITY_TO_CLASS( flying_crowbar, CFlyingCrowbar );
void CFlyingCrowbar::Spawn( )
{
Precache( );
// The flying crowbar is MOVETYPE_TOSS, and SOLID_BBOX.
// We want it to be affected by gravity, and hit objects
// within the game.
pev->movetype = MOVETYPE_TOSS;
pev->solid = SOLID_BBOX;
// Use the world crowbar model.
SET_MODEL(ENT(pev), "models/w_crowbar.mdl");
// Set the origin and size for the HL engine collision
// tables.
UTIL_SetOrigin( pev, pev->origin );
UTIL_SetSize(pev, Vector(-4, -4, -4), Vector(4, 4, 4));
// Store the owner for later use. We want the owner to be able
// to hit themselves with the crowbar. The pev->owner gets cleared
// later to avoid hitting the player as they throw the crowbar.
if ( pev->owner )
m_hOwner = Instance( pev->owner );
// Set the think funtion.
SetThink( BubbleThink );
pev->nextthink = gpGlobals->time + 0.25;
// Set the touch function.
SetTouch( SpinTouch );
}
void CFlyingCrowbar::Precache( )
{
PRECACHE_MODEL ("models/w_crowbar.mdl");
PRECACHE_SOUND ("weapons/cbar_hitbod1.wav");
PRECACHE_SOUND ("weapons/cbar_hit1.wav");
PRECACHE_SOUND ("weapons/cbar_miss1.wav");
}
void CFlyingCrowbar::SpinTouch( CBaseEntity *pOther )
{
// We touched something in the game. Look to see if the object
// is allowed to take damage.
if (pOther->pev->takedamage)
{
// Get the traceline info to the target.
TraceResult tr = UTIL_GetGlobalTrace( );
// Apply damage to the target. If we have an owner stored, use that one,
// otherwise count it as self-inflicted.
ClearMultiDamage( );
pOther->TraceAttack(pev, 90, pev->velocity.Normalize(), &tr,
DMG_NEVERGIB );
if (m_hOwner != NULL)
ApplyMultiDamage( pev, m_hOwner->pev );
else
ApplyMultiDamage( pev, pev );
}
// If we hit a player, make a nice squishy thunk sound. Otherwise
// make a clang noise and throw a bunch of sparks.
if (pOther->IsPlayer())
EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, "weapons/cbar_hitbod1.wav",
1.0, ATTN_NORM, 0, 100);
else
{
EMIT_SOUND_DYN(ENT(pev), CHAN_WEAPON, "weapons/cbar_hit1.wav",
1.0, ATTN_NORM, 0, 100);
if (UTIL_PointContents(pev->origin) != CONTENTS_WATER)
{
UTIL_Sparks( pev->origin );
UTIL_Sparks( pev->origin );
UTIL_Sparks( pev->origin );
}
}
// Don't draw the flying crowbar anymore.
pev->effects |= EF_NODRAW;
pev->solid = SOLID_NOT;
// Spawn a crowbar weapon
CBasePlayerWeapon *pItem = (CBasePlayerWeapon *)Create( "weapon_crowbar",
pev->origin , pev->angles, edict() );
// Spawn a weapon box
CWeaponBox *pWeaponBox = (CWeaponBox *)CBaseEntity::Create(
"weaponbox", pev->origin, pev->angles, edict() );
// don't let weapon box tilt.
pWeaponBox->pev->angles.x = 0;
pWeaponBox->pev->angles.z = 0;
// remove the weapon box after 4 mins.
pWeaponBox->pev->nextthink = gpGlobals->time + 240;
pWeaponBox->SetThink( CWeaponBox::Kill );
// Pack the crowbar in the weapon box
pWeaponBox->PackWeapon( pItem );
// *** Start BubbleMod Rune code ***
// Check to see if the crowbar rune is active on the owner,
// if it is, then remove this crowbar after 3 seconds
// instead if 2 mins. This prevents too many crowbars from
// piling up on the server.
//
// REMOVE THIS IF YOU ARE NOT USING THE RUNE CODE
if (m_pPlayer->m_RuneFlags == RUNE_CROWBAR)
pWeaponBox->pev->nextthink = gpGlobals->time + 3;
// *** End BubbleMod Rune Code ***
// Get the unit vector in the direction of motion.
Vector vecDir = pev->velocity.Normalize( );
// Trace a line along the velocity vector to get the normal at impact.
TraceResult tr;
UTIL_TraceLine(pev->origin, pev->origin + vecDir * 100,
dont_ignore_monsters, ENT(pev), &tr);
// Throw the weapon box along the normal so it looks kinda
// like a ricochet. This would be better if I actually
// calcualted the reflection angle, but I'm lazy. :)
pWeaponBox->pev->velocity = tr.vecPlaneNormal * 300;
// Remove this flying_crowbar from the world.
SetThink ( SUB_Remove );
pev->nextthink = gpGlobals->time + .1;
}
void CFlyingCrowbar::BubbleThink( void )
{
// We have no owner. We do this .25 seconds AFTER the crowbar
// is thrown so that we don't hit the owner immediately when throwing
// it. If is comes back later, we want to be able to hit the owner.
pev->owner = NULL;
// Only think every .25 seconds.
pev->nextthink = gpGlobals->time + 0.25;
// Make a whooshy sound.
EMIT_SOUND_DYN(ENT(pev), CHAN_VOICE, "weapons/cbar_miss1.wav",
1, ATTN_NORM, 0, 120);
// If the crowbar enters water, make some bubbles.
if (pev->waterlevel)
UTIL_BubbleTrail( pev->origin - pev->velocity * 0.1, pev->origin, 1 );
}

View File

@ -0,0 +1,57 @@
// ---------------------------------------------------------------
// Flying Crowbar Entity. Ver 1.0 as seen in Lambda BubbleMod
// ---------------------------------------------------------------
// 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.
//
// ---------------------------------------------------------------
// Flying Crowbar Entity
#ifndef C_FLYING_CROWBAR
#define C_FLYING_CROWBAR
class CFlyingCrowbar : public CBaseEntity
{
public:
void Spawn( void );
void Precache( void );
void EXPORT BubbleThink( void );
void EXPORT SpinTouch( CBaseEntity *pOther );
CBasePlayer *m_pPlayer;
private:
EHANDLE m_hOwner; // Original owner is stored here so we can
// allow the crowbar to hit the user.
};
#endif

View File

@ -0,0 +1,669 @@
// ---------------------------------------------------------------
// 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 "player.h"
#include "weapons.h"
#include "gamerules.h"
#include "game.h"
#include "BMOD_constants.h"
#define MAX_RULE_BUFFER 1024
extern DLL_GLOBAL int g_VoteStatus;
extern DLL_GLOBAL float g_VoteTimer;
typedef struct mapcycle_item_s
{
struct mapcycle_item_s *next;
char mapname[ 32 ];
int minplayers, maxplayers;
char rulebuffer[ MAX_RULE_BUFFER ];
} mapcycle_item_t;
typedef struct mapcycle_s
{
struct mapcycle_item_s *items;
struct mapcycle_item_s *next_item;
} mapcycle_t;
extern DLL_GLOBAL BOOL g_fGameOver;
extern int gmsgSpectator;
extern edict_t *EntSelectSpawnPoint( CBaseEntity *pPlayer );
extern int CountPlayers( void );
extern void DestroyMapCycle( mapcycle_t *cycle );
extern int ReloadMapCycleFile( char *filename, mapcycle_t *cycle );
extern void ExtractCommandString( char *s, char *szCommand );
extern cvar_t bm_guns;
extern cvar_t bm_ammo;
extern cvar_t bm_g;
extern cvar_t bm_cbar_mod;
extern cvar_t bm_mp5_mod;
extern cvar_t bm_shotty_mod;
extern cvar_t bm_xbow_mod;
extern cvar_t bm_rpg_mod;
extern cvar_t bm_tau_mod;
extern cvar_t bm_gluon_mod;
extern cvar_t bm_hornet_mod;
extern cvar_t bm_trip_mod;
extern cvar_t bm_snarks_mod;
extern cvar_t bm_spawneffects;
/*
extern cvar_t bm_score_crowbar;
extern cvar_t bm_score_throwncbar;
extern cvar_t bm_score_9mm;
extern cvar_t bm_score_357;
extern cvar_t bm_score_mp5;
extern cvar_t bm_score_shotgun;
extern cvar_t bm_score_squidspit;
extern cvar_t bm_score_zapgun;
extern cvar_t bm_score_mp5grenade;
extern cvar_t bm_score_gluon;
extern cvar_t bm_score_tau;
extern cvar_t bm_score_bolt;
extern cvar_t bm_score_crossbow;
extern cvar_t bm_score_satchel;
extern cvar_t bm_score_handgrenade;
extern cvar_t bm_score_rpg;
extern cvar_t bm_score_snarks;
extern cvar_t bm_score_tripmine;
int CGameRules :: BMOD_IPointsForKill( CBasePlayer *pAttacker, CBasePlayer *pKilled, entvars_t *pInflictor)
{
if (g_pGameRules->IsTeamplay())
{
if ( !pKilled )
return 0;
if ( !pAttacker )
return 1;
if ( pAttacker != pKilled && PlayerRelationship( pAttacker, pKilled ) == GR_TEAMMATE )
return -1;
}
if (!strcmp(STRING(pInflictor->classname), "weapon_crowbar"))
return bm_score_crowbar.value;
else if (!strcmp(STRING(pInflictor->classname), "flying_crowbar"))
return bm_score_throwncbar.value;
else if (!strcmp(STRING(pInflictor->classname), "weapon_9mmhandgun"))
return bm_score_9mm.value;
else if (!strcmp(STRING(pInflictor->classname), "weapon_357"))
return bm_score_357.value;
else if (!strcmp(STRING(pInflictor->classname), "weapon_9mmAR"))
return bm_score_mp5.value;
else if (!strcmp(STRING(pInflictor->classname), "weapon_shotgun"))
return bm_score_shotgun.value;
else if (!strcmp(STRING(pInflictor->classname), "squidspit"))
return bm_score_squidspit.value;
else if (!strcmp(STRING(pInflictor->classname), "weapon_hornetgun"))
return bm_score_zapgun.value;
else if (!strcmp(STRING(pInflictor->classname), "weapon_egon"))
return bm_score_gluon.value;
else if (!strcmp(STRING(pInflictor->classname), "weapon_gauss"))
return bm_score_tau.value;
else if (!strcmp(STRING(pInflictor->classname), "bolt"))
return bm_score_bolt.value;
else if (!strcmp(STRING(pInflictor->classname), "weapon_crossbow"))
return bm_score_crossbow.value;
else if (!strcmp(STRING(pInflictor->classname), "monster_satchel"))
return bm_score_satchel.value;
else if (!strcmp(STRING(pInflictor->classname), "hand_grenade"))
return bm_score_handgrenade.value;
else if (!strcmp(STRING(pInflictor->classname), "rpg_rocket"))
return bm_score_rpg.value;
else if (!strcmp(STRING(pInflictor->classname), "monster_snark"))
return bm_score_snarks.value;
else
return 1;
}
*/
void CHalfLifeMultiplay :: BMOD_ClientDisconnected(edict_t *pClient, CBasePlayer *pPlayer)
{
// Disconnecting observers
//MESSAGE_BEGIN( MSG_ALL, gmsgSpectator );
// WRITE_BYTE( ENTINDEX(pClient) );
// WRITE_BYTE( 0 );
//MESSAGE_END();
CBasePlayer *client = NULL;
while ( ((client = (CBasePlayer*)UTIL_FindEntityByClassname( client, "player" )) != NULL) && (!FNullEnt(client->edict())) )
{
if ( !client->pev )
continue;
if ( client == pPlayer )
continue;
// If a spectator was chasing this player, move him/her onto the next player
if ( client->m_hObserverTarget == pPlayer )
{
int iMode = client->pev->iuser1;
client->pev->iuser1 = 0;
client->m_hObserverTarget = NULL;
client->Observer_SetMode( iMode );
}
}
// Destroy all satchels, trips, and snark mines owned by this player.
DeactivateSatchels( pPlayer );
DeactivateTrips( pPlayer );
DeactivateSnarkTrips( pPlayer );
pPlayer->m_bIsConnected = FALSE;
UTIL_SaveRestorePlayer(pPlayer, 1, 0);
}
void CHalfLifeMultiplay :: BMOD_PlayerSpawn( CBasePlayer *pPlayer )
{
// Send new players into observer mode.
if (!pPlayer->m_iFirstSpawn)
{
pPlayer->m_iFirstSpawn = TRUE;
edict_t *pentSpawnSpot = EntSelectSpawnPoint( pPlayer );
pPlayer->StartObserver( VARS(pentSpawnSpot)->origin, VARS(pentSpawnSpot)->angles);
pPlayer->m_iSpawnKills = 0;
pPlayer->m_iTypeKills = 0;
pPlayer->m_bBanMe = FALSE;
UTIL_SaveRestorePlayer(pPlayer, 0, 0);
}
// Else stuff for a new player.
else if (bm_spawneffects.value) {
MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY );
WRITE_BYTE( TE_TELEPORT ); //This denotes which temporary intity we want to use
WRITE_COORD(pPlayer->pev->origin.x);// Location-X
WRITE_COORD(pPlayer->pev->origin.y);// Location-Y
WRITE_COORD(pPlayer->pev->origin.z);// Location-Z
MESSAGE_END();
EMIT_SOUND(ENT(pPlayer->pev), CHAN_BODY, "debris/beamstart8.wav", 1.0, ATTN_NORM);
}
}
void CHalfLifeMultiplay :: BMOD_InitHUD( CBasePlayer *pl )
{
pl->m_bIsConnected = TRUE;
pl->m_iKillsThisFrame = 0;
pl->m_iSpamSay = 0;
pl->m_LocateMode = FALSE;
pl->m_LeetSpeak = FALSE;
// pl->m_iHLHack = 0;
}
void CGameRules :: BMOD_PreChangeLevel( void )
{
return;
}
void CHalfLifeMultiplay :: BMOD_PreChangeLevel( void )
{
static char szPreviousMapCycleFile[ 256 ];
static mapcycle_t mapcycle;
char szNextMap[32];
char szFirstMapInList[32];
char szCommands[ 1500 ];
char szRules[ 1500 ];
int minplayers = 0, maxplayers = 0;
strcpy( szFirstMapInList, "hldm1" ); // the absolute default level is hldm1
int curplayers;
BOOL do_cycle = TRUE;
// find the map to change to
char *mapcfile = (char*)CVAR_GET_STRING( "mapcyclefile" );
ASSERT( mapcfile != NULL );
szCommands[ 0 ] = '\0';
szRules[ 0 ] = '\0';
curplayers = CountPlayers();
// Has the map cycle filename changed?
if ( stricmp( mapcfile, szPreviousMapCycleFile ) )
{
strcpy( szPreviousMapCycleFile, mapcfile );
DestroyMapCycle( &mapcycle );
if ( !ReloadMapCycleFile( mapcfile, &mapcycle ) || ( !mapcycle.items ) )
{
ALERT( at_console, "Unable to load map cycle file %s\n", mapcfile );
do_cycle = FALSE;
}
}
if ( do_cycle && mapcycle.items )
{
BOOL keeplooking = FALSE;
BOOL found = FALSE;
mapcycle_item_s *item;
// Assume current map
strcpy( szNextMap, STRING(gpGlobals->mapname) );
strcpy( szFirstMapInList, STRING(gpGlobals->mapname) );
// Traverse list
for ( item = mapcycle.next_item; item->next != mapcycle.next_item; item = item->next )
{
keeplooking = FALSE;
ASSERT( item != NULL );
if ( item->minplayers != 0 )
{
if ( curplayers >= item->minplayers )
{
found = TRUE;
minplayers = item->minplayers;
}
else
{
keeplooking = TRUE;
}
}
if ( item->maxplayers != 0 )
{
if ( curplayers <= item->maxplayers )
{
found = TRUE;
maxplayers = item->maxplayers;
}
else
{
keeplooking = TRUE;
}
}
if ( keeplooking )
continue;
found = TRUE;
break;
}
if ( !found )
{
item = mapcycle.next_item;
}
// Increment next item pointer
mapcycle.next_item = item->next;
// Perform logic on current item
strcpy( szNextMap, item->mapname );
ExtractCommandString( item->rulebuffer, szCommands );
strcpy( szRules, item->rulebuffer );
}
if ( !IS_MAP_VALID(szNextMap) )
{
strcpy( szNextMap, szFirstMapInList );
}
CVAR_SET_STRING("bm_map", STRING(gpGlobals->mapname) );
CVAR_SET_STRING("bm_nextmap", szNextMap );
}
// Bmod version of Changelevel
void CHalfLifeMultiplay :: ChangeLevel( void )
{
char szNextMap[32];
// Confirm what map we need.
// BMOD_PreChangeLevel();
strcpy( szNextMap, (char*)CVAR_GET_STRING( "bm_nextmap" ) );
g_fGameOver = TRUE;
ALERT( at_console, "CHANGE LEVEL: %s\n", szNextMap );
CHANGE_LEVEL( szNextMap, NULL );
}
void CHalfLifeMultiplay :: BMOD_Think ( void )
{
static float setVarsTime = 0;
if (setVarsTime < gpGlobals->time )
{
g_engfuncs.pfnCvar_DirectSet( &bm_ver, UTIL_VarArgs( "%s", BMOD_VERSION ) );
g_engfuncs.pfnCvar_DirectSet( &bm_bname, UTIL_VarArgs( "%s", BMOD_BRANCH_NAME ) );
g_engfuncs.pfnCvar_DirectSet( &bm_bver, UTIL_VarArgs( "%s", BMOD_BRANCH_VERSION ) );
g_engfuncs.pfnCvar_DirectSet( &bm_burl, UTIL_VarArgs( "%s", BMOD_BRANCH_URL ) );
BMOD_UpdateGuns();
BMOD_UpdateMods();
//UTIL_ClientPrintAll( HUD_PRINTTALK, UTIL_VarArgs( "<SERVER> updated at %f", gpGlobals->time));
setVarsTime = gpGlobals->time + 1;
}
// BMod voting
if ((g_VoteStatus == 1) && (g_VoteTimer < gpGlobals->time))
{
int players = CountPlayers();
int votesNeeded = (players * 3 / 4) + ((players < 3) ? 1 : 0);
char winner[81];
strcpy(winner, UTIL_CountVotes());
int winvotes = winner[0];
char map[81];
strcpy(map, &winner[1]);
UTIL_SpeakAll("dadeda");
if (winvotes >= votesNeeded) {
UTIL_ClientPrintAll( HUD_PRINTTALK, "<SERVER> *** We have a winner! ***\n");
}
else {
UTIL_ClientPrintAll( HUD_PRINTTALK, "<SERVER> *** Voting is closed! ***\n");
}
/*if (winvotes)
UTIL_ClientPrintAll( HUD_PRINTTALK, UTIL_VarArgs( "<SERVER> \"%s\" got %i vote(s). (needed %i to win with %i players)\n",
&(winner[1]),
winvotes,
votesNeeded,
players ) );*/
if (winvotes == 0)
UTIL_ClientPrintAll( HUD_PRINTTALK, "<SERVER> No votes were cast!\n");
if (winvotes >= votesNeeded)
{
if (!strcmp(map, "extend")) {
UTIL_ClientPrintAll( HUD_PRINTTALK, "<SERVER> Extend won the vote! This map will be extended 30 mins & 25 kills.\n");
int newTime = CVAR_GET_FLOAT("mp_timelimit") + 30;
int newFrags = CVAR_GET_FLOAT("mp_fraglimit") + 25;
CVAR_SET_FLOAT( "mp_timelimit", (newTime > bm_maxtime.value) ? bm_maxtime.value : newTime);
CVAR_SET_FLOAT( "mp_fraglimit", (newFrags > bm_maxfrags.value) ? bm_maxfrags.value : newFrags);
g_VoteStatus = 0;
}
else {
UTIL_ClientPrintAll( HUD_PRINTTALK, UTIL_VarArgs( "<SERVER> \"%s\" Won the vote! Changing map... please wait.\n",
&(winner[1])
));
CVAR_SET_STRING("bm_nextmap", &(winner[1]));
g_VoteStatus = 2;
g_VoteTimer = gpGlobals->time + 10;
}
UTIL_LogPrintf( "// Map \"%s\" won the map vote.\n", map);
}
else
{
if (winvotes)
UTIL_ClientPrintAll( HUD_PRINTTALK, UTIL_VarArgs( "<SERVER> \"%s\" got %i vote(s). (needed %i to win with %i players)\n",
&(winner[1]),
winvotes,
votesNeeded,
players ) );
UTIL_LogPrintf( "// Map vote ended.\n", map);
g_VoteStatus = 0;
}
}
if ((g_VoteStatus == 2) && (g_VoteTimer < gpGlobals->time))
{
g_VoteStatus = 0;
CVAR_SET_FLOAT( "mp_timelimit", 1);
}
// BMod
}
void CHalfLifeMultiplay :: BMOD_GiveGunsAndAmmo ( CBasePlayer *pPlayer )
{
char *pName;
char itemlist[1025];
char szTemp[80];
int iszItem;
// Give ammo
// make a copy because strtok is destructive
strncpy( itemlist, bm_ammo.string, 1024 );
pName = itemlist;
pName = strtok( pName, ";" );
while ( pName != NULL && *pName )
{
strcpy( szTemp, "ammo_" );
strcat( szTemp, pName );
iszItem = ALLOC_STRING( szTemp );
pPlayer->GiveNamedItem( STRING(iszItem) );
pName = strtok( NULL, ";" );
}
// Give guns
// make a copy because strtok is destructive
strncpy( itemlist, bm_guns.string, 1024 );
pName = itemlist;
pName = strtok( pName, ";" );
int guns = 0;
while ( pName != NULL && *pName )
{
strcpy( szTemp, "weapon_" );
strcat( szTemp, pName );
if (!strcmp(szTemp, "weapon_glock"))
{
strcpy( szTemp, "weapon_9mmhandgun" );
}
else if (!strcmp(szTemp, "weapon_mp5"))
{
strcpy( szTemp, "weapon_9mmAR" );
}
else if (!strcmp(szTemp, "weapon_python"))
{
strcpy( szTemp, "weapon_357" );
}
iszItem = ALLOC_STRING( szTemp );
pPlayer->GiveNamedItem( STRING(iszItem) );
pPlayer->SelectItem( STRING(iszItem) );
pName = strtok( NULL, ";" );
}
}
void CHalfLifeMultiplay :: BMOD_UpdateGuns ( void )
{
char *pName;
char itemlist[1024];
int guns = 0;
// guns
// make a copy because strtok is destructive
strncpy( itemlist, bm_guns.string, 1024 );
pName = itemlist;
pName = strtok( pName, ";" );
while ( pName != NULL && *pName )
{
if (!strcmp(pName, "crowbar"))
{
guns = guns | (1 << 0);
}
else if (!strcmp(pName, "9mmhandgun") || !strcmp(pName, "glock"))
{
guns = guns | (1 << 1);
}
else if (!strcmp(pName, "357") || !strcmp(pName, "python"))
{
guns = guns | (1 << 2);
}
else if (!strcmp(pName, "9mmAR") || !strcmp(pName, "mp5"))
{
guns = guns | (1 << 3);
}
else if (!strcmp(pName, "shotgun"))
{
guns = guns | (1 << 4);
}
else if (!strcmp(pName, "egon"))
{
guns = guns | (1 << 5);
}
else if (!strcmp(pName, "gauss"))
{
guns = guns | (1 << 6);
}
else if (!strcmp(pName, "rpg"))
{
guns = guns | (1 << 7);
}
else if (!strcmp(pName, "hornetgun"))
{
guns = guns | (1 << 8);
}
else if (!strcmp(pName, "tripmine"))
{
guns = guns | (1 << 9);
}
else if (!strcmp(pName, "satchel"))
{
guns = guns | (1 << 10);
}
else if (!strcmp(pName, "handgrenade"))
{
guns = guns | (1 << 11);
}
else if (!strcmp(pName, "snark"))
{
guns = guns | (1 << 12);
}
else if (!strcmp(pName, "crossbow"))
{
guns = guns | (1 << 13);
}
pName = strtok( NULL, ";" );
}
g_engfuncs.pfnCvar_DirectSet( &bm_g, UTIL_VarArgs( "%d", guns ) );
}
void CHalfLifeMultiplay :: BMOD_UpdateMods ( void )
{
int mods = 0;
// mods
// bm_cbar_mod
// bm_mp5_mod
// bm_shotty_mod
// bm_xbow_mod
// bm_rpg_mod
// bm_tau_mod
// bm_gluon_mod
// bm_hornet_mod
// bm_trip_mod
// bm_snarks_mod
if (bm_cbar_mod.value)
{
mods = mods | (1 << 0);
}
/*
if (!strcmp(pName, "9mmhandgun") || !strcmp(pName, "glock"))
{
mods = mods | (1 << 1);
}
*/
/*
if (!strcmp(pName, "357") || !strcmp(pName, "python"))
{
mods = mods | (1 << 2);
}
*/
if (bm_mp5_mod.value)
{
mods = mods | (1 << 3);
}
if (bm_shotty_mod.value)
{
mods = mods | (1 << 4);
}
if (bm_gluon_mod.value)
{
mods = mods | (1 << 5);
}
if (bm_tau_mod.value)
{
mods = mods | (1 << 6);
}
if (bm_rpg_mod.value)
{
mods = mods | (1 << 7);
}
if (bm_hornet_mod.value)
{
mods = mods | (1 << 8);
}
if (bm_trip_mod.value)
{
mods = mods | (1 << 9);
}
/*
if (!strcmp(pName, "satchel"))
{
mods = mods | (1 << 10);
}
*/
/*
if (!strcmp(pName, "handgrenade"))
{
mods = mods | (1 << 11);
}
*/
if (bm_snarks_mod.value)
{
mods = mods | (1 << 12);
}
if (bm_xbow_mod.value)
{
mods = mods | (1 << 13);
}
g_engfuncs.pfnCvar_DirectSet( &bm_mods, UTIL_VarArgs( "%d", mods ) );
}

View File

@ -0,0 +1,163 @@
// ---------------------------------------------------------------
// 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 "BMOD_hornetgun.h"
//=========================================================
// Bullsquid's spit projectile
//=========================================================
class BMODSquidSpit : public CBaseEntity
{
public:
void Spawn( void );
void Precache( void );
static void Shoot( entvars_t *Owner, Vector vecStart, Vector vecVelocity );
void Touch( CBaseEntity *pOther );
void EXPORT Animate( void );
static TYPEDESCRIPTION m_SaveData[];
int m_maxFrame;
entvars_t *pevOwner;
};
LINK_ENTITY_TO_CLASS( bmod_squidspit, BMODSquidSpit );
void BMODSquidSpit::Precache( void )
{
}
void BMODSquidSpit::Spawn( void )
{
pev->movetype = MOVETYPE_FLY;
pev->classname = MAKE_STRING( "bmod_squidspit" );
pev->solid = SOLID_BBOX;
pev->rendermode = kRenderTransAlpha;
pev->renderamt = 255;
SET_MODEL(ENT(pev), "sprites/bigspit.spr");
pev->frame = 0;
pev->scale = 0.5;
UTIL_SetSize( pev, Vector( -4, -4, -4), Vector(4, 4, 4) );
m_maxFrame = (float) MODEL_FRAMES( pev->modelindex ) - 1;
MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY );
WRITE_BYTE( TE_BEAMFOLLOW );
WRITE_SHORT(entindex()); // entity
WRITE_SHORT(g_sModelIndexSmokeTrail ); // model
WRITE_BYTE( 2 ); // life
WRITE_BYTE( 4 ); // width
WRITE_BYTE( 128 ); // r, g, b
WRITE_BYTE( 200 ); // r, g, b
WRITE_BYTE( 0 ); // r, g, b
WRITE_BYTE( 255 ); // brightness
MESSAGE_END(); // move PHS/PVS data sending into here (SEND_ALL, SEND_PVS, SEND_PHS)
}
void BMODSquidSpit::Animate( void )
{
pev->nextthink = gpGlobals->time + 0.1;
if ( pev->frame++ )
{
if ( pev->frame > m_maxFrame )
{
pev->frame = 0;
}
}
}
void BMODSquidSpit::Shoot( entvars_t *Owner, Vector vecStart, Vector vecVelocity )
{
BMODSquidSpit *pSpit = GetClassPtr( (BMODSquidSpit *)NULL );
pSpit->Spawn();
UTIL_SetOrigin( pSpit->pev, vecStart );
pSpit->pev->velocity = vecVelocity;
pSpit->pev->owner = ENT(Owner);
pSpit->pevOwner = Owner;
pSpit->SetThink ( Animate );
pSpit->pev->nextthink = gpGlobals->time + 0.1;
}
void BMODSquidSpit::Touch ( CBaseEntity *pOther )
{
TraceResult tr;
int iPitch;
// splat sound
iPitch = RANDOM_FLOAT( 90, 110 );
EMIT_SOUND_DYN( ENT(pev), CHAN_VOICE, "bullchicken/bc_acid1.wav", 1, ATTN_NORM, 0, iPitch );
switch ( RANDOM_LONG( 0, 1 ) )
{
case 0:
EMIT_SOUND_DYN( ENT(pev), CHAN_WEAPON, "bullchicken/bc_spithit1.wav", 1, ATTN_NORM, 0, iPitch );
break;
case 1:
EMIT_SOUND_DYN( ENT(pev), CHAN_WEAPON, "bullchicken/bc_spithit2.wav", 1, ATTN_NORM, 0, iPitch );
break;
}
// make a splat on the wall
UTIL_TraceLine( pev->origin, pev->origin + pev->velocity, dont_ignore_monsters, ENT( pev ), &tr );
UTIL_DecalTrace(&tr, DECAL_SPIT1 + RANDOM_LONG(0,1));
// make some flecks
MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, tr.vecEndPos );
WRITE_BYTE( TE_SPRITE_SPRAY );
WRITE_COORD( tr.vecEndPos.x); // pos
WRITE_COORD( tr.vecEndPos.y);
WRITE_COORD( tr.vecEndPos.z);
WRITE_COORD( tr.vecPlaneNormal.x); // dir
WRITE_COORD( tr.vecPlaneNormal.y);
WRITE_COORD( tr.vecPlaneNormal.z);
WRITE_SHORT( g_sModelIndexSpit ); // model
WRITE_BYTE ( 5 ); // count
WRITE_BYTE ( 30 ); // speed
WRITE_BYTE ( 80 ); // noise ( client will divide by 100 )
MESSAGE_END();
if ( pOther->IsPlayer() )
{
ClearMultiDamage( );
pOther->TraceAttack( pevOwner, 30, pev->origin + pev->velocity, &tr, DMG_GENERIC );
ApplyMultiDamage( pev, pevOwner );
}
SetThink ( SUB_Remove );
pev->nextthink = gpGlobals->time;
}

View File

@ -0,0 +1,72 @@
#ifndef HORNETGUN_H
#define HORNETGUN_H
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "monsters.h"
#include "weapons.h"
#include "nodes.h"
#include "player.h"
#include "hornet.h"
#include "gamerules.h"
#include "decals.h"
#include "BMOD_messaging.h"
extern cvar_t bm_hornet_mod;
#define HGUN_MAX_BEAMS 6
#define HGUN_CHARGE_TIME .8 / HGUN_MAX_BEAMS
#define HGUN_ZAP_TIME 1
class CHgun : public CBasePlayerWeapon
{
public:
void Spawn( void );
void Precache( void );
int iItemSlot( void ) { return 4; }
int GetItemInfo(ItemInfo *p);
int AddToPlayer( CBasePlayer *pPlayer );
void PrimaryAttack( void );
void SecondaryAttack( void );
BOOL Deploy( void );
BOOL IsUseable( void );
void Holster( int skiplocal = 0 );
void Reload( void );
void Recharge( void );
void WeaponIdle( void );
float m_flNextAnimTime;
float m_flRechargeTime;
int m_iFirePhase;// don't save me.
float m_fNextPhaseTime;
CBeam *m_pBeam[HGUN_MAX_BEAMS];
void ClearBeams( );
void ArmBeam( Vector color );
void ZapBeam( void );
void BeamGlow( void );
void FreezeRay( void );
void ZapGun (void );
void MultiZapGun (void );
void SquidSpit ( void );
void LaunchSnark ( void );
void OldPrimaryAttack( void );
void OldSecondaryAttack( void );
int m_iFireMode;
float m_fModeSwitchDelay;
int m_iBeams;
short m_sGlowSpr;
int m_iMaxammo;
short iZapBeamSpr;
private:
unsigned short m_usHornetFire;
};
#endif

View File

@ -0,0 +1,121 @@
// ---------------------------------------------------------------
// 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 "BMOD_messaging.h"
#include "game.h"
#include "BMOD_constants.h"
extern cvar_t timeleft;
extern cvar_t fragsleft;
// extern cvar_t timelimit;
extern cvar_t fraglimit;
// pEnt is the player the message needs to go to
// iChannel is the message channel defind in BMOD_messaging.h
// vecColor is r, g, b color values for the message
// vecTime is fadein, hold, and fadeout times in seconds.
// msg is the message to display.
//
// Special msg values:
// "SPEC" - spectator message.
//
void PrintMessage( CBaseEntity *pEnt, int iChannel, Vector vecColor, Vector vecTime, char *msg)
{
char szText[256];
hudtextparms_t hText;
if (!strcmp("SPEC", msg))
{
char szTime[51] = "No Limit";
if (timeleft.value)
{
float time = timeleft.value;
sprintf(szTime, "%im, %is", (int)time/60, (int)time%60 );
}
// BMOD_PreChangeLevel();
sprintf(szText, "BUBBLE MOD - http://www.bubblemod.org\n%s Version %s - %s\n\nCurrent Map: %s\nNext Map: %s\nTime Left: %s\nFrags Left: %i/%i",
BMOD_BRANCH_NAME,
BMOD_BRANCH_VERSION,
BMOD_PLATFORM,
CVAR_GET_STRING("bm_map"),
CVAR_GET_STRING("bm_nextmap"),
szTime,
(int)fragsleft.value,
(int)fraglimit.value
);
}
else {
sprintf(szText, msg);
}
memset(&hText, 0, sizeof(hText));
switch (iChannel)
{
case BMOD_CHAN_INFO:
hText.x = 0.01;
hText.y = 0.1;
break;
case BMOD_CHAN_RUNE:
hText.x = -1;
hText.y = 1;
break;
case BMOD_CHAN_COUNTDOWN:
hText.x = -1;
hText.y = -1;
break;
case BMOD_CHAN_WEAPON:
hText.x = -1;
hText.y = 0.875;
break;
}
hText.a1 = 240; // Brightness
hText.a2 = 240;
hText.r1 = vecColor.x; // Color
hText.r2 = vecColor.x;
hText.g1 = vecColor.y;
hText.g2 = vecColor.y;
hText.b1 = vecColor.z;
hText.b2 = vecColor.z;
hText.channel = iChannel; // Channel
hText.effect = 0; //Just fade in fade out
hText.fadeinTime = vecTime.x;
hText.fadeoutTime = vecTime.z;
hText.holdTime = vecTime.y;
hText.fxTime = 0.5; //Does nothing in this case
UTIL_HudMessage(pEnt, hText, szText);
}

View File

@ -0,0 +1,44 @@
// ---------------------------------------------------------------
// 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.
//
// ---------------------------------------------------------------
// This contains the messaging functions for the spectator messages
// rune, and weapon info messages.
#ifndef BMOD_MESSAGING
#define BMOD_MESSAGING
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#define BMOD_CHAN_INFO 1
#define BMOD_CHAN_RUNE 2
#define BMOD_CHAN_COUNTDOWN 3
#define BMOD_CHAN_WEAPON 4
void PrintMessage( CBaseEntity *pEnt, int iChannel, Vector vecColor, Vector vecTime, char *msg);
#endif

View File

@ -0,0 +1,704 @@
// ---------------------------------------------------------------
// 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 "player.h"
#include "weapons.h"
#include "gamerules.h"
#include "BMOD_messaging.h"
#include "BMOD_CameraPoint.h"
#include "BMOD_player.h"
extern int gmsgCurWeapon;
extern int gmsgSetFOV;
extern int gmsgTeamInfo;
extern int gmsgSpectator;
extern void respawn(entvars_t *pev, BOOL fCopyCorpse);
extern cvar_t bm_spawnkilltime;
extern cvar_t bm_typekills;
extern cvar_t bm_bantime;
extern cvar_t bm_antispam;
extern cvar_t bm_spamlimit;
extern cvar_t bm_typecam;
// Player has become a spectator. Set it up.
// This was moved from player.cpp.
void CBasePlayer::StartObserver( Vector vecPosition, Vector vecViewAngle )
{
// ??
// clear any clientside entities attached to this player
MESSAGE_BEGIN( MSG_PAS, SVC_TEMPENTITY, pev->origin );
WRITE_BYTE( TE_KILLPLAYERATTACHMENTS );
WRITE_BYTE( (BYTE)entindex() );
MESSAGE_END();
// Holster weapon immediately, to allow it to cleanup
if (m_pActiveItem)
m_pActiveItem->Holster( );
// ?? Let go of tanks?
if ( m_pTank != NULL )
{
m_pTank->Use( this, this, USE_OFF, 0 );
m_pTank = NULL;
}
// clear out the suit message cache so we don't keep chattering
SetSuitUpdate(NULL, FALSE, 0);
// Tell Ammo Hud that the player is dead
MESSAGE_BEGIN( MSG_ONE, gmsgCurWeapon, NULL, pev );
WRITE_BYTE(0);
WRITE_BYTE(0XFF);
WRITE_BYTE(0xFF);
MESSAGE_END();
// reset FOV
m_iFOV = 0;
m_iClientFOV = -1;
pev->fov = m_iFOV;
SET_VIEW(edict(), edict());
MESSAGE_BEGIN( MSG_ONE, gmsgSetFOV, NULL, pev );
WRITE_BYTE(0);
MESSAGE_END();
// Setup flags
m_iHideHUD = (HIDEHUD_FLASHLIGHT | HIDEHUD_WEAPONS | HIDEHUD_HEALTH);
m_afPhysicsFlags |= PFLAG_OBSERVER;
pev->effects |= EF_NODRAW;
pev->view_ofs = g_vecZero;
pev->angles = pev->v_angle = vecViewAngle;
pev->fixangle = TRUE;
pev->solid = SOLID_NOT;
pev->takedamage = DAMAGE_NO;
pev->movetype = MOVETYPE_NOCLIP;
ClearBits( m_afPhysicsFlags, PFLAG_DUCKING );
ClearBits( pev->flags, FL_DUCKING );
pev->deadflag = DEAD_RESPAWNABLE;
pev->health = 1;
// Clear out the status bar
m_fInitHUD = TRUE;
// Update Team Status
// pev->team = 0;
// Remove all the player's stuff
// RemoveAllItems( FALSE );
// Move them to the new position
UTIL_SetOrigin( pev, vecPosition );
// Find a player to watch
Observer_SetMode(OBS_ROAMING);
// Tell all clients this player is now a spectator
//MESSAGE_BEGIN( MSG_ALL, gmsgSpectator );
// WRITE_BYTE( ENTINDEX( edict() ) );
// WRITE_BYTE( 1 );
//MESSAGE_END();
//MESSAGE_BEGIN( MSG_ALL, gmsgTeamInfo );
// WRITE_BYTE( ENTINDEX(edict()) );
// WRITE_STRING( "" );
//MESSAGE_END();
m_fMsgTimer = gpGlobals->time + .5;
m_bSentMsg = FALSE;
}
// Leave observer mode
void CBasePlayer::StopObserver( void )
{
// Turn off spectator
if ( pev->iuser1 || pev->iuser2 )
{
// Tell all clients this player is not a spectator anymore
//MESSAGE_BEGIN( MSG_ALL, gmsgSpectator );
// WRITE_BYTE( ENTINDEX( edict() ) );
// WRITE_BYTE( 0 );
//MESSAGE_END();
pev->iuser1 = pev->iuser2 = 0;
m_hObserverTarget = NULL;
m_iHideHUD = 0;
//MESSAGE_BEGIN( MSG_ALL, gmsgTeamInfo );
// WRITE_BYTE( ENTINDEX(edict()) );
// WRITE_STRING( m_szTeamName );
//MESSAGE_END();
}
}
// Find the next client in the game for this player to spectate
void CBasePlayer::Observer_FindNextPlayer( bool bReverse )
{
int iStart;
if ( m_hObserverTarget )
iStart = ENTINDEX( m_hObserverTarget->edict() );
else
iStart = ENTINDEX( edict() );
int iCurrent = iStart;
m_hObserverTarget = NULL;
int iDir = 1;
do
{
iCurrent += iDir;
// Loop through the clients
if (iCurrent > gpGlobals->maxClients)
iCurrent = 1;
if (iCurrent < 1)
iCurrent = gpGlobals->maxClients;
CBaseEntity *pEnt = UTIL_PlayerByIndex( iCurrent );
if ( !pEnt )
continue;
if ( pEnt == this )
continue;
// Don't spec observers or invisible players or defunct players
if ( ((CBasePlayer*)pEnt)->IsObserver()
|| (pEnt->pev->effects & EF_NODRAW)
|| (STRING(pEnt->pev->netname)[0] == 0)
|| (!((CBasePlayer*)pEnt)->m_bIsConnected)
)
continue;
// MOD AUTHORS: Add checks on target here.
m_hObserverTarget = pEnt;
break;
} while ( iCurrent != iStart );
// Did we find a target?
if ( m_hObserverTarget )
{
// Store the target in pev so the physics DLL can get to it
pev->iuser2 = ENTINDEX( m_hObserverTarget->edict() );
// Move to the target
UTIL_SetOrigin( pev, m_hObserverTarget->pev->origin );
// ClientPrint( pev, HUD_PRINTCENTER, UTIL_VarArgs ("Chase Camera: %s\n", STRING( m_hObserverTarget->pev->netname ) ) );
ALERT( at_console, "Now Tracking %s\n", STRING( m_hObserverTarget->pev->netname ) );
}
else
{
ALERT( at_console, "No observer targets.\n" );
}
}
// Handle buttons in observer mode
void CBasePlayer::Observer_HandleButtons()
{
// Slow down mouse clicks
if ( m_fMsgTimer <= gpGlobals->time )
{
// Show the observer mode instructions
if (!m_bSentMsg)
{
m_bSentMsg = TRUE;
PrintMessage( this, BMOD_CHAN_INFO, Vector (20,250,20), Vector (.5, 15, 2), "SPEC");
PrintMessage( this, BMOD_CHAN_RUNE, Vector (20,250,20), Vector (.5, 86400, 2),
"-Spectator Mode-\n FIRE=Spawn JUMP=Switch Modes ALT FIRE=Switch Targets");
}
// Check to see if the observer wants to spray their logo
if (pev->impulse == 201) {
ImpulseCommands();
}
// Jump changes modes: Chase to Roaming
if ( pev->button & IN_JUMP )
{
if ( pev->iuser1 == OBS_ROAMING )
Observer_SetMode( OBS_CHASE_FREE );
else
Observer_SetMode( OBS_ROAMING );
m_fMsgTimer = gpGlobals->time + 0.2;
}
// Attack2 cycles player targets
if ( pev->button & IN_ATTACK2 && pev->iuser1 != OBS_ROAMING )
{
Observer_FindNextPlayer( false );
m_fMsgTimer = gpGlobals->time + 0.2;
}
// Attack Spawns
// if ( m_afButtonPressed & IN_ATTACK && pev->iuser1 != OBS_ROAMING )
if ( pev->button & IN_ATTACK )
{
// g_engfuncs.pfnServerPrint( "Player spawned from Obs!\n" );
StopObserver();
m_fMsgTimer = gpGlobals->time + 0.2;
}
}
// clear attack/use commands from player
m_afButtonPressed = 0;
pev->button = 0;
m_afButtonReleased = 0;
pev->impulse = 0;
if ((m_hObserverTarget != NULL) && (m_hObserverTarget->IsPlayer()) && (pev->iuser1 == OBS_CHASE_FREE))
{
pev->origin = m_hObserverTarget->pev->origin;
pev->velocity = m_hObserverTarget->pev->velocity;
}
}
// Attempt to change the observer mode
void CBasePlayer::Observer_SetMode( int iMode )
{
// Just abort if we're changing to the mode we're already in
if ( iMode == pev->iuser1 )
return;
// Changing to Roaming?
if ( iMode == OBS_ROAMING )
{
// MOD AUTHORS: If you don't want to allow roaming observers at all in your mod, just abort here.
pev->iuser1 = OBS_ROAMING;
pev->iuser2 = 0;
m_hObserverTarget = NULL;
ClientPrint( pev, HUD_PRINTCENTER, "#Spec_Mode3" );
// pev->maxspeed = 320;
pev->maxspeed = 1000;
return;
}
// Changing to Chase Lock?
if ( iMode == OBS_CHASE_LOCKED )
{
// If changing from Roaming, or starting observing, make sure there is a target
if ( m_hObserverTarget == NULL )
Observer_FindNextPlayer( false );
if (m_hObserverTarget)
{
pev->iuser1 = OBS_CHASE_LOCKED;
pev->iuser2 = ENTINDEX( m_hObserverTarget->edict() );
ClientPrint( pev, HUD_PRINTCENTER, "#Spec_Mode1" );
pev->maxspeed = 0;
}
else
{
ClientPrint( pev, HUD_PRINTCENTER, "#Spec_NoTarget" );
Observer_SetMode(OBS_ROAMING);
}
return;
}
// Changing to Chase Freelook?
if ( iMode == OBS_CHASE_FREE )
{
// If changing from Roaming, or starting observing, make sure there is a target
// if ( m_hObserverTarget == NULL )
if ( pev->iuser1 == OBS_ROAMING )
Observer_FindNextPlayer( false );
if (m_hObserverTarget)
{
pev->iuser1 = OBS_CHASE_FREE;
pev->iuser2 = ENTINDEX( m_hObserverTarget->edict() );
// ClientPrint( pev, HUD_PRINTCENTER, "Chase-Camera Mode" );
pev->maxspeed = 0;
}
else
{
ClientPrint( pev, HUD_PRINTCENTER, "#Spec_NoTarget" );
Observer_SetMode(OBS_ROAMING);
}
return;
}
}
void CBasePlayer::BMOD_PreThink(void)
{
// Bubblemod freeze ray
if (m_flFreezeTime > 0)
{
if (m_flFreezeTime <= gpGlobals->time)
{
EnableControl(TRUE);
// pev->movetype = MOVETYPE_WALK;
pev->rendermode = kRenderNormal;
pev->renderfx = kRenderFxNone;
pev->renderamt = 0;
m_flFreezeTime = 0;
}
else
{
pev->v_angle = m_vFreezeAngle;
pev->fixangle = TRUE;
}
}
// Bubblemod spawn
if (
m_fSpawnTimeStamp &&
m_fSpawnTimeStamp + bm_spawnkilltime.value >= gpGlobals->time &&
m_iMessageFire
)
{
PrintMessage( this, BMOD_CHAN_INFO, Vector (255,0,0), Vector (.1, bm_spawnkilltime.value, .1),
UTIL_VarArgs("Spawn Protection: %d seconds", (int)(m_fSpawnTimeStamp + bm_spawnkilltime.value - gpGlobals->time))
);
}
if (m_fSpawnTimeStamp > 0 &&
((m_fSpawnTimeStamp + bm_spawnkilltime.value) <= gpGlobals->time) ) {
if (m_RuneFlags == RUNE_NONE &&
m_flFreezeTime == 0) {
pev->rendermode = kRenderNormal;
pev->renderfx = kRenderFxNone;
pev->renderamt = 0;
}
BMOD_ResetSpawnKill();
}
// Bubblemod runes
if (m_RuneFlags && (m_RuneTime < gpGlobals->time) )
{
m_RuneFlags = RUNE_NONE;
pev->rendermode = kRenderNormal;
pev->renderfx = kRenderFxNone;
pev->renderamt = 0;
}
// BubbleMod Type detection
if (pev->button & ~IN_SCORE ) {
BMOD_ResetTypeKill();
}
// Color the typer
if (BMOD_IsTyping() &&
m_iMessageFire ) {
if (!(m_iMessageCounter % 2)) {
//MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, pev->origin );
// WRITE_BYTE( TE_SMOKE );
// WRITE_COORD( pev->origin.x );
// WRITE_COORD( pev->origin.y );
// WRITE_COORD( pev->origin.z - 36 );
// WRITE_SHORT( g_sModelIndexSmoke );
// WRITE_BYTE( 10 ); // scale * 10
// WRITE_BYTE( 10 ); // framerate
//MESSAGE_END();
MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, pev->origin );
WRITE_BYTE( TE_SPRITE );
WRITE_COORD( pev->origin.x + RANDOM_LONG( -10, 10) );
WRITE_COORD( pev->origin.y + RANDOM_LONG( -10, 10) );
WRITE_COORD( pev->origin.z + RANDOM_LONG( -30, 30) );
WRITE_SHORT( g_sModelIndexFlare );
WRITE_BYTE( 3 ); // scale * 10
WRITE_BYTE( 255 ); // alpha
MESSAGE_END();
}
float fCos = cos( gpGlobals->time * 4.00) * 8;
float fSin = sin( gpGlobals->time * 4.00) * 8;
MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, pev->origin );
WRITE_BYTE( TE_BUBBLES );
WRITE_COORD( pev->origin.x + fCos);
WRITE_COORD( pev->origin.y + fSin);
WRITE_COORD( pev->origin.z - 36 );
WRITE_COORD( pev->origin.x + fCos); // mins
WRITE_COORD( pev->origin.y + fSin);
WRITE_COORD( pev->origin.z - 36 );
WRITE_COORD( 75 ); // height
WRITE_SHORT( g_sModelIndexBubbles );
WRITE_BYTE( 3 ); // count
WRITE_COORD( -1 ); // speed
MESSAGE_END();
// Away put your weapons!
//if (m_pActiveItem) {
// ResetAutoaim( );
// m_pActiveItem->Holster( );
// m_pActiveItem = NULL;
//}
m_pLastItem = m_pActiveItem;
if (!m_bTypeMode) {
m_bTypeMode = TRUE;
// EnableControl(FALSE);
if (bm_typecam.value) {
// spawn a camera above us and use that for our view.
CCamPoint *pCam = (CCamPoint*)CBaseEntity::Create( "campoint",
pev->origin + Vector(0,0,40),
Vector(pev->angles.x + 22, pev->angles.y + 180, 0),
edict() );
if (pCam) {
pCam->m_pOwner = this;
pCam->Think();
// UTIL_ClientPrintAll( HUD_PRINTTALK, "<SERVER> Camera point created.\n");
SET_VIEW(edict(), pCam->edict());
SET_MODEL(ENT(pCam->pev), STRING(pev->model) );
pev->fov = m_iFOV = 140;
}
}
}
}
}
void CBasePlayer::BMOD_Think( void )
{
// BMOD End - Message delayer.
// Message delayer. USE THIS for general messages to players.
// counts tenths of seconds.
if (m_fMessageTimer < gpGlobals->time)
{
m_fMessageTimer = gpGlobals->time + .1;
m_iMessageCounter++;
m_iMessageFire = TRUE;
}
// Locator
if (m_LocateMode && m_iMessageFire) {
int yang = (int)pev->angles.y;
if (yang < 0)
yang += 360;
ClientPrint( pev, HUD_PRINTCENTER, UTIL_VarArgs ("Location: %dx %dy %dz, facing %d",
(int)pev->origin.x,
(int)pev->origin.y,
(int)pev->origin.z,
yang
) );
}
// Llamas!
if (m_IsLlama && m_iMessageFire && !(m_iMessageCounter%5)) {
CLIENT_COMMAND(edict(), "drop\n");
}
// Autoban
if (m_bBanMe && m_iMessageFire)
{
char cmd[81] = "";
sprintf( cmd, "banid %d %s kick\n", (int)bm_bantime.value, GETPLAYERAUTHID( edict() ));
SERVER_COMMAND(cmd);
}
// BMOD Begin - Spam Kick
if (m_iMessageFire && !(m_iMessageCounter%10) && m_iSpamSay)
{
m_iSpamSay--;
}
if (bm_antispam.value && m_iSpamSay > bm_spamlimit.value)
{
char cmd[81] = "";
sprintf( cmd, "kick # %u\n", GETPLAYERUSERID( edict() ));
SERVER_COMMAND(cmd);
UTIL_ClientPrintAll( HUD_PRINTTALK, UTIL_VarArgs( "<SERVER> %s was kicked for spamming.\n",
STRING( pev->netname )));
UTIL_LogPrintf( "\"SERVER<-1><-1><>\" say \"%s was was kicked for spamming.\"\n",
STRING( pev->netname ));
UTIL_LogPrintf( "// \"%s<%i><%s><%s>\" was kicked for spamming.\n",
STRING( pev->netname ),
GETPLAYERUSERID( edict() ),
GETPLAYERAUTHID( edict() ),
g_engfuncs.pfnInfoKeyValue( g_engfuncs.pfnGetInfoKeyBuffer( edict() ), "model" )
);
m_iSpamSay = 0;
}
// BMOD End - Spam Kick
}
void CBasePlayer::BMOD_PostThink( void )
{
}
void CBasePlayer::BMOD_Identify( void )
{
static float timer = gpGlobals->time;
static CBasePlayer *LastIdentPlayer = NULL;
TraceResult tr;
CBasePlayer *pPlayer = GetClassPtr((CBasePlayer *)pev);
Vector anglesAim = pPlayer->pev->v_angle;
UTIL_MakeVectors( anglesAim );
anglesAim.x = -anglesAim.x;
Vector vecSrc = pPlayer->GetGunPosition( ) - gpGlobals->v_up * 1;
Vector vecDir = gpGlobals->v_forward;
gpGlobals->trace_flags = FTRACE_SIMPLEBOX;
UTIL_TraceLine(vecSrc, vecSrc + vecDir * 8192, dont_ignore_monsters, ENT(pPlayer->pev), &tr);
CBaseEntity *pOther = CBaseEntity::Instance( tr.pHit );
// Do we have our nose in a wall?
if (((tr.vecEndPos - vecSrc).Length() > 40) || pOther->IsPlayer()) {
BMOD_ResetTypeKill();
}
if ( pOther->IsPlayer() &&
(
(CBasePlayer *)pOther != LastIdentPlayer ||
timer <= gpGlobals->time
)
)
{
char szExtra[81] = "\n";
if (((CBasePlayer *)pOther)->BMOD_IsASpawn()) {
strcat(szExtra, "\nFresh Spawn! DO NOT SHOOT!");
}
if (((CBasePlayer *)pOther)->BMOD_IsTyping()) {
strcat(szExtra, "\nTyping! DO NOT SHOOT!");
}
CBasePlayer *pPlayer = (CBasePlayer *)pOther;
if (IsObserver())
ClientPrint( pev, HUD_PRINTCENTER, UTIL_VarArgs ("-%s-\n(%s) %i / %i%s",
STRING( pPlayer->pev->netname ),
g_engfuncs.pfnInfoKeyValue( g_engfuncs.pfnGetInfoKeyBuffer( pPlayer->edict() ), "model" ),
(int)pPlayer->pev->health,
(int)pPlayer->pev->armorvalue,
szExtra
) );
else if ( g_pGameRules->PlayerRelationship( pOther, this ) == GR_TEAMMATE )
ClientPrint( pev, HUD_PRINTCENTER, UTIL_VarArgs ("-%s-\n%i / %i",
STRING( pPlayer->pev->netname ),
(int)pPlayer->pev->health,
(int)pPlayer->pev->armorvalue)
);
else
ClientPrint( pev, HUD_PRINTCENTER, UTIL_VarArgs ("-%s-\n(%s)%s",
STRING( pPlayer->pev->netname ),
g_engfuncs.pfnInfoKeyValue( g_engfuncs.pfnGetInfoKeyBuffer( pPlayer->edict() ), "model" ),
szExtra
) );
timer = gpGlobals->time + .5;
LastIdentPlayer = (CBasePlayer *)pOther;
}
else if (!pOther->IsPlayer()) {
LastIdentPlayer = NULL;
}
}
int CBasePlayer::BMOD_WasSpawnKilled( void )
{
if ( !IsAlive() &&
m_fSpawnTimeStamp &&
((m_fSpawnTimeStamp + bm_spawnkilltime.value) > gpGlobals->time) &&
bm_spawnkilltime.value)
return TRUE;
return FALSE;
}
int CBasePlayer::BMOD_IsASpawn( void )
{
if ( IsAlive() &&
m_fSpawnTimeStamp &&
((m_fSpawnTimeStamp + bm_spawnkilltime.value) > gpGlobals->time) &&
bm_spawnkilltime.value)
return TRUE;
return FALSE;
}
void CBasePlayer::BMOD_ResetSpawnKill( void )
{
if (m_RuneFlags == RUNE_NONE &&
m_flFreezeTime == 0) {
pev->rendermode = kRenderNormal;
pev->renderfx = kRenderFxNone;
pev->renderamt = 0;
}
m_fSpawnTimeStamp = 0;
PrintMessage( this, BMOD_CHAN_INFO, Vector (20,250,20), Vector (.1, 1, .1), "");
}
int CBasePlayer::BMOD_WasTypeKilled( void )
{
if ( !IsAlive() &&
m_flTypeKillStamp > 0 &&
m_flTypeKillStamp < gpGlobals->time &&
!bm_typekills.value )
return TRUE;
return FALSE;
}
int CBasePlayer::BMOD_IsTyping( void )
{
if ( IsAlive() &&
m_flTypeKillStamp &&
m_flTypeKillStamp < gpGlobals->time &&
!bm_typekills.value ) {
// Do we have a crowbar?
if (m_pActiveItem != NULL &&
strcmp("weapon_crowbar", STRING(m_pActiveItem->pev->classname))
)
{
BMOD_ResetTypeKill();
return FALSE;
}
return TRUE;
}
return FALSE;
}
void CBasePlayer::BMOD_ResetTypeKill( void )
{
if ( IsAlive() ) {
// make a sound if we are coming out of type mode.
if (m_bTypeMode)
{
EMIT_SOUND(ENT(pev), CHAN_VOICE, "fvox/alert.wav", 1.0, ATTN_NORM);
SET_VIEW(edict(), edict());
pev->fov = m_iFOV = 0;
}
m_bTypeMode = FALSE;
// EnableControl(TRUE);
m_flTypeKillStamp = gpGlobals->time + 4;
}
return;
}

View File

@ -0,0 +1,53 @@
// ---------------------------------------------------------------
// 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.
//
// ---------------------------------------------------------------
#ifndef BMOD_PLAYER_H
#define BMOD_PLAYER_H
#define OBS_CHASE_LOCKED 1
#define OBS_CHASE_FREE 2
#define OBS_ROAMING 3
/*
typedef enum
{
RUNE_NONE,
RUNE_CROWBAR,
RUNE_GRENADE,
RUNE_357,
RUNE_HEALTH,
RUNE_BATTERY,
RUNE_SHOTGUN,
} RUNE_FLAGS;
*/
#define RUNE_NONE 0
#define RUNE_CROWBAR (1<<0)
#define RUNE_GRENADE (1<<1)
#define RUNE_357 (1<<2)
#define RUNE_HEALTH (1<<3)
#define RUNE_BATTERY (1<<4)
#define RUNE_SHOTGUN (1<<5)
#endif

View File

@ -0,0 +1,444 @@
// ---------------------------------------------------------------
// 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 );

View File

@ -0,0 +1,49 @@
// ---------------------------------------------------------------
// 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.
//
// ---------------------------------------------------------------
// Runes
#ifndef RUNE_H
#define RUNE_H
class CRune : public CBaseEntity
{
public:
void Spawn( void );
void Precache(void);
CBaseEntity* Respawn( void );
void EXPORT RuneTouch( CBaseEntity *pOther );
void EXPORT Materialize( void );
void EXPORT MaterializeRandom( void );
virtual BOOL MyTouch( CBasePlayer *pPlayer ) { EMIT_SOUND( pPlayer->edict(), CHAN_ITEM, "items/gunpickup2.wav", 1, ATTN_NORM ); return TRUE; };
BOOL IsRune( void ) { return TRUE; }
virtual char* RuneName ( void ) { return "Generic Rune"; }
BOOL m_randomize;
Vector m_vRuneColor;
};
#endif // RUNE_H

View File

@ -0,0 +1,524 @@
// ---------------------------------------------------------------
// 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.
//
// ---------------------------------------------------------------
// Snark Mines
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "monsters.h"
#include "weapons.h"
#include "nodes.h"
#include "player.h"
#include "effects.h"
#include "gamerules.h"
#include "BMOD_snarkmine.h"
#define TRIPMINE_PRIMARY_VOLUME 450
#define TRIPSNARK_FLARE "sprites/xspark3.spr"
extern cvar_t bm_spawnmines;
enum tripmine_e {
TRIPMINE_IDLE1 = 0,
TRIPMINE_IDLE2,
TRIPMINE_ARM1,
TRIPMINE_ARM2,
TRIPMINE_FIDGET,
TRIPMINE_HOLSTER,
TRIPMINE_DRAW,
TRIPMINE_WORLD,
TRIPMINE_GROUND,
};
LINK_ENTITY_TO_CLASS( monster_tripsnark, CTripSnarkGrenade );
TYPEDESCRIPTION CTripSnarkGrenade::m_SaveData[] =
{
DEFINE_FIELD( CTripSnarkGrenade, m_flPowerUp, FIELD_TIME ),
DEFINE_FIELD( CTripSnarkGrenade, m_vecDir, FIELD_VECTOR ),
DEFINE_FIELD( CTripSnarkGrenade, m_vecEnd, FIELD_POSITION_VECTOR ),
DEFINE_FIELD( CTripSnarkGrenade, m_flBeamLength, FIELD_FLOAT ),
DEFINE_FIELD( CTripSnarkGrenade, m_hOwner, FIELD_EHANDLE ),
DEFINE_FIELD( CTripSnarkGrenade, m_pBeam, FIELD_CLASSPTR ),
DEFINE_FIELD( CTripSnarkGrenade, m_posOwner, FIELD_POSITION_VECTOR ),
DEFINE_FIELD( CTripSnarkGrenade, m_angleOwner, FIELD_VECTOR ),
DEFINE_FIELD( CTripSnarkGrenade, m_pRealOwner, FIELD_EDICT ),
};
IMPLEMENT_SAVERESTORE(CTripSnarkGrenade,CGrenade);
void CTripSnarkGrenade :: Spawn( void )
{
Precache( );
// motor
pev->movetype = MOVETYPE_FLY;
pev->solid = SOLID_NOT;
SET_MODEL(ENT(pev), "models/v_tripmine.mdl");
pev->frame = 0;
pev->body = 3;
pev->sequence = TRIPMINE_WORLD;
ResetSequenceInfo( );
pev->framerate = 0;
UTIL_SetSize(pev, Vector( -8, -8, -8), Vector(8, 8, 8));
UTIL_SetOrigin( pev, pev->origin );
if (pev->spawnflags & 1)
{
// power up quickly
m_flPowerUp = gpGlobals->time + 1.0;
}
else
{
// power up in 2.5 seconds
m_flPowerUp = gpGlobals->time + 2.5;
}
SetThink( PowerupThink );
pev->nextthink = gpGlobals->time + 0.2;
pev->takedamage = DAMAGE_YES;
// pev->dmg = gSkillData.plrDmgTripmine;
pev->health = 1; // don't let die normally
if (pev->owner != NULL)
{
// play deploy sound
EMIT_SOUND( ENT(pev), CHAN_VOICE, "weapons/mine_deploy.wav", 1.0, ATTN_NORM );
EMIT_SOUND( ENT(pev), CHAN_BODY, "weapons/mine_charge.wav", 0.2, ATTN_NORM ); // chargeup
m_pRealOwner = pev->owner;// see CTripSnarkGrenade for why.
}
UTIL_MakeAimVectors( pev->angles );
m_vecDir = gpGlobals->v_forward;
m_vecEnd = pev->origin + m_vecDir * 2048;
}
void CTripSnarkGrenade :: Precache( void )
{
PRECACHE_MODEL("models/v_tripmine.mdl");
PRECACHE_SOUND("weapons/mine_deploy.wav");
PRECACHE_SOUND("squeek/sqk_deploy1.wav");
PRECACHE_SOUND("weapons/mine_charge.wav");
PRECACHE_SOUND("debris/beamstart2.wav");
PRECACHE_MODEL( TRIPSNARK_FLARE );
m_LaserSprite = PRECACHE_MODEL( "sprites/laserbeam.spr" );
}
void CTripSnarkGrenade :: WarningThink( void )
{
// play warning sound
// EMIT_SOUND( ENT(pev), CHAN_VOICE, "buttons/Blip2.wav", 1.0, ATTN_NORM );
// set to power up
SetThink( PowerupThink );
pev->nextthink = gpGlobals->time + 1.0;
}
void CTripSnarkGrenade :: PowerupThink( void )
{
TraceResult tr;
if (m_hOwner == NULL)
{
// find an owner
edict_t *oldowner = pev->owner;
pev->owner = NULL;
UTIL_TraceLine( pev->origin + m_vecDir * 8, pev->origin - m_vecDir * 32, dont_ignore_monsters, ENT( pev ), &tr );
if (tr.fStartSolid || (oldowner && tr.pHit == oldowner))
{
pev->owner = oldowner;
m_flPowerUp += 0.1;
pev->nextthink = gpGlobals->time + 0.1;
return;
}
if (tr.flFraction < 1.0)
{
pev->owner = tr.pHit;
m_hOwner = CBaseEntity::Instance( pev->owner );
m_posOwner = m_hOwner->pev->origin;
m_angleOwner = m_hOwner->pev->angles;
}
else
{
STOP_SOUND( ENT(pev), CHAN_VOICE, "weapons/mine_deploy.wav" );
STOP_SOUND( ENT(pev), CHAN_BODY, "weapons/mine_charge.wav" );
SetThink( SUB_Remove );
pev->nextthink = gpGlobals->time + 0.1;
ALERT( at_console, "WARNING:Tripmine at %.0f, %.0f, %.0f removed\n", pev->origin.x, pev->origin.y, pev->origin.z );
KillBeam();
return;
}
}
else if (m_posOwner != m_hOwner->pev->origin || m_angleOwner != m_hOwner->pev->angles)
{
// disable
STOP_SOUND( ENT(pev), CHAN_VOICE, "weapons/mine_deploy.wav" );
STOP_SOUND( ENT(pev), CHAN_BODY, "weapons/mine_charge.wav" );
CBaseEntity *pMine = Create( "weapon_snark", pev->origin + m_vecDir * 24, pev->angles );
pMine->pev->spawnflags |= SF_NORESPAWN;
SetThink( SUB_Remove );
KillBeam();
pev->nextthink = gpGlobals->time + 0.1;
return;
/*
// Just detonate
pev->owner = m_pRealOwner;
pev->health = 0;
Killed( VARS( pev->owner ), GIB_NORMAL );
return;
*/
}
// ALERT( at_console, "%d %.0f %.0f %0.f\n", pev->owner, m_pOwner->pev->origin.x, m_pOwner->pev->origin.y, m_pOwner->pev->origin.z );
if (gpGlobals->time > m_flPowerUp)
{
// make solid
pev->solid = SOLID_BBOX;
UTIL_SetOrigin( pev, pev->origin );
MakeBeam( );
// play enabled sound
EMIT_SOUND_DYN( ENT(pev), CHAN_VOICE, "squeek/sqk_deploy1.wav", 0.5, ATTN_NORM, 1.0, 75 );
}
pev->nextthink = gpGlobals->time + 0.1;
}
void CTripSnarkGrenade :: KillBeam( void )
{
if ( m_pBeam )
{
UTIL_Remove( m_pBeam );
m_pBeam = NULL;
}
}
void CTripSnarkGrenade :: MakeBeam( void )
{
TraceResult tr;
// ALERT( at_console, "serverflags %f\n", gpGlobals->serverflags );
UTIL_TraceLine( pev->origin, m_vecEnd, dont_ignore_monsters, ENT( pev ), &tr );
m_flBeamLength = tr.flFraction;
// set to follow laser spot
SetThink( BeamBreakThink );
pev->nextthink = gpGlobals->time + 0.1;
Vector vecTmpEnd = pev->origin + m_vecDir * 2048 * m_flBeamLength;
m_pBeam = CBeam::BeamCreate( g_pModelNameLaser, 10 );
m_pBeam->PointEntInit( vecTmpEnd, entindex() );
m_pBeam->SetColor( 255, 20, 20 );
m_pBeam->SetScrollRate( 255 );
m_pBeam->SetBrightness( 40 );
if (IsSpawnMine())
{
pev->owner = m_pRealOwner;
pev->health = 0;
Killed( VARS( pev->owner ), GIB_NORMAL );
UTIL_SpeakBadWeapon();
UTIL_ClientPrintAll( HUD_PRINTTALK, UTIL_VarArgs( "%s tried to place a spawn snark mine!\n",
STRING( VARS( pev->owner )->netname ) ) );
}
}
void CTripSnarkGrenade :: BeamBreakThink( void )
{
BOOL bBlowup = 0;
TraceResult tr;
// HACKHACK Set simple box using this really nice global!
gpGlobals->trace_flags = FTRACE_SIMPLEBOX;
UTIL_TraceLine( pev->origin, m_vecEnd, dont_ignore_monsters, ENT( pev ), &tr );
// ALERT( at_console, "%f : %f\n", tr.flFraction, m_flBeamLength );
// respawn detect.
if ( !m_pBeam )
{
MakeBeam( );
if ( tr.pHit )
m_hOwner = CBaseEntity::Instance( tr.pHit ); // reset owner too
}
if (fabs( m_flBeamLength - tr.flFraction ) > 0.001)
{
bBlowup = 1;
}
else
{
if (m_hOwner == NULL)
bBlowup = 1;
else if (m_posOwner != m_hOwner->pev->origin)
bBlowup = 1;
else if (m_angleOwner != m_hOwner->pev->angles)
bBlowup = 1;
}
if (bBlowup)
{
// a bit of a hack, but all CGrenade code passes pev->owner along to make sure the proper player gets credit for the kill
// so we have to restore pev->owner from pRealOwner, because an entity's tracelines don't strike it's pev->owner which meant
// that a player couldn't trigger his own tripmine. Now that the mine is exploding, it's safe the restore the owner so the
// CGrenade code knows who the explosive really belongs to.
pev->owner = m_pRealOwner;
pev->health = 0;
Killed( VARS( pev->owner ), GIB_NORMAL );
return;
}
pev->nextthink = gpGlobals->time + 0.1;
}
int CTripSnarkGrenade :: TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType )
{
if (gpGlobals->time < m_flPowerUp && flDamage < pev->health)
{
// disable
// Create( "weapon_tripsnark", pev->origin + m_vecDir * 24, pev->angles );
SetThink( SUB_Remove );
pev->nextthink = gpGlobals->time + 0.1;
KillBeam();
return FALSE;
}
return CGrenade::TakeDamage( pevInflictor, pevAttacker, flDamage, bitsDamageType );
}
void CTripSnarkGrenade::Killed( entvars_t *pevAttacker, int iGib )
{
pev->takedamage = DAMAGE_NO;
if ( pevAttacker && ( pevAttacker->flags & FL_CLIENT ) )
{
// some client has destroyed this mine, he'll get credit for any kills
pev->owner = ENT( pevAttacker );
}
SetThink( DelayDeathThink );
pev->nextthink = gpGlobals->time + RANDOM_FLOAT( 0.1, 0.3 );
EMIT_SOUND( ENT(pev), CHAN_BODY, "common/null.wav", 0.5, ATTN_NORM ); // shut off chargeup
}
void CTripSnarkGrenade::Explode( TraceResult *pTrace )
{
// Make mine invisible
pev->model = iStringNull;//invisible
pev->solid = SOLID_NOT;// intangible
pev->effects |= EF_NODRAW;
pev->takedamage = DAMAGE_NO;
// Pull out of the wall a bit
if ( pTrace->flFraction != 1.0 )
{
pev->origin = pTrace->vecEndPos + (pTrace->vecPlaneNormal * 20);
}
// Make teleport sound effect
EMIT_SOUND( ENT(pev), CHAN_BODY, "debris/beamstart2.wav", 0.5, ATTN_NORM );
// Create Animated Sprite
m_pSprite = CSprite::SpriteCreate( TRIPSNARK_FLARE, pev->origin, TRUE );
m_pSprite->Animate( 1 );
m_pSprite->pev->scale = 1.4;
m_pSprite->SetTransparency( kRenderGlow, 255, 255, 255, 255, kRenderFxNoDissipation );
m_pSprite->pev->spawnflags |= SF_SPRITE_TEMPORARY;
// Spawn snarks
CBaseEntity *pSqueak = CBaseEntity::Create( "monster_snark", pev->origin, m_vecDir , pev->owner );
pSqueak->pev->velocity = m_vecDir * 200;
pSqueak = CBaseEntity::Create( "monster_snark", pev->origin + Vector(8, 8, 0), m_vecDir , pev->owner );
pSqueak->pev->velocity = m_vecDir * 200;
pSqueak = CBaseEntity::Create( "monster_snark", pev->origin + Vector(-8, 8, 0), m_vecDir , pev->owner );
pSqueak->pev->velocity = m_vecDir * 200;
pSqueak = CBaseEntity::Create( "monster_snark", pev->origin + Vector(8, -8, 0), m_vecDir , pev->owner );
pSqueak->pev->velocity = m_vecDir * 200;
pSqueak = CBaseEntity::Create( "monster_snark", pev->origin + Vector(-8, -8, 0), m_vecDir , pev->owner );
pSqueak->pev->velocity = m_vecDir * 200;
// Tell the mine what do do for the next little while.
SetThink( RiftThink );
pev->nextthink = gpGlobals->time + 0.1;
m_RiftTime = gpGlobals->time + 3;
}
void CTripSnarkGrenade::RiftThink( void )
{
// Setup next think time
pev->nextthink = gpGlobals->time + 0.1;
// Make a lightning strike
Vector vecEnd;
TraceResult tr;
vecEnd.x = RANDOM_FLOAT(-1.0,1.0); // Pick a random direction
vecEnd.y = RANDOM_FLOAT(-1.0,1.0);
vecEnd.z = RANDOM_FLOAT(-1.0,1.0);
// vecEnd = vecEnd.Normalize();
vecEnd = pev->origin + vecEnd.Normalize() * 128;
UTIL_TraceLine( pev->origin, vecEnd, ignore_monsters, ENT(pev), &tr);
MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY );
WRITE_BYTE( TE_BEAMPOINTS );
WRITE_COORD(pev->origin.x);
WRITE_COORD(pev->origin.y);
WRITE_COORD(pev->origin.z);
WRITE_COORD( tr.vecEndPos.x );
WRITE_COORD( tr.vecEndPos.y );
WRITE_COORD( tr.vecEndPos.z );
WRITE_SHORT( m_LaserSprite );
WRITE_BYTE( 0 ); // Starting frame
WRITE_BYTE( 0 ); // framerate * 0.1
WRITE_BYTE( 5 ); // life * 0.1
WRITE_BYTE( 3 ); // width
WRITE_BYTE( 64 ); // noise
WRITE_BYTE( 10 ); // color r,g,b
WRITE_BYTE( 200 ); // color r,g,b
WRITE_BYTE( 255 ); // color r,g,b
WRITE_BYTE( 255 ); // brightness
WRITE_BYTE( 0 ); // scroll speed
MESSAGE_END();
// Animate Sprite
m_pSprite->Animate(1);
// Check to see if the rift should fade away
if (m_RiftTime <= gpGlobals->time) {
m_pSprite->Expand( 10, 500 );
m_pSprite = NULL;
UTIL_Remove( this );
}
}
void CTripSnarkGrenade::DelayDeathThink( void )
{
KillBeam();
TraceResult tr;
UTIL_TraceLine ( pev->origin + m_vecDir * 8, pev->origin - m_vecDir * 64, dont_ignore_monsters, ENT(pev), & tr);
Explode( &tr );
}
BOOL CTripSnarkGrenade::IsSpawnMine()
{
if (bm_spawnmines.value)
return FALSE;
BOOL result = FALSE;
CBaseEntity *pEntity = NULL;
TraceResult tr;
Vector vecSpot, vecTop;
Vector vecSrc = pev->origin;
float flRadius = 375;
int bInWater = (UTIL_PointContents ( vecSrc ) == CONTENTS_WATER);
vecSrc.z += 1;// in case grenade is lying on the ground
// iterate on all entities in the vicinity.
while ((pEntity = UTIL_FindEntityInSphere( pEntity, vecSrc, flRadius )) != NULL)
{
// Only look for deathmatch spawn points
if ( FClassnameIs( pEntity->pev, "info_player_deathmatch" ) )
{
// blast's don't tavel into or out of water,
// so ignore spawn points that lie on the other side.
if (bInWater && pEntity->pev->waterlevel == 0)
continue;
if (!bInWater && pEntity->pev->waterlevel == 3)
continue;
// Trace a small line from the trip out to the potential damage radius.
UTIL_TraceLine ( vecSrc, vecSrc + m_vecDir * flRadius, ignore_monsters, ENT(pev), &tr );
vecSpot = tr.vecEndPos;
UTIL_TraceLine( pEntity->pev->origin, pEntity->pev->origin - Vector(0,0,1024), ignore_monsters, ENT(pev), &tr);
Vector vecTop = pEntity->pev->origin + Vector(0,0,36);
float height = fabs(vecTop.z - tr.vecEndPos.z) / 2;
if (UTIL_OBB_LineTest(vecSrc, vecSpot, Vector(vecTop.x, vecTop.y, (vecTop.z + tr.vecEndPos.z) / 2), Vector(16,16,height) ))
result = TRUE;
}
}
return result;
}
void CTripSnarkGrenade::Deactivate( void )
{
pev->solid = SOLID_NOT;
KillBeam();
UTIL_Remove( this );
}
//=========================================================
// DeactivateSnarkTrips - removes all snark trips owned by
// the provided player.
//
// Made this global on purpose.
//=========================================================
void DeactivateSnarkTrips( CBasePlayer *pOwner )
{
edict_t *pFind;
pFind = FIND_ENTITY_BY_CLASSNAME( NULL, "monster_tripsnark" );
while ( !FNullEnt( pFind ) )
{
CBaseEntity *pEnt = CBaseEntity::Instance( pFind );
CTripSnarkGrenade *pTrip = (CTripSnarkGrenade *)pEnt;
if ( pTrip )
{
if ( pTrip->Owner() == pOwner->edict() )
{
pTrip->Deactivate();
}
}
pFind = FIND_ENTITY_BY_CLASSNAME( pFind, "monster_tripsnark" );
}
}

View File

@ -0,0 +1,84 @@
// ---------------------------------------------------------------
// 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.
//
// ---------------------------------------------------------------
// Snark Mines
#ifndef SNARKMINE_H
#define SNARKMINE_H
#include "extdll.h"
#include "monsters.h"
#include "weapons.h"
#include "nodes.h"
#include "player.h"
#include "effects.h"
class CTripSnarkGrenade : public CGrenade
{
void Spawn( void );
void Precache( void );
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
int TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType );
void EXPORT WarningThink( void );
void EXPORT PowerupThink( void );
void EXPORT BeamBreakThink( void );
void EXPORT DelayDeathThink( void );
void EXPORT RiftThink( void );
void Killed( entvars_t *pevAttacker, int iGib );
void Explode( TraceResult *pTrace );
void MakeBeam( void );
void KillBeam( void );
BOOL IsSpawnMine( void );
float m_flPowerUp;
Vector m_vecDir;
Vector m_vecEnd;
float m_flBeamLength;
EHANDLE m_hOwner;
CBeam *m_pBeam;
Vector m_posOwner;
Vector m_angleOwner;
edict_t *m_pRealOwner;// tracelines don't hit PEV->OWNER, which means a player couldn't detonate his own trip mine, so we store the owner here.
private:
int m_RiftTime;
CSprite *m_pSprite;
short m_LaserSprite;
public:
void Deactivate( void );
edict_t *Owner( void ) { return m_pRealOwner; };
};
#endif

View File

@ -0,0 +1,153 @@
// ---------------------------------------------------------------
// 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.
//
// ---------------------------------------------------------------
// Extra Snark Functions
#include "squeakgrenade.h"
#include "BMOD_snarkmine.h"
extern cvar_t bm_snarks_mod;
void CSqueak::SecondaryAttack( void )
{
if (!bm_snarks_mod.value || m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] < 5)
return;
UTIL_MakeVectors( m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle );
Vector vecSrc = m_pPlayer->GetGunPosition( );
Vector vecAiming = gpGlobals->v_forward;
TraceResult tr;
UTIL_TraceLine( vecSrc, vecSrc + vecAiming * 128, dont_ignore_monsters, ENT( m_pPlayer->pev ), &tr );
if (tr.flFraction < 1.0)
{
// ALERT( at_console, "hit %f\n", tr.flFraction );
CBaseEntity *pEntity = CBaseEntity::Instance( tr.pHit );
if (pEntity && !(pEntity->pev->flags & FL_CONVEYOR))
{
Vector angles = UTIL_VecToAngles( tr.vecPlaneNormal );
CBaseEntity *pEnt = CBaseEntity::Create( "monster_tripsnark", tr.vecEndPos + tr.vecPlaneNormal * 8, angles, m_pPlayer->edict() );
CTripSnarkGrenade *pMine = (CTripSnarkGrenade *)pEnt;
m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] -= 5;
// player "shoot" animation
m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
if (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] > 0)
{
SendWeaponAnim( SQUEAK_UP );
}
else
{
// no more mines!
RetireWeapon();
return;
}
}
else
{
// ALERT( at_console, "no deploy\n" );
}
}
else
{
}
m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.3;
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + RANDOM_FLOAT ( 10, 15 );
}
//=========================================================
// BestVisibleEnemy - this functions searches the link
// list whose head is the caller's m_pLink field, and returns
// a pointer to the enemy entity in that list that is nearest the
// caller.
//
// !!!UNDONE - currently, this only returns the closest enemy.
// we'll want to consider distance, relationship, attack types, back turned, etc.
//=========================================================
CBaseEntity *CSqueakGrenade :: BMOD_BestVisibleEnemy ( void )
{
CBaseEntity *pReturn;
CBaseEntity *pNextEnt;
BOOL typer;
int iNearest;
int iDist;
int iBestRelationship;
iNearest = 8192;// so first visible entity will become the closest.
pNextEnt = m_pLink;
pReturn = NULL;
typer = 0;
iBestRelationship = R_NO;
while ( pNextEnt != NULL )
{
if (pNextEnt->IsPlayer()) {
typer = ((CBasePlayer*)pNextEnt)->BMOD_IsTyping();
}
else {
typer = 0;
}
if ( pNextEnt->IsAlive() && !typer)
{
if ( IRelationship( pNextEnt) > iBestRelationship )
{
// this entity is disliked MORE than the entity that we
// currently think is the best visible enemy. No need to do
// a distance check, just get mad at this one for now.
iBestRelationship = IRelationship ( pNextEnt );
iNearest = ( pNextEnt->pev->origin - pev->origin ).Length();
pReturn = pNextEnt;
}
else if ( IRelationship( pNextEnt) == iBestRelationship )
{
// this entity is disliked just as much as the entity that
// we currently think is the best visible enemy, so we only
// get mad at it if it is closer.
iDist = ( pNextEnt->pev->origin - pev->origin ).Length();
if ( iDist <= iNearest )
{
iNearest = iDist;
iBestRelationship = IRelationship ( pNextEnt );
pReturn = pNextEnt;
}
}
}
pNextEnt = pNextEnt->m_pLink;
}
return pReturn;
}

View File

@ -0,0 +1,155 @@
// ---------------------------------------------------------------
// 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 "player.h"
#include "weapons.h"
#include "gamerules.h"
#include "game.h"
#include "tripmine.h"
#include "shake.h"
BOOL CTripmineGrenade::BMOD_IsSpawnMine()
{
if (bm_spawnmines.value)
return FALSE;
BOOL result = FALSE;
CBaseEntity *pEntity = NULL;
TraceResult tr;
Vector vecSpot, vecTop;
Vector vecSrc = pev->origin;
float flRadius = pev->dmg * 2.5;
int bInWater = (UTIL_PointContents ( vecSrc ) == CONTENTS_WATER);
vecSrc.z += 1;// in case grenade is lying on the ground
// iterate on all entities in the vicinity.
while ((pEntity = UTIL_FindEntityInSphere( pEntity, vecSrc, flRadius )) != NULL)
{
// Only look for deathmatch spawn points
if ( FClassnameIs( pEntity->pev, "info_player_deathmatch" ) )
{
// blast's don't tavel into or out of water,
// so ignore spawn points that lie on the other side.
if (bInWater && pEntity->pev->waterlevel == 0)
continue;
if (!bInWater && pEntity->pev->waterlevel == 3)
continue;
// Trace a small line from the trip out to the potential damage radius.
UTIL_TraceLine ( vecSrc, vecSrc + m_vecDir * flRadius, ignore_monsters, ENT(pev), &tr );
vecSpot = tr.vecEndPos;
UTIL_TraceLine( pEntity->pev->origin, pEntity->pev->origin - Vector(0,0,1024), ignore_monsters, ENT(pev), &tr);
Vector vecTop = pEntity->pev->origin + Vector(0,0,36);
float height = fabs(vecTop.z - tr.vecEndPos.z) / 2;
if (UTIL_OBB_LineTest(vecSrc, vecSpot, Vector(vecTop.x, vecTop.y, (vecTop.z + tr.vecEndPos.z) / 2), Vector(16,16,height) ))
result = TRUE;
}
}
return result;
}
void CTripmineGrenade::FlashBang( void )
{
#define FLASH_RANGE 600
pev->nextthink = gpGlobals->time + 0.3;
SetThink( Smoke );
// Find all players in range
CBaseEntity *pEntity = NULL;
TraceResult tr;
Vector vecSpot;
float amount, range;
EMIT_SOUND( ENT(pev), CHAN_VOICE, "weapons/pl_gun2.wav", 1, ATTN_NORM);
while ((pEntity = UTIL_FindEntityInSphere( pEntity, pev->origin, FLASH_RANGE )) != NULL)
{
// Only look for players
if ( FClassnameIs( pEntity->pev, "player" ) )
{
vecSpot = pEntity->BodyTarget( pev->origin );
// Trace a small line from the trip out to the player.
UTIL_TraceLine ( pev->origin, vecSpot, dont_ignore_monsters, ENT(pev), &tr );
if (tr.flFraction == 1.0 || tr.pHit == pEntity->edict())
{
range = (vecSpot - pev->origin).Length();
amount = range
* range
* -1
/ FLASH_RANGE
+ 255;
UTIL_ScreenFade( pEntity, Vector(255,255,255), 5.0, 1.0, amount, FFADE_IN);
}
}
}
}
void CTripmineGrenade::Deactivate( void )
{
pev->solid = SOLID_NOT;
KillBeam();
UTIL_Remove( this );
}
//=========================================================
// DeactivateTrips - removes all trips owned by
// the provided player.
//
// Made this global on purpose.
//=========================================================
void DeactivateTrips( CBasePlayer *pOwner )
{
edict_t *pFind;
pFind = FIND_ENTITY_BY_CLASSNAME( NULL, "monster_tripmine" );
while ( !FNullEnt( pFind ) )
{
CBaseEntity *pEnt = CBaseEntity::Instance( pFind );
CTripmineGrenade *pTrip = (CTripmineGrenade *)pEnt;
if ( pTrip )
{
if ( pTrip->Owner() == pOwner->edict() )
{
pTrip->Deactivate();
}
}
pFind = FIND_ENTITY_BY_CLASSNAME( pFind, "monster_tripmine" );
}
}

View File

@ -0,0 +1,533 @@
// ---------------------------------------------------------------
// 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 "saverestore.h"
#include <time.h>
#include "shake.h"
#include "decals.h"
#include "player.h"
#include "weapons.h"
#include "gamerules.h"
#include <string.h>
#include <time.h>
// bigguy's CastPlayer functions
CBasePlayer* UTIL_CastPlayer ( CBaseEntity *pEnt )
{
if (pEnt) // check validity
{
if (pEnt->IsPlayer()) // is it even a player?
{
CBasePlayer *plr = GetClassPtr((CBasePlayer *)pEnt); // cast player
if (plr) // check validity
return plr; // return pointer
}
}
return NULL; // otherwise, its not a player
}
CBasePlayer* UTIL_CastPlayer ( entvars_t *pev )
{
if (pev) // check validity
{
if (FClassnameIs(pev, "player")) // is it even a player?
{
CBasePlayer *plr = GetClassPtr((CBasePlayer *)pev); // cast player
if (plr) // check validity
return plr; // return pointer
}
}
return NULL; // otherwise, its not a player
}
CBasePlayer* UTIL_CastPlayer ( edict_t *pEdict )
{
if (pEdict) // check validity
{
// if (FClassnameIs(pEdict, "player")) // is it even a player?
// {
entvars_t *pev = &pEdict->v;
// CBasePlayer *plr = GetClassPtr((CBasePlayer *)pev); // cast player
CBasePlayer *plr = (CBasePlayer*) CBasePlayer::Instance( pev ); // cast player
if (plr) // check validity
return plr; // return pointer
// }
}
return NULL; // otherwise, its not a player
}
CBasePlayer* UTIL_CastPlayer ( int index )
{
if (index > 0 && index <= gpGlobals->maxClients) // check validity
{
edict_t *pEdict = INDEXENT(index); // cast pEdict
CBasePlayer *plr = UTIL_CastPlayer(pEdict); // cast player
if (plr) // check validity
return plr; // return pointer
}
return NULL; // otherwise, its not a player
}
// Oriented Bounding Box to line segment intersection test
// Adapted from Miguel Gomez article on Gamasutra Oct. '99
//
// Arguments are line start point, line end point, BBox center, and BBox extents
//
// Returns TRUE if the line and BBox intersect, FALSE if they do not.
BOOL UTIL_OBB_LineTest(Vector vecSrc, Vector vecDst, Vector boxP, Vector boxE)
{
// Unit vector in direction of line.
Vector l = vecDst - vecSrc;
// Half of line segment length
float hl = fabs(l.Length() / 2);
l = l.Normalize();
// midpoint of line segemnt.
Vector mid = (vecDst + vecSrc) / 2;
// The separating axis.
Vector T = boxP - mid;
/*
char sPlayers[256] = "";
sprintf(sPlayers, "Start: %f, %f, %f\nEnd: %f, %f, %f\nhl: %f\nunit: %f, %f, %f\n\n", vecSrc.x, vecSrc.y, vecSrc.z,
vecDst.x, vecDst.y, vecDst.z, hl, l.x, l.y, l.z);
g_engfuncs.pfnServerPrint( sPlayers );
MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY );
WRITE_BYTE( TE_BEAMPOINTS );
WRITE_COORD(mid.x);
WRITE_COORD(mid.y);
WRITE_COORD(mid.z);
WRITE_COORD(mid.x + (hl * l.x));
WRITE_COORD(mid.y + (hl * l.y));
WRITE_COORD(mid.z + (hl * l.z));
WRITE_SHORT( g_sModelIndexLaser );
WRITE_BYTE( 0 ); // Starting frame
WRITE_BYTE( 0 ); // framerate * 0.1
WRITE_BYTE( 255 ); // life * 0.1
WRITE_BYTE( 10 ); // width
WRITE_BYTE( 0 ); // noise
WRITE_BYTE( 0 ); // color r,g,b
WRITE_BYTE( 0 ); // color r,g,b
WRITE_BYTE( 255 ); // color r,g,b
WRITE_BYTE( 255 ); // brightness
WRITE_BYTE( 0 ); // scroll speed
MESSAGE_END();
MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY );
WRITE_BYTE( TE_BEAMPOINTS );
WRITE_COORD(mid.x);
WRITE_COORD(mid.y);
WRITE_COORD(mid.z);
WRITE_COORD(mid.x - (hl * l.x));
WRITE_COORD(mid.y - (hl * l.y));
WRITE_COORD(mid.z - (hl * l.z));
WRITE_SHORT( g_sModelIndexLaser );
WRITE_BYTE( 0 ); // Starting frame
WRITE_BYTE( 0 ); // framerate * 0.1
WRITE_BYTE( 255 ); // life * 0.1
WRITE_BYTE( 10 ); // width
WRITE_BYTE( 0 ); // noise
WRITE_BYTE( 255 ); // color r,g,b
WRITE_BYTE( 0 ); // color r,g,b
WRITE_BYTE( 0 ); // color r,g,b
WRITE_BYTE( 255 ); // brightness
WRITE_BYTE( 0 ); // scroll speed
MESSAGE_END();
MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY );
WRITE_BYTE( TE_BEAMPOINTS );
WRITE_COORD(mid.x);
WRITE_COORD(mid.y);
WRITE_COORD(mid.z);
WRITE_COORD(boxP.x);
WRITE_COORD(boxP.y);
WRITE_COORD(boxP.z);
WRITE_SHORT( g_sModelIndexLaser );
WRITE_BYTE( 0 ); // Starting frame
WRITE_BYTE( 0 ); // framerate * 0.1
WRITE_BYTE( 255 ); // life * 0.1
WRITE_BYTE( 10 ); // width
WRITE_BYTE( 0 ); // noise
WRITE_BYTE( 255 ); // color r,g,b
WRITE_BYTE( 255 ); // color r,g,b
WRITE_BYTE( 255 ); // color r,g,b
WRITE_BYTE( 255 ); // brightness
WRITE_BYTE( 0 ); // scroll speed
MESSAGE_END();
*/
// The box is assumed to be axis aligned to the world, so we start
// with those trivial cases.
if( ( fabs(T.x) > boxE.x + hl * fabs(l.x) ) ||
( fabs(T.y) > boxE.y + hl * fabs(l.y) ) ||
( fabs(T.z) > boxE.z + hl * fabs(l.z) ) )
return FALSE;
// Now we check the box transformed into the line space.
if ( ( fabs(T.y*l.z - T.z*l.y) > boxE.y*fabs(l.z) + boxE.z*fabs(l.y) ) ||
( fabs(T.z*l.x - T.x*l.z) > boxE.z*fabs(l.x) + boxE.x*fabs(l.z) ) ||
( fabs(T.x*l.y - T.y*l.x) > boxE.x*fabs(l.y) + boxE.y*fabs(l.x) ) )
return FALSE;
return TRUE;
}
// Oriented Bounding Box to point intersection test
//
// Arguments are line point, BBox center, and BBox extents
//
// Returns TRUE if the point and BBox intersect, FALSE if they do not.
BOOL UTIL_OBB_PointTest(Vector vecSrc, Vector boxP, Vector boxE)
{
if ((vecSrc.x < (boxP.x - boxE.x) )||
(vecSrc.x > (boxP.x + boxE.x) )||
(vecSrc.y < (boxP.y - boxE.y) )||
(vecSrc.y > (boxP.y + boxE.y) )||
(vecSrc.z < (boxP.z - boxE.z) )||
(vecSrc.z > (boxP.z + boxE.z) ))
return FALSE;
return TRUE;
}
void UTIL_SpeakAll( char *message )
{
char text[256];
strcpy(text, "speak \"");
strcat(text, message);
strcat(text, "\"\n");
CBasePlayer *client = NULL;
while ( ((client = (CBasePlayer*)UTIL_FindEntityByClassname( client, "player" )) != NULL) && (!FNullEnt(client->edict())) )
{
CLIENT_COMMAND(client->edict(), text);
}
}
void UTIL_SpeakBadWeapon( void )
{
switch (RANDOM_LONG(0, 3))
{
case 0:
UTIL_SpeakAll("deeoo, warning, unauthorized weapon use detected");
break;
case 1:
UTIL_SpeakAll("deeoo, warning, weapon violation detected");
break;
case 2:
UTIL_SpeakAll("deeoo, warning, forbidden use of detonation device");
break;
case 3:
UTIL_SpeakAll("deeoo, warning, illegal explosion in sector fourty two");
break;
}
}
char* UTIL_CountVotes()
{
static char string[128];
char maps[32][81];
int votes[32];
int p = 0;
int q = 0;
for (int i = 0; i < 32; i++)
{
strcpy(maps[i], "");
votes[i] = 0;
}
CBasePlayer *client = NULL;
for ( i = 1; i <= gpGlobals->maxClients; i++ )
{
client = (CBasePlayer*)UTIL_PlayerByIndex( i );
if ( client && (client->m_bIsConnected) && (IS_MAP_VALID(client->m_sMapVote) || !strcmp(client->m_sMapVote, "extend")))
{
p = 0;
while(strcmp(client->m_sMapVote, maps[p]) && (p < 32))
{
p++;
}
if (p < 32)
{
votes[p]++;
}
else
{
strcpy(maps[q], client->m_sMapVote);
votes[q]++;
q++;
}
}
}
q = 0;
for (i = 0; i < 32; i++)
{
if (votes[i] > votes[q])
q = i;
}
string[0] = (char)votes[q];
string[1] = 0;
strcat(&(string[1]), maps[q]);
return string;
}
typedef struct
{
char WONid[81];
// unsigned int WONid;
int frags;
int deaths;
int SpawnKills;
int TypeKills;
BOOL IsLlama;
} SavedPlayer;
void UTIL_SaveRestorePlayer( CBasePlayer *pPlayer, BOOL save, BOOL resetall )
{
// return;
static SavedPlayer Player[32];
static BOOL init = FALSE;
// Initialize the array
if (!init || resetall)
{
for (int i = 0; i < 32; i++)
{
Player[i].WONid[0] = 0;
// Player[i].WONid = 0;
Player[i].frags = 0;
Player[i].deaths = 0;
Player[i].SpawnKills = 0;
Player[i].TypeKills = 0;
Player[i].IsLlama = 0;
}
init = TRUE;
}
if (resetall)
return;
// Save a player's data
if (save)
{
for (int i = 0; i < 32; i++)
{
if (Player[i].WONid[0] == 0)
// if (Player[i].WONid == 0)
{
strcpy(Player[i].WONid, GETPLAYERAUTHID(pPlayer->edict()));
// Player[i].WONid = GETPLAYERAUTHID(pPlayer->edict());
//Player[i].frags = pPlayer->pev->frags;
//Player[i].deaths = pPlayer->m_iDeaths;
Player[i].SpawnKills = pPlayer->m_iSpawnKills;
Player[i].TypeKills = pPlayer->m_iTypeKills;
Player[i].IsLlama = pPlayer->m_IsLlama;
break;
}
}
}
// Otherwise load a player's data
else
{
for (int i = 0; i < 32; i++)
{
if (!strcmp(Player[i].WONid, GETPLAYERAUTHID(pPlayer->edict())))
// if (Player[i].WONid == GETPLAYERAUTHID(pPlayer->edict()))
{
//pPlayer->pev->frags = Player[i].frags;
//pPlayer->m_iDeaths = Player[i].deaths;
pPlayer->m_IsLlama = Player[i].IsLlama;
pPlayer->m_iSpawnKills = Player[i].SpawnKills;
pPlayer->m_iTypeKills = Player[i].TypeKills;
Player[i].WONid[0] = 0;
// Player[i].WONid = 0;
Player[i].frags = 0;
Player[i].deaths = 0;
Player[i].SpawnKills = 0;
Player[i].TypeKills = 0;
break;
}
}
}
}
const int NUMSTRINGS = 43;
const char *XLate [NUMSTRINGS*5] ={ "YOU", "J00", "JO0", "j00", "Jo0",
"?", "?!", "!?", "?!?", "!?!",
"!", "!!", "!", "!!", "!",
"IES", "YS", "yZ", "Y$", "y5",
"HACKER", "H4X0r" ,"H4><0r", "h4X0r", "h4XoR",
"SUCK", "SuX0rZ" ,"Su><0rZ", "sUX0rz", "suXoRZ",
"DUDE", "D00D" ,"d00d", "dUUD", "|)0o|)",
"QU", "|<u", "Ku", "kU", "]<U",
"ENOUGH", "3nUfF", "EnUF" ,"3|\\|UF", "eNuFF",
"DOES", "dUz", "D0Z", "Du$", "duuZZ",
"TOO", "2", "2", "2", "2",
"TO", "2", "2", "2", "2",
"FOR", "4", "4", "Fo|2", "f0R",
"WHAT", "wUt", "Wu7", "Wu+", "wU++",
"ROCK", "|20X0rZ" ,"ro><orZ", "r()x()|2$", "r0x0rZ",
"COOL", "|<3w3l" ,"k3vv3l", "KeW3|_", "k3vv3L",
"STUPID", "$t00piD" ,"Z+00p!d", "S700P!D", "z7OOp!d",
"A", "/\\", "A", "4", "@",
"B", "B", "b", "8", "|3",
"C", "C", "c", "[", "(",
"D", "D", "d", "|)", "|]",
"E", "E", "e", "3", "3",
"F", "F", "f", "F", "f",
"G", "G", "g", "G", "6",
"H", "H", "h", "H", "h",
"I", "I", "i", "!", "!",
"J", "J", "j", "J", "j",
"K", "K", "k" ,"|<", "]<",
"L", "L", "l", "1", "|_",
"M", "M", "m", "M", "m",
"N", "N", "n", "|\\|", "N",
"O", "<>", "o", "0", "()",
"P", "P", "p", "P", "p",
"Q", "Q", "q", "Q", "q",
"R", "R", "r", "|2", "|2",
"S", "z", "$", "5", "Z",
"T", "T", "t", "7", "+",
"U", "U", "u", "U", "u",
"V", "V", "v", "\\/", "V",
"W", "W", "w", "vv", "W",
"X", "X", "x", "><", "%",
"Y", "Y", "y", "Y", "y",
"Z", "Z", "z", "Z", "z"
};
void UTIL_Speak_2_l33t( char *szTarget, char *szOString )
{
const int MAX_L33T = 512;
int i = 0;
char szNewString[MAX_L33T] = "";
char szString[MAX_L33T] = "";
strcpy(szString, szOString);
int j;
BOOL match;
for (i=0; i<(int)strlen(szString); i++)
{
szString[i] = toupper(szString[i]);
};
i = 0;
for (i=0; i<(int)strlen(szString); i++)
{
match = false;
for(j=0; j<NUMSTRINGS; j++)
{
if (!strncmp(szString+i, XLate[j*5], strlen(XLate[j*5])) )
{
strcat(szNewString, XLate[j*5+RANDOM_LONG(1,4)]);
i += strlen(XLate[j*5])-1;
match= true;
break;
}
}
if (!match)
{
strncat(szNewString, szString+i, 1);
}
}
strcat(szTarget, szNewString);
}
void UTIL_SayTime( void ) {
// tm_sec: seconds after the minute (0-59)
// tm_min: minutes after hour (0-59)
// tm_hour: hours after midnight (0-23)
// tm_mday: day of month (1-31)
// tm_mon: month of year (0-11; January == 0)
// tm_year: year (value of current year minus 1900)
struct tm *adjustedTime;
time_t sysTime;
time( &sysTime ); // Get system time encoded as time_t
adjustedTime = localtime( &sysTime ); // Adjust for local time
char szTime[80];
int hour = adjustedTime->tm_hour;
hour = hour > 12 ? hour - 12 : hour;
hour = hour == 0 ? 12 : hour;
int min = adjustedTime->tm_min;
char *ampm = "AM";
if (adjustedTime->tm_hour > 11)
ampm = "PM";
sprintf(szTime, "<SERVER> Local server time is: %d:%02d %s\n", hour, min, ampm);
UTIL_ClientPrintAll( HUD_PRINTTALK, szTime);
}
// Convert a four digit hex string to an int.
int UTIL_axtoi(char *hexStg) {
int n = 0; // position in string
int m = 0; // position in digit[] to shift
int count; // loop index
int intValue = 0; // integer value of hex string
int digit[5]; // hold values to convert
while (n < 4) {
if (hexStg[n]=='\0')
break;
if (hexStg[n] > 0x29 && hexStg[n] < 0x40 ) //if 0 to 9
digit[n] = hexStg[n] & 0x0f; //convert to int
else if (hexStg[n] >='a' && hexStg[n] <= 'f') //if a to f
digit[n] = (hexStg[n] & 0x0f) + 9; //convert to int
else if (hexStg[n] >='A' && hexStg[n] <= 'F') //if A to F
digit[n] = (hexStg[n] & 0x0f) + 9; //convert to int
else break;
n++;
}
count = n;
m = n - 1;
n = 0;
while(n < count) {
// digit[n] is value of hex digit at position n
// (m << 2) is the number of positions to shift
// OR the bits into return value
intValue = intValue | (digit[n] << (m << 2));
m--; // adjust the position to set
n++; // next digit to process
}
return (intValue);
}

View File

@ -0,0 +1,369 @@
// ---------------------------------------------------------------
// Zap Rift Entity
//
// 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 "monsters.h"
#include "weapons.h"
#include "nodes.h"
#include "player.h"
#include "gamerules.h"
#include "effects.h"
#include "BMOD_zapgunrift.h"
#include "shake.h"
#define RIFTSPR "sprites/cnt1.spr"
#define RIFTSPR2 "sprites/cnt1.spr"
LINK_ENTITY_TO_CLASS( zaprift, CZapRift );
void CZapRift::Precache( void )
{
PRECACHE_SOUND("debris/zap4.wav");
PRECACHE_SOUND("weapons/electro4.wav");
PRECACHE_SOUND("hassault/hw_shoot1.wav");
PRECACHE_MODEL( RIFTSPR );
PRECACHE_MODEL( RIFTSPR2 );
}
void CZapRift::Spawn( void )
{
pev->classname = MAKE_STRING( "zapgun" );
pev->movetype = MOVETYPE_FLY;
pev->solid = SOLID_NOT;
pev->rendermode = kRenderGlow;
pev->renderamt = 240;
pev->renderfx = kRenderFxNoDissipation;
UTIL_MakeAimVectors( pev->angles );
//pev->origin = pev->origin + gpGlobals->v_forward * 8;
SET_MODEL(ENT(pev), RIFTSPR);
pev->frame = 0;
pev->scale = 2;
m_maxFrame = (float) MODEL_FRAMES( pev->modelindex ) - 1;
// Create Inner Animated Sprite
m_pSprite = CSprite::SpriteCreate( RIFTSPR2, pev->origin, TRUE );
m_pSprite->Animate( 1 );
m_pSprite->pev->scale = 1;
m_pSprite->SetTransparency( kRenderGlow, 255, 255, 255, 180, kRenderFxNoDissipation );
m_pSprite->pev->spawnflags |= SF_SPRITE_TEMPORARY;
SetThink ( Animate );
pev->nextthink = gpGlobals->time + 0.1;
m_fLifeSpan = gpGlobals->time + 3;
m_fNextElectrify = gpGlobals->time + 0.1;
EMIT_SOUND_DYN( ENT(pev), CHAN_WEAPON, "debris/zap4.wav", 1, ATTN_NORM, 0,100 );
}
void CZapRift::Animate( void )
{
pev->nextthink = gpGlobals->time + 0.1;
if ( pev->frame++ )
{
if ( pev->frame > m_maxFrame )
{
pev->frame = 0;
}
}
m_pSprite->pev->scale = RANDOM_FLOAT(.5, 3);
if ( m_fLifeSpan < gpGlobals->time)
{
pev->effects |= EF_NODRAW;
m_pSprite->Expand( 10, 100 );
SetThink(SUB_Remove);
pev->nextthink = gpGlobals->time + 5;
}
if ( m_fNextElectrify < gpGlobals->time )
{
// Send out electric streamers and do area effect damage
for (int i = 0; i < 3; i++)
{
Vector vecTemp;
Vector vecEnd = Vector (0,0,0);
// Hopefully find a long beam
for (int j = 0; j < 5; j++)
{
vecTemp = FindBeam();
if ( vecTemp.Length() > vecEnd.Length() )
vecEnd = vecTemp;
}
// Draw the streamer
MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY );
WRITE_BYTE( TE_BEAMPOINTS );
WRITE_COORD(pev->origin.x);
WRITE_COORD(pev->origin.y);
WRITE_COORD(pev->origin.z);
WRITE_COORD( vecEnd.x );
WRITE_COORD( vecEnd.y );
WRITE_COORD( vecEnd.z );
WRITE_SHORT( g_sModelIndexLightning );
WRITE_BYTE( 0 ); // Starting frame
WRITE_BYTE( 0 ); // framerate * 0.1
WRITE_BYTE( 20 ); // life * 0.1
WRITE_BYTE( 80 ); // width
WRITE_BYTE( 50 ); // noise
WRITE_BYTE( 180 ); // color r,g,b
WRITE_BYTE( 255 ); // color r,g,b
WRITE_BYTE( 96 ); // color r,g,b
WRITE_BYTE( 255 ); // brightness
WRITE_BYTE( 0 ); // scroll speed
MESSAGE_END();
}
// Deal damage.
CBaseEntity *pEntity= NULL;
TraceResult tr;
while ((pEntity = UTIL_FindEntityInSphere( pEntity, pev->origin, 512 )) != NULL)
{
// Only look for players
if ( pEntity->pev->takedamage != DAMAGE_NO )
{
// blast's don't tavel out of water,
// so ignore players that lie on the other side.
if (pEntity->pev->waterlevel == 0)
continue;
// Trace to the target
UTIL_TraceLine( pev->origin, pEntity->BodyTarget( pev->origin ) , dont_ignore_monsters, ENT(pev), &tr);
if (tr.flFraction == 1.0 || tr.pHit == pEntity->edict())
{
ClearMultiDamage( );
pEntity->TraceAttack( VARS( pev->owner ), 30, Vector(0,0,1), &tr, DMG_SHOCK | DMG_ALWAYSGIB );
ApplyMultiDamage( pev, VARS( pev->owner ) );
UTIL_ScreenFade( pEntity, Vector(180,255,96), 2, 0.5, 128, FFADE_IN );
}
}
}
m_fNextElectrify = gpGlobals->time + 1;
}
}
Vector CZapRift::FindBeam( void )
{
TraceResult tr;
// Direction is within the forward hemisphere.
UTIL_MakeAimVectors( pev->angles );
Vector vecDir = gpGlobals->v_right * RANDOM_FLOAT( -1, 1)
+ gpGlobals->v_up * RANDOM_FLOAT( -1, 1)
+ gpGlobals->v_forward * RANDOM_FLOAT( 0, 1);
vecDir = vecDir.Normalize();
// Maximum distance
float fDist = 1024;
// End point of the streamer
Vector vecEnd = pev->origin + vecDir * fDist;
// Trace to the end of the streamer to see if
// there is architecture in the way.
UTIL_TraceLine(pev->origin, vecEnd, ignore_monsters, ENT(pev), &tr);
fDist = (tr.vecEndPos - pev->origin).Length();
// Now we need to find the distance to the water transition.
// (if there is one)
if (UTIL_PointContents(tr.vecEndPos) != CONTENTS_WATER)
{
Vector vecMin = pev->origin;
Vector vecMax = pev->origin + vecDir * fDist;
Vector vecMid;
float diff = fDist;
while (diff > 1.0)
{
vecMid = vecMin + (vecMax - vecMin).Normalize() * diff / 2;
if (UTIL_PointContents(vecMid) == CONTENTS_WATER)
{
vecMin = vecMid;
}
else
{
vecMax = vecMid;
}
diff = (vecMax - vecMin).Length();
}
fDist = (vecMid - pev->origin).Length();
}
// Return new endpoint.
return pev->origin + vecDir * fDist;
}
LINK_ENTITY_TO_CLASS( zapbounce, CZapBounce );
void CZapBounce::Precache( void )
{
PRECACHE_SOUND("debris/zap4.wav");
PRECACHE_SOUND("weapons/electro4.wav");
PRECACHE_SOUND("hassault/hw_shoot1.wav");
PRECACHE_MODEL( RIFTSPR );
PRECACHE_MODEL( RIFTSPR2 );
}
void CZapBounce::Spawn( void )
{
pev->classname = MAKE_STRING( "multizapper" );
pev->movetype = MOVETYPE_FLY;
pev->solid = SOLID_NOT;
//UTIL_MakeAimVectors( pev->angles );
m_vecStart = pev->origin;
m_vecDir = pev->angles;
m_fDamage = 90;
m_iBounce = 5;
m_bFirstZap = TRUE;
SetThink ( BounceThink );
pev->nextthink = gpGlobals->time + 0.2;
EMIT_SOUND_DYN( ENT(pev), CHAN_WEAPON, "debris/zap4.wav", 1, ATTN_NORM, 0,100 );
}
void CZapBounce::BounceThink( void )
{
TraceResult tr;
CBaseEntity *pEntity;
pev->nextthink = gpGlobals->time + 0.05;
// Zap Forward with some randomness.
if (!m_bFirstZap)
{
m_vecDir = m_vecDir * 5 + Vector(RANDOM_FLOAT( -1, 1),
RANDOM_FLOAT( -1, 1),
RANDOM_FLOAT( -1, 1)
);
}
m_vecDir = m_vecDir.Normalize();
// Maximum distance for this segment.
float fDist = 128;
// End point of the streamer
Vector vecEnd = m_vecStart + m_vecDir * fDist;
// Trace to the end of the streamer
UTIL_TraceLine(m_vecStart, vecEnd, dont_ignore_monsters, pentIgnore, &tr);
fDist = (tr.vecEndPos - m_vecStart).Length();
// draw lightning
for (int i = 0; i < 2; i++)
{
MESSAGE_BEGIN( MSG_BROADCAST, SVC_TEMPENTITY );
WRITE_BYTE( TE_BEAMPOINTS );
WRITE_COORD(m_vecStart.x);
WRITE_COORD(m_vecStart.y);
WRITE_COORD(m_vecStart.z);
WRITE_COORD( tr.vecEndPos.x );
WRITE_COORD( tr.vecEndPos.y );
WRITE_COORD( tr.vecEndPos.z );
WRITE_SHORT( g_sModelIndexLightning );
WRITE_BYTE( 0 ); // Starting frame
WRITE_BYTE( 0 ); // framerate * 0.1
WRITE_BYTE( 10 ); // life * 0.1
WRITE_BYTE( m_iBounce * 10 ); // width
WRITE_BYTE( 10 * (6 - m_iBounce )); // noise
WRITE_BYTE( 96 ); // color r,g,b
WRITE_BYTE( 180 ); // color r,g,b
WRITE_BYTE( 255 ); // color r,g,b
WRITE_BYTE( m_iBounce * 50); // brightness
WRITE_BYTE( 0 ); // scroll speed
MESSAGE_END();
}
m_vecStart = tr.vecEndPos;
// Did we hit an entity? Then do damage.
pEntity = CBaseEntity::Instance(tr.pHit);
if (pEntity) {
if (pEntity->pev->takedamage)
{
ClearMultiDamage( );
pEntity->TraceAttack( VARS(pev->owner), m_fDamage, m_vecDir, &tr, DMG_SHOCK | DMG_ALWAYSGIB );
ApplyMultiDamage( VARS(pev->owner), VARS(pev->owner) );
UTIL_ScreenFade( pEntity, Vector(96,180,255), 2, 0.5, 128, FFADE_IN );
}
// Did we hit a wall? Then reflect.
else
{
float n;
n = -DotProduct(tr.vecPlaneNormal, m_vecDir);
Vector r;
r = 2.0 * tr.vecPlaneNormal * n + m_vecDir;
m_vecDir = r;
}
pentIgnore = ENT(pEntity->pev);
}
// We can hurt ourselves after the first beam.
m_bFirstZap = FALSE;
// bounce once
m_iBounce--;
if (m_iBounce < 1)
{
// UTIL_ClientPrintAll( HUD_PRINTTALK, "<SERVER> Zap bounce point destroyed.\n");
SetThink(SUB_Remove);
pev->nextthink = gpGlobals->time + .1;
return;
}
// split beam?
if (RANDOM_LONG(0,100) < 80)
{
m_fDamage *= .75;
CZapBounce* pRift = (CZapBounce*)CBaseEntity::Create( "zapbounce",
m_vecStart,
m_vecDir,
ENT(pev->owner) );
pRift->m_fDamage = m_fDamage;
pRift->m_iBounce = m_iBounce;
pRift->m_bFirstZap = FALSE;
pRift->pev->nextthink = gpGlobals->time + RANDOM_LONG(.2,.3);
}
}

View File

@ -0,0 +1,62 @@
// ---------------------------------------------------------------
// Zap Rift Entity
//
// 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.
//
// ---------------------------------------------------------------
#ifndef C_ZAP_RIFT
#define C_ZAP_RIFT
class CZapRift : public CPointEntity
{
public:
void Spawn( void );
void Precache( void );
void EXPORT Animate( void );
Vector FindBeam( void );
int m_maxFrame;
CSprite *m_pSprite;
float m_fLifeSpan;
float m_fNextElectrify;
Vector m_vecZapDir;
};
class CZapBounce : public CPointEntity
{
public:
void Spawn( void );
void Precache( void );
void EXPORT BounceThink( void );
Vector m_vecStart;
Vector m_vecDir;
edict_t *pentIgnore;
BOOL m_bFirstZap;
float m_fDamage;
int m_iBounce;
};
#endif

91
dlls/bubblemod/egon.h Normal file
View File

@ -0,0 +1,91 @@
#ifndef EGON_H
#define EGON_H
#include "weapons.h"
#define BUBBLE_SOUND_OFF "debris/flesh5.wav"
#define BUBBLE_SOUND_RUN "debris/flesh5.wav"
#define BUBBLE_SOUND_STARTUP "debris/flesh6.wav"
#define EGON_PRIMARY_VOLUME 450
extern cvar_t bm_gluon_mod;
class CEgon : public CBasePlayerWeapon
{
public:
#ifndef CLIENT_DLL
int Save( CSave &save );
int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
#endif
void Spawn( void );
void Precache( void );
int iItemSlot( void ) { return 4; }
int GetItemInfo(ItemInfo *p);
int AddToPlayer( CBasePlayer *pPlayer );
BOOL Deploy( void );
void Holster( int skiplocal = 0 );
void UpdateEffect( const Vector &startPoint, const Vector &endPoint, float timeBlend );
void CreateEffect ( void );
void DestroyEffect ( void );
void EndAttack( void );
void Attack( void );
void PrimaryAttack( void );
void WeaponIdle( void );
float m_flAmmoUseTime;// since we use < 1 point of ammo per update, we subtract ammo on a timer.
float GetPulseInterval( void );
float GetDischargeInterval( void );
void Fire( const Vector &vecOrigSrc, const Vector &vecDir );
BOOL HasAmmo( void );
void UseAmmo( int count );
enum EGON_FIREMODE { FIRE_NARROW, FIRE_WIDE};
CBeam *m_pBeam;
CBeam *m_pNoise;
CSprite *m_pSprite;
virtual BOOL UseDecrement( void )
{
#if defined( CLIENT_WEAPONS )
return TRUE;
#else
return FALSE;
#endif
}
unsigned short m_usEgonStop;
// BMOD Begin - bubblegun
void BubbleAttack( void );
void FireBubbles( void );
float m_bubbletime;
void FireHeal( void );
static int g_fireAnims1[];
static int g_fireAnims2[];
float m_healAmmoUsed;
float m_healAmmoUseTime;
// BMOD End - bubblegun
private:
float m_shootTime;
EGON_FIREMODE m_fireMode;
float m_shakeTime;
BOOL m_deployed;
unsigned short m_usEgonFire;
};
#endif

View File

@ -0,0 +1,68 @@
#ifndef SQUEAKGRENADE_H
#define SQUEAKGRENADE_H
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "monsters.h"
#include "weapons.h"
#include "nodes.h"
#include "player.h"
#include "soundent.h"
#include "gamerules.h"
#include "BMOD_messaging.h"
enum w_squeak_e {
WSQUEAK_IDLE1 = 0,
WSQUEAK_FIDGET,
WSQUEAK_JUMP,
WSQUEAK_RUN,
};
enum squeak_e {
SQUEAK_IDLE1 = 0,
SQUEAK_FIDGETFIT,
SQUEAK_FIDGETNIP,
SQUEAK_DOWN,
SQUEAK_UP,
SQUEAK_THROW
};
extern cvar_t bm_snarks_mod;
extern cvar_t bm_snarktrails;
class CSqueakGrenade : public CGrenade
{
void Spawn( void );
void Precache( void );
int Classify( void );
void EXPORT SuperBounceTouch( CBaseEntity *pOther );
void EXPORT HuntThink( void );
int BloodColor( void ) { return BLOOD_COLOR_YELLOW; }
void Killed( entvars_t *pevAttacker, int iGib );
void GibMonster( void );
CBaseEntity *CSqueakGrenade :: BMOD_BestVisibleEnemy ( void );
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
static float m_flNextBounceSoundTime;
// CBaseEntity *m_pTarget;
float m_flDie;
Vector m_vecTarget;
float m_flNextHunt;
float m_flNextHit;
Vector m_posPrev;
EHANDLE m_hOwner;
int m_iMyClass;
public:
BOOL m_bWasLaunched;
};
#endif

48
dlls/bubblemod/tripmine.h Normal file
View File

@ -0,0 +1,48 @@
#ifndef TRIPMINE_H
#define TRIPMINE_H
class CTripmineGrenade : public CGrenade
{
void Spawn( void );
void Precache( void );
virtual int Save( CSave &save );
virtual int Restore( CRestore &restore );
static TYPEDESCRIPTION m_SaveData[];
int TakeDamage( entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType );
void EXPORT WarningThink( void );
void EXPORT PowerupThink( void );
void EXPORT BeamBreakThink( void );
void EXPORT DelayDeathThink( void );
void Killed( entvars_t *pevAttacker, int iGib );
void MakeBeam( void );
void KillBeam( void );
float m_flPowerUp;
Vector m_vecDir;
Vector m_vecEnd;
float m_flBeamLength;
EHANDLE m_hOwner;
CBeam *m_pBeam;
Vector m_posOwner;
Vector m_angleOwner;
edict_t *m_pRealOwner;// tracelines don't hit PEV->OWNER, which means a player couldn't detonate his own trip mine, so we store the owner here.
// BMOD Begin - New tripmine functions
BOOL BMOD_IsSpawnMine( void );
void FlashBang( void );
public:
void Deactivate( void );
edict_t *Owner( void ) { return m_pRealOwner; };
BOOL m_bIsFlashbang;
// BMOD End - New tripmine functions
};
#endif