786 lines
28 KiB
C#
786 lines
28 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
|
|
using System.Text;
|
|
using UnityEngine;
|
|
|
|
using Thousandto.Cfg.Data;
|
|
using Thousandto.Code.Logic.LocalPlayerBT;
|
|
using Thousandto.Core.Asset;
|
|
using Thousandto.Core.Base;
|
|
using Thousandto.Code.Center;
|
|
using Thousandto.Code.Global;
|
|
using Thousandto.Plugins.Common.UniScene;
|
|
#pragma warning disable 0219
|
|
#pragma warning disable 0168
|
|
#pragma warning disable 0162
|
|
namespace Thousandto.Code.Logic
|
|
{
|
|
/// <summary>
|
|
/// 战斗的一些通用函数
|
|
/// </summary>
|
|
public static class CombatUtil
|
|
{
|
|
//查询目标时的缓存信息
|
|
private static List<SearchTargetInfo> _searchCache = new List<SearchTargetInfo>(32);
|
|
private static List<SearchCollectionInfo> _searchCollectCache = new List<SearchCollectionInfo>(32);
|
|
|
|
//用于排序的比较函数
|
|
private static Comparison<SearchTargetInfo> compareFunc;
|
|
private static Comparison<SearchTargetInfo> compareAngleFunc;
|
|
private static Comparison<SearchCollectionInfo> compareCollectFunc;
|
|
|
|
//静态构造函数
|
|
static CombatUtil()
|
|
{
|
|
compareFunc = (left, right) =>
|
|
{
|
|
return left.distanceSq.CompareTo(right.distanceSq);
|
|
};
|
|
|
|
compareAngleFunc = (left, right) =>
|
|
{
|
|
return left.angle.CompareTo(right.angle);
|
|
};
|
|
|
|
compareCollectFunc = (left, right) =>
|
|
{
|
|
return left.distanceSq.CompareTo(right.distanceSq);
|
|
};
|
|
|
|
}
|
|
|
|
public static SkillHitType ConvertToHitType(int serverData)
|
|
{
|
|
if (IsBeatHit(serverData))
|
|
{
|
|
return SkillHitType.HitStiff;
|
|
}
|
|
else if (IsBeatBack(serverData))
|
|
{
|
|
return SkillHitType.HitBack;
|
|
}
|
|
else if (IsBeatFly(serverData))
|
|
{
|
|
return SkillHitType.HitFly;
|
|
}
|
|
else if (IsBeatGrap(serverData))
|
|
{
|
|
return SkillHitType.HitGrab;
|
|
}
|
|
return SkillHitType.None;
|
|
}
|
|
//受击僵直
|
|
public static bool IsBeatHit(int type)
|
|
{
|
|
if ((type & (int)SkillEffectType.AttackHit) != 0)
|
|
return true;
|
|
return false;
|
|
}
|
|
//击退
|
|
public static bool IsBeatBack(int type)
|
|
{
|
|
if ((type & (int)SkillEffectType.AttackBack) != 0)
|
|
return true;
|
|
return false;
|
|
}
|
|
//击飞
|
|
public static bool IsBeatFly(int type)
|
|
{
|
|
if ((type & (int)SkillEffectType.AttackFly) != 0)
|
|
return true;
|
|
return false;
|
|
}
|
|
//抓取
|
|
public static bool IsBeatGrap(int type)
|
|
{
|
|
if ((type & (int)SkillEffectType.AttackGrab) != 0)
|
|
return true;
|
|
return false;
|
|
}
|
|
//暴击
|
|
public static bool IsCrit(int type)
|
|
{
|
|
if ((type & (uint)SkillEffectType.Crit) != 0)
|
|
return true;
|
|
return false;
|
|
}
|
|
//会心
|
|
public static bool IsHuiXin(int type)
|
|
{
|
|
if ((type & (uint)SkillEffectType.HuiXin) != 0)
|
|
return true;
|
|
return false;
|
|
}
|
|
//致命一击
|
|
public static bool IsZhuiJi(int type)
|
|
{
|
|
if ((type & (uint)SkillEffectType.ZhuiJi) != 0)
|
|
return true;
|
|
return false;
|
|
}
|
|
//幸运一击
|
|
public static bool IsLianJi(int type)
|
|
{
|
|
if ((type & (uint)SkillEffectType.LianJi) != 0)
|
|
return true;
|
|
return false;
|
|
}
|
|
//无敌
|
|
public static bool IsInvincible(int type)
|
|
{
|
|
if ((type & (uint)SkillEffectType.Invincible) != 0)
|
|
return true;
|
|
return false;
|
|
}
|
|
//免疫
|
|
public static bool IsImmune(int type)
|
|
{
|
|
if ((type & (uint)SkillEffectType.Immune) != 0)
|
|
return true;
|
|
return false;
|
|
}
|
|
//是否是多倍攻击
|
|
public static bool IsMultipleAtk(int type)
|
|
{
|
|
if ((type & (uint)SkillEffectType.MultipleAtk) != 0)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
//获取技能寻路距离
|
|
public static float GetSkillFindPathDis(SkillVisualInfo skill)
|
|
{
|
|
if (skill == null)
|
|
return 0f;
|
|
if (skill.UseNeedDis <= 1.5f)
|
|
{
|
|
return skill.UseNeedDis * 0.8f;
|
|
}
|
|
else
|
|
{
|
|
return skill.UseNeedDis - 1.5f;
|
|
}
|
|
}
|
|
|
|
//是否可以选择玩家
|
|
public static bool CanShowRPhead(LocalPlayer user, RemotePlayer rp)
|
|
{
|
|
if (rp == null || user == null)
|
|
return false;
|
|
if (GameCenter.LuaSystem.Adaptor.IsTeamMember(rp.ID))
|
|
{
|
|
return true;
|
|
}
|
|
//判断地图是否能够PK
|
|
if (user.Scene.Cfg != null && user.Scene.Cfg.PkState == 0)
|
|
{
|
|
return true;
|
|
}
|
|
//判断是否在仇恨列表
|
|
if (user.IsStrikeBack(rp.ID))
|
|
{
|
|
return false;
|
|
}
|
|
//var pkDefine = PkValueConstDefine.GetPkDefine(rp.PropMoudle.PkValue);
|
|
//if (pkDefine != null && pkDefine.CanBeAttack) //PK值高到可以被主动攻击
|
|
//{
|
|
// return false;
|
|
//}
|
|
if (CheckPKModel(user, rp))
|
|
{
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
//判断两个阵营之间是否可以攻击
|
|
public static bool MonsterSceneCampIsEnemy(int camp1, int camp2, int type)
|
|
{
|
|
switch (type)
|
|
{
|
|
case 1:
|
|
if (camp2 >= 1 && camp2 <= 16)
|
|
{
|
|
return (camp1 >> (camp2 - 1) & 1) == 0;
|
|
}
|
|
break;
|
|
}
|
|
return camp1 != camp2;
|
|
}
|
|
//判断两个阵营之间是否可以攻击
|
|
public static bool PlayerSceneCampIsEnemy(int camp1, int camp2, int type)
|
|
{
|
|
switch (type)
|
|
{
|
|
case 1:
|
|
return (camp1 >> 16) != (camp2 >> 16);
|
|
}
|
|
return camp1 != camp2;
|
|
}
|
|
|
|
//是否是技能的目标
|
|
public static bool CanAttackTarget(LocalPlayer user, Character c, bool checkBlock)
|
|
{
|
|
bool result = false;
|
|
do
|
|
{
|
|
if (c == null || c.IsDead() || c.InSafeTile)
|
|
{
|
|
result = false;
|
|
break;
|
|
}
|
|
|
|
//宠物不能被攻击
|
|
if (c is Pet)
|
|
{
|
|
result = false;
|
|
break;
|
|
}
|
|
|
|
if (c is Monster)
|
|
{
|
|
//判断怪物阵营
|
|
result = MonsterSceneCampIsEnemy(user.PropMoudle.SceneCampID, c.PropMoudle.SceneCampID, user.Scene.Cfg.SceneCameMatchType);
|
|
break;
|
|
}
|
|
|
|
if (c is RemotePlayer)
|
|
{
|
|
RemotePlayer rp = c as RemotePlayer;
|
|
if (GameCenter.LuaSystem.Adaptor.IsTeamMember(rp.ID))
|
|
{
|
|
result = false;
|
|
break;
|
|
}
|
|
|
|
//判断地图是否能够PK
|
|
if (user.Scene.Cfg != null && user.Scene.Cfg.PkState == 0)
|
|
{
|
|
result = false;
|
|
break;
|
|
}
|
|
|
|
//判断是否在仇恨列表
|
|
if (user.IsStrikeBack(rp.ID))
|
|
{
|
|
// 通过PK模式判断不能攻击的话,如果没有开启自动反击,那么就直接设置为false;
|
|
result = CheckPKModel(user, rp);
|
|
if (!result && GameCenter.GameSetting.GetSetting(GameSettingKeyCode.MandateAutoStrikeBack) <= 0)
|
|
{
|
|
result = false;
|
|
}
|
|
else
|
|
{
|
|
result = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//最后检查PK模式
|
|
result = CheckPKModel(user, rp);
|
|
}
|
|
|
|
} while (false);
|
|
|
|
if (result && c is RemotePlayer)
|
|
{
|
|
var rp = c as RemotePlayer;
|
|
//检查变身状态
|
|
if (user.IsChangeModel)
|
|
{
|
|
//主角在变身状态
|
|
if (rp.IsChangeModel)
|
|
{
|
|
//其他玩家在变身状态
|
|
result = user.ChangeModelCfg.IsAttChange != 0 && rp.ChangeModelCfg.IsChangeAtt != 0;
|
|
}
|
|
else
|
|
{
|
|
//其他玩家不在变身状态
|
|
result = user.ChangeModelCfg.IsAttRole != 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//主角不在变身状态
|
|
if (rp.IsChangeModel)
|
|
{
|
|
//其他玩家在变身状态
|
|
result = rp.ChangeModelCfg.IsRoleAtt != 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
//检测阻挡,只有攻击其他玩家会检测阻挡,防止怪物穿墙打不到
|
|
if (checkBlock && result && c is RemotePlayer)
|
|
{
|
|
//判断攻击路径上是否有阻挡
|
|
var start = user.Position2d;
|
|
var end = c.Position2d;
|
|
|
|
var dis = Vector2.Distance(end, start);
|
|
var whileCount = (int)(dis / user.Scene.navigator.CellSize + 1);
|
|
|
|
var tmpPos = Vector2.zero;
|
|
var lerpValue = 0f;
|
|
for (int i = 0; i <= whileCount; ++i)
|
|
{
|
|
lerpValue = i / (float)whileCount;
|
|
tmpPos = Vector2.Lerp(start, end, lerpValue);
|
|
if (user.Scene.navigator.IsBlocked(tmpPos))
|
|
{
|
|
result = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
//通过PK模式来判断是否攻击
|
|
public static bool CheckPKModel(LocalPlayer user, RemotePlayer rp)
|
|
{
|
|
bool result = false;
|
|
//判断PK模式
|
|
switch (user.PropMoudle.PkModel)
|
|
{
|
|
//和平攻击模式,不能攻击
|
|
case PKMode.PeaceMode:
|
|
result = false;
|
|
break;
|
|
//全体攻击模式,可以攻击队友以外的 , 这里没有判断是否是队友,是因为如果是队友肯定不能被攻击,这个在攻击判断的最前面已经做了判断.IsTeamMember()
|
|
case PKMode.AllMode:
|
|
result = true;
|
|
break;
|
|
//本服模式
|
|
case PKMode.SelfServer:
|
|
result = user.PropMoudle.ServerID != rp.PropMoudle.ServerID;
|
|
break;
|
|
//场景阵营模式,可以攻击对立场景阵营的玩家
|
|
case PKMode.SceneCampMode:
|
|
result = PlayerSceneCampIsEnemy(user.PropMoudle.SceneCampID, rp.PropMoudle.SceneCampID, user.Scene.Cfg.SceneCameMatchType);
|
|
break;
|
|
// 公会:玩家可以攻击除公会外的其他玩家
|
|
case PKMode.GuildMode:
|
|
if (user.GuildID <= 0)
|
|
{
|
|
result = true;
|
|
}
|
|
else
|
|
{
|
|
result = user.GuildID != rp.GuildID;
|
|
}
|
|
break;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
//查找技能目标,根据技能方向来决定选择哪些目标
|
|
public static List<Character> MatchSkillTarget(LocalPlayer user, Vector2 userPos, Vector2 userDir, FindTargetInfo findInfo)
|
|
{
|
|
var scene = GameCenter.GameSceneSystem.GetActivedScene();
|
|
if (scene == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
userDir = userDir.normalized;
|
|
_searchCache.Clear();
|
|
var selectTarget = user.GetCurSelectedTarget();
|
|
switch (findInfo.AreaType)
|
|
{
|
|
case SkillTargetArea.Rectangle: //矩形
|
|
{
|
|
float width = findInfo.RectWidth + 0.2f;
|
|
float height = findInfo.RectHeight + 0.2f;
|
|
|
|
List<Character> toBeSelectList = scene.FindAll<Character>();
|
|
if (toBeSelectList == null || toBeSelectList.Count <= 0)
|
|
return null;
|
|
var skillAreaShape = new Math2d.Obb(userPos, userDir, width / 2, height, 0);
|
|
|
|
for (int i = 0; i < toBeSelectList.Count; ++i)
|
|
{
|
|
var c = toBeSelectList[i];
|
|
var tarCircle = new Math2d.Circle(c.Position2d, c.PropMoudle.LogicBodyRadius);
|
|
if (Math2d.CollisionTest(skillAreaShape, tarCircle))
|
|
{
|
|
if (CanAttackTarget(user, c, true))
|
|
{
|
|
float disSq = (selectTarget == c) ? 0f : (userPos - c.Position2d).sqrMagnitude;
|
|
_searchCache.Add(new SearchTargetInfo(c, disSq));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case SkillTargetArea.FanShaped: //扇形
|
|
{
|
|
int angle = (int)findInfo.SectorAngle;
|
|
float radius = findInfo.SectorRadius + 0.2f;
|
|
|
|
List<Character> toBeSelectList = scene.FindAll<Character>();
|
|
if (toBeSelectList == null || toBeSelectList.Count <= 0)
|
|
return null;
|
|
|
|
var skillAreaShape = new Math2d.Sector(userPos, radius, userDir, angle * Mathf.Deg2Rad * 0.5f);
|
|
for (int i = 0; i < toBeSelectList.Count; ++i)
|
|
{
|
|
var c = toBeSelectList[i];
|
|
var tarCircle = new Math2d.Circle(c.Position2d, c.PropMoudle.LogicBodyRadius);
|
|
if (Math2d.CollisionTest(ref skillAreaShape, ref tarCircle))
|
|
{
|
|
if (CanAttackTarget(user, c, true))
|
|
{
|
|
float disSq = (selectTarget == c) ? 0f : (userPos - c.Position2d).sqrMagnitude;
|
|
_searchCache.Add(new SearchTargetInfo(c, disSq));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case SkillTargetArea.Round: //圆形
|
|
{
|
|
float radius = findInfo.RoundRadius + 0.2f;
|
|
|
|
List<Character> toBeSelectList = scene.FindAll<Character>();
|
|
if (toBeSelectList == null || toBeSelectList.Count <= 0)
|
|
return null;
|
|
|
|
var skillCircle = new Math2d.Circle(userPos, radius + user.PropMoudle.LogicBodyRadius);
|
|
for (int i = 0; i < toBeSelectList.Count; ++i)
|
|
{
|
|
var c = toBeSelectList[i];
|
|
var tarCircle = new Math2d.Circle(c.Position2d, c.PropMoudle.LogicBodyRadius);
|
|
if (Math2d.CollisionTest(ref skillCircle, ref tarCircle))
|
|
{
|
|
if (CanAttackTarget(user, c, true))
|
|
{
|
|
float disSq = (selectTarget == c) ? 0f : (userPos - c.Position2d).sqrMagnitude;
|
|
_searchCache.Add(new SearchTargetInfo(c, disSq));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (_searchCache.Count > 0)
|
|
{
|
|
_searchCache.Sort(compareFunc);
|
|
|
|
|
|
List<Character> result = new List<Character>();
|
|
for (int i = 0; result.Count < findInfo.MaxTargetCount && i < _searchCache.Count; ++i)
|
|
{
|
|
if (!result.Contains(_searchCache[i].target))
|
|
{
|
|
result.Add(_searchCache[i].target);
|
|
}
|
|
}
|
|
_searchCache.Clear();
|
|
return result;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public static Character FindSkillMainTarget(LocalPlayer user, Vector2 findDir, float dis)
|
|
{
|
|
List<Character> toBeSelectList = GameCenter.GameSceneSystem.ActivedScene.FindAll<Character>();
|
|
_searchCache.Clear();
|
|
List<SearchTargetInfo> playerCache = new List<SearchTargetInfo>(32);
|
|
for (int i = 0; i < toBeSelectList.Count && _searchCache.Count < 32; ++i)
|
|
{
|
|
Character c = toBeSelectList[i];
|
|
if (CanAttackTarget(user, c, false) && c.CanBeSelect && CheckDistanceValid(user, c, dis))
|
|
{
|
|
var serachInfo = new SearchTargetInfo(c, user.GetSqrDistance2d(c.Position2d), (int)Vector2.Angle(findDir.normalized, (c.Position2d - user.Position2d).normalized));
|
|
_searchCache.Add(serachInfo);
|
|
if (c is RemotePlayer)
|
|
{
|
|
playerCache.Add(serachInfo);
|
|
}
|
|
}
|
|
}
|
|
if (playerCache.Count > 0)
|
|
{
|
|
playerCache.Sort(compareAngleFunc);
|
|
|
|
return playerCache[0].target;
|
|
}
|
|
if (_searchCache.Count > 0)
|
|
{
|
|
_searchCache.Sort(compareAngleFunc);
|
|
return _searchCache[0].target;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public static Character FindCanAtkRecentlyTarget(LocalPlayer user)
|
|
{
|
|
List<Character> toBeSelectList = GameCenter.GameSceneSystem.ActivedScene.FindAll<Character>();
|
|
_searchCache.Clear();
|
|
for (int i = 0; i < toBeSelectList.Count && _searchCache.Count < 32; ++i)
|
|
{
|
|
Character c = toBeSelectList[i];
|
|
if (CanAttackTarget(user, c, false) && c.CanBeSelect)
|
|
{
|
|
float disSq = user.GetSqrDistance2d(c.Position2d);
|
|
_searchCache.Add(new SearchTargetInfo(c, disSq));
|
|
}
|
|
}
|
|
|
|
if (_searchCache.Count > 0)
|
|
{
|
|
_searchCache.Sort(compareFunc);
|
|
return _searchCache[0].target;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
|
|
//查找挂机攻击目标
|
|
public static Character FindMandateTarget(LocalPlayer user, int targetID)
|
|
{
|
|
if (GameCenter.GameSceneSystem.ActivedScene == null)
|
|
{
|
|
return null;
|
|
}
|
|
if (targetID != 0)
|
|
{
|
|
|
|
List<Monster> toBeSelectList = GameCenter.GameSceneSystem.ActivedScene.FindAll<Monster>();
|
|
_searchCache.Clear();
|
|
for (int i = 0; i < toBeSelectList.Count && _searchCache.Count < 64; ++i)
|
|
{
|
|
Monster c = toBeSelectList[i];
|
|
if (c.PropMoudle.CfgID == targetID && CanAttackTarget(user, c, false) && c.CanBeSelect)
|
|
{
|
|
float disSq = user.GetSqrDistance2d(c.Position2d);
|
|
_searchCache.Add(new SearchTargetInfo(c, disSq));
|
|
}
|
|
}
|
|
|
|
if (_searchCache.Count > 0)
|
|
{
|
|
_searchCache.Sort(compareFunc);
|
|
return _searchCache[0].target;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
List<Character> toBeSelectList = GameCenter.GameSceneSystem.ActivedScene.FindAll<Character>();
|
|
_searchCache.Clear();
|
|
for (int i = 0; i < toBeSelectList.Count && _searchCache.Count < 64; ++i)
|
|
{
|
|
Character c = toBeSelectList[i];
|
|
if (CanAttackTarget(user, c, false) && c.CanBeSelect)
|
|
{
|
|
float disSq = user.GetSqrDistance2d(c.Position2d);
|
|
var serchInfo = new SearchTargetInfo(c, disSq);
|
|
_searchCache.Add(serchInfo);
|
|
}
|
|
}
|
|
|
|
if (_searchCache.Count > 0)
|
|
{
|
|
_searchCache.Sort(compareFunc);
|
|
return _searchCache[0].target;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public static Collection FindCollectTarget(LocalPlayer user, int collectID)
|
|
{
|
|
List<Collection> toBeSelectList = GameCenter.GameSceneSystem.ActivedScene.FindAll<Collection>();
|
|
_searchCollectCache.Clear();
|
|
for (int i = 0; i < toBeSelectList.Count; ++i)
|
|
{
|
|
Collection c = toBeSelectList[i];
|
|
if (c.PropMoudle.CfgID == collectID)
|
|
{
|
|
float disSq = user.GetSqrDistance2d(c.Position2d);
|
|
_searchCollectCache.Add(new SearchCollectionInfo(c, disSq));
|
|
}
|
|
}
|
|
|
|
if (_searchCollectCache.Count > 0)
|
|
{
|
|
_searchCollectCache.Sort(compareCollectFunc);
|
|
}
|
|
return _searchCollectCache.Count > 0 ? _searchCollectCache[0].target : null;
|
|
}
|
|
|
|
public static bool CheckDistanceValid(Character user, Character target, float length)
|
|
{
|
|
bool result = false;
|
|
if (user != null && target != null && user.ModelTransform != null && target.ModelTransform != null)
|
|
{
|
|
var distance = (user.GetDistance2d(target.Position2d)) - target.PropMoudle.LogicBodyRadius / 2f;
|
|
if (distance <= 0f)
|
|
return true;
|
|
Vector2 hitPos;
|
|
if (distance <= length)
|
|
{
|
|
result = true;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public static bool CheckMandeteDistanceValid(Character user, Character target, float length)
|
|
{
|
|
if (length > 6)
|
|
{
|
|
length = 6;
|
|
}
|
|
bool result = false;
|
|
if (user != null && target != null && user.ModelTransform != null && target.ModelTransform != null)
|
|
{
|
|
var distance = (user.GetDistance2d(target.Position2d));// - target.PropMoudle.LogicBodyRadius / 2f;
|
|
if (distance <= 0f)
|
|
return true;
|
|
Vector2 hitPos;
|
|
if (distance < length)
|
|
{
|
|
result = true;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
//是否是技能的目标
|
|
public static bool CanShowWarningFiled(LocalPlayer user, Character target)
|
|
{
|
|
if (user == null)
|
|
return false;
|
|
if (target == null || target.IsDead())
|
|
{
|
|
return false;
|
|
}
|
|
if (target is Monster)
|
|
{
|
|
//判断怪物阵营
|
|
return MonsterSceneCampIsEnemy(user.PropMoudle.SceneCampID, target.PropMoudle.SceneCampID, user.Scene.Cfg.SceneCameMatchType);
|
|
}
|
|
|
|
//宠物
|
|
RemotePlayer rp = null;
|
|
if (target is Pet)
|
|
{
|
|
var pet = target as Pet;
|
|
rp = GameCenter.GameSceneSystem.FindEntity<RemotePlayer>(pet.PropMoudle.MasterID);
|
|
}
|
|
|
|
if (target is RemotePlayer)
|
|
{
|
|
rp = target as RemotePlayer;
|
|
}
|
|
|
|
if (rp != null)
|
|
{
|
|
if (GameCenter.LuaSystem.Adaptor.IsTeamMember(rp.ID))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
//判断地图是否能够PK
|
|
if (user.Scene.Cfg != null && user.Scene.Cfg.PkState == 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
//判断是否在仇恨列表
|
|
if (user.IsStrikeBack(rp.ID))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
//最后判断PK模式
|
|
return CheckPKModel(user, rp);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//展示警示圈
|
|
public static void ShowWarningFiled(SkillVisualInfo cfg, Entity owner)
|
|
{
|
|
if (owner is Character && !CanShowWarningFiled(GameCenter.GameSceneSystem.GetLocalPlayer(), owner as Character))
|
|
{
|
|
//只有敌对角色才会展示警示圈
|
|
return;
|
|
}
|
|
//展示警示圈
|
|
var findEvents = cfg.FindEvent(SkillEventDefine.PlayHit);
|
|
if (findEvents.Count > 0)
|
|
{
|
|
var findEvent = findEvents[0] as PlayHitEventInfo;
|
|
if (findEvent.FindInfo.ShowWarningField)
|
|
{
|
|
var hitTime = findEvent.EventFrame * Skill.OneFrameTime;
|
|
switch (findEvent.FindInfo.AreaType)
|
|
{
|
|
case SkillTargetArea.Rectangle:
|
|
GameCenter.WarningFiledManager.AddFiled(owner, false, false, findEvent.FindInfo.AreaType, findEvent.FindInfo.RectWidth, findEvent.FindInfo.RectHeight, findEvent.FindInfo.StartDis, hitTime);
|
|
break;
|
|
case SkillTargetArea.FanShaped:
|
|
GameCenter.WarningFiledManager.AddFiled(owner, false, false, findEvent.FindInfo.AreaType, findEvent.FindInfo.SectorAngle, findEvent.FindInfo.SectorRadius, findEvent.FindInfo.StartDis, hitTime);
|
|
break;
|
|
case SkillTargetArea.Round:
|
|
GameCenter.WarningFiledManager.AddFiled(owner, false, false, findEvent.FindInfo.AreaType, findEvent.FindInfo.RoundRadius, 0f, findEvent.FindInfo.StartDis, hitTime);
|
|
break;
|
|
}
|
|
GameCenter.PushFixEvent(LogicEventDefine.EID_EVENT_SHOWBOSS_WARNINGFILED, new object[] { owner.Position2d, owner.GetFacingDirection2d(), hitTime, findEvent });
|
|
}
|
|
}
|
|
}
|
|
|
|
//展示boss技能提示
|
|
public static void ShowBossSkillWarning(DeclareSkill cfg, Entity owner)
|
|
{
|
|
var monster = owner as Monster;
|
|
if (monster == null)
|
|
return;
|
|
if (string.IsNullOrEmpty(cfg.PromptText) || cfg.PromptLifeTime <= 0)
|
|
return;
|
|
|
|
GameCenter.PushFixEvent(LogicEventDefine.EID_EVENT_SHOWSKILLWARNING_EFFECT, new object[] { cfg.PromptText, cfg.PromptDelay / 1000f, cfg.PromptLifeTime / 1000f });
|
|
|
|
}
|
|
|
|
#region //私有类以及结构
|
|
struct SearchTargetInfo
|
|
{
|
|
public Character target;
|
|
public float distanceSq;
|
|
public int angle;
|
|
public SearchTargetInfo(Character target, float distanceSq, int angle = 0)
|
|
{
|
|
this.target = target;
|
|
this.distanceSq = distanceSq;
|
|
this.angle = angle;
|
|
}
|
|
}
|
|
|
|
//查询的采集物信息
|
|
private struct SearchCollectionInfo
|
|
{
|
|
public Collection target;
|
|
public float distanceSq;
|
|
public SearchCollectionInfo(Collection target, float distanceSq)
|
|
{
|
|
this.target = target;
|
|
this.distanceSq = distanceSq;
|
|
}
|
|
}
|
|
#endregion
|
|
}
|
|
}
|