-
Notifications
You must be signed in to change notification settings - Fork 8
the games programming systems
the big idea is: make everything easy to use, accessible using one or two methods to manipulate the feature you want.
let's say you want to add a structure (just a hypothetical example), you add it to the structure database, and if it has a special event add it at the method "stractures_spacial_events" at stracture_manger.java in:game objects package.
now you can add 10 of these with their own stats and events, by just adding to the database and a method in some class. no need to reinvent the wheel or think about what to do where etc.
lets start
add an item:
go to db packge, then open item db, inside the method gen_items() after all the item add:
db.put("item name","item name",5,0,2,1,30");
the first string is the handle that will be used to call the item using db.get("item name").
the second string is the data separated by a comma here is the data table columns: //name,amount,paid,cost,min_price,max_price
so in "item name" the 5 is the amount then 0 is how much was paid for the item of this type,2 is the current cost , 1,30 is the price range from 1-30.
all items will be added to the market items attribute, items data is stored on the item class that acts as a modal for the data (item.java is inside game_object package).
the items owned by the player are stored on the player class on items ArrayList (its an arraylist in market too).
player class has a few methods to manipulate its items. buy,sell,get_item(by name), and items_list(returns a string list of players items).
let's say we want to make an event that requires the player to have 3 engines for some reason.
to get the engine item handle (from player) we will write:
item e = game_manger.p.get_item("engine");
this can be done from any object in the game.
if the player never got an engine e will be null check it like that:
if(e==null){/*do somthing*/}
now lets check if he has 3 of these (if e is not null):
if(e.amount>3){/*do somthing*/}
need to remove 3 engines?
e.amount-=3;
obviously, it heavily uses and relies on the item system.
what it does is handle buying selling and displaying items.
its methods are mainly on market.java
and player.java
in game_objects package.
in market.java
, we have methods that deal with the market's supply and demand (supply_and_demend_gen
method),display_all
method returns a string with all of markets items , and a method that just gets the items price by items position in the items ArrayList get_item_price
.
pupulate_items
fills the items ArrayList inside market with all the items inside item db.
the player also has an ArrayList of items why? simple the player has items he owns and thers the items available for trade in market, both are different things.
the markets supply_and_demend_gen
changes the prices and amount of items in the market, for now it does this randomly for each item in the items ArrayList in the market.
the players item prices change to the market items using markets update_player_item_price
method its called when the player wants to sell items in market_screen
under the method do_sell
like tis:
game_manger.m.update_player_item_price(game_manger.p);
player has buy
and sell
methods to manipulate his own items, get_item
method will get an item modal by name from players items, items_list
method will return a string with all the players items.
buy
method gets an item and the amount of the item you want to buy, it calculates the price and all the rest inside.
sell
method is the opposite of buy, it adds credits and reduces an item amount, it gets a price (price per item) after the amount because some events let you sell items at different prices than its attribute price\cost.
it also calculates the tax you owe from the sell and adds it to tax owed, so if you want to sell on "black market" dont use sell.
for both sell and buy return a boolean, if a buy or sell item succeeds it will return true.
example use in smuglers_sell event in do_event
in event_manger.java
:
//check if can buy
if(game_manger.p.buy(goods_to_sell, goods_amount))
{
cio.println("done deal");
messge = "done deal";
}else
{
cio.println("deal failed (you dont have enough credits");
messge = "deal failed";
}
that's how players buy method is used, can be used like this all over the project. it could have been sell method, with minor changes.
there are 3 types, for now, events you activate in events screen, immediate events that happen as soon as they appear (you see their results on event screen the same turn they happen, and long term events to handle events that happen after a few turns.
all possible none long term event that can happen are stored on the event_db
from this pool events are generated.
regular events and immediate events that happen or can be activated are stored on the players events ArrayList attributes.
those events are added using random_events
method of event_manger
class (random_events also clears all previous none long term events).
random_events
runs inside game_manger
inside pass_turn
method once the players selects the pass turn option in the games main menu.
inside game_main
screen show_events
shows all the activatable events and immediate events that happened this turn. it asks the player to select an event, and then the event runs in do_event
method of event_manger
.
inside do_event
thers all of the activatble events logic like:
if(action.equals("smuglers_sell"))
{
will run if its a smuglers_sell event (there can be a couple of events that have the same action in the database).
each event logic is special as it meant to change the games pace a little.
immediate events are run as soon as random_events
methods pick one.
the logic of immediate events is inside do_immidiate
method like:
//events that cause you to loss money
if(action.equals("money_reduce"))
{
as you can see its the same as do_event
the difference is that you don't ask for user input, immediate events resolve automatically.
like activatable events, the action logic can be used with multiple events in the database, "money_reduce" action can be a "meteor shower" or "armed robbery"(this event type can be negated by buying insurance we don't want an event that breaks the game).
and it can have any type of logic you can imagine.
long term events are a bit different they work with counters,as they are events that happen after a few turns, the counter collection and the current counter list are attributes of player class:
counters_list
is an ArrayList and attribute of player.java
it holds the names of all long term events currently waiting to happen.
counters
is a IndexableMap and attribute of player.java
it holds the counter count and the max value it will count to (done behind the scenes using methods (inside the player class):
add_counter
is a method that adds a counter, it gets the name and the duration example: add_counter("bla bla",3)
this means bla bla will happen in 3 turns.
add_counter_once
is the same as add_counter
but it won't add the counter if its already exists in counter ,useful if you want one instance of a certain long-term event.
remove_counter
does exactly what it says, removes a counter by name lets say we want to remove "bla bla" we will call remove_counter("bla bla")
.
reset_counter
resets a counter by name, in case you want the long term event to run from the start again.
each pass_turn
the counters will be updated using long_term_events_update
of the event_manger
class. once a counter is finished do_long_term_events
will run (also inside event_manger
).
do_long_term_events
is where the event happens, like immediate and activate events each event has its own unique logic :
if(name.equals("worker_union_fine"))
{
for example inside this if is the logic that will happen once the timer for worker_union_fine ends, the player will get a fine for not paying his employees.
and thats how the event system works, the code itself is not complicated to read once you know what it does.
this one is a smaller system, most of it is in player.java
.
in short, tax is added when you sell stuff, if you don't, a counter will start for a long-term event, hen it ends you will get a fine.
i made this before i had the long term events counters.
add_taxes
method inside player
is how you add taxes from player earnings, it gets the earnings multiply it by the tax_rate
which is a player attribute, and adds the result of that calculation to taxes_owed
.
taxes_owed
is how much tax you owe.
update_taxes
is a player
method that runs every pass_turn
.
update_taxes
checks if you owe taxes if you do it incraments didnt_pay_taxes_c
attribute which is the counter that counts how many turns you didnt pay all your taxes. paying taxes resets didnt_pay_taxes_c
to 0.
if you dont and the counter exceeds 13 taxes_problem
boolean attribute turns true. then you're in real problems.
but before that if(didnt_pay_taxes_c>didnt_pay_taxes_max)
you will get a fine (tax increase).
pay taxes functionality is in mangment_screen
under pay_taxes
there the player is asked if he wants to pay taxes, if he does, the amount he chose to pay goes into player class pay_taxes
method.
and that's it for taxes, its a simple system for now.
the station personal are used in events and calculating stats and other modifiers.
general workers and engineers are used to maintain the station and its system, there will be a minimum number you need to run the station.
guards are used for all security-related stats and events.
all these are managed using station_personal
class inside game objects package.
station_personal
is also an attribute in player
called s_personal
it holds an instance of station_personal
.
to access station_personal
simply write:
game_manger.p.s_personal
from anywhere within the project.
all of players station personal are stored on station_personal
class attribute called plist
which is an IndexableMap used to store character
class.
character
is a very flexible class it has two IndexableMaps one for stats
and one for traits
, in station_personal
a character is used to describe a group o people like workers/guards, etc. usually character
will be used to describe a single character.
using station_personal
class to add personal type thars create_personal
method it gets three arguments:String name,int amount,int salary.
let's say we want to add a guards type with the amount of 2 and salary of 300 per turn:
create_personal("guards", 2,300);
now we will add 3 more guards:
add_personal("guards", 3);
thers also a method to remove personal (incase you fire them etc etc):
remove_personal("guards", 3);
this will remove 3 guards.
calculate_salery
will return all of the station's personal salary that needs to be paied for this turn.
the actual salary you need to pay from the last turns is stored on payments_owed
attribute.
in player
thers a method called incrament_sallery_owed
it does what it says it does, it incraments the salery you owe all of your orkers this turn to
payments_owed
in the station_personal
instance in player.
incrament_sallery_owed
is called every pass_turn
inside pass_turn
we have an if:
//if owe personal payments
if(game_manger.p.s_personal.payments_owed>0)
{
game_manger.p.add_counter_once("worker_union_fine",12);
}
if you don't pay your workers a timer will start, if you dont pay your workers you will get a fine.
in pay_sallery
in player
once some of the salery is payd the counter is removed:
remove_counter("worker_union_fine");
you need to pay at least 200 credits for the counter to stop.
if the time fires the long term event, inside event_manger
inside do_long_term_events
thers an if for worker_union_fine:
if(name.equals("worker_union_fine"))
{
the code inside that if will increment the times you got a worker union fine:
game_manger.p.s_personal.union_fine++;
the fine is multiplied by the times you got it and once you get too many, your business gets closed.
this one is the easiest, goto upgrades db, add the upgrade, and that's it, it's available to buy on management screen.
//upgrade name,price,desc
db.put("better_plumbing","better_plumbing/500/better plumbing will make your station plumbing system degrade slower and easier to fix");
that's an example upgrade the name is:better_plumbing it costs 500 credits and after that is the upgrade description.
the upgrade will be added to the upgrades the player can buy.
what will it do depends on you, you can call the players upgrades for anything.
so you can check if a player has an upgrade every pass_turn and then do something, or check if the player has a certain upgrade inside an event, lets say its a robbery event, check if "the player has the advanced security" upgrade then don't do the negative part of the event. or an event that increases supply and demand or anything you can think about.
that's it, you add an event and program what it does somewhere so it will do something.
edit upgrade logic now has its own file called upgrades_system
it's inside game_objects
package.
upgrades also may have requirements so the new upgrades table columns are:
//upgrade name,price,desc,requirement
requirement is a string of other upgrade names separated by a comma.
some upgrades need you to have other upgrades operational
marketing is used to get more goods in the market or advertising rent space.
for now you can market for goods on marketing_system
in market_goods
marketing for goods increases all the goods amounts next turn for one turn.
the more you pay for goods marketing the more people see it the more goods will come to your station (you asked for it).
critical systems can be damaged and also upgrades.
damaged upgrades cant be used (except for ones that give you a permanent bonus).
critical systems can do a lot of problems.
each turn your engineers will fix damages at the cost of supplies (if you have supplies).
the more engineers you have the faster the repairs will be, see damage_system.update_damege_effects
that method runs every pass_turn
.