1
Fork 0
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:
yogurt 2017-09-27 18:10:22 -05:00
parent 56491266cc
commit 33f8709d76
7 changed files with 333 additions and 30 deletions

View file

@ -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;
} }
} }

View file

@ -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;
}
} }
} }

View file

@ -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;

View file

@ -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;

View file

@ -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;
}
} }
} }

View file

@ -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

View 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;