diff --git a/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj b/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj
index 092793af..2b5d91c4 100644
--- a/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj
+++ b/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj
@@ -94,6 +94,7 @@
+
diff --git a/FFXIVClassic Map Server/actors/chara/ai/HateContainer.cs b/FFXIVClassic Map Server/actors/chara/ai/HateContainer.cs
index c4a4c014..e4274bcf 100644
--- a/FFXIVClassic Map Server/actors/chara/ai/HateContainer.cs
+++ b/FFXIVClassic Map Server/actors/chara/ai/HateContainer.cs
@@ -23,6 +23,7 @@ namespace FFXIVClassic_Map_Server.actors.chara.ai
this.isActive = isActive;
}
}
+
class HateContainer
{
private Dictionary hateList;
diff --git a/FFXIVClassic Map Server/actors/chara/ai/StatusEffects.cs b/FFXIVClassic Map Server/actors/chara/ai/StatusEffects.cs
new file mode 100644
index 00000000..95b9a3ce
--- /dev/null
+++ b/FFXIVClassic Map Server/actors/chara/ai/StatusEffects.cs
@@ -0,0 +1,444 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using FFXIVClassic_Map_Server.Actors;
+using FFXIVClassic_Map_Server.lua;
+
+namespace FFXIVClassic_Map_Server.actors.chara.ai
+{
+ enum StatusEffectId
+ {
+ RageofHalone = 221021,
+
+ Quick = 223001,
+ Haste = 223002,
+ Slow = 223003,
+ Petrification = 223004,
+ Paralysis = 223005,
+ Silence = 223006,
+ Blind = 223007,
+ Mute = 223008,
+ Slowcast = 223009,
+ Glare = 223010,
+ Poison = 223011,
+ Transfixion = 223012,
+ Pacification = 223013,
+ Amnesia = 223014,
+ Stun = 223015,
+ Daze = 223016,
+ ExposedFront = 223017,
+ ExposedRight = 223018,
+ ExposedRear = 223019,
+ ExposedLeft = 223020,
+ Incapacitation = 223021,
+ Incapacitation2 = 223022,
+ Incapacitation3 = 223023,
+ Incapacitation4 = 223024,
+ Incapacitation5 = 223025,
+ Incapacitation6 = 223026,
+ Incapacitation7 = 223027,
+ Incapacitation8 = 223028,
+ HPBoost = 223029,
+ HPPenalty = 223030,
+ MPBoost = 223031,
+ MPPenalty = 223032,
+ AttackUp = 223033,
+ AttackDown = 223034,
+ AccuracyUp = 223035,
+ AccuracyDown = 223036,
+ DefenseUp = 223037,
+ DefenseDown = 223038,
+ EvasionUp = 223039,
+ EvasionDown = 223040,
+ MagicPotencyUp = 223041,
+ MagicPotencyDown = 223042,
+ MagicAccuracyUp = 223043,
+ MagicAccuracyDown = 223044,
+ MagicDefenseUp = 223045,
+ MagicDefenseDown = 223046,
+ MagicResistanceUp = 223047,
+ MagicResistanceDown = 223048,
+ CombatFinesse = 223049,
+ CombatHindrance = 223050,
+ MagicFinesse = 223051,
+ MagicHindrance = 223052,
+ CombatResilience = 223053,
+ CombatVulnerability = 223054,
+ MagicVulnerability = 223055,
+ MagicResilience = 223056,
+ Inhibited = 223057,
+ AegisBoon = 223058,
+ Deflection = 223059,
+ Outmaneuver = 223060,
+ Provoked = 223061,
+ Sentinel = 223062,
+ Cover = 223063,
+ Rampart = 223064,
+ StillPrecision = 223065,
+ Cadence = 223066,
+ DiscerningEye = 223067,
+ TemperedWill = 223068,
+ Obsess = 223069,
+ Ambidexterity = 223070,
+ BattleCalm = 223071,
+ MasterofArms = 223072,
+ Taunted = 223073,
+ Blindside = 223074,
+ Featherfoot = 223075,
+ PresenceofMind = 223076,
+ CoeurlStep = 223077,
+ EnduringMarch = 223078,
+ MurderousIntent = 223079,
+ Entrench = 223080,
+ Bloodbath = 223081,
+ Retaliation = 223082,
+ Foresight = 223083,
+ Defender = 223084,
+ Rampage = 223085,
+ Enraged = 223086,
+ Warmonger = 223087,
+ Disorientx1 = 223088,
+ Disorientx2 = 223089,
+ Disorientx3 = 223090,
+ KeenFlurry = 223091,
+ ComradeinArms = 223092,
+ Ferocity = 223093,
+ Invigorate = 223094,
+ LineofFire = 223095,
+ Jump = 223096,
+ Collusion = 223097,
+ Diversion = 223098,
+ SpeedSurge = 223099,
+ LifeSurge = 223100,
+ SpeedSap = 223101,
+ LifeSap = 223102,
+ Farshot = 223103,
+ QuellingStrike = 223104,
+ RagingStrike = 223105,
+ HawksEye = 223106,
+ SubtleRelease = 223107,
+ Decoy = 223108,
+ Profundity = 223109,
+ TranceChant = 223110,
+ RoamingSoul = 223111,
+ Purge = 223112,
+ Spiritsong = 223113,
+ Resonance = 223114,
+ Soughspeak = 223115,
+ PresenceofMind2 = 223116,
+ SanguineRite = 223117,
+ PunishingBarbs = 223118,
+ DarkSeal = 223119,
+ Emulate = 223120,
+ ParadigmShift = 223121,
+ ConcussiveBlowx1 = 223123,
+ ConcussiveBlowx2 = 223124,
+ ConcussiveBlowx3 = 223125,
+ SkullSunder = 223126,
+ Bloodletter = 223127,
+ Levinbolt = 223128,
+ Protect = 223129,
+ Shell = 223130,
+ Reraise = 223131,
+ ShockSpikes = 223132,
+ Stoneskin = 223133,
+ Scourge = 223134,
+ Bio = 223135,
+ Dia = 223136,
+ Banish = 223137,
+ StygianSpikes = 223138,
+ ATKAbsorbed = 223139,
+ DEFAbsorbed = 223140,
+ ACCAbsorbed = 223141,
+ EVAAbsorbed = 223142,
+ AbsorbATK = 223143,
+ AbsorbDEF = 223144,
+ AbsorbACC = 223145,
+ AbsorbEVA = 223146,
+ SoulWard = 223147,
+ Burn = 223148,
+ Frost = 223149,
+ Shock = 223150,
+ Drown = 223151,
+ Choke = 223152,
+ Rasp = 223153,
+ Flare = 223154,
+ Freeze = 223155,
+ Burst = 223156,
+ Flood = 223157,
+ Tornado = 223158,
+ Quake = 223159,
+ Berserk = 223160,
+ RegimenofRuin = 223161,
+ RegimenofTrauma = 223162,
+ RegimenofDespair = 223163,
+ RegimenofConstraint = 223164,
+ Weakness = 223165,
+ Scavenge = 223166,
+ Fastcast = 223167,
+ MidnightHowl = 223168,
+ Outlast = 223169,
+ Steadfast = 223170,
+ DoubleNock = 223171,
+ TripleNock = 223172,
+ Covered = 223173,
+ PerfectDodge = 223174,
+ ExpertMining = 223175,
+ ExpertLogging = 223176,
+ ExpertHarvesting = 223177,
+ ExpertFishing = 223178,
+ ExpertSpearfishing = 223179,
+ Regen = 223180,
+ Refresh = 223181,
+ Regain = 223182,
+ TPBleed = 223183,
+ Empowered = 223184,
+ Imperiled = 223185,
+ Adept = 223186,
+ Inept = 223187,
+ Quick2 = 223188,
+ Quick3 = 223189,
+ WristFlick = 223190,
+ Glossolalia = 223191,
+ SonorousBlast = 223192,
+ Comradery = 223193,
+ StrengthinNumbers = 223194,
+
+ BrinkofDeath = 223197,
+ CraftersGrace = 223198,
+ GatherersGrace = 223199,
+ Rebirth = 223200,
+ Stealth = 223201,
+ StealthII = 223202,
+ StealthIII = 223203,
+ StealthIV = 223204,
+ Combo = 223205,
+ GoringBlade = 223206,
+ Berserk2 = 223207,
+ Rampage2 = 223208,
+ FistsofFire = 223209,
+ FistsofEarth = 223210,
+ FistsofWind = 223211,
+ PowerSurgeI = 223212,
+ PowerSurgeII = 223213,
+ PowerSurgeIII = 223214,
+ LifeSurgeI = 223215,
+ LifeSurgeII = 223216,
+ LifeSurgeIII = 223217,
+ DreadSpike = 223218,
+ BloodforBlood = 223219,
+ Barrage = 223220,
+ RagingStrike2 = 223221,
+
+ Swiftsong = 223224,
+ SacredPrism = 223225,
+ ShroudofSaints = 223226,
+ ClericStance = 223227,
+ BlissfulMind = 223228,
+ DarkSeal2 = 223229,
+ Resonance2 = 223230,
+ Excruciate = 223231,
+ Necrogenesis = 223232,
+ Parsimony = 223233,
+ SanguineRite2 = 223234,
+ Aero = 223235,
+ Outmaneuver2 = 223236,
+ Blindside2 = 223237,
+ Decoy2 = 223238,
+ Protect2 = 223239,
+ SanguineRite3 = 223240,
+ Bloodletter2 = 223241,
+ FullyBlissfulMind = 223242,
+ MagicEvasionDown = 223243,
+ HundredFists = 223244,
+ SpinningHeel = 223245,
+ DivineVeil = 223248,
+ HallowedGround = 223249,
+ Vengeance = 223250,
+ Antagonize = 223251,
+ MightyStrikes = 223252,
+ BattleVoice = 223253,
+ BalladofMagi = 223254,
+ PaeonofWar = 223255,
+ MinuetofRigor = 223256,
+ GoldLung = 223258,
+ Goldbile = 223259,
+ AurumVeil = 223260,
+ AurumVeilII = 223261,
+ Flare2 = 223262,
+ Resting = 223263,
+ DivineRegen = 223264,
+ DefenseAndEvasionUp = 223265,
+ MagicDefenseAndEvasionUp = 223266,
+ AttackUp2 = 223267,
+ MagicPotencyUp2 = 223268,
+ DefenseAndEvasionDown = 223269,
+ MagicDefenseAndEvasionDown = 223270,
+ Poison2 = 223271,
+ DeepBurn = 223272,
+ LunarCurtain = 223273,
+ DefenseUp2 = 223274,
+ AttackDown2 = 223275,
+ Sanction = 223992,
+ IntactPodlingToting = 223993,
+ RedRidingHooded = 223994,
+ Medicated = 223998,
+ WellFed = 223999,
+
+ Sleep = 228001,
+ Bind = 228011,
+ Fixation = 228012,
+ Bind2 = 228013,
+ Heavy = 228021,
+ Charm = 228031,
+ Flee = 228041,
+ Doom = 228051,
+ SynthesisSupport = 230001,
+ WoodyardAccess = 230002,
+ SmithsForgeAccess = 230003,
+ ArmorersForgeAccess = 230004,
+ GemmaryAccess = 230005,
+ TanneryAccess = 230006,
+ ClothshopAccess = 230007,
+ LaboratoryAccess = 230008,
+ CookeryAccess = 230009,
+ MinersSupport = 230010,
+ BotanistsSupport = 230011,
+ FishersSupport = 230012,
+ GearChange = 230013,
+ GearDamage = 230014,
+ HeavyGearDamage = 230015,
+ Lamed = 230016,
+ Lamed2 = 230017,
+ Lamed3 = 230018,
+ Poison3 = 231002,
+ Envenom = 231003,
+ Berserk4 = 231004,
+ GuardiansAspect = 253002,
+
+
+ // custom effects here
+ }
+
+ class StatusEffect
+ {
+ // todo: probably use get;set;
+
+ private Character owner;
+ private StatusEffectId id;
+ private string name; // name of this effect
+ private DateTime startTime; // when was this effect added
+ private DateTime lastTick; // when did this effect last tick
+ private uint durationMs; // how long should this effect last in ms
+ private uint tickMs; // how often should this effect proc
+ private int magnitude; // a value specified by scripter which is guaranteed to be used by all effects
+ private byte tier; // same effect with higher tier overwrites this
+ private Dictionary variables; // list of variables which belong to this effect, to be set/retrieved with GetVariable(key), SetVariable(key, val)
+
+ public StatusEffect(uint id, int magnitude, uint tickMs, uint durationMs, byte tier = 0)
+ {
+ this.id = (StatusEffectId)id;
+ this.magnitude = magnitude;
+ this.tickMs = tickMs;
+ this.durationMs = durationMs;
+ this.tier = tier;
+
+ // todo: use tick instead of now?
+ this.startTime = DateTime.Now;
+ this.lastTick = startTime;
+
+ // todo: set the effect name to be called by scripts or just lookup effects in db
+ // name = WorldManager.GetEffectInfo(id).Name;
+ // todo: check if can gain effect
+ // todo: call effect's onGain
+ }
+
+ // return true when duration has elapsed
+ public bool Update(DateTime tick)
+ {
+ // todo: maybe not tick if already reached duration?
+ if (tickMs != 0 && (lastTick - startTime).Milliseconds >= tickMs)
+ {
+ // todo: call effect's onTick
+ // todo: maybe keep a global lua object instead of creating a new one each time we wanna call a script
+ lastTick = tick;
+ }
+ if (startTime.Millisecond + durationMs >= tick.Millisecond)
+ {
+ // todo: call effect's onLose
+ return true;
+ }
+ return false;
+ }
+
+ public uint GetEffectId()
+ {
+ return (uint)id;
+ }
+
+ public string GetName()
+ {
+ return name;
+ }
+
+ public uint GetDurationMs()
+ {
+ return durationMs;
+ }
+
+ public uint GetTickMs()
+ {
+ return tickMs;
+ }
+
+ public int GetMagnitude()
+ {
+ return magnitude;
+ }
+
+ public byte GetTier()
+ {
+ return tier;
+ }
+
+ public UInt64 GetVariable(string key)
+ {
+ return variables?[key] ?? 0;
+ }
+
+ public void SetName(string name)
+ {
+ this.name = name;
+ }
+
+ public void SetDurationMs(uint durationMs)
+ {
+ this.durationMs = durationMs;
+ }
+
+ public void SetTickMs(uint tickMs)
+ {
+ this.tickMs = tickMs;
+ }
+
+ public void SetTier(byte tier)
+ {
+ this.tier = tier;
+ }
+
+ public void SetVariable(string key, UInt64 val)
+ {
+ if (variables != null)
+ {
+ variables[key] = val;
+ }
+ else
+ {
+ variables = new Dictionary();
+ variables[key] = val;
+ }
+ }
+ }
+}