public void StopAllActions( bool resetAnim ) { if ( m_RotationTimer != null ) { m_RotationTimer.Stop(); m_RotationTimer = null; } CancelAim( resetAnim ); CancelCharge(); CancelDefensiveFormation( resetAnim ); if ( m_DefenseTimer != null ) { if ( resetAnim ) m_DefenseTimer.Interrupt(); else m_DefenseTimer.Stop(); m_DefenseTimer = null; } if ( m_AttackTimer != null ) { if ( resetAnim ) m_AttackTimer.Interrupt(); else m_AttackTimer.Stop(); m_AttackTimer = null; } if ( resetAnim && m_AnimationTimer != null ) m_AnimationTimer.RefreshAnimation(); }
public void FinishDefense() { Mobile mob = AttachedTo as Mobile; IKhaerosMobile km = mob as IKhaerosMobile; BaseWeapon weapon = mob.Weapon as BaseWeapon; if ( m_DefenseTimer == null ) return; // we weren't defending int parries = m_DefenseTimer.Parries; DefenseType type = m_DefenseTimer.Type; /*bool weaponParrySuccess = false; if ( km != null && weapon != null && !( mob.FindItemOnLayer( Layer.TwoHanded) is BaseShield ) ) { if ( parries > 0 && km.Feats.GetFeatLevel(FeatList.WeaponParrying) > 0 && mob is PlayerMobile ) // weapon parrying feat { PlayerMobile pm = mob as PlayerMobile; if ( weapon.NameType == pm.WeaponSpecialization || weapon.NameType == pm.SecondSpecialization ) { if ( km.Feats.GetFeatLevel(FeatList.WeaponParrying) == 1 && type == DefenseType.ParrySwing ) weaponParrySuccess = true; else if ( km.Feats.GetFeatLevel(FeatList.WeaponParrying) == 2 && (type == DefenseType.ParrySwing || type == DefenseType.ParryThrust) ) weaponParrySuccess = true; else if ( km.Feats.GetFeatLevel(FeatList.WeaponParrying) >= 3 ) weaponParrySuccess = true; } } } if ( weaponParrySuccess ) m_NextAction = DateTime.Now;*/ m_DefenseTimer.Stop(); m_DefenseTimer = null; // reset animation if ( km.TrippedTimer == null ) ResetAnimation( mob ); else // assume 'dead' position again LoopLyingDownAnimation(); UpdateACBrainExternal(); //UpdateQueueDelay(); List<Mobile> opponents = new List<Mobile>( m_Aggressors ); // necessary due to concurrency foreach ( Mobile opponent in opponents ) GetCSA( opponent ).UpdateACBrainExternal(); }
// I've moved or turned public void OnMoved( Point3D oldLocation ) { m_LastAnimAction = DateTime.Now; Mobile mob = AttachedTo as Mobile; if ( m_RotationTimer != null ) { if ( oldLocation == mob.Location ) return; // we can't possibly stop this awesomeness else // foul play! { m_RotationTimer.Stop(); // stop that shit m_RotationTimer = null; } } CancelQueuedAction(); if ( m_DefensiveFormationTimer != null ) { m_DefensiveFormationTimer.Stop(); m_DefensiveFormationTimer = null; } if ( m_Charging ) { if ( mob.Hidden ) mob.RevealingAction(); if ( ((int)mob.Direction) <= 7 ) // walking in charge cancels it { mob.SendMessage( "You stopped running and thus fumbled your charge." ); CancelCharge(); } } // fumble my attack and defense if ( m_AttackTimer != null ) { m_AttackTimer.Stop(); m_AttackTimer = null; } if ( m_DefenseTimer != null ) { m_DefenseTimer.Stop(); m_DefenseTimer = null; } if ( m_DefensiveFormation ) { if ( mob.Location != oldLocation ) // not just turning CancelDefensiveFormation( false ); // moved while in defensive formation else // this needs a tiny delay, otherwise the animation is sent together with the 'movement' one Timer.DelayCall( TimeSpan.FromMilliseconds( 50 ), new TimerStateCallback( AnimationRefreshCallback ), this ); } if ( m_Aiming ) { if ( mob.Location != oldLocation ) // not just turning CancelAim( false ); // moved while aiming else // this needs a tiny delay, otherwise the animation is sent together with the 'movement' one Timer.DelayCall( TimeSpan.FromMilliseconds( 50 ), new TimerStateCallback( AnimationRefreshCallback ), this ); } // check if i'm showing my back to any of my combatants, if so, check if they're swinging anything, and make it connect List<Mobile> opponents = new List<Mobile>( m_Aggressors ); // necessary due to concurrency foreach ( Mobile opponent in opponents ) { GetCSA( opponent ).CheckForFreeAttack( mob, oldLocation ); GetCSA( opponent ).OnAfterOpponentMoved( mob ); } BaseWeapon weapon = mob.Weapon as BaseWeapon; int myRange = weapon.MaxRange; if ( AttachedTo is BaseCreature && ((BaseCreature)AttachedTo).RangeFight > myRange ) myRange = ((BaseCreature)AttachedTo).RangeFight; if ( m_Charging && m_Opponent != null ) { if ( m_Opponent.InRange( mob, myRange ) ) // we are in range, but charge might not be valid { if ( ValidateCharge( mob, m_Opponent ) ) { //mob.SendMessage( "Charge Okay." ); bool weWin = true; // we're going to strike them now, but let's see if they are, too if ( ValidateCharge( m_Opponent, mob ) ) { // seems they have a valid charge BaseWeapon opponentWeapon = m_Opponent.Weapon as BaseWeapon; int theirRange = opponentWeapon.MaxRange; if ( m_Opponent is BaseCreature && ((BaseCreature)m_Opponent).RangeFight > theirRange ) theirRange = ((BaseCreature)m_Opponent).RangeFight; if ( m_Opponent.InRange( mob, theirRange ) ) { // they can charge-strike us as well! lets make it somewhat randomized double myRidingSkill = mob.Skills[SkillName.Riding].Value + ((IKhaerosMobile)mob).RideBonus; double theirRidingSkill = m_Opponent.Skills[SkillName.Riding].Value + ((IKhaerosMobile)m_Opponent).RideBonus; if ( !mob.Mounted ) myRidingSkill = 0; if ( !m_Opponent.Mounted ) theirRidingSkill = 0; double myWeaponSkill = mob.Skills[weapon.Skill].Base; double theirWeaponSkill = m_Opponent.Skills[opponentWeapon.Skill].Base; double myTacticsSkill = mob.Skills[SkillName.Tactics].Base; double theirTacticsSkill = m_Opponent.Skills[SkillName.Tactics].Base; double ourSum = myRidingSkill + myWeaponSkill + myTacticsSkill; double theirSum = theirRidingSkill + theirWeaponSkill + theirTacticsSkill; double chance = ( ourSum / theirSum ) / 2; // fifty-fifty at same skills and backgrounds if ( Utility.RandomDouble() < chance ) weWin = true; else weWin = false; } } if ( weWin ) { double chargeBonus = CalculateChargeBonus( m_Opponent.Location ); m_ChargeEndTime = DateTime.Now; SetChargeCooldown(mob); ChargeIconRefreshCallback( AttachedTo ); Timer.DelayCall( GetChargeNoRunDelay(), new TimerStateCallback( ChargeIconRefreshCallback ), AttachedTo ); AttackType chargetype = ChargeAttackType( weapon ); m_AttackTimer = new AttackTimer( mob, chargetype, TimeSpan.Zero ); FinishAttack( chargeBonus ); CancelCharge(); } else // they win :( { CombatSystemAttachment opCSA = GetCSA( m_Opponent ); double chargeBonus = opCSA.CalculateChargeBonus( mob.Location ); opCSA.ChargeEndTime = DateTime.Now; SetChargeCooldown(m_Opponent); ChargeIconRefreshCallback( m_Opponent ); Timer.DelayCall( GetChargeNoRunDelay(), new TimerStateCallback( ChargeIconRefreshCallback ), m_Opponent ); AttackType chargetype = ChargeAttackType( m_Opponent.Weapon ); opCSA.AttackTimer = new AttackTimer( m_Opponent, chargetype, TimeSpan.Zero ); opCSA.FinishAttack( chargeBonus ); opCSA.CancelCharge(); } } else // this is a showstopper { if ( m_ErrorMessage != "" ) mob.SendMessage( m_ErrorMessage ); CancelCharge(); } } else if ( m_Opponent.InRange( mob, myRange+2 ) ) { GetCSA( m_Opponent ).ChargeAlert( ChargeAttackType( weapon ) ); // alerts auto combat } } else if ( m_BullRushing ) { IKhaerosMobile km = mob as IKhaerosMobile; if ( (mob.Direction&Direction.Mask) != m_BullRushDirection ) { m_BullRushing = false; mob.SendMessage( "Bull Rush interrupted due to not rushing in a straight line." ); } else { List<Mobile> list = new List<Mobile>(); int moveXOffset = 0; int moveYOffset = 0; switch ( mob.Direction&Direction.Mask ) { case Direction.South: case Direction.North: { moveXOffset = 1; break; } case Direction.West: case Direction.East: { moveYOffset = 1; break; } case Direction.Up: case Direction.Down: { moveXOffset = 1; moveYOffset = -1; break; } case Direction.Left: case Direction.Right: { moveXOffset = 1; moveYOffset = 1; break; } } foreach ( Mobile candidate in mob.GetMobilesInRange( myRange ) ) { if ( candidate != null && mob != candidate ) if ( IsOnCollisionCourse( candidate ) ) list.Add( candidate ); } foreach ( Mobile opponent in list ) { bool randomDir = Utility.RandomBool(); if ( !BaseAI.AreAllies( mob, opponent ) ) { // only attacks non-allies mob.Combatant = opponent; m_AttackTimer = new AttackTimer( mob, AttackType.Swing, TimeSpan.Zero ); FinishAttack(); } Point3D newLoc = new Point3D(); newLoc.X = opponent.Location.X + ( randomDir ? -1 : 1 ) * moveXOffset; newLoc.Y = opponent.Location.Y + ( randomDir ? -1 : 1 ) * moveYOffset; newLoc.Z = opponent.Location.Z; if ( opponent.Map.CanSpawnMobile( newLoc ) ) opponent.SetLocation( newLoc, true ); int additionalPush = 0; if ( km.Feats.GetFeatLevel(FeatList.BullRush) >= 3 ) additionalPush = 2; else if ( km.Feats.GetFeatLevel(FeatList.BullRush) == 2 ) additionalPush = 1; // move x more times if ( additionalPush > 0 ) GetCSA( opponent ).GotBullRushed( ( randomDir ? -1 : 1 ) * moveXOffset, ( randomDir ? -1 : 1 ) * moveYOffset, 2 ); } } m_BullRushSteps++; if ( m_BullRushSteps > km.Feats.GetFeatLevel(FeatList.BullRush) * 2 ) CancelSequences(); } UpdateACBrainExternal(); }
public bool BeginDefense( DefenseType defensetype, bool playerInitiated ) { Mobile defender = AttachedTo as Mobile; if ( !CanBeginCombatAction() || !CanBeginParry() ) return false; if ( m_Opponent != null && !m_PerformingSequence ) SpellHelper.Turn( defender, m_Opponent ); StopAllActions( false ); BaseShield shield = defender.FindItemOnLayer( Layer.TwoHanded ) as BaseShield; BaseWeapon twohander = defender.FindItemOnLayer( Layer.TwoHanded ) as BaseWeapon; BaseWeapon onehander = defender.FindItemOnLayer( Layer.OneHanded ) as BaseWeapon; if ( ((IKhaerosMobile)defender).TrippedTimer != null ) // always same animation if tripped { StopAnimating( false ); if ( defender.Body.Type == BodyType.Human ) { if ( twohander != null ) Animate( 21, 4, 1, false, false, 255 ); else Animate( 21, 5, 1, false, false, 255 ); } } int zMod = 0; if ( defender is BaseCreature ) zMod = ((BaseCreature)defender).Height; switch ( (int)defensetype ) { case (int)DefenseType.ParrySwing: { IEntity from = new Entity( Server.Serial.Zero, new Point3D( defender.X, defender.Y, defender.Z + zMod ), defender.Map ); IEntity to = new Entity( Server.Serial.Zero, new Point3D( defender.X, defender.Y, defender.Z + 25 + zMod*2 ), defender.Map ); SendCombatAlerts( from, to, 7035, 3, 0, true, false, 3, 2, 9501, 1, 0, EffectLayer.Head, 0x100 ); if ( ((IKhaerosMobile)defender).TrippedTimer == null ) { if ( defender.Body.Type == BodyType.Human ) { if ( defender.Mounted ) { if ( shield != null || twohander != null ) Animate( 27, 4, 1, false, false, 255 ); else Animate( 28, 2, 1, false, false, 255 ); } else Animate( 14, 2, 1, false, false, 255 ); } else { int[] anim = BAData.GetAnimation( defender, DefenseType.ParrySwing ); if ( anim != null ) Animate( anim[0], anim[1], 1, false, false, 255 ); } } break; } case (int)DefenseType.ParryThrust: { IEntity from = new Entity( Server.Serial.Zero, new Point3D( defender.X, defender.Y, defender.Z + zMod ), defender.Map ); IEntity to = new Entity( Server.Serial.Zero, new Point3D( defender.X, defender.Y, defender.Z + 25 + zMod*2 ), defender.Map ); SendCombatAlerts( from, to, 7035, 3, 0, true, false, 62, 2, 9501, 1, 0, EffectLayer.Head, 0x100 ); if ( ((IKhaerosMobile)defender).TrippedTimer == null ) { if ( defender.Body.Type == BodyType.Human ) { if ( defender.Mounted ) if ( twohander != null ) Animate( 28, 8, 1, false, false, 255 ); else Animate( 27, 2, 1, false, false, 255 ); else Animate( 16, 3, 1, false, false, 255 ); } else { int[] anim = BAData.GetAnimation( defender, DefenseType.ParryThrust ); if ( anim != null ) Animate( anim[0], anim[1], 1, false, false, 255 ); } } break; } case (int)DefenseType.ParryOverhead: { IEntity from = new Entity( Server.Serial.Zero, new Point3D( defender.X, defender.Y, defender.Z + zMod ), defender.Map ); IEntity to = new Entity( Server.Serial.Zero, new Point3D( defender.X, defender.Y, defender.Z + 25 + zMod*2 ), defender.Map ); SendCombatAlerts( from, to, 7035, 3, 0, true, false, 37, 2, 9501, 1, 0, EffectLayer.Head, 0x100 ); if ( ((IKhaerosMobile)defender).TrippedTimer == null ) { if ( defender.Body.Type == BodyType.Human ) { if ( defender.Mounted ) { if ( shield != null || onehander != null ) Animate( 27, 3, 1, false, false, 255 ); else Animate( 27, 2, 1, false, false, 255 ); } else { if ( shield != null ) Animate( 12, 2, 1, false, false, 255 ); else Animate( 17, 1, 1, false, false, 255 ); } } else { int[] anim = BAData.GetAnimation( defender, DefenseType.ParryOverhead ); if ( anim != null ) Animate( anim[0], anim[1], 1, false, false, 255 ); } } break; } } TimeSpan delay = TimeSpan.FromSeconds( 1.5 ); IKhaerosMobile km = defender as IKhaerosMobile; BaseWeapon weapon = defender.Weapon as BaseWeapon; if ( defender.FindItemOnLayer( Layer.TwoHanded ) is BaseShield ) { // we parried with a shield delay -= TimeSpan.FromSeconds( 0.5 ); // parrying with shield takes 0.5s less } else if ( km.Feats.GetFeatLevel(FeatList.WeaponParrying) > 0 && defender is PlayerMobile ) // weapon parrying feat { PlayerMobile pm = defender as PlayerMobile; if ( weapon.NameType == pm.WeaponSpecialization || weapon.NameType == pm.SecondSpecialization ) { if ( km.Feats.GetFeatLevel(FeatList.WeaponParrying) == 1 ) delay -= TimeSpan.FromSeconds( 0.125 ); else if ( km.Feats.GetFeatLevel(FeatList.WeaponParrying) == 2 ) delay -= TimeSpan.FromSeconds( 0.25 ); else if ( km.Feats.GetFeatLevel(FeatList.WeaponParrying) == 3 ) delay -= TimeSpan.FromSeconds( 0.5 ); } } m_NextDefenseAction = DateTime.Now + delay; m_DefenseTimer = new DefenseTimer( defender, defensetype, TimeSpan.FromSeconds( GetParryDuration() ) ); m_DefenseTimer.Start(); if ( BandageContext.GetContext( defender ) != null ) { BandageContext.GetContext( defender ).StopHeal(); if ( defender is IKhaerosMobile ) { if ( ((IKhaerosMobile)defender).HealingTimer != null ) { ((IKhaerosMobile)defender).HealingTimer.Stop(); ((IKhaerosMobile)defender).HealingTimer = null; } } } return true; }