mirror of
				https://bitbucket.org/Ioncannon/project-meteor-server.git
				synced 2025-05-20 08:26:59 -04:00 
			
		
		
		
	More targeting changes
Added CanUse instead of CanAttack/CanWeaponSkill/CanCast since they all check the same things anyway. Fixed some bugs like mp checking against hp in AddMP.
This commit is contained in:
		| @@ -232,8 +232,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) | ||||
| @@ -247,9 +246,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. | ||||
|             } | ||||
|         } | ||||
|  | ||||
| @@ -446,20 +442,11 @@ 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() | ||||
|         { | ||||
| @@ -628,7 +615,7 @@ namespace FFXIVClassic_Map_Server.Actors | ||||
|         public void SetMP(uint mp) | ||||
|         { | ||||
|             charaWork.parameterSave.mpMax = (short)mp; | ||||
|             if (mp > charaWork.parameterSave.hpMax[0]) | ||||
|             if (mp > charaWork.parameterSave.mpMax) | ||||
|                 SetMaxMP(mp); | ||||
|  | ||||
|             updateFlags |= ActorUpdateFlags.HpTpMp; | ||||
| @@ -1070,6 +1057,7 @@ namespace FFXIVClassic_Map_Server.Actors | ||||
|         { | ||||
|             statusEffects.CallLuaFunctionByFlag((uint)StatusEffectFlags.ActivateOnHit, "onCrit", this, defender, action, actionContainer); | ||||
|         } | ||||
|  | ||||
|         //The order of messages that appears after using a command is: | ||||
|  | ||||
|         //1. Cast start messages. (ie "You begin casting... ") | ||||
| @@ -1146,13 +1134,14 @@ namespace FFXIVClassic_Map_Server.Actors | ||||
|             { | ||||
|                 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()); | ||||
|         } | ||||
|   | ||||
| @@ -36,13 +36,12 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state | ||||
|  | ||||
|             this.target = target != null ? target : owner; | ||||
|  | ||||
|             if (returnCode == 0 && owner.CanCast(this.target, spell)) | ||||
|             if (returnCode == 0 && owner.CanUse(this.target, spell, errorResult)) | ||||
|             { | ||||
|                 OnStart(); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 errorResult = new CommandResult(owner.actorId, 32553, 0); | ||||
|                 interrupt = true; | ||||
|             } | ||||
|         } | ||||
| @@ -174,7 +173,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() | ||||
|   | ||||
| @@ -24,7 +24,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state | ||||
|             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)) | ||||
|             if (returnCode == 0 && owner.CanUse(this.target, skill, errorResult)) | ||||
|             { | ||||
|                 OnStart(); | ||||
|             } | ||||
| @@ -167,7 +167,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() | ||||
|   | ||||
| @@ -188,7 +188,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) | ||||
| @@ -209,18 +209,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; | ||||
| @@ -264,7 +252,7 @@ namespace FFXIVClassic_Map_Server.Actors | ||||
|             zone.BroadcastPacketsAroundActor(this, GetSpawnPackets(null, 0x01)); | ||||
|             zone.BroadcastPacketsAroundActor(this, GetInitPackets()); | ||||
|             charaWork.parameterSave.hp = charaWork.parameterSave.hpMax; | ||||
|             charaWork.parameterSave.mp = charaWork.parameterSave.mpMax; | ||||
|             charaWork.parameterSave.hp = (short[])charaWork.parameterSave.hpMax.Clone(); | ||||
|             RecalculateStats(); | ||||
|  | ||||
|             OnSpawn(); | ||||
|   | ||||
| @@ -2169,110 +2169,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; | ||||
|         } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user