* * * Форумы на Наша-Life THREAD * * * -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- THREAD : [Coding]: FlashBand в вашем моде (и не только! см. тему) Started at 14-03-2005 12:12 by Fena Visit at https://bbs.hl-inside.ru/showthread.php?threadid=14227 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- [Post 1] Author : Fena Date : 14-03-2005 12:12 Title : [Coding]: FlashBand в вашем моде (и не только! см. тему) Добрый день! И так... сегодня я вам раааскажу как сделать мммм световоую гранату (FlashBang) [b](1)[/b] и покажу пример смены суток [b](2)[/b]. Яб конечно дал вам всего прау строк.. но думаю не все додумаюцца куда их вставлять... поэтому опишу создание гранаты с 0... [b](1)[/b] И так... приступим.... создадим файлик на сервере (HL2 DLL) например weapon_flashbang... в нём напишем: [size=1][i]Fena добавил [date]1110802456[/date]:[/i][/size] [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::Deploy( void ) { m_bRedraw = false; m_fDrawbackFinished = false; return BaseClass::Deploy(); } //----------------------------------------------------------------------------- // 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; }[/code] см далее > [size=1][i]Fena добавил [date]1110802529[/date]:[/i][/size] [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::DecrementAmmo( 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; }[/code] [size=1][i]Fena добавил [date]1110802628[/date]:[/i][/size] С этим всё... дале там-же создадим файл 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 m_pMainGlow; CHandle 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( pEntity ); if (pPlayer->IsBot()) { // blind the bot CCSBot *pBot = static_cast( 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(); }[/code] см далее > [size=1][i]Fena добавил [date]1110802649[/date]:[/i][/size] [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::DelayThink ); 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::DelayThink() { 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::DelayThink ); pGrenade->SetNextThink( gpGlobals->curtime + timer ); return pGrenade; }[/code] Теперь нам нужен ещё 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 [/code] С серверной частью закончили... теперь собсно обратимся к клиенту... ну тут мало... короче откроем файлик c_weapon__stubs_hl2.cpp в нём после слов: [b]STUB_WEAPON_CLASS( weapon_frag, WeaponFrag, C_BaseHLCombatWeapon );[/b] напишем: [code] STUB_WEAPON_CLASS( weapon_flash, WeaponFlash, C_BaseHLCombatWeapon );[/code] Всё компилируем... затем добавим в папку scripts файлик weapon_flash.txt туда собсно всё писанём... запускаем мод.. give weapon_flash и вуаля. [b]___________________________[/b] [b]2[/b] Теперь самое главное :) Вот видео Смены суток... Скачать его можно [URL=http://gcnet.ru/~fmmypor/ROD_engine_part_1.avi]тут[/URL] Вот... Описывать как это сделать в моде не буду... но могу дать подсказку... обратите внимание на: [code] r_shadowangles r_shadowblobbycutoff r_shadowbreak r_shadowcolor r_shadowdir r_shadowdist [/code] Вот... это только начало, что можно изменить... может ещё раасскажу как сделать денамический skybox... но эт потом :) -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- [Post 2] Author : Lolmen Date : 14-03-2005 12:17 Меня больше заинтересовало Динамическое время суток. Интересно а как создать Пушку контроля физики как в e3_2003 ну что предметы либо синим лучом подбрасывает либо просто скрепляет шариками? :D Я то-то пробывал с physgun ом работать но что-то мягко говря херня получается. :) -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- [Post 3] Author : Fena Date : 14-03-2005 12:21 эм... только в самом начале.. [b]#include "cbase.h"[/b] нада потсавить на самую первую строку... -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- [Post 4] Author : ScorpyX Date : 14-03-2005 12:25 Fena... ты монстр :] ТАК ДЕРЖАТЬ и не расслабляться. авось когданить будет разрабатывать игры или еще что нить... -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- [Post 5] Author : xen Date : 14-03-2005 17:14 А вообще разрабы обещали ВСТРОЕННУЮ поддержку смены времени суток в реальном времени.. а раз она встроенная - значит там ничего сложного быть не должно... -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- [Post 6] Author : EHOT Date : 18-03-2005 11:52 А что писанём-то в weapon_flash.txt ? -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- [Post 7] Author : Fena Date : 18-03-2005 13:33 [code] WeaponData { // Weapon data is loaded by both the Game and Client DLLs. "printname" "FlashBang" "viewmodel" "models/weapons/v_grenade.mdl" "playermodel" "models/items/grenadeAmmo.mdl" "anim_prefix" "Grenade" "bucket" "4" "bucket_position" "3" "clip_size" "-1" "clip2_size" "-1" "default_clip" "1" "default_clip2" "-1" "primary_ammo" "grenade" "secondary_ammo" "None" "weight" "1" "item_flags" "18" // ITEM_FLAG_NOAUTORELOAD | ITEM_FLAG_EXHAUSTIBLE // Sounds for the weapon. There is a max of 16 sounds per category (i.e. max 16 "single_shot" sounds) SoundData { "special1" "WeaponFlash.Roll" "double_shot" "common/null.wav" "single_shot" "common/null.wav" } // Weapon Sprite data is loaded by the Client DLL. TextureData { "weapon" { "font" "WeaponIcons" "character" "k" } "weapon_s" { "font" "WeaponIconsSelected" "character" "k" } "ammo" { "font" "WeaponIcons" "character" "v" } "crosshair" { "font" "Crosshairs" "character" "Q" } "autoaim" { "file" "sprites/crosshairs" "x" "48" "y" "72" "width" "24" "height" "24" } } } [/code] -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- [Post 8] Author : Free Date : 18-03-2005 14:58 Фена....Смена суток плавно выглядит или как на ролике? -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- [Post 9] Author : Fena Date : 18-03-2005 15:03 Плавно... просто я потсавил большую скорость спец. для ролика -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- [Post 10] Author : Lolmen Date : 22-03-2005 20:25 Да, вот только я чёго то не найду файла c_weapon__stubs_hl2.cpp -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- [Post 11] Author : Fena Date : 23-03-2005 10:39 [QUOTE][i]Оригинальное сообщение от Lolmen [/i] [B]Да, вот только я чёго то не найду файла c_weapon__stubs_hl2.cpp [/B][/QUOTE] в клиенте -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- The messages has been download from Форумы на Наша-Life at https://bbs.hl-inside.ru at 02.05.2024 11:37:43