098 Asgard Script Set Download Now!

Post your Custom Scripts or Packages.

Moderator: POL Developer

Post Reply

Was this download helpful?

Yes
9
90%
No
1
10%
 
Total votes: 10

JaceAce
Expert Poster
Posts: 74
Joined: Fri Feb 29, 2008 10:56 pm

098 Asgard Script Set Download Now!

Post by JaceAce »

Thanks to Salinaksm!
Thanks to Pol Team!

Another script set ready to download!

Asgard!

(Remember they are what they are. This is not a "completely" flawless script set)
You will still need to "tweak" this script set. But it will help you on your way. It should compile and start up using POL 098. I recently fixed the region spawner to work although it may need "tweaking"
.createnpc was fixed too...

May Asgard Rise Again!

:grouphug:
Attachments
pol98Asgard-02.zip
Download this now! Need I say More?
(2.73 MiB) Downloaded 1005 times
Salinaksm
New User
Posts: 8
Joined: Mon Apr 27, 2009 5:42 am
Location: Salina, KS

Re: 098 Asgard Script Set Download Now!

Post by Salinaksm »

For a little history on this script base. At least for those who don't already know. Asgard is based off of the Ack Raw scripts which were based from the Ackadia scripts in which had there beginnings as an experiment by Dundee in a shard that used player policing instead of a large code of conduct and staff policing. This experiment got it's base script from WOD (The World Of Dreams), Dundee's first attempt at fixing what he thought made UO proper suck.
Today this script set rests somewhere between the two shard basis. Still designed around a player policed ruleset with many of the later additions too the WOD custom items base. Some of these custom items include viewable paintings, a dragon statue, marble horse statues and other various deco items.
Attached to this post you will find a zipped up copy of the verdata.mul file that contains these items. A new art.mul and artidx.mul can be created using UOFiddler, since the newer clients will not use the verdata file.
verdata.zip
(4.15 MiB) Downloaded 539 times
JaceAce
Expert Poster
Posts: 74
Joined: Fri Feb 29, 2008 10:56 pm

Re: 098 Asgard Script Set Download Now!

Post by JaceAce »

Note to all:

JaceAce does not support this script set. Salinaksm i believe supports this script set.

JaceAce supports the wod98 script set.
Salinaksm
New User
Posts: 8
Joined: Mon Apr 27, 2009 5:42 am
Location: Salina, KS

Re: 098 Asgard Script Set Download Now!

Post by Salinaksm »

At this time my official development of the conversion has stalled due to more important daily living issues taking up too much of my time. I'll be getting back on this script set as soon as time allows. You download and use this script set at your own peril. ¬_¬
As I have stated before, if you want to use any of the custom graphics defined in some of the deco scripts, you will have to download the verdata file i posted above and then merge that file into the art.idx and art.mul files of ML using UOFiddler. It's a simple and pretty pain free process, just takes Fiddler several minutes to do it. Other wise some deco deeds and items defined in this script set are useless. And you should remove these custom items, if not used, not so much for an overall folder size for the server but more for the fact that some of these items will try and spawn in high end chests and other loot.
If you have a question, send me a pm and I will try and get back to you as soon as I can. Hopefully with a usable solution. I am by no means a master scripter, and it was only with Jace's help that the scripts have gotten as far as they have, officially. My local Asgrad script set is a little different than the down loadable version here is, but I am not yet ready to replace Jace's upload with the slightly more advanced set yet.
That all said. Be warned, this conversion is nowhere near ready for live use yet. There are many bugs left to fix. Such as should be expected with a jump of three core versions. Keep in mind that this is a 95 - 98 conversion and is a very rough draft.
User avatar
billie_d_kidd
New User
Posts: 1
Joined: Sat Jul 11, 2009 11:56 am

Re: 098 Asgard Script Set Download Now!

Post by billie_d_kidd »

I'm new to the forum (and to the romp into the great unknown of UOem creation) but I wanted to let you know how much I am enjoying the script set you uploaded. A big thank you for sharing. I hope to see more of it in the future!
rainmaker24
New User
Posts: 12
Joined: Sun Feb 27, 2011 11:24 am

Re: 098 Asgard Script Set Download Now!

Post by rainmaker24 »

I"m having issues with the merchants for this script set. When I createnpc for any kind of "merchant" (not banker, or stablemaster)
the merchant is basically just an empty shell of a person. It doesn't respond to commands, the server isn't giving it a name and they just stay naked.

Is there something i'm doing wrong?
gundamwing84
Grandmaster Poster
Posts: 178
Joined: Tue Sep 08, 2009 1:57 am

Re: 098 Asgard Script Set Download Now!

Post by gundamwing84 »

Im also having a problem, with merchants like a mage or shipwright, they always reply that they are homeless.

although i know why(the towns.inc file is showing the wrong area for npcs to be in i suppose[this all has to do with townstones and area for towns])

i dont know how to fix it im unsure of this line in towns.inc:

Code: Select all

function FindTownFromLocation (x, y)
	if (x >=0   and x <=0   and y >= 0 and y <= 0 )
		return TOWN_BRENIN;

	endif
	return 0;
endfunction
(yes i have taken out the rest of the towns, i plan to make brenan britainia and have that as the only safe town on my shard)

i have never seen an x, y descriptor like that before so any help on that(or to properly set up a towns limits so the vendors dont always say they are homeless) would be much appreciated :)

Id also like to thank you for the awesome script set, it has really helped me out more then any others. i love the glowies system, spawner, and everything else :D thank you kindly :)

-Mat
gundamwing84
Grandmaster Poster
Posts: 178
Joined: Tue Sep 08, 2009 1:57 am

Re: 098 Asgard Script Set Download Now!

Post by gundamwing84 »

ok so im pretty sure i was able to work out those x and z. i made a picture for you on paint to what I think that line meant(lol dont laugh)

http://i1111.photobucket.com/albums/h46 ... 1301368740

if this is right let me know.

also if this IS right, i already set up britain the same way,
this is how i put it.

Code: Select all

function FindTownFromLocation (x, y)
	if (x >= 1285 and x <= 1706 and y >= 1550 and y <= 1802 )
		return TOWN_BRENIN;

	endif
	return 0;
endfunction
the vendors still say they are homeless which can i can only believe to be 2 things:
1. my theory about the x> <x, y> <y locater is wrong
2. something is wrong with the townstone.inc, towns.inc, townstone.src, or townnumbers.cfg.

im going to post these full scripts/inc/cfg files into codes below so u can have a look(these are all avaliable in the asgard script set)

towns.inc

Code: Select all

Const TOWN_BRENIN			:= 1;



Const TOWN_START			:= 1;
Const TOWN_END				:= 1;




///////////////////
//  Figures out out if a location is within a town, and if so, what town
///////////////////

function FindTownFromLocation (x, y)
	if (x >= 1285 and x <= 1706 and y >= 1550 and y <= 1802 )
		return TOWN_BRENIN;

	endif
	return 0;
endfunction




///////////////////
//  Finds the town that a given NPC is located in
///////////////////

function FindMyTown (npc)
	return FindTownFromLocation (npc.x, npc.y);
endfunction




///////////////////
//  Determines the name of a town from its number
///////////////////

function GetNameOfTown (townnum)
		
	case (townnum)
		TOWN_BRENIN:
			return "Brenin";
			
		default:
			return "";
	endcase
	return "";
endfunction

townstone.src

Code: Select all

use os;
use uo;

include "include/client";
//include "include/myutil";
include "include/yesno";
include "include/objtype";
include "../pkg/world/townstones/townstone";
include "../pkg/tools/gumps/customgumps";


var stonetownname, stoneempirename;
var stonetownnum, stoneempirenum;
var stonemayor, stoneempiremayor;

program townstone (who, stone);
	if (GetObjProperty (who, "#townstonemenu"))
		if (GetProcess (GetObjProperty (who, "#townstonemenu")))
			return;
		endif
	endif
	SetObjProperty (who, "#townstonemenu", GetPid());

	stonetownnum := GetObjProperty (stone, "townnum");
	stonetownname := GetObjProperty (stone, "town");

	//This should only occur once, when the townstone is created
	if (!GetGlobalProperty ("Townstone"+stonetownnum) )
		SetGlobalProperty ("Townstone"+stonetownnum, stone.serial);
		SetObjProperty (stone, "fealty", stonetownnum);
		SetObjProperty (stone, "empirename", stonetownname);
	endif

	stoneempirenum := GetEmpireNumber (stonetownnum);
	stoneempirename := GetEmpireName (stoneempirenum);

	if (!stonetownname or !stonetownnum or !stoneempirenum or !stoneempirename)
		SendSysMessage (who, "Hmm, something wrong with this stone.  Page a GM.");
		EraseObjProperty (who, "#townstonemenu");
		return;
	endif



	//Check to make sure that everyone we have listed as a member of town actually is
	SendSysMessage (who, "Loading, please wait...", FONT_NORMAL, FONTCOLOR_YELLOW);
	sleepms (200);
	FixRoster (stone);

	//Added to make sure that if the character has the town cprop - they are on the stone
	var town := GetObjProperty (who, "townnum");
	if ( town == stonetownnum )
		var roster := GetObjProperty (stone, "roster");
		if (!roster)
			roster := dictionary;
		endif
		if ( roster[who.serial] != who.name )
			roster[who.serial] := who.name;
			SetObjProperty (stone, "roster", roster);
		endif
	endif	
	if (!who.cmdlevel)
		if (BannedFromStone (who, stone))
			SendSysMessage (who, "You are banned from this stone and can not use it.", FONT_NORMAL, FONTCOLOR_YELLOW);
			EraseObjProperty (who, "#townstonemenu");
			return;
		endif
  	endif
	//Try to take over the stone.  Then check to see if they want to join the town
	if (CheckTownTakeOver (who, stone))
		EraseObjProperty (who, "#townstonemenu");
		return;
	endif
	if (CheckJoinTown (who, stone))
		EraseObjProperty (who, "#townstonemenu");
		return;
	endif

	//If they're not a member of the town or a member of the town's master stone, they can only
	//view the town roster
	var yourtown := getobjproperty (who, "townnum");
	if (!who.cmdlevel)
		if (BannedFromStone (who, stone) or !yourtown or (yourtown != stonetownnum and who != stoneempiremayor))
			DisplayRoster (who, stone, "roster");
			EraseObjProperty (who, "#townstonemenu");
			return;
		endif
  	endif

	var menuname := CSTR (stone.name);
	stonemayor := FindMayorOfTown (stonetownnum);
	stoneempiremayor := FindMayorOfTown (stoneempirenum);
	if (GetObjProperty (stone, "fealty"))
		menuname := menuname + " [loyal to " + stoneempirename + "]";
	endif

	//Verify that, if they're in the militia, they're in the right militia
	if (stonetownnum == yourtown and who.guildid and who.title_guild != "young")
		var townguild := GetGuildByTownNum (stoneempirenum);
		if (who.guildid != townguild.guildid)
			var oldguild := FindGuild (who.guildid);
			oldguild.RemoveMember (who);
			townguild.AddMember (who);
			who.title_guild := GetEmpireName (stonetownnum);
		endif
		DoWarThing (who.guildid);
	endif

	//Message so the player knows that they've already conquered this town
	if (stoneempirenum == yourtown and stoneempirenum != stonetownnum)
		SendSysMessage (who, "This town has declared fealty to you");
	endif
	
	//collect money if they're the mayor
	if (who == stoneempiremayor)
		CollectPay (who, stone);
	endif

	var militiaoption := "Join Militia";
	if (who.guildid and who.title_guild != "young")
		militiaoption := "Resign from Militia";
	endif

	var stonemenu := CreateCustomMenu (menuname, 1, 1);
	AddOptionToCustomMenu (stonemenu,  "Citizen Roster (and voting)");//1
	AddOptionToCustomMenu (stonemenu,  "Display Mayors");//2
	AddOptionToCustomMenu (stonemenu,  "Display Empires");//3
	AddOptionToCustomMenu (stonemenu,  militiaoption);//4
	AddOptionToCustomMenu (stonemenu,  "Visit Town's Website");//5
	if (who == stonemayor or who == stoneempiremayor or who.cmdlevel)
		AddOptionToCustomMenu (stonemenu, "Mayor's Menu");//6
	endif
	var selection := SelectCustomMenuOption (who, stonemenu);

	case ( selection[3] )
		1:	DisplayRoster (who, stone, "vote");
		2:	ListMayors (who, stone, "roster" );
		3:	DisplayEmpires (who);
		4:	JoinMilitia (who, stone);
		5:	VisitWebsite (who, stone);
		6:	DoMayorMenu (who, stone);
		default:
			SendSysMessage (who, "Canceled");
			EraseObjProperty (who, "#townstonemenu");
			return;
		endcase
		EraseObjProperty (who, "#townstonemenu");
endprogram




///////////////////
//  Special options just for the mayor of the town
///////////////////

function DoMayorMenu (who, stone)
	var menuname := cstr(stone.name + " [MAYOR " + who.name + "]");

	var stonemenu := CreateCustomMenu (menuname, 1, 1);
	AddOptionToCustomMenu (stonemenu, "Ban Citizen");//1
	AddOptionToCustomMenu (stonemenu, "Remove Ban");//2
	AddOptionToCustomMenu (stonemenu, "Ban non-Citizen");//3
	AddOptionToCustomMenu (stonemenu, "Make Wanted");//4
	AddOptionToCustomMenu (stonemenu, "Remove Wanted");//5
	AddOptionToCustomMenu (stonemenu, "Embargo");//6
	AddOptionToCustomMenu (stonemenu, "Declare Fealty");//7
	AddOptionToCustomMenu (stonemenu, "Enter Town WebSite");//8
	AddOptionToCustomMenu (stonemenu, "Declare War");//9
	AddOptionToCustomMenu (stonemenu, "Declare Peace");//10
	if (stonetownnum == stoneempirenum)
		AddOptionToCustomMenu (stonemenu, "Rename Empire");//11
	endif
	
	var selection := SelectCustomMenuOption(who, stonemenu);
	case ( selection[3] )
		1:
			DisplayRoster (who, stone, "ban");
		2:	
			DisplayBanned (who, stone);
		3:
			DisplayAll (who, stone, "ban");
		4:
			DisplayAll (who, stone, "wanted");
		5:
			DisplayWanted (who, stone);
		6:
			ListMayors (who, stone, "embargo");
		7:
			ListMayors (who, stone, "vote" );
		8:
			EnterWebSite ( who, stone );
		9:
			ListMayors (who, stone, "war" );
		10:
			ListMayors (who, stone, "peace" );
		11:
			RenameEmpire ( who, stone );
		default:
			SendSysMessage (who, "Canceled");
	endcase
endfunction

function RemoveMember( who, vote, stone, dict )

	var bans := dictionary;
	if ( getobjproperty(stone,"bans") )
		bans := getobjproperty(stone,"bans");
	endif

	var outcasts := dictionary;
	if ( getobjproperty(stone,"outcasts") )
		outcasts := getobjproperty(stone,"outcasts");
	endif

	var outcast := YesNo(who,"Make Outcast?");

	foreach memberserial in ( dict.keys() )
		if ( dict[ memberserial ] == vote )
			bans[ memberserial ] := vote;
			Setobjproperty(stone,"bans",bans);
			if (outcast)
				outcasts[ memberserial ] := vote;
				SetObjProperty(stone,"outcasts",outcasts);
			endif
			var jerk := systemfindobjectbyserial( memberserial );
			if (jerk)
				SendSysMessage(who,"You ban " + vote );
				RemoveFromRoster( jerk, getobjproperty(stone,"townnum") );
				SendSysMessage( jerk, "You have been removed from " + stone.name);
				if (outcast)
					SendSysMessage(who,"And " + vote + " is now an outcast" );
					SendSysMessage( jerk, "And outcast of " + stone.name);
				endif
				return;
			else
				foreach acctname in ListAccounts()
					var acct := FindAccount(acctname);
					for i := 1 to 5
						var char := acct.GetCharacter(i);
						if (char.serial == memberserial)
							SendSysMessage(who,"You ban " + vote );
							RemoveFromRoster( char, getobjproperty(stone,"townnum") );
							if (outcast)
								SendSysMessage(who,"And " + vote + " is now an outcast" );
							endif
							return;
						endif
					endfor
				endforeach
			endif
		endif
	endforeach

	SendSysMessage(who,"You are unable to ban " + vote);
endfunction


function DisplayWanted (who, stone)

	var menuname := cstr(stone.name);

	var wanted := dictionary;
	if ( getobjproperty(stone,"wanted") )
		wanted := getobjproperty(stone,"wanted");
	else
		SendSysMessage (who, "No one is wanted!");
		return;
	endif
	
	var roster := { };
	foreach memberserial in ( wanted.keys() )
		roster.append( wanted[ memberserial ] );
	endforeach

	var citnum := 1;
	var selection := { };
	repeat
		var stonemenu := CreateCustomMenu (menuname, 1, 1);
		var i;
		for ( i := citnum; i <= citnum+10; i := i + 1 )
			if ( i <= roster.size() )
				AddOptionToCustomMenu (stonemenu, roster[ i ]);
			endif
		endfor
		if ( roster.size() > (citnum+10) )
			AddOptionToCustomMenu (stonemenu, "NEXT PAGE");
		endif
		selection := SelectCustomMenuOption(who, stonemenu);
		if ( selection[3] == 12 )
			citnum := citnum + 10;
		else
			if ( selection[3] )
				var vote := (selection[3] + (citnum-1) );
				set_critical(1);
				RemoveWanted (who, roster[ vote ], stone, wanted);
				set_critical(0);
			endif
		endif
	until (selection[3] != 12);

endfunction

function DisplayBanned (who, stone)

	var menuname := cstr(stone.name);

	var bans := dictionary;
	if ( getobjproperty(stone,"bans") )
		bans := getobjproperty(stone,"bans");
	else
		SendSysMessage (who, "No one is banned!");
		return;
	endif
	
	var roster := { };
	foreach memberserial in ( bans.keys() )
		roster.append( bans[ memberserial ] );
	endforeach

	var citnum := 1;
	var selection := { };
	repeat
		var stonemenu := CreateCustomMenu(menuname, 1, 1);
		var i;
		for ( i := citnum; i <= citnum+10; i := i + 1 )
			if ( i <= roster.size() )
				AddOptionToCustomMenu (stonemenu, roster[ i ]);
			endif
		endfor
		if ( roster.size() > (citnum+10) )
			AddOptionToCustomMenu (stonemenu, "NEXT PAGE");
		endif
		selection := SelectCustomMenuOption(who, stonemenu);
		if ( selection[3] == 12 )
			citnum := citnum + 10;
		else
			if ( selection[3] )
				var vote := (selection[3] + (citnum-1) );
				set_critical(1);
				RemoveBan (who, roster[ vote ], stone, bans);
				set_critical(0);
			endif
		endif
	until (selection[3] != 12);

endfunction

function RemoveWanted (who, vote, stone, dict)
	var wanted := dictionary;
	var wantedbystone := dictionary;

	if (getobjproperty (stone, "wanted") )
		wanted := getobjproperty(stone,"wanted");
	endif

	
	foreach memberserial in (dict.keys())
		if (dict [memberserial] == vote)
			wanted.erase (memberserial);
			//Lets check the characters wanted tag
			if ( getobjproperty(memberserial,"wanted") )
				wantedbystone := getobjproperty(memberserial,"wanted"); // get the stones currently wanting this guy
			endif
			wantedbystone.erase (stone.name); // erase the stone from the wanted cprop
			Setobjproperty(memberserial,"wanted",wantedbystone); // resave the remaining stones 
			Setobjproperty (stone, "wanted", wanted);

					
			var jerk := FindPlayerBySerial (memberserial);
			if (jerk)
				SendSysMessage (who,"You lift the wanted status on " + vote );
				SendSysMessage (jerk, "Your wanted status has been removed from " + stone.name);
				return;
			endif
		endif
	endforeach

	SendSysMessage(who,"You are unable to un-want the person!");
endfunction

function RemoveBan (who, vote, stone, dict)
	var bans := dictionary;
	if (getobjproperty (stone, "bans") )
		bans := getobjproperty(stone,"bans");
	endif

	var outcasts := dictionary;
	if ( getobjproperty (stone, "outcasts") )
		outcasts := getobjproperty (stone, "outcasts");
	endif

	foreach memberserial in (dict.keys())
		if (dict [memberserial] == vote)
			bans.erase (memberserial);
			Setobjproperty (stone, "bans", bans);

			if ( outcasts.exists( memberserial ) )
				outcasts.erase(memberserial);
				SetObjProperty(stone,"outcasts",outcasts);
			endif
			
			var jerk := FindPlayerBySerial (memberserial);
			if (jerk)
				SendSysMessage (who,"You lift the ban on " + vote );
				SendSysMessage (jerk, "The ban has been removed from " + stone.name);
				return;
			endif
		endif
	endforeach

	SendSysMessage(who,"You are unable to un-ban the person!");
endfunction

function DisplayAll(who, stone, rosterfunction)
	var menuname := cstr (stone.name);

	var thisroster := dictionary;
	if (GetObjProperty (stone, "roster"))
		thisroster := getobjproperty (stone, "roster");
	endif

	var dict := dictionary;
	foreach acctname in ListAccounts()
		var acct := FindAccount (acctname);
		for charidx := 1 to 5
			var char := acct.GetCharacter( charidx );
			if (char)
				if (!thisroster.exists (char.serial) and (!char.cmdlevel) )
					if ( getobjproperty (char, "validchar"))
						var logon_time := CINT (GetObjProperty (who, "logontime"));
						if (logon_time > ReadGameClock() - 1209600)
							dict[ char.serial ] := char.name;
						endif
					endif
				endif
			endif
		endfor
	endforeach

	var roster := { };
	foreach memberserial in ( dict.keys() )
		roster.append( dict[ memberserial ] );
	endforeach

	var citnum := 1;
	var selection := { };
	repeat
		var stonemenu := CreateCustomMenu(menuname, 1, 1);
		var i;
		for ( i := citnum; i <= citnum+10; i := i + 1 )
			if ( i <= roster.size() )
				var citizen := roster[ i ];
				AddOptionToCustomMenu (stonemenu, citizen);
			endif
		endfor
		if ( roster.size() > (citnum+10) )
			AddOptionToCustomMenu (stonemenu, "NEXT PAGE");
		endif
		selection := SelectCustomMenuOption(who, stonemenu);
		if ( selection[3] == 12 )
			citnum := citnum + 10;
		else
			if ( selection[3] )
				var vote := (selection[3] + (citnum-1) );
				set_critical(1);
				case ( rosterfunction )
				"ban": RemoveNonMember( who, roster[ vote ], stone, dict );
				"wanted": MakeWanted ( who, roster[ vote ], stone, dict );
				"roster": return;
				endcase
				set_critical(0);
			endif
		endif
	until (selection[3] != 12);

endfunction

function MakeWanted( who, vote, stone, dict )

	var wanted := dictionary;
	var wantedbystone := dictionary;
	if ( getobjproperty(stone,"wanted") )
		wanted := getobjproperty(stone,"wanted");
	endif

	foreach memberserial in ( dict.keys() )
		if ( dict[ memberserial ] == vote )
			wanted[ memberserial ] := vote;
			Setobjproperty(stone,"wanted",wanted);
			
			var jerk := systemfindobjectbyserial( memberserial );

			// Lets check to see if they are wanted by anywhere else
			if ( getobjproperty(memberserial,"wanted") )
				wantedbystone := getobjproperty(memberserial,"wanted");
			endif
			// Lets add the new wanted flag
			wantedbystone[ stone.name ] := stone.name;
			Setobjproperty(memberserial,"wanted",wantedbystone);


			if (jerk)
				SendSysMessage(who,"You mark  " + vote + " wanted" );
				
				return;
			else
				foreach acctname in ListAccounts()
					var acct := FindAccount(acctname);
					for i := 1 to 5
						var char := acct.GetCharacter(i);
						if (char.serial == memberserial)
							SendSysMessage(who,"You mark  " + vote + " wanted" );
													
							return;
						endif
					endfor
				endforeach
			endif
		endif
	endforeach

	SendSysMessage(who,"You are unable to make wanted " + vote);

endfunction

function RemoveNonMember( who, vote, stone, dict )

	var bans := dictionary;
	if ( getobjproperty(stone,"bans") )
		bans := getobjproperty(stone,"bans");
	endif

	var outcasts := dictionary;
	if ( getobjproperty(stone,"outcasts") )
		outcasts := getobjproperty(stone,"outcasts");
	endif

	var outcast := YesNo(who,"Make Outcast?");

	foreach memberserial in ( dict.keys() )
		if ( dict[ memberserial ] == vote )
			bans[ memberserial ] := vote;
			Setobjproperty(stone,"bans",bans);
			if (outcast)
				outcasts[ memberserial ] := vote;
				SetObjProperty(stone,"outcasts",outcasts);
			endif
			var jerk := systemfindobjectbyserial( memberserial );
			if (jerk)
				SendSysMessage(who,"You ban " + vote );
				RemoveFromRoster( jerk, getobjproperty(stone,"townnum") );
				SendSysMessage( jerk, "You have been removed from " + stone.name);
				if (outcast)
					SendSysMessage(who,"And " + vote + " is now an outcast" );
					SendSysMessage( jerk, "And outcast of " + stone.name);
				endif
				return;
			else
				foreach acctname in ListAccounts()
					var acct := FindAccount(acctname);
					for i := 1 to 5
						var char := acct.GetCharacter(i);
						if (char.serial == memberserial)
							SendSysMessage(who,"You ban " + vote );
							RemoveFromRoster( char, getobjproperty(stone,"townnum") );
							if (outcast)
								SendSysMessage(who,"And " + vote + " is now an outcast" );
							endif
							return;
						endif
					endfor
				endforeach
			endif
		endif
	endforeach

	SendSysMessage(who,"You are unable to ban " + vote);

endfunction




///////////////////
//  The mayor of the town can swear fealty to another town
///////////////////

function swearfealty (who, stone, vote)
	if (getobjproperty(stone,"timeconquered"))
		var timeconquered := getobjproperty(stone,"timeconquered");
		if ( timeconquered > ReadGameClock() )
			EraseObjProperty( stone, "timeconquered" );
		elseif ( (timeconquered + 259200) > ReadGameClock() )
			SendSysMessage (who, "You can't change fealty yet!");
			return;
		endif
	endif
	var histownnum := FindTownByMayor (vote);
	if ( histownnum == stonetownnum)
		SendSysMessage (who, "Your city is now independent");
		eraseobjproperty (stone, "fealty");
		eraseobjproperty (stone, "empirename");
		SetObjProperty (stone, "lastpay", ReadGameClock());
		ReassignMilitia (stone, GetGuildByTownNum (stonetownnum));
		return;
	endif
	
	var hisstone := GetStoneByNumber (histownnum);
	if (!hisstone)
		SendSysMessage (who, "Error finding town!");
		return;
	endif
	
	if (GetObjProperty (hisstone, "fealty"))
		SendSysMessage (who, "That city is not independant.");
		return;
	endif
	
	SetObjProperty (stone, "fealty", histownnum);
	EraseObjProperty (stone, "empirename");
	SendSysMessage (who, "You swear fealty to " + vote);
	ReassignMilitia (stone, GetGuildByTownNum (histownnum));
	return;
endfunction




///////////////////
//  basically bans all the members of the given town
///////////////////

function EmbargoTown (who, stone, vote);
	var histownnum := FindTownByMayor (vote);
	if (!histownnum)
		return;
	endif
	if (histownnum == stonetownnum)
		SendSysMessage (who, "Your cannot embargo your own town!");
		return;
	endif

	var hisstone := GetStoneByNumber (histownnum);
	var hisroster := GetObjProperty (hisstone, "roster");
	if (!hisroster)
		return;
	endif
	
	var bans := GetObjProperty (stone, "bans");
	if (!bans)
		bans := dictionary;
	endif

	foreach citizen in ( hisroster.keys() )
		if (!bans.exists [citizen])
			bans [citizen] := hisroster [citizen];
			sendsysmessage( who, "You ban " + hisroster[ citizen ]);
		endif
	endforeach
	setobjproperty( stone, "bans", bans );
	broadcast (stone.name + " has banned the citizens of " + GetTownName (histownnum));
endfunction




///////////////////
//  Very messy way of doing things, this function tries to find the town by the name of its mayor...
///////////////////

function FindTownByMayor (mayorname)
	for townnum := 1 to 20
		var thatmayor := FindMayorOfTown (townnum);
		if (thatmayor.name == mayorname)
			return townnum;
		endif
	endfor
	return 0;
endfunction



///////////////////
//  Allows the lord of an empire to rename the empire
///////////////////

function RenameEmpire (who, stone)
	if (stoneempirenum != stonetownnum)
		SendSysMessage (who, "You do not have the authority to perform this action.");
		return;
	endif

	var EmpireName := SendTextEntryGump (who, "Rename the Empire:", TE_CANCEL_ENABLE, TE_STYLE_NORMAL, 30);
	if (!EmpireName)
		SendSysMessage (who, "Canceled");
		return;
	endif

	SetObjProperty( stone, "empirename", EmpireName );
	UpdateAllGuildTitles (EmpireName);
endfunction




///////////////////
//  When the name of the empire is changed, we have to change the titles of all the militia members
///////////////////

function UpdateAllGuildTitles (EmpireName)
	var townguildid := GetGuildByTownNum (stonetownnum);
	foreach acctname in ListAccounts()
		var acct := FindAccount (acctname);
		for charidx := 1 to 5
			var char := acct.GetCharacter (charidx);
			if (char)
				if (char.guildid == townguildid and char.title_guild != "young")
					char.title_guild := EmpireName;
				endif
			endif
		endfor
	endforeach
endfunction




///////////////////
//  Declare war on another town
///////////////////

function DeclareWarOnTown (who, stone, vote)
	var histownnum := FindTownByMayor (vote);
	if (!histownnum)
		SendSysMessage (who, "That ain't right.");
		return;
	endif
	if (histownnum == stonetownnum)
		SendSysMessage(who, "Your cannot declare war on your own town!");
		return;
	endif
	
	var hisempirenum := GetEmpireNumber (histownnum);
	if (hisempirenum == stoneempirenum)
		SendSysMessage (who, "That town is a member of your empire!");
		return;
	endif
	
	var hisstone := GetStoneByNumber (histownnum);
	var hisroster := GetObjProperty (hisstone, "militia");
	if (!hisroster)
		hisroster := dictionary;
	endif

	var bans := GetObjProperty (stone, "bans");
	if (!bans)
		bans := dictionary;
	endif

	foreach citizen in ( hisroster.keys() )
		if (!bans.exists[ citizen ] )
			bans[ citizen ] := hisroster[ citizen ];
			sendsysmessage( who, "You ban " + hisroster[ citizen ]);
		endif
	endforeach
	setobjproperty ( stone, "bans", bans );
	DeclareWar (who, stone, hisstone, histownnum);
endfunction

function warofftown ( who, stone, vote )
	var histownnum := FindTownByMayor( vote );
	if (!histownnum) return; endif
	var mytownnum := getobjproperty( stone, "townnum");
	var hisstoneserial := GetGlobalProperty("Townstone"+histownnum);
	var hisstone := SystemFindObjectBySerial( hisstoneserial );
	if ( histownnum == mytownnum )
		SendSysMessage(who, "Your at peace with your own town!");
		return;
	else
		DeclarePeace( who, stone, hisstone, histownnum );
		SendSysMessage( who, "Don't forget to lift the bans on their militia!" );
	endif

endfunction




///////////////////
//  Declare war on another town
///////////////////

function DeclareWar (who, fromstone, tostone, townnum)
	var wars := GetObjProperty (fromstone, "wars");
	if (!wars)
		wars := dictionary;
	endif

	if ( wars.exists ( townnum ) )
		SendSysMessage ( who, "You have already declared war on " + tostone.name );
	else
		wars[ townnum ] := ReadGameClock();
		SetObjProperty ( fromstone, "wars", wars );
		broadcast(fromstone.name + " has declared war on " + tostone.name, FONT_NORMAL, FONTCOLOR_RED);
	endif
endfunction

function DeclarePeace( who, fromstone, tostone, townnum )

	var wars := dictionary;
	if ( getobjproperty( fromstone, "wars" ) )
		wars := getobjproperty( fromstone, "wars" );
	else
		SendSysMessage( who, "You have not declared war any towns");
	endif

	if (!wars.exists( townnum ) )
		SendSysMessage( who, "You have not declared war with " + tostone.name );
	else
		wars.erase(townnum );
		if (!wars.size())
			EraseObjProperty( fromstone, "wars" );
		else
			SetObjProperty( fromstone, "wars", wars );
		endif
		broadcast(fromstone.name + " has declared peace with " + tostone.name, FONT_NORMAL, FONTCOLOR_GREEN);
		wars := GetObjProperty( tostone, "wars" );
		if ( wars.exists( GetObjProperty( fromstone, "townnum" )) )
			broadcast("(but " + tostone.name + " has still declared war on " + fromstone.name, FONT_NORMAL, FONTCOLOR_RED);
		endif
	endif

endfunction















///////////////////
//  Menu used for several functions, such as displaying the townmembers, voting on the mayor, etc
///////////////////

function DisplayRoster (who, stone, rosterfunction)
	var menuname := cstr(stone.name);
	var dict := GetObjProperty (stone, "roster");
	if (!dict or !dict.keys())
		SendSysMessage (who, "This stone seems to be abandoned.");
		return;
	endif

	var roster := { };
	foreach memberserial in (dict.keys())
		roster.append (dict [memberserial]);
	endforeach

	var militia := GetObjProperty (stone,"militia");
	if (!militia)
		militia := dictionary;
	endif
	var milroster := { };
	foreach name in (militia.keys())
		milroster.append (militia [name]);
	endforeach

	var mayor := FindMayorOfTown (stonetownnum);
	var citnum := 1;
	var selection := { };
	repeat
		var stonemenu := CreateCustomMenu (menuname, 1, 1);
		for i := citnum to (citnum + 10)
			if (i <= roster.size())
				var citizen := roster [ i ];
				if ( roster [ i ] == mayor.name)
					citizen := citizen + " [MAYOR]";
				endif
				if ( roster[ i ] in milroster )
					citizen := citizen + " [MILITIA]";
				endif
				AddOptionToCustomMenu (stonemenu, citizen);
			endif
		endfor
		if ( roster.size() > (citnum+10) )
			AddOptionToCustomMenu (stonemenu, "NEXT PAGE");
		endif
		selection := SelectCustomMenuOption (who, stonemenu);
		if (!selection[3])
			return;
		elseif (selection[3] == 12)
			citnum := citnum + 10;
		else
			var vote := selection[3] + (citnum-1);
			if (vote)
				case ( rosterfunction )
					"vote":
						set_critical(1);
						RecordVote (who, roster [vote], stone, dict);
						set_critical(0);
					"ban":
						set_critical(1);
						RemoveMember (who, roster [vote], stone, dict);
						set_critical(0);
					"roster":
						return;
					default:
						return;
				endcase
			endif
		endif
	until (selection[3] != 12);
endfunction




///////////////////
//  Set the player's vote for mayor
///////////////////

function RecordVote (who, vote, stone, dict)
	var votes := GetObjProperty (stone, "votes");
	if (!votes)
		votes := dictionary;
	endif

	foreach memberserial in (dict.keys())
		if (dict[ memberserial ] == vote)
			votes [who.serial] := memberserial;
			Setobjproperty (stone, "votes", votes);
			SendSysMessage (who, "You cast your vote for " + vote );
			return;
		endif
	endforeach

	SendSysMessage (who, "You are unable to vote for " + vote);
endfunction




///////////////////
//  Similar to DispayRoster, this function displays all the mayors and performs
//  different functions with them
///////////////////

function ListMayors (who, stone, menufunction)
	var roster := { };
	var mayorindex := { };
	var stoneindex := dictionary;
	for townnum := 1 to 20
		var thatstone := GetStoneByNumber (townnum);
		if (thatstone)
			var thatmayor := FindMayorOfTown (townnum);
			if (thatmayor)
				var displayname := thatmayor.name + ", " + GetTownName (townnum);
				roster.append (displayname);
				stoneindex [thatmayor.name] := thatstone;
				mayorindex.append (thatmayor.name);
			endif
		endif
	endfor

	var citnum := 1;
	var selection := { };
	repeat
		var stonemenu := CreateCustomMenu ("The mayors of Ackadia", 1, 1);
		for i := citnum to (citnum+10)
			if ( i <= roster.size() )
				var citizen := roster[ i ];
				AddOptionToCustomMenu (stonemenu, citizen);
			endif
		endfor
		if (roster.size() > (citnum+10))
			AddOptionToCustomMenu (stonemenu, "NEXT PAGE");
		endif
		selection := SelectCustomMenuOption (who, stonemenu);
		if (!selection[3])
			return;
		//Next page
		elseif (selection[3] == 12)
			citnum := citnum + 10;
		else
			var vote := (selection[3] + (citnum-1) );
			if (who == stonemayor or who == stoneempiremayor or who.cmdlevel)
				case ( menufunction )
					"vote":
						swearfealty (who, stone, mayorindex [vote]);
					"embargo":
						embargotown (who, stone, mayorindex [vote]);
					"war":
						DeclareWarOnTown (who, stone, mayorindex [vote]);
					"peace":
						warofftown (who, stone, mayorindex [vote]);
					default: 
						DisplayRoster( who, stoneindex[ mayorindex[ vote ]], "roster" );
				endcase
			else
				DisplayRoster( who, stoneindex[ mayorindex[ vote ]], "roster" );
			endif
			return;
		endif
	until (selection[3] != 12);

endfunction




///////////////////
//  Similar to DispayRoster, this function displays all the empires in the game
///////////////////

function DisplayEmpires (who)
	var empirelist := dictionary;
	var displaynames := { };
	for i := 1 to 20
		var thatstone := GetStoneByNumber (i);
		if (thatstone)
			if (!GetObjProperty (thatstone, "fealty"))
				var empirename := GetEmpireName (i);
				empirelist [empirename] := i;
				displaynames.append (empirename);
			endif
		endif
	endfor

	var citnum := 1;
	repeat
		var stonemenu := CreateCustomMenu ("Empires of Ackadia", 1, 1);
		for i := citnum to (citnum+10)
			if ( i <= displaynames.size() )
				AddOptionToCustomMenu (stonemenu, displaynames[i]);
			endif
		endfor
		if ( displaynames.size() > (citnum+10) )
			AddOptionToCustomMenu (stonemenu, "NEXT PAGE");
		endif
		var selection := SelectCustomMenuOption (who, stonemenu);
		if (!selection[3])
			return;
		elseif ( selection[3] == 12 )
			citnum := citnum + 10;
		else
			var vote := selection[3] + (citnum-1);
			DisplayEmpire (who, empirelist [displaynames [vote]]);
			return;
		endif
	until (selection[3] != 12);

endfunction




///////////////////
//  Displays all the towns in an empire
///////////////////

function DisplayEmpire (who, empirenum)
	var stone := GetStoneByNumber (empirenum);
	if (!stone)
		SendSysMessage (who, "That ain't good.");
		return;
	endif
	var substones := GetEmpireSubStones (empirenum);
	substones.append (stone);

	var empireindex := dictionary;
	var displaynames := { };
	foreach substone in substones
		empireindex [substone.name] := substone;
		displaynames.append (substone.name);
	endforeach

	var menuname := "The Empire of " + GetEmpireName (empirenum);
	var citnum := 1;
	repeat
		var stonemenu := CreateCustomMenu (menuname, 1, 1);
		for i := citnum to (citnum+10)
			if ( i <= substones.size() )
				AddOptionToCustomMenu (stonemenu, displaynames[i]);
			endif
		endfor

		if ( substones.size() > (citnum+10) )
			AddOptionToCustomMenu (stonemenu, "NEXT PAGE");
		endif
		var selection := SelectCustomMenuOption(who, stonemenu);
		if (!selection[3])
			return;
		elseif ( selection[3] == 12 )
			citnum := citnum + 10;
		else
			var selnum := selection[3] + (citnum-1);
			if (selnum)
				SendSysMessage (who, displaynames [selnum]);
				var thatstone := empireindex [displaynames [selnum]];
				DisplayRoster (who, thatstone, "roster");
				return;
			endif
		endif
	until (selection[3] != 12);
endfunction




///////////////////
//  Make sure that the guilds are correctly at war
///////////////////

function DoWarThing (guildid)
	var guild := FindGuild( guildid );
	foreach otherguild in ListGuilds ()
		guild.addenemyguild (otherguild);
	endforeach
	guild.addallyguild (guild);
endfunction




///////////////////
//  The head mayor of the empire can collect taxes
///////////////////

function CollectPay (who, stone)
	if (stonetownnum != stoneempirenum)
		if (who == stoneempiremayor)
			SendSysMessage (who, "You can only collect dues from the capital, you magesty.");
		endif
		//This is a substone
		return;
	endif

	if (who != stoneempiremayor)
		return;
	endif

	var lastpay := GetObjProperty (stone, "lastpay");
	if (!lastpay)
		SetObjProperty (stone, "lastpay", ReadGameClock());
		lastpay := ReadGameClock();
	endif
	
	var days := CINT((ReadGameClock() - lastpay) / 86400);
	if (!days)
		SendSysMessage (who, "It is not time to collect from this stone yet");
		return;
	endif
	
	SendSysMessage (who, days + " days have passed since you last collected");
	var substones := GetEmpireSubStones (stonetownnum);
	substones.append (stone);

	SendSysMessage (who, "You have " + substones.size() + " towns in your Empire");
	var countmembers := 0;
	var substonecount := 1;
	foreach substone in substones
		if (GetObjProperty (substone, "collectpay"))
			substonecount := substonecount + 1;
			var roster := GetObjProperty (substone, "roster");
			if (roster)
				countmembers := countmembers + roster.size();
			endif
		else
			setobjproperty (substone, "collectpay", 1);
		endif
		SetObjProperty (stone, "lastpay", (lastpay + (days*86400)));
	endforeach

	var payamount := substonecount * 250 + countmembers * 100;
	payamount := payamount * days;
	SendSysMessage (who, "You have collected " + payamount + " gold, Your Majesty.");
	if (payamount > 60000)
		repeat
			CreateItemInContainer (who.backpack, UOBJ_GOLD_COIN, 60000);
			payamount := payamount - 60000;
		until (payamount < 60000);
	endif

	CreateItemInContainer (who.backpack, UOBJ_GOLD_COIN, payamount);
endfunction




///////////////////
//  Allows the mayor to enter a website for the town
///////////////////

function EnterWebsite (who, stone)
	var townurl := SendTextEntryGump (who, "Enter this town's website URL:", TE_CANCEL_ENABLE, TE_STYLE_NORMAL, 40);
	if (!townurl)
		SendSysMessage (who, "Canceled");
		townurl := "http://www.ackadia.org/";
	endif

	SetObjProperty (stone, "townurl", townurl);
endfunction




///////////////////
//  Kewl function that can open a website from within the UO client
///////////////////

function VisitWebsite (who, stone)
	var townurl := GetObjProperty (stone, "townurl");
	if (!townurl)
		townurl := "http://www.ackadia.org/";
	endif
	OpenBrowser (who, townurl);
endfunction




///////////////////
//  Check to see if we want to join the militia, or, if we're already in the militia, resign
///////////////////

function JoinMilitia( who, stone )
	if (GetObjProperty (who, "townnum") != stonetownnum)
		SendSysMessage (who, "This is not your townstone!");
		return;
	endif
	
	if (who.title_guild == "young")
		SendSysMessage (who, "You can't join a militia when you are still young, try again later");
		return;
	endif

	var militia := GetObjProperty (stone, "militia");
	if (!militia)
		militia := dictionary;
	endif

	//if they're already in the militia, resign
	if (who.guildid)
		SendSysMessage (who, "You resign from the militia!");
		who.title_guild := "";
		var guild := FindGuild (who.guildid);
		guild.removemember (who);
		militia.erase (who.serial);
		SetObjProperty (stone, "militia", militia);
		return;
	endif
	
	var lastjoined := GetObjProperty (who, "joinedmilitia");
	if (!lastjoined)
		lastjoined := ReadGameClock() - 259201;
	endif
	
	//You can only join every 3 days
	var canjoinagain := lastjoined + 259200;
	if (canjoinagain > ReadGameClock())
		var hours := CINT ( (canjoinagain - ReadGameClock())/3600) + 1;
		SendSysMessage (who, "You can't join the militia again for " + hours + " hours!");
		return;
	endif

	militia [who.serial] := who.name;
	Setobjproperty (stone, "militia", militia);
	var guild :=GetGuildByTownNum (stonetownnum);
	guild.addmember (who);
	who.title_guild := GetEmpireName (stonetownnum);
	SendSysMessage (who, "Welcome to the army, soldier!");
	SetObjProperty (who, "joinedmilitia", ReadGameClock());
endfunction




///////////////////
//  Check to see if the player wants to join the town
///////////////////

function CheckJoinTown (who, stone)
	var yourtownnum := GetObjProperty (who, "townnum");
	if (yourtownnum == stonetownnum)
		//they already belong to this town
		return;
	endif

	var lastjoined := GetObjProperty (who, "joinedtown");
	if (lastjoined and lastjoined + 259200 > ReadGameClock())
		var hours := CINT ((lastjoined + 259000 - ReadGameClock())/3600);
		SendSysMessage (who, "You can't join another town for " + hours + " hours!");
		return;
	endif

	if (YesNo (who, "Join this town?") )
		RemoveFromRoster (who, yourtownnum);
		var roster := GetObjProperty (stone, "roster");
		if (!roster)
			roster := dictionary;
		endif
		roster[who.serial] := who.name;
		SetObjProperty (stone, "roster", roster);
		SetObjProperty (who, "townnum", stonetownnum);
		SetObjProperty (who, "joinedtown", ReadGameClock());
	endif
endfunction




///////////////////
//  Checks to see if the player wants to conquer the town (if they're in the militia and this
//  town isn't already a part of their empire
///////////////////

function CheckTownTakeOver (who, stone)
	if (!who.guildid or who.title_guild == "young" )
		return 0;
	endif

	var townguild := GetGuildByTownNum (stonetownnum);
	var townguildid := townguild.guildid;
	if (who.guildid == townguildid)
		return 0;
	endif

	var empirenum := GetEmpireNumber (GetObjProperty (who, "townnum"));
	if (!empirenum)
		return 0;
	endif
	if (empirenum == stoneempirenum)
		SendSysMessage (who, "This town is already part of your empire");
		return 0;
	endif

	//You can only conquer a town if there's less than 3 qualifying members of the militia
	var numdefenders := CountMilitia (stone);
	if (numdefenders >= 3)
		SendSysMessage (who, "This town is too well defended to conquer.");
		return 0;
	endif

	//Ask them if they want to
	if (!YesNo (who, "Conquer it?"))
		return 0;
	endif
	
	var newempirename := GetEmpireName (GetObjProperty (who, "townnum"));
	Broadcast (stonetownname + " has been conquered by " + who.name + " of " + newempirename, FONT_NORMAL, FONTCOLOR_RED);
	SysLog (stonetownname + " has been conquered by " + who.name + " of " + newempirename);

	ReassignMilitia (stone, who.guildid);
	RebuildEmpire (empirenum);
	SetObjproperty (stone, "fealty", empirenum);
	SetObjProperty (stone, "timeconquered", ReadGameClock());
	eraseobjproperty (stone, "collectpay");
	return 1;
endfunction




///////////////////
//  Calculates how many (qualifying) players are in the militia
///////////////////

function CountMilitia (stone)
	var militia := GetObjProperty (stone, "militia");
	if (!militia)
		return 0;
	endif

	var militiacount := 0;
	foreach playerserial in (militia.keys())
		var player := FindPlayerBySerial (playerserial);
		if (player and !player.dead)
			//They only count if they've logged on in the past 5 days
			if (GetObjProperty (player, "logontime") + 432000 > ReadGameClock())
				militiacount := militiacount + 1;
			endif
		endif
	endforeach
	return militiacount;
endfunction




///////////////////
//  Makes sure that all the substones of the conquered town are reassigned to the new empire
///////////////////

function RebuildEmpire (empirenum)
	foreach substone in GetEmpireSubStones (stonetownnum)
		SetObjProperty (substone, "fealty", empirenum);
	endforeach
endfunction




///////////////////
//  When a town gets conquered or declares independance, we have to reassign the militia to the new militia
///////////////////

function ReassignMilitia (stone, newguildid)
	SetObjProperty (stone, "guildid", newguildid);
	var militia := GetObjProperty (stone, "militia");
	if (!militia)
		militia := dictionary;
	endif
	
	var newguild := FindGuild (newguildid);
	if (!newguild)
		EraseObjProperty (stone, "guildid");
		return;
	endif
	
	var EmpireName := GetEmpireName (stonetownnum);
	foreach playerserial in (militia.keys())
		var player := FindPlayerBySerial (playerserial);
		if (player)
			if (player.guildid)
				var oldguild := FindGuild (player.guildid);
				oldguild.RemoveMember (player);
				newguild.AddMember (player);
				player.title_guild := EmpireName;
				
				if (!len (oldguild.members))
					DestroyGuild (oldguild);
				endif
			endif
		endif
	endforeach
	
	
	foreach substone in GetEmpireSubStones (stonetownnum)
		ReassignMilitia (substone, newguildid);
	endforeach
	
endfunction




///////////////////
//  Necessary evil for making sure all the data on the stone is up to date
///////////////////

function FixRoster (byref stone)
	set_critical (1);
	var roster := GetObjProperty (stone, "roster");
	
	if (!roster)
		return;
	endif
	var militia := GetObjProperty (stone, "militia");
	var votes := GetObjProperty (stone, "votes");

	foreach playerserial in (roster.keys())
		var player := FindPlayerBySerial (playerserial);
		if (!player)
			Syslog ("Removing " + roster[playerserial] + " from townstone " + stonetownnum + ", no longer exists");
			roster.erase (playerserial);
			votes.erase (playerserial);
			militia.erase (playerserial);
		else
			var playerstown := GetObjProperty (player, "townnum");
			//They shouldn't be a member of this town because they joined another one
			if (!playerstown or playerstown != stonetownnum)
				Syslog ("Removing " + roster[playerserial] + " from townstone " + stonetownnum + ", joined other town");
				roster.erase (playerserial);
				votes.erase (playerserial);
				militia.erase (playerserial);
			//They don't count if they haven't logged in in a month
			elseif (GetObjProperty (player, "logontime") < ReadGameClock() - 2592000)
				Syslog ("Removing " + roster[playerserial] + " from townstone " + stonetownnum + ", hasn't logged on in a month");
				roster.erase (playerserial);
				votes.erase (playerserial);
				militia.erase (playerserial);
			//They've been banned, so throw them out
			elseif (BannedFromStone (player, stone) or OutcastFromStone (player, stone))
				Syslog ("Removing " + roster[playerserial] + " from townstone " + stonetownnum + ", banned from town");
				roster.erase (playerserial);
				votes.erase (playerserial);
				militia.erase (playerserial);
			
			//DEBUG - should be a check for cmdlevel here, but disabled for testing
			endif
			//Make sure they're really supposed to be in the militia
			if (!player.guildid and player.title_guild != "young")
				player.title_guild := "";
				militia.erase (playerserial);
			endif
		endif
	endforeach
	
	//Make sure there's not someone in the militia that shouldn't be there
	foreach playerserial in (militia.keys())
		if (!roster.exists (playerserial))
			militia.erase (playerserial);
		else
			militia [playerserial] := roster [playerserial];
		endif
	endforeach
	
	//One more time for votes...
	foreach playerserial in (votes.keys())
		if (!roster.exists (playerserial))
			votes.erase (playerserial);
		endif
	endforeach
	
	SetObjProperty (stone, "roster", roster);
	SetObjProperty (stone, "militia", militia);
	SetObjProperty (stone, "votes", votes);
	set_critical (0);
endfunction

function OpenBrowser( who, url );
/*
0xA5 Packet
Open Web Browser (Variable # of bytes)
* BYTE cmd
* BYTE[2] blockSize
* BYTE[blockSize-3] null terminated full web address
*/

var tempvar := "";
var packetlength;
var i;

for( i := 1; i <= len( url ); i := i + 1 )
  tempvar := tempvar + ConvertLetterToHex( url[i] );
endfor

packetlength := (len( tempvar ) + 2 + 4) / 2;
packetlength := ConvertToPacketHex( packetlength );
CorrectSize( packetlength, 4 );

var terminator := cint(packetlength) - 3;

SendPacket(who, "A5"+packetlength+tempvar+terminator);
endfunction


function ConvertLetterToHex( letter )

   case( cstr(letter) )
     "A" : return "41";
     "Ä" : return "C4";
     "B" : return "42";
     "C" : return "43";
     "D" : return "44";
     "E" : return "45";
     "F" : return "46";
     "G" : return "47";
     "H" : return "48";
     "I" : return "49";
     "J" : return "4A";
     "K" : return "4B";
     "L" : return "4C";
     "M" : return "4D";
     "N" : return "4E";
     "O" : return "4F";
     "Ö" : return "D6";
     "P" : return "50";
     "Q" : return "51";
     "R" : return "52";
     "S" : return "53";
     "T" : return "54";
     "U" : return "55";
     "Ü" : return "DC";
     "V" : return "56";
     "W" : return "57";
     "X" : return "58";
     "Y" : return "59";
     "Z" : return "5A";

     "a" : return "61";
     "ä" : return "E4";
     "b" : return "62";
     "c" : return "63";
     "d" : return "64";
     "e" : return "65";
     "f" : return "66";
     "g" : return "67";
     "h" : return "68";
     "i" : return "69";
     "j" : return "6A";
     "k" : return "6B";
     "l" : return "6C";
     "m" : return "6D";
     "n" : return "6E";
     "o" : return "6F";
     "ö" : return "F6";
     "p" : return "70";
     "q" : return "71";
     "r" : return "72";
     "s" : return "73";
     "t" : return "74";
     "u" : return "75";
     "ü" : return "FC";
     "v" : return "76";
     "w" : return "77";
     "x" : return "78";
     "y" : return "79";
     "z" : return "7A";

     "!" : return "21";
     "/" : return "2F";
     "[" : return "5B";
     "]" : return "5D";
     "@" : return "40";
     "=" : return "3D";
     "#" : return "23";
     "'" : return "27";
     "´" : return "B4";
     "`" : return "60";
     "{" : return "7B";
     "}" : return "7D";
     "_" : return "5F";
     "," : return "2C";
     "." : return "2E";
     "<" : return "3C";
     ">" : return "3E";
     "|" : return "7C";
     "^" : return "5E";
     "ß" : return "DF";
     "?" : return "3F";
     ":" : return "3A";
     ";" : return "3B";
     "-" : return "2D";
     "+" : return "2B";
     "*" : return "2A";
     "(" : return "28";
     ")" : return "29";
     "1" : return "31";
     "2" : return "32";
     "3" : return "33";
     "4" : return "34";
     "5" : return "35";
     "6" : return "36";
     "7" : return "37";
     "8" : return "38";
     "9" : return "39";
     "0" : return "30";
     " " : return "20";
     default: exit;
  endcase

endfunction

function CorrectSize( byref pstring, laenge )

while( len(pstring) != laenge )
  pstring := "0"+pstring;
endwhile

endfunction


function ConvertToPacketHex( text )
var newhex := cstr(hex( text ));
newhex["0x"] := "";

return newhex;
endfunction


townnumbers.cfg

Code: Select all

Townstone 1
{
	townnumber	1
	townname	Brenin
	rect 1285 1550 1706 1802
}

townstone.inc

Code: Select all

use guilds;

///////////////////
//  Search for the nearest stone from the mobile
///////////////////

function FindMyStone (me)
	var mystone := FindStoneByLocation (me.x, me.y);
	return mystone;
endfunction




///////////////////
//  Search for the nearest stone to the location
///////////////////

function FindStoneByLocation (x, y)
	var parms := { };
	parms[1] := x;
	parms[2] := y;
	var mystone := run_script_to_completion (":townstones:findstone", parms);
	return mystone;
endfunction




///////////////////
//  Finds the stone of the given townnumber (1-20)
///////////////////

function GetStoneByNumber (townnum)
	var stoneserial := GetGlobalProperty ("Townstone"+townnum);
	if (stoneserial)
		var thatstone := SystemFindObjectBySerial (stoneserial);
		if (thatstone)
			return thatstone;
		endif
	endif
	return 0;
endfunction




///////////////////
//  Determines if the given player is banned from the given townstone
///////////////////

function BannedFromTown (who, townnum)
	var stone := GetStoneByNumber (townnum);
	return BannedFromStone (who, stone);
endfunction

function BannedFromStone (who, stone)
	if (!stone or !who)
		return 0;
	endif

	if (who.criminal)
		return 1;
	endif

	var bans := GetObjProperty (stone, "bans");
	if (!bans)
		return 0;
	endif
	if (bans.exists (who.serial))
		SendSysMessage (who, "You have been banned from " + stone.name);
		RemoveFromRoster (who, GetObjProperty (stone, "townnum"));
		return 1;
	endif
	return 0;
endfunction



///////////////////
//  Determines if the given player is outcast from the given townstone
///////////////////

function OutcastFromTown (who, townnum)
	var stone := GetStoneByNumber (townnum);
	return OutcastFromStone (who, stone);
endfunction

function OutcastFromStone (who, stone)
	if (!stone or !who)
		return 0;
	endif

	var outcasts := GetObjProperty (stone, "outcasts");
	if (!outcasts)
		return 0;
	endif
	if (outcasts.exists (who.serial))
		SendSysMessage (who, "You have been cast out from " + stone.name);
		return 1;
	endif
	return 0;
endfunction




///////////////////
//  Removes the given player from the town roster
///////////////////

function RemoveFromRoster (who, townnum)
	if (!who or !townnum)
		return;
	endif
	
	var yourtown := GetObjProperty (who, "townnum");
	if (yourtown != townnum)
		return;
	endif
	
	var oldstone := GetStoneByNumber (townnum);
	if (!oldstone)
		return;
	endif

	set_critical(1);
	var roster := GetObjProperty (oldstone, "roster");
	if (roster.exists (who.serial))
		roster.erase (who.serial);
		SetObjProperty (oldstone, "roster", roster);
	endif
	
	var votes  := GetObjProperty (oldstone, "votes");
	if (votes.exists (who.serial))
		votes.erase (who.serial);
		SetObjProperty (oldstone, "votes", votes);
	endif

	var militia := GetObjProperty (oldstone, "militia");
	if (militia.exists (who.serial))
		militia.erase (who.serial);
		SetObjProperty (oldstone, "militia", militia);
	endif

	if (who.guildid)
		who.title_guild := "";
		var guild := FindGuild (who.guildid);
		if (guild)
			guild.removemember (who);
		endif
	endif

	who.title_race := "";
	EraseObjProperty (who, "townnum");
	EraseObjProperty (who, "town");
	set_critical(0);
endfunction




///////////////////
//  Figures out the name of the town from the townnum
///////////////////

function GetTownName (townnum)
	var stone := GetStoneByNumber (townnum);
	if (!stone)
		return "";
	endif
	if (GetObjProperty (stone, "town"))
		return GetObjProperty (stone, "town");
	endif
	return "";
endfunction




///////////////////
//  Gets the name of the empire
///////////////////

function GetEmpireName (townnum)
	var masterstone := GetEmpireMasterStone (townnum);
	if (!masterstone)
		return "";
	endif

	var EmpireName := GetObjProperty (masterstone, "empirename");
	if (!EmpireName)
//		EmpireName := GetObjProperty (masterstone, "town") + " Militia";
		EmpireName := "No Empire";
	endif

	return EmpireName;
endfunction




///////////////////
//  Gets the townnumber of the empire
///////////////////

function GetEmpireNumber (townnum)
	var masterstone := GetEmpireMasterStone (townnum);
	if (!masterstone)
		return 0;
	endif

	var EmpireNum := GetObjProperty (masterstone, "townnum");
	if (!EmpireNum)
		return 0;
	endif
	return EmpireNum;
endfunction



///////////////////
//  Figures out the highest level stone of an empire
///////////////////

function GetEmpireMasterStone (townnum)
	var stone := GetStoneByNumber (townnum);
	if (!stone)
		return 0;
	endif

	if (GetObjProperty (stone, "fealty"))
		stone := GetStoneByNumber (GetObjProperty (stone, "fealty"));
	endif
	return stone;
endfunction




///////////////////
//  Returns an array of all the stonenumbers of stones loyal to the given empire
///////////////////

function GetEmpireSubStones (empirenum)
	var townstones := {};
	for i := 1 to 20
		var substone := GetStoneByNumber (i);
		if (substone)
			var fealty := GetObjProperty (substone, "fealty");
			if (fealty and fealty == empirenum)
				townstones.append (substone);
			endif		
		endif
	endfor
	return townstones;
endfunction





///////////////////
//  Tries to find the mayor of the given town
///////////////////

function FindMayorOfTown (townnum)
	var stone := GetStoneByNumber (townnum);
	if (!stone)
		return 0;
	endif
	
	var votes := GetObjProperty (stone, "votes");	//dictionary
	if (!votes)
		return 0;
	endif

	var roster := GetObjProperty (stone, "roster");	//dictionary
	if (!roster)
		return;
	endif

	var mayorvotes := dictionary;
	foreach playerserial in (votes.keys())
		var player := FindPlayerBySerial (playerserial);
		if (player)
			var laston := GetObjProperty (player, "logontime");
			if (!laston)
				laston := 0;
			endif
			if (laston + 1209600 > ReadGameClock())
				if (mayorvotes.exists (votes[playerserial]))
					mayorvotes [votes [playerserial]] := mayorvotes [votes [playerserial]] + 1;
				else
					mayorvotes [votes [playerserial]] := 1;
				endif
			endif
		endif
	endforeach
	
	//make sure somebody voted
	if (!mayorvotes.keys())
		return 0;
	endif
	
	var chosenmayor := 0;
	var highestvote := 0;
	foreach key in (mayorvotes.keys())
//		AlertGM (key + " got " + mayorvotes[key] + " votes");
		if (mayorvotes[key] > highestvote)
			highestvote := mayorvotes[key];
			chosenmayor := key;
		endif
	endforeach
	
	//Shouldn't happend, but may as well make sure
	if (!highestvote or !chosenmayor)
		return 0;
	endif
	return FindPlayerBySerial (chosenmayor);
endfunction




///////////////////
//  Figures out the town's guild
///////////////////

function GetGuildByTownNum (townnum)
	var stone := GetEmpireMasterStone (townnum);
	if (!stone)
		return 0;
	endif
	
	if (GetObjProperty (stone, "guildid"))
		var guild := FindGuild (GetObjProperty (stone, "guildid"));
		if (guild)
			return guild;
		endif
	endif

	var guild := CreateGuild();
	SetObjProperty (stone, "guildid", guild.guildid);

	//declare war on everyone
	foreach otherguild in ListGuilds()
		guild.addenemyguild (otherguild);
	endforeach
	guild.addallyguild (guild);
	return guild;
endfunction




///////////////////
//  Finds the online or offline player by their serial number
///////////////////

function FindPlayerBySerial (plrserial)
	var plr := SystemFindObjectBySerial (plrserial);
	if (!plr)
		plr := SystemFindObjectBySerial (plrserial, SYSFIND_SEARCH_OFFLINE_MOBILES);
	endif
	if (plr)
		return plr;
	endif
	return 0;
endfunction
Please help me out, this is the only thing i cant figure out after spending days on this.

kind regards,
-Mat
User avatar
*Edwards
Forum Regular
Posts: 303
Joined: Fri Dec 28, 2007 11:19 pm
Location: Montreal, Canada

Re: 098 Asgard Script Set Download Now!

Post by *Edwards »

I'm sure you could get some help with the fantasia//forgotten s scripts pkg. Look in pkg/systems/areas

This may give you more functionnalities with your regions.
gundamwing84
Grandmaster Poster
Posts: 178
Joined: Tue Sep 08, 2009 1:57 am

Re: 098 Asgard Script Set Download Now!

Post by gundamwing84 »

*Edwards wrote:I'm sure you could get some help with the fantasia//forgotten s scripts pkg. Look in pkg/systems/areas

This may give you more functionnalities with your regions.

wow im looking through it right now, and its exactly how i imagined this one im using now on asgard would be. i would like to use this to fix our own, however our merchant.src file is tied in with our townstones.(hence why they are saying they are homeless, im not sure how to get them to recognize britain as their "home" town) :(

as im not that great a scripter(im still learning) im worried if i try and incorporate this system into our asgard shard it still might not fix the merchant trouble :(

i will give it a try and get back to you, thankyou kindly for the help :)

-Mat
User avatar
*Edwards
Forum Regular
Posts: 303
Joined: Fri Dec 28, 2007 11:19 pm
Location: Montreal, Canada

Re: 098 Asgard Script Set Download Now!

Post by *Edwards »

That would be easy!

I.E.:

You setupt a property on your merchants in Britain via an automated system or by yourself. Let's say the name of the town.

Code: Select all

use uo;

include ":areas:managment";

function do_merchant_stuff( merchant )

     var get_merchant_region := GetObjProperty( merchant, "MerchantTown" );

     if( A_IsInArea( merchant, get_merchant_region ))
          //do stuff here.
     endif

     return 1;
endfunction
An automated script would not be that difficult
I.E.:
Find a script where you merchants are initialized

Code: Select all

use uo;

include ":areas:managment";

function set_merchant_region( merchant )

     var get_region := A_IsWhere( merchant );
     SetObjProperty( merchant, "MerchantTown", get_region );

     return 1;
endfunction
This is a plug and use package! Easily customized. You do not need extra pkg and this is meant to be like that!



I did not take the time to look at your merchant.src. If you still need help, ask here and someone might answer you shortly!
xblade
New User
Posts: 18
Joined: Thu Sep 02, 2010 4:47 am

Re: 098 Asgard Script Set Download Now!

Post by xblade »

Just wondering about the Verdata file , id like to download it and have but the extraction process seems not to work , saying that the File is corrupt , so just wondering if anyone got the chance to download it and post it up here for me and future others wanting the file :)
Cheers xblade :)
Post Reply