Skip to content

fix(Scripts/ICC): make the Lady Deathwhisper elevator wait 7s at each… - #27149

Open
EricksOliveira wants to merge 1 commit into
azerothcore:masterfrom
EricksOliveira:fixElevatorICC
Open

fix(Scripts/ICC): make the Lady Deathwhisper elevator wait 7s at each…#27149
EricksOliveira wants to merge 1 commit into
azerothcore:masterfrom
EricksOliveira:fixElevatorICC

Conversation

@EricksOliveira

Copy link
Copy Markdown
Contributor

… stop

The elevator was driven by a free running 3000 ms tick that had nothing to do with the moment it actually reached an end of its path, so the time it stood still was uniformly random in [0, 3000] ms and a raid often could not board it.

Count the dwell only while the transport is parked, so it always starts on arrival: rearm the timer while it is moving, and flip GOState once 7000 ms have passed at a stop. StaticTransport::Update clamps PathProgress to exactly 0 and GetPauseTime() and freezes there while GOState matches, so those comparisons detect "parked at a stop" exactly.

The ride itself is untouched. The client renders it from TransportAnimation.dbc, so pause time and path progress are left alone and no SQL is needed.

Changes Proposed:

This PR proposes changes to:

  • Core (units, players, creatures, game systems).
  • Scripts (bosses, spell scripts, creature scripts).
  • Database (SAI, creatures, etc).

AI-assisted Pull Requests

Important

Using AI tools to prepare pull requests is allowed, but it must be disclosed and it must follow our AC guidelines for AI Agentic Engineering (link below).

You are expected to fully understand the changes you submit and to be able to explain and justify them when maintainers ask.

  • AI tools (e.g. Claude, ChatGPT, or similar) were used entirely or partially to prepare this pull request. If checked, specify which tools and models below.
    • Tools/models used: Opus5
  • I have read and understood the AC guidelines for AI Agentic Engineering

Issues Addressed:

SOURCE:

The changes have been validated through:

  • Live research (checked on live servers, e.g Classic WotLK, Retail, etc.)
  • Sniffs (remember to share them with the open source community!)
  • Video evidence, knowledge databases or other public sources (e.g forums, Wowhead, etc.)
  • The changes promoted by this pull request come partially or entirely from another project (cherry-pick). Cherry-picks must be committed using the proper --author tag in order to be accepted, thus crediting the original authors, unless otherwise unable to be found

Tests Performed:

This PR has been:

  • Tested in-game by the author.
  • Tested in-game by other community members/someone else other than the author/has been live on production servers.
  • This pull request requires further testing and may have edge cases to be tested.

How to Test the Changes:

  • This pull request can be tested by following the reproduction steps provided in the linked issue
  • This pull request requires further testing. Provide steps to test your changes. If it requires any specific setup e.g multiple players please specify it as well.

Known Issues and TODO List:

  • [ ]
  • [ ]

How to Test AzerothCore PRs

When a PR is ready to be tested, it will be marked as [WAITING TO BE TESTED].

You can help by testing PRs and writing your feedback here on the PR's page on GitHub. Follow the instructions here:

http://www.azerothcore.org/wiki/How-to-test-a-PR

REMEMBER: when testing a PR that changes something generic (i.e. a part of code that handles more than one specific thing), the tester should not only check that the PR does its job (e.g. fixing spell XXX) but especially check that the PR does not cause any regression (i.e. introducing new bugs).

For example: if a PR fixes spell X by changing a part of code that handles spells X, Y, and Z, we should not only test X, but we should test Y and Z as well.

… stop

The elevator was driven by a free running 3000 ms tick that had nothing to do
with the moment it actually reached an end of its path, so the time it stood
still was uniformly random in [0, 3000] ms and a raid often could not board it.

Count the dwell only while the transport is parked, so it always starts on
arrival: rearm the timer while it is moving, and flip GOState once 7000 ms have
passed at a stop. StaticTransport::Update clamps PathProgress to exactly 0 and
GetPauseTime() and freezes there while GOState matches, so those comparisons
detect "parked at a stop" exactly.

The ride itself is untouched. The client renders it from TransportAnimation.dbc,
so pause time and path progress are left alone and no SQL is needed.

Closes azerothcore#20324

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions github-actions Bot added Script Refers to C++ Scripts for the Core file-cpp Used to trigger the matrix build labels Aug 14, 2026
@coderabbitai

coderabbitai Bot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The change adds a named seven-second dwell-time constant for the Lady Deathwhisper elevator. The instance constructor uses this constant to initialize the elevator timer. Elevator updates reset the timer during movement, decrement it while the transport is parked at an endpoint, and reverse direction when the dwell interval expires.

Merge Risk: 🟡 Moderate · up to 786a2

The change is intended to guarantee a 7-second elevator stop, but the current timing logic can shorten that stop or cause immediate departure when an endpoint is reached. This bounded correctness issue should be addressed or explicitly accepted before merging.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro Plus

Run ID: e4d2201f-5a17-4b62-b55c-69ddba689999

📥 Commits

Reviewing files that changed from the base of the PR and between 7d9027d and 786a2c2.

📒 Files selected for processing (1)
  • src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp

Comment on lines +1684 to +1690
else if (DarkwhisperElevatorTimer <= diff)
{
if (trans->GetGoState() == GO_STATE_READY && trans->GetPathProgress() == 0)
trans->SetGoState(GO_STATE_ACTIVE);
else if (trans->GetGoState() == GO_STATE_ACTIVE && trans->GetPathProgress() == trans->GetPauseTime())
trans->SetGoState(GO_STATE_READY);
DarkwhisperElevatorTimer = DARKWHISPER_ELEVATOR_DWELL_TIME;
trans->SetGoState(atBottom ? GO_STATE_ACTIVE : GO_STATE_READY);
}
}
else
DarkwhisperElevatorTimer -= diff;
else
DarkwhisperElevatorTimer -= diff;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

fd -t f '^(Map|Transport)\.(cpp|h)$' . \
  -x rg -n -C 6 \
  'InstanceMap::Update|instance_data->Update|StaticTransport::Update|GetPathProgress|GetPauseTime' {}

Repository: azerothcore/azerothcore-wotlk

Length of output: 6406


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- review guidance files ---'
for f in .agents/docs/code-review.md .agents/docs/self-review-rules.md .agents/docs/cpp-guidelines.md .agents/docs/cpp-scripts.md; do
    if [ -f "$f" ]; then
        printf '\n--- %s ---\n' "$f"
        sed -n '1,240p' "$f"
    else
        printf '\n--- missing: %s ---\n' "$f"
    fi
done

printf '\n--- candidate files ---\n'
fd -t f -i 'map|transport' src/server/game src/server/scripts 2>/dev/null | head -80

printf '\n--- target source ---\n'
sed -n '1610,1710p' src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp

printf '\n--- target diff ---\n'
git diff -- src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp

printf '\n--- update implementations ---\n'
rg -n -C 18 'void (Map|InstanceMap|StaticTransport)::Update|instance_data->Update|Map::Update' src/server/game

Repository: azerothcore/azerothcore-wotlk

Length of output: 50387


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- review guidance files ---'
for f in .agents/docs/code-review.md .agents/docs/self-review-rules.md .agents/docs/cpp-guidelines.md .agents/docs/cpp-scripts.md; do
    if [ -f "$f" ]; then
        printf '\n--- %s ---\n' "$f"
        sed -n '1,240p' "$f"
    else
        printf '\n--- missing: %s ---\n' "$f"
    fi
done

printf '\n--- target source ---\n'
sed -n '1610,1710p' src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp

printf '\n--- target diff ---\n'
git diff -- src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp

printf '\n--- update implementations ---\n'
rg -n -C 18 'void (Map|InstanceMap|StaticTransport)::Update|instance_data->Update|Map::Update' src/server/game

Repository: azerothcore/azerothcore-wotlk

Length of output: 50387


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- map update ordering ---'
sed -n '436,565p' src/server/game/Maps/Map.cpp
sed -n '968,1025p' src/server/game/Entities/Transport/Transport.cpp

printf '\n--- elevator declarations and initialization ---\n'
rg -n -C 8 'DARKWHISPER_ELEVATOR|DarkwhisperElevatorTimer|LadyDeathwisperElevatorGUID|GO_LADY_DEATHWHISPER_ELEVATOR' \
  src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp

printf '\n--- repository state ---\n'
git status --short
git diff --stat
git diff --unified=30 -- src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp

printf '\n--- relevant current-master history summary ---\n'
git log -8 --oneline -- src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp

Repository: azerothcore/azerothcore-wotlk

Length of output: 12080


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- change under review ---'
git show --format=fuller --stat --oneline 786a2c20
git show --format= --unified=25 786a2c20 -- src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp

printf '\n--- parent implementation ---\n'
git show 786a2c20^:src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp |
    sed -n '55,85p;195,225p;1635,1685p;1895,1925p'

printf '\n--- update-diff bounds ---\n'
rg -n -C 5 't_diff|diff.*MAX|MAX.*diff|Update\([^)]*diff|World::Update' \
  src/server/game/World src/server/game/Maps src/server/game/Server | head -240

printf '\n--- deterministic timer model ---\n'
python3 - <<'PY'
DWELL = 7000

def tick(timer, progress, diff, pause):
    # StaticTransport::Update runs before InstanceMap::Update.
    arrived = progress < pause and progress + diff >= pause
    progress = pause if arrived else min(progress + diff, pause)
    parked = progress == pause
    if not parked:
        timer = DWELL
        action = "moving"
    elif timer <= diff:
        timer = DWELL
        action = "depart"
    else:
        timer -= diff
        action = "parked"
    return timer, progress, action, arrived

for diff in (1000, 8000):
    result = tick(DWELL, 6500, diff, 7000)
    print({"diff": diff, "result": result})
PY

Repository: azerothcore/azerothcore-wotlk

Length of output: 33187


Reset the dwell timer when the transport reaches an endpoint.

StaticTransport::Update runs before this code, so subtracting the full diff can shorten the stop or depart immediately when diff >= 7 seconds. Track endpoint arrival and decrement DarkwhisperElevatorTimer only on later updates.

Source: MCP tools

@EricksOliveira

Copy link
Copy Markdown
Contributor Author

Self-review — fixElevatorICC → master

Outcome clean — 1 round, zero findings

Reviewed 786a2c204 (fixElevatorICC vs upstream/master 7d9027d73, merge-base diff — 1 file, +24 −14)

By Claude Code, Opus 5 — self-review v0.3, 2026-08-15

Tested in-game by the author 7 s dwell timed at both stops over consecutive cycles; ridden as a passenger up and down; first departure after the Lady Deathwhisper kill; leaving and re-entering a saved instance with her already DONE.

Review details (1 round)

Intent Once Lady Deathwhisper is defeated, her elevator in the Oratory of the Damned (GameObject 202220, a StaticTransport) must stay motionless for a fixed 7 seconds at each end of its cycle before departing, replacing the random 0–3 s dwell that made it hard to board — without changing the ride duration and without any SQL.

Project rules .agents/docs/self-review-rules.md found and applied (content-script blast radius, in-game testing recorded from the author rather than guessed).

Coverage every changed file reviewed; the changeset is a single file and git show --stat confirms no other files ride along.

Codestyle apps/codestyle/codestyle-cpp.py could not be executed — no Python interpreter on this machine. The reviewer read the script and applied its rules by hand to every changed line: no if(, no trailing brace on if/else, no ;;, no tabs, no trailing whitespace, no duplicated blank lines, east-const respected, longest changed line 117 columns.

Round 1 — 786a2c204, clean

No findings. What the reviewer verified rather than assumed:

  • atBottom / atTop are exact: with a non-zero pause time, StaticTransport::Update (src/server/game/Entities/Transport/Transport.cpp:968-1019) clamps PathProgress to exactly 0 and to GetPauseTime() and returns early there, so neither test can fire mid-transit. All four entry states, including the two where a GOState flip lands mid-leg, converge on a parked state — no stall, no oscillation.
  • Update order: InstanceMap::Update (src/server/game/Maps/Map.cpp:2127-2134) runs Map::Update before the instance script, so the transport moves before the script observes it; the dwell measures ~7000 ms, and ~7000 ms plus one tick if the order were reversed.
  • Ride duration and the no-SQL claim: GO 202220 is type 11 with Data0 = 14733 and Data1 = 1 (data/sql/base/db_world/gameobject_template.sql:21463); the diff touches neither SetPauseTime, SetPathProgress, nor the animation period.
  • First departure after the kill: the block is skipped entirely while the boss is not DONE, so the timer holds its Initialize() value, and StaticTransport::Create spawns the elevator parked at the top via startOpen.
  • No leftovers: no debug logging, no commented-out code, no stray TODO.

Two points the reviewer raised and dismissed on its own, recorded for the maintainer:

  • DARKWHISPER_ELEVATOR_DWELL_TIME spells "Darkwhisper", not "Deathwhisper" — deliberate, it mirrors the pre-existing DarkwhisperElevatorTimer member. Naming, no written rule covers it.
  • cpp-guidelines.md prefers EventMap/TaskScheduler over hand-rolled tick counters, and this class already holds an EventMap. The rule scopes itself to CreatureAI members, the diff reuses an existing counter rather than adding one, and the logic here is state polling, which an EventMap does not express better.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

file-cpp Used to trigger the matrix build Script Refers to C++ Scripts for the Core

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[WotLK/ICC] Elevator in Oratory of the Dammed: Too Fast

1 participant