P3-SDK 0.9
P3 Software Development Kit
Loading...
Searching...
No Matches
Persistent Data

GameAttributes are used to store common persistent data, such as operator settings, statistics, and high scores. DataManagerModes are modes that assist in managing sets of GameAttributes. GameAttributeManagerMode is a helper mode that is used for instantiating at least the 3 DataManagerModes that the game framework relies on: SettingsMode, StatisticsMode, and HighScoresMode.

Reading GameAttribute Values

To use the value of a GameAttribute in your game Mode, make a call to data.GetGameAttributeValue("<AttributeKey>").ToInt(), ToLong(), ToFloat(), ToDouble(), ToString(), or ToBool(). For example:

int numAliens = data.GetGameAttributeValue("NumAliens").ToInt();

Saving GameAttribute Values

To update a stored GameAttribute in your game Mode, get a local instance of the GameAttribute, change the value as desired, and store the attribute. For example:

GameAttribute alienAttribute = data.GetGameAttribute("NumAliens");
// Set the value to 5.
alienAttribute.Set(5);
// Alternatively, increment or decrement the attribute value
alienAttribute.Increment(2); // argument can be positive or negative
alienAttribute.Increment(); // same as Increment(1);
alienAttribute.Decrement(); // same as Increment(-1);
data.StoreGameAttribute(alienAttribute);

Default GameAttributes

The P3App framework implements a number of GameAttributes that can be used by all games. These are used in 4 scopes: App-Specific GameAttributes, Playfield Module-Specific GameAttributes, Playfield Module Local GameAttributes, Global GameAttributes

App-Specific GameAttributes

These are saved independently per app. Key: "Settings" (This is also the default key. So access don't need to include the key).

Volume

Name Description Min Max Increment Default
Volume Percentage of maximum volume 0f 1f 0.02f 0.2f

Credit Handling

Name Description Min Max Increment Default
FreePlay Allow games to be started with no credits true
NumBonusCredits Number of credits awarded for money bonus 0 10 1 0
NumCreditPointsRequiredForBonus Number of Credit Points required before being awarded bonus credits 2 20 1 8
NumCreditPoints0 Number of Credit Points for Money Switch 0 1 10 1 1
NumCreditPoints1 Number of Credit Points for Money Switch 1 1 10 1 1
NumCreditPoints2 Number of Credit Points for Money Switch 2 1 10 1 1
NumCreditPointsPerGame Number of Credit Points per Game 1 10 1 2

Note - The total number of credits and the max allowable credit points are both global settings, described in the Global Credit GameAttributes section

A Credit Point is worth 1/NumCreditPointsPerGame, therefore the number of Credits is the number of Credit Points divided by NumCreditPointsPerGame. If the "number of Credit Points since the last game" >= NumCreditPointsRequiredForBonus, then NumBonusCredits many Credits are awarded as a bonus (and "the number of Credit Points since the last game" is decreased by NumCreditPointsRequiredForBonus without affecting the total number of Credit Points).

General Game Handling

Name Description Min Max Increment Default
MaxPlayers Maximum number of players per game 1 9 1 4
AllowPlayerRemoval Allow players to be removed from game by holding the start button true
NumBalls Number of balls per game 1 10 1 3
SoftRestartEnabled Allow aborting game by holding the start button true
ServiceModeReset Reset game when starting service mode true
PlayGameIntro Enable playing of the game intro false
RandomizersEnabled Allow randomizers to return random numbers (apps can use this GameAttribute; the framework doesn't make use of it. It just provides it for commonality with other apps) true
CheatDetection Detect cheaters (apps can use this GameAttribute; the framework doesn't make use of it. It just provides it for commonality with other apps) 0 2 1 1

Feature Menu Configuration

Name Description Min Max Increment Default
FeatureMenuEnabled Show feature menu when requested true
ProfilesEnabled Allow use of player profiles true
AllowDefaultProfile Allow setting of a default profile true
ChangeProfileAllowed Allow players to change profile true
ManageProfilesAllowed Allow players to manage profiles true
TeamGamesAllowed Team games allowed true
SaveRestoreStateAllowed Allow players to save/restore game state to/from their profile true
SelectNoneProfileAllowed Allow players to select the None profile, which is like never choosing a profile true
SelectAddProfileAllowed Allow players to select the Add Profile option, which will allow them to add a new profile true
RequireProfileSelection Don't allow players to back out of the profile selection menu. Force them to choose a profile false
RequireProfileNameEntry Re-enter the profile name entry dialog if it is completed with a blank name false

The above options determine what elements appear in the feature menu for profile-based features. You can dynamically set things like SelectNoneProfileAllowed and SelectAddProfileAllowed to true or false so that they show or don't show in various menus.

Multimorphic.P3App.Data.GameAttribute attr = data.GetGameAttribute("SelectAddProfileAllowed");
attr.Set(false);

Ball Search Configuration

Name Description Min Max Increment Default
BallSearchSubsystemEnable Allow ball searching true
SearchInitialInactivityTime Inactivity time (in seconds) before starting a ball search 5 20 1 10
SearchNextInactivityTime Inactivity time (in seconds) before repeating a ball search 5 20 1 10
SearchTriesBeforeLaunch Number of times to search before launching a new ball 0 20 1 3
SearchLaunchEnable Automatically Launch a Chase Ball After x Failed Searches true
WallScoopSearchEnable Let Built-in wall/scoop search logic run true

Slingshot Configuration

Name Description Min Max Increment Default
SlingshotPulseTime Time (in milliseconds) to pulse slingshots when activated 2 14 1 12
SlingshotSwitchPolarity Slingshot switch activation polarity, true for NO, false for NC. true

Tilt Configuration

Name Description Min Max Increment Default
TiltEnable Tilt detection enable false
TiltUseTiltBob Use tilt bob for tilt detection true
TiltWarnings Number of warnings to issue before tilting 0 10 1 2
TiltWarningDelay Time (in seconds) to wait between warning detects 0f 3f 0.1f 1.2f
TiltSettleDelay Time (in seconds) to wait after tilting before "Evt_TiltSettled" is issued 2 10 1 5

Button Configuration

Name Description Min Max Increment Default
UseSecondaryFlipperButtons One-handed play enabled false
UseOtherFlipperButtons Use red buttons for all lower playfield flippers false

Despite its name, UseOtherFlipperButtons must be set to true to enable single-button control of the lower playfield flippers on each side.

Backbox Color GameAttributes

By default, the colors of the three different LED strings in the backbox are controlled by a mode. An app can take control of the LEDs by running LED scripts at a higher priority than the BackboxColorsMode, but if it doesn't, the following GameAttributes set the colors of the backbox and allow the user to change them.

Name Description Min Max Increment Default
P3Red Red value for backbox P3 RGB LEDs 0 255 5 0
P3Green Green value for backbox P3 RGB LEDs 0 255 5 0
P3Blue Blue value for backbox P3 RGB LEDs 0 255 5 255
PFRed Red value for RGB LEDs mounted above upper playfield 0 255 5 255
PFGreen Green value for RGB LEDs mounted above upper playfield 0 255 5 255
PFBlue Blue value for RGB LEDs mounted above upper playfield 0 255 5 255
BackboxRed Red value for RGB LEDs behind the translite in the backbox 0 255 5 255
BackboxGreen Green value for RGB LEDs behind the translite in the backbox 0 255 5 255
BackboxBlue Blue value for RGB LEDs behind the translite in the backbox 0 255 5 255

Redemption GameAttributes

The redemption GameAttributes are only used when your <AppCode>SettingsMode.redemptionEnabled property is true. Otherwise, none of the redemption GameAttributes will show up in the operator settings.

*Note - There is currently no code in the framework to handle ticket dispensing. These attributes are provided as starting points. Example code for ticket dispensing is available upon request from Multimorphic.

Name Description Min Max Increment Default
TicketsEnabled Enable the ticket dispensing logic false
TicketDispenseTimeout Time (in seconds) to wait after last notch event before logging a dispense error 0 1000 10 20
TicketErrorDisplayLength Time (in seconds) to display a dispense error message when an error is detected 0 1000 10 20
TicketsResetErrorCount Reset the error count each game false
TicketsErrorCount Tickets earned but not dispensed due to dispenser error 0 10000 1 0
MinTicketAward Base ticket payout 0 100 1 2
ForceTicketTest Test: Force dispenser on false

Debug GameAttributes

These GameAttributes enable various popups and debug options.

Name Description Min Max Increment Default
BallsInPlayDebug Enables popups when ballsInPlay changes (only if the app send Evt_BallsInPlay with the new number of balls in play when it should change) false
LaunchDebug Enables launch-related debug popups false
LaunchFailedDebug Enables debug popups for failed launches false
EnableIRGridDebug Shows on the playfield display a virtual version of the IR grid used for ball tracking false
PopupDuration Time (in seconds) to show debug popups 1 10 1 3

The following GameAttribute is for setting the app's logging level (which types of log messages should be logged). By default, this is set to 0 (e.g. All) when simulating your app and 2 (e.g. Exception) when running on the P3 so the log doesn't get too big on location machines that are never turned off. For debugging issues with users, ask them to change their logging level to "All" (represented internally as 0).

  • 0: All
  • 1: Warning
  • 2: Exception
  • 3: Error
  • 4: None
Name Description Min Max Increment Default
LoggingLevel Logging level 0 4 1 0

Replay GameAttributes

See the Replays section for the GameAttributes related to Replays.

Playfield Module-Specific GameAttributes

These are saved per playfield module. An example is a VUK launch strength that is tuned for the ball to eject with enough speed to reach a wireform or other feature. Another example is flipper strength, which might be tuned to be strong enough to flip a ball up a steep ramp on one playfield and might be weaker on single-level playfield to avoid damaging components. All apps that run against that playfield will use the saved setting. These are saved on the P3 so that if another of the same playfield is installed, the same settings will be used. Key: "PlayfieldModuleSettings"

These can be customized by creating a subclass of Multimorphic.P3App.Modes.Data.PlayfieldModuleSettingsMode and instantiating it in <AppCode>GameAttributeManagementMode, similar to how SettingsMode is subclassed and instantiated there.

Name Description Min Max Increment Default
launchStrengthMin<N> Minimum pulse time for trough VUK N 10 40 1 30
launchStrengthMax<N> Maximum pulse time for trough VUK N 10 40 1 30

where N is the VUKNumber of a TroughLauncher, for example launchStrengthMin0 and launchStrengthMax0.

There will also be a LED Brightness setting for each LED String element, Collection of numbered LEDs and individual LEDs on the module (excluding the Base P3 LEDs).

Name Description Min Max Increment Default
LEDBrightness<LEDName> Brightness for <LEDName> 0f 1f 0.01f 1f

Playfield Module Local GameAttributes

These are saved per playfield module and are saved on the playfield module. This allows playfield-specific calibration values to stay with the playfield module. Therefore, if the playfield is installed in another P3, software will load the saved calibration settings. Key: "PlayfieldModuleLocalSettings"

These can be customized by creating a subclass of Multimorphic.P3App.Modes.Data.PlayfieldModuleLocalSettingsMode and instantiating it in <AppCode>GameAttributeManagementMode, similar to how SettingsMode is subclassed and instantiated there.

  • There are no default playfield module local GameAttributes. Playfield module drivers need to create any that they need.

Global GameAttributes

These are saved to a global database accessible by all apps. This is useful for things like the strength of the staging coil, which needs to kick balls up into the P3's ball trough the same way, regardless of which playfield is installed or which app is running. Key: "GlobalSettings"

These can be customized by creating a subclass of Multimorphic.P3App.Modes.Data.GlobalSettingsMode and instantiating it in <AppCode>GameAttributeManagementMode, similar to how SettingsMode is subclassed and instantiated there.

Global Credit GameAttributes

Name Description Min Max Increment Default
NumCreditPoints Number of credit points 0 100 1 0
NumCredits Number of credits currently stored on the machine 0 20 1 0
MaxCreditPoints Maximum allowed credit points 10 500 5 100

Global Coil GameAttributes

Name Description Min Max Increment Default
vukDrain vukDrain Pulse Time 4 30 1 16
vukDrainStack vukDrain Stack Pulse Time 4 30 1 20

Global Ball Tracking GameAttributes

Name Description Min Max Increment Default
BallTrackingPreset Ball tracking preset configuration 1 4 1 1

Global General Config GameAttributes

Name Description Min Max Increment Default
exitRequiresCoinDoor Exiting apps requires coin door open true

Global Gameplay GameAttributes

Name Description Min Max Increment Default
TimeBeforeStartOfBallAutolaunch Seconds to wait before auto-launching ball, in seconds. 0 waits forever. 0 300 10 0

Global Audio GameAttributes

Name Description Min Max Increment Default
Volume Percentage of maximum volume 0f 1.0f 0.02f 0.2f
BluetoothEnabled Enable Bluetooth system false

Global General Illumination GameAttributes

Name Description Min Max Increment Default
SpeakerPanelBrightness Brightness value for speaker panel 0 255 5 255

Global Servo Wall/Scoop GameAttributes

These settings are only available to owners of the servo wall/scoop assembly:

Name Description Min Max Increment Default
AutoRefreshWallsScoops Auto-refresh Walls/Scoops position false
UpPosWall<N> Up position for wall N 35 255 1 180
DownPosWall<N> Down position for wall N 35 255 1 75
UpPosScoop<N> Up position for scoop N 35 255 1 180
DownPosScoop<N> Down position for scoop N 35 255 1 75
ScoopEntranceOperationStyle Use both scoop optos to detect ball entry more accurately, but a bit slower. false

Where N is from 0 to 5 inclusive, for example UpPosWall0 and UpPosScoop0.

These settings are available to all owners, for use as directed by Multimorphic support:

Name Description Min Max Increment Default
ScoopMoatEntranceRetriggerDelay Time to ignore repeat scoop entry events. Contact support for advice. 0.05f 1.0f 0.05f 0.30f
ScoopMoatExitRetriggerDelay Time to ignore repeat scoop exit events. Contact support for advice. 0.05f 1.0f 0.05f 0.15f

Global LED Brightness GameAttributes

Name Description Min Max Increment Default
LEDBrightnessbackbox Brightness for Backbox 0f 1f 0.01f 1f
LEDBrightnessbackboxBack Brightness for Backbox Back 0f 1f 0.01f 0.14f
LEDBrightnessbackboxBottom Brightness for Backbox Bottom 0f 1f 0.01f 0.14f
LEDBrightnessbackboxFront Brightness for Backbox Front 0f 1f 0.01f 0.14f
LEDBrightnessbackboxP3 Brightness for Backbox P3 0f 1f 0.01f 1f
LEDBrightnessbackboxTop Brightness for Backbox Top 0f 1f 0.01f 0.14f
LEDBrightnesscabinetBack Brightness for Cabinet Back 0f 1f 0.01f 0.14f
LEDBrightnesscabinetBottom Brightness for Cabinet Bottom 0f 1f 0.01f 0.14f
LEDBrightnesscabinetFront Brightness for Cabinet Front 0f 1f 0.01f 0.14f
LEDBrightnesscabinetTop Brightness for Cabinet Top 0f 1f 0.01f 0.14f
LEDBrightnessflasherSideModuleLeft Brightness for Left Side 0f 1f 0.01f 1f
LEDBrightnessflasherSideModuleRight Brightness for Right Side 0f 1f 0.01f 1f
LEDBrightnessplayfield Brightness for Playfield 0f 1f 0.01f 1f
LEDBrightnessscoop Brightness for Scoop 0f 1f 0.01f 0.4f
LEDBrightnessspeakerLeft Brightness for Speaker Left 0f 1f 0.01f 0.14f
LEDBrightnessspeakerRight Brightness for Speaker Right 0f 1f 0.01f 0.14f
LEDBrightnesswall Brightness for Wall 0f 1f 0.01f 0.4f
UseCustomBackboxLEDIndexes Use custom backbox LED indexes false
CustomBackboxLEDIndexFirst First backbox LED index 0 1363 1 682
CustomBackboxLEDIndexLast Last backbox LED index 0 1363 1 1100

Customizing Default GameAttributes

If you want to modify the default parameters for your game, override the CustomizeGameAttribute method with code that looks for the desired GameAttribute.Item field and then returns a modified GameAttributes.

Here's an example customization of a GameAttribute. The default attribute "NumBalls" defaults to a value of 3 and can be modified by the operator. This customization is used for a one ball game. It sets the value to 1, and hides it so it can't be modified by the operator.

From a subclass of SettingsMode :

protected override GameAttribute CustomizeGameAttribute(GameAttribute attr)
{
// Start by allowing base module to make any necessary changes.
attr = base.CustomizeGameAttribute(attr);
if (attr.Item == "NumBalls")
{
attr.Value.Set(1);
attr.Options |= GameAttributeOptions.Hidden;
}
return attr;
}

Creating GameAttributes

If your game needs settings or statistics GameAttributes other than the defaults, or if you want to track specific high score categories, you can create a subclass of GameAttributeManagerMode and use it to instantiate subclasses of SettingsMode, StatisticsMode, and HighScoresMode.

Example P3SAGameAttributeManagerMode:

protected override void InstantiateAndAddModes()
{
base.InstantiateAndAddModes();
settingsMode = new P3SASettingsMode(p3, Priority);
// Use PRIORITY_HIGH_SCORES mode for the high score logic so the score boards work properly in Attract Mode.
highScoresMode = new P3SAHighScoresMode(p3, Priorities.PRIORITY_HIGH_SCORES);
statisticsMode = new P3SAStatisticsMode(p3, Priority);
eventProfileManagerMode = new P3SAEventProfileManagerMode(p3, Priority+1);
}

In your Multimorphic.P3App.Modes.Data.SettingsMode subclass, add a call to InitAttr(...) with parameters that define the new GameAttribute. These calls should typically go in an override of CreateDefaultAttrs(), which is the method used by the base class to create all of the default GameAttributes.

Example of subclassing CreateDefaultAttrs and adding a custom GameAttribute:

protected override void CreateDefaultAttrs()
{
base.CreateDefaultAttrs();
// Create a GameAttribute called "NumAliens" with a current value of 6, minimum value of 2,
// maximum value of 8, increment of 1, and default of 6.
// The first argument is the version. This argument is no longer used by the framework.
// It was replaced by the GameAttributeCompareOptions as explained in the next section.
InitAttr(12, "NumAliens", "Number of aliens to defeat", "Aliens", "Service Menu/Settings/Gameplay/Alien Attack Mode", PRW, 6, 2, 8, 1, 6);
}

InitAttr() is a helper function with many variations that help create the GameAttributes and get them stored and tracked properly.

Forcing GameAttributes to Update when Their Definition Changes

You might want to change the definition of a GameAttribute after users have deployed and run the app. Whether or not the changes force an update to the user's saved values is determined by Multimorphic.P3App.Data.GameAttributeCompareOptions. First decide what's used to determine the GameAttribute has changed (CompareAll, CompareAllExceptValue, CompareNone). Then, if it's determined to have changed, decide if the stored value should be updated based on UpdateValueIfAnyChange and UpdateValueIfDefaultChanged.

These GameAttributeCompareOptions can be passed in as a final parameter to the InitAttr calls. Example:

InitAttr(12, "NumAliens", "Number of aliens to defeat", "Aliens", "Service Menu/Settings/Gameplay/Alien Attack Mode", PRW, 6, 2, 8, 1, 6, GameAttributeCompareOptions.CompareAllExceptValue | GameAttributeCompareOptions.UpdateValueIfAnyChange);

Customizing GameAttribute ToString methods

You can customize how the value of a GameAttribute is displayed on the screen by assigning custom ToString() methods. In the following example, the "SoundTrackRatio" GameAttribute is given a custom ToString() method:

/// <summary>
/// Assigns custom ToString() methods.
/// </summary>
protected void SetCustomToStrings()
{
GameAttribute attr = data.GetGameAttribute(Key, "SoundTrackRatio");
attr.setCustomUserString(attrFloatToFloat2D);
}
private string attrFloatToFloat2D(string origStr)
{
float origFloat = Convert.ToSingle(origStr);
return origFloat.ToString("0.00");
}

Run Code When Saving Operator Settings

To run specific code when certain GameAttributes are modified in the operator's ServiceMode Menu, you'll need to override the ProcessSavedAttributeEventHandler method in the subclass of the SettingsMode the GameAttribute is created in. Example:

protected override void ProcessSavedAttributeEventHandler(string evtName, object evtData)
{
base.ProcessSavedAttributeEventHandler(evtName, evtData);
GameAttribute attribute = (GameAttribute)evtData;
if (attribute.Item == "UseRightVUK" || attribute.Item == "UseLeftVUK")
{
PostModeEventToModes("Evt_SetupVUKs", 0);
}
}

Stock GameAttribute Profiles

Stock profiles allow GameAttribute settings to be forced to pre-determined values. All stock profiles are created at run-time as determined by code in your subclasses of GameAttributeManagerMode and SettingsMode. Simply override the GameAttributeManagerMode's CreateStockProfiles method and put in calls to the profileManagerMode's AddStockProfile method. Then make calls to an override of the SettingsMode's UpdateStockProfileAttributes method.

Here's an example that creates 5 stock profiles (Default, Easy, Medium, Hard, and Custom). Note that the boolean parameter in the call to UpdateProfileAttribute determines if the resulting stock profile's attribute is read-only or not. In this example, it's read-only for all except the "Custom" profile. This means that after activating the stock profile, the "NumAliens" GameAttribute won't be user-settable unless the activated profile was the "Custom" one.

Example code from a GameAttributeManagerMode subclass:

protected override void CreateStockProfiles()
{
base.CreateStockProfiles();
profileManagerMode.AddStockProfile("Default");
profileManagerMode.AddStockProfile("Easy");
profileManagerMode.AddStockProfile("Medium");
profileManagerMode.AddStockProfile("Hard");
profileManagerMode.AddStockProfile("Custom");
settingsMode.UpdateStockProfileAttributes("Default");
settingsMode.UpdateStockProfileAttributes("Easy");
settingsMode.UpdateStockProfileAttributes("Medium");
settingsMode.UpdateStockProfileAttributes("Hard");
settingsMode.UpdateStockProfileAttributes("Custom");
}

Example code from a SettingsMode subclass:

public override void UpdateStockProfileAttributes(string name)
{
if (name == "Default")
{
// NOTE - ALWAYS write the value as a string, regardless of its actual type. It'll
// be converted to the correct type when the attribute is updated in the lower level logic.
UpdateProfileAttribute(name, "NumAliens", "6", true);
}
else if (name == "Custom")
{
UpdateProfileAttribute(name, "NumAliens", "6", false);
}
else if (name == "Easy")
{
UpdateProfileAttribute(name, "NumAliens", "2", true);
}
else if (name == "Medium")
{
UpdateProfileAttribute(name, "NumAliens", "6", true);
}
else if (name == "Hard")
{
UpdateProfileAttribute(name, "NumAliens", "8", true);
}
}

High Scores

High Scores are managed internally as GameAttributes to provide persistence. <AppCode>GameAttributeManagerMode instantiates a HighScoresMode and sends it whatever HighScoreCategories are defined. Then when told to do so, the HighScoresMode compares player data against existing high scores for the category and prompts for name entry when new high scores are achieved. Apps can later request high score data to be sent to the GUI for each category, commonly during AttractMode.

High Score Categories

Apps wanting the framework to help track high scores need to define one or more Multimorphic.P3App.Modes.Data.HighScoreCategory and tell the framework about it by posting ModeToMode "Evt_AddHighScoreCategory" events in <AppCode>GameAttributeManagerMode.mode_started().

A high score value is stored as a double to avoid the loss of precision at 10M with a float.

The HighScoreCategory constructor has this signature:

public HighScoreCategory(string key, string description, int numPlaces);

A HighScoreCategory has the following fields:

Field Type Description
key string The player data key where the application stores the high score value with calls like data.currentPlayer.SaveData(key, scoreValue)
description string Description to be used in high score displays, more like a name.
numPlaces int Number of entries to store
defaultValues List<double> Default values for each entry
defaultNames List<string> Default player name for each entry
decimalPlaces int Number of decimals to show in high score displays
zeroValue double Value to use when the high score is reset by the user. Typically the worst possible score. Default is 0.
sortDirection bool false = larger is better (default), true = smaller is better.
disallowedForRestoredGames bool true = restored games not eligible for this high score, false = restored games are eligible.
eventName string Event Profile associated with this category. Default is null for regular high scores.

Example code in <AppCode>GameAttributeManagerMode.mode_started():

List<string> defaultNames = new List<string> { "GS", "JW", "RC", "LP", "TW", "TJ", "SG", "DT", "NP", "SS" };
// More ramps is better, starts at 0, restored games not eligible because of infinite number of balls
HighScoreCategory leftRampsCategory = new HighScoreCategory("LeftRamps", "Left Ramps Completed", 10);
List<double> leftRampsDefaultValues = new List<double> { 30L, 29L, 28L, 27L, 26L, 25L, 24L, 23L, 22L, 21L };
leftRampsCategory.SetDefaultValues(leftRampsDefaultValues);
leftRampsCategory.SetDefaultNames(defaultNames);
leftRampsCategory.SetDecimalPlaces(0);
leftRampsCategory.SetZeroValue(0);
leftRampsCategory.SetSortDirection(false);
leftRampsCategory.DisallowFromRestoredGames(true);
PostModeEventToModes("Evt_AddHighScoreCategory", leftRampsCategory);
// Shorter time is better, timer is 60s, cannot cheat with more balls so eligible for restored games.
HighScoreCategory hurryUpCategory = new HighScoreCategory("HurryUp", "Hurry Up", 10);
List<double> hurryUpDefaultValues = new List<double> { 30L, 32L, 34L, 36L, 38L, 40L, 42L, 44L, 46L, 48L };
hurryUpCategory.SetDefaultValues(hurryUpDefaultValues);
hurryUpCategory.SetDefaultNames(defaultNames);
hurryUpCategory.SetDecimalPlaces(1);
hurryUpCategory.SetZeroValue(60.0);
hurryUpCategory.SetSortDirection(true);
hurryUpCategory.DisallowFromRestoredGames(false);
PostModeEventToModes("Evt_AddHighScoreCategory", hurryUpCategory);

Initiating High Score Comparisons

This happens automatically when processing end of game if <AppCode>BaseGameMode.highScoreCheckEnabled is true. If you want high score comparisons to run at another time, set <AppCode>BaseGameMode.highScoreCheckEnabled to false and post ModeToMode event "Evt_LookForHighScores".

PostModeEventToModes("Evt_LookForHighScores", 0);

Framework code will receive that event and initiate high score checks against the player data, as referenced by the high score categories. If a new high score was achieved, the player will be prompted to enter his or her name. When comparisons and entry are completed, the internal logic posts "Evt_HighScoreEntryFinished". So handle that if you are setting <AppCode>BaseGameMode.highscoreCheckEnabled to false, because that's what allows the end of game processing to finish.

Displaying High Score Tables

In most games, the app will initiate the appearance of the high score tables. This is done by posting the ModeToMode event "Evt_ShowHighScores" with an int parameter representing the category to show. To cycle through more tables, continue posting that event with an incremented or decremented index. It's common to map the right flipper button to increment through the high score tables and the left flipper button to decrement through the high score tables.

PostModeEventToModes("Evt_ShowHighScores", <categoryNum>);

To stop displaying the high score tables, issue the "Evt_HideHighScores" event:

PostModeEventToModes("Evt_HideHighScores", true);

When "Evt_ShowHighScores" event is received by the internal high score processing logic, it will prepare a Multimorphic.P3App.Modes.Data.HighScoreDisplayData object and post it to the GUI through the ModeToGUI event "Evt_ShowHighScores".

Then when the "Evt_HideHighScores" event is received, it will reissue the "Evt_HideHighScores" event to the GUI.