From 33f8709d765e3aa97a19cdd72f63a96ee99520ea Mon Sep 17 00:00:00 2001 From: yogurt Date: Wed, 27 Sep 2017 18:10:22 -0500 Subject: [PATCH 1/9] 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. --- FFXIVClassic Map Server/Database.cs | 66 +++++- FFXIVClassic Map Server/WorldManager.cs | 9 +- .../actors/chara/BattleSave.cs | 2 +- .../actors/chara/CharaWork.cs | 2 +- .../actors/chara/player/Player.cs | 191 +++++++++++++++++- data/scripts/commands/EquipAbilityCommand.lua | 59 +++++- data/scripts/commands/gm/giveexp.lua | 34 ++++ 7 files changed, 333 insertions(+), 30 deletions(-) create mode 100644 data/scripts/commands/gm/giveexp.lua diff --git a/FFXIVClassic Map Server/Database.cs b/FFXIVClassic Map Server/Database.cs index 995cdf20..643bda61 100644 --- a/FFXIVClassic Map Server/Database.cs +++ b/FFXIVClassic Map Server/Database.cs @@ -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 if (commandId > 2700083200) @@ -1245,7 +1245,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("@classId", classId); cmd.Parameters.AddWithValue("@commandId", commandId); cmd.Parameters.AddWithValue("@hotbarSlot", hotbarSlot); 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> hotbarList = new List>(); + 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 GetInventory(Player player, uint slotOffset, uint type) { List items = new List(); @@ -2146,9 +2197,9 @@ namespace FFXIVClassic_Map_Server } } - public static Dictionary LoadGlobalBattleCommandList() + public static void LoadGlobalBattleCommandList(Dictionary battleCommandDict, Dictionary, uint> battleCommandIdByLevel) { - var battleCommands = new Dictionary(); + //var battleCommands = new Dictionary(); 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.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(battleCommand.job, battleCommand.level), id | 0xA0F00000); } } } @@ -2208,7 +2263,6 @@ namespace FFXIVClassic_Map_Server conn.Dispose(); } } - return battleCommands; } } diff --git a/FFXIVClassic Map Server/WorldManager.cs b/FFXIVClassic Map Server/WorldManager.cs index 065955f4..47a61226 100644 --- a/FFXIVClassic Map Server/WorldManager.cs +++ b/FFXIVClassic Map Server/WorldManager.cs @@ -40,6 +40,7 @@ namespace FFXIVClassic_Map_Server private Dictionary currentPlayerParties = new Dictionary(); //GroupId, Party object private Dictionary statusEffectList = new Dictionary(); private Dictionary battleCommandList = new Dictionary(); + private Dictionary, uint> battleCommandIdByLevel = new Dictionary, uint>();//Holds battle command ids keyed by class id and level (in that order) private Dictionary battleNpcGenusMods = new Dictionary(); private Dictionary battleNpcPoolMods = new Dictionary(); private Dictionary battleNpcSpawnMods = new Dictionary(); @@ -1422,7 +1423,7 @@ namespace FFXIVClassic_Map_Server public void LoadBattleCommands() { - battleCommandList = Database.LoadGlobalBattleCommandList(); + Database.LoadGlobalBattleCommandList(battleCommandList, battleCommandIdByLevel); } public BattleCommand GetBattleCommand(uint id) @@ -1430,5 +1431,11 @@ namespace FFXIVClassic_Map_Server BattleCommand battleCommand; 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; + } } } diff --git a/FFXIVClassic Map Server/actors/chara/BattleSave.cs b/FFXIVClassic Map Server/actors/chara/BattleSave.cs index bf9a6000..8d2928e4 100644 --- a/FFXIVClassic Map Server/actors/chara/BattleSave.cs +++ b/FFXIVClassic Map Server/actors/chara/BattleSave.cs @@ -5,7 +5,7 @@ public float potencial = 6.6f; public short[] skillLevel = 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 int physicalExp; diff --git a/FFXIVClassic Map Server/actors/chara/CharaWork.cs b/FFXIVClassic Map Server/actors/chara/CharaWork.cs index 652178d6..45afc964 100644 --- a/FFXIVClassic Map Server/actors/chara/CharaWork.cs +++ b/FFXIVClassic Map Server/actors/chara/CharaWork.cs @@ -23,7 +23,7 @@ public uint[] command = new uint[64]; //ACTORS public byte[] commandCategory = new byte[64]; public byte commandBorder = 0x20; - public bool[] commandAcquired = new bool[4096]; + public bool[] commandAcquired = new bool[4096]; public bool[] additionalCommandAcquired = new bool[36]; public uint currentContentGroup; diff --git a/FFXIVClassic Map Server/actors/chara/player/Player.cs b/FFXIVClassic Map Server/actors/chara/player/Player.cs index fab60a05..2c139abd 100644 --- a/FFXIVClassic Map Server/actors/chara/player/Player.cs +++ b/FFXIVClassic Map Server/actors/chara/player/Player.cs @@ -956,11 +956,11 @@ namespace FFXIVClassic_Map_Server.Actors //Calculate hp/mp //Get Potenciel ?????? - + //Set HP/MP/TP PARAMS //Set mainskill and level - + //Set Parameters //Set current EXP @@ -972,7 +972,6 @@ namespace FFXIVClassic_Map_Server.Actors //Check if bonus point available... set //Set rested EXP - charaWork.parameterSave.state_mainSkill[0] = classId; charaWork.parameterSave.state_mainSkillLevel = charaWork.battleSave.skillLevel[classId-1]; playerWork.restBonusExpRate = 0.0f; @@ -1846,7 +1845,89 @@ namespace FFXIVClassic_Map_Server.Actors 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 slotsToUpdate = new List(); + + //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 slotsToUpdate = new List(); + slotsToUpdate.Add(hotbarSlot1); + slotsToUpdate.Add(hotbarSlot2); + UpdateHotbar(slotsToUpdate); + } + + public void EquipAbility(ushort hotbarSlot, uint commandId) { var ability = Server.GetWorldManager().GetBattleCommand(commandId); 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.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]); + 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); } @@ -1897,11 +1978,11 @@ namespace FFXIVClassic_Map_Server.Actors charaWork.parameterSave.commandSlot_recastTime[trueHotbarSlot - charaWork.commandBorder] = recastEnd; 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." if (!isAlreadyEquipped) - SendGameMessage(Server.GetWorldManager().GetActor(), 30603, 0x20, 0, commandId); + SendGameMessage(Server.GetWorldManager().GetActor(), 30603, 0x20, 0, commandId ^ 0xA0F00000); } //Ability is already equipped 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 slotsToUpdate = new List(); ushort trueHotbarSlot = (ushort)(hotbarSlot + charaWork.commandBorder - 1); @@ -1928,14 +2009,16 @@ namespace FFXIVClassic_Map_Server.Actors Database.UnequipAbility(this, (ushort)(trueHotbarSlot - charaWork.commandBorder)); charaWork.command[trueHotbarSlot] = 0; 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); } //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) + public ushort FindFirstCommandSlotById(uint commandId) { if(commandId != 0) commandId |= 0xA0F00000; @@ -2200,5 +2283,93 @@ namespace FFXIVClassic_Map_Server.Actors // todo: this really shouldnt be called on each ws? 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; + } } } diff --git a/data/scripts/commands/EquipAbilityCommand.lua b/data/scripts/commands/EquipAbilityCommand.lua index e11e5d27..6b2251d8 100644 --- a/data/scripts/commands/EquipAbilityCommand.lua +++ b/data/scripts/commands/EquipAbilityCommand.lua @@ -10,8 +10,10 @@ function onEventStarted(player, equipAbilityWidget, triggername, slot, commandid 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." @@ -19,30 +21,65 @@ function onEventStarted(player, equipAbilityWidget, triggername, slot, commandid 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" + if (player.charaWork.battleSave.skillLevel[ability.job - 1] < 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); + + 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 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? --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); + local classId = player:GetJob(); + local jobId = player:ConvertClassIdToJobId(classId); + + 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 player:UnequipAbility(slot); end end + player:endEvent(); end \ No newline at end of file diff --git a/data/scripts/commands/gm/giveexp.lua b/data/scripts/commands/gm/giveexp.lua new file mode 100644 index 00000000..d27366ca --- /dev/null +++ b/data/scripts/commands/gm/giveexp.lua @@ -0,0 +1,34 @@ +require("global"); + +properties = { + permissions = 0, + parameters = "sss", + description = +[[ +Adds experience to player or . +!giveexp | +!giveexp | +]], +} + +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; \ No newline at end of file From ab98f3662faa1ff6993b7279b5f62d00d43063e4 Mon Sep 17 00:00:00 2001 From: yogurt Date: Wed, 27 Sep 2017 18:12:02 -0500 Subject: [PATCH 2/9] Removed old EquipAbility function from player.cs --- .../actors/chara/player/Player.cs | 74 ------------------- 1 file changed, 74 deletions(-) diff --git a/FFXIVClassic Map Server/actors/chara/player/Player.cs b/FFXIVClassic Map Server/actors/chara/player/Player.cs index 2c139abd..8876c08f 100644 --- a/FFXIVClassic Map Server/actors/chara/player/Player.cs +++ b/FFXIVClassic Map Server/actors/chara/player/Player.cs @@ -1927,80 +1927,6 @@ namespace FFXIVClassic_Map_Server.Actors UpdateHotbar(slotsToUpdate); } - public void EquipAbility(ushort hotbarSlot, uint 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) - { - //If the ability is already equipped, we can't add it to the hotbar again. - if (isAlreadyEquipped) - canEquip = false; - else - trueHotbarSlot = FindFirstCommandSlotById(0); - } - //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) - { - //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, charaWork.parameterSave.state_mainSkill[0], (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, charaWork.parameterSave.state_mainSkill[0], (ushort) (trueHotbarSlot - charaWork.commandBorder), trueCommandId, recastEnd); - - //"[Command] set." - if (!isAlreadyEquipped) - SendGameMessage(Server.GetWorldManager().GetActor(), 30603, 0x20, 0, commandId ^ 0xA0F00000); - } - //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, bool printMessage = true) { List slotsToUpdate = new List(); From 5dfbc0f249eb7af40ac5ef7376c02827808b2bc5 Mon Sep 17 00:00:00 2001 From: yogurt Date: Sat, 30 Sep 2017 07:28:08 -0500 Subject: [PATCH 3/9] EXP and levels now get saved and loaded from database, changed battlecommand id dictionary to hold lists to account for archer and DoH/DoLs getting multiple abilities at certain levels. Level 1 abilities are now added to the hotbar on character creation. --- FFXIVClassic Lobby Server/Database.cs | 42 +++++- FFXIVClassic Map Server/Database.cs | 141 +++++++++++++++++- FFXIVClassic Map Server/WorldManager.cs | 8 +- .../actors/chara/player/Player.cs | 71 ++++++--- .../utils/CharacterUtils.cs | 26 ++++ 5 files changed, 254 insertions(+), 34 deletions(-) diff --git a/FFXIVClassic Lobby Server/Database.cs b/FFXIVClassic Lobby Server/Database.cs index deb776b4..dce95d6b 100644 --- a/FFXIVClassic Lobby Server/Database.cs +++ b/FFXIVClassic Lobby Server/Database.cs @@ -231,15 +231,51 @@ namespace FFXIVClassic_Lobby_Server catch (MySqlException e) { Program.Log.Error(e.ToString()); - + conn.Dispose(); + return; + } + //Create Hotbar + try + { + MySqlCommand cmd = new MySqlCommand(); + cmd.Connection = conn; + cmd.CommandText = "SELECT id FROM server_battle_commands WHERE classJob = @classjob AND lvl = 1 ORDER BY id DESC"; + cmd.Prepare(); + + cmd.Parameters.AddWithValue("@classJob", charaInfo.currentClass); + List defaultActions = new List(); + using (var reader = cmd.ExecuteReader()) + { + while(reader.Read()) + { + defaultActions.Add(reader.GetUInt32("id")); + } + } + MySqlCommand cmd2 = new MySqlCommand(); + cmd2.Connection = conn; + cmd2.CommandText = "INSERT INTO characters_hotbar (characterId, classId, hotbarSlot, commandId, recastTime) VALUES (@characterId, @classId, @hotbarSlot, @commandId, 0)"; + cmd2.Prepare(); + cmd2.Parameters.AddWithValue("@characterId", cid); + cmd2.Parameters.AddWithValue("@classId", charaInfo.currentClass); + cmd2.Parameters.Add("@hotbarSlot", MySqlDbType.Int16); + cmd2.Parameters.Add("@commandId", MySqlDbType.Int16); + + for(int i = 0; i < defaultActions.Count; i++) + { + cmd2.Parameters["@hotbarSlot"].Value = i; + cmd2.Parameters["@commandId"].Value = defaultActions[i]; + cmd2.ExecuteNonQuery(); + } + } + catch(MySqlException e) + { + Program.Log.Error(e.ToString()); } finally { conn.Dispose(); } - - } Program.Log.Debug("[SQL] CID={0} state updated to active(2).", cid); diff --git a/FFXIVClassic Map Server/Database.cs b/FFXIVClassic Map Server/Database.cs index 643bda61..2aeb81f2 100644 --- a/FFXIVClassic Map Server/Database.cs +++ b/FFXIVClassic Map Server/Database.cs @@ -785,6 +785,62 @@ namespace FFXIVClassic_Map_Server } } + //Get class experience + query = @" + SELECT + pug, + gla, + mrd, + arc, + lnc, + + thm, + cnj, + + crp, + bsm, + arm, + gsm, + ltw, + wvr, + alc, + cul, + + min, + btn, + fsh + FROM characters_class_exp WHERE characterId = @charId"; + + cmd = new MySqlCommand(query, conn); + cmd.Parameters.AddWithValue("@charId", player.actorId); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + if (reader.Read()) + { + player.charaWork.battleSave.skillPoint[Player.CLASSID_PUG - 1] = reader.GetInt16("pug"); + player.charaWork.battleSave.skillPoint[Player.CLASSID_GLA - 1] = reader.GetInt16("gla"); + player.charaWork.battleSave.skillPoint[Player.CLASSID_MRD - 1] = reader.GetInt16("mrd"); + player.charaWork.battleSave.skillPoint[Player.CLASSID_ARC - 1] = reader.GetInt16("arc"); + player.charaWork.battleSave.skillPoint[Player.CLASSID_LNC - 1] = reader.GetInt16("lnc"); + + player.charaWork.battleSave.skillPoint[Player.CLASSID_THM - 1] = reader.GetInt16("thm"); + player.charaWork.battleSave.skillPoint[Player.CLASSID_CNJ - 1] = reader.GetInt16("cnj"); + + player.charaWork.battleSave.skillPoint[Player.CLASSID_CRP - 1] = reader.GetInt16("crp"); + player.charaWork.battleSave.skillPoint[Player.CLASSID_BSM - 1] = reader.GetInt16("bsm"); + player.charaWork.battleSave.skillPoint[Player.CLASSID_ARM - 1] = reader.GetInt16("arm"); + player.charaWork.battleSave.skillPoint[Player.CLASSID_GSM - 1] = reader.GetInt16("gsm"); + player.charaWork.battleSave.skillPoint[Player.CLASSID_LTW - 1] = reader.GetInt16("ltw"); + player.charaWork.battleSave.skillPoint[Player.CLASSID_WVR - 1] = reader.GetInt16("wvr"); + player.charaWork.battleSave.skillPoint[Player.CLASSID_ALC - 1] = reader.GetInt16("alc"); + player.charaWork.battleSave.skillPoint[Player.CLASSID_CUL - 1] = reader.GetInt16("cul"); + + player.charaWork.battleSave.skillPoint[Player.CLASSID_MIN - 1] = reader.GetInt16("min"); + player.charaWork.battleSave.skillPoint[Player.CLASSID_BTN - 1] = reader.GetInt16("btn"); + player.charaWork.battleSave.skillPoint[Player.CLASSID_FSH - 1] = reader.GetInt16("fsh"); + } + } + //Load Saved Parameters query = @" SELECT @@ -1327,7 +1383,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("@classId", player.GetCurrentClassOrJob()); player.charaWork.commandBorder = 32; @@ -2197,10 +2253,8 @@ namespace FFXIVClassic_Map_Server } } - public static void LoadGlobalBattleCommandList(Dictionary battleCommandDict, Dictionary, uint> battleCommandIdByLevel) + public static void LoadGlobalBattleCommandList(Dictionary battleCommandDict, Dictionary, List> battleCommandIdByLevel) { - //var battleCommands = new Dictionary(); - 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 @@ -2248,9 +2302,16 @@ namespace FFXIVClassic_Map_Server 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(battleCommand.job, battleCommand.level), id | 0xA0F00000); + Tuple tuple = Tuple.Create(battleCommand.job, battleCommand.level); + if (battleCommandIdByLevel.ContainsKey(tuple)) + { + battleCommandIdByLevel[tuple].Add(id | 0xA0F00000); + } + else + { + List list = new List() { id | 0xA0F00000 }; + battleCommandIdByLevel.Add(tuple, list); + } } } } @@ -2264,6 +2325,72 @@ namespace FFXIVClassic_Map_Server } } } + + public static void SetExp(Player player, byte classId, int exp) + { + 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(); + + var query = String.Format(@" + UPDATE characters_class_exp + SET + {0} = @exp + WHERE + characterId = @characterId", CharacterUtils.GetClassNameForId(classId)); + MySqlCommand cmd = new MySqlCommand(query, conn); + + cmd.Prepare(); + cmd = new MySqlCommand(query, conn); + cmd.Parameters.AddWithValue("@characterId", player.actorId); + cmd.Parameters.AddWithValue("@exp", exp); + cmd.ExecuteNonQuery(); + } + catch (MySqlException e) + { + Program.Log.Error(e.ToString()); + } + finally + { + conn.Dispose(); + } + } + } + + public static void SetLevel(Player player, byte classId, short level) + { + 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(); + + var query = String.Format(@" + UPDATE characters_class_levels + SET + {0} = @lvl + WHERE + characterId = @characterId", CharacterUtils.GetClassNameForId(classId)); + MySqlCommand cmd = new MySqlCommand(query, conn); + + cmd.Prepare(); + cmd = new MySqlCommand(query, conn); + cmd.Parameters.AddWithValue("@characterId", player.actorId); + cmd.Parameters.AddWithValue("@lvl", level); + cmd.ExecuteNonQuery(); + } + catch (MySqlException e) + { + Program.Log.Error(e.ToString()); + } + finally + { + conn.Dispose(); + } + } + } } } diff --git a/FFXIVClassic Map Server/WorldManager.cs b/FFXIVClassic Map Server/WorldManager.cs index 47a61226..2e88ee53 100644 --- a/FFXIVClassic Map Server/WorldManager.cs +++ b/FFXIVClassic Map Server/WorldManager.cs @@ -40,7 +40,7 @@ namespace FFXIVClassic_Map_Server private Dictionary currentPlayerParties = new Dictionary(); //GroupId, Party object private Dictionary statusEffectList = new Dictionary(); private Dictionary battleCommandList = new Dictionary(); - private Dictionary, uint> battleCommandIdByLevel = new Dictionary, uint>();//Holds battle command ids keyed by class id and level (in that order) + private Dictionary, List> battleCommandIdByLevel = new Dictionary, List>();//Holds battle command ids keyed by class id and level (in that order) private Dictionary battleNpcGenusMods = new Dictionary(); private Dictionary battleNpcPoolMods = new Dictionary(); private Dictionary battleNpcSpawnMods = new Dictionary(); @@ -1432,10 +1432,10 @@ namespace FFXIVClassic_Map_Server return battleCommandList.TryGetValue((ushort)id, out battleCommand) ? battleCommand.Clone() : null; } - public uint GetBattleCommandIdByLevel(byte classId, short level) + public List GetBattleCommandIdByLevel(byte classId, short level) { - uint id = 0; - return battleCommandIdByLevel.TryGetValue(Tuple.Create(classId, level), out id) ? id : 0; + List ids; + return battleCommandIdByLevel.TryGetValue(Tuple.Create(classId, level), out ids) ? ids : new List(); } } } diff --git a/FFXIVClassic Map Server/actors/chara/player/Player.cs b/FFXIVClassic Map Server/actors/chara/player/Player.cs index 8876c08f..4dca7286 100644 --- a/FFXIVClassic Map Server/actors/chara/player/Player.cs +++ b/FFXIVClassic Map Server/actors/chara/player/Player.cs @@ -387,13 +387,30 @@ namespace FFXIVClassic_Map_Server.Actors propPacketUtil.AddProperty("charaWork.battleTemp.castGauge_speed[0]"); propPacketUtil.AddProperty("charaWork.battleTemp.castGauge_speed[1]"); - + //Battle Save Skillpoint - + propPacketUtil.AddProperty($"charaWork.battleSave.skillPoint[{CLASSID_ALC - 1}]"); + propPacketUtil.AddProperty($"charaWork.battleSave.skillPoint[{CLASSID_ARC - 1}]"); + propPacketUtil.AddProperty($"charaWork.battleSave.skillPoint[{CLASSID_ARM - 1}]"); + propPacketUtil.AddProperty($"charaWork.battleSave.skillPoint[{CLASSID_BSM - 1}]"); + propPacketUtil.AddProperty($"charaWork.battleSave.skillPoint[{CLASSID_BTN - 1}]"); + propPacketUtil.AddProperty($"charaWork.battleSave.skillPoint[{CLASSID_CNJ - 1}]"); + propPacketUtil.AddProperty($"charaWork.battleSave.skillPoint[{CLASSID_CRP - 1}]"); + propPacketUtil.AddProperty($"charaWork.battleSave.skillPoint[{CLASSID_CUL - 1}]"); + propPacketUtil.AddProperty($"charaWork.battleSave.skillPoint[{CLASSID_FSH - 1}]"); + propPacketUtil.AddProperty($"charaWork.battleSave.skillPoint[{CLASSID_GLA - 1}]"); + propPacketUtil.AddProperty($"charaWork.battleSave.skillPoint[{CLASSID_GSM - 1}]"); + propPacketUtil.AddProperty($"charaWork.battleSave.skillPoint[{CLASSID_LNC - 1}]"); + propPacketUtil.AddProperty($"charaWork.battleSave.skillPoint[{CLASSID_LTW - 1}]"); + propPacketUtil.AddProperty($"charaWork.battleSave.skillPoint[{CLASSID_MIN - 1}]"); + propPacketUtil.AddProperty($"charaWork.battleSave.skillPoint[{CLASSID_MRD - 1}]"); + propPacketUtil.AddProperty($"charaWork.battleSave.skillPoint[{CLASSID_PUG - 1}]"); + propPacketUtil.AddProperty($"charaWork.battleSave.skillPoint[{CLASSID_THM - 1}]"); + propPacketUtil.AddProperty($"charaWork.battleSave.skillPoint[{CLASSID_WVR - 1}]"); + //Commands propPacketUtil.AddProperty("charaWork.commandBorder"); - for (int i = 0; i < charaWork.command.Length; i++) { if (charaWork.command[i] != 0) @@ -407,7 +424,6 @@ namespace FFXIVClassic_Map_Server.Actors } } } - for (int i = 0; i < charaWork.commandCategory.Length; i++) { @@ -421,7 +437,6 @@ namespace FFXIVClassic_Map_Server.Actors if (charaWork.commandAcquired[i] != false) propPacketUtil.AddProperty(String.Format("charaWork.commandAcquired[{0}]", i)); } - for (int i = 0; i < charaWork.additionalCommandAcquired.Length; i++) { @@ -436,13 +451,11 @@ namespace FFXIVClassic_Map_Server.Actors 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)); - } - */ + 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]"); @@ -2212,14 +2225,14 @@ namespace FFXIVClassic_Map_Server.Actors //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 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 @@ -2243,14 +2256,17 @@ namespace FFXIVClassic_Map_Server.Actors 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 + + Database.SetLevel(this, classId, GetLevel()); } + //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($"charaWork.battleSave.skillPoint[{classId - 1}]"); - //Cap experience for level 50 - QueuePackets(expPropertyPacket.Done()); + QueuePackets(expPropertyPacket.Done()); + Database.SetExp(this, classId, charaWork.battleSave.skillPoint[classId - 1]); } public void LevelUp(byte classId) @@ -2263,12 +2279,12 @@ namespace FFXIVClassic_Map_Server.Actors 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) + List commandIds = Server.GetWorldManager().GetBattleCommandIdByLevel(classId, GetLevel()); + foreach(uint commandId in commandIds) { EquipAbilityInFirstOpenSlot(classId, commandId, false); byte jobId = ConvertClassIdToJobId(classId); - if (jobId != classId) + if (jobId != classId) EquipAbilityInFirstOpenSlot(jobId, commandId, false); } } @@ -2287,7 +2303,7 @@ namespace FFXIVClassic_Map_Server.Actors break; case CLASSID_ARC: case CLASSID_LNC: - jobId += 10; + jobId += 11; break; case CLASSID_THM: case CLASSID_CNJ: @@ -2297,5 +2313,20 @@ namespace FFXIVClassic_Map_Server.Actors return jobId; } + + public void SetCurrentJob(byte jobId) + { + currentJob = jobId; + BroadcastPacket(SetCurrentJobPacket.BuildPacket(actorId, jobId), true); + Database.LoadHotbar(this); + } + + public byte GetCurrentClassOrJob() + { + if (currentJob != 0) + return (byte) currentJob; + + return charaWork.parameterSave.state_mainSkill[0]; + } } } diff --git a/FFXIVClassic Map Server/utils/CharacterUtils.cs b/FFXIVClassic Map Server/utils/CharacterUtils.cs index 3df2bc6a..b420b5fa 100644 --- a/FFXIVClassic Map Server/utils/CharacterUtils.cs +++ b/FFXIVClassic Map Server/utils/CharacterUtils.cs @@ -96,5 +96,31 @@ namespace FFXIVClassic_Map_Server.utils } } + public static string GetClassNameForId(short id) + { + switch (id) + { + case 2: return "pug"; + case 3: return "gla"; + case 4: return "mrd"; + case 7: return "arc"; + case 8: return "lnc"; + case 22: return "thm"; + case 23: return "cnj"; + case 29: return "crp"; + case 30: return "bsm"; + case 31: return "arm"; + case 32: return "gsm"; + case 33: return "ltw"; + case 34: return "wvr"; + case 35: return "alc"; + case 36: return "cul"; + case 39: return "min"; + case 40: return "btn"; + case 41: return "fsh"; + default: return "undefined"; + } + } + } } From f3a823af03435c5e1b14b5a07c25a9de19790a1a Mon Sep 17 00:00:00 2001 From: yogurt Date: Sat, 30 Sep 2017 20:04:45 -0500 Subject: [PATCH 4/9] Only send current class's exp on login. Exp now updates on class change --- .../actors/chara/player/Player.cs | 22 +++---------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/FFXIVClassic Map Server/actors/chara/player/Player.cs b/FFXIVClassic Map Server/actors/chara/player/Player.cs index 4dca7286..56010d9f 100644 --- a/FFXIVClassic Map Server/actors/chara/player/Player.cs +++ b/FFXIVClassic Map Server/actors/chara/player/Player.cs @@ -389,24 +389,7 @@ namespace FFXIVClassic_Map_Server.Actors propPacketUtil.AddProperty("charaWork.battleTemp.castGauge_speed[1]"); //Battle Save Skillpoint - propPacketUtil.AddProperty($"charaWork.battleSave.skillPoint[{CLASSID_ALC - 1}]"); - propPacketUtil.AddProperty($"charaWork.battleSave.skillPoint[{CLASSID_ARC - 1}]"); - propPacketUtil.AddProperty($"charaWork.battleSave.skillPoint[{CLASSID_ARM - 1}]"); - propPacketUtil.AddProperty($"charaWork.battleSave.skillPoint[{CLASSID_BSM - 1}]"); - propPacketUtil.AddProperty($"charaWork.battleSave.skillPoint[{CLASSID_BTN - 1}]"); - propPacketUtil.AddProperty($"charaWork.battleSave.skillPoint[{CLASSID_CNJ - 1}]"); - propPacketUtil.AddProperty($"charaWork.battleSave.skillPoint[{CLASSID_CRP - 1}]"); - propPacketUtil.AddProperty($"charaWork.battleSave.skillPoint[{CLASSID_CUL - 1}]"); - propPacketUtil.AddProperty($"charaWork.battleSave.skillPoint[{CLASSID_FSH - 1}]"); - propPacketUtil.AddProperty($"charaWork.battleSave.skillPoint[{CLASSID_GLA - 1}]"); - propPacketUtil.AddProperty($"charaWork.battleSave.skillPoint[{CLASSID_GSM - 1}]"); - propPacketUtil.AddProperty($"charaWork.battleSave.skillPoint[{CLASSID_LNC - 1}]"); - propPacketUtil.AddProperty($"charaWork.battleSave.skillPoint[{CLASSID_LTW - 1}]"); - propPacketUtil.AddProperty($"charaWork.battleSave.skillPoint[{CLASSID_MIN - 1}]"); - propPacketUtil.AddProperty($"charaWork.battleSave.skillPoint[{CLASSID_MRD - 1}]"); - propPacketUtil.AddProperty($"charaWork.battleSave.skillPoint[{CLASSID_PUG - 1}]"); - propPacketUtil.AddProperty($"charaWork.battleSave.skillPoint[{CLASSID_THM - 1}]"); - propPacketUtil.AddProperty($"charaWork.battleSave.skillPoint[{CLASSID_WVR - 1}]"); + propPacketUtil.AddProperty($"charaWork.battleSave.skillPoint[{charaWork.parameterSave.state_mainSkill[0] - 1}]"); //Commands propPacketUtil.AddProperty("charaWork.commandBorder"); @@ -1000,7 +983,8 @@ namespace FFXIVClassic_Map_Server.Actors propertyBuilder.AddProperty("charaWork.parameterSave.state_mainSkillLevel"); propertyBuilder.NewTarget("playerWork/expBonus"); propertyBuilder.AddProperty("playerWork.restBonusExpRate"); - + propertyBuilder.NewTarget("charaWork/battleStateForSelf"); + propertyBuilder.AddProperty($"charaWork.battleSave.skillPoint[{classId - 1}]"); Database.LoadHotbar(this); var time = Utils.UnixTimeStampUTC(); From 116a573f85c4448e683af5b7d66c237920bc819a Mon Sep 17 00:00:00 2001 From: yogurt Date: Fri, 6 Oct 2017 20:45:10 -0500 Subject: [PATCH 5/9] Save class/level parameter save info on level up --- FFXIVClassic Map Server/actors/chara/player/Player.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/FFXIVClassic Map Server/actors/chara/player/Player.cs b/FFXIVClassic Map Server/actors/chara/player/Player.cs index 56010d9f..0579e523 100644 --- a/FFXIVClassic Map Server/actors/chara/player/Player.cs +++ b/FFXIVClassic Map Server/actors/chara/player/Player.cs @@ -2219,6 +2219,7 @@ namespace FFXIVClassic_Map_Server.Actors //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); leveled = true; @@ -2242,6 +2243,7 @@ namespace FFXIVClassic_Map_Server.Actors //also i dunno how to do this 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]); From 92de857cda8e9b97d5c82a07022f54cddc7716ff Mon Sep 17 00:00:00 2001 From: yogurt Date: Tue, 10 Oct 2017 13:32:47 -0500 Subject: [PATCH 6/9] opening quest stuff --- FFXIVClassic Lobby Server/Database.cs | 2 +- FFXIVClassic Map Server/Database.cs | 38 ++-- FFXIVClassic Map Server/WorldManager.cs | 2 + FFXIVClassic Map Server/actors/Actor.cs | 3 + FFXIVClassic Map Server/actors/area/Area.cs | 3 +- FFXIVClassic Map Server/actors/area/Zone.cs | 10 + .../actors/chara/Character.cs | 12 +- .../actors/chara/ai/BattleCommand.cs | 2 +- .../ai/controllers/BattleNpcController.cs | 1 - .../actors/chara/ai/helpers/PathFind.cs | 8 +- .../actors/chara/ai/state/WeaponSkillState.cs | 2 +- .../actors/chara/npc/BattleNpc.cs | 12 +- .../actors/chara/npc/Npc.cs | 2 +- .../actors/chara/player/Player.cs | 36 +++- .../actors/director/Director.cs | 3 +- .../actors/group/ContentGroup.cs | 2 +- FFXIVClassic Map Server/actors/quest/Quest.cs | 2 +- FFXIVClassic Map Server/lua/LuaEngine.cs | 25 ++- .../Actor/battle/BattleActionX01Packet.cs | 1 + data/scripts/commands/gm/eaction.lua | 34 ++++ data/scripts/commands/gm/setmaxhp.lua | 33 ++++ data/scripts/commands/gm/setmaxmp.lua | 33 ++++ data/scripts/commands/gm/yolo.lua | 178 ++++++++++++++++++ .../commands/weaponskill/chaos_thrust.lua | 26 +++ data/scripts/commands/weaponskill/default.lua | 26 +++ .../commands/weaponskill/doom_spike.lua | 26 +++ .../commands/weaponskill/dread_spike.lua | 26 +++ data/scripts/commands/weaponskill/feint.lua | 26 +++ .../commands/weaponskill/flat_blade.lua | 26 +++ .../commands/weaponskill/full_thrust.lua | 26 +++ .../commands/weaponskill/heavy_thrust.lua | 27 +++ .../commands/weaponskill/impulse_drive.lua | 26 +++ .../commands/weaponskill/leg_sweep.lua | 26 +++ data/scripts/commands/weaponskill/pummel.lua | 26 +++ .../commands/weaponskill/true_thrust.lua | 26 +++ .../commands/weaponskill/vorpal_thrust.lua | 26 +++ data/scripts/content/SimpleContent30010.lua | 38 ++-- .../directors/Quest/QuestDirectorMan0g001.lua | 63 ++++--- .../fst0Battle03/PopulaceStandard/yda.lua | 7 +- .../PopulaceStandard/serpent_private_hill.lua | 7 + .../PopulaceStandard/task_board.lua | 7 + .../fst0Town01a/PopulaceStandard/gagaroon.lua | 7 + .../fst0Town01a/PopulaceStandard/louisoix.lua | 7 + .../serpent_private_carver.lua | 7 + .../serpent_private_holmes.lua | 7 + .../PopulaceStandard/serpent_private_kirk.lua | 7 + .../serpent_private_stone.lua | 7 + .../serpent_private_white.lua | 7 + .../sea0Town01a/PopulaceStandard/rubh_hob.lua | 7 + 49 files changed, 873 insertions(+), 88 deletions(-) create mode 100644 data/scripts/commands/gm/eaction.lua create mode 100644 data/scripts/commands/gm/setmaxhp.lua create mode 100644 data/scripts/commands/gm/setmaxmp.lua create mode 100644 data/scripts/commands/gm/yolo.lua create mode 100644 data/scripts/commands/weaponskill/chaos_thrust.lua create mode 100644 data/scripts/commands/weaponskill/default.lua create mode 100644 data/scripts/commands/weaponskill/doom_spike.lua create mode 100644 data/scripts/commands/weaponskill/dread_spike.lua create mode 100644 data/scripts/commands/weaponskill/feint.lua create mode 100644 data/scripts/commands/weaponskill/flat_blade.lua create mode 100644 data/scripts/commands/weaponskill/full_thrust.lua create mode 100644 data/scripts/commands/weaponskill/heavy_thrust.lua create mode 100644 data/scripts/commands/weaponskill/impulse_drive.lua create mode 100644 data/scripts/commands/weaponskill/leg_sweep.lua create mode 100644 data/scripts/commands/weaponskill/pummel.lua create mode 100644 data/scripts/commands/weaponskill/true_thrust.lua create mode 100644 data/scripts/commands/weaponskill/vorpal_thrust.lua create mode 100644 data/scripts/unique/fst0Town01/PopulaceStandard/serpent_private_hill.lua create mode 100644 data/scripts/unique/fst0Town01/PopulaceStandard/task_board.lua create mode 100644 data/scripts/unique/fst0Town01a/PopulaceStandard/gagaroon.lua create mode 100644 data/scripts/unique/fst0Town01a/PopulaceStandard/louisoix.lua create mode 100644 data/scripts/unique/fst0Town01a/PopulaceStandard/serpent_private_carver.lua create mode 100644 data/scripts/unique/fst0Town01a/PopulaceStandard/serpent_private_holmes.lua create mode 100644 data/scripts/unique/fst0Town01a/PopulaceStandard/serpent_private_kirk.lua create mode 100644 data/scripts/unique/fst0Town01a/PopulaceStandard/serpent_private_stone.lua create mode 100644 data/scripts/unique/fst0Town01a/PopulaceStandard/serpent_private_white.lua create mode 100644 data/scripts/unique/sea0Town01a/PopulaceStandard/rubh_hob.lua diff --git a/FFXIVClassic Lobby Server/Database.cs b/FFXIVClassic Lobby Server/Database.cs index dce95d6b..a08da78e 100644 --- a/FFXIVClassic Lobby Server/Database.cs +++ b/FFXIVClassic Lobby Server/Database.cs @@ -219,7 +219,7 @@ namespace FFXIVClassic_Lobby_Server { MySqlCommand cmd = new MySqlCommand(); cmd.Connection = conn; - cmd.CommandText = String.Format("INSERT INTO characters_parametersave(characterId, hp, hpMax, mp, mpMax, mainSkill, mainSkillLevel) VALUES(@characterId, 1, 1, 1, 1, @mainSkill, 1);", CharacterCreatorUtils.GetClassNameForId((short)charaInfo.currentClass)); + cmd.CommandText = String.Format("INSERT INTO characters_parametersave(characterId, hp, hpMax, mp, mpMax, mainSkill, mainSkillLevel) VALUES(@characterId, 1900, 1000, 115, 115, @mainSkill, 1);", CharacterCreatorUtils.GetClassNameForId((short)charaInfo.currentClass)); cmd.Prepare(); cmd.Parameters.AddWithValue("@characterId", cid); diff --git a/FFXIVClassic Map Server/Database.cs b/FFXIVClassic Map Server/Database.cs index 2aeb81f2..8a0f3188 100644 --- a/FFXIVClassic Map Server/Database.cs +++ b/FFXIVClassic Map Server/Database.cs @@ -817,27 +817,27 @@ namespace FFXIVClassic_Map_Server { if (reader.Read()) { - player.charaWork.battleSave.skillPoint[Player.CLASSID_PUG - 1] = reader.GetInt16("pug"); - player.charaWork.battleSave.skillPoint[Player.CLASSID_GLA - 1] = reader.GetInt16("gla"); - player.charaWork.battleSave.skillPoint[Player.CLASSID_MRD - 1] = reader.GetInt16("mrd"); - player.charaWork.battleSave.skillPoint[Player.CLASSID_ARC - 1] = reader.GetInt16("arc"); - player.charaWork.battleSave.skillPoint[Player.CLASSID_LNC - 1] = reader.GetInt16("lnc"); + player.charaWork.battleSave.skillPoint[Player.CLASSID_PUG - 1] = reader.GetInt32("pug"); + player.charaWork.battleSave.skillPoint[Player.CLASSID_GLA - 1] = reader.GetInt32("gla"); + player.charaWork.battleSave.skillPoint[Player.CLASSID_MRD - 1] = reader.GetInt32("mrd"); + player.charaWork.battleSave.skillPoint[Player.CLASSID_ARC - 1] = reader.GetInt32("arc"); + player.charaWork.battleSave.skillPoint[Player.CLASSID_LNC - 1] = reader.GetInt32("lnc"); - player.charaWork.battleSave.skillPoint[Player.CLASSID_THM - 1] = reader.GetInt16("thm"); - player.charaWork.battleSave.skillPoint[Player.CLASSID_CNJ - 1] = reader.GetInt16("cnj"); + player.charaWork.battleSave.skillPoint[Player.CLASSID_THM - 1] = reader.GetInt32("thm"); + player.charaWork.battleSave.skillPoint[Player.CLASSID_CNJ - 1] = reader.GetInt32("cnj"); - player.charaWork.battleSave.skillPoint[Player.CLASSID_CRP - 1] = reader.GetInt16("crp"); - player.charaWork.battleSave.skillPoint[Player.CLASSID_BSM - 1] = reader.GetInt16("bsm"); - player.charaWork.battleSave.skillPoint[Player.CLASSID_ARM - 1] = reader.GetInt16("arm"); - player.charaWork.battleSave.skillPoint[Player.CLASSID_GSM - 1] = reader.GetInt16("gsm"); - player.charaWork.battleSave.skillPoint[Player.CLASSID_LTW - 1] = reader.GetInt16("ltw"); - player.charaWork.battleSave.skillPoint[Player.CLASSID_WVR - 1] = reader.GetInt16("wvr"); - player.charaWork.battleSave.skillPoint[Player.CLASSID_ALC - 1] = reader.GetInt16("alc"); - player.charaWork.battleSave.skillPoint[Player.CLASSID_CUL - 1] = reader.GetInt16("cul"); - - player.charaWork.battleSave.skillPoint[Player.CLASSID_MIN - 1] = reader.GetInt16("min"); - player.charaWork.battleSave.skillPoint[Player.CLASSID_BTN - 1] = reader.GetInt16("btn"); - player.charaWork.battleSave.skillPoint[Player.CLASSID_FSH - 1] = reader.GetInt16("fsh"); + player.charaWork.battleSave.skillPoint[Player.CLASSID_CRP - 1] = reader.GetInt32("crp"); + player.charaWork.battleSave.skillPoint[Player.CLASSID_BSM - 1] = reader.GetInt32("bsm"); + player.charaWork.battleSave.skillPoint[Player.CLASSID_ARM - 1] = reader.GetInt32("arm"); + player.charaWork.battleSave.skillPoint[Player.CLASSID_GSM - 1] = reader.GetInt32("gsm"); + player.charaWork.battleSave.skillPoint[Player.CLASSID_LTW - 1] = reader.GetInt32("ltw"); + player.charaWork.battleSave.skillPoint[Player.CLASSID_WVR - 1] = reader.GetInt32("wvr"); + player.charaWork.battleSave.skillPoint[Player.CLASSID_ALC - 1] = reader.GetInt32("alc"); + player.charaWork.battleSave.skillPoint[Player.CLASSID_CUL - 1] = reader.GetInt32("cul"); + + player.charaWork.battleSave.skillPoint[Player.CLASSID_MIN - 1] = reader.GetInt32("min"); + player.charaWork.battleSave.skillPoint[Player.CLASSID_BTN - 1] = reader.GetInt32("btn"); + player.charaWork.battleSave.skillPoint[Player.CLASSID_FSH - 1] = reader.GetInt32("fsh"); } } diff --git a/FFXIVClassic Map Server/WorldManager.cs b/FFXIVClassic Map Server/WorldManager.cs index 978187cd..a3c2db1d 100644 --- a/FFXIVClassic Map Server/WorldManager.cs +++ b/FFXIVClassic Map Server/WorldManager.cs @@ -1291,7 +1291,9 @@ namespace FFXIVClassic_Map_Server { Program.Tick = DateTime.Now; foreach (Zone zone in zoneList.Values) + { zone.Update(Program.Tick); + } Program.LastTick = Program.Tick; } } diff --git a/FFXIVClassic Map Server/actors/Actor.cs b/FFXIVClassic Map Server/actors/Actor.cs index 313b62cc..cce7f1a8 100644 --- a/FFXIVClassic Map Server/actors/Actor.cs +++ b/FFXIVClassic Map Server/actors/Actor.cs @@ -438,6 +438,9 @@ namespace FFXIVClassic_Map_Server.Actors updateFlags = ActorUpdateFlags.None; zone.BroadcastPacketsAroundActor(this, packets); + + SetActorPropetyPacket hpInfo = new SetActorPropetyPacket("charaWork/exp"); + hpInfo.AddTarget(); } } diff --git a/FFXIVClassic Map Server/actors/area/Area.cs b/FFXIVClassic Map Server/actors/area/Area.cs index 7e657d1a..b3a0e6c2 100644 --- a/FFXIVClassic Map Server/actors/area/Area.cs +++ b/FFXIVClassic Map Server/actors/area/Area.cs @@ -489,13 +489,14 @@ namespace FFXIVClassic_Map_Server.Actors zoneId = actorId; Npc npc; - if (isMob) npc = new BattleNpc(mActorList.Count + 1, actorClass, uniqueId, this, x, y, z, rot, state, animId, null); else npc = new Npc(mActorList.Count + 1, actorClass, uniqueId, this, x, y, z, rot, state, animId, null); npc.LoadEventConditions(actorClass.eventConditions); + npc.SetMaxHP(300); + npc.SetHP(300); AddActorToZone(npc); diff --git a/FFXIVClassic Map Server/actors/area/Zone.cs b/FFXIVClassic Map Server/actors/area/Zone.cs index 27cb19ab..dc3a5787 100644 --- a/FFXIVClassic Map Server/actors/area/Zone.cs +++ b/FFXIVClassic Map Server/actors/area/Zone.cs @@ -152,6 +152,7 @@ namespace FFXIVClassic_Map_Server.actors.area contentAreas.Add(areaName, new List()); PrivateAreaContent contentArea = new PrivateAreaContent(this, classPath, areaName, 1, director, starterPlayer); contentAreas[areaName].Add(contentArea); + return contentArea; } } @@ -167,6 +168,15 @@ namespace FFXIVClassic_Map_Server.actors.area public override void Update(DateTime tick) { base.Update(tick); + foreach (var a in privateAreas.Values) + foreach(var b in a.Values) + b.Update(tick); + + foreach (var a in contentAreas.Values) + foreach (var b in a) + { + b.Update(tick); + } // todo: again, this is retarded but debug stuff var diffTime = tick - lastUpdate; diff --git a/FFXIVClassic Map Server/actors/chara/Character.cs b/FFXIVClassic Map Server/actors/chara/Character.cs index 618c3b18..c9621219 100644 --- a/FFXIVClassic Map Server/actors/chara/Character.cs +++ b/FFXIVClassic Map Server/actors/chara/Character.cs @@ -401,6 +401,7 @@ namespace FFXIVClassic_Map_Server.Actors aiContainer.Engage(zone.FindActorInArea(targid)); } } + return false; } @@ -470,7 +471,7 @@ namespace FFXIVClassic_Map_Server.Actors public bool IsAlive() { - return !aiContainer.IsDead() && GetHP() > 0; + return !aiContainer.IsDead();// && GetHP() > 0; } public short GetHP() @@ -511,7 +512,7 @@ namespace FFXIVClassic_Map_Server.Actors public byte GetHPP() { - return (byte)((charaWork.parameterSave.hp[0] / charaWork.parameterSave.hpMax[0]) * 100); + return (byte)(charaWork.parameterSave.hp[0] == 0 ? 0 : (charaWork.parameterSave.hp[0] / charaWork.parameterSave.hpMax[0]) * 100); } public void SetHP(uint hp) @@ -570,7 +571,11 @@ namespace FFXIVClassic_Map_Server.Actors public void AddTP(int tp) { charaWork.parameterTemp.tp = (short)((charaWork.parameterTemp.tp + tp).Clamp(0, 3000)); + tpBase = (ushort) charaWork.parameterTemp.tp; updateFlags |= ActorUpdateFlags.HpTpMp; + + if (tpBase >= 1000) + lua.LuaEngine.GetInstance().OnSignal("tpOver1000"); } public void DelHP(int hp) @@ -638,6 +643,9 @@ namespace FFXIVClassic_Map_Server.Actors target.DelHP(action.amount); if (target is BattleNpc) ((BattleNpc)target).lastAttacker = this; + + AddTP(115); + target.AddTP(100); } public virtual void OnCast(State state, BattleAction[] actions, ref BattleAction[] errors) diff --git a/FFXIVClassic Map Server/actors/chara/ai/BattleCommand.cs b/FFXIVClassic Map Server/actors/chara/ai/BattleCommand.cs index 8a01284c..dc04bb46 100644 --- a/FFXIVClassic Map Server/actors/chara/ai/BattleCommand.cs +++ b/FFXIVClassic Map Server/actors/chara/ai/BattleCommand.cs @@ -233,7 +233,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai if (mpCost != 0) return (ushort)Math.Ceiling((cost * mpCost * 0.001)); - return tpCost; + return mpCost != 0 ? (ushort)Math.Ceiling((cost * mpCost * 0.001)) : (ushort)0; } public List GetTargets() diff --git a/FFXIVClassic Map Server/actors/chara/ai/controllers/BattleNpcController.cs b/FFXIVClassic Map Server/actors/chara/ai/controllers/BattleNpcController.cs index 43359fed..3a802c19 100644 --- a/FFXIVClassic Map Server/actors/chara/ai/controllers/BattleNpcController.cs +++ b/FFXIVClassic Map Server/actors/chara/ai/controllers/BattleNpcController.cs @@ -194,7 +194,6 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers protected virtual void DoCombatTick(DateTime tick, List contentGroupCharas = null) { HandleHate(); - // todo: magic/attack/ws cooldowns etc if (TryDeaggro()) { diff --git a/FFXIVClassic Map Server/actors/chara/ai/helpers/PathFind.cs b/FFXIVClassic Map Server/actors/chara/ai/helpers/PathFind.cs index 9af398f0..399bb9b5 100644 --- a/FFXIVClassic Map Server/actors/chara/ai/helpers/PathFind.cs +++ b/FFXIVClassic Map Server/actors/chara/ai/helpers/PathFind.cs @@ -44,7 +44,13 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai { var pos = new Vector3(owner.positionX, owner.positionY, owner.positionZ); var dest = new Vector3(x, y, z); - var zone = (Zone)owner.GetZone(); + + Zone zone; + if (owner.GetZone() is PrivateArea || owner.GetZone() is PrivateAreaContent) + zone = (Zone)((PrivateArea)owner.GetZone()).GetParentZone(); + else + zone = (Zone)owner.GetZone(); + var sw = new System.Diagnostics.Stopwatch(); sw.Start(); diff --git a/FFXIVClassic Map Server/actors/chara/ai/state/WeaponSkillState.cs b/FFXIVClassic Map Server/actors/chara/ai/state/WeaponSkillState.cs index e9b05019..f918c8be 100644 --- a/FFXIVClassic Map Server/actors/chara/ai/state/WeaponSkillState.cs +++ b/FFXIVClassic Map Server/actors/chara/ai/state/WeaponSkillState.cs @@ -106,7 +106,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state var errors = (BattleAction[])actions.Clone(); owner.OnWeaponSkill(this, actions, ref errors); - owner.DoBattleAction(skill.id, 0, actions); + owner.DoBattleAction(skill.id, skill.battleAnimation, actions); } public override void TryInterrupt() diff --git a/FFXIVClassic Map Server/actors/chara/npc/BattleNpc.cs b/FFXIVClassic Map Server/actors/chara/npc/BattleNpc.cs index e90bb91f..c528a12c 100644 --- a/FFXIVClassic Map Server/actors/chara/npc/BattleNpc.cs +++ b/FFXIVClassic Map Server/actors/chara/npc/BattleNpc.cs @@ -298,7 +298,13 @@ namespace FFXIVClassic_Map_Server.Actors // onDeath(monster, player, killer) lua.LuaEngine.CallLuaBattleFunction(this, "onDeath", this, partyMember, lastAttacker); // defeat/defeats - ((Player)lastAttacker).QueuePacket(BattleActionX01Packet.BuildPacket(lastAttacker.actorId, 0, 0, new BattleAction(actorId, 30108, 0))); + + if (lastAttacker is Player) + ((Player)lastAttacker).QueuePacket(BattleActionX01Packet.BuildPacket(lastAttacker.actorId, 0, 0, new BattleAction(actorId, 30108, 0))); + + if(partyMember is Player) + ((Player)partyMember).AddExp(1500, (byte)partyMember.GetJob(), 5); + } } else @@ -311,8 +317,10 @@ namespace FFXIVClassic_Map_Server.Actors positionUpdates?.Clear(); aiContainer.InternalDie(tick, despawnTime); this.ResetMoveSpeeds(); - + // todo: reset cooldowns + + lua.LuaEngine.GetInstance().OnSignal("mobkill"); } else { diff --git a/FFXIVClassic Map Server/actors/chara/npc/Npc.cs b/FFXIVClassic Map Server/actors/chara/npc/Npc.cs index 8feb3f51..31c9541d 100644 --- a/FFXIVClassic Map Server/actors/chara/npc/Npc.cs +++ b/FFXIVClassic Map Server/actors/chara/npc/Npc.cs @@ -80,7 +80,7 @@ namespace FFXIVClassic_Map_Server.Actors charaWork.parameterSave.hpMax[0] = 80; } for (int i = 0; i < 32; i++ ) - charaWork.property[i] = (byte)(((int)actorClass.propertyFlags >> i) & 1); + charaWork.property[i] = (byte)(((int)actorClass.propertyFlags >> i) & 1); npcWork.pushCommand = actorClass.pushCommand; npcWork.pushCommandSub = actorClass.pushCommandSub; diff --git a/FFXIVClassic Map Server/actors/chara/player/Player.cs b/FFXIVClassic Map Server/actors/chara/player/Player.cs index 0579e523..cd2d3509 100644 --- a/FFXIVClassic Map Server/actors/chara/player/Player.cs +++ b/FFXIVClassic Map Server/actors/chara/player/Player.cs @@ -234,7 +234,7 @@ namespace FFXIVClassic_Map_Server.Actors charaWork.commandBorder = 0x20; - charaWork.parameterTemp.tp = 3000; + charaWork.parameterTemp.tp = 0; Database.LoadPlayerCharacter(this); lastPlayTimeUpdate = Utils.UnixTimeStampUTC(); @@ -1777,9 +1777,13 @@ namespace FFXIVClassic_Map_Server.Actors propPacketUtil.AddProperty($"charaWork.parameterSave.state_mainSkillLevel"); packets.AddRange(propPacketUtil.Done()); + } base.PostUpdate(tick, packets); + SetActorPropetyPacket hpInfo = new SetActorPropetyPacket("charaWork/exp"); + hpInfo.AddTarget(); + QueuePacket(hpInfo.BuildPacket(actorId)); } public override void Die(DateTime tick) @@ -1813,19 +1817,20 @@ namespace FFXIVClassic_Map_Server.Actors 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)); + propPacketUtil.AddProperty($"charaWork.command[{slot}]"); + propPacketUtil.AddProperty($"charaWork.commandCategory[{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; - compatibiltyUtil.AddProperty(String.Format("charaWork.parameterSave.commandSlot_compatibility[{0}]", slot - charaWork.commandBorder)); + propPacketUtil.AddProperty($"charaWork.parameterSave.commandSlot_compatibility[{slot - charaWork.commandBorder}]"); } QueuePackets(propPacketUtil.Done()); - QueuePackets(compatibiltyUtil.Done()); + //QueuePackets(compatibiltyUtil.Done()); } //Update recast timers for the passed in hotbar slots @@ -1874,6 +1879,7 @@ namespace FFXIVClassic_Map_Server.Actors uint recastEnd = Utils.UnixTimeStampUTC() + maxRecastTime; List slotsToUpdate = new List(); + 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 == charaWork.parameterSave.state_mainSkill[0]) @@ -1887,7 +1893,6 @@ namespace FFXIVClassic_Map_Server.Actors UpdateHotbar(slotsToUpdate); } - Database.EquipAbility(this, classId, (ushort) (hotbarSlot - charaWork.commandBorder), commandId, recastEnd); if(printMessage) SendGameMessage(Server.GetWorldManager().GetActor(), 30603, 0x20, 0, commandId); @@ -2184,6 +2189,8 @@ namespace FFXIVClassic_Map_Server.Actors { ((BattleNpc)target).hateContainer.UpdateHate(this, action.amount); } + + LuaEngine.GetInstance().OnSignal("playerAttack"); } public override void OnCast(State state, BattleAction[] actions, ref BattleAction[] errors) @@ -2213,7 +2220,6 @@ namespace FFXIVClassic_Map_Server.Actors 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, unlocking skills and removing experience from exp until we don't have enough to level up @@ -2314,5 +2320,21 @@ namespace FFXIVClassic_Map_Server.Actors 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(0); + //SendCharaExpInfo(); + //ActorPropertyPacketUtil exp = new ActorPropertyPacketUtil("charaWork/exp", this); + SetActorPropetyPacket hpInfo = new SetActorPropetyPacket("charaWork/exp"); + hpInfo.AddTarget(); + QueuePacket(hpInfo.BuildPacket(actorId)); + } + } } diff --git a/FFXIVClassic Map Server/actors/director/Director.cs b/FFXIVClassic Map Server/actors/director/Director.cs index 53eee828..04d1740f 100644 --- a/FFXIVClassic Map Server/actors/director/Director.cs +++ b/FFXIVClassic Map Server/actors/director/Director.cs @@ -103,7 +103,7 @@ namespace FFXIVClassic_Map_Server.actors.director List lparams = CallLuaScript("init", args2); - if (lparams.Count >= 1 && lparams[0].value is string) + if (lparams != null && lparams.Count >= 1 && lparams[0].value is string) { classPath = (string)lparams[0].value; className = classPath.Substring(classPath.LastIndexOf("/") + 1); @@ -270,6 +270,7 @@ namespace FFXIVClassic_Map_Server.actors.director { if (directorScript != null) { + directorScript = LuaEngine.LoadScript(String.Format(LuaEngine.FILEPATH_DIRECTORS, directorScriptPath)); if (!directorScript.Globals.Get(funcName).IsNil()) { DynValue result = directorScript.Call(directorScript.Globals[funcName], args); diff --git a/FFXIVClassic Map Server/actors/group/ContentGroup.cs b/FFXIVClassic Map Server/actors/group/ContentGroup.cs index 4370f1c4..bebeb49c 100644 --- a/FFXIVClassic Map Server/actors/group/ContentGroup.cs +++ b/FFXIVClassic Map Server/actors/group/ContentGroup.cs @@ -49,7 +49,7 @@ namespace FFXIVClassic_Map_Server.actors.group { if (actor == null) return; - + members.Add(actor.actorId); if (actor is Character) diff --git a/FFXIVClassic Map Server/actors/quest/Quest.cs b/FFXIVClassic Map Server/actors/quest/Quest.cs index 17a2e292..109f8570 100644 --- a/FFXIVClassic Map Server/actors/quest/Quest.cs +++ b/FFXIVClassic Map Server/actors/quest/Quest.cs @@ -93,7 +93,7 @@ namespace FFXIVClassic_Map_Server.Actors return false; } else - return (questFlags & (1 << bitIndex)) == (1 << bitIndex); + return (questFlags & (1 << bitIndex)) == (1 << bitIndex); } public uint GetPhase() diff --git a/FFXIVClassic Map Server/lua/LuaEngine.cs b/FFXIVClassic Map Server/lua/LuaEngine.cs index e2373967..7de47460 100644 --- a/FFXIVClassic Map Server/lua/LuaEngine.cs +++ b/FFXIVClassic Map Server/lua/LuaEngine.cs @@ -224,7 +224,7 @@ namespace FFXIVClassic_Map_Server.lua Program.Log.Error($"LuaEngine.CallLuaBattleCommandFunction [{functionName}] {e.Message}"); } DynValue res = new DynValue(); - + if (!script.Globals.Get(functionName).IsNil()) { res = script.Call(script.Globals.Get(functionName), args); @@ -234,7 +234,27 @@ namespace FFXIVClassic_Map_Server.lua } else { - Program.Log.Error($"LuaEngine.CallLuaBattleCommandFunction [{command.name}] Unable to find script {path}"); + path = $"./scripts/commands/{folder}/default.lua"; + //Program.Log.Error($"LuaEngine.CallLuaBattleCommandFunction [{command.name}] Unable to find script {path}"); + var script = LoadGlobals(); + + try + { + script.DoFile(path); + } + catch (Exception e) + { + Program.Log.Error($"LuaEngine.CallLuaBattleCommandFunction [{functionName}] {e.Message}"); + } + DynValue res = new DynValue(); + DynValue r = script.Globals.Get(functionName); + + if (!script.Globals.Get(functionName).IsNil()) + { + res = script.Call(script.Globals.Get(functionName), args); + if (res != null) + return (int)res.Number; + } } return -1; } @@ -461,6 +481,7 @@ namespace FFXIVClassic_Map_Server.lua Coroutine coroutine = script.CreateCoroutine(script.Globals[funcName]).Coroutine; DynValue value = coroutine.Resume(args2); ResolveResume(player, coroutine, value); + } else { diff --git a/FFXIVClassic Map Server/packets/send/Actor/battle/BattleActionX01Packet.cs b/FFXIVClassic Map Server/packets/send/Actor/battle/BattleActionX01Packet.cs index de771305..006a2740 100644 --- a/FFXIVClassic Map Server/packets/send/Actor/battle/BattleActionX01Packet.cs +++ b/FFXIVClassic Map Server/packets/send/Actor/battle/BattleActionX01Packet.cs @@ -25,6 +25,7 @@ namespace FFXIVClassic_Map_Server.packets.send.actor.battle using (BinaryWriter binWriter = new BinaryWriter(mem)) { binWriter.Write((UInt32)sourceActorId); + binWriter.Write((UInt32)animationId); //Missing... last value is float, string in here as well? diff --git a/data/scripts/commands/gm/eaction.lua b/data/scripts/commands/gm/eaction.lua new file mode 100644 index 00000000..597c4952 --- /dev/null +++ b/data/scripts/commands/gm/eaction.lua @@ -0,0 +1,34 @@ +require("global"); + +properties = { + permissions = 0, + parameters = "s", + description = +[[ +Equips in the first open slot without checking if you can. +!eaction +]], +} + +function onTrigger(player, argc, commandid) + local sender = "[givegil] "; + + print(commandid); + 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 + classid = player:GetCurrentClassOrJob(); + commandid = tonumber(commandid) or 0; + + local added = player:EquipAbilityInFirstOpenSlot(classid, commandid); + + else + print(sender.."unable to add command, ensure player name is valid."); + end; +end; \ No newline at end of file diff --git a/data/scripts/commands/gm/setmaxhp.lua b/data/scripts/commands/gm/setmaxhp.lua new file mode 100644 index 00000000..5088680c --- /dev/null +++ b/data/scripts/commands/gm/setmaxhp.lua @@ -0,0 +1,33 @@ +require("global"); + +properties = { + permissions = 0, + parameters = "sss", + description = +[[ +Sets player or 's maximum hp to and heals them to full. +!setmaxhp | +!setmaxhp +]], +} + +function onTrigger(player, argc, hp, name, lastName) + local sender = "[setmaxhp] "; + + 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 + hp = tonumber(hp) or 1; + location = INVENTORY_CURRENCY; + + player:hpstuff(hp); + else + print(sender.."unable to add experience, ensure player name is valid."); + end; +end; \ No newline at end of file diff --git a/data/scripts/commands/gm/setmaxmp.lua b/data/scripts/commands/gm/setmaxmp.lua new file mode 100644 index 00000000..5088680c --- /dev/null +++ b/data/scripts/commands/gm/setmaxmp.lua @@ -0,0 +1,33 @@ +require("global"); + +properties = { + permissions = 0, + parameters = "sss", + description = +[[ +Sets player or 's maximum hp to and heals them to full. +!setmaxhp | +!setmaxhp +]], +} + +function onTrigger(player, argc, hp, name, lastName) + local sender = "[setmaxhp] "; + + 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 + hp = tonumber(hp) or 1; + location = INVENTORY_CURRENCY; + + player:hpstuff(hp); + else + print(sender.."unable to add experience, ensure player name is valid."); + end; +end; \ No newline at end of file diff --git a/data/scripts/commands/gm/yolo.lua b/data/scripts/commands/gm/yolo.lua new file mode 100644 index 00000000..34ad7d25 --- /dev/null +++ b/data/scripts/commands/gm/yolo.lua @@ -0,0 +1,178 @@ +require("global"); + +properties = { + permissions = 0, + parameters = "ssss", + description = +[[ +yolo +]], +} + +local quests = +{ + [111807] = { level = 25, weight = 4, rewardexp = 1080 }, + [110868] = { level = 50, weight = 4, rewardexp = 4400 }, + [111603] = { level = 22, weight = 5, rewardexp = 1100 }, + [111602] = { level = 22, weight = 5, rewardexp = 1100 }, + [111420] = { level = 45, weight = 5, rewardexp = 4450 }, + [110811] = { level = 18, weight = 6, rewardexp = 780 }, + [110814] = { level = 18, weight = 6, rewardexp = 780 }, + [110707] = { level = 25, weight = 6, rewardexp = 1620 }, + [110682] = { level = 34, weight = 6, rewardexp = 3180 }, + [111202] = { level = 35, weight = 6, rewardexp = 3360 }, + [111222] = { level = 35, weight = 6, rewardexp = 3360 }, + [111302] = { level = 35, weight = 6, rewardexp = 3360 }, + [111223] = { level = 40, weight = 6, rewardexp = 4260 }, + [110819] = { level = 45, weight = 6, rewardexp = 5340 }, + [111224] = { level = 45, weight = 6, rewardexp = 5340 }, + [111225] = { level = 45, weight = 6, rewardexp = 5340 }, + [110867] = { level = 45, weight = 6, rewardexp = 5340 }, + [110869] = { level = 45, weight = 6, rewardexp = 5340 }, + [110708] = { level = 45, weight = 6, rewardexp = 5340 }, + [110627] = { level = 45, weight = 6, rewardexp = 5340 }, + [111434] = { level = 50, weight = 6, rewardexp = 6600 }, + [110850] = { level = 1, weight = 7, rewardexp = 40 }, + [110851] = { level = 1, weight = 7, rewardexp = 40 }, + [110841] = { level = 20, weight = 7, rewardexp = 1120 }, + [110642] = { level = 20, weight = 7, rewardexp = 1120 }, + [110840] = { level = 20, weight = 7, rewardexp = 1120 }, + [110727] = { level = 21, weight = 7, rewardexp = 1401 }, + [111221] = { level = 30, weight = 7, rewardexp = 2661 }, + [111241] = { level = 30, weight = 7, rewardexp = 2661 }, + [110687] = { level = 28, weight = 9, rewardexp = 2970 }, + [110016] = { level = 34, weight = 50, rewardexp = 26500 }, + [110017] = { level = 38, weight = 50, rewardexp = 32500 }, + [110019] = { level = 46, weight = 50, rewardexp = 46000 } +}; + +local expTable = { + 570, -- 1 + 700, + 880, + 1100, + 1500, + 1800, + 2300, + 3200, + 4300, + 5000, -- 10 + 5900, + 6800, + 7700, + 8700, + 9700, + 11000, + 12000, + 13000, + 15000, + 16000, -- 20 + 20000, + 22000, + 23000, + 25000, + 27000, + 29000, + 31000, + 33000, + 35000, + 38000, -- 30 + 45000, + 47000, + 50000, + 53000, + 56000, + 59000, + 62000, + 65000, + 68000, + 71000, -- 40 + 74000, + 78000, + 81000, + 85000, + 89000, + 92000, + 96000, + 100000, + 100000, + 110000 -- 50 +}; + +local commandCost = { + ["raise"] = 150, + ["cure"] = 40, + ["cura"] = 100, + ["curaga"] = 150, +}; +-- stone: (1, 9) (5, 12) (10, ) +-- cure: (1, 5) (5, 6) (10, ) +-- aero: (1, 9) (5, 12) (10, ) +-- protect: (1, 9) (5, 12) (10, ) +--[[ +function onTrigger(player, argc, id, level, weight) + id = tonumber(id) or 111807; + level = tonumber(level) or quests[id].level; + weight = tonumber(weight) or quests[id].weight; + local messageId = MESSAGE_TYPE_SYSTEM_ERROR; + local sender = "yolo"; + + if id == 1 then + return + end + local message = calcSkillPoint(player, level, weight); + if player then + player.SendMessage(messageId, sender, string.format("calculated %s | expected %s", message, quests[id].rewardexp)); + end; + printf("calculated %s | expected %s", message, quests[id].rewardexp); +end; +]] + +function onTrigger(player, argc, skillName, level) + local messageId = MESSAGE_TYPE_SYSTEM_ERROR; + local sender = "yolo"; + + if player then + if false then + local effectId = 223004; + + player.statusEffects.RemoveStatusEffect(effectId); + player.statusEffects.AddStatusEffect(effectId, 1, 0, 5); + return; + end; + + local pos = player:GetPos(); + local x = tonumber(pos[0]); + local y = tonumber(pos[1]); + local z = tonumber(pos[2]); + local rot = tonumber(pos[3]); + local zone = pos[4]; + + printf("%f %f %f", x, y, z); + --local x, y, z = player.GetPos(); + for i = 1, 1 do + + local actor = player.GetZone().SpawnActor(2207303, 'ass', x, y, z, rot, 0, 0, true ); + + --actor.FollowTarget(player, 3.2); + end; + return; + end + level = tonumber(level) or 1; + if player then + player.SendMessage(messageId, sender, string.format("name %s | cost %d | level %u", skillName, calculateCommandCost(player, skillName, level), level)); + end; +end; + +function calculateCommandCost(player, skillName, level) + if skillName and level and commandCost[skillName] then + return math.ceil((8000 + (level - 70) * 500) * (commandCost[skillName] * 0.001)); + end; + return 1; +end + +function calcSkillPoint(player, lvl, weight) + weight = weight / 100 + + return math.ceil(expTable[lvl] * weight) +end \ No newline at end of file diff --git a/data/scripts/commands/weaponskill/chaos_thrust.lua b/data/scripts/commands/weaponskill/chaos_thrust.lua new file mode 100644 index 00000000..98ea45f1 --- /dev/null +++ b/data/scripts/commands/weaponskill/chaos_thrust.lua @@ -0,0 +1,26 @@ +require("global"); + +function onSkillPrepare(caster, target, skill) + return 0; +end; + +function onSkillStart(caster, target, skill) + return 0; +end; + +function onSkillFinish(caster, target, skill, action) + local damage = math.random(100, 200); + + -- todo: populate a global script with statuses and modifiers + action.worldMasterTextId = 0x765D; + + -- todo: populate a global script with statuses and modifiers + -- magic.HandleAttackMagic(caster, target, spell, action) + -- action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636); + --action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636); + + if target.hateContainer then + target.hateContainer.UpdateHate(caster, damage); + end; + return damage; +end; \ No newline at end of file diff --git a/data/scripts/commands/weaponskill/default.lua b/data/scripts/commands/weaponskill/default.lua new file mode 100644 index 00000000..965bcb8d --- /dev/null +++ b/data/scripts/commands/weaponskill/default.lua @@ -0,0 +1,26 @@ +require("global"); + +function onSkillPrepare(caster, target, skill) + return 0; +end; + +function onSkillStart(caster, target, skill) + return 0; +end; + +function onSkillFinish(caster, target, skill, action) + local damage = math.random(100, 200); + + -- todo: populate a global script with statuses and modifiers + action.worldMasterTextId = 0x765D; + + -- todo: populate a global script with statuses and modifiers + -- magic.HandleAttackMagic(caster, target, spell, action) + -- action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636); + action.effectId = bit32.bxor(0x8000000, skill.effectAnimation, 15636); + + if target.hateContainer then + target.hateContainer.UpdateHate(caster, damage); + end; + return damage; +end; \ No newline at end of file diff --git a/data/scripts/commands/weaponskill/doom_spike.lua b/data/scripts/commands/weaponskill/doom_spike.lua new file mode 100644 index 00000000..98ea45f1 --- /dev/null +++ b/data/scripts/commands/weaponskill/doom_spike.lua @@ -0,0 +1,26 @@ +require("global"); + +function onSkillPrepare(caster, target, skill) + return 0; +end; + +function onSkillStart(caster, target, skill) + return 0; +end; + +function onSkillFinish(caster, target, skill, action) + local damage = math.random(100, 200); + + -- todo: populate a global script with statuses and modifiers + action.worldMasterTextId = 0x765D; + + -- todo: populate a global script with statuses and modifiers + -- magic.HandleAttackMagic(caster, target, spell, action) + -- action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636); + --action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636); + + if target.hateContainer then + target.hateContainer.UpdateHate(caster, damage); + end; + return damage; +end; \ No newline at end of file diff --git a/data/scripts/commands/weaponskill/dread_spike.lua b/data/scripts/commands/weaponskill/dread_spike.lua new file mode 100644 index 00000000..98ea45f1 --- /dev/null +++ b/data/scripts/commands/weaponskill/dread_spike.lua @@ -0,0 +1,26 @@ +require("global"); + +function onSkillPrepare(caster, target, skill) + return 0; +end; + +function onSkillStart(caster, target, skill) + return 0; +end; + +function onSkillFinish(caster, target, skill, action) + local damage = math.random(100, 200); + + -- todo: populate a global script with statuses and modifiers + action.worldMasterTextId = 0x765D; + + -- todo: populate a global script with statuses and modifiers + -- magic.HandleAttackMagic(caster, target, spell, action) + -- action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636); + --action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636); + + if target.hateContainer then + target.hateContainer.UpdateHate(caster, damage); + end; + return damage; +end; \ No newline at end of file diff --git a/data/scripts/commands/weaponskill/feint.lua b/data/scripts/commands/weaponskill/feint.lua new file mode 100644 index 00000000..98ea45f1 --- /dev/null +++ b/data/scripts/commands/weaponskill/feint.lua @@ -0,0 +1,26 @@ +require("global"); + +function onSkillPrepare(caster, target, skill) + return 0; +end; + +function onSkillStart(caster, target, skill) + return 0; +end; + +function onSkillFinish(caster, target, skill, action) + local damage = math.random(100, 200); + + -- todo: populate a global script with statuses and modifiers + action.worldMasterTextId = 0x765D; + + -- todo: populate a global script with statuses and modifiers + -- magic.HandleAttackMagic(caster, target, spell, action) + -- action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636); + --action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636); + + if target.hateContainer then + target.hateContainer.UpdateHate(caster, damage); + end; + return damage; +end; \ No newline at end of file diff --git a/data/scripts/commands/weaponskill/flat_blade.lua b/data/scripts/commands/weaponskill/flat_blade.lua new file mode 100644 index 00000000..fa1c4b1f --- /dev/null +++ b/data/scripts/commands/weaponskill/flat_blade.lua @@ -0,0 +1,26 @@ +require("global"); + +function onSkillPrepare(caster, target, skill) + return 0; +end; + +function onSkillStart(caster, target, skill) + return 0; +end; + +function onSkillFinish(caster, target, skill, action) + local damage = math.random(100, 200); + + -- todo: populate a global script with statuses and modifiers + action.worldMasterTextId = 0x765D; + + -- todo: populate a global script with statuses and modifiers + -- magic.HandleAttackMagic(caster, target, spell, action) + -- action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636); + action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636); + + if target.hateContainer then + target.hateContainer.UpdateHate(caster, damage); + end; + return damage; +end; \ No newline at end of file diff --git a/data/scripts/commands/weaponskill/full_thrust.lua b/data/scripts/commands/weaponskill/full_thrust.lua new file mode 100644 index 00000000..98ea45f1 --- /dev/null +++ b/data/scripts/commands/weaponskill/full_thrust.lua @@ -0,0 +1,26 @@ +require("global"); + +function onSkillPrepare(caster, target, skill) + return 0; +end; + +function onSkillStart(caster, target, skill) + return 0; +end; + +function onSkillFinish(caster, target, skill, action) + local damage = math.random(100, 200); + + -- todo: populate a global script with statuses and modifiers + action.worldMasterTextId = 0x765D; + + -- todo: populate a global script with statuses and modifiers + -- magic.HandleAttackMagic(caster, target, spell, action) + -- action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636); + --action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636); + + if target.hateContainer then + target.hateContainer.UpdateHate(caster, damage); + end; + return damage; +end; \ No newline at end of file diff --git a/data/scripts/commands/weaponskill/heavy_thrust.lua b/data/scripts/commands/weaponskill/heavy_thrust.lua new file mode 100644 index 00000000..9c72078a --- /dev/null +++ b/data/scripts/commands/weaponskill/heavy_thrust.lua @@ -0,0 +1,27 @@ +require("global"); + +function onSkillPrepare(caster, target, skill) + return 0; +end; + +function onSkillStart(caster, target, skill) + return 0; +end; + +function onSkillFinish(caster, target, skill, action) + local damage = math.random(100, 200); + + -- todo: populate a global script with statuses and modifiers + action.worldMasterTextId = 0x765D; + + -- todo: populate a global script with statuses and modifiers + -- magic.HandleAttackMagic(caster, target, spell, action) + -- action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636); + + action.effectId = bit32.bxor(0x8000000, skill.effectAnimation, 15636); + + if target.hateContainer then + target.hateContainer.UpdateHate(caster, damage); + end; + return damage; +end; \ No newline at end of file diff --git a/data/scripts/commands/weaponskill/impulse_drive.lua b/data/scripts/commands/weaponskill/impulse_drive.lua new file mode 100644 index 00000000..98ea45f1 --- /dev/null +++ b/data/scripts/commands/weaponskill/impulse_drive.lua @@ -0,0 +1,26 @@ +require("global"); + +function onSkillPrepare(caster, target, skill) + return 0; +end; + +function onSkillStart(caster, target, skill) + return 0; +end; + +function onSkillFinish(caster, target, skill, action) + local damage = math.random(100, 200); + + -- todo: populate a global script with statuses and modifiers + action.worldMasterTextId = 0x765D; + + -- todo: populate a global script with statuses and modifiers + -- magic.HandleAttackMagic(caster, target, spell, action) + -- action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636); + --action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636); + + if target.hateContainer then + target.hateContainer.UpdateHate(caster, damage); + end; + return damage; +end; \ No newline at end of file diff --git a/data/scripts/commands/weaponskill/leg_sweep.lua b/data/scripts/commands/weaponskill/leg_sweep.lua new file mode 100644 index 00000000..98ea45f1 --- /dev/null +++ b/data/scripts/commands/weaponskill/leg_sweep.lua @@ -0,0 +1,26 @@ +require("global"); + +function onSkillPrepare(caster, target, skill) + return 0; +end; + +function onSkillStart(caster, target, skill) + return 0; +end; + +function onSkillFinish(caster, target, skill, action) + local damage = math.random(100, 200); + + -- todo: populate a global script with statuses and modifiers + action.worldMasterTextId = 0x765D; + + -- todo: populate a global script with statuses and modifiers + -- magic.HandleAttackMagic(caster, target, spell, action) + -- action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636); + --action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636); + + if target.hateContainer then + target.hateContainer.UpdateHate(caster, damage); + end; + return damage; +end; \ No newline at end of file diff --git a/data/scripts/commands/weaponskill/pummel.lua b/data/scripts/commands/weaponskill/pummel.lua new file mode 100644 index 00000000..98ea45f1 --- /dev/null +++ b/data/scripts/commands/weaponskill/pummel.lua @@ -0,0 +1,26 @@ +require("global"); + +function onSkillPrepare(caster, target, skill) + return 0; +end; + +function onSkillStart(caster, target, skill) + return 0; +end; + +function onSkillFinish(caster, target, skill, action) + local damage = math.random(100, 200); + + -- todo: populate a global script with statuses and modifiers + action.worldMasterTextId = 0x765D; + + -- todo: populate a global script with statuses and modifiers + -- magic.HandleAttackMagic(caster, target, spell, action) + -- action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636); + --action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636); + + if target.hateContainer then + target.hateContainer.UpdateHate(caster, damage); + end; + return damage; +end; \ No newline at end of file diff --git a/data/scripts/commands/weaponskill/true_thrust.lua b/data/scripts/commands/weaponskill/true_thrust.lua new file mode 100644 index 00000000..965bcb8d --- /dev/null +++ b/data/scripts/commands/weaponskill/true_thrust.lua @@ -0,0 +1,26 @@ +require("global"); + +function onSkillPrepare(caster, target, skill) + return 0; +end; + +function onSkillStart(caster, target, skill) + return 0; +end; + +function onSkillFinish(caster, target, skill, action) + local damage = math.random(100, 200); + + -- todo: populate a global script with statuses and modifiers + action.worldMasterTextId = 0x765D; + + -- todo: populate a global script with statuses and modifiers + -- magic.HandleAttackMagic(caster, target, spell, action) + -- action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636); + action.effectId = bit32.bxor(0x8000000, skill.effectAnimation, 15636); + + if target.hateContainer then + target.hateContainer.UpdateHate(caster, damage); + end; + return damage; +end; \ No newline at end of file diff --git a/data/scripts/commands/weaponskill/vorpal_thrust.lua b/data/scripts/commands/weaponskill/vorpal_thrust.lua new file mode 100644 index 00000000..98ea45f1 --- /dev/null +++ b/data/scripts/commands/weaponskill/vorpal_thrust.lua @@ -0,0 +1,26 @@ +require("global"); + +function onSkillPrepare(caster, target, skill) + return 0; +end; + +function onSkillStart(caster, target, skill) + return 0; +end; + +function onSkillFinish(caster, target, skill, action) + local damage = math.random(100, 200); + + -- todo: populate a global script with statuses and modifiers + action.worldMasterTextId = 0x765D; + + -- todo: populate a global script with statuses and modifiers + -- magic.HandleAttackMagic(caster, target, spell, action) + -- action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636); + --action.effectId = bit32.bxor(0x8000000, spell.effectAnimation, 15636); + + if target.hateContainer then + target.hateContainer.UpdateHate(caster, damage); + end; + return damage; +end; \ No newline at end of file diff --git a/data/scripts/content/SimpleContent30010.lua b/data/scripts/content/SimpleContent30010.lua index d78c2935..3e3b72f9 100644 --- a/data/scripts/content/SimpleContent30010.lua +++ b/data/scripts/content/SimpleContent30010.lua @@ -1,25 +1,31 @@ +require ("global") function onCreate(starterPlayer, contentArea, director) + --papalymo = contentArea:SpawnActor(2290005, "papalymo", 365.89, 4.0943, -706.72, -0.718); + --yda = contentArea:SpawnActor(2290006, "yda", 365.266, 4.122, -700.73, 1.5659); + --yda = GetWorldManager().SpawnBattleNpcById(6, contentArea); + --papalymo = GetWorldManager().SpawnBattleNpcById(7, contentArea); + + --mob1 = GetWorldManager().SpawnBattleNpcById(3, contentArea); + --mob2 = GetWorldManager().SpawnBattleNpcById(4, contentArea); + --mob3 = GetWorldManager().SpawnBattleNpcById(5, contentArea); + ---yda:ChangeState(2); - papalymo = contentArea:SpawnActor(2290005, "papalymo", 365.89, 4.0943, -706.72, -0.718); - yda = contentArea:SpawnActor(2290006, "yda", 365.266, 4.122, -700.73, 1.5659); - yda:ChangeState(2); + --mob1 = contentArea:SpawnActor(2201407, "mob1", 374.427, 4.4, -698.711, -1.942); + --mob2 = contentArea:SpawnActor(2201407, "mob2", 375.377, 4.4, -700.247, -1.992); + --mob3 = contentArea:SpawnActor(2201407, "mob3", 375.125, 4.4, -703.591, -1.54); - mob1 = contentArea:SpawnActor(2201407, "mob1", 374.427, 4.4, -698.711, -1.942); - mob2 = contentArea:SpawnActor(2201407, "mob2", 375.377, 4.4, -700.247, -1.992); - mob3 = contentArea:SpawnActor(2201407, "mob3", 375.125, 4.4, -703.591, -1.54); + --openingStoper = contentArea:SpawnActor(1090384, "openingstoper", 356.09, 3.74, -701.62, -1.41); - openingStoper = contentArea:SpawnActor(1090384, "openingstoper", 356.09, 3.74, -701.62, -1.41); + --director:AddMember(starterPlayer); + --director:AddMember(director); +-- director:AddMember(papalymo); + --director:AddMember(yda); + --director:AddMember(mob1); + --director:AddMember(mob2); + --director:AddMember(mob3); - director:AddMember(starterPlayer); - director:AddMember(director); - director:AddMember(papalymo); - director:AddMember(yda); - director:AddMember(mob1); - director:AddMember(mob2); - director:AddMember(mob3); - - director:StartContentGroup(); + --director:StartContentGroup(); end diff --git a/data/scripts/directors/Quest/QuestDirectorMan0g001.lua b/data/scripts/directors/Quest/QuestDirectorMan0g001.lua index 81bf270e..e6dc16e3 100644 --- a/data/scripts/directors/Quest/QuestDirectorMan0g001.lua +++ b/data/scripts/directors/Quest/QuestDirectorMan0g001.lua @@ -14,44 +14,52 @@ function onCreateContentArea(players, director, contentArea, contentGroup) local worldManager = GetWorldManager(); - yshtola = GetWorldManager().SpawnBattleNpcById(6, contentArea); - stahlmann = GetWorldManager().SpawnBattleNpcById(7, contentArea); + yda = GetWorldManager().SpawnBattleNpcById(6, contentArea); + papalymo = GetWorldManager().SpawnBattleNpcById(7, contentArea); + + mob1 = GetWorldManager().SpawnBattleNpcById(3, contentArea); + mob2 = GetWorldManager().SpawnBattleNpcById(4, contentArea); + mob3 = GetWorldManager().SpawnBattleNpcById(5, contentArea); + + --papalymo = contentArea:SpawnActor(2290005, "papalymo", 365.89, 4.0943, -706.72, -0.718); + --yda = contentArea:SpawnActor(2290006, "yda", 365.266, 4.122, -700.73, 1.5659); + --yda:ChangeState(2); - mob1 = GetWorldManager().SpawnBattleNpcById(3, contentArea); - mob2 = GetWorldManager().SpawnBattleNpcById(4, contentArea); - mob3 = GetWorldManager().SpawnBattleNpcById(5, contentArea); + --mob1 = contentArea:SpawnActor(2201407, "mob1", 374.427, 4.4, -698.711, -1.942); + --mob2 = contentArea:SpawnActor(2201407, "mob2", 375.377, 4.4, -700.247, -1.992); + --mob3 = contentArea:SpawnActor(2201407, "mob3", 375.125, 4.4, -703.591, -1.54); + openingStoper = contentArea:SpawnActor(1090384, "openingstoper", 356.09, 3.74, -701.62, -1.41); + + local added = false; - for i = 0, players.Count do - local player = players[i]; - print("asses "..players.Count) + for player in players do if player.currentParty and not added then - print("shitness") - player.currentParty.members:Add(yshtola.actorId); - print("cunt") - player.currentParty.members:Add(stahlmann.actorId); - print("dickbag") + player.currentParty.members:Add(yda.actorId); + print("cunt"); + player.currentParty.members:Add(papalymo.actorId); + print("dickbag"); added = true; end; -- dont let player die + print("shittttt3"); player:SetMod(modifiersGlobal.MinimumHpLock, 1); - contentGroup:AddMember(player) - print("shittttt") - break + print("shittttt2"); + director:AddMember(player) + print("shittttt1"); + --GetWorldManager():DoZoneChangeContent(player, contentArea, 362.4087, 4, -703.8168, 1.5419, 16); end; print("shit") - contentGroup:AddMember(director); - print("shit2"); - contentGroup:AddMember(yshtola); - print("shit3") - contentGroup:AddMember(stahlmann); - print("shit4") - contentGroup:AddMember(mob1); - print("shit5") - contentGroup:AddMember(mob2); - print("shit6") - contentGroup:AddMember(mob3); + director:AddMember(director); + director:AddMember(yda); + director:AddMember(papalymo); + director:AddMember(mob1); + director:AddMember(mob2); + print("shit6") + director:AddMember(mob3); print("dicks") + + director:StartContentGroup(); end function onEventStarted(player, actor, triggerName) @@ -120,5 +128,4 @@ end function main(director, contentGroup) print("shitstain") onCreateContentArea(director:GetPlayerMembers(), director, director:GetZone(), contentGroup); - player:EndEvent(); end; \ No newline at end of file diff --git a/data/scripts/unique/fst0Battle03/PopulaceStandard/yda.lua b/data/scripts/unique/fst0Battle03/PopulaceStandard/yda.lua index a82963ad..0f4d5f7e 100644 --- a/data/scripts/unique/fst0Battle03/PopulaceStandard/yda.lua +++ b/data/scripts/unique/fst0Battle03/PopulaceStandard/yda.lua @@ -7,9 +7,10 @@ end function onEventStarted(player, npc, triggerName) man0g0Quest = player:GetQuest("Man0g0"); - + print("hi"); if (man0g0Quest ~= nil) then - + + print("hi2"); if (triggerName == "pushDefault") then callClientFunction(player, "delegateEvent", player, man0g0Quest, "processTtrNomal002", nil, nil, nil); elseif (triggerName == "talkDefault") then @@ -22,6 +23,7 @@ function onEventStarted(player, npc, triggerName) man0g0Quest:SaveData(); player:GetDirector("OpeningDirector"):onTalkEvent(player, npc); --Was she talked to after papalymo? + print("hi3"); else if (man0g0Quest:GetQuestFlag(MAN0G0_FLAG_MINITUT_DONE1) == true) then @@ -41,6 +43,7 @@ function onEventStarted(player, npc, triggerName) player:KickEvent(director, "noticeEvent", true); player:SetLoginDirector(director); + print("hi5"); GetWorldManager():DoZoneChangeContent(player, contentArea, 362.4087, 4, -703.8168, 1.5419, 16); return; else diff --git a/data/scripts/unique/fst0Town01/PopulaceStandard/serpent_private_hill.lua b/data/scripts/unique/fst0Town01/PopulaceStandard/serpent_private_hill.lua new file mode 100644 index 00000000..02e67d32 --- /dev/null +++ b/data/scripts/unique/fst0Town01/PopulaceStandard/serpent_private_hill.lua @@ -0,0 +1,7 @@ +require ("global") + +function onEventStarted(player, npc) + defaultFst = GetStaticActor("DftFst"); + callClientFunction(player, "delegateEvent", player, defaultFst, "defaultTalkWithSerpent_private_hill_001", nil, nil, nil); + player:endEvent(); +end \ No newline at end of file diff --git a/data/scripts/unique/fst0Town01/PopulaceStandard/task_board.lua b/data/scripts/unique/fst0Town01/PopulaceStandard/task_board.lua new file mode 100644 index 00000000..b7448428 --- /dev/null +++ b/data/scripts/unique/fst0Town01/PopulaceStandard/task_board.lua @@ -0,0 +1,7 @@ +require ("global") + +function onEventStarted(player, npc) + defaultFst = GetStaticActor("DftFst"); + callClientFunction(player, "delegateEvent", player, defaultFst, "defaultTalkWithTask_board_001", nil, nil, nil); + player:endEvent(); +end \ No newline at end of file diff --git a/data/scripts/unique/fst0Town01a/PopulaceStandard/gagaroon.lua b/data/scripts/unique/fst0Town01a/PopulaceStandard/gagaroon.lua new file mode 100644 index 00000000..19143bdf --- /dev/null +++ b/data/scripts/unique/fst0Town01a/PopulaceStandard/gagaroon.lua @@ -0,0 +1,7 @@ +require ("global") + +function onEventStarted(player, npc) + defaultFst = GetStaticActor("DftFst"); + callClientFunction(player, "delegateEvent", player, defaultFst, "defaultTalkWithGagaroon_001", nil, nil, nil); + player:endEvent(); +end \ No newline at end of file diff --git a/data/scripts/unique/fst0Town01a/PopulaceStandard/louisoix.lua b/data/scripts/unique/fst0Town01a/PopulaceStandard/louisoix.lua new file mode 100644 index 00000000..b0b08cd5 --- /dev/null +++ b/data/scripts/unique/fst0Town01a/PopulaceStandard/louisoix.lua @@ -0,0 +1,7 @@ +require ("global") + +function onEventStarted(player, npc) + defaultFst = GetStaticActor("DftFst"); + callClientFunction(player, "delegateEvent", player, defaultFst, "defaultTalkWithLouisoix_001", nil, nil, nil); + player:endEvent(); +end \ No newline at end of file diff --git a/data/scripts/unique/fst0Town01a/PopulaceStandard/serpent_private_carver.lua b/data/scripts/unique/fst0Town01a/PopulaceStandard/serpent_private_carver.lua new file mode 100644 index 00000000..0a24f7e7 --- /dev/null +++ b/data/scripts/unique/fst0Town01a/PopulaceStandard/serpent_private_carver.lua @@ -0,0 +1,7 @@ +require ("global") + +function onEventStarted(player, npc) + defaultFst = GetStaticActor("DftFst"); + callClientFunction(player, "delegateEvent", player, defaultFst, "defaultTalkWithSerpent_private_carver_001", nil, nil, nil); + player:endEvent(); +end \ No newline at end of file diff --git a/data/scripts/unique/fst0Town01a/PopulaceStandard/serpent_private_holmes.lua b/data/scripts/unique/fst0Town01a/PopulaceStandard/serpent_private_holmes.lua new file mode 100644 index 00000000..fc7c975d --- /dev/null +++ b/data/scripts/unique/fst0Town01a/PopulaceStandard/serpent_private_holmes.lua @@ -0,0 +1,7 @@ +require ("global") + +function onEventStarted(player, npc) + defaultFst = GetStaticActor("DftFst"); + callClientFunction(player, "delegateEvent", player, defaultFst, "defaultTalkWithSerpent_private_holmes_001", nil, nil, nil); + player:endEvent(); +end \ No newline at end of file diff --git a/data/scripts/unique/fst0Town01a/PopulaceStandard/serpent_private_kirk.lua b/data/scripts/unique/fst0Town01a/PopulaceStandard/serpent_private_kirk.lua new file mode 100644 index 00000000..c7b840aa --- /dev/null +++ b/data/scripts/unique/fst0Town01a/PopulaceStandard/serpent_private_kirk.lua @@ -0,0 +1,7 @@ +require ("global") + +function onEventStarted(player, npc) + defaultFst = GetStaticActor("DftFst"); + callClientFunction(player, "delegateEvent", player, defaultFst, "defaultTalkWithSerpent_private_kirk_001", nil, nil, nil); + player:endEvent(); +end \ No newline at end of file diff --git a/data/scripts/unique/fst0Town01a/PopulaceStandard/serpent_private_stone.lua b/data/scripts/unique/fst0Town01a/PopulaceStandard/serpent_private_stone.lua new file mode 100644 index 00000000..d6d2ff82 --- /dev/null +++ b/data/scripts/unique/fst0Town01a/PopulaceStandard/serpent_private_stone.lua @@ -0,0 +1,7 @@ +require ("global") + +function onEventStarted(player, npc) + defaultFst = GetStaticActor("DftFst"); + callClientFunction(player, "delegateEvent", player, defaultFst, "defaultTalkWithSerpent_private_stone_001", nil, nil, nil); + player:endEvent(); +end \ No newline at end of file diff --git a/data/scripts/unique/fst0Town01a/PopulaceStandard/serpent_private_white.lua b/data/scripts/unique/fst0Town01a/PopulaceStandard/serpent_private_white.lua new file mode 100644 index 00000000..d66e5dad --- /dev/null +++ b/data/scripts/unique/fst0Town01a/PopulaceStandard/serpent_private_white.lua @@ -0,0 +1,7 @@ +require ("global") + +function onEventStarted(player, npc) + defaultFst = GetStaticActor("DftFst"); + callClientFunction(player, "delegateEvent", player, defaultFst, "defaultTalkWithSerpent_private_white_001", nil, nil, nil); + player:endEvent(); +end \ No newline at end of file diff --git a/data/scripts/unique/sea0Town01a/PopulaceStandard/rubh_hob.lua b/data/scripts/unique/sea0Town01a/PopulaceStandard/rubh_hob.lua new file mode 100644 index 00000000..2b97c724 --- /dev/null +++ b/data/scripts/unique/sea0Town01a/PopulaceStandard/rubh_hob.lua @@ -0,0 +1,7 @@ +require ("global") + +function onEventStarted(player, npc) + defaultSea = GetStaticActor("DftSea"); + callClientFunction(player, "delegateEvent", player, defaultSea, "defaultTalkWithRubh_hob_001", nil, nil, nil); + player:endEvent(); +end \ No newline at end of file From 460722d3d5be1c42abdfd260f2216d87f363ac99 Mon Sep 17 00:00:00 2001 From: yogurt Date: Wed, 11 Oct 2017 06:42:06 -0500 Subject: [PATCH 7/9] Opening changes --- FFXIVClassic Map Server/WorldManager.cs | 3 +- .../actors/chara/Character.cs | 1 - .../actors/chara/npc/BattleNpc.cs | 2 +- data/scripts/content/SimpleContent30010.lua | 36 ++++++++++--------- .../directors/Quest/QuestDirectorMan0g001.lua | 11 +++--- data/scripts/spells/blizzara.lua | 19 ++++++++++ data/scripts/spells/thunder.lua | 18 ++++++++++ 7 files changed, 65 insertions(+), 25 deletions(-) create mode 100644 data/scripts/spells/blizzara.lua create mode 100644 data/scripts/spells/thunder.lua diff --git a/FFXIVClassic Map Server/WorldManager.cs b/FFXIVClassic Map Server/WorldManager.cs index a3c2db1d..69b55b3b 100644 --- a/FFXIVClassic Map Server/WorldManager.cs +++ b/FFXIVClassic Map Server/WorldManager.cs @@ -640,7 +640,8 @@ namespace FFXIVClassic_Map_Server battleNpc.dropListId = reader.GetUInt32("dropListId"); battleNpc.spellListId = reader.GetUInt32("spellListId"); battleNpc.skillListId = reader.GetUInt32("skillListId"); - + battleNpc.SetMaxHP(1000); + battleNpc.SetHP(1000); battleNpc.SetBattleNpcId(reader.GetUInt32("bnpcId")); battleNpc.CalculateBaseStats(); battleNpc.RecalculateStats(); diff --git a/FFXIVClassic Map Server/actors/chara/Character.cs b/FFXIVClassic Map Server/actors/chara/Character.cs index c9621219..e34164ac 100644 --- a/FFXIVClassic Map Server/actors/chara/Character.cs +++ b/FFXIVClassic Map Server/actors/chara/Character.cs @@ -603,7 +603,6 @@ namespace FFXIVClassic_Map_Server.Actors { if (GetMod((uint)Modifier.Hp) != 0) { - } // todo: recalculate stats and crap updateFlags |= ActorUpdateFlags.HpTpMp; diff --git a/FFXIVClassic Map Server/actors/chara/npc/BattleNpc.cs b/FFXIVClassic Map Server/actors/chara/npc/BattleNpc.cs index c528a12c..e52940fc 100644 --- a/FFXIVClassic Map Server/actors/chara/npc/BattleNpc.cs +++ b/FFXIVClassic Map Server/actors/chara/npc/BattleNpc.cs @@ -82,7 +82,7 @@ namespace FFXIVClassic_Map_Server.Actors //charaWork.property[2] = 1; //npcWork.hateType = 1; - + this.hateContainer = new HateContainer(this); this.allegiance = CharacterTargetingAllegiance.BattleNpcs; diff --git a/data/scripts/content/SimpleContent30010.lua b/data/scripts/content/SimpleContent30010.lua index 3e3b72f9..6f1a7de6 100644 --- a/data/scripts/content/SimpleContent30010.lua +++ b/data/scripts/content/SimpleContent30010.lua @@ -1,29 +1,33 @@ require ("global") +require ("modifiers") function onCreate(starterPlayer, contentArea, director) --papalymo = contentArea:SpawnActor(2290005, "papalymo", 365.89, 4.0943, -706.72, -0.718); --yda = contentArea:SpawnActor(2290006, "yda", 365.266, 4.122, -700.73, 1.5659); - --yda = GetWorldManager().SpawnBattleNpcById(6, contentArea); - --papalymo = GetWorldManager().SpawnBattleNpcById(7, contentArea); - - --mob1 = GetWorldManager().SpawnBattleNpcById(3, contentArea); - --mob2 = GetWorldManager().SpawnBattleNpcById(4, contentArea); - --mob3 = GetWorldManager().SpawnBattleNpcById(5, contentArea); - ---yda:ChangeState(2); - + --mob1 = contentArea:SpawnActor(2201407, "mob1", 374.427, 4.4, -698.711, -1.942); --mob2 = contentArea:SpawnActor(2201407, "mob2", 375.377, 4.4, -700.247, -1.992); --mob3 = contentArea:SpawnActor(2201407, "mob3", 375.125, 4.4, -703.591, -1.54); + yda = GetWorldManager().SpawnBattleNpcById(6, contentArea); + papalymo = GetWorldManager().SpawnBattleNpcById(7, contentArea); + yda:ChangeState(2); + mob1 = GetWorldManager().SpawnBattleNpcById(3, contentArea); + mob2 = GetWorldManager().SpawnBattleNpcById(4, contentArea); + mob3 = GetWorldManager().SpawnBattleNpcById(5, contentArea); + starterPlayer.currentParty.members:Add(yda.actorId); + starterPlayer.currentParty.members:Add(papalymo.actorId); + starterPlayer:SetMod(modifiersGlobal.MinimumHpLock, 1); - --openingStoper = contentArea:SpawnActor(1090384, "openingstoper", 356.09, 3.74, -701.62, -1.41); - --director:AddMember(starterPlayer); - --director:AddMember(director); --- director:AddMember(papalymo); - --director:AddMember(yda); - --director:AddMember(mob1); - --director:AddMember(mob2); - --director:AddMember(mob3); + openingStoper = contentArea:SpawnActor(1090384, "openingstoper", 356.09, 3.74, -701.62, -1.41); + + director:AddMember(starterPlayer); + director:AddMember(director); + director:AddMember(papalymo); + director:AddMember(yda); + director:AddMember(mob1); + director:AddMember(mob2); + director:AddMember(mob3); --director:StartContentGroup(); diff --git a/data/scripts/directors/Quest/QuestDirectorMan0g001.lua b/data/scripts/directors/Quest/QuestDirectorMan0g001.lua index e6dc16e3..26dacb87 100644 --- a/data/scripts/directors/Quest/QuestDirectorMan0g001.lua +++ b/data/scripts/directors/Quest/QuestDirectorMan0g001.lua @@ -13,10 +13,10 @@ end function onCreateContentArea(players, director, contentArea, contentGroup) local worldManager = GetWorldManager(); - - yda = GetWorldManager().SpawnBattleNpcById(6, contentArea); - papalymo = GetWorldManager().SpawnBattleNpcById(7, contentArea); - + --[[ + --yda = GetWorldManager().SpawnBattleNpcById(6, contentArea); + --papalymo = GetWorldManager().SpawnBattleNpcById(7, contentArea); + --yda:ChangeState(2); mob1 = GetWorldManager().SpawnBattleNpcById(3, contentArea); mob2 = GetWorldManager().SpawnBattleNpcById(4, contentArea); mob3 = GetWorldManager().SpawnBattleNpcById(5, contentArea); @@ -47,7 +47,6 @@ function onCreateContentArea(players, director, contentArea, contentGroup) print("shittttt2"); director:AddMember(player) print("shittttt1"); - --GetWorldManager():DoZoneChangeContent(player, contentArea, 362.4087, 4, -703.8168, 1.5419, 16); end; print("shit") director:AddMember(director); @@ -58,7 +57,7 @@ function onCreateContentArea(players, director, contentArea, contentGroup) print("shit6") director:AddMember(mob3); print("dicks") - +]] director:StartContentGroup(); end diff --git a/data/scripts/spells/blizzara.lua b/data/scripts/spells/blizzara.lua new file mode 100644 index 00000000..72ccc0bd --- /dev/null +++ b/data/scripts/spells/blizzara.lua @@ -0,0 +1,19 @@ +function onSpellPrepare(caster, target, spell) + return 0; +end; + +function onSpellStart(caster, target, spell) + return 0; +end; + +function onSpellFinish(caster, target, spell, action) + local damage = math.random(10, 100); + print("fuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuckkk") + + action.param = damage; + if target.hateContainer then + target.hateContainer.AddBaseHate(caster); + target.hateContainer.UpdateHate(caster, damage); + end; + return damage; +end; \ No newline at end of file diff --git a/data/scripts/spells/thunder.lua b/data/scripts/spells/thunder.lua new file mode 100644 index 00000000..1418061a --- /dev/null +++ b/data/scripts/spells/thunder.lua @@ -0,0 +1,18 @@ +function onSpellPrepare(caster, target, spell) + return 0; +end; + +function onSpellStart(caster, target, spell) + return 0; +end; + +function onSpellFinish(caster, target, spell, action) + local damage = math.random(10, 100); + print("fuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuckkk") + + if target.hateContainer then + target.hateContainer.AddBaseHate(caster); + target.hateContainer.UpdateHate(caster, damage); + end; + return damage; +end; \ No newline at end of file From 520ae7a119b150a72db2da4d2e2d1eb37d58d0c2 Mon Sep 17 00:00:00 2001 From: Tahir Akhlaq Date: Wed, 11 Oct 2017 14:46:24 +0100 Subject: [PATCH 8/9] added helpers for DoW/DoM/DoH/DoH - fixed allies not being able to aggro on roam - fixed static characters aggroing --- FFXIVClassic Map Server/WorldManager.cs | 9 +- FFXIVClassic Map Server/actors/area/Area.cs | 2 +- FFXIVClassic Map Server/actors/area/Zone.cs | 3 +- .../actors/chara/Character.cs | 35 ++++- .../chara/ai/controllers/AllyController.cs | 15 ++ .../ai/controllers/BattleNpcController.cs | 3 +- .../actors/chara/npc/Ally.cs | 2 + .../actors/chara/npc/BattleNpc.cs | 1 - .../actors/chara/player/Player.cs | 13 -- .../directors/Quest/QuestDirectorMan0g001.lua | 92 +++++------- data/scripts/global.lua | 8 ++ .../Monster/bloodthirsty_wolf.lua | 58 -------- .../unique/fst0Battle03/Monster/papalymo.lua | 17 ++- .../unique/fst0Battle03/Monster/yda.lua | 11 ++ sql/server_battlenpc_genus.sql | 132 +++++++++--------- sql/server_battlenpc_groups.sql | 2 +- sql/server_battlenpc_pools.sql | 10 +- sql/server_battlenpc_spawn_locations.sql | 12 +- 18 files changed, 208 insertions(+), 217 deletions(-) diff --git a/FFXIVClassic Map Server/WorldManager.cs b/FFXIVClassic Map Server/WorldManager.cs index 69b55b3b..77c61050 100644 --- a/FFXIVClassic Map Server/WorldManager.cs +++ b/FFXIVClassic Map Server/WorldManager.cs @@ -593,8 +593,15 @@ namespace FFXIVClassic_Map_Server // todo: add to private areas, set up immunity, mob linking, // - load skill/spell/drop lists, set detection icon, load pool/family/group mods + var allegiance = (CharacterTargetingAllegiance)reader.GetByte("allegiance"); + BattleNpc battleNpc = null; - var battleNpc = new BattleNpc(actorId, Server.GetWorldManager().GetActorClass(reader.GetUInt32("actorClassId")), + if (allegiance == CharacterTargetingAllegiance.Player) + battleNpc = new Ally(actorId, Server.GetWorldManager().GetActorClass(reader.GetUInt32("actorClassId")), + reader.GetString("scriptName"), area, reader.GetFloat("positionX"), reader.GetFloat("positionY"), reader.GetFloat("positionZ"), reader.GetFloat("rotation"), + reader.GetUInt16("actorState"), reader.GetUInt32("animationId"), ""); + else + battleNpc = new BattleNpc(actorId, Server.GetWorldManager().GetActorClass(reader.GetUInt32("actorClassId")), reader.GetString("scriptName"), area, reader.GetFloat("positionX"), reader.GetFloat("positionY"), reader.GetFloat("positionZ"), reader.GetFloat("rotation"), reader.GetUInt16("actorState"), reader.GetUInt32("animationId"), ""); diff --git a/FFXIVClassic Map Server/actors/area/Area.cs b/FFXIVClassic Map Server/actors/area/Area.cs index b3a0e6c2..9363319a 100644 --- a/FFXIVClassic Map Server/actors/area/Area.cs +++ b/FFXIVClassic Map Server/actors/area/Area.cs @@ -472,7 +472,7 @@ namespace FFXIVClassic_Map_Server.Actors } } - public Npc SpawnActor(uint classId, string uniqueId, float x, float y, float z, float rot = 0, ushort state = 0, uint animId = 0, bool isMob = true) + public Npc SpawnActor(uint classId, string uniqueId, float x, float y, float z, float rot = 0, ushort state = 0, uint animId = 0, bool isMob = false) { lock (mActorList) { diff --git a/FFXIVClassic Map Server/actors/area/Zone.cs b/FFXIVClassic Map Server/actors/area/Zone.cs index dc3a5787..1286657f 100644 --- a/FFXIVClassic Map Server/actors/area/Zone.cs +++ b/FFXIVClassic Map Server/actors/area/Zone.cs @@ -168,15 +168,14 @@ namespace FFXIVClassic_Map_Server.actors.area public override void Update(DateTime tick) { base.Update(tick); + foreach (var a in privateAreas.Values) foreach(var b in a.Values) b.Update(tick); foreach (var a in contentAreas.Values) foreach (var b in a) - { b.Update(tick); - } // todo: again, this is retarded but debug stuff var diffTime = tick - lastUpdate; diff --git a/FFXIVClassic Map Server/actors/chara/Character.cs b/FFXIVClassic Map Server/actors/chara/Character.cs index e34164ac..fc71863d 100644 --- a/FFXIVClassic Map Server/actors/chara/Character.cs +++ b/FFXIVClassic Map Server/actors/chara/Character.cs @@ -45,6 +45,19 @@ namespace FFXIVClassic_Map_Server.Actors public const int CLASSID_THM = 22; public const int CLASSID_CNJ = 23; + public const int CLASSID_CRP = 29; + public const int CLASSID_BSM = 30; + public const int CLASSID_ARM = 31; + public const int CLASSID_GSM = 32; + public const int CLASSID_LTW = 33; + public const int CLASSID_WVR = 34; + public const int CLASSID_ALC = 35; + public const int CLASSID_CUL = 36; + + public const int CLASSID_MIN = 39; + public const int CLASSID_BTN = 40; + public const int CLASSID_FSH = 41; + public const int SIZE = 0; public const int COLORINFO = 1; public const int FACEINFO = 2; @@ -347,7 +360,7 @@ namespace FFXIVClassic_Map_Server.Actors public virtual bool IsValidTarget(Character target, ValidTarget validTarget) { - return true; + return !target.isStatic; } public virtual bool CanAttack() @@ -753,6 +766,26 @@ namespace FFXIVClassic_Map_Server.Actors { return this is Ally; } + + public bool IsDiscipleOfWar() + { + return currentJob < CLASSID_THM; + } + + public bool IsDiscipleOfMagic() + { + return currentJob >= CLASSID_THM && currentJob < CLASSID_CRP; + } + + public bool IsDiscipleOfHand() + { + return currentJob >= CLASSID_CRP && currentJob < CLASSID_MIN; + } + + public bool IsDiscipleOfLand() + { + return currentJob >= CLASSID_MIN; + } #endregion lua helpers #endregion ai stuff } diff --git a/FFXIVClassic Map Server/actors/chara/ai/controllers/AllyController.cs b/FFXIVClassic Map Server/actors/chara/ai/controllers/AllyController.cs index b5820871..5f748f72 100644 --- a/FFXIVClassic Map Server/actors/chara/ai/controllers/AllyController.cs +++ b/FFXIVClassic Map Server/actors/chara/ai/controllers/AllyController.cs @@ -34,5 +34,20 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers } base.DoCombatTick(tick, contentGroupCharas); } + protected override void DoRoamTick(DateTime tick, List contentGroupCharas = null) + { + if (owner.currentContentGroup != null) + { + contentGroupCharas = new List(owner.currentContentGroup.GetMemberCount()); + foreach (var charaId in owner.currentContentGroup.GetMembers()) + { + var chara = owner.zone.FindActorInArea(charaId); + + if (chara != null) + contentGroupCharas.Add(chara); + } + } + base.DoRoamTick(tick, contentGroupCharas); + } } } diff --git a/FFXIVClassic Map Server/actors/chara/ai/controllers/BattleNpcController.cs b/FFXIVClassic Map Server/actors/chara/ai/controllers/BattleNpcController.cs index 3a802c19..50280503 100644 --- a/FFXIVClassic Map Server/actors/chara/ai/controllers/BattleNpcController.cs +++ b/FFXIVClassic Map Server/actors/chara/ai/controllers/BattleNpcController.cs @@ -127,7 +127,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers // todo: } - protected virtual void DoRoamTick(DateTime tick) + protected virtual void DoRoamTick(DateTime tick, List contentGroupCharas = null) { if (owner.hateContainer.GetHateList().Count > 0) { @@ -159,6 +159,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers owner.aiContainer.pathFind.SetPathFlags(PathFindFlags.None); owner.aiContainer.pathFind.PathInRange(owner.spawnX, owner.spawnY, owner.spawnZ, 1.5f, 50.0f); } + lua.LuaEngine.CallLuaBattleFunction(owner, "onRoam", owner, contentGroupCharas); } diff --git a/FFXIVClassic Map Server/actors/chara/npc/Ally.cs b/FFXIVClassic Map Server/actors/chara/npc/Ally.cs index 5ef2546b..d8924544 100644 --- a/FFXIVClassic Map Server/actors/chara/npc/Ally.cs +++ b/FFXIVClassic Map Server/actors/chara/npc/Ally.cs @@ -18,6 +18,8 @@ namespace FFXIVClassic_Map_Server.actors.chara.npc { aiContainer = new AIContainer(this, new AllyController(this), new PathFind(this), new TargetFind(this)); this.allegiance = CharacterTargetingAllegiance.Player; + this.isAutoAttackEnabled = true; + this.isMovingToSpawn = false; } } } diff --git a/FFXIVClassic Map Server/actors/chara/npc/BattleNpc.cs b/FFXIVClassic Map Server/actors/chara/npc/BattleNpc.cs index e52940fc..07e8d69d 100644 --- a/FFXIVClassic Map Server/actors/chara/npc/BattleNpc.cs +++ b/FFXIVClassic Map Server/actors/chara/npc/BattleNpc.cs @@ -365,7 +365,6 @@ namespace FFXIVClassic_Map_Server.Actors { this.isMovingToSpawn = false; } - lua.LuaEngine.CallLuaBattleFunction(this, "onRoam", this); } } diff --git a/FFXIVClassic Map Server/actors/chara/player/Player.cs b/FFXIVClassic Map Server/actors/chara/player/Player.cs index cd2d3509..5262425c 100644 --- a/FFXIVClassic Map Server/actors/chara/player/Player.cs +++ b/FFXIVClassic Map Server/actors/chara/player/Player.cs @@ -31,19 +31,6 @@ namespace FFXIVClassic_Map_Server.Actors { class Player : Character { - public const int CLASSID_CRP = 29; - public const int CLASSID_BSM = 30; - public const int CLASSID_ARM = 31; - public const int CLASSID_GSM = 32; - public const int CLASSID_LTW = 33; - public const int CLASSID_WVR = 34; - public const int CLASSID_ALC = 35; - public const int CLASSID_CUL = 36; - - public const int CLASSID_MIN = 39; - public const int CLASSID_BTN = 40; - public const int CLASSID_FSH = 41; - public const int MAXSIZE_INVENTORY_NORMAL = 200; public const int MAXSIZE_INVENTORY_CURRANCY = 320; public const int MAXSIZE_INVENTORY_KEYITEMS = 500; diff --git a/data/scripts/directors/Quest/QuestDirectorMan0g001.lua b/data/scripts/directors/Quest/QuestDirectorMan0g001.lua index 26dacb87..1c766c02 100644 --- a/data/scripts/directors/Quest/QuestDirectorMan0g001.lua +++ b/data/scripts/directors/Quest/QuestDirectorMan0g001.lua @@ -11,78 +11,54 @@ function init() end function onCreateContentArea(players, director, contentArea, contentGroup) - - local worldManager = GetWorldManager(); - --[[ - --yda = GetWorldManager().SpawnBattleNpcById(6, contentArea); - --papalymo = GetWorldManager().SpawnBattleNpcById(7, contentArea); - --yda:ChangeState(2); - mob1 = GetWorldManager().SpawnBattleNpcById(3, contentArea); - mob2 = GetWorldManager().SpawnBattleNpcById(4, contentArea); - mob3 = GetWorldManager().SpawnBattleNpcById(5, contentArea); - - --papalymo = contentArea:SpawnActor(2290005, "papalymo", 365.89, 4.0943, -706.72, -0.718); - --yda = contentArea:SpawnActor(2290006, "yda", 365.266, 4.122, -700.73, 1.5659); - --yda:ChangeState(2); - - --mob1 = contentArea:SpawnActor(2201407, "mob1", 374.427, 4.4, -698.711, -1.942); - --mob2 = contentArea:SpawnActor(2201407, "mob2", 375.377, 4.4, -700.247, -1.992); - --mob3 = contentArea:SpawnActor(2201407, "mob3", 375.125, 4.4, -703.591, -1.54); - - openingStoper = contentArea:SpawnActor(1090384, "openingstoper", 356.09, 3.74, -701.62, -1.41); - - - local added = false; - for player in players do - if player.currentParty and not added then - player.currentParty.members:Add(yda.actorId); - print("cunt"); - player.currentParty.members:Add(papalymo.actorId); - print("dickbag"); - added = true; - end; - -- dont let player die - print("shittttt3"); - player:SetMod(modifiersGlobal.MinimumHpLock, 1); - print("shittttt2"); - director:AddMember(player) - print("shittttt1"); - end; - print("shit") - director:AddMember(director); - director:AddMember(yda); - director:AddMember(papalymo); - director:AddMember(mob1); - director:AddMember(mob2); - print("shit6") - director:AddMember(mob3); - print("dicks") -]] director:StartContentGroup(); end -function onEventStarted(player, actor, triggerName) - +function onEventStarted(player, actor, triggerName) man0g0Quest = player:GetQuest("Man0g0"); startTutorialMode(player); callClientFunction(player, "delegateEvent", player, man0g0Quest, "processTtrBtl001", nil, nil, nil); player:EndEvent(); waitForSignal("playerActive"); - wait(2); --If this isn't here, the scripts bugs out. TODO: Find a better alternative. + wait(1); --If this isn't here, the scripts bugs out. TODO: Find a better alternative. kickEventContinue(player, actor, "noticeEvent", "noticeEvent"); callClientFunction(player, "delegateEvent", player, man0g0Quest, "processTtrBtl002", nil, nil, nil); player:EndEvent(); - + waitForSignal("playerAttack"); closeTutorialWidget(player); + showTutorialSuccessWidget(player, 9055); --Open TutorialSuccessWidget for attacking enemy wait(3); - - man0g0Quest:NextPhase(5); openTutorialWidget(player, CONTROLLER_KEYBOARD, TUTORIAL_TP); - wait(5); - - man0g0Quest:NextPhase(6); + waitForSignal("tpOver1000"); closeTutorialWidget(player); - print("ass") + openTutorialWidget(player, CONTROLLER_KEYBOARD, TUTORIAL_WEAPONSKILLS); + + if player:IsDiscipleOfWar() then + waitForSignal("weaponskillUsed"); --Should be wait for weaponskillUsed signal + elseif player:IsDiscipleOfMagic() then + waitForSignal("spellUsed") + elseif player:IsDiscipleOfHand() then + waitForSignal("abilityUsed") + elseif player:IsDiscipleOfLand() then + waitForSignal("abilityUsed") + end + closeTutorialWidget(player); + showTutorialSuccessWidget(player, 9065); --Open TutorialSuccessWidget for weapon skill + + waitForSignal("mobkill"); --Should be wait for mobkill + waitForSignal("mobkill"); + waitForSignal("mobkill"); + worldMaster = GetWorldMaster(); + player:SendDataPacket("attention", worldMaster, "", 51073, 2); + wait(7); + player:ChangeMusic(7); + player:ChangeState(0); + kickEventContinue(player, actor, "noticeEvent", "noticeEvent"); + callClientFunction(player, "delegateEvent", player, man0g0Quest, "processEvent020_1", nil, nil, nil); + + player:GetZone():ContentFinished(); + player:EndEvent(); + GetWorldManager():DoZoneChange(player, 155, "PrivateAreaMasterPast", 1, 15, 175.38, -1.21, -1156.51, -2.1); --[[ IF DoW: OpenWidget (TP) @@ -104,7 +80,6 @@ function onEventStarted(player, actor, triggerName) end function onUpdate(deltaTime, area) - print("fuck") end function onTalkEvent(player, npc) @@ -125,6 +100,5 @@ function onCommand(player, command) end function main(director, contentGroup) - print("shitstain") onCreateContentArea(director:GetPlayerMembers(), director, director:GetZone(), contentGroup); end; \ No newline at end of file diff --git a/data/scripts/global.lua b/data/scripts/global.lua index b26475fb..770c09ff 100644 --- a/data/scripts/global.lua +++ b/data/scripts/global.lua @@ -116,6 +116,14 @@ DAMAGE_TAKEN_TYPE_MAGIC = 2; DAMAGE_TAKEN_TYPE_WEAPONSKILL = 3; DAMAGE_TAKEN_TYPE_ABILITY = 4; +-- CLASSID +CLASSID_PUG = 2; +CLASSID_GLA = 3; +CLASSID_MRD = 4; +CLASSID_ARC = 7; +CLASSID_LNC = 8; +CLASSID_THM = 22; +CLASSID_CNJ = 23; --UTILS diff --git a/data/scripts/unique/fst0Battle03/Monster/bloodthirsty_wolf.lua b/data/scripts/unique/fst0Battle03/Monster/bloodthirsty_wolf.lua index d0f3b4cb..e69de29b 100644 --- a/data/scripts/unique/fst0Battle03/Monster/bloodthirsty_wolf.lua +++ b/data/scripts/unique/fst0Battle03/Monster/bloodthirsty_wolf.lua @@ -1,58 +0,0 @@ -require ("global") -require ("modifiers") -require ("ally") - -function onSpawn(mob) - -end; - -function onDamageTaken(mob, attacker, damage, damageType) - if attacker.IsPlayer() then - local man0g0Quest = attacker:GetQuest("Man0g0"); - if damageType == DAMAGE_TAKEN_TYPE_ATTACK then - if man0g0Quest:GetPhase() == 5 then - closeTutorialWidget(player); - showTutorialSuccessWidget(player, 9055); --Open TutorialSuccessWidget for attacking enemy - man0g0Quest:NextPhase(6); - end; - elseif damageType == DAMAGE_TAKEN_TYPE_WEAPONSKILL or damageType == DAMAGE_TAKEN_TYPE_MAGIC then - if man0g0Quest:GetPhase() == 6 then - closeTutorialWidget(player); - showTutorialSuccessWidget(player, 9065); --Open TutorialSuccessWidget for weapon skill - man0g0Quest:NextPhase(7); - end; - end; - end; -end; - -function onDeath(mob, player, lastAttacker) - if player then - local man0g0Quest = player:GetQuest("Man0g0"); - if man0g0Quest and man0g0Quest:GetPhase() >= 7 then - man0g0Quest:NextPhase(man0g0Quest:GetPhase() + 1); - mob:SetTempVar("playerId", player.actorId); - if man0g0Quest:GetPhase() == 10 then - local worldMaster = GetWorldMaster(); - player:SendDataPacket("attention", worldMaster, "", 51073, 1); - kickEventContinue(player, director, "noticeEvent", "noticeEvent"); - callClientFunction(player, "delegateEvent", player, man0g0Quest, "processEvent020_1", nil, nil, nil); - player:ChangeMusic(7); - player:Disengage(0x0000); - mob:SetTempVar("complete", 1); - end; - end; - end; -end; - -function onDespawn(mob) - if zone then - local player = zone.FindActorInArea(mob:GetTempVar("playerId")); - - if player and mob:GetTempVar("complete") == 1 then - local man0g0Quest = player:GetQuest("Man0g0"); - player:GetZone():ContentFinished(); - player:EndEvent(); - GetWorldManager():DoZoneChange(player, 155, "PrivateAreaMasterPast", 1, 15, 175.38, -1.21, -1156.51, -2.1); - end; - end; -end; \ No newline at end of file diff --git a/data/scripts/unique/fst0Battle03/Monster/papalymo.lua b/data/scripts/unique/fst0Battle03/Monster/papalymo.lua index a262f46b..cc9807e1 100644 --- a/data/scripts/unique/fst0Battle03/Monster/papalymo.lua +++ b/data/scripts/unique/fst0Battle03/Monster/papalymo.lua @@ -1,11 +1,22 @@ require ("global") - require ("ally") function onSpawn(ally) + ally:SetMaxHP(69420) + ally:SetHP(ally:GetMaxHP()) ally.isAutoAttackEnabled = false; -end; + ally.neutral = false +end function onCombatTick(ally, target, tick, contentGroupCharas) allyGlobal.onCombatTick(ally, target, tick, contentGroupCharas); -end; \ No newline at end of file +end + + +function onRoam(ally, contentGroupCharas) + ally.detectionType = 0xFF + ally.isMovingToSpawn = false + ally.neutral = false + ally.animationId = 0 + allyGlobal.onCombatTick(ally, nil, nil, contentGroupCharas) +end \ No newline at end of file diff --git a/data/scripts/unique/fst0Battle03/Monster/yda.lua b/data/scripts/unique/fst0Battle03/Monster/yda.lua index 2abf6f76..0c8a9523 100644 --- a/data/scripts/unique/fst0Battle03/Monster/yda.lua +++ b/data/scripts/unique/fst0Battle03/Monster/yda.lua @@ -3,9 +3,20 @@ require ("global") require ("ally") function onSpawn(ally) + ally:SetMaxHP(69420) + ally:SetHP(ally:GetMaxHP()) ally.isAutoAttackEnabled = false + ally.neutral = false end function onCombatTick(ally, target, tick, contentGroupCharas) allyGlobal.onCombatTick(ally, target, tick, contentGroupCharas) +end + +function onRoam(ally, contentGroupCharas) + ally.detectionType = 0xFF + ally.isMovingToSpawn = false + ally.neutral = false + ally.animationId = 0 + allyGlobal.onCombatTick(ally, contentGroupCharas) end \ No newline at end of file diff --git a/sql/server_battlenpc_genus.sql b/sql/server_battlenpc_genus.sql index cb6ad985..8c5793bb 100644 --- a/sql/server_battlenpc_genus.sql +++ b/sql/server_battlenpc_genus.sql @@ -65,71 +65,71 @@ CREATE TABLE `server_battlenpc_genus` ( LOCK TABLES `server_battlenpc_genus` WRITE; /*!40000 ALTER TABLE `server_battlenpc_genus` DISABLE KEYS */; set autocommit=0; -INSERT INTO `server_battlenpc_genus` VALUES (1,'Aldgoat',1,0,1,'Beast',1,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (2,'Antelope',1,0,1,'Beast',1,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (3,'Wolf',1,0,1,'Beast',2,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (4,'Opo-opo',1,0,1,'Beast',1,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (5,'Coeurl',1,0,1,'Beast',15,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (6,'Goobbue',1,0,1,'Beast',4,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (7,'Sheep',1,0,1,'Beast',1,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (8,'Buffalo',1,0,1,'Beast',4,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (9,'Boar',1,0,1,'Beast',2,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (10,'Moon-Mouse?',1,0,1,'Beast',2,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (11,'Mole',1,0,1,'Beast',4,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (12,'Rodent',1,0,1,'Beast',2,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (13,'Cactuar',1,0,2,'Plantoid',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (14,'Funguar',1,0,2,'Plantoid',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (15,'Flying-trap',1,0,2,'Plantoid',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (16,'Morbol',1,0,2,'Plantoid',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (17,'Orobon',1,0,3,'Aquan',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (18,'Gigantoad',1,0,3,'Aquan',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (19,'Salamander',1,0,3,'Aquan',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (20,'Jelly-fish',1,0,3,'Aquan',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (21,'Slug',1,0,3,'Aquan',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (22,'Megalo-crab',1,0,3,'Aquan',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (23,'Amaalja',1,0,4,'Spoken',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (24,'Ixal',1,0,4,'Spoken',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (25,'Qiqirn',1,0,4,'Spoken',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (26,'Goblin',1,0,4,'Spoken',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (27,'Kobold',1,0,4,'Spoken',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (28,'Sylph',1,0,4,'Spoken',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (29,'Person',1,0,4,'Spoken',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (30,'Drake',1,0,5,'Reptilian',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (31,'Basilisk',1,0,5,'Reptilian',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (32,'Raptor',1,0,5,'Reptilian',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (33,'Ant-ring',1,0,6,'Insect',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (34,'Swarm',1,0,6,'Insect',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (35,'Diremite',1,0,6,'Insect',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (36,'Chigoe',1,0,6,'Insect',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (37,'Gnat',1,0,6,'Insect',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (38,'Beetle',1,0,6,'Insect',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (39,'Yarzon',1,0,6,'Insect',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (40,'Apkallu',1,0,7,'Avian',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (41,'Vulture',1,0,7,'Avian',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (42,'Dodo',1,0,7,'Avian',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (43,'Bat',1,0,7,'Avian',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (44,'Hippogryph',1,0,7,'Avian',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (45,'Puk',1,0,7,'Avian',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (46,'Ghost',1,0,8,'Undead',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (47,'The-Damned',1,0,8,'Undead',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (48,'Wight',1,0,8,'Undead',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (49,'Coblyn',1,0,9,'Cursed',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (50,'Spriggan',1,0,9,'Cursed',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (51,'Ahriman',1,0,10,'Voidsent',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (52,'Imp',1,0,10,'Voidsent',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (53,'Will-O-Wisp',1,0,10,'Voidsent',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (54,'Fire-Elemental',1,0,10,'Voidsent',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (55,'Water-Elemental',1,0,10,'Voidsent',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (56,'Earth-Elemental',1,0,10,'Voidsent',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (57,'Lightning-Elemental',1,0,10,'Voidsent',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (58,'Ice-Elemental',1,0,10,'Voidsent',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (59,'Wind-Elemental',1,0,10,'Voidsent',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (60,'Ogre',1,0,10,'Voidsent',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (61,'Phurble',1,0,10,'Voidsent',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (62,'Plasmoid',1,0,10,'Voidsent',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (63,'Flan',1,0,10,'Voidsent',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (64,'Bomb',1,0,10,'Voidsent',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); -INSERT INTO `server_battlenpc_genus` VALUES (65,'Grenade',1,0,10,'Voidsent',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (1,'Aldgoat',1,8,1,'Beast',1,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (2,'Antelope',1,8,1,'Beast',1,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (3,'Wolf',1,8,1,'Beast',2,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (4,'Opo-opo',1,8,1,'Beast',1,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (5,'Coeurl',1,8,1,'Beast',15,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (6,'Goobbue',1,8,1,'Beast',4,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (7,'Sheep',1,8,1,'Beast',1,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (8,'Buffalo',1,8,1,'Beast',4,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (9,'Boar',1,8,1,'Beast',2,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (10,'Moon-Mouse?',1,8,1,'Beast',2,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (11,'Mole',1,8,1,'Beast',4,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (12,'Rodent',1,8,1,'Beast',2,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (13,'Cactuar',1,8,2,'Plantoid',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (14,'Funguar',1,8,2,'Plantoid',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (15,'Flying-trap',1,8,2,'Plantoid',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (16,'Morbol',1,8,2,'Plantoid',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (17,'Orobon',1,8,3,'Aquan',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (18,'Gigantoad',1,8,3,'Aquan',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (19,'Salamander',1,8,3,'Aquan',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (20,'Jelly-fish',1,8,3,'Aquan',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (21,'Slug',1,8,3,'Aquan',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (22,'Megalo-crab',1,8,3,'Aquan',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (23,'Amaalja',1,8,4,'Spoken',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (24,'Ixal',1,8,4,'Spoken',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (25,'Qiqirn',1,8,4,'Spoken',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (26,'Goblin',1,8,4,'Spoken',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (27,'Kobold',1,8,4,'Spoken',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (28,'Sylph',1,8,4,'Spoken',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (29,'Person',1,8,4,'Spoken',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (30,'Drake',1,8,5,'Reptilian',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (31,'Basilisk',1,8,5,'Reptilian',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (32,'Raptor',1,8,5,'Reptilian',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (33,'Ant-ring',1,8,6,'Insect',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (34,'Swarm',1,8,6,'Insect',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (35,'Diremite',1,8,6,'Insect',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (36,'Chigoe',1,8,6,'Insect',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (37,'Gnat',1,8,6,'Insect',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (38,'Beetle',1,8,6,'Insect',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (39,'Yarzon',1,8,6,'Insect',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (40,'Apkallu',1,8,7,'Avian',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (41,'Vulture',1,8,7,'Avian',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (42,'Dodo',1,8,7,'Avian',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (43,'Bat',1,8,7,'Avian',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (44,'Hippogryph',1,8,7,'Avian',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (45,'Puk',1,8,7,'Avian',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (46,'Ghost',1,8,8,'Undead',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (47,'The-Damned',1,8,8,'Undead',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (48,'Wight',1,8,8,'Undead',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (49,'Coblyn',1,8,9,'Cursed',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (50,'Spriggan',1,8,9,'Cursed',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (51,'Ahriman',1,8,10,'Voidsent',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (52,'Imp',1,8,10,'Voidsent',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (53,'Will-O-Wisp',1,8,10,'Voidsent',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (54,'Fire-Elemental',1,8,10,'Voidsent',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (55,'Water-Elemental',1,8,10,'Voidsent',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (56,'Earth-Elemental',1,8,10,'Voidsent',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (57,'Lightning-Elemental',1,8,10,'Voidsent',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (58,'Ice-Elemental',1,8,10,'Voidsent',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (59,'Wind-Elemental',1,8,10,'Voidsent',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (60,'Ogre',1,8,10,'Voidsent',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (61,'Phurble',1,8,10,'Voidsent',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (62,'Plasmoid',1,8,10,'Voidsent',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (63,'Flan',1,8,10,'Voidsent',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (64,'Bomb',1,8,10,'Voidsent',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); +INSERT INTO `server_battlenpc_genus` VALUES (65,'Grenade',1,8,10,'Voidsent',0,100,100,100,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0); /*!40000 ALTER TABLE `server_battlenpc_genus` ENABLE KEYS */; UNLOCK TABLES; commit; @@ -143,4 +143,4 @@ commit; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2017-09-16 2:42:51 +-- Dump completed on 2017-10-11 14:48:52 diff --git a/sql/server_battlenpc_groups.sql b/sql/server_battlenpc_groups.sql index e04c0014..d5bea565 100644 --- a/sql/server_battlenpc_groups.sql +++ b/sql/server_battlenpc_groups.sql @@ -67,4 +67,4 @@ commit; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2017-09-16 2:42:34 +-- Dump completed on 2017-10-11 14:44:48 diff --git a/sql/server_battlenpc_pools.sql b/sql/server_battlenpc_pools.sql index e7bb7073..11082723 100644 --- a/sql/server_battlenpc_pools.sql +++ b/sql/server_battlenpc_pools.sql @@ -46,12 +46,14 @@ CREATE TABLE `server_battlenpc_pools` ( LOCK TABLES `server_battlenpc_pools` WRITE; /*!40000 ALTER TABLE `server_battlenpc_pools` DISABLE KEYS */; +set autocommit=0; INSERT INTO `server_battlenpc_pools` VALUES (1,2104001,'wharf_rat',12,0,1,4200,1,0,0,0,0,0); -INSERT INTO `server_battlenpc_pools` VALUES (2,2205403,'bloodthirsty_wolf',3,0,1,4200,1,0,0,0,0,0); -INSERT INTO `server_battlenpc_pools` VALUES (3,2290001,'yda',29,2,1,4200,1,0,0,0,0,0); -INSERT INTO `server_battlenpc_pools` VALUES (4,2290002,'papalymo',29,22,1,4200,1,0,0,0,0,0); +INSERT INTO `server_battlenpc_pools` VALUES (2,2201407,'bloodthirsty_wolf',3,0,1,4200,1,0,0,0,0,0); +INSERT INTO `server_battlenpc_pools` VALUES (3,2290005,'yda',29,2,1,4200,1,0,0,0,0,0); +INSERT INTO `server_battlenpc_pools` VALUES (4,2290006,'papalymo',29,22,1,4200,1,0,0,0,0,0); /*!40000 ALTER TABLE `server_battlenpc_pools` ENABLE KEYS */; UNLOCK TABLES; +commit; /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; @@ -62,4 +64,4 @@ UNLOCK TABLES; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2017-09-16 2:40:29 +-- Dump completed on 2017-10-11 14:47:40 diff --git a/sql/server_battlenpc_spawn_locations.sql b/sql/server_battlenpc_spawn_locations.sql index 4e6bbdaa..039614a2 100644 --- a/sql/server_battlenpc_spawn_locations.sql +++ b/sql/server_battlenpc_spawn_locations.sql @@ -43,11 +43,11 @@ LOCK TABLES `server_battlenpc_spawn_locations` WRITE; set autocommit=0; INSERT INTO `server_battlenpc_spawn_locations` VALUES (1,'test',1,25.584,200,-450,-2.514); INSERT INTO `server_battlenpc_spawn_locations` VALUES (2,'test',1,20,200,-444,-3.14); -INSERT INTO `server_battlenpc_spawn_locations` VALUES (3,'bloodthirsty_wolf',2,-3.02,17.35,14.24,-2.81); -INSERT INTO `server_battlenpc_spawn_locations` VALUES (4,'bloodthirsty_wolf',2,0.02,17.35,14.24,-2.81); -INSERT INTO `server_battlenpc_spawn_locations` VALUES (5,'bloodthirsty_wolf',2,-6.02,17.35,14.24,-2.81); -INSERT INTO `server_battlenpc_spawn_locations` VALUES (6,'yshtola',3,-8,16.35,6,0.5); -INSERT INTO `server_battlenpc_spawn_locations` VALUES (7,'papalymo',4,0,16.35,22,3); +INSERT INTO `server_battlenpc_spawn_locations` VALUES (3,'bloodthirsty_wolf',2,374.427,4.4,-698.711,-1.942); +INSERT INTO `server_battlenpc_spawn_locations` VALUES (4,'bloodthirsty_wolf',2,375.377,4.4,-700.247,-1.992); +INSERT INTO `server_battlenpc_spawn_locations` VALUES (5,'bloodthirsty_wolf',2,375.125,4.4,-703.591,-1.54); +INSERT INTO `server_battlenpc_spawn_locations` VALUES (6,'yda',3,365.266,4.122,-700.73,1.5659); +INSERT INTO `server_battlenpc_spawn_locations` VALUES (7,'papalymo',4,365.89,4.0943,-706.72,-0.718); /*!40000 ALTER TABLE `server_battlenpc_spawn_locations` ENABLE KEYS */; UNLOCK TABLES; commit; @@ -61,4 +61,4 @@ commit; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2017-09-16 2:43:52 +-- Dump completed on 2017-10-11 14:47:29 From 27200b8df587feede1d0bde310592aeebbe433d7 Mon Sep 17 00:00:00 2001 From: Tahir Akhlaq Date: Wed, 11 Oct 2017 19:23:40 +0100 Subject: [PATCH 9/9] moved ally engage stuff to ContentArea onUpdate --- FFXIVClassic Map Server/actors/Actor.cs | 2 +- FFXIVClassic Map Server/actors/area/Area.cs | 14 +++++-- .../actors/chara/Character.cs | 25 +++---------- .../actors/chara/ai/HateContainer.cs | 10 +---- .../ai/controllers/BattleNpcController.cs | 8 ++-- .../actors/chara/ai/controllers/Controller.cs | 1 + .../actors/chara/ai/state/AttackState.cs | 4 +- .../actors/chara/npc/BattleNpc.cs | 22 +---------- .../actors/chara/player/Player.cs | 11 +++++- FFXIVClassic Map Server/lua/LuaEngine.cs | 2 +- data/scripts/ally.lua | 24 ++++++------ data/scripts/content/SimpleContent30010.lua | 37 +++++++++++++++++++ .../Monster/bloodthirsty_wolf.lua | 22 +++++++++++ .../unique/fst0Battle03/Monster/papalymo.lua | 15 +------- .../unique/fst0Battle03/Monster/yda.lua | 16 +------- 15 files changed, 115 insertions(+), 98 deletions(-) diff --git a/FFXIVClassic Map Server/actors/Actor.cs b/FFXIVClassic Map Server/actors/Actor.cs index cce7f1a8..15b70eb3 100644 --- a/FFXIVClassic Map Server/actors/Actor.cs +++ b/FFXIVClassic Map Server/actors/Actor.cs @@ -61,7 +61,7 @@ namespace FFXIVClassic_Map_Server.Actors public List classParams; public List positionUpdates; - public DateTime lastMoveUpdate; + protected DateTime lastUpdateScript; protected DateTime lastUpdate; public Actor target; diff --git a/FFXIVClassic Map Server/actors/area/Area.cs b/FFXIVClassic Map Server/actors/area/Area.cs index 9363319a..2d245fe3 100644 --- a/FFXIVClassic Map Server/actors/area/Area.cs +++ b/FFXIVClassic Map Server/actors/area/Area.cs @@ -421,6 +421,11 @@ namespace FFXIVClassic_Map_Server.Actors return GetAllActors(); } + public virtual List GetAllies() + { + return GetAllActors(); + } + public void BroadcastPacketsAroundActor(Actor actor, List packets) { foreach (SubPacket packet in packets) @@ -662,11 +667,14 @@ namespace FFXIVClassic_Map_Server.Actors { lock (mActorList) { - foreach (Actor a in mActorList.Values) + foreach (Actor a in mActorList.Values.ToList()) a.Update(tick); - var deltaTime = (tick - Program.LastTick).TotalMilliseconds; - LuaEngine.GetInstance().CallLuaFunction(null, this, "onUpdate", true, deltaTime, this); + if ((tick - lastUpdateScript).TotalMilliseconds > 1500) + { + LuaEngine.GetInstance().CallLuaFunctionForReturn(LuaEngine.GetScriptPath(this), "onUpdate", true, this, tick); + lastUpdateScript = tick; + } } } diff --git a/FFXIVClassic Map Server/actors/chara/Character.cs b/FFXIVClassic Map Server/actors/chara/Character.cs index fc71863d..6c497bdf 100644 --- a/FFXIVClassic Map Server/actors/chara/Character.cs +++ b/FFXIVClassic Map Server/actors/chara/Character.cs @@ -136,7 +136,6 @@ namespace FFXIVClassic_Map_Server.Actors this.statusEffects = new StatusEffectContainer(this); // todo: move this somewhere more appropriate - ResetMoveSpeeds(); // todo: base this on equip and shit SetMod((uint)Modifier.AttackRange, 3); SetMod((uint)Modifier.AttackDelay, (Program.Random.Next(30, 60) * 100)); @@ -277,22 +276,8 @@ namespace FFXIVClassic_Map_Server.Actors public void FollowTarget(Actor target, float stepSize = 1.2f, int maxPath = 25, float radius = 0.0f) { - var player = target as Player; - - if (player != null) - { - if (this.target != player) - { - this.target = target; - } - // todo: move this to own function thing - this.oldMoveState = this.moveState; - this.moveState = 2; - updateFlags |= ActorUpdateFlags.Position | ActorUpdateFlags.Speed; - //this.moveSpeeds = player.moveSpeeds; - - PathTo(player.positionX, player.positionY, player.positionZ, stepSize, maxPath, radius); - } + if (target != null) + PathTo(target.positionX, target.positionY, target.positionZ, stepSize, maxPath, radius); } public Int64 GetMod(uint modifier) @@ -654,8 +639,10 @@ namespace FFXIVClassic_Map_Server.Actors // todo: call onAttack/onDamageTaken target.DelHP(action.amount); if (target is BattleNpc) + { ((BattleNpc)target).lastAttacker = this; - + ((BattleNpc)target).hateContainer.UpdateHate(this, action.amount); + } AddTP(115); target.AddTP(100); } @@ -754,7 +741,7 @@ namespace FFXIVClassic_Map_Server.Actors public bool IsMonster() { - return this is BattleNpc && !IsAlly(); + return this is BattleNpc; } public bool IsPet() diff --git a/FFXIVClassic Map Server/actors/chara/ai/HateContainer.cs b/FFXIVClassic Map Server/actors/chara/ai/HateContainer.cs index d5a0904b..47086f68 100644 --- a/FFXIVClassic Map Server/actors/chara/ai/HateContainer.cs +++ b/FFXIVClassic Map Server/actors/chara/ai/HateContainer.cs @@ -39,15 +39,11 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai { if (!HasHateForTarget(target)) hateList.Add(target, new HateEntry(target, 1, 0, true)); - else - Program.Log.Error($"{target.actorName} is already on [{owner.actorId}]{owner.actorName}'s hate list!"); } public void UpdateHate(Character target, int damage) { - if (!HasHateForTarget(target)) - AddBaseHate(target); - + AddBaseHate(target); //hateList[target].volatileEnmity += (uint)damage; hateList[target].cumulativeEnmity += (uint)damage; } @@ -55,13 +51,9 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai public void ClearHate(Character target = null) { if (target != null) - { hateList.Remove(target); - } else - { hateList.Clear(); - } } private void UpdateHate(HateEntry entry) diff --git a/FFXIVClassic Map Server/actors/chara/ai/controllers/BattleNpcController.cs b/FFXIVClassic Map Server/actors/chara/ai/controllers/BattleNpcController.cs index 50280503..19356009 100644 --- a/FFXIVClassic Map Server/actors/chara/ai/controllers/BattleNpcController.cs +++ b/FFXIVClassic Map Server/actors/chara/ai/controllers/BattleNpcController.cs @@ -102,8 +102,6 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers owner.aiContainer.pathFind.PreparePath(owner.spawnX, owner.spawnY, owner.spawnZ, 1.5f, 10); neutralTime = lastActionTime; owner.hateContainer.ClearHate(); - owner.ResetMoveSpeeds(); - owner.moveState = 1; lua.LuaEngine.CallLuaBattleFunction(owner, "onDisengage", owner, target, Utils.UnixTimeStampUTC(lastUpdate)); } @@ -203,7 +201,11 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers } Move(); - lua.LuaEngine.CallLuaBattleFunction(owner, "onCombatTick", owner, owner.target, Utils.UnixTimeStampUTC(tick), contentGroupCharas); + if ((tick - lastCombatTickScript).TotalSeconds > 2) + { + lua.LuaEngine.CallLuaBattleFunction(owner, "onCombatTick", owner, owner.target, Utils.UnixTimeStampUTC(tick), contentGroupCharas); + lastCombatTickScript = tick; + } } protected virtual void Move() diff --git a/FFXIVClassic Map Server/actors/chara/ai/controllers/Controller.cs b/FFXIVClassic Map Server/actors/chara/ai/controllers/Controller.cs index e91bf4ed..ab194953 100644 --- a/FFXIVClassic Map Server/actors/chara/ai/controllers/Controller.cs +++ b/FFXIVClassic Map Server/actors/chara/ai/controllers/Controller.cs @@ -11,6 +11,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers { protected Character owner; + protected DateTime lastCombatTickScript; protected DateTime lastUpdate; public bool canUpdate = true; protected bool autoAttackEnabled = true; diff --git a/FFXIVClassic Map Server/actors/chara/ai/state/AttackState.cs b/FFXIVClassic Map Server/actors/chara/ai/state/AttackState.cs index 0a925e53..79f63178 100644 --- a/FFXIVClassic Map Server/actors/chara/ai/state/AttackState.cs +++ b/FFXIVClassic Map Server/actors/chara/ai/state/AttackState.cs @@ -38,7 +38,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state if (target == null || target.IsDead()) { - if (owner is BattleNpc) + if (owner.IsMonster() || owner.IsAlly()) target = ((BattleNpc)owner).hateContainer.GetMostHatedTarget(); } else @@ -141,7 +141,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state // todo: shouldnt need to check if owner is dead since all states would be cleared if (owner.IsDead() || target.IsDead()) { - if (owner is BattleNpc) + if (owner.IsMonster() || owner.IsAlly()) ((BattleNpc)owner).hateContainer.ClearHate(target); owner.aiContainer.ChangeTarget(null); diff --git a/FFXIVClassic Map Server/actors/chara/npc/BattleNpc.cs b/FFXIVClassic Map Server/actors/chara/npc/BattleNpc.cs index 07e8d69d..160f8050 100644 --- a/FFXIVClassic Map Server/actors/chara/npc/BattleNpc.cs +++ b/FFXIVClassic Map Server/actors/chara/npc/BattleNpc.cs @@ -90,12 +90,7 @@ namespace FFXIVClassic_Map_Server.Actors spawnY = posY; spawnZ = posZ; - // todo: read these from db also - detectionType = DetectionType.Sight; - this.moveState = 2; - ResetMoveSpeeds(); despawnTime = 10; - respawnTime = 30; CalculateBaseStats(); } @@ -245,19 +240,7 @@ namespace FFXIVClassic_Map_Server.Actors { if (respawnTime > 0) { - base.Spawn(tick); - - this.isMovingToSpawn = false; - this.ResetMoveSpeeds(); - this.hateContainer.ClearHate(); - zone.BroadcastPacketsAroundActor(this, GetSpawnPackets(null, 0x01)); - zone.BroadcastPacketsAroundActor(this, GetInitPackets()); - charaWork.parameterSave.hp = charaWork.parameterSave.hpMax; - charaWork.parameterSave.mp = charaWork.parameterSave.mpMax; - RecalculateStats(); - - OnSpawn(); - updateFlags |= ActorUpdateFlags.AllNpc; + ForceRespawn(); } } @@ -266,7 +249,6 @@ namespace FFXIVClassic_Map_Server.Actors base.Spawn(Program.Tick); this.isMovingToSpawn = false; - this.ResetMoveSpeeds(); this.hateContainer.ClearHate(); zone.BroadcastPacketsAroundActor(this, GetSpawnPackets(null, 0x01)); zone.BroadcastPacketsAroundActor(this, GetInitPackets()); @@ -316,8 +298,6 @@ namespace FFXIVClassic_Map_Server.Actors } positionUpdates?.Clear(); aiContainer.InternalDie(tick, despawnTime); - this.ResetMoveSpeeds(); - // todo: reset cooldowns lua.LuaEngine.GetInstance().OnSignal("mobkill"); diff --git a/FFXIVClassic Map Server/actors/chara/player/Player.cs b/FFXIVClassic Map Server/actors/chara/player/Player.cs index 5262425c..f71843b8 100644 --- a/FFXIVClassic Map Server/actors/chara/player/Player.cs +++ b/FFXIVClassic Map Server/actors/chara/player/Player.cs @@ -2188,6 +2188,7 @@ namespace FFXIVClassic_Map_Server.Actors // todo: should just make a thing that updates the one slot cause this is dumb as hell UpdateHotbarTimer(spell.id, spell.recastTimeSeconds); + LuaEngine.GetInstance().OnSignal("spellUse"); } public override void OnWeaponSkill(State state, BattleAction[] actions, ref BattleAction[] errors) @@ -2199,8 +2200,16 @@ namespace FFXIVClassic_Map_Server.Actors UpdateHotbarTimer(skill.id, skill.recastTimeSeconds); // 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, BattleAction[] actions, ref BattleAction[] errors) + { + base.OnAbility(state, actions, ref errors); + + 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 public void AddExp(int exp, byte classId, int bonusPercent = 0) { diff --git a/FFXIVClassic Map Server/lua/LuaEngine.cs b/FFXIVClassic Map Server/lua/LuaEngine.cs index 7de47460..7d28ab28 100644 --- a/FFXIVClassic Map Server/lua/LuaEngine.cs +++ b/FFXIVClassic Map Server/lua/LuaEngine.cs @@ -259,7 +259,7 @@ namespace FFXIVClassic_Map_Server.lua return -1; } - private static string GetScriptPath(Actor target) + public static string GetScriptPath(Actor target) { if (target is Player) { diff --git a/data/scripts/ally.lua b/data/scripts/ally.lua index b8c39ff3..c8625288 100644 --- a/data/scripts/ally.lua +++ b/data/scripts/ally.lua @@ -36,21 +36,22 @@ end function allyGlobal.HelpPlayers(ally, contentGroupCharas, pickRandomTarget) if contentGroupCharas then - for _, chara in pairs(contentGroupCharas) do + print("assssss") if chara then -- probably a player, or another ally -- todo: queue support actions, heal, try pull hate off player etc - if chara.IsPlayer() then + if chara:IsPlayer() then -- do stuff - if not ally.IsEngaged() then - if chara.IsEngaged() then + if not ally:IsEngaged() then + if chara:IsEngaged() then + print("ass") allyGlobal.EngageTarget(ally, chara.target, nil) + return true end end - elseif chara.IsMonster() and chara.IsEngaged() then - if not ally.IsEngaged() then - allyGlobal.EngageTarget(ally, chara.target, nil) - end + elseif chara:IsMonster() and chara:IsEngaged() then + allyGlobal.EngageTarget(ally, chara, nil) + return true end end end @@ -67,14 +68,15 @@ end function allyGlobal.EngageTarget(ally, target, contentGroupCharas) if contentGroupCharas then - for _, chara in pairs(contentGroupCharas) do + for chara in contentGroupCharas do if chara.IsMonster() then if chara.allegiance ~= ally.allegiance then - ally.Engage(chara) + ally:Engage(chara) end end end elseif target then - ally.Engage(target) + ally:Engage(target) + ally.hateContainer:AddBaseHate(target); end end \ No newline at end of file diff --git a/data/scripts/content/SimpleContent30010.lua b/data/scripts/content/SimpleContent30010.lua index 6f1a7de6..5894bbf6 100644 --- a/data/scripts/content/SimpleContent30010.lua +++ b/data/scripts/content/SimpleContent30010.lua @@ -1,4 +1,5 @@ require ("global") +require ("ally") require ("modifiers") function onCreate(starterPlayer, contentArea, director) @@ -33,6 +34,42 @@ function onCreate(starterPlayer, contentArea, director) end +function onUpdate(area, tick) + local players = area:GetPlayers() + local mobs = area:GetMonsters() + local allies = area:GetAllies() + local resumeChecks = true + for player in players do + if player then + local exitLoop = false + for ally in allies do + if ally then + if not ally:IsEngaged() then + if player:IsEngaged() then + ally.neutral = false + ally.isAutoAttackEnabled = true + ally:SetMod(modifiersGlobal.Speed, 8) + allyGlobal.EngageTarget(ally, player.target) + exitLoop = true + break + -- todo: support scripted paths + elseif ally:GetSpeed() > 0 then + + end + end + end + end + if exitLoop then + resumeChecks = false + break + end + end + end + if not resumeChecks then + return + end +end + function onDestroy() diff --git a/data/scripts/unique/fst0Battle03/Monster/bloodthirsty_wolf.lua b/data/scripts/unique/fst0Battle03/Monster/bloodthirsty_wolf.lua index e69de29b..a4e24895 100644 --- a/data/scripts/unique/fst0Battle03/Monster/bloodthirsty_wolf.lua +++ b/data/scripts/unique/fst0Battle03/Monster/bloodthirsty_wolf.lua @@ -0,0 +1,22 @@ +require ("modifiers") + +function onSpawn(mob) + mob:SetMod(modifiersGlobal.Speed, 0) +end + +function onDamageTaken(mob, attacker, damage) + if not attacker:IsPlayer() and mob:GetHP() - damage < 0 then + mob:addHP(damage) + end +end + +function onCombatTick(mob, target, tick, contentGroupCharas) + if mob:GetSpeed() == 0 then + mob:SetMod(modifiersGlobal.Speed, 8) + end +end + +function onDisengage(mob) + mob:SetMod(modifiersGlobal.Speed, 0) + mob:Despawn() +end \ No newline at end of file diff --git a/data/scripts/unique/fst0Battle03/Monster/papalymo.lua b/data/scripts/unique/fst0Battle03/Monster/papalymo.lua index cc9807e1..ca9e38ca 100644 --- a/data/scripts/unique/fst0Battle03/Monster/papalymo.lua +++ b/data/scripts/unique/fst0Battle03/Monster/papalymo.lua @@ -1,4 +1,5 @@ require ("global") +require ("modifiers") require ("ally") function onSpawn(ally) @@ -6,17 +7,5 @@ function onSpawn(ally) ally:SetHP(ally:GetMaxHP()) ally.isAutoAttackEnabled = false; ally.neutral = false -end - -function onCombatTick(ally, target, tick, contentGroupCharas) - allyGlobal.onCombatTick(ally, target, tick, contentGroupCharas); -end - - -function onRoam(ally, contentGroupCharas) - ally.detectionType = 0xFF - ally.isMovingToSpawn = false - ally.neutral = false - ally.animationId = 0 - allyGlobal.onCombatTick(ally, nil, nil, contentGroupCharas) + ally:SetMod(modifiersGlobal.Speed, 0) end \ No newline at end of file diff --git a/data/scripts/unique/fst0Battle03/Monster/yda.lua b/data/scripts/unique/fst0Battle03/Monster/yda.lua index 0c8a9523..c48a4968 100644 --- a/data/scripts/unique/fst0Battle03/Monster/yda.lua +++ b/data/scripts/unique/fst0Battle03/Monster/yda.lua @@ -1,22 +1,10 @@ require ("global") - require ("ally") function onSpawn(ally) ally:SetMaxHP(69420) ally:SetHP(ally:GetMaxHP()) - ally.isAutoAttackEnabled = false + ally.isAutoAttackEnabled = false; ally.neutral = false + ally:SetMod(modifiersGlobal.Speed, 0) end - -function onCombatTick(ally, target, tick, contentGroupCharas) - allyGlobal.onCombatTick(ally, target, tick, contentGroupCharas) -end - -function onRoam(ally, contentGroupCharas) - ally.detectionType = 0xFF - ally.isMovingToSpawn = false - ally.neutral = false - ally.animationId = 0 - allyGlobal.onCombatTick(ally, contentGroupCharas) -end \ No newline at end of file