| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599 |
- using Client.MirControls;
- using Client.MirGraphics;
- using Client.MirScenes;
- using Client.MirSounds;
- using Client.MirScenes.Dialogs;
- using SlimDX;
- namespace Client.MirObjects
- {
- public abstract class MapObject
- {
- public static Font ChatFont = new Font(Settings.FontName, 10F);
- public static List<MirLabel> LabelList = new List<MirLabel>();
- public static UserObject User;
- public static UserHeroObject Hero;
- public static HeroObject HeroObject;
- public static MapObject MouseObject, TargetObject, MagicObject;
- private static uint mouseObjectID;
- public static uint MouseObjectID
- {
- get => mouseObjectID;
- set
- {
- if (mouseObjectID == value) return;
- mouseObjectID = value;
- MouseObject = MapControl.Objects.TryGetValue(value, out var obj) ? obj : null;
- }
- }
- private static uint lastTargetObjectId;
- private static uint targetObjectID;
- public static uint TargetObjectID
- {
- get => targetObjectID;
- set
- {
- if (targetObjectID == value) return;
- lastTargetObjectId = value;
- targetObjectID = value;
- TargetObject = MapControl.Objects.TryGetValue(value, out var obj) ? obj : null;
- }
- }
- private static uint magicObjectID;
- public static uint MagicObjectID
- {
- get => magicObjectID;
- set
- {
- if (magicObjectID == value) return;
- magicObjectID = value;
- MagicObject = MapControl.Objects.TryGetValue(value, out var obj) ? obj : null;
- }
- }
- public abstract ObjectType Race { get; }
- public abstract bool Blocking { get; }
- public uint ObjectID;
- public string Name = string.Empty;
- public Point CurrentLocation, MapLocation;
- public MirDirection Direction;
- public bool Dead, Hidden, SitDown, Sneaking;
- public PoisonType Poison;
- public long DeadTime;
- public byte AI;
- public bool InTrapRock;
- public int JumpDistance;
- public bool Blend = true;
- public long BlindTime;
- public byte BlindCount;
- private byte percentHealth;
- public virtual byte PercentHealth
- {
- get { return percentHealth; }
- set
- {
- if (percentHealth == value) return;
- percentHealth = value;
- }
- }
- public long HealthTime;
- private byte percentMana;
- public virtual byte PercentMana
- {
- get { return percentMana; }
- set
- {
- if (percentMana == value) return;
- percentMana = value;
- }
- }
- public uint LastTargetObjectId => lastTargetObjectId;
- public List<QueuedAction> ActionFeed = new List<QueuedAction>();
- public QueuedAction NextAction
- {
- get { return ActionFeed.Count > 0 ? ActionFeed[0] : null; }
- }
- public List<Effect> Effects = new List<Effect>();
- public List<BuffType> Buffs = new List<BuffType>();
- public MLibrary BodyLibrary;
- public Color DrawColour = Color.White, NameColour = Color.White, LightColour = Color.White;
- public MirLabel NameLabel, ChatLabel, GuildLabel;
- public long ChatTime;
- public int DrawFrame, DrawWingFrame;
- public Point DrawLocation, Movement, FinalDrawLocation, OffSetMove;
- public Rectangle DisplayRectangle;
- public int Light, DrawY;
- public long NextMotion, NextMotion2;
- public MirAction CurrentAction;
- public byte CurrentActionLevel;
- public bool SkipFrames;
- public FrameLoop FrameLoop = null;
- //Sound
- public int StruckWeapon;
- public MirLabel TempLabel;
- public static List<MirLabel> DamageLabelList = new List<MirLabel>();
- public List<Damage> Damages = new List<Damage>();
- protected Point GlobalDisplayLocationOffset
- {
- get { return new Point(0, 0); }
- }
- protected MapObject() { }
- protected MapObject(uint objectID)
- {
- ObjectID = objectID;
- if (MapControl.Objects.TryGetValue(ObjectID, out var existingObject))
- existingObject.Remove();
- MapControl.Objects[ObjectID] = this;
- MapControl.ObjectsList.Add(this);
- RestoreTargetStates();
- }
- public void Remove()
- {
- if (MouseObject == this) MouseObjectID = 0;
- if (TargetObject == this)
- {
- TargetObjectID = 0;
- lastTargetObjectId = ObjectID;
- }
- if (MagicObject == this) MagicObjectID = 0;
- if (this == User.NextMagicObject)
- User.ClearMagic();
- MapControl.Objects.Remove(ObjectID);
- MapControl.ObjectsList.Remove(this);
- GameScene.Scene.MapControl.RemoveObject(this);
- if (ObjectID == Hero?.ObjectID)
- HeroObject = null;
- if (ObjectID != GameScene.NPCID) return;
- GameScene.NPCID = 0;
- GameScene.Scene.NPCDialog.Hide();
- }
- public abstract void Process();
- public abstract void Draw();
- public abstract bool MouseOver(Point p);
- private void RestoreTargetStates()
- {
- if (MouseObjectID == ObjectID)
- MouseObject = this;
- if (TargetObjectID == ObjectID)
- TargetObject = this;
- if (MagicObjectID == ObjectID)
- MagicObject = this;
- if (!this.Dead &&
- TargetObject == null &&
- LastTargetObjectId == ObjectID)
- {
- switch (Race)
- {
- case ObjectType.Player:
- case ObjectType.Monster:
- case ObjectType.Hero:
- targetObjectID = ObjectID;
- TargetObject = this;
- break;
- }
- }
- }
- public void AddBuffEffect(BuffType type)
- {
- for (int i = 0; i < Effects.Count; i++)
- {
- if (!(Effects[i] is BuffEffect)) continue;
- if (((BuffEffect)(Effects[i])).BuffType == type) return;
- }
- PlayerObject ob = null;
- if (Race == ObjectType.Player)
- {
- ob = (PlayerObject)this;
- }
- switch (type)
- {
- case BuffType.Fury:
- Effects.Add(new BuffEffect(Libraries.Magic3, 190, 7, 1400, this, true, type) { Repeat = true });
- break;
- case BuffType.ImmortalSkin:
- Effects.Add(new BuffEffect(Libraries.Magic3, 570, 5, 1400, this, true, type) { Repeat = true });
- break;
- case BuffType.SwiftFeet:
- if (ob != null) ob.Sprint = true;
- break;
- case BuffType.MoonLight:
- case BuffType.DarkBody:
- if (ob != null) ob.Sneaking = true;
- break;
- case BuffType.VampireShot:
- Effects.Add(new BuffEffect(Libraries.Magic3, 2110, 6, 1400, this, true, type) { Repeat = false });
- break;
- case BuffType.PoisonShot:
- Effects.Add(new BuffEffect(Libraries.Magic3, 2310, 7, 1400, this, true, type) { Repeat = false });
- break;
- case BuffType.EnergyShield:
- BuffEffect effect;
- Effects.Add(effect = new BuffEffect(Libraries.Magic2, 1880, 9, 900, this, true, type) { Repeat = false });
- SoundManager.PlaySound(20000 + (ushort)Spell.EnergyShield * 10 + 0);
- effect.Complete += (o, e) =>
- {
- Effects.Add(new BuffEffect(Libraries.Magic2, 1900, 2, 800, this, true, type) { Repeat = true });
- };
- break;
- case BuffType.MagicBooster:
- Effects.Add(new BuffEffect(Libraries.Magic3, 90, 6, 1200, this, true, type) { Repeat = true });
- break;
- case BuffType.PetEnhancer:
- Effects.Add(new BuffEffect(Libraries.Magic3, 230, 6, 1200, this, true, type) { Repeat = true });
- break;
- case BuffType.GameMaster:
- Effects.Add(new BuffEffect(Libraries.CHumEffect[5], 0, 1, 1200, this, true, type) { Repeat = true });
- break;
- case BuffType.GeneralMeowMeowShield:
- Effects.Add(new BuffEffect(Libraries.Monsters[(ushort)Monster.GeneralMeowMeow], 529, 7, 700, this, true, type) { Repeat = true, Light = 1 });
- MirSounds.SoundManager.PlaySound(8322);
- break;
- case BuffType.PowerBeadBuff:
- Effects.Add(new BuffEffect(Libraries.Monsters[(ushort)Monster.PowerUpBead], 64, 6, 600, this, true, type) { Blend = true, Repeat = true });
- break;
- case BuffType.HornedArcherBuff:
- Effects.Add(effect = new BuffEffect(Libraries.Monsters[(ushort)Monster.HornedArcher], 468, 6, 600, this, true, type) { Repeat = false });
- effect.Complete += (o, e) =>
- {
- Effects.Add(new BuffEffect(Libraries.Monsters[(ushort)Monster.HornedArcher], 474, 3, 1000, this, true, type) { Blend = true, Repeat = true });
- };
- break;
- case BuffType.ColdArcherBuff:
- Effects.Add(effect = new BuffEffect(Libraries.Monsters[(ushort)Monster.HornedArcher], 477, 7, 700, this, true, type) { Repeat = false });
- effect.Complete += (o, e) =>
- {
- Effects.Add(new BuffEffect(Libraries.Monsters[(ushort)Monster.HornedArcher], 484, 3, 1000, this, true, type) { Blend = true, Repeat = true });
- };
- break;
- case BuffType.HornedWarriorShield:
- Effects.Add(new BuffEffect(Libraries.Monsters[(ushort)Monster.HornedWarrior], 912, 18, 1800, this, true, type) { Repeat = true });
- break;
- case BuffType.HornedCommanderShield:
- Effects.Add(effect = new BuffEffect(Libraries.Monsters[(ushort)Monster.HornedCommander], 1173, 1, 100, this, true, type) { Repeat = false, Light = 1 });
- effect.Complete += (o, e) =>
- {
- Effects.Add(new BuffEffect(Libraries.Monsters[(ushort)Monster.HornedCommander], 1174, 16, 1600, this, true, type) { Repeat = true, Light = 1 });
- };
- break;
- }
- }
- public void RemoveBuffEffect(BuffType type)
- {
- PlayerObject ob = null;
- if (Race == ObjectType.Player)
- {
- ob = (PlayerObject)this;
- }
- for (int i = 0; i < Effects.Count; i++)
- {
- if (!(Effects[i] is BuffEffect)) continue;
- if (((BuffEffect)(Effects[i])).BuffType != type) continue;
- Effects[i].Repeat = false;
- }
- switch (type)
- {
- case BuffType.SwiftFeet:
- if (ob != null) ob.Sprint = false;
- break;
- case BuffType.MoonLight:
- case BuffType.DarkBody:
- if (ob != null) ob.Sneaking = false;
- break;
- }
- }
- public Color ApplyDrawColour()
- {
- Color drawColour = DrawColour;
- if (drawColour == Color.Gray)
- {
- drawColour = Color.White;
- DXManager.SetGrayscale(true);
- }
- return drawColour;
- }
- public virtual Missile CreateProjectile(int baseIndex, MLibrary library, bool blend, int count, int interval, int skip, int lightDistance = 6, bool direction16 = true, Color? lightColour = null, uint targetID = 0)
- {
- return null;
- }
- public void Chat(string text)
- {
- if (ChatLabel != null && !ChatLabel.IsDisposed)
- {
- ChatLabel.Dispose();
- ChatLabel = null;
- }
- const int chatWidth = 200;
- List<string> chat = new List<string>();
- int index = 0;
- for (int i = 1; i < text.Length; i++)
- if (TextRenderer.MeasureText(CMain.Graphics, text.Substring(index, i - index), ChatFont).Width > chatWidth)
- {
- chat.Add(text.Substring(index, i - index - 1));
- index = i - 1;
- }
- chat.Add(text.Substring(index, text.Length - index));
- text = chat[0];
- for (int i = 1; i < chat.Count; i++)
- text += string.Format("\n{0}", chat[i]);
- ChatLabel = new MirLabel
- {
- AutoSize = true,
- BackColour = Color.Transparent,
- ForeColour = Color.White,
- OutLine = true,
- OutLineColour = Color.Black,
- DrawFormat = TextFormatFlags.HorizontalCenter,
- Text = text,
- };
- ChatTime = CMain.Time + 5000;
- }
- public virtual void DrawChat()
- {
- if (ChatLabel == null || ChatLabel.IsDisposed) return;
- if (CMain.Time > ChatTime)
- {
- ChatLabel.Dispose();
- ChatLabel = null;
- return;
- }
- ChatLabel.ForeColour = Dead ? Color.Gray : Color.White;
- ChatLabel.Location = new Point(DisplayRectangle.X + (48 - ChatLabel.Size.Width) / 2, DisplayRectangle.Y - (60 + ChatLabel.Size.Height) - (Dead ? 35 : 0));
- ChatLabel.Draw();
- }
- public virtual void CreateLabel()
- {
- NameLabel = null;
- for (int i = 0; i < LabelList.Count; i++)
- {
- if (LabelList[i].Text != Name || LabelList[i].ForeColour != NameColour) continue;
- NameLabel = LabelList[i];
- break;
- }
- if (NameLabel != null && !NameLabel.IsDisposed) return;
- NameLabel = new MirLabel
- {
- AutoSize = true,
- BackColour = Color.Transparent,
- ForeColour = NameColour,
- OutLine = true,
- OutLineColour = Color.Black,
- Text = Name,
- };
- NameLabel.Disposing += (o, e) => LabelList.Remove(NameLabel);
- LabelList.Add(NameLabel);
- }
- public virtual void DrawName()
- {
- CreateLabel();
- if (NameLabel == null) return;
- //NameLabel.Text = Name; //When CreateLabel() is called, the name is already determined, so there's no need to assign it every time in DrawName.
- NameLabel.Location = new Point(DisplayRectangle.X + (50 - NameLabel.Size.Width) / 2, DisplayRectangle.Y - (32 - NameLabel.Size.Height / 2) + (Dead ? 35 : 8)); //was 48 -
- NameLabel.Draw();
- }
- public virtual void DrawBlend()
- {
- DXManager.SetBlend(true, 0.3F); //0.8
- Draw();
- DXManager.SetBlend(false);
- }
- public void DrawDamages()
- {
- for (int i = Damages.Count - 1; i >= 0; i--)
- {
- Damage info = Damages[i];
- if (CMain.Time > info.ExpireTime)
- {
- if (info.DamageLabel != null)
- {
- info.DamageLabel.Dispose();
- }
- Damages.RemoveAt(i);
- }
- else
- {
- info.Draw(DisplayRectangle.Location);
- }
- }
- }
- public virtual bool ShouldDrawHealth()
- {
- return false;
- }
- public void DrawHealth()
- {
- string name = Name;
- if (Name.Contains("(")) name = Name.Substring(Name.IndexOf("(") + 1, Name.Length - Name.IndexOf("(") - 2);
- if (Dead) return;
- if (Race != ObjectType.Player && Race != ObjectType.Monster && Race != ObjectType.Hero) return;
- if (CMain.Time >= HealthTime)
- {
- if (!ShouldDrawHealth()) return;
- }
- Libraries.Prguse2.Draw(0, DisplayRectangle.X + 8, DisplayRectangle.Y - 64);
- int index = 1;
- switch (Race)
- {
- case ObjectType.Player:
- index = 12;
- if (GroupDialog.GroupList.Contains(name) && name != User.Name) index = 10;
- break;
- case ObjectType.Monster:
- if (GroupDialog.GroupList.Contains(name) || name == User.Name) index = 11;
- break;
- case ObjectType.Hero:
- if (GroupDialog.GroupList.Contains(MapObject.HeroObject?.OwnerName)) // Fails but not game breaking
- {
- index = 11;
- }
- if (HeroObject.HeroObject?.OwnerName == User.Name)
- {
- index = 1;
- if ((MapObject.HeroObject.Class != MirClass.Warrior && HeroObject.Level > 7) || (MapObject.HeroObject.Class == MirClass.Warrior && HeroObject.Level > 25))
- {
- Libraries.Prguse2.Draw(10, new Rectangle(0, 0, (int)(32 * PercentMana / 100F), 4), new Point(DisplayRectangle.X + 8, DisplayRectangle.Y - 60), Color.White, false);
- }
- }
- break;
- }
- Libraries.Prguse2.Draw(index, new Rectangle(0, 0, (int)(32 * PercentHealth / 100F), 4), new Point(DisplayRectangle.X + 8, DisplayRectangle.Y - 64), Color.White, false);
- }
- public void DrawPoison()
- {
- byte poisoncount = 0;
- if (Poison != PoisonType.None)
- {
- if (Poison.HasFlag(PoisonType.Green))
- {
- DXManager.Draw(DXManager.PoisonDotBackground, new Rectangle(0, 0, 6, 6), new Vector3((float)(DisplayRectangle.X + 7 + (poisoncount * 5)), (float)(DisplayRectangle.Y - 21), 0.0F), Color.Black);
- DXManager.Draw(DXManager.RadarTexture, new Rectangle(0, 0, 4, 4), new Vector3((float)(DisplayRectangle.X + 8 + (poisoncount * 5)), (float)(DisplayRectangle.Y - 20), 0.0F), Color.Green);
- poisoncount++;
- }
- if (Poison.HasFlag(PoisonType.Red))
- {
- DXManager.Draw(DXManager.PoisonDotBackground, new Rectangle(0, 0, 6, 6), new Vector3((float)(DisplayRectangle.X + 7 + (poisoncount * 5)), (float)(DisplayRectangle.Y - 21), 0.0F), Color.Black);
- DXManager.Draw(DXManager.RadarTexture, new Rectangle(0, 0, 4, 4), new Vector3((float)(DisplayRectangle.X + 8 + (poisoncount * 5)), (float)(DisplayRectangle.Y - 20), 0.0F), Color.Red);
- poisoncount++;
- }
- if (Poison.HasFlag(PoisonType.Bleeding))
- {
- DXManager.Draw(DXManager.PoisonDotBackground, new Rectangle(0, 0, 6, 6), new Vector3((float)(DisplayRectangle.X + 7 + (poisoncount * 5)), (float)(DisplayRectangle.Y - 21), 0.0F), Color.Black);
- DXManager.Draw(DXManager.RadarTexture, new Rectangle(0, 0, 4, 4), new Vector3((float)(DisplayRectangle.X + 8 + (poisoncount * 5)), (float)(DisplayRectangle.Y - 20), 0.0F), Color.DarkRed);
- poisoncount++;
- }
- if (Poison.HasFlag(PoisonType.Slow))
- {
- DXManager.Draw(DXManager.PoisonDotBackground, new Rectangle(0, 0, 6, 6), new Vector3((float)(DisplayRectangle.X + 7 + (poisoncount * 5)), (float)(DisplayRectangle.Y - 21), 0.0F), Color.Black);
- DXManager.Draw(DXManager.RadarTexture, new Rectangle(0, 0, 4, 4), new Vector3((float)(DisplayRectangle.X + 8 + (poisoncount * 5)), (float)(DisplayRectangle.Y - 20), 0.0F), Color.Purple);
- poisoncount++;
- }
- if (Poison.HasFlag(PoisonType.Stun) || Poison.HasFlag(PoisonType.Dazed))
- {
- DXManager.Draw(DXManager.PoisonDotBackground, new Rectangle(0, 0, 6, 6), new Vector3((float)(DisplayRectangle.X + 7 + (poisoncount * 5)), (float)(DisplayRectangle.Y - 21), 0.0F), Color.Black);
- DXManager.Draw(DXManager.RadarTexture, new Rectangle(0, 0, 4, 4), new Vector3((float)(DisplayRectangle.X + 8 + (poisoncount * 5)), (float)(DisplayRectangle.Y - 20), 0.0F), Color.Yellow);
- poisoncount++;
- }
- if (Poison.HasFlag(PoisonType.Blindness))
- {
- DXManager.Draw(DXManager.PoisonDotBackground, new Rectangle(0, 0, 6, 6), new Vector3((float)(DisplayRectangle.X + 7 + (poisoncount * 5)), (float)(DisplayRectangle.Y - 21), 0.0F), Color.Black);
- DXManager.Draw(DXManager.RadarTexture, new Rectangle(0, 0, 4, 4), new Vector3((float)(DisplayRectangle.X + 8 + (poisoncount * 5)), (float)(DisplayRectangle.Y - 20), 0.0F), Color.MediumVioletRed);
- poisoncount++;
- }
- if (Poison.HasFlag(PoisonType.Frozen))
- {
- DXManager.Draw(DXManager.PoisonDotBackground, new Rectangle(0, 0, 6, 6), new Vector3((float)(DisplayRectangle.X + 7 + (poisoncount * 5)), (float)(DisplayRectangle.Y - 21), 0.0F), Color.Black);
- DXManager.Draw(DXManager.RadarTexture, new Rectangle(0, 0, 4, 4), new Vector3((float)(DisplayRectangle.X + 8 + (poisoncount * 5)), (float)(DisplayRectangle.Y - 20), 0.0F), Color.Blue);
- poisoncount++;
- }
- if (Poison.HasFlag(PoisonType.Paralysis) || Poison.HasFlag(PoisonType.LRParalysis))
- {
- DXManager.Draw(DXManager.PoisonDotBackground, new Rectangle(0, 0, 6, 6), new Vector3((float)(DisplayRectangle.X + 7 + (poisoncount * 5)), (float)(DisplayRectangle.Y - 21), 0.0F), Color.Black);
- DXManager.Draw(DXManager.RadarTexture, new Rectangle(0, 0, 4, 4), new Vector3((float)(DisplayRectangle.X + 8 + (poisoncount * 5)), (float)(DisplayRectangle.Y - 20), 0.0F), Color.Gray);
- poisoncount++;
- }
- if (Poison.HasFlag(PoisonType.DelayedExplosion))
- {
- DXManager.Draw(DXManager.PoisonDotBackground, new Rectangle(0, 0, 6, 6), new Vector3((float)(DisplayRectangle.X + 7 + (poisoncount * 5)), (float)(DisplayRectangle.Y - 21), 0.0F), Color.Black);
- DXManager.Draw(DXManager.RadarTexture, new Rectangle(0, 0, 4, 4), new Vector3((float)(DisplayRectangle.X + 8 + (poisoncount * 5)), (float)(DisplayRectangle.Y - 20), 0.0F), Color.Orange);
- poisoncount++;
- }
- }
- }
- public abstract void DrawBehindEffects(bool effectsEnabled);
- public abstract void DrawEffects(bool effectsEnabled);
- protected void LoopFrame(int start, int frameCount, int frameInterval, int duration)
- {
- if (FrameLoop == null)
- {
- FrameLoop = new FrameLoop
- {
- Start = start,
- End = start + frameCount - 1,
- Loops = (duration / (frameInterval * frameCount)) - 1 //Remove 1 count as we've already done a loop before this is checked
- };
- }
- }
- }
- public class FrameLoop
- {
- public MirAction Action { get; set; }
- public int Start { get; set; }
- public int End { get; set; }
- public int Loops { get; set; }
- public int CurrentCount { get; set; }
- }
- }
|