Devblog:

Confession: I play a lot of PLAYERUNKNOWN's BattleGrounds (hereafter PUBG). I like the Battle Royale idea of a massive free-for-all with one victor left standing at the end.

So when searching for an interesting way to test PVP mechanics in our upcoming Beta Test, we were kicking around a few ideas. A generic "pvp arena" works for a bit but after a while you get bored of just duelling. So Daleron and I decided we'd just pound out a bastardization of PUBG in UO.

For those of you who haven't played PUBG or its more-successful clone, Fortnite, the premise is thus: 100 players parachute onto an island, armed with nothing, and fight to the death with whatever gear they can find. There are weapons, armor, grenades, healing supplies, and all that good stuff sitting on tables and floors scattered across the huge island of Erangel (and later other maps). This loot is waiting for the player in houses, hunting cabins, hospitals, power plants, and apartment buildings. You gear up as best you can and then it's kill or be killed.

Meanwhile, a timer is constantly counting down: There are three "circles" you need to care about in PUBG: Red, white, and blue. The Red circle appears occasionally and anywhere inside its radius gets hit with a massive artillery strike. The Blue circle forms the boundary between safe and danger zones. Outside the Blue Circle you take damage over time and inside it you are safe (from the zone, not from other players). Periodically, the Blue Circle begins to contract, forcing players ever closer together. The White Circle does nothing except show where the Blue Circle will pause. Ignoring the silly Red zone, the game flow goes like this:

  1. Parachute from a C-130 Hercules onto the island
  2. White zone appears
  3. Blue zone slowly contracts until it reaches the white zone, then stops
  4. White zone contracts
  5. Wait a short period of time
  6. Go to step 3, repeat until one player remains.

(Click to enlarge)

I decided to implement this as a Finite-State Machine with some adaptations to fit the PUBG game flow (which is of course a first-person 3D shooter) into UO (a tile-based third-person isometric pseudo-3D game):

public enum BattleState {
    Idle, //game not running, nobody able to join
    Joining, //players able to join
    Parachuting, //if it was pubg you'd be in the herc or parachuting
    Playing, // game in progress
}

In Zulu Hotel our circles are actually rectangles because it's tile-based and the coordinate system is rectangular, and thus makes the math easier/faster. We use the graphics from the Energy Field spell and others to denote the White and Blue zones. We don't have Red zones.

Instead of Erangel, our game is played on Verity Isle (aka Moonglow Island). It turns out this is a great place for this minigame because it's massive and has several distinct areas already in: There's the city of Moonglow itself, with the docks and the bank, the Lycaeum, the Telescope, a grave yard, the Council of Mages stronghold, large expanses of wooded terrain, and farmhouses dotting the rest of the island. Instead of assault rifles and energy drinks, our island has katanas, war maces, and other weapons scattered about. You can find arrows for your bow, magic reagents, bandages, potions, and all manner of shields and armor.

Instead of parachuting from a Hercules, when BattleState is in the Joining state, the game just kills all its participants and lets them disperse freely across the island as ghosts. When the countdown is complete we call the BeginPlay() function:

public static void BeginPlay() {
    foreach( Mobile pm in _Players ){
        pm.Resurrect();
        _AlivePlayers.Add(pm);
        pm.OnDeathEvent += OnPlayerDeath;
        pm.SendMessage("Last one standing in Moonglow wins!");
    }
    _state = BattleState.Playing;

    _ZoneCenter = _FinalZoneCenters[ Utility.RandomMinMax(0, _FinalZoneCenters.Length - 1) ];
    _CurrentStageEnumerator = _ZoneStages.GetEnumerator();
    _NextStageEnumerator = _ZoneStages.GetEnumerator();
    _NextStageEnumerator.MoveNext();
    ZoneTick();
    HandleZoneDamageTimer();
}

Right at the top of the function you can see that it iterates through all the Mobiles in the list of players (_Players), resurrects each player, and then play begins. From there the game follows the same flow as I outlined above, alternating between contracting the zone and waiting for someone to win, until the final zone is just a single tile and any remaining combatants are literally forced to stand on top of each other at which point I suspect Warrior-spec characters will probably have a distinct advantage.

Speaking of classes, I'm excited to see how skilled players will play to their strengths and make the terrain work for them. I went through and hand-chose a long list of what PUBG players call "final circles": points on the map about which the zone contracts to its smallest. I chose about 40 points with a good variety of characteristics: Some urban, which I imagine will benefit Warrior-spec characters since they can use obstacles for cover. Some wooded and open, which I imagine will benefit Mages and Rangers. Powerplayers gonna do what powerplayers gonna do.

There's no reason you can't take a Bard or a Thief into the arena, of course, but fair warning: I've been focusing my efforts on "the Big 3" pvp classes, and we'll get to the others afterwards. Some of the later Zulu Hotel spin-offs and clones implemented a "Song book" for Bards to cast spells, but I'm taking an old-school approach: Get the fundamentals of the original ZH2 and/or ZH3 correct and then see where it goes from that point. We have Necromancer and Earth spellbooks for Mages but that's it so far. If a "Song book" or whatever ZH Scandinavia calls it needs to be added we can do that in the future.