Some RPG games have implemented system where you can read book and scrolls. As you probably noticed - books serve no purpose in M&B games except being one time use objects for raising your character stats. That's why I decided to create this bad boy to bring some immersion and content to your mod.
First, let's take a look at pros & cons of this kit:
Pros:
Cons:
Now take a look at the screenshots to have an idea how it looks like:
*Please take a note that the open book texture and scroll item mesh is not included in the OSP. For the open book mesh I provided you with a texture template with important areas (book cover area, book page area and actual text box area) marked out. Open scroll mesh currently uses Native texture.
How it works:
Credits:
For a foundation you're going to need the necessary resources. You can find them here.
The file contains:
Next, the presentation code (insert to module_presentations):
Now it's time for scripts (insert to module_scripts):
Now the meshes (insert to module_meshes):
Items (insert to module_items):
Finally, the mission templates (insert to module_mission_templates):
Now insert the book_reading, in the same way other triggers are to the mission you want to be able to read.
Example in town_center mission:
That concludes the installation. Now test if everything works correctly. Give player the items you added and press 'B' while in mission you added the trigger to.
Instructions on how to add your own books & scrolls and multiple language support are located in the second post below.
Overwiew
First, let's take a look at pros & cons of this kit:
Pros:
- Ease of manipulation - the code is documented and should be easy to modify if you know what you're doing.
- Versatility - possibilities with this kit are almost limitless. You can start a quest after loading certain page for example.
- Compatibility - script should be compatible with most of the mods without custom fonts, you should be able to make it multiplayer compatible with no problems. Not sure how it looks like with custom font installed.
- User friendly GUI - book selection menu is very intuitive and easy to work with.
- Page generator included - text boxes in this game have weird behavior of changing their position if there's too little or too much text in the string with defined area size. That's why I created a simple pages generator for you in JavaScript so you don't have to match your text with the box size by trial and error for every page.
Cons:
- Modding experience required - unfortunately, the kit requires you to know at least some fundamentals of M&B scripting. Well, if you know what operations try_begin, else_try, try_end and str_store_string are there for then you should be fine.
- Your own effort required - you probably know this by know. You're going to add your own books and/or scrolls after all. Also, the presentation is going to look much better if you create your own high-res textures for books.
- Could still be buggy - I tried my best to ensure that most of the bugs and exploits were taken care of, however I'm only human after all. Please post a comment here if you encounter any bugs or problems.
Now take a look at the screenshots to have an idea how it looks like:
*Please take a note that the open book texture and scroll item mesh is not included in the OSP. For the open book mesh I provided you with a texture template with important areas (book cover area, book page area and actual text box area) marked out. Open scroll mesh currently uses Native texture.
How it works:
- After you press the defined button (default 'B') while in specific mission in mission_templates, the book selection menu will open up. Then you can scroll thru the item menu and select the item you want to read. Additionally, there's an item mesh sneak peak on the left displayed on hower. Currently there are as many selectable items supported as big is the maximum size merchant inventory. Press the defined button again to quit.
- After you select the item the script get_book_details_from_book_database is called for the item you selected and presentation is automatically closed and re-opened (instant process). The script assigns variables for presentation for the specific item.
- Basic presentation elements are created for the variables from previous script and script flip_page_for_book is called. It's purpose is to generate the text from ready strings. Note that currently you can have max two pages for scrolls (makes sense, doesn't it) and as many as you like for books. Book pages amount is only limited to as many as the game engine can handle.
Credits:
- me (Masterancza/Garedyr)
- rubik (because I took inspiration on how to do item selection menu from one of his OSP's)
Installation
For a foundation you're going to need the necessary resources. You can find them here.
The file contains:
- book_generator folder - this folder contains a simple but powerful tool when it comes to generating book and scroll pages for our presentation. Extract it anywhere.
- Resource folder - you need to either drop the book_reading_osp.brf (which is inside of it) to your mod resources folder or merge it with existing brf file.
- Textures folder - Here you can find the template open book texture. Just drop the file to your mod's textures folder. You can edit it later.
Next, the presentation code (insert to module_presentations):
Code:
("book_reading", prsntf_manual_end_only, 0,
[
(ti_on_presentation_load,
[
(presentation_set_duration, 999999),
(set_fixed_point_multiplier, 1000),
(str_clear, s1), # for left text box
(str_clear, s2), # for right text box or title
(str_clear, s3), # for left page number
(str_clear, s4), # for right page number
## Menu
(try_begin),
(eq, "$g_book", 1),
(create_mesh_overlay, "$g_presentation_obj_1", "mesh_book_menu"),
# Header
(create_text_overlay, "$g_presentation_obj_title", "@Select a book or scroll^ to read:^^^^^^^^", tf_double_space|tf_center_justify),
(position_set_x, pos1, 685), # was 655
(position_set_y, pos1, 385), # 200 530
(overlay_set_position, "$g_presentation_obj_title", pos1),
(position_set_x, pos1, 1000), # was 1100
(position_set_y, pos1, 1000), # was 1100
(overlay_set_size, "$g_presentation_obj_title", pos1),
(position_set_x, pos1, 975), # was 945
(position_set_y, pos1, 150),
(overlay_set_area_size, "$g_presentation_obj_title", pos1),
# Scrollable area
(create_text_overlay, "$g_presentation_obj_2", "str_empty_string", tf_scrollable),
(position_set_x, pos1, 630), # was 600
(position_set_y, pos1, 250), # was 250
(overlay_set_position, "$g_presentation_obj_2", pos1),
(position_set_x, pos1, 168), # was 138
(position_set_y, pos1, 230), # was 230
(overlay_set_area_size, "$g_presentation_obj_2", pos1),
# Div begin
(set_container_overlay, "$g_presentation_obj_2"),
(troop_clear_inventory, "trp_temp_array_a"),
(troop_get_inventory_capacity, ":inv_cap", "trp_player"),
# Checking player's inventory for books
(try_for_range, ":i_slot", 0, ":inv_cap"),
(troop_get_inventory_slot, ":item", "trp_player", ":i_slot"),
(neq, ":item", -1),
(item_get_type, ":typ", ":item"),
(eq, ":typ", itp_type_book),
# Dupe checker
(assign, ":found_dupes", 0),
(try_for_range, ":dupe_checker", 10, 106),
(troop_get_inventory_slot, ":possible_dupe", "trp_temp_array_a", ":dupe_checker"),
(eq, ":possible_dupe", ":item"),
(val_add, ":found_dupes", 1),
(try_end),
# Adding item to array if no dupes were found
(try_begin),
(eq, ":found_dupes", 0),
(troop_add_item, "trp_temp_array_a", ":item"),
(try_end),
(try_end),
# Assigning base positions
(assign, ":pos_x", 0),
(assign, ":pos_y", 1250),
(assign, ":slot_no", 10),
# A total of 32 rows
(try_for_range, ":unused_height", 0, 32),
(try_for_range, ":unused_width", 0, 3), # 3 columns
(create_mesh_overlay, reg1, "mesh_mp_inventory_choose"),
(position_set_x, pos1, 320), # was 320
(position_set_y, pos1, 320), # was 320
(overlay_set_size, reg1, pos1),
(position_set_x, pos1, ":pos_x"),
(position_set_y, pos1, ":pos_y"),
(overlay_set_position, reg1, pos1),
(troop_set_slot, "trp_temp_array_a", ":slot_no", reg1),
(create_mesh_overlay, reg1, "mesh_inv_slot"),
(position_set_x, pos1, 400), # was 400
(position_set_y, pos1, 400), # was 400
(overlay_set_size, reg1, pos1),
(position_set_x, pos1, ":pos_x"),
(position_set_y, pos1, ":pos_y"),
(overlay_set_position, reg1, pos1),
(troop_get_inventory_slot, ":item_no", "trp_temp_array_a", ":slot_no"),
(val_max, ":item_no", 0),
(create_mesh_overlay_with_item_id, reg1, ":item_no"),
(position_set_x, pos1, 400), # was 400
(position_set_y, pos1, 400), # was 400
(overlay_set_size, reg1, pos1),
(store_add, ":item_x", ":pos_x", 20),
(store_add, ":item_y", ":pos_y", 20),
(position_set_x, pos1, ":item_x"),
(position_set_y, pos1, ":item_y"),
(overlay_set_position, reg1, pos1),
(troop_set_slot, "trp_temp_array_b", ":slot_no", reg1),
(val_add, ":pos_x", 40),
(val_add, ":slot_no", 1),
(try_end),
(assign, ":pos_x", 0),
(val_sub, ":pos_y", 40),
(try_end),
(set_container_overlay, -1),
# Div end
# Hint
(create_text_overlay, "$g_presentation_obj_3", "@Press 'B' again to quit", tf_with_outline|tf_center_justify),
(overlay_set_color, "$g_presentation_obj_3", 0xFFFFFF),
(position_set_x, pos1, 800), # was 138
(position_set_y, pos1, 800), # was 230
(overlay_set_size, "$g_presentation_obj_3", pos1),
(position_set_x, pos1, 694), # was 600
(position_set_y, pos1, 140), # was 250
(overlay_set_position, "$g_presentation_obj_3", pos1),
# Book mesh sneak peak
(assign, "$g_current_opened_item_mesh", -1),
(try_for_range, ":slot_no_c", 10, 106),
(troop_get_inventory_slot, ":item_no_c", "trp_temp_array_a", ":slot_no_c"),
(neq, ":item_no_c", -1),
(create_mesh_overlay_with_item_id, reg1, ":item_no_c"),
(position_set_x, pos1, 2300), # was 138
(position_set_y, pos1, 2300), # was 230
(overlay_set_size, reg1, pos1),
(position_set_x, pos1, 325), # was 600
(position_set_y, pos1, 436), # was 250
(overlay_set_position, reg1, pos1),
(overlay_set_display, reg1, 0),
(troop_set_slot, "trp_temp_array_c", ":slot_no_c", reg1),
(try_end),
## Books & Scrolls
(else_try),
# Current book/scroll page flips
(assign, "$g_current_flips", 0),
# First page
(call_script, "script_flip_page_for_book", "$g_book"),
## Book
(try_begin),
(eq, "$g_book_style", 0),
# Book mesh
(create_mesh_overlay, "$g_presentation_obj_1", "$g_book_mesh"),
# Book title
(create_text_overlay, "$g_presentation_obj_title", s2, tf_double_space|tf_center_justify),
(position_set_x, pos1, 665),
(position_set_y, pos1, 385), # 200 530
(overlay_set_position, "$g_presentation_obj_title", pos1),
(position_set_x, pos1, 1200), # was 1000
(position_set_y, pos1, 1200), # was 1000
(overlay_set_size, "$g_presentation_obj_title", pos1),
(position_set_x, pos1, 955), # was 480
(position_set_y, pos1, 150),
(overlay_set_area_size, "$g_presentation_obj_title", pos1),
# Book title on/off
(try_begin),
(eq, "$g_book_title", 0),
(overlay_set_display, "$g_presentation_obj_title", 0),
(try_end),
# Page numbers
# Left
(create_text_overlay, "$g_presentation_obj_2", s3, tf_center_justify),
(position_set_x, pos1, 320),
(position_set_y, pos1, 138),
(overlay_set_position, "$g_presentation_obj_2", pos1),
# Right
(create_text_overlay, "$g_presentation_obj_3", s4, tf_center_justify),
(position_set_x, pos1, 660), # was 650
(position_set_y, pos1, 138),
(overlay_set_position, "$g_presentation_obj_3", pos1),
# Page numbers on/off
(try_begin),
(eq, "$g_book_page_numbers", 0),
(overlay_set_display, "$g_presentation_obj_2", 0),
(overlay_set_display, "$g_presentation_obj_3", 0),
(try_end),
# Text boxes
# Left align
(create_text_overlay, "$g_presentation_obj_4", s1, tf_double_space),
(position_set_x, pos1, 170), # x is higher by 10 in reality | was 175
(position_set_y, pos1, 185), # was 165
(overlay_set_position, "$g_presentation_obj_4", pos1),
(position_set_x, pos1, 900), # text size x
(position_set_y, pos1, 900), # text size y
(overlay_set_size, "$g_presentation_obj_4", pos1),
(position_set_x, pos1, 470), # x is exactly same in reality | was 475
(position_set_y, pos1, 50), # was 220
(overlay_set_area_size, "$g_presentation_obj_4", pos1),
# Right align
(create_text_overlay, "$g_presentation_obj_5", s2, tf_double_space),
(position_set_x, pos1, 530), # was 520
(position_set_y, pos1, 185), # 200 530 | was 165
(overlay_set_position, "$g_presentation_obj_5", pos1),
(position_set_x, pos1, 900), # was 1100
(position_set_y, pos1, 900), # was 1100
(overlay_set_size, "$g_presentation_obj_5", pos1),
(position_set_x, pos1, 820), # was 810
(position_set_y, pos1, 50),
(overlay_set_area_size, "$g_presentation_obj_5", pos1),
# If book has title right text is hidden for the first page
(try_begin),
(eq, "$g_book_title", 1),
(overlay_set_display, "$g_presentation_obj_5", 0),
(try_end),
# Buttons
# Previous page button
(create_image_button_overlay, "$g_presentation_obj_6", "mesh_book_arrow_left", "mesh_book_arrow_left_pressed"),
(position_set_x, pos1, 300),
(position_set_y, pos1, 300),
(overlay_set_size, "$g_presentation_obj_6", pos1),
(position_set_x, pos1, 175),
(position_set_y, pos1, 136),
(overlay_set_position, "$g_presentation_obj_6", pos1),
# Next page button
(create_image_button_overlay, "$g_presentation_obj_7", "mesh_book_arrow_right", "mesh_book_arrow_right_pressed"),
(position_set_x, pos1, 300),
(position_set_y, pos1, 300),
(overlay_set_size, "$g_presentation_obj_7", pos1),
(position_set_x, pos1, 790), # was 800
(position_set_y, pos1, 136),
(overlay_set_position, "$g_presentation_obj_7", pos1),
## Scroll
(else_try),
# Scroll mesh front
(create_mesh_overlay, "$g_presentation_obj_1", "$g_book_mesh"),
# Scroll mesh back
(create_mesh_overlay, "$g_presentation_obj_2", "$g_book_mesh_back"),
(overlay_set_display, "$g_presentation_obj_2", 0), # hidden
# Text box
(create_text_overlay, "$g_presentation_obj_3", s1, tf_double_space),
(position_set_x, pos1, 360),
(position_set_y, pos1, 165),
(overlay_set_position, "$g_presentation_obj_3", pos1),
(position_set_x, pos1, 900), # text size x
(position_set_y, pos1, 900), # text size y
(overlay_set_size, "$g_presentation_obj_3", pos1),
(position_set_x, pos1, 700),
(position_set_y, pos1, 50),
(overlay_set_area_size, "$g_presentation_obj_3", pos1),
# Previous page button
(create_image_button_overlay, "$g_presentation_obj_4", "mesh_book_arrow_left", "mesh_book_arrow_left_pressed"),
(position_set_x, pos1, 300),
(position_set_y, pos1, 300),
(overlay_set_size, "$g_presentation_obj_4", pos1),
(position_set_x, pos1, 330),
(position_set_y, pos1, 115),
(overlay_set_position, "$g_presentation_obj_4", pos1),
# Next page button
(create_image_button_overlay, "$g_presentation_obj_5", "mesh_book_arrow_right", "mesh_book_arrow_right_pressed"),
(position_set_x, pos1, 300),
(position_set_y, pos1, 300),
(overlay_set_size, "$g_presentation_obj_5", pos1),
(position_set_x, pos1, 650),
(position_set_y, pos1, 115),
(overlay_set_position, "$g_presentation_obj_5", pos1),
(try_end),
(try_end),
]),
(ti_on_presentation_run,
[
(set_fixed_point_multiplier, 1000),
# Exit
(try_begin),
(key_clicked, key_b),
(presentation_set_duration, 0),
(try_end),
# String & Button hiding/showing
(try_begin),
(neq, "$g_book", 1), # not in book menu
(try_begin),
(ge, "$g_current_flips", 1), # after one flip
# Book
(try_begin),
(eq, "$g_book_style", 0),
# Title switch
(try_begin),
(eq, "$g_book_title", 1),
(overlay_set_display, "$g_presentation_obj_title", 0),
(overlay_set_display, "$g_presentation_obj_5", 1),
(try_end),
# Button switch
# Previous page button
(overlay_set_display, "$g_presentation_obj_6", 1),
# Next page button
(try_begin),
(eq, "$g_current_flips", "$g_max_flips"),
(overlay_set_display, "$g_presentation_obj_7", 0),
(else_try),
(overlay_set_display, "$g_presentation_obj_7", 1),
(try_end),
# Scroll
(else_try),
# Hiding back page and enabling front one
(overlay_set_display, "$g_presentation_obj_1", 0),
(overlay_set_display, "$g_presentation_obj_2", 1),
# Button switch
# Previous page button
(overlay_set_display, "$g_presentation_obj_4", 1),
# Next page button
(overlay_set_display, "$g_presentation_obj_5", 0),
(try_end),
(else_try),
# Book
(try_begin),
(eq, "$g_book_style", 0),
# Title switch
(try_begin),
(eq, "$g_book_title", 1),
(overlay_set_display, "$g_presentation_obj_title", 1),
(overlay_set_display, "$g_presentation_obj_5", 0),
(try_end),
# Button switch
# Previous page button
(overlay_set_display, "$g_presentation_obj_6", 0),
# Next page button
(try_begin),
(neq, "$g_max_flips", 0),
(overlay_set_display, "$g_presentation_obj_7", 1),
(try_end),
# Scroll
(else_try),
# Hiding back page and enabling front one
(overlay_set_display, "$g_presentation_obj_1", 1),
(overlay_set_display, "$g_presentation_obj_2", 0),
# Button switch
# Previous page button
(overlay_set_display, "$g_presentation_obj_4", 0),
# Next page button
(try_begin),
(neq, "$g_max_flips", 0),
(overlay_set_display, "$g_presentation_obj_5", 1),
(else_try),
(overlay_set_display, "$g_presentation_obj_5", 0),
(try_end),
(try_end),
(try_end),
(try_end),
]),
(ti_on_presentation_mouse_enter_leave,
[
(store_trigger_param_1, ":object"),
(store_trigger_param_2, ":enter_leave"),
(try_begin),
(eq, "$g_book", 1),
(try_begin),
(eq, ":enter_leave", 0),
(try_for_range, ":slot_no", 10, 106),
(troop_slot_eq, "trp_temp_array_a", ":slot_no", ":object"),
(troop_get_inventory_slot, ":item", "trp_temp_array_a", ":slot_no"),
(try_begin),
(neq, ":item", -1),
(troop_get_slot, ":target_obj", "trp_temp_array_b", ":slot_no"),
(troop_get_slot, ":target_obj_c", "trp_temp_array_c", ":slot_no"),
(overlay_get_position, pos0, ":target_obj"),
(show_item_details, ":item", pos0, 100),
(assign, "$g_current_opened_item_details", ":slot_no"),
# Open mesh sneak peak
(try_begin),
(neq, "$g_current_opened_item_mesh", -1),
(overlay_set_display, "$g_current_opened_item_mesh", 0), # bug fix
(try_end),
(overlay_set_display, ":target_obj_c", 1),
(assign, "$g_current_opened_item_mesh", ":target_obj_c"),
(try_end),
(try_end),
(else_try),
(try_for_range, ":slot_no", 10, 106),
(troop_slot_eq, "trp_temp_array_a", ":slot_no", ":object"),
(try_begin),
(eq, "$g_current_opened_item_details", ":slot_no"),
(close_item_details),
# Close mesh sneak peak
(overlay_set_display, "$g_current_opened_item_mesh", 0),
(assign, "$g_current_opened_item_mesh", -1),
(try_end),
(try_end),
(try_end),
(try_end),
]),
(ti_on_presentation_mouse_press,
[
(store_trigger_param_1, ":przycisk"),
(store_trigger_param_2, ":rodzaj"),
# Book selection menu
(try_begin),
(eq, "$g_book", 1),
(try_begin),
(eq, ":rodzaj", 0),
(try_for_range, ":slot_no", 10, 106),
(troop_slot_eq, "trp_temp_array_a", ":slot_no", ":przycisk"),
(troop_get_inventory_slot, ":item", "trp_temp_array_a", ":slot_no"),
(try_begin),
(neq, ":item", -1),
(close_item_details),
(call_script, "script_get_book_details_from_book_database", ":item"),
(play_sound, "snd_click"),
(presentation_set_duration, 0),
(start_presentation, "prsnt_book_reading"),
(try_end),
(try_end),
(try_end),
(try_end),
]),
(ti_on_presentation_event_state_change,
[
(store_trigger_param_1, ":przycisk"),
# Page flipping buttons
(try_begin),
(neq, "$g_book", 1),
# Book
(try_begin),
(eq, "$g_book_style", 0),
# Page - 1
(try_begin),
(eq, ":przycisk", "$g_presentation_obj_6"),
(val_add, "$g_current_flips", -1),
(call_script, "script_flip_page_for_book", "$g_book"),
# Page numbers -
(overlay_set_text, "$g_presentation_obj_2", s3),
(overlay_set_text, "$g_presentation_obj_3", s4),
# Text boxes
(overlay_set_text, "$g_presentation_obj_4", s1),
(overlay_set_text, "$g_presentation_obj_5", s2),
# Page flip sound
#(play_sound, "snd_page_flip"),
# Page + 1
(else_try),
(eq, ":przycisk", "$g_presentation_obj_7"),
(val_add, "$g_current_flips", 1),
(call_script, "script_flip_page_for_book", "$g_book"),
# Page numbers +
(overlay_set_text, "$g_presentation_obj_2", s3),
(overlay_set_text, "$g_presentation_obj_3", s4),
# Text boxes
(overlay_set_text, "$g_presentation_obj_4", s1),
(overlay_set_text, "$g_presentation_obj_5", s2),
# Page flip sound
#(play_sound, "snd_page_flip"),
(try_end),
# Scroll
(else_try),
# Page - 1
(try_begin),
(eq, ":przycisk", "$g_presentation_obj_4"),
(val_add, "$g_current_flips", -1),
(call_script, "script_flip_page_for_book", "$g_book"),
# Text box
(overlay_set_text, "$g_presentation_obj_3", s1),
# Page flip sound
#(play_sound, "snd_page_flip"),
# Page + 1
(else_try),
(eq, ":przycisk", "$g_presentation_obj_5"),
(val_add, "$g_current_flips", 1),
(call_script, "script_flip_page_for_book", "$g_book"),
# Text box
(overlay_set_text, "$g_presentation_obj_3", s1),
# Page flip sound
#(play_sound, "snd_page_flip"),
(try_end),
(try_end),
(try_end),
]),
]),
Now it's time for scripts (insert to module_scripts):
Code:
# script_flip_page_for_book
# Input: book
# Output: s1, s2, s3, s4
# Script used for getting book/scroll text pages
("flip_page_for_book",
[
(store_script_param, ":book", 1),
(str_clear, s1),
(str_clear, s2),
(str_clear, s3),
(str_clear, s4),
(try_begin),
# Temp book 1
(eq, ":book", "itm_book_temp_1"),
(try_begin),
# Title
(eq, "$g_current_flips", 0),
(str_store_string, s1, "str_empty_string"),
(str_store_string, s2, "@ Template book^^by^^Garedyr"),
(str_store_string, s3, "str_empty_string"),
(str_store_string, s4, "str_empty_string"),
(else_try),
# Page 1 & 2
(eq, "$g_current_flips", 1),
(str_store_string, s1, "@ Lorem ipsum dolor sit amet,^ consectetur adipiscing elit. Vivamus^ vitae euismod enim. Sed porttitor^ sagittis velit vitae auctor. Sed^ iaculis pharetra nulla, ut placerat^ lacus volutpat eget. Vestibulum^ fermentum quam sit amet fermentum^ facilisis. Suspendisse in lectus ut^ dolor facilisis ornare. Aenean^ tincidunt auctor rutrum.^ Pellentesque erat mauris, blandit et^ egestas a, porttitor at libero.^ Phasellus eleifend tempor tortor, in^ blandit ligula molestie eu.^ Phasellus feugiat semper orci, nec^ luctus nisi molestie sed. Praesent^ rhoncus, diam ac sollicitudin^ sagittis, ex elit aliquam ex, sed^ ornare odio ex eu arcu. Praesent^ felis justo, tincidunt eleifend^ posuere at, ultricies vitae quam.^ Nam arcu libero, dictum non laoreet^ porttitor, imperdiet quis dui."),
(str_store_string, s2, "@ Integer a vestibulum lorem.^ Suspendisse vulputate dolor nec^ neque aliquam, ac suscipit lacus^ imperdiet. Vestibulum eget tristique^ arcu. Nulla ultricies augue id nisl^ porttitor aliquet nec a turpis.^ Vivamus a tempor dolor. Ut in diam^ convallis, egestas nibh eu,^ scelerisque est. Proin faucibus^ interdum libero nec viverra. Sed^ quis consectetur nulla. Aliquam sit^ amet neque nunc. Vivamus molestie^ egestas mollis. Nam vulputate magna^ metus, sit amet porta velit volutpat^ quis. Nam tempor felis orci, ut^ vehicula sapien posuere eu. In^ finibus interdum lacus at^ tincidunt.^^^^^^"),
(str_store_string, s3, "@1"),
(str_store_string, s4, "@2"),
(else_try),
# Page 3 & 4
(eq, "$g_current_flips", 2),
(str_store_string, s1, "@ Donec bibendum dapibus elit id^ imperdiet. Cras dapibus ligula^ turpis, vel consectetur enim^ interdum at. Pellentesque habitant^ morbi tristique senectus et netus et^ malesuada fames ac turpis egestas.^ Praesent dapibus, nunc a gravida^ commodo, felis ex porta mi, vel^ mattis sem diam vel nunc. Nam et^ lorem lobortis nibh finibus^ lobortis. Pellentesque sit amet arcu^ vel nisl dignissim sodales. Vivamus^ at sem vel purus fermentum aliquet.^ Ut quis facilisis dolor. Aliquam^ varius consequat pulvinar. Nulla^ massa justo, interdum id pulvinar^ ac, ultrices sed magna. Fusce erat^ felis, elementum et ullamcorper sed,^ elementum nec sapien. Fusce vitae^ ultrices erat, mattis cursus libero.^ Pellentesque cursus mauris lectus,^ sit amet pretium nisi bibendum non.^ Aenean sed metus sem. Morbi sed"),
(str_store_string, s2, "@ nulla lacinia, mollis dui sed,^ finibus lorem. Cras lobortis^ convallis hendrerit. Ut dapibus^ sodales pellentesque. Mauris^ dignissim sapien quis viverra^ mollis. Donec eros felis, dapibus^ eget lorem vitae, vestibulum^ imperdiet orci. Aliquam vel augue^ porttitor arcu porttitor imperdiet.^ Mauris pharetra euismod libero, sit^ amet interdum urna porta id. Proin^ vitae dolor viverra, rhoncus tortor^ eget, pulvinar velit. Suspendisse^ sed nisl eu lacus pharetra luctus.^ Fusce porttitor tellus vitae metus^ viverra suscipit. Orci varius^ natoque penatibus et magnis dis^ parturient montes, nascetur^ ridiculus mus. Mauris commodo eros^ pharetra dignissim dictum. Donec^ fermentum nulla porttitor ante^ finibus ultrices. Donec a imperdiet^ mi, et rhoncus neque. Donec"),
(str_store_string, s3, "@3"),
(str_store_string, s4, "@4"),
(else_try),
# Page 5 & 6
(eq, "$g_current_flips", 3),
(str_store_string, s1, "@ consequat scelerisque venenatis. Ut^ a dolor dolor. Nullam vitae aliquet^ elit. Maecenas a felis a nisi^ vulputate placerat. Sed gravida, leo^ non malesuada sodales, nisi tellus^ volutpat arcu, eu rutrum lorem justo^ ut libero. Integer scelerisque augue^ eget aliquet maximus. Maecenas in^ tempor elit. Mauris vel pretium^ lacus, in tincidunt quam. Maecenas^ pellentesque, justo quis fringilla^ maximus, lacus nulla molestie justo,^ ut dictum tellus neque id nulla.^ Curabitur orci metus, feugiat at^ dolor egestas, viverra malesuada^ nisi. Morbi est ante, viverra in^ nisl sed, sollicitudin malesuada^ sem. Vestibulum leo est, accumsan^ non augue eu, pretium imperdiet^ erat. Nam mollis posuere augue ut^ vestibulum. Sed tortor neque,^ imperdiet a sodales a, bibendum ac^ urna."),
(str_store_string, s2, "@ Praesent interdum convallis^ malesuada. Suspendisse potenti.^ Quisque quis fringilla quam, dapibus^ elementum augue. Etiam vulputate^ blandit dolor, id aliquet urna.^ Suspendisse eleifend eu lorem quis^ vehicula. Nullam tincidunt justo et^ dolor egestas pellentesque. Maecenas^ vitae feugiat augue, sed tempor^ nunc. Praesent vel vehicula lectus,^ quis imperdiet quam. Vestibulum^ maximus elit sit amet cursus dictum.^ Vivamus accumsan quis tortor vitae^ accumsan. Aenean lobortis nisi id^ quam aliquet efficitur. Sed^ consectetur sapien sit amet eleifend^ tristique. Aenean eu sapien eu elit^ blandit laoreet a sed purus.^^^^^^"),
(str_store_string, s3, "@5"),
(str_store_string, s4, "@6"),
(try_end),
(else_try),
(eq, ":book", "itm_temp_scroll"),
(try_begin),
(eq, "$g_current_flips", 0),
(str_store_string, s1, "@ Lorem ipsum dolor sit amet,^ consectetur adipiscing elit. Donec^ porta lorem nec felis cursus, eget^ pellentesque diam gravida. Vivamus^ ac enim tincidunt, pellentesque^ libero eu, faucibus est. Donec^ placerat dolor bibendum, dignissim^ purus sit amet, tincidunt purus.^ Praesent vel odio quis quam dictum^ congue ac luctus nisl. Class aptent^ taciti sociosqu ad litora torquent^ per conubia nostra, per inceptos^ himenaeos. Quisque tellus nisl,^ blandit vitae euismod et, convallis^ vitae urna. Etiam sed purus erat.^ Morbi varius ornare leo quis^ porttitor. Ut sed cursus est, non^ feugiat risus. Suspendisse a ipsum^ mattis, dapibus lacus sit amet,^ ultricies mauris. Fusce quis nisl^ varius, porta eros quis, finibus^ nulla.^^"),
(else_try),
(str_store_string, s1, "@ Vestibulum tempus orci lectus, et^ aliquam quam facilisis tincidunt.^ Phasellus porttitor porttitor augue,^ non vestibulum eros faucibus sit^ amet. Interdum et malesuada fames ac^ ante ipsum primis in faucibus. Nunc^ turpis purus, congue ac odio et,^ scelerisque bibendum urna. Aenean^ dignissim mi ante, nec pharetra^ tortor porta sit amet. Duis^ consectetur pulvinar ipsum, non^ aliquam elit congue id. Curabitur^ pharetra condimentum enim, ut^ viverra risus tempor eu. Integer^ dapibus nisl vitae lectus gravida^ rutrum. Maecenas elementum massa sit^ amet ligula porta, nec eleifend elit^ aliquet. Etiam volutpat dignissim^ enim id blandit. Sed ligula lectus,^ hendrerit porttitor velit nec,^ fermentum iaculis erat. Integer nibh^ ipsum, venenatis quis venenatis ut,^ volutpat vel ligula. Nam finibus,"),
(try_end),
(try_end),
]),
# Garedyr end
# script_get_book_details_from_book_database
# Input: book
# Output: "$g_book", "$g_book_mesh", "$g_book_mesh"_back, "$g_book_style", "$g_book_title", "$g_book_page_numbers", "$g_max_flips"
# Script used to initiate book/scroll variables
("get_book_details_from_book_database",
[
(store_script_param, ":book", 1),
# For both books and scrolls
# Used to determine book for reading by menu
(assign, "$g_book", ":book"),
# Book variables
# "$g_book_mesh" - determines which mesh will be used for presentation
# "$g_book_style" - determines whether use book or scroll style presentation
# "$g_book_title" - set it to 1 if you want the first page to be title page, 0 for no title
# "$g_book_page_numbers" - set it to 1 if you want to display page numbers, 0 for no page numbers
# "$g_max_flips" - range 0-x, determines how many times you can flip pages
# Scroll variables
# "$g_book_mesh" - determines which mesh will be used for presentation
# "$g_book_mesh_back" - determines which mesh will be used for the second scroll page (use same as above if there isn't any)
# "$g_book_style" - determines whether use book or scroll style presentation
# "$g_max_flips" - range 0-1, determines how many times you can flip pages (scrolls usually have only front and back page)
# Books
(try_begin),
# Template book
(eq, ":book", "itm_book_temp_1"),
(assign, "$g_book_mesh", "mesh_book_open_1"),
(assign, "$g_book_style", 0),
(assign, "$g_book_title", 1),
(assign, "$g_book_page_numbers", 1),
(assign, "$g_max_flips", 3),
# Scrolls
(else_try),
# Template scroll
(eq, ":book", "itm_temp_scroll"),
(assign, "$g_book_mesh", "mesh_scroll_open_1"),
(assign, "$g_book_mesh_back", "mesh_scroll_open_1_back"),
(assign, "$g_book_style", 1),
(assign, "$g_max_flips", 1),
(try_end),
]),
# Garedyr end
Now the meshes (insert to module_meshes):
Code:
("book_arrow_left", 0, "cb_ui_comp_arrow_l_d", 0, 0, 0, 0, 0, 0, 1, 1, 1),
("book_arrow_left_pressed", 0, "cb_ui_comp_arrow_l_p", 0, 0, 0, 0, 0, 0, 1, 1, 1),
("book_arrow_right", 0, "cb_ui_comp_arrow_r_d", 0, 0, 0, 0, 0, 0, 1, 1, 1),
("book_arrow_right_pressed", 0, "cb_ui_comp_arrow_r_p", 0, 0, 0, 0, 0, 0, 1, 1, 1),
("book_menu", 0, "book_menu", 0, 0, 0, 0, 0, 0, 1, 1, 1),
("book_open_1", 0, "book_open_1", 0, 0, 0, 0, 0, 0, 1, 1, 1),
("scroll_open_1", 0, "scroll_open_1", 0, 0, 0, 0, 0, 0, 1, 1, 1),
("scroll_open_1_back", 0, "scroll_open_1_back", 0, 0, 0, 0, 0, 0, 1, 1, 1),
Items (insert to module_items):
Code:
["book_temp_1","temp book 1", [("book_b",0)], itp_type_book, 0, 50,weight(2)|abundance(100),imodbits_none],
["temp_scroll","template scroll", [("book_b",0)], itp_type_book, 0,0,weight(0)|abundance(0),0],
Finally, the mission templates (insert to module_mission_templates):
Code:
# Book reading
# Make sure you maintain at least 0.5 second delay on the trigger.
# Otherwise the presentation won't load correctly and you may experience funny things.
# Ofc you can call the presentation from elsewhere if you want to do so.
book_reading = (
0, 0.5, 0,
[(neg|is_presentation_active, "prsnt_book_reading"), (key_clicked, key_b)],
[
# You can start from any book directly here if you insert
# get_book_details_from_book_database for your item and comment out the line below.
(assign, "$g_book", 1), # 1 = book menu
(start_presentation, "prsnt_book_reading"),
])
Now insert the book_reading, in the same way other triggers are to the mission you want to be able to read.
Example in town_center mission:
(44,mtef_visitor_source|mtef_team_1,af_override_horse,aif_start_alarmed,1,[]),
(45,mtef_visitor_source|mtef_team_1,af_override_horse,aif_start_alarmed,1,[]),
(46,mtef_visitor_source|mtef_team_1,af_override_horse,aif_start_alarmed,1,[]),
(47,mtef_visitor_source|mtef_team_1,af_override_horse,aif_start_alarmed,1,[]),
],
[
[...]
book_reading,
[...]
(ti_on_agent_spawn, 0, 0, [],
[
(store_trigger_param_1, ":agent_no"),
(call_script, "script_init_town_agent", ":agent_no"),
(try_begin),
(45,mtef_visitor_source|mtef_team_1,af_override_horse,aif_start_alarmed,1,[]),
(46,mtef_visitor_source|mtef_team_1,af_override_horse,aif_start_alarmed,1,[]),
(47,mtef_visitor_source|mtef_team_1,af_override_horse,aif_start_alarmed,1,[]),
],
[
[...]
book_reading,
[...]
(ti_on_agent_spawn, 0, 0, [],
[
(store_trigger_param_1, ":agent_no"),
(call_script, "script_init_town_agent", ":agent_no"),
(try_begin),
That concludes the installation. Now test if everything works correctly. Give player the items you added and press 'B' while in mission you added the trigger to.
Instructions on how to add your own books & scrolls and multiple language support are located in the second post below.
Last edited: