//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTFFlameThrower::StartFlame() { if ( m_iWeaponState == FT_STATE_AIRBLASTING ) { C_BaseEntity *pModel = GetWeaponForEffect(); if ( pModel ) { pModel->ParticleProp()->Create( "pyro_blast", PATTACH_POINT_FOLLOW, "muzzle" ); } //CLocalPlayerFilter filter; //EmitSound( filter, entindex(), "Weapon_FlameThrower.AirBurstAttack" ); } else { CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); // normally, crossfade between start sound & firing loop in 3.5 sec float flCrossfadeTime = 3.5; if ( m_pFiringLoop && ( m_bCritFire != m_bFiringLoopCritical ) ) { // If we're firing and changing between critical & noncritical, just need to change the firing loop. // Set crossfade time to zero so we skip the start sound and go to the loop immediately. flCrossfadeTime = 0; StopFlame( true ); } StopPilotLight(); if ( !m_pFiringStartSound && !m_pFiringLoop ) { RestartParticleEffect(); CLocalPlayerFilter filter; // Play the fire start sound const char *shootsound = GetShootSound( SINGLE ); if ( flCrossfadeTime > 0.0 ) { // play the firing start sound and fade it out m_pFiringStartSound = controller.SoundCreate( filter, entindex(), shootsound ); controller.Play( m_pFiringStartSound, 1.0, 100 ); controller.SoundChangeVolume( m_pFiringStartSound, 0.0, flCrossfadeTime ); } // Start the fire sound loop and fade it in if ( m_bCritFire ) { shootsound = GetShootSound( BURST ); } else { shootsound = GetShootSound( SPECIAL1 ); } m_pFiringLoop = controller.SoundCreate( filter, entindex(), shootsound ); m_bFiringLoopCritical = m_bCritFire; // play the firing loop sound and fade it in if ( flCrossfadeTime > 0.0 ) { controller.Play( m_pFiringLoop, 0.0, 100 ); controller.SoundChangeVolume( m_pFiringLoop, 1.0, flCrossfadeTime ); } else { controller.Play( m_pFiringLoop, 1.0, 100 ); } } if( m_bHitTarget != m_bOldHitTarget ) { if ( m_bHitTarget ) { CLocalPlayerFilter filter; m_pHitTargetSound = controller.SoundCreate( filter, entindex(), "Weapon_FlameThrower.FireHit" ); controller.Play( m_pHitTargetSound, 1.0f, 100.0f ); } else if ( m_pHitTargetSound ) { controller.SoundDestroy( m_pHitTargetSound ); m_pHitTargetSound = NULL; } m_bOldHitTarget = m_bHitTarget; } } }
WorldObjectWidget::WorldObjectWidget(QWidget *parent) : QWidget(parent), ui(new Ui::WorldObjectWidget) { ui->setupUi(this); selection.object = 0; selection_type = 0; UnsetSelection(); ui->actionsButton->setMenu(&action_menu); connect(ui->objectName, SIGNAL(textChanged(QString)), this, SLOT(UpdateName(QString))); // Geometry connect(ui->objectPosX, SIGNAL(valueChanged(double)), this, SLOT(UpdateGeometry())); connect(ui->objectPosY, SIGNAL(valueChanged(double)), this, SLOT(UpdateGeometry())); connect(ui->objectPosZ, SIGNAL(valueChanged(double)), this, SLOT(UpdateGeometry())); connect(ui->objectRotationX, SIGNAL(valueChanged(double)), this, SLOT(UpdateGeometry())); connect(ui->objectRotationY, SIGNAL(valueChanged(double)), this, SLOT(UpdateGeometry())); connect(ui->objectRotationZ, SIGNAL(valueChanged(double)), this, SLOT(UpdateGeometry())); connect(ui->objectScaleX, SIGNAL(valueChanged(double)), this, SLOT(UpdateGeometry())); connect(ui->objectScaleY, SIGNAL(valueChanged(double)), this, SLOT(UpdateGeometry())); connect(ui->objectScaleZ, SIGNAL(valueChanged(double)), this, SLOT(UpdateGeometry())); connect(ui->objectFloor, SIGNAL(valueChanged(int)), this, SLOT(UpdateFloor())); connect(ui->inheritsFloor, SIGNAL(toggled(bool)), this, SLOT(UpdateFloor())); // Collider connect(ui->displayColliders, SIGNAL(toggled(bool)), this, SLOT(UpdateColliderDisplay())); connect(ui->collider_type, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateColliderType())); connect(ui->collider_pos_x, SIGNAL(valueChanged(double)), this, SLOT(UpdateColliderGeometry())); connect(ui->collider_pos_y, SIGNAL(valueChanged(double)), this, SLOT(UpdateColliderGeometry())); connect(ui->collider_pos_z, SIGNAL(valueChanged(double)), this, SLOT(UpdateColliderGeometry())); connect(ui->collider_hpr_x, SIGNAL(valueChanged(double)), this, SLOT(UpdateColliderGeometry())); connect(ui->collider_hpr_y, SIGNAL(valueChanged(double)), this, SLOT(UpdateColliderGeometry())); connect(ui->collider_hpr_z, SIGNAL(valueChanged(double)), this, SLOT(UpdateColliderGeometry())); connect(ui->collider_scale_x, SIGNAL(valueChanged(double)), this, SLOT(UpdateColliderGeometry())); connect(ui->collider_scale_y, SIGNAL(valueChanged(double)), this, SLOT(UpdateColliderGeometry())); connect(ui->collider_scale_z, SIGNAL(valueChanged(double)), this, SLOT(UpdateColliderGeometry())); // Light connect(ui->lightSetEnabled, SIGNAL(toggled(bool)), this, SLOT(LightSetEnabled(bool))); connect(ui->lightSetDisabled, SIGNAL(toggled(bool)), this, SLOT(LightSetDisabled(bool))); connect(ui->lightColorR, SIGNAL(valueChanged(double)), this, SLOT(UpdateLightColor())); connect(ui->lightColorG, SIGNAL(valueChanged(double)), this, SLOT(UpdateLightColor())); connect(ui->lightColorB, SIGNAL(valueChanged(double)), this, SLOT(UpdateLightColor())); connect(ui->lightAttenuationA, SIGNAL(valueChanged(double)), this, SLOT(UpdateLightAttenuation())); connect(ui->lightAttenuationB, SIGNAL(valueChanged(double)), this, SLOT(UpdateLightAttenuation())); connect(ui->lightAttenuationC, SIGNAL(valueChanged(double)), this, SLOT(UpdateLightAttenuation())); connect(ui->lightTypesList, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateLightType())); connect(ui->lightCompile, SIGNAL(clicked()), this, SLOT(LightCompile())); connect(ui->lightPriority, SIGNAL(valueChanged(int)), this, SLOT(UpdateLightPriority())); connect(ui->addLightTarget, SIGNAL(clicked()), this, SLOT(AddEnlightenedObject())); connect(ui->deleteLightTarget, SIGNAL(clicked()), this, SLOT(DeleteEnlightenedObject())); connect(ui->showFrustum, SIGNAL(toggled(bool)), this, SLOT(LightShowFrustum(bool))); connect(ui->lightTargets, SIGNAL(updatedPriority()), this, SLOT(UpdateEnlightenedObject())); connect(ui->lightTargets, SIGNAL(updatedPropagation()), this, SLOT(UpdateEnlightenedObject())); // Light -> Shadow caster connect(ui->shadowFilmSize, SIGNAL(valueChanged(int)), this, SLOT(UpdateShadowCaster())); connect(ui->shadowNear, SIGNAL(valueChanged(int)), this, SLOT(UpdateShadowCaster())); connect(ui->shadowFar, SIGNAL(valueChanged(int)), this, SLOT(UpdateShadowCaster())); connect(ui->shadowBufferSizeX, SIGNAL(valueChanged(int)), this, SLOT(UpdateShadowCaster())); connect(ui->shadowBufferSizeY, SIGNAL(valueChanged(int)), this, SLOT(UpdateShadowCaster())); // Render connect(ui->selectModel, SIGNAL(clicked()), this, SLOT(PickModel())); connect(ui->selectTexture, SIGNAL(clicked()), this, SLOT(PickTexture())); connect(ui->objectModel, SIGNAL(textChanged(QString)), this, SLOT(UpdateRender())); connect(ui->objectTexture, SIGNAL(textChanged(QString)), this, SLOT(UpdateRender())); connect(ui->objectFocus, SIGNAL(clicked()), this, SLOT(FocusCurrentObject())); connect(ui->useTexture, SIGNAL(toggled(bool)), this, SLOT(UpdateRender())); connect(ui->useColor, SIGNAL(toggled(bool)), this, SLOT(UpdateRender())); connect(ui->useOpacity, SIGNAL(toggled(bool)), this, SLOT(UpdateRender())); connect(ui->colorRed, SIGNAL(valueChanged(double)), SLOT(UpdateRender())); connect(ui->colorGreen, SIGNAL(valueChanged(double)), SLOT(UpdateRender())); connect(ui->colorBlue, SIGNAL(valueChanged(double)), SLOT(UpdateRender())); connect(ui->opacity, SIGNAL(valueChanged(double)), SLOT(UpdateRender())); connect(ui->objectToggleVisibility, SIGNAL(clicked()), this, SLOT(ToogleCurrentObject())); // Waypoint connect(ui->setCurrentWaypoint, SIGNAL(clicked()), this, SLOT(SetCurrentWaypoint())); connect(ui->selectCurrentWaypoint, SIGNAL(clicked()), this, SLOT(SelectCurrentWaypoint())); // Behaviour connect(ui->objectTypeList, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateBehaviour())); connect(ui->character, SIGNAL(textChanged(QString)), this, SLOT(UpdateBehaviour())); connect(ui->dialog, SIGNAL(textChanged(QString)), this, SLOT(UpdateBehaviour())); connect(ui->script, SIGNAL(textChanged(QString)), this, SLOT(UpdateBehaviour())); connect(ui->doorLocked, SIGNAL(toggled(bool)), this, SLOT(UpdateBehaviour())); connect(ui->key, SIGNAL(textChanged(QString)), this, SLOT(UpdateBehaviour())); connect(ui->interactionUse, SIGNAL(toggled(bool)), this, SLOT(UpdateBehaviour())); connect(ui->interactionUseSkill, SIGNAL(toggled(bool)), this, SLOT(UpdateBehaviour())); connect(ui->interactionUseSpell, SIGNAL(toggled(bool)), this, SLOT(UpdateBehaviour())); connect(ui->interactionUseObject, SIGNAL(toggled(bool)), this, SLOT(UpdateBehaviour())); connect(ui->interactionLookAt, SIGNAL(toggled(bool)), this, SLOT(UpdateBehaviour())); connect(ui->interactionTalkTo, SIGNAL(toggled(bool)), this, SLOT(UpdateBehaviour())); connect(ui->selectCharacter, SIGNAL(clicked()), this, SLOT(SelectCharacter())); connect(ui->selectItem, SIGNAL(clicked()), this, SLOT(SelectItem())); connect(ui->selectKey, SIGNAL(clicked()), this, SLOT(SelectKey())); connect(ui->selectScript, SIGNAL(clicked()), this, SLOT(SelectScript())); connect(ui->selectDialog, SIGNAL(clicked()), this, SLOT(SelectDialog())); // Render Particles connect(ui->particleEffectName, SIGNAL(textChanged(QString)), this, SLOT(UpdateParticleEffect())); connect(ui->showParticleEffect, SIGNAL(clicked()), this, SLOT(RestartParticleEffect())); connect(ui->selectParticleEffect, SIGNAL(clicked()), this, SLOT(SelectParticleEffect())); ui->actionsButton->setMenu(&action_menu); action_menu.addAction("Copy", this, SIGNAL(CopyRequested()), QKeySequence::Copy); action_menu.addAction("Paste", this, SIGNAL(PasteRequested()), QKeySequence::Paste); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTFFlameThrower::PrimaryAttack() { // Are we capable of firing again? if ( m_flNextPrimaryAttack > gpGlobals->curtime ) return; // Get the player owning the weapon. CTFPlayer *pOwner = ToTFPlayer( GetPlayerOwner() ); if ( !pOwner ) return; if ( !CanAttack() ) { #if defined ( CLIENT_DLL ) StopFlame(); #endif m_iWeaponState = FT_STATE_IDLE; return; } CalcIsAttackCritical(); // Because the muzzle is so long, it can stick through a wall if the player is right up against it. // Make sure the weapon can't fire in this condition by tracing a line between the eye point and the end of the muzzle. trace_t trace; Vector vecEye = pOwner->EyePosition(); Vector vecMuzzlePos = GetVisualMuzzlePos(); CTraceFilterIgnoreObjects traceFilter( this, COLLISION_GROUP_NONE ); UTIL_TraceLine( vecEye, vecMuzzlePos, MASK_SOLID, &traceFilter, &trace ); if ( trace.fraction < 1.0 && ( !trace.m_pEnt || trace.m_pEnt->m_takedamage == DAMAGE_NO ) ) { // there is something between the eye and the end of the muzzle, most likely a wall, don't fire, and stop firing if we already are if ( m_iWeaponState > FT_STATE_IDLE ) { #if defined ( CLIENT_DLL ) StopFlame(); #endif m_iWeaponState = FT_STATE_IDLE; } return; } switch ( m_iWeaponState ) { case FT_STATE_IDLE: case FT_STATE_AIRBLASTING: { // Just started, play PRE and start looping view model anim pOwner->DoAnimationEvent( PLAYERANIMEVENT_ATTACK_PRE ); SendWeaponAnim( ACT_VM_PRIMARYATTACK ); m_flStartFiringTime = gpGlobals->curtime + 0.16; // 5 frames at 30 fps m_iWeaponState = FT_STATE_STARTFIRING; } break; case FT_STATE_STARTFIRING: { // if some time has elapsed, start playing the looping third person anim if ( gpGlobals->curtime > m_flStartFiringTime ) { m_iWeaponState = FT_STATE_FIRING; m_flNextPrimaryAttackAnim = gpGlobals->curtime; } } break; case FT_STATE_FIRING: { if ( gpGlobals->curtime >= m_flNextPrimaryAttackAnim ) { pOwner->DoAnimationEvent( PLAYERANIMEVENT_ATTACK_PRIMARY ); m_flNextPrimaryAttackAnim = gpGlobals->curtime + 1.4; // fewer than 45 frames! } } break; default: break; } #ifdef CLIENT_DLL // Restart our particle effect if we've transitioned across water boundaries if ( m_iParticleWaterLevel != -1 && pOwner->GetWaterLevel() != m_iParticleWaterLevel ) { if ( m_iParticleWaterLevel == WL_Eyes || pOwner->GetWaterLevel() == WL_Eyes ) { RestartParticleEffect(); } } #endif #ifdef CLIENT_DLL // Handle the flamethrower light if (tf2c_muzzlelight.GetBool()) { dlight_t *dl = effects->CL_AllocDlight(LIGHT_INDEX_MUZZLEFLASH + index); dl->origin = vecMuzzlePos; dl->color.r = 255; dl->color.g = 100; dl->color.b = 10; dl->die = gpGlobals->curtime + 0.01f; dl->radius = 240.f; dl->decay = 512.0f; dl->style = 5; } #endif #if !defined (CLIENT_DLL) // Let the player remember the usercmd he fired a weapon on. Assists in making decisions about lag compensation. pOwner->NoteWeaponFired(); pOwner->SpeakWeaponFire(); CTF_GameStats.Event_PlayerFiredWeapon( pOwner, m_bCritFire ); // Move other players back to history positions based on local player's lag lagcompensation->StartLagCompensation( pOwner, pOwner->GetCurrentCommand() ); #endif float flFiringInterval = m_pWeaponInfo->GetWeaponData( m_iWeaponMode ).m_flTimeFireDelay; CALL_ATTRIB_HOOK_FLOAT( flFiringInterval, mult_postfiredelay ); // Don't attack if we're underwater if ( pOwner->GetWaterLevel() != WL_Eyes ) { // Find eligible entities in a cone in front of us. Vector vOrigin = pOwner->Weapon_ShootPosition(); Vector vForward, vRight, vUp; QAngle vAngles = pOwner->EyeAngles() + pOwner->GetPunchAngle(); AngleVectors( vAngles, &vForward, &vRight, &vUp ); #define NUM_TEST_VECTORS 30 #ifdef CLIENT_DLL bool bWasCritical = m_bCritFire; #endif // Burn & Ignite 'em int iDmgType = g_aWeaponDamageTypes[ GetWeaponID() ]; m_bCritFire = IsCurrentAttackACrit(); if ( m_bCritFire ) { iDmgType |= DMG_CRITICAL; } #ifdef CLIENT_DLL if ( bWasCritical != m_bCritFire ) { RestartParticleEffect(); } #endif #ifdef GAME_DLL // create the flame entity int iDamagePerSec = m_pWeaponInfo->GetWeaponData( m_iWeaponMode ).m_nDamage; float flDamage = (float)iDamagePerSec * flFiringInterval; CALL_ATTRIB_HOOK_FLOAT( flDamage, mult_dmg ); CTFFlameEntity::Create( GetFlameOriginPos(), pOwner->EyeAngles(), this, iDmgType, flDamage ); #endif } #ifdef GAME_DLL // Figure how much ammo we're using per shot and add it to our remainder to subtract. (We may be using less than 1.0 ammo units // per frame, depending on how constants are tuned, so keep an accumulator so we can expend fractional amounts of ammo per shot.) // Note we do this only on server and network it to client. If we predict it on client, it can get slightly out of sync w/server // and cause ammo pickup indicators to appear float flAmmoPerSecond = TF_FLAMETHROWER_AMMO_PER_SECOND_PRIMARY_ATTACK; CALL_ATTRIB_HOOK_FLOAT( flAmmoPerSecond, mult_flame_ammopersec ); m_flAmmoUseRemainder += flAmmoPerSecond * flFiringInterval; // take the integer portion of the ammo use accumulator and subtract it from player's ammo count; any fractional amount of ammo use // remains and will get used in the next shot int iAmmoToSubtract = (int) m_flAmmoUseRemainder; if ( iAmmoToSubtract > 0 ) { pOwner->RemoveAmmo( iAmmoToSubtract, m_iPrimaryAmmoType ); m_flAmmoUseRemainder -= iAmmoToSubtract; // round to 2 digits of precision m_flAmmoUseRemainder = (float) ( (int) (m_flAmmoUseRemainder * 100) ) / 100.0f; } #endif m_flNextPrimaryAttack = gpGlobals->curtime + flFiringInterval; m_flTimeWeaponIdle = gpGlobals->curtime + flFiringInterval; #if !defined (CLIENT_DLL) lagcompensation->FinishLagCompensation( pOwner ); #endif }