diff --git a/FFXIVClassic Common Class Lib/Utils.cs b/FFXIVClassic Common Class Lib/Utils.cs index fb4db252..a0c05140 100644 --- a/FFXIVClassic Common Class Lib/Utils.cs +++ b/FFXIVClassic Common Class Lib/Utils.cs @@ -7,6 +7,7 @@ namespace FFXIVClassic.Common public static class Utils { private static readonly uint[] _lookup32 = CreateLookup32(); + private static readonly DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); private static uint[] CreateLookup32() { @@ -106,6 +107,11 @@ namespace FFXIVClassic.Common return unixTimeStamp; } + public static DateTime UnixTimeStampToDateTime(uint timestamp) + { + return epoch.AddSeconds(timestamp); + } + public static ulong SwapEndian(ulong input) { return 0x00000000000000FF & (input >> 56) | diff --git a/FFXIVClassic Map Server/Database.cs b/FFXIVClassic Map Server/Database.cs index 6f81de73..a9577c3c 100644 --- a/FFXIVClassic Map Server/Database.cs +++ b/FFXIVClassic Map Server/Database.cs @@ -925,13 +925,13 @@ namespace FFXIVClassic_Map_Server { while (reader.Read()) { - var id = reader.GetUInt32(0); - var duration = reader.GetUInt32(1); - var magnitude = reader.GetUInt64(2); - var tick = reader.GetUInt32(3); - var tier = reader.GetByte(4); - var extra = reader.GetUInt64(5); - + var id = reader.GetUInt32("statusId"); + var duration = reader.GetUInt32("duration"); + var magnitude = reader.GetUInt64("magnitude"); + var tick = reader.GetUInt32("tick"); + var tier = reader.GetByte("tier"); + var extra = reader.GetUInt64("extra"); + var effect = Server.GetWorldManager().GetStatusEffect(id); if (effect != null) { @@ -942,7 +942,7 @@ namespace FFXIVClassic_Map_Server effect.SetExtra(extra); // dont wanna send ton of messages on login (i assume retail doesnt) - player.statusEffects.AddStatusEffect(effect, null, true); + player.statusEffects.AddStatusEffect(effect, null); } } } @@ -2287,7 +2287,7 @@ namespace FFXIVClassic_Map_Server { conn.Open(); - var query = @"SELECT id, name, flags, overwrite, tickMs FROM server_statuseffects;"; + var query = @"SELECT id, name, flags, overwrite, tickMs, hidden, silentOnGain, silentOnLoss, statusGainTextId, statusLossTextId FROM server_statuseffects;"; MySqlCommand cmd = new MySqlCommand(query, conn); @@ -2300,7 +2300,14 @@ namespace FFXIVClassic_Map_Server var flags = reader.GetUInt32("flags"); var overwrite = reader.GetByte("overwrite"); var tickMs = reader.GetUInt32("tickMs"); - var effect = new StatusEffect(id, name, flags, overwrite, tickMs); + var hidden = reader.GetBoolean("hidden"); + var silentOnGain = reader.GetBoolean("silentOnGain"); + var silentOnLoss = reader.GetBoolean("silentOnLoss"); + var statusGainTextId = reader.GetUInt16("statusGainTextId"); + var statusLossTextId = reader.GetUInt16("statusLossTextId"); + + var effect = new StatusEffect(id, name, flags, overwrite, tickMs, hidden, silentOnGain, silentOnLoss, statusGainTextId, statusLossTextId); + lua.LuaEngine.LoadStatusEffectScript(effect); effects.Add(id, effect); } @@ -2392,8 +2399,8 @@ namespace FFXIVClassic_Map_Server battleCommand.job = reader.GetByte("classJob"); battleCommand.level = reader.GetByte("lvl"); battleCommand.requirements = (BattleCommandRequirements)reader.GetUInt16("requirements"); - battleCommand.mainTarget = (ValidTarget)reader.GetByte("mainTarget"); - battleCommand.validTarget = (ValidTarget)reader.GetByte("validTarget"); + battleCommand.mainTarget = (ValidTarget)reader.GetUInt16("mainTarget"); + battleCommand.validTarget = (ValidTarget)reader.GetUInt16("validTarget"); battleCommand.aoeType = (TargetFindAOEType)reader.GetByte("aoeType"); battleCommand.basePotency = reader.GetUInt16("basePotency"); battleCommand.numHits = reader.GetByte("numHits"); @@ -2410,8 +2417,8 @@ namespace FFXIVClassic_Map_Server battleCommand.castTimeMs = reader.GetUInt32("castTime"); battleCommand.maxRecastTimeSeconds = reader.GetUInt32("recastTime"); battleCommand.recastTimeMs = battleCommand.maxRecastTimeSeconds * 1000; - battleCommand.mpCost = reader.GetUInt16("mpCost"); - battleCommand.tpCost = reader.GetUInt16("tpCost"); + battleCommand.mpCost = reader.GetInt16("mpCost"); + battleCommand.tpCost = reader.GetInt16("tpCost"); battleCommand.animationType = reader.GetByte("animationType"); battleCommand.effectAnimation = reader.GetUInt16("effectAnimation"); battleCommand.modelAnimation = reader.GetUInt16("modelAnimation"); @@ -2433,7 +2440,26 @@ namespace FFXIVClassic_Map_Server battleCommand.actionType = (ActionType)reader.GetInt16("actionType"); battleCommand.accuracyModifier = reader.GetFloat("accuracyMod"); battleCommand.worldMasterTextId = reader.GetUInt16("worldMasterTextId"); - lua.LuaEngine.LoadBattleCommandScript(battleCommand, "weaponskill"); + + string folderName = ""; + + switch (battleCommand.commandType) + { + case CommandType.AutoAttack: + folderName = "autoattack"; + break; + case CommandType.WeaponSkill: + folderName = "weaponskill"; + break; + case CommandType.Ability: + folderName = "ability"; + break; + case CommandType.Spell: + folderName = "magic"; + break; + } + + lua.LuaEngine.LoadBattleCommandScript(battleCommand, folderName); battleCommandDict.Add(id, battleCommand); Tuple tuple = Tuple.Create(battleCommand.job, battleCommand.level); diff --git a/FFXIVClassic Map Server/WorldManager.cs b/FFXIVClassic Map Server/WorldManager.cs index 149cfd41..65b53d09 100644 --- a/FFXIVClassic Map Server/WorldManager.cs +++ b/FFXIVClassic Map Server/WorldManager.cs @@ -478,7 +478,7 @@ namespace FFXIVClassic_Map_Server battleNpcGenusMods.TryGetValue(battleNpc.genusId, out battleNpc.genusMods); battleNpcSpawnMods.TryGetValue(battleNpc.GetBattleNpcId(), out battleNpc.spawnMods); - battleNpc.SetMod((uint)Modifier.Speed, reader.GetByte("speed")); + battleNpc.SetMod((uint)Modifier.MovementSpeed, reader.GetByte("speed")); battleNpc.neutral = reader.GetByte("aggroType") == 0; battleNpc.SetDetectionType(reader.GetUInt32("detection")); @@ -603,7 +603,7 @@ namespace FFXIVClassic_Map_Server reader.GetUInt16("actorState"), reader.GetUInt32("animationId"), ""); battleNpc.SetBattleNpcId(reader.GetUInt32("bnpcId")); - battleNpc.SetMod((uint)Modifier.Speed, reader.GetByte("speed")); + battleNpc.SetMod((uint)Modifier.MovementSpeed, reader.GetByte("speed")); battleNpc.neutral = reader.GetByte("aggroType") == 0; // set mob mods diff --git a/FFXIVClassic Map Server/actors/Actor.cs b/FFXIVClassic Map Server/actors/Actor.cs index 07cc9f26..e2fc5df2 100644 --- a/FFXIVClassic Map Server/actors/Actor.cs +++ b/FFXIVClassic Map Server/actors/Actor.cs @@ -29,6 +29,7 @@ namespace FFXIVClassic_Map_Server.Actors Stats = 0x100, Status = 0x200, StatusTime = 0x400, + Hotbar = 0x800, AllNpc = 0xDF, AllPlayer = 0x13F @@ -92,6 +93,7 @@ namespace FFXIVClassic_Map_Server.Actors this.moveSpeeds[1] = SetActorSpeedPacket.DEFAULT_WALK; this.moveSpeeds[2] = SetActorSpeedPacket.DEFAULT_RUN; this.moveSpeeds[3] = SetActorSpeedPacket.DEFAULT_ACTIVE; + positionUpdates = new List(); } public void SetPushCircleRange(string triggerName, float size) @@ -650,7 +652,7 @@ namespace FFXIVClassic_Map_Server.Actors public void LookAt(Actor actor) { - if (actor != null && actor != this) + if (actor != null) { LookAt(actor.positionX, actor.positionZ); } @@ -670,16 +672,20 @@ namespace FFXIVClassic_Map_Server.Actors public void LookAt(float x, float z) { - var rot1 = this.rotation; + //Don't rotate if the lookat position is same as our current position + if (positionX != x || positionZ != z) + { + var rot1 = this.rotation; - var dX = this.positionX - x; - var dY = this.positionZ - z; - var rot2 = Math.Atan2(dY, dX); - var dRot = Math.PI - rot2 + Math.PI / 2; + var dX = this.positionX - x; + var dY = this.positionZ - z; + var rot2 = Math.Atan2(dY, dX); + var dRot = Math.PI - rot2 + Math.PI / 2; - // pending move, dont need to unset it - this.updateFlags |= ActorUpdateFlags.Position; - rotation = (float)dRot; + // pending move, dont need to unset it + this.updateFlags |= ActorUpdateFlags.Position; + rotation = (float)dRot; + } } // todo: is this legit? diff --git a/FFXIVClassic Map Server/actors/chara/Character.cs b/FFXIVClassic Map Server/actors/chara/Character.cs index c505b0c5..adda181a 100644 --- a/FFXIVClassic Map Server/actors/chara/Character.cs +++ b/FFXIVClassic Map Server/actors/chara/Character.cs @@ -149,8 +149,8 @@ namespace FFXIVClassic_Map_Server.Actors // todo: move this somewhere more appropriate // todo: base this on equip and shit SetMod((uint)Modifier.AttackRange, 3); - SetMod((uint)Modifier.AttackDelay, (Program.Random.Next(30, 60) * 100)); - SetMod((uint)Modifier.Speed, (uint)moveSpeeds[2]); + SetMod((uint)Modifier.Delay, (Program.Random.Next(30, 60) * 100)); + SetMod((uint)Modifier.MovementSpeed, (uint)moveSpeeds[2]); spawnX = positionX; spawnY = positionY; @@ -238,8 +238,7 @@ namespace FFXIVClassic_Map_Server.Actors public void DoBattleAction(ushort commandId, uint animationId, CommandResult[] results) { int currentIndex = 0; - //AoE abilities only ever hit 16 people, so we probably won't need this loop anymore - //Apparently aoe are limited to 8? + while (true) { if (results.Length - currentIndex >= 10) @@ -253,9 +252,6 @@ namespace FFXIVClassic_Map_Server.Actors } else break; - - //I think aoe effects play on all hit enemies. Firaga does at least - //animationId = 0; //If more than one packet is sent out, only send the animation once to avoid double playing. } } @@ -317,7 +313,7 @@ namespace FFXIVClassic_Map_Server.Actors else modifiers.Add((Modifier)modifier, val); - if (modifier <= 35) + if (modifier >= 3 && modifier <= 35) updateFlags |= ActorUpdateFlags.Stats; } @@ -344,6 +340,29 @@ namespace FFXIVClassic_Map_Server.Actors SetMod(modifier, newVal); } + public void MultiplyMod(Modifier modifier, double val) + { + MultiplyMod((uint)modifier, val); + } + + public void MultiplyMod(uint modifier, double val) + { + double newVal = GetMod(modifier) * val; + SetMod(modifier, newVal); + } + + public void DivideMod(Modifier modifier, double val) + { + DivideMod((uint)modifier, val); + } + + public void DivideMod(uint modifier, double val) + { + double newVal = GetMod(modifier) / val; + SetMod(modifier, newVal); + } + + public virtual void OnPath(Vector3 point) { //lua.LuaEngine.CallLuaBattleFunction(this, "onPath", this, point); @@ -380,7 +399,7 @@ namespace FFXIVClassic_Map_Server.Actors if ((updateFlags & ActorUpdateFlags.SubState) != 0) { - //packets.Add(SetActorSubStatePacket.BuildPacket(actorId, currentSubState)); + packets.Add(SetActorSubStatePacket.BuildPacket(actorId, currentSubState)); //packets.Add(CommandResultX00Packet.BuildPacket(actorId, 0x72000062, 0)); //packets.Add(CommandResultX01Packet.BuildPacket(actorId, 0x7C000062, 21001, new CommandResult(actorId, 0, 1))); @@ -390,6 +409,7 @@ namespace FFXIVClassic_Map_Server.Actors if ((updateFlags & ActorUpdateFlags.Status) != 0) { + List statusPackets = statusEffects.GetStatusPackets(); packets.AddRange(statusPackets); statusPackets.Clear(); @@ -428,24 +448,15 @@ namespace FFXIVClassic_Map_Server.Actors return true; } - public virtual bool CanCast(Character target, BattleCommand spell) + public virtual bool CanUse(Character target, BattleCommand skill, CommandResult error = null) { return false; } - public virtual bool CanWeaponSkill(Character target, BattleCommand skill) - { - return false; - } - - public virtual bool CanUseAbility(Character target, BattleCommand ability) - { - return false; - } public virtual uint GetAttackDelayMs() { - return (uint)GetMod((uint)Modifier.AttackDelay); + return (uint)GetMod((uint)Modifier.Delay); } public virtual uint GetAttackRange() @@ -523,8 +534,8 @@ namespace FFXIVClassic_Map_Server.Actors aiContainer.Reset(); // todo: reset hp/mp/tp etc here ChangeState(SetActorStatePacket.MAIN_STATE_PASSIVE); - charaWork.parameterSave.hp = charaWork.parameterSave.hpMax; - charaWork.parameterSave.mp = charaWork.parameterSave.mpMax; + SetHP((uint) GetMaxHP()); + SetMP((uint) GetMaxMP()); RecalculateStats(); } @@ -609,8 +620,8 @@ namespace FFXIVClassic_Map_Server.Actors public void SetMP(uint mp) { - charaWork.parameterSave.mpMax = (short)mp; - if (mp > charaWork.parameterSave.hpMax[0]) + charaWork.parameterSave.mp = (short)mp; + if (mp > charaWork.parameterSave.mpMax) SetMaxMP(mp); updateFlags |= ActorUpdateFlags.HpTpMp; @@ -621,8 +632,9 @@ namespace FFXIVClassic_Map_Server.Actors charaWork.parameterSave.mp = (short)mp; updateFlags |= ActorUpdateFlags.HpTpMp; } + // todo: the following functions are virtuals since we want to check hidden item bonuses etc on player for certain conditions - public virtual void AddHP(int hp) + public virtual void AddHP(int hp, CommandResultContainer resultContainer = null) { // dont wanna die ded, don't want to send update if hp isn't actually changed if (IsAlive() && hp != 0) @@ -634,6 +646,9 @@ namespace FFXIVClassic_Map_Server.Actors charaWork.parameterSave.hp[0] = (short)addHp; updateFlags |= ActorUpdateFlags.HpTpMp; + + if (charaWork.parameterSave.hp[0] < 1) + Die(Program.Tick, resultContainer); } } @@ -675,9 +690,9 @@ namespace FFXIVClassic_Map_Server.Actors } } - public void DelHP(int hp) + public void DelHP(int hp, CommandResultContainer resultContainer = null) { - AddHP((short)-hp); + AddHP((short)-hp, resultContainer); } public void DelMP(int mp) @@ -743,7 +758,7 @@ namespace FFXIVClassic_Map_Server.Actors public virtual float GetSpeed() { // todo: for battlenpc/player calculate speed - return (float) GetMod((uint)Modifier.Speed); + return (float) GetMod((uint)Modifier.MovementSpeed); } public virtual void OnAttack(State state, CommandResult action, ref CommandResult error) @@ -821,55 +836,55 @@ namespace FFXIVClassic_Map_Server.Actors } - public virtual void OnDamageDealt(Character defender, CommandResult action, CommandResultContainer actionContainer = null) + public virtual void OnDamageDealt(Character defender, BattleCommand skill, CommandResult action, CommandResultContainer actionContainer = null) { switch (action.hitType) { case (HitType.Miss): - OnMiss(this, action, actionContainer); + OnMiss(defender, skill, action, actionContainer); + break; + case (HitType.Crit): + OnCrit(defender, skill, action, actionContainer); + OnHit(defender, skill, action, actionContainer); break; default: - OnHit(defender, action, actionContainer); + OnHit(defender, skill, action, actionContainer); break; } //TP is only gained from autoattacks and abilities - if (action.commandType == CommandType.AutoAttack || action.commandType == CommandType.Ability) + if ((action.commandType == CommandType.AutoAttack || action.commandType == CommandType.Ability) && action.hitType != HitType.Miss) { //TP gained on an attack is usually 100 * delay. //Store TP seems to add .1% per point. - double weaponDelay = GetMod(Modifier.AttackDelay) / 1000.0; - var storeTPPercent = 1 + (GetMod(Modifier.StoreTP) * 0.001); + double weaponDelay = GetMod(Modifier.Delay) / 1000.0; + var storeTPPercent = 1 + (GetMod(Modifier.StoreTp) * 0.001); AddTP((int)(weaponDelay * 100 * storeTPPercent)); } } - public virtual void OnDamageTaken(Character attacker, CommandResult action, CommandResultContainer actionContainer = null) + public virtual void OnDamageTaken(Character attacker, BattleCommand skill, CommandResult action, CommandResultContainer actionContainer = null) { switch (action.hitType) { case (HitType.Miss): - OnEvade(attacker, action, actionContainer); + OnEvade(attacker, skill, action, actionContainer); break; case (HitType.Parry): - OnParry(attacker, action, actionContainer); + OnParry(attacker, skill, action, actionContainer); break; case (HitType.Block): - OnBlock(attacker, action, actionContainer); + OnBlock(attacker, skill, action, actionContainer); break; } - statusEffects.CallLuaFunctionByFlag((uint)StatusEffectFlags.ActivateOnDamageTaken, "onDamageTaken", attacker, this, action); - + statusEffects.CallLuaFunctionByFlag((uint)StatusEffectFlags.ActivateOnDamageTaken, "onDamageTaken", attacker, this, skill, action, actionContainer); + //TP gain formula seems to be something like 5 * e ^ ( -0.667 * [defender's level] ) * damage taken, rounded up //This should be completely accurate at level 50, but isn't totally accurate at lower levels. //Don't know if store tp impacts this double tpModifier = 5 * Math.Pow(Math.E, (-0.0667 * GetLevel())); AddTP((int)Math.Ceiling(tpModifier * action.amount)); - - - if (charaWork.parameterSave.hp[0] < 1) - Die(Program.Tick, actionContainer); } public UInt64 GetTempVar(string name) @@ -978,8 +993,7 @@ namespace FFXIVClassic_Map_Server.Actors { StatusEffect procEffect = Server.GetWorldManager().GetStatusEffect(effectId); procEffect.SetDuration(5); - procEffect.SetSilent(true); - statusEffects.AddStatusEffect(procEffect, this, true, true); + statusEffects.AddStatusEffect(procEffect, this); } //Otherwise we're reseting a proc, remove the status else @@ -1013,36 +1027,41 @@ namespace FFXIVClassic_Map_Server.Actors } //Called when this character evades attacker's action - public void OnEvade(Character attacker, CommandResult action, CommandResultContainer actionContainer = null) + public void OnEvade(Character attacker, BattleCommand skill, CommandResult action, CommandResultContainer actionContainer = null) { SetProc((ushort)HitType.Evade); - statusEffects.CallLuaFunctionByFlag((uint)StatusEffectFlags.ActivateOnEvade, "onEvade", attacker, this, action, actionContainer); + statusEffects.CallLuaFunctionByFlag((uint)StatusEffectFlags.ActivateOnEvade, "onEvade", attacker, this, skill, action, actionContainer); } //Called when this character blocks attacker's action - public void OnBlock(Character attacker, CommandResult action, CommandResultContainer actionContainer = null) + public void OnBlock(Character attacker, BattleCommand skill, CommandResult action, CommandResultContainer actionContainer = null) { SetProc((ushort)HitType.Block); - statusEffects.CallLuaFunctionByFlag((uint)StatusEffectFlags.ActivateOnBlock, "onBlock", attacker, this, action, actionContainer); + statusEffects.CallLuaFunctionByFlag((uint)StatusEffectFlags.ActivateOnBlock, "onBlock", attacker, this, skill, action, actionContainer); } //Called when this character parries attacker's action - public void OnParry(Character attacker, CommandResult action, CommandResultContainer actionContainer = null) + public void OnParry(Character attacker, BattleCommand skill, CommandResult action, CommandResultContainer actionContainer = null) { SetProc((ushort)HitType.Parry); - statusEffects.CallLuaFunctionByFlag((uint)StatusEffectFlags.ActivateOnParry, "onParry", attacker, this, action, actionContainer); + statusEffects.CallLuaFunctionByFlag((uint)StatusEffectFlags.ActivateOnParry, "onParry", attacker, this, skill, action, actionContainer); } //Called when this character misses - public void OnMiss(Character defender, CommandResult action, CommandResultContainer actionContainer = null) + public void OnMiss(Character defender, BattleCommand skill, CommandResult action, CommandResultContainer actionContainer = null) { SetProc((ushort)HitType.Miss); - statusEffects.CallLuaFunctionByFlag((uint)StatusEffectFlags.ActivateOnMiss, "onMiss", this, defender, action, actionContainer); + statusEffects.CallLuaFunctionByFlag((uint)StatusEffectFlags.ActivateOnMiss, "onMiss", this, defender, skill, action, actionContainer); } - public void OnHit(Character defender, CommandResult action, CommandResultContainer actionContainer = null) + public void OnHit(Character defender, BattleCommand skill, CommandResult action, CommandResultContainer actionContainer = null) { - statusEffects.CallLuaFunctionByFlag((uint)StatusEffectFlags.ActivateOnHit, "onHit", this, defender, action, actionContainer); + statusEffects.CallLuaFunctionByFlag((uint)StatusEffectFlags.ActivateOnHit, "onHit", this, defender, skill, action, actionContainer); + } + + public void OnCrit(Character defender, BattleCommand skill, CommandResult action, CommandResultContainer actionContainer = null) + { + statusEffects.CallLuaFunctionByFlag((uint)StatusEffectFlags.ActivateOnCrit, "onCrit", this, defender, skill, action, actionContainer); } //The order of messages that appears after using a command is: @@ -1056,7 +1075,7 @@ namespace FFXIVClassic_Map_Server.Actors //5. The hit itself. For single hit commands this message is "Your [command] hits [target] for x damage" for multi hits it's "[Target] takes x points of damage" //6. Stoneskin falling off //6. Buffs that activate after a command hits, like Aegis Boon and Divine Veil - + //After all hits //7. If it's a multi-hit command there's a "{numhits]fold attack..." message or if all hits miss an "All attacks missed" message //8. Buffs that fall off after the skill ends, like Excruciate @@ -1092,7 +1111,7 @@ namespace FFXIVClassic_Map_Server.Actors lua.LuaEngine.CallLuaBattleCommandFunction(this, command, folder, "onSkillFinish", this, chara, command, action, actions); //cached script //skill.CallLuaFunction(owner, "onSkillFinish", this, chara, command, action, actions); - if (action.hitType > HitType.Evade && action.hitType != HitType.Resist) + if (action.ActionLanded()) { hitTarget = true; hitCount++; @@ -1116,18 +1135,20 @@ namespace FFXIVClassic_Map_Server.Actors actions.AddAction(new CommandResult(actorId, 30202, 0)); } + DelMP(command.CalculateMpCost(this)); + DelTP(command.CalculateTpCost(this)); + //Now that we know if we hit the target we can check if the combo continues if (this is Player) { if (command.isCombo && hitTarget) ((Player)this).SetCombos(command.comboNextCommandId); - else + //Only reset combo if the command is a spell or weaponskill, since abilities can be used between combo skills + else if (command.commandType == CommandType.Spell || command.commandType == CommandType.WeaponSkill) ((Player)this).SetCombos(); } - CommandResult error = new CommandResult(actorId, 0, 0); - DelMP(command.CalculateMpCost(this)); - DelTP(command.CalculateTpCost(this)); + actions.CombineLists(); DoBattleAction(command.id, command.battleAnimation, actions.GetList()); } @@ -1135,8 +1156,8 @@ namespace FFXIVClassic_Map_Server.Actors public List GetPartyMembersInRange(uint range) { TargetFind targetFind = new TargetFind(this); - targetFind.SetAOEType(ValidTarget.PartyMember, TargetFindAOEType.Circle, TargetFindAOETarget.Self, range, 0, 10, 0, 0); - targetFind.FindWithinArea(this, ValidTarget.PartyMember, TargetFindAOETarget.Self); + targetFind.SetAOEType(ValidTarget.Party, TargetFindAOEType.Circle, TargetFindAOETarget.Self, range, 0, 10, 0, 0); + targetFind.FindWithinArea(this, ValidTarget.Party, TargetFindAOETarget.Self); return targetFind.GetTargets(); } diff --git a/FFXIVClassic Map Server/actors/chara/Modifier.cs b/FFXIVClassic Map Server/actors/chara/Modifier.cs index 5cf627ba..bba437b7 100644 --- a/FFXIVClassic Map Server/actors/chara/Modifier.cs +++ b/FFXIVClassic Map Server/actors/chara/Modifier.cs @@ -7,88 +7,157 @@ namespace FFXIVClassic_Map_Server.actors.chara //Also, 0-35 should probably match with up BattleTemp enum Modifier : UInt32 { - NAMEPLATE_SHOWN = 0, - TARGETABLE = 1, - NAMEPLATE_SHOWN2 = 2, - //NAMEPLATE_SHOWN2 = 3, + //These line up with ParamNames starting at 15001 and appear on gear + //Health + Hp = 0, //Max HP + Mp = 1, //Max MP + Tp = 2, //Max TP - Strength = 3, - Vitality = 4, - Dexterity = 5, - Intelligence = 6, - Mind = 7, - Piety = 8, + //Main stats + Strength = 3, + Vitality = 4, + Dexterity = 5, + Intelligence = 6, + Mind = 7, + Piety = 8, - ResistFire = 9, - ResistIce = 10, - ResistWind = 11, - ResistLightning = 12, - ResistEarth = 13, - ResistWater = 14, + //Elemental Resistances + FireResistance = 9, //Lowers Fire damage taken + IceResistance = 10, //Lowers Ice damage taken + WindResistance = 11, //Lowers Wind damage taken + EarthResistance = 12, //Lowers Earth damage taken + LightningResistance = 13, //Lowers Lightning damage taken + WaterResistance = 14, //Lowers Water damage taken - Accuracy = 15, - Evasion = 16, - Attack = 17, - Defense = 18, //Is there a magic defense stat? 19 maybe? - MagicAttack = 23, - MagicHeal = 24, - MagicEnhancePotency = 25, - MagicEnfeeblingPotency = 26, + //Physical Secondary stats + Accuracy = 15, //Increases chance to hit with physical attacks + Evasion = 16, //Decreases chance to be hit by physical attacks + Attack = 17, //Increases damage done with physical attacks + Defense = 18, //Decreases damage taken from physical attacks - MagicAccuracy = 27, - MagicEvasion = 28, + //Physical crit stats + CriticalHitRating = 19, //Increases chance to crit with physical attacks + CriticalHitEvasion = 20, //Decreases chance to be crit by physical attacks + CriticalHitAttackPower = 21, //Increases damage done by critical physical attacks + CriticalHitResilience = 22, //Decreases damage taken from critical physical attacks - CraftProcessing = 30, - CraftMagicProcessing = 31, - CraftProcessControl = 32, + //Magic secondary stats + AttackMagicPotency = 23, //Increases damage done with magical attacks + HealingMagicPotency = 24, //Increases healing done with magic healing + EnhancementMagicPotency = 25, //Increases effect of enhancement magic + EnfeeblingMagicPotency = 26, //Increases effect of enfeebling magic + MagicAccuracy = 27, //Decreases chance for magic to be evaded + MagicEvasion = 28, //Increases chance to evade magic - HarvestPotency = 33, - HarvestLimit = 34, - HarvestRate = 35, + //Crafting stats + Craftsmanship = 29, + MagicCraftsmanship = 30, + Control = 31, + Gathering = 32, + Output = 33, + Perception = 34, - None = 36, - Hp = 37, - HpPercent = 38, - Mp = 39, - MpPercent = 40, - Tp = 41, - TpPercent = 42, - Regen = 43, - Refresh = 44, + //Magic crit stats + MagicCriticalHitRating = 35, //Increases chance to crit with magical attacks + MagicCriticalHitEvasion = 36, //Decreases chance to be crit by magical attacks + MagicCriticalHitPotency = 37, //Increases damage done by critical magical attacks + MagicCriticalHitResilience = 38, //Decreases damage taken from critical magical attacks - AttackRange = 45, - Speed = 46, - AttackDelay = 47, + //Blocking stats + Parry = 39, //Increases chance to parry + BlockRate = 40, //Increases chance to block + Block = 41, //Reduces damage taken from blocked attacks - Raise = 48, - MinimumHpLock = 49, // hp cannot fall below this value - AttackType = 50, // slashing, piercing, etc - BlockRate = 51, - Block = 52, - CritRating = 53, - HasShield = 54, // Need this because shields are required for blocks. Could have used BlockRate or Block but BlockRate is provided by Gallant Sollerets and Block is provided by some buffs. - HitCount = 55, // Amount of hits in an auto attack. Usually 1, 2 for h2h, 3 with spinning heel + //Elemental Potencies + FireMagicPotency = 42, //Increases damage done by Fire Magic + IceMagicPotency = 43, //Increases damage done by Ice Magic + WindMagicPotency = 44, //Increases damage done by Wind Magic + EarthMagicPotency = 45, //Increases damage done by Earth Magic + LightningMagicPotency = 46, //Increases damage done by Lightning Magic + WaterMagicPotency = 47, //Increases damage done by Water Magic - //Flat percent increases to these rates. Probably a better way to do this - RawEvadeRate = 56, - RawParryRate = 57, - RawBlockRate = 58, - RawResistRate = 59, - RawHitRate = 60, - RawCritRate = 61, + //Miscellaneous + Regen = 48, //Restores health over time + Refresh = 49, //Restores MP over time + StoreTp = 50, //Increases TP gained by auto attacks and damaging abiltiies + Enmity = 51, //Increases enmity gained from actions + Spikes = 52, //Deals damage or status to attacker when hit + Haste = 53, //Increases attack speed + //54 and 55 didn't have names and seem to be unused + ReducedDurabilityLoss = 56, //Reduces durability loss + IncreasedSpiritbondGain = 57, //Increases rate of spiritbonding + Damage = 58, //Increases damage of auto attacks + Delay = 59, //Increases rate of auto attacks + Fastcast = 60, //Increases speed of casts + MovementSpeed = 61, //Increases movement speed + Exp = 62, //Increases experience gained + RestingHp = 63, //? + RestingMp = 64, //? - DamageTakenDown = 62, // Percent damage taken down - StoreTP = 63, //.1% extra tp per point. Lancer trait is 50 StoreTP - PhysicalCritRate = 64, //CritRating but only for physical attacks. Increases chance of critting. - PhysicalCritEvasion = 65, //Opposite of CritRating. Reduces chance of being crit by phyiscal attacks - PhysicalCritAttack = 66, //Increases damage done by Physical Critical hits - PhysicalCritResilience = 67, //Decreases damage taken by Physical Critical hits - Parry = 68, //Increases chance to parry - MagicCritPotency = 69, //Increases - Regain = 70, //TP regen, should be -90 out of combat, Invigorate sets to 100+ depending on traits - RegenDown = 71, //Damage over time effects. Separate from normal Regen because of how they are displayed in game - Stoneskin = 72, //Nullifies damage - MinimumTpLock = 73, //Don't let TP fall below this, used in openings - KnockbackImmune = 74 //Immune to knockback effects when above 0 + //Attack property resistances + SlashingResistance = 65, //Reduces damage taken by slashing attacks + PiercingResistance = 66, //Reduces damage taken by piercing attacks + BluntResistance = 67, //Reduces damage taken by blunt attacks + ProjectileResistance = 68, //Reduces damage taken by projectile attacks + SonicResistance = 69, //Reduces damage taken by sonic attacks + BreathResistance = 70, //Reduces damage taken by breath attacks + PhysicalResistance = 71, //Reduces damage taken by physical attacks + MagicResistance = 72, //Reduces damage taken by magic attacks + + //Status resistances + SlowResistance = 73, //Reduces chance to be inflicted with slow by status magic + PetrificationResistance = 74, //Reduces chance to be inflicted with petrification by status magic + ParalysisResistance = 75, //Reduces chance to be inflicted with paralysis by status magic + SilenceResistance = 76, //Reduces chance to be inflicted with silence by status magic + BlindResistance = 77, //Reduces chance to be inflicted with blind by status magic + PoisonResistance = 78, //Reduces chance to be inflicted with poison by status magic + StunResistance = 79, //Reduces chance to be inflicted with stun by status magic + SleepResistance = 80, //Reduces chance to be inflicted with sleep by status magic + BindResistance = 81, //Reduces chance to be inflicted with bind by status magic + HeavyResistance = 82, //Reduces chance to be inflicted with heavy by status magic + DoomResistance = 83, //Reduces chance to be inflicted with doom by status magic + + //84-101 didn't have names and seem to be unused + //Miscellaneous + ConserveMp = 101, //Chance to reduce mp used by actions + SpellInterruptResistance = 102, //Reduces chance to be interrupted by damage while casting + DoubleDownOdds = 103, //Increases double down odds + HqDiscoveryRate = 104, + + + //Non-gear mods + None = 105, + NAMEPLATE_SHOWN = 106, + TARGETABLE = 107, + NAMEPLATE_SHOWN2 = 108, + + HpPercent = 109, + MpPercent = 110, + TpPercent = 111, + + AttackRange = 112, //How far away in yalms this character can attack from (probably won't need this when auto attack skills are done) + + Raise = 113, + MinimumHpLock = 114, //Stops HP from falling below this value + MinimumMpLock = 115, //Stops MP from falling below this value + MinimumTpLock = 116, //Stops TP from falling below this value + AttackType = 117, //Attack property of auto attacks (might not need this when auto attack skills are done, unsure) + CanBlock = 118, //Whether the character can block attacks. (For players this is only true when they have a shield) + HitCount = 119, //Amount of hits in an auto attack. Usually 1, 2 for h2h, 3 with spinning heel + + //Flat percent increases to these rates. Might not need these? + RawEvadeRate = 120, + RawParryRate = 121, + RawBlockRate = 122, + RawResistRate = 123, + RawHitRate = 124, + RawCritRate = 125, + + DamageTakenDown = 126, //Percent damage taken down + Regain = 127, //TP regen, should be -90 out of combat, Invigorate sets to 100+ depending on traits + RegenDown = 128, //Damage over time effects. Separate from normal Regen because of how they are displayed in game + Stoneskin = 129, //Nullifies damage + KnockbackImmune = 130, //Immune to knockback effects when above 0 + Stealth = 131, //Not visisble when above 0 } } diff --git a/FFXIVClassic Map Server/actors/chara/ai/BattleCommand.cs b/FFXIVClassic Map Server/actors/chara/ai/BattleCommand.cs index 151c54a9..2a9cf6f6 100644 --- a/FFXIVClassic Map Server/actors/chara/ai/BattleCommand.cs +++ b/FFXIVClassic Map Server/actors/chara/ai/BattleCommand.cs @@ -109,8 +109,8 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai public uint castTimeMs; //cast time in milliseconds public uint recastTimeMs; //recast time in milliseconds public uint maxRecastTimeSeconds; //maximum recast time in seconds - public ushort mpCost; - public ushort tpCost; + public short mpCost; //short in case these casts can have negative cost + public short tpCost; //short because there are certain cases where we want weaponskills to have negative costs (such as Feint) public byte animationType; public ushort effectAnimation; public ushort modelAnimation; @@ -188,10 +188,10 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai return castTimeMs == 0; } - //Checks whether the skill can be used on the given target - public bool IsValidMainTarget(Character user, Character target) + //Checks whether the skill can be used on the given targets, uses error to return specific text ids for errors + public bool IsValidMainTarget(Character user, Character target, CommandResult error = null) { - targetFind = new TargetFind(user); + targetFind = new TargetFind(user, target); if (aoeType == TargetFindAOEType.Box) { @@ -204,6 +204,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai /* worldMasterTextId + 32511 Target does not exist 32512 cannot be performed on a KO'd target. 32513 can only be performed on a KO'd target. 32514 cannot be performed on yourself. @@ -211,117 +212,112 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai 32516 cannot be performed on a friendly target. 32517 can only be performed on a friendly target. 32518 cannot be performed on an enemy. - 32519 can only be performed on an enemy, - 32556 unable to execute [weaponskill]. Conditions for use are not met. + 32519 can only be performed on an enemy. + 32547 That command cannot be performed on the current target. + 32548 That command cannot be performed on a party member */ - - // cant target dead - if ((mainTarget & (ValidTarget.Corpse | ValidTarget.CorpseOnly)) == 0 && target.IsDead()) + if (target == null) { - // cannot be perfomed on - if (user is Player) - ((Player)user).SendGameMessage(Server.GetWorldManager().GetActor(), 32512, 0x20, (uint)id); + error?.SetTextId(32511); return false; } - //level too high - if (level > user.GetLevel()) + //This skill can't be used on a corpse and target is dead + if ((mainTarget & ValidTarget.Corpse) == 0 && target.IsDead()) { - if (user is Player) - ((Player)user).SendGameMessage(Server.GetWorldManager().GetActor(), 32527, 0x20, (uint)id); - //return false; - } - - //Proc requirement - if (procRequirement != BattleCommandProcRequirement.None && !user.charaWork.battleTemp.timingCommandFlag[(int) procRequirement - 1]) - { - if (user is Player) - ((Player)user).SendGameMessage(Server.GetWorldManager().GetActor(), 32556, 0x20, (uint)id); + error?.SetTextId(32512); return false; } - //costs too much tp - if (CalculateTpCost(user) > user.GetTP()) + //This skill must be used on a corpse and target is alive + if ((mainTarget & ValidTarget.CorpseOnly) != 0 && target.IsAlive()) { - if (user is Player) - ((Player)user).SendGameMessage(Server.GetWorldManager().GetActor(), 32546, 0x20, (uint)id); + error?.SetTextId(32513); return false; } - // todo: calculate cost based on modifiers also (probably in BattleUtils) - if (BattleUtils.CalculateSpellCost(user, target, this) > user.GetMP()) + //This skill can't be used on self and target is self + if ((mainTarget & ValidTarget.Self) == 0 && target == user) { - if (user is Player) - ((Player)user).SendGameMessage(Server.GetWorldManager().GetActor(), 32545, 0x20, (uint)id); + error?.SetTextId(32514); return false; } - // todo: check target requirements - if (requirements != BattleCommandRequirements.None) + //This skill must be used on self and target isn't self + if ((mainTarget & ValidTarget.SelfOnly) != 0 && target != user) { - if (false) - { - // Unable to execute [@SHEET(xtx/command,$E8(1),2)]. Conditions for use are not met. - if (user is Player) - ((Player)user).SendGameMessage(Server.GetWorldManager().GetActor(), 32556, 0x20, (uint)id); - return false; - } + error?.SetTextId(32515); + return false; } - - // todo: i dont care to message for each scenario, just the most common ones.. - if ((mainTarget & ValidTarget.CorpseOnly) != 0) + //This skill can't be used on an ally and target is an ally + if ((mainTarget & ValidTarget.Ally) == 0 && target.allegiance == user.allegiance) { - if (target != null && target.IsAlive()) - { - if (user is Player) - ((Player)user).SendGameMessage(Server.GetWorldManager().GetActor(), 32513, 0x20, (uint)id); - return false; - } + error?.SetTextId(32516); + return false; } - if ((mainTarget & ValidTarget.Enemy) != 0) + //This skill must be used on an ally and target is not an ally + if ((mainTarget & ValidTarget.AllyOnly) != 0 && target.allegiance != user.allegiance) { - if (target == user || target != null && - user.allegiance == target.allegiance) - { - if (user is Player) - ((Player)user).SendGameMessage(Server.GetWorldManager().GetActor(), 32519, 0x20, (uint)id); - return false; - } + error?.SetTextId(32517); + return false; } - if ((mainTarget & ValidTarget.Ally) != 0) + //This skill can't be used on an enemu and target is an enemy + if ((mainTarget & ValidTarget.Enemy) == 0 && target.allegiance != user.allegiance) { - if (target == null || target.allegiance != user.allegiance) - { - if (user is Player) - ((Player)user).SendGameMessage(Server.GetWorldManager().GetActor(), 32517, 0x20, (uint)id); - return false; - } + error?.SetTextId(32518); + return false; } - if ((mainTarget & ValidTarget.PartyMember) != 0) + //This skill must be used on an enemy and target is an ally + if ((mainTarget & ValidTarget.EnemyOnly) != 0 && target.allegiance == user.allegiance) { - if (target == null || target.currentParty != user.currentParty) - { - if (user is Player) - ((Player)user).SendGameMessage(Server.GetWorldManager().GetActor(), 32547, 0x20, (uint)id); - return false; - } + error?.SetTextId(32519); + return false; } - if ((mainTarget & ValidTarget.Player) != 0) + //This skill can't be used on party members and target is a party member + if ((mainTarget & ValidTarget.Party) == 0 && target.currentParty == user.currentParty) { - if (!(target is Player)) - { - if (user is Player) - ((Player)user).SendGameMessage(Server.GetWorldManager().GetActor(), 32517, 0x20, (uint)id); - return false; - } + error?.SetTextId(32548); + return false; } - return true;// targetFind.CanTarget(target, true, true, true); //this will be done later + //This skill must be used on party members and target is not a party member + if ((mainTarget & ValidTarget.PartyOnly) != 0 && target.currentParty != user.currentParty) + { + error?.SetTextId(32547); + return false; + } + + //This skill can't be used on NPCs and target is an npc + if ((mainTarget & ValidTarget.NPC) == 0 && target.isStatic) + { + error?.SetTextId(32547); + return false; + } + + //This skill must be used on NPCs and target is not an npc + if ((mainTarget & ValidTarget.NPCOnly) != 0 && !target.isStatic) + { + error?.SetTextId(32547); + return false; + } + + // todo: why is player always zoning? + // cant target if zoning + if (target is Player && ((Player)target).playerSession.isUpdatesLocked) + { + user.aiContainer.ChangeTarget(null); + return false; + } + + if (target.zone != user.zone) + return false; + + return true; } public ushort CalculateMpCost(Character user) @@ -363,15 +359,15 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai //Calculate TP cost taking into considerating the combo bonus rate for players //Should this set tpCost or should it be called like CalculateMp where it gets calculated each time? //Might cause issues with the delay between starting and finishing a WS - public ushort CalculateTpCost(Character user) + public short CalculateTpCost(Character user) { - ushort tp = tpCost; + short tp = tpCost; //Calculate tp cost if (user is Player) { var player = user as Player; if (player.playerWork.comboNextCommandId[0] == id || player.playerWork.comboNextCommandId[1] == id) - tp = (ushort)Math.Ceiling((float)tpCost * (1 - player.playerWork.comboCostBonusRate)); + tp = (short)Math.Ceiling((float)tpCost * (1 - player.playerWork.comboCostBonusRate)); } return tp; @@ -386,5 +382,10 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai { return (ushort) commandType; } + + public ushort GetActionType() + { + return (ushort) actionType; + } } } \ No newline at end of file diff --git a/FFXIVClassic Map Server/actors/chara/ai/StatusEffect.cs b/FFXIVClassic Map Server/actors/chara/ai/StatusEffect.cs index b0b25631..7f006567 100644 --- a/FFXIVClassic Map Server/actors/chara/ai/StatusEffect.cs +++ b/FFXIVClassic Map Server/actors/chara/ai/StatusEffect.cs @@ -320,28 +320,28 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai // custom effects here // status for having procs fall off - EvadeProc = 253003, - BlockProc = 253004, - ParryProc = 253005, - MissProc = 253006, - EXPChain = 253007 + EvadeProc = 300000, + BlockProc = 300001, + ParryProc = 300002, + MissProc = 300003, + EXPChain = 300004 } [Flags] enum StatusEffectFlags : uint { None = 0, - Silent = 1 << 0, // dont display effect loss message - //Loss flags - LoseOnDeath = 1 << 1, // effects removed on death - LoseOnZoning = 1 << 2, // effects removed on zoning - LoseOnEsuna = 1 << 3, // effects which can be removed with esuna (debuffs) - LoseOnDispel = 1 << 4, // some buffs which player might be able to dispel from mob - LoseOnLogout = 1 << 5, // effects removed on logging out - LoseOnAttacking = 1 << 6, // effects removed when owner attacks another entity - LoseOnCastStart = 1 << 7, // effects removed when owner starts casting - LoseOnAggro = 1 << 8, // effects removed when owner gains enmity (swiftsong) + //Loss flags - Do we need loseonattacking/caststart? Could just be done with activate flags + LoseOnDeath = 1 << 0, // effects removed on death + LoseOnZoning = 1 << 1, // effects removed on zoning + LoseOnEsuna = 1 << 2, // effects which can be removed with esuna (debuffs) + LoseOnDispel = 1 << 3, // some buffs which player might be able to dispel from mob + LoseOnLogout = 1 << 4, // effects removed on logging out + LoseOnAttacking = 1 << 5, // effects removed when owner attacks another entity + LoseOnCastStart = 1 << 6, // effects removed when owner starts casting + LoseOnAggro = 1 << 7, // effects removed when owner gains enmity (swiftsong) + LoseOnClassChange = 1 << 8, //Effect falls off whhen changing class //Activate flags ActivateOnCastStart = 1 << 9, //Activates when a cast starts. @@ -368,9 +368,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai PreventMovement = 1 << 26, // effects which prevent movement such as bind, still allows turning in place PreventTurn = 1 << 27, // effects which prevent turning, such as stun PreventUntarget = 1 << 28, // effects which prevent changing targets, such as fixation - - Stealth = 1 << 29, // sneak/invis - Stance = 1 << 30, // effects that do not have a timer + Stance = 1 << 29 // effects that do not have a timer } enum StatusEffectOverwrite : byte @@ -387,19 +385,22 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai private Character owner; private Character source; private StatusEffectId id; - private string name; // name of this effect - private DateTime startTime; // when was this effect added - private DateTime endTime; // when this status falls off - private DateTime lastTick; // when did this effect last tick - private uint duration; // how long should this effect last in seconds - private uint tickMs; // how often should this effect proc - private double magnitude; // a value specified by scripter which is guaranteed to be used by all effects - private byte tier; // same effect with higher tier overwrites this - private double extra; // optional value - private StatusEffectFlags flags; // death/erase/dispel etc - private StatusEffectOverwrite overwrite; // how to handle adding an effect with same id (see StatusEfectOverwrite) - private bool silent = false; // do i send a message on losing effect - private bool hidden = false; + private string name; // name of this effect + private DateTime startTime; // when was this effect added + private DateTime endTime; // when this status falls off + private DateTime lastTick; // when did this effect last tick + private uint duration; // how long should this effect last in seconds + private uint tickMs; // how often should this effect proc + private double magnitude; // a value specified by scripter which is guaranteed to be used by all effects + private byte tier; // same effect with higher tier overwrites this + private double extra; // optional value + private StatusEffectFlags flags; // death/erase/dispel etc + private StatusEffectOverwrite overwrite; // how to handle adding an effect with same id (see StatusEfectOverwrite) + private bool silentOnGain = false; //Whether a message is sent when the status is gained + private bool silentOnLoss = false; //Whether a message is sent when the status is lost + private bool hidden = false; //Whether this status is shown. Used for things that aren't really status effects like exp chains and procs + private ushort statusGainTextId = 30328; //The text id used when the status is gained. 30328: [Command] grants you the effect of [status] (Used for buffs) + private ushort statusLossTextId = 30331; //The text id used when the status effect falls off when its time runs out. 30331: You are no longer under the effect of [status] (Used for buffs) public LuaScript script; HitEffect animationEffect; @@ -433,26 +434,36 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai this.name = effect.name; this.flags = effect.flags; this.overwrite = effect.overwrite; + this.statusGainTextId = effect.statusGainTextId; + this.statusLossTextId = effect.statusLossTextId; this.extra = effect.extra; this.script = effect.script; + this.silentOnGain = effect.silentOnGain; + this.silentOnLoss = effect.silentOnLoss; + this.hidden = effect.hidden; } - public StatusEffect(uint id, string name, uint flags, uint overwrite, uint tickMs) + public StatusEffect(uint id, string name, uint flags, uint overwrite, uint tickMs, bool hidden, bool silentOnGain, bool silentOnLoss, ushort statusGainTextId, ushort statusLossTextId) { this.id = (StatusEffectId)id; this.name = name; this.flags = (StatusEffectFlags)flags; this.overwrite = (StatusEffectOverwrite)overwrite; this.tickMs = tickMs; + this.hidden = hidden; + this.silentOnGain = silentOnGain; + this.silentOnLoss = silentOnLoss; + this.statusGainTextId = statusGainTextId; + this.statusLossTextId = statusLossTextId; } // return true when duration has elapsed - public bool Update(DateTime tick) + public bool Update(DateTime tick, CommandResultContainer resultContainer = null) { if (tickMs != 0 && (tick - lastTick).TotalMilliseconds >= tickMs) { lastTick = tick; - if (LuaEngine.CallLuaStatusEffectFunction(this.owner, this, "onTick", this.owner, this) > 0) + if (LuaEngine.CallLuaStatusEffectFunction(this.owner, this, "onTick", this.owner, this, resultContainer) > 0) return true; } @@ -548,9 +559,14 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai return (byte)overwrite; } - public bool GetSilent() + public bool GetSilentOnGain() { - return silent; + return silentOnGain; + } + + public bool GetSilentOnLoss() + { + return silentOnLoss; } public bool GetHidden() @@ -558,6 +574,16 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai return hidden; } + public ushort GetStatusGainTextId() + { + return statusGainTextId; + } + + public ushort GetStatusLossTextId() + { + return statusLossTextId; + } + public void SetStartTime(DateTime time) { this.startTime = time; @@ -566,7 +592,15 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai public void SetEndTime(DateTime time) { - endTime = time; + //If it's a stance, just set endtime to highest number possible for XIV + if ((flags & StatusEffectFlags.Stance) != 0) + { + endTime = Utils.UnixTimeStampToDateTime(4294967295); + } + else + { + endTime = time; + } } //Refresh the status, updating the end time based on the duration of the status and broadcasts the new time @@ -629,9 +663,14 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai this.overwrite = (StatusEffectOverwrite)overwrite; } - public void SetSilent(bool silent) + public void SetSilentOnGain(bool silent) { - this.silent = silent; + this.silentOnGain = silent; + } + + public void SetSilentOnLoss(bool silent) + { + this.silentOnLoss = silent; } public void SetHidden(bool hidden) @@ -639,6 +678,17 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai this.hidden = hidden; } + public void SetStatusGainTextId(ushort textId) + { + this.statusGainTextId = textId; + } + + public void SetStatusLossTextId(ushort textId) + { + this.statusLossTextId = textId; + } + + public void SetAnimation(uint hitEffect) { animationEffect = (HitEffect)hitEffect; diff --git a/FFXIVClassic Map Server/actors/chara/ai/StatusEffectContainer.cs b/FFXIVClassic Map Server/actors/chara/ai/StatusEffectContainer.cs index 4c2dd6cd..9e0925d8 100644 --- a/FFXIVClassic Map Server/actors/chara/ai/StatusEffectContainer.cs +++ b/FFXIVClassic Map Server/actors/chara/ai/StatusEffectContainer.cs @@ -30,39 +30,41 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai public void Update(DateTime tick) { + CommandResultContainer resultContainer = new CommandResultContainer(); + //Regen/Refresh/Regain effects tick every 3 seconds if ((DateTime.Now - lastTick).Seconds >= 3) { - RegenTick(tick); + RegenTick(tick, resultContainer); lastTick = DateTime.Now; } - // list of effects to remove - // if (owner is Player) UpdateTimeAtIndex(4, 4294967295); + // list of effects to remove var removeEffects = new List(); - for (int i = 0; i < effects.Values.Count; i++) + var effectsList = effects.Values; + for (int i = effectsList.Count - 1; i >= 0; i--) { // effect's update function returns true if effect has completed - if (effects.Values.ElementAt(i).Update(tick)) - removeEffects.Add(effects.Values.ElementAt(i)); - + if (effectsList.ElementAt(i).Update(tick, resultContainer)) + removeEffects.Add(effectsList.ElementAt(i)); } // remove effects from this list foreach (var effect in removeEffects) { - RemoveStatusEffect(effect); + RemoveStatusEffect(effect, resultContainer, effect.GetStatusLossTextId()); } - if (sendUpdate) + resultContainer.CombineLists(); + + if (resultContainer.GetList().Count > 0) { - owner.zone.BroadcastPacketsAroundActor(owner, owner.GetActorStatusPackets()); - sendUpdate = false; + owner.DoBattleAction(0, 0x7c000062, resultContainer.GetList()); } } //regen/refresh/regain - public void RegenTick(DateTime tick) + public void RegenTick(DateTime tick, CommandResultContainer resultContainer) { ushort dotTick = (ushort) owner.GetMod(Modifier.RegenDown); ushort regenTick = (ushort) owner.GetMod(Modifier.Regen); @@ -72,18 +74,24 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai //DoTs tick before regen and the full dot damage is displayed, even if some or all of it is nullified by regen. Only effects like stoneskin actually alter the number shown if (dotTick > 0) { - CommandResult action = new CommandResult(owner.actorId, 30331, (uint)(HitEffect.HitEffectType | HitEffect.Hit), dotTick); + //Unsure why 10105 is the textId used + //Also unsure why magicshield is used + CommandResult action = new CommandResult(owner.actorId, 10105, (uint)(HitEffect.MagicEffectType | HitEffect.MagicShield | HitEffect.NoResist), dotTick); utils.BattleUtils.HandleStoneskin(owner, action); // todo: figure out how to make red numbers appear for enemies getting hurt by dots - //owner.DelHP(action.amount); - utils.BattleUtils.DamageTarget(owner, owner, action, null); - owner.DoBattleAction(0, 0, action); + resultContainer.AddAction(action); + owner.DelHP(action.amount, resultContainer); } //DoTs are the only effect to show numbers, so that doesnt need to be handled for these - owner.AddHP(regenTick); - owner.AddMP(refreshtick); - owner.AddTP(regainTick); + if (regenTick != 0) + owner.AddHP(regenTick); + + if (refreshtick != 0) + owner.AddMP(refreshtick); + + if (regainTick != 0) + owner.AddTP(regainTick); } public bool HasStatusEffect(uint id) @@ -96,55 +104,59 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai return effects.ContainsKey((uint)id); } - public CommandResult AddStatusForCommandResult(uint id, byte tier = 1, ulong magnitude = 0, uint duration = 0) - { - CommandResult action = null; - - if (AddStatusEffect(id, tier, magnitude, duration)) - action = new CommandResult(owner.actorId, 30328, id | (uint)HitEffect.StatusEffectType); - - return action; - } - - public bool AddStatusEffect(uint id) + public bool AddStatusEffect(uint id, CommandResultContainer actionContainer = null, ushort worldmasterTextId = 30328) { var se = Server.GetWorldManager().GetStatusEffect(id); - return AddStatusEffect(se, owner); + if (se != null) + { + worldmasterTextId = se.GetStatusGainTextId(); + } + + return AddStatusEffect(se, owner, actionContainer, worldmasterTextId); } - public bool AddStatusEffect(uint id, byte tier) + public bool AddStatusEffect(uint id, byte tier, CommandResultContainer actionContainer = null, ushort worldmasterTextId = 30328) { var se = Server.GetWorldManager().GetStatusEffect(id); - se.SetTier(tier); + if (se != null) + { + se.SetTier(tier); + worldmasterTextId = se.GetStatusGainTextId(); + } - return AddStatusEffect(se, owner); + return AddStatusEffect(se, owner, actionContainer, worldmasterTextId); } - public bool AddStatusEffect(uint id, byte tier, double magnitude) + public bool AddStatusEffect(uint id, byte tier, double magnitude, CommandResultContainer actionContainer = null, ushort worldmasterTextId = 30328) { var se = Server.GetWorldManager().GetStatusEffect(id); - se.SetMagnitude(magnitude); - se.SetTier(tier); + if (se != null) + { + se.SetMagnitude(magnitude); + se.SetTier(tier); + worldmasterTextId = se.GetStatusGainTextId(); + } - return AddStatusEffect(se, owner); + return AddStatusEffect(se, owner, actionContainer, worldmasterTextId); } - public bool AddStatusEffect(uint id, byte tier, double magnitude, uint duration, int tickMs = 3000) + public bool AddStatusEffect(uint id, byte tier, double magnitude, uint duration, int tickMs, CommandResultContainer actionContainer = null, ushort worldmasterTextId = 30328) { var se = Server.GetWorldManager().GetStatusEffect(id); + if (se != null) { se.SetDuration(duration); - se.SetStartTime(DateTime.Now); se.SetOwner(owner); + worldmasterTextId = se.GetStatusGainTextId(); } - return AddStatusEffect(se ?? new StatusEffect(this.owner, id, magnitude, 3000, duration, tier), owner); + return AddStatusEffect(se ?? new StatusEffect(this.owner, id, magnitude, 3000, duration, tier), owner, actionContainer, worldmasterTextId); } - public bool AddStatusEffect(StatusEffect newEffect, Character source, bool silent = false, bool hidden = false) + public bool AddStatusEffect(StatusEffect newEffect, Character source, CommandResultContainer actionContainer = null, ushort worldmasterTextId = 30328) { /* worldMasterTextId @@ -166,9 +178,10 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai if (canOverwrite || effect == null) { // send packet to client with effect added message - if (effect != null && (!silent || !effect.GetSilent() || (effect.GetFlags() & (uint)StatusEffectFlags.Silent) == 0)) + if (newEffect != null && !newEffect.GetSilentOnGain()) { - // todo: send packet to client with effect added message + if (actionContainer != null) + actionContainer.AddAction(new CommandResult(owner.actorId, worldmasterTextId, newEffect.GetStatusEffectId() | (uint)HitEffect.StatusEffectType)); } // wont send a message about losing effect here @@ -181,13 +194,9 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai if (effects.Count < MAX_EFFECTS) { - if(newEffect.script != null) - newEffect.CallLuaFunction(this.owner, "onGain", this.owner, newEffect); - else - LuaEngine.CallLuaStatusEffectFunction(this.owner, newEffect, "onGain", this.owner, newEffect); + newEffect.CallLuaFunction(this.owner, "onGain", this.owner, newEffect, actionContainer); + effects.Add(newEffect.GetStatusEffectId(), newEffect); - //newEffect.SetSilent(silent); - newEffect.SetHidden(hidden); if (!newEffect.GetHidden()) { @@ -212,15 +221,19 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai return false; } - public bool RemoveStatusEffect(StatusEffect effect, bool silent = false) + //playEffect determines whether the effect of the animation that's going to play with actionContainer is going to play on owner + //Generally, for abilities removing an effect, this is true and for effects removing themselves it's false. + public bool RemoveStatusEffect(StatusEffect effect, CommandResultContainer actionContainer = null, ushort worldmasterTextId = 30331, bool playEffect = true) { bool removedEffect = false; if (effect != null && effects.ContainsKey(effect.GetStatusEffectId())) { // send packet to client with effect remove message - if (!silent && !effect.GetSilent() && (effect.GetFlags() & (uint)StatusEffectFlags.Silent) == 0) + if (!effect.GetSilentOnLoss()) { - owner.DoBattleAction(0, 0, new CommandResult(owner.actorId, 30331, effect.GetStatusEffectId())); + //Only send a message if we're using an actioncontainer and the effect normally sends a message when it's lost + if (actionContainer != null) + actionContainer.AddAction(new CommandResult(owner.actorId, worldmasterTextId, effect.GetStatusEffectId() | (playEffect ? 0 : (uint)HitEffect.StatusLossType))); } //hidden effects not in charawork @@ -230,54 +243,20 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai SetStatusAtIndex(index, 0); SetTimeAtIndex(index, 0); } + // function onLose(actor, effect) effects.Remove(effect.GetStatusEffectId()); - if(effect.script != null) - effect.CallLuaFunction(owner, "onLose", owner, effect); - else - LuaEngine.CallLuaStatusEffectFunction(this.owner, effect, "onLose", this.owner, effect); + effect.CallLuaFunction(owner, "onLose", owner, effect, actionContainer); owner.RecalculateStats(); - sendUpdate = true; removedEffect = true; } return removedEffect; } - public bool RemoveStatusEffect(uint effectId, bool silent = false) + public bool RemoveStatusEffect(uint effectId, CommandResultContainer resultContainer = null, ushort worldmasterTextId = 30331, bool playEffect = true) { - bool removedEffect = false; - foreach (var effect in effects.Values) - { - if (effect.GetStatusEffectId() == effectId) - { - RemoveStatusEffect(effect, effect.GetSilent() || silent); - removedEffect = true; - break; - } - } - - return removedEffect; - } - - - //Remove status effect and return the CommandResult message instead of sending it immediately - public CommandResult RemoveStatusEffectForCommandResult(uint effectId, ushort worldMasterTextId = 30331) - { - CommandResult action = null; - if (RemoveStatusEffect(effectId, true)) - action = new CommandResult(owner.actorId, worldMasterTextId, effectId); - - return action; - } - - //Remove status effect and return the CommandResult message instead of sending it immediately - public CommandResult RemoveStatusEffectForCommandResult(StatusEffect effect, ushort worldMasterTextId = 30331) - { - CommandResult action = null; - if (RemoveStatusEffect(effect, true)) - action = new CommandResult(owner.actorId, worldMasterTextId, effect.GetStatusEffectId()); - return action; + return RemoveStatusEffect(GetStatusEffectById(effectId), resultContainer, worldmasterTextId, playEffect); } public StatusEffect CopyEffect(StatusEffect effect) @@ -288,14 +267,14 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai return AddStatusEffect(newEffect, effect.GetSource()) ? newEffect : null; } - public bool RemoveStatusEffectsByFlags(uint flags, bool silent = false) + public bool RemoveStatusEffectsByFlags(uint flags, CommandResultContainer resultContainer = null) { // build list of effects to remove var removeEffects = GetStatusEffectsByFlag(flags); // remove effects from main list foreach (var effect in removeEffects) - RemoveStatusEffect(effect, silent); + RemoveStatusEffect(effect, resultContainer, effect.GetStatusLossTextId(), true); // removed an effect with one of these flags return removeEffects.Count > 0; @@ -321,6 +300,16 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai return list; } + public StatusEffect GetRandomEffectByFlag(uint flag) + { + var list = GetStatusEffectsByFlag(flag); + + if (list.Count > 0) + return list[Program.Random.Next(list.Count)]; + + return null; + } + // todo: why the fuck cant c# convert enums/ public bool HasStatusEffectsByFlag(StatusEffectFlags flags) { @@ -429,7 +418,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai SetStatusAtIndex(index, (ushort) (newEffectId - 200000)); SetTimeAtIndex(index, time); - return new CommandResult(owner.actorId, 30328, (uint) HitEffect.StatusEffectType | newEffectId); + return new CommandResult(owner.actorId, 30330, (uint) HitEffect.StatusEffectType | newEffectId); } } } \ No newline at end of file diff --git a/FFXIVClassic Map Server/actors/chara/ai/controllers/BattleNpcController.cs b/FFXIVClassic Map Server/actors/chara/ai/controllers/BattleNpcController.cs index 7edf4dac..8f21f8c8 100644 --- a/FFXIVClassic Map Server/actors/chara/ai/controllers/BattleNpcController.cs +++ b/FFXIVClassic Map Server/actors/chara/ai/controllers/BattleNpcController.cs @@ -210,7 +210,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers Disengage(); return; } - owner.SetMod((uint)Modifier.Speed, 5); + owner.SetMod((uint)Modifier.MovementSpeed, 5); if ((tick - lastCombatTickScript).TotalSeconds > 3) { Move(); @@ -223,7 +223,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers protected virtual void Move() { - if (!owner.aiContainer.CanFollowPath()) + if (!owner.aiContainer.CanFollowPath() || owner.statusEffects.HasStatusEffectsByFlag(StatusEffectFlags.PreventMovement)) { return; } @@ -363,7 +363,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers // todo: seems ffxiv doesnt even differentiate between sneak/invis? { - hasSneak = target.statusEffects.HasStatusEffectsByFlag((uint)StatusEffectFlags.Stealth); + hasSneak = target.GetMod(Modifier.Stealth) > 0; hasInvisible = hasSneak; } diff --git a/FFXIVClassic Map Server/actors/chara/ai/helpers/TargetFind.cs b/FFXIVClassic Map Server/actors/chara/ai/helpers/TargetFind.cs index c3dbce81..49adbcb8 100644 --- a/FFXIVClassic Map Server/actors/chara/ai/helpers/TargetFind.cs +++ b/FFXIVClassic Map Server/actors/chara/ai/helpers/TargetFind.cs @@ -10,21 +10,28 @@ using FFXIVClassic_Map_Server.actors.group; namespace FFXIVClassic_Map_Server.actors.chara.ai { - // https://github.com/Windower/POLUtils/blob/master/PlayOnline.FFXI/Enums.cs [Flags] public enum ValidTarget : ushort { None = 0x00, - Self = 0x01, - Player = 0x02, - PartyMember = 0x04, - Ally = 0x08, - NPC = 0x10, - Enemy = 0x20, - Unknown = 0x40, - Object = 0x60, - CorpseOnly = 0x80, - Corpse = 0x9D // CorpseOnly + NPC + Ally + Partymember + Self + Self = 0x01, //Can be used on self (if this flag isn't set and target is self, return false) + SelfOnly = 0x02, //Must be used on self (if this flag is set and target isn't self, return false) + Party = 0x4, //Can be used on party members + PartyOnly = 0x8, //Must be used on party members + Ally = 0x10, //Can be used on allies + AllyOnly = 0x20, //Must be used on allies + NPC = 0x40, //Can be used on static NPCs + NPCOnly = 0x80, //Must be used on static NPCs + Enemy = 0x100, //Can be used on enemies + EnemyOnly = 0x200, //Must be used on enemies + Object = 0x400, //Can be used on objects + ObjectOnly = 0x800, //Must be used on objects + Corpse = 0x1000, //Can be used on corpses + CorpseOnly = 0x2000, //Must be used on corpses + + //These are only used for ValidTarget, not MainTarget + MainTargetParty = 0x4000, //Can be used on main target's party (This will basically always be true.) + MainTargetPartyOnly = 0x8000, //Must be used on main target's party (This is for Protect basically.) } /// Targeting from/to different entity types @@ -66,12 +73,13 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai class TargetFind { private Character owner; - private Character masterTarget; // if target is a pet, this is the owner + private Character mainTarget; //This is the target that the skill is being used on + private Character masterTarget; //If mainTarget is a pet, this is the owner private TargetFindCharacterType findType; private ValidTarget validTarget; private TargetFindAOETarget aoeTarget; private TargetFindAOEType aoeType; - private Vector3 aoeTargetPosition; //This is the center of circle an cone AOEs and the position where line aoes come out + private Vector3 aoeTargetPosition; //This is the center of circle of cone AOEs and the position where line aoes come out. If we have mainTarget this might not be needed? private float aoeTargetRotation; //This is the direction the aoe target is facing private float maxDistance; //Radius for circle and cone AOEs, length for line AOEs private float minDistance; //Minimum distance to that target must be to be able to be hit @@ -82,14 +90,16 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai private float param; private List targets; - public TargetFind(Character owner) + public TargetFind(Character owner, Character mainTarget = null) { - this.owner = owner; Reset(); + this.owner = owner; + this.mainTarget = mainTarget == null ? owner : mainTarget; } public void Reset() { + this.mainTarget = owner; this.findType = TargetFindCharacterType.None; this.validTarget = ValidTarget.Enemy; this.aoeType = TargetFindAOEType.None; @@ -201,11 +211,6 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai //if (targets.Count > 8) //targets.RemoveRange(8, targets.Count - 8); - - //Curaga starts with lowest health players, so the targets are definitely sorted at least for some abilities - //Other aoe abilities might be sorted by distance? - //Protect is random - targets.Sort(delegate (Character a, Character b) { return a.GetHP().CompareTo(b.GetHP()); }); } /// @@ -323,41 +328,57 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai if (target == null || !retarget && targets.Contains(target)) return false; - //This skill can't be used on self and target is self, return false - if ((validTarget & ValidTarget.Self) == 0 && target == owner) + if (target == null) return false; - //This skill can't be used on NPCs and target is an NPC, return false - if ((validTarget & ValidTarget.NPC) == 0 && target.isStatic) - return false; - - //This skill can't be used on corpses and target is dead, return false + //This skill can't be used on a corpse and target is dead if ((validTarget & ValidTarget.Corpse) == 0 && target.IsDead()) return false; - //This skill must be used on Allies and target is not an ally, return false - if ((validTarget & ValidTarget.Ally) != 0 && target.allegiance != owner.allegiance) - return false; - - - //This skill can't be used on players and target is a player, return false - //Do we need a player flag? Ally/Enemy flags probably serve the same purpose - //if ((validTarget & ValidTarget.Player) == 0 && target is Player) - //return false; - - - //This skill must be used on enemies an target is not an enemy - if ((validTarget & ValidTarget.Enemy) != 0 && target.allegiance == owner.allegiance) - return false; - - //This skill must be used on a party member and target is not in owner's party, return false - if ((validTarget & ValidTarget.PartyMember) != 0 && target.currentParty != owner.currentParty) - return false; - - //This skill must be used on a corpse and target is alive, return false + //This skill must be used on a corpse and target is alive if ((validTarget & ValidTarget.CorpseOnly) != 0 && target.IsAlive()) return false; + //This skill can't be used on self and target is self + if ((validTarget & ValidTarget.Self) == 0 && target == owner) + return false; + + //This skill must be used on self and target isn't self + if ((validTarget & ValidTarget.SelfOnly) != 0 && target != owner) + return false; + + //This skill can't be used on an ally and target is an ally + if ((validTarget & ValidTarget.Ally) == 0 && target.allegiance == owner.allegiance) + return false; + + //This skill must be used on an ally and target is not an ally + if ((validTarget & ValidTarget.AllyOnly) != 0 && target.allegiance != owner.allegiance) + return false; + + //This skill can't be used on an enemu and target is an enemy + if ((validTarget & ValidTarget.Enemy) == 0 && target.allegiance != owner.allegiance) + return false; + + //This skill must be used on an enemy and target is an ally + if ((validTarget & ValidTarget.EnemyOnly) != 0 && target.allegiance == owner.allegiance) + return false; + + //This skill can't be used on party members and target is a party member + if ((validTarget & ValidTarget.Party) == 0 && target.currentParty == owner.currentParty) + return false; + + //This skill must be used on party members and target is not a party member + if ((validTarget & ValidTarget.PartyOnly) != 0 && target.currentParty != owner.currentParty) + return false; + + //This skill can't be used on NPCs and target is an npc + if ((validTarget & ValidTarget.NPC) == 0 && target.isStatic) + return false; + + //This skill must be used on NPCs and target is not an npc + if ((validTarget & ValidTarget.NPCOnly) != 0 && !target.isStatic) + return false; + // todo: why is player always zoning? // cant target if zoning if (target is Player && ((Player)target).playerSession.isUpdatesLocked) @@ -372,6 +393,15 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai if (validTarget == ValidTarget.Self && aoeType == TargetFindAOEType.None && owner != target) return false; + //This skill can't be used on main target's party members and target is a party member of main target + if ((validTarget & ValidTarget.MainTargetParty) == 0 && target.currentParty == mainTarget.currentParty) + return false; + + //This skill must be used on main target's party members and target is not a party member of main target + if ((validTarget & ValidTarget.MainTargetPartyOnly) != 0 && target.currentParty != mainTarget.currentParty) + return false; + + // this is fuckin retarded, think of a better way l8r if (!ignoreAOE) { diff --git a/FFXIVClassic Map Server/actors/chara/ai/state/AbilityState.cs b/FFXIVClassic Map Server/actors/chara/ai/state/AbilityState.cs index 8d7d3d5a..a37cb2dd 100644 --- a/FFXIVClassic Map Server/actors/chara/ai/state/AbilityState.cs +++ b/FFXIVClassic Map Server/actors/chara/ai/state/AbilityState.cs @@ -15,10 +15,11 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state { this.startTime = DateTime.Now; this.skill = Server.GetWorldManager().GetBattleCommand(skillId); - var returnCode = lua.LuaEngine.CallLuaBattleCommandFunction(owner, skill, "ability", "onAbilityPrepare", owner, target, skill); + var returnCode = skill.CallLuaFunction(owner, "onAbilityPrepare", owner, target, skill); - this.target = target != null ? target : owner; + this.target = (skill.mainTarget & ValidTarget.SelfOnly) != 0 ? owner : target; + errorResult = new CommandResult(owner.actorId, 32553, 0); if (returnCode == 0) { OnStart(); @@ -32,7 +33,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state public override void OnStart() { - var returnCode = lua.LuaEngine.CallLuaBattleCommandFunction(owner, skill, "ability", "onAbilityStart", owner, target, skill); + var returnCode = skill.CallLuaFunction(owner, "onAbilityStart", owner, target, skill); if (returnCode != 0) { diff --git a/FFXIVClassic Map Server/actors/chara/ai/state/AttackState.cs b/FFXIVClassic Map Server/actors/chara/ai/state/AttackState.cs index 45c48ec7..14e7d226 100644 --- a/FFXIVClassic Map Server/actors/chara/ai/state/AttackState.cs +++ b/FFXIVClassic Map Server/actors/chara/ai/state/AttackState.cs @@ -100,26 +100,35 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state //List actions = new List(); CommandResultContainer actions = new CommandResultContainer(); - - var i = 0; - for (int hitNum = 0; hitNum < 1 /* owner.GetMod((uint) Modifier.HitCount)*/; hitNum++) - { - CommandResult action = new CommandResult(target.actorId, 0x765D, (uint)HitEffect.Hit, 100, (byte)HitDirection.None, (byte) hitNum); - action.commandType = CommandType.AutoAttack; - action.actionType = ActionType.Physical; - action.actionProperty = (ActionProperty) owner.GetMod(Modifier.AttackType); - // evasion, miss, dodge, etc to be handled in script, calling helpers from scripts/weaponskills.lua - // temporary evade/miss/etc function to test hit effects - action.DoAction(owner, target, null, actions); - } - // todo: this is fuckin stupid, probably only need *one* error packet, not an error for each action - CommandResult[] errors = (CommandResult[])actions.GetList().ToArray().Clone(); - CommandResult error = null;// new BattleAction(0, null, 0, 0); - //owner.DoActions(null, actions.GetList(), ref error); - //owner.OnAttack(this, actions[0], ref errorResult); - var anim = (uint)(17 << 24 | 1 << 12); - owner.DoBattleAction(22104, anim, actions.GetList()); + //This is all temporary until the skill sheet is finishd and the different auto attacks are added to the database + //Some mobs have multiple unique auto attacks that they switch between as well as ranged auto attacks, so we'll need a way to handle that + //For now, just use a temporary hardcoded BattleCommand that's the same for everyone. + BattleCommand attackCommand = new BattleCommand(22104, "Attack"); + attackCommand.range = 5; + attackCommand.rangeHeight = 10; + attackCommand.worldMasterTextId = 0x765D; + attackCommand.mainTarget = (ValidTarget)768; + attackCommand.validTarget = (ValidTarget)17152; + attackCommand.commandType = CommandType.AutoAttack; + attackCommand.numHits = (byte)owner.GetMod(Modifier.HitCount); + attackCommand.basePotency = 100; + ActionProperty property = (owner.GetMod(Modifier.AttackType) != 0) ? (ActionProperty)owner.GetMod(Modifier.AttackType) : ActionProperty.Slashing; + attackCommand.actionProperty = property; + attackCommand.actionType = ActionType.Physical; + + uint anim = (17 << 24 | 1 << 12); + + if (owner is Player) + anim = (25 << 24 | 1 << 12); + + attackCommand.battleAnimation = anim; + + if (owner.CanUse(target, attackCommand)) + { + attackCommand.targetFind.FindWithinArea(target, attackCommand.validTarget, attackCommand.aoeTarget); + owner.DoBattleCommand(attackCommand, "autoattack"); + } } public override void TryInterrupt() diff --git a/FFXIVClassic Map Server/actors/chara/ai/state/DeathState.cs b/FFXIVClassic Map Server/actors/chara/ai/state/DeathState.cs index 01a5a06a..4e049679 100644 --- a/FFXIVClassic Map Server/actors/chara/ai/state/DeathState.cs +++ b/FFXIVClassic Map Server/actors/chara/ai/state/DeathState.cs @@ -12,7 +12,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state { owner.Disengage(); owner.ChangeState(SetActorStatePacket.MAIN_STATE_DEAD); - owner.statusEffects.RemoveStatusEffectsByFlags((uint)StatusEffectFlags.LoseOnDeath, true); + owner.statusEffects.RemoveStatusEffectsByFlags((uint)StatusEffectFlags.LoseOnDeath); //var deathStatePacket = SetActorStatePacket.BuildPacket(owner.actorId, SetActorStatePacket.MAIN_STATE_DEAD2, owner.currentSubState); //owner.zone.BroadcastPacketAroundActor(owner, deathStatePacket); canInterrupt = false; diff --git a/FFXIVClassic Map Server/actors/chara/ai/state/MagicState.cs b/FFXIVClassic Map Server/actors/chara/ai/state/MagicState.cs index b569db4c..4008a72a 100644 --- a/FFXIVClassic Map Server/actors/chara/ai/state/MagicState.cs +++ b/FFXIVClassic Map Server/actors/chara/ai/state/MagicState.cs @@ -18,32 +18,28 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state this.startPos = owner.GetPosAsVector3(); this.startTime = DateTime.Now; this.spell = Server.GetWorldManager().GetBattleCommand(spellId); - var returnCode = lua.LuaEngine.CallLuaBattleCommandFunction(owner, spell, "magic", "onMagicPrepare", owner, target, spell); - - //Modify spell based on status effects. Need to do it here because they can modify cast times - List effects = owner.statusEffects.GetStatusEffectsByFlag((uint)(StatusEffectFlags.ActivateOnCastStart)); + var returnCode = spell.CallLuaFunction(owner, "onMagicPrepare", owner, target, spell); //modify skill based on status effects //Do this here to allow buffs like Resonance to increase range before checking CanCast() - foreach (var effect in effects) - lua.LuaEngine.CallLuaStatusEffectFunction(owner, effect, "onMagicCast", owner, effect, spell); + owner.statusEffects.CallLuaFunctionByFlag((uint)StatusEffectFlags.ActivateOnCastStart, "onMagicCast", owner, spell); - this.target = target != null ? target : owner; + this.target = (spell.mainTarget & ValidTarget.SelfOnly) != 0 ? owner : target; - if (returnCode == 0 && owner.CanCast(this.target, spell)) + errorResult = new CommandResult(owner.actorId, 32553, 0); + if (returnCode == 0 && owner.CanUse(this.target, spell, errorResult)) { OnStart(); } else { - errorResult = new CommandResult(owner.actorId, 32553, 0); interrupt = true; } } public override void OnStart() { - var returnCode = lua.LuaEngine.CallLuaBattleCommandFunction(owner, spell, "magic", "onMagicStart", owner, target, spell); + var returnCode = spell.CallLuaFunction(owner, "onMagicStart", owner, target, spell); if (returnCode != 0) { @@ -62,7 +58,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state Player p = (Player)owner; if (spell.comboStep == 1 || ((p.playerWork.comboNextCommandId[0] == spell.id || p.playerWork.comboNextCommandId[1] == spell.id))) { - lua.LuaEngine.CallLuaBattleCommandFunction(owner, spell, "magic", "onCombo", owner, target, spell); + spell.CallLuaFunction(owner, "onCombo", owner, target, spell); spell.isCombo = true; } } @@ -168,7 +164,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state private bool CanCast() { - return owner.CanCast(target, spell) && spell.IsValidMainTarget(owner, target) && !HasMoved(); + return owner.CanUse(target, spell); } private bool HasMoved() diff --git a/FFXIVClassic Map Server/actors/chara/ai/state/WeaponSkillState.cs b/FFXIVClassic Map Server/actors/chara/ai/state/WeaponSkillState.cs index 28b8d4eb..a6ecb15e 100644 --- a/FFXIVClassic Map Server/actors/chara/ai/state/WeaponSkillState.cs +++ b/FFXIVClassic Map Server/actors/chara/ai/state/WeaponSkillState.cs @@ -14,11 +14,14 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state base(owner, target) { this.startTime = DateTime.Now; - //this.target = skill.targetFind. this.skill = Server.GetWorldManager().GetBattleCommand(skillId); - var returnCode = lua.LuaEngine.CallLuaBattleCommandFunction(owner, skill, "weaponskill", "onSkillPrepare", owner, target, skill); - if (returnCode == 0 && owner.CanWeaponSkill(target, skill)) + var returnCode = skill.CallLuaFunction(owner, "onSkillPrepare", owner, target, skill); + + this.target = (skill.mainTarget & ValidTarget.SelfOnly) != 0 ? owner : target; + + errorResult = new CommandResult(owner.actorId, 32553, 0); + if (returnCode == 0 && owner.CanUse(this.target, skill, errorResult)) { OnStart(); } @@ -31,7 +34,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state public override void OnStart() { - var returnCode = lua.LuaEngine.CallLuaBattleCommandFunction(owner, skill, "weaponskill", "onSkillStart", owner, target, skill); + var returnCode = skill.CallLuaFunction(owner, "onSkillStart", owner, target, skill); if (returnCode != 0) { @@ -48,8 +51,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state { //If there is a position bonus if (skill.positionBonus != BattleCommandPositionBonus.None) - //lua.LuaEngine.CallLuaBattleCommandFunction(owner, skill, "weaponskill", "onPositional", owner, target, skill); - skill.CallLuaFunction(owner, "onPositional", owner, target, skill); + skill.CallLuaFunction(owner, "weaponskill", "onPositional", owner, target, skill); //Combo stuff if (owner is Player) @@ -61,7 +63,6 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state //If owner is a player and the skill being used is part of the current combo if (p.playerWork.comboNextCommandId[0] == skill.id || p.playerWork.comboNextCommandId[1] == skill.id) { - lua.LuaEngine.CallLuaBattleCommandFunction(owner, skill, "weaponskill", "onCombo", owner, target, skill); skill.CallLuaFunction(owner, "onCombo", owner, target, skill); skill.isCombo = true; } @@ -161,7 +162,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state private bool CanUse() { - return owner.CanWeaponSkill(target, skill) && skill.IsValidMainTarget(owner, target); + return owner.CanUse(target, skill); } public BattleCommand GetWeaponSkill() diff --git a/FFXIVClassic Map Server/actors/chara/ai/utils/BattleUtils.cs b/FFXIVClassic Map Server/actors/chara/ai/utils/BattleUtils.cs index 7f4d215c..85141818 100644 --- a/FFXIVClassic Map Server/actors/chara/ai/utils/BattleUtils.cs +++ b/FFXIVClassic Map Server/actors/chara/ai/utils/BattleUtils.cs @@ -12,37 +12,55 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.utils static class BattleUtils { - public static Dictionary SingleHitTypeTextIds = new Dictionary() + public static Dictionary PhysicalHitTypeTextIds = new Dictionary() { { HitType.Miss, 30311 }, { HitType.Evade, 30310 }, { HitType.Parry, 30308 }, { HitType.Block, 30306 }, - { HitType.Resist, 30310 }, //Resists seem to use the evade text id { HitType.Hit, 30301 }, { HitType.Crit, 30302 } }; + public static Dictionary MagicalHitTypeTextIds = new Dictionary() + { + { HitType.SingleResist,30318 }, + { HitType.DoubleResist,30317 }, + { HitType.TripleResist, 30316 },//Triple Resists seem to use the same text ID as full resists + { HitType.FullResist,30316 }, + { HitType.Hit, 30319 }, + { HitType.Crit, 30392 } //Unsure why crit is separated from the rest of the ids + }; + public static Dictionary MultiHitTypeTextIds = new Dictionary() { { HitType.Miss, 30449 }, //The attack misses. { HitType.Evade, 0 }, //Evades were removed before multi hit skills got their own messages, so this doesnt exist { HitType.Parry, 30448 }, //[Target] parries, taking x points of damage. { HitType.Block, 30447 }, //[Target] blocks, taking x points of damage. - { HitType.Resist, 0 }, //No spells are multi-hit, so this doesn't exist { HitType.Hit, 30443 }, //[Target] tales x points of damage { HitType.Crit, 30444 } //Critical! [Target] takes x points of damage. }; - public static Dictionary HitTypeEffects = new Dictionary() + public static Dictionary HitTypeEffectsPhysical = new Dictionary() { { HitType.Miss, 0 }, { HitType.Evade, HitEffect.Evade }, { HitType.Parry, HitEffect.Parry }, { HitType.Block, HitEffect.Block }, - { HitType.Resist, HitEffect.RecoilLv1 },//Probably don't need this, resists are handled differently to the rest { HitType.Hit, HitEffect.Hit }, - { HitType.Crit, HitEffect.Crit } + { HitType.Crit, HitEffect.Crit | HitEffect.CriticalHit } + }; + + //Magic attacks can't miss, be blocked, or parried. Resists are technically evades + public static Dictionary HitTypeEffectsMagical = new Dictionary() + { + { HitType.SingleResist, HitEffect.WeakResist }, + { HitType.DoubleResist, HitEffect.WeakResist }, + { HitType.TripleResist, HitEffect.WeakResist }, + { HitType.FullResist, HitEffect.FullResist }, + { HitType.Hit, HitEffect.NoResist }, + { HitType.Crit, HitEffect.Crit } }; public static Dictionary KnockbackEffects = new Dictionary() @@ -201,7 +219,8 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.utils //Or we could have HitTypes for DoubleResist, TripleResist, and FullResist that get used here. public static void CalculateResistDamage(Character attacker, Character defender, BattleCommand skill, CommandResult action) { - double percentResist = 0.5; + //Every tier of resist is a 25% reduction in damage. ie SingleResist is 25% damage taken down, Double is 50% damage taken down, etc + double percentResist = 0.25 * (action.hitType - HitType.SingleResist + 1); action.amountMitigated = (ushort)(action.amount * (1 - percentResist)); action.amount = (ushort)(action.amount * percentResist); @@ -217,7 +236,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.utils defender.SubtractMod((uint)Modifier.Stoneskin, mitigation); } - public static void DamageTarget(Character attacker, Character defender, CommandResult action, CommandResultContainer actionContainer= null) + public static void DamageTarget(Character attacker, Character defender, BattleCommand skill, CommandResult action, CommandResultContainer actionContainer= null) { if (defender != null) { @@ -230,9 +249,9 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.utils bnpc.lastAttacker = attacker; } - defender.DelHP((short)action.amount); - attacker.OnDamageDealt(defender, action, actionContainer); - defender.OnDamageTaken(attacker, action, actionContainer); + defender.DelHP((short)action.amount, actionContainer); + attacker.OnDamageDealt(defender, skill, action, actionContainer); + defender.OnDamageTaken(attacker, skill, action, actionContainer); // todo: other stuff too if (defender is BattleNpc) @@ -248,13 +267,13 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.utils } } - public static void HealTarget(Character caster, Character target, CommandResult action, CommandResultContainer actionContainer = null) + public static void HealTarget(Character caster, Character target, BattleCommand skill, CommandResult action, CommandResultContainer actionContainer = null) { if (target != null) { - target.AddHP(action.amount); + target.AddHP(action.amount, actionContainer); - target.statusEffects.CallLuaFunctionByFlag((uint) StatusEffectFlags.ActivateOnHealed, "onHealed", caster, target, action, actionContainer); + target.statusEffects.CallLuaFunctionByFlag((uint)StatusEffectFlags.ActivateOnHealed, "onHealed", caster, target, skill, action, actionContainer); } } @@ -279,7 +298,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.utils public static double GetParryRate(Character attacker, Character defender, BattleCommand skill, CommandResult action) { //Can't parry with shield, can't parry rear attacks - if (defender.GetMod((uint)Modifier.HasShield) != 0 || action.param == (byte) HitDirection.Rear) + if (defender.GetMod((uint)Modifier.CanBlock) != 0 || action.param == (byte) HitDirection.Rear) return 0; double parryRate = 10.0; @@ -324,7 +343,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.utils public static double GetBlockRate(Character attacker, Character defender, BattleCommand skill, CommandResult action) { //Shields are required to block and can't block from rear. - if (defender.GetMod((uint)Modifier.HasShield) == 0 || action.param == (byte)HitDirection.Rear) + if (defender.GetMod((uint)Modifier.CanBlock) == 0 || action.param == (byte)HitDirection.Rear) return 0; short dlvl = (short)(defender.GetLevel() - attacker.GetLevel()); @@ -355,11 +374,26 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.utils return false; } + //This probably isn't totally correct but it's close enough for now. + //Full Resists seem to be calculated in a different way because the resist rates don't seem to line up with kanikan's testing (their tests didn't show any full resists) + //Non-spells with elemental damage can be resisted, it just doesnt say in the chat that they were. As far as I can tell, all mob-specific attacks are considered not to be spells public static bool TryResist(Character attacker, Character defender, BattleCommand skill, CommandResult action) { - if ((Program.Random.NextDouble() * 100) <= action.resistRate) + //The rate degrades for each check. Meaning with 100% resist, the attack will always be resisted, but it won't necessarily be a triple or full resist + //Rates beyond 100 still increase the chance for higher resist tiers though + double rate = action.resistRate; + + int i = -1; + + while ((Program.Random.NextDouble() * 100) <= rate && i < 4) { - action.hitType = HitType.Resist; + rate /= 2; + i++; + } + + if (i != -1) + { + action.hitType = (HitType) ((int) HitType.SingleResist + i); CalculateResistDamage(attacker, defender, skill, action); return true; } @@ -425,6 +459,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.utils FinishActionStatus(caster, target, skill, action, actionContainer); break; default: + action.effectId = (uint) HitEffect.AnimationEffectType; actionContainer.AddAction(action); break; } @@ -450,7 +485,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.utils } //Actions have different text ids depending on whether they're a part of a multi-hit ws or not. - Dictionary textIds = SingleHitTypeTextIds; + Dictionary textIds = PhysicalHitTypeTextIds; //If this is the first hit of a multi hit command, add the "You use [command] on [target]" action //Needs to be done here because certain buff messages appear before it. @@ -473,23 +508,27 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.utils actionContainer.AddAction(action); action.enmity = (ushort) (action.enmity * (skill != null ? skill.enmityModifier : 1)); + //Damage the target - DamageTarget(attacker, defender, action, actionContainer); + DamageTarget(attacker, defender, skill, action, actionContainer); } public static void FinishActionSpell(Character attacker, Character defender, BattleCommand skill, CommandResult action, CommandResultContainer actionContainer = null) { + //I'm assuming that like physical attacks stoneskin is taken into account before mitigation + HandleStoneskin(defender, action); + //Determine the hit type of the action - if (!TryMiss(attacker, defender, skill, action)) + //Spells don't seem to be able to miss, instead magic acc/eva is used for resists (which are generally called evades in game) + //Unlike blocks and parries, crits do not go through resists. + if (!TryResist(attacker, defender, skill, action)) { - HandleStoneskin(defender, action); if (!TryCrit(attacker, defender, skill, action)) - if (!TryResist(attacker, defender, skill, action)) - action.hitType = HitType.Hit; + action.hitType = HitType.Hit; } - //There are no multi-hit spells - action.worldMasterTextId = SingleHitTypeTextIds[action.hitType]; + //There are no multi-hit spells, so we don't need to take that into account + action.worldMasterTextId = MagicalHitTypeTextIds[action.hitType]; //Set the hit effect SetHitEffectSpell(attacker, defender, skill, action); @@ -500,7 +539,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.utils actionContainer.AddAction(action); - DamageTarget(attacker, defender, action, actionContainer); + DamageTarget(attacker, defender, skill, action, actionContainer); } public static void FinishActionHeal(Character attacker, Character defender, BattleCommand skill, CommandResult action, CommandResultContainer actionContainer = null) @@ -510,7 +549,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.utils actionContainer.AddAction(action); - HealTarget(attacker, defender, action, actionContainer); + HealTarget(attacker, defender, skill, action, actionContainer); } public static void FinishActionStatus(Character attacker, Character defender, BattleCommand skill, CommandResult action, CommandResultContainer actionContainer = null) @@ -542,10 +581,10 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.utils hitEffect |= HitEffect.RecoilLv3; } - hitEffect |= HitTypeEffects[hitType]; + hitEffect |= HitTypeEffectsPhysical[hitType]; //For combos that land, add the combo effect - if (skill != null && skill.isCombo && hitType > HitType.Evade && hitType != HitType.Evade && !skill.comboEffectAdded) + if (skill != null && skill.isCombo && action.ActionLanded() && !skill.comboEffectAdded) { hitEffect |= (HitEffect)(skill.comboStep << 15); skill.comboEffectAdded = true; @@ -555,7 +594,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.utils if (hitType >= HitType.Parry) { //Protect / Shell only show on physical/ magical attacks respectively. - if (defender.statusEffects.HasStatusEffect(StatusEffectId.Protect)) + if (defender.statusEffects.HasStatusEffect(StatusEffectId.Protect) || defender.statusEffects.HasStatusEffect(StatusEffectId.Protect2)) if (action != null) hitEffect |= HitEffect.Protect; @@ -572,20 +611,8 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.utils var hitEffect = HitEffect.MagicEffectType; HitType hitType = action.hitType; - //Recoil levels for spells are a bit different than physical. Recoil levels are used for resists. - //Lv1 is for larger resists, Lv2 is for smaller resists and Lv3 is for no resists. Crit is still used for crits - if (hitType == HitType.Resist) - { - //todo: calculate resist levels and figure out what the difference between Lv1 and 2 in retail was. For now assuming a full resist with 0 damage dealt is Lv1, all other resists Lv2 - if (action.amount == 0) - hitEffect |= HitEffect.RecoilLv1; - else - hitEffect |= HitEffect.RecoilLv2; - } - else - hitEffect |= HitEffect.RecoilLv3; - hitEffect |= HitTypeEffects[hitType]; + hitEffect |= HitTypeEffectsMagical[hitType]; if (skill != null && skill.isCombo && !skill.comboEffectAdded) { @@ -594,16 +621,15 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.utils } //if attack hit the target, take into account protective status effects - if (hitType >= HitType.Block) + if (action.ActionLanded()) { //Protect / Shell only show on physical/ magical attacks respectively. + //The magic hit effect category only has a flag for shell (and another shield effect that seems unused) + //Even though traited protect gives magic defense, the shell effect doesn't play on attacks + //This also means stoneskin doesnt show, but it does reduce damage if (defender.statusEffects.HasStatusEffect(StatusEffectId.Shell)) if (action != null) - hitEffect |= HitEffect.Shell; - - if (defender.statusEffects.HasStatusEffect(StatusEffectId.Stoneskin)) - if (action != null) - hitEffect |= HitEffect.Stoneskin; + hitEffect |= HitEffect.MagicShell; } action.effectId = (uint)hitEffect; } @@ -654,7 +680,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.utils double rand = Program.Random.NextDouble(); //Statuses only land for non-resisted attacks and attacks that hit - if (skill != null && skill.statusId != 0 && (action.hitType > HitType.Evade && action.hitType != HitType.Resist) && rand < skill.statusChance) + if (skill != null && skill.statusId != 0 && (action.ActionLanded()) && rand < skill.statusChance) { StatusEffect effect = Server.GetWorldManager().GetStatusEffect(skill.statusId); //Because combos might change duration or tier @@ -670,7 +696,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.utils { //If we need an extra action to show the status text if (isAdditional) - results.AddAction(target.actorId, 30328, skill.statusId | (uint) HitEffect.StatusEffectType); + results.AddAction(target.actorId, effect.GetStatusGainTextId(), skill.statusId | (uint) HitEffect.StatusEffectType); } else action.worldMasterTextId = 32002;//Is this right? @@ -733,7 +759,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.utils return 0; int baseLevel = Math.Min(player.GetLevel(), mob.GetLevel()); - ushort baseEXP = BASEEXP[baseLevel]; + ushort baseEXP = BASEEXP[baseLevel - 1]; double dlvlModifier = 1.0; @@ -864,10 +890,9 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.utils totalBonus += GetChainBonus(expChainNumber); StatusEffect newChain = Server.GetWorldManager().GetStatusEffect((uint)StatusEffectId.EXPChain); - newChain.SetSilent(true); newChain.SetDuration(timeLimit); newChain.SetTier((byte)(Math.Min(expChainNumber + 1, 255))); - attacker.statusEffects.AddStatusEffect(newChain, attacker, true, true); + attacker.statusEffects.AddStatusEffect(newChain, attacker); actionContainer?.AddEXPActions(attacker.AddExp(baseExp, (byte)attacker.GetClass(), (byte)(totalBonus.Min(255)))); } diff --git a/FFXIVClassic Map Server/actors/chara/npc/BattleNpc.cs b/FFXIVClassic Map Server/actors/chara/npc/BattleNpc.cs index c16d5889..7d736201 100644 --- a/FFXIVClassic Map Server/actors/chara/npc/BattleNpc.cs +++ b/FFXIVClassic Map Server/actors/chara/npc/BattleNpc.cs @@ -181,7 +181,7 @@ namespace FFXIVClassic_Map_Server.Actors return true; } - public override bool CanCast(Character target, BattleCommand spell) + public override bool CanUse(Character target, BattleCommand spell, CommandResult error = null) { // todo: if (target == null) @@ -202,18 +202,6 @@ namespace FFXIVClassic_Map_Server.Actors return true; } - public override bool CanWeaponSkill(Character target, BattleCommand skill) - { - // todo: - return true; - } - - public override bool CanUseAbility(Character target, BattleCommand ability) - { - // todo: - return false; - } - public uint GetDespawnTime() { return despawnTime; @@ -256,8 +244,6 @@ namespace FFXIVClassic_Map_Server.Actors 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(); @@ -280,6 +266,7 @@ namespace FFXIVClassic_Map_Server.Actors // defeat/defeats if (actionContainer != null) actionContainer.AddEXPAction(new CommandResult(actorId, 30108, 0)); + if (lastAttacker.currentParty != null && lastAttacker.currentParty is Party) { foreach (var memberId in ((Party)lastAttacker.currentParty).members) @@ -303,6 +290,7 @@ namespace FFXIVClassic_Map_Server.Actors if (positionUpdates != null) positionUpdates.Clear(); + aiContainer.InternalDie(tick, despawnTime); //this.ResetMoveSpeeds(); // todo: reset cooldowns @@ -446,11 +434,11 @@ namespace FFXIVClassic_Map_Server.Actors mobModifiers.Add((MobModifier)mobModId, val); } - public override void OnDamageTaken(Character attacker, CommandResult action, CommandResultContainer actionContainer = null) + public override void OnDamageTaken(Character attacker, BattleCommand skill, CommandResult action, CommandResultContainer actionContainer = null) { if (GetMobMod((uint)MobModifier.DefendScript) != 0) lua.LuaEngine.CallLuaBattleFunction(this, "onDamageTaken", this, attacker, action.amount); - base.OnDamageTaken(attacker, action, actionContainer); + base.OnDamageTaken(attacker, skill, action, actionContainer); } } } diff --git a/FFXIVClassic Map Server/actors/chara/player/Player.cs b/FFXIVClassic Map Server/actors/chara/player/Player.cs index 280a3bbb..5c94d1d8 100644 --- a/FFXIVClassic Map Server/actors/chara/player/Player.cs +++ b/FFXIVClassic Map Server/actors/chara/player/Player.cs @@ -139,6 +139,8 @@ namespace FFXIVClassic_Map_Server.Actors private List ownedDirectors = new List(); private Director loginInitDirector = null; + List hotbarSlotsToUpdate = new List(); + public PlayerWork playerWork = new PlayerWork(); public Session playerSession; @@ -759,10 +761,11 @@ namespace FFXIVClassic_Map_Server.Actors this.positionZ = destinationZ; this.rotation = destinationRot; + this.statusEffects.RemoveStatusEffectsByFlags((uint)StatusEffectFlags.LoseOnZoning); + //Save Player Database.SavePlayerPlayTime(this); Database.SavePlayerPosition(this); - this.statusEffects.RemoveStatusEffectsByFlags((uint)StatusEffectFlags.LoseOnZoning, true); Database.SavePlayerStatusEffects(this); } @@ -1018,6 +1021,12 @@ namespace FFXIVClassic_Map_Server.Actors //Check if bonus point available... set + //Remove buffs that fall off when changing class + CommandResultContainer resultContainer = new CommandResultContainer(); + statusEffects.RemoveStatusEffectsByFlags((uint)StatusEffectFlags.LoseOnClassChange, resultContainer); + resultContainer.CombineLists(); + DoBattleAction(0, 0x7c000062, resultContainer.GetList()); + //Set rested EXP charaWork.parameterSave.state_mainSkill[0] = classId; charaWork.parameterSave.state_mainSkillLevel = charaWork.battleSave.skillLevel[classId-1]; @@ -1956,7 +1965,14 @@ namespace FFXIVClassic_Map_Server.Actors } QueuePackets(propPacketUtil.Done()); + } + if ((updateFlags & ActorUpdateFlags.Hotbar) != 0) + { + UpdateHotbar(hotbarSlotsToUpdate); + hotbarSlotsToUpdate.Clear(); + + updateFlags ^= ActorUpdateFlags.Hotbar; } @@ -1972,12 +1988,11 @@ namespace FFXIVClassic_Map_Server.Actors //Update commands and recast timers for the entire hotbar public void UpdateHotbar() { - List slotsToUpdate = new List(); for (ushort i = charaWork.commandBorder; i < charaWork.commandBorder + 30; i++) { - slotsToUpdate.Add(i); + hotbarSlotsToUpdate.Add(i); } - UpdateHotbar(slotsToUpdate); + updateFlags |= ActorUpdateFlags.Hotbar; } //Updates the hotbar and recast timers for only certain hotbar slots @@ -2049,7 +2064,6 @@ namespace FFXIVClassic_Map_Server.Actors ushort lowHotbarSlot = (ushort)(hotbarSlot - charaWork.commandBorder); ushort maxRecastTime = (ushort)(ability != null ? ability.maxRecastTimeSeconds : 5); 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) @@ -2061,8 +2075,8 @@ namespace FFXIVClassic_Map_Server.Actors charaWork.parameterTemp.maxCommandRecastTime[lowHotbarSlot] = maxRecastTime; charaWork.parameterSave.commandSlot_recastTime[lowHotbarSlot] = recastEnd; - slotsToUpdate.Add(hotbarSlot); - UpdateHotbar(slotsToUpdate); + hotbarSlotsToUpdate.Add(hotbarSlot); + updateFlags |= ActorUpdateFlags.Hotbar; } @@ -2098,25 +2112,23 @@ namespace FFXIVClassic_Map_Server.Actors Database.EquipAbility(this, GetCurrentClassOrJob(), (ushort)(lowHotbarSlot2), 0xA0F00000 ^ charaWork.command[hotbarSlot2], charaWork.parameterSave.commandSlot_recastTime[lowHotbarSlot2]); //Update slots on client - List slotsToUpdate = new List(); - slotsToUpdate.Add(hotbarSlot1); - slotsToUpdate.Add(hotbarSlot2); - UpdateHotbar(slotsToUpdate); + hotbarSlotsToUpdate.Add(hotbarSlot1); + hotbarSlotsToUpdate.Add(hotbarSlot2); + updateFlags |= ActorUpdateFlags.Hotbar; } public void UnequipAbility(ushort hotbarSlot, bool printMessage = true) { - List slotsToUpdate = new List(); - ushort trueHotbarSlot = (ushort)(hotbarSlot + charaWork.commandBorder - 1); + ushort trueHotbarSlot = (ushort)(hotbarSlot + charaWork.commandBorder); uint commandId = charaWork.command[trueHotbarSlot]; - Database.UnequipAbility(this, (ushort)(trueHotbarSlot - charaWork.commandBorder)); + Database.UnequipAbility(this, hotbarSlot); charaWork.command[trueHotbarSlot] = 0; - slotsToUpdate.Add(trueHotbarSlot); + hotbarSlotsToUpdate.Add(trueHotbarSlot); - if(printMessage) + if (printMessage && commandId != 0) SendGameMessage(Server.GetWorldManager().GetActor(), 30604, 0x20, 0, 0xA0F00000 ^ commandId); - UpdateHotbar(slotsToUpdate); + updateFlags |= ActorUpdateFlags.Hotbar; } //Finds the first hotbar slot with a given commandId. @@ -2290,110 +2302,75 @@ namespace FFXIVClassic_Map_Server.Actors return true; } - public override bool CanCast(Character target, BattleCommand spell) + //Do we need separate functions? they check the same things + public override bool CanUse(Character target, BattleCommand skill, CommandResult error = null) { - //Might want to do these with a CommandResult instead to be consistent with the rest of command stuff - if (GetHotbarTimer(spell.id) > Utils.UnixTimeStampUTC()) - { - // todo: this needs confirming - // Please wait a moment and try again. - SendGameMessage(Server.GetWorldManager().GetActor(), 32535, 0x20, (uint)spell.id); - return false; - } - if (target == null) - { - // Target does not exist. - SendGameMessage(Server.GetWorldManager().GetActor(), 32511, 0x20, (uint)spell.id); - return false; - } - if (Utils.XZDistance(positionX, positionZ, target.positionX, target.positionZ) > spell.range) - { - // The target is too far away. - SendGameMessage(Server.GetWorldManager().GetActor(), 32539, 0x20, (uint)spell.id); - return false; - } - if (Utils.XZDistance(positionX, positionZ, target.positionX, target.positionZ) < spell.minRange) - { - // The target is too close. - SendGameMessage(Server.GetWorldManager().GetActor(), 32538, 0x20, (uint)spell.id); - return false; - } - if (target.positionY - positionY > (spell.rangeHeight / 2)) - { - // The target is too far above you. - SendGameMessage(Server.GetWorldManager().GetActor(), 32540, 0x20, (uint)spell.id); - return false; - } - if (positionY - target.positionY > (spell.rangeHeight / 2)) - { - // The target is too far below you. - SendGameMessage(Server.GetWorldManager().GetActor(), 32541, 0x20, (uint)spell.id); - return false; - } - if (!IsValidTarget(target, spell.mainTarget) || !spell.IsValidMainTarget(this, target)) + if (!skill.IsValidMainTarget(this, target, error) || !IsValidTarget(target, skill.mainTarget)) { // error packet is set in IsValidTarget return false; } - return true; - } - public override bool CanWeaponSkill(Character target, BattleCommand skill) - { - // todo: see worldmaster ids 32558~32557 for proper ko message and stuff + //Might want to do these with a BattleAction instead to be consistent with the rest of command stuff if (GetHotbarTimer(skill.id) > Utils.UnixTimeStampUTC()) { // todo: this needs confirming // Please wait a moment and try again. - SendGameMessage(Server.GetWorldManager().GetActor(), 32535, 0x20, (uint)skill.id); + error?.SetTextId(32535); return false; } - if (target == null) + if (Utils.XZDistance(positionX, positionZ, target.positionX, target.positionZ) > skill.range) { - // Target does not exist. - SendGameMessage(Server.GetWorldManager().GetActor(), 32511, 0x20, (uint)skill.id); + // The target is too far away. + error?.SetTextId(32539); + return false; + } + + if (Utils.XZDistance(positionX, positionZ, target.positionX, target.positionZ) < skill.minRange) + { + // The target is too close. + error?.SetTextId(32538); return false; } - //Original game checked height difference before horizontal distance if (target.positionY - positionY > (skill.rangeHeight / 2)) { // The target is too far above you. - SendGameMessage(Server.GetWorldManager().GetActor(), 32540, 0x20, (uint)skill.id); + error?.SetTextId(32540); return false; } if (positionY - target.positionY > (skill.rangeHeight / 2)) { // The target is too far below you. - SendGameMessage(Server.GetWorldManager().GetActor(), 32541, 0x20, (uint)skill.id); + error?.SetTextId(32541); return false; } - var targetDist = Utils.XZDistance(positionX, positionZ, target.positionX, target.positionZ); - - if (targetDist > skill.range) + if (skill.CalculateMpCost(this) > GetMP()) { - // The target is out of range. - SendGameMessage(Server.GetWorldManager().GetActor(), 32537, 0x20, (uint)skill.id); + // You do not have enough MP. + error?.SetTextId(32545); return false; } - if (targetDist < skill.minRange) + if (skill.CalculateTpCost(this) > GetTP()) { - // The target is too close. - SendGameMessage(Server.GetWorldManager().GetActor(), 32538, 0x20, (uint)skill.id); + // You do not have enough TP. + error?.SetTextId(32546); return false; } - - if (!IsValidTarget(target, skill.validTarget) || !skill.IsValidMainTarget(this, target)) + //Proc requirement + if (skill.procRequirement != BattleCommandProcRequirement.None && !charaWork.battleTemp.timingCommandFlag[(int)skill.procRequirement - 1]) { - // error packet is set in IsValidTarget + //Conditions for use are not met + error?.SetTextId(32556); return false; } + return true; } @@ -2598,7 +2575,7 @@ namespace FFXIVClassic_Map_Server.Actors StatusEffect comboEffect = new StatusEffect(this, Server.GetWorldManager().GetStatusEffect((uint) StatusEffectId.Combo)); comboEffect.SetDuration(13); comboEffect.SetOverwritable(1); - statusEffects.AddStatusEffect(comboEffect, this, true); + statusEffects.AddStatusEffect(comboEffect, this); playerWork.comboCostBonusRate = 1; } //Otherwise we're ending a combo, remove the status @@ -2634,10 +2611,10 @@ namespace FFXIVClassic_Map_Server.Actors } var hasShield = equip.GetItemAtSlot(SLOT_OFFHAND) != null ? 1 : 0; - SetMod((uint)Modifier.HasShield, hasShield); + SetMod((uint)Modifier.CanBlock, hasShield); SetMod((uint)Modifier.AttackType, damageAttribute); - SetMod((uint)Modifier.AttackDelay, attackDelay); + SetMod((uint)Modifier.Delay, attackDelay); SetMod((uint)Modifier.HitCount, hitCount); //These stats all correlate in a 3:2 fashion @@ -2647,13 +2624,13 @@ namespace FFXIVClassic_Map_Server.Actors AddMod((uint)Modifier.Defense, (long)(GetMod(Modifier.Vitality) * 0.667)); //These stats correlate in a 4:1 fashion. (Unsure if MND is accurate but it would make sense for it to be) - AddMod((uint)Modifier.MagicAttack, (long)((float)GetMod(Modifier.Intelligence) * 0.25)); + AddMod((uint)Modifier.AttackMagicPotency, (long)((float)GetMod(Modifier.Intelligence) * 0.25)); AddMod((uint)Modifier.MagicAccuracy, (long)((float)GetMod(Modifier.Mind) * 0.25)); - AddMod((uint)Modifier.MagicHeal, (long)((float)GetMod(Modifier.Mind) * 0.25)); + AddMod((uint)Modifier.HealingMagicPotency, (long)((float)GetMod(Modifier.Mind) * 0.25)); AddMod((uint)Modifier.MagicEvasion, (long)((float)GetMod(Modifier.Piety) * 0.25)); - AddMod((uint)Modifier.MagicEnfeeblingPotency, (long)((float)GetMod(Modifier.Piety) * 0.25)); + AddMod((uint)Modifier.EnfeeblingMagicPotency, (long)((float)GetMod(Modifier.Piety) * 0.25)); //VIT correlates to HP in a 1:1 fashion AddMod((uint)Modifier.Hp, (long)((float)Modifier.Vitality)); diff --git a/FFXIVClassic Map Server/actors/group/Group.cs b/FFXIVClassic Map Server/actors/group/Group.cs index 6b15364c..e5f1e164 100644 --- a/FFXIVClassic Map Server/actors/group/Group.cs +++ b/FFXIVClassic Map Server/actors/group/Group.cs @@ -2,6 +2,7 @@ using FFXIVClassic_Map_Server.dataobjects; using FFXIVClassic_Map_Server.packets.send.group; using FFXIVClassic_Map_Server.packets.send.groups; +using System; using System.Collections.Generic; namespace FFXIVClassic_Map_Server.actors.group @@ -126,13 +127,14 @@ namespace FFXIVClassic_Map_Server.actors.group while (true) { - if (GetMemberCount() - currentIndex >= 64) + int memberCount = Math.Min(GetMemberCount(), members.Count); + if (memberCount - currentIndex >= 64) session.QueuePacket(GroupMembersX64Packet.buildPacket(session.id, session.GetActor().zoneId, time, members, ref currentIndex)); - else if (GetMemberCount() - currentIndex >= 32) + else if (memberCount - currentIndex >= 32) session.QueuePacket(GroupMembersX32Packet.buildPacket(session.id, session.GetActor().zoneId, time, members, ref currentIndex)); - else if (GetMemberCount() - currentIndex >= 16) + else if (memberCount - currentIndex >= 16) session.QueuePacket(GroupMembersX16Packet.buildPacket(session.id, session.GetActor().zoneId, time, members, ref currentIndex)); - else if (GetMemberCount() - currentIndex > 0) + else if (memberCount - currentIndex > 0) session.QueuePacket(GroupMembersX08Packet.buildPacket(session.id, session.GetActor().zoneId, time, members, ref currentIndex)); else break; diff --git a/FFXIVClassic Map Server/packets/send/Actor/battle/CommandResult.cs b/FFXIVClassic Map Server/packets/send/Actor/battle/CommandResult.cs index c58b282a..09c663cd 100644 --- a/FFXIVClassic Map Server/packets/send/Actor/battle/CommandResult.cs +++ b/FFXIVClassic Map Server/packets/send/Actor/battle/CommandResult.cs @@ -8,13 +8,26 @@ namespace FFXIVClassic_Map_Server.packets.send.actor.battle //These flags can be stacked and mixed, but the client will prioritize certain flags over others. [Flags] public enum HitEffect : uint - { - //All HitEffects have the last byte 0x8 + { + //This is used for physical attacks HitEffectType = 8 << 24, + //This is used for additioanl effect hits. Only difference from HitEffectType is that it does not play audio. + AdditionalEffectType = 24 << 24, //Status effects use 32 << 24 StatusEffectType = 32 << 24, - //Magic effects use 48 << 24 + //When losing a status effect while using a skill, this prevents the hit effect from playing on the actor playing the animation + StatusLossType = 40 << 24, + //Magic effects use 48 << 24, this is also used for when statuses are lost on attack MagicEffectType = 48 << 24, + //This places the number on the user regardless of the target this hit effect is for, used for things like bloodbath + SelfHealType = 72 << 24, + //Plays the effect animation with no text or additional effects. Unsure if there are any flags. Used for things like Convert + AnimationEffectType = 96 << 24, + + //Each Type has it's own set of flags. These should be split into their own enums, + //but for now just keep them all under HitEffect so we don't have to change anything. + + //HitEffectType flags //Not setting RecoilLv2 or RecoilLv3 results in the weaker RecoilLv1. //These are the recoil animations that play on the target, ranging from weak to strong. @@ -54,15 +67,10 @@ namespace FFXIVClassic_Map_Server.packets.send.actor.battle //Another effect plays when both Protect and Shell flags are activated. //Not sure what this effect is. //Random guess: if the attack was a hybrid of both physical and magical and the target had both Protect and Shell buffs applied. - Protect = 1 << 6 | HitEffectType, - Shell = 1 << 7 | HitEffectType, + Protect = 1 << 6, + Shell = 1 << 7, ProtectShellSpecial = Protect | Shell, - // Required for heal text to be blue, not sure if that's all it's used for - Heal = 1 << 8, - MP = 1 << 9, //Causes "MP" text to appear when used with MagicEffectType. | with Heal to make text blue - TP = 1 << 10,//Causes "TP" text to appear when used with MagicEffectType. | with Heal to make text blue - //If only HitEffect1 is set out of the hit effects, the "Evade!" pop-up text triggers along with the evade visual. //If no hit effects are set, the "Miss!" pop-up is triggered and no hit visual is played. HitEffect1 = 1 << 9, @@ -103,17 +111,69 @@ namespace FFXIVClassic_Map_Server.packets.send.actor.battle UnknownShieldEffect = HitEffect5 | HitEffect4, Stoneskin = HitEffect5 | HitEffect4 | HitEffect1, - //Unknown = 1 << 14, -- Not sure what this flag does; might be another HitEffect. - //A special effect when performing appropriate skill combos in succession. //Ex: Thunder (SkillCombo1 Effect) -> Thundara (SkillCombo2 Effect) -> Thundaga (SkillCombo3 Effect) //Special Note: SkillCombo4 was never actually used in 1.0 since combos only chained up to 3 times maximum. SkillCombo1 = 1 << 15, SkillCombo2 = 1 << 16, SkillCombo3 = SkillCombo1 | SkillCombo2, - SkillCombo4 = 1 << 17 + SkillCombo4 = 1 << 17, - //Flags beyond here are unknown/untested. + //This is used in the absorb effect for some reason + Unknown = 1 << 19, + + //AdditionalEffectType flags + //The AdditionalEffectType is used for the additional effects some weapons have. + //These effect ids do not repeat the effect of the attack and will not show without a preceding HitEffectType or MagicEffectType + + //It's unclear what this is for. The ifrit fight capture has a BLM using the garuda weapon + //and this flag is set every time but has no apparent effect. + UnknownAdditionalFlag = 1, + + //These play effects on the target + FireEffect = 1 << 10, + IceEffect = 2 << 10, + WindEffect = 3 << 10, + EarthEffect = 4 << 10, + LightningEffect = 5 << 10, + WaterEffect = 6 << 10, + AstralEffect = 7 << 10, //Possibly for blind? + UmbralEffect = 8 << 10, //Posibly for poison? + + //Unknown status effect effects + StatusEffect1 = 12 << 10, + StatusEffect2 = 13 << 10, + + HPAbsorbEffect = 14 << 10, + MPAbsorbEffect = 15 << 10, + TPAbsorbEffect = 16 << 10, + TripleAbsorbEffect = 17 << 10, //Not sure about this + MoogleEffect = 18 << 10, + + //MagicEffectType Flags + //THese are used for magic effects that deal or heal damage as well as damage over time effects + //Crit is the same as HitEffectType + FullResist = 0, + WeakResist = 1 << 0, //Used for level 1, 2, and 3 resists probably + NoResist = 1 << 1, + + MagicShell = 1 << 4, //Used when casting on target with shell effects. MagicEffectType doesnt have a flag for protect or stoneskin + MagicShield = 1 << 5, //When used with an command that has an animation, this plays a purple shield effect. DoTs also have this flag set (at least on ifrit) but they have no animations so it doesnt show + + // Required for heal text to be blue, not sure if that's all it's used for + Heal = 1 << 8, + MP = 1 << 9, //Causes "MP" text to appear when used with MagicEffectType. | with Heal to make text blue + TP = 1 << 10, //Causes "TP" text to appear when used with MagicEffectType. | with Heal to make text blue + + //SelfHealType flags + //This category causes numbers to appear on the user rather regardless of the target associated with the hit effect and do not play an animation + //These determine the text that displays (HP has no text) + SelfHealHP = 0, + SelfHealMP = 1 << 0, //Shows MP text on self. | with SelfHeal to make blue + SelfHealTP = 1 << 1, //Shows TP text on self. | with SelfHeal to make blue + + //Causes self healing numbers to be blue + SelfHeal = 1 << 10, } //Mixing some of these flags will cause the client to crash. @@ -134,9 +194,12 @@ namespace FFXIVClassic_Map_Server.packets.send.actor.battle Evade = 1, Parry = 2, Block = 3, - Resist = 4, - Hit = 5, - Crit = 6 + SingleResist = 4, + DoubleResist = 5, + TripleResist = 6, + FullResist = 7, + Hit = 8, + Crit = 9 } //Type of action @@ -326,5 +389,16 @@ namespace FFXIVClassic_Map_Server.packets.send.actor.battle { return (ushort)hitType; } + + public void SetTextId(ushort id) + { + worldMasterTextId = id; + } + + //Whether this action didn't miss, and wasn't evaded or resisted + public bool ActionLanded() + { + return hitType > HitType.Evade && hitType != HitType.SingleResist && hitType != HitType.DoubleResist && hitType != HitType.FullResist; + } } } diff --git a/FFXIVClassic Map Server/packets/send/Actor/battle/CommandResultContainer.cs b/FFXIVClassic Map Server/packets/send/Actor/battle/CommandResultContainer.cs index 43ac47a3..ddb3cda4 100644 --- a/FFXIVClassic Map Server/packets/send/Actor/battle/CommandResultContainer.cs +++ b/FFXIVClassic Map Server/packets/send/Actor/battle/CommandResultContainer.cs @@ -20,6 +20,8 @@ namespace FFXIVClassic_Map_Server.packets.send.actor.battle } //Just to make scripting simpler + //These have to be split into the normal actions and absorb actions because they use different flags + //AddMP/HP/TPAction are for actions where the targetID is the person being targeted by command. Like Sanguine Rite would use AddMPAction public void AddMPAction(uint targetId, ushort worldMasterTextId, ushort amount) { uint effectId = (uint) (HitEffect.MagicEffectType | HitEffect.MP | HitEffect.Heal); @@ -28,13 +30,38 @@ namespace FFXIVClassic_Map_Server.packets.send.actor.battle public void AddHPAction(uint targetId, ushort worldMasterTextId, ushort amount) { - uint effectId = (uint)(HitEffect.MagicEffectType | HitEffect.Heal); + uint effectId = (uint) (HitEffect.MagicEffectType | HitEffect.Heal); AddAction(targetId, worldMasterTextId, effectId, amount); } public void AddTPAction(uint targetId, ushort worldMasterTextId, ushort amount) { - uint effectId = (uint)(HitEffect.MagicEffectType | HitEffect.TP); + uint effectId = (uint) (HitEffect.MagicEffectType | HitEffect.TP | HitEffect.Heal); + AddAction(targetId, worldMasterTextId, effectId, amount); + } + + //These are used for skills where the targetId is the person using a command. For example casting with parsimony would use AddMPAbsorbAction + public void AddMPAbsorbAction(uint targetId, ushort worldMasterTextId, ushort amount) + { + uint effectId = (uint) (HitEffect.SelfHealType | HitEffect.SelfHealMP | HitEffect.SelfHeal); + AddAction(targetId, worldMasterTextId, effectId, amount); + } + + public void AddHPAbsorbAction(uint targetId, ushort worldMasterTextId, ushort amount) + { + uint effectId = (uint) (HitEffect.SelfHealType | HitEffect.SelfHeal | HitEffect.SelfHeal); + AddAction(targetId, worldMasterTextId, effectId, amount); + } + + public void AddTPAbsorbAction(uint targetId, ushort worldMasterTextId, ushort amount) + { + uint effectId = (uint) (HitEffect.SelfHealType | HitEffect.SelfHealTP | HitEffect.SelfHeal); + AddAction(targetId, worldMasterTextId, effectId, amount); + } + + public void AddHitAction(uint targetId, ushort worldMasterTextId, ushort amount) + { + uint effectId = (uint) (HitEffect.HitEffectType | HitEffect.Hit); AddAction(targetId, worldMasterTextId, effectId, amount); } diff --git a/FFXIVClassic World Server/DataObjects/Group/Group.cs b/FFXIVClassic World Server/DataObjects/Group/Group.cs index abeb02a9..43ce5b77 100644 --- a/FFXIVClassic World Server/DataObjects/Group/Group.cs +++ b/FFXIVClassic World Server/DataObjects/Group/Group.cs @@ -1,5 +1,6 @@ using FFXIVClassic.Common; using FFXIVClassic_World_Server.Packets.Send.Subpackets.Groups; +using System; using System.Collections.Generic; namespace FFXIVClassic_World_Server.DataObjects.Group @@ -104,13 +105,14 @@ namespace FFXIVClassic_World_Server.DataObjects.Group while (true) { - if (GetMemberCount() - currentIndex >= 64) + int memberCount = Math.Min(GetMemberCount(), members.Count); + if (memberCount - currentIndex >= 64) session.clientConnection.QueuePacket(GroupMembersX64Packet.buildPacket(session.sessionId, session.currentZoneId, time, members, ref currentIndex)); - else if (GetMemberCount() - currentIndex >= 32) + else if (memberCount - currentIndex >= 32) session.clientConnection.QueuePacket(GroupMembersX32Packet.buildPacket(session.sessionId, session.currentZoneId, time, members, ref currentIndex)); - else if (GetMemberCount() - currentIndex >= 16) + else if (memberCount - currentIndex >= 16) session.clientConnection.QueuePacket(GroupMembersX16Packet.buildPacket(session.sessionId, session.currentZoneId, time, members, ref currentIndex)); - else if (GetMemberCount() - currentIndex > 0) + else if (memberCount - currentIndex > 0) session.clientConnection.QueuePacket(GroupMembersX08Packet.buildPacket(session.sessionId, session.currentZoneId, time, members, ref currentIndex)); else break; diff --git a/data/scripts/battleutils.lua b/data/scripts/battleutils.lua index 6cfe600e..00a9f53d 100644 --- a/data/scripts/battleutils.lua +++ b/data/scripts/battleutils.lua @@ -61,4 +61,47 @@ TargetFindAOEType = Circle = 1, Cone = 2, Box = 3 +} + +StatusEffectFlags = +{ + None = 0, + + --Loss flags - Do we need loseonattacking/caststart? Could just be done with activate flags + LoseOnDeath = bit32.lshift(1, 0), -- effects removed on death + LoseOnZoning = bit32.lshift(1, 1), -- effects removed on zoning + LoseOnEsuna = bit32.lshift(1, 2), -- effects which can be removed with esuna (debuffs) + LoseOnDispel = bit32.lshift(1, 3), -- some buffs which player might be able to dispel from mob + LoseOnLogout = bit32.lshift(1, 4), -- effects removed on logging out + LoseOnAttacking = bit32.lshift(1, 5), -- effects removed when owner attacks another entity + LoseOnCastStart = bit32.lshift(1, 6), -- effects removed when owner starts casting + LoseOnAggro = bit32.lshift(1, 7), -- effects removed when owner gains enmity (swiftsong) + LoseOnClassChange = bit32.lshift(1, 8), --Effect falls off whhen changing class + + --Activate flags + ActivateOnCastStart = bit32.lshift(1, 9), --Activates when a cast starts. + ActivateOnCommandStart = bit32.lshift(1, 10), --Activates when a command is used, before iterating over targets. Used for things like power surge, excruciate. + ActivateOnCommandFinish = bit32.lshift(1, 11), --Activates when the command is finished, after all targets have been iterated over. Used for things like Excruciate and Resonance falling off. + ActivateOnPreactionTarget = bit32.lshift(1, 12), --Activates after initial rates are calculated for an action against owner + ActivateOnPreactionCaster = bit32.lshift(1, 13), --Activates after initial rates are calculated for an action by owner + ActivateOnDamageTaken = bit32.lshift(1, 14), + ActivateOnHealed = bit32.lshift(1, 15), + + --Should these be rolled into DamageTaken? + ActivateOnMiss = bit32.lshift(1, 16), --Activates when owner misses + ActivateOnEvade = bit32.lshift(1, 17), --Activates when owner evades + ActivateOnParry = bit32.lshift(1, 18), --Activates when owner parries + ActivateOnBlock = bit32.lshift(1, 19), --Activates when owner evades + ActivateOnHit = bit32.lshift(1, 20), --Activates when owner hits + ActivateOnCrit = bit32.lshift(1, 21), --Activates when owner crits + + --Prevent flags. Sleep/stun/petrify/etc combine these + PreventSpell = bit32.lshift(1, 22), -- effects which prevent using spells, such as silence + PreventWeaponSkill = bit32.lshift(1, 23), -- effects which prevent using weaponskills, such as pacification + PreventAbility = bit32.lshift(1, 24), -- effects which prevent using abilities, such as amnesia + PreventAttack = bit32.lshift(1, 25), -- effects which prevent basic attacks + PreventMovement = bit32.lshift(1, 26), -- effects which prevent movement such as bind, still allows turning in place + PreventTurn = bit32.lshift(1, 27), -- effects which prevent turning, such as stun + PreventUntarget = bit32.lshift(1, 28), -- effects which prevent changing targets, such as fixation + Stance = bit32.lshift(1, 29) -- effects that do not have a timer } \ No newline at end of file diff --git a/data/scripts/commands/EsunaMagic.lua b/data/scripts/commands/EsunaMagic.lua new file mode 100644 index 00000000..a349c17a --- /dev/null +++ b/data/scripts/commands/EsunaMagic.lua @@ -0,0 +1,5 @@ +function onEventStarted(player, command, triggerName, arg1, arg2, arg3, arg4, targetActor, arg5, arg6, arg7, arg8) + player.Cast(command.actorId, targetActor); + + player:endEvent(); +end \ No newline at end of file diff --git a/data/scripts/commands/TeleportCommand.lua b/data/scripts/commands/TeleportCommand.lua index b3a1b310..327608f4 100644 --- a/data/scripts/commands/TeleportCommand.lua +++ b/data/scripts/commands/TeleportCommand.lua @@ -92,6 +92,14 @@ function onEventStarted(player, actor, triggerName, isTeleport) if (choice == 1) then player:PlayAnimation(0x4000FFB); player:SendGameMessage(worldMaster, 34104, 0x20); + + --bandaid fix for returning while dead, missing things like weakness and the heal number + if (player:GetHP() == 0) then + player:SetHP(player.GetMaxHP()); + player:ChangeState(0); + player:PlayAnimation(0x01000066); + end + if (isInn) then --Return to Inn if (player:GetHomePointInn() == 1) then @@ -107,12 +115,6 @@ function onEventStarted(player, actor, triggerName, isTeleport) if (destination ~= nil) then randoPos = getRandomPointInBand(destination[2], destination[4], 3, 5); rotation = getAngleFacing(randoPos.x, randoPos.y, destination[2], destination[4]); - --bandaid fix for returning while dead, missing things like weakness and the heal number - if (player:GetHP() == 0) then - player:SetHP(player.GetMaxHP()); - player:ChangeState(0); - player:PlayAnimation(0x01000066); - end GetWorldManager():DoZoneChange(player, destination[1], nil, 0, 2, randoPos.x, destination[3], randoPos.y, rotation); end diff --git a/data/scripts/commands/ability/battle_voice.lua b/data/scripts/commands/ability/battle_voice.lua index cecc4d45..9cc183b2 100644 --- a/data/scripts/commands/ability/battle_voice.lua +++ b/data/scripts/commands/ability/battle_voice.lua @@ -12,8 +12,12 @@ end; function onSkillFinish(caster, target, skill, action, actionContainer) --Only the bard gets the Battle Voice effect if caster == target then - actionContainer.AddAction(caster.statusEffects.AddStatusForBattleAction(223253, 1, 0, 30)); + local effect = GetWorldManager():GetStatusEffect(223253); + effect.SetDuration(30); + caster.statusEffects.AddStatusEffect(effect, caster, actionContainer); end - action.DoAction(caster, target, skill, actionContainer); + local effect = GetWorldManager():GetStatusEffect(223029); + effect.SetDuration(60); + caster.statusEffects.AddStatusEffect(effect, caster, actionContainer); end; \ No newline at end of file diff --git a/data/scripts/commands/ability/berserk.lua b/data/scripts/commands/ability/berserk.lua index 5163866b..227bb1a1 100644 --- a/data/scripts/commands/ability/berserk.lua +++ b/data/scripts/commands/ability/berserk.lua @@ -14,6 +14,18 @@ function onAbilityStart(caster, target, ability) end; function onSkillFinish(caster, target, skill, action, actionContainer) - --DoAction handles rates, buffs, dealing damage - action.DoAction(caster, target, skill, actionContainer); + --223207: Berserk + --223208: Rampage + --Remove Rampage effect. I'm assuming no message is sent like LNC surges + caster.statusEffects.RemoveStatusEffect(223208); + + --If caster has berserk already, remove it and send a message. + local buff = caster.statusEffects.GetStatusEffectById(223207) + + if buff ~= nil then + caster.statusEffects.RemoveStatusEffect(buff, actionContainer, 30329); + else + --DoAction handles rates, buffs, dealing damage + action.DoAction(caster, target, skill, actionContainer); + end end; \ No newline at end of file diff --git a/data/scripts/commands/ability/blissful_mind.lua b/data/scripts/commands/ability/blissful_mind.lua index 7af11cf1..7c60d12e 100644 --- a/data/scripts/commands/ability/blissful_mind.lua +++ b/data/scripts/commands/ability/blissful_mind.lua @@ -22,22 +22,18 @@ function onSkillFinish(caster, target, skill, action, actionContainer) --If we have a buff then Blissful Mind removes that buff and restores MP. Otherwise, it adds the Blissful Mind effect if buff ~= nil then local amount = buff.GetExtra(); - local remAction = caster.statusEffects.RemoveStatusEffectForBattleAction(buff, 30329); - caster.AddMP(amount); actionContainer.AddMPAction(caster.actorId, 33007, amount); - actionContainer.AddAction(remAction); + caster.statusEffects.RemoveStatusEffect(buff, actionContainer, 30329); else --Blissful mind takes 25% of CURRENT HP and begins storing MP up to that point, at which point the buff changes to indicate its full local amount = caster.GetHP() * 0.25; - caster.DelHP(amount); + caster.DelHP(amount, actionContainer); skill.statusMagnitude = amount; --DoAction handles rates, buffs, dealing damage action.DoAction(caster, target, skill, actionContainer); - end - end; \ No newline at end of file diff --git a/data/scripts/commands/ability/chameleon.lua b/data/scripts/commands/ability/chameleon.lua index 92e6c1a5..206401c9 100644 --- a/data/scripts/commands/ability/chameleon.lua +++ b/data/scripts/commands/ability/chameleon.lua @@ -14,5 +14,7 @@ function onAbilityStart(caster, target, ability) end; function onSkillFinish(caster, target, skill, action, actionContainer) - target.hateContainer.UpdateHate(caster, -840); + --Need a way to get all targets with hate for player + --target.hateContainer.UpdateHate(caster, -840); + action.DoAction(caster, target, skill, actionContainer); end; \ No newline at end of file diff --git a/data/scripts/commands/ability/cleric_stance.lua b/data/scripts/commands/ability/cleric_stance.lua index 0cae6d8d..7750a78c 100644 --- a/data/scripts/commands/ability/cleric_stance.lua +++ b/data/scripts/commands/ability/cleric_stance.lua @@ -10,6 +10,12 @@ function onAbilityStart(caster, target, ability) end; function onSkillFinish(caster, target, skill, action, actionContainer) - --DoAction handles rates, buffs, dealing damage - action.DoAction(caster, target, skill, actionContainer); + local buff = caster.statusEffects.GetStatusEffectById(223227) + + if buff ~= nil then + caster.statusEffects.RemoveStatusEffect(buff, actionContainer, 30329); + else + --DoAction handles rates, buffs, dealing damage + action.DoAction(caster, target, skill, actionContainer); + end end; \ No newline at end of file diff --git a/data/scripts/commands/ability/convert.lua b/data/scripts/commands/ability/convert.lua new file mode 100644 index 00000000..8b4fc608 --- /dev/null +++ b/data/scripts/commands/ability/convert.lua @@ -0,0 +1,20 @@ +require("global"); +require("ability"); + +function onAbilityPrepare(caster, target, ability) + return 0; +end; + +function onAbilityStart(caster, target, ability) + return 0; +end; + +function onSkillFinish(caster, target, skill, action, actionContainer) + newMP = math.min(caster.GetHP(), caster.GetMaxMP()) + newHP = math.min(caster.GetMP(), caster.GetMaxHP()) + caster.SetHP(newHP) + caster.SetMP(newMP) + + --Set effect id + action.DoAction(caster, target, skill, actionContainer); +end; \ No newline at end of file diff --git a/data/scripts/commands/ability/cover.lua b/data/scripts/commands/ability/cover.lua index 0f4be40a..4ac09ab9 100644 --- a/data/scripts/commands/ability/cover.lua +++ b/data/scripts/commands/ability/cover.lua @@ -17,7 +17,7 @@ function onSkillFinish(caster, target, skill, action, actionContainer) coverTier = 2; end - actionContainer.AddAction(caster.statusEffects.AddStatusForBattleAction(223063, coverTier, skill.statusDuration)); + caster.statusEffects.AddStatusEffect(223063, coverTier, 0, 15, 0); --Apply Covered to target action.DoAction(caster, target, skill, actionContainer); diff --git a/data/scripts/commands/ability/dread_spike.lua b/data/scripts/commands/ability/dread_spike.lua index c17ac693..4755a296 100644 --- a/data/scripts/commands/ability/dread_spike.lua +++ b/data/scripts/commands/ability/dread_spike.lua @@ -1,18 +1,23 @@ require("global"); require("ability"); + function onAbilityPrepare(caster, target, ability) return 0; end; +function onAbilityStart(caster, target, ability) + return 0; +end; + function onSkillFinish(caster, target, skill, action, actionContainer) --Need a better way to do this for i = 223212,223217 do - local remAction = caster.statusEffects.RemoveStatusEffectForBattleAction(i, 30329) + local buff = caster.statusEffects.GetStatusEffectById(i); - if remAction ~= nil then - actionContainer.AddAction(remAction); + if buff ~= nil then + caster.statusEffects.RemoveStatusEffect(buff, actionContainer, 30329); skill.statusTier = 2; break; end diff --git a/data/scripts/commands/ability/fists_of_wind.lua b/data/scripts/commands/ability/fists_of_wind.lua new file mode 100644 index 00000000..84ac5ce7 --- /dev/null +++ b/data/scripts/commands/ability/fists_of_wind.lua @@ -0,0 +1,19 @@ +require("global"); +require("ability"); + +function onAbilityPrepare(caster, target, ability) + return 0; +end; + +function onAbilityStart(caster, target, ability) + --27124: Enhanced Fists of Fire + if caster.HasTrait(27124) then + ability.statusTier = 2; + end + return 0; +end; + +function onSkillFinish(caster, target, skill, action, actionContainer) + --DoAction handles rates, buffs, dealing damage + action.DoAction(caster, target, skill, actionContainer); +end; \ No newline at end of file diff --git a/data/scripts/commands/ability/hundred_fists.lua b/data/scripts/commands/ability/hundred_fists.lua index 716534d7..15355468 100644 --- a/data/scripts/commands/ability/hundred_fists.lua +++ b/data/scripts/commands/ability/hundred_fists.lua @@ -12,6 +12,6 @@ end; function onSkillFinish(caster, target, skill, action, actionContainer) --Take off 1/3 of attack delay. Not sure if this is the exact amount HF reduces by - action.statusMagnitude = 0.33 * caster.GetMod(modifiersGlobal.AttackDelay); + skill.statusMagnitude = 0.33 * caster.GetMod(modifiersGlobal.Delay); action.DoAction(caster, target, skill, actionContainer); end; \ No newline at end of file diff --git a/data/scripts/commands/ability/life_surge.lua b/data/scripts/commands/ability/life_surge.lua index 06f165fd..49500d7a 100644 --- a/data/scripts/commands/ability/life_surge.lua +++ b/data/scripts/commands/ability/life_surge.lua @@ -20,9 +20,9 @@ function onSkillFinish(caster, target, skill, action, actionContainer) --223213: Power Surge II --223212: Power Surge III --No message is sent when PS is removed by Life Surge - caster.statusEffects.RemoveStatusEffect(223212, true); - caster.statusEffects.RemoveStatusEffect(223213, true); - caster.statusEffects.RemoveStatusEffect(223214, true); + caster.statusEffects.RemoveStatusEffect(223212); + caster.statusEffects.RemoveStatusEffect(223213); + caster.statusEffects.RemoveStatusEffect(223214); --Using this ability moves to the next LS buff @@ -45,7 +45,6 @@ function onSkillFinish(caster, target, skill, action, actionContainer) end if not (removeId == 0) then - --caster.statusEffects.RemoveStatusEffect(removeId, true); caster.statusEffects.ReplaceEffect(caster.statusEffects.GetStatusEffectById(removeId), skill.statusId, skill.statusTier, skill.statusMagnitude, skill.statusDuration); end --DoAction handles rates, buffs, dealing damage diff --git a/data/scripts/commands/ability/power_surge.lua b/data/scripts/commands/ability/power_surge.lua index 54976f89..f8695889 100644 --- a/data/scripts/commands/ability/power_surge.lua +++ b/data/scripts/commands/ability/power_surge.lua @@ -14,11 +14,17 @@ function onAbilityStart(caster, target, ability) end; function onSkillFinish(caster, target, skill, action, actionContainer) - --Need a better way to do this - actionContainer.AddAction(caster.statusEffects.RemoveStatusEffectForBattleAction(223215)); - actionContainer.AddAction(caster.statusEffects.RemoveStatusEffectForBattleAction(223216)); - actionContainer.AddAction(caster.statusEffects.RemoveStatusEffectForBattleAction(223217)); + caster.statusEffects.RemoveStatusEffect(223215); + caster.statusEffects.RemoveStatusEffect(223216); + caster.statusEffects.RemoveStatusEffect(223217); - --DoAction handles rates, buffs, dealing damage - action.DoAction(caster, target, skill, actionContainer); + --If caster has any of the power surge effects + local buff = caster.statusEffects.GetStatusEffectById(223212) or caster.statusEffects.GetStatusEffectById(223213) or caster.statusEffects.GetStatusEffectById(223214); + + if buff ~= nil then + caster.statusEffects.RemoveStatusEffect(buff, actionContainer, 30329); + else + --DoAction handles rates, buffs, dealing damage + action.DoAction(caster, target, skill, actionContainer); + end end; \ No newline at end of file diff --git a/data/scripts/commands/ability/quelling_strike.lua b/data/scripts/commands/ability/quelling_strike.lua index 35c507a4..f9cff85f 100644 --- a/data/scripts/commands/ability/quelling_strike.lua +++ b/data/scripts/commands/ability/quelling_strike.lua @@ -12,18 +12,21 @@ end; function onSkillFinish(caster, target, skill, action, actionContainer) --QS gives 300 TP by default. skill.statusMagnitude = 300; - --I'm assuming that with raging strikes, that increases to 500. - --and traited that increases again to 750 (or 450 without RS) - if caster.statusEffects.HasStatusEffect(223221) then - actionContainer.AddAction(caster.statusEffects.RemoveStatusEffectForBattleAction(223221)); - skill.statusMagnitude = 500; - end --27241: Enhanced Quelling Strike: Increases TP gained from QS by 50% if caster.HasTrait(27241) then skill.statusMagnitude = skill.statusMagnitude * 1.5; end + --When raging strikes is active, Quelling Strikes removes it and immediately restores 100 TP for each tier ofr Raging Strikes. + local buff = caster.statusEffects.GetStatusEffectById(223221) + + if buff ~= nil then + skill.tpCost = -100 * (buff.GetTier() - 1); + --QS doesn't send a message + caster.statusEffects.RemoveStatusEffect(buff); + end + --DoAction handles rates, buffs, dealing damage action.DoAction(caster, target, skill, actionContainer); end; \ No newline at end of file diff --git a/data/scripts/commands/ability/raging_strike.lua b/data/scripts/commands/ability/raging_strike.lua index 5e265f08..e27a5a42 100644 --- a/data/scripts/commands/ability/raging_strike.lua +++ b/data/scripts/commands/ability/raging_strike.lua @@ -6,14 +6,23 @@ function onAbilityPrepare(caster, target, ability) end; function onAbilityStart(caster, target, ability) + ability.statusMagnitude = 100; --27243: Enhanced Raging Strike: Increases effect of Raging Strike by 50% if caster.HasTrait(27241) then - ability.statusTier = 2; + ability.statusMagnitude = ability.statusMagnitude * 1.5; end return 0; end; function onSkillFinish(caster, target, skill, action, actionContainer) - --DoAction handles rates, buffs, dealing damage - action.DoAction(caster, target, skill, actionContainer); + --If caster has raging strike, remove it and send message, otherwise apply it. + local buff = caster.statusEffects.GetStatusEffectById(223221) + + if buff ~= nil then + --30329: Your Raging Strike removes your Raging Strike effect. + caster.statusEffects.RemoveStatusEffect(buff, actionContainer, 30329); + else + --DoAction handles rates, buffs, dealing damage + action.DoAction(caster, target, skill, actionContainer); + end end; \ No newline at end of file diff --git a/data/scripts/commands/ability/rampage.lua b/data/scripts/commands/ability/rampage.lua index 49c9bd60..7b0307de 100644 --- a/data/scripts/commands/ability/rampage.lua +++ b/data/scripts/commands/ability/rampage.lua @@ -14,6 +14,18 @@ function onAbilityStart(caster, target, ability) end; function onSkillFinish(caster, target, skill, action, actionContainer) - --DoAction handles rates, buffs, dealing damage - action.DoAction(caster, target, skill, actionContainer); + --223207: Berserk + --223208: Rampage + --Remove Berserk effect. I'm assuming no message is sent like LNC surges + caster.statusEffects.RemoveStatusEffect(223207); + + --If caster has rampage already, remove it and send a message. + local buff = caster.statusEffects.GetStatusEffectById(223208) + + if buff ~= nil then + caster.statusEffects.RemoveStatusEffect(buff, actionContainer, 30329); + else + --DoAction handles rates, buffs, dealing damage + action.DoAction(caster, target, skill, actionContainer); + end end; \ No newline at end of file diff --git a/data/scripts/commands/weaponskill/shoulder_tackle.lua b/data/scripts/commands/ability/shoulder_tackle.lua similarity index 83% rename from data/scripts/commands/weaponskill/shoulder_tackle.lua rename to data/scripts/commands/ability/shoulder_tackle.lua index 2fef254a..1f05b3fe 100644 --- a/data/scripts/commands/weaponskill/shoulder_tackle.lua +++ b/data/scripts/commands/ability/shoulder_tackle.lua @@ -1,11 +1,11 @@ require("global"); -require("weaponskill"); +require("ability"); -function onSkillPrepare(caster, target, skill) +function onAbilityPrepare(caster, target, ability) return 0; end; -function onSkillStart(caster, target, skill) +function onAbilityStart(caster, target, ability) return 0; end; diff --git a/data/scripts/commands/ability/tempered_will.lua b/data/scripts/commands/ability/tempered_will.lua index f024acaf..1c0c4bc3 100644 --- a/data/scripts/commands/ability/tempered_will.lua +++ b/data/scripts/commands/ability/tempered_will.lua @@ -12,9 +12,9 @@ end; function onSkillFinish(caster, target, skill, action, actionContainer) --Is this before or after status is gained? --Will probably need to switch to a flag for this because it might include more than just these 3 effects. - actionContainer.AddAction(caster.statusEffects.RemoveStatusEffectForBattleAction(228011)); - actionContainer.AddAction(caster.statusEffects.RemoveStatusEffectForBattleAction(228013)); - actionContainer.AddAction(caster.statusEffects.RemoveStatusEffectForBattleAction(228021)); + caster.statusEffects.RemoveStatusEffect(228011, actionContainer, 30329); + caster.statusEffects.RemoveStatusEffect(228013, actionContainer, 30329); + caster.statusEffects.RemoveStatusEffect(228021, actionContainer, 30329); action.DoAction(caster, target, skill, actionContainer); end; \ No newline at end of file diff --git a/data/scripts/commands/autoattack/default.lua b/data/scripts/commands/autoattack/default.lua new file mode 100644 index 00000000..29ac2f8b --- /dev/null +++ b/data/scripts/commands/autoattack/default.lua @@ -0,0 +1,17 @@ +require("global"); + +function onSkillPrepare(caster, target, skill) + return 0; +end; + +function onSkillStart(caster, target, skill) + return 0; +end; + +function onSkillFinish(caster, target, skill, action, actionContainer) + --calculate ws damage + action.amount = skill.basePotency; + + --DoAction handles rates, buffs, dealing damage + action.DoAction(caster, target, skill, actionContainer); +end; \ No newline at end of file diff --git a/data/scripts/commands/gm/ba.lua b/data/scripts/commands/gm/ba.lua index 43354441..c716b61b 100644 --- a/data/scripts/commands/gm/ba.lua +++ b/data/scripts/commands/gm/ba.lua @@ -2,7 +2,7 @@ require("global"); properties = { permissions = 0, - parameters = "sssss", + parameters = "sss", description = [[ Adds experience to player or . @@ -11,18 +11,19 @@ Adds experience to player or . ]], } -function onTrigger(player, argc, commandId, animationId, textId, effectId, amount) +function onTrigger(player, argc, animType, modelAnim, effectId) local sender = "[battleaction] "; - if player then - cid = tonumber(commandId) or 0; - aid = tonumber(animationId) or 0; - tid = tonumber(textId) or 0; - print(effectId) - eid = tonumber(effectId) or 0; - amt = tonumber(amount) or 0; - - player:DoBattleActionAnimation(cid, aid, tid, eid, amt); + local actor = GetWorldManager():GetActorInWorld(player.currentTarget) or nil; + if player and actor then + aid = tonumber(animType) or 0 + mid = tonumber(modelAnim) or 0 + eid = tonumber(effectId) or 0 + local id = bit32.lshift(aid, 24); + id = bit32.bor(id, bit32.lshift(mid, 12)); + id = bit32.bor(id, eid) + print((tonumber(id))) + player:DoBattleAction(30301, id); else print(sender.."unable to add experience, ensure player name is valid."); end; diff --git a/data/scripts/commands/gm/equipactions.lua b/data/scripts/commands/gm/equipactions.lua new file mode 100644 index 00000000..9d4363d2 --- /dev/null +++ b/data/scripts/commands/gm/equipactions.lua @@ -0,0 +1,42 @@ +require("global"); +require("modifiers"); +properties = { + permissions = 0, + parameters = "s", + description = +[[ +equips all your class and job actions +]], +} + +classToActions = { + [2] = { Start = 27100, End = 27119}, + [3] = { Start = 27140, End = 27159}, + [4] = { Start = 27180, End = 27199}, + [7] = { Start = 27220, End = 27239}, + [8] = { Start = 27260, End = 27279}, + [22] = { Start = 27300, End = 27319}, + [23] = { Start = 27340, End = 27359} +} + +function onTrigger(player, argc) + local messageId = MESSAGE_TYPE_SYSTEM_ERROR; + local sender = "equipactions"; + + classId = player.GetClass() + + if classToActions[classId] then + s = classToActions[classId].Start + e = classToActions[classId].End + print('h') + for i = 0, 30 do + player.UnequipAbility(i, false) + end + + for commandid = s, e do + if GetWorldManager():GetBattleCommand(commandid) then + player:EquipAbilityInFirstOpenSlot(player:GetCurrentClassOrJob(), commandid); + end + end + end +end \ No newline at end of file diff --git a/data/scripts/commands/gm/graphic.lua b/data/scripts/commands/gm/graphic.lua index d2c0e7fe..0c45c317 100644 --- a/data/scripts/commands/gm/graphic.lua +++ b/data/scripts/commands/gm/graphic.lua @@ -20,16 +20,22 @@ function onTrigger(player, argc, slot, wId, eId, vId, cId) vId = tonumber(vId) or 0; cId = tonumber(cId) or 0; - if player and argc > 0 then - if argc > 2 then - player:GraphicChange(slot, wId, eId, vId, cId); - player:SendMessage(messageID, sender, string.format("Changing appearance on slot %u", slot)); + local actor = GetWorldManager():GetActorInWorld(player.currentTarget) or nil; + if player and actor then + if player and argc > 0 then + + -- player.appearanceIds[5] = player.achievementPoints; + if argc > 2 then + actor:GraphicChange(slot, wId, eId, vId, cId); + --player.achievementPoints = player.achievementPoints + 1; + actor:SendMessage(messageID, sender, string.format("Changing appearance on slot %u", slot)); + actor:SendMessage(messageID, sender, string.format("points %u", player.appearanceIds[5])); + else + actor.appearanceIds[slot] = wId; + end + actor:SendAppearance(); else - player:GraphicChange(slot, wId); - end - player:SendAppearance(); - else - player:SendMessage(messageID, sender, "No parameters sent! Usage: "..properties.description); + player:SendMessage(messageID, sender, "No parameters sent! Usage: "..properties.description); + end; end; - end; \ No newline at end of file diff --git a/data/scripts/commands/gm/spawnnpc.lua b/data/scripts/commands/gm/spawnnpc.lua new file mode 100644 index 00000000..bf8870d1 --- /dev/null +++ b/data/scripts/commands/gm/spawnnpc.lua @@ -0,0 +1,135 @@ +require("global"); +require("modifiers"); +properties = { + permissions = 0, + parameters = "sss", + description = +[[ +yolo +]], +} + +local modelIds = +{ + ["titan"] = 2107401, + ["ifrit"] = 2107302, + ["ifrithotair"] = 2207310, + ["nail"] = 2207307, + ["garuda"] = 2209501, + ["garudahelper"] = 2209516, + ["plume"] = 2209502, + ["monolith"] = 2209506, + ["mog"] = 2210408, + ["nael"] = 2210902, + ["meteor"] = 2210903, + ["cactuar"] = 2200905, + ["morbol"] = 2201002, + ["drake"] = 2202209, + ["ogre"] = 2202502, + ["treant"] = 2202801, + ["couerl"] = 2203203, + ["wyvern"] = 2203801, + ["clouddragon"] = 2208101, + ["golem"] = 2208901, + ["atomos"] = 2111002, + ["chimera"] = 2308701, + ["salamander"] = 2201302, + ["ahriman"] = 2201704, + ["rat"] = 9111275, + ["bat"] = 2104113, + ["chigoe"] = 2105613, + ["hedgemole"] = 2105709, + ["gnat"] = 2200604, + ["bird"] = 2201208, + ["puk"] = 2200112, + ["angler"] = 2204507, + ["snurble"] = 2204403, + ["lemur"] = 2200505, + ["doe"] = 2200303, + ["hippogryph"] = 2200405, + ["trap"] = 2202710, + ["goat"] = 2102312, + ["dodo"] = 9111263, + ["imp"] = 2202607, + ["spriggan"] = 2290036, + ["cyclops"] = 2210701, + ["raptor"] = 2200205, + ["wolf"] = 2201429, + ["fungus"] = 2205907, + ["basilisk"] = 2200708, + ["bomb"] = 2201611, + ["jellyfish"] = 2105415, + ["slug"] = 2104205, + ["coblyn"] = 2202103, + ["ghost"] = 2204317, + ["crab"] = 2107613, + ["yarzon"] = 2205520, + ["elemental"] = 2105104, + ["boar"] = 2201505, + ["kobold"] = 2206629, + ["sylph"] = 2206702, + ["ixal"] = 2206434, + ["amaljaa"] = 2206502, + ["qiqirn"] = 2206304, + ["apkallu"] = 2202902, + ["goobbue"] = 2103301, + ["garlean"] = 2207005, + ["flan"] = 2103404, + ["swarm"] = 2105304, + ["goblin"] = 2210301, + ["buffalo"] = 2200802, + ["skeleton"] = 2201902, + ["zombie"] = 2201807, + ["toad"] = 2203107, + ["wisp"] = 2209903, + ["juggernaut"] = 6000243, + ["mammet"] = 6000246, + ["lantern"] = 1200329, + ["helper"] = 2310605, + ["diremite"] = 2101108, + ["gong"] = 1200050, +} + +function onTrigger(player, argc, name, width, height, blockCount) + local messageID = MESSAGE_TYPE_SYSTEM_ERROR; + local sender = "spawnnpc"; + + if player and (modelIds[name] != nil) then + 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]; + local w = tonumber(width) or 0; + + local h = tonumber(height) or 0; + local blocks = tonumber(blockCount) or 0; + for b = 0, blocks do + for i = 0, w do + for j = 0, h do + local actor = player.GetZone().SpawnActor(2104001, 'ass', x + (i * 1), y, z + (j * 1), rot, 0, 0, true); + actor.ChangeNpcAppearance(modelIds[name]); + actor.SetMaxHP(5000); + actor.SetHP(5000); + actor.SetMod(modifiersGlobal.CanBlock, 1); + actor.SetMod(modifiersGlobal.AttackRange, 3); + actor.SetMod(modifiersGlobal.MovementSpeed, 5); + actor.SetMobMod(mobModifiersGlobal.Roams, 1); + actor.SetMobMod(mobModifiersGlobal.RoamDelay, 10); + actor.charaWork.parameterSave.state_mainSkillLevel = 52; + actor.moveState = 3; + end; + end; + + x = x + 500 + end; + return; + elseif player and (modelIds[name] == nil) then + player:SendMessage(messageID, sender, "That name isn't valid"); + else + print("I don't even know how you managed this") + end + + return; +end; \ No newline at end of file diff --git a/data/scripts/commands/gm/vdragon.lua b/data/scripts/commands/gm/vdragon.lua new file mode 100644 index 00000000..52cade43 --- /dev/null +++ b/data/scripts/commands/gm/vdragon.lua @@ -0,0 +1,24 @@ +require("global"); +require("utils"); + +properties = { + permissions = 0, + parameters = "sssss", + description = +[[ +Angle stuff! +!anglestuff +]], +} + +function onTrigger(player, argc) + local sender = "[battleaction] "; + + if player and player.currentTarget then + local actor = GetWorldManager():GetActorInWorld(player.currentTarget) or nil; + actor.Ability(23459, actor.actorId); + + 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 index 724694c7..6977d157 100644 --- a/data/scripts/commands/gm/yolo.lua +++ b/data/scripts/commands/gm/yolo.lua @@ -163,11 +163,12 @@ function onTrigger(player, argc, width, height, blockCount) actor.ChangeNpcAppearance(2200905); actor.SetMaxHP(5000); actor.SetHP(5000); - actor.SetMod(modifiersGlobal.HasShield, 1); + actor.SetMod(modifiersGlobal.CanBlock, 1); actor.SetMod(modifiersGlobal.AttackRange, 3); - actor.SetMod(modifiersGlobal.Speed, 5); + actor.SetMod(modifiersGlobal.MovementSpeed, 5); actor.SetMobMod(mobModifiersGlobal.Roams, 1); - actor.SetMobMod(mobModifiersGlobal.RoamDelay, 3); + actor.SetMobMod(mobModifiersGlobal.RoamDelay, 10); + actor.charaWork.parameterSave.state_mainSkillLevel = 52; actor.moveState = 3; end end diff --git a/data/scripts/commands/magic/aero.lua b/data/scripts/commands/magic/aero.lua index 3deb8462..96f979b4 100644 --- a/data/scripts/commands/magic/aero.lua +++ b/data/scripts/commands/magic/aero.lua @@ -12,7 +12,7 @@ end; function onSkillFinish(caster, target, skill, action, actionContainer) --calculate damage action.amount = skill.basePotency; - action.statusMagnitude = 15; + skill.statusMagnitude = 15; --DoAction handles rates, buffs, dealing damage action.DoAction(caster, target, skill, actionContainer); diff --git a/data/scripts/commands/magic/aerora.lua b/data/scripts/commands/magic/aerora.lua index d8e01c53..e07bcfd1 100644 --- a/data/scripts/commands/magic/aerora.lua +++ b/data/scripts/commands/magic/aerora.lua @@ -12,22 +12,16 @@ end; --Increased damage and conversion to single target function onCombo(caster, target, spell) spell.aoeType = 0; - spell.potency = spell.potency * 1.5; + spell.basePotency = spell.basePotency * 1.5; end; function onSkillFinish(caster, target, skill, action, actionContainer) - --Dispels an effect on each target. - local effects = target.statusEffects.GetStatusEffectsByFlag2(16); --lose on dispel - if effects != nil then - target.statusEffects.RemoveStatusEffect(effects[0]); - end; - --calculate damage action.amount = skill.basePotency; --DoAction handles rates, buffs, dealing damage action.DoAction(caster, target, skill, actionContainer); - --Try to apply status effect - action.TryStatus(caster, target, skill, actionContainer, true); + --Dispels an effect on each target. + target.statusEffects.RemoveStatusEffect(GetRandomEffectByFlag(8), actionContainer, 30336); end; \ No newline at end of file diff --git a/data/scripts/commands/magic/cura.lua b/data/scripts/commands/magic/cura.lua index 6713dadc..c07686a4 100644 --- a/data/scripts/commands/magic/cura.lua +++ b/data/scripts/commands/magic/cura.lua @@ -1,5 +1,6 @@ require("global"); require("magic"); +require("modifiers"); function onMagicPrepare(caster, target, spell) return 0; @@ -14,7 +15,7 @@ function onSkillFinish(caster, target, skill, action, actionContainer) --2.5 HP per Healing Magic Potency --0.5 HP per MND --this is WITH WHM AF chest, don't know formula without AF. AF seems to increase healing by 7-10%? - action.amount = 2.5 * caster.GetMod(modifiersGlobal.MagicHeal) + 0.5 * (caster.GetMod(modifiersGlobal.Mind)); + action.amount = 2.5 * caster.GetMod(modifiersGlobal.HealingMagicPotency) + 0.5 * (caster.GetMod(modifiersGlobal.Mind)); --DoAction handles rates, buffs, dealing damage action.DoAction(caster, target, skill, actionContainer); diff --git a/data/scripts/commands/magic/cure.lua b/data/scripts/commands/magic/cure.lua index cafa30a2..78b86ff6 100644 --- a/data/scripts/commands/magic/cure.lua +++ b/data/scripts/commands/magic/cure.lua @@ -30,7 +30,7 @@ function onSkillFinish(caster, target, skill, action, actionContainer) hpPerMND = 0.25; end - action.amount = hpPerHMP * caster.GetMod(modifiersGlobal.MagicHeal) + hpPerMND * (caster.GetMod(modifiersGlobal.Mind)); + action.amount = hpPerHMP * caster.GetMod(modifiersGlobal.HealingMagicPotency) + hpPerMND * (caster.GetMod(modifiersGlobal.Mind)); --DoAction handles rates, buffs, dealing damage action.DoAction(caster, target, skill, actionContainer); diff --git a/data/scripts/commands/magic/esuna.lua b/data/scripts/commands/magic/esuna.lua new file mode 100644 index 00000000..2e58b6ce --- /dev/null +++ b/data/scripts/commands/magic/esuna.lua @@ -0,0 +1,22 @@ +require("global"); +require("magic"); +require("battleutils"); + +function onMagicPrepare(caster, target, spell) + if not target.statusEffects.HasStatusEffectsByFlag(StatusEffectFlags.LoseOnEsuna) then + return -1 + end + + return 0; +end; + +function onMagicStart(caster, target, spell) + return 0; +end; + +function onSkillFinish(caster, target, skill, action, actionContainer) + + removeEffect = target.statusEffects.GetRandomEffectByFlag(StatusEffectFlags.LoseOnEsuna) + + target.statusEffects.RemoveStatusEffect(removeEffect, actionContainer, 30331); +end; \ No newline at end of file diff --git a/data/scripts/commands/magic/fire.lua b/data/scripts/commands/magic/fire.lua index cb88bda7..ad185e22 100644 --- a/data/scripts/commands/magic/fire.lua +++ b/data/scripts/commands/magic/fire.lua @@ -11,7 +11,7 @@ end; function onSkillFinish(caster, target, skill, action, actionContainer) --calculate damage - action.amount = skill.basePotency; + action.amount = 5000;-- skill.basePotency; --DoAction handles rates, buffs, dealing damage action.DoAction(caster, target, skill, actionContainer); diff --git a/data/scripts/commands/magic/flare.lua b/data/scripts/commands/magic/flare.lua index 6fbe1c9b..fd75684f 100644 --- a/data/scripts/commands/magic/flare.lua +++ b/data/scripts/commands/magic/flare.lua @@ -12,6 +12,7 @@ end; function onSkillFinish(caster, target, skill, action, actionContainer) --calculate damage action.amount = skill.basePotency; + skill.statusMagnitude = 20; --DoAction handles rates, buffs, dealing damage action.DoAction(caster, target, skill, actionContainer); diff --git a/data/scripts/commands/magic/holy_succor.lua b/data/scripts/commands/magic/holy_succor.lua index 4ce6c182..b10a7c56 100644 --- a/data/scripts/commands/magic/holy_succor.lua +++ b/data/scripts/commands/magic/holy_succor.lua @@ -24,6 +24,6 @@ function onSkillFinish(caster, target, skill, action, actionContainer) if caster != target then caster.AddHP(action.amount / 2) --33012: You recover [amount] HP. - actionContainer.AddHPAction(caster.actorId, 33012, (action.amount / 2)); + actionContainer.AddHPAbsorbAction(caster.actorId, 33012, (action.amount / 2)); end end; \ No newline at end of file diff --git a/data/scripts/commands/magic/protect.lua b/data/scripts/commands/magic/protect.lua index 454e030a..f00ffa35 100644 --- a/data/scripts/commands/magic/protect.lua +++ b/data/scripts/commands/magic/protect.lua @@ -12,7 +12,7 @@ end; function onSkillFinish(caster, target, skill, action, actionContainer) --Actual amount of def/mdef will be calculated in OnGain - skill.statusMagnitude = caster.GetMod(modifiersGlobal.MagicEnhancePotency); + skill.statusMagnitude = caster.GetMod(modifiersGlobal.EnhancementMagicPotency); --27365: Enhanced Protect: Increases magic defense gained from Protect. if caster.HasTrait(27365) then diff --git a/data/scripts/commands/magic/raise.lua b/data/scripts/commands/magic/raise.lua index ea794ea8..1ca7913f 100644 --- a/data/scripts/commands/magic/raise.lua +++ b/data/scripts/commands/magic/raise.lua @@ -15,4 +15,5 @@ end; --Not sure how raise works yet. function onSkillFinish(caster, target, skill, action, actionContainer) + action.DoAction(caster, target, skill, actionContainer) end; \ No newline at end of file diff --git a/data/scripts/commands/magic/regen.lua b/data/scripts/commands/magic/regen.lua index db4bc502..66159400 100644 --- a/data/scripts/commands/magic/regen.lua +++ b/data/scripts/commands/magic/regen.lua @@ -25,7 +25,7 @@ function onSkillFinish(caster, target, skill, action, actionContainer) intercept = intercept * 1.25; end - local regenTick = (slope * caster.GetMod(modifiersGlobal.MagicEnhancePotency)) + intercept) + 1; + local regenTick = (slope * caster.GetMod(modifiersGlobal.EnhancementMagicPotency)) + intercept + 1; spell.statusMagnitude = regenTick; diff --git a/data/scripts/commands/magic/stone.lua b/data/scripts/commands/magic/stone.lua index 728384d3..99bf6ec0 100644 --- a/data/scripts/commands/magic/stone.lua +++ b/data/scripts/commands/magic/stone.lua @@ -12,7 +12,7 @@ end; function onSkillFinish(caster, target, skill, action, actionContainer) --calculate damage action.amount = skill.basePotency; - action.statusMagnitude = 50; + skill.statusMagnitude = 50; --DoAction handles rates, buffs, dealing damage action.DoAction(caster, target, skill, actionContainer); diff --git a/data/scripts/commands/magic/stoneskin.lua b/data/scripts/commands/magic/stoneskin.lua index c49b190a..6a3c6010 100644 --- a/data/scripts/commands/magic/stoneskin.lua +++ b/data/scripts/commands/magic/stoneskin.lua @@ -1,5 +1,6 @@ require("global"); require("magic"); +require("modifiers") function onMagicPrepare(caster, target, spell) return 0; @@ -19,7 +20,7 @@ function onSkillFinish(caster, target, skill, action, actionContainer) hpPerPoint = 1.96; end - spell.statusMagnitude = hpPerPoint * caster.GetMod(modifiersGlobal.MagicEnhancePotency); + skill.statusMagnitude = hpPerPoint * caster.GetMod(modifiersGlobal.EnhancementMagicPotency); --DoAction handles rates, buffs, dealing damage action.DoAction(caster, target, skill, actionContainer); diff --git a/data/scripts/commands/magic/swiftsong.lua b/data/scripts/commands/magic/swiftsong.lua new file mode 100644 index 00000000..5ca9cd04 --- /dev/null +++ b/data/scripts/commands/magic/swiftsong.lua @@ -0,0 +1,35 @@ +require("global"); +require("magic"); + +function onMagicPrepare(caster, target, skill) + return 0; +end; + +function onMagicStart(caster, target, skill) + return 0; +end; + +function onSkillFinish(caster, target, skill, action, actionContainer) + --223224: Swiftsong + --223254: Ballad Of Magi + --223256: Minuet of Rigor + --If target has one of these effects that was from this caster, remove it + local oldSong; + local paeon = target.statusEffects.GetStatusEffectById(223255); + local ballad = target.statusEffects.GetStatusEffectById(223254); + local minuet = target.statusEffects.GetStatusEffectById(223256); + if paeon and paeon.GetSource() == caster then + oldSong = paeon; + elseif ballad and ballad.GetSource() == caster then + oldSong = ballad; + elseif minuet and minuet.GetSource() == caster then + oldSong = minuet; + end + + if oldSong then + target.statusEffects.RemoveStatusEffect(oldSong); + end + + --DoAction handles rates, buffs, dealing damage + action.DoAction(caster, target, skill, actionContainer); +end; \ No newline at end of file diff --git a/data/scripts/commands/weaponskill/breath_of_the_dragon.lua b/data/scripts/commands/weaponskill/breath_of_the_dragon.lua new file mode 100644 index 00000000..85f185b6 --- /dev/null +++ b/data/scripts/commands/weaponskill/breath_of_the_dragon.lua @@ -0,0 +1,17 @@ +require("global"); +require("ability"); + +function onAbilityPrepare(caster, target, ability) + return 0; +end; + +function onAbilityStart(caster, target, ability) + return 0; +end; + +function onSkillFinish(caster, target, skill, action, actionContainer) + action.amount = skill.basePotency; + + --DoAction handles rates, buffs, dealing damage + action.DoAction(caster, target, skill, actionContainer); +end; \ No newline at end of file diff --git a/data/scripts/commands/weaponskill/breath_of_the_ram.lua b/data/scripts/commands/weaponskill/breath_of_the_ram.lua new file mode 100644 index 00000000..85f185b6 --- /dev/null +++ b/data/scripts/commands/weaponskill/breath_of_the_ram.lua @@ -0,0 +1,17 @@ +require("global"); +require("ability"); + +function onAbilityPrepare(caster, target, ability) + return 0; +end; + +function onAbilityStart(caster, target, ability) + return 0; +end; + +function onSkillFinish(caster, target, skill, action, actionContainer) + action.amount = skill.basePotency; + + --DoAction handles rates, buffs, dealing damage + action.DoAction(caster, target, skill, actionContainer); +end; \ No newline at end of file diff --git a/data/scripts/commands/weaponskill/demolish.lua b/data/scripts/commands/weaponskill/demolish.lua index 733e9e4d..3bdd6712 100644 --- a/data/scripts/commands/weaponskill/demolish.lua +++ b/data/scripts/commands/weaponskill/demolish.lua @@ -12,10 +12,7 @@ end; --Dispel --Does dispel have a text id? function onCombo(caster, target, skill) - local effects = target.statusEffects.GetStatusEffectsByFlag(16); --lose on dispel - if effects != nil then - target.statusEffects.RemoveStatusEffect(effects[0]); - end; + return 0; end; function onSkillFinish(caster, target, skill, action, actionContainer) @@ -25,6 +22,7 @@ function onSkillFinish(caster, target, skill, action, actionContainer) --DoAction handles rates, buffs, dealing damage action.DoAction(caster, target, skill, actionContainer); - --Try to apply status effect - action.TryStatus(caster, target, skill, actionContainer, true); + if skill.isCombo then + target.statusEffects.RemoveStatusEffect(GetRandomEffectByFlag(8), actionContainer, 30336); + end 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 index e40f0057..09f8b0d6 100644 --- a/data/scripts/commands/weaponskill/doom_spike.lua +++ b/data/scripts/commands/weaponskill/doom_spike.lua @@ -1,5 +1,6 @@ require("global"); require("weaponskill"); +require("utils"); function onSkillPrepare(caster, target, skill) return 0; @@ -16,7 +17,7 @@ end; function onSkillFinish(caster, target, skill, action, actionContainer) --calculate ws damage - action.amount = skill.basePotency; + action.amount = 5000;--skill.basePotency; --DoAction handles rates, buffs, dealing damage action.DoAction(caster, target, skill, actionContainer); diff --git a/data/scripts/commands/weaponskill/dragon_kick.lua b/data/scripts/commands/weaponskill/dragon_kick.lua index 115ab485..3e4fcb29 100644 --- a/data/scripts/commands/weaponskill/dragon_kick.lua +++ b/data/scripts/commands/weaponskill/dragon_kick.lua @@ -21,6 +21,9 @@ function onSkillFinish(caster, target, skill, action, actionContainer) --DoAction handles rates, buffs, dealing damage action.DoAction(caster, target, skill, actionContainer); - --Try to apply status effect - action.TryStatus(caster, target, skill, actionContainer, true); + --Status only seems to apply on the first hit + if(action.ActionLanded() and action.hitNum == 1) then + --Try to apply status effect + action.TryStatus(caster, target, skill, actionContainer, true); + end end; \ No newline at end of file diff --git a/data/scripts/commands/weaponskill/godsbane.lua b/data/scripts/commands/weaponskill/godsbane.lua index d47129ac..8a8a3673 100644 --- a/data/scripts/commands/weaponskill/godsbane.lua +++ b/data/scripts/commands/weaponskill/godsbane.lua @@ -1,20 +1,16 @@ require("global"); require("weaponskill"); +require("modifiers") function onSkillPrepare(caster, target, skill) return 0; end; function onSkillStart(caster, target, skill) - return 0; -end; - ---Increased crit rate -function onCombo(caster, target, skill) --Get Berserk statuseffect local berserk = caster.statusEffects.GetStatusEffectById(223160); - --if it isn't nil, remove the AP and Defense mods and reset extra to 0, increase potency + --if it isn't nil, remove the AP and Defense mods and reset extra to 0, increase accuracy if berserk != nil then local apPerHit = 20; local defPerHit = 20; @@ -23,14 +19,20 @@ function onCombo(caster, target, skill) apPerHit = 24; end - attacker.SubtractMod(modifiersGlobal.Attack, apPerHit * berserk.GetExtra()); - attacker.Add(modifiersGlobal.Defense, defPerHit * berserk.GetExtra()); + caster.SubtractMod(modifiersGlobal.Attack, apPerHit * berserk.GetExtra()); + caster.Add(modifiersGlobal.Defense, defPerHit * berserk.GetExtra()); berserk.SetExtra(0); - - --This is about 50% crit. Don't know if that's what it gave on retail but seems kind of reasonable - skill.critRateBonus = 300; + skill.accuracyModifier = 50; end; + + return 0; +end; + +--Increased crit rate +function onCombo(caster, target, skill) + --This is about 25% crit. Don't know if that's what it gave on retail but seems kind of reasonable + skill.critRateBonus = 200; end; function onSkillFinish(caster, target, skill, action, actionContainer) diff --git a/data/scripts/commands/weaponskill/maim.lua b/data/scripts/commands/weaponskill/maim.lua index 861e4315..5901282d 100644 --- a/data/scripts/commands/weaponskill/maim.lua +++ b/data/scripts/commands/weaponskill/maim.lua @@ -15,7 +15,7 @@ end; function onSkillFinish(caster, target, skill, action, actionContainer) --calculate ws damage - skill.Potency = 100; + skill.basePotency = 100; --DoAction handles rates, buffs, dealing damage action.DoAction(caster, target, skill, actionContainer); diff --git a/data/scripts/commands/weaponskill/steel_cyclone.lua b/data/scripts/commands/weaponskill/steel_cyclone.lua index 4f1314cd..579f7df0 100644 --- a/data/scripts/commands/weaponskill/steel_cyclone.lua +++ b/data/scripts/commands/weaponskill/steel_cyclone.lua @@ -1,11 +1,27 @@ require("global"); require("weaponskill"); +require("modifiers") function onSkillPrepare(caster, target, skill) return 0; end; +--Resets rampage to increase damage function onSkillStart(caster, target, skill) + --Get Rampage statuseffect + local rampage = caster.statusEffects.GetStatusEffectById(223208); + + --if it isn't nil, remove the AP and Defense mods and reset extra to 0, increase potency + if rampage != nil then + local parryPerDT = 20; + local delayMsPerDT = 100; + + caster.SubtractMod(modifiersGlobal.Parry, parryPerDT * rampage.GetExtra()); + caster.AddMod(modifiersGlobal.Delay, delayMsPerDT * rampage.GetExtra()); + + rampage.SetExtra(0); + skill.basePotency = skill.basePotency * 1.5; + end; return 0; end; @@ -15,6 +31,10 @@ function onCombo(caster, target, skill) end; function onSkillFinish(caster, target, skill, action, actionContainer) + if target.target == caster then + skill.statusId = 223015 + end; + --calculate ws damage action.amount = skill.basePotency; @@ -23,4 +43,6 @@ function onSkillFinish(caster, target, skill, action, actionContainer) --Try to apply status effect action.TryStatus(caster, target, skill, actionContainer, true); + + skill.statusId = 0; end; \ No newline at end of file diff --git a/data/scripts/commands/weaponskill/sucker_punch.lua b/data/scripts/commands/weaponskill/sucker_punch.lua index 5f188546..b408a139 100644 --- a/data/scripts/commands/weaponskill/sucker_punch.lua +++ b/data/scripts/commands/weaponskill/sucker_punch.lua @@ -28,7 +28,7 @@ function onSkillFinish(caster, target, skill, action, actionContainer) --1.21: Equation used to calculate amount of MP adjusted. --fug --This might mean max MP isn't involved and the difference was between patches. need to recheck videos - if action.GetHitType() > HitType.Evade and (action.param == HitDirection.Right or action.param == HitDirection.Left) then + if action.ActionLanded() and (action.param == HitDirection.Right or action.param == HitDirection.Left) then local mpToReturn = 0; if skill.isCombo then @@ -39,6 +39,6 @@ function onSkillFinish(caster, target, skill, action, actionContainer) caster.AddMP(mpToReturn); --30452: You recover x MP. - actionContainer.AddMPAction(caster.actorId, 30452, mpToReturn); + actionContainer.AddMPAbsorbAction(caster.actorId, 30452, mpToReturn); end end; \ No newline at end of file diff --git a/data/scripts/commands/weaponskill/voice_of_the_dragon.lua b/data/scripts/commands/weaponskill/voice_of_the_dragon.lua new file mode 100644 index 00000000..85f185b6 --- /dev/null +++ b/data/scripts/commands/weaponskill/voice_of_the_dragon.lua @@ -0,0 +1,17 @@ +require("global"); +require("ability"); + +function onAbilityPrepare(caster, target, ability) + return 0; +end; + +function onAbilityStart(caster, target, ability) + return 0; +end; + +function onSkillFinish(caster, target, skill, action, actionContainer) + action.amount = skill.basePotency; + + --DoAction handles rates, buffs, dealing damage + action.DoAction(caster, target, skill, actionContainer); +end; \ No newline at end of file diff --git a/data/scripts/commands/weaponskill/whirlwind.lua b/data/scripts/commands/weaponskill/whirlwind.lua index 26b7a7e1..3a78263f 100644 --- a/data/scripts/commands/weaponskill/whirlwind.lua +++ b/data/scripts/commands/weaponskill/whirlwind.lua @@ -1,5 +1,6 @@ require("global"); require("weaponskill"); +require("modifiers") function onSkillPrepare(caster, target, skill) return 0; @@ -23,8 +24,8 @@ function onCombo(caster, target, skill) apPerHit = 24; end - attacker.SubtractMod(modifiersGlobal.Attack, apPerHit * berserk.GetExtra()); - attacker.Add(modifiersGlobal.Defense, defPerHit * berserk.GetExtra()); + caster.SubtractMod(modifiersGlobal.Attack, apPerHit * berserk.GetExtra()); + caster.Add(modifiersGlobal.Defense, defPerHit * berserk.GetExtra()); berserk.SetExtra(0); skill.basePotency = skill.basePotency * 1.5; diff --git a/data/scripts/effects/aegis_boon.lua b/data/scripts/effects/aegis_boon.lua index 2f909fd1..72286396 100644 --- a/data/scripts/effects/aegis_boon.lua +++ b/data/scripts/effects/aegis_boon.lua @@ -3,17 +3,17 @@ require("utils") --Forces a full block (0 damage taken) function onPreAction(effect, caster, target, skill, action, actionContainer) - --If action hit from the rear and is a weaponskill ation + --Can aegis boon block rear attacks or non-physical attacks? action.blockRate = 100.0; end; --Heals for the amount of HP blocked, up to a certain point. I don't know what determines the cap but it seems to be 703 at level 50. Unsure if it scales down based on level, dlvl, or if that's an arbitrary cap added. -function onBlock(effect, attacker, defender, action, actionContainer) +function onBlock(effect, attacker, defender, skill, action, actionContainer) --Amount blocked local absorbAmount = math.Clamp(action.amountMitigated, 0, 703); --33008: You recover x HP from Aegis Boon defender.AddHP(absorbAmount); actionContainer.AddHPAction(defender.actorId, 33008, absorbAmount); - actionContainer.AddAction(defender.statusEffects.RemoveStatusEffectForBattleAction(effect)); + defender.statusEffects.RemoveStatusEffect(effect, actionContainer); end; \ No newline at end of file diff --git a/data/scripts/effects/aero.lua b/data/scripts/effects/aero.lua index 53a413c4..5e647f12 100644 --- a/data/scripts/effects/aero.lua +++ b/data/scripts/effects/aero.lua @@ -1,10 +1,10 @@ require("modifiers") --Doesn't do flat damage. 20 on Lv 50 Truffle Hog, 11 on Coincounter, 7 on nael hard, 19 on 52 fachan -function onGain(owner, effect) +function onGain(owner, effect, actionContainer) owner.AddMod(modifiersGlobal.RegenDown, effect.GetMagnitude()); end; -function onLose(owner, effect) +function onLose(owner, effect, actionContainer) owner.AddMod(modifiersGlobal.RegenDown, effect.GetMagnitude()); end; \ No newline at end of file diff --git a/data/scripts/effects/ballad_of_magi.lua b/data/scripts/effects/ballad_of_magi.lua index e64f5751..9df99bf5 100644 --- a/data/scripts/effects/ballad_of_magi.lua +++ b/data/scripts/effects/ballad_of_magi.lua @@ -1,10 +1,10 @@ require("modifiers") -function onGain(owner, effect) +function onGain(owner, effect, actionContainer) --Only one song per bard can be active, need to figure out a good way to do this owner.AddMod(modifiersGlobal.Refresh, effect.GetMagnitude()); end; -function onLose(owner, effect) +function onLose(owner, effect, actionContainer) owner.SubtractMod(modifiersGlobal.Refresh, effect.GetMagnitude()); end; \ No newline at end of file diff --git a/data/scripts/effects/barrage.lua b/data/scripts/effects/barrage.lua index 59c097da..3ef7300a 100644 --- a/data/scripts/effects/barrage.lua +++ b/data/scripts/effects/barrage.lua @@ -8,6 +8,6 @@ end; function onCommandFinish(effect, owner, skill, actionContainer) --27259: Light Shot if skill.id == 27259 then - actionContainer.AddAction(owner.statusEffects.RemoveStatusEffectForBattleAction(effect)); + owner.statusEffects.RemoveStatusEffect(effect, actionContainer, 30331, false); end end; \ No newline at end of file diff --git a/data/scripts/effects/battle_voice.lua b/data/scripts/effects/battle_voice.lua index 4cbc19ff..8c2f1e56 100644 --- a/data/scripts/effects/battle_voice.lua +++ b/data/scripts/effects/battle_voice.lua @@ -1,3 +1,8 @@ require("modifiers") ---BV doesn't really do anything i think \ No newline at end of file +--BV doesn't really do anything i think +function onGain(owner, effect, actionContainer) +end; + +function onLose(owner, effect, actionContainer) +end; \ No newline at end of file diff --git a/data/scripts/effects/berserk2.lua b/data/scripts/effects/berserk2.lua index 0a7d37ec..0481c1de 100644 --- a/data/scripts/effects/berserk2.lua +++ b/data/scripts/effects/berserk2.lua @@ -1,13 +1,12 @@ require("modifiers"); -function onGain(owner, effect) - owner.statusEffects.RemoveStatusEffect(223208); +function onGain(owner, effect, actionContainer) end --Increases attack power and reduces defense with each successful attack --Does this include weaponskills? --Is this on every hit or every succesfull skill useage? -function onHit(effect, attacker, defender, action, actionContainer) +function onHit(effect, attacker, defender, skill, action, actionContainer) --Trait increases effect by 20%. Does this include the reduced defense, --does this increase the cap or the rate at which you get AP or both? @@ -32,7 +31,7 @@ function onHit(effect, attacker, defender, action, actionContainer) end end; -function onDamageTaken(effect, attacker, defender, action, actionContainer) +function onDamageTaken(effect, attacker, defender, skill, action, actionContainer) local apPerHit = 20; local defPerHit = 20; @@ -45,7 +44,7 @@ function onDamageTaken(effect, attacker, defender, action, actionContainer) effect.SetExtra(0); end -function onLose(owner, effect) +function onLose(owner, effect, actionContainer) local apPerHit = 20; local defPerHit = 20; diff --git a/data/scripts/effects/bind.lua b/data/scripts/effects/bind.lua index 2ef3b0f4..c57b0582 100644 --- a/data/scripts/effects/bind.lua +++ b/data/scripts/effects/bind.lua @@ -1,7 +1,7 @@ require("modifiers"); -function onGain(target, effect) +function onGain(owner, effect, actionContainer) end; -function onLose(target, effect) +function onLose(owner, effect, actionContainer) end; \ No newline at end of file diff --git a/data/scripts/effects/blind.lua b/data/scripts/effects/blind.lua index 59e06fbd..2dec4f7d 100644 --- a/data/scripts/effects/blind.lua +++ b/data/scripts/effects/blind.lua @@ -1,9 +1,9 @@ require("modifiers") -function onGain(owner, effect) +function onGain(owner, effect, actionContainer) owner.SubtractMod(modifiersGlobal.Accuracy, effect.GetMagnitude()); end; -function onLose(owner, effect) +function onLose(owner, effect, actionContainer) owner.AddMod(modifiersGlobal.Accuracy, effect.GetMagnitude()); end; \ No newline at end of file diff --git a/data/scripts/effects/blindside.lua b/data/scripts/effects/blindside.lua index 27590af4..0e0e30d5 100644 --- a/data/scripts/effects/blindside.lua +++ b/data/scripts/effects/blindside.lua @@ -4,12 +4,12 @@ require("battleutils") --Forces crit of a single WS action from rear. function onPreAction(effect, caster, target, skill, action, actionContainer) --If action hit from the rear and is a weaponskill ation - if (action.param == HitDirection.Rear and action.commandType == CommandType.WeaponSkill) then + if (action.param == HitDirection.Rear and skill.GetCommandType() == CommandType.WeaponSkill) then --Set action's crit rate to 100% action.critRate = 100.0; end --Remove status and add message - actionsList.AddAction(target.statusEffects.RemoveForBattleAction(effect)); + target.statusEffects.RemoveStatusEffect(effect, actionContainer); end; diff --git a/data/scripts/effects/blindside2.lua b/data/scripts/effects/blindside2.lua new file mode 100644 index 00000000..6b5c3452 --- /dev/null +++ b/data/scripts/effects/blindside2.lua @@ -0,0 +1,17 @@ +require("modifiers") +require("battleutils") + +--Forces crit of a single WS action from rear. +function onPreAction(effect, caster, target, skill, action, actionContainer) + --If action hit from the rear and is a weaponskill ation + if (action.param == HitDirection.Rear and skill.GetCommandType() == CommandType.WeaponSkill) then + --Set action's crit rate to 100% + action.critRate = 100.0; + end + + --Figure out INT bonus for tier 2 + + --Remove status and add message + target.statusEffects.RemoveStatusEffect(effect, actionContainer); +end; + diff --git a/data/scripts/effects/blissful_mind.lua b/data/scripts/effects/blissful_mind.lua index 1c12cfff..9ff217e1 100644 --- a/data/scripts/effects/blissful_mind.lua +++ b/data/scripts/effects/blissful_mind.lua @@ -2,15 +2,13 @@ --Based on a few videos it seems like it heals for 0.5% of max MP every second, traited. This is an early guess but it seems correct --Untraited is less clear. It could be 0.25%, 0.30%, or 0.40%. Guessing it's 0.30 -function onTick(owner, effect) +function onTick(owner, effect, actionContainer) local percentPerSecond = 0.0030; if effect.GetTier() == 2 then percentPerSecond = 0.005; end - print(effect.GetExtra()); - local amount = percentPerSecond * owner.GetMaxMP() + 0.25; effect.SetExtra(effect.GetExtra() + amount); if effect.GetExtra() >= effect.GetMagnitude() then diff --git a/data/scripts/effects/block_proc.lua b/data/scripts/effects/block_proc.lua index 1f6d7161..eb71402a 100644 --- a/data/scripts/effects/block_proc.lua +++ b/data/scripts/effects/block_proc.lua @@ -1,3 +1,3 @@ -function onLose(target, effect) - target:SetProc(1, false); +function onLose(owner, effect, actionContainer) + owner:SetProc(1, false); end; \ No newline at end of file diff --git a/data/scripts/effects/blood_for_blood.lua b/data/scripts/effects/blood_for_blood.lua index b63c88bd..d1fa7d55 100644 --- a/data/scripts/effects/blood_for_blood.lua +++ b/data/scripts/effects/blood_for_blood.lua @@ -3,7 +3,7 @@ require("battleUtils") --Takes 10% of hp rounded down when using a weaponskill --Random guess, but increases damage by 10% (12.5% traited)? function onPreAction(effect, caster, target, skill, action, actionContainer) - if skill.commandType == CommandType.Weaponskill then + if skill.GetCommandType() == CommandType.Weaponskill then local hpToRemove = math.floor(caster.GetHP() * 0.10); local modifier = 1.10; @@ -12,9 +12,9 @@ function onPreAction(effect, caster, target, skill, action, actionContainer) end action.amount = action.amount * modifier; - caster.DelHP(hpToRemove); + caster.DelHP(hpToRemove, actionContainer); - --Remove status and add message - actionContainer.AddAction(target.statusEffects.RemoveForBattleAction(effect)); + --Remove status and add message + caster.statusEffects.RemoveStatusEffect(effect, actionContainer, 30331, true); end end; \ No newline at end of file diff --git a/data/scripts/effects/bloodbath.lua b/data/scripts/effects/bloodbath.lua index b74d099e..cd6775d6 100644 --- a/data/scripts/effects/bloodbath.lua +++ b/data/scripts/effects/bloodbath.lua @@ -1,7 +1,8 @@ require("modifiers"); +require("battleutils") --Absorb HP on next WS or ability -function onHit(effect, attacker, defender, action, actionContainer) +function onHit(effect, attacker, defender, skill, action, actionContainer) --1.21: Absorb HP amount no longer affected by player VIT rating. --Bloodbath seems based on both defener and attacker's stats, even after 1.21. @@ -11,14 +12,14 @@ function onHit(effect, attacker, defender, action, actionContainer) --Possibly magic resist? Slashing resist? --For now using 1.0 as baseline since that seems to be the average - if action.commandType == CommandType.Weaponskill or action.commandType == CommandType.Ability then + if skill.GetCommandType() == CommandType.Weaponskill or skill.GetCommandType() == CommandType.Ability then local absorbModifier = 1.0 local absorbAmount = action.amount * absorbModifier; attacker.AddHP(absorbAmount); --30332: You absorb hp from target - actionContainer.AddHPAction(defender.actorId, 30332, absorbAmount) + actionContainer.AddHPAbsorbAction(defender.actorId, 30332, absorbAmount) --Bloodbath is lost after absorbing hp - actionContainer.AddAction(defender.statusEffects.RemoveStatusEffectForBattleAction(effect)); + defender.statusEffects.RemoveStatusEffect(effect,actionContainer, 30331, false); end end; \ No newline at end of file diff --git a/data/scripts/effects/bloodletter.lua b/data/scripts/effects/bloodletter.lua index 2a4b0129..5a0401e3 100644 --- a/data/scripts/effects/bloodletter.lua +++ b/data/scripts/effects/bloodletter.lua @@ -8,13 +8,14 @@ require("modifiers") --Bloodletter is apparently impacted by PIE --http://forum.square-enix.com/ffxiv/threads/35795-STR-DEX-PIE-ATK-Testing/page2 --Chance to land is also impacted by PIE -function onGain(owner, effect) +--This is because PIE increases Enfeebling Magic Potency which impacts additional effect damage and land rates +function onGain(owner, effect, actionContainer) owner.AddMod(modifiersGlobal.RegenDown, 15); end --Additional damage is 570 at level 50 --https://ffxiv.gamerescape.com/w/index.php?title=Bloodletter&oldid=298020 -function onLose(owner, effect) +function onLose(owner, effect, actionContainer) owner.SubtractMod(modifiersGlobal.RegenDown, 15); - owner.DelHP(570); + owner.DelHP(570, actionContainer); end diff --git a/data/scripts/effects/bloodletter2.lua b/data/scripts/effects/bloodletter2.lua index 01449669..70c48e7a 100644 --- a/data/scripts/effects/bloodletter2.lua +++ b/data/scripts/effects/bloodletter2.lua @@ -1,10 +1,10 @@ require("modifiers") --Bloodletter2 is the uncomboed version of Bloodletter. It doesn't deal any additional damage when it falls off but has the same tick damage -function onGain(owner, effect) +function onGain(owner, effect, actionContainer) owner.AddMod(modifiersGlobal.RegenDown, 15); end -function onLose(owner, effect) +function onLose(owner, effect, actionContainer) owner.SubtractMod(modifiersGlobal.RegenDown, 15); end diff --git a/data/scripts/effects/cleric_stance.lua b/data/scripts/effects/cleric_stance.lua index 2bb252d8..6617758f 100644 --- a/data/scripts/effects/cleric_stance.lua +++ b/data/scripts/effects/cleric_stance.lua @@ -1,12 +1,12 @@ require("modifiers") -function onGain(target, effect) +function onGain(owner, effect, actionContainer) --Multiples Attack Magic Potency by 1.2 and Healing Magic Potency by 0.8 - target.SetMod(modifiersGlobal.MagicAttack, target.GetMod(modifiersGlobal.MagicAttack) * 1.2); - target.SetMod(modifiersGlobal.MagicHeal, target.GetMod(modifiersGlobal.MagicHeal) * 0.8); + owner.MultiplyMod(modifiersGlobal.AttackMagicPotency, 1.2); + owner.MultiplyMod(modifiersGlobal.HealingMagicPotency, 0.8); end; -function onLose(target, effect) - target.SetMod(modifiersGlobal.MagicAttack, target.GetMod(modifiersGlobal.MagicAttack) / 1.2); - target.SetMod(modifiersGlobal.MagicHeal, target.GetMod(modifiersGlobal.MagicHeal) / 0.8); +function onLose(owner, effect, actionContainer) + owner.DivideMod(modifiersGlobal.AttackMagicPotency, 1.2); + owner.DivideMod(modifiersGlobal.HealingMagicPotency, 0.8); end; \ No newline at end of file diff --git a/data/scripts/effects/collusion.lua b/data/scripts/effects/collusion.lua index 7f015f81..e700e6df 100644 --- a/data/scripts/effects/collusion.lua +++ b/data/scripts/effects/collusion.lua @@ -1,10 +1,10 @@ require("modifiers") -function onHit(effect, attacker, defender, action, actionContainer) +function onHit(effect, attacker, defender, skill, action, actionContainer) local enmity = action.enmity; action.enmity = 0; defender.hateContainer.UpdateHate(effect.GetSource(), enmity); --Does collusion send a message? - actionContainer.AddAction(attacker.statusEffects.RemoveStatusEffectForBattleAction(effect)); + defender.statusEffects.RemoveStatusEffect(effect, actionContainer, 30331, false); end; \ No newline at end of file diff --git a/data/scripts/effects/combo.lua b/data/scripts/effects/combo.lua index 44503843..5ff9a4fc 100644 --- a/data/scripts/effects/combo.lua +++ b/data/scripts/effects/combo.lua @@ -1,3 +1,6 @@ -function onLose(target, effect) - target:SetCombos(); +function onGain(owner, effect, actionContainer) +end; + +function onLose(owner, effect, actionContainer) + owner:SetCombos(); end; \ No newline at end of file diff --git a/data/scripts/effects/cover.lua b/data/scripts/effects/cover.lua index b63b5e5c..89f31cc4 100644 --- a/data/scripts/effects/cover.lua +++ b/data/scripts/effects/cover.lua @@ -1,7 +1,7 @@ require("modifiers") --Enahnced Cover: Restores 25% of damage taken as MP. Does not send a message -function onDamageTaken(effect, attacker, defender, action, actionContainer) +function onDamageTaken(effect, attacker, defender, skill, action, actionContainer) if effect.GetTier() == 2 then defender.AddMP(0.25 * action.amount); end diff --git a/data/scripts/effects/dark_seal2.lua b/data/scripts/effects/dark_seal2.lua index 61cf1a1e..f0e7ecc6 100644 --- a/data/scripts/effects/dark_seal2.lua +++ b/data/scripts/effects/dark_seal2.lua @@ -5,9 +5,9 @@ require("battleutils") --There isn't really any information on this, but due to the fact it falls off BEFORE the target is hit, --I'm assuming it increases a spell's accuracy modifier instead of giving actual magic accuracy function onCommandStart(effect, owner, skill, actionContainer) - if skill.actionType == ActionType.Magic then + if skill.GetActionType() == ActionType.Magic then --50 is random guess. skill.accuracyModifier = skill.accuracyModifier + 50; - actionContainer.AddAction(owner.RemoveStatusEffectForBattleAction(effect)); + owner.statusEffects.RemoveStatusEffect(effect, actionContainer, 30331, false); end end \ No newline at end of file diff --git a/data/scripts/effects/decoy.lua b/data/scripts/effects/decoy.lua index e5a6e860..f2ed8729 100644 --- a/data/scripts/effects/decoy.lua +++ b/data/scripts/effects/decoy.lua @@ -5,12 +5,13 @@ require("battleutils") function onPreAction(effect, caster, target, skill, action, actionContainer) --Evade single ranged or magic attack --Traited allows for physical attacks - if target.allegiance != caster.allegiance and (skill.isRanged or action.actionType == ActionType.Magic) then + if target.allegiance != caster.allegiance and (skill.isRanged or skill.GetActionType() == ActionType.Magic) then + --Unsure if decoy forces a miss/resist or if this is the one case where the evade hittype is used --Set action's hit rate to 0 - action.hirRate = 0.0; - + action.hitRate = 0.0; + action.resistRate = 750; --Remove status and add message - actionContainer.AddAction(target.statusEffects.RemoveStatusEffectForBattleAction(effect)); + defender.statusEffects.RemoveStatusEffect(effect, actionContainer, 30331, false); end end; \ No newline at end of file diff --git a/data/scripts/effects/decoy2.lua b/data/scripts/effects/decoy2.lua index bac5a365..f962798d 100644 --- a/data/scripts/effects/decoy2.lua +++ b/data/scripts/effects/decoy2.lua @@ -5,11 +5,12 @@ require("battleutils") function onPreAction(effect, caster, target, skill, action, actionContainer) --Evade single ranged or magic attack --Traited allows for physical attacks - if target.allegiance != caster.allegiance and (skill.isRanged or action.actionType == ActionType.Magic or action.actionType == ActionType.Physical) then + if target.allegiance != caster.allegiance and (skill.isRanged or skill.GetActionType() == ActionType.Magic or skill.GetActionType() == ActionType.Physical) then --Set action's hit rate to 0 - action.hirRate = 0.0; + action.hitRate = 0.0; + action.resistRate = 400; --Remove status and add message - actionContainer.AddAction(target.statusEffects.RemoveStatusEffectForBattleAction(effect)); + defender.statusEffects.RemoveStatusEffect(effect, actionContainer, 30331, false); end end; \ No newline at end of file diff --git a/data/scripts/effects/default.lua b/data/scripts/effects/default.lua index b74871e4..d9f217a4 100644 --- a/data/scripts/effects/default.lua +++ b/data/scripts/effects/default.lua @@ -1,5 +1,5 @@ -function onGain(target, effect) +function onGain(owner, effect, actionContainer) end; -function onLose(target, effect) +function onLose(owner, effect, actionContainer) end; \ No newline at end of file diff --git a/data/scripts/effects/defense_down.lua b/data/scripts/effects/defense_down.lua index 19b20cc9..f8e0305a 100644 --- a/data/scripts/effects/defense_down.lua +++ b/data/scripts/effects/defense_down.lua @@ -1,9 +1,9 @@ require("modifiers") -function onGain(owner, effect) +function onGain(owner, effect, actionContainer) owner.SubtractMod(modifiersGlobal.Defense, effect.GetMagnitude()); end -function onLose(owner, effect) +function onLose(owner, effect, actionContainer) owner.AddMod(modifiersGlobal.Defense, effect.GetMagnitude()); end diff --git a/data/scripts/effects/divine_regen.lua b/data/scripts/effects/divine_regen.lua index f137f72a..f9795399 100644 --- a/data/scripts/effects/divine_regen.lua +++ b/data/scripts/effects/divine_regen.lua @@ -1,9 +1,9 @@ require("modifiers") -function onGain(owner, effect) +function onGain(owner, effect, actionContainer) owner.AddMod(modifiersGlobal.Regen, effect.GetMagnitude()); end -function onLose(owner, effect) +function onLose(owner, effect, actionContainer) owner.SubtractMod(modifiersGlobal.Regen, effect.GetMagnitude()); end diff --git a/data/scripts/effects/divine_veil.lua b/data/scripts/effects/divine_veil.lua index b81fb802..fab3b76f 100644 --- a/data/scripts/effects/divine_veil.lua +++ b/data/scripts/effects/divine_veil.lua @@ -1,18 +1,18 @@ require("modifiers") --Increases block rate by 100% -function onGain(owner, effect) +function onGain(owner, effect, actionContainer) owner.AddMod(modifiersGlobal.RawBlockRate, 100); end -function onLose(owner, effect) +function onLose(owner, effect, actionContainer) owner.SubtractMod(modifiersGlobal.RawBlockRate, 100); end --Applys Divine Regen to party in range when healed by cure or cura -function onHealed(caster, target, effect, skill, action, actionContainer) +function onHealed(effect, caster, target, skill, action, actionContainer) -- cure cura - if (skill.id == 27346 or skill.id == 27347) and (caster != owner) then + if (skill.id == 27346 or skill.id == 27347) and (caster != target) then local regenDuration = 30; --Apparently heals for 85 without AF, 113 with. Unsure if these can be improved with stats local magnitude = 85 @@ -23,9 +23,8 @@ function onHealed(caster, target, effect, skill, action, actionContainer) end --For each party member in range, add divine regen - for chara in owner.GetPartyMembersInRange(8) do - local addAction = chara.statusEffects.AddStatusForBattleAction(223264, effect.GetTier(), magnitude, regenDuration); - actionContainer.AddAction(addAction); + for chara in target.GetPartyMembersInRange(8) do + chara.statusEffects.AddStatusEffect(223264, effect.GetTier(), magnitude, regenDuration, actionContainer); end end end; \ No newline at end of file diff --git a/data/scripts/effects/dread_spike.lua b/data/scripts/effects/dread_spike.lua index e5677cd1..83592924 100644 --- a/data/scripts/effects/dread_spike.lua +++ b/data/scripts/effects/dread_spike.lua @@ -7,8 +7,8 @@ require("battleutils") --It still shows the enemy's "Enemy used [command]." message but there is no 0 damage dealt message. --Don't know how this works with multi-hit attacks or even how it works with stoneskin or other buffs that respond to damage -- I dont really know how this should work... -function onDamageTaken(effect, attacker, defender, action, actionContainer) - if action.actionType == ActionType.Physical then +function onDamageTaken(effect, attacker, defender, skill, action, actionContainer) + if skill.GetActionType() == ActionType.Physical then --maybe this works? local absorbPercent = 0.5; @@ -24,7 +24,6 @@ function onDamageTaken(effect, attacker, defender, action, actionContainer) --30451: You recover [absorbAmount] HP. actionContainer.AddHPAction(defender.actorId, 30451, absorbAmount) --Dread Spike is lost after absorbing hp - actionContainer.AddAction(defender.statusEffects.RemoveStatusEffectForBattleAction(effect)); + defender.statusEffects.RemoveStatusEffect(effect, actionContainer, 30331, false); end -end; - +end; \ No newline at end of file diff --git a/data/scripts/effects/enduring_march.lua b/data/scripts/effects/enduring_march.lua index 32aaa489..4bc44e98 100644 --- a/data/scripts/effects/enduring_march.lua +++ b/data/scripts/effects/enduring_march.lua @@ -1,20 +1,20 @@ require("modifiers") -function onGain(target, effect) +function onGain(owner, effect, actionContainer) --Traited increases speed by 20%. Assuming that means it actually increases speed instead of simply offsetting the negative speed it has by default local speedModifier = 0.8; if effect.GetTier() == 2 then speedModifier = 1.2; end - target.SetMod(modifiersGlobal.Speed, target.GetMod(modifiersGlobal.Speed) * speedModifier); + owner.MultiplyMod(modifiersGlobal.MovementSpeed, speedModifier); end; -function onLose(target, effect) +function onLose(owner, effect, actionContainer) local speedModifier = 0.8; if effect.GetTier() == 2 then speedModifier = 1.2; end - target.SetMod(modifiersGlobal.Speed, target.GetMod(modifiersGlobal.Speed) / speedModifier); + owner.DivideMod(modifiersGlobal.MovementSpeed, speedModifier); end; \ No newline at end of file diff --git a/data/scripts/effects/evade_proc.lua b/data/scripts/effects/evade_proc.lua index 5e6a46e2..d9b162e4 100644 --- a/data/scripts/effects/evade_proc.lua +++ b/data/scripts/effects/evade_proc.lua @@ -1,3 +1,3 @@ -function onLose(target, effect) - target:SetProc(0, false); +function onLose(owner, effect, actionContainer) + owner:SetProc(0, false); end; \ No newline at end of file diff --git a/data/scripts/effects/excruciate.lua b/data/scripts/effects/excruciate.lua index 59e3e499..0a35bf39 100644 --- a/data/scripts/effects/excruciate.lua +++ b/data/scripts/effects/excruciate.lua @@ -2,7 +2,7 @@ require("modifiers") require("battleutils") --Gradually increases critical rate of spells -function onTick(owner, effect) +function onTick(owner, effect, actionContainer) --No clue how fast the crit rate increases or how often it ticks --Only clue I have to go on is that the strategy seemed to be to use it --before or after fire/thunder and you'd usually get a crit at firaga/thundaga @@ -23,8 +23,8 @@ function onCommandStart(effect, owner, skill, actionContainer) skill.bonusCritRate = skill.bonusCritRate + effect.GetMagnitude(); end -function onCrit(effect, attacker, defender, action, actionContainer) - if action.commandType == CommandType.Spell then - actionContainer.AddAction(attacker.statusEffects.RemoveStatusEffectForBattleAction(effect)); +function onCrit(effect, attacker, defender, skill, action, actionContainer) + if skill.GetCommandType() == CommandType.Spell then + attacker.statusEffects.RemoveStatusEffect(effect, actionContainer, 30331, false); end end \ No newline at end of file diff --git a/data/scripts/effects/expchain.lua b/data/scripts/effects/expchain.lua new file mode 100644 index 00000000..a9cd5f56 --- /dev/null +++ b/data/scripts/effects/expchain.lua @@ -0,0 +1,7 @@ +require("modifiers") + +function onGain(owner, effect, actionContainer) +end; + +function onLose(owner, effect, actionContainer) +end; \ No newline at end of file diff --git a/data/scripts/effects/featherfoot.lua b/data/scripts/effects/featherfoot.lua index 13f635c3..97cd67c0 100644 --- a/data/scripts/effects/featherfoot.lua +++ b/data/scripts/effects/featherfoot.lua @@ -1,16 +1,16 @@ require("modifiers"); --15% in ARR, dont know how it worked in 1.0 -function onGain(target, effect) - target.AddMod(modifiersGlobal.RawEvadeRate, 15); +function onGain(owner, effect, actionContainer) + owner.AddMod(modifiersGlobal.RawEvadeRate, 15); end; -function onLose(target, effect) - target.SubtractMod(modifiersGlobal.RawEvadeRate, 15); +function onLose(owner, effect, actionContainer) + owner.SubtractMod(modifiersGlobal.RawEvadeRate, 15); end; --Returns 25%? of amount dodged as MP -function onEvade(effect, attacker, defender, action, actionContainer) +function onEvade(effect, attacker, defender, skill, action, actionContainer) --25% of amount dodged untraited, 50% traited local percent = 0.25; if (effect.GetTier() == 2) then @@ -22,5 +22,5 @@ function onEvade(effect, attacker, defender, action, actionContainer) --33010: You recover x MP from Featherfoot actionContainer.AddMPAction(defender.actorId, 33010, mpToReturn); --Featherfoot is lost after evading - actionContainer.AddAction(defender.statusEffects.RemoveStatusEffectForBattleAction(effect)); + defender.statusEffects.RemoveStatusEffect(effect, actionContainer, 30331, false); end; \ No newline at end of file diff --git a/data/scripts/effects/fists_of_earth.lua b/data/scripts/effects/fists_of_earth.lua index d9ce7955..749dd2b3 100644 --- a/data/scripts/effects/fists_of_earth.lua +++ b/data/scripts/effects/fists_of_earth.lua @@ -1,6 +1,4 @@ -function onGain(target, effect) - target.statusEffects.RemoveStatusEffect(223209) - target.statusEffects.RemoveStatusEffect(223211) +function onGain(owner, effect, actionContainer) end; --Need to do more research on these. diff --git a/data/scripts/effects/fists_of_fire.lua b/data/scripts/effects/fists_of_fire.lua index 36442318..f4176486 100644 --- a/data/scripts/effects/fists_of_fire.lua +++ b/data/scripts/effects/fists_of_fire.lua @@ -1,4 +1,2 @@ -function onGain(target, effect) - target.statusEffects.RemoveStatusEffect(223210) - target.statusEffects.RemoveStatusEffect(223211) +function onGain(owner, effect, actionContainer) end; \ No newline at end of file diff --git a/data/scripts/effects/fists_of_wind.lua b/data/scripts/effects/fists_of_wind.lua index 06eaf213..f4176486 100644 --- a/data/scripts/effects/fists_of_wind.lua +++ b/data/scripts/effects/fists_of_wind.lua @@ -1,4 +1,2 @@ -function onGain(target, effect) - target.statusEffects.RemoveStatusEffect(223210) - target.statusEffects.RemoveStatusEffect(223209) +function onGain(owner, effect, actionContainer) end; \ No newline at end of file diff --git a/data/scripts/effects/flare2.lua b/data/scripts/effects/flare2.lua new file mode 100644 index 00000000..db26b1d0 --- /dev/null +++ b/data/scripts/effects/flare2.lua @@ -0,0 +1,9 @@ +require("modifiers") + +function onGain(owner, effect, actionContainer) + owner.AddMod(modifiersGlobal.RegenDown, effect.GetMagnitude()); +end + +function onLose(owner, effect, actionContainer) + owner.SubtractMod(modifiersGlobal.RegenDown, effect.GetMagnitude()); +end diff --git a/data/scripts/effects/foresight.lua b/data/scripts/effects/foresight.lua index 2ffcde2f..9c4497f5 100644 --- a/data/scripts/effects/foresight.lua +++ b/data/scripts/effects/foresight.lua @@ -1,15 +1,15 @@ require("modifiers") -function onGain(target, effect) +function onGain(owner, effect, actionContainer) --Parry is .1% per , Random guess but gonna say it gives 20% worth of parry. - target.AddMod(modifiersGlobal.Parry, 200); + owner.AddMod(modifiersGlobal.Parry, 200); end; -function onParry(effect, attacker, defender, action, actionContainer) +function onParry(effect, attacker, defender, skill, action, actionContainer) --Foresight is lost after parrying - actionContainer.AddAction(defender.statusEffects.RemoveStatusEffectForBattleAction(effect)); + defender.statusEffects.RemoveStatusEffect(effect, actionContainer, 30331, false); end; -function onLose(target, effect) - target.SubtractMod(modifiersGlobal.Parry, 200); +function onLose(owner, effect, actionContainer) + owner.SubtractMod(modifiersGlobal.Parry, 200); end; \ No newline at end of file diff --git a/data/scripts/effects/fully_blissful_mind.lua b/data/scripts/effects/fully_blissful_mind.lua index bbd1b7ef..9bc11a7a 100644 --- a/data/scripts/effects/fully_blissful_mind.lua +++ b/data/scripts/effects/fully_blissful_mind.lua @@ -1,7 +1,7 @@ -function onGain(owner, effect) +function onGain(owner, effect, actionContainer) --Using extra because that's what blissful_mind uses effect.SetExtra(effect.GetMagnitude()); end -function onLose(owner, effect) +function onLose(owner, effect, actionContainer) end diff --git a/data/scripts/effects/glare.lua b/data/scripts/effects/glare.lua new file mode 100644 index 00000000..2dec4f7d --- /dev/null +++ b/data/scripts/effects/glare.lua @@ -0,0 +1,9 @@ +require("modifiers") + +function onGain(owner, effect, actionContainer) + owner.SubtractMod(modifiersGlobal.Accuracy, effect.GetMagnitude()); +end; + +function onLose(owner, effect, actionContainer) + owner.AddMod(modifiersGlobal.Accuracy, effect.GetMagnitude()); +end; \ No newline at end of file diff --git a/data/scripts/effects/goring_blade.lua b/data/scripts/effects/goring_blade.lua index c1f8d794..db26b1d0 100644 --- a/data/scripts/effects/goring_blade.lua +++ b/data/scripts/effects/goring_blade.lua @@ -1,9 +1,9 @@ require("modifiers") -function onGain(owner, effect) +function onGain(owner, effect, actionContainer) owner.AddMod(modifiersGlobal.RegenDown, effect.GetMagnitude()); end -function onLose(owner, effect) +function onLose(owner, effect, actionContainer) owner.SubtractMod(modifiersGlobal.RegenDown, effect.GetMagnitude()); end diff --git a/data/scripts/effects/hallowed_ground.lua b/data/scripts/effects/hallowed_ground.lua new file mode 100644 index 00000000..210ee3d0 --- /dev/null +++ b/data/scripts/effects/hallowed_ground.lua @@ -0,0 +1,9 @@ +require("modifiers") + +function onGain(owner, effect, actionContainer) + owner.AddMod(modifiersGlobal.DamageTakenDown, 100); +end; + +function onLose(owner, effect, actionContainer) + owner.SubtractMod(modifiersGlobal.DamageTakenDown, 100); +end; \ No newline at end of file diff --git a/data/scripts/effects/haste.lua b/data/scripts/effects/haste.lua index 328f0f90..af2199f9 100644 --- a/data/scripts/effects/haste.lua +++ b/data/scripts/effects/haste.lua @@ -1,10 +1,10 @@ require("modifiers") --Set magnitude to milliseconds that HF will reduce delay by -function onGain(target, effect) - target.SubtractMod(modifiersGlobal.AttackDelay, effect.GetMagnitude()); +function onGain(owner, effect, actionContainer) + owner.MultiplyMod(modifiersGlobal.AttackDelay, effect.GetMagnitude()); end; -function onLose(target, effect) - target.AddMod(modifiersGlobal.AttackDelay, effect.GetMagnitude()); +function onLose(owner, effect, actionContainer) + owner.DivideMod(modifiersGlobal.AttackDelay, effect.GetMagnitude()); end; \ No newline at end of file diff --git a/data/scripts/effects/hawks_eye.lua b/data/scripts/effects/hawks_eye.lua index a62f2b9a..f0e4079a 100644 --- a/data/scripts/effects/hawks_eye.lua +++ b/data/scripts/effects/hawks_eye.lua @@ -6,19 +6,19 @@ require("modifiers"); --This could mean traited hawk's eye gives 28.125% (18.75% * 1.5) or it could mean it gives 68.75% (18.75% + 50%) --It's also possible that Hawk's Eye gives 15 + 15% accuracy untraited, which would give 450.85, which would be rounded down. --In that case, traited hawks eye could be 15 + 22.5% or 22.5 + 22.5% or (15 + 15%) * 1.5 -function onGain(target, effect) +function onGain(owner, effect, actionContainer) local accuracyMod = 0.1875; if effect.GetTier() == 2 then accuracyMod = 0.28125; end - local amountGained = accuracyMod * target.GetMod(modifiersGlobal.Accuracy); + local amountGained = accuracyMod * owner.GetMod(modifiersGlobal.Accuracy); effect.SetMagnitude(amountGained); - target.AddMod(modifiersGlobal.Accuracy, effect.GetMagnitude()); + owner.AddMod(modifiersGlobal.Accuracy, effect.GetMagnitude()); end; -function onLose(target, effect) +function onLose(owner, effect, actionContainer) - target.SubtractMod(modifiersGlobal.Accuracy, effect.GetMagnitude()); + owner.SubtractMod(modifiersGlobal.Accuracy, effect.GetMagnitude()); end; \ No newline at end of file diff --git a/data/scripts/effects/heavy.lua b/data/scripts/effects/heavy.lua index e49f8813..0e59ab1d 100644 --- a/data/scripts/effects/heavy.lua +++ b/data/scripts/effects/heavy.lua @@ -1,13 +1,13 @@ require("modifiers") -function onGain(target, effect) - local speedModifier = 0.5; +function onGain(owner, effect, actionContainer) + local speedModifier = 0.8; - target.SetMod(modifiersGlobal.Speed, target.GetMod(modifiersGlobal.Speed) * speedModifier); + owner.MultiplyMod(modifiersGlobal.MovementSpeed, speedModifier); end; -function onLose(target, effect) - local speedModifier = 0.5; +function onLose(owner, effect, actionContainer) + local speedModifier = 0.8; - target.SetMod(modifiersGlobal.Speed, target.GetMod(modifiersGlobal.Speed) / speedModifier); + owner.DivideMod(modifiersGlobal.MovementSpeed, speedModifier); end; \ No newline at end of file diff --git a/data/scripts/effects/hp_boost.lua b/data/scripts/effects/hp_boost.lua index d3c93575..64fde502 100644 --- a/data/scripts/effects/hp_boost.lua +++ b/data/scripts/effects/hp_boost.lua @@ -2,14 +2,14 @@ require("modifiers") --Battle Voice grants HP_Boost and it sets max hp to 125% normal amount and heals for the difference between current --This doesn't seem like the correct way to do this. If max HP changes between gainign and losing wont this break? -function onGain(target, effect) - local newMaxHP = target.GetMaxHP() * 1.25; - local healAmount = newMaxHP - target.GetMaxHP(); +function onGain(owner, effect, actionContainer) + local newMaxHP = owner.GetMaxHP() * 1.25; + local healAmount = newMaxHP - owner.GetMaxHP(); - target.SetMaxHP(newMaxHP); - target.AddHP(healAmount); + owner.SetMaxHP(newMaxHP); + owner.AddHP(healAmount); end; -function onLose(target, effect) - target.SetMaxHP(target.GetMaxHP() / 1.25); +function onLose(owner, effect, actionContainer) + owner.SetMaxHP(owner.GetMaxHP() / 1.25); end; \ No newline at end of file diff --git a/data/scripts/effects/hp_penalty.lua b/data/scripts/effects/hp_penalty.lua new file mode 100644 index 00000000..daf5c20c --- /dev/null +++ b/data/scripts/effects/hp_penalty.lua @@ -0,0 +1,11 @@ +require("modifiers") + +function onGain(owner, effect, actionContainer) + local newMaxHP = owner.GetMaxHP() * 0.75; + + owner.SetMaxHP(newMaxHP); +end; + +function onLose(owner, effect, actionContainer) + owner.SetMaxHP(owner.GetMaxHP() / 0.75); +end; \ No newline at end of file diff --git a/data/scripts/effects/hundred_fists.lua b/data/scripts/effects/hundred_fists.lua index 28b32b7b..7c6d4475 100644 --- a/data/scripts/effects/hundred_fists.lua +++ b/data/scripts/effects/hundred_fists.lua @@ -1,10 +1,10 @@ require("modifiers") --Set magnitude to milliseconds that HF will reduce delay by -function onGain(target, effect) - target.SubtractMod(modifiersGlobal.AttackDelay), effect.GetMagnitude()); +function onGain(owner, effect, actionContainer) + owner.SubtractMod(modifiersGlobal.Delay, effect.GetMagnitude()); end; -function onLose(target, effect) - target.AddMod(modifiersGlobal.AttackDelay), effect.GetMagnitude()); +function onLose(owner, effect, actionContainer) + owner.AddMod(modifiersGlobal.Delay, effect.GetMagnitude()); end; \ No newline at end of file diff --git a/data/scripts/effects/invigorate.lua b/data/scripts/effects/invigorate.lua index a4aac14c..4524940f 100644 --- a/data/scripts/effects/invigorate.lua +++ b/data/scripts/effects/invigorate.lua @@ -1,10 +1,10 @@ require("modifiers") --100 TP per tick without AF. 133 TP per tick with AF -function onGain(owner, effect) +function onGain(owner, effect, actionContainer) owner.AddMod(modifiersGlobal.Regain, effect.GetMagnitude()); end -function onLose(owner, effect) +function onLose(owner, effect, actionContainer) owner.SubtractMod(modifiersGlobal.Regain, effect.GetMagnitude()); end diff --git a/data/scripts/effects/keen_flurry.lua b/data/scripts/effects/keen_flurry.lua index d80ea770..f31059a1 100644 --- a/data/scripts/effects/keen_flurry.lua +++ b/data/scripts/effects/keen_flurry.lua @@ -3,7 +3,7 @@ require("battleutils") --Untraited reduces cooldown by 50% --Traited reduces cooldown by 100% function onCommandStart(effect, owner, skill, actionContainer) - if skill.commandType == CommandType.Weaponskill then + if skill.GetCommandType() == CommandType.Weaponskill then local reduction = 0.5; if effect.GetTier() == 2 then @@ -11,5 +11,6 @@ function onCommandStart(effect, owner, skill, actionContainer) end skill.recastTimeMs = skill.recastTimeMs - (reduction * skill.recastTimeMs); + owner.statusEffects.RemoveStatusEffect(effect, actionContainer, 30331, false); end end; \ No newline at end of file diff --git a/data/scripts/effects/life_surge_I.lua b/data/scripts/effects/life_surge_I.lua index 3f3a5ab5..864fff62 100644 --- a/data/scripts/effects/life_surge_I.lua +++ b/data/scripts/effects/life_surge_I.lua @@ -4,8 +4,8 @@ require("battleutils") --Trait: Increases healing by 20%. Is this the base % or the amount after taking the base percent? --I'm guessing the way it works is that LSI/II/III have 10/20/30% absorb by default and 30/40/50% traited. --Seems to match what i can find in videos -function onHit(effect, attacker, defender, action, actionContainer) - if action.commandType == CommandType.AutoAttack then +function onHit(effect, attacker, defender, skill, action, actionContainer) + if skill.GetCommandType() == CommandType.AutoAttack then local healPercent = 0.10; if effect.GetTier() == 2 then @@ -14,6 +14,6 @@ function onHit(effect, attacker, defender, action, actionContainer) local amount = math.floor((healPercent * action.amount) + 1); attacker.AddHP(amount); - actionContainer.AddHPAction(defender.actorId, 30332, amount); + actionContainer.AddHPAbsorbAction(defender.actorId, 30332, amount); end end; \ No newline at end of file diff --git a/data/scripts/effects/life_surge_II.lua b/data/scripts/effects/life_surge_II.lua index 3b74a94e..944dcafb 100644 --- a/data/scripts/effects/life_surge_II.lua +++ b/data/scripts/effects/life_surge_II.lua @@ -1,7 +1,7 @@ require("battleutils") -function onHit(effect, attacker, defender, action, actionContainer) - if action.commandType == CommandType.AutoAttack then +function onHit(effect, attacker, defender, skill, action, actionContainer) + if skill.GetCommandType() == CommandType.AutoAttack then local healPercent = 0.20; if effect.GetTier() == 2 then @@ -10,6 +10,6 @@ function onHit(effect, attacker, defender, action, actionContainer) local amount = math.floor((healPercent * action.amount) + 1); attacker.AddHP(amount); - actionContainer.AddHPAction(defender.actorId, 30332, amount); + actionContainer.AddHPAbsorbAction(defender.actorId, 30332, amount); end end; \ No newline at end of file diff --git a/data/scripts/effects/life_surge_III.lua b/data/scripts/effects/life_surge_III.lua index 3f3a5ab5..9307829f 100644 --- a/data/scripts/effects/life_surge_III.lua +++ b/data/scripts/effects/life_surge_III.lua @@ -4,16 +4,16 @@ require("battleutils") --Trait: Increases healing by 20%. Is this the base % or the amount after taking the base percent? --I'm guessing the way it works is that LSI/II/III have 10/20/30% absorb by default and 30/40/50% traited. --Seems to match what i can find in videos -function onHit(effect, attacker, defender, action, actionContainer) - if action.commandType == CommandType.AutoAttack then - local healPercent = 0.10; +function onHit(effect, attacker, defender, skill, action, actionContainer) + if skill.GetCommandType() == CommandType.AutoAttack then + local healPercent = 0.30; if effect.GetTier() == 2 then - healPercent = 0.30; + healPercent = 0.50; end local amount = math.floor((healPercent * action.amount) + 1); attacker.AddHP(amount); - actionContainer.AddHPAction(defender.actorId, 30332, amount); + actionContainer.AddHPAbsorbAction(defender.actorId, 30332, amount); end end; \ No newline at end of file diff --git a/data/scripts/effects/magic_evasion_down.lua b/data/scripts/effects/magic_evasion_down.lua index 2afa58ba..0bc153a0 100644 --- a/data/scripts/effects/magic_evasion_down.lua +++ b/data/scripts/effects/magic_evasion_down.lua @@ -1,9 +1,9 @@ require("modifiers") -function onGain(owner, effect) +function onGain(owner, effect, actionContainer) owner.SubtractMod(modifiersGlobal.MagicEvasion, effect.GetMagnitude()); end -function onLose(owner, effect) +function onLose(owner, effect, actionContainer) owner.AddMod(modifiersGlobal.MagicEvasion, effect.GetMagnitude()); end diff --git a/data/scripts/effects/minuet_of_rigor.lua b/data/scripts/effects/minuet_of_rigor.lua index 87919522..da4a20d0 100644 --- a/data/scripts/effects/minuet_of_rigor.lua +++ b/data/scripts/effects/minuet_of_rigor.lua @@ -1,12 +1,12 @@ require("modifiers") -function onGain(owner, effect) +function onGain(owner, effect, actionContainer) --Only one song per bard can be active, need to figure out a good way to do this owner.AddMod(modifiersGlobal.Accuracy, effect.GetMagnitude()); owner.AddMod(modifiersGlobal.MagicAccuracy, effect.GetMagnitude()); end; -function onLose(owner, effect) +function onLose(owner, effect, actionContainer) owner.SubtractMod(modifiersGlobal.Accuracy, effect.GetMagnitude()); owner.SubtractMod(modifiersGlobal.MagicAccuracy, effect.GetMagnitude()); end; \ No newline at end of file diff --git a/data/scripts/effects/miss_proc.lua b/data/scripts/effects/miss_proc.lua index 2983289a..daf71a9f 100644 --- a/data/scripts/effects/miss_proc.lua +++ b/data/scripts/effects/miss_proc.lua @@ -1,3 +1,3 @@ -function onLose(target, effect) - target:SetProc(3, false); +function onLose(owner, effect, actionContainer) + owner:SetProc(3, false); end; \ No newline at end of file diff --git a/data/scripts/effects/necrogenesis.lua b/data/scripts/effects/necrogenesis.lua index e340f958..76c281e7 100644 --- a/data/scripts/effects/necrogenesis.lua +++ b/data/scripts/effects/necrogenesis.lua @@ -1,12 +1,12 @@ require("modifiers") require("battleutils") -function onHit(effect, attacker, defender, action, actionContainer) - if action.commandType == CommandType.Spell then +function onHit(effect, attacker, defender, skill, action, actionContainer) + if skill.GetCommandType() == CommandType.Spell then --Necrogenesis returns 75% of damage done rounded up(?) as MP. local hpToReturn = math.ceil(0.75 * action.amount); - attacker.AddMp(hpToReturn); - actionContainer.AddHPAction(attacker.actorId, 33012, mpToReturn); - actionContainer.AddAction(attacker.statusEffects.RemoveStatusEffectForBattleAction(effect)); + attacker.AddHP(hpToReturn); + actionContainer.AddHPAbsorbAction(defender.actorId, 33012, hpToReturn); + attacker.statusEffects.RemoveStatusEffect(effect, actionContainer, 30331, false); end end \ No newline at end of file diff --git a/data/scripts/effects/outmaneuver2.lua b/data/scripts/effects/outmaneuver2.lua index f54e864e..e44f58be 100644 --- a/data/scripts/effects/outmaneuver2.lua +++ b/data/scripts/effects/outmaneuver2.lua @@ -1,16 +1,16 @@ require("modifiers") --Add 30 raw block rate. No idea how much block it actually gives. -function onGain(owner, effect) +function onGain(owner, effect, actionContainer) owner.AddMod(modifiersGlobal.RawBlockRate, 30); end -function onLose(owner, effect) +function onLose(owner, effect, actionContainer) owner.SubtractMod(modifiersGlobal.RawBlockRate, 30); end --Gives 200 TP on block. Traited: Gives 10% of the amount blocked back as MP -function onBlock(effect, attacker, defender, action, actionContainer) +function onBlock(effect, attacker, defender, skill, action, actionContainer) --200 TP on block defender.AddTP(200); diff --git a/data/scripts/effects/paeon_of_war.lua b/data/scripts/effects/paeon_of_war.lua index ec50abf6..55868d91 100644 --- a/data/scripts/effects/paeon_of_war.lua +++ b/data/scripts/effects/paeon_of_war.lua @@ -1,10 +1,10 @@ require("modifiers") -function onGain(owner, effect) +function onGain(owner, effect, actionContainer) --Only one song per bard can be active, need to figure out a good way to do this owner.AddMod(modifiersGlobal.Regain, effect.GetMagnitude()); end; -function onLose(owner, effect) +function onLose(owner, effect, actionContainer) owner.SubtractMod(modifiersGlobal.Regain, effect.GetMagnitude()); end; \ No newline at end of file diff --git a/data/scripts/effects/parry_proc.lua b/data/scripts/effects/parry_proc.lua index 97e6911a..e2887d6f 100644 --- a/data/scripts/effects/parry_proc.lua +++ b/data/scripts/effects/parry_proc.lua @@ -1,3 +1,3 @@ -function onLose(target, effect) - target:SetProc(2, false); +function onLose(owner, effect, actionContainer) + owner:SetProc(2, false); end; \ No newline at end of file diff --git a/data/scripts/effects/parsimony.lua b/data/scripts/effects/parsimony.lua index cb3ea325..2fa632d0 100644 --- a/data/scripts/effects/parsimony.lua +++ b/data/scripts/effects/parsimony.lua @@ -2,16 +2,23 @@ require("modifiers") require("battleutils") --Forces crit of a single WS action from rear. -function onMagicCast(caster, effect, skill) +function onMagicCast(effect, caster, skill) skill.mpCost = skill.mpCost / 2; end; -function onHit(effect, attacker, defender, action, actionContainer) - if action.commandType == CommandType.Spell then - --Parsimony returns 35% of damage done rounded up as MP. - local mpToReturn = math.ceil(0.35 * action.amount); - attacker.AddMp(mpToReturn); - actionContainer.AddMPAction(attacker.actorId, 33007, mpToReturn); - actionContainer.AddAction(attacker.statusEffects.RemoveStatusEffectForBattleAction(effect)); +--Having two identical functions seems weird. also don't know if parsimony still activates if resisted or evaded? +function onHit(effect, attacker, defender, skill, action, actionContainer) + if skill.GetCommandType() == CommandType.Spell then + local percent = 0.10; + + if effect.GetTier() == 2 then + percent = 0.35; + end + + --Parsimony returns 10% (35 traited) of damage done rounded up as MP. + local mpToReturn = math.ceil(percent * action.amount); + attacker.AddMP(mpToReturn); + actionContainer.AddMPAbsorbAction(0, 33007, mpToReturn); + defender.statusEffects.RemoveStatusEffect(effect, actionContainer, 30331, false); end end \ No newline at end of file diff --git a/data/scripts/effects/poison.lua b/data/scripts/effects/poison.lua index 34f9ca6c..db26b1d0 100644 --- a/data/scripts/effects/poison.lua +++ b/data/scripts/effects/poison.lua @@ -1,7 +1,9 @@ -function onGain(owner, effect) +require("modifiers") + +function onGain(owner, effect, actionContainer) owner.AddMod(modifiersGlobal.RegenDown, effect.GetMagnitude()); end -function onLose(owner, effect) +function onLose(owner, effect, actionContainer) owner.SubtractMod(modifiersGlobal.RegenDown, effect.GetMagnitude()); end diff --git a/data/scripts/effects/power_surge_I.lua b/data/scripts/effects/power_surge_I.lua index ccef5719..10c7be0d 100644 --- a/data/scripts/effects/power_surge_I.lua +++ b/data/scripts/effects/power_surge_I.lua @@ -2,9 +2,23 @@ require("modifiers") require("battleutils") --https://www.bluegartr.com/threads/107403-Stats-and-how-they-work/page22 -function onGain(owner, effect) - owner.AddMod(modifiersGlobal.Attack, 115); - owner.SubtractMod(modifiersGlobal.Defense, 158); + +--Base amount of attack gained is 105, which is multiplied by 1.1 if traited. This is why it gives 231 Attack at level 2 +--Unsure why defense is a weird number +function onGain(owner, effect, actionContainer) + local attackGained = 315; + local defenseLost = 158; + + --Enhanced Power Surge: Increases effect of Power Surge by 10% (assuming this doesn't lower defense further) + if owner.HasTrait(27281) then + attackGained = attackGained * 1.1; + end + + effect.SetMagnitude(attackGained); + effect.SetExtra(defenseLost); + + owner.AddMod(modifiersGlobal.Attack, effect.GetMagnitude()); + owner.SubtractMod(modifiersGlobal.Defense, effect.GetExtra()); end function onCommandStart(effect, owner, command, actionContainer) @@ -14,7 +28,7 @@ function onCommandStart(effect, owner, command, actionContainer) effect.SetTier(effect.GetTier() + 1); --Takes 10 weaponskills/jumps to increase level - if effect.GetTier() > 10 then + if effect.GetTier() > 1 then local action = owner.statusEffects.ReplaceEffect(effect, 223213, 1, 1, 60); actionContainer.AddAction(action); else @@ -23,7 +37,7 @@ function onCommandStart(effect, owner, command, actionContainer) end end -function onLose(owner, effect) - owner.SubtractMod(modifiersGlobal.Attack, 115); - owner.AddMod(modifiersGlobal.Defense, 158); +function onLose(owner, effect, actionContainer) + owner.SubtractMod(modifiersGlobal.Attack, effect.GetMagnitude()); + owner.AddMod(modifiersGlobal.Defense, effect.GetExtra()); end \ No newline at end of file diff --git a/data/scripts/effects/power_surge_II.lua b/data/scripts/effects/power_surge_II.lua index dc87d18f..b2bfe34c 100644 --- a/data/scripts/effects/power_surge_II.lua +++ b/data/scripts/effects/power_surge_II.lua @@ -2,9 +2,20 @@ require("modifiers") require("battleutils") --https://www.bluegartr.com/threads/107403-Stats-and-how-they-work/page22 -function onGain(owner, effect) - owner.AddMod(modifiersGlobal.Attack, 230); - owner.SubtractMod(modifiersGlobal.Defense, 158); +function onGain(owner, effect, actionContainer) + local attackGained = 210; + local defenseLost = 158; + + --Enhanced Power Surge: Increases effect of Power Surge by 10% (assuming this doesn't lower defense further) + if owner.HasTrait(27281) then + attackGained = attackGained * 1.1; + end + + effect.SetMagnitude(attackGained); + effect.SetExtra(defenseLost); + + owner.AddMod(modifiersGlobal.Attack, effect.GetMagnitude()); + owner.SubtractMod(modifiersGlobal.Defense, effect.GetExtra()); end function onCommandStart(effect, owner, command, actionContainer) @@ -23,8 +34,7 @@ function onCommandStart(effect, owner, command, actionContainer) end end -function onLose(owner, effect) - owner.SubtractMod(modifiersGlobal.Attack, 230); - owner.AddMod(modifiersGlobal.Defense, 158); -end - +function onLose(owner, effect, actionContainer) + owner.SubtractMod(modifiersGlobal.Attack, effect.GetMagnitude()); + owner.AddMod(modifiersGlobal.Defense, effect.GetExtra()); +end \ No newline at end of file diff --git a/data/scripts/effects/power_surge_III.lua b/data/scripts/effects/power_surge_III.lua index 5d9e46c8..ccb3d1dd 100644 --- a/data/scripts/effects/power_surge_III.lua +++ b/data/scripts/effects/power_surge_III.lua @@ -2,9 +2,20 @@ require("modifiers") require("battleutils") --https://www.bluegartr.com/threads/107403-Stats-and-how-they-work/page22 -function onGain(owner, effect) - owner.AddMod(modifiersGlobal.Attack, 345); - owner.SubtractMod(modifiersGlobal.Defense, 158); +function onGain(owner, effect, actionContainer) + local attackGained = 315; + local defenseLost = 158; + + --Enhanced Power Surge: Increases effect of Power Surge by 10% (assuming this doesn't lower defense further) + if owner.HasTrait(27281) then + attackGained = attackGained * 1.1; + end + + effect.SetMagnitude(attackGained); + effect.SetExtra(defenseLost); + + owner.AddMod(modifiersGlobal.Attack, effect.GetMagnitude()); + owner.SubtractMod(modifiersGlobal.Defense, effect.GetExtra()); end function onCommandStart(effect, owner, command, actionContainer) @@ -16,8 +27,7 @@ function onCommandStart(effect, owner, command, actionContainer) end end -function onLose(owner, effect) - owner.SubtractMod(modifiersGlobal.Attack, 345); - owner.AddMod(modifiersGlobal.Defense, 158); -end - +function onLose(owner, effect, actionContainer) + owner.SubtractMod(modifiersGlobal.Attack, effect.GetMagnitude()); + owner.AddMod(modifiersGlobal.Defense, effect.GetExtra()); +end \ No newline at end of file diff --git a/data/scripts/effects/protect.lua b/data/scripts/effects/protect.lua index 2a30e14b..56f4dd9a 100644 --- a/data/scripts/effects/protect.lua +++ b/data/scripts/effects/protect.lua @@ -1,18 +1,18 @@ require("modifiers") -function onGain(target, effect) +function onGain(owner, effect, actionContainer) --Magnitude is caster's Enhancing Magic Potency. --http://forum.square-enix.com/ffxiv/threads/41900-White-Mage-A-Guide --5-4-5-4-5-4-5-4-5 repeating points of Enhancing for 1 defense --4.56 * Enhancing Potency local defenseBuff = 4.56 * effect.GetMagnitude(); - target.AddMod(modifiersGlobal.Defense, defenseBuff); + owner.AddMod(modifiersGlobal.Defense, defenseBuff); end; -function onLose(target, effect) +function onLose(owner, effect, actionContainer) local defenseBuff = 4.56 * effect.GetMagnitude(); - target.SubtractMod(modifiersGlobal.Defense, defenseBuff); + owner.SubtractMod(modifiersGlobal.Defense, defenseBuff); end; diff --git a/data/scripts/effects/protect2.lua b/data/scripts/effects/protect2.lua index 0065e980..167a9bc6 100644 --- a/data/scripts/effects/protect2.lua +++ b/data/scripts/effects/protect2.lua @@ -1,6 +1,6 @@ require("modifiers") -function onGain(target, effect) +function onGain(owner, effect, actionContainer) --Magnitude is caster's Enhancing Magic Potency. --http://forum.square-enix.com/ffxiv/threads/41900-White-Mage-A-Guide --5-4-5-4-5-4-5-4-5 repeating points of Enhancing for 1 defense @@ -8,29 +8,29 @@ function onGain(target, effect) local defenseBuff = 4.56 * effect.GetMagnitude(); local magicDefenseBuff = 0; - target.AddMod(modifiersGlobal.Defense, defenseBuff); + owner.AddMod(modifiersGlobal.Defense, defenseBuff); --27365: Enhanced Protect: Increases magic defense gained from Protect. --There is no "magic defense" stat, instead it gives stats to each resist stat. magicDefenseBuff = 6.67 * effect.GetMagnitude(); - for i = modifiersGlobal.ResistFire, modifiersGlobal.ResistWater do - target.AddMod(i, magicDefenseBuff); + for i = modifiersGlobal.FireResistance, modifiersGlobal.WaterResistance do + owner.AddMod(i, magicDefenseBuff); end end; -function onLose(target, effect) +function onLose(owner, effect, actionContainer) local defenseBuff = 4.56 * effect.GetMagnitude(); local magicDefenseBuff = 0; - target.SubtractMod(modifiersGlobal.Defense, defenseBuff); + owner.SubtractMod(modifiersGlobal.Defense, defenseBuff); --27365: Enhanced Protect: Increases magic defense gained from Protect. --There is no "magic defense" stat, instead it gives stats to each resist stat. magicDefenseBuff = 6.67 * effect.GetMagnitude(); - for i = modifiersGlobal.ResistFire, modifiersGlobal.ResistWater do - target.SubtractMod(i, magicDefenseBuff); + for i = modifiersGlobal.FireResistance, modifiersGlobal.WaterResistance do + owner.SubtractMod(i, magicDefenseBuff); end end; diff --git a/data/scripts/effects/quelling_strike.lua b/data/scripts/effects/quelling_strike.lua index 347b8e1a..41600277 100644 --- a/data/scripts/effects/quelling_strike.lua +++ b/data/scripts/effects/quelling_strike.lua @@ -5,12 +5,10 @@ require("battleutils") --Traited reduces cooldown by 100% function onCommandStart(effect, owner, skill, actionContainer) --Does this apply to auto attacks? - if skill.commandType == CommandType.Weaponskill or skill.commandType == CommandType.Ability or skill.commandType == CommandType.Magic then - if skill.actionType == ActionType.Physical or skill.actionType == ActionType.Magic then - --No idea what the enmity effect is - skill.enmityModifier = skill.enmityModifier * 0.5; - - owner.AddTP(effect.GetMagnitude()); + if skill.GetCommandType() == CommandType.Weaponskill or skill.GetCommandType() == CommandType.Ability or skill.GetCommandType() == CommandType.Magic then + if skill.GetActionType() == ActionType.Physical or skill.GetActionType() == ActionType.Magic then + skill.enmityModifier = skill.enmityModifier * 0.8; + skill.tpCost = skill.tpCost - effect.GetMagnitude(); end end end; \ No newline at end of file diff --git a/data/scripts/effects/quick.lua b/data/scripts/effects/quick.lua index 65861376..b3c7ff3e 100644 --- a/data/scripts/effects/quick.lua +++ b/data/scripts/effects/quick.lua @@ -1,13 +1,13 @@ require("modifiers") -function onGain(target, effect) +function onGain(owner, effect, actionContainer) local speedModifier = 1.25; - target.SetMod(modifiersGlobal.Speed, target.GetMod(modifiersGlobal.Speed) * speedModifier); + owner.MultiplyMod(modifiersGlobal.MovementSpeed, speedModifier); end; -function onLose(target, effect) +function onLose(owner, effect, actionContainer) local speedModifier = 1.25; - target.SetMod(modifiersGlobal.Speed, target.GetMod(modifiersGlobal.Speed) / speedModifier); + owner.DivideMod(modifiersGlobal.MovementSpeed, speedModifier); end; \ No newline at end of file diff --git a/data/scripts/effects/raging_strike2.lua b/data/scripts/effects/raging_strike2.lua new file mode 100644 index 00000000..4f1a4c7d --- /dev/null +++ b/data/scripts/effects/raging_strike2.lua @@ -0,0 +1,17 @@ +require("modifiers") +require("battleutils") + +function onHit(effect, attacker, defender, skill, action, actionContainer) + if skill.id == 27259 then + --Effect stacks up to 3 times + if effect.GetTier() < 3 then + effect.SetTier(effect.GetTier() + 1); + end + end +end + +function onMiss(effect, attacker, defender, skill, action, actionContainer) + if skill.id == 27259 then + + end +end \ No newline at end of file diff --git a/data/scripts/effects/rampage2.lua b/data/scripts/effects/rampage2.lua index 80e7895a..169b65e7 100644 --- a/data/scripts/effects/rampage2.lua +++ b/data/scripts/effects/rampage2.lua @@ -1,48 +1,47 @@ require("modifiers") +require("battleutils") require("utils") parryPerDT = 20; delayMsPerDT = 100; -function onGain(owner, effect) - owner.statusEffects.RemoveStatusEffect(223207); +function onGain(owner, effect, actionContainer) end --Increases parry rating and attack speed for each hit. (Need more info) -function onDamageTaken(effect, attacker, defender, action, actionContainer) - +function onDamageTaken(effect, attacker, defender, skill, action, actionContainer) --Assuming 20 parry rating every time you're hit up to 200 --Delay is more complicated. Most axes are around 4 seconds, so i'm gonna assume it cuts off a full second at max if (effect.GetExtra() < 10) then effect.SetExtra(effect.GetExtra() + 1); - attacker.AddMod(modifiersGlobal.Parry, parryPerDT); - attacker.SubtractMod(modifiersGlobal.AttackDelay, delayMsPerDT); + defender.AddMod(modifiersGlobal.Parry, parryPerDT); + defender.SubtractMod(modifiersGlobal.Delay, delayMsPerDT); end end --Heals for 50% of damage dealt on crits with a maximum of 20% of max hp --Also only heals for as much hp as you're missing at most -function onCrit(effect, attacker, defender, action, actionContainer) - local healAmount = math.Clamp(action.amount * 0.50, 0, defender.GetMaxHP() * 0.20); - healAmount = math.Clamp(healAmount, 0, defender.GetMaxHP() - defender.GetHP()); - defender.AddHP(healAmount); +function onCrit(effect, attacker, defender, skill, action, actionContainer) + local healAmount = math.Clamp(action.amount * 0.50, 0, attacker.GetMaxHP() * 0.20); + healAmount = math.Clamp(healAmount, 0, attacker.GetMaxHP() - attacker.GetHP()); + attacker.AddHP(healAmount); --33012: You recover [healAmount] HP. - actionContainer.AddHPAction(owner.actorId, 33008, healAmount); + actionContainer.AddHPAbsorbAction(defender.actorId, 33008, healAmount); end; --"Effect fades over time" -function onTick(owner, effect) +--Rampage ticks every 6 seconds +function onTick(owner, effect, actionContainer) --Enduring march prevents fading of rampage effect if not owner.statusEffects.HasStatusEffect(223078) and (effect.GetExtra() > 0) then - --Going to assume that every 5 seconds a single hits worth of rampage is lost. - attacker.SubtractMod(modifiersGlobal.Parry, parryPerDT); - attacker.AddMod(modifiersGlobal.Delay, delayMsPerDT); + owner.SubtractMod(modifiersGlobal.Parry, parryPerDT); + owner.AddMod(modifiersGlobal.Delay, delayMsPerDT); effect.SetExtra(effect.GetExtra() - 1); end end -function onLose(owner, effect) - attacker.SubtractMod(modifiersGlobal.Parry, effect.GetExtra() * parryPerDT); - attacker.AddMod(modifiersGlobal.Delay, effect.GetExtra() * delayMsPerDT); +function onLose(owner, effect, actionContainer) + owner.SubtractMod(modifiersGlobal.Parry, effect.GetExtra() * parryPerDT); + owner.AddMod(modifiersGlobal.Delay, effect.GetExtra() * delayMsPerDT); end \ No newline at end of file diff --git a/data/scripts/effects/rampart.lua b/data/scripts/effects/rampart.lua index 6602e09a..d6476278 100644 --- a/data/scripts/effects/rampart.lua +++ b/data/scripts/effects/rampart.lua @@ -4,12 +4,12 @@ require("modifiers") --Guessing it scales with level. If I had to guess it's either 2.1 * level or (2 * level) + 5. --I'm going to guess the latter since it always leaves you with a whole number. I could be completely wrong though --The party_battle_leve has rampart giving 36? defense. It's from an earlier patch so probably useless -function onGain(target, effect) - effect.SetMagnitude(2 * target.GetLevel() + 5); +function onGain(owner, effect, actionContainer) + effect.SetMagnitude(2 * owner.GetLevel() + 5); - target.AddMod(modifiersGlobal.Defense, effect.GetMagnitude()); + owner.AddMod(modifiersGlobal.Defense, effect.GetMagnitude()); end; -function onLose(target, effect) - target.SubtractMod(modifiersGlobal.Defense, effect.GetMagnitude()); +function onLose(owner, effect, actionContainer) + owner.SubtractMod(modifiersGlobal.Defense, effect.GetMagnitude()); end; \ No newline at end of file diff --git a/data/scripts/effects/refresh.lua b/data/scripts/effects/refresh.lua index b5d53fdc..8524d7bf 100644 --- a/data/scripts/effects/refresh.lua +++ b/data/scripts/effects/refresh.lua @@ -1,7 +1,9 @@ -function onGain(owner, effect) +require("modifiers") + +function onGain(owner, effect, actionContainer) owner.AddMod(modifiersGlobal.Refresh, effect.GetMagnitude()); end -function onLose(owner, effect) +function onLose(owner, effect, actionContainer) owner.SubtractMod(modifiersGlobal.Refresh, effect.GetMagnitude()); end diff --git a/data/scripts/effects/regain.lua b/data/scripts/effects/regain.lua index cec064eb..9c3aeabf 100644 --- a/data/scripts/effects/regain.lua +++ b/data/scripts/effects/regain.lua @@ -1,7 +1,9 @@ -function onGain(owner, effect) +require("modifiers") + +function onGain(owner, effect, actionContainer) owner.AddMod(modifiersGlobal.Regain, effect.GetMagnitude()); end -function onLose(owner, effect) +function onLose(owner, effect, actionContainer) owner.SubtractMod(modifiersGlobal.Regain, effect.GetMagnitude()); end diff --git a/data/scripts/effects/regen.lua b/data/scripts/effects/regen.lua index e63ed6d9..45157ea7 100644 --- a/data/scripts/effects/regen.lua +++ b/data/scripts/effects/regen.lua @@ -1,8 +1,8 @@ --Regen is modified by Enhancing Magic Potency. Formula here: http://forum.square-enix.com/ffxiv/threads/41900-White-Mage-A-Guide -function onGain(owner, effect) +function onGain(owner, effect, actionContainer) owner.AddMod(modifiersGlobal.Regen, effect.GetMagnitude()); end -function onLose(owner, effect) +function onLose(owner, effect, actionContainer) owner.SubtractMod(modifiersGlobal.Regen, effect.GetMagnitude()); end diff --git a/data/scripts/effects/resonance2.lua b/data/scripts/effects/resonance2.lua index 34b3748a..56426f1f 100644 --- a/data/scripts/effects/resonance2.lua +++ b/data/scripts/effects/resonance2.lua @@ -3,13 +3,15 @@ require("battleutils") --Increases range of a single spell, no clue by how much, 25% is a random guess --It isn't clear if it has an effect on the aoe portion of skills or just the normal range, i've seen people on the OF say both. -function onMagicStart(caster, effect, skill) +--It also increased height of skills +function onMagicCast(effect, caster, skill) skill.range = skill.range * 1.25; + skill.rangeHeight = skill.rangeHeight * 1.25; end; --The effect falls off after the skill is finished, meaning if you start a cast and cancel, it shouldn't fall off. function onCommandFinish(effect, owner, skill, actionContainer) - if action.commandType == CommandType.Spell then - actionContainer.AddAction(owner.statusEffects.RemoveStatusEffectForBattleAction(effect)); + if skill.GetCommandType() == CommandType.Spell then + owner.statusEffects.RemoveStatusEffect(effect, actionContainer, 30331, false); end end \ No newline at end of file diff --git a/data/scripts/effects/sacred_prism.lua b/data/scripts/effects/sacred_prism.lua new file mode 100644 index 00000000..236b71cc --- /dev/null +++ b/data/scripts/effects/sacred_prism.lua @@ -0,0 +1,19 @@ +require("modifiers") +require("battleutils") + +--Cure, Cura, Regen, Esuna, Enhancing spells (Hardcoded as Stoneskin and Sanguine since we dont have a good way to check what's an enhancing spell) +supportedSpells = [27346, 27347, 27358, 27357, 27350, 27307] + +function onMagicCast(effect, caster, skill) + if supportedSpells[skill.id] then + skill.castTimeMs = skill.castTimeMs * 1.5; + skill.aoeType = TargetFindAOEType.Circle; + skill.aoeRange = 15; + end +end + +function onCommandFinish(effect, owner, skill, actionContainer) + if supportedSpells[skill.id] then + owner.statusEffects.RemoveStatusEffect(effect, actionContainer, 30331, false); + end +end; \ No newline at end of file diff --git a/data/scripts/effects/sanguine_rite2.lua b/data/scripts/effects/sanguine_rite2.lua index 969284ae..87820d59 100644 --- a/data/scripts/effects/sanguine_rite2.lua +++ b/data/scripts/effects/sanguine_rite2.lua @@ -1,8 +1,8 @@ require("modifiers") --Sanguine Rite restores 30% of damage taken as MP -function onDamageTaken(effect, attacker, defender, action, actionContainer) +function onDamageTaken(effect, attacker, defender, skill, action, actionContainer) local mpToRestore = action.amount * 0.30; defender.AddMP(mpToRestore); - actionContainer.AddMPAction(defender, 33011, mpToRestore); + actionContainer.AddMPAction(defender.actorId, 33011, mpToRestore); end \ No newline at end of file diff --git a/data/scripts/effects/sanguine_rite3.lua b/data/scripts/effects/sanguine_rite3.lua index e702d0b2..329dac74 100644 --- a/data/scripts/effects/sanguine_rite3.lua +++ b/data/scripts/effects/sanguine_rite3.lua @@ -1,22 +1,22 @@ require("modifiers") -function onGain(target, effect) +function onGain(owner, effect, actionContainer) --Traited Sanguine Rite reduces damage taken by 25%. --The icon in game says it's 50%, but it's lying local amount = 25; - target.AddMod(modifiersGlobal.DamageTakenDown, amount); + owner.AddMod(modifiersGlobal.DamageTakenDown, amount); end; -function onLose(target, effect) +function onLose(owner, effect, actionContainer) local amount = 25; - target.SubtractMod(modifiersGlobal.DamageTakenDown, amount); + owner.SubtractMod(modifiersGlobal.DamageTakenDown, amount); end; --Sanguine Rite restores 30% of damage taken as MP -function onDamageTaken(effect, attacker, defender, action, actionContainer) +function onDamageTaken(effect, attacker, defender, skill, action, actionContainer) local mpToRestore = action.amount * 0.30; defender.AddMP(mpToRestore); - actionContainer.AddMPAction(defender, 33011, mpToRestore); + actionContainer.AddMPAction(defender.actorId, 33011, mpToRestore); end \ No newline at end of file diff --git a/data/scripts/effects/sentinel.lua b/data/scripts/effects/sentinel.lua index 6ca3b4a1..637a10fc 100644 --- a/data/scripts/effects/sentinel.lua +++ b/data/scripts/effects/sentinel.lua @@ -1,30 +1,30 @@ require("modifiers") require("battleutils") -function onGain(target, effect) +function onGain(owner, effect, actionContainer) --Untraited Sentinel is 30% damage taken down, traited is 50% local amount = 30; if effect.GetTier() == 2 then amount = 50; end - target.AddMod(modifiersGlobal.DamageTakenDown, amount); + owner.AddMod(modifiersGlobal.DamageTakenDown, amount); end; -function onLose(target, effect) +function onLose(owner, effect, actionContainer) local amount = 30; if effect.GetTier() == 2 then amount = 50; end - target.SubtractMod(modifiersGlobal.DamageTakenDown, amount); + owner.SubtractMod(modifiersGlobal.DamageTakenDown, amount); end; --Increases action's enmity by 100 for weaponskills --http://forum.square-enix.com/ffxiv/threads/47393-Tachi-s-Guide-to-Paladin-%28post-1.22b%29 --Sentinel only works on weaponskills. It's possible that was a bug because the description says actions -function onHit(effect, attacker, defender, action, actionContainer) - if action.commandType == CommandType.WeaponSkill then +function onHit(effect, attacker, defender, skill, action, actionContainer) + if skill.GetCommandType() == CommandType.WeaponSkill then action.enmity = action.enmity + 100; end end \ No newline at end of file diff --git a/data/scripts/effects/sleep.lua b/data/scripts/effects/sleep.lua new file mode 100644 index 00000000..a526dcba --- /dev/null +++ b/data/scripts/effects/sleep.lua @@ -0,0 +1,12 @@ +require("modifiers") + +--Set magnitude to milliseconds that HF will reduce delay by +function onGain(owner, effect, actionContainer) +end; + +function onLose(owner, effect, actionContainer) +end; + +function onDamageTaken(effect, attacker, defender, skill, action, actionContainer) + defender.statusEffects.RemoveStatusEffect(effect, actionContainer) +end; \ No newline at end of file diff --git a/data/scripts/effects/slow.lua b/data/scripts/effects/slow.lua new file mode 100644 index 00000000..af2199f9 --- /dev/null +++ b/data/scripts/effects/slow.lua @@ -0,0 +1,10 @@ +require("modifiers") + +--Set magnitude to milliseconds that HF will reduce delay by +function onGain(owner, effect, actionContainer) + owner.MultiplyMod(modifiersGlobal.AttackDelay, effect.GetMagnitude()); +end; + +function onLose(owner, effect, actionContainer) + owner.DivideMod(modifiersGlobal.AttackDelay, effect.GetMagnitude()); +end; \ No newline at end of file diff --git a/data/scripts/effects/slowcast.lua b/data/scripts/effects/slowcast.lua new file mode 100644 index 00000000..a363fcfe --- /dev/null +++ b/data/scripts/effects/slowcast.lua @@ -0,0 +1,9 @@ +require("modifiers") +require("battleutils") + +--Increases range of a single spell, no clue by how much, 25% is a random guess +--It isn't clear if it has an effect on the aoe portion of skills or just the normal range, i've seen people on the OF say both. +--It also increased height of skills +function onMagicCast(effect, caster, skill) + skill.castTimeMs = skill.castTimeMs * 1.5; +end; \ No newline at end of file diff --git a/data/scripts/effects/spinning_heel.lua b/data/scripts/effects/spinning_heel.lua index d8531b82..d226be7f 100644 --- a/data/scripts/effects/spinning_heel.lua +++ b/data/scripts/effects/spinning_heel.lua @@ -1,10 +1,10 @@ require("modifiers") -function onGain(target, effect) - target.SetMod(modifiersGlobal.HitCount, 3); +function onGain(owner, effect, actionContainer) + owner.SetMod(modifiersGlobal.HitCount, 3); end; -function onLose(target, effect) - target.SetMod(modifiersGlobal.HitCount, 2); +function onLose(owner, effect, actionContainer) + owner.SetMod(modifiersGlobal.HitCount, 2); end; diff --git a/data/scripts/effects/stoneskin.lua b/data/scripts/effects/stoneskin.lua index 9905d3fc..d717285b 100644 --- a/data/scripts/effects/stoneskin.lua +++ b/data/scripts/effects/stoneskin.lua @@ -1,13 +1,18 @@ require("modifiers") -function onGain(owner, effect) +function onGain(owner, effect, actionContainer) owner.AddMod(modifiersGlobal.Stoneskin, effect.GetMagnitude()); end +--This is wrong, need to think of a good way of keeping track of how much stoneskin is left when it falls off. +function onLose(owner, effect, actionContainer) + owner.SetMod(modifiersGlobal.Stoneskin, 0); +end + --Using extra for how much mitigation stoneskin has -function onPostAction(caster, target, effect, skill, action, actionContainer) - if (owner.GetMod(modifiersGlobal.Stoneskin) <= 0) then - actionContainer.AddAction(owner.statusEffects.RemoveStatusEffectForBattleAction(effect)); +function onDamageTaken(effect, attacker, defender, skill, action, actionContainer) + if (defender.GetMod(modifiersGlobal.Stoneskin) <= 0) then + defender.statusEffects.RemoveStatusEffect(effect, actionContainer, 30331, false); end end; \ No newline at end of file diff --git a/data/scripts/effects/swiftsong.lua b/data/scripts/effects/swiftsong.lua new file mode 100644 index 00000000..b3c7ff3e --- /dev/null +++ b/data/scripts/effects/swiftsong.lua @@ -0,0 +1,13 @@ +require("modifiers") + +function onGain(owner, effect, actionContainer) + local speedModifier = 1.25; + + owner.MultiplyMod(modifiersGlobal.MovementSpeed, speedModifier); +end; + +function onLose(owner, effect, actionContainer) + local speedModifier = 1.25; + + owner.DivideMod(modifiersGlobal.MovementSpeed, speedModifier); +end; \ No newline at end of file diff --git a/data/scripts/effects/tempered_will.lua b/data/scripts/effects/tempered_will.lua index 4cef7878..d55c99c8 100644 --- a/data/scripts/effects/tempered_will.lua +++ b/data/scripts/effects/tempered_will.lua @@ -1,7 +1,9 @@ -function onGain(owner, effect) +require("modifiers") + +function onGain(owner, effect, actionContainer) owner.AddMod(modifiersGlobal.KnockbackImmune, 1); end -function onLose(owner, effect) +function onLose(owner, effect, actionContainer) owner.SubtractMod(modifiersGlobal.KnockbackImmune, 1); end \ No newline at end of file diff --git a/data/scripts/effects/tp_bleed.lua b/data/scripts/effects/tp_bleed.lua index 435c4842..e5707afe 100644 --- a/data/scripts/effects/tp_bleed.lua +++ b/data/scripts/effects/tp_bleed.lua @@ -1,7 +1,9 @@ -function onGain(owner, effect) +require("modifiers") + +function onGain(owner, effect, actionContainer) owner.SubtractMod(modifiersGlobal.Regain, effect.GetMagnitude()); end -function onLose(owner, effect) +function onLose(owner, effect, actionContainer) owner.AddMod(modifiersGlobal.Regain, effect.GetMagnitude()); end diff --git a/data/scripts/effects/vengeance.lua b/data/scripts/effects/vengeance.lua index 5c5379c4..6fbcc795 100644 --- a/data/scripts/effects/vengeance.lua +++ b/data/scripts/effects/vengeance.lua @@ -1,15 +1,15 @@ require("modifiers") require("battleutils") ---Unclear what the exact damage is but it seems like it's the total amount of damage the attack would have done before parrying -function onDamageTaken(effect, attacker, defender, action, actionContainer) - local amount = action.amount + action.mitigatedAmount; +--Unclear what the exact damage is but it seems like it's the total amount of damage the attack would have done before parrying + 1 +function onDamageTaken(effect, attacker, defender, skill, action, actionContainer) + local amount = action.amount + action.amountMitigated + 1; --Only reflects magical attacks if wearing AF chest - if action.actionType == ActionType.Physical or (action.actionType == ActionType.Magic and effect.GetTier() == 2) then + if skill.GetActionType() == ActionType.Physical or (skill.GetActionType() == ActionType.Magic and effect.GetTier() == 2) then --30350: Counter! You hit target for x points of damage --There are counter messages for blocks, can Vengeance be blocked/parried? - attacker.DelHP(amount); + attacker.DelHP(amount, actionContainer); actionContainer.AddHitAction(attacker.actorId, 30350, amount); end; end; \ No newline at end of file diff --git a/data/scripts/hiteffect.lua b/data/scripts/hiteffect.lua index 1285d363..4640df2c 100644 --- a/data/scripts/hiteffect.lua +++ b/data/scripts/hiteffect.lua @@ -1,22 +1,37 @@ HitEffect = { - --All HitEffects have the last byte 0x8 - HitEffectType = 134217728, --8 << 24 - --Status effects use 32 <<,24 - StatusEffectType = 536870912,--32 << 24, - --Heal effects use 48 << 24 - MagicEffectType = 805306368,--48 << 24 + --This is used for physical attacks + HitEffectType = bit32.lshift(8,24), + --This is used for additioanl effect hits. Only difference from HitEffectType is that it does not play audio. + AdditionalEffectType = bit32.lshift(24, 24), + --Status effects use 32 << 24 + StatusEffectType = bit32.lshift(32, 24), + --When losing a status effect while using a skill, this prevents the hit effect from playing on the actor playing the animation + StatusLossType = bit32.lshift(40, 24), + --Magic effects use 48 << 24, this is also used for when statuses are lost on attack + MagicEffectType = bit32.lshift(48, 24), + --This places the number on the user regardless of the target this hit effect is for, used for things like bloodbath + SelfHealType = bit32.lshift(72, 24), + --Plays the effect animation with no text or additional effects. Unsure if there are any flags. Used for things like Convert + AnimationEffectType = bit32.lshift(96, 24), + + --Each Type has it's own set of flags. These should be split into their own enums, + --but for now just keep them all under HitEffect so we don't have to change anything. + + --HitEffectType flags --Not setting RecoilLv2 or RecoilLv3 results in the weaker RecoilLv1. --These are the recoil animations that play on the target, ranging from weak to strong. --The recoil that gets set was likely based on the percentage of HP lost from the attack. - --These are used for resists for spells. RecoilLV1 is a full resist, RecoilLv2 is a partial resist, RecoilLv3 is no resist, CriticalHit is a crit + --These also have a visual effect with heals and spells but in reverse. RecoilLv1 has a large effect, Lv3 has none. Crit is very large + --For spells they represent resists. Lv0 is a max resist, Lv3 is no resist. Crit is still used for crits. + --Heals used the same effects sometimes but it isn't clear what for, it seems random? Possibly something like a trait proccing or even just a bug RecoilLv1 = 0, - RecoilLv2 = 1, - RecoilLv3 = 2, + RecoilLv2 = bit32.lshift(1, 0), + RecoilLv3 = bit32.lshift(1, 1), --Setting both recoil flags triggers the "Critical!" pop-up text and hit visual effect. - CriticalHit = 3, + CriticalHit = 3, --RecoilLv2 | RecoilLv3 --Hit visual and sound effects when connecting with the target. --Mixing these flags together will yield different results. @@ -28,14 +43,13 @@ HitEffect = --HitVisual2 is for piercing attacks --HitVisual1 | Hitvisual2 is for blunt attacks --HitVisual3 is for projectile attacks - --Basically, takes the attack property as defined by the weapon and shifts it left 2 + --Basically take the attack property of a weapon and shift it left 2 --For auto attacks attack property is weapon's damageAttributeType1 --Still not totally sure how this works with weaponskills or what hitvisual4 or the other combinations are for - HitVisual1 = 4, - HitVisual2 = 8, - HitVisual3 = 16, - HitVisual4 = 32, - + HitVisual1 = bit32.lshift(1, 2), + HitVisual2 = bit32.lshift(1, 3), + HitVisual3 = bit32.lshift(1, 4), + HitVisual4 = bit32.lshift(1, 5), --An additional visual effect that plays on the target when attacked if: --The attack is physical and they have the protect buff on. @@ -44,62 +58,111 @@ HitEffect = --Another effect plays when both Protect and Shell flags are activated. --Not sure what this effect is. --Random guess: if the attack was a hybrid of both physical and magical and the target had both Protect and Shell buffs applied. - Protect = 64, - Shell = 128, - ProtectShellSpecial = 192,-- Protect | Shell, + Protect = bit32.lshift(1, 6), + Shell = bit32.lshift(1, 7), + ProtectShellSpecial = 192, --Protect | Shell - Heal = 256,-- Required for heal text to be blue along with HealEffectType, not sure if that's all it's used for - MP = 512, - --If only HitEffect1 is set out of the hit effects, the "Evade!" pop-up text triggers along with the evade visual. --If no hit effects are set, the "Miss!" pop-up is triggered and no hit visual is played. - HitEffect1 = 512, - HitEffect2 = 1024, --Plays the standard hit visual effect, but with no sound if used alone. - HitEffect3 = 2048, --Yellow effect, crit? - HitEffect4 = 4096, --Plays the blocking animation - HitEffect5 = 8192, - GustyHitEffect = 3072,--HitEffect3 | HitEffect2, - GreenTintedHitEffect = 4608,-- HitEffect4 | HitEffect1, + HitEffect1 = bit32.lshift(1, 9), + HitEffect2 = bit32.lshift(1, 10), --Plays the standard hit visual effect, but with no sound if used alone. + HitEffect3 = bit32.lshift(1, 11), --Yellow effect, crit? + HitEffect4 = bit32.lshift(1, 12), --Plays the blocking animation + HitEffect5 = bit32.lshift(1, 13), + GustyHitEffect = 3072, --HitEffect3 | HitEffect2 + GreenTintedHitEffect = 4608, --HitEffect4 | HitEffect1 --For specific animations Miss = 0, - Evade = 512, - Hit = 1536, --HitEffect1 | HitEffect2, - Parry = 3584, --Hit | HitEffect3, - Block = 4096, - Crit = 2048, + Evade = HitEffect1, + Hit = 1536, --HitEffect1 | HitEffect2, + Crit = HitEffect3, + Parry = 3584, --Hit | HitEffect3, + Block = HitEffect4, --Knocks you back away from the attacker. - KnockbackLv1 = 5632,-- HitEffect4 | HitEffect2 | HitEffect1, - KnockbackLv2 = 6144,-- HitEffect4 | HitEffect3, - KnockbackLv3 = 6656,-- HitEffect4 | HitEffect3 | HitEffect1, - KnockbackLv4 = 7168,-- HitEffect4 | HitEffect3 | HitEffect2, - KnockbackLv5 = 7680,-- HitEffect4 | HitEffect3 | HitEffect2 | HitEffect1, + KnockbackLv1 = 5632, --HitEffect4 | HitEffect2 | HitEffect1 + KnockbackLv2 = 6144, --HitEffect4 | HitEffect3 + KnockbackLv3 = 6656, --HitEffect4 | HitEffect3 | HitEffect1 + KnockbackLv4 = 7168, --HitEffect4 | HitEffect3 | HitEffect2 + KnockbackLv5 = 7680, --HitEffect4 | HitEffect3 | HitEffect2 | HitEffect1 --Knocks you away from the attacker in a counter-clockwise direction. - KnockbackCounterClockwiseLv1 = 8192, - KnockbackCounterClockwiseLv2 = 8704,-- HitEffect5 | HitEffect1, + KnockbackCounterClockwiseLv1 = HitEffect5, + KnockbackCounterClockwiseLv2 = 8704, --HitEffect5 | HitEffect1 --Knocks you away from the attacker in a clockwise direction. - KnockbackClockwiseLv1 = 9216,-- HitEffect5 | HitEffect2, - KnockbackClockwiseLv2 = 9728,-- HitEffect5 | HitEffect2 | HitEffect1, + KnockbackClockwiseLv1 = 9216, --HitEffect5 | HitEffect2 + KnockbackClockwiseLv2 = 9728, --HitEffect5 | HitEffect2 | HitEffect1 --Completely drags target to the attacker, even across large distances. - DrawIn = 10240,-- HitEffect5 | HitEffect3, + DrawIn = 10240, --HitEffect5 | HitEffect3 --An additional visual effect that plays on the target based on according buff. - UnknownShieldEffect = 12288,-- HitEffect5 | HitEffect4, - Stoneskin = 12800,-- HitEffect5 | HitEffect4 | HitEffect1, - - --Unknown = 1 << 14, -- Not sure what this flag does; might be another HitEffect. + UnknownShieldEffect = 12288, --HitEffect5 | HitEffect4 + Stoneskin = 12800, --HitEffect5 | HitEffect4 | HitEffect1 --A special effect when performing appropriate skill combos in succession. --Ex: Thunder (SkillCombo1 Effect) -> Thundara (SkillCombo2 Effect) -> Thundaga (SkillCombo3 Effect) --Special Note: SkillCombo4 was never actually used in 1.0 since combos only chained up to 3 times maximum. - SkillCombo1 = 32768, - SkillCombo2 = 65536, - SkillCombo3 = 98304,-- SkillCombo1 | SkillCombo2, - SkillCombo4 = 131072 + SkillCombo1 = bit32.lshift(1, 15), + SkillCombo2 = bit32.lshift(1, 16), + SkillCombo3 = 98304, --SkillCombo1 | SkillCombo2 + SkillCombo4 = bit32.lshift(1, 17), - --Flags beyond here are unknown/untested. + --This is used in the absorb effect for some reason + Unknown = bit32.lshift(1, 19), + + --AdditionalEffectType flags + --The AdditionalEffectType is used for the additional effects some weapons have. + --These effect ids do not repeat the effect of the attack and will not show without a preceding HitEffectType or MagicEffectType + + --It's unclear what this is for. The ifrit fight capture has a BLM using the garuda weapon + --and this flag is set every time but has no apparent effect. + UnknownAdditionalFlag = 1, + + --These play effects on the target + FireEffect = bit32.lshift(1, 10), + IceEffect = bit32.lshift(2, 10), + WindEffect = bit32.lshift(3, 10), + EarthEffect = bit32.lshift(4, 10), + LightningEffect = bit32.lshift(5, 10), + WaterEffect = bit32.lshift(6, 10), + AstralEffect = bit32.lshift(7, 10), --Possibly for blind? + UmbralEffect = bit32.lshift(8, 10), --Posibly for poison? + + --Unknown status effect effects + StatusEffect1 = bit32.lshift(12, 10), + StatusEffect2 = bit32.lshift(13, 10), + + HPAbsorbEffect = bit32.lshift(14, 10), + MPAbsorbEffect = bit32.lshift(15, 10), + TPAbsorbEffect = bit32.lshift(16, 10), + TripleAbsorbEffect = bit32.lshift(17, 10), --Not sure about this + MoogleEffect = bit32.lshift(18, 10), + + --MagicEffectType Flags + --THese are used for magic effects that deal or heal damage as well as damage over time effects + --Crit is the same as HitEffectType + FullResist = 0, + WeakResist = bit32.lshift(1, 0), --Used for level 1, 2, and 3 resists probably + NoResist = bit32.lshift(1, 1), + + MagicShell = bit32.lshift(1, 4), --Used when casting on target with shell effects. MagicEffectType doesnt have a flag for protect or stoneskin + MagicShield = bit32.lshift(1, 5), --When used with an command that has an animation, this plays a purple shield effect. DoTs also have this flag set (at least on ifrit) but they have no animations so it doesnt show + + -- Required for heal text to be blue, not sure if that's all it's used for + Heal = bit32.lshift(1, 8), + MP = bit32.lshift(1, 9), --Causes "MP" text to appear when used with MagicEffectType. | with Heal to make text blue + TP = bit32.lshift(1, 10), --Causes "TP" text to appear when used with MagicEffectType. | with Heal to make text blue + + --SelfHealType flags + --This category causes numbers to appear on the user rather regardless of the target associated with the hit effect and do not play an animation + --These determine the text that displays (HP has no text) + SelfHealHP = 0, + SelfHealMP = bit32.lshift(1, 0), --Shows MP text on self. | with SelfHeal to make blue + SelfHealTP = bit32.lshift(1, 1), --Shows TP text on self. | with SelfHeal to make blue + + --Causes self healing numbers to be blue + SelfHeal = bit32.lshift(1, 10), } \ No newline at end of file diff --git a/data/scripts/modifiers.lua b/data/scripts/modifiers.lua index c760753b..832a9dc9 100644 --- a/data/scripts/modifiers.lua +++ b/data/scripts/modifiers.lua @@ -1,88 +1,157 @@ modifiersGlobal = { - NAMEPLATE_SHOWN = 0, - TARGETABLE = 1, - NAMEPLATE_SHOWN2 = 2, - --NAMEPLATE_SHOWN2 = 3, + --These line up with ParamNames starting at 15001 and appear on gear + --Health + Hp = 0, --Max HP + Mp = 1, --Max MP + Tp = 2, --Max TP - Strength = 3, - Vitality = 4, - Dexterity = 5, - Intelligence = 6, - Mind = 7, - Piety = 8, + --Main stats + Strength = 3, + Vitality = 4, + Dexterity = 5, + Intelligence = 6, + Mind = 7, + Piety = 8, - ResistFire = 9, - ResistIce = 10, - ResistWind = 11, - ResistLightning = 12, - ResistEarth = 13, - ResistWater = 14, + --Elemental Resistances + FireResistance = 9, --Lowers Fire damage taken + IceResistance = 10, --Lowers Ice damage taken + WindResistance = 11, --Lowers Wind damage taken + EarthResistance = 12, --Lowers Earth damage taken + LightningResistance = 13, --Lowers Lightning damage taken + WaterResistance = 14, --Lowers Water damage taken - Accuracy = 15, - Evasion = 16, - Attack = 17, - Defense = 18, --Is there a magic defense stat? 19 maybe? - MagicAttack = 23, - MagicHeal = 24, - MagicEnhancePotency = 25, - MagicEnfeeblingPotency = 26, + --Physical Secondary stats + Accuracy = 15, --Increases chance to hit with physical attacks + Evasion = 16, --Decreases chance to be hit by physical attacks + Attack = 17, --Increases damage done with physical attacks + Defense = 18, --Decreases damage taken from physical attacks - MagicAccuracy = 27, - MagicEvasion = 28, + --Physical crit stats + CriticalHitRating = 19, --Increases chance to crit with physical attacks + CriticalHitEvasion = 20, --Decreases chance to be crit by physical attacks + CriticalHitAttackPower = 21, --Increases damage done by critical physical attacks + CriticalHitResilience = 22, --Decreases damage taken from critical physical attacks - CraftProcessing = 30, - CraftMagicProcessing = 31, - CraftProcessControl = 32, + --Magic secondary stats + AttackMagicPotency = 23, --Increases damage done with magical attacks + HealingMagicPotency = 24, --Increases healing done with magic healing + EnhancementMagicPotency = 25, --Increases effect of enhancement magic + EnfeeblingMagicPotency = 26, --Increases effect of enfeebling magic + MagicAccuracy = 27, --Decreases chance for magic to be evaded + MagicEvasion = 28, --Increases chance to evade magic - HarvestPotency = 33, - HarvestLimit = 34, - HarvestRate = 35, + --Crafting stats + Craftsmanship = 29, + MagicCraftsmanship = 30, + Control = 31, + Gathering = 32, + Output = 33, + Perception = 34, - None = 36, - Hp = 37, - HpPercent = 38, - Mp = 39, - MpPercent = 40, - Tp = 41, - TpPercent = 42, - Regen = 43, - Refresh = 44, + --Magic crit stats + MagicCriticalHitRating = 35, --Increases chance to crit with magical attacks + MagicCriticalHitEvasion = 36, --Decreases chance to be crit by magical attacks + MagicCriticalHitPotency = 37, --Increases damage done by critical magical attacks + MagicCriticalHitResilience = 38, --Decreases damage taken from critical magical attacks - AttackRange = 45, - Speed = 46, - AttackDelay = 47, + --Blocking stats + Parry = 39, --Increases chance to parry + BlockRate = 40, --Increases chance to block + Block = 41, --Reduces damage taken from blocked attacks - Raise = 48, - MinimumHpLock = 49, -- hp cannot fall below this value - AttackType = 50, -- slashing, piercing, etc - BlockRate = 51, - Block = 52, - CritRating = 53, - HasShield = 54, -- Need this because shields are required for blocks. Could have used BlockRate or Block but BlockRate is provided by Gallant Sollerets and Block is provided by some buffs. - HitCount = 55, -- Amount of hits in an auto attack. Usually 1, 2 for h2h, 3 with spinning heel + --Elemental Potencies + FireMagicPotency = 42, --Increases damage done by Fire Magic + IceMagicPotency = 43, --Increases damage done by Ice Magic + WindMagicPotency = 44, --Increases damage done by Wind Magic + EarthMagicPotency = 45, --Increases damage done by Earth Magic + LightningMagicPotency = 46, --Increases damage done by Lightning Magic + WaterMagicPotency = 47, --Increases damage done by Water Magic - --Flat percent increases to these rates. Probably a better way to do this - RawEvadeRate = 56, - RawParryRate = 57, - RawBlockRate = 58, - RawResistRate = 59, - RawHitRate = 60, - RawCritRate = 61, + --Miscellaneous + Regen = 48, --Restores health over time + Refresh = 49, --Restores MP over time + StoreTp = 50, --Increases TP gained by auto attacks and damaging abiltiies + Enmity = 51, --Increases enmity gained from actions + Spikes = 52, --Deals damage or status to attacker when hit + Haste = 53, --Increases attack speed + --54 and 55 didn't have names and seem to be unused + ReducedDurabilityLoss = 56, --Reduces durability loss + IncreasedSpiritbondGain = 57, --Increases rate of spiritbonding + Damage = 58, --Increases damage of auto attacks + Delay = 59, --Increases rate of auto attacks + Fastcast = 60, --Increases speed of casts + MovementSpeed = 61, --Increases movement speed + Exp = 62, --Increases experience gained + RestingHp = 63, --? + RestingMp = 64, --? - DamageTakenDown = 62, -- Percent damage taken down - StoreTP = 63, --.1% extra tp per point. Lancer trait is 50 StoreTP - PhysicalCritRate = 64, --CritRating but only for physical attacks. Increases chance of critting. - PhysicalCritEvasion = 65, --Opposite of CritRating. Reduces chance of being crit by phyiscal attacks - PhysicalCritAttack = 66, --Increases damage done by Physical Critical hits - PhysicalCritResilience = 67, --Decreases damage taken by Physical Critical hits - Parry = 68, --Increases chance to parry - MagicCritPotency = 69, --Increases - Regain = 70, --TP regen, should be -90 out of combat, Invigorate sets to 100+ depending on traits - RegenDown = 71, --Damage over time effects. Separate from normal Regen because of how they are displayed in game - Stoneskin = 72, --Nullifies damage - MinimumTpLock = 73, --Don't let TP fall below this, used in openings - KnockbackImmune = 74 --Immune to knockback effects when above 0 + --Attack property resistances + SlashingResistance = 65, --Reduces damage taken by slashing attacks + PiercingResistance = 66, --Reduces damage taken by piercing attacks + BluntResistance = 67, --Reduces damage taken by blunt attacks + ProjectileResistance = 68, --Reduces damage taken by projectile attacks + SonicResistance = 69, --Reduces damage taken by sonic attacks + BreathResistance = 70, --Reduces damage taken by breath attacks + PhysicalResistance = 71, --Reduces damage taken by physical attacks + MagicResistance = 72, --Reduces damage taken by magic attacks + + --Status resistances + SlowResistance = 73, --Reduces chance to be inflicted with slow by status magic + PetrificationResistance = 74, --Reduces chance to be inflicted with petrification by status magic + ParalysisResistance = 75, --Reduces chance to be inflicted with paralysis by status magic + SilenceResistance = 76, --Reduces chance to be inflicted with silence by status magic + BlindResistance = 77, --Reduces chance to be inflicted with blind by status magic + PoisonResistance = 78, --Reduces chance to be inflicted with poison by status magic + StunResistance = 79, --Reduces chance to be inflicted with stun by status magic + SleepResistance = 80, --Reduces chance to be inflicted with sleep by status magic + BindResistance = 81, --Reduces chance to be inflicted with bind by status magic + HeavyResistance = 82, --Reduces chance to be inflicted with heavy by status magic + DoomResistance = 83, --Reduces chance to be inflicted with doom by status magic + + --84-101 didn't have names and seem to be unused + --Miscellaneous + ConserveMp = 101, --Chance to reduce mp used by actions + SpellInterruptResistance = 102, --Reduces chance to be interrupted by damage while casting + DoubleDownOdds = 103, --Increases double down odds + HqDiscoveryRate = 104, + + + --Non-gear mods + None = 105, + NAMEPLATE_SHOWN = 106, + TARGETABLE = 107, + NAMEPLATE_SHOWN2 = 108, + + HpPercent = 109, + MpPercent = 110, + TpPercent = 111, + + AttackRange = 112, --How far away in yalms this character can attack from (probably won't need this when auto attack skills are done) + + Raise = 113, + MinimumHpLock = 114, --Stops HP from falling below this value + MinimumMpLock = 115, --Stops MP from falling below this value + MinimumTpLock = 116, --Stops TP from falling below this value + AttackType = 117, --Attack property of auto attacks (might not need this when auto attack skills are done, unsure) + CanBlock = 118, --Whether the character can block attacks. (For players this is only true when they have a shield) + HitCount = 119, --Amount of hits in an auto attack. Usually 1, 2 for h2h, 3 with spinning heel + + --Flat percent increases to these rates. Might not need these? + RawEvadeRate = 120, + RawParryRate = 121, + RawBlockRate = 122, + RawResistRate = 123, + RawHitRate = 124, + RawCritRate = 125, + + DamageTakenDown = 126, --Percent damage taken down + Regain = 127, --TP regen, should be -90 out of combat, Invigorate sets to 100+ depending on traits + RegenDown = 128, --Damage over time effects. Separate from normal Regen because of how they are displayed in game + Stoneskin = 129, --Nullifies damage + KnockbackImmune = 130, --Immune to knockback effects when above 0 + Stealth = 131, } mobModifiersGlobal = diff --git a/sql/server_battle_commands.sql b/sql/server_battle_commands.sql index 3dc81887..3dd1b654 100644 --- a/sql/server_battle_commands.sql +++ b/sql/server_battle_commands.sql @@ -1,8 +1,8 @@ --- MySQL dump 10.13 Distrib 5.7.11, for Win64 (x86_64) +-- MySQL dump 10.13 Distrib 5.7.23, for Win64 (x86_64) -- -- Host: localhost Database: ffxiv_server -- ------------------------------------------------------ --- Server version 5.7.11 +-- Server version 5.7.23 /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; @@ -28,8 +28,8 @@ CREATE TABLE `server_battle_commands` ( `classJob` tinyint(3) unsigned NOT NULL, `lvl` tinyint(3) unsigned NOT NULL, `requirements` smallint(5) unsigned NOT NULL, - `mainTarget` tinyint(3) unsigned NOT NULL, - `validTarget` tinyint(3) unsigned NOT NULL, + `mainTarget` smallint(5) unsigned NOT NULL, + `validTarget` smallint(5) unsigned NOT NULL, `aoeType` tinyint(3) unsigned NOT NULL, `aoeRange` float NOT NULL DEFAULT '0', `aoeMinRange` float NOT NULL DEFAULT '0', @@ -79,157 +79,157 @@ CREATE TABLE `server_battle_commands` ( LOCK TABLES `server_battle_commands` WRITE; /*!40000 ALTER TABLE `server_battle_commands` DISABLE KEYS */; set autocommit=0; -INSERT INTO `server_battle_commands` VALUES (23456,'breath_of_the_lion',0,1,0,1,32,2,12,0,0.5,0,1,100,1,0,0,0,0,0,10,2,0,0,0,11,3500,10,0,0,19,0,1,3,318771200,0,0,0,3,0,30301,2,2,9,1); -INSERT INTO `server_battle_commands` VALUES (23457,'voice_of_the_lion',0,1,0,1,32,3,20,0,0,0,1,100,1,0,0,0,0,0,10,2,0,0,0,11,3500,10,0,0,19,0,2,3,318775296,0,0,0,3,0,30301,2,2,9,1); -INSERT INTO `server_battle_commands` VALUES (23458,'breath_of_the_dragon',0,1,0,1,32,2,12,0,0.666667,0.25,1,100,1,0,0,0,0,0,10,2,0,0,0,11,3500,10,0,0,19,0,3,3,318779392,0,0,0,3,0,30301,2,2,9,1); -INSERT INTO `server_battle_commands` VALUES (23459,'voice_of_the_dragon',0,1,0,1,32,1,22,15,2,0,1,100,1,0,0,0,0,0,10,2,0,0,0,11,3500,10,0,0,19,0,4,3,318783488,0,0,0,3,0,30301,2,2,9,1); -INSERT INTO `server_battle_commands` VALUES (23460,'breath_of_the_ram',0,1,0,1,32,2,12,0,0.666667,-0.25,1,100,1,0,0,0,0,0,10,2,0,0,0,11,3500,10,0,0,19,0,5,3,318787584,0,0,0,3,0,30301,2,2,9,1); -INSERT INTO `server_battle_commands` VALUES (23461,'voice_of_the_ram',0,1,0,1,32,1,10,0,2,0,1,100,1,0,0,0,0,0,10,2,0,0,0,11,3500,10,0,0,19,0,6,3,318791680,0,0,0,3,0,30301,2,2,9,1); -INSERT INTO `server_battle_commands` VALUES (23462,'dissent_of_the_bat',0,1,0,1,32,2,16,0,0.66667,0,1,100,1,0,0,0,0,0,10,2,0,0,0,11,3500,10,0,0,19,0,7,3,318795776,0,0,0,3,0,30301,2,2,9,1); -INSERT INTO `server_battle_commands` VALUES (23463,'chaotic_chorus',0,1,0,1,32,1,16,0,2,0,1,100,1,0,0,0,0,0,10,2,0,0,0,11,3500,10,0,0,19,0,8,3,318799872,0,0,0,3,0,30301,2,2,9,1); -INSERT INTO `server_battle_commands` VALUES (23464,'the_scorpions_sting',0,1,0,1,32,2,12,0,0.5,1,1,100,1,0,0,0,0,0,10,2,0,0,0,11,3500,10,0,0,19,0,9,3,318803968,0,0,0,3,0,30301,2,2,9,1); -INSERT INTO `server_battle_commands` VALUES (27100,'second_wind',2,6,3,1,1,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,0,0,0,0,0,45,0,0,14,519,2,3,234889735,0,0,0,0,0,30320,3,3,13,0); -INSERT INTO `server_battle_commands` VALUES (27101,'blindside',2,14,3,1,1,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223237,60,1,0,0,60,0,0,14,635,2,3,234889851,0,0,0,0,0,30328,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27102,'taunt',2,42,4,32,32,0,0,0,0,0,0,100,1,0,0,15,0,0,10,2,223073,5,1,0,0,60,0,0,14,517,2,3,234889733,0,0,0,0,0,30328,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27103,'featherfoot',2,2,3,1,1,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223075,30,1,0,0,60,0,0,14,535,2,3,234889751,0,0,0,0,0,30328,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27104,'fists_of_fire',2,34,4,1,1,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223209,4294967295,1,0,0,10,0,0,14,684,2,3,234889900,0,0,0,0,0,30328,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27105,'fists_of_earth',2,22,4,1,1,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223210,4294967295,1,0,0,10,0,0,14,685,2,3,234889901,0,0,0,0,0,30328,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27106,'hundred_fists',15,50,0,1,1,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223244,15,1,0,0,900,0,0,14,712,2,3,234889928,0,0,0,0,0,30328,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27107,'spinning_heel',15,35,0,1,1,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223245,20,1,0,0,120,0,0,14,718,2,3,234889934,0,0,0,0,0,30328,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27108,'shoulder_tackle',15,30,0,32,32,0,0,0,0,0,0,100,1,0,0,15,0,0,10,2,223015,10,0.75,0,0,60,0,0,18,1048,205,3,302830616,0,0,0,0,0,30301,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27109,'fists_of_wind',15,40,0,1,1,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223211,4294967295,1,0,0,10,0,0,14,720,2,3,234889936,0,0,0,0,0,30328,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27110,'pummel',2,1,1,32,32,0,0,0,0,0,0,100,1,1,0,5,0,0,10,2,0,0,0,0,0,10,0,1000,18,1027,1,3,301995011,0,27111,27113,1,0,30301,2,1,3,0); -INSERT INTO `server_battle_commands` VALUES (27111,'concussive_blow',2,10,1,32,32,0,0,0,0,0,0,100,1,4,0,5,0,0,10,2,223007,30,0,0,0,30,0,1500,18,20,3,3,302002196,0,27112,0,2,0,30301,2,1,3,0); -INSERT INTO `server_battle_commands` VALUES (27112,'simian_thrash',2,50,4,32,32,0,0,0,0,0,0,100,9,0,0,5,0,0,10,2,0,0,0,0,0,80,0,2000,18,1003,202,3,302818283,0,0,0,3,0,30301,2,1,3,0); -INSERT INTO `server_battle_commands` VALUES (27113,'aura_pulse',2,38,4,32,32,1,8,0,0,0,1,100,1,0,0,5,0,0,10,2,223003,30,0,0,0,40,0,1500,18,66,203,3,302821442,0,0,0,2,0,30301,2,1,3,0); -INSERT INTO `server_battle_commands` VALUES (27114,'pounce',2,4,4,32,32,0,0,0,0,0,0,100,1,2,0,5,0,0,10,2,223015,10,0,0,0,20,0,1500,18,8,3,3,302002184,0,27115,27117,1,0,30301,2,1,3,0); -INSERT INTO `server_battle_commands` VALUES (27115,'demolish',2,30,1,32,32,0,0,0,0,0,0,100,1,0,0,5,0,0,10,2,0,0,0,0,0,30,0,1500,18,1028,2,3,301999108,0,27116,0,2,0,30301,2,1,3,0); -INSERT INTO `server_battle_commands` VALUES (27116,'howling_fist',2,46,4,32,32,0,0,0,0,0,0,100,1,4,0,5,0,0,10,2,0,0,0,0,0,80,0,3000,18,1029,2,3,301999109,0,0,0,3,0,30301,2,1,3,0); -INSERT INTO `server_battle_commands` VALUES (27117,'sucker_punch',2,26,1,32,32,0,0,0,0,0,0,100,1,4,0,5,0,0,10,2,0,0,0,0,0,15,0,1000,18,73,3,3,302002249,0,0,0,3,0,30301,2,1,3,0); -INSERT INTO `server_battle_commands` VALUES (27118,'dragon_kick',15,45,0,32,32,0,0,0,0,0,0,100,1,0,0,5,0,0,10,2,223013,10,0,0,0,60,0,2000,18,1041,204,3,302826513,0,0,0,0,0,30301,2,1,3,0); -INSERT INTO `server_battle_commands` VALUES (27119,'haymaker',2,18,4,32,32,0,0,0,0,0,0,100,1,0,2,5,0,0,10,2,223015,10,0.75,0,0,5,0,250,18,23,201,3,302813207,0,0,0,0,0,30301,2,1,3,0); -INSERT INTO `server_battle_commands` VALUES (27140,'sentinel',3,22,3,1,1,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223062,15,1,0,0,90,0,0,14,526,2,3,234889742,0,0,0,0,0,30328,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27141,'aegis_boon',3,6,8,1,1,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223058,30,1,0,0,60,0,0,14,583,21,3,234967623,0,0,0,0,0,30328,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27142,'rampart',3,2,3,1,5,0,8,0,0,0,1,100,1,0,0,0,0,0,10,2,223064,60,1,0,0,120,0,0,14,536,2,3,234889752,0,0,0,0,0,30328,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27143,'tempered_will',3,42,8,1,1,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223068,20,1,0,0,180,0,0,14,515,2,3,234889731,0,0,0,0,0,30328,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27144,'outmaneuver',3,34,8,1,1,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223236,30,1,0,0,90,0,0,14,512,21,3,234967552,0,0,0,0,0,30328,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27145,'flash',3,14,3,32,32,0,8,0,0,0,0,100,1,0,0,15,0,0,10,2,223007,10,0,0,0,30,0,0,14,696,2,3,234889912,0,0,0,0,0,30101,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27146,'cover',16,30,0,12,12,0,0,0,0,0,0,100,1,0,0,15,0,0,10,2,223173,15,1,0,0,60,0,0,14,725,2,3,234889941,0,0,0,0,0,30328,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27147,'divine_veil',16,35,0,1,1,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223248,20,1,0,0,60,0,0,14,713,2,3,234889929,0,0,0,0,0,30328,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27148,'hallowed_ground',16,50,0,1,1,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223249,20,1,0,0,900,0,0,14,709,2,3,234889925,0,0,0,0,0,30328,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27149,'holy_succor',16,40,0,9,9,0,0,0,0,0,0,100,1,0,0,15,0,0,10,2,0,0,0,3,2000,10,100,0,1,701,1,3,16782013,0,0,0,0,0,30328,3,3,13,0); -INSERT INTO `server_battle_commands` VALUES (27150,'fast_blade',3,1,1,32,32,0,0,0,0,0,0,100,1,1,0,5,0,0,10,2,0,0,0,0,0,10,0,1000,18,1023,1,3,301995007,0,27151,27152,1,0,30301,2,1,1,0); -INSERT INTO `server_battle_commands` VALUES (27151,'flat_blade',3,26,1,32,32,0,0,0,0,0,0,100,1,0,0,5,0,0,10,2,0,0,0,0,0,10,0,1500,18,1024,2,3,301999104,0,0,0,2,0,30301,2,1,1,0); -INSERT INTO `server_battle_commands` VALUES (27152,'savage_blade',3,10,1,32,32,0,0,0,0,0,0,100,1,0,0,5,0,0,10,2,0,0,0,0,0,30,0,1000,18,1025,1,3,301995009,0,27153,0,2,0,30301,2,1,1,0); -INSERT INTO `server_battle_commands` VALUES (27153,'goring_blade',3,50,8,32,32,0,0,0,0,0,0,100,1,2,0,5,0,0,10,2,223206,30,0,0,0,60,0,3000,18,1026,301,3,303223810,0,0,0,3,0,30301,2,1,1,0); -INSERT INTO `server_battle_commands` VALUES (27154,'riot_blade',3,30,8,32,32,0,0,0,0,0,0,100,1,2,0,15,0,0,10,2,223038,30,0,0,0,80,0,2000,18,75,2,3,301998155,0,27155,0,1,0,30301,2,1,1,1); -INSERT INTO `server_battle_commands` VALUES (27155,'rage_of_halone',3,46,8,32,32,0,0,0,0,0,0,100,5,0,0,5,0,0,10,2,0,0,0,0,0,20,0,1500,18,1008,302,3,303227888,0,0,0,2,-40,30301,2,1,1,0); -INSERT INTO `server_battle_commands` VALUES (27156,'shield_bash',3,18,17,32,32,0,0,0,0,0,0,100,1,0,0,5,0,0,10,2,223015,5,0.75,0,0,30,0,250,18,5,26,3,302096389,0,0,0,0,0,30301,2,1,1,0); -INSERT INTO `server_battle_commands` VALUES (27157,'war_drum',3,38,24,32,32,1,8,0,0,0,1,100,1,0,4,5,0,0,10,2,0,0,0,0,0,60,0,500,14,502,21,3,234967542,0,0,0,0,0,30301,2,1,1,0); -INSERT INTO `server_battle_commands` VALUES (27158,'phalanx',3,4,8,32,32,0,0,0,0,0,0,100,1,0,4,5,0,0,10,2,0,0,0,0,0,5,0,250,18,32,1,3,301994016,0,27159,0,1,0,30301,2,1,1,0); -INSERT INTO `server_battle_commands` VALUES (27159,'spirits_within',16,45,0,32,32,0,0,0,0,0,0,100,1,0,0,5,0,0,10,2,0,0,0,0,0,60,0,3000,18,1044,304,3,303236116,0,0,0,2,50,30301,2,1,1,0); -INSERT INTO `server_battle_commands` VALUES (27180,'provoke',4,14,3,32,32,0,0,0,0,0,0,100,1,0,0,15,0,0,10,2,223034,30,0,0,0,30,0,0,14,600,2,3,234889816,0,0,0,0,0,30101,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27181,'foresight',4,2,3,1,1,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223083,30,1,0,0,60,0,0,14,545,2,3,234889761,0,0,0,0,0,30328,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27182,'bloodbath',4,6,3,1,1,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223081,30,1,0,0,60,0,0,14,581,2,3,234889797,0,0,0,0,0,30328,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27183,'berserk',4,22,32,1,1,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223207,4294967295,1,0,0,10,0,0,14,682,2,3,234889898,0,0,0,0,0,30328,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27184,'rampage',4,34,32,1,1,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223208,4294967295,1,0,0,10,0,0,14,546,2,3,234889762,0,0,0,0,0,30328,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27185,'enduring_march',4,42,32,1,1,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223078,20,1,0,0,180,0,0,14,539,2,3,234889755,0,0,0,0,0,30328,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27186,'vengeance',17,30,0,1,1,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223250,15,1,0,0,150,0,0,14,714,2,3,234889930,0,0,0,0,0,30328,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27187,'antagonize',17,35,0,1,1,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223251,15,1,0,0,120,0,0,14,715,2,3,234889931,0,0,0,0,0,30328,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27188,'collusion',17,40,0,12,12,0,0,0,0,0,0,100,1,0,0,15,0,0,10,2,223097,15,1,0,0,90,0,0,14,711,2,3,234889927,0,0,0,0,0,30328,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27189,'mighty_strikes',17,50,0,1,1,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223252,15,1,0,0,900,0,0,14,716,2,3,234889932,0,0,0,0,0,30328,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27190,'heavy_swing',4,1,1,32,32,0,0,0,0,0,0,100,1,1,0,5,0,0,10,2,0,0,0,0,0,10,0,1000,18,14,1,3,301993998,0,27191,0,1,0,30301,2,1,1,0); -INSERT INTO `server_battle_commands` VALUES (27191,'skull_sunder',4,10,1,32,32,0,0,0,0,0,0,100,1,0,0,5,0,0,10,2,0,0,0,0,0,30,0,1500,18,43,1,3,301994027,0,27192,0,2,0,30301,2,1,1,0); -INSERT INTO `server_battle_commands` VALUES (27192,'steel_cyclone',17,45,0,32,32,1,8,0,0,0,1,100,1,0,0,5,0,0,10,2,223015,3,0,0,0,30,0,2000,18,1040,404,3,303645712,0,0,0,3,0,30301,2,1,1,0); -INSERT INTO `server_battle_commands` VALUES (27193,'brutal_swing',4,4,1,32,32,0,0,0,0,0,0,100,1,4,0,5,0,0,10,2,0,0,0,0,0,20,0,1500,18,15,3,3,302002191,0,27194,0,1,0,30301,2,1,1,0); -INSERT INTO `server_battle_commands` VALUES (27194,'maim',4,26,1,32,32,0,0,0,0,0,0,100,1,0,0,5,0,0,10,2,0,0,0,0,0,30,0,1500,18,88,1,3,301994072,0,27195,0,2,0,30301,2,1,1,0); -INSERT INTO `server_battle_commands` VALUES (27195,'godsbane',4,50,32,32,32,0,0,0,0,0,0,100,3,0,0,5,0,0,10,2,0,0,0,0,0,60,0,3000,18,1014,402,3,303637494,0,0,0,3,0,30301,2,1,1,0); -INSERT INTO `server_battle_commands` VALUES (27196,'path_of_the_storm',4,38,32,32,32,0,0,0,0,0,0,100,1,2,0,5,0,0,10,2,228021,30,0,0,0,30,0,1500,18,44,401,3,303632428,0,27197,0,1,0,30301,2,1,1,0); -INSERT INTO `server_battle_commands` VALUES (27197,'whirlwind',4,46,32,32,32,1,8,0,0,0,1,100,1,0,0,5,0,0,10,2,0,0,0,0,0,80,0,3000,18,1015,403,3,303641591,0,0,0,2,0,30301,2,1,1,0); -INSERT INTO `server_battle_commands` VALUES (27198,'fracture',4,18,32,32,32,0,0,0,0,0,0,100,1,0,3,5,0,0,10,2,223013,8,0.75,0,0,40,0,500,18,42,3,3,302002218,0,0,0,0,0,30301,2,1,1,0); -INSERT INTO `server_battle_commands` VALUES (27199,'overpower',4,30,1,32,32,2,8,0,0.5,0,1,100,1,0,3,8,0,0,10,2,0,0,0,0,0,5,0,250,18,89,1,3,301994073,0,0,0,0,0,30301,2,1,1,0); -INSERT INTO `server_battle_commands` VALUES (27220,'hawks_eye',7,6,3,1,1,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223106,15,1,0,0,90,0,0,14,516,2,3,234889732,0,0,0,0,0,30328,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27221,'quelling_strike',7,22,3,1,1,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223104,30,1,0,0,60,0,0,14,614,2,3,234889830,0,0,0,0,0,30328,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27222,'decoy',7,2,3,1,1,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223108,60,1,0,0,90,100,0,14,565,2,3,234889781,0,0,0,0,0,30328,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27223,'chameleon',7,42,3,1,1,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,0,0,0,0,0,180,0,0,14,504,2,3,234889720,0,0,0,0,0,30328,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27224,'barrage',7,34,64,1,1,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223220,60,1,0,0,90,0,0,14,683,2,3,234889899,0,0,0,0,0,30328,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27225,'raging_strike',7,14,64,1,1,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223221,4294967295,1,0,0,10,0,0,14,632,2,3,234889848,0,0,0,0,0,30328,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27226,'swiftsong',7,26,64,1,5,1,20,0,0,0,1,100,1,0,0,0,0,0,10,2,223224,180,1,0,0,10,100,0,1,150,1,3,16781462,0,0,0,0,0,30328,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27227,'battle_voice',18,50,0,1,5,1,20,0,0,0,1,100,1,0,0,0,0,0,10,2,223029,60,1,0,0,900,0,0,14,721,2,3,234889937,0,0,0,0,0,30328,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27228,'heavy_shot',7,1,1,32,32,0,0,0,0,0,0,100,1,0,0,20,0,8,10,2,0,0,0,0,0,10,0,1000,18,1036,4,3,302007308,0,27229,27231,1,0,30301,2,1,4,1); -INSERT INTO `server_battle_commands` VALUES (27229,'leaden_arrow',7,10,1,32,32,0,0,0,0,0,0,100,1,0,0,20,0,0,10,2,228021,30,0.75,0,0,30,0,1500,18,1035,4,3,302007307,0,27230,0,2,0,30301,2,1,4,1); -INSERT INTO `server_battle_commands` VALUES (27230,'wide_volley',7,50,64,32,32,1,8,0,0,0,0,100,1,0,0,20,0,0,10,2,0,0,0,0,0,80,0,2000,18,18,703,3,304869394,0,0,0,3,-20,30301,2,1,4,1); -INSERT INTO `server_battle_commands` VALUES (27231,'quick_nock',7,38,64,32,32,2,10,0,0.5,0,1,100,1,0,0,10,0,0,10,2,0,0,0,0,0,180,0,1000,18,1017,702,3,304866297,0,27232,0,2,0,30301,2,1,4,1); -INSERT INTO `server_battle_commands` VALUES (27232,'rain_of_death',18,45,0,32,32,1,8,0,0,0,0,100,1,0,0,20,0,0,10,2,223015,5,0.75,0,0,30,0,3000,18,1037,704,3,304874509,0,0,0,3,0,30301,2,1,4,1); -INSERT INTO `server_battle_commands` VALUES (27233,'piercing_arrow',7,4,1,32,32,0,0,0,0,0,0,100,1,0,0,20,0,8,10,2,0,0,0,0,0,20,0,1000,18,1038,1,3,301995022,0,27234,27236,1,0,30301,2,1,4,1); -INSERT INTO `server_battle_commands` VALUES (27234,'gloom_arrow',7,30,1,32,32,0,0,0,0,0,0,100,1,0,0,20,0,0,10,2,223007,30,0,0,0,10,0,1000,18,1039,4,3,302007311,0,27235,0,2,0,30301,2,1,4,1); -INSERT INTO `server_battle_commands` VALUES (27235,'bloodletter',7,46,64,32,32,0,0,0,0,0,0,100,1,0,0,20,0,0,10,2,223241,30,0.75,0,0,80,0,1500,18,53,701,3,304861237,0,0,0,3,0,30301,2,1,4,1); -INSERT INTO `server_battle_commands` VALUES (27236,'shadowbind',7,18,64,32,32,0,0,0,0,0,0,100,1,0,0,20,0,0,10,2,228011,15,0.9,0,0,40,0,250,18,17,4,3,302006289,0,0,0,2,0,30301,2,1,4,1); -INSERT INTO `server_battle_commands` VALUES (27237,'ballad_of_magi',18,30,0,1,5,1,20,0,0,0,1,100,1,0,0,0,0,0,10,2,223254,180,1,8,3000,10,100,0,1,709,1,3,16782021,0,0,0,0,0,30328,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27238,'paeon_of_war',18,40,0,1,5,1,20,0,0,0,1,100,1,0,0,0,0,0,10,2,223255,180,1,8,3000,10,50,1000,1,710,1,3,16782022,0,0,0,0,0,30328,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27239,'minuet_of_rigor',18,35,0,1,5,1,20,0,0,0,1,100,1,0,0,0,0,0,10,2,223256,180,1,8,3000,10,100,0,1,711,1,3,16782023,0,0,0,0,0,30328,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27258,'refill',7,1,0,1,1,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,32613,3,0,0,0); -INSERT INTO `server_battle_commands` VALUES (27259,'light_shot',7,1,0,32,32,0,0,0,0,0,0,100,1,0,0,20,0,0,10,2,0,0,0,0,0,0,0,0,17,0,1,3,285216768,0,0,0,0,0,30301,3,1,0,1); -INSERT INTO `server_battle_commands` VALUES (27260,'invigorate',8,14,3,1,1,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223094,30,1,0,0,90,0,0,14,575,2,3,234889791,0,0,0,0,0,30328,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27261,'power_surge',8,34,128,1,1,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223212,60,1,0,0,10,0,0,14,686,2,3,234889902,0,0,0,0,0,30328,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27262,'life_surge',8,22,128,1,1,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223215,180,1,0,0,15,0,250,14,687,2,3,234889903,0,0,0,0,0,30328,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27263,'dread_spike',8,42,128,1,1,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223218,30,1,0,0,120,0,0,14,686,2,3,234889902,0,0,0,0,0,30328,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27264,'blood_for_blood',8,6,3,1,1,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223219,60,1,0,0,60,0,0,14,689,2,3,234889905,0,0,0,0,0,30328,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27265,'keen_flurry',8,26,3,1,1,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223091,30,1,0,0,90,0,0,14,569,2,3,234889785,0,0,0,0,0,30328,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27266,'jump',19,30,0,32,32,0,0,0,0,0,0,100,1,0,0,20,0,0,10,2,0,0,0,0,0,60,0,0,18,1045,804,3,305284117,0,0,0,0,0,30301,3,1,2,0); -INSERT INTO `server_battle_commands` VALUES (27267,'elusive_jump',19,40,0,1,1,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,0,0,0,0,0,180,0,0,18,1046,806,3,305292310,0,0,0,0,0,30101,3,0,0,0); -INSERT INTO `server_battle_commands` VALUES (27268,'dragonfire_dive',19,50,0,32,32,1,4,0,0,0,0,100,1,0,0,20,0,0,10,2,0,0,0,0,0,900,0,0,18,1045,804,3,305284117,0,0,0,0,0,30301,3,2,5,0); -INSERT INTO `server_battle_commands` VALUES (27269,'true_thrust',8,1,1,32,32,0,0,0,0,0,0,100,1,1,0,5,0,0,10,2,0,0,0,0,0,10,0,1000,18,1030,2,3,301999110,0,27270,27273,1,0,30301,2,1,2,0); -INSERT INTO `server_battle_commands` VALUES (27270,'leg_sweep',8,30,1,32,32,2,8,0,0.5,0,1,100,1,0,0,5,0,0,10,2,223015,8,0,0,0,30,0,1000,18,37,1,3,301994021,0,27271,0,2,0,30301,2,1,2,0); -INSERT INTO `server_battle_commands` VALUES (27271,'doom_spike',8,46,128,32,32,3,5,0,0,0,1,100,1,0,0,5,0,0,10,2,0,0,0,0,0,60,0,3000,18,83,801,3,305270867,0,0,0,3,0,30301,2,1,2,0); -INSERT INTO `server_battle_commands` VALUES (27272,'disembowel',19,35,0,32,32,0,0,0,0,0,0,100,1,0,0,5,0,0,10,2,223005,15,0.75,0,0,30,0,750,18,1042,2,3,301999122,0,0,0,0,0,30301,2,1,2,0); -INSERT INTO `server_battle_commands` VALUES (27273,'heavy_thrust',8,10,1,32,32,0,0,0,0,0,0,100,1,0,0,5,0,0,10,2,223015,4,0.75,0,0,20,0,1500,18,1031,1,3,301995015,0,0,0,0,0,30301,2,1,2,0); -INSERT INTO `server_battle_commands` VALUES (27274,'vorpal_thrust',8,2,1,32,32,0,0,0,0,0,0,100,1,2,0,5,0,0,10,2,0,0,0,0,0,20,0,1500,18,1032,2,3,301999112,0,27275,0,1,0,30301,2,1,2,0); -INSERT INTO `server_battle_commands` VALUES (27275,'impulse_drive',8,18,1,32,32,0,0,0,0,0,0,100,1,4,0,5,0,0,10,2,0,0,0,0,0,30,0,1500,18,1033,2,3,301999113,0,27276,27277,2,0,30301,2,1,2,0); -INSERT INTO `server_battle_commands` VALUES (27276,'chaos_thrust',8,50,128,32,32,0,0,0,0,0,0,100,6,0,0,5,0,0,10,2,0,0,0,0,0,80,0,3000,18,40,802,3,305274920,0,0,0,3,0,30301,2,1,2,0); -INSERT INTO `server_battle_commands` VALUES (27277,'ring_of_talons',19,45,0,32,32,1,8,0,0,0,1,100,1,0,0,5,0,0,10,2,0,0,0,0,0,60,0,2000,18,1009,803,3,305279985,0,0,0,3,0,30301,2,1,2,0); -INSERT INTO `server_battle_commands` VALUES (27278,'feint',8,4,1,32,32,0,0,0,0,0,0,100,1,0,1,5,0,0,10,2,0,0,0,0,0,10,0,250,18,39,2,3,301998119,0,27272,0,1,100,30301,2,1,2,0); -INSERT INTO `server_battle_commands` VALUES (27279,'full_thrust',8,38,128,32,32,0,0,0,0,0,0,100,1,0,1,5,0,0,10,2,0,0,0,0,0,30,0,250,18,1034,801,3,305271818,0,0,0,0,50,30301,2,1,2,0); -INSERT INTO `server_battle_commands` VALUES (27300,'dark_seal',22,14,3,1,1,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223229,30,1,0,0,90,0,0,14,518,2,3,234889734,0,0,0,0,0,30328,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27301,'resonance',22,22,3,1,1,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223230,30,1,0,0,90,0,0,14,669,2,3,234889885,0,0,0,0,0,30328,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27302,'excruciate',22,38,256,1,1,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223231,30,1,0,0,90,0,0,14,694,2,3,234889910,0,0,0,0,0,30328,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27303,'necrogenesis',22,6,3,1,1,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223232,30,1,0,0,90,0,0,14,695,2,3,234889911,0,0,0,0,0,30328,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27304,'parsimony',22,2,256,1,1,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223233,30,1,0,0,90,0,0,14,568,2,3,234889784,0,0,0,0,0,30328,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27305,'convert',26,30,0,1,1,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,0,0,0,0,0,450,0,0,14,724,2,3,234889940,0,0,0,0,0,30101,3,0,0,0); -INSERT INTO `server_battle_commands` VALUES (27306,'sleep',22,42,256,32,32,0,0,0,0,0,0,100,1,0,0,20,0,0,10,2,228001,60,0.9,2,3000,0,75,0,1,651,1,3,16781963,0,0,0,0,0,30328,4,4,12,0); -INSERT INTO `server_battle_commands` VALUES (27307,'sanguine_rite',22,30,3,1,1,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223234,20,1,0,0,60,120,0,1,152,1,3,16781464,0,0,0,0,0,30328,4,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27308,'blizzard',22,4,256,32,32,0,0,0,0,0,0,100,1,0,0,20,0,0,10,2,228021,30,0.75,2,3000,10,90,0,1,502,1,3,16781814,0,0,0,0,0,30301,4,2,6,0); -INSERT INTO `server_battle_commands` VALUES (27309,'blizzara',22,26,256,32,32,1,8,0,0,0,0,100,1,0,0,20,0,0,10,2,228011,30,0.75,0,0,40,150,0,1,506,1,3,16781818,0,0,0,0,0,30301,4,2,6,0); -INSERT INTO `server_battle_commands` VALUES (27310,'fire',22,10,3,32,32,1,8,0,0,0,0,100,1,0,0,20,0,0,10,2,0,0,0,2,3000,8,105,0,1,501,1,3,16781813,0,27311,0,1,0,30301,4,2,5,0); -INSERT INTO `server_battle_commands` VALUES (27311,'fira',22,34,3,32,32,1,8,0,0,0,0,100,1,0,0,20,0,0,10,2,0,0,0,2,5000,16,180,0,1,504,1,3,16781816,0,27312,0,2,0,30301,4,2,5,0); -INSERT INTO `server_battle_commands` VALUES (27312,'firaga',22,50,256,32,32,1,8,0,0,0,0,100,1,0,0,20,0,0,10,2,0,0,0,2,8000,7,255,0,1,700,1,3,16782012,0,0,0,3,0,30301,4,2,5,0); -INSERT INTO `server_battle_commands` VALUES (27313,'thunder',22,1,3,32,32,0,0,0,0,0,0,100,1,0,0,20,0,0,10,2,0,0,0,2,2000,6,75,0,1,503,1,3,16781815,0,27314,0,1,0,30301,4,2,9,0); -INSERT INTO `server_battle_commands` VALUES (27314,'thundara',22,18,256,32,32,0,0,0,0,0,0,100,1,0,0,20,0,0,10,2,223015,4,0.75,0,0,30,135,0,1,508,1,3,16781820,0,27315,27316,2,0,30301,4,2,9,0); -INSERT INTO `server_battle_commands` VALUES (27315,'thundaga',22,46,256,32,32,0,0,0,0,0,0,100,1,0,0,20,0,0,10,2,0,0,0,2,5000,45,195,0,1,509,1,3,16781821,0,0,0,3,0,30301,4,2,9,0); -INSERT INTO `server_battle_commands` VALUES (27316,'burst',26,50,0,32,32,0,0,0,0,0,0,100,1,0,0,20,0,0,10,2,0,0,0,2,4000,900,90,0,1,705,1,3,16782017,0,0,0,3,0,30301,4,2,9,0); -INSERT INTO `server_battle_commands` VALUES (27317,'sleepga',26,45,0,32,32,1,8,0,0,0,0,100,1,0,0,20,0,0,10,2,228001,60,0.9,2,4000,0,100,0,1,704,1,3,16782016,0,0,0,0,0,30328,4,4,12,0); -INSERT INTO `server_battle_commands` VALUES (27318,'flare',26,40,0,1,32,1,8,0,0,0,1,100,1,0,0,20,0,0,10,2,223262,30,0.75,2,8000,120,200,0,1,706,1,3,16782018,0,0,0,0,0,30301,4,2,5,0); -INSERT INTO `server_battle_commands` VALUES (27319,'freeze',26,35,0,32,32,0,0,0,0,0,0,100,1,0,0,20,0,0,10,2,0,0,0,2,5000,120,120,0,1,707,1,3,16782019,0,0,0,0,0,30301,4,2,6,0); -INSERT INTO `server_battle_commands` VALUES (27340,'sacred_prism',23,34,3,1,1,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223225,60,1,0,0,90,0,0,14,690,2,3,234889906,0,0,0,0,0,30328,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27341,'shroud_of_saints',23,38,512,1,1,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223226,20,1,0,0,180,0,0,14,691,2,3,234889907,0,0,0,0,0,30328,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27342,'cleric_stance',23,10,512,1,1,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223227,4294967295,1,0,0,30,0,0,14,692,2,3,234889908,0,0,0,0,0,30328,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27343,'blissful_mind',23,14,512,1,1,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223228,4294967295,1,0,0,30,0,0,14,693,2,3,234889909,0,0,0,0,0,30328,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27344,'presence_of_mind',27,30,0,1,1,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223116,30,1,0,0,300,0,0,14,722,2,3,234889938,0,0,0,0,0,30328,3,4,0,0); -INSERT INTO `server_battle_commands` VALUES (27345,'benediction',27,50,0,1,5,1,20,0,0,0,1,100,1,0,0,0,0,0,10,2,0,0,0,0,0,900,0,0,14,723,2,3,234889939,0,0,0,0,0,30320,3,3,13,0); -INSERT INTO `server_battle_commands` VALUES (27346,'cure',23,2,3,9,9,0,0,0,0,0,0,100,1,0,0,20,0,0,10,2,0,0,0,3,2000,5,40,0,1,101,1,3,16781413,0,0,0,0,0,30320,4,3,13,0); -INSERT INTO `server_battle_commands` VALUES (27347,'cura',23,30,512,9,9,0,0,0,0,0,0,100,1,0,0,20,0,0,10,2,0,0,0,3,2000,5,100,0,1,103,1,3,16781415,0,0,0,0,0,30320,4,3,13,0); -INSERT INTO `server_battle_commands` VALUES (27348,'curaga',23,46,512,5,5,1,15,0,0,0,0,100,1,0,0,20,0,0,10,2,0,0,0,3,3000,10,150,0,1,146,1,3,16781458,0,0,0,0,0,30320,4,3,13,0); -INSERT INTO `server_battle_commands` VALUES (27349,'raise',23,18,512,130,130,0,0,0,0,0,0,100,1,0,0,20,0,0,10,2,0,0,0,3,10000,300,150,0,1,148,1,3,16781460,0,0,0,0,0,30101,4,4,11,0); -INSERT INTO `server_battle_commands` VALUES (27350,'stoneskin',23,26,3,9,9,0,0,0,0,0,0,100,1,0,0,20,0,0,10,2,223133,300,1,3,3000,30,50,0,1,133,1,3,16781445,0,0,0,0,0,30328,4,4,8,0); -INSERT INTO `server_battle_commands` VALUES (27351,'protect',23,6,3,5,5,1,20,0,0,0,0,100,1,0,0,20,0,0,10,2,223129,300,1,3,3000,30,80,0,1,1085,1,3,16782397,0,0,0,0,0,30328,4,4,11,0); -INSERT INTO `server_battle_commands` VALUES (27352,'repose',23,50,0,32,32,0,0,0,0,0,0,100,1,0,0,20,0,0,10,2,228001,60,0.9,3,3000,0,80,0,1,151,1,3,16781463,0,0,0,0,0,30328,4,4,10,0); -INSERT INTO `server_battle_commands` VALUES (27353,'aero',23,4,3,32,32,0,0,0,0,0,0,100,1,0,0,20,0,0,10,2,223235,20,0.75,3,3000,6,75,0,1,510,1,3,16781822,0,27354,0,1,0,30301,4,2,7,0); -INSERT INTO `server_battle_commands` VALUES (27354,'aerora',23,42,512,32,32,1,0,0,0,0,0,100,1,0,0,20,0,0,10,2,0,0,0,3,4000,20,150,0,1,511,1,3,16781823,0,0,0,2,0,30301,4,2,7,0); -INSERT INTO `server_battle_commands` VALUES (27355,'stone',23,1,3,32,32,0,0,0,0,0,0,100,1,0,0,20,0,0,10,2,223243,10,0.75,3,2000,6,75,0,1,513,1,3,16781825,0,27356,0,1,0,30301,4,2,8,0); -INSERT INTO `server_battle_commands` VALUES (27356,'stonera',23,22,512,32,32,1,0,0,0,0,0,100,1,0,0,20,0,0,10,2,228021,30,0.75,3,3000,30,150,0,1,514,1,3,16781826,0,0,0,2,0,30301,4,2,8,0); -INSERT INTO `server_battle_commands` VALUES (27357,'esuna',27,40,0,9,9,0,0,0,0,0,0,100,1,0,0,20,0,0,10,2,0,0,0,3,2000,10,40,0,1,702,1,3,16782014,0,0,0,0,0,30329,4,0,13,0); -INSERT INTO `server_battle_commands` VALUES (27358,'regen',27,35,0,9,9,0,0,0,0,0,0,100,1,0,0,20,0,0,10,2,223180,45,1,3,2000,5,20,0,1,703,1,3,16782015,0,0,0,0,0,30328,4,4,13,0); -INSERT INTO `server_battle_commands` VALUES (27359,'holy',27,45,0,1,32,1,8,0,0,0,1,100,1,0,0,0,0,0,10,2,228011,10,0.9,0,0,300,100,0,1,708,1,3,16782020,0,0,0,0,0,30301,4,2,11,0); +INSERT INTO `server_battle_commands` VALUES (23456,'breath_of_the_lion',0,1,0,31,17152,2,12,0,0.5,0,1,100,1,0,0,0,0,0,10,2,0,0,0,11,3500,10,0,0,19,0,1,3,318771200,0,0,0,3,0,30301,2,2,9,1); +INSERT INTO `server_battle_commands` VALUES (23457,'voice_of_the_lion',0,1,0,31,17152,3,20,0,0,0,1,100,1,0,0,0,0,0,10,2,0,0,0,11,3500,10,0,0,19,0,2,3,318775296,0,0,0,3,0,30301,2,2,9,1); +INSERT INTO `server_battle_commands` VALUES (23458,'breath_of_the_dragon',0,1,0,31,17152,2,12,0,0.666667,0.25,1,100,1,0,0,0,0,0,10,2,0,0,0,11,3500,10,0,0,19,0,3,3,318779392,0,0,0,3,0,30301,2,2,9,1); +INSERT INTO `server_battle_commands` VALUES (23459,'voice_of_the_dragon',0,1,0,31,17152,1,22,15,2,0,1,100,1,0,0,0,0,0,10,2,0,0,0,11,3500,10,0,0,19,0,4,3,318783488,0,0,0,3,0,30301,2,2,9,1); +INSERT INTO `server_battle_commands` VALUES (23460,'breath_of_the_ram',0,1,0,31,17152,2,12,0,0.666667,-0.25,1,100,1,0,0,0,0,0,10,2,0,0,0,11,3500,10,0,0,19,0,5,3,318787584,0,0,0,3,0,30301,2,2,9,1); +INSERT INTO `server_battle_commands` VALUES (23461,'voice_of_the_ram',0,1,0,31,17152,1,10,0,2,0,1,100,1,0,0,0,0,0,10,2,0,0,0,11,3500,10,0,0,19,0,6,3,318791680,0,0,0,3,0,30301,2,2,9,1); +INSERT INTO `server_battle_commands` VALUES (23462,'dissent_of_the_bat',0,1,0,31,17152,2,16,0,0.66667,0,1,100,1,0,0,0,0,0,10,2,0,0,0,11,3500,10,0,0,19,0,7,3,318795776,0,0,0,3,0,30301,2,2,9,1); +INSERT INTO `server_battle_commands` VALUES (23463,'chaotic_chorus',0,1,0,31,17152,1,16,0,2,0,1,100,1,0,0,0,0,0,10,2,0,0,0,11,3500,10,0,0,19,0,8,3,318799872,0,0,0,3,0,30301,2,2,9,1); +INSERT INTO `server_battle_commands` VALUES (23464,'the_scorpions_sting',0,1,0,31,17152,2,12,0,0.5,1,1,100,1,0,0,0,0,0,10,2,0,0,0,11,3500,10,0,0,19,0,9,3,318803968,0,0,0,3,0,30301,2,2,9,1); +INSERT INTO `server_battle_commands` VALUES (27100,'second_wind',2,6,3,31,16415,0,0,0,0,0,1,100,1,0,0,0,0,0,10,2,0,0,0,0,0,45,0,0,14,519,2,3,234889735,0,0,0,0,0,30320,3,3,13,0); +INSERT INTO `server_battle_commands` VALUES (27101,'blindside',2,14,3,31,16415,0,0,0,0,0,1,100,1,0,0,0,0,0,10,2,223237,60,1,0,0,60,0,0,14,635,2,3,234889851,0,0,0,0,0,30328,3,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27102,'taunt',2,42,4,768,17152,0,0,0,0,0,0,100,1,0,0,15,0,0,10,2,223073,5,1,0,0,60,0,0,14,517,2,3,234889733,0,0,0,0,0,30335,3,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27103,'featherfoot',2,2,3,31,16415,0,0,0,0,0,1,100,1,0,0,0,0,0,10,2,223075,30,1,0,0,60,0,0,14,535,2,3,234889751,0,0,0,0,0,30328,3,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27104,'fists_of_fire',2,34,4,31,16415,0,0,0,0,0,1,100,1,0,0,0,0,0,10,2,223209,4294967295,1,0,0,10,0,0,14,684,2,3,234889900,0,0,0,0,0,30328,3,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27105,'fists_of_earth',2,22,4,31,16415,0,0,0,0,0,1,100,1,0,0,0,0,0,10,2,223210,4294967295,1,0,0,10,0,0,14,685,2,3,234889901,0,0,0,0,0,30328,3,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27106,'hundred_fists',15,50,0,31,16415,0,0,0,0,0,1,100,1,0,0,0,0,0,10,2,223244,15,1,0,0,900,0,0,14,712,2,3,234889928,0,0,0,0,0,30328,3,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27107,'spinning_heel',15,35,0,31,16415,0,0,0,0,0,1,100,1,0,0,0,0,0,10,2,223245,20,1,0,0,120,0,0,14,718,2,3,234889934,0,0,0,0,0,30328,3,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27108,'shoulder_tackle',15,30,0,768,17152,0,0,0,0,0,0,100,1,0,0,15,0,0,10,2,223015,10,0.75,0,0,60,0,0,18,1048,205,3,302830616,0,0,0,0,0,30301,3,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27109,'fists_of_wind',15,40,0,31,16415,0,0,0,0,0,1,100,1,0,0,0,0,0,10,2,223211,4294967295,1,0,0,10,0,0,14,720,2,3,234889936,0,0,0,0,0,30328,3,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27110,'pummel',2,1,1,768,17152,0,0,0,0,0,0,100,1,1,0,5,0,0,10,2,0,0,0,0,0,10,0,1000,18,1027,1,3,301995011,0,27111,27113,1,0,30301,2,1,3,0); +INSERT INTO `server_battle_commands` VALUES (27111,'concussive_blow',2,10,1,768,17152,0,0,0,0,0,0,100,1,4,0,5,0,0,10,2,223007,30,0,0,0,30,0,1500,18,20,3,3,302002196,0,27112,0,2,0,30301,2,1,3,0); +INSERT INTO `server_battle_commands` VALUES (27112,'simian_thrash',2,50,4,768,17152,0,0,0,0,0,0,100,9,0,0,5,0,0,10,2,0,0,0,0,0,80,0,2000,18,1003,202,3,302818283,0,0,0,3,0,30301,2,1,3,0); +INSERT INTO `server_battle_commands` VALUES (27113,'aura_pulse',2,38,4,768,17152,1,8,0,0,0,1,100,1,0,0,5,0,0,10,2,223003,30,0,0,0,40,0,1500,18,66,203,3,302821442,0,0,0,2,0,30301,2,1,3,0); +INSERT INTO `server_battle_commands` VALUES (27114,'pounce',2,4,4,768,17152,0,0,0,0,0,0,100,1,2,0,5,0,0,10,2,223015,10,0,0,0,20,0,1500,18,8,3,3,302002184,0,27115,27117,1,0,30301,2,1,3,0); +INSERT INTO `server_battle_commands` VALUES (27115,'demolish',2,30,1,768,17152,0,0,0,0,0,0,100,1,0,0,5,0,0,10,2,0,0,0,0,0,30,0,1500,18,1028,2,3,301999108,0,27116,0,2,0,30301,2,1,3,0); +INSERT INTO `server_battle_commands` VALUES (27116,'howling_fist',2,46,4,768,17152,0,0,0,0,0,0,100,1,4,0,5,0,0,10,2,0,0,0,0,0,80,0,3000,18,1029,2,3,301999109,0,0,0,3,0,30301,2,1,3,0); +INSERT INTO `server_battle_commands` VALUES (27117,'sucker_punch',2,26,1,768,17152,0,0,0,0,0,0,100,1,4,0,5,0,0,10,2,0,0,0,0,0,15,0,1000,18,73,3,3,302002249,0,0,0,3,0,30301,2,1,3,0); +INSERT INTO `server_battle_commands` VALUES (27118,'dragon_kick',15,45,0,768,17152,0,0,0,0,0,0,100,1,0,0,5,0,0,10,2,223013,10,0,0,0,60,0,2000,18,1041,204,3,302826513,0,0,0,0,0,30301,2,1,3,0); +INSERT INTO `server_battle_commands` VALUES (27119,'haymaker',2,18,4,768,17152,0,0,0,0,0,0,100,1,0,2,5,0,0,10,2,223015,10,0.75,0,0,5,0,250,18,23,201,3,302813207,0,0,0,0,0,30301,2,1,3,0); +INSERT INTO `server_battle_commands` VALUES (27140,'sentinel',3,22,3,31,16415,0,0,0,0,0,1,100,1,0,0,0,0,0,10,2,223062,15,1,0,0,90,0,0,14,526,2,3,234889742,0,0,0,0,0,30328,3,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27141,'aegis_boon',3,6,8,31,16415,0,0,0,0,0,1,100,1,0,0,0,0,0,10,2,223058,30,1,0,0,60,0,0,14,583,21,3,234967623,0,0,0,0,0,30328,3,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27142,'rampart',3,2,3,31,16445,0,8,0,0,0,1,100,1,0,0,0,0,0,10,2,223064,60,1,0,0,120,0,0,14,536,2,3,234889752,0,0,0,0,0,30328,3,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27143,'tempered_will',3,42,8,31,16415,0,0,0,0,0,1,100,1,0,0,0,0,0,10,2,223068,20,1,0,0,180,0,0,14,515,2,3,234889731,0,0,0,0,0,30328,3,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27144,'outmaneuver',3,34,8,31,16415,0,0,0,0,0,1,100,1,0,0,0,0,0,10,2,223236,30,1,0,0,90,0,0,14,512,21,3,234967552,0,0,0,0,0,30328,3,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27145,'flash',3,14,3,768,17152,0,8,0,0,0,0,100,1,0,0,15,0,0,10,2,223007,10,0,0,0,30,0,0,14,696,2,3,234889912,0,0,0,0,0,30101,3,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27146,'cover',16,30,0,60,16412,0,0,0,0,0,1,100,1,0,0,15,0,0,10,2,223173,15,1,0,0,60,0,0,14,725,2,3,234889941,0,0,0,0,0,30328,3,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27147,'divine_veil',16,35,0,31,16415,0,0,0,0,0,1,100,1,0,0,0,0,0,10,2,223248,20,1,0,0,60,0,0,14,713,2,3,234889929,0,0,0,0,0,30328,3,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27148,'hallowed_ground',16,50,0,31,16415,0,0,0,0,0,1,100,1,0,0,0,0,0,10,2,223249,20,1,0,0,900,0,0,14,709,2,3,234889925,0,0,0,0,0,30328,3,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27149,'holy_succor',16,40,0,53,16405,0,0,0,0,0,1,100,1,0,0,15,0,0,10,2,0,0,0,3,2000,10,100,0,1,701,1,3,16782013,0,0,0,0,0,30328,4,3,13,0); +INSERT INTO `server_battle_commands` VALUES (27150,'fast_blade',3,1,1,768,17152,0,0,0,0,0,0,100,1,1,0,5,0,0,10,2,0,0,0,0,0,10,0,1000,18,1023,1,3,301995007,0,27151,27152,1,0,30301,2,1,1,0); +INSERT INTO `server_battle_commands` VALUES (27151,'flat_blade',3,26,1,768,17152,0,0,0,0,0,0,100,1,0,0,5,0,0,10,2,0,0,0,0,0,10,0,1500,18,1024,2,3,301999104,0,0,0,2,0,30301,2,1,1,0); +INSERT INTO `server_battle_commands` VALUES (27152,'savage_blade',3,10,1,768,17152,0,0,0,0,0,0,100,1,0,0,5,0,0,10,2,0,0,0,0,0,30,0,1000,18,1025,1,3,301995009,0,27153,0,2,0,30301,2,1,1,0); +INSERT INTO `server_battle_commands` VALUES (27153,'goring_blade',3,50,8,768,17152,0,0,0,0,0,0,100,1,2,0,5,0,0,10,2,223206,30,0,0,0,60,0,3000,18,1026,301,3,303223810,0,0,0,3,0,30301,2,1,1,0); +INSERT INTO `server_battle_commands` VALUES (27154,'riot_blade',3,30,8,768,17152,0,0,0,0,0,0,100,1,2,0,15,0,0,10,2,223038,30,0,0,0,80,0,2000,18,75,2,3,301998155,0,27155,0,1,0,30301,2,1,1,1); +INSERT INTO `server_battle_commands` VALUES (27155,'rage_of_halone',3,46,8,768,17152,0,0,0,0,0,0,100,5,0,0,5,0,0,10,2,0,0,0,0,0,20,0,1500,18,1008,302,3,303227888,0,0,0,2,-40,30301,2,1,1,0); +INSERT INTO `server_battle_commands` VALUES (27156,'shield_bash',3,18,17,768,17152,0,0,0,0,0,0,100,1,0,0,5,0,0,10,2,223015,5,0.75,0,0,30,0,250,18,5,26,3,302096389,0,0,0,0,0,30301,2,1,1,0); +INSERT INTO `server_battle_commands` VALUES (27157,'war_drum',3,38,24,768,17152,1,8,0,0,0,1,100,1,0,4,5,0,0,10,2,0,0,0,0,0,60,0,500,14,502,21,3,234967542,0,0,0,0,0,30301,2,1,1,0); +INSERT INTO `server_battle_commands` VALUES (27158,'phalanx',3,4,8,768,17152,0,0,0,0,0,1,100,1,0,4,5,0,0,10,2,0,0,0,0,0,5,0,250,18,32,1,3,301994016,0,27159,0,1,0,30301,2,1,1,0); +INSERT INTO `server_battle_commands` VALUES (27159,'spirits_within',16,45,0,768,17152,0,0,0,0,0,0,100,1,0,0,5,0,0,10,2,0,0,0,0,0,60,0,3000,18,1044,304,3,303236116,0,0,0,2,50,30301,2,1,1,0); +INSERT INTO `server_battle_commands` VALUES (27180,'provoke',4,14,3,768,17152,0,0,0,0,0,0,100,1,0,0,15,0,0,10,2,223034,30,0,0,0,30,0,0,14,600,2,3,234889816,0,0,0,0,0,30101,3,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27181,'foresight',4,2,3,31,16415,0,0,0,0,0,1,100,1,0,0,0,0,0,10,2,223083,30,1,0,0,60,0,0,14,545,2,3,234889761,0,0,0,0,0,30328,3,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27182,'bloodbath',4,6,3,31,16415,0,0,0,0,0,1,100,1,0,0,0,0,0,10,2,223081,30,1,0,0,60,0,0,14,581,2,3,234889797,0,0,0,0,0,30328,3,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27183,'berserk',4,22,32,31,16415,0,0,0,0,0,1,100,1,0,0,0,0,0,10,2,223207,4294967295,1,0,0,10,0,0,14,682,2,3,234889898,0,0,0,0,0,30328,3,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27184,'rampage',4,34,32,31,16415,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223208,4294967295,1,0,0,10,0,0,14,546,2,3,234889762,0,0,0,0,0,30328,3,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27185,'enduring_march',4,42,32,31,16415,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223078,20,1,0,0,180,0,0,14,539,2,3,234889755,0,0,0,0,0,30328,3,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27186,'vengeance',17,30,0,31,16415,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223250,15,1,0,0,150,0,0,14,714,2,3,234889930,0,0,0,0,0,30328,3,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27187,'antagonize',17,35,0,31,16415,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223251,15,1,0,0,120,0,0,14,715,2,3,234889931,0,0,0,0,0,30328,3,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27188,'collusion',17,40,0,60,16412,0,0,0,0,0,0,100,1,0,0,15,0,0,10,2,223097,15,1,0,0,90,0,0,14,711,2,3,234889927,0,0,0,0,0,30328,3,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27189,'mighty_strikes',17,50,0,31,16415,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223252,15,1,0,0,900,0,0,14,716,2,3,234889932,0,0,0,0,0,30328,3,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27190,'heavy_swing',4,1,1,768,17152,0,0,0,0,0,0,100,1,1,0,5,0,0,10,2,0,0,0,0,0,10,0,1000,18,14,1,3,301993998,0,27191,0,1,0,30301,2,1,1,0); +INSERT INTO `server_battle_commands` VALUES (27191,'skull_sunder',4,10,1,768,17152,0,0,0,0,0,0,100,1,0,0,5,0,0,10,2,0,0,0,0,0,30,0,1500,18,43,1,3,301994027,0,27192,0,2,0,30301,2,1,1,0); +INSERT INTO `server_battle_commands` VALUES (27192,'steel_cyclone',17,45,0,768,17152,1,8,0,0,0,1,100,1,0,0,5,0,0,10,2,223015,3,0,0,0,30,0,2000,18,1040,404,3,303645712,0,0,0,3,0,30301,2,1,1,0); +INSERT INTO `server_battle_commands` VALUES (27193,'brutal_swing',4,4,1,768,17152,0,0,0,0,0,0,100,1,4,0,5,0,0,10,2,0,0,0,0,0,20,0,1500,18,15,3,3,302002191,0,27194,0,1,0,30301,2,1,1,0); +INSERT INTO `server_battle_commands` VALUES (27194,'maim',4,26,1,768,17152,0,0,0,0,0,0,100,1,0,0,5,0,0,10,2,0,0,0,0,0,30,0,1500,18,88,1,3,301994072,0,27195,0,2,0,30301,2,1,1,0); +INSERT INTO `server_battle_commands` VALUES (27195,'godsbane',4,50,32,768,17152,0,0,0,0,0,0,100,3,0,0,5,0,0,10,2,0,0,0,0,0,60,0,3000,18,1014,402,3,303637494,0,0,0,3,0,30301,2,1,1,0); +INSERT INTO `server_battle_commands` VALUES (27196,'path_of_the_storm',4,38,32,768,17152,0,0,0,0,0,0,100,1,2,0,5,0,0,10,2,228021,30,0,0,0,30,0,1500,18,44,401,3,303632428,0,27197,0,1,0,30301,2,1,1,0); +INSERT INTO `server_battle_commands` VALUES (27197,'whirlwind',4,46,32,768,17152,1,8,0,0,0,1,100,1,0,0,5,0,0,10,2,0,0,0,0,0,80,0,3000,18,1015,403,3,303641591,0,0,0,2,0,30301,2,1,1,0); +INSERT INTO `server_battle_commands` VALUES (27198,'fracture',4,18,32,768,17152,0,0,0,0,0,0,100,1,0,3,5,0,0,10,2,223013,8,0.75,0,0,40,0,500,18,42,3,3,302002218,0,0,0,0,0,30301,2,1,1,0); +INSERT INTO `server_battle_commands` VALUES (27199,'overpower',4,30,1,768,17152,2,8,0,0.5,0,1,100,1,0,3,8,0,0,10,2,0,0,0,0,0,5,0,250,18,89,1,3,301994073,0,0,0,0,0,30301,2,1,1,0); +INSERT INTO `server_battle_commands` VALUES (27220,'hawks_eye',7,6,3,31,16415,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223106,15,1,0,0,90,0,0,14,516,2,3,234889732,0,0,0,0,0,30328,3,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27221,'quelling_strike',7,22,3,31,16415,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223104,30,1,0,0,60,0,0,14,614,2,3,234889830,0,0,0,0,0,30328,3,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27222,'decoy',7,2,3,31,16415,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223108,60,1,0,0,90,100,0,14,565,2,3,234889781,0,0,0,0,0,30328,3,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27223,'chameleon',7,42,3,31,16415,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,0,0,0,0,0,180,0,0,14,504,2,3,234889720,0,0,0,0,0,30101,3,0,0,0); +INSERT INTO `server_battle_commands` VALUES (27224,'barrage',7,34,64,31,16415,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223220,60,1,0,0,90,0,0,14,683,2,3,234889899,0,0,0,0,0,30328,3,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27225,'raging_strike',7,14,64,31,16415,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223221,4294967295,1,0,0,10,0,0,14,632,2,3,234889848,0,0,0,0,0,30328,3,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27226,'swiftsong',7,26,64,31,16445,1,20,0,0,0,1,100,1,0,0,0,0,0,10,2,223224,180,1,0,0,10,100,0,1,150,1,3,16781462,0,0,0,0,0,30328,4,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27227,'battle_voice',18,50,0,31,16445,1,20,0,0,0,1,100,1,0,0,0,0,0,10,2,223029,60,1,0,0,900,0,0,14,721,2,3,234889937,0,0,0,0,0,30328,3,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27228,'heavy_shot',7,1,1,768,17152,0,0,0,0,0,0,100,1,0,0,20,0,8,10,2,0,0,0,0,0,10,0,1000,18,1036,4,3,302007308,0,27229,27231,1,0,30301,2,1,4,1); +INSERT INTO `server_battle_commands` VALUES (27229,'leaden_arrow',7,10,1,768,17152,0,0,0,0,0,0,100,1,0,0,20,0,0,10,2,228021,30,0.75,0,0,30,0,1500,18,1035,4,3,302007307,0,27230,0,2,0,30301,2,1,4,1); +INSERT INTO `server_battle_commands` VALUES (27230,'wide_volley',7,50,64,768,17152,1,8,0,0,0,0,100,1,0,0,20,0,0,10,2,0,0,0,0,0,80,0,2000,18,18,703,3,304869394,0,0,0,3,-20,30301,2,1,4,1); +INSERT INTO `server_battle_commands` VALUES (27231,'quick_nock',7,38,64,768,17152,2,10,0,0.5,0,1,100,1,0,0,10,0,0,10,2,0,0,0,0,0,180,0,1000,18,1017,702,3,304866297,0,27232,0,2,0,30301,2,1,4,1); +INSERT INTO `server_battle_commands` VALUES (27232,'rain_of_death',18,45,0,768,17152,1,8,0,0,0,0,100,1,0,0,20,0,0,10,2,223015,5,0.75,0,0,30,0,3000,18,1037,704,3,304874509,0,0,0,3,0,30301,2,1,4,1); +INSERT INTO `server_battle_commands` VALUES (27233,'piercing_arrow',7,4,1,768,17152,0,0,0,0,0,0,100,1,0,0,20,0,8,10,2,0,0,0,0,0,20,0,1000,18,1038,1,3,301995022,0,27234,27236,1,0,30301,2,1,4,1); +INSERT INTO `server_battle_commands` VALUES (27234,'gloom_arrow',7,30,1,768,17152,0,0,0,0,0,0,100,1,0,0,20,0,0,10,2,223007,30,0,0,0,10,0,1000,18,1039,4,3,302007311,0,27235,0,2,0,30301,2,1,4,1); +INSERT INTO `server_battle_commands` VALUES (27235,'bloodletter',7,46,64,768,17152,0,0,0,0,0,0,100,1,0,0,20,0,0,10,2,223241,30,0.75,0,0,80,0,1500,18,53,701,3,304861237,0,0,0,3,0,30301,2,1,4,1); +INSERT INTO `server_battle_commands` VALUES (27236,'shadowbind',7,18,64,768,17152,0,0,0,0,0,0,100,1,0,0,20,0,0,10,2,228011,15,0.9,0,0,40,0,250,18,17,4,3,302006289,0,0,0,2,0,30301,2,1,4,1); +INSERT INTO `server_battle_commands` VALUES (27237,'ballad_of_magi',18,30,0,31,16445,1,20,0,0,0,1,100,1,0,0,0,0,0,10,2,223254,180,1,8,3000,10,100,0,1,709,1,3,16782021,0,0,0,0,0,30328,4,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27238,'paeon_of_war',18,40,0,31,16445,1,20,0,0,0,1,100,1,0,0,0,0,0,10,2,223255,180,1,8,3000,10,50,1000,1,710,1,3,16782022,0,0,0,0,0,30328,4,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27239,'minuet_of_rigor',18,35,0,31,16445,1,20,0,0,0,1,100,1,0,0,0,0,0,10,2,223256,180,1,8,3000,10,100,0,1,711,1,3,16782023,0,0,0,0,0,30328,4,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27258,'refill',7,1,0,31,16415,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,32613,3,0,0,0); +INSERT INTO `server_battle_commands` VALUES (27259,'light_shot',7,1,0,768,17152,0,0,0,0,0,0,100,1,0,0,20,0,0,10,2,0,0,0,0,0,0,0,0,17,0,1,3,285216768,0,0,0,0,0,30301,3,1,0,1); +INSERT INTO `server_battle_commands` VALUES (27260,'invigorate',8,14,3,31,16415,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223094,30,1,0,0,90,0,0,14,575,2,3,234889791,0,0,0,0,0,30328,3,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27261,'power_surge',8,34,128,31,16415,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223212,60,1,0,0,10,0,0,14,686,2,3,234889902,0,0,0,0,0,30328,3,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27262,'life_surge',8,22,128,31,16415,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223215,180,1,0,0,15,0,250,14,687,2,3,234889903,0,0,0,0,0,30328,3,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27263,'dread_spike',8,42,128,31,16415,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223218,30,1,0,0,120,0,0,14,686,2,3,234889902,0,0,0,0,0,30328,3,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27264,'blood_for_blood',8,6,3,31,16415,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223219,60,1,0,0,60,0,0,14,689,2,3,234889905,0,0,0,0,0,30328,3,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27265,'keen_flurry',8,26,3,31,16415,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223091,30,1,0,0,90,0,0,14,569,2,3,234889785,0,0,0,0,0,30328,3,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27266,'jump',19,30,0,768,17152,0,0,0,0,0,0,100,1,0,0,20,0,0,10,2,0,0,0,0,0,60,0,0,18,1045,804,3,305284117,0,0,0,0,0,30301,3,1,2,0); +INSERT INTO `server_battle_commands` VALUES (27267,'elusive_jump',19,40,0,31,16415,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,0,0,0,0,0,180,0,0,18,1046,806,3,305292310,0,0,0,0,0,30101,3,0,0,0); +INSERT INTO `server_battle_commands` VALUES (27268,'dragonfire_dive',19,50,0,768,17152,1,4,0,0,0,0,100,1,0,0,20,0,0,10,2,0,0,0,0,0,900,0,0,18,1045,804,3,305284117,0,0,0,0,0,30301,3,2,5,0); +INSERT INTO `server_battle_commands` VALUES (27269,'true_thrust',8,1,1,768,17152,0,0,0,0,0,0,100,1,1,0,5,0,0,10,2,0,0,0,0,0,10,0,1000,18,1030,2,3,301999110,0,27270,27273,1,0,30301,2,1,2,0); +INSERT INTO `server_battle_commands` VALUES (27270,'leg_sweep',8,30,1,768,17152,2,8,0,0.5,0,1,100,1,0,0,5,0,0,10,2,223015,8,0,0,0,30,0,1000,18,37,1,3,301994021,0,27271,0,2,0,30301,2,1,2,0); +INSERT INTO `server_battle_commands` VALUES (27271,'doom_spike',8,46,128,768,17152,3,5,0,0,0,1,100,1,0,0,5,0,0,10,2,0,0,0,0,0,60,0,3000,18,83,801,3,305270867,0,0,0,3,0,30301,2,1,2,0); +INSERT INTO `server_battle_commands` VALUES (27272,'disembowel',19,35,0,768,17152,0,0,0,0,0,0,100,1,0,0,5,0,0,10,2,223005,15,0.75,0,0,30,0,750,18,1042,2,3,301999122,0,0,0,0,0,30301,2,1,2,0); +INSERT INTO `server_battle_commands` VALUES (27273,'heavy_thrust',8,10,1,768,17152,0,0,0,0,0,0,100,1,0,0,5,0,0,10,2,223015,4,0.75,0,0,20,0,1500,18,1031,1,3,301995015,0,0,0,0,0,30301,2,1,2,0); +INSERT INTO `server_battle_commands` VALUES (27274,'vorpal_thrust',8,2,1,768,17152,0,0,0,0,0,0,100,1,2,0,5,0,0,10,2,0,0,0,0,0,20,0,1500,18,1032,2,3,301999112,0,27275,0,1,0,30301,2,1,2,0); +INSERT INTO `server_battle_commands` VALUES (27275,'impulse_drive',8,18,1,768,17152,0,0,0,0,0,0,100,1,4,0,5,0,0,10,2,0,0,0,0,0,30,0,1500,18,1033,2,3,301999113,0,27276,27277,2,0,30301,2,1,2,0); +INSERT INTO `server_battle_commands` VALUES (27276,'chaos_thrust',8,50,128,768,17152,0,0,0,0,0,0,100,6,0,0,5,0,0,10,2,0,0,0,0,0,80,0,3000,18,40,802,3,305274920,0,0,0,3,0,30301,2,1,2,0); +INSERT INTO `server_battle_commands` VALUES (27277,'ring_of_talons',19,45,0,768,17152,1,8,0,0,0,1,100,1,0,0,5,0,0,10,2,0,0,0,0,0,60,0,2000,18,1009,803,3,305279985,0,0,0,3,0,30301,2,1,2,0); +INSERT INTO `server_battle_commands` VALUES (27278,'feint',8,4,1,768,17152,0,0,0,0,0,0,100,1,0,1,5,0,0,10,2,0,0,0,0,0,10,0,250,18,39,2,3,301998119,0,27272,0,1,100,30301,2,1,2,0); +INSERT INTO `server_battle_commands` VALUES (27279,'full_thrust',8,38,128,768,17152,0,0,0,0,0,0,100,1,0,1,5,0,0,10,2,0,0,0,0,0,30,0,250,18,1034,801,3,305271818,0,0,0,0,50,30301,2,1,2,0); +INSERT INTO `server_battle_commands` VALUES (27300,'dark_seal',22,14,3,31,16415,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223229,30,1,0,0,90,0,0,14,518,2,3,234889734,0,0,0,0,0,30328,3,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27301,'resonance',22,22,3,31,16415,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223230,30,1,0,0,90,0,0,14,669,2,3,234889885,0,0,0,0,0,30328,3,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27302,'excruciate',22,38,256,31,16415,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223231,30,1,0,0,90,0,0,14,694,2,3,234889910,0,0,0,0,0,30328,3,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27303,'necrogenesis',22,6,3,31,16415,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223232,30,1,0,0,90,0,0,14,695,2,3,234889911,0,0,0,0,0,30328,3,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27304,'parsimony',22,2,256,31,16415,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223233,30,1,0,0,90,0,0,14,568,2,3,234889784,0,0,0,0,0,30328,3,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27305,'convert',26,30,0,31,16415,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,0,0,0,0,0,450,0,0,14,724,2,3,234889940,0,0,0,0,0,30101,3,0,0,0); +INSERT INTO `server_battle_commands` VALUES (27306,'sleep',22,42,256,768,17152,0,0,0,0,0,0,100,1,0,0,20,0,0,10,2,228001,60,0.9,2,3000,0,75,0,1,651,1,3,16781963,0,0,0,0,0,30335,4,4,12,0); +INSERT INTO `server_battle_commands` VALUES (27307,'sanguine_rite',22,30,3,31,16415,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223234,20,1,0,0,60,120,0,1,152,1,3,16781464,0,0,0,0,0,30328,4,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27308,'blizzard',22,4,256,768,17152,0,0,0,0,0,0,100,1,0,0,20,0,0,10,2,228021,30,0.75,2,3000,10,90,0,1,502,1,3,16781814,0,0,0,0,0,30301,4,2,6,0); +INSERT INTO `server_battle_commands` VALUES (27309,'blizzara',22,26,256,768,17152,1,8,0,0,0,0,100,1,0,0,20,0,0,10,2,228011,30,0.75,0,0,40,150,0,1,506,1,3,16781818,0,0,0,0,0,30301,4,2,6,0); +INSERT INTO `server_battle_commands` VALUES (27310,'fire',22,10,3,768,17152,1,8,0,0,0,0,100,1,0,0,20,0,0,10,2,0,0,0,2,3000,8,105,0,1,501,1,3,16781813,0,27311,0,1,0,30301,4,2,5,0); +INSERT INTO `server_battle_commands` VALUES (27311,'fira',22,34,3,768,17152,1,8,0,0,0,0,100,1,0,0,20,0,0,10,2,0,0,0,2,5000,16,180,0,1,504,1,3,16781816,0,27312,0,2,0,30301,4,2,5,0); +INSERT INTO `server_battle_commands` VALUES (27312,'firaga',22,50,256,768,17152,1,8,0,0,0,0,100,1,0,0,20,0,0,10,2,0,0,0,2,8000,7,255,0,1,700,1,3,16782012,0,0,0,3,0,30301,4,2,5,0); +INSERT INTO `server_battle_commands` VALUES (27313,'thunder',22,1,3,768,17152,0,0,0,0,0,0,100,1,0,0,20,0,0,10,2,0,0,0,2,2000,6,75,0,1,503,1,3,16781815,0,27314,0,1,0,30301,4,2,9,0); +INSERT INTO `server_battle_commands` VALUES (27314,'thundara',22,18,256,768,17152,0,0,0,0,0,0,100,1,0,0,20,0,0,10,2,223015,4,0.75,0,0,30,135,0,1,508,1,3,16781820,0,27315,27316,2,0,30301,4,2,9,0); +INSERT INTO `server_battle_commands` VALUES (27315,'thundaga',22,46,256,768,17152,0,0,0,0,0,0,100,1,0,0,20,0,0,10,2,0,0,0,2,5000,45,195,0,1,509,1,3,16781821,0,0,0,3,0,30301,4,2,9,0); +INSERT INTO `server_battle_commands` VALUES (27316,'burst',26,50,0,768,17152,0,0,0,0,0,0,100,1,0,0,20,0,0,10,2,0,0,0,2,4000,900,90,0,1,705,1,3,16782017,0,0,0,3,0,30301,4,2,9,0); +INSERT INTO `server_battle_commands` VALUES (27317,'sleepga',26,45,0,768,17152,1,8,0,0,0,0,100,1,0,0,20,0,0,10,2,228001,60,0.9,2,4000,0,100,0,1,704,1,3,16782016,0,0,0,0,0,30335,4,4,12,0); +INSERT INTO `server_battle_commands` VALUES (27318,'flare',26,40,0,31,17152,1,8,0,0,0,1,100,1,0,0,20,0,0,10,2,223262,30,0.75,2,8000,120,200,0,1,706,1,3,16782018,0,0,0,0,0,30301,4,2,5,0); +INSERT INTO `server_battle_commands` VALUES (27319,'freeze',26,35,0,768,17152,0,0,0,0,0,0,100,1,0,0,20,0,0,10,2,0,0,0,2,5000,120,120,0,1,707,1,3,16782019,0,0,0,0,0,30301,4,2,6,0); +INSERT INTO `server_battle_commands` VALUES (27340,'sacred_prism',23,34,3,31,16415,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223225,60,1,0,0,90,0,0,14,690,2,3,234889906,0,0,0,0,0,30328,3,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27341,'shroud_of_saints',23,38,512,31,16415,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223226,20,1,0,0,180,0,0,14,691,2,3,234889907,0,0,0,0,0,30328,3,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27342,'cleric_stance',23,10,512,31,16415,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223227,4294967295,1,0,0,30,0,0,14,692,2,3,234889908,0,0,0,0,0,30328,3,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27343,'blissful_mind',23,14,512,31,16415,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223228,4294967295,1,0,0,30,0,0,14,693,2,3,234889909,0,0,0,0,0,30328,3,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27344,'presence_of_mind',27,30,0,31,16415,0,0,0,0,0,0,100,1,0,0,0,0,0,10,2,223116,30,1,0,0,300,0,0,14,722,2,3,234889938,0,0,0,0,0,30328,3,4,0,0); +INSERT INTO `server_battle_commands` VALUES (27345,'benediction',27,50,0,31,16445,1,20,0,0,0,1,100,1,0,0,0,0,0,10,2,0,0,0,0,0,900,0,0,14,723,2,3,234889939,0,0,0,0,0,30320,3,3,13,0); +INSERT INTO `server_battle_commands` VALUES (27346,'cure',23,2,3,53,16393,0,0,0,0,0,0,100,1,0,0,20,0,0,10,2,0,0,0,3,2000,5,40,0,1,101,1,3,16781413,0,0,0,0,0,30320,4,3,13,0); +INSERT INTO `server_battle_commands` VALUES (27347,'cura',23,30,512,53,16393,0,0,0,0,0,0,100,1,0,0,20,0,0,10,2,0,0,0,3,2000,5,100,0,1,103,1,3,16781415,0,0,0,0,0,30320,4,3,13,0); +INSERT INTO `server_battle_commands` VALUES (27348,'curaga',23,46,512,61,16445,1,15,0,0,0,0,100,1,0,0,20,0,0,10,2,0,0,0,3,3000,10,150,0,1,146,1,3,16781458,0,0,0,0,0,30320,4,3,13,0); +INSERT INTO `server_battle_commands` VALUES (27349,'raise',23,18,512,12340,28724,0,0,0,0,0,0,100,1,0,0,20,0,0,10,2,0,0,0,3,10000,300,150,0,1,148,1,3,16781460,0,0,0,0,0,30101,4,4,11,0); +INSERT INTO `server_battle_commands` VALUES (27350,'stoneskin',23,26,3,53,16393,0,0,0,0,0,0,100,1,0,0,20,0,0,10,2,223133,300,1,3,3000,30,50,0,1,133,1,3,16781445,0,0,0,0,0,30328,4,4,8,0); +INSERT INTO `server_battle_commands` VALUES (27351,'protect',23,6,3,53,49205,1,20,0,0,0,0,100,1,0,0,20,0,0,10,2,223129,300,1,3,3000,30,80,0,1,1085,1,3,16782397,0,0,0,0,0,30328,4,4,11,0); +INSERT INTO `server_battle_commands` VALUES (27352,'repose',23,50,0,768,17152,0,0,0,0,0,0,100,1,0,0,20,0,0,10,2,228001,60,0.9,3,3000,0,80,0,1,151,1,3,16781463,0,0,0,0,0,30328,4,4,10,0); +INSERT INTO `server_battle_commands` VALUES (27353,'aero',23,4,3,768,17152,0,0,0,0,0,0,100,1,0,0,20,0,0,10,2,223235,20,0.75,3,3000,6,75,0,1,510,1,3,16781822,0,27354,0,1,0,30301,4,2,7,0); +INSERT INTO `server_battle_commands` VALUES (27354,'aerora',23,42,512,768,17152,1,0,0,0,0,0,100,1,0,0,20,0,0,10,2,0,0,0,3,4000,20,150,0,1,511,1,3,16781823,0,0,0,2,0,30301,4,2,7,0); +INSERT INTO `server_battle_commands` VALUES (27355,'stone',23,1,3,768,17152,0,0,0,0,0,0,100,1,0,0,20,0,0,10,2,223243,10,0.75,3,2000,6,75,0,1,513,1,3,16781825,0,27356,0,1,0,30301,4,2,8,0); +INSERT INTO `server_battle_commands` VALUES (27356,'stonera',23,22,512,768,17152,1,0,0,0,0,0,100,1,0,0,20,0,0,10,2,228021,30,0.75,3,3000,30,150,0,1,514,1,3,16781826,0,0,0,2,0,30301,4,2,8,0); +INSERT INTO `server_battle_commands` VALUES (27357,'esuna',27,40,0,53,16405,0,0,0,0,0,0,100,1,0,0,20,0,0,10,2,0,0,0,3,2000,10,40,0,1,702,1,3,16782014,0,0,0,0,0,30329,4,0,13,0); +INSERT INTO `server_battle_commands` VALUES (27358,'regen',27,35,0,53,16405,0,0,0,0,0,0,100,1,0,0,20,0,0,10,2,223180,45,1,3,2000,5,20,0,1,703,1,3,16782015,0,0,0,0,0,30328,4,4,13,0); +INSERT INTO `server_battle_commands` VALUES (27359,'holy',27,45,0,31,17152,1,8,0,0,0,1,100,1,0,0,0,0,0,10,2,228011,10,0.9,0,0,300,100,0,1,708,1,3,16782020,0,0,0,0,0,30301,4,2,11,0); /*!40000 ALTER TABLE `server_battle_commands` ENABLE KEYS */; UNLOCK TABLES; commit; @@ -243,4 +243,4 @@ commit; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2018-07-02 0:22:43 +-- Dump completed on 2019-06-05 18:56:04 diff --git a/sql/server_battle_traits.sql b/sql/server_battle_traits.sql index 89d7930f..b5bf7413 100644 --- a/sql/server_battle_traits.sql +++ b/sql/server_battle_traits.sql @@ -1,8 +1,8 @@ --- MySQL dump 10.13 Distrib 5.7.11, for Win64 (x86_64) +-- MySQL dump 10.13 Distrib 5.7.23, for Win64 (x86_64) -- -- Host: localhost Database: ffxiv_server -- ------------------------------------------------------ --- Server version 5.7.11 +-- Server version 5.7.23 /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; @@ -46,8 +46,8 @@ INSERT INTO `server_battle_traits` VALUES (27241,'enhanced_quelling_strike',7,32 INSERT INTO `server_battle_traits` VALUES (27243,'enhanced_raging_strike',7,36,0,0); INSERT INTO `server_battle_traits` VALUES (27244,'enhanced_decoy',7,16,0,0); INSERT INTO `server_battle_traits` VALUES (27245,'swift_chameleon',7,48,0,0); -INSERT INTO `server_battle_traits` VALUES (27246,'enhanced_physical_crit_accuracy',7,40,64,10); -INSERT INTO `server_battle_traits` VALUES (27247,'enhanced_physical_crit_evasion',7,20,65,10); +INSERT INTO `server_battle_traits` VALUES (27246,'enhanced_physical_crit_accuracy',7,40,19,10); +INSERT INTO `server_battle_traits` VALUES (27247,'enhanced_physical_crit_evasion',7,20,20,10); INSERT INTO `server_battle_traits` VALUES (27248,'enhanced_physical_evasion',7,12,16,8); INSERT INTO `server_battle_traits` VALUES (27249,'enhanced_physical_accuracy',7,8,15,8); INSERT INTO `server_battle_traits` VALUES (27250,'enhanced_physical_accuracy_ii',7,24,15,10); @@ -61,15 +61,15 @@ INSERT INTO `server_battle_traits` VALUES (27126,'enhanced_physical_accuracy',2, INSERT INTO `server_battle_traits` VALUES (27127,'enhanced_physical_attack',2,8,17,8); INSERT INTO `server_battle_traits` VALUES (27128,'enhanced_physical_attack_ii',2,40,17,10); INSERT INTO `server_battle_traits` VALUES (27129,'enhanced_evasion',2,12,16,8); -INSERT INTO `server_battle_traits` VALUES (27130,'enhanced_physical_crit_damage',2,32,66,10); +INSERT INTO `server_battle_traits` VALUES (27130,'enhanced_physical_crit_damage',2,32,21,10); INSERT INTO `server_battle_traits` VALUES (27160,'enhanced_sentinel',3,36,0,0); INSERT INTO `server_battle_traits` VALUES (27161,'enhanced_flash',3,28,0,0); INSERT INTO `server_battle_traits` VALUES (27162,'enhanced_flash_ii',3,48,0,0); INSERT INTO `server_battle_traits` VALUES (27163,'enhanced_rampart',3,12,0,0); INSERT INTO `server_battle_traits` VALUES (27164,'swift_aegis_boon',3,20,0,0); INSERT INTO `server_battle_traits` VALUES (27165,'enhanced_outmaneuver',3,44,0,0); -INSERT INTO `server_battle_traits` VALUES (27167,'enhanced_block_rate',3,16,51,10); -INSERT INTO `server_battle_traits` VALUES (27166,'enhanced_physical_crit_resilience',3,32,67,10); +INSERT INTO `server_battle_traits` VALUES (27167,'enhanced_block_rate',3,16,41,10); +INSERT INTO `server_battle_traits` VALUES (27166,'enhanced_physical_crit_resilience',3,32,22,10); INSERT INTO `server_battle_traits` VALUES (27168,'enhanced_physical_defense',3,8,18,10); INSERT INTO `server_battle_traits` VALUES (27169,'enhanced_physical_defense_ii',3,24,18,10); INSERT INTO `server_battle_traits` VALUES (27170,'enhanced_physical_defense_iii',3,40,18,12); @@ -79,8 +79,8 @@ INSERT INTO `server_battle_traits` VALUES (27202,'swift_bloodbath',4,16,0,0); INSERT INTO `server_battle_traits` VALUES (27203,'enhanced_enduring_march',4,48,0,0); INSERT INTO `server_battle_traits` VALUES (27204,'enhanced_rampage',4,44,0,0); INSERT INTO `server_battle_traits` VALUES (27205,'enhanced_berserk',4,36,0,0); -INSERT INTO `server_battle_traits` VALUES (27206,'enhanced_physical_crit_evasion',4,32,65,10); -INSERT INTO `server_battle_traits` VALUES (27207,'enhanced_parry',4,24,68,8); +INSERT INTO `server_battle_traits` VALUES (27206,'enhanced_physical_crit_evasion',4,32,20,10); +INSERT INTO `server_battle_traits` VALUES (27207,'enhanced_parry',4,24,39,8); INSERT INTO `server_battle_traits` VALUES (27208,'enhanced_physical_defense',4,12,18,8); INSERT INTO `server_battle_traits` VALUES (27209,'enhanced_physical_defense_ii',4,40,18,10); INSERT INTO `server_battle_traits` VALUES (27210,'enhanced_physical_attack_power',4,8,17,8); @@ -90,8 +90,8 @@ INSERT INTO `server_battle_traits` VALUES (27282,'enhanced_life_surge',8,32,0,0) INSERT INTO `server_battle_traits` VALUES (27283,'enhanced_blood_for_blood',8,48,0,0); INSERT INTO `server_battle_traits` VALUES (27284,'swift_blood_for_blood',8,16,0,0); INSERT INTO `server_battle_traits` VALUES (27285,'enhanced_keen_flurry',8,36,0,0); -INSERT INTO `server_battle_traits` VALUES (27286,'store_tp',8,12,63,50); -INSERT INTO `server_battle_traits` VALUES (27287,'enhanced_physical_crit_accuracy',8,24,64,10); +INSERT INTO `server_battle_traits` VALUES (27286,'store_tp',8,12,50,50); +INSERT INTO `server_battle_traits` VALUES (27287,'enhanced_physical_crit_accuracy',8,24,19,10); INSERT INTO `server_battle_traits` VALUES (27288,'enhanced_physical_attack_power',8,8,17,8); INSERT INTO `server_battle_traits` VALUES (27289,'enhanced_physical_attack_power_ii',8,20,17,10); INSERT INTO `server_battle_traits` VALUES (27290,'enhanced_physical_attack_power_iii',8,40,17,10); @@ -104,8 +104,8 @@ INSERT INTO `server_battle_traits` VALUES (27325,'enhanced_enfeebling_magic',22, INSERT INTO `server_battle_traits` VALUES (27326,'enhanced_enfeebling_magic_ii',22,28,26,10); INSERT INTO `server_battle_traits` VALUES (27327,'enhanced_magic_potency',22,8,23,8); INSERT INTO `server_battle_traits` VALUES (27328,'enhanced_magic_potency_ii',22,28,23,10); -INSERT INTO `server_battle_traits` VALUES (27329,'enhanced_magic_crit_potency',22,40,69,10); -INSERT INTO `server_battle_traits` VALUES (27330,'auto-refresh',22,20,44,3); +INSERT INTO `server_battle_traits` VALUES (27329,'enhanced_magic_crit_potency',22,40,37,10); +INSERT INTO `server_battle_traits` VALUES (27330,'auto-refresh',22,20,49,3); INSERT INTO `server_battle_traits` VALUES (27360,'swift_sacred_prism',23,40,0,0); INSERT INTO `server_battle_traits` VALUES (27361,'swift_shroud_of_saints',23,44,0,0); INSERT INTO `server_battle_traits` VALUES (27362,'enhanced_blissful_mind',23,32,0,0); @@ -116,7 +116,7 @@ INSERT INTO `server_battle_traits` VALUES (27366,'greater_enhancing_magic',23,12 INSERT INTO `server_battle_traits` VALUES (27367,'greater_healing',23,8,24,8); INSERT INTO `server_battle_traits` VALUES (27368,'greater_healing_ii',23,18,24,10); INSERT INTO `server_battle_traits` VALUES (27369,'enhanced_magic_accuracy',23,16,27,8); -INSERT INTO `server_battle_traits` VALUES (27370,'auto-refresh',23,20,44,3); +INSERT INTO `server_battle_traits` VALUES (27370,'auto-refresh',23,20,49,3); /*!40000 ALTER TABLE `server_battle_traits` ENABLE KEYS */; UNLOCK TABLES; commit; @@ -130,4 +130,4 @@ commit; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2018-06-25 23:30:47 +-- Dump completed on 2019-06-01 21:15:51 diff --git a/sql/server_statuseffects.sql b/sql/server_statuseffects.sql index 03c7b3c7..1ff10094 100644 --- a/sql/server_statuseffects.sql +++ b/sql/server_statuseffects.sql @@ -1,8 +1,8 @@ --- MySQL dump 10.13 Distrib 5.7.11, for Win64 (x86_64) +-- MySQL dump 10.13 Distrib 5.7.23, for Win64 (x86_64) -- -- Host: localhost Database: ffxiv_server -- ------------------------------------------------------ --- Server version 5.7.11 +-- Server version 5.7.23 /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; @@ -28,6 +28,11 @@ CREATE TABLE `server_statuseffects` ( `flags` int(10) unsigned NOT NULL DEFAULT '10', `overwrite` tinyint(3) unsigned NOT NULL DEFAULT '1', `tickMs` int(10) unsigned NOT NULL DEFAULT '3000', + `hidden` tinyint(4) NOT NULL DEFAULT '0', + `silentOnGain` tinyint(4) NOT NULL DEFAULT '0', + `silentOnLoss` tinyint(4) NOT NULL DEFAULT '0', + `statusGainTextId` smallint(6) NOT NULL DEFAULT '30328', + `statusLossTextId` int(11) NOT NULL DEFAULT '30331', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; /*!40101 SET character_set_client = @saved_cs_client */; @@ -39,94 +44,102 @@ CREATE TABLE `server_statuseffects` ( LOCK TABLES `server_statuseffects` WRITE; /*!40000 ALTER TABLE `server_statuseffects` DISABLE KEYS */; set autocommit=0; -INSERT INTO `server_statuseffects` VALUES (223001,'quick',18,2,0); -INSERT INTO `server_statuseffects` VALUES (223002,'haste',18,2,0); -INSERT INTO `server_statuseffects` VALUES (223004,'petrification',264241194,2,0); -INSERT INTO `server_statuseffects` VALUES (223005,'paralysis',42,2,3000); -INSERT INTO `server_statuseffects` VALUES (223006,'silence',4194346,2,0); -INSERT INTO `server_statuseffects` VALUES (223007,'blind',42,2,0); -INSERT INTO `server_statuseffects` VALUES (223008,'mute',4194346,2,0); -INSERT INTO `server_statuseffects` VALUES (223010,'glare',42,2,0); -INSERT INTO `server_statuseffects` VALUES (223011,'poison',42,2,0); -INSERT INTO `server_statuseffects` VALUES (223012,'transfixion',268435498,2,0); -INSERT INTO `server_statuseffects` VALUES (223013,'pacification',8388650,2,0); -INSERT INTO `server_statuseffects` VALUES (223014,'amnesia',16777258,2,0); -INSERT INTO `server_statuseffects` VALUES (223015,'stun',264241194,2,0); -INSERT INTO `server_statuseffects` VALUES (223016,'daze',264241194,2,0); -INSERT INTO `server_statuseffects` VALUES (223029,'hp_boost',18,2,0); -INSERT INTO `server_statuseffects` VALUES (223030,'hp_penalty',42,2,0); -INSERT INTO `server_statuseffects` VALUES (223038,'defense_down',42,2,0); -INSERT INTO `server_statuseffects` VALUES (223058,'aegis_boon',528434,2,0); -INSERT INTO `server_statuseffects` VALUES (223062,'sentinel',1048626,2,0); -INSERT INTO `server_statuseffects` VALUES (223063,'cover',16434,2,0); -INSERT INTO `server_statuseffects` VALUES (223064,'rampart',18,2,0); -INSERT INTO `server_statuseffects` VALUES (223068,'tempered_will',18,2,0); -INSERT INTO `server_statuseffects` VALUES (223075,'featherfoot',131122,2,0); -INSERT INTO `server_statuseffects` VALUES (223078,'enduring_march',18,2,0); -INSERT INTO `server_statuseffects` VALUES (223081,'bloodbath',1048626,2,0); -INSERT INTO `server_statuseffects` VALUES (223083,'foresight',262194,2,0); -INSERT INTO `server_statuseffects` VALUES (223091,'keen_flurry',18,2,0); -INSERT INTO `server_statuseffects` VALUES (223094,'invigorate',18,2,0); -INSERT INTO `server_statuseffects` VALUES (223097,'collusion',1048626,1,0); -INSERT INTO `server_statuseffects` VALUES (223104,'quelling_strike',1058,2,0); -INSERT INTO `server_statuseffects` VALUES (223106,'hawks_eye',18,2,0); -INSERT INTO `server_statuseffects` VALUES (223108,'decoy',4130,2,0); -INSERT INTO `server_statuseffects` VALUES (223127,'bloodletter',42,2,0); -INSERT INTO `server_statuseffects` VALUES (223129,'protect',18,2,0); -INSERT INTO `server_statuseffects` VALUES (223133,'stoneskin',16402,1,0); -INSERT INTO `server_statuseffects` VALUES (223173,'covered',42,2,0); -INSERT INTO `server_statuseffects` VALUES (223180,'regen',18,2,0); -INSERT INTO `server_statuseffects` VALUES (223181,'refresh',18,2,0); -INSERT INTO `server_statuseffects` VALUES (223182,'regain',18,2,0); -INSERT INTO `server_statuseffects` VALUES (223183,'tp_bleed',42,2,0); -INSERT INTO `server_statuseffects` VALUES (223205,'combo',42,2,0); -INSERT INTO `server_statuseffects` VALUES (223206,'goring_blade',42,2,0); -INSERT INTO `server_statuseffects` VALUES (223207,'berserk2',1074806818,1,0); -INSERT INTO `server_statuseffects` VALUES (223208,'rampage2',1075855394,1,5000); -INSERT INTO `server_statuseffects` VALUES (223209,'fists_of_fire',1073742882,2,0); -INSERT INTO `server_statuseffects` VALUES (223210,'fists_of_earth',1073742882,2,0); -INSERT INTO `server_statuseffects` VALUES (223211,'fists_of_wind',1073742882,2,0); -INSERT INTO `server_statuseffects` VALUES (223212,'power_surge_I',1058,2,0); -INSERT INTO `server_statuseffects` VALUES (223213,'power_surge_II',1058,2,0); -INSERT INTO `server_statuseffects` VALUES (223214,'power_surge_III',1058,2,0); -INSERT INTO `server_statuseffects` VALUES (223215,'life_surge_I',1048626,2,0); -INSERT INTO `server_statuseffects` VALUES (223216,'life_surge_II',1048626,2,0); -INSERT INTO `server_statuseffects` VALUES (223217,'life_surge_III',1048626,2,0); -INSERT INTO `server_statuseffects` VALUES (223218,'dread_spike',16418,2,0); -INSERT INTO `server_statuseffects` VALUES (223219,'blood_for_blood',8210,2,0); -INSERT INTO `server_statuseffects` VALUES (223220,'barrage',3090,2,0); -INSERT INTO `server_statuseffects` VALUES (223221,'raging_strike2',1074855970,1,0); -INSERT INTO `server_statuseffects` VALUES (223227,'cleric_stance',8226,1,0); -INSERT INTO `server_statuseffects` VALUES (223228,'blissful_mind',1073741858,1,1000); -INSERT INTO `server_statuseffects` VALUES (223229,'dark_seal2',1042,2,0); -INSERT INTO `server_statuseffects` VALUES (223230,'resonance2',2578,1,0); -INSERT INTO `server_statuseffects` VALUES (223231,'excruciate',2098194,2,3000); -INSERT INTO `server_statuseffects` VALUES (223232,'necrogenesis',1048594,1,0); -INSERT INTO `server_statuseffects` VALUES (223233,'parsimony',1049106,1,0); -INSERT INTO `server_statuseffects` VALUES (223234,'sanguine_rite2',16402,1,0); -INSERT INTO `server_statuseffects` VALUES (223236,'outmaneuver2',524338,2,0); -INSERT INTO `server_statuseffects` VALUES (223237,'blindside2',8226,1,0); -INSERT INTO `server_statuseffects` VALUES (223238,'decoy2',4130,2,0); -INSERT INTO `server_statuseffects` VALUES (223239,'protect2',18,2,0); -INSERT INTO `server_statuseffects` VALUES (223240,'sanguine_rite3',16402,1,0); -INSERT INTO `server_statuseffects` VALUES (223241,'bloodletter2',42,2,0); -INSERT INTO `server_statuseffects` VALUES (223242,'fully_blissful_mind',1073741858,1,0); -INSERT INTO `server_statuseffects` VALUES (223243,'magic_evasion_down',18,2,0); -INSERT INTO `server_statuseffects` VALUES (223245,'spinning_heel',18,1,0); -INSERT INTO `server_statuseffects` VALUES (223248,'divine_veil',36914,2,0); -INSERT INTO `server_statuseffects` VALUES (223250,'vengeance',16418,1,5000); -INSERT INTO `server_statuseffects` VALUES (223251,'antagonize',1048626,2,0); -INSERT INTO `server_statuseffects` VALUES (223253,'battle_voice',18,2,0); -INSERT INTO `server_statuseffects` VALUES (223254,'ballad_of_magi',18,2,0); -INSERT INTO `server_statuseffects` VALUES (223255,'paeon_of_war',18,2,0); -INSERT INTO `server_statuseffects` VALUES (223256,'minuet_of_rigor',18,2,0); -INSERT INTO `server_statuseffects` VALUES (223264,'divine_regen',18,2,0); -INSERT INTO `server_statuseffects` VALUES (228021,'heavy',42,2,0); -INSERT INTO `server_statuseffects` VALUES (253003,'evade_proc',34,1,0); -INSERT INTO `server_statuseffects` VALUES (253004,'block_proc',34,1,0); -INSERT INTO `server_statuseffects` VALUES (253005,'parry_proc',34,1,0); -INSERT INTO `server_statuseffects` VALUES (253006,'miss_proc',34,1,0); -INSERT INTO `server_statuseffects` VALUES (253007,'expchain',34,1,0); +INSERT INTO `server_statuseffects` VALUES (223001,'quick',9,2,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223002,'haste',9,2,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223003,'slow',21,2,0,0,0,0,30335,30338); +INSERT INTO `server_statuseffects` VALUES (223004,'petrification',264241173,2,0,0,0,0,30335,30338); +INSERT INTO `server_statuseffects` VALUES (223005,'paralysis',21,2,3000,0,0,0,30335,30338); +INSERT INTO `server_statuseffects` VALUES (223006,'silence',4194325,2,0,0,0,0,30335,30338); +INSERT INTO `server_statuseffects` VALUES (223007,'blind',21,2,0,0,0,0,30335,30338); +INSERT INTO `server_statuseffects` VALUES (223008,'mute',4194325,2,0,0,0,0,30335,30338); +INSERT INTO `server_statuseffects` VALUES (223009,'slowcast',517,1,0,0,0,0,30335,30338); +INSERT INTO `server_statuseffects` VALUES (223010,'glare',21,2,0,0,0,0,30335,30338); +INSERT INTO `server_statuseffects` VALUES (223011,'poison',21,2,0,0,0,0,30335,30338); +INSERT INTO `server_statuseffects` VALUES (223012,'transfixion',268435477,2,0,0,0,0,30335,30338); +INSERT INTO `server_statuseffects` VALUES (223013,'pacification',8388629,2,0,0,0,0,30335,30338); +INSERT INTO `server_statuseffects` VALUES (223014,'amnesia',16777237,2,0,0,0,0,30335,30338); +INSERT INTO `server_statuseffects` VALUES (223015,'stun',264241173,2,0,0,0,0,30335,30338); +INSERT INTO `server_statuseffects` VALUES (223016,'daze',264241173,2,0,0,0,0,30335,30338); +INSERT INTO `server_statuseffects` VALUES (223029,'hp_boost',9,2,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223030,'hp_penalty',21,2,0,0,0,0,30335,30338); +INSERT INTO `server_statuseffects` VALUES (223038,'defense_down',21,2,0,0,0,0,30335,30338); +INSERT INTO `server_statuseffects` VALUES (223058,'aegis_boon',528409,2,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223062,'sentinel',1048601,2,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223063,'cover',16409,2,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223064,'rampart',9,2,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223068,'tempered_will',9,2,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223075,'featherfoot',131097,2,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223078,'enduring_march',9,2,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223081,'bloodbath',1048601,2,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223083,'foresight',262169,2,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223091,'keen_flurry',1033,2,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223094,'invigorate',9,2,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223097,'collusion',1048601,1,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223104,'quelling_strike',1041,2,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223106,'hawks_eye',9,2,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223108,'decoy',4113,2,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223127,'bloodletter',21,2,0,0,0,0,30335,30338); +INSERT INTO `server_statuseffects` VALUES (223129,'protect',9,2,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223133,'stoneskin',16393,1,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223173,'covered',4105,2,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223180,'regen',9,2,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223181,'refresh',9,2,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223182,'regain',9,2,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223183,'tp_bleed',21,2,0,0,0,0,30335,30338); +INSERT INTO `server_statuseffects` VALUES (223205,'combo',21,2,0,0,1,0,0,30331); +INSERT INTO `server_statuseffects` VALUES (223206,'goring_blade',21,2,0,0,0,0,30335,30338); +INSERT INTO `server_statuseffects` VALUES (223207,'berserk2',537936145,1,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223208,'rampage2',538984721,1,5000,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223209,'fists_of_fire',536872209,2,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223210,'fists_of_earth',536872209,2,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223211,'fists_of_wind',536872209,2,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223212,'power_surge_I',1297,2,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223213,'power_surge_II',1297,2,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223214,'power_surge_III',1297,2,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223215,'life_surge_I',1048857,2,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223216,'life_surge_II',1048857,2,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223217,'life_surge_III',1048857,2,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223218,'dread_spike',16649,2,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223219,'blood_for_blood',8209,2,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223220,'barrage',3081,2,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223221,'raging_strike2',537985297,1,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223224,'swiftsong',137,2,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223227,'cleric_stance',8209,1,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223228,'blissful_mind',536871185,1,1000,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223229,'dark_seal2',1033,2,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223230,'resonance2',2569,1,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223231,'excruciate',2098185,2,3000,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223232,'necrogenesis',1048585,1,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223233,'parsimony',1049097,1,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223234,'sanguine_rite2',16393,1,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223235,'aero',21,2,0,0,0,0,30335,30338); +INSERT INTO `server_statuseffects` VALUES (223236,'outmaneuver2',524313,2,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223237,'blindside2',8209,1,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223238,'decoy2',4113,2,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223239,'protect2',9,2,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223240,'sanguine_rite3',16393,1,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223241,'bloodletter2',21,2,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223242,'fully_blissful_mind',536871185,1,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223243,'magic_evasion_down',9,2,0,0,0,0,30335,30338); +INSERT INTO `server_statuseffects` VALUES (223244,'hundred_fists',257,2,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223245,'spinning_heel',9,1,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223248,'divine_veil',36889,2,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223250,'vengeance',16401,1,5000,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223251,'antagonize',1048601,2,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223252,'mighty_strikes',8209,1,3000,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223253,'battle_voice',9,2,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223254,'ballad_of_magi',9,2,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223255,'paeon_of_war',9,2,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223256,'minuet_of_rigor',9,2,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (223264,'divine_regen',9,2,0,0,0,0,30328,30331); +INSERT INTO `server_statuseffects` VALUES (228001,'sleep',264273941,2,0,0,0,0,30335,30338); +INSERT INTO `server_statuseffects` VALUES (228011,'bind',67108885,2,0,0,0,0,30335,30338); +INSERT INTO `server_statuseffects` VALUES (228021,'heavy',21,2,0,0,0,0,30335,30338); +INSERT INTO `server_statuseffects` VALUES (300000,'evade_proc',273,1,0,1,1,1,0,30331); +INSERT INTO `server_statuseffects` VALUES (300001,'block_proc',273,1,0,1,1,1,0,30331); +INSERT INTO `server_statuseffects` VALUES (300002,'parry_proc',273,1,0,1,1,1,0,30331); +INSERT INTO `server_statuseffects` VALUES (300003,'miss_proc',273,1,0,1,1,1,0,30331); +INSERT INTO `server_statuseffects` VALUES (300004,'expchain',273,1,0,1,1,1,0,30331); /*!40000 ALTER TABLE `server_statuseffects` ENABLE KEYS */; UNLOCK TABLES; commit; @@ -140,4 +153,4 @@ commit; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2018-06-25 23:30:50 +-- Dump completed on 2019-06-05 18:56:07