Various bug fixes.
This commit is contained in:
@@ -10,9 +10,7 @@ class Bandit {
|
|||||||
string weapon_type; // "spear" or "axe"
|
string weapon_type; // "spear" or "axe"
|
||||||
int sound_handle;
|
int sound_handle;
|
||||||
timer move_timer;
|
timer move_timer;
|
||||||
timer alert_timer;
|
|
||||||
timer attack_timer;
|
timer attack_timer;
|
||||||
int next_alert_delay;
|
|
||||||
int move_interval;
|
int move_interval;
|
||||||
|
|
||||||
// Wandering behavior properties
|
// Wandering behavior properties
|
||||||
@@ -38,9 +36,7 @@ class Bandit {
|
|||||||
move_interval = random(BANDIT_MOVE_INTERVAL_MIN, BANDIT_MOVE_INTERVAL_MAX);
|
move_interval = random(BANDIT_MOVE_INTERVAL_MIN, BANDIT_MOVE_INTERVAL_MAX);
|
||||||
|
|
||||||
move_timer.restart();
|
move_timer.restart();
|
||||||
alert_timer.restart();
|
|
||||||
attack_timer.restart();
|
attack_timer.restart();
|
||||||
next_alert_delay = random(BANDIT_ALERT_MIN_DELAY, BANDIT_ALERT_MAX_DELAY);
|
|
||||||
|
|
||||||
// Initialize wandering behavior (start aggressive during invasion)
|
// Initialize wandering behavior (start aggressive during invasion)
|
||||||
behavior_state = "aggressive";
|
behavior_state = "aggressive";
|
||||||
@@ -87,7 +83,8 @@ void spawn_bandit(int expansion_start, int expansion_end) {
|
|||||||
|
|
||||||
Bandit@ b = Bandit(spawn_x, expansion_start, expansion_end);
|
Bandit@ b = Bandit(spawn_x, expansion_start, expansion_end);
|
||||||
bandits.insert_last(b);
|
bandits.insert_last(b);
|
||||||
b.sound_handle = play_creature_voice(b.alert_sound, x, spawn_x, BANDIT_SOUND_VOLUME_STEP);
|
// Play looping sound that follows the bandit
|
||||||
|
b.sound_handle = play_1d_with_volume_step(b.alert_sound, x, spawn_x, true, BANDIT_SOUND_VOLUME_STEP);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool can_bandit_attack_player(Bandit@ bandit) {
|
bool can_bandit_attack_player(Bandit@ bandit) {
|
||||||
@@ -177,18 +174,15 @@ void try_attack_barricade_bandit(Bandit@ bandit) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void update_bandit(Bandit@ bandit) {
|
void update_bandit(Bandit@ bandit) {
|
||||||
// Play alert sound at intervals
|
// Update looping sound position
|
||||||
if (bandit.alert_timer.elapsed > bandit.next_alert_delay) {
|
if (bandit.sound_handle != -1 && p.sound_is_active(bandit.sound_handle)) {
|
||||||
bandit.alert_timer.restart();
|
p.update_sound_1d(bandit.sound_handle, bandit.position);
|
||||||
bandit.next_alert_delay = random(BANDIT_ALERT_MIN_DELAY, BANDIT_ALERT_MAX_DELAY);
|
} else if (bandit.sound_handle == -1 || !p.sound_is_active(bandit.sound_handle)) {
|
||||||
|
// Restart looping sound if it stopped
|
||||||
// Destroy old sound handle before playing new one to prevent overlapping
|
|
||||||
if (bandit.sound_handle != -1) {
|
if (bandit.sound_handle != -1) {
|
||||||
p.destroy_sound(bandit.sound_handle);
|
p.destroy_sound(bandit.sound_handle);
|
||||||
bandit.sound_handle = -1;
|
|
||||||
}
|
}
|
||||||
|
bandit.sound_handle = play_1d_with_volume_step(bandit.alert_sound, x, bandit.position, true, BANDIT_SOUND_VOLUME_STEP);
|
||||||
bandit.sound_handle = play_creature_voice(bandit.alert_sound, x, bandit.position, BANDIT_SOUND_VOLUME_STEP);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (try_attack_player_bandit(bandit)) {
|
if (try_attack_player_bandit(bandit)) {
|
||||||
|
|||||||
@@ -38,10 +38,8 @@ class FlyingCreature {
|
|||||||
int sound_handle;
|
int sound_handle;
|
||||||
int fall_sound_handle;
|
int fall_sound_handle;
|
||||||
timer move_timer;
|
timer move_timer;
|
||||||
timer sound_timer;
|
|
||||||
timer fall_timer;
|
timer fall_timer;
|
||||||
int next_move_delay;
|
int next_move_delay;
|
||||||
int next_sound_delay;
|
|
||||||
string voice_sound;
|
string voice_sound;
|
||||||
bool fading_out;
|
bool fading_out;
|
||||||
bool ready_to_remove;
|
bool ready_to_remove;
|
||||||
@@ -63,10 +61,8 @@ class FlyingCreature {
|
|||||||
}
|
}
|
||||||
|
|
||||||
move_timer.restart();
|
move_timer.restart();
|
||||||
sound_timer.restart();
|
|
||||||
|
|
||||||
next_move_delay = random(cfg.move_interval_min, cfg.move_interval_max);
|
next_move_delay = random(cfg.move_interval_min, cfg.move_interval_max);
|
||||||
next_sound_delay = random(cfg.sound_delay_min, cfg.sound_delay_max);
|
|
||||||
fading_out = false;
|
fading_out = false;
|
||||||
ready_to_remove = false;
|
ready_to_remove = false;
|
||||||
}
|
}
|
||||||
@@ -229,7 +225,8 @@ bool spawn_flying_creature(string creature_type) {
|
|||||||
|
|
||||||
FlyingCreature@ c = FlyingCreature(creature_type, spawn_x, area_start, area_end, cfg);
|
FlyingCreature@ c = FlyingCreature(creature_type, spawn_x, area_start, area_end, cfg);
|
||||||
flying_creatures.insert_last(c);
|
flying_creatures.insert_last(c);
|
||||||
c.sound_handle = play_creature_voice(c.voice_sound, x, spawn_x, cfg.sound_volume_step);
|
// Play looping sound that follows the flying creature
|
||||||
|
c.sound_handle = play_1d_with_volume_step(c.voice_sound, x, spawn_x, true, cfg.sound_volume_step);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -267,10 +264,15 @@ void update_flying_creature(FlyingCreature@ creature) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (creature.sound_timer.elapsed > creature.next_sound_delay) {
|
// Update looping sound position
|
||||||
creature.sound_timer.restart();
|
if (creature.sound_handle != -1 && p.sound_is_active(creature.sound_handle)) {
|
||||||
creature.next_sound_delay = random(cfg.sound_delay_min, cfg.sound_delay_max);
|
p.update_sound_1d(creature.sound_handle, creature.position);
|
||||||
creature.sound_handle = play_creature_voice(creature.voice_sound, x, creature.position, cfg.sound_volume_step);
|
} else if (creature.sound_handle == -1 || !p.sound_is_active(creature.sound_handle)) {
|
||||||
|
// Restart looping sound if it stopped
|
||||||
|
if (creature.sound_handle != -1) {
|
||||||
|
p.destroy_sound(creature.sound_handle);
|
||||||
|
}
|
||||||
|
creature.sound_handle = play_1d_with_volume_step(creature.voice_sound, x, creature.position, true, cfg.sound_volume_step);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cfg.fly_away_chance > 0 && random(1, 1000) <= cfg.fly_away_chance) {
|
if (cfg.fly_away_chance > 0 && random(1, 1000) <= cfg.fly_away_chance) {
|
||||||
|
|||||||
@@ -8,10 +8,8 @@ class GroundGame {
|
|||||||
int health;
|
int health;
|
||||||
int sound_handle;
|
int sound_handle;
|
||||||
timer move_timer;
|
timer move_timer;
|
||||||
timer sound_timer;
|
|
||||||
timer attack_timer;
|
timer attack_timer;
|
||||||
int next_move_delay;
|
int next_move_delay;
|
||||||
int next_sound_delay;
|
|
||||||
string voice_sound;
|
string voice_sound;
|
||||||
string state; // "wandering" or "charging"
|
string state; // "wandering" or "charging"
|
||||||
int area_start;
|
int area_start;
|
||||||
@@ -32,11 +30,9 @@ class GroundGame {
|
|||||||
voice_sound = ground_game_boar_sounds[random(0, ground_game_boar_sounds.length() - 1)];
|
voice_sound = ground_game_boar_sounds[random(0, ground_game_boar_sounds.length() - 1)];
|
||||||
|
|
||||||
move_timer.restart();
|
move_timer.restart();
|
||||||
sound_timer.restart();
|
|
||||||
attack_timer.restart();
|
attack_timer.restart();
|
||||||
|
|
||||||
next_move_delay = random(BOAR_MOVE_INTERVAL_MIN, BOAR_MOVE_INTERVAL_MAX);
|
next_move_delay = random(BOAR_MOVE_INTERVAL_MIN, BOAR_MOVE_INTERVAL_MAX);
|
||||||
next_sound_delay = random(BOAR_SOUND_MIN_DELAY, BOAR_SOUND_MAX_DELAY);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GroundGame@[] ground_games;
|
GroundGame@[] ground_games;
|
||||||
@@ -80,7 +76,8 @@ void spawn_ground_game(int expansion_start, int expansion_end) {
|
|||||||
|
|
||||||
GroundGame@ b = GroundGame(spawn_x, expansion_start, expansion_end, "boar");
|
GroundGame@ b = GroundGame(spawn_x, expansion_start, expansion_end, "boar");
|
||||||
ground_games.insert_last(b);
|
ground_games.insert_last(b);
|
||||||
b.sound_handle = play_creature_voice(b.voice_sound, x, spawn_x, BOAR_SOUND_VOLUME_STEP);
|
// Play looping sound that follows the boar
|
||||||
|
b.sound_handle = play_1d_with_volume_step(b.voice_sound, x, spawn_x, true, BOAR_SOUND_VOLUME_STEP);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool can_ground_game_attack_player(GroundGame@ game) {
|
bool can_ground_game_attack_player(GroundGame@ game) {
|
||||||
@@ -113,12 +110,15 @@ bool try_attack_player_ground_game(GroundGame@ game) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void update_ground_game(GroundGame@ game) {
|
void update_ground_game(GroundGame@ game) {
|
||||||
// Sound logic
|
// Update looping sound position
|
||||||
if (game.sound_timer.elapsed > game.next_sound_delay) {
|
if (game.sound_handle != -1 && p.sound_is_active(game.sound_handle)) {
|
||||||
game.sound_timer.restart();
|
p.update_sound_1d(game.sound_handle, game.position);
|
||||||
game.next_sound_delay = random(BOAR_SOUND_MIN_DELAY, BOAR_SOUND_MAX_DELAY);
|
} else if (game.sound_handle == -1 || !p.sound_is_active(game.sound_handle)) {
|
||||||
// Only play if wandering or occasionally while charging
|
// Restart looping sound if it stopped for some reason
|
||||||
game.sound_handle = play_creature_voice(game.voice_sound, x, game.position, BOAR_SOUND_VOLUME_STEP);
|
if (game.sound_handle != -1) {
|
||||||
|
p.destroy_sound(game.sound_handle);
|
||||||
|
}
|
||||||
|
game.sound_handle = play_1d_with_volume_step(game.voice_sound, x, game.position, true, BOAR_SOUND_VOLUME_STEP);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Combat logic
|
// Combat logic
|
||||||
|
|||||||
@@ -10,9 +10,7 @@ class Undead {
|
|||||||
string voice_sound;
|
string voice_sound;
|
||||||
int sound_handle;
|
int sound_handle;
|
||||||
timer move_timer;
|
timer move_timer;
|
||||||
timer groan_timer;
|
|
||||||
timer attack_timer;
|
timer attack_timer;
|
||||||
int next_groan_delay;
|
|
||||||
|
|
||||||
Undead(int pos, string type = "zombie") {
|
Undead(int pos, string type = "zombie") {
|
||||||
position = pos;
|
position = pos;
|
||||||
@@ -22,9 +20,7 @@ class Undead {
|
|||||||
voice_sound = undead_zombie_sounds[sound_index];
|
voice_sound = undead_zombie_sounds[sound_index];
|
||||||
sound_handle = -1;
|
sound_handle = -1;
|
||||||
move_timer.restart();
|
move_timer.restart();
|
||||||
groan_timer.restart();
|
|
||||||
attack_timer.restart();
|
attack_timer.restart();
|
||||||
next_groan_delay = random(ZOMBIE_GROAN_MIN_DELAY, ZOMBIE_GROAN_MAX_DELAY);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Undead@[] undeads;
|
Undead@[] undeads;
|
||||||
@@ -65,7 +61,8 @@ void spawn_undead() {
|
|||||||
|
|
||||||
Undead@ z = Undead(spawn_x, "zombie");
|
Undead@ z = Undead(spawn_x, "zombie");
|
||||||
undeads.insert_last(z);
|
undeads.insert_last(z);
|
||||||
z.sound_handle = play_creature_voice(z.voice_sound, x, spawn_x, ZOMBIE_SOUND_VOLUME_STEP);
|
// Play looping sound that follows the zombie
|
||||||
|
z.sound_handle = play_1d_with_volume_step(z.voice_sound, x, spawn_x, true, ZOMBIE_SOUND_VOLUME_STEP);
|
||||||
}
|
}
|
||||||
|
|
||||||
void try_attack_barricade_undead(Undead@ undead) {
|
void try_attack_barricade_undead(Undead@ undead) {
|
||||||
@@ -131,17 +128,15 @@ bool try_attack_player_undead(Undead@ undead) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void update_undead(Undead@ undead) {
|
void update_undead(Undead@ undead) {
|
||||||
if (undead.groan_timer.elapsed > undead.next_groan_delay) {
|
// Update looping sound position
|
||||||
undead.groan_timer.restart();
|
if (undead.sound_handle != -1 && p.sound_is_active(undead.sound_handle)) {
|
||||||
undead.next_groan_delay = random(ZOMBIE_GROAN_MIN_DELAY, ZOMBIE_GROAN_MAX_DELAY);
|
p.update_sound_1d(undead.sound_handle, undead.position);
|
||||||
|
} else if (undead.sound_handle == -1 || !p.sound_is_active(undead.sound_handle)) {
|
||||||
// Destroy old sound handle before playing new one to prevent overlapping
|
// Restart looping sound if it stopped for some reason
|
||||||
if (undead.sound_handle != -1) {
|
if (undead.sound_handle != -1) {
|
||||||
p.destroy_sound(undead.sound_handle);
|
p.destroy_sound(undead.sound_handle);
|
||||||
undead.sound_handle = -1;
|
|
||||||
}
|
}
|
||||||
|
undead.sound_handle = play_1d_with_volume_step(undead.voice_sound, x, undead.position, true, ZOMBIE_SOUND_VOLUME_STEP);
|
||||||
undead.sound_handle = play_creature_voice(undead.voice_sound, x, undead.position, ZOMBIE_SOUND_VOLUME_STEP);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (try_attack_player_undead(undead)) {
|
if (try_attack_player_undead(undead)) {
|
||||||
|
|||||||
@@ -558,23 +558,30 @@ void perform_search(int current_x)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Trees (Sticks/Vines) - Check for nearby tree anywhere
|
// Trees (Sticks/Vines) - Check for nearby tree, but only on non-stone terrain
|
||||||
|
// Skip tree search if player is on stone terrain (prioritize stone finding)
|
||||||
|
string search_terrain = get_terrain_at_position(current_x);
|
||||||
|
bool skip_tree_search = (search_terrain == "stone" || search_terrain == "gravel" ||
|
||||||
|
search_terrain == "snow" || search_terrain == "hard_stone");
|
||||||
|
|
||||||
Tree@ nearest = null;
|
Tree@ nearest = null;
|
||||||
int nearest_distance = 999;
|
int nearest_distance = 999;
|
||||||
for(uint i=0; i<trees.length(); i++)
|
if (!skip_tree_search) {
|
||||||
{
|
for(uint i=0; i<trees.length(); i++)
|
||||||
int distance = trees[i].position - current_x;
|
|
||||||
if (distance < 0) distance = -distance;
|
|
||||||
if(distance <= 1 && distance < nearest_distance)
|
|
||||||
{
|
{
|
||||||
nearest_distance = distance;
|
int distance = trees[i].position - current_x;
|
||||||
@nearest = @trees[i];
|
if (distance < 0) distance = -distance;
|
||||||
if (nearest_distance == 0) {
|
if(distance <= 1 && distance < nearest_distance)
|
||||||
break;
|
{
|
||||||
|
nearest_distance = distance;
|
||||||
|
@nearest = @trees[i];
|
||||||
|
if (nearest_distance == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(@nearest != null)
|
if(@nearest != null)
|
||||||
{
|
{
|
||||||
if(nearest.is_chopped) {
|
if(nearest.is_chopped) {
|
||||||
@@ -659,7 +666,7 @@ void perform_search(int current_x)
|
|||||||
MountainRange@ mountain = get_mountain_at(current_x);
|
MountainRange@ mountain = get_mountain_at(current_x);
|
||||||
if (mountain !is null) {
|
if (mountain !is null) {
|
||||||
string terrain = mountain.get_terrain_at(current_x);
|
string terrain = mountain.get_terrain_at(current_x);
|
||||||
if (terrain == "stone" || terrain == "hard_stone") {
|
if (terrain == "stone" || terrain == "hard_stone" || terrain == "gravel") {
|
||||||
is_stone_terrain = true;
|
is_stone_terrain = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -671,7 +678,7 @@ void perform_search(int current_x)
|
|||||||
if (terrain.find("mountain:") == 0) {
|
if (terrain.find("mountain:") == 0) {
|
||||||
terrain = terrain.substr(9);
|
terrain = terrain.substr(9);
|
||||||
}
|
}
|
||||||
if (terrain == "stone" || terrain == "hard_stone") {
|
if (terrain == "stone" || terrain == "hard_stone" || terrain == "gravel") {
|
||||||
is_stone_terrain = true;
|
is_stone_terrain = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -177,17 +177,18 @@ string get_equipment_name(int equip_type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool equipment_available(int equip_type) {
|
bool equipment_available(int equip_type) {
|
||||||
if (equip_type == EQUIP_SPEAR) return inv_spears > 0;
|
// Check unruned items first
|
||||||
if (equip_type == EQUIP_AXE) return inv_axes > 0;
|
if (equip_type == EQUIP_SPEAR) return inv_spears > 0 || has_any_runed_version(equip_type);
|
||||||
if (equip_type == EQUIP_SLING) return inv_slings > 0;
|
if (equip_type == EQUIP_AXE) return inv_axes > 0 || has_any_runed_version(equip_type);
|
||||||
if (equip_type == EQUIP_BOW) return inv_bows > 0;
|
if (equip_type == EQUIP_SLING) return inv_slings > 0 || has_any_runed_version(equip_type);
|
||||||
if (equip_type == EQUIP_HAT) return inv_skin_hats > 0;
|
if (equip_type == EQUIP_BOW) return inv_bows > 0 || has_any_runed_version(equip_type);
|
||||||
if (equip_type == EQUIP_GLOVES) return inv_skin_gloves > 0;
|
if (equip_type == EQUIP_HAT) return inv_skin_hats > 0 || has_any_runed_version(equip_type);
|
||||||
if (equip_type == EQUIP_PANTS) return inv_skin_pants > 0;
|
if (equip_type == EQUIP_GLOVES) return inv_skin_gloves > 0 || has_any_runed_version(equip_type);
|
||||||
if (equip_type == EQUIP_TUNIC) return inv_skin_tunics > 0;
|
if (equip_type == EQUIP_PANTS) return inv_skin_pants > 0 || has_any_runed_version(equip_type);
|
||||||
if (equip_type == EQUIP_MOCCASINS) return inv_moccasins > 0;
|
if (equip_type == EQUIP_TUNIC) return inv_skin_tunics > 0 || has_any_runed_version(equip_type);
|
||||||
if (equip_type == EQUIP_POUCH) return inv_skin_pouches > 0;
|
if (equip_type == EQUIP_MOCCASINS) return inv_moccasins > 0 || has_any_runed_version(equip_type);
|
||||||
if (equip_type == EQUIP_BACKPACK) return inv_backpacks > 0;
|
if (equip_type == EQUIP_POUCH) return inv_skin_pouches > 0 || has_any_runed_version(equip_type);
|
||||||
|
if (equip_type == EQUIP_BACKPACK) return inv_backpacks > 0 || has_any_runed_version(equip_type);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,10 @@ void check_altar_menu(int player_x) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void sacrifice_item(int item_type) {
|
void sacrifice_item(int item_type) {
|
||||||
|
if (item_type == -2 || is_runed_item_type(item_type)) {
|
||||||
|
speak_with_history("Runed items cannot be sacrificed.", true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
int available = get_personal_count(item_type);
|
int available = get_personal_count(item_type);
|
||||||
if (available <= 0) {
|
if (available <= 0) {
|
||||||
speak_with_history("Nothing to sacrifice.", true);
|
speak_with_history("Nothing to sacrifice.", true);
|
||||||
@@ -66,6 +70,10 @@ void sacrifice_item(int item_type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void sacrifice_item_max(int item_type) {
|
void sacrifice_item_max(int item_type) {
|
||||||
|
if (item_type == -2 || is_runed_item_type(item_type)) {
|
||||||
|
speak_with_history("Runed items cannot be sacrificed.", true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
int available = get_personal_count(item_type);
|
int available = get_personal_count(item_type);
|
||||||
if (available <= 0) {
|
if (available <= 0) {
|
||||||
speak_with_history("Nothing to sacrifice.", true);
|
speak_with_history("Nothing to sacrifice.", true);
|
||||||
|
|||||||
@@ -32,6 +32,19 @@ void build_personal_inventory_options(string[]@ options, int[]@ item_types) {
|
|||||||
options.insert_last("Moccasins: " + inv_moccasins); item_types.insert_last(ITEM_MOCCASINS);
|
options.insert_last("Moccasins: " + inv_moccasins); item_types.insert_last(ITEM_MOCCASINS);
|
||||||
options.insert_last("Skin Pouches: " + inv_skin_pouches); item_types.insert_last(ITEM_SKIN_POUCHES);
|
options.insert_last("Skin Pouches: " + inv_skin_pouches); item_types.insert_last(ITEM_SKIN_POUCHES);
|
||||||
options.insert_last("Backpacks: " + inv_backpacks); item_types.insert_last(ITEM_BACKPACKS);
|
options.insert_last("Backpacks: " + inv_backpacks); item_types.insert_last(ITEM_BACKPACKS);
|
||||||
|
|
||||||
|
// Add runed items
|
||||||
|
int[] runeable = get_runeable_equipment_types();
|
||||||
|
for (uint i = 0; i < runeable.length(); i++) {
|
||||||
|
int equip_type = runeable[i];
|
||||||
|
// For now, only check for Swiftness rune
|
||||||
|
int count = get_runed_item_count(equip_type, RUNE_SWIFTNESS);
|
||||||
|
if (count > 0) {
|
||||||
|
string name = "Runed " + get_base_equipment_name(equip_type) + " of Quickness";
|
||||||
|
options.insert_last(name + ": " + count);
|
||||||
|
item_types.insert_last(encode_runed_item_type(equip_type, RUNE_SWIFTNESS));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void show_inventory() {
|
void show_inventory() {
|
||||||
@@ -50,6 +63,21 @@ void show_inventory() {
|
|||||||
info += inv_incense + " incense. ";
|
info += inv_incense + " incense. ";
|
||||||
info += "Tools: " + inv_spears + " spears, " + inv_slings + " slings, " + inv_axes + " axes, " + inv_snares + " snares, " + inv_knives + " knives, " + inv_fishing_poles + " fishing poles, " + inv_ropes + " ropes, " + inv_reed_baskets + " reed baskets, " + inv_clay_pots + " clay pots. ";
|
info += "Tools: " + inv_spears + " spears, " + inv_slings + " slings, " + inv_axes + " axes, " + inv_snares + " snares, " + inv_knives + " knives, " + inv_fishing_poles + " fishing poles, " + inv_ropes + " ropes, " + inv_reed_baskets + " reed baskets, " + inv_clay_pots + " clay pots. ";
|
||||||
info += "Clothing: " + inv_skin_hats + " hats, " + inv_skin_gloves + " gloves, " + inv_skin_pants + " pants, " + inv_skin_tunics + " tunics, " + inv_moccasins + " moccasins, " + inv_skin_pouches + " skin pouches.";
|
info += "Clothing: " + inv_skin_hats + " hats, " + inv_skin_gloves + " gloves, " + inv_skin_pants + " pants, " + inv_skin_tunics + " tunics, " + inv_moccasins + " moccasins, " + inv_skin_pouches + " skin pouches.";
|
||||||
|
|
||||||
|
// Add runed items summary
|
||||||
|
string runed_info = "";
|
||||||
|
int[] runeable = get_runeable_equipment_types();
|
||||||
|
for (uint i = 0; i < runeable.length(); i++) {
|
||||||
|
int count = get_runed_item_count(runeable[i], RUNE_SWIFTNESS);
|
||||||
|
if (count > 0) {
|
||||||
|
if (runed_info.length() > 0) runed_info += ", ";
|
||||||
|
runed_info += count + " Runed " + get_base_equipment_name(runeable[i]) + " of Quickness";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (runed_info.length() > 0) {
|
||||||
|
info += " Runed items: " + runed_info + ".";
|
||||||
|
}
|
||||||
|
|
||||||
speak_with_history(info, true);
|
speak_with_history(info, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,44 @@ int prompt_transfer_amount(const string prompt, int max_amount) {
|
|||||||
return amount;
|
return amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Encode runed item info into a negative item type
|
||||||
|
// Format: -1000 - (equip_type * 10) - rune_type
|
||||||
|
// This allows us to extract both equip_type and rune_type from a single int
|
||||||
|
int encode_runed_item_type(int equip_type, int rune_type) {
|
||||||
|
return -1000 - (equip_type * 10) - rune_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode a runed item type back to equip_type and rune_type
|
||||||
|
void decode_runed_item_type(int encoded, int& out equip_type, int& out rune_type) {
|
||||||
|
int decoded = -(encoded + 1000);
|
||||||
|
equip_type = decoded / 10;
|
||||||
|
rune_type = decoded % 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if an item_type represents a runed item
|
||||||
|
bool is_runed_item_type(int item_type) {
|
||||||
|
return item_type <= -1000;
|
||||||
|
}
|
||||||
|
|
||||||
void deposit_item(int item_type) {
|
void deposit_item(int item_type) {
|
||||||
|
// Handle runed items
|
||||||
|
if (is_runed_item_type(item_type)) {
|
||||||
|
int equip_type, rune_type;
|
||||||
|
decode_runed_item_type(item_type, equip_type, rune_type);
|
||||||
|
if (deposit_runed_item(equip_type, rune_type)) {
|
||||||
|
string name = "Runed " + get_base_equipment_name(equip_type) + " of " + get_rune_effect_name(rune_type);
|
||||||
|
cleanup_equipment_after_inventory_change();
|
||||||
|
speak_with_history("Deposited " + name + ".", true);
|
||||||
|
} else {
|
||||||
|
speak_with_history("Nothing to deposit.", true);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Handle legacy -2 marker (shouldn't happen anymore but keep for safety)
|
||||||
|
if (item_type == -2) {
|
||||||
|
speak_with_history("Runed items cannot be deposited into storage.", true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
int available = get_personal_count(item_type);
|
int available = get_personal_count(item_type);
|
||||||
if (available <= 0) {
|
if (available <= 0) {
|
||||||
speak_with_history("Nothing to deposit.", true);
|
speak_with_history("Nothing to deposit.", true);
|
||||||
@@ -80,6 +117,30 @@ void deposit_item(int item_type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void deposit_item_max(int item_type) {
|
void deposit_item_max(int item_type) {
|
||||||
|
// Handle runed items
|
||||||
|
if (is_runed_item_type(item_type)) {
|
||||||
|
int equip_type, rune_type;
|
||||||
|
decode_runed_item_type(item_type, equip_type, rune_type);
|
||||||
|
int personal = get_runed_item_count(equip_type, rune_type);
|
||||||
|
if (personal <= 0) {
|
||||||
|
speak_with_history("Nothing to deposit.", true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int count = 0;
|
||||||
|
while (get_runed_item_count(equip_type, rune_type) > 0) {
|
||||||
|
deposit_runed_item(equip_type, rune_type);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
string name = "Runed " + get_base_equipment_name(equip_type) + " of " + get_rune_effect_name(rune_type);
|
||||||
|
cleanup_equipment_after_inventory_change();
|
||||||
|
speak_with_history("Deposited " + count + " " + name + ".", true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Handle legacy -2 marker
|
||||||
|
if (item_type == -2) {
|
||||||
|
speak_with_history("Runed items cannot be deposited into storage.", true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
int available = get_personal_count(item_type);
|
int available = get_personal_count(item_type);
|
||||||
if (available <= 0) {
|
if (available <= 0) {
|
||||||
speak_with_history("Nothing to deposit.", true);
|
speak_with_history("Nothing to deposit.", true);
|
||||||
@@ -128,6 +189,18 @@ void deposit_item_max(int item_type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void withdraw_item(int item_type) {
|
void withdraw_item(int item_type) {
|
||||||
|
// Handle runed items
|
||||||
|
if (is_runed_item_type(item_type)) {
|
||||||
|
int equip_type, rune_type;
|
||||||
|
decode_runed_item_type(item_type, equip_type, rune_type);
|
||||||
|
if (withdraw_runed_item(equip_type, rune_type)) {
|
||||||
|
string name = "Runed " + get_base_equipment_name(equip_type) + " of " + get_rune_effect_name(rune_type);
|
||||||
|
speak_with_history("Withdrew " + name + ".", true);
|
||||||
|
} else {
|
||||||
|
speak_with_history("Nothing to withdraw.", true);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
int available = get_storage_count(item_type);
|
int available = get_storage_count(item_type);
|
||||||
if (available <= 0) {
|
if (available <= 0) {
|
||||||
speak_with_history("Nothing to withdraw.", true);
|
speak_with_history("Nothing to withdraw.", true);
|
||||||
@@ -175,6 +248,24 @@ void withdraw_item(int item_type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void withdraw_item_max(int item_type) {
|
void withdraw_item_max(int item_type) {
|
||||||
|
// Handle runed items
|
||||||
|
if (is_runed_item_type(item_type)) {
|
||||||
|
int equip_type, rune_type;
|
||||||
|
decode_runed_item_type(item_type, equip_type, rune_type);
|
||||||
|
int stored = get_stored_runed_item_count(equip_type, rune_type);
|
||||||
|
if (stored <= 0) {
|
||||||
|
speak_with_history("Nothing to withdraw.", true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int count = 0;
|
||||||
|
while (get_stored_runed_item_count(equip_type, rune_type) > 0) {
|
||||||
|
withdraw_runed_item(equip_type, rune_type);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
string name = "Runed " + get_base_equipment_name(equip_type) + " of " + get_rune_effect_name(rune_type);
|
||||||
|
speak_with_history("Withdrew " + count + " " + name + ".", true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
int available = get_storage_count(item_type);
|
int available = get_storage_count(item_type);
|
||||||
if (available <= 0) {
|
if (available <= 0) {
|
||||||
speak_with_history("Nothing to withdraw.", true);
|
speak_with_history("Nothing to withdraw.", true);
|
||||||
@@ -255,6 +346,18 @@ void build_storage_inventory_options(string[]@ options, int[]@ item_types) {
|
|||||||
options.insert_last("Moccasins: " + storage_moccasins); item_types.insert_last(ITEM_MOCCASINS);
|
options.insert_last("Moccasins: " + storage_moccasins); item_types.insert_last(ITEM_MOCCASINS);
|
||||||
options.insert_last("Skin Pouches: " + storage_skin_pouches); item_types.insert_last(ITEM_SKIN_POUCHES);
|
options.insert_last("Skin Pouches: " + storage_skin_pouches); item_types.insert_last(ITEM_SKIN_POUCHES);
|
||||||
options.insert_last("Backpacks: " + storage_backpacks); item_types.insert_last(ITEM_BACKPACKS);
|
options.insert_last("Backpacks: " + storage_backpacks); item_types.insert_last(ITEM_BACKPACKS);
|
||||||
|
|
||||||
|
// Add stored runed items
|
||||||
|
int[] runeable = get_runeable_equipment_types();
|
||||||
|
for (uint i = 0; i < runeable.length(); i++) {
|
||||||
|
int equip_type = runeable[i];
|
||||||
|
int count = get_stored_runed_item_count(equip_type, RUNE_SWIFTNESS);
|
||||||
|
if (count > 0) {
|
||||||
|
string name = "Runed " + get_base_equipment_name(equip_type) + " of Quickness";
|
||||||
|
options.insert_last(name + ": " + count);
|
||||||
|
item_types.insert_last(encode_runed_item_type(equip_type, RUNE_SWIFTNESS));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void run_storage_menu() {
|
void run_storage_menu() {
|
||||||
|
|||||||
@@ -93,16 +93,19 @@ void apply_quest_reward(int score) {
|
|||||||
int skins_added = add_to_stack(inv_skins, skins_gain);
|
int skins_added = add_to_stack(inv_skins, skins_gain);
|
||||||
inv_skins += skins_added;
|
inv_skins += skins_added;
|
||||||
|
|
||||||
string message = "Quest reward: favor +" + format_favor(favor_gain) + ".";
|
string message = "Quest Complete!\n\nRewards:\n";
|
||||||
if (stones_gain > 0) message += " Stones +" + stones_added + ".";
|
message += "Favor: +" + format_favor(favor_gain) + "\n";
|
||||||
if (logs_gain > 0) message += " Logs +" + logs_added + ".";
|
if (stones_gain > 0) message += "Stones: +" + stones_added + "\n";
|
||||||
if (skins_gain > 0) message += " Skins +" + skins_added + ".";
|
if (logs_gain > 0) message += "Logs: +" + logs_added + "\n";
|
||||||
speak_with_history(message, true);
|
if (skins_gain > 0) message += "Skins: +" + skins_added + "\n";
|
||||||
|
message += "\nScore: " + score;
|
||||||
|
text_reader(message, "Quest Rewards", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void run_quest(int quest_type) {
|
void run_quest(int quest_type) {
|
||||||
speak_with_history(get_quest_description(quest_type), true);
|
string quest_name = get_quest_name(quest_type);
|
||||||
wait(800);
|
string quest_desc = get_quest_description(quest_type);
|
||||||
|
text_reader(quest_name + "\n\n" + quest_desc, "Quest Instructions", true);
|
||||||
p.pause_all();
|
p.pause_all();
|
||||||
int score = 0;
|
int score = 0;
|
||||||
if (quest_type == QUEST_BAT_INVASION) score = run_bat_invasion();
|
if (quest_type == QUEST_BAT_INVASION) score = run_bat_invasion();
|
||||||
|
|||||||
@@ -22,6 +22,9 @@ const int RUNE_SWIFTNESS_GATHER_BONUS = 5;
|
|||||||
// Value: count of that runed item type
|
// Value: count of that runed item type
|
||||||
dictionary runed_items;
|
dictionary runed_items;
|
||||||
|
|
||||||
|
// Dictionary for stored runed items (base storage)
|
||||||
|
dictionary stored_runed_items;
|
||||||
|
|
||||||
// Track which rune is on equipped items
|
// Track which rune is on equipped items
|
||||||
int equipped_head_rune = RUNE_NONE;
|
int equipped_head_rune = RUNE_NONE;
|
||||||
int equipped_torso_rune = RUNE_NONE;
|
int equipped_torso_rune = RUNE_NONE;
|
||||||
@@ -91,6 +94,51 @@ bool has_any_runed_version(int equip_type) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get count of stored runed items
|
||||||
|
int get_stored_runed_item_count(int equip_type, int rune_type) {
|
||||||
|
string key = make_runed_key(equip_type, rune_type);
|
||||||
|
if (stored_runed_items.exists(key)) {
|
||||||
|
return int(stored_runed_items[key]);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a runed item to storage
|
||||||
|
void add_stored_runed_item(int equip_type, int rune_type) {
|
||||||
|
string key = make_runed_key(equip_type, rune_type);
|
||||||
|
int current = get_stored_runed_item_count(equip_type, rune_type);
|
||||||
|
stored_runed_items.set(key, current + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove a runed item from storage
|
||||||
|
void remove_stored_runed_item(int equip_type, int rune_type) {
|
||||||
|
string key = make_runed_key(equip_type, rune_type);
|
||||||
|
int current = get_stored_runed_item_count(equip_type, rune_type);
|
||||||
|
if (current > 0) {
|
||||||
|
stored_runed_items.set(key, current - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deposit runed item from personal inventory to storage
|
||||||
|
bool deposit_runed_item(int equip_type, int rune_type) {
|
||||||
|
int personal = get_runed_item_count(equip_type, rune_type);
|
||||||
|
if (personal <= 0) return false;
|
||||||
|
|
||||||
|
remove_runed_item(equip_type, rune_type);
|
||||||
|
add_stored_runed_item(equip_type, rune_type);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Withdraw runed item from storage to personal inventory
|
||||||
|
bool withdraw_runed_item(int equip_type, int rune_type) {
|
||||||
|
int stored = get_stored_runed_item_count(equip_type, rune_type);
|
||||||
|
if (stored <= 0) return false;
|
||||||
|
|
||||||
|
remove_stored_runed_item(equip_type, rune_type);
|
||||||
|
add_runed_item(equip_type, rune_type);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Get the rune type on equipped item for a given slot
|
// Get the rune type on equipped item for a given slot
|
||||||
int get_equipped_rune_for_slot(int equip_type) {
|
int get_equipped_rune_for_slot(int equip_type) {
|
||||||
if (equip_type == EQUIP_SPEAR || equip_type == EQUIP_AXE ||
|
if (equip_type == EQUIP_SPEAR || equip_type == EQUIP_AXE ||
|
||||||
@@ -148,6 +196,7 @@ void reset_rune_data() {
|
|||||||
rune_swiftness_unlocked = false;
|
rune_swiftness_unlocked = false;
|
||||||
unicorn_boss_defeated = false;
|
unicorn_boss_defeated = false;
|
||||||
runed_items.delete_all();
|
runed_items.delete_all();
|
||||||
|
stored_runed_items.delete_all();
|
||||||
equipped_head_rune = RUNE_NONE;
|
equipped_head_rune = RUNE_NONE;
|
||||||
equipped_torso_rune = RUNE_NONE;
|
equipped_torso_rune = RUNE_NONE;
|
||||||
equipped_arms_rune = RUNE_NONE;
|
equipped_arms_rune = RUNE_NONE;
|
||||||
|
|||||||
@@ -110,6 +110,7 @@ void stop_active_sounds() {
|
|||||||
p.destroy_sound(sling_sound_handle);
|
p.destroy_sound(sling_sound_handle);
|
||||||
sling_sound_handle = -1;
|
sling_sound_handle = -1;
|
||||||
}
|
}
|
||||||
|
stop_all_weather_sounds();
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear_world_objects() {
|
void clear_world_objects() {
|
||||||
@@ -494,6 +495,36 @@ bool load_game_state_from_raw(const string&in rawData) {
|
|||||||
if (get_raw_number(rawData, "inventory_skin_tunics", value)) inv_skin_tunics = value;
|
if (get_raw_number(rawData, "inventory_skin_tunics", value)) inv_skin_tunics = value;
|
||||||
if (get_raw_number(rawData, "inventory_moccasins", value)) inv_moccasins = value;
|
if (get_raw_number(rawData, "inventory_moccasins", value)) inv_moccasins = value;
|
||||||
if (get_raw_number(rawData, "inventory_skin_pouches", value)) inv_skin_pouches = value;
|
if (get_raw_number(rawData, "inventory_skin_pouches", value)) inv_skin_pouches = value;
|
||||||
|
if (get_raw_number(rawData, "inventory_backpacks", value)) inv_backpacks = value;
|
||||||
|
|
||||||
|
if (get_raw_number(rawData, "storage_stones", value)) storage_stones = value;
|
||||||
|
if (get_raw_number(rawData, "storage_sticks", value)) storage_sticks = value;
|
||||||
|
if (get_raw_number(rawData, "storage_vines", value)) storage_vines = value;
|
||||||
|
if (get_raw_number(rawData, "storage_reeds", value)) storage_reeds = value;
|
||||||
|
if (get_raw_number(rawData, "storage_logs", value)) storage_logs = value;
|
||||||
|
if (get_raw_number(rawData, "storage_clay", value)) storage_clay = value;
|
||||||
|
if (get_raw_number(rawData, "storage_small_game", value)) storage_small_game = value;
|
||||||
|
if (get_raw_number(rawData, "storage_meat", value)) storage_meat = value;
|
||||||
|
if (get_raw_number(rawData, "storage_skins", value)) storage_skins = value;
|
||||||
|
if (get_raw_number(rawData, "storage_feathers", value)) storage_feathers = value;
|
||||||
|
if (get_raw_number(rawData, "storage_down", value)) storage_down = value;
|
||||||
|
if (get_raw_number(rawData, "storage_incense", value)) storage_incense = value;
|
||||||
|
if (get_raw_number(rawData, "storage_spears", value)) storage_spears = value;
|
||||||
|
if (get_raw_number(rawData, "storage_snares", value)) storage_snares = value;
|
||||||
|
if (get_raw_number(rawData, "storage_axes", value)) storage_axes = value;
|
||||||
|
if (get_raw_number(rawData, "storage_knives", value)) storage_knives = value;
|
||||||
|
if (get_raw_number(rawData, "storage_fishing_poles", value)) storage_fishing_poles = value;
|
||||||
|
if (get_raw_number(rawData, "storage_slings", value)) storage_slings = value;
|
||||||
|
if (get_raw_number(rawData, "storage_ropes", value)) storage_ropes = value;
|
||||||
|
if (get_raw_number(rawData, "storage_reed_baskets", value)) storage_reed_baskets = value;
|
||||||
|
if (get_raw_number(rawData, "storage_clay_pots", value)) storage_clay_pots = value;
|
||||||
|
if (get_raw_number(rawData, "storage_skin_hats", value)) storage_skin_hats = value;
|
||||||
|
if (get_raw_number(rawData, "storage_skin_gloves", value)) storage_skin_gloves = value;
|
||||||
|
if (get_raw_number(rawData, "storage_skin_pants", value)) storage_skin_pants = value;
|
||||||
|
if (get_raw_number(rawData, "storage_skin_tunics", value)) storage_skin_tunics = value;
|
||||||
|
if (get_raw_number(rawData, "storage_moccasins", value)) storage_moccasins = value;
|
||||||
|
if (get_raw_number(rawData, "storage_skin_pouches", value)) storage_skin_pouches = value;
|
||||||
|
if (get_raw_number(rawData, "storage_backpacks", value)) storage_backpacks = value;
|
||||||
|
|
||||||
if (get_raw_bool(rawData, "equipment_spear_equipped", bool_value)) spear_equipped = bool_value;
|
if (get_raw_bool(rawData, "equipment_spear_equipped", bool_value)) spear_equipped = bool_value;
|
||||||
if (get_raw_bool(rawData, "equipment_axe_equipped", bool_value)) axe_equipped = bool_value;
|
if (get_raw_bool(rawData, "equipment_axe_equipped", bool_value)) axe_equipped = bool_value;
|
||||||
@@ -505,9 +536,12 @@ bool load_game_state_from_raw(const string&in rawData) {
|
|||||||
if (get_raw_number(rawData, "equipment_feet", value)) equipped_feet = value;
|
if (get_raw_number(rawData, "equipment_feet", value)) equipped_feet = value;
|
||||||
if (get_raw_number(rawData, "equipment_arms", value)) equipped_arms = value;
|
if (get_raw_number(rawData, "equipment_arms", value)) equipped_arms = value;
|
||||||
|
|
||||||
if (equipped_arms != EQUIP_POUCH && equipped_arms != EQUIP_BACKPACK) equipped_arms = EQUIP_NONE;
|
if (!equipment_available(equipped_head)) equipped_head = EQUIP_NONE;
|
||||||
if (equipped_arms == EQUIP_POUCH && inv_skin_pouches <= 0) equipped_arms = EQUIP_NONE;
|
if (!equipment_available(equipped_torso)) equipped_torso = EQUIP_NONE;
|
||||||
if (equipped_arms == EQUIP_BACKPACK && inv_backpacks <= 0) equipped_arms = EQUIP_NONE;
|
if (!equipment_available(equipped_hands)) equipped_hands = EQUIP_NONE;
|
||||||
|
if (!equipment_available(equipped_legs)) equipped_legs = EQUIP_NONE;
|
||||||
|
if (!equipment_available(equipped_feet)) equipped_feet = EQUIP_NONE;
|
||||||
|
if (!equipment_available(equipped_arms)) equipped_arms = EQUIP_NONE;
|
||||||
if (incense_hours_remaining > 0) incense_burning = true;
|
if (incense_hours_remaining > 0) incense_burning = true;
|
||||||
|
|
||||||
if (inv_small_game_types.length() == 0 && inv_small_game > 0) {
|
if (inv_small_game_types.length() == 0 && inv_small_game > 0) {
|
||||||
@@ -642,6 +676,18 @@ bool save_game_state() {
|
|||||||
}
|
}
|
||||||
saveData.set("runed_items", join_string_array(runed_items_data));
|
saveData.set("runed_items", join_string_array(runed_items_data));
|
||||||
|
|
||||||
|
// Save stored runed items dictionary
|
||||||
|
string[] stored_runed_items_data;
|
||||||
|
string[]@ stored_keys = stored_runed_items.get_keys();
|
||||||
|
for (uint i = 0; i < stored_keys.length(); i++) {
|
||||||
|
string key = stored_keys[i];
|
||||||
|
int count = int(stored_runed_items[key]);
|
||||||
|
if (count > 0) {
|
||||||
|
stored_runed_items_data.insert_last(key + "=" + count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
saveData.set("stored_runed_items", join_string_array(stored_runed_items_data));
|
||||||
|
|
||||||
saveData.set("time_current_hour", current_hour);
|
saveData.set("time_current_hour", current_hour);
|
||||||
saveData.set("time_current_day", current_day);
|
saveData.set("time_current_day", current_day);
|
||||||
saveData.set("time_is_daytime", is_daytime);
|
saveData.set("time_is_daytime", is_daytime);
|
||||||
@@ -923,14 +969,9 @@ bool load_game_state() {
|
|||||||
equipped_hands = int(get_number(saveData, "equipment_hands", EQUIP_NONE));
|
equipped_hands = int(get_number(saveData, "equipment_hands", EQUIP_NONE));
|
||||||
equipped_legs = int(get_number(saveData, "equipment_legs", EQUIP_NONE));
|
equipped_legs = int(get_number(saveData, "equipment_legs", EQUIP_NONE));
|
||||||
equipped_feet = int(get_number(saveData, "equipment_feet", EQUIP_NONE));
|
equipped_feet = int(get_number(saveData, "equipment_feet", EQUIP_NONE));
|
||||||
if (equipped_head != EQUIP_HAT) equipped_head = EQUIP_NONE;
|
|
||||||
if (equipped_torso != EQUIP_TUNIC) equipped_torso = EQUIP_NONE;
|
// Note: Equipment validation moved after runed items are loaded (see below)
|
||||||
if (equipped_hands != EQUIP_GLOVES) equipped_hands = EQUIP_NONE;
|
|
||||||
if (equipped_legs != EQUIP_PANTS) equipped_legs = EQUIP_NONE;
|
|
||||||
if (equipped_feet != EQUIP_MOCCASINS) equipped_feet = EQUIP_NONE;
|
|
||||||
if (equipped_arms != EQUIP_POUCH && equipped_arms != EQUIP_BACKPACK) equipped_arms = EQUIP_NONE;
|
|
||||||
if (equipped_arms == EQUIP_POUCH && inv_skin_pouches <= 0) equipped_arms = EQUIP_NONE;
|
|
||||||
if (equipped_arms == EQUIP_BACKPACK && inv_backpacks <= 0) equipped_arms = EQUIP_NONE;
|
|
||||||
reset_quick_slots();
|
reset_quick_slots();
|
||||||
string[] loadedQuickSlots = get_string_list_or_split(saveData, "equipment_quick_slots");
|
string[] loadedQuickSlots = get_string_list_or_split(saveData, "equipment_quick_slots");
|
||||||
uint slot_count = loadedQuickSlots.length();
|
uint slot_count = loadedQuickSlots.length();
|
||||||
@@ -941,7 +982,6 @@ bool load_game_state() {
|
|||||||
quick_slots[i] = slot_value;
|
quick_slots[i] = slot_value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
update_max_health_from_equipment();
|
|
||||||
|
|
||||||
// Load rune system data
|
// Load rune system data
|
||||||
rune_swiftness_unlocked = get_bool(saveData, "rune_swiftness_unlocked", false);
|
rune_swiftness_unlocked = get_bool(saveData, "rune_swiftness_unlocked", false);
|
||||||
@@ -969,6 +1009,32 @@ bool load_game_state() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load stored runed items dictionary
|
||||||
|
stored_runed_items.delete_all();
|
||||||
|
string[] loaded_stored_runed_items = get_string_list_or_split(saveData, "stored_runed_items");
|
||||||
|
for (uint i = 0; i < loaded_stored_runed_items.length(); i++) {
|
||||||
|
string entry = loaded_stored_runed_items[i];
|
||||||
|
int eq_pos = entry.find("=");
|
||||||
|
if (eq_pos > 0) {
|
||||||
|
string key = entry.substr(0, eq_pos);
|
||||||
|
int count = parse_int(entry.substr(eq_pos + 1));
|
||||||
|
if (count > 0) {
|
||||||
|
stored_runed_items.set(key, count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate equipped items now that runed items are loaded
|
||||||
|
if (!equipment_available(equipped_head)) equipped_head = EQUIP_NONE;
|
||||||
|
if (!equipment_available(equipped_torso)) equipped_torso = EQUIP_NONE;
|
||||||
|
if (!equipment_available(equipped_hands)) equipped_hands = EQUIP_NONE;
|
||||||
|
if (!equipment_available(equipped_legs)) equipped_legs = EQUIP_NONE;
|
||||||
|
if (!equipment_available(equipped_feet)) equipped_feet = EQUIP_NONE;
|
||||||
|
if (!equipment_available(equipped_arms)) equipped_arms = EQUIP_NONE;
|
||||||
|
|
||||||
|
// Now that both equipment and runes are loaded, update stats
|
||||||
|
update_max_health_from_equipment();
|
||||||
|
|
||||||
current_hour = int(get_number(saveData, "time_current_hour", 8));
|
current_hour = int(get_number(saveData, "time_current_hour", 8));
|
||||||
current_day = int(get_number(saveData, "time_current_day", 1));
|
current_day = int(get_number(saveData, "time_current_day", 1));
|
||||||
sun_setting_warned = get_bool(saveData, "time_sun_setting_warned", false);
|
sun_setting_warned = get_bool(saveData, "time_sun_setting_warned", false);
|
||||||
@@ -1122,15 +1188,15 @@ bool load_game_state() {
|
|||||||
b.wander_direction_change_interval = random(BANDIT_WANDER_DIRECTION_CHANGE_MIN, BANDIT_WANDER_DIRECTION_CHANGE_MAX);
|
b.wander_direction_change_interval = random(BANDIT_WANDER_DIRECTION_CHANGE_MIN, BANDIT_WANDER_DIRECTION_CHANGE_MAX);
|
||||||
b.wander_direction_timer.restart();
|
b.wander_direction_timer.restart();
|
||||||
b.move_timer.restart();
|
b.move_timer.restart();
|
||||||
b.alert_timer.restart();
|
|
||||||
b.attack_timer.restart();
|
b.attack_timer.restart();
|
||||||
|
|
||||||
// Restore alert sound based on weapon type
|
// Restore alert sound based on weapon type
|
||||||
int sound_index = random(0, bandit_sounds.length() - 1);
|
int sound_index = random(0, bandit_sounds.length() - 1);
|
||||||
b.alert_sound = bandit_sounds[sound_index];
|
b.alert_sound = bandit_sounds[sound_index];
|
||||||
b.next_alert_delay = random(BANDIT_ALERT_MIN_DELAY, BANDIT_ALERT_MAX_DELAY);
|
|
||||||
|
|
||||||
bandits.insert_last(b);
|
bandits.insert_last(b);
|
||||||
|
// Start looping sound for loaded bandit
|
||||||
|
b.sound_handle = play_1d_with_volume_step(b.alert_sound, x, b.position, true, BANDIT_SOUND_VOLUME_STEP);
|
||||||
}
|
}
|
||||||
|
|
||||||
string[] mountainData = get_string_list_or_split(saveData, "mountains_data");
|
string[] mountainData = get_string_list_or_split(saveData, "mountains_data");
|
||||||
|
|||||||
@@ -391,9 +391,9 @@ void update_time() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (current_hour == 6) {
|
if (current_hour == 6) {
|
||||||
save_game_state();
|
|
||||||
process_daily_weapon_breakage();
|
process_daily_weapon_breakage();
|
||||||
attempt_daily_quest();
|
attempt_daily_quest();
|
||||||
|
save_game_state();
|
||||||
}
|
}
|
||||||
attempt_daily_invasion();
|
attempt_daily_invasion();
|
||||||
keep_base_fires_fed();
|
keep_base_fires_fed();
|
||||||
|
|||||||
@@ -39,6 +39,13 @@ class ThunderStrike {
|
|||||||
movement_timer.restart();
|
movement_timer.restart();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~ThunderStrike() {
|
||||||
|
if (sound_handle != -1) {
|
||||||
|
p.destroy_sound(sound_handle);
|
||||||
|
sound_handle = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void update() {
|
void update() {
|
||||||
if (direction == 0) return; // Stationary thunder
|
if (direction == 0) return; // Stationary thunder
|
||||||
|
|
||||||
@@ -77,6 +84,7 @@ string[] thunder_sounds = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void init_weather() {
|
void init_weather() {
|
||||||
|
stop_all_weather_sounds();
|
||||||
weather_state = WEATHER_CLEAR;
|
weather_state = WEATHER_CLEAR;
|
||||||
wind_intensity = INTENSITY_NONE;
|
wind_intensity = INTENSITY_NONE;
|
||||||
rain_intensity = INTENSITY_NONE;
|
rain_intensity = INTENSITY_NONE;
|
||||||
|
|||||||
Reference in New Issue
Block a user