123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291 |
- using CommonAI.RTS; using CommonLang.Vector;
- using CommonAI.Zone.Instance;
- using CommonLang;
- using CommonLang.Property;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- namespace CommonAI.Zone.Helper
- {
- public enum AttackShape : byte
- {
- [DescAttribute("单体")]
- Single = 255,
- [DescAttribute("圆形")]
- Round = 0,
- [DescAttribute("扇形")]
- Fan = 1,
- [DescAttribute("胶囊条状")]
- Strip = 2,
- [DescAttribute("胶囊射线(以原点出去)")]
- StripRay = 3,
- [DescAttribute("胶囊射线,接触到最近")]
- StripRayTouchEnd = 4,
- [DescAttribute("方形条状")]
- RectStrip = 12,
- [DescAttribute("方形射线(以原点出去)")]
- RectStripRay = 13,
- [DescAttribute("横向胶囊条状")]
- WideStrip = 14,
- [DescAttribute("连线类型,比如激光塔持续造成伤害")]
- LineToTarget = 5,
- [DescAttribute("连线类型,比如伸出去的钩子")]
- LineToStart = 7,
- [DescAttribute("圆环,中间是空的")]
- Circle = 6,
- }
- public enum AttackReason : byte
- {
- [Desc("范围攻击或者技能攻击")]
- Attack = 0,
- [Desc("搜索范围内可攻击目标")]
- Look = 1,
- [Desc("被攻击后反击")]
- Damaged = 2,
- [Desc("移动被阻挡后攻击")]
- MoveBlocked = 3,
- [Desc("检测仇恨目标")]
- Tracing = 4,
- }
- public class AttackRangeHelper
- {
- private readonly InstanceUnit mLauncherUnit;
- private readonly InstanceZone mParent;
- private float mCircleInR;
- private AttackReason mAttackReason = AttackReason.Attack;
- private ITemplateData mWeapon;
- public AttackRangeHelper(InstanceUnit launcher)
- {
- this.mLauncherUnit = launcher;
- this.mParent = launcher.Parent;
- }
- public AttackShape Shape { get; set; }
- public SkillTemplate.CastTarget ExpectTarget { get; set; }
- public float BodySize { get; set; }
- public float FanAngle { get; set; }
- public float Direction { get; set; }
- public float Distance { get; set; }
- public float StripWide { get; set; }
- public bool IsHadAttackable(float X, float Y, float r, SpellTemplate spell)
- {
- var b = mParent.ForEachNearObjects<InstanceUnit>(X, Y, r, (InstanceUnit o, ref bool cancel) =>
- {
- if (mLauncherUnit.AoiStatus == o.AoiStatus)
- {
- if (mParent.IsAttackable(mLauncherUnit, o, spell.ExpectTarget, AttackReason.Attack, spell))
- {
- cancel = true;
- }
- }
- });
- return b;
- }
- /// <summary>
- /// 范围伤害,碰撞检测
- /// </summary>
- /// <param name="list"></param>
- /// <param name="reason"></param>
- /// <param name="weapon"></param>
- /// <param name="X"></param>
- /// <param name="Y"></param>
- /// <param name="PrevX"></param>
- /// <param name="PrevY"></param>
- /// <param name="max_affect"></param>
- /// <param name="aoi"></param>
- /// <returns></returns>
- ///
- public void GetShapeAttackable(
- List<InstanceUnit> list,
- AttackReason reason,
- ITemplateData weapon,
- float X,
- float Y,
- float PrevX,
- float PrevY,
- int max_affect,
- ObjectAoiStatus aoi)
- {
- mAttackReason = reason;
- mWeapon = weapon;
- switch (Shape)
- {
- case AttackShape.Round:
- if (PrevX != X || PrevY != Y)
- {
- mParent.getObjectsRoundLineRange<InstanceUnit>(touch_RoundLine, PrevX, PrevY, X, Y, BodySize, list, aoi);
- }
- else
- {
- mParent.getObjectsRoundRange<InstanceUnit>(touch_Round, X, Y, BodySize, list, aoi);
- }
- break;
- case AttackShape.Circle:
- if (BodySize > StripWide)
- {
- mCircleInR = BodySize - StripWide;
- mParent.getObjectsRoundRange<InstanceUnit>(touch_Circle, X, Y, BodySize, list, aoi);
- }
- else
- {
- mParent.getObjectsRoundRange<InstanceUnit>(touch_Round, X, Y, BodySize, list, aoi);
- }
- break;
- case AttackShape.Fan:
- {
- float dfan = FanAngle / 2f;
- mParent.getObjectsFanRange<InstanceUnit>(touch_Fan, X, Y, BodySize, Direction - dfan, Direction + dfan, list, aoi);
- }
- break;
- case AttackShape.Strip:
- {
- //float d_angle = this.Direction + CMath.PI_DIV_2;
- float d_width = StripWide / 2f;
- float d_distance = Distance / 2f;
- Vector2 p0 = new Vector2(X, Y);
- Vector2 p1 = new Vector2(X, Y);
- MathVector.movePolar(p0, this.Direction, -d_distance);
- MathVector.movePolar(p1, this.Direction, d_distance);
- mParent.getObjectsRoundLineRange<InstanceUnit>(touch_RoundLine, p0.X, p0.Y, p1.X, p1.Y, d_width, list, aoi);
- }
- break;
- case AttackShape.StripRay:
- {
- float d_width = StripWide / 2f;
- float d_distance = Distance;
- Vector2 p1 = new Vector2(X, Y);
- MathVector.movePolar(p1, this.Direction, d_distance);
- mParent.getObjectsRoundLineRange<InstanceUnit>(touch_RoundLine, X, Y, p1.X, p1.Y, d_width, list, aoi);
- }
- break;
- case AttackShape.StripRayTouchEnd:
- {
- float d_width = StripWide / 2f;
- float d_distance = Distance;
- Vector2 p1 = new Vector2(X, Y);
- MathVector.movePolar(p1, this.Direction, d_distance);
- mParent.getObjectsRoundLineRange<InstanceUnit>(touch_RoundLine, X, Y, p1.X, p1.Y, d_width, list, aoi);
- if (list.Count > 1)
- {
- list.Sort(new ObjectBodySorterNearest<InstanceUnit>(X, Y, d_width));
- list.RemoveRange(1, list.Count - 1);
- }
- }
- break;
- case AttackShape.RectStrip:
- {
- //float d_angle = this.Direction + CMath.PI_DIV_2;
- float d_width = StripWide / 2f;
- float d_distance = Distance / 2f;
- Vector2 p0 = new Vector2(X, Y);
- Vector2 p1 = new Vector2(X, Y);
- MathVector.movePolar(p0, this.Direction, -d_distance);
- MathVector.movePolar(p1, this.Direction, d_distance);
- mParent.getObjectsRectLineRange<InstanceUnit>(touch_RectLine, p0.X, p0.Y, p1.X, p1.Y, d_width, list, aoi);
- }
- break;
- case AttackShape.RectStripRay:
- {
- float d_width = StripWide / 2f;
- float d_distance = Distance;
- Vector2 p1 = new Vector2(X, Y);
- MathVector.movePolar(p1, this.Direction, d_distance);
- mParent.getObjectsRectLineRange<InstanceUnit>(touch_RectLine, X, Y, p1.X, p1.Y, d_width, list, aoi);
- }
- break;
- case AttackShape.WideStrip:
- {
- float d_width = StripWide / 2f;
- float d_angle = Direction + CMath.PI_DIV_2;
- float d_distance = Distance / 2f;
- Vector2 p0 = new Vector2(X, Y);
- Vector2 p1 = new Vector2(X, Y);
- MathVector.movePolar(p0, d_angle, -d_width);
- MathVector.movePolar(p1, d_angle, +d_width);
- mParent.getObjectsRoundLineRange<InstanceUnit>(touch_RoundLine, p0.X, p0.Y, p1.X, p1.Y, d_distance, list, aoi);
- }
- break;
- case AttackShape.Single:
- case AttackShape.LineToTarget:
- case AttackShape.LineToStart:
- //此类型作为单独命中指定目标//
- break;
- default:
- {
- mParent.getObjectsRoundRange<InstanceUnit>(touch_Round, X, Y, BodySize, list, aoi);
- }
- break;
- }
- // 最大攻击数量 //
- if (max_affect > 0 && list.Count > max_affect)
- {
- CUtils.RandomList(mParent.RandomN, list);
- while (list.Count > max_affect)
- {
- list.RemoveAt(list.Count - 1);
- }
- }
- }
- private bool touch_Round(InstanceZoneObject o, float x, float y, float r)
- {
- if (CMath.intersectRound(x, y, r, o.X, o.Y, o.BodyHitSize))
- {
- return mParent.IsAttackable(mLauncherUnit, o as InstanceUnit, ExpectTarget, mAttackReason, mWeapon);
- }
- return false;
- }
- private bool touch_Fan(InstanceZoneObject o, float x, float y, float distance, float startAngle, float endAngle)
- {
- if (CMath.intersectFanRound(x, y, distance, o.X, o.Y, o.BodyHitSize, startAngle, endAngle))
- {
- return mParent.IsAttackable(mLauncherUnit, o as InstanceUnit, ExpectTarget, mAttackReason, mWeapon);
- }
- return false;
- }
- private bool touch_RoundLine(InstanceZoneObject o, float x1, float y1, float x2, float y2, float line_r)
- {
- if (Collider.Object_HitBody_TouchRoundLine(o, x1, y1, x2, y2, line_r))
- {
- return mParent.IsAttackable(mLauncherUnit, o as InstanceUnit, ExpectTarget, mAttackReason, mWeapon);
- }
- return false;
- }
- private bool touch_RectLine(InstanceZoneObject o, float x1, float y1, float x2, float y2, float line_r)
- {
- if (Collider.Object_HitBody_TouchRectLine(o, x1, y1, x2, y2, line_r))
- {
- return mParent.IsAttackable(mLauncherUnit, o as InstanceUnit, ExpectTarget, mAttackReason, mWeapon);
- }
- return false;
- }
- private bool touch_Circle(InstanceZoneObject o, float x, float y, float r)
- {
- if (CMath.intersectRound(x, y, r, o.X, o.Y, o.BodyHitSize))
- {
- if (mParent.IsAttackable(mLauncherUnit, o as InstanceUnit, ExpectTarget, mAttackReason, mWeapon))
- {
- if (mCircleInR < o.BodyHitSize)
- {
- return true;
- }
- return (!CMath.includeRound2(x, y, mCircleInR, o.X, o.Y, o.BodyHitSize));
- }
- }
- return false;
- }
- }
- }
|