public static void HandleContract(Session session, params string[] parameters) { if (!(parameters?.Length > 0)) { return; } if (!uint.TryParse(parameters[0], out var contractId)) { return; } ContractTracker contractTracker = new ContractTracker(contractId, session.Player.Guid.Full) { Stage = 0, TimeWhenDone = 0, TimeWhenRepeats = 0, DeleteContract = 0, SetAsDisplayContract = 1 }; if (!session.Player.TrackedContracts.ContainsKey(contractId)) { session.Player.TrackedContracts.Add(contractId, contractTracker); } GameEventSendClientContractTracker contractMsg = new GameEventSendClientContractTracker(session, contractTracker); session.Network.EnqueueSend(contractMsg); ChatPacket.SendServerMessage(session, "You just added " + contractTracker.ContractDetails.ContractName, ChatMessageType.Broadcast); }
public override void Unpack(BinaryReader reader) { base.Unpack(reader); ContractTracker.Unpack(reader); DeleteContract = reader.ReadBool32(); SetAsDisplayContract = reader.ReadBool32(); }
/// <summary> /// This method is part of the contract tracking functions. This is used to remove or abandon a contract. /// The method validates the id passed from the client against the portal.dat file, then sends the appropriate /// response to the client to remove the item from the quest panel. Og II /// </summary> /// <param name="contractId">This is the contract id passed to us from the client that we want to remove.</param> public void HandleActionAbandonContract(uint contractId) { ContractTracker contractTracker = new ContractTracker(contractId, Guid.Full) { Stage = 0, TimeWhenDone = 0, TimeWhenRepeats = 0, DeleteContract = 1, SetAsDisplayContract = 0 }; GameEventSendClientContractTracker contractMsg = new GameEventSendClientContractTracker(Session, contractTracker); /* todo fix for new EF model * AceContractTracker contract = new AceContractTracker(); * if (TrackedContracts.ContainsKey(contractId)) * contract = TrackedContracts[contractId].SnapShotOfAceContractTracker(); * * TrackedContracts.Remove(contractId); * LastUseTracker.Remove((int)contractId); * AceObject.TrackedContracts.Remove(contractId); * * DatabaseManager.Shard.DeleteContract(contract, deleteSuccess => * { * if (deleteSuccess) * log.Info($"ContractId {contractId:X} successfully deleted"); * else * log.Error($"Unable to delete contractId {contractId:X} "); * }); * * Session.Network.EnqueueSend(contractMsg);*/ }
public GameEventSendClientContractTracker(Session session, CharacterPropertiesContractRegistry contract) : base(GameEventType.SendClientContractTracker, GameMessageGroup.UIQueue, session) { var contractTracker = new ContractTracker(session.Player, contract); Writer.Write(contractTracker); Writer.Write(Convert.ToUInt32(contractTracker.DeleteContract)); Writer.Write(Convert.ToUInt32(contractTracker.SetAsDisplayContract)); }
/// <summary> /// This message is used to both add and remove quests in your quest panel. The first use case, the add is stright forward /// and is sent in response to an onUse of a contract from your inventory. F7B1 0036 - Inventory_UseEvent /// The second use case is the abandon quest. This sends a F7B1 0316 Social_AbandonContract in this case you send back the contract id /// you got in the message from the client and pass back a 1 in the deleteContract parameter. Og II /// </summary> /// <param name="session">Our player session used for getting message recipient guid and the correct message sequence.</param> /// <param name="contractTracker">This class contains all of the information we need to send the client about the contract. </param> public GameEventSendClientContractTracker(Session session, ContractTracker contractTracker) : base(GameEventType.SendClientContractTracker, GameMessageGroup.Group09, session) { Writer.Write(contractTracker.Version); Writer.Write(contractTracker.ContractId); Writer.Write(contractTracker.Stage); Writer.Write(contractTracker.TimeWhenDone); Writer.Write(contractTracker.TimeWhenRepeats); Writer.Write(contractTracker.DeleteContract); Writer.Write(contractTracker.SetAsDisplayContract); }
/// <summary> /// This is raised by Player.HandleActionUseItem, and is wrapped in ActionChain.<para /> /// The actor of the ActionChain is the player using the item.<para /> /// The item should be in the players possession. /// /// The OnUse method for this class is to use a contract to add a tracked quest to our quest panel. /// This gives the player access to information about the quest such as starting and ending NPC locations, /// and shows our progress for kill tasks as well as any timing information such as when we can repeat the /// quest or how much longer we have to complete it in the case of at timed quest. Og II /// </summary> public override void UseItem(Player player, ActionChain actionChain) { if (UseCreateContractId == null) { var spellTable = DatManager.PortalDat.SpellTable; if (!spellTable.Spells.ContainsKey((uint)SpellDID)) { return; } var spellBase = DatManager.PortalDat.SpellTable.Spells[(uint)SpellDID]; var spell = DatabaseManager.World.GetCachedSpell((uint)SpellDID); string castMessage = "The gem casts " + spell.Name + " on you"; ////These if statements are to catch spells with an apostrophe in the dat file which throws off the client in reading it from the dat. if (spell.MetaSpellId == 3810) { castMessage = "The gem casts Asheron's Benediction on you"; } if (spell.MetaSpellId == 3811) { castMessage = "The gem casts Blackmoor's Favor on you"; } if (spell.MetaSpellId == 3953) { castMessage = "The gem casts Carraida's Benediction on you"; } if (spell.MetaSpellId == 4024) { castMessage = "The gem casts Asheron's Lesser Benediction on you"; } castMessage += "."; // If not refreshing/surpassing/less than active spell, which I will check for in the very near future when I get the active enchantment list implemented. player.Session.Network.EnqueueSend(new GameMessageSystemChat(castMessage, ChatMessageType.Magic)); player.PlayParticleEffect((PlayScript)spellBase.TargetEffect, player.Guid); const ushort layer = 1; // FIXME: This will be tracked soon, once a list is made to track active enchantments var gem = new Enchantment(player, SpellDID.Value, (double)spell.Duration, layer, spell.Category); player.Session.Network.EnqueueSend(new GameEventMagicUpdateEnchantment(player.Session, gem)); // add to enchantment registry player.EnchantmentManager.Add(gem, false); ////session.Player.HandleActionRemoveItemFromInventory(Guid.Full, (uint)ContainerId, 1); This is commented out to aid in testing. Will be uncommented later. player.SendUseDoneEvent(); return; } ContractTracker contractTracker = new ContractTracker((uint)UseCreateContractId, player.Guid.Full) { Stage = 0, TimeWhenDone = 0, TimeWhenRepeats = 0, DeleteContract = 0, SetAsDisplayContract = 1 }; if (CooldownId != null && player.LastUseTracker.TryGetValue(CooldownId.Value, out var lastUse)) { var timeRemaining = lastUse.AddSeconds(CooldownDuration ?? 0.00).Subtract(DateTime.Now); if (timeRemaining.Seconds > 0) { ChatPacket.SendServerMessage(player.Session, "You cannot use another contract for " + timeRemaining.Seconds + " seconds", ChatMessageType.Broadcast); player.SendUseDoneEvent(); return; } } // We need to see if we are tracking this quest already. Also, I cannot be used on world, so I must have a container id if (!player.TrackedContracts.ContainsKey((uint)UseCreateContractId) && ContainerId != null) { player.TrackedContracts.Add((uint)UseCreateContractId, contractTracker); // This will track our use for each contract using the shared cooldown server side. if (CooldownId != null) { // add or update. if (!player.LastUseTracker.ContainsKey(CooldownId.Value)) { player.LastUseTracker.Add(CooldownId.Value, DateTime.Now); } else { player.LastUseTracker[CooldownId.Value] = DateTime.Now; } } GameEventSendClientContractTracker contractMsg = new GameEventSendClientContractTracker(player.Session, contractTracker); player.Session.Network.EnqueueSend(contractMsg); ChatPacket.SendServerMessage(player.Session, "You just added " + contractTracker.ContractDetails.ContractName, ChatMessageType.Broadcast); // TODO: Add sending the 02C2 message UpdateEnchantment. They added a second use to this existing system // so they could show the delay on the client side - it is not really an enchantment but the they overloaded the use. Og II // Thanks Slushnas for letting me know about this as well as an awesome pcap that shows it all in action. // TODO: there is a lot of work to do here. I am stubbing this in for now to send the right message. Lots of magic numbers at the moment. Debug.Assert(CooldownId != null, "CooldownId != null"); Debug.Assert(CooldownDuration != null, "CooldownDuration != null"); //const ushort layer = 0x10000; // FIXME: we need to track how many layers of the exact same spell we have in effect. const ushort layer = 1; //const uint spellCategory = 0x8000; // FIXME: Not sure where we get this from var spellBase = new SpellBase(0, CooldownDuration.Value, 0, -666); // cooldown not being used in network packet? var gem = new Enchantment(player, spellBase, spellBase.Duration, layer, /*CooldownId.Value,*/ (uint)EnchantmentTypeFlags.Cooldown); player.Session.Network.EnqueueSend(new GameEventMagicUpdateEnchantment(player.Session, gem)); // Ok this was not known to us, so we used the contract - now remove it from inventory. // HandleActionRemoveItemFromInventory is has it's own action chain. player.TryRemoveItemFromInventoryWithNetworking(this, 1); } else { ChatPacket.SendServerMessage(player.Session, "You already have this quest tracked: " + contractTracker.ContractDetails.ContractName, ChatMessageType.Broadcast); } // No mater any condition we need to send the use done event to clear the hour glass from the client. player.SendUseDoneEvent(); }
public void ActOnUseContract(Player player) { ContractTracker contractTracker = new ContractTracker((uint)UseCreateContractId, player.Guid.Full) { Stage = 0, TimeWhenDone = 0, TimeWhenRepeats = 0, DeleteContract = 0, SetAsDisplayContract = 1 }; if (CooldownId != null && player.LastUseTracker.TryGetValue(CooldownId.Value, out var lastUse)) { var timeRemaining = lastUse.AddSeconds(CooldownDuration ?? 0.00).Subtract(DateTime.Now); if (timeRemaining.Seconds > 0) { ChatPacket.SendServerMessage(player.Session, "You cannot use another contract for " + timeRemaining.Seconds + " seconds", ChatMessageType.Broadcast); return; } } // We need to see if we are tracking this quest already. Also, I cannot be used on world, so I must have a container id if (!player.TrackedContracts.ContainsKey((uint)UseCreateContractId) && ContainerId != null) { player.TrackedContracts.Add((uint)UseCreateContractId, contractTracker); // This will track our use for each contract using the shared cooldown server side. if (CooldownId != null) { // add or update. if (!player.LastUseTracker.ContainsKey(CooldownId.Value)) { player.LastUseTracker.Add(CooldownId.Value, DateTime.Now); } else { player.LastUseTracker[CooldownId.Value] = DateTime.Now; } } player.Session.Network.EnqueueSend(new GameEventSendClientContractTracker(player.Session, contractTracker)); ChatPacket.SendServerMessage(player.Session, "You just added " + contractTracker.ContractDetails.ContractName, ChatMessageType.Broadcast); // TODO: Add sending the 02C2 message UpdateEnchantment. They added a second use to this existing system // so they could show the delay on the client side - it is not really an enchantment but the they overloaded the use. Og II // Thanks Slushnas for letting me know about this as well as an awesome pcap that shows it all in action. // TODO: there is a lot of work to do here. I am stubbing this in for now to send the right message. Lots of magic numbers at the moment. Debug.Assert(CooldownId != null, "CooldownId != null"); Debug.Assert(CooldownDuration != null, "CooldownDuration != null"); //const ushort layer = 0x10000; // FIXME: we need to track how many layers of the exact same spell we have in effect. const ushort layer = 1; //const uint spellCategory = 0x8000; // FIXME: Not sure where we get this from var spellBase = new SpellBase(0, CooldownDuration.Value, 0, -666); // cooldown not being used in network packet? var gem = new Enchantment(player, spellBase, layer, /*CooldownId.Value,*/ EnchantmentMask.Cooldown); player.Session.Network.EnqueueSend(new GameEventMagicUpdateEnchantment(player.Session, gem)); // Ok this was not known to us, so we used the contract - now remove it from inventory. // HandleActionRemoveItemFromInventory is has it's own action chain. player.TryConsumeFromInventoryWithNetworking(this, 1); } else { ChatPacket.SendServerMessage(player.Session, "You already have this quest tracked: " + contractTracker.ContractDetails.ContractName, ChatMessageType.Broadcast); } }
/// <summary> /// This is raised by Player.HandleActionUseItem.<para /> /// The item should be in the players possession. /// /// The OnUse method for this class is to use a contract to add a tracked quest to our quest panel. /// This gives the player access to information about the quest such as starting and ending NPC locations, /// and shows our progress for kill tasks as well as any timing information such as when we can repeat the /// quest or how much longer we have to complete it in the case of at timed quest. Og II /// </summary> public override void UseItem(Player player) { // TODO: verify use requirements if (UseCreateContractId == null) { //var spell = new Spell((uint)SpellDID); /* * //These if statements are to catch spells with an apostrophe in the dat file which throws off the client in reading it from the dat. * if (spell.MetaSpellId == 3810) * castMessage = "The gem casts Asheron's Benediction on you"; * if (spell.MetaSpellId == 3811) * castMessage = "The gem casts Blackmoor's Favor on you"; * if (spell.MetaSpellId == 3953) * castMessage = "The gem casts Carraida's Benediction on you"; * if (spell.MetaSpellId == 4024) * castMessage = "The gem casts Asheron's Lesser Benediction on you"; */ player.CreateItemSpell(this, (uint)SpellDID); if ((GetProperty(PropertyBool.UnlimitedUse) ?? false) == false) { player.TryConsumeFromInventoryWithNetworking(this); } player.SendUseDoneEvent(); return; } ContractTracker contractTracker = new ContractTracker((uint)UseCreateContractId, player.Guid.Full) { Stage = 0, TimeWhenDone = 0, TimeWhenRepeats = 0, DeleteContract = 0, SetAsDisplayContract = 1 }; if (CooldownId != null && player.LastUseTracker.TryGetValue(CooldownId.Value, out var lastUse)) { var timeRemaining = lastUse.AddSeconds(CooldownDuration ?? 0.00).Subtract(DateTime.Now); if (timeRemaining.Seconds > 0) { ChatPacket.SendServerMessage(player.Session, "You cannot use another contract for " + timeRemaining.Seconds + " seconds", ChatMessageType.Broadcast); player.SendUseDoneEvent(); return; } } // We need to see if we are tracking this quest already. Also, I cannot be used on world, so I must have a container id if (!player.TrackedContracts.ContainsKey((uint)UseCreateContractId) && ContainerId != null) { player.TrackedContracts.Add((uint)UseCreateContractId, contractTracker); // This will track our use for each contract using the shared cooldown server side. if (CooldownId != null) { // add or update. if (!player.LastUseTracker.ContainsKey(CooldownId.Value)) { player.LastUseTracker.Add(CooldownId.Value, DateTime.Now); } else { player.LastUseTracker[CooldownId.Value] = DateTime.Now; } } GameEventSendClientContractTracker contractMsg = new GameEventSendClientContractTracker(player.Session, contractTracker); player.Session.Network.EnqueueSend(contractMsg); ChatPacket.SendServerMessage(player.Session, "You just added " + contractTracker.ContractDetails.ContractName, ChatMessageType.Broadcast); // TODO: Add sending the 02C2 message UpdateEnchantment. They added a second use to this existing system // so they could show the delay on the client side - it is not really an enchantment but the they overloaded the use. Og II // Thanks Slushnas for letting me know about this as well as an awesome pcap that shows it all in action. // TODO: there is a lot of work to do here. I am stubbing this in for now to send the right message. Lots of magic numbers at the moment. Debug.Assert(CooldownId != null, "CooldownId != null"); Debug.Assert(CooldownDuration != null, "CooldownDuration != null"); //const ushort layer = 0x10000; // FIXME: we need to track how many layers of the exact same spell we have in effect. const ushort layer = 1; //const uint spellCategory = 0x8000; // FIXME: Not sure where we get this from var spellBase = new SpellBase(0, CooldownDuration.Value, 0, -666); // cooldown not being used in network packet? var gem = new Enchantment(player, player.Guid.Full, spellBase, spellBase.Duration, layer, /*CooldownId.Value,*/ EnchantmentMask.Cooldown); player.Session.Network.EnqueueSend(new GameEventMagicUpdateEnchantment(player.Session, gem)); // Ok this was not known to us, so we used the contract - now remove it from inventory. // HandleActionRemoveItemFromInventory is has it's own action chain. player.TryConsumeFromInventoryWithNetworking(this, 1); } else { ChatPacket.SendServerMessage(player.Session, "You already have this quest tracked: " + contractTracker.ContractDetails.ContractName, ChatMessageType.Broadcast); } // No mater any condition we need to send the use done event to clear the hour glass from the client. player.SendUseDoneEvent(); }
public Contract() { _signees = new List<Signee>(); _tracker = new ContractTracker(); }
public override void Pack(BinaryWriter writer) { ContractTracker.Pack(writer); writer.WriteBool32(DeleteContract); writer.WriteBool32(SetAsDisplayContract); }