Adjusted weather. Hopefully fixed trees for real this time, so far so good.

This commit is contained in:
Storm Dragon
2026-01-20 16:54:03 -05:00
parent 1be438a870
commit 5c25ba9a19
5 changed files with 225 additions and 57 deletions
+192 -14
View File
@@ -28,7 +28,6 @@ void apply_falling_damage(int fall_height) {
// Feedback
screen_reader_speak("Fell " + fall_height + " feet! Took " + damage + " damage. " + player_health + " health remaining.", true);
}
// Tree Object
class Tree {
int position;
@@ -61,12 +60,24 @@ class Tree {
minutes_since_depletion = 0;
}
void respawn(int grass_start, int grass_end) {
void respawn() {
if (sound_handle != -1) {
p.destroy_sound(sound_handle);
sound_handle = -1;
}
position = random(grass_start, grass_end);
int areaStart = 0;
int areaEnd = 0;
if (!get_tree_area_bounds_for_position(position, areaStart, areaEnd)) {
areaStart = BASE_END + 1;
areaEnd = GRASS_END;
}
Tree@ currentTree = @this;
if (!place_tree_in_area(currentTree, areaStart, areaEnd)) {
return;
}
refill();
}
@@ -106,7 +117,7 @@ class Tree {
if (is_chopped) {
if (minutes_since_depletion >= 5) {
respawn(BASE_END + 1, GRASS_END);
respawn();
}
return;
}
@@ -170,33 +181,200 @@ class Tree {
}
Tree@[] trees;
bool tree_too_close(int pos) {
// Check distance from base (must be at least 5 tiles away)
if (pos <= BASE_END + 5) {
bool get_tree_area_bounds_for_position(int pos, int &out areaStart, int &out areaEnd) {
if (pos >= BASE_END + 1 && pos <= GRASS_END) {
areaStart = BASE_END + 1;
areaEnd = GRASS_END;
return true;
}
// Check distance from other trees (must be at least 10 tiles apart)
if (expanded_area_start == -1 || pos < expanded_area_start || pos > expanded_area_end) {
return false;
}
int index = pos - expanded_area_start;
if (index < 0 || index >= int(expanded_terrain_types.length())) return false;
if (expanded_terrain_types[index] != "grass") return false;
int left = index;
while (left > 0 && expanded_terrain_types[left - 1] == "grass") {
left--;
}
int right = index;
int maxIndex = int(expanded_terrain_types.length()) - 1;
while (right < maxIndex && expanded_terrain_types[right + 1] == "grass") {
right++;
}
areaStart = expanded_area_start + left;
areaEnd = expanded_area_start + right;
return true;
}
int count_trees_in_area(int areaStart, int areaEnd, Tree@ ignoreTree) {
int count = 0;
for (uint i = 0; i < trees.length(); i++) {
if (@trees[i] is ignoreTree) continue;
if (trees[i].position >= areaStart && trees[i].position <= areaEnd) {
count++;
}
}
return count;
}
bool tree_too_close_in_area(int pos, int areaStart, int areaEnd, Tree@ ignoreTree) {
// Keep trees away from the base edge
if (pos < BASE_END + 5) {
return true;
}
for (uint i = 0; i < trees.length(); i++) {
if (@trees[i] is ignoreTree) continue;
if (trees[i].position < areaStart || trees[i].position > areaEnd) continue;
int distance = trees[i].position - pos;
if (distance < 0) distance = -distance;
if (distance < 10) {
if (distance < TREE_MIN_DISTANCE) {
return true;
}
}
return false;
}
void spawn_trees(int grass_start, int grass_end) {
int attempts = 10;
bool place_tree_in_area(Tree@ tree, int areaStart, int areaEnd) {
if (count_trees_in_area(areaStart, areaEnd, tree) >= TREE_MAX_PER_AREA) {
return false;
}
int attempts = 20;
for (int i = 0; i < attempts; i++) {
int pos = random(grass_start, grass_end);
if (tree_too_close(pos)) {
int pos = random(areaStart, areaEnd);
if (tree_too_close_in_area(pos, areaStart, areaEnd, tree)) {
continue;
}
tree.position = pos;
return true;
}
return false;
}
bool spawn_tree_in_area(int areaStart, int areaEnd) {
if (count_trees_in_area(areaStart, areaEnd, null) >= TREE_MAX_PER_AREA) {
return false;
}
int attempts = 20;
for (int i = 0; i < attempts; i++) {
int pos = random(areaStart, areaEnd);
if (tree_too_close_in_area(pos, areaStart, areaEnd, null)) {
continue;
}
Tree@ t = Tree(pos);
trees.insert_last(t);
return;
return true;
}
return false;
}
void spawn_trees(int grass_start, int grass_end) {
spawn_tree_in_area(grass_start, grass_end);
}
void get_grass_areas(int[]@ areaStarts, int[]@ areaEnds) {
areaStarts.resize(0);
areaEnds.resize(0);
areaStarts.insert_last(BASE_END + 1);
areaEnds.insert_last(GRASS_END);
if (expanded_area_start == -1) return;
int total = int(expanded_terrain_types.length());
int index = 0;
while (index < total) {
if (expanded_terrain_types[index] == "grass") {
int segmentStart = index;
while (index + 1 < total && expanded_terrain_types[index + 1] == "grass") {
index++;
}
int segmentEnd = index;
areaStarts.insert_last(expanded_area_start + segmentStart);
areaEnds.insert_last(expanded_area_start + segmentEnd);
}
index++;
}
}
bool relocate_tree_to_any_area(Tree@ tree, int[]@ areaStarts, int[]@ areaEnds) {
for (uint i = 0; i < areaStarts.length(); i++) {
if (count_trees_in_area(areaStarts[i], areaEnds[i], tree) >= TREE_MAX_PER_AREA) continue;
if (place_tree_in_area(tree, areaStarts[i], areaEnds[i])) {
return true;
}
}
return false;
}
void normalize_tree_positions() {
int[] areaStarts;
int[] areaEnds;
get_grass_areas(areaStarts, areaEnds);
if (areaStarts.length() == 0) return;
for (uint i = 0; i < trees.length(); i++) {
int areaStart = 0;
int areaEnd = 0;
if (!get_tree_area_bounds_for_position(trees[i].position, areaStart, areaEnd)) {
if (!relocate_tree_to_any_area(trees[i], areaStarts, areaEnds)) {
if (trees[i].sound_handle != -1) {
p.destroy_sound(trees[i].sound_handle);
}
trees.remove_at(i);
i--;
}
}
}
for (uint areaIndex = 0; areaIndex < areaStarts.length(); areaIndex++) {
int areaStart = areaStarts[areaIndex];
int areaEnd = areaEnds[areaIndex];
int[] areaTreeIndices;
for (uint i = 0; i < trees.length(); i++) {
if (trees[i].position >= areaStart && trees[i].position <= areaEnd) {
areaTreeIndices.insert_last(i);
}
}
while (areaTreeIndices.length() > TREE_MAX_PER_AREA) {
uint treeIndex = areaTreeIndices[areaTreeIndices.length() - 1];
Tree@ tree = trees[treeIndex];
if (!relocate_tree_to_any_area(tree, areaStarts, areaEnds)) {
if (tree.sound_handle != -1) {
p.destroy_sound(tree.sound_handle);
}
trees.remove_at(treeIndex);
}
areaTreeIndices.resize(0);
for (uint i = 0; i < trees.length(); i++) {
if (trees[i].position >= areaStart && trees[i].position <= areaEnd) {
areaTreeIndices.insert_last(i);
}
}
}
if (areaTreeIndices.length() == 2) {
Tree@ firstTree = trees[areaTreeIndices[0]];
Tree@ secondTree = trees[areaTreeIndices[1]];
int distance = firstTree.position - secondTree.position;
if (distance < 0) distance = -distance;
if (distance < TREE_MIN_DISTANCE) {
if (!place_tree_in_area(secondTree, areaStart, areaEnd)) {
place_tree_in_area(firstTree, areaStart, areaEnd);
}
}
}
}
}