123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244 |
- using CommonAI.Zone;
- using CommonAI.Zone.ZoneEditor;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using XmdsCommonServer.Plugin.Scene;
- using CommonAI.Zone.Instance;
- using CommonAI.Zone.Helper;
- using CommonLang;
- using System.Diagnostics;
- using CommonAI.Data;
- namespace XmdsCommonZone.Zones
- {
- /// <summary>
- /// 定时刷宝箱类,最初用于连服宝箱,类似的功能需要继承该类,类似于Zone80001.cs
- /// </summary>
- public class ZoneIntervalRebirthMonster : XmdsServerScene
- {
- private bool initedFromServer = false;
- private TimeTaskMS timeTask = null;
- private int maxMonsterNum = 0;
- private int createMonsterIntervalMS = 0;
- // 按时间从小到大排序 { openTime, closeTime, openTime, closeTime ... }
- private int[] timeOpenCloseList = null;
- // 按概率从小到大排序 {怪物id, 万分比概率, 怪物id,万分比概率 ...}
- private int[] monsterIdProbabilityList = null;
- private List<InstanceUnit> monsterList = new List<InstanceUnit>();
- // monster的出生地坐标列表
- private List<InstanceFlag> usingPointList = new List<InstanceFlag>();
- private List<InstanceFlag> freePointList = new List<InstanceFlag>();
- public ZoneIntervalRebirthMonster(TemplateManager templates, InstanceZoneListener listener, SceneData data, GSCreateAreaData gsData, string bindGameSrvId)
- : base(templates, listener, data, gsData, bindGameSrvId)
- {
- AddEvents();
- }
- /// <summary>
- /// 从游戏服初始化场景数据
- /// </summary>
- /// <param name="timeOpenCloseList">从00点到当前的毫秒数{openTime, closeTime, openTime, closeTime ...}</param>
- /// <param name="monsterIdProbabilityList">monsterId,万分比概率{monsterId, probability, monsterId, probability ...}</param>
- /// <param name="createMonsterIntervalMS">创建Monster的时间间隔,单位毫秒</param>
- /// <param name="maxMonsterCount">创建monster的最大个数</param>
- public void InitSceneDataFromGameServer(int[] timeOpenCloseList, int[] monsterIdProbabilityList, int createMonsterIntervalMS, int maxMonsterNum)
- {
- Debug.Assert(!initedFromServer, "ZoneIntervalRebirthMonster.InitSceneDataFromGameServer already call, can not call it twice");
- initedFromServer = true;
- Log.Error("ZoneIntervalRebirthMonster.InitSceneDataFromGameServer");
- this.timeOpenCloseList = SortListBySecondValue(timeOpenCloseList);
- this.monsterIdProbabilityList = SortListBySecondValue(monsterIdProbabilityList);
- this.createMonsterIntervalMS = createMonsterIntervalMS;
- this.maxMonsterNum = maxMonsterNum;
- AdjustMonsterProbability(this.monsterIdProbabilityList);
-
- if (CheckInOpenTime(0))
- {
- TryCreateAllMonster(null);
- }else
- {
- timeTask = AddTimePeriodicMS(30000, WaitOpenTime);
- }
- }
- private void AdjustMonsterProbability(int[] list)
- {
- float n = 0;
- for (int i = 1; i < list.Length; i += 2)
- {
- n += list[i];
- }
- float scale = 10000f / n;
- int p = 0;
- for (int i = 1; i < list.Length; i += 2)
- {
- list[i] = (int)(list[i] * scale) + p;
- p = list[i];
- }
- list[list.Length - 1] = 10000;
- }
- private int[] SortListBySecondValue(int[] list)
- {
- int listLen = list.Length;
- int[] newList = new int[listLen];
- bool[] freeList = new bool[listLen / 2];
- for (int i = 0; i < listLen / 2; i++)
- freeList[i] = true;
- for (int n = 0; n < listLen; n += 2)
- {
- int tmpIdx = 0, probability = int.MaxValue;
- for (int i = 1; i < listLen; i += 2)
- {
- if (freeList[i/2] && list[i] < probability)
- {
- tmpIdx = i;
- probability = list[i];
- }
- }
- freeList[tmpIdx/2] = false;
- newList[n] = list[tmpIdx - 1];
- newList[n+1] = probability;
- }
- return newList;
- }
- private bool CheckInOpenTime(int offsetMillisecond)
- {
- DateTime datetime = DateTime.Now.AddMilliseconds(offsetMillisecond);
- int time = datetime.Hour * 3600000 + datetime.Minute * 60000 + datetime.Second * 1000 + datetime.Millisecond;
- for (int i = 0; i < timeOpenCloseList.Length; i += 2)
- {
- if (timeOpenCloseList[i] <= time && timeOpenCloseList[i + 1] > time)
- return true;
- }
- return false;
- }
- // 获得到下次开启的MS数
- private int GetDeltaTimeToOpen()
- {
- DateTime datetime = DateTime.Now;
- int time = datetime.Hour * 3600000 + datetime.Minute * 60000 + datetime.Second * 1000 + datetime.Millisecond;
- for (int i = 0; i < timeOpenCloseList.Length; i += 2)
- {
- if (timeOpenCloseList[i] > time)
- return timeOpenCloseList[i] - time;
- else if (timeOpenCloseList[i + 1] > time)
- return 0;
- }
- return 3600000 * 24 - time + timeOpenCloseList[0];
- }
- private void AddEvents()
- {
- OnInit += ZoneIntervalRebirthMonster_OnInit;
- OnUnitDead += ZoneIntervalRebirthMonster_OnUnitDead;
- }
- private void ZoneIntervalRebirthMonster_OnInit(InstanceZone zone)
- {
- Log.Error("ZoneIntervalRebirthMonster.ZoneIntervalRebirthMonster_OnInit");
- int i = 1;
- while(true)
- {
- InstanceFlag flag = getFlag(string.Format("bz{0:00}", i++));
- if (flag == null)
- break;
- freePointList.Add(flag);
- }
-
- // int[] timeList = { 14 * 3600000, 16 * 3600000, 16 * 3600000 + 10 * 60000, 16 * 3600000 + 30 * 60000, 17 * 3600000 , 18 * 3600000 };
- // int[] monsterIdProbablilityList = new int[] { 91110, 6000, 91120,3000, 91130,1000 };
- // InitSceneDataFromGameServer(timeList, monsterIdProbablilityList, 30000, 12);
- }
-
- private void ZoneIntervalRebirthMonster_OnUnitDead(InstanceZone zone, InstanceUnit obj, InstanceUnit attacker)
- {
- int idx = monsterList.FindIndex((unit) => { return obj == unit; });
- if (idx < 0)
- return;
- freePointList.Add(usingPointList[idx]);
- usingPointList.RemoveAt(idx);
- monsterList.RemoveAt(idx);
- if (!CheckInOpenTime(createMonsterIntervalMS))
- {
- if (timeTask != null)
- return;
- timeTask = AddTimePeriodicMS(30000, WaitOpenTime);
- return;
- }
- DelayCall(createMonsterIntervalMS, TryCreateMonster);
- }
- private void DelayCall(int delayMS, TickHandler handler)
- {
- long endTicks = DateTime.Now.Ticks + delayMS * TimeSpan.TicksPerMillisecond;
- AddTimePeriodicMS(1000, (TimeTaskMS task) =>
- {
- if (DateTime.Now.Ticks > endTicks)
- {
- task.Stop();
- handler(null);
- }
- });
- }
- private void WaitOpenTime(TimeTaskMS task)
- {
- if (CheckInOpenTime(0))
- {
- timeTask.Stop();
- timeTask = null;
- TryCreateAllMonster(null);
- }
- }
- private void TryCreateAllMonster(TimeTaskMS task)
- {
- if (monsterList.Count >= maxMonsterNum)
- {
- return;
- }
-
- int n = maxMonsterNum - monsterList.Count;
- Log.Error("ZoneIntervalRebirthMonster TryCreateAllMonster will create count=" + n);
- while (--n >= 0)
- TryCreateMonster(null);
- }
- private void TryCreateMonster(TimeTaskMS task)
- {
- if (monsterList.Count >= maxMonsterNum) return;
- int probalility = RandomN.Next(0, 10000);
- int monsterId = 0;
- for (int i = 1; i < monsterIdProbabilityList.Length; i += 2)
- {
- if (probalility <= monsterIdProbabilityList[i])
- {
- monsterId = monsterIdProbabilityList[i - 1];
- break;
- }
- }
- if (monsterId == 0) return;
- int flagIdx = RandomN.Next(0, freePointList.Count);
- InstanceFlag flag = freePointList[flagIdx];
- InstanceUnit unit = AddUnit(monsterId, null, 1, 0, flag.X, flag.Y, (float)RandomN.NextDouble() * 6.28f);
- if (unit != null)
- {
- monsterList.Add(unit);
- freePointList.RemoveAt(flagIdx);
- usingPointList.Add(flag);
- Log.Error("ZoneIntervalRebirthMonster createMonster count=" + monsterList.Count);
- }
- }
- }
- }
|