All pastes #499781 Raw Edit

rogue patch

public cpp v1 · immutable
·published 2007-05-21 07:25 UTC
rendered paste body
Index: src/game/Object.cpp===================================================================--- src/game/Object.cpp    (revision 3674)+++ src/game/Object.cpp    (working copy)@@ -672,7 +672,8 @@     float dx = GetPositionX() - obj->GetPositionX();     float dy = GetPositionY() - obj->GetPositionY();     float dz = GetPositionZ() - obj->GetPositionZ();-    float sizefactor = GetObjectSize() + obj->GetObjectSize();+    float sizefactor = GetObjectSize() + obj->GetObjectSize()- 2.28; //size factor is too big student1+    if (sizefactor <= 0) sizefactor = 1; //makes sures values are not negative for too little objects student1     float dist = sqrt((dx*dx) + (dy*dy) + (dz*dz)) - sizefactor;     return ( dist > 0 ? dist * dist : 0);}Index: src/game/Spell.cpp===================================================================--- src/game/Spell.cpp    (revision 3674)+++ src/game/Spell.cpp    (working copy)@@ -43,6 +43,7 @@#include "SharedDefines.h"#include "Tools.h"+#define SPELL_CHANNEL_UPDATE_INTERVAL 1000extern pEffect SpellEffects[TOTAL_SPELL_EFFECTS];@@ -1234,11 +1235,11 @@                     if( ((Player*)m_caster)->HasMovementFlags(MOVEMENTFLAG_JUMPING) )                         cancel();-                    // check for incapacitating player states-                    if( m_caster->hasUnitState(UNIT_STAT_STUNDED) ||+                   // check for incapacitating player states+                   if( (( m_caster->hasUnitState(UNIT_STAT_STUNDED) ||                         m_caster->hasUnitState(UNIT_STAT_ROOT) ||-                        m_caster->hasUnitState(UNIT_STAT_CONFUSED) )-                        cancel();+                        m_caster->hasUnitState(UNIT_STAT_CONFUSED))) &&    (m_spellInfo->SpellIconID != 252))//Player can use vanish even if he is incapacitated                      +                        cancel();                     // check if player has turned if flag is set                     if( m_spellInfo->ChannelInterruptFlags & CHANNEL_FLAG_TURNING && m_castOrientation != m_caster->GetOrientation() )@@ -1956,6 +1957,12 @@             }         }+        +        // Target must not be in combat from what i know only R0gu3\S4p requires that+        // TODO: find a correct mask ?+       // if(m_spellInfo->SpellIconID == 249  && m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && target->isInCombat())+       //     return SPELL_FAILED_TARGET_IN_COMBAT;+         //Must be behind the target.         if( m_spellInfo->AttributesEx2 == 0x100000 && (m_spellInfo->AttributesEx & 0x200) == 0x200 && target->HasInArc(M_PI, m_caster) )         {@@ -1979,11 +1986,21 @@         if(m_spellInfo->AreaId && m_spellInfo->AreaId != m_caster->GetAreaId())             return SPELL_FAILED_REQUIRES_AREA;     }+    //If caster or target is a player that is stunned will not be able to restun that target again (student1) Also caster will not be able to stun a mob 5 levels higher+    if (m_caster->hasUnitState(UNIT_STAT_STUNDED))+        return SPELL_FAILED_STUNNED;-    if(m_caster->hasUnitState(UNIT_STAT_STUNDED))+    //If already stunned cannot restun player+    if (((m_spellInfo->SpellIconID == 249) && (m_targets.getUnitTarget()->hasUnitState(UNIT_STAT_STUNDED))+        && (m_targets.getUnitTarget()->GetTypeId()==TYPEID_PLAYER)))         return SPELL_FAILED_STUNNED;-    // not let players cast non-triggered spells at mount (and let do it to creatures)+    //will not be able to stun a high level player+    if((target->getLevel() > m_caster->getLevel() + 10)&&(m_spellInfo->SpellIconID == 249)+        && (target->GetTypeId()==TYPEID_PLAYER))+            return SPELL_FAILED_HIGHLEVEL;+    +    // not let players cast non-triggered spells at mount (and let do it to creatures)     if(m_caster->IsMounted() && !m_IsTriggeredSpell && m_caster->GetTypeId()==TYPEID_PLAYER)         return SPELL_FAILED_NOT_MOUNTED;@@ -2272,7 +2289,7 @@                 //detect if any mod is in x range.if true,can't steath.FIX ME!                 if(m_spellInfo->Attributes == 169148432 || m_caster->GetTypeId() != TYPEID_PLAYER)                     break;-+                // Find nearby creatures                 CellPair p(MaNGOS::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY()));                 Cell cell = RedZone::GetZone(p);                 cell.data.Part.reserved = ALL_DISTRICT;@@ -2285,7 +2302,11 @@                 CellLock<GridReadGuard> cell_lock(cell, p);                 cell_lock->Visit(cell_lock, object_checker, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));-                if(found_creature)+                +                            +                // If mob found is not stunned or R0gu3\V4nish is not being used, can't stealth+                if (((found_creature) && (m_spellInfo->SpellIconID != 252)) &&+                    (!found_creature->hasUnitState(UNIT_STAT_STUNDED)))                     return SPELL_FAILED_CANT_STEALTH;             };break;@@ -2822,3 +2843,7 @@     m_targets.Update(m_caster);}Index: src/game/Spell.h===================================================================--- src/game/Spell.h    (revision 3674)+++ src/game/Spell.h    (working copy)@@ -418,6 +418,7 @@     public:         void EffectNULL(uint32 );+        void EffectDistract(uint32 i);         void EffectSchoolDMG(uint32 i);         void EffectInstaKill(uint32 i);         void EffectDummy(uint32 i);Index: src/game/SpellAuras.cpp===================================================================--- src/game/SpellAuras.cpp    (revision 3674)+++ src/game/SpellAuras.cpp    (working copy)@@ -43,11 +43,14 @@#include "ConfusedMovementGenerator.h"#include "TargetedMovementGenerator.h"#include "Formulas.h"+#include "CreatureAI.h"#include "BattleGround.h"-#include "CreatureAI.h"++pAuraHandler AuraHandler[TOTAL_AURAS]={+     &Aura::HandleNULL,                                      //  0 SPELL_AURA_NONE     &Aura::HandleBindSight,                                 //  1 SPELL_AURA_BIND_SIGHT     &Aura::HandleModPossess,                                //  2 SPELL_AURA_MOD_POSSESS@@ -202,7 +205,7 @@     &Aura::HandleAuraTrackStealthed,                        //151 SPELL_AURA_TRACK_STEALTHED     &Aura::HandleNULL,                                      //152 SPELL_AURA_MOD_DETECTED_RANGE     &Aura::HandleNULL,                                      //153 SPELL_AURA_SPLIT_DAMAGE_FLAT-    &Aura::HandleNULL,                                      //154 SPELL_AURA_MOD_STEALTH_LEVEL+    &Aura::HandleNoImmediateEffect,                         //154 SPELL_AURA_MOD_STEALTH_LEVEL     &Aura::HandleNULL,                                      //155 SPELL_AURA_MOD_WATER_BREATHING     &Aura::HandleNoImmediateEffect,                         //156 SPELL_AURA_MOD_REPUTATION_GAIN     &Aura::HandleNULL,                                      //157 SPELL_AURA_PET_DAMAGE_MULTI@@ -269,6 +272,9 @@     &Aura::HandleNULL,                                      //218     &Aura::HandleNULL,                                      //219 SPELL_AURA_MOD_MANA_REGEN     &Aura::HandleNULL,                                      //220+++};Aura::Aura(SpellEntry const* spellproto, uint32 eff, Unit *target, Unit *caster, Item* castItem) :@@ -1584,7 +1590,6 @@     //TODO: add stealthed tracking effect}-void Aura::HandleAuraModScale(bool apply, bool Real){     m_target->ApplyPercentModFloatValue(OBJECT_FIELD_SCALE_X,m_modifier.m_amount,apply);@@ -1744,15 +1749,21 @@void Aura::HandleModConfuse(bool apply, bool Real){+     Unit* caster = GetCaster();+    uint32 apply_stat = UNIT_STAT_CONFUSED;-    uint32 apply_stat = UNIT_STAT_CONFUSED;     if( apply )     {         m_target->addUnitState(UNIT_STAT_CONFUSED);                                                             // probably wrong         m_target->SetFlag(UNIT_FIELD_FLAGS,(apply_stat<<16));+        // R0gu3/Bl1nd ability stops attack+        // TODO: does all confuses ?+        if ( caster && (GetSpellProto()->Mechanic == MECHANIC_CONFUSED) && (GetSpellProto()->SpellFamilyName == SPELLFAMILY_ROGUE))+             caster->AttackStop();+         // only at real add aura         if(Real)         {@@ -1897,6 +1908,11 @@         m_target->SetUInt64Value (UNIT_FIELD_TARGET, 0);         m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE);+      // Stop attack if spell has knockout effect+       if (caster && (GetSpellProto()->Mechanic == MECHANIC_KNOCKOUT))+           caster->AttackStop();+      +         // only at real add aura         if(Real)         {@@ -1913,20 +1929,24 @@                 m_target->SetOrientation(m_target->GetAngle(caster));             }+            // Creature specific             if(m_target->GetTypeId() != TYPEID_PLAYER)             {                 ((Creature *)m_target)->StopMoving();+                 //Removes threat and stops combat state so from player so he can re-stealth                 if( GetSpellProto()->SpellFamilyName == SPELLFAMILY_ROGUE && (GetSpellProto()->SpellIconID == 249) )                 {                     //Unit will not attack player if out of range                    ((Creature *)m_target)->CombatStop();+                   caster->RemoveFromInHateListOf(((Creature *)m_target));                    ((Creature *)m_target)->DeleteThreatList();                 }             }             WorldPacket data(SMSG_FORCE_MOVE_ROOT, 8);+             data.append(m_target->GetPackGUID());             data << uint32(0);             m_target->SendMessageToSet(&data,true);@@ -1948,6 +1968,7 @@             data << uint32(0);             m_target->SendMessageToSet(&data,true);+             //If sap is used then threat is removed and mob goes back to normal waypoint             if( m_target->GetTypeId() != TYPEID_PLAYER && GetSpellProto()->SpellFamilyName == SPELLFAMILY_ROGUE && (GetSpellProto()->SpellIconID == 249))             {  @@ -1958,6 +1979,18 @@                                     if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_HUNTER && GetSpellProto()->SpellIconID == 1721)             {+                // Unit will not attack player if out of range+                if(caster)+                    caster->RemoveFromInHateListOf(((Creature *)m_target));++                ((Creature *)m_target)->CombatStop();+                ((Creature *)m_target)->AI()->EnterEvadeMode();+                ((Creature *)m_target)->DeleteThreatList();+                ((Creature *)m_target)->RemoveAllAuras();+            }++            if ((GetSpellProto()->SpellFamilyName == SPELLFAMILY_HUNTER && GetSpellProto()->SpellIconID == 1721))+            {                 if( !caster || caster->GetTypeId()!=TYPEID_PLAYER )                     return;@@ -1989,7 +2022,8 @@void Aura::HandleModStealth(bool apply, bool Real){-    if(apply)+   Unit* caster = GetCaster();+   if(apply)     {         m_target->m_stealthvalue = CalculateDamage();         m_target->SetFlag(UNIT_FIELD_BYTES_1, PLAYER_STATE_FLAG_STEALTH);@@ -2008,17 +2042,22 @@                 m_target->CastSpell(m_target, 21009, true, NULL, this);                 m_target->ApplyStats(false);             }-        }+        }     }     else     {         m_target->m_stealthvalue = 0;         m_target->RemoveFlag(UNIT_FIELD_BYTES_1, PLAYER_STATE_FLAG_STEALTH);-         // only at real aura remove         if(Real)         {+            // Caster comes back to normal state after vanish is finished.+            if (caster->hasUnitState(UNIT_STAT_VANISHED))+               caster->clearUnitState(UNIT_STAT_VANISHED);++            // Make target visible             m_target->SetVisibility(VISIBILITY_ON);+             if(m_target->GetTypeId() == TYPEID_PLAYER)                 m_target->SendUpdateToPlayer((Player*)m_target);Index: src/game/SpellAuras.h===================================================================--- src/game/SpellAuras.h    (revision 3674)+++ src/game/SpellAuras.h    (working copy)@@ -162,7 +162,7 @@         void HandleModShieldBlockPCT(bool Apply, bool Real);         void HandleAuraTrackStealthed(bool Apply, bool Real);         void HandleModShieldBlock(bool Apply, bool Real);-        void HandleForceReaction(bool Apply, bool Real);+        void HandleForceReaction(bool Apply, bool Real);         void HandleAuraModRangedHaste(bool Apply, bool Real);         void HandleRangedAmmoHaste(bool Apply, bool Real);         void HandleModHealingDone(bool Apply, bool Real);Index: src/game/SpellEffects.cpp===================================================================--- src/game/SpellEffects.cpp    (revision 3674)+++ src/game/SpellEffects.cpp    (working copy)@@ -50,6 +50,7 @@pEffect SpellEffects[TOTAL_SPELL_EFFECTS]={+     &Spell::EffectNULL,                                     //  0     &Spell::EffectInstaKill,                                //  1 SPELL_EFFECT_INSTAKILL     &Spell::EffectSchoolDMG,                                //  2 SPELL_EFFECT_SCHOOL_DAMAGE@@ -119,7 +120,7 @@     &Spell::EffectNULL,                                     // 66 SPELL_EFFECT_POWER_FUNNEL             unused     &Spell::EffectHealMaxHealth,                            // 67 SPELL_EFFECT_HEAL_MAX_HEALTH     &Spell::EffectInterruptCast,                            // 68 SPELL_EFFECT_INTERRUPT_CAST-    &Spell::EffectNULL,                                     // 69 SPELL_EFFECT_DISTRACT+    &Spell::EffectDistract,                                 // 69 SPELL_EFFECT_DISTRACT     &Spell::EffectNULL,                                     // 70 SPELL_EFFECT_PULL                     one spell: Distract Move     &Spell::EffectPickPocket,                               // 71 SPELL_EFFECT_PICKPOCKET     &Spell::EffectAddFarsight,                              // 72 SPELL_EFFECT_ADD_FARSIGHT@@ -186,6 +187,7 @@     &Spell::EffectNULL,                                     //133 SPELL_EFFECT_133                      one spell: Forget     &Spell::EffectNULL,                                     //134 SPELL_EFFECT_134     &Spell::EffectNULL,                                     //135 SPELL_EFFECT_135                      pet related+};void Spell::EffectNULL(uint32 i)@@ -352,8 +354,8 @@         }         return;     }--    // Cold Snap - immediately finishes the cooldown on Frost spells+      +    // Cold Snap - immediately finishes the cooldown on Frost spells     if(m_spellInfo->Id == 12472)     {         if(m_caster->GetTypeId()!=TYPEID_PLAYER)@@ -1494,31 +1496,77 @@         ((Player*)unitTarget)->SetCanDualWield(true);}+void Spell::EffectDistract(uint32 i)+{+   // Check for possible target this line crashed server so removed+   // if (!unitTarget)+   //     return;++    int32 levelDiff = m_caster->getLevel() - unitTarget->getLevel();++    //If there is a victim to distract+    if ((levelDiff > -5) && unitTarget->IsHostileTo(m_caster))+    {+        // Gets angle of distract epicenter / target+        float angle = unitTarget->GetAngle(m_targets.m_destX, m_targets.m_destY);++        //Set proper orientation+        unitTarget->SetOrientation(angle);++        // Update animation if target is creature+        if(unitTarget->GetTypeId() != TYPEID_PLAYER)+        {++            Creature& pUnit = *((Creature *)unitTarget);++            // Creature movement notifier+            CellPair cPair = MaNGOS::ComputeCellPair(pUnit.GetPositionX(), pUnit.GetPositionY());+            Cell cell = RedZone::GetZone(cPair);+            cell.data.Part.reserved = ALL_DISTRICT;+            MaNGOS::CreatureVisibleMovementNotifier notifier(pUnit);+            TypeContainerVisitor<MaNGOS::CreatureVisibleMovementNotifier, WorldTypeMapContainer > player_notifier(notifier);+            CellLock<GridReadGuard> cell_lock(cell, cPair);+            cell_lock->Visit(cell_lock, player_notifier, *MapManager::Instance().GetMap(pUnit.GetMapId(), &pUnit));++            // Stop moving+            ((Creature *)unitTarget)->StopMoving();++            // TODO: set time to distract center and resume walking with the pull fct++        }+    }+}+void Spell::EffectPickPocket(uint32 i){+    // Only players can pickpocket     if( m_caster->GetTypeId() != TYPEID_PLAYER )         return;-    //victim must be creature and attackable+    // Victim must be creature and not friendly     if( !unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT || m_caster->IsFriendlyTo(unitTarget) )         return;-    //victim have to be alive and humanoid or undead-    if( unitTarget->isAlive() &&-        (((Creature*)unitTarget)->GetCreatureInfo()->type == CREATURE_TYPE_HUMANOID ||-        ((Creature*)unitTarget)->GetCreatureInfo()->type == CREATURE_TYPE_UNDEAD))+    // Victim have to be alive and humanoid or undead+    // TODO: should be checked in Spell::CanCast() Spell.cpp:1826+    if( unitTarget->isAlive() && (+        ((Creature*)unitTarget)->GetCreatureInfo()->type == CREATURE_TYPE_HUMANOID ||+        ((Creature*)unitTarget)->GetCreatureInfo()->type == CREATURE_TYPE_UNDEAD+      ))     {-        int32 chance = 10 + m_caster->getLevel() - unitTarget->getLevel();-+        // TODO: check wowwiki.com formula+        int32 chance = 15 + m_caster->getLevel() - unitTarget->getLevel();         if (chance > irand(0, 19))         {             //Stealing successful+             //sLog.outDebug("Sending loot from pickpocket");             ((Player*)m_caster)->SendLoot(unitTarget->GetGUID(),LOOT_PICKPOCKETING);+         }         else         {-            //Reveal action + get attack+            // Reveal caster             m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);             if (((Creature*)unitTarget)->AI())                 ((Creature*)unitTarget)->AI()->AttackStart(m_caster);@@ -2333,6 +2381,24 @@     if(!unitTarget)         return;     unitTarget->CombatStop();+    +    //Vanish allows to remove all treat and cast regular stealth so other spells can be used+        if (m_spellInfo->SpellIconID == 252)  +            {+             m_caster->AttackStop();+            ((Player *)m_caster)->addUnitState(UNIT_STAT_VANISHED);+            }          +    +    +    //If player is rooted player looses root with vanish+       if ((m_caster->hasUnitState(UNIT_STAT_ROOT)&& (m_spellInfo->SpellIconID == 252)))+           {+                              +            ((Player *)m_caster)->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);+            ((Player *)m_caster)->ApplySpellImmune(339,IMMUNITY_MECHANIC,8,true);                        +                  +           }+        }void Spell::EffectAddComboPoints(uint32 i)Index: src/game/Unit.cpp===================================================================--- src/game/Unit.cpp    (revision 3674)+++ src/game/Unit.cpp    (working copy)@@ -39,6 +39,11 @@#include "Totem.h"#include "TemporarySummon.h"+// TODO: check if those are needed+#include "RedZoneDistrict.h"+#include "CellImpl.h"+#include "GridNotifiersImpl.h"+#include "MapManager.h"#include <math.h>float baseMoveSpeed[MAX_MOVE_TYPE] =@@ -4594,17 +4599,16 @@     return gain;}+bool Unit::isVisibleFor(Unit* u, bool detect){-    if(!u)-        return false;--    // Visible units, always are visible for all pjs+    +    // Visible units, always are visible for all pjs     if (m_Visibility == VISIBILITY_ON)         return true;     // Always can see self-    if (u==this)+    if (u == this)         return true;     // GMs are visible for higher gms (or players are visible for gms)@@ -4634,35 +4638,203 @@             return true;     }-    // if in non-detect mode then invisible for unit-    if(!detect)-        return false;+    +    //if in non-detect mode then invisible for unit+     if ((!detect) && (!u->IsHostileTo(this)))+         return false;+    ++    // Special cases     bool IsVisible = true;-    bool notInFront = u->isInFront(this, MAX_DIST_INVISIBLE_UNIT * MAX_DIST_INVISIBLE_UNIT) ? 0 : 1;-    float Distance = sqrt(GetDistanceSq(u));+    bool isNotFront = u->isInFront(this, MAX_DIST_INVISIBLE_UNIT * MAX_DIST_INVISIBLE_UNIT)? 0 : 1;+    float distance = sqrt(GetDistanceSq(u));++    // If is attacked then stealth is lost, some creature can use stealth too+    if (this->isAttacked())+        return IsVisible && ( distance <= MAX_DIST_INVISIBLE_UNIT * MAX_DIST_INVISIBLE_UNIT);++    // If there is collision rogue is seen regardless of level difference+    // TODO: check sizes in DB+    if (distance < 0.5f)+        return IsVisible && ( distance <= MAX_DIST_INVISIBLE_UNIT * MAX_DIST_INVISIBLE_UNIT);++    //If a mob or player is stunned he will not be able to detect stealth+    if ((u->hasUnitState(UNIT_STAT_STUNDED)) && (u != this))+    {+        IsVisible = false;+        return IsVisible && ( distance <= MAX_DIST_INVISIBLE_UNIT * MAX_DIST_INVISIBLE_UNIT);+    }++    // Cases based on level difference and position+    int32 levelDiff = u->getLevel() - this->getLevel();++    // If victim has more than 5 lvls above caster+    if ((this->GetTypeId() == TYPEID_UNIT)&& ( levelDiff > 5 ))+        return IsVisible && ( distance <= MAX_DIST_INVISIBLE_UNIT * MAX_DIST_INVISIBLE_UNIT);++    // If caster has more than 5 levels above victim+    if ((this->GetTypeId() == TYPEID_UNIT)&& ( levelDiff < -5 ))+    {+        IsVisible = false;+        return IsVisible && ( distance <= MAX_DIST_INVISIBLE_UNIT * MAX_DIST_INVISIBLE_UNIT);+    }+     float prob = 0;+    float modifier = 1; // 100 pct+    float pvpMultiplier = 0;+    float distanceFormula = 0;+    int32 rank = 0;+    //This allows to check talent tree and will add addition stealth dependant on used points)+     uint32 stealthMod = 0;+     AuraList& mStealthMod = GetAurasByType(SPELL_AURA_MOD_STEALTH_LEVEL);+     for(AuraList::iterator i = mStealthMod.begin();i != mStealthMod.end(); ++i)+         stealthMod += (*i)->GetModifier()->m_amount;+    //****************************************************************************************+    int32 x = (((u->m_detectStealth+1) / 5) - (((m_stealthvalue+1) / 5) + (stealthMod/5) + 59)); // Stealth detection calculation+    +    if (x<0) x = 1;+    // Check rank if mob is not a player otherwise rank = 1 and there is no modifier when in pvp+    if (u->GetTypeId() != TYPEID_PLAYER)+        rank = ((Creature const*)u)->GetCreatureInfo()->rank;-    // Function for detection (can be improved)-    // Take into account that this function is executed every x secs, so prob must be low for right working+    // Probabilty of being seen+    if (levelDiff < 0)+        distanceFormula = ((sWorld.getRate(RATE_CREATURE_AGGRO) * 16) / (abs(levelDiff) + 1.5)) * 2;+    if (levelDiff >= 0)+        distanceFormula = (((sWorld.getRate(RATE_CREATURE_AGGRO) * 16)) / 2) * (levelDiff + 1);-    int32 x = u->getLevel() + (u->m_detectStealth / 5) - (m_stealthvalue / 5) + 59;-    if (x<0) x = 0;-    float AverageDist = 1 - 0.11016949*x + 0.00301637*x*x;  //at this distance, the detector has to be a 15% prob of detect-    if (AverageDist < 1) AverageDist = 1;-    if (Distance > AverageDist)-        //prob between 10% and 0%-        prob = (AverageDist-200+9*Distance)/(AverageDist-20);+    // Original probability values+    // removed level of mob in calculation as it should not affect the detection, it is mainly dependant on level difference+    float averageDist = 1 - 0.11016949 * x + 0.00301637 * x * x;  //at this distance, the detector has to be a 15% prob of detect+    if (averageDist < 1) averageDist = 1;++    if (distance > averageDist)+        prob = (averageDist - 200 + 9 * distance) / (averageDist - 20);     //prob between 10% and 0%     else-        prob = 75 - (60/AverageDist)*Distance;              //prob between 15% and 75% (75% max prob)-    if (notInFront)-        prob = prob/100;+        prob = 75 - (60 / averageDist) * distance;                          //prob between 15% and 75% (75% max prob)++    // If is not in front, probability floor+    if (isNotFront)+        prob = prob / 100;     if (prob < 0.1)-        prob = 0.1;                                         //min prob of detect is 0.1+        prob = 0.1;-    IsVisible = roll_chance_f(prob);+  +    // Mob rank affects modifier+    modifier = rank <= 4 ? 1 + rank * 0.2f : 1;-    return IsVisible && ( Distance <= MAX_DIST_INVISIBLE_UNIT * MAX_DIST_INVISIBLE_UNIT);++    // PVP distance assigned depending on level+    if (this->GetTypeId() == TYPEID_PLAYER)+    {+        // Level diff floor/ceiling <-5,5>+        pvpMultiplier = levelDiff > 5 ? 12 : levelDiff < 5 ? 2 : 7 + levelDiff;+        pvpMultiplier = pvpMultiplier - (x / 100);+    }++    // PVP stealth handler+    if (this->GetTypeId() == TYPEID_PLAYER)+    {+        // Do not loose stealth when coming from back unless mob is more than 10 levels higher than rogue+        if ((isNotFront) && (levelDiff > -10 ))+        {+            IsVisible = false;+            return IsVisible && ( distance <= MAX_DIST_INVISIBLE_UNIT * MAX_DIST_INVISIBLE_UNIT);+        }++        // If comes in front+        if (!isNotFront && (distance >= pvpMultiplier))+        {+            IsVisible = false;+            return IsVisible && ( distance <= MAX_DIST_INVISIBLE_UNIT * MAX_DIST_INVISIBLE_UNIT);+        }++        if (!isNotFront && (distance < pvpMultiplier))+        {+            IsVisible = true;+            return IsVisible && ( distance <= MAX_DIST_INVISIBLE_UNIT * MAX_DIST_INVISIBLE_UNIT);+        }+    }+    else+    {+        // PVE stealth handler++        +        // Distance of approch player stays stealth 100% is dependant of level. No probabiliy or detection is rolled+        // This establishes a buffer zone in between mob start to see you and mob start to roll probabilities or detect you+        if ((distance < 100) && (distance > ((distanceFormula * 2) * modifier)) && (distance > 0.24f))+        {+            IsVisible = false;+            return IsVisible && ( distance <= MAX_DIST_INVISIBLE_UNIT * MAX_DIST_INVISIBLE_UNIT);++        }++        //If victim is level lower or more probability of detection drops+        if ((levelDiff < 0) && (distance > 0.24f))+        {+            if (abs(levelDiff ) > 4)+                IsVisible = false;+            else+            {+                if (rand_chance() > ( prob * modifier / (30 + levelDiff * 5)))+                    IsVisible = false;+            }++            return IsVisible && ( distance <= MAX_DIST_INVISIBLE_UNIT * MAX_DIST_INVISIBLE_UNIT);+        }++        //If mob is a higher level but is approached from behind, mob will turn towards the player and attack if closer than 7 feet+        if ( ( levelDiff >= 5) && (distance > 0.24f) )+        {+            // Cast unit to creature+            Creature& pUnit = *(Creature *)u;++            // Creature turns to look at caster+            ((Creature* )u)->SetInFront(this);++            CellPair cPair = MaNGOS::ComputeCellPair(pUnit.GetPositionX(), pUnit.GetPositionY());+            Cell cell = RedZone::GetZone(cPair);+            cell.data.Part.reserved = ALL_DISTRICT;+            MaNGOS::CreatureVisibleMovementNotifier notifier(pUnit);+            TypeContainerVisitor<MaNGOS::CreatureVisibleMovementNotifier, WorldTypeMapContainer > player_notifier(notifier);+            CellLock<GridReadGuard> cell_lock(cell, cPair);+            cell_lock->Visit(cell_lock, player_notifier, *MapManager::Instance().GetMap(pUnit.GetMapId(), &pUnit));+            ((Creature *)u)->StopMoving();++            //If player comes close to mob he gets detected ( Formula is based on agro and level difference between mob and player+            //Formula used is (((aggro * 16)/5) * level difference between mob and player) Will give you the level of detection+            //At agro 0.4 and at a difference of 5 levels you can approach until 6.4 feet. At a level diff of 6 you are detected at 7.68 feet or closer etc+            if (distance <= ((distanceFormula) * modifier))+            {+                //Puts mob back to threat to normal value TODO: ?+                IsVisible = true;+                return IsVisible && ( distance <= MAX_DIST_INVISIBLE_UNIT * MAX_DIST_INVISIBLE_UNIT);+            }+            else+            {+                IsVisible = false;+                return IsVisible && ( distance <= MAX_DIST_INVISIBLE_UNIT * MAX_DIST_INVISIBLE_UNIT);+            }+        }++        // Level detection based on level, the higher the mob level the higher the chance of detection.+        if ((distance > 0.24f) && (levelDiff < 5) && (levelDiff >= 0))+        {+                if (rand_chance() > ((prob * modifier) / (30 - levelDiff * 5) ))+                    IsVisible = false;+                else+                    IsVisible = true;++                return IsVisible && ( distance <= MAX_DIST_INVISIBLE_UNIT * MAX_DIST_INVISIBLE_UNIT);+        }+    }++    // Didn't match any criteria ?+    DEBUG_LOG("Unit::isVisibleForFor unhandled result, dist %f levelDiff %i target_type %u prob %u modifier %u",distance,levelDiff,u->GetTypeId(),prob, modifier);++    // Safety return+    return IsVisible && ( distance <= MAX_DIST_INVISIBLE_UNIT * MAX_DIST_INVISIBLE_UNIT);}void Unit::SetVisibility(UnitVisibility x)@@ -5472,4 +5644,4 @@Unit* Unit::GetUnit(WorldObject& object, uint64 guid){     return ObjectAccessor::Instance().GetUnit(object,guid);-}\ No newline at end of file+}Index: src/game/Unit.h===================================================================--- src/game/Unit.h    (revision 3674)+++ src/game/Unit.h    (working copy)@@ -171,6 +171,7 @@{     UNIT_STAT_STOPPED       = 0,     UNIT_STAT_DIED          = 1,+    UNIT_STAT_VANISHED      = 1,                            // TODO: stat similar to died, are there any differences?     UNIT_STAT_ATTACKING     = 2,                            // player is attacking someone     UNIT_STAT_ATTACK_BY     = 4,                            // player is attack by someone                                                             // player is in combat mode