XmdsVirtual_Player.cs 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972
  1. using CommonAI.Zone;
  2. using CommonLang;
  3. using System.Collections.Generic;
  4. using XmdsCommon.Message;
  5. using XmdsCommon.Plugin;
  6. using XmdsCommonServer.Message;
  7. using XmdsCommonServer.Plugin.Units;
  8. using XmdsCommonServer.Plugin.XmdsSkillTemplate.Skills;
  9. using CommonAI.Zone.Instance;
  10. using System;
  11. using CommonLang.Vector;
  12. using XmdsCommon.EditorData;
  13. using CommonAI.Zone.Formula;
  14. using CommonAI.Data;
  15. using CommonAI;
  16. using CommonAI.data;
  17. using XmdsCommonSkill.Plugin.CardSkill;
  18. namespace XmdsCommonServer.Plugin
  19. {
  20. public partial class XmdsVirtual_Player : XmdsVirtual
  21. {
  22. /// <summary>
  23. /// 攻击记录.
  24. /// </summary>
  25. private HashMap<string, string> mAtkRecordMap = new HashMap<string, string>();
  26. /// <summary>
  27. /// PK值在线计时器.
  28. /// </summary>
  29. private TimeInterval<int> mPKValueCycleTimer = null;
  30. /// <summary>
  31. /// PK信息.
  32. /// </summary>
  33. private PKInfo mPKInfo = null;
  34. /// <summary>
  35. /// 药剂HP恢复.
  36. /// </summary>
  37. private ItemRecoveryTask mHPRecoveryTask = new ItemRecoveryTask();
  38. /// <summary>
  39. /// 宠物.
  40. /// </summary>
  41. private XmdsVirtual_Pet mPet = null;
  42. protected long mPkTime = 0;
  43. public XmdsVirtual_Player(XmdsInstancePlayer unit) : base(unit)
  44. {
  45. unit.OnRebirth += Unit_OnRebirth;
  46. unit.OnRemoved += Unit_OnRemoved;
  47. }
  48. private void Unit_OnRemoved(CommonAI.Zone.Instance.InstanceUnit unit)
  49. {
  50. //主人离开场景,移除宠物.
  51. if (mPet != null)
  52. {
  53. DismissPet();
  54. }
  55. }
  56. private void Unit_OnRebirth(CommonAI.Zone.Instance.InstanceUnit unit)
  57. {
  58. //重置遗言.
  59. SyncTestament(0);
  60. }
  61. public void SyncTestament(byte testamentID)
  62. {
  63. if (mProp.ServerData.BaseInfo.Testament != testamentID)
  64. {
  65. mProp.ServerData.BaseInfo.Testament = testamentID;
  66. SyncPlayerVisibleData();
  67. SendTestamentChangeEventB2C(testamentID);
  68. }
  69. }
  70. /** 获得宠物天赋加成 */
  71. public override int GetPetTalentAddition(UnitFateType type)
  72. {
  73. if(mPet != null && type == mPet.GetUnitFateType())
  74. {
  75. return mPet.GetPetTalentAddition(type);
  76. }
  77. return 0;
  78. }
  79. public override XmdsVirtual_Player GetPlayerUnit()
  80. {
  81. return this;
  82. }
  83. #region override.
  84. protected override void Init(bool pointLv)
  85. {
  86. InitPKCycleTimer();
  87. InitQuestData();
  88. // InitQuestFlags();
  89. this.mProp.ServerData.PlayerEntered = true;
  90. //同步客户端可见信息.
  91. //设置发给别的玩家显示信息//
  92. PlayerVisibleDataB2C pvdb2c = new PlayerVisibleDataB2C();
  93. //avatar信息.
  94. pvdb2c.AvatarList = mProp.ServerData.AvatarList;
  95. //基础信息.
  96. pvdb2c.BaseInfo = mProp.ServerData.BaseInfo;
  97. //PK相关信息.
  98. pvdb2c.UnitPKInfo = mProp.ServerData.UnitPKInfo;
  99. //场景数据.
  100. pvdb2c.UnitSceneInfo = mProp.ServerData.UnitSceneInfo;
  101. mUnit.SetVisibleInfo(pvdb2c);
  102. mPKInfo = this.mProp.ServerData.UnitPKInfo;
  103. #region 宠物数据MOCK.
  104. //-------------------------------------------------.
  105. /*
  106. //宠物Mock数据.测试数据,当前宠物为无敌状态.
  107. PetData pd = new PetData();
  108. pd.PetConfig = new XmdsPetConifg();
  109. pd.PetConfig.Mode = XmdsPetConifg.XmdsPetFollowMode.ActiveAtk;
  110. pd.BaseInfo = new PetBaseInfo();
  111. XmdsUnitSkillInfo skillInfo = new XmdsUnitSkillInfo();
  112. List<GameSkill> l = new List<GameSkill>();
  113. GameSkill gs = new GameSkill();
  114. gs.SkillID = 100101;
  115. gs.SkillLevel = 1;
  116. gs.SkillType = GameSkill.XmdsSkillType.normalAtk;
  117. l.Add(gs);
  118. skillInfo.UnitSkills = l;
  119. pd.SkillInfo = skillInfo;
  120. UnitInfo info = XmdsBattleSkill.GetUnitInfo(DEFAULT_TEMPLATE_ID);
  121. this.mProp.ServerData.UnitPetData = pd;
  122. this.mProp.ServerData.UnitPetData.BaseInfo.level = 1;
  123. this.mProp.ServerData.UnitPetData.UnitProp = (info.Properties as XmdsUnitProperties).ServerData.Prop;
  124. this.mProp.ServerData.UnitPetData.UnitProp.MinPhy = 1;// 4803;
  125. this.mProp.ServerData.UnitPetData.UnitProp.MaxPhy = 1;// 4921;
  126. this.mProp.ServerData.UnitPetData.UnitProp.Hit = 710;
  127. this.mProp.ServerData.UnitPetData.UnitProp.Crit = 50;
  128. this.mProp.ServerData.UnitPetData.UnitProp.Dodge = 1;
  129. this.mProp.ServerData.UnitPetData.UnitProp.Rescrit = 949;
  130. this.mProp.ServerData.UnitPetData.UnitProp.Ac = 2229;
  131. this.mProp.ServerData.UnitPetData.UnitProp.Resist = 1500;
  132. this.mProp.ServerData.UnitPetData.UnitProp.HP = 1;
  133. */
  134. //-------------------------------------------------.
  135. #endregion
  136. //宠物数据.
  137. ChangePet(this.mProp.ServerData.UnitPetData);
  138. if (mProp.BotTestTemplate)
  139. {
  140. (this.mUnit as XmdsInstancePlayer).SendBotTestAutoFight();
  141. }
  142. }
  143. public override void doEvent(JSGCustomOpType type)
  144. {
  145. if(type == JSGCustomOpType.UpdateAutoBattleFlag)
  146. {
  147. SetAutoBattleB2C evt = new SetAutoBattleB2C();
  148. InstancePlayer playerUnit = mUnit as InstancePlayer;
  149. evt.isAutoBattle = playerUnit.IsGuard ? 1 : 0;
  150. this.mUnit.queueEvent(evt);
  151. }
  152. }
  153. public void OnUnitReEnter(UnitInfo temp, int force, int level, Vector2 enterPos)
  154. {
  155. SyncClientData();
  156. }
  157. protected override void SyncClientData()
  158. {
  159. base.SyncClientData();
  160. SyncPKValue(mPKInfo.CurPKValue, true);
  161. }
  162. public override void SyncBattlePropsFields(ulong mask)
  163. {
  164. if (mask != 0)
  165. {
  166. if (mBattlePropChangeEvt == null)
  167. {
  168. mBattlePropChangeEvt = new PlayerBattlePropChangeEventB2C();
  169. }
  170. mBattlePropChangeEvt.Mask |= mask;
  171. }
  172. }
  173. public long getPkTime()
  174. {
  175. return CUtils.CurrentTimeMS - mPkTime;
  176. }
  177. public int getPkValue()
  178. {
  179. return mPKInfo.CurPKValue;
  180. }
  181. public override void OnUnitDead(XmdsVirtual killer)
  182. {
  183. //怪物死亡时,需要计算组队分享人员名单.
  184. mHateSystem.CalAtkAssistantList(false);
  185. base.OnUnitDead(killer);
  186. }
  187. public override int OnHit(XmdsVirtual attacker, AttackSource source)
  188. {
  189. int ret = base.OnHit(attacker, source);
  190. if (ret > 0 && attacker is XmdsVirtual_Player)
  191. {
  192. mPkTime = CUtils.CurrentTimeMS;
  193. }
  194. return ret;
  195. }
  196. public override void OnHitOthter(XmdsVirtual target)
  197. {
  198. if (mHateSystem.ContainsID(target.mUnit.ID) == false)
  199. {
  200. mHateSystem.AddTarget(target);
  201. }
  202. if (CalPKValue(target) == true)
  203. {
  204. if ((target is XmdsVirtual_Player ||
  205. target is XmdsVirtual_SummonUnit ||
  206. target is XmdsVirtual_Pet) &&
  207. target.GetCurPKLevel() == PKLevel.White)
  208. {
  209. string id = target.GetPlayerUUID();
  210. if (id != this.GetPlayerUUID() && !string.IsNullOrEmpty(id))
  211. {
  212. //判断该单位是否有被攻击过.
  213. if (mAtkRecordMap.ContainsKey(id) == false)
  214. {
  215. AtkRecordAdd(id);
  216. }
  217. }
  218. }
  219. }
  220. #region MOCK 恢复道具.
  221. //PropertyChangeEventR2B evt = new PropertyChangeEventR2B();
  222. //evt.ChangeType = PropertyChangeEventR2B.PropertyChangeType.HP;
  223. //evt.ChangeValue = 10000;
  224. //evt.Duration = 10000;
  225. //evt.ChangeValueType = PropertyChangeEventR2B.ValueType.Value;
  226. //OnRceivePropertyChangeEventR2B(evt);
  227. #endregion
  228. }
  229. public override bool TryLaunchSkill(InstanceUnit.SkillState skill, ref InstanceUnit.LaunchSkillParam param)
  230. {
  231. #region PK保护.
  232. //var pkprotect = IsInPKProtect(param.TargetUnitID);
  233. //if (pkprotect)
  234. //{
  235. // SendMsgToClient(CommonAI.XmdsConstConfig.TIPS_IN_PK_PROTECT);
  236. // return false;
  237. //}
  238. #endregion
  239. bool ret = base.TryLaunchSkill(skill, ref param);
  240. if (ret == true)
  241. {
  242. if (param.TargetUnitID != 0 && (this.mHateSystem.ContainsID(param.TargetUnitID) == false))
  243. {
  244. InstanceUnit u = this.mUnit.Parent.getUnit(param.TargetUnitID);
  245. if (u != null && u != this.mUnit)
  246. {
  247. if (!this.IsAllies(u.Virtual as XmdsVirtual, false))
  248. {
  249. this.mHateSystem.AddTarget(u.Virtual as XmdsVirtual);
  250. }
  251. }
  252. }
  253. }
  254. return ret;
  255. }
  256. public override void OnKillUnit(XmdsVirtual dead)
  257. {
  258. if (CalPKValue(dead) == true)
  259. {
  260. if (dead.IsPlayerUnit() &&
  261. dead.GetCurPKLevel() == PKLevel.White &&
  262. dead.GetPlayerUUID() != this.GetPlayerUUID())
  263. {
  264. SyncPKValue(XmdsGameConfig.Instance.PK_KILL_ADD + this.mPKInfo.CurPKValue);
  265. }
  266. }
  267. #region Mock技能增删.
  268. /*
  269. List<GameSkill> ret = new List<GameSkill>();
  270. GameSkill gs = new GameSkill();
  271. gs.SkillID = 300010;
  272. gs.SkillLevel = ++skilllv;
  273. gs.SkillType = GameSkill.XmdsSkillType.active;
  274. gs.TalentSkillLevel = 1;
  275. ret.Add(gs);
  276. Mock_ReplaceSkill(ret);
  277. */
  278. #endregion
  279. }
  280. protected override void OnCombatStateChange(BattleStatus status)
  281. {
  282. base.OnCombatStateChange(status);
  283. if (status == BattleStatus.None) { mAtkRecordMap.Clear(); }
  284. /*测试怪物伤害信息.
  285. GetMonsterSufferDamageInfoC2B evt = new GetMonsterSufferDamageInfoC2B();
  286. evt.MonsterID = 3;
  287. (this.mUnit as XmdsInstancePlayer).OnReceiveGetMonsterSufferDamageInfoC2B(evt);
  288. */
  289. }
  290. protected override bool JudgeChangeCombatStateChange(BattleStatus status, byte reason)
  291. {
  292. //普通情况下,召唤物未出战斗状态,主人也处于战斗状态.
  293. if (status == BattleStatus.None && reason == 0)
  294. {
  295. if (mSummonList != null && mSummonList.Count > 0)
  296. {
  297. for (int i = 0; i < mSummonList.Count; i++)
  298. {
  299. if (mSummonList[i].CombatState != BattleStatus.None)
  300. {
  301. return false;
  302. }
  303. }
  304. }
  305. //如果宠物在战斗状态,主人无法脱战.
  306. if (mPet != null && mPet.CombatState != BattleStatus.None)
  307. {
  308. return false;
  309. }
  310. }
  311. return true;
  312. }
  313. protected override void CombatStateConnect(BattleStatus status, byte reason)
  314. {
  315. //主人进入战斗状态,影响召唤物.
  316. if (mSummonList != null && mSummonList.Count > 0)
  317. {
  318. for (int i = 0; i < mSummonList.Count; i++)
  319. {
  320. mSummonList[i].SetCombatState(status);
  321. }
  322. }
  323. if (mPet != null && mPet.mUnit.IsDead() == false)
  324. {
  325. mPet.SetCombatState(status);
  326. }
  327. }
  328. public override string GetPlayerUUID()
  329. {
  330. return (mUnit as XmdsInstancePlayer).PlayerUUID;
  331. }
  332. public override bool IsMember(XmdsVirtual target, PKMode mode, bool includeSelf, bool onlyForTeam = false)
  333. {
  334. bool ret = false;
  335. if (this.mUnit == target.mUnit)
  336. {
  337. return includeSelf == true;
  338. }
  339. if (target.mUnit.Virtual is XmdsCommon.ZoneClient.XmdsClientVirtual.XmdsClientVirtual_Pet)
  340. {
  341. return true;//自动选取目标时选中宠物的bug
  342. }
  343. //非玩家单位统一走force.
  344. if (target.IsPlayerUnit() == false)
  345. {
  346. ret = this.mUnit.Force == target.mUnit.Force ? true : false;
  347. }
  348. else
  349. {
  350. switch (mode)
  351. {
  352. case PKMode.Peace://和平模式使用默认出生的force.
  353. //只用阵营会导致,不是队友,给他加增益buff得情况
  354. ret = this.mUnit.Force == target.mUnit.Force ? true : false;
  355. if (ret && onlyForTeam)
  356. {
  357. ret = this.IsTeamMember(target.GetPlayerUUID());
  358. }
  359. break;
  360. case PKMode.force://阵营模式使用Camp.
  361. ret = this.IsCampMember(target.GetForceID());
  362. if (ret == false)
  363. {
  364. ret = this.IsTeamMember(target.GetPlayerUUID());
  365. }
  366. break;
  367. case PKMode.Guild:
  368. ret = this.IsGuildMember(target.GetGuildID());
  369. if (ret == false)
  370. {
  371. ret = this.IsTeamMember(target.GetPlayerUUID());
  372. }
  373. break;
  374. case PKMode.Team:
  375. ret = this.IsTeamMember(target.GetPlayerUUID());
  376. break;
  377. case PKMode.All:
  378. ret = (target.GetPlayerUUID() == this.GetPlayerUUID());
  379. break;
  380. case PKMode.Justice:
  381. ret = target.GetCurPKLevel() == PKLevel.White ? true : false;
  382. if (ret == false)
  383. {
  384. ret = this.IsTeamMember(target.GetPlayerUUID());
  385. }
  386. break;
  387. case PKMode.Server:
  388. ret = this.IsServerMember(target.GetServerID());
  389. if (ret == false)
  390. {
  391. ret = this.IsTeamMember(target.GetPlayerUUID());
  392. }
  393. break;
  394. }
  395. }
  396. return ret;
  397. }
  398. public override void OnUpdateTriggerSkill(int intervalMS, bool slowRefresh)
  399. {
  400. base.OnUpdateTriggerSkill(intervalMS, slowRefresh);
  401. UpdatePKCycleTimer(intervalMS);
  402. UpdateItemRecoveryTask(intervalMS);
  403. }
  404. public override bool IsPlayerUnit() { return true; }
  405. protected override void Dispose()
  406. {
  407. mUnit.OnRebirth -= Unit_OnRebirth;
  408. mUnit.OnRemoved -= Unit_OnRemoved;
  409. CleanSummonList();
  410. if (mAtkRecordMap != null)
  411. {
  412. mAtkRecordMap.Clear();
  413. }
  414. mPet = null;
  415. base.Dispose();
  416. }
  417. public bool AllowUseAutoGuard()
  418. {
  419. bool ret = false;
  420. try
  421. {
  422. //机器人玩家默认可以使用自动战斗.
  423. if (mProp.BotTestTemplate)
  424. {
  425. return true;
  426. }
  427. ret = mProp.ServerData.UnitSceneInfo.AllowAutoGuard;
  428. }
  429. catch (Exception error)
  430. {
  431. ret = true;
  432. FormatLog(CommonLang.Log.LoggerLevel.ERROR, "AllowUseAutoGuard Error:{0}", error.ToString());
  433. }
  434. return ret;
  435. }
  436. protected override void InitSceneInfo()
  437. {
  438. base.InitSceneInfo();
  439. switch (this.mUnit.GetSceneType())
  440. {
  441. case CommonAI.Data.SceneType.Dungeon://副本中索敌范围扩大.
  442. case CommonAI.Data.SceneType.DanTiao:
  443. case CommonAI.Data.SceneType.JJC:
  444. case CommonAI.Data.SceneType.GuildDungeon:
  445. case CommonAI.Data.SceneType.MengZhan:
  446. case CommonAI.Data.SceneType.FiveVFive:
  447. case CommonAI.Data.SceneType.GoblinTower:
  448. case CommonAI.Data.SceneType.SourceDungeon:
  449. case CommonAI.Data.SceneType.HaoYueJing:
  450. case CommonAI.Data.SceneType.GuildBoss:
  451. case CommonAI.Data.SceneType.SecretDungeon:
  452. case CommonAI.Data.SceneType.FightLevelUltra:
  453. case CommonAI.Data.SceneType.PickLotus:
  454. case CommonAI.Data.SceneType.CROSS_SERVER_NEW:
  455. case CommonAI.Data.SceneType.NCS_FengShen:
  456. case CommonAI.Data.SceneType.DEVIL:
  457. (this.mUnit as XmdsInstancePlayer).SetGuardSearchRange(XmdsConfig.Instance.DUNGEON_AUTO_GUARD_RANGE);
  458. break;
  459. case CommonAI.Data.SceneType.NCS_MutilCross:
  460. case CommonAI.Data.SceneType.NCS_DoubleCross:
  461. (this.mUnit as XmdsInstancePlayer).SetGuardSearchRange(XmdsConfig.Instance.PVP_AUTO_GUARD_RANGE);
  462. break;
  463. default:
  464. (this.mUnit as XmdsInstancePlayer).SetGuardSearchRange(XmdsConfig.Instance.NORMALSCENE_AUTO_GUARD_RANGE);
  465. break;
  466. }
  467. //针对一些特殊的副本,设置拾取范围(全部改成手动拾取,所以这里没啥用了)
  468. //switch (this.mUnit.GetSceneType())
  469. //{
  470. // case CommonAI.Data.SceneType.NCS_MutilCross:
  471. // case CommonAI.Data.SceneType.NCS_DoubleCross:
  472. // case CommonAI.Data.SceneType.NCS_FengShen:
  473. // case CommonAI.Data.SceneType.DEVIL:
  474. // this.mUnit.SetAutoPickRange(XmdsConstConfig.AUTOPICK_RANGE_PVP);
  475. // break;
  476. // default:
  477. // break;
  478. //}
  479. }
  480. #endregion
  481. #region private.
  482. private void SendTestamentChangeEventB2C(byte testamentID)
  483. {
  484. TestamentChangeEventB2C evt = new TestamentChangeEventB2C();
  485. evt.TestamentID = testamentID;
  486. this.mUnit.queueEvent(evt);
  487. }
  488. private void SendPKLevelChangeEventB2C(PKLevel lv)
  489. {
  490. PlayerPKLvChangeEventB2C evt = new PlayerPKLvChangeEventB2C();
  491. evt.CurLv = lv;
  492. this.mUnit.queueEvent(evt);
  493. }
  494. private void SendPKValueChangeEventB2C(int v)
  495. {
  496. PlayerPKValueChangeEventB2C evt = new PlayerPKValueChangeEventB2C();
  497. evt.CurPKValue = v;
  498. this.mUnit.queueEvent(evt);
  499. }
  500. /// <summary>
  501. /// PK值在线衰退计时器.
  502. /// </summary>
  503. private void InitPKCycleTimer()
  504. {
  505. mPKValueCycleTimer = new TimeInterval<int>(XmdsGameConfig.Instance.PK_VALUE_UPDATE_CYCLE);
  506. mPKValueCycleTimer.FirstTimeEnable = false;
  507. }
  508. /// <summary>
  509. /// 刷新计时器.
  510. /// </summary>
  511. /// <param name="intervalMS"></param>
  512. private void UpdatePKCycleTimer(int intervalMS)
  513. {
  514. if (mPKInfo != null && mPKInfo.CurPKValue > 0 && mPKValueCycleTimer.Update(intervalMS))
  515. {
  516. SyncPKValue(mPKInfo.CurPKValue - XmdsGameConfig.Instance.PK_VALUE_REDUCE);
  517. }
  518. }
  519. /// <summary>
  520. /// 攻击列表刷新.
  521. /// </summary>
  522. /// <param name="id"></param>
  523. private void AtkRecordAdd(string id)
  524. {
  525. mAtkRecordMap.Add(id, id);
  526. SyncPKValue(XmdsGameConfig.Instance.PK_ATK_ADD + mPKInfo.CurPKValue);
  527. }
  528. /// <summary>
  529. /// 同步PK值.
  530. /// </summary>
  531. /// <param name="v"></param>
  532. private void SyncPKValue(int v, bool refresh = false)
  533. {
  534. v = (int)CMath.getInRange(v, 0, int.MaxValue);
  535. if (mPKInfo.CurPKValue == v && refresh == false) { return; }
  536. mPKInfo.CurPKValue = v;
  537. //等于0时重置.
  538. if (mPKInfo.CurPKValue == 0 && mPKValueCycleTimer != null)
  539. {
  540. mPKValueCycleTimer.Reset();
  541. }
  542. SendPKValueChangeEventB2C(v);
  543. //等级变更时推送给客户端.
  544. PKLevel l;
  545. if (mPKInfo.CurPKValue == 0)
  546. {
  547. l = PKLevel.White;
  548. }
  549. else if (CMath.isIncludeEqual(mPKInfo.CurPKValue,
  550. XmdsGameConfig.Instance.PK_LEVEL_BLACK_RANGE[0],
  551. XmdsGameConfig.Instance.PK_LEVEL_BLACK_RANGE[1]))
  552. {
  553. l = PKLevel.Black;
  554. }
  555. else if (CMath.isIncludeEqual(mPKInfo.CurPKValue,
  556. XmdsGameConfig.Instance.PK_LEVEL_YELLOW_RANGE[0],
  557. XmdsGameConfig.Instance.PK_LEVEL_YELLOW_RANGE[1]))
  558. {
  559. l = PKLevel.Yellow;
  560. }
  561. else
  562. {
  563. l = PKLevel.Red;
  564. }
  565. if (mPKInfo.CurPKLevel != l)
  566. {
  567. mPKInfo.CurPKLevel = l;
  568. SyncPlayerVisibleData();
  569. SendPKLevelChangeEventB2C(l);
  570. }
  571. }
  572. private void UpdateItemRecoveryTask(int intervalMS)
  573. {
  574. mHPRecoveryTask.Update(intervalMS);
  575. }
  576. private bool IsInPKProtect(uint objID)
  577. {
  578. bool ret = false;
  579. //野外场景做判断.
  580. if (GetCurSceneType() != XmdsServerSceneData.NORMAL_MAP) { return ret; }
  581. //自己等级.
  582. int unitlv = this.GetUnitLv();
  583. //对方等级.
  584. int targetUnitLv = 0;
  585. uint id = objID;
  586. if (id != 0 && id != this.mUnit.ID)
  587. {
  588. var target = this.mUnit.Parent.getUnit(id);
  589. if (target != null)
  590. {
  591. var uuid = (target.Virtual as XmdsVirtual).GetPlayerUUID();
  592. var targetplayer = this.mUnit.Parent.getPlayerByUUID(uuid);
  593. if (targetplayer != null)
  594. {
  595. targetUnitLv = (targetplayer.Virtual as XmdsVirtual).GetUnitLv();
  596. //小于等于保护等级,不受伤害.
  597. if (targetUnitLv <= XmdsConfig.Instance.PK_PROTECT_LV || unitlv <= XmdsConfig.Instance.PK_PROTECT_LV)
  598. {
  599. ret = true;
  600. }
  601. }
  602. }
  603. }
  604. return ret;
  605. }
  606. //消耗过大,暂时屏蔽,后期考虑优化方案
  607. public override bool IsAttackable(XmdsVirtual attacker)
  608. {
  609. //只在野外地图下判断.
  610. //if (GetCurSceneType() == XmdsServerSceneData.NORMAL_MAP)
  611. //{
  612. // //自己等级.
  613. // int unitLv = GetUnitLv();
  614. // int attackerLv = 0;
  615. // string uuid = attacker.GetPlayerUUID();
  616. // var v = this.mUnit.Parent.getPlayerByUUID(uuid);
  617. // if (v != null && v != this.mUnit)
  618. // {
  619. // attackerLv = (v.Virtual as XmdsVirtual_Player).GetUnitLv();
  620. // if (attackerLv <= XmdsConfig.Instance.PK_PROTECT_LV || unitLv <= XmdsConfig.Instance.PK_PROTECT_LV)
  621. // {
  622. // return false;
  623. // }
  624. // }
  625. //}
  626. return true;
  627. }
  628. public class ItemRecoveryTask
  629. {
  630. public const int CYCLE_TIME = 500;
  631. private XmdsVirtual mOwner;
  632. private PropertyChangeEventR2B mEvt;
  633. private int mLifeTime = -1;
  634. private int mPassTime;
  635. private int mTimes = 1;
  636. private bool showFloatTips = false;
  637. public ItemRecoveryTask()
  638. {
  639. }
  640. public void Init(XmdsVirtual zv, PropertyChangeEventR2B evt, bool show)
  641. {
  642. mOwner = zv;
  643. mEvt = evt;
  644. mPassTime = CYCLE_TIME;
  645. //剩余时间.
  646. mLifeTime = (int)(evt.TimestampMS - TimeUtil.GetTimestampMS());
  647. //每秒次数.
  648. mTimes = (evt.Duration / CYCLE_TIME);
  649. showFloatTips = show;
  650. }
  651. public void Update(int intervalMS)
  652. {
  653. if (!IsEnd())
  654. {
  655. if (mPassTime >= CYCLE_TIME)
  656. {
  657. mPassTime -= CYCLE_TIME;
  658. switch (mEvt.ChangeType)
  659. {
  660. case PropertyChangeEventR2B.PropertyChangeType.HP:
  661. mOwner.AddHP(mEvt.ChangeValueType, (mEvt.ChangeValue * 1.0f / mTimes), showFloatTips);
  662. break;
  663. default: break;
  664. }
  665. }
  666. mPassTime += intervalMS;
  667. mLifeTime -= intervalMS;
  668. }
  669. }
  670. private bool IsEnd()
  671. {
  672. return (mLifeTime < 0);
  673. }
  674. }
  675. #endregion
  676. #region SummonUnit.
  677. private List<XmdsVirtual_SummonUnit> mSummonList = new List<XmdsVirtual_SummonUnit>();
  678. public void AddSummonUnitList(XmdsVirtual_SummonUnit unit)
  679. {
  680. mSummonList.Add(unit);
  681. unit.mUnit.OnDead += MUnit_OnDead;
  682. }
  683. private void MUnit_OnDead(CommonAI.Zone.Instance.InstanceUnit unit, CommonAI.Zone.Instance.InstanceUnit attacker)
  684. {
  685. XmdsVirtual_SummonUnit v = unit.Virtual as XmdsVirtual_SummonUnit;
  686. if (v != null && mSummonList != null)
  687. {
  688. unit.OnDead -= MUnit_OnDead;
  689. mSummonList.Remove(v);
  690. }
  691. }
  692. public int GetSummonUnitListCount()
  693. {
  694. return mSummonList.Count;
  695. }
  696. public XmdsVirtual_SummonUnit GetFirstTimesupSummonUnit()
  697. {
  698. if (mSummonList.Count > 0)
  699. {
  700. return mSummonList[0];
  701. }
  702. return null;
  703. }
  704. public void CleanSummonList()
  705. {
  706. if (mSummonList != null && mSummonList.Count > 0)
  707. {
  708. for (int i = 0; i < mSummonList.Count; i++)
  709. {
  710. mSummonList[i].mUnit.OnDead -= MUnit_OnDead;
  711. }
  712. mSummonList.Clear();
  713. }
  714. }
  715. #endregion
  716. #region Pet.
  717. public XmdsVirtual_Pet GetPet()
  718. {
  719. return mPet;
  720. }
  721. public override InstanceUnit GetPetUnit()
  722. {
  723. if(mPet != null)
  724. return mPet.mUnit;
  725. return null;
  726. }
  727. private void SummonPetData(PetData data)
  728. {
  729. if (data == null) { return; }
  730. var pos = mUnit.Parent.PathFinder.FindNearMoveableNode(
  731. mUnit.X,
  732. mUnit.Y,
  733. XmdsConfig.Instance.PET_IDLE_FOLLOW_MAX_DISTANCE, true);
  734. if (pos == null)
  735. {
  736. log.Error(" SummonPetData pos = null");
  737. return;
  738. }
  739. UnitInfo info = XmdsBattleSkill.GetUnitInfo(XmdsConstConfig.DEFAULT_PET_TEMPLATE_ID);
  740. if(info == null)
  741. {
  742. log.Warn("找不到宠物模板:" + XmdsConstConfig.DEFAULT_PET_TEMPLATE_ID);
  743. return ;
  744. }
  745. AddUnitEvent aue = null;
  746. XmdsUnitProperties prop = info.Properties as XmdsUnitProperties;
  747. //单位战斗属性赋值.
  748. //单位等级.
  749. prop.ServerData.BaseInfo.UnitLv = data.BaseInfo.level;
  750. //进阶等级.
  751. prop.ServerData.BaseInfo.StateLv = data.BaseInfo.StateLv;
  752. //能力赋值.
  753. prop.ServerData.Prop = data.UnitProp;
  754. //技能赋值.
  755. prop.ServerData.Skills = data.SkillInfo;
  756. var unit = (mUnit.Parent.AddUnit(
  757. info, info.Name,
  758. mUnit.Force, data.BaseInfo.level,
  759. pos.PosX,
  760. pos.PosY,
  761. mUnit.Direction,
  762. out aue,
  763. mUnit)) as XmdsInstancePet;
  764. var petVirtual = (unit.Virtual) as XmdsVirtual_Pet;
  765. data.BaseInfo.MasterID = this.mUnit.ID;
  766. petVirtual.InitVisibleData(data.BaseInfo);
  767. petVirtual.SetMaster(this);
  768. petVirtual.SetFollowMode(data.PetConfig.Mode);
  769. //设置宠物.
  770. mPet = petVirtual;
  771. //设置主人.
  772. unit.Master = this.mUnit;
  773. //宠物死亡后,清空引用避免内存泄露.
  774. unit.OnDead += PetUnit_OnDead;
  775. }
  776. private void PetUnit_OnDead(InstanceUnit unit, InstanceUnit attacker)
  777. {
  778. unit.OnDead -= PetUnit_OnDead;
  779. mPet = null;
  780. }
  781. /// <summary>
  782. /// 遣散宠物.
  783. /// </summary>
  784. private void DismissPet()
  785. {
  786. if (mPet != null)
  787. {
  788. this.mUnit.Parent.RemoveObjectByID(mPet.mUnit.ID);
  789. mPet = null;
  790. }
  791. }
  792. private void ChangePet(PetData data)
  793. {
  794. if (mPet != null)
  795. {
  796. DismissPet();
  797. }
  798. //召唤宠物.
  799. SummonPetData(data);
  800. }
  801. //宠物基础属性变更.
  802. private void UpdatePetBaseInfo(PetBaseInfo info)
  803. {
  804. //基础信息更新.
  805. if (mPet != null)
  806. {
  807. mPet.UpdateBaseInfo(info);
  808. }
  809. }
  810. //所有宠物相关属性变更.
  811. private void UpdatePetData(PetData data)
  812. {
  813. if (mPet != null)
  814. {
  815. //更新基础信息.
  816. UpdatePetBaseInfo(data.BaseInfo);
  817. //属性变更.
  818. mPet.UpdatePetProps(data.UnitProp);
  819. }
  820. }
  821. private void UpdatePetSkillInfo(PetSkillChangeEventR2B evt)
  822. {
  823. if (mPet != null)
  824. {
  825. mPet.OnReceivePetSkillChangeEventR2B(evt);
  826. }
  827. }
  828. #endregion
  829. }
  830. }