Fena
(TRADITIONAL SKINHEAD)
Зарегистрирован: Sep 2003
Проживает: Russian Federation/Moscow
Написал: 227 сообщений
Оценка: 16 чел.
|
[Coding]: FlashBand в вашем моде (и не только! см. тему)
Добрый день! И так... сегодня я вам раааскажу как сделать мммм световоую гранату (FlashBang) (1) и покажу пример смены суток (2). Яб конечно дал вам всего прау строк.. но думаю не все додумаюцца куда их вставлять... поэтому опишу создание гранаты с 0...
(1)
И так... приступим.... создадим файлик на сервере (HL2 DLL) например weapon_flashbang... в нём напишем:
Fena добавил 14-03-2005 в 12:14:16:
code:
#include "player.h"
#include "gamerules.h"
#include "grenade_flash.h"
#include "npcevent.h"
#include "engine/IEngineSound.h"
#include "items.h"
#include "in_buttons.h"
#include "cbase.h"
#include "NPCEvent.h"
#include "basehlcombatweapon.h"
#include "soundent.h"
#include "ieffects.h"
#include "vstdlib/random.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#define GRENADE_TIMER 3.0f //Seconds
#define GRENADE_PAUSED_NO 0
#define GRENADE_PAUSED_PRIMARY 1
#define GRENADE_PAUSED_SECONDARY 2
#define GRENADE_RADIUS 4.0f // inches
//-----------------------------------------------------------------------------
// Fragmentation grenades
//-----------------------------------------------------------------------------
class CWeaponFlash: public CBaseHLCombatWeapon
{
DECLARE_CLASS( CWeaponFlash, CBaseHLCombatWeapon );
public:
DECLARE_SERVERCLASS();
virtual float GetFireRate( void ) { return 1; };
void Precache( void );
void Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator );
void PrimaryAttack( void );
void SecondaryAttack( void );
void DecrementAmmo( CBaseCombatCharacter *pOwner );
void ItemPostFrame( void );
bool Deploy( void );
bool Holster( CBaseCombatWeapon *pSwitchingTo = NULL );
int CapabilitiesGet( void ) { return bits_CAP_WEAPON_RANGE_ATTACK1; }
bool Reload( void );
private:
void ThrowGrenade( CBasePlayer *pPlayer );
void RollGrenade( CBasePlayer *pPlayer );
void LobGrenade( CBasePlayer *pPlayer );
// check a throw from vecSrc. If not valid, move the position back along the line to vecEye
void CheckThrowPosition( CBasePlayer *pPlayer, const Vector &vecEye, Vector &vecSrc );
bool m_bRedraw; //Draw the weapon again after throwing a grenade
int m_AttackPaused;
bool m_fDrawbackFinished;
DECLARE_ACTTABLE();
DECLARE_DATADESC();
};
BEGIN_DATADESC( CWeaponFlash )
DEFINE_FIELD( m_bRedraw, FIELD_BOOLEAN ),
DEFINE_FIELD( m_AttackPaused, FIELD_INTEGER ),
DEFINE_FIELD( m_fDrawbackFinished, FIELD_BOOLEAN ),
END_DATADESC()
acttable_t CWeaponFlash::m_acttable[] =
{
{ ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_SLAM, true },
};
IMPLEMENT_ACTTABLE(CWeaponFlash);
IMPLEMENT_SERVERCLASS_ST(CWeaponFlash, DT_WeaponFlash)
END_SEND_TABLE()
LINK_ENTITY_TO_CLASS( weapon_flash, CWeaponFlash );
PRECACHE_WEAPON_REGISTER(weapon_flash);
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CWeaponFlash::Precache( void )
{
BaseClass::Precache();
UTIL_PrecacheOther( "npc_grenade_flash" );
PrecacheScriptSound( "WeaponFlash.Throw" );
PrecacheScriptSound( "WeaponFlash.Roll" );
m_bRedraw = false;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CWeaponFlash:eploy( void )
{
m_bRedraw = false;
m_fDrawbackFinished = false;
return BaseClass:eploy();
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CWeaponFlash::Holster( CBaseCombatWeapon *pSwitchingTo )
{
m_bRedraw = false;
m_fDrawbackFinished = false;
return BaseClass::Holster( pSwitchingTo );
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pEvent -
// *pOperator -
//-----------------------------------------------------------------------------
void CWeaponFlash::Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator )
{
CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
bool fThrewGrenade = false;
switch( pEvent->event )
{
case EVENT_WEAPON_SEQUENCE_FINISHED:
m_fDrawbackFinished = true;
break;
case EVENT_WEAPON_THROW:
ThrowGrenade( pOwner );
DecrementAmmo( pOwner );
fThrewGrenade = true;
break;
case EVENT_WEAPON_THROW2:
RollGrenade( pOwner );
DecrementAmmo( pOwner );
fThrewGrenade = true;
break;
case EVENT_WEAPON_THROW3:
LobGrenade( pOwner );
DecrementAmmo( pOwner );
fThrewGrenade = true;
break;
default:
BaseClass::Operator_HandleAnimEvent( pEvent, pOperator );
break;
}
#define RETHROW_DELAY 0.5
if( fThrewGrenade )
{
m_flNextPrimaryAttack = gpGlobals->curtime + RETHROW_DELAY;
m_flNextSecondaryAttack = gpGlobals->curtime + RETHROW_DELAY;
m_flTimeWeaponIdle = FLT_MAX; //NOTE: This is set once the animation has finished up!
// Make a sound designed to scare snipers back into their holes!
CBaseCombatCharacter *pOwner = GetOwner();
if( pOwner )
{
Vector vecSrc = pOwner->Weapon_ShootPosition();
Vector vecDir;
AngleVectors( pOwner->EyeAngles(), &vecDir );
trace_t tr;
UTIL_TraceLine( vecSrc, vecSrc + vecDir * 1024, MASK_SOLID_BRUSHONLY, pOwner, COLLISION_GROUP_NONE, &tr );
CSoundEnt::InsertSound( SOUND_DANGER_SNIPERONLY, tr.endpos, 384, 0.2, pOwner );
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CWeaponFlash::Reload( void )
{
if ( !HasPrimaryAmmo() )
return false;
if ( ( m_bRedraw ) && ( m_flNextPrimaryAttack <= gpGlobals->curtime ) && ( m_flNextSecondaryAttack <= gpGlobals->curtime ) )
{
//Redraw the weapon
SendWeaponAnim( ACT_VM_DRAW );
//Update our times
m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration();
m_flNextSecondaryAttack = gpGlobals->curtime + SequenceDuration();
m_flTimeWeaponIdle = gpGlobals->curtime + SequenceDuration();
//Mark this as done
m_bRedraw = false;
}
return true;
}
см далее >
Fena добавил 14-03-2005 в 12:15:29:
code://-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CWeaponFlash::SecondaryAttack( void )
{
if ( m_bRedraw )
return;
if ( !HasPrimaryAmmo() )
return;
CBaseCombatCharacter *pOwner = GetOwner();
if ( pOwner == NULL )
return;
CBasePlayer *pPlayer = ToBasePlayer( pOwner );
if ( pPlayer == NULL )
return;
// Note that this is a secondary attack and prepare the grenade attack to pause.
m_AttackPaused = GRENADE_PAUSED_SECONDARY;
SendWeaponAnim( ACT_VM_PULLBACK_LOW );
// Don't let weapon idle interfere in the middle of a throw!
m_flTimeWeaponIdle = FLT_MAX;
m_flNextSecondaryAttack = FLT_MAX;
// If I'm now out of ammo, switch away
if ( !HasPrimaryAmmo() )
{
pPlayer->SwitchToNextBestWeapon( this );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CWeaponFlash::PrimaryAttack( void )
{
if ( m_bRedraw )
return;
CBaseCombatCharacter *pOwner = GetOwner();
if ( pOwner == NULL )
{
return;
}
CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );;
if ( !pPlayer )
return;
// Note that this is a primary attack and prepare the grenade attack to pause.
m_AttackPaused = GRENADE_PAUSED_PRIMARY;
SendWeaponAnim( ACT_VM_PULLBACK_HIGH );
// Put both of these off indefinitely. We do not know how long
// the player will hold the grenade.
m_flTimeWeaponIdle = FLT_MAX;
m_flNextPrimaryAttack = FLT_MAX;
// If I'm now out of ammo, switch away
if ( !HasPrimaryAmmo() )
{
pPlayer->SwitchToNextBestWeapon( this );
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pOwner -
//-----------------------------------------------------------------------------
void CWeaponFlash:ecrementAmmo( CBaseCombatCharacter *pOwner )
{
pOwner->RemoveAmmo( 1, m_iPrimaryAmmoType );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CWeaponFlash::ItemPostFrame( void )
{
if( m_fDrawbackFinished )
{
CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
if (pOwner)
{
switch( m_AttackPaused )
{
case GRENADE_PAUSED_PRIMARY:
if( !(pOwner->m_nButtons & IN_ATTACK) )
{
SendWeaponAnim( ACT_VM_THROW );
m_fDrawbackFinished = false;
}
break;
case GRENADE_PAUSED_SECONDARY:
if( !(pOwner->m_nButtons & IN_ATTACK2) )
{
//See if we're ducking
if ( pOwner->m_nButtons & IN_DUCK )
{
//Send the weapon animation
SendWeaponAnim( ACT_VM_SECONDARYATTACK );
}
else
{
//Send the weapon animation
SendWeaponAnim( ACT_VM_HAULBACK );
}
m_fDrawbackFinished = false;
}
break;
default:
break;
}
}
}
BaseClass::ItemPostFrame();
if ( m_bRedraw )
{
if ( IsViewModelSequenceFinished() )
{
Reload();
}
}
}
// check a throw from vecSrc. If not valid, move the position back along the line to vecEye
void CWeaponFlash::CheckThrowPosition( CBasePlayer *pPlayer, const Vector &vecEye, Vector &vecSrc )
{
trace_t tr;
UTIL_TraceHull( vecEye, vecSrc, -Vector(GRENADE_RADIUS+2,GRENADE_RADIUS+2,GRENADE_RADIUS+2), Vector(GRENADE_RADIUS+2,GRENADE_RADIUS+2,GRENADE_RADIUS+2),
pPlayer->PhysicsSolidMaskForEntity(), pPlayer, pPlayer->GetCollisionGroup(), &tr );
if ( tr.DidHit() )
{
vecSrc = tr.endpos;
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pPlayer -
//-----------------------------------------------------------------------------
void CWeaponFlash::ThrowGrenade( CBasePlayer *pPlayer )
{
Vector vecEye = pPlayer->EyePosition();
Vector vForward, vRight;
pPlayer->EyeVectors( &vForward, &vRight, NULL );
Vector vecSrc = vecEye + vForward * 18.0f + vRight * 8.0f;
CheckThrowPosition( pPlayer, vecEye, vecSrc );
// vForward[0] += 0.1f;
vForward[2] += 0.1f;
Vector vecThrow;
pPlayer->GetVelocity( &vecThrow, NULL );
vecThrow += vForward * 1200;
Flashgrenade_Create( vecSrc, vec3_angle, vecThrow, AngularImpulse(600,random->RandomInt(-1200,1200),0), pPlayer, GRENADE_TIMER );
pPlayer->ViewPunch( QAngle(random->RandomFloat( -5, 10 ),0,0) );
// CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
/*CFlare *pFlare = CFlare::Create( pOwner->Weapon_ShootPosition(), pOwner->EyeAngles(), pOwner, FLARE_DURATION );
Vector forward;
pOwner->EyeVectors( &forward );
pFlare->SetAbsVelocity( forward * 700 );
if ( pFlare == NULL )
return;
*/
m_bRedraw = true;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pPlayer -
//-----------------------------------------------------------------------------
void CWeaponFlash::LobGrenade( CBasePlayer *pPlayer )
{
Vector vecEye = pPlayer->EyePosition();
Vector vForward, vRight;
pPlayer->EyeVectors( &vForward, &vRight, NULL );
Vector vecSrc = vecEye + vForward * 18.0f + vRight * 8.0f + Vector( 0, 0, -8 );
CheckThrowPosition( pPlayer, vecEye, vecSrc );
Vector vecThrow;
pPlayer->GetVelocity( &vecThrow, NULL );
vecThrow += vForward * 350 + Vector( 0, 0, 50 );
Flashgrenade_Create( vecSrc, vec3_angle, vecThrow, AngularImpulse(200,random->RandomInt(-600,600),0), pPlayer, GRENADE_TIMER );
WeaponSound( WPN_DOUBLE );
m_bRedraw = true;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pPlayer -
//-----------------------------------------------------------------------------
void CWeaponFlash::RollGrenade( CBasePlayer *pPlayer )
{
// BUGBUG: Hardcoded grenade width of 4 - better not change the model
Vector vecSrc;
pPlayer->CollisionProp()->NormalizedToWorldSpace( Vector( 0.5f, 0.5f, 0.0f ), &vecSrc );
vecSrc.z += GRENADE_RADIUS;
Vector vecFacing = pPlayer->BodyDirection2D( );
// no up/down direction
vecFacing.z = 0;
VectorNormalize( vecFacing );
trace_t tr;
UTIL_TraceLine( vecSrc, vecSrc - Vector(0,0,16), MASK_PLAYERSOLID, pPlayer, COLLISION_GROUP_NONE, &tr );
if ( tr.fraction != 1.0 )
{
// compute forward vec parallel to floor plane and roll grenade along that
Vector tangent;
CrossProduct( vecFacing, tr.plane.normal, tangent );
CrossProduct( tr.plane.normal, tangent, vecFacing );
}
vecSrc += (vecFacing * 18.0);
CheckThrowPosition( pPlayer, pPlayer->WorldSpaceCenter(), vecSrc );
Vector vecThrow;
pPlayer->GetVelocity( &vecThrow, NULL );
vecThrow += vecFacing * 700;
// put it on its side
QAngle orientation(0,pPlayer->GetLocalAngles().y,-90);
// roll it
AngularImpulse rotSpeed(0,0,720);
Flashgrenade_Create( vecSrc, orientation, vecThrow, rotSpeed, pPlayer, GRENADE_TIMER );
WeaponSound( SPECIAL1 );
m_bRedraw = true;
}
Fena добавил 14-03-2005 в 12:17:08:
С этим всё... дале там-же создадим файл grenade_flash.cpp
Вот его код:
code:
#include "cbase.h"
#include "basegrenade_shared.h"
#include "grenade_flash.h"
#include "Sprite.h"
#include "SpriteTrail.h"
#include "soundent.h"
#include "particle_smokegrenade.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#define FLASH_GRENADE_BLIP_FREQUENCY 1.0f
#define FLASH_GRENADE_BLIP_FAST_FREQUENCY 0.3f
#define FLASH_GRENADE_GRACE_TIME_AFTER_PICKUP 1.5f
const float GRENADE_COEFFICIENT_OF_RESTITUTION = 0.2f;
/*
ConVar sk_plr_dmg_fraggrenade ( "sk_plr_dmg_fraggrenade","0");
ConVar sk_npc_dmg_fraggrenade ( "sk_npc_dmg_fraggrenade","0");
*/
ConVar sk_flashgrenade_radius ( "sk_flashgrenade_radius", "0");
#define FLASHGRENADE_MODEL "models/Weapons/w_flashgrenade.mdl"
class CGrenadeFlash : public CBaseGrenade
{
DECLARE_CLASS( CGrenadeFlash, CBaseGrenade );
#if !defined( CLIENT_DLL )
DECLARE_DATADESC();
#endif
~CGrenadeFlash( void );
public:
void Spawn( void );
void OnRestore( void );
void Precache( void );
bool CreateVPhysics( void );
void CreateEffects( void );
void SetTimer( float detonateDelay, float warnDelay );
void SetVelocity( const Vector &velocity, const AngularImpulse &angVelocity );
int OnTakeDamage( const CTakeDamageInfo &inputInfo );
void BlipSound() { EmitSound( "Grenade.Blip" ); }
void DelayThink();
void CreateSmokeTrail( void );
void VPhysicsUpdate( IPhysicsObject *pPhysics );
void OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason );
protected:
CHandle<CSprite> m_pMainGlow;
CHandle<CSpriteTrail> m_pGlowTrail;
float m_flNextBlipTime;
bool m_inSolid;
};
LINK_ENTITY_TO_CLASS( npc_grenade_flash, CGrenadeFlash );
BEGIN_DATADESC( CGrenadeFlash )
// Fields
DEFINE_FIELD( m_pMainGlow, FIELD_EHANDLE ),
DEFINE_FIELD( m_pGlowTrail, FIELD_EHANDLE ),
DEFINE_FIELD( m_flNextBlipTime, FIELD_TIME ),
DEFINE_FIELD( m_inSolid, FIELD_BOOLEAN ),
// Function Pointers
DEFINE_THINKFUNC( DelayThink ),
END_DATADESC()
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CGrenadeFlash::~CGrenadeFlash( void )
{
}
void RadiusFlash(
Vector vecSrc,
CBaseEntity *pevInflictor,
CBaseEntity *pevAttacker,
float flDamage,
int iClassIgnore,
int bitsDamageType )
{
CBaseEntity *pEntity = NULL;
trace_t tr;
float flAdjustedDamage, falloff;
Vector vecSpot;
float flRadius = 1500;
if ( flRadius )
falloff = flDamage / flRadius;
else
falloff = 1.0;
int bInWater = (UTIL_PointContents ( vecSrc ) == CONTENTS_WATER);
vecSrc.z += 1;// in case grenade is lying on the ground
if ( !pevAttacker )
pevAttacker = pevInflictor;
// iterate on all entities in the vicinity.
while ((pEntity = gEntList.FindEntityInSphere( pEntity, vecSrc, flRadius )) != NULL)
{
// get the heck out of here if it aint a player.
if (pEntity->IsPlayer() == FALSE)
continue;
if (( pEntity->m_takedamage != DAMAGE_NO ) && (pEntity->m_lifeState != LIFE_DEAD))
{
// blast's don't tavel into or out of water
if (bInWater && pEntity->GetWaterLevel() == 0)
continue;
if (!bInWater && pEntity->GetWaterLevel() == 3)
continue;
vecSpot = pEntity->BodyTarget( vecSrc );
UTIL_TraceLine( vecSrc, vecSpot, MASK_SHOT, pevInflictor, COLLISION_GROUP_NONE, &tr );
if ( tr.fraction == 1.0 || tr.m_pEnt == pEntity )
{// the explosion can 'see' this entity, so hurt them!
if (tr.startsolid)
{
// if we're stuck inside them, fixup the position and distance
tr.endpos = vecSrc;
tr.fraction = 0.0;
}
// decrease damage for an ent that's farther from the bomb.
flAdjustedDamage = ( vecSrc - tr.endpos ).Length() * falloff;
flAdjustedDamage = flDamage - flAdjustedDamage;
if ( flAdjustedDamage < 0 )
{
flAdjustedDamage = 0;
}
Vector vecLOS;
float flDot;
Vector vForward;
AngleVectors( pEntity->EyeAngles(), &vForward );
vecLOS = ( vecSrc - (pEntity->EyePosition()));
flDot = DotProduct (vecLOS, vForward);
float fadeTime, fadeHold;
int alpha;
// if target is facing the bomb, the effect lasts longer
if (flDot >= 0.0)
{
fadeTime = flAdjustedDamage * 3.0f;
fadeHold = flAdjustedDamage / 1.5f;
alpha = 255;
}
else
{
fadeTime = flAdjustedDamage * 1.75f;
fadeHold = flAdjustedDamage / 3.5f;
alpha = 200;
}
color32 clr = { 255, 255, 255, 255 };
UTIL_ScreenFade( pEntity, clr, fadeTime, fadeHold, FFADE_IN );
//MIKETODO: bots
/*
CBasePlayer *pPlayer = static_cast<CBasePlayer *>( pEntity );
if (pPlayer->IsBot())
{
// blind the bot
CCSBot *pBot = static_cast<CCSBot *>( pPlayer );
pBot->Blind( 0.33f * fadeTime );
}
*/
}
}
}
}
void CGrenadeFlash::Spawn( void )
{
Precache( );
SetModel( FLASHGRENADE_MODEL );
if( GetOwnerEntity() && GetOwnerEntity()->IsPlayer() )
{
//m_flDamage = sk_plr_dmg_fraggrenade.GetFloat();
m_DmgRadius = sk_flashgrenade_radius.GetFloat();
}
else
{
//m_flDamage = sk_npc_dmg_fraggrenade.GetFloat();
m_DmgRadius = sk_flashgrenade_radius.GetFloat();
}
m_takedamage = DAMAGE_YES;
m_iHealth = 1;
SetSize( -Vector(4,4,4), Vector(4,4,4) );
SetCollisionGroup( COLLISION_GROUP_WEAPON );
CreateVPhysics();
CreateEffects();
BlipSound();
m_flNextBlipTime = gpGlobals->curtime + FLASH_GRENADE_BLIP_FREQUENCY;
AddSolidFlags( FSOLID_NOT_STANDABLE );
BaseClass::Spawn();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CGrenadeFlash::OnRestore( void )
{
CreateEffects();
BaseClass::OnRestore();
}
см далее >
Fena добавил 14-03-2005 в 12:17:29:
code://-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CGrenadeFlash::CreateEffects( void )
{
// Start up the eye glow
//m_pMainGlow = CSprite::SpriteCreate( "sprites/redglow1.vmt", GetLocalOrigin(), false );
// int nAttachment = LookupAttachment( "fuse" );
/* if ( m_pMainGlow != NULL )
{
m_pMainGlow->FollowEntity( this );
m_pMainGlow->SetAttachment( this, nAttachment );
m_pMainGlow->SetTransparency( kRenderGlow, 255, 255, 255, 200, kRenderFxNoDissipation );
m_pMainGlow->SetScale( 0.2f );
m_pMainGlow->SetGlowProxySize( 4.0f );
}
// Start up the eye trail
// m_pGlowTrail = CSpriteTrail::SpriteTrailCreate( "sprites/bluelaser1.vmt", GetLocalOrigin(), false );
if ( m_pGlowTrail != NULL )
{
m_pGlowTrail->FollowEntity( this );
m_pGlowTrail->SetAttachment( this, nAttachment );
m_pGlowTrail->SetTransparency( kRenderTransAdd, 255, 0, 0, 255, kRenderFxNone );
m_pGlowTrail->SetStartWidth( 8.0f );
m_pGlowTrail->SetEndWidth( 1.0f );
m_pGlowTrail->SetLifeTime( 0.5f );
}
*/
}
bool CGrenadeFlash::CreateVPhysics()
{
// Create the object in the physics system
VPhysicsInitNormal( SOLID_BBOX, 0, false );
return true;
}
// this will hit only things that are in newCollisionGroup, but NOT in collisionGroupAlreadyChecked
class CTraceFilterCollisionGroupDelta : public CTraceFilterEntitiesOnly
{
public:
// It does have a base, but we'll never network anything below here..
DECLARE_CLASS_NOBASE( CTraceFilterCollisionGroupDelta );
CTraceFilterCollisionGroupDelta( const IHandleEntity *passentity, int collisionGroupAlreadyChecked, int newCollisionGroup )
: m_pPassEnt(passentity), m_collisionGroupAlreadyChecked( collisionGroupAlreadyChecked ), m_newCollisionGroup( newCollisionGroup )
{
}
virtual bool ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask )
{
if ( !PassServerEntityFilter( pHandleEntity, m_pPassEnt ) )
return false;
CBaseEntity *pEntity = EntityFromEntityHandle( pHandleEntity );
if ( pEntity )
{
if ( g_pGameRules->ShouldCollide( m_collisionGroupAlreadyChecked, pEntity->GetCollisionGroup() ) )
return false;
if ( g_pGameRules->ShouldCollide( m_newCollisionGroup, pEntity->GetCollisionGroup() ) )
return true;
}
return false;
}
protected:
const IHandleEntity *m_pPassEnt;
int m_collisionGroupAlreadyChecked;
int m_newCollisionGroup;
};
void CGrenadeFlash::VPhysicsUpdate( IPhysicsObject *pPhysics )
{
BaseClass::VPhysicsUpdate( pPhysics );
Vector vel;
AngularImpulse angVel;
pPhysics->GetVelocity( &vel, &angVel );
Vector start = GetAbsOrigin();
// find all entities that my collision group wouldn't hit, but COLLISION_GROUP_NONE would and bounce off of them as a ray cast
CTraceFilterCollisionGroupDelta filter( this, GetCollisionGroup(), COLLISION_GROUP_NONE );
trace_t tr;
// UNDONE: Hull won't work with hitboxes - hits outer hull. But the whole point of this test is to hit hitboxes.
#if 0
UTIL_TraceHull( start, start + vel * gpGlobals->frametime, CollisionProp()->OBBMins(), CollisionProp()->OBBMaxs(), CONTENTS_HITBOX|CONTENTS_MONSTER|CONTENTS_SOLID, &filter, &tr );
#else
UTIL_TraceLine( start, start + vel * gpGlobals->frametime, CONTENTS_HITBOX|CONTENTS_MONSTER|CONTENTS_SOLID, &filter, &tr );
#endif
if ( tr.startsolid )
{
if ( !m_inSolid )
{
// UNDONE: Do a better contact solution that uses relative velocity?
vel *= -GRENADE_COEFFICIENT_OF_RESTITUTION; // bounce backwards
pPhysics->SetVelocity( &vel, NULL );
}
m_inSolid = true;
return;
}
m_inSolid = false;
if ( tr.DidHit() )
{
Vector dir = vel;
VectorNormalize(dir);
// send a tiny amount of damage so the character will react to getting bonked
CTakeDamageInfo info( this, GetThrower(), pPhysics->GetMass() * vel, GetAbsOrigin(), 0.1f, DMG_CRUSH );
tr.m_pEnt->TakeDamage( info );
// reflect velocity around normal
vel = -2.0f * tr.plane.normal * DotProduct(vel,tr.plane.normal) + vel;
// absorb 80% in impact
vel *= GRENADE_COEFFICIENT_OF_RESTITUTION;
angVel *= -0.5f;
pPhysics->SetVelocity( &vel, &angVel );
}
}
void CGrenadeFlash::Precache( void )
{
PrecacheModel( FLASHGRENADE_MODEL );
PrecacheScriptSound( "Grenade.Blip" );
BaseClass::Precache();
}
void CGrenadeFlash::SetTimer( float detonateDelay, float warnDelay )
{
m_flDetonateTime = gpGlobals->curtime + detonateDelay;
m_flWarnAITime = gpGlobals->curtime + warnDelay;
SetThink( &CGrenadeFlash:elayThink );
SetNextThink( gpGlobals->curtime );
}
void CGrenadeFlash::OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason )
{
#ifdef HL2MP
SetTimer( FLASH_GRENADE_GRACE_TIME_AFTER_PICKUP, FLASH_GRENADE_GRACE_TIME_AFTER_PICKUP / 2);
SetThrower( pPhysGunUser );
BlipSound();
m_flNextBlipTime = gpGlobals->curtime + FLASH_GRENADE_BLIP_FAST_FREQUENCY;
m_bHasWarnedAI = true;
#endif
BaseClass::OnPhysGunPickup( pPhysGunUser, reason );
}
void CGrenadeFlash:elayThink()
{
RadiusFlash ( GetAbsOrigin(), this, false, 4, CLASS_NONE, DMG_BLAST );
if( gpGlobals->curtime > m_flDetonateTime )
{
AddEffects( EF_NODRAW );
return;
}
if( !m_bHasWarnedAI && gpGlobals->curtime >= m_flWarnAITime )
{
#if !defined( CLIENT_DLL )
CSoundEnt::InsertSound ( SOUND_DANGER, GetAbsOrigin(), 400, 1.5, this );
#endif
m_bHasWarnedAI = true;
}
if( gpGlobals->curtime > m_flNextBlipTime )
{
BlipSound();
if( m_bHasWarnedAI )
{
m_flNextBlipTime = gpGlobals->curtime + FLASH_GRENADE_BLIP_FAST_FREQUENCY;
}
else
{
m_flNextBlipTime = gpGlobals->curtime + FLASH_GRENADE_BLIP_FREQUENCY;
}
}
SetNextThink( gpGlobals->curtime + 0.1 );
}
void CGrenadeFlash::SetVelocity( const Vector &velocity, const AngularImpulse &angVelocity )
{
IPhysicsObject *pPhysicsObject = VPhysicsGetObject();
if ( pPhysicsObject )
{
pPhysicsObject->AddVelocity( &velocity, &angVelocity );
}
}
int CGrenadeFlash::OnTakeDamage( const CTakeDamageInfo &inputInfo )
{
// Manually apply vphysics because BaseCombatCharacter takedamage doesn't call back to CBaseEntity OnTakeDamage
VPhysicsTakeDamage( inputInfo );
// Grenades only suffer blast damage and burn damage.
if( !(inputInfo.GetDamageType() & (DMG_BLAST|DMG_BURN) ) )
return 0;
return BaseClass::OnTakeDamage( inputInfo );
}
CBaseGrenade *Flashgrenade_Create(
const Vector &position,
const QAngle &angles,
const Vector &velocity,
const AngularImpulse &angVelocity,
CBaseCombatCharacter *pOwner,
float timer )
{
CGrenadeFlash *pGrenade = (CGrenadeFlash *)CBaseEntity::Create( "npc_grenade_flash", position, angles, pOwner );
// Set the timer for 1 second less than requested. We're going to issue a SOUND_DANGER
// one second before detonation.
pGrenade->SetTimer( timer, timer - 1.5f );
pGrenade->SetVelocity( velocity, angVelocity );
pGrenade->SetThrower( ToBaseCombatCharacter( pOwner ) );
pGrenade->m_takedamage = DAMAGE_EVENTS_ONLY;
pGrenade->SetThink( &CGrenadeFlash:elayThink );
pGrenade->SetNextThink( gpGlobals->curtime + timer );
return pGrenade;
}
Теперь нам нужен ещё h файл... создадим: grenade_flash.h
Code:
code:
#ifndef GRENADE_FLASH_H
#define GRENADE_FLASH_H
#pragma once
class CBaseGrenade;
struct edict_t;
#include "basegrenade_shared.h"
CBaseGrenade *Flashgrenade_Create(
const Vector &position,
const QAngle &angles,
const Vector &velocity,
const AngularImpulse &angVelocity,
CBaseCombatCharacter *pOwner,
float timer );
#endif
С серверной частью закончили... теперь собсно обратимся к клиенту... ну тут мало... короче откроем файлик c_weapon__stubs_hl2.cpp
в нём после слов: STUB_WEAPON_CLASS( weapon_frag, WeaponFrag, C_BaseHLCombatWeapon );
напишем:
code:
STUB_WEAPON_CLASS( weapon_flash, WeaponFlash, C_BaseHLCombatWeapon );
Всё компилируем... затем добавим в папку scripts файлик weapon_flash.txt туда собсно всё писанём... запускаем мод.. give weapon_flash и вуаля.
___________________________
2
Теперь самое главное Вот видео Смены суток... Скачать его можно тут
Вот... Описывать как это сделать в моде не буду... но могу дать подсказку... обратите внимание на:
code:
r_shadowangles
r_shadowblobbycutoff
r_shadowbreak
r_shadowcolor
r_shadowdir
r_shadowdist
Вот... это только начало, что можно изменить... может ещё раасскажу как сделать денамический skybox... но эт потом
Свобода, Равенство, Солидарность
Пол бычка http://polbi4ka.h16.ru
|