FlashBanG в вашем моде !!! Или по русски Слеповуха!!! Добрый день! И так... сегодня я вам раааскажу как сделать мммм световоую гранату.... И так... приступим.... создадим файлик на сервере (HL2 DLL) например weapon_flashbang... в нём напишем:
#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"
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
#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();
// 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 ); } }
// 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 ); } }
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;
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; }
С этим всё... дале там-же создадим файл grenade_flash.cpp Вот его код:
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;
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;
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 ) { }
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 ); } }
// 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;
С серверной частью закончили... теперь собсно обратимся к клиенту... ну тут мало... короче откроем файлик c_weapon__stubs_hl2.cpp в нём после слов: STUB_WEAPON_CLASS( weapon_frag, WeaponFrag, C_BaseHLCombatWeapon ); напишем:
[quote]Всё компилируем... затем добавим в папку scripts файлик weapon_flash.txt туда собсно всё писанём... запускаем мод.. give weapon_flash и вуаля!!![/quote] что надо прописать в weapon_flash.txt? напишите на мыло плизз x13_ok@bk.ru