diff --git a/EULA b/EULA deleted file mode 100644 index 719f9fdbe..000000000 --- a/EULA +++ /dev/null @@ -1,9 +0,0 @@ -MaNGOS End-User License Agreement - -MaNGOS has been built with education as the main target, thus you may only use -the source code and binary releases provided by the project for educational -purposes. You are not allowed to use MaNGOS for any commercial purpose, and you -are not allowed to use MaNGOS for hosting MaNGOS servers for public usage. - -By translating the supplied source code into binary form and running the final -executable you agree with MaNGOS EULA. diff --git a/WARNING b/WARNING new file mode 100644 index 000000000..89688d768 --- /dev/null +++ b/WARNING @@ -0,0 +1,11 @@ +The Massive Network Game Object Server (MaNGOS) has been built with education +as the main target and the MaNGOS team would like to keep it that way. + +Since any public and/or commercial use of this software is considered illegal +in many countries (please refer to your local law), the MaNGOS team +will not provide any help nor support with such usage in any way. +Every user of this software is encouraged to make sure no law is being broken +on his side. + +Both the MaNGOS team and MaNGOS foundation don't take any responsibility +for any kind of usage of this software by the end users. diff --git a/src/game/CreatureEventAI.cpp b/src/game/CreatureEventAI.cpp index a85aa7abd..c2df6c436 100644 --- a/src/game/CreatureEventAI.cpp +++ b/src/game/CreatureEventAI.cpp @@ -1089,9 +1089,11 @@ void CreatureEventAI::UpdateAI(const uint32 diff) break; case EVENT_T_RANGE: if (Combat) - if (m_creature->IsInMap(m_creature->getVictim())) - if (m_creature->IsInRange(m_creature->getVictim(),(float)(*i).Event.range.minDist,(float)(*i).Event.range.maxDist)) + { + if (m_creature->getVictim() && m_creature->IsInMap(m_creature->getVictim())) + if (m_creature->IsInRange(m_creature->getVictim(), (float)(*i).Event.range.minDist, (float)(*i).Event.range.maxDist)) ProcessEvent(*i); + } break; } } diff --git a/src/game/GameObject.h b/src/game/GameObject.h index c6f802cb1..9eddf9092 100644 --- a/src/game/GameObject.h +++ b/src/game/GameObject.h @@ -567,14 +567,6 @@ class MANGOS_DLL_SPEC GameObject : public WorldObject bool IsTransport() const; - void SetOwnerGUID(uint64 owner) - { - m_spawnedByDefault = false; // all object with owner is despawned after delay - SetUInt64Value(OBJECT_FIELD_CREATED_BY, owner); - } - uint64 GetOwnerGUID() const { return GetUInt64Value(OBJECT_FIELD_CREATED_BY); } - Unit* GetOwner() const; - uint32 GetDBTableGUIDLow() const { return m_DBTableGuid; } void UpdateRotationFields(float rotation2 = 0.0f, float rotation3 = 0.0f); @@ -593,6 +585,21 @@ class MANGOS_DLL_SPEC GameObject : public WorldObject bool LoadFromDB(uint32 guid, Map *map); void DeleteFromDB(); + void SetOwnerGUID(uint64 owner) + { + m_spawnedByDefault = false; // all object with owner is despawned after delay + SetUInt64Value(OBJECT_FIELD_CREATED_BY, owner); + } + uint64 GetOwnerGUID() const { return GetUInt64Value(OBJECT_FIELD_CREATED_BY); } + Unit* GetOwner() const; + + void SetSpellId(uint32 id) + { + m_spawnedByDefault = false; // all summoned object is despawned after delay + m_spellId = id; + } + uint32 GetSpellId() const { return m_spellId;} + time_t GetRespawnTime() const { return m_respawnTime; } time_t GetRespawnTimeEx() const { @@ -619,8 +626,6 @@ class MANGOS_DLL_SPEC GameObject : public WorldObject uint32 GetRespawnDelay() const { return m_respawnDelayTime; } void Refresh(); void Delete(); - void SetSpellId(uint32 id) { m_spellId = id;} - uint32 GetSpellId() const { return m_spellId;} void getFishLoot(Loot *loot, Player* loot_owner); GameobjectTypes GetGoType() const { return GameobjectTypes(GetByteValue(GAMEOBJECT_BYTES_1, 1)); } void SetGoType(GameobjectTypes type) { SetByteValue(GAMEOBJECT_BYTES_1, 1, type); } diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 486900975..904a1a0cd 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -15923,7 +15923,7 @@ void Player::outDebugValues() const sLog.outDebug("HP is: \t\t\t%u\t\tMP is: \t\t\t%u",GetMaxHealth(), GetMaxPower(POWER_MANA)); sLog.outDebug("AGILITY is: \t\t%f\t\tSTRENGTH is: \t\t%f",GetStat(STAT_AGILITY), GetStat(STAT_STRENGTH)); sLog.outDebug("INTELLECT is: \t\t%f\t\tSPIRIT is: \t\t%f",GetStat(STAT_INTELLECT), GetStat(STAT_SPIRIT)); - sLog.outDebug("STAMINA is: \t\t%f\t\tSPIRIT is: \t\t%f",GetStat(STAT_STAMINA), GetStat(STAT_SPIRIT)); + sLog.outDebug("STAMINA is: \t\t%f",GetStat(STAT_STAMINA)); sLog.outDebug("Armor is: \t\t%u\t\tBlock is: \t\t%f",GetArmor(), GetFloatValue(PLAYER_BLOCK_PERCENTAGE)); sLog.outDebug("HolyRes is: \t\t%u\t\tFireRes is: \t\t%u",GetResistance(SPELL_SCHOOL_HOLY), GetResistance(SPELL_SCHOOL_FIRE)); sLog.outDebug("NatureRes is: \t\t%u\t\tFrostRes is: \t\t%u",GetResistance(SPELL_SCHOOL_NATURE), GetResistance(SPELL_SCHOOL_FROST)); diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h index 2e138e517..11b311bcb 100644 --- a/src/game/SharedDefines.h +++ b/src/game/SharedDefines.h @@ -1781,6 +1781,7 @@ enum CreatureType CREATURE_TYPE_GAS_CLOUD = 13 }; +uint32 const CREATURE_TYPEMASK_DEMON_OR_UNDEAD = (1 << (CREATURE_TYPE_DEMON-1)) | (1 << (CREATURE_TYPE_UNDEAD-1)); uint32 const CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD = (1 << (CREATURE_TYPE_HUMANOID-1)) | (1 << (CREATURE_TYPE_UNDEAD-1)); uint32 const CREATURE_TYPEMASK_MECHANICAL_OR_ELEMENTAL = (1 << (CREATURE_TYPE_MECHANICAL-1)) | (1 << (CREATURE_TYPE_ELEMENTAL-1)); diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 5c660c1ca..7e92f2d24 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -1200,10 +1200,21 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask) return; } - unit->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + // not break stealth by cast targeting + if (!(m_spellInfo->AttributesEx & SPELL_ATTR_EX_NOT_BREAK_STEALTH)) + unit->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); - if (!(m_spellInfo->AttributesEx & SPELL_ATTR_EX_NO_INITIAL_AGGRO)) + // can cause back attack (if detected) + if (!(m_spellInfo->AttributesEx & SPELL_ATTR_EX_NO_INITIAL_AGGRO) && + m_caster->isVisibleForOrDetect(unit,false)) // stealth removed at Spell::cast if spell break it { + // use speedup check to avoid re-remove after above lines + if (m_spellInfo->AttributesEx & SPELL_ATTR_EX_NOT_BREAK_STEALTH) + unit->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + + // caster can be detected but have stealth aura + m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + if (!unit->IsStandState() && !unit->hasUnitState(UNIT_STAT_STUNNED)) unit->SetStandState(UNIT_STAND_STATE_STAND); @@ -5448,8 +5459,10 @@ bool Spell::CheckTargetCreatureType(Unit* target) const { uint32 spellCreatureTargetMask = m_spellInfo->TargetCreatureType; - // Curse of Doom : not find another way to fix spell target check :/ - if(m_spellInfo->SpellFamilyName==SPELLFAMILY_WARLOCK && m_spellInfo->SpellFamilyFlags == UI64LIT(0x0200000000)) + // Curse of Doom & Exorcism: not find another way to fix spell target check :/ + if (m_spellInfo->SpellFamilyName==SPELLFAMILY_WARLOCK && m_spellInfo->Category == 1179 || + // TODO: will be removed in 3.2.x + m_spellInfo->SpellFamilyName==SPELLFAMILY_PALADIN && m_spellInfo->Category == 19) { // not allow cast at player if(target->GetTypeId()==TYPEID_PLAYER) diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 6012c6a01..1d7aa31a2 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -4733,39 +4733,40 @@ void Spell::EffectSummonObjectWild(uint32 i) } int32 duration = GetSpellDuration(m_spellInfo); + pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0); pGameObj->SetSpellId(m_spellInfo->Id); - if(pGameObj->GetGoType() != GAMEOBJECT_TYPE_FLAGDROP) // make dropped flag clickable for other players (not set owner guid (created by) for this)... - m_caster->AddGameObject(pGameObj); + // Wild object not have owner and check clickable by players map->Add(pGameObj); - if(pGameObj->GetMapId() == 489 && pGameObj->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP) //WS + if(pGameObj->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP && m_caster->GetTypeId() == TYPEID_PLAYER) { - if(m_caster->GetTypeId() == TYPEID_PLAYER) + Player *pl = (Player*)m_caster; + BattleGround* bg = ((Player *)m_caster)->GetBattleGround(); + + switch(pGameObj->GetMapId()) { - Player *pl = (Player*)m_caster; - BattleGround* bg = ((Player *)m_caster)->GetBattleGround(); - if(bg && bg->GetTypeID()==BATTLEGROUND_WS && bg->GetStatus() == STATUS_IN_PROGRESS) + case 489: //WS { - uint32 team = ALLIANCE; + if(bg && bg->GetTypeID()==BATTLEGROUND_WS && bg->GetStatus() == STATUS_IN_PROGRESS) + { + uint32 team = ALLIANCE; - if(pl->GetTeam() == team) - team = HORDE; + if(pl->GetTeam() == team) + team = HORDE; - ((BattleGroundWS*)bg)->SetDroppedFlagGUID(pGameObj->GetGUID(),team); + ((BattleGroundWS*)bg)->SetDroppedFlagGUID(pGameObj->GetGUID(),team); + } + break; } - } - } - - if(pGameObj->GetMapId() == 566 && pGameObj->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP) //EY - { - if(m_caster->GetTypeId() == TYPEID_PLAYER) - { - BattleGround* bg = ((Player *)m_caster)->GetBattleGround(); - if(bg && bg->GetTypeID()==BATTLEGROUND_EY && bg->GetStatus() == STATUS_IN_PROGRESS) + case 566: //EY { - ((BattleGroundEY*)bg)->SetDroppedFlagGUID(pGameObj->GetGUID()); + if(bg && bg->GetTypeID()==BATTLEGROUND_EY && bg->GetStatus() == STATUS_IN_PROGRESS) + { + ((BattleGroundEY*)bg)->SetDroppedFlagGUID(pGameObj->GetGUID()); + } + break; } } } @@ -4779,7 +4780,7 @@ void Spell::EffectSummonObjectWild(uint32 i) linkedGO->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0); linkedGO->SetSpellId(m_spellInfo->Id); - m_caster->AddGameObject(linkedGO); + // Wild object not have owner and check clickable by players map->Add(linkedGO); } else diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 89401250b..885de4c0a 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -3410,6 +3410,7 @@ bool Unit::AddAura(Aura *Aur) // ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load) if( !isAlive() && !IsDeathPersistentSpell(aurSpellInfo) && + Aur->GetId() != 2584 && // Waiting to Resurrect (not have death persistence flag) (GetTypeId()!=TYPEID_PLAYER || !((Player*)this)->GetSession()->PlayerLoading()) ) { delete Aur; @@ -4471,7 +4472,7 @@ bool Unit::HandleHasteAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu case 13877: case 33735: { - target = SelectNearbyTarget(); + target = SelectNearbyTarget(pVictim); if(!target) return false; basepoints0 = damage; @@ -4552,7 +4553,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu if(procSpell && procSpell->Id == 26654) return false; - target = SelectNearbyTarget(); + target = SelectNearbyTarget(pVictim); if(!target) return false; @@ -5083,7 +5084,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu if(procSpell && procSpell->Id == 26654) return false; - target = SelectNearbyTarget(); + target = SelectNearbyTarget(pVictim); if(!target) return false; @@ -8277,6 +8278,13 @@ bool Unit::isSpellCrit(Unit *pVictim, SpellEntry const *spellProto, SpellSchoolM crit_chance+=aura->GetModifier()->m_amount; break; } + // Exorcism + else if (spellProto->Category == 19) + { + if (pVictim->GetCreatureTypeMask() & CREATURE_TYPEMASK_DEMON_OR_UNDEAD) + return true; + break; + } break; case SPELLFAMILY_SHAMAN: // Lava Burst @@ -9853,11 +9861,11 @@ bool Unit::SelectHostilTarget() // it in combat but attacker not make any damage and not enter to aggro radius to have record in threat list // for example at owner command to pet attack some far away creature // Note: creature not have targeted movement generator but have attacker in this case - if( GetMotionMaster()->GetCurrentMovementGeneratorType() != TARGETED_MOTION_TYPE ) + if (GetMotionMaster()->GetCurrentMovementGeneratorType() != TARGETED_MOTION_TYPE || hasUnitState(UNIT_STAT_FOLLOW)) { for(AttackerSet::const_iterator itr = m_attackers.begin(); itr != m_attackers.end(); ++itr) { - if( (*itr)->IsInMap(this) && (*itr)->isTargetableForAttack() && (*itr)->isInAccessablePlaceFor((Creature*)this) ) + if ((*itr)->IsInMap(this) && (*itr)->isTargetableForAttack() && (*itr)->isInAccessablePlaceFor((Creature*)this)) return false; } } @@ -11379,7 +11387,7 @@ void Unit::UpdateReactives( uint32 p_time ) } } -Unit* Unit::SelectNearbyTarget() const +Unit* Unit::SelectNearbyTarget(Unit* except /*= NULL*/) const { CellPair p(MaNGOS::ComputeCellPair(GetPositionX(), GetPositionY())); Cell cell(p); @@ -11401,8 +11409,8 @@ Unit* Unit::SelectNearbyTarget() const } // remove current target - if(getVictim()) - targets.remove(getVictim()); + if(except) + targets.remove(except); // remove not LoS targets for(std::list::iterator tIter = targets.begin(); tIter != targets.end();) diff --git a/src/game/Unit.h b/src/game/Unit.h index d59551093..89fdf816e 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -919,7 +919,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject Unit* getVictim() const { return m_attacking; } void CombatStop(bool includingCast = false); void CombatStopWithPets(bool includingCast = false); - Unit* SelectNearbyTarget() const; + Unit* SelectNearbyTarget(Unit* except = NULL) const; bool hasNegativeAuraWithInterruptFlag(uint32 flag); void SendMeleeAttackStop(Unit* victim); void SendMeleeAttackStart(Unit* pVictim); diff --git a/src/mangosd/Master.cpp b/src/mangosd/Master.cpp index 14b13d87b..676b4297e 100644 --- a/src/mangosd/Master.cpp +++ b/src/mangosd/Master.cpp @@ -223,12 +223,14 @@ int Master::Run() _HookSignals(); ///- Launch WorldRunnable thread - ACE_Based::Thread t(*new WorldRunnable); + ACE_Based::Thread t(new WorldRunnable); t.setPriority(ACE_Based::Highest); // set server online loginDatabase.PExecute("UPDATE realmlist SET color = 0, population = 0 WHERE id = '%d'",realmID); + ACE_Based::Thread* cliThread = NULL; + #ifdef WIN32 if (sConfig.GetBoolDefault("Console.Enable", true) && (m_ServiceStatus == -1)/* need disable console in service mode*/) #else @@ -236,10 +238,10 @@ int Master::Run() #endif { ///- Launch CliRunnable thread - ACE_Based::Thread td1(*new CliRunnable); + cliThread = new ACE_Based::Thread(new CliRunnable); } - ACE_Based::Thread td2(*new RARunnable); + ACE_Based::Thread td2(new RARunnable); ///- Handle affinity for multiple processors and process priority on Windows #ifdef WIN32 @@ -300,7 +302,7 @@ int Master::Run() { FreezeDetectorRunnable *fdr = new FreezeDetectorRunnable(); fdr->SetDelayTime(freeze_delay*1000); - ACE_Based::Thread t(*fdr); + ACE_Based::Thread t(fdr); t.setPriority(ACE_Based::Highest); } @@ -338,9 +340,10 @@ int Master::Run() sLog.outString( "Halting process..." ); - #ifdef WIN32 - if (sConfig.GetBoolDefault("Console.Enable", true)) + if(cliThread) { + #ifdef WIN32 + // this only way to terminate CLI thread exist at Win32 (alt. way exist only in Windows Vista API) //_exit(1); // send keyboard input to safely unblock the CLI thread @@ -375,8 +378,17 @@ int Master::Run() b[3].Event.KeyEvent.wRepeatCount = 1; DWORD numb; BOOL ret = WriteConsoleInput(hStdIn, b, 4, &numb); + + cliThread->wait(); + + #else + + cliThread->destroy(); + + #endif + + delete cliThread; } - #endif // for some unknown reason, unloading scripts here and not in worldrunnable // fixes a memory leak related to detaching threads from the module diff --git a/src/realmd/AuthSocket.cpp b/src/realmd/AuthSocket.cpp index 5611d85e8..02e6aad80 100644 --- a/src/realmd/AuthSocket.cpp +++ b/src/realmd/AuthSocket.cpp @@ -926,7 +926,7 @@ bool AuthSocket::_HandleXferResume() ibuf.Read((char*)&start,sizeof(start)); fseek(pPatch, start, 0); - ACE_Based::Thread u(*new PatcherRunnable(this)); + ACE_Based::Thread u(new PatcherRunnable(this)); return true; } @@ -959,7 +959,7 @@ bool AuthSocket::_HandleXferAccept() ibuf.Remove(1); // clear input buffer fseek(pPatch, 0, 0); - ACE_Based::Thread u(*new PatcherRunnable(this)); + ACE_Based::Thread u(new PatcherRunnable(this)); return true; } diff --git a/src/shared/Database/Database.h b/src/shared/Database/Database.h index da3e9a706..d7dfd23e2 100644 --- a/src/shared/Database/Database.h +++ b/src/shared/Database/Database.h @@ -39,7 +39,7 @@ class MANGOS_DLL_SPEC Database TransactionQueues m_tranQueues; ///< Transaction queues from diff. threads QueryQueues m_queryQueues; ///< Query queues from diff threads - SqlDelayThread* m_threadBody; ///< Pointer to delay sql executer + SqlDelayThread* m_threadBody; ///< Pointer to delay sql executer (owned by m_delayThread) ACE_Based::Thread* m_delayThread; ///< Pointer to executer thread public: diff --git a/src/shared/Database/DatabaseMysql.cpp b/src/shared/Database/DatabaseMysql.cpp index 1a56c1b64..969617272 100644 --- a/src/shared/Database/DatabaseMysql.cpp +++ b/src/shared/Database/DatabaseMysql.cpp @@ -424,8 +424,8 @@ void DatabaseMysql::InitDelayThread() assert(!m_delayThread); //New delay thread for delay execute - m_threadBody = new MySQLDelayThread(this); - m_delayThread = new ACE_Based::Thread(*m_threadBody); + m_threadBody = new MySQLDelayThread(this); // will deleted at m_delayThread delete + m_delayThread = new ACE_Based::Thread(m_threadBody); } void DatabaseMysql::HaltDelayThread() diff --git a/src/shared/Database/DatabasePostgre.cpp b/src/shared/Database/DatabasePostgre.cpp index 55b60be5a..359728410 100644 --- a/src/shared/Database/DatabasePostgre.cpp +++ b/src/shared/Database/DatabasePostgre.cpp @@ -364,8 +364,8 @@ void DatabasePostgre::InitDelayThread() assert(!m_delayThread); //New delay thread for delay execute - m_threadBody = new PGSQLDelayThread(this); - m_delayThread = new ACE_Based::Thread(*m_threadBody); + m_threadBody = new PGSQLDelayThread(this); // Will be deleted on m_delayThread delete + m_delayThread = new ACE_Based::Thread(m_threadBody); } void DatabasePostgre::HaltDelayThread() diff --git a/src/shared/Threading.cpp b/src/shared/Threading.cpp index 496e86353..25bd3120c 100644 --- a/src/shared/Threading.cpp +++ b/src/shared/Threading.cpp @@ -101,7 +101,7 @@ Thread::Thread() : m_task(0), m_iThreadId(0), m_hThreadHandle(0) } -Thread::Thread(Runnable& instance) : m_task(&instance), m_iThreadId(0), m_hThreadHandle(0) +Thread::Thread(Runnable* instance) : m_task(instance), m_iThreadId(0), m_hThreadHandle(0) { bool _start = start(); ASSERT (_start); @@ -110,6 +110,9 @@ Thread::Thread(Runnable& instance) : m_task(&instance), m_iThreadId(0), m_hThrea Thread::~Thread() { //Wait(); + + // deleted runnable object (owned by Thread) + delete m_task; } //initialize Thread's class static member diff --git a/src/shared/Threading.h b/src/shared/Threading.h index eac3c0e8e..ab423696c 100644 --- a/src/shared/Threading.h +++ b/src/shared/Threading.h @@ -61,7 +61,7 @@ namespace ACE_Based { public: Thread(); - Thread(Runnable& instance); + explicit Thread(Runnable* instance); ~Thread(); bool start(); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index e592c6e2c..cde51ab1f 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8315" + #define REVISION_NR "8326" #endif // __REVISION_NR_H__