Work on inital game experience mostly stable now. Juswt need to flesh out the goals system.
This commit is contained in:
@@ -31,6 +31,7 @@ sound_pool p(300);
|
||||
#include "src/inventory.nvgt"
|
||||
#include "src/pet_system.nvgt"
|
||||
#include "src/quest_system.nvgt"
|
||||
#include "src/goals.nvgt"
|
||||
#include "src/environment.nvgt"
|
||||
#include "src/combat.nvgt"
|
||||
#include "src/fylgja_system.nvgt"
|
||||
@@ -211,6 +212,7 @@ void run_game() {
|
||||
init_item_registry();
|
||||
init_pet_sounds();
|
||||
init_search_pools();
|
||||
init_goal_state();
|
||||
|
||||
while (true) {
|
||||
bool game_started = false;
|
||||
@@ -376,6 +378,9 @@ void run_game() {
|
||||
speak_with_history(get_health_report(), true);
|
||||
}
|
||||
|
||||
// Current goal key (G)
|
||||
check_goal_key();
|
||||
|
||||
// Coordinates Key
|
||||
if (key_pressed(KEY_X)) {
|
||||
string direction_label = (facing == 1) ? tr("system.direction.east") : tr("system.direction.west");
|
||||
@@ -623,6 +628,8 @@ void run_game() {
|
||||
int attack_cooldown = 1000;
|
||||
if (spear_equipped)
|
||||
attack_cooldown = 800;
|
||||
if (great_spear_equipped)
|
||||
attack_cooldown = GREAT_SPEAR_ATTACK_COOLDOWN_MS;
|
||||
if (axe_equipped)
|
||||
attack_cooldown = 1600;
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ Some of the first things you will want are a stone knife a spear a stone axe and
|
||||
- **F** fylgja menu once unlocked
|
||||
- **Tab** adventure menu outside base once per day
|
||||
- **H** health
|
||||
- **G** current goal speaks the next incomplete goal and unspent goal points
|
||||
- **T** time
|
||||
- **X** coordinates and terrain
|
||||
- **1 to 0** quick slots press in Equipment to bind an item to equip or in Inventory to bind a count check
|
||||
@@ -195,6 +196,17 @@ Pets are optional companions that can fight and retrieve drops
|
||||
- Bowstrings are crafted from sinew at a fire and used to craft bows
|
||||
- Storage is separate and accessed in the base Inventory menu when storage exists
|
||||
|
||||
## Goals and Mastery
|
||||
Completing one-time character milestones awards goal points.
|
||||
- Press **G** to hear your current goal and unspent points.
|
||||
- Open **P** (Character info) and choose **Goals** for the full menu.
|
||||
- Spend goal points in **Mastery** to unlock concrete benefits.
|
||||
|
||||
Current categories:
|
||||
- **Crafting Mastery 1** (2 points) crafted basic tools are sturdier.
|
||||
- **Crafting Mastery 2** (3 points) unlocks the great spear recipe.
|
||||
- **Crafting Mastery 3** (4 points) great spear reaches 2 tiles but has a slower attack window.
|
||||
|
||||
## Saving and Loading
|
||||
- The game auto saves daily at 6 AM in game time
|
||||
- Load from the main menu starting a new game prompts if a save exists
|
||||
|
||||
+57
@@ -462,6 +462,9 @@ crafting.weapons.prompt=Wapens. {option}
|
||||
crafting.weapons.option.spear=Speer (1 Stok, 1 Rankplant, 1 Klip) [Vereis Mes]
|
||||
crafting.weapons.option.sling=Slinger (1 Vel, 2 Rankplante)
|
||||
crafting.weapons.option.bow=Boog (1 Stok, 1 Boogstring)
|
||||
system.crafting.weapons.option.great_spear=Groot Speer (1 Speer, 1 Blok, 2 Rankplante, 2 Senuwee) [Vereis Handwerk Bemeestering 2]
|
||||
system.crafting.weapons.crafted.great_spear='n Groot Speer gemaak.
|
||||
system.crafting.weapons.great_spear.requires_mastery=Groot speer vereis Handwerk Bemeestering 2.
|
||||
crafting.weapons.crafted.spear='n Speer gemaak.
|
||||
crafting.weapons.crafted.sling='n Slinger gemaak.
|
||||
crafting.weapons.crafted.bow='n Boog gemaak.
|
||||
@@ -968,3 +971,57 @@ msg.fe2a9d6606e0=draugnorak
|
||||
msg.feea4a3b0a84==== Eenhoringjag ===
|
||||
msg.fefc084f67de=D of J - Tweede nota
|
||||
msg.ff5ac0b6df7b=boë
|
||||
|
||||
msg.14941e07fc96=Groot Spere
|
||||
msg.4fd74919913c=groot speer
|
||||
msg.f03527f80533=groot spere
|
||||
|
||||
system.character.info.goals=Doelwitte: {unspent} onbestee, {earned} verdien
|
||||
system.character.info.goals_menu=Doelwitte
|
||||
system.goals.all_complete=Alle huidige doelwitte voltooi. Onbestede doelpunte: {unspent}.
|
||||
system.goals.completed.entry_many={goal}. {points} doelpunte toegeken.
|
||||
system.goals.completed.entry_one={goal}. 1 doelpunt toegeken.
|
||||
system.goals.completed.none=Nog geen doelwitte voltooi nie.
|
||||
system.goals.completed.prompt=Voltooide doelwitte. {option}
|
||||
system.goals.current=Huidige doelwit: {goal}. Onbestede doelpunte: {unspent}.
|
||||
system.goals.goal.build_altar.name=Bou 'n altaar.
|
||||
system.goals.goal.build_firepit.name=Bou 'n vuurput.
|
||||
system.goals.goal.build_storage.name=Bou berging.
|
||||
system.goals.goal.complete_quest.name=Voltooi 'n soektog.
|
||||
system.goals.goal.completed=Doelwit voltooi: {goal}. {points} doelpunte toegeken.
|
||||
system.goals.goal.craft_knife.name=Maak 'n mes.
|
||||
system.goals.goal.craft_spear.name=Maak 'n speer.
|
||||
system.goals.goal.engrave_rune.name=Grafeer 'n rune.
|
||||
system.goals.goal.light_fire.name=Steek 'n vuur aan.
|
||||
system.goals.goal.unknown.name=Onbekende doelwit.
|
||||
system.goals.goal.win_adventure.name=Wen 'n avontuur.
|
||||
system.goals.menu.completed=Voltooide doelwitte
|
||||
system.goals.menu.current=Huidige doelwit: {goal}
|
||||
system.goals.menu.current_done=Huidige doelwit: alles voltooi
|
||||
system.goals.menu.earned=Totale doelpunte verdien: {earned}
|
||||
system.goals.menu.earned_solo=Totale doelpunte verdien: {earned}
|
||||
system.goals.menu.mastery=Bemeestering
|
||||
system.goals.menu.prompt=Doelwitte. {option}
|
||||
system.goals.menu.unspent=Onbestede doelpunte: {unspent}
|
||||
system.goals.menu.unspent_solo=Onbestede doelpunte: {unspent}
|
||||
system.goals.reward.many=Beloning: {count} doelpunte.
|
||||
system.goals.reward.one=Beloning: 1 doelpunt.
|
||||
|
||||
system.goals.mastery.unknown.name=Onbekende bemeestering
|
||||
system.goals.mastery.unlocked=Ontgrendel {unlock}.
|
||||
|
||||
system.goals.mastery.prompt=Bemeestering. {option}
|
||||
system.goals.mastery.crafting.level1=Gemaakte basiese gereedskap is stewiger.
|
||||
system.goals.mastery.crafting.level2=Ontsluit groot speer resep.
|
||||
system.goals.mastery.crafting.level3=Groot speer bereik 2 teëls maar het 'n stadiger aanvalsvenster.
|
||||
system.goals.mastery.crafting.name=Handwerk Bemeestering
|
||||
system.goals.mastery.unknown.name=Onbekende bemeestering
|
||||
system.goals.mastery.unknown_level=Onbekende ontgrendeling
|
||||
system.goals.mastery.maxed=Handwerk Bemeestering: maks bereik
|
||||
system.goals.mastery.summary={category} vlak {level} van {max}. Volgende koste: {cost} doelpunte.
|
||||
system.goals.mastery.unlocked=Ontgrendel {unlock}.
|
||||
system.goals.mastery.confirm=Spandeer {cost} doelpunte om {unlock} te ontgrendel?
|
||||
system.goals.mastery.already_maxed=Handwerk Bemeestering is reeds maks.
|
||||
system.goals.mastery.not_enough_points=Benodig {cost} doelpunte. Jy het {unspent}.
|
||||
system.goals.mastery.spend_failed=Kon nie die doelpunt spandeer nie.
|
||||
system.goals.menu.back=Terug
|
||||
|
||||
+68
-14
@@ -229,8 +229,56 @@ character.info.speed=Speed {status}
|
||||
character.info.pet=Pet {pet}, health {health} of {max_health}, loyalty {loyalty} of {max_loyalty}
|
||||
character.info.pet_knocked_out=Knocked out for {hours} {hour_label}.
|
||||
character.info.pet_none=No pet.
|
||||
character.info.goals=Goals: {unspent} unspent, {earned} earned
|
||||
character.info.goals_menu=Goals
|
||||
character.word.hour=hour
|
||||
character.word.hours=hours
|
||||
goals.current=Current goal: {goal}. Unspent goal points: {unspent}.
|
||||
goals.all_complete=All current goals complete. Unspent goal points: {unspent}.
|
||||
goals.goal.completed=Goal complete: {goal}. Awarded {points} goal points.
|
||||
goals.reward.one=Reward: 1 goal point.
|
||||
goals.reward.many=Reward: {count} goal points.
|
||||
goals.goal.craft_knife.name=Craft a knife.
|
||||
goals.goal.craft_spear.name=Craft a spear.
|
||||
goals.goal.build_firepit.name=Build a firepit.
|
||||
goals.goal.light_fire.name=Light a fire.
|
||||
goals.goal.build_storage.name=Build storage.
|
||||
goals.goal.build_altar.name=Build an altar.
|
||||
goals.goal.complete_quest.name=Complete a quest.
|
||||
goals.goal.win_adventure.name=Win an adventure.
|
||||
goals.goal.engrave_rune.name=Engrave a rune.
|
||||
goals.goal.unknown.name=Unknown goal.
|
||||
goals.menu.prompt=Goals. {option}
|
||||
goals.menu.current=Current goal: {goal}
|
||||
goals.menu.current_done=Current goal: all complete
|
||||
goals.menu.completed=Completed goals
|
||||
goals.menu.mastery=Mastery
|
||||
goals.menu.unspent=Unspent goal points: {unspent}
|
||||
goals.menu.unspent_solo=Unspent goal points: {unspent}
|
||||
goals.menu.earned=Total goal points earned: {earned}
|
||||
goals.menu.earned_solo=Total goal points earned: {earned}
|
||||
goals.menu.back=Back
|
||||
goals.completed.prompt=Completed goals. {option}
|
||||
goals.completed.none=No goals completed yet.
|
||||
goals.completed.entry_one={goal}. Awarded 1 goal point.
|
||||
goals.completed.entry_many={goal}. Awarded {points} goal points.
|
||||
goals.mastery.prompt=Mastery. {option}
|
||||
goals.mastery.crafting.name=Crafting Mastery
|
||||
goals.mastery.unknown.name=Unknown mastery
|
||||
goals.mastery.unknown_level=Unknown unlock
|
||||
goals.mastery.maxed=Crafting Mastery: maxed out
|
||||
goals.mastery.summary={category} level {level} of {max}. Next cost: {cost} goal points.
|
||||
goals.mastery.unlocked=Unlocked {unlock}.
|
||||
goals.mastery.confirm=Spend {cost} goal points to unlock {unlock}?
|
||||
goals.mastery.already_maxed=Crafting Mastery is already maxed out.
|
||||
goals.mastery.not_enough_points=Need {cost} goal points. You have {unspent}.
|
||||
goals.mastery.spend_failed=Could not spend the goal point.
|
||||
goals.mastery.crafting.level1=Crafted basic tools are sturdier.
|
||||
goals.mastery.crafting.level2=Unlock great spear recipe.
|
||||
goals.mastery.crafting.level3=Great spear reaches 2 tiles but has a slower attack window.
|
||||
crafting.weapons.option.great_spear=Great Spear (1 Spear, 1 Log, 2 Vines, 2 Sinew) [Requires Crafting Mastery 2]
|
||||
crafting.weapons.crafted.great_spear=Crafted a Great Spear.
|
||||
crafting.weapons.great_spear.requires_mastery=Great spear requires Crafting Mastery 2.
|
||||
pet.default_name=pet
|
||||
pet.returned=A {pet} returns to you.
|
||||
pet.knocked_out=Your {pet} has been knocked out.
|
||||
@@ -622,7 +670,7 @@ msg.03268c7d7239=backpacks
|
||||
msg.03976920927e=rope
|
||||
; src/item_registry.nvgt:item_display:small_game
|
||||
msg.0406529811c7=Small Game
|
||||
; draugnorak.nvgt:608:ui_info_box[2]
|
||||
; draugnorak.nvgt:653:ui_info_box[2]
|
||||
msg.041d8413712d=A crash log was written to your save data folder.
|
||||
; seed:learn_sounds_label:sounds/enemies/vampyr1.ogg
|
||||
msg.04a8916a9494=vampyr1
|
||||
@@ -668,6 +716,8 @@ msg.126dd3b70a5c=Logs
|
||||
msg.136e4cb03bd5=Failed to save file
|
||||
; src/item_registry.nvgt:item_plural:quivers
|
||||
msg.145ba8a7a0f2=quivers
|
||||
; src/item_registry.nvgt:item_display:great_spears
|
||||
msg.14941e07fc96=Great Spears
|
||||
; src/bosses/bandit_hideout.nvgt:860:insert_last[0]
|
||||
msg.14f5f5ff4f76=No survivors were found.
|
||||
; seed:learn_sounds_label:sounds/game/game_falls.ogg
|
||||
@@ -858,19 +908,21 @@ msg.4f773e9d5bf0=Bows
|
||||
msg.4f7f358cd341=goose
|
||||
; src/item_registry.nvgt:item_display:clay_pots
|
||||
msg.4f99d3d5b638=Clay Pots
|
||||
; src/item_registry.nvgt:item_singular:great_spear
|
||||
msg.4fd74919913c=great spear
|
||||
; seed:learn_sounds_label:sounds/game/turkey.ogg
|
||||
msg.5009c8e190ee=turkey
|
||||
; src/quests/skeletal_bard_game.nvgt:51:insert_last[0]
|
||||
msg.508e8bc0cc57=- Use Up/Down to change the number
|
||||
; seed:learn_sounds_label:sounds/weapons/sling_low_range.ogg
|
||||
msg.5123c22ce6a5=sling low range
|
||||
; draugnorak.nvgt:81:insert_last[0]
|
||||
; draugnorak.nvgt:112:insert_last[0]
|
||||
msg.528fb1c4e5fb=New Game
|
||||
; seed:learn_sounds_label:sounds/quests/squish.ogg
|
||||
msg.5460f2e3c43e=squish
|
||||
; seed:learn_sounds_label:sounds/actions/fishpole_break.ogg
|
||||
msg.546330ee64db=fishpole break
|
||||
; draugnorak.nvgt:608:ui_info_box[0]
|
||||
; draugnorak.nvgt:653:ui_info_box[0]
|
||||
msg.54fc2d657ed6=Draugnorak
|
||||
; seed:learn_sounds_label:sounds/enemies/vampyr3.ogg
|
||||
msg.55748cf43121=vampyr3
|
||||
@@ -898,7 +950,7 @@ msg.5cac31311668=Pasture is full. No livestock were recovered.
|
||||
msg.5cc7429297c8=that can be destroyed with an axe.
|
||||
; seed:learn_sounds_label:sounds/actions/cast_strength.ogg
|
||||
msg.5dfc869b7588=cast strength
|
||||
; src/time_system.nvgt:793:notify[0]
|
||||
; src/time_system.nvgt:794:notify[0]
|
||||
msg.5ea84b1201bb={arg1} favor grants you the eyes of an eagle.
|
||||
; seed:learn_sounds_label:sounds/menu/menu_select.ogg
|
||||
; seed:learn_sounds_label:sounds/menu.bak/menu_select.ogg
|
||||
@@ -982,8 +1034,8 @@ msg.7e83de91b4a2=bandit female dies
|
||||
msg.7f7e3bbf8864=An enemy is no longer in range of your currently wielded weapon.
|
||||
; src/item_registry.nvgt:item_display:backpacks
|
||||
msg.7fae743693f4=Backpacks
|
||||
; draugnorak.nvgt:194:ui_info_box[1]
|
||||
; draugnorak.nvgt:208:ui_info_box[1]
|
||||
; draugnorak.nvgt:231:ui_info_box[1]
|
||||
; draugnorak.nvgt:245:ui_info_box[1]
|
||||
msg.802aa6576577=Load Game
|
||||
; src/item_registry.nvgt:item_plural:sticks
|
||||
msg.803e4c41bbd2=sticks
|
||||
@@ -992,8 +1044,8 @@ msg.803e4c41bbd2=sticks
|
||||
msg.80655da8d80a=tree
|
||||
; src/item_registry.nvgt:item_plural:canoes
|
||||
msg.806baaf8e039=canoes
|
||||
; src/time_system.nvgt:775:notify[0]
|
||||
; src/time_system.nvgt:785:notify[0]
|
||||
; src/time_system.nvgt:776:notify[0]
|
||||
; src/time_system.nvgt:786:notify[0]
|
||||
msg.81df04a81e24={arg1} favor shines upon you. {arg2}
|
||||
; src/quests/catch_the_boomerang_game.nvgt:22:insert_last[0]
|
||||
msg.823be948275f=- Better timing earns more points (up to 4)
|
||||
@@ -1019,7 +1071,7 @@ msg.86e257c3efcb=Oldest notification. {arg1}
|
||||
msg.87383ce4344d=Bowstrings
|
||||
; src/item_registry.nvgt:item_plural:ropes
|
||||
msg.87cdb5c91437=ropes
|
||||
; src/time_system.nvgt:789:notify[0]
|
||||
; src/time_system.nvgt:790:notify[0]
|
||||
msg.8818f1d55166={arg1} radiance fills residents with purpose.
|
||||
; src/quests/bat_invasion_game.nvgt:7:insert_last[0]
|
||||
msg.88749dbbbf09==== Bat Invasion ===
|
||||
@@ -1037,7 +1089,7 @@ msg.8f993ac20023=You enter a narrow mountain pass. A massive Unicorn blocks your
|
||||
msg.917ee46db0cd=bee
|
||||
; seed:learn_sounds_label:sounds/player_male_damage.ogg
|
||||
msg.924e0eb6b6f1=player male damage
|
||||
; src/time_system.nvgt:780:notify[0]
|
||||
; src/time_system.nvgt:781:notify[0]
|
||||
msg.9281d2fe5f08={arg1} favor shines upon you. You feel swift for a while.
|
||||
; seed:learn_sounds_label:sounds/actions/climb_rope.ogg
|
||||
msg.92abc6d6953f=climb rope
|
||||
@@ -1220,7 +1272,7 @@ msg.d0cb2acd0739=skin
|
||||
msg.d34b6217ea75=enemy falls
|
||||
; src/item_registry.nvgt:item_display:skin_gloves
|
||||
msg.d373510877fd=Skin Gloves
|
||||
; draugnorak.nvgt:608:ui_info_box[1]
|
||||
; draugnorak.nvgt:653:ui_info_box[1]
|
||||
; seed:manual
|
||||
msg.d39008c4a392=Unhandled exception
|
||||
; src/item_registry.nvgt:item_singular:backpack
|
||||
@@ -1313,7 +1365,7 @@ msg.e7409fcb54bc=feed fire
|
||||
msg.e8002c169040=wood
|
||||
; src/quests/escape_from_hel_game.nvgt:13:insert_last[0]
|
||||
msg.e8216720d30b=- Press SPACE to jump over graves
|
||||
; draugnorak.nvgt:96:insert_last[0]
|
||||
; draugnorak.nvgt:132:insert_last[0]
|
||||
msg.e8db3a42f86f=Learn Sounds
|
||||
; src/bosses/bandit_hideout.nvgt:845:insert_last[0]
|
||||
msg.e8e8f4ee7a5a=You can now engrave weapons with this rune at the crafting menu.
|
||||
@@ -1330,6 +1382,8 @@ msg.ee200b3d8ae2=Spears
|
||||
msg.eff5a5f34d9a=unicorn on bridge
|
||||
; seed:learn_sounds_label:sounds/weapons/bow_draw.ogg
|
||||
msg.f015f25c409b=bow draw
|
||||
; src/item_registry.nvgt:item_plural:great_spears
|
||||
msg.f03527f80533=great spears
|
||||
; src/item_registry.nvgt:item_display:ropes
|
||||
msg.f12b2d219fe8=Ropes
|
||||
; src/quests/catch_the_boomerang_game.nvgt:14:insert_last[0]
|
||||
@@ -1342,9 +1396,9 @@ msg.f3d964225e83=player female damage
|
||||
msg.f5cabf873590=reed
|
||||
; src/bosses/bandit_hideout.nvgt:301:insert_last[0]
|
||||
msg.f77fc018cb7b=You find a hidden bandit base deep in the forest.
|
||||
; draugnorak.nvgt:112:insert_last[0]
|
||||
; draugnorak.nvgt:148:insert_last[0]
|
||||
msg.f83b6fe3aebf=Exit
|
||||
; src/inventory_items.nvgt:460:speak_with_history[0]
|
||||
; src/inventory_items.nvgt:504:speak_with_history[0]
|
||||
; src/quests/skeletal_bard_game.nvgt:26:speak_with_history[0]
|
||||
; src/quests/skeletal_bard_game.nvgt:32:speak_with_history[0]
|
||||
msg.f85b4b604c9b={arg1}.
|
||||
|
||||
+68
-14
@@ -229,8 +229,56 @@ character.info.speed=Speed {status}
|
||||
character.info.pet=Pet {pet}, health {health} of {max_health}, loyalty {loyalty} of {max_loyalty}
|
||||
character.info.pet_knocked_out=Knocked out for {hours} {hour_label}.
|
||||
character.info.pet_none=No pet.
|
||||
character.info.goals=Goals: {unspent} unspent, {earned} earned
|
||||
character.info.goals_menu=Goals
|
||||
character.word.hour=hour
|
||||
character.word.hours=hours
|
||||
goals.current=Current goal: {goal}. Unspent goal points: {unspent}.
|
||||
goals.all_complete=All current goals complete. Unspent goal points: {unspent}.
|
||||
goals.goal.completed=Goal complete: {goal}. Awarded {points} goal points.
|
||||
goals.reward.one=Reward: 1 goal point.
|
||||
goals.reward.many=Reward: {count} goal points.
|
||||
goals.goal.craft_knife.name=Craft a knife.
|
||||
goals.goal.craft_spear.name=Craft a spear.
|
||||
goals.goal.build_firepit.name=Build a firepit.
|
||||
goals.goal.light_fire.name=Light a fire.
|
||||
goals.goal.build_storage.name=Build storage.
|
||||
goals.goal.build_altar.name=Build an altar.
|
||||
goals.goal.complete_quest.name=Complete a quest.
|
||||
goals.goal.win_adventure.name=Win an adventure.
|
||||
goals.goal.engrave_rune.name=Engrave a rune.
|
||||
goals.goal.unknown.name=Unknown goal.
|
||||
goals.menu.prompt=Goals. {option}
|
||||
goals.menu.current=Current goal: {goal}
|
||||
goals.menu.current_done=Current goal: all complete
|
||||
goals.menu.completed=Completed goals
|
||||
goals.menu.mastery=Mastery
|
||||
goals.menu.unspent=Unspent goal points: {unspent}
|
||||
goals.menu.unspent_solo=Unspent goal points: {unspent}
|
||||
goals.menu.earned=Total goal points earned: {earned}
|
||||
goals.menu.earned_solo=Total goal points earned: {earned}
|
||||
goals.menu.back=Back
|
||||
goals.completed.prompt=Completed goals. {option}
|
||||
goals.completed.none=No goals completed yet.
|
||||
goals.completed.entry_one={goal}. Awarded 1 goal point.
|
||||
goals.completed.entry_many={goal}. Awarded {points} goal points.
|
||||
goals.mastery.prompt=Mastery. {option}
|
||||
goals.mastery.crafting.name=Crafting Mastery
|
||||
goals.mastery.unknown.name=Unknown mastery
|
||||
goals.mastery.unknown_level=Unknown unlock
|
||||
goals.mastery.maxed=Crafting Mastery: maxed out
|
||||
goals.mastery.summary={category} level {level} of {max}. Next cost: {cost} goal points.
|
||||
goals.mastery.unlocked=Unlocked {unlock}.
|
||||
goals.mastery.confirm=Spend {cost} goal points to unlock {unlock}?
|
||||
goals.mastery.already_maxed=Crafting Mastery is already maxed out.
|
||||
goals.mastery.not_enough_points=Need {cost} goal points. You have {unspent}.
|
||||
goals.mastery.spend_failed=Could not spend the goal point.
|
||||
goals.mastery.crafting.level1=Crafted basic tools are sturdier.
|
||||
goals.mastery.crafting.level2=Unlock great spear recipe.
|
||||
goals.mastery.crafting.level3=Great spear reaches 2 tiles but has a slower attack window.
|
||||
crafting.weapons.option.great_spear=Great Spear (1 Spear, 1 Log, 2 Vines, 2 Sinew) [Requires Crafting Mastery 2]
|
||||
crafting.weapons.crafted.great_spear=Crafted a Great Spear.
|
||||
crafting.weapons.great_spear.requires_mastery=Great spear requires Crafting Mastery 2.
|
||||
pet.default_name=pet
|
||||
pet.returned=A {pet} returns to you.
|
||||
pet.knocked_out=Your {pet} has been knocked out.
|
||||
@@ -622,7 +670,7 @@ msg.03268c7d7239=backpacks
|
||||
msg.03976920927e=rope
|
||||
; src/item_registry.nvgt:item_display:small_game
|
||||
msg.0406529811c7=Small Game
|
||||
; draugnorak.nvgt:608:ui_info_box[2]
|
||||
; draugnorak.nvgt:653:ui_info_box[2]
|
||||
msg.041d8413712d=A crash log was written to your save data folder.
|
||||
; seed:learn_sounds_label:sounds/enemies/vampyr1.ogg
|
||||
msg.04a8916a9494=vampyr1
|
||||
@@ -668,6 +716,8 @@ msg.126dd3b70a5c=Logs
|
||||
msg.136e4cb03bd5=Failed to save file
|
||||
; src/item_registry.nvgt:item_plural:quivers
|
||||
msg.145ba8a7a0f2=quivers
|
||||
; src/item_registry.nvgt:item_display:great_spears
|
||||
msg.14941e07fc96=Great Spears
|
||||
; src/bosses/bandit_hideout.nvgt:860:insert_last[0]
|
||||
msg.14f5f5ff4f76=No survivors were found.
|
||||
; seed:learn_sounds_label:sounds/game/game_falls.ogg
|
||||
@@ -858,19 +908,21 @@ msg.4f773e9d5bf0=Bows
|
||||
msg.4f7f358cd341=goose
|
||||
; src/item_registry.nvgt:item_display:clay_pots
|
||||
msg.4f99d3d5b638=Clay Pots
|
||||
; src/item_registry.nvgt:item_singular:great_spear
|
||||
msg.4fd74919913c=great spear
|
||||
; seed:learn_sounds_label:sounds/game/turkey.ogg
|
||||
msg.5009c8e190ee=turkey
|
||||
; src/quests/skeletal_bard_game.nvgt:51:insert_last[0]
|
||||
msg.508e8bc0cc57=- Use Up/Down to change the number
|
||||
; seed:learn_sounds_label:sounds/weapons/sling_low_range.ogg
|
||||
msg.5123c22ce6a5=sling low range
|
||||
; draugnorak.nvgt:81:insert_last[0]
|
||||
; draugnorak.nvgt:112:insert_last[0]
|
||||
msg.528fb1c4e5fb=New Game
|
||||
; seed:learn_sounds_label:sounds/quests/squish.ogg
|
||||
msg.5460f2e3c43e=squish
|
||||
; seed:learn_sounds_label:sounds/actions/fishpole_break.ogg
|
||||
msg.546330ee64db=fishpole break
|
||||
; draugnorak.nvgt:608:ui_info_box[0]
|
||||
; draugnorak.nvgt:653:ui_info_box[0]
|
||||
msg.54fc2d657ed6=Draugnorak
|
||||
; seed:learn_sounds_label:sounds/enemies/vampyr3.ogg
|
||||
msg.55748cf43121=vampyr3
|
||||
@@ -898,7 +950,7 @@ msg.5cac31311668=Pasture is full. No livestock were recovered.
|
||||
msg.5cc7429297c8=that can be destroyed with an axe.
|
||||
; seed:learn_sounds_label:sounds/actions/cast_strength.ogg
|
||||
msg.5dfc869b7588=cast strength
|
||||
; src/time_system.nvgt:793:notify[0]
|
||||
; src/time_system.nvgt:794:notify[0]
|
||||
msg.5ea84b1201bb={arg1} favor grants you the eyes of an eagle.
|
||||
; seed:learn_sounds_label:sounds/menu/menu_select.ogg
|
||||
; seed:learn_sounds_label:sounds/menu.bak/menu_select.ogg
|
||||
@@ -982,8 +1034,8 @@ msg.7e83de91b4a2=bandit female dies
|
||||
msg.7f7e3bbf8864=An enemy is no longer in range of your currently wielded weapon.
|
||||
; src/item_registry.nvgt:item_display:backpacks
|
||||
msg.7fae743693f4=Backpacks
|
||||
; draugnorak.nvgt:194:ui_info_box[1]
|
||||
; draugnorak.nvgt:208:ui_info_box[1]
|
||||
; draugnorak.nvgt:231:ui_info_box[1]
|
||||
; draugnorak.nvgt:245:ui_info_box[1]
|
||||
msg.802aa6576577=Load Game
|
||||
; src/item_registry.nvgt:item_plural:sticks
|
||||
msg.803e4c41bbd2=sticks
|
||||
@@ -992,8 +1044,8 @@ msg.803e4c41bbd2=sticks
|
||||
msg.80655da8d80a=tree
|
||||
; src/item_registry.nvgt:item_plural:canoes
|
||||
msg.806baaf8e039=canoes
|
||||
; src/time_system.nvgt:775:notify[0]
|
||||
; src/time_system.nvgt:785:notify[0]
|
||||
; src/time_system.nvgt:776:notify[0]
|
||||
; src/time_system.nvgt:786:notify[0]
|
||||
msg.81df04a81e24={arg1} favor shines upon you. {arg2}
|
||||
; src/quests/catch_the_boomerang_game.nvgt:22:insert_last[0]
|
||||
msg.823be948275f=- Better timing earns more points (up to 4)
|
||||
@@ -1019,7 +1071,7 @@ msg.86e257c3efcb=Oldest notification. {arg1}
|
||||
msg.87383ce4344d=Bowstrings
|
||||
; src/item_registry.nvgt:item_plural:ropes
|
||||
msg.87cdb5c91437=ropes
|
||||
; src/time_system.nvgt:789:notify[0]
|
||||
; src/time_system.nvgt:790:notify[0]
|
||||
msg.8818f1d55166={arg1} radiance fills residents with purpose.
|
||||
; src/quests/bat_invasion_game.nvgt:7:insert_last[0]
|
||||
msg.88749dbbbf09==== Bat Invasion ===
|
||||
@@ -1037,7 +1089,7 @@ msg.8f993ac20023=You enter a narrow mountain pass. A massive Unicorn blocks your
|
||||
msg.917ee46db0cd=bee
|
||||
; seed:learn_sounds_label:sounds/player_male_damage.ogg
|
||||
msg.924e0eb6b6f1=player male damage
|
||||
; src/time_system.nvgt:780:notify[0]
|
||||
; src/time_system.nvgt:781:notify[0]
|
||||
msg.9281d2fe5f08={arg1} favor shines upon you. You feel swift for a while.
|
||||
; seed:learn_sounds_label:sounds/actions/climb_rope.ogg
|
||||
msg.92abc6d6953f=climb rope
|
||||
@@ -1220,7 +1272,7 @@ msg.d0cb2acd0739=skin
|
||||
msg.d34b6217ea75=enemy falls
|
||||
; src/item_registry.nvgt:item_display:skin_gloves
|
||||
msg.d373510877fd=Skin Gloves
|
||||
; draugnorak.nvgt:608:ui_info_box[1]
|
||||
; draugnorak.nvgt:653:ui_info_box[1]
|
||||
; seed:manual
|
||||
msg.d39008c4a392=Unhandled exception
|
||||
; src/item_registry.nvgt:item_singular:backpack
|
||||
@@ -1313,7 +1365,7 @@ msg.e7409fcb54bc=feed fire
|
||||
msg.e8002c169040=wood
|
||||
; src/quests/escape_from_hel_game.nvgt:13:insert_last[0]
|
||||
msg.e8216720d30b=- Press SPACE to jump over graves
|
||||
; draugnorak.nvgt:96:insert_last[0]
|
||||
; draugnorak.nvgt:132:insert_last[0]
|
||||
msg.e8db3a42f86f=Learn Sounds
|
||||
; src/bosses/bandit_hideout.nvgt:845:insert_last[0]
|
||||
msg.e8e8f4ee7a5a=You can now engrave weapons with this rune at the crafting menu.
|
||||
@@ -1330,6 +1382,8 @@ msg.ee200b3d8ae2=Spears
|
||||
msg.eff5a5f34d9a=unicorn on bridge
|
||||
; seed:learn_sounds_label:sounds/weapons/bow_draw.ogg
|
||||
msg.f015f25c409b=bow draw
|
||||
; src/item_registry.nvgt:item_plural:great_spears
|
||||
msg.f03527f80533=great spears
|
||||
; src/item_registry.nvgt:item_display:ropes
|
||||
msg.f12b2d219fe8=Ropes
|
||||
; src/quests/catch_the_boomerang_game.nvgt:14:insert_last[0]
|
||||
@@ -1342,9 +1396,9 @@ msg.f3d964225e83=player female damage
|
||||
msg.f5cabf873590=reed
|
||||
; src/bosses/bandit_hideout.nvgt:301:insert_last[0]
|
||||
msg.f77fc018cb7b=You find a hidden bandit base deep in the forest.
|
||||
; draugnorak.nvgt:112:insert_last[0]
|
||||
; draugnorak.nvgt:148:insert_last[0]
|
||||
msg.f83b6fe3aebf=Exit
|
||||
; src/inventory_items.nvgt:460:speak_with_history[0]
|
||||
; src/inventory_items.nvgt:504:speak_with_history[0]
|
||||
; src/quests/skeletal_bard_game.nvgt:26:speak_with_history[0]
|
||||
; src/quests/skeletal_bard_game.nvgt:32:speak_with_history[0]
|
||||
msg.f85b4b604c9b={arg1}.
|
||||
|
||||
+57
@@ -462,6 +462,9 @@ crafting.weapons.prompt=Armas. {option}
|
||||
crafting.weapons.option.spear=Lanza (1 Palo, 1 Liana, 1 Piedra) [Requiere Cuchillo]
|
||||
crafting.weapons.option.sling=Honda (1 Piel, 2 Lianas)
|
||||
crafting.weapons.option.bow=Arco (1 Palo, 1 Cuerda de arco)
|
||||
system.crafting.weapons.option.great_spear=Lanza Grande (1 Lanza, 1 Tronco, 2 Lianas, 2 Tendones) [Requiere Maestría de Fabricación 2]
|
||||
system.crafting.weapons.crafted.great_spear=Fabricaste una lanza grande.
|
||||
system.crafting.weapons.great_spear.requires_mastery=La lanza grande requiere Maestría de Fabricación 2.
|
||||
crafting.weapons.crafted.spear=Fabricaste una lanza.
|
||||
crafting.weapons.crafted.sling=Fabricaste una honda.
|
||||
crafting.weapons.crafted.bow=Fabricaste un arco.
|
||||
@@ -968,3 +971,57 @@ msg.fe2a9d6606e0=draugnorak
|
||||
msg.feea4a3b0a84==== Unicornio Hunt ===
|
||||
msg.fefc084f67de=D o J - Segunda nota
|
||||
msg.ff5ac0b6df7b=arcos
|
||||
|
||||
msg.14941e07fc96=Grandes Lanzas
|
||||
msg.4fd74919913c=lanza grande
|
||||
msg.f03527f80533=grandes lanzas
|
||||
|
||||
system.character.info.goals=Objetivos: {unspent} sin gastar, {earned} ganados
|
||||
system.character.info.goals_menu=Objetivos
|
||||
system.goals.all_complete=Todos los objetivos actuales completados. Puntos sin gastar: {unspent}.
|
||||
system.goals.completed.entry_many={goal}. {points} puntos otorgados.
|
||||
system.goals.completed.entry_one={goal}. 1 punto otorgado.
|
||||
system.goals.completed.none=Aún no se han completado objetivos.
|
||||
system.goals.completed.prompt=Objetivos completados. {option}
|
||||
system.goals.current=Objetivo actual: {goal}. Puntos sin gastar: {unspent}.
|
||||
system.goals.goal.build_altar.name=Construye un altar.
|
||||
system.goals.goal.build_firepit.name=Construye un fogón.
|
||||
system.goals.goal.build_storage.name=Construye almacenamiento.
|
||||
system.goals.goal.complete_quest.name=Completa una misión.
|
||||
system.goals.goal.completed=Objetivo completado: {goal}. {points} puntos otorgados.
|
||||
system.goals.goal.craft_knife.name=Fabrica un cuchillo.
|
||||
system.goals.goal.craft_spear.name=Fabrica una lanza.
|
||||
system.goals.goal.engrave_rune.name=Graba una runa.
|
||||
system.goals.goal.light_fire.name=Enciende un fuego.
|
||||
system.goals.goal.unknown.name=Objetivo desconocido.
|
||||
system.goals.goal.win_adventure.name=Gana una aventura.
|
||||
system.goals.menu.completed=Objetivos completados
|
||||
system.goals.menu.current=Objetivo actual: {goal}
|
||||
system.goals.menu.current_done=Objetivo actual: todo completado
|
||||
system.goals.menu.earned=Puntos totales ganados: {earned}
|
||||
system.goals.menu.earned_solo=Puntos totales ganados: {earned}
|
||||
system.goals.menu.mastery=Maestría
|
||||
system.goals.menu.prompt=Objetivos. {option}
|
||||
system.goals.menu.unspent=Puntos sin gastar: {unspent}
|
||||
system.goals.menu.unspent_solo=Puntos sin gastar: {unspent}
|
||||
system.goals.reward.many=Recompensa: {count} puntos.
|
||||
system.goals.reward.one=Recompensa: 1 punto.
|
||||
|
||||
system.goals.mastery.unknown.name=Maestría desconocida
|
||||
system.goals.mastery.unlocked=Desbloqueado {unlock}.
|
||||
|
||||
system.goals.mastery.prompt=Maestría. {option}
|
||||
system.goals.mastery.crafting.level1=Las herramientas básicas fabricadas son más resistentes.
|
||||
system.goals.mastery.crafting.level2=Desbloquea la receta de la lanza grande.
|
||||
system.goals.mastery.crafting.level3=La lanza grande alcanza 2 casillas pero tiene una ventana de ataque más lenta.
|
||||
system.goals.mastery.crafting.name=Maestría de Fabricación
|
||||
system.goals.mastery.unknown.name=Maestría desconocida
|
||||
system.goals.mastery.unknown_level=Desbloqueo desconocido
|
||||
system.goals.mastery.maxed=Maestría de Fabricación: al máximo
|
||||
system.goals.mastery.summary={category} nivel {level} de {max}. Coste siguiente: {cost} puntos.
|
||||
system.goals.mastery.unlocked=Desbloqueado {unlock}.
|
||||
system.goals.mastery.confirm=¿Gastar {cost} puntos para desbloquear {unlock}?
|
||||
system.goals.mastery.already_maxed=La Maestría de Fabricación ya está al máximo.
|
||||
system.goals.mastery.not_enough_points=Necesitas {cost} puntos. Tienes {unspent}.
|
||||
system.goals.mastery.spend_failed=No se pudo gastar el punto.
|
||||
system.goals.menu.back=Atrás
|
||||
|
||||
@@ -732,8 +732,56 @@ def write_catalog(entries: Dict[str, Dict[str, object]], output_path: Path) -> N
|
||||
("system.character.info.pet", "Pet {pet}, health {health} of {max_health}, loyalty {loyalty} of {max_loyalty}"),
|
||||
("system.character.info.pet_knocked_out", "Knocked out for {hours} {hour_label}."),
|
||||
("system.character.info.pet_none", "No pet."),
|
||||
("system.character.info.goals", "Goals: {unspent} unspent, {earned} earned"),
|
||||
("system.character.info.goals_menu", "Goals"),
|
||||
("system.character.word.hour", "hour"),
|
||||
("system.character.word.hours", "hours"),
|
||||
("system.goals.current", "Current goal: {goal}. Unspent goal points: {unspent}."),
|
||||
("system.goals.all_complete", "All current goals complete. Unspent goal points: {unspent}."),
|
||||
("system.goals.goal.completed", "Goal complete: {goal}. Awarded {points} goal points."),
|
||||
("system.goals.reward.one", "Reward: 1 goal point."),
|
||||
("system.goals.reward.many", "Reward: {count} goal points."),
|
||||
("system.goals.goal.craft_knife.name", "Craft a knife."),
|
||||
("system.goals.goal.craft_spear.name", "Craft a spear."),
|
||||
("system.goals.goal.build_firepit.name", "Build a firepit."),
|
||||
("system.goals.goal.light_fire.name", "Light a fire."),
|
||||
("system.goals.goal.build_storage.name", "Build storage."),
|
||||
("system.goals.goal.build_altar.name", "Build an altar."),
|
||||
("system.goals.goal.complete_quest.name", "Complete a quest."),
|
||||
("system.goals.goal.win_adventure.name", "Win an adventure."),
|
||||
("system.goals.goal.engrave_rune.name", "Engrave a rune."),
|
||||
("system.goals.goal.unknown.name", "Unknown goal."),
|
||||
("system.goals.menu.prompt", "Goals. {option}"),
|
||||
("system.goals.menu.current", "Current goal: {goal}"),
|
||||
("system.goals.menu.current_done", "Current goal: all complete"),
|
||||
("system.goals.menu.completed", "Completed goals"),
|
||||
("system.goals.menu.mastery", "Mastery"),
|
||||
("system.goals.menu.unspent", "Unspent goal points: {unspent}"),
|
||||
("system.goals.menu.unspent_solo", "Unspent goal points: {unspent}"),
|
||||
("system.goals.menu.earned", "Total goal points earned: {earned}"),
|
||||
("system.goals.menu.earned_solo", "Total goal points earned: {earned}"),
|
||||
("system.goals.menu.back", "Back"),
|
||||
("system.goals.completed.prompt", "Completed goals. {option}"),
|
||||
("system.goals.completed.none", "No goals completed yet."),
|
||||
("system.goals.completed.entry_one", "{goal}. Awarded 1 goal point."),
|
||||
("system.goals.completed.entry_many", "{goal}. Awarded {points} goal points."),
|
||||
("system.goals.mastery.prompt", "Mastery. {option}"),
|
||||
("system.goals.mastery.crafting.name", "Crafting Mastery"),
|
||||
("system.goals.mastery.unknown.name", "Unknown mastery"),
|
||||
("system.goals.mastery.unknown_level", "Unknown unlock"),
|
||||
("system.goals.mastery.maxed", "Crafting Mastery: maxed out"),
|
||||
("system.goals.mastery.summary", "{category} level {level} of {max}. Next cost: {cost} goal points."),
|
||||
("system.goals.mastery.unlocked", "Unlocked {unlock}."),
|
||||
("system.goals.mastery.confirm", "Spend {cost} goal points to unlock {unlock}?"),
|
||||
("system.goals.mastery.already_maxed", "Crafting Mastery is already maxed out."),
|
||||
("system.goals.mastery.not_enough_points", "Need {cost} goal points. You have {unspent}."),
|
||||
("system.goals.mastery.spend_failed", "Could not spend the goal point."),
|
||||
("system.goals.mastery.crafting.level1", "Crafted basic tools are sturdier."),
|
||||
("system.goals.mastery.crafting.level2", "Unlock great spear recipe."),
|
||||
("system.goals.mastery.crafting.level3", "Great spear reaches 2 tiles but has a slower attack window."),
|
||||
("system.crafting.weapons.option.great_spear", "Great Spear (1 Spear, 1 Log, 2 Vines, 2 Sinew) [Requires Crafting Mastery 2]"),
|
||||
("system.crafting.weapons.crafted.great_spear", "Crafted a Great Spear."),
|
||||
("system.crafting.weapons.great_spear.requires_mastery", "Great spear requires Crafting Mastery 2."),
|
||||
("system.pet.default_name", "pet"),
|
||||
("system.pet.returned", "A {pet} returns to you."),
|
||||
("system.pet.knocked_out", "Your {pet} has been knocked out."),
|
||||
|
||||
@@ -863,5 +863,6 @@ void give_bandit_hideout_rewards() {
|
||||
|
||||
i18n_translate_string_array_in_place(rewards);
|
||||
text_reader_lines(rewards, i18n_text("Bandit's Hideout"), true);
|
||||
complete_goal(GOAL_WIN_ADVENTURE);
|
||||
attempt_pet_offer_from_adventure();
|
||||
}
|
||||
|
||||
@@ -733,5 +733,6 @@ void give_unicorn_rewards() {
|
||||
|
||||
// Display rewards in text reader
|
||||
text_reader_lines(rewards, tr("system.adventure.unicorn.victory_title"), true);
|
||||
complete_goal(GOAL_WIN_ADVENTURE);
|
||||
attempt_pet_offer_from_adventure();
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ void perform_attack(int current_x) {
|
||||
perform_sling_attack(current_x);
|
||||
} else if (spear_equipped) {
|
||||
perform_spear_attack(current_x);
|
||||
} else if (great_spear_equipped) {
|
||||
perform_great_spear_attack(current_x);
|
||||
} else if (axe_equipped) {
|
||||
perform_axe_attack(current_x);
|
||||
} else {
|
||||
@@ -409,3 +411,25 @@ void release_sling_attack(int player_x) {
|
||||
play_creature_hit_sound("sounds/enemies/zombie_hit.ogg", player_x, target_x, ZOMBIE_SOUND_VOLUME_STEP);
|
||||
}
|
||||
}
|
||||
|
||||
void perform_great_spear_attack(int current_x) {
|
||||
p.play_stationary("sounds/weapons/spear_swing.ogg", false);
|
||||
|
||||
int damage = apply_weapon_rune_damage(GREAT_SPEAR_DAMAGE);
|
||||
int reach = get_great_spear_range();
|
||||
int hit_pos = attack_enemy_ranged(current_x - reach, current_x + reach, damage);
|
||||
if (hit_pos != -1) {
|
||||
p.play_stationary("sounds/weapons/spear_hit.ogg", false);
|
||||
if (get_bandit_at(hit_pos) != null) {
|
||||
play_creature_hit_sound("sounds/enemies/zombie_hit.ogg", x, hit_pos, BANDIT_SOUND_VOLUME_STEP);
|
||||
} else if (get_boar_at(hit_pos) != null) {
|
||||
play_creature_hit_sound("sounds/enemies/zombie_hit.ogg", x, hit_pos, BOAR_SOUND_VOLUME_STEP);
|
||||
} else {
|
||||
play_creature_hit_sound("sounds/enemies/zombie_hit.ogg", x, hit_pos, ZOMBIE_SOUND_VOLUME_STEP);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Hit tree with great spear (sound only, 0 damage)
|
||||
hit_tree_with_spear(current_x);
|
||||
}
|
||||
|
||||
@@ -175,6 +175,7 @@ void craft_firepit() {
|
||||
simulate_crafting(9);
|
||||
add_personal_count(ITEM_STONES, -9);
|
||||
add_world_firepit(x);
|
||||
complete_goal(GOAL_BUILD_FIREPIT);
|
||||
speak_with_history(tr("system.crafting.buildings.firepit.built"), true);
|
||||
} else {
|
||||
speak_crafting_missing(missing);
|
||||
@@ -211,6 +212,7 @@ void craft_campfire() {
|
||||
add_personal_count(ITEM_STICKS, -2);
|
||||
// Build the fire at the firepit location, not player location
|
||||
add_world_fire(firepit.position);
|
||||
complete_goal(GOAL_LIGHT_FIRE);
|
||||
speak_with_history(tr("system.crafting.buildings.fire.built"), true);
|
||||
} else {
|
||||
speak_crafting_missing(missing);
|
||||
@@ -288,6 +290,7 @@ void craft_storage() {
|
||||
add_personal_count(ITEM_VINES, -vineCost);
|
||||
if (world_storages.length() == 0) {
|
||||
add_world_storage(x);
|
||||
complete_goal(GOAL_BUILD_STORAGE);
|
||||
}
|
||||
storage_level = targetLevel;
|
||||
dictionary storageArgs;
|
||||
@@ -381,6 +384,7 @@ void craft_altar() {
|
||||
add_personal_count(ITEM_STONES, -ALTAR_STONE_COST);
|
||||
add_personal_count(ITEM_STICKS, -ALTAR_STICK_COST);
|
||||
add_world_altar(x);
|
||||
complete_goal(GOAL_BUILD_ALTAR);
|
||||
speak_with_history(tr("system.crafting.buildings.altar.built"), true);
|
||||
} else {
|
||||
speak_crafting_missing(missing);
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
// Get the base equipment name without any rune prefix
|
||||
string get_base_equipment_name(int equip_type) {
|
||||
if (equip_type == EQUIP_GREAT_SPEAR)
|
||||
return i18n_lookup_key_with_fallback("system.equipment.name.great_spear", "Great Spear");
|
||||
if (equip_type == EQUIP_SPEAR)
|
||||
return i18n_lookup_key_with_fallback("system.equipment.name.spear", "Spear");
|
||||
if (equip_type == EQUIP_AXE)
|
||||
@@ -32,6 +34,8 @@ string get_base_equipment_name(int equip_type) {
|
||||
}
|
||||
|
||||
string get_base_equipment_name_plural(int equip_type) {
|
||||
if (equip_type == EQUIP_GREAT_SPEAR)
|
||||
return i18n_lookup_key_with_fallback("system.equipment.name_plural.great_spears", "Great Spears");
|
||||
if (equip_type == EQUIP_SPEAR)
|
||||
return i18n_lookup_key_with_fallback("system.equipment.name_plural.spears", "Spears");
|
||||
if (equip_type == EQUIP_AXE)
|
||||
@@ -61,6 +65,8 @@ string get_base_equipment_name_plural(int equip_type) {
|
||||
|
||||
// Get inventory count for an equipment type
|
||||
int get_unruned_equipment_count(int equip_type) {
|
||||
if (equip_type == EQUIP_GREAT_SPEAR)
|
||||
return get_personal_count(ITEM_GREAT_SPEARS);
|
||||
if (equip_type == EQUIP_SPEAR)
|
||||
return get_personal_count(ITEM_SPEARS);
|
||||
if (equip_type == EQUIP_AXE)
|
||||
@@ -90,6 +96,10 @@ int get_unruned_equipment_count(int equip_type) {
|
||||
|
||||
// Decrement inventory for an equipment type
|
||||
void decrement_unruned_equipment(int equip_type) {
|
||||
if (equip_type == EQUIP_GREAT_SPEAR) {
|
||||
add_personal_count(ITEM_GREAT_SPEARS, -1);
|
||||
return;
|
||||
}
|
||||
if (equip_type == EQUIP_SPEAR) {
|
||||
add_personal_count(ITEM_SPEARS, -1);
|
||||
return;
|
||||
@@ -316,6 +326,7 @@ void engrave_rune(int equip_type, int rune_type) {
|
||||
dictionary engravedArgs;
|
||||
engravedArgs.set("item", runed_name);
|
||||
speak_with_history(trf("system.crafting.runes.engraved", engravedArgs), true);
|
||||
complete_goal(GOAL_ENGRAVE_RUNE);
|
||||
} else {
|
||||
speak_crafting_missing(missing);
|
||||
}
|
||||
@@ -377,4 +388,7 @@ void engrave_rune_max(int equip_type, int rune_type) {
|
||||
engravedMaxArgs.set("item", item_name);
|
||||
engravedMaxArgs.set("rune", get_rune_name(rune_type));
|
||||
speak_with_history(trf("system.crafting.runes.engraved_max", engravedMaxArgs), true);
|
||||
if (max_craft > 0) {
|
||||
complete_goal(GOAL_ENGRAVE_RUNE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,6 +99,7 @@ void craft_knife() {
|
||||
simulate_crafting(2);
|
||||
add_personal_count(ITEM_STONES, -2);
|
||||
add_personal_count(ITEM_KNIVES, 1);
|
||||
complete_goal(GOAL_CRAFT_KNIFE);
|
||||
speak_with_history(tr("system.crafting.tools.crafted.stone_knife"), true);
|
||||
} else {
|
||||
speak_crafting_missing(missing);
|
||||
|
||||
@@ -3,6 +3,9 @@ void run_weapons_menu() {
|
||||
int selection = 0;
|
||||
string[] options = {tr("system.crafting.weapons.option.spear"), tr("system.crafting.weapons.option.sling"),
|
||||
tr("system.crafting.weapons.option.bow")};
|
||||
if (get_crafting_mastery_level() >= 2) {
|
||||
options.insert_last(tr("system.crafting.weapons.option.great_spear"));
|
||||
}
|
||||
speak_menu_prompt("system.crafting.weapons.prompt", options[selection]);
|
||||
|
||||
while (true) {
|
||||
@@ -39,6 +42,8 @@ void run_weapons_menu() {
|
||||
craft_sling();
|
||||
else if (selection == 2)
|
||||
craft_bow();
|
||||
else if (selection == 3)
|
||||
craft_great_spear();
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -50,6 +55,8 @@ void run_weapons_menu() {
|
||||
craft_sling_max();
|
||||
else if (selection == 2)
|
||||
craft_bow_max();
|
||||
else if (selection == 3)
|
||||
craft_great_spear();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -76,6 +83,7 @@ void craft_spear() {
|
||||
add_personal_count(ITEM_VINES, -1);
|
||||
add_personal_count(ITEM_STONES, -1);
|
||||
add_personal_count(ITEM_SPEARS, 1);
|
||||
complete_goal(GOAL_CRAFT_SPEAR);
|
||||
speak_with_history(tr("system.crafting.weapons.crafted.spear"), true);
|
||||
} else {
|
||||
speak_crafting_missing(missing);
|
||||
@@ -319,3 +327,37 @@ void craft_axe_max() {
|
||||
axeArgs.set("count", max_craft);
|
||||
speak_with_history(trf("system.crafting.weapons.crafted_max.stone_axes", axeArgs), true);
|
||||
}
|
||||
|
||||
// Great spear recipe: requires a base spear, extra materials, and Crafting
|
||||
// Mastery 2. Range 2 with a slower attack/recovery to balance.
|
||||
void craft_great_spear() {
|
||||
if (get_crafting_mastery_level() < 2) {
|
||||
speak_with_history(tr("system.crafting.weapons.great_spear.requires_mastery"), true);
|
||||
return;
|
||||
}
|
||||
string missing = "";
|
||||
if (get_personal_count(ITEM_SPEARS) < 1)
|
||||
missing += "1 spear ";
|
||||
if (get_personal_count(ITEM_LOGS) < 1)
|
||||
missing += "1 log ";
|
||||
if (get_personal_count(ITEM_VINES) < 2)
|
||||
missing += "2 vines ";
|
||||
if (get_personal_count(ITEM_SINEW) < 2)
|
||||
missing += "2 sinew ";
|
||||
|
||||
if (missing == "") {
|
||||
if (get_personal_count(ITEM_GREAT_SPEARS) >= get_personal_stack_limit()) {
|
||||
speak_cant_carry_any_more_item(ITEM_GREAT_SPEARS);
|
||||
return;
|
||||
}
|
||||
simulate_crafting(8);
|
||||
add_personal_count(ITEM_SPEARS, -1);
|
||||
add_personal_count(ITEM_LOGS, -1);
|
||||
add_personal_count(ITEM_VINES, -2);
|
||||
add_personal_count(ITEM_SINEW, -2);
|
||||
add_personal_count(ITEM_GREAT_SPEARS, 1);
|
||||
speak_with_history(tr("system.crafting.weapons.crafted.great_spear"), true);
|
||||
} else {
|
||||
speak_crafting_missing(missing);
|
||||
}
|
||||
}
|
||||
|
||||
+481
@@ -0,0 +1,481 @@
|
||||
// Goals and Mastery system
|
||||
// Tracks one-time character milestones, goal points, and the
|
||||
// initial Crafting Mastery spend path. See goal.md for design notes.
|
||||
|
||||
const int GOAL_CRAFT_KNIFE = 0;
|
||||
const int GOAL_CRAFT_SPEAR = 1;
|
||||
const int GOAL_BUILD_FIREPIT = 2;
|
||||
const int GOAL_LIGHT_FIRE = 3;
|
||||
const int GOAL_BUILD_STORAGE = 4;
|
||||
const int GOAL_BUILD_ALTAR = 5;
|
||||
const int GOAL_COMPLETE_QUEST = 6;
|
||||
const int GOAL_WIN_ADVENTURE = 7;
|
||||
const int GOAL_ENGRAVE_RUNE = 8;
|
||||
const int GOAL_COUNT = 9;
|
||||
|
||||
// Mastery spend categories.
|
||||
const int MASTERY_CRAFTING = 0;
|
||||
const int MASTERY_CATEGORY_COUNT = 1;
|
||||
|
||||
// Maximum spendable Crafting Mastery level in the first pass.
|
||||
const int CRAFTING_MASTERY_MAX_LEVEL = 3;
|
||||
|
||||
bool[] goalsCompleted;
|
||||
int goalPointsUnspent = 0;
|
||||
int goalPointsEarned = 0;
|
||||
int craftingMasteryLevel = 0;
|
||||
|
||||
int goal_reward_points(int goalId) {
|
||||
if (goalId == GOAL_CRAFT_KNIFE) return 1;
|
||||
if (goalId == GOAL_CRAFT_SPEAR) return 1;
|
||||
if (goalId == GOAL_BUILD_FIREPIT) return 1;
|
||||
if (goalId == GOAL_LIGHT_FIRE) return 1;
|
||||
if (goalId == GOAL_BUILD_STORAGE) return 2;
|
||||
if (goalId == GOAL_BUILD_ALTAR) return 2;
|
||||
if (goalId == GOAL_COMPLETE_QUEST) return 2;
|
||||
if (goalId == GOAL_WIN_ADVENTURE) return 3;
|
||||
if (goalId == GOAL_ENGRAVE_RUNE) return 3;
|
||||
return 0;
|
||||
}
|
||||
|
||||
string goal_name_key(int goalId) {
|
||||
if (goalId == GOAL_CRAFT_KNIFE) return "system.goals.goal.craft_knife.name";
|
||||
if (goalId == GOAL_CRAFT_SPEAR) return "system.goals.goal.craft_spear.name";
|
||||
if (goalId == GOAL_BUILD_FIREPIT) return "system.goals.goal.build_firepit.name";
|
||||
if (goalId == GOAL_LIGHT_FIRE) return "system.goals.goal.light_fire.name";
|
||||
if (goalId == GOAL_BUILD_STORAGE) return "system.goals.goal.build_storage.name";
|
||||
if (goalId == GOAL_BUILD_ALTAR) return "system.goals.goal.build_altar.name";
|
||||
if (goalId == GOAL_COMPLETE_QUEST) return "system.goals.goal.complete_quest.name";
|
||||
if (goalId == GOAL_WIN_ADVENTURE) return "system.goals.goal.win_adventure.name";
|
||||
if (goalId == GOAL_ENGRAVE_RUNE) return "system.goals.goal.engrave_rune.name";
|
||||
return "system.goals.goal.unknown.name";
|
||||
}
|
||||
|
||||
string goal_name(int goalId) {
|
||||
return tr(goal_name_key(goalId));
|
||||
}
|
||||
|
||||
string goal_summary(int goalId) {
|
||||
string name = goal_name(goalId);
|
||||
if (name == goal_name_key(goalId)) {
|
||||
if (goalId == GOAL_CRAFT_KNIFE) name = "Craft a knife.";
|
||||
else if (goalId == GOAL_CRAFT_SPEAR) name = "Craft a spear.";
|
||||
else if (goalId == GOAL_BUILD_FIREPIT) name = "Build a firepit.";
|
||||
else if (goalId == GOAL_LIGHT_FIRE) name = "Light a fire.";
|
||||
else if (goalId == GOAL_BUILD_STORAGE) name = "Build storage.";
|
||||
else if (goalId == GOAL_BUILD_ALTAR) name = "Build an altar.";
|
||||
else if (goalId == GOAL_COMPLETE_QUEST) name = "Complete a quest.";
|
||||
else if (goalId == GOAL_WIN_ADVENTURE) name = "Win an adventure.";
|
||||
else if (goalId == GOAL_ENGRAVE_RUNE) name = "Engrave a rune.";
|
||||
}
|
||||
int points = goal_reward_points(goalId);
|
||||
if (points == 1) {
|
||||
return name + " " + tr("system.goals.reward.one");
|
||||
}
|
||||
dictionary args;
|
||||
args.set("count", points);
|
||||
return name + " " + trf("system.goals.reward.many", args);
|
||||
}
|
||||
|
||||
void init_goal_state() {
|
||||
goalsCompleted.resize(GOAL_COUNT);
|
||||
for (int i = 0; i < GOAL_COUNT; i++) {
|
||||
goalsCompleted[i] = false;
|
||||
}
|
||||
goalPointsUnspent = 0;
|
||||
goalPointsEarned = 0;
|
||||
craftingMasteryLevel = 0;
|
||||
}
|
||||
|
||||
void reset_goal_state() {
|
||||
init_goal_state();
|
||||
}
|
||||
|
||||
bool is_valid_goal_id(int goalId) {
|
||||
return goalId >= 0 && goalId < GOAL_COUNT;
|
||||
}
|
||||
|
||||
bool is_goal_completed(int goalId) {
|
||||
if (!is_valid_goal_id(goalId))
|
||||
return false;
|
||||
return goalsCompleted[goalId];
|
||||
}
|
||||
|
||||
int get_current_goal_id() {
|
||||
for (int i = 0; i < GOAL_COUNT; i++) {
|
||||
if (!goalsCompleted[i]) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool complete_goal(int goalId) {
|
||||
if (!is_valid_goal_id(goalId)) {
|
||||
return false;
|
||||
}
|
||||
if (goalsCompleted[goalId]) {
|
||||
return false;
|
||||
}
|
||||
goalsCompleted[goalId] = true;
|
||||
int points = goal_reward_points(goalId);
|
||||
goalPointsUnspent += points;
|
||||
goalPointsEarned += points;
|
||||
|
||||
dictionary args;
|
||||
args.set("goal", goal_name(goalId));
|
||||
args.set("points", points);
|
||||
notify(trf("system.goals.goal.completed", args));
|
||||
return true;
|
||||
}
|
||||
|
||||
string speak_current_goal() {
|
||||
int currentId = get_current_goal_id();
|
||||
dictionary unspentArgs;
|
||||
unspentArgs.set("unspent", goalPointsUnspent);
|
||||
if (currentId == -1) {
|
||||
return trf("system.goals.all_complete", unspentArgs);
|
||||
}
|
||||
dictionary args;
|
||||
args.set("goal", goal_summary(currentId));
|
||||
args.set("unspent", goalPointsUnspent);
|
||||
return trf("system.goals.current", args);
|
||||
}
|
||||
|
||||
void check_goal_key() {
|
||||
if (key_pressed(KEY_G)) {
|
||||
speak_with_history(speak_current_goal(), true);
|
||||
}
|
||||
}
|
||||
|
||||
string mastery_category_name(int categoryId) {
|
||||
if (categoryId == MASTERY_CRAFTING) return tr("system.goals.mastery.crafting.name");
|
||||
return tr("system.goals.mastery.unknown.name");
|
||||
}
|
||||
|
||||
int mastery_current_level(int categoryId) {
|
||||
if (categoryId == MASTERY_CRAFTING) return craftingMasteryLevel;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mastery_max_level(int categoryId) {
|
||||
if (categoryId == MASTERY_CRAFTING) return CRAFTING_MASTERY_MAX_LEVEL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mastery_cost_for_next_level(int categoryId) {
|
||||
int level = mastery_current_level(categoryId);
|
||||
int maxLevel = mastery_max_level(categoryId);
|
||||
if (level >= maxLevel)
|
||||
return -1;
|
||||
if (categoryId == MASTERY_CRAFTING) {
|
||||
if (level == 0) return 2;
|
||||
if (level == 1) return 3;
|
||||
if (level == 2) return 4;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
string mastery_unlock_key(int categoryId, int level) {
|
||||
if (categoryId == MASTERY_CRAFTING) {
|
||||
if (level == 1) return "system.goals.mastery.crafting.level1";
|
||||
if (level == 2) return "system.goals.mastery.crafting.level2";
|
||||
if (level == 3) return "system.goals.mastery.crafting.level3";
|
||||
}
|
||||
return "system.goals.mastery.unknown_level";
|
||||
}
|
||||
|
||||
string mastery_unlock_label(int categoryId, int level) {
|
||||
return tr(mastery_unlock_key(categoryId, level));
|
||||
}
|
||||
|
||||
string mastery_level_summary(int categoryId) {
|
||||
int level = mastery_current_level(categoryId);
|
||||
int maxLevel = mastery_max_level(categoryId);
|
||||
int cost = mastery_cost_for_next_level(categoryId);
|
||||
if (level >= maxLevel) {
|
||||
return tr("system.goals.mastery.maxed");
|
||||
}
|
||||
dictionary args;
|
||||
args.set("category", mastery_category_name(categoryId));
|
||||
args.set("level", level);
|
||||
args.set("max", maxLevel);
|
||||
args.set("cost", cost);
|
||||
return trf("system.goals.mastery.summary", args);
|
||||
}
|
||||
|
||||
bool can_spend_mastery_point(int categoryId) {
|
||||
if (mastery_current_level(categoryId) >= mastery_max_level(categoryId))
|
||||
return false;
|
||||
int cost = mastery_cost_for_next_level(categoryId);
|
||||
if (cost < 0)
|
||||
return false;
|
||||
return goalPointsUnspent >= cost;
|
||||
}
|
||||
|
||||
bool spend_mastery_point(int categoryId) {
|
||||
int cost = mastery_cost_for_next_level(categoryId);
|
||||
if (cost < 0)
|
||||
return false;
|
||||
if (goalPointsUnspent < cost)
|
||||
return false;
|
||||
if (categoryId == MASTERY_CRAFTING) {
|
||||
if (craftingMasteryLevel >= CRAFTING_MASTERY_MAX_LEVEL)
|
||||
return false;
|
||||
goalPointsUnspent -= cost;
|
||||
craftingMasteryLevel++;
|
||||
dictionary args;
|
||||
args.set("unlock", mastery_unlock_label(categoryId, craftingMasteryLevel));
|
||||
notify(trf("system.goals.mastery.unlocked", args));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
float get_crafting_mastery_break_multiplier() {
|
||||
if (craftingMasteryLevel >= 1)
|
||||
return 0.5;
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
int get_goal_points_unspent() {
|
||||
return goalPointsUnspent;
|
||||
}
|
||||
|
||||
int get_goal_points_earned() {
|
||||
return goalPointsEarned;
|
||||
}
|
||||
|
||||
int get_crafting_mastery_level() {
|
||||
return craftingMasteryLevel;
|
||||
}
|
||||
|
||||
void run_goals_menu() {
|
||||
string[] options;
|
||||
int currentId = get_current_goal_id();
|
||||
if (currentId == -1) {
|
||||
options.insert_last(tr("system.goals.menu.current_done"));
|
||||
} else {
|
||||
dictionary args;
|
||||
args.set("goal", goal_summary(currentId));
|
||||
options.insert_last(trf("system.goals.menu.current", args));
|
||||
}
|
||||
options.insert_last(tr("system.goals.menu.completed"));
|
||||
options.insert_last(tr("system.goals.menu.mastery"));
|
||||
dictionary unspentArgs;
|
||||
unspentArgs.set("unspent", goalPointsUnspent);
|
||||
options.insert_last(trf("system.goals.menu.unspent", unspentArgs));
|
||||
dictionary earnedArgs;
|
||||
earnedArgs.set("earned", goalPointsEarned);
|
||||
options.insert_last(trf("system.goals.menu.earned", earnedArgs));
|
||||
|
||||
speak_menu_prompt("system.goals.menu.prompt", options[0]);
|
||||
int selection = 0;
|
||||
speak_with_history(options[selection], true);
|
||||
|
||||
while (true) {
|
||||
wait(5);
|
||||
if (menu_background_tick()) {
|
||||
return;
|
||||
}
|
||||
if (key_pressed(KEY_ESCAPE)) {
|
||||
speak_with_history(tr("system.menu.closed"), true);
|
||||
return;
|
||||
}
|
||||
if (key_pressed(KEY_DOWN)) {
|
||||
play_menu_move_sound();
|
||||
selection++;
|
||||
if (selection >= int(options.length()))
|
||||
selection = 0;
|
||||
speak_with_history(options[selection], true);
|
||||
}
|
||||
if (key_pressed(KEY_UP)) {
|
||||
play_menu_move_sound();
|
||||
selection--;
|
||||
if (selection < 0)
|
||||
selection = int(options.length()) - 1;
|
||||
speak_with_history(options[selection], true);
|
||||
}
|
||||
if (key_pressed(KEY_RETURN)) {
|
||||
play_menu_select_sound();
|
||||
if (selection == 0) {
|
||||
speak_with_history(speak_current_goal(), true);
|
||||
} else if (selection == 1) {
|
||||
run_completed_goals_menu();
|
||||
} else if (selection == 2) {
|
||||
run_mastery_menu();
|
||||
} else if (selection == 3) {
|
||||
dictionary args;
|
||||
args.set("unspent", goalPointsUnspent);
|
||||
speak_with_history(trf("system.goals.menu.unspent_solo", args), true);
|
||||
} else if (selection == 4) {
|
||||
dictionary args;
|
||||
args.set("earned", goalPointsEarned);
|
||||
speak_with_history(trf("system.goals.menu.earned_solo", args), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void run_completed_goals_menu() {
|
||||
int completedCount = 0;
|
||||
for (int i = 0; i < GOAL_COUNT; i++) {
|
||||
if (goalsCompleted[i]) {
|
||||
completedCount++;
|
||||
}
|
||||
}
|
||||
if (completedCount == 0) {
|
||||
speak_with_history(tr("system.goals.completed.none"), true);
|
||||
return;
|
||||
}
|
||||
|
||||
string[] options;
|
||||
for (int i = 0; i < GOAL_COUNT; i++) {
|
||||
if (!goalsCompleted[i])
|
||||
continue;
|
||||
int points = goal_reward_points(i);
|
||||
dictionary args;
|
||||
args.set("goal", goal_name(i));
|
||||
if (points == 1) {
|
||||
options.insert_last(trf("system.goals.completed.entry_one", args));
|
||||
} else {
|
||||
args.set("points", points);
|
||||
options.insert_last(trf("system.goals.completed.entry_many", args));
|
||||
}
|
||||
}
|
||||
|
||||
speak_menu_prompt("system.goals.completed.prompt", options[0]);
|
||||
int selection = 0;
|
||||
speak_with_history(options[selection], true);
|
||||
|
||||
while (true) {
|
||||
wait(5);
|
||||
if (menu_background_tick()) {
|
||||
return;
|
||||
}
|
||||
if (key_pressed(KEY_ESCAPE)) {
|
||||
speak_with_history(tr("system.menu.closed"), true);
|
||||
return;
|
||||
}
|
||||
if (key_pressed(KEY_DOWN)) {
|
||||
play_menu_move_sound();
|
||||
selection++;
|
||||
if (selection >= int(options.length()))
|
||||
selection = 0;
|
||||
speak_with_history(options[selection], true);
|
||||
}
|
||||
if (key_pressed(KEY_UP)) {
|
||||
play_menu_move_sound();
|
||||
selection--;
|
||||
if (selection < 0)
|
||||
selection = int(options.length()) - 1;
|
||||
speak_with_history(options[selection], true);
|
||||
}
|
||||
if (key_pressed(KEY_RETURN)) {
|
||||
play_menu_select_sound();
|
||||
speak_with_history(options[selection], true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void run_mastery_menu() {
|
||||
string[] options;
|
||||
int[] optionCategories;
|
||||
for (int i = 0; i < MASTERY_CATEGORY_COUNT; i++) {
|
||||
options.insert_last(mastery_level_summary(i));
|
||||
optionCategories.insert_last(i);
|
||||
}
|
||||
options.insert_last(tr("system.goals.menu.back"));
|
||||
int backIndex = int(options.length()) - 1;
|
||||
|
||||
speak_menu_prompt("system.goals.mastery.prompt", options[0]);
|
||||
int selection = 0;
|
||||
speak_with_history(options[selection], true);
|
||||
|
||||
while (true) {
|
||||
wait(5);
|
||||
if (menu_background_tick()) {
|
||||
return;
|
||||
}
|
||||
if (key_pressed(KEY_ESCAPE)) {
|
||||
speak_with_history(tr("system.menu.closed"), true);
|
||||
return;
|
||||
}
|
||||
if (key_pressed(KEY_DOWN)) {
|
||||
play_menu_move_sound();
|
||||
selection++;
|
||||
if (selection >= int(options.length()))
|
||||
selection = 0;
|
||||
speak_with_history(options[selection], true);
|
||||
}
|
||||
if (key_pressed(KEY_UP)) {
|
||||
play_menu_move_sound();
|
||||
selection--;
|
||||
if (selection < 0)
|
||||
selection = int(options.length()) - 1;
|
||||
speak_with_history(options[selection], true);
|
||||
}
|
||||
if (key_pressed(KEY_RETURN)) {
|
||||
play_menu_select_sound();
|
||||
if (selection == backIndex) {
|
||||
return;
|
||||
}
|
||||
int categoryId = optionCategories[selection];
|
||||
if (mastery_current_level(categoryId) >= mastery_max_level(categoryId)) {
|
||||
speak_with_history(tr("system.goals.mastery.already_maxed"), true);
|
||||
continue;
|
||||
}
|
||||
int cost = mastery_cost_for_next_level(categoryId);
|
||||
if (goalPointsUnspent < cost) {
|
||||
dictionary args;
|
||||
args.set("cost", cost);
|
||||
args.set("unspent", goalPointsUnspent);
|
||||
speak_with_history(trf("system.goals.mastery.not_enough_points", args), true);
|
||||
continue;
|
||||
}
|
||||
dictionary promptArgs;
|
||||
promptArgs.set("cost", cost);
|
||||
promptArgs.set("unlock", mastery_unlock_label(categoryId, mastery_current_level(categoryId) + 1));
|
||||
int confirm = ui_question("", trf("system.goals.mastery.confirm", promptArgs));
|
||||
if (confirm != 1) {
|
||||
speak_with_history(tr("system.menu.canceled"), true);
|
||||
continue;
|
||||
}
|
||||
if (spend_mastery_point(categoryId)) {
|
||||
options[selection] = mastery_level_summary(categoryId);
|
||||
speak_with_history(options[selection], true);
|
||||
} else {
|
||||
speak_with_history(tr("system.goals.mastery.spend_failed"), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string goals_serialize_completed() {
|
||||
string result = "";
|
||||
for (int i = 0; i < GOAL_COUNT; i++) {
|
||||
if (i > 0)
|
||||
result += ",";
|
||||
result += goalsCompleted[i] ? "1" : "0";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void goals_deserialize_completed(const string& in data) {
|
||||
if (goalsCompleted.length() != GOAL_COUNT) {
|
||||
goalsCompleted.resize(GOAL_COUNT);
|
||||
}
|
||||
for (int i = 0; i < GOAL_COUNT; i++) {
|
||||
goalsCompleted[i] = false;
|
||||
}
|
||||
if (data.length() == 0)
|
||||
return;
|
||||
string[] @parts = data.split(",");
|
||||
uint count = parts.length();
|
||||
if (count > uint(GOAL_COUNT))
|
||||
count = uint(GOAL_COUNT);
|
||||
for (uint i = 0; i < count; i++) {
|
||||
if (parts[i] == "1")
|
||||
goalsCompleted[i] = true;
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,14 @@ const int EQUIP_POUCH = 8;
|
||||
const int EQUIP_BOW = 9;
|
||||
const int EQUIP_BACKPACK = 10;
|
||||
const int EQUIP_FISHING_POLE = 11;
|
||||
const int EQUIP_GREAT_SPEAR = 12;
|
||||
|
||||
// Great spear equipment: long reach only after Crafting Mastery 3, with slower
|
||||
// attack recovery than a base spear at all levels.
|
||||
const int GREAT_SPEAR_BASE_RANGE = 1;
|
||||
const int GREAT_SPEAR_MASTERY_RANGE = 2;
|
||||
const int GREAT_SPEAR_DAMAGE = 5;
|
||||
const int GREAT_SPEAR_ATTACK_COOLDOWN_MS = 1100;
|
||||
|
||||
// Health bonuses from equipment
|
||||
const int HAT_MAX_HEALTH_BONUS = 1;
|
||||
@@ -25,6 +33,7 @@ const int MOCCASINS_MAX_HEALTH_BONUS = 2;
|
||||
|
||||
// Equipment state
|
||||
bool spear_equipped = false;
|
||||
bool great_spear_equipped = false;
|
||||
bool axe_equipped = false;
|
||||
bool sling_equipped = false;
|
||||
bool bow_equipped = false;
|
||||
@@ -136,6 +145,8 @@ string get_equipment_name(int equip_type) {
|
||||
|
||||
bool equipment_available(int equip_type) {
|
||||
// Check unruned items first, then runed versions
|
||||
if (equip_type == EQUIP_GREAT_SPEAR)
|
||||
return get_personal_count(ITEM_GREAT_SPEARS) > 0 || has_any_runed_version(equip_type);
|
||||
if (equip_type == EQUIP_SPEAR)
|
||||
return get_personal_count(ITEM_SPEARS) > 0 || has_any_runed_version(equip_type);
|
||||
if (equip_type == EQUIP_AXE)
|
||||
@@ -164,9 +175,10 @@ bool equipment_available(int equip_type) {
|
||||
}
|
||||
|
||||
void equip_equipment_type(int equip_type) {
|
||||
if (equip_type == EQUIP_SPEAR || equip_type == EQUIP_AXE || equip_type == EQUIP_SLING || equip_type == EQUIP_BOW ||
|
||||
equip_type == EQUIP_FISHING_POLE) {
|
||||
if (equip_type == EQUIP_SPEAR || equip_type == EQUIP_GREAT_SPEAR || equip_type == EQUIP_AXE ||
|
||||
equip_type == EQUIP_SLING || equip_type == EQUIP_BOW || equip_type == EQUIP_FISHING_POLE) {
|
||||
spear_equipped = (equip_type == EQUIP_SPEAR);
|
||||
great_spear_equipped = (equip_type == EQUIP_GREAT_SPEAR);
|
||||
axe_equipped = (equip_type == EQUIP_AXE);
|
||||
sling_equipped = (equip_type == EQUIP_SLING);
|
||||
bow_equipped = (equip_type == EQUIP_BOW);
|
||||
@@ -193,6 +205,8 @@ void equip_equipment_type(int equip_type) {
|
||||
bool equipment_is_equipped(int equip_type) {
|
||||
if (equip_type == EQUIP_SPEAR)
|
||||
return spear_equipped;
|
||||
if (equip_type == EQUIP_GREAT_SPEAR)
|
||||
return great_spear_equipped;
|
||||
if (equip_type == EQUIP_AXE)
|
||||
return axe_equipped;
|
||||
if (equip_type == EQUIP_SLING)
|
||||
@@ -221,6 +235,8 @@ bool equipment_is_equipped(int equip_type) {
|
||||
void unequip_equipment_type(int equip_type) {
|
||||
if (equip_type == EQUIP_SPEAR) {
|
||||
spear_equipped = false;
|
||||
} else if (equip_type == EQUIP_GREAT_SPEAR) {
|
||||
great_spear_equipped = false;
|
||||
} else if (equip_type == EQUIP_AXE) {
|
||||
axe_equipped = false;
|
||||
} else if (equip_type == EQUIP_SLING) {
|
||||
@@ -571,6 +587,8 @@ string format_favor(double value) {
|
||||
string get_equipped_weapon_name() {
|
||||
if (spear_equipped)
|
||||
return get_base_equipment_name(EQUIP_SPEAR);
|
||||
if (great_spear_equipped)
|
||||
return get_base_equipment_name(EQUIP_GREAT_SPEAR);
|
||||
if (axe_equipped)
|
||||
return get_base_equipment_name(EQUIP_AXE);
|
||||
if (sling_equipped)
|
||||
@@ -601,9 +619,17 @@ string get_speed_status() {
|
||||
return i18n_lookup_key_with_fallback("system.character.speed.normal", "normal");
|
||||
}
|
||||
|
||||
int get_great_spear_range() {
|
||||
if (get_crafting_mastery_level() >= 3)
|
||||
return GREAT_SPEAR_MASTERY_RANGE;
|
||||
return GREAT_SPEAR_BASE_RANGE;
|
||||
}
|
||||
|
||||
void cleanup_equipment_after_inventory_change() {
|
||||
if (!equipment_available(EQUIP_SPEAR))
|
||||
spear_equipped = false;
|
||||
if (!equipment_available(EQUIP_GREAT_SPEAR))
|
||||
great_spear_equipped = false;
|
||||
if (!equipment_available(EQUIP_AXE))
|
||||
axe_equipped = false;
|
||||
if (!equipment_available(EQUIP_SLING))
|
||||
@@ -614,7 +640,8 @@ void cleanup_equipment_after_inventory_change() {
|
||||
fishing_pole_equipped = false;
|
||||
|
||||
bool any_weapon_equipped =
|
||||
spear_equipped || axe_equipped || sling_equipped || bow_equipped || fishing_pole_equipped;
|
||||
spear_equipped || great_spear_equipped || axe_equipped || sling_equipped || bow_equipped ||
|
||||
fishing_pole_equipped;
|
||||
if (!any_weapon_equipped)
|
||||
equipped_weapon_rune = RUNE_NONE;
|
||||
|
||||
@@ -649,3 +676,22 @@ void cleanup_equipment_after_inventory_change() {
|
||||
clamp_arrows_to_quiver_limit();
|
||||
update_max_health_from_equipment();
|
||||
}
|
||||
|
||||
int get_equipped_weapon_equip_type() {
|
||||
if (spear_equipped) return EQUIP_SPEAR;
|
||||
if (great_spear_equipped) return EQUIP_GREAT_SPEAR;
|
||||
if (axe_equipped) return EQUIP_AXE;
|
||||
if (sling_equipped) return EQUIP_SLING;
|
||||
if (bow_equipped) return EQUIP_BOW;
|
||||
if (fishing_pole_equipped) return EQUIP_FISHING_POLE;
|
||||
return EQUIP_NONE;
|
||||
}
|
||||
|
||||
void unequip_all_weapons() {
|
||||
spear_equipped = false;
|
||||
great_spear_equipped = false;
|
||||
axe_equipped = false;
|
||||
sling_equipped = false;
|
||||
bow_equipped = false;
|
||||
fishing_pole_equipped = false;
|
||||
}
|
||||
|
||||
@@ -41,7 +41,8 @@ const int ITEM_FISH = 35;
|
||||
const int ITEM_SMOKED_FISH = 36;
|
||||
const int ITEM_HEAL_SCROLL = 37;
|
||||
const int ITEM_BASKET_FOOD = 38;
|
||||
const int ITEM_COUNT = 39; // Total number of item types
|
||||
const int ITEM_GREAT_SPEARS = 39;
|
||||
const int ITEM_COUNT = 40; // Total number of item types
|
||||
|
||||
// Item definition class
|
||||
class ItemDefinition {
|
||||
@@ -137,6 +138,7 @@ void init_item_registry() {
|
||||
ItemDefinition(ITEM_HEAL_SCROLL, "heal scrolls", "heal scroll", "Heal Scrolls", 0.50);
|
||||
item_registry[ITEM_BASKET_FOOD] = ItemDefinition(ITEM_BASKET_FOOD, "baskets of fruits and nuts",
|
||||
"basket of fruits and nuts", "Baskets of Fruits and Nuts", 0.15);
|
||||
item_registry[ITEM_GREAT_SPEARS] = ItemDefinition(ITEM_GREAT_SPEARS, "great spears", "great spear", "Great Spears", 1.20);
|
||||
|
||||
// Define display order for inventory menus
|
||||
// This controls the order items appear in menus
|
||||
@@ -150,7 +152,7 @@ void init_item_registry() {
|
||||
// Misc items
|
||||
ITEM_INCENSE, ITEM_HEAL_SCROLL,
|
||||
// Weapons
|
||||
ITEM_SPEARS, ITEM_SLINGS, ITEM_AXES, ITEM_BOWS, ITEM_ARROWS, ITEM_QUIVERS, ITEM_BOWSTRINGS,
|
||||
ITEM_SPEARS, ITEM_GREAT_SPEARS, ITEM_SLINGS, ITEM_AXES, ITEM_BOWS, ITEM_ARROWS, ITEM_QUIVERS, ITEM_BOWSTRINGS,
|
||||
// Tools
|
||||
ITEM_SNARES, ITEM_KNIVES, ITEM_FISHING_POLES, ITEM_ROPES, ITEM_REED_BASKETS, ITEM_CLAY_POTS, ITEM_CANOES,
|
||||
// Clothing
|
||||
|
||||
@@ -122,10 +122,18 @@ void run_character_info_menu() {
|
||||
favorArgs.set("favor", format_favor(favor));
|
||||
options.insert_last(trf("system.character.info.favor", favorArgs));
|
||||
|
||||
dictionary pointsArgs;
|
||||
pointsArgs.set("unspent", goalPointsUnspent);
|
||||
pointsArgs.set("earned", goalPointsEarned);
|
||||
options.insert_last(trf("system.character.info.goals", pointsArgs));
|
||||
|
||||
dictionary speedArgs;
|
||||
speedArgs.set("status", get_speed_status());
|
||||
options.insert_last(trf("system.character.info.speed", speedArgs));
|
||||
|
||||
int goalsOptionIndex = options.length();
|
||||
options.insert_last(tr("system.character.info.goals_menu"));
|
||||
|
||||
if (petActive) {
|
||||
dictionary petArgs;
|
||||
petArgs.set("pet", get_pet_display_name());
|
||||
@@ -215,6 +223,11 @@ void run_character_info_menu() {
|
||||
continue;
|
||||
|
||||
int optionIndex = filtered_indices[selection];
|
||||
if (optionIndex == goalsOptionIndex) {
|
||||
play_menu_select_sound();
|
||||
run_goals_menu();
|
||||
return;
|
||||
}
|
||||
if (optionIndex == petOptionIndex && petActive) {
|
||||
if (is_pet_knocked_out()) {
|
||||
dictionary args;
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
// Check if player has any equipment (including runed items)
|
||||
bool has_any_equipment() {
|
||||
// Check unruned items
|
||||
if (get_personal_count(ITEM_SPEARS) > 0 || get_personal_count(ITEM_AXES) > 0 ||
|
||||
if (get_personal_count(ITEM_SPEARS) > 0 || get_personal_count(ITEM_GREAT_SPEARS) > 0 ||
|
||||
get_personal_count(ITEM_AXES) > 0 ||
|
||||
get_personal_count(ITEM_SLINGS) > 0 || get_personal_count(ITEM_BOWS) > 0 ||
|
||||
get_personal_count(ITEM_FISHING_POLES) > 0 || get_personal_count(ITEM_SKIN_HATS) > 0 ||
|
||||
get_personal_count(ITEM_SKIN_GLOVES) > 0 || get_personal_count(ITEM_SKIN_PANTS) > 0 ||
|
||||
@@ -73,6 +74,12 @@ void run_equipment_menu() {
|
||||
equipment_types.insert_last(EQUIP_SPEAR);
|
||||
rune_types.insert_last(RUNE_NONE);
|
||||
}
|
||||
if (get_personal_count(ITEM_GREAT_SPEARS) > 0) {
|
||||
string status = get_equipment_menu_equipped_suffix(is_runed_item_equipped(EQUIP_GREAT_SPEAR, RUNE_NONE));
|
||||
options.insert_last(get_full_equipment_name(EQUIP_GREAT_SPEAR, RUNE_NONE) + status);
|
||||
equipment_types.insert_last(EQUIP_GREAT_SPEAR);
|
||||
rune_types.insert_last(RUNE_NONE);
|
||||
}
|
||||
if (get_personal_count(ITEM_SLINGS) > 0) {
|
||||
string status = get_equipment_menu_equipped_suffix(is_runed_item_equipped(EQUIP_SLING, RUNE_NONE));
|
||||
options.insert_last(get_full_equipment_name(EQUIP_SLING, RUNE_NONE) + status);
|
||||
|
||||
@@ -187,6 +187,7 @@ void apply_quest_reward(int score) {
|
||||
scoreArgs.set("score", score);
|
||||
message += "\n" + trf("system.quest.rewards.score_line", scoreArgs);
|
||||
text_reader(message, tr("system.quest.rewards.title"), true);
|
||||
complete_goal(GOAL_COMPLETE_QUEST);
|
||||
attempt_pet_offer_from_quest(score);
|
||||
}
|
||||
|
||||
|
||||
@@ -175,8 +175,13 @@ bool withdraw_runed_item(int equip_type, int rune_type) {
|
||||
}
|
||||
|
||||
// Get the rune type on equipped item for a given slot
|
||||
bool is_weapon_equipment_type(int equip_type) {
|
||||
return equip_type == EQUIP_SPEAR || equip_type == EQUIP_GREAT_SPEAR || equip_type == EQUIP_AXE ||
|
||||
equip_type == EQUIP_SLING || equip_type == EQUIP_BOW;
|
||||
}
|
||||
|
||||
int get_equipped_rune_for_slot(int equip_type) {
|
||||
if (equip_type == EQUIP_SPEAR || equip_type == EQUIP_AXE || equip_type == EQUIP_SLING || equip_type == EQUIP_BOW) {
|
||||
if (is_weapon_equipment_type(equip_type)) {
|
||||
return equipped_weapon_rune;
|
||||
}
|
||||
if (equip_type == EQUIP_HAT)
|
||||
@@ -196,7 +201,7 @@ int get_equipped_rune_for_slot(int equip_type) {
|
||||
|
||||
// Set the rune on an equipped item slot
|
||||
void set_equipped_rune_for_slot(int equip_type, int rune_type) {
|
||||
if (equip_type == EQUIP_SPEAR || equip_type == EQUIP_AXE || equip_type == EQUIP_SLING || equip_type == EQUIP_BOW) {
|
||||
if (is_weapon_equipment_type(equip_type)) {
|
||||
equipped_weapon_rune = rune_type;
|
||||
return;
|
||||
}
|
||||
@@ -235,6 +240,7 @@ void clear_equipped_rune_for_slot(int equip_type) {
|
||||
int[] get_runeable_equipment_types() {
|
||||
int[] types;
|
||||
types.insert_last(EQUIP_SPEAR);
|
||||
types.insert_last(EQUIP_GREAT_SPEAR);
|
||||
types.insert_last(EQUIP_AXE);
|
||||
types.insert_last(EQUIP_SLING);
|
||||
types.insert_last(EQUIP_BOW);
|
||||
@@ -252,6 +258,7 @@ int[] get_runeable_equipment_types_for_rune(int rune_type) {
|
||||
if (rune_type == RUNE_DESTRUCTION) {
|
||||
int[] types;
|
||||
types.insert_last(EQUIP_SPEAR);
|
||||
types.insert_last(EQUIP_GREAT_SPEAR);
|
||||
types.insert_last(EQUIP_AXE);
|
||||
types.insert_last(EQUIP_SLING);
|
||||
types.insert_last(EQUIP_BOW);
|
||||
|
||||
+31
-2
@@ -624,11 +624,13 @@ void reset_game_state() {
|
||||
blessing_search_active = false;
|
||||
reset_fylgja_state();
|
||||
reset_pet_state();
|
||||
reset_goal_state();
|
||||
|
||||
// Reset inventory using the registry system
|
||||
reset_inventory();
|
||||
|
||||
spear_equipped = false;
|
||||
great_spear_equipped = false;
|
||||
axe_equipped = false;
|
||||
sling_equipped = false;
|
||||
bow_equipped = false;
|
||||
@@ -876,6 +878,7 @@ bool save_game_state() {
|
||||
saveData.set("storage_fish_weights", join_string_array(storageFishWeightsData));
|
||||
|
||||
saveData.set("equipment_spear_equipped", spear_equipped);
|
||||
saveData.set("equipment_great_spear_equipped", great_spear_equipped);
|
||||
saveData.set("equipment_axe_equipped", axe_equipped);
|
||||
saveData.set("equipment_sling_equipped", sling_equipped);
|
||||
saveData.set("equipment_bow_equipped", bow_equipped);
|
||||
@@ -974,6 +977,11 @@ bool save_game_state() {
|
||||
}
|
||||
saveData.set("quest_queue", join_string_array(questData));
|
||||
|
||||
saveData.set("goals_completed", goals_serialize_completed());
|
||||
saveData.set("goal_points_unspent", goalPointsUnspent);
|
||||
saveData.set("goal_points_earned", goalPointsEarned);
|
||||
saveData.set("crafting_mastery_level", craftingMasteryLevel);
|
||||
|
||||
saveData.set("weather_data", serialize_weather());
|
||||
|
||||
saveData.set("world_map_size", MAP_SIZE);
|
||||
@@ -1314,6 +1322,7 @@ bool load_game_state_from_file(const string& in filename) {
|
||||
}
|
||||
|
||||
spear_equipped = get_bool(saveData, "equipment_spear_equipped", false);
|
||||
great_spear_equipped = get_bool(saveData, "equipment_great_spear_equipped", false);
|
||||
axe_equipped = get_bool(saveData, "equipment_axe_equipped", false);
|
||||
sling_equipped = get_bool(saveData, "equipment_sling_equipped", false);
|
||||
bow_equipped = get_bool(saveData, "equipment_bow_equipped", false);
|
||||
@@ -1332,7 +1341,7 @@ bool load_game_state_from_file(const string& in filename) {
|
||||
slot_count = quick_slots.length();
|
||||
for (uint i = 0; i < slot_count; i++) {
|
||||
int slot_value = parse_int(loadedQuickSlots[i]);
|
||||
if (slot_value >= EQUIP_NONE && slot_value <= EQUIP_FISHING_POLE) {
|
||||
if (slot_value >= EQUIP_NONE && slot_value <= EQUIP_GREAT_SPEAR) {
|
||||
quick_slots[i] = slot_value;
|
||||
}
|
||||
}
|
||||
@@ -1405,6 +1414,8 @@ bool load_game_state_from_file(const string& in filename) {
|
||||
// Validate equipped items now that runed items are loaded
|
||||
if (!equipment_available(EQUIP_SPEAR))
|
||||
spear_equipped = false;
|
||||
if (!equipment_available(EQUIP_GREAT_SPEAR))
|
||||
great_spear_equipped = false;
|
||||
if (!equipment_available(EQUIP_AXE))
|
||||
axe_equipped = false;
|
||||
if (!equipment_available(EQUIP_SLING))
|
||||
@@ -1415,7 +1426,8 @@ bool load_game_state_from_file(const string& in filename) {
|
||||
fishing_pole_equipped = false;
|
||||
|
||||
bool any_weapon_equipped =
|
||||
spear_equipped || axe_equipped || sling_equipped || bow_equipped || fishing_pole_equipped;
|
||||
spear_equipped || great_spear_equipped || axe_equipped || sling_equipped || bow_equipped ||
|
||||
fishing_pole_equipped;
|
||||
if (!any_weapon_equipped)
|
||||
equipped_weapon_rune = RUNE_NONE;
|
||||
|
||||
@@ -1560,6 +1572,23 @@ bool load_game_state_from_file(const string& in filename) {
|
||||
}
|
||||
}
|
||||
|
||||
init_goal_state();
|
||||
string loadedGoals;
|
||||
if (saveData.get("goals_completed", loadedGoals)) {
|
||||
goals_deserialize_completed(loadedGoals);
|
||||
}
|
||||
goalPointsUnspent = int(get_number(saveData, "goal_points_unspent", 0));
|
||||
goalPointsEarned = int(get_number(saveData, "goal_points_earned", 0));
|
||||
craftingMasteryLevel = int(get_number(saveData, "crafting_mastery_level", 0));
|
||||
if (goalPointsUnspent < 0)
|
||||
goalPointsUnspent = 0;
|
||||
if (goalPointsEarned < goalPointsUnspent)
|
||||
goalPointsEarned = goalPointsUnspent;
|
||||
if (craftingMasteryLevel < 0)
|
||||
craftingMasteryLevel = 0;
|
||||
if (craftingMasteryLevel > CRAFTING_MASTERY_MAX_LEVEL)
|
||||
craftingMasteryLevel = CRAFTING_MASTERY_MAX_LEVEL;
|
||||
|
||||
if (current_hour < 0)
|
||||
current_hour = 0;
|
||||
if (current_hour > 23)
|
||||
|
||||
@@ -147,7 +147,8 @@ void attempt_player_item_break_check() {
|
||||
return;
|
||||
|
||||
int roll = random(1, PLAYER_ITEM_BREAK_ROLL_MAX);
|
||||
int checkChance = int(playerItemBreakChance); // Floor for comparison
|
||||
float masteryMultiplier = get_crafting_mastery_break_multiplier();
|
||||
int checkChance = int(playerItemBreakChance * masteryMultiplier); // Floor for comparison
|
||||
if (roll <= checkChance) {
|
||||
int pickIndex = random(0, int(breakableItems.length()) - 1);
|
||||
int itemType = breakableItems[pickIndex];
|
||||
|
||||
@@ -28,6 +28,8 @@ int get_current_weapon_range() {
|
||||
return BOW_RANGE;
|
||||
if (spear_equipped)
|
||||
return 1;
|
||||
if (great_spear_equipped)
|
||||
return get_great_spear_range();
|
||||
if (axe_equipped)
|
||||
return 0;
|
||||
return -1;
|
||||
|
||||
Reference in New Issue
Block a user