diff options
-rw-r--r-- | sql/updates/287_world_scripts.sql | 2 | ||||
-rw-r--r-- | src/bindings/scripts/scripts/creature/mob_event_ai.cpp | 10 | ||||
-rw-r--r-- | src/game/AggressorAI.cpp | 4 | ||||
-rw-r--r-- | src/game/Creature.cpp | 10 | ||||
-rw-r--r-- | src/game/GridNotifiers.cpp | 2 | ||||
-rw-r--r-- | src/game/GridNotifiers.h | 3 | ||||
-rw-r--r-- | src/game/Map.cpp | 60 | ||||
-rw-r--r-- | src/game/ObjectMgr.cpp | 3 | ||||
-rw-r--r-- | src/game/OutdoorPvPObjectiveAI.cpp | 1 | ||||
-rw-r--r-- | src/game/Player.cpp | 17 | ||||
-rw-r--r-- | src/game/ReactorAI.cpp | 11 | ||||
-rw-r--r-- | src/game/Spell.cpp | 14 | ||||
-rw-r--r-- | src/game/SpellAuras.cpp | 25 | ||||
-rw-r--r-- | src/game/SpellEffects.cpp | 3 | ||||
-rw-r--r-- | src/game/StatSystem.cpp | 20 | ||||
-rw-r--r-- | src/game/Totem.cpp | 4 | ||||
-rw-r--r-- | src/game/Unit.cpp | 17 | ||||
-rw-r--r-- | src/game/WaypointManager.cpp | 68 | ||||
-rw-r--r-- | src/game/WaypointManager.h | 1 | ||||
-rw-r--r-- | src/shared/Database/DBCStructure.h | 4 |
20 files changed, 218 insertions, 61 deletions
diff --git a/sql/updates/287_world_scripts.sql b/sql/updates/287_world_scripts.sql index 725f81b02e9..8021ee2b01e 100644 --- a/sql/updates/287_world_scripts.sql +++ b/sql/updates/287_world_scripts.sql @@ -1,2 +1,2 @@ -UPDATE `creature_template` SET `ScriptName` = 'npc_steam_tonk' WHERE `entry` = '19405';
+UPDATE `creature_template` SET `ScriptName` = 'npc_steam_tonk' WHERE `entry` = '19405'; UPDATE `creature_template` SET `ScriptName` = 'npc_tonk_mine' WHERE `entry` = '15368';
\ No newline at end of file diff --git a/src/bindings/scripts/scripts/creature/mob_event_ai.cpp b/src/bindings/scripts/scripts/creature/mob_event_ai.cpp index 289b6b925c5..657a1f41b5b 100644 --- a/src/bindings/scripts/scripts/creature/mob_event_ai.cpp +++ b/src/bindings/scripts/scripts/creature/mob_event_ai.cpp @@ -1038,7 +1038,15 @@ struct TRINITY_DLL_DECL Mob_EventAI : public ScriptedAI m_creature->CombatStop(); m_creature->LoadCreaturesAddon(); if( m_creature->isAlive() ) - m_creature->GetMotionMaster()->MoveTargetedHome(); + { + if (Unit* owner = m_creature->GetOwner()) + { + if (owner->isAlive()) + m_creature->GetMotionMaster()->MoveFollow(owner,PET_FOLLOW_DIST,PET_FOLLOW_ANGLE); + } + else + m_creature->GetMotionMaster()->MoveTargetedHome(); + } m_creature->SetLootRecipient(NULL); diff --git a/src/game/AggressorAI.cpp b/src/game/AggressorAI.cpp index 0c45fff79f4..4b090f3c799 100644 --- a/src/game/AggressorAI.cpp +++ b/src/game/AggressorAI.cpp @@ -98,7 +98,7 @@ void AggressorAI::EnterEvadeMode() //i_tracker.Reset(TIME_INTERVAL_LOOK); } - if(!i_creature.isCharmed()) + if(!i_creature.GetCharmerOrOwner()) { i_creature.RemoveAllAuras(); @@ -106,6 +106,8 @@ void AggressorAI::EnterEvadeMode() if( i_creature.GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE ) i_creature.GetMotionMaster()->MoveTargetedHome(); } + else if (i_creature.GetOwner() && i_creature.GetOwner()->isAlive()) + i_creature.GetMotionMaster()->MoveFollow(i_creature.GetOwner(),PET_FOLLOW_DIST,PET_FOLLOW_ANGLE); i_creature.DeleteThreatList(); i_victimGuid = 0; diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index b2b6639148e..79c1bf18008 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -1279,8 +1279,11 @@ void Creature::SelectLevel(const CreatureInfo *cinfo) SetBaseWeaponDamage(RANGED_ATTACK, MINDAMAGE, cinfo->minrangedmg * damagemod); SetBaseWeaponDamage(RANGED_ATTACK, MAXDAMAGE, cinfo->maxrangedmg * damagemod); - SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, cinfo->attackpower * damagemod); - SetModifierValue(UNIT_MOD_ATTACK_POWER_RANGED, BASE_VALUE, cinfo->rangedattackpower * damagemod); + // this value is not accurate, but should be close to the real value + SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, level * 5); + SetModifierValue(UNIT_MOD_ATTACK_POWER_RANGED, BASE_VALUE, level * 5); + //SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, cinfo->attackpower * damagemod); + //SetModifierValue(UNIT_MOD_ATTACK_POWER_RANGED, BASE_VALUE, cinfo->rangedattackpower * damagemod); } float Creature::_GetHealthMod(int32 Rank) @@ -1888,7 +1891,8 @@ void Creature::CallAssistence() for(std::list<Creature*>::iterator iter = assistList.begin(); iter != assistList.end(); ++iter) { - (*iter)->SetNoCallAssistence(true); + //(*iter)->SetNoCallAssistence(true); + (*iter)->CombatStart(getVictim()); if((*iter)->AI()) (*iter)->AI()->AttackStart(getVictim()); } diff --git a/src/game/GridNotifiers.cpp b/src/game/GridNotifiers.cpp index 54ee2e67726..0c952f69649 100644 --- a/src/game/GridNotifiers.cpp +++ b/src/game/GridNotifiers.cpp @@ -190,7 +190,7 @@ Deliverer::Visit(DynamicObjectMapType &m) { // Send packet back to the caster if the caster has vision of dynamic object Player* caster = (Player*)iter->getSource()->GetCaster(); - if (caster->GetUInt64Value(PLAYER_FARSIGHT) == iter->getSource()->GetGUID() && + if (caster && caster->GetUInt64Value(PLAYER_FARSIGHT) == iter->getSource()->GetGUID() && (!i_dist || iter->getSource()->GetDistance(&i_source) <= i_dist)) SendPacket(caster); } diff --git a/src/game/GridNotifiers.h b/src/game/GridNotifiers.h index 3561f30861c..6b4dd39306c 100644 --- a/src/game/GridNotifiers.h +++ b/src/game/GridNotifiers.h @@ -783,6 +783,9 @@ namespace Trinity if(u->getFaction() != i_funit->getFaction() ) return false; + if(!u->isAggressive()) + return false; + // only free creature if( u->GetCharmerOrOwnerGUID() ) return false; diff --git a/src/game/Map.cpp b/src/game/Map.cpp index f8201f53219..246af3792fb 100644 --- a/src/game/Map.cpp +++ b/src/game/Map.cpp @@ -594,7 +594,7 @@ bool Map::loaded(const GridPair &p) const return ( getNGrid(p.x_coord, p.y_coord) && isGridObjectDataLoaded(p.x_coord, p.y_coord) ); } -void Map::UpdateActiveCells(const float &x, const float &y, const uint32 &t_diff) +/*void Map::UpdateActiveCells(const float &x, const float &y, const uint32 &t_diff) { CellPair standing_cell(Trinity::ComputeCellPair(x, y)); @@ -635,27 +635,75 @@ void Map::UpdateActiveCells(const float &x, const float &y, const uint32 &t_diff } } } -} +}*/ void Map::Update(const uint32 &t_diff) { resetMarkedCells(); // update cells around players - for(MapRefManager::iterator iter = m_mapRefManager.begin(); iter != m_mapRefManager.end(); ++iter) + /*for(MapRefManager::iterator iter = m_mapRefManager.begin(); iter != m_mapRefManager.end(); ++iter) { Player* plr = iter->getSource(); if(plr->IsInWorld()) UpdateActiveCells(plr->GetPositionX(), plr->GetPositionY(), t_diff); - } + }*/ // update cells around active objects // clone the active object list, because update might remove from it std::set<WorldObject *> activeObjects(i_activeObjects); + for(MapRefManager::iterator iter = m_mapRefManager.begin(); iter != m_mapRefManager.end(); ++iter) + { + Player* plr = iter->getSource(); + if(plr->IsInWorld()) + activeObjects.insert(plr); + } + + Trinity::ObjectUpdater updater(t_diff); + // for creature + TypeContainerVisitor<Trinity::ObjectUpdater, GridTypeMapContainer > grid_object_update(updater); + // for pets + TypeContainerVisitor<Trinity::ObjectUpdater, WorldTypeMapContainer > world_object_update(updater); + for(std::set<WorldObject *>::iterator iter = activeObjects.begin(); iter != activeObjects.end(); ++iter) { - if((*iter)->IsInWorld()) - UpdateActiveCells((*iter)->GetPositionX(), (*iter)->GetPositionY(), t_diff); + if(!(*iter)->IsInWorld()) + continue; + + CellPair standing_cell(Trinity::ComputeCellPair((*iter)->GetPositionX(), (*iter)->GetPositionY())); + + // Check for correctness of standing_cell, it also avoids problems with update_cell + if (standing_cell.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || standing_cell.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) + continue; + + // the overloaded operators handle range checking + // so ther's no need for range checking inside the loop + CellPair begin_cell(standing_cell), end_cell(standing_cell); + begin_cell << 1; begin_cell -= 1; // upper left + end_cell >> 1; end_cell += 1; // lower right + + for(uint32 x = begin_cell.x_coord; x <= end_cell.x_coord; ++x) + { + for(uint32 y = begin_cell.y_coord; y <= end_cell.y_coord; ++y) + { + // marked cells are those that have been visited + // don't visit the same cell twice + uint32 cell_id = (y * TOTAL_NUMBER_OF_CELLS_PER_MAP) + x; + if(!isCellMarked(cell_id)) + { + markCell(cell_id); + CellPair pair(x,y); + Cell cell(pair); + cell.data.Part.reserved = CENTER_DISTRICT; + cell.SetNoCreate(); + CellLock<NullGuard> cell_lock(cell, pair); + cell_lock->Visit(cell_lock, grid_object_update, *this); + cell_lock->Visit(cell_lock, world_object_update, *this); + } + } + } + + // UpdateActiveCells((*iter)->GetPositionX(), (*iter)->GetPositionY(), t_diff); } // Don't unload grids if it's battleground, since we may have manually added GOs,creatures, those doesn't load from DB at grid re-load ! diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 751a3ca4fbc..e6fc35b21a4 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -44,6 +44,7 @@ #include "InstanceSaveMgr.h" #include "SpellAuras.h" #include "Util.h" +#include "WaypointManager.h" INSTANTIATE_SINGLETON_1(ObjectMgr); @@ -7471,6 +7472,8 @@ void ObjectMgr::LoadDbScriptStrings() CheckScripts(sGameObjectScripts,ids); CheckScripts(sEventScripts,ids); + WaypointMgr.CheckTextsExistance(ids); + for(std::set<int32>::const_iterator itr = ids.begin(); itr != ids.end(); ++itr) sLog.outErrorDb( "Table `db_script_string` has unused string id %u", *itr); } diff --git a/src/game/OutdoorPvPObjectiveAI.cpp b/src/game/OutdoorPvPObjectiveAI.cpp index 9c9603a7f91..e8595e791f7 100644 --- a/src/game/OutdoorPvPObjectiveAI.cpp +++ b/src/game/OutdoorPvPObjectiveAI.cpp @@ -28,6 +28,7 @@ OutdoorPvPObjectiveAI::OutdoorPvPObjectiveAI(Creature &c) : i_creature(c) { sLog.outDebug("OutdoorPvP objective AI assigned to creature guid %u", c.GetGUIDLow()); + c.SetAggressive(true); } void OutdoorPvPObjectiveAI::MoveInLineOfSight(Unit *u) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 8fe5baed6f4..1f17a75819d 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -1016,6 +1016,13 @@ void Player::Update( uint32 p_time ) CheckExploreSystem(); + /*if(isCharmed()) + { + if(Unit *charmer = GetCharmer()) + if(charmer->GetTypeId() == TYPEID_UNIT && ((Creature*)charmer)->AI()) + ((Creature*)charmer)->AI()->UpdateCharmedAI(this, p_time); + }*/ + // Update items that have just a limited lifetime if (now>m_Last_tick) UpdateItemDuration(uint32(now- m_Last_tick)); @@ -5266,6 +5273,10 @@ bool Player::SetPosition(float x, float y, float z, float orientation, bool tele x = GetPositionX(); y = GetPositionY(); z = GetPositionZ(); + + // group update + if(GetGroup() && (old_x != x || old_y != y)) + SetGroupUpdateFlag(GROUP_UPDATE_FLAG_POSITION); } // code block for underwater state update @@ -5273,10 +5284,6 @@ bool Player::SetPosition(float x, float y, float z, float orientation, bool tele CheckExploreSystem(); - // group update - if(GetGroup()) - SetGroupUpdateFlag(GROUP_UPDATE_FLAG_POSITION); - return true; } @@ -14285,7 +14292,7 @@ void Player::_LoadAuras(QueryResult *result, uint32 timediff) damage = aura->GetModifier()->m_amount; aura->SetLoadedState(caster_guid,damage,maxduration,remaintime,remaincharges); AddAura(aura); - sLog.outString("Added aura spellid %u, effect %u", spellproto->Id, effindex); + sLog.outDetail("Added aura spellid %u, effect %u", spellproto->Id, effindex); } } while( result->NextRow() ); diff --git a/src/game/ReactorAI.cpp b/src/game/ReactorAI.cpp index 41e5fb51f10..9d596751075 100644 --- a/src/game/ReactorAI.cpp +++ b/src/game/ReactorAI.cpp @@ -123,7 +123,12 @@ ReactorAI::EnterEvadeMode() i_creature.CombatStop(); i_creature.SetLootRecipient(NULL); - // Remove TargetedMovementGenerator from MotionMaster stack list, and add HomeMovementGenerator instead - if( i_creature.GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE ) - i_creature.GetMotionMaster()->MoveTargetedHome(); + if(!i_creature.GetCharmerOrOwner()) + { + // Remove TargetedMovementGenerator from MotionMaster stack list, and add HomeMovementGenerator instead + if( i_creature.GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE ) + i_creature.GetMotionMaster()->MoveTargetedHome(); + } + else if (i_creature.GetOwner() && i_creature.GetOwner()->isAlive()) + i_creature.GetMotionMaster()->MoveFollow(i_creature.GetOwner(),PET_FOLLOW_DIST,PET_FOLLOW_ANGLE); } diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 0c1f25964a9..5cdbef26eed 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -715,7 +715,8 @@ void Spell::AddUnitTarget(Unit* pVictim, uint32 effIndex) if(m_originalCaster) target.missCondition = m_originalCaster->SpellHitResult(pVictim, m_spellInfo, m_canReflect); else - target.missCondition = SPELL_MISS_NONE; + target.missCondition = SPELL_MISS_EVADE; //SPELL_MISS_NONE; + if (target.missCondition == SPELL_MISS_NONE) ++m_countOfHit; else @@ -928,6 +929,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target) return; SpellMissInfo missInfo = target->missCondition; + // Need init unitTarget by default unit (can changed in code on reflect) // Or on missInfo!=SPELL_MISS_NONE unitTarget undefined (but need in trigger subsystem) unitTarget = unit; @@ -939,6 +941,16 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target) if (target->reflectResult == SPELL_MISS_NONE) // If reflected spell hit caster -> do all effect on him DoSpellHitOnUnit(m_caster, mask); } + else //TODO: This is a hack. need fix + { + uint32 tempMask = 0; + for(uint32 i = 0; i < 3; ++i) + if(m_spellInfo->Effect[i] == SPELL_EFFECT_DUMMY + || m_spellInfo->Effect[i] == SPELL_EFFECT_TRIGGER_SPELL) + tempMask |= 1<<i; + if(tempMask &= mask) + DoSpellHitOnUnit(unit, tempMask); + } // Do triggers only on miss/resist/parry/dodge if (missInfo!=SPELL_MISS_NONE) diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 874b9236fc1..46842bc3ced 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -3147,18 +3147,23 @@ void Aura::HandleAuraModDisarm(bool apply, bool Real) else m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISARMED); - // only at real add/remove aura - if (m_target->GetTypeId() != TYPEID_PLAYER) - return; - - // main-hand attack speed already set to special value for feral form already and don't must change and reset at remove. - if (((Player *)m_target)->IsInFeralForm()) - return; + if (m_target->GetTypeId() == TYPEID_PLAYER) + { + // main-hand attack speed already set to special value for feral form already and don't must change and reset at remove. + if (((Player *)m_target)->IsInFeralForm()) + return; - if (apply) - m_target->SetAttackTime(BASE_ATTACK,BASE_ATTACK_TIME); + if (apply) + m_target->SetAttackTime(BASE_ATTACK,BASE_ATTACK_TIME); + else + ((Player *)m_target)->SetRegularAttackTime(); + } else - ((Player *)m_target)->SetRegularAttackTime(); + { + // creature does not have equipment + if(apply && !((Creature*)m_target)->GetCurrentEquipmentId()) + return; + } m_target->UpdateDamagePhysical(BASE_ATTACK); } diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 6984fc5789c..56d8c415503 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -1871,6 +1871,7 @@ void Spell::EffectTriggerSpell(uint32 i) // Cloak of Shadows case 35729 : { + m_caster->RemoveAurasWithDispelType(DISPEL_ALL); Unit::AuraMap& Auras = m_caster->GetAuras(); for(Unit::AuraMap::iterator iter = Auras.begin(); iter != Auras.end(); ++iter) { @@ -2187,7 +2188,7 @@ void Spell::EffectApplyAura(uint32 i) // Prayer of Mending (jump animation), we need formal caster instead original for correct animation if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST && (m_spellInfo->SpellFamilyFlags & 0x00002000000000LL)) - m_caster->CastSpell(unitTarget,41637,true,NULL,Aur); + m_caster->CastSpell(unitTarget,41637,true,NULL,Aur,m_originalCasterGUID); } void Spell::EffectUnlearnSpecialization( uint32 i ) diff --git a/src/game/StatSystem.cpp b/src/game/StatSystem.cpp index 3533c5c8a02..64bad232994 100644 --- a/src/game/StatSystem.cpp +++ b/src/game/StatSystem.cpp @@ -737,15 +737,27 @@ void Creature::UpdateDamagePhysical(WeaponAttackType attType) break; } - float att_speed = float(GetAttackTime(attType))/1000.0f; + //float att_speed = float(GetAttackTime(attType))/1000.0f; - float base_value = GetModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType)/ 14.0f * att_speed; + float weapon_mindamage = GetWeaponDamageRange(attType, MINDAMAGE); + float weapon_maxdamage = GetWeaponDamageRange(attType, MAXDAMAGE); + + //This formula is not correct + //The correct one is (Damage_from_AttackPower + Base_Weapon_Damage) * Multiplier + //We do not know the multiplier, so we assume attack power is about 25% damage + //float base_value = GetModifierValue(unitMod, BASE_VALUE) + GetTotalAttackPowerValue(attType)/ 14.0f * att_speed; + float base_value = GetModifierValue(unitMod, BASE_VALUE) + + (weapon_mindamage + weapon_maxdamage) / 6 + / GetTotalAttackPowerValue(attType) * getLevel() * 5; float base_pct = GetModifierValue(unitMod, BASE_PCT); float total_value = GetModifierValue(unitMod, TOTAL_VALUE); float total_pct = GetModifierValue(unitMod, TOTAL_PCT); - float weapon_mindamage = GetWeaponDamageRange(attType, MINDAMAGE); - float weapon_maxdamage = GetWeaponDamageRange(attType, MAXDAMAGE); + if(attType == BASE_ATTACK && HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISARMED)) + { + weapon_mindamage = 0; + weapon_maxdamage = 0; + } float mindamage = ((base_value + weapon_mindamage) * base_pct + total_value) * total_pct ; float maxdamage = ((base_value + weapon_maxdamage) * base_pct + total_value) * total_pct ; diff --git a/src/game/Totem.cpp b/src/game/Totem.cpp index 73ae274644e..26c471d441a 100644 --- a/src/game/Totem.cpp +++ b/src/game/Totem.cpp @@ -181,7 +181,7 @@ void Totem::SetTypeBySummonSpell(SpellEntry const * spellProto) bool Totem::IsImmunedToSpell(SpellEntry const* spellInfo, bool useCharges) { - for (int i=0;i<3;i++) +/* for (int i=0;i<3;i++) { switch(spellInfo->EffectApplyAuraName[i]) { @@ -191,6 +191,6 @@ bool Totem::IsImmunedToSpell(SpellEntry const* spellInfo, bool useCharges) default: continue; } - } + }*/ return Creature::IsImmunedToSpell(spellInfo, useCharges); } diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index e4a83c88093..642b49ee99a 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -1475,7 +1475,7 @@ uint32 Unit::SpellNonMeleeDamageLog(Unit *pVictim, uint32 spellID, uint32 damage GetGUIDLow(), GetTypeId(), pVictim->GetGUIDLow(), pVictim->GetTypeId(), damage, spellID, absorb,resist); // Actual log sent to client - SendSpellNonMeleeDamageLog(pVictim, spellID, damage, GetSpellSchoolMask(spellInfo), absorb, resist, false, 0, crit); + SendSpellNonMeleeDamageLog(pVictim, spellID, damage + resist, GetSpellSchoolMask(spellInfo), absorb, resist, false, 0, crit); // Procflags uint32 procAttacker = PROC_FLAG_HIT_SPELL; @@ -8486,10 +8486,16 @@ void Unit::CombatStart(Unit* target) if(!target->isInCombat() && target->GetTypeId() != TYPEID_PLAYER && ((Creature*)target)->isAggressive() && ((Creature*)target)->AI()) + { + SetInCombatWith(target); + target->SetInCombatWith(this); ((Creature*)target)->AI()->AttackStart(this); - - SetInCombatWith(target); - target->SetInCombatWith(this); + } + else + { + SetInCombatWith(target); + target->SetInCombatWith(this); + } if(Player* attackedPlayer = target->GetCharmerOrOwnerPlayerOrPlayerItself()) SetContestedPvP(attackedPlayer); @@ -9622,6 +9628,9 @@ void Unit::SetMaxHealth(uint32 val) void Unit::SetPower(Powers power, uint32 val) { + if(GetPower(power) == val) + return; + uint32 maxPower = GetMaxPower(power); if(maxPower < val) val = maxPower; diff --git a/src/game/WaypointManager.cpp b/src/game/WaypointManager.cpp index a6dda2477ff..831f616060b 100644 --- a/src/game/WaypointManager.cpp +++ b/src/game/WaypointManager.cpp @@ -124,32 +124,18 @@ void WaypointManager::Load() be.emote = fields[7].GetUInt32(); be.spell = fields[8].GetUInt32(); - // load and store without holes in array - int j = 0; for(int i = 0; i < MAX_WAYPOINT_TEXT; ++i) { - be.textid[j] = fields[9+i].GetUInt32(); - if(be.textid[j]) + be.textid[i] = fields[9+i].GetUInt32(); + if(be.textid[i]) { - if (be.textid[j] < MIN_DB_SCRIPT_STRING_ID || be.textid[j] >= MAX_DB_SCRIPT_STRING_ID) + if (be.textid[i] < MIN_DB_SCRIPT_STRING_ID || be.textid[i] >= MAX_DB_SCRIPT_STRING_ID) { - sLog.outErrorDb( "Table `db_script_string` not have string id %u", be.textid[j]); + sLog.outErrorDb( "Table `db_script_string` not have string id %u", be.textid[i]); continue; } - - if (!objmgr.GetTrinityStringLocale (be.textid[j])) - { - sLog.outErrorDb("ERROR: Waypoint path %d (point %d), have invalid text id (%i) in `textid%d, ignored.", - id, point, be.textid[j], i+1); - continue; - } - - ++j; // to next internal field } } - // fill array tail - for(; j < MAX_WAYPOINT_TEXT; ++j) - be.textid[j] = 0; // save memory by not storing empty behaviors if(!be.isEmpty()) @@ -308,3 +294,49 @@ void WaypointManager::SetNodeText(uint32 id, uint32 point, const char *text_fiel if(field == "model2") node.behavior->model2 = text ? atoi(text) : 0; } } + +void WaypointManager::CheckTextsExistance(std::set<int32>& ids) +{ + WaypointPathMap::iterator pmItr = m_pathMap.begin(); + for ( ; pmItr != m_pathMap.end(); ++pmItr) + { + for (int i = 0; i < pmItr->second.size(); ++i) + { + if (!pmItr->second[i].behavior) + continue; + + // Now we check text existence and put all zero texts ids to the end of array + + // Counting leading zeros for futher textid shift + int zeroCount = 0; + for (int j = 0; j < MAX_WAYPOINT_TEXT; ++j) + { + if (!pmItr->second[i].behavior->textid[j]) + { + ++zeroCount; + continue; + } + else + { + if (!objmgr.GetTrinityStringLocale(pmItr->second[i].behavior->textid[j])) + { + sLog.outErrorDb("ERROR: Some waypoint has textid%u with not existing %u text.", j, pmItr->second[i].behavior->textid[j]); + pmItr->second[i].behavior->textid[j] = 0; + ++zeroCount; + continue; + } + else + ids.erase(pmItr->second[i].behavior->textid[j]); + + // Shifting check + if (zeroCount) + { + // Correct textid but some zeros leading, so move it forward. + pmItr->second[i].behavior->textid[j-zeroCount] = pmItr->second[i].behavior->textid[j]; + pmItr->second[i].behavior->textid[j] = 0; + } + } + } + } + } +} diff --git a/src/game/WaypointManager.h b/src/game/WaypointManager.h index 75f01cc82f3..38cf5551d64 100644 --- a/src/game/WaypointManager.h +++ b/src/game/WaypointManager.h @@ -78,6 +78,7 @@ class WaypointManager void DeletePath(uint32 id); void SetNodePosition(uint32 id, uint32 point, float x, float y, float z); void SetNodeText(uint32 id, uint32 point, const char *text_field, const char *text); + void CheckTextsExistance(std::set<int32>& ids); private: void _addNode(uint32 id, uint32 point, float x, float y, float z, float o, uint32 delay, uint32 wpGuid); diff --git a/src/shared/Database/DBCStructure.h b/src/shared/Database/DBCStructure.h index a71f80ac8c7..ce72661066b 100644 --- a/src/shared/Database/DBCStructure.h +++ b/src/shared/Database/DBCStructure.h @@ -229,6 +229,8 @@ struct FactionTemplateEntry // helpers bool IsFriendlyTo(FactionTemplateEntry const& entry) const { + if(ID == entry.ID) + return true; if(enemyFaction1 == entry.faction || enemyFaction2 == entry.faction || enemyFaction3 == entry.faction || enemyFaction4 == entry.faction ) return false; if(friendFaction1 == entry.faction || friendFaction2 == entry.faction || friendFaction3 == entry.faction || friendFaction4 == entry.faction ) @@ -237,6 +239,8 @@ struct FactionTemplateEntry } bool IsHostileTo(FactionTemplateEntry const& entry) const { + if(ID == entry.ID) + return false; if(enemyFaction1 == entry.faction || enemyFaction2 == entry.faction || enemyFaction3 == entry.faction || enemyFaction4 == entry.faction ) return true; if(friendFaction1 == entry.faction || friendFaction2 == entry.faction || friendFaction3 == entry.faction || friendFaction4 == entry.faction ) |