From d926ad63c037457198cec8a28a86863643d92dc6 Mon Sep 17 00:00:00 2001 From: Shauren Date: Wed, 13 Feb 2013 20:21:26 +0100 Subject: Core/Spells: Fixed charge effects with non-explicit targets --- src/server/game/Miscellaneous/SharedDefines.h | 7 ++++- src/server/game/Movement/MotionMaster.cpp | 7 +++-- src/server/game/Movement/MotionMaster.h | 2 +- .../MovementGenerators/PointMovementGenerator.cpp | 4 +-- src/server/game/Movement/PathGenerator.h | 4 +-- src/server/game/Movement/Spline/MoveSplineInit.cpp | 2 +- src/server/game/Spells/Spell.cpp | 33 ++++++++++------------ src/server/game/Spells/SpellEffects.cpp | 3 +- src/server/scripts/Commands/cs_mmaps.cpp | 2 +- 9 files changed, 34 insertions(+), 30 deletions(-) (limited to 'src/server') diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index 9ad1c104e1c..a2d1cdd83dd 100644 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -3157,7 +3157,12 @@ enum SummonType enum EventId { EVENT_CHARGE = 1003, - EVENT_JUMP = 1004 + EVENT_JUMP = 1004, + + /// Special charge event which is used for charge spells that have explicit targets + /// and had a path already generated - using it in PointMovementGenerator will not + /// create a new spline and launch it + EVENT_CHARGE_PREPATH = 1005 }; enum ResponseCodes diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp index c9ca7772186..8e045b98dbb 100644 --- a/src/server/game/Movement/MotionMaster.cpp +++ b/src/server/game/Movement/MotionMaster.cpp @@ -424,15 +424,16 @@ void MotionMaster::MoveCharge(float x, float y, float z, float speed, uint32 id, } } -void MotionMaster::MoveCharge(PathGenerator path, float speed, uint32 id) +void MotionMaster::MoveCharge(PathGenerator const& path) { Vector3 dest = path.GetActualEndPosition(); - MoveCharge(dest.x, dest.y, dest.z, speed, id); + MoveCharge(dest.x, dest.y, dest.z, SPEED_CHARGE, EVENT_CHARGE_PREPATH); + // Charge movement is not started when using EVENT_CHARGE_PREPATH Movement::MoveSplineInit init(_owner); init.MovebyPath(path.GetPath()); - init.SetVelocity(speed); + init.SetVelocity(SPEED_CHARGE); init.Launch(); } diff --git a/src/server/game/Movement/MotionMaster.h b/src/server/game/Movement/MotionMaster.h index 4b6075aac10..f2f3959dba5 100644 --- a/src/server/game/Movement/MotionMaster.h +++ b/src/server/game/Movement/MotionMaster.h @@ -162,7 +162,7 @@ class MotionMaster //: private std::stack void MoveTakeoff(uint32 id, Position const& pos); void MoveCharge(float x, float y, float z, float speed = SPEED_CHARGE, uint32 id = EVENT_CHARGE, bool generatePath = false); - void MoveCharge(PathGenerator path, float speed = SPEED_CHARGE, uint32 id = EVENT_CHARGE); + void MoveCharge(PathGenerator const& path); void MoveKnockbackFrom(float srcX, float srcY, float speedXY, float speedZ); void MoveJumpTo(float angle, float speedXY, float speedZ); void MoveJump(Position const& pos, float speedXY, float speedZ, uint32 id = EVENT_JUMP) diff --git a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp index 1f5503948c8..ea7a8c4c710 100755 --- a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp @@ -34,7 +34,7 @@ void PointMovementGenerator::DoInitialize(T* unit) unit->AddUnitState(UNIT_STATE_ROAMING|UNIT_STATE_ROAMING_MOVE); - if (id == EVENT_CHARGE) + if (id == EVENT_CHARGE_PREPATH) return; Movement::MoveSplineInit init(unit); @@ -58,7 +58,7 @@ bool PointMovementGenerator::DoUpdate(T* unit, uint32 /*diff*/) unit->AddUnitState(UNIT_STATE_ROAMING_MOVE); - if (id != EVENT_CHARGE && i_recalculateSpeed && !unit->movespline->Finalized()) + if (id != EVENT_CHARGE_PREPATH && i_recalculateSpeed && !unit->movespline->Finalized()) { i_recalculateSpeed = false; Movement::MoveSplineInit init(unit); diff --git a/src/server/game/Movement/PathGenerator.h b/src/server/game/Movement/PathGenerator.h index a20f900b584..d41d3160db5 100644 --- a/src/server/game/Movement/PathGenerator.h +++ b/src/server/game/Movement/PathGenerator.h @@ -55,7 +55,7 @@ enum PathType class PathGenerator { public: - PathGenerator(Unit const* owner); + explicit PathGenerator(Unit const* owner); ~PathGenerator(); // Calculate the path from owner to given destination @@ -71,7 +71,7 @@ class PathGenerator Vector3 const& GetEndPosition() const { return _endPosition; } Vector3 const& GetActualEndPosition() const { return _actualEndPosition; } - PointsArray& GetPath() { return _pathPoints; } + PointsArray const& GetPath() const { return _pathPoints; } PathType GetPathType() const { return _type; } private: diff --git a/src/server/game/Movement/Spline/MoveSplineInit.cpp b/src/server/game/Movement/Spline/MoveSplineInit.cpp index 1e4d4950ea0..e661cf877e3 100644 --- a/src/server/game/Movement/Spline/MoveSplineInit.cpp +++ b/src/server/game/Movement/Spline/MoveSplineInit.cpp @@ -158,7 +158,7 @@ namespace Movement { PathGenerator path(unit); bool result = path.CalculatePath(dest.x, dest.y, dest.z, forceDestination); - if (result && path.GetPathType() & ~PATHFIND_NOPATH) + if (result && !(path.GetPathType() & PATHFIND_NOPATH)) { MovebyPath(path.GetPath()); return; diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 18dc6f104a4..53bcd6bd077 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -5148,26 +5148,23 @@ SpellCastResult Spell::CheckCast(bool strict) if (m_caster->HasUnitState(UNIT_STATE_ROOT)) return SPELL_FAILED_ROOTED; - Unit* target = m_targets.GetUnitTarget(); - - if (!target) - return SPELL_FAILED_DONT_REPORT; - - if (m_caster->GetTypeId() == TYPEID_PLAYER) - if (!target->isAlive()) - return SPELL_FAILED_BAD_TARGETS; - - Position pos; - target->GetContactPoint(m_caster, pos.m_positionX, pos.m_positionY, pos.m_positionZ); - target->GetFirstCollisionPosition(pos, CONTACT_DISTANCE, target->GetRelativeAngle(m_caster)); + if (GetSpellInfo()->NeedsExplicitUnitTarget()) + { + Unit* target = m_targets.GetUnitTarget(); + if (!target) + return SPELL_FAILED_DONT_REPORT; - m_preGeneratedPath.SetPathLengthLimit(m_spellInfo->GetMaxRange(true) * 1.5f); - bool result = m_preGeneratedPath.CalculatePath(pos.m_positionX, pos.m_positionY, pos.m_positionZ + target->GetObjectSize()); - if (m_preGeneratedPath.GetPathType() & PATHFIND_SHORT) - return SPELL_FAILED_OUT_OF_RANGE; - else if (!result) - return SPELL_FAILED_NOPATH; + Position pos; + target->GetContactPoint(m_caster, pos.m_positionX, pos.m_positionY, pos.m_positionZ); + target->GetFirstCollisionPosition(pos, CONTACT_DISTANCE, target->GetRelativeAngle(m_caster)); + m_preGeneratedPath.SetPathLengthLimit(m_spellInfo->GetMaxRange(true) * 1.5f); + bool result = m_preGeneratedPath.CalculatePath(pos.m_positionX, pos.m_positionY, pos.m_positionZ + target->GetObjectSize()); + if (m_preGeneratedPath.GetPathType() & PATHFIND_SHORT) + return SPELL_FAILED_OUT_OF_RANGE; + else if (!result || m_preGeneratedPath.GetPathType() & PATHFIND_NOPATH) + return SPELL_FAILED_NOPATH; + } break; } case SPELL_EFFECT_SKINNING: diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 8b440b665ad..93e4b2e4771 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -4918,7 +4918,8 @@ void Spell::EffectCharge(SpellEffIndex /*effIndex*/) if (effectHandleMode == SPELL_EFFECT_HANDLE_LAUNCH_TARGET) { - if (m_preGeneratedPath.GetPathType() & PATHFIND_NOPATH) + // Spell is not using explicit target - no generated path + if (m_preGeneratedPath.GetPathType() == PATHFIND_BLANK) { Position pos; unitTarget->GetContactPoint(m_caster, pos.m_positionX, pos.m_positionY, pos.m_positionZ); diff --git a/src/server/scripts/Commands/cs_mmaps.cpp b/src/server/scripts/Commands/cs_mmaps.cpp index 97861133983..79cd0deb75e 100644 --- a/src/server/scripts/Commands/cs_mmaps.cpp +++ b/src/server/scripts/Commands/cs_mmaps.cpp @@ -95,7 +95,7 @@ public: path.SetUseStraightPath(useStraightPath); bool result = path.CalculatePath(x, y, z); - PointsArray pointPath = path.GetPath(); + PointsArray const& pointPath = path.GetPath(); handler->PSendSysMessage("%s's path to %s:", target->GetName().c_str(), player->GetName().c_str()); handler->PSendSysMessage("Building: %s", useStraightPath ? "StraightPath" : "SmoothPath"); handler->PSendSysMessage("Result: %s - Length: "SIZEFMTD" - Type: %u", (result ? "true" : "false"), pointPath.size(), path.GetPathType()); -- cgit v1.2.3 From ca280dbe051f2d9c43bbda128a6aa6bc19d8149f Mon Sep 17 00:00:00 2001 From: Shauren Date: Wed, 13 Feb 2013 20:24:23 +0100 Subject: Core/Loot: Only 3 items of the same entry can drop on 25 man raid difficulties and 1 everywhere else (non-raid or 10 man) --- src/server/game/Entities/Creature/Creature.cpp | 4 +++ src/server/game/Entities/GameObject/GameObject.cpp | 4 +++ src/server/game/Loot/LootMgr.cpp | 30 ++++++++++++++-------- src/server/game/Loot/LootMgr.h | 3 ++- 4 files changed, 30 insertions(+), 11 deletions(-) (limited to 'src/server') diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 93d4796f21a..220bc4378ae 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -289,6 +289,10 @@ bool Creature::InitEntry(uint32 Entry, uint32 /*team*/, const CreatureData* data --diff; } + // Initialize loot duplicate count depending on raid difficulty + if (GetMap()->IsRaid() && GetMap()->GetSpawnMode() & RAID_DIFFICULTY_MASK_25MAN) + loot.maxDuplicates = 3; + SetEntry(Entry); // normal entry always m_creatureInfo = cinfo; // map mode related always diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index bf0fbb4199d..61e7943453e 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -258,6 +258,10 @@ bool GameObject::Create(uint32 guidlow, uint32 name_id, Map* map, uint32 phaseMa LastUsedScriptID = GetGOInfo()->ScriptId; AIM_Initialize(); + // Initialize loot duplicate count depending on raid difficulty + if (map->IsRaid() && map->GetSpawnMode() & RAID_DIFFICULTY_MASK_25MAN) + loot.maxDuplicates = 3; + return true; } diff --git a/src/server/game/Loot/LootMgr.cpp b/src/server/game/Loot/LootMgr.cpp index 128cf358557..56e72a10930 100644 --- a/src/server/game/Loot/LootMgr.cpp +++ b/src/server/game/Loot/LootMgr.cpp @@ -52,16 +52,27 @@ LootStore LootTemplates_Reference("reference_loot_template", "reference LootStore LootTemplates_Skinning("skinning_loot_template", "creature skinning id", true); LootStore LootTemplates_Spell("spell_loot_template", "spell id (random item creating)", false); -struct NotMatchingLootMode : public std::unary_function +// Selects invalid loot items to be removed from group possible entries (before rolling) +struct LootGroupInvalidSelector : public std::unary_function { - explicit NotMatchingLootMode(uint16 lootMode) : _lootMode(lootMode) { } + explicit LootGroupInvalidSelector(Loot const& loot, uint16 lootMode) : _loot(loot), _lootMode(lootMode) { } bool operator()(LootStoreItem* item) const { - return !(item->lootmode & _lootMode); + if (!(item->lootmode & _lootMode)) + return true; + + uint8 foundDuplicates = 0; + for (std::vector::const_iterator itr = _loot.items.begin(); itr != _loot.items.end(); ++itr) + if (itr->itemid == item->itemid) + if (++foundDuplicates == _loot.maxDuplicates) + return true; + + return false; } private: + Loot const& _loot; uint16 _lootMode; }; @@ -89,7 +100,7 @@ class LootTemplate::LootGroup // A set of loot def LootStoreItemList ExplicitlyChanced; // Entries with chances defined in DB LootStoreItemList EqualChanced; // Zero chances - every entry takes the same chance - LootStoreItem const* Roll(uint16 lootMode) const; // Rolls an item from the group, returns NULL if all miss their chances + LootStoreItem const* Roll(Loot& loot, uint16 lootMode) const; // Rolls an item from the group, returns NULL if all miss their chances // This class must never be copied - storing pointers LootGroup(LootGroup const&); @@ -1076,10 +1087,10 @@ void LootTemplate::LootGroup::AddEntry(LootStoreItem* item) } // Rolls an item from the group, returns NULL if all miss their chances -LootStoreItem const* LootTemplate::LootGroup::Roll(uint16 lootMode) const +LootStoreItem const* LootTemplate::LootGroup::Roll(Loot& loot, uint16 lootMode) const { LootStoreItemList possibleLoot = ExplicitlyChanced; - possibleLoot.remove_if(NotMatchingLootMode(lootMode)); + possibleLoot.remove_if(LootGroupInvalidSelector(loot, lootMode)); if (!possibleLoot.empty()) // First explicitly chanced entries are checked { @@ -1098,7 +1109,7 @@ LootStoreItem const* LootTemplate::LootGroup::Roll(uint16 lootMode) const } possibleLoot = EqualChanced; - possibleLoot.remove_if(NotMatchingLootMode(lootMode)); + possibleLoot.remove_if(LootGroupInvalidSelector(loot, lootMode)); if (!possibleLoot.empty()) // If nothing selected yet - an item is taken from equal-chanced part return Trinity::Containers::SelectRandomContainerElement(possibleLoot); @@ -1145,7 +1156,7 @@ void LootTemplate::LootGroup::CopyConditions(ConditionList /*conditions*/) // Rolls an item from the group (if any takes its chance) and adds the item to the loot void LootTemplate::LootGroup::Process(Loot& loot, uint16 lootMode) const { - if (LootStoreItem const* item = Roll(lootMode)) + if (LootStoreItem const* item = Roll(loot, lootMode)) loot.AddItem(*item); } @@ -1285,7 +1296,7 @@ void LootTemplate::Process(Loot& loot, bool rate, uint16 lootMode, uint8 groupId for (LootStoreItemList::const_iterator i = Entries.begin(); i != Entries.end(); ++i) { LootStoreItem* item = *i; - if (item->lootmode &~ lootMode) // Do not add if mode mismatch + if (!(item->lootmode & lootMode)) // Do not add if mode mismatch continue; if (!item->Roll(rate)) @@ -1294,7 +1305,6 @@ void LootTemplate::Process(Loot& loot, bool rate, uint16 lootMode, uint8 groupId if (item->mincountOrRef < 0) // References processing { LootTemplate const* Referenced = LootTemplates_Reference.GetLootFor(-item->mincountOrRef); - if (!Referenced) continue; // Error message already printed at loading stage diff --git a/src/server/game/Loot/LootMgr.h b/src/server/game/Loot/LootMgr.h index df2717ee36e..5c858a35242 100644 --- a/src/server/game/Loot/LootMgr.h +++ b/src/server/game/Loot/LootMgr.h @@ -298,12 +298,13 @@ struct Loot uint8 unlootedCount; uint64 roundRobinPlayer; // GUID of the player having the Round-Robin ownership for the loot. If 0, round robin owner has released. LootType loot_type; // required for achievement system + uint8 maxDuplicates; // Max amount of items with the same entry that can drop (default is 1; on 25 man raid mode 3) // GUIDLow of container that holds this loot (item_instance.entry) // Only set for inventory items that can be right-click looted uint32 containerID; - Loot(uint32 _gold = 0) : gold(_gold), unlootedCount(0), loot_type(LOOT_CORPSE), containerID(0) {} + Loot(uint32 _gold = 0) : gold(_gold), unlootedCount(0), loot_type(LOOT_CORPSE), maxDuplicates(1), containerID(0) {} ~Loot() { clear(); } // For deleting items at loot removal since there is no backward interface to the Item() -- cgit v1.2.3