Code:
namespace Turbo.Plugins.Razor
{
using SharpDX.DirectWrite;
using System;
using System.Drawing;
using System.Linq;
using Turbo.Plugins.Default;
using Turbo.Plugins.Razor.Movable;
public class ImmunityIndicator : BasePlugin, IInGameTopPainter, IMovable
{
public bool ShowCountdown { get; set; } = true;
public bool ShowCountdownBar { get; set; } = true;
//public bool ShowCountdownOnCursor { get; set; } = false;
public int ShowStyle { get; set; } = 2; //0 = Nothing, 1 = Glow, 2 = Parentheses
public string ImmunityText { get; set; } = "Immune"; //for immunities that only last a fraction of a second
public IFont NotifyFont { get; set; }
public IFont SFont { get; set; }
public IFont StyleFont { get; set; } //for style 2
public float BarWidth { get; set; } = 30f; //35f
public float BarHeight { get; set; } = 3f;
public IBrush TimerHigh { get; set; }
public IBrush TimerLow { get; set; }
public IBrush BgBrush { get; set; }
public IBrush SkillBorderLight { get; set; }
public IBrush SkillBorderDark { get; set; }
private double duration;
private double totaltime;
private int LandStartTick;
private int RCRStartTick;
public ImmunityIndicator()
{
Enabled = true;
Order = 100003;
}
public override void Load(IController hud)
{
base.Load(hud);
NotifyFont = Hud.Render.CreateFont("tahoma", 20, 255, 98, 247, 252, true, false, 100, 0, 0, 0, true); //242, 192, 41 //235, 189, 52
SFont = Hud.Render.CreateFont("tahoma", 10, 255, 0, 0, 0, true, false, 100, 98, 247, 252, true); //98, 252, 234 //242, 192, 41 //255, 100, 50
StyleFont = Hud.Render.CreateFont("arial", 75, 255, 0, 0, 0, false, false, 75, 98, 247, 252, true); //255, 201, 38 //235, 189, 52
BgBrush = Hud.Render.CreateBrush(150, 25, 25, 25, 0);
TimerHigh = Hud.Render.CreateBrush(255, 0, 255, 100, 0); //242, 192, 41 //255, 201, 38 //0, 255, 100
TimerLow = Hud.Render.CreateBrush(255, 255, 0, 0, 0);
SkillBorderLight = Hud.Render.CreateBrush(125, 98, 247, 252, 1); //95, 95, 95 //235, 227, 164 //138, 135, 109
SkillBorderDark = Hud.Render.CreateBrush(200, 0, 0, 0, 1);
}
public void PaintTopInGame(ClipState clipState)
{
if (clipState != ClipState.BeforeClip) return;
if ((Hud.Game.MapMode == MapMode.WaypointMap) || (Hud.Game.MapMode == MapMode.ActMap) || (Hud.Game.MapMode == MapMode.Map)) return;
IPlayer me = Hud.Game.Me;
IScreenCoordinate pos = me.FloorCoordinate.ToScreenCoordinate();
IScreenCoordinate pos2 = me.CollisionCoordinate.ToScreenCoordinate();
duration = 0;
totaltime = 0;
if (me.Powers.BuffIsActive(Hud.Sno.SnoPowers.Generic_ActorInvulBuff.Sno)) //stasis
{
IBuff buff = me.Powers.GetBuff(Hud.Sno.SnoPowers.Generic_ActorInvulBuff.Sno);
double remaining = buff.TimeLeftSeconds[0];
if (duration < remaining)
{
duration = remaining;
totaltime = buff.TimeElapsedSeconds[0] + remaining;
}
}
if (me.Powers.BuffIsActive(Hud.Sno.SnoPowers.Generic_PagesBuffInvulnerable.Sno)) //Shield Pylon
{
IBuff buff = me.Powers.GetBuff(Hud.Sno.SnoPowers.Generic_PagesBuffInvulnerable.Sno);
double remaining = buff.TimeLeftSeconds[0];
if (duration < remaining)
{
duration = remaining;
totaltime = buff.TimeElapsedSeconds[0] + remaining;
}
}
if (me.HeroClassDefinition.HeroClass == HeroClass.Monk)
{
if (duration < 4 && me.Powers.BuffIsActive(Hud.Sno.SnoPowers.Monk_Serenity.Sno, 0))
{
IBuff buff = me.Powers.GetBuff(Hud.Sno.SnoPowers.Monk_Serenity.Sno);
double remaining = buff.TimeLeftSeconds[0];
if (duration < remaining)
{
duration = remaining;
totaltime = buff.TimeElapsedSeconds[0] + remaining;
}
}
if (duration < 2 && me.Powers.BuffIsActive(Hud.Sno.SnoPowers.Monk_Passive_NearDeathExperience.Sno, 3))
{
IBuff buff = me.Powers.GetBuff(Hud.Sno.SnoPowers.Monk_Passive_NearDeathExperience.Sno);
double remaining = buff.TimeLeftSeconds[3];
if (duration < remaining)
{
duration = remaining;
totaltime = buff.TimeElapsedSeconds[3] + remaining;
}
}
}
else if (me.HeroClassDefinition.HeroClass == HeroClass.DemonHunter)
{
//smoke screen
if (duration < 1.5 && me.Powers.BuffIsActive(Hud.Sno.SnoPowers.DemonHunter_SmokeScreen.Sno))
{
IBuff buff = me.Powers.GetBuff(Hud.Sno.SnoPowers.DemonHunter_SmokeScreen.Sno);
int index = buff.TimeLeftSeconds[2] > 0 ? 2 : 0;
double remaining = buff.TimeLeftSeconds[index];
if (duration < remaining)
{
duration = remaining;
totaltime = buff.TimeElapsedSeconds[index] + remaining;
}
}
}
else if (me.HeroClassDefinition.HeroClass == HeroClass.Necromancer)
{
//land of the dead: invigoration + crimson set 3-pc bonus
if (duration < 10 && me.Defense.drCombined == 1f && me.Powers.BuffIsActive(483574))
{
if (Hud.Game.Me.Powers.UsedSkills.Any(s => s.SnoPower.Sno == Hud.Sno.SnoPowers.Necromancer_LandOfTheDead.Sno && s.Rune == 0))
{
if (RCRStartTick == 0)
RCRStartTick = Hud.Game.CurrentGameTick;
//evidence suggests that the effect is caused by LotD: Invigoration
if (me.Powers.BuffIsActive(Hud.Sno.SnoPowers.Necromancer_LandOfTheDead.Sno, 3) && LandStartTick == 0)
{
IBuff buff = me.Powers.GetBuff(Hud.Sno.SnoPowers.Necromancer_LandOfTheDead.Sno);
LandStartTick = Hud.Game.CurrentGameTick - (int)(buff.TimeElapsedSeconds[0]*60);
}
if (RCRStartTick != 0 && LandStartTick != 0)
{
duration = (double)(RCRStartTick + 600 - Hud.Game.CurrentGameTick)/60d;
totaltime = 10;
//TextLayout notify = NotifyFont.GetTextLayout((RCRStartTick - LandStartTick).ToString());
//NotifyFont.DrawText(notify, Hud.Window.CursorX, Hud.Window.CursorY - notify.Metrics.Height);
}
}
}
else
{
LandStartTick = 0;
RCRStartTick = 0;
}
//bone armor: limited immunity
if (duration < 5 && me.Powers.BuffIsActive(Hud.Sno.SnoPowers.Necromancer_BoneArmor.Sno, 1))
{
IBuff buff = me.Powers.GetBuff(Hud.Sno.SnoPowers.Necromancer_BoneArmor.Sno);
double remaining = buff.TimeLeftSeconds[1];
if (duration < remaining)
{
duration = remaining;
totaltime = buff.TimeElapsedSeconds[1] + remaining;
}
}
//rathma's shield
if (duration < 4 && me.Powers.BuffIsActive(Hud.Sno.SnoPowers.Necromancer_Passive_RathmasShield.Sno, 1))
{
IBuff buff = me.Powers.GetBuff(Hud.Sno.SnoPowers.Necromancer_Passive_RathmasShield.Sno);
double remaining = buff.TimeLeftSeconds[1];
if (duration < remaining)
{
duration = remaining;
totaltime = buff.TimeElapsedSeconds[1] + remaining;
}
}
//final service secondary proc effect
if (duration < 4 && me.Powers.BuffIsActive(Hud.Sno.SnoPowers.Necromancer_Passive_FinalService.Sno, 2))
{
IBuff buff = me.Powers.GetBuff(Hud.Sno.SnoPowers.Necromancer_Passive_FinalService.Sno);
double remaining = me.Powers.GetBuff(Hud.Sno.SnoPowers.Necromancer_Passive_FinalService.Sno).TimeLeftSeconds[2];
if (duration < remaining)
{
duration = remaining;
totaltime = buff.TimeElapsedSeconds[2] + remaining;
}
}
}
else if (me.HeroClassDefinition.HeroClass == HeroClass.WitchDoctor)
{
if (duration < 3 && me.Powers.BuffIsActive(Hud.Sno.SnoPowers.WitchDoctor_SpiritWalk.Sno))
{
//check if spirit walk mojo is equipped
//otherwise
IBuff buff = me.Powers.GetBuff(Hud.Sno.SnoPowers.WitchDoctor_SpiritWalk.Sno);
double remaining = buff.TimeLeftSeconds[0];
if (duration < remaining)
{
duration = remaining;
totaltime = buff.TimeElapsedSeconds[0] + remaining;
}
}
if (duration < 2 && me.Powers.BuffIsActive(Hud.Sno.SnoPowers.WitchDoctor_Passive_SpiritVessel.Sno, 2))
{
IBuff buff = me.Powers.GetBuff(Hud.Sno.SnoPowers.WitchDoctor_Passive_SpiritVessel.Sno);
double remaining = buff.TimeLeftSeconds[2];
if (duration < remaining)
{
duration = remaining;
totaltime = buff.TimeElapsedSeconds[2] + remaining;
}
}
}
if (duration > 0 || me.Powers.BuffIsActive(Hud.Sno.SnoPowers.Generic_InvulnerableDuringBuff.Sno) || me.Defense.drCombined == 1f) //InvulnerableDuringBuff (blood rush, teleport, vault immunity)
{
switch (ShowStyle)
{
case 0:
//show nothing
break;
case 1:
//your character glows yellow
var glowTexture = Hud.Texture.GetTexture(1981524232);
float width = Hud.Window.Size.Width*0.05f; //(100/1920)
glowTexture.Draw(pos.X - width, pos2.Y - width, width*2, width*2, 1f); //100
break;
case 2:
//parenthetical outline of the shield bubble
//TextLayout layout = StyleFont.GetTextLayout("( )"); //ImmunityText
//StyleFont.DrawText(layout, pos.X - layout.Metrics.Width*0.5f, pos2.Y - layout.Metrics.Height*0.6f);
//approximate farthest right point from player's feet given their character model radius
float radius = Hud.Game.Me.RadiusBottom;
float rotation = -45f;
IWorldCoordinate center = Hud.Game.Me.FloorCoordinate;
int i = 2;
float sx = radius * (float)Math.Cos((i * 90 + rotation) * Math.PI / 180f);
float sy = radius * (float)Math.Sin((i * 90 + rotation) * Math.PI / 180f);
IScreenCoordinate sPos = Hud.Window.WorldToScreenCoordinate(center.X + sx, center.Y + sy, center.Z);
//draw right parenthesis
TextLayout layout = StyleFont.GetTextLayout(")");
StyleFont.DrawText(layout, sPos.X, sPos.Y - layout.Metrics.Height*0.97f);
//draw left parenthesis
layout = StyleFont.GetTextLayout("(");
StyleFont.DrawText(layout, pos.X - (sPos.X - pos.X) - layout.Metrics.Width, sPos.Y - layout.Metrics.Height*0.97f);
break;
//default:
}
/*if (ShowCountdownOnCursor && duration > 0)
{
TextLayout notify = NotifyFont.GetTextLayout(duration.ToString(duration < 1 ? "F1" : "F0"));
NotifyFont.DrawText(notify, Hud.Window.CursorX, Hud.Window.CursorY - notify.Metrics.Height);
TextLayout s = SFont.GetTextLayout("s");
SFont.DrawText(s, Hud.Window.CursorX + notify.Metrics.Width, Hud.Window.CursorY - s.Metrics.Height);
}*/
}
}
public void OnRegister(MovableController mover)
{
//initialize position and dimension elements
IPlayer me = Hud.Game.Me;
IScreenCoordinate pos = me.FloorCoordinate.ToScreenCoordinate();
TextLayout notify = NotifyFont.GetTextLayout(ImmunityText); //ImmunityText
float h = Hud.Window.Size.Height * 0.001667f * BarHeight;
float w = Hud.Window.Size.Width * 0.00155f * BarWidth;
w = Math.Max(w, notify.Metrics.Width);
h += notify.Metrics.Height + 3;
//pos.X - notify.Metrics.Width*0.5f, Hud.Game.Me.ScreenCoordinate.Y - Hud.Window.Size.Height*0.2f
//Hud.Game.Me.ScreenCoordinate.Y - Hud.Window.Size.Height*0.2f + notify.Metrics.Height - sLayout.Metrics.Height*1.15f
//MovableAreas.Add(new MovableArea("Countdown") { Enabled = ShowTracker, Rectangle = new RectangleF(ui.Rectangle.X - ProcRuleCalculator.StandardIconSize - Gap, ui.Rectangle.Y, ProcRuleCalculator.StandardIconSize + Gap + Hud.Window.Size.Width * 0.00155f * BarWidth + 12, ProcRuleCalculator.StandardIconSize*4 + Gap*3) });
mover.CreateArea(
this,
"Countdown", //area name
new RectangleF(pos.X - notify.Metrics.Width*0.5f, Hud.Game.Me.ScreenCoordinate.Y - Hud.Window.Size.Height*0.2f, w, h), //position + dimensions
ShowCountdown || ShowCountdownBar, //enabled at start?
true, //save to config file?
ResizeMode.Off //resizable
);
}
//public void PaintTopInGame(ClipState clipState)
//public void PaintWorld(WorldLayer layer)
//public override void PaintFloater(float deltaX = 0, float deltaY = 0)
public void PaintArea(MovableController mover, MovableArea area, float deltaX = 0, float deltaY = 0)
{
var x = area.Rectangle.X + deltaX;
var y = area.Rectangle.Y + deltaY;
var xPos = x + area.Rectangle.Width*0.5f; //center // - notify.Metrics.Width*0.55f - sLayout.Metrics.Width*0.5f;
if (duration > 0 && (ShowCountdown || ShowCountdownBar))
{
if (ShowCountdown)
{
TextLayout notify = NotifyFont.GetTextLayout(duration.ToString(duration < 1 ? "F1" : "F0")); //ImmunityText
TextLayout sLayout = SFont.GetTextLayout("s"); //ImmunityText
NotifyFont.DrawText(notify, xPos - notify.Metrics.Width*0.5f, y);
SFont.DrawText(sLayout, xPos + notify.Metrics.Width*0.55f, y + notify.Metrics.Height - sLayout.Metrics.Height*1.15f);
y += notify.Metrics.Height;
}
if (ShowCountdownBar)
{
float h = (float)(int)(Hud.Window.Size.Height * 0.001667f * BarHeight); //rounding for border line crispness
float w = Hud.Window.Size.Width * 0.00155f * BarWidth;
float pct = (float)(duration / totaltime);
float filled = w * pct;
//float y = Hud.Game.Me.ScreenCoordinate.Y - Hud.Window.Size.Height*0.2f + notify.Metrics.Height; // + 2;
float xBar = xPos - w*0.5f;
BgBrush.DrawRectangle(xBar, y, w, h);
TimerLow.DrawRectangle(xPos - filled*0.5f, y, filled, h);
TimerHigh.Opacity = pct;
TimerHigh.DrawRectangle(xPos - filled*0.5f, y, filled, h);
SkillBorderDark.DrawRectangle(xBar - 1, y - 1, w + 2, h + 2);
SkillBorderLight.DrawRectangle(xBar - 2, y - 2, w + 4, h + 4);
SkillBorderDark.DrawRectangle(xBar - 3, y - 3, w + 6, h + 6);
}
}
else if (ShowCountdown && Hud.Game.Me.Powers.BuffIsActive(Hud.Sno.SnoPowers.Generic_InvulnerableDuringBuff.Sno))
{
TextLayout notify = NotifyFont.GetTextLayout(ImmunityText); //ImmunityText
NotifyFont.DrawText(notify, xPos - notify.Metrics.Width*0.5f, y);
}
}
}
}