InstanceZone.cs 109 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881
  1. using CommonAI.Data;
  2. using CommonAI.RTS;
  3. using CommonAI.Zone.EventTrigger;
  4. using CommonAI.Zone.Formula;
  5. using CommonAI.Zone.Helper;
  6. using CommonAI.ZoneClient;
  7. using CommonAI.ZoneEditor;
  8. using CommonAI.ZoneServer.JSGModule;
  9. using CommonLang;
  10. using CommonLang.Concurrent;
  11. using CommonLang.IO;
  12. using CommonLang.Log;
  13. using CommonLang.Property;
  14. using CommonLang.Vector;
  15. using System;
  16. using System.Collections.Generic;
  17. using System.Diagnostics;
  18. using static CommonAI.Zone.SpellTemplate;
  19. using static CommonAI.Zone.UnitInfo;
  20. namespace CommonAI.Zone.Instance
  21. {
  22. /// <summary>
  23. /// 服务端场景
  24. /// </summary>
  25. public partial class InstanceZone : GameEntity
  26. {
  27. private static AtomicInteger s_alloc_zone_count = new AtomicInteger(0);
  28. private static AtomicInteger s_active_zone_count = new AtomicInteger(0);
  29. /// <summary>
  30. /// 分配实例数量
  31. /// </summary>
  32. public static int AllocZoneCount { get { return s_alloc_zone_count.Value; } }
  33. /// <summary>
  34. /// 未释放实例数量
  35. /// </summary>
  36. public static int ActiveZoneCount { get { return s_active_zone_count.Value; } }
  37. //------------------------------------------------------------------------
  38. // 基础数据
  39. private InstanceZoneListener mListener;
  40. private TemplateManager mTemplates;
  41. private IFormula mFormula = TemplateManager.Factory.Formula;
  42. private IQuestAdapter mQuestAdapter;
  43. private SyncMessageQueue<Action> mSyncActionQueue = new SyncMessageQueue<Action>();
  44. private Queue<Event> mSendingEvents = new Queue<Event>();
  45. private InstanceZoneObjectMap mObjects;
  46. public TemplateManager Templates { get { return mTemplates; } }
  47. public IQuestAdapter QuestAdapter { get { return mQuestAdapter; } }
  48. public int UpdateIntervalMS { get { return mLastInterval; } }
  49. private readonly int mMaxUnitCount;
  50. private int mLastInterval = 0;
  51. private ulong mTimer = 0;
  52. private long mCurPassTimeMS = 0;
  53. private long mQueryPassTimeMS = 0;
  54. private int mQueryPassTimeSEC = 0;
  55. private bool mHalfSync = false;
  56. readonly private Random random;
  57. readonly private Logger log;
  58. public string UUID { get; set; }
  59. //------------------------------------------------------------------------
  60. readonly private ZoneInfo m_TerrainSrc;
  61. readonly private SpaceDivision mSpaceDiv;
  62. public ZoneInfo TerrainSrc { get { return m_TerrainSrc; } }
  63. public ZoneInfo Terrain { get { return path_terrain_data.Data; } }
  64. public int SpaceDivSize { get; private set; }
  65. [Desc("单位当前帧位移的最小距离")]
  66. public float MinStep { get; private set; }
  67. [Desc("最大单位数量")]
  68. public int MaxUnitCount { get { return mMaxUnitCount; } }
  69. [Desc("场景中是否存在Area")]
  70. public bool HasArea { get { return mHasArea; } }
  71. //山大王id
  72. protected int mKingID;
  73. //绑定服务器
  74. protected string mBindGameSrvId;
  75. //------------------------------------------------------------------------
  76. /// <summary>
  77. ///
  78. /// </summary>
  79. /// <param name="templates"></param>
  80. /// <param name="listener">消息接收者</param>
  81. /// <param name="data">场景数据</param>
  82. /// <param name="spaceDivSize">空间分割参数</param>
  83. /// <param name="maxUnitCount">最大单位数</param>
  84. /// <param name="randomSeed">随机种子</param>
  85. internal InstanceZone(TemplateManager templates, InstanceZoneListener listener, ZoneEditor.SceneData data, GSCreateAreaData gsData,
  86. int spaceDivSize, int maxUnitCount, int randomSeed)
  87. {
  88. InstanceZone.s_alloc_zone_count++;
  89. InstanceZone.s_active_zone_count++;
  90. var info = data.ZoneData;
  91. this.log = LoggerFactory.GetLogger(string.Format("InstanceZone({0})", info.TemplateID));
  92. this.random = TemplateManager.Factory.CreateRandom(randomSeed);// new Random(randomSeed);
  93. this.mTemplates = templates;
  94. this.IsSyncZ = false;
  95. this.MinStep = MoveHelper.GetDistance(1000 / templates.CFG.SYSTEM_FPS, templates.CFG.OBJECT_MOVE_TO_MIN_STEP_SEC);
  96. if (spaceDivSize < 1)
  97. {
  98. throw new Exception("SpaceDivSize must large than map 1 !");
  99. }
  100. this.mMaxUnitCount = maxUnitCount;
  101. this.mListener = listener;
  102. this.m_TerrainSrc = info;
  103. this.SpaceDivSize = spaceDivSize;
  104. this.mSpaceDiv = new SpaceDivision(
  105. m_TerrainSrc.TotalWidth,
  106. m_TerrainSrc.TotalHeight,
  107. spaceDivSize * m_TerrainSrc.GridCellW,
  108. spaceDivSize * m_TerrainSrc.GridCellH);
  109. this.mObjects = new InstanceZoneObjectMap();
  110. // this.path_terrain_data = new InstanceZoneManhattanMap(templates, info.Clone() as ZoneInfo);
  111. // this.path_finder = new AstarManhattan(path_terrain_data, true, spaceDivSize);
  112. // this.path_terrain_area_gen = new ManhattanMapAreaGenerator(path_terrain_data.Data);
  113. this.InitTerrain(data, spaceDivSize, out this.path_terrain_data, out this.path_finder, out this.path_terrain_area_gen);
  114. this.mQuestAdapter = TemplateManager.Factory.CreateQuestAdapter(this);
  115. this.baseInit(data, gsData);
  116. }
  117. protected virtual void baseInit(ZoneEditor.SceneData data, GSCreateAreaData gsData)
  118. {
  119. }
  120. // -----------------------------------------------------------------------------------
  121. ~InstanceZone()
  122. {
  123. InstanceZone.s_alloc_zone_count--;
  124. }
  125. protected override void Disposing()
  126. {
  127. base.Disposing();
  128. this.ClearEvents();
  129. foreach (var obj in mObjects.Objects)
  130. {
  131. obj.Dispose();
  132. }
  133. this.mObjects.Dispose();
  134. this.mObjects = null;
  135. foreach (var flg in mFlags.Values)
  136. {
  137. flg.Dispose();
  138. }
  139. this.mFlags.Clear();
  140. this.DisposeTerrain();
  141. this.mSpaceDiv.Dispose();
  142. this.mQuestAdapter.Dispose();
  143. this.mQuestAdapter = null;
  144. this.mListener = null;
  145. this.mTemplates = null;
  146. this.mFormula = null;
  147. this.mSyncActionQueue = null;
  148. this.mSendingEvents = null;
  149. this.mTasks.Clear();
  150. this.mTasks = null;
  151. this.mTimeTasks.Dispose();
  152. this.mTimeTasks = null;
  153. this.EnvironmentVarMap.Clear();
  154. this.mFlags.Clear();
  155. this.m_UnitsPos.Clear();
  156. this.m_UnitsStates.Clear();
  157. InstanceZone.s_active_zone_count--;
  158. }
  159. // -----------------------------------------------------------------------------------
  160. protected Logger Log { get { return log; } }
  161. public int TotalWidth { get { return m_TerrainSrc.TotalWidth; } }
  162. public int TotalHeight { get { return m_TerrainSrc.TotalHeight; } }
  163. public int GridCellW { get { return m_TerrainSrc.GridCellW; } }
  164. public int GridCellH { get { return m_TerrainSrc.GridCellH; } }
  165. public int XCount { get { return m_TerrainSrc.XCount; } }
  166. public int YCount { get { return m_TerrainSrc.YCount; } }
  167. public ulong Tick { get { return mTimer; } }
  168. /// <summary>
  169. /// 是否发 SyncPosEvent 包
  170. /// </summary>
  171. public bool SyncPos
  172. {
  173. get { return sync_pos_list.Enable; }
  174. set { sync_pos_list.Enable = value; }
  175. }
  176. /// <summary>
  177. /// 是否为低速率网络同步(将优化为半字通信)
  178. /// </summary>
  179. public bool IsHalfSync
  180. {
  181. get { return mHalfSync; }
  182. set
  183. {
  184. if (value && TotalWidth <= 255 && TotalHeight <= 255)
  185. {
  186. mHalfSync = value;
  187. }
  188. else
  189. {
  190. mHalfSync = false;
  191. }
  192. }
  193. }
  194. /// <summary>
  195. /// 同步包是否包含Z
  196. /// </summary>
  197. public bool IsSyncZ
  198. {
  199. get;
  200. set;
  201. }
  202. public long PassTimeMS { get { return mQueryPassTimeMS; } }
  203. public int PassTimeSEC { get { return mQueryPassTimeSEC; } }
  204. public Random RandomN { get { return random; } }
  205. // public void Trace(string text)
  206. // {
  207. // log.Info(text);
  208. // }
  209. // -----------------------------------------------------------------------------------
  210. //------------------------------------------------------------------------------------
  211. #region TIMING_AND_TASK
  212. private SyncMessageQueue<Action<InstanceZone>> mTasks = new SyncMessageQueue<Action<InstanceZone>>();
  213. private TimeTaskQueue mTimeTasks = new TimeTaskQueue();
  214. private void doTask(Action<InstanceZone> task)
  215. {
  216. task(this);
  217. }
  218. /// <summary>
  219. /// 【线程安全】向主线程排一个任务
  220. /// </summary>
  221. /// <param name="task"></param>
  222. public void queueTask(Action<InstanceZone> task)
  223. {
  224. mTasks.Enqueue(task);
  225. }
  226. public string GetInfo()
  227. {
  228. if(this.mObjects == null)
  229. {
  230. return "对象:-1";
  231. }
  232. return "对象:" + AllObjectsCount + ", 单位:" + AllUnitsCount + ", 法术:" + AllSpellsCount + ", 道具:" + AllItemsCount + ", 玩家:" + AllPlayersCount;
  233. }
  234. /// <summary>
  235. /// 【线程安全】增加时间任务
  236. /// </summary>
  237. /// <param name="intervalMS"></param>
  238. /// <param name="delayMS"></param>
  239. /// <param name="repeat"></param>
  240. /// <param name="handler"></param>
  241. public TimeTaskMS AddTimeTask(int intervalMS, int delayMS, int repeat, TickHandler handler)
  242. {
  243. return mTimeTasks.AddTimeTask(intervalMS, delayMS, repeat, handler);
  244. }
  245. /// <summary>
  246. /// 【线程安全】增加延时回调方法
  247. /// </summary>
  248. /// <param name="delayMS"></param>
  249. /// <param name="handler"></param>
  250. public TimeTaskMS AddTimeDelayMS(int delayMS, TickHandler handler)
  251. {
  252. return mTimeTasks.AddTimeDelayMS(delayMS, handler);
  253. }
  254. /// <summary>
  255. /// 【线程安全】增加定时回调方法
  256. /// </summary>
  257. /// <param name="intervalMS"></param>
  258. /// <param name="handler"></param>
  259. public TimeTaskMS AddTimePeriodicMS(int intervalMS, TickHandler handler)
  260. {
  261. if(intervalMS <= 0)
  262. {
  263. log.Error("增加定时任务异常:" + intervalMS);
  264. return null;
  265. }
  266. return mTimeTasks.AddTimePeriodicMS(intervalMS, handler);
  267. }
  268. #endregion
  269. //-----------------------------------------------------------------------------------
  270. /// <summary>
  271. /// 【线程安全】向当前场景输入指令
  272. /// </summary>
  273. /// <param name="act"></param>
  274. public void pushAction(Action act)
  275. {
  276. mSyncActionQueue.Enqueue(act);
  277. }
  278. protected internal void queueEventInternal(Event evt)
  279. {
  280. mSendingEvents.Enqueue(evt);
  281. }
  282. /// <summary>
  283. /// 【内部调用】输出消息
  284. /// </summary>
  285. public void queueEvent(ZoneEvent evt, GameEntity sender = null)
  286. {
  287. if (sender != null) { evt.sender = sender; }
  288. this.queueEventInternal(evt);
  289. }
  290. /// <summary>
  291. /// 【内部调用】输出消息
  292. /// </summary>
  293. /// <param name="obj"></param>
  294. /// <param name="evt"></param>
  295. public void queueObjectEvent(InstanceZoneObject obj, ObjectEvent evt, bool force = false)
  296. {
  297. if(mSendingEvents == null)
  298. {
  299. if(mObjects == null)
  300. {
  301. log.Warn("queueObjectEvent exception1: " + this.GetSceneID() + ", mObjects null, " + this.UUID + ", " + evt.MessageID);
  302. }
  303. else
  304. {
  305. log.Warn("queueObjectEvent exception2: " + this.GetSceneID() + ", Players: " + this.AllPlayersCount + ", Items: "
  306. + this.AllItemsCount + ", Units: " + this.AllUnitsCount + ", " + this.UUID + ", " + evt.MessageID);
  307. }
  308. return;
  309. }
  310. if (obj.ID == 0)
  311. return;
  312. if (!force && !obj.IsInZone)
  313. return;
  314. obj.onSendingEvent(ref evt);
  315. if (evt != null)
  316. {
  317. evt.object_id = obj.ID;
  318. evt.sender = obj;
  319. mSendingEvents.Enqueue(evt);
  320. }
  321. }
  322. /// <summary>
  323. /// 立即发送指令
  324. /// </summary>
  325. /// <param name="obj"></param>
  326. /// <param name="req"></param>
  327. /// <param name="rsp"></param>
  328. public void sendActorResponse(InstanceZoneObject obj, ActorRequest req, ActorResponse rsp)
  329. {
  330. if (obj.ID == 0)
  331. return;
  332. if (!obj.IsInZone)
  333. return;
  334. rsp.MessageID = req.MessageID;
  335. rsp.object_id = obj.ID;
  336. rsp.sender = obj;
  337. mSendingEvents.Enqueue(rsp);
  338. }
  339. public void sendMessageBox(string msg)
  340. {
  341. queueEventInternal(new TestMessageBox(msg));
  342. }
  343. public virtual int GetSceneID() { return 0; }
  344. //-----------------------------------------------------------------------------------
  345. public void RecvMessageFromGameServer(ZoneServer.SendMessageR2B msg)
  346. {
  347. LastRecvMessageR2B = msg;
  348. if (mOnRecvFromGS != null)
  349. {
  350. mOnRecvFromGS.Invoke(this, msg);
  351. }
  352. }
  353. public void SendMessageToGameServer(string msg)
  354. {
  355. ZoneServer.SendMessageB2R b2r = new ZoneServer.SendMessageB2R();
  356. b2r.Message = msg;
  357. LastSentMessageB2R = b2r;
  358. if (mOnSendToGS != null)
  359. {
  360. mOnSendToGS.Invoke(this, b2r);
  361. }
  362. }
  363. public void SendEventToGameServer(IExternalizable evt)
  364. {
  365. ZoneServer.SendEventB2R b2r = new ZoneServer.SendEventB2R();
  366. b2r.evt = evt;
  367. if (mOnSendMessageB2REvent != null)
  368. {
  369. mOnSendMessageB2REvent.Invoke(this, b2r);
  370. }
  371. }
  372. public bool CheckAutoDropItem()
  373. {
  374. return this.mListener.CheckDropItem();
  375. }
  376. //-----------------------------------------------------------------------------------
  377. public virtual void Update(int intervalMS, bool slowRefresh)
  378. {
  379. beginEventsRecord();
  380. this.mLastInterval = intervalMS;
  381. this.MinStep = MoveHelper.GetDistance(intervalMS, Templates.CFG.OBJECT_MOVE_TO_MIN_STEP_SEC);
  382. if (mTimer == 0)
  383. {
  384. mCurPassTimeMS = 0;
  385. mQueryPassTimeMS = 0;
  386. mQueryPassTimeSEC = 0;
  387. foreach (InstanceFlag f in mFlags.Values)
  388. {
  389. f.OnStart();
  390. }
  391. if (mOnInit != null)
  392. mOnInit.Invoke(this);
  393. }
  394. mTasks.ProcessMessages(doTask);
  395. mSyncActionQueue.ProcessMessages(updateAction);
  396. mObjects.Refresh();
  397. var objetes = mObjects.Objects;
  398. {
  399. // clean space div state
  400. foreach (InstanceZoneObject u in objetes)
  401. {
  402. u.onUpdate(this, slowRefresh);
  403. }
  404. mSpaceDiv.ClearSpaceNearChanges();
  405. bool dirty = false;
  406. foreach (InstanceZoneObject u in objetes)
  407. {
  408. if (u.Enable)
  409. {
  410. dirty = u.updatePos(this);
  411. u.mCurCellNode.MarkPosDirty(dirty);
  412. if (dirty && u.ClientVisible && u.SyncPos)
  413. {
  414. if (mOnObjectPosChanged != null)
  415. {
  416. mOnObjectPosChanged.Invoke(this, u);
  417. }
  418. sync_pos_list.Add(u);
  419. }
  420. }
  421. }
  422. }
  423. foreach (InstanceFlag f in mFlags.Values)
  424. {
  425. f.update();
  426. }
  427. if (mOnUpdate != null)
  428. {
  429. mOnUpdate.Invoke(this);
  430. }
  431. updateEvents();
  432. mTimeTasks.Update(intervalMS);
  433. mCurPassTimeMS += intervalMS;
  434. mQueryPassTimeMS = mCurPassTimeMS;
  435. mQueryPassTimeSEC = (int)(mCurPassTimeMS / 1000);
  436. mTimer++;
  437. }
  438. private void updateAction(Action act)
  439. {
  440. if (act is SystemMessage)
  441. {
  442. processSystemMessage(act as SystemMessage);
  443. }
  444. else if (act is ObjectAction)
  445. {
  446. ObjectAction oa = (ObjectAction)act;
  447. InstanceUnit unit = act.sender as InstanceUnit;
  448. if (unit == null)
  449. {
  450. unit = mObjects.GetObject<InstanceUnit>(oa.object_id);
  451. }
  452. if (unit != null)
  453. {
  454. unit.doAction(oa);
  455. if (mOnHandleObjectAction != null)
  456. {
  457. mOnHandleObjectAction.Invoke(unit, oa);
  458. }
  459. mFormula.OnUnitHandleNetMessage(unit, oa);
  460. }
  461. else
  462. {
  463. log.Info("Drop message : " + oa);
  464. }
  465. }
  466. else
  467. {
  468. if (mOnHandleAction != null)
  469. {
  470. mOnHandleAction.Invoke(this, act);
  471. }
  472. mFormula.OnZoneHandleNetMessage(this, act);
  473. }
  474. }
  475. private void updateEvents()
  476. {
  477. if (sync_pos_list.Enable)
  478. {
  479. queueEvent(sync_pos_list.AsEvent(this));
  480. }
  481. sync_pos_list.Clear();
  482. while (mSendingEvents.Count > 0)
  483. {
  484. Event evt = mSendingEvents.Dequeue();
  485. //log.Info("---->onEvent:" + evt.ToString());
  486. mListener.onEventHandler(evt);
  487. if (mOnPostEvent != null)
  488. {
  489. mOnPostEvent.Invoke(this, evt);
  490. }
  491. if (evt is GameOverEvent && mOnGameOver != null)
  492. {
  493. mOnGameOver.Invoke(this, evt as GameOverEvent);
  494. }
  495. }
  496. }
  497. virtual protected void processSystemMessage(SystemMessage msg)
  498. {
  499. if (msg is Ping)
  500. {
  501. queueEventInternal(new Pong(msg as Ping));
  502. }
  503. }
  504. //-------------------------------------------------------------------------------------------
  505. #region OBJECTS
  506. private uint mObjectIDIndexer = 0;
  507. internal uint genObjectID()
  508. {
  509. mObjectIDIndexer++;
  510. return mObjectIDIndexer;
  511. }
  512. // 获取一个单位
  513. public T getObject<T>(uint obj_id) where T : InstanceZoneObject
  514. {
  515. if (obj_id == 0) return null;
  516. T go = mObjects.GetObject<T>(obj_id);
  517. if (go != null)
  518. {
  519. return go;
  520. }
  521. return null;
  522. }
  523. public InstanceUnit getUnit(uint obj_id)
  524. {
  525. if (obj_id == 0) return null;
  526. return mObjects.GetObject<InstanceUnit>(obj_id);
  527. }
  528. public InstanceUnit getUnitByTemplateID(int templateId)
  529. {
  530. if (templateId == 0) return null;
  531. foreach (InstanceUnit u in mObjects.Units)
  532. {
  533. if (u.Info.TemplateID == templateId)
  534. {
  535. return u;
  536. }
  537. }
  538. return null;
  539. }
  540. public InstanceUnit getUnitByName(string name)
  541. {
  542. if (string.IsNullOrEmpty(name))
  543. {
  544. return null;
  545. }
  546. foreach (InstanceUnit u in mObjects.Units)
  547. {
  548. if (name.Equals(u.Name))
  549. {
  550. return u;
  551. }
  552. }
  553. return null;
  554. }
  555. public InstancePlayer getPlayerByUUID(string playerUUID)
  556. {
  557. if (string.IsNullOrEmpty(playerUUID))
  558. {
  559. return null;
  560. }
  561. return mObjects.GetPlayer(playerUUID);
  562. }
  563. public InstanceItem getItemByName(string name)
  564. {
  565. if (string.IsNullOrEmpty(name))
  566. {
  567. return null;
  568. }
  569. foreach (InstanceItem u in mObjects.Items)
  570. {
  571. if (name.Equals(u.Name))
  572. {
  573. return u;
  574. }
  575. }
  576. return null;
  577. }
  578. public InstanceUnit getUnitByID(int UnitID)
  579. {
  580. foreach (InstanceUnit obj in mObjects.Units)
  581. {
  582. if (obj.ID == UnitID)
  583. {
  584. return obj;
  585. }
  586. }
  587. return null;
  588. }
  589. public IEnumerable<InstancePlayer> AllPlayers { get { return mObjects.Players; } }
  590. public int AllPlayersCount { get { return mObjects.PlayersCount; } }
  591. public IEnumerable<InstanceUnit> AllUnits { get { return mObjects.Units; } }
  592. public int AllUnitsCount { get { return mObjects.UnitsCount; } }
  593. public IEnumerable<InstanceSpell> AllSpells { get { return mObjects.Spells; } }
  594. public int AllSpellsCount { get { return mObjects.SpellsCount; } }
  595. public IEnumerable<InstanceItem> AllItems { get { return mObjects.Items; } }
  596. public int AllItemsCount { get { return mObjects.ItemsCount; } }
  597. public IEnumerable<InstanceZoneObject> AllObjects { get { return mObjects.Objects; } }
  598. public int AllObjectsCount { get { return mObjects.ObjectsCount; } }
  599. [Obsolete("use {@link #AllUnits} {@link #AllSpells} {@link #AllItems} for best performance!")]
  600. public IEnumerable<InstanceZoneObject> allObjs()
  601. {
  602. return mObjects.Objects;
  603. }
  604. [Obsolete("use {@link #AllUnitsCount} {@link #AllSpellsCount} {@link #AllItemsCount} for best performance!")]
  605. public int allObjsCount()
  606. {
  607. return mObjects.ObjectsCount;
  608. }
  609. [Obsolete]
  610. public List<T> selectUnits<T>(Predicate<T> select) where T : InstanceUnit
  611. {
  612. List<T> ret = new List<T>(mObjects.UnitsCount);
  613. foreach (InstanceUnit obj in mObjects.Units)
  614. {
  615. if (select(obj as T))
  616. {
  617. ret.Add(obj as T);
  618. }
  619. }
  620. return ret;
  621. }
  622. public void selectUnits<T>(Predicate<T> select, List<T> ret) where T : InstanceUnit
  623. {
  624. foreach (InstanceUnit obj in mObjects.Units)
  625. {
  626. if (select(obj as T))
  627. {
  628. ret.Add(obj as T);
  629. }
  630. }
  631. }
  632. public T selectRandomUnit<T>(Predicate<T> select) where T : InstanceUnit
  633. {
  634. T ret = null;
  635. using (var list = ListObjectPool<InstanceUnit>.AllocAutoRelease())
  636. {
  637. foreach (InstanceUnit obj in mObjects.Units)
  638. {
  639. if (obj is T && select(obj as T))
  640. {
  641. list.Add(obj as T);
  642. }
  643. }
  644. if (list.Count > 0)
  645. {
  646. ret = CUtils.GetRandomInArray<InstanceUnit>(list, random) as T;
  647. }
  648. }
  649. return ret;
  650. }
  651. public T selectUnit<T>(Predicate<T> select) where T : InstanceUnit
  652. {
  653. foreach (InstanceUnit obj in mObjects.Units)
  654. {
  655. if (select(obj as T))
  656. {
  657. return obj as T;
  658. }
  659. }
  660. return null;
  661. }
  662. //-------------------------------------------------------------------------------------------
  663. /// <summary>
  664. /// 创建一个单位实体
  665. /// </summary>
  666. virtual public InstanceZoneObject CreateUnit(UnitInfo info, string name, int force, int alliesForce, int level)
  667. {
  668. InstanceUnit unit = TemplateManager.Factory.CreateUnit(this, info, name, force, alliesForce, level);
  669. if (unit != null)
  670. {
  671. return unit;
  672. }
  673. switch (info.UType)
  674. {
  675. case UnitInfo.UnitType.TYPE_PLAYER:
  676. return new InstancePlayer(this, info, name, force, level, alliesForce);
  677. case UnitInfo.UnitType.TYPE_MANUAL:
  678. return new InstanceManual(this, info, name, force, level);
  679. case UnitInfo.UnitType.TYPE_PET:
  680. return new InstancePet(this, info, name, force, level);
  681. case UnitInfo.UnitType.TYPE_SUMMON:
  682. return new InstanceSummon(this, info, name, force, level);
  683. case UnitInfo.UnitType.TYPE_BUILDING:
  684. return new InstanceBuilding(this, info, name, force, level);
  685. case UnitInfo.UnitType.TYPE_MONSTER:
  686. return new InstanceGuard(this, info, name, force, level);
  687. case UnitInfo.UnitType.TYPE_NPC:
  688. return new InstanceGuard(this, info, name, force, level);
  689. default:
  690. return new InstanceGuard(this, info, name, force, level);
  691. }
  692. }
  693. //-------------------------------------------------------------------------------------------
  694. public InstanceUnit AddUnit(int unitTemplateID, string name, int force, int level, float x, float y, float direction, bool pointLv = false)
  695. {
  696. UnitInfo info = Templates.getUnit(unitTemplateID);
  697. if (info != null)
  698. {
  699. return AddUnit(info, name, force, level, x, y, direction, null, "", 0, pointLv);
  700. }
  701. return null;
  702. }
  703. /// <summary>
  704. /// 添加一个单位
  705. /// </summary>
  706. /// <param name="info">单位模板</param>
  707. /// <param name="name">场景中名字(Key)</param>
  708. /// <param name="force">单位阵营</param>
  709. /// <param name="level">单位等级</param>
  710. /// <param name="x">坐标</param>
  711. /// <param name="y">坐标</param>
  712. /// <param name="direction">方向</param>
  713. /// <param name="summoner">召唤者</param>
  714. /// <returns></returns>
  715. public InstanceUnit AddUnit(UnitInfo info, string name, int force, int level, float x, float y, float direction,
  716. InstanceUnit summoner = null, String clientShowName = "", int gsFlag = 0, bool pointLv = false)
  717. {
  718. AddUnitEvent add;
  719. return AddUnit(info, name, force, level, x, y, direction, out add, summoner, clientShowName, gsFlag, 0, pointLv);
  720. }
  721. /// <summary>
  722. /// 添加一个单位
  723. /// </summary>
  724. /// <param name="info">单位模板</param>
  725. /// <param name="name">场景中名字(Key)</param>
  726. /// <param name="force">单位阵营</param>
  727. /// <param name="level">单位等级</param>
  728. /// <param name="x">坐标</param>
  729. /// <param name="y">坐标</param>
  730. /// <param name="direction">方向</param>
  731. /// <param name="add">输出事件</param>
  732. /// <param name="summoner">召唤者</param>
  733. /// <returns></returns>
  734. public InstanceUnit AddUnit(UnitInfo info, string name, int force, int level, float x, float y, float direction,
  735. out AddUnitEvent add, InstanceUnit summoner = null, String clientShowName = "", int gsFlag = 0, int alliesForce = 0, bool pointLv = false)
  736. {
  737. add = null;
  738. if (mObjects.UnitsCount >= mMaxUnitCount)
  739. {
  740. log.Warn(string.Format("Zone Unit TryAdd max: {0}, {1}, 单位数量:{2}", this.TerrainSrc.ID, info.TemplateID, mObjects.UnitsCount));
  741. return null;
  742. }
  743. if (mTryAddUnit != null && !mTryAddUnit.Invoke(info))
  744. {
  745. //log.Info(string.Format("Zone Unit TryAdd max: {0}, {1}, 单位数量:{2}", this.TerrainSrc.ID, info.TemplateID, mObjects.UnitsCount));
  746. return null;
  747. }
  748. // 创建实体单位
  749. InstanceZoneObject ret = CreateUnit(info, name, force, alliesForce, level);
  750. // 存入单位列表
  751. if (ret is InstanceUnit)
  752. {
  753. InstanceUnit unit = ret as InstanceUnit;
  754. //unit.Name = name;
  755. unit.gameServerFlag = gsFlag;
  756. // 存入单位列表
  757. if (unit.tryAdd(x, y, direction))
  758. {
  759. mObjects.AddObject(unit);
  760. this.LastAddedUnit = unit;
  761. if (unit is ISummonedUnit)
  762. {
  763. ((ISummonedUnit)unit).SummonerUnit = summoner;
  764. }
  765. try
  766. {
  767. unit.onAdded(this, pointLv);
  768. if (mOnUnitAdded != null)
  769. mOnUnitAdded.Invoke(this, unit);
  770. add = new AddUnitEvent();
  771. add.sender = unit;
  772. if (unit.ClientVisible)
  773. {
  774. if (clientShowName != null && !unit.IsPlayer && clientShowName.Length > 0)
  775. {
  776. unit.SetDiaplayerName(clientShowName);
  777. }
  778. //// 阵营判断
  779. //if(info.UType == UnitType.TYPE_MONSTER && force > 1)
  780. //{
  781. // add.flag = 1;
  782. //}
  783. queueEvent(add);
  784. }
  785. }
  786. catch (Exception err)
  787. {
  788. log.Warn("AddUnit catch :" + name + ", e:" + err);
  789. add.ErrorMessage = err.Message;
  790. return null;
  791. }
  792. finally
  793. {
  794. add.Sync = unit.GenSyncUnitInfo(true);
  795. }
  796. return unit;
  797. }
  798. }
  799. return null;
  800. }
  801. public InstanceItem AddItem(ItemTemplate template, string name, float x, float y, float direction, int force, string disPlayName,
  802. out AddItemEvent add, InstanceUnit creater,int from)
  803. {
  804. add = null;
  805. if (mTryAddItem != null && !mTryAddItem.Invoke(template))
  806. {
  807. //log.Info(string.Format("Zone item TryAdd max: {0}, {1}", this.mSceneType, template.TemplateID));
  808. return null;
  809. }
  810. InstanceItem ret = TemplateManager.Factory.CreateItem(this, template, name, force, creater, disPlayName,from);
  811. ret.setPos(x, y);
  812. if (ret.tryAdd(x, y, direction))
  813. {
  814. mObjects.AddObject(ret);
  815. this.LastCreatedInstanceItem = ret;
  816. add = new AddItemEvent();
  817. add.sender = ret;
  818. if (ret.ClientVisible)
  819. {
  820. queueEvent(add);
  821. }
  822. try
  823. {
  824. ret.onAdded(this);
  825. if (mItemAdded != null)
  826. mItemAdded.Invoke(this, ret, creater);
  827. }
  828. catch (Exception err)
  829. {
  830. log.Warn("AddItem: " + template.ID + ", catch: " + err);
  831. add.ErrorMessage = err.Message;
  832. return null;
  833. }
  834. finally
  835. {
  836. add.Sync = ret.GenSyncItemInfo(true, null);
  837. }
  838. return ret;
  839. }
  840. return null;
  841. }
  842. public InstanceItem AddItem(ItemTemplate template, string name, float x, float y, float direction, int force, string disPlayName, InstanceUnit creater,int from=0)
  843. {
  844. AddItemEvent add;
  845. return AddItem(template, name, x, y, direction, force, disPlayName, out add, creater,from);
  846. }
  847. /// <summary>
  848. /// 添加一个法术或飞行道具
  849. /// </summary>
  850. /// <param name="template"></param>
  851. /// <param name="launch"></param>
  852. /// <param name="sender"></param>
  853. /// <param name="launcher">此法术的最初发起者</param>
  854. /// <param name="target_obj_id"></param>
  855. /// <param name="targetPos"></param>
  856. /// <param name="startX"></param>
  857. /// <param name="startY"></param>
  858. /// <param name="direction"></param>
  859. /// <param name="chain"></param>
  860. /// <returns></returns>
  861. public InstanceSpell AddSpell(
  862. XmdsSkillType fromSkillType,
  863. SpellTemplate template,
  864. LaunchSpell launch,
  865. InstanceZoneObject sender,
  866. InstanceUnit launcher,
  867. uint target_obj_id,
  868. Vector2 targetPos,
  869. float startX,
  870. float startY,
  871. float direction,
  872. SpellChainLevelInfo chain = null,
  873. int actionIndex = -1,
  874. int maxAffectUnit = 0,
  875. Dictionary<uint, InstanceUnit> damageList = null,
  876. int spellIndex = 0,
  877. JSGCreateSpellData createData = null)
  878. {
  879. if (template != null && sender != null)
  880. {
  881. InstanceUnit target = getUnit(target_obj_id);
  882. switch (template.MType)
  883. {
  884. // case SpellTemplate.MotionType.Missile:
  885. // if (target == null)
  886. // {
  887. // return null;
  888. // }
  889. // break;
  890. case SpellTemplate.MotionType.BindingTarget:
  891. if (target == null)
  892. {
  893. return null;
  894. }
  895. startX = target.X;
  896. startY = target.Y;
  897. break;
  898. case SpellTemplate.MotionType.SelectTarget:
  899. if (targetPos != null)
  900. {
  901. startX = targetPos.X;
  902. startY = targetPos.Y;
  903. }
  904. break;
  905. case SpellTemplate.MotionType.SeekerMissile:
  906. case SpellTemplate.MotionType.SeekerSelectTarget:
  907. {
  908. target = null;
  909. target_obj_id = 0;
  910. }
  911. break;
  912. case SpellTemplate.MotionType.Chain:
  913. if (target == null)
  914. {
  915. return null;
  916. }
  917. break;
  918. case SpellTemplate.MotionType.Cannon:
  919. if (target == null && targetPos == null)
  920. {
  921. targetPos = new Vector2(startX, startY);
  922. }
  923. break;
  924. }
  925. // 创建实体单位
  926. //InstanceSpell ret = new InstanceSpell(this, template, launch, launcher, sender, chainLevel);
  927. InstanceSpell ret = TemplateManager.Factory.CreateSpell(this, template, launch, launcher, sender, fromSkillType, damageList, spellIndex, createData);
  928. //ret.Direction = direction;
  929. ret.BindActionIndex = actionIndex;
  930. ret.MaxAffectUnit = (maxAffectUnit == 0) ? ret.Info.MaxAffectUnit : maxAffectUnit;
  931. ret.faceTo(direction);
  932. ret.setChainInfo(chain);
  933. ret.setTargetPos(targetPos);
  934. ret.setTarget(target);
  935. // 存入单位列表
  936. float xChanage, yChange;
  937. launch.GetXModify(launcher, out xChanage, out yChange);
  938. if (ret.tryAdd(startX + xChanage, startY + yChange, direction))
  939. {
  940. //System.Console.WriteLine("--AddSpell: " + ret.Info.ID + ", " + ret.ID);
  941. launcher.Virtual.DispatchSendSpellOverEvent(launch, template, ret.X, ret.Y);
  942. mObjects.AddObject(ret);
  943. this.LastLaunchSpell = ret.Info;
  944. ret.onAdded(this);
  945. if (ret.ClientVisible)
  946. {
  947. // 产生事件
  948. AddSpellEvent evt = new AddSpellEvent(ret);
  949. evt.sender = ret;
  950. queueEvent(evt);
  951. }
  952. return ret;
  953. }
  954. }
  955. return null;
  956. }
  957. // 移除一个单位
  958. public bool RemoveObject(InstanceZoneObject obj)
  959. {
  960. //Console.WriteLine("RemoveObject : " + obj.ID);
  961. if (mObjects.RemoveObject(obj))
  962. {
  963. obj.onRemoved(this);
  964. if (obj is InstanceUnit)
  965. {
  966. InstanceUnit unit = obj as InstanceUnit;
  967. mFormula.OnUnitRemoved(unit);
  968. if (mOnUnitRemoved != null)
  969. mOnUnitRemoved.Invoke(this, unit);
  970. }
  971. else if(obj is InstanceItem)
  972. {
  973. if (this.mOnItemRemoved != null)
  974. this.mOnItemRemoved.Invoke(this, (InstanceItem)obj);
  975. }
  976. if (obj.ClientVisible)
  977. {
  978. RemoveObjectEvent remove = new RemoveObjectEvent(obj.ID);
  979. remove.sender = obj;
  980. queueEvent(remove);
  981. }
  982. obj.Dispose();
  983. return true;
  984. }
  985. return false;
  986. }
  987. public InstanceZoneObject RemoveObjectByID(uint oid)
  988. {
  989. var obj = mObjects.GetObject<InstanceZoneObject>(oid);
  990. if (obj != null && RemoveObject(obj))
  991. {
  992. return obj;
  993. }
  994. return null;
  995. }
  996. public InstanceZoneObject RemoveUnitByID(uint unitTemplateId)
  997. {
  998. InstanceUnit obj = mObjects.GetUnit(unitTemplateId);
  999. if (obj != null && RemoveObject(obj))
  1000. {
  1001. return obj;
  1002. }
  1003. return null;
  1004. }
  1005. public InstanceZoneObject RemoveSpellByLaunchIDAndSpellID(int launchId, int spellId)
  1006. {
  1007. InstanceSpell spell = mObjects.GetSpllByLanuchAndSpellId(launchId, spellId);
  1008. if(spell != null && RemoveObject(spell))
  1009. {
  1010. return spell;
  1011. }
  1012. return null;
  1013. }
  1014. public InstanceZoneObject RemoveItemByID(uint unitTemplateId)
  1015. {
  1016. InstanceItem obj = mObjects.GetItem(unitTemplateId);
  1017. if (obj != null && RemoveObject(obj))
  1018. {
  1019. Console.WriteLine("成功移除单位:" + unitTemplateId);
  1020. return obj;
  1021. }
  1022. return null;
  1023. }
  1024. public int GetZoneKingID()
  1025. {
  1026. return this.mKingID;
  1027. }
  1028. public string GetBindGameSrvID()
  1029. {
  1030. return this.mBindGameSrvId;
  1031. }
  1032. //----------------------------------------------------------------------------------------------------------------------------------------
  1033. private class InstanceZoneObjectMap
  1034. {
  1035. private class DirtyList<K, T> where T : InstanceZoneObject
  1036. {
  1037. private bool dirty = true;
  1038. private List<T> mObjectsCollection = new List<T>();
  1039. private HashMap<K, T> mObjects = new HashMap<K, T>();
  1040. public int Count { get { return mObjects.Count; } }
  1041. public void Add(K key, T obj)
  1042. {
  1043. dirty = true;
  1044. mObjects.Add(key, obj);
  1045. }
  1046. public void Put(K key, T obj)
  1047. {
  1048. dirty = true;
  1049. mObjects.Put(key, obj);
  1050. }
  1051. public bool Remove(K key)
  1052. {
  1053. if (mObjects.Remove(key))
  1054. {
  1055. dirty = true;
  1056. return true;
  1057. }
  1058. return false;
  1059. }
  1060. public void Dispose()
  1061. {
  1062. mObjectsCollection.Clear();
  1063. mObjects.Clear();
  1064. }
  1065. public T Get(K key)
  1066. {
  1067. return mObjects.Get(key);
  1068. }
  1069. public bool ContainsKey(K key)
  1070. {
  1071. return mObjects.ContainsKey(key);
  1072. }
  1073. public IEnumerable<T> GetCollection()
  1074. {
  1075. if (dirty)
  1076. {
  1077. dirty = false;
  1078. mObjectsCollection.Clear();
  1079. mObjectsCollection.AddRange(mObjects.Values);
  1080. }
  1081. return mObjectsCollection;
  1082. }
  1083. }
  1084. private DirtyList<uint, InstanceZoneObject> mObjects = new DirtyList<uint, InstanceZoneObject>();
  1085. private DirtyList<uint, InstanceUnit> mObjects_MirrorUnits = new DirtyList<uint, InstanceUnit>();
  1086. private DirtyList<uint, InstanceSpell> mObjects_MirrorSpells = new DirtyList<uint, InstanceSpell>();
  1087. private DirtyList<uint, InstanceItem> mObjects_MirrorItems = new DirtyList<uint, InstanceItem>();
  1088. private DirtyList<string, InstancePlayer> mObjects_MirrorPlayers = new DirtyList<string, InstancePlayer>();
  1089. internal void Refresh()
  1090. {
  1091. //mObjects.Refresh();
  1092. //mObjects_MirrorUnits.Refresh();
  1093. //mObjects_MirrorSpells.Refresh();
  1094. //mObjects_MirrorItems.Refresh();
  1095. //mObjects_MirrorPlayers.Refresh();
  1096. }
  1097. public void AddObject(InstanceZoneObject obj)
  1098. {
  1099. mObjects.Add(obj.ID, obj);
  1100. if (obj is InstanceUnit)
  1101. {
  1102. mObjects_MirrorUnits.Add(obj.ID, obj as InstanceUnit);
  1103. }
  1104. else if (obj is InstanceSpell)
  1105. {
  1106. mObjects_MirrorSpells.Add(obj.ID, obj as InstanceSpell);
  1107. }
  1108. else if (obj is InstanceItem)
  1109. {
  1110. mObjects_MirrorItems.Add(obj.ID, obj as InstanceItem);
  1111. }
  1112. if (obj is InstancePlayer)
  1113. {
  1114. var p = obj as InstancePlayer;
  1115. mObjects_MirrorPlayers.Put(p.PlayerUUID, p);
  1116. }
  1117. }
  1118. public bool RemoveObject(InstanceZoneObject obj)
  1119. {
  1120. if (mObjects.Remove(obj.ID))
  1121. {
  1122. if (obj is InstanceUnit)
  1123. {
  1124. mObjects_MirrorUnits.Remove(obj.ID);
  1125. }
  1126. else if (obj is InstanceSpell)
  1127. {
  1128. mObjects_MirrorSpells.Remove(obj.ID);
  1129. }
  1130. else if (obj is InstanceItem)
  1131. {
  1132. mObjects_MirrorItems.Remove(obj.ID);
  1133. }
  1134. if (obj is InstancePlayer)
  1135. {
  1136. var p = obj as InstancePlayer;
  1137. mObjects_MirrorPlayers.Remove(p.PlayerUUID);
  1138. }
  1139. return true;
  1140. }
  1141. return false;
  1142. }
  1143. private InstanceZoneObject GetObject(uint id)
  1144. {
  1145. return mObjects.Get(id);
  1146. }
  1147. public bool ContainsObject(InstanceZoneObject obj)
  1148. {
  1149. return mObjects.ContainsKey(obj.ID);
  1150. }
  1151. public bool ContainsObjectByKey(uint id)
  1152. {
  1153. return mObjects.ContainsKey(id);
  1154. }
  1155. public void Dispose()
  1156. {
  1157. mObjects.Dispose();
  1158. mObjects_MirrorUnits.Dispose();
  1159. mObjects_MirrorSpells.Dispose();
  1160. mObjects_MirrorItems.Dispose();
  1161. mObjects_MirrorPlayers.Dispose();
  1162. }
  1163. public T GetObject<T>(uint id) where T : InstanceZoneObject
  1164. {
  1165. Type type = typeof(T);
  1166. if (type.IsSubclassOf(typeof(InstanceUnit)))
  1167. {
  1168. return mObjects_MirrorUnits.Get(id) as T;
  1169. }
  1170. else if (type.IsSubclassOf(typeof(InstanceSpell)))
  1171. {
  1172. return mObjects_MirrorSpells.Get(id) as T;
  1173. }
  1174. else if (type.IsSubclassOf(typeof(InstanceItem)))
  1175. {
  1176. return mObjects_MirrorItems.Get(id) as T;
  1177. }
  1178. else
  1179. {
  1180. return mObjects.Get(id) as T;
  1181. }
  1182. }
  1183. public InstanceUnit GetUnit(uint unitTemplateId)
  1184. {
  1185. foreach (InstanceUnit obj in mObjects_MirrorUnits.GetCollection())
  1186. {
  1187. if (obj.Info.ID == unitTemplateId)
  1188. {
  1189. return obj;
  1190. }
  1191. }
  1192. return null;
  1193. }
  1194. public InstanceSpell GetSpllByLanuchAndSpellId(int launchId, int spellId)
  1195. {
  1196. foreach (InstanceSpell obj in mObjects_MirrorSpells.GetCollection())
  1197. {
  1198. if (obj.Info.ID == spellId && obj.LauncherID == launchId)
  1199. {
  1200. return obj;
  1201. }
  1202. }
  1203. return null;
  1204. }
  1205. public InstanceItem GetItem(uint itemId)
  1206. {
  1207. return mObjects_MirrorItems.Get(itemId);
  1208. }
  1209. public InstancePlayer GetPlayer(string uuid)
  1210. {
  1211. return mObjects_MirrorPlayers.Get(uuid);
  1212. }
  1213. public int ObjectsCount { get { return mObjects.Count; } }
  1214. public IEnumerable<InstanceZoneObject> Objects { get { return mObjects.GetCollection(); } }
  1215. public int UnitsCount { get { return mObjects_MirrorUnits.Count; } }
  1216. public IEnumerable<InstanceUnit> Units { get { return mObjects_MirrorUnits.GetCollection(); } }
  1217. public int SpellsCount { get { return mObjects_MirrorSpells.Count; } }
  1218. public IEnumerable<InstanceSpell> Spells { get { return mObjects_MirrorSpells.GetCollection(); } }
  1219. public int ItemsCount { get { return mObjects_MirrorItems.Count; } }
  1220. public IEnumerable<InstanceItem> Items { get { return mObjects_MirrorItems.GetCollection(); } }
  1221. public int PlayersCount { get { return mObjects_MirrorPlayers.Count; } }
  1222. public IEnumerable<InstancePlayer> Players { get { return mObjects_MirrorPlayers.GetCollection(); } }
  1223. }
  1224. #endregion
  1225. //------------------------------------------------------------------------------------
  1226. #region CALL_BACK
  1227. internal void cb_unitDamageCallBack(InstanceUnit target, InstanceUnit attacker, int reduceHP, AttackSource source)
  1228. {
  1229. LastHittedUnit = target;
  1230. LastAttackUnit = attacker;
  1231. if (attacker != null)
  1232. attacker.callback_onAttack(this, target, reduceHP, source);
  1233. if (target != null)
  1234. target.callback_onDamage(this, attacker, reduceHP, source);
  1235. if (mOnUnitDamage != null)
  1236. mOnUnitDamage.Invoke(this, target, attacker, reduceHP, source);
  1237. }
  1238. internal void cb_unitDeadCallBack(InstanceUnit obj, InstanceUnit attacker)
  1239. {
  1240. statisticForceDead(obj);
  1241. LastHittedUnit = obj;
  1242. LastKilledUnit = obj;
  1243. //if (attacker == null)
  1244. // attacker = obj;
  1245. LastAttackUnit = attacker;
  1246. obj.doDead(attacker);
  1247. if(attacker != null)
  1248. {
  1249. obj.deadDropItems(attacker.Force);
  1250. attacker.CurrentMoney += obj.Info.DropMoney;
  1251. }
  1252. mFormula.OnUnitDead(obj, attacker);
  1253. obj.callback_onDead(this, attacker);
  1254. if (mOnUnitDead != null)
  1255. mOnUnitDead.Invoke(this, obj, attacker);
  1256. obj.mProcessDeadCallbackTime = CommonLang.CUtils.localTimeMS;
  1257. }
  1258. internal void cb_unitActivatedCallBack(InstanceUnit obj)
  1259. {
  1260. nearChange(obj);
  1261. LastActivatedUnit = obj;
  1262. obj.callback_onActivated(this);
  1263. if (mOnUnitActivated != null)
  1264. mOnUnitActivated.Invoke(this, obj);
  1265. }
  1266. internal void cb_unitRebirthCallBack(InstanceUnit obj)
  1267. {
  1268. LastRebirthUnit = obj;
  1269. obj.callback_onRebirth(this);
  1270. if (mOnUnitRebirth != null)
  1271. mOnUnitRebirth.Invoke(this, obj);
  1272. }
  1273. internal void cb_unitGotInventoryItemCallBack(InstanceUnit obj, ItemTemplate item, int count)
  1274. {
  1275. LastUnitGotInventoryItem = item;
  1276. obj.callback_onGotInventoryItem(this, item);
  1277. if (mOnUnitGotInventoryItem != null)
  1278. mOnUnitGotInventoryItem.Invoke(this, obj, item, count);
  1279. }
  1280. internal void cb_unitLostInventoryItemCallBack(InstanceUnit obj, ItemTemplate item, int count)
  1281. {
  1282. LastUnitLostInventoryItem = item;
  1283. obj.callback_onLostInventoryItem(this, item);
  1284. if (mOnUnitLostInventoryItem != null)
  1285. mOnUnitLostInventoryItem.Invoke(this, obj, item, count);
  1286. }
  1287. internal int cb_unitGotInstanceItemCallBack(InstanceUnit obj, InstanceItem item)
  1288. {
  1289. LastUnitGotInstanceItem = item;
  1290. obj.callback_onGotInstanceItem(this, item);
  1291. short times = 0;
  1292. if (mOnUnitGotInstanceItem != null)
  1293. {
  1294. InstancePlayer player = (obj as InstancePlayer);
  1295. if (player == null)
  1296. {
  1297. return 0;
  1298. }
  1299. if (item.unitPickInfo != null)
  1300. {
  1301. if (item.Info.maxPickTimes > 0)
  1302. {
  1303. times = item.unitPickInfo.Get(player.PlayerUUID);
  1304. if (times >= item.Info.maxPickTimes)
  1305. {
  1306. player.Virtual.SendMsgToClient(XmdsConstConfig.TIPS_PICK_MAX);
  1307. return item.Info.maxPickTimes;
  1308. }
  1309. }
  1310. item.unitPickInfo.Put(player.PlayerUUID, ++times);
  1311. item.TotalPickTimes++;
  1312. }
  1313. mOnUnitGotInstanceItem.Invoke(this, obj, item);
  1314. }
  1315. return times;
  1316. }
  1317. internal void cb_unitUseItemCallBack(InstanceUnit obj, ItemTemplate item, InstanceUnit item_creater)
  1318. {
  1319. LastUnitUseItem = item;
  1320. obj.callback_onUseItem(this, item, item_creater);
  1321. if (mOnUnitUseItem != null)
  1322. mOnUnitUseItem.Invoke(this, obj, item, item_creater);
  1323. }
  1324. internal void cb_unitGotBuffCallBack(InstanceUnit obj, InstanceUnit.BuffState buff)
  1325. {
  1326. LastUnitGotBuff = buff.Data;
  1327. obj.callback_onGotBuff(this, buff);
  1328. if (mOnUnitGotBuff != null)
  1329. mOnUnitGotBuff.Invoke(this, obj, buff);
  1330. }
  1331. internal void cb_unitLostBuffCallBack(InstanceUnit obj, InstanceUnit.BuffState buff)
  1332. {
  1333. obj.callback_onLostBuff(this, buff);
  1334. if (mOnUnitLostBuff != null)
  1335. mOnUnitLostBuff.Invoke(this, obj, buff);
  1336. }
  1337. internal void cb_unitGotMoneyCallBack(InstanceUnit obj, int add_money)
  1338. {
  1339. if (mOnUnitGotMoney != null)
  1340. {
  1341. mOnUnitGotMoney.Invoke(obj, add_money);
  1342. }
  1343. }
  1344. internal void cb_unitPickUnitCallBack(InstanceUnit src, InstanceUnit pickable)
  1345. {
  1346. LastPickableUnit = pickable;
  1347. if (mOnUnitPickUnit != null)
  1348. {
  1349. mOnUnitPickUnit.Invoke(this, src, pickable);
  1350. }
  1351. }
  1352. public void cb_unitOutBattleCallBack(InstanceUnit obj)
  1353. {
  1354. if (mOnUnitOutBattle != null)
  1355. {
  1356. mOnUnitOutBattle.Invoke(this, obj);
  1357. }
  1358. }
  1359. internal bool cb_unitTryPickItem(InstanceUnit unit, InstanceItem item)
  1360. {
  1361. LastPickingItem = item;
  1362. LastPickingItemUnit = unit;
  1363. bool ret = true;
  1364. if (mTryPickItem != null)
  1365. {
  1366. foreach (TryPickItemHandler trypick in mTryPickItem.GetInvocationList())
  1367. {
  1368. if (!trypick.Invoke(this, unit, item))
  1369. {
  1370. ret = false;
  1371. }
  1372. }
  1373. }
  1374. return ret;
  1375. }
  1376. internal void cb_unitFinishPickItem(InstanceUnit unit, InstanceItem item)
  1377. {
  1378. if (mFinishPickItem != null)
  1379. {
  1380. mFinishPickItem.Invoke(this, unit, item);
  1381. }
  1382. }
  1383. internal void cb_unitLaunchSkill(InstanceUnit unit, CommonAI.Zone.Instance.InstanceUnit.SkillState ss)
  1384. {
  1385. LastLaunchSkill = ss.Data;
  1386. LastLaunchSkillUnit = unit;
  1387. if (mOnUnitLaunchSkill != null)
  1388. {
  1389. mOnUnitLaunchSkill.Invoke(this, unit, ss);
  1390. }
  1391. }
  1392. internal void cb_playerReady(InstancePlayer player)
  1393. {
  1394. if (mPlayerReady != null)
  1395. {
  1396. mPlayerReady.Invoke(player);
  1397. }
  1398. }
  1399. #endregion
  1400. //-------------------------------------------------------------------------------------------
  1401. #region UNIT_ATTACK
  1402. /// <summary>
  1403. /// 获得两个对象是否是队友
  1404. /// </summary>
  1405. /// <param name="src"></param>
  1406. /// <param name="dst"></param>
  1407. /// <returns></returns>
  1408. public virtual bool IsTeammates(InstanceUnit src, InstanceUnit dst)
  1409. {
  1410. return false;
  1411. }
  1412. /// <summary>
  1413. /// 测试是否可见,单位间可交互(AOI)
  1414. /// </summary>
  1415. /// <param name="src"></param>
  1416. /// <param name="dst"></param>
  1417. /// <returns></returns>
  1418. public virtual bool IsVisibleAOI(InstanceZoneObject src, InstanceZoneObject dst)
  1419. {
  1420. if (src.AoiStatus == dst.AoiStatus)
  1421. {
  1422. if (dst is InstanceUnit)
  1423. {
  1424. return (dst as InstanceUnit).IsVisible;
  1425. }
  1426. return true;
  1427. }
  1428. else if (src.AoiStatus != null)
  1429. {
  1430. return src.AoiStatus.CanSeeOther;
  1431. }
  1432. else if (dst.AoiStatus != null)
  1433. {
  1434. return dst.AoiStatus.CanSeeMe;
  1435. }
  1436. return false;
  1437. }
  1438. /// <summary>
  1439. /// 测试是否可攻击
  1440. /// </summary>
  1441. /// <param name="src"></param>
  1442. /// <param name="target"></param>
  1443. /// <param name="expectTarget"></param>
  1444. /// <param name="reason"></param>
  1445. /// <param name="weapon"></param>
  1446. /// <returns></returns>
  1447. public virtual bool IsAttackable(InstanceUnit src, InstanceUnit target, SkillTemplate.CastTarget expectTarget, AttackReason reason, ITemplateData weapon)
  1448. {
  1449. if(src == null || target == null)
  1450. {
  1451. return false;
  1452. }
  1453. if (!IsVisibleAOI(src, target))
  1454. {
  1455. return false;
  1456. }
  1457. if (target.CanWhiplashDeadBody)
  1458. {
  1459. if (!target.IsAttackable)
  1460. return false;
  1461. if (!target.IsVisible)
  1462. return false;
  1463. if (target.IsInvincible)
  1464. return false;
  1465. }
  1466. else
  1467. {
  1468. if (!target.IsActive)
  1469. return false;
  1470. if (!target.IsVisible)
  1471. return false;
  1472. if (target.IsInvincible)
  1473. return false;
  1474. }
  1475. switch (expectTarget)
  1476. {
  1477. case SkillTemplate.CastTarget.Enemy:
  1478. return src.Force != target.Force;
  1479. case SkillTemplate.CastTarget.PetForMaster:
  1480. if (src is InstancePet)
  1481. {
  1482. return (src as InstancePet).Master == target;
  1483. }
  1484. return false;
  1485. case SkillTemplate.CastTarget.Alias:
  1486. return (src != target) && (src.Force == target.Force);
  1487. case SkillTemplate.CastTarget.AlliesIncludeSelf:
  1488. return (src.Force == target.Force);
  1489. case SkillTemplate.CastTarget.AlliesExcludeSelf:
  1490. return (src != target) && (src.Force == target.Force);
  1491. case SkillTemplate.CastTarget.EveryOne:
  1492. return true;
  1493. case SkillTemplate.CastTarget.EveryOneExcludeSelf:
  1494. return (src != target);
  1495. case SkillTemplate.CastTarget.Self:
  1496. return src == target;
  1497. case SkillTemplate.CastTarget.EnemyAndSelf:
  1498. return src.Force != target.Force || src == target;
  1499. case SkillTemplate.CastTarget.NA:
  1500. default:
  1501. return false;
  1502. }
  1503. }
  1504. /// <summary>
  1505. /// 扫描所有可攻击对象
  1506. /// </summary>
  1507. /// <param name="src"></param>
  1508. /// <param name="list"></param>
  1509. /// <param name="expectTarget"></param>
  1510. /// <param name="reason"></param>
  1511. /// <param name="weapon"></param>
  1512. public void getAttackableUnits(InstanceUnit src, List<InstanceUnit> list, SkillTemplate.CastTarget expectTarget, AttackReason reason, ITemplateData weapon)
  1513. {
  1514. for (int i = list.Count - 1; i >= 0; --i)
  1515. {
  1516. InstanceUnit o = list[i];
  1517. if (!IsAttackable(src, o, expectTarget, reason, weapon))
  1518. {
  1519. list.RemoveAt(i);
  1520. }
  1521. }
  1522. }
  1523. /// <summary>
  1524. /// 对单个单位攻击。
  1525. /// </summary>
  1526. /// <param name="src"></param>
  1527. /// <param name="attack"></param>
  1528. /// <param name="target"></param>
  1529. /// <param name="expectTarget">判断IsAttackable</param>
  1530. /// <returns></returns>
  1531. public bool unitAttackSingle(
  1532. InstanceUnit src,
  1533. AttackSource attack,
  1534. InstanceUnit target,
  1535. SkillTemplate.CastTarget expectTarget)
  1536. {
  1537. if (IsAttackable(src, target, expectTarget, AttackReason.Attack, attack.Weapon))
  1538. {
  1539. target.doHitAttack(src, attack);
  1540. return true;
  1541. }
  1542. return false;
  1543. }
  1544. /// <summary>
  1545. /// 某个单位对指定列表里的 IsAttackable 单位发起攻击。
  1546. /// 此操作会修改List
  1547. /// </summary>
  1548. /// <param name="src"></param>
  1549. /// <param name="attack"></param>
  1550. /// <param name="list">调用完成后,列表中未命中单位会自动移除。</param>
  1551. /// <param name="expectTarget">判断IsAttackable</param>
  1552. /// <returns></returns>
  1553. public int unitAttack(
  1554. InstanceUnit src,
  1555. AttackSource attack,
  1556. List<InstanceUnit> list,
  1557. SkillTemplate.CastTarget expectTarget)
  1558. {
  1559. int count = 0;
  1560. for (int i = list.Count - 1; i >= 0; --i)
  1561. {
  1562. InstanceUnit o = list[i];
  1563. if (IsAttackable(src, o, expectTarget, AttackReason.Attack, attack.Weapon))
  1564. {
  1565. o.doHitAttack(src, attack);
  1566. count++;
  1567. }
  1568. else
  1569. {
  1570. list.RemoveAt(i);
  1571. }
  1572. }
  1573. return count;
  1574. }
  1575. /// <summary>
  1576. /// 直接对列表中的单位攻击,不做任何判断。
  1577. /// </summary>
  1578. /// <param name="src"></param>
  1579. /// <param name="attack"></param>
  1580. /// <param name="list"></param>
  1581. public int unitAttackDirect(
  1582. InstanceUnit src,
  1583. AttackSource attack,
  1584. List<InstanceUnit> list)
  1585. {
  1586. int count = 0;
  1587. for (int i = list.Count - 1; i >= 0; --i)
  1588. {
  1589. InstanceUnit o = list[i];
  1590. o.doHitAttack(src, attack);
  1591. count++;
  1592. }
  1593. return count;
  1594. }
  1595. /// <summary>
  1596. /// 某个单位发起周身攻击
  1597. /// </summary>
  1598. /// <param name="src"></param>
  1599. /// <param name="attack"></param>
  1600. /// <param name="range"></param>
  1601. /// <param name="expectTarget"></param>
  1602. /// <returns></returns>
  1603. public int unitAttackRound(
  1604. InstanceUnit src,
  1605. AttackSource attack,
  1606. float range,
  1607. SkillTemplate.CastTarget expectTarget)
  1608. {
  1609. using (var list = ListObjectPool<InstanceUnit>.AllocAutoRelease())
  1610. {
  1611. getObjectsRoundRange<InstanceUnit>(
  1612. Collider.Object_HitBody_TouchRound,
  1613. src.X, src.Y, range,
  1614. list, src.AoiStatus);
  1615. return unitAttack(src, attack, list, expectTarget);
  1616. }
  1617. }
  1618. /// <summary>
  1619. /// 某个单位发起扇形范围攻击
  1620. /// </summary>
  1621. /// <param name="src"></param>
  1622. /// <param name="attack"></param>
  1623. /// <param name="direction"></param>
  1624. /// <param name="range"></param>
  1625. /// <param name="angle"></param>
  1626. /// <param name="expectTarget"></param>
  1627. /// <returns></returns>
  1628. public int unitAttackFan(
  1629. InstanceUnit src,
  1630. AttackSource attack,
  1631. float direction,
  1632. float range,
  1633. float angle,
  1634. SkillTemplate.CastTarget expectTarget)
  1635. {
  1636. float dr = angle / 2;
  1637. using (var list = ListObjectPool<InstanceUnit>.AllocAutoRelease())
  1638. {
  1639. getObjectsFanRange<InstanceUnit>(
  1640. Collider.Object_HitBody_TouchFan,
  1641. src.X, src.Y, range,
  1642. direction - dr,
  1643. direction + dr,
  1644. list, src.AoiStatus);
  1645. return unitAttack(src, attack, list, expectTarget);
  1646. }
  1647. }
  1648. //-------------------------------------------------------------------------------------------------------
  1649. // 单位释放法术
  1650. //-------------------------------------------------------------------------------------------------------
  1651. public void unitLaunchSpell(
  1652. XmdsSkillType fromSkillType,
  1653. InstanceUnit launcher,
  1654. LaunchSpell launch,
  1655. float startX,
  1656. float startY,
  1657. uint targetUnitID = 0,
  1658. Vector2 targetPos = null, int actionIndex = -1, int maxAffectUnit = 0, float pointDir = 0)
  1659. {
  1660. if(launch == null)
  1661. {
  1662. log.Error("单位释放技能异常: " + launcher.Info.ID + ", " + new StackTrace().ToString());
  1663. return;
  1664. }
  1665. if (CUtils.RandomPercent(RandomN, launch.LaunchPercent))
  1666. {
  1667. float direction = pointDir == 0 ? launcher.Direction : pointDir;
  1668. if (targetPos != null)
  1669. {
  1670. //direction = MathVector.getDegree(startX, startY, targetPos.x, targetPos.y);
  1671. targetPos = (Vector2)targetPos.Clone();
  1672. }
  1673. SpellTemplate spell = Templates.getSpell(launch.SpellID);
  1674. if(spell == null)
  1675. {
  1676. log.Error("unitLaunchSpell找不到法术模板:" + launcher.PlayerUUID + ", " + launch.SpellID + ", SN: " + launch.SerialNumber);
  1677. return;
  1678. }
  1679. JSGCreateSpellData createData;
  1680. if (spell != null && launch.Count > 0 && mFormula.TryLaunchSpell(launcher, launch, ref spell, out createData, ref startX, ref startY))
  1681. {
  1682. SpellChainLevelInfo chain = null;
  1683. if (launch.ChainLevel > 0)
  1684. {
  1685. chain = new SpellChainLevelInfo(launch);
  1686. }
  1687. switch (launch.PType)
  1688. {
  1689. case LaunchSpell.PosType.POS_TYPE_FAN:
  1690. {
  1691. float startAngle = direction - launch.Angle / 2f;// + launch.StartAngle;
  1692. float interAngle = launch.Count > 0 ? launch.Angle / (launch.Count - 1) : 0;
  1693. for (int i = 0; i < launch.Count; i++)
  1694. {
  1695. AddSpell(fromSkillType, spell, launch, launcher, launcher,
  1696. targetUnitID, targetPos, startX, startY,
  1697. startAngle + interAngle * i, chain, actionIndex, maxAffectUnit);
  1698. }
  1699. }
  1700. break;
  1701. case LaunchSpell.PosType.POS_TYPE_TOSAMETARGET:
  1702. {
  1703. InstanceUnit target = SeekSpellAttackable(launcher, spell, launcher.AoiStatus, startX, startY, launch.SeekingTargetRange,
  1704. spell.ExpectTarget, SeekingExpect.Nearest, null);
  1705. if (target != null)
  1706. {
  1707. launcher.faceTo(target.X, target.Y);
  1708. launcher.SendForceSync();
  1709. targetPos = new Vector2(target.X, target.Y);
  1710. //Console.WriteLine("-------------targetPos 1 - " + target.X + ", " + target.Y);
  1711. //Console.WriteLine("-------------targetPos 2 - " + targetPos);
  1712. int[] index = { 0, -1, 1 };
  1713. float testAngle = (float)Math.Atan2(targetPos.Y - launcher.Y, targetPos.X - launcher.X);
  1714. float xBase = 3.0f;
  1715. float xAdd = (float)(xBase * Math.Sin(testAngle)); //角Dir的对边
  1716. float yAdd = (float)(xBase * Math.Cos(testAngle)); //Dir的邻边
  1717. for (int i = 0; i < launch.Count; i++)
  1718. {
  1719. float tempX = startX - xAdd * index[i];
  1720. float tempY = startY + yAdd * index[i];
  1721. float angle = (float)Math.Atan2(targetPos.Y - tempY, targetPos.X - tempX);
  1722. AddSpell(fromSkillType, spell, launch, launcher, launcher,
  1723. targetUnitID, targetPos, tempX, tempY,
  1724. angle, chain, actionIndex, maxAffectUnit);
  1725. }
  1726. }
  1727. else
  1728. {
  1729. int[] index = { 0, -1, 1 };
  1730. float xBase = 3.0f;
  1731. float xAdd = (float)(xBase * Math.Sin(direction)); //角Dir的对边
  1732. float yAdd = (float)(xBase * Math.Cos(direction)); //Dir的邻边
  1733. float[] startAngleTemp = { 0, launch.Angle, launch.Angle * 1.2f, launch.Angle * 1.4f, launch.Angle * 1.5f };
  1734. for (int i = 0; i < launch.Count; i++)
  1735. {
  1736. float tempX = startX - xAdd * index[i];
  1737. float tempY = startY + yAdd * index[i];
  1738. AddSpell(fromSkillType, spell, launch, launcher, launcher,
  1739. targetUnitID, targetPos, tempX, tempY,
  1740. direction - startAngleTemp[i] * index[i], chain, actionIndex, maxAffectUnit);
  1741. }
  1742. }
  1743. }
  1744. break;
  1745. case LaunchSpell.PosType.POS_TYPE_CYCLE:
  1746. {
  1747. float startAngle = direction + launch.StartAngle;
  1748. float interAngle = CMath.PI_MUL_2 / launch.Count;
  1749. InstanceSpell[] spellBrothers = null;
  1750. if (launch.Count > 1 && spell.MType == SpellTemplate.MotionType.Foxfire)
  1751. {
  1752. spellBrothers = new InstanceSpell[launch.Count];
  1753. }
  1754. for (int i = 0; i < launch.Count; i++)
  1755. {
  1756. var sb = AddSpell(fromSkillType, spell, launch, launcher, launcher,
  1757. targetUnitID, targetPos, startX, startY,
  1758. startAngle + interAngle * i, chain, actionIndex, maxAffectUnit);
  1759. if (spellBrothers != null)
  1760. {
  1761. spellBrothers[i] = sb;
  1762. sb.brothers = spellBrothers;
  1763. }
  1764. }
  1765. }
  1766. break;
  1767. case LaunchSpell.PosType.POS_TYPE_X:
  1768. {
  1769. float startAngle = direction + launch.StartAngle;
  1770. float[] interAngle = { launch.Angle, CMath.PI_F - launch.Angle, CMath.PI_F + launch.Angle, CMath.PI_F * 2 - launch.Angle };
  1771. Dictionary<uint, InstanceUnit> damageList = (spell.HitIntervalMS <= 0 ? new Dictionary<uint, InstanceUnit>() : null);
  1772. for (int i = 0; i < 4; i++)
  1773. {
  1774. AddSpell(fromSkillType, spell, launch, launcher, launcher, targetUnitID, targetPos,
  1775. startX, startY, startAngle + interAngle[i], chain, actionIndex, maxAffectUnit, damageList);
  1776. }
  1777. }
  1778. break;
  1779. case LaunchSpell.PosType.POS_TYPE_RANDOM_DIRECTION:
  1780. {
  1781. for (int i = 0; i < launch.Count; i++)
  1782. {
  1783. float d = (float)(random.NextDouble() * CMath.PI_MUL_2);
  1784. AddSpell(fromSkillType, spell, launch, launcher,
  1785. launcher, targetUnitID, targetPos, startX,
  1786. startY, d, chain, actionIndex, maxAffectUnit);
  1787. }
  1788. }
  1789. break;
  1790. case LaunchSpell.PosType.POS_TYPE_AREA:
  1791. using (var enemy_list = ListObjectPool<InstanceUnit>.AllocAutoRelease())
  1792. {
  1793. SeekSpellAttackable(enemy_list, startX, startY, launcher, spell, launch, chain);
  1794. for (int i = 0; i < launch.Count && i < enemy_list.Count; i++)
  1795. {
  1796. AddSpell(fromSkillType, spell, launch, launcher, launcher, enemy_list[i].ID, null,
  1797. startX, startY, direction, chain, actionIndex, maxAffectUnit);
  1798. }
  1799. }
  1800. break;
  1801. case LaunchSpell.PosType.POS_TYPE_RANDOM_FOR_SPELL:
  1802. launch_randomTypeSpell(fromSkillType, spell, launcher, launch, chain, launcher, actionIndex);
  1803. break;
  1804. case LaunchSpell.PosType.POS_TYPE_RANDOM_POS:
  1805. launch_randomPosSpell(fromSkillType, spell, launcher, launch, chain, launcher, actionIndex);
  1806. break;
  1807. case LaunchSpell.PosType.POS_TYPE_MANY_CANNON:
  1808. launch_ManyCannon(fromSkillType, spell, launcher, launch, chain, launcher, targetUnitID, actionIndex, createData);
  1809. break;
  1810. case LaunchSpell.PosType.POS_TYPE_DEFAULT_SINGLE:
  1811. default:
  1812. {
  1813. AddSpell(fromSkillType, spell, launch, launcher, launcher,
  1814. targetUnitID, targetPos, startX, startY,
  1815. direction + launch.StartAngle, chain, actionIndex, maxAffectUnit);
  1816. }
  1817. break;
  1818. }
  1819. }
  1820. }
  1821. }
  1822. // 单位释放法术
  1823. public void spellLaunchSpell(
  1824. XmdsSkillType fromSkillType,
  1825. InstanceSpell sender,
  1826. LaunchSpell launch,
  1827. float startX,
  1828. float startY,
  1829. uint targetUnitID = 0,
  1830. Vector2 targetPos = null, int actionIndex = -1, int maxAffectUnit = 0)
  1831. {
  1832. switch (launch.SenderUnit)
  1833. {
  1834. case LaunchSpell.LaunchSpllSenderUnit.Launcher:
  1835. this.unitLaunchSpell(fromSkillType, sender.Launcher, launch, startX, startY, targetUnitID, targetPos);
  1836. return;
  1837. }
  1838. if (CUtils.RandomPercent(RandomN, launch.LaunchPercent))
  1839. {
  1840. SpellChainLevelInfo chain = sender.ChainInfo;
  1841. if (chain != null)
  1842. {
  1843. if (!chain.TryLaunch(launch.SpellID))
  1844. {
  1845. // chain is end //
  1846. return;
  1847. }
  1848. }
  1849. SpellTemplate spell = Templates.getSpell(launch.SpellID);
  1850. JSGCreateSpellData createData;
  1851. if (spell != null && launch.Count > 0 && mFormula.TryLaunchSpell(sender.Launcher, launch, ref spell, out createData, ref startX, ref startY))
  1852. {
  1853. float direction = sender.Direction;
  1854. if (targetPos != null)
  1855. {
  1856. direction = MathVector.getDegree(startX, startY, targetPos.X, targetPos.Y);
  1857. targetPos = (Vector2)targetPos.Clone();
  1858. }
  1859. switch (launch.PType)
  1860. {
  1861. case LaunchSpell.PosType.POS_TYPE_FAN:
  1862. {
  1863. float startAngle = direction - launch.Angle / 2f + launch.StartAngle;
  1864. float interAngle = launch.Count > 0 ? launch.Angle / (launch.Count - 1) : 0;
  1865. for (int i = 0; i < launch.Count; i++)
  1866. {
  1867. AddSpell(fromSkillType, spell, launch, sender, sender.Launcher,
  1868. targetUnitID, targetPos, startX, startY,
  1869. startAngle + interAngle * i, chain, actionIndex, maxAffectUnit);
  1870. }
  1871. }
  1872. break;
  1873. case LaunchSpell.PosType.POS_TYPE_CYCLE:
  1874. {
  1875. float startAngle = direction + launch.StartAngle;
  1876. float interAngle = CMath.PI_MUL_2 / launch.Count;
  1877. for (int i = 0; i < launch.Count; i++)
  1878. {
  1879. AddSpell(fromSkillType, spell, launch, sender, sender.Launcher,
  1880. targetUnitID, targetPos, startX, startY,
  1881. startAngle + interAngle * i, chain, actionIndex, maxAffectUnit);
  1882. }
  1883. }
  1884. break;
  1885. case LaunchSpell.PosType.POS_TYPE_X:
  1886. {
  1887. float startAngle = direction + launch.StartAngle;
  1888. float[] interAngle = { launch.Angle, CMath.PI_F - launch.Angle, CMath.PI_F + launch.Angle, CMath.PI_F * 2 - launch.Angle };
  1889. Dictionary<uint, InstanceUnit> damageList = (spell.HitIntervalMS <= 0 ? new Dictionary<uint, InstanceUnit>() : null);
  1890. for (int i = 0; i < launch.Count; i++)
  1891. {
  1892. AddSpell(fromSkillType, spell, launch, sender, sender.Launcher, targetUnitID,
  1893. targetPos, startX, startY, startAngle + interAngle[i], chain, actionIndex, maxAffectUnit, damageList);
  1894. }
  1895. }
  1896. break;
  1897. case LaunchSpell.PosType.POS_TYPE_RANDOM_FOR_SPELL:
  1898. launch_randomTypeSpell(fromSkillType, spell, sender, launch, chain, sender.Launcher, actionIndex);
  1899. break;
  1900. case LaunchSpell.PosType.POS_TYPE_MANY_CANNON:
  1901. launch_ManyCannon(fromSkillType, spell, sender, launch, chain, sender.Launcher, targetUnitID, actionIndex, createData);
  1902. break;
  1903. case LaunchSpell.PosType.POS_TYPE_RANDOM_POS:
  1904. launch_randomPosSpell(fromSkillType, spell, sender, launch, chain, sender.Launcher, actionIndex);
  1905. break;
  1906. case LaunchSpell.PosType.POS_TYPE_RANDOM_DIRECTION:
  1907. {
  1908. for (int i = 0; i < launch.Count; i++)
  1909. {
  1910. float d = (float)(random.NextDouble() * CMath.PI_MUL_2);
  1911. AddSpell(fromSkillType, spell, launch, sender, sender.Launcher,
  1912. targetUnitID, targetPos, startX, startY, d, chain, actionIndex, maxAffectUnit);
  1913. }
  1914. }
  1915. break;
  1916. case LaunchSpell.PosType.POS_TYPE_AREA:
  1917. using (var enemy_list = ListObjectPool<InstanceUnit>.AllocAutoRelease())
  1918. {
  1919. SeekSpellAttackable(enemy_list, startX, startY, sender.Launcher, spell, launch, chain);
  1920. for (int i = 0; i < launch.Count && i < enemy_list.Count; i++)
  1921. {
  1922. AddSpell(fromSkillType, spell, launch, sender, sender.Launcher,
  1923. enemy_list[i].ID, targetPos, startX, startY, direction, chain, actionIndex, maxAffectUnit);
  1924. }
  1925. }
  1926. break;
  1927. case LaunchSpell.PosType.POS_TYPE_DEFAULT_SINGLE:
  1928. default:
  1929. {
  1930. AddSpell(fromSkillType, spell, launch, sender, sender.Launcher,
  1931. targetUnitID, targetPos, startX, startY, direction, chain, actionIndex, maxAffectUnit);
  1932. }
  1933. break;
  1934. }
  1935. }
  1936. }
  1937. }
  1938. public void attackLaunchSpell(
  1939. XmdsSkillType fromSkillType,
  1940. InstanceUnit attacker,
  1941. InstanceUnit damage,
  1942. AttackSource source,
  1943. int serverExt = 0)
  1944. {
  1945. LaunchSpell launch = source.Attack.Spell;
  1946. if (launch == null)
  1947. return;
  1948. InstanceZoneObject sender;
  1949. if (source.FromSpellUnit != null)
  1950. {
  1951. sender = source.FromSpellUnit;
  1952. }
  1953. else
  1954. {
  1955. sender = attacker;
  1956. }
  1957. switch (launch.SenderUnit)
  1958. {
  1959. case LaunchSpell.LaunchSpllSenderUnit.Launcher:
  1960. sender = attacker;
  1961. break;
  1962. case LaunchSpell.LaunchSpllSenderUnit.DamagedUnit:
  1963. sender = damage;
  1964. break;
  1965. }
  1966. if (CUtils.RandomPercent(RandomN, launch.LaunchPercent))
  1967. {
  1968. float startX = damage.X;
  1969. float startY = damage.Y;
  1970. SpellTemplate spell = Templates.getSpell(launch.SpellID);
  1971. JSGCreateSpellData createData;
  1972. if (spell != null && launch.Count > 0 && mFormula.TryLaunchSpell(attacker, launch, ref spell, out createData, ref startX, ref startY))
  1973. {
  1974. SpellChainLevelInfo chain = null;
  1975. if (source.FromSpellUnit != null && source.FromSpellUnit.ChainInfo != null)
  1976. {
  1977. chain = source.FromSpellUnit.ChainInfo;
  1978. if (!chain.TryLaunch(launch.SpellID))
  1979. {
  1980. // chain is end //
  1981. return;
  1982. }
  1983. }
  1984. switch (launch.PType)
  1985. {
  1986. case LaunchSpell.PosType.POS_TYPE_FAN:
  1987. {
  1988. float startAngle = sender.Direction - launch.Angle / 2f + launch.StartAngle;
  1989. float interAngle = launch.Count > 0 ? launch.Angle / (launch.Count - 1) : 0;
  1990. for (int i = 0; i < launch.Count; i++)
  1991. {
  1992. AddSpell(fromSkillType, spell, launch, sender, attacker, damage.ID, null,
  1993. startX, startY, startAngle + interAngle * i, chain, serverExt);
  1994. }
  1995. }
  1996. break;
  1997. case LaunchSpell.PosType.POS_TYPE_CYCLE:
  1998. {
  1999. float startAngle = sender.Direction + launch.StartAngle;
  2000. float interAngle = CMath.PI_MUL_2 / launch.Count;
  2001. for (int i = 0; i < launch.Count; i++)
  2002. {
  2003. AddSpell(fromSkillType, spell, launch, sender, attacker, damage.ID, null,
  2004. startX, startY, startAngle + interAngle * i, chain, serverExt);
  2005. }
  2006. }
  2007. break;
  2008. case LaunchSpell.PosType.POS_TYPE_X:
  2009. {
  2010. float startAngle = sender.Direction + launch.StartAngle;
  2011. float[] interAngle = { launch.Angle, CMath.PI_F - launch.Angle, CMath.PI_F + launch.Angle, CMath.PI_F * 2 - launch.Angle };
  2012. Dictionary<uint, InstanceUnit> damageList = (spell.HitIntervalMS <= 0 ? new Dictionary<uint, InstanceUnit>() : null);
  2013. for (int i = 0; i < launch.Count; i++)
  2014. {
  2015. AddSpell(fromSkillType, spell, launch, sender, attacker, damage.ID, null,
  2016. startX, startY, startAngle + interAngle[i], chain, serverExt, 0, damageList);
  2017. }
  2018. }
  2019. break;
  2020. case LaunchSpell.PosType.POS_TYPE_RANDOM_FOR_SPELL:
  2021. launch_randomTypeSpell(fromSkillType, spell, sender, launch, chain, attacker, serverExt);
  2022. break;
  2023. case LaunchSpell.PosType.POS_TYPE_MANY_CANNON:
  2024. launch_ManyCannon(fromSkillType, spell, sender, launch, chain, attacker, damage.ID, serverExt, createData);
  2025. break;
  2026. case LaunchSpell.PosType.POS_TYPE_RANDOM_POS:
  2027. launch_randomPosSpell(fromSkillType, spell, sender, launch, chain, attacker, serverExt);
  2028. break;
  2029. case LaunchSpell.PosType.POS_TYPE_RANDOM_DIRECTION:
  2030. {
  2031. for (int i = 0; i < launch.Count; i++)
  2032. {
  2033. float d = (float)(random.NextDouble() * CMath.PI_MUL_2);
  2034. AddSpell(fromSkillType, spell, launch, sender, attacker, damage.ID, null,
  2035. startX, startY, d, chain, serverExt);
  2036. }
  2037. }
  2038. break;
  2039. case LaunchSpell.PosType.POS_TYPE_AREA:
  2040. using (var enemy_list = ListObjectPool<InstanceUnit>.AllocAutoRelease())
  2041. {
  2042. SeekSpellAttackable(enemy_list, startX, startY, attacker, spell, launch, chain);
  2043. for (int i = 0; i < launch.Count && i < enemy_list.Count; i++)
  2044. {
  2045. AddSpell(fromSkillType, spell, launch, sender, attacker, enemy_list[i].ID, null,
  2046. startX, startY, 0, chain, serverExt);
  2047. }
  2048. }
  2049. break;
  2050. case LaunchSpell.PosType.POS_TYPE_DEFAULT_SINGLE:
  2051. default:
  2052. {
  2053. AddSpell(fromSkillType, spell, launch, sender, attacker, damage.ID, null,
  2054. startX, startY, sender.Direction, chain, serverExt);
  2055. }
  2056. break;
  2057. }
  2058. }
  2059. }
  2060. }
  2061. private void launch_randomTypeSpell(XmdsSkillType fromSkillType, SpellTemplate spell, InstanceZoneObject sender,
  2062. LaunchSpell launch, SpellChainLevelInfo chain, InstanceUnit attacker, int serverExt = 0)
  2063. {
  2064. using (var list = ListObjectPool<InstanceUnit>.AllocAutoRelease())
  2065. {
  2066. attacker.Parent.getObjectsRoundRange<InstanceUnit>(
  2067. (obj, dx, dy, dr) =>
  2068. {
  2069. var u = obj as InstanceUnit;
  2070. //己方单位.
  2071. if ((attacker.IsPlayer && !u.IsPlayer) || (!attacker.IsPlayer && u.IsPlayer))
  2072. {
  2073. return CMath.includeRoundPoint(dx, dy, dr, u.X, u.Y);
  2074. }
  2075. return false;
  2076. },
  2077. attacker.X,
  2078. attacker.Y,
  2079. launch.SeekingTargetRange,
  2080. list, attacker.AoiStatus);
  2081. int maxCount = launch.Count == 0 ? list.Count : Math.Min(launch.Count, list.Count);
  2082. for (int i = 0; i < maxCount; i++)
  2083. {
  2084. float r = (float)(random.NextDouble() * spell.BodySize);
  2085. float a = (float)(random.NextDouble() * CMath.PI_MUL_2);
  2086. float x = (float)(list[i].X + Math.Cos(a) * r);
  2087. float y = (float)(list[i].Y + Math.Sin(a) * r);
  2088. float d = (float)(random.NextDouble() * CMath.PI_MUL_2);
  2089. AddSpell(fromSkillType, spell, launch, sender, attacker, 0, null,
  2090. x, y, d, chain, serverExt);
  2091. }
  2092. }
  2093. }
  2094. private void launch_randomPosSpell(XmdsSkillType fromSkillType, SpellTemplate spell, InstanceZoneObject sender,
  2095. LaunchSpell launch, SpellChainLevelInfo chain, InstanceUnit attacker, int serverExt = 0)
  2096. {
  2097. for (int i = 0; i < launch.Count; i++)
  2098. {
  2099. float x = (float)(random.NextDouble() * launch.SpellRange/2);
  2100. float y = (float)(random.NextDouble() * launch.SpellRange/2);
  2101. float d = (float)(random.NextDouble() * CMath.PI_MUL_2);
  2102. int randX = random.Next() % 2 == 0 ? 1 : -1;
  2103. int randY = random.Next() % 2 == 0 ? 1 : -1;
  2104. AddSpell(fromSkillType, spell, launch, sender, attacker, 0, null,
  2105. sender.X + x * randX, sender.Y + y * randY, d, chain, serverExt);
  2106. }
  2107. }
  2108. public InstanceSpell launch_ManyCannon(XmdsSkillType fromSkillType, SpellTemplate spell, InstanceZoneObject sender,
  2109. LaunchSpell launch, SpellChainLevelInfo chain, InstanceUnit attacker, uint targetUnitID, int serverExt, JSGCreateSpellData createData)
  2110. {
  2111. //float angleOffset = targetUnitID == 0 ? launch.StartAngle / 3 : launch.StartAngle;
  2112. float angleOffset = JSGModule.GetCurveStartAngleOffect(attacker, getUnit(targetUnitID), launch.StartAngle, spell.SeekingRange);
  2113. float startAngle = CMath.OpitimizeRadians(attacker.Direction) + angleOffset;
  2114. float launchX = attacker.X - (float)(1.0f * Math.Cos(attacker.Direction));
  2115. float launchY = attacker.Y - (float)(1.0f * Math.Sin(attacker.Direction));
  2116. Vector2 targetPos = JSGModule.GetCurveDefaultTargetPos(attacker, spell.SeekingRange);
  2117. //System.Console.WriteLine("targetPos: " + targetPos.X + ", " + targetPos.Y);
  2118. int totalCount = createData == null ? launch.Count : createData.mMaxSpellCount;
  2119. return AddSpell(fromSkillType, spell, launch, sender, attacker, targetUnitID, targetPos,
  2120. launchX, launchY, startAngle, chain, serverExt, 0, null, totalCount-1, createData);
  2121. }
  2122. public void spellSummonUnit(InstanceSpell summoner, SummonUnit summon)
  2123. {
  2124. float x = summoner.X;
  2125. float y = summoner.Y;
  2126. float radius = summoner.BodyBlockSize;
  2127. UnitInfo info = Templates.getUnit(summon.UnitTemplateID);
  2128. if (info.UType != UnitType.TYPE_SUMMON || info.LifeTimeMS <= 0)
  2129. {
  2130. log.Warn("召唤非召唤类单位1:" + summoner.ID + ", 召唤id: " + summon.UnitTemplateID);
  2131. return;
  2132. }
  2133. //UnitInfo un = (UnitInfo)info.Clone();
  2134. //un.UType = UnitInfo.UnitType.TYPE_SUMMON;
  2135. string name = null;
  2136. if (TemplateManager.Formula.TrySummonUnit(summoner.Launcher, summon, ref info, ref name))
  2137. {
  2138. for (int i = 0; i < summon.Count; i++)
  2139. {
  2140. float dx, dy, dr;
  2141. //float angle = (float)RandomN.NextDouble() * CMath.PI_MUL_2;
  2142. //float lengt = (float)RandomN.NextDouble() * radius;
  2143. //dx = x + (float)Math.Cos(angle) * lengt;
  2144. //dy = y + (float)Math.Sin(angle) * lengt;
  2145. //dr = (float)RandomN.NextDouble() * CMath.PI_MUL_2;
  2146. //召唤单位时判断当前位置能否行走,防止被召唤单位卡在地图里.Editor by Alex.
  2147. var pos = PathFinder.FindNearRandomMoveableNode(RandomN, x, y, radius, true);
  2148. if (pos == null)
  2149. {
  2150. dx = summoner.Launcher.X;
  2151. dy = summoner.Launcher.Y;
  2152. }
  2153. else
  2154. {
  2155. dx = pos.PosX;
  2156. dy = pos.PosY;
  2157. }
  2158. dr = summoner.Direction;
  2159. InstanceUnit unit = null;
  2160. if (!summoner.Launcher.IsActive)
  2161. {
  2162. unit = AddUnit(info, name, summoner.Launcher.Force, summon.UnitLevel, dx, dy, dr, null);
  2163. }
  2164. else
  2165. {
  2166. unit = AddUnit(info, name, summoner.Launcher.Force, summon.UnitLevel, dx, dy, dr, summoner.Launcher);
  2167. }
  2168. if (unit != null)
  2169. {
  2170. if (info.LifeTimeMS > 0)
  2171. {
  2172. AddTimeDelayMS(info.LifeTimeMS, (task) =>
  2173. {
  2174. unit.kill();
  2175. });
  2176. }
  2177. if (summon.Effect != null)
  2178. {
  2179. queueEvent(new AddEffectEvent(unit.ID, dx, dy, dr, summon.Effect));
  2180. }
  2181. }
  2182. }
  2183. }
  2184. }
  2185. public void unitSummonUnit(InstanceUnit summoner, SummonUnit summon)
  2186. {
  2187. float x = summoner.X;
  2188. float y = summoner.Y;
  2189. MathVector.movePolar(ref x, ref y, summoner.Direction, summoner.BodyBlockSize * 4);
  2190. float radius = summoner.BodyBlockSize * 2;
  2191. UnitInfo info = Templates.getUnit(summon.UnitTemplateID);
  2192. if (info.UType != UnitType.TYPE_SUMMON || info.LifeTimeMS <= 0)
  2193. {
  2194. log.Warn("召唤非召唤类单位2:" + summoner.ID + ", 召唤id: " + summon.UnitTemplateID);
  2195. return;
  2196. }
  2197. //UnitInfo un = (UnitInfo)info.Clone();
  2198. //un.UType = UnitInfo.UnitType.TYPE_SUMMON;
  2199. string name = null;
  2200. if (TemplateManager.Formula.TrySummonUnit(summoner, summon, ref info, ref name))
  2201. {
  2202. for (int i = 0; i < summon.Count; i++)
  2203. {
  2204. float angle = (float)RandomN.NextDouble() * CMath.PI_MUL_2;
  2205. float lengt = (float)RandomN.NextDouble() * radius;
  2206. float dx = x + (float)Math.Cos(angle) * lengt;
  2207. float dy = y + (float)Math.Sin(angle) * lengt;
  2208. float dr = (float)RandomN.NextDouble() * CMath.PI_MUL_2;
  2209. InstanceUnit unit = AddUnit(info, name, summoner.Force, summon.UnitLevel, dx, dy, dr, summoner);
  2210. if (unit != null)
  2211. {
  2212. if (info.LifeTimeMS > 0)
  2213. {
  2214. AddTimeDelayMS(info.LifeTimeMS, (task) =>
  2215. {
  2216. unit.kill();
  2217. });
  2218. }
  2219. if (summon.Effect != null)
  2220. {
  2221. queueEvent(new AddEffectEvent(unit.ID, dx, dy, dr, summon.Effect));
  2222. }
  2223. }
  2224. }
  2225. }
  2226. }
  2227. public InstanceUnit summonUnit(InstanceUnit summoner, UnitInfo info, string name, int level, float x, float y, float direction)
  2228. {
  2229. if (info.UType != UnitType.TYPE_SUMMON || info.LifeTimeMS <= 0)
  2230. {
  2231. log.Warn("召唤非召唤类单位3:" + summoner.ID + ", 召唤id: " + info.ID);
  2232. return null;
  2233. }
  2234. InstanceUnit unit = AddUnit(info, name, summoner.Force, level, x, y, direction, summoner);
  2235. if (unit != null)
  2236. {
  2237. if (info.LifeTimeMS > 0)
  2238. {
  2239. AddTimeDelayMS(info.LifeTimeMS, (task) =>
  2240. {
  2241. unit.kill();
  2242. });
  2243. }
  2244. }
  2245. return unit;
  2246. }
  2247. /// <summary>
  2248. /// 锁定范围内指定目标
  2249. /// </summary>
  2250. /// <param name="spell"></param>
  2251. /// <param name="X"></param>
  2252. /// <param name="Y"></param>
  2253. /// <param name="range"></param>
  2254. /// <param name="expectTarget"></param>
  2255. /// <param name="expectSeeking"></param>
  2256. /// <param name="chain"></param>
  2257. /// <returns></returns>
  2258. public virtual InstanceUnit SeekSpellAttackable(
  2259. InstanceUnit launcher,
  2260. SpellTemplate spellData,
  2261. ObjectAoiStatus aoiStatus,
  2262. float X, float Y, float range,
  2263. SkillTemplate.CastTarget expectTarget,
  2264. SpellTemplate.SeekingExpect expectSeeking,
  2265. SpellChainLevelInfo chain)
  2266. {
  2267. using (var list = ListObjectPool<InstanceUnit>.AllocAutoRelease())
  2268. {
  2269. getObjectsRoundRange<InstanceUnit>((InstanceZoneObject o, float x, float y, float r) =>
  2270. {
  2271. InstanceUnit u = o as InstanceUnit;
  2272. if (chain != null)
  2273. {
  2274. switch (expectSeeking)
  2275. {
  2276. case SpellTemplate.SeekingExpect.RandomIgnoreInChain:
  2277. case SpellTemplate.SeekingExpect.NearestIgnoreInChain:
  2278. case SpellTemplate.SeekingExpect.FarthestIgnoreInChain:
  2279. if (chain.ContainsTarget(u))
  2280. {
  2281. return false;
  2282. }
  2283. break;
  2284. default:
  2285. if (chain.LastTarget == u)
  2286. {
  2287. return false;
  2288. }
  2289. break;
  2290. }
  2291. }
  2292. if (IsAttackable(launcher, u, expectTarget, AttackReason.Look, spellData))
  2293. {
  2294. return CMath.intersectRound(x, y, r, o.X, o.Y, o.BodyHitSize);
  2295. }
  2296. return false;
  2297. }, X, Y, range, list, aoiStatus);
  2298. switch (expectSeeking)
  2299. {
  2300. case SpellTemplate.SeekingExpect.Random:
  2301. case SpellTemplate.SeekingExpect.RandomIgnoreInChain:
  2302. CUtils.RandomList(RandomN, list);
  2303. break;
  2304. case SpellTemplate.SeekingExpect.Nearest:
  2305. case SpellTemplate.SeekingExpect.NearestIgnoreInChain:
  2306. list.Sort(new ObjectSorterNearest<InstanceUnit>(X, Y));
  2307. break;
  2308. case SpellTemplate.SeekingExpect.Farthest:
  2309. case SpellTemplate.SeekingExpect.FarthestIgnoreInChain:
  2310. list.Sort(new ObjectSorterFarthest<InstanceUnit>(X, Y));
  2311. break;
  2312. }
  2313. if (list.Count > 0)
  2314. {
  2315. return list[0];
  2316. }
  2317. }
  2318. return null;
  2319. }
  2320. public virtual void SeekSpellAttackable(List<InstanceUnit> ret, float X, float Y,
  2321. InstanceUnit Launcher,
  2322. SpellTemplate spell,
  2323. LaunchSpell launch,
  2324. SpellChainLevelInfo chain)
  2325. {
  2326. getObjectsRoundRange<InstanceUnit>((InstanceZoneObject o, float x, float y, float r) =>
  2327. {
  2328. InstanceUnit u = o as InstanceUnit;
  2329. if (chain != null)
  2330. {
  2331. switch (launch.SeekingTargetExpect)
  2332. {
  2333. case SpellTemplate.SeekingExpect.RandomIgnoreInChain:
  2334. case SpellTemplate.SeekingExpect.NearestIgnoreInChain:
  2335. case SpellTemplate.SeekingExpect.FarthestIgnoreInChain:
  2336. if (chain.ContainsTarget(u))
  2337. {
  2338. return false;
  2339. }
  2340. break;
  2341. default:
  2342. if (chain.LastTarget == u)
  2343. {
  2344. return false;
  2345. }
  2346. break;
  2347. }
  2348. }
  2349. if (IsAttackable(Launcher, u, spell.ExpectTarget, AttackReason.Look, spell))
  2350. {
  2351. return CMath.intersectRound(x, y, r, o.X, o.Y, o.BodyHitSize);
  2352. }
  2353. return false;
  2354. }, X, Y, launch.SeekingTargetRange, ret, Launcher.AoiStatus);
  2355. switch (launch.SeekingTargetExpect)
  2356. {
  2357. case SpellTemplate.SeekingExpect.Random:
  2358. case SpellTemplate.SeekingExpect.RandomIgnoreInChain:
  2359. CUtils.RandomList(RandomN, ret);
  2360. break;
  2361. case SpellTemplate.SeekingExpect.Nearest:
  2362. case SpellTemplate.SeekingExpect.NearestIgnoreInChain:
  2363. ret.Sort(new ObjectSorterNearest<InstanceUnit>(X, Y));
  2364. break;
  2365. case SpellTemplate.SeekingExpect.Farthest:
  2366. case SpellTemplate.SeekingExpect.FarthestIgnoreInChain:
  2367. ret.Sort(new ObjectSorterFarthest<InstanceUnit>(X, Y));
  2368. break;
  2369. }
  2370. }
  2371. /**游戏服场景标识通知*/
  2372. public virtual void GSZoneFlagNotifyMsg(int value1)
  2373. {
  2374. }
  2375. #endregion
  2376. //-------------------------------------------------------------------------------------------------------//
  2377. #region EDITOR_AND_SCRIPT
  2378. readonly private HashMap<string, InstanceFlag> mFlags = new HashMap<string, InstanceFlag>();
  2379. private bool mHasArea = false;
  2380. protected bool addFlag(InstanceFlag flag)
  2381. {
  2382. if (!mFlags.ContainsKey(flag.Name))
  2383. {
  2384. mFlags.Add(flag.Name, flag);
  2385. flag.onAdded();
  2386. if (flag is ZoneArea)
  2387. {
  2388. mHasArea = true;
  2389. }
  2390. return true;
  2391. }
  2392. return false;
  2393. }
  2394. public InstanceFlag getFlag(string name)
  2395. {
  2396. if(string.IsNullOrEmpty(name))
  2397. {
  2398. return null;
  2399. }
  2400. return mFlags.Get(name);
  2401. }
  2402. public T getFlagAs<T>(string name) where T : InstanceFlag
  2403. {
  2404. return mFlags.Get(name) as T;
  2405. }
  2406. public bool setFlag(string name, bool enable)
  2407. {
  2408. InstanceFlag flag = getFlag(name);
  2409. if (flag != null)
  2410. {
  2411. flag.Enable = enable;
  2412. return true;
  2413. }
  2414. return false;
  2415. }
  2416. #endregion
  2417. //-------------------------------------------------------------------------------------------------------//
  2418. #region Environment
  2419. private HashMap<string, EnvironmentVar> EnvironmentVarMap = new HashMap<string, EnvironmentVar>();
  2420. public void AddEnvironmentVar(string key, object value, bool syncToClient)
  2421. {
  2422. if (!string.IsNullOrEmpty(key))
  2423. {
  2424. EnvironmentVar var = EnvironmentVarMap.Get(key);
  2425. if (var != null)
  2426. {
  2427. if (EnvironmentVar.ALWAYS_SYNC_ENVIRONMENT_VAR || (var.SyncToClient && var.Value != value))
  2428. {
  2429. queueEvent(new SyncEnvironmentVarEvent(key, value));
  2430. }
  2431. var.Value = value;
  2432. }
  2433. else
  2434. {
  2435. var = new EnvironmentVar(key, syncToClient, value);
  2436. EnvironmentVarMap.Add(key, var);
  2437. if (EnvironmentVar.ALWAYS_SYNC_ENVIRONMENT_VAR || var.SyncToClient)
  2438. {
  2439. queueEvent(new SyncEnvironmentVarEvent(key, value));
  2440. }
  2441. }
  2442. }
  2443. }
  2444. public void SetEnvironmentVar(string key, object value)
  2445. {
  2446. if (!string.IsNullOrEmpty(key))
  2447. {
  2448. EnvironmentVar var = EnvironmentVarMap.Get(key);
  2449. if (var != null)
  2450. {
  2451. if (EnvironmentVar.ALWAYS_SYNC_ENVIRONMENT_VAR || (var.SyncToClient && var.Value != value))
  2452. {
  2453. queueEvent(new SyncEnvironmentVarEvent(key, value));
  2454. }
  2455. var.Value = value;
  2456. }
  2457. }
  2458. }
  2459. public T GetEnvironmentVarAs<T>(string key)
  2460. {
  2461. if (!string.IsNullOrEmpty(key))
  2462. {
  2463. EnvironmentVar var = EnvironmentVarMap.Get(key);
  2464. if (var != null)
  2465. {
  2466. try
  2467. {
  2468. return (T)var.Value;
  2469. }
  2470. catch (Exception err)
  2471. {
  2472. log.Warn("GetEnvironmentVarAs : " + key + ", catch: " + err);
  2473. }
  2474. }
  2475. }
  2476. return default(T);
  2477. }
  2478. public int ListEnvironmentVars(List<EnvironmentVar> list)
  2479. {
  2480. list.AddRange(EnvironmentVarMap.Values);
  2481. return EnvironmentVarMap.Count;
  2482. }
  2483. public ClientStruct.ZoneEnvironmentVar[] GetCurrentZoneVars()
  2484. {
  2485. ClientStruct.ZoneEnvironmentVar[] ret = new ClientStruct.ZoneEnvironmentVar[EnvironmentVarMap.Count];
  2486. int i = 0;
  2487. foreach (EnvironmentVar var in EnvironmentVarMap.Values)
  2488. {
  2489. ret[i] = new ClientStruct.ZoneEnvironmentVar();
  2490. ret[i].Key = var.Key;
  2491. ret[i].Value = var.Value;
  2492. ret[i].SyncToClient = var.SyncToClient;
  2493. i++;
  2494. }
  2495. return ret;
  2496. }
  2497. protected void BindZoneVar(ZoneVar var, BindValuesAdapter api)
  2498. {
  2499. if (string.IsNullOrEmpty(var.Key))
  2500. {
  2501. // Error
  2502. return;
  2503. }
  2504. if (var.Value is IEditorValue)
  2505. {
  2506. IEditorValue evalue = (var.Value as IEditorValue);
  2507. AddEnvironmentVar(var.Key, evalue.GetEnvValue(api), var.SyncToClient);
  2508. }
  2509. else if (var.Value is Array)
  2510. {
  2511. Array array = var.Value as Array;
  2512. for (int i = 0; i < array.Length; i++)
  2513. {
  2514. object e = array.GetValue(i);
  2515. if (e is IEditorValue)
  2516. {
  2517. string key = string.Format(var.Key + "[{0}]", i);
  2518. IEditorValue evalue = (e as IEditorValue);
  2519. AddEnvironmentVar(key, evalue.GetEnvValue(api), var.SyncToClient);
  2520. }
  2521. }
  2522. }
  2523. }
  2524. #endregion
  2525. //-------------------------------------------------------------------------------------------------------//
  2526. #region QUEST
  2527. /// <summary>
  2528. /// 【第三方系统通知】任务已接受
  2529. /// </summary>
  2530. /// <param name="playerUUID"></param>
  2531. /// <param name="quest"></param>
  2532. internal void gs_OnQuestAccepted(string playerUUID, string quest)
  2533. {
  2534. queueTask((InstanceZone zone) =>
  2535. {
  2536. InstancePlayer p = getPlayerByUUID(playerUUID);
  2537. if (p != null)
  2538. {
  2539. p.doQuestAccepted(quest);
  2540. if (mOnQuestAccepted != null)
  2541. mOnQuestAccepted.Invoke(p, quest);
  2542. }
  2543. });
  2544. }
  2545. /// <summary>
  2546. /// 【第三方系统通知】任务已完成
  2547. /// </summary>
  2548. /// <param name="playerUUID"></param>
  2549. /// <param name="quest"></param>
  2550. internal void gs_OnQuestCommitted(string playerUUID, string quest)
  2551. {
  2552. queueTask((InstanceZone zone) =>
  2553. {
  2554. InstancePlayer p = getPlayerByUUID(playerUUID);
  2555. if (p != null)
  2556. {
  2557. if (mOnQuestCommitted != null)
  2558. mOnQuestCommitted.Invoke(p, quest);
  2559. p.doQuestCommitted(quest);
  2560. }
  2561. });
  2562. }
  2563. /// <summary>
  2564. /// 【第三方系统通知】任务已放弃
  2565. /// </summary>
  2566. /// <param name="playerUUID"></param>
  2567. /// <param name="quest"></param>
  2568. internal void gs_OnQuestDropped(string playerUUID, string quest)
  2569. {
  2570. queueTask((InstanceZone zone) =>
  2571. {
  2572. InstancePlayer p = getPlayerByUUID(playerUUID);
  2573. if (p != null)
  2574. {
  2575. if (mOnQuestDropped != null)
  2576. mOnQuestDropped.Invoke(p, quest);
  2577. p.doQuestDropped(quest);
  2578. }
  2579. });
  2580. }
  2581. /// <summary>
  2582. /// 【第三方系统通知】任务状态已改变
  2583. /// </summary>
  2584. /// <param name="playerUUID"></param>
  2585. /// <param name="quest"></param>
  2586. /// <param name="key"></param>
  2587. /// <param name="value"></param>
  2588. internal void gs_OnQuestStatusChanged(string playerUUID, string quest, string key, string value)
  2589. {
  2590. queueTask((InstanceZone zone) =>
  2591. {
  2592. InstancePlayer p = getPlayerByUUID(playerUUID);
  2593. if (p != null)
  2594. {
  2595. p.doQuestStatusChanged(quest, key, value);
  2596. if (mOnQuestStatusChanged != null)
  2597. mOnQuestStatusChanged.Invoke(p, quest, key, value);
  2598. }
  2599. });
  2600. }
  2601. //给单个玩家发送消息
  2602. internal void doSendMsgToPlayer(InstancePlayer player, CommonLang.Protocol.IMessage msg)
  2603. {
  2604. mQuestAdapter.DoSendMsgToPlayer(player.PlayerUUID, msg);
  2605. }
  2606. /// <summary>
  2607. /// 本地通知游戏服
  2608. /// </summary>
  2609. /// <param name="player"></param>
  2610. /// <param name="quest"></param>
  2611. /// <param name="args"></param>
  2612. internal void doAcceptQuest(InstancePlayer player, string quest, string args)
  2613. {
  2614. mQuestAdapter.DoAcceptQuest(player.PlayerUUID, quest, args);
  2615. }
  2616. /// <summary>
  2617. /// 本地通知游戏服
  2618. /// </summary>
  2619. /// <param name="player"></param>
  2620. /// <param name="quest"></param>
  2621. /// <param name="args"></param>
  2622. internal void doCommitQuest(InstancePlayer player, string quest, string args)
  2623. {
  2624. mQuestAdapter.DoCommitQuest(player.PlayerUUID, quest, args);
  2625. }
  2626. /// <summary>
  2627. /// 本地通知游戏服
  2628. /// </summary>
  2629. /// <param name="player"></param>
  2630. /// <param name="quest"></param>
  2631. /// <param name="args"></param>
  2632. internal void doDropQuest(InstancePlayer player, string quest, string args)
  2633. {
  2634. mQuestAdapter.DoDropQuest(player.PlayerUUID, quest, args);
  2635. }
  2636. /// <summary>
  2637. /// 本地通知游戏服
  2638. /// </summary>
  2639. /// <param name="player"></param>
  2640. /// <param name="quest"></param>
  2641. /// <param name="key"></param>
  2642. /// <param name="value"></param>
  2643. internal void doUpdateQuestStatus(InstancePlayer player, string quest, string key, string value)
  2644. {
  2645. mQuestAdapter.DoUpdateQuestStatus(player.PlayerUUID, quest, key, value);
  2646. }
  2647. #endregion
  2648. //-------------------------------------------------------------------------------------------------------//
  2649. }
  2650. }