From 2bfaf376ef8e8b78911eba008e5e2351c5316501 Mon Sep 17 00:00:00 2001 From: Tahir Akhlaq Date: Tue, 5 Sep 2017 23:32:57 +0100 Subject: [PATCH] moved battlenpc loading to db (still doesnt load for some reason) --- FFXIVClassic Map Server/Database.cs | 47 +--------- FFXIVClassic Map Server/Server.cs | 1 + FFXIVClassic Map Server/WorldManager.cs | 85 ++++++++++++++++++- FFXIVClassic Map Server/actors/area/Area.cs | 7 ++ .../actors/chara/Character.cs | 2 +- .../actors/chara/ai/AIContainer.cs | 2 - .../actors/chara/ai/BattleCommand.cs | 1 - .../actors/chara/ai/PathFind.cs | 3 +- .../ai/controllers/BattleNpcController.cs | 4 - .../chara/ai/controllers/PetController.cs | 2 +- .../chara/ai/controllers/PlayerController.cs | 4 - .../actors/chara/ai/state/AttackState.cs | 6 +- .../actors/chara/ai/state/MagicState.cs | 3 - .../actors/chara/ai/state/WeaponSkillState.cs | 3 - .../actors/chara/npc/BattleNpc.cs | 1 + FFXIVClassic Map Server/lua/LuaEngine.cs | 2 +- sql/server_battlenpc_groups.sql | 2 +- sql/server_battlenpc_spawn_locations.sql | 5 +- 18 files changed, 107 insertions(+), 73 deletions(-) diff --git a/FFXIVClassic Map Server/Database.cs b/FFXIVClassic Map Server/Database.cs index 214abd12..995cdf20 100644 --- a/FFXIVClassic Map Server/Database.cs +++ b/FFXIVClassic Map Server/Database.cs @@ -12,6 +12,8 @@ using FFXIVClassic_Map_Server.Actors; using FFXIVClassic_Map_Server.actors.chara.player; using FFXIVClassic_Map_Server.packets.receive.supportdesk; using FFXIVClassic_Map_Server.actors.chara.ai; +using FFXIVClassic_Map_Server.Actors.Chara; +using FFXIVClassic_Map_Server.actors.chara; namespace FFXIVClassic_Map_Server { @@ -2208,51 +2210,6 @@ namespace FFXIVClassic_Map_Server } return battleCommands; } - - public static Dictionary LoadBattleNpcList(uint zoneId) - { - Dictionary battleNpcList = new Dictionary(); - - using (MySqlConnection conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD))) - { - try - { - conn.Open(); - var query = @""; - /* - var query = @"SELECT bsl.uniqueId, bsl.groupId, bsl.positionX, bls.positionY, bsl.positionZ, " + - @"bgr.groupId, bgr.genusId, bgr.actorClassId, bgr.minLevel, bgr.maxLevel, bgr.respawnTime, " + - @"bgr.hp, bgr.mp, bgr.skillListId, bgr.spellListId, bgr.dropListId, bgr.allegiance, " + - @"bgr.spawnType, bgr.animationId, bgr.actorState, bgr.privateAreaName, bgr.privateAreaLevel, bgr.zoneId, " + - @"bge.genusId, bge.modelSize, bge.kindredId, bge.detection, bge.hpp, bge.mpp, bge.tpp, bge.str, bge.vit, bge.dex, " + - @"bge.int, bge.mnd, bge.pie, bge.att, bge.acc, bge.def, bge.eva, bge.slash, bge.pierce, bge.h2h, bge.blunt, " + - @"bge.fire, bge.ice, bge.wind, bge.lightning, bge.earth, bge.water FROM " + - @"server_battlenpc_spawn_locations bsl INNER JOIN server_battlenpc_groups bgr ON bsl.groupId = bgr.groupId INNER JOIN " + - @"server_battlenpc_genus bge ON bgr.genusId = bgr.genusId INNER JOIN WHERE bgr.zoneId = @zoneId"; - */ - MySqlCommand cmd = new MySqlCommand(query, conn); - cmd.Parameters.AddWithValue("@zoneId", zoneId); - - cmd.ExecuteNonQuery(); - using (MySqlDataReader reader = cmd.ExecuteReader()) - { - while (reader.Read()) - { - - } - } - } - catch (MySqlException e) - { - Program.Log.Error(e.ToString()); - } - finally - { - conn.Dispose(); - } - } - return battleNpcList; - } } } diff --git a/FFXIVClassic Map Server/Server.cs b/FFXIVClassic Map Server/Server.cs index d1234872..3d0605ee 100644 --- a/FFXIVClassic Map Server/Server.cs +++ b/FFXIVClassic Map Server/Server.cs @@ -53,6 +53,7 @@ namespace FFXIVClassic_Map_Server mWorldManager.LoadSeamlessBoundryList(); mWorldManager.LoadActorClasses(); mWorldManager.LoadSpawnLocations(); + mWorldManager.LoadBattleNpcs(); mWorldManager.SpawnAllActors(); mWorldManager.LoadStatusEffects(); mWorldManager.LoadBattleCommands(); diff --git a/FFXIVClassic Map Server/WorldManager.cs b/FFXIVClassic Map Server/WorldManager.cs index ba77904b..693f8b0f 100644 --- a/FFXIVClassic Map Server/WorldManager.cs +++ b/FFXIVClassic Map Server/WorldManager.cs @@ -24,6 +24,7 @@ using System.Threading; using System.Diagnostics; using FFXIVClassic_Map_Server.actors.director; using FFXIVClassic_Map_Server.actors.chara.ai; +using FFXIVClassic_Map_Server.actors.chara; namespace FFXIVClassic_Map_Server { @@ -418,6 +419,88 @@ namespace FFXIVClassic_Map_Server Program.Log.Info(String.Format("Loaded {0} spawn(s).", count)); } + public void LoadBattleNpcs() + { + using (MySqlConnection conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD))) + { + try + { + conn.Open(); + var query = @" + SELECT bsl.uniqueId, bsl.groupId, bsl.positionX, bsl.positionY, bsl.positionZ, bsl.rotation, + bgr.groupId, bgr.genusId, bgr.actorClassId, bgr.minLevel, bgr.maxLevel, bgr.respawnTime, + bgr.hp, bgr.mp, bgr.skillListId, bgr.spellListId, bgr.dropListId, bgr.allegiance, + bgr.spawnType, bgr.animationId, bgr.actorState, bgr.privateAreaName, bgr.privateAreaLevel, bgr.zoneId, + bge.genusId, bge.modelSize, bge.kindredId, bge.detection, bge.hpp, bge.mpp, bge.tpp, bge.str, bge.vit, bge.dex, + bge.int, bge.mnd, bge.pie, bge.att, bge.acc, bge.def, bge.eva, bge.slash, bge.pierce, bge.h2h, bge.blunt, + bge.fire, bge.ice, bge.wind, bge.lightning, bge.earth, bge.water FROM + server_battlenpc_spawn_locations bsl INNER JOIN server_battlenpc_groups bgr ON bsl.groupId = bgr.groupId INNER JOIN + server_battlenpc_genus bge ON bgr.genusId = bgr.genusId WHERE bgr.zoneId = @zoneId; + "; + foreach (var zone in zoneList.Values) + { + MySqlCommand cmd = new MySqlCommand(query, conn); + cmd.Parameters.AddWithValue("@zoneId", zone.GetZoneID()); + + cmd.ExecuteNonQuery(); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + int actorId = zone.GetActorCount() + 1; + + var battleNpc = new BattleNpc(actorId, Server.GetWorldManager().GetActorClass(reader.GetUInt32("actorClassId")), + reader.GetString("uniqueId"), zone, reader.GetFloat("positionX"), reader.GetFloat("positionY"), reader.GetFloat("positionZ"), reader.GetFloat("rotation"), + reader.GetUInt16("actorState"), reader.GetUInt32("animationId"), ""); + + battleNpc.kindredType = (KindredType)reader.GetUInt32("kindredId"); + battleNpc.npcSpawnType = (NpcSpawnType)reader.GetUInt32("spawnType"); + + // todo: setup private areas and other crap and + // set up rest of stat resists + battleNpc.SetMod((uint)Modifier.Hp, reader.GetUInt32("hp")); + battleNpc.SetMod((uint)Modifier.HpPercent, reader.GetUInt32("hpp")); + battleNpc.SetMod((uint)Modifier.Mp, reader.GetUInt32("mp")); + battleNpc.SetMod((uint)Modifier.MpPercent, reader.GetUInt32("mpp")); + battleNpc.SetMod((uint)Modifier.Tp, reader.GetUInt32("tp")); + battleNpc.SetMod((uint)Modifier.TpPercent, reader.GetUInt32("tpp")); + + battleNpc.SetMod((uint)Modifier.Strength, reader.GetUInt32("str")); + battleNpc.SetMod((uint)Modifier.Vitality, reader.GetUInt32("vit")); + battleNpc.SetMod((uint)Modifier.Dexterity, reader.GetUInt32("dex")); + battleNpc.SetMod((uint)Modifier.Intelligence, reader.GetUInt32("int")); + battleNpc.SetMod((uint)Modifier.Mind, reader.GetUInt32("mnd")); + battleNpc.SetMod((uint)Modifier.Piety, reader.GetUInt32("pie")); + battleNpc.SetMod((uint)Modifier.Attack, reader.GetUInt32("att")); + battleNpc.SetMod((uint)Modifier.Accuracy, reader.GetUInt32("acc")); + battleNpc.SetMod((uint)Modifier.Defense, reader.GetUInt32("def")); + battleNpc.SetMod((uint)Modifier.Evasion, reader.GetUInt32("eva")); + + //battleNpc.SetMod((uint)Modifier.ResistFire, ) + + battleNpc.SetAggroType(reader.GetUInt32("detection")); + + // todo: load spell/skill/drop lists + battleNpc.dropListId = reader.GetUInt32("dropListId"); + battleNpc.spellListId = reader.GetUInt32("spellListId"); + battleNpc.skillListId = reader.GetUInt32("skillListId"); + + zone.AddActorToZone(battleNpc); + } + } + } + } + catch (MySqlException e) + { + Program.Log.Error(e.ToString()); + } + finally + { + conn.Dispose(); + } + } + } + public void SpawnAllActors() { Program.Log.Info("Spawning actors..."); @@ -1013,7 +1096,7 @@ namespace FFXIVClassic_Map_Server public void ZoneThreadLoop(Object state) { - // todo: fuck coroutines, seem to be causing it to hang + // todo: coroutines GetActorInWorld stuff seems to be causing it to hang // todo: spawn new thread for each zone on startup lock (zoneList) { diff --git a/FFXIVClassic Map Server/actors/area/Area.cs b/FFXIVClassic Map Server/actors/area/Area.cs index 5d559f38..dac57595 100644 --- a/FFXIVClassic Map Server/actors/area/Area.cs +++ b/FFXIVClassic Map Server/actors/area/Area.cs @@ -395,6 +395,13 @@ namespace FFXIVClassic_Map_Server.Actors } } + public int GetActorCount() + { + lock (mActorList) + { + return mActorList.Count; + } + } public virtual List GetAllActors() { diff --git a/FFXIVClassic Map Server/actors/chara/Character.cs b/FFXIVClassic Map Server/actors/chara/Character.cs index 5e40cac1..9c046c17 100644 --- a/FFXIVClassic Map Server/actors/chara/Character.cs +++ b/FFXIVClassic Map Server/actors/chara/Character.cs @@ -94,7 +94,7 @@ namespace FFXIVClassic_Map_Server.Actors public Pet pet; - public Dictionary modifiers = new Dictionary(); + private Dictionary modifiers = new Dictionary(); protected ushort hpBase, hpMaxBase, mpBase, mpMaxBase, tpBase; protected BattleTemp baseStats = new BattleTemp(); diff --git a/FFXIVClassic Map Server/actors/chara/ai/AIContainer.cs b/FFXIVClassic Map Server/actors/chara/ai/AIContainer.cs index 65787acb..a666de9d 100644 --- a/FFXIVClassic Map Server/actors/chara/ai/AIContainer.cs +++ b/FFXIVClassic Map Server/actors/chara/ai/AIContainer.cs @@ -11,8 +11,6 @@ using FFXIVClassic_Map_Server.packets.send.actor; // port of ai code in dsp by kjLotus (https://github.com/DarkstarProject/darkstar/blob/master/src/map/ai) namespace FFXIVClassic_Map_Server.actors.chara.ai { - // todo: actually implement stuff - // todo: use spell/ability/ws/mobskill objects instead of looking up ids class AIContainer { private Character owner; diff --git a/FFXIVClassic Map Server/actors/chara/ai/BattleCommand.cs b/FFXIVClassic Map Server/actors/chara/ai/BattleCommand.cs index 974911f9..ef44cffc 100644 --- a/FFXIVClassic Map Server/actors/chara/ai/BattleCommand.cs +++ b/FFXIVClassic Map Server/actors/chara/ai/BattleCommand.cs @@ -158,7 +158,6 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai if (BattleUtils.CalculateSpellCost(user, target, this) > user.GetMP()) { - // todo: error message if (user is Player) ((Player)user).SendGameMessage(Server.GetWorldManager().GetActor(), 32545, 0x20, (uint)id); return false; diff --git a/FFXIVClassic Map Server/actors/chara/ai/PathFind.cs b/FFXIVClassic Map Server/actors/chara/ai/PathFind.cs index 98025a49..7b6e638f 100644 --- a/FFXIVClassic Map Server/actors/chara/ai/PathFind.cs +++ b/FFXIVClassic Map Server/actors/chara/ai/PathFind.cs @@ -14,7 +14,7 @@ using FFXIVClassic_Map_Server.packets.send.actor; namespace FFXIVClassic_Map_Server.actors.chara.ai { - // todo: path flags, check for obstacles etc + // todo: check for obstacles, los, etc public enum PathFindFlags { None, @@ -40,7 +40,6 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai PreparePath(dest.X, dest.Y, dest.Z, stepSize, maxPath, polyRadius); } - // todo: is this class even needed? public void PreparePath(float x, float y, float z, float stepSize = 1.25f, int maxPath = 40, float polyRadius = 0.0f) { var pos = new Vector3(owner.positionX, owner.positionY, owner.positionZ); diff --git a/FFXIVClassic Map Server/actors/chara/ai/controllers/BattleNpcController.cs b/FFXIVClassic Map Server/actors/chara/ai/controllers/BattleNpcController.cs index bda45635..60fba17a 100644 --- a/FFXIVClassic Map Server/actors/chara/ai/controllers/BattleNpcController.cs +++ b/FFXIVClassic Map Server/actors/chara/ai/controllers/BattleNpcController.cs @@ -75,10 +75,6 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers if (owner.GetState() != SetActorStatePacket.MAIN_STATE_ACTIVE) owner.ChangeState(SetActorStatePacket.MAIN_STATE_ACTIVE); - - // todo: check speed/is able to move - // todo: too far, path to player if mob, message if player - // owner.ResetMoveSpeeds(); owner.moveState = 2; lastActionTime = DateTime.Now; battleStartTime = lastActionTime; diff --git a/FFXIVClassic Map Server/actors/chara/ai/controllers/PetController.cs b/FFXIVClassic Map Server/actors/chara/ai/controllers/PetController.cs index dff7bfae..bfcef0ac 100644 --- a/FFXIVClassic Map Server/actors/chara/ai/controllers/PetController.cs +++ b/FFXIVClassic Map Server/actors/chara/ai/controllers/PetController.cs @@ -19,7 +19,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers public override void Update(DateTime tick) { - // todo: handle player stuff on tick + // todo: handle pet stuff on tick } public override void ChangeTarget(Character target) diff --git a/FFXIVClassic Map Server/actors/chara/ai/controllers/PlayerController.cs b/FFXIVClassic Map Server/actors/chara/ai/controllers/PlayerController.cs index 962ad0a8..975fd417 100644 --- a/FFXIVClassic Map Server/actors/chara/ai/controllers/PlayerController.cs +++ b/FFXIVClassic Map Server/actors/chara/ai/controllers/PlayerController.cs @@ -21,10 +21,8 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers public override void Update(DateTime tick) { - // todo: handle player stuff on tick if (owner.newMainState != owner.currentMainState) { - //owner.updateFlags = ActorUpdateFlags.Combat; if (owner.newMainState == SetActorStatePacket.MAIN_STATE_ACTIVE) { owner.Engage(); @@ -48,8 +46,6 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers var canEngage = this.owner.aiContainer.InternalEngage(target); if (canEngage) { - // todo: check speed/is able to move - // todo: too far, path to player if mob, message if player if (owner.statusEffects.HasStatusEffect(StatusEffectId.Sleep)) { // That command cannot be performed. diff --git a/FFXIVClassic Map Server/actors/chara/ai/state/AttackState.cs b/FFXIVClassic Map Server/actors/chara/ai/state/AttackState.cs index aa540f79..f0e8df36 100644 --- a/FFXIVClassic Map Server/actors/chara/ai/state/AttackState.cs +++ b/FFXIVClassic Map Server/actors/chara/ai/state/AttackState.cs @@ -23,12 +23,11 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state ChangeTarget(target); attackTime = startTime; owner.aiContainer.pathFind?.Clear(); - // todo: should handle everything here instead of on next tick.. } public override void OnStart() { - // todo: check within attack range + } public override bool Update(DateTime tick) @@ -150,6 +149,9 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state // todo: shouldnt need to check if owner is dead since all states would be cleared if (owner.aiContainer.IsDead() || target.aiContainer.IsDead()) { + if (owner is BattleNpc) + ((BattleNpc)owner).hateContainer.ClearHate(target); + owner.aiContainer.ChangeTarget(null); return false; } diff --git a/FFXIVClassic Map Server/actors/chara/ai/state/MagicState.cs b/FFXIVClassic Map Server/actors/chara/ai/state/MagicState.cs index 47964a82..9d40df1b 100644 --- a/FFXIVClassic Map Server/actors/chara/ai/state/MagicState.cs +++ b/FFXIVClassic Map Server/actors/chara/ai/state/MagicState.cs @@ -23,14 +23,11 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state { this.startPos = owner.GetPosAsVector3(); this.startTime = DateTime.Now; - // todo: lookup spell from global table this.spell = Server.GetWorldManager().GetBattleCommand(spellId); var returnCode = lua.LuaEngine.CallLuaBattleCommandFunction(owner, spell, "magic", "onMagicPrepare", owner, target, spell); - // todo: check recast if (returnCode == 0 && owner.CanCast(target, spell)) { - // todo: Azia can fix, check the recast time and send error OnStart(); } else diff --git a/FFXIVClassic Map Server/actors/chara/ai/state/WeaponSkillState.cs b/FFXIVClassic Map Server/actors/chara/ai/state/WeaponSkillState.cs index 3ed288e0..4a5558e5 100644 --- a/FFXIVClassic Map Server/actors/chara/ai/state/WeaponSkillState.cs +++ b/FFXIVClassic Map Server/actors/chara/ai/state/WeaponSkillState.cs @@ -20,14 +20,11 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state base(owner, target) { this.startTime = DateTime.Now; - // todo: lookup skill from global table this.skill = Server.GetWorldManager().GetBattleCommand(skillId); var returnCode = lua.LuaEngine.CallLuaBattleCommandFunction(owner, skill, "weaponskill", "onSkillPrepare", owner, target, skill); - // todo: check recast if (returnCode == 0 && owner.CanWeaponSkill(target, skill)) { - // todo: Azia can fix, check the recast time and send error OnStart(); } else diff --git a/FFXIVClassic Map Server/actors/chara/npc/BattleNpc.cs b/FFXIVClassic Map Server/actors/chara/npc/BattleNpc.cs index cf4a30b8..ec6daad3 100644 --- a/FFXIVClassic Map Server/actors/chara/npc/BattleNpc.cs +++ b/FFXIVClassic Map Server/actors/chara/npc/BattleNpc.cs @@ -58,6 +58,7 @@ namespace FFXIVClassic_Map_Server.Actors public Character lastAttacker; + public uint spellListId, skillListId, dropListId; public Dictionary skillList = new Dictionary(); public Dictionary spellList = new Dictionary(); diff --git a/FFXIVClassic Map Server/lua/LuaEngine.cs b/FFXIVClassic Map Server/lua/LuaEngine.cs index 26936b4b..e2373967 100644 --- a/FFXIVClassic Map Server/lua/LuaEngine.cs +++ b/FFXIVClassic Map Server/lua/LuaEngine.cs @@ -175,7 +175,7 @@ namespace FFXIVClassic_Map_Server.lua public static int CallLuaStatusEffectFunction(Character actor, StatusEffect effect, string functionName, params object[] args) { - // todo: this is stupid, load the actual effect crap + // todo: this is stupid, load the actual effect name from db table var name = ((StatusEffectId)effect.GetStatusEffectId()).ToString().ToLower(); string path = $"./scripts/effects/{name}.lua"; diff --git a/sql/server_battlenpc_groups.sql b/sql/server_battlenpc_groups.sql index 2640f895..65b4dc35 100644 --- a/sql/server_battlenpc_groups.sql +++ b/sql/server_battlenpc_groups.sql @@ -20,7 +20,7 @@ CREATE TABLE `server_battlenpc_groups` ( `actorClassId` int(10) unsigned NOT NULL, `minLevel` tinyint(3) unsigned NOT NULL DEFAULT '1', `maxLevel` tinyint(3) unsigned NOT NULL DEFAULT '1', - `respawnTime` int(10) unisgned NOT NULL DEFAULT '10', + `respawnTime` int(10) unsigned NOT NULL DEFAULT '10', `hp` int(10) unsigned NOT NULL DEFAULT '0', `mp` int(10) unsigned NOT NULL DEFAULT '0', `skillListId` int(10) unsigned NOT NULL DEFAULT '0', diff --git a/sql/server_battlenpc_spawn_locations.sql b/sql/server_battlenpc_spawn_locations.sql index 49ad0a0d..ec82c077 100644 --- a/sql/server_battlenpc_spawn_locations.sql +++ b/sql/server_battlenpc_spawn_locations.sql @@ -20,5 +20,6 @@ CREATE TABLE `server_battlenpc_spawn_locations` ( `positionX` float NOT NULL, `positionY` float NOT NULL, `positionZ` float NOT NULL, - `rotation` float NOT NULL, -) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1; + `rotation` float NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */;