Publish source: Unlicense, public README, repo hygiene
The remote was previously a distribution-only point for pre-built DLLs. This opens the source. - LICENSE: Unlicense, with a GPL-3.0 carve-out for src/dpslog/WeirdDPSMate (a DPSMate fork that keeps its own license) - README.md replaces the stale internal one with the user-facing docs from DLL_README.md, swapping the 'Why No Source Code?' section for build and layout notes. DLL_README.md is dropped; one README now serves both. - RELEASING.md: drop the trim-the-README-per-release dance and the remote/WeirdUtils/ distribution clone, both obsolete now - gitignore agent/editor scratch, build caches, the vendored WSBT addon, and the WeirdThreat/uwu-logs checkouts (separate upstream repos) - Commit outstanding module work: superweirdo, clickthrough portal visuals, transform44 decompiles, worldmarkers demo presets, tools/
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
# MPQ Load Order — WoW 1.12.1
|
||||
|
||||
`MPQ_InitializeArchives` (0x403740) loads in two phases.
|
||||
|
||||
## Phase 1 — Base archives (loaded by index)
|
||||
|
||||
Filename table at `0x82e12c`:
|
||||
|
||||
| Index | Archive |
|
||||
|-------|---------|
|
||||
| 0 | model.MPQ |
|
||||
| 1 | texture.MPQ |
|
||||
| 2 | terrain.MPQ |
|
||||
| 3 | wmo.MPQ |
|
||||
| 4 | sound.MPQ |
|
||||
| 5 | misc.MPQ |
|
||||
| 6 | interface.MPQ |
|
||||
| 7 | fonts.MPQ |
|
||||
| 8 | speech.MPQ |
|
||||
| 9 | dbc.MPQ |
|
||||
| 10 | speech2.MPQ |
|
||||
|
||||
Each opened via `OpenMPQArchiveWithPaths` (0x403b00) which tries `Data\name` then `..\Data\name`.
|
||||
|
||||
## Phase 2 — Patch archives
|
||||
|
||||
- `MPQArchiveEnumerator` (0x4039b0) discovers `patch-?.MPQ` files via glob
|
||||
- Then opens `patch.MPQ` and any discovered `patch-X.MPQ` archives
|
||||
|
||||
## Search order at file lookup time
|
||||
|
||||
`File_FindInArchive` (0x6549a0) searches the global archive array at `0x8826b4` recursively — later-registered archives (patches) are checked first. The array is searched from `count-1` down to `0`, so patches override base content.
|
||||
|
||||
## Global archive array
|
||||
|
||||
```
|
||||
Struct at 0x8826b4:
|
||||
+0x00 [0x8826b4]: capacity
|
||||
+0x04 [0x8826b8]: count
|
||||
+0x08 [0x8826bc]: array_ptr (SArchive**)
|
||||
+0x0C [0x8826c0]: growth_incr
|
||||
```
|
||||
@@ -0,0 +1,143 @@
|
||||
-- MarkerPresets: save and restore world marker layouts.
|
||||
-- Demonstrates the WorldMarker / GetWorldMarker / ClearWorldMarker API.
|
||||
--
|
||||
-- /mp save <name> — snapshot all current marker positions
|
||||
-- /mp place <name> — restore a saved layout (places all markers at once)
|
||||
-- /mp clear — clear all markers
|
||||
-- /mp list — list saved presets
|
||||
-- /mp delete <name> — delete a preset
|
||||
|
||||
local NUM_MARKERS = 5
|
||||
local PREFIX = "|cff00ccff[Markers]|r "
|
||||
|
||||
local function msg(text)
|
||||
DEFAULT_CHAT_FRAME:AddMessage(PREFIX .. text)
|
||||
end
|
||||
|
||||
local function savePreset(name)
|
||||
if not name or name == "" then
|
||||
msg("Usage: /mp save <name>")
|
||||
return
|
||||
end
|
||||
|
||||
local preset = {}
|
||||
local count = 0
|
||||
for i = 1, NUM_MARKERS do
|
||||
local x, y, z, area = GetWorldMarker(i)
|
||||
if x then
|
||||
preset[i] = { x = x, y = y, z = z, area = area }
|
||||
count = count + 1
|
||||
end
|
||||
end
|
||||
|
||||
if count == 0 then
|
||||
msg("No markers to save.")
|
||||
return
|
||||
end
|
||||
|
||||
MarkerPresets_Saved[name] = preset
|
||||
msg("Saved |cffffffff" .. name .. "|r (" .. count .. " marker" .. (count > 1 and "s" or "") .. ")")
|
||||
end
|
||||
|
||||
local function placePreset(name)
|
||||
if not name or name == "" then
|
||||
msg("Usage: /mp place <name>")
|
||||
return
|
||||
end
|
||||
|
||||
local preset = MarkerPresets_Saved[name]
|
||||
if not preset then
|
||||
msg("No preset named |cffffffff" .. name .. "|r")
|
||||
return
|
||||
end
|
||||
|
||||
if not CanSetWorldMarkers() then
|
||||
msg("|cffff4444No permission|r (need leader or assist)")
|
||||
return
|
||||
end
|
||||
|
||||
-- Clear existing markers, then place the saved ones
|
||||
ClearWorldMarker()
|
||||
|
||||
local count = 0
|
||||
for i = 1, NUM_MARKERS do
|
||||
local m = preset[i]
|
||||
if m then
|
||||
WorldMarker(i, m.x, m.y, m.z)
|
||||
count = count + 1
|
||||
end
|
||||
end
|
||||
|
||||
msg("Placed |cffffffff" .. name .. "|r (" .. count .. " marker" .. (count > 1 and "s" or "") .. ")")
|
||||
end
|
||||
|
||||
local function clearMarkers()
|
||||
if not CanSetWorldMarkers() then
|
||||
msg("|cffff4444No permission|r (need leader or assist)")
|
||||
return
|
||||
end
|
||||
ClearWorldMarker()
|
||||
msg("Cleared all markers.")
|
||||
end
|
||||
|
||||
local function listPresets()
|
||||
local any = false
|
||||
for name, preset in pairs(MarkerPresets_Saved) do
|
||||
local count = 0
|
||||
for i = 1, NUM_MARKERS do
|
||||
if preset[i] then count = count + 1 end
|
||||
end
|
||||
msg(" |cffffffff" .. name .. "|r — " .. count .. " marker" .. (count > 1 and "s" or ""))
|
||||
any = true
|
||||
end
|
||||
if not any then
|
||||
msg("No saved presets.")
|
||||
end
|
||||
end
|
||||
|
||||
local function deletePreset(name)
|
||||
if not name or name == "" then
|
||||
msg("Usage: /mp delete <name>")
|
||||
return
|
||||
end
|
||||
if not MarkerPresets_Saved[name] then
|
||||
msg("No preset named |cffffffff" .. name .. "|r")
|
||||
return
|
||||
end
|
||||
MarkerPresets_Saved[name] = nil
|
||||
msg("Deleted |cffffffff" .. name .. "|r")
|
||||
end
|
||||
|
||||
local f = CreateFrame("Frame")
|
||||
f:RegisterEvent("VARIABLES_LOADED")
|
||||
f:SetScript("OnEvent", function()
|
||||
MarkerPresets_Saved = MarkerPresets_Saved or {}
|
||||
end)
|
||||
|
||||
SLASH_MARKERPRESETS1 = "/mp"
|
||||
SLASH_MARKERPRESETS2 = "/markerpreset"
|
||||
SlashCmdList["MARKERPRESETS"] = function(input)
|
||||
local cmd, rest = string.match(input, "^(%S+)%s*(.*)")
|
||||
if not cmd then
|
||||
msg("Commands: save | place | clear | list | delete")
|
||||
return
|
||||
end
|
||||
|
||||
cmd = string.lower(cmd)
|
||||
local name = rest ~= "" and rest or nil
|
||||
|
||||
if cmd == "save" then
|
||||
savePreset(name)
|
||||
elseif cmd == "place" or cmd == "load" then
|
||||
placePreset(name)
|
||||
elseif cmd == "clear" then
|
||||
clearMarkers()
|
||||
elseif cmd == "list" or cmd == "ls" then
|
||||
listPresets()
|
||||
elseif cmd == "delete" or cmd == "del" or cmd == "rm" then
|
||||
deletePreset(name)
|
||||
else
|
||||
msg("Unknown command: " .. cmd)
|
||||
msg("Commands: save | place | clear | list | delete")
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,7 @@
|
||||
## Interface: 11200
|
||||
## Title: [WeirdUtils] Marker Presets
|
||||
## Notes: Save and restore world marker positions. Requires WeirdUtils World Markers.
|
||||
## Version: 1.0
|
||||
## SavedVariablesPerCharacter: MarkerPresetsDB
|
||||
|
||||
MarkerPresets.lua
|
||||
@@ -22,7 +22,6 @@ const std = @import("std");
|
||||
const hook = @import("zhook");
|
||||
const lua = @import("../lua.zig");
|
||||
const o = @import("offsets.zig");
|
||||
const offsets = @import("../offsets.zig");
|
||||
const wow = @import("../wow.zig");
|
||||
const logging = @import("../logging.zig");
|
||||
|
||||
@@ -356,7 +355,7 @@ fn placeMarker(index: usize, pos: Vec3) bool {
|
||||
// Store persistent definition
|
||||
marker_defs[index] = .{
|
||||
.pos = pos,
|
||||
.area_id = hook.readMem(u32, offsets.ZONE_AREA_ID),
|
||||
.area_id = wow.getMapId(),
|
||||
.active = true,
|
||||
};
|
||||
|
||||
@@ -590,7 +589,7 @@ fn tickAnimations() void {
|
||||
if (player != 0) {
|
||||
const player_pos = getUnitPosition(player);
|
||||
if (player_pos.x != 0 or player_pos.y != 0 or player_pos.z != 0) {
|
||||
const current_area = hook.readMem(u32, offsets.ZONE_AREA_ID);
|
||||
const current_area = wow.getMapId();
|
||||
for (0..NUM_MARKERS) |i| {
|
||||
if (!marker_defs[i].active) continue;
|
||||
if (marker_entities[i] != null) continue; // entity alive, skip
|
||||
|
||||
Reference in New Issue
Block a user