Scripting on Pit Boss: Planning and Prototyping a Portfolio Piece


Scripting on Pit Boss

//TL;DR at the end.

Welcome to the first batch of DevLogs for Pit Boss! I’m Dan Panfili (@DanPanVR), scripting lead and co-level designer for the project. Pit Boss is a 3rd person casino simulator where players balance making money and catching cheaters. The project is being developed by Johan Rodriguez (@DerpySky, Art), Noah Chisenhall (@FateOfReality, Sound and Narrative), and yours truly for MJ Johns’ Level Design course at UT Austin.

The What and Why: Background

As a mid-career academic looking to break into the game industry, creating portfolio pieces is my (and many others’) primary goal. University courses have some unique benefits that make them an excellent place to generate portfolio content: real-time instructor feedback, multi-discipline collaboration, and pre-established deadlines. In this DevLog, I’ll be going into how I am planning and prototyping Pit Boss specifically for use in my portfolio.

Overplanning and overcommitting to features and mechanics is the fastest way to either (1) any % speedrun a buggy project, or (2) ensure you won’t finish the project at all. Knowing this, the team decided to find existing games we’d like to use as inspiration, while finding a theme and central mechanic. We landed on a casino setting, wanting a game that plays like Hitman with narrative akin to Paper’s Please. This gave me 3 distinct scripting challenges: a Hitman-esque character controller, crowd-scale AI ecosystem, and contextual dialogue. 

The Bread and Butter: Character Controller

A good first step for any game is establishing how players will view and move around the world. 

To give the Hitman feel, I created a 3rd person controller with a “camera cart” as a child of the player’s head.The camera rotates with the player head while maintaining the camera angle. Input from mouse or right joystick is taken, then the player asset is rotated along the Y-axis for horizontal orientation while the head is rotated on the X-axis for vertical orientation. The vertical orientation needed to be limited to prevent players from inverting their heads, so I clamped the rotation using a nand gate filter. While the look function was very quick to implement, clamping the rotation was only capable through consistent trial-and-error and mass googling.

Our cursor (similar to the aim mechanic from Hitman) originates from the player’s head out into the environment rather than from the camera. This provides more realistic information to what the player character is attending to, and is achieved with a raycast giving the current position of fixation from the player character. This will be used later for implementation of the “interact” mechanic. The cursor information is also used to inform our post-processing pipeline, for functions like depth of field.

Movement is kept simple, using linear interpolation (Lerp) to smoothly translate the player character in the direction of WASD or the left joystick. Movement is applied in reference to the direction the player is facing.

I was also able to implement a few additional features, including a camera zoom that allows to move the camera closer or further from the player using the mouse wheel (though WebGL does not support mouse wheel input, so I may need to rebind). There are now buttons for interact and aim, but currently they do not have (the appropriate) functions.

While not the largest “WOW” factor of a portfolio piece, making sure people can move through the space with little to no interference provides a more professional feel. We may let Dark Souls slide, but people generally do not enjoy clunky control schemes or buggy cameras. While the starting system is not perfect, it is functional without major bugs (that we have yet found).

The Romans and Countrymen: AI Crowds

Having a rich social atmosphere is essential to games like ours and Hitman. Thus, we wanted to have a dynamic crowd of staff and patrons in the casino to interact with. To start, we will be treating our staff like furniture (capitalism taught us this) and just making customers that feely move around with space with particular goals in mind. This is broken up into N categories: Spawn, Move, Gamble, Buy, Socialize, and Leave.

Starting at ground zero, I made a simple AI using a modified player character model and the Unity NavMesh agent. Wanting to spawn a crowd, I created an array for the NPC AI prefab and made a spawn-on-click function for the player controller. This quickly became MANY simple AI with a movement function, as accidental mass spawning tests gave us a benchmark of ~1000 that can be handled on screen at playable frame rates. Testing further with a function that sets the NPC movement destination to the current cursor position demonstrated that (while able to render) that only ~100 AI agents will respond immediately to a given call at a time. This gave us a good limit for the number of NPCs that can initiate an action at any given time.

To manage performance costs of the agents, knowing we wanted a large crowd and would not be keeping the current sphere + capsule mesh, I looked at our source and similar titles. A very helpful talk was from the team behind Assassin’s Creed Unity on AI recycling.This reinforced my idea for simple AI on the mass scale, but gave me insight into how to sprinkle in more robust NPCs in an efficient way through proximity and context parameters. In addition, finding ways to efficiently draw all the NPCs was found in an essential piece of software—SpeedTree. Learning to use GPU instancing in Unity to provide variation in similar assets will allow for super efficient crowd drawing, even in a WebGL setting.

Now that we have the foundation for our NPCs and can tell them where to go, most other functions (gamble, socialize, etc) are primarily accomplished by giving the AI a position to move to, then initiating a state change that changes their animation. This is largely simple to do from the scripting end with ordinal/boolean states, and now becomes Art’s job to make all the relevant animations (sorry Johan). Of note, the spawn and leave functions will be performed at teleportation stations that allow for context-relevant instantiating of the NPCs.

The larger ecosystem mostly revolves around game-state data. The player’s goal is to maximize the money the casino is making in a night. To calculate how much money is being made (and lost) at each tick of game time, I’ll be implementing a simple attribute system for NPCs and casino games. When an NPC takes a seat at a game, it has a chance to win or lose (based on the house edge for that game), and get a red or green dollar sign above their head depending on this result. These can be varying rates of money depending on the game, which can be indexed fairly easily. However, there will be cheaters that the player must catch to avoid losing too much money or scaring away other customers. These cheaters will have a social cue (likely animation) that shows when they’re cheating, and players will see them consistently get wins.

This is a primary focus for demonstrating technical expertise in my portfolio. While the proposed is a large chaotic system, it is made of small easily distinguishable parts that can be implemented by a single developer. It also acts as a platform for making more robust AI systems. We aim to incorporate more than these base behaviors—like reactions to the player character and between-AI interactions—but starting here provides us with the core of our gameplay.

The Prose and Person: Dialogue

Finally, we reach the primary way players interact with the game world. The dialogue system is not yet implemented in any way, but is currently being planned. We require speech options for a wide variety of randomly generated characters, of which the best approach appears to be a context-based text database. A great example of this comes from Valve’s fuzzy pattern match dialogue system. As long as we keep proper world state data, we can match appropriate dialogue for any number of situations and characters. For example, pulling dialogue for a (Greeting) from a (Male) (Customer) at the (Bar), versus a (Greeting) from a (Nonbinary) (Staff) at the (Bar), is easily distinguishable by parameters pulled from the world and NPCs. Likewise, you can have multiple options for a given set of parameters, and just randomize selection to texturize dialogue more effectively.

Dialogue will require interacting (character controller) with an NPC, displaying a text box with their context-relevant dialogue, then supplying options for the player to choose in response. The player responses can also be coded in the same way of NPC dialogue, and trigger a world state and/or NPC state change. For example, if a player confronts a cheater and chooses to confiscate the cheater’s winnings in dialogue, the casino money score will go up in world state and the cheater’s action state can be set to “leave.” This allows for freedom in narrative design with efficient impact of player choice on the world will minimal programming. This method also means that scripting only needs to handle worldstate changes, reading in text, and choosing the appropriate dialogue while allowing narration to “code” what use-case each dialogue is for in any spreadsheet program.

This is another seemingly chaotic system that I believe will make for a good portfolio piece. Breaking down complex systems into robust, easy to break down functions is invaluable. Even better is showing examples of making a system primarily to allow other members of a team easy implementation of their assets.

The Winners and Losers: Win Condition

In Pit Boss, a basic “win” state would be reaching a profit threshold for the day. Worldstate will keep track of time remaining in the night, as well as profit generated from NPC gambling and purchases. This is the foundation of the gameplay loop, and can have other elements added on as we progress through development. Likely, we will be incorporating side missions (e.g. catch 5 cheaters), story elements (dialogue options that will affect world state), and more intricacies in systems like NPC gambling mechanics or social grouping. This goal seems very achievable within our time-limit, and I suspect we will be able to implement some prospective features by the final deadline.

The TL and DR: Scripting Summary

Scripting has thus far implemented a basic 3rd person character controller (Move, Look, Zoom in/out) with inputs premade for planned functions (interact, aim). NPC crowd generation is a primary gameplay component, and thus far scripting has made a simple AI character that can move across NavMeshes to specific points, and can efficiently texture individual NPCs using GPU instancing. NPC AI will be expanded to spawn, plan movements to key areas, interact with gambling tables and stores, and leave the gameplay area. Dialogue is the primary interactive function of the player, and is currently in the pre-planning phase. Interacting with an NPC will open a text box of dialogue, which the player will then be able to choose a response from. The dialogue system uses context-matching to choose what dialogue and responses to display, and responses can impact world state. Win condition is having the most money at the end of the time limit, generated by NPCs gambling but lost by NPCs cheating. Additional objectives may be added for bonus score, and story elements may be introduced based on time-limit outcome


Anyhow, that's a wrap!  If you have any insight on the project or my approach to portfolio pieces, let me know if the comments below. Until next time, peace!

-Dan

Get Pit Boss

Leave a comment

Log in with itch.io to leave a comment.