-
Notifications
You must be signed in to change notification settings - Fork 0
How to write an event
Events are separated broadly into two categories KNOWN and UNKNOWN. Known events are events that the user will be able to see and anticipate on their calendar. Unknown events are invisible to the user but are still spawned when the calendar is first initialized (at the start of the game / year) not "on the fly" as each day passes.
Additionally, all events follow this function signature
public static Outcome Event(DataManager, Requirements)
-
DataManager
holds all information about the league, player, and current game session. -
Requirements
holds the different objects the user will need to send in, for instance a child to participate in an event or a sum of money. -
Outcome
holds a status integer and outcome string which will be displayed to the user upon completion of the Event
In this example we'll be writing an event in which a random grandchild is going on a field trip with a parent chaperone. Additionally, you'll need to provide funds to your grandchild so they can bring home a souvenir.
First step in writing a known event is to layout the basic design in the xml file: Resources\events.xml
The top level tag in this document is <events></events>
, to add an event use the tag directly beneath like so:
<event type="1" id="5" name="Grandkids go on a field trip" description="{0} is going on a field trip! Additionally the school has asked for more chaperones so please provide one, {1}!" priority="2" req_children="false" req_parent="true" req_grandpa="false" req_money="true" req_accept="false" month="3" day="0"/>
Let's break this event down by each subtag that is required:
-
type: 0 for unknown or 1 for known events
-
id: the unique numerical id for which to represent your event. It is very important that this is unique. It is recommended you work in your own space this way two people working on events and committing them won't have merge conflicts. To check how we currently distribute the ID numbers check the bottom of this page.
-
name: The name of the event that will be displayed to the user
-
description: A brief description of the event and what the user will need to provide. Note {0} denotes a empty space that can be filled in later. Each different name requires a new {#}. As shown, the user's name would go in {1}
-
priority: A number which describes how important the current event is. 0 is lowest and 2 is the highest. An event with a priority of 0 will be passed over silently with output appearing only in the mail panel. An event with priority of 1 will "pause" the current simulation to prompt the user for input before continuing. An event with priority 2 will stop the simulation completely. Presumably this is only for major events
-
req_children, req_parent, req_grandpa, req_money, req_accept: these are the required inputs for the event. For our event the user needs to provide a parent from their team and also an amount of money. Hence we marked these fields "true".
-
month and day: additionally programmers can specify the specific month and day the event occur (please remember we only have 28 day month currently). Moreover, the DAY field is OPTIONAL. Leaving this out or setting it to 0 will result being "seasonal" and a random day during the specified month will be chosen for the event.
Now we can begin programming the function which will interact with data.
Open EventManager.cs
and scroll to the bottom. You will see functions of the form "Event#". The # corresponds to the event id you gave in your xml, so find the numerical correct place to put your event and use the function signature:
public static Outcome Event5(DataManager manager, Requirement requirements)
{
}
By the time this function is called the Requirement
object will already be initialized with our needed Parent and money so we don't need to worry about them and can assume they have already been initialized. You can access them using properties requirements.Parent
and requirements.Money
. Additionally, because this event chose a random child requirements.Child
will also be initialized. It is up to the developer to know what they need to get from the Requirements object.
DataManager
is a complex datastructure with literally every piece of data in the game. Check out DataManager.cs
for the various properties you can work with.
Now lets write the body of our function. If our parents intelligence and popularity have a sum of greater than 110 and our child's popularity is > 50 we can say the event is a success. Additionally if your child has > $50 he can buy a kickass souvenir.
int successes = 0;
List<string> outcome = new List<string>();
Outcome returnObj = new Outcome();
if(requirements.Parent.Popularity + requirements.Parent.Intelligence > 110)
{
requirements.Parent.Popularity += 5;
string outcome += outcome.Add(String.Format("{0} gained popularity ", requirements.Parent.Name));
successes++;
}
else
{
//some parent failure outcomes
}
if(requirements.Child.Popularity > 50 && requirements.Money > 50)
{
requirements.Child.Popularity += 10
successes+=2;
//some strings for child gains
}
else if (requirements.Child.Popularity > 50)
{
requirements.Child.Popularity += 5
successes++;
//some strings for child gains / loses, etc
}
//event can be as complex as you want...continuing onwards
manager.PlayerFamily.Grandpa.Money -= requirements.Money
if (successes >= 2)
{
string outComeString = string.Join(", ", outcome);
returnObj.Status = (int)Enums.EventOutcome.SUCCESS;
returnObj.OutcomeDescription = String.Format("{0} had a great time at the field trip, {1}", requirements.Child.Name, outComeString)
}
else
{
returnObj.Status = (int)Enums.EventOutcome.FAILURE;
returnObj.OutcomeDescription = "etc, etc";
}
return returnObj;
Above is the function body, pay special attention to strings. Events don't have to be concrete pass or fail, depending on different control flows it can go many different ways and have many different varied outcomes. If you want a random integer check out Constants.RANDOM.Next(int minValue, int maxValue)
NOTE: Objects in requirements are passed by reference this means that when you change an object in the requirements (e.g. a Parent or Child stat) is is immediately reflected in the DataManager. So you don't have to worry about finding the matching Child or Parent object in the DataManager, you can just directly change it from requirements
NOTE: The Outcome.Status
field is not as important as the Outcome.OutcomeDescription
field. While we may use the Outcome Status int later for more dynamic events currently only the Outcome.OutcomeDescription
will be displayed to the user! So it is important to alert the user to what happened.
Now we'll look at a random event. They are extremely similar to known events except for how they're declared in the xml file:
<event type="0" id="1" name="Grandpa wins the lottery" description="You won the lottery! con fucking gratys" priority="1" chance="0.2" req_children="false" req_parent="false" req_grandpa="false" req_money="false" req_accept="false"/>
Key differences:
-
Event type is 0 for "hidden/unknown"
-
chance is a new field not on a known event. The chance is a decimal of how likely this event is to happen on any given day. Here our chance is 0.2, or 20%. Please remember there are 336 days in a year. If the chance was 1% it would still occur on average about 3 times a year
-
day and month: Note these are not present in the xml because currently they are not applicable
Other than that it is the same as writing a known event, as long as the Event function matches the event ID and function signature you will be good to go!
known
<event type="1" id="" name="" description="" priority="" req_children="" req_parent="" req_grandpa="" req_money="true" req_accept="" month="" day=""/>
unknown
<event type="0" id="" name="" description="" priority="1" chance="" req_children="" req_parent="" req_grandpa="false" req_money="" req_accept=""/>
These are the current event id namespaces, please use the corresponding ids as specified below.
- 0-100: reserved (do not use)
- 101-1000: Kevin
- 1001-2000: Patrick
- 2001-3000: Christoher