public Monster(Int32 UniqId, MonsterInfo aInfo, Generator aGenerator) : base(UniqId) { this.Id = (Int16)aInfo.Id; this.Name = aInfo.Name; this.AIType = aInfo.AIType; mLook = aInfo.Look; this.Level = aInfo.Level; this.CurHP = aInfo.Life; this.MaxHP = aInfo.Life; this.Dexterity = aInfo.Dexterity; this.MinAtk = (Int32)Math.Min(aInfo.MinAtk, aInfo.MaxAtk); this.MaxAtk = (Int32)Math.Max(aInfo.MinAtk, aInfo.MaxAtk); this.Defence = (UInt16)aInfo.Defense; this.Dodge = aInfo.Dodge; this.AtkRange = aInfo.AtkRange; this.ViewRange = aInfo.ViewRange; this.AtkSpeed = aInfo.AtkSpeed; this.MoveSpeed = aInfo.MoveSpeed; this.MagicDef = (Int32)aInfo.MagicDef; this.MagicAtk = (Int32)aInfo.MaxAtk; this.MagicType = (UInt16)aInfo.MagicType; this.MagicLevel = 0; if (aInfo.MagicType != 0) { this.AtkType = 21; } else { this.AtkType = 2; } this.DropMoney = (Int32)aInfo.DropMoney; this.DropHP = (Int32)aInfo.DropHP; this.DropMP = (Int32)aInfo.DropMP; DropArmet = aInfo.DropArmet; DropNecklace = aInfo.DropNecklace; DropArmor = aInfo.DropArmor; DropRing = aInfo.DropRing; DropWeapon = aInfo.DropWeapon; DropShield = aInfo.DropShield; DropShoes = aInfo.DropShoes; mOnDie = aInfo.OnDie; mGenerator = aGenerator; //this.RespawnSpeed = RespawnSpeed; this.Disappeared = false; this.LastDieTime = -1; this.Timer = new Timer(); this.Timer.Interval = 500; this.Timer.Elapsed += new ElapsedEventHandler(Process); this.Brain = new MonsterAI(this, 500, MoveSpeed, AtkSpeed, ViewRange, 5, AtkRange); }
private static void OnTimedEvent(object source) { ScheduleTask task = source as ScheduleTask; if (task is MonsterTask) { MonsterTask monsterTask = task as MonsterTask; if (monsterTask.mapCode == 1) { long ticks1 = TimeUtil.NOW(); SysConOut.WriteLine("----------------------------------时间触发器时间间隔----------------------------" + (ticks1 - ScheduleExecutor2.Instance.Oldticks).ToString()); ScheduleExecutor2.Instance.Oldticks = ticks1; } } if (task.InternalLock.TryEnter()) { bool logRunTime = false; long nowTicks = TimeUtil.CurrentTicksInexact; try { task.run(); } catch (System.Exception ex) { LogManager.WriteLog(LogTypes.Error, string.Format("{0}执行时异常,{1}", task.ToString(), ex.ToString())); } finally { logRunTime = task.InternalLock.Leave(); } if (logRunTime) { long finishTicks = TimeUtil.CurrentTicksInexact; if (finishTicks - nowTicks > TimeUtil.SECOND) { try { MonsterTask monsterTask = task as MonsterTask; if (null != monsterTask) { LogManager.WriteLog(LogTypes.Error, string.Format("{0} mapCode:{1},subMapCode:{2},执行时间:{3}毫秒" , task.ToString(), monsterTask.mapCode, monsterTask.subMapCode, finishTicks - nowTicks)); } else { LogManager.WriteLog(LogTypes.Error, string.Format("{0}执行时间:{1}毫秒", task.ToString(), finishTicks - nowTicks)); } } catch { //写日志异常就不记了 } } } } }
public void ThreadFunction() { while (true) { foreach (var s in TimerDict) { ScheduleTask task = s.Key as ScheduleTask; if (task.InternalLock.TryEnter()) { bool logRunTime = false; long nowTicks = TimeUtil.CurrentTicksInexact; try { task.run(); } catch (System.Exception ex) { LogManager.WriteLog(LogTypes.Error, string.Format("{0}执行时异常,{1}", task.ToString(), ex.ToString())); } finally { logRunTime = task.InternalLock.Leave(); } if (logRunTime) { long finishTicks = TimeUtil.CurrentTicksInexact; if (finishTicks - nowTicks > TimeUtil.SECOND) { try { MonsterTask monsterTask = task as MonsterTask; if (null != monsterTask) { LogManager.WriteLog(LogTypes.Error, string.Format("{0} mapCode:{1},subMapCode:{2},执行时间:{3}毫秒" , task.ToString(), monsterTask.mapCode, monsterTask.subMapCode, finishTicks - nowTicks)); } else { LogManager.WriteLog(LogTypes.Error, string.Format("{0}执行时间:{1}毫秒", task.ToString(), finishTicks - nowTicks)); } } catch { //写日志异常就不记了 } } } } } Thread.Sleep(2000); } }
private static void OnTimedEvent(object source) { ScheduleTask task = source as ScheduleTask; if (task.InternalLock.TryEnter()) { bool logRunTime = false; long nowTicks = TimeUtil.CurrentTicksInexact; try { task.run(); } catch (Exception ex) { LogManager.WriteLog(LogTypes.Error, string.Format("{0}执行时异常,{1}", task.ToString(), ex.ToString()), null, true); } finally { logRunTime = task.InternalLock.Leave(); } if (logRunTime) { long finishTicks = TimeUtil.CurrentTicksInexact; if (finishTicks - nowTicks > 1000L) { try { MonsterTask monsterTask = task as MonsterTask; if (null != monsterTask) { LogManager.WriteLog(LogTypes.Error, string.Format("{0} mapCode:{1},subMapCode:{2},执行时间:{3}毫秒", new object[] { task.ToString(), monsterTask.mapCode, monsterTask.subMapCode, finishTicks - nowTicks }), null, true); } else { LogManager.WriteLog(LogTypes.Error, string.Format("{0}执行时间:{1}毫秒", task.ToString(), finishTicks - nowTicks), null, true); } } catch { } } } } }
/// <summary> /// 周期性任务 /// </summary> /// <param name="task">任务</param> /// <param name="delay">延迟开始时间(毫秒)</param> /// <param name="periodic">间隔周期时间(毫秒)</param> /// <returns></returns> public void scheduleExecute(ScheduleTask task, int delay, int periodic) { if (periodic < 15 || periodic > 86400 * 1000) { throw new Exception("不正确的调度时间间隔periodic = " + periodic); } if (delay <= 0) { delay = periodic; } lock (this) { Timer timer; if (!TimerDict.TryGetValue(task, out timer)) { int szDuetime = Global.GetRandomNumber(delay / 2, delay * 3 / 2); timer = new Timer(OnTimedEvent, task, szDuetime, periodic); TimerDict.Add(task, timer); if (task is MonsterTask) { MonsterTask monsterTask = task as MonsterTask; if (monsterTask.mapCode == 1) { SysConOut.WriteLine(string.Format("Duetime = {0} periodic = {1}", szDuetime, periodic)); } } } else { timer.Change(periodic, periodic); if (task is MonsterTask) { MonsterTask monsterTask = task as MonsterTask; if (monsterTask.mapCode == 1) { SysConOut.WriteLine(string.Format("periodic = {0} periodic = {1}", periodic, periodic)); } } } } }
private static void OnTimedEvent(object source) { ScheduleTask task = source as ScheduleTask; if (task.InternalLock.TryEnter()) { try { task.run(); } catch (System.Exception ex) { LogManager.WriteLog(LogTypes.Error, string.Format("{0}执行时异常,{1}", task.ToString(), ex.ToString())); } finally { task.InternalLock.Leave(); } } else { try { MonsterTask monsterTask = task as MonsterTask; if (null != monsterTask) { LogManager.WriteLog(LogTypes.Error, string.Format("{0}自身执行时间超过设定的时间间隔,本次执行取消,mapCode:{1},subMapCode:{2}" , task.ToString(), monsterTask.mapCode, monsterTask.subMapCode)); } else { LogManager.WriteLog(LogTypes.Error, string.Format("{0}自身执行时间超过设定的时间间隔,本次执行取消", task.ToString())); } } catch { //写日志异常就不记了 } } }
public static void GetMonstersInfo() { sLogger.Info("Loading monsters informations..."); using (var connection = sDefaultPool.GetConnection()) { using (var command = connection.CreateCommand()) { command.CommandText = ( "SELECT `id`, `name`, `type`, `ai_type`, `look`, `level`, `life`, `escape_life`, " + "`attack_user`, `attack_min`, `attack_max`, `defense`, `dexterity`, `dodge`, " + "`magic_type`, `magic_def`, `magic_hitrate`, `view_range`, `attack_range`, " + "`attack_speed`, `move_speed`, `run_speed`, " + "`drop_armet`, `drop_necklace`, `drop_armor`, `drop_ring`, `drop_weapon`, `drop_shield`, `drop_shoes`, " + "`drop_money`, `drop_hp`, `drop_mp`, `extra_exp`, `extra_damage` FROM `monstertype`"); command.Prepare(); sLogger.Debug("Executing SQL: {0}", GetSqlCommand(command)); using (var reader = command.ExecuteReader()) { while (reader.Read()) { MonsterInfo monster_type = new MonsterInfo { Id = reader.GetInt32("id"), Name = reader.GetString("name"), Type = reader.GetByte("type"), AIType = reader.GetByte("ai_type"), Look = reader.GetUInt32("look"), Level = reader.GetByte("level"), Life = reader.GetUInt16("life"), EscapeLife = reader.GetUInt16("escape_life"), AtkUser = reader.GetByte("attack_user"), MinAtk = reader.GetUInt32("attack_min"), MaxAtk = reader.GetUInt32("attack_max"), Defense = reader.GetUInt32("defense"), Dexterity = reader.GetByte("dexterity"), Dodge = reader.GetByte("dodge"), MagicType = reader.GetUInt16("magic_type"), MagicDef = reader.GetUInt32("magic_def"), MagicHitrate = reader.GetUInt32("magic_hitrate"), ViewRange = reader.GetByte("view_range"), AtkRange = reader.GetByte("attack_range"), AtkSpeed = reader.GetUInt16("attack_speed"), MoveSpeed = reader.GetUInt16("move_speed"), RunSpeed = reader.GetUInt16("run_speed"), DropArmet = reader.GetByte("drop_armet"), DropNecklace = reader.GetByte("drop_necklace"), DropArmor = reader.GetByte("drop_armor"), DropRing = reader.GetByte("drop_ring"), DropWeapon = reader.GetByte("drop_weapon"), DropShield = reader.GetByte("drop_shield"), DropShoes = reader.GetByte("drop_shoes"), DropMoney = reader.GetUInt32("drop_money"), DropHP = reader.GetUInt32("drop_hp"), DropMP = reader.GetUInt32("drop_mp"), ExtraExp = reader.GetUInt16("extra_exp"), ExtraDamage = reader.GetUInt16("extra_damage") }; AllMonsters.TryAdd(monster_type.Id, monster_type); } } } } String[] scripts = Directory.GetFiles(Program.RootPath + "/Drops", "*.lua"); for (Int32 i = 0; i < scripts.Length; i++) { FileInfo file = new FileInfo(scripts[i]); Int32 uid = Int32.Parse(file.Name.Replace(".lua", "")); try { MonsterTask task = new MonsterTask(uid, file.FullName); MonsterInfo info; if (AllMonsters.TryGetValue(uid, out info)) { info.OnDie = task; AllMonsters.TryUpdate(uid, info, AllMonsters[uid]); } } catch (SyntaxErrorException exc) { sLogger.Error("Failed to load the task {0}. Error: {1}", uid, exc.Message); } } }
private void AttackObjectsInRange(NecClient client, int damage) { float perHp = 100.0f; //Damage Players in range foreach (NecClient targetClient in client.map.clientLookup.GetAll()) { if (targetClient == client) { continue; //skip damaging yourself } if (targetClient.character.partyId == client.character.partyId && client.character.partyId != 0) { continue; //skip damaging party members } //if (targetClient.Soul.CriminalLevel == 0 && client.CriminalOnlyDamage == true) continue; //skip attacking non criminal players. TODO double distanceToCharacter = Distance(targetClient.character.x, targetClient.character.y, client.character.x, client.character.y); _Logger.Debug( $"target Character name [{targetClient.character.name}] distanceToCharacter [{distanceToCharacter}] Radius { /*[{monsterSpawn.Radius}]*/" 125 "} {targetClient.character.name}"); if (distanceToCharacter > /*targetClient.Character.Radius +*/ 125) { continue; } if (targetClient.character.hp.depleted) { continue; } damage -= targetClient.character.battleParam.plusPhysicalDefence; if (damage < 0) { damage = 1; //pity damage } targetClient.character.hp.Modify(-damage, client.character.instanceId); perHp = (float)targetClient.character.hp.current / targetClient.character.hp.max * 100; _Logger.Debug( $"CurrentHp [{targetClient.character.hp.current}] MaxHp[{targetClient.character.hp.max}] perHp[{perHp}]"); RecvCharaUpdateHp cHpUpdate = new RecvCharaUpdateHp(targetClient.character.hp.current); _server.router.Send(targetClient, cHpUpdate.ToPacket()); //logic to turn characters to criminals on criminal actions. possibly should move to character task. client.character.criminalState += 1; if ((client.character.criminalState == 1) | (client.character.criminalState == 2) | (client.character.criminalState == 3)) { IBuffer res40 = BufferProvider.Provide(); res40.WriteUInt32(client.character.instanceId); res40.WriteByte(client.character.criminalState); _Logger.Debug($"Setting crime level for Character {client.character.name} to {client.character.criminalState}"); router.Send(client.map, (ushort)AreaPacketId.recv_chara_update_notify_crime_lv, res40, ServerType.Area); //Router.Send(client.Map, (ushort) AreaPacketId.recv_charabody_notify_crime_lv, res40, ServerType.Area, client); } if (client.character.criminalState > 255) { client.character.criminalState = 255; } DamageTheObject(client, targetClient.character.instanceId, damage, perHp); } //Damage Monsters in range foreach (MonsterSpawn monsterSpawn in client.map.monsterSpawns.Values) { double distanceToObject = Distance(monsterSpawn.x, monsterSpawn.y, client.character.x, client.character.y); //_Logger.Debug($"target Monster name [{monsterSpawn.name}] distanceToObject [{distanceToObject}] Radius [{monsterSpawn.radius}] {monsterSpawn.name}"); if (distanceToObject > monsterSpawn.radius * 5 ) //increased hitbox for monsters by a factor of 5. Beetle radius is 40 { continue; } if (monsterSpawn.hp.depleted) { continue; } monsterSpawn.hp.Modify(-damage, client.character.instanceId); perHp = (float)monsterSpawn.hp.current / monsterSpawn.hp.max * 100; _Logger.Debug($"CurrentHp [{monsterSpawn.hp.current}] MaxHp[{monsterSpawn.hp.max}] perHp[{perHp}]"); //just for fun. turn on inactive monsters if (monsterSpawn.active == false) { monsterSpawn.active = true; monsterSpawn.spawnActive = true; if (!monsterSpawn.taskActive) { MonsterTask monsterTask = new MonsterTask(_server, monsterSpawn); if (monsterSpawn.defaultCoords) { monsterTask.monsterHome = monsterSpawn.monsterCoords[0]; } else { monsterTask.monsterHome = monsterSpawn.monsterCoords.Find(x => x.coordIdx == 64); } monsterTask.Start(); } } DamageTheObject(client, monsterSpawn.instanceId, damage, perHp); } //Damage NPCs in range foreach (NpcSpawn npcSpawn in client.map.npcSpawns.Values) { double distanceToObject = Distance(npcSpawn.x, npcSpawn.y, client.character.x, client.character.y); // _Logger.Debug($"target NPC name [{npcSpawn.name}] distanceToObject [{distanceToObject}] Radius [{npcSpawn.radius}] {npcSpawn.name}"); if (distanceToObject > npcSpawn.radius) { continue; } //attacking an NPC is a misdimeanor crime for non-criminals. if ((client.character.criminalState == 0)) { client.character.criminalState += 1; IBuffer res40 = BufferProvider.Provide(); res40.WriteUInt32(client.character.instanceId); res40.WriteByte(client.character.criminalState); router.Send(client.map, (ushort)AreaPacketId.recv_chara_update_notify_crime_lv, res40, ServerType.Area); } DamageTheObject(client, npcSpawn.instanceId, damage, perHp); } }
public void Enter(NecClient client, MapPosition mapPosition = null) { if (client.map != null) { client.map.Leave(client); } client.map = this; _Logger.Info(client, $"Entering Map: {id}:{fullName}"); // If position is passed in use it and set character position, if null then use map default coords // If this isn't set here, the wrong coords are in character until send_movement_info updates it. if (mapPosition != null) { client.character.x = mapPosition.x; client.character.y = mapPosition.y; client.character.z = mapPosition.z; client.character.heading = mapPosition.heading; } //set character coords to default map entry coords If arriving form another map. else if (client.character.mapId != id) { client.character.x = x; client.character.y = y; client.character.z = z; client.character.heading = orientation; } client.character.mapId = id; client.character.mapChange = false; clientLookup.Add(client); _Logger.Debug($"Client Lookup count is now : {clientLookup.GetAll().Count} for map {id} "); _Logger.Debug($"Character State for character {client.character.name} is {client.character.state}"); //Send your character data to the other living or dead players on the map. //on successful map entry, update the client database position if (!_server.database.UpdateCharacter(client.character)) { _Logger.Error("Could not update the database with current known player position"); } if (!_server.database.UpdateSoul(client.soul)) { _Logger.Error("Could not update the database with soul details "); } //ToDo move all this rendering logic to Send_Map_Entry. We dont need a copy of this logic on every map instance. RecvDataNotifyCharaData myCharacterData = new RecvDataNotifyCharaData(client.character, client.soul.name); //dead //you are dead here. only getting soul form characters. sorry bro. if (client.character.state.HasFlag(CharacterState.SoulForm)) { foreach (NecClient otherClient in clientLookup.GetAll()) { if (otherClient == client) { continue; } if (otherClient.character.state.HasFlag(CharacterState.SoulForm)) { _server.router.Send(myCharacterData, otherClient); } } } else //Bro, you alive! You gon see living characters! { foreach (NecClient otherClient in clientLookup.GetAll()) { if (otherClient == client) { continue; } if (otherClient.character.state.HasFlag(CharacterState.SoulForm)) { continue; } _server.router.Send(myCharacterData, otherClient); } } if (client.union != null) { RecvDataNotifyUnionData myUnionData = new RecvDataNotifyUnionData(client.character, client.union.name); _server.router.Send(this, myUnionData, client); } Task.Delay(TimeSpan.FromSeconds(10)).ContinueWith (t1 => { foreach (MonsterSpawn monsterSpawn in monsterSpawns.Values) { if (monsterSpawn.active) { monsterSpawn.spawnActive = true; if (!monsterSpawn.taskActive) { MonsterTask monsterTask = new MonsterTask(_server, monsterSpawn); if (monsterSpawn.defaultCoords) { monsterTask.monsterHome = monsterSpawn.monsterCoords[0]; } else { monsterTask.monsterHome = monsterSpawn.monsterCoords.Find(x => x.coordIdx == 64); } monsterTask.Start(); } else { if (monsterSpawn.monsterVisible) { _Logger.Debug($"MonsterTask already running for [{monsterSpawn.name}]"); RecvDataNotifyMonsterData monsterData = new RecvDataNotifyMonsterData(monsterSpawn); _server.router.Send(monsterData, client); if (!monsterSpawn.GetAgro()) { monsterSpawn.MonsterMove(_server, client, monsterSpawn.monsterWalkVelocity, 2, 0); } } } } } } ); }
public void Enter(NecClient client, MapPosition mapPosition = null) { if (client.Map != null) { client.Map.Leave(client); } Logger.Info(client, $"Entering Map: {Id}:{FullName}"); // If position is passed in use it and set character position, if null then use map default coords // If this isn't set here, the wrong coords are in character until send_movement_info updates it. if (mapPosition != null) { client.Character.X = mapPosition.X; client.Character.Y = mapPosition.Y; client.Character.Z = mapPosition.Z; client.Character.Heading = mapPosition.Heading; } else { client.Character.X = this.X; client.Character.Y = this.Y; client.Character.Z = this.Z; client.Character.Heading = this.Orientation; } client.Map = this; client.Character.MapId = Id; client.Character.mapChange = false; ClientLookup.Add(client); Logger.Debug($"Client Lookup count is now : {ClientLookup.GetAll().Count} for map {this.Id} "); RecvDataNotifyCharaData myCharacterData = new RecvDataNotifyCharaData(client.Character, client.Soul.Name); _server.Router.Send(this, myCharacterData, client); if (client.Union != null) { RecvDataNotifyUnionData myUnionData = new RecvDataNotifyUnionData(client.Character, client.Union.Name); _server.Router.Send(this, myUnionData, client); } foreach (MonsterSpawn monsterSpawn in this.MonsterSpawns.Values) { if (monsterSpawn.Active == true) { monsterSpawn.SpawnActive = true; if (!monsterSpawn.TaskActive) { MonsterTask monsterTask = new MonsterTask(_server, monsterSpawn); if (monsterSpawn.defaultCoords) { monsterTask.monsterHome = monsterSpawn.monsterCoords[0]; } else { monsterTask.monsterHome = monsterSpawn.monsterCoords.Find(x => x.CoordIdx == 64); } monsterTask.Start(); } else { if (monsterSpawn.MonsterVisible) { Logger.Debug($"MonsterTask already running for [{monsterSpawn.Name}]"); RecvDataNotifyMonsterData monsterData = new RecvDataNotifyMonsterData(monsterSpawn); _server.Router.Send(monsterData, client); if (!monsterSpawn.GetAgro()) { monsterSpawn.MonsterMove(_server, client, monsterSpawn.MonsterWalkVelocity, (byte)2, (byte)0); } } } } } //on successful map entry, update the client database position if (!_server.Database.UpdateCharacter(client.Character)) { Logger.Error("Could not update the database with current known player position"); } }