Making a weapon that heal players: Difference between revisions

From Valve Developer Community
Jump to navigation Jump to search
(Changed PoV and fixed up on spelling)
Line 3: Line 3:
== Purpose ==
== Purpose ==


Here i will show you how to make weapons heal Players, useful for class based mods/games.
This tutorial will teach the programmer how to create a weapon that heals players.


== Constructor ==
== Constructor ==


First of all add this to your weapon constructor.
The following block of code is a integer variable,


m_bDropped = 0; // this is to make sure the medic drops it one at a time
m_bDropped = 0; // This is to make sure the Medic drops it one at a time


== Primaryfire ==
== Primary Fire ==


This right here is working code that launches one health vial per single fire.
The primary fire of the weapon is to drop one health vial per shot. Comments have been added for more clarifying.


<source lang=cpp>
<source lang=cpp>
     if (!m_bDropped) { // if it hasnt been dropped...
     if (!m_bDropped) { // If the health vial hasn't been dropped, continue
#ifndef CLIENT_DLL
#ifndef CLIENT_DLL
       CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); // get the player
       CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); // Grab the wielder


       Vector  vecEye = pPlayer->EyePosition(); // Get the eye vector
       Vector  vecEye = pPlayer->EyePosition(); // Get the eye vector of the wielder
       Vector  vForward, vRight; // create 2 new vectors
       Vector  vForward, vRight; // Create 2 new vectors


       pPlayer->EyeVectors( &vForward, &vRight, NULL );  // so we know what direction forward is
       pPlayer->EyeVectors( &vForward, &vRight, NULL );  // Getting direction forward
       Vector vecSrc = vecEye + vForward * 18.0f + vRight * 8.0f; // do some crazy math to find the source for our spawning
       Vector vecSrc = vecEye + vForward * 18.0f + vRight * 8.0f; // Finding source of spawning
 
       trace_t tr; // Gets the trace
       trace_t tr; // we need a trace


       UTIL_TraceHull( vecEye, vecSrc, -Vector(6,6,6), Vector(6,6,6),
       UTIL_TraceHull( vecEye, vecSrc, -Vector(6,6,6), Vector(6,6,6),
         pPlayer->PhysicsSolidMaskForEntity(), pPlayer, pPlayer->GetCollisionGroup(), &tr ); // to make sure we can spawn it without it being in anything else
         pPlayer->PhysicsSolidMaskForEntity(), pPlayer, pPlayer->GetCollisionGroup(), &tr ); // Checks if anything in front of it
        
        
       if ( tr.DidHit() ) // if we hit...
       if ( tr.DidHit() ) // If hit
       {
       {
         vecSrc = tr.endpos; // than something happens
         vecSrc = tr.endpos; // Drop at location
       }
       }


   //  CheckThrowPosition( pPlayer, vecEye, vecSrc );
   //  CheckThrowPosition( pPlayer, vecEye, vecSrc );
   //  vForward[0] += 0.1f;
   //  vForward[0] += 0.1f;
       vForward[2] += 0.1f; // something else
       vForward[2] += 0.1f; // Something else


       Vector vecThrow;
       Vector vecThrow;
       AngleVectors( pPlayer->EyeAngles() + pPlayer->GetPunchAngle(), &vecThrow ); // get the vector fo the impulse on our health vial
       AngleVectors( pPlayer->EyeAngles() + pPlayer->GetPunchAngle(), &vecThrow ); // Get Vector for Impulse on Health Vial
       // pPlayer->GetVelocity( &vecThrow, NULL );
       // pPlayer->GetVelocity( &vecThrow, NULL );
       VectorScale( vecThrow, 1000.0f, vecThrow ); // scale it down
       VectorScale( vecThrow, 1000.0f, vecThrow ); // Scale vial down
       // vecThrow += vForward * 1200;
       // vecThrow += vForward * 1200;


       CBaseEntity *pVial = NULL; // null and then!
       CBaseEntity *pVial = NULL; // Null
 
       pVial = CBaseEntity::Create( "item_healthvial", pPlayer->Weapon_ShootPosition(), QAngle(80,60,0), pPlayer ); // Creates
       pVial = CBaseEntity::Create( "item_healthvial", pPlayer->Weapon_ShootPosition(), QAngle(80,60,0), pPlayer ); create that shit!
       pVial->AddSpawnFlags(SF_NORESPAWN); // Doesn't allow respawning
       pVial->AddSpawnFlags(SF_NORESPAWN); // DONT LET IT RESPAWN!
       if (!pVial) // Has to have to be created to throw it
       if (!pVial) // have to have created it for it to be thrown
       {
       {
         DevMsg("unable to create item\n");
         DevMsg("unable to create item\n");
       }else // YEA BIZZNATCH
       }else // Works
       {
       {
         DevMsg(2, "Starting item throw (Server)\n");
         DevMsg(2, "Starting item throw (Server)\n");


         IPhysicsObject *pPhysicsObject = pVial->VPhysicsGetObject(); // get the physics object
         IPhysicsObject *pPhysicsObject = pVial->VPhysicsGetObject(); // Get the physic object
         if ( pPhysicsObject )
         if ( pPhysicsObject )
         {
         {
             DevMsg(2, "Throwing item (Server)\n");
             DevMsg(2, "Throwing item (Server)\n");
             pPhysicsObject->SetVelocity( &vecThrow, NULL );// throw that fuckin thing.
             pPhysicsObject->SetVelocity( &vecThrow, NULL );// Throw vial
              
              
         }
         }
       }
       }
       m_bDropped = 1; // change the flag...
       m_bDropped = 1; // Change flag
#endif
#endif
   } else {
   } else {
       DevMsg(2, "Already dropped one. Release the button. (Server)\n"); // damnit gotta let go of that button.
       DevMsg(2, "Already dropped one. Release the button. (Server)\n"); // Let go of button
   }</source>
   }</source>


== ItemPostFrame ==
== Item Post Frame ==


We will add this to the itempostframe in the weapon.
This block of code will add to the ItemPostFrame in the weapon.


<source lang=cpp>if (!((pOwner->m_nButtons & IN_ATTACK) || (pOwner->m_nButtons & IN_ATTACK2) || (pOwner->m_nButtons & IN_RELOAD)))
<source lang=cpp>if (!((pOwner->m_nButtons & IN_ATTACK) || (pOwner->m_nButtons & IN_ATTACK2) || (pOwner->m_nButtons & IN_RELOAD)))
Line 82: Line 80:
== Secondary Fire ==
== Secondary Fire ==


If a player is too close from the medic/gun will health the player too.
If player(s) are too close from the medic or the gun, it will heal the player(s).


<source lang=cpp>
<source lang=cpp>
Line 88: Line 86:
// Purpose:
// Purpose:
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CWeaponHealer::SecondaryAttack( void )
void CWeaponHealer::SecondaryAttack( void )  
{
{
   if (CanHealPlayer())
   if (CanHealPlayer()) // Checks if it can heal
       HealPlayer();
       HealPlayer(); // Run method
}
}


bool CWeaponHealer::CanHealPlayer( void )
bool CWeaponHealer::CanHealPlayer( void ) // Checks boolean
{
{
   if (!m_bFired){
   if (!m_bFired){ // If it hasn't been fired,
       CHL2MP_Player *pOwner = ToHL2MPPlayer( GetOwner() );
       CHL2MP_Player *pOwner = ToHL2MPPlayer( GetOwner() ); // Get owner of fun


       if (!pOwner)
       if (!pOwner) // If owner doesn't exist
       {
       {
         return false;
         return false; // Terminate code and return false
       }
       }


       Vector vecSrc, vecAiming;
       Vector vecSrc, vecAiming; // Create vectors used for secondary fire


       // Take the eye position and direction
       // Take the eye position and direction
       vecSrc = pOwner->EyePosition();
       vecSrc = pOwner->EyePosition();
        
        
       QAngle angles = pOwner->GetLocalAngles();
       QAngle angles = pOwner->GetLocalAngles(); // Get local angles


       AngleVectors( angles, &vecAiming );
       AngleVectors( angles, &vecAiming );


       trace_t tr;
       trace_t tr; // Create a new trace to use


       Vector  vecEnd = vecSrc + (vecAiming * 42);
       Vector  vecEnd = vecSrc + (vecAiming * 42);
Line 120: Line 118:
       if (tr.fraction < 1.0)
       if (tr.fraction < 1.0)
       {
       {
         // Don\'t attach to a living creature
         // Don't attach to a living creature
         if (tr.m_pEnt)
         if (tr.m_pEnt)
         {
         {
Line 127: Line 125:
             if (pBCC)
             if (pBCC)
             {
             {
               if (pBCC->GetHealth()<100)
               if (pBCC->GetHealth()<100) // If player does not have 100 health
                   return true;
                   return true; // Return true to
             }
             }
         }
         }
         return false;
         return false; // Else return false
       }
       }
       else
       else
Line 139: Line 137:
   }else {return false;}
   }else {return false;}
}
}
bool CWeaponHealer::HealPlayer( void )
bool CWeaponHealer::HealPlayer( void ) // Heal player declaration
{
{
   m_bFired = 1;
   m_bFired = 1; // Sets it to fired


   CHL2MP_Player *pOwner = ToHL2MPPlayer( GetOwner() );
   CHL2MP_Player *pOwner = ToHL2MPPlayer( GetOwner() ); // Get owner of health vial


   if (!pOwner)
   if (!pOwner) // If Owner is no longer in server
   {
   {
       return false;
       return false; // Terminate code
   }
   }


Line 166: Line 164:
   if (tr.fraction < 1.0)
   if (tr.fraction < 1.0)
   {
   {
       // Don\'t attach to a living creature
       // Don't attach to a living creature
       if (tr.m_pEnt)
       if (tr.m_pEnt)
       {
       {
Line 177: Line 175:
               CBasePlayer *pPlayer = ToBasePlayer(pEntity);
               CBasePlayer *pPlayer = ToBasePlayer(pEntity);


               CPASAttenuationFilter filter( pPlayer, "HealthVial.Touch" );
               CPASAttenuationFilter filter( pPlayer, "HealthVial.Touch" ); // Filters
               EmitSound( filter, pPlayer->entindex(), "HealthVial.Touch" );
               EmitSound( filter, pPlayer->entindex(), "HealthVial.Touch" ); // Play HealthVial.Touch
               pEntity->TakeHealth( 20, DMG_GENERIC );
               pEntity->TakeHealth( 20, DMG_GENERIC ); // Damage 20 health under generic reason
#endif
#endif
               return true;
               return true;

Revision as of 23:41, 7 October 2012

Broom icon.png
This article or section needs to be cleaned up to conform to a higher standard of quality because:
Spelling and grammar.
For help, see the VDC Editing Help and Wikipedia cleanup process. Also, remember to check for any notes left by the tagger at this article's talk page.
Broom icon.png
This article or section should be converted to third person to conform to wiki standards.

Purpose

This tutorial will teach the programmer how to create a weapon that heals players.

Constructor

The following block of code is a integer variable,

m_bDropped = 0; // This is to make sure the Medic drops it one at a time

Primary Fire

The primary fire of the weapon is to drop one health vial per shot. Comments have been added for more clarifying.

    if (!m_bDropped) { // If the health vial hasn't been dropped, continue
#ifndef CLIENT_DLL
      CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); // Grab the wielder

      Vector   vecEye = pPlayer->EyePosition(); // Get the eye vector of the wielder
      Vector   vForward, vRight; // Create 2 new vectors

      pPlayer->EyeVectors( &vForward, &vRight, NULL );  // Getting direction forward
      Vector vecSrc = vecEye + vForward * 18.0f + vRight * 8.0f; // Finding source of spawning
      trace_t tr; // Gets the trace

      UTIL_TraceHull( vecEye, vecSrc, -Vector(6,6,6), Vector(6,6,6),
         pPlayer->PhysicsSolidMaskForEntity(), pPlayer, pPlayer->GetCollisionGroup(), &tr ); // Checks if anything in front of it
      
      if ( tr.DidHit() ) // If hit
      {
         vecSrc = tr.endpos; // Drop at location
      }

   //   CheckThrowPosition( pPlayer, vecEye, vecSrc );
   //   vForward[0] += 0.1f;
      vForward[2] += 0.1f; // Something else

      Vector vecThrow;
      AngleVectors( pPlayer->EyeAngles() + pPlayer->GetPunchAngle(), &vecThrow ); // Get Vector for Impulse on Health Vial
      // pPlayer->GetVelocity( &vecThrow, NULL );
      VectorScale( vecThrow, 1000.0f, vecThrow ); // Scale vial down
      // vecThrow += vForward * 1200;

      CBaseEntity *pVial = NULL; // Null
      pVial = CBaseEntity::Create( "item_healthvial", pPlayer->Weapon_ShootPosition(), QAngle(80,60,0), pPlayer ); // Creates
      pVial->AddSpawnFlags(SF_NORESPAWN); // Doesn't allow respawning
      if (!pVial) // Has to have to be created to throw it
      {
         DevMsg("unable to create item\n");
      }else // Works
      {
         DevMsg(2, "Starting item throw (Server)\n");

         IPhysicsObject *pPhysicsObject = pVial->VPhysicsGetObject(); // Get the physic object
         if ( pPhysicsObject )
         {
            DevMsg(2, "Throwing item (Server)\n");
            pPhysicsObject->SetVelocity( &vecThrow, NULL );// Throw vial
            
         }
      }
      m_bDropped = 1; // Change flag
#endif
   } else {
      DevMsg(2, "Already dropped one. Release the button. (Server)\n"); // Let go of button
   }

Item Post Frame

This block of code will add to the ItemPostFrame in the weapon.

if (!((pOwner->m_nButtons & IN_ATTACK) || (pOwner->m_nButtons & IN_ATTACK2) || (pOwner->m_nButtons & IN_RELOAD)))
   {
      m_bDropped = 0;
   }

Secondary Fire

If player(s) are too close from the medic or the gun, it will heal the player(s).

//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CWeaponHealer::SecondaryAttack( void ) 
{
   if (CanHealPlayer()) // Checks if it can heal
      HealPlayer(); // Run method
}

bool CWeaponHealer::CanHealPlayer( void ) // Checks boolean
{
   if (!m_bFired){ // If it hasn't been fired,
      CHL2MP_Player *pOwner = ToHL2MPPlayer( GetOwner() ); // Get owner of fun

      if (!pOwner) // If owner doesn't exist
      {
         return false; // Terminate code and return false
      }

      Vector vecSrc, vecAiming; // Create vectors used for secondary fire

      // Take the eye position and direction
      vecSrc = pOwner->EyePosition();
      
      QAngle angles = pOwner->GetLocalAngles(); // Get local angles

      AngleVectors( angles, &vecAiming );

      trace_t tr; // Create a new trace to use

      Vector   vecEnd = vecSrc + (vecAiming * 42);
      UTIL_TraceLine( vecSrc, vecEnd, MASK_SOLID, pOwner, COLLISION_GROUP_NONE, &tr );
      
      if (tr.fraction < 1.0)
      {
         // Don't attach to a living creature
         if (tr.m_pEnt)
         {
            CBaseEntity *pEntity = tr.m_pEnt;
            CBaseCombatCharacter *pBCC      = ToBaseCombatCharacter( pEntity );
            if (pBCC)
            {
               if (pBCC->GetHealth()<100) // If player does not have 100 health
                  return true; // Return true to 
            }
         }
         return false; // Else return false
      }
      else
      {
         return false;
      }
   }else {return false;}
}
bool CWeaponHealer::HealPlayer( void ) // Heal player declaration
{
   m_bFired = 1; // Sets it to fired

   CHL2MP_Player *pOwner = ToHL2MPPlayer( GetOwner() ); // Get owner of health vial

   if (!pOwner) // If Owner is no longer in server
   {
      return false; // Terminate code
   }

   Vector vecSrc, vecAiming;

   // Take the eye position and direction
   vecSrc = pOwner->EyePosition();
   
   QAngle angles = pOwner->GetLocalAngles();

   AngleVectors( angles, &vecAiming );

   trace_t tr;

   Vector   vecEnd = vecSrc + (vecAiming * 42);
   UTIL_TraceLine( vecSrc, vecEnd, MASK_SOLID, pOwner, COLLISION_GROUP_NONE, &tr );
   
   if (tr.fraction < 1.0)
   {
      // Don't attach to a living creature
      if (tr.m_pEnt)
      {
         CBaseEntity *pEntity = tr.m_pEnt;
         if (pEntity->IsPlayer())
         {
            if (pEntity->GetHealth()<pEntity->GetMaxHealth())
            {
#ifndef CLIENT_DLL
               CBasePlayer *pPlayer = ToBasePlayer(pEntity);

               CPASAttenuationFilter filter( pPlayer, "HealthVial.Touch" ); // Filters
               EmitSound( filter, pPlayer->entindex(), "HealthVial.Touch" ); // Play HealthVial.Touch
               pEntity->TakeHealth( 20, DMG_GENERIC ); // Damage 20 health under generic reason
#endif
               return true;
            }
         }
      }
      return false;
   }
   else
   {
      return false;
   }
}