void CActorControllerComponent::OnActionSitToggle() { if (GetStance() == EActorStance::eAS_SittingFloor) SetStance(EActorStance::eAS_Standing); else SetStance(EActorStance::eAS_SittingFloor); }
//----------------------------------------------------------------------------- // Purpose: Allows firing as fast as button is pressed //----------------------------------------------------------------------------- void CWeaponAK47::ItemPostFrame( void ) { BaseClass::ItemPostFrame(); if ( m_bInReload ) { return; } CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); if ( pOwner == NULL ) { return; } if ( pOwner->m_nButtons & IN_ATTACK ) { if (m_flAttackEnds<gpGlobals->curtime) { SendWeaponAnim(ACT_VM_IDLE); } } else { //The firing cycle ended. Reset the burst counter to the max value m_iBurst=BURST; if ( ( pOwner->m_nButtons & IN_ATTACK ) && ( m_flNextPrimaryAttack < gpGlobals->curtime ) && ( m_iClip1 <= 0 ) ) { DryFire(); } } CheckZoomToggle(); //check the character's current stance for the accuracy calculation GetStance(); }
void CActorControllerComponent::OnActionKneelToggle() { if (GetStance() == EActorStance::eAS_Kneeling) SetStance(EActorStance::eAS_Standing); else SetStance(EActorStance::eAS_Kneeling); }
void CActorControllerComponent::OnActionCrouchToggle() { if (GetStance() == EActorStance::eAS_Crouching) SetStance(EActorStance::eAS_Standing); else SetStance(EActorStance::eAS_Crouching); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CWeaponAK47::ItemPreFrame( void ) { GetStance(); BaseClass::ItemPreFrame(); }
float CActorControllerComponent::GetMovementBaseSpeed(TInputFlags movementDirectionFlags) const { const static float walkBaseSpeed { 2.1f }; const static float jogBaseSpeed { 4.2f }; const static float runBaseSpeed { 6.3f }; const static float crawlBaseSpeed { 1.2f }; const static float proneBaseSpeed { 0.4f }; const static float crouchBaseSpeed { 1.2f }; float baseSpeed { 0.0f }; float dirScale { 1.0f }; switch (GetStance()) { case EActorStance::eAS_Standing: // Work out a base for walking, jogging or sprinting. if (IsSprinting()) { baseSpeed = runBaseSpeed; } else { if (IsJogging()) baseSpeed = jogBaseSpeed; else baseSpeed = walkBaseSpeed; } break; case EActorStance::eAS_Crawling: baseSpeed = crawlBaseSpeed; break; case EActorStance::eAS_Prone: baseSpeed = proneBaseSpeed; break; case EActorStance::eAS_Crouching: baseSpeed = crouchBaseSpeed; break; case EActorStance::eAS_Swimming: baseSpeed = walkBaseSpeed; break; case EActorStance::eAS_Flying: baseSpeed = jogBaseSpeed; break; case EActorStance::eAS_Spellcasting: baseSpeed = walkBaseSpeed; break; default: // Don't let them control movement. baseSpeed = 0.0f; break; } // Scale it based on their movement direction. switch (movementDirectionFlags) { case (TInputFlags)EInputFlag::Forward: dirScale = 1.0f; break; case ((TInputFlags)EInputFlag::Forward | (TInputFlags)EInputFlag::Right): dirScale = 0.9f; break; case ((TInputFlags)EInputFlag::Forward | (TInputFlags)EInputFlag::Left): dirScale = 0.9f; break; case (TInputFlags)EInputFlag::Right: dirScale = 0.85f; break; case (TInputFlags)EInputFlag::Left: dirScale = 0.85f; break; case (TInputFlags)EInputFlag::Backward: dirScale = 0.71f; break; case ((TInputFlags)EInputFlag::Backward | (TInputFlags)EInputFlag::Right): dirScale = 0.71f; break; case ((TInputFlags)EInputFlag::Backward | (TInputFlags)EInputFlag::Left): dirScale = 0.71f; break; default: dirScale = 0.0f; break; } return baseSpeed * dirScale; }
void CombatManager::ApplyCombatEvent(psCombatGameEvent *event, int attack_result) { psCharacter *attacker_data = event->GetAttackerData(); psCharacter *target_data=event->GetTargetData(); MathVar *weaponDecay = NULL; MathVar *blockDecay = NULL; MathVar *armorDecay = NULL; MathEnvironment env; psItem *weapon = attacker_data->Inventory().GetEffectiveWeaponInSlot(event->GetWeaponSlot()); psItem *blockingWeapon = target_data->Inventory().GetEffectiveWeaponInSlot(event->GetWeaponSlot(),true); psItem *struckArmor = target_data->Inventory().GetEffectiveArmorInSlot(event->AttackLocation); // there may only be a decay if you actually hit your target by some means if(attack_result == ATTACK_DAMAGE || attack_result == ATTACK_BLOCKED) { // we are guaranteed some armor is present - real one, race one or base one CS_ASSERT(struckArmor); float ArmorVsWeapon = weapon->GetArmorVSWeaponResistance(struckArmor->GetBaseStats()); // clamp value between 0 and 1 ArmorVsWeapon = ArmorVsWeapon > 1.0F ? 1.0F : ArmorVsWeapon < 0.0F ? 0.0F : ArmorVsWeapon; env.Define("Weapon", weapon); // weapon that was used to attack env.Define("BlockingWeapon", blockingWeapon); // weapon that blocked the attack env.Define("Armor", struckArmor); // armor hit env.Define("ArmorVsWeapon", ArmorVsWeapon); // armor vs weapon effectiveness env.Define("Damage", event->FinalDamage); // actual damage dealt env.Define("Blocked", (attack_result == ATTACK_BLOCKED)); // identifies whether this attack was blocked calc_decay->Evaluate(&env); weaponDecay = env.Lookup("WeaponDecay"); blockDecay = env.Lookup("BlockingDecay"); armorDecay = env.Lookup("ArmorDecay"); } gemActor *gemAttacker = dynamic_cast<gemActor*> ((gemObject *) event->attacker); gemActor *gemTarget = dynamic_cast<gemActor*> ((gemObject *) event->target); switch (attack_result) { case ATTACK_DAMAGE: { bool isNearlyDead = false; if (target_data->GetMaxHP().Current() > 0.0 && target_data->GetHP()/target_data->GetMaxHP().Current() > 0.2) { if ((target_data->GetHP() - event->FinalDamage) / target_data->GetMaxHP().Current() <= 0.2) isNearlyDead = true; } psCombatEventMessage ev(event->AttackerCID, isNearlyDead ? psCombatEventMessage::COMBAT_DAMAGE_NEARLY_DEAD : psCombatEventMessage::COMBAT_DAMAGE, gemAttacker->GetEID(), gemTarget->GetEID(), event->AttackLocation, event->FinalDamage, weapon->GetAttackAnimID(gemAttacker->GetCharacterData()), gemTarget->FindAnimIndex("hit")); ev.Multicast(gemTarget->GetMulticastClients(),0,MAX_COMBAT_EVENT_RANGE); // Apply final damage if (target_data!=NULL) { gemTarget->DoDamage(gemAttacker,event->FinalDamage); if (gemAttacker) { gemAttacker->InvokeAttackScripts(gemTarget, weapon); } if (gemTarget) { gemTarget->InvokeDefenseScripts(gemAttacker, weapon); if(isNearlyDead) { gemTarget->InvokeNearlyDeadScripts(gemAttacker, weapon); } } } // If the target wasn't in combat, it is now... // Note that other modes shouldn't be interrupted automatically if (gemTarget->GetMode() == PSCHARACTER_MODE_PEACE || gemTarget->GetMode() == PSCHARACTER_MODE_WORK) { if (gemTarget->GetClient()) // Set reciprocal target gemTarget->GetClient()->SetTargetObject(gemAttacker,true); // The default stance is 'Fully Defensive'. Stance initialStance = GetStance(cacheManager, "FullyDefensive"); AttackSomeone(gemTarget,gemAttacker,initialStance); } if (weapon) { weapon->AddDecay(weaponDecay->GetValue()); } if (struckArmor) { struckArmor->AddDecay(armorDecay->GetValue()); } NotifyTarget(gemAttacker,gemTarget); break; } case ATTACK_DODGED: { psCombatEventMessage ev(event->AttackerCID, psCombatEventMessage::COMBAT_DODGE, gemAttacker->GetEID(), gemTarget->GetEID(), event->AttackLocation, 0, // no dmg on a dodge weapon->GetAttackAnimID(gemAttacker->GetCharacterData()), (unsigned int)-1); // no defense anims yet ev.Multicast(gemTarget->GetMulticastClients(),0,MAX_COMBAT_EVENT_RANGE); NotifyTarget(gemAttacker,gemTarget); break; } case ATTACK_BLOCKED: { psCombatEventMessage ev(event->AttackerCID, psCombatEventMessage::COMBAT_BLOCK, gemAttacker->GetEID(), gemTarget->GetEID(), event->AttackLocation, 0, // no dmg on a block weapon->GetAttackAnimID( gemAttacker->GetCharacterData() ), (unsigned int)-1); // no defense anims yet ev.Multicast(gemTarget->GetMulticastClients(),0,MAX_COMBAT_EVENT_RANGE); if (weapon) { weapon->AddDecay(weaponDecay->GetValue()); } if (blockingWeapon) { blockingWeapon->AddDecay(blockDecay->GetValue()); } NotifyTarget(gemAttacker,gemTarget); break; } case ATTACK_MISSED: { psCombatEventMessage ev(event->AttackerCID, psCombatEventMessage::COMBAT_MISS, gemAttacker->GetEID(), gemTarget->GetEID(), event->AttackLocation, 0, // no dmg on a miss weapon->GetAttackAnimID( gemAttacker->GetCharacterData() ), (unsigned int)-1); // no defense anims yet ev.Multicast(gemTarget->GetMulticastClients(),0,MAX_COMBAT_EVENT_RANGE); NotifyTarget(gemAttacker,gemTarget); break; } case ATTACK_OUTOFRANGE: { if (event->AttackerCID) { psserver->SendSystemError(event->AttackerCID,"You are too far away to attack!"); // Auto-stop attack is commented out below, when out of range to prevent npc kiting by jumping in and out of range //if (event->attacker && event->attacker.IsValid()) // StopAttack(dynamic_cast<gemActor*>((gemObject *) event->attacker)); // if you run away, you exit attack mode } break; } case ATTACK_BADANGLE: { if (event->AttackerCID) // if human player { psserver->SendSystemError(event->AttackerCID,"You must face the enemy to attack!"); // Auto-stop attack is commented out below, when out of range to prevent npc kiting by jumping in and out of range //if (event->attacker && event->attacker.IsValid()) // StopAttack(dynamic_cast<gemActor*>((gemObject *) event->attacker)); // if you run away, you exit attack mode } break; } case ATTACK_OUTOFAMMO: { psserver->SendSystemError(event->AttackerCID, "You are out of ammo!"); if (event->attacker && event->attacker.IsValid()) StopAttack(dynamic_cast<gemActor*>((gemObject *) event->attacker)); // if you run out of ammo, you exit attack mode break; } } }