/// <summary> /// </summary> /// <param name="client"> /// </param> public static void Read(ZoneClient client) { // client got all the needed data and // wants to enter the world. After we // reply to this, the character will really be in game var announce = new CharInPlayMessage { Identity = client.Character.Identity, Unknown = 0x00 }; client.Playfield.Announce(announce); // Player is in game now, starting is over, set stats normally now client.Character.Starting = false; // Needed fix, so gmlevel will be loaded client.Character.Stats[StatIds.gmlevel].Value = client.Character.Stats[StatIds.gmlevel].Value; // Mobs get sent whenever player enters playfield, BUT (!) they are NOT synchronized, because the mobs don't save stuff yet. // for instance: the waypoints the mob went through will NOT be saved and therefore when you re-enter the PF, it will AGAIN // walk the same waypoints. // TODO: Fix it /*foreach (MobType mob in NPCPool.Mobs) { // TODO: Make cache - use pf indexing somehow. if (mob.pf == client.Character.pf) { mob.SendToClient(client); } }*/ }
/// <summary> /// </summary> /// <param name="client"> /// </param> /// <param name="quality"> /// </param> public static void TradeSkillBuildPressed(ZoneClient client, int quality) { TradeSkillInfo source = client.Character.TradeSkillSource; TradeSkillInfo target = client.Character.TradeSkillTarget; Item sourceItem = client.Character.BaseInventory.GetItemInContainer(source.Container, source.Placement); Item targetItem = client.Character.BaseInventory.GetItemInContainer(target.Container, target.Placement); TradeSkillEntry ts = TradeSkill.Instance.GetTradeSkillEntry(sourceItem.HighID, targetItem.HighID); quality = Math.Min(quality, ItemLoader.ItemList[ts.ResultHighId].Quality); if (ts != null) { if (WindowBuild(client, quality, ts, sourceItem, targetItem)) { Item newItem = new Item(quality, ts.ResultLowId, ts.ResultHighId); InventoryError inventoryError = client.Character.BaseInventory.TryAdd(newItem); if (inventoryError == InventoryError.OK) { AddTemplate.Send(client, newItem); // Delete source? if ((ts.DeleteFlag & 1) == 1) { client.Character.BaseInventory.RemoveItem(source.Container, source.Placement); DeleteItem.Send(client, source.Container, source.Placement); } // Delete target? if ((ts.DeleteFlag & 2) == 2) { client.Character.BaseInventory.RemoveItem(target.Container, target.Placement); DeleteItem.Send(client, target.Container, target.Placement); } client.Character.Playfield.Publish( ChatText.CreateIM( client.Character, SuccessMessage( sourceItem, targetItem, new Item(quality, ts.ResultLowId, ts.ResultHighId)))); client.Character.Stats[StatIds.xp].Value += CalculateXP(quality, ts); } } } else { client.Character.Playfield.Publish( ChatText.CreateIM( client.Character, "It is not possible to assemble those two items. Maybe the order was wrong?")); client.Character.Playfield.Publish(ChatText.CreateIM(client.Character, "No combination found!")); } }
/// <summary> /// </summary> /// <param name="fullArgs"> /// </param> /// <param name="client"> /// </param> public static void Read(string fullArgs, ZoneClient client) { string temp = string.Empty; do { temp = fullArgs; fullArgs = fullArgs.Replace(" ", " "); } while (temp != fullArgs); string[] cmdArgs = fullArgs.Trim().Split(' '); Program.csc.CallChatCommand(cmdArgs[0].ToLower(), client, client.Character.Identity, cmdArgs); }
public static void UseSkillWithPositionHandler(ZoneClient client, Packet packet) { ushort skillid; uint x, y; if (!packet.TryReadUShort(out skillid) || !packet.TryReadUInt(out x) || !packet.TryReadUInt(out y)) { Log.WriteLine(LogLevel.Warn, "Couldn't read UseSkillWithPosition packet. {0} ", client); return; } Skill skill; if (!client.Character.SkillsActive.TryGetValue(skillid, out skill)) { Log.WriteLine(LogLevel.Warn, "User tried to use a wrong skill. {0} {1} ", skillid, client); return; } var self = client.Character; var block = self.Map.Block; if (x == 0 || y == 0 || x > block.Width || y > block.Height) { Log.WriteLine(LogLevel.Warn, "User tried to use skill out of map boundaries. {0} {1} {2} {3}", x, y, skillid, client); return; } if (skill.Info.MaxTargets <= 1) { // No AoE skill :s Log.WriteLine(LogLevel.Warn, "User tried to use skill with no MaxTargets or less than 1. {0} {1}", skillid, client); return; } self.AttackSkillAoE(skillid, x, y); }
public static void GiveGuildMoney(ZoneClient client, Packet packet) { long GiveMoney; if (!packet.TryReadLong(out GiveMoney)) { return; } if (client.Character.Guild == null) { return; } if (client.Character.Character.Money < GiveMoney) { //todo response you have money to low return; } client.Character.Character.Money -= GiveMoney; client.Character.ChangeMoney(client.Character.Character.Money); client.Character.Guild.GuildMoney += GiveMoney; client.Character.Guild.GuildMoneySave(); client.Character.Guild.GuildStore.SendAddGuildStore(Data.GuildStoreAddFlags.Gold, client.Character.Character.Name, GiveMoney, client.Character.Guild.GuildMoney); }
public void RemoveClient(ZoneClient client) { ClientManagerMutex.WaitOne(); try { if (client.Character == null) { return; } ZoneClient deleted; clientsByName.TryRemove(client.Character.Character.Name, out deleted); clientsByID.TryRemove(client.Character.ID, out deleted); GroupManager.Instance.OnCharacterRemove(client.Character); if (deleted != client) { Log.WriteLine(LogLevel.Warn, "There was a duplicate client object registered for {0}.", client.Character.Name); } } finally { ClientManagerMutex.ReleaseMutex(); } }
public static void QuestionHandler(ZoneClient client, Packet packet) { byte answer; if (!packet.TryReadByte(out answer)) { Log.WriteLine(LogLevel.Warn, "Received invalid question response."); return; } var character = client.Character; if (character.Question == null) { return; } if (character.Question.Answers.Count <= answer) { return; } character.Question.Function(character, answer); character.Question = null; }
/// <summary> /// </summary> /// <param name="message"> /// </param> /// <param name="cli"> /// </param> /// <exception cref="ArgumentOutOfRangeException"> /// </exception> /// <exception cref="NotImplementedException"> /// </exception> public static void AddItemToContainer(ContainerAddItemMessage message, ZoneClient cli) { bool noAppearanceUpdate = false; /* Container ID's: * 0065 Weaponpage * 0066 Armorpage * 0067 Implantpage * 0068 Inventory (places 64-93) * 0069 Bank * 006B Backpack * 006C KnuBot Trade Window * 006E Overflow window * 006F Trade Window * 0073 Socialpage * 0767 Shop Inventory * 0790 Playershop Inventory * DEAD Trade Window (incoming) It's bank now (when you put something into the bank) */ var fromContainerID = (int)message.SourceContainer.Type; int fromPlacement = message.SourceContainer.Instance; Identity toIdentity = message.Target; int toPlacement = message.TargetPlacement; // Where and what does need to be moved/added? IInventoryPage sendingPage = cli.Character.BaseInventory.Pages[fromContainerID]; IItem itemFrom = sendingPage[fromPlacement]; // Receiver of the item (IInstancedEntity, can be mostly all from NPC, Character or Bag, later even playfields) // Turn 0xDEAD into C350 if instance is the same if (toIdentity.Type == IdentityType.IncomingTradeWindow) { toIdentity.Type = IdentityType.CanbeAffected; } IItemContainer itemReceiver = cli.Playfield.FindByIdentity(toIdentity) as IItemContainer; if (itemReceiver == null) { throw new ArgumentOutOfRangeException( "No Entity found: " + message.Target.Type.ToString() + ":" + message.Target.Instance); } // On which inventorypage should the item be added? IInventoryPage receivingPage; if ((toPlacement == 0x6f) && (message.Target.Type == IdentityType.IncomingTradeWindow)) { receivingPage = itemReceiver.BaseInventory.Pages[(int)IdentityType.Bank]; } else { receivingPage = itemReceiver.BaseInventory.PageFromSlot(toPlacement); } // Get standard page if toplacement cant be found (0x6F for next free slot) // TODO: If Entities are not the same (other player, bag etc) then always add to the standard page if ((receivingPage == null) || (itemReceiver.GetType() != cli.Character.GetType())) { receivingPage = itemReceiver.BaseInventory.Pages[itemReceiver.BaseInventory.StandardPage]; } if (receivingPage == null) { throw new ArgumentOutOfRangeException("No inventorypage found."); } if (toPlacement == 0x6f) { toPlacement = receivingPage.FindFreeSlot(); } // Is there already a item? IItem itemTo; try { itemTo = receivingPage[toPlacement]; } catch (Exception) { itemTo = null; } // Calculating delay for equip/unequip/switch gear int delay = 20; cli.Character.DoNotDoTimers = true; IItemSlotHandler equipTo = receivingPage as IItemSlotHandler; IItemSlotHandler unequipFrom = sendingPage as IItemSlotHandler; noAppearanceUpdate = !((equipTo is WeaponInventoryPage) || (equipTo is ArmorInventoryPage) || (equipTo is SocialArmorInventoryPage)); noAppearanceUpdate &= !((unequipFrom is WeaponInventoryPage) || (unequipFrom is ArmorInventoryPage) || (unequipFrom is SocialArmorInventoryPage)); if (equipTo != null) { if (itemTo != null) { if (receivingPage.NeedsItemCheck) { Actions action = GetAction(sendingPage, itemFrom); if (action.CheckRequirements(cli.Character)) { UnEquip.Send(cli, receivingPage, toPlacement); if (!noAppearanceUpdate) { // Equipmentpages need delays // Delay when equipping/unequipping // has to be redone, jumping breaks the equiping/unequiping // and other messages have to be done too // like heartbeat timer, damage from environment and such delay = (itemFrom.GetAttribute(211) == 1234567890 ? 20 : itemFrom.GetAttribute(211)) + (itemTo.GetAttribute(211) == 1234567890 ? 20 : itemTo.GetAttribute(211)); } Thread.Sleep(delay * 10); // social has to wait for 0.2 secs too (for helmet update) cli.Character.Send(message); equipTo.HotSwap(sendingPage, fromPlacement, toPlacement); Equip.Send(cli, receivingPage, toPlacement); } } } else { if (receivingPage.NeedsItemCheck) { if (itemFrom == null) { throw new NullReferenceException("itemFrom can not be null, possible inventory error"); } Actions action = GetAction(receivingPage, itemFrom); if (action.CheckRequirements(cli.Character)) { if (!noAppearanceUpdate) { // Equipmentpages need delays // Delay when equipping/unequipping // has to be redone, jumping breaks the equiping/unequiping // and other messages have to be done too // like heartbeat timer, damage from environment and such delay = itemFrom.GetAttribute(211); if ((equipTo is SocialArmorInventoryPage) || (delay == 1234567890)) { delay = 20; } Thread.Sleep(delay * 10); } if (sendingPage == receivingPage) { // Switch rings for example UnEquip.Send(cli, sendingPage, fromPlacement); } cli.Character.Send(message); equipTo.Equip(sendingPage, fromPlacement, toPlacement); Equip.Send(cli, receivingPage, toPlacement); } } } } else { if (unequipFrom != null) { // Send to client first if (!noAppearanceUpdate) { // Equipmentpages need delays // Delay when equipping/unequipping // has to be redone, jumping breaks the equiping/unequiping // and other messages have to be done too // like heartbeat timer, damage from environment and such delay = itemFrom.GetAttribute(211); if ((unequipFrom is SocialArmorInventoryPage) || (delay == 1234567890)) { delay = 20; } Thread.Sleep(delay * 10); } UnEquip.Send(cli, sendingPage, fromPlacement); unequipFrom.Unequip(fromPlacement, receivingPage, toPlacement); cli.Character.Send(message); } else { // No equipment page involved, just send ContainerAddItemMessage back message.TargetPlacement = receivingPage.FindFreeSlot(); IItem item = sendingPage.Remove(fromPlacement); receivingPage.Add(message.TargetPlacement, item); cli.Character.Send(message); } } cli.Character.DoNotDoTimers = false; cli.Character.Stats.ClearChangedFlags(); // Apply item functions before sending the appearanceupdate message cli.Character.CalculateSkills(); if (!noAppearanceUpdate) { AppearanceUpdate.AnnounceAppearanceUpdate(cli.Character); } }
/// <summary> /// </summary> /// <param name="message"> /// </param> /// <param name="client"> /// </param> public static void Read(OrgClientMessage message, ZoneClient client) { switch ((byte)message.Command) { case 1: { // org create /* client wants to create organization * name of org is message.CommandArgs */ if (OrganizationDao.CreateOrganization( message.CommandArgs, DateTime.UtcNow, client.Character.Identity.Instance)) { client.Character.Playfield.Publish( ChatText.CreateIM(client.Character, "You have created the guild: " + message.CommandArgs)); int orgID = OrganizationDao.GetOrganizationId(message.CommandArgs); // Make sure the order of these next two lines is not swapped -NV client.Character.Stats[StatIds.clanlevel].Value = 0; client.Character.Stats[StatIds.clan].Value = orgID; break; } else { client.Character.Playfield.Publish( ChatText.CreateIM(client.Character, "This guild already <font color=#DC143C>exists</font>")); break; } } case 2: // org ranks // Displays Org Rank Structure. /* Select governingform from DB, Roll through display from GovForm */ if (client.Character.Stats[StatIds.clan].BaseValue == 0) { client.Character.Playfield.Publish( ChatText.CreateIM(client.Character, "You're not in an organization!")); break; } int governingForm = OrganizationDao.GetGovernmentForm((int)client.Character.Stats[StatIds.clan].BaseValue); client.Character.Playfield.Publish( ChatText.CreateIM(client.Character, "Current Rank Structure: " + GetRankList(governingForm))); break; case 3: // org contract break; case 4: Console.WriteLine("Case 4 Started"); break; case 5: { IInstancedEntity tPlayer = null; if ((tPlayer = client.Playfield.FindByIdentity(message.Target)) != null) { string orgDescription = string.Empty, orgObjective = string.Empty, orgHistory = string.Empty, orgLeaderName = string.Empty; int orgGoverningForm = 0, orgLeaderID = 0; DBOrganization orgData = OrganizationDao.GetOrganizationData((int)tPlayer.Stats[StatIds.clan].BaseValue); if (orgData != null) { orgDescription = orgData.Description; orgObjective = orgData.Objective; orgHistory = orgData.History; orgGoverningForm = orgData.GovernmentForm; orgLeaderID = orgData.LeaderID; } orgLeaderName = CharacterDao.GetCharacterNameById(orgLeaderID); string textGovForm = null; if (orgGoverningForm == 0) { textGovForm = "Department"; } else if (orgGoverningForm == 1) { textGovForm = "Faction"; } else if (orgGoverningForm == 2) { textGovForm = "Republic"; } else if (orgGoverningForm == 3) { textGovForm = "Monarchy"; } else if (orgGoverningForm == 4) { textGovForm = "Anarchism"; } else if (orgGoverningForm == 5) { textGovForm = "Feudalism"; } else { textGovForm = "Department"; } string orgRank = GetRank(orgGoverningForm, tPlayer.Stats[StatIds.clanlevel].BaseValue); var infoMessage = new OrgInfoMessage { Identity = tPlayer.Identity, Unknown = 0x00, Unknown1 = 0x00000000, Unknown2 = 0x00000000, Organization = new Identity { Type = IdentityType.Organization, Instance = (int) tPlayer.Stats[StatIds.clan] .BaseValue }, // TODO: Possible NULL here OrganizationName = (tPlayer as Character).OrganizationName, Description = orgDescription, Objective = orgObjective, GoverningForm = textGovForm, LeaderName = orgLeaderName, Rank = orgRank, Unknown3 = new object[0] }; client.SendCompressed(infoMessage); } } break; case 6: // Add Org Bank to prez DBOrganization orgDisband = OrganizationDao.GetOrganizationData((int)client.Character.Stats[StatIds.clan].BaseValue); client.Character.Stats[StatIds.cash].BaseValue += (uint)orgDisband.Bank; // Clear stat 5 (Clan) from all chars where value=orgId StatDao.DisbandOrganization((int)client.Character.Stats[StatIds.clan].BaseValue); break; case 7: // org startvote <"text"> <duration(minutes)> <entries> // arguments (<text> <duration> and <entries>) are in CmdStr break; case 8: // org vote info break; case 9: // <entry> is CmdStr break; case 10: { // some arg in CmdByte. No idea what it is // create the target namespace t_promote Character toPromote = null; int targetOldRank = -1; int targetNewRank; toPromote = client.Playfield.FindByIdentity<Character>(message.Target); if (toPromote != null) { // First we check if target is in the same org as you if (toPromote.Stats[StatIds.clan].BaseValue != client.Character.Stats[StatIds.clan].BaseValue) { // not in same org client.Character.Playfield.Publish( ChatText.CreateIM(client.Character, "Target is not in your organization!")); break; } // Target is in same org, are you eligible to promote? Promoter Rank has to be TargetRank-2 or == 0 if ((client.Character.Stats[StatIds.clanlevel].Value == (toPromote.Stats[StatIds.clanlevel].Value - 2)) || (client.Character.Stats[StatIds.clanlevel].Value == 0)) { // Promoter is eligible. Start the process // First we get the details about the org itself DBOrganization orgPromote = OrganizationDao.GetOrganizationData((int)client.Character.Stats[StatIds.clan].BaseValue); int promoteGovForm = -1; string promotedToRank = string.Empty; if (orgPromote != null) { // Check if new rank == 0, if so, demote promoter if ((targetOldRank - 1) == 0) { /* This is a bit more complex. Here we need to promote new president first * then we go about demoting old president * finally we set the new leader in Sql * Reset OrgName to set changes */ OrganizationDao.SetNewPrez(orgPromote.ID, toPromote.Identity.Instance); toPromote.Stats[StatIds.clanlevel].Value = 0; client.Character.Stats[StatIds.clanlevel].Value = 1; client.Character.Playfield.Publish( ChatText.CreateIM( client.Character, "You've passed leadership of the organization to: " + (toPromote as Character).Name)); client.Character.Playfield.Publish( ChatText.CreateIM( toPromote, "You've been promoted to the rank of " + promotedToRank + " by " + client.Character.Name)); } else { // Just Promote targetOldRank = toPromote.Stats[StatIds.clanlevel].Value; targetNewRank = targetOldRank - 1; promotedToRank = GetRank(promoteGovForm, (uint)targetNewRank); toPromote.Stats[StatIds.clanlevel].Value = targetNewRank; client.Character.Playfield.Publish( ChatText.CreateIM( client.Character, "You've promoted " + (toPromote as Character).Name + " to " + promotedToRank)); client.Character.Playfield.Publish( ChatText.CreateIM( toPromote, "You've been promoted to the rank of " + promotedToRank + " by " + client.Character.Name)); } } else { client.Character.Playfield.Publish( ChatText.CreateIM(client.Character, "Organization does not exist?")); } } else { // Promoter not eligible to promote client.Character.Playfield.Publish( ChatText.CreateIM( client.Character, "Your Rank is not high enough to promote " + (toPromote as Character).Name)); } } break; } case 11: // demote target player // create the target namespace t_demote Character toDemote = null; int targetCurRank = -1; int targetNewerRank = -1; toDemote = client.Character.Playfield.FindByIdentity<Character>(message.Target); if (toDemote != null) { // First we check if target is in the same org as you if (toDemote.Stats[StatIds.clan].BaseValue != client.Character.Stats[StatIds.clan].BaseValue) { // not in same org client.Character.Playfield.Publish( ChatText.CreateIM(client.Character, "Target is not in your organization!")); break; } // Target is in same org, are you eligible to demote? Promoter Rank has to be TargetRank-2 or == 0 if ((client.Character.Stats[StatIds.clanlevel].Value <= (toDemote.Stats[StatIds.clanlevel].Value - 2)) || (client.Character.Stats[StatIds.clanlevel].Value == 0)) { // Promoter is eligible. Start the process // First we get the details about the org itself DBOrganization orgDemote = OrganizationDao.GetOrganizationData((int)client.Character.Stats[StatIds.clan].BaseValue); int demoteGovForm = -1; string demotedToRank = string.Empty; if (orgDemote == null) { client.Character.Playfield.Publish( ChatText.CreateIM(client.Character, "Organization does not exist?")); break; } // Check whether new rank would be lower than lowest for current govform if ((targetCurRank + 1) > GetLowestRank(orgDemote.GovernmentForm)) { client.Character.Playfield.Publish( ChatText.CreateIM(client.Character, "You can't demote character any lower!")); break; } targetCurRank = toDemote.Stats[StatIds.clanlevel].Value; targetNewerRank = targetCurRank + 1; demotedToRank = GetRank(demoteGovForm, (uint)targetNewerRank); toDemote.Stats[StatIds.clanlevel].Value = targetNewerRank; client.Character.Playfield.Publish( ChatText.CreateIM( client.Character, "You've demoted " + (toDemote as Character).Name + " to " + demotedToRank)); client.Character.Playfield.Publish( ChatText.CreateIM( toDemote, "You've been demoted to the rank of " + demotedToRank + " by " + client.Character.Name)); break; } else { // Promoter not eligible to promote client.Character.Playfield.Publish( ChatText.CreateIM( client.Character, "Your Rank is not high enough to demote " + (toDemote as Character).Name)); break; } } break; case 12: Console.WriteLine("Case 12 Started"); break; case 13: // kick <name> from org // <name> is CmdStr // create the t_player Client namespace, using CmdStr to find character id, in replacement of target.Instance uint kickedFrom = client.Character.Stats[StatIds.clan].BaseValue; DBCharacter kickChar = CharacterDao.GetByCharName(message.CommandArgs); if (kickChar == null) { client.Character.Playfield.Publish( ChatText.CreateIM( client.Character, "No character with name " + message.CommandArgs + " exists.")); break; } int kickeeId = kickChar.Id; Character targetPlayer = client.Playfield.FindByIdentity<Character>( new Identity() { Type = IdentityType.CanbeAffected, Instance = kickeeId }); if (targetPlayer != null) { // Check if CmdStr is actually part of the org uint kickeeOrgId = targetPlayer.Stats[StatIds.clan].BaseValue; if (kickeeOrgId != client.Character.Stats[StatIds.clan].BaseValue) { // Not part of Org. break out. client.Character.Playfield.Publish( ChatText.CreateIM( client.Character, message.CommandArgs + "is not a member of your organization!")); break; } // They are part of the org, so begin the processing... // First we check if the player is online... int onlineStatus = OnlineDao.IsOnline(client.Character.Identity.Instance).Online; if (onlineStatus == 0) { // Player isn't online. Org Kicks are processed in a different method // TODO: Offline Org KICK // StatDao.SetStat(targetPlayer.Identity, ) break; } // Player is online. Start the kick. string kickedFromName = targetPlayer.OrganizationName; targetPlayer[StatIds.clanlevel].Value = 0; targetPlayer[StatIds.clan].Value = 0; client.Character.Playfield.Publish( ChatText.CreateIM( targetPlayer, "You've been kicked from the organization " + kickedFromName)); } // TODO: Offline Org KICK break; case 14: { Character tPlayer = client.Playfield.FindByIdentity<Character>(message.Target); if (tPlayer != null) { var inviteMessage = new OrgInviteMessage { Identity = tPlayer.Identity, Unknown = 0x00, Unknown1 = 0x00000000, Unknown2 = 0x00000000, Organization = new Identity { Type = IdentityType.Organization, Instance = (int) client.Character.Stats[ (int)StatIds.clan].Value }, OrganizationName = client.Character.OrganizationName, Unknown3 = 0x00000000 }; tPlayer.Client.SendCompressed(inviteMessage); } } break; case 15: { // target.Instance holds the OrgID of the Org wishing to be joined. int orgIdtoJoin = message.Target.Instance; int gov_form = OrganizationDao.GetGovernmentForm(orgIdtoJoin); // Make sure the order of these next two lines is not swapped -NV client.Character.Stats[StatIds.clanlevel].Value = GetLowestRank(gov_form); client.Character.Stats[StatIds.clan].Value = orgIdtoJoin; } break; #region /org leave case 16: // org leave // TODO: Disband org if it was leader that left org. -Suiv- // I don't think a Disband happens if leader leaves. I don't think leader -can- leave without passing lead to another // Something worth testing on Testlive perhaps ~Chaz // Just because something happens on TL, doesnt mean its a good idea. Really tbh id prefer it if you had to explicitly type /org disband to disband rather than /org leave doing it... -NV // Agreeing with NV. Org Leader can't leave without passing lead on. org disband requires /org disband to specifically be issued, with a Yes/No box. int govern_form = OrganizationDao.GetGovernmentForm(client.Character.Stats[StatIds.clan].Value); if ((client.Character.Stats[StatIds.clanlevel].Value == 0) && (govern_form != 4)) { client.Character.Playfield.Publish( ChatText.CreateIM( client.Character, "Organization Leader cannot leave organization without Disbanding or Passing Leadership!")); } else { int oldOrgId = client.Character.Stats[StatIds.clan].Value; string orgName = OrganizationDao.GetOrganizationData(oldOrgId).Name; client.Character.Playfield.Publish( ChatText.CreateIM(client.Character, "You left the organization " + orgName + ".")); } break; #endregion #region /org tax | /org tax <tax> case 17: // gets or sets org tax // <tax> is CmdStr // if no <tax>, then just send chat text with current tax info if (message.CommandArgs == null) { client.Character.Playfield.Publish( ChatText.CreateIM(client.Character, "The current organization tax rate is: ")); break; } else { break; } #endregion #region /org bank case 18: { /* // org bank dt = ms.ReadDatatable("SELECT * FROM organizations WHERE ID=" + client.Character.OrgId); if (dt.Rows.Count > 0) { var bank_credits = (UInt64)dt.Rows[0]["Bank"]; client.SendChatText("Your bank has " + bank_credits + " credits in its account"); } */ } break; #endregion #region /org bank add <cash> case 19: { /* if (client.Character.OrgId == 0) { client.SendChatText("You are not in an organisation."); break; } // org bank add <cash> var minuscredits_fromplayer = Convert.ToInt32(message.CommandArgs); var characters_credits = client.Character.Stats.Cash.Value; if (characters_credits < minuscredits_fromplayer) { client.SendChatText("You do not have enough Credits"); } else { var total_Creditsspent = characters_credits - minuscredits_fromplayer; client.Character.Stats.Cash.Set(total_Creditsspent); ms.SqlUpdate( "UPDATE `organizations` SET `Bank` = `Bank` + " + minuscredits_fromplayer + " WHERE `ID` = " + client.Character.OrgId); client.SendChatText("You have donated " + minuscredits_fromplayer + " to the organization"); }*/ } break; #endregion #region /org bank remove <cash> case 20: /* // org bank remove <cash> // <cash> is CmdStr // player wants to take credits from org bank // only leader can do that if ((client.Character.Stats.ClanLevel.Value != 0) || (client.Character.OrgId == 0)) { client.SendChatText("You're not the leader of an Organization"); break; } var removeCredits = Convert.ToInt32(message.CommandArgs); long orgBank = 0; dt = ms.ReadDatatable("SELECT Bank FROM organizations WHERE ID = " + client.Character.OrgId); if (dt.Rows.Count > 0) { orgBank = (Int64)dt.Rows[0][0]; } if (removeCredits > orgBank) { client.SendChatText("Not enough credits in Organization Bank!"); break; } else { var neworgbank = orgBank - removeCredits; var existingcreds = 0; existingcreds = client.Character.Stats.Cash.Value; var newcreds = existingcreds + removeCredits; ms.SqlUpdate( "UPDATE organizations SET Bank = " + neworgbank + " WHERE ID = " + client.Character.OrgId); client.Character.Stats.Cash.Set(newcreds); client.SendChatText("You've removed " + removeCredits + " credits from the organization bank"); } */ break; #endregion #region /org bank paymembers <cash> case 21: // <cash> is CmdStr // give <cash> credits to every org member // credits are taken from org bank // only leader can do it break; #endregion #region /org debt case 22: // send player text about how big is his/her tax debt to org break; #endregion #region /org history <text> case 23: { /* if (client.Character.Stats.ClanLevel.Value == 0) { // org history <history text> ms.SqlUpdate( "UPDATE organizations SET history = '" + message.CommandArgs + "' WHERE ID = '" + client.Character.OrgId + "'"); client.SendChatText("History Updated"); } else { client.SendChatText("You must be the Organization Leader to perform this command!"); }*/ } break; #endregion #region /org objective <text> case 24: { /* if (client.Character.Stats.ClanLevel.Value == 0) { // org objective <objective text> ms.SqlUpdate( "UPDATE organizations SET objective = '" + message.CommandArgs + "' WHERE ID = '" + client.Character.OrgId + "'"); client.SendChatText("Objective Updated"); } else { client.SendChatText("You must be the Organization Leader to perform this command!"); }*/ } break; #endregion #region /org description <text> case 25: { /* if (client.Character.Stats.ClanLevel.Value == 0) { // org description <description text> ms.SqlUpdate( "UPDATE organizations SET description = '" + message.CommandArgs + "' WHERE ID = '" + client.Character.OrgId + "'"); client.SendChatText("Description Updated"); } else { client.SendChatText("You must be the Organization Leader to perform this command!"); }*/ } break; #endregion #region /org name <text> case 26: { // org name <name> /* Renames Organization * Checks for Existing Orgs with similar name to stop crash * Chaz */ /* if (client.Character.Stats.ClanLevel.Value == 0) { var SqlQuery26 = "SELECT * FROM organizations WHERE Name LIKE '" + message.CommandArgs + "' LIMIT 1"; string CurrentOrg = null; dt = ms.ReadDatatable(SqlQuery26); if (dt.Rows.Count > 0) { CurrentOrg = (string)dt.Rows[0]["Name"]; } if (CurrentOrg == null) { var SqlQuery27 = "UPDATE organizations SET Name = '" + message.CommandArgs + "' WHERE ID = '" + client.Character.OrgId + "'"; ms.SqlUpdate(SqlQuery27); client.SendChatText("Organization Name Changed to: " + message.CommandArgs); // Forces reloading of org name and the like // XXXX TODO: Make it reload for all other members in the org client.Character.OrgId = client.Character.OrgId; break; } else { client.SendChatText("An Organization already exists with that name"); break; } } else { client.SendChatText("You must be the organization leader to perform this command!"); }*/ break; } #endregion #region /org governingform <text> case 27: { // org governingform <form> /* Current Governing Forms: * Department, Faction, Republic, Monarchy, Anarchism, Feudalism */ /* // Check on whether your President or not if (client.Character.Stats.ClanLevel.Value == 0) { // first we drop the case on the input, just to be sure. var GovFormNum = -1; if (message.CommandArgs == null) { // list gov forms client.SendChatText( "List of Accepted Governing Forms is: department, faction, republic, monarchy, anarchism, feudalism"); break; } // was correct input passed? switch (message.CommandArgs.ToLower()) { case "department": GovFormNum = 0; break; case "faction": GovFormNum = 1; break; case "republic": GovFormNum = 2; break; case "monarchy": GovFormNum = 3; break; case "anarchism": GovFormNum = 4; break; case "feudalism": GovFormNum = 5; break; default: client.SendChatText(message.CommandArgs + " Is an invalid Governing Form!"); client.SendChatText( "Accepted Governing Forms are: department, faction, republic, monarchy, anarchism, feudalism"); break; } if (GovFormNum != -1) { ms.SqlUpdate( "UPDATE organizations SET GovernmentForm = '" + GovFormNum + "' WHERE ID = '" + client.Character.OrgId + "'"); foreach (var currentCharId in OrgMisc.GetOrgMembers(client.Character.OrgId, true)) { client.Character.Stats.ClanLevel.Set(GetLowestRank(GovFormNum)); } client.SendChatText("Governing Form is now: " + message.CommandArgs); break; } } else { // Haha! You're not the org leader! client.SendChatText("You must be the Org Leader to perform this command"); break; }*/ } break; #endregion #region /org stopvote <text> case 28: // <text> is CmdStr break; #endregion #region unknown command default: break; #endregion } }
public static void GuildExtraRequest(ZoneClient client, Packet packet) { if (client.Character.Guild == null && client.Character.GuildAcademy == null) { return; } byte response; ushort ResponseCode; if (!packet.TryReadByte(out response)) { return; } switch (response) { case 0: if (client.Character.Guild == null) { //todo Response for is not in Guild end academymember return; } ResponseCode = 6104; break; case 1: break; case 2: break; } if (!client.Character.IsInaAcademy) { using (var pack = new Packet(SH38Type.GuildItemList)) { pack.WriteUShort(6104); //Responsecode // pack.WriteLong(client.Character.Guild.GuildMoney); //guildmoney pack.WriteByte((byte)client.Character.Guild.GuildStore.GuildStorageItems.Count); //ItemCount foreach (var pItem in client.Character.Guild.GuildStore.GuildStorageItems.Values) { if (pItem.ItemInfo.Slot == ItemSlot.None) { pItem.WriteInfo(pack); pack.WriteByte((byte)pItem.Ammount);//amount } else { pItem.WriteInfo(pack); } } client.SendPacket(pack); } } else { using (var pack = new Packet(SH38Type.GuildItemList)) { pack.WriteUShort(6104); //Responsecode // pack.WriteLong(client.Character.Guild.GuildMoney); //guildmoney pack.WriteByte((byte)client.Character.GuildAcademy.Guild.GuildStore.GuildStorageItems.Count); //ItemCount foreach (var pItem in client.Character.GuildAcademy.Guild.GuildStore.GuildStorageItems.Values) { if (pItem.ItemInfo.Slot == ItemSlot.None) { pItem.WriteInfo(pack); pack.WriteByte((byte)pItem.Ammount);//amount } else { pItem.WriteInfo(pack); } } client.SendPacket(pack); } } }
/// <summary> /// </summary> /// <param name="client"> /// </param> /// <param name="container"> /// </param> /// <param name="placement"> /// </param> public static void Send(ZoneClient client, int container, int placement) { client.Character.Playfield.Send(client, Create(client.Character, container, placement)); }
public static void WalkHandler(ZoneClient client, Packet packet) { HandleMovement(client.Character, packet, false); }
public static void EndRestHandler(ZoneClient client, Packet packet) { client.Character.Rest(false); }
public static void HandleUnknown(ZoneClient client, Packet packet) { // I have no idea what this does... Maybe some aggro request? }
/// <summary> /// </summary> /// <param name="message"> /// </param> /// <param name="client"> /// </param> public static void Read(ChatCmdMessage message, ZoneClient client) { string fullArgs = message.Command.TrimEnd(char.MinValue); Read(fullArgs, client); }
/// <summary> /// </summary> /// <param name="message"> /// </param> /// <param name="client"> /// </param> public static void Read(CharDCMoveMessage message, ZoneClient client) { byte moveType = message.MoveType; var heading = new Quaternion(message.Heading.X, message.Heading.Y, message.Heading.Z, message.Heading.W); Coordinate coordinates = new Coordinate(message.Coordinates); // TODO: Find out what these (tmpInt) are and name them int tmpInt1 = message.Unknown1; int tmpInt2 = message.Unknown2; int tmpInt3 = message.Unknown3; /* * if (!client.Character.DoNotDoTimers) * { * var teleportPlayfield = WallCollision.WallCollisionCheck( * coordinates.x, coordinates.z, client.Character.PlayField); * if (teleportPlayfield.ZoneToPlayfield >= 1) * { * var coordHeading = WallCollision.GetCoord( * teleportPlayfield, coordinates.x, coordinates.z, coordinates); * if (teleportPlayfield.Flags != 1337 && client.Character.PlayField != 152 || Math.Abs(client.Character.Coordinates.y - teleportPlayfield.Y) <= 2 || teleportPlayfield.Flags == 1337 || && Math.Abs(client.Character.Coordinates.y - teleportPlayfield.Y) <= 6) || { || client.Teleport( || coordHeading.Coordinates, coordHeading.Heading, teleportPlayfield.ZoneToPlayfield); || Program.zoneServer.Clients.Remove(client); || } || || return; || } || || if (client.Character.Stats.LastConcretePlayfieldInstance.Value != 0) || { || var correspondingDoor = DoorHandler.DoorinRange( || client.Character.PlayField, client.Character.Coordinates, 1.0f); || if (correspondingDoor != null) || { || correspondingDoor = DoorHandler.FindCorrespondingDoor(correspondingDoor, client.Character); || client.Character.Stats.LastConcretePlayfieldInstance.Value = 0; || var aoc = correspondingDoor.Coordinates; || aoc.x += correspondingDoor.hX * 3; || aoc.y += correspondingDoor.hY * 3; || aoc.z += correspondingDoor.hZ * 3; || client.Teleport(aoc, client.Character.Heading, correspondingDoor.playfield); || Program.zoneServer.Clients.Remove(client); || return; || } || } ||} */ // Is this correct? Shouldnt the client input be compared to the prediction and then be overridden to prevent teleportation exploits? // - Algorithman client.Character.RawCoordinates = coordinates.coordinate; client.Character.RawHeading = heading; client.Character.UpdateMoveType(moveType); /* Start NV Heading Testing Code * Yaw: 0 to 360 Degrees (North turning clockwise to a complete revolution) * Roll: Not sure, but is always 0 cause we can't roll in AO * Pitch: 90 to -90 Degrees (90 is nose in the air, 0 is level, -90 is nose to the ground) */ /* Comment this line with a '//' to enable heading testing * client.SendChatText("Raw Headings: X: " + client.Character.heading.x + " Y: " + client.Character.heading.y + " Z:" + client.Character.heading.z); * * client.SendChatText("Yaw: " + Math.Round(180 * client.Character.heading.yaw / Math.PI) + " Degrees"); * client.SendChatText("Roll: " + Math.Round(180 * client.Character.heading.roll / Math.PI) + " Degrees"); * client.SendChatText("Pitch: " + Math.Round(180 * client.Character.heading.pitch / Math.PI) + " Degrees"); * /* End NV Heading testing code */ /* start of packet */ var reply = new CharDCMoveMessage { Identity = client.Character.Identity, Unknown = 0x00, MoveType = moveType, Heading = new SmokeLounge.AOtomation.Messaging.GameData.Quaternion { X = heading .xf, Y = heading .yf, Z = heading .zf, W = heading .wf }, Coordinates = new Vector3 { X = coordinates.x, Y = coordinates.y, Z = coordinates.z }, Unknown1 = tmpInt1, Unknown2 = tmpInt2, Unknown3 = tmpInt3 }; client.Playfield.Publish(new IMSendAOtomationMessageToPlayfield { Body = reply }); // TODO: rewrite statelscheck /* * if (Statels.StatelppfonEnter.ContainsKey(client.Character.PlayField)) * { * foreach (var s in Statels.StatelppfonEnter[client.Character.PlayField]) * { * if (s.onEnter(client)) * { * return; * } * * if (s.onTargetinVicinity(client)) * { * return; * } * } * } */ }
/// <summary> /// </summary> /// <param name="message"> /// </param> /// <param name="client"> /// </param> public static void Read(CharDCMoveMessage message, ZoneClient client) { byte moveType = message.MoveType; var heading = new Quaternion(message.Heading.X, message.Heading.Y, message.Heading.Z, message.Heading.W); Coordinate coordinates = new Coordinate(message.Coordinates); // TODO: Find out what these (tmpInt) are and name them int tmpInt1 = message.Unknown1; int tmpInt2 = message.Unknown2; int tmpInt3 = message.Unknown3; /* if (!client.Character.DoNotDoTimers) { var teleportPlayfield = WallCollision.WallCollisionCheck( coordinates.x, coordinates.z, client.Character.PlayField); if (teleportPlayfield.ZoneToPlayfield >= 1) { var coordHeading = WallCollision.GetCoord( teleportPlayfield, coordinates.x, coordinates.z, coordinates); if (teleportPlayfield.Flags != 1337 && client.Character.PlayField != 152 || Math.Abs(client.Character.Coordinates.y - teleportPlayfield.Y) <= 2 || teleportPlayfield.Flags == 1337 && Math.Abs(client.Character.Coordinates.y - teleportPlayfield.Y) <= 6) { client.Teleport( coordHeading.Coordinates, coordHeading.Heading, teleportPlayfield.ZoneToPlayfield); Program.zoneServer.Clients.Remove(client); } return; } if (client.Character.Stats.LastConcretePlayfieldInstance.Value != 0) { var correspondingDoor = DoorHandler.DoorinRange( client.Character.PlayField, client.Character.Coordinates, 1.0f); if (correspondingDoor != null) { correspondingDoor = DoorHandler.FindCorrespondingDoor(correspondingDoor, client.Character); client.Character.Stats.LastConcretePlayfieldInstance.Value = 0; var aoc = correspondingDoor.Coordinates; aoc.x += correspondingDoor.hX * 3; aoc.y += correspondingDoor.hY * 3; aoc.z += correspondingDoor.hZ * 3; client.Teleport(aoc, client.Character.Heading, correspondingDoor.playfield); Program.zoneServer.Clients.Remove(client); return; } } } */ // Is this correct? Shouldnt the client input be compared to the prediction and then be overridden to prevent teleportation exploits? // - Algorithman client.Character.RawCoordinates = coordinates.coordinate; client.Character.RawHeading = heading; client.Character.UpdateMoveType(moveType); /* Start NV Heading Testing Code * Yaw: 0 to 360 Degrees (North turning clockwise to a complete revolution) * Roll: Not sure, but is always 0 cause we can't roll in AO * Pitch: 90 to -90 Degrees (90 is nose in the air, 0 is level, -90 is nose to the ground) */ /* Comment this line with a '//' to enable heading testing client.SendChatText("Raw Headings: X: " + client.Character.heading.x + " Y: " + client.Character.heading.y + " Z:" + client.Character.heading.z); client.SendChatText("Yaw: " + Math.Round(180 * client.Character.heading.yaw / Math.PI) + " Degrees"); client.SendChatText("Roll: " + Math.Round(180 * client.Character.heading.roll / Math.PI) + " Degrees"); client.SendChatText("Pitch: " + Math.Round(180 * client.Character.heading.pitch / Math.PI) + " Degrees"); /* End NV Heading testing code */ /* start of packet */ var reply = new CharDCMoveMessage { Identity = client.Character.Identity, Unknown = 0x00, MoveType = moveType, Heading = new SmokeLounge.AOtomation.Messaging.GameData.Quaternion { X = heading .xf, Y = heading .yf, Z = heading .zf, W = heading .wf }, Coordinates = new Vector3 { X = coordinates.x, Y = coordinates.y, Z = coordinates.z }, Unknown1 = tmpInt1, Unknown2 = tmpInt2, Unknown3 = tmpInt3 }; client.Playfield.Publish(new IMSendAOtomationMessageToPlayfield { Body = reply }); // TODO: rewrite statelscheck /* if (Statels.StatelppfonEnter.ContainsKey(client.Character.PlayField)) { foreach (var s in Statels.StatelppfonEnter[client.Character.PlayField]) { if (s.onEnter(client)) { return; } if (s.onTargetinVicinity(client)) { return; } } } */ }
/// <summary> /// </summary> /// <param name="client"> /// </param> /// <param name="desiredQuality"> /// </param> /// <param name="ts"> /// </param> /// <param name="sourceItem"> /// </param> /// <param name="targetItem"> /// </param> /// <returns> /// </returns> private static bool WindowBuild( ZoneClient client, int desiredQuality, TradeSkillEntry ts, Item sourceItem, Item targetItem) { if (!((ts.MinTargetQL >= targetItem.Quality) || (ts.MinTargetQL == 0))) { return false; } if (!ts.ValidateRange(sourceItem.Quality, targetItem.Quality)) { return false; } foreach (TradeSkillSkill tss in ts.Skills) { if (client.Character.Stats[tss.StatId].Value < Convert.ToInt32(tss.Percent / 100M * targetItem.Quality)) { return false; } } return true; }
/// <summary> /// </summary> /// <param name="client"> /// </param> private static void TradeSkillChanged(ZoneClient client) { TradeSkillInfo source = client.Character.TradeSkillSource; TradeSkillInfo target = client.Character.TradeSkillTarget; if ((source != null) && (target != null)) { Item sourceItem = client.Character.BaseInventory.GetItemInContainer(source.Container, source.Placement); Item targetItem = client.Character.BaseInventory.GetItemInContainer(target.Container, target.Placement); TradeSkillEntry ts = TradeSkill.Instance.GetTradeSkillEntry(sourceItem.HighID, targetItem.HighID); if (ts != null) { if (ts.ValidateRange(sourceItem.Quality, targetItem.Quality)) { foreach (TradeSkillSkill tsi in ts.Skills) { int skillReq = (int)Math.Ceiling(tsi.Percent / 100M * targetItem.Quality); if (skillReq > client.Character.Stats[tsi.StatId].Value) { TradeSkillPacket.SendRequirement(client.Character, tsi.StatId, skillReq); } } int leastbump = 0; int maxbump = 0; if (ts.IsImplant) { if (targetItem.Quality >= 250) { maxbump = 5; } else if (targetItem.Quality >= 201) { maxbump = 4; } else if (targetItem.Quality >= 150) { maxbump = 3; } else if (targetItem.Quality >= 100) { maxbump = 2; } else if (targetItem.Quality >= 50) { maxbump = 1; } } foreach (TradeSkillSkill tsSkill in ts.Skills) { if (tsSkill.SkillPerBump != 0) { leastbump = Math.Min( Convert.ToInt32( (client.Character.Stats[tsSkill.StatId].Value - (tsSkill.Percent / 100M * targetItem.Quality)) / tsSkill.SkillPerBump), maxbump); } } TradeSkillPacket.SendResult( client.Character, targetItem.Quality, Math.Min(targetItem.Quality + leastbump, ItemLoader.ItemList[ts.ResultHighId].Quality), ts.ResultLowId, ts.ResultHighId); } else { TradeSkillPacket.SendOutOfRange( client.Character, Convert.ToInt32( Math.Round((double)targetItem.Quality - ts.QLRangePercent * targetItem.Quality / 100))); } } else { TradeSkillPacket.SendNotTradeskill(client.Character); } } }
/// <summary> /// </summary> /// <param name="client"> /// </param> /// <param name="container"> /// </param> /// <param name="placement"> /// </param> public static void TradeSkillTargetChanged(ZoneClient client, int container, int placement) { if ((container != 0) && (placement != 0)) { client.Character.TradeSkillTarget = new TradeSkillInfo(0, container, placement); Item item = client.Character.BaseInventory.GetItemInContainer(container, placement); TradeSkillPacket.SendTarget(client.Character, TradeSkill.Instance.TargetProcessesCount(item.HighID)); TradeSkillChanged(client); } else { client.Character.TradeSkillTarget = null; } }
public static void AttackMeleeHandler(ZoneClient client, Packet packet) { client.Character.Attack(null); }
public static void UseSkillWithTargetHandler(ZoneClient client, Packet packet) { ushort skillid, victimid; if (!packet.TryReadUShort(out skillid) || !packet.TryReadUShort(out victimid)) { Log.WriteLine(LogLevel.Warn, "Couldn't read useskill packet {0}", client); return; } Skill skill; if (!client.Character.SkillsActive.TryGetValue(skillid, out skill)) { Log.WriteLine(LogLevel.Warn, "User tried to use a wrong skill. {0} {1} ", skillid, client); return; } MapObject victim; if (!client.Character.MapSector.Objects.TryGetValue(victimid, out victim)) { Log.WriteLine(LogLevel.Warn, "User tried to do something with an unknown victim. {0} {1} {2}", skillid, victimid, client); } var self = client.Character; if (skill.Info.DemandType == 6) { if (!(victim is ZoneCharacter)) { return; } var zc = victim as ZoneCharacter; // Only Heal has this // Some heal calculation here uint amount = 12 * (uint)Program.Randomizer.Next(1, 300); //lulz if (amount > victim.MaxHP - victim.HP) { amount = victim.MaxHP - victim.HP; } zc.HP += amount; ushort id = self.UpdateCounter; SendSkillStartSelf(self, skillid, victimid, id); SendSkillStartOthers(self, skillid, victimid, id); SendSkillOK(self); SendSkillAnimationForPlayer(self, skillid, id); // Damage as heal val :D SendSkill(self, id, victimid, amount, zc.HP, zc.UpdateCounter); } else { if (!(victim is Mob)) { return; } uint dmgmin = (uint)self.GetWeaponDamage(true); uint dmgmax = (uint)(self.GetWeaponDamage(true) + (self.GetWeaponDamage(true) % 3)); uint amount = (uint)Program.Randomizer.Next((int)dmgmin, (int)dmgmax); if (amount > victim.HP) { victim.HP = 0; } else { victim.HP -= amount; } ushort id = self.UpdateCounter; SendSkillStartSelf(self, skillid, victimid, id); SendSkillStartOthers(self, skillid, victimid, id); SendSkillOK(self); SendSkillAnimationForPlayer(self, skillid, id); SendSkill(self, id, victimid, amount, victim.HP, victim.UpdateCounter, 0x01, 0x01); if (!victim.IsDead) { victim.Attack(self); } } }
public static void TradeReqestDecline(ZoneClient pClient, Packet pPacket) { TradeManager.Instance.RemoveReqest(pClient); }
/// <summary> /// </summary> /// <param name="packet"> /// </param> /// <param name="client"> /// </param> public static void Read(CharacterActionMessage packet, ZoneClient client) { var actionNum = (int)packet.Action; int unknown1 = packet.Unknown1; int args1 = packet.Parameter1; int args2 = packet.Parameter2; short unknown2 = packet.Unknown2; switch (actionNum) { case 19: { // Cast nano // CastNanoSpell var msg = new CastNanoSpellMessage { Identity = client.Character.Identity, Unknown = 0x00, NanoId = args2, Target = packet.Target, Unknown1 = 0x00000000, Caster = client.Character.Identity }; client.Character.Playfield.Announce(msg); // TODO: This has to be delayed (Casting attack speed) and needs to move to some other part // TODO: Check nanoskill requirements // TODO: Lower current nano points/check if enough nano points // CharacterAction 107 var characterAction107 = new CharacterActionMessage { Identity = client.Character.Identity, Unknown = 0x00, Action = CharacterActionType.FinishNanoCasting, Unknown1 = 0x00000000, Target = Identity.None, Parameter1 = 1, Parameter2 = args2, Unknown2 = 0x0000 }; client.Character.Playfield.Announce(characterAction107); // CharacterAction 98 var characterAction98 = new CharacterActionMessage { Identity = packet.Target, Unknown = 0x00, Action = CharacterActionType.SetNanoDuration, Unknown1 = 0x00000000, Target = new Identity { Type = IdentityType .NanoProgram, Instance = args2 }, Parameter1 = client.Character.Identity.Instance, Parameter2 = 0x249F0, // duration? // Algorithman: Yes, it's duration Unknown2 = 0x0000 }; client.Character.Playfield.Announce(characterAction98); } break; /* this is here to prevent server crash that is caused by * search action if server doesn't reply if something is * found or not */ case 66: { // If action == search /* Msg 110:136744723 = "No hidden objects found." */ // TODO: SEARCH!! SendFeedback.Send(client, 110, 136744723); } break; case 105: { // If action == Info Request IInstancedEntity tPlayer = client.Playfield.FindByIdentity(packet.Target); var tChar = tPlayer as Character; if (tChar != null) { uint LegacyScore = tChar.Stats[StatIds.pvp_rating].BaseValue; string LegacyTitle = null; if (LegacyScore < 1400) { LegacyTitle = string.Empty; } else if (LegacyScore < 1500) { LegacyTitle = "Freshman"; } else if (LegacyScore < 1600) { LegacyTitle = "Rookie"; } else if (LegacyScore < 1700) { LegacyTitle = "Apprentice"; } else if (LegacyScore < 1800) { LegacyTitle = "Novice"; } else if (LegacyScore < 1900) { LegacyTitle = "Neophyte"; } else if (LegacyScore < 2000) { LegacyTitle = "Experienced"; } else if (LegacyScore < 2100) { LegacyTitle = "Expert"; } else if (LegacyScore < 2300) { LegacyTitle = "Master"; } else if (LegacyScore < 2500) { LegacyTitle = "Champion"; } else { LegacyTitle = "Grand Master"; } int orgGoverningForm = 0; try { orgGoverningForm = OrganizationDao.GetGovernmentForm(tChar.Stats[StatIds.clan].Value); } catch (Exception) { } // Uses methods in ZoneEngine\PacketHandlers\OrgClient.cs /* Known packetFlags-- * 0x40 - No org | 0x41 - Org | 0x43 - Org and towers | 0x47 - Org, towers, player has personal towers | 0x50 - No pvp data shown * Bitflags-- * Bit0 = hasOrg, Bit1 = orgTowers, Bit2 = personalTowers, Bit3 = (Int32) time until supression changes (Byte) type of supression level?, Bit4 = noPvpDataShown, Bit5 = hasFaction, Bit6 = ?, Bit 7 = null. */ int? orgId; string orgRank; InfoPacketType type; if (tPlayer.Stats[StatIds.clan].BaseValue == 0) { type = InfoPacketType.Character; orgId = null; orgRank = null; } else { type = InfoPacketType.CharacterOrg; orgId = (int?)tPlayer.Stats[StatIds.clan].BaseValue; if (client.Character.Stats[StatIds.clan].BaseValue == tPlayer.Stats[StatIds.clan].BaseValue) { orgRank = OrgClient.GetRank( orgGoverningForm, tPlayer.Stats[StatIds.clanlevel].BaseValue); } else { orgRank = string.Empty; } } var info = new CharacterInfoPacket { Unknown1 = 0x01, Profession = (Profession)tPlayer.Stats[StatIds.profession].Value, Level = (byte)tPlayer.Stats[StatIds.level].Value, TitleLevel = (byte)tPlayer.Stats[StatIds.titlelevel].Value, VisualProfession = (Profession)tPlayer.Stats[StatIds.visualflags].Value, SideXp = 0, Health = tPlayer.Stats[StatIds.health].Value, MaxHealth = tPlayer.Stats[StatIds.life].Value, BreedHostility = 0x00000000, OrganizationId = orgId, FirstName = tChar.FirstName, LastName = tChar.LastName, LegacyTitle = LegacyTitle, Unknown2 = 0x0000, OrganizationRank = orgRank, TowerFields = null, CityPlayfieldId = 0x00000000, Towers = null, InvadersKilled = tPlayer.Stats[StatIds.invaderskilled].Value, KilledByInvaders = tPlayer.Stats[StatIds.killedbyinvaders].Value, AiLevel = tPlayer.Stats[StatIds.alienlevel].Value, PvpDuelWins = tPlayer.Stats[StatIds.pvpduelkills].Value, PvpDuelLoses = tPlayer.Stats[StatIds.pvpdueldeaths].Value, PvpProfessionDuelLoses = tPlayer.Stats[StatIds.pvpprofessiondueldeaths].Value, PvpSoloKills = tPlayer.Stats[StatIds.pvprankedsolokills].Value, PvpTeamKills = tPlayer.Stats[StatIds.pvprankedteamkills].Value, PvpSoloScore = tPlayer.Stats[StatIds.pvpsoloscore].Value, PvpTeamScore = tPlayer.Stats[StatIds.pvpteamscore].Value, PvpDuelScore = tPlayer.Stats[StatIds.pvpduelscore].Value }; var infoPacketMessage = new InfoPacketMessage { Identity = tPlayer.Identity, Unknown = 0x00, Type = type, Info = info }; client.SendCompressed(infoPacketMessage); } else { // TODO: NPC's /* var npc = (NonPlayerCharacterClass) FindDynel.FindDynelById(packet.Target); if (npc != null) { var infoPacket = new PacketWriter(); // Start packet header infoPacket.PushByte(0xDF); infoPacket.PushByte(0xDF); infoPacket.PushShort(10); infoPacket.PushShort(1); infoPacket.PushShort(0); infoPacket.PushInt(3086); // sender (server ID) infoPacket.PushInt(client.Character.Id.Instance); // receiver infoPacket.PushInt(0x4D38242E); // packet ID infoPacket.PushIdentity(npc.Id); // affected identity infoPacket.PushByte(0); // ? // End packet header infoPacket.PushByte(0x50); // npc's just have 0x50 infoPacket.PushByte(1); // esi_001? infoPacket.PushByte((byte)npc.Stats.Profession.Value); // Profession infoPacket.PushByte((byte)npc.Stats.Level.Value); // Level infoPacket.PushByte((byte)npc.Stats.TitleLevel.Value); // Titlelevel infoPacket.PushByte((byte)npc.Stats.VisualProfession.Value); // Visual Profession infoPacket.PushShort(0); // no idea for npc's infoPacket.PushUInt(npc.Stats.Health.Value); // Current Health (Health) infoPacket.PushUInt(npc.Stats.Life.Value); // Max Health (Life) infoPacket.PushInt(0); // BreedHostility? infoPacket.PushUInt(0); // org ID infoPacket.PushShort(0); infoPacket.PushShort(0); infoPacket.PushShort(0); infoPacket.PushShort(0); infoPacket.PushInt(0x499602d2); infoPacket.PushInt(0x499602d2); infoPacket.PushInt(0x499602d2); var infoPacketA = infoPacket.Finish(); client.SendCompressed(infoPacketA); }*/ } } break; case 120: { // If action == Logout // Start 30 second logout timer if client is not a GM (statid 215) if (client.Character.Stats[StatIds.gmlevel].Value == 0) { ((Character)client.Character).StartLogoutTimer(); } else { // If client is a GM, disconnect without timer client.Character.Dispose(); } } break; case 121: { // If action == Stop Logout // Stop current logout timer and send stop logout packet ((Character)client.Character).StopLogoutTimer(); client.Character.UpdateMoveType((byte)client.Character.PreviousMoveMode); client.Playfield.Announce(packet); // client.CancelLogOut(); } break; case 87: { // If action == Stand client.Character.UpdateMoveType(37); client.Playfield.Announce(packet); if (client.Character.InLogoutTimerPeriod()) { client.Playfield.Send( client, new CharacterActionMessage() { Action = CharacterActionType.StopLogout, Identity = client.Character.Identity }); ((Character)client.Character).StopLogoutTimer(); } // Send stand up packet, and cancel timer/send stop logout packet if timer is enabled // client.StandCancelLogout(); } break; case 22: { // Kick Team Member } break; case 24: { // Leave Team /* var team = new TeamClass(); team.LeaveTeam(client); */ } break; case 25: { // Transfer Team Leadership } break; case 26: { // Team Join Request // Send Team Invite Request To Target Player /* var team = new TeamClass(); team.SendTeamRequest(client, packet.Target); */ } break; case 28: { /* // Request Reply // Check if positive or negative response // if positive var team = new TeamClass(); var teamID = TeamClass.GenerateNewTeamId(client, packet.Target); // Destination Client 0 = Sender, 1 = Reciever // Reciever Packets /////////////////// // CharAction 15 team.TeamRequestReply(client, packet.Target); // CharAction 23 team.TeamRequestReplyCharacterAction23(client, packet.Target); // TeamMember Packet team.TeamReplyPacketTeamMember(1, client, packet.Target, "Member1"); // TeamMemberInfo Packet team.TeamReplyPacketTeamMemberInfo(1, client, packet.Target); // TeamMember Packet team.TeamReplyPacketTeamMember(1, client, packet.Target, "Member2"); // Sender Packets ///////////////// // TeamMember Packet team.TeamReplyPacketTeamMember(0, client, packet.Target, "Member1"); // TeamMemberInfo Packet team.TeamReplyPacketTeamMemberInfo(0, client, packet.Target); // TeamMember Packet team.TeamReplyPacketTeamMember(0, client, packet.Target, "Member2"); */ } break; case 0x70: // Remove/Delete item ItemDao.RemoveItem( (int)packet.Target.Type, client.Character.Identity.Instance, packet.Target.Instance); client.Character.BaseInventory.RemoveItem((int)packet.Target.Type, packet.Target.Instance); client.SendCompressed(packet); break; case 0x34: // Split? IItem it = client.Character.BaseInventory.Pages[(int)packet.Target.Type][packet.Target.Instance]; it.MultipleCount -= args2; Item newItem = new Item(it.Quality, it.LowID, it.HighID); newItem.MultipleCount = args2; client.Character.BaseInventory.Pages[(int)packet.Target.Type].Add( client.Character.BaseInventory.Pages[(int)packet.Target.Type].FindFreeSlot(), newItem); client.Character.BaseInventory.Pages[(int)packet.Target.Type].Write(); break; case 0x35: client.Character.BaseInventory.Pages[(int)packet.Target.Type][packet.Target.Instance].MultipleCount += client.Character.BaseInventory.Pages[(int)packet.Target.Type][args2].MultipleCount; client.Character.BaseInventory.Pages[(int)packet.Target.Type].Remove(args2); client.Character.BaseInventory.Pages[(int)packet.Target.Type].Write(); client.SendCompressed(packet); break; // ################################################################################### // Spandexpants: This is all i have done so far as to make sneak turn on and off, // currently i cannot find a missing packet or link which tells the server the player // has stopped sneaking, hidden packet or something, will come back to later. // ################################################################################### // Sneak Packet Received case 163: { // TODO: IF SNEAKING IS ALLOWED RUN THIS CODE. // Send Action 162 : Enable Sneak var sneak = new CharacterActionMessage { Identity = client.Character.Identity, Unknown = 0x00, Action = CharacterActionType.StartedSneaking, Unknown1 = 0x00000000, Target = Identity.None, Parameter1 = 0, Parameter2 = 0, Unknown2 = 0x0000 }; client.SendCompressed(sneak); // End of Enable sneak // TODO: IF SNEAKING IS NOT ALLOWED SEND REJECTION PACKET } break; case 81: { Identity item1 = packet.Target; var item2 = new Identity { Type = (IdentityType)args1, Instance = args2 }; client.Character.TradeSkillSource = new TradeSkillInfo(0, (int)item1.Type, item1.Instance); client.Character.TradeSkillTarget = new TradeSkillInfo(1, (int)item2.Type, item2.Instance); TradeSkillReceiver.TradeSkillBuildPressed(client, 300); break; } case 166: { client.Character.Stats[StatIds.visualflags].Value = args2; // client.SendChatText("Setting Visual Flag to "+unknown3.ToString()); AppearanceUpdate.AnnounceAppearanceUpdate((Character)client.Character); break; } case 0xdc: TradeSkillReceiver.TradeSkillSourceChanged(client, args1, args2); break; case 0xdd: TradeSkillReceiver.TradeSkillTargetChanged(client, args1, args2); break; case 0xde: TradeSkillReceiver.TradeSkillBuildPressed(client, packet.Target.Instance); break; default: { client.Playfield.Announce(packet); } break; } }
public static void TradeAccept(ZoneClient pClient, Packet pPacket) { TradeManager.Instance.AcceptTrade(pClient); }
public static void StopHandler(ZoneClient client, Packet packet) { HandleMovement(client.Character, packet, true, true); }
public static void TradeLock(ZoneClient pClient, Packet pPacket) { pClient.Character.Trade?.TradeLock(pClient.Character); }
public static void TradeAgree(ZoneClient pClient, Packet pPacket) { pClient.Character.Trade?.AcceptTrade(pClient.Character); }
/// <summary> /// </summary> /// <param name="message"> /// </param> /// <param name="client"> /// </param> private static void Reply(GenericCmdMessage message, ZoneClient client) { // Acknowledge action message.Identity = client.Character.Identity; message.Temp1 = 1; message.Unknown = 0; client.SendCompressed(message); }
/// <summary> /// </summary> /// <param name="charID"> /// </param> /// <param name="client"> /// </param> public void Read(int charID, ZoneClient client) { // Don't edit anything in this region // unless you are 300% sure you know what you're doing // Character is created and read when Client connects in Client.cs->CreateCharacter // client.CreateCharacter(charID); client.Server.Info( client, "Client connected. ID: {0} IP: {1} Character name: {2}", client.Character.Identity.Instance, client.ClientAddress, client.Character.Name); // now we have to start sending packets like // character stats, inventory, playfield info // and so on. I will put some packets here just // to get us in game. We have to start moving // these packets somewhere else and make packet // builders instead of sending (half) hardcoded // packets. /* send chat server info to client */ ChatServerInfo.Send(client); /* send playfield info to client */ PlayfieldAnarchyF.Send(client); var sendSCFUs = new IMSendPlayerSCFUs { toClient = client }; ((Playfield)client.Playfield).SendSCFUsToClient(sendSCFUs); /* set SocialStatus to 0 */ client.Character.Stats[521].BaseValue = 0; // Stat.SendDirect(client, 521, 0, false); var identity = new Identity { Type = IdentityType.CanbeAffected, Instance = charID }; /* Action 167 Animation and Stance Data maybe? */ var message = new CharacterActionMessage { Identity = identity, Action = CharacterActionType.ChangeAnimationAndStance, Target = Identity.None, Parameter1 = 0x00000000, Parameter2 = 0x00000001 }; client.SendCompressed(message); var gameTimeMessage = new GameTimeMessage { Identity = identity, Unknown1 = 30024.0f, Unknown3 = 185408, Unknown4 = 80183.3125f }; client.SendCompressed(gameTimeMessage); /* set SocialStatus to 0 */ // Stat.SendDirect(client, 521, 0, false); /* again */ // Stat.SendDirect(client, 521, 0, false); /* visual */ SimpleCharFullUpdate.SendToPlayfield(client); /* inventory, items and all that */ FullCharacter.Send(client); var specials = new[] { new SpecialAttackInfo { Unknown1 = 0x0000AAC0, Unknown2 = 0x00023569, Unknown3 = 0x00000064, Unknown4 = "MAAT" }, new SpecialAttackInfo { Unknown1 = 0x0000A431, Unknown2 = 0x0000A430, Unknown3 = 0x00000090, Unknown4 = "DIIT" }, new SpecialAttackInfo { Unknown1 = 0x00011294, Unknown2 = 0x00011295, Unknown3 = 0x0000008E, Unknown4 = "BRAW" } }; var specialAttackWeaponMessage = new SpecialAttackWeaponMessage { Identity = identity, Specials = specials }; client.SendCompressed(specialAttackWeaponMessage); // done // Timers are allowed to update client stats now. client.Character.DoNotDoTimers = false; // spawn all active monsters to client // TODO: Implement NonPlayerCharacterHandler // NonPlayerCharacterHandler.SpawnMonstersInPlayfieldToClient(client, client.Character.PlayField); // TODO: Implement VendorHandler // if (VendorHandler.GetNumberofVendorsinPlayfield(client.Character.PlayField) > 0) // { // Shops // VendorHandler.GetVendorsInPF(client); // } // WeaponItemFullCharUpdate Maybe the right location , First Check if weapons present usually in equipment // Packets.WeaponItemFullUpdate.Send(client, client.Character); // TODO: create a better alternative to ProcessTimers // client.Character.ProcessTimers(DateTime.Now + TimeSpan.FromMilliseconds(200)); client.Character.CalculateSkills(); AppearanceUpdate.AnnounceAppearanceUpdate((Character)client.Character); // done, so we call a hook. // Call all OnConnect script Methods Program.csc.CallMethod("OnConnect", (Character)client.Character); }
/// <summary> /// </summary> /// <param name="message"> /// </param> /// <param name="client"> /// </param> /// <exception cref="NullReferenceException"> /// </exception> public static void Read(GenericCmdMessage message, ZoneClient client) { switch (message.Action) { case GenericCmdAction.Get: break; case GenericCmdAction.Drop: break; case GenericCmdAction.Use: if (message.Target.Type == IdentityType.Inventory) { Item item = null; try { item = client.Character.BaseInventory.GetItemInContainer( (int)message.Target.Type, message.Target.Instance); } catch (Exception) { } if (item == null) { throw new NullReferenceException( "No item found at " + message.Target.Type + "/" + message.Target.Instance); } TemplateAction.Send(client, item, (int)message.Target.Type, message.Target.Instance); if (ItemLoader.ItemList[item.HighID].IsConsumable()) { item.MultipleCount--; if (item.MultipleCount == 0) { client.Character.BaseInventory.RemoveItem( (int)message.Target.Type, message.Target.Instance); DeleteItem.Send(client, (int)message.Target.Type, message.Target.Instance); } } item.PerformAction(client.Character, EventType.OnUse, message.Target.Instance); Reply(message, client); } else { string s = "Generic Command received:\r\nAction: " + message.Action.ToString() + "(" + ((int)message.Action).ToString() + ")\r\nTarget: " + message.Target.Type + " " + ((int)message.Target.Type).ToString("X8") + ":" + message.Target.Instance.ToString("X8"); if (PlayfieldLoader.PFData.ContainsKey(client.Character.Playfield.Identity.Instance)) { StatelData sd = PlayfieldLoader.PFData[client.Playfield.Identity.Instance].Statels.FirstOrDefault( x => (x.StatelIdentity.Type == message.Target.Type) && (x.StatelIdentity.Instance == message.Target.Instance)); if (sd != null) { s = s + "\r\nFound Statel with " + sd.Events.Count + " events"; Events onUse = sd.Events.FirstOrDefault(x => x.EventType == (int)EventType.OnUse); if (onUse != null) { onUse.Perform(client.Character, client.Character); } } } client.Character.Send(new ChatTextMessage() { Identity = client.Character.Identity, Text = s }); } break; } }
/// <summary> /// </summary> /// <param name="message"> /// </param> /// <param name="client"> /// </param> public static void Read(OrgClientMessage message, ZoneClient client) { switch ((byte)message.Command) { case 1: { // org create /* client wants to create organization * name of org is message.CommandArgs */ if (OrganizationDao.CreateOrganization( message.CommandArgs, DateTime.UtcNow, client.Character.Identity.Instance)) { client.Character.Playfield.Publish( ChatText.CreateIM(client.Character, "You have created the guild: " + message.CommandArgs)); int orgID = OrganizationDao.GetOrganizationId(message.CommandArgs); // Make sure the order of these next two lines is not swapped -NV client.Character.Stats[StatIds.clanlevel].Value = 0; client.Character.Stats[StatIds.clan].Value = orgID; break; } else { client.Character.Playfield.Publish( ChatText.CreateIM(client.Character, "This guild already <font color=#DC143C>exists</font>")); break; } } case 2: // org ranks // Displays Org Rank Structure. /* Select governingform from DB, Roll through display from GovForm */ if (client.Character.Stats[StatIds.clan].BaseValue == 0) { client.Character.Playfield.Publish( ChatText.CreateIM(client.Character, "You're not in an organization!")); break; } int governingForm = OrganizationDao.GetGovernmentForm((int)client.Character.Stats[StatIds.clan].BaseValue); client.Character.Playfield.Publish( ChatText.CreateIM(client.Character, "Current Rank Structure: " + GetRankList(governingForm))); break; case 3: // org contract break; case 4: Console.WriteLine("Case 4 Started"); break; case 5: { IInstancedEntity tPlayer = null; if ((tPlayer = client.Playfield.FindByIdentity(message.Target)) != null) { string orgDescription = string.Empty, orgObjective = string.Empty, orgHistory = string.Empty, orgLeaderName = string.Empty; int orgGoverningForm = 0, orgLeaderID = 0; DBOrganization orgData = OrganizationDao.GetOrganizationData((int)tPlayer.Stats[StatIds.clan].BaseValue); if (orgData != null) { orgDescription = orgData.Description; orgObjective = orgData.Objective; orgHistory = orgData.History; orgGoverningForm = orgData.GovernmentForm; orgLeaderID = orgData.LeaderID; } orgLeaderName = CharacterDao.GetCharacterNameById(orgLeaderID); string textGovForm = null; if (orgGoverningForm == 0) { textGovForm = "Department"; } else if (orgGoverningForm == 1) { textGovForm = "Faction"; } else if (orgGoverningForm == 2) { textGovForm = "Republic"; } else if (orgGoverningForm == 3) { textGovForm = "Monarchy"; } else if (orgGoverningForm == 4) { textGovForm = "Anarchism"; } else if (orgGoverningForm == 5) { textGovForm = "Feudalism"; } else { textGovForm = "Department"; } string orgRank = GetRank(orgGoverningForm, tPlayer.Stats[StatIds.clanlevel].BaseValue); var infoMessage = new OrgInfoMessage { Identity = tPlayer.Identity, Unknown = 0x00, Unknown1 = 0x00000000, Unknown2 = 0x00000000, Organization = new Identity { Type = IdentityType.Organization, Instance = (int) tPlayer.Stats[StatIds.clan] .BaseValue }, // TODO: Possible NULL here OrganizationName = (tPlayer as Character).OrganizationName, Description = orgDescription, Objective = orgObjective, GoverningForm = textGovForm, LeaderName = orgLeaderName, Rank = orgRank, Unknown3 = new object[0] }; client.SendCompressed(infoMessage); } } break; case 6: // Add Org Bank to prez DBOrganization orgDisband = OrganizationDao.GetOrganizationData((int)client.Character.Stats[StatIds.clan].BaseValue); client.Character.Stats[StatIds.cash].BaseValue += (uint)orgDisband.Bank; // Clear stat 5 (Clan) from all chars where value=orgId StatDao.DisbandOrganization((int)client.Character.Stats[StatIds.clan].BaseValue); break; case 7: // org startvote <"text"> <duration(minutes)> <entries> // arguments (<text> <duration> and <entries>) are in CmdStr break; case 8: // org vote info break; case 9: // <entry> is CmdStr break; case 10: { // some arg in CmdByte. No idea what it is // create the target namespace t_promote Character toPromote = null; int targetOldRank = -1; int targetNewRank; toPromote = client.Playfield.FindByIdentity <Character>(message.Target); if (toPromote != null) { // First we check if target is in the same org as you if (toPromote.Stats[StatIds.clan].BaseValue != client.Character.Stats[StatIds.clan].BaseValue) { // not in same org client.Character.Playfield.Publish( ChatText.CreateIM(client.Character, "Target is not in your organization!")); break; } // Target is in same org, are you eligible to promote? Promoter Rank has to be TargetRank-2 or == 0 if ((client.Character.Stats[StatIds.clanlevel].Value == (toPromote.Stats[StatIds.clanlevel].Value - 2)) || (client.Character.Stats[StatIds.clanlevel].Value == 0)) { // Promoter is eligible. Start the process // First we get the details about the org itself DBOrganization orgPromote = OrganizationDao.GetOrganizationData((int)client.Character.Stats[StatIds.clan].BaseValue); int promoteGovForm = -1; string promotedToRank = string.Empty; if (orgPromote != null) { // Check if new rank == 0, if so, demote promoter if ((targetOldRank - 1) == 0) { /* This is a bit more complex. Here we need to promote new president first * then we go about demoting old president * finally we set the new leader in Sql * Reset OrgName to set changes */ OrganizationDao.SetNewPrez(orgPromote.ID, toPromote.Identity.Instance); toPromote.Stats[StatIds.clanlevel].Value = 0; client.Character.Stats[StatIds.clanlevel].Value = 1; client.Character.Playfield.Publish( ChatText.CreateIM( client.Character, "You've passed leadership of the organization to: " + (toPromote as Character).Name)); client.Character.Playfield.Publish( ChatText.CreateIM( toPromote, "You've been promoted to the rank of " + promotedToRank + " by " + client.Character.Name)); } else { // Just Promote targetOldRank = toPromote.Stats[StatIds.clanlevel].Value; targetNewRank = targetOldRank - 1; promotedToRank = GetRank(promoteGovForm, (uint)targetNewRank); toPromote.Stats[StatIds.clanlevel].Value = targetNewRank; client.Character.Playfield.Publish( ChatText.CreateIM( client.Character, "You've promoted " + (toPromote as Character).Name + " to " + promotedToRank)); client.Character.Playfield.Publish( ChatText.CreateIM( toPromote, "You've been promoted to the rank of " + promotedToRank + " by " + client.Character.Name)); } } else { client.Character.Playfield.Publish( ChatText.CreateIM(client.Character, "Organization does not exist?")); } } else { // Promoter not eligible to promote client.Character.Playfield.Publish( ChatText.CreateIM( client.Character, "Your Rank is not high enough to promote " + (toPromote as Character).Name)); } } break; } case 11: // demote target player // create the target namespace t_demote Character toDemote = null; int targetCurRank = -1; int targetNewerRank = -1; toDemote = client.Character.Playfield.FindByIdentity <Character>(message.Target); if (toDemote != null) { // First we check if target is in the same org as you if (toDemote.Stats[StatIds.clan].BaseValue != client.Character.Stats[StatIds.clan].BaseValue) { // not in same org client.Character.Playfield.Publish( ChatText.CreateIM(client.Character, "Target is not in your organization!")); break; } // Target is in same org, are you eligible to demote? Promoter Rank has to be TargetRank-2 or == 0 if ((client.Character.Stats[StatIds.clanlevel].Value <= (toDemote.Stats[StatIds.clanlevel].Value - 2)) || (client.Character.Stats[StatIds.clanlevel].Value == 0)) { // Promoter is eligible. Start the process // First we get the details about the org itself DBOrganization orgDemote = OrganizationDao.GetOrganizationData((int)client.Character.Stats[StatIds.clan].BaseValue); int demoteGovForm = -1; string demotedToRank = string.Empty; if (orgDemote == null) { client.Character.Playfield.Publish( ChatText.CreateIM(client.Character, "Organization does not exist?")); break; } // Check whether new rank would be lower than lowest for current govform if ((targetCurRank + 1) > GetLowestRank(orgDemote.GovernmentForm)) { client.Character.Playfield.Publish( ChatText.CreateIM(client.Character, "You can't demote character any lower!")); break; } targetCurRank = toDemote.Stats[StatIds.clanlevel].Value; targetNewerRank = targetCurRank + 1; demotedToRank = GetRank(demoteGovForm, (uint)targetNewerRank); toDemote.Stats[StatIds.clanlevel].Value = targetNewerRank; client.Character.Playfield.Publish( ChatText.CreateIM( client.Character, "You've demoted " + (toDemote as Character).Name + " to " + demotedToRank)); client.Character.Playfield.Publish( ChatText.CreateIM( toDemote, "You've been demoted to the rank of " + demotedToRank + " by " + client.Character.Name)); break; } else { // Promoter not eligible to promote client.Character.Playfield.Publish( ChatText.CreateIM( client.Character, "Your Rank is not high enough to demote " + (toDemote as Character).Name)); break; } } break; case 12: Console.WriteLine("Case 12 Started"); break; case 13: // kick <name> from org // <name> is CmdStr // create the t_player Client namespace, using CmdStr to find character id, in replacement of target.Instance uint kickedFrom = client.Character.Stats[StatIds.clan].BaseValue; DBCharacter kickChar = CharacterDao.GetByCharName(message.CommandArgs); if (kickChar == null) { client.Character.Playfield.Publish( ChatText.CreateIM( client.Character, "No character with name " + message.CommandArgs + " exists.")); break; } int kickeeId = kickChar.Id; Character targetPlayer = client.Playfield.FindByIdentity <Character>( new Identity() { Type = IdentityType.CanbeAffected, Instance = kickeeId }); if (targetPlayer != null) { // Check if CmdStr is actually part of the org uint kickeeOrgId = targetPlayer.Stats[StatIds.clan].BaseValue; if (kickeeOrgId != client.Character.Stats[StatIds.clan].BaseValue) { // Not part of Org. break out. client.Character.Playfield.Publish( ChatText.CreateIM( client.Character, message.CommandArgs + "is not a member of your organization!")); break; } // They are part of the org, so begin the processing... // First we check if the player is online... int onlineStatus = OnlineDao.IsOnline(client.Character.Identity.Instance).Online; if (onlineStatus == 0) { // Player isn't online. Org Kicks are processed in a different method // TODO: Offline Org KICK // StatDao.SetStat(targetPlayer.Identity, ) break; } // Player is online. Start the kick. string kickedFromName = targetPlayer.OrganizationName; targetPlayer[StatIds.clanlevel].Value = 0; targetPlayer[StatIds.clan].Value = 0; client.Character.Playfield.Publish( ChatText.CreateIM( targetPlayer, "You've been kicked from the organization " + kickedFromName)); } // TODO: Offline Org KICK break; case 14: { Character tPlayer = client.Playfield.FindByIdentity <Character>(message.Target); if (tPlayer != null) { var inviteMessage = new OrgInviteMessage { Identity = tPlayer.Identity, Unknown = 0x00, Unknown1 = 0x00000000, Unknown2 = 0x00000000, Organization = new Identity { Type = IdentityType.Organization, Instance = (int) client.Character.Stats[ (int)StatIds.clan].Value }, OrganizationName = client.Character.OrganizationName, Unknown3 = 0x00000000 }; tPlayer.Client.SendCompressed(inviteMessage); } } break; case 15: { // target.Instance holds the OrgID of the Org wishing to be joined. int orgIdtoJoin = message.Target.Instance; int gov_form = OrganizationDao.GetGovernmentForm(orgIdtoJoin); // Make sure the order of these next two lines is not swapped -NV client.Character.Stats[StatIds.clanlevel].Value = GetLowestRank(gov_form); client.Character.Stats[StatIds.clan].Value = orgIdtoJoin; } break; #region /org leave case 16: // org leave // TODO: Disband org if it was leader that left org. -Suiv- // I don't think a Disband happens if leader leaves. I don't think leader -can- leave without passing lead to another // Something worth testing on Testlive perhaps ~Chaz // Just because something happens on TL, doesnt mean its a good idea. Really tbh id prefer it if you had to explicitly type /org disband to disband rather than /org leave doing it... -NV // Agreeing with NV. Org Leader can't leave without passing lead on. org disband requires /org disband to specifically be issued, with a Yes/No box. int govern_form = OrganizationDao.GetGovernmentForm(client.Character.Stats[StatIds.clan].Value); if ((client.Character.Stats[StatIds.clanlevel].Value == 0) && (govern_form != 4)) { client.Character.Playfield.Publish( ChatText.CreateIM( client.Character, "Organization Leader cannot leave organization without Disbanding or Passing Leadership!")); } else { int oldOrgId = client.Character.Stats[StatIds.clan].Value; string orgName = OrganizationDao.GetOrganizationData(oldOrgId).Name; client.Character.Playfield.Publish( ChatText.CreateIM(client.Character, "You left the organization " + orgName + ".")); } break; #endregion #region /org tax | /org tax <tax> case 17: // gets or sets org tax // <tax> is CmdStr // if no <tax>, then just send chat text with current tax info if (message.CommandArgs == null) { client.Character.Playfield.Publish( ChatText.CreateIM(client.Character, "The current organization tax rate is: ")); break; } else { break; } #endregion #region /org bank case 18: { /* * // org bank * dt = ms.ReadDatatable("SELECT * FROM organizations WHERE ID=" + client.Character.OrgId); * if (dt.Rows.Count > 0) * { * var bank_credits = (UInt64)dt.Rows[0]["Bank"]; * client.SendChatText("Your bank has " + bank_credits + " credits in its account"); * } */ } break; #endregion #region /org bank add <cash> case 19: { /* * if (client.Character.OrgId == 0) * { * client.SendChatText("You are not in an organisation."); * * break; * } * * // org bank add <cash> * var minuscredits_fromplayer = Convert.ToInt32(message.CommandArgs); * var characters_credits = client.Character.Stats.Cash.Value; * * if (characters_credits < minuscredits_fromplayer) * { * client.SendChatText("You do not have enough Credits"); * } * else * { * var total_Creditsspent = characters_credits - minuscredits_fromplayer; * client.Character.Stats.Cash.Set(total_Creditsspent); * * ms.SqlUpdate( * "UPDATE `organizations` SET `Bank` = `Bank` + " + minuscredits_fromplayer + " WHERE `ID` = " + client.Character.OrgId); + client.SendChatText("You have donated " + minuscredits_fromplayer + " to the organization"); + }*/ } break; #endregion #region /org bank remove <cash> case 20: /* * // org bank remove <cash> * // <cash> is CmdStr * // player wants to take credits from org bank * // only leader can do that * if ((client.Character.Stats.ClanLevel.Value != 0) || (client.Character.OrgId == 0)) * { * client.SendChatText("You're not the leader of an Organization"); * break; * } * * var removeCredits = Convert.ToInt32(message.CommandArgs); * long orgBank = 0; * dt = ms.ReadDatatable("SELECT Bank FROM organizations WHERE ID = " + client.Character.OrgId); * if (dt.Rows.Count > 0) * { * orgBank = (Int64)dt.Rows[0][0]; * } * * if (removeCredits > orgBank) * { * client.SendChatText("Not enough credits in Organization Bank!"); * break; * } * else * { * var neworgbank = orgBank - removeCredits; * var existingcreds = 0; * existingcreds = client.Character.Stats.Cash.Value; * var newcreds = existingcreds + removeCredits; * ms.SqlUpdate( * "UPDATE organizations SET Bank = " + neworgbank + " WHERE ID = " + client.Character.OrgId); * client.Character.Stats.Cash.Set(newcreds); * client.SendChatText("You've removed " + removeCredits + " credits from the organization bank"); * } */ break; #endregion #region /org bank paymembers <cash> case 21: // <cash> is CmdStr // give <cash> credits to every org member // credits are taken from org bank // only leader can do it break; #endregion #region /org debt case 22: // send player text about how big is his/her tax debt to org break; #endregion #region /org history <text> case 23: { /* * if (client.Character.Stats.ClanLevel.Value == 0) * { * // org history <history text> * ms.SqlUpdate( * "UPDATE organizations SET history = '" + message.CommandArgs + "' WHERE ID = '" + client.Character.OrgId + "'"); + client.SendChatText("History Updated"); + } + else + { + client.SendChatText("You must be the Organization Leader to perform this command!"); + }*/ } break; #endregion #region /org objective <text> case 24: { /* * if (client.Character.Stats.ClanLevel.Value == 0) * { * // org objective <objective text> * ms.SqlUpdate( * "UPDATE organizations SET objective = '" + message.CommandArgs + "' WHERE ID = '" + client.Character.OrgId + "'"); + client.SendChatText("Objective Updated"); + } + else + { + client.SendChatText("You must be the Organization Leader to perform this command!"); + }*/ } break; #endregion #region /org description <text> case 25: { /* * if (client.Character.Stats.ClanLevel.Value == 0) * { * // org description <description text> * ms.SqlUpdate( * "UPDATE organizations SET description = '" + message.CommandArgs + "' WHERE ID = '" + client.Character.OrgId + "'"); + client.SendChatText("Description Updated"); + } + else + { + client.SendChatText("You must be the Organization Leader to perform this command!"); + }*/ } break; #endregion #region /org name <text> case 26: { // org name <name> /* Renames Organization * Checks for Existing Orgs with similar name to stop crash * Chaz */ /* * if (client.Character.Stats.ClanLevel.Value == 0) * { * var SqlQuery26 = "SELECT * FROM organizations WHERE Name LIKE '" + message.CommandArgs + "' LIMIT 1"; + string CurrentOrg = null; + dt = ms.ReadDatatable(SqlQuery26); + if (dt.Rows.Count > 0) + { + CurrentOrg = (string)dt.Rows[0]["Name"]; + } + + if (CurrentOrg == null) + { + var SqlQuery27 = "UPDATE organizations SET Name = '" + message.CommandArgs + "' WHERE ID = '" + client.Character.OrgId + "'"; + ms.SqlUpdate(SqlQuery27); + client.SendChatText("Organization Name Changed to: " + message.CommandArgs); + + // Forces reloading of org name and the like + // XXXX TODO: Make it reload for all other members in the org + client.Character.OrgId = client.Character.OrgId; + break; + } + else + { + client.SendChatText("An Organization already exists with that name"); + break; + } + } + else + { + client.SendChatText("You must be the organization leader to perform this command!"); + }*/ break; } #endregion #region /org governingform <text> case 27: { // org governingform <form> /* Current Governing Forms: * Department, Faction, Republic, Monarchy, Anarchism, Feudalism */ /* * // Check on whether your President or not * if (client.Character.Stats.ClanLevel.Value == 0) * { * // first we drop the case on the input, just to be sure. * var GovFormNum = -1; * if (message.CommandArgs == null) * { * // list gov forms * client.SendChatText( * "List of Accepted Governing Forms is: department, faction, republic, monarchy, anarchism, feudalism"); * break; * } * * // was correct input passed? * switch (message.CommandArgs.ToLower()) * { * case "department": * GovFormNum = 0; * break; * case "faction": * GovFormNum = 1; * break; * case "republic": * GovFormNum = 2; * break; * case "monarchy": * GovFormNum = 3; * break; * case "anarchism": * GovFormNum = 4; * break; * case "feudalism": * GovFormNum = 5; * break; * default: * client.SendChatText(message.CommandArgs + " Is an invalid Governing Form!"); * client.SendChatText( * "Accepted Governing Forms are: department, faction, republic, monarchy, anarchism, feudalism"); * break; * } * * if (GovFormNum != -1) * { * ms.SqlUpdate( * "UPDATE organizations SET GovernmentForm = '" + GovFormNum + "' WHERE ID = '" + client.Character.OrgId + "'"); + foreach (var currentCharId in OrgMisc.GetOrgMembers(client.Character.OrgId, true)) + { + client.Character.Stats.ClanLevel.Set(GetLowestRank(GovFormNum)); + } + + client.SendChatText("Governing Form is now: " + message.CommandArgs); + break; + } + } + else + { + // Haha! You're not the org leader! + client.SendChatText("You must be the Org Leader to perform this command"); + break; + }*/ } break; #endregion #region /org stopvote <text> case 28: // <text> is CmdStr break; #endregion #region unknown command default: break; #endregion } }
public static void PartyInformation(ZoneClient client, Packet packet) { SendPartyInformation(client); }
/// <summary> /// </summary> /// <param name="dynel"> /// </param> /// <param name="destination"> /// </param> /// <param name="heading"> /// </param> /// <param name="playfield"> /// </param> public void Teleport(Dynel dynel, Coordinate destination, IQuaternion heading, Identity playfield) { // Prevent client from entering this again if (dynel.DoNotDoTimers) { return; } Thread.Sleep(200); int dynelId = dynel.Identity.Instance; // Disable sending stat changes and wait a bit to clear the queue dynel.DoNotDoTimers = true; Thread.Sleep(1000); // Teleport to another playfield TeleportMessageHandler.Default.Send( dynel as ICharacter, destination.coordinate, (Vector.Quaternion)heading, playfield); // Send packet, disconnect, and other playfield waits for connect DespawnMessage despawnMessage = DespawnMessageHandler.Default.Create(dynel.Identity); this.AnnounceOthers(despawnMessage, dynel.Identity); dynel.RawCoordinates = new Vector3() { X = destination.x, Y = destination.y, Z = destination.z }; dynel.RawHeading = new Vector.Quaternion(heading.xf, heading.yf, heading.zf, heading.wf); // IMPORTANT!! // Dispose the character object, save new playfield data and then recreate it // else you would end up at weird coordinates in the same playfield // Save client object ZoneClient client = (ZoneClient)dynel.Controller.Client; // Set client=null so dynel can really dispose IPlayfield newPlayfield = this.server.PlayfieldById(playfield); Pool.Instance.GetObject <Playfield>( Identity.None, new Identity() { Type = playfield.Type, Instance = playfield.Instance }); if (newPlayfield == null) { newPlayfield = new Playfield(this.server, playfield); } dynel.Playfield = newPlayfield; dynel.Controller.Client = null; dynel.Dispose(); LogUtil.Debug(DebugInfoDetail.Database, "Saving to pf " + playfield.Instance); // TODO: Get new server ip from chatengine (which has to log all zoneengine's playfields) // for now, just transmit our ip and port IPAddress tempIp; if (IPAddress.TryParse(Config.Instance.CurrentConfig.ZoneIP, out tempIp) == false) { IPHostEntry zoneHost = Dns.GetHostEntry(Config.Instance.CurrentConfig.ZoneIP); foreach (IPAddress ip in zoneHost.AddressList) { if (ip.AddressFamily == AddressFamily.InterNetwork) { tempIp = ip; break; } } } var redirect = new ZoneRedirectionMessage { ServerIpAddress = tempIp, ServerPort = (ushort)this.server.TcpEndPoint.Port }; if (client != null) { client.SendCompressed(redirect); } // client.Server.DisconnectClient(client); }
/// <summary> /// </summary> /// <param name="commandName"> /// </param> /// <param name="client"> /// </param> /// <param name="target"> /// </param> /// <param name="commandArguments"> /// </param> public void CallChatCommand(string commandName, ZoneClient client, Identity target, string[] commandArguments) { Assembly assembly = Assembly.GetExecutingAssembly(); if (commandName.ToUpperInvariant() != "LISTCOMMANDS") { foreach (KeyValuePair <string, Type> kv in this.chatCommands) { if (kv.Key.Substring(kv.Key.IndexOf(":", StringComparison.Ordinal) + 1).ToUpperInvariant() == commandName.ToUpperInvariant()) { AOChatCommand aoc = (AOChatCommand) assembly.CreateInstance( kv.Key.Substring(0, kv.Key.IndexOf(":", StringComparison.Ordinal))); if (aoc != null) { // Check GM Level bitwise if ((client.Character.Stats[StatIds.gmlevel].Value < aoc.GMLevelNeeded()) && (aoc.GMLevelNeeded() > 0)) { client.Character.Playfield.Publish( ChatText.CreateIM( client.Character, "You are not authorized to use this command!. This incident will be recorded.")); // It is not yet :) return; } // Check if only one argument has been passed for "help" if (commandArguments.Length == 2) { if (commandArguments[1].ToUpperInvariant() == "HELP") { aoc.CommandHelp(client.Character); return; } } // Execute the command with the given command arguments, if CheckCommandArguments is true else print command help if (aoc.CheckCommandArguments(commandArguments)) { aoc.ExecuteCommand(client.Character, target, commandArguments); } else { aoc.CommandHelp(client.Character); } } } } } else { client.Character.Playfield.Publish(ChatText.CreateIM(client.Character, "Available Commands:")); string[] scriptNames = this.chatCommands.Keys.ToArray(); for (int i = 0; i < scriptNames.Length; i++) { scriptNames[i] = scriptNames[i].Substring(scriptNames[i].IndexOf(":", StringComparison.Ordinal) + 1) + ":" + scriptNames[i].Substring( 0, scriptNames[i].IndexOf(":", StringComparison.Ordinal)); } Array.Sort(scriptNames); foreach (string scriptName in scriptNames) { string typename = scriptName.Substring(scriptName.IndexOf(":", StringComparison.Ordinal) + 1); AOChatCommand aoc = (AOChatCommand)assembly.CreateInstance(typename); if (aoc != null) { if (client.Character.Stats[StatIds.gmlevel].Value >= aoc.GMLevelNeeded()) { client.Character.Playfield.Publish( ChatText.CreateIM( client.Character, scriptName.Substring(0, scriptName.IndexOf(":", StringComparison.Ordinal)))); } } } } }
public static void StopAttackMeleeHandler(ZoneClient client, Packet packet) { client.Character.AttackStop(); }
public static void HandlePong(ZoneClient character, Packet packet) { character.HasPong = true; }
public static void BeginRestHandler(ZoneClient client, Packet packet) { client.Character.Rest(true); }
public static void MoveItemHandler(ZoneClient pClient, Packet pPacket) { byte oldslot, oldstate, newslot, newstate; if (!pPacket.TryReadByte(out oldslot) || !pPacket.TryReadByte(out oldstate) || !pPacket.TryReadByte(out newslot) || !pPacket.TryReadByte(out newstate)) { Log.WriteLine(LogLevel.Warn, "Could not read item move."); return; } if (oldslot == newslot) { Log.WriteLine(LogLevel.Warn, "Client tried to dupe an item."); return; } Item source; if (!pClient.Character.Inventory.InventoryItems.TryGetValue(oldslot, out source) && newstate != 0x00 && oldstate != 0x00 || newstate == 0x00) { if (pClient.Character.Guild != null) { if (newstate == 0x00 && oldstate == 0x24) { source.Flags = ItemFlags.GuildItem; } else if (newstate == 0x24 && oldstate == 0x00) { source.Flags = ItemFlags.Normal; } else if (source == null || newstate != 0x24) { if (!pClient.Character.Guild.GuildStore.GuildStorageItems.TryGetValue(oldslot, out source)) { return; } } } if (source == null) { Log.WriteLine(LogLevel.Warn, "Client tried to move empty slot."); return; } } if (newslot == 0xff || newstate == 0xff) { pClient.Character.Inventory.InventoryItems.Remove(oldslot); source.Delete(); //TODO: make a drop ModifyInventorySlot(pClient.Character, oldslot, oldstate, (byte)source.Slot, null); } else if (newstate == 0x00 && oldstate == 0x24 && pClient.Character.Guild != null) { if (!pClient.Character.Guild.GuildStore.GetHasFreeGuildStoreSlot()) { //todo GuildStorefuell return; } pClient.Character.Inventory.RemoveInventory(source); pClient.Character.Guild.GuildStore.GuildStorageItems.Add(newslot, source); pClient.Character.Guild.GuildStore.SendAddGuildStore(GuildStoreAddFlags.Item, pClient.Character.Character.Name, source.Ammount, 0, source.ItemInfo.ItemID); pClient.Character.Guild.GuildStore.SaveStoreItem(pClient.Character.Guild.ID, source.ItemInfo.ItemID, newslot); ModifyInventorySlot(pClient.Character, oldstate, newstate, oldslot, null); ModifyInventorySlot(pClient.Character, oldstate, newstate, oldslot, newslot, source); return; } else if (oldstate == 0x00 && newstate == 0x24 && pClient.Character.Guild != null) { if (!pClient.Character.Guild.GuildStore.GuildStorageItems.TryGetValue(oldslot, out source)) { return; } source.Slot = (sbyte)newslot; pClient.Character.Guild.GuildStore.GuildStorageItems.Remove(oldslot); pClient.Character.Inventory.AddToInventory(source); pClient.Character.Guild.GuildStore.SendRemoveFromGuildStore(GuildStoreAddFlags.Item, pClient.Character.Character.Name, source.Ammount, 0, source.ItemInfo.ItemID); pClient.Character.Guild.GuildStore.RemoveStoreItem(pClient.Character.Guild.ID, source.ItemInfo.ItemID); ModifyInventorySlot(pClient.Character, newstate, oldstate, newslot, oldslot, null); ModifyInventorySlot(pClient.Character, newstate, newstate, newstate, newslot, source); return; } if (source.Flags == ItemFlags.Normal) { Item destination; if (pClient.Character.Inventory.InventoryItems.TryGetValue(newslot, out destination)) { //item swap pClient.Character.Inventory.InventoryItems.Remove(oldslot); pClient.Character.Inventory.InventoryItems.Remove(newslot); source.Slot = (sbyte)newslot; destination.Slot = (sbyte)oldslot; pClient.Character.Inventory.InventoryItems.Add(newslot, source); pClient.Character.Inventory.InventoryItems.Add(oldslot, destination); source.Save(); destination.Save(); ModifyInventorySlot(pClient.Character, newslot, 0x24, oldslot, destination); ModifyInventorySlot(pClient.Character, oldslot, 0x24, newslot, source); } else { //item moved to empty slot pClient.Character.Inventory.InventoryItems.Remove(oldslot); pClient.Character.Inventory.InventoryItems.Add(newslot, source); source.Slot = (sbyte)newslot; source.Save(); ModifyInventorySlot(pClient.Character, newslot, 0x24, oldslot, null); ModifyInventorySlot(pClient.Character, oldslot, 0x24, newslot, source); } } else if (source.Flags == ItemFlags.GuildItem) { Item destination; if (pClient.Character.Guild.GuildStore.GuildStorageItems.TryGetValue(newslot, out destination)) { //item swap pClient.Character.Guild.GuildStore.GuildStorageItems.Remove(oldslot); pClient.Character.Guild.GuildStore.GuildStorageItems.Remove(newslot); source.Slot = (sbyte)newslot; destination.Slot = (sbyte)oldslot; pClient.Character.Guild.GuildStore.GuildStorageItems.Add(newslot, source); pClient.Character.Guild.GuildStore.GuildStorageItems.Add(oldslot, destination); ModifyInventorySlot(pClient.Character, oldstate, newstate, newslot, oldslot, destination); ModifyInventorySlot(pClient.Character, oldstate, oldstate, newstate, newslot, source); } else { //item moved to empty slot pClient.Character.Guild.GuildStore.GuildStorageItems.Remove(oldslot); pClient.Character.Guild.GuildStore.GuildStorageItems.Add(newslot, source); source.Slot = (sbyte)newslot; ModifyInventorySlot(pClient.Character, oldstate, newstate, newslot, oldslot, null); ModifyInventorySlot(pClient.Character, newstate, oldstate, newstate, newslot, source); } } }