mirror of
https://bitbucket.org/Ioncannon/project-meteor-server.git
synced 2025-04-02 19:42:05 -04:00
BattleCommand changes
New targeting flags for BattleCommand and TargetFind. (This breaks combat until new BattleCommand data is in) Changed MP and TP to shorts in BattleCommand to handle cases where they might go negative. (might not be correct?)
This commit is contained in:
parent
3e58cdbd6c
commit
a458608322
@ -2431,8 +2431,8 @@ namespace FFXIVClassic_Map_Server
|
|||||||
battleCommand.castTimeMs = reader.GetUInt32("castTime");
|
battleCommand.castTimeMs = reader.GetUInt32("castTime");
|
||||||
battleCommand.maxRecastTimeSeconds = reader.GetUInt32("recastTime");
|
battleCommand.maxRecastTimeSeconds = reader.GetUInt32("recastTime");
|
||||||
battleCommand.recastTimeMs = battleCommand.maxRecastTimeSeconds * 1000;
|
battleCommand.recastTimeMs = battleCommand.maxRecastTimeSeconds * 1000;
|
||||||
battleCommand.mpCost = reader.GetUInt16("mpCost");
|
battleCommand.mpCost = reader.GetInt16("mpCost");
|
||||||
battleCommand.tpCost = reader.GetUInt16("tpCost");
|
battleCommand.tpCost = reader.GetInt16("tpCost");
|
||||||
battleCommand.animationType = reader.GetByte("animationType");
|
battleCommand.animationType = reader.GetByte("animationType");
|
||||||
battleCommand.effectAnimation = reader.GetUInt16("effectAnimation");
|
battleCommand.effectAnimation = reader.GetUInt16("effectAnimation");
|
||||||
battleCommand.modelAnimation = reader.GetUInt16("modelAnimation");
|
battleCommand.modelAnimation = reader.GetUInt16("modelAnimation");
|
||||||
|
@ -1160,8 +1160,8 @@ namespace FFXIVClassic_Map_Server.Actors
|
|||||||
public List<Character> GetPartyMembersInRange(uint range)
|
public List<Character> GetPartyMembersInRange(uint range)
|
||||||
{
|
{
|
||||||
TargetFind targetFind = new TargetFind(this);
|
TargetFind targetFind = new TargetFind(this);
|
||||||
targetFind.SetAOEType(ValidTarget.PartyMember, TargetFindAOEType.Circle, TargetFindAOETarget.Self, range, 0, 10, 0, 0);
|
targetFind.SetAOEType(ValidTarget.Party, TargetFindAOEType.Circle, TargetFindAOETarget.Self, range, 0, 10, 0, 0);
|
||||||
targetFind.FindWithinArea(this, ValidTarget.PartyMember, TargetFindAOETarget.Self);
|
targetFind.FindWithinArea(this, ValidTarget.Party, TargetFindAOETarget.Self);
|
||||||
return targetFind.GetTargets();
|
return targetFind.GetTargets();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -114,8 +114,8 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
|
|||||||
public uint castTimeMs; //cast time in milliseconds
|
public uint castTimeMs; //cast time in milliseconds
|
||||||
public uint recastTimeMs; //recast time in milliseconds
|
public uint recastTimeMs; //recast time in milliseconds
|
||||||
public uint maxRecastTimeSeconds; //maximum recast time in seconds
|
public uint maxRecastTimeSeconds; //maximum recast time in seconds
|
||||||
public ushort mpCost;
|
public short mpCost; //short in case these casts can have negative cost
|
||||||
public ushort tpCost;
|
public short tpCost; //short because there are certain cases where we want weaponskills to have negative costs (such as Feint)
|
||||||
public byte animationType;
|
public byte animationType;
|
||||||
public ushort effectAnimation;
|
public ushort effectAnimation;
|
||||||
public ushort modelAnimation;
|
public ushort modelAnimation;
|
||||||
@ -193,10 +193,10 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
|
|||||||
return castTimeMs == 0;
|
return castTimeMs == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Checks whether the skill can be used on the given 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)
|
public bool IsValidMainTarget(Character user, Character target, CommandResult error = null)
|
||||||
{
|
{
|
||||||
targetFind = new TargetFind(user);
|
targetFind = new TargetFind(user, target);
|
||||||
|
|
||||||
if (aoeType == TargetFindAOEType.Box)
|
if (aoeType == TargetFindAOEType.Box)
|
||||||
{
|
{
|
||||||
@ -209,6 +209,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
worldMasterTextId
|
worldMasterTextId
|
||||||
|
32511 Target does not exist
|
||||||
32512 cannot be performed on a KO'd target.
|
32512 cannot be performed on a KO'd target.
|
||||||
32513 can only be performed on a KO'd target.
|
32513 can only be performed on a KO'd target.
|
||||||
32514 cannot be performed on yourself.
|
32514 cannot be performed on yourself.
|
||||||
@ -216,117 +217,112 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
|
|||||||
32516 cannot be performed on a friendly target.
|
32516 cannot be performed on a friendly target.
|
||||||
32517 can only be performed on a friendly target.
|
32517 can only be performed on a friendly target.
|
||||||
32518 cannot be performed on an enemy.
|
32518 cannot be performed on an enemy.
|
||||||
32519 can only be performed on an enemy,
|
32519 can only be performed on an enemy.
|
||||||
32556 unable to execute [weaponskill]. Conditions for use are not met.
|
32547 That command cannot be performed on the current target.
|
||||||
|
32548 That command cannot be performed on a party member
|
||||||
*/
|
*/
|
||||||
|
if (target == null)
|
||||||
// cant target dead
|
|
||||||
if ((mainTarget & (ValidTarget.Corpse | ValidTarget.CorpseOnly)) == 0 && target.IsDead())
|
|
||||||
{
|
{
|
||||||
// cannot be perfomed on
|
error?.SetTextId(32511);
|
||||||
if (user is Player)
|
|
||||||
((Player)user).SendGameMessage(Server.GetWorldManager().GetActor(), 32512, 0x20, (uint)id);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//level too high
|
//This skill can't be used on a corpse and target is dead
|
||||||
if (level > user.GetLevel())
|
if ((mainTarget & ValidTarget.Corpse) == 0 && target.IsDead())
|
||||||
{
|
{
|
||||||
if (user is Player)
|
error?.SetTextId(32512);
|
||||||
((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);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//costs too much tp
|
//This skill must be used on a corpse and target is alive
|
||||||
if (CalculateTpCost(user) > user.GetTP())
|
if ((mainTarget & ValidTarget.CorpseOnly) != 0 && target.IsAlive())
|
||||||
{
|
{
|
||||||
if (user is Player)
|
error?.SetTextId(32513);
|
||||||
((Player)user).SendGameMessage(Server.GetWorldManager().GetActor(), 32546, 0x20, (uint)id);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: calculate cost based on modifiers also (probably in BattleUtils)
|
//This skill can't be used on self and target is self
|
||||||
if (BattleUtils.CalculateSpellCost(user, target, this) > user.GetMP())
|
if ((mainTarget & ValidTarget.Self) == 0 && target == user)
|
||||||
{
|
{
|
||||||
if (user is Player)
|
error?.SetTextId(32514);
|
||||||
((Player)user).SendGameMessage(Server.GetWorldManager().GetActor(), 32545, 0x20, (uint)id);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: check target requirements
|
//This skill must be used on self and target isn't self
|
||||||
if (requirements != BattleCommandRequirements.None)
|
if ((mainTarget & ValidTarget.SelfOnly) != 0 && target != user)
|
||||||
{
|
{
|
||||||
if (false)
|
error?.SetTextId(32515);
|
||||||
{
|
|
||||||
// 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;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
//This skill can't be used on an ally and target is an ally
|
||||||
// todo: i dont care to message for each scenario, just the most common ones..
|
if ((mainTarget & ValidTarget.Ally) == 0 && target.allegiance == user.allegiance)
|
||||||
if ((mainTarget & ValidTarget.CorpseOnly) != 0)
|
|
||||||
{
|
{
|
||||||
if (target != null && target.IsAlive())
|
error?.SetTextId(32516);
|
||||||
{
|
|
||||||
if (user is Player)
|
|
||||||
((Player)user).SendGameMessage(Server.GetWorldManager().GetActor(), 32513, 0x20, (uint)id);
|
|
||||||
return false;
|
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 &&
|
error?.SetTextId(32517);
|
||||||
user.allegiance == target.allegiance)
|
|
||||||
{
|
|
||||||
if (user is Player)
|
|
||||||
((Player)user).SendGameMessage(Server.GetWorldManager().GetActor(), 32519, 0x20, (uint)id);
|
|
||||||
return false;
|
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)
|
error?.SetTextId(32518);
|
||||||
{
|
|
||||||
if (user is Player)
|
|
||||||
((Player)user).SendGameMessage(Server.GetWorldManager().GetActor(), 32517, 0x20, (uint)id);
|
|
||||||
return false;
|
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)
|
error?.SetTextId(32519);
|
||||||
{
|
|
||||||
if (user is Player)
|
|
||||||
((Player)user).SendGameMessage(Server.GetWorldManager().GetActor(), 32547, 0x20, (uint)id);
|
|
||||||
return false;
|
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))
|
error?.SetTextId(32548);
|
||||||
{
|
|
||||||
if (user is Player)
|
|
||||||
((Player)user).SendGameMessage(Server.GetWorldManager().GetActor(), 32517, 0x20, (uint)id);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//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;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;// targetFind.CanTarget(target, true, true, true); //this will be done later
|
//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)
|
public ushort CalculateMpCost(Character user)
|
||||||
@ -368,15 +364,15 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
|
|||||||
//Calculate TP cost taking into considerating the combo bonus rate for players
|
//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?
|
//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
|
//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
|
//Calculate tp cost
|
||||||
if (user is Player)
|
if (user is Player)
|
||||||
{
|
{
|
||||||
var player = user as Player;
|
var player = user as Player;
|
||||||
if (player.playerWork.comboNextCommandId[0] == id || player.playerWork.comboNextCommandId[1] == id)
|
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;
|
return tp;
|
||||||
|
@ -14,21 +14,24 @@ using FFXIVClassic_Map_Server.packets.send.actor;
|
|||||||
|
|
||||||
namespace FFXIVClassic_Map_Server.actors.chara.ai
|
namespace FFXIVClassic_Map_Server.actors.chara.ai
|
||||||
{
|
{
|
||||||
// https://github.com/Windower/POLUtils/blob/master/PlayOnline.FFXI/Enums.cs
|
|
||||||
[Flags]
|
[Flags]
|
||||||
public enum ValidTarget : ushort
|
public enum ValidTarget : ushort
|
||||||
{
|
{
|
||||||
None = 0x00,
|
None = 0x00,
|
||||||
Self = 0x01,
|
Self = 0x01, //Can be used on self (if this flag isn't set and target is self, return false)
|
||||||
Player = 0x02,
|
SelfOnly = 0x02, //Must be used on self (if this flag is set and target isn't self, return false)
|
||||||
PartyMember = 0x04,
|
Party = 0x4, //Can be used on party members
|
||||||
Ally = 0x08,
|
PartyOnly = 0x8, //Must be used on party members
|
||||||
NPC = 0x10,
|
Ally = 0x10, //Can be used on allies
|
||||||
Enemy = 0x20,
|
AllyOnly = 0x20, //Must be used on allies
|
||||||
Unknown = 0x40,
|
NPC = 0x40, //Can be used on static NPCs
|
||||||
Object = 0x60,
|
NPCOnly = 0x60, //Must be used on static NPCs
|
||||||
CorpseOnly = 0x80,
|
Enemy = 0x80, //Can be used on enemies
|
||||||
Corpse = 0x9D // CorpseOnly + NPC + Ally + Partymember + Self
|
EnemyOnly = 0x100, //Must be used on enemies
|
||||||
|
Object = 0x200, //Can be used on objects
|
||||||
|
ObjectOnly = 0x400, //Must be used on objects
|
||||||
|
Corpse = 0x600, //Can be used on corpses
|
||||||
|
CorpseOnly = 0x800, //Must be used on corpses
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Targeting from/to different entity types </summary>
|
/// <summary> Targeting from/to different entity types </summary>
|
||||||
@ -70,12 +73,13 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
|
|||||||
class TargetFind
|
class TargetFind
|
||||||
{
|
{
|
||||||
private Character owner;
|
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 TargetFindCharacterType findType;
|
||||||
private ValidTarget validTarget;
|
private ValidTarget validTarget;
|
||||||
private TargetFindAOETarget aoeTarget;
|
private TargetFindAOETarget aoeTarget;
|
||||||
private TargetFindAOEType aoeType;
|
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 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 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
|
private float minDistance; //Minimum distance to that target must be to be able to be hit
|
||||||
@ -86,14 +90,16 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
|
|||||||
private float param;
|
private float param;
|
||||||
private List<Character> targets;
|
private List<Character> targets;
|
||||||
|
|
||||||
public TargetFind(Character owner)
|
public TargetFind(Character owner, Character mainTarget = null)
|
||||||
{
|
{
|
||||||
this.owner = owner;
|
|
||||||
Reset();
|
Reset();
|
||||||
|
this.owner = owner;
|
||||||
|
this.masterTarget = mainTarget == null ? owner : mainTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Reset()
|
public void Reset()
|
||||||
{
|
{
|
||||||
|
this.mainTarget = owner;
|
||||||
this.findType = TargetFindCharacterType.None;
|
this.findType = TargetFindCharacterType.None;
|
||||||
this.validTarget = ValidTarget.Enemy;
|
this.validTarget = ValidTarget.Enemy;
|
||||||
this.aoeType = TargetFindAOEType.None;
|
this.aoeType = TargetFindAOEType.None;
|
||||||
@ -205,11 +211,6 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
|
|||||||
|
|
||||||
//if (targets.Count > 8)
|
//if (targets.Count > 8)
|
||||||
//targets.RemoveRange(8, 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()); });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -327,41 +328,57 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
|
|||||||
if (target == null || !retarget && targets.Contains(target))
|
if (target == null || !retarget && targets.Contains(target))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
//This skill can't be used on self and target is self, return false
|
if (target == null)
|
||||||
if ((validTarget & ValidTarget.Self) == 0 && target == owner)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
//This skill can't be used on NPCs and target is an NPC, return false
|
//This skill can't be used on a corpse and target is dead
|
||||||
if ((validTarget & ValidTarget.NPC) == 0 && target.isStatic)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
//This skill can't be used on corpses and target is dead, return false
|
|
||||||
if ((validTarget & ValidTarget.Corpse) == 0 && target.IsDead())
|
if ((validTarget & ValidTarget.Corpse) == 0 && target.IsDead())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
//This skill must be used on Allies and target is not an ally, return false
|
//This skill must be used on a corpse and target is alive
|
||||||
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
|
|
||||||
if ((validTarget & ValidTarget.CorpseOnly) != 0 && target.IsAlive())
|
if ((validTarget & ValidTarget.CorpseOnly) != 0 && target.IsAlive())
|
||||||
return false;
|
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?
|
// todo: why is player always zoning?
|
||||||
// cant target if zoning
|
// cant target if zoning
|
||||||
if (target is Player && ((Player)target).playerSession.isUpdatesLocked)
|
if (target is Player && ((Player)target).playerSession.isUpdatesLocked)
|
||||||
|
Loading…
Reference in New Issue
Block a user