1
Fork 0
mirror of https://bitbucket.org/Ioncannon/project-meteor-server.git synced 2025-04-23 05:07:47 +00:00

moved battlenpc loading to db (still doesnt load for some reason)

This commit is contained in:
Tahir Akhlaq 2017-09-05 23:32:57 +01:00
parent 68a2d5f0b9
commit 2bfaf376ef
18 changed files with 107 additions and 73 deletions

View file

@ -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<uint, BattleNpc> LoadBattleNpcList(uint zoneId)
{
Dictionary<uint, BattleNpc> battleNpcList = new Dictionary<uint, BattleNpc>();
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;
}
}
}

View file

@ -53,6 +53,7 @@ namespace FFXIVClassic_Map_Server
mWorldManager.LoadSeamlessBoundryList();
mWorldManager.LoadActorClasses();
mWorldManager.LoadSpawnLocations();
mWorldManager.LoadBattleNpcs();
mWorldManager.SpawnAllActors();
mWorldManager.LoadStatusEffects();
mWorldManager.LoadBattleCommands();

View file

@ -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)
{

View file

@ -395,6 +395,13 @@ namespace FFXIVClassic_Map_Server.Actors
}
}
public int GetActorCount()
{
lock (mActorList)
{
return mActorList.Count;
}
}
public virtual List<Actor> GetAllActors()
{

View file

@ -94,7 +94,7 @@ namespace FFXIVClassic_Map_Server.Actors
public Pet pet;
public Dictionary<Modifier, Int64> modifiers = new Dictionary<Modifier, long>();
private Dictionary<Modifier, Int64> modifiers = new Dictionary<Modifier, long>();
protected ushort hpBase, hpMaxBase, mpBase, mpMaxBase, tpBase;
protected BattleTemp baseStats = new BattleTemp();

View file

@ -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;

View file

@ -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;

View file

@ -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);

View file

@ -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;

View file

@ -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)

View file

@ -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.

View file

@ -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;
}

View file

@ -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

View file

@ -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

View file

@ -58,6 +58,7 @@ namespace FFXIVClassic_Map_Server.Actors
public Character lastAttacker;
public uint spellListId, skillListId, dropListId;
public Dictionary<uint, BattleCommand> skillList = new Dictionary<uint, BattleCommand>();
public Dictionary<uint, BattleCommand> spellList = new Dictionary<uint, BattleCommand>();

View file

@ -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";

View file

@ -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',

View file

@ -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 */;