XmdsInstancePlayer.cs 67 KB

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