A few minor bug fixes with area expansion.
This commit is contained in:
@@ -6,4 +6,3 @@ lib_windows/
|
|||||||
stub/
|
stub/
|
||||||
include/
|
include/
|
||||||
save.dat
|
save.dat
|
||||||
save.dat_robust
|
|
||||||
|
|||||||
Binary file not shown.
@@ -5,6 +5,11 @@ string get_footstep_sound(int current_x, int base_end, int grass_end)
|
|||||||
return "sounds/terrain/shallow_water.ogg";
|
return "sounds/terrain/shallow_water.ogg";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Firepit uses hard stone sound
|
||||||
|
if (get_firepit_at(current_x) != null) {
|
||||||
|
return "sounds/terrain/hard_stone.ogg";
|
||||||
|
}
|
||||||
|
|
||||||
if (current_x <= base_end)
|
if (current_x <= base_end)
|
||||||
{
|
{
|
||||||
// Base area
|
// Base area
|
||||||
|
|||||||
+69
-70
@@ -251,6 +251,75 @@ void perform_search(int current_x)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Trees (Sticks/Vines) - Check for nearby tree anywhere
|
||||||
|
Tree@ nearest = null;
|
||||||
|
int nearest_distance = 999;
|
||||||
|
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;
|
||||||
|
@nearest = @trees[i];
|
||||||
|
if (nearest_distance == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(@nearest != null)
|
||||||
|
{
|
||||||
|
if(nearest.is_chopped) {
|
||||||
|
screen_reader_speak("This tree has been cut down.", true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nearest.depleted) {
|
||||||
|
screen_reader_speak("This tree is empty.", true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(nearest.sticks > 0 || nearest.vines > 0)
|
||||||
|
{
|
||||||
|
bool find_stick = (nearest.vines <= 0) || (nearest.sticks > 0 && random(0, 1) == 0);
|
||||||
|
|
||||||
|
if(find_stick)
|
||||||
|
{
|
||||||
|
if (inv_sticks >= MAX_ITEM_STACK) {
|
||||||
|
screen_reader_speak("You can't carry any more sticks.", true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
nearest.sticks--;
|
||||||
|
inv_sticks++;
|
||||||
|
p.play_stationary("sounds/items/stick.ogg", false);
|
||||||
|
screen_reader_speak("Found a stick.", true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (inv_vines >= MAX_ITEM_STACK) {
|
||||||
|
screen_reader_speak("You can't carry any more vines.", true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
nearest.vines--;
|
||||||
|
inv_vines++;
|
||||||
|
p.play_stationary("sounds/items/vine.ogg", false);
|
||||||
|
screen_reader_speak("Found a vine.", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(nearest.sticks == 0 && nearest.vines == 0) {
|
||||||
|
nearest.depleted = true;
|
||||||
|
nearest.regen_timer.restart();
|
||||||
|
nearest.minutes_since_depletion = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
screen_reader_speak("This area has nothing left.", true);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Gravel Area - Stones (20-34)
|
// Gravel Area - Stones (20-34)
|
||||||
if (current_x >= 20 && current_x <= 34)
|
if (current_x >= 20 && current_x <= 34)
|
||||||
{
|
{
|
||||||
@@ -266,76 +335,6 @@ void perform_search(int current_x)
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Grass Area - Trees (Sticks/Vines) (5-19)
|
|
||||||
if (current_x >= 5 && current_x <= 19)
|
|
||||||
{
|
|
||||||
Tree@ nearest = null;
|
|
||||||
for(uint i=0; i<trees.length(); i++)
|
|
||||||
{
|
|
||||||
if(trees[i].position >= current_x - 1 && trees[i].position <= current_x + 1)
|
|
||||||
{
|
|
||||||
@nearest = @trees[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(@nearest != null)
|
|
||||||
{
|
|
||||||
if(nearest.is_chopped) {
|
|
||||||
screen_reader_speak("This tree has been cut down.", true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nearest.depleted) {
|
|
||||||
screen_reader_speak("This tree is empty.", true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(nearest.sticks > 0 || nearest.vines > 0)
|
|
||||||
{
|
|
||||||
bool find_stick = (nearest.vines <= 0) || (nearest.sticks > 0 && random(0, 1) == 0);
|
|
||||||
|
|
||||||
if(find_stick)
|
|
||||||
{
|
|
||||||
if (inv_sticks >= MAX_ITEM_STACK) {
|
|
||||||
screen_reader_speak("You can't carry any more sticks.", true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
nearest.sticks--;
|
|
||||||
inv_sticks++;
|
|
||||||
p.play_stationary("sounds/items/stick.ogg", false);
|
|
||||||
screen_reader_speak("Found a stick.", true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (inv_vines >= MAX_ITEM_STACK) {
|
|
||||||
screen_reader_speak("You can't carry any more vines.", true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
nearest.vines--;
|
|
||||||
inv_vines++;
|
|
||||||
p.play_stationary("sounds/items/vine.ogg", false);
|
|
||||||
screen_reader_speak("Found a vine.", true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(nearest.sticks == 0 && nearest.vines == 0) {
|
|
||||||
nearest.depleted = true;
|
|
||||||
nearest.regen_timer.restart();
|
|
||||||
nearest.minutes_since_depletion = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
screen_reader_speak("This area has nothing left.", true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
screen_reader_speak("Found nothing.", true);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
screen_reader_speak("Found nothing.", true);
|
screen_reader_speak("Found nothing.", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-20
@@ -1,7 +1,6 @@
|
|||||||
// Save system
|
// Save system
|
||||||
|
|
||||||
const string SAVE_FILE_PATH = "save.dat";
|
const string SAVE_FILE_PATH = "save.dat";
|
||||||
const string SAVE_BACKUP_SUFFIX = "_robust";
|
|
||||||
const string SAVE_ENCRYPTION_KEY = "draugnorak_save_v1";
|
const string SAVE_ENCRYPTION_KEY = "draugnorak_save_v1";
|
||||||
const int SAVE_VERSION = 1;
|
const int SAVE_VERSION = 1;
|
||||||
|
|
||||||
@@ -17,38 +16,21 @@ string decrypt_save_data(const string&in encryptedData) {
|
|||||||
return string_aes_decrypt(encryptedData, SAVE_ENCRYPTION_KEY);
|
return string_aes_decrypt(encryptedData, SAVE_ENCRYPTION_KEY);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool save_robust_data(const string&in filename, const string&in data) {
|
bool save_data(const string&in filename, const string&in data) {
|
||||||
if (data.length() == 0) {
|
if (data.length() == 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
string backupPath = filename + SAVE_BACKUP_SUFFIX;
|
|
||||||
if (file_exists(filename)) {
|
|
||||||
if (!file_copy(filename, backupPath, true)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
file tmp;
|
file tmp;
|
||||||
if (!tmp.open(filename, "wb")) {
|
if (!tmp.open(filename, "wb")) {
|
||||||
if (file_exists(backupPath)) {
|
|
||||||
file_copy(backupPath, filename, true);
|
|
||||||
file_delete(backupPath);
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tmp.write(data) < data.length()) {
|
if (tmp.write(data) < data.length()) {
|
||||||
tmp.close();
|
tmp.close();
|
||||||
if (file_exists(backupPath)) {
|
|
||||||
file_copy(backupPath, filename, true);
|
|
||||||
file_delete(backupPath);
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp.close();
|
tmp.close();
|
||||||
file_delete(backupPath);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -310,7 +292,7 @@ bool save_game_state() {
|
|||||||
|
|
||||||
string rawData = saveData.serialize();
|
string rawData = saveData.serialize();
|
||||||
string encryptedData = encrypt_save_data(rawData);
|
string encryptedData = encrypt_save_data(rawData);
|
||||||
return save_robust_data(SAVE_FILE_PATH, encryptedData);
|
return save_data(SAVE_FILE_PATH, encryptedData);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool load_game_state() {
|
bool load_game_state() {
|
||||||
|
|||||||
+30
-70
@@ -44,82 +44,42 @@ void expand_area() {
|
|||||||
expanded_area_end = MAP_SIZE + EXPANSION_SIZE - 1;
|
expanded_area_end = MAP_SIZE + EXPANSION_SIZE - 1;
|
||||||
MAP_SIZE += EXPANSION_SIZE;
|
MAP_SIZE += EXPANSION_SIZE;
|
||||||
|
|
||||||
// Generate random terrain for the 30 new tiles
|
// Generate a single terrain type for the entire new area
|
||||||
|
string terrain_type;
|
||||||
|
int terrain_roll = random(0, 2);
|
||||||
|
if (terrain_roll == 0) {
|
||||||
|
terrain_type = "stone";
|
||||||
|
} else if (terrain_roll == 1) {
|
||||||
|
terrain_type = "grass";
|
||||||
|
} else {
|
||||||
|
terrain_type = "snow";
|
||||||
|
}
|
||||||
|
|
||||||
expanded_terrain_types.resize(EXPANSION_SIZE);
|
expanded_terrain_types.resize(EXPANSION_SIZE);
|
||||||
for (int i = 0; i < EXPANSION_SIZE; i++) {
|
for (int i = 0; i < EXPANSION_SIZE; i++) {
|
||||||
int terrain_roll = random(0, 2);
|
expanded_terrain_types[i] = terrain_type;
|
||||||
if (terrain_roll == 0) {
|
|
||||||
expanded_terrain_types[i] = "stone";
|
|
||||||
} else if (terrain_roll == 1) {
|
|
||||||
expanded_terrain_types[i] = "grass";
|
|
||||||
} else {
|
|
||||||
expanded_terrain_types[i] = "snow";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate streams (30% chance for a stream)
|
// Place exactly one feature: either a stream or a tree
|
||||||
int stream_roll = random(1, 100);
|
bool place_stream = (terrain_type != "grass") || (random(0, 1) == 0);
|
||||||
if (stream_roll <= 30) {
|
|
||||||
// Determine stream width (1-5 tiles)
|
if (place_stream) {
|
||||||
int stream_width = random(1, 5);
|
int stream_width = random(1, 5);
|
||||||
|
int stream_start = random(0, EXPANSION_SIZE - stream_width);
|
||||||
|
int actual_start = expanded_area_start + stream_start;
|
||||||
|
add_world_stream(actual_start, stream_width);
|
||||||
|
|
||||||
// Find a valid starting position for the stream
|
string width_desc = "very small";
|
||||||
// Stream can only be in grass, stone, or snow areas
|
if (stream_width == 2) width_desc = "small";
|
||||||
int attempts = 0;
|
else if (stream_width == 3) width_desc = "medium";
|
||||||
int stream_start = -1;
|
else if (stream_width == 4) width_desc = "wide";
|
||||||
while (attempts < 50) {
|
else if (stream_width == 5) width_desc = "very wide";
|
||||||
int candidate_start = random(0, EXPANSION_SIZE - stream_width);
|
|
||||||
bool valid_position = true;
|
|
||||||
|
|
||||||
// Check if all tiles in this range are valid for a stream
|
notify("A " + width_desc + " stream flows through the new area at x " + actual_start + ".");
|
||||||
for (int i = 0; i < stream_width; i++) {
|
} else {
|
||||||
string terrain = expanded_terrain_types[candidate_start + i];
|
int tree_pos = random(expanded_area_start, expanded_area_end);
|
||||||
// Streams can be in any terrain type
|
Tree@ t = Tree(tree_pos);
|
||||||
if (terrain != "grass" && terrain != "stone" && terrain != "snow") {
|
trees.insert_last(t);
|
||||||
valid_position = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (valid_position) {
|
|
||||||
stream_start = candidate_start;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
attempts++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the stream if we found a valid position
|
|
||||||
if (stream_start != -1) {
|
|
||||||
int actual_start = expanded_area_start + stream_start;
|
|
||||||
add_world_stream(actual_start, stream_width);
|
|
||||||
|
|
||||||
string width_desc = "very small";
|
|
||||||
if (stream_width == 2) width_desc = "small";
|
|
||||||
else if (stream_width == 3) width_desc = "medium";
|
|
||||||
else if (stream_width == 4) width_desc = "wide";
|
|
||||||
else if (stream_width == 5) width_desc = "very wide";
|
|
||||||
|
|
||||||
notify("A " + width_desc + " stream flows through the new area at x " + actual_start + ".");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate trees in grass areas (50% chance for each grass tile)
|
|
||||||
for (int i = 0; i < EXPANSION_SIZE; i++) {
|
|
||||||
if (expanded_terrain_types[i] == "grass") {
|
|
||||||
int tile_pos = expanded_area_start + i;
|
|
||||||
|
|
||||||
// Skip if this position has a stream
|
|
||||||
if (is_position_in_water(tile_pos)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 50% chance to spawn a tree
|
|
||||||
int tree_roll = random(1, 100);
|
|
||||||
if (tree_roll <= 50) {
|
|
||||||
Tree@ t = Tree(tile_pos);
|
|
||||||
trees.insert_last(t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
area_expanded_today = true;
|
area_expanded_today = true;
|
||||||
@@ -235,7 +195,7 @@ string get_time_string() {
|
|||||||
period = "pm";
|
period = "pm";
|
||||||
}
|
}
|
||||||
|
|
||||||
return display_hour + " oclock " + period;
|
return display_hour + " oclock " + period + " day " + current_day;
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_ambience_transition() {
|
void check_ambience_transition() {
|
||||||
|
|||||||
@@ -609,9 +609,7 @@ bool damage_zombie_at(int pos, int damage) {
|
|||||||
if (zombies[i].health <= 0) {
|
if (zombies[i].health <= 0) {
|
||||||
play_1d_with_volume_step("sounds/enemies/enemy_falls.ogg", x, pos, false, ZOMBIE_SOUND_VOLUME_STEP);
|
play_1d_with_volume_step("sounds/enemies/enemy_falls.ogg", x, pos, false, ZOMBIE_SOUND_VOLUME_STEP);
|
||||||
zombies.remove_at(i);
|
zombies.remove_at(i);
|
||||||
screen_reader_speak("Zombie killed.", true);
|
|
||||||
} else {
|
} else {
|
||||||
screen_reader_speak("Hit zombie.", true);
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -814,9 +812,7 @@ bool damage_bandit_at(int pos, int damage) {
|
|||||||
if (bandits[i].health <= 0) {
|
if (bandits[i].health <= 0) {
|
||||||
play_1d_with_volume_step("sounds/enemies/enemy_falls.ogg", x, pos, false, BANDIT_SOUND_VOLUME_STEP);
|
play_1d_with_volume_step("sounds/enemies/enemy_falls.ogg", x, pos, false, BANDIT_SOUND_VOLUME_STEP);
|
||||||
bandits.remove_at(i);
|
bandits.remove_at(i);
|
||||||
screen_reader_speak("Bandit killed.", true);
|
|
||||||
} else {
|
} else {
|
||||||
screen_reader_speak("Hit bandit.", true);
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -842,4 +838,3 @@ WorldStream@ get_stream_at(int pos) {
|
|||||||
bool is_position_in_water(int pos) {
|
bool is_position_in_water(int pos) {
|
||||||
return get_stream_at(pos) != null;
|
return get_stream_at(pos) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user