void FileWeaponInfo_t::Parse( KeyValues *pKeyValuesData, const char *szWeaponName ) { // Okay, we tried at least once to look this up... bParsedScript = true; // Classname Q_strncpy( szClassName, szWeaponName, MAX_WEAPON_STRING ); // Printable name Q_strncpy( szPrintName, pKeyValuesData->GetString( "printname", WEAPON_PRINTNAME_MISSING ), MAX_WEAPON_STRING ); // View model & world model Q_strncpy( szViewModel, pKeyValuesData->GetString( "viewmodel" ), MAX_WEAPON_STRING ); Q_strncpy( szWorldModel, pKeyValuesData->GetString( "playermodel" ), MAX_WEAPON_STRING ); Q_strncpy( szAnimationPrefix, pKeyValuesData->GetString( "anim_prefix" ), MAX_WEAPON_PREFIX ); iSlot = pKeyValuesData->GetInt( "bucket", 0 ); iPosition = pKeyValuesData->GetInt( "bucket_position", 0 ); // Use the console (X360) buckets if hud_fastswitch is set to 2. #ifdef CLIENT_DLL if ( hud_fastswitch.GetInt() == 2 ) #else if ( IsX360() ) #endif { iSlot = pKeyValuesData->GetInt( "bucket_360", iSlot ); iPosition = pKeyValuesData->GetInt( "bucket_position_360", iPosition ); } iMaxClip1 = pKeyValuesData->GetInt( "clip_size", WEAPON_NOCLIP ); // Max primary clips gun can hold (assume they don't use clips by default) iMaxClip2 = pKeyValuesData->GetInt( "clip2_size", WEAPON_NOCLIP ); // Max secondary clips gun can hold (assume they don't use clips by default) iDefaultClip1 = pKeyValuesData->GetInt( "default_clip", iMaxClip1 ); // amount of primary ammo placed in the primary clip when it's picked up iDefaultClip2 = pKeyValuesData->GetInt( "default_clip2", iMaxClip2 ); // amount of secondary ammo placed in the secondary clip when it's picked up iWeight = pKeyValuesData->GetInt( "weight", 0 ); iRumbleEffect = pKeyValuesData->GetInt( "rumble", -1 ); // LAME old way to specify item flags. // Weapon scripts should use the flag names. iFlags = pKeyValuesData->GetInt( "item_flags", ITEM_FLAG_LIMITINWORLD ); for ( int i=0; i < ARRAYSIZE( g_ItemFlags ); i++ ) { int iVal = pKeyValuesData->GetInt( g_ItemFlags[i].m_pFlagName, -1 ); if ( iVal == 0 ) { iFlags &= ~g_ItemFlags[i].m_iFlagValue; } else if ( iVal == 1 ) { iFlags |= g_ItemFlags[i].m_iFlagValue; } } bShowUsageHint = pKeyValuesData->GetBool( "showusagehint", false ); bAutoSwitchTo = pKeyValuesData->GetBool( "autoswitchto", true ); bAutoSwitchFrom = pKeyValuesData->GetBool( "autoswitchfrom", true ); m_bBuiltRightHanded = pKeyValuesData->GetBool( "BuiltRightHanded", true ); m_bAllowFlipping = pKeyValuesData->GetBool( "AllowFlipping", true ); m_bMeleeWeapon = pKeyValuesData->GetBool( "MeleeWeapon", false ); #if defined(_DEBUG) && defined(HL2_CLIENT_DLL) // make sure two weapons aren't in the same slot & position if ( iSlot >= MAX_WEAPON_SLOTS || iPosition >= MAX_WEAPON_POSITIONS ) { Warning( "Invalid weapon slot or position [slot %d/%d MAX], pos[%d/%d MAX]\n", iSlot, MAX_WEAPON_SLOTS - 1, iPosition, MAX_WEAPON_POSITIONS - 1 ); } else { if (g_bUsedWeaponSlots[iSlot][iPosition]) { Warning( "Duplicately assigned weapon slots in selection hud: %s (%d, %d)\n", szPrintName, iSlot, iPosition ); } g_bUsedWeaponSlots[iSlot][iPosition] = true; } #endif // Primary ammo used const char *pAmmo = pKeyValuesData->GetString( "primary_ammo", "None" ); if ( strcmp("None", pAmmo) == 0 ) Q_strncpy( szAmmo1, "", sizeof( szAmmo1 ) ); else Q_strncpy( szAmmo1, pAmmo, sizeof( szAmmo1 ) ); iAmmoType = GetAmmoDef()->Index( szAmmo1 ); // Secondary ammo used pAmmo = pKeyValuesData->GetString( "secondary_ammo", "None" ); if ( strcmp("None", pAmmo) == 0) Q_strncpy( szAmmo2, "", sizeof( szAmmo2 ) ); else Q_strncpy( szAmmo2, pAmmo, sizeof( szAmmo2 ) ); iAmmo2Type = GetAmmoDef()->Index( szAmmo2 ); // AI AddOn const char *pAIAddOn = pKeyValuesData->GetString( "ai_addon", "ai_addon_basecombatweapon" ); if ( strcmp("None", pAIAddOn) == 0) Q_strncpy( szAIAddOn, "", sizeof( szAIAddOn ) ); else Q_strncpy( szAIAddOn, pAIAddOn, sizeof( szAIAddOn ) ); // Now read the weapon sounds memset( aShootSounds, 0, sizeof( aShootSounds ) ); KeyValues *pSoundData = pKeyValuesData->FindKey( "SoundData" ); if ( pSoundData ) { for ( int i = EMPTY; i < NUM_SHOOT_SOUND_TYPES; i++ ) { const char *soundname = pSoundData->GetString( pWeaponSoundCategories[i] ); if ( soundname && soundname[0] ) { Q_strncpy( aShootSounds[i], soundname, MAX_WEAPON_STRING ); } } } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CItem_AmmoCrate::SetupCrate( void ) { SetModelName( AllocPooledString( m_lpzModelNames[m_nAmmoType] ) ); m_nAmmoIndex = GetAmmoDef()->Index( m_lpzAmmoNames[m_nAmmoType] ); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CNPC_GroundTurret::Spawn( void ) { Precache(); UTIL_SetModel( this, "models/combine_turrets/ground_turret.mdl" ); SetNavType( NAV_FLY ); SetSolid( SOLID_VPHYSICS ); SetBloodColor( DONT_BLEED ); m_iHealth = 125; m_flFieldOfView = cos( ((GROUNDTURRET_VIEWCONE / 2.0f) * M_PI / 180.0f) ); m_NPCState = NPC_STATE_NONE; m_vecSpread.x = 0.5; m_vecSpread.y = 0.5; m_vecSpread.z = 0.5; CapabilitiesClear(); AddEFlags( EFL_NO_DISSOLVE ); NPCInit(); CapabilitiesAdd( bits_CAP_SIMPLE_RADIUS_DAMAGE ); m_iAmmoType = GetAmmoDef()->Index( "PISTOL" ); m_pSmoke = NULL; m_bHasExploded = false; m_bEnabled = false; if( ai_newgroundturret.GetBool() ) { m_flSensingDist = 384; SetDistLook( m_flSensingDist ); } else { m_flSensingDist = 2048; } if( !GetParent() ) { DevMsg("ERROR! npc_ground_turret with no parent!\n"); UTIL_Remove(this); return; } m_flTimeNextShoot = gpGlobals->curtime; m_flTimeNextPing = gpGlobals->curtime; m_vecClosedPos = GetAbsOrigin(); StudioFrameAdvance(); Vector vecPos; GetAttachment( "eyes", vecPos ); SetViewOffset( vecPos - GetAbsOrigin() ); GetAttachment( "light", vecPos ); m_vecLightOffset = vecPos - GetAbsOrigin(); }
//----------------------------------------------------------------------------- // Chooses an item when the player is full //----------------------------------------------------------------------------- void CItem_DynamicResupply::SpawnFullItem( CItem_DynamicResupply *pMaster, CBasePlayer *pPlayer, int iDebug ) { // Can we not actually spawn the item? if ( !HasSpawnFlags(SF_DYNAMICRESUPPLY_ALWAYS_SPAWN) ) return; float flRatio[NUM_AMMO_ITEMS]; int i; float flTotalProb = 0.0f; for ( i = 0; i < NUM_AMMO_ITEMS; ++i ) { int iAmmoType = GetAmmoDef()->Index( g_DynamicResupplyAmmoItems[i].sAmmoDef ); bool bCanSpawn = pPlayer->Weapon_GetWpnForAmmo( iAmmoType ) != NULL; if ( bCanSpawn && ( g_DynamicResupplyAmmoItems[i].flFullProbability != 0 ) && ( pMaster->m_flDesiredAmmo[i] != 0.0f ) ) { flTotalProb += g_DynamicResupplyAmmoItems[i].flFullProbability; flRatio[i] = flTotalProb; } else { flRatio[i] = -1.0f; } } if ( flTotalProb == 0.0f ) { // If we're supposed to fallback to just a health vial, do that and finish. if ( pMaster->HasSpawnFlags(SF_DYNAMICRESUPPLY_FALLBACK_TO_VIAL) ) { CBaseEntity::Create( "item_healthvial", GetAbsOrigin(), GetAbsAngles(), this ); if ( iDebug ) { Msg("Player is full, spawning item_healthvial due to spawnflag.\n", g_DynamicResupplyAmmoItems[i].sEntityName ); } return; } // Otherwise, spawn the first ammo item in the list flRatio[0] = 1.0f; flTotalProb = 1.0f; } float flChoice = random->RandomFloat( 0.0f, flTotalProb ); for ( i = 0; i < NUM_AMMO_ITEMS; ++i ) { if ( flChoice <= flRatio[i] ) { CBaseEntity::Create( g_DynamicResupplyAmmoItems[i].sEntityName, GetAbsOrigin(), GetAbsAngles(), this ); if ( iDebug ) { Msg("Player is full, spawning %s \n", g_DynamicResupplyAmmoItems[i].sEntityName ); } return; } } if ( iDebug ) { Msg("Player is full on all health + ammo, is not spawning.\n" ); } }
bool IsAmmoType( int iAmmoType, const char *pAmmoName ) { return GetAmmoDef()->Index( pAmmoName ) == iAmmoType; }
//----------------------------------------------------------------------------- // Purpose: Return true if the specified player can carry any more of the ammo type //----------------------------------------------------------------------------- bool CGameRules::CanHaveAmmo( CBaseCombatCharacter *pPlayer, const char *szName ) { return CanHaveAmmo( pPlayer, GetAmmoDef()->Index(szName) ); }
void CBulletManager::SimulateBullet(CBullet& oBullet, float dt) { Vector vecOriginal = oBullet.m_vecOrigin; Assert(oBullet.m_hShooter.Get()); if (!oBullet.m_hShooter) return; bool bHasTraveledBefore = false; if (oBullet.m_flDistanceTraveled > 0) bHasTraveledBefore = true; // initialize these before the penetration loop, we'll need them to make our tracer after Vector vecTracerSrc = oBullet.m_vecOrigin; trace_t tr; // main enter bullet trace float flRange = dt; if (flRange < 0) flRange = 8000; bool bFullPenetrationDistance = false; Vector vecEnd = oBullet.m_vecOrigin + oBullet.m_vecDirection * flRange; int i; for (i = oBullet.m_iPenetrations; i < da_bullet_penetrations.GetInt(); i++) { CTraceFilterSimpleList tf(COLLISION_GROUP_NONE); tf.AddEntityToIgnore(oBullet.m_hShooter); for (int j = 0; j < oBullet.m_ahObjectsHit.Count(); j++) tf.AddEntityToIgnore(oBullet.m_ahObjectsHit[j]); UTIL_TraceLine( oBullet.m_vecOrigin, vecEnd, MASK_SOLID|CONTENTS_DEBRIS|CONTENTS_HITBOX, &tf, &tr ); if (da_bullet_debug.GetBool()) { #ifdef CLIENT_DLL DebugDrawLine(oBullet.m_vecOrigin + Vector(0, 0, 1), tr.endpos + Vector(0, 0, 1), 0, 255, 255, true, dt<0?10:0.1); #else DebugDrawLine(oBullet.m_vecOrigin + Vector(0, 0, 1), tr.endpos + Vector(0, 0, 1), 255, 255, 0, true, dt<0?10:0.1); #endif } Vector vecTraceEnd = tr.endpos; bool bBSPModel = tr.DidHitWorld(); if (tr.allsolid) { oBullet.m_flDistanceTraveled += (oBullet.m_vecOrigin - vecEnd).Length(); oBullet.m_vecOrigin = vecEnd; break; // We're inside something. Do nothing. } if ( sv_showimpacts.GetBool() && tr.fraction < 1.0f ) { #ifdef CLIENT_DLL // draw red client impact markers debugoverlay->AddBoxOverlay( tr.endpos, Vector(-2,-2,-2), Vector(2,2,2), QAngle( 0, 0, 0), 255,0,0,127, sv_showimpacts.GetFloat() ); if ( tr.m_pEnt && tr.m_pEnt->IsPlayer() ) { C_BasePlayer *player = ToBasePlayer( tr.m_pEnt ); player->DrawClientHitboxes( sv_showimpacts.GetFloat(), true ); } #else // draw blue server impact markers NDebugOverlay::Box( tr.endpos, Vector(-2,-2,-2), Vector(2,2,2), 0,0,255,127, sv_showimpacts.GetFloat() ); if ( tr.m_pEnt && tr.m_pEnt->IsPlayer() ) { CBasePlayer *player = ToBasePlayer( tr.m_pEnt ); player->DrawServerHitboxes( sv_showimpacts.GetFloat(), true ); } #endif } Assert(oBullet.m_iBulletType > 0); int iDamageType = DMG_BULLET | DMG_NEVERGIB | GetAmmoDef()->DamageType(oBullet.m_iBulletType); if (i == 0) iDamageType |= DMG_DIRECT; if (tr.startsolid) { trace_t tr2; UTIL_TraceLine( tr.endpos - oBullet.m_vecDirection, oBullet.m_vecOrigin, CONTENTS_SOLID|CONTENTS_MOVEABLE, NULL, COLLISION_GROUP_NONE, &tr2 ); // let's have a bullet exit effect if we penetrated a solid surface if (oBullet.m_bDoEffects && tr2.m_pEnt && tr2.m_pEnt->IsBSPModel()) UTIL_ImpactTrace( &tr2, iDamageType ); // ignore the entity we just hit for the next trace to avoid weird impact behaviors oBullet.m_ahObjectsHit.AddToTail(tr2.m_pEnt); } if ( tr.fraction == 1.0f ) { oBullet.m_flDistanceTraveled += (oBullet.m_vecOrigin - vecEnd).Length(); oBullet.m_vecOrigin = vecEnd; break; // we didn't hit anything, stop tracing shoot } weapontype_t eWeaponType = WT_NONE; CSDKWeaponInfo *pWeaponInfo = CSDKWeaponInfo::GetWeaponInfo(oBullet.m_eWeaponID); Assert(pWeaponInfo); if (pWeaponInfo) eWeaponType = pWeaponInfo->m_eWeaponType; float flDamageMultiplier = 1; float flMaxRange = 3000; // Power formula works like so: // pow( x, distance/y ) // The damage will be at 1 when the distance is 0 units, and at // x% when the distance is y units, with a gradual decay approaching zero switch (eWeaponType) { case WT_RIFLE: flDamageMultiplier = 0.75f; flMaxRange = 3000; break; case WT_SHOTGUN: flDamageMultiplier = 0.40f; flMaxRange = 500; break; case WT_SMG: flDamageMultiplier = 0.50f; flMaxRange = 1000; break; case WT_PISTOL: default: flDamageMultiplier = 0.55f; flMaxRange = 1500; break; } flMaxRange *= oBullet.m_hShooter->m_Shared.ModifySkillValue(1, 0.5f, SKILL_MARKSMAN); //calculate the damage based on the distance the bullet travelled. oBullet.m_flDistanceTraveled += tr.fraction * flRange; float flCurrentDistance = oBullet.m_flDistanceTraveled; // First 500 units, no decrease in damage. if (eWeaponType == WT_SHOTGUN) flCurrentDistance -= 350; else flCurrentDistance -= 500; if (flCurrentDistance < 0) flCurrentDistance = 0; if (flCurrentDistance > flMaxRange) flCurrentDistance = flMaxRange; float flDistanceMultiplier = pow(flDamageMultiplier, (flCurrentDistance / flMaxRange)); if( oBullet.m_bDoEffects ) { // See if the bullet ended up underwater + started out of the water if ( enginetrace->GetPointContents( tr.endpos ) & (CONTENTS_WATER|CONTENTS_SLIME) ) { CBaseEntity* pIgnore; if (oBullet.m_ahObjectsHit.Count()) pIgnore = oBullet.m_ahObjectsHit.Tail(); else pIgnore = oBullet.m_hShooter; trace_t waterTrace; UTIL_TraceLine( oBullet.m_vecOrigin, tr.endpos, (MASK_SHOT|CONTENTS_WATER|CONTENTS_SLIME), pIgnore, COLLISION_GROUP_NONE, &waterTrace ); if( waterTrace.allsolid != 1 ) { CEffectData data; data.m_vOrigin = waterTrace.endpos; data.m_vNormal = waterTrace.plane.normal; data.m_flScale = random->RandomFloat( 8, 12 ); if ( waterTrace.contents & CONTENTS_SLIME ) data.m_fFlags |= FX_WATER_IN_SLIME; DispatchEffect( "gunshotsplash", data ); } } else { //Do Regular hit effects // Don't decal nodraw surfaces if ( !( tr.surface.flags & (SURF_SKY|SURF_NODRAW|SURF_HINT|SURF_SKIP) ) ) { CBaseEntity *pEntity = tr.m_pEnt; //Tony; only while using teams do we check for friendly fire. if ( DAGameRules()->IsTeamplay() && pEntity && pEntity->IsPlayer() && (pEntity->GetBaseAnimating() && !pEntity->GetBaseAnimating()->IsRagdoll()) ) { if ( pEntity->GetTeamNumber() != oBullet.m_hShooter->GetTeamNumber() ) UTIL_ImpactTrace( &tr, iDamageType ); } //Tony; non player, just go nuts, else UTIL_ImpactTrace( &tr, iDamageType ); } } } // bDoEffects // add damage to entity that we hit #ifdef GAME_DLL float flBulletDamage = oBullet.m_iBulletDamage * flDistanceMultiplier / (i+1); // Each iteration the bullet drops in strength if (oBullet.m_hShooter->IsStyleSkillActive(SKILL_MARKSMAN)) flBulletDamage = oBullet.m_iBulletDamage * flDistanceMultiplier / (i/2+1); // Each iteration the bullet drops in strength but not nearly as much. ClearMultiDamage(); CTakeDamageInfo info( oBullet.m_hShooter, oBullet.m_hShooter, oBullet.m_hWeapon, flBulletDamage, iDamageType ); CalculateBulletDamageForce( &info, oBullet.m_iBulletType, oBullet.m_vecDirection, tr.endpos ); tr.m_pEnt->DispatchTraceAttack( info, oBullet.m_vecDirection, &tr ); oBullet.m_hShooter->TraceAttackToTriggers( info, tr.startpos, tr.endpos, oBullet.m_vecDirection ); ApplyMultiDamage(); #else flDistanceMultiplier = flDistanceMultiplier; // Silence warning. #endif if (tr.m_pEnt && !FStrEq(tr.m_pEnt->GetClassname(), "worldspawn")) oBullet.m_ahObjectsHit.AddToTail(tr.m_pEnt); float flPenetrationDistance; switch (eWeaponType) { case WT_RIFLE: flPenetrationDistance = 25; break; case WT_SHOTGUN: flPenetrationDistance = 5; break; case WT_SMG: flPenetrationDistance = 15; break; case WT_PISTOL: default: flPenetrationDistance = 15; break; } flPenetrationDistance = oBullet.m_hShooter->m_Shared.ModifySkillValue(flPenetrationDistance, 1, SKILL_MARKSMAN); Vector vecBackwards = tr.endpos + oBullet.m_vecDirection * flPenetrationDistance; if (tr.m_pEnt->IsBSPModel()) UTIL_TraceLine( vecBackwards, tr.endpos, CONTENTS_SOLID|CONTENTS_MOVEABLE, NULL, COLLISION_GROUP_NONE, &tr ); else UTIL_TraceLine( vecBackwards, tr.endpos, CONTENTS_HITBOX, NULL, COLLISION_GROUP_NONE, &tr ); if (tr.startsolid) { bFullPenetrationDistance = true; break; } // Set up the next trace. One unit in the direction of fire so that we firmly embed // ourselves in whatever solid was hit, to make sure we don't hit it again on next trace. if (dt < 0 && bBSPModel) { UTIL_TraceLine( vecTraceEnd + oBullet.m_vecDirection, vecTraceEnd + oBullet.m_vecDirection * flPenetrationDistance, CONTENTS_SOLID|CONTENTS_MOVEABLE, NULL, COLLISION_GROUP_NONE, &tr ); if (tr.startsolid) oBullet.m_vecOrigin = tr.startpos + oBullet.m_vecDirection; else oBullet.m_vecOrigin = vecTraceEnd + oBullet.m_vecDirection; } else oBullet.m_vecOrigin = vecTraceEnd + oBullet.m_vecDirection; } oBullet.m_iPenetrations = i; // the bullet's done penetrating, let's spawn our particle system if (oBullet.m_bDoEffects && dt < 0) oBullet.m_hShooter->MakeTracer( oBullet.m_vecOrigin, tr, TRACER_TYPE_DEFAULT, !bHasTraveledBefore ); #ifdef CLIENT_DLL if (oBullet.m_hRenderHandle != INVALID_CLIENT_RENDER_HANDLE) ClientLeafSystem()->RenderableChanged( oBullet.m_hRenderHandle ); #endif if (bFullPenetrationDistance || oBullet.m_iPenetrations >= da_bullet_penetrations.GetInt()) oBullet.Deactivate(); if (dt < 0) oBullet.Deactivate(); if (!bHasTraveledBefore && oBullet.m_flCurrAlpha == 0 && oBullet.m_flGoalAlpha == 0) oBullet.m_bActive = false; if (da_bullet_debug.GetBool()) { #ifdef CLIENT_DLL DebugDrawLine(vecOriginal, oBullet.m_vecOrigin, 0, 0, 255, true, dt<0?10:0.1); #else DebugDrawLine(vecOriginal, oBullet.m_vecOrigin, 255, 0, 0, true, dt<0?10:0.1); #endif } }
//------------------------------------------------------------------------------ // Purpose: Fire a round from the cannon // Notes: Only call this if you have an enemy. //------------------------------------------------------------------------------ void CNPC_CombineDropship::FireCannonRound( void ) { Vector vecPenetrate; trace_t tr; QAngle vecAimAngle; Vector vecToEnemy, vecEnemyTarget; Vector vecMuzzle; Vector vecAimDir; // HACKHACK until we actually get a muzzle attachment // GetAttachment( "muzzle", vecMuzzle, vecAimAngle ); vecMuzzle = GetAbsOrigin(); vecAimAngle = GetAbsAngles(); Vector shipDir, shipLeft; AngleVectors( vecAimAngle, &shipDir ); vecMuzzle.z += 72; vecMuzzle += shipDir * 96; vecEnemyTarget = GetEnemy()->BodyTarget( vecMuzzle, false ); // Aim with the muzzle's attachment point. VectorSubtract( vecEnemyTarget, vecMuzzle, vecToEnemy ); QAngle enemyAngles; VectorAngles(vecToEnemy, enemyAngles ); float diff = fabs( UTIL_AngleDiff( enemyAngles.y, vecAimAngle.y )); // only allow 90 degrees of freedom when firing if ( diff > 45 ) { StopCannon(); m_flTimeNextAttack = gpGlobals->curtime + 0.05; return; } if ( !m_bIsFiring ) // start up sound { StartCannon(); } VectorNormalize( vecToEnemy ); // If the gun is wildly off target, stop firing! // FIXME - this should use a vector pointing // to the enemy's location PLUS the stitching // error! (sjb) !!!BUGBUG // AngleVectors( vecAimAngle, &vecAimDir ); /* if( DotProduct( vecToEnemy, vecAimDir ) < 0.980 ) { StopCannonBurst(); m_flTimeNextAttack = gpGlobals->curtime + 0.1; return; } */ //Add a muzzle flash g_pEffects->MuzzleFlash( vecMuzzle, vecAimAngle, random->RandomFloat( 5.0f, 7.0f ) , MUZZLEFLASH_TYPE_GUNSHIP ); m_flTimeNextAttack = gpGlobals->curtime + 0.05; // Cheat. Fire directly at the target, plus noise. int ammoType = GetAmmoDef()->Index("CombineCannon"); FireBullets( 1, vecMuzzle, vecToEnemy, VECTOR_CONE_2DEGREES, 8192, ammoType, 1, -1, -1, 1 /* override damage */ ); }
void CNB_Weapon_Detail::UpdateLabels( CASW_WeaponInfo *pWeaponData ) { C_ASW_Player *pPlayer = C_ASW_Player::GetLocalASWPlayer(); if ( !pPlayer ) return; CASW_Marine_Profile *pProfile = Briefing()->GetMarineProfileByProfileIndex( m_nProfileIndex ); switch( m_nDetailIndex ) { case 0: { // for the chainsaw (which uses melee damage as a skill modifier), it applies a base value to the specified number in the script file // even if the skill is at 0 - because of this, we have to make a special case for the chainsaw and shift those values from the // "bonus" side to the "base" side because the base bonus always exists - confused yet? float flBaseSkillDmgShift = 0; int nBonusDmg = 0; int nPellets = pWeaponData->m_iNumPellets; if ( pProfile ) { if ( FStrEq("asw_weapon_prifle", pWeaponData->szClassName) ) nBonusDmg = MarineSkills()->GetSkillBasedValue(pProfile, ASW_MARINE_SKILL_ACCURACY, ASW_MARINE_SUBSKILL_ACCURACY_PRIFLE_DMG); else if ( FStrEq("asw_weapon_shotgun", pWeaponData->szClassName) ) nBonusDmg = MarineSkills()->GetSkillBasedValue(pProfile, ASW_MARINE_SKILL_ACCURACY, ASW_MARINE_SUBSKILL_ACCURACY_SHOTGUN_DMG); else if ( FStrEq("asw_weapon_railgun", pWeaponData->szClassName) ) nBonusDmg = MarineSkills()->GetSkillBasedValue(pProfile, ASW_MARINE_SKILL_ACCURACY, ASW_MARINE_SUBSKILL_ACCURACY_RAILGUN_DMG); else if ( FStrEq("asw_weapon_flamer", pWeaponData->szClassName) || FStrEq("asw_weapon_sentry_flamer", pWeaponData->szClassName) ) nBonusDmg = MarineSkills()->GetSkillBasedValue(pProfile, ASW_MARINE_SKILL_ACCURACY, ASW_MARINE_SUBSKILL_ACCURACY_FLAMER_DMG); else if ( FStrEq("asw_weapon_pistol", pWeaponData->szClassName) ) nBonusDmg = MarineSkills()->GetSkillBasedValue(pProfile, ASW_MARINE_SKILL_ACCURACY, ASW_MARINE_SUBSKILL_ACCURACY_PISTOL_DMG); else if ( FStrEq("asw_weapon_pdw", pWeaponData->szClassName) ) nBonusDmg = MarineSkills()->GetSkillBasedValue(pProfile, ASW_MARINE_SKILL_ACCURACY, ASW_MARINE_SUBSKILL_ACCURACY_PDW_DMG); else if ( FStrEq("asw_weapon_sniper_rifle", pWeaponData->szClassName) ) nBonusDmg = MarineSkills()->GetSkillBasedValue(pProfile, ASW_MARINE_SKILL_ACCURACY, ASW_MARINE_SUBSKILL_ACCURACY_SNIPER_RIFLE_DMG); else if ( FStrEq("asw_weapon_tesla_gun", pWeaponData->szClassName) ) nBonusDmg = 0.5f + MarineSkills()->GetSkillBasedValue(pProfile, ASW_MARINE_SKILL_ACCURACY, ASW_MARINE_SUBSKILL_ACCURACY_TESLA_CANNON_DMG); else if ( FStrEq("asw_weapon_chainsaw", pWeaponData->szClassName) ) { flBaseSkillDmgShift = asw_skill_melee_dmg_base.GetFloat(); nBonusDmg = MarineSkills()->GetSkillBasedValue(pProfile, ASW_MARINE_SKILL_MELEE, ASW_MARINE_SUBSKILL_MELEE_DMG); } else if ( FStrEq("asw_weapon_vindicator", pWeaponData->szClassName) ) { nBonusDmg = MarineSkills()->GetSkillBasedValue(pProfile, ASW_MARINE_SKILL_VINDICATOR, ASW_MARINE_SUBSKILL_VINDICATOR_DAMAGE); nPellets = MarineSkills()->GetSkillBasedValue(pProfile, ASW_MARINE_SKILL_VINDICATOR, ASW_MARINE_SUBSKILL_VINDICATOR_PELLETS); } else if ( FStrEq("asw_weapon_autogun", pWeaponData->szClassName) || FStrEq("asw_weapon_minigun", pWeaponData->szClassName) ) nBonusDmg = MarineSkills()->GetSkillBasedValue(pProfile, ASW_MARINE_SKILL_AUTOGUN, ASW_MARINE_SUBSKILL_AUTOGUN_DMG); else if ( FStrEq("asw_weapon_grenade_launcher", pWeaponData->szClassName) || FStrEq("asw_weapon_sentry_cannon", pWeaponData->szClassName) ) nBonusDmg = MarineSkills()->GetSkillBasedValue(pProfile, ASW_MARINE_SKILL_GRENADES, ASW_MARINE_SUBSKILL_GRENADE_CLUSTER_DMG); else nBonusDmg = MarineSkills()->GetSkillBasedValue(pProfile, ASW_MARINE_SKILL_ACCURACY, ASW_MARINE_SUBSKILL_ACCURACY_RIFLE_DMG); } // fire power static wchar_t wszPowerLine[32]; int iDamValue = (pWeaponData->m_flBaseDamage*pWeaponData->m_iNumPellets)+flBaseSkillDmgShift; int nTotalBonusDmg = (nBonusDmg*nPellets)-flBaseSkillDmgShift; Q_snwprintf( wszPowerLine, sizeof( wszPowerLine ), g_pVGuiLocalize->Find( "#asw_weapon_details_firepower" ) ); wchar_t wzDamValue[10]; if ( iDamValue <= 0 ) { Q_snwprintf( wzDamValue, sizeof( wzDamValue ), g_pVGuiLocalize->Find( "#asw_weapon_altfire_NA" ) ); } else if ( nTotalBonusDmg > 0 ) { Q_snwprintf( wzDamValue, sizeof( wzDamValue ), L"%d (+%d)", iDamValue, nTotalBonusDmg ); } else { Q_snwprintf( wzDamValue, sizeof( wzDamValue ), L"%d", iDamValue ); } m_pTitleLabel->SetText( wszPowerLine ); m_pTitleLabel->SetVisible( true ); m_pValueLabel->SetText( wzDamValue ); m_pValueLabel->SetVisible( true ); float flDamage = iDamValue + nTotalBonusDmg; float flCurrent = 0.0f; if ( flDamage > 60 ) flCurrent = 1.0f; else if ( iDamValue > 0 ) flCurrent = MAX( (flDamage-5.0f) / 55.0f, 0.05f ); if ( flDamage <= 0.0f ) { m_pValueLabel->SetText( L"N/A" ); m_pStatsBar->SetVisible( false ); } else { m_pStatsBar->Init( flCurrent, flCurrent, 0.1f, false, false ); m_pStatsBar->SetVisible( true ); } break; } case 1: { // fire rate static wchar_t wszRateLine[32]; Q_snwprintf( wszRateLine, sizeof( wszRateLine ), g_pVGuiLocalize->Find( "#asw_weapon_details_firerate" ) ); m_pTitleLabel->SetText( wszRateLine ); m_pTitleLabel->SetVisible( true ); float flRate = pWeaponData->m_flFireRate; wchar_t wzFireValue[32]; float flCurrent = 0.0f; if ( flRate <= 0 ) { Q_snwprintf( wzFireValue, sizeof( wzFireValue ), g_pVGuiLocalize->Find( "#asw_weapon_altfire_NA" ) ); } else { Q_snwprintf( wzFireValue, sizeof( wzFireValue ), L"%.1f / %s", (1.0f/flRate), g_pVGuiLocalize->Find( "#asw_weapon_details_seconds" ) ); if ( flRate <= 0.125f ) flCurrent = 1.0f - MIN( ((pWeaponData->m_flFireRate-0.03f)/0.125f)*0.5f, 0.48f ); else flCurrent = 1.0f - MIN( ((pWeaponData->m_flFireRate-0.5f)/0.65f)+0.5f, 0.98f ); } m_pValueLabel->SetText( wzFireValue ); m_pValueLabel->SetVisible( true ); m_pStatsBar->Init( flCurrent, flCurrent, 0.1f, false, false ); m_pStatsBar->SetVisible( true ); break; } case 2: { // the skill modifies the base reload time by this amount so all of the numbers in the script files are incorrect for displaying base amount float flBaseSkillModifier = asw_skill_reloading_base.GetFloat(); // reload time static wchar_t wszReloadLine[32]; Q_snwprintf( wszReloadLine, sizeof( wszReloadLine ), g_pVGuiLocalize->Find( "#asw_weapon_details_reload" ) ); float flBaseReload = pWeaponData->flReloadTime; if ( pWeaponData->m_flDisplayReloadTime >= 0 ) flBaseReload = pWeaponData->m_flDisplayReloadTime; float flCurrent = flBaseReload; float flRealReload = flBaseReload; wchar_t wzReloadValue[32]; if ( flBaseReload <= 0 ) { Q_snwprintf( wzReloadValue, sizeof( wzReloadValue ), g_pVGuiLocalize->Find( "#asw_weapon_altfire_NA" ) ); } else { float fSpeedScale = 1; float flReloadDiff = 0; if ( pProfile ) { fSpeedScale = MarineSkills()->GetSkillBasedValue(pProfile, ASW_MARINE_SKILL_RELOADING, ASW_MARINE_SUBSKILL_RELOADING_SPEED_SCALE); if ( fSpeedScale != 1 ) { flRealReload = flBaseReload * fSpeedScale; // to get an accurate difference, we need to multiply the script defined base reload amount by the base modifier that the Skill does flReloadDiff = flRealReload - (flBaseReload * flBaseSkillModifier); } } if ( flReloadDiff != 0 ) Q_snwprintf( wzReloadValue, sizeof( wzReloadValue ), L"%.1f %s (%s%.1f)", (flBaseReload*flBaseSkillModifier), g_pVGuiLocalize->Find( "#asw_weapon_details_seconds" ), (flReloadDiff>0)?L"+":L"", flReloadDiff ); else Q_snwprintf( wzReloadValue, sizeof( wzReloadValue ), L"%.1f %s", (flBaseReload*flBaseSkillModifier), g_pVGuiLocalize->Find( "#asw_weapon_details_seconds" ) ); flCurrent = 1.0f - MIN( (flRealReload-0.75f)/2.5f, 0.99f ); } m_pTitleLabel->SetText( wszReloadLine ); m_pTitleLabel->SetVisible( true ); m_pValueLabel->SetText( wzReloadValue ); m_pValueLabel->SetVisible( true ); m_pStatsBar->Init( flCurrent, flCurrent, 0.1f, false, false ); m_pStatsBar->SetVisible( true ); break; } case 3: { // clip capacity static wchar_t wszClipLine[32]; Q_snwprintf( wszClipLine, sizeof( wszClipLine ), g_pVGuiLocalize->Find( "#asw_weapon_details_clipsize" ) ); int iClipValue = pWeaponData->iMaxClip1; int nMaxBulletsPerGun = GetAmmoDef()->MaxCarry( pWeaponData->iAmmoType, NULL ); int iNumClips = ( nMaxBulletsPerGun / iClipValue ) + 1; if ( pWeaponData->m_bShowClipsDoubled ) { iNumClips *= 2; } if ( pWeaponData->m_iDisplayClipSize >= 0 ) iClipValue = pWeaponData->m_iDisplayClipSize; wchar_t wzClipValue[10]; if ( iClipValue == 111 ) // magic number for infinite ammo { // this displays an "infinity" symbol in the neosans font wzClipValue[0] = 0x221E; wzClipValue[1] = L'\0'; } else if ( pWeaponData->m_bShowClipsInWeaponDetail ) { Q_snwprintf( wzClipValue, sizeof( wzClipValue ), L"%d x %d", iClipValue, iNumClips ); } else { Q_snwprintf( wzClipValue, sizeof( wzClipValue ), L"%d", iClipValue ); } float flCurrent = MIN( (float)iClipValue/200.0f, 1.0f ); m_pTitleLabel->SetText( wszClipLine ); m_pTitleLabel->SetVisible( true ); m_pValueLabel->SetText( wzClipValue ); m_pValueLabel->SetVisible( true ); m_pStatsBar->Init( flCurrent, flCurrent, 0.1f, false, false ); m_pStatsBar->SetVisible( true ); break; } case 4: { // alt fire static wchar_t wszAltLine[32]; Q_snwprintf( wszAltLine, sizeof( wszAltLine ), g_pVGuiLocalize->Find( "#asw_weapon_details_altfire" ) ); wchar_t wzAltValue[64]; bool bHighlightText = false; if ( !Q_stricmp( pWeaponData->szAltFireText, "" ) ) Q_snwprintf( wzAltValue, sizeof( wzAltValue ), g_pVGuiLocalize->Find( "#asw_weapon_altfire_none" ) ); else { int iAltFire = pWeaponData->iDefaultClip2; if ( iAltFire > 0 ) Q_snwprintf( wzAltValue, sizeof( wzAltValue ), L"%d %s", iAltFire, g_pVGuiLocalize->Find( pWeaponData->szAltFireText ) ); else Q_snwprintf( wzAltValue, sizeof( wzAltValue ), g_pVGuiLocalize->Find( pWeaponData->szAltFireText ) ); bHighlightText = true; } m_pTitleLabel->SetText( wszAltLine ); m_pTitleLabel->SetVisible( true ); m_pValueLabel->SetText( wzAltValue ); m_pValueLabel->SetVisible( true ); m_pStatsBar->SetVisible( false ); break; } case 5: { // attributes static wchar_t wszAttributesLine[32]; Q_snwprintf( wszAttributesLine, sizeof( wszAttributesLine ), g_pVGuiLocalize->Find( "#asw_weapon_details_notes" ) ); //wchar_t wszAttributesTempNull[4]; //wchar_t wszAttributesTempText[64]; wchar_t wszAttributesValue[64]; bool bHighlightText = false; //Q_snwprintf( wszAttributesTempText, sizeof( wszAttributesTempText ), g_pVGuiLocalize->Find( pWeaponData->szAttributesText ) ); //Q_snwprintf( wszAttributesTempNull, sizeof( wszAttributesTempNull ), "" ); if ( !Q_wcscmp( g_pVGuiLocalize->Find( pWeaponData->szAttributesText ), g_pVGuiLocalize->Find( "#asw_weapon_null_line" ) ) ) //asw_weapon_null_line { // Q_snwprintf( wszAttributesValue, sizeof( wszAttributesValue ), g_pVGuiLocalize->Find( "#asw_weapon_altfire_none" ) ); m_pTitleLabel->SetVisible( false ); m_pValueLabel->SetVisible( false ); } else { Q_snwprintf( wszAttributesValue, sizeof( wszAttributesValue ), g_pVGuiLocalize->Find( pWeaponData->szAttributesText ) ); bHighlightText = true; m_pTitleLabel->SetText( wszAttributesLine ); m_pTitleLabel->SetVisible( true ); m_pValueLabel->SetText( wszAttributesValue ); m_pValueLabel->SetVisible( true ); } m_pStatsBar->SetVisible( false ); break; } case 6: { int nRequiredLevel = pPlayer->GetWeaponLevelRequirement( pWeaponData->szClassName ); if ( nRequiredLevel == -1 ) { m_pTitleLabel->SetVisible( false ); m_pValueLabel->SetVisible( false ); m_pStatsBar->SetVisible( false ); return; } // required level static wchar_t wszAltLine[32]; Q_snwprintf( wszAltLine, sizeof( wszAltLine ), g_pVGuiLocalize->Find( "#asw_weapon_details_required_level" ) ); nRequiredLevel++; // for display it's actually 1 higher (levels start from 0 in code) wchar_t wzAltValue[64]; Q_snwprintf( wzAltValue, sizeof( wzAltValue ), L"%d", nRequiredLevel ); m_pTitleLabel->SetText( wszAltLine ); m_pTitleLabel->SetVisible( true ); m_pValueLabel->SetText( wzAltValue ); m_pValueLabel->SetVisible( true ); m_pStatsBar->SetVisible( false ); break; } } }
void CASW_Ammo_Drop::ActivateUseIcon( CASW_Marine* pMarine, int nHoldType ) { if ( nHoldType == ASW_USE_HOLD_START ) return; CASW_Weapon *pWeapon = GetAmmoUseUnits( pMarine ); if( pWeapon ) { int iAmmoType = pWeapon->GetPrimaryAmmoType(); int iGuns = pMarine->GetNumberOfWeaponsUsingAmmo( iAmmoType ); int iMaxAmmoCount = GetAmmoDef()->MaxCarry( iAmmoType, pMarine ) * iGuns; int iBullets = pMarine->GetAmmoCount( iAmmoType ); int iAmmoCost = GetAmmoUnitCost( iAmmoType ); int iClipsToGive = CASW_Ammo_Drop_Shared::GetAmmoClipsToGive( iAmmoType ); pMarine->SetAmmoCount( MIN( iBullets + pWeapon->GetMaxClip1() * iClipsToGive, iMaxAmmoCount ), iAmmoType ); m_iAmmoUnitsRemaining -= iAmmoCost; pMarine->GetMarineSpeech()->Chatter(CHATTER_USE); IGameEvent * event = gameeventmanager->CreateEvent( "ammo_pickup" ); if ( event ) { CASW_Player *pPlayer = pMarine->GetCommander(); event->SetInt( "userid", ( pPlayer ? pPlayer->GetUserID() : 0 ) ); event->SetInt( "entindex", pMarine->entindex() ); gameeventmanager->FireEvent( event ); } if ( m_iAmmoUnitsRemaining <= 0 ) { CTakeDamageInfo info; BaseClass::Event_Killed( info ); } CASW_Marine *pDeployer = m_hDeployer.Get(); if ( pDeployer && pMarine != pDeployer && !m_bSuppliedAmmo ) { m_bSuppliedAmmo = true; if ( pDeployer->GetCommander() ) { pDeployer->GetCommander()->AwardAchievement( ACHIEVEMENT_ASW_AMMO_RESUPPLY ); } } } else { if ( pMarine->IsInhabited() ) { CASW_Player *pCommander = pMarine->GetCommander(); if ( pCommander ) { CSingleUserRecipientFilter filter( pCommander ); EmitSound( filter, pMarine->entindex(), "ASW_Ammobag.Fail", NULL, 0.0f ); } } } }
//----------------------------------------------------------------------------- // Purpose: Spawn the entity //----------------------------------------------------------------------------- void CNPC_CombineCamera::Spawn() { Precache(); SetModel(COMBINE_CAMERA_MODEL); m_pEyeFlash = CSprite::SpriteCreate(COMBINE_CAMERA_FLASH_SPRITE, GetLocalOrigin(), FALSE); m_pEyeFlash->SetTransparency(kRenderGlow, 255, 255, 255, 0, kRenderFxNoDissipation); m_pEyeFlash->SetAttachment(this, 2); m_pEyeFlash->SetBrightness(0); m_pEyeFlash->SetScale(1.0); BaseClass::Spawn(); m_HackedGunPos = Vector(0, 0, 12.75); SetViewOffset(EyeOffset(ACT_IDLE)); m_flFieldOfView = CAMERA_FOV_WIDE; m_takedamage = DAMAGE_YES; m_iHealth = 50; m_bloodColor = BLOOD_COLOR_MECH; SetSolid(SOLID_BBOX); AddSolidFlags(FSOLID_NOT_STANDABLE); SetHeight(COMBINE_CAMERA_RETRACT_HEIGHT); AddFlag(FL_AIMTARGET); SetPoseParameter(COMBINE_CAMERA_BC_YAW, 0); SetPoseParameter(COMBINE_CAMERA_BC_PITCH, 0); m_iAmmoType = GetAmmoDef()->Index("Pistol"); // Create our eye sprite m_pEyeGlow = CSprite::SpriteCreate(COMBINE_CAMERA_GLOW_SPRITE, GetLocalOrigin(), false); m_pEyeGlow->SetTransparency(kRenderWorldGlow, 255, 0, 0, 128, kRenderFxNoDissipation); m_pEyeGlow->SetAttachment(this, 2); // Set our enabled state m_bEnabled = ((m_spawnflags & SF_COMBINE_CAMERA_STARTINACTIVE) == false); // Make sure the radii are sane. if (m_nOuterRadius <= 0) { m_nOuterRadius = 300; } if (m_nInnerRadius <= 0) { m_nInnerRadius = 450; } if (m_nOuterRadius < m_nInnerRadius) { swap(m_nOuterRadius, m_nInnerRadius); } // Do we start active? if (m_bEnabled) { Deploy(); } else { SetEyeState(CAMERA_EYE_DISABLED); } //Adrian: No shadows on these guys. AddEffects( EF_NOSHADOW ); // Stagger our starting times SetNextThink( gpGlobals->curtime + random->RandomFloat(0.1f, 0.3f) ); // Don't allow us to skip animation setup because our attachments are critical to us! SetBoneCacheFlags( BCF_NO_ANIMATION_SKIP ); }
//----------------------------------------------------------------------------- // Purpose: Returns the amount of ammunition of the specified type the character's carrying //----------------------------------------------------------------------------- int CBaseCombatCharacter::GetAmmoCount( char *szName ) const { return GetAmmoCount( GetAmmoDef()->Index(szName) ); }
void CBaseCombatCharacter::RemoveAmmo( int iCount, const char *szName ) { RemoveAmmo( iCount, GetAmmoDef()->Index(szName) ); }