//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- BuildingHudAlert_t C_BaseObject::GetBuildingAlertLevel( void ) { float flHealthPercent = GetHealth() / GetMaxHealth(); BuildingHudAlert_t alertLevel = BUILDING_HUD_ALERT_NONE; if ( HasSapper() ) { alertLevel = BUILDING_HUD_ALERT_SAPPER; } else if ( !IsBuilding() && flHealthPercent < 0.33 ) { alertLevel = BUILDING_HUD_ALERT_VERY_LOW_HEALTH; } else if ( !IsBuilding() && flHealthPercent < 0.66 ) { alertLevel = BUILDING_HUD_ALERT_LOW_HEALTH; } BuildingHudAlert_t iFakeAlert = (BuildingHudAlert_t)cl_obj_fake_alert.GetInt(); if ( iFakeAlert > BUILDING_HUD_ALERT_NONE && iFakeAlert < MAX_BUILDING_HUD_ALERT_LEVEL ) { alertLevel = iFakeAlert; } return alertLevel; }
//----------------------------------------------------------------------------- // Purpose: Player has waved his crosshair over this entity. Display appropriate hints. //----------------------------------------------------------------------------- void C_BaseObject::DisplayHintTo( C_BasePlayer *pPlayer ) { bool bHintPlayed = false; C_TFPlayer *pTFPlayer = ToTFPlayer(pPlayer); if ( InSameTeam( pPlayer ) ) { // We're looking at a friendly object. if ( HasSapper() ) { bHintPlayed = pPlayer->HintMessage( HINT_OBJECT_HAS_SAPPER, true, true ); } if ( pTFPlayer->IsPlayerClass( TF_CLASS_ENGINEER ) ) { // I'm an engineer. // If I'm looking at a constructing object, let me know I can help build it (but not // if I built it myself, since I've already got that hint from the wrench). if ( !bHintPlayed && IsBuilding() && GetBuilder() != pTFPlayer ) { bHintPlayed = pPlayer->HintMessage( HINT_ENGINEER_USE_WRENCH_ONOTHER, false, true ); } // If it's damaged, I can repair it if ( !bHintPlayed && !IsBuilding() && GetHealth() < GetMaxHealth() ) { bHintPlayed = pPlayer->HintMessage( HINT_ENGINEER_REPAIR_OBJECT, false, true ); } } } }
//----------------------------------------------------------------------------- // Purpose: Prevent switching when working on something //----------------------------------------------------------------------------- bool CWeaponBuilder::CanHolster( void ) { if ( IsBuilding() ) return false; return BaseClass::CanHolster(); }
//----------------------------------------------------------------------------- // Purpose: Return true if this object should be active //----------------------------------------------------------------------------- bool CBaseObject::ShouldBeActive( void ) { // Placing and/or constructing objects shouldn't be active if ( IsPlacing() || IsBuilding() ) return false; return true; }
//----------------------------------------------------------------------------- // Purpose: Find nearby objects and buff them. //----------------------------------------------------------------------------- void CObjectBuffStation::BuffNearbyObjects( CBaseObject *pObjectToTarget, bool bPlacing ) { // ROBIN: Disabled object buffing for now return; // Check for a team. if ( !GetTFTeam() ) return; // Am I ready to power anything? if ( IsBuilding() || ( !bPlacing && IsPlacing() ) ) return; // Am I already full? if ( m_nObjectCount >= BUFF_STATION_MAX_OBJECTS ) return; // Do we have a specific target? if ( pObjectToTarget ) { if( !pObjectToTarget->CanBeHookedToBuffStation() || pObjectToTarget->GetBuffStation() ) return; if ( IsWithinBuffRange( pObjectToTarget ) ) { AttachObject( pObjectToTarget, bPlacing ); } } else { // Find nearby objects for ( int iObject = 0; iObject < GetTFTeam()->GetNumObjects(); iObject++ ) { CBaseObject *pObject = GetTFTeam()->GetObject( iObject ); assert(pObject); if ( pObject == this || !pObject->CanBeHookedToBuffStation() || pObject->GetBuffStation() ) continue; // Make sure it's within range if ( IsWithinBuffRange( pObject ) ) { AttachObject( pObject, bPlacing ); // Am I now full? if ( m_nObjectCount >= BUFF_STATION_MAX_OBJECTS ) break; } } } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CObjectBuffStation::BoostObjectThink( void ) { // Set next boost object think time. SetNextThink( gpGlobals->curtime + BUFF_STATION_BOOST_OBJECT_THINK_INTERVAL, BUFF_STATION_BOOST_OBJECT_THINK_CONTEXT ); // If we're emped, placing, or building, we're not ready to powerup if ( IsPlacing() || IsBuilding() || HasPowerup( POWERUP_EMP ) ) return; float flMaxRangeSq = obj_buff_station_obj_range.GetFloat(); flMaxRangeSq *= flMaxRangeSq; // Boost objects. for ( int iObject = m_nObjectCount; --iObject >= 0; ) { CBaseObject *pObject = m_hObjects[iObject].Get(); if ( !pObject || !InSameTeam( pObject ) ) { DetachObjectByIndex( iObject ); continue; } // Check for out of range. float flDistSq = GetAbsOrigin().DistToSqr( pObject->GetAbsOrigin() ); if ( flDistSq > flMaxRangeSq ) { DetachObjectByIndex( iObject ); continue; } // Don't powerup it until it's finished building if ( pObject->IsPlacing() || pObject->IsBuilding() ) continue; // Boost it if ( !pObject->AttemptToPowerup( POWERUP_BOOST, BUFF_STATION_BOOST_OBJECT_THINK_INTERVAL, 0, this, &m_aObjectAttachInfo[iObject].m_DamageModifier ) ) { m_aObjectAttachInfo[iObject].m_DamageModifier.RemoveModifier(); } } }
void Info::SetFromFeatureType(FeatureType & ft) { MapObject::SetFromFeatureType(ft); std::string primaryName; std::string secondaryName; GetPrefferedNames(primaryName, secondaryName); m_sortedTypes = m_types; m_sortedTypes.SortBySpec(); m_primaryFeatureName = primaryName; if (IsBookmark()) { m_uiTitle = GetBookmarkName(); auto const secondaryTitle = m_customName.empty() ? primaryName : m_customName; if (m_uiTitle != secondaryTitle) m_uiSecondaryTitle = secondaryTitle; m_uiSubtitle = FormatSubtitle(true /* withType */); m_uiAddress = m_address; } else if (!primaryName.empty()) { m_uiTitle = primaryName; m_uiSecondaryTitle = secondaryName; m_uiSubtitle = FormatSubtitle(true /* withType */); m_uiAddress = m_address; } else if (IsBuilding()) { bool const isAddressEmpty = m_address.empty(); m_uiTitle = isAddressEmpty ? GetLocalizedType() : m_address; m_uiSubtitle = FormatSubtitle(!isAddressEmpty /* withType */); } else { m_uiTitle = GetLocalizedType(); m_uiSubtitle = FormatSubtitle(false /* withType */); m_uiAddress = m_address; } m_hotelType = ftypes::IsHotelChecker::Instance().GetHotelType(ft); }
kml::LocalizableString Info::FormatNewBookmarkName() const { kml::LocalizableString bookmarkName; if (IsFeature()) { m_name.ForEach([&bookmarkName](int8_t langCode, std::string const & localName) { if (!localName.empty()) bookmarkName[langCode] = localName; }); if (bookmarkName.empty() && IsBuilding() && !m_address.empty()) kml::SetDefaultStr(bookmarkName, m_address); } else if (!m_uiTitle.empty()) { kml::SetDefaultStr(bookmarkName, m_uiTitle); } return bookmarkName; }
bool Info::ShouldShowAddBusiness() const { return m_canEditOrAdd && IsBuilding(); }
bool Info::ShouldShowAddPlace() const { auto const isPointOrBuilding = IsPointType() || IsBuilding(); return m_canEditOrAdd && !(IsFeature() && isPointOrBuilding); }
void CObjectTeleporter::DeterminePlaybackRate( void ) { float flPlaybackRate = GetPlaybackRate(); bool bWasBelowFullSpeed = ( flPlaybackRate < 1.0f ); if ( IsBuilding() ) { // Default half rate, author build anim as if one player is building SetPlaybackRate( GetConstructionMultiplier() * 0.5 ); } else if ( IsPlacing() ) { SetPlaybackRate( 1.0f ); } else { float flFrameTime = 0.1; // BaseObjectThink delay switch( m_iState ) { case TELEPORTER_STATE_READY: { // spin up to 1.0 from whatever we're at, at some high rate flPlaybackRate = Approach( 1.0f, flPlaybackRate, 0.5f * flFrameTime ); } break; case TELEPORTER_STATE_RECHARGING: { // Recharge - spin down to low and back up to full speed over 10 seconds // 0 -> 4, spin to low // 4 -> 6, stay at low // 6 -> 10, spin to 1.0 float flScale = g_flTeleporterRechargeTimes[GetUpgradeLevel() - 1] / g_flTeleporterRechargeTimes[0]; float flToLow = 4.0f * flScale; float flToHigh = 6.0f * flScale; float flRechargeTime = g_flTeleporterRechargeTimes[GetUpgradeLevel() - 1]; float flTimeSinceChange = gpGlobals->curtime - m_flLastStateChangeTime; float flLowSpinSpeed = 0.15f; if ( flTimeSinceChange <= flToLow ) { flPlaybackRate = RemapVal( gpGlobals->curtime, m_flLastStateChangeTime, m_flLastStateChangeTime + flToLow, 1.0f, flLowSpinSpeed ); } else if ( flTimeSinceChange > flToLow && flTimeSinceChange <= flToHigh ) { flPlaybackRate = flLowSpinSpeed; } else { flPlaybackRate = RemapVal( gpGlobals->curtime, m_flLastStateChangeTime + flToHigh, m_flLastStateChangeTime + flRechargeTime, flLowSpinSpeed, 1.0f ); } } break; default: { if ( m_flLastStateChangeTime <= 0.0f ) { flPlaybackRate = 0.0f; } else { // lost connect - spin down to 0.0 from whatever we're at, slowish rate flPlaybackRate = Approach( 0.0f, flPlaybackRate, 0.25f * flFrameTime ); } } break; } SetPlaybackRate( flPlaybackRate ); } bool bBelowFullSpeed = ( GetPlaybackRate() < 1.0f ); if ( m_iBlurBodygroup >= 0 && bBelowFullSpeed != bWasBelowFullSpeed ) { if ( bBelowFullSpeed ) { SetBodygroup( m_iBlurBodygroup, 0 ); // turn off blur bodygroup } else { SetBodygroup( m_iBlurBodygroup, 1 ); // turn on blur bodygroup } } StudioFrameAdvance(); }
bool Info::ShouldShowAddPlace() const { return !IsSponsoredHotel() && (!IsFeature() || (!IsPointType() && !IsBuilding())); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void C_BaseObject::OnDataChanged( DataUpdateType_t updateType ) { if (updateType == DATA_UPDATE_CREATED) { CreateBuildPoints(); } BaseClass::OnDataChanged( updateType ); // Did we just finish building? if ( m_bWasBuilding && !m_bBuilding ) { FinishedBuilding(); } // Did we just go active? bool bShouldBeActive = ShouldBeActive(); if ( !m_bWasActive && bShouldBeActive ) { OnGoActive(); } else if ( m_bWasActive && !bShouldBeActive ) { OnGoInactive(); } if ( m_bDisabled != m_bOldDisabled ) { if ( m_bDisabled ) { OnStartDisabled(); } else { OnEndDisabled(); } } if ( ( !IsBuilding() && m_iHealth != m_iOldHealth ) ) { // recalc our damage particle state BuildingDamageLevel_t damageLevel = CalculateDamageLevel(); if ( damageLevel != m_damageLevel ) { UpdateDamageEffects( damageLevel ); m_damageLevel = damageLevel; } } if ( m_bWasBuilding && !m_bBuilding ) { // Force update damage effect when finishing construction. BuildingDamageLevel_t damageLevel = CalculateDamageLevel(); UpdateDamageEffects( damageLevel ); m_damageLevel = damageLevel; } // Kill all particles when getting picked up. if ( !m_bWasCarried && m_bCarried ) { ParticleProp()->StopParticlesInvolving( this ); } if ( m_iHealth > m_iOldHealth && m_iHealth == m_iMaxHealth ) { // If we were just fully healed, remove all decals RemoveAllDecals(); } if ( GetOwner() == C_TFPlayer::GetLocalTFPlayer() ) { IGameEvent *event = gameeventmanager->CreateEvent( "building_info_changed" ); if ( event ) { event->SetInt( "building_type", GetType() ); event->SetInt( "object_mode", GetObjectMode() ); gameeventmanager->FireEventClientSide( event ); } } if ( IsPlacing() && GetSequence() != m_nObjectOldSequence ) { // Ignore server sequences while placing OnPlacementStateChanged( m_iLastPlacementPosValid > 0 ); } }
void C_ObjectSentrygun::ClientThink( void ) { // Turtling sentryguns don't think if ( IsTurtled() ) return; if ( IsPlacing() || IsBuilding() ) return; if ( m_hEnemy != NULL ) { // Figure out where we're firing at Vector vecMid = EyePosition(); Vector vecFireTarget = m_hEnemy->WorldSpaceCenter(); // + vecMid; // BodyTarget( vecMid ); Vector vecDirToEnemy = vecFireTarget - vecMid; QAngle angToTarget; VectorAngles(vecDirToEnemy, angToTarget); angToTarget.y = UTIL_AngleMod( angToTarget.y ); if (angToTarget.x < -180) angToTarget.x += 360; if (angToTarget.x > 180) angToTarget.x -= 360; // now all numbers should be in [1...360] // pin to turret limitations to [-50...50] if (angToTarget.x > 50) angToTarget.x = 50; else if (angToTarget.x < -50) angToTarget.x = -50; m_vecGoalAngles.y = angToTarget.y; m_vecGoalAngles.x = angToTarget.x; MoveTurret(); return; } // Rotate if ( !MoveTurret() ) { // Play a sound occasionally if ( random->RandomFloat(0, 1) < 0.02 ) { EmitSound( "ObjectSentrygun.Idle" ); } // Switch rotation direction if (m_bTurningRight) { m_bTurningRight = false; m_vecGoalAngles.y = m_iLeftBound; } else { m_bTurningRight = true; m_vecGoalAngles.y = m_iRightBound; } // Randomly look up and down a bit if ( random->RandomFloat(0, 1) < 0.3 ) { m_vecGoalAngles.x = (int)random->RandomFloat(-10,10); } } }