From 8095eede5a1123e8f5b4131e1d07f1679df85691 Mon Sep 17 00:00:00 2001 From: Blaymoira Date: Sun, 25 Jan 2009 17:38:27 +0100 Subject: [PATCH 1/7] *Support for quest 10458, 10481, 10480 - by mrbungle --HG-- branch : trunk --- sql/updates/965_world_scripts.sql | 2 +- sql/updates/973_world_scripts.sql | 1 + sql/updates/CMakeLists.txt | 1 + .../shadowmoon_valley/shadowmoon_valley.cpp | 132 +++++++++++++++++- 4 files changed, 129 insertions(+), 7 deletions(-) create mode 100644 sql/updates/973_world_scripts.sql diff --git a/sql/updates/965_world_scripts.sql b/sql/updates/965_world_scripts.sql index 8f141c9290..9c93f78ec0 100644 --- a/sql/updates/965_world_scripts.sql +++ b/sql/updates/965_world_scripts.sql @@ -1,4 +1,4 @@ -INSERT INTO `spell_script_target` VALUES +REPLACE INTO `spell_script_target` VALUES (33655,0,183350), (33655,0,183351), (44374,1,24722), diff --git a/sql/updates/973_world_scripts.sql b/sql/updates/973_world_scripts.sql new file mode 100644 index 0000000000..42b970aaed --- /dev/null +++ b/sql/updates/973_world_scripts.sql @@ -0,0 +1 @@ +update creature_template set scriptname = 'npc_enraged_spirit' where entry in (21050, 21061, 21060, 21059); \ No newline at end of file diff --git a/sql/updates/CMakeLists.txt b/sql/updates/CMakeLists.txt index c92e30e023..c7b09fe325 100644 --- a/sql/updates/CMakeLists.txt +++ b/sql/updates/CMakeLists.txt @@ -161,4 +161,5 @@ INSTALL(FILES 965_world_scripts.sql 966_world_scripts.sql 970_world_scripts.sql +973_world_scripts.sql DESTINATION share/trinity/sql/updates) diff --git a/src/bindings/scripts/scripts/zone/shadowmoon_valley/shadowmoon_valley.cpp b/src/bindings/scripts/scripts/zone/shadowmoon_valley/shadowmoon_valley.cpp index 30056b1e7a..83244ff7b7 100644 --- a/src/bindings/scripts/scripts/zone/shadowmoon_valley/shadowmoon_valley.cpp +++ b/src/bindings/scripts/scripts/zone/shadowmoon_valley/shadowmoon_valley.cpp @@ -17,7 +17,7 @@ /* ScriptData SDName: Shadowmoon_Valley SD%Complete: 100 -SDComment: Quest support: 10519, 10583, 10601, 10814, 10804, 10854, 11082, 10781, 10451. Vendor Drake Dealer Hurlunk. +SDComment: Quest support: 10519, 10583, 10601, 10814, 10804, 10854, 10458, 10481, 10480, 11082, 10781, 10451. Vendor Drake Dealer Hurlunk. SDCategory: Shadowmoon Valley EndScriptData */ @@ -36,6 +36,7 @@ mob_torloth_the_magnificent mob_illidari_spawn npc_lord_illidan_stormrage go_crystal_prison +npc_enraged_spirit EndContentData */ #include "precompiled.h" @@ -958,7 +959,7 @@ struct TRINITY_DLL_DECL npc_earthmender_wildaAI : public npc_escortAI } ((Creature*)CoilskarAssassin)->AI()->AttackStart(m_creature); } - else error_log("SD2 ERROR: Coilskar Assassin couldn't be summmoned"); + else error_log("TSCR ERROR: Coilskar Assassin couldn't be summmoned"); } void JustDied(Unit* killer) @@ -1636,6 +1637,120 @@ CreatureAI* GetAI_mob_torloth_the_magnificent(Creature* c) return new mob_torloth_the_magnificentAI(c); } +/*#### +# npc_enraged_spirits +####*/ + +/* QUESTS */ +#define QUEST_ENRAGED_SPIRITS_FIRE_EARTH 10458 +#define QUEST_ENRAGED_SPIRITS_AIR 10481 +#define QUEST_ENRAGED_SPIRITS_WATER 10480 + +/* Totem */ +#define ENTRY_TOTEM_OF_SPIRITS 21071 +#define RADIUS_TOTEM_OF_SPIRITS 15 + +/* SPIRITS */ +#define ENTRY_ENRAGED_EARTH_SPIRIT 21050 +#define ENTRY_ENRAGED_FIRE_SPIRIT 21061 +#define ENTRY_ENRAGED_AIR_SPIRIT 21060 +#define ENTRY_ENRAGED_WATER_SPIRIT 21059 + +/* SOULS */ +#define ENTRY_EARTHEN_SOUL 21073 +#define ENTRY_FIERY_SOUL 21097 +#define ENTRY_ENRAGED_AIRY_SOUL 21116 +#define ENTRY_ENRAGED_WATERY_SOUL 21109 // wrong model + +/* SPELL KILLCREDIT - not working!?! - using KilledMonster */ +#define SPELL_EARTHEN_SOUL_CAPTURED_CREDIT 36108 +#define SPELL_FIERY_SOUL_CAPTURED_CREDIT 36117 +#define SPELL_AIRY_SOUL_CAPTURED_CREDIT 36182 +#define SPELL_WATERY_SOUL_CAPTURED_CREDIT 36171 + +/* KilledMonster Workaround */ +#define CREDIT_FIRE 21094 +#define CREDIT_WATER 21095 +#define CREDIT_AIR 21096 +#define CREDIT_EARTH 21092 + +/* Captured Spell/Buff */ +#define SPELL_SOUL_CAPTURED 36115 + +/* Factions */ +#define ENRAGED_SOUL_FRIENDLY 35 +#define ENRAGED_SOUL_HOSTILE 14 + +struct TRINITY_DLL_DECL npc_enraged_spiritAI : public ScriptedAI +{ + npc_enraged_spiritAI(Creature *c) : ScriptedAI(c) {Reset();} + + void Reset() { } + + void Aggro(Unit *who){} + + void JustDied(Unit* killer) + { + // always spawn spirit on death + // if totem around + // move spirit to totem and cast kill count + uint32 entry = 0; + uint32 credit = 0; + + switch(m_creature->GetEntry()) { + case ENTRY_ENRAGED_FIRE_SPIRIT: + entry = ENTRY_FIERY_SOUL; + //credit = SPELL_FIERY_SOUL_CAPTURED_CREDIT; + credit = CREDIT_FIRE; + break; + case ENTRY_ENRAGED_EARTH_SPIRIT: + entry = ENTRY_EARTHEN_SOUL; + //credit = SPELL_EARTHEN_SOUL_CAPTURED_CREDIT; + credit = CREDIT_EARTH; + break; + case ENTRY_ENRAGED_AIR_SPIRIT: + entry = ENTRY_ENRAGED_AIRY_SOUL; + //credit = SPELL_AIRY_SOUL_CAPTURED_CREDIT; + credit = CREDIT_AIR; + break; + case ENTRY_ENRAGED_WATER_SPIRIT: + entry = ENTRY_ENRAGED_WATERY_SOUL; + //credit = SPELL_WATERY_SOUL_CAPTURED_CREDIT; + credit = CREDIT_WATER; + break; + } + + // Spawn Soul on Kill ALWAYS! + Creature* Summoned = NULL; + Unit* totemOspirits = NULL; + + if ( entry != 0 ) + Summoned = DoSpawnCreature(entry, 0, 0, 1, 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 5000); + + // FIND TOTEM, PROCESS QUEST + if (Summoned) + { + totemOspirits = FindCreature(ENTRY_TOTEM_OF_SPIRITS, RADIUS_TOTEM_OF_SPIRITS, m_creature); + if (totemOspirits) + { + Summoned->setFaction(ENRAGED_SOUL_FRIENDLY); + Summoned->GetMotionMaster()->MovePoint(0,totemOspirits->GetPositionX(), totemOspirits->GetPositionY(), Summoned->GetPositionZ()); + + Player* Owner = (Player*)totemOspirits->GetOwner(); + if (Owner) + // DoCast(Owner, credit); -- not working! + Owner->KilledMonster(credit, Summoned->GetGUID()); + DoCast(totemOspirits,SPELL_SOUL_CAPTURED); + } + } + } +}; + +CreatureAI* GetAI_npc_enraged_spirit(Creature *_Creature) +{ +return new npc_enraged_spiritAI(_Creature); +} + /*##### # ######*/ @@ -1708,21 +1823,26 @@ void AddSC_shadowmoon_valley() newscript = new Script; newscript->Name = "npc_lord_illidan_stormrage"; - newscript->GetAI = GetAI_npc_lord_illidan_stormrage; + newscript->GetAI = &GetAI_npc_lord_illidan_stormrage; newscript->RegisterSelf(); newscript = new Script; newscript->Name = "go_crystal_prison"; - newscript->pGOQuestAccept = GOQuestAccept_GO_crystal_prison; + newscript->pGOQuestAccept = &GOQuestAccept_GO_crystal_prison; newscript->RegisterSelf(); newscript = new Script; newscript->Name = "mob_illidari_spawn"; - newscript->GetAI = GetAI_mob_illidari_spawn; + newscript->GetAI = &GetAI_mob_illidari_spawn; newscript->RegisterSelf(); newscript = new Script; newscript->Name = "mob_torloth_the_magnificent"; - newscript->GetAI = GetAI_mob_torloth_the_magnificent; + newscript->GetAI = &GetAI_mob_torloth_the_magnificent; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_enraged_spirit"; + newscript->GetAI = &GetAI_npc_enraged_spirit; newscript->RegisterSelf(); } From 039791db46c5fb94cedce1c2688926494e7f2757 Mon Sep 17 00:00:00 2001 From: KingPin Date: Sun, 25 Jan 2009 19:20:54 -0500 Subject: [PATCH 2/7] Fixes for genrevision --HG-- branch : trunk --- src/tools/genrevision/genrevision.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tools/genrevision/genrevision.cpp b/src/tools/genrevision/genrevision.cpp index f9abc71b47..99c407c33d 100644 --- a/src/tools/genrevision/genrevision.cpp +++ b/src/tools/genrevision/genrevision.cpp @@ -87,6 +87,7 @@ void extractDataFromHG(FILE* EntriesFile, std::string path, bool url, RawData& d { thash_str[i] = hash_str[i]; } + thash_str[12] = '\0'; strcpy(data.hash_str,thash_str); strcpy(data.rev_str,revision_str); From 91d49437bd51c8d928e8f5e0c06a8777d9e01f14 Mon Sep 17 00:00:00 2001 From: megamage Date: Mon, 26 Jan 2009 18:13:21 -0600 Subject: [PATCH 3/7] *Fix charge speed. --HG-- branch : trunk --- src/game/DestinationHolderImp.h | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/game/DestinationHolderImp.h b/src/game/DestinationHolderImp.h index f799c8613e..f30768e799 100644 --- a/src/game/DestinationHolderImp.h +++ b/src/game/DestinationHolderImp.h @@ -96,14 +96,12 @@ DestinationHolder::StartTravel(TRAVELLER &traveller, bool sendMove) else //Walking on the ground dist = sqrt((dx*dx) + (dy*dy)); + float speed; if(traveller.GetTraveller().hasUnitState(UNIT_STAT_CHARGING)) - i_totalTravelTime = 1000; + speed = 0.025f; // assume it is 25 yard per second else - { - float speed = traveller.Speed(); - speed *= 0.001f; // speed is in seconds so convert from second to millisecond - i_totalTravelTime = static_cast(dist/speed); - } + speed = traveller.Speed() * 0.001f; // speed is in seconds so convert from second to millisecond + i_totalTravelTime = static_cast(dist/speed); i_timeElapsed = 0; if(sendMove) From 8dd98a1a12f097bbd5d1f1b09814cc6dfae5f2e6 Mon Sep 17 00:00:00 2001 From: KingPin Date: Mon, 26 Jan 2009 19:43:00 -0500 Subject: [PATCH 4/7] Non working code backed out --HG-- branch : trunk --- src/game/Spell.cpp | 26 +++----------------------- src/game/World.cpp | 5 ----- src/game/World.h | 4 ---- src/trinitycore/trinitycore.conf.dist | 18 ------------------ 4 files changed, 3 insertions(+), 50 deletions(-) diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index ddfb9c01be..aa0d24ffdb 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -4168,29 +4168,9 @@ uint8 Spell::CanCast(bool strict) // not allow cast fly spells at old maps by players (all spells is self target) if(m_caster->GetTypeId()==TYPEID_PLAYER) { - if(!((Player*)m_caster)->isGameMaster()) - { - uint32 v_map = GetVirtualMapForMapAndZone(m_caster->GetMapId(),m_caster->GetZoneId()); - switch(v_map) - { - case 0: - case 1: - { - if (!sWorld.getConfig(CONFIG_FLYING_MOUNTS_AZEROTH)) - return SPELL_FAILED_NOT_HERE; - } break; - case 530: - { - if (!sWorld.getConfig(CONFIG_FLYING_MOUNTS_OUTLAND)) - return SPELL_FAILED_NOT_HERE; - } break; - default: - { - if (!sWorld.getConfig(CONFIG_FLYING_MOUNTS_OTHERS)) - return SPELL_FAILED_NOT_HERE; - } break; - } - } + if( !((Player*)m_caster)->isGameMaster() && + GetVirtualMapForMapAndZone(m_caster->GetMapId(),m_caster->GetZoneId()) != 530) + return SPELL_FAILED_NOT_HERE; } break; diff --git a/src/game/World.cpp b/src/game/World.cpp index 219c656dca..89a0b75cd3 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -526,11 +526,6 @@ void World::LoadConfigSettings(bool reload) ///- Read other configuration items from the config file - ///- Do we allow flying mounts in Azeroth/Outland and others (others being instances, BGs, arenas)? - m_configs[CONFIG_FLYING_MOUNTS_AZEROTH] = sConfig.GetBoolDefault("FlyingMounts.Azeroth", false); - m_configs[CONFIG_FLYING_MOUNTS_OUTLAND] = sConfig.GetBoolDefault("FlyingMounts.Outland", true); - m_configs[CONFIG_FLYING_MOUNTS_OTHERS] = sConfig.GetBoolDefault("FlyingMounts.Others", false); - m_configs[CONFIG_COMPRESSION] = sConfig.GetIntDefault("Compression", 1); if(m_configs[CONFIG_COMPRESSION] < 1 || m_configs[CONFIG_COMPRESSION] > 9) { diff --git a/src/game/World.h b/src/game/World.h index e2e2096726..63d9b52d7f 100644 --- a/src/game/World.h +++ b/src/game/World.h @@ -184,10 +184,6 @@ enum WorldConfigs CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS, CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER, - CONFIG_FLYING_MOUNTS_AZEROTH, - CONFIG_FLYING_MOUNTS_OUTLAND, - CONFIG_FLYING_MOUNTS_OTHERS, - CONFIG_MAX_WHO, CONFIG_BG_START_MUSIC, CONFIG_START_ALL_SPELLS, diff --git a/src/trinitycore/trinitycore.conf.dist b/src/trinitycore/trinitycore.conf.dist index 7da04b0bdf..27253cc875 100644 --- a/src/trinitycore/trinitycore.conf.dist +++ b/src/trinitycore/trinitycore.conf.dist @@ -502,21 +502,6 @@ LogColors = "" # Default: 0 (false) # 1 (true) # -# FlyingMounts.Azeroth -# Enable/disable flying mounts in Azeroth (map 0 and 1). -# Default: 0 - off -# 1 - on (may be crashy) -# -# FlyingMounts.Outland -# Enable/disable flying mounts in Outland (map 530). -# Default: 1 - on -# 0 - off -# -# FlyingMounts.Others -# Enable/disable flying mounts in other maps (instances, arenas, BGs, etc). -# Default: 0 - off -# 1 - on (may be crashy) -# # CastUnstuck # Allow cast or not Unstuck spell at .start or client Help option use # Default: 1 (true) @@ -622,9 +607,6 @@ ActivateWeather = 1 Battleground.CastDeserter = 1 Battleground.QueueAnnouncer.Enable = 1 Battleground.QueueAnnouncer.PlayerOnly = 0 -FlyingMounts.Azeroth = 0 -FlyingMounts.Outland = 1 -FlyingMounts.Others = 0 CastUnstuck = 1 Instance.IgnoreLevel = 0 Instance.IgnoreRaid = 0 From 50c912dc0037821ff89fc19f8a84c3cca50035c6 Mon Sep 17 00:00:00 2001 From: KingPin Date: Mon, 26 Jan 2009 20:03:51 -0500 Subject: [PATCH 5/7] * Rest of the new can fly code removed. --HG-- branch : trunk --- src/game/Player.cpp | 54 ++------------------------------------------- src/game/Player.h | 5 +---- src/game/Spell.cpp | 6 +++-- 3 files changed, 7 insertions(+), 58 deletions(-) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 533b9e68ac..e7ae690c5b 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -18753,7 +18753,8 @@ void Player::SetClientControl(Unit* target, uint8 allowMove) void Player::UpdateZoneDependentAuras( uint32 newZone ) { // remove new continent flight forms - if(!CanFlyInMap(GetVirtualMapForMapAndZone(GetMapId(),newZone))) + if( !isGameMaster() && + GetVirtualMapForMapAndZone(GetMapId(),newZone) != 530) { RemoveSpellsCausingAura(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED); RemoveSpellsCausingAura(SPELL_AURA_FLY); @@ -19219,54 +19220,3 @@ void Player::UpdateCharmedAI() } } -bool Player::CanFlyInMap(const uint32 mapID) const -{ - // we return false if the map doesn't even exist - MapEntry const *entry = sMapStore.LookupEntry(mapID); - if(!entry) - { - sLog.outDebug("Unknown mapID handed to Player::CanFlyInMap; disallowing flying."); - return false; - } - - // GMs can always fly - if( isGameMaster() ) - { - return true; - } - - // check whether we can fly here depending on map/config - switch(mapID) - { - // kalimdor/eastern kingdoms - case 0: - case 1: - { - return sWorld.getConfig(CONFIG_FLYING_MOUNTS_AZEROTH); - } - // outland - case 530: - { - return sWorld.getConfig(CONFIG_FLYING_MOUNTS_OUTLAND); - } - // all other maps - default: - { - return sWorld.getConfig(CONFIG_FLYING_MOUNTS_OTHERS); - } - } -} - -// this is just a dummy function that does the same as CanFlyInMap, but based on area ID -bool Player::CanFlyInArea(const uint32 areaID) const -{ - // we return false if the area doesn't even exist - AreaTableEntry const *entry = sAreaStore.LookupEntry(areaID); - if(!entry) - { - sLog.outDebug("Unknown areaID handed to Player::CanFlyInArea; disallowing flying."); - return false; - } - - return CanFlyInMap(entry->mapid); -} diff --git a/src/game/Player.h b/src/game/Player.h index 90a0f29ab8..a5fd39a890 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -2036,10 +2036,7 @@ class TRINITY_DLL_SPEC Player : public Unit uint32 GetOldPetSpell() const { return m_oldpetspell; } void SetOldPetSpell(uint32 petspell) { m_oldpetspell = petspell; } - // check if player can fly in map/area according to config - bool CanFlyInMap(const uint32 mapID) const; - bool CanFlyInArea(const uint32 areaID) const; - + /*********************************************************/ /*** INSTANCE SYSTEM ***/ /*********************************************************/ diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index fb5662bfd7..7963a9b087 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -4172,9 +4172,11 @@ uint8 Spell::CanCast(bool strict) case SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED: case SPELL_AURA_FLY: { + // not allow cast fly spells at old maps by players (all spells is self target) if(m_caster->GetTypeId()==TYPEID_PLAYER) { - if(!((Player*)m_caster)->CanFlyInMap(GetVirtualMapForMapAndZone(m_caster->GetMapId(),m_caster->GetZoneId()))) + if( !((Player*)m_caster)->isGameMaster() && + GetVirtualMapForMapAndZone(m_caster->GetMapId(),m_caster->GetZoneId()) != 530) return SPELL_FAILED_NOT_HERE; } break; @@ -5425,4 +5427,4 @@ int32 Spell::CalculateDamageDone(Unit *unit, const uint32 effectMask, float *mul } return damageDone; -} \ No newline at end of file +} From 635d16439aab8ef33ba0a810f8a8bcb897907d3c Mon Sep 17 00:00:00 2001 From: megamage Date: Mon, 26 Jan 2009 19:23:50 -0600 Subject: [PATCH 6/7] *Fix some bugs about chain spells. Will not hit the selected target twice. Will always hit the selected target as the first target. --HG-- branch : trunk --- src/game/Spell.cpp | 133 +++++++++++++++++++++++---------------------- src/game/Spell.h | 14 +++-- 2 files changed, 77 insertions(+), 70 deletions(-) diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index fb5662bfd7..a02bd20275 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -1330,55 +1330,45 @@ struct TargetDistanceOrder : public std::binary_function &TagUnitMap, Unit* pUnitTarget, float max_range, uint32 unMaxTargets) +void Spell::SearchChainTarget(std::list &TagUnitMap, float max_range, uint32 num, SpellTargets TargetType) { - if(!pUnitTarget) + Unit *cur = m_targets.getUnitTarget(); + if(!cur) return; //FIXME: This very like horrible hack and wrong for most spells if(m_spellInfo->DmgClass != SPELL_DAMAGE_CLASS_MELEE) - max_range += unMaxTargets * CHAIN_SPELL_JUMP_RADIUS; + max_range += num * CHAIN_SPELL_JUMP_RADIUS; - std::list tempUnitMap; - Trinity::AnyAoETargetUnitInObjectRangeCheck u_check(pUnitTarget, m_caster, max_range); - Trinity::UnitListSearcher searcher(tempUnitMap, u_check); - m_caster->VisitNearbyObject(max_range, searcher); + std::list tempUnitMap; + SearchAreaTarget(tempUnitMap, max_range, PUSH_TARGET_CENTER, TargetType); + tempUnitMap.remove(cur); - tempUnitMap.sort(TargetDistanceOrder(pUnitTarget)); - - if(tempUnitMap.empty()) - return; - - uint32 t = unMaxTargets; - if(pUnitTarget != m_caster) + while(num) { - if(*tempUnitMap.begin() == pUnitTarget) - tempUnitMap.erase(tempUnitMap.begin()); - TagUnitMap.push_back(pUnitTarget); - --t; - } - Unit *prev = pUnitTarget; + TagUnitMap.push_back(cur); + --num; - std::list::iterator next = tempUnitMap.begin(); - - while(t && next != tempUnitMap.end()) - { - if(prev->GetDistance(*next) > CHAIN_SPELL_JUMP_RADIUS) + if(tempUnitMap.empty()) break; - if(!prev->IsWithinLOSInMap(*next) - || m_spellInfo->DmgClass==SPELL_DAMAGE_CLASS_MELEE && !m_caster->isInFront(*next, max_range)) + tempUnitMap.sort(TargetDistanceOrder(cur)); + std::list::iterator next = tempUnitMap.begin(); + + if(cur->GetDistance(*next) > CHAIN_SPELL_JUMP_RADIUS) + break; + + while(!cur->IsWithinLOSInMap(*next) + || m_spellInfo->DmgClass==SPELL_DAMAGE_CLASS_MELEE + && !m_caster->isInFront(*next, max_range)) { ++next; - continue; + if(next == tempUnitMap.end()) + return; } - prev = *next; - TagUnitMap.push_back(prev); - tempUnitMap.erase(next); - tempUnitMap.sort(TargetDistanceOrder(prev)); - next = tempUnitMap.begin(); - --t; + cur = *next; + tempUnitMap.erase(next); } } @@ -1395,11 +1385,22 @@ void Spell::SearchAreaTarget(std::list &TagUnitMap, float radius, const u x = m_targets.m_destX; y = m_targets.m_destY; } - else + else if(type == PUSH_SELF_CENTER) { x = m_caster->GetPositionX(); y = m_caster->GetPositionY(); } + else if(type == PUSH_TARGET_CENTER) + { + Unit *target = m_targets.getUnitTarget(); + if(!target) + { + sLog.outError( "SPELL: cannot find unit target for spell ID %u\n", m_spellInfo->Id ); + return; + } + x = target->GetPositionX(); + y = target->GetPositionY(); + } Trinity::SpellNotifierCreatureAndPlayer notifier(*this, TagUnitMap, radius, type, TargetType, entry); if((m_spellInfo->AttributesEx3 & SPELL_ATTR_EX3_PLAYERS_ONLY) @@ -1431,13 +1432,13 @@ Unit* Spell::SearchNearbyTarget(float radius, SpellTargets TargetType, uint32 en } } default: - case SPELL_TARGETS_AOE_DAMAGE: + case SPELL_TARGETS_ENEMY: { Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(m_caster, m_caster, radius); Trinity::UnitLastSearcher searcher(target, u_check); m_caster->VisitNearbyObject(radius, searcher); }break; - case SPELL_TARGETS_FRIENDLY: + case SPELL_TARGETS_ALLY: { Trinity::AnyFriendlyUnitInObjectRangeCheck u_check(m_caster, m_caster, radius); Trinity::UnitLastSearcher searcher(target, u_check); @@ -1531,13 +1532,10 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list &TagUnitMap) target->GetPartyMember(TagUnitMap, radius); break; case TARGET_UNIT_TARGET_ENEMY: - if(Unit* pUnitTarget = SelectMagnetTarget()) - { - if(EffectChainTarget <= 1) - TagUnitMap.push_back(pUnitTarget); - else //TODO: chain target should also use magnet target - SearchChainTarget(TagUnitMap, pUnitTarget, radius, EffectChainTarget); - } + if(EffectChainTarget <= 1) + TagUnitMap.push_back(SelectMagnetTarget()); + else if(SelectMagnetTarget()) //TODO: chain target should also use magnet target + SearchChainTarget(TagUnitMap, radius, EffectChainTarget, SPELL_TARGETS_ENEMY); break; } }break; @@ -1584,12 +1582,12 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list &TagUnitMap) case TARGET_UNIT_AREA_ENEMY_GROUND: m_targets.m_targetMask |= TARGET_FLAG_DEST_LOCATION; case TARGET_UNIT_AREA_ENEMY: - SearchAreaTarget(TagUnitMap, radius, PUSH_DEST_CENTER, SPELL_TARGETS_AOE_DAMAGE); + SearchAreaTarget(TagUnitMap, radius, PUSH_DEST_CENTER, SPELL_TARGETS_ENEMY); break; case TARGET_UNIT_AREA_ALLY_GROUND: m_targets.m_targetMask |= TARGET_FLAG_DEST_LOCATION; case TARGET_UNIT_AREA_ALLY: - SearchAreaTarget(TagUnitMap, radius, PUSH_DEST_CENTER, SPELL_TARGETS_FRIENDLY); + SearchAreaTarget(TagUnitMap, radius, PUSH_DEST_CENTER, SPELL_TARGETS_ALLY); break; case TARGET_UNIT_AREA_PARTY_GROUND: m_targets.m_targetMask |= TARGET_FLAG_DEST_LOCATION; @@ -1604,7 +1602,7 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list &TagUnitMap) SpellScriptTarget::const_iterator upper = spellmgr.GetEndSpellScriptTarget(m_spellInfo->Id); if(lower==upper) { - SearchAreaTarget(TagUnitMap, radius, PUSH_DEST_CENTER, SPELL_TARGETS_AOE_DAMAGE); + SearchAreaTarget(TagUnitMap, radius, PUSH_DEST_CENTER, SPELL_TARGETS_ENEMY); sLog.outErrorDb("Spell (ID: %u) (caster Entry: %u) does not have record in `spell_script_target`", m_spellInfo->Id, m_caster->GetEntry()); break; } @@ -1664,32 +1662,39 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list &TagUnitMap) case TARGET_IN_FRONT_OF_CASTER: case TARGET_UNIT_CONE_ENEMY_UNKNOWN: if(m_customAttr & SPELL_ATTR_CU_CONE_BACK) - SearchAreaTarget(TagUnitMap, radius, PUSH_IN_BACK, SPELL_TARGETS_AOE_DAMAGE); + SearchAreaTarget(TagUnitMap, radius, PUSH_IN_BACK, SPELL_TARGETS_ENEMY); else if(m_customAttr & SPELL_ATTR_CU_CONE_LINE) - SearchAreaTarget(TagUnitMap, radius, PUSH_IN_LINE, SPELL_TARGETS_AOE_DAMAGE); + SearchAreaTarget(TagUnitMap, radius, PUSH_IN_LINE, SPELL_TARGETS_ENEMY); else - SearchAreaTarget(TagUnitMap, radius, PUSH_IN_FRONT, SPELL_TARGETS_AOE_DAMAGE); + SearchAreaTarget(TagUnitMap, radius, PUSH_IN_FRONT, SPELL_TARGETS_ENEMY); break; case TARGET_UNIT_CONE_ALLY: - SearchAreaTarget(TagUnitMap, radius, PUSH_IN_FRONT, SPELL_TARGETS_FRIENDLY); + SearchAreaTarget(TagUnitMap, radius, PUSH_IN_FRONT, SPELL_TARGETS_ALLY); break; // nearby target case TARGET_UNIT_NEARBY_ALLY: - { - if(Unit* pUnitTarget = SearchNearbyTarget(radius, SPELL_TARGETS_FRIENDLY)) - TagUnitMap.push_back(pUnitTarget); - }break; - case TARGET_RANDOM_ENEMY_CHAIN_IN_AREA: - { - if(EffectChainTarget <= 1) + if(!m_targets.getUnitTarget()) + m_targets.setUnitTarget(SearchNearbyTarget(radius, SPELL_TARGETS_ALLY)); + if(m_targets.getUnitTarget()) { - if(Unit* pUnitTarget = SearchNearbyTarget(radius, SPELL_TARGETS_AOE_DAMAGE)) - TagUnitMap.push_back(pUnitTarget); + if(EffectChainTarget <= 1) + TagUnitMap.push_back(m_targets.getUnitTarget()); + else + SearchChainTarget(TagUnitMap, radius, EffectChainTarget, SPELL_TARGETS_ALLY); } - else - SearchChainTarget(TagUnitMap, m_caster, radius, EffectChainTarget); - }break; + break; + case TARGET_RANDOM_ENEMY_CHAIN_IN_AREA: + if(!m_targets.getUnitTarget()) + m_targets.setUnitTarget(SearchNearbyTarget(radius, SPELL_TARGETS_ENEMY)); + if(m_targets.getUnitTarget()) + { + if(EffectChainTarget <= 1) + TagUnitMap.push_back(m_targets.getUnitTarget()); + else + SearchChainTarget(TagUnitMap, radius, EffectChainTarget, SPELL_TARGETS_ENEMY); + } + break; case TARGET_SCRIPT: case TARGET_SCRIPT_COORDINATES: case TARGET_UNIT_AREA_SCRIPT: @@ -1800,7 +1805,7 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list &TagUnitMap) float max_range = radius + unMaxTargets * CHAIN_SPELL_JUMP_RADIUS; std::list tempUnitMap; - Trinity::SpellNotifierCreatureAndPlayer notifier(*this, tempUnitMap, max_range, PUSH_SELF_CENTER, SPELL_TARGETS_FRIENDLY); + Trinity::SpellNotifierCreatureAndPlayer notifier(*this, tempUnitMap, max_range, PUSH_SELF_CENTER, SPELL_TARGETS_ALLY); m_caster->VisitNearbyObject(max_range, notifier); if(m_caster != pUnitTarget && std::find(tempUnitMap.begin(),tempUnitMap.end(),m_caster) == tempUnitMap.end() ) diff --git a/src/game/Spell.h b/src/game/Spell.h index 9debbf7efd..f645dec828 100644 --- a/src/game/Spell.h +++ b/src/game/Spell.h @@ -83,6 +83,7 @@ enum SpellNotifyPushType PUSH_IN_LINE, PUSH_SELF_CENTER, PUSH_DEST_CENTER, + PUSH_TARGET_CENTER, }; bool IsQuestTameSpell(uint32 spellId); @@ -202,8 +203,8 @@ enum ReplenishType enum SpellTargets { - SPELL_TARGETS_FRIENDLY, - SPELL_TARGETS_AOE_DAMAGE, + SPELL_TARGETS_ALLY, + SPELL_TARGETS_ENEMY, SPELL_TARGETS_ENTRY }; @@ -539,8 +540,9 @@ class Spell bool IsAliveUnitPresentInTargetList(); void SearchAreaTarget(std::list &data, float radius, const uint32 &type, SpellTargets TargetType, uint32 entry = 0); + void SearchChainTarget(std::list &data, float radius, uint32 unMaxTargets, + SpellTargets TargetType); Unit* SearchNearbyTarget(float radius, SpellTargets TargetType, uint32 entry = 0); - void SearchChainTarget(std::list &data, Unit* pUnitTarget, float max_range, uint32 unMaxTargets); bool IsValidSingleTargetEffect(Unit const* target, Targets type) const; bool IsValidSingleTargetSpell(Unit const* target) const; void CalculateDamageDoneForAllTargets(); @@ -584,7 +586,7 @@ namespace Trinity uint32 i_entry; SpellNotifierCreatureAndPlayer(Spell &spell, std::list &data, float radius, const uint32 &type, - SpellTargets TargetType = SPELL_TARGETS_AOE_DAMAGE, uint32 entry = 0) + SpellTargets TargetType = SPELL_TARGETS_ENEMY, uint32 entry = 0) : i_data(&data), i_spell(spell), i_push_type(type), i_radius(radius), i_TargetType(TargetType), i_entry(entry) { i_caster = spell.GetCaster(); @@ -604,11 +606,11 @@ namespace Trinity switch (i_TargetType) { - case SPELL_TARGETS_FRIENDLY: + case SPELL_TARGETS_ALLY: if (!itr->getSource()->isAttackableByAOE() || !i_caster->IsFriendlyTo( itr->getSource() )) continue; break; - case SPELL_TARGETS_AOE_DAMAGE: + case SPELL_TARGETS_ENEMY: { if(itr->getSource()->GetTypeId()==TYPEID_UNIT && ((Creature*)itr->getSource())->isTotem()) continue; From ed6337550e8655e24ed078bbc288f7ac2b448f77 Mon Sep 17 00:00:00 2001 From: megamage Date: Tue, 27 Jan 2009 14:34:42 -0600 Subject: [PATCH 7/7] *Fix target priority of chain heal. --HG-- branch : trunk --- src/game/SharedDefines.h | 3 +- src/game/Spell.cpp | 126 +++++++++++++-------------------------- src/game/Spell.h | 3 +- src/game/SpellMgr.cpp | 1 + 4 files changed, 46 insertions(+), 87 deletions(-) diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h index 7fd985149a..03149d078a 100644 --- a/src/game/SharedDefines.h +++ b/src/game/SharedDefines.h @@ -853,8 +853,7 @@ enum Targets TARGET_DEST_CASTER_BACK_LEFT = 42, //water totem TARGET_DEST_CASTER_BACK_RIGHT = 43, //air totem TARGET_DEST_CASTER_FRONT_RIGHT = 44, //fire totem - TARGET_CHAIN_HEAL = 45, - //TARGET_UNIT_CHAINHEAL + TARGET_UNIT_CHAINHEAL = 45, TARGET_SCRIPT_COORDINATES = 46, //TARGET_DEST_NEARBY_ENTRY TARGET_DEST_CASTER_FRONT = 47, diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index f13c251cc1..bf6959e147 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -1288,6 +1288,7 @@ struct ChainHealingOrder : public std::binary_function -{ - public: - const Unit* MainTarget; - ChainHealingFullHealth(const Unit* Target) : MainTarget(Target) {}; - - bool operator()(const Unit* Target) - { - return (Target != MainTarget && Target->GetHealth() == Target->GetMaxHealth()); - } -}; - // Helper for targets nearest to the spell target // The spell target is always first unless there is a target at _completely_ the same position (unbelievable case) struct TargetDistanceOrder : public std::binary_function @@ -1341,7 +1330,15 @@ void Spell::SearchChainTarget(std::list &TagUnitMap, float max_range, uin max_range += num * CHAIN_SPELL_JUMP_RADIUS; std::list tempUnitMap; - SearchAreaTarget(tempUnitMap, max_range, PUSH_TARGET_CENTER, TargetType); + if(TargetType == SPELL_TARGETS_CHAINHEAL) + { + SearchAreaTarget(tempUnitMap, max_range, PUSH_TARGET_CENTER, SPELL_TARGETS_ALLY); + tempUnitMap.sort(ChainHealingOrder(m_caster)); + if(cur->GetHealth() == cur->GetMaxHealth() && tempUnitMap.size()) + cur = tempUnitMap.front(); + } + else + SearchAreaTarget(tempUnitMap, max_range, PUSH_TARGET_CENTER, TargetType); tempUnitMap.remove(cur); while(num) @@ -1352,19 +1349,34 @@ void Spell::SearchChainTarget(std::list &TagUnitMap, float max_range, uin if(tempUnitMap.empty()) break; - tempUnitMap.sort(TargetDistanceOrder(cur)); - std::list::iterator next = tempUnitMap.begin(); + std::list::iterator next; - if(cur->GetDistance(*next) > CHAIN_SPELL_JUMP_RADIUS) - break; - - while(!cur->IsWithinLOSInMap(*next) - || m_spellInfo->DmgClass==SPELL_DAMAGE_CLASS_MELEE - && !m_caster->isInFront(*next, max_range)) + if(TargetType == SPELL_TARGETS_CHAINHEAL) { - ++next; - if(next == tempUnitMap.end()) - return; + next = tempUnitMap.begin(); + while(cur->GetDistance(*next) > CHAIN_SPELL_JUMP_RADIUS + || !cur->IsWithinLOSInMap(*next)) + { + ++next; + if(next == tempUnitMap.end()) + return; + } + } + else + { + tempUnitMap.sort(TargetDistanceOrder(cur)); + next = tempUnitMap.begin(); + + if(cur->GetDistance(*next) > CHAIN_SPELL_JUMP_RADIUS) + break; + while(!cur->IsWithinLOSInMap(*next) + || m_spellInfo->DmgClass==SPELL_DAMAGE_CLASS_MELEE + && !m_caster->isInFront(*next, max_range)) + { + ++next; + if(next == tempUnitMap.end() || cur->GetDistance(*next) > CHAIN_SPELL_JUMP_RADIUS) + return; + } } cur = *next; @@ -1537,6 +1549,12 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list &TagUnitMap) else if(SelectMagnetTarget()) //TODO: chain target should also use magnet target SearchChainTarget(TagUnitMap, radius, EffectChainTarget, SPELL_TARGETS_ENEMY); break; + case TARGET_UNIT_CHAINHEAL: + if(EffectChainTarget <= 1) + TagUnitMap.push_back(target); + else + SearchChainTarget(TagUnitMap, radius, EffectChainTarget, SPELL_TARGETS_CHAINHEAL); + break; } }break; @@ -1791,66 +1809,6 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list &TagUnitMap) TagUnitMap.push_back(m_caster); break; } - case TARGET_CHAIN_HEAL: - { - Unit* pUnitTarget = m_targets.getUnitTarget(); - if(!pUnitTarget) - break; - - if (EffectChainTarget <= 1) - TagUnitMap.push_back(pUnitTarget); - else - { - unMaxTargets = EffectChainTarget; - float max_range = radius + unMaxTargets * CHAIN_SPELL_JUMP_RADIUS; - - std::list tempUnitMap; - Trinity::SpellNotifierCreatureAndPlayer notifier(*this, tempUnitMap, max_range, PUSH_SELF_CENTER, SPELL_TARGETS_ALLY); - m_caster->VisitNearbyObject(max_range, notifier); - - if(m_caster != pUnitTarget && std::find(tempUnitMap.begin(),tempUnitMap.end(),m_caster) == tempUnitMap.end() ) - tempUnitMap.push_front(m_caster); - - tempUnitMap.sort(TargetDistanceOrder(pUnitTarget)); - - if(tempUnitMap.empty()) - break; - - if(*tempUnitMap.begin() == pUnitTarget) - tempUnitMap.erase(tempUnitMap.begin()); - - TagUnitMap.push_back(pUnitTarget); - uint32 t = unMaxTargets - 1; - Unit *prev = pUnitTarget; - std::list::iterator next = tempUnitMap.begin(); - - while(t && next != tempUnitMap.end() ) - { - if(prev->GetDistance(*next) > CHAIN_SPELL_JUMP_RADIUS) - break; - - if(!prev->IsWithinLOSInMap(*next)) - { - ++next; - continue; - } - - if((*next)->GetHealth() == (*next)->GetMaxHealth()) - { - next = tempUnitMap.erase(next); - continue; - } - - prev = *next; - TagUnitMap.push_back(prev); - tempUnitMap.erase(next); - tempUnitMap.sort(TargetDistanceOrder(prev)); - next = tempUnitMap.begin(); - - --t; - } - } - }break; case TARGET_AREAEFFECT_PARTY_AND_CLASS: { Player* targetPlayer = m_targets.getUnitTarget() && m_targets.getUnitTarget()->GetTypeId() == TYPEID_PLAYER diff --git a/src/game/Spell.h b/src/game/Spell.h index f645dec828..68d18fdeec 100644 --- a/src/game/Spell.h +++ b/src/game/Spell.h @@ -205,7 +205,8 @@ enum SpellTargets { SPELL_TARGETS_ALLY, SPELL_TARGETS_ENEMY, - SPELL_TARGETS_ENTRY + SPELL_TARGETS_ENTRY, + SPELL_TARGETS_CHAINHEAL, }; #define SPELL_SPELL_CHANNEL_UPDATE_INTERVAL 1000 diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index 258ab662d0..0892ddabea 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -107,6 +107,7 @@ SpellMgr::SpellMgr() case TARGET_UNIT_TARGET_ENEMY: case TARGET_UNIT_TARGET_PARTY: case TARGET_UNIT_PARTY_TARGET: + case TARGET_UNIT_CHAINHEAL: SpellTargetType[i] = TARGET_TYPE_UNIT_TARGET; break; case TARGET_UNIT_CHANNEL: