Статистика ( общая по моделям ), шт.
Играя в Халф-Лайф, вы не задумывались над тем, что в нем чего-то не хватает? Чего-то очень близкого, родного, горячего...
weapon_flamethrower
Играя в Халф-Лайф, вы не задумывались над тем, что в нем чего-то не хватает? Чего-то очень близкого, родного, горячего...
Автор / ы урока : Ghoul [BB] Просмотров : 3859 ( +1 ) Скачиваний : 0 Прислал / (а) : Streit Дата создания : 07.04.2011 20:36:58 Источник : http://www.half-life.ru/forum Рейтинг : ( 1 ) Поделиться :
Имеются следующие переводы : |
русский |
Играя в Халф-Лайф, вы не задумывались над тем, что в нем чего-то не хватает? Чего-то очень близкого,
родного, горячего… Представленные в игре виды оружия удовлетворят самый изощренный вкус - тут и стандартный
огнестрел, и переносная ракетница, и всевозможные энерго-экспериментальные футуристические пушки, и даже
такая экзотика, как биооружие Чужих… Но ЭТОГО еще не было!
Знакомьтесь: ОГНЕМЕТ! Огнемет это - друг пожарников, пироманов и просто тех, кому стало слишком холодно.
Ниже приведена подробная инструкция по кодингу и дальнейшей эксплуатации сего девайса!
Итак, начнем.
Сначала создадим сам "огонь":
Клиентная часть.
cl_dll/hl/hl_baseentity.cpp
Ищем:
// CGrenade Stubs
void CGrenade::BounceSound( void ) { }
// CFlame
void CFlame::BounceSound( void ) { }
void CFlame::Explode( Vector, Vector ) { }
void CFlame::Explode( TraceResult *, int ) { }
void CFlame::Killed( entvars_t *, int ) { }
void CFlame::Spawn( void ) { }
CFlame*CFlame::ShootFlame( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity ){ return 0; }
Переходим теперь к серверной части (т.е. dlls)
Откроем файл weapons.h
И найдем:
class CGrenade : public CBaseMonster
{
public:
void Spawn( void );
Добавим после этого класса ( после }; ):
class CFlame : public CBaseMonster
{
public:
static CFlame *ShootFlame( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity );
void Spawn( void );
void Explode( Vector vecSrc, Vector vecAim );
void Explode( TraceResult *pTrace, int bitsDamageType );
void EXPORT Smoke( void );
void EXPORT BounceTouch( CBaseEntity *pOther );
void EXPORT SlideTouch( CBaseEntity *pOther );
void EXPORT ExplodeTouch( CBaseEntity *pOther );
void EXPORT DangerSoundThink( void );
void EXPORT PreDetonate( void );
void EXPORT Detonate( void );
void EXPORT DetonateUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
virtual void BounceSound( void );
virtual int BloodColor( void ) { return DONT_BLEED; }
virtual void Killed( entvars_t *pevAttacker, int iGib );
BOOL m_fRegisteredSound;
};
Регистрация ресурсов:
В weapons.cpp найдем:
DLL_GLOBAL short g_sModelIndexFireball;// holds the index for the fireball
DLL_GLOBAL short g_sModelIndexFlame;// Flamethrower flame
g_sModelIndexFireball = PRECACHE_MODEL ("sprites/zerogxplode.spr");// fireball
g_sModelIndexFlame = PRECACHE_MODEL ("sprites/flame.spr");// Flamethrower
Теперь откроем weapons.h и найдем:
extern DLL_GLOBAL short g_sModelIndexFireball;// holds the index for the fireball
extern DLL_GLOBAL short g_sModelIndexFlame;// flame
С регистрацией огня, вроде, все.
Создадим новую переменную для skill.cfg, указывающую на ущерб огнемета.
Откроем game.cpp и найдем:
// RPG
cvar_t sk_plr_rpg1 = {"sk_plr_rpg1","0"};
cvar_t sk_plr_rpg2 = {"sk_plr_rpg2","0"};
cvar_t sk_plr_rpg3 = {"sk_plr_rpg3","0"};
// Flamethrower
cvar_t sk_plr_flamethrower1 = {"sk_plr_flamethrower1","0"};
cvar_t sk_plr_flamethrower2 = {"sk_plr_flamethrower2","0"};
cvar_t sk_plr_flamethrower3 = {"sk_plr_flamethrower3","0"};
В этом же файле ниже найдем:
// RPG
CVAR_REGISTER ( &sk_plr_rpg1 );
CVAR_REGISTER ( &sk_plr_rpg2 );
CVAR_REGISTER ( &sk_plr_rpg3 );
//Flamethrower
CVAR_REGISTER ( &sk_plr_flamethrower1 );
CVAR_REGISTER ( &sk_plr_flamethrower2 );
CVAR_REGISTER ( &sk_plr_flamethrower3 );
Все. Открываем gamerules.cpp и ищем:
// RPG
gSkillData.plrDmgRPG = GetSkillCvar( "sk_plr_rpg");
//flamethrower
gSkillData.plrDmgFlamethrower = GetSkillCvar( "sk_plr_flamethrower");
Все. Теперь обратим наш взор на skill.h, где найдем строку:
float plrDmgFlamethrower;
С регистрацией все. Теперь осталось открыть skill.cfg и вставить:
// Flamethrower
sk_plr_flamethrower1 "12"
sk_plr_flamethrower2 "12"
sk_plr_flamethrower3 "12"
(не думайте, что 12 ущерба - это мало, ибо огнемет у нас будет стрелять сразу 6 сгустками вот такого огня…)
Теперь регистрируем новый тип боеприпасов:
В cbase.h ищем:
Переходим в client.cpp и ищем:
cd->ammo_rockets = pl->ammo_rockets;
cd->vuser1.y = pl->ammo_fuel;
Напоследок переходим в player.cpp, где найдем:
ammo_rockets = AmmoInventory( GetAmmoIndex( "rockets" ) );
ammo_fuel = AmmoInventory( GetAmmoIndex( "fuel" ) );
Напоследок не забываем заглянуть в weapons.h, где объявляем новое количество боезапаса:
Ищем:
#define ROCKET_MAX_CARRY 5
#define _FUEL_MAX_CARRY 250
Теперь переходим к самому главному - регистрации нового класса оружия. Остаемся в файле weapons.h, где находим:
#define WEAPON_flamethrower 16
Чуть ниже ставим вес оружия, ищем:
#define FLAMETHROWER_WEIGHT 40
Теперь переходим к weapons.cpp, где ищем:
// gauss
UTIL_PrecacheOtherWeapon( "weapon_gauss" );
UTIL_PrecacheOther( "ammo_gaussclip" );
// Flamethrower
UTIL_PrecacheOtherWeapon( "weapon_flamethrower" );
UTIL_PrecacheOther( "ammo_fuel" );
Можно добавить еще в player.cpp, после:
GiveNamedItem( "weapon_357" );
GiveNamedItem( "weapon_flamethrower" );
Это с читом импульс 101 даем огнемет.
Ну вот. Теперь главное - код пламени:
создадим файл и обзовем его flame.cpp:
#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "monsters.h"
#include "weapons.h"
#include "nodes.h"
#include "soundent.h"
#include "decals.h"
LINK_ENTITY_TO_CLASS( flamethrower_flame, CFlame );
void CFlame::Explode( Vector vecSrc, Vector vecAim )
{
TraceResult tr;
UTIL_TraceLine ( pev->origin, pev->origin + Vector ( 0, 0, -32 ), ignore_monsters, ENT(pev), & tr);
Explode( &tr, DMG_BURN );
}
void CFlame::Explode( TraceResult *pTrace, int bitsDamageType )
{
float flRndSound;
pev->model = iStringNull;
pev->solid = SOLID_NOT;
pev->takedamage = DAMAGE_NO;
// Pull out of the wall a bit
if ( pTrace->flFraction != 1.0 )
{
pev->origin = pTrace->vecEndPos + (pTrace->vecPlaneNormal * 60);
}
int iContents = UTIL_PointContents ( pev->origin );
MESSAGE_BEGIN( MSG_PAS, SVC_TEMPENTITY, pev->origin );
WRITE_BYTE( TE_EXPLOSION );
WRITE_COORD( pev->origin.x );
WRITE_COORD( pev->origin.y );
WRITE_COORD( pev->origin.z );
WRITE_SHORT( g_sModelIndexFlame );
WRITE_BYTE( 10 );
WRITE_BYTE( 15 );
WRITE_BYTE( TE_EXPLFLAG_NOSOUND );
MESSAGE_END();
MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, pev->origin );
WRITE_BYTE( TE_DLIGHT );
WRITE_COORD( pev->origin.x );
WRITE_COORD( pev->origin.y );
WRITE_COORD( pev->origin.z );
WRITE_BYTE( 50 );
WRITE_BYTE( 220 );
WRITE_BYTE( 150 );
WRITE_BYTE( 0 );
WRITE_BYTE( 10 );
WRITE_BYTE( 10 );
MESSAGE_END();
CSoundEnt::InsertSound ( bits_SOUND_COMBAT, pev->origin, BIG_EXPLOSION_VOLUME, 3.0 );
entvars_t *pevOwner;
if ( pev->owner )
pevOwner = VARS( pev->owner );
else
pevOwner = NULL;
pev->owner = NULL;
::RadiusDamage( pev->origin, pev, pevOwner, pev->dmg, 175, CLASS_NONE, DMG_BURN );
if ( RANDOM_FLOAT( 0 , 1 ) < 0.5 )
{
UTIL_DecalTrace( pTrace, DECAL_SMALLSCORCH1 );
}
else
{
UTIL_DecalTrace( pTrace, DECAL_SMALLSCORCH3 );
}
flRndSound = RANDOM_FLOAT( 0 , 1 );
EMIT_SOUND(ENT(pev), CHAN_VOICE, "weapons/flame_hitwall.wav", 0.55, ATTN_NORM);
pev->effects |= EF_NODRAW;
pev->velocity = g_vecZero;
SetThink( Smoke );
pev->nextthink = gpGlobals->time + 0.1;
}
void CFlame::Smoke( void )
{
if (UTIL_PointContents ( pev->origin ) == CONTENTS_WATER)
{
UTIL_Bubbles( pev->origin - Vector( 64, 64, 64 ), pev->origin + Vector( 64, 64, 64 ), 100 );
}
else
{
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 );
WRITE_SHORT( g_sModelIndexSmoke );
WRITE_BYTE( 10 );
WRITE_BYTE( 6 );
MESSAGE_END();
}
UTIL_Remove( this );
}
void CFlame::Killed( entvars_t *pevAttacker, int iGib )
{
Detonate( );
}
void CFlame::DetonateUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
SetThink( Detonate );
pev->nextthink = gpGlobals->time;
}
void CFlame::PreDetonate( void )
{
CSoundEnt::InsertSound ( bits_SOUND_DANGER, pev->origin, 400, 0.3 );
SetThink( Detonate );
pev->nextthink = gpGlobals->time + 1;
}
void CFlame::Detonate( void )
{
TraceResult tr;
Vector vecSpot;
vecSpot = pev->origin + Vector ( 0 , 0 , 8 );
UTIL_TraceLine ( vecSpot, vecSpot + Vector ( 0, 0, -40 ), ignore_monsters, ENT(pev), & tr);
Explode( &tr, DMG_BURN );
}
void CFlame::ExplodeTouch( CBaseEntity *pOther )
{
TraceResult tr;
Vector vecSpot;
pev->enemy = pOther->edict();
vecSpot = pev->origin - pev->velocity.Normalize() * 32;
UTIL_TraceLine( vecSpot, vecSpot + pev->velocity.Normalize() * 64, ignore_monsters, ENT(pev), &tr );
Explode( &tr, DMG_BURN );
}
void CFlame::DangerSoundThink( void )
{
if (!IsInWorld())
{
UTIL_Remove( this );
return;
}
CSoundEnt::InsertSound ( bits_SOUND_DANGER, pev->origin + pev->velocity * 0.5, pev->velocity.Length( ), 0.2 );
pev->nextthink = gpGlobals->time + 0.2;
if (pev->waterlevel != 0)
{
pev->velocity = pev->velocity * 0.5;
}
}
void CFlame::BounceTouch( CBaseEntity *pOther )
{
if ( pOther->edict() == pev->owner )
return;
if (m_flNextAttack < gpGlobals->time && pev->velocity.Length() > 100)
{
entvars_t *pevOwner = VARS( pev->owner );
if (pevOwner)
{
TraceResult tr = UTIL_GetGlobalTrace( );
ClearMultiDamage( );
pOther->TraceAttack(pevOwner, 1, gpGlobals->v_forward, &tr, DMG_CLUB );
ApplyMultiDamage( pev, pevOwner);
}
m_flNextAttack = gpGlobals->time + 1.0;
}
Vector vecTestVelocity;
vecTestVelocity = pev->velocity;
vecTestVelocity.z *= 0.45;
if ( !m_fRegisteredSound && vecTestVelocity.Length() <= 60 )
{
CSoundEnt::InsertSound ( bits_SOUND_DANGER, pev->origin, pev->dmg / 0.4, 0.3 );
m_fRegisteredSound = TRUE;
}
if (pev->flags & FL_ONGROUND)
{
pev->velocity = pev->velocity * 0.8;
pev->sequence = RANDOM_LONG( 1, 1 );
}
else
{
BounceSound();
}
pev->framerate = pev->velocity.Length() / 200.0;
if (pev->framerate > 1.0)
pev->framerate = 1;
else if (pev->framerate < 0.5)
pev->framerate = 0;
}
void CFlame::SlideTouch( CBaseEntity *pOther )
{
if ( pOther->edict() == pev->owner )
return;
if (pev->flags & FL_ONGROUND)
{
pev->velocity = pev->velocity * 0.95;
if (pev->velocity.x != 0 || pev->velocity.y != 0)
{
}
}
else
{
BounceSound();
}
}
void CFlame :: BounceSound( void )
{
EMIT_SOUND(ENT(pev), CHAN_VOICE, "weapons/flame_hitwall.wav", 0.25, ATTN_NORM);
}
void CFlame:: Spawn( void )
{
pev->movetype = MOVETYPE_BOUNCE;
pev->classname = MAKE_STRING( "flamethrower_flame" );
pev->solid = SOLID_BBOX;
SET_MODEL(ENT(pev), "sprites/flamesteam.spr");
pev->rendermode = kRenderTransAdd;
pev->rendercolor.x = 255;
pev->rendercolor.y = 255;
pev->rendercolor.z = 255;
pev->renderamt = 255;
if ( RANDOM_FLOAT( 0 , 1 ) < 0.5 )
{
pev->scale = 1;
}
else
{
pev->scale = 2;
}
UTIL_SetSize(pev, Vector ( 0, 0, 0 ), Vector ( 0, 0, 0 ) );
pev->dmg = gSkillData.plrDmgFlamethrower;
m_fRegisteredSound = FALSE;
}
CFlame *CFlame::ShootFlame( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity )
{
CFlame *pFlame = GetClassPtr( (CFlame *)NULL );
pFlame->Spawn();
pFlame->pev->gravity = 1.5;
UTIL_SetOrigin( pFlame->pev, vecStart );
pFlame->pev->velocity = vecVelocity;
pFlame->pev->angles = UTIL_VecToAngles (pFlame->pev->velocity);
pFlame->pev->owner = ENT(pevOwner);
pFlame->SetThink( DangerSoundThink );
pFlame->pev->nextthink = gpGlobals->time;
pFlame->SetTouch( ExplodeTouch );
pFlame->pev->dmg = gSkillData.plrDmgFlamethrower;
return pFlame;
}
Теперь с самим огнеметом:
Создадим flamethrower.cpp
#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"
enum flamethrower_e
{
FLAMETHROWER_LONGIDLE,
FLAMETHROWER_IDLE1,
FLAMETHROWER_RELOAD,
FLAMETHROWER_DEPLOY,
FLAMETHROWER_HOLSTER,
FLAMETHROWER_SHOOT,
};
class CFLAMETHROWER : 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 );
BOOL Deploy( void );
void Holster( int skiplocal = 0 );
void Reload( void );
void WeaponIdle( void );
float m_flNextAnimTime;
};
LINK_ENTITY_TO_CLASS( weapon_flamethrower, CFLAMETHROWER );
void CFLAMETHROWER::Spawn( )
{
pev->classname = MAKE_STRING("weapon_flamethrower");
Precache( );
SET_MODEL(ENT(pev), "models/w_flamethrower.mdl");
m_iId = WEAPON_flamethrower;
m_iDefaultAmmo = 100;
FallInit();
}
void CFLAMETHROWER::Precache( void )
{
PRECACHE_MODEL("models/v_flamethrower.mdl");
PRECACHE_MODEL("models/w_flamethrower.mdl");
PRECACHE_MODEL("models/p_flamethrower.mdl");
PRECACHE_MODEL("sprites/flamesteam.spr");
PRECACHE_MODEL("models/w_flamefuel.mdl");
PRECACHE_SOUND("items/9mmclip1.wav");
PRECACHE_SOUND("weapons/flamethrower_reload.wav");
PRECACHE_SOUND("weapons/flame_hitwall.wav");
PRECACHE_SOUND("items/clipinsert1.wav");
PRECACHE_SOUND("items/cliprelease1.wav");
PRECACHE_SOUND ("weapons/flamethrower.wav");
PRECACHE_SOUND ("weapons/357_cock1.wav");
m_flNextPrimaryAttack = gpGlobals->time + 0.5;
}
int CFLAMETHROWER::GetItemInfo(ItemInfo *p)
{
p->pszName = STRING(pev->classname);
p->pszAmmo1 = "fuel";
p->iMaxAmmo1 = _FUEL_MAX_CARRY;
p->pszAmmo2 = NULL;
p->iMaxAmmo2 = -1;
p->iMaxClip = 100;
p->iSlot = 4;
p->iPosition = 4;
p->iFlags = 0;
p->iId = m_iId = WEAPON_flamethrower;
p->iWeight = FLAMETHROWER_WEIGHT;
return 1;
}
int CFLAMETHROWER::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;
}
BOOL CFLAMETHROWER::Deploy( )
{
return DefaultDeploy( "models/v_flamethrower.mdl", "models/p_flamethrower.mdl", FLAMETHROWER_DEPLOY, "mp5" );
}
void CFLAMETHROWER::Holster( int skiplocal )
{
SendWeaponAnim( FLAMETHROWER_HOLSTER );
}
void CFLAMETHROWER::PrimaryAttack( void )
{
if (m_pPlayer->pev->waterlevel == 3)
{
PlayEmptySound( );
m_flNextPrimaryAttack = gpGlobals->time + 0.15;
return;
}
if (m_iClip <= 0)
{
PlayEmptySound();
m_flNextPrimaryAttack = 0.15;
return;
}
m_pPlayer->m_iWeaponVolume = NORMAL_GUN_VOLUME;
m_pPlayer->m_iWeaponFlash = NORMAL_GUN_FLASH;
m_iClip--;
SendWeaponAnim( FLAMETHROWER_SHOOT );
m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/flamethrower.wav", 0.8, ATTN_NORM);
UTIL_MakeVectors( m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle );
CFlame::ShootFlame( m_pPlayer->pev,
m_pPlayer->pev->origin + m_pPlayer->pev->view_ofs + gpGlobals->v_forward * 16 + gpGlobals->v_right * 5 + gpGlobals->v_up * -10,
gpGlobals->v_forward * 900 );
CFlame::ShootFlame( m_pPlayer->pev,
m_pPlayer->pev->origin + m_pPlayer->pev->view_ofs + gpGlobals->v_forward * 16 + gpGlobals->v_right * 10 + gpGlobals->v_up * -15,
gpGlobals->v_forward * 920 );
CFlame::ShootFlame( m_pPlayer->pev,
m_pPlayer->pev->origin + m_pPlayer->pev->view_ofs + gpGlobals->v_forward * 24 + gpGlobals->v_right * 15 + gpGlobals->v_up * -20,
gpGlobals->v_forward * 940 );
CFlame::ShootFlame( m_pPlayer->pev,
m_pPlayer->pev->origin + m_pPlayer->pev->view_ofs + gpGlobals->v_forward * 24 + gpGlobals->v_right * 5 + gpGlobals->v_up * -10,
gpGlobals->v_forward * 960 );
CFlame::ShootFlame( m_pPlayer->pev,
m_pPlayer->pev->origin + m_pPlayer->pev->view_ofs + gpGlobals->v_forward * 32 + gpGlobals->v_right * 10 + gpGlobals->v_up * -15,
gpGlobals->v_forward * 980 );
CFlame::ShootFlame( m_pPlayer->pev,
m_pPlayer->pev->origin + m_pPlayer->pev->view_ofs + gpGlobals->v_forward * 32 + gpGlobals->v_right * 15 + gpGlobals->v_up * -20,
gpGlobals->v_forward * 1000 );
MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, pev->origin );
WRITE_BYTE( TE_DLIGHT );
WRITE_COORD( pev->origin.x );
WRITE_COORD( pev->origin.y );
WRITE_COORD( pev->origin.z );
WRITE_BYTE( 75 );
WRITE_BYTE( 128 );
WRITE_BYTE( 128 );
WRITE_BYTE( 0 );
WRITE_BYTE( 5 );
WRITE_BYTE( 10 );
MESSAGE_END();
m_flNextPrimaryAttack = gpGlobals->time + 0.1;
m_flTimeWeaponIdle = gpGlobals->time + 5;
m_pPlayer->pev->punchangle.x -= 1;
}
void CFLAMETHROWER::Reload( void )
{
int iResult;
if ( m_iClip == 100 )
{
m_flNextPrimaryAttack = gpGlobals->time + 0.5;
return;
}
if (m_iClip == 0)
{
iResult = DefaultReload( 100, FLAMETHROWER_RELOAD, 4.3 );
EMIT_SOUND(ENT(pev), CHAN_ITEM, "weapons/flamethrower_reload.wav", 1, ATTN_NORM);
}
if (iResult)
{
m_flTimeWeaponIdle = gpGlobals->time + RANDOM_FLOAT ( 10, 15 );
}
}
void CFLAMETHROWER::WeaponIdle( void )
{
ResetEmptySound( );
m_pPlayer->GetAutoaimVector( AUTOAIM_5DEGREES );
if (m_flTimeWeaponIdle > gpGlobals->time)
return;
int iAnim;
switch ( RANDOM_LONG( 0, 1 ) )
{
case 0:
iAnim = FLAMETHROWER_IDLE1;
break;
default:
case 1:
iAnim = FLAMETHROWER_LONGIDLE;
break;
}
SendWeaponAnim( iAnim );
m_flTimeWeaponIdle = gpGlobals->time + RANDOM_FLOAT ( 10, 15 );
}
class CFLAMETHROWERAmmo : public CBasePlayerAmmo
{
void Spawn( void )
{
Precache( );
SET_MODEL(ENT(pev), "models/w_flamefuel.mdl");
CBasePlayerAmmo::Spawn( );
}
void Precache( void )
{
PRECACHE_MODEL ("models/w_flamefuel.mdl");
PRECACHE_SOUND("items/9mmclip1.wav");
}
BOOL AddAmmo( CBaseEntity *pOther )
{
int bResult = (pOther->GiveAmmo( 50, "fuel", _FUEL_MAX_CARRY ) != -1);
if (bResult)
{
EMIT_SOUND(ENT(pev), CHAN_ITEM, "items/9mmclip1.wav", 1, ATTN_NORM);
}
return bResult;
}
};
LINK_ENTITY_TO_CLASS( ammo_fuel, CFLAMETHROWERAmmo );
В следующем файле - все необходимые ресурсы - модели, спрайты, etc.
З.Ы. Не судите строго, если я что забыл сюда написать или чего-то криво объяснил…
Примечание редактора: Внимание! Компилировать клиент нужно только после компиляции сервера! Т.е. в первой части надо просто внести изменения на клиенте и сохранить их, иначе будут ошибки типа: error C2653: CFlame : is not a class or namespace name.
Похожие 1. Создание нового ствола - Создание нового ствола с новыми патронами 2. Фикс: func_healthcharger - Фикс: func_healthcharger и func_recharger 3. Создание сценариев - Для создания сценариев (aka скриптов) в Half-Life существуют две энтити: scripted_sequence и scripted_sentence. Первая отвечает за движения, выполняемые монстром/персонажем, будь то ходьба, бег, нажатие кнопки, тряска автомата с газировкой или почёсывание подбородка. Вторая служит для того, чтобы персонаж произнес какую-то фразу. При этом его голова повернётся в сторону слушателя, и рот будет открываться в соответствии с амплитудой звука.
Вы не можете комментировать, т.к. вы не зарегистрированы.