diff --git a/FFXIVClassic Common Class Lib/FFXIVClassic Common Class Lib.csproj b/FFXIVClassic Common Class Lib/FFXIVClassic Common Class Lib.csproj
index b30b954f..a2c8c826 100644
--- a/FFXIVClassic Common Class Lib/FFXIVClassic Common Class Lib.csproj
+++ b/FFXIVClassic Common Class Lib/FFXIVClassic Common Class Lib.csproj
@@ -10,7 +10,7 @@
Properties
FFXIVClassic.Common
FFXIVClassic.Common
- v4.5
+ v4.5.1
512
@@ -38,6 +38,26 @@
false
true
+
+ true
+ bin\Debug\
+ DEBUG;TRACE
+ true
+ full
+ x64
+ prompt
+ MinimumRecommendedRules.ruleset
+
+
+ bin\x64\Release\
+ TRACE
+ true
+ true
+ pdbonly
+ x64
+ prompt
+ MinimumRecommendedRules.ruleset
+
..\packages\DotNetZip.1.10.1\lib\net20\DotNetZip.dll
@@ -90,4 +110,4 @@
-->
-
+
\ No newline at end of file
diff --git a/FFXIVClassic Common Class Lib/app.config b/FFXIVClassic Common Class Lib/app.config
index 143834c2..e418f4e3 100644
--- a/FFXIVClassic Common Class Lib/app.config
+++ b/FFXIVClassic Common Class Lib/app.config
@@ -1,9 +1,9 @@
-
+
-
-
+
+
-
\ No newline at end of file
+
diff --git a/FFXIVClassic Lobby Server/FFXIVClassic Lobby Server.csproj b/FFXIVClassic Lobby Server/FFXIVClassic Lobby Server.csproj
index 962c3676..ddd0697a 100644
--- a/FFXIVClassic Lobby Server/FFXIVClassic Lobby Server.csproj
+++ b/FFXIVClassic Lobby Server/FFXIVClassic Lobby Server.csproj
@@ -10,7 +10,7 @@
Properties
FFXIVClassic_Lobby_Server
FFXIVClassic_Lobby_Server
- v4.5
+ v4.5.1
512
false
publish\
@@ -28,6 +28,7 @@
false
true
cc1ba6f5
+
AnyCPU
@@ -50,6 +51,28 @@
4
true
+
+ true
+ bin\Debug\
+ DEBUG;TRACE
+ true
+ full
+ x64
+ prompt
+ MinimumRecommendedRules.ruleset
+ true
+
+
+ bin\x64\Release\
+ TRACE
+ true
+ true
+ pdbonly
+ x64
+ prompt
+ MinimumRecommendedRules.ruleset
+ true
+
..\packages\Cyotek.CircularBuffer.1.0.0.0\lib\net20\Cyotek.Collections.Generic.CircularBuffer.dll
diff --git a/FFXIVClassic Lobby Server/app.config b/FFXIVClassic Lobby Server/app.config
index 143834c2..e418f4e3 100644
--- a/FFXIVClassic Lobby Server/app.config
+++ b/FFXIVClassic Lobby Server/app.config
@@ -1,9 +1,9 @@
-
+
-
-
+
+
-
\ No newline at end of file
+
diff --git a/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj b/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj
index e5f93603..ad15389b 100644
--- a/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj
+++ b/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj
@@ -40,6 +40,28 @@
Always
+
+ true
+ bin\Debug\
+ DEBUG;TRACE
+ true
+ full
+ x64
+ prompt
+ MinimumRecommendedRules.ruleset
+ true
+
+
+ bin\x64\Release\
+ TRACE
+ true
+ true
+ pdbonly
+ x64
+ prompt
+ MinimumRecommendedRules.ruleset
+ true
+
..\packages\Cyotek.CircularBuffer.1.0.0.0\lib\net20\Cyotek.Collections.Generic.CircularBuffer.dll
diff --git a/FFXIVClassic Map Server/WorldManager.cs b/FFXIVClassic Map Server/WorldManager.cs
index 77c61050..2ab4afff 100644
--- a/FFXIVClassic Map Server/WorldManager.cs
+++ b/FFXIVClassic Map Server/WorldManager.cs
@@ -511,7 +511,6 @@ namespace FFXIVClassic_Map_Server
battleNpc.SetMod((uint)Modifier.Defense, reader.GetUInt32("def"));
battleNpc.SetMod((uint)Modifier.Evasion, reader.GetUInt32("eva"));
-
battleNpc.dropListId = reader.GetUInt32("dropListId");
battleNpc.spellListId = reader.GetUInt32("spellListId");
battleNpc.skillListId = reader.GetUInt32("skillListId");
@@ -644,12 +643,48 @@ namespace FFXIVClassic_Map_Server
battleNpc.SetMod((uint)Modifier.Defense, reader.GetUInt32("def"));
battleNpc.SetMod((uint)Modifier.Evasion, reader.GetUInt32("eva"));
+ if (battleNpc.poolMods != null)
+ {
+ foreach (var a in battleNpc.poolMods.mobModList)
+ {
+ battleNpc.SetMobMod(a.Value.id, (long)(a.Value.value));
+ }
+ foreach (var a in battleNpc.poolMods.modList)
+ {
+ battleNpc.SetMod(a.Key, (long)(a.Value.value));
+ }
+ }
+
+ if (battleNpc.genusMods != null)
+ {
+ foreach (var a in battleNpc.genusMods.mobModList)
+ {
+ battleNpc.SetMobMod(a.Key, (long)(a.Value.value));
+ }
+ foreach (var a in battleNpc.genusMods.modList)
+ {
+ battleNpc.SetMod(a.Key, (long)(a.Value.value));
+ }
+ }
+
+ if(battleNpc.spawnMods != null)
+ {
+ foreach (var a in battleNpc.spawnMods.mobModList)
+ {
+ battleNpc.SetMobMod(a.Key, (long)(a.Value.value));
+ }
+
+ foreach (var a in battleNpc.spawnMods.modList)
+ {
+ battleNpc.SetMod(a.Key, (long)(a.Value.value));
+ }
+ }
+
battleNpc.dropListId = reader.GetUInt32("dropListId");
battleNpc.spellListId = reader.GetUInt32("spellListId");
battleNpc.skillListId = reader.GetUInt32("skillListId");
- battleNpc.SetMaxHP(1000);
- battleNpc.SetHP(1000);
battleNpc.SetBattleNpcId(reader.GetUInt32("bnpcId"));
+ battleNpc.SetRespawnTime(reader.GetUInt32("respawnTime"));
battleNpc.CalculateBaseStats();
battleNpc.RecalculateStats();
//battleNpc.SetMod((uint)Modifier.ResistFire, )
@@ -679,7 +714,7 @@ namespace FFXIVClassic_Map_Server
try
{
conn.Open();
- var query = $"SELECT {primaryKey}, modId, modVal, isMobMod FROM {tableName} GROUP BY {primaryKey};";
+ var query = $"SELECT {primaryKey}, modId, modVal, isMobMod FROM {tableName}";
MySqlCommand cmd = new MySqlCommand(query, conn);
@@ -688,9 +723,9 @@ namespace FFXIVClassic_Map_Server
while (reader.Read())
{
var id = reader.GetUInt32(primaryKey);
- ModifierList modList = new ModifierList(id);
+ ModifierList modList = list.TryGetValue(id, out modList) ? modList : new ModifierList(id);
modList.SetModifier(reader.GetUInt16("modId"), reader.GetInt64("modVal"), reader.GetBoolean("isMobMod"));
- list.Add(id, modList);
+ list[id] = modList;
}
}
}
diff --git a/FFXIVClassic Map Server/actors/Actor.cs b/FFXIVClassic Map Server/actors/Actor.cs
index 15b70eb3..4e397668 100644
--- a/FFXIVClassic Map Server/actors/Actor.cs
+++ b/FFXIVClassic Map Server/actors/Actor.cs
@@ -438,9 +438,6 @@ namespace FFXIVClassic_Map_Server.Actors
updateFlags = ActorUpdateFlags.None;
zone.BroadcastPacketsAroundActor(this, packets);
-
- SetActorPropetyPacket hpInfo = new SetActorPropetyPacket("charaWork/exp");
- hpInfo.AddTarget();
}
}
diff --git a/FFXIVClassic Map Server/actors/area/Area.cs b/FFXIVClassic Map Server/actors/area/Area.cs
index 2d245fe3..c44b71d4 100644
--- a/FFXIVClassic Map Server/actors/area/Area.cs
+++ b/FFXIVClassic Map Server/actors/area/Area.cs
@@ -419,8 +419,8 @@ namespace FFXIVClassic_Map_Server.Actors
public virtual List GetMonsters()
{
return GetAllActors();
- }
-
+ }
+
public virtual List GetAllies()
{
return GetAllActors();
@@ -500,8 +500,8 @@ namespace FFXIVClassic_Map_Server.Actors
npc = new Npc(mActorList.Count + 1, actorClass, uniqueId, this, x, y, z, rot, state, animId, null);
npc.LoadEventConditions(actorClass.eventConditions);
- npc.SetMaxHP(300);
- npc.SetHP(300);
+ //npc.SetMaxHP(30000);
+ //npc.SetHP(30000);
AddActorToZone(npc);
@@ -669,12 +669,12 @@ namespace FFXIVClassic_Map_Server.Actors
{
foreach (Actor a in mActorList.Values.ToList())
a.Update(tick);
-
+
if ((tick - lastUpdateScript).TotalMilliseconds > 1500)
{
- LuaEngine.GetInstance().CallLuaFunctionForReturn(LuaEngine.GetScriptPath(this), "onUpdate", true, this, tick);
+ //LuaEngine.GetInstance().CallLuaFunctionForReturn(LuaEngine.GetScriptPath(this), "onUpdate", true, this, tick);
lastUpdateScript = tick;
- }
+ }
}
}
diff --git a/FFXIVClassic Map Server/actors/area/Zone.cs b/FFXIVClassic Map Server/actors/area/Zone.cs
index 1286657f..07c2937f 100644
--- a/FFXIVClassic Map Server/actors/area/Zone.cs
+++ b/FFXIVClassic Map Server/actors/area/Zone.cs
@@ -132,6 +132,18 @@ namespace FFXIVClassic_Map_Server.actors.area
return actor;
}
}
+
+ foreach (List paList in contentAreas.Values)
+ {
+ foreach (PrivateArea pa in paList)
+ {
+ Actor actor = pa.FindActorInArea(id);
+ if (actor != null)
+ return actor;
+ }
+ }
+
+
return null;
}
else
@@ -184,7 +196,7 @@ namespace FFXIVClassic_Map_Server.actors.area
{
if (this.pathCalls > 0)
{
- Program.Log.Debug("Number of pathfinding calls {0} average time {1}ms", pathCalls, (float)(pathCallTime / pathCalls));
+ Program.Log.Debug("Number of pathfinding calls {0} average time {1}ms", pathCalls, (float)(pathCallTime / pathCalls));
}
lastUpdate = tick;
}
diff --git a/FFXIVClassic Map Server/actors/chara/Character.cs b/FFXIVClassic Map Server/actors/chara/Character.cs
index 6c497bdf..491792b0 100644
--- a/FFXIVClassic Map Server/actors/chara/Character.cs
+++ b/FFXIVClassic Map Server/actors/chara/Character.cs
@@ -229,10 +229,10 @@ namespace FFXIVClassic_Map_Server.Actors
public void DoBattleAction(ushort commandId, uint animationId, BattleAction[] actions)
{
int currentIndex = 0;
-
+ //AoE abilities only ever hit 16 people, so we probably won't need this loop anymore
while (true)
{
- if (actions.Length - currentIndex >= 18)
+ if (actions.Length - currentIndex >= 10)
zone.BroadcastPacketAroundActor(this, BattleActionX18Packet.BuildPacket(actorId, animationId, commandId, actions, ref currentIndex));
else if (actions.Length - currentIndex > 1)
zone.BroadcastPacketAroundActor(this, BattleActionX10Packet.BuildPacket(actorId, animationId, commandId, actions, ref currentIndex));
@@ -243,7 +243,9 @@ namespace FFXIVClassic_Map_Server.Actors
}
else
break;
- animationId = 0; //If more than one packet is sent out, only send the animation once to avoid double playing.
+
+ //I think aoe effects play on all hit enemies. Firaga does at least
+ //animationId = 0; //If more than one packet is sent out, only send the animation once to avoid double playing.
}
}
@@ -298,7 +300,7 @@ namespace FFXIVClassic_Map_Server.Actors
public virtual void OnPath(Vector3 point)
{
- lua.LuaEngine.CallLuaBattleFunction(this, "onPath", this, point);
+ //lua.LuaEngine.CallLuaBattleFunction(this, "onPath", this, point);
updateFlags |= ActorUpdateFlags.Position;
this.isAtSpawn = false;
@@ -332,7 +334,7 @@ namespace FFXIVClassic_Map_Server.Actors
if ((updateFlags & ActorUpdateFlags.HpTpMp) != 0)
{
- var propPacketUtil = new ActorPropertyPacketUtil("charaWork.parameterSave", this);
+ var propPacketUtil = new ActorPropertyPacketUtil("charaWork/stateAtQuicklyForAll", this);
propPacketUtil.AddProperty("charaWork.parameterSave.mp");
propPacketUtil.AddProperty("charaWork.parameterSave.mpMax");
@@ -455,6 +457,7 @@ namespace FFXIVClassic_Map_Server.Actors
{
// todo: actual despawn timer
aiContainer.InternalDie(tick, 10);
+ ChangeSpeed(0.0f, 0.0f, 0.0f, 0.0f);
}
public virtual void Despawn(DateTime tick)
@@ -528,6 +531,20 @@ namespace FFXIVClassic_Map_Server.Actors
updateFlags |= ActorUpdateFlags.HpTpMp;
}
+ public void SetMP(uint mp)
+ {
+ charaWork.parameterSave.mpMax = (short)mp;
+ if (mp > charaWork.parameterSave.hpMax[0])
+ SetMaxMP(mp);
+
+ updateFlags |= ActorUpdateFlags.HpTpMp;
+ }
+
+ public void SetMaxMP(uint mp)
+ {
+ charaWork.parameterSave.mp = (short)mp;
+ updateFlags |= ActorUpdateFlags.HpTpMp;
+ }
// todo: the following functions are virtuals since we want to check hidden item bonuses etc on player for certain conditions
public virtual void AddHP(int hp)
{
@@ -547,7 +564,7 @@ namespace FFXIVClassic_Map_Server.Actors
}
}
- public short GetJob()
+ public short GetClass()
{
return charaWork.parameterSave.state_mainSkill[0];
}
@@ -599,8 +616,30 @@ namespace FFXIVClassic_Map_Server.Actors
public void RecalculateStats()
{
- if (GetMod((uint)Modifier.Hp) != 0)
+ uint hpMod = (uint) GetMod((uint)Modifier.Hp);
+ if (hpMod != 0)
{
+ SetMaxHP(hpMod);
+ uint hpp = (uint) GetMod((uint) Modifier.HpPercent);
+ uint hp = hpMod;
+ if(hpp != 0)
+ {
+ hp = (uint) Math.Ceiling(((float)hpp / 100.0f) * hpMod);
+ }
+ SetHP(hp);
+ }
+
+ uint mpMod = (uint)GetMod((uint)Modifier.Mp);
+ if (mpMod != 0)
+ {
+ SetMaxMP(mpMod);
+ uint mpp = (uint)GetMod((uint)Modifier.MpPercent);
+ uint mp = mpMod;
+ if (mpp != 0)
+ {
+ mp = (uint)Math.Ceiling(((float)mpp / 100.0f) * mpMod);
+ }
+ SetMP(mp);
}
// todo: recalculate stats and crap
updateFlags |= ActorUpdateFlags.HpTpMp;
@@ -635,14 +674,8 @@ namespace FFXIVClassic_Map_Server.Actors
//var packet = BattleActionX01Packet.BuildPacket(owner.actorId, owner.actorId, target.actorId, (uint)0x19001000, (uint)0x8000604, (ushort)0x765D, (ushort)BattleActionX01PacketCommand.Attack, (ushort)damage, (byte)0x1);
}
- target.OnDamageTaken(this, action, DamageTakenType.Ability);
// todo: call onAttack/onDamageTaken
- target.DelHP(action.amount);
- if (target is BattleNpc)
- {
- ((BattleNpc)target).lastAttacker = this;
- ((BattleNpc)target).hateContainer.UpdateHate(this, action.amount);
- }
+ BattleUtils.DamageTarget(this, target, action, DamageTakenType.Attack);
AddTP(115);
target.AddTP(100);
}
@@ -651,13 +684,14 @@ namespace FFXIVClassic_Map_Server.Actors
{
var spell = ((MagicState)state).GetSpell();
// damage is handled in script
- this.DelMP(spell.mpCost); // mpCost can be set in script e.g. if caster has something for free spells
+ var spellCost = spell.CalculateCost((uint)this.GetLevel());
+ this.DelMP(spellCost); // mpCost can be set in script e.g. if caster has something for free spells
- foreach (var action in actions)
- zone.FindActorInArea(action.targetId).OnDamageTaken(this, action, DamageTakenType.Magic);
+ foreach (BattleAction action in actions)
+ if (zone.FindActorInArea(action.targetId) is Character chara)
+ BattleUtils.DamageTarget(this, chara, action, DamageTakenType.Magic);
- if (target is BattleNpc)
- ((BattleNpc)target).lastAttacker = this;
+ lua.LuaEngine.GetInstance().OnSignal("spellUsed");
}
public virtual void OnWeaponSkill(State state, BattleAction[] actions, ref BattleAction[] errors)
@@ -666,11 +700,11 @@ namespace FFXIVClassic_Map_Server.Actors
// damage is handled in script
this.DelTP(skill.tpCost);
- foreach (var action in actions)
- zone.FindActorInArea(action.targetId)?.OnDamageTaken(this, action, DamageTakenType.Weaponskill);
+ foreach (BattleAction action in actions)
+ if (zone.FindActorInArea(action.targetId) is Character chara)
+ BattleUtils.DamageTarget(this, chara, action, DamageTakenType.Weaponskill);
- if (target is BattleNpc)
- ((BattleNpc)target).lastAttacker = this;
+ lua.LuaEngine.GetInstance().OnSignal("weaponskillUsed");
}
public virtual void OnAbility(State state, BattleAction[] actions, ref BattleAction[] errors)
@@ -756,22 +790,22 @@ namespace FFXIVClassic_Map_Server.Actors
public bool IsDiscipleOfWar()
{
- return currentJob < CLASSID_THM;
+ return GetClass() < CLASSID_THM;
}
public bool IsDiscipleOfMagic()
{
- return currentJob >= CLASSID_THM && currentJob < CLASSID_CRP;
+ return GetClass() >= CLASSID_THM && currentJob < CLASSID_CRP;
}
public bool IsDiscipleOfHand()
{
- return currentJob >= CLASSID_CRP && currentJob < CLASSID_MIN;
+ return GetClass() >= CLASSID_CRP && currentJob < CLASSID_MIN;
}
public bool IsDiscipleOfLand()
{
- return currentJob >= CLASSID_MIN;
+ return GetClass() >= CLASSID_MIN;
}
#endregion lua helpers
#endregion ai stuff
diff --git a/FFXIVClassic Map Server/actors/chara/ai/controllers/AllyController.cs b/FFXIVClassic Map Server/actors/chara/ai/controllers/AllyController.cs
index 5f748f72..4098e2bb 100644
--- a/FFXIVClassic Map Server/actors/chara/ai/controllers/AllyController.cs
+++ b/FFXIVClassic Map Server/actors/chara/ai/controllers/AllyController.cs
@@ -5,6 +5,7 @@ using System.Text;
using System.Threading.Tasks;
using FFXIVClassic_Map_Server.Actors;
using FFXIVClassic_Map_Server.actors.chara.npc;
+using FFXIVClassic.Common;
namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers
{
@@ -17,10 +18,11 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers
{
this.owner = owner;
}
-
- // server really likes to hang whenever scripts iterate area's actorlist
- protected override void DoCombatTick(DateTime tick, List contentGroupCharas = null)
+
+ protected List GetContentGroupCharas()
{
+ List contentGroupCharas = null;
+
if (owner.currentContentGroup != null)
{
contentGroupCharas = new List(owner.currentContentGroup.GetMemberCount());
@@ -32,20 +34,46 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers
contentGroupCharas.Add(chara);
}
}
+
+ return contentGroupCharas;
+ }
+
+ //Iterate over players in the group and if they are fighting, assist them
+ protected override void TryAggro(DateTime tick)
+ {
+ //lua.LuaEngine.CallLuaBattleFunction(owner, "tryAggro", owner, GetContentGroupCharas());
+
+ foreach(Character chara in GetContentGroupCharas())
+ {
+ if(chara.IsPlayer())
+ {
+ if(owner.aiContainer.GetTargetFind().CanTarget((Character) chara.target) && chara.target is BattleNpc && ((BattleNpc)chara.target).hateContainer.HasHateForTarget(chara))
+ {
+ owner.Engage(chara.target.actorId);
+ owner.hateContainer.AddBaseHate((Character) chara.target);
+ break;
+ }
+ }
+ }
+ //base.TryAggro(tick);
+ }
+
+ // server really likes to hang whenever scripts iterate area's actorlist
+ protected override void DoCombatTick(DateTime tick, List contentGroupCharas = null)
+ {
+ if (contentGroupCharas == null)
+ {
+ contentGroupCharas = GetContentGroupCharas();
+ }
+
base.DoCombatTick(tick, contentGroupCharas);
}
+
protected override void DoRoamTick(DateTime tick, List contentGroupCharas = null)
{
- if (owner.currentContentGroup != null)
+ if (contentGroupCharas == null)
{
- contentGroupCharas = new List(owner.currentContentGroup.GetMemberCount());
- foreach (var charaId in owner.currentContentGroup.GetMembers())
- {
- var chara = owner.zone.FindActorInArea(charaId);
-
- if (chara != null)
- contentGroupCharas.Add(chara);
- }
+ contentGroupCharas = GetContentGroupCharas();
}
base.DoRoamTick(tick, contentGroupCharas);
}
diff --git a/FFXIVClassic Map Server/actors/chara/ai/controllers/BattleNpcController.cs b/FFXIVClassic Map Server/actors/chara/ai/controllers/BattleNpcController.cs
index 19356009..6711ccad 100644
--- a/FFXIVClassic Map Server/actors/chara/ai/controllers/BattleNpcController.cs
+++ b/FFXIVClassic Map Server/actors/chara/ai/controllers/BattleNpcController.cs
@@ -39,12 +39,20 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers
public override void Update(DateTime tick)
{
lastUpdate = tick;
+
// todo: handle aggro/deaggro and other shit here
- if (owner.aiContainer.IsEngaged())
+ if (!owner.aiContainer.IsEngaged())
{
- DoCombatTick(tick);
+ TryAggro(tick);
}
- else if (!owner.IsDead())
+
+ if(owner.aiContainer.IsEngaged())
+ {
+ //DoCombatTick(tick);
+ }
+
+ //Only move if owner isn't dead and is either too far away from their spawn point or is meant to roam
+ if (!owner.IsDead() && (owner.isMovingToSpawn || owner.GetMobMod((uint) MobModifier.Roams) > 0))
{
DoRoamTick(tick);
}
@@ -63,6 +71,38 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers
return false;
}
+ //If the owner isn't moving to spawn, iterate over nearby enemies and
+ //aggro the first one that is within 10 levels and can be detected, then engage
+ protected virtual void TryAggro(DateTime tick)
+ {
+ if (tick >= neutralTime && !owner.isMovingToSpawn)
+ {
+ if (!owner.neutral && owner.IsAlive())
+ {
+ foreach (var chara in owner.zone.GetActorsAroundActor(owner, 50))
+ {
+ if (owner.allegiance == chara.allegiance)
+ continue;
+
+ if (owner.aiContainer.pathFind.AtPoint() && owner.detectionType != DetectionType.None)
+ {
+ uint levelDifference = (uint)Math.Abs(owner.GetLevel() - chara.GetLevel());
+
+ if (levelDifference <= 10 || (owner.detectionType & DetectionType.IgnoreLevelDifference) != 0 && CanAggroTarget(chara))
+ {
+ owner.hateContainer.AddBaseHate(chara);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (owner.hateContainer.GetHateList().Count > 0)
+ {
+ Engage(owner.hateContainer.GetMostHatedTarget());
+ }
+ }
public override bool Engage(Character target)
{
var canEngage = this.owner.aiContainer.InternalEngage(target);
@@ -77,6 +117,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers
owner.ChangeState(SetActorStatePacket.MAIN_STATE_ACTIVE);
owner.moveState = 2;
+ //owner.SetMod((uint)Modifier.Speed, 5);
lastActionTime = DateTime.Now;
battleStartTime = lastActionTime;
// todo: adjust cooldowns with modifiers
@@ -127,12 +168,6 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers
protected virtual void DoRoamTick(DateTime tick, List contentGroupCharas = null)
{
- if (owner.hateContainer.GetHateList().Count > 0)
- {
- Engage(owner.hateContainer.GetMostHatedTarget());
- return;
- }
-
if (tick >= waitTime)
{
neutralTime = tick.AddSeconds(5);
@@ -148,7 +183,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers
}
}
- waitTime = tick.AddSeconds(10);
+ waitTime = tick.AddSeconds(owner.GetMobMod((uint) MobModifier.RoamDelay));
owner.OnRoam(tick);
if (CanMoveForward(0.0f) && !owner.aiContainer.pathFind.IsFollowingPath())
@@ -157,31 +192,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers
owner.aiContainer.pathFind.SetPathFlags(PathFindFlags.None);
owner.aiContainer.pathFind.PathInRange(owner.spawnX, owner.spawnY, owner.spawnZ, 1.5f, 50.0f);
}
- lua.LuaEngine.CallLuaBattleFunction(owner, "onRoam", owner, contentGroupCharas);
- }
-
-
- if (tick >= neutralTime)
- {
- if (!owner.neutral && owner.IsAlive())
- {
- foreach (var chara in owner.zone.GetActorsAroundActor(owner, 50))
- {
- if (owner.allegiance == chara.allegiance)
- continue;
-
- if (!owner.isMovingToSpawn && owner.aiContainer.pathFind.AtPoint() && owner.detectionType != DetectionType.None)
- {
- uint levelDifference = (uint)Math.Abs(owner.GetLevel() - chara.GetLevel());
-
- if (levelDifference <= 10 || (owner.detectionType & DetectionType.IgnoreLevelDifference) != 0 && CanAggroTarget(chara))
- {
- owner.hateContainer.AddBaseHate(chara);
- break;
- }
- }
- }
- }
+ //lua.LuaEngine.CallLuaBattleFunction(owner, "onRoam", owner, contentGroupCharas);
}
if (owner.aiContainer.pathFind.IsFollowingPath() && owner.aiContainer.CanFollowPath())
@@ -200,7 +211,9 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.controllers
return;
}
+
Move();
+
if ((tick - lastCombatTickScript).TotalSeconds > 2)
{
lua.LuaEngine.CallLuaBattleFunction(owner, "onCombatTick", owner, owner.target, Utils.UnixTimeStampUTC(tick), contentGroupCharas);
diff --git a/FFXIVClassic Map Server/actors/chara/ai/helpers/TargetFind.cs b/FFXIVClassic Map Server/actors/chara/ai/helpers/TargetFind.cs
index 585dafb9..ab374ea3 100644
--- a/FFXIVClassic Map Server/actors/chara/ai/helpers/TargetFind.cs
+++ b/FFXIVClassic Map Server/actors/chara/ai/helpers/TargetFind.cs
@@ -159,6 +159,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
///
public void FindWithinArea(Character target, ValidTarget flags, TargetFindAOETarget aoeTarget)
{
+ targets.Clear();
validTarget = flags;
// are we creating aoe circles around target or self
if (aoeTarget == TargetFindAOETarget.Self)
@@ -174,59 +175,63 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
if (masterTarget != null)
targets.Add(masterTarget);
- if (IsPlayer(owner))
+ if (aoeType != TargetFindAOEType.None)
{
- if (masterTarget is Player)
+ if (IsPlayer(owner))
{
- findType = TargetFindCharacterType.PlayerToPlayer;
-
- if (masterTarget.currentParty != null)
+ if (masterTarget is Player)
{
- if ((validTarget & (ValidTarget.Ally | ValidTarget.PartyMember)) != 0)
- AddAllInAlliance(masterTarget, withPet);
+ findType = TargetFindCharacterType.PlayerToPlayer;
+
+ if (masterTarget.currentParty != null)
+ {
+ if ((validTarget & (ValidTarget.Ally | ValidTarget.PartyMember)) != 0)
+ AddAllInAlliance(masterTarget, withPet);
+ else
+ AddAllInParty(masterTarget, withPet);
+ }
else
- AddAllInParty(masterTarget, withPet);
+ {
+ AddTarget(masterTarget, withPet);
+ }
}
else
{
- AddTarget(masterTarget, withPet);
+ findType = TargetFindCharacterType.PlayerToBattleNpc;
+ AddAllBattleNpcs(masterTarget, false);
}
}
else
{
- findType = TargetFindCharacterType.PlayerToBattleNpc;
- AddAllBattleNpcs(masterTarget, false);
- }
- }
- else
- {
- // todo: this needs checking..
- if (masterTarget is Player || owner.allegiance == CharacterTargetingAllegiance.Player)
- findType = TargetFindCharacterType.BattleNpcToPlayer;
- else
- findType = TargetFindCharacterType.BattleNpcToBattleNpc;
-
- // todo: configurable pet aoe buff
- if (findType == TargetFindCharacterType.BattleNpcToBattleNpc && TryGetMasterTarget(target) != null)
- withPet = true;
-
- // todo: does ffxiv have call for help flag?
- //if ((findFlags & ValidTarget.HitAll) != 0)
- //{
- // AddAllInZone(masterTarget, withPet);
- //}
-
- AddAllInAlliance(target, withPet);
-
- if (findType == TargetFindCharacterType.BattleNpcToPlayer)
- {
- if (owner.allegiance == CharacterTargetingAllegiance.Player)
- AddAllInZone(masterTarget, withPet);
+ // todo: this needs checking..
+ if (masterTarget is Player || owner.allegiance == CharacterTargetingAllegiance.Player)
+ findType = TargetFindCharacterType.BattleNpcToPlayer;
else
- AddAllInHateList();
+ findType = TargetFindCharacterType.BattleNpcToBattleNpc;
+
+ // todo: configurable pet aoe buff
+ if (findType == TargetFindCharacterType.BattleNpcToBattleNpc && TryGetMasterTarget(target) != null)
+ withPet = true;
+
+ // todo: does ffxiv have call for help flag?
+ //if ((findFlags & ValidTarget.HitAll) != 0)
+ //{
+ // AddAllInZone(masterTarget, withPet);
+ //}
+
+ AddAllInAlliance(target, withPet);
+
+ if (findType == TargetFindCharacterType.BattleNpcToPlayer)
+ {
+ if (owner.allegiance == CharacterTargetingAllegiance.Player)
+ AddAllInZone(masterTarget, withPet);
+ else
+ AddAllInHateList();
+ }
}
}
-
+ if(targets.Count > 16)
+ targets.RemoveRange(16, targets.Count - 16);
}
///
@@ -288,7 +293,8 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
private void AddAllBattleNpcs(Character target, bool withPet)
{
- var actors = owner.zone.GetActorsAroundActor(owner, 50);
+ int dist = (int)maxDistance;
+ var actors = owner.zone.GetActorsAroundActor(target, dist);
foreach (BattleNpc actor in actors)
{
@@ -375,12 +381,13 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
private bool IsWithinCircle(Character target, float maxDistance)
{
// todo: make y diff modifiable?
- if (Math.Abs(owner.positionX - target.positionY) > 6.0f)
- return false;
+
+ //if (Math.Abs(owner.positionX - target.positionY) > 6.0f)
+ // return false;
if (this.targetPosition == null)
this.targetPosition = aoeTarget == TargetFindAOETarget.Self ? owner.GetPosAsVector3() : masterTarget.GetPosAsVector3();
- return target.GetPosAsVector3().IsWithinCircle(targetPosition, param);
+ return target.GetPosAsVector3().IsWithinCircle(targetPosition, maxDistance);
}
private bool IsPlayer(Character target)
diff --git a/FFXIVClassic Map Server/actors/chara/ai/state/AttackState.cs b/FFXIVClassic Map Server/actors/chara/ai/state/AttackState.cs
index 79f63178..56087d39 100644
--- a/FFXIVClassic Map Server/actors/chara/ai/state/AttackState.cs
+++ b/FFXIVClassic Map Server/actors/chara/ai/state/AttackState.cs
@@ -129,6 +129,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
private bool CanAttack()
{
+ return false;
if (!owner.isAutoAttackEnabled)
{
return false;
diff --git a/FFXIVClassic Map Server/actors/chara/ai/state/DeathState.cs b/FFXIVClassic Map Server/actors/chara/ai/state/DeathState.cs
index 0bb584bf..61d76a62 100644
--- a/FFXIVClassic Map Server/actors/chara/ai/state/DeathState.cs
+++ b/FFXIVClassic Map Server/actors/chara/ai/state/DeathState.cs
@@ -15,7 +15,9 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
: base(owner, null)
{
owner.Disengage();
- owner.ChangeState(SetActorStatePacket.MAIN_STATE_DEAD2);
+ //owner.ChangeState(SetActorStatePacket.MAIN_STATE_DEAD2);
+ var deathStatePacket = SetActorStatePacket.BuildPacket(owner.actorId, SetActorStatePacket.MAIN_STATE_DEAD, owner.currentSubState);
+ owner.zone.BroadcastPacketAroundActor(owner, deathStatePacket);
canInterrupt = false;
startTime = tick;
despawnTime = startTime.AddSeconds(timeToFadeOut);
diff --git a/FFXIVClassic Map Server/actors/chara/ai/state/MagicState.cs b/FFXIVClassic Map Server/actors/chara/ai/state/MagicState.cs
index 9d40df1b..8e28554e 100644
--- a/FFXIVClassic Map Server/actors/chara/ai/state/MagicState.cs
+++ b/FFXIVClassic Map Server/actors/chara/ai/state/MagicState.cs
@@ -110,16 +110,16 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
var i = 0;
foreach (var chara in targets)
{
- var action = new BattleAction(target.actorId, spell.worldMasterTextId, spell.battleAnimation, 0, (byte)HitDirection.None, 1);
+ var action = new BattleAction(chara.actorId, spell.worldMasterTextId, spell.battleAnimation, 0, (byte)HitDirection.None, 1);
action.amount = (ushort)lua.LuaEngine.CallLuaBattleCommandFunction(owner, spell, "magic", "onMagicFinish", owner, chara, spell, action);
actions[i++] = action;
}
// todo: this is fuckin stupid, probably only need *one* error packet, not an error for each action
var errors = (BattleAction[])actions.Clone();
-
owner.OnCast(this, actions, ref errors);
owner.DoBattleAction(spell.id, spell.battleAnimation, actions);
+
}
public override void TryInterrupt()
diff --git a/FFXIVClassic Map Server/actors/chara/ai/state/WeaponSkillState.cs b/FFXIVClassic Map Server/actors/chara/ai/state/WeaponSkillState.cs
index f918c8be..f9bbefad 100644
--- a/FFXIVClassic Map Server/actors/chara/ai/state/WeaponSkillState.cs
+++ b/FFXIVClassic Map Server/actors/chara/ai/state/WeaponSkillState.cs
@@ -88,7 +88,6 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
{
skill.targetFind.FindWithinArea(target, skill.validTarget, skill.aoeTarget);
isCompleted = true;
-
var targets = skill.targetFind.GetTargets();
BattleAction[] actions = new BattleAction[targets.Count];
@@ -100,11 +99,11 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.state
// evasion, miss, dodge, etc to be handled in script, calling helpers from scripts/weaponskills.lua
action.amount = (ushort)lua.LuaEngine.CallLuaBattleCommandFunction(owner, skill, "weaponskill", "onSkillFinish", owner, target, skill, action);
actions[i++] = action;
+ chara.Engage(chara.actorId, 1);
}
// todo: this is fuckin stupid, probably only need *one* error packet, not an error for each action
var errors = (BattleAction[])actions.Clone();
-
owner.OnWeaponSkill(this, actions, ref errors);
owner.DoBattleAction(skill.id, skill.battleAnimation, actions);
}
diff --git a/FFXIVClassic Map Server/actors/chara/ai/utils/BattleUtils.cs b/FFXIVClassic Map Server/actors/chara/ai/utils/BattleUtils.cs
index 37a7197e..ed2a1050 100644
--- a/FFXIVClassic Map Server/actors/chara/ai/utils/BattleUtils.cs
+++ b/FFXIVClassic Map Server/actors/chara/ai/utils/BattleUtils.cs
@@ -76,18 +76,24 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai.utils
return damage;
}
- public static void DamageTarget(Character attacker, Character defender, BattleAction action)
+ public static void DamageTarget(Character attacker, Character defender, BattleAction action, DamageTakenType type)
{
- // todo: other stuff too
- if (defender is BattleNpc)
+ if (defender != null)
{
- if (!((BattleNpc)defender).hateContainer.HasHateForTarget(attacker))
+ // todo: other stuff too
+ if (defender is BattleNpc)
{
- ((BattleNpc)defender).hateContainer.AddBaseHate(attacker);
+ var bnpc = defender as BattleNpc;
+ if (!bnpc.hateContainer.HasHateForTarget(attacker))
+ {
+ bnpc.hateContainer.AddBaseHate(attacker);
+ }
+ bnpc.hateContainer.UpdateHate(attacker, action.amount);
+ bnpc.lastAttacker = attacker;
}
- ((BattleNpc)defender).hateContainer.UpdateHate(attacker, action.amount);
+ defender.DelHP((short)action.amount);
+ defender.OnDamageTaken(attacker, action, type);
}
- defender.DelHP((short)action.amount);
}
public static int CalculateSpellDamage(Character attacker, Character defender, BattleCommand spell)
diff --git a/FFXIVClassic Map Server/actors/chara/npc/BattleNpc.cs b/FFXIVClassic Map Server/actors/chara/npc/BattleNpc.cs
index 160f8050..4b94313a 100644
--- a/FFXIVClassic Map Server/actors/chara/npc/BattleNpc.cs
+++ b/FFXIVClassic Map Server/actors/chara/npc/BattleNpc.cs
@@ -172,7 +172,7 @@ namespace FFXIVClassic_Map_Server.Actors
packets = new List();
if ((updateFlags & ActorUpdateFlags.HpTpMp) != 0)
{
- var propPacketUtil = new ActorPropertyPacketUtil("charaWork.parameterSave", this);
+ var propPacketUtil = new ActorPropertyPacketUtil("charaWork/stateAtQuicklyForAll", this);
propPacketUtil.AddProperty("charaWork.parameterSave.hp[0]");
propPacketUtil.AddProperty("charaWork.parameterSave.hpMax[0]");
@@ -272,6 +272,10 @@ namespace FFXIVClassic_Map_Server.Actors
if (lastAttacker is Player)
{
+ //I think this is, or should be odne in DoBattleAction. Packet capture had the message in the same packet as an attack
+ // defeat/defeats
+ //((Player)lastAttacker).QueuePacket(BattleActionX01Packet.BuildPacket(lastAttacker.actorId, 0, 0, new BattleAction(actorId, 30108, 0)));
+
if (lastAttacker.currentParty != null && lastAttacker.currentParty is Party)
{
foreach (var memberId in ((Party)lastAttacker.currentParty).members)
@@ -279,14 +283,9 @@ namespace FFXIVClassic_Map_Server.Actors
var partyMember = zone.FindActorInArea(memberId);
// onDeath(monster, player, killer)
lua.LuaEngine.CallLuaBattleFunction(this, "onDeath", this, partyMember, lastAttacker);
- // defeat/defeats
-
- if (lastAttacker is Player)
- ((Player)lastAttacker).QueuePacket(BattleActionX01Packet.BuildPacket(lastAttacker.actorId, 0, 0, new BattleAction(actorId, 30108, 0)));
-
- if(partyMember is Player)
- ((Player)partyMember).AddExp(1500, (byte)partyMember.GetJob(), 5);
+ if (partyMember is Player)
+ ((Player)partyMember).AddExp(1500, (byte)partyMember.GetClass(), 5);
}
}
else
@@ -298,6 +297,7 @@ 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/npc/MobModifier.cs b/FFXIVClassic Map Server/actors/chara/npc/MobModifier.cs
index 21a75d53..fe2600e6 100644
--- a/FFXIVClassic Map Server/actors/chara/npc/MobModifier.cs
+++ b/FFXIVClassic Map Server/actors/chara/npc/MobModifier.cs
@@ -32,5 +32,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.npc
AbilityScript = 21, // call my script's onAbility whenever i finish using an ability
CallForHelp = 22, // actor with this id outside of target's party with this can attack me
FreeForAll = 23, // any actor can attack me
+ Roams = 24, // Do I walk around?
+ RoamDelay = 25 // What is the delay between roam ticks
}
}
\ No newline at end of file
diff --git a/FFXIVClassic Map Server/actors/chara/player/Player.cs b/FFXIVClassic Map Server/actors/chara/player/Player.cs
index f71843b8..5ac7fd6d 100644
--- a/FFXIVClassic Map Server/actors/chara/player/Player.cs
+++ b/FFXIVClassic Map Server/actors/chara/player/Player.cs
@@ -557,6 +557,9 @@ namespace FFXIVClassic_Map_Server.Actors
if (currentContentGroup != null)
currentContentGroup.SendGroupPackets(playerSession);
+
+ if (currentParty != null)
+ currentParty.SendGroupPackets(playerSession);
}
private void SendRemoveInventoryPackets(List slots)
@@ -1625,7 +1628,7 @@ namespace FFXIVClassic_Map_Server.Actors
//Update Instance
List aroundMe = new List();
- if (zone != null)
+ if (zone != null)
aroundMe.AddRange(zone.GetActorsAroundActor(this, 50));
if (zone2 != null)
aroundMe.AddRange(zone2.GetActorsAroundActor(this, 50));
@@ -1714,6 +1717,7 @@ namespace FFXIVClassic_Map_Server.Actors
//currentParty.members.Remove(this);
if (partyGroup.members.Count == 0)
Server.GetWorldManager().NoMembersInParty((Party)currentParty);
+
currentParty = null;
}
@@ -1755,7 +1759,7 @@ namespace FFXIVClassic_Map_Server.Actors
if ((updateFlags & ActorUpdateFlags.HpTpMp) != 0)
{
- var propPacketUtil = new ActorPropertyPacketUtil("charaWork.parameterSave", this);
+ var propPacketUtil = new ActorPropertyPacketUtil("charaWork/stateAtQuicklyForAll", this);
// todo: should this be using job as index?
propPacketUtil.AddProperty($"charaWork.parameterSave.hp[{0}]");
@@ -1768,9 +1772,6 @@ namespace FFXIVClassic_Map_Server.Actors
}
base.PostUpdate(tick, packets);
- SetActorPropetyPacket hpInfo = new SetActorPropetyPacket("charaWork/exp");
- hpInfo.AddTarget();
- QueuePacket(hpInfo.BuildPacket(actorId));
}
public override void Die(DateTime tick)
@@ -1801,7 +1802,6 @@ namespace FFXIVClassic_Map_Server.Actors
public void UpdateHotbarCommands(List slotsToUpdate)
{
ActorPropertyPacketUtil propPacketUtil = new ActorPropertyPacketUtil("charaWork/command", this);
- ActorPropertyPacketUtil compatibiltyUtil = new ActorPropertyPacketUtil("charaWork/commandDetailForSelf", this);
foreach (ushort slot in slotsToUpdate)
{
propPacketUtil.AddProperty($"charaWork.command[{slot}]");
@@ -2184,9 +2184,9 @@ namespace FFXIVClassic_Map_Server.Actors
{
// todo: update hotbar timers to skill's recast time (also needs to be done on class change or equip crap)
base.OnCast(state, actions, ref errors);
+
var spell = ((MagicState)state).GetSpell();
- // todo: should just make a thing that updates the one slot cause this is dumb as hell
-
+ // 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");
}
@@ -2309,27 +2309,23 @@ namespace FFXIVClassic_Map_Server.Actors
Database.LoadHotbar(this);
}
+ //Gets the id of the player's current job. If they aren't a job, gets the id of their class
public byte GetCurrentClassOrJob()
{
if (currentJob != 0)
return (byte) currentJob;
-
return charaWork.parameterSave.state_mainSkill[0];
}
public void hpstuff(uint hp)
{
SetMaxHP(hp);
- SetHP(hp);
+ SetHP(hp);
mpMaxBase = (ushort)hp;
charaWork.parameterSave.mpMax = (short)hp;
charaWork.parameterSave.mp = (short)hp;
- AddTP(0);
- //SendCharaExpInfo();
- //ActorPropertyPacketUtil exp = new ActorPropertyPacketUtil("charaWork/exp", this);
- SetActorPropetyPacket hpInfo = new SetActorPropetyPacket("charaWork/exp");
- hpInfo.AddTarget();
- QueuePacket(hpInfo.BuildPacket(actorId));
+ AddTP(3000);
+ updateFlags |= ActorUpdateFlags.HpTpMp;
}
}
diff --git a/FFXIVClassic Map Server/actors/director/Director.cs b/FFXIVClassic Map Server/actors/director/Director.cs
index 04d1740f..e2a566a6 100644
--- a/FFXIVClassic Map Server/actors/director/Director.cs
+++ b/FFXIVClassic Map Server/actors/director/Director.cs
@@ -161,6 +161,9 @@ namespace FFXIVClassic_Map_Server.actors.director
{
members.Add(actor);
+ if (actor is Player)
+ ((Player)actor).AddDirector(this);
+
if (contentGroup != null)
contentGroup.AddMember(actor);
}
diff --git a/FFXIVClassic Map Server/actors/group/ContentGroup.cs b/FFXIVClassic Map Server/actors/group/ContentGroup.cs
index bebeb49c..950bbad0 100644
--- a/FFXIVClassic Map Server/actors/group/ContentGroup.cs
+++ b/FFXIVClassic Map Server/actors/group/ContentGroup.cs
@@ -42,6 +42,7 @@ namespace FFXIVClassic_Map_Server.actors.group
public void Start()
{
isStarted = true;
+
SendGroupPacketsAll(members);
}
@@ -50,7 +51,8 @@ namespace FFXIVClassic_Map_Server.actors.group
if (actor == null)
return;
- members.Add(actor.actorId);
+ if(!members.Contains(actor.actorId))
+ members.Add(actor.actorId);
if (actor is Character)
((Character)actor).SetCurrentContentGroup(this);
@@ -121,7 +123,6 @@ namespace FFXIVClassic_Map_Server.actors.group
}
session.QueuePacket(GroupMembersEndPacket.buildPacket(session.id, session.GetActor().zoneId, time, this));
-
}
public override uint GetTypeId()
diff --git a/FFXIVClassic Map Server/actors/group/Party.cs b/FFXIVClassic Map Server/actors/group/Party.cs
index 436cc9d9..385c5a77 100644
--- a/FFXIVClassic Map Server/actors/group/Party.cs
+++ b/FFXIVClassic Map Server/actors/group/Party.cs
@@ -63,12 +63,24 @@ namespace FFXIVClassic_Map_Server.actors.group
List groupMembers = new List();
groupMembers.Add(new GroupMember(id, -1, 0, false, true, Server.GetWorldManager().GetActorInWorld(id).customDisplayName));
foreach (uint charaId in members)
- {
- if (charaId != id)
- groupMembers.Add(new GroupMember(charaId, -1, 0, false, true, Server.GetWorldManager().GetActorInWorld(charaId).customDisplayName));
+ {
+ var chara = Server.GetWorldManager().GetActorInWorld(charaId);
+ if (charaId != id && chara != null)
+ groupMembers.Add(new GroupMember(charaId, -1, 0, false, true, chara.customDisplayName));
}
return groupMembers;
}
+ public void AddMember(uint memberId)
+ {
+ members.Add(memberId);
+ SendGroupPacketsAll(members);
+ }
+
+ public void RemoveMember(uint memberId)
+ {
+ members.Remove(memberId);
+ SendGroupPacketsAll(members);
+ }
}
}
diff --git a/FFXIVClassic Map Server/dataobjects/ZoneConnection.cs b/FFXIVClassic Map Server/dataobjects/ZoneConnection.cs
index 4a7fcc98..786a604d 100644
--- a/FFXIVClassic Map Server/dataobjects/ZoneConnection.cs
+++ b/FFXIVClassic Map Server/dataobjects/ZoneConnection.cs
@@ -24,7 +24,7 @@ namespace FFXIVClassic_Map_Server.dataobjects
public void FlushQueuedSendPackets()
{
- if (!socket.Connected)
+ if (socket == null || !socket.Connected)
return;
while (SendPacketQueue.Count > 0)
diff --git a/FFXIVClassic Map Server/lua/LuaEngine.cs b/FFXIVClassic Map Server/lua/LuaEngine.cs
index 7d28ab28..d4f50f72 100644
--- a/FFXIVClassic Map Server/lua/LuaEngine.cs
+++ b/FFXIVClassic Map Server/lua/LuaEngine.cs
@@ -478,10 +478,18 @@ namespace FFXIVClassic_Map_Server.lua
{
if (!script.Globals.Get(funcName).IsNil())
{
- Coroutine coroutine = script.CreateCoroutine(script.Globals[funcName]).Coroutine;
- DynValue value = coroutine.Resume(args2);
- ResolveResume(player, coroutine, value);
-
+ try
+ {
+ Coroutine coroutine = script.CreateCoroutine(script.Globals[funcName]).Coroutine;
+ DynValue value = coroutine.Resume(args2);
+ ResolveResume(player, coroutine, value);
+ }
+ catch(Exception e)
+ {
+ player.SendMessage(0x20, "", e.Message);
+ player.EndEvent();
+
+ }
}
else
{
diff --git a/FFXIVClassic Map Server/packets/send/Actor/SetActorPropetyPacket.cs b/FFXIVClassic Map Server/packets/send/Actor/SetActorPropetyPacket.cs
index aabba72e..eec4278b 100644
--- a/FFXIVClassic Map Server/packets/send/Actor/SetActorPropetyPacket.cs
+++ b/FFXIVClassic Map Server/packets/send/Actor/SetActorPropetyPacket.cs
@@ -112,7 +112,6 @@ namespace FFXIVClassic_Map_Server.packets.send.actor
{
string[] split = name.Split('.');
int arrayIndex = 0;
-
if (!(split[0].Equals("work") || split[0].Equals("charaWork") || split[0].Equals("playerWork") || split[0].Equals("npcWork") || split[0].Equals("guildleveWork")))
return false;
diff --git a/FFXIVClassic Map Server/packets/send/Actor/battle/BattleActionX18Packet.cs b/FFXIVClassic Map Server/packets/send/Actor/battle/BattleActionX18Packet.cs
index 2fe2279f..d2411857 100644
--- a/FFXIVClassic Map Server/packets/send/Actor/battle/BattleActionX18Packet.cs
+++ b/FFXIVClassic Map Server/packets/send/Actor/battle/BattleActionX18Packet.cs
@@ -35,33 +35,33 @@ namespace FFXIVClassic_Map_Server.packets.send.actor.battle
binWriter.Write((UInt16)commandId);
binWriter.Write((UInt16)0x810); //?
- binWriter.Seek(0x58, SeekOrigin.Begin);
+ binWriter.Seek(0x28, SeekOrigin.Begin);
for (int i = 0; i < max; i++)
binWriter.Write((UInt32)actionList[listOffset + i].targetId);
- binWriter.Seek(0xA0, SeekOrigin.Begin);
+ binWriter.Seek(0x70, SeekOrigin.Begin);
for (int i = 0; i < max; i++)
binWriter.Write((UInt16)actionList[listOffset + i].amount);
- binWriter.Seek(0xC4, SeekOrigin.Begin);
+ binWriter.Seek(0x94, SeekOrigin.Begin);
for (int i = 0; i < max; i++)
binWriter.Write((UInt16)actionList[listOffset + i].worldMasterTextId);
- binWriter.Seek(0xE8, SeekOrigin.Begin);
+ binWriter.Seek(0xB8, SeekOrigin.Begin);
for (int i = 0; i < max; i++)
binWriter.Write((UInt32)actionList[listOffset + i].effectId);
- binWriter.Seek(0x130, SeekOrigin.Begin);
+ binWriter.Seek(0x100, SeekOrigin.Begin);
for (int i = 0; i < max; i++)
binWriter.Write((Byte)actionList[listOffset + i].param);
- binWriter.Seek(0x142, SeekOrigin.Begin);
+ binWriter.Seek(0x112, SeekOrigin.Begin);
for (int i = 0; i < max; i++)
binWriter.Write((Byte)actionList[listOffset + i].unknown);
listOffset += max;
}
- }
+ }
return new SubPacket(OPCODE, sourceActorId, data);
}
diff --git a/FFXIVClassic World Server/App.config b/FFXIVClassic World Server/App.config
index 329f3599..0860683f 100644
--- a/FFXIVClassic World Server/App.config
+++ b/FFXIVClassic World Server/App.config
@@ -1,7 +1,7 @@
-
+
diff --git a/FFXIVClassic World Server/FFXIVClassic World Server.csproj b/FFXIVClassic World Server/FFXIVClassic World Server.csproj
index 2bf7f335..bc28d6b8 100644
--- a/FFXIVClassic World Server/FFXIVClassic World Server.csproj
+++ b/FFXIVClassic World Server/FFXIVClassic World Server.csproj
@@ -9,7 +9,7 @@
Properties
FFXIVClassic_World_Server
FFXIVClassic World Server
- v4.5
+ v4.5.1
512
true
@@ -48,6 +48,26 @@
prompt
4
+
+ true
+ bin\Debug\
+ DEBUG;TRACE
+ full
+ x64
+ prompt
+ MinimumRecommendedRules.ruleset
+ true
+
+
+ bin\x64\Release\
+ TRACE
+ true
+ pdbonly
+ x64
+ prompt
+ MinimumRecommendedRules.ruleset
+ true
+
..\packages\Cyotek.CircularBuffer.1.0.0.0\lib\net20\Cyotek.Collections.Generic.CircularBuffer.dll
@@ -190,7 +210,8 @@
-
+
+