mirror of
https://github.com/brues-code/ClassicAPI.git
synced 2026-11-14 15:10:39 +00:00
129 lines
4.9 KiB
C++
129 lines
4.9 KiB
C++
// This file is part of ClassicAPI.
|
|
//
|
|
// ClassicAPI is free software: you can redistribute it and/or modify it under the terms
|
|
// of the GNU Lesser General Public License as published by the Free Software Foundation, either
|
|
// version 3 of the License, or (at your option) any later version.
|
|
//
|
|
// ClassicAPI is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
// PURPOSE. See the GNU Lesser General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Lesser General Public License along with
|
|
// ClassicAPI. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
#include "Game.h"
|
|
#include "Offsets.h"
|
|
|
|
#include <cstdint>
|
|
|
|
namespace Instance::Info {
|
|
|
|
namespace {
|
|
|
|
// Map.dbc instance-type enum, indexable from 0..4. Vanilla never uses
|
|
// slot 4 (arena), but the modern API string set includes it.
|
|
const char *const kTypeNames[] = {
|
|
"none", // 0 — open world
|
|
"party", // 1 — 5-man dungeon
|
|
"raid", // 2 — raid
|
|
"pvp", // 3 — battleground
|
|
"arena", // 4 — unused in vanilla
|
|
};
|
|
|
|
// Per-type player cap. Vanilla has no per-map cap stored client-side
|
|
// (MapDifficulty.dbc was a TBC addition), so we return the type's
|
|
// canonical max. ZG / AQ20 / WSG / AB return 40 instead of their true
|
|
// caps; same answer for any custom raid on private servers. Addons
|
|
// that need exact caps must supply their own table.
|
|
int CapForType(uint32_t type) {
|
|
switch (type) {
|
|
case 1: return 5;
|
|
case 2: return 40;
|
|
case 3: return 40;
|
|
case 4: return 5;
|
|
default: return 0;
|
|
}
|
|
}
|
|
|
|
const uint8_t *MapRecord(uint32_t mapID) {
|
|
const int count = *reinterpret_cast<const int *>(
|
|
static_cast<uintptr_t>(Offsets::VAR_MAP_COUNT));
|
|
if (static_cast<int>(mapID) < 0 || static_cast<int>(mapID) > count)
|
|
return nullptr;
|
|
const uint8_t *const *records =
|
|
*reinterpret_cast<const uint8_t *const *const *>(
|
|
static_cast<uintptr_t>(Offsets::VAR_MAP_RECORDS));
|
|
if (records == nullptr)
|
|
return nullptr;
|
|
return records[mapID];
|
|
}
|
|
|
|
} // namespace
|
|
|
|
// `GetInstanceInfo()` — returns the modern 9-tuple shape, with vanilla
|
|
// degeneracies for fields the 1.12 client doesn't track:
|
|
// name, type, difficultyID, difficultyName, maxPlayers,
|
|
// dynamicDifficulty, isDynamic, instanceID, instanceGroupSize
|
|
//
|
|
// - `name` / `type` come from Map.dbc.
|
|
// - `difficultyID` / `difficultyName` are always `1` / `"Normal"` (no
|
|
// heroic mode pre-TBC; MapDifficulty.dbc doesn't exist).
|
|
// - `maxPlayers` is the type's canonical cap (see `CapForType`).
|
|
// - `dynamicDifficulty` is always `0` and `isDynamic` is always `false`
|
|
// (dynamic difficulty was a Cataclysm-era addition).
|
|
// - `instanceID` is the current Map.dbc ID. (Modern docs call this
|
|
// "instanceID" but it's really the mapID — both vanilla and modern
|
|
// put the same value here.)
|
|
// - `instanceGroupSize` mirrors `maxPlayers` (no per-group-config
|
|
// variants in vanilla).
|
|
static int __fastcall Script_GetInstanceInfo(void *L) {
|
|
const uint32_t mapID = *reinterpret_cast<const uint32_t *>(
|
|
static_cast<uintptr_t>(Offsets::VAR_CURRENT_MAP_ID));
|
|
|
|
const uint8_t *rec = MapRecord(mapID);
|
|
if (rec == nullptr) {
|
|
Game::Lua::PushString(L, "");
|
|
Game::Lua::PushString(L, "none");
|
|
Game::Lua::PushNumber(L, 1.0);
|
|
Game::Lua::PushString(L, "Normal");
|
|
Game::Lua::PushNumber(L, 0.0);
|
|
Game::Lua::PushNumber(L, 0.0);
|
|
Game::Lua::PushBool(L, false);
|
|
Game::Lua::PushNumber(L, static_cast<double>(mapID));
|
|
Game::Lua::PushNumber(L, 0.0);
|
|
return 9;
|
|
}
|
|
|
|
const uint32_t type = *reinterpret_cast<const uint32_t *>(
|
|
rec + Offsets::OFF_MAP_INSTANCE_TYPE);
|
|
const uint32_t locale = *reinterpret_cast<const uint32_t *>(
|
|
static_cast<uintptr_t>(Offsets::VAR_LOCALE_INDEX));
|
|
const char *name = *reinterpret_cast<const char *const *>(
|
|
rec + Offsets::OFF_MAP_NAME + locale * 4);
|
|
|
|
const char *typeName =
|
|
(type < sizeof(kTypeNames) / sizeof(kTypeNames[0])) ? kTypeNames[type]
|
|
: "none";
|
|
const int cap = CapForType(type);
|
|
|
|
Game::Lua::PushString(L, name != nullptr ? name : "");
|
|
Game::Lua::PushString(L, typeName);
|
|
Game::Lua::PushNumber(L, 1.0);
|
|
Game::Lua::PushString(L, "Normal");
|
|
Game::Lua::PushNumber(L, static_cast<double>(cap));
|
|
Game::Lua::PushNumber(L, 0.0);
|
|
Game::Lua::PushBool(L, false);
|
|
Game::Lua::PushNumber(L, static_cast<double>(mapID));
|
|
Game::Lua::PushNumber(L, static_cast<double>(cap));
|
|
return 9;
|
|
}
|
|
|
|
static void RegisterLuaFunctions() {
|
|
Game::Lua::RegisterGlobalFunction("GetInstanceInfo",
|
|
&Script_GetInstanceInfo);
|
|
}
|
|
|
|
static const Game::ModuleAutoRegister _autoreg{&RegisterLuaFunctions};
|
|
|
|
} // namespace Instance::Info
|