diff --git a/FFXIVClassic Map Server/actors/Actor.cs b/FFXIVClassic Map Server/actors/Actor.cs index cce7f1a8..15b70eb3 100644 --- a/FFXIVClassic Map Server/actors/Actor.cs +++ b/FFXIVClassic Map Server/actors/Actor.cs @@ -61,7 +61,7 @@ namespace FFXIVClassic_Map_Server.Actors public List classParams; public List positionUpdates; - public DateTime lastMoveUpdate; + protected DateTime lastUpdateScript; protected DateTime lastUpdate; public Actor target; diff --git a/FFXIVClassic Map Server/actors/area/Area.cs b/FFXIVClassic Map Server/actors/area/Area.cs index 9363319a..2d245fe3 100644 --- a/FFXIVClassic Map Server/actors/area/Area.cs +++ b/FFXIVClassic Map Server/actors/area/Area.cs @@ -421,6 +421,11 @@ namespace FFXIVClassic_Map_Server.Actors return GetAllActors(); } + public virtual List GetAllies() + { + return GetAllActors(); + } + public void BroadcastPacketsAroundActor(Actor actor, List packets) { foreach (SubPacket packet in packets) @@ -662,11 +667,14 @@ namespace FFXIVClassic_Map_Server.Actors { lock (mActorList) { - foreach (Actor a in mActorList.Values) + foreach (Actor a in mActorList.Values.ToList()) a.Update(tick); - var deltaTime = (tick - Program.LastTick).TotalMilliseconds; - LuaEngine.GetInstance().CallLuaFunction(null, this, "onUpdate", true, deltaTime, this); + if ((tick - lastUpdateScript).TotalMilliseconds > 1500) + { + LuaEngine.GetInstance().CallLuaFunctionForReturn(LuaEngine.GetScriptPath(this), "onUpdate", true, this, tick); + lastUpdateScript = tick; + } } } diff --git a/FFXIVClassic Map Server/actors/chara/Character.cs b/FFXIVClassic Map Server/actors/chara/Character.cs index fc71863d..6c497bdf 100644 --- a/FFXIVClassic Map Server/actors/chara/Character.cs +++ b/FFXIVClassic Map Server/actors/chara/Character.cs @@ -136,7 +136,6 @@ namespace FFXIVClassic_Map_Server.Actors this.statusEffects = new StatusEffectContainer(this); // todo: move this somewhere more appropriate - ResetMoveSpeeds(); // todo: base this on equip and shit SetMod((uint)Modifier.AttackRange, 3); SetMod((uint)Modifier.AttackDelay, (Program.Random.Next(30, 60) * 100)); @@ -277,22 +276,8 @@ namespace FFXIVClassic_Map_Server.Actors public void FollowTarget(Actor target, float stepSize = 1.2f, int maxPath = 25, float radius = 0.0f) { - var player = target as Player; - - if (player != null) - { - if (this.target != player) - { - this.target = target; - } - // todo: move this to own function thing - this.oldMoveState = this.moveState; - this.moveState = 2; - updateFlags |= ActorUpdateFlags.Position | ActorUpdateFlags.Speed; - //this.moveSpeeds = player.moveSpeeds; - - PathTo(player.positionX, player.positionY, player.positionZ, stepSize, maxPath, radius); - } + if (target != null) + PathTo(target.positionX, target.positionY, target.positionZ, stepSize, maxPath, radius); } public Int64 GetMod(uint modifier) @@ -654,8 +639,10 @@ namespace FFXIVClassic_Map_Server.Actors // todo: call onAttack/onDamageTaken target.DelHP(action.amount); if (target is BattleNpc) + { ((BattleNpc)target).lastAttacker = this; - + ((BattleNpc)target).hateContainer.UpdateHate(this, action.amount); + } AddTP(115); target.AddTP(100); } @@ -754,7 +741,7 @@ namespace FFXIVClassic_Map_Server.Actors public bool IsMonster() { - return this is BattleNpc && !IsAlly(); + return this is BattleNpc; } public bool IsPet() diff --git a/FFXIVClassic Map Server/actors/chara/ai/HateContainer.cs b/FFXIVClassic Map Server/actors/chara/ai/HateContainer.cs index d5a0904b..47086f68 100644 --- a/FFXIVClassic Map Server/actors/chara/ai/HateContainer.cs +++ b/FFXIVClassic Map Server/actors/chara/ai/HateContainer.cs @@ -39,15 +39,11 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai { if (!HasHateForTarget(target)) hateList.Add(target, new HateEntry(target, 1, 0, true)); - else - Program.Log.Error($"{target.actorName} is already on [{owner.actorId}]{owner.actorName}'s hate list!"); } public void UpdateHate(Character target, int damage) { - if (!HasHateForTarget(target)) - AddBaseHate(target); - + AddBaseHate(target); //hateList[target].volatileEnmity += (uint)damage; hateList[target].cumulativeEnmity += (uint)damage; } @@ -55,13 +51,9 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai public void ClearHate(Character target = null) { if (target != null) - { hateList.Remove(target); - } else - { hateList.Clear(); - } } private void UpdateHate(HateEntry entry) diff --git a/FFXIVClassic Map Server/actors/chara/ai/controllers/BattleNpcController.cs b/FFXIVClassic Map Server/actors/chara/ai/controllers/BattleNpcController.cs index 50280503..19356009 100644 --- a/FFXIVClassic Map Server/actors/chara/ai/controllers/BattleNpcController.cs +++ b/FFXIVClassic Map Server/actors/chara/ai/controllers/BattleNpcController.cs @@ -102,8 +102,6 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers owner.aiContainer.pathFind.PreparePath(owner.spawnX, owner.spawnY, owner.spawnZ, 1.5f, 10); neutralTime = lastActionTime; owner.hateContainer.ClearHate(); - owner.ResetMoveSpeeds(); - owner.moveState = 1; lua.LuaEngine.CallLuaBattleFunction(owner, "onDisengage", owner, target, Utils.UnixTimeStampUTC(lastUpdate)); } @@ -203,7 +201,11 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers } Move(); - lua.LuaEngine.CallLuaBattleFunction(owner, "onCombatTick", owner, owner.target, Utils.UnixTimeStampUTC(tick), contentGroupCharas); + if ((tick - lastCombatTickScript).TotalSeconds > 2) + { + lua.LuaEngine.CallLuaBattleFunction(owner, "onCombatTick", owner, owner.target, Utils.UnixTimeStampUTC(tick), contentGroupCharas); + lastCombatTickScript = tick; + } } protected virtual void Move() diff --git a/FFXIVClassic Map Server/actors/chara/ai/controllers/Controller.cs b/FFXIVClassic Map Server/actors/chara/ai/controllers/Controller.cs index e91bf4ed..ab194953 100644 --- a/FFXIVClassic Map Server/actors/chara/ai/controllers/Controller.cs +++ b/FFXIVClassic Map Server/actors/chara/ai/controllers/Controller.cs @@ -11,6 +11,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers { protected Character owner; + protected DateTime lastCombatTickScript; protected DateTime lastUpdate; public bool canUpdate = true; protected bool autoAttackEnabled = true; diff --git a/FFXIVClassic Map Server/actors/chara/ai/state/AttackState.cs b/FFXIVClassic Map Server/actors/chara/ai/state/AttackState.cs index 0a925e53..79f63178 100644 --- a/FFXIVClassic Map Server/actors/chara/ai/state/AttackState.cs +++ b/FFXIVClassic Map Server/actors/chara/ai/state/AttackState.cs @@ -38,7 +38,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state if (target == null || target.IsDead()) { - if (owner is BattleNpc) + if (owner.IsMonster() || owner.IsAlly()) target = ((BattleNpc)owner).hateContainer.GetMostHatedTarget(); } else @@ -141,7 +141,7 @@ 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.IsDead() || target.IsDead()) { - if (owner is BattleNpc) + if (owner.IsMonster() || owner.IsAlly()) ((BattleNpc)owner).hateContainer.ClearHate(target); owner.aiContainer.ChangeTarget(null); diff --git a/FFXIVClassic Map Server/actors/chara/npc/BattleNpc.cs b/FFXIVClassic Map Server/actors/chara/npc/BattleNpc.cs index 07e8d69d..160f8050 100644 --- a/FFXIVClassic Map Server/actors/chara/npc/BattleNpc.cs +++ b/FFXIVClassic Map Server/actors/chara/npc/BattleNpc.cs @@ -90,12 +90,7 @@ namespace FFXIVClassic_Map_Server.Actors spawnY = posY; spawnZ = posZ; - // todo: read these from db also - detectionType = DetectionType.Sight; - this.moveState = 2; - ResetMoveSpeeds(); despawnTime = 10; - respawnTime = 30; CalculateBaseStats(); } @@ -245,19 +240,7 @@ namespace FFXIVClassic_Map_Server.Actors { if (respawnTime > 0) { - base.Spawn(tick); - - this.isMovingToSpawn = false; - this.ResetMoveSpeeds(); - this.hateContainer.ClearHate(); - zone.BroadcastPacketsAroundActor(this, GetSpawnPackets(null, 0x01)); - zone.BroadcastPacketsAroundActor(this, GetInitPackets()); - charaWork.parameterSave.hp = charaWork.parameterSave.hpMax; - charaWork.parameterSave.mp = charaWork.parameterSave.mpMax; - RecalculateStats(); - - OnSpawn(); - updateFlags |= ActorUpdateFlags.AllNpc; + ForceRespawn(); } } @@ -266,7 +249,6 @@ namespace FFXIVClassic_Map_Server.Actors base.Spawn(Program.Tick); this.isMovingToSpawn = false; - this.ResetMoveSpeeds(); this.hateContainer.ClearHate(); zone.BroadcastPacketsAroundActor(this, GetSpawnPackets(null, 0x01)); zone.BroadcastPacketsAroundActor(this, GetInitPackets()); @@ -316,8 +298,6 @@ namespace FFXIVClassic_Map_Server.Actors } positionUpdates?.Clear(); aiContainer.InternalDie(tick, despawnTime); - this.ResetMoveSpeeds(); - // todo: reset cooldowns lua.LuaEngine.GetInstance().OnSignal("mobkill"); diff --git a/FFXIVClassic Map Server/actors/chara/player/Player.cs b/FFXIVClassic Map Server/actors/chara/player/Player.cs index 5262425c..f71843b8 100644 --- a/FFXIVClassic Map Server/actors/chara/player/Player.cs +++ b/FFXIVClassic Map Server/actors/chara/player/Player.cs @@ -2188,6 +2188,7 @@ namespace FFXIVClassic_Map_Server.Actors // todo: should just make a thing that updates the one slot cause this is dumb as hell UpdateHotbarTimer(spell.id, spell.recastTimeSeconds); + LuaEngine.GetInstance().OnSignal("spellUse"); } public override void OnWeaponSkill(State state, BattleAction[] actions, ref BattleAction[] errors) @@ -2199,8 +2200,16 @@ namespace FFXIVClassic_Map_Server.Actors UpdateHotbarTimer(skill.id, skill.recastTimeSeconds); // todo: this really shouldnt be called on each ws? lua.LuaEngine.CallLuaBattleFunction(this, "onWeaponSkill", this, state.GetTarget(), skill); + LuaEngine.GetInstance().OnSignal("weaponskillUse"); } - + + public override void OnAbility(State state, BattleAction[] actions, ref BattleAction[] errors) + { + base.OnAbility(state, actions, ref errors); + + LuaEngine.GetInstance().OnSignal("abilityUse"); + } + //Handles exp being added, does not handle figuring out exp bonus from buffs or skill/link chains or any of that public void AddExp(int exp, byte classId, int bonusPercent = 0) { diff --git a/FFXIVClassic Map Server/lua/LuaEngine.cs b/FFXIVClassic Map Server/lua/LuaEngine.cs index 7de47460..7d28ab28 100644 --- a/FFXIVClassic Map Server/lua/LuaEngine.cs +++ b/FFXIVClassic Map Server/lua/LuaEngine.cs @@ -259,7 +259,7 @@ namespace FFXIVClassic_Map_Server.lua return -1; } - private static string GetScriptPath(Actor target) + public static string GetScriptPath(Actor target) { if (target is Player) { diff --git a/data/scripts/ally.lua b/data/scripts/ally.lua index b8c39ff3..c8625288 100644 --- a/data/scripts/ally.lua +++ b/data/scripts/ally.lua @@ -36,21 +36,22 @@ end function allyGlobal.HelpPlayers(ally, contentGroupCharas, pickRandomTarget) if contentGroupCharas then - for _, chara in pairs(contentGroupCharas) do + print("assssss") if chara then -- probably a player, or another ally -- todo: queue support actions, heal, try pull hate off player etc - if chara.IsPlayer() then + if chara:IsPlayer() then -- do stuff - if not ally.IsEngaged() then - if chara.IsEngaged() then + if not ally:IsEngaged() then + if chara:IsEngaged() then + print("ass") allyGlobal.EngageTarget(ally, chara.target, nil) + return true end end - elseif chara.IsMonster() and chara.IsEngaged() then - if not ally.IsEngaged() then - allyGlobal.EngageTarget(ally, chara.target, nil) - end + elseif chara:IsMonster() and chara:IsEngaged() then + allyGlobal.EngageTarget(ally, chara, nil) + return true end end end @@ -67,14 +68,15 @@ end function allyGlobal.EngageTarget(ally, target, contentGroupCharas) if contentGroupCharas then - for _, chara in pairs(contentGroupCharas) do + for chara in contentGroupCharas do if chara.IsMonster() then if chara.allegiance ~= ally.allegiance then - ally.Engage(chara) + ally:Engage(chara) end end end elseif target then - ally.Engage(target) + ally:Engage(target) + ally.hateContainer:AddBaseHate(target); end end \ No newline at end of file diff --git a/data/scripts/content/SimpleContent30010.lua b/data/scripts/content/SimpleContent30010.lua index 6f1a7de6..5894bbf6 100644 --- a/data/scripts/content/SimpleContent30010.lua +++ b/data/scripts/content/SimpleContent30010.lua @@ -1,4 +1,5 @@ require ("global") +require ("ally") require ("modifiers") function onCreate(starterPlayer, contentArea, director) @@ -33,6 +34,42 @@ function onCreate(starterPlayer, contentArea, director) end +function onUpdate(area, tick) + local players = area:GetPlayers() + local mobs = area:GetMonsters() + local allies = area:GetAllies() + local resumeChecks = true + for player in players do + if player then + local exitLoop = false + for ally in allies do + if ally then + if not ally:IsEngaged() then + if player:IsEngaged() then + ally.neutral = false + ally.isAutoAttackEnabled = true + ally:SetMod(modifiersGlobal.Speed, 8) + allyGlobal.EngageTarget(ally, player.target) + exitLoop = true + break + -- todo: support scripted paths + elseif ally:GetSpeed() > 0 then + + end + end + end + end + if exitLoop then + resumeChecks = false + break + end + end + end + if not resumeChecks then + return + end +end + function onDestroy() diff --git a/data/scripts/unique/fst0Battle03/Monster/bloodthirsty_wolf.lua b/data/scripts/unique/fst0Battle03/Monster/bloodthirsty_wolf.lua index e69de29b..a4e24895 100644 --- a/data/scripts/unique/fst0Battle03/Monster/bloodthirsty_wolf.lua +++ b/data/scripts/unique/fst0Battle03/Monster/bloodthirsty_wolf.lua @@ -0,0 +1,22 @@ +require ("modifiers") + +function onSpawn(mob) + mob:SetMod(modifiersGlobal.Speed, 0) +end + +function onDamageTaken(mob, attacker, damage) + if not attacker:IsPlayer() and mob:GetHP() - damage < 0 then + mob:addHP(damage) + end +end + +function onCombatTick(mob, target, tick, contentGroupCharas) + if mob:GetSpeed() == 0 then + mob:SetMod(modifiersGlobal.Speed, 8) + end +end + +function onDisengage(mob) + mob:SetMod(modifiersGlobal.Speed, 0) + mob:Despawn() +end \ No newline at end of file diff --git a/data/scripts/unique/fst0Battle03/Monster/papalymo.lua b/data/scripts/unique/fst0Battle03/Monster/papalymo.lua index cc9807e1..ca9e38ca 100644 --- a/data/scripts/unique/fst0Battle03/Monster/papalymo.lua +++ b/data/scripts/unique/fst0Battle03/Monster/papalymo.lua @@ -1,4 +1,5 @@ require ("global") +require ("modifiers") require ("ally") function onSpawn(ally) @@ -6,17 +7,5 @@ function onSpawn(ally) ally:SetHP(ally:GetMaxHP()) ally.isAutoAttackEnabled = false; ally.neutral = false -end - -function onCombatTick(ally, target, tick, contentGroupCharas) - allyGlobal.onCombatTick(ally, target, tick, contentGroupCharas); -end - - -function onRoam(ally, contentGroupCharas) - ally.detectionType = 0xFF - ally.isMovingToSpawn = false - ally.neutral = false - ally.animationId = 0 - allyGlobal.onCombatTick(ally, nil, nil, contentGroupCharas) + ally:SetMod(modifiersGlobal.Speed, 0) end \ No newline at end of file diff --git a/data/scripts/unique/fst0Battle03/Monster/yda.lua b/data/scripts/unique/fst0Battle03/Monster/yda.lua index 0c8a9523..c48a4968 100644 --- a/data/scripts/unique/fst0Battle03/Monster/yda.lua +++ b/data/scripts/unique/fst0Battle03/Monster/yda.lua @@ -1,22 +1,10 @@ require ("global") - require ("ally") function onSpawn(ally) ally:SetMaxHP(69420) ally:SetHP(ally:GetMaxHP()) - ally.isAutoAttackEnabled = false + ally.isAutoAttackEnabled = false; ally.neutral = false + ally:SetMod(modifiersGlobal.Speed, 0) end - -function onCombatTick(ally, target, tick, contentGroupCharas) - allyGlobal.onCombatTick(ally, target, tick, contentGroupCharas) -end - -function onRoam(ally, contentGroupCharas) - ally.detectionType = 0xFF - ally.isMovingToSpawn = false - ally.neutral = false - ally.animationId = 0 - allyGlobal.onCombatTick(ally, contentGroupCharas) -end \ No newline at end of file