fix: Migrates RunebookGump to DynamicGump (#1915)
This commit is contained in:
parent
0ce58deefb
commit
873c25bbc5
2 changed files with 370 additions and 450 deletions
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
using Server.Items;
|
using Server.Items;
|
||||||
using Server.Multis;
|
using Server.Multis;
|
||||||
using Server.Network;
|
using Server.Network;
|
||||||
|
|
@ -7,504 +8,418 @@ using Server.Spells.Chivalry;
|
||||||
using Server.Spells.Fourth;
|
using Server.Spells.Fourth;
|
||||||
using Server.Spells.Seventh;
|
using Server.Spells.Seventh;
|
||||||
|
|
||||||
namespace Server.Gumps
|
namespace Server.Gumps;
|
||||||
|
|
||||||
|
public class RunebookGump : DynamicGump
|
||||||
{
|
{
|
||||||
public class RunebookGump : Gump
|
private readonly Runebook _book;
|
||||||
|
public Runebook Book => _book;
|
||||||
|
|
||||||
|
public RunebookGump(Runebook book) : base(150, 200) => _book = book;
|
||||||
|
|
||||||
|
protected override void BuildLayout(ref DynamicGumpBuilder builder)
|
||||||
{
|
{
|
||||||
public RunebookGump(Mobile from, Runebook book) : base(150, 200)
|
AddBackground(ref builder);
|
||||||
|
AddIndex(ref builder);
|
||||||
|
|
||||||
|
for (var page = 0; page < 8; ++page)
|
||||||
{
|
{
|
||||||
Book = book;
|
builder.AddPage(2 + page);
|
||||||
|
|
||||||
AddBackground();
|
builder.AddButton(125, 14, 2205, 2205, 0, GumpButtonType.Page, 1 + page);
|
||||||
AddIndex();
|
|
||||||
|
|
||||||
for (var page = 0; page < 8; ++page)
|
if (page < 7)
|
||||||
{
|
{
|
||||||
AddPage(2 + page);
|
builder.AddButton(393, 14, 2206, 2206, 0, GumpButtonType.Page, 3 + page);
|
||||||
|
}
|
||||||
|
|
||||||
AddButton(125, 14, 2205, 2205, 0, GumpButtonType.Page, 1 + page);
|
for (var half = 0; half < 2; ++half)
|
||||||
|
{
|
||||||
if (page < 7)
|
AddDetails(ref builder, page * 2 + half, half);
|
||||||
{
|
|
||||||
AddButton(393, 14, 2206, 2206, 0, GumpButtonType.Page, 3 + page);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var half = 0; half < 2; ++half)
|
|
||||||
{
|
|
||||||
AddDetails(page * 2 + half, half);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public Runebook Book { get; }
|
public static int GetMapHue(Map map)
|
||||||
|
{
|
||||||
public int GetMapHue(Map map)
|
if (map == Map.Trammel)
|
||||||
{
|
{
|
||||||
if (map == Map.Trammel)
|
return 10;
|
||||||
{
|
|
||||||
return 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (map == Map.Felucca)
|
|
||||||
{
|
|
||||||
return 81;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (map == Map.Ilshenar)
|
|
||||||
{
|
|
||||||
return 1102;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (map == Map.Malas)
|
|
||||||
{
|
|
||||||
return 1102;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (map == Map.Tokuno)
|
|
||||||
{
|
|
||||||
return 1154;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetName(string name)
|
if (map == Map.Felucca)
|
||||||
{
|
{
|
||||||
if (name == null || (name = name.Trim()).Length <= 0)
|
return 81;
|
||||||
{
|
|
||||||
return "(indescript)";
|
|
||||||
}
|
|
||||||
|
|
||||||
return name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddBackground()
|
if (map == Map.Ilshenar)
|
||||||
{
|
{
|
||||||
AddPage(0);
|
return 1102;
|
||||||
|
|
||||||
// Background image
|
|
||||||
AddImage(100, 10, 2200);
|
|
||||||
|
|
||||||
// Two separators
|
|
||||||
for (var i = 0; i < 2; ++i)
|
|
||||||
{
|
|
||||||
var xOffset = 125 + i * 165;
|
|
||||||
|
|
||||||
AddImage(xOffset, 50, 57);
|
|
||||||
xOffset += 20;
|
|
||||||
|
|
||||||
for (var j = 0; j < 6; ++j, xOffset += 15)
|
|
||||||
{
|
|
||||||
AddImage(xOffset, 50, 58);
|
|
||||||
}
|
|
||||||
|
|
||||||
AddImage(xOffset - 5, 50, 59);
|
|
||||||
}
|
|
||||||
|
|
||||||
// First four page buttons
|
|
||||||
for (int i = 0, xOffset = 130, gumpID = 2225; i < 4; ++i, xOffset += 35, ++gumpID)
|
|
||||||
{
|
|
||||||
AddButton(xOffset, 187, gumpID, gumpID, 0, GumpButtonType.Page, 2 + i);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next four page buttons
|
|
||||||
for (int i = 0, xOffset = 300, gumpID = 2229; i < 4; ++i, xOffset += 35, ++gumpID)
|
|
||||||
{
|
|
||||||
AddButton(xOffset, 187, gumpID, gumpID, 0, GumpButtonType.Page, 6 + i);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Charges
|
|
||||||
AddHtmlLocalized(140, 40, 80, 18, 1011296); // Charges:
|
|
||||||
AddHtml(220, 40, 30, 18, Book.CurCharges.ToString());
|
|
||||||
|
|
||||||
// Max charges
|
|
||||||
AddHtmlLocalized(300, 40, 100, 18, 1011297); // Max Charges:
|
|
||||||
AddHtml(400, 40, 30, 18, Book.MaxCharges.ToString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddIndex()
|
if (map == Map.Malas)
|
||||||
{
|
{
|
||||||
// Index
|
return 1102;
|
||||||
AddPage(1);
|
|
||||||
|
|
||||||
// Rename button
|
|
||||||
AddButton(125, 15, 2472, 2473, 1);
|
|
||||||
AddHtmlLocalized(158, 22, 100, 18, 1011299); // Rename book
|
|
||||||
|
|
||||||
// List of entries
|
|
||||||
var entries = Book.Entries;
|
|
||||||
|
|
||||||
for (var i = 0; i < 16; ++i)
|
|
||||||
{
|
|
||||||
string desc;
|
|
||||||
int hue;
|
|
||||||
|
|
||||||
if (i < entries.Count)
|
|
||||||
{
|
|
||||||
desc = GetName(entries[i].Description);
|
|
||||||
hue = GetMapHue(entries[i].Map);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
desc = "Empty";
|
|
||||||
hue = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use charge button
|
|
||||||
AddButton(130 + i / 8 * 160, 65 + i % 8 * 15, 2103, 2104, 2 + i * 6 + 0);
|
|
||||||
|
|
||||||
// Description label
|
|
||||||
AddLabelCropped(145 + i / 8 * 160, 60 + i % 8 * 15, 115, 17, hue, desc);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Turn page button
|
|
||||||
AddButton(393, 14, 2206, 2206, 0, GumpButtonType.Page, 2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddDetails(int index, int half)
|
if (map == Map.Tokuno)
|
||||||
{
|
{
|
||||||
|
return 1154;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static ReadOnlySpan<char> GetName(ReadOnlySpan<char> name) => name.IsEmpty ? "(indescript)" : name.Trim();
|
||||||
|
|
||||||
|
private void AddBackground(ref DynamicGumpBuilder builder)
|
||||||
|
{
|
||||||
|
builder.AddPage();
|
||||||
|
|
||||||
|
// Background image
|
||||||
|
builder.AddImage(100, 10, 2200);
|
||||||
|
|
||||||
|
// Two separators
|
||||||
|
for (var i = 0; i < 2; ++i)
|
||||||
|
{
|
||||||
|
var xOffset = 125 + i * 165;
|
||||||
|
|
||||||
|
builder.AddImage(xOffset, 50, 57);
|
||||||
|
xOffset += 20;
|
||||||
|
|
||||||
|
for (var j = 0; j < 6; ++j, xOffset += 15)
|
||||||
|
{
|
||||||
|
builder.AddImage(xOffset, 50, 58);
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.AddImage(xOffset - 5, 50, 59);
|
||||||
|
}
|
||||||
|
|
||||||
|
// First four page buttons
|
||||||
|
for (int i = 0, xOffset = 130, gumpID = 2225; i < 4; ++i, xOffset += 35, ++gumpID)
|
||||||
|
{
|
||||||
|
builder.AddButton(xOffset, 187, gumpID, gumpID, 0, GumpButtonType.Page, 2 + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next four page buttons
|
||||||
|
for (int i = 0, xOffset = 300, gumpID = 2229; i < 4; ++i, xOffset += 35, ++gumpID)
|
||||||
|
{
|
||||||
|
builder.AddButton(xOffset, 187, gumpID, gumpID, 0, GumpButtonType.Page, 6 + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Charges
|
||||||
|
builder.AddHtmlLocalized(140, 40, 80, 18, 1011296); // Charges:
|
||||||
|
builder.AddHtml(220, 40, 30, 18, $"{_book.CurCharges}");
|
||||||
|
|
||||||
|
// Max charges
|
||||||
|
builder.AddHtmlLocalized(300, 40, 100, 18, 1011297); // Max Charges:
|
||||||
|
builder.AddHtml(400, 40, 30, 18, $"{_book.MaxCharges}");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddIndex(ref DynamicGumpBuilder builder)
|
||||||
|
{
|
||||||
|
// Index
|
||||||
|
builder.AddPage(1);
|
||||||
|
|
||||||
|
// Rename button
|
||||||
|
builder.AddButton(125, 15, 2472, 2473, 1);
|
||||||
|
builder.AddHtmlLocalized(158, 22, 100, 18, 1011299); // Rename book
|
||||||
|
|
||||||
|
// List of entries
|
||||||
|
var entries = _book.Entries;
|
||||||
|
|
||||||
|
for (var i = 0; i < 16; ++i)
|
||||||
|
{
|
||||||
|
var entry = entries[i];
|
||||||
|
|
||||||
// Use charge button
|
// Use charge button
|
||||||
AddButton(130 + half * 160, 65, 2103, 2104, 2 + index * 6 + 0);
|
builder.AddButton(130 + i / 8 * 160, 65 + i % 8 * 15, 2103, 2104, 2 + i * 6 + 0);
|
||||||
|
|
||||||
string desc;
|
// Description label
|
||||||
int hue;
|
if (i < entries.Count)
|
||||||
|
|
||||||
if (index < Book.Entries.Count)
|
|
||||||
{
|
{
|
||||||
var e = Book.Entries[index];
|
builder.AddLabelCropped(
|
||||||
|
145 + i / 8 * 160,
|
||||||
desc = GetName(e.Description);
|
60 + i % 8 * 15,
|
||||||
hue = GetMapHue(e.Map);
|
115,
|
||||||
|
17,
|
||||||
// Location labels
|
GetMapHue(entry.Map),
|
||||||
int xLong = 0, yLat = 0;
|
GetName(entry.Description)
|
||||||
int xMins = 0, yMins = 0;
|
);
|
||||||
bool xEast = false, ySouth = false;
|
|
||||||
|
|
||||||
if (Sextant.Format(e.Location, e.Map, ref xLong, ref yLat, ref xMins, ref yMins, ref xEast, ref ySouth))
|
|
||||||
{
|
|
||||||
AddLabel(135 + half * 160, 80, 0, $"{yLat}° {yMins}'{(ySouth ? "S" : "N")}");
|
|
||||||
AddLabel(135 + half * 160, 95, 0, $"{xLong}° {xMins}'{(xEast ? "E" : "W")}");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Drop rune button
|
|
||||||
AddButton(135 + half * 160, 115, 2437, 2438, 2 + index * 6 + 1);
|
|
||||||
AddHtmlLocalized(150 + half * 160, 115, 100, 18, 1011298); // Drop rune
|
|
||||||
|
|
||||||
// Set as default button
|
|
||||||
var defButtonID = e != Book.Default ? 2361 : 2360;
|
|
||||||
|
|
||||||
AddButton(160 + half * 140, 20, defButtonID, defButtonID, 2 + index * 6 + 2);
|
|
||||||
AddHtmlLocalized(175 + half * 140, 15, 100, 18, 1011300); // Set default
|
|
||||||
|
|
||||||
if (Core.AOS)
|
|
||||||
{
|
|
||||||
AddButton(135 + half * 160, 140, 2103, 2104, 2 + index * 6 + 3);
|
|
||||||
AddHtmlLocalized(150 + half * 160, 136, 110, 20, 1062722); // Recall
|
|
||||||
|
|
||||||
AddButton(135 + half * 160, 158, 2103, 2104, 2 + index * 6 + 4);
|
|
||||||
AddHtmlLocalized(150 + half * 160, 154, 110, 20, 1062723); // Gate Travel
|
|
||||||
|
|
||||||
AddButton(135 + half * 160, 176, 2103, 2104, 2 + index * 6 + 5);
|
|
||||||
AddHtmlLocalized(150 + half * 160, 172, 110, 20, 1062724); // Sacred Journey
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Recall button
|
|
||||||
AddButton(135 + half * 160, 140, 2271, 2271, 2 + index * 6 + 3);
|
|
||||||
|
|
||||||
// Gate button
|
|
||||||
AddButton(205 + half * 160, 140, 2291, 2291, 2 + index * 6 + 4);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
desc = "Empty";
|
builder.AddLabelCropped(145 + i / 8 * 160, 60 + i % 8 * 15, 115, 17, 0, "Empty");
|
||||||
hue = 0;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Turn page button
|
||||||
|
builder.AddButton(393, 14, 2206, 2206, 0, GumpButtonType.Page, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddDetails(ref DynamicGumpBuilder builder, int index, int half)
|
||||||
|
{
|
||||||
|
// Use charge button
|
||||||
|
builder.AddButton(130 + half * 160, 65, 2103, 2104, 2 + index * 6 + 0);
|
||||||
|
|
||||||
|
if (index < _book.Entries.Count)
|
||||||
|
{
|
||||||
|
var e = _book.Entries[index];
|
||||||
|
|
||||||
|
// Location labels
|
||||||
|
var xLong = 0;
|
||||||
|
var yLat = 0;
|
||||||
|
var xMins = 0;
|
||||||
|
var yMins = 0;
|
||||||
|
var xEast = false;
|
||||||
|
var ySouth = false;
|
||||||
|
|
||||||
|
if (Sextant.Format(e.Location, e.Map, ref xLong, ref yLat, ref xMins, ref yMins, ref xEast, ref ySouth))
|
||||||
|
{
|
||||||
|
builder.AddLabel(135 + half * 160, 80, 0, $"{yLat}° {yMins}'{(ySouth ? "S" : "N")}");
|
||||||
|
builder.AddLabel(135 + half * 160, 95, 0, $"{xLong}° {xMins}'{(xEast ? "E" : "W")}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Drop rune button
|
||||||
|
builder.AddButton(135 + half * 160, 115, 2437, 2438, 2 + index * 6 + 1);
|
||||||
|
builder.AddHtmlLocalized(150 + half * 160, 115, 100, 18, 1011298); // Drop rune
|
||||||
|
|
||||||
|
// Set as default button
|
||||||
|
var defButtonID = e != _book.Default ? 2361 : 2360;
|
||||||
|
|
||||||
|
builder.AddButton(160 + half * 140, 20, defButtonID, defButtonID, 2 + index * 6 + 2);
|
||||||
|
builder.AddHtmlLocalized(175 + half * 140, 15, 100, 18, 1011300); // Set default
|
||||||
|
|
||||||
|
if (Core.AOS)
|
||||||
|
{
|
||||||
|
builder.AddButton(135 + half * 160, 140, 2103, 2104, 2 + index * 6 + 3);
|
||||||
|
builder.AddHtmlLocalized(150 + half * 160, 136, 110, 20, 1062722); // Recall
|
||||||
|
|
||||||
|
builder.AddButton(135 + half * 160, 158, 2103, 2104, 2 + index * 6 + 4);
|
||||||
|
builder.AddHtmlLocalized(150 + half * 160, 154, 110, 20, 1062723); // Gate Travel
|
||||||
|
|
||||||
|
builder.AddButton(135 + half * 160, 176, 2103, 2104, 2 + index * 6 + 5);
|
||||||
|
builder.AddHtmlLocalized(150 + half * 160, 172, 110, 20, 1062724); // Sacred Journey
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Recall button
|
||||||
|
builder.AddButton(135 + half * 160, 140, 2271, 2271, 2 + index * 6 + 3);
|
||||||
|
|
||||||
|
// Gate button
|
||||||
|
builder.AddButton(205 + half * 160, 140, 2291, 2291, 2 + index * 6 + 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Description label
|
// Description label
|
||||||
AddLabelCropped(145 + half * 160, 60, 115, 17, hue, desc);
|
builder.AddLabelCropped(145 + half * 160, 60, 115, 17, GetMapHue(e.Map), GetName(e.Description));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Description label
|
||||||
|
builder.AddLabelCropped(145 + half * 160, 60, 115, 17, 0, "Empty");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool HasSpell(Mobile from, int spellID) => Spellbook.Find(from, spellID)?.HasSpell(spellID) == true;
|
||||||
|
|
||||||
|
public override void OnResponse(NetState state, in RelayInfo info)
|
||||||
|
{
|
||||||
|
var from = state.Mobile;
|
||||||
|
|
||||||
|
_book.Openers.Remove(from);
|
||||||
|
|
||||||
|
if (_book.Deleted || !from.InRange(_book.GetWorldLocation(), Core.ML ? 3 : 1) || !DesignContext.Check(from))
|
||||||
|
{
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool HasSpell(Mobile from, int spellID) => Spellbook.Find(from, spellID)?.HasSpell(spellID) == true;
|
var buttonID = info.ButtonID;
|
||||||
|
|
||||||
public override void OnResponse(NetState state, in RelayInfo info)
|
if (buttonID == 1) // Rename book
|
||||||
{
|
{
|
||||||
var from = state.Mobile;
|
if (!_book.IsLockedDown || from.AccessLevel >= AccessLevel.GameMaster)
|
||||||
|
|
||||||
if (Book.Deleted || !from.InRange(Book.GetWorldLocation(), Core.ML ? 3 : 1) || !DesignContext.Check(from))
|
|
||||||
{
|
{
|
||||||
Book.Openers.Remove(from);
|
from.SendLocalizedMessage(502414); // Please enter a title for the runebook:
|
||||||
return;
|
from.Prompt = new InternalPrompt(_book);
|
||||||
}
|
|
||||||
|
|
||||||
var buttonID = info.ButtonID;
|
|
||||||
|
|
||||||
if (buttonID == 1) // Rename book
|
|
||||||
{
|
|
||||||
if (!Book.IsLockedDown || from.AccessLevel >= AccessLevel.GameMaster)
|
|
||||||
{
|
|
||||||
from.SendLocalizedMessage(502414); // Please enter a title for the runebook:
|
|
||||||
from.Prompt = new InternalPrompt(Book);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Book.Openers.Remove(from);
|
|
||||||
|
|
||||||
from.SendLocalizedMessage(502413, null, 0x35); // That cannot be done while the book is locked down.
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
buttonID -= 2;
|
from.SendLocalizedMessage(502413, null, 0x35); // That cannot be done while the book is locked down.
|
||||||
|
}
|
||||||
|
|
||||||
var index = buttonID / 6;
|
return;
|
||||||
var type = buttonID % 6;
|
}
|
||||||
|
|
||||||
if (index >= 0 && index < Book.Entries.Count)
|
buttonID -= 2;
|
||||||
|
|
||||||
|
var index = Math.DivRem(buttonID, 6, out var type);
|
||||||
|
|
||||||
|
if (index < 0 || index > _book.Entries.Count)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var e = _book.Entries[index];
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case 0: // Use charges
|
||||||
{
|
{
|
||||||
var e = Book.Entries[index];
|
if (_book.CurCharges <= 0)
|
||||||
|
|
||||||
switch (type)
|
|
||||||
{
|
{
|
||||||
case 0: // Use charges
|
from.SendLocalizedMessage(502412); // There are no charges left on that item.
|
||||||
{
|
|
||||||
if (Book.CurCharges <= 0)
|
|
||||||
{
|
|
||||||
from.CloseGump<RunebookGump>();
|
|
||||||
from.SendGump(new RunebookGump(from, Book));
|
|
||||||
|
|
||||||
from.SendLocalizedMessage(502412); // There are no charges left on that item.
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int xLong = 0, yLat = 0;
|
|
||||||
int xMins = 0, yMins = 0;
|
|
||||||
bool xEast = false, ySouth = false;
|
|
||||||
|
|
||||||
if (Sextant.Format(
|
|
||||||
e.Location,
|
|
||||||
e.Map,
|
|
||||||
ref xLong,
|
|
||||||
ref yLat,
|
|
||||||
ref xMins,
|
|
||||||
ref yMins,
|
|
||||||
ref xEast,
|
|
||||||
ref ySouth
|
|
||||||
))
|
|
||||||
{
|
|
||||||
var location =
|
|
||||||
$"{yLat}° {yMins}'{(ySouth ? "S" : "N")}, {xLong}' {xMins}'{(xEast ? "E" : "W")}";
|
|
||||||
from.SendMessage(location);
|
|
||||||
}
|
|
||||||
|
|
||||||
Book.OnTravel();
|
|
||||||
new RecallSpell(from, e, Book, Book).Cast();
|
|
||||||
|
|
||||||
Book.Openers.Remove(from);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 1: // Drop rune
|
|
||||||
{
|
|
||||||
if (!Book.IsLockedDown || from.AccessLevel >= AccessLevel.GameMaster)
|
|
||||||
{
|
|
||||||
Book.DropRune(from, e, index);
|
|
||||||
|
|
||||||
from.CloseGump<RunebookGump>();
|
|
||||||
if (!Core.ML)
|
|
||||||
{
|
|
||||||
from.SendGump(new RunebookGump(from, Book));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Book.Openers.Remove(from);
|
|
||||||
|
|
||||||
from.SendLocalizedMessage(
|
|
||||||
502413,
|
|
||||||
null,
|
|
||||||
0x35
|
|
||||||
); // That cannot be done while the book is locked down.
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 2: // Set default
|
|
||||||
{
|
|
||||||
if (Book.CheckAccess(from))
|
|
||||||
{
|
|
||||||
Book.Default = e;
|
|
||||||
|
|
||||||
from.CloseGump<RunebookGump>();
|
|
||||||
from.SendGump(new RunebookGump(from, Book));
|
|
||||||
|
|
||||||
from.SendLocalizedMessage(502417); // New default location set.
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 3: // Recall
|
|
||||||
{
|
|
||||||
if (HasSpell(from, 31))
|
|
||||||
{
|
|
||||||
int xLong = 0, yLat = 0;
|
|
||||||
int xMins = 0, yMins = 0;
|
|
||||||
bool xEast = false, ySouth = false;
|
|
||||||
|
|
||||||
if (Sextant.Format(
|
|
||||||
e.Location,
|
|
||||||
e.Map,
|
|
||||||
ref xLong,
|
|
||||||
ref yLat,
|
|
||||||
ref xMins,
|
|
||||||
ref yMins,
|
|
||||||
ref xEast,
|
|
||||||
ref ySouth
|
|
||||||
))
|
|
||||||
{
|
|
||||||
var location =
|
|
||||||
$"{yLat}° {yMins}'{(ySouth ? "S" : "N")}, {xLong}' {xMins}'{(xEast ? "E" : "W")}";
|
|
||||||
from.SendMessage(location);
|
|
||||||
}
|
|
||||||
|
|
||||||
Book.OnTravel();
|
|
||||||
new RecallSpell(from, e).Cast();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
from.SendLocalizedMessage(500015); // You do not have that spell!
|
|
||||||
}
|
|
||||||
|
|
||||||
Book.Openers.Remove(from);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 4: // Gate
|
|
||||||
{
|
|
||||||
if (HasSpell(from, 51))
|
|
||||||
{
|
|
||||||
int xLong = 0, yLat = 0;
|
|
||||||
int xMins = 0, yMins = 0;
|
|
||||||
bool xEast = false, ySouth = false;
|
|
||||||
|
|
||||||
if (Sextant.Format(
|
|
||||||
e.Location,
|
|
||||||
e.Map,
|
|
||||||
ref xLong,
|
|
||||||
ref yLat,
|
|
||||||
ref xMins,
|
|
||||||
ref yMins,
|
|
||||||
ref xEast,
|
|
||||||
ref ySouth
|
|
||||||
))
|
|
||||||
{
|
|
||||||
var location =
|
|
||||||
$"{yLat}° {yMins}'{(ySouth ? "S" : "N")}, {xLong}' {xMins}'{(xEast ? "E" : "W")}";
|
|
||||||
from.SendMessage(location);
|
|
||||||
}
|
|
||||||
|
|
||||||
Book.OnTravel();
|
|
||||||
new GateTravelSpell(from, e).Cast();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
from.SendLocalizedMessage(500015); // You do not have that spell!
|
|
||||||
}
|
|
||||||
|
|
||||||
Book.Openers.Remove(from);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 5: // Sacred Journey
|
|
||||||
{
|
|
||||||
if (Core.AOS)
|
|
||||||
{
|
|
||||||
if (HasSpell(from, 209))
|
|
||||||
{
|
|
||||||
int xLong = 0, yLat = 0;
|
|
||||||
int xMins = 0, yMins = 0;
|
|
||||||
bool xEast = false, ySouth = false;
|
|
||||||
|
|
||||||
if (Sextant.Format(
|
|
||||||
e.Location,
|
|
||||||
e.Map,
|
|
||||||
ref xLong,
|
|
||||||
ref yLat,
|
|
||||||
ref xMins,
|
|
||||||
ref yMins,
|
|
||||||
ref xEast,
|
|
||||||
ref ySouth
|
|
||||||
))
|
|
||||||
{
|
|
||||||
var location =
|
|
||||||
$"{yLat}° {yMins}'{(ySouth ? "S" : "N")}, {xLong}' {xMins}'{(xEast ? "E" : "W")}";
|
|
||||||
from.SendMessage(location);
|
|
||||||
}
|
|
||||||
|
|
||||||
Book.OnTravel();
|
|
||||||
new SacredJourneySpell(from, e).Cast();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
from.SendLocalizedMessage(500015); // You do not have that spell!
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Book.Openers.Remove(from);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SendTargetCoordinates(from, e.Location, e.Map);
|
||||||
|
|
||||||
|
_book.OnTravel();
|
||||||
|
new RecallSpell(from, e, _book, _book).Cast();
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else
|
case 1: // Drop rune
|
||||||
{
|
{
|
||||||
Book.Openers.Remove(from);
|
if (!_book.IsLockedDown || from.AccessLevel >= AccessLevel.GameMaster)
|
||||||
|
{
|
||||||
|
_book.DropRune(from, e, index);
|
||||||
|
|
||||||
|
if (!Core.ML)
|
||||||
|
{
|
||||||
|
_book.SendGumpTo(from);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// That cannot be done while the book is locked down.
|
||||||
|
from.SendLocalizedMessage(502413, null, 0x35);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
case 2: // Set default
|
||||||
|
{
|
||||||
|
if (_book.CheckAccess(from))
|
||||||
|
{
|
||||||
|
_book.Default = e;
|
||||||
|
|
||||||
|
// Resend the runebook gump
|
||||||
|
_book.SendGumpTo(from);
|
||||||
|
|
||||||
|
from.SendLocalizedMessage(502417); // New default location set.
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 3: // Recall
|
||||||
|
{
|
||||||
|
if (!HasSpell(from, 31))
|
||||||
|
{
|
||||||
|
from.SendLocalizedMessage(500015); // You do not have that spell!
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
SendTargetCoordinates(from, e.Location, e.Map);
|
||||||
|
|
||||||
|
_book.OnTravel();
|
||||||
|
new RecallSpell(from, e).Cast();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 4: // Gate
|
||||||
|
{
|
||||||
|
if (!HasSpell(from, 51))
|
||||||
|
{
|
||||||
|
from.SendLocalizedMessage(500015); // You do not have that spell!
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
SendTargetCoordinates(from, e.Location, e.Map);
|
||||||
|
|
||||||
|
_book.OnTravel();
|
||||||
|
new GateTravelSpell(from, e).Cast();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 5: // Sacred Journey
|
||||||
|
{
|
||||||
|
if (Core.AOS)
|
||||||
|
{
|
||||||
|
if (!HasSpell(from, 209))
|
||||||
|
{
|
||||||
|
from.SendLocalizedMessage(500015); // You do not have that spell!
|
||||||
|
_book.Openers.Remove(from);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
SendTargetCoordinates(from, e.Location, e.Map);
|
||||||
|
|
||||||
|
_book.OnTravel();
|
||||||
|
new SacredJourneySpell(from, e).Cast();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SendTargetCoordinates(Mobile to, Point3D location, Map map)
|
||||||
|
{
|
||||||
|
var xLong = 0;
|
||||||
|
var yLat = 0;
|
||||||
|
var xMins = 0;
|
||||||
|
var yMins = 0;
|
||||||
|
bool xEast = false, ySouth = false;
|
||||||
|
|
||||||
|
if (Sextant.Format(
|
||||||
|
location,
|
||||||
|
map,
|
||||||
|
ref xLong,
|
||||||
|
ref yLat,
|
||||||
|
ref xMins,
|
||||||
|
ref yMins,
|
||||||
|
ref xEast,
|
||||||
|
ref ySouth
|
||||||
|
))
|
||||||
|
{
|
||||||
|
var locationString =
|
||||||
|
$"{yLat}° {yMins}'{(ySouth ? "S" : "N")}, {xLong}' {xMins}'{(xEast ? "E" : "W")}";
|
||||||
|
to.SendMessage(locationString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class InternalPrompt : Prompt
|
||||||
|
{
|
||||||
|
private readonly Runebook _book;
|
||||||
|
|
||||||
|
public InternalPrompt(Runebook book) => _book = book;
|
||||||
|
|
||||||
|
public override void OnResponse(Mobile from, string text)
|
||||||
|
{
|
||||||
|
if (_book.Deleted || !from.InRange(_book.GetWorldLocation(), Core.ML ? 3 : 1))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_book.CheckAccess(from))
|
||||||
|
{
|
||||||
|
_book.Description = text.AsSpan().Trim().FixHtml();
|
||||||
|
_book.SendGumpTo(from);
|
||||||
|
|
||||||
|
from.SendMessage("The book's title has been changed.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
from.SendLocalizedMessage(502416); // That cannot be done while the book is locked down.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class InternalPrompt : Prompt
|
public override void OnCancel(Mobile from)
|
||||||
{
|
{
|
||||||
private readonly Runebook m_Book;
|
from.SendLocalizedMessage(502415); // Request cancelled.
|
||||||
|
|
||||||
public InternalPrompt(Runebook book) => m_Book = book;
|
if (!_book.Deleted && from.InRange(_book.GetWorldLocation(), Core.ML ? 3 : 1))
|
||||||
|
|
||||||
public override void OnResponse(Mobile from, string text)
|
|
||||||
{
|
{
|
||||||
if (m_Book.Deleted || !from.InRange(m_Book.GetWorldLocation(), Core.ML ? 3 : 1))
|
_book.SendGumpTo(from);
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_Book.CheckAccess(from))
|
|
||||||
{
|
|
||||||
m_Book.Description = text.AsSpan().Trim().FixHtml();
|
|
||||||
|
|
||||||
from.CloseGump<RunebookGump>();
|
|
||||||
from.SendGump(new RunebookGump(from, m_Book));
|
|
||||||
|
|
||||||
from.SendMessage("The book's title has been changed.");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_Book.Openers.Remove(from);
|
|
||||||
|
|
||||||
from.SendLocalizedMessage(502416); // That cannot be done while the book is locked down.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnCancel(Mobile from)
|
|
||||||
{
|
|
||||||
from.SendLocalizedMessage(502415); // Request cancelled.
|
|
||||||
|
|
||||||
if (!m_Book.Deleted && from.InRange(m_Book.GetWorldLocation(), Core.ML ? 3 : 1))
|
|
||||||
{
|
|
||||||
from.CloseGump<RunebookGump>();
|
|
||||||
from.SendGump(new RunebookGump(from, m_Book));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@ public partial class Runebook : Item, ISecurable, ICraftable
|
||||||
[CommandProperty(AccessLevel.GameMaster)]
|
[CommandProperty(AccessLevel.GameMaster)]
|
||||||
public DateTime NextUse { get; set; }
|
public DateTime NextUse { get; set; }
|
||||||
|
|
||||||
public List<Mobile> Openers { get; set; } = new();
|
public HashSet<Mobile> Openers { get; } = new();
|
||||||
|
|
||||||
public override int LabelNumber => 1041267; // runebook
|
public override int LabelNumber => 1041267; // runebook
|
||||||
|
|
||||||
|
|
@ -262,13 +262,18 @@ public partial class Runebook : Item, ISecurable, ICraftable
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
from.CloseGump<RunebookGump>();
|
SendGumpTo(from);
|
||||||
from.SendGump(new RunebookGump(from, this));
|
|
||||||
|
|
||||||
Openers.Add(from);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SendGumpTo(Mobile from)
|
||||||
|
{
|
||||||
|
from.CloseGump<RunebookGump>();
|
||||||
|
from.SendGump(new RunebookGump(this));
|
||||||
|
|
||||||
|
Openers.Add(from);
|
||||||
|
}
|
||||||
|
|
||||||
public virtual void OnTravel()
|
public virtual void OnTravel()
|
||||||
{
|
{
|
||||||
if (!Core.SA)
|
if (!Core.SA)
|
||||||
|
|
@ -408,7 +413,7 @@ public partial class RunebookEntry
|
||||||
|
|
||||||
public RunebookEntry(
|
public RunebookEntry(
|
||||||
Runebook runebook,
|
Runebook runebook,
|
||||||
Point3D loc = new(),
|
Point3D loc = default,
|
||||||
Map map = null,
|
Map map = null,
|
||||||
string description = null,
|
string description = null,
|
||||||
BaseHouse house = null
|
BaseHouse house = null
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue