Overwrite

Complete Overwrite of the Folder with the free shard. ServUO 57.3 has been added.
This commit is contained in:
Unstable Kitsune
2023-11-28 23:20:26 -05:00
parent 3cd54811de
commit b918192e4e
11608 changed files with 2644205 additions and 47 deletions

View File

@@ -0,0 +1,83 @@
#region References
using System;
using System.Collections;
using Server;
using Server.Network;
#endregion
namespace Knives.TownHouses
{
public class Errors
{
private static readonly ArrayList s_ErrorLog = new ArrayList();
private static readonly ArrayList s_Checked = new ArrayList();
public static ArrayList ErrorLog { get { return s_ErrorLog; } }
public static ArrayList Checked { get { return s_Checked; } }
public static void Initialize()
{
RUOVersion.AddCommand("TownHouseErrors", AccessLevel.Developer, OnErrors);
EventSink.Login += OnLogin;
}
private static void OnErrors(CommandInfo e)
{
if (e.ArgString == null || e.ArgString == "")
{
new ErrorsGump(e.Mobile);
}
else
{
Report(e.ArgString + " - " + e.Mobile.Name);
}
}
private static void OnLogin(LoginEventArgs e)
{
if (e.Mobile.AccessLevel != AccessLevel.Player && s_ErrorLog.Count != 0 && !s_Checked.Contains(e.Mobile))
{
new ErrorsNotifyGump(e.Mobile);
}
}
public static void Report(string error)
{
s_ErrorLog.Add(String.Format("<B>{0}</B><BR>{1}<BR>", DateTime.UtcNow, error));
s_Checked.Clear();
Notify();
}
private static void Notify()
{
foreach (var state in NetState.Instances)
{
if (state.Mobile == null)
{
continue;
}
if (state.Mobile.AccessLevel != AccessLevel.Player)
{
Notify(state.Mobile);
}
}
}
public static void Notify(Mobile m)
{
if (m.HasGump(typeof(ErrorsGump)))
{
new ErrorsGump(m);
}
else
{
new ErrorsNotifyGump(m);
}
}
}
}

View File

@@ -0,0 +1,65 @@
#region References
using Server;
#endregion
namespace Knives.TownHouses
{
public class ErrorsGump : GumpPlusLight
{
public ErrorsGump(Mobile m)
: base(m, 100, 100)
{
Errors.Checked.Add(m);
m.CloseGump(typeof(ErrorsGump));
}
protected override void BuildGump()
{
var width = 400;
var y = 10;
AddHtml(0, y, width, "<CENTER>TownHouse Errors");
AddImage(width / 2 - 100, y + 2, 0x39);
AddImage(width / 2 + 70, y + 2, 0x3B);
AddButton(width - 20, y, 0x5689, 0x5689, "Help", Help);
var str = HTML.Black;
foreach (string text in Errors.ErrorLog)
{
str += text;
}
AddHtml(20, y += 25, width - 40, 200, str, true, true);
y += 200;
if (Owner.AccessLevel >= AccessLevel.Administrator)
{
AddButton(width / 2 - 30, y += 10, 0x98B, 0x98B, "Clear", ClearLog);
AddHtml(width / 2 - 23, y + 3, 51, "<CENTER>Clear");
}
AddBackgroundZero(0, 0, width, y + 40, 0x1400);
}
private void Help()
{
NewGump();
new InfoGump(
Owner,
300,
300,
HTML.White +
" Errors reported by either the TownHouse system or other staff members! Administrators have the power to clear this list. All staff members can report an error using the [TownHouseErrors command.",
true);
}
private void ClearLog()
{
Errors.ErrorLog.Clear();
NewGump();
}
}
}

View File

@@ -0,0 +1,26 @@
#region References
using Server;
#endregion
namespace Knives.TownHouses
{
public class ErrorsNotifyGump : GumpPlusLight
{
public ErrorsNotifyGump(Mobile m)
: base(m, 250, 100)
{
m.CloseGump(typeof(ErrorsNotifyGump));
}
protected override void BuildGump()
{
AddButton(0, 0, 0x1590, 0x1590, "Errors", Errors);
AddItem(20, 20, 0x22C4);
}
private void Errors()
{
new ErrorsGump(Owner);
}
}
}

View File

@@ -0,0 +1,23 @@
#region References
using Server.Gumps;
#endregion
namespace Knives.TownHouses
{
public class BackgroundPlus : GumpBackground
{
public bool Override { get; set; }
public BackgroundPlus(int x, int y, int width, int height, int back)
: base(x, y, width, height, back)
{
Override = true;
}
public BackgroundPlus(int x, int y, int width, int height, int back, bool over)
: base(x, y, width, height, back)
{
Override = over;
}
}
}

View File

@@ -0,0 +1,51 @@
#region References
using Server.Gumps;
#endregion
namespace Knives.TownHouses
{
public class ButtonPlus : GumpButton
{
private readonly string c_Name;
private readonly object c_Callback;
private readonly object c_Param;
public string Name { get { return c_Name; } }
public ButtonPlus(int x, int y, int normalID, int pressedID, int buttonID, string name, GumpCallback back)
: base(x, y, normalID, pressedID, buttonID, GumpButtonType.Reply, 0)
{
c_Name = name;
c_Callback = back;
c_Param = "";
}
public ButtonPlus(
int x,
int y,
int normalID,
int pressedID,
int buttonID,
string name,
GumpStateCallback back,
object param)
: base(x, y, normalID, pressedID, buttonID, GumpButtonType.Reply, 0)
{
c_Name = name;
c_Callback = back;
c_Param = param;
}
public void Invoke()
{
if (c_Callback is GumpCallback)
{
((GumpCallback)c_Callback)();
}
else if (c_Callback is GumpStateCallback)
{
((GumpStateCallback)c_Callback)(c_Param);
}
}
}
}

View File

@@ -0,0 +1,281 @@
#region References
using System;
using System.Collections;
using Server;
using Server.Gumps;
using Server.Network;
#endregion
namespace Knives.TownHouses
{
public delegate void GumpStateCallback(object obj);
public delegate void GumpCallback();
public abstract class GumpPlusLight : Gump
{
public static void RefreshGump(Mobile m, Type type)
{
if (m.NetState == null)
{
return;
}
foreach (var g in m.NetState.Gumps)
{
if (g is GumpPlusLight && g.GetType() == type)
{
m.CloseGump(type);
((GumpPlusLight)g).NewGump();
return;
}
}
}
private readonly Mobile c_Owner;
private readonly Hashtable c_Buttons;
private readonly Hashtable c_Fields;
public Mobile Owner { get { return c_Owner; } }
public GumpPlusLight(Mobile m, int x, int y)
: base(x, y)
{
c_Owner = m;
c_Buttons = new Hashtable();
c_Fields = new Hashtable();
Timer.DelayCall(TimeSpan.FromSeconds(0), NewGump);
}
public void Clear()
{
Entries.Clear();
c_Buttons.Clear();
c_Fields.Clear();
}
public virtual void NewGump()
{
NewGump(true);
}
public void NewGump(bool clear)
{
if (clear)
{
Clear();
}
BuildGump();
c_Owner.SendGump(this);
}
public void SameGump()
{
c_Owner.SendGump(this);
}
protected abstract void BuildGump();
private int UniqueButton()
{
var random = 0;
do
{
random = Utility.Random(20000);
}
while (c_Buttons[random] != null);
return random;
}
private int UniqueTextId()
{
var random = 0;
do
{
random = Utility.Random(20000);
}
while (c_Buttons[random] != null);
return random;
}
public void AddBackgroundZero(int x, int y, int width, int height, int back)
{
AddBackgroundZero(x, y, width, height, back, true);
}
public void AddBackgroundZero(int x, int y, int width, int height, int back, bool over)
{
var plus = new BackgroundPlus(x, y, width, height, back, over);
Entries.Insert(0, plus);
}
public new void AddBackground(int x, int y, int width, int height, int back)
{
AddBackground(x, y, width, height, back, true);
}
public void AddBackground(int x, int y, int width, int height, int back, bool over)
{
var plus = new BackgroundPlus(x, y, width, height, back, over);
Add(plus);
}
public void AddButton(int x, int y, int id, GumpCallback callback)
{
AddButton(x, y, id, id, "None", callback);
}
public void AddButton(int x, int y, int id, GumpStateCallback callback, object arg)
{
AddButton(x, y, id, id, "None", callback, arg);
}
public void AddButton(int x, int y, int id, string name, GumpCallback callback)
{
AddButton(x, y, id, id, name, callback);
}
public void AddButton(int x, int y, int id, string name, GumpStateCallback callback, object arg)
{
AddButton(x, y, id, id, name, callback, arg);
}
public void AddButton(int x, int y, int up, int down, GumpCallback callback)
{
AddButton(x, y, up, down, "None", callback);
}
public void AddButton(int x, int y, int up, int down, string name, GumpCallback callback)
{
var id = UniqueButton();
var button = new ButtonPlus(x, y, up, down, id, name, callback);
Add(button);
c_Buttons[id] = button;
}
public void AddButton(int x, int y, int up, int down, GumpStateCallback callback, object arg)
{
AddButton(x, y, up, down, "None", callback, arg);
}
public void AddButton(int x, int y, int up, int down, string name, GumpStateCallback callback, object arg)
{
var id = UniqueButton();
var button = new ButtonPlus(x, y, up, down, id, name, callback, arg);
Add(button);
c_Buttons[id] = button;
}
public void AddHtml(int x, int y, int width, string text)
{
AddHtml(x, y, width, 21, HTML.White + text, false, false, true);
}
public void AddHtml(int x, int y, int width, string text, bool over)
{
AddHtml(x, y, width, 21, HTML.White + text, false, false, over);
}
public new void AddHtml(int x, int y, int width, int height, string text, bool back, bool scroll)
{
AddHtml(x, y, width, height, HTML.White + text, back, scroll, true);
}
public void AddHtml(int x, int y, int width, int height, string text, bool back, bool scroll, bool over)
{
var html = new HtmlPlus(x, y, width, height, HTML.White + text, back, scroll, over);
Add(html);
}
public void AddTextField(int x, int y, int width, int height, int color, int back, string name, string text)
{
var id = UniqueTextId();
AddImageTiled(x, y, width, height, back);
AddTextEntry(x, y, width, height, color, id, text);
c_Fields[id] = name;
c_Fields[name] = text;
}
public string GetTextField(string name)
{
if (c_Fields[name] == null)
{
return "";
}
return c_Fields[name].ToString();
}
public int GetTextFieldInt(string name)
{
return Utility.ToInt32(GetTextField(name));
}
protected virtual void OnClose()
{ }
public override void OnResponse(NetState state, RelayInfo info)
{
var name = "";
try
{
if (info.ButtonID == -5)
{
NewGump();
return;
}
foreach (var t in info.TextEntries)
{
c_Fields[c_Fields[t.EntryID].ToString()] = t.Text;
}
if (info.ButtonID == 0)
{
OnClose();
}
if (c_Buttons[info.ButtonID] == null || !(c_Buttons[info.ButtonID] is ButtonPlus))
{
return;
}
name = ((ButtonPlus)c_Buttons[info.ButtonID]).Name;
((ButtonPlus)c_Buttons[info.ButtonID]).Invoke();
}
catch (Exception e)
{
Errors.Report("An error occured during a gump response. More information can be found on the console.");
if (name != "")
{
Console.WriteLine("{0} gump name triggered an error.", name);
}
Console.WriteLine(e.Message);
Console.WriteLine(e.Source);
Console.WriteLine(e.StackTrace);
}
}
}
}

View File

@@ -0,0 +1,17 @@
namespace Knives.TownHouses
{
public class HTML
{
public static string White { get { return "<BASEFONT COLOR=#FFFFFF>"; } }
public static string Red { get { return "<BASEFONT COLOR=#FF0000>"; } }
public static string AshRed { get { return "<BASEFONT COLOR=#FF9999>"; } }
public static string Green { get { return "<BASEFONT COLOR=#00FF00>"; } }
public static string Blue { get { return "<BASEFONT COLOR=#0000FF>"; } }
public static string Gray { get { return "<BASEFONT COLOR=#999999>"; } }
public static string DarkGray { get { return "<BASEFONT COLOR=#222222>"; } }
public static string Black { get { return "<BASEFONT COLOR=#111111>"; } }
public static string Yellow { get { return "<BASEFONT COLOR=#FFFF00>"; } }
public static string Purple { get { return "<BASEFONT COLOR=#990099>"; } }
public static string LightPurple { get { return "<BASEFONT COLOR=#CC00FF>"; } }
}
}

View File

@@ -0,0 +1,23 @@
#region References
using Server.Gumps;
#endregion
namespace Knives.TownHouses
{
public class HtmlPlus : GumpHtml
{
public bool Override { get; set; }
public HtmlPlus(int x, int y, int width, int height, string text, bool back, bool scroll)
: base(x, y, width, height, text, back, scroll)
{
Override = true;
}
public HtmlPlus(int x, int y, int width, int height, string text, bool back, bool scroll, bool over)
: base(x, y, width, height, text, back, scroll)
{
Override = over;
}
}
}

View File

@@ -0,0 +1,32 @@
#region References
using Server;
#endregion
namespace Knives.TownHouses
{
public class InfoGump : GumpPlusLight
{
private readonly int c_Width;
private readonly int c_Height;
private readonly string c_Text;
private readonly bool c_Scroll;
public InfoGump(Mobile m, int width, int height, string text, bool scroll)
: base(m, 100, 100)
{
c_Width = width;
c_Height = height;
c_Text = text;
c_Scroll = scroll;
NewGump();
}
protected override void BuildGump()
{
AddBackground(0, 0, c_Width, c_Height, 0x13BE);
AddHtml(20, 20, c_Width - 40, c_Height - 40, HTML.White + c_Text, false, c_Scroll);
}
}
}

View File

@@ -0,0 +1,144 @@
#region References
using System;
using Server;
#endregion
namespace Knives.TownHouses
{
public class ContractConfirmGump : GumpPlusLight
{
private readonly RentalContract c_Contract;
public ContractConfirmGump(Mobile m, RentalContract rc)
: base(m, 100, 100)
{
m.CloseGump(typeof(ContractConfirmGump));
c_Contract = rc;
}
protected override void BuildGump()
{
var width = 300;
var y = 0;
if (c_Contract.RentalClient == null)
{
AddHtml(0, y + 5, width, HTML.Black + "<CENTER>Rent this House?");
}
else
{
AddHtml(0, y + 5, width, HTML.Black + "<CENTER>Rental Agreement");
}
var text =
String.Format(
" I, {0}, agree to rent this property from {1} for the sum of {2} every {3}. " +
"The funds for this payment will be taken directly from my bank. In the case where " +
"I cannot pay this fee, the property will return to {1}. I may cancel this agreement at any time by " +
"demolishing the property. {1} may also cancel this agreement at any time by either demolishing their " +
"property or canceling the contract, in which case your security deposit will be returned.",
c_Contract.RentalClient == null ? "_____" : c_Contract.RentalClient.Name,
c_Contract.RentalMaster.Name,
c_Contract.Free ? 0 : c_Contract.Price,
c_Contract.PriceTypeShort.ToLower());
text += "<BR> Here is some more info reguarding this property:<BR>";
text += String.Format("<CENTER>Lockdowns: {0}<BR>", c_Contract.Locks);
text += String.Format("Secures: {0}<BR>", c_Contract.Secures);
text += String.Format(
"Floors: {0}<BR>",
(c_Contract.MaxZ - c_Contract.MinZ < 200) ? (c_Contract.MaxZ - c_Contract.MinZ) / 20 + 1 : 1);
text += String.Format("Space: {0} cubic units", c_Contract.CalcVolume());
AddHtml(40, y += 30, width - 60, 200, HTML.Black + text, false, true);
y += 200;
if (c_Contract.RentalClient == null)
{
AddHtml(60, y += 20, 60, HTML.Black + "Preview");
AddButton(40, y + 3, 0x837, 0x838, "Preview", Preview);
var locsec = c_Contract.ValidateLocSec();
if (Owner != c_Contract.RentalMaster && locsec)
{
AddHtml(width - 100, y, 60, HTML.Black + "Accept");
AddButton(width - 60, y + 3, 0x232C, 0x232D, "Accept", Accept);
}
else
{
AddImage(width - 60, y - 10, 0x232C);
}
if (!locsec)
{
Owner.SendMessage(
(Owner == c_Contract.RentalMaster
? "You don't have the lockdowns or secures available for this contract."
: "The owner of this contract cannot rent this property at this time."));
}
}
else
{
if (Owner == c_Contract.RentalMaster)
{
AddHtml(60, y += 20, 100, HTML.Black + "Cancel Contract");
AddButton(40, y + 3, 0x837, 0x838, "Cancel Contract", CancelContract);
}
else
{
AddImage(width - 60, y += 20, 0x232C);
}
}
AddBackgroundZero(0, 0, width, y + 23, 0x24A4);
}
protected override void OnClose()
{
c_Contract.ClearPreview();
}
private void Preview()
{
c_Contract.ShowAreaPreview(Owner);
NewGump();
}
private void CancelContract()
{
if (Owner == c_Contract.RentalClient)
{
c_Contract.House.Delete();
}
else
{
c_Contract.Delete();
}
}
private void Accept()
{
if (!c_Contract.ValidateLocSec())
{
Owner.SendMessage("The owner of this contract cannot rent this property at this time.");
return;
}
c_Contract.Purchase(Owner);
if (!c_Contract.Owned)
{
return;
}
c_Contract.Visible = true;
c_Contract.RentalClient = Owner;
c_Contract.RentalClient.AddToBackpack(new RentalContractCopy(c_Contract));
}
}
}

View File

@@ -0,0 +1,670 @@
#region References
using System;
using System.Collections;
using Server;
using Server.Targeting;
#endregion
namespace Knives.TownHouses
{
public class ContractSetupGump : GumpPlusLight
{
public enum Page
{
Blocks,
Floors,
Sign,
LocSec,
Length,
Price
}
public enum TargetType
{
SignLoc,
MinZ,
MaxZ,
BlockOne,
BlockTwo
}
private readonly RentalContract c_Contract;
private Page c_Page;
public ContractSetupGump(Mobile m, RentalContract contract)
: base(m, 50, 50)
{
m.CloseGump(typeof(ContractSetupGump));
c_Contract = contract;
}
protected override void BuildGump()
{
var width = 300;
var y = 0;
switch (c_Page)
{
case Page.Blocks:
BlocksPage(width, ref y);
break;
case Page.Floors:
FloorsPage(width, ref y);
break;
case Page.Sign:
SignPage(width, ref y);
break;
case Page.LocSec:
LocSecPage(width, ref y);
break;
case Page.Length:
LengthPage(width, ref y);
break;
case Page.Price:
PricePage(width, ref y);
break;
}
AddBackgroundZero(0, 0, width, y + 40, 0x13BE);
}
private void BlocksPage(int width, ref int y)
{
if (c_Contract == null)
{
return;
}
c_Contract.ShowAreaPreview(Owner);
AddHtml(0, y += 10, width, "<CENTER>Create the Area");
AddImage(width / 2 - 100, y + 2, 0x39);
AddImage(width / 2 + 70, y + 2, 0x3B);
y += 25;
if (!General.HasOtherContract(c_Contract.ParentHouse, c_Contract))
{
AddHtml(60, y, 90, "Entire House");
AddButton(30, y, c_Contract.EntireHouse ? 0xD3 : 0xD2, "Entire House", EntireHouse);
}
if (!c_Contract.EntireHouse)
{
AddHtml(170, y, 70, "Add Area");
AddButton(240, y, 0x15E1, 0x15E5, "Add Area", AddBlock);
AddHtml(170, y += 20, 70, "Clear All");
AddButton(240, y, 0x15E1, 0x15E5, "Clear All", ClearBlocks);
}
var helptext =
String.Format(
" Welcome to the rental contract setup menu! To begin, you must " +
"first create the area which you wish to sell. As seen above, there are two ways to do this: " +
"rent the entire house, or parts of it. As you create the area, a simple preview will show you exactly " +
"what area you've selected so far. You can make all sorts of odd shapes by using multiple areas!");
AddHtml(10, y += 35, width - 20, 170, helptext, false, false);
y += 170;
if (c_Contract.EntireHouse || c_Contract.Blocks.Count != 0)
{
AddHtml(width - 60, y += 20, 60, "Next");
AddButton(width - 30, y, 0x15E1, 0x15E5, "Next", ChangePage, (int)c_Page + (c_Contract.EntireHouse ? 4 : 1));
}
}
private void FloorsPage(int width, ref int y)
{
AddHtml(0, y += 10, width, "<CENTER>Floors");
AddImage(width / 2 - 100, y + 2, 0x39);
AddImage(width / 2 + 70, y + 2, 0x3B);
AddHtml(40, y += 25, 80, "Base Floor");
AddButton(110, y, 0x15E1, 0x15E5, "Base Floor", MinZSelect);
AddHtml(160, y, 80, "Top Floor");
AddButton(230, y, 0x15E1, 0x15E5, "Top Floor", MaxZSelect);
AddHtml(
100,
y += 25,
100,
String.Format(
"{0} total floor{1}",
c_Contract.Floors > 10 ? "1" : "" + c_Contract.Floors,
c_Contract.Floors == 1 || c_Contract.Floors > 10 ? "" : "s"));
var helptext =
String.Format(
" Now you will need to target the floors you wish to rent out. " +
"If you only want one floor, you can skip targeting the top floor. Everything within the base " +
"and highest floor will come with the rental, and the more floors, the higher the cost later on.");
AddHtml(10, y += 35, width - 20, 120, helptext, false, false);
y += 120;
AddHtml(30, y += 20, 80, "Previous");
AddButton(10, y, 0x15E3, 0x15E7, "Previous", ChangePage, (int)c_Page - 1);
if (c_Contract.MinZ != short.MinValue)
{
AddHtml(width - 60, y, 60, "Next");
AddButton(width - 30, y, 0x15E1, 0x15E5, "Next", ChangePage, (int)c_Page + 1);
}
}
private void SignPage(int width, ref int y)
{
if (c_Contract == null)
{
return;
}
c_Contract.ShowSignPreview();
AddHtml(0, y += 10, width, "<CENTER>Their Sign Location");
AddImage(width / 2 - 100, y + 2, 0x39);
AddImage(width / 2 + 70, y + 2, 0x3B);
AddHtml(100, y += 25, 80, "Set Location");
AddButton(180, y, 0x15E1, 0x15E5, "Sign Loc", SignLocSelect);
var helptext =
String.Format(
" With this sign, the rentee will have all the powers an owner has " +
"over their area. If they use this power to demolish their rental unit, they have broken their " +
"contract and will not receive their security deposit. They can also ban you from their rental home!");
AddHtml(10, y += 35, width - 20, 110, helptext, false, false);
y += 110;
AddHtml(30, y += 20, 80, "Previous");
AddButton(10, y, 0x15E3, 0x15E7, "Previous", ChangePage, (int)c_Page - 1);
if (c_Contract.SignLoc != Point3D.Zero)
{
AddHtml(width - 60, y, 60, "Next");
AddButton(width - 30, y, 0x15E1, 0x15E5, "Next", ChangePage, (int)c_Page + 1);
}
}
private void LocSecPage(int width, ref int y)
{
AddHtml(0, y += 10, width, "<CENTER>Lockdowns and Secures");
AddImage(width / 2 - 100, y + 2, 0x39);
AddImage(width / 2 + 70, y + 2, 0x3B);
AddHtml(0, y += 25, width, "<CENTER>Suggest Secures");
AddButton(width / 2 - 70, y + 3, 0x2716, "Suggest LocSec", SuggestLocSec);
AddButton(width / 2 + 60, y + 3, 0x2716, "Suggest LocSec", SuggestLocSec);
AddHtml(
30,
y += 25,
width / 2 - 20,
"<DIV ALIGN=RIGHT>Secures (Max: " + (General.RemainingSecures(c_Contract.ParentHouse) + c_Contract.Secures) + ")");
AddTextField(width / 2 + 50, y, 50, 20, 0x480, 0xBBC, "Secures", c_Contract.Secures.ToString());
AddButton(width / 2 + 25, y + 3, 0x2716, "Secures", Secures);
AddHtml(
30,
y += 20,
width / 2 - 20,
"<DIV ALIGN=RIGHT>Lockdowns (Max: " + (General.RemainingLocks(c_Contract.ParentHouse) + c_Contract.Locks) + ")");
AddTextField(width / 2 + 50, y, 50, 20, 0x480, 0xBBC, "Lockdowns", c_Contract.Locks.ToString());
AddButton(width / 2 + 25, y + 3, 0x2716, "Lockdowns", Lockdowns);
var helptext =
String.Format(
" Without giving storage, this wouldn't be much of a home! Here you give them lockdowns " +
"and secures from your own home. Use the suggest button for an idea of how much you should give. Be very careful when " +
"renting your property: if you use too much storage you begin to use storage you reserved for your clients. " +
"You will receive a 48 hour warning when this happens, but after that the contract disappears!");
AddHtml(10, y += 35, width - 20, 180, helptext, false, false);
y += 180;
AddHtml(30, y += 20, 80, "Previous");
AddButton(10, y, 0x15E3, 0x15E7, "Previous", ChangePage, (int)c_Page - 1);
if (c_Contract.Locks != 0 && c_Contract.Secures != 0)
{
AddHtml(width - 60, y, 60, "Next");
AddButton(width - 30, y, 0x15E1, 0x15E5, "Next", ChangePage, (int)c_Page + 1);
}
}
private void LengthPage(int width, ref int y)
{
AddHtml(0, y += 10, width, "<CENTER>Time Period");
AddImage(width / 2 - 100, y + 2, 0x39);
AddImage(width / 2 + 70, y + 2, 0x3B);
AddHtml(120, y += 25, 50, c_Contract.PriceType);
AddButton(170, y + 8, 0x985, "LengthUp", LengthUp);
AddButton(170, y - 2, 0x983, "LengthDown", LengthDown);
var helptext =
String.Format(
" Every {0} the bank will automatically transfer the rental cost from them to you. " +
"By using the arrows, you can cycle through other time periods to something better fitting your needs.",
c_Contract.PriceTypeShort.ToLower());
AddHtml(10, y += 35, width - 20, 100, helptext, false, false);
y += 100;
AddHtml(30, y += 20, 80, "Previous");
AddButton(10, y, 0x15E3, 0x15E7, "Previous", ChangePage, (int)c_Page - (c_Contract.EntireHouse ? 4 : 1));
AddHtml(width - 60, y, 60, "Next");
AddButton(width - 30, y, 0x15E1, 0x15E5, "Next", ChangePage, (int)c_Page + 1);
}
private void PricePage(int width, ref int y)
{
AddHtml(0, y += 10, width, "<CENTER>Charge Per Period");
AddImage(width / 2 - 100, y + 2, 0x39);
AddImage(width / 2 + 70, y + 2, 0x3B);
AddHtml(0, y += 25, width, "<CENTER>Free");
AddButton(width / 2 - 80, y, c_Contract.Free ? 0xD3 : 0xD2, "Free", Free);
AddButton(width / 2 + 60, y, c_Contract.Free ? 0xD3 : 0xD2, "Free", Free);
if (!c_Contract.Free)
{
AddHtml(0, y += 25, width / 2 - 20, "<DIV ALIGN=RIGHT>Per " + c_Contract.PriceTypeShort);
AddTextField(width / 2 + 20, y, 70, 20, 0x480, 0xBBC, "Price", c_Contract.Price.ToString());
AddButton(width / 2 - 5, y + 3, 0x2716, "Price", Price);
AddHtml(0, y += 20, width, "<CENTER>Suggest");
AddButton(width / 2 - 70, y + 3, 0x2716, "Suggest", SuggestPrice);
AddButton(width / 2 + 60, y + 3, 0x2716, "Suggest", SuggestPrice);
}
var helptext =
String.Format(
" Now you can finalize the contract by including your price per {0}. " +
"Once you finalize, the only way you can modify it is to dump it and start a new contract! By " +
"using the suggest button, a price will automatically be figured based on the following:<BR>",
c_Contract.PriceTypeShort);
helptext += String.Format("<CENTER>Volume: {0}<BR>", c_Contract.CalcVolume());
helptext += String.Format("Cost per unit: {0} gold</CENTER>", General.SuggestionFactor);
helptext += "<br> You may also give this space away for free using the option above.";
AddHtml(10, y += 35, width - 20, 150, helptext, false, true);
y += 150;
AddHtml(30, y += 20, 80, "Previous");
AddButton(10, y, 0x15E3, 0x15E7, "Previous", ChangePage, (int)c_Page - 1);
if (c_Contract.Price != 0)
{
AddHtml(width - 70, y, 60, "Finalize");
AddButton(width - 30, y, 0x15E1, 0x15E5, "Finalize", FinalizeSetup);
}
}
protected override void OnClose()
{
c_Contract.ClearPreview();
}
private void SuggestPrice()
{
if (c_Contract == null)
{
return;
}
c_Contract.Price = c_Contract.CalcVolume() * General.SuggestionFactor;
if (c_Contract.RentByTime == TimeSpan.FromDays(1))
{
c_Contract.Price /= 60;
}
if (c_Contract.RentByTime == TimeSpan.FromDays(7))
{
c_Contract.Price = (int)(c_Contract.Price / 8.57);
}
if (c_Contract.RentByTime == TimeSpan.FromDays(30))
{
c_Contract.Price /= 2;
}
NewGump();
}
private void SuggestLocSec()
{
var price = c_Contract.CalcVolume() * General.SuggestionFactor;
c_Contract.Secures = price / 75;
c_Contract.Locks = c_Contract.Secures / 2;
c_Contract.FixLocSec();
NewGump();
}
private void Price()
{
c_Contract.Price = GetTextFieldInt("Price");
Owner.SendMessage("Price set!");
NewGump();
}
private void Secures()
{
c_Contract.Secures = GetTextFieldInt("Secures");
Owner.SendMessage("Secures set!");
NewGump();
}
private void Lockdowns()
{
c_Contract.Locks = GetTextFieldInt("Lockdowns");
Owner.SendMessage("Lockdowns set!");
NewGump();
}
private void ChangePage(object obj)
{
if (c_Contract == null || !(obj is int))
{
return;
}
c_Contract.ClearPreview();
c_Page = (Page)(int)obj;
NewGump();
}
private void EntireHouse()
{
if (c_Contract == null || c_Contract.ParentHouse == null)
{
return;
}
c_Contract.EntireHouse = !c_Contract.EntireHouse;
c_Contract.ClearPreview();
if (c_Contract.EntireHouse)
{
var list = new ArrayList();
var once = false;
foreach (var rect in RUOVersion.RegionArea(c_Contract.ParentHouse.Region))
{
list.Add(new Rectangle2D(new Point2D(rect.Start.X, rect.Start.Y), new Point2D(rect.End.X, rect.End.Y)));
if (once)
{
continue;
}
if (rect.Start.Z >= rect.End.Z)
{
c_Contract.MinZ = rect.End.Z;
c_Contract.MaxZ = rect.Start.Z;
}
else
{
c_Contract.MinZ = rect.Start.Z;
c_Contract.MaxZ = rect.End.Z;
}
once = true;
}
c_Contract.Blocks = list;
}
else
{
c_Contract.Blocks.Clear();
c_Contract.MinZ = short.MinValue;
c_Contract.MaxZ = short.MinValue;
}
NewGump();
}
private void SignLocSelect()
{
Owner.Target = new InternalTarget(this, c_Contract, TargetType.SignLoc);
}
private void MinZSelect()
{
Owner.SendMessage("Target the base floor for your rental area.");
Owner.Target = new InternalTarget(this, c_Contract, TargetType.MinZ);
}
private void MaxZSelect()
{
Owner.SendMessage("Target the highest floor for your rental area.");
Owner.Target = new InternalTarget(this, c_Contract, TargetType.MaxZ);
}
private void LengthUp()
{
if (c_Contract == null)
{
return;
}
c_Contract.NextPriceType();
if (c_Contract.RentByTime == TimeSpan.FromDays(0))
{
c_Contract.RentByTime = TimeSpan.FromDays(1);
}
NewGump();
}
private void LengthDown()
{
if (c_Contract == null)
{
return;
}
c_Contract.PrevPriceType();
if (c_Contract.RentByTime == TimeSpan.FromDays(0))
{
c_Contract.RentByTime = TimeSpan.FromDays(30);
}
NewGump();
}
private void Free()
{
c_Contract.Free = !c_Contract.Free;
NewGump();
}
private void AddBlock()
{
Owner.SendMessage("Target the north western corner.");
Owner.Target = new InternalTarget(this, c_Contract, TargetType.BlockOne);
}
private void ClearBlocks()
{
if (c_Contract == null)
{
return;
}
c_Contract.Blocks.Clear();
c_Contract.ClearPreview();
NewGump();
}
private void FinalizeSetup()
{
if (c_Contract == null)
{
return;
}
if (c_Contract.Price == 0)
{
Owner.SendMessage("You can't rent the area for 0 gold!");
NewGump();
return;
}
c_Contract.Completed = true;
c_Contract.BanLoc = c_Contract.ParentHouse.Region.GoLocation;
if (c_Contract.EntireHouse)
{
var point = c_Contract.ParentHouse.Sign.Location;
c_Contract.SignLoc = new Point3D(point.X, point.Y, point.Z - 5);
c_Contract.Secures = Core.AOS ? c_Contract.ParentHouse.GetAosMaxSecures() : c_Contract.ParentHouse.MaxSecures;
c_Contract.Locks = Core.AOS ? c_Contract.ParentHouse.GetAosMaxLockdowns() : c_Contract.ParentHouse.MaxLockDowns;
}
Owner.SendMessage("You have finalized this rental contract. Now find someone to sign it!");
}
private class InternalTarget : Target
{
private readonly ContractSetupGump c_Gump;
private readonly RentalContract c_Contract;
private readonly TargetType c_Type;
private readonly Point3D c_BoundOne;
public InternalTarget(ContractSetupGump gump, RentalContract contract, TargetType type)
: this(gump, contract, type, Point3D.Zero)
{ }
public InternalTarget(ContractSetupGump gump, RentalContract contract, TargetType type, Point3D point)
: base(20, true, TargetFlags.None)
{
c_Gump = gump;
c_Contract = contract;
c_Type = type;
c_BoundOne = point;
}
protected override void OnTarget(Mobile m, object o)
{
var point = (IPoint3D)o;
if (c_Contract == null || c_Contract.ParentHouse == null)
{
return;
}
if (!c_Contract.ParentHouse.Region.Contains(new Point3D(point.X, point.Y, point.Z)))
{
m.SendMessage("You must target within the home.");
m.Target = new InternalTarget(c_Gump, c_Contract, c_Type, c_BoundOne);
return;
}
switch (c_Type)
{
case TargetType.SignLoc:
c_Contract.SignLoc = new Point3D(point.X, point.Y, point.Z);
c_Contract.ShowSignPreview();
c_Gump.NewGump();
break;
case TargetType.MinZ:
if (!c_Contract.ParentHouse.Region.Contains(new Point3D(point.X, point.Y, point.Z)))
{
m.SendMessage("That isn't within your house.");
}
else if (c_Contract.HasContractedArea(point.Z))
{
m.SendMessage("That area is already taken by another rental contract.");
}
else
{
c_Contract.MinZ = point.Z;
if (c_Contract.MaxZ < c_Contract.MinZ + 19)
{
c_Contract.MaxZ = point.Z + 19;
}
}
c_Contract.ShowFloorsPreview(m);
c_Gump.NewGump();
break;
case TargetType.MaxZ:
if (!c_Contract.ParentHouse.Region.Contains(new Point3D(point.X, point.Y, point.Z)))
{
m.SendMessage("That isn't within your house.");
}
else if (c_Contract.HasContractedArea(point.Z))
{
m.SendMessage("That area is already taken by another rental contract.");
}
else
{
c_Contract.MaxZ = point.Z + 19;
if (c_Contract.MinZ > c_Contract.MaxZ)
{
c_Contract.MinZ = point.Z;
}
}
c_Contract.ShowFloorsPreview(m);
c_Gump.NewGump();
break;
case TargetType.BlockOne:
m.SendMessage("Now target the south eastern corner.");
m.Target = new InternalTarget(c_Gump, c_Contract, TargetType.BlockTwo, new Point3D(point.X, point.Y, point.Z));
break;
case TargetType.BlockTwo:
var rect = TownHouseSetupGump.FixRect(new Rectangle2D(c_BoundOne, new Point3D(point.X + 1, point.Y + 1, point.Z)));
if (c_Contract.HasContractedArea(rect, point.Z))
{
m.SendMessage("That area is already taken by another rental contract.");
}
else
{
c_Contract.Blocks.Add(rect);
c_Contract.ShowAreaPreview(m);
}
c_Gump.NewGump();
break;
}
}
protected override void OnTargetCancel(Mobile m, TargetCancelType cancelType)
{
c_Gump.NewGump();
}
}
}
}

View File

@@ -0,0 +1,76 @@
#region References
using System;
using Server;
#endregion
namespace Knives.TownHouses
{
public class TownHouseConfirmGump : GumpPlusLight
{
private readonly TownHouseSign c_Sign;
private bool c_Items;
public TownHouseConfirmGump(Mobile m, TownHouseSign sign)
: base(m, 100, 100)
{
c_Sign = sign;
}
protected override void BuildGump()
{
var width = 200;
var y = 0;
AddHtml(
0,
y += 10,
width,
String.Format("<CENTER>{0} this House?", c_Sign.RentByTime == TimeSpan.Zero ? "Purchase" : "Rent"));
AddImage(width / 2 - 100, y + 2, 0x39);
AddImage(width / 2 + 70, y + 2, 0x3B);
if (c_Sign.RentByTime == TimeSpan.Zero)
{
AddHtml(0, y += 25, width, String.Format("<CENTER>{0}: {1}", "Price", c_Sign.Free ? "Free" : "" + c_Sign.Price));
}
else if (c_Sign.RecurRent)
{
AddHtml(0, y += 25, width, String.Format("<CENTER>{0}: {1}", "Recurring " + c_Sign.PriceType, c_Sign.Price));
}
else
{
AddHtml(0, y += 25, width, String.Format("<CENTER>{0}: {1}", "One " + c_Sign.PriceTypeShort, c_Sign.Price));
}
if (c_Sign.KeepItems)
{
AddHtml(0, y += 20, width, "<CENTER>Cost of Items: " + c_Sign.ItemsPrice);
AddButton(20, y, c_Items ? 0xD3 : 0xD2, "Items", Items);
}
AddHtml(0, y += 20, width, "<CENTER>Lockdowns: " + c_Sign.Locks);
AddHtml(0, y += 20, width, "<CENTER>Secures: " + c_Sign.Secures);
AddButton(10, y += 25, 0xFB1, 0xFB3, "Cancel", Cancel);
AddButton(width - 40, y, 0xFB7, 0xFB9, "Confirm", Confirm);
AddBackgroundZero(0, 0, width, y + 40, 0x13BE);
}
private void Items()
{
c_Items = !c_Items;
NewGump();
}
private void Cancel()
{ }
private void Confirm()
{
c_Sign.Purchase(Owner, c_Items);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,241 @@
#if ServUO58
#define ServUOX
#endif
#region References
using System.Collections;
using Server;
using Server.Gumps;
using Server.Multis;
#endregion
namespace Knives.TownHouses
{
public class TownHousesGump : GumpPlusLight
{
public enum ListPage
{
Town,
House
}
public static void Initialize()
{
RUOVersion.AddCommand("TownHouses", AccessLevel.Counselor, OnHouses);
}
private static void OnHouses(CommandInfo info)
{
new TownHousesGump(info.Mobile);
}
private ListPage c_ListPage;
private int c_Page;
public TownHousesGump(Mobile m)
: base(m, 100, 100)
{
m.CloseGump(typeof(TownHousesGump));
}
protected override void BuildGump()
{
var width = 400;
var y = 0;
AddHtml(0, y += 10, width, "<CENTER>TownHouses Main Menu");
AddImage(width / 2 - 120, y + 2, 0x39);
AddImage(width / 2 + 90, y + 2, 0x3B);
var pp = 10;
if (c_Page != 0)
{
AddButton(width / 2 - 10, y += 25, 0x25E4, 0x25E5, "Page Down", PageDown);
}
var list = new ArrayList();
if (c_ListPage == ListPage.Town)
{
list.AddRange(TownHouseSign.AllSigns);
}
else
{
list.AddRange(BaseHouse.AllHouses);
}
list.Sort(new InternalSort());
AddHtml(
0,
y += 20,
width,
"<CENTER>" + (c_ListPage == ListPage.Town ? "TownHouses" : "Houses") + " Count: " + list.Count);
AddHtml(0, y += 25, width, "<CENTER>TownHouses / Houses");
AddButton(width / 2 - 100, y + 3, c_ListPage == ListPage.Town ? 0x939 : 0x2716, "Page", Page, ListPage.Town);
AddButton(width / 2 + 90, y + 3, c_ListPage == ListPage.House ? 0x939 : 0x2716, "Page", Page, ListPage.House);
TownHouseSign sign = null;
BaseHouse house = null;
y += 5;
for (var i = c_Page * pp; i < (c_Page + 1) * pp && i < list.Count; ++i)
{
if (c_ListPage == ListPage.Town)
{
sign = (TownHouseSign)list[i];
AddHtml(30, y += 20, width / 2 - 20, "<DIV ALIGN=LEFT>" + sign.Name);
AddButton(15, y + 3, 0x2716, "TownHouse Menu", TownHouseMenu, sign);
if (sign.House != null && sign.House.Owner != null)
{
AddHtml(width / 2, y, width / 2 - 40, "<DIV ALIGN=RIGHT>" + sign.House.Owner.RawName);
AddButton(width - 30, y + 3, 0x2716, "House Menu", HouseMenu, sign.House);
}
}
else
{
house = (BaseHouse)list[i];
AddHtml(30, y += 20, width / 2 - 20, "<DIV ALIGN=LEFT>" + house.Name);
AddButton(15, y + 3, 0x2716, "Goto", Goto, house);
if (house.Owner != null)
{
AddHtml(width / 2, y, width / 2 - 40, "<DIV ALIGN=RIGHT>" + house.Owner.RawName);
AddButton(width - 30, y + 3, 0x2716, "House Menu", HouseMenu, house);
}
}
}
if (pp * (c_Page + 1) < list.Count)
{
AddButton(width / 2 - 10, y += 25, 0x25E8, 0x25E9, "Page Up", PageUp);
}
if (c_ListPage == ListPage.Town)
{
AddHtml(0, y += 35, width, "<CENTER>Add New TownHouse");
AddButton(width / 2 - 80, y + 3, 0x2716, "New", New);
AddButton(width / 2 + 70, y + 3, 0x2716, "New", New);
}
AddBackgroundZero(0, 0, width, y + 40, 0x13BE);
}
private void TownHouseMenu(object obj)
{
if (!(obj is TownHouseSign))
{
return;
}
NewGump();
new TownHouseSetupGump(Owner, (TownHouseSign)obj);
}
private void Page(object obj)
{
c_ListPage = (ListPage)obj;
NewGump();
}
private void Goto(object obj)
{
if (!(obj is BaseHouse))
{
return;
}
Owner.Location = ((BaseHouse)obj).BanLocation;
Owner.Map = ((BaseHouse)obj).Map;
NewGump();
}
private void HouseMenu(object obj)
{
if (!(obj is BaseHouse))
{
return;
}
NewGump();
#if ServUOX
Owner.SendGump(new HouseGump(0, Owner, (BaseHouse)obj));
#else
if (Core.AOS)
{
Owner.SendGump(new HouseGumpAOS(0, Owner, (BaseHouse)obj));
}
else
{
Owner.SendGump(new HouseGump(Owner, (BaseHouse)obj));
}
#endif
}
private void New()
{
var sign = new TownHouseSign();
Owner.AddToBackpack(sign);
Owner.SendMessage("A new sign is now in your backpack. It will move on it's own during setup, but if you don't complete setup you may want to delete it.");
NewGump();
new TownHouseSetupGump(Owner, sign);
}
private void PageUp()
{
c_Page++;
NewGump();
}
private void PageDown()
{
c_Page--;
NewGump();
}
private class InternalSort : IComparer
{
public int Compare(object x, object y)
{
if (x == null && y == null)
{
return 0;
}
if (x is TownHouseSign)
{
var a = (TownHouseSign)x;
var b = (TownHouseSign)y;
return Insensitive.Compare(a.Name, b.Name);
}
else
{
var a = (BaseHouse)x;
var b = (BaseHouse)y;
if (a.Owner == null && b.Owner != null)
{
return -1;
}
if (a.Owner != null && b.Owner == null)
{
return 1;
}
return Insensitive.Compare(a.Owner.RawName, b.Owner.RawName);
}
}
}
}
}

View File

@@ -0,0 +1,422 @@
#region References
using System;
using System.Linq;
using Server;
using Server.Items;
using Server.Multis;
#endregion
namespace Knives.TownHouses
{
public class RentalContract : TownHouseSign
{
private Mobile c_RentalMaster;
private Mobile c_RentalClient;
private BaseHouse c_ParentHouse;
public BaseHouse ParentHouse { get { return c_ParentHouse; } }
public Mobile RentalClient
{
get { return c_RentalClient; }
set
{
c_RentalClient = value;
InvalidateProperties();
}
}
public Mobile RentalMaster { get { return c_RentalMaster; } }
public bool Completed { get; set; }
public bool EntireHouse { get; set; }
public RentalContract()
{
ItemID = 0x14F0;
Movable = true;
RentByTime = TimeSpan.FromDays(1);
RecurRent = true;
MaxZ = MinZ;
}
public bool HasContractedArea(Rectangle2D rect, int z)
{
foreach (Item item in AllSigns)
{
if (item is RentalContract && item != this && item.Map == Map && c_ParentHouse == ((RentalContract)item).ParentHouse)
{
foreach (Rectangle2D rect2 in ((RentalContract)item).Blocks)
{
for (var x = rect.Start.X; x < rect.End.X; ++x)
{
for (var y = rect.Start.Y; y < rect.End.Y; ++y)
{
if (rect2.Contains(new Point2D(x, y)))
{
if (((RentalContract)item).MinZ <= z && ((RentalContract)item).MaxZ >= z)
{
return true;
}
}
}
}
}
}
}
return false;
}
public bool HasContractedArea(int z)
{
foreach (Item item in AllSigns)
{
if (item is RentalContract && item != this && item.Map == Map && c_ParentHouse == ((RentalContract)item).ParentHouse)
{
if (((RentalContract)item).MinZ <= z && ((RentalContract)item).MaxZ >= z)
{
return true;
}
}
}
return false;
}
public void DepositTo(Mobile m)
{
if (m == null)
{
return;
}
if (Free)
{
m.SendMessage("Since this home is free, you do not receive the deposit.");
return;
}
m.BankBox.DropItem(new Gold(Price));
m.SendMessage("You have received a {0} gold deposit from your town house.", Price);
}
public override void ValidateOwnership()
{
if (Completed && c_RentalMaster == null)
{
Delete();
return;
}
if (c_RentalClient != null && (c_ParentHouse == null || c_ParentHouse.Deleted))
{
Delete();
return;
}
if (c_RentalClient != null && !Owned)
{
Delete();
return;
}
if (ParentHouse == null)
{
return;
}
if (!ValidateLocSec())
{
if (DemolishTimer == null)
{
BeginDemolishTimer(TimeSpan.FromHours(48));
}
}
else
{
ClearDemolishTimer();
}
}
protected override void DemolishAlert()
{
if (ParentHouse == null || c_RentalMaster == null || c_RentalClient == null)
{
return;
}
c_RentalMaster.SendMessage(
"You have begun to use lockdowns reserved for {0}, and their rental unit will collapse in {1}.",
c_RentalClient.Name,
Math.Round((DemolishTime - DateTime.UtcNow).TotalHours, 2));
c_RentalClient.SendMessage(
"Alert your land lord, {0}, they are using storage reserved for you. They have violated the rental agreement, which will end in {1} if nothing is done.",
c_RentalMaster.Name,
Math.Round((DemolishTime - DateTime.UtcNow).TotalHours, 2));
}
public void FixLocSec()
{
var count = 0;
if ((count = General.RemainingSecures(c_ParentHouse) + Secures) < Secures)
{
Secures = count;
}
if ((count = General.RemainingLocks(c_ParentHouse) + Locks) < Locks)
{
Locks = count;
}
}
public bool ValidateLocSec()
{
if (General.RemainingSecures(c_ParentHouse) + Secures < Secures)
{
return false;
}
if (General.RemainingLocks(c_ParentHouse) + Locks < Locks)
{
return false;
}
return true;
}
public override void ConvertItems(bool keep)
{
if (House == null || c_ParentHouse == null || c_RentalMaster == null)
{
return;
}
foreach (BaseDoor door in c_ParentHouse.Doors.OfType<BaseDoor>().ToArray())
{
if (door.Map == House.Map && House.Region.Contains(door.Location))
{
ConvertDoor(door);
}
}
foreach (SecureInfo info in c_ParentHouse.Secures.ToArray())
{
if (info.Item.Map == House.Map && House.Region.Contains(info.Item.Location))
{
c_ParentHouse.Release(c_RentalMaster, info.Item);
}
}
foreach (Item item in c_ParentHouse.LockDowns.Keys.ToArray())
{
if (item.Map == House.Map && House.Region.Contains(item.Location))
{
c_ParentHouse.Release(c_RentalMaster, item);
}
}
}
public override void UnconvertDoors()
{
if (House == null || c_ParentHouse == null)
{
return;
}
foreach (BaseDoor door in House.Doors.OfType<BaseDoor>().ToArray())
{
House.Doors.Remove(door);
}
}
protected override void OnRentPaid()
{
if (c_RentalMaster == null || c_RentalClient == null)
{
return;
}
if (Free)
{
return;
}
c_RentalMaster.BankBox.DropItem(new Gold(Price));
c_RentalMaster.SendMessage("The bank has transfered your rent from {0}.", c_RentalClient.Name);
}
public override void ClearHouse()
{
if (!Deleted)
{
Delete();
}
base.ClearHouse();
}
public override void OnDoubleClick(Mobile m)
{
ValidateOwnership();
if (Deleted)
{
return;
}
if (c_RentalMaster == null)
{
c_RentalMaster = m;
}
var house = BaseHouse.FindHouseAt(m);
if (c_ParentHouse == null)
{
c_ParentHouse = house;
}
if (house == null || (house != c_ParentHouse && house != House))
{
m.SendMessage("You must be in the home to view this contract.");
return;
}
if (m == c_RentalMaster && !Completed && house is TownHouse && ((TownHouse)house).ForSaleSign.PriceType != "Sale")
{
c_ParentHouse = null;
m.SendMessage("You can only rent property you own.");
return;
}
if (m == c_RentalMaster && !Completed && General.EntireHouseContracted(c_ParentHouse))
{
m.SendMessage("This entire house already has a rental contract.");
return;
}
if (Completed)
{
new ContractConfirmGump(m, this);
}
else if (m == c_RentalMaster)
{
new ContractSetupGump(m, this);
}
else
{
m.SendMessage("This rental contract has not yet been completed.");
}
}
public override void GetProperties(ObjectPropertyList list)
{
if (c_RentalClient != null)
{
list.Add("a house rental contract with " + c_RentalClient.Name);
}
else if (Completed)
{
list.Add("a completed house rental contract");
}
else
{
list.Add("an uncompleted house rental contract");
}
}
public override void Delete()
{
if (c_ParentHouse == null)
{
base.Delete();
return;
}
if (!Owned && !c_ParentHouse.IsFriend(c_RentalClient))
{
if (c_RentalClient != null && c_RentalMaster != null)
{
c_RentalMaster.SendMessage(
"{0} has ended your rental agreement. Because you revoked their access, their last payment will be refunded.",
c_RentalMaster.Name);
c_RentalClient.SendMessage(
"You have ended your rental agreement with {0}. Because your access was revoked, your last payment is refunded.",
c_RentalClient.Name);
}
DepositTo(c_RentalClient);
}
else if (Owned)
{
if (c_RentalClient != null && c_RentalMaster != null)
{
c_RentalClient.SendMessage(
"{0} has ended your rental agreement. Since they broke the contract, your are refunded the last payment.",
c_RentalMaster.Name);
c_RentalMaster.SendMessage(
"You have ended your rental agreement with {0}. They will be refunded their last payment.",
c_RentalClient.Name);
}
DepositTo(c_RentalClient);
PackUpHouse();
}
else
{
if (c_RentalClient != null && c_RentalMaster != null)
{
c_RentalMaster.SendMessage("{0} has ended your rental agreement.", c_RentalClient.Name);
c_RentalClient.SendMessage("You have ended your rental agreement with {0}.", c_RentalMaster.Name);
}
DepositTo(c_RentalMaster);
}
ClearRentTimer();
base.Delete();
}
public RentalContract(Serial serial)
: base(serial)
{
RecurRent = true;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(1); // version
// Version 1
writer.Write(EntireHouse);
writer.Write(c_RentalMaster);
writer.Write(c_RentalClient);
writer.Write(c_ParentHouse);
writer.Write(Completed);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadInt();
if (version >= 1)
{
EntireHouse = reader.ReadBool();
}
c_RentalMaster = reader.ReadMobile();
c_RentalClient = reader.ReadMobile();
c_ParentHouse = reader.ReadItem() as BaseHouse;
Completed = reader.ReadBool();
}
}
}

View File

@@ -0,0 +1,47 @@
#region References
using Server;
#endregion
namespace Knives.TownHouses
{
public class RentalContractCopy : Item
{
private readonly RentalContract c_Contract;
public RentalContractCopy(RentalContract contract)
{
Name = "rental contract copy";
ItemID = 0x14F0;
c_Contract = contract;
}
public override void OnDoubleClick(Mobile m)
{
if (c_Contract == null || c_Contract.Deleted)
{
Delete();
return;
}
c_Contract.OnDoubleClick(m);
}
public RentalContractCopy(Serial serial)
: base(serial)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,67 @@
#region References
using Server;
#endregion
namespace Knives.TownHouses
{
public class RentalLicense : Item
{
private Mobile c_Owner;
public Mobile Owner
{
get { return c_Owner; }
set
{
c_Owner = value;
InvalidateProperties();
}
}
public RentalLicense()
: base(0x14F0)
{ }
public override void GetProperties(ObjectPropertyList list)
{
if (c_Owner != null)
{
list.Add("a renter's license belonging to " + c_Owner.Name);
}
else
{
list.Add("a renter's license");
}
}
public override void OnDoubleClick(Mobile m)
{
if (c_Owner == null)
{
c_Owner = m;
}
}
public RentalLicense(Serial serial)
: base(serial)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
writer.Write(c_Owner);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.ReadInt();
c_Owner = reader.ReadMobile();
}
}
}

View File

@@ -0,0 +1,316 @@
#region References
using System.Collections;
using Server;
using Server.Multis;
using Server.Targeting;
#endregion
namespace Knives.TownHouses
{
public enum HammerJob
{
Flip,
Swap
}
public class SignHammer : Item
{
private static readonly Hashtable s_Table = new Hashtable();
private static readonly ArrayList s_List = new ArrayList();
public static void Initialize()
{
// Signs
s_Table[0xB95] = 0xB96;
s_Table[0xB96] = 0xB95;
s_Table[0xBA3] = 0xBA4;
s_Table[0xBA4] = 0xBA3;
s_Table[0xBA5] = 0xBA6;
s_Table[0xBA6] = 0xBA5;
s_Table[0xBA7] = 0xBA8;
s_Table[0xBA8] = 0xBA7;
s_Table[0xBA9] = 0xBAA;
s_Table[0xBAA] = 0xBA9;
s_Table[0xBAB] = 0xBAC;
s_Table[0xBAC] = 0xBAB;
s_Table[0xBAD] = 0xBAE;
s_Table[0xBAE] = 0xBAD;
s_Table[0xBAF] = 0xBB0;
s_Table[0xBB0] = 0xBAF;
s_Table[0xBB1] = 0xBB2;
s_Table[0xBB2] = 0xBB1;
s_Table[0xBB3] = 0xBB4;
s_Table[0xBB4] = 0xBB3;
s_Table[0xBB5] = 0xBB6;
s_Table[0xBB6] = 0xBB5;
s_Table[0xBB7] = 0xBB8;
s_Table[0xBB8] = 0xBB7;
s_Table[0xBB9] = 0xBBA;
s_Table[0xBBA] = 0xBB9;
s_Table[0xBBB] = 0xBBC;
s_Table[0xBBC] = 0xBBB;
s_Table[0xBBD] = 0xBBE;
s_Table[0xBBE] = 0xBBD;
s_Table[0xBBF] = 0xBC0;
s_Table[0xBC0] = 0xBBF;
s_Table[0xBC1] = 0xBC2;
s_Table[0xBC2] = 0xBC1;
s_Table[0xBC3] = 0xBC4;
s_Table[0xBC4] = 0xBC3;
s_Table[0xBC5] = 0xBC6;
s_Table[0xBC6] = 0xBC5;
s_Table[0xBC7] = 0xBC8;
s_Table[0xBC8] = 0xBC7;
s_Table[0xBC9] = 0xBCA;
s_Table[0xBCA] = 0xBC9;
s_Table[0xBCB] = 0xBCC;
s_Table[0xBCC] = 0xBCB;
s_Table[0xBCD] = 0xBCE;
s_Table[0xBCE] = 0xBCD;
s_Table[0xBCF] = 0xBD0;
s_Table[0xBD0] = 0xBCF;
s_Table[0xBD1] = 0xBD2;
s_Table[0xBD2] = 0xBD1;
s_Table[0xBD3] = 0xBD4;
s_Table[0xBD4] = 0xBD3;
s_Table[0xBD5] = 0xBD6;
s_Table[0xBD6] = 0xBD5;
s_Table[0xBD7] = 0xBD8;
s_Table[0xBD8] = 0xBD7;
s_Table[0xBD9] = 0xBDA;
s_Table[0xBDA] = 0xBD9;
s_Table[0xBDB] = 0xBDC;
s_Table[0xBDC] = 0xBDB;
s_Table[0xBDD] = 0xBDE;
s_Table[0xBDE] = 0xBDD;
s_Table[0xBDF] = 0xBE0;
s_Table[0xBE0] = 0xBDF;
s_Table[0xBE1] = 0xBE2;
s_Table[0xBE2] = 0xBE1;
s_Table[0xBE3] = 0xBE4;
s_Table[0xBE4] = 0xBE3;
s_Table[0xBE5] = 0xBE6;
s_Table[0xBE6] = 0xBE5;
s_Table[0xBE7] = 0xBE8;
s_Table[0xBE8] = 0xBE7;
s_Table[0xBE9] = 0xBEA;
s_Table[0xBEA] = 0xBE9;
s_Table[0xBEB] = 0xBEC;
s_Table[0xBEC] = 0xBEB;
s_Table[0xBED] = 0xBEE;
s_Table[0xBEE] = 0xBED;
s_Table[0xBEF] = 0xBF0;
s_Table[0xBF0] = 0xBEF;
s_Table[0xBF1] = 0xBF2;
s_Table[0xBF2] = 0xBF1;
s_Table[0xBF3] = 0xBF4;
s_Table[0xBF4] = 0xBF3;
s_Table[0xBF5] = 0xBF6;
s_Table[0xBF6] = 0xBF5;
s_Table[0xBF7] = 0xBF8;
s_Table[0xBF8] = 0xBF7;
s_Table[0xBF9] = 0xBFA;
s_Table[0xBFA] = 0xBF9;
s_Table[0xBFB] = 0xBFC;
s_Table[0xBFC] = 0xBFB;
s_Table[0xBFD] = 0xBFE;
s_Table[0xBFE] = 0xBFD;
s_Table[0xBFF] = 0xC00;
s_Table[0xC00] = 0xBFF;
s_Table[0xC01] = 0xC02;
s_Table[0xC02] = 0xC01;
s_Table[0xC03] = 0xC04;
s_Table[0xC04] = 0xC03;
s_Table[0xC05] = 0xC06;
s_Table[0xC06] = 0xC05;
s_Table[0xC07] = 0xC08;
s_Table[0xC08] = 0xC07;
s_Table[0xC09] = 0xC0A;
s_Table[0xC0A] = 0xC09;
s_Table[0xC0B] = 0xC0C;
s_Table[0xC0C] = 0xC0B;
s_Table[0xC0D] = 0xC0E;
s_Table[0xC0E] = 0xC0D;
// Hangers
s_Table[0xB97] = 0xB98;
s_Table[0xB98] = 0xB97;
s_Table[0xB99] = 0xB9A;
s_Table[0xB9A] = 0xB99;
s_Table[0xB9B] = 0xB9C;
s_Table[0xB9C] = 0xB9B;
s_Table[0xB9D] = 0xB9E;
s_Table[0xB9E] = 0xB9D;
s_Table[0xB9F] = 0xBA0;
s_Table[0xBA0] = 0xB9F;
s_Table[0xBA1] = 0xBA2;
s_Table[0xBA2] = 0xBA1;
// Hangers for swapping
s_List.Add(0xB97);
s_List.Add(0xB98);
s_List.Add(0xB99);
s_List.Add(0xB9A);
s_List.Add(0xB9B);
s_List.Add(0xB9C);
s_List.Add(0xB9D);
s_List.Add(0xB9E);
s_List.Add(0xB9F);
s_List.Add(0xBA0);
s_List.Add(0xBA1);
s_List.Add(0xBA2);
}
public HammerJob Job { get; set; }
[Constructable]
public SignHammer()
: base(0x13E3)
{
Name = "Sign Hammer";
}
public int GetFlipFor(int id)
{
return (s_Table[id] == null ? id : (int)s_Table[id]);
}
public int GetNextSign(int id)
{
if (!s_List.Contains(id))
{
return id;
}
var idx = s_List.IndexOf(id);
if (idx + 2 < s_List.Count)
{
return (int)s_List[idx + 2];
}
if (idx % 2 == 0)
{
return (int)s_List[0];
}
return (int)s_List[1];
}
public override void OnDoubleClick(Mobile m)
{
if (RootParent != m)
{
m.SendMessage("That item must be in your backpack to use.");
return;
}
var house = BaseHouse.FindHouseAt(m);
if (m.AccessLevel < AccessLevel.Counselor && (house == null || house.Owner != m))
{
m.SendMessage("You have to be inside your house to use this.");
return;
}
m.BeginTarget(3, false, TargetFlags.None, OnTarget);
}
protected void OnTarget(Mobile m, object obj)
{
var item = obj as Item;
if (item == null)
{
m.SendMessage("You cannot change that with this.");
return;
}
if (item == this)
{
new SignHammerGump(m, this);
return;
}
if (Job == HammerJob.Flip)
{
var id = GetFlipFor(item.ItemID);
if (id == item.ItemID)
{
m.SendMessage("You cannot change that with this.");
}
else
{
item.ItemID = id;
}
}
else
{
var id = GetNextSign(item.ItemID);
if (id == item.ItemID)
{
m.SendMessage("You cannot change that with this.");
}
else
{
item.ItemID = id;
}
}
}
public SignHammer(Serial serial)
: base(serial)
{ }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.ReadInt();
}
}
public class SignHammerGump : GumpPlusLight
{
private readonly SignHammer c_Hammer;
public SignHammerGump(Mobile m, SignHammer hammer)
: base(m, 100, 100)
{
c_Hammer = hammer;
NewGump();
}
protected override void BuildGump()
{
AddBackground(0, 0, 200, 200, 2600);
AddButton(50, 45, 2152, 2154, "Swap", Swap);
AddHtml(90, 50, 70, "Swap Hanger");
AddButton(50, 95, 2152, 2154, "Flip", Flip);
AddHtml(90, 100, 70, "Flip Sign or Hanger");
}
private void Swap()
{
c_Hammer.Job = HammerJob.Swap;
}
private void Flip()
{
c_Hammer.Job = HammerJob.Flip;
}
}
}

View File

@@ -0,0 +1,337 @@
#if ServUO58
#define ServUOX
#endif
#region References
using System;
using System.Collections.Generic;
using System.Linq;
using Server;
using Server.Multis;
using Server.Targeting;
#endregion
namespace Knives.TownHouses
{
public class TownHouse : VersionHouse
{
public static List<TownHouse> AllTownHouses { get; private set; }
static TownHouse()
{
AllTownHouses = new List<TownHouse>();
}
private readonly List<Sector> _Sectors = new List<Sector>();
private Item _Hanger;
public Item Hanger
{
get
{
return _Hanger ?? (_Hanger = new Item(0xB98)
{
Movable = false,
Location = Sign.Location,
Map = Sign.Map
});
}
set { _Hanger = value; }
}
public TownHouseSign ForSaleSign { get; private set; }
public override Rectangle2D[] Area
{
get
{
if (ForSaleSign == null)
{
return new Rectangle2D[100];
}
var rects = new Rectangle2D[ForSaleSign.Blocks.Count];
for (var i = 0; i < ForSaleSign.Blocks.Count && i < rects.Length; ++i)
{
rects[i] = (Rectangle2D)ForSaleSign.Blocks[i];
}
return rects;
}
}
public TownHouse(Mobile m, TownHouseSign sign, int locks, int secures)
: base(0x1DD6 | 0x4000, m, locks, secures)
{
ForSaleSign = sign;
SetSign(0, 0, 0);
AllTownHouses.Add(this);
}
public TownHouse(Serial serial)
: base(serial)
{
AllTownHouses.Add(this);
}
public void InitSectorDefinition()
{
if (ForSaleSign == null || ForSaleSign.Blocks.Count == 0)
{
return;
}
var blocks = (Rectangle2D)ForSaleSign.Blocks[0];
var minX = blocks.Start.X;
var minY = blocks.Start.Y;
var maxX = blocks.End.X;
var maxY = blocks.End.Y;
foreach (Rectangle2D rect in ForSaleSign.Blocks)
{
if (rect.Start.X < minX)
{
minX = rect.Start.X;
}
if (rect.Start.Y < minY)
{
minY = rect.Start.Y;
}
if (rect.End.X > maxX)
{
maxX = rect.End.X;
}
if (rect.End.Y > maxY)
{
maxY = rect.End.Y;
}
}
foreach (var sector in _Sectors)
{
sector.OnMultiLeave(this);
}
_Sectors.Clear();
for (var x = minX; x < maxX; ++x)
{
for (var y = minY; y < maxY; ++y)
{
var s = Map.GetSector(new Point2D(x, y));
if (!_Sectors.Contains(s))
_Sectors.Add(s);
}
}
foreach (var sector in _Sectors)
{
sector.OnMultiEnter(this);
}
Components.Resize(maxX - minX, maxY - minY);
Components.Add(0x520, Components.Width - 1, Components.Height - 1, -5);
}
public override bool IsInside(Point3D p, int height)
{
if (ForSaleSign == null)
{
return false;
}
if (Map == null || Region == null)
{
Delete();
return false;
}
Sector sector = null;
try
{
if (ForSaleSign is RentalContract && Region.Contains(p))
{
return true;
}
sector = Map.GetSector(p);
if (
sector.Multis.Any(
m =>
m != this && m is TownHouse && ((TownHouse)m).ForSaleSign is RentalContract && ((TownHouse)m).IsInside(p, height)))
{
return false;
}
return Region.Contains(p);
}
catch (Exception e)
{
Errors.Report("Error occured in IsInside(). More information on the console.");
Console.WriteLine("Info:{0}, {1}, {2}, {3}", Map, sector, Region, sector != null ? "" + sector.Multis : "**");
Console.WriteLine(e.Source);
Console.WriteLine(e.Message);
Console.WriteLine(e.StackTrace);
return false;
}
}
public static int MaxVendors = 50;
#if ServUOX
public override int GetVendorSystemMaxVendors()
{
return MaxVendors;
}
#else
public override int GetNewVendorSystemMaxVendors()
{
return MaxVendors;
}
#endif
public override int GetAosMaxSecures()
{
return MaxSecures;
}
public override int GetAosMaxLockdowns()
{
return MaxLockDowns;
}
public override void OnMapChange()
{
base.OnMapChange();
if (_Hanger != null)
{
_Hanger.Map = Map;
}
}
public override void OnLocationChange(Point3D oldLocation)
{
base.OnLocationChange(oldLocation);
if (_Hanger != null)
{
_Hanger.Location = Sign.Location;
}
}
public override void OnSpeech(SpeechEventArgs e)
{
if (e.Mobile != Owner || !IsInside(e.Mobile))
{
return;
}
if (e.Speech.ToLower() == "check house rent")
{
ForSaleSign.CheckRentTimer();
}
Timer.DelayCall(TimeSpan.Zero, new TimerStateCallback(AfterSpeech), e.Mobile);
}
private void AfterSpeech(object o)
{
if (!(o is Mobile))
{
return;
}
var m = (Mobile)o;
if (!(m.Target is HouseBanTarget) || ForSaleSign == null || !ForSaleSign.NoBanning)
{
return;
}
m.Target.Cancel(m, TargetCancelType.Canceled);
m.SendMessage(0x161, "You cannot ban people from this house.");
}
public override void OnDelete()
{
if (_Hanger != null)
{
_Hanger.Delete();
}
foreach (var item in Sign.GetItemsInRange(0).Where(item => item != Sign))
{
item.Visible = true;
}
ForSaleSign.ClearHouse();
Doors.Clear();
AllTownHouses.Remove(this);
base.OnDelete();
}
public override void OnAfterDelete()
{
base.OnAfterDelete();
AllTownHouses.Remove(this);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(4);
// Version 2
writer.Write(_Hanger);
// Version 1
writer.Write(ForSaleSign);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadInt();
if (version >= 2)
{
_Hanger = reader.ReadItem();
}
ForSaleSign = reader.ReadItem<TownHouseSign>();
if (version <= 2)
{
var count = reader.ReadInt();
for (var i = 0; i < count; ++i)
{
reader.ReadRect2D();
}
}
ItemID = 0x1DD6 | 0x4000;
Price = Math.Max(1, Price);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,39 @@
#region References
using Server;
#endregion
namespace Knives.TownHouses
{
public delegate void TownHouseCommandHandler(CommandInfo info);
public class CommandInfo
{
private readonly Mobile c_Mobile;
private readonly string c_Command;
private readonly string c_ArgString;
private readonly string[] c_Arguments;
public Mobile Mobile { get { return c_Mobile; } }
public string Command { get { return c_Command; } }
public string ArgString { get { return c_ArgString; } }
public string[] Arguments { get { return c_Arguments; } }
public CommandInfo(Mobile m, string com, string args, string[] arglist)
{
c_Mobile = m;
c_Command = com;
c_ArgString = args;
c_Arguments = arglist;
}
public string GetString(int num)
{
if (c_Arguments.Length > num)
{
return c_Arguments[num];
}
return "";
}
}
}

View File

@@ -0,0 +1,64 @@
#region References
using Server;
#endregion
namespace Knives.TownHouses
{
public class DecoreItemInfo
{
private string c_TypeString;
private string c_Name;
private int c_ItemID;
private int c_Hue;
private Point3D c_Location;
private Map c_Map;
public string TypeString { get { return c_TypeString; } }
public string Name { get { return c_Name; } }
public int ItemID { get { return c_ItemID; } }
public int Hue { get { return c_Hue; } }
public Point3D Location { get { return c_Location; } }
public Map Map { get { return c_Map; } }
public DecoreItemInfo()
{ }
public DecoreItemInfo(string typestring, string name, int itemid, int hue, Point3D loc, Map map)
{
c_TypeString = typestring;
c_ItemID = itemid;
c_Location = loc;
c_Map = map;
}
public void Save(GenericWriter writer)
{
writer.Write(1); // Version
// Version 1
writer.Write(c_Hue);
writer.Write(c_Name);
writer.Write(c_TypeString);
writer.Write(c_ItemID);
writer.Write(c_Location);
writer.Write(c_Map);
}
public void Load(GenericReader reader)
{
var version = reader.ReadInt();
if (version >= 1)
{
c_Hue = reader.ReadInt();
c_Name = reader.ReadString();
}
c_TypeString = reader.ReadString();
c_ItemID = reader.ReadInt();
c_Location = reader.ReadPoint3D();
c_Map = reader.ReadMap();
}
}
}

View File

@@ -0,0 +1,247 @@
#region References
using System.Linq;
using Server;
using Server.Multis;
#endregion
namespace Knives.TownHouses
{
public class General
{
public static string Version { get { return "3.01"; } }
// This setting determines the suggested gold value for a single square of a home
// which then derives price, lockdowns and secures.
public static int SuggestionFactor { get { return 600; } }
// This setting determines if players need License in order to rent out their property
public static bool RequireRenterLicense { get { return false; } }
public static void Configure()
{
EventSink.WorldSave += OnSave;
EventSink.ServerStarted += OnStarted;
EventSink.Login += OnLogin;
EventSink.Speech += HandleSpeech;
}
private static void OnStarted()
{
var i = TownHouse.AllTownHouses.Count;
while (--i >= 0)
{
if (i >= TownHouse.AllTownHouses.Count)
continue;
var h = TownHouse.AllTownHouses[i];
h.InitSectorDefinition();
RUOVersion.UpdateRegion(h.ForSaleSign);
}
}
public static void OnSave(WorldSaveEventArgs e)
{
var i = TownHouseSign.AllSigns.Count;
while (--i >= 0)
{
if (i >= TownHouseSign.AllSigns.Count)
continue;
var s = TownHouseSign.AllSigns[i];
s.ValidateOwnership();
}
}
private static void OnLogin(LoginEventArgs e)
{
var houses = BaseHouse.AllHouses.OfType<TownHouse>();
foreach (var house in houses.Where(h => h.IsSameAccount(h.Owner, e.Mobile)))
{
house.ForSaleSign.CheckDemolishTimer();
}
}
private static void HandleSpeech(SpeechEventArgs e)
{
try
{
var house = BaseHouse.FindHouseAt(e.Mobile);
if (house == null)
{
return;
}
if (house is TownHouse)
{
house.OnSpeech(e);
}
if (Insensitive.Equals(e.Speech, "create rental contract") && CanRent(e.Mobile, house, true))
{
e.Mobile.AddToBackpack(new RentalContract());
e.Mobile.SendMessage("A rental contract has been placed in your bag.");
}
else if (Insensitive.Equals(e.Speech, "check storage"))
{
int count;
e.Mobile.SendMessage(
"You have {0:#,0} lockdowns and {1:#,0} secures available.",
RemainingSecures(house),
RemainingLocks(house));
if ((count = AllRentalLocks(house)) != 0)
{
e.Mobile.SendMessage("Current rentals are using {0:#,0} of your lockdowns.", count);
}
if ((count = AllRentalSecures(house)) != 0)
{
e.Mobile.SendMessage("Current rentals are using {0:#,0} of your secures.", count);
}
}
}
catch
{ }
}
private static bool CanRent(Mobile m, BaseHouse house, bool say)
{
if (house is TownHouse && ((TownHouse)house).ForSaleSign.PriceType != "Sale")
{
if (say)
{
m.SendMessage("You must own your property to rent it.");
}
return false;
}
if (RequireRenterLicense)
{
var lic = m.Backpack.FindItemByType<RentalLicense>();
if (lic != null && lic.Owner == null)
{
lic.Owner = m;
}
if (lic == null || lic.Owner != m)
{
if (say)
{
m.SendMessage("You must have a renter's license to rent your property.");
}
return false;
}
}
if (EntireHouseContracted(house))
{
if (say)
{
m.SendMessage("This entire house already has a rental contract.");
}
return false;
}
if (RemainingSecures(house) < 0 || RemainingLocks(house) < 0)
{
if (say)
{
m.SendMessage("You don't have the storage available to rent property.");
}
return false;
}
return true;
}
#region Rental Info
public static bool EntireHouseContracted(BaseHouse house)
{
return TownHouseSign.AllSigns.OfType<RentalContract>().Any(s => house == s.ParentHouse && s.EntireHouse);
}
public static bool HasContract(BaseHouse house)
{
return TownHouseSign.AllSigns.OfType<RentalContract>().Any(s => house == s.ParentHouse);
}
public static bool HasOtherContract(BaseHouse house, RentalContract c)
{
return TownHouseSign.AllSigns.OfType<RentalContract>().Any(s => s != c && house == s.ParentHouse && s.EntireHouse);
}
public static int RemainingSecures(BaseHouse house)
{
if (house == null)
{
return 0;
}
int total;
if (Core.AOS)
{
int a, b, c, d;
total = house.GetAosMaxSecures() - house.GetAosCurSecures(out a, out b, out c, out d);
}
else
{
total = house.MaxSecures - house.SecureCount;
}
return total - AllRentalSecures(house);
}
public static int RemainingLocks(BaseHouse house)
{
if (house == null)
{
return 0;
}
int total;
if (Core.AOS)
{
total = house.GetAosMaxLockdowns() - house.GetAosCurLockdowns();
}
else
{
total = house.MaxLockDowns - house.LockDownCount;
}
return total - AllRentalLocks(house);
}
public static int AllRentalSecures(BaseHouse house)
{
return TownHouseSign.AllSigns.OfType<RentalContract>()
.Where(s => s.ParentHouse == house)
.Aggregate(0, (c, s) => c + s.Secures);
}
public static int AllRentalLocks(BaseHouse house)
{
return TownHouseSign.AllSigns.OfType<RentalContract>()
.Where(s => s.ParentHouse == house)
.Aggregate(0, (c, s) => c + s.Locks);
}
#endregion
}
}

View File

@@ -0,0 +1,132 @@
#if ServUO58
#define ServUOX
#endif
using System.Collections;
using Server;
using Server.Network;
using Server.Gumps;
using System.IO;
namespace Knives.TownHouses
{
public class GumpResponse
{
private static PacketHandler m_Successor;
public static void Initialize()
{
m_Successor = PacketHandlers.GetHandler(0xB1);
PacketHandlers.Register(0xB1, 0, true, DisplayGumpResponse);
#if !ServUOX
PacketHandlers.Register6017(0xB1, 0, true, DisplayGumpResponse);
#endif
}
public static void DisplayGumpResponse(NetState state, PacketReader pvSrc)
{
int serial = pvSrc.ReadInt32();
int typeID = pvSrc.ReadInt32();
int button = pvSrc.ReadInt32();
pvSrc.Seek(-12, SeekOrigin.Current);
int index = state.Gumps.Count;
while (--index >= 0)
{
if (index >= state.Gumps.Count)
continue;
Gump gump = state.Gumps[index];
if (gump == null)
continue;
if (gump.Serial == serial && gump.TypeID == typeID)
{
state.Gumps.RemoveAt(index);
if (!CheckResponse(gump, state.Mobile, button))
return;
if (!state.Gumps.Contains(gump))
state.Gumps.Insert(index, gump);
}
}
if (m_Successor != null)
m_Successor.OnReceive(state, pvSrc);
else
PacketHandlers.DisplayGumpResponse(state, pvSrc);
}
private static bool CheckResponse(Gump gump, Mobile m, int id)
{
if (m == null || !m.Player)
return true;
TownHouse th = null;
ArrayList list = new ArrayList();
foreach (Item item in m.GetItemsInRange(20))
{
if (item is TownHouse)
list.Add(item);
}
foreach (TownHouse t in list)
{
if (t.Owner == m)
{
th = t;
break;
}
}
if (th == null || th.ForSaleSign == null)
return true;
#if ServUOX
if (gump is HouseGump)
#else
if (gump is HouseGumpAOS)
#endif
{
int val = id - 1;
if (val < 0)
return true;
int type = val % 15;
int index = val / 15;
if (th.ForSaleSign.ForcePublic && type == 3 && index == 12 && th.Public)
{
m.SendMessage("This house cannot be private.");
m.SendGump(gump);
return false;
}
if (th.ForSaleSign.ForcePrivate && type == 3 && index == 13 && !th.Public)
{
m.SendMessage("This house cannot be public.");
m.SendGump(gump);
return false;
}
if (th.ForSaleSign.NoTrade && type == 6 && index == 1)
{
m.SendMessage("This house cannot be traded.");
m.SendGump(gump);
return false;
}
}
return true;
}
}
}

View File

@@ -0,0 +1,106 @@
#if ServUO58
#define ServUOX
#endif
#region References
using System;
using System.Collections.Generic;
using Server;
using Server.Commands;
using Server.Multis;
#endregion
namespace Knives.TownHouses
{
public class RUOVersion
{
private static readonly Dictionary<string, TownHouseCommandHandler> s_Commands =
new Dictionary<string, TownHouseCommandHandler>(StringComparer.OrdinalIgnoreCase);
public static void AddCommand(string com, AccessLevel acc, TownHouseCommandHandler cch)
{
s_Commands[com.ToLower()] = cch;
CommandSystem.Register(com, acc, OnCommand);
}
public static void OnCommand(CommandEventArgs e)
{
if (s_Commands[e.Command] != null)
{
s_Commands[e.Command](new CommandInfo(e.Mobile, e.Command, e.ArgString, e.Arguments));
}
}
public static void UpdateRegion(TownHouseSign sign)
{
if (sign.House == null)
{
return;
}
sign.House.UpdateRegion();
Rectangle3D rect;
for (var i = 0; i < sign.House.Region.Area.Length; ++i)
{
rect = sign.House.Region.Area[i];
sign.House.Region.Area[i] =
new Rectangle3D(
new Point3D(rect.Start.X - sign.House.X, rect.Start.Y - sign.House.Y, sign.MinZ),
new Point3D(rect.End.X - sign.House.X, rect.End.Y - sign.House.Y, sign.MaxZ));
}
sign.House.Region.Unregister();
sign.House.Region.Register();
sign.House.Region.GoLocation = sign.BanLoc;
}
public static bool RegionContains(Region region, Mobile m)
{
return m != null && m.Region.IsPartOf(region);
}
public static Rectangle3D[] RegionArea(Region region)
{
return region.Area;
}
}
public class VersionHouse : BaseHouse
{
public override Rectangle2D[] Area { get { return new Rectangle2D[5]; } }
public override Point3D BaseBanLocation { get { return Point3D.Zero; } }
public VersionHouse(int id, Mobile m, int locks, int secures)
: base(id, m, locks, secures)
{ }
public VersionHouse(Serial serial)
: base(serial)
{ }
#if !ServUOX
public override Server.Multis.Deeds.HouseDeed GetDeed()
{
return null;
}
#endif
// ReSharper disable RedundantOverridenMember
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
}
// ReSharper restore RedundantOverridenMember
}
}

Binary file not shown.