commit a4bbe43f87ef4325c20b2c7a46843395a5799100 Author: iisaev Date: Thu Sep 10 10:59:36 2026 +0300 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c301ca8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,37 @@ +# Godot 4.x +.godot/ +.idea/ +sdk/ +bin/ +obj/ + +#ai +.omo/ +.opencode/ + +gen/ +obj/ +bin/ + +*.tres~ +*.tscn~ + +# GDScript LSP +.godot/ + +# Export +*.exe +*.dmg +*.apk +*.aab +*.pck +*.zip +*.log + +# OS +.DS_Store +Thumbs.db + +# Editor +*.import +*.godot.uid diff --git a/avatars/marao/sad.png b/avatars/marao/sad.png new file mode 100644 index 0000000..0c70266 Binary files /dev/null and b/avatars/marao/sad.png differ diff --git a/avatars/marao/smile.png b/avatars/marao/smile.png new file mode 100644 index 0000000..7ed7a9f Binary files /dev/null and b/avatars/marao/smile.png differ diff --git a/avatars/marao/think.png b/avatars/marao/think.png new file mode 100644 index 0000000..037e12d Binary files /dev/null and b/avatars/marao/think.png differ diff --git a/backgrounds/00006-4133256041.png b/backgrounds/00006-4133256041.png new file mode 100644 index 0000000..4db2e7f Binary files /dev/null and b/backgrounds/00006-4133256041.png differ diff --git a/backgrounds/black.png b/backgrounds/black.png new file mode 100644 index 0000000..3cf27f4 Binary files /dev/null and b/backgrounds/black.png differ diff --git a/backgrounds/empty.png b/backgrounds/empty.png new file mode 100644 index 0000000..fdf950d Binary files /dev/null and b/backgrounds/empty.png differ diff --git a/backgrounds/empty_lightmap.png b/backgrounds/empty_lightmap.png new file mode 100644 index 0000000..8c3d6f2 Binary files /dev/null and b/backgrounds/empty_lightmap.png differ diff --git a/backgrounds/home/basement.png b/backgrounds/home/basement.png new file mode 100644 index 0000000..c4ec04f Binary files /dev/null and b/backgrounds/home/basement.png differ diff --git a/backgrounds/home/basement_depth.png b/backgrounds/home/basement_depth.png new file mode 100644 index 0000000..ea6ca5c Binary files /dev/null and b/backgrounds/home/basement_depth.png differ diff --git a/backgrounds/home/bedroom.png b/backgrounds/home/bedroom.png new file mode 100644 index 0000000..5227844 Binary files /dev/null and b/backgrounds/home/bedroom.png differ diff --git a/backgrounds/home/bedroom_depth.png b/backgrounds/home/bedroom_depth.png new file mode 100644 index 0000000..96b45e7 Binary files /dev/null and b/backgrounds/home/bedroom_depth.png differ diff --git a/backgrounds/home/kitchen.png b/backgrounds/home/kitchen.png new file mode 100644 index 0000000..a746260 Binary files /dev/null and b/backgrounds/home/kitchen.png differ diff --git a/backgrounds/home/kitchen_depth.pdn b/backgrounds/home/kitchen_depth.pdn new file mode 100644 index 0000000..762c03e Binary files /dev/null and b/backgrounds/home/kitchen_depth.pdn differ diff --git a/backgrounds/home/kitchen_depth.png b/backgrounds/home/kitchen_depth.png new file mode 100644 index 0000000..594bf69 Binary files /dev/null and b/backgrounds/home/kitchen_depth.png differ diff --git a/backgrounds/home/outside.png b/backgrounds/home/outside.png new file mode 100644 index 0000000..f13aa9a Binary files /dev/null and b/backgrounds/home/outside.png differ diff --git a/backgrounds/home/outside_albedo.png b/backgrounds/home/outside_albedo.png new file mode 100644 index 0000000..4fe44e4 Binary files /dev/null and b/backgrounds/home/outside_albedo.png differ diff --git a/backgrounds/home/outside_depth.png b/backgrounds/home/outside_depth.png new file mode 100644 index 0000000..b94a966 Binary files /dev/null and b/backgrounds/home/outside_depth.png differ diff --git a/backgrounds/home/vestibule.png b/backgrounds/home/vestibule.png new file mode 100644 index 0000000..9592df5 Binary files /dev/null and b/backgrounds/home/vestibule.png differ diff --git a/backgrounds/home/vestibule_depth.png b/backgrounds/home/vestibule_depth.png new file mode 100644 index 0000000..1459513 Binary files /dev/null and b/backgrounds/home/vestibule_depth.png differ diff --git a/backgrounds/home/workroom.png b/backgrounds/home/workroom.png new file mode 100644 index 0000000..f1d14ec Binary files /dev/null and b/backgrounds/home/workroom.png differ diff --git a/backgrounds/home/workroom_depth.png b/backgrounds/home/workroom_depth.png new file mode 100644 index 0000000..34c2b2b Binary files /dev/null and b/backgrounds/home/workroom_depth.png differ diff --git a/backgrounds/prolog/00021-1983628424.png b/backgrounds/prolog/00021-1983628424.png new file mode 100644 index 0000000..558c5b4 Binary files /dev/null and b/backgrounds/prolog/00021-1983628424.png differ diff --git a/backgrounds/prolog/book_ground.png b/backgrounds/prolog/book_ground.png new file mode 100644 index 0000000..a18797e Binary files /dev/null and b/backgrounds/prolog/book_ground.png differ diff --git a/backgrounds/prolog/cloak_ground.png b/backgrounds/prolog/cloak_ground.png new file mode 100644 index 0000000..a18797e Binary files /dev/null and b/backgrounds/prolog/cloak_ground.png differ diff --git a/backgrounds/prolog/marao_1.png b/backgrounds/prolog/marao_1.png new file mode 100644 index 0000000..b6c9a39 Binary files /dev/null and b/backgrounds/prolog/marao_1.png differ diff --git a/backgrounds/prolog/marao_preview.png b/backgrounds/prolog/marao_preview.png new file mode 100644 index 0000000..3d24b90 Binary files /dev/null and b/backgrounds/prolog/marao_preview.png differ diff --git a/backgrounds/prolog/start_lane.png b/backgrounds/prolog/start_lane.png new file mode 100644 index 0000000..534c2e8 Binary files /dev/null and b/backgrounds/prolog/start_lane.png differ diff --git a/backgrounds/prolog/start_lane_albedo.png b/backgrounds/prolog/start_lane_albedo.png new file mode 100644 index 0000000..9437e63 Binary files /dev/null and b/backgrounds/prolog/start_lane_albedo.png differ diff --git a/backgrounds/prolog/start_lane_depth.png b/backgrounds/prolog/start_lane_depth.png new file mode 100644 index 0000000..7b4f609 Binary files /dev/null and b/backgrounds/prolog/start_lane_depth.png differ diff --git a/backgrounds/prolog/take_cloack.png b/backgrounds/prolog/take_cloack.png new file mode 100644 index 0000000..f92ba8c Binary files /dev/null and b/backgrounds/prolog/take_cloack.png differ diff --git a/backgrounds/town/town_entry_0.png b/backgrounds/town/town_entry_0.png new file mode 100644 index 0000000..f7b4a81 Binary files /dev/null and b/backgrounds/town/town_entry_0.png differ diff --git a/backgrounds/town/town_entry_0_depth.png b/backgrounds/town/town_entry_0_depth.png new file mode 100644 index 0000000..f26af69 Binary files /dev/null and b/backgrounds/town/town_entry_0_depth.png differ diff --git a/backgrounds/town/town_entry_1.png b/backgrounds/town/town_entry_1.png new file mode 100644 index 0000000..ece68b9 Binary files /dev/null and b/backgrounds/town/town_entry_1.png differ diff --git a/backgrounds/town/town_entry_1_depth.png b/backgrounds/town/town_entry_1_depth.png new file mode 100644 index 0000000..7fead71 Binary files /dev/null and b/backgrounds/town/town_entry_1_depth.png differ diff --git a/backgrounds/town/town_entry_2.png b/backgrounds/town/town_entry_2.png new file mode 100644 index 0000000..4368335 Binary files /dev/null and b/backgrounds/town/town_entry_2.png differ diff --git a/backgrounds/town/town_entry_2_depth.png b/backgrounds/town/town_entry_2_depth.png new file mode 100644 index 0000000..c9a63c1 Binary files /dev/null and b/backgrounds/town/town_entry_2_depth.png differ diff --git a/backgrounds/town/town_entry_3.png b/backgrounds/town/town_entry_3.png new file mode 100644 index 0000000..b18a791 Binary files /dev/null and b/backgrounds/town/town_entry_3.png differ diff --git a/backgrounds/town/town_entry_3_depth.png b/backgrounds/town/town_entry_3_depth.png new file mode 100644 index 0000000..034b12e Binary files /dev/null and b/backgrounds/town/town_entry_3_depth.png differ diff --git a/backgrounds/town/town_entry_4.png b/backgrounds/town/town_entry_4.png new file mode 100644 index 0000000..cfd57f4 Binary files /dev/null and b/backgrounds/town/town_entry_4.png differ diff --git a/backgrounds/town/town_entry_4_depth.png b/backgrounds/town/town_entry_4_depth.png new file mode 100644 index 0000000..ae78287 Binary files /dev/null and b/backgrounds/town/town_entry_4_depth.png differ diff --git a/characters/actions.json b/characters/actions.json new file mode 100644 index 0000000..fc7f09a --- /dev/null +++ b/characters/actions.json @@ -0,0 +1,5 @@ +{ "Items": [ + ${actions/physics_attack}, + ${actions/physics_defence}, + ${actions/physics_stun} +]} \ No newline at end of file diff --git a/characters/actions/physics_attack.json b/characters/actions/physics_attack.json new file mode 100644 index 0000000..6f061fe --- /dev/null +++ b/characters/actions/physics_attack.json @@ -0,0 +1,12 @@ +{ + "Id": "physics/attack", + "Name": "characters/action/physics_attack/name", + "Description": "characters/action/physics_attack/description", + "Image": "characters/actions/physics_attack", + "Type": "ToEnemy", + "Values": [ + "RequiredPoint=1", + "Attack=1.0", + "AttackType=Physics" + ] +} \ No newline at end of file diff --git a/characters/actions/physics_attack.png b/characters/actions/physics_attack.png new file mode 100644 index 0000000..3c82744 Binary files /dev/null and b/characters/actions/physics_attack.png differ diff --git a/characters/actions/physics_defence.json b/characters/actions/physics_defence.json new file mode 100644 index 0000000..7465c31 --- /dev/null +++ b/characters/actions/physics_defence.json @@ -0,0 +1,11 @@ +{ + "Id": "physics/defence", + "Name": "characters/action/defence/name", + "Description": "characters/action/defence/description", + "Image": "characters/actions/physics_defence", + "Type": "ToAlias", + "Values": [ + "RequiredPoint=1", + "Defence=4" + ] +} \ No newline at end of file diff --git a/characters/actions/physics_defence.png b/characters/actions/physics_defence.png new file mode 100644 index 0000000..2ea0797 Binary files /dev/null and b/characters/actions/physics_defence.png differ diff --git a/characters/actions/physics_stun.json b/characters/actions/physics_stun.json new file mode 100644 index 0000000..ecff35d --- /dev/null +++ b/characters/actions/physics_stun.json @@ -0,0 +1,12 @@ +{ + "Id": "physics/stun", + "Name": "characters/action/stun/name", + "Description": "characters/action/stun/description", + "Image": "characters/actions/physics_stun", + "Type": "ToEnemy", + "Values": [ + "RequiredPoint=2", + "AttackType=Physics", + "Turn=3" + ] +} \ No newline at end of file diff --git a/characters/actions/physics_stun.png b/characters/actions/physics_stun.png new file mode 100644 index 0000000..f97dbc6 Binary files /dev/null and b/characters/actions/physics_stun.png differ diff --git a/characters/characters.json b/characters/characters.json new file mode 100644 index 0000000..e5190fa --- /dev/null +++ b/characters/characters.json @@ -0,0 +1,3 @@ +{ "Items": [ + ${player/marao} +]} \ No newline at end of file diff --git a/characters/effects/stun.png b/characters/effects/stun.png new file mode 100644 index 0000000..faf9859 Binary files /dev/null and b/characters/effects/stun.png differ diff --git a/characters/enemies.json b/characters/enemies.json new file mode 100644 index 0000000..8934687 --- /dev/null +++ b/characters/enemies.json @@ -0,0 +1,13 @@ +{ "Items": [ + ${enemies/wolf_1}, + ${enemies/wolf_2}, + ${enemies/wolf_3}, + ${enemies/wolf_4}, + ${enemies/wolf_5}, + ${enemies/wolf_6}, + ${enemies/wolf_7}, + ${enemies/wolf_8}, + ${enemies/wolf_9}, + ${enemies/wolf_10}, + ${enemies/werewolf_girl_1} +]} \ No newline at end of file diff --git a/characters/enemies/werewolf_girl_1.json b/characters/enemies/werewolf_girl_1.json new file mode 100644 index 0000000..f4b9bc1 --- /dev/null +++ b/characters/enemies/werewolf_girl_1.json @@ -0,0 +1,20 @@ +{ + "Id": "werewolf_girl_1", + "Name": "characters/enemies/werewolf_girl", + "Image": "characters/enemies/werewolf_girl_1", + "Behaviour": "base", + + "Level": 1, + "Point": 1, + "Health": 25, + "Defence": 0, + "Attack": 8, + "Exp": 50, + + "RecruitmentChance": 50, + + "Actions": ["physics/attack", "physics/defence"], + "Loot": [ + { "ItemId": "food/wolf_meat", "MinCount": 2, "MaxCount": 2, "Probability": 100 } + ] +} \ No newline at end of file diff --git a/characters/enemies/werewolf_girl_1.png b/characters/enemies/werewolf_girl_1.png new file mode 100644 index 0000000..ba77aff Binary files /dev/null and b/characters/enemies/werewolf_girl_1.png differ diff --git a/characters/enemies/wolf_1.json b/characters/enemies/wolf_1.json new file mode 100644 index 0000000..721c826 --- /dev/null +++ b/characters/enemies/wolf_1.json @@ -0,0 +1,20 @@ +{ + "Id": "wolf_1", + "Name": "characters/enemies/wolf", + "Image": "characters/enemies/wolf_1", + "Behaviour": "base", + + "Level": 1, + "Point": 1, + "Health": 15, + "Defence": 0, + "Attack": 4, + "Exp": 5, + "RecruitmentChance": 0, + + "Actions": ["physics/attack", "physics/defence"], + "Loot": [ + { "ItemId": "food/wolf_meat", "MinCount": 1, "MaxCount": 1, "Probability": 100 }, + { "ItemId": "resource/branches", "MinCount": 1, "MaxCount": 1, "Probability": 100 } + ] +} \ No newline at end of file diff --git a/characters/enemies/wolf_1.png b/characters/enemies/wolf_1.png new file mode 100644 index 0000000..74ad137 Binary files /dev/null and b/characters/enemies/wolf_1.png differ diff --git a/characters/enemies/wolf_10.json b/characters/enemies/wolf_10.json new file mode 100644 index 0000000..f5946f1 --- /dev/null +++ b/characters/enemies/wolf_10.json @@ -0,0 +1,20 @@ +{ + "Id": "wolf_10", + "Name": "characters/enemies/wolf", + "Image": "characters/enemies/wolf_10", + "Behaviour": "base", + + "Level": 1, + "Point": 1, + "Health": 15, + "Defence": 0, + "Attack": 4, + "Exp": 5, + "RecruitmentChance": 0, + + "Actions": ["physics/attack", "physics/defence"], + "Loot": [ + { "ItemId": "food/wolf_meat", "MinCount": 1, "MaxCount": 1, "Probability": 100 }, + { "ItemId": "resource/branches", "MinCount": 1, "MaxCount": 1, "Probability": 100 } + ] +} \ No newline at end of file diff --git a/characters/enemies/wolf_10.png b/characters/enemies/wolf_10.png new file mode 100644 index 0000000..3402270 Binary files /dev/null and b/characters/enemies/wolf_10.png differ diff --git a/characters/enemies/wolf_2.json b/characters/enemies/wolf_2.json new file mode 100644 index 0000000..e2d5517 --- /dev/null +++ b/characters/enemies/wolf_2.json @@ -0,0 +1,20 @@ +{ + "Id": "wolf_2", + "Name": "characters/enemies/wolf", + "Image": "characters/enemies/wolf_2", + "Behaviour": "base", + + "Level": 1, + "Point": 1, + "Health": 15, + "Defence": 0, + "Attack": 4, + "Exp": 5, + "RecruitmentChance": 0, + + "Actions": ["physics/attack", "physics/defence"], + "Loot": [ + { "ItemId": "food/wolf_meat", "MinCount": 1, "MaxCount": 1, "Probability": 100 }, + { "ItemId": "resource/branches", "MinCount": 1, "MaxCount": 1, "Probability": 100 } + ] +} \ No newline at end of file diff --git a/characters/enemies/wolf_2.png b/characters/enemies/wolf_2.png new file mode 100644 index 0000000..55babbb Binary files /dev/null and b/characters/enemies/wolf_2.png differ diff --git a/characters/enemies/wolf_3.json b/characters/enemies/wolf_3.json new file mode 100644 index 0000000..eac8eb6 --- /dev/null +++ b/characters/enemies/wolf_3.json @@ -0,0 +1,20 @@ +{ + "Id": "wolf_3", + "Name": "characters/enemies/wolf", + "Image": "characters/enemies/wolf_3", + "Behaviour": "base", + + "Level": 1, + "Point": 1, + "Health": 15, + "Defence": 0, + "Attack": 4, + "Exp": 5, + "RecruitmentChance": 0, + + "Actions": ["physics/attack", "physics/defence"], + "Loot": [ + { "ItemId": "food/wolf_meat", "MinCount": 1, "MaxCount": 1, "Probability": 100 }, + { "ItemId": "resource/branches", "MinCount": 1, "MaxCount": 1, "Probability": 100 } + ] +} \ No newline at end of file diff --git a/characters/enemies/wolf_3.png b/characters/enemies/wolf_3.png new file mode 100644 index 0000000..758d6b8 Binary files /dev/null and b/characters/enemies/wolf_3.png differ diff --git a/characters/enemies/wolf_4.json b/characters/enemies/wolf_4.json new file mode 100644 index 0000000..088ec65 --- /dev/null +++ b/characters/enemies/wolf_4.json @@ -0,0 +1,20 @@ +{ + "Id": "wolf_4", + "Name": "characters/enemies/wolf", + "Image": "characters/enemies/wolf_4", + "Behaviour": "base", + + "Level": 1, + "Point": 1, + "Health": 15, + "Defence": 0, + "Attack": 4, + "Exp": 5, + "RecruitmentChance": 0, + + "Actions": ["physics/attack", "physics/defence"], + "Loot": [ + { "ItemId": "food/wolf_meat", "MinCount": 1, "MaxCount": 1, "Probability": 100 }, + { "ItemId": "resource/branches", "MinCount": 1, "MaxCount": 1, "Probability": 100 } + ] +} \ No newline at end of file diff --git a/characters/enemies/wolf_4.png b/characters/enemies/wolf_4.png new file mode 100644 index 0000000..369463c Binary files /dev/null and b/characters/enemies/wolf_4.png differ diff --git a/characters/enemies/wolf_5.json b/characters/enemies/wolf_5.json new file mode 100644 index 0000000..a25ea26 --- /dev/null +++ b/characters/enemies/wolf_5.json @@ -0,0 +1,20 @@ +{ + "Id": "wolf_5", + "Name": "characters/enemies/wolf", + "Image": "characters/enemies/wolf_5", + "Behaviour": "base", + + "Level": 1, + "Point": 1, + "Health": 15, + "Defence": 0, + "Attack": 4, + "Exp": 5, + "RecruitmentChance": 0, + + "Actions": ["physics/attack", "physics/defence"], + "Loot": [ + { "ItemId": "food/wolf_meat", "MinCount": 1, "MaxCount": 1, "Probability": 100 }, + { "ItemId": "resource/branches", "MinCount": 1, "MaxCount": 1, "Probability": 100 } + ] +} \ No newline at end of file diff --git a/characters/enemies/wolf_5.png b/characters/enemies/wolf_5.png new file mode 100644 index 0000000..c241c60 Binary files /dev/null and b/characters/enemies/wolf_5.png differ diff --git a/characters/enemies/wolf_6.json b/characters/enemies/wolf_6.json new file mode 100644 index 0000000..537dae2 --- /dev/null +++ b/characters/enemies/wolf_6.json @@ -0,0 +1,20 @@ +{ + "Id": "wolf_6", + "Name": "characters/enemies/wolf", + "Image": "characters/enemies/wolf_6", + "Behaviour": "base", + + "Level": 1, + "Point": 1, + "Health": 15, + "Defence": 0, + "Attack": 4, + "Exp": 5, + "RecruitmentChance": 0, + + "Actions": ["physics/attack", "physics/defence"], + "Loot": [ + { "ItemId": "food/wolf_meat", "MinCount": 1, "MaxCount": 1, "Probability": 100 }, + { "ItemId": "resource/branches", "MinCount": 1, "MaxCount": 1, "Probability": 100 } + ] +} \ No newline at end of file diff --git a/characters/enemies/wolf_6.png b/characters/enemies/wolf_6.png new file mode 100644 index 0000000..4380c6f Binary files /dev/null and b/characters/enemies/wolf_6.png differ diff --git a/characters/enemies/wolf_7.json b/characters/enemies/wolf_7.json new file mode 100644 index 0000000..4e27fa4 --- /dev/null +++ b/characters/enemies/wolf_7.json @@ -0,0 +1,20 @@ +{ + "Id": "wolf_7", + "Name": "characters/enemies/wolf", + "Image": "characters/enemies/wolf_7", + "Behaviour": "base", + + "Level": 1, + "Point": 1, + "Health": 15, + "Defence": 0, + "Attack": 4, + "Exp": 5, + "RecruitmentChance": 0, + + "Actions": ["physics/attack", "physics/defence"], + "Loot": [ + { "ItemId": "food/wolf_meat", "MinCount": 1, "MaxCount": 1, "Probability": 100 }, + { "ItemId": "resource/branches", "MinCount": 1, "MaxCount": 1, "Probability": 100 } + ] +} \ No newline at end of file diff --git a/characters/enemies/wolf_7.png b/characters/enemies/wolf_7.png new file mode 100644 index 0000000..6f34c28 Binary files /dev/null and b/characters/enemies/wolf_7.png differ diff --git a/characters/enemies/wolf_8.json b/characters/enemies/wolf_8.json new file mode 100644 index 0000000..d12ace4 --- /dev/null +++ b/characters/enemies/wolf_8.json @@ -0,0 +1,20 @@ +{ + "Id": "wolf_8", + "Name": "characters/enemies/wolf", + "Image": "characters/enemies/wolf_8", + "Behaviour": "base", + + "Level": 1, + "Point": 1, + "Health": 15, + "Defence": 0, + "Attack": 4, + "Exp": 5, + "RecruitmentChance": 0, + + "Actions": ["physics/attack", "physics/defence"], + "Loot": [ + { "ItemId": "food/wolf_meat", "MinCount": 1, "MaxCount": 1, "Probability": 100 }, + { "ItemId": "resource/branches", "MinCount": 1, "MaxCount": 1, "Probability": 100 } + ] +} \ No newline at end of file diff --git a/characters/enemies/wolf_8.png b/characters/enemies/wolf_8.png new file mode 100644 index 0000000..0a94c12 Binary files /dev/null and b/characters/enemies/wolf_8.png differ diff --git a/characters/enemies/wolf_9.json b/characters/enemies/wolf_9.json new file mode 100644 index 0000000..8308c96 --- /dev/null +++ b/characters/enemies/wolf_9.json @@ -0,0 +1,20 @@ +{ + "Id": "wolf_9", + "Name": "characters/enemies/wolf", + "Image": "characters/enemies/wolf_9", + "Behaviour": "base", + + "Level": 1, + "Point": 1, + "Health": 15, + "Defence": 0, + "Attack": 4, + "Exp": 5, + "RecruitmentChance": 0, + + "Actions": ["physics/attack", "physics/defence"], + "Loot": [ + { "ItemId": "food/wolf_meat", "MinCount": 1, "MaxCount": 1, "Probability": 100 }, + { "ItemId": "resource/branches", "MinCount": 1, "MaxCount": 1, "Probability": 100 } + ] +} \ No newline at end of file diff --git a/characters/enemies/wolf_9.png b/characters/enemies/wolf_9.png new file mode 100644 index 0000000..6f69fbc Binary files /dev/null and b/characters/enemies/wolf_9.png differ diff --git a/characters/player/marao.json b/characters/player/marao.json new file mode 100644 index 0000000..1722511 --- /dev/null +++ b/characters/player/marao.json @@ -0,0 +1,13 @@ +{ + "Id": "Marao", + "Name": "characters/player/marao", + "Image": "characters/player/marao", + + "Level": 1, + "Point": 1, + "Health": 16, + "Defence": 0, + "Attack": 5, + + "Actions": ["physics/attack", "physics/defence"] +} \ No newline at end of file diff --git a/characters/player/marao.png b/characters/player/marao.png new file mode 100644 index 0000000..dd10b81 Binary files /dev/null and b/characters/player/marao.png differ diff --git a/characters/skills.json b/characters/skills.json new file mode 100644 index 0000000..e49d189 --- /dev/null +++ b/characters/skills.json @@ -0,0 +1,3 @@ +{ "Items": [ + ${skills/slave_master} +]} \ No newline at end of file diff --git a/characters/skills/slave_master.json b/characters/skills/slave_master.json new file mode 100644 index 0000000..3d573ee --- /dev/null +++ b/characters/skills/slave_master.json @@ -0,0 +1,8 @@ +{ + "Id": "slave_master", + "Name": "characters/skills/slave_master_name", + "Description": "characters/skills/slave_master", + "Image": "characters/skills/slave_master", + "Type": 1, + "Rare": 3 +} \ No newline at end of file diff --git a/effects/00275-1947611809.png b/effects/00275-1947611809.png new file mode 100644 index 0000000..afdfc10 Binary files /dev/null and b/effects/00275-1947611809.png differ diff --git a/effects/00276-1947611809.png b/effects/00276-1947611809.png new file mode 100644 index 0000000..76c944b Binary files /dev/null and b/effects/00276-1947611809.png differ diff --git a/effects/00277-1947611809.png b/effects/00277-1947611809.png new file mode 100644 index 0000000..ca12a17 Binary files /dev/null and b/effects/00277-1947611809.png differ diff --git a/effects/00278-1947611809.png b/effects/00278-1947611809.png new file mode 100644 index 0000000..95da069 Binary files /dev/null and b/effects/00278-1947611809.png differ diff --git a/effects/00279-1947611809.png b/effects/00279-1947611809.png new file mode 100644 index 0000000..7068a7e Binary files /dev/null and b/effects/00279-1947611809.png differ diff --git a/effects/00280-2887412231.png b/effects/00280-2887412231.png new file mode 100644 index 0000000..bdb417e Binary files /dev/null and b/effects/00280-2887412231.png differ diff --git a/effects/00282-2887412231.png b/effects/00282-2887412231.png new file mode 100644 index 0000000..6381b23 Binary files /dev/null and b/effects/00282-2887412231.png differ diff --git a/effects/00283-2887412231.png b/effects/00283-2887412231.png new file mode 100644 index 0000000..1ddce8d Binary files /dev/null and b/effects/00283-2887412231.png differ diff --git a/effects/00285-2887412231.png b/effects/00285-2887412231.png new file mode 100644 index 0000000..3f0e1c0 Binary files /dev/null and b/effects/00285-2887412231.png differ diff --git a/effects/00287-2887412231.png b/effects/00287-2887412231.png new file mode 100644 index 0000000..a394294 Binary files /dev/null and b/effects/00287-2887412231.png differ diff --git a/effects/cards/stun_effect.png b/effects/cards/stun_effect.png new file mode 100644 index 0000000..faf9859 Binary files /dev/null and b/effects/cards/stun_effect.png differ diff --git a/effects/gradient.png b/effects/gradient.png new file mode 100644 index 0000000..315009b Binary files /dev/null and b/effects/gradient.png differ diff --git a/effects/points.png b/effects/points.png new file mode 100644 index 0000000..ba09644 Binary files /dev/null and b/effects/points.png differ diff --git a/effects/points2.png b/effects/points2.png new file mode 100644 index 0000000..2402afa Binary files /dev/null and b/effects/points2.png differ diff --git a/effects/select.png b/effects/select.png new file mode 100644 index 0000000..bab3f61 Binary files /dev/null and b/effects/select.png differ diff --git a/effects/splash_00.png b/effects/splash_00.png new file mode 100644 index 0000000..31a0c19 Binary files /dev/null and b/effects/splash_00.png differ diff --git a/effects/splash_01.png b/effects/splash_01.png new file mode 100644 index 0000000..6cb07f5 Binary files /dev/null and b/effects/splash_01.png differ diff --git a/effects/splash_02.png b/effects/splash_02.png new file mode 100644 index 0000000..72b81fa Binary files /dev/null and b/effects/splash_02.png differ diff --git a/effects/stun_effect.png b/effects/stun_effect.png new file mode 100644 index 0000000..b45215e Binary files /dev/null and b/effects/stun_effect.png differ diff --git a/effects/webcells.png b/effects/webcells.png new file mode 100644 index 0000000..ba42192 Binary files /dev/null and b/effects/webcells.png differ diff --git a/interactives/graveyard_interactives.json b/interactives/graveyard_interactives.json new file mode 100644 index 0000000..123c177 --- /dev/null +++ b/interactives/graveyard_interactives.json @@ -0,0 +1,28 @@ +{ + "Items": [ + { + "id": "crypt_spot", + "layer": "foreground", + "zIndex": 5, + "enabled": true, + "visible": true, + "cursor": "PointingHand", + "hitArea": { "type": "rect", "x": 0.55, "y": 0.35, "width": 0.22, "height": 0.45 }, + "actions": { + "onClick": { "scenario": "scenarios/prolog/graveyard_read.scenario" } + } + }, + { + "id": "book_wipe", + "layer": "foreground", + "zIndex": 6, + "enabled": true, + "visible": true, + "cursor": "PointingHand", + "hitArea": { "type": "rect", "x": 0.30, "y": 0.62, "width": 0.12, "height": 0.12 }, + "actions": { + "onClick": { "scenario": "scenarios/prolog/graveyard_azif.scenario" } + } + } + ] +} diff --git a/interactives/morning_interactives.json b/interactives/morning_interactives.json new file mode 100644 index 0000000..f3ab637 --- /dev/null +++ b/interactives/morning_interactives.json @@ -0,0 +1,39 @@ +{ + "Items": [ + { + "id": "cloak_ground", + "texture": "cloak_ground", + "layer": "foreground", + "zIndex": 5, + "enabled": true, + "visible": true, + "cursor": "PointingHand", + "hitArea": { + "type": "rect", + "x": 0.27239782, + "y": 0.7092288, + "width": 0.06675094, + "height": 0.17319852, + "radius": 0.05 + }, + "highlight": { "color": "#FFD70044", "scale": 1, "duration": 0.12 }, + "actions": { + "onClick": { "scenario": "scenarios/prolog/morning_cloak.scenario" } + } + }, + { + "id": "book_ground", + "texture": "book_ground", + "layer": "foreground", + "zIndex": 6, + "enabled": true, + "visible": true, + "cursor": "PointingHand", + "hitArea": { "type": "rect", "x": 0.30, "y": 0.66, "width": 0.10, "height": 0.09 }, + "highlight": { "color": "#9966FF44", "scale": 1, "duration": 0.12 }, + "actions": { + "onClick": { "scenario": "scenarios/prolog/morning_book.scenario" } + } + } + ] +} diff --git a/items/food/ration.json b/items/food/ration.json new file mode 100644 index 0000000..8d3b48c --- /dev/null +++ b/items/food/ration.json @@ -0,0 +1,9 @@ +{ + "Id": "food/ration", + "Name": "items/food/ration/name", + "Description": "items/food/ration/desc", + "Cost": 5, + "Sprite": "food/ration", + "ItemType": "Food", + "ItemAction": "null" +} \ No newline at end of file diff --git a/items/food/ration.png b/items/food/ration.png new file mode 100644 index 0000000..0c6028e Binary files /dev/null and b/items/food/ration.png differ diff --git a/items/food/wolf_meat.json b/items/food/wolf_meat.json new file mode 100644 index 0000000..27eee47 --- /dev/null +++ b/items/food/wolf_meat.json @@ -0,0 +1,9 @@ +{ + "Id": "food/wolf_meat", + "Name": "items/food/wolf_meat/name", + "Description": "items/food/wolf_meat/desc", + "Cost": 1, + "Sprite": "food/wolf_meat", + "ItemType": "Resource,Food", + "ItemAction": "null" +} \ No newline at end of file diff --git a/items/food/wolf_meat.png b/items/food/wolf_meat.png new file mode 100644 index 0000000..6b6d6ab Binary files /dev/null and b/items/food/wolf_meat.png differ diff --git a/items/items.json b/items/items.json new file mode 100644 index 0000000..2587f6d --- /dev/null +++ b/items/items.json @@ -0,0 +1,7 @@ +{ + "Items": [ + ${food/ration}, + ${food/wolf_meat}, + ${resource/branches} + ] +} \ No newline at end of file diff --git a/items/recipe/00079-3547745985.png b/items/recipe/00079-3547745985.png new file mode 100644 index 0000000..60233ba Binary files /dev/null and b/items/recipe/00079-3547745985.png differ diff --git a/items/recipe/recipe.png b/items/recipe/recipe.png new file mode 100644 index 0000000..2c82c0d Binary files /dev/null and b/items/recipe/recipe.png differ diff --git a/items/resource/branches.json b/items/resource/branches.json new file mode 100644 index 0000000..07dc0fb --- /dev/null +++ b/items/resource/branches.json @@ -0,0 +1,9 @@ +{ + "Id": "resource/branches", + "Name": "items/resource/branches/name", + "Description": "items/resource/branches/desc", + "Cost": 0, + "Sprite": "resource/branches", + "ItemType": "Resource", + "ItemAction": "null" +} \ No newline at end of file diff --git a/items/resource/branches.png b/items/resource/branches.png new file mode 100644 index 0000000..8868c4c Binary files /dev/null and b/items/resource/branches.png differ diff --git a/locale/en.properties b/locale/en.properties new file mode 100644 index 0000000..2a710ba --- /dev/null +++ b/locale/en.properties @@ -0,0 +1,103 @@ +mod_core_name = Core +mod_core_desc = Game core + +prolog/title = * A few missed moments earlier * +prolog/line1 = Being thoroughly wasted, Marao lay peacefully in the alley. +prolog/line2 = He was robbed blind, beaten, and dumped in the first back alley. +prolog/line4 = Cats had pissed in his mouth, his head and ass ached with pain. +prolog/choose_path = [What to do?] +prolog/opt_home = Return home +prolog/opt_alley = Check the alley +home_outside/prompt = +home_outside/opt_enter = Enter the house +home_outside/opt_town = To the town +home_outside/opt_forest = To the forest +town_entry/prompt = +town_entry/opt_home = Return home +town_entry/opt_square = To the square +town_outskirts/prompt = +town_outskirts/opt_home = Return home +town_outskirts/opt_forest = To the forest +menu/version = v1.0 - 2026.01.29 +menu/resume = Resume +menu/saves = Saves +menu/settings = Settings +menu/exit = Exit +menu/newgame = New Game +ui/add_to_party = New party member +ui/journal/new = New journal entry +ui/journal/updated = Quest updated +ui/battle/next = End turn +ui/battle/endgame = End +ui/battle/endgame/to_main_menu = Main menu +ui/battle/victory = Victory +ui/battle/victory/return = Continue +ui/battle/exp = Experience +ui/diner/rationday = Daily consumption: {0} +ui/diner/rationmax = Supplies will last {0} days +ui/cook/cook = Cook +ui/cook/close = Close +ui/cook/recipe_time = {0} minutes +ui/cook/recipe_out = Cooking result: {0} +ui/menu/new_game = New Game +ui/menu/load = Load +ui/menu/settings = Settings +ui/menu/exit = Exit +quest/prolog = Prologue +quest/prolog/0 = It's cold, need to put something on... +quest/prolog/1 = I don't remember a damn thing... Need to look around, maybe I can recall something. +quest/prolog/2 = I found the recipe book I bought the night before. It's getting dark, need to find shelter. +quest/prolog/3 = quest3 +items/food/ration/name = Ration +items/food/ration/desc = A daily ration unit for one person +items/food/wolf_meat/name = Wolf cutlet +items/food/wolf_meat/desc = Raw wolf meat +items/resource/branches/name = Branches +items/resource/branches/desc = Fuel for a campfire +recipe/wolf_meat_to_ration/name = Ration from wolf meat +recipe/wolf_meat_to_ration/desc = A recipe describing how to properly cook wolf meat to make it safe to eat +characters/player/marao = Marao +characters/enemies/wolf = Wolf +characters/enemies/werewolf_girl = Werewolf +characters/action/physics_attack/name = Basic attack +characters/action/physics_attack/description = Attacks an enemy with a weapon, with a damage multiplier of 1.0 +characters/action/defence/name = Defence +characters/action/defence/description = Protects the target with a defence multiplier of 1.0 +characters/action/stun/name = Stun +characters/action/stun/description = Stuns the target for 2 turns +characters/skills/slave_master_name = Slave Trader +characters/skills/slave_master = Gives the ability to enslave a defeated enemy with a base chance of 10%. The upkeep of the slave falls on your shoulders. +settings/back = Back +settings/audio = Audio +settings/sounds = Sounds +settings/music = Music +settings/volume = Volume +settings/language = Language +settings/lang_ru = Russian +settings/lang_en = English +settings/lang_zh = 中文 +settings/tab_general = General +settings/tab_audio = Sound +settings/tab_display = Display +settings/display = Display +settings/window_mode = Window Mode +settings/window_mode_windowed = Windowed +settings/window_mode_fullscreen = Fullscreen +settings/window_mode_borderless = Borderless +settings/resolution = Resolution +settings/monitor = Monitor +settings/monitor_screen = Screen {0} ({1}x{2}) +settings/vsync = V-Sync +settings/scale = Scale +settings/scale_1x = 1x +settings/scale_2x = 2x +settings/scale_3x = 3x +settings/scale_4x = 4x +settings/tab_mods = Mod Settings +settings/mod_list_title = Mods +settings/mods_no_settings = No mod settings available +settings/mods_reset = Reset to Defaults +launcher/title = Settings +launcher/play = Play +launcher/exit = Exit +quest/naked_morning = Naked Morning diff --git a/locale/ru.properties b/locale/ru.properties new file mode 100644 index 0000000..616ab0c --- /dev/null +++ b/locale/ru.properties @@ -0,0 +1,103 @@ +mod_core_name = Ядро +mod_core_desc = Ядро игры + +prolog/title = * Несколькими упущенными моментами ранее * +prolog/line1 = Будучи изрядно набуханным, Марао мирно лежал в переулке. +prolog/line2 = Его обокрали до нитки, избили и выкинули в первой же подворотне. +prolog/line4 = Во рту было нассано кошками, голова и жопа ныли от боли. +prolog/choose_path = [Что делать?] +prolog/opt_home = Вернуться к дому +prolog/opt_alley = Проверить переулок +home_outside/prompt = +home_outside/opt_enter = Зайти в дом +home_outside/opt_town = В город +home_outside/opt_forest = В лес +town_entry/prompt = +town_entry/opt_home = Вернуться к дому +town_entry/opt_square = На площадь +town_outskirts/prompt = +town_outskirts/opt_home = Вернуться к дому +town_outskirts/opt_forest = В лес +menu/version = v1.0 - 2026.01.29 +menu/resume = Вернуться +menu/saves = Сохранения +menu/settings = Настройки +menu/exit = Выход +menu/newgame = Новая игра +ui/add_to_party = Новый член отряда +ui/journal/new = Новая запись в журнале +ui/journal/updated = Задание обновлено +ui/battle/next = Конец хода +ui/battle/endgame = Конец +ui/battle/endgame/to_main_menu = Главное меню +ui/battle/victory = Победа +ui/battle/victory/return = Продолжить +ui/battle/exp = Опыт +ui/diner/rationday = Потребление в сутки: {0} +ui/diner/rationmax = Запасов хватит на {0} дней +ui/cook/cook = Готовить +ui/cook/close = Выйти +ui/cook/recipe_time = {0} минут +ui/cook/recipe_out = Результат приготовления: {0} +ui/menu/new_game = Новая игра +ui/menu/load = Загрузить +ui/menu/settings = Настройки +ui/menu/exit = Выход +quest/prolog = Пролог +quest/prolog/0 = Холодно, нужно во что-то одеться... +quest/prolog/1 = Ничерта не помню... Нужно осмотреться, вдруг я смогу что нибудь вспомнить. +quest/prolog/2 = Я нашёл книгу рецептов, которую купил на кануне. Уже темнеет нужно найти укрытие. +quest/prolog/3 = квест3 +items/food/ration/name = Рацион +items/food/ration/desc = Единица суточного рациона для одного человека +items/food/wolf_meat/name = Волчья вырезка +items/food/wolf_meat/desc = Сырое мясо волка +items/resource/branches/name = Ветки +items/resource/branches/desc = Топливо для костра +recipe/wolf_meat_to_ration/name = Рацион из волчьего мяса +recipe/wolf_meat_to_ration/desc = Рецепт описывает как правильно приготовить волчатину, чтобы безопасно употребить её в пищу +characters/player/marao = Марао +characters/enemies/wolf = Волк +characters/enemies/werewolf_girl = Оборотень +characters/action/physics_attack/name = Простая атака +characters/action/physics_attack/description = Атакует врага оружием, с коэффициентом урона 1.0 +characters/action/defence/name = Защита +characters/action/defence/description = Защищает цель с коэффициентом защиты 1.0 +characters/action/stun/name = Ошеломление +characters/action/stun/description = Ошеломляет цель на 2 хода +characters/skills/slave_master_name = Работорговец +characters/skills/slave_master = Даёт возможность взять в рабство поверженного врага с базовым шансом в 10%. Содержание раба ложится на твои плечи. +settings/back = Назад +settings/audio = Аудио +settings/sounds = Звуки +settings/music = Музыка +settings/volume = Громкость +settings/language = Язык +settings/lang_ru = Русский +settings/lang_en = English +settings/lang_zh = 中文 +settings/tab_general = Основное +settings/tab_audio = Звук +settings/tab_display = Экран +settings/display = Экран +settings/window_mode = Режим окна +settings/window_mode_windowed = Оконный +settings/window_mode_fullscreen = Полный экран +settings/window_mode_borderless = Без рамки +settings/resolution = Разрешение +settings/monitor = Монитор +settings/monitor_screen = Экран {0} ({1}x{2}) +settings/vsync = Вертикальная синхронизация +settings/scale = Масштаб +settings/scale_1x = 1x +settings/scale_2x = 2x +settings/scale_3x = 3x +settings/scale_4x = 4x +settings/tab_mods = Настройки модов +settings/mod_list_title = Моды +settings/mods_no_settings = Нет доступных настроек модов +settings/mods_reset = Сбросить настройки +launcher/title = Настройки +launcher/play = Играть +launcher/exit = Выход +quest/naked_morning = Голое утро diff --git a/locale/scenarios_en.properties b/locale/scenarios_en.properties new file mode 100644 index 0000000..844fe15 --- /dev/null +++ b/locale/scenarios_en.properties @@ -0,0 +1,26 @@ +home_outside/prompt = +home_outside/opt_enter = Enter the house +home_outside/opt_town = To the town +home_outside/opt_forest = To the forest +town_entry/prompt = +town_entry/opt_home = Return home +town_entry/opt_square = To the square +town_outskirts/prompt = +town_outskirts/opt_home = Return home +town_outskirts/opt_forest = To the forest +vestibule/diner/prompt = +vestibule/diner/opt_workroom = To the workroom +vestibule/diner/opt_dinerroom = To the dining room +vestibule/diner/opt_bedroom = To the bedroom +vestibule/diner/opt_cellar = To the basement +vestibule/diner/opt_outside = Outside +rooms/workroom/prompt = The workroom, no one will distract you from your research here +rooms/workroom/opt_exit = Leave +rooms/bedroom/prompt = Your bedroom, you can sleep and regain your strength here +rooms/bedroom/opt_exit = Leave +rooms/kitchen/prompt = A room equipped as a kitchen +rooms/kitchen/opt_exit = Leave +rooms/livingroom/prompt = Living room +rooms/livingroom/opt_exit = Leave +rooms/basement/prompt = Basement +rooms/basement/opt_exit = Leave diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..e5440c2 --- /dev/null +++ b/manifest.json @@ -0,0 +1,10 @@ +{ + "id": "core", + "name": "Core", + "version": "1.0.0", + "author": "ct", + "description": "Game core", + "sources": [ + "src/*.cs" + ] +} diff --git a/mod.png b/mod.png new file mode 100644 index 0000000..2edfb90 Binary files /dev/null and b/mod.png differ diff --git a/music/Abyssal Void.ogg b/music/Abyssal Void.ogg new file mode 100644 index 0000000..bb80de7 Binary files /dev/null and b/music/Abyssal Void.ogg differ diff --git a/music/Airborne Melody.ogg b/music/Airborne Melody.ogg new file mode 100644 index 0000000..c257b6f Binary files /dev/null and b/music/Airborne Melody.ogg differ diff --git a/music/Aura of Decay.ogg b/music/Aura of Decay.ogg new file mode 100644 index 0000000..728e93e Binary files /dev/null and b/music/Aura of Decay.ogg differ diff --git a/music/Binary Prelude.ogg b/music/Binary Prelude.ogg new file mode 100644 index 0000000..57ab7b4 Binary files /dev/null and b/music/Binary Prelude.ogg differ diff --git a/music/Cinders of Dawn.ogg b/music/Cinders of Dawn.ogg new file mode 100644 index 0000000..17b6d50 Binary files /dev/null and b/music/Cinders of Dawn.ogg differ diff --git a/music/Circuit Dreams II.ogg b/music/Circuit Dreams II.ogg new file mode 100644 index 0000000..3cf5858 Binary files /dev/null and b/music/Circuit Dreams II.ogg differ diff --git a/music/Crimson Echoes.ogg b/music/Crimson Echoes.ogg new file mode 100644 index 0000000..830e468 Binary files /dev/null and b/music/Crimson Echoes.ogg differ diff --git a/music/Crimson Horizon.ogg b/music/Crimson Horizon.ogg new file mode 100644 index 0000000..dca27bc Binary files /dev/null and b/music/Crimson Horizon.ogg differ diff --git a/music/Empty Save Room.ogg b/music/Empty Save Room.ogg new file mode 100644 index 0000000..f53518d Binary files /dev/null and b/music/Empty Save Room.ogg differ diff --git a/music/Glass Symphony.ogg b/music/Glass Symphony.ogg new file mode 100644 index 0000000..d6f23ad Binary files /dev/null and b/music/Glass Symphony.ogg differ diff --git a/music/Hex Doom Cart.ogg b/music/Hex Doom Cart.ogg new file mode 100644 index 0000000..95a1aed Binary files /dev/null and b/music/Hex Doom Cart.ogg differ diff --git a/music/Iron Resonance II.ogg b/music/Iron Resonance II.ogg new file mode 100644 index 0000000..645ccd1 Binary files /dev/null and b/music/Iron Resonance II.ogg differ diff --git a/music/Iron Resonance.ogg b/music/Iron Resonance.ogg new file mode 100644 index 0000000..f0b5b8c Binary files /dev/null and b/music/Iron Resonance.ogg differ diff --git a/music/Luminous Twilight.ogg b/music/Luminous Twilight.ogg new file mode 100644 index 0000000..93bfc90 Binary files /dev/null and b/music/Luminous Twilight.ogg differ diff --git a/music/Melancholic Journey.ogg b/music/Melancholic Journey.ogg new file mode 100644 index 0000000..48d99d4 Binary files /dev/null and b/music/Melancholic Journey.ogg differ diff --git a/music/Nebula Pulse Echoes.ogg b/music/Nebula Pulse Echoes.ogg new file mode 100644 index 0000000..7a9aee6 Binary files /dev/null and b/music/Nebula Pulse Echoes.ogg differ diff --git a/music/Quantum Archive.ogg b/music/Quantum Archive.ogg new file mode 100644 index 0000000..49ff83c Binary files /dev/null and b/music/Quantum Archive.ogg differ diff --git a/music/Rusty Frequencies.ogg b/music/Rusty Frequencies.ogg new file mode 100644 index 0000000..c7a181d Binary files /dev/null and b/music/Rusty Frequencies.ogg differ diff --git a/music/Serpent's Lament.ogg b/music/Serpent's Lament.ogg new file mode 100644 index 0000000..5dafad5 Binary files /dev/null and b/music/Serpent's Lament.ogg differ diff --git a/music/Skull Resonance.ogg b/music/Skull Resonance.ogg new file mode 100644 index 0000000..ef26343 Binary files /dev/null and b/music/Skull Resonance.ogg differ diff --git a/music/Twilight Interlude.ogg b/music/Twilight Interlude.ogg new file mode 100644 index 0000000..9d71fac Binary files /dev/null and b/music/Twilight Interlude.ogg differ diff --git a/music/Venom's Embrace.ogg b/music/Venom's Embrace.ogg new file mode 100644 index 0000000..544ecd5 Binary files /dev/null and b/music/Venom's Embrace.ogg differ diff --git a/music/playlists/battle.json b/music/playlists/battle.json new file mode 100644 index 0000000..51c4d47 --- /dev/null +++ b/music/playlists/battle.json @@ -0,0 +1,22 @@ +{ + "Scene": "Battle", + "Musics": [ + { + "MusicType": "Combat", + "MusicNames": [ + "Aura of Decay", + "Circuit Dreams II", + "Crimson Echoes", + "Crimson Horizon", + "Glass Symphony", + "Hex Doom Cart", + "Iron Resonance", + "Iron Resonance II", + "Luminous Twilight", + "Rusty Frequencies", + "Skull Resonance", + "Venom's Embrace" + ] + } + ] +} diff --git a/music/playlists/default.json b/music/playlists/default.json new file mode 100644 index 0000000..dec940f --- /dev/null +++ b/music/playlists/default.json @@ -0,0 +1,36 @@ +{ + "Scene": "default", + "Musics": [ + { + "MusicType": "Ambient", + "MusicNames": [ + "Abyssal Void", + "Airborne Melody", + "Binary Prelude", + "Cinders of Dawn", + "Melancholic Journey", + "Nebula Pulse Echoes", + "Quantum Archive", + "Twilight Interlude" + ] + }, + { + "MusicType": "Combat", + "MusicNames": [ + "Aura of Decay", + "Circuit Dreams II", + "Crimson Echoes", + "Crimson Horizon", + "Glass Symphony", + "Hex Doom Cart", + "Iron Resonance", + "Iron Resonance II", + "Luminous Twilight", + "Rusty Frequencies", + "Skull Resonance", + "Venom's Embrace", + "Empty Save Room" + ] + } + ] +} diff --git a/music/playlists/mainmenu.json b/music/playlists/mainmenu.json new file mode 100644 index 0000000..7b6b3ba --- /dev/null +++ b/music/playlists/mainmenu.json @@ -0,0 +1,11 @@ +{ + "Scene": "MainMenu", + "Musics": [ + { + "MusicType": "Ambient", + "MusicNames": [ + "Serpent's Lament" + ] + } + ] +} diff --git a/music/playlists/town_entry.json b/music/playlists/town_entry.json new file mode 100644 index 0000000..cddcd7c --- /dev/null +++ b/music/playlists/town_entry.json @@ -0,0 +1,20 @@ +{ + "Scene": "town_entry", + "Musics": [ + { + "MusicType": "Ambient", + "MusicNames": [ + "Abyssal Void", + "Cinders of Dawn" + ] + }, + { + "MusicType": "Combat", + "MusicNames": [ + "Aura of Decay", + "Circuit Dreams II", + "Iron Resonance II" + ] + } + ] +} diff --git a/quests/quests.json b/quests/quests.json new file mode 100644 index 0000000..1d8ea11 --- /dev/null +++ b/quests/quests.json @@ -0,0 +1,17 @@ +{ + "Items": [ + { + "Id": "PrologQuest", + "Name": "quest/prolog", + "StatusToDescription": { + "0": "quest/prolog/0", + "1": "quest/prolog/1", + "2": "quest/prolog/2" + } + }, + { + "Id": "NakedMorningQuest", + "Name": "quest/naked_morning" + } + ] +} diff --git a/scenarios/home/home_basement_default.scenario b/scenarios/home/home_basement_default.scenario new file mode 100644 index 0000000..3f15514 --- /dev/null +++ b/scenarios/home/home_basement_default.scenario @@ -0,0 +1,10 @@ +scene: home_basement +priority: 10 +--- +light_set [{"x":0.38576052,"y":0.31548673,"radius":700,"influence":0.5,"color":"#ffff00"},{"x":0.16893204,"y":0.20154873,"radius":700,"influence":0.5,"color":"#ffff00"},{"x":0.5864078,"y":0.3254425,"radius":700,"influence":0.5,"color":"#ffff00"},{"x":0.8116505,"y":0.27123895,"radius":700,"influence":0.5,"color":"#ffff00"}] +select "Подвал" key=rooms/basement/prompt +option "Выйти" key=rooms/basement/opt_exit -> :exit + +:exit +switch_scene home_vestibule +end diff --git a/scenarios/home/home_bedroom_default.scenario b/scenarios/home/home_bedroom_default.scenario new file mode 100644 index 0000000..b7c5c24 --- /dev/null +++ b/scenarios/home/home_bedroom_default.scenario @@ -0,0 +1,10 @@ +scene: home_bedroom +save_allowed: true +priority: 10 +--- +select "Твоя спальня, тут можно поспать и набраться сил" key=rooms/bedroom/prompt +option "Выйти" key=rooms/bedroom/opt_exit -> :exit + +:exit +switch_scene home_vestibule +end diff --git a/scenarios/home/home_kitchen_default.scenario b/scenarios/home/home_kitchen_default.scenario new file mode 100644 index 0000000..a67b1e7 --- /dev/null +++ b/scenarios/home/home_kitchen_default.scenario @@ -0,0 +1,10 @@ +scene: home_kitchen +priority: 10 +--- +light_set [{"x":0.43052286,"y":0.5760054,"radius":500,"influence":1,"color":"#ffff00"},{"x":0.103702,"y":0.26946074,"radius":500,"influence":1,"color":"#ffff00"}] +select "Комната оборудованная под кухню" key=rooms/kitchen/prompt +option "Выйти" key=rooms/kitchen/opt_exit -> :exit + +:exit +switch_scene home_vestibule +end diff --git a/scenarios/home/home_livingroom_default.scenario b/scenarios/home/home_livingroom_default.scenario new file mode 100644 index 0000000..ea1d31d --- /dev/null +++ b/scenarios/home/home_livingroom_default.scenario @@ -0,0 +1,10 @@ +scene: home_livingroom +priority: 10 +--- +light_set [{"x":0.32427186,"y":0.5831858,"radius":300,"influence":1,"color":"#ffff00"},{"x":0.11262136,"y":0.44159293,"radius":300,"influence":0.6,"color":"#ffff00"}] +select "Гостинная" key=rooms/livingroom/prompt +option "Выйти" key=rooms/livingroom/opt_exit -> :exit + +:exit +switch_scene home_vestibule +end diff --git a/scenarios/home/home_outside_default.scenario b/scenarios/home/home_outside_default.scenario new file mode 100644 index 0000000..24d57a5 --- /dev/null +++ b/scenarios/home/home_outside_default.scenario @@ -0,0 +1,20 @@ +scene: home_outside +priority: 10 +--- +light_set [{"x":0.29462293,"y":0.43369123,"radius":100,"influence":1,"color":"#ffff00"},{"x":0.29967362,"y":0.62050235,"radius":100,"influence":1,"color":"#ffff00"},{"x":0.49256954,"y":0.40350124,"radius":100,"influence":1,"color":"#ffff00"},{"x":0.5846468,"y":0.37935096,"radius":100,"influence":1,"color":"#ffff00"},{"x":0.33943588,"y":0.41643897,"radius":100,"influence":1,"color":"#ffff00"},{"x":0.43495983,"y":0.41557643,"radius":100,"influence":1,"color":"#ffff00"},{"x":0.30102944,"y":0.5208026,"radius":100,"influence":1,"color":"#ffff00"},{"x":0.67573905,"y":0.40436372,"radius":100,"influence":1,"color":"#ffff00"},{"x":0.3522381,"y":0.5113151,"radius":100,"influence":1,"color":"#ffff00"},{"x":0.6782009,"y":0.507865,"radius":150,"influence":1,"color":"#ffff00"}] +select "" key=home_outside/prompt +option "Зайти в дом" key=home_outside/opt_enter -> :enter +option "В город" key=home_outside/opt_town -> :town +option "В лес" key=home_outside/opt_forest -> :forest + +:enter +switch_scene home_vestibule +end + +:town +switch_scene town_entry +end + +:forest +switch_scene forest +end diff --git a/scenarios/home/home_vestibule_default.scenario b/scenarios/home/home_vestibule_default.scenario new file mode 100644 index 0000000..2d25bb4 --- /dev/null +++ b/scenarios/home/home_vestibule_default.scenario @@ -0,0 +1,30 @@ +scene: home_vestibule +priority: 40 +--- +light_set [{"x":0.32427186,"y":0.5831858,"radius":300,"influence":1,"color":"#ffff00"},{"x":0.11262136,"y":0.44159293,"radius":300,"influence":0.6,"color":"#ffff00"}] +select "" key=vestibule/diner/prompt +option "В рабочую комнату" key=vestibule/diner/opt_workroom -> :workroom +option "В обеденную комнату" key=vestibule/diner/opt_dinerroom -> :kitchen +option "В спальню" key=vestibule/diner/opt_bedroom -> :bedroom +option "В подвал" key=vestibule/diner/opt_cellar -> :cellar +option "На улицу" key=vestibule/diner/opt_outside -> :outside + +:workroom +switch_scene home_workroom +end + +:kitchen +switch_scene home_kitchen +end + +:bedroom +switch_scene home_bedroom +end + +:cellar +switch_scene home_basement +end + +:outside +switch_scene home_outside +end diff --git a/scenarios/home/home_workroom_default.scenario b/scenarios/home/home_workroom_default.scenario new file mode 100644 index 0000000..8a45e1b --- /dev/null +++ b/scenarios/home/home_workroom_default.scenario @@ -0,0 +1,10 @@ +scene: home_workroom +priority: 10 +--- +light_set [{"x":0.45825243,"y":0.5865044,"radius":300,"influence":1,"color":"#ffff00"},{"x":0.5190939,"y":0.52787614,"radius":300,"influence":1,"color":"#ffff00"},{"x":0.77411,"y":0.45929205,"radius":300,"influence":1,"color":"#ffff00"},{"x":0.8699029,"y":0.4869469,"radius":300,"influence":1,"color":"#ffff00"}] +select "Рабочий кабинет, тут тебя никто не будет отвлекать от исследований" key=rooms/workroom/prompt +option "Выйти" key=rooms/workroom/opt_exit -> :exit + +:exit +switch_scene home_vestibule +end diff --git a/scenarios/prolog/graveyard_arrival.scenario b/scenarios/prolog/graveyard_arrival.scenario new file mode 100644 index 0000000..aa05408 --- /dev/null +++ b/scenarios/prolog/graveyard_arrival.scenario @@ -0,0 +1,16 @@ +scene: prolog_graveyard +priority: 10 +is_one_run: true +--- +background prolog/00025-165590409 + +text "Могильные плиты тянулись вдаль, серые и мрачные. Старые дубы качали голыми ветвями. Где-то каркала ворона." +text "Свистки стихли — полицейские потеряли его из виду." first=marao/think +text "Марао перевёл дух и прислонился к высокому склепу с выцветшей надписью: «Семья фон Штольц»." first=marao/think +text "И тут его скрутило. Живот скрутило так, что он согнулся пополам." first=marao/sad +text "— Ну вот. Организм. Раньше я мог пол-литра пива и огурцы, а теперь от одной воды уже..." first=marao/sad +text "Он покосился на книгу, которая всё ещё была у него под мышкой." first=marao/think +text "— Хм. А чего бы и нет? Всё равно время есть." first=marao/smile + +notify "За склепом можно уединиться." +end diff --git a/scenarios/prolog/graveyard_azif.scenario b/scenarios/prolog/graveyard_azif.scenario new file mode 100644 index 0000000..8d07816 --- /dev/null +++ b/scenarios/prolog/graveyard_azif.scenario @@ -0,0 +1,35 @@ +# Клик по книге — Аль-Азиф просыпается (канон: глава 4). +# Файл без шапки: InteractiveManager отрезает метаданные, играет только тело. +text "Марао плюнул и присел, сложив книгу стопкой страниц. Поднёс к пятой точке." first=marao/think +ptext "Книга заорала." +ptext "— НЕ СМЕЙ!" +text "Голос был похож на скрип несмазанных ворот, смешанный с плачем сотни младенцев. Буквы на раскрытой странице корчились, складываясь в ужасные морды, которые разевали рты." first=marao/think +text "— Ты умеешь говорить?" first=marao/think +ptext "— Я — АЛЬ АЗИФ, КНИГА МЁРТВЫХ ИМЁН! Я СВОДИЛ С УМА ЦИВИЛИЗАЦИИ! Я — ГЛАС БЕЗДНЫ!" +text "— Понятно. — Марао кивнул и снова придвинул книгу к себе." first=marao/smile +ptext "— Я УНИЧТОЖУ ТВОЙ РОД ДО СЕДЬМОГО КОЛЕНА!" +text "Страницы засветились багровым, по кладбищу побежали тени, могильные плиты затряслись." +text "— Да тихо ты. Голова от тебя болит. Я тут только что обосрался от страха, когда за мной полиция бежала, а ты ревёшь на всё кладбище..." first=marao/sad +ptext "Книга попыталась вторгнуться в его разум. Поток видений: бескрайние океаны тьмы, гигантские щупальца, разрывающие реальность, звёзды, гаснущие одна за другой." +text "Марао просто икнул. В его голове стоял запах дешёвого портвейна, играла шарманка и мелькала мысль о том, что надо бы кефирчику холодного." first=marao/think +ptext "— ПОЧЕМУ ТЫ НЕ БЕЖИШЬ В УЖАСЕ?!" +text "— А чё бежать? Ты бумажка. Говорящая, но бумажка. И вообще: если я тебя в штаны не засуну, то как мне вытираться?" first=marao/think +ptext "— ТЫ НЕ ПОНИМАЕШЬ! ТЫ ОТКРЫЛ ПОРТАЛЫ! ВЕЗДЕ! В ГОРОДАХ, В ПОЛЯХ, В ДОМАХ! ОНИ ПРИДУТ!" +text "— Какие ещё порталы? А, это я стихи читал. Ну, казахские. Красиво же." first=marao/smile +ptext "— ЭТО БЫЛИ ЗАКЛИНАНИЯ ВЫЗОВА!" +text "— А они платить будут? За аренду материка? Или мне потом штрафы за самострой придут?" first=marao/think +ptext "Книга захлебнулась собственным сиянием. Она попыталась захлопнуться и выскользнуть, но Марао держал её крепко." +text "— Слушай, книга. Орать можешь сколько влезет. Но мне нужно прийти в себя, одеться и пожрать. Давай договоримся: ты не орёшь — я не пытаюсь тобой подтереться. Идёт?" first=marao/think +ptext "Книга онемела." +ptext "— ТЫ... ТЫ СМЕЕШЬСЯ НАД ДРЕВНИМ УЖАСОМ?.." +text "— Да не смеюсь я. Хочешь, я тебя вон тем листом лопуха протру? Будешь чистенькая. Хочешь?" first=marao/smile +ptext "Книга издала звук, похожий на всхлип." +ptext "Вдалеке снова засвистели полицейские свистки." +sound locations/prolog/police +text "Марао встал, накинул красную тряпку и сунул книгу под мышку." first=marao/smile +text "— Валим. Давай, книжка, показывай, где тут трактир. А то у меня всего две мысли: «нахера я такой голый» и «где бы опохмелиться»." first=marao/smile +title "Конец пролога. Впереди — дорога вдоль реки..." + +action quest.add_tag quest_id=NakedMorningQuest tag=azif_awake +interactive_remove book_wipe +end diff --git a/scenarios/prolog/graveyard_ensure_book.scenario b/scenarios/prolog/graveyard_ensure_book.scenario new file mode 100644 index 0000000..bb2acd3 --- /dev/null +++ b/scenarios/prolog/graveyard_ensure_book.scenario @@ -0,0 +1,7 @@ +scene: prolog_graveyard +priority: 15 +condition: NakedMorningQuest.hasTag("graveyard_read") && NakedMorningQuest.notHasTag("azif_awake") +--- +# Прочитано, но Аль-Азиф ещё не проснулся: держим хотспот книги на сцене. +interactive_add book_wipe +end diff --git a/scenarios/prolog/graveyard_ensure_crypt.scenario b/scenarios/prolog/graveyard_ensure_crypt.scenario new file mode 100644 index 0000000..0772881 --- /dev/null +++ b/scenarios/prolog/graveyard_ensure_crypt.scenario @@ -0,0 +1,8 @@ +scene: prolog_graveyard +priority: 15 +condition: NakedMorningQuest.notHasTag("graveyard_read") +--- +# Книга ещё не прочитана вслух: держим хотспот «за склепом» на сцене. +# Идемпотентно при каждом входе (Add по тому же id возвращает существующий объект). +interactive_add crypt_spot +end diff --git a/scenarios/prolog/graveyard_read.scenario b/scenarios/prolog/graveyard_read.scenario new file mode 100644 index 0000000..ff83b0f --- /dev/null +++ b/scenarios/prolog/graveyard_read.scenario @@ -0,0 +1,25 @@ +# Клик «за склепом» — нужда и первое чтение (канон: глава 3). +# Файл без шапки: InteractiveManager отрезает метаданные, играет только тело. +text "Марао отошёл за склеп и присел на корточки. Кладбище было тихим, спокойным. Только ветер гонял сухие листья по плитам." first=marao/think +text "— А чего бы и нет? Всё равно время есть." +text "Он открыл книгу на первой попавшейся странице." first=marao/think +text "Буквы напоминали кириллицу, но с множеством крючков, хвостов и точек, которые, казалось, шевелились. Некоторые строки мерцали. Марао прищурился и потёр глаза." first=marao/think +text "— Казахский. Точно казахский. У нас на стройке был казах Ахмет — он ругался так же. Все слова знакомые, а смысла ноль." first=marao/smile +text "Он начал читать вслух, с интонацией базарного зазывалы, выговаривая страшные имена как «Джамбулат-ага» и «Алма-ата»." first=marao/smile + +background_color red +ptext "Где-то далеко, в Океане Кошмаров, Ктулху вздрогнул во сне." +ptext "Священный ритм «Ph'nglui mglw'nafh...» кто-то читал со словами «...и сметаны по два фунта, да?»" +ptext "Порталы стали открываться по всему материку — с противным чавкающим звуком, похожим на открывание банки с тушёнкой." +background prolog/00025-165590409 + +text "Марао закончил читать, закрыл книгу и снова скривился." first=marao/think +text "— И как теперь вытираться?" +text "Лопухов не было. Только крапива да старый газетный клочок. И книга." first=marao/think +text "Он потянул страницу за уголок — ноль реакции. Дёрнул сильнее: бумага была твёрдой, как металл, но гибкой. Он рвал и так, и сяк, даже ногтями пытался. Бесполезно." first=marao/sad +text "— Что за брак! Я за такие деньги..." first=marao/sad + +action quest.add_tag quest_id=NakedMorningQuest tag=graveyard_read +interactive_remove crypt_spot +interactive_add book_wipe +end diff --git a/scenarios/prolog/morning_book.scenario b/scenarios/prolog/morning_book.scenario new file mode 100644 index 0000000..80828a7 --- /dev/null +++ b/scenarios/prolog/morning_book.scenario @@ -0,0 +1,12 @@ +# Клик по книге — Аль-Азиф в спячке и молчит (канон: главы 1-3). +# Файл без шапки: InteractiveManager отрезает метаданные, играет только тело. +text "Рядом, в грязи, лежала толстая книга в сером кожаном переплёте, с металлическими уголками, покрытыми зеленоватой патиной." first=marao/think +text "На обложке был странный барельеф: многорукая фигура с головой осьминога сжимала перевёрнутые звёзды." first=marao/think +text "— Какая-то мутная хрень. Откуда она у меня?" first=marao/sad +text "В голове мелькнул смутный образ: он в какой-то лавке протягивает монеты и берёт книгу. Но когда? Где? Почему? Больше ничего." first=marao/think +text "Марао пожал плечами и сунул книгу под мышку." first=marao/smile +text "— Ладно, бумага не жрёт. Пойдём, найдём, где опохмелиться." first=marao/smile +action quest.add_tag quest_id=NakedMorningQuest tag=book_taken +interactive_remove book_ground +switch_scene prolog_alley +end diff --git a/scenarios/prolog/morning_cloak.scenario b/scenarios/prolog/morning_cloak.scenario new file mode 100644 index 0000000..6a5cf5e --- /dev/null +++ b/scenarios/prolog/morning_cloak.scenario @@ -0,0 +1,10 @@ +# Клик по красной тряпке — Марао прикрывается (канон: глава 1). +# Файл без шапки: InteractiveManager отрезает метаданные, играет только тело. +text "Он сделал шаг, другой, придерживаясь за стену, и наступил на что-то мягкое. Красная тряпка." first=marao/think +text "Выцветшая, с бахромой по краям. Когда-то это было что-то вроде плаща или шали. На ткани угадывался вышитый крест." first=marao/think +text "Марао развернул её, оценил размер и намотал на плечи, как римскую тогу. Края едва доходили до колен." first=marao/smile +text "— Лучше, чем ничего. Срам прикрыт, хоть сзади и развевается, как знамя нищего легиона." first=marao/smile +action quest.add_tag quest_id=NakedMorningQuest tag=cloak_taken +interactive_remove cloak_ground +switch_scene prolog_alley +end diff --git a/scenarios/prolog/morning_items_ensure.scenario b/scenarios/prolog/morning_items_ensure.scenario new file mode 100644 index 0000000..1fa5ff0 --- /dev/null +++ b/scenarios/prolog/morning_items_ensure.scenario @@ -0,0 +1,9 @@ +scene: prolog_alley +priority: 15 +condition: NakedMorningQuest.notHasTag("cloak_taken") && NakedMorningQuest.notHasTag("book_taken") +--- +# Ни один предмет ещё не взят: держим оба интерактива на сцене. +# Не is_one_run — идемпотентно пересоздаёт объекты при каждом входе (Add по тому же id возвращает существующий). +interactive_add cloak_ground +interactive_add book_ground +end diff --git a/scenarios/prolog/morning_police.scenario b/scenarios/prolog/morning_police.scenario new file mode 100644 index 0000000..e3e6420 --- /dev/null +++ b/scenarios/prolog/morning_police.scenario @@ -0,0 +1,22 @@ +scene: prolog_alley +priority: 20 +is_one_run: true +condition: NakedMorningQuest.hasTag("cloak_taken") && NakedMorningQuest.hasTag("book_taken") +--- +sound locations/prolog/police +delay 0.7 hidden=true +title "Глава 2. Погоня" + +ptext "Из подворотни вышли трое полицейских в синих мундирах, с медными пуговицами, начищенными до блеска." +ptext "— ЭЙ, ТЫ! СТОЯТЬ!" +ptext "— Голый мужик в красной тряпке по городу бегает! Извращенец!" +text "— Какой извращенец? Я же одет... почти..." first=marao/think +ptext "Толстый полицейский с красным лицом поднёс свисток к губам и дул в него так, что закладывало уши. Молодой, с усиками, уже бежал вперёд, расстёгивая кобуру." +ptext "— ДЕРЖИ ЕГО!" +text "Спорить с полицией Марао был не готов. Спорить с полицией Марао не умел вообще. Он развернулся и побежал." first=marao/sad +text "Босые ноги, топот сапог за спиной, крики «Держи его!» — Марао летел по улочке, перепрыгнул через бочку с водой, шлёпнулся на колени, вскочил и побежал дальше." first=marao/sad +text "Он свернул влево, потом вправо и нырнул в ближайшую арку. Выбежав с другой стороны, он оказался у высоких кованых ворот." first=marao/think +text "За воротами было кладбище. Марао нырнул внутрь." first=marao/think + +switch_scene prolog_graveyard +end diff --git a/scenarios/prolog/morning_restore_book.scenario b/scenarios/prolog/morning_restore_book.scenario new file mode 100644 index 0000000..1cb27ce --- /dev/null +++ b/scenarios/prolog/morning_restore_book.scenario @@ -0,0 +1,7 @@ +scene: prolog_alley +priority: 15 +condition: NakedMorningQuest.hasTag("cloak_taken") && NakedMorningQuest.notHasTag("book_taken") +--- +# Тряпка взята, книга ещё нет: возвращаем книгу после перезагрузки сцены. +interactive_add book_ground +end diff --git a/scenarios/prolog/morning_restore_cloak.scenario b/scenarios/prolog/morning_restore_cloak.scenario new file mode 100644 index 0000000..759310c --- /dev/null +++ b/scenarios/prolog/morning_restore_cloak.scenario @@ -0,0 +1,7 @@ +scene: prolog_alley +priority: 15 +condition: NakedMorningQuest.hasTag("book_taken") && NakedMorningQuest.notHasTag("cloak_taken") +--- +# Книга взята, тряпка ещё нет: возвращаем тряпку после перезагрузки сцены. +interactive_add cloak_ground +end diff --git a/scenarios/prolog/morning_wake.scenario b/scenarios/prolog/morning_wake.scenario new file mode 100644 index 0000000..f212420 --- /dev/null +++ b/scenarios/prolog/morning_wake.scenario @@ -0,0 +1,17 @@ +scene: prolog_alley +priority: 10 +is_one_run: true +--- +background prolog/start_lane +title "Глава 1. Пробуждение" + +text "Марао открыл глаза и сразу пожалел об этом." first=marao/sad +text "Голова раскалывалась так, будто внутри неё поселился кузнец с молотом. Во рту было сухо и горько, как после трёх дней пьянки без закуски." first=marao/sad +text "Он лежал в грязном переулке между двух облезлых стен. Вокруг валялись тряпки, осколки бутылок и куски газет, которые ветер гонял по лужам." first=marao/think +text "Память отказывалась работать. Последнее, что он помнил: звон стаканов. Потом темнота. И всё." first=marao/think +text "Холодный воздух пробрал до костей. Марао посмотрел вниз, на себя, и снова выругался — уже громче." first=marao/think +text "— Да что ж такое! Где мои штаны?!" first=marao/sad +text "Он был абсолютно голый. Босые ступни на холодном камне. Тело болело — как будто его били чем-то тяжёлым. Возможно ногами. Возможно и по лицу." first=marao/sad + +notify "Осмотрись. В переулке что-то лежит." +end diff --git a/scenarios/start.scenario b/scenarios/start.scenario new file mode 100644 index 0000000..5a86eaf --- /dev/null +++ b/scenarios/start.scenario @@ -0,0 +1,6 @@ +scene: start_scene +priority: 0 +is_one_run: true +--- +switch_scene prolog_alley +end diff --git a/scenarios/town/town_entry_default.scenario b/scenarios/town/town_entry_default.scenario new file mode 100644 index 0000000..6940b75 --- /dev/null +++ b/scenarios/town/town_entry_default.scenario @@ -0,0 +1,14 @@ +scene: town_entry +priority: 40 +--- +select "" key=town_entry/prompt +option "Вернуться к дому" key=town_entry/opt_home -> :home +option "На площадь" key=town_entry/opt_square -> :square + +:home +switch_scene home_outside +end + +:square +switch_scene town_outskirts +end diff --git a/scenarios/town/town_outskirts_default.scenario b/scenarios/town/town_outskirts_default.scenario new file mode 100644 index 0000000..6a79474 --- /dev/null +++ b/scenarios/town/town_outskirts_default.scenario @@ -0,0 +1,14 @@ +scene: town_outskirts +priority: 10 +--- +select "" key=town_outskirts/prompt +option "Вернуться к дому" key=town_outskirts/opt_home -> :home +option "В лес" key=town_outskirts/opt_forest -> :forest + +:home +switch_scene home_outside +end + +:forest +switch_scene forest +end diff --git a/scenes/home_basement.json b/scenes/home_basement.json new file mode 100644 index 0000000..9586e17 --- /dev/null +++ b/scenes/home_basement.json @@ -0,0 +1,6 @@ +{ + "name": "home_basement", + "defaultBackground": "home/basement", + "defaultAmbient": "", + "defaultScenario": "scenarios/home/home_basement_default.scenario" +} diff --git a/scenes/home_bedroom.json b/scenes/home_bedroom.json new file mode 100644 index 0000000..9ca756e --- /dev/null +++ b/scenes/home_bedroom.json @@ -0,0 +1,6 @@ +{ + "name": "home_bedroom", + "defaultBackground": "home/bedroom", + "defaultAmbient": "", + "defaultScenario": "scenarios/home/home_bedroom_default.scenario" +} diff --git a/scenes/home_kitchen.json b/scenes/home_kitchen.json new file mode 100644 index 0000000..d0366da --- /dev/null +++ b/scenes/home_kitchen.json @@ -0,0 +1,6 @@ +{ + "name": "home_kitchen", + "defaultBackground": "home/kitchen", + "defaultAmbient": "", + "defaultScenario": "scenarios/home/home_kitchen_default.scenario" +} diff --git a/scenes/home_livingroom.json b/scenes/home_livingroom.json new file mode 100644 index 0000000..9961b4d --- /dev/null +++ b/scenes/home_livingroom.json @@ -0,0 +1,6 @@ +{ + "name": "home_livingroom", + "defaultBackground": "home/livingroom", + "defaultAmbient": "", + "defaultScenario": "scenarios/home/home_livingroom_default.scenario" +} diff --git a/scenes/home_outside.json b/scenes/home_outside.json new file mode 100644 index 0000000..e387e0b --- /dev/null +++ b/scenes/home_outside.json @@ -0,0 +1,6 @@ +{ + "name": "home_outside", + "defaultBackground": "home/outside", + "defaultAmbient": "locations/home/outside/river", + "defaultScenario": "scenarios/home/home_outside_default.scenario" +} diff --git a/scenes/home_vestibule.json b/scenes/home_vestibule.json new file mode 100644 index 0000000..159e12a --- /dev/null +++ b/scenes/home_vestibule.json @@ -0,0 +1,6 @@ +{ + "name": "home_vestibule", + "defaultBackground": "home/vestibule", + "defaultAmbient": "", + "defaultScenario": "scenarios/home/home_vestibule_default.scenario" +} diff --git a/scenes/home_workroom.json b/scenes/home_workroom.json new file mode 100644 index 0000000..5d52115 --- /dev/null +++ b/scenes/home_workroom.json @@ -0,0 +1,6 @@ +{ + "name": "home_workroom", + "defaultBackground": "home/workroom", + "defaultAmbient": "", + "defaultScenario": "scenarios/home/home_workroom_default.scenario" +} diff --git a/scenes/prolog_alley.json b/scenes/prolog_alley.json new file mode 100644 index 0000000..9c25bf6 --- /dev/null +++ b/scenes/prolog_alley.json @@ -0,0 +1,6 @@ +{ + "name": "prolog_alley", + "defaultBackground": "prolog/start_lane", + "defaultAmbient": "", + "defaultScenario": "scenarios/prolog/morning_wake.scenario" +} diff --git a/scenes/prolog_graveyard.json b/scenes/prolog_graveyard.json new file mode 100644 index 0000000..1a298b0 --- /dev/null +++ b/scenes/prolog_graveyard.json @@ -0,0 +1,6 @@ +{ + "name": "prolog_graveyard", + "defaultBackground": "prolog/00025-165590409", + "defaultAmbient": "", + "defaultScenario": "scenarios/prolog/graveyard_arrival.scenario" +} diff --git a/scenes/start_scene.json b/scenes/start_scene.json new file mode 100644 index 0000000..d21856d --- /dev/null +++ b/scenes/start_scene.json @@ -0,0 +1,3 @@ +{ + "name": "start_scene" +} diff --git a/scenes/tow_outskirts.json b/scenes/tow_outskirts.json new file mode 100644 index 0000000..7b4ea65 --- /dev/null +++ b/scenes/tow_outskirts.json @@ -0,0 +1,6 @@ +{ + "name": "town_outskirts", + "defaultBackground": "town/outskirts", + "defaultAmbient": "", + "defaultScenario": "scenarios/town/town_outskirts_default.scenario" +} diff --git a/scenes/town_entry.json b/scenes/town_entry.json new file mode 100644 index 0000000..69b1dd6 --- /dev/null +++ b/scenes/town_entry.json @@ -0,0 +1,6 @@ +{ + "name": "town_entry", + "defaultBackground": ["town/town_entry_0", "town/town_entry_1", "town/town_entry_2", "town/town_entry_3", "town/town_entry_4"], + "defaultAmbient": "", + "defaultScenario": "scenarios/town/town_entry_default.scenario" +} diff --git a/shaders/2d_cubism_mask.gdshader b/shaders/2d_cubism_mask.gdshader new file mode 100644 index 0000000..8e1c74e --- /dev/null +++ b/shaders/2d_cubism_mask.gdshader @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +// SPDX-FileCopyrightText: 2023 MizunagiKB +// GDCubism shader: Mask +shader_type canvas_item; +render_mode blend_mix, unshaded; + +uniform vec4 channel : source_color; +uniform sampler2D tex_main : filter_linear_mipmap; + +void fragment() { + COLOR = channel * texture(tex_main, UV).a; +} diff --git a/shaders/2d_cubism_mask_add.gdshader b/shaders/2d_cubism_mask_add.gdshader new file mode 100644 index 0000000..0f39e7a --- /dev/null +++ b/shaders/2d_cubism_mask_add.gdshader @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: MIT +// SPDX-FileCopyrightText: 2023 MizunagiKB +// GDCubism shader: Mask + Add +shader_type canvas_item; +render_mode blend_premul_alpha, unshaded; + +uniform vec4 color_base : source_color; +uniform vec4 color_screen : source_color; +uniform vec4 color_multiply : source_color; +uniform vec4 channel : source_color; +uniform sampler2D tex_main : filter_linear_mipmap; +uniform sampler2D tex_mask : filter_linear_mipmap; + +uniform float mask_scale; +uniform vec2 canvas_size; +uniform vec2 mesh_offset; + +varying vec2 MASK_UV; +varying vec4 modulate; + +void vertex() { + vec2 mask_size = vec2(textureSize(tex_mask, 0)) / mask_scale; + vec2 mask_vtx = VERTEX - mesh_offset; + MASK_UV = mask_vtx / mask_size; + + modulate = COLOR; +} + +void fragment() { + vec4 color_tex = texture(tex_main, UV); + color_tex.rgb = color_tex.rgb * color_multiply.rgb; + + // premul alpha + color_tex.rgb = color_tex.rgb + color_screen.rgb - (color_tex.rgb * color_screen.rgb); + vec4 color_for_mask = color_tex * color_base * modulate; + color_for_mask.rgb = color_for_mask.rgb * color_for_mask.a; + + vec4 clip_mask = texture(tex_mask, MASK_UV) * channel; + + float mask_val = clip_mask.r + clip_mask.g + clip_mask.b + clip_mask.a; + color_for_mask.rgb = color_for_mask.rgb * mask_val; + COLOR = vec4(color_for_mask.rgb, 0.0); +} diff --git a/shaders/2d_cubism_mask_add_inv.gdshader b/shaders/2d_cubism_mask_add_inv.gdshader new file mode 100644 index 0000000..358ee04 --- /dev/null +++ b/shaders/2d_cubism_mask_add_inv.gdshader @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: MIT +// SPDX-FileCopyrightText: 2023 MizunagiKB +// GDCubism shader: Mask + AddInv +shader_type canvas_item; +render_mode blend_premul_alpha, unshaded; + +uniform vec4 color_base : source_color; +uniform vec4 color_screen : source_color; +uniform vec4 color_multiply : source_color; +uniform vec4 channel : source_color; +uniform sampler2D tex_main : filter_linear_mipmap; +uniform sampler2D tex_mask : filter_linear_mipmap; + +uniform float mask_scale; +uniform vec2 canvas_size; +uniform vec2 mesh_offset; + +varying vec2 MASK_UV; +varying vec4 modulate; + +void vertex() { + vec2 mask_size = vec2(textureSize(tex_mask, 0)) / mask_scale; + vec2 mask_vtx = VERTEX - mesh_offset; + MASK_UV = mask_vtx / mask_size; + + modulate = COLOR; +} + +void fragment() { + vec4 color_tex = texture(tex_main, UV); + color_tex.rgb = color_tex.rgb * color_multiply.rgb; + + // premul alpha + color_tex.rgb = color_tex.rgb + color_screen.rgb - (color_tex.rgb * color_screen.rgb); + vec4 color_for_mask = color_tex * color_base * modulate; + color_for_mask.rgb = color_for_mask.rgb * color_for_mask.a; + + vec4 clip_mask = texture(tex_mask, MASK_UV) * channel; + + float mask_val = clip_mask.r + clip_mask.g + clip_mask.b + clip_mask.a; + color_for_mask.rgb = color_for_mask.rgb * (1.0 - mask_val); + COLOR = vec4(color_for_mask.rgb, 0.0); +} diff --git a/shaders/2d_cubism_mask_mix.gdshader b/shaders/2d_cubism_mask_mix.gdshader new file mode 100644 index 0000000..34b63b4 --- /dev/null +++ b/shaders/2d_cubism_mask_mix.gdshader @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: MIT +// SPDX-FileCopyrightText: 2023 MizunagiKB +// GDCubism shader: Mask + Mix +shader_type canvas_item; +render_mode blend_premul_alpha, unshaded; + +uniform vec4 color_base : source_color; +uniform vec4 color_screen : source_color; +uniform vec4 color_multiply : source_color; +uniform vec4 channel : source_color; +uniform sampler2D tex_main : filter_linear_mipmap; +uniform sampler2D tex_mask : filter_linear_mipmap; + +uniform float mask_scale; +uniform vec2 canvas_size; +uniform vec2 mesh_offset; + +varying vec2 MASK_UV; +varying vec4 modulate; + +void vertex() { + vec2 mask_size = vec2(textureSize(tex_mask, 0)) / mask_scale; + vec2 mask_vtx = VERTEX - mesh_offset; + MASK_UV = mask_vtx / mask_size; + + modulate = COLOR; +} + +void fragment() { + vec4 color_tex = texture(tex_main, UV); + color_tex.rgb = color_tex.rgb * color_multiply.rgb; + + // premul alpha + color_tex.rgb = color_tex.rgb + color_screen.rgb - (color_tex.rgb * color_screen.rgb); + vec4 color_for_mask = color_tex * color_base * modulate; + color_for_mask.rgb = color_for_mask.rgb * color_for_mask.a; + + vec4 clip_mask = texture(tex_mask, MASK_UV) * channel; + + float mask_val = clip_mask.r + clip_mask.g + clip_mask.b + clip_mask.a; + color_for_mask = color_for_mask * mask_val; + COLOR = color_for_mask; +} diff --git a/shaders/2d_cubism_mask_mix_inv.gdshader b/shaders/2d_cubism_mask_mix_inv.gdshader new file mode 100644 index 0000000..016d9ef --- /dev/null +++ b/shaders/2d_cubism_mask_mix_inv.gdshader @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: MIT +// SPDX-FileCopyrightText: 2023 MizunagiKB +// GDCubism shader: Mask + MixInv +shader_type canvas_item; +render_mode blend_premul_alpha, unshaded; + +uniform vec4 color_base : source_color; +uniform vec4 color_screen : source_color; +uniform vec4 color_multiply : source_color; +uniform vec4 channel : source_color; +uniform sampler2D tex_main : filter_linear_mipmap; +uniform sampler2D tex_mask : filter_linear_mipmap; + +uniform float mask_scale; +uniform vec2 canvas_size; +uniform vec2 mesh_offset; + +varying vec2 MASK_UV; +varying vec4 modulate; + +void vertex() { + vec2 mask_size = vec2(textureSize(tex_mask, 0)) / mask_scale; + vec2 mask_vtx = VERTEX - mesh_offset; + MASK_UV = mask_vtx / mask_size; + + modulate = COLOR; +} + +void fragment() { + vec4 color_tex = texture(tex_main, UV); + color_tex.rgb = color_tex.rgb * color_multiply.rgb; + + // premul alpha + color_tex.rgb = color_tex.rgb + color_screen.rgb - (color_tex.rgb * color_screen.rgb); + vec4 color_for_mask = color_tex * color_base * modulate; + color_for_mask.rgb = color_for_mask.rgb * color_for_mask.a; + + vec4 clip_mask = texture(tex_mask, MASK_UV) * channel; + + float mask_val = clip_mask.r + clip_mask.g + clip_mask.b + clip_mask.a; + color_for_mask = color_for_mask * (1.0 - mask_val); + COLOR = color_for_mask; +} diff --git a/shaders/2d_cubism_mask_mul.gdshader b/shaders/2d_cubism_mask_mul.gdshader new file mode 100644 index 0000000..899c2f6 --- /dev/null +++ b/shaders/2d_cubism_mask_mul.gdshader @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: MIT +// SPDX-FileCopyrightText: 2023 MizunagiKB +// GDCubism shader: Mask + Mul +shader_type canvas_item; +render_mode blend_mul, unshaded; + +uniform vec4 color_base : source_color; +uniform vec4 color_screen : source_color; +uniform vec4 color_multiply : source_color; +uniform vec4 channel : source_color; +uniform sampler2D tex_main : filter_linear_mipmap; +uniform sampler2D tex_mask : filter_linear_mipmap; + +uniform float mask_scale; +uniform vec2 canvas_size; +uniform vec2 mesh_offset; + +varying vec2 MASK_UV; +varying vec4 modulate; + +void vertex() { + vec2 mask_size = vec2(textureSize(tex_mask, 0)) / mask_scale; + vec2 mask_vtx = VERTEX - mesh_offset; + MASK_UV = mask_vtx / mask_size; + + modulate = COLOR; +} + +void fragment() { + vec4 color_tex = texture(tex_main, UV); + color_tex.rgb = color_tex.rgb * color_multiply.rgb; + + // premul alpha + color_tex.rgb = color_tex.rgb + color_screen.rgb - (color_tex.rgb * color_screen.rgb); + vec4 color_for_mask = color_tex * color_base * modulate; + color_for_mask.rgb = color_for_mask.rgb * color_for_mask.a; + + vec4 clip_mask = texture(tex_mask, MASK_UV) * channel; + + float mask_val = clip_mask.r + clip_mask.g + clip_mask.b + clip_mask.a; + color_for_mask = color_for_mask * mask_val; + COLOR = vec4( + color_for_mask.r + (1.0 - color_for_mask.a), + color_for_mask.g + (1.0 - color_for_mask.a), + color_for_mask.b + (1.0 - color_for_mask.a), + 1.0 + ); +} diff --git a/shaders/2d_cubism_mask_mul_inv.gdshader b/shaders/2d_cubism_mask_mul_inv.gdshader new file mode 100644 index 0000000..7c65013 --- /dev/null +++ b/shaders/2d_cubism_mask_mul_inv.gdshader @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: MIT +// SPDX-FileCopyrightText: 2023 MizunagiKB +// GDCubism shader: Mask + MulInv +shader_type canvas_item; +render_mode blend_mul, unshaded; + +uniform vec4 color_base : source_color; +uniform vec4 color_screen : source_color; +uniform vec4 color_multiply : source_color; +uniform vec4 channel : source_color; +uniform sampler2D tex_main : filter_linear_mipmap; +uniform sampler2D tex_mask : filter_linear_mipmap; + +uniform float mask_scale; +uniform vec2 canvas_size; +uniform vec2 mesh_offset; + +varying vec2 MASK_UV; +varying vec4 modulate; + +void vertex() { + vec2 mask_size = vec2(textureSize(tex_mask, 0)) / mask_scale; + vec2 mask_vtx = VERTEX - mesh_offset; + MASK_UV = mask_vtx / mask_size; + + modulate = COLOR; +} + +void fragment() { + vec4 color_tex = texture(tex_main, UV); + color_tex.rgb = color_tex.rgb * color_multiply.rgb; + + // premul alpha + color_tex.rgb = color_tex.rgb + color_screen.rgb - (color_tex.rgb * color_screen.rgb); + vec4 color_for_mask = color_tex * color_base * modulate; + color_for_mask.rgb = color_for_mask.rgb * color_for_mask.a; + + vec4 clip_mask = texture(tex_mask, MASK_UV) * channel; + + float mask_val = clip_mask.r + clip_mask.g + clip_mask.b + clip_mask.a; + color_for_mask = color_for_mask * (1.0 - mask_val); + COLOR = vec4( + color_for_mask.r + (1.0 - color_for_mask.a), + color_for_mask.g + (1.0 - color_for_mask.a), + color_for_mask.b + (1.0 - color_for_mask.a), + 1.0 + ); +} diff --git a/shaders/2d_cubism_norm_add.gdshader b/shaders/2d_cubism_norm_add.gdshader new file mode 100644 index 0000000..ec2a553 --- /dev/null +++ b/shaders/2d_cubism_norm_add.gdshader @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: MIT +// SPDX-FileCopyrightText: 2023 MizunagiKB +// GDCubism shader: Add +shader_type canvas_item; +render_mode blend_premul_alpha, unshaded; + +uniform vec4 color_base : source_color; +uniform vec4 color_screen : source_color; +uniform vec4 color_multiply : source_color; +uniform vec4 channel : source_color; +uniform sampler2D tex_main : filter_linear_mipmap; + +varying vec4 modulate; + +void vertex() { + modulate = COLOR; +} + +void fragment() { + vec4 color_tex = texture(tex_main, UV); + color_tex.rgb = color_tex.rgb * color_multiply.rgb; + + // premul alpha + color_tex.rgb = (color_tex.rgb + color_screen.rgb) - (color_tex.rgb * color_screen.rgb); + vec4 color = color_tex * color_base * modulate; + COLOR = vec4(color.rgb * color.a, 0.0); +} diff --git a/shaders/2d_cubism_norm_mix.gdshader b/shaders/2d_cubism_norm_mix.gdshader new file mode 100644 index 0000000..83f33fc --- /dev/null +++ b/shaders/2d_cubism_norm_mix.gdshader @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: MIT +// SPDX-FileCopyrightText: 2023 MizunagiKB +// GDCubism shader: Mix +shader_type canvas_item; +render_mode blend_premul_alpha, unshaded; + +uniform vec4 color_base : source_color; +uniform vec4 color_screen : source_color; +uniform vec4 color_multiply : source_color; +uniform vec4 channel : source_color; +uniform sampler2D tex_main : filter_linear_mipmap; + +varying vec4 modulate; + +void vertex() { + modulate = COLOR; +} + +void fragment() { + vec4 color_tex = texture(tex_main, UV); + color_tex.rgb = color_tex.rgb * color_multiply.rgb; + + // premul alpha + color_tex.rgb = (color_tex.rgb + color_screen.rgb) - (color_tex.rgb * color_screen.rgb); + vec4 color = color_tex * color_base * modulate; + COLOR = vec4(color.rgb * color.a, color.a); +} diff --git a/shaders/2d_cubism_norm_mul.gdshader b/shaders/2d_cubism_norm_mul.gdshader new file mode 100644 index 0000000..3e15268 --- /dev/null +++ b/shaders/2d_cubism_norm_mul.gdshader @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: MIT +// SPDX-FileCopyrightText: 2023 MizunagiKB +// GDCubism shader: Mul +shader_type canvas_item; +render_mode blend_premul_alpha, unshaded; + +uniform vec4 color_base : source_color; +uniform vec4 color_screen : source_color; +uniform vec4 color_multiply : source_color; +uniform vec4 channel : source_color; +uniform sampler2D tex_main : filter_linear_mipmap; + +varying vec4 modulate; + +void vertex() { + modulate = COLOR; +} + +void fragment() { + vec4 color_tex = texture(tex_main, UV); + color_tex.rgb = color_tex.rgb * color_multiply.rgb; + + // premul alpha + color_tex.rgb = (color_tex.rgb + color_screen.rgb) - (color_tex.rgb * color_screen.rgb); + vec4 color = color_tex * color_base * modulate; + COLOR = vec4(color.rgb * color.a, color.a); +} diff --git a/shaders/SHADER_CONTRACT.md b/shaders/SHADER_CONTRACT.md new file mode 100644 index 0000000..6450d07 --- /dev/null +++ b/shaders/SHADER_CONTRACT.md @@ -0,0 +1,145 @@ +# Shader contract for gd_cubism (Live2D) + +## Overview + +gd_cubism uses 10 shaders to render Live2D models. Each drawable (mesh part) +selects one of these shaders based on its blend mode and mask configuration. +A mod can replace any shader by placing a `.gdshader` file with the same name +in its `shaders/` directory. + +## Mandatory contract + +### Uniforms — DO NOT remove or rename + +Every shader below MUST declare the uniforms listed in its section. The C++ renderer +sets these uniforms by name via `ShaderMaterial::set_shader_parameter()`. +Removing or renaming a uniform will break rendering. + +You MAY add new uniforms (e.g. `uniform float pixel_size = 4.0;`), but you +must set them manually in code via `model.GetMeshes()`. + +### Vertex shader + +All shaders MUST include `UV.y = 1.0 - UV.y;` in the vertex function. +This flips the texture vertically to match Live2D's coordinate system. + +### blend_mode must match + +The `render_mode` line must remain compatible with the blend operation +the C++ code expects. Changing `blend_premul_alpha` to `blend_mix` +will produce incorrect transparency. + +--- + +## Shader catalog + +### 1. `2d_cubism_norm_mix.gdshader` — Normal blend (most drawables) + +render_mode: `blend_premul_alpha, unshaded` + +Mandatory uniforms: +``` +uniform vec4 color_base : source_color; +uniform vec4 color_screen : source_color; +uniform vec4 color_multiply : source_color; +uniform vec4 channel : source_color; +uniform sampler2D tex_main : filter_linear_mipmap; +``` + +Varying: `varying vec4 modulate` (passed from vertex: `modulate = COLOR`) + +Fragment output: `COLOR = vec4(color.rgb * color.a, color.a);` + +### 2. `2d_cubism_norm_add.gdshader` — Additive blend + +Same uniforms and contract as norm_mix. Fragment output: +`COLOR = vec4(color.rgb * color.a, 0.0);` (alpha=0 for additive) + +### 3. `2d_cubism_norm_mul.gdshader` — Multiply blend + +Same uniforms and contract as norm_mix. + +### 4. `2d_cubism_mask.gdshader` — Mask generation (offscreen) + +render_mode: `blend_mix, unshaded` + +Mandatory uniforms: +``` +uniform vec4 channel : source_color; +uniform sampler2D tex_main : filter_linear_mipmap; +``` + +Fragment output: `COLOR = channel * texture(tex_main, UV).a;` + +This shader writes alpha to the mask texture. Not visible on screen. + +### 5–10. Masked drawable shaders + +`2d_cubism_mask_mix`, `mask_add`, `mask_mul`, `mask_mix_inv`, `mask_add_inv`, `mask_mul_inv` + +render_mode: same as their non-mask counterpart + +Mandatory uniforms (all of norm_mix PLUS): +``` +uniform sampler2D tex_mask : filter_linear_mipmap; +``` + +Additional varyings (computed in vertex): +``` +varying vec2 MASK_UV; +``` + +Mask UV computation in vertex: +```glsl +MASK_UV = (VERTEX - mesh_offset) / mask_size; +// where mask_size = textureSize(tex_mask, 0) / mask_scale +``` + +Fragment must sample `tex_mask` and multiply/lerp the main color by +the sum of mask channels: `clip_mask.r + clip_mask.g + clip_mask.b + clip_mask.a`. +The `_inv` variants invert this: `(1.0 - mask_val)`. + +--- + +## How to add custom logic + +**Safe additions** (will not break rendering): +- Add new `uniform` declarations (set values via `ShaderMaterial.SetShaderParameter`) +- Modify internal fragment calculations (e.g. pixel-art downscale) +- Add conditional logic (e.g. `if (pixel_size > 1.0) { ... }`) + +**Allowed modifications:** +- Change texture filtering: `filter_linear_mipmap` → `filter_nearest` +- Add post-processing in fragment (color grading, dithering, outline) +- Add noise/procedural effects using new uniforms + +**Forbidden modifications:** +- Remove or rename mandatory uniforms +- Change `render_mode` blend type +- Remove `UV.y = 1.0 - UV.y` from vertex +- Change the data type of mandatory uniforms (vec4 → vec3, etc.) + +--- + +## Mod override example + +To create a pixel-art Live2D shader: + +1. Copy `2d_cubism_norm_mix.gdshader` to `mods/your_mod/shaders/` +2. Add a new uniform: `uniform float pixel_size : hint_range(1.0, 16.0) = 4.0;` +3. Modify fragment to downsample: +```glsl +vec2 tex_size = vec2(textureSize(tex_main, 0)); +vec2 snapped_uv = floor(UV * tex_size / pixel_size) * pixel_size / tex_size; +vec4 color_tex = texture(tex_main, snapped_uv); +``` +4. Keep all mandatory uniforms and the vertex shader intact. +5. In code, find the material and set `pixel_size`: +```csharp +var meshes = model.GetMeshes(); +foreach (var kv in meshes) { + var mesh = (ArrayMesh)kv.Value; + var mat = (ShaderMaterial)mesh.SurfaceGetMaterial(0); + mat.SetShaderParameter("pixel_size", 4.0f); +} +``` diff --git a/sounds/battle/deadground.ogg b/sounds/battle/deadground.ogg new file mode 100644 index 0000000..f881d44 Binary files /dev/null and b/sounds/battle/deadground.ogg differ diff --git a/sounds/battle/winground.ogg b/sounds/battle/winground.ogg new file mode 100644 index 0000000..74c8dd3 Binary files /dev/null and b/sounds/battle/winground.ogg differ diff --git a/sounds/locations/home/outside/river.ogg b/sounds/locations/home/outside/river.ogg new file mode 100644 index 0000000..2b6a69b Binary files /dev/null and b/sounds/locations/home/outside/river.ogg differ diff --git a/sounds/locations/prolog/police.ogg b/sounds/locations/prolog/police.ogg new file mode 100644 index 0000000..231fcc1 Binary files /dev/null and b/sounds/locations/prolog/police.ogg differ diff --git a/sounds/locations/prolog/police_go_on.ogg b/sounds/locations/prolog/police_go_on.ogg new file mode 100644 index 0000000..d7d43e5 Binary files /dev/null and b/sounds/locations/prolog/police_go_on.ogg differ diff --git a/sounds/record_scratch.ogg b/sounds/record_scratch.ogg new file mode 100644 index 0000000..05bf438 Binary files /dev/null and b/sounds/record_scratch.ogg differ diff --git a/sounds/ui/button.ogg b/sounds/ui/button.ogg new file mode 100644 index 0000000..f65af56 Binary files /dev/null and b/sounds/ui/button.ogg differ diff --git a/sounds/ui/click.ogg b/sounds/ui/click.ogg new file mode 100644 index 0000000..6b22252 Binary files /dev/null and b/sounds/ui/click.ogg differ diff --git a/sounds/ui/close_click.ogg b/sounds/ui/close_click.ogg new file mode 100644 index 0000000..7adc2e3 Binary files /dev/null and b/sounds/ui/close_click.ogg differ diff --git a/sounds/ui/journal.ogg b/sounds/ui/journal.ogg new file mode 100644 index 0000000..b2a6506 Binary files /dev/null and b/sounds/ui/journal.ogg differ diff --git a/sounds/ui/new_character.ogg b/sounds/ui/new_character.ogg new file mode 100644 index 0000000..4cd98ca Binary files /dev/null and b/sounds/ui/new_character.ogg differ diff --git a/sounds/ui/skip.ogg b/sounds/ui/skip.ogg new file mode 100644 index 0000000..246a92c Binary files /dev/null and b/sounds/ui/skip.ogg differ diff --git a/src/EnslaveCondition.cs b/src/EnslaveCondition.cs new file mode 100644 index 0000000..cdb4c57 --- /dev/null +++ b/src/EnslaveCondition.cs @@ -0,0 +1,34 @@ +using Cthangover.Core.Characters; +using Cthangover.Core.Relationship; +using Cthangover.Core.Settings; + +namespace Cthangover.Core.Relationship +{ + /// + /// Recruitment condition that gates the "enslave" recruit option + /// behind the slave_master skill. When the player attempts to + /// recruit an NPC, the recruitment system queries all registered + /// implementations; if this condition + /// is present and the player does not have the skill, the enslavement + /// option is hidden or disabled. + /// + public class EnslaveCondition : IRecruitCondition + { + /// + /// Identifies this condition as the enslavement gate for the + /// recruitment system (maps to enslave option). + /// + public string Id => "enslave"; + + /// + /// Determines whether enslavement is available for the given enemy. + /// Checks the runtime skill data for the slave_master skill. + /// The target is provided but not inspected + /// because the condition depends solely on the player's skills. + /// + public bool CanRecruit(Character enemy, RuntimeData runtime) + { + return runtime.SkillData.HasSkill("slave_master"); + } + } +} diff --git a/src/StarterPartyInitializer.cs b/src/StarterPartyInitializer.cs new file mode 100644 index 0000000..f891d67 --- /dev/null +++ b/src/StarterPartyInitializer.cs @@ -0,0 +1,51 @@ +using Cthangover.Core.Mods; +using Cthangover.Core.Settings; + +namespace Cthangover.Core.Characters +{ + /// + /// Populates the initial player party with the default starter + /// character "Marao" when the core mod finishes loading. + /// + /// The party can only be populated during OnModResourcesReady, + /// not earlier. OnModLoaded and the constructor fire inside + /// ModRegistry.InitializeModCompiler.LoadModCode, + /// where mod JSON resources are not yet guaranteed to be accessible. + /// AddCharacterToParty chains into CharacterFactory.Get, + /// which calls ModManager.CollectJsonGroup — this requires + /// file providers to be fully set up, which only happens after the + /// entire ModRegistry.Initialize pipeline completes. + /// + /// OnModResourcesReady is invoked by ModInitializerRegistry + /// .NotifyResourcesReady at the end of SceneManager.Initialize, + /// after ModRegistry finishes discovery, SceneEventRegistry + /// is primed, and scene definitions are collected. At that point all + /// factories can safely read mod JSON data. + /// + /// Mods that introduce additional starter characters should implement + /// their own IModInitializer and call AddCharacterToParty + /// from OnModResourcesReady for their character IDs. + /// + public class StarterPartyInitializer : IModInitializer + { + /// + /// No-op: cross-mod lifecycle notifications are not needed for + /// starter party setup. Each mod's OnModResourcesReady + /// handles its own default characters independently. + /// + public void OnModLoaded(string modId) { } + + /// + /// Adds the core mod's default starter character "Marao" + /// to both Characters and BattleSet via + /// CharacterData.AddCharacterToParty. Called once, after + /// all mod file providers and JSON resources are guaranteed to + /// be accessible. + /// + public void OnModResourcesReady() + { + GameData.Instance.Runtime.CharacterData.AddCharacterToParty("Marao"); + GameData.Instance.Runtime.SkillData.AddSkill("slave_master"); + } + } +} diff --git a/status_effects/status_effects.json b/status_effects/status_effects.json new file mode 100644 index 0000000..deacc5a Binary files /dev/null and b/status_effects/status_effects.json differ diff --git a/wrappers/default.wrappertmpl b/wrappers/default.wrappertmpl new file mode 100644 index 0000000..5528ed5 --- /dev/null +++ b/wrappers/default.wrappertmpl @@ -0,0 +1,30 @@ +using Godot; +using System; +using System.Linq; +using System.Collections.Generic; + +public static class SceneBuilderScript +{ + private static Node _root; + + public static T Get(string name) where T : Node + { + return _root.GetNode(name); + } + + public static Node Get(string name) + { + return _root.GetNode(name); + } + + public static T FindNode(string nodeName) where T : Node + { + return Cthangover.Core.Scenes.SceneContextNode.FindNode(nodeName); + } + + public static void Run(Node root) + { + _root = root; + {{USER_CODE}} + } +}