summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/ISSUE_TEMPLATE/bb_crash_issues.yml2
-rw-r--r--data/sql/updates/db_world/2025_11_17_04.sql10
-rw-r--r--src/server/game/Miscellaneous/Language.h5
-rw-r--r--src/server/scripts/Commands/cs_quest.cpp48
-rw-r--r--src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp89
5 files changed, 106 insertions, 48 deletions
diff --git a/.github/ISSUE_TEMPLATE/bb_crash_issues.yml b/.github/ISSUE_TEMPLATE/bb_crash_issues.yml
index 43b07bf793..9e94e5bbc2 100644
--- a/.github/ISSUE_TEMPLATE/bb_crash_issues.yml
+++ b/.github/ISSUE_TEMPLATE/bb_crash_issues.yml
@@ -31,7 +31,7 @@ body:
description: |
Do you have any logs or screenshots that can be useful?
Crash logs in text are preffered over screenshots.
- If you have logs in text form please upload them to [Gist](https://gist.github.com/) or PasteBin and upload the link.
+ DO NOT POST THE FULL CRASH LOG IN THE ISSUE BODY. DO NOT UPLOAD TEXT FILES. USE [GITHUB GIST](https://gist.github.com/), PASTEBIN, OR ANY SIMILAR SERVICE INSTEAD.
validations:
required: false
- type: input
diff --git a/data/sql/updates/db_world/2025_11_17_04.sql b/data/sql/updates/db_world/2025_11_17_04.sql
new file mode 100644
index 0000000000..7cc968b76c
--- /dev/null
+++ b/data/sql/updates/db_world/2025_11_17_04.sql
@@ -0,0 +1,10 @@
+-- DB update 2025_11_17_03 -> 2025_11_17_04
+--
+DELETE FROM `acore_string` WHERE `entry` IN (5088, 5089);
+INSERT INTO `acore_string` (`entry`, `content_default`) VALUES
+(5088, 'Quest: {} ({}) \nStatus: {}'),
+(5089, 'Quest can\'t be taken!');
+
+DELETE FROM `command` WHERE `name` = 'quest status';
+INSERT INTO `command` (`name`, `security`, `help`) VALUES
+('quest status', 2, 'Syntax: .quest status $id [$name]. Displays the selected player\'s status for the specified quest.');
diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h
index 66db5fd998..66268e3b48 100644
--- a/src/server/game/Miscellaneous/Language.h
+++ b/src/server/game/Miscellaneous/Language.h
@@ -1157,7 +1157,10 @@ enum AcoreStrings
LANG_CMD_NO_DOOR_FOUND = 5086,
LANG_CMD_DOOR_OPENED = 5087,
- // Room for more strings 5088-9999
+ LANG_CMD_QUEST_STATUS = 5088,
+ LANG_CMD_QUEST_UNAVAILABLE = 5089,
+
+ // Room for more strings 5090-9999
// Level requirement notifications
LANG_SAY_REQ = 6604,
diff --git a/src/server/scripts/Commands/cs_quest.cpp b/src/server/scripts/Commands/cs_quest.cpp
index c2ae75cb6a..9730b32210 100644
--- a/src/server/scripts/Commands/cs_quest.cpp
+++ b/src/server/scripts/Commands/cs_quest.cpp
@@ -37,6 +37,7 @@ public:
{ "complete", HandleQuestComplete, SEC_GAMEMASTER, Console::Yes },
{ "remove", HandleQuestRemove, SEC_GAMEMASTER, Console::Yes },
{ "reward", HandleQuestReward, SEC_GAMEMASTER, Console::Yes },
+ { "status", HandleQuestStatus, SEC_GAMEMASTER, Console::Yes },
};
static ChatCommandTable commandTable =
{
@@ -724,6 +725,53 @@ public:
handler->SetSentErrorMessage(false);
return true;
}
+
+ static bool HandleQuestStatus(ChatHandler* handler, Quest const* quest, Optional<PlayerIdentifier> playerTarget)
+ {
+ if (!playerTarget)
+ playerTarget = PlayerIdentifier::FromTargetOrSelf(handler);
+
+ if (!playerTarget)
+ {
+ handler->SendErrorMessage(LANG_PLAYER_NOT_FOUND);
+ return false;
+ }
+
+ uint32 entry = quest->GetQuestId();
+ std::string status;
+ if (Player* player = playerTarget->GetConnectedPlayer())
+ {
+ QuestStatus qs = player->GetQuestStatus(entry);
+ switch (qs)
+ {
+ case QUEST_STATUS_NONE:
+ status = "Not Taken";
+ break;
+ case QUEST_STATUS_COMPLETE:
+ status = "Complete";
+ break;
+ case QUEST_STATUS_INCOMPLETE:
+ status = "Incomplete";
+ break;
+ case QUEST_STATUS_FAILED:
+ status = "Failed";
+ break;
+ case QUEST_STATUS_REWARDED:
+ status = "Rewarded";
+ break;
+ default:
+ status = "Unknown";
+ break;
+ }
+
+ handler->PSendSysMessage(LANG_CMD_QUEST_STATUS, quest->GetTitle(), entry, status);
+
+ if (!player->CanTakeQuest(quest, true))
+ handler->PSendSysMessage(LANG_CMD_QUEST_UNAVAILABLE, entry, status);
+ }
+
+ return true;
+ }
};
void AddSC_quest_commandscript()
diff --git a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp
index dfddd2b715..0170859795 100644
--- a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp
+++ b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp
@@ -80,10 +80,10 @@ enum CreatureIds
NPC_ANUBAR_VENOMANCER = 29217,
};
-enum Phases : uint8
+enum Groups : uint8
{
- PHASE_EMERGED = 1,
- PHASE_SUBMERGED
+ GROUP_EMERGED = 1,
+ GROUP_SUBMERGED
};
enum SubPhase : uint8
@@ -117,7 +117,7 @@ struct boss_anub_arak : public BossAI
_submergePhase = SUBMERGE_NONE;
ScheduleHealthCheckEvent({ 75, 50, 25 }, [&]{
- events.Reset();
+ events.CancelEventGroup(GROUP_EMERGED);
Talk(SAY_SUBMERGE);
DoCastSelf(SPELL_CLEAR_ALL_DEBUFFS, true);
DoCastSelf(SPELL_SUBMERGE, false);
@@ -133,75 +133,74 @@ struct boss_anub_arak : public BossAI
DoCastSelf(SPELL_IMPALE_PERIODIC, true);
++_submergePhase;
- events.Reset();
ScheduleSubmerged();
}
}
void ScheduleEmerged()
{
- events.SetPhase(PHASE_EMERGED);
- events.ScheduleEvent(EVENT_CARRION_BEETLES, 6500ms, 0, PHASE_EMERGED);
- events.ScheduleEvent(EVENT_LEECHING_SWARM, 20s, 0, PHASE_EMERGED);
- events.ScheduleEvent(EVENT_POUND, 15s, 0, PHASE_EMERGED);
+ events.CancelEventGroup(GROUP_SUBMERGED);
+ events.ScheduleEvent(EVENT_CARRION_BEETLES, 6500ms, GROUP_EMERGED);
+ events.ScheduleEvent(EVENT_LEECHING_SWARM, 20s, GROUP_EMERGED);
+ events.ScheduleEvent(EVENT_POUND, 15s, GROUP_EMERGED);
};
void ScheduleSubmerged()
{
- events.SetPhase(PHASE_SUBMERGED);
- events.ScheduleEvent(EVENT_EMERGE, 60s, 0, PHASE_SUBMERGED);
+ events.CancelEventGroup(GROUP_EMERGED);
+ events.ScheduleEvent(EVENT_EMERGE, 60s, GROUP_SUBMERGED);
switch (_submergePhase)
{
case SUBMERGE_75:
- events.ScheduleEvent(EVENT_SUMMON_GUARDIAN, 4s, 0, PHASE_SUBMERGED);
+ events.ScheduleEvent(EVENT_SUMMON_GUARDIAN, 4s, GROUP_SUBMERGED);
if (IsHeroic())
- events.ScheduleEvent(EVENT_SUMMON_GUARDIAN, 7s, 0, PHASE_SUBMERGED);
+ events.ScheduleEvent(EVENT_SUMMON_GUARDIAN, 7s, GROUP_SUBMERGED);
_remainingLargeSummonsBeforeEmerge = IsHeroic() ? 2 : 1;
- events.ScheduleEvent(EVENT_SUMMON_ASSASSINS, 4s, 0, PHASE_SUBMERGED);
- events.ScheduleEvent(EVENT_SUMMON_ASSASSINS, 24s, 0, PHASE_SUBMERGED);
- events.ScheduleEvent(EVENT_SUMMON_ASSASSINS, 44s, 0, PHASE_SUBMERGED);
+ events.ScheduleEvent(EVENT_SUMMON_ASSASSINS, 4s, GROUP_SUBMERGED);
+ events.ScheduleEvent(EVENT_SUMMON_ASSASSINS, 24s, GROUP_SUBMERGED);
+ events.ScheduleEvent(EVENT_SUMMON_ASSASSINS, 44s, GROUP_SUBMERGED);
break;
case SUBMERGE_50:
- events.ScheduleEvent(EVENT_SUMMON_GUARDIAN, 4s, 0, PHASE_SUBMERGED);
+ events.ScheduleEvent(EVENT_SUMMON_GUARDIAN, 4s, GROUP_SUBMERGED);
if (IsHeroic())
- events.ScheduleEvent(EVENT_SUMMON_GUARDIAN, 7s, 0, PHASE_SUBMERGED);
+ events.ScheduleEvent(EVENT_SUMMON_GUARDIAN, 7s, GROUP_SUBMERGED);
- events.ScheduleEvent(EVENT_SUMMON_VENOMANCER, 24s, 0, PHASE_SUBMERGED);
+ events.ScheduleEvent(EVENT_SUMMON_VENOMANCER, 24s, GROUP_SUBMERGED);
if (IsHeroic())
- events.ScheduleEvent(EVENT_SUMMON_VENOMANCER, 29s, 0, PHASE_SUBMERGED);
+ events.ScheduleEvent(EVENT_SUMMON_VENOMANCER, 29s, GROUP_SUBMERGED);
_remainingLargeSummonsBeforeEmerge = IsHeroic() ? 4 : 2;
- events.ScheduleEvent(EVENT_SUMMON_ASSASSINS, 4s, 0, PHASE_SUBMERGED);
- events.ScheduleEvent(EVENT_SUMMON_ASSASSINS, 24s, 0, PHASE_SUBMERGED);
- events.ScheduleEvent(EVENT_SUMMON_ASSASSINS, 44s, 0, PHASE_SUBMERGED);
+ events.ScheduleEvent(EVENT_SUMMON_ASSASSINS, 4s, GROUP_SUBMERGED);
+ events.ScheduleEvent(EVENT_SUMMON_ASSASSINS, 24s, GROUP_SUBMERGED);
+ events.ScheduleEvent(EVENT_SUMMON_ASSASSINS, 44s, GROUP_SUBMERGED);
break;
case SUBMERGE_25:
- events.ScheduleEvent(EVENT_SUMMON_GUARDIAN, 4s, 0, PHASE_SUBMERGED);
+ events.ScheduleEvent(EVENT_SUMMON_GUARDIAN, 4s, GROUP_SUBMERGED);
if (IsHeroic())
- events.ScheduleEvent(EVENT_SUMMON_GUARDIAN, 7s, 0, PHASE_SUBMERGED);
+ events.ScheduleEvent(EVENT_SUMMON_GUARDIAN, 7s, GROUP_SUBMERGED);
- events.ScheduleEvent(EVENT_SUMMON_VENOMANCER, 24s, 0, PHASE_SUBMERGED);
+ events.ScheduleEvent(EVENT_SUMMON_VENOMANCER, 24s, GROUP_SUBMERGED);
if (IsHeroic())
- events.ScheduleEvent(EVENT_SUMMON_VENOMANCER, 29s, 0, PHASE_SUBMERGED);
+ events.ScheduleEvent(EVENT_SUMMON_VENOMANCER, 29s, GROUP_SUBMERGED);
_remainingLargeSummonsBeforeEmerge = IsHeroic() ? 4 : 2;
- events.ScheduleEvent(EVENT_SUMMON_ASSASSINS, 4s, 0, PHASE_SUBMERGED);
- events.ScheduleEvent(EVENT_SUMMON_DARTER, 4s, 0, PHASE_SUBMERGED);
+ events.ScheduleEvent(EVENT_SUMMON_ASSASSINS, 4s, GROUP_SUBMERGED);
+ events.ScheduleEvent(EVENT_SUMMON_DARTER, 4s, GROUP_SUBMERGED);
- events.ScheduleEvent(EVENT_SUMMON_DARTER, 12s, 0, PHASE_SUBMERGED);
+ events.ScheduleEvent(EVENT_SUMMON_DARTER, 12s, GROUP_SUBMERGED);
- events.ScheduleEvent(EVENT_SUMMON_ASSASSINS, 24s, 0, PHASE_SUBMERGED);
- events.ScheduleEvent(EVENT_SUMMON_DARTER, 26s, 0, PHASE_SUBMERGED);
+ events.ScheduleEvent(EVENT_SUMMON_ASSASSINS, 24s, GROUP_SUBMERGED);
+ events.ScheduleEvent(EVENT_SUMMON_DARTER, 26s, GROUP_SUBMERGED);
- events.ScheduleEvent(EVENT_SUMMON_DARTER, 32s, 0, PHASE_SUBMERGED);
+ events.ScheduleEvent(EVENT_SUMMON_DARTER, 32s, GROUP_SUBMERGED);
- events.ScheduleEvent(EVENT_SUMMON_ASSASSINS, 44s, 0, PHASE_SUBMERGED);
- events.ScheduleEvent(EVENT_SUMMON_DARTER, 45s, 0, PHASE_SUBMERGED);
+ events.ScheduleEvent(EVENT_SUMMON_ASSASSINS, 44s, GROUP_SUBMERGED);
+ events.ScheduleEvent(EVENT_SUMMON_DARTER, 45s, GROUP_SUBMERGED);
break;
default:
break;
@@ -213,9 +212,8 @@ struct boss_anub_arak : public BossAI
Talk(SAY_AGGRO);
instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
- events.SetPhase(PHASE_EMERGED);
- events.ScheduleEvent(EVENT_CLOSE_DOORS, 5s, 0, PHASE_EMERGED);
ScheduleEmerged();
+ events.ScheduleEvent(EVENT_CLOSE_DOORS, 5s);
// set up world triggers
std::list<TempSummon*> summoned;
@@ -285,9 +283,8 @@ struct boss_anub_arak : public BossAI
--_remainingLargeSummonsBeforeEmerge;
if (_remainingLargeSummonsBeforeEmerge == 0)
{
- events.Reset();
- events.SetPhase(PHASE_SUBMERGED);
- events.ScheduleEvent(EVENT_EMERGE, 5s, 0, PHASE_SUBMERGED);
+ me->RemoveAurasDueToSpell(SPELL_IMPALE_PERIODIC);
+ events.RescheduleEvent(EVENT_EMERGE, 5s, GROUP_SUBMERGED);
}
break;
}
@@ -319,12 +316,12 @@ struct boss_anub_arak : public BossAI
break;
case EVENT_CARRION_BEETLES:
DoCastSelf(SPELL_CARRION_BEETLES);
- events.ScheduleEvent(EVENT_CARRION_BEETLES, 25s, 0, PHASE_EMERGED);
+ events.ScheduleEvent(EVENT_CARRION_BEETLES, 25s, GROUP_EMERGED);
break;
case EVENT_LEECHING_SWARM:
Talk(SAY_LOCUST);
DoCastSelf(SPELL_LEECHING_SWARM);
- events.ScheduleEvent(EVENT_LEECHING_SWARM, 20s, 0, PHASE_EMERGED);
+ events.ScheduleEvent(EVENT_LEECHING_SWARM, 20s, GROUP_EMERGED);
break;
case EVENT_POUND:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 10.0f))
@@ -332,10 +329,10 @@ struct boss_anub_arak : public BossAI
DoCastSelf(SPELL_SELF_ROOT, true);
me->DisableRotate(true);
me->SendMovementFlagUpdate();
- events.ScheduleEvent(EVENT_ENABLE_ROTATE, 3300ms, 0, PHASE_EMERGED);
+ events.ScheduleEvent(EVENT_ENABLE_ROTATE, 3300ms, GROUP_EMERGED);
DoCast(target, SPELL_POUND);
}
- events.ScheduleEvent(EVENT_POUND, 18s, 0, PHASE_EMERGED);
+ events.ScheduleEvent(EVENT_POUND, 18s, GROUP_EMERGED);
break;
case EVENT_ENABLE_ROTATE:
me->RemoveAurasDueToSpell(SPELL_SELF_ROOT);
@@ -376,10 +373,10 @@ struct boss_anub_arak : public BossAI
void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask) override
{
+ BossAI::DamageTaken(attacker, damage, damagetype, damageSchoolMask);
+
if (me->HasAura(SPELL_SUBMERGE) && damage >= me->GetHealth())
damage = me->GetHealth() - 1;
-
- BossAI::DamageTaken(attacker, damage, damagetype, damageSchoolMask);
}
private: