ZoneObject.Spell.cs 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875
  1. using CommonAI.RTS;
  2. using CommonLang.Vector;
  3. using CommonAI.Zone;
  4. using CommonAI.Zone.Helper;
  5. using CommonLang;
  6. using System;
  7. using System.Collections.Generic;
  8. using System.Linq;
  9. using System.Text;
  10. using CommonLang.Log;
  11. namespace CommonAI.ZoneClient
  12. {
  13. public class ZoneSpell : ZoneObject
  14. {
  15. public readonly SpellTemplate Info;
  16. public override string Name { get { return null; } }
  17. public override string DisplayName { get { return Info.Name; } }
  18. public override float X { get { return mLocalPos.X; } }
  19. public override float Y { get { return mLocalPos.Y; } }
  20. public override float Z { get { return mLocal_Z; } }
  21. public override float RadiusSize { get { return mDisplaySize; } }
  22. public float RotationX { get; internal set; }
  23. public ZoneObject Sender { get; internal set; }
  24. public ZoneUnit Launcher { get; internal set; }
  25. public ZoneUnit Target { get; internal set; }
  26. public Vector2 TargetPos { get; internal set; }
  27. public Vector2 StartPos { get { return mStartPos; } }
  28. public float LaunchHeight { get { return mStartHeight; } set { this.mStartHeight = value; this.mLocal_Z = value; } }
  29. public float BodySize { get { return mDisplaySize; } }
  30. public float Distance { get { return mDisplayDistance; } }
  31. public int PassTimeMS { get { return mPassTimeMS; } }
  32. private Vector2 mLocalPos = new Vector2();
  33. private float mLocal_Z = 0;
  34. private float mSizeLimit, mDisplaySize;
  35. private float mDistanceLimit, mDisplayDistance;
  36. private Vector2 mStartPos = new Vector2();
  37. private float mStartDirection;
  38. private float mStartHeight;
  39. private int mPassTimeMS;
  40. private float mSpeed;
  41. //private float mMoveDistance;
  42. private int mCurveMissileIndex = -1;
  43. private PopupKeyFrames<SpellTemplate.KeyFrame> mKeyFrames;
  44. private TimeInterval<SpellTemplate.KeyFrame> mHitIntervalTicker;
  45. private AddSpellEvent mAddEvent;
  46. public System.Action OnTargetChanged = null;
  47. private static HashMap<string, int> hashCurveMissileCnt = new HashMap<string, int>();
  48. private string strCurveMissileIndexKey;
  49. public ZoneSpell(SpellTemplate info, SyncSpellInfo syn, ZoneLayer parent, AddSpellEvent add)
  50. : base(syn.ObjectID, parent)
  51. {
  52. this.Info = info;
  53. RotationX = 0;
  54. this.mStartPos.SetX(syn.x);
  55. this.mStartPos.SetY(syn.y);
  56. this.mPos.SetX(syn.x);
  57. this.mPos.SetY(syn.y);
  58. this.mLocalPos.SetX(syn.x);
  59. this.mLocalPos.SetY(syn.y);
  60. this.mDirection = this.mStartDirection = syn.direction;
  61. this.mDistanceLimit = this.mDisplayDistance = info.Distance;
  62. this.mSizeLimit = this.mDisplaySize = info.BodySize;
  63. this.mPassTimeMS = 0;
  64. this.mAddEvent = add;
  65. if (add != null && add.IsHeight)
  66. {
  67. this.mLocal_Z = add.height;
  68. }
  69. this.mKeyFrames = new PopupKeyFrames<SpellTemplate.KeyFrame>();
  70. this.mKeyFrames.AddRange(info.KeyFrames);
  71. this.mHitIntervalTicker = new TimeInterval<SpellTemplate.KeyFrame>(info.HitIntervalMS);
  72. this.mHitIntervalTicker.Tag = info.HitIntervalKeyFrame;
  73. this.mSpeed = info.MSpeedSEC;
  74. //this.mMoveDistance = 0;
  75. if (syn.HasSpeed)
  76. {
  77. this.mSpeed = syn.CurSpeed;
  78. }
  79. if(info.MType == SpellTemplate.MotionType.CurveMissile)
  80. {
  81. int cnt;
  82. strCurveMissileIndexKey = add.sender_unit_id.ToString() + ":" + info.TemplateID.ToString();
  83. if (hashCurveMissileCnt.TryGetValue(strCurveMissileIndexKey, out cnt))
  84. {
  85. hashCurveMissileCnt[strCurveMissileIndexKey] = ++cnt;
  86. }
  87. else
  88. {
  89. hashCurveMissileCnt.Add(strCurveMissileIndexKey, 1);
  90. cnt = 1;
  91. }
  92. mCurveMissileIndex = cnt-1;
  93. }
  94. }
  95. protected override void Disposing()
  96. {
  97. if (!string.IsNullOrEmpty(strCurveMissileIndexKey))
  98. {
  99. int cnt;
  100. if (hashCurveMissileCnt.TryGetValue(strCurveMissileIndexKey, out cnt))
  101. {
  102. if (cnt <= 1)
  103. {
  104. hashCurveMissileCnt.Remove(strCurveMissileIndexKey);
  105. }
  106. else
  107. {
  108. hashCurveMissileCnt[strCurveMissileIndexKey] = cnt - 1;
  109. }
  110. }
  111. }
  112. base.Disposing();
  113. }
  114. protected internal override void OnAdded()
  115. {
  116. base.OnAdded();
  117. float radius = 0;
  118. if (mAddEvent != null)
  119. {
  120. if (mAddEvent.LaunchData.FromUnitBody && Sender != null && (Sender is ZoneUnit))
  121. {
  122. radius = (Sender as ZoneUnit).Info.LaunchSpellRadius;
  123. }
  124. else
  125. {
  126. radius = mAddEvent.LaunchData.LaunchSpellRadius;
  127. }
  128. }
  129. if (!Info.IsLaunchSpellEventSyncPos)
  130. {
  131. switch (Info.MType)
  132. {
  133. case SpellTemplate.MotionType.SelectTarget:
  134. if (Target != null)
  135. {
  136. mStartPos.SetX(Target.X);
  137. mStartPos.SetY(Target.Y);
  138. mLocal_Z = Target.Z;
  139. mStartDirection = Target.ServerDirection;
  140. }
  141. MathVector.movePolar(mStartPos, mStartDirection, radius);
  142. break;
  143. case SpellTemplate.MotionType.SelectLauncher:
  144. if (Launcher != null)
  145. {
  146. mStartPos.SetX(Launcher.X);
  147. mStartPos.SetY(Launcher.Y);
  148. mLocal_Z = Launcher.Z;
  149. mStartDirection = Launcher.ServerDirection;
  150. }
  151. MathVector.movePolar(mStartPos, mStartDirection, radius);
  152. break;
  153. case SpellTemplate.MotionType.Chain:
  154. if (Sender != null)
  155. {
  156. mStartPos.SetX(Sender.X);
  157. mStartPos.SetY(Sender.Y);
  158. mLocal_Z = Sender.Z;
  159. }
  160. break;
  161. case SpellTemplate.MotionType.AOE_Binding:
  162. case SpellTemplate.MotionType.Binding:
  163. if (Sender != null)
  164. {
  165. mStartPos.SetX(Sender.X);
  166. mStartPos.SetY(Sender.Y);
  167. mLocal_Z = Sender.Z;
  168. }
  169. break;
  170. case SpellTemplate.MotionType.AOE_BindingTarget:
  171. case SpellTemplate.MotionType.BindingTarget:
  172. if (Target != null)
  173. {
  174. mStartPos.SetX(Target.X);
  175. mStartPos.SetY(Target.Y);
  176. mLocal_Z = Target.Z;
  177. }
  178. break;
  179. }
  180. this.mPos.SetX(this.mStartPos.X);
  181. this.mPos.SetY(this.mStartPos.Y);
  182. this.mLocalPos.SetX(this.mStartPos.X);
  183. this.mLocalPos.SetY(this.mStartPos.Y);
  184. this.mDirection = this.mStartDirection;
  185. }
  186. if (Info.TargetEffect != null)
  187. {
  188. if (Target != null)
  189. {
  190. Parent.PreQueueEvent(new UnitEffectEvent(Target.ObjectID, Info.TargetEffect));
  191. }
  192. else if (TargetPos != null)
  193. {
  194. Parent.PreQueueEvent(new AddEffectEvent(0,TargetPos.X, TargetPos.Y, mDirection, Info.TargetEffect));
  195. }
  196. }
  197. }
  198. public override void ForceSyncPos(float x, float y)
  199. {
  200. this.mPos.SetX(x);
  201. this.mPos.SetY(y);
  202. this.mLocalPos.SetX(x);
  203. this.mLocalPos.SetY(y);
  204. }
  205. internal protected override void DoEvent(ObjectEvent e)
  206. {
  207. if (e is SpellLockTargetEvent)
  208. {
  209. doSpellLockTargetEvent(e as SpellLockTargetEvent);
  210. }
  211. else if (e is ObjectForceSyncPosEvent)
  212. {
  213. var oe = e as ObjectForceSyncPosEvent;
  214. this.ForceSyncPos(oe.X, oe.Y);
  215. this.Direction = oe.Direction;
  216. }
  217. }
  218. private void doSpellLockTargetEvent(SpellLockTargetEvent e)
  219. {
  220. if (Parent == null)
  221. {
  222. log.Error("doSpellLockTargetEvent -> Parent == null");
  223. }
  224. if (Info == null)
  225. {
  226. log.Error("doSpellLockTargetEvent -> Info == null");
  227. }
  228. if (e == null)
  229. {
  230. log.Error("doSpellLockTargetEvent -> e == null");
  231. }
  232. this.Target = Parent.GetUnit(e.target_obj_id);
  233. if(OnTargetChanged != null)
  234. {
  235. OnTargetChanged();
  236. }
  237. switch (Info.MType)
  238. {
  239. case SpellTemplate.MotionType.SeekerSelectTarget:
  240. if (Target != null)
  241. {
  242. this.mLocalPos.SetX(Target.X);
  243. this.mLocalPos.SetY(Target.Y);
  244. this.mLocal_Z = Target.Z;
  245. }
  246. break;
  247. }
  248. }
  249. internal protected override void Update()
  250. {
  251. int intervalMS = Parent.CurrentIntervalMS;
  252. mPassTimeMS += intervalMS;
  253. //法术位置更新交给战斗服
  254. /*if (Parent.ActorSyncMode != SyncMode.ForceByServer && (Info.MaxMoveDistance == 0 || mMoveDistance < Info.MaxMoveDistance))
  255. {
  256. updateMotion(intervalMS);
  257. }*/
  258. if (!this.Parent.IsSyncZ && Info.HeightUpdate)
  259. {
  260. var prez = this.mLocal_Z;
  261. updateZPos();
  262. //根据z向高度的变化,调整法术x轴Rotation
  263. float difz = mLocal_Z - prez;
  264. float speed_distance = MoveHelper.GetDistance(intervalMS, mSpeed);
  265. RotationX = (float)Math.Atan2(difz, speed_distance);
  266. }
  267. /*switch (Info.MType)
  268. {
  269. case SpellTemplate.MotionType.AOE:
  270. case SpellTemplate.MotionType.AOE_Binding:
  271. case SpellTemplate.MotionType.AOE_BindingTarget:
  272. updateAOE(intervalMS);
  273. break;
  274. }
  275. switch (Info.BodyShape)
  276. {
  277. case SpellTemplate.Shape.StripRayTouchEnd:
  278. updateRayTouchEnd();
  279. break;
  280. case SpellTemplate.Shape.LineToStart:
  281. case SpellTemplate.Shape.LineToTarget:
  282. updateLineToTarget();
  283. break;
  284. }
  285. if (Info.IsMoveable && (Info.MaxMoveDistance == 0 || mMoveDistance < Info.MaxMoveDistance))
  286. {
  287. MoveHelper.UpdateSpeed(intervalMS, ref mSpeed, Info.MSpeedAdd, Info.MSpeedAcc);
  288. MoveHelper.UpdateMoveDistance(intervalMS, ref mMoveDistance, mSpeed);
  289. }
  290. updateKeyFrames();*/
  291. }
  292. public override void SyncPos(ref SyncPosEvent.UnitPos pos)
  293. {
  294. base.SyncPos(ref pos);
  295. if (Parent.ActorSyncMode == SyncMode.ForceByServer)
  296. {
  297. mLocalPos.SetX(pos.X);
  298. mLocalPos.SetY(pos.Y);
  299. if (Parent.IsSyncZ) { this.Z = pos.Z; }
  300. }
  301. }
  302. //-----------------------------------------------------------------------
  303. #region _UpdateMotions_
  304. float foxfireRoundAngle = 0f;
  305. //float foxfireSeekWait = 0f;
  306. private Logger log = LoggerFactory.GetLogger("ZoneClientSpell");
  307. /// <summary>
  308. /// 更新移动行为
  309. /// </summary>
  310. private void updateMotion(int intervalMS)
  311. {
  312. float speed_distance = MoveHelper.GetDistance(intervalMS, mSpeed);
  313. try
  314. {
  315. switch (Info.MType)
  316. {
  317. case SpellTemplate.MotionType.SelectLauncher:
  318. case SpellTemplate.MotionType.SelectTarget:
  319. break;
  320. case SpellTemplate.MotionType.Cannon:
  321. case SpellTemplate.MotionType.Straight:
  322. MathVector.movePolar(mLocalPos, mStartDirection, speed_distance);
  323. break;
  324. case SpellTemplate.MotionType.StraightAndStop:
  325. if (PassTimeMS < Info.BoomerangFlyTime)
  326. {
  327. MathVector.movePolar(mLocalPos, mStartDirection, speed_distance);
  328. }
  329. //else if (PassTimeMS > Info.BoomerangFlyTime + Info.BoomerangHangtime)
  330. //{
  331. // PreFlyTo(Sender.X, Sender.Y, mSpeed * 1.8f, intervalMS);
  332. //}
  333. break;
  334. case SpellTemplate.MotionType.Boomerang1:
  335. if (PassTimeMS < Info.BoomerangFlyTime)
  336. {
  337. MathVector.movePolar(mLocalPos, mStartDirection, speed_distance);
  338. }
  339. else if (Sender != null && PassTimeMS > Info.BoomerangFlyTime + Info.BoomerangHangtime)
  340. {
  341. PreFlyTo(Sender.X, Sender.Y, mSpeed * 1.4f, intervalMS);
  342. }
  343. break;
  344. case SpellTemplate.MotionType.Boomerang2:
  345. if (PassTimeMS < Info.BoomerangFlyTime)
  346. {
  347. MathVector.movePolar(mLocalPos, mStartDirection, speed_distance);
  348. }
  349. else if (PassTimeMS > Info.BoomerangFlyTime + Info.BoomerangHangtime)
  350. {
  351. PreFlyTo(mStartPos.X, mStartPos.Y, mSpeed * 1.4f, intervalMS);
  352. }
  353. break;
  354. case SpellTemplate.MotionType.Immovability:
  355. case SpellTemplate.MotionType.AOE:
  356. mLocalPos.SetX(mPos.X);
  357. mLocalPos.SetY(mPos.Y);
  358. break;
  359. case SpellTemplate.MotionType.AOE_Binding:
  360. case SpellTemplate.MotionType.Binding:
  361. if (Sender != null)
  362. {
  363. updateBinding(Sender.X, Sender.Y, Sender.Direction, intervalMS);
  364. }
  365. else
  366. {
  367. adjustPos(speed_distance);
  368. }
  369. break;
  370. case SpellTemplate.MotionType.AOE_BindingTarget:
  371. case SpellTemplate.MotionType.BindingTarget:
  372. if (Target != null)
  373. {
  374. updateBinding(Target.X, Target.Y, Target.Direction, intervalMS);
  375. }
  376. else
  377. {
  378. adjustPos(speed_distance);
  379. }
  380. break;
  381. case SpellTemplate.MotionType.Missile:
  382. case SpellTemplate.MotionType.MissileAttackRoute:
  383. if (Target != null)
  384. {
  385. if (Info.RotateSpeedSEC == 0)
  386. {
  387. PreFaceTo(Target.X, Target.Y);
  388. }
  389. PreFlyTo(Target.X, Target.Y, mSpeed, intervalMS);
  390. }
  391. else
  392. {
  393. MathVector.movePolar(mLocalPos, mStartDirection, speed_distance);
  394. }
  395. break;
  396. case SpellTemplate.MotionType.SeekerMissile:
  397. if (Target != null)
  398. {
  399. if (Info.SeekingTurningAngleSEC != 0)
  400. {
  401. FlyToTargetTunning(Target.X, Target.Y, mSpeed, Info.SeekingTurningAngleSEC, intervalMS);
  402. }
  403. else
  404. {
  405. PreFaceTo(Target.X, Target.Y);
  406. PreFlyTo(Target.X, Target.Y, mSpeed, intervalMS);
  407. }
  408. }
  409. else
  410. {
  411. MathVector.movePolar(mLocalPos, mStartDirection, speed_distance);
  412. }
  413. break;
  414. case SpellTemplate.MotionType.SeekerSelectTarget:
  415. break;
  416. case SpellTemplate.MotionType.Chain:
  417. if (Sender != null && Sender.IsEnable && Target != null && Target.IsActive)
  418. {
  419. mLocalPos.SetX(Sender.X);
  420. mLocalPos.SetY(Sender.Y);
  421. PreFaceTo(Target.X, Target.Y);
  422. }
  423. break;
  424. case SpellTemplate.MotionType.CurveMissile:
  425. IPosBase targetPos = Target == null ? (IPosBase)TargetPos : (IPosBase)Target;
  426. if(targetPos == null)
  427. {
  428. PreFlyTo(mStartDirection, mSpeed, intervalMS);
  429. }
  430. else if (Info.SeekingTurningAngleSEC != 0)
  431. {
  432. FlyToTargetTunning(targetPos.X, targetPos.Y, mSpeed, Info.SeekingTurningAngleSEC, intervalMS);
  433. }
  434. else
  435. {
  436. PreFaceTo(targetPos.X, targetPos.Y);
  437. PreFlyTo(targetPos.X, targetPos.Y, mSpeed, intervalMS);
  438. }
  439. break;
  440. case SpellTemplate.MotionType.Foxfire:
  441. if (Target == null)
  442. {
  443. var mLaunchData = mAddEvent.LaunchData;
  444. foxfireRoundAngle = mStartDirection + PassTimeMS * 0.001f * 3;
  445. var x = (float)(Math.Cos(foxfireRoundAngle + 0.3f) * mLaunchData.LaunchSpellRadius);
  446. var y = (float)(Math.Sin(foxfireRoundAngle + 0.3f) * mLaunchData.LaunchSpellRadius);
  447. if (Sender != null)
  448. {
  449. x = Sender.X + x;
  450. y = Sender.Y + y;
  451. }
  452. else
  453. {
  454. x = mStartPos.X + x;
  455. y = mStartPos.Y + y;
  456. }
  457. PreFlyTo(x, y, mSpeed, intervalMS);
  458. if (Info.RotateSpeedSEC == 0)
  459. {
  460. PreFaceTo(foxfireRoundAngle + (float)Math.PI * 0.25f);
  461. }
  462. //foxfireSeekWait += intervalMS;
  463. }
  464. else
  465. {
  466. if (Info.SeekingTurningAngleSEC != 0)
  467. {
  468. FlyToTargetTunning(Target.X, Target.Y, mSpeed, Info.SeekingTurningAngleSEC, intervalMS);
  469. }
  470. else
  471. {
  472. PreFaceTo(Target.X, Target.Y);
  473. PreFlyTo(Target.X, Target.Y, mSpeed, intervalMS);
  474. }
  475. }
  476. break;
  477. }
  478. if (Info.BodyShape == SpellTemplate.Shape.LineToTarget)
  479. {
  480. if (Target != null)
  481. {
  482. PreFaceTo(Target.X, Target.Y);
  483. }
  484. }
  485. else if (Info.BodyShape == SpellTemplate.Shape.LineToStart)
  486. {
  487. PreFaceTo(StartPos.X, StartPos.Y);
  488. }
  489. else if (Info.RotateSpeedSEC != 0 && Info.MType != SpellTemplate.MotionType.SeekerMissile)
  490. {
  491. this.mDirection += MoveHelper.GetDistance(intervalMS, Info.RotateSpeedSEC);
  492. }
  493. }
  494. catch (Exception e) {
  495. log.Error(e.Message + "\n" + "Info.MType = " + Info.MType + " Info.BodyShape = " + Info.BodyShape);
  496. }
  497. }
  498. private void updateZPos()
  499. {
  500. switch (Info.MType)
  501. {
  502. case SpellTemplate.MotionType.Immovability:
  503. case SpellTemplate.MotionType.SelectTarget:
  504. case SpellTemplate.MotionType.SelectLauncher:
  505. case SpellTemplate.MotionType.AOE:
  506. updateFloatingZ(mStartHeight);
  507. break;
  508. case SpellTemplate.MotionType.Straight:
  509. case SpellTemplate.MotionType.Boomerang1:
  510. case SpellTemplate.MotionType.Boomerang2:
  511. case SpellTemplate.MotionType.StraightAndStop:
  512. updateFloatingZ(mStartHeight);
  513. break;
  514. case SpellTemplate.MotionType.AOE_Binding:
  515. case SpellTemplate.MotionType.Binding:
  516. if (Sender != null)
  517. {
  518. this.mLocal_Z = Sender.Z;
  519. }
  520. break;
  521. case SpellTemplate.MotionType.AOE_BindingTarget:
  522. case SpellTemplate.MotionType.BindingTarget:
  523. if (Target != null)
  524. {
  525. this.mLocal_Z = Target.Z;
  526. }
  527. break;
  528. case SpellTemplate.MotionType.Cannon:
  529. if (TargetPos != null)
  530. {
  531. updateTargetZ(TargetPos, 0);
  532. }
  533. break;
  534. case SpellTemplate.MotionType.Missile:
  535. case SpellTemplate.MotionType.SeekerMissile:
  536. case SpellTemplate.MotionType.MissileAttackRoute:
  537. if (Target != null)
  538. {
  539. updateTargetZ(new TVector2(Target.X, Target.Y), Target.Z + Target.Info.BodyHeight * 0.6f);
  540. }
  541. break;
  542. case SpellTemplate.MotionType.CurveMissile:
  543. if (Target != null)
  544. {
  545. updata3DParabola(new TVector2(Target.X, Target.Y));
  546. }
  547. break;
  548. }
  549. }
  550. private void updata3DParabola(IVector2 targetPos)
  551. {
  552. TVector2 nowPos = new TVector2(mLocalPos.X, mLocalPos.Y);
  553. TVector2 vcStart = new TVector2(mStartPos.X, mStartPos.Y);
  554. TVector2 vcEnd = new TVector2(targetPos.X, targetPos.Y);
  555. TVector2 v1 = nowPos - vcStart;
  556. TVector2 v2 = vcEnd - vcStart;
  557. float a = (float)Math.Atan2(v1.Y, v1.X);
  558. float b = (float)Math.Atan2(v2.Y, v2.X);
  559. if (float.Equals(a, b) || float.Equals(Math.PI, Math.Abs(a - b)))
  560. {
  561. mLocal_Z = Target.Z;
  562. }
  563. else
  564. {
  565. float dis = nowPos.DistanceTo(vcStart) * (float)Math.Abs(Math.Sin(a - b));
  566. mLocal_Z = this.mStartHeight + dis *1.6f* (float)Math.Sin(Math.PI / 6 * mCurveMissileIndex);
  567. //ClientLog.LogWarning(">z:{0}, index:{1}, ({2},{3})->({4},{5})->({6},{7})", mLocal_Z, mCurveMissileIndex, mStartPos.X, mStartPos.Y, TargetPos.X, targetPos.Y, nowPos.X, nowPos.Y);
  568. }
  569. }
  570. /// <summary>
  571. /// 计算有固定目标Z坐标
  572. /// </summary>
  573. /// <param name="targetPos"></param>
  574. /// <param name="targetZ"></param>
  575. private void updateTargetZ(IVector2 targetPos, float targetZ)
  576. {
  577. float fdis = MathVector.getDistance(mStartPos, targetPos);
  578. float odis = MathVector.getDistance(mStartPos, mLocalPos);
  579. float pct = CMath.getInRange((fdis == 0 ? 0 : (odis / fdis)), 0, 1);//生命周期百分比//
  580. float dz = CMath.getMiddleValue(pct, mStartHeight, targetZ);//和目标高度差//
  581. float ph = 0;//抛物线相对高度//
  582. if (Info.ParabolaHeight != 0)
  583. {
  584. //计算抛物线//
  585. ph = (float)Math.Sin(pct * CMath.PI_F) * Info.ParabolaHeight;
  586. }
  587. this.mLocal_Z = dz + ph;
  588. }
  589. private void updateFloatingZ(float targetZ)
  590. {
  591. float pct = (float)mPassTimeMS / (float)Info.LifeTimeMS;//生命周期百分比//
  592. float dz = CMath.getMiddleValue(pct, mStartHeight, targetZ);//和目标高度差//
  593. float ph = 0;//抛物线相对高度//
  594. if (Info.ParabolaHeight != 0)
  595. {
  596. //计算抛物线//
  597. ph = (float)Math.Sin(pct * CMath.PI_F) * Info.ParabolaHeight;
  598. }
  599. this.mLocal_Z = dz + ph;
  600. }
  601. private void updateBinding(float x, float y, float direction, int intervalMS)
  602. {
  603. if (Info.IsBindingDirection)
  604. {
  605. mDirection = direction;
  606. }
  607. if (Info.IsBindingOrbit)
  608. {
  609. float dadd = Info.OrbitDistance;
  610. float ox = (float)Math.Cos(Direction) * dadd;
  611. float oy = (float)Math.Sin(Direction) * dadd;
  612. mLocalPos.SetX(x + ox);
  613. mLocalPos.SetY(y + oy);
  614. }
  615. else
  616. {
  617. mLocalPos.SetX(x);
  618. mLocalPos.SetY(y);
  619. }
  620. }
  621. #endregion
  622. //---------------------------------------------------------------------------------------------------
  623. #region _UpdateShape_
  624. private void updateAOE(int intervalMS)
  625. {
  626. switch (Info.BodyShape)
  627. {
  628. case SpellTemplate.Shape.LineToTarget:
  629. case SpellTemplate.Shape.LineToStart:
  630. case SpellTemplate.Shape.Strip:
  631. case SpellTemplate.Shape.StripRay:
  632. case SpellTemplate.Shape.StripRayTouchEnd:
  633. case SpellTemplate.Shape.RectStrip:
  634. case SpellTemplate.Shape.RectStripRay:
  635. updateAoeMotion(intervalMS, Info.Distance, ref mDistanceLimit);
  636. mDisplayDistance = mDistanceLimit;
  637. break;
  638. default:
  639. updateAoeMotion(intervalMS, Info.BodySize, ref mSizeLimit);
  640. mDisplaySize = mSizeLimit;
  641. break;
  642. }
  643. }
  644. private void updateAoeMotion(int intervalMS, float base_value, ref float value)
  645. {
  646. switch (Info.AOEMType)
  647. {
  648. case SpellTemplate.AoeMotionType.Sine:
  649. value = (float)Math.Sin(CMath.PI_F * mPassTimeMS / (float)Info.LifeTimeMS) * base_value;
  650. break;
  651. case SpellTemplate.AoeMotionType.Linear:
  652. default:
  653. value += MoveHelper.GetDistance(intervalMS, mSpeed);
  654. break;
  655. }
  656. }
  657. private void updateRayTouchEnd()
  658. {
  659. if (Launcher != null)
  660. {
  661. float d_width = Info.RectWide / 2f;
  662. Vector2 p1 = new Vector2(X, Y);
  663. MathVector.movePolar(p1, this.Direction, this.mDistanceLimit);
  664. using (var list = ListObjectPool<ZoneUnit>.AllocAutoRelease())
  665. {
  666. Parent.ForEachNearObjectsRect(this.X, this.Y, p1.X, p1.Y, (ZoneObject u, ref bool cancel) =>
  667. {
  668. if ((u is ZoneUnit))
  669. {
  670. ZoneUnit zu = u as ZoneUnit;
  671. if (Parent.IsAttackable(Launcher, zu, Info.ExpectTarget))
  672. {
  673. if ((CMath.intersectLineRound(this.X, this.Y, p1.X, p1.Y, zu.X, zu.Y, d_width + zu.BodyHitSize)))
  674. {
  675. list.Add(u as ZoneUnit);
  676. }
  677. }
  678. }
  679. });
  680. if (list.Count > 0)
  681. {
  682. list.Sort(new ObjectBodySorterNearest<ZoneUnit>(this.X, this.Y, 0));
  683. this.mDisplayDistance = CMath.getDistance(this.X, this.Y, list[0].X, list[0].Y);
  684. this.mDisplayDistance = Math.Min(mDisplayDistance, this.mDistanceLimit);
  685. }
  686. else
  687. {
  688. this.mDisplayDistance = this.mDistanceLimit;
  689. }
  690. }
  691. }
  692. }
  693. private void updateLineToTarget()
  694. {
  695. if (Info.BodyShape == SpellTemplate.Shape.LineToTarget)
  696. {
  697. if (Target != null)
  698. {
  699. this.mDisplayDistance = CMath.getDistance(this.X, this.Y, Target.X, Target.Y);
  700. this.mDisplayDistance = Math.Min(mDisplayDistance, this.mDistanceLimit);
  701. PreFaceTo(Target.X, Target.Y);
  702. }
  703. else
  704. {
  705. this.mDisplayDistance = 0;
  706. }
  707. }
  708. else if (Info.BodyShape == SpellTemplate.Shape.LineToStart)
  709. {
  710. this.mDisplayDistance = CMath.getDistance(this.X, this.Y, mStartPos.X, mStartPos.Y);
  711. this.mDisplayDistance = Math.Min(mDisplayDistance, this.mDistanceLimit);
  712. PreFaceTo(mStartPos.X, mStartPos.Y);
  713. }
  714. else
  715. {
  716. this.mDisplayDistance = 0;
  717. }
  718. }
  719. #endregion
  720. //---------------------------------------------------------------------------------------------------
  721. #region _UpdateKeyFrames_
  722. /// <summary>
  723. /// 更新范围检测以及关键帧
  724. /// </summary>
  725. private void updateKeyFrames()
  726. {
  727. switch (Info.MType)
  728. {
  729. case SpellTemplate.MotionType.Missile:
  730. case SpellTemplate.MotionType.SeekerMissile:
  731. case SpellTemplate.MotionType.Cannon:
  732. case SpellTemplate.MotionType.Chain:
  733. case SpellTemplate.MotionType.CurveMissile:
  734. break;
  735. default:
  736. if (Info.BodyShape == SpellTemplate.Shape.LineToTarget || Info.BodyShape == SpellTemplate.Shape.LineToStart)
  737. {
  738. }
  739. else
  740. {
  741. updateKeyFramesRanged();
  742. }
  743. break;
  744. }
  745. }
  746. private void updateKeyFramesRanged()
  747. {
  748. using (var kfs = ListObjectPool<SpellTemplate.KeyFrame>.AllocAutoRelease())
  749. {
  750. // int kfs_count = mKeyFrames.PopKeyFrames(PassTimeMS, kfs);
  751. bool is_interval_test = mHitIntervalTicker.Update(Parent.CurrentIntervalMS);
  752. //if (kfs_count > 0)
  753. //{
  754. // for (int i = 0; i < kfs.Count; i++)
  755. // {
  756. // if (kfs[i].Effect != null)
  757. // {
  758. // Parent.PreQueueEvent(new UnitEffectEvent(ObjectID, kfs[i].Effect));
  759. // }
  760. // }
  761. //}
  762. if (Info.HitOnExplosion)
  763. {
  764. }
  765. else if (Info.HitIntervalMS == 0)
  766. {
  767. }
  768. else if (is_interval_test)
  769. {
  770. if (Info.HitIntervalKeyFrame != null && Info.HitIntervalKeyFrame.Effect != null)
  771. {
  772. Parent.PreQueueEvent(new UnitEffectEvent(ObjectID, Info.HitIntervalKeyFrame.Effect));
  773. }
  774. }
  775. }
  776. }
  777. #endregion
  778. //---------------------------------------------------------------------------------------------------
  779. private void adjustPos(float min_distance)
  780. {
  781. float fdistance = MathVector.getDistance(mLocalPos, mPos);
  782. if (fdistance < min_distance)
  783. {
  784. MathVector.moveTo(mLocalPos, mPos.X, mPos.Y, min_distance);
  785. }
  786. else
  787. {
  788. MathVector.moveTo(mLocalPos, mPos.X, mPos.Y, fdistance / 2f);
  789. }
  790. }
  791. private void PreFaceTo(float angle)
  792. {
  793. this.mDirection = angle;
  794. }
  795. private void PreFaceTo(float x, float y)
  796. {
  797. if (this.X == x && this.Y == y)
  798. {
  799. return;
  800. }
  801. this.mDirection = (float)(Math.Atan2(y - this.Y, x - this.X));
  802. }
  803. private void PreTurnTo(float add)
  804. {
  805. this.mDirection += add;
  806. }
  807. private void PreFlyTo(float x, float y, float speedSEC, int intervalMS)
  808. {
  809. float distance = MoveHelper.GetDistance(intervalMS, speedSEC);
  810. MathVector.moveTo(mLocalPos, x, y, distance);
  811. }
  812. private void PreFlyTo(float direction, float speedSEC, int intervalMS)
  813. {
  814. float distance = MoveHelper.GetDistance(intervalMS, speedSEC);
  815. float dx = (float)(Math.Cos(direction) * distance);
  816. float dy = (float)(Math.Sin(direction) * distance);
  817. mLocalPos.AddX(dx);
  818. mLocalPos.AddY(dy);
  819. }
  820. public void FlyToTargetTunning(float x, float y, float speedSEC, float tunningSpeedSEC, int intervalMS)
  821. {
  822. MoveHelper.MoveToTargetTunning(ref mLocalPos, ref mDirection, x, y, speedSEC, tunningSpeedSEC, intervalMS);
  823. }
  824. }
  825. }