LINK_ENTITY_TO_CLASS( energy_wave, CEnergyWave );
EXTERN_SEND_TABLE(DT_BaseEntity)
IMPLEMENT_SERVERCLASS_ST(CEnergyWave, DT_EWaveEffect)
END_SEND_TABLE()
//---------------------------------------------------------
// Save/Restore
//---------------------------------------------------------
BEGIN_DATADESC( CEnergyWave )
END_DATADESC()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CEnergyWave::Precache( void )
{
SetClassname("energy_wave");
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CEnergyWave::Spawn( void )
{
Precache();
// Make it translucent
m_nRenderFX = kRenderTransAlpha;
SetRenderColorA( 255 );
SetSolid( SOLID_BBOX );
SetMoveType( MOVETYPE_NONE );
UTIL_SetSize( this, vec3_origin, vec3_origin );
// Think function
SetNextThink( gpGlobals->curtime + 0.1f );
}
//-----------------------------------------------------------------------------
// Purpose: Create an energy wave
//-----------------------------------------------------------------------------
CEnergyWave* CEnergyWave::Create( CBaseEntity *pentOwner )
{
CEnergyWave *pEWave = (CEnergyWave*)CreateEntityByName("energy_wave");
UTIL_SetOrigin( pEWave, pentOwner->GetLocalOrigin() );
pEWave->SetOwnerEntity( pentOwner );
pEWave->SetLocalAngles( pentOwner->GetLocalAngles() );
pEWave->Spawn();
return pEWave;
}
А во второй это:
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef ENERGYWAVE_H
#define ENERGYWAVE_H
#ifdef _WIN32
#pragma once
#endif
#include "basecombatweapon.h"
#include "energy_wave.h"
//-----------------------------------------------------------------------------
// Purpose: Shield
//-----------------------------------------------------------------------------
class CEnergyWave : public CBaseEntity
{
DECLARE_DATADESC();
public:
DECLARE_CLASS( CEnergyWave, CBaseEntity );
DECLARE_SERVERCLASS();
public:
void Spawn( void );
void Precache( void );
public:
static CEnergyWave* Create( CBaseEntity *pentOwner );
};
#endif //ENERGYWAVE_H
Всё, а сейчас надо сделать так что б наш хоундей смог сделать энергоудар как в первой части хл=) Значит так, добовляем опять таки в сервер часть 2 файла: 1)grenade_energy.cpp и 2)grenade_energy.h и в первый вписываем:
//========= Copyright © 1996-2001, Valve LLC, All rights reserved. ============
//
// Purpose: Projectile shot by mortar synth.
//
// $NoKeywords: $
//=============================================================================
#include "cbase.h"
#include "grenade_energy.h"
#include "soundent.h"
#include "player.h"
#include "hl2_shareddefs.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#define ENERGY_GRENADE_LIFETIME 1
ConVar sk_dmg_energy_grenade ( "sk_dmg_energy_grenade","0");
ConVar sk_energy_grenade_radius ( "sk_energy_grenade_radius","0");
BEGIN_DATADESC( CGrenadeEnergy )
DEFINE_FIELD( m_flMaxFrame, FIELD_INTEGER ),
DEFINE_FIELD( m_nEnergySprite, FIELD_INTEGER ),
DEFINE_FIELD( m_flLaunchTime, FIELD_TIME ),
// Function pointers
// DEFINE_FUNCTION( Animate ),
// DEFINE_FUNCTION( GrenadeEnergyTouch ),
END_DATADESC()
LINK_ENTITY_TO_CLASS( grenade_energy, CGrenadeEnergy );
void CGrenadeEnergy::Spawn( void )
{
Precache( );
SetSolid( SOLID_BBOX );
SetMoveType( MOVETYPE_FLY );
SetModel( "Models/weapons/w_energy_grenade.mdl" );
SetUse( DetonateUse );
SetTouch( GrenadeEnergyTouch );
SetNextThink( gpGlobals->curtime + 0.1f );
m_flDamage = sk_dmg_energy_grenade.GetFloat();
m_DmgRadius = sk_energy_grenade_radius.GetFloat();
m_takedamage = DAMAGE_YES;
m_iHealth = 1;
SetCycle( 0.0f );
m_flModelScale = 0.5;
m_flLaunchTime = gpGlobals->curtime;
SetCollisionGroup( HL2COLLISION_GROUP_HOUNDEYE );
UTIL_SetSize( this, vec3_origin, vec3_origin );
m_flMaxFrame = (float) modelinfo->GetModelFrameCount( GetModel() ) - 1;
}
//------------------------------------------------------------------------------
// Purpose :
// Input :
// Output :
//------------------------------------------------------------------------------
void CGrenadeEnergy::Shoot( CBaseEntity* pOwner, const Vector &vStart, Vector vVelocity )
{
CGrenadeEnergy *pEnergy = (CGrenadeEnergy *)CreateEntityByName( "grenade_energy" );
pEnergy->Spawn();
UTIL_SetOrigin( pEnergy, vStart );
pEnergy->SetAbsVelocity( vVelocity );
pEnergy->SetOwnerEntity( pOwner );
pEnergy->SetThink ( Animate );
pEnergy->SetNextThink( gpGlobals->curtime + 0.1f );
pEnergy->m_nRenderMode = kRenderTransAdd;
pEnergy->SetRenderColor( 160, 160, 160, 255 );
pEnergy->m_nRenderFX = kRenderFxNone;
}
//------------------------------------------------------------------------------
// Purpose :
// Input :
// Output :
//------------------------------------------------------------------------------
void CGrenadeEnergy::Animate( void )
{
float flLifeLeft = 1-(gpGlobals->curtime - m_flLaunchTime)/ENERGY_GRENADE_LIFETIME;
if (flLifeLeft < 0)
{
SetRenderColorA( 0 );
SetThink(NULL);
UTIL_Remove(this);
}
SetNextThink( gpGlobals->curtime + 0.01f );
QAngle angles;
VectorAngles( GetAbsVelocity(), angles );
SetLocalAngles( angles );
SetNextThink( gpGlobals->curtime + 0.1f );
StudioFrameAdvance( );
SetRenderColorA( flLifeLeft );
}
void CGrenadeEnergy::Event_Killed( const CTakeDamageInfo &info )
{
Detonate( );
}
void CGrenadeEnergy::GrenadeEnergyTouch( CBaseEntity *pOther )
{
if ( pOther->m_takedamage )
{
float flLifeLeft = 1-(gpGlobals->curtime - m_flLaunchTime)/ENERGY_GRENADE_LIFETIME;
if ( pOther->GetFlags() & (FL_CLIENT) )
{
CBasePlayer *pPlayer = ( CBasePlayer * )pOther;
float flKick = 120 * flLifeLeft;
pPlayer->m_Local.m_vecPunchAngle.SetX( flKick * (random->RandomInt(0,1) == 1) ? -1 : 1 );
pPlayer->m_Local.m_vecPunchAngle.SetY( flKick * (random->RandomInt(0,1) == 1) ? -1 : 1 );
}
float flDamage = m_flDamage * flLifeLeft;
if (flDamage < 1)
{
flDamage = 1;
}
trace_t tr;
tr = GetTouchTrace();
CTakeDamageInfo info( this, GetThrower(), m_flDamage * flLifeLeft, DMG_SONIC );
CalculateMeleeDamageForce( &info, (tr.endpos - tr.startpos), tr.endpos );
pOther->TakeDamage( info );
}
Detonate();
}
void CGrenadeEnergy::Detonate(void)
{
m_takedamage = DAMAGE_NO;
UTIL_Remove( this );
}
void CGrenadeEnergy::Precache( void )
{
engine->PrecacheModel("Models/weapons/w_energy_grenade.mdl");
}
А в другой это:
//=========== © Copyright 1999 Valve, L.L.C. All rights reserved. ===========
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
// Purpose: Projectile shot by mortar synth
//
// $Workfile: $
// $Date: $
//
//-----------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================
#ifndef GRENADEENERGY_H
#define GRENADEENERGY_H
#include "basegrenade_shared.h"
class CGrenadeEnergy : public CBaseGrenade
{
public:
DECLARE_CLASS( CGrenadeEnergy, CBaseGrenade );
static void Shoot( CBaseEntity* pOwner, const Vector &vStart, Vector vVelocity );
public:
void Spawn( void );
void Precache( void );
void Animate( void );
void GrenadeEnergyTouch( CBaseEntity *pOther );
void Event_Killed( const CTakeDamageInfo &info );
int m_flMaxFrame;
int m_nEnergySprite;
float m_flModelScale;
float m_flLaunchTime; // When was this thing launched
void EXPORT Detonate(void);
DECLARE_DATADESC();
};
#endif //GRENADEENERGY_H
Всё, ну теперь надо сделать класс для собаки, а то если не делать она будет тупо смотреть на всех и не нападать=) Так вот идём в файл baseentity.h и там находим строку:
//Class_Houndeye,
Засцетируем её что б было так:
//Class_Houndeye,
И этот файл можно закрывать. Теперь идем в эту папку (src/game_shared\hl2\hl2_gamerules.cpp) и там ищем строки:
// > CLASS_ANTLION
Это начало класса Антлиона, если спустится чуть ниже вы увидете такую строку:
//CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_HOUNDEYE, D_HT, 0);
Эта строка определяет отношение антлиона к нашей собаке, так что эту строку надо расцетировать. Далее так же спускаемя по всем классам и ищем такие же стоки и разцетируем всех их, кроме той которая в полностью зацетированном классе npc_bullsquid. Когда мы спускаемя до класса npc_houndeye его надо полностью разцетировать. Когда мы всё это сделали, то надо в этом же файле ищем строку:
//case CLASS_HOUNDEYE: return "CLASS_HOUNDEYE";
Её тоже надо разцетировать=) Всё с классом закончили, теперь нам надо доделать всё с эффектами в клиентовской части, так что добовляем в клиент часть (src/cl_dll/hl2_hud) 2 файла: 1)energy_wave_effect.cpp и 2)energy_wave_effect.h в первый вписываем вот этот код:
//=========== © Copyright 2000 Valve, L.L.C. All rights reserved. ===========
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
// Purpose: The EWave effect
//
// $Workfile: $
// $Date: $
//
//-----------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================
#include "cbase.h"
#include "energy_wave_effect.h"
//-----------------------------------------------------------------------------
// constructor, destructor
//-----------------------------------------------------------------------------
CEnergyWaveEffect::CEnergyWaveEffect( TraceLineFunc_t traceline,
TraceHullFunc_t traceHull ) :
CSheetSimulator(traceline, traceHull)
{
Init(EWAVE_NUM_HORIZONTAL_POINTS, EWAVE_NUM_VERTICAL_POINTS, EWAVE_NUM_CONTROL_POINTS);
}
//-----------------------------------------------------------------------------
// compute rest positions of the springs
//-----------------------------------------------------------------------------
void CEnergyWaveEffect::ComputeRestPositions()
{
int i;
// Set the initial directions and distances (in ewave space)...
for ( i = 0; i < EWAVE_NUM_VERTICAL_POINTS; ++i)
{
// Choose phi centered at pi/2
float phi = (M_PI - m_EWavePhi) * 0.5f + m_EWavePhi *
(float)i / (float)(EWAVE_NUM_VERTICAL_POINTS - 1);
for (int j = 0; j < EWAVE_NUM_HORIZONTAL_POINTS; ++j)
{
// Choose theta centered at pi/2 also (y, or forward axis)
float theta = (M_PI - m_EWaveTheta) * 0.5f + m_EWaveTheta *
(float)j / (float)(EWAVE_NUM_HORIZONTAL_POINTS - 1);
int idx = i * EWAVE_NUM_HORIZONTAL_POINTS + j;
GetFixedPoint(idx).x = cos(theta) * sin(phi) * m_RestDistance;
GetFixedPoint(idx).y = sin(theta) * sin(phi) * m_RestDistance;
GetFixedPoint(idx).z = cos(phi) * m_RestDistance;
}
}
// Compute box for fake volume testing
Vector dist = GetFixedPoint(0) - GetFixedPoint(1);
float l = dist.Length();
SetBoundingBox( Vector( -l * 0.25f, -l * 0.25f, -l * 0.25f),
Vector( l * 0.25f, l * 0.25f, l * 0.25f) );
}
void CEnergyWaveEffect::MakeSpring( int p1, int p2 )
{
Vector dist = GetFixedPoint(p1) - GetFixedPoint(p2);
AddSpring( p1, p2, dist.Length() );
}
void CEnergyWaveEffect::ComputeSprings()
{
// Do the main springs first
// Compute springs and rest lengths...
int i, j;
for ( i = 0; i < EWAVE_NUM_VERTICAL_POINTS; ++i)
{
for ( j = 0; j < EWAVE_NUM_HORIZONTAL_POINTS; ++j)
{
// Here's the particle we're making springs for
int idx = i * EWAVE_NUM_HORIZONTAL_POINTS + j;
// Make a spring connected to the control point
AddFixedPointSpring( idx, idx, 0.0f );
}
}
// Add four corner springs
MakeSpring( 0, 3 );
MakeSpring( 0, 12 );
MakeSpring( 12, 15 );
MakeSpring( 3, 15 );
}
//------------------------------------------------------------------------------
// Purpose : Overwrite. Energy wave does no collisions
// Input :
// Output :
//------------------------------------------------------------------------------
void CEnergyWaveEffect::DetectCollisions()
{
return;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CEnergyWaveEffect::Precache( void )
{
SetFixedSpringConstant( 200.0f );
SetPointSpringConstant( 0.5f );
SetSpringDampConstant( 10.0f );
SetViscousDrag( 0.25f );
m_RestDistance = 500.0;
m_EWaveTheta = M_PI * EWAVE_INITIAL_THETA / 180.0f;
m_EWavePhi = M_PI * EWAVE_INITIAL_PHI / 180.0f;
// Computes the rest positions
ComputeRestPositions();
// Computes the springs
ComputeSprings();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CEnergyWaveEffect::Spawn( void )
{
Precache();
}
//-----------------------------------------------------------------------------
// Computes the opacity....
//-----------------------------------------------------------------------------
float CEnergyWaveEffect::ComputeOpacity( const Vector& pt, const Vector& center ) const
{
float dist = pt.DistTo( center ) / m_RestDistance;
dist = sqrt(dist);
if (dist > 1.0)
dist = 1.0f;
return (1.0 - dist) * 35;
}
теперь во второй пишем это:
//========= Copyright © 1996-2001, Valve LLC, All rights reserved. ============
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#ifndef ENERGYWAVEEFFECT_H
#define ENERGYWAVEEFFECT_H
#ifdef _WIN32
#pragma once
#endif
#include "mathlib.h"
#include "Vector.h"
#include "UtlVector.h"
#include "SheetSimulator.h"
// --------------------------------------
// Energy wave defs
// --------------------------------------
enum
{
EWAVE_NUM_HORIZONTAL_POINTS = 10,
EWAVE_NUM_VERTICAL_POINTS = 10,
EWAVE_NUM_CONTROL_POINTS = EWAVE_NUM_HORIZONTAL_POINTS * EWAVE_NUM_VERTICAL_POINTS,
EWAVE_INITIAL_THETA = 135,
EWAVE_INITIAL_PHI = 135,
};
//-----------------------------------------------------------------------------
// Purpose: Energy Wave Effect
//-----------------------------------------------------------------------------
class CEnergyWaveEffect : public CSheetSimulator
{
public:
CEnergyWaveEffect( TraceLineFunc_t traceline, TraceHullFunc_t traceHull );
void Precache();
void Spawn();
// Computes the opacity....
float ComputeOpacity( const Vector& pt, const Vector& center ) const;
void DetectCollisions();
private:
CEnergyWaveEffect( const CEnergyWaveEffect & ); // not defined, not accessible
// Simulation set up
void ComputeRestPositions();
void MakeSpring( int p1, int p2 );
void ComputeSprings();
float m_RestDistance;
float m_EWaveTheta;
float m_EWavePhi;
};
#endif // ENERGYWAVEEFFECT_H
Всё, теперь проект можно компилить=) После того как скомпилили, идём в папку scripts в файл game_sounds_manifest.txt и где то перед:
"precache_file" "scripts/npc_sounds_eli.txt"
Вставим такую строку:
"precache_file" "scripts/npc_sounds_houndeye.txt"
Сохраняем этот файл и в этой же папке создаем текстовый документ под названием npc_sounds_houndeye.txt и туда вписываем всё это:
"NPC_Houndeye.Anger1"
{
"channel" "CHAN_VOICE"
"volume" "VOL_NORM"
"pitch" "PITCH_NORM"
"soundlevel" "SNDLVL_NORM"
"wave" "npc/houndeye/he_pain3.wav"
}
"NPC_Houndeye.Anger2"
{
"channel" "CHAN_VOICE"
"volume" "VOL_NORM"
"pitch" "PITCH_NORM"
"soundlevel" "SNDLVL_NORM"
"wave" "npc/houndeye/he_pain1.wav"
}
"NPC_Houndeye.SpeakSentence"
{
"channel" "CHAN_VOICE"
"volume" "VOL_NORM"
"pitch" "PITCH_NORM"
"soundlevel" "SNDLVL_NORM"
"wave" "npc/houndeye/he_bark_group_attack_reply.wav"
}
"NPC_Houndeye.Idle"
{
"channel" "CHAN_VOICE"
"volume" "VOL_NORM"
"pitch" "PITCH_NORM"
"soundlevel" "SNDLVL_NORM"
"rndwave"
{
"wave" "npc/houndeye/he_idle1.wav"
"wave" "npc/houndeye/he_idle2.wav"
"wave" "npc/houndeye/he_idle3.wav"
}
}
"NPC_Houndeye.WarmUp"
{
"channel" "CHAN_WEAPON"
"volume" "VOL_NORM"
"pitch" "PITCH_NORM"
"soundlevel" "SNDLVL_NORM"
"rndwave"
{
"wave" "npc/houndeye/he_attack1.wav"
"wave" "npc/houndeye/he_attack3.wav"
}
}
"NPC_Houndeye.Warn"
{
"channel" "CHAN_VOICE"
"volume" "VOL_NORM"
"pitch" "PITCH_NORM"
"soundlevel" "SNDLVL_NORM"
"rndwave"
{
"wave" "npc/houndeye/he_hunt1.wav"
"wave" "npc/houndeye/he_hunt2.wav"
"wave" "npc/houndeye/he_hunt3.wav"
}
}
"NPC_Houndeye.Alert"
{
"channel" "CHAN_VOICE"
"volume" "VOL_NORM"
"pitch" "PITCH_NORM"
"soundlevel" "SNDLVL_NORM"
"rndwave"
{
"wave" "npc/houndeye/he_alert2.wav"
"wave" "npc/houndeye/he_alert3.wav"
}
}
"NPC_Houndeye.Die"
{
"channel" "CHAN_VOICE"
"volume" "VOL_NORM"
"pitch" "PITCH_NORM"
"soundlevel" "SNDLVL_NORM"
"rndwave"
{
"wave" "npc/houndeye/he_die1.wav"
"wave" "npc/houndeye/he_die2.wav"
"wave" "npc/houndeye/he_die3.wav"
}
}
"NPC_Houndeye.Pain"
{
"channel" "CHAN_VOICE"
"volume" "VOL_NORM"
"pitch" "PITCH_NORM"
"soundlevel" "SNDLVL_NORM"
"rndwave"
{
"wave" "npc/houndeye/he_pain1.wav"
"wave" "npc/houndeye/he_pain3.wav"
"wave" "npc/houndeye/he_pain4.wav"
"wave" "npc/houndeye/he_pain5.wav"
}
}
"NPC_Houndeye.Retreat"
{
"channel" "CHAN_VOICE"
"volume" "VOL_NORM"
"pitch" "PITCH_NORM"
"soundlevel" "SNDLVL_NORM"
"wave" "npc/houndeye/he_bark_group_retreat.wav"
}
"NPC_Houndeye.SonicAttack"
{
"channel" "CHAN_WEAPON"
"volume" "VOL_NORM"
"pitch" "PITCH_NORM"
"soundlevel" "SNDLVL_NORM"
"rndwave"
{
"wave" "npc/houndeye/he_blast1.wav"
"wave" "npc/houndeye/he_blast2.wav"
"wave" "npc/houndeye/he_blast3.wav"
}
}
"NPC_Houndeye.GroupAttack"
{
"channel" "CHAN_VOICE"
"volume" "VOL_NORM"
"pitch" "PITCH_NORM"
"soundlevel" "SNDLVL_NORM"
"wave" "npc/houndeye/he_bark_group_attack.wav"
}
"NPC_Houndeye.GroupFollow"
{
"channel" "CHAN_VOICE"
"volume" "VOL_NORM"
"pitch" "PITCH_NORM"
"soundlevel" "SNDLVL_NORM"
"wave" "npc/houndeye/he_bark_group_run_follow.wav"
}
Сохраняем и качаем звуки к нашей собаке=) Кстате, модели в этот раз не будет, так как она для мода и я не имею права её вылаживать, но можно достать модель из хл1 сорс и мода субстеинс под Half-Life 2. На этом всё, надеюсь вы будите довольны новым монстром!