Fix restored bot passengers and add capital Cataclysm portals
This commit is contained in:
1 parent
19075b6c75
commit
bc8f171055
23 files changed
+1184
-24
No files matched your search
@@ -1,3 +1,216 @@
|
||||
# Commit checkpoint: transport resumption, deck return and capital portals
|
||||
|
||||
User requested a local commit of all completed changes since19075b6c75. Includes
|
||||
stopped-only recorded deck stand fallback, adoption of restored native ship
|
||||
passengers and safe recorded exit, capital Cataclysm/Tol Barad/Vashjir graph
|
||||
bindings and scoped spell repairs (migration07), plus tests/docs/evidence.
|
||||
Transport final build and six tests passed; portal native tests verified all12
|
||||
transfers and both-faction Vashjir graph denial. Temporary profiles/tele fixtures
|
||||
removed, generated profiles/schedules restored. Final server362937 is operational;
|
||||
no lifecycle operation or push as part of committing. Earlier uncommitted/pending
|
||||
notes below are historical; consult git log for the resulting commit.
|
||||
|
||||
# Latest: capital Cataclysm/Tol portals COMPLETE, all12 native transfers verified
|
||||
|
||||
Applied SQL07 graphbindings forSW/Org Hyjal,Deepholm,Uldum,TwilightHighlands,
|
||||
TolBarad,Vashjir (6/capital). Sources factionACL1/2, duplicateOrgTol219035 skipped.
|
||||
Nine existing templates keptdata6=0 and worked. OrgTol206595 failednativeclick
|
||||
atdata6=0 twice, nowvisitorcast1 and verifiednative88341arrival732. Vash90244/
|
||||
90245 previouslyempty; native DBteleporteffects160117/118 + existingSmugglersScar
|
||||
fixedtarget(-4570.29,3478.06,-101.809), visitorcast207690/691. Explicitfixedcave
|
||||
landing, NOT retailquestprogress destinations. Other targets/conditions unchanged.
|
||||
|
||||
All12 nativeclicks/expectedarrivalcoordinates verified using35Karggan/36Edwin85.
|
||||
Finalresults/evidence doc/clientless/checkpoints/2026-10-29-capital-cata-portals.
|
||||
Area5146/children policies byteunchanged. Nativebothbotquery target5057 mask0
|
||||
allowed0, both hardgraphtravelattempts rejected destinationdenied. Nodes/edges
|
||||
remainpresent/enabled. Migrationreplay preservedbindings/effects/targets. Three
|
||||
existing portal/ACK/area-node regressions passed; no newC++ changes/buildneeded.
|
||||
|
||||
Temp profileskarggan.lua/edwin.lua removed after verifyingexacttestcontents;
|
||||
generatedprofiles+daily schedulesrestored. Bothtestbotsreturnedowncapitals;
|
||||
12vcore_cata_probe_*gametelefixturesdeleted,cache reloaded,count0. No human edits.
|
||||
EarlierHyjalbaselinefalsefailurewasreadingtooearly; finalsaveproveditworked,
|
||||
userinformed andblanketcasterchange undone. AfterfixfirstTolretestattempt before
|
||||
Edwinonline was rejected; real afteronline nativeclickARRIVED andfinalJSONcorrect.
|
||||
|
||||
Final server362937 undergdb/tmuxvcore-worldserver, console/tmp/vcore-cata-portals-
|
||||
final-start-20261029.log. Freshready11s/process+8085/8087 verified. Known old
|
||||
OutdoorPvPshutdowntracespreserved. No commit/push. Prior uncommitteddeckreturn/
|
||||
resumedpassengerWIP preserved. SQL07intent-to-add becausecustomSQLignored.
|
||||
See capital-cataclysm-portals.md. Taskcomplete; report andwaituserfeedback.
|
||||
|
||||
# Active task: capital Cataclysm/Tol Barad portals incl blocked Vashjir
|
||||
|
||||
User asks graph entries + real functionality checks for bothcapitals inclVashjir,
|
||||
keeping global area ban. Native imports done12 unique spawns (OrgTol duplicate
|
||||
219035 intentionally skipped). SQL07 prepared/applied, scoped data6visitorcast
|
||||
for206595 (OrgTol FAILED live twice atdata6=0),207690/207691 (Vash emptyserver
|
||||
spells). Nine other templates keep originaldata6=0 and native targets/conditions.
|
||||
Vash90244/90245 hadNOeffects/targets; added DBnative teleport effects160117/118
|
||||
and fixed existing gameteleSmugglersScar landing(-4570.29,3478.06,-101.809),
|
||||
NOT claimed retailquest-dependent destination logic. GraphSQL seedonlypreserves
|
||||
manual positions/enabledflags. SourceACL Alliance/Horde; area catalog unchanged.
|
||||
|
||||
Temp tests use35KargganAlliance85 and36EdwinHorde85, nohumans. Temporary specific
|
||||
profiles karggan.lua/edwin.lua under sourceadventure/profiles copied fromgenerated
|
||||
DB thenbehavior.enabled/daily_schedule=false. ORIGINAL backups /tmp/vcore-cata-
|
||||
portals/*-profile-original.lua; files DID NOT EXIST before task. MUST REMOVEONLY
|
||||
these2 profiles aftertests; luareload+scheduleon torestoregeneratedbehavior.
|
||||
12 temporary game_tele namesvcore_cata_probe_<spawn> created; deleteonlythatprefix
|
||||
and reloadgame_tele aftertests. No testfixtureleftinrepo/DB onfinish.
|
||||
|
||||
Probe script/tmp/vcore-cata-portals/probe.py completed12tests;11successful.
|
||||
Failure OrgTolspawn211264 remainedsource after30s/retry; nowchangeddata6=1 and
|
||||
issued shutdown10 to361432 (console/tmp/vcore-cata-portals-start-20261029.log)
|
||||
for cache reload. Needwaitfullexit+gdbtrace thenstartsameinstalledbinaryfreshgdb
|
||||
console/tmp/vcore-cata-portals-final-start-20261029.log,verifyready/ports. Retest
|
||||
211264 withEdwin36 viaGMtelefixture+nativeclientlessportalobjectuse; pollsaveall/
|
||||
DBuntiltargetmap732(-603.724,1387.62,22.0498). Original probes JSONsaved beforefix
|
||||
/tmp/vcore-cata-portals/probes-before-tol-fix.json. Update finalprobes.json entry.
|
||||
Other11 includingBOTHVashlandings passednativeclick->expectedposition. Native
|
||||
35 areaqueriesbothVashtargets returnedfactionMask0/allowed0 area5057; real hard
|
||||
travel_to_node35 targetVash rejected detail destinationdenied. Need repeat36
|
||||
areaqueries whennotintransfer. Verifypolicy before.tsv byteunchanged.
|
||||
|
||||
Corrected earlier misleadingHyjalbaseline: firstDBread tooearly, finalsave proved
|
||||
native0 worked; user informed, blanketcasterchange undone before tests. Do NOT
|
||||
claim all portals broken. Otherexistinguncommitteddeckreturn/resumedpassengerWIP
|
||||
preserved. No newC++ source changes inthisportal task; DBreloadrequiredrestarts.
|
||||
Next finishOrgTolretest,cleanupfixtures/profiles, tests/docs/evidence,report.
|
||||
|
||||
# Latest: resumed-passenger build INSTALLED, server READY; Shanron on normal plan
|
||||
|
||||
User explicitly released recording hold and requested install/restart. Old349322
|
||||
fully exited after known OutdoorPvP shutdown destructor crash (oldconsole trace
|
||||
retained). Installed successful prepared build using existing CMake:
|
||||
/tmp/vcore-transport-resume-install.log. Fresh gdb/tmux vcore-worldserver
|
||||
PID356681, console/tmp/vcore-transport-resume-start-20261029.log. NewServer.log
|
||||
freshready12s, both8085/8087 listening, process persists. No source/config/DB
|
||||
changes for deployment; prior uncommitted deck-return+passenger-resume WIP remains.
|
||||
|
||||
Requested native clientless login140 to check Shanron without manual position/
|
||||
profile/dayplan override. Core LoadFromDB reported transportGUID2 unavailable,
|
||||
teleported him to homebind before controller startup; same warning for26.
|
||||
Thus no restored attachment existed to exercise new ResumePassenger for140.
|
||||
Confirmed140 online/profileloaded, normal restintent poi_guard_111 arrived and
|
||||
rest_sleep/rest_look micros. No TRANSPORT_RESUME live event observed yet; do not
|
||||
claim restored-passenger/exit behavior live-proven from this deployment. Six
|
||||
focused tests and complete build previously passed. Core inability to restore
|
||||
certain ship bindings remains a separate observed limitation. User was told
|
||||
Shanron resumed ordinary schedule via core homebind fallback, not new deck exit.
|
||||
No push/commit requested. Server operational. Recording hold is now released.
|
||||
|
||||
# Latest: orphan-passenger fix READY; USER HOLD NO INSTALL/RESTART
|
||||
|
||||
Final complete build passed/tmp/vcore-transport-resume-final-build.log (source
|
||||
TransportMgr object rebuilt after final edits, link completed). Six targeted
|
||||
tests pass/tmp/vcore-resumed-passenger-tests.json. Latest additional detached
|
||||
land-tail ownership assertion passes in test_transport log. Native attachment
|
||||
adoption + next permitted recorded halt + ordinary exit implemented; current
|
||||
installed server349322/executable21:00:04 unchanged. No runtime console commands,
|
||||
DB/profile/dayplan changes, installation or restart in this task. Existing
|
||||
uncommitted stopped-deck-return fallback work retained. New fix is source/build
|
||||
only and NOT live-verified. See resumed-transport-passengers.md.
|
||||
USER IS RECORDING ROUTES. Notify ready and WAIT for explicit hold release before
|
||||
install/restart. No pending builds/test processes. No commit/push requested.
|
||||
|
||||
# Latest: resumed-passenger fix prepared; USER RECORDING, NO RESTART/INSTALL
|
||||
|
||||
User explicitly requests fix for Shanron's orphaned native ship attachment but
|
||||
NO restart while recording more routes. Added TransportMgr::ResumePassenger
|
||||
and Resumed flag; Lua Adventure controller invokes before actions, after
|
||||
observation/maintenance. Preserve normal active rides; require actual known
|
||||
recorded vehicle+managed alive noncombat passenger, no taxi/pending teleport,
|
||||
allowed stop. Lazy ensure both stop and graph data load. Reconstruct only Riding
|
||||
state, never reboard/teleport/change schedule. At each Riding update choose actual
|
||||
currently stopped permitted recorded dock; no guessed prior destination. Reuse
|
||||
normal deck return/budget/recorded exit incl native map-transfer ACK; keep control
|
||||
through detached land tail until arrived. No exiting at newly forbidden stops.
|
||||
Unrecorded/forbidden services untouched. No static tram DB persistence repair.
|
||||
Six tests passed/tmp/vcore-resumed-passenger-tests.json; extended production
|
||||
transport harness includes restart adoption, preserved normal rides, complete
|
||||
native-modeled exits, denied stops, unknown/unmanaged, landtail and cross-map.
|
||||
Final build running/tmp/vcore-transport-resume-final-build.log. Source latest
|
||||
changes after initialbuild must be included; verify final completion.
|
||||
Current server349322 remains unchanged, NO console/lifecycle/DB/profile changes.
|
||||
Doc resumed-transport-passengers.md. Previous uncommitted deck-return fallback
|
||||
work preserved. Next finish final build/checks, tell user ready; WAIT for user
|
||||
recording hold release before any install/restart. Live behavior unverified.
|
||||
|
||||
# Latest diagnosis: Shanron140 attached to ship but no resumed ride controller
|
||||
|
||||
User observes Shanron aboard ship toSW. Native console transport status140:
|
||||
`No transport ride state for this character.` actioninfo140 Idle/empty. Character
|
||||
DB online map0(-8644.53,1335.31,6.12629),transguid2(The Bravery). Currentserver
|
||||
349322. Both previous and current boot logged generated140 startup but no native
|
||||
boarding/travel progression; normal core restores MO_TRANSPORT attachment from
|
||||
saved character, CPC `_rides` exists only in memory and Start refuses already
|
||||
attached players. Thus restored ship passenger has no ride driver to initiate
|
||||
recorded exit/deck fallback. Distinct from120Brynna's repeated return issue.
|
||||
No code/DB/lifecycle/relocation changes for Shanron investigation; existing
|
||||
uncommitted stopped-deck fallback changes preserved. Needed follow-up: adopt
|
||||
already attached managed passengers after login/restart using matching recorded
|
||||
service; disembark only at an actual safe recorded dock, then resume normal plan.
|
||||
Do not simply detach/teleport a passenger in transit. Existing120fallback still
|
||||
requires a tracked ride to call DeckMgr::Update and cannot solve orphaned ride.
|
||||
|
||||
# Latest: stopped deck-return fallback INSTALLED, server READY
|
||||
|
||||
User permits transfer to recorded onboard stand after return failure only while
|
||||
vehicle stopped. Implemented checked direct native spline launch + persistent
|
||||
return failure state and safe native passenger relocation fallback. No detach,
|
||||
no transportGUID changes, exact recorded local anchor, same transport/map,
|
||||
alive/no combat/no pending teleport, valid coordinates, stopped+exitBudget1s
|
||||
reserve independently rechecked. Ordinary recorded exit still follows.
|
||||
Five tests PASS: deck control (including failed start/return, motion and short
|
||||
halt rejection), actual fallback helper with doubles, real meshes, generic
|
||||
transport, grid loading. Build/tmp/vcore-deck-return-build.log PASS. Installed
|
||||
/tmp/vcore-deck-return-install.log after341932 fully exited (old known OutdoorPvP
|
||||
shutdown fault trace retained). Fresh gdb/tmux PID349322, console
|
||||
/tmp/vcore-deck-return-start-20261029.log, freshready13s,8085/8087 listeners,
|
||||
process verified. Installed binary contains DECK_RETURN_FALLBACK string.
|
||||
No native fallback event seen yet; no live/visual acceptance claim. Natural bot
|
||||
loader active; no manual forced action, DB relocation or profile/plan override.
|
||||
Doc deck-return-fallback.md. All these changes UNCOMMITTED after19075b6c75.
|
||||
Previous SESSION diagnostic edit is intentional. Report completion; await user.
|
||||
|
||||
# Latest: stopped deck-return fallback implemented, build passed
|
||||
|
||||
User explicitly permits transfer back to recorded onboard stand after return
|
||||
navigation fails, only while vehicle stopped. Added Passenger.Returning/
|
||||
ReturnFailed, checked immediate native spline launch, failed/timeout/interrupted
|
||||
return handling; helper rechecks actual same passenger/map, stopped and exit
|
||||
reserve+1s, life/combat/teleport, valid local/world coordinates. Native local
|
||||
position+TransportBase passenger relocation+broadcast; attachment never removed.
|
||||
Ordinary recorded exit remains unchanged. Tests controller/native helper/real
|
||||
mesh passed, generic transport/grid tests running. Build
|
||||
/tmp/vcore-deck-return-build.log complete PASS. Not yet installed. Currentserver
|
||||
341932 remains running. Prior SESSION diagnostic change is expected WIP after
|
||||
commit19075b6c75. New doc deck-return-fallback.md. Next: finish test checks,
|
||||
graceful shutdown/install/restart undergdb, freshready+ports, observe boarding/
|
||||
returns/exits; do not claim actual fallback occurred until logged.
|
||||
|
||||
# Latest: Brynna120 stuck aboard tram; diagnosed repeated deck return
|
||||
|
||||
User observes Brynna in wagon. Branch19075b6c75 clean at investigation start.
|
||||
Native status120 Riding SW->IF spawn18803 point4 elapsed238825, abort0, action
|
||||
Moving. Prior rescueSW completed20:45:28, normal boarding20:46:42/Riding20:46:43.
|
||||
Deck outing target(2.419,-3.118,-10.445). At destination20:47:55 and20:47:58
|
||||
repeated DECK_WALK return target(-0.112,-0.187,-10.345),length3.87. Next dock
|
||||
20:50:17..22 dozens of identical return launches per second, NO Leaving state.
|
||||
This confirms recurring deck-return problem, not lost attachment after restart.
|
||||
DeckMgr::Launch reports success unconditionally via MotionMaster LaunchMoveSpline
|
||||
(void), Update uses IsSplineEnabled and retries when actual local target not
|
||||
reached. Exact cause (launch failure, motion slot priority, competing stop) not
|
||||
proven yet. Unit UpdateSplinePosition does update transport-local position.
|
||||
Server.log has _checkPathLengths validation errors for76/110, NOT120; do not
|
||||
attribute those to Brynna without evidence. No code or DB/teleport/lifecycle
|
||||
changes in this diagnosis. Server341932 remains running. Ordinary rescue refuses
|
||||
attached passengers by design; do not detach/teleport moving wagon passenger.
|
||||
Next fix should validate actual deck spline start/completion, avoid repeated
|
||||
return issuance, reserve enough dock time, retain safe passenger attachment.
|
||||
|
||||
# Commit checkpoint: group follow, grounded portal and explicit tram rescue
|
||||
|
||||
User requested a local commit of the current completed changes. Includes group
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
# Capital Cataclysm portals and Tol Barad
|
||||
|
||||
World migration `2026_10_29_07_capital_cataclysm_portals.sql` adds twelve native
|
||||
GameObject portal graph bindings, six for each capital. Source faction ACL is
|
||||
Alliance1 or Horde2; destination area rules retain precedence. Imports and SQL
|
||||
seed only: existing enabled flags and manually adjusted positions survive.
|
||||
|
||||
| Destination | Stormwind spawn | Orgrimmar spawn |
|
||||
| --- | --- | --- |
|
||||
| Hyjal | 200624 | 219028 |
|
||||
| Deepholm | 200625 | 211258 |
|
||||
| Uldum | 200626 | 211259 |
|
||||
| Twilight Highlands | 200627 | 211260 |
|
||||
| Tol Barad Peninsula | 220365 | 211264 |
|
||||
| Vashj'ir | 220366 | 211257 |
|
||||
|
||||
Orgrimmar Tol Barad duplicate219035 is coincident with211264 and deliberately
|
||||
has no second graph edge. Its shared template receives the same repair.
|
||||
|
||||
Nine existing portal templates worked in native tests without caster changes.
|
||||
Orgrimmar Tol Barad206595 accepted clicks but failed to transfer Edwin85 in two
|
||||
attempts; changing only this template to native visitor-cast mode made its
|
||||
88341 teleport work. Native target coordinates and conditions remain unchanged.
|
||||
An early Hyjal failure inference was corrected: first save/read was too early,
|
||||
final save showed successful arrival. No blanket caster change was retained.
|
||||
|
||||
Vashj'ir server-only spells90244/90245 had neither effects nor target positions.
|
||||
The migration supplies direct native teleport effects160117/160118 and visitor
|
||||
casting for207690/207691. The fixed landing comes from the existing project
|
||||
SmugglersScar game_tele1514 at map0(-4570.29,3478.06,-101.809). This is a deliberate
|
||||
fixed cave destination, not reconstructed retail quest-progress destination
|
||||
selection. No quest completion is granted or visibility condition bypassed.
|
||||
|
||||
Vashj'ir and children remain closed by unchanged area5146 faction mask0. Both
|
||||
source and destination nodes and the portal edges exist/enabled. Native area
|
||||
queries for Alliance35 and Horde36 resolve the landing to5057 with inherited
|
||||
factionMask0 and allowed0. Actual hard travel_to_node attempts are rejected with
|
||||
`destination node denied by area/node catalog` for both factions. Diagnostic
|
||||
native-click tests intentionally exercise the underlying portal, outside
|
||||
ordinary autonomous planning; the ban was never disabled.
|
||||
|
||||
## Verification and cleanup
|
||||
|
||||
Twelve native CMSG_GAMEOBJ_USE clicks with level85 Karggan35 and Edwin36 reached
|
||||
their expected spell_target_position destinations. Full position snapshots are
|
||||
in checkpoints/2026-10-29-capital-cata-portals/probes.json. Before-Tol-fix output
|
||||
is retained separately. An initial post-restart retest attempted a click before
|
||||
Edwin finished login and was rejected; the successful retest waited for online
|
||||
state and native interaction-range validation. Do not count that login race as
|
||||
a portal failure or an unverified success.
|
||||
|
||||
Migration replay preserved binding/effect/target results. Existing native portal
|
||||
use, transfer/ACK and area-node regressions passed. No new C++ changes/build were
|
||||
required; two restarts loaded server spell/template DB changes. Final server
|
||||
PID362937 under gdb/tmux vcore-worldserver, console
|
||||
/tmp/vcore-cata-portals-final-start-20261029.log; freshready11s,8085/8087 verified.
|
||||
Known OutdoorPvP shutdown fault traces retained in earlier consoles.
|
||||
|
||||
The two temporary specific profiles were removed and generated profiles plus
|
||||
daily schedules restored. Testbots returned to their own capitals. Twelve
|
||||
vcore_cata_probe_* game_tele fixtures were deleted and cache reloaded (count0).
|
||||
No human character modified. Prior uncommitted transport fixes preserved.
|
||||
Native transfers are verified; final client-side visual acceptance remains with
|
||||
the user. No commit or push requested for this task.
|
||||
@@ -0,0 +1,13 @@
|
||||
gameobject_spawn_id gameobject_entry spell_id id enabled from_node_key to_node_key allowed_factions
|
||||
200624 207692 94565 1798 1 portal_go_200624_source portal_go_200624_target 1
|
||||
200625 207693 84515 1799 1 portal_go_200625_source portal_go_200625_target 1
|
||||
200626 207695 94564 1800 1 portal_go_200626_source portal_go_200626_target 1
|
||||
200627 207694 85545 1801 1 portal_go_200627_source portal_go_200627_target 1
|
||||
211257 207690 90244 1808 1 portal_go_211257_source portal_go_211257_target 2
|
||||
211258 207689 84513 1803 1 portal_go_211258_source portal_go_211258_target 2
|
||||
211259 207687 94564 1804 1 portal_go_211259_source portal_go_211259_target 2
|
||||
211260 207686 82621 1805 1 portal_go_211260_source portal_go_211260_target 2
|
||||
211264 206595 88341 1806 1 portal_go_211264_source portal_go_211264_target 2
|
||||
219028 207688 94565 1807 1 portal_go_219028_source portal_go_219028_target 2
|
||||
220365 206594 88339 1802 1 portal_go_220365_source portal_go_220365_target 1
|
||||
220366 207691 90245 1809 1 portal_go_220366_source portal_go_220366_target 1
|
||||
|
+20
@@ -0,0 +1,20 @@
|
||||
Native portal click sent: bot=35 spawn=200624 entry=207692. Check teleport completion and cast diagnostics.
|
||||
Native portal click sent: bot=35 spawn=200625 entry=207693. Check teleport completion and cast diagnostics.
|
||||
[?2004hTC>Native portal click sent: bot=35 spawn=200626 entry=207695. Check teleport completion and cast diagnostics.
|
||||
Native portal click sent: bot=35 spawn=200627 entry=207694. Check teleport completion and cast diagnostics.
|
||||
[?2004hTC>Native portal click sent: bot=35 spawn=220365 entry=206594. Check teleport completion and cast diagnostics.
|
||||
Native portal click sent: bot=35 spawn=220366 entry=207691. Check teleport completion and cast diagnostics.
|
||||
Native portal click sent: bot=36 spawn=219028 entry=207688. Check teleport completion and cast diagnostics.
|
||||
Native portal click sent: bot=36 spawn=211258 entry=207689. Check teleport completion and cast diagnostics.
|
||||
Native portal click sent: bot=36 spawn=211259 entry=207687. Check teleport completion and cast diagnostics.
|
||||
[?2004hTC>Native portal click sent: bot=36 spawn=211260 entry=207686. Check teleport completion and cast diagnostics.
|
||||
TC> Area access GUID 35: revision=1 map=0 area=5057 factionMask=0 minLevel=80 maxLevel=82 gap=5 knownLevel=1 preferFlight=0 nodeMask=-1 allowed=0
|
||||
TC> Area access GUID 35: revision=1 map=0 area=5057 factionMask=0 minLevel=80 maxLevel=82 gap=5 knownLevel=1 preferFlight=0 nodeMask=-1 allowed=0
|
||||
Native portal click sent: bot=36 spawn=211264 entry=206595. Check teleport completion and cast diagnostics.
|
||||
Native portal click sent: bot=36 spawn=211257 entry=207690. Check teleport completion and cast diagnostics.
|
||||
TC> Action GUID 35: state=Failed action='travel_to_node' target='' targetGuid=0 entry=0 detail='destination node denied by area/node catalog'
|
||||
[?2004hTC>Native portal click sent: bot=36 spawn=211264 entry=206595. Check teleport completion and cast diagnostics.
|
||||
[?2004hTC>Native portal click sent: bot=36 spawn=211264 entry=206595. Check teleport completion and cast diagnostics.
|
||||
Area access GUID 36: revision=1 map=0 area=5057 factionMask=0 minLevel=80 maxLevel=82 gap=5 knownLevel=1 preferFlight=0 nodeMask=3 allowed=0
|
||||
TC> Area access GUID 36: revision=1 map=0 area=5057 factionMask=0 minLevel=80 maxLevel=82 gap=5 knownLevel=1 preferFlight=0 nodeMask=3 allowed=0
|
||||
Action GUID 36: state=Failed action='travel_to_node' target='' targetGuid=0 entry=0 detail='destination node denied by area/node catalog'
|
||||
+218
@@ -0,0 +1,218 @@
|
||||
[
|
||||
{
|
||||
"spawn": 200624,
|
||||
"bot": 35,
|
||||
"at_source": true,
|
||||
"success": true,
|
||||
"actual": [
|
||||
1.0,
|
||||
5534.08,
|
||||
-3624.69,
|
||||
1567.04
|
||||
],
|
||||
"expected": [
|
||||
1.0,
|
||||
5534.08,
|
||||
-3624.69,
|
||||
1567.04
|
||||
]
|
||||
},
|
||||
{
|
||||
"spawn": 200625,
|
||||
"bot": 35,
|
||||
"at_source": true,
|
||||
"success": true,
|
||||
"actual": [
|
||||
646.0,
|
||||
974.921,
|
||||
566.768,
|
||||
-47.5163
|
||||
],
|
||||
"expected": [
|
||||
646.0,
|
||||
974.921,
|
||||
566.768,
|
||||
-47.5163
|
||||
]
|
||||
},
|
||||
{
|
||||
"spawn": 200626,
|
||||
"bot": 35,
|
||||
"at_source": true,
|
||||
"success": true,
|
||||
"actual": [
|
||||
1.0,
|
||||
-9443.31,
|
||||
-958.365,
|
||||
111.012
|
||||
],
|
||||
"expected": [
|
||||
1.0,
|
||||
-9443.31,
|
||||
-958.365,
|
||||
111.012
|
||||
]
|
||||
},
|
||||
{
|
||||
"spawn": 200627,
|
||||
"bot": 35,
|
||||
"at_source": true,
|
||||
"success": true,
|
||||
"actual": [
|
||||
0.0,
|
||||
-4890.07,
|
||||
-6626.74,
|
||||
10.2846
|
||||
],
|
||||
"expected": [
|
||||
0.0,
|
||||
-4890.07,
|
||||
-6626.74,
|
||||
10.2846
|
||||
]
|
||||
},
|
||||
{
|
||||
"spawn": 220365,
|
||||
"bot": 35,
|
||||
"at_source": true,
|
||||
"success": true,
|
||||
"actual": [
|
||||
732.0,
|
||||
-369.208,
|
||||
1058.73,
|
||||
21.7719
|
||||
],
|
||||
"expected": [
|
||||
732.0,
|
||||
-369.208,
|
||||
1058.73,
|
||||
21.7719
|
||||
]
|
||||
},
|
||||
{
|
||||
"spawn": 220366,
|
||||
"bot": 35,
|
||||
"at_source": true,
|
||||
"success": true,
|
||||
"actual": [
|
||||
0.0,
|
||||
-4570.29,
|
||||
3478.06,
|
||||
-101.809
|
||||
],
|
||||
"expected": [
|
||||
0.0,
|
||||
-4570.29,
|
||||
3478.06,
|
||||
-101.809
|
||||
]
|
||||
},
|
||||
{
|
||||
"spawn": 219028,
|
||||
"bot": 36,
|
||||
"at_source": true,
|
||||
"success": true,
|
||||
"actual": [
|
||||
1.0,
|
||||
5534.08,
|
||||
-3624.69,
|
||||
1567.04
|
||||
],
|
||||
"expected": [
|
||||
1.0,
|
||||
5534.08,
|
||||
-3624.69,
|
||||
1567.04
|
||||
]
|
||||
},
|
||||
{
|
||||
"spawn": 211258,
|
||||
"bot": 36,
|
||||
"at_source": true,
|
||||
"success": true,
|
||||
"actual": [
|
||||
646.0,
|
||||
995.808,
|
||||
471.879,
|
||||
-48.1172
|
||||
],
|
||||
"expected": [
|
||||
646.0,
|
||||
995.808,
|
||||
471.879,
|
||||
-48.1172
|
||||
]
|
||||
},
|
||||
{
|
||||
"spawn": 211259,
|
||||
"bot": 36,
|
||||
"at_source": true,
|
||||
"success": true,
|
||||
"actual": [
|
||||
1.0,
|
||||
-9443.31,
|
||||
-958.365,
|
||||
111.012
|
||||
],
|
||||
"expected": [
|
||||
1.0,
|
||||
-9443.31,
|
||||
-958.365,
|
||||
111.012
|
||||
]
|
||||
},
|
||||
{
|
||||
"spawn": 211260,
|
||||
"bot": 36,
|
||||
"at_source": true,
|
||||
"success": true,
|
||||
"actual": [
|
||||
0.0,
|
||||
-4032.79,
|
||||
-6318.53,
|
||||
38.6975
|
||||
],
|
||||
"expected": [
|
||||
0.0,
|
||||
-4032.79,
|
||||
-6318.53,
|
||||
38.6975
|
||||
]
|
||||
},
|
||||
{
|
||||
"spawn": 211264,
|
||||
"bot": 36,
|
||||
"at_source": true,
|
||||
"success": false,
|
||||
"actual": [
|
||||
1.0,
|
||||
2031.22,
|
||||
-4330.87,
|
||||
95.771
|
||||
],
|
||||
"expected": [
|
||||
732.0,
|
||||
-603.724,
|
||||
1387.62,
|
||||
22.0498
|
||||
]
|
||||
},
|
||||
{
|
||||
"spawn": 211257,
|
||||
"bot": 36,
|
||||
"at_source": true,
|
||||
"success": true,
|
||||
"actual": [
|
||||
0.0,
|
||||
-4570.29,
|
||||
3478.06,
|
||||
-101.809
|
||||
],
|
||||
"expected": [
|
||||
0.0,
|
||||
-4570.29,
|
||||
3478.06,
|
||||
-101.809
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,219 @@
|
||||
[
|
||||
{
|
||||
"spawn": 200624,
|
||||
"bot": 35,
|
||||
"at_source": true,
|
||||
"success": true,
|
||||
"actual": [
|
||||
1.0,
|
||||
5534.08,
|
||||
-3624.69,
|
||||
1567.04
|
||||
],
|
||||
"expected": [
|
||||
1.0,
|
||||
5534.08,
|
||||
-3624.69,
|
||||
1567.04
|
||||
]
|
||||
},
|
||||
{
|
||||
"spawn": 200625,
|
||||
"bot": 35,
|
||||
"at_source": true,
|
||||
"success": true,
|
||||
"actual": [
|
||||
646.0,
|
||||
974.921,
|
||||
566.768,
|
||||
-47.5163
|
||||
],
|
||||
"expected": [
|
||||
646.0,
|
||||
974.921,
|
||||
566.768,
|
||||
-47.5163
|
||||
]
|
||||
},
|
||||
{
|
||||
"spawn": 200626,
|
||||
"bot": 35,
|
||||
"at_source": true,
|
||||
"success": true,
|
||||
"actual": [
|
||||
1.0,
|
||||
-9443.31,
|
||||
-958.365,
|
||||
111.012
|
||||
],
|
||||
"expected": [
|
||||
1.0,
|
||||
-9443.31,
|
||||
-958.365,
|
||||
111.012
|
||||
]
|
||||
},
|
||||
{
|
||||
"spawn": 200627,
|
||||
"bot": 35,
|
||||
"at_source": true,
|
||||
"success": true,
|
||||
"actual": [
|
||||
0.0,
|
||||
-4890.07,
|
||||
-6626.74,
|
||||
10.2846
|
||||
],
|
||||
"expected": [
|
||||
0.0,
|
||||
-4890.07,
|
||||
-6626.74,
|
||||
10.2846
|
||||
]
|
||||
},
|
||||
{
|
||||
"spawn": 220365,
|
||||
"bot": 35,
|
||||
"at_source": true,
|
||||
"success": true,
|
||||
"actual": [
|
||||
732.0,
|
||||
-369.208,
|
||||
1058.73,
|
||||
21.7719
|
||||
],
|
||||
"expected": [
|
||||
732.0,
|
||||
-369.208,
|
||||
1058.73,
|
||||
21.7719
|
||||
]
|
||||
},
|
||||
{
|
||||
"spawn": 220366,
|
||||
"bot": 35,
|
||||
"at_source": true,
|
||||
"success": true,
|
||||
"actual": [
|
||||
0.0,
|
||||
-4570.29,
|
||||
3478.06,
|
||||
-101.809
|
||||
],
|
||||
"expected": [
|
||||
0.0,
|
||||
-4570.29,
|
||||
3478.06,
|
||||
-101.809
|
||||
]
|
||||
},
|
||||
{
|
||||
"spawn": 219028,
|
||||
"bot": 36,
|
||||
"at_source": true,
|
||||
"success": true,
|
||||
"actual": [
|
||||
1.0,
|
||||
5534.08,
|
||||
-3624.69,
|
||||
1567.04
|
||||
],
|
||||
"expected": [
|
||||
1.0,
|
||||
5534.08,
|
||||
-3624.69,
|
||||
1567.04
|
||||
]
|
||||
},
|
||||
{
|
||||
"spawn": 211258,
|
||||
"bot": 36,
|
||||
"at_source": true,
|
||||
"success": true,
|
||||
"actual": [
|
||||
646.0,
|
||||
995.808,
|
||||
471.879,
|
||||
-48.1172
|
||||
],
|
||||
"expected": [
|
||||
646.0,
|
||||
995.808,
|
||||
471.879,
|
||||
-48.1172
|
||||
]
|
||||
},
|
||||
{
|
||||
"spawn": 211259,
|
||||
"bot": 36,
|
||||
"at_source": true,
|
||||
"success": true,
|
||||
"actual": [
|
||||
1.0,
|
||||
-9443.31,
|
||||
-958.365,
|
||||
111.012
|
||||
],
|
||||
"expected": [
|
||||
1.0,
|
||||
-9443.31,
|
||||
-958.365,
|
||||
111.012
|
||||
]
|
||||
},
|
||||
{
|
||||
"spawn": 211260,
|
||||
"bot": 36,
|
||||
"at_source": true,
|
||||
"success": true,
|
||||
"actual": [
|
||||
0.0,
|
||||
-4032.79,
|
||||
-6318.53,
|
||||
38.6975
|
||||
],
|
||||
"expected": [
|
||||
0.0,
|
||||
-4032.79,
|
||||
-6318.53,
|
||||
38.6975
|
||||
]
|
||||
},
|
||||
{
|
||||
"spawn": 211264,
|
||||
"bot": 36,
|
||||
"at_source": true,
|
||||
"success": true,
|
||||
"actual": [
|
||||
732.0,
|
||||
-603.724,
|
||||
1387.62,
|
||||
22.0498
|
||||
],
|
||||
"expected": [
|
||||
732.0,
|
||||
-603.724,
|
||||
1387.62,
|
||||
22.0498
|
||||
],
|
||||
"retest": "native click after confirmed online state; visitor cast=1"
|
||||
},
|
||||
{
|
||||
"spawn": 211257,
|
||||
"bot": 36,
|
||||
"at_source": true,
|
||||
"success": true,
|
||||
"actual": [
|
||||
0.0,
|
||||
-4570.29,
|
||||
3478.06,
|
||||
-101.809
|
||||
],
|
||||
"expected": [
|
||||
0.0,
|
||||
-4570.29,
|
||||
3478.06,
|
||||
-101.809
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,19 @@
|
||||
Id Effect EffectAmplitude EffectAura EffectAuraPeriod EffectBasePoints EffectBonusCoefficient EffectChainAmplitude EffectChainTargets EffectDieSides EffectItemType EffectMechanic EffectMiscValue EffectMiscValueB EffectPointsPerResource EffectRadiusIndex EffectRadiusMaxIndex EffectRealPointsPerLevel EffectSpellClassMaskA EffectSpellClassMaskB EffectSpellClassMaskC EffectTriggerSpell EffectImplicitTargetA EffectImplicitTargetB SpellID EffectIndex Comment
|
||||
160117 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 25 17 90244 0 Orgrimmar Vashjir portal: fixed SmugglersScar landing
|
||||
160118 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 25 17 90245 0 Stormwind Vashjir portal: fixed SmugglersScar landing
|
||||
ID EffectIndex MapID PositionX PositionY PositionZ Orientation VerifiedBuild
|
||||
90244 0 0 -4570.29 3478.06 -101.809 5.62628 0
|
||||
90245 0 0 -4570.29 3478.06 -101.809 5.62628 0
|
||||
entry data6
|
||||
206594 0
|
||||
206595 1
|
||||
207686 0
|
||||
207687 0
|
||||
207688 0
|
||||
207689 0
|
||||
207690 1
|
||||
207691 1
|
||||
207692 0
|
||||
207693 0
|
||||
207694 0
|
||||
207695 0
|
||||
|
Whitespace-only changes.
|
|
@@ -0,0 +1,13 @@
|
||||
entry type data0 data6
|
||||
206594 22 88339 0
|
||||
206595 22 88341 0
|
||||
207686 22 82621 0
|
||||
207687 22 94564 0
|
||||
207688 22 94565 0
|
||||
207689 22 84513 0
|
||||
207690 22 90244 0
|
||||
207691 22 90245 0
|
||||
207692 22 94565 0
|
||||
207693 22 84515 0
|
||||
207694 22 85545 0
|
||||
207695 22 94564 0
|
||||
|
@@ -0,0 +1 @@
|
||||
Production area destination excludes outside and unreachable graph nodes.
|
||||
@@ -0,0 +1 @@
|
||||
Portal near/far ACK and denied same-map transfer regressions passed.
|
||||
@@ -0,0 +1,3 @@
|
||||
Interactive portal native click, near/far/global ACK, denial, timeout and target checks passed.
|
||||
Native portal destination discovery and unsupported/ambiguous spell rejection passed.
|
||||
Production clientless ACK completion sequence increments only after completed near/far transfers.
|
||||
@@ -0,0 +1,5 @@
|
||||
area_id map_id parent_area_id display_name allowed_factions min_level max_level max_level_gap prefer_flight notes
|
||||
4815 0 5146 Tang'tharwald NULL 80 82 NULL NULL
|
||||
5144 0 5146 Schimmernde Weiten NULL 80 82 NULL NULL
|
||||
5145 0 5146 Abyssische Tiefen NULL 80 82 NULL NULL
|
||||
5146 0 0 Vashj'ir 0 NULL NULL NULL NULL Vashjir closed to all AdventureBots, including child areas
|
||||
|
@@ -0,0 +1,41 @@
|
||||
# Stopped-vehicle fallback to the recorded deck stand
|
||||
|
||||
User authorized transferring a bot to the recorded onboard stand when its return
|
||||
navigation fails, exclusively while the vehicle is stopped. Implemented in
|
||||
ClientlessTransportDeckMgr for its supported Bravery/tram deck meshes.
|
||||
|
||||
Bord movement now starts with checked native MoveSplineInit::Launch rather than
|
||||
a void MotionMaster wrapper. Failed launch is not reported as a successful walk.
|
||||
The controller distinguishes return walks from initial deck outings. A failed
|
||||
path/launch, stopped-short return, timeout or departure-interrupted return sets
|
||||
a persistent return-failure flag. An insufficient walk budget defers the attempt
|
||||
and allows the same safe fallback once a sufficient stopped window exists.
|
||||
|
||||
At an arrival dock, a failed return can relocate only to the exact recorded local
|
||||
stand. The helper independently rechecks stopped state, same map, actual same
|
||||
transport attachment, alive/no combat/no pending teleport, finite bounded local
|
||||
coordinates, valid transformed world coordinates and remaining exit budget+1s.
|
||||
It stops the old spline, updates transport-local coordinates, calls the native
|
||||
passenger relocation and broadcasts movement state. It never removes/adds a
|
||||
passenger or changes vehicle/GUID. The normal reverse recorded exit then runs,
|
||||
subject to the existing AtDock recheck. No relocation during vehicle motion.
|
||||
|
||||
Tests: production controller and actual relocation helper against deterministic
|
||||
doubles; real WMO/M2 deck mesh tests; generic transport and grid-loading tests.
|
||||
Compile log /tmp/vcore-deck-return-build.log. Initial gameplay root cause behind
|
||||
Brynna's repeated return launches was not fully instrumented; checked launch and
|
||||
bounded fallback address this failure without claiming static passenger
|
||||
persistence across restart was repaired. Runtime deployment results appended
|
||||
below after installation.
|
||||
|
||||
## Installed state
|
||||
|
||||
Successful build and five focused tests. Installed after complete process exit;
|
||||
startup PID349322 undergdb in vcore-worldserver reached ready in13s and listens
|
||||
on8085/8087. Install log /tmp/vcore-deck-return-install.log; new console
|
||||
/tmp/vcore-deck-return-start-20261029.log. Prior known OutdoorPvP shutdown fault
|
||||
trace retained in the previous console. No native fallback occurrence observed
|
||||
yet and no manually forced trip/profile/position/plan change for this task.
|
||||
Native helper/control test logs /tmp/vcore-deck-return-helper-test.log and
|
||||
-control-test.log; real meshes/transport/grid logs share that prefix. Visual
|
||||
acceptance and actual fallback use remain unverified.
|
||||
@@ -0,0 +1,62 @@
|
||||
# Resume restored clientless transport passengers
|
||||
|
||||
Shanron140 retained native Bravery spawn2 attachment after restart but had no
|
||||
CPC ride state. The AdventureBot Lua controller now invokes ResumePassenger
|
||||
before supply/combat/intent actions while a restored exit is owned. Observation
|
||||
and population maintenance still run first. Active ordinary executor rides are
|
||||
never replaced. Dead/combat/pending teleport/taxi and unmanaged players are not
|
||||
adopted. Actual native attachment is required; no passenger is invented.
|
||||
|
||||
For an orphaned passenger, ensure stop and graph data are loaded; match a recorded
|
||||
stop to the actual native transport object/pointer, spawn and entry; enforce
|
||||
area/node/faction/level access. Seed a Resumed Riding record without reboarding,
|
||||
relocating, clearing schedules or changing attachments. Unrecorded/forbidden
|
||||
services are untouched. Failed ride records with an attached passenger can also
|
||||
be recovered this way.
|
||||
|
||||
While Riding, choose the first actual permitted recorded dock the vehicle stops
|
||||
at (deterministic node tie-break for coincident stops). Do not infer the original
|
||||
journey destination or force a detour back to the seed dock. Native AtDock checks
|
||||
map, position, heading and stopped state. Reuse deck return, stop-time budgets
|
||||
and the ordinary reversed recorded exit. No exit at subsequently denied stops.
|
||||
Native cross-map worldport ACK and transport copies retain the same service.
|
||||
The resumed controller keeps ownership through the land portion after passenger
|
||||
detachment, releasing it on Arrived/Failed so normal day planning can continue.
|
||||
Static tram passenger persistence itself is unchanged: this requires an actual
|
||||
restored/attached passenger, not merely a saved position in the tram tunnel.
|
||||
|
||||
Six focused tests passed: real transport methods now cover orphan adoption,
|
||||
no duplicate boarding, normal ride preservation, unmanaged/unknown/denied cases,
|
||||
first actual permitted dock, real exit completion, land-tail ownership and
|
||||
cross-map restored ships. Existing deck controller/native fallback/real mesh,
|
||||
transport grid and group travel tests also pass. Results
|
||||
/tmp/vcore-resumed-passenger-tests.json; final build log
|
||||
/tmp/vcore-transport-resume-final-build.log. Gameplay remains unverified until a
|
||||
later install/restart.
|
||||
|
||||
USER HOLD: the user is recording more routes. Do not install or restart now.
|
||||
Current running server349322 and its installed executable remain untouched;
|
||||
changes are source/build only. Existing uncommitted deck-return fallback work
|
||||
is preserved. No DB/profile/plan/action changes are required for this fix.
|
||||
|
||||
Final complete build succeeded (/tmp/vcore-transport-resume-final-build.log).
|
||||
Current server process349322 and installed executable timestamp21:00:04 were
|
||||
verified unchanged. Six test results remain successful, including the added
|
||||
land-tail check. Ready for later installation; user recording hold remains in
|
||||
force. No pending build processes or native gameplay verification.
|
||||
|
||||
## Deployment after recording hold release
|
||||
|
||||
User authorized installation/restart. Installed prepared build successfully,
|
||||
log /tmp/vcore-transport-resume-install.log. Fresh PID356681 undergdb/tmux,
|
||||
console /tmp/vcore-transport-resume-start-20261029.log. Freshready12s, process
|
||||
persistence and8085/8087 verified. Known old OutdoorPvP shutdown destructor
|
||||
fault captured before full old process exit. Source/config/DB untouched by deploy.
|
||||
|
||||
Native login140 requested to inspect Shanron. Core transport restoration failed
|
||||
for savedGUID2 and moved him to homebind before controller activation. He then
|
||||
arrived at restlocation poi_guard_111 and executed rest micros. No manual position,
|
||||
profile or dayplan override. The new resumed-attachment branch could not be live
|
||||
validated on him because actual attachment was absent; automated tests remain
|
||||
the verification of that branch. Core missing-transport restoration is separate.
|
||||
Earlier no-install notes above record the completed hold, not a current ban.
|
||||
@@ -0,0 +1,54 @@
|
||||
-- Empty Vashjir spells and the live-failing Orgrimmar Tol Barad portal
|
||||
-- cast as their visitor. Other casting modes/conditions/destinations stay.
|
||||
UPDATE gameobject_template SET data6=1
|
||||
WHERE entry IN(207690,207691,206595) AND type=22 AND data2=0 AND data6=0;
|
||||
|
||||
-- Two pre-existing server-only Vashj'ir spells had NO effects or destinations.
|
||||
-- Supply a direct native teleport to the project's existing SmugglersScar
|
||||
-- game_tele landing (existing named cave destination). This is an explicit fixed landing,
|
||||
-- not a reconstruction of quest-dependent retail destinations.
|
||||
INSERT IGNORE INTO spelleffect_dbc
|
||||
(Id,Effect,EffectImplicitTargetA,EffectImplicitTargetB,SpellID,EffectIndex,Comment)
|
||||
SELECT 160117,5,25,17,90244,0,'Orgrimmar Vashjir portal: fixed SmugglersScar landing'
|
||||
WHERE NOT EXISTS(SELECT 1 FROM spelleffect_dbc WHERE SpellID=90244 AND EffectIndex=0);
|
||||
INSERT IGNORE INTO spelleffect_dbc
|
||||
(Id,Effect,EffectImplicitTargetA,EffectImplicitTargetB,SpellID,EffectIndex,Comment)
|
||||
SELECT 160118,5,25,17,90245,0,'Stormwind Vashjir portal: fixed SmugglersScar landing'
|
||||
WHERE NOT EXISTS(SELECT 1 FROM spelleffect_dbc WHERE SpellID=90245 AND EffectIndex=0);
|
||||
INSERT IGNORE INTO spell_target_position
|
||||
(ID,EffectIndex,MapID,PositionX,PositionY,PositionZ,Orientation,VerifiedBuild)
|
||||
SELECT s.spell,0,t.map,t.position_x,t.position_y,t.position_z,t.orientation,0
|
||||
FROM (SELECT 90244 AS spell UNION ALL SELECT 90245) s
|
||||
JOIN game_tele t ON t.name='SmugglersScar';
|
||||
|
||||
-- Source faction permission is independent of destination region permission.
|
||||
-- In particular Vashjir stays forbidden by the unchanged area catalog.
|
||||
INSERT INTO vcore_clientless_node_access(node_key,allowed_factions,notes)
|
||||
SELECT CONCAT('portal_go_',g.guid,'_source'),IF(g.map=0,1,2),'Capital Cataclysm portal; destination area policy still applies'
|
||||
FROM gameobject g
|
||||
WHERE g.guid IN(200624,200625,200626,200627,220365,220366,211257,211258,211259,211260,211264,219028)
|
||||
ON DUPLICATE KEY UPDATE allowed_factions=VALUES(allowed_factions),notes=VALUES(notes);
|
||||
|
||||
-- Persist the same seed-only native bindings produced by portal object import.
|
||||
-- Existing enabled flags and manually adjusted graph positions are preserved.
|
||||
INSERT IGNORE INTO vcore_clientless_world_point
|
||||
(point_key,category,map,position_x,position_y,position_z,orientation,enabled,comment)
|
||||
SELECT CONCAT('portal_go_',g.guid,'_source'),'travel_portal',g.map,g.position_x,g.position_y,g.position_z,g.orientation,1,'Capital Cataclysm native portal source'
|
||||
FROM gameobject g WHERE g.guid IN(200624,200625,200626,200627,220365,220366,211257,211258,211259,211260,211264,219028);
|
||||
INSERT IGNORE INTO vcore_clientless_world_point
|
||||
(point_key,category,map,position_x,position_y,position_z,orientation,enabled,comment)
|
||||
SELECT CONCAT('portal_go_',g.guid,'_target'),'travel_portal',p.MapID,p.PositionX,p.PositionY,p.PositionZ,p.Orientation,1,'Capital Cataclysm native portal target'
|
||||
FROM gameobject g JOIN gameobject_template t ON t.entry=g.id JOIN spell_target_position p ON p.ID=t.data0 AND p.EffectIndex=0
|
||||
WHERE g.guid IN(200624,200625,200626,200627,220365,220366,211257,211258,211259,211260,211264,219028);
|
||||
INSERT IGNORE INTO vcore_clientless_travel_node(node_key,node_type,world_point_key,enabled,comment)
|
||||
SELECT p.point_key,'portal',p.point_key,1,'Capital Cataclysm native portal'
|
||||
FROM vcore_clientless_world_point p
|
||||
WHERE p.point_key REGEXP '^portal_go_(200624|200625|200626|200627|220365|220366|211257|211258|211259|211260|211264|219028)_(source|target)$';
|
||||
INSERT IGNORE INTO vcore_clientless_travel_edge(from_node_key,to_node_key,edge_type,cost,bidirectional,enabled,comment)
|
||||
SELECT CONCAT('portal_go_',g.guid,'_source'),CONCAT('portal_go_',g.guid,'_target'),'portal_use',1,0,1,'Capital Cataclysm native portal click'
|
||||
FROM gameobject g WHERE g.guid IN(200624,200625,200626,200627,220365,220366,211257,211258,211259,211260,211264,219028);
|
||||
INSERT IGNORE INTO vcore_clientless_portal_use(edge_id,gameobject_spawn_id,gameobject_entry,spell_id)
|
||||
SELECT e.id,g.guid,g.id,t.data0
|
||||
FROM gameobject g JOIN gameobject_template t ON t.entry=g.id
|
||||
JOIN vcore_clientless_travel_edge e ON e.from_node_key=CONCAT('portal_go_',g.guid,'_source') AND e.to_node_key=CONCAT('portal_go_',g.guid,'_target') AND e.edge_type='portal_use'
|
||||
WHERE g.guid IN(200624,200625,200626,200627,220365,220366,211257,211258,211259,211260,211264,219028);
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "ClientlessPlayerMgr.h"
|
||||
#include "ClientlessActionExecutorMgr.h"
|
||||
#include "ClientlessTravelMgr.h"
|
||||
#include "ClientlessTransportMgr.h"
|
||||
#include "AdventureBehaviorMgr.h"
|
||||
#include "AdventureCombatMgr.h"
|
||||
#include "AdventureInteractionMgr.h"
|
||||
@@ -235,6 +236,9 @@ public:
|
||||
sClientlessLuaEngine->UpdateWorldPresence(player,sAdventureBehaviorMgr->InteractionIntent(player));
|
||||
sAdventureGroupTravelMgr->Observe(player,diff);
|
||||
sAdventurePopulationMgr->Maintain(player,diff);
|
||||
// Restart restores native ship attachment, but CPC ride execution is
|
||||
// transient. Own its safe recorded exit before starting another action.
|
||||
if(sClientlessTransportMgr->ResumePassenger(player))return;
|
||||
if(sAdventureGroupTravelMgr->Airborne(player)){sAdventureGroupTravelMgr->Follow(player);return;}
|
||||
if(sAdventureSupplyMgr->Update(player,diff,sAdventureCombatMgr->Busy(player)))return;
|
||||
if(!sAdventureCombatMgr->Update(player,diff) && !sAdventureInteractionMgr->Update(player,diff))
|
||||
|
||||
@@ -10,6 +10,9 @@
|
||||
#include "MoveSplineInit.h"
|
||||
#include "Chat.h"
|
||||
#include "Log.h"
|
||||
#include "VehicleDefines.h"
|
||||
#include "WorldPacket.h"
|
||||
#include "Opcodes.h"
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <unordered_map>
|
||||
@@ -22,7 +25,7 @@ std::unordered_map<uint32,Model> Models;
|
||||
struct Passenger
|
||||
{
|
||||
ObjectGuid Transport;
|
||||
bool Tried=false,Moving=false,Reserved=false;
|
||||
bool Tried=false,Moving=false,Reserved=false,Returning=false,ReturnFailed=false;
|
||||
Point Target{};
|
||||
time_t Deadline=0;
|
||||
};
|
||||
@@ -61,18 +64,46 @@ Model* Get(uint32 entry)
|
||||
TC_LOG_INFO("server.adventurebot.navigation","DECK_MESH entry=%u polygons=%u error='%s'",entry,model.Mesh.Polygons(),model.Error.c_str());
|
||||
return &model;
|
||||
}
|
||||
void Launch(Player* player,Passenger& state,std::vector<Point> const& path)
|
||||
bool Launch(Player* player,Passenger& state,std::vector<Point> const& path)
|
||||
{
|
||||
Movement::PointsArray points;
|
||||
// Already in transport coordinates; never transform these a second time.
|
||||
for(auto const& p:path)points.emplace_back(p[0],p[1],p[2]);
|
||||
Movement::MoveSplineInit init(player);init.DisableTransportPathTransformations();
|
||||
init.MovebyPath(points);init.SetWalk(true);init.SetVelocity(2.0f);
|
||||
player->GetMotionMaster()->LaunchMoveSpline(std::move(init));
|
||||
if(init.Launch()<=0)
|
||||
{state.Moving=false;return false;}
|
||||
state.Moving=true;state.Target=path.back();
|
||||
state.Deadline=GameTime::GetGameTime()+time_t(std::ceil(Length(path)/2.0f))+5;
|
||||
TC_LOG_INFO("server.adventurebot.navigation","DECK_WALK guid=%u points=%u length=%.2f target=(%.3f %.3f %.3f)",
|
||||
player->GetGUID().GetCounter(),uint32(path.size()),Length(path),state.Target[0],state.Target[1],state.Target[2]);
|
||||
return true;
|
||||
}
|
||||
bool ReturnToRecordedStand(Player* player,GameObject* object,Position const& anchor,uint32 exitBudget)
|
||||
{
|
||||
TransportDockState dock;
|
||||
auto transport=object->ToTransportBase();
|
||||
if(!transport || player->GetTransport()!=transport || !player->IsAlive() || player->IsInCombat() ||
|
||||
player->IsBeingTeleported() || player->GetMap()!=object->GetMap() ||
|
||||
!object->GetTransportDockState(dock) || !dock.Stopped || uint64(dock.RemainingPause)<uint64(exitBudget)+1000)return false;
|
||||
float x=anchor.GetPositionX(),y=anchor.GetPositionY(),z=anchor.GetPositionZ(),o=anchor.GetOrientation();
|
||||
if(!std::isfinite(x) || !std::isfinite(y) || !std::isfinite(z) ||
|
||||
std::fabs(x)>100 || std::fabs(y)>100 || std::fabs(z)>100)return false;
|
||||
transport->CalculatePassengerPosition(x,y,z,&o);
|
||||
if(!Trinity::IsValidMapCoord(x,y,z,o))return false;
|
||||
player->StopMoving();
|
||||
// Preserve the real passenger attachment and its transport GUID. Change
|
||||
// only its local position, then use native passenger relocation/broadcast.
|
||||
player->m_movementInfo.transport.pos.Relocate(anchor);
|
||||
transport->UpdatePassengerPosition(object->GetMap(),player,x,y,z,o,false);
|
||||
player->m_movementInfo.guid=player->GetGUID();
|
||||
player->m_movementInfo.pos.Relocate(player->GetPosition());
|
||||
player->m_movementInfo.time=GameTime::GetGameTimeMS();
|
||||
WorldPacket update(SMSG_MOVE_UPDATE);player->WriteMovementInfo(update);
|
||||
player->SendMessageToSet(&update,true);
|
||||
TC_LOG_WARN("server.adventurebot.navigation","DECK_RETURN_FALLBACK guid=%u entry=%u local=(%.3f %.3f %.3f)",
|
||||
player->GetGUID().GetCounter(),object->GetEntry(),anchor.GetPositionX(),anchor.GetPositionY(),anchor.GetPositionZ());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
void ClientlessTransportDeckMgr::Clear(uint32 guid){Passengers.erase(guid);}
|
||||
@@ -87,28 +118,45 @@ bool ClientlessTransportDeckMgr::Update(Player* player,GameObject* object,Positi
|
||||
Point current=Local(player);
|
||||
if(!stopped || !player->IsAlive() || player->IsInCombat())
|
||||
{
|
||||
if(state.Moving){player->StopMoving();state.Moving=false;state.Reserved=false;}
|
||||
if(state.Moving){player->StopMoving();state.ReturnFailed|=state.Returning;state.Moving=false;state.Reserved=false;}
|
||||
return false;
|
||||
}
|
||||
if(state.Moving)
|
||||
{
|
||||
// Every active walk retains a reserve before departure, even after a lag spike.
|
||||
if(dock.RemainingPause<1500 || GameTime::GetGameTime()>state.Deadline)
|
||||
{player->StopMoving();state.Moving=false;state.Reserved=false;return false;}
|
||||
if(player->IsSplineEnabled())return false;
|
||||
{
|
||||
player->StopMoving();state.Moving=false;state.Reserved=false;
|
||||
state.ReturnFailed|=state.Returning;
|
||||
if(!state.Returning)return false;
|
||||
}
|
||||
else if(player->IsSplineEnabled())return false;
|
||||
state.Moving=false;
|
||||
if(Distance(current,state.Target)>0.8f){state.Reserved=false;return false;}
|
||||
if(Distance(current,state.Target)>0.8f)
|
||||
{state.Reserved=false;state.ReturnFailed|=state.Returning;if(!state.Returning)return false;}
|
||||
}
|
||||
Point anchor{exitAnchor.GetPositionX(),exitAnchor.GetPositionY(),exitAnchor.GetPositionZ()};
|
||||
if(arriving)
|
||||
{
|
||||
state.Reserved=false;
|
||||
if(Distance(current,anchor)<=0.65f)return dock.RemainingPause>=exitBudget;
|
||||
if(Distance(current,anchor)<=0.65f){state.ReturnFailed=false;return dock.RemainingPause>=exitBudget;}
|
||||
if(state.ReturnFailed)
|
||||
{
|
||||
if(!ReturnToRecordedStand(player,object,exitAnchor,exitBudget))return false;
|
||||
state.Moving=state.Returning=state.ReturnFailed=false;return true;
|
||||
}
|
||||
std::vector<Point> path;
|
||||
if(!model->Mesh.Path(current,anchor,path))return false; // remain attached, never cut across the deck
|
||||
if(!model->Mesh.Path(current,anchor,path) || path.size()<2)
|
||||
{
|
||||
state.ReturnFailed=true;
|
||||
if(!ReturnToRecordedStand(player,object,exitAnchor,exitBudget))return false;
|
||||
state.ReturnFailed=false;return true;
|
||||
}
|
||||
uint64 budget=uint64(std::ceil(Length(path)/2.0f)*1000)+exitBudget+2000;
|
||||
if(path.size()<2 || dock.RemainingPause<budget)return false;
|
||||
Launch(player,state,path);return false;
|
||||
if(dock.RemainingPause<budget){state.ReturnFailed=true;return false;}
|
||||
state.Returning=true;
|
||||
if(!Launch(player,state,path))state.ReturnFailed=true;
|
||||
return false;
|
||||
}
|
||||
if(state.Tried)return false;
|
||||
state.Tried=true;
|
||||
@@ -141,7 +189,7 @@ bool ClientlessTransportDeckMgr::Update(Player* player,GameObject* object,Positi
|
||||
if(clearance>=1.5f && score>bestScore){bestScore=score;best=std::move(path);}
|
||||
}
|
||||
if(!best.empty())
|
||||
{Launch(player,state,best);state.Reserved=true;}
|
||||
{state.Returning=false;if(Launch(player,state,best))state.Reserved=true;}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -415,6 +415,56 @@ bool ClientlessTransportMgr::Start(Player* player, std::string const& from, std:
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ClientlessTransportMgr::ResumePassenger(Player* player)
|
||||
{
|
||||
if(!player || !player->IsInWorld() || !sClientlessPlayerMgr->IsManaged(player->GetGUID().GetCounter()) ||
|
||||
!player->IsAlive() || player->IsInCombat() || player->IsBeingTeleported() || player->IsInFlight())return false;
|
||||
uint32 guid=player->GetGUID().GetCounter();auto existing=_rides.find(guid);
|
||||
if(existing!=_rides.end() && existing->second.Status.Phase!=ClientlessTransportPhase::Arrived &&
|
||||
existing->second.Status.Phase!=ClientlessTransportPhase::Failed)
|
||||
return existing->second.Resumed; // never replace a normal executor-owned ride
|
||||
if(!player->GetTransport() || !EnsureLoaded() || !sClientlessTravelGraphMgr->EnsureLoaded())return false;
|
||||
ClientlessTransportStop const* source=nullptr;
|
||||
for(auto const& entry:_stops)
|
||||
{
|
||||
auto const& stop=entry.second;
|
||||
auto object=FindObject(player,stop);
|
||||
auto node=sClientlessTravelGraphMgr->FindNode(stop.Node);
|
||||
if(!object || object->ToTransportBase()!=player->GetTransport() || !node ||
|
||||
!sAdventureAreaMgr->AllowsNode(player,*node))continue;
|
||||
if(!source || stop.Node<source->Node)source=&stop;
|
||||
}
|
||||
if(!source)return false; // unknown vehicles and forbidden stops retain their owner
|
||||
Ride ride;ride.From=ride.To=*source;ride.Resumed=true;
|
||||
ride.Status.Phase=ClientlessTransportPhase::Riding;
|
||||
ride.Status.Detail="restored passenger; waiting for a permitted recorded dock";
|
||||
ClientlessTransportDeckMgr::Clear(guid);
|
||||
_rides[guid]=std::move(ride);
|
||||
TC_LOG_INFO("server.adventurebot.navigation","TRANSPORT_RESUME guid=%u spawn=%u entry=%u",guid,source->Spawn,source->Entry);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ClientlessTransportMgr::SelectResumedDock(Player* player,GameObject* object,Ride& ride)
|
||||
{
|
||||
if(!ride.Resumed || !object || player->GetTransport()!=object->ToTransportBase())return false;
|
||||
ClientlessTransportStop const* chosen=nullptr;
|
||||
for(auto const& entry:_stops)
|
||||
{
|
||||
auto const& stop=entry.second;
|
||||
auto node=sClientlessTravelGraphMgr->FindNode(stop.Node);
|
||||
if(!SameService(ride.From,stop) || !node || !sAdventureAreaMgr->AllowsNode(player,*node) ||
|
||||
!AtDock(player,object,stop,0))continue;
|
||||
if(!chosen || stop.Node<chosen->Node)chosen=&stop;
|
||||
}
|
||||
if(!chosen)return false;
|
||||
if(ride.From.Node!=chosen->Node || ride.To.Node!=chosen->Node)
|
||||
{
|
||||
TC_LOG_INFO("server.adventurebot.navigation","TRANSPORT_RESUME_DOCK guid=%u node='%s'",player->GetGUID().GetCounter(),chosen->Node.c_str());
|
||||
ride.From=ride.To=*chosen;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
ClientlessTransportStatus const* ClientlessTransportMgr::GetStatus(uint32 guid) const
|
||||
{
|
||||
auto itr = _rides.find(guid);
|
||||
@@ -524,9 +574,10 @@ void ClientlessTransportMgr::UpdateRide(Player* player, Ride& ride, uint32 diff)
|
||||
}
|
||||
fail("transport passenger identity changed; attachment retained");return;
|
||||
}
|
||||
bool permittedArrival=!ride.Resumed || SelectResumedDock(player,object,ride);
|
||||
ClientlessTransportStop const* arrival = nullptr;
|
||||
if (AtDock(player, object, ride.To, 0)) arrival = &ride.To;
|
||||
else if (ride.Abort && AtDock(player, object, ride.From, 0)) arrival = &ride.From;
|
||||
if (permittedArrival && AtDock(player, object, ride.To, 0)) arrival = &ride.To;
|
||||
else if (!ride.Resumed && ride.Abort && AtDock(player, object, ride.From, 0)) arrival = &ride.From;
|
||||
auto const& exit = arrival ? *arrival : ride.From;
|
||||
uint32 exitBudget=uint32(PathLength(exit)/std::max(1.0f,player->GetSpeed(MOVE_RUN))*1000)+uint32(exit.Points.size())*100+1500;
|
||||
bool ready=ClientlessTransportDeckMgr::Update(player,object,exit.Points.back().Pos,arrival!=nullptr,exitBudget);
|
||||
|
||||
@@ -54,6 +54,8 @@ public:
|
||||
bool ArrivalNode(Player* player, std::string const& from, std::string& to);
|
||||
ClientlessTransportStop const* GetStop(std::string const& node);
|
||||
bool Start(Player* player, std::string const& from, std::string const& to, std::string& error);
|
||||
// Returns true while a restored passenger is owned by its resumed exit.
|
||||
bool ResumePassenger(Player* player);
|
||||
ClientlessTransportStatus const* GetStatus(uint32 guid) const;
|
||||
void Cancel(uint32 guid);
|
||||
void Update(uint32 diff);
|
||||
@@ -81,6 +83,7 @@ private:
|
||||
uint32 PointTimeout = 0;
|
||||
bool Moving = false;
|
||||
bool Abort = false;
|
||||
bool Resumed = false;
|
||||
uint32 RecoveryMs = 0, Recoveries = 0;
|
||||
bool RecoveryMoving = false;
|
||||
uint8 WaitStage=0; // 0 node, 1 walking out, 2 waiting, 3 returning
|
||||
@@ -92,6 +95,7 @@ private:
|
||||
bool Save(Player* player, std::string const& stand, std::string& error);
|
||||
void UpdateRide(Player* player, Ride& ride, uint32 diff);
|
||||
void RecoverPassenger(Player* player, Ride& ride, uint32 diff);
|
||||
bool SelectResumedDock(Player* player, GameObject* object, Ride& ride);
|
||||
void SetPhase(Player* player, Ride& ride, ClientlessTransportPhase phase, char const* detail);
|
||||
GameObject* FindObject(Player* player, ClientlessTransportStop const& stop) const;
|
||||
bool AtDock(Player* player, GameObject* object, ClientlessTransportStop const& stop, uint32 requiredPause) const;
|
||||
|
||||
@@ -97,9 +97,10 @@ public:
|
||||
float GetSpeed(int)const{return 7;}void StopMoving(){}bool IsSplineEnabled()const{return false;}
|
||||
Motion* GetMotionMaster(){return &motion;}Session* GetSession(){return &session;}
|
||||
};
|
||||
struct Node{} node;
|
||||
struct Graph{Node* FindNode(std::string const&){return &node;}}graph;auto sClientlessTravelGraphMgr=&graph;
|
||||
struct AreaAccess{bool allowed=true;bool Applies(Player*){return true;}bool AllowsNode(Player*,Node const&){return allowed;}}areas;auto sAdventureAreaMgr=&areas;
|
||||
struct Node{std::string Key;} node;
|
||||
struct Graph{unsigned loads=0;bool EnsureLoaded(){++loads;return true;}Node* FindNode(std::string const&key){node.Key=key;return &node;}}graph;auto sClientlessTravelGraphMgr=&graph;
|
||||
struct Core{bool managed=true;bool IsManaged(unsigned){return managed;}}clientless;auto sClientlessPlayerMgr=&clientless;
|
||||
struct AreaAccess{std::string denied;bool allowed=true;bool Applies(Player*){return true;}bool AllowsNode(Player*,Node const&n){return allowed&&n.Key!=denied;}}areas;auto sAdventureAreaMgr=&areas;
|
||||
namespace ClientlessTransportDeckMgr {bool ready=true;int calls=0;void Clear(uint32){} bool Update(Player*,GameObject*,Position const&,bool,uint32){++calls;return ready;}}
|
||||
namespace ClientlessPositioning{bool available=false;bool Nearby(Player*p,Position const&,float,Position&spot,std::vector<Position>&path){if(!available)return false;spot=*p;spot.x+=2;path={*p,spot};return true;}}
|
||||
void TransportBase::CalculatePassengerPosition(float&x,float&y,float&z,float*o)const{CalculatePassengerPosition(x,y,z,o,go->x,go->y,go->z,go->o);}
|
||||
@@ -130,6 +131,7 @@ helpers = '\n'.join(function(source, marker) for marker in [
|
||||
' float Distance(', ' bool SameService(', ' bool LoadNode(', ' Position WorldPoint(', ' float PathLength('
|
||||
])
|
||||
methods = '\n'.join(function(source, marker) for marker in [
|
||||
'bool ClientlessTransportMgr::ResumePassenger(', 'bool ClientlessTransportMgr::SelectResumedDock(',
|
||||
'bool ClientlessTransportMgr::HasConnection(', 'bool ClientlessTransportMgr::AtDock(',
|
||||
'bool ClientlessTransportMgr::Sample(', 'bool ClientlessTransportMgr::Start(',
|
||||
'void ClientlessTransportMgr::SetPhase(', 'void ClientlessTransportMgr::Cancel(',
|
||||
@@ -243,6 +245,41 @@ int main(){
|
||||
ClientlessPositioning::available=false;
|
||||
Player denied;denied.object=&dock;areas.allowed=false;
|
||||
assert(!mgr.Start(&denied,"A","B",error));areas.allowed=true;
|
||||
// Restored attachment without transient CPC state is adopted, never reboarded.
|
||||
ClientlessTransportMgr resumed;resumed._stops["A"]=stop("A",5,0);resumed._stops["B"]=stop("B",100,104);
|
||||
Player orphan;GameObject vessel;vessel.x=50;vessel.state.Stopped=false;orphan.object=&vessel;orphan.x=51;
|
||||
vessel.base.AddPassenger(&orphan);orphan.m_movementInfo.transport.pos.x=1;
|
||||
assert(resumed.ResumePassenger(&orphan));auto& adopted=resumed._rides.at(26);
|
||||
assert(adopted.Resumed&&adopted.Status.Phase==Phase::Riding&&orphan.teleports==0&&graph.loads>0);
|
||||
run(resumed,orphan,adopted);assert(orphan.transport==&vessel.base&&adopted.Status.Phase==Phase::Riding);
|
||||
// B is the first actual permitted stop, even though seed A was selected.
|
||||
vessel.x=100;vessel.state.Stopped=true;orphan.x=101;
|
||||
resumed.UpdateRide(&orphan,adopted,100);assert(adopted.To.Node=="B");
|
||||
assert(resumed.ResumePassenger(&orphan));run(resumed,orphan,adopted);
|
||||
assert(adopted.Status.Phase==Phase::Arrived&&!orphan.transport&&orphan.x==104);
|
||||
assert(!resumed.ResumePassenger(&orphan));
|
||||
// After detachment the remaining land transition still owns the bot until done.
|
||||
adopted.Status.Phase=Phase::Leaving;assert(resumed.ResumePassenger(&orphan));
|
||||
adopted.Status.Phase=Phase::Arrived;assert(!resumed.ResumePassenger(&orphan));
|
||||
// Existing normal rides are never replaced by passenger adoption.
|
||||
vessel.x=5;orphan.x=0;assert(resumed.Start(&orphan,"A","B",error));run(resumed,orphan,resumed._rides.at(26));
|
||||
assert(!resumed.ResumePassenger(&orphan)&&!resumed._rides.at(26).Resumed);
|
||||
// Unknown vehicles, unmanaged players and entirely forbidden services are untouched.
|
||||
resumed._rides.clear();clientless.managed=false;assert(!resumed.ResumePassenger(&orphan));clientless.managed=true;
|
||||
vessel.spawn=99;assert(!resumed.ResumePassenger(&orphan));vessel.spawn=1;
|
||||
areas.allowed=false;assert(!resumed.ResumePassenger(&orphan));areas.allowed=true;
|
||||
// An adopted passenger must not leave at a subsequently forbidden dock.
|
||||
vessel.x=50;orphan.x=51;assert(resumed.ResumePassenger(&orphan));areas.denied="B";
|
||||
vessel.x=100;orphan.x=101;run(resumed,orphan,resumed._rides.at(26));assert(orphan.transport);
|
||||
areas.denied.clear();run(resumed,orphan,resumed._rides.at(26));assert(!orphan.transport&&orphan.x==104);
|
||||
// Native cross-map ship restoration keeps the same service after worldport ACK.
|
||||
resumed._rides.clear();resumed._stops["A"].Map=1;
|
||||
GameObject copy1;copy1.map=1;copy1.x=50;copy1.state.Stopped=false;
|
||||
orphan.map=1;orphan.object=©1;copy1.base.AddPassenger(&orphan);orphan.x=51;
|
||||
assert(resumed.ResumePassenger(&orphan));run(resumed,orphan,resumed._rides.at(26));assert(orphan.transport);
|
||||
copy1.base.RemovePassenger(&orphan);orphan.map=0;orphan.object=&vessel;vessel.x=100;
|
||||
vessel.base.AddPassenger(&orphan);orphan.x=101;orphan.m_movementInfo.transport.pos.x=1;
|
||||
run(resumed,orphan,resumed._rides.at(26));assert(!orphan.transport&&orphan.map==0&&orphan.x==104);
|
||||
std::cout<<"Transport dock, frame, recorder, cross-map copy and ride regressions passed\n";
|
||||
}
|
||||
'''
|
||||
|
||||
@@ -25,7 +25,7 @@ struct Player{Point current{0,0,0};unsigned id=1;bool spline=false,alive=true,co
|
||||
Guid GetGUID(){return {id};}bool IsAlive(){return alive;}bool IsInCombat(){return combat;}bool IsSplineEnabled(){return spline;}
|
||||
void StopMoving(){++stops;spline=false;}void* GetTransport(){return transport;}void GetPlayerListInGrid(std::list<Player*>&,int){} void GetCreatureListWithEntryInGrid(std::list<Creature*>&,int,int){}};
|
||||
struct Creature:Player{};
|
||||
struct Passenger{unsigned Transport=0;bool Tried=false,Moving=false,Reserved=false;Point Target{};time_t Deadline=0;};
|
||||
struct Passenger{unsigned Transport=0;bool Tried=false,Moving=false,Reserved=false,Returning=false,ReturnFailed=false;Point Target{};time_t Deadline=0;};
|
||||
std::unordered_map<unsigned,Passenger> Passengers;
|
||||
float Distance(Point const&a,Point const&b){return std::sqrt(std::pow(a[0]-b[0],2)+std::pow(a[1]-b[1],2)+std::pow(a[2]-b[2],2));}
|
||||
Point Local(Player*p){return p->current;}float Length(std::vector<Point>const&path){float n=0;for(unsigned i=1;i<path.size();++i)n+=Distance(path[i-1],path[i]);return n;}
|
||||
@@ -33,8 +33,12 @@ struct Mesh{bool blocked=false;unsigned Polygons(){return 50;}bool Path(Point co
|
||||
struct Model{Mesh Mesh;}model;
|
||||
Model* Get(unsigned entry){return entry==176310?&model:nullptr;}
|
||||
namespace GameTime{time_t now=100;time_t GetGameTime(){return now;}}
|
||||
int launches=0;
|
||||
void Launch(Player*p,Passenger&s,std::vector<Point>const&path){++launches;p->spline=true;s.Moving=true;s.Target=path.back();s.Deadline=GameTime::now+20;}
|
||||
int launches=0;bool launchOK=true;
|
||||
bool Launch(Player*p,Passenger&s,std::vector<Point>const&path){++launches;if(!launchOK)return false;p->spline=true;s.Moving=true;s.Target=path.back();s.Deadline=GameTime::now+20;return true;}
|
||||
unsigned fallback=0;
|
||||
bool ReturnToRecordedStand(Player*p,GameObject*go,Position const&a,unsigned budget){
|
||||
if(!go->dock.Stopped||go->dock.RemainingPause<budget+1000||!p->alive||p->combat||p->transport!=go)return false;
|
||||
++fallback;p->current={a.x,a.y,a.z};return true;}
|
||||
namespace ClientlessTransportDeckMgr{bool Update(Player*,GameObject*,Position const&,bool,uint32);}
|
||||
'''+s[a:b]+r'''
|
||||
int main(){Player p;Position anchor;
|
||||
@@ -50,12 +54,20 @@ int main(){Player p;Position anchor;
|
||||
// Arriving at the next dock starts a real return, provided it fits the halt.
|
||||
p.current={4,0,0};object.dock.Stopped=true;object.dock.RemainingPause=6000;
|
||||
assert(!ClientlessTransportDeckMgr::Update(&p,&object,anchor,true,5000));assert(launches==1);
|
||||
object.dock.RemainingPause=60000;assert(!ClientlessTransportDeckMgr::Update(&p,&object,anchor,true,5000));assert(launches==2);
|
||||
Passengers[1].ReturnFailed=false;object.dock.RemainingPause=60000;assert(!ClientlessTransportDeckMgr::Update(&p,&object,anchor,true,5000));assert(launches==2);
|
||||
assert(!ClientlessTransportDeckMgr::Update(&p,&object,anchor,true,5000)); // still moving
|
||||
p.spline=false;p.current={0,0,0};assert(ClientlessTransportDeckMgr::Update(&p,&object,anchor,true,5000));
|
||||
// Interrupted arrival never claims the exit anchor was reached.
|
||||
p.current={4,0,0};model.Mesh.blocked=true;assert(!ClientlessTransportDeckMgr::Update(&p,&object,anchor,true,5000));assert(launches==2);
|
||||
model.Mesh.blocked=false;p.combat=true;assert(!ClientlessTransportDeckMgr::Update(&p,&object,anchor,true,5000));p.combat=false;
|
||||
// A failed arrival path may transfer to the exact recorded local anchor, preserving attachment.
|
||||
p.current={4,0,0};model.Mesh.blocked=true;assert(ClientlessTransportDeckMgr::Update(&p,&object,anchor,true,5000));assert(launches==2&&fallback==1&&p.transport==&object);
|
||||
// Repeated interrupted return is bounded and uses the fallback at a stopped dock.
|
||||
model.Mesh.blocked=false;p.current={4,0,0};Passengers[1].Moving=Passengers[1].Returning=true;
|
||||
Passengers[1].Target={0,0,0};Passengers[1].Deadline=200;p.spline=false;
|
||||
assert(ClientlessTransportDeckMgr::Update(&p,&object,anchor,true,5000)&&fallback==2);
|
||||
object.dock.Stopped=false;p.current={4,0,0};Passengers[1].ReturnFailed=true;
|
||||
assert(!ClientlessTransportDeckMgr::Update(&p,&object,anchor,true,5000)&&fallback==2);
|
||||
object.dock.Stopped=true;object.dock.RemainingPause=5500;
|
||||
assert(!ClientlessTransportDeckMgr::Update(&p,&object,anchor,true,5000)&&fallback==2);
|
||||
object.dock.RemainingPause=60000;p.combat=true;assert(!ClientlessTransportDeckMgr::Update(&p,&object,anchor,true,5000));p.combat=false;
|
||||
Passengers.clear();p.current={0,0,0};p.spline=false;launches=0;
|
||||
ClientlessTransportDeckMgr::Update(&p,&object,anchor,false,5000);Point first=Passengers[1].Target;
|
||||
Player other;other.id=2;ClientlessTransportDeckMgr::Update(&other,&object,anchor,false,5000);
|
||||
@@ -63,6 +75,10 @@ int main(){Player p;Position anchor;
|
||||
// Near departure, a running walk is stopped on the deck.
|
||||
object.dock.RemainingPause=1000;assert(!ClientlessTransportDeckMgr::Update(&p,&object,anchor,false,5000));assert(!p.spline);
|
||||
object.entry=999;assert(ClientlessTransportDeckMgr::Update(&p,&object,anchor,true,5000));
|
||||
Passengers.clear();object.entry=176310;object.dock.RemainingPause=60000;
|
||||
p.current={4,0,0};p.spline=false;launchOK=false;auto before=fallback;
|
||||
assert(!ClientlessTransportDeckMgr::Update(&p,&object,anchor,true,5000)&&Passengers[1].ReturnFailed);
|
||||
assert(ClientlessTransportDeckMgr::Update(&p,&object,anchor,true,5000)&&fallback==before+1);
|
||||
std::cout<<"Production deck controller: halt budgets, departure interruption, return-before-exit, blocked paths and reservations passed\n";
|
||||
}
|
||||
'''
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
"""Run the native recorded-stand fallback with deterministic passenger relocation."""
|
||||
from pathlib import Path
|
||||
import subprocess,tempfile
|
||||
root=Path(__file__).resolve().parents[2]
|
||||
s=(root/'src/server/game/World/ClientlessTransportDeckMgr.cpp').read_text();a=s.index('bool ReturnToRecordedStand(');b=s.index('\n}\nvoid ClientlessTransportDeckMgr::Clear',a)
|
||||
code=r'''
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
using uint32=unsigned;using uint64=unsigned long long;
|
||||
#define TC_LOG_WARN(...) ((void)0)
|
||||
constexpr int SMSG_MOVE_UPDATE=1;
|
||||
struct Position{float x=0,y=0,z=0,o=0;float GetPositionX()const{return x;}float GetPositionY()const{return y;}float GetPositionZ()const{return z;}float GetOrientation()const{return o;}void Relocate(Position const&p){*this=p;}};
|
||||
struct Guid{unsigned GetCounter(){return 120;}};
|
||||
struct WorldPacket{explicit WorldPacket(int){}};
|
||||
namespace GameTime{unsigned GetGameTimeMS(){return 123;}}
|
||||
namespace Trinity{bool IsValidMapCoord(float x,float y,float z,float o){return std::isfinite(x)&&std::isfinite(y)&&std::isfinite(z)&&std::isfinite(o)&&std::fabs(x)<17000;}}
|
||||
struct Player;struct Transport{
|
||||
unsigned relocations=0;void CalculatePassengerPosition(float&x,float&y,float&z,float*){x+=100;y+=200;z+=300;}
|
||||
void UpdatePassengerPosition(int*,Player*,float,float,float,float,bool);
|
||||
}transport;
|
||||
int map;
|
||||
struct Player:Position{bool alive=true,combat=false,teleport=false;int*world=↦Transport*attached=&transport;unsigned stops=0,updates=0;
|
||||
struct{Guid guid;Position pos;unsigned time=0;struct{Position pos;unsigned guid=42;}transport;}m_movementInfo;
|
||||
bool IsAlive(){return alive;}bool IsInCombat(){return combat;}bool IsBeingTeleported(){return teleport;}
|
||||
Transport*GetTransport(){return attached;}int*GetMap(){return world;}Guid GetGUID(){return {};}
|
||||
void StopMoving(){++stops;}Position GetPosition(){return *this;}
|
||||
void WriteMovementInfo(WorldPacket&){assert(m_movementInfo.transport.guid==42);}
|
||||
void SendMessageToSet(WorldPacket*,bool){++updates;}
|
||||
};
|
||||
void Transport::UpdatePassengerPosition(int*,Player*p,float x,float y,float z,float o,bool){++relocations;p->x=x;p->y=y;p->z=z;p->o=o;}
|
||||
struct TransportDockState{bool Stopped=true;unsigned RemainingPause=10000;};
|
||||
struct GameObject{TransportDockState dock;bool valid=true;Transport*ToTransportBase(){return valid?&transport:nullptr;}int*GetMap(){return ↦}bool GetTransportDockState(TransportDockState&d){d=dock;return true;}unsigned GetEntry(){return 176081;}}object;
|
||||
'''+s[a:b]+r'''
|
||||
int main(){
|
||||
Player p;Position anchor{2,-3,-10,0};
|
||||
assert(ReturnToRecordedStand(&p,&object,anchor,5000));
|
||||
assert(p.attached==&transport&&transport.relocations==1&&p.updates==1&&p.stops==1);
|
||||
assert(p.m_movementInfo.transport.pos.x==2&&p.m_movementInfo.transport.pos.z==-10);
|
||||
assert(p.x==102&&p.y==197&&p.z==290&&p.m_movementInfo.pos.x==102);
|
||||
object.dock.Stopped=false;assert(!ReturnToRecordedStand(&p,&object,anchor,5000));object.dock.Stopped=true;
|
||||
object.dock.RemainingPause=5999;assert(!ReturnToRecordedStand(&p,&object,anchor,5000));object.dock.RemainingPause=6000;
|
||||
p.combat=true;assert(!ReturnToRecordedStand(&p,&object,anchor,5000));p.combat=false;
|
||||
p.alive=false;assert(!ReturnToRecordedStand(&p,&object,anchor,5000));p.alive=true;
|
||||
p.teleport=true;assert(!ReturnToRecordedStand(&p,&object,anchor,5000));p.teleport=false;
|
||||
p.attached=nullptr;assert(!ReturnToRecordedStand(&p,&object,anchor,5000));p.attached=&transport;
|
||||
anchor.x=101;assert(!ReturnToRecordedStand(&p,&object,anchor,5000));anchor.x=NAN;assert(!ReturnToRecordedStand(&p,&object,anchor,5000));
|
||||
assert(transport.relocations==1&&p.updates==1); // rejected operations never move or detach
|
||||
}
|
||||
'''
|
||||
with tempfile.TemporaryDirectory()as d:
|
||||
p=Path(d);(p/'test.cpp').write_text(code)
|
||||
subprocess.run(['c++','-std=c++17',str(p/'test.cpp'),'-o',str(p/'test')],check=True)
|
||||
subprocess.run([str(p/'test')],check=True)
|
||||
print('Native deck fallback: stopped-only, sufficient exit reserve, exact local anchor, preserved attachment, world transform and movement broadcast passed')
|
||||
Reference in new issue
Block a user