added z coords for portal discovery and minster disovery
This commit is contained in:
parent
91cd934878
commit
bb493febb4
7 changed files with 168 additions and 1573 deletions
|
|
@ -108,6 +108,7 @@ namespace MosswartMassacre
|
|||
CoreManager.Current.CharacterFilter.LoginComplete += CharacterFilter_LoginComplete;
|
||||
CoreManager.Current.CharacterFilter.Death += OnCharacterDeath;
|
||||
CoreManager.Current.WorldFilter.CreateObject += OnSpawn;
|
||||
CoreManager.Current.WorldFilter.CreateObject += OnPortalDetected;
|
||||
CoreManager.Current.WorldFilter.ReleaseObject += OnDespawn;
|
||||
// Subscribe to inventory change events for taper tracking
|
||||
CoreManager.Current.WorldFilter.CreateObject += OnInventoryCreate;
|
||||
|
|
@ -172,6 +173,7 @@ namespace MosswartMassacre
|
|||
CoreManager.Current.ChatBoxMessage -= new EventHandler<ChatTextInterceptEventArgs>(AllChatText);
|
||||
CoreManager.Current.CharacterFilter.Death -= OnCharacterDeath;
|
||||
CoreManager.Current.WorldFilter.CreateObject -= OnSpawn;
|
||||
CoreManager.Current.WorldFilter.CreateObject -= OnPortalDetected;
|
||||
CoreManager.Current.WorldFilter.ReleaseObject -= OnDespawn;
|
||||
// Unsubscribe from inventory change events
|
||||
CoreManager.Current.WorldFilter.CreateObject -= OnInventoryCreate;
|
||||
|
|
@ -454,12 +456,51 @@ namespace MosswartMassacre
|
|||
|
||||
try
|
||||
{
|
||||
var coords = mob.Coordinates();
|
||||
const string fmt = "F7";
|
||||
string ns = coords.NorthSouth.ToString(fmt, CultureInfo.InvariantCulture);
|
||||
string ew = coords.EastWest.ToString(fmt, CultureInfo.InvariantCulture);
|
||||
// Get DECAL coordinates
|
||||
var decalCoords = mob.Coordinates();
|
||||
if (decalCoords == null) return;
|
||||
|
||||
await WebSocket.SendSpawnAsync(ns, ew, mob.Name);
|
||||
const string fmt = "F7";
|
||||
string ns = decalCoords.NorthSouth.ToString(fmt, CultureInfo.InvariantCulture);
|
||||
string ew = decalCoords.EastWest.ToString(fmt, CultureInfo.InvariantCulture);
|
||||
|
||||
// Get Z coordinate using RawCoordinates() for accurate world Z position
|
||||
string zCoord = "0";
|
||||
try
|
||||
{
|
||||
var rawCoords = mob.RawCoordinates();
|
||||
if (rawCoords != null)
|
||||
{
|
||||
zCoord = rawCoords.Z.ToString("F2", CultureInfo.InvariantCulture);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fallback to player Z approximation if RawCoordinates fails
|
||||
var playerCoords = Coordinates.Me;
|
||||
if (Math.Abs(playerCoords.Z) > 0.1)
|
||||
{
|
||||
zCoord = playerCoords.Z.ToString("F2", CultureInfo.InvariantCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Fallback to player Z approximation on error
|
||||
try
|
||||
{
|
||||
var playerCoords = Coordinates.Me;
|
||||
if (Math.Abs(playerCoords.Z) > 0.1)
|
||||
{
|
||||
zCoord = playerCoords.Z.ToString("F2", CultureInfo.InvariantCulture);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
zCoord = "0";
|
||||
}
|
||||
}
|
||||
|
||||
await WebSocket.SendSpawnAsync(ns, ew, zCoord, mob.Name);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
@ -467,6 +508,66 @@ namespace MosswartMassacre
|
|||
}
|
||||
}
|
||||
|
||||
private async void OnPortalDetected(object sender, CreateObjectEventArgs e)
|
||||
{
|
||||
var portal = e.New;
|
||||
if (portal.ObjectClass != ObjectClass.Portal) return;
|
||||
|
||||
try
|
||||
{
|
||||
// Get portal coordinates from DECAL
|
||||
var decalCoords = portal.Coordinates();
|
||||
if (decalCoords == null) return;
|
||||
|
||||
const string fmt = "F7";
|
||||
string ns = decalCoords.NorthSouth.ToString(fmt, CultureInfo.InvariantCulture);
|
||||
string ew = decalCoords.EastWest.ToString(fmt, CultureInfo.InvariantCulture);
|
||||
|
||||
// Get Z coordinate using RawCoordinates() for accurate world Z position
|
||||
string zCoord = "0";
|
||||
try
|
||||
{
|
||||
var rawCoords = portal.RawCoordinates();
|
||||
if (rawCoords != null)
|
||||
{
|
||||
zCoord = rawCoords.Z.ToString("F2", CultureInfo.InvariantCulture);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fallback to player Z approximation if RawCoordinates fails
|
||||
var playerCoords = Coordinates.Me;
|
||||
if (Math.Abs(playerCoords.Z) > 0.1)
|
||||
{
|
||||
zCoord = playerCoords.Z.ToString("F2", CultureInfo.InvariantCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Fallback to player Z approximation on error
|
||||
try
|
||||
{
|
||||
var playerCoords = Coordinates.Me;
|
||||
if (Math.Abs(playerCoords.Z) > 0.1)
|
||||
{
|
||||
zCoord = playerCoords.Z.ToString("F2", CultureInfo.InvariantCulture);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
zCoord = "0";
|
||||
}
|
||||
}
|
||||
|
||||
await WebSocket.SendPortalAsync(ns, ew, zCoord, portal.Name);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
PluginCore.WriteToChat($"[PORTAL ERROR] {ex.Message}");
|
||||
PluginCore.WriteToChat($"[WS] Portal send failed: {ex}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void OnDespawn(object sender, ReleaseObjectEventArgs e)
|
||||
{
|
||||
|
|
@ -775,12 +876,12 @@ namespace MosswartMassacre
|
|||
rareTextOnly = null;
|
||||
|
||||
// Match pattern: "<name> has discovered the <something>!"
|
||||
string pattern = @"^(?<name>['A-Za-z ]+)\s(?<text>has discovered the .*!$)";
|
||||
string pattern = @"^(?<name>['A-Za-z ]+)\shas discovered the (?<item>.*?)!$";
|
||||
Match match = Regex.Match(text, pattern);
|
||||
|
||||
if (match.Success && match.Groups["name"].Value == CoreManager.Current.CharacterFilter.Name)
|
||||
{
|
||||
rareTextOnly = match.Groups["text"].Value; // just "has discovered the Ancient Pickle!"
|
||||
rareTextOnly = match.Groups["item"].Value; // just "Ancient Pickle"
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,6 +41,29 @@ namespace MosswartMassacre
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return any WorldObject's raw world position by reading the
|
||||
/// physics-object pointer (same offsets: +0x84/88/8C).
|
||||
/// </summary>
|
||||
public static unsafe Vector3 GetWorldObjectPosition(int objectId)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!CoreManager.Current.Actions.IsValidObject(objectId))
|
||||
return new Vector3();
|
||||
|
||||
byte* p = (byte*)CoreManager.Current.Actions.Underlying.GetPhysicsObjectPtr(objectId);
|
||||
return new Vector3(
|
||||
*(float*)(p + 0x84), // X
|
||||
*(float*)(p + 0x88), // Y
|
||||
*(float*)(p + 0x8C)); // Z
|
||||
}
|
||||
catch
|
||||
{
|
||||
return new Vector3();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convenience: returns the current landcell (upper 16 bits of landblock).
|
||||
/// </summary>
|
||||
|
|
@ -65,6 +88,26 @@ namespace MosswartMassacre
|
|||
return new Coordinates(ew, ns, pos.Z);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get AC-style coordinates (EW/NS/Z) for any WorldObject.
|
||||
/// </summary>
|
||||
public static Coordinates GetWorldObjectCoordinates(WorldObject wo)
|
||||
{
|
||||
if (wo == null) return new Coordinates();
|
||||
|
||||
Vector3 pos = GetWorldObjectPosition(wo.Id);
|
||||
|
||||
// Get landcell from the object's coordinates
|
||||
var coordsObj = wo.Coordinates();
|
||||
if (coordsObj == null) return new Coordinates();
|
||||
|
||||
// Convert DECAL coords to our Coordinates with Z
|
||||
double ew = coordsObj.EastWest;
|
||||
double ns = coordsObj.NorthSouth;
|
||||
|
||||
return new Coordinates(ew, ns, pos.Z);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------
|
||||
* 3) Generic math helpers you may want later
|
||||
* -------------------------------------------------------- */
|
||||
|
|
|
|||
|
|
@ -226,7 +226,7 @@ namespace MosswartMassacre
|
|||
var json = JsonConvert.SerializeObject(envelope);
|
||||
await SendEncodedAsync(json, CancellationToken.None);
|
||||
}
|
||||
public static async Task SendSpawnAsync(string nsCoord, string ewCoord, string monster)
|
||||
public static async Task SendSpawnAsync(string nsCoord, string ewCoord, string zCoord, string monster)
|
||||
{
|
||||
var envelope = new
|
||||
{
|
||||
|
|
@ -235,8 +235,24 @@ namespace MosswartMassacre
|
|||
character_name = CoreManager.Current.CharacterFilter.Name,
|
||||
mob = monster,
|
||||
ns = nsCoord,
|
||||
ew = ewCoord
|
||||
ew = ewCoord,
|
||||
z = zCoord
|
||||
};
|
||||
var json = JsonConvert.SerializeObject(envelope);
|
||||
await SendEncodedAsync(json, CancellationToken.None);
|
||||
}
|
||||
|
||||
public static async Task SendPortalAsync(string nsCoord, string ewCoord, string zCoord, string portalName)
|
||||
{
|
||||
var envelope = new
|
||||
{
|
||||
type = "portal",
|
||||
timestamp = DateTime.UtcNow.ToString("o"),
|
||||
character_name = CoreManager.Current.CharacterFilter.Name,
|
||||
portal_name = portalName,
|
||||
ns = nsCoord,
|
||||
ew = ewCoord,
|
||||
z = zCoord
|
||||
};
|
||||
var json = JsonConvert.SerializeObject(envelope);
|
||||
await SendEncodedAsync(json, CancellationToken.None);
|
||||
|
|
|
|||
BIN
dereth.png
BIN
dereth.png
Binary file not shown.
|
Before Width: | Height: | Size: 5.6 MiB |
File diff suppressed because it is too large
Load diff
|
|
@ -1,110 +0,0 @@
|
|||
local libQuest = {
|
||||
List = {},
|
||||
Dictionary = {}
|
||||
}
|
||||
|
||||
---@class Quest: Object
|
||||
---@field id number
|
||||
---@field solves number
|
||||
---@field timestamp number
|
||||
---@field description string
|
||||
---@field maxsolves number
|
||||
---@field delta number
|
||||
---@field expiretime number
|
||||
|
||||
local function OnChatText(evt)
|
||||
local taskname, solves, timestamp, description, maxsolves, delta = string.match(evt.Message, "([%w%s%(%)-]+) %- (%d+) solves %((%d+)%)\"([^\"]+)\" (%-?%d+) (%d+)")
|
||||
if taskname and solves and timestamp and description and maxsolves and delta then
|
||||
table.insert(libQuest.List, {id=taskname,solves=solves,timestamp=timestamp,description=description,maxsolves=maxsolves,delta=delta,expiretime=timestamp+delta})
|
||||
libQuest.Dictionary[taskname] = {id=taskname,solves=solves,timestamp=timestamp,description=description,maxsolves=maxsolves,delta=delta,expiretime=timestamp+delta}
|
||||
end
|
||||
end
|
||||
|
||||
function libQuest:Clear()
|
||||
self.List = {}
|
||||
self.Dictionary = {}
|
||||
end
|
||||
|
||||
function libQuest:Refresh()
|
||||
self:Clear()
|
||||
game.OnTick.Once(function (evt)
|
||||
game.World.OnChatText.Add(OnChatText)
|
||||
sleep(100)
|
||||
game.Actions.InvokeChat("/myquests")
|
||||
sleep(3000)
|
||||
game.World.OnChatText.Remove(OnChatText)
|
||||
end)
|
||||
end
|
||||
|
||||
function libQuest:IsQuestAvailable(queststamp)
|
||||
local quest = self.Dictionary[queststamp]
|
||||
if quest == nil then return true end
|
||||
return quest.expiretime < os.time()
|
||||
end
|
||||
|
||||
function libQuest:IsQuestMaxSolved(queststamp)
|
||||
local quest = self.Dictionary[queststamp]
|
||||
if quest == nil then return false end
|
||||
if tonumber(quest.maxsolves) == tonumber(quest.solves) then return true end
|
||||
return false
|
||||
end
|
||||
|
||||
function libQuest:HasQuestFlag(queststamp)
|
||||
local quest = self.Dictionary[queststamp]
|
||||
return quest ~= nil
|
||||
end
|
||||
|
||||
function libQuest:GetFieldByID(quest, id)
|
||||
local fields = {
|
||||
quest.id,
|
||||
quest.solves,
|
||||
quest.timestamp,
|
||||
quest.maxsolves,
|
||||
quest.delta,
|
||||
quest.expiretime
|
||||
}
|
||||
return fields[id] or quest.id
|
||||
end
|
||||
|
||||
function libQuest:FormatTimeStamp(time)
|
||||
return tostring(os.date("%m/%d/%Y %H:%M:%S", time))
|
||||
end
|
||||
|
||||
function libQuest:FormatSeconds(seconds)
|
||||
if seconds <= 0 then
|
||||
return "0s"
|
||||
end
|
||||
local days = math.floor(seconds / 86400)
|
||||
seconds = seconds % 86400
|
||||
local hours = math.floor(seconds / 3600)
|
||||
seconds = seconds % 3600
|
||||
local minutes = math.floor(seconds / 60)
|
||||
seconds = math.floor(seconds % 60)
|
||||
|
||||
local result = ""
|
||||
if days > 0 then
|
||||
result = result .. days .. "d "
|
||||
end
|
||||
if hours > 0 then
|
||||
result = result .. hours .. "h "
|
||||
end
|
||||
if minutes > 0 then
|
||||
result = result .. minutes .. "m "
|
||||
end
|
||||
if seconds > 0 or result == "" then
|
||||
result = result .. seconds .. "s"
|
||||
end
|
||||
|
||||
return result:match("^%s*(.-)%s*$") -- Trim any trailing space
|
||||
end
|
||||
|
||||
function libQuest:GetTimeUntilExpire(quest)
|
||||
if quest == nil then return "Unknown" end
|
||||
local expireTime = self:FormatSeconds(quest.expiretime - os.time())
|
||||
if expireTime == "0s" then
|
||||
return "Ready"
|
||||
end
|
||||
return expireTime
|
||||
end
|
||||
|
||||
return libQuest
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 3.8 MiB |
Loading…
Add table
Add a link
Reference in a new issue