From 35f925105633214d3729bced8a7c7a9df0102786 Mon Sep 17 00:00:00 2001 From: yogurt Date: Tue, 22 Aug 2017 14:50:53 -0500 Subject: [PATCH 1/2] Split update hotbar function into seperate command and recast functions, fixed recast packet spam, recast timers now reset when commands are added to the hotbar and when changing classes, and are now saved in the databse correctly and sent on login. Merged demo's changes. --- FFXIVClassic Map Server/Database.cs | 11 +- .../actors/chara/player/Player.cs | 115 +++++++++++------- 2 files changed, 83 insertions(+), 43 deletions(-) diff --git a/FFXIVClassic Map Server/Database.cs b/FFXIVClassic Map Server/Database.cs index 00f4dbec..1990683b 100644 --- a/FFXIVClassic Map Server/Database.cs +++ b/FFXIVClassic Map Server/Database.cs @@ -1286,7 +1286,7 @@ namespace FFXIVClassic_Map_Server cmd = new MySqlCommand(query, conn); cmd.Parameters.AddWithValue("@charId", player.actorId); cmd.Parameters.AddWithValue("@classId", player.charaWork.parameterSave.state_mainSkill[0]); - cmd.Parameters.AddWithValue("@hotbarSlot", hotbarSlot - 1); + cmd.Parameters.AddWithValue("@hotbarSlot", hotbarSlot); cmd.ExecuteNonQuery(); } catch (MySqlException e) @@ -1336,9 +1336,16 @@ namespace FFXIVClassic_Map_Server while (reader.Read()) { int index = reader.GetUInt16(0); - player.charaWork.command[index] = reader.GetUInt32(1); + uint trueCommandId = reader.GetUInt32(1); + player.charaWork.command[index] = trueCommandId; player.charaWork.commandCategory[index] = 1; player.charaWork.parameterSave.commandSlot_recastTime[index - player.charaWork.commandBorder] = reader.GetUInt32(2); + + //Recast timer + Ability ability = Server.GetWorldManager().GetAbility((ushort)(trueCommandId ^ 2700083200)); + player.charaWork.parameterTemp.maxCommandRecastTime[index - player.charaWork.commandBorder] = (ushort) (ability != null ? ability.recastTimeSeconds : 1); + //Previous recast timer + player.charaWork.parameterSave.commandSlot_recastTime[index - player.charaWork.commandBorder] = reader.GetUInt32(2); } } } diff --git a/FFXIVClassic Map Server/actors/chara/player/Player.cs b/FFXIVClassic Map Server/actors/chara/player/Player.cs index b8b5cfe7..0035c9d8 100644 --- a/FFXIVClassic Map Server/actors/chara/player/Player.cs +++ b/FFXIVClassic Map Server/actors/chara/player/Player.cs @@ -399,7 +399,15 @@ namespace FFXIVClassic_Map_Server.Actors 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)); + } + } } @@ -968,7 +976,6 @@ namespace FFXIVClassic_Map_Server.Actors charaWork.parameterSave.state_mainSkill[0] = classId; charaWork.parameterSave.state_mainSkillLevel = charaWork.battleSave.skillLevel[classId-1]; - Database.LoadHotbar(this); playerWork.restBonusExpRate = 0.0f; ActorPropertyPacketUtil propertyBuilder = new ActorPropertyPacketUtil("charaWork/stateForAll", this); @@ -978,7 +985,18 @@ namespace FFXIVClassic_Map_Server.Actors propertyBuilder.NewTarget("playerWork/expBonus"); propertyBuilder.AddProperty("playerWork.restBonusExpRate"); - QueuePackets(GetUpdateHotbarPacket(actorId).Done()); + 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(); @@ -1747,58 +1765,62 @@ namespace FFXIVClassic_Map_Server.Actors aiContainer.InternalDie(tick, 60); } - //Update all the hotbar slots past the commandborder. Commands before the commandborder only need to be sent on init since they never change - public ActorPropertyPacketUtil GetUpdateHotbarPacket(uint playerActorId) + //Update commands and recast timers for the entire hotbar + public void UpdateHotbar() { List slotsToUpdate = new List(); for (ushort i = charaWork.commandBorder; i < charaWork.commandBorder + 30; i++) { slotsToUpdate.Add(i); } - - return GetUpdateHotbarPacket(playerActorId, slotsToUpdate); + UpdateHotbar(slotsToUpdate); } - //Update select hotbar slots. - public ActorPropertyPacketUtil GetUpdateHotbarPacket(uint playerActorId, List slotsToUpdate) + //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); - - propPacketUtil.AddProperty("charaWork.commandBorder"); - + ActorPropertyPacketUtil compatibiltyUtil = new ActorPropertyPacketUtil("charaWork/commandDetailForSelf", this); foreach (ushort slot in slotsToUpdate) { propPacketUtil.AddProperty(String.Format("charaWork.command[{0}]", slot)); propPacketUtil.AddProperty(String.Format("charaWork.commandCategory[{0}]", slot)); } - for (int i = 0; i < charaWork.parameterSave.commandSlot_compatibility.Length; i++) + //Enable or disable slots based on whether there is an ability in that slot + foreach (ushort slot in slotsToUpdate) { - //charaWork.parameterSave.commandSlot_compatibility[i] = true; - // propPacketUtil.AddProperty(String.Format("charaWork.parameterSave.commandSlot_compatibility[{0}]", i)); + charaWork.parameterSave.commandSlot_compatibility[slot - charaWork.commandBorder] = charaWork.command[slot] != 0; + compatibiltyUtil.AddProperty(String.Format("charaWork.parameterSave.commandSlot_compatibility[{0}]", slot - charaWork.commandBorder)); } - charaWork.parameterTemp.otherClassAbilityCount[0] = 3; - 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]"); + 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); - for(int i = 0; i < charaWork.parameterSave.commandSlot_recastTime.Length; i++) + + foreach (ushort slot in slotsToUpdate) { - propPacketUtil.AddProperty(String.Format("charawork.parameterSave.commandSlot_recastTime[{0}]", i)); - propPacketUtil.AddProperty(String.Format("charawork.parameterTemp.maxCommandRecastTime[{0}]", i)); + 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()); - - return propPacketUtil; } - public void EquipAbility(ushort hotbarSlot, uint commandId, uint recastTime) + public void EquipAbility(ushort hotbarSlot, ushort commandId) { //if (charaWork.commandAcquired[commandId]) { @@ -1814,8 +1836,8 @@ namespace FFXIVClassic_Map_Server.Actors //If hotbar slot is 0, look for the first open slot if (hotbarSlot == 0) { - trueHotbarSlot = findFirstCommandSlotById(0); - int equippedSlot = findFirstCommandSlotById(trueCommandId); + trueHotbarSlot = FindFirstCommandSlotById(0); + ushort equippedSlot = FindFirstCommandSlotById(trueCommandId); //We can only equip a command if there is an open hotbar slot and if the command was not found in the hotbar. canEquip = trueHotbarSlot < endOfHotbar && equippedSlot >= endOfHotbar; //If the command was found in the hotbar, mark it as already equipped @@ -1824,32 +1846,47 @@ namespace FFXIVClassic_Map_Server.Actors //If the slot the command is being moved to is occupied, move that command to the slot currently occupied by the command being placed. else if (charaWork.command[trueHotbarSlot] != trueCommandId) { - ushort oldSlot = findFirstCommandSlotById(trueCommandId); + //Search for where the ability we're equipping is already equipped + ushort oldSlot = FindFirstCommandSlotById(trueCommandId); + //If the command was found, update the old slot, otherwise it will just be overwritten if (oldSlot < endOfHotbar) { - Database.EquipAbility(this, oldSlot, charaWork.command[trueHotbarSlot], recastTime); charaWork.command[oldSlot] = charaWork.command[trueHotbarSlot]; slotsToUpdate.Add(oldSlot); + //Need to update the old slot's recast timer as well + charaWork.parameterTemp.maxCommandRecastTime[oldSlot - charaWork.commandBorder] = charaWork.parameterTemp.maxCommandRecastTime[trueHotbarSlot - charaWork.commandBorder]; + //I don't know how the game handled moving abilities in terms of cooldowns. + //I'm assuming they just keep whatever their current cooldown was instead of being reset to their max but SE were dicks in 1.0 so who knows + charaWork.parameterSave.commandSlot_recastTime[oldSlot - charaWork.commandBorder] = charaWork.parameterSave.commandSlot_recastTime[trueHotbarSlot - charaWork.commandBorder]; + Database.EquipAbility(this, oldSlot, charaWork.command[trueHotbarSlot], charaWork.parameterSave.commandSlot_recastTime[oldSlot - charaWork.commandBorder]); } } - + if (canEquip) { - Actor a = Server.GetStaticActors(trueCommandId); - Database.EquipAbility(this, trueHotbarSlot, trueCommandId, recastTime); charaWork.command[trueHotbarSlot] = trueCommandId; charaWork.commandCategory[trueHotbarSlot] = 1; + + //Set recast time + ushort maxRecastTime = (ushort)Server.GetWorldManager().GetAbility(commandId).recastTimeSeconds; + uint recastEnd = Utils.UnixTimeStampUTC() + maxRecastTime; + charaWork.parameterTemp.maxCommandRecastTime[trueHotbarSlot - charaWork.commandBorder] = maxRecastTime; + charaWork.parameterSave.commandSlot_recastTime[trueHotbarSlot - charaWork.commandBorder] = recastEnd; slotsToUpdate.Add(trueHotbarSlot); + Database.EquipAbility(this, trueHotbarSlot, trueCommandId, recastEnd); + //"[Command] set." - SendGameMessage(Server.GetWorldManager().GetActor(), 30603, 0x20, 0, commandId); + SendGameMessage(Server.GetWorldManager().GetActor(), 30603, 0x20, 0, (int)commandId); } + //Ability is already equipped else if (isAlreadyEquipped) { //"That action is already set to an action slot." SendGameMessage(Server.GetWorldManager().GetActor(), 30719, 0x20, 0); } + //Hotbar full else { //"You cannot set any more actions." @@ -1860,17 +1897,13 @@ namespace FFXIVClassic_Map_Server.Actors else if (trueCommandId == 2700083200 && charaWork.command[trueHotbarSlot] != 0) { //Need to get the commandId this way because when unequipping an ability the commandId is 0. - commandId = charaWork.command[trueHotbarSlot] ^ 2700083200; SendGameMessage(Server.GetWorldManager().GetActor(), 30604, 0x20, 0, charaWork.command[trueHotbarSlot] ^ 2700083200); Database.UnequipAbility(this, trueHotbarSlot); charaWork.command[trueHotbarSlot] = 0; - slotsToUpdate.Add(trueHotbarSlot); - //"[Command] removed." - SendGameMessage(Server.GetWorldManager().GetActor(), 30747, 0x20, 0); + slotsToUpdate.Add(trueHotbarSlot); } - ActorPropertyPacketUtil packet = GetUpdateHotbarPacket(actorId, slotsToUpdate); - QueuePackets(packet.Done()); + UpdateHotbar(slotsToUpdate); } //action not acquired // else @@ -1882,7 +1915,7 @@ namespace FFXIVClassic_Map_Server.Actors //Finds the first hotbar slot with a given commandId. //If the returned value is outside the hotbar, it indicates it wasn't found. - private ushort findFirstCommandSlotById(uint commandId) + private ushort FindFirstCommandSlotById(uint commandId) { ushort firstSlot = (ushort)(charaWork.commandBorder + 30); From e3901382584c2ba3ed885e6b57fffcbe2e78c846 Mon Sep 17 00:00:00 2001 From: yogurt Date: Tue, 22 Aug 2017 14:56:57 -0500 Subject: [PATCH 2/2] Removed unneeded recast timer parameter in EquipAbility call in EquipAbilityCommand.lua --- data/scripts/commands/EquipAbilityCommand.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/scripts/commands/EquipAbilityCommand.lua b/data/scripts/commands/EquipAbilityCommand.lua index 946c5a2a..51569a2d 100644 --- a/data/scripts/commands/EquipAbilityCommand.lua +++ b/data/scripts/commands/EquipAbilityCommand.lua @@ -8,7 +8,7 @@ require ("global") function onEventStarted(player, equipAbilityWidget, triggername, slot, ability, unkown, arg1, arg2, arg3, arg4, arg5, arg6) if ability then - player:EquipAbility(slot, ability, 1); + player:EquipAbility(slot, ability); end player:endEvent(); end \ No newline at end of file