diff --git a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/Character_Add.gd b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/Character_Add.gd index c3cc775..67008c4 100644 --- a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/Character_Add.gd +++ b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/Character_Add.gd @@ -19,7 +19,7 @@ const Cap_New_Button = preload("res://UserInterface/Option.tscn") func _ready() -> void: theme=load(settings.themeFile) - $Title/But_SaveChar.call_deferred("grab_focus") + $Title/But_SaveChar.grab_focus() _populate_output_character_format() #This function is helper function for name dropdown task and should be added in ImportCharacter.gd file to diff --git a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/Character_Add.tscn b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/Character_Add.tscn index 4815a41..051bfa5 100644 --- a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/Character_Add.tscn +++ b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/Character_Add.tscn @@ -23,7 +23,6 @@ margin_left = 215.0 margin_top = 23.0 margin_right = 997.0 margin_bottom = 447.0 -focus_mode = 0 [node name="Title" type="Label" parent="."] anchor_right = 1.0 @@ -68,7 +67,6 @@ margin_left = 370.0 margin_top = 31.0 margin_right = 989.0 margin_bottom = 452.0 -follow_focus = true [node name="VBoxContainer" type="VBoxContainer" parent="Title/ScrollContainer"] diff --git a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/HistoryViewer.gd b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/HistoryViewer.gd index b128ed9..843b361 100644 --- a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/HistoryViewer.gd +++ b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/HistoryViewer.gd @@ -23,8 +23,6 @@ func _ready() -> void: print("Loaded history array size is: " + str(history_source.output_history_array.size())) update_pager() - - $Background/MarginContainer/Rows/ItemList/But_ChangeScene.call_deferred("grab_focus") #DKM TEMP: # page_displayer.text = "1" # if(current_history.get_child_count() > 0): diff --git a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/HistoryViewer.tscn b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/HistoryViewer.tscn index 350ad8a..0c22f55 100644 --- a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/HistoryViewer.tscn +++ b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/HistoryViewer.tscn @@ -2,10 +2,9 @@ [ext_resource path="res://Screens/HistoryViewer.gd" type="Script" id=1] [ext_resource path="res://userInterface/But_ChangeScene.tscn" type="PackedScene" id=2] -[ext_resource path="res://assets/Themes/Dark Theme/ui_controlNode_dark_theme.tres" type="Theme" id=3] +[ext_resource path="res://assets/ui_controlNode_dark_theme.tres" type="Theme" id=3] [ext_resource path="res://Screens/But_HistoryPager.gd" type="Script" id=4] - [node name="HistoryViewer" type="Control"] anchor_right = 1.0 anchor_bottom = 1.0 diff --git a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/ImportCharacter.gd b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/ImportCharacter.gd index ea8330f..4e61008 100644 --- a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/ImportCharacter.gd +++ b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/ImportCharacter.gd @@ -26,8 +26,8 @@ func _ready() -> void: theme=load(settings.themeFile) _populate_output_character_format() #Uncomment this if we want to grab focus on the "Open Character File" option by default - #$VBoxContainer2/But_OpenFile.call_deferred("grab_focus") - $But_Play.call_deferred("grab_focus") #This will grab focus on the "Start Game" option by default + #$VBoxContainer2/But_OpenFile.grab_focus() + $But_Play.grab_focus() #This will grab focus on the "Start Game" option by default func _on_Button_pressed(): $FileDialog.popup() @@ -140,9 +140,8 @@ func _populate_preset_character_format(file:File): # Connect the last LineEdit back to the first button if previous_control != $VBoxContainer2/Save_Button: - #previous_control.focus_next = $VBoxContainer2/But_OpenFile.get_path() - #$VBoxContainer2/But_OpenFile.focus_previous = previous_control.get_path() - previous_control.focus_next = $But_Play.get_path() + previous_control.focus_next = $VBoxContainer2/But_OpenFile.get_path() + $VBoxContainer2/But_OpenFile.focus_previous = previous_control.get_path() #FUNCTION clear the character sheet @@ -164,7 +163,7 @@ func _on_FileDialog_file_selected(path): _populate_preset_character_format(file) file.close() - $VBoxContainer2/But_OpenFile.call_deferred("grab_focus") + $VBoxContainer2/But_OpenFile.grab_focus() #FUNCTION save data to character singleton #Params: None diff --git a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/ImportCharacter.tscn b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/ImportCharacter.tscn index 3dd669c..72dd121 100644 --- a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/ImportCharacter.tscn +++ b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/ImportCharacter.tscn @@ -1,10 +1,9 @@ -[gd_scene load_steps=6 format=2] +[gd_scene load_steps=5 format=2] [ext_resource path="res://Screens/ImportCharacter.gd" type="Script" id=1] [ext_resource path="res://UserInterface/But_PlayButton.gd" type="Script" id=2] [ext_resource path="res://UserInterface/Title.tscn" type="PackedScene" id=3] [ext_resource path="res://UserInterface/But_ChangeScene.tscn" type="PackedScene" id=4] -[ext_resource path="res://UserInterface/FileDialog_Controls.gd" type="Script" id=5] [node name="Control" type="Control"] anchor_right = 1.0 @@ -36,7 +35,6 @@ rect_min_size = Vector2( 400, 140 ) window_title = "Open a File" mode = 0 access = 2 -script = ExtResource( 5 ) __meta__ = { "_edit_use_anchors_": false } diff --git a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/MenuScreen.gd b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/MenuScreen.gd index 83bfa20..42aa2e9 100644 --- a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/MenuScreen.gd +++ b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/MenuScreen.gd @@ -8,5 +8,4 @@ onready var settings = get_node("/root/GlobalSaveInstance").settingsInstance # Called when the node enters the scene tree for the first time. func _ready() -> void: theme=load(settings.themeFile) - GlobalSaveInstance.load_fontSize(theme) - $VBoxContainer/But_NewGame.call_deferred("grab_focus") + $VBoxContainer/But_NewGame.grab_focus() diff --git a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/MenuScreen.tscn b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/MenuScreen.tscn index f7782d0..44de02e 100644 --- a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/MenuScreen.tscn +++ b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/MenuScreen.tscn @@ -4,7 +4,7 @@ [ext_resource path="res://Screens/MenuScreen.gd" type="Script" id=2] [ext_resource path="res://assets/liberation_serif_40pt.tres" type="DynamicFont" id=3] [ext_resource path="res://UserInterface/Title.tscn" type="PackedScene" id=5] -[ext_resource path="res://assets/Themes/Dark Theme/ui_controlNode_dark_theme.tres" type="Theme" id=6] +[ext_resource path="res://assets/ui_controlNode_dark_theme.tres" type="Theme" id=6] [ext_resource path="res://UserInterface/But_Quit.tscn" type="PackedScene" id=10] [node name="MenuScreen" type="Control"] diff --git a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/MenuServerOptions.gd b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/MenuServerOptions.gd index fc2f494..e01947f 100644 --- a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/MenuServerOptions.gd +++ b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/MenuServerOptions.gd @@ -8,4 +8,4 @@ onready var settings = get_node("/root/GlobalSaveInstance").settingsInstance # Called when the node enters the scene tree for the first time. func _ready() -> void: theme=load(settings.themeFile) - $VBoxContainer/But_Multi_Join.call_deferred("grab_focus") + $VBoxContainer/But_Multi_Join.grab_focus() diff --git a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/MenuServerOptions.tscn b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/MenuServerOptions.tscn index 7531000..e26e779 100644 --- a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/MenuServerOptions.tscn +++ b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/MenuServerOptions.tscn @@ -2,8 +2,7 @@ [ext_resource path="res://UserInterface/But_ChangeScene.tscn" type="PackedScene" id=1] [ext_resource path="res://Screens/MenuServerOptions.gd" type="Script" id=2] -[ext_resource path="res://assets/Themes/Dark Theme/ui_controlNode_dark_theme.tres" type="Theme" id=6] - +[ext_resource path="res://assets/ui_controlNode_dark_theme.tres" type="Theme" id=6] [node name="MenuServerOptions" type="Control"] anchor_right = 1.0 diff --git a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/MoreOptions.gd b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/MoreOptions.gd index 20b93c7..95f1032 100644 --- a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/MoreOptions.gd +++ b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/MoreOptions.gd @@ -8,4 +8,4 @@ onready var settings = get_node("/root/GlobalSaveInstance").settingsInstance # Called when the node enters the scene tree for the first time. func _ready() -> void: theme=load(settings.themeFile) - $VBoxContainer/But_ResumeGame.call_deferred("grab_focus") + $VBoxContainer/But_ResumeGame.grab_focus() diff --git a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/MoreOptions.tscn b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/MoreOptions.tscn index 6c19f79..e1494ce 100644 --- a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/MoreOptions.tscn +++ b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/MoreOptions.tscn @@ -3,8 +3,7 @@ [ext_resource path="res://UserInterface/But_ChangeScene.tscn" type="PackedScene" id=1] [ext_resource path="res://UserInterface/But_ResumeGame.gd" type="Script" id=2] [ext_resource path="res://Screens/MoreOptions.gd" type="Script" id=3] -[ext_resource path="res://assets/Themes/Dark Theme/ui_controlNode_dark_theme.tres" type="Theme" id=6] - +[ext_resource path="res://assets/ui_controlNode_dark_theme.tres" type="Theme" id=6] [node name="MoreOptions" type="Control"] anchor_right = 1.0 diff --git a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/PlayerSelection.gd b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/PlayerSelection.gd index 4eca2f9..6aa9b23 100644 --- a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/PlayerSelection.gd +++ b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/PlayerSelection.gd @@ -8,4 +8,4 @@ onready var settings = get_node("/root/GlobalSaveInstance").settingsInstance # Called when the node enters the scene tree for the first time. func _ready() -> void: theme=load(settings.themeFile) - $VBoxContainer/But_ChoosePlayer.call_deferred("grab_focus") + $VBoxContainer/But_ChoosePlayer.grab_focus() diff --git a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/PlayerSelection.tscn b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/PlayerSelection.tscn index 9091428..fa1e992 100644 --- a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/PlayerSelection.tscn +++ b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/PlayerSelection.tscn @@ -2,8 +2,7 @@ [ext_resource path="res://UserInterface/But_ChangeScene.tscn" type="PackedScene" id=1] [ext_resource path="res://Screens/PlayerSelection.gd" type="Script" id=2] -[ext_resource path="res://assets/Themes/Dark Theme/ui_controlNode_dark_theme.tres" type="Theme" id=6] - +[ext_resource path="res://assets/ui_controlNode_dark_theme.tres" type="Theme" id=6] [node name="PlayerSelection" type="Control"] anchor_right = 1.0 diff --git a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/SettingsMenuConfig.gd b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/SettingsMenuConfig.gd index 55340cd..724ebaf 100644 --- a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/SettingsMenuConfig.gd +++ b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/SettingsMenuConfig.gd @@ -7,10 +7,6 @@ extends Control #Allow us to link to the dropdowns on the UI: export (NodePath) var genre_dropdown_path export (NodePath) var game_dropdown_path -export (NodePath) var theme_dropdown_path - -#Allows us to set the directory where themes will be looked for -export var theme_directory_path: String = "res://assets/Themes/" # Items to Fill the dropdown Lists onready var keyboardContents = ["Qwerty", "Dvorak", "Alphabetical"] @@ -21,7 +17,6 @@ onready var saveObject = get_node('/root/GlobalSaveInstance') onready var genre_dropdown = get_node(genre_dropdown_path) onready var game_dropdown = get_node(game_dropdown_path) -onready var theme_dropdown = get_node(theme_dropdown_path) #res://SettingsMenuControl.tscn @@ -32,9 +27,6 @@ onready var GAL = Genre_Layer.new() const Game_Layer := preload("res://globalScripts/GSP_Lookups.gd") onready var GSP = Game_Layer.new() -#Dictionary to store file paths for themes and their corresponding names, will be a 2D array -var themes_names_paths_dict = {} - # Vars For UI Widgets onready var NameVar = get_node('SettingsScroll/HBoxContainer/RootVboxPlayerPreferences/Label/VBoxPlayerPreferances/DisplayNameLineEdit') @@ -75,21 +67,16 @@ func saveToInstance(): var savedKeyboardItems = keyboardLayoutList.get_selected_items() var keyboardSelection = savedKeyboardItems[0] saveObject.settingsInstance.visualKeyboardLayout = keyboardSelection - -# var savedThemeItems = themeChoiceList.get_selected_items() -# var themeSelection = savedThemeItems[0] -# saveObject.settingsInstance.themeChoiceInt = themeSelection -# #DKM TEMP: for web version, setting this to the singleton without requiring reprocess of file -# if(saveObject.settingsInstance.themeChoiceInt == 1): -# saveObject.settingsInstance.themeFile = "res://assets/ui_controlNode_light_theme.tres" -# else: -# saveObject.settingsInstance.themeFile = "res://assets/ui_controlNode_dark_theme.tres" - - print(theme_dropdown.get_selected_id()) - saveObject.settingsInstance.themeFile = themes_names_paths_dict[theme_dropdown.get_item_text(theme_dropdown.get_selected_id())] + var savedThemeItems = themeChoiceList.get_selected_items() + var themeSelection = savedThemeItems[0] + saveObject.settingsInstance.themeChoiceInt = themeSelection + #DKM TEMP: for web version, setting this to the singleton without requiring reprocess of file + if(saveObject.settingsInstance.themeChoiceInt == 1): + saveObject.settingsInstance.themeFile = "res://assets/ui_controlNode_light_theme.tres" + else: + saveObject.settingsInstance.themeFile = "res://assets/ui_controlNode_dark_theme.tres" #Load selected theme: theme=load(saveObject.settingsInstance.themeFile) - #Trigger re-load of the file name #saveObject.load_settings_file() #theme=load(saveObject.settingsInstance.themeFile) @@ -111,12 +98,15 @@ func saveFile(): var keyboardSelection = savedKeyboardItems[0] + var savedThemeItems = themeChoiceList.get_selected_items() + + var themeSelection = savedThemeItems[0] + print(typeof(keyboardSelection)) iniFile.set_value("virtual_keyboard", "keyboard_layout", keyboardSelection) - # save the filepath to the theme we're using - iniFile.set_value("theme", "theme_selection", themes_names_paths_dict[theme_dropdown.get_item_text(theme_dropdown.get_selected_id())]) + iniFile.set_value("theme", "theme_selection", themeSelection) iniFile.set_value("player_preferences", "genre_selection", saveObject.settingsInstance.genre_options[genre_dropdown.get_selected_id()]) iniFile.set_value("player_preferences", "game_selection", saveObject.settingsInstance.game_options[game_dropdown.get_selected_id()]) @@ -162,86 +152,13 @@ func add_game_options(): if(game != "OPEND6_FANTASY"): saveObject.settingsInstance.game_options.append(game) game_dropdown.add_item(str(game).to_lower()) - -#FUNCTION: Add Theme Options (to dropdown and dictionary) -#PARAMS: None -#Returns: None -#Notes: loads themes from theme_directory_path, themes_names_paths_dict is edited -func add_theme_options(): - var themeChoices = get_theme_paths_recursive(theme_directory_path) - for theme_path in themeChoices: - var theme_name = get_theme_name(theme_path) - theme_dropdown.add_item(theme_name) - themes_names_paths_dict[theme_name] = theme_path - -#FUNCTION: Get Theme Paths Recursive -#PARAMS: None -#Returns: array of valid theme paths from theme_directory_path and subdirectories -#Notes: -func get_theme_paths_recursive(directory_path) -> Array: - var to_return_array = [] - var directory = Directory.new() - # open() can return OK, FAILED, or ERR_... - if directory.open(directory_path) == OK: - # start a stream to list files and directories - directory.list_dir_begin(true, true) # "true" leaves out . and .. directories and hidden files - var file_name = directory.get_next() - var file_path = directory_path + file_name - print(file_path) - # I don't know if this is the correct way to check for file existence - # in an ideal world, this finds bundled resources, but I genuinely have no idea if this is the right way to do that - while file_name != "": - # check if the file is actually a directory - if directory.current_is_dir(): - file_path = file_path + "/" - to_return_array.append_array(get_theme_paths_recursive(file_path)) - elif ResourceLoader.exists(file_path) || directory.file_exists(file_path): - # make sure the file is a theme file - # check for the text "gd_resource type=\"Theme\"" - # this should be more efficient than loading the whole resource, then checking its type? - var file = File.new() - file.open(file_path, File.READ) - var file_first_line = file.get_line() - if file_first_line.find("gd_resource type=\"Theme\"") != -1: - #file is a theme file - to_return_array.append(file_path) - file_name = directory.get_next() - file_path = directory_path + file_name - directory.list_dir_end() - return to_return_array - else: - return [] - -#FUNCTION: Get Theme Name -#PARAMS: path to theme -#Returns: name of theme resource or theme's filename if theme has no name -#Notes: -func get_theme_name(theme_path) -> String: - var regex = RegEx.new() - regex.compile("resource_name = \"(.*)\"") - - var theme_file = File.new() - theme_file.open(theme_path, File.READ) - var file_text = theme_file.get_as_text() - # get the first capture group from the regex as the name - var regex_result = regex.search(file_text) - if regex_result != null: - # if the theme has a name - var theme_name = regex_result.get_string(1) - return theme_name - - regex.compile(".*\/(.*$)") - return regex.search(theme_path).get_string(1) - func _ready(): #Get our initial genre options for dropdown: add_genre_options() #Get our initial game system options for dropdown: add_game_options() - #Get theme options for dropdown: - add_theme_options() #Get the singleton's values for initial settings: NameVar.text = saveObject.settingsInstance.inputName @@ -254,14 +171,6 @@ func _ready(): #genre_dropdown.select(saveObject.settingsInstance.genre_selection) genre_dropdown.select(saveObject.settingsInstance.genre_options.find(saveObject.settingsInstance.genre_selection)) game_dropdown.select(saveObject.settingsInstance.game_options.find(saveObject.settingsInstance.game_selection)) - - #loop through the theme dropdown ooptions until we find the one that matches the name of the saved theme and select it - for i in range(theme_dropdown.get_item_count()): - #print("theme dropdown i = " + str(i)) - #print("theme dropdown text = " + theme_dropdown.get_item_text(i)) - if theme_dropdown.get_item_text(i) == get_theme_name(saveObject.settingsInstance.themeFile): - theme_dropdown.select(i) - break print(NameVar.get_path()) @@ -271,9 +180,14 @@ func _ready(): keyboardLayoutList.select(0,true) +# Init Theme Choice List + + for i in range(2): + themeChoiceList.add_item(themeContents[i],null,true) + keyboardLayoutList.select(saveObject.settingsInstance.visualKeyboardLayout,true) + themeChoiceList.select(saveObject.settingsInstance.themeChoiceInt,true) + #Load selected theme: theme=load(saveObject.settingsInstance.themeFile) - - $HBoxBottomRow/But_ChangeScene.call_deferred("grab_focus") diff --git a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/SettingsMenuControl.tscn b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/SettingsMenuControl.tscn index c41068f..48461e6 100644 --- a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/SettingsMenuControl.tscn +++ b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/SettingsMenuControl.tscn @@ -1,11 +1,8 @@ -[gd_scene load_steps=8 format=2] +[gd_scene load_steps=5 format=2] [ext_resource path="res://Screens/SettingsMenuConfig.gd" type="Script" id=1] [ext_resource path="res://assets/liberation_serif.tres" type="DynamicFont" id=2] [ext_resource path="res://UserInterface/But_ChangeScene.gd" type="Script" id=3] -[ext_resource path="res://UserInterface/Slider_Controls.gd" type="Script" id=4] -[ext_resource path="res://UserInterface/ItemList_Controls.gd" type="Script" id=5] -[ext_resource path="res://UserInterface/OptionBut_Controls.gd" type="Script" id=6] [sub_resource type="Theme" id=1] default_font = ExtResource( 2 ) @@ -17,7 +14,6 @@ theme = SubResource( 1 ) script = ExtResource( 1 ) genre_dropdown_path = NodePath("SettingsScroll/HBoxContainer/RootVboxPlayerPreferences/Label/VBoxPlayerPreferances/VBoxContainer/OptionBut_Genre") game_dropdown_path = NodePath("SettingsScroll/HBoxContainer/RootVboxPlayerPreferences/Label/VBoxPlayerPreferances/VBoxContainer/OptionBut_Game") -theme_dropdown_path = NodePath("SettingsScroll/HBoxContainer/RootVboxVisualControls2/Label2/VBoxContainer/OptionBut_Theme") [node name="Panel" type="Panel" parent="."] anchor_right = 1.0 @@ -97,7 +93,6 @@ value = 5.0 rounded = true tick_count = 10 ticks_on_borders = true -script = ExtResource( 4 ) [node name="BrightnessLabel" type="Label" parent="SettingsScroll/HBoxContainer/RootVboxVisualControls/VisualControlsLabel/VisualControlsVBox"] margin_top = 43.0 @@ -115,7 +110,6 @@ value = 5.0 rounded = true tick_count = 10 ticks_on_borders = true -script = ExtResource( 4 ) [node name="RootVboxPlayerPreferences" type="VBoxContainer" parent="SettingsScroll/HBoxContainer"] margin_left = 368.0 @@ -174,7 +168,6 @@ value = 5.0 rounded = true tick_count = 10 ticks_on_borders = true -script = ExtResource( 4 ) [node name="VBoxContainer" type="VBoxContainer" parent="SettingsScroll/HBoxContainer/RootVboxPlayerPreferences/Label/VBoxPlayerPreferances"] margin_top = 99.0 @@ -190,7 +183,6 @@ text = "Genre Selection:" margin_top = 23.0 margin_right = 145.0 margin_bottom = 48.0 -script = ExtResource( 6 ) [node name="LabelGS" type="Label" parent="SettingsScroll/HBoxContainer/RootVboxPlayerPreferences/Label/VBoxPlayerPreferances/VBoxContainer"] margin_top = 52.0 @@ -202,7 +194,6 @@ text = "Game System:" margin_top = 75.0 margin_right = 145.0 margin_bottom = 100.0 -script = ExtResource( 6 ) [node name="RootVboxGeneralSettings" type="VBoxContainer" parent="SettingsScroll/HBoxContainer"] margin_left = 545.0 @@ -239,7 +230,6 @@ max_value = 10.0 rounded = true tick_count = 10 ticks_on_borders = true -script = ExtResource( 4 ) [node name="HBoxClosedCaptions" type="HBoxContainer" parent="SettingsScroll/HBoxContainer/RootVboxGeneralSettings/GeneralSettingsLabel/VBoxContainer"] margin_top = 43.0 @@ -309,16 +299,10 @@ margin_right = 155.0 margin_bottom = 32.0 auto_height = true -[node name="OptionBut_Theme" type="OptionButton" parent="SettingsScroll/HBoxContainer/RootVboxVisualControls2/Label2/VBoxContainer"] -margin_top = 36.0 -margin_right = 155.0 -margin_bottom = 61.0 -script = ExtResource( 6 ) - [node name="HBoxVirtualKeyboardEnabled" type="HBoxContainer" parent="SettingsScroll/HBoxContainer/RootVboxVisualControls2/Label2/VBoxContainer"] -margin_top = 65.0 +margin_top = 36.0 margin_right = 155.0 -margin_bottom = 92.0 +margin_bottom = 63.0 [node name="VisualKeyBoardLabel" type="Label" parent="SettingsScroll/HBoxContainer/RootVboxVisualControls2/Label2/VBoxContainer/HBoxVirtualKeyboardEnabled"] margin_top = 4.0 @@ -332,9 +316,9 @@ margin_right = 138.0 margin_bottom = 27.0 [node name="HBoxKeyboardLayout" type="HBoxContainer" parent="SettingsScroll/HBoxContainer/RootVboxVisualControls2/Label2/VBoxContainer"] -margin_top = 96.0 +margin_top = 67.0 margin_right = 155.0 -margin_bottom = 115.0 +margin_bottom = 86.0 [node name="LayoutLabel" type="Label" parent="SettingsScroll/HBoxContainer/RootVboxVisualControls2/Label2/VBoxContainer/HBoxKeyboardLayout"] margin_right = 120.0 @@ -342,10 +326,9 @@ margin_bottom = 19.0 text = "Layout Preference:" [node name="LayoutItemList" type="ItemList" parent="SettingsScroll/HBoxContainer/RootVboxVisualControls2/Label2/VBoxContainer"] -margin_top = 119.0 +margin_top = 90.0 margin_right = 155.0 -margin_bottom = 128.0 +margin_bottom = 99.0 auto_height = true -script = ExtResource( 5 ) [connection signal="button_up" from="HBoxBottomRow/But_ChangeScene" to="HBoxBottomRow/But_ChangeScene" method="_on_But_NewGame_button_up"] diff --git a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/grabFocus.gd b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/grabFocus.gd index 12187fc..f3dcd9e 100644 --- a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/grabFocus.gd +++ b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/Screens/grabFocus.gd @@ -4,4 +4,4 @@ extends Control func _ready() -> void: - $Title/But_ChangeScene.call_deferred("grab_focus") + $Title/But_ChangeScene.grab_focus() diff --git a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/UserInterface/But_ResumeGame.gd b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/UserInterface/But_ResumeGame.gd index 948c31f..ee37c4f 100644 --- a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/UserInterface/But_ResumeGame.gd +++ b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/UserInterface/But_ResumeGame.gd @@ -11,4 +11,4 @@ func _on_But_ResumeGame_button_up(): #DKM TEMP: cleanup this scene! thisScene.queue_free() root.add_child(gameScene) - gameScene.get_node("Background/MarginContainer/Rows/ItemList/But_MoreOptions").call_deferred("grab_focus") + diff --git a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/_toArchive/ui_controlNode_dark_theme.tres b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/_toArchive/ui_controlNode_dark_theme.tres index 1aaa5a7..b606d40 100644 --- a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/_toArchive/ui_controlNode_dark_theme.tres +++ b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/_toArchive/ui_controlNode_dark_theme.tres @@ -1,6 +1,6 @@ [gd_resource type="Theme" load_steps=3 format=2] -[ext_resource path="res://assets/Themes/Dark Theme/sbf_black.tres" type="StyleBox" id=1] +[ext_resource path="res://assets/sbf_black.tres" type="StyleBox" id=1] [ext_resource path="res://assets/liberation_serif_30pt.tres" type="DynamicFont" id=2] [resource] diff --git a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/_userFiles/Module_Demo_003_Loc.xml b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/_userFiles/Module_Demo_003_Loc.xml index fd25b3c..ce93167 100644 --- a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/_userFiles/Module_Demo_003_Loc.xml +++ b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/_userFiles/Module_Demo_003_Loc.xml @@ -37,6 +37,7 @@ Travel to the Forgotten Realms Try to lift a heavy weight! (Strength check test.) Examine the hold more closely? (Intuition check test.) + Start extended conflict (combat test) Boat_002 Shore_001 Misc_001 @@ -45,7 +46,8 @@ Test_000 Test_001 Test_002 - Test_003 + Test_003 + Test_004 Boat_002 @@ -55,7 +57,6 @@ Continue Boat_001 - Boat_003 ShowText @@ -135,7 +136,15 @@ A peg on the wall twists in a way you didn't expect... Boat_003 - + + Test_004 + StartExtendedConflict + Bandit + NA + NA + Boat_001 + + Tempestuous Seas A test location away from the island; rampant with sea monsters and storms! diff --git a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/_userFiles/PlayerPreferences.cfg b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/_userFiles/PlayerPreferences.cfg index c0ab220..6ae9d5a 100644 --- a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/_userFiles/PlayerPreferences.cfg +++ b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/_userFiles/PlayerPreferences.cfg @@ -3,7 +3,7 @@ player_name="Tester the Wary!" risk_threshold=2.0 genre_selection="FANTASY" -game_selection="OPEND6_FANTASY" +game_selection="BCIRPG_PERCENTILE" [visual_controls] @@ -22,4 +22,4 @@ keyboard_layout=2 [theme] -theme_selection="res://assets/Themes/Dark Theme/ui_controlNode_dark_theme.tres" +theme_selection=0 diff --git a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/_userFiles/game_01.tscn b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/_userFiles/game_01.tscn index 4f977ea..747c299 100644 --- a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/_userFiles/game_01.tscn +++ b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/_userFiles/game_01.tscn @@ -1,17 +1,16 @@ [gd_scene load_steps=6 format=2] -[ext_resource path="res://gamePlay/But_Option.tscn" type="PackedScene" id=1] -[ext_resource path="res://assets/liberation_serif_30pt.tres" type="DynamicFont" id=2] -[ext_resource path="res://assets/Themes/ui_controlNode_dark_theme.tres" type="Theme" id=3] -[ext_resource path="res://gamePlay/But_MoreOptions.gd" type="Script" id=4] -[ext_resource path="res://gamePlay/Game.gd" type="Script" id=5] - +[ext_resource path="res://assets/liberation_serif_30pt.tres" type="DynamicFont" id=1] +[ext_resource path="res://assets/ui_controlNode_dark_theme.tres" type="Theme" id=2] +[ext_resource path="res://gamePlay/But_Option.tscn" type="PackedScene" id=3] +[ext_resource path="res://gamePlay/Game.gd" type="Script" id=4] +[ext_resource path="res://gamePlay/But_MoreOptions.gd" type="Script" id=5] [node name="Game" type="Control"] anchor_right = 1.0 anchor_bottom = 1.0 -theme = ExtResource( 3 ) -script = ExtResource( 5 ) +theme = ExtResource( 2 ) +script = ExtResource( 4 ) [node name="Background" type="PanelContainer" parent="."] anchor_right = 1.0 @@ -42,12 +41,13 @@ custom_constants/separation = 10 margin_right = 708.0 margin_bottom = 40.0 rect_min_size = Vector2( 0, 40 ) +focus_mode = 0 [node name="But_MoreOptions" type="Button" parent="Background/MarginContainer/Rows/ItemList"] margin_right = 197.0 margin_bottom = 36.0 text = "More Options" -script = ExtResource( 4 ) +script = ExtResource( 5 ) __meta__ = { "_edit_use_anchors_": false } @@ -79,16 +79,17 @@ margin_left = 1.0 margin_top = 1.0 margin_right = 707.0 margin_bottom = 119.0 +follow_focus = true [node name="OptionsContainer" type="VBoxContainer" parent="Background/MarginContainer/Rows/InputArea/ScrollContainer"] margin_right = 108.0 margin_bottom = 36.0 custom_constants/separation = 5 -[node name="option1" type="Button" parent="Background/MarginContainer/Rows/InputArea/ScrollContainer/OptionsContainer" instance=ExtResource( 1 )] +[node name="option1" type="Button" parent="Background/MarginContainer/Rows/InputArea/ScrollContainer/OptionsContainer" instance=ExtResource( 3 )] margin_right = 108.0 margin_bottom = 36.0 -custom_fonts/font = ExtResource( 2 ) +custom_fonts/font = ExtResource( 1 ) text = "Option 1" align = 0 __meta__ = { @@ -100,9 +101,6 @@ anchor_left = 1.0 anchor_right = 1.0 margin_left = -294.0 margin_bottom = 406.0 -__meta__ = { -"_edit_use_anchors_": false -} [node name="MarginContainer" type="MarginContainer" parent="Con_charSheet"] margin_left = 1.0 @@ -118,6 +116,7 @@ margin_bottom = 404.0 margin_right = 292.0 margin_bottom = 40.0 rect_min_size = Vector2( 0, 40 ) +focus_mode = 0 __meta__ = { "_edit_use_anchors_": false } @@ -131,14 +130,12 @@ margin_bottom = 43.0 text = "Character Sheet" align = 1 valign = 1 -__meta__ = { -"_edit_use_anchors_": false -} [node name="CharacterSheet" type="TextEdit" parent="Con_charSheet/MarginContainer/VBoxContainer"] margin_top = 44.0 margin_right = 292.0 margin_bottom = 404.0 +focus_mode = 0 size_flags_vertical = 3 readonly = true wrap_enabled = true @@ -169,6 +166,7 @@ size_flags_vertical = 3 margin_right = 290.0 margin_bottom = 40.0 rect_min_size = Vector2( 0, 40 ) +focus_mode = 0 __meta__ = { "_edit_use_anchors_": false } @@ -190,6 +188,7 @@ __meta__ = { margin_top = 44.0 margin_right = 290.0 margin_bottom = 194.0 +focus_mode = 0 size_flags_vertical = 3 text = "Nothing yet " diff --git a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/assets/sbf_black.tres b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/assets/sbf_black.tres new file mode 100644 index 0000000..859abe4 --- /dev/null +++ b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/assets/sbf_black.tres @@ -0,0 +1,9 @@ +[gd_resource type="StyleBoxFlat" format=2] + +[resource] +bg_color = Color( 0, 0, 0, 1 ) +border_width_left = 1 +border_width_top = 1 +border_width_right = 1 +border_width_bottom = 1 +border_color = Color( 0, 0, 0, 1 ) diff --git a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/assets/sbf_white.tres b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/assets/sbf_white.tres new file mode 100644 index 0000000..418e195 --- /dev/null +++ b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/assets/sbf_white.tres @@ -0,0 +1,9 @@ +[gd_resource type="StyleBoxFlat" format=2] + +[resource] +bg_color = Color( 1, 1, 1, 1 ) +border_width_left = 1 +border_width_top = 1 +border_width_right = 1 +border_width_bottom = 1 +border_color = Color( 1, 1, 1, 1 ) diff --git a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/assets/ui_controlNode_dark_theme.tres b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/assets/ui_controlNode_dark_theme.tres new file mode 100644 index 0000000..38a6ae1 --- /dev/null +++ b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/assets/ui_controlNode_dark_theme.tres @@ -0,0 +1,120 @@ +[gd_resource type="Theme" load_steps=5 format=2] + +[ext_resource path="res://assets/sbf_black.tres" type="StyleBox" id=1] +[ext_resource path="res://assets/liberation_serif_30pt.tres" type="DynamicFont" id=2] +[ext_resource path="res://assets/liberation_serif_20pt.tres" type="DynamicFont" id=3] +[ext_resource path="res://assets/liberation_serif.tres" type="DynamicFont" id=4] + +[resource] +Button/colors/font_color = Color( 1, 1, 1, 1 ) +Button/colors/font_color_disabled = Color( 0.9, 0.9, 0.9, 0.2 ) +Button/colors/font_color_hover = Color( 0.94, 0.94, 0.94, 1 ) +Button/colors/font_color_pressed = Color( 1, 1, 1, 1 ) +Button/constants/hseparation = 2 +Button/fonts/font = ExtResource( 2 ) +Button/styles/disabled = null +Button/styles/focus = null +Button/styles/hover = null +Button/styles/normal = ExtResource( 1 ) +Button/styles/pressed = ExtResource( 1 ) +ItemList/colors/font_color = Color( 1, 1, 1, 1 ) +ItemList/colors/font_color_selected = Color( 1, 1, 1, 1 ) +ItemList/colors/guide_color = Color( 0, 0, 0, 0.1 ) +ItemList/constants/hseparation = 4 +ItemList/constants/icon_margin = 4 +ItemList/constants/line_separation = 2 +ItemList/constants/vseparation = 2 +ItemList/fonts/font = ExtResource( 3 ) +ItemList/styles/bg = ExtResource( 1 ) +ItemList/styles/bg_focus = ExtResource( 1 ) +ItemList/styles/cursor = null +ItemList/styles/cursor_unfocused = ExtResource( 1 ) +ItemList/styles/selected = null +ItemList/styles/selected_focus = null +Label/colors/font_color = Color( 1, 1, 1, 1 ) +Label/colors/font_color_shadow = Color( 0, 0, 0, 0 ) +Label/colors/font_outline_modulate = Color( 1, 1, 1, 1 ) +Label/constants/line_spacing = 3 +Label/constants/shadow_as_outline = 0 +Label/constants/shadow_offset_x = 1 +Label/constants/shadow_offset_y = 1 +Label/fonts/font = ExtResource( 3 ) +Label/styles/normal = ExtResource( 1 ) +LineEdit/colors/clear_button_color = Color( 0.88, 0.88, 0.88, 1 ) +LineEdit/colors/clear_button_color_pressed = Color( 1, 1, 1, 1 ) +LineEdit/colors/cursor_color = Color( 0.94, 0.94, 0.94, 1 ) +LineEdit/colors/font_color = Color( 1, 1, 1, 1 ) +LineEdit/colors/font_color_selected = Color( 1, 1, 1, 1 ) +LineEdit/colors/font_color_uneditable = Color( 0.88, 0.88, 0.88, 0.5 ) +LineEdit/colors/selection_color = Color( 0.49, 0.49, 0.49, 1 ) +LineEdit/constants/minimum_spaces = 12 +LineEdit/fonts/font = null +LineEdit/icons/clear = null +LineEdit/styles/focus = null +LineEdit/styles/normal = ExtResource( 1 ) +LineEdit/styles/read_only = null +MarginContainer/constants/margin_bottom = 0 +MarginContainer/constants/margin_left = 0 +MarginContainer/constants/margin_right = 0 +MarginContainer/constants/margin_top = 0 +Panel/styles/panel = ExtResource( 1 ) +PanelContainer/styles/panel = ExtResource( 1 ) +Tabs/colors/font_color_bg = Color( 1, 1, 1, 1 ) +Tabs/colors/font_color_disabled = Color( 0.9, 0.9, 0.9, 0.2 ) +Tabs/colors/font_color_fg = Color( 1, 1, 1, 1 ) +Tabs/constants/hseparation = 4 +Tabs/constants/label_valign_bg = 2 +Tabs/constants/label_valign_fg = 0 +Tabs/constants/top_margin = 24 +Tabs/fonts/font = ExtResource( 3 ) +Tabs/icons/close = null +Tabs/icons/decrement = null +Tabs/icons/decrement_highlight = null +Tabs/icons/increment = null +Tabs/icons/increment_highlight = null +Tabs/styles/button = ExtResource( 1 ) +Tabs/styles/button_pressed = null +Tabs/styles/panel = ExtResource( 1 ) +Tabs/styles/tab_bg = ExtResource( 1 ) +Tabs/styles/tab_disabled = null +Tabs/styles/tab_fg = ExtResource( 1 ) +TextEdit/colors/background_color = Color( 1, 1, 1, 1 ) +TextEdit/colors/bookmark_color = Color( 0.08, 0.49, 0.98, 1 ) +TextEdit/colors/brace_mismatch_color = Color( 1, 0.2, 0.2, 1 ) +TextEdit/colors/breakpoint_color = Color( 0.8, 0.8, 0.4, 0.2 ) +TextEdit/colors/caret_background_color = Color( 0, 0, 0, 1 ) +TextEdit/colors/caret_color = Color( 0.88, 0.88, 0.88, 1 ) +TextEdit/colors/code_folding_color = Color( 0.8, 0.8, 0.8, 0.8 ) +TextEdit/colors/completion_background_color = Color( 0.17, 0.16, 0.2, 1 ) +TextEdit/colors/completion_existing_color = Color( 0.87, 0.87, 0.87, 0.13 ) +TextEdit/colors/completion_font_color = Color( 0.67, 0.67, 0.67, 1 ) +TextEdit/colors/completion_scroll_color = Color( 1, 1, 1, 1 ) +TextEdit/colors/completion_selected_color = Color( 0.26, 0.26, 0.27, 1 ) +TextEdit/colors/current_line_color = Color( 0.25, 0.25, 0.26, 0.8 ) +TextEdit/colors/executing_line_color = Color( 0.2, 0.8, 0.2, 0.4 ) +TextEdit/colors/font_color = Color( 1, 1, 1, 1 ) +TextEdit/colors/font_color_readonly = Color( 0.933333, 0.933333, 0.933333, 0.501961 ) +TextEdit/colors/font_color_selected = Color( 1, 1, 1, 1 ) +TextEdit/colors/function_color = Color( 0.4, 0.64, 0.81, 1 ) +TextEdit/colors/line_number_color = Color( 0.67, 0.67, 0.67, 0.4 ) +TextEdit/colors/mark_color = Color( 1, 0.4, 0.4, 0.4 ) +TextEdit/colors/member_variable_color = Color( 0.9, 0.31, 0.35, 1 ) +TextEdit/colors/number_color = Color( 0.92, 0.58, 0.2, 1 ) +TextEdit/colors/safe_line_number_color = Color( 0.67, 0.78, 0.67, 0.6 ) +TextEdit/colors/selection_color = Color( 0.49, 0.49, 0.49, 1 ) +TextEdit/colors/symbol_color = Color( 0.94, 0.94, 0.94, 1 ) +TextEdit/colors/word_highlighted_color = Color( 0.8, 0.9, 0.9, 0.15 ) +TextEdit/constants/completion_lines = 7 +TextEdit/constants/completion_max_width = 50 +TextEdit/constants/completion_scroll_width = 3 +TextEdit/constants/line_spacing = 4 +TextEdit/fonts/font = ExtResource( 4 ) +TextEdit/icons/fold = null +TextEdit/icons/folded = null +TextEdit/icons/space = null +TextEdit/icons/tab = null +TextEdit/styles/completion = ExtResource( 1 ) +TextEdit/styles/focus = ExtResource( 1 ) +TextEdit/styles/normal = ExtResource( 1 ) +TextEdit/styles/read_only = ExtResource( 1 ) +VBoxContainer/constants/separation = 4 diff --git a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/assets/ui_controlNode_light_theme.tres b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/assets/ui_controlNode_light_theme.tres new file mode 100644 index 0000000..7fcfd40 --- /dev/null +++ b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/assets/ui_controlNode_light_theme.tres @@ -0,0 +1,120 @@ +[gd_resource type="Theme" load_steps=5 format=2] + +[ext_resource path="res://assets/sbf_white.tres" type="StyleBox" id=1] +[ext_resource path="res://assets/liberation_serif_30pt.tres" type="DynamicFont" id=2] +[ext_resource path="res://assets/liberation_serif_20pt.tres" type="DynamicFont" id=3] +[ext_resource path="res://assets/liberation_serif.tres" type="DynamicFont" id=4] + +[resource] +Button/colors/font_color = Color( 0, 0, 0, 1 ) +Button/colors/font_color_disabled = Color( 0.9, 0.9, 0.9, 0.2 ) +Button/colors/font_color_hover = Color( 0.94, 0.94, 0.94, 1 ) +Button/colors/font_color_pressed = Color( 1, 1, 1, 1 ) +Button/constants/hseparation = 2 +Button/fonts/font = ExtResource( 2 ) +Button/styles/disabled = null +Button/styles/focus = null +Button/styles/hover = null +Button/styles/normal = ExtResource( 1 ) +Button/styles/pressed = ExtResource( 1 ) +ItemList/colors/font_color = Color( 0, 0, 0, 1 ) +ItemList/colors/font_color_selected = Color( 1, 1, 1, 1 ) +ItemList/colors/guide_color = Color( 0, 0, 0, 0.1 ) +ItemList/constants/hseparation = 4 +ItemList/constants/icon_margin = 4 +ItemList/constants/line_separation = 2 +ItemList/constants/vseparation = 2 +ItemList/fonts/font = null +ItemList/styles/bg = ExtResource( 1 ) +ItemList/styles/bg_focus = ExtResource( 1 ) +ItemList/styles/cursor = null +ItemList/styles/cursor_unfocused = ExtResource( 1 ) +ItemList/styles/selected = null +ItemList/styles/selected_focus = null +Label/colors/font_color = Color( 0, 0, 0, 1 ) +Label/colors/font_color_shadow = Color( 0, 0, 0, 0 ) +Label/colors/font_outline_modulate = Color( 1, 1, 1, 1 ) +Label/constants/line_spacing = 3 +Label/constants/shadow_as_outline = 0 +Label/constants/shadow_offset_x = 1 +Label/constants/shadow_offset_y = 1 +Label/fonts/font = ExtResource( 3 ) +Label/styles/normal = ExtResource( 1 ) +LineEdit/colors/clear_button_color = Color( 0.88, 0.88, 0.88, 1 ) +LineEdit/colors/clear_button_color_pressed = Color( 1, 1, 1, 1 ) +LineEdit/colors/cursor_color = Color( 0.94, 0.94, 0.94, 1 ) +LineEdit/colors/font_color = Color( 0, 0, 0, 1 ) +LineEdit/colors/font_color_selected = Color( 0, 0, 0, 1 ) +LineEdit/colors/font_color_uneditable = Color( 0.88, 0.88, 0.88, 0.5 ) +LineEdit/colors/selection_color = Color( 0.49, 0.49, 0.49, 1 ) +LineEdit/constants/minimum_spaces = 12 +LineEdit/fonts/font = null +LineEdit/icons/clear = null +LineEdit/styles/focus = null +LineEdit/styles/normal = ExtResource( 1 ) +LineEdit/styles/read_only = null +MarginContainer/constants/margin_bottom = 0 +MarginContainer/constants/margin_left = 0 +MarginContainer/constants/margin_right = 0 +MarginContainer/constants/margin_top = 0 +Panel/styles/panel = ExtResource( 1 ) +PanelContainer/styles/panel = ExtResource( 1 ) +Tabs/colors/font_color_bg = Color( 0, 0, 0, 1 ) +Tabs/colors/font_color_disabled = Color( 0.9, 0.9, 0.9, 0.2 ) +Tabs/colors/font_color_fg = Color( 0, 0, 0, 1 ) +Tabs/constants/hseparation = 4 +Tabs/constants/label_valign_bg = 2 +Tabs/constants/label_valign_fg = 0 +Tabs/constants/top_margin = 24 +Tabs/fonts/font = ExtResource( 3 ) +Tabs/icons/close = null +Tabs/icons/decrement = null +Tabs/icons/decrement_highlight = null +Tabs/icons/increment = null +Tabs/icons/increment_highlight = null +Tabs/styles/button = ExtResource( 1 ) +Tabs/styles/button_pressed = null +Tabs/styles/panel = ExtResource( 1 ) +Tabs/styles/tab_bg = ExtResource( 1 ) +Tabs/styles/tab_disabled = null +Tabs/styles/tab_fg = ExtResource( 1 ) +TextEdit/colors/background_color = Color( 1, 1, 1, 1 ) +TextEdit/colors/bookmark_color = Color( 0.08, 0.49, 0.98, 1 ) +TextEdit/colors/brace_mismatch_color = Color( 1, 0.2, 0.2, 1 ) +TextEdit/colors/breakpoint_color = Color( 0.8, 0.8, 0.4, 0.2 ) +TextEdit/colors/caret_background_color = Color( 0, 0, 0, 1 ) +TextEdit/colors/caret_color = Color( 0.88, 0.88, 0.88, 1 ) +TextEdit/colors/code_folding_color = Color( 0.8, 0.8, 0.8, 0.8 ) +TextEdit/colors/completion_background_color = Color( 0.17, 0.16, 0.2, 1 ) +TextEdit/colors/completion_existing_color = Color( 0.87, 0.87, 0.87, 0.13 ) +TextEdit/colors/completion_font_color = Color( 0.67, 0.67, 0.67, 1 ) +TextEdit/colors/completion_scroll_color = Color( 1, 1, 1, 1 ) +TextEdit/colors/completion_selected_color = Color( 0.26, 0.26, 0.27, 1 ) +TextEdit/colors/current_line_color = Color( 0.25, 0.25, 0.26, 0.8 ) +TextEdit/colors/executing_line_color = Color( 0.2, 0.8, 0.2, 0.4 ) +TextEdit/colors/font_color = Color( 0.00392157, 0.00392157, 0.00392157, 1 ) +TextEdit/colors/font_color_readonly = Color( 0.0588235, 0.0588235, 0.0588235, 0.501961 ) +TextEdit/colors/font_color_selected = Color( 0, 0, 0, 1 ) +TextEdit/colors/function_color = Color( 0.4, 0.64, 0.81, 1 ) +TextEdit/colors/line_number_color = Color( 0.67, 0.67, 0.67, 0.4 ) +TextEdit/colors/mark_color = Color( 1, 0.4, 0.4, 0.4 ) +TextEdit/colors/member_variable_color = Color( 0.9, 0.31, 0.35, 1 ) +TextEdit/colors/number_color = Color( 0.92, 0.58, 0.2, 1 ) +TextEdit/colors/safe_line_number_color = Color( 0.67, 0.78, 0.67, 0.6 ) +TextEdit/colors/selection_color = Color( 0.49, 0.49, 0.49, 1 ) +TextEdit/colors/symbol_color = Color( 0.94, 0.94, 0.94, 1 ) +TextEdit/colors/word_highlighted_color = Color( 0.8, 0.9, 0.9, 0.15 ) +TextEdit/constants/completion_lines = 7 +TextEdit/constants/completion_max_width = 50 +TextEdit/constants/completion_scroll_width = 3 +TextEdit/constants/line_spacing = 4 +TextEdit/fonts/font = ExtResource( 4 ) +TextEdit/icons/fold = null +TextEdit/icons/folded = null +TextEdit/icons/space = null +TextEdit/icons/tab = null +TextEdit/styles/completion = ExtResource( 1 ) +TextEdit/styles/focus = ExtResource( 1 ) +TextEdit/styles/normal = ExtResource( 1 ) +TextEdit/styles/read_only = ExtResource( 1 ) +VBoxContainer/constants/separation = 4 diff --git a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/gamePlay/Game.gd b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/gamePlay/Game.gd index 7f7368c..8e68bd8 100644 --- a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/gamePlay/Game.gd +++ b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/gamePlay/Game.gd @@ -30,6 +30,11 @@ onready var options_container = $Background/MarginContainer/Rows/InputArea/Scrol onready var pSingleton = get_node("/root/PlayerCharacter") onready var charSheet = $Con_charSheet/MarginContainer/VBoxContainer/CharacterSheet +# --- Conflict / Turn system (d20) --- +var conflict_state = null # Dictionary state machine or null +var conflict_return_node = "" # where to go back after conflict ends +onready var ConflictMgr = preload("res://globalScripts/ConflictManagerD20.gd").new() + #Ability_Checker are used as passed by module and return Check_Results const Ability_Checker_Source := preload("res://globalScripts/game_abilitychecks.gd") onready var Ability_Checker = Ability_Checker_Source.new() @@ -51,7 +56,6 @@ var regionsArray func _ready() -> void: save_module() theme=load(settings.themeFile) - GlobalSaveInstance.load_fontSize(theme) #Sets a default button to grab focus #Node Builders should override this by setting the focused button to the first selectable option @@ -220,10 +224,10 @@ func loadGameNode(parser:XMLParser)->Locale: match child_node_name: "ID": parser.read() - if parser.get_node_type() == XMLParser.NODE_TEXT: + if parser.get_node_type() == XMLParser.NODE_TEXT: var id_node_data = parser.get_node_data() - #print("Found Id named: " + id_node_data) spaceNode.locale_name = id_node_data.strip_edges(true,true) + print("LOADED SPACE:", spaceNode.locale_name) "START": parser.read() if (parser.get_node_type() == XMLParser.NODE_TEXT) && (parser.get_node_data().strip_edges(true,true).to_upper() == "TRUE"): @@ -231,10 +235,10 @@ func loadGameNode(parser:XMLParser)->Locale: spaceNode.is_starting_locale = true "ACTION": parser.read() - if parser.get_node_type() == XMLParser.NODE_TEXT: + if parser.get_node_type() == XMLParser.NODE_TEXT: var action_node_data = parser.get_node_data() - #print("Found Action named: " + action_node_data) - spaceNode.locale_action = action_node_data.strip_edges(true,true) + spaceNode.locale_action = action_node_data.strip_edges(true,true) + print(" ACTION =", spaceNode.locale_action) "TEXT": parser.read() if parser.get_node_type() == XMLParser.NODE_TEXT: @@ -298,7 +302,9 @@ func runXML_NodeBuilder(module_file_path:String)->Array: var destArr = nodeArray_XML[0].destinations_array create_option(option, destArr[i]) i = i+1 - options_container.get_child(0).call_deferred("grab_focus") + if options_container.get_child_count() > 0: + options_container.get_child(0).grab_focus() + return nodeArray_XML @@ -339,7 +345,9 @@ func runJSON_NodeBuilder(module_file_path:String)->Array: var destArr = nodeArray_JSON[0].destinations_array create_option(option, destArr[i]) i = i+1 - options_container.get_child(0).grab_focus() + if options_container.get_child_count() > 0: + options_container.get_child(0).grab_focus() + return nodeArray_JSON @@ -410,7 +418,11 @@ func add_option_to_game(optionNew: Control) -> void: #DKM TEMP: these need to be dynamically added with the options themselves func _on_option_pressed(destinationSelected: String) -> void: - #print("Destination node for pressed option is: " + destinationSelected) + # If we are inside a conflict flow, options are "CONFLICT:*" tokens, not locale names. + print("OPTION CLICKED:", destinationSelected) + if conflict_state != null and destinationSelected.begins_with("CONFLICT:"): + _handle_conflict_choice(destinationSelected) + return change_node(destinationSelected) func get_node_by_name(nodeName: String) -> Locale: @@ -504,8 +516,30 @@ func change_node(destinationNode: String, _destinationParams: Array = []) -> voi # var degreeOfSuccess = result[4] # var dice = result[5] + + # --- NEW: d20 conflict hooks (see diagrams) --- + elif target_Locale.locale_action == "StartSimpleConflict": + # Store where to return after the conflict finishes (optional) + if target_Locale.destinations_array.size() > 0: + conflict_return_node = target_Locale.destinations_array[0] + else: + conflict_return_node = "" + + _start_simple_conflict(target_Locale.locale_action_params) + return + elif target_Locale.locale_action == "StartExtendedConflict": + print(">>> HIT StartExtendedConflict <<<") + if target_Locale.destinations_array.size() > 0: + conflict_return_node = target_Locale.destinations_array[0] + else: + conflict_return_node = "" + + _start_extended_conflict(target_Locale.locale_action_params) + return #change_node(target_Locale.destinations_array[0]) - options_container.get_child(0).grab_focus() + if options_container.get_child_count() > 0: + options_container.get_child(0).grab_focus() + #FUNCTION: Find Relocation Location #Params: array containing the names of target: 0.region, 1.location, 2.space @@ -531,3 +565,456 @@ func save_module(): scene.pack(self) #var _saveResponse = ResourceSaver.save("user://game_01.tscn", scene) var _saveResponse = ResourceSaver.save("res://_userFiles/game_01.tscn", scene) + + +# --------------------------------------------------------------------------- +# d20 Conflict / Turn System implementation (MVP) +# This section implements the flow in your diagrams without changing your UI: +# we re-use the existing OptionsContainer buttons by emitting destinations that +# start with "CONFLICT:". +# +# Godot 3.5 compatible. +# --------------------------------------------------------------------------- + +func _start_simple_conflict(params: Array) -> void: + # params (optional): [npc_name] + var npc_name = "Bandit" + if params.size() > 0: + npc_name = str(params[0]) + + var npc = ConflictMgr.make_default_npc(npc_name) + conflict_state = { + "mode": "simple", + "step": "choose_intent", + "pc_intent": "", + "pc_trait": "", + "npc_intent": "", + "npc_trait": "", + "npc": npc + } + create_response("[Conflict] Choose your intent (talk / move / do / fight).") + clear_prior_options() + _render_conflict() + +func _start_extended_conflict(params: Array) -> void: + var npc_name = "Bandit" + if params.size() > 0: + npc_name = str(params[0]) + + var npc = ConflictMgr.make_default_npc(npc_name) + conflict_state = { + "mode": "extended", + "step": "initiative", + "round": 1, + "turn": "", + "distance": 1, # 1 = in melee range (MVP) + "pc_turn": {"moved": false, "acted": false}, + "pc_status": {"hidden": false, "dodging": false, "disengaged": false, "helping": false, "reaction": ""}, + "npc": npc + } + create_response("[Combat] Extended conflict started. Rolling initiative…") + clear_prior_options() + _render_conflict() + +func _handle_conflict_choice(token: String) -> void: + # token format: CONFLICT:: + var parts = token.split(":", false) + if parts.size() < 3: + return + var kind = parts[1] + var value = parts[2] + + if conflict_state == null: + return + + match conflict_state["mode"]: + "simple": + _handle_simple_choice(kind, value) + "extended": + _handle_extended_choice(kind, value) + _: + pass + +func _render_conflict() -> void: + if conflict_state == null: + return + match conflict_state["mode"]: + "simple": + _render_simple() + "extended": + _render_extended() + _: + pass + +# --- SIMPLE CONFLICT (Diagram 1) ------------------------------------------- + +func _render_simple() -> void: + clear_prior_options() + match conflict_state["step"]: + "choose_intent": + create_option("Talk", "CONFLICT:intent:talk") + create_option("Move", "CONFLICT:intent:move") + create_option("Do", "CONFLICT:intent:do") + create_option("Fight", "CONFLICT:intent:fight") + "choose_trait": + var intent = conflict_state["pc_intent"] + create_response("[Conflict] Using what? Pick a trait for intent: " + intent) + var caps = _pc_caps_dict() + var group = ConflictMgr.intent_cap_group(intent) + for cap_name in group: + if caps.has(cap_name): + create_option(cap_name, "CONFLICT:trait:" + cap_name) + create_option("Back", "CONFLICT:nav:back") + "end": + create_option("Continue", "CONFLICT:end:ok") + _: + create_option("Continue", "CONFLICT:end:ok") + +func _handle_simple_choice(kind: String, value: String) -> void: + match kind: + "intent": + conflict_state["pc_intent"] = value + conflict_state["step"] = "choose_trait" + _render_conflict() + "trait": + conflict_state["pc_trait"] = value + _resolve_simple_conflict() + conflict_state["step"] = "end" + _render_conflict() + "nav": + if value == "back": + conflict_state["step"] = "choose_intent" + _render_conflict() + "end": + # exit conflict and go back + var return_to = conflict_return_node + conflict_state = null + conflict_return_node = "" + if return_to != "": + change_node(return_to) + else: + # If no return node provided, just rebuild current node options by doing nothing. + pass + _: + pass + +func _resolve_simple_conflict() -> void: + var pc_intent = str(conflict_state["pc_intent"]) + var pc_trait = str(conflict_state["pc_trait"]) + + # NPC chooses an intent (MVP AI) and best matching trait + var npc_intents = ["talk", "move", "do", "fight"] + randomize() + var npc_intent = npc_intents[randi() % npc_intents.size()] + conflict_state["npc_intent"] = npc_intent + + var npc = conflict_state["npc"] + var npc_trait = _npc_best_trait(npc, npc_intent) + conflict_state["npc_trait"] = npc_trait + + # Calculate trait mods (Diagram: Trait Mods -> Total Mods) + var pc_percent = _pc_get_percent(pc_trait) + var npc_percent = _npc_get_percent(npc, npc_trait) + + var roll = ConflictMgr.contested_roll(pc_percent, npc_percent, 0, 0) + + var pc_total = roll["pc"]["total"] + var npc_total = roll["npc"]["total"] + var margin = int(roll["margin"]) + var outcome = str(roll["outcome"]) + + var winner = "TIE" + if margin > 0: + winner = "PC" + elif margin < 0: + winner = "NPC" + + + var msg = "[Conflict Result]\n" + msg += "PC intent: %s (using %s)\n" % [pc_intent, pc_trait] + msg += "NPC intent: %s (using %s)\n" % [npc_intent, npc_trait] + msg += "PC roll %d + mod %d = %d\n" % [roll["pc"]["roll"], roll["pc"]["mod"], pc_total] + msg += "NPC roll %d + mod %d = %d\n" % [roll["npc"]["roll"], roll["npc"]["mod"], npc_total] + msg += "Outcome: %s (margin %d) => %s\n" % [winner, margin, outcome] + + # If it's a fight intent for either side, apply a tiny MVP damage to show the loop works + if pc_intent == "fight" or npc_intent == "fight": + var dmg = 1 + int(abs(margin) / 5) + if outcome == "CRIT_SUCCESS" or outcome == "CRIT_FAIL": + dmg += 2 + if margin > 0: + _npc_take_damage(conflict_state["npc"], dmg) + msg += "PC hits %s for %d damage. NPC HP now %d.\n" % [npc["name"], dmg, npc["hp"]] + elif margin < 0: + _pc_take_damage(dmg) + msg += "NPC hits PC for %d damage. PC HP now %d.\n" % [dmg, _pc_get_hp()] + else: + msg += "No damage (tie).\n" + + create_response(msg) + +# --- EXTENDED CONFLICT (Diagrams 2/3/4) ------------------------------------ + +func _render_extended() -> void: + clear_prior_options() + match conflict_state["step"]: + "initiative": + # Initiative Order (Diagram 2) + var npc = conflict_state["npc"] + var roll = ConflictMgr.contested_roll(_pc_get_percent("AG"), _npc_get_percent(npc, "AG"), 0, 0) + if int(roll["margin"]) >= 0: + conflict_state["turn"] = "pc" + else: + conflict_state["turn"] = "npc" + + create_response("[Initiative] PC total %d vs NPC total %d. %s goes first." % [roll["pc"]["total"], roll["npc"]["total"], conflict_state["turn"].to_upper()]) + conflict_state["step"] = "turn_start" + create_option("Continue", "CONFLICT:flow:next") + "turn_start": + # Reset per-turn flags + conflict_state["pc_turn"] = {"moved": false, "acted": false} + # Clean up some one-turn statuses + conflict_state["pc_status"]["helping"] = false + conflict_state["pc_status"]["reaction"] = "" + var npc = conflict_state["npc"] + create_response("[Round %d] PC HP %d | %s HP %d" % [conflict_state["round"], _pc_get_hp(), npc["name"], npc["hp"]]) + if conflict_state["turn"] == "pc": + conflict_state["step"] = "pc_choose" + _render_extended() + else: + conflict_state["step"] = "npc_act" + create_option("Continue", "CONFLICT:flow:next") + "pc_choose": + # Action Declaration (Diagram 2) + list from Diagram 3 + create_response("[Your turn] Choose action (you may Move + 1 Action).") + create_option("Move", "CONFLICT:act:move") + create_option("Attack", "CONFLICT:act:attack") + create_option("Hide", "CONFLICT:act:hide") + create_option("Dodge", "CONFLICT:act:dodge") + create_option("Disengage", "CONFLICT:act:disengage") + create_option("Help", "CONFLICT:act:help") + create_option("Set reaction", "CONFLICT:act:reaction") + create_option("Spell", "CONFLICT:act:spell") + create_option("Flee", "CONFLICT:act:flee") + # Only allow End Turn if you already moved or acted + var moved = conflict_state["pc_turn"]["moved"] + var acted = conflict_state["pc_turn"]["acted"] + if moved or acted: + create_option("End turn", "CONFLICT:act:endturn") + "npc_act": + create_response(_npc_take_turn()) + conflict_state["turn"] = "pc" + conflict_state["round"] += 1 + conflict_state["step"] = "turn_start" + create_option("Continue", "CONFLICT:flow:next") + "end": + create_option("Continue", "CONFLICT:end:ok") + _: + create_option("Continue", "CONFLICT:end:ok") + +func _handle_extended_choice(kind: String, value: String) -> void: + if kind == "flow": + _render_conflict() + return + if kind == "end": + var return_to = conflict_return_node + conflict_state = null + conflict_return_node = "" + if return_to != "": + change_node(return_to) + return + if kind != "act": + return + + match value: + "move": + conflict_state["pc_turn"]["moved"] = true + create_response("[Move] You reposition. (MVP: distance stays " + str(conflict_state["distance"]) + ")") + conflict_state["step"] = "pc_choose" + _render_conflict() + "attack": + conflict_state["pc_turn"]["acted"] = true + create_response(_pc_attack_npc()) + if _check_combat_end(): + conflict_state["step"] = "end" + _render_conflict() + else: + conflict_state["step"] = "pc_choose" + _render_conflict() + "hide": + conflict_state["pc_turn"]["acted"] = true + create_response(_pc_try_hide()) + conflict_state["step"] = "pc_choose" + _render_conflict() + "dodge": + conflict_state["pc_turn"]["acted"] = true + conflict_state["pc_status"]["dodging"] = true + create_response("[Dodge] Until your next turn, attacks against you are harder.") + conflict_state["step"] = "pc_choose" + _render_conflict() + "disengage": + conflict_state["pc_turn"]["acted"] = true + conflict_state["pc_status"]["disengaged"] = true + create_response("[Disengage] You avoid opportunity attacks this round (MVP flag).") + conflict_state["step"] = "pc_choose" + _render_conflict() + "help": + conflict_state["pc_turn"]["acted"] = true + conflict_state["pc_status"]["helping"] = true + create_response("[Help] You set up an ally (MVP: stored as a flag).") + conflict_state["step"] = "pc_choose" + _render_conflict() + "reaction": + conflict_state["pc_turn"]["acted"] = true + conflict_state["pc_status"]["reaction"] = "basic_reaction" + create_response("[Set reaction] Reaction set (MVP placeholder).") + conflict_state["step"] = "pc_choose" + _render_conflict() + "spell": + conflict_state["pc_turn"]["acted"] = true + create_response("[Spell] Spell casting placeholder (hook your spell system here).") + conflict_state["step"] = "pc_choose" + _render_conflict() + "flee": + create_response("[Flee] You leave the conflict.") + conflict_state["step"] = "end" + _render_conflict() + "endturn": + conflict_state["turn"] = "npc" + conflict_state["step"] = "npc_act" + _render_conflict() + _: + pass + +func _pc_attack_npc() -> String: + # Conflict Results Process (Diagram 2): + # - Situational modifiers: e.g., target dodging/hidden etc. + # - Defender vs Opponent results matrix => we use margin tiers. + var npc = conflict_state["npc"] + var situ_pc = 0 + var situ_npc = 0 + if npc["status"]["dodging"]: + situ_pc -= 2 + var roll = ConflictMgr.contested_roll(_pc_get_percent("ST"), _npc_get_percent(npc, "AG"), situ_pc, situ_npc) + var margin = int(roll["margin"]) + var outcome = str(roll["outcome"]) + + var msg = "[Attack]\n" + msg += "PC %d vs NPC %d (margin %d => %s)\n" % [roll["pc"]["total"], roll["npc"]["total"], margin, outcome] + + if margin > 0: + var dmg = 2 + int(margin / 5) + if outcome == "CRIT_SUCCESS": + dmg += 3 + _npc_take_damage(npc, dmg) + msg += "Hit! Dealt %d damage. %s HP now %d." % [dmg, npc["name"], npc["hp"]] + else: + msg += "Miss." + return msg + +func _npc_take_turn() -> String: + var npc = conflict_state["npc"] + # Very simple AI for MVP: + # - if PC is hidden, NPC tries to "search" (opposed IN vs AG) + # - else NPC attacks (opposed ST vs AG) with penalty if PC is dodging + if conflict_state["pc_status"]["hidden"]: + var roll = ConflictMgr.contested_roll(_npc_get_percent(npc, "IN"), _pc_get_percent("AG"), 0, 0) + if int(roll["margin"]) > 0: + conflict_state["pc_status"]["hidden"] = false + return "[NPC] %s spots you! (You are no longer hidden)" % npc["name"] + return "[NPC] %s searches but can’t find you." % npc["name"] + + var situ_npc = 0 + if conflict_state["pc_status"]["dodging"]: + situ_npc -= 2 + var roll2 = ConflictMgr.contested_roll(_npc_get_percent(npc, "ST"), _pc_get_percent("AG"), situ_npc, 0) + var margin2 = int(roll2["margin"]) # NPC - PC + # NOTE: contested_roll returns margin as PC - NPC by default, so invert meaning here + # We called with (npc, pc) as (pc_percent, npc_percent) in the function, so margin is NPC - PC. + if margin2 > 0: + var dmg = 2 + int(margin2 / 5) + if str(roll2["outcome"]) == "CRIT_SUCCESS": + dmg += 3 + _pc_take_damage(dmg) + if _pc_get_hp() <= 0: + return "[NPC] %s hits you for %d damage. You are defeated." % [npc["name"], dmg] + return "[NPC] %s hits you for %d damage. PC HP now %d." % [npc["name"], dmg, _pc_get_hp()] + return "[NPC] %s attacks but misses." % npc["name"] + +func _pc_try_hide() -> String: + var npc = conflict_state["npc"] + var roll = ConflictMgr.contested_roll(_pc_get_percent("AG"), _npc_get_percent(npc, "IN"), 0, 0) + if int(roll["margin"]) > 0: + conflict_state["pc_status"]["hidden"] = true + return "[Hide] Success. You are hidden." + return "[Hide] Failed. They keep track of you." + +func _check_combat_end() -> bool: + var npc = conflict_state["npc"] + if npc["hp"] <= 0: + create_response("[Combat] %s is defeated." % npc["name"]) + return true + if _pc_get_hp() <= 0: + create_response("[Combat] You are defeated.") + return true + return false + +# --- PC/NPC stat helpers ---------------------------------------------------- + +func _pc_caps_dict() -> Dictionary: + var d = {} + var p = PlayerCharacter.pc + if p == null: + return d + for cap in p.player_capabilities: + d[str(cap.name)] = int(cap.score) + int(cap.modifier) + return d + +func _pc_get_percent(cap_name: String) -> int: + var p = PlayerCharacter.pc + if p == null: + return 0 + for cap in p.player_capabilities: + if str(cap.name).to_upper() == cap_name.to_upper(): + return int(cap.score) + int(cap.modifier) + return 0 + +func _pc_get_hp() -> int: + var p = PlayerCharacter.pc + if p == null: + return 0 + for cap in p.player_capabilities: + if str(cap.name) == "Health": + return int(cap.score) + return 0 + +func _pc_take_damage(dmg: int) -> void: + var p = PlayerCharacter.pc + if p == null: + return + for cap in p.player_capabilities: + if str(cap.name) == "Health": + cap.score = int(cap.score) - int(dmg) + return + +func _npc_get_percent(npc: Dictionary, cap_name: String) -> int: + if npc.has("caps") and npc["caps"].has(cap_name): + return int(npc["caps"][cap_name]) + return 0 + +func _npc_best_trait(npc: Dictionary, intent: String) -> String: + var group = ConflictMgr.intent_cap_group(intent) + var best = "" + var best_val = -999 + for cap_name in group: + var v = _npc_get_percent(npc, cap_name) + if v > best_val: + best_val = v + best = cap_name + if best != "": + return best + return group[0] + + +func _npc_take_damage(npc: Dictionary, dmg: int) -> void: + npc["hp"] = int(npc["hp"]) - int(dmg) diff --git a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/gamePlay/Game.tscn b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/gamePlay/Game.tscn index 351c887..ba8181c 100644 --- a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/gamePlay/Game.tscn +++ b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/gamePlay/Game.tscn @@ -2,7 +2,7 @@ [ext_resource path="res://gamePlay/But_Option.tscn" type="PackedScene" id=1] [ext_resource path="res://gamePlay/Game.gd" type="Script" id=2] -[ext_resource path="res://assets/Themes/Dark Theme/ui_controlNode_dark_theme.tres" type="Theme" id=3] +[ext_resource path="res://assets/ui_controlNode_dark_theme.tres" type="Theme" id=3] [ext_resource path="res://gamePlay/But_MoreOptions.gd" type="Script" id=9] [node name="Game" type="Control"] diff --git a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/globalScripts/CombatManager.gd b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/globalScripts/CombatManager.gd index f8e5bea..a206c92 100644 --- a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/globalScripts/CombatManager.gd +++ b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/globalScripts/CombatManager.gd @@ -48,16 +48,56 @@ var combat_active = false var current_turn = "player" # "player" or "opponent" var round_number = 0 +# Per-character defending state (avoids requiring a `defending` field on character scripts) +var _defending_state = {} + # Initialize the combat manager func _init(): # Create a die manager for percentage dice (two d10s) dieManager = DieManager.new([10, 10], 0.5) + +# --- Helpers for compatibility with different character data models --- + +func _char_id(ch): + if ch == null: + return 0 + if ch.has_method("get_instance_id"): + return ch.get_instance_id() + return int(ch) + +func _is_alive(ch): + if ch == null: + return false + if ch.has_method("is_alive"): + return ch.is_alive() + # Fallback: treat objects with hp as alive if hp > 0 + if ch.get("hp") != null: + return int(ch.get("hp")) > 0 + return true + +func _apply_damage(ch, damage): + if ch == null: + return + if ch.has_method("take_damage"): + ch.take_damage(damage) + return + # Fallback: subtract from hp if present + if ch.get("hp") != null: + ch.set("hp", int(ch.get("hp")) - int(damage)) + +func _is_defending(ch): + return _defending_state.get(_char_id(ch), false) + +func _set_defending(ch, value): + _defending_state[_char_id(ch)] = bool(value) + # Start a new combat encounter func start_combat(player_ref, opponent_ref): player = player_ref opponent = opponent_ref combat_active = true + _defending_state = {} round_number = 1 current_turn = "player" @@ -68,8 +108,8 @@ func end_combat(): combat_active = false var result = "Combat ended." - if player.is_alive(): - if !opponent.is_alive(): + if _is_alive(player): + if !_is_alive(opponent): result += " " + player.name + " is victorious!" else: result += " Combat was interrupted." @@ -85,6 +125,8 @@ func next_turn(): else: current_turn = "player" round_number += 1 + # New round: clear any lingering defensive stances + _defending_state = {} return "Round " + str(round_number) + ", " + current_turn + "'s turn." @@ -101,6 +143,9 @@ func attack(attacker, defender, stat_or_skill, difficulty="AVERAGE"): # Apply difficulty modifier to the base percentage var difficulty_mod = DIFFICULTY_MODIFIER[difficulty] var modified_percentage = clamp(base_percentage + difficulty_mod, 0, 100) / 100.0 + # If the defender is defending, make the attack harder (simple MVP rule) + if _is_defending(defender): + modified_percentage = max(0.0, modified_percentage - 0.20) # Set up the die manager with the modified percentage as the passing threshold dieManager.clearData() @@ -131,40 +176,59 @@ func attack(attacker, defender, stat_or_skill, difficulty="AVERAGE"): var damage = int(base_damage * strength_modifier * (1 + max(0, roll_result[4]))) # Apply damage to defender - defender.take_damage(damage) + _apply_damage(defender, damage) + # Consumes the defending stance once attacked + _set_defending(defender, false) result["damage"] = damage result["message"] = attacker.name + " successfully attacks " + defender.name + " for " + str(damage) + " damage!" else: result["damage"] = 0 result["message"] = attacker.name + " attempts to attack " + defender.name + " but misses!" + # Consumes the defending stance once targeted + _set_defending(defender, false) return result # Perform a defend action - increases defense for next round func defend(character): - character.defending = true + _set_defending(character, true) return character.name + " takes a defensive stance." # Check if character has the given stat or skill func has_stat_or_skill(character, stat_or_skill): - if stat_or_skill in character.attributes: + var attrs = character.get("attributes") + if attrs != null and stat_or_skill in attrs: return true - elif stat_or_skill in character.skills: + var skills = character.get("skills") + if skills != null and stat_or_skill in skills: return true + var caps = character.get("player_capabilities") + if caps != null: + for c in caps: + if c != null and c.name == stat_or_skill: + return true return false # Get the value of a character's stat or skill func get_character_value(character, stat_or_skill): - if stat_or_skill in character.attributes: - return character.attributes[stat_or_skill] - elif stat_or_skill in character.skills: - return character.skills[stat_or_skill] + var attrs = character.get("attributes") + if attrs != null and stat_or_skill in attrs: + return attrs[stat_or_skill] + var skills = character.get("skills") + if skills != null and stat_or_skill in skills: + return skills[stat_or_skill] + # Fallback: BCI-RPG character model uses player_capabilities (Array[Char_Capability]) + var caps = character.get("player_capabilities") + if caps != null: + for c in caps: + if c != null and c.name == stat_or_skill: + return c.score return 0 # Execute an AI turn for the opponent. (Not literal AI fyi. This is just for the computer's turns) func execute_ai_turn(): - if !combat_active || current_turn != "opponent" || !opponent.is_alive(): + if !combat_active || current_turn != "opponent" || !_is_alive(opponent): return "No valid opponent turn to execute." var action_result = "" @@ -203,7 +267,7 @@ func run_test_combat(player_ref, opponent_ref): var attack_result = attack(player, opponent, "ST") combat_log.append(attack_result["message"]) - if !opponent.is_alive(): + if !_is_alive(opponent): combat_log.append(end_combat()) break @@ -211,7 +275,7 @@ func run_test_combat(player_ref, opponent_ref): else: combat_log.append(execute_ai_turn()) - if !player.is_alive(): + if !_is_alive(player): combat_log.append(end_combat()) break diff --git a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/globalScripts/ConflictManagerD20.gd b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/globalScripts/ConflictManagerD20.gd new file mode 100644 index 0000000..db82cf8 --- /dev/null +++ b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/globalScripts/ConflictManagerD20.gd @@ -0,0 +1,85 @@ +extends Node +class_name ConflictManagerD20 + +const D20_Converter_Source := preload("res://globalScripts/D20_Converter.gd") + +var _converter = null +var _d20_manager = null + +func _init(): + _converter = D20_Converter_Source.new() + _d20_manager = DieManager.new([20], 0.0) + +# Intent -> recommended capabilities +func intent_cap_group(intent: String) -> Array: + match intent.to_lower(): + "talk": + return ["CH", "PR", "MX", "SD"] + "move": + return ["AG", "MD", "QU"] + "fight": + return ["ST", "AG", "CO"] + "do": + return ["AG","CO","QU","MD","ST","RE","ME","IN","EM","CH","PR","MX","SD"] + _: + return [] + +func make_default_npc(name: String = "Bandit") -> Dictionary: + var caps = { + "ST": 55, "AG": 50, "CO": 45, + "RE": 40, "ME": 40, "IN": 35, "EM": 35, + "CH": 30, "PR": 30, "MX": 30, "SD": 30, + "MD": 45, "QU": 45 + } + return { + "name": name, + "caps": caps, + "hp": 12, + "status": {"hidden": false, "dodging": false, "disengaged": false} + } + +func contested_roll(pc_percent: int, npc_percent: int, situational_pc: int = 0, situational_npc: int = 0) -> Dictionary: + var pc_mod = percentile_to_d20_mod(pc_percent) + situational_pc + var npc_mod = percentile_to_d20_mod(npc_percent) + situational_npc + + var pc_roll = roll_d20() + var npc_roll = roll_d20() + + var pc_total = pc_roll + pc_mod + var npc_total = npc_roll + npc_mod + + var margin = pc_total - npc_total + var outcome = margin_to_outcome(margin) + + return { + "pc": {"roll": pc_roll, "mod": pc_mod, "total": pc_total}, + "npc": {"roll": npc_roll, "mod": npc_mod, "total": npc_total}, + "margin": margin, + "outcome": outcome + } + +func percentile_to_d20_mod(percent: int) -> int: + var score20 = _converter.FUNC_1(int(clamp(percent, 0, 100))) + return int(floor((score20 - 10) / 2.0)) + +func margin_to_outcome(margin: int) -> String: + if margin >= 10: + return "CRIT_SUCCESS" + elif margin >= 5: + return "STRONG_SUCCESS" + elif margin >= 1: + return "WEAK_SUCCESS" + elif margin == 0: + return "TIE" + elif margin <= -10: + return "CRIT_FAIL" + else: + return "FAIL" + +func roll_d20() -> int: + _d20_manager.clearData() + _d20_manager.setDieManager([20], 0.0) + var res = _d20_manager.rollDice() + if res.size() > 0 and res[0].size() > 0: + return int(res[0][0]) + return 1 diff --git a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/globalScripts/Die.gd b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/globalScripts/Die.gd index e2c7c66..4632fd6 100644 --- a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/globalScripts/Die.gd +++ b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/globalScripts/Die.gd @@ -12,8 +12,6 @@ func _init(value): #returns an integer value of the rolled result (assuming the die is a valid type) func rollDie(): - randomize() - var rolledNum rolledNum = randi() % numFaces + 1 return rolledNum diff --git a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/globalScripts/DieManager.gd b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/globalScripts/DieManager.gd index c565d6b..3ed72e8 100644 --- a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/globalScripts/DieManager.gd +++ b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/globalScripts/DieManager.gd @@ -31,6 +31,7 @@ var degreeOfSuccess #Constructor for diemanager class func _init(dice, percent): + randomize() # Seed RNG once for this DieManager instance desiredDice = dice neededPercentageToPass = percent loadData() @@ -78,8 +79,8 @@ func returnDiePercentage(inputedDie): #Checks if a percentageroll is being done if isPercentageRoll: - #This conditional is used to detemrine if the rolled value is - #for the tens or ones digit + # Percentile: treat a d10 roll of 10 as digit 0 + # (00 will later be interpreted as 100 in rollDice()) return float(rolledVal % 10) return float(rolledVal) / float(inputedDie.numFaces) @@ -98,7 +99,14 @@ func rollDice(): var sumOfPercentages = 0 if isPercentageRoll: - sumOfPercentages += (returnDiePercentage(diceUsed[0]) / 10.0) + (returnDiePercentage(diceUsed[1]) / 100.0) + # Percentile roll using two d10s: + # tens digit: 0-9, ones digit: 0-9 + var tens_digit = int(returnDiePercentage(diceUsed[0])) + var ones_digit = int(returnDiePercentage(diceUsed[1])) + var percentile_int = (tens_digit * 10) + ones_digit # 0..99 + if percentile_int == 0: + percentile_int = 100 # interpret 00 as 100 + sumOfPercentages += float(percentile_int) / 100.0 else: #DKM TEMP: not percentage roll: print("TEMP: not percentage roll") @@ -120,9 +128,9 @@ func rollDice(): result.append(stepify((float(sumOfPercentages) / float(denominator)), 0.0001)) - passedRoll = (result[1] >= neededPercentageToPass) + passedRoll = (result[1] <= neededPercentageToPass) #NOTE: degree of success is always calculated regardlesss of success/failure. Let me know if this should be changed - degreeOfSuccess = result[1] - neededPercentageToPass + degreeOfSuccess = neededPercentageToPass - result[1] result.append(passedRoll) result.append(neededPercentageToPass) result.append(degreeOfSuccess) diff --git a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/globalScripts/globalSaveInstance.gd b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/globalScripts/globalSaveInstance.gd index ce1e108..3769126 100644 --- a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/globalScripts/globalSaveInstance.gd +++ b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/globalScripts/globalSaveInstance.gd @@ -28,11 +28,9 @@ func load_settings_file(): #Keyboard: settingsInstance.visualKeyboardLayout = config.get_value("virtual_keyboard", "keyboard_layout") #Theme: - #settingsInstance.themeChoice = config.get_value("theme", "theme_selection") - settingsInstance.themeFile = config.get_value("theme", "theme_selection") - print(settingsInstance.themeFile) + settingsInstance.themeChoiceInt = config.get_value("theme", "theme_selection") - #load_themeFile() + load_themeFile() #DKM TEMP: working print("Input name loaded as: " + str(settingsInstance.inputName)) @@ -40,32 +38,7 @@ func load_settings_file(): func load_themeFile() -> void: #DKM TEMP: this shouldn't be hard-coded: -# if(settingsInstance.themeChoice == 1): -# settingsInstance.themeFile = "res://assets/ui_controlNode_light_theme.tres" -# else: -# settingsInstance.themeFile = "res://assets/ui_controlNode_dark_theme.tres" - - #settingsInstance.themeFile = "res://assets/Themes/" + settingsInstance.themeChoice - pass - -func load_fontSize(theme): - var fontToUse - match settingsInstance.fontSize: - 1.0: - fontToUse = load("res://assets/liberation_serif.tres") - 2.0: - fontToUse = load("res://assets/liberation_serif_20pt.tres") - 3.0: - fontToUse = load("res://assets/liberation_serif_30pt.tres") - 4.0: - fontToUse = load("res://assets/liberation_serif_40pt.tres") - _: - fontToUse = load("res://assets/liberation_serif_50pt.tres") - - theme.set_font("font","font", fontToUse) - theme.set_font("font","Button", fontToUse) - theme.set_font("font","ItemList", fontToUse) - theme.set_font("font","Label", fontToUse) - theme.set_font("font","LineEdit", fontToUse) - theme.set_font("font","Tabs", fontToUse) - theme.set_font("font","TextEdit", fontToUse) + if(settingsInstance.themeChoiceInt == 1): + settingsInstance.themeFile = "res://assets/ui_controlNode_light_theme.tres" + else: + settingsInstance.themeFile = "res://assets/ui_controlNode_dark_theme.tres" diff --git a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/globalScripts/playerSettingsTemplate.gd b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/globalScripts/playerSettingsTemplate.gd index 7a1daaf..8411487 100644 --- a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/globalScripts/playerSettingsTemplate.gd +++ b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/globalScripts/playerSettingsTemplate.gd @@ -9,7 +9,7 @@ class_name PlayerSettingsTemplate var inputName = "none" var riskFactor = 0 var brightness = 3 -var fontSize = 3.0 +var fontSize = 11 var volume = 6 var bClosedCaptions = true var bdevConsole = false @@ -23,7 +23,9 @@ var game_selection = game_options[0] # Setting of 0 is Qwerty, Setting of 1 is Davorak, Setting of 2 is Alphabetical var visualKeyboardLayout = 0 -var themeFile = "res://assets/Themes/Dark Theme/ui_controlNode_dark_theme.tres" +# Setting of 0 is dark, setting of 1 is light, and so on +var themeChoiceInt = 0 +var themeFile = "res://assets/ui_controlNode_dark_theme.tres" func _ready(): pass diff --git a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/project.godot b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/project.godot index 042e9f4..f263fc2 100644 --- a/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/project.godot +++ b/Phase2/MVP/Game/bcirpg_game_mvp_2024_0831A/project.godot @@ -34,6 +34,11 @@ _global_script_classes=[ { "language": "GDScript", "path": "res://globalScripts/CombatManager.gd" }, { +"base": "Node", +"class": "ConflictManagerD20", +"language": "GDScript", +"path": "res://globalScripts/ConflictManagerD20.gd" +}, { "base": "Reference", "class": "D20_Converter", "language": "GDScript", @@ -90,6 +95,7 @@ _global_script_class_icons={ "Char_Capability": "", "CheckResult": "", "CombatManager": "", +"ConflictManagerD20": "", "D20_Converter": "", "Die": "", "DieManager": "", @@ -120,17 +126,17 @@ GameCurrent="*res://globalScripts/gameCurrent.gd" open_file_hotkey={ "deadzone": 0.5, -"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":true,"command":true,"pressed":false,"scancode":0,"physical_scancode":79,"unicode":0,"echo":false,"script":null) +"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":true,"meta":true,"command":true,"pressed":false,"scancode":0,"physical_scancode":79,"unicode":0,"echo":false,"script":null) ] } save_character_file_hotkey={ "deadzone": 0.5, -"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":true,"command":true,"pressed":false,"scancode":0,"physical_scancode":83,"unicode":0,"echo":false,"script":null) +"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":true,"meta":true,"command":true,"pressed":false,"scancode":0,"physical_scancode":83,"unicode":0,"echo":false,"script":null) ] } back_to_main_menu_hotkey={ "deadzone": 0.5, -"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":true,"command":true,"pressed":false,"scancode":0,"physical_scancode":77,"unicode":0,"echo":false,"script":null) +"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":true,"meta":true,"command":true,"pressed":false,"scancode":0,"physical_scancode":77,"unicode":0,"echo":false,"script":null) ] } diff --git a/bcirpg_mvp1.zip b/bcirpg_mvp1.zip new file mode 100644 index 0000000..1f44984 Binary files /dev/null and b/bcirpg_mvp1.zip differ