RunUO Community

This is a sample guest message. Register a free account today to become a member! Once signed in, you'll be able to participate on this site by adding your own topics and posts, as well as connect with other members through your own private inbox!

Commission Poll: Automated PvP

Popularity?

  • I don't think it will take off, but I'm not certain, go for it.

    Votes: 0 0.0%
  • I don't think it will take off, but I'm not certain, don't waste your time.

    Votes: 0 0.0%
  • Don't bother, you'll just be wasting your time.

    Votes: 0 0.0%

  • Total voters
    5
  • Poll closed .

Vorspire

Knight
Re-designing the UI to give it a more updated "look and feel", also to use a new "SuperGump" system where entry ID's are a thing of that past, because you can attach a delegate to each button that handles the click and also provides you with all the information you need about the clicked button (same applied to text entries, radios, check-boxes)
Was going to post a screenshot but the upload seems to be broken :(
 

Pure Insanity

Sorceror
Hmm, honestly. I could care less about the system. But I'd love to take a peak at the gumps and see what you're talking about, never considered using delegates for gumps.
 

Vorspire

Knight
I don't think anyone has considered using delegates for gumps, but it works and very nicely at that, for example:

Rich (BB code):
	public abstract class AutoPVP_UI_Template : SuperGump
	{
		private bool _Minimized = false;
		public bool Minimized { get { return _Minimized; } }

		public AutoPVP_UI_Template(Gump parent, PlayerMobile user, params object[] args)
			: base(parent, user, args)
		{
			if (Args[0] != null && Args[0] is Boolean)
			{ _Minimized = Args.Get<bool>(0); }
			else
			{ Args[0] = _Minimized; }

			AddBackground(0, 0, 600, 50, 9270);

			AddLabel(0, 0, 85, @"Left Title");

			if (!_Minimized)
			{ AddButton(395, 115, 250, 251, new ButtonResponse(MinimizeHandler)); }
			else
			{ AddButton(395, 115, 252, 253, new ButtonResponse(MinimizeHandler)); }

			AddLabel(303, 0, 85, @"Right Title");

			AddBackground(0, 50, 600, 350, 9270);
		}

		private void MinimizeHandler(GumpButton entry)
		{
			Args[0] = !_Minimized;
			Refresh();
		}
	}

That's a prototype, but the real magic happens when it comes to pagination and you have to assign an indexed button ID to each entry and append the entry index to he button ID, which can be annoying.
The SuperGump doesn't require any sort of buttonID, because you can specify the handler directly.
You can even use an in-line delegate as the handler (of course), which makes it even more easy.
The constructor for a SuperGump allows for a parent gump to be specified (for gump trees where applicable), the current PlayerMobile user and a list of object parameters (which are converted to an embedded SuperGump_Params class)

SuperGump params lets you pass any excess arguments to your gump without the need to create extra constructors other than what is needed, correct usage of the Args property (SuperGump_Params) can result in storage/retrieval of any values as long as you code the index properly when retrieving them.

The Supergump also comes with a Refresh and Close method as standard.
The Refresh method takes one argument (bool openIfClosed) - This will re-open the gump if it's closed, else ignore the Refresh call.
The Refresh method will automatically close the current gump and re-send it with all of the original constructor parameters including the embedded Args property, meaning your custom values can be changed in real-time then updated for the Refresh.

There are a lot of other features to the SuperGumps system, but they are not verified so I won't discuss them yet :)
 

Pure Insanity

Sorceror
Eh, pretty neat idea. Just seems like a bit of extra work for something that I'm working on. But of course...if you have the SuperGump class already built...guess it's not much work. =P

Currently I'm working on a gump(s) that will basically be like a double panned explorer window. Allowing different "pages" on each side. I'm doing it based the info that is sent to the gump, like most gumps do. Imagine I could make it a lot more cleaner and probably would of saved myself some work of dealing with the multiple List<>'s by using delegates like you did...but oh well. Guess I stick to my old way.

I just like picking your brain for ideas some times, as you are pretty good at thinking outside the box...which is what I like. =D

Now if only you'd stop toying with old crappy php and move onto asp.net...heh. =P
 

Jeff

Lord
Code:
AddButton(395, 115, 250, 251, new ButtonResponse(MinimizeHandler));
can be...
Code:
AddButton(395, 115, 250, 251, MinimizeHandler);
no need for the response wrapper... quite uneeded.
 

Pure Insanity

Sorceror
Doing it the first way...would actually use an extra amount of un-needed memory...correct? Seeing as how it's creating a new one each time that code is called...of course without seeing all the code, I can't confirm this...
 

Vorspire

Knight
Code:
AddButton(395, 115, 250, 251, new ButtonResponse(MinimizeHandler));
can be...
Code:
AddButton(395, 115, 250, 251, MinimizeHandler);
no need for the response wrapper... quite uneeded.

Because this is an excerpt example that doesn't feature the ButtonResponse delegate, I thought it better to include it as a point of reference, no point in obfuscating examples for no reason.
I've been writing TimerCallbacks for years without declaring TimeStateCallback handlers ;)

Doing it the first way...would actually use an extra amount of un-needed memory...correct? Seeing as how it's creating a new one each time that code is called...of course without seeing all the code, I can't confirm this...

Like 1 byte of overhead I think, heh :)

At the end of the day, using a delegate is going to save you development time and if it does actually impact on the resources it needs to run, I would doubt it would be noticeable, so it's definately a plus for me :)

You're doing a double-panelled gump with pagination support on both panels?
I did that for Skill/Spell restrictions for the PvP system, here's the working version if it helps, but the old Gump class file is pretty bloated and probably contains unnecessary code as I lifted it's base design quickly from another gump script I had done about 2 years ago.
Rich (BB code):
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.IO;

using Server;
using Server.Mobiles;
using Server.Regions;
using Server.Gumps;
using Server.Network;
using Server.Spells;

namespace Server.AutoPVP
{
	public class AutoPVP_AdminRestrictionsUI : Gump
	{
		public enum Buttons
		{
			Null = 0,
			PreviousSkills = 1,
			NextSkills = 2,
			PreviousSpells = 3,
			NextSpells = 4
		}

		private PlayerMobile _User = null;
		private AutoPVP_AdminBattlesUI _BattleUI = null;
		private AutoPVP_Battle _Battle = null;
		private int
			_SkillsPerPage = 9,
			_SkillYSpacer = 35,
			_SkillsPage = 0,
			_SpellsPerPage = 9,
			_SpellsYSpacer = 35,
			_SpellsPage = 0,
			_FontHue = 84,
			_ErrorHue = 237,
			_IndexBase = 10000,
			_SkillsLength = 0,
			_SpellsLength = 0;

		public AutoPVP_AdminRestrictionsUI(PlayerMobile user, AutoPVP_AdminBattlesUI battlesUI, AutoPVP_Battle battle)
			: this(user, battlesUI, battle, 0, 0)
		{ }

		public AutoPVP_AdminRestrictionsUI(PlayerMobile user, AutoPVP_AdminBattlesUI battlesUI, AutoPVP_Battle battle, int skillPage, int spellPage)
			: base(0, 0)
		{
			if (user == null || battlesUI == null || battle == null)
			{ return; }

			_User = user;
			_BattleUI = battlesUI;
			_Battle = battle;

			if (skillPage < 0)
			{ skillPage = 0; }

			_SkillsPage = skillPage;

			if (spellPage < 0)
			{ spellPage = 0; }

			_SpellsPage = spellPage;

			this.Closable = true;
			this.Disposable = true;
			this.Dragable = true;
			this.Resizable = false;

			AddPage(0);
			AddBackground(75, 75, 300, 50, 9270);
			AddLabel(95, 90, _FontHue, AutoPVP_System.GetMessage(_User, 542));
			AddBackground(75, 125, 300, 345, 9270);

			BuildSkillsList();

			if (_SkillsPage > 0)
			{ AddButton(180, 460, 2468, 2467, (int)Buttons.PreviousSkills, GumpButtonType.Reply, 0); }
			else
			{ AddImage(180, 460, 2468, _ErrorHue); }

			if (_SkillsPage + 1 < (int)Math.Ceiling((double)_SkillsLength / _SkillsPerPage))
			{ AddButton(265, 460, 2471, 2470, (int)Buttons.NextSkills, GumpButtonType.Reply, 0); }
			else
			{ AddImage(265, 460, 2471, _ErrorHue); }

			AddBackground(375, 75, 300, 50, 9270);
			AddLabel(395, 90, _FontHue, AutoPVP_System.GetMessage(_User, 543));
			AddBackground(375, 125, 300, 345, 9270);

			BuildSpellsList();

			if (_SpellsPage > 0)
			{ AddButton(480, 460, 2468, 2467, (int)Buttons.PreviousSpells, GumpButtonType.Reply, 0); }
			else
			{ AddImage(480, 460, 2468, _ErrorHue); }

			if (_SpellsPage + 1 < (int)Math.Ceiling((double)_SpellsLength / _SpellsPerPage))
			{ AddButton(565, 460, 2471, 2470, (int)Buttons.NextSpells, GumpButtonType.Reply, 0); }
			else
			{ AddImage(565, 460, 2471, _ErrorHue); }
		}

		private void BuildSkillsList()
		{
			int count = SkillInfo.Table.Length;

			for (int i = 0, index = _SkillsPage * _SkillsPerPage; i < _SkillsPerPage && index < count; i++, index++)
			{
				int yPos = 145 + (i * _SkillYSpacer);
				SkillName skill = (SkillName)index;

				bool restricted1 = _Battle.AdvancedOptions.PreparingRules.IsRestricted(skill);
				bool restricted2 = _Battle.AdvancedOptions.GameRules.IsRestricted(skill);

				AddCheck(100, yPos, 2152, 2154, restricted1, (_IndexBase * 2) + (int)skill);
				AddCheck(140, yPos, 2152, 2154, restricted2, (_IndexBase * 3) + (int)skill);
				AddLabel(180, yPos + 5, _FontHue, skill.ToString());

				_SkillsLength++;
			}
		}

		private void BuildSpellsList()
		{
			for (int i = 0, index = _SpellsPage * _SpellsPerPage; i < _SpellsPerPage && index < SpellRegistry.Types.Length; i++, index++)
			{
				Spell spell;

				try { spell = SpellRegistry.NewSpell(index, null, null); }
				catch
				{
					i--;
					continue;
				}

				if (spell == null)
				{
					i--;
					continue;
				}

				int yPos = 145 + (i * _SpellsYSpacer);

				bool restricted1 = _Battle.AdvancedOptions.PreparingRules.IsRestricted(spell);
				bool restricted2 = _Battle.AdvancedOptions.GameRules.IsRestricted(spell);

				AddCheck(400, yPos, 2152, 2154, restricted1, (_IndexBase * 4) + index);
				AddCheck(440, yPos, 2152, 2154, restricted2, (_IndexBase * 5) + index);
				AddLabel(480, yPos + 5, _FontHue, spell.Name);

				_SpellsLength++;
			}
		}

		public void Close()
		{ Close(true); }

		public void Close(bool all)
		{
			if (_User.HasGump(typeof(AutoPVP_AdminRestrictionsUI)))
			{ _User.CloseGump(typeof(AutoPVP_AdminRestrictionsUI)); }

			if (!all)
			{ _BattleUI.ResendGump(); }
		}

		public void ResendGump(int skillPage, int spellPage)
		{
			if (_User.HasGump(typeof(AutoPVP_AdminRestrictionsUI)))
			{ _User.CloseGump(typeof(AutoPVP_AdminRestrictionsUI)); }

			_User.SendGump(new AutoPVP_AdminRestrictionsUI(_User, _BattleUI, _Battle, skillPage, spellPage));
		}

		public override void OnResponse(NetState sender, RelayInfo info)
		{
			for (int i = 0, index = _SkillsPage * _SkillsPerPage; i < _SpellsPerPage && index < SkillInfo.Table.Length; i++, index++)
			{
				int switchID1 = (_IndexBase * 2) + index, switchID2 = (_IndexBase * 3) + index;

				_Battle.AdvancedOptions.PreparingRules.SkillRestrictions[index] = info.IsSwitched(switchID1);
				_Battle.AdvancedOptions.GameRules.SkillRestrictions[index] = info.IsSwitched(switchID2);
			}

			for (int i = 0, index = _SpellsPage * _SpellsPerPage; i < _SpellsPerPage && index < SpellRegistry.Types.Length; i++, index++)
			{
				int switchID1 = (_IndexBase * 4) + index, switchID2 = (_IndexBase * 5) + index;

				_Battle.AdvancedOptions.PreparingRules.SpellRestrictions[index] = info.IsSwitched(switchID1);
				_Battle.AdvancedOptions.GameRules.SpellRestrictions[index] = info.IsSwitched(switchID2);
			}
			
			Mobile from = sender.Mobile;
			int bid = info.ButtonID;

			switch (bid)
			{
				default:
				case (int)Buttons.Null: { Close(false); } break;
				case (int)Buttons.PreviousSkills: { ResendGump(_SkillsPage - 1, _SpellsPage); } break;
				case (int)Buttons.NextSkills: { ResendGump(_SkillsPage + 1, _SpellsPage); } break;
				case (int)Buttons.PreviousSpells: { ResendGump(_SkillsPage, _SpellsPage - 1); } break;
				case (int)Buttons.NextSpells: { ResendGump(_SkillsPage, _SpellsPage + 1); } break;
			}
		}
	}
}
 

Pure Insanity

Sorceror
Yeah, that's basically what I'm doing. Using loops, to loop through lists to build both panes separately. Except it's a bit more of pain for what I'm doing, as the panes effect each other depending on the feedback. I guess I could of went the extra mile and just used delegates...just never even considered using delegates for gumps in a way that you're using them, but I do like the idea. Perhaps my next project I give that method a try. =D
 

Jeff

Lord
Doing it the first way...would actually use an extra amount of un-needed memory...correct? Seeing as how it's creating a new one each time that code is called...of course without seeing all the code, I can't confirm this...
The compiler is smart enough to pick up on it and remove the uneeded wrapper... So in reality there is nothing different, except visually.
 

Vorspire

Knight
Insanity, I will be releasing the SuperGumps system with the AutoPVP system under it's namespace, but I will also release it as a separate project after that, it features an abstract template class to handle Listed gumps and takes a generic parameter, handles pagination, etc, known as SuperGumpList<T> - it will also havee full custom scroll-bar support (do a search for GumpWidgets on the forums)
 

Pure Insanity

Sorceror
Hmm, now you got me interested again. Can't wait to see it and dig through it. =D

And I've seen the GumpWidgets thing, just never really looked into it much.
 

Vorspire

Knight
Just another update.
This system is definitely in the Release candidate stage, actually it's currently version 1.0.2 RC1

A lot of things have been added since my last post, it's an ongoing project that will not be released until it is perfect, with every available feature that can be thought of that should be standard in any PvP System.

* Each separate battle can have it's own Notoriety handlers for Name Colour, Harmful and Beneficial checks.
* LightLevel added to battle configs.
* Weather system added for special effects
* More yet to be listed.
 

Iraq-

Sorceror
I don't know how the prizing of this system works currently, but it'd be cool if we could:
A) Enable/Disable Prizes (could run them as a main event, or just a side game with no rewards)
B) We could click "Add Prize", then get a target cursor, and click a customized item within our packs (similar to the complete customizable vendor, or one of the paintball systems out there).
C) We could then select "Add Another Prize", if there were to be multiple prizes.
D) We could then select who gets the prize, whether it be 1st, 2nd, 3rd, or an entire team, or everyone who participated, or even a spectators cut or reward.

Other things I could think to add to a complete PVP system (if your looking for ideas to fuel the system) are:
  • Multiple Starting Options for an Automated Start/End feature:
    • Based on a specific time span (Every Hour, 24 Hours, or every 7 days, etc). Or
    • Based on a paid entry fee cap reached (Battle runs once the system has collected 5 million gold, to be split between the winning members (split could be decided by option D at the top of this post).
    • Or Based on a Join Stone option, similar to the Challenge Gloves in XML Points system, where players (or staff) could manipulate the teams, perhaps the game size, and adjust some attributes of the game type they're about to play (# of caps in CTF, or Total Kills in FFA, etc).
  • Spectator Gambling:
    • One of the major qualms many people of UO have with running Events is that once they start, it takes so many people out of the world game. This is meant to keep people active, even while watching the Events. People could bet on the winning team or for/against a specific player.
    • The main concept has been talked about amongst the players but has yet (I don't even think privately) to be written or released for UO. It'd be a really nice feature, and would add an entire new dimension to the PVP events, since then even the non-pvpers (half of the server pop often times) could participate and enjoy..
 

Tresdni

Squire
I agree on the gambling part. There was an old pvp duel system with gambling implemented, but the rest of the system was kind of half ass. This feature would make your release uber epic.
 
Top