private static bool AttachClass() { unit u = GetFilterUnit(); if (GetUnitAbilityLevel(u, FourCC("Aloc")) > 0) { return(false); } if (Indexer.ContainsKey(GetHandleId(u))) { return(false); } if (CustomTypes.ContainsKey(GetUnitTypeId(u))) { Indexer[GetHandleId(u)] = (NoxUnit)Activator.CreateInstance(CustomTypes[GetUnitTypeId(u)], u); } else if (IsUnitType(u, UNIT_TYPE_HERO)) { Indexer[GetHandleId(u)] = new NoxHero(u); } else { Indexer[GetHandleId(u)] = new NoxUnit(u); } u = null; return(false); }
public Status ApplyStatus(NoxUnit source, NoxUnit target, int level, float duration, int initialStacks = 1, int bonusLevel = 0, float bonusDuration = 0, int bonusStacks = 1) { if (!target.ContainsStatus(Id)) { // create new status and add it to unit return(target.AddStatus(Id, new Status(Id, this, source, target, level, duration))); } return(target.GetStatus(Id).Reapply(bonusDuration, bonusLevel, bonusStacks)); }
/// <summary> /// Ensure all damage goes through this. /// </summary> /// <param name="target"></param> /// <param name="damage"></param> public void Damage(NoxUnit target, float damage) { DamageEngineIgnore = true; UnitDamageTarget(this, target, damage, true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_UNIVERSAL, null); DamageEngineIgnore = false; if (IsUnitDeadBJ(target)) { AwaitRemoval(target, this); // weird bug BECAUSE WC3REFUNDED SHIT HI-HI } }
//public Status ApplyStatus(NoxUnit source, NoxUnit target, int level, float duration, int bonusLevel = 0, float bonusDuration = 0, ) //{ // if (!target.ContainsStatus(Id)) // // create new status and add it to unit // return target.AddStatus(Id, new Status(Id, this, source, target, level, duration)); // return target.GetStatus(Id).Reapply(bonusDuration, bonusLevel, 0); //} // [Obsolete] //#pragma warning disable CS0809 // Obsolete member overrides non-obsolete member public override Status ApplyStatus(NoxUnit source, NoxUnit target, int level, float duration, int bonusLevel = 0, float bonusDuration = 0) //#pragma warning restore CS0809 // Obsolete member overrides non-obsolete member { if (!target.ContainsStatus(Id)) { // create new status and add it to unit return(target.AddStatus(Id, new Status(Id, this, source, target, level, duration))); } return(target.GetStatus(Id).Reapply(bonusDuration, bonusLevel, 0)); }
public void RegisterOnHit(NoxUnit whatUnit) { if (whatUnit.ContainsOnHit(Id)) { whatUnit.GetOnHit(Id).Count++; } else { whatUnit.AddOnHit(Id, new OnHit(this)); } }
public void UnregisterOnHit(NoxUnit whatUnit) { if (whatUnit.ContainsOnHit(Id)) { OnHit hit = whatUnit.GetOnHit(Id); hit.Count--; if (hit.Count == 0) { whatUnit.RemoveOnHit(Id); } } }
/// <summary> /// Reverse the source and target to make it AmHit. /// </summary> /// <param name="source"></param> /// <param name="target"></param> public void ApplyOnHit(NoxUnit source, NoxUnit target, float damage, float processedDamage) { if (GetRandomReal(0, 1) < source.TriggerChance * Type.Chance) { if (!Type.Epic) { for (int i = 0; i < Count; i++) { Type.Callback.Invoke(source, target, damage, processedDamage, this); } } else { Type.Callback.Invoke(source, target, damage, processedDamage, this); } } }
// **************** // * Unit Methods * // **************** private void DamageHandler() { if (DamageEngineIgnore) { return; } if (GetEventDamage() < 1) { return; } NoxUnit source = Cast(GetEventDamageSource()); BlzSetEventDamage(0); // ~this is the target //if (!Ranged) // later float dmg = source.WeaponDamage(); source.DealPhysicalDamage(this, dmg, true, true, false, Ranged); }
/// <summary> /// Do not call RemoveUnit on indexed unit or permaleak. /// </summary> /// <param name="u"></param> private static void AwaitRemoval(NoxUnit u, NoxUnit killer) { if (!Indexer.ContainsKey(GetHandleId(u))) { return; // this is a very weird thing to happen, but will happen for Neutrals so yeah } if (u.Corpse) { return; } KillEvent @event = new KillEvent() { EventInfo = new NoxRaven.Events.Metas.KillMeta() { Killer = killer, Dying = u } }; killer.OnKill(@event); u.OnDeath(@event); foreach (Status st in u.Statuses.Values) { st.Remove(); } u.Statuses.Clear();// just in case if (GetUnitAbilityLevel(u, FourCC("Aloc")) > 0) { return; // wat } if (IsUnitType(u, UNIT_TYPE_HERO)) { return; // always leak heroes } u.Corpse = true; Utils.DelayedInvoke(KeepCorpsesFor, () => { u.Remove(); }); // ah shiet, change to let resurrections //ue = null; }
/// <summary> /// Permanent status. /// </summary> /// <param name="id"></param> /// <param name="type"></param> /// <param name="source"></param> /// <param name="target"></param> /// <param name="level"></param> /// <param name="duration"></param> /// <param name="stacking"></param> /// <param name="periodic"></param> private Status(int id, TimedType type, NoxUnit source, NoxUnit target, int level, int initialStacks, int stacksLim, float duration, float periodicTimeout, bool stacking, bool periodic, bool permanent = false) { //if(type.DataType != null) //Data = Activator.CreateInstance(type.DataType); Id = id; Type = type; Source = source; Target = target; Level = level; Stacking = stacking; Periodic = periodic; //Permanent = permanent; PeriodicTimeout = periodicTimeout; StacksLim = stacksLim; Duration = duration; t = CreateTimer(); if (periodic) { PeriodicTicks = 0; TimeRemain = duration; TimerStart(t, PeriodicTimeout, false, PeriodicTimerRestart); } else { TimerStart(t, duration, false, Remove); } if (stacking) { Stacks = initialStacks; } if (Type.Apply != null) { Type.Apply.Invoke(this); } if (Type.Effectpath != null && Type.Attachment != null) { SpecialEffect = AddSpecialEffectTarget(Type.Effectpath, target._Self, Type.Attachment); } }
public bool ContainsOnHit(NoxUnit whatUnit) { return(whatUnit.ContainsOnHit(Id)); }
/// <summary> /// Damage parsers that takes care of all calculations. Damage parser calculates outgoing damage from the unit. /// </summary> /// <param name="target">Whos is the target</param> /// <param name="damage"></param> /// <param name="triggerOnHit">Does it apply on-hit effects?</param> /// <param name="triggerCrit">Can it crit?</param> public void DealPhysicalDamage(NoxUnit target, float damage, bool triggerOnHit, bool triggerCrit, bool isSpell, bool isRanged) { if (damage < 0) { return; } location loc = Location(GetUnitX(target) + GetRandomReal(0, 5), GetUnitY(target) + GetRandomReal(0, 5)); float pars = damage; float critC = CritChance; float critD = CritDamage; // maths pars *= (1 - Math.Min(target.DamageReduction, 1)); float armor = BlzGetUnitArmor(target); if (armor < 0) { pars *= (1.71f - Pow(1f - ARMOR_CONST, -armor)); // war3 real armor reduction is 1.71-pow(xxx) - why? - no idea } else { pars *= 1 / (1 + armor * ARMOR_CONST * (1 - ArmorPenetration)); // Inverse armor reduction function, got by solving: Armor * CONST / (1 + ARMOR * CONST) } //Event Pars DamageEvent parsThroughUnit = new DamageEvent() { EventInfo = new DamageMeta() { Source = this, Target = target, Damage = damage, TriggerOnHit = triggerOnHit, TriggerCrit = triggerCrit, IsSpell = isSpell, IsRanged = isRanged }, ProcessedDamage = pars, CritChance = critC, CritDamage = critD }; OnDealPhysicalDamage.Invoke(parsThroughUnit); target.OnRecievePhysicalDamage.Invoke(parsThroughUnit); pars = parsThroughUnit.ProcessedDamage; critC = parsThroughUnit.CritChance; critD = parsThroughUnit.CritDamage; // The logic if (triggerCrit && GetRandomReal(0, 1) < critC) { pars *= critD; Utils.TextDirectionRandom(Utils.NotateNumber(R2I(pars)), loc, 8.5f, 255, 0, 0, 0, 1.3f, GetOwningPlayer(this)); Utils.TextDirectionRandom(Utils.NotateNumber(R2I(pars)), loc, 8.5f, 255, 0, 0, 0, 1.3f, GetOwningPlayer(target)); } else { Utils.TextDirectionRandom(Utils.NotateNumber(R2I(pars)), loc, 6.9f, 255, 0, 0, 0, 0.8f, GetOwningPlayer(this)); Utils.TextDirectionRandom(Utils.NotateNumber(R2I(pars)), loc, 6.9f, 255, 0, 0, 0, 0.8f, GetOwningPlayer(target)); } Damage(target, pars); if (isSpell) { Heal(pars * SpellVamp); } else { Heal(pars * Lifesteal); } // Now that's done // Onhits if (triggerOnHit) { List <OnHit> onhits = new List <OnHit>(OnHits.Values); foreach (OnHit onhit in onhits) { onhit.ApplyOnHit(this, target, damage, pars); } //ApplyAmHits(source); } // cleanup RemoveLocation(loc); loc = null; }
/// <summary> /// Periodic Timed Stacking Status /// </summary> internal Status(int id, TimedType type, NoxUnit source, NoxUnit target, int level, float duration, float peridoticTimeout, int initialStacks, int stacksLim) : this(id, type, source, target, level, initialStacks, stacksLim, duration, peridoticTimeout, false, true) { }
/// <summary> /// Periodic Timed Status /// </summary> internal Status(int id, TimedType type, NoxUnit source, NoxUnit target, int level, float duration, float periodicTimeout) : this(id, type, source, target, level, 0, 0, duration, periodicTimeout, false, true) { }
///// <summary> ///// Permanent Status ///// </summary> //internal Status(int id, StatusType type, NoxUnit source, NoxUnit target, int level) // : this(id, type, source, target, level, 0, 0, 0, 0, false, false, true) { } ///// <summary> ///// Permanent Stacking ///// </summary> //internal Status(int id, StatusType type, NoxUnit source, NoxUnit target, int level, int initialStacks, int stacksLim) // : this(id, type, source, target, level, initialStacks, stacksLim, 0, 0, true, false, true) { } ///// <summary> ///// Permanent Periodic ///// </summary> ///// <param name="id"></param> ///// <param name="type"></param> ///// <param name="source"></param> ///// <param name="target"></param> ///// <param name="level"></param> //internal Status(int id, StatusType type, NoxUnit source, NoxUnit target, int level) // : this(id, type, source, target, level, 0, 0, 0, 0, false, true, true) { } /// <summary> /// Timed Status /// </summary> internal Status(int id, TimedType type, NoxUnit source, NoxUnit target, int level, float duration) : this(id, type, source, target, level, 0, 0, duration, 0, false, false) { }
public OnHit GetOnHit(NoxUnit whatUnit) { return(whatUnit.GetOnHit(Id)); }
public Status GetStatus(NoxUnit unit) => unit.GetStatus(Id);
/// <summary> /// Run when all static data is initialized.<br /> /// Types taht need to be initialized before running: UnitEntity Custom Classes, Players, Items /// </summary> public static void RunAfterExtensionsReady() { int abilid = FourCC("AD00"); for (int i = 0; i < NoxUnit.Abilities_BonusDamage.Length; i++) { NoxUnit.Abilities_BonusDamage[i] = abilid; if ((i + 1) % 10 == 0) { abilid += 246; } abilid++; } abilid = FourCC("AR00"); for (int i = 0; i < NoxUnit.Abilities_BonusArmor.Length; i++) { NoxUnit.Abilities_BonusArmor[i] = abilid; if ((i + 1) % 10 == 0) { abilid += 246; } abilid++; } abilid = FourCC("CR00"); for (int i = 0; i < NoxUnit.Abilities_Corruption.Length; i++) { NoxUnit.Abilities_Corruption[i] = abilid; if ((i + 1) % 10 == 0) { abilid += 246; } abilid++; } abilid = FourCC("ST00"); for (int i = 0; i < NoxHero.Abilities_Strength.Length; i++) { NoxHero.Abilities_Strength[i] = abilid; if ((i + 1) % 10 == 0) { abilid += 246; } abilid++; } abilid = FourCC("AG00"); for (int i = 0; i < NoxHero.Abilities_Agility.Length; i++) { NoxHero.Abilities_Agility[i] = abilid; if ((i + 1) % 10 == 0) { abilid += 246; } abilid++; } abilid = FourCC("IN00"); for (int i = 0; i < NoxHero.Abilities_Intelligence.Length; i++) { NoxHero.Abilities_Intelligence[i] = abilid; if ((i + 1) % 10 == 0) { abilid += 246; } abilid++; } NoxUnit.InitUnitLogic(); NoxItem.InitItemLogic(); NoxAbility.InitAbilityLogic(); TimerStart(CreateTimer(), 1800, true, GCRoutine); }
public void Kill(NoxUnit whoToKill) { Kill(whoToKill); AwaitRemoval(this, whoToKill); }