mirror of
https://bitbucket.org/Ioncannon/project-meteor-server.git
synced 2025-04-20 11:47:48 +00:00
Added exp and leveling functions, redid equip ability functions to allow adding abilities that aren't for the player's current class and made functions more clear, added dictionary of BattleCommand ids indexed by a tuple containing classId and level.
This commit is contained in:
parent
56491266cc
commit
33f8709d76
7 changed files with 333 additions and 30 deletions
|
@ -1218,7 +1218,7 @@ namespace FFXIVClassic_Map_Server
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
public static void EquipAbility(Player player, ushort hotbarSlot, uint commandId, uint recastTime)
|
public static void EquipAbility(Player player, byte classId, ushort hotbarSlot, uint commandId, uint recastTime)
|
||||||
{
|
{
|
||||||
//2700083201 is where abilities start. 2700083200 is for unequipping abilities. Trying to put this in the hotbar will crash the game, need to put 0 instead
|
//2700083201 is where abilities start. 2700083200 is for unequipping abilities. Trying to put this in the hotbar will crash the game, need to put 0 instead
|
||||||
if (commandId > 2700083200)
|
if (commandId > 2700083200)
|
||||||
|
@ -1245,7 +1245,7 @@ namespace FFXIVClassic_Map_Server
|
||||||
|
|
||||||
cmd = new MySqlCommand(query, conn);
|
cmd = new MySqlCommand(query, conn);
|
||||||
cmd.Parameters.AddWithValue("@charId", player.actorId);
|
cmd.Parameters.AddWithValue("@charId", player.actorId);
|
||||||
cmd.Parameters.AddWithValue("@classId", player.charaWork.parameterSave.state_mainSkill[0]);
|
cmd.Parameters.AddWithValue("@classId", classId);
|
||||||
cmd.Parameters.AddWithValue("@commandId", commandId);
|
cmd.Parameters.AddWithValue("@commandId", commandId);
|
||||||
cmd.Parameters.AddWithValue("@hotbarSlot", hotbarSlot);
|
cmd.Parameters.AddWithValue("@hotbarSlot", hotbarSlot);
|
||||||
cmd.Parameters.AddWithValue("@recastTime", recastTime);
|
cmd.Parameters.AddWithValue("@recastTime", recastTime);
|
||||||
|
@ -1358,6 +1358,57 @@ namespace FFXIVClassic_Map_Server
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ushort FindFirstCommandSlot(Player player, byte classId)
|
||||||
|
{
|
||||||
|
ushort slot = 0;
|
||||||
|
using (MySqlConnection conn = new MySqlConnection(
|
||||||
|
String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}",
|
||||||
|
ConfigConstants.DATABASE_HOST,
|
||||||
|
ConfigConstants.DATABASE_PORT,
|
||||||
|
ConfigConstants.DATABASE_NAME,
|
||||||
|
ConfigConstants.DATABASE_USERNAME,
|
||||||
|
ConfigConstants.DATABASE_PASSWORD)))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
conn.Open();
|
||||||
|
MySqlCommand cmd;
|
||||||
|
string query = "";
|
||||||
|
|
||||||
|
//Drop
|
||||||
|
List<Tuple<ushort, uint>> hotbarList = new List<Tuple<ushort, uint>>();
|
||||||
|
query = @"
|
||||||
|
SELECT hotbarSlot
|
||||||
|
FROM characters_hotbar
|
||||||
|
WHERE characterId = @charId AND classId = @classId
|
||||||
|
ORDER BY hotbarSlot
|
||||||
|
";
|
||||||
|
cmd = new MySqlCommand(query, conn);
|
||||||
|
cmd.Parameters.AddWithValue("@charId", player.actorId);
|
||||||
|
cmd.Parameters.AddWithValue("@classId", classId);
|
||||||
|
|
||||||
|
using (MySqlDataReader reader = cmd.ExecuteReader())
|
||||||
|
{
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
if (slot != reader.GetUInt16("hotbarSlot"))
|
||||||
|
return slot;
|
||||||
|
|
||||||
|
slot++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (MySqlException e)
|
||||||
|
{
|
||||||
|
Program.Log.Error(e.ToString());
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
conn.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return slot;
|
||||||
|
}
|
||||||
public static List<InventoryItem> GetInventory(Player player, uint slotOffset, uint type)
|
public static List<InventoryItem> GetInventory(Player player, uint slotOffset, uint type)
|
||||||
{
|
{
|
||||||
List<InventoryItem> items = new List<InventoryItem>();
|
List<InventoryItem> items = new List<InventoryItem>();
|
||||||
|
@ -2146,9 +2197,9 @@ namespace FFXIVClassic_Map_Server
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Dictionary<ushort, BattleCommand> LoadGlobalBattleCommandList()
|
public static void LoadGlobalBattleCommandList(Dictionary<ushort, BattleCommand> battleCommandDict, Dictionary<Tuple<byte, short>, uint> battleCommandIdByLevel)
|
||||||
{
|
{
|
||||||
var battleCommands = new Dictionary<ushort, BattleCommand>();
|
//var battleCommands = new Dictionary<ushort, BattleCommand>();
|
||||||
|
|
||||||
using (MySqlConnection conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD)))
|
using (MySqlConnection conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD)))
|
||||||
{
|
{
|
||||||
|
@ -2195,7 +2246,11 @@ namespace FFXIVClassic_Map_Server
|
||||||
battleCommand.battleAnimation = reader.GetUInt32("battleAnimation");
|
battleCommand.battleAnimation = reader.GetUInt32("battleAnimation");
|
||||||
battleCommand.validUser = (BattleCommandValidUser)reader.GetByte("validUser");
|
battleCommand.validUser = (BattleCommandValidUser)reader.GetByte("validUser");
|
||||||
|
|
||||||
battleCommands.Add(id, battleCommand);
|
battleCommandDict.Add(id, battleCommand);
|
||||||
|
|
||||||
|
//Handle level 1 abilities separately because of FUCKING ARCHER REEE, just add those to the hotbar when the job is unlocked or on char creation, ez
|
||||||
|
if(battleCommand.level > 1)
|
||||||
|
battleCommandIdByLevel.Add(Tuple.Create<byte, short>(battleCommand.job, battleCommand.level), id | 0xA0F00000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2208,7 +2263,6 @@ namespace FFXIVClassic_Map_Server
|
||||||
conn.Dispose();
|
conn.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return battleCommands;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,7 @@ namespace FFXIVClassic_Map_Server
|
||||||
private Dictionary<ulong, Party> currentPlayerParties = new Dictionary<ulong, Party>(); //GroupId, Party object
|
private Dictionary<ulong, Party> currentPlayerParties = new Dictionary<ulong, Party>(); //GroupId, Party object
|
||||||
private Dictionary<uint, StatusEffect> statusEffectList = new Dictionary<uint, StatusEffect>();
|
private Dictionary<uint, StatusEffect> statusEffectList = new Dictionary<uint, StatusEffect>();
|
||||||
private Dictionary<ushort, BattleCommand> battleCommandList = new Dictionary<ushort, BattleCommand>();
|
private Dictionary<ushort, BattleCommand> battleCommandList = new Dictionary<ushort, BattleCommand>();
|
||||||
|
private Dictionary<Tuple<byte, short>, uint> battleCommandIdByLevel = new Dictionary<Tuple<byte, short>, uint>();//Holds battle command ids keyed by class id and level (in that order)
|
||||||
private Dictionary<uint, ModifierList> battleNpcGenusMods = new Dictionary<uint, ModifierList>();
|
private Dictionary<uint, ModifierList> battleNpcGenusMods = new Dictionary<uint, ModifierList>();
|
||||||
private Dictionary<uint, ModifierList> battleNpcPoolMods = new Dictionary<uint, ModifierList>();
|
private Dictionary<uint, ModifierList> battleNpcPoolMods = new Dictionary<uint, ModifierList>();
|
||||||
private Dictionary<uint, ModifierList> battleNpcSpawnMods = new Dictionary<uint, ModifierList>();
|
private Dictionary<uint, ModifierList> battleNpcSpawnMods = new Dictionary<uint, ModifierList>();
|
||||||
|
@ -1422,7 +1423,7 @@ namespace FFXIVClassic_Map_Server
|
||||||
|
|
||||||
public void LoadBattleCommands()
|
public void LoadBattleCommands()
|
||||||
{
|
{
|
||||||
battleCommandList = Database.LoadGlobalBattleCommandList();
|
Database.LoadGlobalBattleCommandList(battleCommandList, battleCommandIdByLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BattleCommand GetBattleCommand(uint id)
|
public BattleCommand GetBattleCommand(uint id)
|
||||||
|
@ -1430,5 +1431,11 @@ namespace FFXIVClassic_Map_Server
|
||||||
BattleCommand battleCommand;
|
BattleCommand battleCommand;
|
||||||
return battleCommandList.TryGetValue((ushort)id, out battleCommand) ? battleCommand.Clone() : null;
|
return battleCommandList.TryGetValue((ushort)id, out battleCommand) ? battleCommand.Clone() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public uint GetBattleCommandIdByLevel(byte classId, short level)
|
||||||
|
{
|
||||||
|
uint id = 0;
|
||||||
|
return battleCommandIdByLevel.TryGetValue(Tuple.Create(classId, level), out id) ? id : 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
public float potencial = 6.6f;
|
public float potencial = 6.6f;
|
||||||
public short[] skillLevel = new short[52];
|
public short[] skillLevel = new short[52];
|
||||||
public short[] skillLevelCap = new short[52];
|
public short[] skillLevelCap = new short[52];
|
||||||
public short[] skillPoint = new short[52];
|
public int[] skillPoint = new int[52];
|
||||||
|
|
||||||
public short physicalLevel;
|
public short physicalLevel;
|
||||||
public int physicalExp;
|
public int physicalExp;
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
public uint[] command = new uint[64]; //ACTORS
|
public uint[] command = new uint[64]; //ACTORS
|
||||||
public byte[] commandCategory = new byte[64];
|
public byte[] commandCategory = new byte[64];
|
||||||
public byte commandBorder = 0x20;
|
public byte commandBorder = 0x20;
|
||||||
public bool[] commandAcquired = new bool[4096];
|
public bool[] commandAcquired = new bool[4096];
|
||||||
public bool[] additionalCommandAcquired = new bool[36];
|
public bool[] additionalCommandAcquired = new bool[36];
|
||||||
|
|
||||||
public uint currentContentGroup;
|
public uint currentContentGroup;
|
||||||
|
|
|
@ -972,7 +972,6 @@ namespace FFXIVClassic_Map_Server.Actors
|
||||||
//Check if bonus point available... set
|
//Check if bonus point available... set
|
||||||
|
|
||||||
//Set rested EXP
|
//Set rested EXP
|
||||||
|
|
||||||
charaWork.parameterSave.state_mainSkill[0] = classId;
|
charaWork.parameterSave.state_mainSkill[0] = classId;
|
||||||
charaWork.parameterSave.state_mainSkillLevel = charaWork.battleSave.skillLevel[classId-1];
|
charaWork.parameterSave.state_mainSkillLevel = charaWork.battleSave.skillLevel[classId-1];
|
||||||
playerWork.restBonusExpRate = 0.0f;
|
playerWork.restBonusExpRate = 0.0f;
|
||||||
|
@ -1846,7 +1845,89 @@ namespace FFXIVClassic_Map_Server.Actors
|
||||||
QueuePackets(recastPacketUtil.Done());
|
QueuePackets(recastPacketUtil.Done());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void EquipAbility(ushort hotbarSlot, ushort commandId)
|
//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 is 32-indexed
|
||||||
|
public void EquipAbility(byte classId, uint commandId, ushort hotbarSlot, bool printMessage = true)
|
||||||
|
{
|
||||||
|
var ability = Server.GetWorldManager().GetBattleCommand(commandId);
|
||||||
|
uint trueCommandId = commandId | 0xA0F00000;
|
||||||
|
ushort lowHotbarSlot = (ushort)(hotbarSlot - charaWork.commandBorder);
|
||||||
|
ushort maxRecastTime = (ushort)ability.recastTimeSeconds;
|
||||||
|
uint recastEnd = Utils.UnixTimeStampUTC() + maxRecastTime;
|
||||||
|
List<ushort> slotsToUpdate = new List<ushort>();
|
||||||
|
|
||||||
|
//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 == charaWork.parameterSave.state_mainSkill[0])
|
||||||
|
{
|
||||||
|
charaWork.command[hotbarSlot] = trueCommandId;
|
||||||
|
charaWork.commandCategory[hotbarSlot] = 1;
|
||||||
|
charaWork.parameterTemp.maxCommandRecastTime[lowHotbarSlot] = maxRecastTime;
|
||||||
|
charaWork.parameterSave.commandSlot_recastTime[lowHotbarSlot] = recastEnd;
|
||||||
|
|
||||||
|
slotsToUpdate.Add(hotbarSlot);
|
||||||
|
UpdateHotbar(slotsToUpdate);
|
||||||
|
}
|
||||||
|
|
||||||
|
Database.EquipAbility(this, classId, (ushort) (hotbarSlot - charaWork.commandBorder), commandId, recastEnd);
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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
|
||||||
|
Database.EquipAbility(this, charaWork.parameterSave.state_mainSkill[0], (ushort)(lowHotbarSlot1), charaWork.command[hotbarSlot1], charaWork.parameterSave.commandSlot_recastTime[lowHotbarSlot1]);
|
||||||
|
|
||||||
|
List<ushort> slotsToUpdate = new List<ushort>();
|
||||||
|
slotsToUpdate.Add(hotbarSlot1);
|
||||||
|
slotsToUpdate.Add(hotbarSlot2);
|
||||||
|
UpdateHotbar(slotsToUpdate);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void EquipAbility(ushort hotbarSlot, uint commandId)
|
||||||
{
|
{
|
||||||
var ability = Server.GetWorldManager().GetBattleCommand(commandId);
|
var ability = Server.GetWorldManager().GetBattleCommand(commandId);
|
||||||
uint trueCommandId = commandId | 0xA0F00000;
|
uint trueCommandId = commandId | 0xA0F00000;
|
||||||
|
@ -1881,7 +1962,7 @@ namespace FFXIVClassic_Map_Server.Actors
|
||||||
charaWork.parameterTemp.maxCommandRecastTime[oldSlot - charaWork.commandBorder] = charaWork.parameterTemp.maxCommandRecastTime[trueHotbarSlot - 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];
|
charaWork.parameterSave.commandSlot_recastTime[oldSlot - charaWork.commandBorder] = charaWork.parameterSave.commandSlot_recastTime[trueHotbarSlot - charaWork.commandBorder];
|
||||||
//Save changes
|
//Save changes
|
||||||
Database.EquipAbility(this, (ushort)(oldSlot - charaWork.commandBorder), charaWork.command[oldSlot], charaWork.parameterSave.commandSlot_recastTime[oldSlot - charaWork.commandBorder]);
|
Database.EquipAbility(this, charaWork.parameterSave.state_mainSkill[0], (ushort)(oldSlot - charaWork.commandBorder), charaWork.command[oldSlot], charaWork.parameterSave.commandSlot_recastTime[oldSlot - charaWork.commandBorder]);
|
||||||
slotsToUpdate.Add(oldSlot);
|
slotsToUpdate.Add(oldSlot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1897,11 +1978,11 @@ namespace FFXIVClassic_Map_Server.Actors
|
||||||
charaWork.parameterSave.commandSlot_recastTime[trueHotbarSlot - charaWork.commandBorder] = recastEnd;
|
charaWork.parameterSave.commandSlot_recastTime[trueHotbarSlot - charaWork.commandBorder] = recastEnd;
|
||||||
slotsToUpdate.Add(trueHotbarSlot);
|
slotsToUpdate.Add(trueHotbarSlot);
|
||||||
|
|
||||||
Database.EquipAbility(this, (ushort) (trueHotbarSlot - charaWork.commandBorder), trueCommandId, recastEnd);
|
Database.EquipAbility(this, charaWork.parameterSave.state_mainSkill[0], (ushort) (trueHotbarSlot - charaWork.commandBorder), trueCommandId, recastEnd);
|
||||||
|
|
||||||
//"[Command] set."
|
//"[Command] set."
|
||||||
if (!isAlreadyEquipped)
|
if (!isAlreadyEquipped)
|
||||||
SendGameMessage(Server.GetWorldManager().GetActor(), 30603, 0x20, 0, commandId);
|
SendGameMessage(Server.GetWorldManager().GetActor(), 30603, 0x20, 0, commandId ^ 0xA0F00000);
|
||||||
}
|
}
|
||||||
//Ability is already equipped
|
//Ability is already equipped
|
||||||
else if (isAlreadyEquipped)
|
else if (isAlreadyEquipped)
|
||||||
|
@ -1920,7 +2001,7 @@ namespace FFXIVClassic_Map_Server.Actors
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void UnequipAbility(ushort hotbarSlot)
|
public void UnequipAbility(ushort hotbarSlot, bool printMessage = true)
|
||||||
{
|
{
|
||||||
List<ushort> slotsToUpdate = new List<ushort>();
|
List<ushort> slotsToUpdate = new List<ushort>();
|
||||||
ushort trueHotbarSlot = (ushort)(hotbarSlot + charaWork.commandBorder - 1);
|
ushort trueHotbarSlot = (ushort)(hotbarSlot + charaWork.commandBorder - 1);
|
||||||
|
@ -1928,14 +2009,16 @@ namespace FFXIVClassic_Map_Server.Actors
|
||||||
Database.UnequipAbility(this, (ushort)(trueHotbarSlot - charaWork.commandBorder));
|
Database.UnequipAbility(this, (ushort)(trueHotbarSlot - charaWork.commandBorder));
|
||||||
charaWork.command[trueHotbarSlot] = 0;
|
charaWork.command[trueHotbarSlot] = 0;
|
||||||
slotsToUpdate.Add(trueHotbarSlot);
|
slotsToUpdate.Add(trueHotbarSlot);
|
||||||
SendGameMessage(Server.GetWorldManager().GetActor(), 30604, 0x20, 0, commandId ^ 0xA0F00000);
|
|
||||||
|
if(printMessage)
|
||||||
|
SendGameMessage(Server.GetWorldManager().GetActor(), 30604, 0x20, 0, commandId ^ 0xA0F00000);
|
||||||
|
|
||||||
UpdateHotbar(slotsToUpdate);
|
UpdateHotbar(slotsToUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Finds the first hotbar slot with a given commandId.
|
//Finds the first hotbar slot with a given commandId.
|
||||||
//If the returned value is outside the hotbar, it indicates it wasn't found.
|
//If the returned value is outside the hotbar, it indicates it wasn't found.
|
||||||
private ushort FindFirstCommandSlotById(uint commandId)
|
public ushort FindFirstCommandSlotById(uint commandId)
|
||||||
{
|
{
|
||||||
if(commandId != 0)
|
if(commandId != 0)
|
||||||
commandId |= 0xA0F00000;
|
commandId |= 0xA0F00000;
|
||||||
|
@ -2200,5 +2283,93 @@ namespace FFXIVClassic_Map_Server.Actors
|
||||||
// todo: this really shouldnt be called on each ws?
|
// todo: this really shouldnt be called on each ws?
|
||||||
lua.LuaEngine.CallLuaBattleFunction(this, "onWeaponSkill", this, state.GetTarget(), skill);
|
lua.LuaEngine.CallLuaBattleFunction(this, "onWeaponSkill", this, state.GetTarget(), skill);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Handles exp being added, does not handle figuring out exp bonus from buffs or skill/link chains or any of that
|
||||||
|
public void AddExp(int exp, byte classId, int bonusPercent = 0)
|
||||||
|
{
|
||||||
|
exp += (int) Math.Ceiling((exp * bonusPercent / 100.0f));
|
||||||
|
//You earn [exp](+[bonusPercent]%) experience point(s).
|
||||||
|
SendGameMessage(this, Server.GetWorldManager().GetActor(), 33934, 0x44, this, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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 and unlocking skills and removing experience
|
||||||
|
while (exp >= diff && GetLevel() < charaWork.battleSave.skillLevelCap[classId])
|
||||||
|
{
|
||||||
|
//Level up
|
||||||
|
LevelUp(classId);
|
||||||
|
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 expPropertyPacket2 = new ActorPropertyPacketUtil("charaWork/exp", this);
|
||||||
|
ActorPropertyPacketUtil expPropertyPacket3 = new ActorPropertyPacketUtil("charaWork/stateForAll", this);
|
||||||
|
expPropertyPacket2.AddProperty($"charaWork.battleSave.skillLevel[{classId - 1}]");
|
||||||
|
expPropertyPacket2.AddProperty($"charaWork.parameterSave.state_mainSkillLevel");
|
||||||
|
QueuePackets(expPropertyPacket2.Done());
|
||||||
|
QueuePackets(expPropertyPacket3.Done());
|
||||||
|
//play levelup animation (do this outside LevelUp so that it only plays once if multiple levels are earned
|
||||||
|
//also i dunno how to do this
|
||||||
|
}
|
||||||
|
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($"charaWork.battleSave.skillPoint[{classId - 1}]");
|
||||||
|
|
||||||
|
//Cap experience for level 50
|
||||||
|
QueuePackets(expPropertyPacket.Done());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LevelUp(byte classId)
|
||||||
|
{
|
||||||
|
if (charaWork.battleSave.skillLevel[classId - 1] < charaWork.battleSave.skillLevelCap[classId])
|
||||||
|
{
|
||||||
|
//Increase level
|
||||||
|
charaWork.battleSave.skillLevel[classId - 1]++;
|
||||||
|
charaWork.parameterSave.state_mainSkillLevel++;
|
||||||
|
|
||||||
|
SendGameMessage(this, Server.GetWorldManager().GetActor(), 33909, 0x44, this, 0, 0, 0, 0, 0, 0, 0, 0, 0, (int) GetLevel());
|
||||||
|
//If there's an ability that unlocks at this level, equip it.
|
||||||
|
uint commandId = Server.GetWorldManager().GetBattleCommandIdByLevel(classId, GetLevel());
|
||||||
|
if (commandId > 0)
|
||||||
|
{
|
||||||
|
EquipAbilityInFirstOpenSlot(classId, commandId, false);
|
||||||
|
byte jobId = ConvertClassIdToJobId(classId);
|
||||||
|
if (jobId != classId)
|
||||||
|
EquipAbilityInFirstOpenSlot(jobId, commandId, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 += 10;
|
||||||
|
break;
|
||||||
|
case CLASSID_THM:
|
||||||
|
case CLASSID_CNJ:
|
||||||
|
jobId += 4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return jobId;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,8 +10,10 @@ function onEventStarted(player, equipAbilityWidget, triggername, slot, commandid
|
||||||
local worldManager = GetWorldManager();
|
local worldManager = GetWorldManager();
|
||||||
local ability = worldManager:GetBattleCommand(commandid);
|
local ability = worldManager:GetBattleCommand(commandid);
|
||||||
|
|
||||||
|
|
||||||
--Equip
|
--Equip
|
||||||
if (commandid > 0) then
|
if (commandid > 0) then
|
||||||
|
--[[]]
|
||||||
--Can the player equip any more cross class actions
|
--Can the player equip any more cross class actions
|
||||||
if (player.charaWork.parameterTemp.otherClassAbilityCount[0] >= player.charaWork.parameterTemp.otherClassAbilityCount[1]) then
|
if (player.charaWork.parameterTemp.otherClassAbilityCount[0] >= player.charaWork.parameterTemp.otherClassAbilityCount[1]) then
|
||||||
--"You cannot set any more actions."
|
--"You cannot set any more actions."
|
||||||
|
@ -21,28 +23,63 @@ function onEventStarted(player, equipAbilityWidget, triggername, slot, commandid
|
||||||
end
|
end
|
||||||
|
|
||||||
--Is the player high enough level in that class to equip the ability
|
--Is the player high enough level in that class to equip the ability
|
||||||
if (player.charaWork.battleSave.skillLevel[ability.job] < ability.level) then
|
if (player.charaWork.battleSave.skillLevel[ability.job - 1] < ability.level) then
|
||||||
|
--"You have not yet acquired that action."
|
||||||
--"You have not yet acquired that action"
|
|
||||||
player:SendGameMessage(GetWorldMaster(), 30742, 0x20, 0, 0);
|
player:SendGameMessage(GetWorldMaster(), 30742, 0x20, 0, 0);
|
||||||
player:endEvent();
|
player:endEvent();
|
||||||
return;
|
return;
|
||||||
end
|
end
|
||||||
|
|
||||||
--Equip the ability
|
|
||||||
player:EquipAbility(slot, commandid);
|
local oldSlot = player:FindFirstCommandSlotById(commandid);
|
||||||
|
local isEquipped = oldSlot < player.charaWork.commandBorder + 30;
|
||||||
|
--If slot is 0, find the first open slot
|
||||||
|
if (slot == 0) then
|
||||||
|
--If the ability is already equipped and slot is 0, then it can't be equipped again
|
||||||
|
--If the slot isn't 0, it's a move or a swap command
|
||||||
|
if (isEquipped == true) then
|
||||||
|
--"That action is already set to an action slot."
|
||||||
|
player:SendGameMessage(GetWorldMaster(), 30719, 0x20, 0);
|
||||||
|
player:endEvent();
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
|
||||||
|
slot = player:FindFirstCommandSlotById(0) - player.charaWork.commandBorder;
|
||||||
|
|
||||||
|
--If the first open slot is outside the hotbar, then the hotbar is full
|
||||||
|
if(slot >= 30) then
|
||||||
|
--"You cannot set any more actions."
|
||||||
|
player:SendGameMessage(Server.GetWorldManager().GetActor(), 30720, 0x20, 0);
|
||||||
|
player:endEvent();
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
slot = slot - 1;
|
||||||
|
end
|
||||||
|
|
||||||
|
if(isEquipped == true) then
|
||||||
|
player:SwapAbilities(oldSlot, slot + player.charaWork.commandBorder);
|
||||||
|
else
|
||||||
|
local tslot = slot + player.charaWork.commandBorder;
|
||||||
|
player:EquipAbility(player.GetJob(), commandid, tslot, true);
|
||||||
|
end
|
||||||
|
|
||||||
--Unequip
|
--Unequip
|
||||||
elseif (commandid == 0) then
|
elseif (commandid == 0) then
|
||||||
commandid = player.charaWork.command[slot + player.charaWork.commandBorder];
|
commandid = player.charaWork.command[slot + player.charaWork.commandBorder - 1];
|
||||||
|
ability = worldManager.GetBattleCommand(commandid);
|
||||||
--Is the ability a part of the player's current class?
|
--Is the ability a part of the player's current class?
|
||||||
--This check isn't correct because of jobs having different ids
|
--This check isn't correct because of jobs having different ids
|
||||||
if(worldManager:GetBattleCommand(commandid).job == player.charaWork.parameterSave.state_mainSkill[0]) then
|
local classId = player:GetJob();
|
||||||
--"Actions of your current class or job cannot be removed."
|
local jobId = player:ConvertClassIdToJobId(classId);
|
||||||
player:SendGameMessage(GetWorldMaster(), 30745, 0x20, 0, 0);
|
|
||||||
|
if(ability.job == classId or ability.job == jobId) then
|
||||||
|
--"Actions of your current class or job cannot be removed."
|
||||||
|
player:SendGameMessage(GetWorldMaster(), 30745, 0x20, 0, 0);
|
||||||
elseif (commandid != 0) then
|
elseif (commandid != 0) then
|
||||||
player:UnequipAbility(slot);
|
player:UnequipAbility(slot);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
player:endEvent();
|
player:endEvent();
|
||||||
end
|
end
|
34
data/scripts/commands/gm/giveexp.lua
Normal file
34
data/scripts/commands/gm/giveexp.lua
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
require("global");
|
||||||
|
|
||||||
|
properties = {
|
||||||
|
permissions = 0,
|
||||||
|
parameters = "sss",
|
||||||
|
description =
|
||||||
|
[[
|
||||||
|
Adds experience <qty> to player or <targetname>.
|
||||||
|
!giveexp <qty> |
|
||||||
|
!giveexp <qty> <targetname> |
|
||||||
|
]],
|
||||||
|
}
|
||||||
|
|
||||||
|
function onTrigger(player, argc, qty, name, lastName)
|
||||||
|
local sender = "[giveexp] ";
|
||||||
|
|
||||||
|
if name then
|
||||||
|
if lastName then
|
||||||
|
player = GetWorldManager():GetPCInWorld(name.." "..lastName) or nil;
|
||||||
|
else
|
||||||
|
player = GetWorldManager():GetPCInWorld(name) or nil;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if player then
|
||||||
|
currency = 1000001;
|
||||||
|
qty = tonumber(qty) or 1;
|
||||||
|
location = INVENTORY_CURRENCY;
|
||||||
|
|
||||||
|
player:AddExp(qty, player.charaWork.parameterSave.state_mainSkill[0], 5);
|
||||||
|
else
|
||||||
|
print(sender.."unable to add experience, ensure player name is valid.");
|
||||||
|
end;
|
||||||
|
end;
|
Loading…
Add table
Reference in a new issue