summaryrefslogtreecommitdiff
path: root/src/server
diff options
context:
space:
mode:
Diffstat (limited to 'src/server')
-rw-r--r--src/server/apps/worldserver/Main.cpp4
-rw-r--r--src/server/apps/worldserver/worldserver.conf.dist14
-rw-r--r--src/server/game/AI/SmartScripts/SmartAI.cpp47
-rw-r--r--src/server/game/AI/SmartScripts/SmartAI.h1
-rw-r--r--src/server/game/AI/SmartScripts/SmartScript.cpp8
-rw-r--r--src/server/game/AI/SmartScripts/SmartScript.h2
-rw-r--r--src/server/game/AI/SmartScripts/SmartScriptMgr.h21
-rw-r--r--src/server/game/Entities/Player/Player.cpp2
-rw-r--r--src/server/game/Entities/Player/PlayerUpdates.cpp2
-rw-r--r--src/server/game/Entities/Unit/StatSystem.cpp4
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp9
-rw-r--r--src/server/game/Entities/Unit/Unit.h2
-rw-r--r--src/server/game/Handlers/MovementHandler.cpp2
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp25
-rw-r--r--src/server/game/Spells/SpellInfoCorrections.cpp8
-rw-r--r--src/server/scripts/Northrend/zone_crystalsong_forest.cpp135
-rw-r--r--src/server/scripts/Northrend/zone_howling_fjord.cpp237
-rw-r--r--src/server/scripts/Northrend/zone_storm_peaks.cpp84
-rw-r--r--src/server/scripts/Spells/spell_druid.cpp11
-rw-r--r--src/server/scripts/Spells/spell_generic.cpp24
-rw-r--r--src/server/scripts/Spells/spell_quest.cpp23
-rw-r--r--src/server/shared/Network/AsyncAcceptor.h52
-rw-r--r--src/server/shared/Network/SocketMgr.h4
23 files changed, 425 insertions, 296 deletions
diff --git a/src/server/apps/worldserver/Main.cpp b/src/server/apps/worldserver/Main.cpp
index d1c10131b1..511c17e367 100644
--- a/src/server/apps/worldserver/Main.cpp
+++ b/src/server/apps/worldserver/Main.cpp
@@ -48,6 +48,7 @@
#include "SecretMgr.h"
#include "SharedDefines.h"
#include "SteadyTimer.h"
+#include "Systemd.h"
#include "World.h"
#include "WorldSessionMgr.h"
#include "WorldSocket.h"
@@ -406,7 +407,8 @@ int main(int argc, char** argv)
sScriptMgr->OnShutdown();
// set server offline
- LoginDatabase.DirectExecute("UPDATE realmlist SET flag = flag | {} WHERE id = '{}'", REALM_FLAG_OFFLINE, realm.Id.Realm);
+ if (!sConfigMgr->GetOption<bool>("Network.UseSocketActivation", false))
+ LoginDatabase.DirectExecute("UPDATE realmlist SET flag = flag | {} WHERE id = '{}'", REALM_FLAG_OFFLINE, realm.Id.Realm);
LOG_INFO("server.worldserver", "Halting process...");
diff --git a/src/server/apps/worldserver/worldserver.conf.dist b/src/server/apps/worldserver/worldserver.conf.dist
index 07945f07f3..089c1911a5 100644
--- a/src/server/apps/worldserver/worldserver.conf.dist
+++ b/src/server/apps/worldserver/worldserver.conf.dist
@@ -398,6 +398,20 @@ Network.TcpNodelay = 1
Network.EnableProxyProtocol = 0
#
+# Network.UseSocketActivation
+# Description: Enable systemd socket activation support for the worldserver.
+# When enabled and the process is started by systemd socket activation,
+# the server will use the socket passed by systemd instead of
+# creating and binding its own listening socket. Disabled by default.
+#
+# When enabled the realm is not automatically set as offline on shutdown.
+#
+# Example: 1 - (Enabled)
+# Default: 0 - (Disabled)
+
+Network.UseSocketActivation = 0
+
+#
###################################################################################################
###################################################################################################
diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp
index f888403491..3c952a42d9 100644
--- a/src/server/game/AI/SmartScripts/SmartAI.cpp
+++ b/src/server/game/AI/SmartScripts/SmartAI.cpp
@@ -858,7 +858,7 @@ void SmartAI::AttackStart(Unit* who)
return;
}
- if (who && me->Attack(who, me->IsWithinMeleeRange(who)))
+ if (who && me->Attack(who, me->IsWithinMeleeRange(who) || _currentRangeMode))
{
if (!me->HasUnitState(UNIT_STATE_NO_COMBAT_MOVEMENT))
{
@@ -870,7 +870,7 @@ void SmartAI::AttackStart(Unit* who)
me->GetMotionMaster()->Clear(false);
}
- me->GetMotionMaster()->MoveChase(who);
+ me->GetMotionMaster()->MoveChase(who, _attackDistance);
}
}
}
@@ -941,6 +941,35 @@ void SmartAI::PassengerBoarded(Unit* who, int8 seatId, bool apply)
void SmartAI::InitializeAI()
{
GetScript()->OnInitialize(me);
+
+ for (SmartScriptHolder const& event : GetScript()->GetEvents())
+ {
+ if (event.GetActionType() != SMART_ACTION_CAST)
+ continue;
+
+ if (!(event.action.cast.castFlags & SMARTCAST_MAIN_SPELL))
+ continue;
+
+ SetMainSpell(event.action.cast.spell);
+ break;
+ }
+
+ // Fallback: use first SMARTCAST_COMBAT_MOVE if no MAIN_SPELL found
+ if (!_currentRangeMode)
+ {
+ for (SmartScriptHolder const& event : GetScript()->GetEvents())
+ {
+ if (event.GetActionType() != SMART_ACTION_CAST)
+ continue;
+
+ if (!(event.action.cast.castFlags & SMARTCAST_COMBAT_MOVE))
+ continue;
+
+ SetMainSpell(event.action.cast.spell);
+ break;
+ }
+ }
+
if (!me->isDead())
{
mJustReset = true;
@@ -1083,6 +1112,20 @@ void SmartAI::SetCurrentRangeMode(bool on, float range)
me->GetMotionMaster()->MoveChase(victim, _attackDistance);
}
+void SmartAI::SetMainSpell(uint32 spellId)
+{
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
+ if (!spellInfo)
+ return;
+
+ float maxRange = spellInfo->GetMaxRange(false);
+ if (maxRange <= NOMINAL_MELEE_RANGE)
+ return;
+
+ _attackDistance = std::max(maxRange - NOMINAL_MELEE_RANGE, 0.0f);
+ _currentRangeMode = true;
+}
+
void SmartAI::DistanceYourself(float range)
{
Unit* victim = me->GetVictim();
diff --git a/src/server/game/AI/SmartScripts/SmartAI.h b/src/server/game/AI/SmartScripts/SmartAI.h
index d6b957cc00..0876336458 100644
--- a/src/server/game/AI/SmartScripts/SmartAI.h
+++ b/src/server/game/AI/SmartScripts/SmartAI.h
@@ -67,6 +67,7 @@ public:
void SetAutoAttack(bool on) { mCanAutoAttack = on; }
void SetCombatMovement(bool on, bool stopOrStartMovement);
void SetCurrentRangeMode(bool on, float range = 0.f);
+ void SetMainSpell(uint32 spellId);
void DistanceYourself(float range);
void SetFollow(Unit* target, float dist = 0.0f, float angle = 0.0f, uint32 credit = 0, uint32 end = 0, uint32 creditType = 0, bool aliveState = true);
void StopFollow(bool complete);
diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp
index e7a5c4fd84..2f66b4ac11 100644
--- a/src/server/game/AI/SmartScripts/SmartScript.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScript.cpp
@@ -707,7 +707,6 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
continue;
}
- // Let us not try to cast spell if we know it is going to fail anyway. Stick to chasing and continue.
if (distanceToTarget > spellMaxRange && isWithinLOSInMap)
{
failedSpellCast = true;
@@ -745,12 +744,9 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
if (e.action.cast.castFlags & SMARTCAST_COMBAT_MOVE)
{
- // If cast flag SMARTCAST_COMBAT_MOVE is set combat movement will not be allowed unless target is outside spell range, out of mana, or LOS.
- if (result == SPELL_FAILED_OUT_OF_RANGE || result == SPELL_CAST_OK)
- // if we are just out of range, we only chase until we are back in spell range.
+ if (result == SPELL_FAILED_OUT_OF_RANGE)
CAST_AI(SmartAI, me->AI())->SetCurrentRangeMode(true, std::max(spellMaxRange - NOMINAL_MELEE_RANGE, 0.0f));
- else // move into melee on any other fail
- // if spell fail for any other reason, we chase to melee range, or stay where we are if spellcast was successful.
+ else if (result != SPELL_CAST_OK)
CAST_AI(SmartAI, me->AI())->SetCurrentRangeMode(false, 0.f);
}
diff --git a/src/server/game/AI/SmartScripts/SmartScript.h b/src/server/game/AI/SmartScripts/SmartScript.h
index e0f32438c8..250fdd775a 100644
--- a/src/server/game/AI/SmartScripts/SmartScript.h
+++ b/src/server/game/AI/SmartScripts/SmartScript.h
@@ -207,6 +207,8 @@ public:
void AddCreatureSummon(ObjectGuid const& guid);
void RemoveCreatureSummon(ObjectGuid const& guid);
+ SmartAIEventList const& GetEvents() const { return mEvents; }
+
private:
void IncPhase(uint32 p);
void DecPhase(uint32 p);
diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h
index 5e8e5e9e0c..8dd177dfa6 100644
--- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h
+++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h
@@ -1932,16 +1932,17 @@ enum SmartEventFlags
enum SmartCastFlags
{
- SMARTCAST_INTERRUPT_PREVIOUS = 0x001, // Interrupt any spell casting
- SMARTCAST_TRIGGERED = 0x002, // Triggered (this makes spell cost zero mana and have no cast time)
- //CAST_FORCE_CAST = 0x004, // Forces cast even if creature is out of mana or out of range
- //CAST_NO_MELEE_IF_OOM = 0x008, // Prevents creature from entering melee if out of mana or out of range
- //CAST_FORCE_TARGET_SELF = 0x010, // Forces the target to cast this spell on itself
- SMARTCAST_AURA_NOT_PRESENT = 0x020, // Only casts the spell if the target does not have an aura from the spell
- SMARTCAST_COMBAT_MOVE = 0x040, // Prevents combat movement if cast successful. Allows movement on range, OOM, LOS
- SMARTCAST_THREATLIST_NOT_SINGLE = 0x080, // Only cast if the source's threatlist is higher than one. This includes pets (see Skeram's True Fulfillment)
- SMARTCAST_TARGET_POWER_MANA = 0x100, // Only cast if the target has power type mana (e.g. Mana Drain)
- SMARTCAST_ENABLE_COMBAT_MOVE_ON_LOS = 0x200,
+ SMARTCAST_INTERRUPT_PREVIOUS = 0x001, // Interrupt any spell casting
+ SMARTCAST_TRIGGERED = 0x002, // Triggered (this makes spell cost zero mana and have no cast time)
+ //CAST_FORCE_CAST = 0x004, // Forces cast even if creature is out of mana or out of range
+ //CAST_NO_MELEE_IF_OOM = 0x008, // Prevents creature from entering melee if out of mana or out of range
+ //CAST_FORCE_TARGET_SELF = 0x010, // Forces the target to cast this spell on itself
+ SMARTCAST_AURA_NOT_PRESENT = 0x020, // Only casts the spell if the target does not have an aura from the spell
+ SMARTCAST_COMBAT_MOVE = 0x040, // Prevents combat movement if cast successful. Allows movement on range, OOM, LOS
+ SMARTCAST_THREATLIST_NOT_SINGLE = 0x080, // Only cast if the source's threatlist is higher than one. This includes pets (see Skeram's True Fulfillment)
+ SMARTCAST_TARGET_POWER_MANA = 0x100, // Only cast if the target has power type mana (e.g. Mana Drain)
+ SMARTCAST_ENABLE_COMBAT_MOVE_ON_LOS = 0x200, // Allows combat movement when not in line of sight
+ SMARTCAST_MAIN_SPELL = 0x400, // Sets this spell's max range as the creature's chase distance on spawn
};
enum SmartFollowType
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 8891c8788e..5bcd49fcf3 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -7647,7 +7647,7 @@ void Player::_ApplyAllItemMods()
if (!proto)
continue;
- ApplyItemDependentAuras(m_items[i], false);
+ ApplyItemDependentAuras(m_items[i], true);
_ApplyItemBonuses(proto, i, true);
WeaponAttackType const attackType = Player::GetAttackBySlot(i);
diff --git a/src/server/game/Entities/Player/PlayerUpdates.cpp b/src/server/game/Entities/Player/PlayerUpdates.cpp
index 1d3b5788b3..9a4427ce49 100644
--- a/src/server/game/Entities/Player/PlayerUpdates.cpp
+++ b/src/server/game/Entities/Player/PlayerUpdates.cpp
@@ -701,7 +701,7 @@ void Player::UpdateRating(CombatRating cr)
void Player::UpdateAllRatings()
{
- for (uint cr = 0; cr < MAX_COMBAT_RATING; ++cr)
+ for (uint8 cr = 0; cr < MAX_COMBAT_RATING; ++cr)
UpdateRating(CombatRating(cr));
}
diff --git a/src/server/game/Entities/Unit/StatSystem.cpp b/src/server/game/Entities/Unit/StatSystem.cpp
index 4e2fd4532a..24c025ac6d 100644
--- a/src/server/game/Entities/Unit/StatSystem.cpp
+++ b/src/server/game/Entities/Unit/StatSystem.cpp
@@ -157,7 +157,7 @@ bool Player::UpdateStats(Stats stat)
mask |= (*i)->GetMiscValue();
if (mask)
{
- for (uint32 rating = 0; rating < MAX_COMBAT_RATING; ++rating)
+ for (uint8 rating = 0; rating < MAX_COMBAT_RATING; ++rating)
if (mask & (1 << rating))
ApplyRatingMod(CombatRating(rating), 0, true);
}
@@ -272,7 +272,7 @@ void Player::UpdateArmor()
float value = GetFlatModifierValue(unitMod, BASE_VALUE); // base armor (from items)
value *= GetPctModifierValue(unitMod, BASE_PCT); // armor percent from items
- value += GetStat(STAT_AGILITY) * 2.0f; // armor bonus from stats
+ value += GetStat(STAT_AGILITY) * 2.0f; // armor bonus from stats
value += GetFlatModifierValue(unitMod, TOTAL_VALUE);
//add dynamic flat mods
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 817bc25b77..623886eb78 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -628,7 +628,7 @@ void Unit::UpdateSplinePosition()
//if (HasUnitState(UNIT_STATE_CANNOT_TURN))
// loc.orientation = GetOrientation();
- if (IsPlayer())
+ if (IsPlayer() || IsPet())
UpdatePosition(loc.x, loc.y, loc.z, loc.orientation);
else
ToCreature()->SetPosition(loc.x, loc.y, loc.z, loc.orientation);
@@ -13465,7 +13465,12 @@ uint32 Unit::MeleeDamageBonusTaken(Unit* attacker, uint32 pdamage, WeaponAttackT
if (mechanicMask)
{
- TakenTotalMod *= GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT, mechanicMask);
+ TakenTotalMod *= GetTotalAuraMultiplier(SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT, [mechanicMask](AuraEffect const* aurEff) -> bool
+ {
+ if (mechanicMask & uint32(1 << (aurEff->GetMiscValue())))
+ return true;
+ return false;
+ });
}
}
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index 8370ebae57..934bb1c70c 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -219,7 +219,7 @@ enum WeaponAttackType : uint8
MAX_ATTACK
};
-enum CombatRating
+enum CombatRating : uint8
{
CR_WEAPON_SKILL = 0,
CR_DEFENSE_SKILL = 1,
diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp
index a878194589..fb40ce36ac 100644
--- a/src/server/game/Handlers/MovementHandler.cpp
+++ b/src/server/game/Handlers/MovementHandler.cpp
@@ -299,6 +299,8 @@ void WorldSession::HandleMoveTeleportAck(WorldPacket& recvData)
plMover->UpdatePosition(dest, true);
+ plMover->SetFallInformation(GameTime::GetGameTime().count(), dest.GetPositionZ());
+
// xinef: teleport pets if they are not unsummoned
if (Pet* pet = plMover->GetPet())
{
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index dcef617a65..7ffb4065f8 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -726,9 +726,12 @@ void AuraEffect::ChangeAmount(int32 newAmount, bool mark, bool onStackOrReapply)
std::list<AuraApplication*> effectApplications;
GetApplicationList(effectApplications);
- for (std::list<AuraApplication*>::const_iterator apptItr = effectApplications.begin(); apptItr != effectApplications.end(); ++apptItr)
- if ((*apptItr)->HasEffect(GetEffIndex()))
- HandleEffect(*apptItr, handleMask, false);
+ for (AuraApplication* aurApp : effectApplications)
+ if (aurApp->HasEffect(GetEffIndex()))
+ {
+ aurApp->GetTarget()->_RegisterAuraEffect(this, false);
+ HandleEffect(aurApp, handleMask, false);
+ }
if (handleMask & AURA_EFFECT_HANDLE_CHANGE_AMOUNT)
{
@@ -739,9 +742,15 @@ void AuraEffect::ChangeAmount(int32 newAmount, bool mark, bool onStackOrReapply)
CalculateSpellMod();
}
- for (std::list<AuraApplication*>::const_iterator apptItr = effectApplications.begin(); apptItr != effectApplications.end(); ++apptItr)
- if ((*apptItr)->HasEffect(GetEffIndex()))
- HandleEffect(*apptItr, handleMask, true);
+ for (AuraApplication* aurApp : effectApplications)
+ if (aurApp->HasEffect(GetEffIndex()))
+ {
+ if (aurApp->GetRemoveMode() != AURA_REMOVE_NONE)
+ continue;
+
+ aurApp->GetTarget()->_RegisterAuraEffect(this, true);
+ HandleEffect(aurApp, handleMask, true);
+ }
}
void AuraEffect::HandleEffect(AuraApplication* aurApp, uint8 mode, bool apply)
@@ -5105,7 +5114,7 @@ void AuraEffect::HandleModRating(AuraApplication const* aurApp, uint8 mode, bool
if (!target->IsPlayer())
return;
- for (uint32 rating = 0; rating < MAX_COMBAT_RATING; ++rating)
+ for (uint8 rating = 0; rating < MAX_COMBAT_RATING; ++rating)
if (GetMiscValue() & (1 << rating))
target->ToPlayer()->ApplyRatingMod(CombatRating(rating), GetAmount(), apply);
}
@@ -5121,7 +5130,7 @@ void AuraEffect::HandleModRatingFromStat(AuraApplication const* aurApp, uint8 mo
return;
// Just recalculate ratings
- for (uint32 rating = 0; rating < MAX_COMBAT_RATING; ++rating)
+ for (uint8 rating = 0; rating < MAX_COMBAT_RATING; ++rating)
if (GetMiscValue() & (1 << rating))
target->ToPlayer()->ApplyRatingMod(CombatRating(rating), 0, apply);
}
diff --git a/src/server/game/Spells/SpellInfoCorrections.cpp b/src/server/game/Spells/SpellInfoCorrections.cpp
index ca45356219..0615f39c00 100644
--- a/src/server/game/Spells/SpellInfoCorrections.cpp
+++ b/src/server/game/Spells/SpellInfoCorrections.cpp
@@ -5162,6 +5162,14 @@ void SpellMgr::LoadSpellInfoCorrections()
spellInfo->ProcCharges = 1;
});
+ ApplySpellFix({
+ 56917, // To Icecrown Airship - Teleport to Airship (A)
+ 57417, // To Icecrown Airship - Teleport to Airship (H)
+ }, [](SpellInfo* spellInfo)
+ {
+ spellInfo->RangeEntry = sSpellRangeStore.LookupEntry(6); // 100 yards
+ });
+
for (uint32 i = 0; i < GetSpellInfoStoreSize(); ++i)
{
SpellInfo* spellInfo = mSpellInfoMap[i];
diff --git a/src/server/scripts/Northrend/zone_crystalsong_forest.cpp b/src/server/scripts/Northrend/zone_crystalsong_forest.cpp
index bdf394cad9..645d3c0224 100644
--- a/src/server/scripts/Northrend/zone_crystalsong_forest.cpp
+++ b/src/server/scripts/Northrend/zone_crystalsong_forest.cpp
@@ -15,52 +15,100 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include "CombatAI.h"
#include "CreatureScript.h"
-#include "PassiveAI.h"
#include "Player.h"
#include "ScriptedCreature.h"
-#include "SmartScriptMgr.h"
+#include "SpellAuras.h"
+#include "SpellScript.h"
#include "Transport.h"
#include "Vehicle.h"
enum ePreparationsForWar
{
- NPC_HAMMERHEAD = 30585,
- NPC_CLOUDBUSTER = 30470,
- TRANSPORT_ORGRIMS_HAMMER = 192241,
- TRANSPORT_THE_SKYBREAKER = 192242
+ NPC_CLOUDBUSTER = 30470,
+ NPC_HAMMERHEAD = 30585,
+ TRANSPORT_ORGRIMS_HAMMER = 192241,
+ TRANSPORT_THE_SKYBREAKER = 192242,
+ SEAT_PLAYER = 0,
+ SPELL_FLIGHT = 48602,
+ SPELL_TO_ICECROWN_PLAYER_AURA_DISMOUNT_A = 56904,
+ SPELL_TO_ICECROWN_PLAYER_AURA_DISMOUNT_H = 57419,
+ SPELL_TO_ICECROWN_AIRSHIP_PLAYER_AURA_TELEPORT_TO_DALARAN = 57460,
+ SPELL_TO_ICECROWN_AIRSHIP_FROST_WYRM_WAITING_TO_SUMMON_AURA = 57498,
+ POINT_END = 16,
+ SPELL_TO_ICECROWN_AIRSHIP_AURA_DISMOUNT_RESPONSE = 56921, // unhandled - vehicle casts 50630 on self
+ SPELL_EJECT_ALL_PASSENGERS = 50630,
+ SPELL_TO_ICECROWN_AIRSHIP_TELEPORT_TO_AIRSHIP_A_FORCE_PLAYER_TO_CAST = 57554,
+ SPELL_TO_ICECROWN_AIRSHIP_TELEPORT_TO_AIRSHIP_H_FORCE_PLAYER_TO_CAST = 57556,
+ SPELL_TO_ICECROWN_AIRSHIP_TELEPORT_TO_AIRSHIP_A = 56917,
+ SPELL_TO_ICECROWN_AIRSHIP_TELEPORT_TO_AIRSHIP_H = 57417,
};
-struct npc_preparations_for_war_vehicle : public NullCreatureAI
+struct npc_preparations_for_war_vehicle : public VehicleAI
{
- npc_preparations_for_war_vehicle(Creature* creature) : NullCreatureAI(creature) { }
-
- uint8 pointId;
- uint32 searchForShipTimer;
- uint32 transportEntry;
+ explicit npc_preparations_for_war_vehicle(Creature* creature) : VehicleAI(creature), searchForShipTimer(0), transportEntry(me->GetEntry() == NPC_CLOUDBUSTER ? TRANSPORT_THE_SKYBREAKER : TRANSPORT_ORGRIMS_HAMMER)
+ {
+ if (transportEntry == TRANSPORT_THE_SKYBREAKER)
+ {
+ // 30476 - [DND] Icecrown Flight To Airship Bunny (A)
+ passenger_x = 31.41805;
+ passenger_y = 0.126893;
+ passenger_z = 41.69821;
+ }
+ else // TRANSPORT_ORGRIMS_HAMMER
+ {
+ // 30588 - [DND] Icecrown Flight To Airship Bunny (H)
+ passenger_x = -18.10283;
+ passenger_y = -0.042108;
+ passenger_z = 45.31725;
+ }
+ }
- void InitializeAI() override
+ void PassengerBoarded(Unit* who, int8 /*seatId*/, bool apply) override
{
- me->GetMotionMaster()->MovePath(me->GetEntry(), FORCED_MOVEMENT_NONE, PathSource::SMART_WAYPOINT_MGR);
+ if (apply)
+ {
+ DoCastSelf(SPELL_TO_ICECROWN_AIRSHIP_PLAYER_AURA_TELEPORT_TO_DALARAN, true);
+ DoCastSelf(SPELL_FLIGHT, true);
+ DoCastSelf(me->GetEntry() == NPC_CLOUDBUSTER ? SPELL_TO_ICECROWN_PLAYER_AURA_DISMOUNT_A : SPELL_TO_ICECROWN_PLAYER_AURA_DISMOUNT_H , true);
+ DoCastSelf(SPELL_TO_ICECROWN_AIRSHIP_FROST_WYRM_WAITING_TO_SUMMON_AURA, true);
+ me->GetMotionMaster()->MovePath(me->GetEntry(), FORCED_MOVEMENT_NONE, PathSource::SMART_WAYPOINT_MGR);
+ }
+ else
+ who->RemoveAurasDueToSpell(VEHICLE_SPELL_PARACHUTE); // maybe vehicle / seat flag should be responsible for parachute gain?
+ }
- NullCreatureAI::InitializeAI();
- pointId = 0;
- searchForShipTimer = 0;
- transportEntry = (me->GetEntry() == NPC_HAMMERHEAD ? TRANSPORT_ORGRIMS_HAMMER : TRANSPORT_THE_SKYBREAKER);
+ void MovementInform(uint32 type, uint32 id) override
+ {
+ if (type == ESCORT_MOTION_TYPE && id == POINT_END)
+ searchForShipTimer = 3000;
}
- void MovementInform(uint32 type, uint32 /*id*/) override
+ void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override
{
- if (type == ESCORT_MOTION_TYPE)
- if (++pointId == 17) // path size
- searchForShipTimer = 3000;
+ switch (spell->Id)
+ {
+ case SPELL_TO_ICECROWN_AIRSHIP_AURA_DISMOUNT_RESPONSE:
+ break;
+ case SPELL_TO_ICECROWN_AIRSHIP_TELEPORT_TO_AIRSHIP_A_FORCE_PLAYER_TO_CAST:
+ case SPELL_TO_ICECROWN_AIRSHIP_TELEPORT_TO_AIRSHIP_H_FORCE_PLAYER_TO_CAST:
+ {
+ uint32 teleportSpell = (spell->Id == SPELL_TO_ICECROWN_AIRSHIP_TELEPORT_TO_AIRSHIP_A_FORCE_PLAYER_TO_CAST)
+ ? SPELL_TO_ICECROWN_AIRSHIP_TELEPORT_TO_AIRSHIP_A
+ : SPELL_TO_ICECROWN_AIRSHIP_TELEPORT_TO_AIRSHIP_H;
+ DoCastSelf(teleportSpell, true); // hack: cast on self to avoid visual glitch on player when ejecting and teleporting on transport
+ DoCastSelf(SPELL_EJECT_ALL_PASSENGERS, true);
+ me->DespawnOrUnsummon(0s);
+ break;
+ }
+ default:
+ break;
+ }
}
void UpdateAI(uint32 diff) override
{
- // horde 7.55f, -0.09, 34.44, 3.13, +20
- // ally 45.18f, 0.03, 40.09, 3.14 +5
-
if (searchForShipTimer)
{
searchForShipTimer += diff;
@@ -68,37 +116,14 @@ struct npc_preparations_for_war_vehicle : public NullCreatureAI
{
searchForShipTimer = 1;
TransportsContainer const& transports = me->GetMap()->GetAllTransports();
- for (TransportsContainer::const_iterator itr = transports.begin(); itr != transports.end(); ++itr)
+ for (auto const transport : transports)
{
- if ((*itr)->GetEntry() == transportEntry)
+ if (transport->GetEntry() == transportEntry)
{
- float x, y, z;
- if (transportEntry == TRANSPORT_ORGRIMS_HAMMER)
- {
- x = 7.55f;
- y = -0.09f;
- z = 54.44f;
- }
- else
- {
- x = 45.18f;
- y = 0.03f;
- z = 45.09f;
- }
+ float x = passenger_x, y = passenger_y, z = passenger_z;
+ transport->CalculatePassengerPosition(x, y, z);
- (*itr)->CalculatePassengerPosition(x, y, z);
-
- if (me->GetDistance2d(x, y) < 10.0f)
- {
- me->DespawnOrUnsummon(1s);
- if (Vehicle* vehicle = me->GetVehicleKit())
- if (Unit* passenger = vehicle->GetPassenger(0))
- {
- passenger->NearTeleportTo(x, y, z - (transportEntry == TRANSPORT_ORGRIMS_HAMMER ? 19.0f : 4.0f), M_PI);
- passenger->RemoveAurasDueToSpell(VEHICLE_SPELL_PARACHUTE); // maybe vehicle / seat flag should be responsible for parachute gain?
- }
- }
- else
+ if (me->GetDistance2d(x, y) > 20.0f) // dismount trigger (56905, 57420) range is 30
me->GetMotionMaster()->MovePoint(0, x, y, z, FORCED_MOVEMENT_NONE, 0.f, 0.f, false, false);
break;
}
@@ -106,6 +131,10 @@ struct npc_preparations_for_war_vehicle : public NullCreatureAI
}
}
}
+private:
+ float passenger_x, passenger_y, passenger_z;
+ uint32 searchForShipTimer;
+ uint32 transportEntry;
};
/*******************************************************
diff --git a/src/server/scripts/Northrend/zone_howling_fjord.cpp b/src/server/scripts/Northrend/zone_howling_fjord.cpp
index fc28598ec2..928a0a71e8 100644
--- a/src/server/scripts/Northrend/zone_howling_fjord.cpp
+++ b/src/server/scripts/Northrend/zone_howling_fjord.cpp
@@ -66,109 +66,6 @@ public:
}
};
-// The cleansing
-enum TurmoilTexts
-{
- SAY_TURMOIL_0 = 0,
- SAY_TURMOIL_1 = 1,
- SAY_TURMOIL_HALF_HP = 2,
- SAY_TURMOIL_DEATH = 3,
-};
-
-class npc_your_inner_turmoil : public CreatureScript
-{
-public:
- npc_your_inner_turmoil() : CreatureScript("npc_your_inner_turmoil") { }
-
- struct npc_your_inner_turmoilAI : public ScriptedAI
- {
- npc_your_inner_turmoilAI(Creature* creature) : ScriptedAI(creature) {}
-
- uint32 timer;
- short phase;
- bool health50;
-
- void Reset() override
- {
- timer = 0;
- phase = 0;
- health50 = false;
- }
-
- void UpdateAI(uint32 diff) override
- {
- if (timer >= 6000 && phase < 2)
- {
- phase++;
- setphase(phase);
- timer = 0;
- }
-
- timer += diff;
-
- DoMeleeAttackIfReady();
- }
-
- void DamageTaken(Unit*, uint32& /*damage*/, DamageEffectType /*damagetype*/, SpellSchoolMask /*damageSchoolMask*/) override
- {
- if (HealthBelowPct(50) && !health50)
- {
- if (TempSummon const* tempSummon = me->ToTempSummon())
- {
- if (WorldObject* summoner = tempSummon->GetSummonerUnit())
- {
- Talk(SAY_TURMOIL_HALF_HP, summoner);
- }
- }
-
- health50 = true;
- }
- }
-
- void JustDied(Unit* /*killer*/) override
- {
- if (TempSummon const* tempSummon = me->ToTempSummon())
- {
- if (WorldObject* summoner = tempSummon->GetSummonerUnit())
- {
- Talk(SAY_TURMOIL_DEATH, summoner);
- }
- }
- }
-
- void setphase(short newPhase)
- {
- Unit* summoner = me->ToTempSummon() ? me->ToTempSummon()->GetSummonerUnit() : nullptr;
- if (!summoner || !summoner->IsPlayer())
- return;
-
- switch (newPhase)
- {
- case 1:
- Talk(SAY_TURMOIL_0, summoner->ToPlayer());
- return;
- case 2:
- {
- Talk(SAY_TURMOIL_1, summoner->ToPlayer());
- me->SetLevel(summoner->GetLevel());
- me->SetFaction(FACTION_MONSTER);
- if (me->GetExactDist(summoner) < 50.0f)
- {
- me->UpdatePosition(summoner->GetPositionX(), summoner->GetPositionY(), summoner->GetPositionZ(), 0.0f, true);
- summoner->CastSpell(me, 50218, true); // clone caster
- AttackStart(summoner);
- }
- }
- }
- }
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return new npc_your_inner_turmoilAI(creature);
- }
-};
-
/*######
## npc_apothecary_hanes
######*/
@@ -457,13 +354,145 @@ class spell_hawk_hunting : public SpellScript
}
};
+/*######
+## Quest 11317, 11322: The Cleansing
+######*/
+
+enum TheCleansing
+{
+ SPELL_CLEANSING_SOUL = 43351,
+ SPELL_SUMMON_INNER_TURMOIL = 50167,
+ SPELL_RECENT_MEDITATION = 61720,
+ SPELL_MIRROR_IMAGE_AURA = 50218,
+
+ QUEST_THE_CLEANSING_H = 11317,
+ QUEST_THE_CLEANSING_A = 11322
+};
+
+// 43365 - The Cleansing: Shrine Cast
+class spell_the_cleansing_shrine_cast : public SpellScript
+{
+ PrepareSpellScript(spell_the_cleansing_shrine_cast);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_RECENT_MEDITATION, SPELL_CLEANSING_SOUL }) &&
+ sObjectMgr->GetQuestTemplate(QUEST_THE_CLEANSING_H) &&
+ sObjectMgr->GetQuestTemplate(QUEST_THE_CLEANSING_A);
+ }
+
+ SpellCastResult CheckCast()
+ {
+ // Error is correct for quest check but may be not correct for aura and this may be a wrong place to send error
+ if (Player* target = GetExplTargetUnit()->ToPlayer())
+ {
+ if (target->HasAura(SPELL_RECENT_MEDITATION) || (!(target->GetQuestStatus(QUEST_THE_CLEANSING_H) == QUEST_STATUS_INCOMPLETE ||
+ target->GetQuestStatus(QUEST_THE_CLEANSING_A) == QUEST_STATUS_INCOMPLETE)))
+ {
+ Spell::SendCastResult(target, GetSpellInfo(), 0, SPELL_FAILED_FIZZLE);
+ return SPELL_FAILED_FIZZLE;
+ }
+ }
+ return SPELL_CAST_OK;
+ }
+
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ GetHitUnit()->CastSpell(GetHitUnit(), SPELL_CLEANSING_SOUL, true);
+ }
+
+ void Register() override
+ {
+ OnCheckCast += SpellCheckCastFn(spell_the_cleansing_shrine_cast::CheckCast);
+ OnEffectHitTarget += SpellEffectFn(spell_the_cleansing_shrine_cast::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+};
+
+// 43351 - Cleansing Soul
+class spell_the_cleansing_cleansing_soul : public AuraScript
+{
+ PrepareAuraScript(spell_the_cleansing_cleansing_soul);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_SUMMON_INNER_TURMOIL, SPELL_RECENT_MEDITATION });
+ }
+
+ void AfterApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ GetTarget()->SetStandState(UNIT_STAND_STATE_SIT);
+ }
+
+ void AfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ Unit* target = GetTarget();
+ target->SetStandState(UNIT_STAND_STATE_STAND);
+ target->CastSpell(target, SPELL_SUMMON_INNER_TURMOIL, true);
+ target->CastSpell(target, SPELL_RECENT_MEDITATION, true);
+ }
+
+ void Register() override
+ {
+ AfterEffectApply += AuraEffectApplyFn(spell_the_cleansing_cleansing_soul::AfterApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
+ AfterEffectRemove += AuraEffectRemoveFn(spell_the_cleansing_cleansing_soul::AfterRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
+ }
+};
+
+// 50217 - The Cleansing: Script Effect Player Cast Mirror Image
+class spell_the_cleansing_mirror_image_script_effect : public SpellScript
+{
+ PrepareSpellScript(spell_the_cleansing_mirror_image_script_effect);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_MIRROR_IMAGE_AURA });
+ }
+
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ GetHitUnit()->CastSpell(GetHitUnit(), SPELL_MIRROR_IMAGE_AURA, true);
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_the_cleansing_mirror_image_script_effect::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+};
+
+// 50238 - The Cleansing: Your Inner Turmoil's On Death Cast on Master
+class spell_the_cleansing_on_death_cast_on_master : public SpellScript
+{
+ PrepareSpellScript(spell_the_cleansing_on_death_cast_on_master);
+
+ bool Validate(SpellInfo const* spellInfo) override
+ {
+ return ValidateSpellInfo({ uint32(spellInfo->GetEffect(EFFECT_0).CalcValue()) });
+ }
+
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ if (Unit* caster = GetCaster())
+ if (TempSummon* casterSummon = caster->ToTempSummon())
+ if (Unit* summoner = casterSummon->GetSummonerUnit())
+ summoner->CastSpell(summoner, GetSpellInfo()->Effects[EFFECT_0].CalcValue(), true);
+ }
+
+ void Register() override
+ {
+ OnEffectHit += SpellEffectFn(spell_the_cleansing_on_death_cast_on_master::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+};
+
void AddSC_howling_fjord()
{
new npc_attracted_reef_bull();
- new npc_your_inner_turmoil();
new npc_apothecary_hanes();
new npc_plaguehound_tracker();
new npc_razael_and_lyana();
RegisterCreatureAI(npc_rodin_lightning_enabler);
RegisterSpellScript(spell_hawk_hunting);
+ RegisterSpellScript(spell_the_cleansing_shrine_cast);
+ RegisterSpellScript(spell_the_cleansing_cleansing_soul);
+ RegisterSpellScript(spell_the_cleansing_mirror_image_script_effect);
+ RegisterSpellScript(spell_the_cleansing_on_death_cast_on_master);
}
diff --git a/src/server/scripts/Northrend/zone_storm_peaks.cpp b/src/server/scripts/Northrend/zone_storm_peaks.cpp
index 5c208f1187..836469a3e8 100644
--- a/src/server/scripts/Northrend/zone_storm_peaks.cpp
+++ b/src/server/scripts/Northrend/zone_storm_peaks.cpp
@@ -915,72 +915,40 @@ public:
}
};
-class npc_hyldsmeet_protodrake : public CreatureScript
+enum HyldsmeetProtoDrake
{
- enum NPCs
- {
- NPC_HYLDSMEET_DRAKERIDER = 29694
- };
+ NPC_HYLDSMEET_DRAKERIDER = 29694
+};
-public:
- npc_hyldsmeet_protodrake() : CreatureScript("npc_hyldsmeet_protodrake") { }
+struct npc_hyldsmeet_protodrake : public CreatureAI
+{
+ explicit npc_hyldsmeet_protodrake(Creature* creature) : CreatureAI(creature), _accessoryRespawnTimer(0) { }
- class npc_hyldsmeet_protodrakeAI : public CreatureAI
+ void PassengerBoarded(Unit* who, int8 /*seat*/, bool apply) override
{
- public:
- npc_hyldsmeet_protodrakeAI(Creature* creature) : CreatureAI(creature), _accessoryRespawnTimer(0), _vehicleKit(creature->GetVehicleKit()) { }
-
- void PassengerBoarded(Unit* who, int8 /*seat*/, bool apply) override
- {
- if (apply)
- {
- class DelayedTransportPositionOffsets : public BasicEvent
- {
- public:
- DelayedTransportPositionOffsets(Unit* owner) : _owner(owner) { }
-
- bool Execute(uint64 /*eventTime*/, uint32 /*updateTime*/) override
- {
- _owner->m_movementInfo.transport.pos.Relocate(-3.5f, 0.f, -0.2f, 0.f);
- return true;
- }
-
- private:
- Unit* _owner;
- };
-
- if (who->IsPlayer())
- who->m_Events.AddEventAtOffset(new DelayedTransportPositionOffsets(who), 500ms);
-
- return;
- }
+ if (apply)
+ return;
- if (who->GetEntry() == NPC_HYLDSMEET_DRAKERIDER)
- _accessoryRespawnTimer = 5 * MINUTE * IN_MILLISECONDS;
- }
+ if (who->GetEntry() == NPC_HYLDSMEET_DRAKERIDER)
+ _accessoryRespawnTimer = 5 * MINUTE * IN_MILLISECONDS;
+ }
- void UpdateAI(uint32 diff) override
+ void UpdateAI(uint32 diff) override
+ {
+ //! We need to manually reinstall accessories because the vehicle itself is friendly to players,
+ //! so EnterEvadeMode is never triggered. The accessory on the other hand is hostile and killable.
+ Vehicle* vehicleKit = me->GetVehicleKit();
+ if (_accessoryRespawnTimer && _accessoryRespawnTimer <= diff && vehicleKit)
{
- //! We need to manually reinstall accessories because the vehicle itself is friendly to players,
- //! so EnterEvadeMode is never triggered. The accessory on the other hand is hostile and killable.
- if (_accessoryRespawnTimer && _accessoryRespawnTimer <= diff && _vehicleKit)
- {
- _vehicleKit->InstallAllAccessories(true);
- _accessoryRespawnTimer = 0;
- }
- else
- _accessoryRespawnTimer -= diff;
+ vehicleKit->InstallAllAccessories(true);
+ _accessoryRespawnTimer = 0;
}
-
- private:
- uint32 _accessoryRespawnTimer;
- Vehicle* _vehicleKit;
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return new npc_hyldsmeet_protodrakeAI(creature);
+ else
+ _accessoryRespawnTimer -= diff;
}
+
+private:
+ uint32 _accessoryRespawnTimer;
};
enum CloseRift
@@ -1215,7 +1183,7 @@ void AddSC_storm_peaks()
new npc_brunnhildar_prisoner();
new npc_freed_protodrake();
new npc_icefang();
- new npc_hyldsmeet_protodrake();
+ RegisterCreatureAI(npc_hyldsmeet_protodrake);
RegisterSpellScript(spell_close_rift_aura);
new npc_vehicle_d16_propelled_delivery();
RegisterSpellScript(spell_q12823_remove_collapsing_cave_aura);
diff --git a/src/server/scripts/Spells/spell_druid.cpp b/src/server/scripts/Spells/spell_druid.cpp
index c6f90e153e..85a12610da 100644
--- a/src/server/scripts/Spells/spell_druid.cpp
+++ b/src/server/scripts/Spells/spell_druid.cpp
@@ -443,15 +443,16 @@ class spell_dru_enrage : public AuraScript
void RecalculateBaseArmor()
{
+ // Recalculate modifies the list while we're iterating through it, so let's copy it instead
Unit::AuraEffectList const& auras = GetTarget()->GetAuraEffectsByType(SPELL_AURA_MOD_BASE_RESISTANCE_PCT);
- for (Unit::AuraEffectList::const_iterator i = auras.begin(); i != auras.end(); ++i)
+ std::vector<AuraEffect*> aurEffs(auras.begin(), auras.end());
+
+ for (AuraEffect* aurEff : aurEffs)
{
- SpellInfo const* spellInfo = (*i)->GetSpellInfo();
+ SpellInfo const* spellInfo = aurEff->GetSpellInfo();
// Dire- / Bear Form (Passive)
if (spellInfo->SpellFamilyName == SPELLFAMILY_DRUID && spellInfo->SpellFamilyFlags.HasFlag(0x0, 0x0, 0x2))
- {
- (*i)->RecalculateAmount();
- }
+ aurEff->RecalculateAmount();
}
}
diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp
index f36f2d2234..38f669693f 100644
--- a/src/server/scripts/Spells/spell_generic.cpp
+++ b/src/server/scripts/Spells/spell_generic.cpp
@@ -5673,6 +5673,29 @@ class spell_gen_bm_on : public SpellScript
}
};
+class spell_gen_whisper_to_controller : public SpellScript
+{
+ PrepareSpellScript(spell_gen_whisper_to_controller);
+
+ bool Validate(SpellInfo const* spellInfo) override
+ {
+ return sObjectMgr->GetBroadcastText(uint32(spellInfo->GetEffect(EFFECT_0).CalcValue()));
+ }
+
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ if (Unit* caster = GetCaster())
+ if (TempSummon* casterSummon = caster->ToTempSummon())
+ if (Player* target = casterSummon->GetSummonerUnit()->ToPlayer())
+ casterSummon->Unit::Whisper(uint32(GetEffectValue()), target, false);
+ }
+
+ void Register() override
+ {
+ OnEffectHit += SpellEffectFn(spell_gen_whisper_to_controller::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+};
+
void AddSC_generic_spell_scripts()
{
RegisterSpellScript(spell_silithyst);
@@ -5846,4 +5869,5 @@ void AddSC_generic_spell_scripts()
RegisterSpellScript(spell_gen_invis_on);
RegisterSpellScript(spell_gen_bm_on);
RegisterSpellScript(spell_gen_bm_off);
+ RegisterSpellScript(spell_gen_whisper_to_controller);
}
diff --git a/src/server/scripts/Spells/spell_quest.cpp b/src/server/scripts/Spells/spell_quest.cpp
index 870cc73850..4e1b563333 100644
--- a/src/server/scripts/Spells/spell_quest.cpp
+++ b/src/server/scripts/Spells/spell_quest.cpp
@@ -247,28 +247,6 @@ class spell_q10525_vision_guide : public AuraScript
}
};
-class spell_q11322_q11317_the_cleansing : public AuraScript
-{
- PrepareAuraScript(spell_q11322_q11317_the_cleansing)
-
- void HandleEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
- {
- Unit* ar = GetCaster();
- if (ar && ar->ToPlayer())
- {
- if (ar->ToPlayer()->GetQuestStatus(11317) == QUEST_STATUS_INCOMPLETE || ar->ToPlayer()->GetQuestStatus(11322) == QUEST_STATUS_INCOMPLETE)
- ar->SummonCreature(27959, 3032.0f, -5095.0f, 723.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000);
-
- ar->SetStandState(UNIT_STAND_STATE_SIT);
- }
- }
-
- void Register() override
- {
- OnEffectApply += AuraEffectApplyFn(spell_q11322_q11317_the_cleansing::HandleEffectApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
- }
-};
-
class spell_q10714_on_spirits_wings : public SpellScript
{
PrepareSpellScript(spell_q10714_on_spirits_wings);
@@ -2499,7 +2477,6 @@ void AddSC_quest_spell_scripts()
RegisterSpellScript(spell_q12014_steady_as_a_rock);
RegisterSpellAndAuraScriptPair(spell_q11026_a11051_banish_the_demons, spell_q11026_a11051_banish_the_demons_aura);
RegisterSpellScript(spell_q10525_vision_guide);
- RegisterSpellScript(spell_q11322_q11317_the_cleansing);
RegisterSpellScript(spell_q10714_on_spirits_wings);
RegisterSpellScript(spell_q10720_the_smallest_creature);
RegisterSpellScript(spell_q13086_last_line_of_defence);
diff --git a/src/server/shared/Network/AsyncAcceptor.h b/src/server/shared/Network/AsyncAcceptor.h
index f91c2ca37e..71c58ed937 100644
--- a/src/server/shared/Network/AsyncAcceptor.h
+++ b/src/server/shared/Network/AsyncAcceptor.h
@@ -20,6 +20,7 @@
#include "IpAddress.h"
#include "Log.h"
+#include "Systemd.h"
#include <atomic>
#include <boost/asio/ip/tcp.hpp>
#include <functional>
@@ -33,10 +34,20 @@ class AsyncAcceptor
public:
typedef void(*AcceptCallback)(tcp::socket&& newSocket, uint32 threadIndex);
- AsyncAcceptor(Acore::Asio::IoContext& ioContext, std::string const& bindIp, uint16 port) :
+ AsyncAcceptor(Acore::Asio::IoContext& ioContext, std::string const& bindIp, uint16 port, bool supportSocketActivation = false) :
_acceptor(ioContext), _endpoint(Acore::Net::make_address(bindIp), port),
- _socket(ioContext), _closed(false), _socketFactory([this](){ return DefaultSocketFactory(); })
+ _socket(ioContext), _closed(false), _socketFactory([this](){ return DefaultSocketFactory(); }),
+ _supportSocketActivation(supportSocketActivation)
{
+ int const listen_fd = get_listen_fd();
+ if (_supportSocketActivation && listen_fd > 0)
+ {
+ LOG_DEBUG("network", "Using socket from systemd socket activation");
+ boost::system::error_code errorCode;
+ _acceptor.assign(boost::asio::ip::tcp::v4(), listen_fd, errorCode);
+ if (errorCode)
+ LOG_WARN("network", "Failed to assign socket {}", errorCode.message());
+ }
}
template<class T>
@@ -72,27 +83,31 @@ public:
bool Bind()
{
boost::system::error_code errorCode;
- _acceptor.open(_endpoint.protocol(), errorCode);
- if (errorCode)
+ // with socket activation the acceptor is already open and bound
+ if (!_acceptor.is_open())
{
- LOG_INFO("network", "Failed to open acceptor {}", errorCode.message());
- return false;
- }
+ _acceptor.open(_endpoint.protocol(), errorCode);
+ if (errorCode)
+ {
+ LOG_INFO("network", "Failed to open acceptor {}", errorCode.message());
+ return false;
+ }
#if AC_PLATFORM != AC_PLATFORM_WINDOWS
- _acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true), errorCode);
- if (errorCode)
- {
- LOG_INFO("network", "Failed to set reuse_address option on acceptor {}", errorCode.message());
- return false;
- }
+ _acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true), errorCode);
+ if (errorCode)
+ {
+ LOG_INFO("network", "Failed to set reuse_address option on acceptor {}", errorCode.message());
+ return false;
+ }
#endif
- _acceptor.bind(_endpoint, errorCode);
- if (errorCode)
- {
- LOG_INFO("network", "Could not bind to {}:{} {}", _endpoint.address().to_string(), _endpoint.port(), errorCode.message());
- return false;
+ _acceptor.bind(_endpoint, errorCode);
+ if (errorCode)
+ {
+ LOG_INFO("network", "Could not bind to {}:{} {}", _endpoint.address().to_string(), _endpoint.port(), errorCode.message());
+ return false;
+ }
}
_acceptor.listen(ACORE_MAX_LISTEN_CONNECTIONS, errorCode);
@@ -124,6 +139,7 @@ private:
tcp::socket _socket;
std::atomic<bool> _closed;
std::function<std::pair<tcp::socket*, uint32>()> _socketFactory;
+ bool _supportSocketActivation;
};
template<class T>
diff --git a/src/server/shared/Network/SocketMgr.h b/src/server/shared/Network/SocketMgr.h
index dc0c5e6f5f..085e4e2380 100644
--- a/src/server/shared/Network/SocketMgr.h
+++ b/src/server/shared/Network/SocketMgr.h
@@ -19,6 +19,7 @@
#define SocketMgr_h__
#include "AsyncAcceptor.h"
+#include "Config.h"
#include "Errors.h"
#include "NetworkThread.h"
#include <boost/asio/ip/tcp.hpp>
@@ -42,7 +43,8 @@ public:
std::unique_ptr<AsyncAcceptor> acceptor;
try
{
- acceptor = std::make_unique<AsyncAcceptor>(ioContext, bindIp, port);
+ bool supportSocketActivation = sConfigMgr->GetOption<bool>("Network.UseSocketActivation", false);
+ acceptor = std::make_unique<AsyncAcceptor>(ioContext, bindIp, port, supportSocketActivation);
}
catch (boost::system::system_error const& err)
{