//private static readonly MotionState motionStateOpen = new UniversalMotion(MotionStance.Standing, new MotionItem(MotionCommand.On)); //private static readonly MotionState motionStateClosed = new UniversalMotion(MotionStance.Standing, new MotionItem(MotionCommand.Off)); /// <summary> /// This is raised by Player.HandleActionUseItem, and is wrapped in ActionChain.<para /> /// The actor of the ActionChain is the item being used.<para /> /// The item does not exist in the players possession.<para /> /// If the item was outside of range, the player will have been commanded to move using DoMoveTo before ActOnUse is called.<para /> /// When this is called, it should be assumed that the player is within range. /// </summary> public override void ActOnUse(WorldObject worldObject) { if (worldObject is Player) { var player = worldObject as Player; ////if (playerDistanceTo >= 2500) ////{ //// var sendTooFarMsg = new GameEventDisplayStatusMessage(player.Session, StatusMessageType1.Enum_0037); //// player.Session.Network.EnqueueSend(sendTooFarMsg, sendUseDoneEvent); //// return; ////} if (!(IsLocked ?? false)) { if (!(IsOpen ?? false)) { var turnToMotion = new UniversalMotion(MotionStance.Standing, Location, Guid); turnToMotion.MovementTypes = MovementTypes.TurnToObject; ActionChain turnToTimer = new ActionChain(); turnToTimer.AddAction(this, () => player.CurrentLandblock.EnqueueBroadcastMotion(player, turnToMotion)); turnToTimer.AddDelaySeconds(1); turnToTimer.AddAction(this, () => Open(player)); turnToTimer.EnqueueChain(); return; } if (Viewer == player.Guid.Full) { Close(player); } // else error msg? } else { CurrentLandblock.EnqueueBroadcastSound(this, Sound.OpenFailDueToLock); } player.SendUseDoneEvent(); } }
// Called by the Landblock for books that are WorldObjects (some notes pinned to the ground, statues, pedestals and tips in training academy, etc public override void ActOnUse(ObjectGuid playerId) { Player player = CurrentLandblock.GetObject(playerId) as Player; if (player == null) { return; } // Make sure player is within the use radius of the item. if (!player.IsWithinUseRadiusOf(this)) { player.DoMoveTo(this); } else { BookUseHandler(player.Session); } }
/// <summary> /// Sends object description if the client requests it /// </summary> /// <param name="item"></param> public void HandleActionForceObjDescSend(ObjectGuid item) { ActionChain objDescChain = new ActionChain(); objDescChain.AddAction(this, () => { WorldObject wo = GetInventoryItem(item); if (wo != null) { CurrentLandblock.EnqueueBroadcast(Location, Landblock.MaxObjectRange, new GameMessageObjDescEvent(wo)); } else { log.Debug($"Error - requested object description for an item I do not know about - {item.Full:X}"); } }); objDescChain.EnqueueChain(); }
/// <summary> /// Called by network packet handler 0xA - GameActionTargetedMissileAttack /// </summary> /// <param name="guid">The target guid</param> /// <param name="attackHeight">The attack height 1-3</param> /// <param name="accuracyLevel">The 0-1 accuracy bar level</param> public void HandleActionTargetedMissileAttack(ObjectGuid guid, uint attackHeight, float accuracyLevel) { var weapon = GetEquippedMissileWeapon(); var ammo = GetEquippedAmmo(); // sanity check accuracyLevel = Math.Clamp(accuracyLevel, 0.0f, 1.0f); if (weapon == null || weapon.IsAmmoLauncher && ammo == null) { return; } AttackHeight = (AttackHeight)attackHeight; AccuracyLevel = accuracyLevel; // get world object of target guid var target = CurrentLandblock?.GetObject(guid); if (target == null) { log.Warn("Unknown target guid " + guid.Full.ToString("X8")); return; } if (MissileTarget == null) { MissileTarget = target; } else { return; } // turn if required var rotateTime = Rotate(target); var actionChain = new ActionChain(); actionChain.AddDelaySeconds(rotateTime); // do missile attack actionChain.AddAction(this, () => LaunchMissile(target)); actionChain.EnqueueChain(); }
public override void HandleActionOnUse(ObjectGuid playerId) { ActionChain chain = new ActionChain(); CurrentLandblock.ChainOnObject(chain, playerId, (WorldObject wo) => { Player player = wo as Player; if (player == null) { return; } ////if (playerDistanceTo >= 2500) ////{ //// var sendTooFarMsg = new GameEventDisplayStatusMessage(player.Session, StatusMessageType1.Enum_0037); //// player.Session.Network.EnqueueSend(sendTooFarMsg, sendUseDoneEvent); //// return; ////} if (!player.IsWithinUseRadiusOf(this)) { player.DoMoveTo(this); } else { ActionChain useObjectChain = new ActionChain(); useObjectChain.AddAction(this, () => { if (AllowedActivator == null) { Activate(playerId); } var sendUseDoneEvent = new GameEventUseDone(player.Session); player.Session.Network.EnqueueSend(sendUseDoneEvent); }); useObjectChain.EnqueueChain(); } }); chain.EnqueueChain(); }
/// <summary> /// Launches a missile attack from player to target /// </summary> public void LaunchMissile(WorldObject target) { if (GetEquippedAmmo() == null || CombatMode == CombatMode.NonCombat) { return; } var creature = target as Creature; if (MissileTarget == null || creature.Health.Current <= 0) { MissileTarget = null; return; } var weapon = GetEquippedWeapon(); var sound = weapon.DefaultCombatStyle == CombatStyle.Crossbow ? Sound.CrossbowRelease : Sound.BowRelease; CurrentLandblock.EnqueueBroadcast(Location, new GameMessageSound(Guid, sound, 1.0f)); float targetTime = 0.0f; var damageSource = LaunchProjectile(target, out targetTime); // todo: get correct animlengths for shoot + reload + aim var animLength = ReloadMotion() * 2.5f; var actionChain = new ActionChain(); //actionChain.AddDelaySeconds(targetTime); //actionChain.AddAction(this, () => DamageTarget(target, damageSource)); if (creature.Health.Current > 0 && GetCharacterOption(CharacterOption.AutoRepeatAttacks)) { // reload animation, accuracy bar refill actionChain.AddDelaySeconds(animLength + AccuracyLevel); actionChain.AddAction(this, () => { LaunchMissile(target); }); actionChain.EnqueueChain(); } else { MissileTarget = null; } }
private void Activate(ObjectGuid activator = new ObjectGuid()) { AllowedActivator = activator.Full; CurrentLandblock?.EnqueueBroadcastMotion(this, motionTipRight); // Stamp Cow tipping quest here; ActionChain autoResetTimer = new ActionChain(); autoResetTimer.AddDelaySeconds(4); autoResetTimer.AddAction(this, () => ResetCow()); autoResetTimer.EnqueueChain(); if (activator.Full > 0) { UseTimestamp++; } }
/// <summary> /// Learns spells in bulk, without notification, filtered by school and level /// </summary> public void LearnSpellsInBulk(uint magicSchool, uint spellLevel) { var spells = DatManager.PortalDat.SpellTable.Spells; Player player = CurrentLandblock.GetObject(Guid) as Player; if (Enum.IsDefined(typeof(SpellLevel), (int)WorldObject.CalculateSpellLevel(spellLevel))) { foreach (var spell in spells) { if ((magicSchool == (uint)spell.Value.School) & ((uint)WorldObject.CalculateSpellLevel(spellLevel) == spell.Value.Power)) { if (Enum.IsDefined(typeof(Network.Enum.Spell), spell.Key)) { player.LearnSpellWithNetworking((uint)spell.Key, false); } } } } }
/// <summary> /// Fired when Client clicks on the Vendor World Object /// </summary> /// <param name="playerId"></param> public override void ActOnUse(ObjectGuid playerId) { Player player = CurrentLandblock.GetObject(playerId) as Player; if (player == null) { return; } if (!player.IsWithinUseRadiusOf(this)) { player.DoMoveTo(this); } else { LoadInventory(); ApproachVendor(player); } }
/// <summary> /// This method will remove a worldobject if we have consumed all of the amount in the merge. /// This checks inventory or wielded items (you could be pulling stackable ammo out of a wielded slot and into a stack in your pack /// It then creates and sends the remove object message. Lastly, if the wo has ever been saved to the db, we clean up after ourselves. /// </summary> /// <param name="session">Session is used for sequence and target</param> /// <param name="fromWo">World object of the item are we merging from that needs to be destroyed.</param> public void RemoveWorldObject(Session session, WorldObject fromWo) { if (HasItem(fromWo.Guid)) { session.Player.RemoveWorldObjectFromInventory(fromWo.Guid); } else { session.Player.RemoveFromWieldedObjects(fromWo.Guid); } GameMessageRemoveObject msgRemoveFrom = new GameMessageRemoveObject(fromWo); CurrentLandblock.EnqueueBroadcast(Location, MaxObjectTrackingRange, msgRemoveFrom); if (fromWo.SnapShotOfAceObject().HasEverBeenSavedToDatabase) { DatabaseManager.Shard.DeleteObject(fromWo.SnapShotOfAceObject(), null); } }
public override void OnCollideEnvironment() { if (!PhysicsObj.is_active()) { return; } //Console.WriteLine("Projectile.OnCollideEnvironment(" + Guid.Full.ToString("X8") + ")"); CurrentLandblock.RemoveWorldObject(Guid, false); PhysicsObj.set_active(false); var player = ProjectileSource as Player; if (player != null) { player.Session.Network.EnqueueSend(new GameMessageSystemChat("Your missile attack hit the environment.", ChatMessageType.Broadcast)); } }
public virtual void ActivateLinks(List <LandblockInstance> sourceObjects) { if (LinkedInstances.Count == 0) { return; } if (IsGenerator) { AddGeneratorLinks(); return; } foreach (var link in LinkedInstances) { var wo = WorldObjectFactory.CreateWorldObject(DatabaseManager.World.GetCachedWeenie(link.WeenieClassId), new ObjectGuid(link.Guid)); if (wo == null) { continue; } wo.Location = new Position(link.ObjCellId, link.OriginX, link.OriginY, link.OriginZ, link.AnglesX, link.AnglesY, link.AnglesZ, link.AnglesW); wo.ActivationTarget = Guid.Full; CurrentLandblock?.AddWorldObject(wo); // process nested links recursively foreach (var subLink in link.LandblockInstanceLink) { var linkInstance = sourceObjects.FirstOrDefault(x => x.Guid == subLink.ChildGuid); if (linkInstance != null) { wo.LinkedInstances.Add(linkInstance); } } if (wo.LinkedInstances.Count > 0) { wo.ActivateLinks(sourceObjects); } } }
/// <summary> /// Handles player targeted casting message /// </summary> public void HandleActionCastTargetedSpell(ObjectGuid guidTarget, uint spellId) { Player player = CurrentLandblock.GetObject(Guid) as Player; WorldObject target = CurrentLandblock.GetObject(guidTarget) as WorldObject; TargetCategory targetCategory = TargetCategory.WorldObject; if (guidTarget == Guid) { targetCategory = TargetCategory.Self; } if (target == null) { target = GetWieldedItem(guidTarget); targetCategory = TargetCategory.Wielded; } if (target == null) { target = GetInventoryItem(guidTarget); targetCategory = TargetCategory.Inventory; } if (target == null) { player.Session.Network.EnqueueSend(new GameEventUseDone(player.Session, errorType: WeenieError.TargetNotAcquired)); targetCategory = TargetCategory.UnDef; return; } if (targetCategory != TargetCategory.WorldObject) { CreatePlayerSpell(guidTarget, spellId); } else { // turn if required var rotateTime = Rotate(target) - 0.25f; var actionChain = new ActionChain(); actionChain.AddDelaySeconds(rotateTime); actionChain.AddAction(this, () => CreatePlayerSpell(guidTarget, spellId)); actionChain.EnqueueChain(); } }
/// <summary> /// This is raised by Player.HandleActionUseItem.<para /> /// The item does not exist in the players possession.<para /> /// If the item was outside of range, the player will have been commanded to move using DoMoveTo before ActOnUse is called.<para /> /// When this is called, it should be assumed that the player is within range. /// </summary> public override void ActOnUse(WorldObject wo) { if (!(wo is Player player)) { return; } // If we have a previous container open, let's close it if (player.LastOpenedContainerId != ObjectGuid.Invalid && player.LastOpenedContainerId != Guid) { var lastOpenedContainer = CurrentLandblock?.GetObject(player.LastOpenedContainerId) as Container; if (lastOpenedContainer != null && lastOpenedContainer.IsOpen && lastOpenedContainer.Viewer == player.Guid.Full) { lastOpenedContainer.Close(player); } } if ((OwnerId.HasValue && OwnerId.Value > 0) || (ContainerId.HasValue && ContainerId.Value > 0)) { return; // Do nothing else if container is owned by something. } if (!IsOpen) { Open(player); } else { if (Viewer == 0) { Close(null); } else if (Viewer == player.Guid.Full) { Close(player); } else { player.SendTransientError(InUseMessage); } } }
/// <summary> /// This is raised by Player.HandleActionUseItem.<para /> /// The item does not exist in the players possession.<para /> /// If the item was outside of range, the player will have been commanded to move using DoMoveTo before ActOnUse is called.<para /> /// When this is called, it should be assumed that the player is within range. /// </summary> public override void ActOnUse(WorldObject wo) { if (!(wo is Player player)) { return; } // If we have a previous container open, let's close it if (player.LastOpenedContainerId != ObjectGuid.Invalid && player.LastOpenedContainerId != Guid) { var lastOpenedContainer = CurrentLandblock?.GetObject(player.LastOpenedContainerId) as Container; if (lastOpenedContainer != null && lastOpenedContainer.IsOpen && lastOpenedContainer.Viewer == player.Guid.Full) { lastOpenedContainer.Close(player); } } if ((OwnerId.HasValue && OwnerId.Value > 0) || (ContainerId.HasValue && ContainerId.Value > 0)) { return; // Do nothing else if container is owned by something. } if (!IsOpen) { Open(player); } else { if (Viewer == 0) { Close(null); } else if (Viewer == player.Guid.Full) { Close(player); } else { player.Session.Network.EnqueueSend(new GameEventCommunicationTransientString(player.Session, $"The {Name} is already in use by someone else!")); } } }
public void HandleActionQueryHealth(ObjectGuid queryId) { if (queryId.Full == 0) { // Deselect the formerly selected Target selectedTarget = ObjectGuid.Invalid; HealthQueryTarget = null; return; } // Remember the selected Target selectedTarget = queryId; HealthQueryTarget = queryId.Full; var obj = CurrentLandblock.GetObject(queryId); if (obj != null) { obj.QueryHealth(Session); } }
/// <summary> /// This will remove the Wielder and CurrentWieldedLocation properties on the item and will remove it from the EquippedObjects dictionary.<para /> /// It does not add it to inventory as you could be unwielding to the ground or a chest. Og II<para /> /// It will also decrease the EncumbranceVal and Value. /// </summary> public bool TryDequipObject(ObjectGuid objectGuid, out WorldObject worldObject) { if (EquippedObjects.Remove(objectGuid, out worldObject)) { worldObject.RemoveProperty(PropertyInt.CurrentWieldedLocation); worldObject.RemoveProperty(PropertyInstanceId.Wielder); EncumbranceVal -= worldObject.EncumbranceVal; Value -= worldObject.Value; if (CurrentLandblock != null) { CurrentLandblock.EnqueueActionBroadcast(Location, Landblock.MaxObjectRange, (Player p) => p.TrackObject(this)); } return(true); } return(false); }
/*public AceObject SnapShotOfAceObject(bool clearDirtyFlags = false) * { * AceObject snapshot = (AceObject)AceObject.Clone(); * if (clearDirtyFlags) * AceObject.ClearDirtyFlags(); * return snapshot; * }*/ public virtual void ActOnUse(ObjectGuid playerId) { // Do Nothing by default if (CurrentLandblock != null) { Player player = CurrentLandblock.GetObject(playerId) as Player; if (player == null) { return; } #if DEBUG var errorMessage = new GameMessageSystemChat($"Default HandleActionOnUse reached, this object ({Name}) not programmed yet.", ChatMessageType.System); player.Session.Network.EnqueueSend(errorMessage); #endif var sendUseDoneEvent = new GameEventUseDone(player.Session); player.Session.Network.EnqueueSend(sendUseDoneEvent); } }
/// <summary> /// This method is called if we unwield missle ammo. It will check to see if I have arrows wielded /// send the message to "hide" the arrow. /// </summary> /// <param name="oldCombatMode"></param> public void HandleUnloadMissileAmmo(CombatMode oldCombatMode) { // Before I can switch to any non missile mode, do I have missile ammo I need to remove? WorldObject ammo = null; HeldItem mEquipedAmmo = Children.Find(s => s.EquipMask == EquipMask.MissileAmmo); if (mEquipedAmmo != null) { ammo = GetInventoryItem(new ObjectGuid(mEquipedAmmo.Guid)); } if (oldCombatMode == CombatMode.Missile) { if (ammo != null) { ammo.Location = null; CurrentLandblock.EnqueueBroadcast(Location, Landblock.MaxObjectRange, new GameMessagePickupEvent(ammo)); } } }
/// <summary> /// This method sets us into peace mode. It checks our current state to see if we have missle ammo equipped /// it will make the call to hid the "ammo" as we switch to peace mode. It will then send the message switch our stance. Og II /// </summary> /// <param name="oldCombatMode"></param> /// <param name="isAutonomous"></param> public void HandleSwitchToPeaceMode(CombatMode oldCombatMode, bool isAutonomous = false) { HandleUnloadMissileAmmo(oldCombatMode); // FIXME: (Og II)<this is a hack for now to be removed.> Placement has an issue we have not figured out. It has to do with animation frame. Og II PositionFlag &= ~UpdatePositionFlag.Placement; // End hack CurrentLandblock.EnqueueBroadcast(Location, Landblock.MaxObjectRange, new GameMessageUpdatePosition(this)); UniversalMotion mm = new UniversalMotion(MotionStance.Standing); mm.MovementData.CurrentStyle = (uint)MotionStance.Standing; SetMotionState(this, mm); var mEquipedAmmo = WieldedObjects.FirstOrDefault(s => s.Value.CurrentWieldedLocation == EquipMask.MissileAmmo).Value; CurrentLandblock.EnqueueBroadcast(Location, Landblock.MaxObjectRange, new GameMessagePrivateUpdatePropertyInt(Sequences, PropertyInt.CombatMode, (uint)CombatMode.NonCombat)); if (mEquipedAmmo != null) { CurrentLandblock.EnqueueBroadcast(Location, Landblock.MaxObjectGhostRange, new GameMessagePickupEvent(mEquipedAmmo)); } }
public void HandleActionQueryHealth(uint objectGuid) { if (objectGuid == 0) { // Deselect the formerly selected Target selectedTarget = ObjectGuid.Invalid; HealthQueryTarget = null; return; } // Remember the selected Target selectedTarget = new ObjectGuid(objectGuid); HealthQueryTarget = objectGuid; var obj = CurrentLandblock?.GetObject(objectGuid); if (obj != null) { obj.QueryHealth(Session); } }
public override void ActOnUse(ObjectGuid playerId) { var player = CurrentLandblock.GetObject(playerId) as Player; if (player == null) { return; } if (!player.IsWithinUseRadiusOf(this)) { player.DoMoveTo(this); } else { ActionChain sancTimer = new ActionChain(); sancTimer.AddAction(player, () => { CurrentLandblock.EnqueueBroadcastMotion(player, sanctuary); CurrentLandblock.EnqueueBroadcastSound(player, Sound.LifestoneOn, 1); }); sancTimer.AddDelaySeconds(DatManager.PortalDat.ReadFromDat <MotionTable>(player.MotionTableId).GetAnimationLength(MotionCommand.Sanctuary)); sancTimer.AddAction(player, () => { if (player.IsWithinUseRadiusOf(this)) { player.Session.Network.EnqueueSend(new GameMessageSystemChat(GetProperty(PropertyString.UseMessage), ChatMessageType.Magic)); player.Sanctuary = player.Location; } // Unsure if there was a fail message... //else //{ // var serverMessage = "You wandered too far to attune with the Lifestone!"; // player.Session.Network.EnqueueSend(new GameMessageSystemChat(serverMessage, ChatMessageType.Magic)); //} player.SendUseDoneEvent(); }); sancTimer.EnqueueChain(); } }
/// <summary> /// Launches a missile attack from monster to target /// </summary> public void RangeAttack() { var dist = GetDistanceToTarget(); //Console.WriteLine("RangeAttack: " + dist); NextAttackTime = Timer.CurrentTime + MissileDelay; var weapon = GetEquippedWeapon(); var sound = weapon.DefaultCombatStyle == CombatStyle.Crossbow ? Sound.CrossbowRelease : Sound.BowRelease; CurrentLandblock.EnqueueBroadcast(Location, new GameMessageSound(Guid, sound, 1.0f)); var player = AttackTarget as Player; var bodyPart = GetBodyPart(); float targetTime = 0.0f; var damageSource = LaunchProjectile(AttackTarget, out targetTime); var animLength = ReloadMotion(); var actionChain = new ActionChain(); actionChain.AddDelaySeconds(targetTime); actionChain.AddAction(this, () => { var critical = false; var damageType = DamageType.Undef; var damage = CalculateDamage(ref damageType, bodyPart, ref critical); if (damage > 0.0f) { player.TakeDamage(this, damageType, damage, bodyPart, critical); } else { player.Session.Network.EnqueueSend(new GameMessageSystemChat($"You evaded {Name}!", ChatMessageType.CombatEnemy)); } }); actionChain.EnqueueChain(); }
// FIXME(ddevec): I broke vendors -- I need to think about how to reimplement this cleanly public override void OnUse(ObjectGuid playerId) { ActionChain chain = new ActionChain(); CurrentLandblock.ChainOnObject(chain, playerId, (WorldObject wo) => { Player player = wo as Player; if (player == null) { return; } string serverMessage = null; // validate within use range, taking into account the radius of the model itself, as well SetupModel csetup = SetupModel.ReadFromDat(PhysicsData.CSetup); float radiusSquared = (GameData.UseRadius + csetup.Radius) * (GameData.UseRadius + csetup.Radius); // We're static, so this is safe -- our Location is never written if (player.Location.SquaredDistanceTo(Location) >= radiusSquared) { serverMessage = "Your way to far away to trust, come closer and buy something or leave me alone!"; } else { // create the outbound server message serverMessage = "You Break it, you bought it!"; } // give player starting money var money = new GameMessagePrivateUpdatePropertyInt(player.Session, PropertyInt.CoinValue, 5000); player.Session.Network.EnqueueSend(money); var welcomemsg = new GameMessageSystemChat(serverMessage, ChatMessageType.Tell); // always send useDone event var sendUseDoneEvent = new GameEventUseDone(player.Session); player.Session.Network.EnqueueSend(welcomemsg, sendUseDoneEvent); player.Session.Network.EnqueueSend(new GameEventApproachVendor(player.Session, Guid)); }); chain.EnqueueChain(); }
public void MoveTo(WorldObject target, float runRate = 1.0f) { if (this is Player) { return; } var motion = new UniversalMotion(CurrentMotionState.Stance, target.Location, target.Guid); motion.MovementTypes = MovementTypes.MoveToObject; motion.Flag |= MovementParams.CanCharge | MovementParams.FailWalk | MovementParams.UseFinalHeading | MovementParams.Sticky | MovementParams.MoveAway; motion.WalkRunThreshold = 1.0f; motion.RunRate = runRate; CurrentMotionState = motion; if (CurrentLandblock != null) { CurrentLandblock.EnqueueBroadcastMotion(this, motion); } }
/// <summary> /// Perform the melee attack swing animation /// </summary> public virtual ActionChain DoSwingMotion(WorldObject target, out float animLength) { var swingAnimation = new MotionItem(GetSwingAnimation(), 1.25f); animLength = MotionTable.GetAnimationLength(MotionTableId, CurrentMotionState.Stance, swingAnimation); var motion = new UniversalMotion(CurrentMotionState.Stance, swingAnimation); motion.MovementData.CurrentStyle = (uint)CurrentMotionState.Stance; motion.MovementData.TurnSpeed = 2.25f; motion.HasTarget = true; motion.TargetGuid = target.Guid; CurrentMotionState = motion; if (CurrentLandblock != null) { CurrentLandblock.EnqueueBroadcastMotion(this, motion); } return(null); }
public void HandleActionTeleToMarketPlace() { var updateCombatMode = new GameMessagePrivateUpdatePropertyInt(this, PropertyInt.CombatMode, (int)CombatMode.NonCombat); CurrentLandblock.EnqueueBroadcastSystemChat(this, $"{Name} is recalling to the marketplace.", ChatMessageType.Recall); Session.Network.EnqueueSend(updateCombatMode); // this should be handled by a different thing, probably a function that forces player into peacemode CurrentLandblock.EnqueueBroadcastMotion(this, motionMarketplaceRecall); // TODO: (OptimShi): Actual animation length is longer than in retail. 18.4s // float mpAnimationLength = MotionTable.GetAnimationLength((uint)MotionTableId, MotionCommand.MarketplaceRecall); // mpChain.AddDelaySeconds(mpAnimationLength); ActionChain mpChain = new ActionChain(); mpChain.AddDelaySeconds(14); // Then do teleport mpChain.AddChain(GetTeleportChain(MarketplaceDrop)); // Set the chain to run mpChain.EnqueueChain(); }
/// <summary> /// This will set the CurrentWieldedLocation property to wieldedLocation and the Wielder property to this guid and will add it to the EquippedObjects dictionary.<para /> /// It will also increase the EncumbranceVal and Value. /// </summary> public bool TryEquipObject(WorldObject worldObject, int wieldedLocation) { if (!WieldedLocationIsAvailable(wieldedLocation)) { return(false); } worldObject.CurrentWieldedLocation = (EquipMask)wieldedLocation; worldObject.WielderId = Biota.Id; EquippedObjects[worldObject.Guid] = worldObject; EncumbranceVal += worldObject.EncumbranceVal; Value += worldObject.Value; if (CurrentLandblock != null) { CurrentLandblock.EnqueueActionBroadcast(Location, Landblock.MaxObjectRange, (Player p) => p.TrackObject(this)); } return(true); }
/// <summary> /// Called when the Player's stamina has recently changed to 0 /// </summary> public void OnExhausted() { // adjust player speed if running if (CurrentMotionCommand == (uint)MotionCommand.RunForward) { var motion = new UniversalMotion(CurrentMotionState.Stance); // this should be autonomous, like retail, but if it's set to autonomous here, the desired effect doesn't happen // motion.IsAutonomous = true; motion.MovementData = new MovementData() { CurrentStyle = (uint)CurrentMotionState.Stance, ForwardCommand = (uint)MotionCommand.RunForward }; CurrentMotionState = motion; if (CurrentLandblock != null) { CurrentLandblock?.EnqueueBroadcastMotion(this, motion); } } Session.Network.EnqueueSend(new GameEventCommunicationTransientString(Session, "You're Exhausted!")); }
/// <summary> /// This is the OnUse method. This is just an initial implemention. I have put in the turn to action at this point. /// If we are out of use radius, move to the object. Once in range, let's turn the creature toward us and get started. /// Note - we may need to make an NPC class vs monster as using a monster does not make them turn towrad you as I recall. Og II /// Also, once we are reading in the emotes table by weenie - this will automatically customize the behavior for creatures. /// </summary> /// <param name="playerId">Identity of the player we are interacting with</param> public override void ActOnUse(ObjectGuid playerId) { Player player = CurrentLandblock.GetObject(playerId) as Player; if (player == null) { return; } if (!player.IsWithinUseRadiusOf(this)) { player.DoMoveTo(this); } else { OnAutonomousMove(player.Location, this.Sequences, MovementTypes.TurnToObject, playerId); GameEventUseDone sendUseDoneEvent = new GameEventUseDone(player.Session); player.Session.Network.EnqueueSend(sendUseDoneEvent); } }