Lyx
Sergeant
It's no secret that the roleplaying aspect of MnB is rather.... repetitive. Quite quickly, you've seen everything, are just running from one battle to the next, and do repetitive missions simply so that certain numbers change, not because its a task you like to do. One way to change that would be more variety in generic quests - but because of how the module system is organized and it's syntax, quests require a lot of effort to implement.
So, today i had a little idea - people who've played sandbox games like pirates, or certain 4x games, are probably aware of random events. You just from time to time get a random popup which informs you that something happened, some stats or stuff changes in the world, and thats it. It's like in one of those board games where you draw a random card from a deck, which tells you about some special event which happened, and which changes stuff.
Now, the nice thing about such random events is that they are trivial to implement, because they require no user interaction and no scene setups, no state-tracking of stuff, and all that crap. It's just a dialog which pops up, you get to click "continue..." , some consequences get applied, and done. Actually, they're so trivial to implement, that its more work to come up with ideas and write nice texts, than to implement them.
I've just spent the last 2 hours setting up a simple system for such random events. I can add events to the pool with just a few lines of code at one single central place (instead of stuff scathered around the module system, as its often the case). What i currently can do is:
1. have a pool of events from which one can be randomly choosen every 2 weeks.
2. When an event is triggered, check if certain conditions are met.
3. Display a notification dialog which shows some text.
4. Apply simple consequences.
Why would one want something like that? Well, you'd want it if you would like the life in the game to be made a bit more variable and colorful, by adding simple random stuff. Just some small things which break the routine.
So, here's your task: What kind of simple random events can you think of? Remember, we're NOT talking about missions, encounters and stuff.... we're just talking about "fire-and-forget" events which require no more presentation than some text. Also, we're not talking about very specific events which only apply in a small amount of situations or have huge and complex consequences - we're talking about small random generic stuff which can happen to (almost) everyone anytime.
Brainstorm ahead!
-----
Currently implemented simple random events:
- Fire in village/town
- Good harvest in village
- Good trading in city
- Lost piece of art found
- Disease in village/town contained/cured
- Player/Companion training accident
Current WIP source snapshot (you need the module system for this):
Put this somewhere (i prefer end) in simple triggers:
And this somewhere (i.e. end) in scripts:
This SHOULD be savegame compatible, but i haven't tested that.
So, today i had a little idea - people who've played sandbox games like pirates, or certain 4x games, are probably aware of random events. You just from time to time get a random popup which informs you that something happened, some stats or stuff changes in the world, and thats it. It's like in one of those board games where you draw a random card from a deck, which tells you about some special event which happened, and which changes stuff.
Now, the nice thing about such random events is that they are trivial to implement, because they require no user interaction and no scene setups, no state-tracking of stuff, and all that crap. It's just a dialog which pops up, you get to click "continue..." , some consequences get applied, and done. Actually, they're so trivial to implement, that its more work to come up with ideas and write nice texts, than to implement them.
I've just spent the last 2 hours setting up a simple system for such random events. I can add events to the pool with just a few lines of code at one single central place (instead of stuff scathered around the module system, as its often the case). What i currently can do is:
1. have a pool of events from which one can be randomly choosen every 2 weeks.
2. When an event is triggered, check if certain conditions are met.
3. Display a notification dialog which shows some text.
4. Apply simple consequences.
Why would one want something like that? Well, you'd want it if you would like the life in the game to be made a bit more variable and colorful, by adding simple random stuff. Just some small things which break the routine.
So, here's your task: What kind of simple random events can you think of? Remember, we're NOT talking about missions, encounters and stuff.... we're just talking about "fire-and-forget" events which require no more presentation than some text. Also, we're not talking about very specific events which only apply in a small amount of situations or have huge and complex consequences - we're talking about small random generic stuff which can happen to (almost) everyone anytime.
Brainstorm ahead!
-----
Currently implemented simple random events:
- Fire in village/town
- Good harvest in village
- Good trading in city
- Lost piece of art found
- Disease in village/town contained/cured
- Player/Companion training accident
Current WIP source snapshot (you need the module system for this):
Put this somewhere (i prefer end) in simple triggers:
Code:
#---BEGIN LYX RANDOM EVENTS---
(1 * 6,[ # interval currently set to 6 hours for testing - should be 14 * 24 for normal play
# Init
# ---------------------------------------------------------------------------
(assign, ":total_events", 7), # update this when adding/removing events!
(val_add, ":total_events", 1), # MnB has weird ideas of ranges
(store_random_in_range, ":curr_event", 0, ":total_events"),
(neq, ":curr_event", "$g_lyx_last_random_event"), # ignore event if same as last
(assign, "$g_lyx_last_random_event", ":curr_event"),
(assign, ":pos", 0),
(try_begin), (eq,1,2), # dummy
# Events
# ---------------------------------------------------------------------------
# --- FIRE IN CITY OR VILLAGE ---
(else_try), (val_add,":pos",1), (eq,":pos",":curr_event"), # this first line is same for all events
(call_script, "script_get_random_center_of_lord", "trp_player", 4),
(assign, ":center_no", reg0),
(neq,":center_no",-1), # skip event if player has no matching center
(call_script, "script_get_player_distance_to_center", ":center_no"), (ge,reg0,8), # abort if player is close
(str_store_party_name, s5, ":center_no"),
(dialog_box, "@A messenger informs you that there was a fire in {s5}. It's under control now, but it may take a while until the damage is repaired.", "@Fire in one of your fiefs:"),
(call_script, "script_change_center_prosperity", ":center_no", -25),
# --- VILLAGE GOOD HARVEST ---
(else_try), (val_add,":pos",1), (eq,":pos",":curr_event"), # this first line is same for all events
(call_script, "script_get_random_center_of_lord", "trp_player", 1),
(assign, ":center_no", reg0),
(neq,":center_no",-1), # skip event if player has no matching center
(call_script, "script_get_center_prosperity", ":center_no"), (le,reg0,75), # abort if center is already rich
(str_store_party_name, s5, ":center_no"),
(dialog_box, "@The village of {s5} had a great harvest recently and the locals managed to trade well. Their prosperity has improved!", "@Good Harvest:"),
(call_script, "script_change_center_prosperity", ":center_no", 25),
# --- CITY GOOD TRADE / LOST ART FOUND---
(else_try), (val_add,":pos",1), (eq,":pos",":curr_event"), # this first line is same for all events
(call_script, "script_get_random_center_of_lord", "trp_player", 2),
(assign, ":center_no", reg0),
(neq,":center_no",-1), # skip event if player has no matching center
(call_script, "script_get_center_prosperity", ":center_no"), (le,reg0,75), # abort if center is already rich
(str_store_party_name, s5, ":center_no"),
(store_random_in_range, ":rand_num", 1, 2),
(try_begin),
(eq,":rand_num",1), (dialog_box, "@The merchant caravans of {s5} managed to do very profitable trading recently. {s5}'s wealth has benefited significantly from this!", "@Good Trading:"),
(else_try),
(eq,":rand_num",2), (dialog_box, "@A famous piece of art, which was long been thought lost, was found near {s5}! It is currently on display in {s5} and people are coming from all over Calradia to see it. The merchants are profiting greatly from this surge in visitors.", "@Lost art found:"),
(try_end),
(call_script, "script_change_center_prosperity", ":center_no", 25),
# --- DISEASE ---
(else_try), (val_add,":pos",1), (eq,":pos",":curr_event"), # this first line is same for all events
(call_script, "script_get_random_center_of_lord", "trp_player", 4),
(assign, ":center_no", reg0),
(neq,":center_no",-1), # skip event if player has no matching center
(call_script, "script_get_player_distance_to_center", ":center_no"), (ge,reg0,8), # abort if player is close
(call_script, "script_get_player_relation_with_center", ":center_no"), (ge,reg0,-30), # abort if center hates you already
(str_store_party_name, s5, ":center_no"),
(dialog_box, "@A messenger informs you that a painful disease has broken out in {s5}. A surgeon was sent, but was unable to find a cure. All he could do, was to contain the plague by seperating the healthy from the sick. The quarantine was succesful, but the trust of {s5}'s people in you, has suffered.", "@Disease contained:"),
(call_script, "script_change_player_relation_with_center", ":center_no", -6),
# --- DISEASE AVERTED ---
(else_try), (val_add,":pos",1), (eq,":pos",":curr_event"), # this first line is same for all events
(call_script, "script_get_random_center_of_lord", "trp_player", 4),
(assign, ":center_no", reg0),
(neq,":center_no",-1), # skip event if player has no matching center
(call_script, "script_get_player_distance_to_center", ":center_no"), (ge,reg0,8), # abort if player is close
(call_script, "script_get_player_relation_with_center", ":center_no"), (le,reg0,30), # abort if center loves you already
(str_store_party_name, s5, ":center_no"),
(dialog_box, "@A messenger informs you that a painful disease had broken out in {s5}. However, a surgeon was sent and managed to find a cure for the plague. The people of {s5} are grateful for how this evil was handled, and their trust in you has improved!", "@Disease averted:"),
(call_script, "script_change_player_relation_with_center", ":center_no", 6),
# --- COMPANION INJURED ---
(else_try), (val_add,":pos",1), (eq,":pos",":curr_event"), # this first line is same for all events
(call_script, "script_get_random_hero_in_playerparty"),
(assign, ":troop_no", reg0),
(neq,":troop_no",-1), # skip event if no companion in party
(call_script, "script_get_troop_health",":troop_no"), (ge,reg0,60), # abort if companion is already weak
(str_store_troop_name, s5, ":troop_no"),
(dialog_box, "@{s5} was accidently injured during today's training. The wounds aren't severe, but it may take some time for {s5} to be in top form again.", "@Training accident:"),
(call_script, "script_change_troop_health", ":troop_no", -40),
# --- PLAYER INJURED ---
(else_try), (val_add,":pos",1), (eq,":pos",":curr_event"), # this first line is same for all events
(call_script, "script_get_troop_health", "trp_player"), (ge,reg0,60), # abort if player is already weak
(dialog_box, "@During today's training, you were accidently injured. While the wounds aren't severe, it may take some time for them to heal.", "@Training accident:"),
(call_script, "script_change_troop_health", "trp_player", -40),
# Closing
# --------------------------------------
(try_end),
]),
#---END LYX RANDOM EVENTS---
And this somewhere (i.e. end) in scripts:
Code:
#---BEGIN LYX HELPER-SCRIPTS---
#script to get a troop's health
#INPUT: arg1 = troop_no
#OUTPUT: reg0 - health percentage
("get_troop_health",[
(store_script_param, ":troop_no", 1),
(store_troop_health, reg0, ":troop_no")
]),
#script to modify a troop's health
#INPUT: arg1 = troop_no, arg2 = health percentage modifier
#OUTPUT: none
("change_troop_health",[
(store_script_param, ":troop_no", 1),
(store_script_param, ":modifier", 2),
(store_troop_health, ":troop_hp",":troop_no"),
(val_add, ":troop_hp", ":modifier"),
(val_clamp, ":troop_hp", 1, 100),
(troop_set_health, ":troop_no", ":troop_hp"),
]),
#script to get a prosperity of a center
#INPUT: arg1 = troop_no
#OUTPUT: reg0 - prosperity (0-100)
("get_center_prosperity",[
(store_script_param, ":troop_no", 1),
(party_get_slot, reg0, ":troop_no", slot_town_prosperity),
]),
#script to get player relation with faction
#INPUT: arg1 = faction_no
#OUTPUT: reg0 - relation
("get_player_relation_with_faction",[
(store_script_param, ":faction_no", 1),
(store_relation, reg0, ":faction_no", "fac_player_supporters_faction"),
]),
#script to get player relation with center
#INPUT: arg1 = center_no
#OUTPUT: reg0 - relation
("get_player_relation_with_center",[
(store_script_param, ":center_no", 1),
(party_get_slot, reg0, ":center_no", slot_center_player_relation),
]),
#script to get player distance between player and a center
#INPUT: arg1 = center_no
#OUTPUT: reg0 - distance
("get_player_distance_to_center",[
(store_script_param, ":center_no", 1),
(store_distance_to_party_from_party, reg0, "p_main_party", ":center_no"),
]),
#script to get a random hero in player's party
#INPUT: none
#OUTPUT: reg0 = troop_no
("get_random_hero_in_playerparty",[
# create list of all heroes in player party
(assign, ":pos", 0),
(try_for_range,":troop_no",companions_begin,heroes_end),
(troop_slot_eq, ":troop_no", slot_troop_occupation, slto_player_companion),
(troop_set_slot, "trp_temp_array_a", ":pos", ":troop_no"),
(val_add, ":pos", 1),
(try_end),
# pick one randomly or output -1 if none found
(try_begin),
(eq,":pos",0), (assign,reg0,-1),
(else_try),
(val_add, ":pos", 1),
(store_random_in_range, ":rand_pos", 0, ":pos"),
(troop_get_slot, reg0, "trp_temp_array_a", ":rand_pos"),
(try_end),
]),
#script to get a random center owned by a lord (may be "trp_player") (by ConstantA & Lyx)
#INPUT: arg1 = troop_no, arg2 = mode (0=all, 1=village, 2=city, 3=castle. 4=city or village, 5=city or castle)
#OUTPUT: reg0 - center_no or -1 if none available
("get_random_center_of_lord",[
(store_script_param, ":troop_no", 1),
(store_script_param, ":mode", 2),
(assign, ":pos", 0),
# consider villages?
(try_begin),
(this_or_next|eq,":mode",0),
(this_or_next|eq,":mode",1),
(eq,":mode",4),
(try_for_range, ":center_no", villages_begin, villages_end),
(party_slot_eq, ":center_no", slot_town_lord, ":troop_no"),
(troop_set_slot, "trp_temp_array_a", ":pos", ":center_no"),
(val_add, ":pos", 1),
(try_end),
(try_end),
# consider cities?
(try_begin),
(this_or_next|eq,":mode",0),
(this_or_next|eq,":mode",2),
(eq,":mode",5),
(try_for_range, ":center_no", towns_begin, towns_end),
(party_slot_eq, ":center_no", slot_town_lord, ":troop_no"),
(troop_set_slot, "trp_temp_array_a", ":pos", ":center_no"),
(val_add, ":pos", 1),
(try_end),
(try_end),
# consider castles?
(try_begin),
(this_or_next|eq,":mode",0),
(this_or_next|eq,":mode",3),
(eq,":mode",5),
(try_for_range, ":center_no", castles_begin, castles_end),
(party_slot_eq, ":center_no", slot_town_lord, ":troop_no"),
(troop_set_slot, "trp_temp_array_a", ":pos", ":center_no"),
(val_add, ":pos", 1),
(try_end),
(try_end),
# pick random from gathered list, or return -1 if none available (none owned by the troop)
(try_begin),
(eq,":pos",0), (assign,reg0,-1),
(else_try),
(val_add, ":pos", 1),
(store_random_in_range, ":rand_pos", 0, ":pos"),
(troop_get_slot, reg0, "trp_temp_array_a", ":rand_pos"),
(try_end),
]),
#---END LYX HELPER-SCRIPTS---
This SHOULD be savegame compatible, but i haven't tested that.