From c3fd8f917ea1342c29e3b7b49ec0b53268d5cae2 Mon Sep 17 00:00:00 2001 From: yogurt Date: Tue, 29 Aug 2017 09:00:09 -0500 Subject: [PATCH] Added UnequipAbility function, made EquipAbility work with zero indexed hotbar database, added new checks to EquipAbilityCommand.lua --- FFXIVClassic Map Server/Database.cs | 2 + .../actors/chara/player/Player.cs | 169 +++++++++--------- data/scripts/commands/EquipAbilityCommand.lua | 42 ++++- 3 files changed, 124 insertions(+), 89 deletions(-) diff --git a/FFXIVClassic Map Server/Database.cs b/FFXIVClassic Map Server/Database.cs index b3574e21..04c27acd 100644 --- a/FFXIVClassic Map Server/Database.cs +++ b/FFXIVClassic Map Server/Database.cs @@ -1259,6 +1259,8 @@ namespace FFXIVClassic_Map_Server } } } + else + UnequipAbility(player, hotbarSlot); } //Unequipping is done by sending an equip packet with 2700083200 as the ability and the hotbar slot of the action being unequipped diff --git a/FFXIVClassic Map Server/actors/chara/player/Player.cs b/FFXIVClassic Map Server/actors/chara/player/Player.cs index 4c7f9306..3881f995 100644 --- a/FFXIVClassic Map Server/actors/chara/player/Player.cs +++ b/FFXIVClassic Map Server/actors/chara/player/Player.cs @@ -975,6 +975,11 @@ namespace FFXIVClassic_Map_Server.Actors 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; + } ActorPropertyPacketUtil propertyBuilder = new ActorPropertyPacketUtil("charaWork/stateForAll", this); @@ -1847,95 +1852,89 @@ namespace FFXIVClassic_Map_Server.Actors public void EquipAbility(ushort hotbarSlot, ushort commandId) { - //if (charaWork.commandAcquired[commandId]) + var ability = Server.GetWorldManager().GetBattleCommand(commandId); + uint trueCommandId = commandId | 0xA0F00000; + ushort trueHotbarSlot = (ushort)(hotbarSlot + charaWork.commandBorder - 1); + ushort endOfHotbar = (ushort)(charaWork.commandBorder + 30); + List slotsToUpdate = new List(); + bool canEquip = true; + + //If the ability is already equipped we need this so we can move its recast timer to the new slot + uint oldRecast = 0; + //Check if the command is already on the hotbar + ushort oldSlot = FindFirstCommandSlotById(trueCommandId); + bool isAlreadyEquipped = oldSlot < endOfHotbar; + + //New ability being added to the hotbar, set truehotbarslot to the first open slot. + if (hotbarSlot == 0) { - uint trueCommandId = 0xA0F00000 | commandId; - ushort trueHotbarSlot = (ushort)(hotbarSlot + charaWork.commandBorder - 1); - ushort endOfHotbar = (ushort)(charaWork.commandBorder + 30); - List slotsToUpdate = new List(); - if (trueCommandId != 2700083200) - { - bool canEquip = true; - bool isAlreadyEquipped = false; - - //If hotbar slot is 0, look for the first open slot - if (hotbarSlot == 0) - { - 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 - isAlreadyEquipped = equippedSlot < endOfHotbar; - } - //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) - { - //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) - { - 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) - { - charaWork.command[trueHotbarSlot] = trueCommandId; - charaWork.commandCategory[trueHotbarSlot] = 1; - - //Set recast time - ushort maxRecastTime = (ushort)Server.GetWorldManager().GetBattleCommand(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, (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." - SendGameMessage(Server.GetWorldManager().GetActor(), 30720, 0x20, 0); - } - } - //Unequip command - else if (trueCommandId == 2700083200 && charaWork.command[trueHotbarSlot] != 0) - { - //Need to get the commandId this way because when unequipping an ability the commandId is 0. - SendGameMessage(Server.GetWorldManager().GetActor(), 30604, 0x20, 0, charaWork.command[trueHotbarSlot] ^ 2700083200); - Database.UnequipAbility(this, trueHotbarSlot); - charaWork.command[trueHotbarSlot] = 0; - slotsToUpdate.Add(trueHotbarSlot); - - } - UpdateHotbar(slotsToUpdate); + //If the ability is already equipped, we can't add it to the hotbar again. + if (isAlreadyEquipped) + canEquip = false; + else + trueHotbarSlot = FindFirstCommandSlotById(0); } - //action not acquired - // else + //If the slot we're moving an command to already has an command there, move that command to the new command's old slot. + //Only need to do this if the new command is already equipped, otherwise we just write over the command there + else if (charaWork.command[trueHotbarSlot] != trueCommandId && isAlreadyEquipped) { - //"You have not yet acquired that action." - //SendGameMessage(Server.GetWorldManager().GetActor(), 30742, 0x20, 0, 0); + //Move the command to oldslot + charaWork.command[oldSlot] = charaWork.command[trueHotbarSlot]; + //Move recast timers to old slot as well and store the old recast timer + oldRecast = charaWork.parameterSave.commandSlot_recastTime[oldSlot - charaWork.commandBorder]; + charaWork.parameterTemp.maxCommandRecastTime[oldSlot - charaWork.commandBorder] = charaWork.parameterTemp.maxCommandRecastTime[trueHotbarSlot - charaWork.commandBorder]; + charaWork.parameterSave.commandSlot_recastTime[oldSlot - charaWork.commandBorder] = charaWork.parameterSave.commandSlot_recastTime[trueHotbarSlot - charaWork.commandBorder]; + //Save changes + Database.EquipAbility(this, (ushort)(oldSlot - charaWork.commandBorder), charaWork.command[oldSlot], charaWork.parameterSave.commandSlot_recastTime[oldSlot - charaWork.commandBorder]); + slotsToUpdate.Add(oldSlot); } + + if (canEquip) + { + charaWork.command[trueHotbarSlot] = trueCommandId; + charaWork.commandCategory[trueHotbarSlot] = 1; + + //Set recast time. If the ability was already equipped, then we use the previous recast timer instead of setting a new one + ushort maxRecastTime = (ushort)ability.recastTimeSeconds; + uint recastEnd = isAlreadyEquipped ? oldRecast : Utils.UnixTimeStampUTC() + maxRecastTime; + charaWork.parameterTemp.maxCommandRecastTime[trueHotbarSlot - charaWork.commandBorder] = maxRecastTime; + charaWork.parameterSave.commandSlot_recastTime[trueHotbarSlot - charaWork.commandBorder] = recastEnd; + slotsToUpdate.Add(trueHotbarSlot); + + Database.EquipAbility(this, (ushort) (trueHotbarSlot - charaWork.commandBorder), trueCommandId, recastEnd); + + //"[Command] set." + if (!isAlreadyEquipped) + SendGameMessage(Server.GetWorldManager().GetActor(), 30603, 0x20, 0, 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." + SendGameMessage(Server.GetWorldManager().GetActor(), 30720, 0x20, 0); + } + + UpdateHotbar(slotsToUpdate); + } + + + public void UnequipAbility(ushort hotbarSlot) + { + List slotsToUpdate = new List(); + ushort trueHotbarSlot = (ushort)(hotbarSlot + charaWork.commandBorder - 1); + uint commandId = charaWork.command[trueHotbarSlot]; + Database.UnequipAbility(this, (ushort)(trueHotbarSlot - charaWork.commandBorder)); + charaWork.command[trueHotbarSlot] = 0; + slotsToUpdate.Add(trueHotbarSlot); + SendGameMessage(Server.GetWorldManager().GetActor(), 30604, 0x20, 0, commandId ^ 0xA0F00000); + + UpdateHotbar(slotsToUpdate); } //Finds the first hotbar slot with a given commandId. diff --git a/data/scripts/commands/EquipAbilityCommand.lua b/data/scripts/commands/EquipAbilityCommand.lua index 946c5a2a..e11e5d27 100644 --- a/data/scripts/commands/EquipAbilityCommand.lua +++ b/data/scripts/commands/EquipAbilityCommand.lua @@ -3,12 +3,46 @@ require ("global") --equipAbilityWidget: Widget that calls this command --triggername: Event Starter ? --slot: Which slot the ability will go into ---ability: Ability being equipped +--commandid: command being equipped -function onEventStarted(player, equipAbilityWidget, triggername, slot, ability, unkown, arg1, arg2, arg3, arg4, arg5, arg6) - if ability then - player:EquipAbility(slot, ability, 1); +function onEventStarted(player, equipAbilityWidget, triggername, slot, commandid, unkown, arg1, arg2, arg3, arg4, arg5, arg6) + local worldManager = GetWorldManager(); + local ability = worldManager:GetBattleCommand(commandid); + + --Equip + if (commandid > 0) then + --Can the player equip any more cross class actions + if (player.charaWork.parameterTemp.otherClassAbilityCount[0] >= player.charaWork.parameterTemp.otherClassAbilityCount[1]) then + --"You cannot set any more actions." + player:SendGameMessage(GetWorldMaster(), 30720, 0x20, 0, 0); + player:endEvent(); + return; + end + + --Is the player high enough level in that class to equip the ability + if (player.charaWork.battleSave.skillLevel[ability.job] < ability.level) then + + --"You have not yet acquired that action" + player:SendGameMessage(GetWorldMaster(), 30742, 0x20, 0, 0); + player:endEvent(); + return; + end + + --Equip the ability + player:EquipAbility(slot, commandid); + --Unequip + elseif (commandid == 0) then + commandid = player.charaWork.command[slot + player.charaWork.commandBorder]; + + --Is the ability a part of the player's current class? + --This check isn't correct because of jobs having different ids + if(worldManager:GetBattleCommand(commandid).job == player.charaWork.parameterSave.state_mainSkill[0]) then + --"Actions of your current class or job cannot be removed." + player:SendGameMessage(GetWorldMaster(), 30745, 0x20, 0, 0); + elseif (commandid != 0) then + player:UnequipAbility(slot); + end end player:endEvent(); end \ No newline at end of file