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!

PvP Duel Event System

ABCGizmo

Sorceror
RunUO Version 2.2 Compatible

Overview:
After updating and correcting some personal variables that I use on my server. I cleaned up this automated or non automated player vs player system. This system allows you to flip a switch and broadcast to your players that a player vs player event is about to start. After the event starts, it takes all the players and begins to pair them up against each other 1 vs 1. After each match a player is put either into the staging area, or into the spectator area. When you are kicked from the tournament after you loose. You will be given a check based on how many rounds you lasted in the tournament. After the tournament is done, the winning player will get a bonus amount of money. The tournament winner will also be announced to everybody online.

You will be able to customize the following things with this system through the control stone.
  • How much gold each player gets per round.
  • How much extra gold the winner of the tournament gets.
  • How big the duel area, staging area and viewing area is.
  • How many walls come up pre-duel, the id of the wall and color of it.
  • The minimum amount of duelers needed for the tournament to start.
  • Ability to turn on the system to be automatic.
  • Set the frequency in how long the system takes to restart after a tournament is completed.
  • Set the Broadcasting text to be any color you like.
The notoriety of the players is controlled using a system designed from Jeff's event hooking tutorials. So there will be no core file editing needed. You just drop it in, set up your variables from the stone. And click KickStart to allow your players to try it. Once you get use to the stone you will be able to place them around the world and whenever you feel like starting a tournament up. Just click the KickStart and set it to True.

It is suggested that you take a little bit of time to set up your arena area. you will need 3 blocked off sections. One for the dueling pit, one for the people in the tournament and one for the spectators or people who lost a match. Make sure you have a moongate or teleporter in your spectator area so they can leave. After setting up your arena.

Setting up the PvPStone
  • use the command [add pvpstone and target somewhere near the arena.
  • double click on the stone to bring up the property menu, or use [Props and target the stone.
  • stand in a corner of the dueling area, click DuelingArea arrow. then click on the Start arrow, then click on the User your location arrow. now move to the adjacent opposite corner of the dueling area. then click on the End arrow. Then again choose the Use your location arrow. Now the dueling area is set up, to confirm type [where. It should say "The Dueling Pit".
  • double click the stone again.
  • pick a location that you want dueler 1 to appear when a match starts. click the DuelLocation1 arrow and click Use Your Location arrow.
  • set up DuelLocation2 like you did for DuelLocation1, except in a different spot.
  • Set up the amount of GoldPerRound, default is 2 gold.
  • Set up the extra gold given to the winner of the tournament GoldWinner, default is 10 gold.
  • Make sure the MapLocation is the same map that the PvPStone and dueling areas are located.
  • Set the MinDuelers to the minimum amount of players you want in the system so it kicks in and runs. Default is 4.
  • Set up the StageingArea like you did with the DuelingArea.
  • Set up the StartLocation somewhere inside the StageingArea you just added. This is where players will enter when it starts.
  • Set up the ViewingArea like you did with the DuelingArea and the StageingArea.
  • Set up the LostLocation to be somewhere in your ViewingArea. This is where players go when they loose a match and are removed from the tournament.
WallMidPoint can be set up between the DuelLocation1 and DuelLocation2. This wall will appear for the 10 seconds before the duel starts. This is just for effects as players cannot hurt each other till the 10 seconds has elapsed.

Feel free to adjust, modify anything related with this system. It is a great starting vanilla pvp system for anybody to pick up and modify (code wise). Hope you all enjoy.
 

Attachments

  • PvPCoreSystem.zip
    10.3 KB · Views: 537

tass23

Page
Nice system man :)
You mentioned using stuff from Jeff for the notoriety, I'll have to look into possibly getting that to run with XmlPvP.
Thanks for posting this, sounds great, I'll check it out in a day or two. :)
 

Iraq-

Sorceror
Drag n Drop works. I changed min duelists down to 1 and it broke it spammed:
Starting Round #1
Starting Round #2
Starting Round #3
Starting Round #4
Starting Round #5
Starting Round #6
Starting Round #7
Starting Round #8
Starting Round #9
Starting Round #10
Starting Round #11
...
Starting Round #1600+ (not sure why it went up to 1600+, but it did)
...
The server has crashed.

I very much like certain aspects of this system though, using noto chain worked well (took a restart before it would work with the registered regions, and gladiators could still attack each other [easy enough to fix], but still can't beat it for Drag n Drop ), blocking skills and spells and doubleclicks, smart thinking with checking for/closing summon familiar gumps, etc. I will be using this as a base shortly.

Also, it seems that Spirit Speak is blocked in the regions you allow the skill to be used because it "casts" it. No big deal really.

One question before I go, if I am to make multiple links in this noto chain, I don't need multiple NotoHandelerChain files right? Just more and more links.. ( PvPNotoChain, 2v2NotoChain, JailNotoChain, etc for example )
 

JamzeMcC

Squire
Starting Round #1
Starting Round #2
Starting Round #3
Starting Round #4
Starting Round #5
Starting Round #6
Starting Round #7
Starting Round #8
Starting Round #9
Starting Round #10
Starting Round #11
...
Starting Round #1600+ (not sure it went up to 1600+, but it did)
...
The server has crashed.

I also had the same issue. Crashed the server. I had it set up for 2 people min. Had 4 people join. Once the first person hit, it would auto end the round and then went nuts to Round 2500+ and then crashed. I havent yet had time to look it over and see if I can find the issue tho. I will try this weekend. if anyone finds the issue before I can look at it, let me know would ya...? Thanks for the release tho! I look forward to being able to use it!
 

Konstantine

Squire
Gizmo made this for Pandora a year or so back when he worked with us. Works very well, we still use it for the 1v1 Daily PvP to this day.
 

Iraq-

Sorceror
The issue seems to be here:
Code:
 public void StartNextMatch()
        {
            //if there are not enough duelers for a match start a new round.
            if (m_DuelList.Count > 1)
                LoadPlayers();
            else
            {
                m_DuelList.Clear();
                StartNewRound();
            }
        }
and here:
Code:
/// <summary>
        /// Start a new round of combat between the participants of the pvp event.
        /// </summary>
        public void StartNewRound()
        {
            //update current round
            m_CurrentRound++;
 
            //load players into dueling system
            if (ParticipateRegion != null)
            {
                foreach (Mobile pm in ParticipateRegion.GetPlayers())
                {
                    if (pm is PlayerMobile && pm.AccessLevel == AccessLevel.Player)
                    {
                        CleanPlayer((PlayerMobile)pm);
                        m_DuelList.Add(pm);
                    }
                }
            }
 
            //tell players what round it is
            BroadCastMessage("Starting Round #" + m_CurrentRound.ToString());
 
            //if this is the first round, add up the total players participating.
            if (m_CurrentRound == 1)
            {
                TotalParticipants = m_DuelList.Count;
            }
 
            //load players into the duel pit.
            LoadPlayers();
        }
and finally here:
Code:
/// <summary>
        /// Load all the players into a duel match.
        /// </summary>
        public void LoadPlayers()
        {
            if (m_DuelList.Count > 1)
            {
 
                //Set up a random generator
                Random rand = new Random(DateTime.Now.Millisecond);
 
                //Grab a random player, set them up, toss them into the fray
                int duelerone = rand.Next(m_DuelList.Count);
                Mobile m1 = m_DuelList[duelerone] as Mobile;
                m_DuelList.Remove(m1);
 
                //Grab a random player, set them up, toss them into the fray
                int duelertwo = rand.Next(m_DuelList.Count);
                Mobile m2 = m_DuelList[duelertwo] as Mobile;
                m_DuelList.Remove(m2);
 
                //Move Duelers
                m1.MoveToWorld(m_DuelLocation1, m_MapLocation);
                m2.MoveToWorld(m_DuelLocation2, m_MapLocation);
 
                //Add the two duelers to the duelers list
                m_CurrentDuelers.Add(m2);
                m_CurrentDuelers.Add(m1);
 
                //Lock them in place
                LockDuelers();
 
                //Make them face each other
                SetFacing(m1,m2);
 
                //Drop the wall down between the duelers
                DropWall();
         
                //broadcast next matchup to viewers
                BroadCastMessage("Next Match: " + m1.Name + " vs " + m2.Name);
            }
            else
            {
                m_DuelList.Clear();
                StartNewRound();
            }
        }

If there is not 2 players in the m_DuelList, it gets cleared and then StartsNewRound().
Now m_DuelList is empty, so it attempts to fill itself up from members within the region, if that fails, the list remains empty and it still LoadPlayers(), which checks m_DuelList for 2+ players (which fails again), and calls StartNewRound() again.

And thus we have located our Infinite loop.

What we need is a check to see if m_DuelList only has 1 member, in which case StartsNewRound() should not be called, and instead that 1 member should be declared the winner.

Additionally if m_DuelList has 0 members then the game should be over.

And as a suggestion for improvement, you could allow the Region to use any current region as it's Parent when placed, allowing you to use CustomRegions, etc to add some more functionality with little effort.
 
Very nice script good work. Just one question....i clicked on kick start players join but for some reason the players are not showing up that they joined that is why it says not enough players to start pvp event is there something you have to change in the script maybe that will fix it? i have it set on minimum participants at 2.....I need help.
 

Iraq-

Sorceror
The stone does not accurately reflect the number of joined participants. This is due to lack of use of properties and InvalidateProperties() whenever somebody joins.
 

jack-0

Traveler
Gizmo, thankyou for sharing this, it's cool :)

Iraq, your post has been very helpful, and I've tried to implement the fix you described. It seems to work, we've tested it with 2-5 players and not encountered any problems with it. However, I only addressed
What we need is a check to see if m_DuelList only has 1 member, in which case StartsNewRound() should not be called, and instead that 1 member should be declared the winner.
by changing LoadPlayers (and I simply copied the inserted code from elsewhere in the script):
Code:
public void LoadPlayers()
        {
            if (m_DuelList.Count > 1)
            {
 
                //Set up a random generator
                Random rand = new Random(DateTime.Now.Millisecond);
 
                //Grab a random player, set them up, toss them into the fray
                int duelerone = rand.Next(m_DuelList.Count);
                Mobile m1 = m_DuelList[duelerone] as Mobile;
                m_DuelList.Remove(m1);
 
                //Grab a random player, set them up, toss them into the fray
                int duelertwo = rand.Next(m_DuelList.Count);
                Mobile m2 = m_DuelList[duelertwo] as Mobile;
                m_DuelList.Remove(m2);
 
                //Move Duelers
                m1.MoveToWorld(m_DuelLocation1, m_MapLocation);
                m2.MoveToWorld(m_DuelLocation2, m_MapLocation);
 
                //Add the two duelers to the duelers list
                m_CurrentDuelers.Add(m2);
                m_CurrentDuelers.Add(m1);
 
                //Lock them in place
                LockDuelers();
 
                //Make them face each other
                SetFacing(m1,m2);
 
                //Drop the wall down between the duelers
                DropWall();
               
                //broadcast next matchup to viewers
                BroadCastMessage("Next Match: " + m1.Name + " vs " + m2.Name);
            }
 
            else if (m_DuelList.Count == 1)  //mod - if there's just 1 player in the duel list
            {
                foreach (Mobile pm in m_DuelList)
                {
                    m_Winner = pm;  //note - set the winner as this player
                }
                //pm.MoveToWorld(m_LostLocation, m_MapLocation);
                string text = m_Winner.Name + " has won the 1v1 tournament";
                World.Broadcast(m_BroadcastHue, true, String.Format("{0}", text));
                //award winner with extra points.
                m_Winner.SendMessage(55, "you recieve an additional " + m_TotalParticipants.ToString() + " points to your rating");
                //award coins
                GiveGold(m_Winner, true);
                //reset current round
                m_CurrentRound = 0;
                //close the event
                CloseEvent();
                //move winner to spectator area.
                m_Winner.MoveToWorld(m_LostLocation, m_MapLocation);
 
            }
 
            else
            {
                m_DuelList.Clear();
                StartNewRound();
            }
        }


and not anything else you mentioned. I'm reluctant to change more things I barely understand while things appear to be working ok ;)

If there's a better way to make this mod than how I've done it, please explain!
 

Iraq-

Sorceror
That sounds good to me, I also added this into the StartNewRound() method:
Code:
if( m_CurrentRound >= 50 )
            {
                Console.WriteLine( "AutoPvpTourny ERROR: Safeguard kicked in to prevent infinite loop and inevitable server crash..." );
                return;
            }

It'll return (and write to your console) if the system starts to spiral out of control.. which will save your shard from crashing, by stopping the event logic flow.. but it's definitely not the most elegant solution :p

Another thing I did was changed the LogoutDelay of the two regions to be ~45minutes instead of the usual 5 so that the region that the event is pulling players from wouldn't suddenly lose it's players..

* It's also worth mentioning that I haven't had this crash since my initial setup a few weeks back, so it's not as big of an issue.
 

Iraq-

Sorceror
The stone does not accurately reflect the number of joined participants. This is due to lack of use of properties and InvalidateProperties() whenever somebody joins.
so how does one fix this ....i'm new to scripting just need a push in the right direction...lol
You'll need to create a property value for m_TotalParticipants, like this:
Code:
public int TotalParticipants{ get{ return m_TotalParticipants; } set{ m_TotalParticipants = value; InvalidateProperties(); } }

And then instead of setting m_TotalParticipants to some value in the code, you'll use the TotalParticipants property which calls InvalidateProperties() everytime it is set ( TotalParticipants = somevalue; ). InvalidateProperties() is what forces the ObjectPropertyList to refresh.

TBH though, it doesn't really matter if it shows or not, you could just as easily remove the GetProperties override on the stone - since no players can see it anyways.
 

lady myra

Traveler
i understand what you are saying but i don't understand where to put the line in the script if i could get a push in the right direction that would help me alot because i am also having this problem
 

Iraq-

Sorceror
do a search for "m_TotalParticipants =", and then the line after it add:
Code:
InvalidateProperties();
I'd give you line #'s but I've already manipulated my copy...
 
Top