From ca4f00cfe39f28ece3f84c3e5f3f6931eae5a487 Mon Sep 17 00:00:00 2001 From: Filip Maj Date: Thu, 25 Jul 2019 19:44:22 -0400 Subject: [PATCH] Fixed bug where no name would appear in the post-chocobo naming cutscene. --- Map Server/Actors/Chara/Player/Player.cs | 3 + Map Server/actors/chara/player/Player.cs | 2858 ---------------------- 2 files changed, 3 insertions(+), 2858 deletions(-) delete mode 100644 Map Server/actors/chara/player/Player.cs diff --git a/Map Server/Actors/Chara/Player/Player.cs b/Map Server/Actors/Chara/Player/Player.cs index 13016595..89857575 100644 --- a/Map Server/Actors/Chara/Player/Player.cs +++ b/Map Server/Actors/Chara/Player/Player.cs @@ -1909,6 +1909,9 @@ namespace Meteor.Map.Actors hasChocobo = true; chocoboAppearance = appearanceId; chocoboName = nameResponse; + + QueuePacket(SetChocoboNamePacket.BuildPacket(actorId, chocoboName)); + QueuePacket(SetHasChocoboPacket.BuildPacket(actorId, hasChocobo)); } public void ChangeChocoboAppearance(byte appearanceId) diff --git a/Map Server/actors/chara/player/Player.cs b/Map Server/actors/chara/player/Player.cs deleted file mode 100644 index 13016595..00000000 --- a/Map Server/actors/chara/player/Player.cs +++ /dev/null @@ -1,2858 +0,0 @@ -/* -=========================================================================== -Copyright (C) 2015-2019 Project Meteor Dev Team - -This file is part of Project Meteor Server. - -Project Meteor Server is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -Project Meteor Server is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Affero General Public License for more details. - -You should have received a copy of the GNU Affero General Public License -along with Project Meteor Server. If not, see . -=========================================================================== -*/ - -using Meteor.Common; -using System; -using System.Collections.Generic; -using MoonSharp.Interpreter; -using Meteor.Map.dataobjects; -using Meteor.Map.dataobjects.chara; -using Meteor.Map.lua; -using Meteor.Map.packets.WorldPackets.Send.Group; -using Meteor.Map.utils; -using Meteor.Map.actors.group; -using Meteor.Map.actors.chara.player; -using Meteor.Map.actors.director; -using Meteor.Map.actors.chara.npc; -using Meteor.Map.actors.chara.ai; -using Meteor.Map.actors.chara.ai.controllers; -using Meteor.Map.actors.chara.ai.utils; -using Meteor.Map.actors.chara.ai.state; -using Meteor.Map.actors.chara; -using Meteor.Map.packets.send; -using Meteor.Map.packets.send.actor; -using Meteor.Map.packets.send.events; -using Meteor.Map.packets.send.actor.inventory; -using Meteor.Map.packets.send.player; -using Meteor.Map.packets.send.actor.battle; -using Meteor.Map.packets.receive.events; -using static Meteor.Map.LuaUtils; - -namespace Meteor.Map.Actors -{ - class Player : Character - { - public const int TIMER_TOTORAK = 0; - public const int TIMER_DZEMAEL = 1; - public const int TIMER_BOWL_OF_EMBERS_HARD = 2; - public const int TIMER_BOWL_OF_EMBERS = 3; - public const int TIMER_THORNMARCH = 4; - public const int TIMER_AURUMVALE = 5; - public const int TIMER_CUTTERSCRY = 6; - public const int TIMER_BATTLE_ALEPORT = 7; - public const int TIMER_BATTLE_HYRSTMILL = 8; - public const int TIMER_BATTLE_GOLDENBAZAAR = 9; - public const int TIMER_HOWLING_EYE_HARD = 10; - public const int TIMER_HOWLING_EYE = 11; - public const int TIMER_CASTRUM_TOWER = 12; - public const int TIMER_BOWL_OF_EMBERS_EXTREME = 13; - public const int TIMER_RIVENROAD = 14; - public const int TIMER_RIVENROAD_HARD = 15; - public const int TIMER_BEHEST = 16; - public const int TIMER_COMPANYBEHEST = 17; - public const int TIMER_RETURN = 18; - public const int TIMER_SKIRMISH = 19; - - public const int NPCLS_GONE = 0; - public const int NPCLS_INACTIVE = 1; - public const int NPCLS_ACTIVE = 2; - public const int NPCLS_ALERT = 3; - - public const int SLOT_MAINHAND = 0; - public const int SLOT_OFFHAND = 1; - public const int SLOT_THROWINGWEAPON = 4; - public const int SLOT_PACK = 5; - public const int SLOT_POUCH = 6; - public const int SLOT_HEAD = 8; - public const int SLOT_UNDERSHIRT = 9; - public const int SLOT_BODY = 10; - public const int SLOT_UNDERGARMENT = 11; - public const int SLOT_LEGS = 12; - public const int SLOT_HANDS = 13; - public const int SLOT_BOOTS = 14; - public const int SLOT_WAIST = 15; - public const int SLOT_NECK = 16; - public const int SLOT_EARS = 17; - public const int SLOT_WRISTS = 19; - public const int SLOT_RIGHTFINGER = 21; - public const int SLOT_LEFTFINGER = 22; - - public static int[] MAXEXP = {570, 700, 880, 1100, 1500, 1800, 2300, 3200, 4300, 5000, //Level <= 10 - 5900, 6800, 7700, 8700, 9700, 11000, 12000, 13000, 15000, 16000, //Level <= 20 - 20000, 22000, 23000, 25000, 27000, 29000, 31000, 33000, 35000, 38000, //Level <= 30 - 45000, 47000, 50000, 53000, 56000, 59000, 62000, 65000, 68000, 71000, //Level <= 40 - 74000, 78000, 81000, 85000, 89000, 92000, 96000, 100000, 100000, 110000}; //Level <= 50 - - //Event Related - public uint currentEventOwner = 0; - public string currentEventName = ""; - public Coroutine currentEventRunning; - - //Player Info - public uint destinationZone; - public ushort destinationSpawnType; - public uint[] timers = new uint[20]; - public uint currentTitle; - public uint playTime; - public uint lastPlayTimeUpdate; - public bool isGM = false; - public bool isZoneChanging = true; - - //Trading - private Player otherTrader = null; - private ReferencedItemPackage myOfferings; - private bool isTradeAccepted = false; - - //GC Related - public byte gcCurrent; - public byte gcRankLimsa; - public byte gcRankGridania; - public byte gcRankUldah; - - //Mount Related - public bool hasChocobo; - public bool hasGoobbue; - public string chocoboName; - public byte mountState = 0; - public byte chocoboAppearance; - public uint rentalExpireTime = 0; - public byte rentalMinLeft = 0; - - public uint achievementPoints; - - //Property Array Request Stuff - private int lastPosition = 0; - private int lastStep = 0; - - //Quest Actors (MUST MATCH playerWork.questScenario/questGuildleve) - public Quest[] questScenario = new Quest[16]; - public uint[] questGuildleve = new uint[8]; - - //Aetheryte - public uint homepoint = 0; - public byte homepointInn = 0; - - //Nameplate Stuff - public uint currentLSPlate = 0; - public byte repairType = 0; - - //Retainer - RetainerMeetingRelationGroup retainerMeetingGroup = null; - public Retainer currentSpawnedRetainer = null; - public bool sentRetainerSpawn = false; - - private List ownedDirectors = new List(); - private Director loginInitDirector = null; - - List hotbarSlotsToUpdate = new List(); - - public PlayerWork playerWork = new PlayerWork(); - - public Session playerSession; - - public Player(Session cp, uint actorID) : base(actorID) - { - playerSession = cp; - actorName = String.Format("_pc{0:00000000}", actorID); - className = "Player"; - - moveSpeeds[0] = SetActorSpeedPacket.DEFAULT_STOP; - moveSpeeds[1] = SetActorSpeedPacket.DEFAULT_WALK; - moveSpeeds[2] = SetActorSpeedPacket.DEFAULT_RUN; - moveSpeeds[3] = SetActorSpeedPacket.DEFAULT_ACTIVE; - - itemPackages[ItemPackage.NORMAL] = new ItemPackage(this, ItemPackage.MAXSIZE_NORMAL, ItemPackage.NORMAL); - itemPackages[ItemPackage.KEYITEMS] = new ItemPackage(this, ItemPackage.MAXSIZE_KEYITEMS, ItemPackage.KEYITEMS); - itemPackages[ItemPackage.CURRENCY_CRYSTALS] = new ItemPackage(this, ItemPackage.MAXSIZE_CURRANCY, ItemPackage.CURRENCY_CRYSTALS); - itemPackages[ItemPackage.MELDREQUEST] = new ItemPackage(this, ItemPackage.MAXSIZE_MELDREQUEST, ItemPackage.MELDREQUEST); - itemPackages[ItemPackage.BAZAAR] = new ItemPackage(this, ItemPackage.MAXSIZE_BAZAAR, ItemPackage.BAZAAR); - itemPackages[ItemPackage.LOOT] = new ItemPackage(this, ItemPackage.MAXSIZE_LOOT, ItemPackage.LOOT); - equipment = new ReferencedItemPackage(this, ItemPackage.MAXSIZE_EQUIPMENT, ItemPackage.EQUIPMENT); - - //Set the Skill level caps of all FFXIV (classes)skills to 50 - for (int i = 0; i < charaWork.battleSave.skillLevelCap.Length; i++) - { - if (i != CLASSID_PUG && - i != CLASSID_MRD && - i != CLASSID_GLA && - i != CLASSID_MRD && - i != CLASSID_ARC && - i != CLASSID_LNC && - i != CLASSID_THM && - i != CLASSID_CNJ && - i != CLASSID_CRP && - i != CLASSID_BSM && - i != CLASSID_ARM && - i != CLASSID_GSM && - i != CLASSID_LTW && - i != CLASSID_WVR && - i != CLASSID_ALC && - i != CLASSID_CUL && - i != CLASSID_MIN && - i != CLASSID_BTN && - i != CLASSID_FSH) - charaWork.battleSave.skillLevelCap[i] = 0xFF; - else - charaWork.battleSave.skillLevelCap[i] = 50; - - } - - charaWork.property[0] = 1; - charaWork.property[1] = 1; - charaWork.property[2] = 1; - charaWork.property[4] = 1; - - charaWork.command[0] = 0xA0F00000 | 21001; - charaWork.command[1] = 0xA0F00000 | 21001; - - charaWork.command[2] = 0xA0F00000 | 21002; - charaWork.command[3] = 0xA0F00000 | 12004; - charaWork.command[4] = 0xA0F00000 | 21005; - charaWork.command[5] = 0xA0F00000 | 21006; - charaWork.command[6] = 0xA0F00000 | 21007; - charaWork.command[7] = 0xA0F00000 | 12009; - charaWork.command[8] = 0xA0F00000 | 12010; - charaWork.command[9] = 0xA0F00000 | 12005; - charaWork.command[10] = 0xA0F00000 | 12007; - charaWork.command[11] = 0xA0F00000 | 12011; - charaWork.command[12] = 0xA0F00000 | 22012; - charaWork.command[13] = 0xA0F00000 | 22013; - charaWork.command[14] = 0xA0F00000 | 29497; - charaWork.command[15] = 0xA0F00000 | 22015; - - charaWork.commandAcquired[27150 - 26000] = true; - - playerWork.questScenarioComplete[110001 - 110001] = true; - playerWork.questGuildleveComplete[120050 - 120001] = true; - - for (int i = 0; i < charaWork.additionalCommandAcquired.Length; i++ ) - charaWork.additionalCommandAcquired[i] = true; - - for (int i = 0; i < charaWork.commandCategory.Length; i++) - charaWork.commandCategory[i] = 1; - - charaWork.battleTemp.generalParameter[3] = 1; - - charaWork.eventSave.bazaarTax = 5; - charaWork.battleSave.potencial = 6.6f; - - charaWork.battleSave.negotiationFlag[0] = true; - - charaWork.commandCategory[0] = 1; - charaWork.commandCategory[1] = 1; - - charaWork.parameterSave.commandSlot_compatibility[0] = true; - charaWork.parameterSave.commandSlot_compatibility[1] = true; - - charaWork.commandBorder = 0x20; - - charaWork.parameterTemp.tp = 0; - - Database.LoadPlayerCharacter(this); - lastPlayTimeUpdate = Utils.UnixTimeStampUTC(); - - this.aiContainer = new AIContainer(this, new PlayerController(this), null, new TargetFind(this)); - allegiance = CharacterTargetingAllegiance.Player; - CalculateBaseStats(); - } - - public List Create0x132Packets() - { - List packets = new List(); - packets.Add(_0x132Packet.BuildPacket(actorId, 0xB, "commandForced")); - packets.Add(_0x132Packet.BuildPacket(actorId, 0xA, "commandDefault")); - packets.Add(_0x132Packet.BuildPacket(actorId, 0x6, "commandWeak")); - packets.Add(_0x132Packet.BuildPacket(actorId, 0x4, "commandContent")); - packets.Add(_0x132Packet.BuildPacket(actorId, 0x6, "commandJudgeMode")); - packets.Add(_0x132Packet.BuildPacket(actorId, 0x100, "commandRequest")); - packets.Add(_0x132Packet.BuildPacket(actorId, 0x100, "widgetCreate")); - packets.Add(_0x132Packet.BuildPacket(actorId, 0x100, "macroRequest")); - return packets; - } - - /* - * PLAYER ARGS: - * Unknown - Bool - * Unknown - Bool - * Is Init Director - Bool - * Unknown - Bool - * Unknown - Number - * Unknown - Bool - * Timer Array - 20 Number - */ - - public override SubPacket CreateScriptBindPacket(Player requestPlayer) - { - List lParams; - if (IsMyPlayer(requestPlayer.actorId)) - { - if (loginInitDirector != null) - lParams = LuaUtils.CreateLuaParamList("/Chara/Player/Player_work", false, false, true, loginInitDirector, true, 0, false, timers, true); - else - lParams = LuaUtils.CreateLuaParamList("/Chara/Player/Player_work", true, false, false, true, 0, false, timers, true); - } - else - lParams = LuaUtils.CreateLuaParamList("/Chara/Player/Player_work", false, false, false, false, false, true); - - ActorInstantiatePacket.BuildPacket(actorId, actorName, className, lParams).DebugPrintSubPacket(); - - - return ActorInstantiatePacket.BuildPacket(actorId, actorName, className, lParams); - } - - public override List GetSpawnPackets(Player requestPlayer, ushort spawnType) - { - List subpackets = new List(); - subpackets.Add(CreateAddActorPacket(8)); - if (IsMyPlayer(requestPlayer.actorId)) - subpackets.AddRange(Create0x132Packets()); - subpackets.Add(CreateSpeedPacket()); - subpackets.Add(CreateSpawnPositonPacket(this, spawnType)); - subpackets.Add(CreateAppearancePacket()); - subpackets.Add(CreateNamePacket()); - subpackets.Add(_0xFPacket.BuildPacket(actorId)); - subpackets.Add(CreateStatePacket()); - subpackets.Add(CreateSubStatePacket()); - subpackets.Add(CreateInitStatusPacket()); - subpackets.Add(CreateSetActorIconPacket()); - subpackets.Add(CreateIsZoneingPacket()); - subpackets.AddRange(CreatePlayerRelatedPackets(requestPlayer.actorId)); - subpackets.Add(CreateScriptBindPacket(requestPlayer)); - return subpackets; - } - - public List CreatePlayerRelatedPackets(uint requestingPlayerActorId) - { - List subpackets = new List(); - - if (gcCurrent != 0) - subpackets.Add(SetGrandCompanyPacket.BuildPacket(actorId, gcCurrent, gcRankLimsa, gcRankGridania, gcRankUldah)); - - if (currentTitle != 0) - subpackets.Add(SetPlayerTitlePacket.BuildPacket(actorId, currentTitle)); - - if (currentJob != 0) - subpackets.Add(SetCurrentJobPacket.BuildPacket(actorId, currentJob)); - - if (IsMyPlayer(requestingPlayerActorId)) - { - subpackets.Add(SetSpecialEventWorkPacket.BuildPacket(actorId)); - - if (hasChocobo && chocoboName != null && !chocoboName.Equals("")) - { - subpackets.Add(SetChocoboNamePacket.BuildPacket(actorId, chocoboName)); - subpackets.Add(SetHasChocoboPacket.BuildPacket(actorId, hasChocobo)); - } - - if (hasGoobbue) - subpackets.Add(SetHasGoobbuePacket.BuildPacket(actorId, hasGoobbue)); - - subpackets.Add(SetAchievementPointsPacket.BuildPacket(actorId, achievementPoints)); - - subpackets.Add(Database.GetLatestAchievements(this)); - subpackets.Add(Database.GetAchievementsPacket(this)); - } - - if (mountState == 1) - subpackets.Add(SetCurrentMountChocoboPacket.BuildPacket(actorId, chocoboAppearance, rentalExpireTime, rentalMinLeft)); - else if (mountState == 2) - subpackets.Add(SetCurrentMountGoobbuePacket.BuildPacket(actorId, 1)); - - return subpackets; - } - - public override List GetInitPackets() - { - ActorPropertyPacketUtil propPacketUtil = new ActorPropertyPacketUtil("/_init", this); - - propPacketUtil.AddProperty("charaWork.eventSave.bazaarTax"); - propPacketUtil.AddProperty("charaWork.battleSave.potencial"); - - //Properties - for (int i = 0; i < charaWork.property.Length; i++) - { - if (charaWork.property[i] != 0) - propPacketUtil.AddProperty(String.Format("charaWork.property[{0}]", i)); - } - - //Parameters - propPacketUtil.AddProperty("charaWork.parameterSave.hp[0]"); - propPacketUtil.AddProperty("charaWork.parameterSave.hpMax[0]"); - propPacketUtil.AddProperty("charaWork.parameterSave.mp"); - propPacketUtil.AddProperty("charaWork.parameterSave.mpMax"); - propPacketUtil.AddProperty("charaWork.parameterTemp.tp"); - propPacketUtil.AddProperty("charaWork.parameterSave.state_mainSkill[0]"); - propPacketUtil.AddProperty("charaWork.parameterSave.state_mainSkillLevel"); - - //Status Times - for (int i = 0; i < charaWork.statusShownTime.Length; i++) - { - if (charaWork.statusShownTime[i] != 0) - propPacketUtil.AddProperty(String.Format("charaWork.statusShownTime[{0}]", i)); - } - - //General Parameters - for (int i = 3; i < charaWork.battleTemp.generalParameter.Length; i++) - { - if (charaWork.battleTemp.generalParameter[i] != 0) - propPacketUtil.AddProperty(String.Format("charaWork.battleTemp.generalParameter[{0}]", i)); - } - - propPacketUtil.AddProperty("charaWork.battleTemp.castGauge_speed[0]"); - propPacketUtil.AddProperty("charaWork.battleTemp.castGauge_speed[1]"); - - //Battle Save Skillpoint - propPacketUtil.AddProperty(String.Format("charaWork.battleSave.skillPoint[{0}]", charaWork.parameterSave.state_mainSkill[0] - 1)); - - //Commands - propPacketUtil.AddProperty("charaWork.commandBorder"); - - propPacketUtil.AddProperty("charaWork.battleSave.negotiationFlag[0]"); - - for (int i = 0; i < charaWork.command.Length; i++) - { - if (charaWork.command[i] != 0) - { - propPacketUtil.AddProperty(String.Format("charaWork.command[{0}]", i)); - //Recast Timers - if(i >= charaWork.commandBorder) - { - propPacketUtil.AddProperty(String.Format("charaWork.parameterTemp.maxCommandRecastTime[{0}]", i - charaWork.commandBorder)); - propPacketUtil.AddProperty(String.Format("charaWork.parameterSave.commandSlot_recastTime[{0}]", i - charaWork.commandBorder)); - } - } - } - - for (int i = 0; i < charaWork.commandCategory.Length; i++) - { - charaWork.commandCategory[i] = 1; - if (charaWork.commandCategory[i] != 0) - propPacketUtil.AddProperty(String.Format("charaWork.commandCategory[{0}]", i)); - } - - for (int i = 0; i < charaWork.commandAcquired.Length; i++) - { - if (charaWork.commandAcquired[i] != false) - propPacketUtil.AddProperty(String.Format("charaWork.commandAcquired[{0}]", i)); - } - - for (int i = 0; i < charaWork.additionalCommandAcquired.Length; i++) - { - if (charaWork.additionalCommandAcquired[i] != false) - propPacketUtil.AddProperty(String.Format("charaWork.additionalCommandAcquired[{0}]", i)); - } - - for (int i = 0; i < charaWork.parameterSave.commandSlot_compatibility.Length; i++) - { - charaWork.parameterSave.commandSlot_compatibility[i] = true; - if (charaWork.parameterSave.commandSlot_compatibility[i]) - propPacketUtil.AddProperty(String.Format("charaWork.parameterSave.commandSlot_compatibility[{0}]", i)); - } - - for (int i = 0; i < charaWork.parameterSave.commandSlot_recastTime.Length; i++) - { - if (charaWork.parameterSave.commandSlot_recastTime[i] != 0) - propPacketUtil.AddProperty(String.Format("charaWork.parameterSave.commandSlot_recastTime[{0}]", i)); - } - - //System - propPacketUtil.AddProperty("charaWork.parameterTemp.forceControl_float_forClientSelf[0]"); - propPacketUtil.AddProperty("charaWork.parameterTemp.forceControl_float_forClientSelf[1]"); - propPacketUtil.AddProperty("charaWork.parameterTemp.forceControl_int16_forClientSelf[0]"); - propPacketUtil.AddProperty("charaWork.parameterTemp.forceControl_int16_forClientSelf[1]"); - - charaWork.parameterTemp.otherClassAbilityCount[0] = 4; - charaWork.parameterTemp.otherClassAbilityCount[1] = 5; - charaWork.parameterTemp.giftCount[1] = 5; - - propPacketUtil.AddProperty("charaWork.parameterTemp.otherClassAbilityCount[0]"); - propPacketUtil.AddProperty("charaWork.parameterTemp.otherClassAbilityCount[1]"); - propPacketUtil.AddProperty("charaWork.parameterTemp.giftCount[1]"); - - propPacketUtil.AddProperty("charaWork.depictionJudge"); - - //Scenario - for (int i = 0; i < playerWork.questScenario.Length; i++) - { - if (playerWork.questScenario[i] != 0) - propPacketUtil.AddProperty(String.Format("playerWork.questScenario[{0}]", i)); - } - - //Guildleve - Local - for (int i = 0; i < playerWork.questGuildleve.Length; i++) - { - if (playerWork.questGuildleve[i] != 0) - propPacketUtil.AddProperty(String.Format("playerWork.questGuildleve[{0}]", i)); - } - - //Guildleve - Regional - for (int i = 0; i < work.guildleveId.Length; i++) - { - if (work.guildleveId[i] != 0) - propPacketUtil.AddProperty(String.Format("work.guildleveId[{0}]", i)); - if (work.guildleveDone[i] != false) - propPacketUtil.AddProperty(String.Format("work.guildleveDone[{0}]", i)); - if (work.guildleveChecked[i] != false) - propPacketUtil.AddProperty(String.Format("work.guildleveChecked[{0}]", i)); - } - - //Bazaar - CheckBazaarFlags(true); - if (charaWork.eventSave.repairType != 0) - propPacketUtil.AddProperty("charaWork.eventSave.repairType"); - if (charaWork.eventTemp.bazaarRetail) - propPacketUtil.AddProperty("charaWork.eventTemp.bazaarRetail"); - if (charaWork.eventTemp.bazaarRepair) - propPacketUtil.AddProperty("charaWork.eventTemp.bazaarRepair"); - if (charaWork.eventTemp.bazaarMateria) - propPacketUtil.AddProperty("charaWork.eventTemp.bazaarMateria"); - - //NPC Linkshell - for (int i = 0; i < playerWork.npcLinkshellChatCalling.Length; i++) - { - if (playerWork.npcLinkshellChatCalling[i] != false) - propPacketUtil.AddProperty(String.Format("playerWork.npcLinkshellChatCalling[{0}]", i)); - if (playerWork.npcLinkshellChatExtra[i] != false) - propPacketUtil.AddProperty(String.Format("playerWork.npcLinkshellChatExtra[{0}]", i)); - } - - propPacketUtil.AddProperty("playerWork.restBonusExpRate"); - - //Profile - propPacketUtil.AddProperty("playerWork.tribe"); - propPacketUtil.AddProperty("playerWork.guardian"); - propPacketUtil.AddProperty("playerWork.birthdayMonth"); - propPacketUtil.AddProperty("playerWork.birthdayDay"); - propPacketUtil.AddProperty("playerWork.initialTown"); - - return propPacketUtil.Done(); - } - - public void SendSeamlessZoneInPackets() - { - QueuePacket(SetMusicPacket.BuildPacket(actorId, zone.bgmDay, SetMusicPacket.EFFECT_FADEIN)); - QueuePacket(SetWeatherPacket.BuildPacket(actorId, SetWeatherPacket.WEATHER_CLEAR, 1)); - } - - public void SendZoneInPackets(WorldManager world, ushort spawnType) - { - QueuePacket(SetActorIsZoningPacket.BuildPacket(actorId, false)); - QueuePacket(SetDalamudPacket.BuildPacket(actorId, 0)); - if (spawnType != 0x13 && spawnType != 0x14) - QueuePacket(SetMusicPacket.BuildPacket(actorId, zone.bgmDay, 0x01)); - QueuePacket(SetWeatherPacket.BuildPacket(actorId, SetWeatherPacket.WEATHER_CLEAR, 1)); - - QueuePacket(SetMapPacket.BuildPacket(actorId, zone.regionId, zone.actorId)); - - QueuePackets(GetSpawnPackets(this, spawnType)); - //GetSpawnPackets(actorId, spawnType).DebugPrintPacket(); - - #region Inventory & Equipment - QueuePacket(InventoryBeginChangePacket.BuildPacket(actorId, true)); - itemPackages[ItemPackage.NORMAL].SendFullPackage(this); - itemPackages[ItemPackage.CURRENCY_CRYSTALS].SendFullPackage(this); - itemPackages[ItemPackage.KEYITEMS].SendFullPackage(this); - itemPackages[ItemPackage.BAZAAR].SendFullPackage(this); - itemPackages[ItemPackage.MELDREQUEST].SendFullPackage(this); - itemPackages[ItemPackage.LOOT].SendFullPackage(this); - equipment.SendUpdate(this); - playerSession.QueuePacket(InventoryEndChangePacket.BuildPacket(actorId)); - #endregion - - playerSession.QueuePacket(GetInitPackets()); - - List areaMasterSpawn = zone.GetSpawnPackets(); - List debugSpawn = world.GetDebugActor().GetSpawnPackets(); - List worldMasterSpawn = world.GetActor().GetSpawnPackets(); - - playerSession.QueuePacket(areaMasterSpawn); - playerSession.QueuePacket(debugSpawn); - playerSession.QueuePacket(worldMasterSpawn); - - //Inn Packets (Dream, Cutscenes, Armoire) - - if (zone.isInn) - { - SetCutsceneBookPacket cutsceneBookPacket = new SetCutsceneBookPacket(); - for (int i = 0; i < 2048; i++) - cutsceneBookPacket.cutsceneFlags[i] = true; - SubPacket packet = cutsceneBookPacket.BuildPacket(actorId, "", 11, 1, 1); - - packet.DebugPrintSubPacket(); - QueuePacket(packet); - QueuePacket(SetPlayerItemStoragePacket.BuildPacket(actorId)); - } - - if (zone.GetWeatherDirector() != null) - { - playerSession.QueuePacket(zone.GetWeatherDirector().GetSpawnPackets()); - } - - - foreach (Director director in ownedDirectors) - { - QueuePackets(director.GetSpawnPackets()); - QueuePackets(director.GetInitPackets()); - } - - if (currentContentGroup != null) - currentContentGroup.SendGroupPackets(playerSession); - - if (currentParty != null) - currentParty.SendGroupPackets(playerSession); - } - - private void SendRemoveInventoryPackets(List slots) - { - int currentIndex = 0; - - while (true) - { - if (slots.Count - currentIndex >= 64) - QueuePacket(InventoryRemoveX64Packet.BuildPacket(actorId, slots, ref currentIndex)); - else if (slots.Count - currentIndex >= 32) - QueuePacket(InventoryRemoveX32Packet.BuildPacket(actorId, slots, ref currentIndex)); - else if (slots.Count - currentIndex >= 16) - QueuePacket(InventoryRemoveX16Packet.BuildPacket(actorId, slots, ref currentIndex)); - else if (slots.Count - currentIndex >= 8) - QueuePacket(InventoryRemoveX08Packet.BuildPacket(actorId, slots, ref currentIndex)); - else if (slots.Count - currentIndex == 1) - QueuePacket(InventoryRemoveX01Packet.BuildPacket(actorId, slots[currentIndex])); - else - break; - } - - } - - public bool IsMyPlayer(uint otherActorId) - { - return actorId == otherActorId; - } - - public void QueuePacket(SubPacket packet) - - { - playerSession.QueuePacket(packet); - } - - public void QueuePackets(List packets) - { - playerSession.QueuePacket(packets); - } - - public void SendPacket(string path) - { - try - { - BasePacket packet = new BasePacket(path); - - packet.ReplaceActorID(actorId); - var packets = packet.GetSubpackets(); - QueuePackets(packets); - } - catch (Exception e) - { - this.SendMessage(SendMessagePacket.MESSAGE_TYPE_SYSTEM_ERROR, "[SendPacket]", "Unable to send packet."); - this.SendMessage(SendMessagePacket.MESSAGE_TYPE_SYSTEM_ERROR, "[SendPacket]", e.Message); - } - } - - public void BroadcastPackets(List packets, bool sendToSelf) - { - foreach (SubPacket packet in packets) - { - if (sendToSelf) - { - - SubPacket clonedPacket = new SubPacket(packet, actorId); - QueuePacket(clonedPacket); - } - - foreach (Actor a in playerSession.actorInstanceList) - { - if (a is Player) - { - Player p = (Player)a; - - if (p.Equals(this)) - continue; - - SubPacket clonedPacket = new SubPacket(packet, a.actorId); - p.QueuePacket(clonedPacket); - } - } - } - } - - public void BroadcastPacket(SubPacket packet, bool sendToSelf) - { - if (sendToSelf) - { - SubPacket clonedPacket = new SubPacket(packet, actorId); - QueuePacket(clonedPacket); - } - - foreach (Actor a in playerSession.actorInstanceList) - { - if (a is Player) - { - Player p = (Player)a; - - if (p.Equals(this)) - continue; - - SubPacket clonedPacket = new SubPacket(packet, a.actorId); - p.QueuePacket(clonedPacket); - } - } - } - - public void ChangeAnimation(uint animId) - { - Actor a = zone.FindActorInArea(currentTarget); - if (a is Npc) - ((Npc)a).animationId = animId; - } - - public void SetDCFlag(bool flag) - { - if (flag) - { - BroadcastPacket(SetActorIconPacket.BuildPacket(actorId, SetActorIconPacket.DISCONNECTING), true); - } - else - { - if (isGM) - BroadcastPacket(SetActorIconPacket.BuildPacket(actorId, SetActorIconPacket.ISGM), true); - else - BroadcastPacket(SetActorIconPacket.BuildPacket(actorId, 0), true); - } - } - - public void CleanupAndSave() - { - playerSession.LockUpdates(true); - - //Remove actor from zone and main server list - zone.RemoveActorFromZone(this); - - //Set Destination to 0 - this.destinationZone = 0; - this.destinationSpawnType = 0; - - //Clean up parties - RemoveFromCurrentPartyAndCleanup(); - - //Save Player - Database.SavePlayerPlayTime(this); - Database.SavePlayerPosition(this); - Database.SavePlayerStatusEffects(this); - } - - public void CleanupAndSave(uint destinationZone, ushort spawnType, float destinationX, float destinationY, float destinationZ, float destinationRot) - { - playerSession.LockUpdates(true); - - //Remove actor from zone and main server list - zone.RemoveActorFromZone(this); - - //Clean up parties - RemoveFromCurrentPartyAndCleanup(); - - //Set destination - this.destinationZone = destinationZone; - this.destinationSpawnType = spawnType; - this.positionX = destinationX; - this.positionY = destinationY; - this.positionZ = destinationZ; - this.rotation = destinationRot; - - this.statusEffects.RemoveStatusEffectsByFlags((uint)StatusEffectFlags.LoseOnZoning); - - //Save Player - Database.SavePlayerPlayTime(this); - Database.SavePlayerPosition(this); - Database.SavePlayerStatusEffects(this); - } - - public Area GetZone() - { - return zone; - } - - public void SendMessage(uint logType, string sender, string message) - { - QueuePacket(SendMessagePacket.BuildPacket(actorId, logType, sender, message)); - } - - public void Logout() - { - // todo: really this should be in CleanupAndSave but we might want logout/disconnect handled separately for some effects - QueuePacket(LogoutPacket.BuildPacket(actorId)); - statusEffects.RemoveStatusEffectsByFlags((uint)StatusEffectFlags.LoseOnLogout); - CleanupAndSave(); - } - - public void QuitGame() - { - QueuePacket(QuitPacket.BuildPacket(actorId)); - statusEffects.RemoveStatusEffectsByFlags((uint)StatusEffectFlags.LoseOnLogout); - CleanupAndSave(); - } - - public uint GetPlayTime(bool doUpdate) - { - if (doUpdate) - { - uint curTime = Utils.UnixTimeStampUTC(); - playTime += curTime - lastPlayTimeUpdate; - lastPlayTimeUpdate = curTime; - } - - return playTime; - } - - public void SavePlayTime() - { - Database.SavePlayerPlayTime(this); - } - - public void ChangeMusic(ushort musicId) - { - QueuePacket(SetMusicPacket.BuildPacket(actorId, musicId, 1)); - } - - public void SendMountAppearance() - { - if (mountState == 1) - BroadcastPacket(SetCurrentMountChocoboPacket.BuildPacket(actorId, chocoboAppearance, rentalExpireTime, rentalMinLeft), true); - else if (mountState == 2) - BroadcastPacket(SetCurrentMountGoobbuePacket.BuildPacket(actorId, 1), true); - } - - public void SetMountState(byte mountState) - { - this.mountState = mountState; - SendMountAppearance(); - } - - public byte GetMountState() - { - return mountState; - } - - public void DoEmote(uint targettedActor, uint animId, uint descId) - { - BroadcastPacket(ActorDoEmotePacket.BuildPacket(actorId, targettedActor, animId, descId), true); - } - - public void SendGameMessage(Actor sourceActor, Actor textIdOwner, ushort textId, byte log, params object[] msgParams) - { - if (msgParams == null || msgParams.Length == 0) - { - QueuePacket(GameMessagePacket.BuildPacket(Server.GetWorldManager().GetActor().actorId, sourceActor.actorId, textIdOwner.actorId, textId, log)); - } - else - QueuePacket(GameMessagePacket.BuildPacket(Server.GetWorldManager().GetActor().actorId, sourceActor.actorId, textIdOwner.actorId, textId, log, LuaUtils.CreateLuaParamList(msgParams))); - } - - public void SendGameMessage(Actor textIdOwner, ushort textId, byte log, params object[] msgParams) - { - if (msgParams == null || msgParams.Length == 0) - QueuePacket(GameMessagePacket.BuildPacket(Server.GetWorldManager().GetActor().actorId, textIdOwner.actorId, textId, log)); - else - QueuePacket(GameMessagePacket.BuildPacket(Server.GetWorldManager().GetActor().actorId, textIdOwner.actorId, textId, log, LuaUtils.CreateLuaParamList(msgParams))); - } - - public void SendGameMessageCustomSender(Actor textIdOwner, ushort textId, byte log, string customSender, params object[] msgParams) - { - if (msgParams == null || msgParams.Length == 0) - QueuePacket(GameMessagePacket.BuildPacket(Server.GetWorldManager().GetActor().actorId, textIdOwner.actorId, textId, customSender, log)); - else - QueuePacket(GameMessagePacket.BuildPacket(Server.GetWorldManager().GetActor().actorId, textIdOwner.actorId, textId, customSender, log, LuaUtils.CreateLuaParamList(msgParams))); - } - - public void SendGameMessageDisplayIDSender(Actor textIdOwner, ushort textId, byte log, uint displayId, params object[] msgParams) - { - if (msgParams == null || msgParams.Length == 0) - QueuePacket(GameMessagePacket.BuildPacket(Server.GetWorldManager().GetActor().actorId, textIdOwner.actorId, textId, displayId, log)); - else - QueuePacket(GameMessagePacket.BuildPacket(Server.GetWorldManager().GetActor().actorId, textIdOwner.actorId, textId, displayId, log, LuaUtils.CreateLuaParamList(msgParams))); - } - - public void BroadcastWorldMessage(ushort worldMasterId, params object[] msgParams) - { - //SubPacket worldMasterMessage = - //zone.BroadcastPacketAroundActor(this, worldMasterMessage); - } - - public void GraphicChange(uint slot, uint graphicId) - { - appearanceIds[slot] = graphicId; - } - - public void GraphicChange(uint slot, uint weapId, uint equipId, uint variantId, uint colorId) - { - - uint mixedVariantId; - - if (weapId == 0) - mixedVariantId = ((variantId & 0x1F) << 5) | colorId; - else - mixedVariantId = variantId; - - uint graphicId = - (weapId & 0x3FF) << 20 | - (equipId & 0x3FF) << 10 | - (mixedVariantId & 0x3FF); - - appearanceIds[slot] = graphicId; - - } - - public void SendAppearance() - { - BroadcastPacket(CreateAppearancePacket(), true); - } - - public void SendCharaExpInfo() - { - if (lastStep == 0) - { - int maxLength; - if ((sizeof(short) * charaWork.battleSave.skillLevel.Length)-lastPosition < 0x5E) - maxLength = (sizeof(short) * charaWork.battleSave.skillLevel.Length) - lastPosition; - else - maxLength = 0x5E; - - byte[] skillLevelBuffer = new byte[maxLength]; - Buffer.BlockCopy(charaWork.battleSave.skillLevel, 0, skillLevelBuffer, 0, skillLevelBuffer.Length); - SetActorPropetyPacket charaInfo1 = new SetActorPropetyPacket("charaWork/exp"); - - charaInfo1.SetIsArrayMode(true); - if (maxLength == 0x5E) - { - charaInfo1.AddBuffer(Utils.MurmurHash2("charaWork.battleSave.skillLevel", 0), skillLevelBuffer, 0, skillLevelBuffer.Length, 0x0); - lastPosition += maxLength; - } - else - { - charaInfo1.AddBuffer(Utils.MurmurHash2("charaWork.battleSave.skillLevel", 0), skillLevelBuffer, 0, skillLevelBuffer.Length, 0x3); - lastPosition = 0; - lastStep++; - } - - charaInfo1.AddTarget(); - - QueuePacket(charaInfo1.BuildPacket(actorId)); - } - else if (lastStep == 1) - { - int maxLength; - if ((sizeof(short) * charaWork.battleSave.skillLevelCap.Length) - lastPosition < 0x5E) - maxLength = (sizeof(short) * charaWork.battleSave.skillLevelCap.Length) - lastPosition; - else - maxLength = 0x5E; - - byte[] skillCapBuffer = new byte[maxLength]; - Buffer.BlockCopy(charaWork.battleSave.skillLevelCap, lastPosition, skillCapBuffer, 0, skillCapBuffer.Length); - SetActorPropetyPacket charaInfo1 = new SetActorPropetyPacket("charaWork/exp"); - - - if (maxLength == 0x5E) - { - charaInfo1.SetIsArrayMode(true); - charaInfo1.AddBuffer(Utils.MurmurHash2("charaWork.battleSave.skillLevelCap", 0), skillCapBuffer, 0, skillCapBuffer.Length, 0x1); - lastPosition += maxLength; - } - else - { - charaInfo1.SetIsArrayMode(false); - charaInfo1.AddBuffer(Utils.MurmurHash2("charaWork.battleSave.skillLevelCap", 0), skillCapBuffer, 0, skillCapBuffer.Length, 0x3); - lastStep = 0; - lastPosition = 0; - } - - charaInfo1.AddTarget(); - - QueuePacket(charaInfo1.BuildPacket(actorId)); - } - - } - - public int GetHighestLevel() - { - int max = 0; - foreach (short level in charaWork.battleSave.skillLevel) - { - if (level > max) - max = level; - } - return max; - } - - public InventoryItem[] GetGearset(ushort classId) - { - return Database.GetEquipment(this, classId); - } - - public void PrepareClassChange(byte classId) - { - SendCharaExpInfo(); - } - - public void DoClassChange(byte classId) - { - //load hotbars - //Calculate stats - //Calculate hp/mp - - //Get Potenciel ?????? - - //Set HP/MP/TP PARAMS - - //Set mainskill and level - - //Set Parameters - - //Set current EXP - - //Set Hotbar Commands 1 - //Set Hotbar Commands 2 - //Set Hotbar Commands 3 - - //Check if bonus point available... set - - //Remove buffs that fall off when changing class - CommandResultContainer resultContainer = new CommandResultContainer(); - statusEffects.RemoveStatusEffectsByFlags((uint)StatusEffectFlags.LoseOnClassChange, resultContainer); - resultContainer.CombineLists(); - DoBattleAction(0, 0x7c000062, resultContainer.GetList()); - - //If new class, init abilties and level - if (charaWork.battleSave.skillLevel[classId - 1] <= 0) - { - UpdateClassLevel(classId, 1); - EquipAbilitiesAtLevel(classId, 1); - } - - //Set rested EXP - charaWork.parameterSave.state_mainSkill[0] = classId; - charaWork.parameterSave.state_mainSkillLevel = charaWork.battleSave.skillLevel[classId-1]; - playerWork.restBonusExpRate = 0.0f; - for(int i = charaWork.commandBorder; i < charaWork.command.Length; i++) - { - charaWork.command[i] = 0; - charaWork.commandCategory[i] = 0; - } - - //If new class, init abilties and level - if (charaWork.battleSave.skillLevel[classId - 1] <= 0) - { - UpdateClassLevel(classId, 1); - EquipAbilitiesAtLevel(classId, 1); - } - - ActorPropertyPacketUtil propertyBuilder = new ActorPropertyPacketUtil("charaWork/stateForAll", this); - - propertyBuilder.AddProperty("charaWork.parameterSave.state_mainSkill[0]"); - propertyBuilder.AddProperty("charaWork.parameterSave.state_mainSkillLevel"); - propertyBuilder.NewTarget("playerWork/expBonus"); - propertyBuilder.AddProperty("playerWork.restBonusExpRate"); - propertyBuilder.NewTarget("charaWork/battleStateForSelf"); - propertyBuilder.AddProperty(String.Format("charaWork.battleSave.skillPoint[{0}]", classId - 1)); - Database.LoadHotbar(this); - - var time = Utils.UnixTimeStampUTC(); - for(int i = charaWork.commandBorder; i < charaWork.command.Length; i++) - { - if(charaWork.command[i] != 0) - { - charaWork.parameterSave.commandSlot_recastTime[i - charaWork.commandBorder] = time + charaWork.parameterTemp.maxCommandRecastTime[i - charaWork.commandBorder]; - } - } - - UpdateHotbar(); - - List packets = propertyBuilder.Done(); - - foreach (SubPacket packet in packets) - BroadcastPacket(packet, true); - - Database.SavePlayerCurrentClass(this); - RecalculateStats(); - } - - public void UpdateClassLevel(byte classId, short level) - { - Database.PlayerCharacterUpdateClassLevel(this, classId, level); - charaWork.battleSave.skillLevel[classId - 1] = level; - ActorPropertyPacketUtil propertyBuilder = new ActorPropertyPacketUtil("charaWork/stateForAll", this); - propertyBuilder.AddProperty(String.Format("charaWork.battleSave.skillLevel[{0}]", classId-1)); - List packets = propertyBuilder.Done(); - QueuePackets(packets); - } - - public void GraphicChange(int slot, InventoryItem invItem) - { - if (invItem == null) - appearanceIds[slot] = 0; - else - { - ItemData item = Server.GetItemGamedata(invItem.itemId); - - if (item is EquipmentItem) - { - EquipmentItem eqItem = (EquipmentItem)item; - - uint mixedVariantId; - - if (eqItem.graphicsWeaponId == 0) - mixedVariantId = ((eqItem.graphicsVariantId & 0x1F) << 5) | eqItem.graphicsColorId; - else - mixedVariantId = eqItem.graphicsVariantId; - - uint graphicId = - (eqItem.graphicsWeaponId & 0x3FF) << 20 | - (eqItem.graphicsEquipmentId & 0x3FF) << 10 | - (mixedVariantId & 0x3FF); - - appearanceIds[slot] = graphicId; - } - - //Handle offhand - if (slot == MAINHAND && item is WeaponItem) - { - WeaponItem wpItem = (WeaponItem)item; - - uint graphicId = - (wpItem.graphicsOffhandWeaponId & 0x3FF) << 20 | - (wpItem.graphicsOffhandEquipmentId & 0x3FF) << 10 | - (wpItem.graphicsOffhandVariantId & 0x3FF); - - appearanceIds[SetActorAppearancePacket.OFFHAND] = graphicId; - } - } - - Database.SavePlayerAppearance(this); - BroadcastPacket(CreateAppearancePacket(), true); - } - - public void SetRepairRequest(byte type) - { - charaWork.eventSave.repairType = type; - ActorPropertyPacketUtil propPacketUtil = new ActorPropertyPacketUtil("charaWork/bazaar", this); - propPacketUtil.AddProperty("charaWork.eventSave.repairType"); - QueuePackets(propPacketUtil.Done()); - } - - public void CheckBazaarFlags(bool noUpdate = false) - { - bool isDealing = false, isRepairing = false, seekingItem = false; - lock (GetItemPackage(ItemPackage.BAZAAR)) - { - foreach (InventoryItem item in GetItemPackage(ItemPackage.BAZAAR).GetRawList()) - { - if (item == null) - break; - - if (item.GetBazaarMode() == InventoryItem.MODE_SELL_SINGLE || item.GetBazaarMode() == InventoryItem.MODE_SELL_PSTACK || item.GetBazaarMode() == InventoryItem.MODE_SELL_FSTACK) - isDealing = true; - if (item.GetBazaarMode() == InventoryItem.MODE_SEEK_REPAIR) - isRepairing = true; - if (item.GetBazaarMode() == InventoryItem.MODE_SEEK_ITEM) - isDealing = true; - - if (isDealing && isRepairing && seekingItem) - break; - } - } - - bool doUpdate = false; - - ActorPropertyPacketUtil propPacketUtil = new ActorPropertyPacketUtil("charaWork/bazaar", this); - if (charaWork.eventTemp.bazaarRetail != isDealing) - { - charaWork.eventTemp.bazaarRetail = isDealing; - propPacketUtil.AddProperty("charaWork.eventTemp.bazaarRetail"); - doUpdate = true; - } - - if (charaWork.eventTemp.bazaarRepair != isRepairing) - { - charaWork.eventTemp.bazaarRepair = isRepairing; - propPacketUtil.AddProperty("charaWork.eventTemp.bazaarRepair"); - doUpdate = true; - } - - if (charaWork.eventTemp.bazaarMateria != (GetItemPackage(ItemPackage.MELDREQUEST).GetCount() != 0)) - { - charaWork.eventTemp.bazaarMateria = GetItemPackage(ItemPackage.MELDREQUEST).GetCount() != 0; - propPacketUtil.AddProperty("charaWork.eventTemp.bazaarMateria"); - doUpdate = true; - } - - if (!noUpdate && doUpdate) - BroadcastPackets(propPacketUtil.Done(), true); - } - - public int GetCurrentGil() - { - if (HasItem(1000001)) - return GetItemPackage(ItemPackage.CURRENCY_CRYSTALS).GetItemByCatelogId(1000001).quantity; - else - return 0; - } - - public Actor GetActorInInstance(uint actorId) - { - foreach (Actor a in playerSession.actorInstanceList) - { - if (a.actorId == actorId) - return a; - } - - return null; - } - - public void SetZoneChanging(bool flag) - { - isZoneChanging = flag; - } - - public bool IsInZoneChange() - { - return isZoneChanging; - } - - public ReferencedItemPackage GetEquipment() - { - return equipment; - } - - public byte GetInitialTown() - { - return playerWork.initialTown; - } - - public uint GetHomePoint() - { - return homepoint; - } - - public byte GetHomePointInn() - { - return homepointInn; - } - - public void SetHomePoint(uint aetheryteId) - { - homepoint = aetheryteId; - Database.SavePlayerHomePoints(this); - } - - public void SetHomePointInn(byte townId) - { - homepointInn = townId; - Database.SavePlayerHomePoints(this); - } - - public bool HasAetheryteNodeUnlocked(uint aetheryteId) - { - if (aetheryteId != 0) - return true; - else - return false; - } - - public int GetFreeQuestSlot() - { - for (int i = 0; i < questScenario.Length; i++) - { - if (questScenario[i] == null) - return i; - } - - return -1; - } - - public int GetFreeGuildleveSlot() - { - for (int i = 0; i < work.guildleveId.Length; i++) - { - if (work.guildleveId[i] == 0) - return i; - } - - return -1; - } - - //For Lua calls, cause MoonSharp goes retard with uint - public void AddQuest(int id, bool isSilent = false) - { - AddQuest((uint)id, isSilent); - } - public void CompleteQuest(int id) - { - CompleteQuest((uint)id); - } - public bool HasQuest(int id) - { - return HasQuest((uint)id); - } - public Quest GetQuest(int id) - { - return GetQuest((uint)id); - } - public bool IsQuestCompleted(int id) - { - return IsQuestCompleted((uint)id); - } - public bool CanAcceptQuest(int id) - { - return CanAcceptQuest((uint)id); - } - //For Lua calls, cause MoonSharp goes retard with uint - - public void AddGuildleve(uint id) - { - int freeSlot = GetFreeGuildleveSlot(); - - if (freeSlot == -1) - return; - - work.guildleveId[freeSlot] = (ushort)id; - Database.SaveGuildleve(this, id, freeSlot); - SendGuildleveClientUpdate(freeSlot); - } - - public void MarkGuildleve(uint id, bool abandoned, bool completed) - { - if (HasGuildleve(id)) - { - for (int i = 0; i < work.guildleveId.Length; i++) - { - if (work.guildleveId[i] == id) - { - work.guildleveChecked[i] = completed; - work.guildleveDone[i] = abandoned; - Database.MarkGuildleve(this, id, abandoned, completed); - SendGuildleveMarkClientUpdate(i); - } - } - } - } - - public void RemoveGuildleve(uint id) - { - if (HasGuildleve(id)) - { - for (int i = 0; i < work.guildleveId.Length; i++) - { - if (work.guildleveId[i] == id) - { - Database.RemoveGuildleve(this, id); - work.guildleveId[i] = 0; - SendGuildleveClientUpdate(i); - break; - } - } - } - } - - public void AddQuest(uint id, bool isSilent = false) - { - Actor actor = Server.GetStaticActors((0xA0F00000 | id)); - AddQuest(actor.actorName, isSilent); - } - - public void AddQuest(string name, bool isSilent = false) - { - Actor actor = Server.GetStaticActors(name); - - if (actor == null) - return; - - uint id = actor.actorId; - - int freeSlot = GetFreeQuestSlot(); - - if (freeSlot == -1) - return; - - playerWork.questScenario[freeSlot] = id; - questScenario[freeSlot] = new Quest(this, playerWork.questScenario[freeSlot], name, null, 0, 0); - Database.SaveQuest(this, questScenario[freeSlot]); - SendQuestClientUpdate(freeSlot); - - if (!isSilent) - { - SendGameMessage(Server.GetWorldManager().GetActor(), 25224, 0x20, (object)questScenario[freeSlot].GetQuestId()); - questScenario[freeSlot].NextPhase(0); - } - } - - public void CompleteQuest(uint id) - { - Actor actor = Server.GetStaticActors((0xA0F00000 | id)); - CompleteQuest(actor.actorName); - } - - public void CompleteQuest(string name) - { - Actor actor = Server.GetStaticActors(name); - - if (actor == null) - return; - - uint id = actor.actorId; - if (HasQuest(id)) - { - Database.CompleteQuest(playerSession.GetActor(), id); - SendGameMessage(Server.GetWorldManager().GetActor(), 25086, 0x20, (object)GetQuest(id).GetQuestId()); - RemoveQuest(id); - } - } - - //TODO: Add checks for you being in an instance or main scenario - public void AbandonQuest(uint id) - { - Quest quest = GetQuest(id); - RemoveQuestByQuestId(id); - quest.DoAbandon(); - } - - public void RemoveQuestByQuestId(uint id) - { - RemoveQuest((0xA0F00000 | id)); - } - - public void RemoveQuest(uint id) - { - if (HasQuest(id)) - { - for (int i = 0; i < questScenario.Length; i++) - { - if (questScenario[i] != null && questScenario[i].actorId == id) - { - Database.RemoveQuest(this, questScenario[i].actorId); - questScenario[i] = null; - playerWork.questScenario[i] = 0; - SendQuestClientUpdate(i); - break; - } - } - } - } - - public void ReplaceQuest(uint oldId, uint newId) - { - if (HasQuest(oldId)) - { - for (int i = 0; i < questScenario.Length; i++) - { - if (questScenario[i] != null && questScenario[i].GetQuestId() == oldId) - { - Actor actor = Server.GetStaticActors((0xA0F00000 | newId)); - playerWork.questScenario[i] = (0xA0F00000 | newId); - questScenario[i] = new Quest(this, playerWork.questScenario[i], actor.actorName, null, 0, 0); - Database.SaveQuest(this, questScenario[i]); - SendQuestClientUpdate(i); - break; - } - } - } - } - - public bool CanAcceptQuest(string name) - { - if (!IsQuestCompleted(name) && !HasQuest(name)) - return true; - else - return false; - } - - public bool CanAcceptQuest(uint id) - { - Actor actor = Server.GetStaticActors((0xA0F00000 | id)); - return CanAcceptQuest(actor.actorName); - } - - public bool IsQuestCompleted(string questName) - { - Actor actor = Server.GetStaticActors(questName); - return IsQuestCompleted(actor.actorId); - } - - public bool IsQuestCompleted(uint questId) - { - return Database.IsQuestCompleted(this, 0xFFFFF & questId); - } - - public Quest GetQuest(uint id) - { - for (int i = 0; i < questScenario.Length; i++) - { - if (questScenario[i] != null && questScenario[i].actorId == (0xA0F00000 | id)) - return questScenario[i]; - } - - return null; - } - - public Quest GetQuest(string name) - { - for (int i = 0; i < questScenario.Length; i++) - { - if (questScenario[i] != null && questScenario[i].actorName.ToLower().Equals(name.ToLower())) - return questScenario[i]; - } - - return null; - } - - public bool HasQuest(string name) - { - for (int i = 0; i < questScenario.Length; i++) - { - if (questScenario[i] != null && questScenario[i].actorName.ToLower().Equals(name.ToLower())) - return true; - } - - return false; - } - - public bool HasQuest(uint id) - { - for (int i = 0; i < questScenario.Length; i++) - { - if (questScenario[i] != null && questScenario[i].actorId == (0xA0F00000 | id)) - return true; - } - - return false; - } - - public bool HasGuildleve(uint id) - { - for (int i = 0; i < work.guildleveId.Length; i++) - { - if (work.guildleveId[i] == id) - return true; - } - - return false; - } - - public int GetQuestSlot(uint id) - { - for (int i = 0; i < questScenario.Length; i++) - { - if (questScenario[i] != null && questScenario[i].actorId == (0xA0F00000 | id)) - return i; - } - - return -1; - } - - public void SetNpcLS(uint npcLSId, uint state) - { - bool isCalling, isExtra; - isCalling = isExtra = false; - - switch (state) - { - case NPCLS_INACTIVE: - - if (playerWork.npcLinkshellChatExtra[npcLSId] == true && playerWork.npcLinkshellChatCalling[npcLSId] == false) - return; - - isExtra = true; - break; - case NPCLS_ACTIVE: - - if (playerWork.npcLinkshellChatExtra[npcLSId] == false && playerWork.npcLinkshellChatCalling[npcLSId] == true) - return; - - isCalling = true; - break; - case NPCLS_ALERT: - - if (playerWork.npcLinkshellChatExtra[npcLSId] == true && playerWork.npcLinkshellChatCalling[npcLSId] == true) - return; - - isExtra = isCalling = true; - break; - } - - playerWork.npcLinkshellChatExtra[npcLSId] = isExtra; - playerWork.npcLinkshellChatCalling[npcLSId] = isCalling; - - Database.SaveNpcLS(this, npcLSId, isCalling, isExtra); - - ActorPropertyPacketUtil propPacketUtil = new ActorPropertyPacketUtil("playerWork/npcLinkshellChat", this); - propPacketUtil.AddProperty(String.Format("playerWork.npcLinkshellChatExtra[{0}]", npcLSId)); - propPacketUtil.AddProperty(String.Format("playerWork.npcLinkshellChatCalling[{0}]", npcLSId)); - QueuePackets(propPacketUtil.Done()); - } - - private void SendQuestClientUpdate(int slot) - { - ActorPropertyPacketUtil propPacketUtil = new ActorPropertyPacketUtil("playerWork/journal", this); - propPacketUtil.AddProperty(String.Format("playerWork.questScenario[{0}]", slot)); - QueuePackets(propPacketUtil.Done()); - } - - private void SendGuildleveClientUpdate(int slot) - { - ActorPropertyPacketUtil propPacketUtil = new ActorPropertyPacketUtil("work/guildleve", this); - propPacketUtil.AddProperty(String.Format("work.guildleveId[{0}]", slot)); - QueuePackets(propPacketUtil.Done()); - } - - private void SendGuildleveMarkClientUpdate(int slot) - { - ActorPropertyPacketUtil propPacketUtil = new ActorPropertyPacketUtil("work/guildleve", this); - propPacketUtil.AddProperty(String.Format("work.guildleveDone[{0}]", slot)); - propPacketUtil.AddProperty(String.Format("work.guildleveChecked[{0}]", slot)); - QueuePackets(propPacketUtil.Done()); - } - - public void SendStartCastbar(uint commandId, uint endTime) - { - playerWork.castCommandClient = commandId; - playerWork.castEndClient = endTime; - ActorPropertyPacketUtil propPacketUtil = new ActorPropertyPacketUtil("playerWork/castState", this); - propPacketUtil.AddProperty("playerWork.castEndClient"); - propPacketUtil.AddProperty("playerWork.castCommandClient"); - QueuePackets(propPacketUtil.Done()); - } - - public void SendEndCastbar() - { - playerWork.castCommandClient = 0; - playerWork.castEndClient = 0; - ActorPropertyPacketUtil propPacketUtil = new ActorPropertyPacketUtil("playerWork/castState", this); - propPacketUtil.AddProperty("playerWork.castCommandClient"); - QueuePackets(propPacketUtil.Done()); - } - - public void SetLoginDirector(Director director) - { - if (ownedDirectors.Contains(director)) - loginInitDirector = director; - } - - public void AddDirector(Director director, bool spawnImmediatly = false) - { - if (!ownedDirectors.Contains(director)) - { - ownedDirectors.Add(director); - director.AddMember(this); - } - } - - public void SendDirectorPackets(Director director) - { - QueuePackets(director.GetSpawnPackets()); - QueuePackets(director.GetInitPackets()); - } - - public void RemoveDirector(Director director) - { - if (ownedDirectors.Contains(director)) - { - QueuePacket(RemoveActorPacket.BuildPacket(director.actorId)); - ownedDirectors.Remove(director); - director.RemoveMember(this); - } - } - - public GuildleveDirector GetGuildleveDirector() - { - foreach (Director d in ownedDirectors) - { - if (d is GuildleveDirector) - return (GuildleveDirector)d; - } - - return null; - } - - public Director GetDirector(string directorName) - { - foreach (Director d in ownedDirectors) - { - if (d.GetScriptPath().Equals(directorName)) - return d; - } - - return null; - } - - public Director GetDirector(uint id) - { - foreach (Director d in ownedDirectors) - { - if (d.actorId == id) - return d; - } - - return null; - } - - public void ExaminePlayer(Actor examinee) - { - Player toBeExamined; - if (examinee is Player) - toBeExamined = (Player)examinee; - else - return; - - QueuePacket(InventoryBeginChangePacket.BuildPacket(toBeExamined.actorId, true)); - toBeExamined.GetEquipment().SendUpdateAsItemPackage(this, ItemPackage.MAXSIZE_EQUIPMENT_OTHERPLAYER, ItemPackage.EQUIPMENT_OTHERPLAYER); - QueuePacket(InventoryEndChangePacket.BuildPacket(toBeExamined.actorId)); - } - - public void SendDataPacket(params object[] parameters) - { - List lParams = LuaUtils.CreateLuaParamList(parameters); - SubPacket spacket = GenericDataPacket.BuildPacket(actorId, lParams); - spacket.DebugPrintSubPacket(); - QueuePacket(spacket); - } - - public void StartEvent(Actor owner, EventStartPacket start) - { - currentEventOwner = start.scriptOwnerActorID; - currentEventName = start.triggerName; - LuaEngine.GetInstance().EventStarted(this, owner, start); - } - - public void UpdateEvent(EventUpdatePacket update) - { - LuaEngine.GetInstance().OnEventUpdate(this, update.luaParams); - } - - public void KickEvent(Actor actor, string conditionName, params object[] parameters) - { - if (actor == null) - return; - - List lParams = LuaUtils.CreateLuaParamList(parameters); - SubPacket spacket = KickEventPacket.BuildPacket(actorId, actor.actorId, 0x75dc1705, conditionName, lParams); - spacket.DebugPrintSubPacket(); - QueuePacket(spacket); - } - - public void KickEventSpecial(Actor actor, uint unknown, string conditionName, params object[] parameters) - { - if (actor == null) - return; - - List lParams = LuaUtils.CreateLuaParamList(parameters); - SubPacket spacket = KickEventPacket.BuildPacket(actorId, actor.actorId, unknown, conditionName, lParams); - spacket.DebugPrintSubPacket(); - QueuePacket(spacket); - } - - public void SetEventStatus(Actor actor, string conditionName, bool enabled, byte unknown) - { - QueuePacket(packets.send.actor.events.SetEventStatus.BuildPacket(actor.actorId, enabled, unknown, conditionName)); - } - - public void RunEventFunction(string functionName, params object[] parameters) - { - List lParams = LuaUtils.CreateLuaParamList(parameters); - SubPacket spacket = RunEventFunctionPacket.BuildPacket(actorId, currentEventOwner, currentEventName, functionName, lParams); - spacket.DebugPrintSubPacket(); - QueuePacket(spacket); - } - - public void EndEvent() - { - SubPacket p = EndEventPacket.BuildPacket(actorId, currentEventOwner, currentEventName); - p.DebugPrintSubPacket(); - QueuePacket(p); - - currentEventOwner = 0; - currentEventName = ""; - currentEventRunning = null; - } - - public void BroadcastCountdown(byte countdownLength, ulong syncTime) - { - BroadcastPacket(StartCountdownPacket.BuildPacket(actorId, countdownLength, syncTime, "Go!"), true); - } - - public void SendInstanceUpdate() - { - //Server.GetWorldManager().SeamlessCheck(this); - - //Update Instance - List aroundMe = new List(); - - if (zone != null) - aroundMe.AddRange(zone.GetActorsAroundActor(this, 50)); - if (zone2 != null) - aroundMe.AddRange(zone2.GetActorsAroundActor(this, 50)); - playerSession.UpdateInstance(aroundMe); - } - - public bool IsInParty() - { - return currentParty != null; - } - - public bool IsPartyLeader() - { - if (IsInParty()) - { - Party party = (Party)currentParty; - return party.GetLeader() == actorId; - } - else - return false; - } - - public void PartyOustPlayer(uint actorId) - { - SubPacket oustPacket = PartyModifyPacket.BuildPacket(playerSession, 1, actorId); - QueuePacket(oustPacket); - } - - public void PartyOustPlayer(string name) - { - SubPacket oustPacket = PartyModifyPacket.BuildPacket(playerSession, 1, name); - QueuePacket(oustPacket); - } - - public void PartyLeave() - { - SubPacket leavePacket = PartyLeavePacket.BuildPacket(playerSession, false); - QueuePacket(leavePacket); - } - - public void PartyDisband() - { - SubPacket disbandPacket = PartyLeavePacket.BuildPacket(playerSession, true); - QueuePacket(disbandPacket); - } - - public void PartyPromote(uint actorId) - { - SubPacket promotePacket = PartyModifyPacket.BuildPacket(playerSession, 0, actorId); - QueuePacket(promotePacket); - } - - public void PartyPromote(string name) - { - SubPacket promotePacket = PartyModifyPacket.BuildPacket(playerSession, 0, name); - QueuePacket(promotePacket); - } - - //A party member list packet came, set the party - public void SetParty(Party group) - { - if (group is Party && currentParty != group) - { - RemoveFromCurrentPartyAndCleanup(); - currentParty = group; - } - } - - //Removes the player from the party and cleans it up if needed - public void RemoveFromCurrentPartyAndCleanup() - { - if (currentParty == null) - return; - - Party partyGroup = (Party) currentParty; - - for (int i = 0; i < partyGroup.members.Count; i++) - { - if (partyGroup.members[i] == actorId) - { - partyGroup.members.RemoveAt(i); - break; - } - } - - //currentParty.members.Remove(this); - if (partyGroup.members.Count == 0) - Server.GetWorldManager().NoMembersInParty((Party)currentParty); - - currentParty = null; - } - - public void IssueChocobo(byte appearanceId, string nameResponse) - { - Database.IssuePlayerChocobo(this, appearanceId, nameResponse); - hasChocobo = true; - chocoboAppearance = appearanceId; - chocoboName = nameResponse; - } - - public void ChangeChocoboAppearance(byte appearanceId) - { - Database.ChangePlayerChocoboAppearance(this, appearanceId); - chocoboAppearance = appearanceId; - } - - public void StartChocoboRental(byte numMins) - { - rentalExpireTime = Utils.UnixTimeStampUTC() + ((uint)numMins * 60); - rentalMinLeft = numMins; - } - - public bool IsChocoboRentalActive() - { - return rentalExpireTime != 0; - } - - public Retainer SpawnMyRetainer(Npc bell, int retainerIndex) - { - Retainer retainer = Database.LoadRetainer(this, retainerIndex); - - float distance = (float)Math.Sqrt(((positionX - bell.positionX) * (positionX - bell.positionX)) + ((positionZ - bell.positionZ) * (positionZ - bell.positionZ))); - float posX = bell.positionX - ((-1.0f * (bell.positionX - positionX)) / distance); - float posZ = bell.positionZ - ((-1.0f * (bell.positionZ - positionZ)) / distance); - - retainer.positionX = posX; - retainer.positionY = positionY; - retainer.positionZ = posZ; - retainer.rotation = (float)Math.Atan2(positionX - posX, positionZ - posZ); - - retainerMeetingGroup = new RetainerMeetingRelationGroup(5555, this, retainer); - retainerMeetingGroup.SendGroupPackets(playerSession); - - currentSpawnedRetainer = retainer; - sentRetainerSpawn = false; - - return retainer; - } - - public void DespawnMyRetainer() - { - if (currentSpawnedRetainer != null) - { - currentSpawnedRetainer = null; - retainerMeetingGroup.SendDeletePacket(playerSession); - retainerMeetingGroup = null; - } - } - - public override void Update(DateTime tick) - { - - // Chocobo Rental Expirey - if (rentalExpireTime != 0) - { - uint tickUTC = Utils.UnixTimeStampUTC(tick); - - //Rental has expired, dismount - if (rentalExpireTime <= tickUTC) - { - rentalExpireTime = 0; - rentalMinLeft = 0; - ChangeMusic(GetZone().bgmDay); - SetMountState(0); - ChangeSpeed(0.0f, 2.0f, 5.0f, 5.0f); - ChangeState(0); - } - else - { - rentalMinLeft = (byte) ((rentalExpireTime - tickUTC) /60); - } - } - - aiContainer.Update(tick); - statusEffects.Update(tick); - } - - public override void PostUpdate(DateTime tick, List packets = null) - { - // todo: is this correct? - if (this.playerSession.isUpdatesLocked) - return; - - // todo: should probably add another flag for battleTemp since all this uses reflection - packets = new List(); - - // we only want the latest update for the player - if ((updateFlags & ActorUpdateFlags.Position) != 0) - { - if (positionUpdates.Count > 1) - positionUpdates.RemoveRange(1, positionUpdates.Count - 1); - } - - if ((updateFlags & ActorUpdateFlags.HpTpMp) != 0) - { - var propPacketUtil = new ActorPropertyPacketUtil("charaWork/stateAtQuicklyForAll", this); - - // todo: should this be using job as index? - propPacketUtil.AddProperty("charaWork.parameterSave.hp[0]"); - propPacketUtil.AddProperty("charaWork.parameterSave.hpMax[0]"); - propPacketUtil.AddProperty("charaWork.parameterSave.state_mainSkill[0]"); - propPacketUtil.AddProperty("charaWork.parameterSave.state_mainSkillLevel"); - - packets.AddRange(propPacketUtil.Done()); - } - - - if ((updateFlags & ActorUpdateFlags.Stats) != 0) - { - var propPacketUtil = new ActorPropertyPacketUtil("charaWork/battleParameter", this); - - for (uint i = 0; i < 35; i++) - { - if (GetMod(i) != charaWork.battleTemp.generalParameter[i]) - { - charaWork.battleTemp.generalParameter[i] = (short)GetMod(i); - propPacketUtil.AddProperty(String.Format("charaWork.battleTemp.generalParameter[{0}]", i)); - } - } - - QueuePackets(propPacketUtil.Done()); - } - - if ((updateFlags & ActorUpdateFlags.Hotbar) != 0) - { - UpdateHotbar(hotbarSlotsToUpdate); - hotbarSlotsToUpdate.Clear(); - - updateFlags ^= ActorUpdateFlags.Hotbar; - } - - base.PostUpdate(tick, packets); - } - - public override void Die(DateTime tick, CommandResultContainer actionContainer = null) - { - // todo: death timer - aiContainer.InternalDie(tick, 60); - } - - //Update commands and recast timers for the entire hotbar - public void UpdateHotbar() - { - for (ushort i = charaWork.commandBorder; i < charaWork.commandBorder + 30; i++) - { - hotbarSlotsToUpdate.Add(i); - } - updateFlags |= ActorUpdateFlags.Hotbar; - } - - //Updates the hotbar and recast timers for only certain hotbar slots - public void UpdateHotbar(List slotsToUpdate) - { - UpdateHotbarCommands(slotsToUpdate); - UpdateRecastTimers(slotsToUpdate); - } - - //Update command ids for the passed in hotbar slots - public void UpdateHotbarCommands(List slotsToUpdate) - { - ActorPropertyPacketUtil propPacketUtil = new ActorPropertyPacketUtil("charaWork/command", this); - foreach (ushort slot in slotsToUpdate) - { - propPacketUtil.AddProperty(String.Format("charaWork.command[{0}]", slot)); - propPacketUtil.AddProperty(String.Format("charaWork.commandCategory[{0}]", slot)); - } - - propPacketUtil.NewTarget("charaWork/commandDetailForSelf"); - //Enable or disable slots based on whether there is an ability in that slot - foreach (ushort slot in slotsToUpdate) - { - charaWork.parameterSave.commandSlot_compatibility[slot - charaWork.commandBorder] = charaWork.command[slot] != 0; - propPacketUtil.AddProperty(String.Format("charaWork.parameterSave.commandSlot_compatibility[{0}]", slot - charaWork.commandBorder)); - } - - QueuePackets(propPacketUtil.Done()); - //QueuePackets(compatibiltyUtil.Done()); - } - - //Update recast timers for the passed in hotbar slots - public void UpdateRecastTimers(List slotsToUpdate) - { - ActorPropertyPacketUtil recastPacketUtil = new ActorPropertyPacketUtil("charaWork/commandDetailForSelf", this); - - foreach (ushort slot in slotsToUpdate) - { - recastPacketUtil.AddProperty(String.Format("charaWork.parameterTemp.maxCommandRecastTime[{0}]", slot - charaWork.commandBorder)); - recastPacketUtil.AddProperty(String.Format("charaWork.parameterSave.commandSlot_recastTime[{0}]", slot - charaWork.commandBorder)); - } - - QueuePackets(recastPacketUtil.Done()); - } - - //Find the first open slot in classId's hotbar and equip an ability there. - public void EquipAbilityInFirstOpenSlot(byte classId, uint commandId, bool printMessage = true) - { - //Find first open slot on class's hotbar slot, then call EquipAbility with that slot. - ushort hotbarSlot = 0; - - //If the class we're equipping for is the current class, we can just look at charawork.command - if(classId == charaWork.parameterSave.state_mainSkill[0]) - hotbarSlot = FindFirstCommandSlotById(0); - //Otherwise, we need to check the database. - else - hotbarSlot = (ushort) (Database.FindFirstCommandSlot(this, classId) + charaWork.commandBorder); - - EquipAbility(classId, commandId, hotbarSlot, printMessage); - } - - //Add commandId to classId's hotbar at hotbarSlot. - //If classId is not the current class, do it in the database - //hotbarSlot starts at 32 - public void EquipAbility(byte classId, uint commandId, ushort hotbarSlot, bool printMessage = true) - { - var ability = Server.GetWorldManager().GetBattleCommand(commandId); - uint trueCommandId = 0xA0F00000 | commandId; - ushort lowHotbarSlot = (ushort)(hotbarSlot - charaWork.commandBorder); - ushort maxRecastTime = (ushort)(ability != null ? ability.maxRecastTimeSeconds : 5); - uint recastEnd = Utils.UnixTimeStampUTC() + maxRecastTime; - - Database.EquipAbility(this, classId, (ushort) (hotbarSlot - charaWork.commandBorder), commandId, recastEnd); - //If the class we're equipping for is the current class (need to find out if state_mainSkill is supposed to change when you're a job) - //then equip the ability in charawork.commands and save in databse, otherwise just save in database - if (classId == GetCurrentClassOrJob()) - { - charaWork.command[hotbarSlot] = trueCommandId; - charaWork.commandCategory[hotbarSlot] = 1; - charaWork.parameterTemp.maxCommandRecastTime[lowHotbarSlot] = maxRecastTime; - charaWork.parameterSave.commandSlot_recastTime[lowHotbarSlot] = recastEnd; - - hotbarSlotsToUpdate.Add(hotbarSlot); - updateFlags |= ActorUpdateFlags.Hotbar; - } - - - if(printMessage) - SendGameMessage(Server.GetWorldManager().GetActor(), 30603, 0x20, 0, commandId); - } - - //Doesn't take a classId because the only way to swap abilities is through the ability equip widget oe /eaction, which only apply to current class - //hotbarSlot 1 and 2 are 32-indexed. - public void SwapAbilities(ushort hotbarSlot1, ushort hotbarSlot2) - { - //0 indexed hotbar slots for saving to database and recast timers - uint lowHotbarSlot1 = (ushort)(hotbarSlot1 - charaWork.commandBorder); - uint lowHotbarSlot2 = (ushort)(hotbarSlot2 - charaWork.commandBorder); - - //Store information about first command - uint commandId = charaWork.command[hotbarSlot1]; - uint recastEnd = charaWork.parameterSave.commandSlot_recastTime[lowHotbarSlot1]; - ushort recastMax = charaWork.parameterTemp.maxCommandRecastTime[lowHotbarSlot1]; - - //Move second command's info to first hotbar slot - charaWork.command[hotbarSlot1] = charaWork.command[hotbarSlot2]; - charaWork.parameterTemp.maxCommandRecastTime[lowHotbarSlot1] = charaWork.parameterTemp.maxCommandRecastTime[lowHotbarSlot2]; - charaWork.parameterSave.commandSlot_recastTime[lowHotbarSlot1] = charaWork.parameterSave.commandSlot_recastTime[lowHotbarSlot2]; - - //Move first command's info to second slot - charaWork.command[hotbarSlot2] = commandId; - charaWork.parameterTemp.maxCommandRecastTime[lowHotbarSlot2] = recastMax; - charaWork.parameterSave.commandSlot_recastTime[lowHotbarSlot2] = recastEnd; - - //Save changes to both slots - Database.EquipAbility(this, GetCurrentClassOrJob(), (ushort)(lowHotbarSlot1), 0xA0F00000 ^ charaWork.command[hotbarSlot1], charaWork.parameterSave.commandSlot_recastTime[lowHotbarSlot1]); - Database.EquipAbility(this, GetCurrentClassOrJob(), (ushort)(lowHotbarSlot2), 0xA0F00000 ^ charaWork.command[hotbarSlot2], charaWork.parameterSave.commandSlot_recastTime[lowHotbarSlot2]); - - //Update slots on client - hotbarSlotsToUpdate.Add(hotbarSlot1); - hotbarSlotsToUpdate.Add(hotbarSlot2); - updateFlags |= ActorUpdateFlags.Hotbar; - } - - public void UnequipAbility(ushort hotbarSlot, bool printMessage = true) - { - ushort trueHotbarSlot = (ushort)(hotbarSlot + charaWork.commandBorder - 1); - uint commandId = charaWork.command[trueHotbarSlot]; - Database.UnequipAbility(this, hotbarSlot); - charaWork.command[trueHotbarSlot] = 0; - hotbarSlotsToUpdate.Add(trueHotbarSlot); - - if (printMessage && commandId != 0) - SendGameMessage(Server.GetWorldManager().GetActor(), 30604, 0x20, 0, 0xA0F00000 ^ commandId); - - updateFlags |= ActorUpdateFlags.Hotbar; - } - - //Finds the first hotbar slot with a given commandId. - //If the returned value is outside the hotbar, it indicates it wasn't found. - public ushort FindFirstCommandSlotById(uint commandId) - { - if(commandId != 0) - commandId |= 0xA0F00000; - - ushort firstSlot = (ushort)(charaWork.commandBorder + 30); - - for (ushort i = charaWork.commandBorder; i < charaWork.commandBorder + 30; i++) - { - if (charaWork.command[i] == commandId) - { - firstSlot = i; - break; - } - } - - return firstSlot; - } - - private void UpdateHotbarTimer(uint commandId, uint recastTimeMs) - { - ushort slot = FindFirstCommandSlotById(commandId); - charaWork.parameterSave.commandSlot_recastTime[slot - charaWork.commandBorder] = Utils.UnixTimeStampUTC(DateTime.Now.AddMilliseconds(recastTimeMs)); - var slots = new List(); - slots.Add(slot); - UpdateRecastTimers(slots); - } - - private uint GetHotbarTimer(uint commandId) - { - ushort slot = FindFirstCommandSlotById(commandId); - return charaWork.parameterSave.commandSlot_recastTime[slot - charaWork.commandBorder]; - } - - public override void Cast(uint spellId, uint targetId = 0) - { - if (aiContainer.CanChangeState()) - aiContainer.Cast(zone.FindActorInArea(targetId == 0 ? currentTarget : targetId), spellId); - else if (aiContainer.IsCurrentState()) - // You are already casting. - SendGameMessage(Server.GetWorldManager().GetActor(), 32536, 0x20); - else - // Please wait a moment and try again. - SendGameMessage(Server.GetWorldManager().GetActor(), 32535, 0x20); - } - - public override void Ability(uint abilityId, uint targetId = 0) - { - if (aiContainer.CanChangeState()) - aiContainer.Ability(zone.FindActorInArea(targetId == 0 ? currentTarget : targetId), abilityId); - else - // Please wait a moment and try again. - SendGameMessage(Server.GetWorldManager().GetActor(), 32535, 0x20); - } - - public override void WeaponSkill(uint skillId, uint targetId = 0) - { - if (aiContainer.CanChangeState()) - aiContainer.WeaponSkill(zone.FindActorInArea(targetId == 0 ? currentTarget : targetId), skillId); - else - // Please wait a moment and try again. - SendGameMessage(Server.GetWorldManager().GetActor(), 32535, 0x20); - } - - public override bool IsValidTarget(Character target, ValidTarget validTarget) - { - if (target == null) - { - // Target does not exist. - SendGameMessage(Server.GetWorldManager().GetActor(), 32511, 0x20); - return false; - } - - if (target.isMovingToSpawn) - { - // That command cannot be performed on the current target. - SendGameMessage(Server.GetWorldManager().GetActor(), 32547, 0x20); - return false; - } - - // enemy only - if ((validTarget & ValidTarget.Enemy) != 0) - { - // todo: this seems ambiguous - if (target.isStatic) - { - // That command cannot be performed on the current target. - SendGameMessage(Server.GetWorldManager().GetActor(), 32547, 0x20); - return false; - } - if (currentParty != null && target.currentParty == currentParty) - { - // That command cannot be performed on a party member. - SendGameMessage(Server.GetWorldManager().GetActor(), 32548, 0x20); - return false; - } - // todo: pvp? - if (target.allegiance == allegiance) - { - // That command cannot be performed on an ally. - SendGameMessage(Server.GetWorldManager().GetActor(), 32549, 0x20); - return false; - } - - bool partyEngaged = false; - // todo: replace with confrontation status effect? (see how dsp does it) - if (target.aiContainer.IsEngaged()) - { - if (currentParty != null) - { - if (target is BattleNpc) - { - var helpingActorId = ((BattleNpc)target).GetMobMod((uint)MobModifier.CallForHelp); - partyEngaged = this.actorId == helpingActorId || (((BattleNpc)target).GetMobMod((uint)MobModifier.FreeForAll) != 0); - } - - if (!partyEngaged) - { - foreach (var memberId in ((Party)currentParty).members) - { - if (memberId == target.currentLockedTarget) - { - partyEngaged = true; - break; - } - } - } - } - else if (target.currentLockedTarget == actorId) - { - partyEngaged = true; - } - } - else - { - partyEngaged = true; - } - - if (!partyEngaged) - { - // That target is already engaged. - SendGameMessage(Server.GetWorldManager().GetActor(), 32520, 0x20); - return false; - } - } - - if ((validTarget & ValidTarget.Ally) != 0 && target.allegiance != allegiance) - { - // That command cannot be performed on the current target. - SendGameMessage(Server.GetWorldManager().GetActor(), 32547, 0x20); - return false; - } - - // todo: isStatic seems ambiguous? - if ((validTarget & ValidTarget.NPC) != 0 && target.isStatic) - return true; - - // todo: why is player always zoning? - // cant target if zoning - if (target is Player && ((Player)target).playerSession.isUpdatesLocked) - { - // That command cannot be performed on the current target. - SendGameMessage(Server.GetWorldManager().GetActor(), 32547, 0x20); - return false; - } - - return true; - } - - //Do we need separate functions? they check the same things - public override bool CanUse(Character target, BattleCommand skill, CommandResult error = null) - { - if (!skill.IsValidMainTarget(this, target, error) || !IsValidTarget(target, skill.mainTarget)) - { - // error packet is set in IsValidTarget - return false; - } - - //Might want to do these with a BattleAction instead to be consistent with the rest of command stuff - if (GetHotbarTimer(skill.id) > Utils.UnixTimeStampUTC()) - { - // todo: this needs confirming - // Please wait a moment and try again. - error?.SetTextId(32535); - return false; - } - - if (Utils.XZDistance(positionX, positionZ, target.positionX, target.positionZ) > skill.range) - { - // The target is too far away. - error?.SetTextId(32539); - return false; - } - - if (Utils.XZDistance(positionX, positionZ, target.positionX, target.positionZ) < skill.minRange) - { - // The target is too close. - error?.SetTextId(32538); - return false; - } - - if (target.positionY - positionY > (skill.rangeHeight / 2)) - { - // The target is too far above you. - error?.SetTextId(32540); - return false; - } - - if (positionY - target.positionY > (skill.rangeHeight / 2)) - { - // The target is too far below you. - error?.SetTextId(32541); - return false; - } - - if (skill.CalculateMpCost(this) > GetMP()) - { - // You do not have enough MP. - error?.SetTextId(32545); - return false; - } - - if (skill.CalculateTpCost(this) > GetTP()) - { - // You do not have enough TP. - error?.SetTextId(32546); - return false; - } - - //Proc requirement - if (skill.procRequirement != BattleCommandProcRequirement.None && !charaWork.battleTemp.timingCommandFlag[(int)skill.procRequirement - 1]) - { - //Conditions for use are not met - error?.SetTextId(32556); - return false; - } - - - return true; - } - - public override void OnAttack(State state, CommandResult action, ref CommandResult error) - { - var target = state.GetTarget(); - - base.OnAttack(state, action, ref error); - - // todo: switch based on main weap (also probably move this anim assignment somewhere else) - action.animation = 0x19001000; - if (error == null) - { - // melee attack animation - //action.animation = 0x19001000; - } - if (target is BattleNpc) - { - ((BattleNpc)target).hateContainer.UpdateHate(this, action.enmity); - } - - LuaEngine.GetInstance().OnSignal("playerAttack"); - } - - public override void OnCast(State state, CommandResult[] actions, BattleCommand spell, ref CommandResult[] errors) - { - // todo: update hotbar timers to skill's recast time (also needs to be done on class change or equip crap) - base.OnCast(state, actions, spell, ref errors); - // todo: should just make a thing that updates the one slot cause this is dumb as hell - UpdateHotbarTimer(spell.id, spell.recastTimeMs); - //LuaEngine.GetInstance().OnSignal("spellUse"); - } - - public override void OnWeaponSkill(State state, CommandResult[] actions, BattleCommand skill, ref CommandResult[] errors) - { - // todo: update hotbar timers to skill's recast time (also needs to be done on class change or equip crap) - base.OnWeaponSkill(state, actions, skill, ref errors); - - // todo: should just make a thing that updates the one slot cause this is dumb as hell - UpdateHotbarTimer(skill.id, skill.recastTimeMs); - // todo: this really shouldnt be called on each ws? - lua.LuaEngine.CallLuaBattleFunction(this, "onWeaponSkill", this, state.GetTarget(), skill); - LuaEngine.GetInstance().OnSignal("weaponskillUse"); - } - - public override void OnAbility(State state, CommandResult[] actions, BattleCommand ability, ref CommandResult[] errors) - { - base.OnAbility(state, actions, ability, ref errors); - UpdateHotbarTimer(ability.id, ability.recastTimeMs); - LuaEngine.GetInstance().OnSignal("abilityUse"); - } - - //Handles exp being added, does not handle figuring out exp bonus from buffs or skill/link chains or any of that - //Returns CommandResults that can be sent to display the EXP gained number and level ups - //exp should be a ushort single the exp graphic overflows after ~65k - public List AddExp(int exp, byte classId, byte bonusPercent = 0) - { - List actionList = new List(); - exp += (int) Math.Ceiling((exp * bonusPercent / 100.0f)); - - //You earn [exp] (+[bonusPercent]%) experience points. - //In non-english languages there are unique messages for each language, hence the use of ClassExperienceTextIds - actionList.Add(new CommandResult(actorId, BattleUtils.ClassExperienceTextIds[classId], 0, (ushort)exp, bonusPercent)); - - bool leveled = false; - int diff = MAXEXP[GetLevel() - 1] - charaWork.battleSave.skillPoint[classId - 1]; - //While there is enough experience to level up, keep leveling up, unlocking skills and removing experience from exp until we don't have enough to level up - while (exp >= diff && GetLevel() < charaWork.battleSave.skillLevelCap[classId]) - { - //Level up - LevelUp(classId, actionList); - leveled = true; - //Reduce exp based on how much exp is needed to level - exp -= diff; - diff = MAXEXP[GetLevel() - 1]; - } - - if(leveled) - { - //Set exp to current class to 0 so that exp is added correctly - charaWork.battleSave.skillPoint[classId - 1] = 0; - //send new level - ActorPropertyPacketUtil levelPropertyPacket = new ActorPropertyPacketUtil("charaWork/stateForAll", this); - levelPropertyPacket.AddProperty(String.Format("charaWork.battleSave.skillLevel[{0}]", classId - 1)); - levelPropertyPacket.AddProperty("charaWork.parameterSave.state_mainSkillLevel"); - QueuePackets(levelPropertyPacket.Done()); - - Database.SetLevel(this, classId, GetLevel()); - Database.SavePlayerCurrentClass(this); - } - //Cap experience for level 50 - charaWork.battleSave.skillPoint[classId - 1] = Math.Min(charaWork.battleSave.skillPoint[classId - 1] + exp, MAXEXP[GetLevel() - 1]); - - ActorPropertyPacketUtil expPropertyPacket = new ActorPropertyPacketUtil("charaWork/battleStateForSelf", this); - expPropertyPacket.AddProperty(String.Format("charaWork.battleSave.skillPoint[{0}]", classId - 1)); - - QueuePackets(expPropertyPacket.Done()); - Database.SetExp(this, classId, charaWork.battleSave.skillPoint[classId - 1]); - - return actionList; - } - - //Equips any abilities for the given classId at the given level. If actionList is not null, adds a "You learn Command" message - private void EquipAbilitiesAtLevel(byte classId, short level, List actionList = null) - { - //If there's any abilites that unlocks at this level, equip them. - List commandIds = Server.GetWorldManager().GetBattleCommandIdByLevel(classId, GetLevel()); - foreach (ushort commandId in commandIds) - { - EquipAbilityInFirstOpenSlot(classId, commandId, false); - byte jobId = ConvertClassIdToJobId(classId); - if (jobId != classId) - EquipAbilityInFirstOpenSlot(jobId, commandId, false); - - //33926: You learn [command]. - if (actionList != null) - { - if (classId == GetCurrentClassOrJob() || jobId == GetCurrentClassOrJob()) - actionList.Add(new CommandResult(actorId, 33926, 0, commandId)); - } - } - } - - //Increaess level of current class and equips new abilities earned at that level - public void LevelUp(byte classId, List actionList = null) - { - if (charaWork.battleSave.skillLevel[classId - 1] < charaWork.battleSave.skillLevelCap[classId]) - { - //Increase level - charaWork.battleSave.skillLevel[classId - 1]++; - charaWork.parameterSave.state_mainSkillLevel++; - - //33909: You attain level [level]. - if (actionList != null) - actionList.Add(new CommandResult(actorId, 33909, 0, (ushort)charaWork.battleSave.skillLevel[classId - 1])); - - EquipAbilitiesAtLevel(classId, GetLevel(), actionList); - } - } - - public static byte ConvertClassIdToJobId(byte classId) - { - byte jobId = classId; - - switch(classId) - { - case CLASSID_PUG: - case CLASSID_GLA: - case CLASSID_MRD: - jobId += 13; - break; - case CLASSID_ARC: - case CLASSID_LNC: - jobId += 11; - break; - case CLASSID_THM: - case CLASSID_CNJ: - jobId += 4; - break; - } - - return jobId; - } - - public void SetCurrentJob(byte jobId) - { - currentJob = jobId; - BroadcastPacket(SetCurrentJobPacket.BuildPacket(actorId, jobId), true); - Database.LoadHotbar(this); - SendCharaExpInfo(); - } - - //Gets the id of the player's current job. If they aren't a job, gets the id of their class - public byte GetCurrentClassOrJob() - { - if (currentJob != 0) - return (byte) currentJob; - return charaWork.parameterSave.state_mainSkill[0]; - } - - public void hpstuff(uint hp) - { - SetMaxHP(hp); - SetHP(hp); - mpMaxBase = (ushort)hp; - charaWork.parameterSave.mpMax = (short)hp; - charaWork.parameterSave.mp = (short)hp; - AddTP(3000); - updateFlags |= ActorUpdateFlags.HpTpMp; - } - - public void SetCombos(int comboId1 = 0, int comboId2 = 0) - { - SetCombos(new int[] { comboId1, comboId2 }); - } - - public void SetCombos(int[] comboIds) - { - Array.Copy(comboIds, playerWork.comboNextCommandId, 2); - - //If we're starting or continuing a combo chain, add the status effect and combo cost bonus - if (comboIds[0] != 0) - { - StatusEffect comboEffect = new StatusEffect(this, Server.GetWorldManager().GetStatusEffect((uint) StatusEffectId.Combo)); - comboEffect.SetDuration(13); - comboEffect.SetOverwritable(1); - statusEffects.AddStatusEffect(comboEffect, this); - playerWork.comboCostBonusRate = 1; - } - //Otherwise we're ending a combo, remove the status - else - { - statusEffects.RemoveStatusEffect(statusEffects.GetStatusEffectById((uint) StatusEffectId.Combo)); - playerWork.comboCostBonusRate = 0; - } - - ActorPropertyPacketUtil comboPropertyPacket = new ActorPropertyPacketUtil("playerWork/combo", this); - comboPropertyPacket.AddProperty("playerWork.comboCostBonusRate"); - comboPropertyPacket.AddProperty("playerWork.comboNextCommandId[0]"); - comboPropertyPacket.AddProperty("playerWork.comboNextCommandId[1]"); - QueuePackets(comboPropertyPacket.Done()); - } - - public override void CalculateBaseStats() - { - base.CalculateBaseStats(); - //Add weapon property mod - var equip = GetEquipment(); - var mainHandItem = equip.GetItemAtSlot(SLOT_MAINHAND); - var damageAttribute = 0; - var attackDelay = 3000; - var hitCount = 1; - - if (mainHandItem != null) - { - var mainHandWeapon = (Server.GetItemGamedata(mainHandItem.itemId) as WeaponItem); - damageAttribute = mainHandWeapon.damageAttributeType1; - attackDelay = (int) (mainHandWeapon.damageInterval * 1000); - hitCount = mainHandWeapon.frequency; - } - - var hasShield = equip.GetItemAtSlot(SLOT_OFFHAND) != null ? 1 : 0; - SetMod((uint)Modifier.CanBlock, hasShield); - - SetMod((uint)Modifier.AttackType, damageAttribute); - SetMod((uint)Modifier.Delay, attackDelay); - SetMod((uint)Modifier.HitCount, hitCount); - - //These stats all correlate in a 3:2 fashion - //It seems these stats don't actually increase their respective stats. The magic stats do, however - AddMod((uint)Modifier.Attack, (long)(GetMod(Modifier.Strength) * 0.667)); - AddMod((uint)Modifier.Accuracy, (long)(GetMod(Modifier.Dexterity) * 0.667)); - AddMod((uint)Modifier.Defense, (long)(GetMod(Modifier.Vitality) * 0.667)); - - //These stats correlate in a 4:1 fashion. (Unsure if MND is accurate but it would make sense for it to be) - AddMod((uint)Modifier.AttackMagicPotency, (long)((float)GetMod(Modifier.Intelligence) * 0.25)); - - AddMod((uint)Modifier.MagicAccuracy, (long)((float)GetMod(Modifier.Mind) * 0.25)); - AddMod((uint)Modifier.HealingMagicPotency, (long)((float)GetMod(Modifier.Mind) * 0.25)); - - AddMod((uint)Modifier.MagicEvasion, (long)((float)GetMod(Modifier.Piety) * 0.25)); - AddMod((uint)Modifier.EnfeeblingMagicPotency, (long)((float)GetMod(Modifier.Piety) * 0.25)); - - //VIT correlates to HP in a 1:1 fashion - AddMod((uint)Modifier.Hp, (long)((float)Modifier.Vitality)); - - CalculateTraitMods(); - } - - public bool HasTrait(ushort id) - { - BattleTrait trait = Server.GetWorldManager().GetBattleTrait(id); - - return HasTrait(trait); - } - - public bool HasTrait(BattleTrait trait) - { - return (trait != null) && (trait.job == GetClass()) && (trait.level <= GetLevel()); - } - - public void CalculateTraitMods() - { - var traitIds = Server.GetWorldManager().GetAllBattleTraitIdsForClass((byte) GetClass()); - - foreach(var traitId in traitIds) - { - var trait = Server.GetWorldManager().GetBattleTrait(traitId); - if(HasTrait(trait)) - { - AddMod(trait.modifier, trait.bonus); - } - } - } - - public bool HasItemEquippedInSlot(uint itemId, ushort slot) - { - var equippedItem = equipment.GetItemAtSlot(slot); - - return equippedItem != null && equippedItem.itemId == itemId; - } - - public Retainer GetSpawnedRetainer() - { - return currentSpawnedRetainer; - } - - public void StartTradeTransaction(Player otherPlayer) - { - myOfferings = new ReferencedItemPackage(this, ItemPackage.MAXSIZE_TRADE, ItemPackage.TRADE); - otherTrader = otherPlayer; - isTradeAccepted = false; - } - - public Player GetOtherTrader() - { - return otherTrader; - } - - public ReferencedItemPackage GetTradeOfferings() - { - return myOfferings; - } - - public bool IsTrading() - { - return otherTrader != null; - } - - public bool IsTradeAccepted() - { - return isTradeAccepted; - } - - public void AddTradeItem(ushort slot, ItemRefParam chosenItem, int tradeQuantity) - { - if (!IsTrading()) - return; - - //Get chosen item - InventoryItem offeredItem = itemPackages[chosenItem.itemPackage].GetItemAtSlot(chosenItem.slot); - offeredItem.SetTradeQuantity(tradeQuantity); - - myOfferings.Set(slot, offeredItem); - SendTradePackets(); - } - - public void RemoveTradeItem(ushort slot) - { - if (!IsTrading()) - return; - - InventoryItem offeredItem = myOfferings.GetItemAtSlot(slot); - offeredItem.SetNormal(); - - myOfferings.Clear(slot); - SendTradePackets(); - } - - public void ClearTradeItems() - { - if (!IsTrading()) - return; - - for (ushort i = 0; i < myOfferings.GetCapacity(); i++) - { - InventoryItem offeredItem = myOfferings.GetItemAtSlot(i); - if (offeredItem != null) - offeredItem.SetNormal(); - } - - myOfferings.ClearAll(); - SendTradePackets(); - } - - private void SendTradePackets() - { - //Send to self - QueuePacket(InventoryBeginChangePacket.BuildPacket(actorId, true)); - myOfferings.SendUpdate(this); - QueuePacket(InventoryEndChangePacket.BuildPacket(actorId)); - - //Send to other trader - otherTrader.QueuePacket(InventoryBeginChangePacket.BuildPacket(actorId, true)); - myOfferings.SendUpdateAsItemPackage(otherTrader); - otherTrader.QueuePacket(InventoryEndChangePacket.BuildPacket(actorId)); - } - - public void AcceptTrade(bool accepted) - { - if (!IsTrading()) - return; - isTradeAccepted = accepted; - } - - public void FinishTradeTransaction() - { - if (myOfferings != null) - { - myOfferings.ClearAll(); - for (ushort i = 0; i < myOfferings.GetCapacity(); i++) - { - InventoryItem offeredItem = myOfferings.GetItemAtSlot(i); - if (offeredItem != null) - offeredItem.SetNormal(); - } - - QueuePacket(InventoryBeginChangePacket.BuildPacket(actorId, true)); - myOfferings.SendUpdate(this); - QueuePacket(InventoryEndChangePacket.BuildPacket(actorId)); - } - - isTradeAccepted = false; - myOfferings = null; - otherTrader = null; - } - - } -}