XmdsInstancePlayer.cs 54 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086
  1. #define OPNE_JSG_AI_TOOLS
  2. using CommonAI.Zone;
  3. using CommonAI.Zone.Helper;
  4. using CommonAI.Zone.Instance;
  5. using System;
  6. using System.Collections.Generic;
  7. using System.Linq;
  8. using System.Text;
  9. using XmdsCommon.Plugin;
  10. using CommonAI.Zone.Formula;
  11. using XmdsCommon.Message;
  12. using CommonLang;
  13. using XmdsCommonServer.Message;
  14. using CommonLang.Vector;
  15. using XmdsCommon.EditorData;
  16. using CommonAI.Zone.ZoneEditor;
  17. using CommonLang.Concurrent;
  18. using static CommonAI.Zone.Instance.InstanceUnit;
  19. using XmdsCommon.ZoneClient.XmdsClientVirtual;
  20. using XmdsCommonServer.Plugin.Scene;
  21. using static CommonAI.XmdsConstConfig;
  22. using System.Collections;
  23. using CommonLang.Log;
  24. using CommonAI.Data;
  25. using static XmdsCommonServer.Plugin.Units.XmdsInstanceUnitStateMachine;
  26. using CommonAI;
  27. namespace XmdsCommonServer.Plugin.Units
  28. {
  29. public class XmdsInstancePlayer : InstancePlayer
  30. {
  31. public enum GuardMode
  32. {
  33. Mode_Point,
  34. Mode_Map,
  35. }
  36. private static HashMap<int, AtomicInteger> CreateInfoMap = new HashMap<int, AtomicInteger>();
  37. //嘲讽状态
  38. protected XmdsInstanceUnitStateMock mMockTarget;
  39. //private TimeInterval<int> mFindItemTimeInterval;
  40. private long mNextAutoFindPickItemTime;
  41. private GuardMode mCurGuardMode = GuardMode.Mode_Point;
  42. private Vector2 mGuardPos = new Vector2();
  43. private bool mDoStopSkill = false;
  44. private static int DEFAULT_CROSS_SERVER_ID = -999;
  45. private const char SPLIT = ':';
  46. private List<int> mAutoGuardTargetList = new List<int>();
  47. private int mAutoGuardTargetTimes = 0;
  48. private const int MAX_AUTO_GUARD_TARGET_TIMES = 500;
  49. private bool mIsReady = false;
  50. private XmdsInstanceUnitStateMachine.XmdsStateFollowAndAttack mXmdsFocusTarget;
  51. private bool mBotTestAutoFight = false;
  52. private int zoneID;
  53. //解决部分情况下未上发(或者上发时机不对)idle,导致别人看到自己在move,唯独自己看到自己是正常的
  54. private int mNotMoveTimes;
  55. private Vector2 mLastMovePos = new Vector2();
  56. //定点自动战斗情况下,玩家不能像怪物一样回原地,所以需要定时检测一下,重置定点的位置
  57. private long mLastAutoAttackTime = 0;
  58. //private Vector2 mLastAutoFightPos = new Vector2();
  59. //下一次通知背包已满时间
  60. //private long mNextNotifyBagFullTime = 0;
  61. public XmdsInstancePlayer(InstanceZone zone, UnitInfo info, string name, int force, int alliesForce, int level)
  62. : base(zone, info, name, force, level, alliesForce)
  63. {
  64. //mFindItemTimeInterval = new TimeInterval<int>(XmdsConfig.Instance.GUARD_FIND_ITEM_CYCLE_TIME);
  65. mCheckGuard.FirstTimeEnable = true;
  66. if (TemplateManager.IsEditor)
  67. {
  68. mIsReady = true;
  69. mBotTestAutoFight = true;
  70. }
  71. else if ((Info.Properties as XmdsUnitProperties).BotTestTemplate)
  72. {
  73. mIsReady = true;
  74. }
  75. OnPlayerCreate();
  76. this.OnHandleAction += OnActionHandle;
  77. }
  78. static void OnActionHandle(InstanceUnit unit, ObjectAction act)
  79. {
  80. if (act is PlayerDramaEndAction && unit.AoiStatus != null)
  81. {
  82. var dramaId = (act as PlayerDramaEndAction).dramaId;
  83. if (unit.AoiStatus is XmdsPlayerAOI)
  84. {
  85. if ((unit.AoiStatus as XmdsPlayerAOI).QuestId == dramaId)
  86. {
  87. unit.setAoiStatus(null);
  88. }
  89. return;
  90. }
  91. if (unit.AoiStatus is DarmaAOI)
  92. {
  93. if ((unit.AoiStatus as DarmaAOI).darmaId == dramaId)
  94. {
  95. unit.setAoiStatus(null);
  96. }
  97. return;
  98. }
  99. }
  100. }
  101. private void clearAutoGuardTargetList()
  102. {
  103. if (mAutoGuardTargetList != null)
  104. {
  105. mAutoGuardTargetList.Clear();
  106. }
  107. mAutoGuardTargetTimes = 0;
  108. }
  109. protected override void Disposing()
  110. {
  111. foreach (var item in mQuestScript)
  112. {
  113. item.Value.Dispose();
  114. }
  115. clearAutoGuardTargetList();
  116. mXmdsFocusTarget = null;
  117. lastAttackUnit = null;
  118. base.Disposing();
  119. }
  120. private System.Action readyAction;
  121. public void PlayerReady()
  122. {
  123. mIsReady = true;
  124. if (readyAction != null)
  125. {
  126. readyAction.Invoke();
  127. }
  128. }
  129. public bool IsPlayerReady()
  130. {
  131. return mIsReady;
  132. }
  133. //--------------------------------------------------------------------------------------
  134. public override bool IsVisible
  135. {
  136. get { return base.IsVisible && mIsReady; }
  137. }
  138. public override bool IsInvincible
  139. {
  140. get { return (!mIsReady || base.IsInvincible); }
  141. }
  142. public XmdsVirtual_Player VirtualPlayer
  143. {
  144. get { return base.Virtual as XmdsVirtual_Player; }
  145. }
  146. public bool CanPickDropableItem
  147. {
  148. get { return VirtualPlayer.VirtualInventorySize >= 1; }
  149. }
  150. /// <summary>
  151. /// 是否是机器人
  152. /// </summary>
  153. //public bool IsBotTest { get; private set; }
  154. //--------------------------------------------------------------------------------------
  155. #region 任务相关
  156. private HashMap<string, Quest.QuestScript> mQuestScript = new HashMap<string, Quest.QuestScript>();
  157. public Quest.QuestScript GetQuestScript(string quest_id)
  158. {
  159. return mQuestScript.Get(quest_id);
  160. }
  161. public IList<Quest.QuestScript> GetAllQuestScript()
  162. {
  163. return new List<Quest.QuestScript>(mQuestScript.Values);
  164. }
  165. public void SetQuestScript(string quest_id, int questType, Quest.QuestScript script)
  166. {
  167. if (mQuestScript.ContainsKey(quest_id))
  168. {
  169. XmdsVirtual.FormatLog(CommonLang.Log.LoggerLevel.ERROR, "SetQuestScript Error : ContainsKey" + quest_id);
  170. RemoveQuestScript(quest_id);
  171. }
  172. mQuestScript.Add(quest_id, script);
  173. script.Init(quest_id, questType, this);
  174. script.Start();
  175. }
  176. public void RemoveQuestScript(string quest_id)
  177. {
  178. Quest.QuestScript qs = mQuestScript.Get(quest_id);
  179. if (qs != null)
  180. {
  181. qs.Dispose();
  182. mQuestScript.Remove(quest_id);
  183. }
  184. }
  185. public List<CommonAI.Zone.Helper.QuestData> GetQuests()
  186. {
  187. return new List<CommonAI.Zone.Helper.QuestData>(mQuests.Values);
  188. }
  189. #endregion
  190. //--------------------------------------------------------------------------------------
  191. #region 作弊惩罚
  192. private TimeExpire<int> mLockTime;
  193. public bool IsLock { get { return mLockTime != null; } }
  194. //索敌范围.
  195. private int mGuardSearchRange = XmdsConfig.Instance.NORMALSCENE_AUTO_GUARD_RANGE;
  196. private int mGuardSearchRangeExt = XmdsConfig.Instance.NORMALSCENE_AUTO_GUARD_RANGE * XmdsConfig.Instance.NORMALSCENE_AUTO_GUARD_RANGE;
  197. /// <summary>
  198. /// 设置自动战斗索敌范围.
  199. /// </summary>
  200. /// <param name="v"></param>
  201. public void SetGuardSearchRange(int v)
  202. {
  203. mGuardSearchRange = v;
  204. mGuardSearchRangeExt = mGuardSearchRange * mGuardSearchRange;
  205. }
  206. /// <summary>
  207. /// 检测到作弊,禁止一切操作一段时间
  208. /// </summary>
  209. /// <param name="timeMS"></param>
  210. public void Lock(int timeMS)
  211. {
  212. this.startIdle();
  213. if (mLockTime != null && mLockTime.ExpireTimeMS >= timeMS)
  214. {
  215. return;
  216. }
  217. else
  218. {
  219. mLockTime = new TimeExpire<int>(timeMS);
  220. }
  221. }
  222. private void upateLock()
  223. {
  224. if (mLockTime != null && mLockTime.Update(Parent.UpdateIntervalMS))
  225. {
  226. mLockTime = null;
  227. }
  228. }
  229. #endregion
  230. //--------------------------------------------------------------------------------------
  231. #region BUFF特殊状态锁定移动.
  232. private TimeExpire<int> mBuffLockMoveTime;
  233. public bool IsBuffLockMove { get { return mBuffLockMoveTime != null; } }
  234. public void BuffMoveLock(int timeMS)
  235. {
  236. this.startIdle();
  237. if (mBuffLockMoveTime != null && mBuffLockMoveTime.ExpireTimeMS >= timeMS)
  238. {
  239. return;
  240. }
  241. else
  242. {
  243. mBuffLockMoveTime = new TimeExpire<int>(timeMS);
  244. }
  245. }
  246. private void UpdateBuffMoveLock()
  247. {
  248. if (mBuffLockMoveTime != null && mBuffLockMoveTime.Update(Parent.UpdateIntervalMS))
  249. {
  250. mBuffLockMoveTime = null;
  251. }
  252. }
  253. #endregion
  254. //--------------------------------------------------------------------------------------
  255. protected override void onUpdate(bool slowRefresh)
  256. {
  257. base.onUpdate(slowRefresh);
  258. this.upateLock();
  259. this.UpdateBuffMoveLock();
  260. this.UpdateDoStopSkill();
  261. this.updateFollowTeam();
  262. this.UpdateAndModifyErrorData();
  263. }
  264. //--------------------------------------------------------------------------------------
  265. protected override void onAction(ObjectAction act)
  266. {
  267. if (IsLock) return;
  268. if (act is UnitAxisAction || act is UnitMoveAction)
  269. {
  270. //BUFF锁定客户端移动.
  271. if (IsBuffLockMove == true)
  272. {
  273. return;
  274. }
  275. }
  276. base.onAction(act);
  277. if (this.IsDead() == true)
  278. {
  279. //单位遗言更改.
  280. if (act is PlayerTestamentChangeEventAction)
  281. {
  282. PlayerTestamentChangeEventAction evt = act as PlayerTestamentChangeEventAction;
  283. ChangeTestament(evt.TestamentID);
  284. }
  285. }
  286. //自动战斗状态变更通知.
  287. if (act is PlayerAutoGuardEventC2B)
  288. {
  289. var evt = act as PlayerAutoGuardEventC2B;
  290. if (evt.Flag == false)
  291. {
  292. if (this.CurrentState is StateSkill)
  293. {
  294. mDoStopSkill = true;
  295. }
  296. }
  297. return;
  298. }
  299. else if (act is PlayerEnterCrossServerRequestC2B)
  300. {
  301. //战斗服判断单位是否在PVPV状态,如果不是发送切换场景请求.
  302. if ((this.Virtual as XmdsVirtual).CombatState != BattleStatus.PVP)
  303. {
  304. //发送协议.
  305. TransUnitEventB2R evt = new TransUnitEventB2R();
  306. //约定跨服场景ID.
  307. evt.SceneID = DEFAULT_CROSS_SERVER_ID;
  308. evt.playerId = this.PlayerUUID;
  309. evt.TargetX = 0;
  310. evt.TargetY = 0;
  311. this.queueEvent(evt);
  312. }
  313. else
  314. {
  315. (this.Virtual as XmdsVirtual).SendMsgToClient(CommonAI.XmdsConstConfig.TIPS_CAN_NOT_ENTER_SCENE);
  316. }
  317. }
  318. else if (act is GetMonsterSufferDamageInfoC2B)
  319. {
  320. var ret = act as GetMonsterSufferDamageInfoC2B;
  321. OnReceiveGetMonsterSufferDamageInfoC2B(ret);
  322. }
  323. foreach (var q in mQuestScript)
  324. {
  325. if (q.Value.TryDoAction(act))
  326. {
  327. break;
  328. }
  329. }
  330. }
  331. protected override bool doLaunchSkill(UnitLaunchSkillAction sk)
  332. {
  333. //Console.WriteLine(" ------------------------------doLaunchSkill - " + sk.SkillID + ", " + this.ID + ", targetID: " +
  334. // sk.TargetObjID + ", XY:" + this.X + ", " + this.Y + ", direction : " + this.Direction + ", " + this.Parent.UUID);
  335. //if(sk.SkillID == 110160)
  336. // sk.SkillID = 110360;
  337. //如果在采集中,不让放技能,并通知客户端.
  338. if (CurrentActionStatus == UnitActionStatus.Pick)
  339. {
  340. this.VirtualPlayer.SendMsgToClient(CommonAI.XmdsConstConfig.TIPS_BE_BUSY);
  341. return false;
  342. }
  343. var skill = this.getSkillState(sk.SkillID);
  344. if (skill == null)
  345. {
  346. return false;
  347. }
  348. return base.doLaunchSkill(sk);
  349. }
  350. public bool PlayerChangeSkill(int oldSkillID, int newSkillID, SkillLevelData levelData)
  351. {
  352. return this.Virtual.ChangeSkill(oldSkillID, newSkillID, levelData);
  353. }
  354. // 获取队伍的天命属性加成
  355. public override int GetTeamFateValue(UnitFateType fateType)
  356. {
  357. if(this.TeamVirtual == null)
  358. {
  359. return this.Virtual.GetPetTalentAddition(fateType);
  360. }
  361. return this.TeamVirtual.GetTeamFateValue(fateType);
  362. }
  363. //查找自动拾取的物品
  364. public override InstanceItem findGuardPickItem()
  365. {
  366. if (CanPickDropableItem)
  367. {
  368. return base.findGuardPickItem();
  369. }
  370. return null;
  371. }
  372. //查找自动战斗等一切情况下的物品拾取
  373. public InstanceItem findAutoGuardPickItem()
  374. {
  375. if (CanPickDropableItem)
  376. {
  377. InstanceItem min = null;
  378. //float min_len = float.MaxValue;
  379. Parent.ForEachNearObjects(this.X, this.Y, this.mAutoPickRange, (InstanceItem u, ref bool cancel) =>
  380. {
  381. if (!u.Info.Pickable && u.IsPickable(this))
  382. {
  383. //float len = MathVector.getDistanceSquare(u.X, u.Y, this.X, this.Y);
  384. //if (min_len > len && len <= searchValue)
  385. //{
  386. // min_len = len;
  387. // min = u;
  388. //}
  389. min = u;
  390. cancel = true;
  391. }
  392. });
  393. return min;
  394. }
  395. return null;
  396. }
  397. protected override void doPickObject(UnitPickObjectAction pick)
  398. {
  399. InstanceZoneObject obj = Parent.getObject<InstanceZoneObject>(pick.PickableObjectID);
  400. if (obj is InstanceItem)
  401. {
  402. InstanceItem item = obj as InstanceItem;
  403. var zip = (item.Info.Properties as XmdsItemProperties);
  404. switch (zip.ItemType)
  405. {
  406. case XmdsItemProperties.XmdsItemType.Equip:
  407. //if (CanPickDropableItem) XmdsDropableInstanceItem.IsPickable已经检查
  408. {
  409. item.DirectPickItem(this, () =>
  410. {
  411. RemoveDropItemB2C rd = new RemoveDropItemB2C(item.ID, this.ID);
  412. this.queueEvent(rd);
  413. });
  414. }
  415. break;
  416. default:
  417. {
  418. if (item.PickItem(this) && item.mFrom == 1)
  419. {
  420. RemoveDropItemB2C rd = new RemoveDropItemB2C(item.ID, this.ID);
  421. this.queueEvent(rd);
  422. }
  423. }
  424. break;
  425. }
  426. }
  427. else if (obj is InstanceUnit)
  428. {
  429. InstanceUnit unit = obj as InstanceUnit;
  430. this.PickUnit(unit);
  431. }
  432. }
  433. protected void TryDirectPickNearItems()
  434. {
  435. int size = this.VirtualPlayer.VirtualInventorySize;
  436. if (size == 0) { return; }
  437. Parent.ForEachNearObjects(this.X, this.Y, this.mAutoPickRange, (InstanceItem u, ref bool cancel) =>
  438. {
  439. if (size > 0)
  440. {
  441. var itemProp = u.Info.Properties as XmdsItemProperties;
  442. if (itemProp.AllowAutoGuardPick == true && u.PassTimeMS > 1000)
  443. {
  444. //自己可以捡的装备再扣除背包数量.
  445. if (u.DirectPickItem(this, () =>
  446. {
  447. RemoveDropItemB2C rd = new RemoveDropItemB2C(u.ID, this.ID);
  448. this.queueEvent(rd);
  449. }))
  450. {
  451. size--;
  452. }
  453. }
  454. }
  455. else
  456. {
  457. cancel = true;
  458. }
  459. });
  460. //this.VirtualPlayer.VirtualInventorySize = size;
  461. }
  462. public void setMocking(InstanceUnit unit)
  463. {
  464. if(unit == null)
  465. {
  466. if(mMockTarget != null)
  467. {
  468. mMockTarget.mMarkRemove = true;
  469. }
  470. mMockTarget = null;
  471. }
  472. else
  473. {
  474. mMockTarget = new XmdsInstanceUnitStateMock(this, unit);
  475. DoMockingAttack();
  476. }
  477. }
  478. protected override void updateGuard()
  479. {
  480. if (mMockTarget != null)
  481. {
  482. DoMockingAttack();
  483. }
  484. else if(this.mFocusPickItem != null && this.mFocusPickItem.IsActive)
  485. {
  486. if (this.mFocusPickItem.IsBlock())
  487. {
  488. this.mFocusPickItem = null;
  489. }
  490. else
  491. {
  492. return;
  493. }
  494. }
  495. else if (IsGuard == true && (mXmdsFocusTarget == null || (mXmdsFocusTarget != null && !mXmdsFocusTarget.IsActive)))
  496. {
  497. mXmdsFocusTarget = null;
  498. InstanceUnit enemy = null;
  499. if (lastAttackUnit != null && lastAttackUnit.IsActive == true)//上一次攻击的单位如果没死且能攻击,继续攻击他.
  500. {
  501. //上次攻击的单位如果超过了一屏范围,取消攻击.
  502. //if (CMath.getDistance(this.X, this.Y, lastAttackUnit.X, lastAttackUnit.Y) > this.mGuardSearchRange)
  503. //{
  504. // lastAttackUnit = null;
  505. //}
  506. //else
  507. {
  508. enemy = lastAttackUnit;
  509. }
  510. }
  511. else
  512. {
  513. lastAttackUnit = null;
  514. }
  515. if (enemy == null)//如果无效再找一次.
  516. {
  517. enemy = findGuardTarget(SkillTemplate.CastTarget.Enemy, AttackReason.Look);
  518. }
  519. if (enemy != null)
  520. {
  521. doXmdsFocusAttack(enemy, SkillTemplate.CastTarget.Enemy);
  522. return;
  523. }
  524. //UpdateXmdsGuard();
  525. }
  526. //自动拾取检测
  527. if(this.DoAutoPick())
  528. {
  529. return;
  530. }
  531. if (mFocusPickItem != null && !mFocusPickItem.IsActive)
  532. {
  533. mFocusPickItem = null;
  534. }
  535. //if (mFindItemTimeInterval.Update(Parent.UpdateIntervalMS))
  536. // {
  537. // TryDirectPickNearItems();
  538. //}
  539. if (IsGuard)
  540. {
  541. // 旋风斩贴近目标 //
  542. var state = CurrentState as StateSkill;
  543. if (state != null)
  544. {
  545. Vector2 movePos = (mXmdsFocusTarget == null) ? state.GetMoveToPos() : new Vector2(mXmdsFocusTarget.Target.X, mXmdsFocusTarget.Target.Y);
  546. if (movePos != null && state.IsControlMoveable && !state.unit.IsCannotMove && state.SkillData.AutoFightFollower)
  547. {
  548. if(state.setMoveTo(movePos.X, movePos.Y))
  549. {
  550. // 移动结束
  551. if((this.CurrentActionSubstate & (byte)UnitActionSubStatus.ChargeAtkMove) > 0)
  552. {
  553. this.RemoveActionSubState(UnitActionSubStatus.ChargeAtkMove);
  554. this.AddActionSubState(UnitActionSubStatus.ChargeAtkIdle);
  555. }
  556. }
  557. else
  558. {
  559. // 移动
  560. if ((this.CurrentActionSubstate & (byte)UnitActionSubStatus.ChargeAtkIdle) > 0)
  561. {
  562. this.RemoveActionSubState(UnitActionSubStatus.ChargeAtkIdle);
  563. this.AddActionSubState(UnitActionSubStatus.ChargeAtkMove);
  564. }
  565. }
  566. return;
  567. }
  568. }
  569. // 没目标定期检测目标 //
  570. if ((mXmdsFocusTarget == null) && (mFocusPickItem == null))
  571. {
  572. if (mCheckGuard.Update(Parent.UpdateIntervalMS))
  573. {
  574. var enemy = findGuardTarget(SkillTemplate.CastTarget.Enemy, AttackReason.Look);
  575. if (enemy != null)
  576. {
  577. doXmdsFocusAttack(enemy, SkillTemplate.CastTarget.Enemy);
  578. return;
  579. }
  580. var alias = findGuardTarget(SkillTemplate.CastTarget.AlliesIncludeSelf, AttackReason.Look);
  581. if (alias != null)
  582. {
  583. doXmdsFocusAttack(alias, SkillTemplate.CastTarget.AlliesIncludeSelf);
  584. return;
  585. }
  586. //if (CommonLang.CUtils.localTimeMS - this.mLastAutoAttackTime > 3000/* && this.X == this.mLastAutoFightPos.X && this.Y == this.mLastAutoFightPos.Y*/)
  587. //{
  588. // this.mLastAutoAttackTime = CommonLang.CUtils.localTimeMS;
  589. // this.mGuardPos.SetX(this.X);
  590. // this.mGuardPos.SetY(this.Y);
  591. //}
  592. }
  593. }
  594. }
  595. }
  596. //是否可以自动拾取
  597. public override bool DoAutoPick(bool ignoreInterval = false)
  598. {
  599. //非自动战斗或者非跟随,退出
  600. if (!this.IsGuard && (this.leadingMan == null || (this.leadingMan != null && !this.canFollowTeam)))
  601. {
  602. return false;
  603. }
  604. if(this.VirtualPlayer.VirtualInventorySize <= 0)
  605. {
  606. //只要自动战斗就提示这个,不合理,客户端自己加
  607. //if(mNextNotifyBagFullTime < CommonLang.CUtils.localTimeMS)
  608. //{
  609. // mNextNotifyBagFullTime = CommonLang.CUtils.localTimeMS + 6000;
  610. // this.Virtual.SendMsgToClient(CommonAI.XmdsConstConfig.TIPS_BAG_FULL);
  611. //}
  612. return false;
  613. }
  614. if (!this.Parent.CheckAutoDropItem() || !IsBattleCanPick())
  615. {
  616. return false;
  617. }
  618. if (mFocusPickItem == null || !mFocusPickItem.IsActive || mFocusPickItem.IsBlock())
  619. {
  620. bool leaderInView = false;
  621. if (this.mTeamVirtual != null && this.canFollowTeam && this.leadingMan != null && this.leadingMan.Enable)
  622. {
  623. // 如果正在跟随图中,取消拾取
  624. if(this.CurrentState is StateFollowLeader)
  625. {
  626. StateFollowLeader folloLeader = this.CurrentState as StateFollowLeader;
  627. if(folloLeader != null && folloLeader.FollowState == StateFollow.MoveState.Move)
  628. {
  629. return false;
  630. }
  631. }
  632. if (!CMath.includeRoundPoint(X, Y, this.mAutoPickRange, leadingMan.X, leadingMan.Y))
  633. {
  634. return false;
  635. }
  636. else
  637. {
  638. leaderInView = true;
  639. }
  640. }
  641. bool canAutoPick = IsGuard || this.CurrentState is StateFollowAndPickItem || leaderInView;
  642. if (canAutoPick && (ignoreInterval || mNextAutoFindPickItemTime < CommonLang.CUtils.localTimeMS))
  643. {
  644. var item = findAutoGuardPickItem();
  645. if (item != null)
  646. {
  647. mNextAutoFindPickItemTime = CommonLang.CUtils.localTimeMS + XmdsConfig.Instance.GUARD_FIND_ITEM_CYCLE_TIME;
  648. doFocusPickItem(item, false);
  649. return true;
  650. }
  651. }
  652. }
  653. else
  654. {
  655. return true;
  656. }
  657. return false;
  658. }
  659. //是否跟随队长
  660. public override bool IsFollowMaster()
  661. {
  662. if(this.leadingMan != null && this.canFollowTeam)
  663. {
  664. return true;
  665. }
  666. return false;
  667. }
  668. private bool IsBattleCanPick()
  669. {
  670. if(this.Virtual.GetBattleStatus() != BattleStatus.None)
  671. {
  672. // 不主动开战
  673. if(this.mXmdsFocusTarget != null && this.mXmdsFocusTarget.TargetUnit.IsActive && !this.mXmdsFocusTarget.TargetUnit.IsFullHP())
  674. {
  675. return false;
  676. }
  677. }
  678. return true;
  679. }
  680. //通知拾取消息
  681. public override void NotifyRemoveDropItemB2C(InstanceItem item)
  682. {
  683. RemoveDropItemB2C rd = new RemoveDropItemB2C(item.ID, this.ID);
  684. this.queueEvent(rd);
  685. }
  686. private void DoMockingAttack()
  687. {
  688. //doXmdsFocusAttack(mMockTarget.GetTargetUnit(), SkillTemplate.CastTarget.Enemy, false, this.DefaultSkillStatus());
  689. if (!(this.CurrentState is XmdsInstanceUnitStateMock) || !(this.CurrentState is StateSkill))
  690. {
  691. changeState(mMockTarget);
  692. queueEvent(new PlayerFocuseTargetEvent(this.ID, mMockTarget.GetTargetUnit().ID, SkillTemplate.CastTarget.Enemy)); ;
  693. }
  694. }
  695. public override BuffState AddBuff(BuffTemplate buff, InstanceUnit sender, int pointMaxOverLayer = 0, bool forever = false, bool bMaxOverlayer = false,
  696. int buffExt = 0, bool isControlBuf = false, bool maxReset = false, int addLayers = 0)
  697. {
  698. XmdsBuffProperties prop = buff.Properties as XmdsBuffProperties;
  699. if (prop.BuffAbilityList != null)
  700. {
  701. int count = prop.BuffAbilityList.Count;
  702. for (int i = 0; i < count; i++)
  703. {
  704. if (XmdsInstanceUtils.IsDebuff(prop.BuffAbilityList[i].ability))
  705. {
  706. isControlBuf = true;
  707. break;
  708. }
  709. }
  710. }
  711. return base.AddBuff(buff, sender, pointMaxOverLayer, forever, bMaxOverlayer, buffExt, isControlBuf, maxReset, addLayers);
  712. }
  713. protected override void doHitAttack(InstanceUnit attacker, AttackSource source)
  714. {
  715. if (this.IsDead())
  716. {
  717. //XmdsAttackProperties zap = (source.Attack.Properties as XmdsAttackProperties);
  718. if (attacker.CurrentState is StateSkill)
  719. {
  720. var skilltemplate = (attacker.CurrentState as StateSkill).SkillData;
  721. if ((skilltemplate.Properties as XmdsSkillProperties).TargetType
  722. == XmdsSkillProperties.XmdsSkillTargetType.AllianceDead)
  723. {
  724. TemplateManager.Formula.OnHit(attacker, source, this);
  725. }
  726. }
  727. }
  728. base.doHitAttack(attacker, source);
  729. }
  730. /// <summary>
  731. /// 更改遗言.
  732. /// </summary>
  733. /// <param name="testamentID"></param>
  734. private void ChangeTestament(byte testamentID)
  735. {
  736. (this.Virtual as XmdsVirtual_Player).SyncTestament(testamentID);
  737. }
  738. public override void InitSkills(LaunchSkill baseSkill, params LaunchSkill[] skills)
  739. {
  740. if (this.Virtual == null ||
  741. (this.Virtual as XmdsVirtual).IsFinishSkillInit() == false)
  742. {
  743. return;
  744. }
  745. base.InitSkills(baseSkill, skills);
  746. }
  747. public override bool tryLaunchRandomSkillAndCancelCurrentSkill(InstanceUnit target, bool autoFocusNearTarget = false)
  748. {
  749. //自动战斗不允许中断当前技能施放.
  750. return false;
  751. }
  752. private void UpdateDoStopSkill()
  753. {
  754. if (this.CurrentState is StateSkill)
  755. {
  756. if (mDoStopSkill)
  757. {
  758. var ss = (this.CurrentState as StateSkill);
  759. if (ss.IsCancelableByMove || ss.IsCancelableBySkill)
  760. {
  761. ss.block();
  762. mDoStopSkill = false;
  763. }
  764. }
  765. }
  766. else
  767. {
  768. mDoStopSkill = false;
  769. }
  770. }
  771. protected override void doGuard(UnitGuardAction act)
  772. {
  773. //没有通关不能自动战斗.
  774. if (act.guard == true && this.Virtual != null && (this.Virtual as XmdsVirtual_Player).AllowUseAutoGuard() == false)
  775. {
  776. // 机器人除外.
  777. if (IsRobot)
  778. {
  779. return;
  780. }
  781. }
  782. cleanFocus();
  783. lastAttackUnit = null;
  784. XmdsVirtual.FormatLog(CommonLang.Log.LoggerLevel.DEBUG, "act.reason:" + act.reason);
  785. if (act.guard == false)
  786. {
  787. // mAutoGuardTargetList.Clear();
  788. }
  789. else
  790. {
  791. try
  792. {
  793. ParseGuardActionReason(act.reason);
  794. }
  795. catch (Exception error)
  796. {
  797. XmdsVirtual.FormatLog(CommonLang.Log.LoggerLevel.ERROR, "ParseGuardActionReason Error : " + act.reason + " error : " + error.ToString());
  798. }
  799. }
  800. base.doGuard(act);
  801. }
  802. //private static List<int> s_RobotScenID = new List<int>() { 21202, 11001, 11002, 11004,11006, 21202,11021,11022,11047,11048,11049,
  803. // 11050,11052,11053,11056,11061,11064, 11019,11065,11068,11071, 11072,11074,12116,12119, 11012,11015,11019,11024,11029,11045};
  804. /// <summary>
  805. /// 解析挂机指令,新增指令头,告知是定点挂机还是全图游走.
  806. /// 第0位 map/point:
  807. /// 第1位 怪物模板ID:
  808. /// EG: map:怪物模板ID:怪物模板ID
  809. /// </summary>
  810. /// <param name="reason"></param>
  811. private void ParseGuardActionReason(string reason)
  812. {
  813. if (mCurGuardMode == GuardMode.Mode_Point)
  814. {
  815. mGuardPos.SetX(this.X);
  816. mGuardPos.SetY(this.Y);
  817. }
  818. # if OPNE_JSG_AI_TOOLS
  819. if (this.IsRobot)
  820. {
  821. this.mGuardSearchRange = 50;
  822. reason = CommonAI.XmdsConstConfig.AUTO_GUARD_MODE_MAP;
  823. }
  824. #endif
  825. if (string.IsNullOrEmpty(reason))
  826. {
  827. return;
  828. }
  829. string[] array = reason.Split(SPLIT);
  830. if (array != null && array.Length > 0)
  831. {
  832. string head = array[0];
  833. if (head == CommonAI.XmdsConstConfig.AUTO_GUARD_MODE_MAP) //全图模式.
  834. {
  835. mCurGuardMode = GuardMode.Mode_Map;
  836. }
  837. else if (head == CommonAI.XmdsConstConfig.AUTO_GUARD_MODE_POINT)//定点模式.
  838. {
  839. mCurGuardMode = GuardMode.Mode_Point;
  840. mGuardPos.SetX(this.X);
  841. mGuardPos.SetY(this.Y);
  842. }
  843. //array可能是point: point:0 point:taskId:targetId
  844. if (array.Length >= 3)
  845. {
  846. clearAutoGuardTargetList();
  847. if (!string.IsNullOrEmpty(array[1]))
  848. {
  849. int taskId = int.Parse(array[1]);
  850. for (int i = 2; i < array.Length; i++)
  851. {
  852. if (!string.IsNullOrEmpty(array[i]))
  853. {
  854. int targetId = int.Parse(array[i]);
  855. if (targetId > 0)
  856. {
  857. mAutoGuardTargetList.Add(targetId);
  858. log.Debug("--------------addTarget id: " + targetId);
  859. }
  860. }
  861. }
  862. }
  863. }
  864. }
  865. }
  866. private float GetGuardPosX()
  867. {
  868. switch (mCurGuardMode)
  869. {
  870. case GuardMode.Mode_Map:
  871. return this.X;
  872. case GuardMode.Mode_Point:
  873. return mGuardPos.X;
  874. default:
  875. return this.X;
  876. }
  877. }
  878. private float GetGuardPosY()
  879. {
  880. switch (mCurGuardMode)
  881. {
  882. case GuardMode.Mode_Map:
  883. return this.Y;
  884. case GuardMode.Mode_Point:
  885. return mGuardPos.Y;
  886. default:
  887. return this.Y;
  888. }
  889. }
  890. //查找自动攻击单位.
  891. public override InstanceUnit findGuardTarget(SkillTemplate.CastTarget expect = SkillTemplate.CastTarget.Enemy, AttackReason reason = AttackReason.Look)
  892. {
  893. InstanceUnit min = null;
  894. if (getAvailableAutoLaunchSkill(expect) != null)
  895. {
  896. //有优先目标取优先目标攻击.
  897. if (mAutoGuardTargetList.Count > 0)
  898. {
  899. //using (var list = ListObjectPool<InstanceUnit>.AllocAutoRelease())
  900. List<InstanceUnit> list = new List<InstanceUnit>();
  901. {
  902. Parent.ForEachNearObjects(GetGuardPosX(), GetGuardPosY(), mGuardSearchRange, (InstanceUnit u, ref bool cancel) =>
  903. {
  904. if (mCurGuardMode == GuardMode.Mode_Point && (MathVector.getDistanceSquare(u.X, u.Y, this.X, this.Y) > mGuardSearchRangeExt))
  905. {
  906. return;
  907. }
  908. if (Parent.IsAttackable(this, u, expect, reason, Info))
  909. {
  910. XmdsVirtual zv = u.Virtual as XmdsVirtual;
  911. if (zv != null)
  912. {
  913. if (mAutoGuardTargetList.Contains(zv.GetVirtualTemplateID()))
  914. {
  915. list.Add(u);
  916. }
  917. }
  918. }
  919. });
  920. if (list.Count > 0)
  921. {
  922. list.Sort((a, b) =>
  923. {
  924. float da = CMath.getDistanceSquare(a.X, a.Y, this.X, this.Y);
  925. float db = CMath.getDistanceSquare(b.X, b.Y, this.X, this.Y);
  926. return (int)(da - db);
  927. });
  928. min = list[0];
  929. if (min != null)
  930. {
  931. mAutoGuardTargetTimes = 0;
  932. }
  933. }
  934. //log.Debug("findGuardTarget times: " + mAutoGuardTargetTimes + " count:" + mAutoGuardTargetList.Count + " min:" + (min == null ? "null" : "finded"));
  935. //找不到目标怪就直接返回null等下一次查找,直到等待MAX_AUTO_GUARD_TARGET_TIMES次数
  936. if (mAutoGuardTargetList.Count > 0 && min == null)
  937. {
  938. mAutoGuardTargetTimes += 1;
  939. if (mAutoGuardTargetTimes >= MAX_AUTO_GUARD_TARGET_TIMES)
  940. {
  941. clearAutoGuardTargetList();
  942. }
  943. else
  944. {
  945. return null;
  946. }
  947. }
  948. }
  949. }
  950. //没有优先目标,按照默认逻辑走.
  951. //原本是走父类逻辑,但是现在要分挂机模式,要分索敌范围.
  952. //base.findGuardTarget(expect, reason);
  953. if (min == null)
  954. {
  955. if (getAvailableSkill(expect) != null)
  956. {
  957. bool isMeSteah = this.IsHasSubState(UnitActionSubStatus.Stealth);
  958. float min_len = float.MaxValue;
  959. Parent.ForEachNearObjects(GetGuardPosX(), GetGuardPosY(), mGuardSearchRange, (InstanceUnit u, ref bool cancel) =>
  960. {
  961. // 别人隐身了,自己没有隐身,自动攻击不到
  962. if(u.Virtual.GetBattleStatus() == BattleStatus.None && u.IsHasSubState(UnitActionSubStatus.Stealth) && !isMeSteah)
  963. {
  964. return;
  965. }
  966. float len = MathVector.getDistanceSquare(u.X, u.Y, this.X, this.Y);
  967. if (mCurGuardMode == GuardMode.Mode_Point && len > mGuardSearchRangeExt)
  968. {
  969. return;
  970. }
  971. if (Parent.IsAttackable(this, u, expect, reason, Info))
  972. {
  973. #if OPNE_JSG_AI_TOOLS
  974. //降低机器人之间的互相PK概率
  975. //if (this.IsRobot && u.IsPlayer)
  976. //{
  977. // XmdsInstancePlayer uPlayer = u as XmdsInstancePlayer;
  978. // if (uPlayer.IsRobot && this.RandomN.Next() % 100 < 95)
  979. // {
  980. // return;
  981. // }
  982. //}
  983. //AI随机攻击目标
  984. if (this.IsRobot && this.RandomN.Next() % 100 < 15)
  985. {
  986. min = u;
  987. cancel = true;
  988. return;
  989. }
  990. #endif
  991. if (min_len > len)
  992. {
  993. min_len = len;
  994. min = u;
  995. }
  996. }
  997. });
  998. }
  999. return min;
  1000. }
  1001. }
  1002. return min;
  1003. }
  1004. /// <summary>
  1005. /// 当任务完成时
  1006. /// </summary>
  1007. /// <param name="qd"></param>
  1008. protected override void onQuestCommitted(QuestData qd)
  1009. {
  1010. int targetId = XmdsQuestData.GetTargetID(qd);
  1011. if (this.mAutoGuardTargetList.Contains(targetId))
  1012. {
  1013. clearAutoGuardTargetList();
  1014. }
  1015. }
  1016. public override void OnReconnected(UnitInfo temp, int force, int level, Vector2 enterPos)
  1017. {
  1018. (this.Virtual as XmdsVirtual_Player).OnUnitReEnter(temp, force, level, enterPos);
  1019. base.OnReconnected(temp, force, level, enterPos);
  1020. }
  1021. public override void OnDisconnected()
  1022. {
  1023. base.OnDisconnected();
  1024. var act = new UnitGuardAction();
  1025. act.guard = false;
  1026. doGuard(act);
  1027. var actFollow = new UnitFollowAction();
  1028. actFollow.follow = false;
  1029. doFollow(actFollow);
  1030. }
  1031. protected override void doFollow(UnitFollowAction act)
  1032. {
  1033. base.doFollow(act);
  1034. if (act.follow == true)
  1035. {
  1036. if (this.TeamVirtual != null && this.stateFollow != null)
  1037. {
  1038. if (this.TeamVirtual.TeamLeader != null && this.TeamVirtual.TeamLeader.Enable)
  1039. {
  1040. if (this.TeamVirtual.acceptAutoFollow(this))
  1041. {
  1042. this.TeamVirtual.changeMemberAutoFollow();
  1043. this.stateFollow.Distance = this.TeamVirtual.TeamLeader.RadiusSize + (this.BodyBlockSize * (this.FollowIndex + 1)) * 2;
  1044. //this.changeState(this.stateFollow);
  1045. }
  1046. else
  1047. {
  1048. this.TeamVirtual.cancelAutoFollow(this);
  1049. this.TeamVirtual.changeMemberAutoFollow();
  1050. }
  1051. }
  1052. else if (this.TeamVirtual.TeamLeader == null)
  1053. {
  1054. this.TeamVirtual.cancelAutoFollow(this);
  1055. this.TeamVirtual.changeMemberAutoFollow();
  1056. }
  1057. }
  1058. }
  1059. else
  1060. {
  1061. if (this.TeamVirtual != null)
  1062. {
  1063. this.TeamVirtual.cancelAutoFollow(this);
  1064. this.TeamVirtual.changeMemberAutoFollow();
  1065. }
  1066. }
  1067. }
  1068. public void SendBotTestAutoFight()
  1069. {
  1070. if (mBotTestAutoFight == true)
  1071. {
  1072. var act = new UnitGuardAction();
  1073. act.guard = true;
  1074. doGuard(act);
  1075. }
  1076. }
  1077. #region 自动释放技能.
  1078. /// <summary>
  1079. /// 获得当前能够使用的技能.
  1080. /// </summary>
  1081. /// <returns></returns>
  1082. protected SkillState GetAvailableAutoLaunchSkill(ref InstanceUnit enemy)
  1083. {
  1084. SkillState ret = null;
  1085. do
  1086. {
  1087. //没蓝直接转普攻.
  1088. if (mXmdsFocusTarget == null) { break; }
  1089. List<SkillState> list = SkillStatus as List<SkillState>;
  1090. XmdsStateFollowAndAttack current = CurrentState as XmdsStateFollowAndAttack;
  1091. //优先多段攻击技能
  1092. if (current != null)
  1093. {
  1094. for (int si = list.Count - 1; si >= 0; --si)
  1095. {
  1096. SkillState sst = list[si];
  1097. if (sst == null || (DefaultSkill != null && DefaultSkill.ID == sst.Data.ID))
  1098. {
  1099. continue;
  1100. }
  1101. if (sst.LaunchSkill.AutoLaunch && sst.IsActive && sst.IsMutilAction() && sst.IsHasNext()
  1102. && sst.IsCD && sst.IsDone && this.VirtualPlayer.SkillAutoLaunchTest(sst))
  1103. {
  1104. //System.Console.WriteLine(" - GetAvailableAutoLaunchSkill - " + sst.ID + ", " + sst.ActionIndex);
  1105. ret = sst;
  1106. break;
  1107. }
  1108. }
  1109. }
  1110. //其次技能.
  1111. if (ret != null) { break; }
  1112. for (int si = list.Count - 1; si >= 0; --si)
  1113. {
  1114. SkillState sst = list[si];
  1115. //非PVP, PVE状态下不允许释放技能
  1116. if (DefaultSkill != null && sst.Data.ID != DefaultSkill.ID &&
  1117. sst.LaunchSkill.AutoLaunch && (Virtual.IsInPVP() || Virtual.IsInPVE()))
  1118. {
  1119. if (!sst.IsCD && sst.IsActive && sst.IsDone && sst.LaunchSkill.AutoLaunch && sst.CanAutoLaunch() &&
  1120. this.VirtualPlayer.SkillAutoLaunchTest(sst))
  1121. {
  1122. //判断需要能量值
  1123. if (!this.Virtual.LaunchSkillCheckTalentInfo(sst))
  1124. {
  1125. continue;
  1126. }
  1127. //切换作用不同的技能,这时需要切换技能目标,会导致丢失原目标.
  1128. if (mXmdsFocusTarget.ExpectTarget != sst.Data.ExpectTarget)
  1129. {
  1130. enemy = findGuardTarget(sst.Data.ExpectTarget, AttackReason.Look);
  1131. }
  1132. if (enemy != null)
  1133. {
  1134. ret = sst;
  1135. }
  1136. break;
  1137. }
  1138. }
  1139. }
  1140. } while (false);
  1141. //没有技能时施放普攻.
  1142. if (ret == null && DefaultSkill != null)
  1143. {
  1144. if (enemy != null)
  1145. {
  1146. ret = getSkillState(DefaultSkill.ID);
  1147. }
  1148. }
  1149. return ret;
  1150. }
  1151. /// <summary>
  1152. /// 判断目标技能是否可以自动释放.
  1153. /// </summary>
  1154. /// <param name="skillid"></param>
  1155. /// <returns></returns>
  1156. //private bool CanAutoLaunchSkill(int skillid)
  1157. //{
  1158. // bool ret = false;
  1159. // var v = (this.Virtual as XmdsVirtual);
  1160. // if (v != null)
  1161. // {
  1162. // ret = v.AllowAutoLaunch(skillid);
  1163. // }
  1164. // return ret;
  1165. //}
  1166. public override SkillState getRandomLaunchableExpectSkill(InstanceUnit target, SkillTemplate.CastTarget expectTarget, AttackReason reason = AttackReason.Tracing, bool checkRange = false)
  1167. {
  1168. var ss = GetAvailableAutoLaunchSkill(ref target);
  1169. if (mXmdsFocusTarget != null && target != null && ss != null)
  1170. {
  1171. //mXmdsFocusTarget.TargetUnit = target;
  1172. //mXmdsFocusTarget.ExpectSkillState = ss;
  1173. //mXmdsFocusTarget.ChangeMoveTarget(target);
  1174. mXmdsFocusTarget.ChangeAttackTarget(ss, target);
  1175. }
  1176. return ss;
  1177. }
  1178. private InstanceUnit lastAttackUnit = null;
  1179. public override SkillState getRandomLaunchableExpectSkill(SkillTemplate.CastTarget expectTarget)
  1180. {
  1181. InstanceUnit unit = null;
  1182. if (mXmdsFocusTarget != null)
  1183. {
  1184. unit = mXmdsFocusTarget.TargetUnit;
  1185. }
  1186. var ss = GetAvailableAutoLaunchSkill(ref unit);
  1187. if (mXmdsFocusTarget != null && unit != null && ss != null)
  1188. {
  1189. //mXmdsFocusTarget.TargetUnit = unit;
  1190. //mXmdsFocusTarget.ExpectSkillState = ss;
  1191. //mXmdsFocusTarget.ChangeMoveTarget(unit);
  1192. if (ss.Data.ExpectTarget != mXmdsFocusTarget.ExpectTarget)
  1193. {
  1194. if (mXmdsFocusTarget.ExpectTarget == SkillTemplate.CastTarget.Enemy)
  1195. {
  1196. lastAttackUnit = mXmdsFocusTarget.TargetUnit;
  1197. }
  1198. }
  1199. mXmdsFocusTarget.ChangeAttackTarget(ss, unit);
  1200. }
  1201. return ss;
  1202. }
  1203. public void OnReceiveGetMonsterSufferDamageInfoC2B(GetMonsterSufferDamageInfoC2B evt)
  1204. {
  1205. var ret = evt as GetMonsterSufferDamageInfoC2B;
  1206. //找到指定的怪物单位,获取伤害信息并排序.
  1207. InstanceUnit iu = this.Parent.getUnit(ret.MonsterID);
  1208. if (iu != null && iu is XmdsInstanceMonster)
  1209. {
  1210. XmdsVirtual_Monster zvm = (iu as XmdsInstanceMonster).Virtual as XmdsVirtual_Monster;
  1211. if (zvm != null)
  1212. {
  1213. HashMap<string, PlayerDamageInfo> map = zvm.GetSufferDamage();
  1214. if (map != null)
  1215. {
  1216. MonsterSufferDamageInfoB2C msg = new MonsterSufferDamageInfoB2C();
  1217. List<PlayerDamageInfo> infoList = new List<PlayerDamageInfo>();
  1218. int playerRank = 0;
  1219. int playerDamage = 0;
  1220. //获取数据并排序.
  1221. foreach (var kvp in map)
  1222. {
  1223. infoList.Add(kvp.Value);
  1224. }
  1225. //伤害从大到小排序.
  1226. infoList.Sort((a, b) =>
  1227. {
  1228. return b.Damage - a.Damage;
  1229. });
  1230. //找到自己的排名和伤害.
  1231. for (int i = 0; i < infoList.Count; i++)
  1232. {
  1233. var temp = infoList[i];
  1234. if (this.PlayerUUID == temp.PlayerUUID)
  1235. {
  1236. playerRank = i + 1;
  1237. playerDamage = temp.Damage;
  1238. break;
  1239. }
  1240. }
  1241. //只取10条详细信息发送.
  1242. if (infoList.Count > 10)
  1243. {
  1244. infoList.RemoveRange(10, infoList.Count - 10);
  1245. }
  1246. msg.PlayerDamage = playerDamage;
  1247. msg.PlayerRank = playerRank;
  1248. msg.InfoList = infoList;
  1249. this.queueEvent(msg);
  1250. }
  1251. }
  1252. }
  1253. }
  1254. #endregion
  1255. #region 绕开底层重新实现自动战斗AI.
  1256. private XmdsInstanceUnitStateMachine.XmdsStateFollowAndAttack doXmdsFocusAttack(InstanceUnit target,
  1257. SkillTemplate.CastTarget expect_target = SkillTemplate.CastTarget.Enemy,
  1258. bool autoFocusNearTarget = true, InstanceUnit.SkillState lanuchSkill = null)
  1259. {
  1260. if ((mAttackTo == null || mAttackTo.IsAttack) && Parent.IsAttackable(this, target, expect_target, AttackReason.Tracing, Info))
  1261. {
  1262. this.mLastAutoAttackTime = CommonLang.CUtils.localTimeMS;
  1263. if (mXmdsFocusTarget != null)
  1264. {
  1265. if (mXmdsFocusTarget.TargetUnit != target)
  1266. {
  1267. mXmdsFocusTarget = new XmdsInstanceUnitStateMachine.XmdsStateFollowAndAttack(this, target, expect_target, autoFocusNearTarget, lanuchSkill);
  1268. if (changeState(mXmdsFocusTarget))
  1269. {
  1270. queueEvent(new PlayerFocuseTargetEvent(this.ID, target.ID, expect_target));
  1271. }
  1272. }
  1273. }
  1274. else
  1275. {
  1276. mXmdsFocusTarget = new XmdsInstanceUnitStateMachine.XmdsStateFollowAndAttack(this, target, expect_target, autoFocusNearTarget, lanuchSkill);
  1277. if (changeState(mXmdsFocusTarget))
  1278. {
  1279. queueEvent(new PlayerFocuseTargetEvent(this.ID, target.ID, expect_target));
  1280. }
  1281. }
  1282. }
  1283. else
  1284. {
  1285. mXmdsFocusTarget = null;
  1286. }
  1287. return mXmdsFocusTarget;
  1288. }
  1289. private void doXmdsFocusAttack(InstanceUnit target, SkillState state)
  1290. {
  1291. SkillTemplate.CastTarget expect_target = state.Data.ExpectTarget;
  1292. if ((mAttackTo == null || mAttackTo.IsAttack) && Parent.IsAttackable(this, target, expect_target, AttackReason.Tracing, Info))
  1293. {
  1294. if (mXmdsFocusTarget != null)
  1295. {
  1296. if (mXmdsFocusTarget.TargetUnit != target)
  1297. {
  1298. mXmdsFocusTarget = new XmdsInstanceUnitStateMachine.XmdsStateFollowAndAttack(this, target, expect_target, true);
  1299. mXmdsFocusTarget.ExpectSkillState = state;
  1300. if (changeState(mXmdsFocusTarget))
  1301. {
  1302. queueEvent(new PlayerFocuseTargetEvent(this.ID, target.ID, expect_target));
  1303. }
  1304. }
  1305. }
  1306. else
  1307. {
  1308. mXmdsFocusTarget = new XmdsInstanceUnitStateMachine.XmdsStateFollowAndAttack(this, target, expect_target, true);
  1309. mXmdsFocusTarget.ExpectSkillState = state;
  1310. if (changeState(mXmdsFocusTarget))
  1311. {
  1312. queueEvent(new PlayerFocuseTargetEvent(this.ID, target.ID, expect_target));
  1313. }
  1314. }
  1315. }
  1316. else
  1317. {
  1318. mXmdsFocusTarget = null;
  1319. }
  1320. }
  1321. protected override void cleanFocus()
  1322. {
  1323. mFocusTarget = null;
  1324. mXmdsFocusTarget = null;
  1325. base.cleanFocus();
  1326. }
  1327. protected override void doFocusTarget(UnitFocuseTargetAction focus)
  1328. {
  1329. if (IsGuard)
  1330. {
  1331. mAttackTo = null;
  1332. InstanceZoneObject src = Parent.getObject<InstanceZoneObject>(focus.targetUnitID);
  1333. //目标不能是宠物
  1334. if ((src is InstanceUnit) && !(src is InstancePet))
  1335. {
  1336. if (!IsNoneSkill && ((src as InstanceUnit).IsActive))
  1337. {
  1338. doXmdsFocusAttack(src as InstanceUnit);
  1339. }
  1340. }
  1341. else if ((src is InstanceItem))
  1342. {
  1343. if (src.Enable)
  1344. {
  1345. doFocusPickItem(src as InstanceItem);
  1346. }
  1347. }
  1348. else
  1349. {
  1350. cleanFocus();
  1351. }
  1352. }
  1353. }
  1354. public override void OnUnitDead()
  1355. {
  1356. this.cleanFocus();
  1357. // 死亡取消自动战斗
  1358. if (this.IsGuard)
  1359. {
  1360. this.IsGuard = false;
  1361. this.Virtual.doEvent(JSGCustomOpType.UpdateAutoBattleFlag);
  1362. }
  1363. }
  1364. public override void doSomething()
  1365. {
  1366. if (mWaitingSkill != null && CurrentState is StateSkill)
  1367. {
  1368. if (doLaunchSkill(mWaitingSkill))
  1369. {
  1370. return;
  1371. }
  1372. }
  1373. else if(this.DoAutoPick())
  1374. {
  1375. return;
  1376. }
  1377. else if (IsGuard)
  1378. {
  1379. if (this.canFollowTeam && leadingMan != null)
  1380. {
  1381. if (leadingMan.AoiStatus != null)
  1382. {
  1383. //若队长进入位面
  1384. UnitGuardAction action = new UnitGuardAction();
  1385. action.guard = false;
  1386. action.reason = "guard to follow";
  1387. doGuard(action);
  1388. startIdle();
  1389. return;
  1390. }
  1391. else if (leadingMan.Virtual.GetBattleStatus() == BattleStatus.None)
  1392. {
  1393. UnitGuardAction action = new UnitGuardAction();
  1394. action.guard = false;
  1395. action.reason = "guard to follow";
  1396. doGuard(action);
  1397. updateStateToFollowTeam();
  1398. mXmdsFocusTarget = null;
  1399. return;
  1400. }
  1401. this.stateFollow.Distance = this.leadingMan.RadiusSize + (this.BodyBlockSize * (this.FollowIndex + 1)) * 2;
  1402. //var distance = leadingMan.RadiusSize + this.BodyBlockSize * 2;
  1403. if (!CMath.includeRoundPoint(X, Y, this.GetFollowDistance(true), leadingMan.X, leadingMan.Y))
  1404. {
  1405. UnitGuardAction action = new UnitGuardAction();
  1406. action.guard = false;
  1407. action.reason = "guard to follow";
  1408. doGuard(action);
  1409. updateStateToFollowTeam();
  1410. mXmdsFocusTarget = null;
  1411. return;
  1412. }
  1413. }
  1414. if (mFocusPickItem != null && mFocusPickItem.IsActive)
  1415. {
  1416. changeState(mFocusPickItem);
  1417. return;
  1418. }
  1419. else
  1420. {
  1421. mFocusPickItem = null;
  1422. }
  1423. if (mXmdsFocusTarget != null && mXmdsFocusTarget.IsActive)
  1424. {
  1425. if (Parent.IsAttackable(this, mXmdsFocusTarget.TargetUnit, SkillTemplate.CastTarget.AlliesIncludeSelf, AttackReason.Attack, Info))
  1426. {
  1427. mXmdsFocusTarget = null;
  1428. }
  1429. else
  1430. {
  1431. changeState(mXmdsFocusTarget);
  1432. return;
  1433. }
  1434. }
  1435. else
  1436. {
  1437. mXmdsFocusTarget = null;
  1438. }
  1439. if (mAttackTo != null && !mAttackTo.IsDone)
  1440. {
  1441. changeState(mAttackTo);
  1442. return;
  1443. }
  1444. }
  1445. else if (this.canFollowTeam && leadingMan != null)
  1446. {
  1447. if (leadingMan.Enable)
  1448. {
  1449. if (this.CurrentState != this.stateFollow)
  1450. {
  1451. if (leadingMan.AoiStatus != null)
  1452. {
  1453. //若队长进入位面
  1454. return;
  1455. }
  1456. this.stateFollow.Distance = this.leadingMan.RadiusSize + (this.BodyBlockSize * (this.FollowIndex + 1)) * 2;
  1457. if (!CMath.includeRoundPoint(X, Y, this.GetFollowDistance(false), leadingMan.X, leadingMan.Y))
  1458. {
  1459. this.updateStateToFollowTeam();
  1460. mXmdsFocusTarget = null;
  1461. }
  1462. else
  1463. {//组队切场景后,如果队长不移动,队员状态不改变
  1464. this.updateStateToFollowTeam();
  1465. mXmdsFocusTarget = null;
  1466. }
  1467. }
  1468. else
  1469. {
  1470. //发生寻路卡死
  1471. //transportToTeamLeader();
  1472. }
  1473. //var distance = leadingMan.RadiusSize + this.BodyBlockSize * 2;
  1474. //if (!CMath.includeRoundPoint(X, Y, distance, leadingMan.X, leadingMan.Y))
  1475. //{
  1476. // this.updateStateToFollowTeam();
  1477. // mXmdsFocusTarget = null;
  1478. // return;
  1479. //}
  1480. return;
  1481. }
  1482. else
  1483. {
  1484. //leadingMan忙,切换leadingMan
  1485. //mTeamVirtual.changeMemberAutoFollow();
  1486. }
  1487. }
  1488. else if (CurrentState is StateChuanGongA || CurrentState is StateChuanGongB || CurrentState is StateClearYaoQi)
  1489. {
  1490. if (CommonLang.CUtils.localTimeMS < chuangongTime)
  1491. {
  1492. return;
  1493. }
  1494. }
  1495. else if(CurrentState is StateDaZuo)
  1496. {
  1497. return;
  1498. }
  1499. else if (CurrentState is StateDaZuoRecoveryAttr)
  1500. {
  1501. return;
  1502. }
  1503. startIdle();
  1504. }
  1505. #endregion
  1506. private float GetFollowDistance(bool isGuard)
  1507. {
  1508. if (isGuard)
  1509. {
  1510. return Templates.CFG.PET_FOLLOW_DISTANCE_MAX;
  1511. }
  1512. return this.stateFollow.Distance;
  1513. }
  1514. private void OnPlayerCreate()
  1515. {
  1516. lock (CreateInfoMap)
  1517. {
  1518. AtomicInteger c = null;
  1519. zoneID = (this.Parent as EditorScene).Data.ID;
  1520. if (CreateInfoMap.TryGetValue(zoneID, out c))
  1521. {
  1522. c++;
  1523. }
  1524. else
  1525. {
  1526. c = new AtomicInteger(1);
  1527. CreateInfoMap.Add(zoneID, c);
  1528. }
  1529. }
  1530. }
  1531. ~XmdsInstancePlayer()
  1532. {
  1533. lock (CreateInfoMap)
  1534. {
  1535. AtomicInteger c = null;
  1536. if (CreateInfoMap.TryGetValue(zoneID, out c))
  1537. {
  1538. c--;
  1539. }
  1540. }
  1541. }
  1542. //组队跟随
  1543. private XmdsTeamVirtual mTeamVirtual;
  1544. public XmdsTeamVirtual TeamVirtual
  1545. {
  1546. set
  1547. {
  1548. mTeamVirtual = value;
  1549. }
  1550. get
  1551. {
  1552. return mTeamVirtual;
  1553. }
  1554. }
  1555. private byte mFollowIndex;
  1556. public byte FollowIndex
  1557. {
  1558. set
  1559. {
  1560. mFollowIndex = value;
  1561. }
  1562. get
  1563. {
  1564. return mFollowIndex;
  1565. }
  1566. }
  1567. protected XmdsInstancePlayer leadingMan;
  1568. public XmdsInstancePlayer Leader
  1569. {
  1570. get
  1571. {
  1572. return leadingMan;
  1573. }
  1574. set
  1575. {
  1576. if (leadingMan != value)
  1577. {
  1578. leadingMan = value;
  1579. if (leadingMan == null)
  1580. {
  1581. this.stateFollow = null;
  1582. }
  1583. else
  1584. {
  1585. if (this.stateFollow == null)
  1586. {
  1587. this.stateFollow = new StateFollowLeader(this, leadingMan, 300);
  1588. }
  1589. else
  1590. {
  1591. this.stateFollow.Follower = leadingMan;
  1592. }
  1593. //this.stateFollow = StateFollowTeam.createStateFollowTeam(this, leadingMan);
  1594. }
  1595. }
  1596. }
  1597. }
  1598. public bool canFollowTeam = false;
  1599. public StateFollowLeader stateFollow;
  1600. override public bool isTeamMemberAndFollow()
  1601. {
  1602. return canFollowTeam;
  1603. }
  1604. //切换至跟随状态
  1605. public void updateStateToFollowTeam()
  1606. {
  1607. if (this.mIsReady)
  1608. {
  1609. if (this.canFollowTeam)
  1610. {
  1611. if (this.stateFollow != null && this.CurrentState != this.stateFollow)
  1612. {
  1613. this.changeState(this.stateFollow);
  1614. }
  1615. else if (this.stateFollow == null)
  1616. {
  1617. mTeamVirtual.changeMemberAutoFollow();
  1618. }
  1619. }
  1620. }
  1621. }
  1622. public void cancelGuard()
  1623. {
  1624. if (IsGuard)
  1625. {
  1626. log.Debug("------guardCanceled: " + this.Name);
  1627. UnitGuardAction action = new UnitGuardAction();
  1628. action.guard = false;
  1629. action.reason = "sdfsdfsdfs";
  1630. doGuard(action);
  1631. SetAutoBattleB2C evt = new SetAutoBattleB2C();
  1632. evt.isAutoBattle = 0;
  1633. this.queueEvent(evt);
  1634. }
  1635. }
  1636. /// <summary>
  1637. ///
  1638. /// </summary>
  1639. private void updateFollowTeam()
  1640. {
  1641. if (this.CurrentState == this.stateFollow && this.mTeamVirtual != null && this.canFollowTeam && this.leadingMan != null && this.leadingMan.Enable)
  1642. {
  1643. // 当前如果正在拾取状态,先捡完再说
  1644. if(this.CurrentState is StateFollowAndPickItem)
  1645. {
  1646. return;
  1647. }
  1648. if (CMath.includeRoundPoint(X, Y, this.GetFollowDistance(true), leadingMan.X, leadingMan.Y))
  1649. {
  1650. //在范围内
  1651. var leader = this.leadingMan;
  1652. if (leader.AoiStatus != null)
  1653. {
  1654. //队长在位面中
  1655. UnitGuardAction action = new UnitGuardAction();
  1656. action.guard = false;
  1657. action.reason = "sdfsdfsdfs";
  1658. doGuard(action);
  1659. startIdle();
  1660. //updateStateToFollowTeam();
  1661. return;
  1662. }
  1663. var vir = leader.Virtual as XmdsVirtual;
  1664. if (vir.CombatState == BattleStatus.PVE)
  1665. {
  1666. if (IsGuard == false)
  1667. {
  1668. //队长在PVE状态
  1669. UnitGuardAction action = new UnitGuardAction();
  1670. action.guard = true;
  1671. action.reason = CommonAI.XmdsConstConfig.AUTO_GUARD_MODE_POINT;
  1672. doGuard(action);
  1673. }
  1674. }
  1675. else if (vir.CombatState == BattleStatus.PVP)
  1676. {
  1677. //队长在PVP状态
  1678. //检查玩家Pk状态在“自由”,“队伍”攻击模式下,则跟随队长攻击目标,否则无视
  1679. var myVir = this.Virtual as XmdsVirtual;
  1680. if (IsGuard == false/* &&( myVir.GetCurPKMode() == PKInfo.PKMode.Team
  1681. || myVir.GetCurPKMode() == PKInfo.PKMode.All)*/)
  1682. {
  1683. UnitGuardAction action = new UnitGuardAction();
  1684. action.guard = true;
  1685. action.reason = CommonAI.XmdsConstConfig.AUTO_GUARD_MODE_POINT;
  1686. doGuard(action);
  1687. }
  1688. }
  1689. }
  1690. else
  1691. {
  1692. UnitGuardAction action = new UnitGuardAction();
  1693. action.guard = false;
  1694. action.reason = "sdfsdfsdfs";
  1695. doGuard(action);
  1696. updateStateToFollowTeam();
  1697. }
  1698. }
  1699. }
  1700. //检测修正部分异常数据
  1701. private void UpdateAndModifyErrorData()
  1702. {
  1703. if(this.CurrentActionStatus == UnitActionStatus.Move)
  1704. {
  1705. if(this.mNotMoveTimes == 0)
  1706. {
  1707. this.mNotMoveTimes = 1;
  1708. this.mLastMovePos.SetX(this.X);
  1709. this.mLastMovePos.SetY(this.Y);
  1710. }
  1711. else if(this.mLastMovePos.X == this.X && this.mLastMovePos.Y == this.Y)
  1712. {
  1713. this.mNotMoveTimes++;
  1714. }
  1715. else
  1716. {
  1717. this.mNotMoveTimes = 0;
  1718. }
  1719. if(this.mNotMoveTimes > 10)
  1720. {
  1721. this.mNotMoveTimes = 0;
  1722. this.doSomething();
  1723. }
  1724. }
  1725. else
  1726. {
  1727. this.mNotMoveTimes = 0;
  1728. }
  1729. }
  1730. //移动到队长旁
  1731. public void moveToLeader()
  1732. {
  1733. if (!this.mIsReady)
  1734. {
  1735. this.readyAction = moveToLeader;
  1736. return;
  1737. }
  1738. if (this.leadingMan != null)
  1739. {
  1740. if (this.CurrentState != this.stateFollow)
  1741. {
  1742. this.changeState(this.stateFollow);
  1743. var virt = this.Virtual as XmdsVirtual;
  1744. if (!virt.IsMounted && !virt.IsInDebuffStatus() && !CMath.includeRoundPoint(this.X, this.Y, this.Templates.CFG.TEAMER_FOLLOW_DISTANCE_LIMIT, this.leadingMan.X, this.leadingMan.Y))
  1745. {
  1746. PlayerSummonMountEventR2B r2b = new PlayerSummonMountEventR2B();
  1747. r2b.TimeMS = 0;
  1748. r2b.IsSummonMount = true;
  1749. (this.Virtual as XmdsVirtual).ReceiveMsgR2B(r2b);
  1750. }
  1751. }
  1752. //float dx, dy;
  1753. //var distance = this.leadingMan.RadiusSize + (this.BodyBlockSize * (this.FollowIndex + 1)) * 2;
  1754. //CMath.RandomPosInRound(Parent.RandomN, this.leadingMan.X, this.leadingMan.Y,
  1755. // distance, out dx, out dy);
  1756. //if (CMath.includeRoundPoint(
  1757. // this.X, this.Y,
  1758. // distance,
  1759. // dx, dy))
  1760. //{
  1761. // this.changeState(this.stateFollow);
  1762. // return;
  1763. //}
  1764. //this.changeState(new StateIdle(this));
  1765. ////StateFollowTeam stateMove = StateFollowTeam.createStateFollowTeam(this, leadingMan);
  1766. //StateMove stateMove = new StateMove(this, dx, dy);
  1767. //stateMove.EndMoveAction = (m) =>
  1768. //{
  1769. // this.changeState(this.stateFollow);
  1770. // return false;
  1771. //};
  1772. //var virt = this.Virtual as XmdsVirtual;
  1773. //if (!virt.IsMounted && !CMath.includeRoundPoint(this.X, this.Y, this.Templates.CFG.TEAMER_FOLLOW_DISTANCE_LIMIT, this.leadingMan.X, this.leadingMan.Y))
  1774. //{
  1775. // PlayerSummonMountEventR2B r2b = new PlayerSummonMountEventR2B();
  1776. // r2b.TimeMS = 0;
  1777. // r2b.IsSummonMount = true;
  1778. // (this.Virtual as XmdsVirtual).ReceiveMsgR2B(r2b);
  1779. //}
  1780. //this.changeState(stateMove);
  1781. }
  1782. }
  1783. protected override void onAdded(bool pointLv)
  1784. {
  1785. base.onAdded(pointLv);
  1786. //吴永辉:进入PVP地图清除技能CD bugId:2797
  1787. XmdsServerScene scene = this.Parent as XmdsServerScene;
  1788. SceneType sceneType = this.VirtualPlayer.mUnit.GetSceneType();
  1789. if (sceneType == SceneType.DanTiao || sceneType == SceneType.JJC || sceneType == SceneType.CrossServer || sceneType == SceneType.MengZhan
  1790. || sceneType == SceneType.FiveVFive || sceneType == SceneType.SourceDungeon
  1791. || sceneType == SceneType.GuildBoss || sceneType == SceneType.SecretDungeon)
  1792. {
  1793. this.ClearAllSkillCD();
  1794. }
  1795. }
  1796. }
  1797. //队伍跟随
  1798. public class StateFollowLeader : VStateFollowLeader
  1799. {
  1800. private InstanceZoneObject follower;
  1801. public InstanceZoneObject Follower
  1802. {
  1803. get
  1804. {
  1805. return follower;
  1806. }
  1807. set
  1808. {
  1809. follower = value;
  1810. this.target = follower;
  1811. }
  1812. }
  1813. public StateFollowLeader(InstanceUnit unit, InstanceZoneObject target, int holdTime = 0) : base(unit, target, holdTime)
  1814. {
  1815. follower = target;
  1816. }
  1817. protected override void onStart()
  1818. {
  1819. if (follower != null)
  1820. {
  1821. unit.SetActionStatus(UnitActionStatus.Move);
  1822. MoveAI.FindPath(follower);
  1823. }
  1824. }
  1825. protected override void onUpdate()
  1826. {
  1827. base.onUpdate();
  1828. switch (FollowState)
  1829. {
  1830. case MoveState.Move:
  1831. var virt = unit.Virtual as XmdsVirtual;
  1832. if (!virt.IsMounted && !virt.IsInDebuffStatus() && !CMath.includeRoundPoint(unit.X, unit.Y, unit.Templates.CFG.TEAMER_FOLLOW_DISTANCE_LIMIT, follower.X, follower.Y))
  1833. {
  1834. //Console.WriteLine("请求上马");
  1835. PlayerSummonMountEventR2B r2b = new PlayerSummonMountEventR2B();
  1836. r2b.TimeMS = 0;
  1837. r2b.IsSummonMount = true;
  1838. (unit.Virtual as XmdsVirtual).ReceiveMsgR2B(r2b);
  1839. }
  1840. break;
  1841. }
  1842. }
  1843. protected override void onUpdateFollowed(IPositionObject target)
  1844. {
  1845. unit.doSomething();
  1846. }
  1847. protected override void onChangedToMove(IPositionObject target)
  1848. {
  1849. var virt = unit.Virtual as XmdsVirtual;
  1850. if (!virt.IsMounted && !virt.IsInDebuffStatus() && !CMath.includeRoundPoint(unit.X, unit.Y, unit.Templates.CFG.TEAMER_FOLLOW_DISTANCE_LIMIT, follower.X, follower.Y))
  1851. {
  1852. PlayerSummonMountEventR2B r2b = new PlayerSummonMountEventR2B();
  1853. r2b.TimeMS = 0;
  1854. r2b.IsSummonMount = true;
  1855. (unit.Virtual as XmdsVirtual).ReceiveMsgR2B(r2b);
  1856. }
  1857. }
  1858. }
  1859. }