rendered paste bodyIndex: 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