From ce38eeb9c54cfcb276c9a4fa8faba9ca5956cd92 Mon Sep 17 00:00:00 2001 From: Kiremon-work Date: Fri, 27 Feb 2026 16:12:57 +0600 Subject: [PATCH 1/4] achievements system added --- assets/data/ResourceScripts.gd | 1 + assets/data/achievements_data.gd | 145 ++++++++++++ assets/data/classes.gd | 6 + .../data/events/act1_princess_declaration.gd | 4 + assets/data/events/act2_finish.gd | 8 + assets/data/events/act3_finish.gd | 12 + assets/data/pregen_characters_data.gd | 8 + assets/data/scenedata.gd | 2 + .../Mansion/Scripts/MansionMainModule.gd | 4 + gui_modules/Universal/Modules/Gallery.tscn | 28 ++- gui_modules/Universal/Modules/Menu.tscn | 221 +++++++++++++++++- .../Universal/Modules/game_plus_bonus.gd | 11 + gui_modules/Universal/Scripts/Gallery.gd | 4 + gui_modules/Universal/Scripts/Menu.gd | 58 +++++ gui_modules/achievements/achi_unit.gd | 21 ++ gui_modules/achievements/achi_unit.tscn | 108 +++++++++ .../achievements/achievements_panel.gd | 29 +++ .../achievements/achievements_panel.tscn | 116 +++++++++ gui_modules/achievements/bonus_unit.gd | 20 ++ gui_modules/achievements/bonus_unit.tscn | 107 +++++++++ gui_modules/achievements/unlock.gd | 47 ++++ gui_modules/achievements/unlock.tscn | 118 ++++++++++ localization/en/main.gd | 65 ++++++ src/character/CharacterClass.gd | 1 + src/character/ch_dyn_stats.gd | 3 +- src/character/ch_stats.gd | 2 +- src/core/achievements.gd | 105 +++++++++ src/core/game_party.gd | 3 + src/core/globals.gd | 3 + src/core/input_handler.gd | 9 +- 30 files changed, 1263 insertions(+), 6 deletions(-) create mode 100644 assets/data/achievements_data.gd create mode 100644 gui_modules/Universal/Modules/game_plus_bonus.gd create mode 100644 gui_modules/achievements/achi_unit.gd create mode 100644 gui_modules/achievements/achi_unit.tscn create mode 100644 gui_modules/achievements/achievements_panel.gd create mode 100644 gui_modules/achievements/achievements_panel.tscn create mode 100644 gui_modules/achievements/bonus_unit.gd create mode 100644 gui_modules/achievements/bonus_unit.tscn create mode 100644 gui_modules/achievements/unlock.gd create mode 100644 gui_modules/achievements/unlock.tscn create mode 100644 src/core/achievements.gd diff --git a/assets/data/ResourceScripts.gd b/assets/data/ResourceScripts.gd index 61ced0963..03e9d551e 100644 --- a/assets/data/ResourceScripts.gd +++ b/assets/data/ResourceScripts.gd @@ -101,6 +101,7 @@ onready var node_data = { input_handler.NODE_ARENA : {name = 'arena', mode = 'scene', scene = preload("res://gui_modules/arena/arena.tscn"), calls = 'open'}, input_handler.NODE_HARD_TUTORIAL_PANEL : {name = 'hard_tutorial_panel', mode = 'scene', scene = preload("res://gui_modules/Universal/Modules/hard_tutorial_panel.tscn")}, input_handler.NODE_HARD_TUTORIAL_LIST : {name = 'hard_tutorial_list', mode = 'scene', scene = preload("res://gui_modules/Universal/Modules/hard_tutorial_list.tscn")}, + input_handler.NODE_ACHI_UNLOCK : {name = 'achi_unlock', mode = 'scene', scene = preload("res://gui_modules/achievements/unlock.tscn")},#calls = 'open' #Animations input_handler.ANIM_TASK_AQUARED : {name = 'ANIMTaskAquared', mode = 'scene', scene = preload("res://gui_modules/Animations/Animation_task_aquired.tscn") }, input_handler.ANIM_BATTLE_START : {name = 'ANIMBattleStart', mode = 'scene', scene = preload("res://gui_modules/Animations/Animation_battle_start.tscn") }, diff --git a/assets/data/achievements_data.gd b/assets/data/achievements_data.gd new file mode 100644 index 000000000..79e60ff1e --- /dev/null +++ b/assets/data/achievements_data.gd @@ -0,0 +1,145 @@ +extends Reference + +var achievements = { + quest_loan = { + name = "ACHIEVEMENT_LOAN_NAME", + description = "ACHIEVEMENT_LOAN_DESC", + hint = "ACHIEVEMENT_LOAN_HINT", + icon = "res://assets/Textures_v2/Universal/Icons/crown.png", + points = 5 + }, + quest_sword_art = { + name = "ACHIEVEMENT_SWORDART_NAME", + description = "ACHIEVEMENT_SWORDART_DESC", + hint = "ACHIEVEMENT_SWORDART_HINT", + icon = "res://assets/Textures_v2/Universal/Icons/crown.png", + points = 5 + }, + act1 = { + name = "ACHIEVEMENT_ACT1_NAME", + description = "ACHIEVEMENT_ACT1_DESC", + hint = "ACHIEVEMENT_ACT1_HINT", + icon = "res://assets/Textures_v2/Universal/Icons/icon_master.png", + points = 5 + }, + act2 = { + name = "ACHIEVEMENT_ACT2_NAME", + description = "ACHIEVEMENT_ACT2_DESC", + hint = "ACHIEVEMENT_ACT2_HINT", + icon = "res://assets/Textures_v2/Universal/Icons/icon_master.png", + points = 5 + }, + act3 = { + name = "ACHIEVEMENT_ACT3_NAME", + description = "ACHIEVEMENT_ACT3_DESC", + hint = "ACHIEVEMENT_ACT3_HINT", + icon = "res://assets/Textures_v2/Universal/Icons/icon_master.png", + points = 5 + }, + char_daisy = { + name = "ACHIEVEMENT_DAISY_NAME", + description = "ACHIEVEMENT_DAISY_DESC", + hint = "ACHIEVEMENT_DAISY_HINT", + icon = "res://assets/images/portraits/daisy_prt/daisy_default_prt_bold.png", + points = 5 + }, + char_kurdan = { + name = "ACHIEVEMENT_KURDAN_NAME", + description = "ACHIEVEMENT_KURDAN_DESC", + hint = "ACHIEVEMENT_KURDAN_HINT", + icon = "res://assets/images/portraits/kurdan_prt.png", + points = 5 + }, + char_aire = { + name = "ACHIEVEMENT_AIRE_NAME", + description = "ACHIEVEMENT_AIRE_DESC", + hint = "ACHIEVEMENT_AIRE_HINT", + icon = "res://assets/images/portraits/aire_prt.png", + points = 5 + }, + char_kuro = { + name = "ACHIEVEMENT_KURO_NAME", + description = "ACHIEVEMENT_KURO_DESC", + hint = "ACHIEVEMENT_KURO_HINT", + icon = "res://assets/images/portraits/Kuro_prt.png", + points = 5 + }, + class_worker = { + name = "ACHIEVEMENT_WORKER_NAME", + description = "ACHIEVEMENT_WORKER_DESC", + hint = "ACHIEVEMENT_WORKER_HINT", + icon = "res://assets/images/iconsclasses/Worker.png", + points = 5 + }, + class_hunter = { + name = "ACHIEVEMENT_HUNTER_NAME", + description = "ACHIEVEMENT_HUNTER_DESC", + hint = "ACHIEVEMENT_HUNTER_HINT", + icon = "res://assets/images/iconsclasses/Hunter.png", + points = 5 + }, + class_chef = { + name = "ACHIEVEMENT_CHEF_NAME", + description = "ACHIEVEMENT_CHEF_DESC", + hint = "ACHIEVEMENT_CHEF_HINT", + icon = "res://assets/images/iconsclasses/Chef.png", + points = 5 + }, + class_harlot = { + name = "ACHIEVEMENT_HARLOT_NAME", + description = "ACHIEVEMENT_HARLOT_DESC", + hint = "ACHIEVEMENT_HARLOT_HINT", + icon = "res://assets/images/iconsclasses/Whore.png", + points = 5 + }, + class_dancer = { + name = "ACHIEVEMENT_DANCER_NAME", + description = "ACHIEVEMENT_DANCER_DESC", + hint = "ACHIEVEMENT_DANCER_HINT", + icon = "res://assets/images/iconsclasses/dancer.png", + points = 5 + }, + class_fighter = { + name = "ACHIEVEMENT_FIGHTER_NAME", + description = "ACHIEVEMENT_FIGHTER_DESC", + hint = "ACHIEVEMENT_FIGHTER_HINT", + icon = "res://assets/images/iconsclasses/Fighter.png", + points = 5 + }, + +} + +var bonuses = { + daisy_start = { + name = "ACHIBONUS_DAISY_START", + description = "ACHIBONUS_DAISY_START_DESC", + hint = "ACHIBONUS_DAISY_START_HINT", + icon = "res://assets/images/portraits/daisy_prt/daisy_default_prt_bold.png", + preparation = "prep_daisy_start", + cost = 10 + }, + kurdan_start = { + name = "ACHIBONUS_KURDAN_START", + description = "ACHIBONUS_KURDAN_START_DESC", + hint = "ACHIBONUS_KURDAN_START_HINT", + icon = "res://assets/images/portraits/kurdan_prt.png", + preparation = "prep_kurdan_start", + cost = 10 + }, + aire_start = { + name = "ACHIBONUS_AIRE_START", + description = "ACHIBONUS_AIRE_START_DESC", + hint = "ACHIBONUS_AIRE_START_HINT", + icon = "res://assets/images/portraits/aire_prt.png", + preparation = "prep_aire_start", + cost = 10 + }, + kuro_start = { + name = "ACHIBONUS_KURO_START", + description = "ACHIBONUS_KURO_START_DESC", + hint = "ACHIBONUS_KURO_START_HINT", + icon = "res://assets/images/portraits/kuro_prt/kuro_default_prt_bold.png", + preparation = "prep_kuro_start", + cost = 5 + } +} diff --git a/assets/data/classes.gd b/assets/data/classes.gd index f5b127f89..0d6b8b156 100644 --- a/assets/data/classes.gd +++ b/assets/data/classes.gd @@ -126,6 +126,7 @@ var professions = { skills = [], combatskills = [], conflict_classes = [], + achievement = "class_worker", }, foreman = { code = 'foreman', @@ -156,6 +157,7 @@ var professions = { skills = [], combatskills = [], conflict_classes = [], + achievement = "class_hunter" }, smith = { code = 'smith', @@ -201,6 +203,7 @@ var professions = { skills = [], combatskills = [], conflict_classes = [], + achievement = "class_chef" }, attendant = { code = 'attendant', @@ -292,6 +295,7 @@ var professions = { skills = [], combatskills = [], conflict_classes = [], + achievement = "class_harlot" }, geisha = { code = 'geisha', @@ -435,6 +439,7 @@ var professions = { skills = [],#'allure','performance'], combatskills = ['distract'], conflict_classes = [], + achievement = "class_dancer" }, maid = { code = 'maid', @@ -467,6 +472,7 @@ var professions = { skills = [], combatskills = [], conflict_classes = [], + achievement = "class_fighter" }, knight = { code = 'knight', diff --git a/assets/data/events/act1_princess_declaration.gd b/assets/data/events/act1_princess_declaration.gd index 34b9e6080..f692cf4ac 100644 --- a/assets/data/events/act1_princess_declaration.gd +++ b/assets/data/events/act1_princess_declaration.gd @@ -200,6 +200,10 @@ var data = { }, { code = "check_masters_story_fame", + }, + { + code = "achievement", + value = "act1" } ], text = [ diff --git a/assets/data/events/act2_finish.gd b/assets/data/events/act2_finish.gd index 6232cdc21..049591287 100644 --- a/assets/data/events/act2_finish.gd +++ b/assets/data/events/act2_finish.gd @@ -3752,6 +3752,10 @@ var data = { { code = "decision", value = "act2_finish" + }, + { + code = "achievement", + value = "act2" } ] }, @@ -4090,6 +4094,10 @@ var data = { { code = "decision", value = "act2_finish" + }, + { + code = "achievement", + value = "act2" } ] }, diff --git a/assets/data/events/act3_finish.gd b/assets/data/events/act3_finish.gd index ae3e0d486..88bb52b3f 100644 --- a/assets/data/events/act3_finish.gd +++ b/assets/data/events/act3_finish.gd @@ -1000,6 +1000,10 @@ var data = { code = "decision", value = "act3_finish" }, + { + code = "achievement", + value = "act3" + }, { code = "add_timed_event", value = "emp_city_init", @@ -1033,6 +1037,10 @@ var data = { code = "decision", value = "act3_finish" }, + { + code = "achievement", + value = "act3" + }, { code = "add_timed_event", value = "emp_city_init", @@ -1414,6 +1422,10 @@ var data = { code = "decision", value = "act3_finish" }, + { + code = "achievement", + value = "act3" + }, { code = "add_timed_event", value = "emp_city_init", diff --git a/assets/data/pregen_characters_data.gd b/assets/data/pregen_characters_data.gd index 35880c3b1..50d2cc424 100644 --- a/assets/data/pregen_characters_data.gd +++ b/assets/data/pregen_characters_data.gd @@ -58,6 +58,8 @@ var pregen_characters = { training_sexservice_adv = ["DaisyTrainingFinished"], training_callmaster = ['DaisyQuestlineFinished'], }, + achievement = "char_daisy", + achi_bonus = "daisy_start", }, Kurdan = { @@ -99,6 +101,8 @@ var pregen_characters = { traits = ['gifted','training_s_combat','training_s_working'], tags = [], sex_skills = {petting = 2, penetration = 15, oral = 4, anal = 0}, + achievement = "char_kurdan", + achi_bonus = "kurdan_start", }, Aire = { code = 'aire', @@ -153,6 +157,8 @@ var pregen_characters = { positive = 'neutral', magic = 'neutral', }, + achievement = "char_aire", + achi_bonus = "aire_start", }, Anastasia = { code = 'anastasia', @@ -832,6 +838,8 @@ var pregen_characters = { positive = 'neutral', magic = 'resist', }, + achievement = "char_kuro", + achi_bonus = "kuro_start" }, Rouge = { diff --git a/assets/data/scenedata.gd b/assets/data/scenedata.gd index fd47332d7..3f078f273 100644 --- a/assets/data/scenedata.gd +++ b/assets/data/scenedata.gd @@ -2234,6 +2234,7 @@ var quests = { stage2 = {code = 'stage2', name = 'MAIN_QUEST_LOAN_NAME', descript = 'MAIN_QUEST_LOAN_STAGE2'}, stage3 = {code = 'stage3', name = 'MAIN_QUEST_LOAN_NAME', descript = 'MAIN_QUEST_LOAN_STAGE3'}, }, + achievement = "quest_loan" }, guilds_introduction = { @@ -2489,6 +2490,7 @@ var quests = { stage15 = {code = 'stage15', name = "SWORD_ARTIFACT_QUEST_NAME", descript = "SWORD_ARTIFACT_QUEST_STAGE_14"}, # go to white stag location stage16 = {code = 'stage16', name = "SWORD_ARTIFACT_QUEST_NAME", descript = "SWORD_ARTIFACT_QUEST_STAGE_15"}, # return to erlen after you're done with temple quest }, + achievement = "quest_sword_art" }, temple_quest = { diff --git a/gui_modules/Mansion/Scripts/MansionMainModule.gd b/gui_modules/Mansion/Scripts/MansionMainModule.gd index 41173bf6b..ab9711566 100644 --- a/gui_modules/Mansion/Scripts/MansionMainModule.gd +++ b/gui_modules/Mansion/Scripts/MansionMainModule.gd @@ -74,6 +74,7 @@ var always_show = [ "map_test" ] +var newgame_bonuses func _ready(): # input_handler.CurrentScene = self @@ -105,6 +106,9 @@ func _ready(): show() input_handler.ActivateTutorial("TUTORIALLIST1") globals.apply_starting_preset() + if newgame_bonuses != null:#can be set externally + input_handler.achievements.prepare_bonuses(newgame_bonuses) + newgame_bonuses = null ResourceScripts.game_globals.reset_limits() SlaveListModule.rebuild() diff --git a/gui_modules/Universal/Modules/Gallery.tscn b/gui_modules/Universal/Modules/Gallery.tscn index 3f07007d3..2acd14373 100644 --- a/gui_modules/Universal/Modules/Gallery.tscn +++ b/gui_modules/Universal/Modules/Gallery.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=27 format=2] +[gd_scene load_steps=28 format=2] [ext_resource path="res://assets/Fonts_v2/PT_Sans/PTSans-Regular.ttf" type="DynamicFontData" id=1] [ext_resource path="res://assets/Themes_v2/UNIVERSAL/NonDecorButton_with_Font.tres" type="Theme" id=2] @@ -23,6 +23,7 @@ [ext_resource path="res://assets/Textures_v2/Gallery/icon_page_default.png" type="Texture" id=21] [ext_resource path="res://assets/Textures_v2/Gallery/icon_page_hover.png" type="Texture" id=22] [ext_resource path="res://assets/Textures_v2/Gallery/icon_page_pressed.png" type="Texture" id=23] +[ext_resource path="res://gui_modules/achievements/achievements_panel.tscn" type="PackedScene" id=24] [sub_resource type="DynamicFont" id=1] size = 60 @@ -167,6 +168,28 @@ text = "GALLERYSCENES" align = 1 valign = 1 +[node name="AchiButton" type="TextureButton" parent="."] +margin_left = 80.0 +margin_top = 82.0 +margin_right = 319.0 +margin_bottom = 132.0 +texture_normal = ExtResource( 4 ) +texture_pressed = ExtResource( 7 ) +texture_hover = ExtResource( 6 ) +expand = true +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="Label" type="Label" parent="AchiButton"] +anchor_right = 1.0 +anchor_bottom = 1.0 +custom_colors/font_color = Color( 0.976471, 0.882353, 0.505882, 1 ) +custom_fonts/font = SubResource( 3 ) +text = "GALLERYACHI" +align = 1 +valign = 1 + [node name="Pagination" type="HBoxContainer" parent="."] margin_left = 130.0 margin_top = 153.0 @@ -331,4 +354,7 @@ __meta__ = { "_edit_use_anchors_": false } +[node name="achievements" parent="." instance=ExtResource( 24 )] +visible = false + [connection signal="pressed" from="ResetProgress" to="." method="_on_ResetProgress_pressed"] diff --git a/gui_modules/Universal/Modules/Menu.tscn b/gui_modules/Universal/Modules/Menu.tscn index b4ab1724d..38c6991a3 100644 --- a/gui_modules/Universal/Modules/Menu.tscn +++ b/gui_modules/Universal/Modules/Menu.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=62 format=2] +[gd_scene load_steps=86 format=2] [ext_resource path="res://assets/Themes_v2/UNIVERSAL/NonDecorButton_with_Font.tres" type="Theme" id=1] [ext_resource path="res://assets/Themes_v2/UNIVERSAL/PT_24_Label.tres" type="Theme" id=2] @@ -43,14 +43,27 @@ [ext_resource path="res://assets/images/buttons/mainmenu/button_discord2.png" type="Texture" id=41] [ext_resource path="res://assets/Textures_v2/CHAR_CREATION/new/button_choose_basic.png" type="Texture" id=42] [ext_resource path="res://assets/Themes_v2/UNIVERSAL/ConfirmWindowTheme.tres" type="Theme" id=43] +[ext_resource path="res://assets/Textures_v2/Universal/Buttons/button_occupation.png" type="Texture" id=44] +[ext_resource path="res://assets/Textures_v2/Universal/Icons/tick.png" type="Texture" id=45] [ext_resource path="res://assets/images/buttons/mainmenu/button_discord.png" type="Texture" id=46] +[ext_resource path="res://assets/Textures_v2/Universal/Buttons/button_occupation_pressed.png" type="Texture" id=47] +[ext_resource path="res://assets/Textures_v2/Universal/Buttons/button_occupation_hover.png" type="Texture" id=48] +[ext_resource path="res://assets/Textures_v2/Universal/Icons/tick_hover.png" type="Texture" id=49] +[ext_resource path="res://assets/Textures_v2/Universal/Icons/tick_chosen.png" type="Texture" id=50] +[ext_resource path="res://assets/Textures_v2/Universal/Icons/tick_chosen_disabled.png" type="Texture" id=51] +[ext_resource path="res://assets/Textures_v2/Universal/Panels/panel_simple.png" type="Texture" id=52] +[ext_resource path="res://assets/Textures_v2/Universal/Panels/panel_square.png" type="Texture" id=53] [ext_resource path="res://assets/Themes_v2/MAIN_MENU/Menu_StartGame_panel.tres" type="StyleBox" id=54] [ext_resource path="res://assets/images/buttons/mainmenu/button_patreon.png" type="Texture" id=55] [ext_resource path="res://assets/Themes_v2/UNIVERSAL/PT_24.tres" type="DynamicFont" id=56] +[ext_resource path="res://gui_modules/Universal/Modules/game_plus_bonus.gd" type="Script" id=57] [ext_resource path="res://assets/images/buttons/mainmenu/button_patreon2.png" type="Texture" id=58] [ext_resource path="res://assets/images/buttons/mainmenu/button_fandom2.png" type="Texture" id=59] [ext_resource path="res://assets/images/buttons/mainmenu/button_itch.png" type="Texture" id=60] [ext_resource path="res://assets/images/buttons/mainmenu/button_fandom.png" type="Texture" id=61] +[ext_resource path="res://assets/images/portraits/daisy_prt/daisy_default_prt_bold.png" type="Texture" id=62] +[ext_resource path="res://assets/Textures_v2/Universal/Buttons/button_occupation_disabled.png" type="Texture" id=63] +[ext_resource path="res://assets/Textures_v2/Universal/Icons/tick_disabled.png" type="Texture" id=64] [sub_resource type="DynamicFont" id=5] size = 64 @@ -94,6 +107,65 @@ region_rect = Rect2( 0, 0, 210, 58 ) texture = ExtResource( 8 ) region_rect = Rect2( 0, 0, 210, 58 ) +[sub_resource type="DynamicFont" id=11] +size = 18 +use_filter = true +font_data = ExtResource( 4 ) + +[sub_resource type="ImageTexture" id=12] + +[sub_resource type="StyleBoxTexture" id=13] +texture = ExtResource( 49 ) +region_rect = Rect2( 0, 0, 40, 40 ) + +[sub_resource type="StyleBoxTexture" id=14] +texture = ExtResource( 50 ) +region_rect = Rect2( 0, 0, 40, 40 ) + +[sub_resource type="StyleBoxTexture" id=21] +texture = ExtResource( 64 ) +region_rect = Rect2( 0, 0, 40, 40 ) + +[sub_resource type="StyleBoxTexture" id=15] +texture = ExtResource( 51 ) +region_rect = Rect2( 0, 0, 40, 40 ) + +[sub_resource type="StyleBoxTexture" id=16] +texture = ExtResource( 45 ) +region_rect = Rect2( 0, 0, 40, 40 ) + +[sub_resource type="StyleBoxTexture" id=17] +texture = ExtResource( 48 ) +region_rect = Rect2( 0, 0, 230, 40 ) +margin_left = 5.0 +margin_right = 5.0 +margin_top = 5.0 +margin_bottom = 5.0 + +[sub_resource type="StyleBoxTexture" id=18] +texture = ExtResource( 47 ) +region_rect = Rect2( 0, 0, 230, 40 ) +margin_left = 5.0 +margin_right = 5.0 +margin_top = 5.0 +margin_bottom = 5.0 + +[sub_resource type="StyleBoxTexture" id=20] +texture = ExtResource( 63 ) +region_rect = Rect2( 0, 0, 230, 40 ) +margin_left = 5.0 +margin_right = 5.0 +margin_top = 5.0 +margin_bottom = 5.0 + +[sub_resource type="StyleBoxTexture" id=19] +texture = ExtResource( 44 ) +region_rect = Rect2( 0, 0, 230, 40 ) +margin_left = 5.0 +margin_right = 5.0 +margin_top = 5.0 +margin_bottom = 5.0 + [node name="Menu" type="Control"] margin_top = -1.0 margin_bottom = -1.0 @@ -745,6 +817,153 @@ __meta__ = { "_edit_use_anchors_": false } +[node name="bonuses" type="TextureRect" parent="NewGamePanel"] +visible = false +margin_left = 717.0 +margin_right = 1256.0 +margin_bottom = 773.0 +texture = ExtResource( 19 ) +expand = true + +[node name="title" type="Label" parent="NewGamePanel/bonuses"] +margin_left = 9.0 +margin_right = 529.0 +margin_bottom = 85.0 +custom_colors/font_color = Color( 0.976471, 0.882353, 0.505882, 1 ) +custom_fonts/font = ExtResource( 15 ) +text = "NEWGAMEPLUSNAME" +align = 1 +valign = 1 + +[node name="points_cont" type="HBoxContainer" parent="NewGamePanel/bonuses"] +margin_left = 16.0 +margin_top = 89.0 +margin_right = 522.0 +margin_bottom = 129.0 +custom_constants/separation = 15 + +[node name="points_name" type="Label" parent="NewGamePanel/bonuses/points_cont"] +margin_top = 2.0 +margin_right = 274.0 +margin_bottom = 37.0 +custom_colors/font_color = Color( 0.976471, 0.882353, 0.505882, 1 ) +custom_fonts/font = SubResource( 7 ) +text = "NEWGAMEPLUS_POINTS" +align = 1 +valign = 1 + +[node name="points" type="Label" parent="NewGamePanel/bonuses/points_cont"] +margin_left = 289.0 +margin_top = 2.0 +margin_right = 350.0 +margin_bottom = 37.0 +custom_colors/font_color = Color( 0.976471, 0.882353, 0.505882, 1 ) +custom_fonts/font = SubResource( 7 ) +text = "00/00" +align = 1 +valign = 1 + +[node name="ScrollContainer" type="ScrollContainer" parent="NewGamePanel/bonuses"] +margin_left = 19.0 +margin_top = 136.0 +margin_right = 519.0 +margin_bottom = 752.0 + +[node name="VBoxContainer" type="VBoxContainer" parent="NewGamePanel/bonuses/ScrollContainer"] +margin_right = 500.0 +size_flags_horizontal = 3 + +[node name="bonus" type="Control" parent="NewGamePanel/bonuses/ScrollContainer/VBoxContainer"] +visible = false +margin_right = 500.0 +margin_bottom = 103.0 +rect_min_size = Vector2( 50, 103 ) +script = ExtResource( 57 ) + +[node name="name" type="Label" parent="NewGamePanel/bonuses/ScrollContainer/VBoxContainer/bonus"] +margin_left = 103.0 +margin_right = 415.0 +margin_bottom = 35.0 +custom_colors/font_color = Color( 0.976471, 0.882353, 0.505882, 1 ) +custom_fonts/font = SubResource( 7 ) +text = "name" + +[node name="cost" type="Label" parent="NewGamePanel/bonuses/ScrollContainer/VBoxContainer/bonus"] +margin_left = 432.0 +margin_right = 458.0 +margin_bottom = 35.0 +custom_colors/font_color = Color( 0.976471, 0.882353, 0.505882, 1 ) +custom_fonts/font = SubResource( 7 ) +text = "00" +align = 2 + +[node name="desc" type="Label" parent="NewGamePanel/bonuses/ScrollContainer/VBoxContainer/bonus"] +margin_left = 104.0 +margin_top = 31.0 +margin_right = 490.0 +margin_bottom = 94.0 +custom_colors/font_color = Color( 0.976471, 0.882353, 0.505882, 1 ) +custom_fonts/font = SubResource( 11 ) +text = "description" + +[node name="icon" type="TextureRect" parent="NewGamePanel/bonuses/ScrollContainer/VBoxContainer/bonus"] +anchor_bottom = 1.0 +margin_left = 4.0 +margin_top = 4.0 +margin_right = 99.0 +margin_bottom = -4.0 +texture = ExtResource( 62 ) +expand = true +stretch_mode = 5 + +[node name="frame" type="TextureRect" parent="NewGamePanel/bonuses/ScrollContainer/VBoxContainer/bonus"] +anchor_bottom = 1.0 +margin_left = 4.0 +margin_top = 4.0 +margin_right = 99.0 +margin_bottom = -4.0 +texture = ExtResource( 52 ) +expand = true +stretch_mode = 5 + +[node name="CheckBox" type="CheckBox" parent="NewGamePanel/bonuses/ScrollContainer/VBoxContainer/bonus"] +margin_left = 461.0 +margin_top = 7.0 +margin_right = 491.0 +margin_bottom = 37.0 +custom_icons/checked_disabled = SubResource( 12 ) +custom_icons/checked = SubResource( 12 ) +custom_icons/unchecked_disabled = SubResource( 12 ) +custom_icons/unchecked = SubResource( 12 ) +custom_styles/hover = SubResource( 13 ) +custom_styles/pressed = SubResource( 14 ) +custom_styles/disabled = SubResource( 21 ) +custom_styles/hover_pressed = SubResource( 15 ) +custom_styles/normal = SubResource( 16 ) +expand_icon = true + +[node name="frame_full" type="NinePatchRect" parent="NewGamePanel/bonuses/ScrollContainer/VBoxContainer/bonus"] +visible = false +anchor_right = 1.0 +anchor_bottom = 1.0 +texture = ExtResource( 53 ) +patch_margin_left = 12 +patch_margin_top = 12 +patch_margin_right = 12 +patch_margin_bottom = 12 + +[node name="btn" type="Button" parent="NewGamePanel/bonuses/ScrollContainer/VBoxContainer/bonus"] +show_behind_parent = true +anchor_right = 1.0 +anchor_bottom = 1.0 +focus_mode = 0 +custom_styles/hover = SubResource( 17 ) +custom_styles/pressed = SubResource( 18 ) +custom_styles/disabled = SubResource( 20 ) +custom_styles/normal = SubResource( 19 ) +toggle_mode = true +enabled_focus_mode = 0 + [node name="NewOrTutorial" type="Panel" parent="."] visible = false anchor_right = 1.0 diff --git a/gui_modules/Universal/Modules/game_plus_bonus.gd b/gui_modules/Universal/Modules/game_plus_bonus.gd new file mode 100644 index 000000000..bbb0b2310 --- /dev/null +++ b/gui_modules/Universal/Modules/game_plus_bonus.gd @@ -0,0 +1,11 @@ +extends Control + +func _ready(): + $btn.connect("toggled", self, "on_btn_toggled") + +func on_btn_toggled(pressed): + $CheckBox.pressed = pressed + +func set_disable(value): + $btn.disabled = value + $CheckBox.disabled = value diff --git a/gui_modules/Universal/Scripts/Gallery.gd b/gui_modules/Universal/Scripts/Gallery.gd index f3f71dc14..858f7ccce 100644 --- a/gui_modules/Universal/Scripts/Gallery.gd +++ b/gui_modules/Universal/Scripts/Gallery.gd @@ -31,6 +31,7 @@ func _ready(): $CharButton.connect("pressed", self, "set_state", ["char"]) $CharButton.set_meta("type", "char") $CloseButton.connect("pressed", self, "close_gallery") + $AchiButton.connect("pressed", self, "open_achievements") set_state("story") $FullScreenImage.connect("gui_input", self, '_on_FullScreenImage_gui_input') @@ -230,3 +231,6 @@ func reset_gallery_progress(): input_handler.progress_data.characters = [] input_handler.save_progress_data(input_handler.progress_data) set_state("story") + +func open_achievements(): + $achievements.show() diff --git a/gui_modules/Universal/Scripts/Menu.gd b/gui_modules/Universal/Scripts/Menu.gd index 802a95a5b..c512171fb 100644 --- a/gui_modules/Universal/Scripts/Menu.gd +++ b/gui_modules/Universal/Scripts/Menu.gd @@ -3,6 +3,12 @@ extends Control var lastsave = null +onready var newgame_bonuses_node = $NewGamePanel/bonuses +onready var newgame_bonuses_cont = $NewGamePanel/bonuses/ScrollContainer/VBoxContainer +var cur_bonus_points = 0 +var max_bonus_points = 0 +var newgame_bonuses = [] + func _ready(): get_tree().set_auto_accept_quit(false) gui_controller.add_close_button($NewGamePanel) @@ -199,6 +205,55 @@ func open_newgame(): # start_preset_update() # $NewGamePanel/PresetContainer/VBoxContainer.get_child(0).emit_signal('pressed') # ResourceScripts.game_globals.skip_prologue = $NewGamePanel/SkipP.pressed + + #new game + + var bonuses = input_handler.achievements.get_unlocked_bonuses() + newgame_bonuses.clear() + newgame_bonuses_node.visible = !bonuses.empty() + if !bonuses.empty(): + cur_bonus_points = 0 + max_bonus_points = input_handler.achievements.get_all_points() + update_bonus_points_text() + input_handler.ClearContainer(newgame_bonuses_cont, ["bonus"]) + for bonus_name in bonuses: + var data = bonuses[bonus_name] + var new_btn = input_handler.DuplicateContainerTemplate(newgame_bonuses_cont, "bonus") + new_btn.get_node("name").text = tr(data.name) + new_btn.get_node("desc").text = tr(data.description) + new_btn.get_node("cost").text = String(data.cost) + new_btn.get_node("icon").texture = data.icon + new_btn.set_meta("cost", data.cost) +# new_btn.set_meta("id", bonus_name) + new_btn.get_node("btn").connect("toggled", self, "bonus_toggled", [bonus_name]) + update_bonus_btns() + +func bonus_toggled(pressed, bonus): + if pressed: + if newgame_bonuses.has(bonus): + push_error("bonus_toggled: newgame_bonuses already has %s" % bonus) + else: + newgame_bonuses.append(bonus) + else: + newgame_bonuses.erase(bonus) + #recalc points + cur_bonus_points = 0 + for node in newgame_bonuses_cont.get_children(): + var btn = node.get_node("btn") + if node.visible and btn.pressed: + cur_bonus_points += node.get_meta("cost") + update_bonus_points_text() + update_bonus_btns() + +func update_bonus_btns(): + var points_left = max_bonus_points - cur_bonus_points + for node in newgame_bonuses_cont.get_children(): + var btn = node.get_node("btn") + if node.visible and !btn.pressed: + node.set_disable(node.get_meta("cost") > points_left) + +func update_bonus_points_text(): + newgame_bonuses_node.get_node("points_cont/points").text = "%s/%s" % [ + cur_bonus_points, max_bonus_points] func select_preset(val): if val == 'custom': @@ -281,6 +336,9 @@ func start_game_confirm(): ResourceScripts.game_globals.original_version = globals.gameversion get_node("/root").remove_child(self) input_handler.ChangeScene('mansion') + if !newgame_bonuses.empty(): + yield(globals, 'scene_change_start') + input_handler.CurrentScene.newgame_bonuses = newgame_bonuses yield(globals, 'scene_changed') gui_controller.windows_opened.clear() self.queue_free() diff --git a/gui_modules/achievements/achi_unit.gd b/gui_modules/achievements/achi_unit.gd new file mode 100644 index 000000000..0e1e2644d --- /dev/null +++ b/gui_modules/achievements/achi_unit.gd @@ -0,0 +1,21 @@ +extends Control + + +#expects dict from achievements_data.gd with loaded icon +func set_opened(data): + $bg_opened.show() + $bg_closed.hide() + $name.text = tr(data.name) + $name.show() + $points.text = "+%s" % data.points + $points.show() + $desc.text = tr(data.description) + $icon.texture = data.icon + +func set_locked(data): + $desc.text = tr(data.hint) +# $bg_opened.hide() +# $bg_closed.show() +# $name.hide() +# $points.hide() +# $icon.texture = load("res://assets/Textures_v2/CHAR_INFO/bubble_charinfo.png") diff --git a/gui_modules/achievements/achi_unit.tscn b/gui_modules/achievements/achi_unit.tscn new file mode 100644 index 000000000..91fc6d005 --- /dev/null +++ b/gui_modules/achievements/achi_unit.tscn @@ -0,0 +1,108 @@ +[gd_scene load_steps=10 format=2] + +[ext_resource path="res://assets/Fonts_v2/Noto_Sans_SC/NotoSansSC-Regular.otf" type="DynamicFontData" id=1] +[ext_resource path="res://assets/images/gui/craftgui/craft.png" type="Texture" id=2] +[ext_resource path="res://assets/Textures_v2/Universal/Panels/panel_simple.png" type="Texture" id=3] +[ext_resource path="res://assets/Textures_v2/ANIMATIONS/ClassAchieved/panel_class.png" type="Texture" id=4] +[ext_resource path="res://assets/Textures_v2/Universal/Panels/panel_square.png" type="Texture" id=5] +[ext_resource path="res://assets/Textures_v2/CHAR_INFO/bubble_charinfo.png" type="Texture" id=6] +[ext_resource path="res://gui_modules/achievements/achi_unit.gd" type="Script" id=7] + +[sub_resource type="DynamicFont" id=5] +size = 24 +use_filter = true +font_data = ExtResource( 1 ) + +[sub_resource type="DynamicFont" id=6] +size = 18 +use_filter = true +font_data = ExtResource( 1 ) + +[node name="achi" type="Control"] +margin_right = 420.0 +margin_bottom = 103.0 +rect_min_size = Vector2( 420, 103 ) +mouse_filter = 2 +script = ExtResource( 7 ) + +[node name="bg_opened" type="NinePatchRect" parent="."] +visible = false +anchor_right = 1.0 +anchor_bottom = 1.0 +texture = ExtResource( 4 ) +patch_margin_left = 15 +patch_margin_top = 15 +patch_margin_right = 15 +patch_margin_bottom = 15 + +[node name="bg_closed" type="NinePatchRect" parent="."] +anchor_right = 1.0 +anchor_bottom = 1.0 +texture = ExtResource( 2 ) +patch_margin_left = 15 +patch_margin_top = 15 +patch_margin_right = 15 +patch_margin_bottom = 15 + +[node name="name" type="Label" parent="."] +visible = false +margin_left = 103.0 +margin_top = 3.0 +margin_right = 377.0 +margin_bottom = 38.0 +custom_colors/font_color = Color( 0.976471, 0.882353, 0.505882, 1 ) +custom_fonts/font = SubResource( 5 ) +text = "name" + +[node name="points" type="Label" parent="."] +visible = false +margin_left = 383.0 +margin_top = 3.0 +margin_right = 409.0 +margin_bottom = 38.0 +grow_horizontal = 0 +custom_colors/font_color = Color( 0.976471, 0.882353, 0.505882, 1 ) +custom_fonts/font = SubResource( 5 ) +text = "+00" +align = 2 + +[node name="desc" type="Label" parent="."] +margin_left = 104.0 +margin_top = 33.0 +margin_right = 409.0 +margin_bottom = 94.0 +custom_colors/font_color = Color( 0.976471, 0.882353, 0.505882, 1 ) +custom_fonts/font = SubResource( 6 ) +text = "description" +autowrap = true + +[node name="icon" type="TextureRect" parent="."] +anchor_bottom = 1.0 +margin_left = 4.0 +margin_top = 4.0 +margin_right = 99.0 +margin_bottom = -4.0 +mouse_filter = 2 +texture = ExtResource( 6 ) +expand = true +stretch_mode = 5 + +[node name="frame" type="TextureRect" parent="."] +anchor_bottom = 1.0 +margin_left = 4.0 +margin_top = 4.0 +margin_right = 99.0 +margin_bottom = -4.0 +mouse_filter = 2 +texture = ExtResource( 3 ) +expand = true +stretch_mode = 5 + +[node name="frame_full" type="NinePatchRect" parent="."] +anchor_right = 1.0 +anchor_bottom = 1.0 +texture = ExtResource( 5 ) +patch_margin_left = 12 +patch_margin_top = 12 +patch_margin_right = 12 +patch_margin_bottom = 12 diff --git a/gui_modules/achievements/achievements_panel.gd b/gui_modules/achievements/achievements_panel.gd new file mode 100644 index 000000000..18db15376 --- /dev/null +++ b/gui_modules/achievements/achievements_panel.gd @@ -0,0 +1,29 @@ +extends Control + +func _ready(): + $CloseButton.connect("pressed", self, "hide") + +func show(): + var achi_cont = $achi_cont + var bonus_cont = $bonus_cont + input_handler.ClearContainer(achi_cont, ["achi"]) + input_handler.ClearContainer(bonus_cont, ["bonus"]) + var dict = input_handler.achievements.get_unlocked_achimnts() + for achi_name in dict: + var new_panel = input_handler.DuplicateContainerTemplate(achi_cont, "achi") + new_panel.set_opened(dict[achi_name]) + dict = input_handler.achievements.get_locked_achimnts() + for achi_name in dict: + var new_panel = input_handler.DuplicateContainerTemplate(achi_cont, "achi") + new_panel.set_locked(dict[achi_name]) + dict = input_handler.achievements.get_unlocked_bonuses() + for bonus_name in dict: + var new_panel = input_handler.DuplicateContainerTemplate(bonus_cont, "bonus") + new_panel.set_opened(dict[bonus_name]) + dict = input_handler.achievements.get_locked_bonuses() + for bonus_name in dict: + var new_panel = input_handler.DuplicateContainerTemplate(bonus_cont, "bonus") + new_panel.set_locked(dict[bonus_name]) + + .show() + diff --git a/gui_modules/achievements/achievements_panel.tscn b/gui_modules/achievements/achievements_panel.tscn new file mode 100644 index 000000000..20569d6ba --- /dev/null +++ b/gui_modules/achievements/achievements_panel.tscn @@ -0,0 +1,116 @@ +[gd_scene load_steps=9 format=2] + +[ext_resource path="res://assets/Fonts_v2/PT_Sans/PTSans-Regular.ttf" type="DynamicFontData" id=1] +[ext_resource path="res://gui_modules/achievements/achievements_panel.gd" type="Script" id=2] +[ext_resource path="res://gui_modules/achievements/achi_unit.tscn" type="PackedScene" id=3] +[ext_resource path="res://src/scenes/CloseButton.tscn" type="PackedScene" id=4] +[ext_resource path="res://gui_modules/achievements/bonus_unit.tscn" type="PackedScene" id=5] +[ext_resource path="res://assets/Textures_v2/MAIN_MENU/Panels/panel_modsoptions.png" type="Texture" id=6] + +[sub_resource type="DynamicFont" id=3] +size = 36 +use_filter = true +font_data = ExtResource( 1 ) + +[sub_resource type="DynamicFont" id=4] +size = 30 +use_filter = true +font_data = ExtResource( 1 ) + +[node name="achievements" type="Control"] +margin_right = 1920.0 +margin_bottom = 1080.0 +script = ExtResource( 2 ) + +[node name="curtain" type="ColorRect" parent="."] +anchor_right = 1.0 +anchor_bottom = 1.0 +color = Color( 0, 0, 0, 0.866667 ) + +[node name="NinePatchRect" type="NinePatchRect" parent="."] +margin_left = 72.0 +margin_top = 15.0 +margin_right = 958.0 +margin_bottom = 1055.0 +texture = ExtResource( 6 ) +patch_margin_left = 26 +patch_margin_top = 88 +patch_margin_right = 26 +patch_margin_bottom = 26 + +[node name="NinePatchRect2" type="NinePatchRect" parent="."] +margin_left = 972.0 +margin_top = 15.0 +margin_right = 1858.0 +margin_bottom = 1055.0 +texture = ExtResource( 6 ) +patch_margin_left = 26 +patch_margin_top = 88 +patch_margin_right = 26 +patch_margin_bottom = 26 + +[node name="achi_label" type="Label" parent="."] +margin_left = 79.0 +margin_top = 16.0 +margin_right = 951.0 +margin_bottom = 66.0 +custom_colors/font_color = Color( 0.976471, 0.882353, 0.505882, 1 ) +custom_fonts/font = SubResource( 3 ) +text = "GALLERYACHI" +align = 1 +valign = 1 + +[node name="achi_text" type="Label" parent="."] +margin_left = 96.0 +margin_top = 58.0 +margin_right = 930.0 +margin_bottom = 98.0 +custom_colors/font_color = Color( 0.976471, 0.882353, 0.505882, 1 ) +custom_fonts/font = SubResource( 4 ) +text = "GALLERYACHITEXT" + +[node name="achi_cont" type="GridContainer" parent="."] +margin_left = 96.0 +margin_top = 124.0 +margin_right = 936.0 +margin_bottom = 1035.0 +columns = 2 + +[node name="achi" parent="achi_cont" instance=ExtResource( 3 )] +visible = false + +[node name="bonus_label" type="Label" parent="."] +margin_left = 976.0 +margin_top = 16.0 +margin_right = 1853.0 +margin_bottom = 66.0 +custom_colors/font_color = Color( 0.976471, 0.882353, 0.505882, 1 ) +custom_fonts/font = SubResource( 3 ) +text = "GALLERYACHIBONUS" +align = 1 +valign = 1 + +[node name="bonus_text" type="Label" parent="."] +margin_left = 995.0 +margin_top = 58.0 +margin_right = 1834.0 +margin_bottom = 98.0 +custom_colors/font_color = Color( 0.976471, 0.882353, 0.505882, 1 ) +custom_fonts/font = SubResource( 4 ) +text = "GALLERYACHIBONUSTEXT" + +[node name="bonus_cont" type="GridContainer" parent="."] +margin_left = 992.0 +margin_top = 114.0 +margin_right = 1838.0 +margin_bottom = 1041.0 +columns = 2 + +[node name="bonus" parent="bonus_cont" instance=ExtResource( 5 )] +visible = false + +[node name="CloseButton" parent="." instance=ExtResource( 4 )] +anchor_left = 1.0 +anchor_right = 1.0 +margin_left = -30.0 +margin_right = 0.0 diff --git a/gui_modules/achievements/bonus_unit.gd b/gui_modules/achievements/bonus_unit.gd new file mode 100644 index 000000000..8cee88566 --- /dev/null +++ b/gui_modules/achievements/bonus_unit.gd @@ -0,0 +1,20 @@ +extends Control + +#expects dict from achievements_data.gd with loaded icon +func set_opened(data): + $bg_opened.show() + $bg_closed.hide() + $name.text = tr(data.name) + $name.show() + $points.text = String(data.cost) + $points.show() + $desc.text = tr(data.description) + $icon.texture = data.icon + +func set_locked(data): + $desc.text = tr(data.hint) +# $bg_opened.hide() +# $bg_closed.show() +# $name.hide() +# $points.hide() +# $icon.texture = load("res://assets/Textures_v2/CHAR_INFO/bubble_charinfo.png") diff --git a/gui_modules/achievements/bonus_unit.tscn b/gui_modules/achievements/bonus_unit.tscn new file mode 100644 index 000000000..ddf87a507 --- /dev/null +++ b/gui_modules/achievements/bonus_unit.tscn @@ -0,0 +1,107 @@ +[gd_scene load_steps=10 format=2] + +[ext_resource path="res://assets/Fonts_v2/Noto_Sans_SC/NotoSansSC-Regular.otf" type="DynamicFontData" id=1] +[ext_resource path="res://assets/Textures_v2/Universal/Panels/panel_simple.png" type="Texture" id=2] +[ext_resource path="res://assets/Textures_v2/Universal/Panels/panel_square.png" type="Texture" id=3] +[ext_resource path="res://assets/Textures_v2/Universal/Buttons/buttonbig_hover.png" type="Texture" id=4] +[ext_resource path="res://assets/Textures_v2/Universal/Buttons/buttonbig_disabled.png" type="Texture" id=5] +[ext_resource path="res://assets/Textures_v2/CHAR_INFO/bubble_charinfo.png" type="Texture" id=6] +[ext_resource path="res://gui_modules/achievements/bonus_unit.gd" type="Script" id=7] + +[sub_resource type="DynamicFont" id=5] +size = 24 +use_filter = true +font_data = ExtResource( 1 ) + +[sub_resource type="DynamicFont" id=6] +size = 18 +use_filter = true +font_data = ExtResource( 1 ) + +[node name="bonus" type="Control"] +margin_right = 420.0 +margin_bottom = 103.0 +rect_min_size = Vector2( 420, 103 ) +mouse_filter = 2 +script = ExtResource( 7 ) + +[node name="bg_opened" type="NinePatchRect" parent="."] +visible = false +anchor_right = 1.0 +anchor_bottom = 1.0 +texture = ExtResource( 4 ) +patch_margin_left = 5 +patch_margin_top = 5 +patch_margin_right = 5 +patch_margin_bottom = 5 + +[node name="bg_closed" type="NinePatchRect" parent="."] +anchor_right = 1.0 +anchor_bottom = 1.0 +texture = ExtResource( 5 ) +patch_margin_left = 5 +patch_margin_top = 5 +patch_margin_right = 5 +patch_margin_bottom = 5 + +[node name="name" type="Label" parent="."] +visible = false +margin_left = 103.0 +margin_top = 3.0 +margin_right = 377.0 +margin_bottom = 38.0 +custom_colors/font_color = Color( 0.976471, 0.882353, 0.505882, 1 ) +custom_fonts/font = SubResource( 5 ) +text = "name" + +[node name="points" type="Label" parent="."] +visible = false +margin_left = 383.0 +margin_top = 3.0 +margin_right = 409.0 +margin_bottom = 38.0 +custom_colors/font_color = Color( 0.976471, 0.882353, 0.505882, 1 ) +custom_fonts/font = SubResource( 5 ) +text = "00" +align = 2 + +[node name="desc" type="Label" parent="."] +margin_left = 104.0 +margin_top = 33.0 +margin_right = 409.0 +margin_bottom = 94.0 +custom_colors/font_color = Color( 0.976471, 0.882353, 0.505882, 1 ) +custom_fonts/font = SubResource( 6 ) +text = "description" +autowrap = true + +[node name="icon" type="TextureRect" parent="."] +anchor_bottom = 1.0 +margin_left = 4.0 +margin_top = 4.0 +margin_right = 99.0 +margin_bottom = -4.0 +mouse_filter = 2 +texture = ExtResource( 6 ) +expand = true +stretch_mode = 5 + +[node name="frame" type="TextureRect" parent="."] +anchor_bottom = 1.0 +margin_left = 4.0 +margin_top = 4.0 +margin_right = 99.0 +margin_bottom = -4.0 +mouse_filter = 2 +texture = ExtResource( 2 ) +expand = true +stretch_mode = 5 + +[node name="frame_full" type="NinePatchRect" parent="."] +anchor_right = 1.0 +anchor_bottom = 1.0 +texture = ExtResource( 3 ) +patch_margin_left = 12 +patch_margin_top = 12 +patch_margin_right = 12 +patch_margin_bottom = 12 diff --git a/gui_modules/achievements/unlock.gd b/gui_modules/achievements/unlock.gd new file mode 100644 index 000000000..9e0386da3 --- /dev/null +++ b/gui_modules/achievements/unlock.gd @@ -0,0 +1,47 @@ +extends Control + +onready var cont = $VBoxContainer +onready var achi_label = $VBoxContainer/achi_label +onready var bonus_label = $VBoxContainer/bonus_label + +const TIME_ON_SCREEN = 6.0 + +func _ready(): + $timer.connect("timeout", self, "close") + +#don't needed in fact, while there is queue_free() at end +#func open(): +# achi_label.hide() +# bonus_label.hide() +# input_handler.ClearContainer(cont, [ +# "achi_label", "achi", "bonus_label", "bonus"]) +# show() +# $timer.start(TIME_ON_SCREEN) + +func close(): + ResourceScripts.core_animations.FadeAnimation(self, 2.0) + var tweennode = input_handler.GetTweenNode(self) + if !tweennode.is_connected("tween_all_completed", self, "queue_free"): + tweennode.connect("tween_all_completed", self, "queue_free", [], CONNECT_ONESHOT) + +func add_achi(data): + var new_panel = input_handler.DuplicateContainerTemplate(cont, "achi") + cont.move_child(new_panel, cont.get_node("bonus_label").get_index()) + new_panel.set_opened(data) + achi_label.show() + restart_timer() +func add_bonus(data): + var new_panel = input_handler.DuplicateContainerTemplate(cont, "bonus") + new_panel.set_opened(data) + bonus_label.show() + restart_timer() + +func restart_timer(): + var tweennode = input_handler.GetTweenNode(self) + if tweennode.is_active(): + tweennode.stop_all() + tweennode.reset_all() + $timer.start(TIME_ON_SCREEN) + yield(get_tree(), 'idle_frame') + raise() + diff --git a/gui_modules/achievements/unlock.tscn b/gui_modules/achievements/unlock.tscn new file mode 100644 index 000000000..d496441e5 --- /dev/null +++ b/gui_modules/achievements/unlock.tscn @@ -0,0 +1,118 @@ +[gd_scene load_steps=8 format=2] + +[ext_resource path="res://assets/Fonts_v2/PT_Sans/PTSans-Regular.ttf" type="DynamicFontData" id=1] +[ext_resource path="res://gui_modules/achievements/bonus_unit.tscn" type="PackedScene" id=2] +[ext_resource path="res://gui_modules/achievements/achi_unit.tscn" type="PackedScene" id=3] +[ext_resource path="res://gui_modules/achievements/unlock.gd" type="Script" id=4] +[ext_resource path="res://assets/Textures_v2/ANIMATIONS/TaskCompleted/panel_complete.png" type="Texture" id=5] +[ext_resource path="res://assets/Textures_v2/ANIMATIONS/TaskCompleted/wing.png" type="Texture" id=6] + +[sub_resource type="DynamicFont" id=1] +size = 36 +use_filter = true +font_data = ExtResource( 1 ) + +[node name="unlock" type="Control"] +anchor_left = 1.0 +anchor_right = 1.0 +anchor_bottom = 1.0 +margin_left = -442.0 +margin_top = 35.0 +margin_right = -22.0 +margin_bottom = -32.0 +mouse_filter = 2 +script = ExtResource( 4 ) + +[node name="VBoxContainer" type="VBoxContainer" parent="."] +anchor_right = 1.0 +anchor_bottom = 1.0 +mouse_filter = 2 +alignment = 2 + +[node name="achi_label" type="Label" parent="VBoxContainer"] +visible = false +margin_top = 701.0 +margin_right = 444.0 +margin_bottom = 748.0 +custom_colors/font_color = Color( 0.976471, 0.882353, 0.505882, 1 ) +custom_fonts/font = SubResource( 1 ) +text = "ACHIEVEMENT_ACQUIRED" +align = 1 +valign = 1 + +[node name="NinePatchRect" type="NinePatchRect" parent="VBoxContainer/achi_label"] +show_behind_parent = true +anchor_right = 1.0 +anchor_bottom = 1.0 +texture = ExtResource( 5 ) +patch_margin_left = 12 +patch_margin_top = 12 +patch_margin_right = 12 +patch_margin_bottom = 12 + +[node name="TextureRect" type="TextureRect" parent="VBoxContainer/achi_label"] +margin_left = 444.0 +margin_right = 464.0 +margin_bottom = 45.0 +texture = ExtResource( 6 ) +expand = true +stretch_mode = 5 + +[node name="TextureRect2" type="TextureRect" parent="VBoxContainer/achi_label"] +margin_left = -20.0 +margin_bottom = 45.0 +texture = ExtResource( 6 ) +expand = true +stretch_mode = 5 +flip_h = true + +[node name="achi" parent="VBoxContainer" instance=ExtResource( 3 )] +visible = false +margin_top = 803.0 +margin_bottom = 906.0 + +[node name="bonus_label" type="Label" parent="VBoxContainer"] +visible = false +margin_top = 859.0 +margin_right = 444.0 +margin_bottom = 906.0 +custom_colors/font_color = Color( 0.976471, 0.882353, 0.505882, 1 ) +custom_fonts/font = SubResource( 1 ) +text = "ACHIBONUS_ACQUIRED" +align = 1 +valign = 1 + +[node name="NinePatchRect" type="NinePatchRect" parent="VBoxContainer/bonus_label"] +show_behind_parent = true +anchor_right = 1.0 +anchor_bottom = 1.0 +texture = ExtResource( 5 ) +patch_margin_left = 12 +patch_margin_top = 12 +patch_margin_right = 12 +patch_margin_bottom = 12 + +[node name="TextureRect" type="TextureRect" parent="VBoxContainer/bonus_label"] +margin_left = 444.0 +margin_right = 464.0 +margin_bottom = 45.0 +texture = ExtResource( 6 ) +expand = true +stretch_mode = 5 + +[node name="TextureRect2" type="TextureRect" parent="VBoxContainer/bonus_label"] +margin_left = -20.0 +margin_bottom = 45.0 +texture = ExtResource( 6 ) +expand = true +stretch_mode = 5 +flip_h = true + +[node name="bonus" parent="VBoxContainer" instance=ExtResource( 2 )] +visible = false +margin_top = 910.0 +margin_bottom = 1013.0 + +[node name="timer" type="Timer" parent="."] +wait_time = 6.0 +one_shot = true diff --git a/localization/en/main.gd b/localization/en/main.gd index bedc380c1..256544464 100644 --- a/localization/en/main.gd +++ b/localization/en/main.gd @@ -25,6 +25,10 @@ var TranslationDict = { GALLERYTOOLTIPTOP = "Scene Condition:", GALLERYRESETBUTTON = "Reset", GALLERYRESETTEXT = "Are you sure you want to reset ALL gallery progress?", + GALLERYACHI = "Achievements", + GALLERYACHITEXT = "Gives NG+ points", + GALLERYACHIBONUS = "NG+ bonuses", + GALLERYACHIBONUSTEXT = "Can be acquired at new game start, using NG+ points", MODLOAD = "Loaded mods", MODLOAD1 = "these mods will be applied to game and available in editor at next game start.", MODLIST = "List of mods available to load", @@ -287,6 +291,8 @@ but still will keep all your characters, items and inventory. Use this mode to l DIFF_EASY = "easy", DIFF_NORMAL = "normal", DIFF_HARD = "hard", + NEWGAMEPLUSNAME = "New game +", + NEWGAMEPLUS_POINTS = "Points:", TUTORIALINFONAME = "Introduction", TUTORIALINFOQUESTION = "Is it your first time playing Strive: Conquest?", TUTORIALINFOEXPLANATION = """You can open tutorial any time you wish, @@ -5102,6 +5108,65 @@ Boosts Productivity by 25%. SETTINGTURN_BASED_TIME_FLOW_NAME = """Turn Based Time Flow""", SETTINGTURN_BASED_TIME_FLOW_DESCRIPT = "Makes time flow into hour long turns.", + ACHIEVEMENT_ACQUIRED = "You acquired achievement", + ACHIBONUS_ACQUIRED = "You unlocked bonus", + ACHIEVEMENT_LOAN_NAME = "The loan paid", + ACHIEVEMENT_LOAN_DESC = "You successfully paid the loan", + ACHIEVEMENT_LOAN_HINT = "Finish 'The loan' quest", + ACHIEVEMENT_SWORDART_NAME = "Forests and Beasts", + ACHIEVEMENT_SWORDART_DESC = "You successfully finished 'Forests and Beasts' quest", + ACHIEVEMENT_SWORDART_HINT = "Finish 'Forests and Beasts' quest", + ACHIEVEMENT_ACT1_NAME = "Act 1 finished", + ACHIEVEMENT_ACT1_DESC = "Act 1 is finished", + ACHIEVEMENT_ACT1_HINT = "Finish 1 act", + ACHIEVEMENT_ACT2_NAME = "Act 2 finished", + ACHIEVEMENT_ACT2_DESC = "Act 2 is finished", + ACHIEVEMENT_ACT2_HINT = "Finish 2 act", + ACHIEVEMENT_ACT3_NAME = "Act 3 finished", + ACHIEVEMENT_ACT3_DESC = "Act 3 is finished", + ACHIEVEMENT_ACT3_HINT = "Finish 3 act", + ACHIEVEMENT_DAISY_NAME = "Daisy joined", + ACHIEVEMENT_DAISY_DESC = "Daisy has joined you", + ACHIEVEMENT_DAISY_HINT = "Find Daisy", + ACHIEVEMENT_KURDAN_NAME = "Kurdan joined", + ACHIEVEMENT_KURDAN_DESC = "Kurdan has joined you", + ACHIEVEMENT_KURDAN_HINT = "Find Kurdan", + ACHIEVEMENT_AIRE_NAME = "Aire joined", + ACHIEVEMENT_AIRE_DESC = "Aire has joined you", + ACHIEVEMENT_AIRE_HINT = "Find Aire", + ACHIEVEMENT_KURO_NAME = "Kuro joined", + ACHIEVEMENT_KURO_DESC = "Kuro has joined you", + ACHIEVEMENT_KURO_HINT = "Find Kuro", + ACHIEVEMENT_WORKER_NAME = "Worker unlocked", + ACHIEVEMENT_WORKER_DESC = "Worker class unlocked", + ACHIEVEMENT_WORKER_HINT = "Get character with worker class", + ACHIEVEMENT_HUNTER_NAME = "Hunter unlocked", + ACHIEVEMENT_HUNTER_DESC = "Hunter class unlocked", + ACHIEVEMENT_HUNTER_HINT = "Get character with Hunter class", + ACHIEVEMENT_CHEF_NAME = "Chef unlocked", + ACHIEVEMENT_CHEF_DESC = "Chef class unlocked", + ACHIEVEMENT_CHEF_HINT = "Get character with Chef class", + ACHIEVEMENT_HARLOT_NAME = "Harlot unlocked", + ACHIEVEMENT_HARLOT_DESC = "Harlot class unlocked", + ACHIEVEMENT_HARLOT_HINT = "Get character with Harlot class", + ACHIEVEMENT_DANCER_NAME = "Dancer unlocked", + ACHIEVEMENT_DANCER_DESC = "Dancer class unlocked", + ACHIEVEMENT_DANCER_HINT = "Get character with Dancer class", + ACHIEVEMENT_FIGHTER_NAME = "Fighter unlocked", + ACHIEVEMENT_FIGHTER_DESC = "Fighter class unlocked", + ACHIEVEMENT_FIGHTER_HINT = "Get character with Fighter class", + ACHIBONUS_DAISY_START = "Start with Daisy", + ACHIBONUS_DAISY_START_DESC = "Start game with Daisy", + ACHIBONUS_DAISY_START_HINT = "Get Daisy", + ACHIBONUS_KURDAN_START = "Start with Kurdan", + ACHIBONUS_KURDAN_START_DESC = "Start game with Kurdan", + ACHIBONUS_KURDAN_START_HINT = "Get Kurdan", + ACHIBONUS_AIRE_START = "Start with Aire", + ACHIBONUS_AIRE_START_DESC = "Start game with Aire", + ACHIBONUS_AIRE_START_HINT = "Get Aire", + ACHIBONUS_KURO_START = "Start with Kuro", + ACHIBONUS_KURO_START_DESC = "Start game with Kuro", + ACHIBONUS_KURO_START_HINT = "Get Kuro", INTRODIALOGUE = """Twelve years have passed since monarchy was overthrown in Aliron Kingdom. Free of the previous reign, its capital Aliron has become a center of society and cultural life, giving even the lowest a chance to become a person of power and influence assuming they are capable... You are one of the people who managed to get there just in time to secure an estate recently freed from old ownership. The only issue is that its sale price is beyond your capability. With no other option to start a new life, you've taken a gigantic loan to achieve your goal. You've become an owner of a small piece of land with a dilapidated mansion on it.""", diff --git a/src/character/CharacterClass.gd b/src/character/CharacterClass.gd index 69cf882f5..992c4721a 100644 --- a/src/character/CharacterClass.gd +++ b/src/character/CharacterClass.gd @@ -567,6 +567,7 @@ func turn_into_unique(code): if data.has('training_disposition'): process_disposition_data(data.training_disposition, true) update_prt() + input_handler.achievements.try_add_char_achimnt(get_stat('unique')) globals.emit_signal("slave_added") diff --git a/src/character/ch_dyn_stats.gd b/src/character/ch_dyn_stats.gd index c616d78ea..292c2e405 100644 --- a/src/character/ch_dyn_stats.gd +++ b/src/character/ch_dyn_stats.gd @@ -799,6 +799,7 @@ func unlock_class(prof, satisfy_progress_reqs = false): if parent.get_ref().is_in_game_party(): globals.text_log_add('char', "%s: acquired profession %s" % [parent.get_ref().get_short_name(), prof.name]) + input_handler.achievements.try_add_prof_achimnt(prof.code) func remove_class(prof_id): @@ -882,7 +883,7 @@ func get_racial_features(race): func process_chardata(chardata): for i in chardata: - if !(i in ['code', 'slave_class', 'tags','sex_traits', 'sex_skills', 'personality', 'training_disposition', 'blocked_training_traits','traits', 'food_like', 'food_hate', 'classes', 'skills', 'mastery']): + if !(i in ['code', 'slave_class', 'tags','sex_traits', 'sex_skills', 'personality', 'training_disposition', 'blocked_training_traits','traits', 'food_like', 'food_hate', 'classes', 'skills', 'mastery', 'achievement', 'achi_bonus']): var st_data = statdata.statdata[i] if !st_data.direct: set_default_value(i, chardata[i]) diff --git a/src/character/ch_stats.gd b/src/character/ch_stats.gd index 5deaeef09..642cdf0f5 100644 --- a/src/character/ch_stats.gd +++ b/src/character/ch_stats.gd @@ -1172,7 +1172,7 @@ func process_chardata(chardata, unique = false): if unique: statlist.unique = chardata.code for i in chardata: - if !(i in ['code', 'slave_class', 'tags','sex_traits', 'sex_skills', 'personality', 'training_disposition', 'blocked_training_traits', 'traits', 'food_like', 'food_hate', 'classes', 'skills', 'mastery']): + if !(i in ['code', 'slave_class', 'tags','sex_traits', 'sex_skills', 'personality', 'training_disposition', 'blocked_training_traits', 'traits', 'food_like', 'food_hate', 'classes', 'skills', 'mastery', 'achievement', 'achi_bonus']): var st_data = statdata.statdata[i] if st_data.direct: update_stat(i, chardata[i], 'set') diff --git a/src/core/achievements.gd b/src/core/achievements.gd new file mode 100644 index 000000000..c1ed7f821 --- /dev/null +++ b/src/core/achievements.gd @@ -0,0 +1,105 @@ +extends Reference + +var data = preload("res://assets/data/achievements_data.gd").new() + +func try_add_achimnt(achi_name): + if input_handler.progress_data['achievements'].has(achi_name): + return + input_handler.update_progress_data("achievements", achi_name) + input_handler.get_spec_node(input_handler.NODE_ACHI_UNLOCK).add_achi(get_achimnt(achi_name)) + +func try_unlock_bonus(bonus_name): + if input_handler.progress_data['achi_bonuses'].has(bonus_name): + return + input_handler.update_progress_data("achi_bonuses", bonus_name) + input_handler.get_spec_node(input_handler.NODE_ACHI_UNLOCK).add_bonus(get_bonus(bonus_name)) + +func try_add_quest_achimnt(quest_name): + if scenedata.quests[quest_name].has("achievement"): + try_add_achimnt(scenedata.quests[quest_name].achievement) + +func try_add_char_achimnt(unique_name): + for pregen_char in worlddata.pregen_characters.values(): + if pregen_char.has("unique") and pregen_char.unique == unique_name: + if pregen_char.has("achievement"): + try_add_achimnt(pregen_char.achievement) + if pregen_char.has("achi_bonus"): + try_unlock_bonus(pregen_char.achi_bonus) + break + +func try_add_prof_achimnt(prof): + var prof_data = classesdata.professions[prof] + if prof_data.has('achievement'): + try_add_achimnt(prof_data.achievement) + + +func get_achimnt(achi_name): + #duplicate() here is practically redundant, + #but I'm keeping it for security reasons + var res = data.achievements[achi_name].duplicate() + res.icon = load(res.icon) + return res +func get_bonus(bonus_name): + #duplicate() here is practically redundant, + #but I'm keeping it for security reasons + var res = data.bonuses[bonus_name].duplicate() + res.icon = load(res.icon) + return res + +func get_all_points(): + var points = 0 + for achi in input_handler.progress_data['achievements']: + points += data.achievements[achi].points + return points + +func prepare_bonuses(list): + for bonus in list: + if data.bonuses.has(bonus): + call(data.bonuses[bonus].preparation) + else: + push_error("no such bonus in achievements: %s!" % bonus) + +func get_unlocked_bonuses(): + var res = {} + for bonus_name in input_handler.progress_data['achi_bonuses']: + res[bonus_name] = data.bonuses[bonus_name].duplicate() + res[bonus_name].icon = load(res[bonus_name].icon) + return res + +func get_locked_bonuses(): + var res = {} + for bonus_name in data.bonuses: + if bonus_name in input_handler.progress_data['achi_bonuses']: + continue + #only hint for now + res[bonus_name] = {hint = data.bonuses[bonus_name].hint} + return res + +func get_unlocked_achimnts(): + var res = {} + for achi_name in input_handler.progress_data['achievements']: + res[achi_name] = data.achievements[achi_name].duplicate() + res[achi_name].icon = load(res[achi_name].icon) + return res + +func get_locked_achimnts(): + var res = {} + for achi_name in data.achievements: + if achi_name in input_handler.progress_data['achievements']: + continue + #only hint for now + res[achi_name] = {hint = data.achievements[achi_name].hint} + return res + +#bonus preparations +func prep_daisy_start(): + globals.common_effects([{code = 'make_story_character', value = 'Daisy'}]) + +func prep_kurdan_start(): + globals.common_effects([{code = 'make_story_character', value = 'Kurdan'}]) + +func prep_aire_start(): + globals.common_effects([{code = 'make_story_character', value = 'Aire'}]) + +func prep_kuro_start(): + globals.common_effects([{code = 'make_story_character', value = 'Kuro'}]) diff --git a/src/core/game_party.gd b/src/core/game_party.gd index 761c662ee..aadccba01 100644 --- a/src/core/game_party.gd +++ b/src/core/game_party.gd @@ -493,11 +493,14 @@ func add_slave(person, child = false): # character_order.push_back(person.id) if person.is_unique(): ResourceScripts.game_world.easter_egg_characters_acquired.append(person.get_stat('unique')) + input_handler.achievements.try_add_char_achimnt(person.get_stat('unique')) person.fill_masternoun() person.set_stat('metrics_ownership', ResourceScripts.game_globals.get_date()[0]) globals.text_log_add("char","New character acquired: " + person.get_short_name() + ". ") globals.emit_signal("slave_added") gui_controller.nav_panel.build_accessible_locations() + for prof in person.get_professions(): + input_handler.achievements.try_add_prof_achimnt(prof) func remove_slave(tempslave, permanent = false): diff --git a/src/core/globals.gd b/src/core/globals.gd index 58de5ea8a..ecae6e418 100644 --- a/src/core/globals.gd +++ b/src/core/globals.gd @@ -2262,6 +2262,7 @@ func common_effects(effects): input_handler.play_animation("quest_completed", args) break ResourceScripts.game_progress.completed_quests.append(i.value) + input_handler.achievements.try_add_quest_achimnt(i.value) 'complete_active_location': complete_location(input_handler.active_location.id) # 'set_completed_quest_location': @@ -2644,6 +2645,8 @@ func common_effects(effects): ResourceScripts.game_party.check_masters_story_fame() 'set_faction_factor': ResourceScripts.slave_quests.set_faction_factor(i.faction, i.value) + 'achievement': + input_handler.achievements.try_add_achimnt(i.value) func after_wedding_event(character): if character == null: diff --git a/src/core/input_handler.gd b/src/core/input_handler.gd index 8ecf31324..b4a528463 100644 --- a/src/core/input_handler.gd +++ b/src/core/input_handler.gd @@ -138,6 +138,7 @@ enum { NODE_ARENA, NODE_HARD_TUTORIAL_PANEL, NODE_HARD_TUTORIAL_LIST, + NODE_ACHI_UNLOCK, #Animations ANIM_TASK_AQUARED, ANIM_BATTLE_START, @@ -219,7 +220,9 @@ var progress_data = { gallery_seq = [], characters = [],#'amelia','duncan','sigmund','myr' monochrome = [], - unique_sprites = {}#daisy = [], cali = [] + unique_sprites = {},#daisy = [], cali = [] + achievements = [], + achi_bonuses = [] } setget save_progress_data #var combat_advance = false #if any result in combat cause advance @@ -238,6 +241,8 @@ var hard_tutorial_btns = { #name = {source, get_btn_func, rect_obj, rect_func} } +var achievements + func set_previous_scene(scene): PreviousScene = scene @@ -326,7 +331,6 @@ func store_progress(): func is_unique_sprite_unlocked(chara, sprite): return progress_data['unique_sprites'].has(chara) and progress_data['unique_sprites'][chara].has(sprite) - func _notification(what): if what == MainLoop.NOTIFICATION_WM_QUIT_REQUEST: quit() @@ -386,6 +390,7 @@ func _ready(): connect("UpgradeUnlocked", self, "upgrade_unlocked") connect("animation_finished", self, "animation_queue_start_force") + achievements = load("res://src/core/achievements.gd").new() func gather_skills_effects(): From 7eabb294468eb4428ce23b0604a997bd005d7968 Mon Sep 17 00:00:00 2001 From: Kiremon-work Date: Tue, 3 Mar 2026 16:08:49 +0600 Subject: [PATCH 2/4] fix for forfit bug on loc and dungeon quests --- gui_modules/Mansion/Scripts/MansionJournalModule.gd | 8 +------- src/core/game_world.gd | 3 ++- src/core/globals.gd | 7 ++++--- src/core/input_handler.gd | 2 ++ src/core/world_gen.gd | 5 +++++ 5 files changed, 14 insertions(+), 11 deletions(-) diff --git a/gui_modules/Mansion/Scripts/MansionJournalModule.gd b/gui_modules/Mansion/Scripts/MansionJournalModule.gd index 8ff6060b0..ce6b32b6e 100644 --- a/gui_modules/Mansion/Scripts/MansionJournalModule.gd +++ b/gui_modules/Mansion/Scripts/MansionJournalModule.gd @@ -203,15 +203,9 @@ func CompleteReqs(): match i.code: "random_material": ResourceScripts.game_res.set_material(i.type, '-', i.value) - selectedquest.state = 'complete' ResourceScripts.slave_quests.check_faction_rating(selectedquest) globals.text_log_add("quest", tr("QUESTCOMPLETEMESSAGE")+": " + tr(selectedquest.name)) - #NOTE, that only quest of "complete_location" with flag "no_autocomplet" should use this code - #of "unquest_location" and "remove_location". If vice versa, it is an error - for i in selectedquest.requirements: - if i.code == "complete_location": - globals.unquest_location(i.location) - globals.remove_location(i.location) + ResourceScripts.game_world.complete_quest(selectedquest, 'complete') Reward() var char_reqs diff --git a/src/core/game_world.gd b/src/core/game_world.gd index 29ff9df3f..ac6170466 100644 --- a/src/core/game_world.gd +++ b/src/core/game_world.gd @@ -418,7 +418,8 @@ func complete_quest(quest, state = 'failed'): ResourceScripts.game_party.remove_quest_task(quest.id) for i in quest.requirements: if i.code in ['complete_location','complete_dungeon']: - #maybe here should be difference (remove or unquest) between quest dungeons and encounters or complete_location and complete_dungeon - its up to you + if i.code == 'complete_location':#dungeon should not be removed + globals.remove_location(i.location) globals.unquest_location(i.location) diff --git a/src/core/globals.gd b/src/core/globals.gd index ecae6e418..e8eac7e9a 100644 --- a/src/core/globals.gd +++ b/src/core/globals.gd @@ -2333,9 +2333,10 @@ func common_effects(effects): 'complete_active_location_quests': if input_handler.active_location.has('questid'): var quest = ResourceScripts.game_world.get_quest_by_id(input_handler.active_location.questid) - for req in quest.requirements: - if req.code in ['complete_location','complete_dungeon'] && req.area == input_handler.active_area.code && req.location == input_handler.active_location.id: - req.completed = true + if quest != null:#can be forfited + for req in quest.requirements: + if req.code in ['complete_location','complete_dungeon'] && req.area == input_handler.active_area.code && req.location == input_handler.active_location.id: + req.completed = true 'affect_active_party': for k in input_handler.get_active_party(): k.affect_char(i, true) diff --git a/src/core/input_handler.gd b/src/core/input_handler.gd index b4a528463..d9b724233 100644 --- a/src/core/input_handler.gd +++ b/src/core/input_handler.gd @@ -1291,6 +1291,8 @@ func mark_quest_location_completed(args): func autocomplete_quest(q_id): var questdata = ResourceScripts.game_world.get_quest_by_id(q_id) + if questdata == null or questdata.state == 'failed':#was forfit + return selectedquest = questdata play_animation("repeatable_quest_completed") PlaySound("questcomplete") diff --git a/src/core/world_gen.gd b/src/core/world_gen.gd index cee212674..90ca514b9 100644 --- a/src/core/world_gen.gd +++ b/src/core/world_gen.gd @@ -737,6 +737,11 @@ func make_repeatable_quest_location(quest,area,req): locationdata.scriptedevents.append(i.duplicate(true)) locationdata.events.clear() if req.has("no_autocomplete"): + #mind that there is `complete_active_location_quests` common effect, which in other + #cases makes the same action as in `mark_quest_location_completed`, but should be added + #manually in encounter. + #I'm still keeping this for `no_autocomplete` case, because it's more consistent + #than manual common effect locationdata.scriptedevents.append({trigger = 'finish_combat', event = 'mark_quest_location_completed', reqs = [], args = {id = quest.id}}) else: locationdata.scriptedevents.append({trigger = 'finish_combat', event = 'finish_quest_location', reqs = [], args = {id = quest.id, source = quest.source, area = quest.area}}) From 5080f4f9c3315486b00d7b89ddcaf970bc935e86 Mon Sep 17 00:00:00 2001 From: Kiremon-work Date: Tue, 3 Mar 2026 17:31:57 +0600 Subject: [PATCH 3/4] fix for bottom loc list in SlaveListModule --- gui_modules/Mansion/Scripts/MansionSlaveListModule.gd | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gui_modules/Mansion/Scripts/MansionSlaveListModule.gd b/gui_modules/Mansion/Scripts/MansionSlaveListModule.gd index 275ab3ad7..d8f75685c 100644 --- a/gui_modules/Mansion/Scripts/MansionSlaveListModule.gd +++ b/gui_modules/Mansion/Scripts/MansionSlaveListModule.gd @@ -11,7 +11,7 @@ onready var CharacterContextMenu = $CharacterContextMenu var populatedlocations = [] var default_locations = ["show_all", "mansion"] -var selected_location = "mansion" +var selected_location = "aliron" var prev_selected_location = "show_all" var visible_persons = [] @@ -470,6 +470,7 @@ func show_location_characters(button = null): if visible_persons.size() < 1 and selected_location != "show_all": selected_location = "show_all" show_location_characters() + update_location_buttons() func update_location_buttons(): From f406d8185065dd43cf8b5ad4b82cbafac6df25ef Mon Sep 17 00:00:00 2001 From: Kiremon-work Date: Wed, 4 Mar 2026 00:48:56 +0600 Subject: [PATCH 4/4] additional fix for quest forfit bug --- src/core/input_handler.gd | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/input_handler.gd b/src/core/input_handler.gd index d9b724233..9c61f8458 100644 --- a/src/core/input_handler.gd +++ b/src/core/input_handler.gd @@ -1281,7 +1281,8 @@ func finish_quest_dungeon(args): func finish_quest_location(args): autocomplete_quest(args.id) - exploration_node.clear_dungeon_confirm() + #autocomplete_quest() can now remove location +# exploration_node.clear_dungeon_confirm() func mark_quest_location_completed(args): var questdata = ResourceScripts.game_world.get_quest_by_id(args.id)