Much more refactor done.
This commit is contained in:
@@ -13,6 +13,11 @@ sound_pool p(100);
|
|||||||
#include "src/enemies/bandit.nvgt"
|
#include "src/enemies/bandit.nvgt"
|
||||||
#include "src/enemies/ground_game.nvgt"
|
#include "src/enemies/ground_game.nvgt"
|
||||||
#include "src/enemies/flying_creatures.nvgt"
|
#include "src/enemies/flying_creatures.nvgt"
|
||||||
|
#include "src/world/world_drops.nvgt"
|
||||||
|
#include "src/world/world_snares.nvgt"
|
||||||
|
#include "src/world/world_fires.nvgt"
|
||||||
|
#include "src/world/world_buildings.nvgt"
|
||||||
|
#include "src/world/world_streams.nvgt"
|
||||||
#include "src/world_state.nvgt"
|
#include "src/world_state.nvgt"
|
||||||
#include "src/ui.nvgt"
|
#include "src/ui.nvgt"
|
||||||
#include "src/inventory.nvgt"
|
#include "src/inventory.nvgt"
|
||||||
|
|||||||
@@ -0,0 +1,163 @@
|
|||||||
|
// World buildings - base structures that provide various benefits
|
||||||
|
// Includes Firepit, HerbGarden, Storage, Pasture, Stable, and Altar
|
||||||
|
|
||||||
|
class WorldFirepit {
|
||||||
|
int position;
|
||||||
|
|
||||||
|
WorldFirepit(int pos) {
|
||||||
|
position = pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WorldFirepit@[] world_firepits;
|
||||||
|
|
||||||
|
class WorldHerbGarden {
|
||||||
|
int position;
|
||||||
|
|
||||||
|
WorldHerbGarden(int pos) {
|
||||||
|
position = pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WorldHerbGarden@[] world_herb_gardens;
|
||||||
|
|
||||||
|
class WorldStorage {
|
||||||
|
int position;
|
||||||
|
|
||||||
|
WorldStorage(int pos) {
|
||||||
|
position = pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WorldStorage@[] world_storages;
|
||||||
|
|
||||||
|
class WorldPasture {
|
||||||
|
int position;
|
||||||
|
|
||||||
|
WorldPasture(int pos) {
|
||||||
|
position = pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WorldPasture@[] world_pastures;
|
||||||
|
|
||||||
|
class WorldStable {
|
||||||
|
int position;
|
||||||
|
|
||||||
|
WorldStable(int pos) {
|
||||||
|
position = pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WorldStable@[] world_stables;
|
||||||
|
|
||||||
|
class WorldAltar {
|
||||||
|
int position;
|
||||||
|
|
||||||
|
WorldAltar(int pos) {
|
||||||
|
position = pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WorldAltar@[] world_altars;
|
||||||
|
|
||||||
|
// Add functions
|
||||||
|
void add_world_firepit(int pos) {
|
||||||
|
WorldFirepit@ fp = WorldFirepit(pos);
|
||||||
|
world_firepits.insert_last(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_world_herb_garden(int pos) {
|
||||||
|
WorldHerbGarden@ hg = WorldHerbGarden(pos);
|
||||||
|
world_herb_gardens.insert_last(hg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_world_storage(int pos) {
|
||||||
|
WorldStorage@ s = WorldStorage(pos);
|
||||||
|
world_storages.insert_last(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_world_pasture(int pos) {
|
||||||
|
WorldPasture@ p = WorldPasture(pos);
|
||||||
|
world_pastures.insert_last(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_world_stable(int pos) {
|
||||||
|
WorldStable@ s = WorldStable(pos);
|
||||||
|
world_stables.insert_last(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_world_altar(int pos) {
|
||||||
|
WorldAltar@ a = WorldAltar(pos);
|
||||||
|
world_altars.insert_last(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Getter functions
|
||||||
|
WorldFirepit@ get_firepit_at(int pos) {
|
||||||
|
for (uint i = 0; i < world_firepits.length(); i++) {
|
||||||
|
if (world_firepits[i].position == pos) {
|
||||||
|
return @world_firepits[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
WorldFirepit@ get_firepit_near(int pos, int range) {
|
||||||
|
// Check for firepit within specified range
|
||||||
|
for (int check_x = pos - range; check_x <= pos + range; check_x++) {
|
||||||
|
WorldFirepit@ firepit = get_firepit_at(check_x);
|
||||||
|
if (firepit != null) {
|
||||||
|
return @firepit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
WorldHerbGarden@ get_herb_garden_at(int pos) {
|
||||||
|
for (uint i = 0; i < world_herb_gardens.length(); i++) {
|
||||||
|
if (world_herb_gardens[i].position == pos) {
|
||||||
|
return @world_herb_gardens[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
WorldHerbGarden@ get_herb_garden_at_base() {
|
||||||
|
// Check if herb garden exists anywhere in base area (0-4)
|
||||||
|
for (uint i = 0; i < world_herb_gardens.length(); i++) {
|
||||||
|
if (world_herb_gardens[i].position <= BASE_END) {
|
||||||
|
return @world_herb_gardens[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
WorldStorage@ get_storage_at(int pos) {
|
||||||
|
for (uint i = 0; i < world_storages.length(); i++) {
|
||||||
|
if (world_storages[i].position == pos) {
|
||||||
|
return @world_storages[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
WorldPasture@ get_pasture_at(int pos) {
|
||||||
|
for (uint i = 0; i < world_pastures.length(); i++) {
|
||||||
|
if (world_pastures[i].position == pos) {
|
||||||
|
return @world_pastures[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
WorldStable@ get_stable_at(int pos) {
|
||||||
|
for (uint i = 0; i < world_stables.length(); i++) {
|
||||||
|
if (world_stables[i].position == pos) {
|
||||||
|
return @world_stables[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
WorldAltar@ get_altar_at(int pos) {
|
||||||
|
for (uint i = 0; i < world_altars.length(); i++) {
|
||||||
|
if (world_altars[i].position == pos) {
|
||||||
|
return @world_altars[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
// World drops - items that can be picked up from the world
|
||||||
|
// Includes item placement, sound management, and pickup logic
|
||||||
|
|
||||||
|
class WorldDrop {
|
||||||
|
int position;
|
||||||
|
string type;
|
||||||
|
int sound_handle;
|
||||||
|
|
||||||
|
WorldDrop(int pos, string t) {
|
||||||
|
position = pos;
|
||||||
|
type = t;
|
||||||
|
sound_handle = -1;
|
||||||
|
// Start looping item sound at position
|
||||||
|
sound_handle = p.play_1d("sounds/items/item.ogg", x, position, true);
|
||||||
|
if (sound_handle != -1) {
|
||||||
|
p.update_sound_positioning_values(sound_handle, -1.0, 3.0, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void update() {
|
||||||
|
if (sound_handle == -1 || !p.sound_is_active(sound_handle)) {
|
||||||
|
sound_handle = p.play_1d("sounds/items/item.ogg", x, position, true);
|
||||||
|
if (sound_handle != -1) {
|
||||||
|
p.update_sound_positioning_values(sound_handle, -1.0, 3.0, true);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Update source position for 1d sound
|
||||||
|
p.update_sound_1d(sound_handle, position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void destroy() {
|
||||||
|
if (sound_handle != -1) {
|
||||||
|
p.destroy_sound(sound_handle);
|
||||||
|
sound_handle = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WorldDrop@[] world_drops;
|
||||||
|
|
||||||
|
void add_world_drop(int pos, string type) {
|
||||||
|
WorldDrop@ d = WorldDrop(pos, type);
|
||||||
|
world_drops.insert_last(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_world_drops() {
|
||||||
|
for (uint i = 0; i < world_drops.length(); i++) {
|
||||||
|
world_drops[i].update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WorldDrop@ get_drop_at(int pos) {
|
||||||
|
for (uint i = 0; i < world_drops.length(); i++) {
|
||||||
|
if (world_drops[i].position == pos) {
|
||||||
|
return @world_drops[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
void remove_drop_at(int pos) {
|
||||||
|
for (uint i = 0; i < world_drops.length(); i++) {
|
||||||
|
if (world_drops[i].position == pos) {
|
||||||
|
world_drops[i].destroy();
|
||||||
|
world_drops.remove_at(i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear_world_drops() {
|
||||||
|
for (uint i = 0; i < world_drops.length(); i++) {
|
||||||
|
world_drops[i].destroy();
|
||||||
|
}
|
||||||
|
world_drops.resize(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool try_pickup_small_game(string game_type) {
|
||||||
|
if (inv_small_game >= get_personal_stack_limit()) {
|
||||||
|
speak_with_history("You can't carry any more small game.", true);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
inv_small_game++;
|
||||||
|
inv_small_game_types.insert_last(game_type);
|
||||||
|
speak_with_history("Picked up " + game_type + ".", true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool try_pickup_world_drop(WorldDrop@ drop) {
|
||||||
|
if (get_flying_creature_config_by_drop_type(drop.type) !is null) {
|
||||||
|
return try_pickup_small_game(drop.type);
|
||||||
|
}
|
||||||
|
if (drop.type == "boar carcass") {
|
||||||
|
if (inv_boar_carcasses >= get_personal_stack_limit()) {
|
||||||
|
speak_with_history("You can't carry any more boar carcasses.", true);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
inv_boar_carcasses++;
|
||||||
|
speak_with_history("Picked up boar carcass.", true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
speak_with_history("Picked up " + drop.type + ".", true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
@@ -0,0 +1,130 @@
|
|||||||
|
// World fires - burning fires that require fuel
|
||||||
|
// Includes fire placement, fuel management, burnout logic, and sound
|
||||||
|
|
||||||
|
class WorldFire {
|
||||||
|
int position;
|
||||||
|
int sound_handle;
|
||||||
|
timer fuel_timer;
|
||||||
|
int fuel_remaining;
|
||||||
|
bool low_fuel_warned;
|
||||||
|
|
||||||
|
WorldFire(int pos) {
|
||||||
|
position = pos;
|
||||||
|
sound_handle = -1;
|
||||||
|
fuel_remaining = 720000; // Start with 12 minutes (12 hours in-game)
|
||||||
|
low_fuel_warned = false;
|
||||||
|
fuel_timer.restart();
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_fuel(int amount) {
|
||||||
|
fuel_remaining += amount;
|
||||||
|
low_fuel_warned = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_burning() {
|
||||||
|
return fuel_remaining > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void update() {
|
||||||
|
// Update fuel
|
||||||
|
if (fuel_remaining > 0) {
|
||||||
|
int elapsed = fuel_timer.elapsed;
|
||||||
|
fuel_timer.restart();
|
||||||
|
fuel_remaining -= elapsed;
|
||||||
|
|
||||||
|
// Warn when fuel is low (30 seconds remaining)
|
||||||
|
if (!low_fuel_warned && fuel_remaining <= 30000 && fuel_remaining > 0) {
|
||||||
|
low_fuel_warned = true;
|
||||||
|
notify("Fire at x " + position + " y " + y + " is getting low!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fire went out
|
||||||
|
if (fuel_remaining <= 0) {
|
||||||
|
fuel_remaining = 0;
|
||||||
|
notify("Fire at x " + position + " y " + y + " has gone out.");
|
||||||
|
if (sound_handle != -1) {
|
||||||
|
p.destroy_sound(sound_handle);
|
||||||
|
sound_handle = -1;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hard cutoff for fire sound.
|
||||||
|
if (is_burning()) {
|
||||||
|
int fire_distance = x - position;
|
||||||
|
if (fire_distance < 0) fire_distance = -fire_distance;
|
||||||
|
if (fire_distance <= FIRE_SOUND_RANGE) {
|
||||||
|
if (sound_handle == -1 || !p.sound_is_active(sound_handle)) {
|
||||||
|
sound_handle = p.play_1d("sounds/items/fire.ogg", x, position, true);
|
||||||
|
if (sound_handle != -1) {
|
||||||
|
p.update_sound_positioning_values(sound_handle, -1.0, FIRE_SOUND_VOLUME_STEP, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (sound_handle != -1) {
|
||||||
|
p.destroy_sound(sound_handle);
|
||||||
|
sound_handle = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void destroy() {
|
||||||
|
if (sound_handle != -1) {
|
||||||
|
p.destroy_sound(sound_handle);
|
||||||
|
sound_handle = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WorldFire@[] world_fires;
|
||||||
|
|
||||||
|
void add_world_fire(int pos) {
|
||||||
|
WorldFire@ f = WorldFire(pos);
|
||||||
|
world_fires.insert_last(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_fires() {
|
||||||
|
// Update all fires and remove any that have burned out
|
||||||
|
for (uint i = 0; i < world_fires.length(); i++) {
|
||||||
|
world_fires[i].update();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove dead fires
|
||||||
|
for (uint i = 0; i < world_fires.length(); i++) {
|
||||||
|
if (!world_fires[i].is_burning()) {
|
||||||
|
world_fires[i].destroy();
|
||||||
|
world_fires.remove_at(i);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WorldFire@ get_fire_at(int pos) {
|
||||||
|
for (uint i = 0; i < world_fires.length(); i++) {
|
||||||
|
if (world_fires[i].position == pos) {
|
||||||
|
return @world_fires[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
WorldFire@ get_fire_near(int pos) {
|
||||||
|
// Check for fire at current position or adjacent tiles
|
||||||
|
for (int check_x = pos - 1; check_x <= pos + 1; check_x++) {
|
||||||
|
WorldFire@ fire = get_fire_at(check_x);
|
||||||
|
if (fire != null && fire.is_burning()) {
|
||||||
|
return @fire;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
WorldFire@ get_fire_within_range(int pos, int range) {
|
||||||
|
// Check for fire within specified range
|
||||||
|
for (int check_x = pos - range; check_x <= pos + range; check_x++) {
|
||||||
|
WorldFire@ fire = get_fire_at(check_x);
|
||||||
|
if (fire != null && fire.is_burning()) {
|
||||||
|
return @fire;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
@@ -0,0 +1,141 @@
|
|||||||
|
// World snares - traps for catching small game
|
||||||
|
// Includes snare placement, catch mechanics, escape logic, and collision detection
|
||||||
|
|
||||||
|
// Small game types that can be caught in snares
|
||||||
|
string[] small_game_types = {"rabbit", "squirrel", "raccoon", "opossum", "groundhog"};
|
||||||
|
|
||||||
|
string get_random_small_game() {
|
||||||
|
int index = random(0, small_game_types.length() - 1);
|
||||||
|
return small_game_types[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
class WorldSnare {
|
||||||
|
int position;
|
||||||
|
bool has_catch;
|
||||||
|
string catch_type; // What type of small game was caught
|
||||||
|
int catch_chance;
|
||||||
|
int escape_chance;
|
||||||
|
int sound_handle;
|
||||||
|
timer minute_timer;
|
||||||
|
bool active; // To prevent immediate breakage on placement
|
||||||
|
|
||||||
|
WorldSnare(int pos) {
|
||||||
|
position = pos;
|
||||||
|
has_catch = false;
|
||||||
|
catch_type = "";
|
||||||
|
catch_chance = 5;
|
||||||
|
escape_chance = 5;
|
||||||
|
active = false; // Becomes active when player steps off
|
||||||
|
sound_handle = -1;
|
||||||
|
|
||||||
|
minute_timer.restart();
|
||||||
|
}
|
||||||
|
|
||||||
|
void update() {
|
||||||
|
// Activate if player moves away
|
||||||
|
if (!active && x != position) {
|
||||||
|
active = true;
|
||||||
|
minute_timer.restart();
|
||||||
|
}
|
||||||
|
|
||||||
|
int snare_distance = x - position;
|
||||||
|
if (snare_distance < 0) snare_distance = -snare_distance;
|
||||||
|
|
||||||
|
if (snare_distance <= SNARE_SOUND_RANGE) {
|
||||||
|
if (sound_handle == -1 || !p.sound_is_active(sound_handle)) {
|
||||||
|
sound_handle = p.play_1d("sounds/actions/set_snare.ogg", x, position, true);
|
||||||
|
if (sound_handle != -1) {
|
||||||
|
p.update_sound_positioning_values(sound_handle, SNARE_SOUND_PAN_STEP, SNARE_SOUND_VOLUME_STEP, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (sound_handle != -1) {
|
||||||
|
p.destroy_sound(sound_handle);
|
||||||
|
sound_handle = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Every minute logic (only when active)
|
||||||
|
if (active && minute_timer.elapsed >= 60000) {
|
||||||
|
minute_timer.restart();
|
||||||
|
|
||||||
|
if (has_catch) {
|
||||||
|
// Animal trying to escape
|
||||||
|
if (escape_chance < 95) escape_chance += 5;
|
||||||
|
|
||||||
|
int roll = random(1, 100);
|
||||||
|
if (roll <= escape_chance) {
|
||||||
|
// Animal escaped!
|
||||||
|
notify("A " + catch_type + " escaped from your snare at x " + position + " y 0!");
|
||||||
|
remove_snare_at(position);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Trying to catch small game
|
||||||
|
if (catch_chance < 75) catch_chance += 5;
|
||||||
|
|
||||||
|
int roll = random(1, 100);
|
||||||
|
if (roll <= catch_chance) {
|
||||||
|
// Caught something!
|
||||||
|
has_catch = true;
|
||||||
|
catch_type = get_random_small_game();
|
||||||
|
escape_chance = 5; // Reset escape chance
|
||||||
|
notify(catch_type + " caught in snare at x " + position + " y 0!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void destroy() {
|
||||||
|
if (sound_handle != -1) {
|
||||||
|
p.destroy_sound(sound_handle);
|
||||||
|
sound_handle = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WorldSnare@[] world_snares;
|
||||||
|
|
||||||
|
void add_world_snare(int pos) {
|
||||||
|
WorldSnare@ s = WorldSnare(pos);
|
||||||
|
world_snares.insert_last(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
WorldSnare@ get_snare_at(int pos) {
|
||||||
|
for (uint i = 0; i < world_snares.length(); i++) {
|
||||||
|
if (world_snares[i].position == pos) {
|
||||||
|
return @world_snares[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
void remove_snare_at(int pos) {
|
||||||
|
for (uint i = 0; i < world_snares.length(); i++) {
|
||||||
|
if (world_snares[i].position == pos) {
|
||||||
|
world_snares[i].destroy();
|
||||||
|
world_snares.remove_at(i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called when player moves onto a tile
|
||||||
|
void check_snare_collision(int player_x) {
|
||||||
|
WorldSnare@ s = get_snare_at(player_x);
|
||||||
|
if (s != null && s.active) {
|
||||||
|
// Break the snare
|
||||||
|
p.play_stationary("sounds/actions/break_snare.ogg", false);
|
||||||
|
|
||||||
|
if (s.has_catch) {
|
||||||
|
speak_with_history("You stepped on your snare! The " + s.catch_type + " escaped.", true);
|
||||||
|
} else {
|
||||||
|
speak_with_history("You stepped on your snare and broke it!", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
remove_snare_at(player_x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_snares() {
|
||||||
|
for (int i = int(world_snares.length()) - 1; i >= 0; i--) {
|
||||||
|
world_snares[i].update();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
// World streams - flowing water for fishing and geese spawning
|
||||||
|
// Includes stream placement, sound management, and position queries
|
||||||
|
|
||||||
|
class WorldStream {
|
||||||
|
int start_position;
|
||||||
|
int end_position;
|
||||||
|
int sound_handle;
|
||||||
|
int sound_position;
|
||||||
|
|
||||||
|
WorldStream(int start_pos, int width) {
|
||||||
|
start_position = start_pos;
|
||||||
|
end_position = start_pos + width - 1;
|
||||||
|
sound_handle = -1;
|
||||||
|
sound_position = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool contains_position(int pos) {
|
||||||
|
return pos >= start_position && pos <= end_position;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_width() {
|
||||||
|
return end_position - start_position + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_center_position() {
|
||||||
|
return (start_position + end_position) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void update() {
|
||||||
|
int sound_pos = 0;
|
||||||
|
if (x < start_position) {
|
||||||
|
sound_pos = start_position;
|
||||||
|
} else if (x > end_position) {
|
||||||
|
sound_pos = end_position;
|
||||||
|
} else {
|
||||||
|
sound_pos = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keep stream sound active so distance-based fade can work.
|
||||||
|
if (sound_handle == -1 || !p.sound_is_active(sound_handle)) {
|
||||||
|
sound_handle = p.play_1d("sounds/terrain/stream.ogg", x, sound_pos, true);
|
||||||
|
sound_position = sound_pos;
|
||||||
|
if (sound_handle != -1) {
|
||||||
|
p.update_sound_positioning_values(sound_handle, -1.0, STREAM_SOUND_VOLUME_STEP, true);
|
||||||
|
}
|
||||||
|
} else if (sound_position != sound_pos) {
|
||||||
|
p.update_sound_1d(sound_handle, sound_pos);
|
||||||
|
sound_position = sound_pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void destroy() {
|
||||||
|
if (sound_handle != -1) {
|
||||||
|
p.destroy_sound(sound_handle);
|
||||||
|
sound_handle = -1;
|
||||||
|
}
|
||||||
|
sound_position = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WorldStream@[] world_streams;
|
||||||
|
|
||||||
|
void add_world_stream(int start_pos, int width) {
|
||||||
|
WorldStream@ s = WorldStream(start_pos, width);
|
||||||
|
world_streams.insert_last(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_streams() {
|
||||||
|
for (uint i = 0; i < world_streams.length(); i++) {
|
||||||
|
world_streams[i].update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WorldStream@ get_stream_at(int pos) {
|
||||||
|
for (uint i = 0; i < world_streams.length(); i++) {
|
||||||
|
if (world_streams[i].contains_position(pos)) {
|
||||||
|
return @world_streams[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_position_in_water(int pos) {
|
||||||
|
return get_stream_at(pos) != null;
|
||||||
|
}
|
||||||
@@ -1,461 +1,14 @@
|
|||||||
// World Objects
|
// World Objects
|
||||||
|
|
||||||
// Small game types that can be caught in snares
|
|
||||||
string[] small_game_types = {"rabbit", "squirrel", "raccoon", "opossum", "groundhog"};
|
|
||||||
|
|
||||||
int barricade_health = 0;
|
int barricade_health = 0;
|
||||||
bool barricade_initialized = false;
|
bool barricade_initialized = false;
|
||||||
int residents_count = 0;
|
int residents_count = 0;
|
||||||
|
|
||||||
string get_random_small_game() {
|
|
||||||
int index = random(0, small_game_types.length() - 1);
|
|
||||||
return small_game_types[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
class WorldDrop {
|
|
||||||
int position;
|
|
||||||
string type;
|
|
||||||
int sound_handle;
|
|
||||||
|
|
||||||
WorldDrop(int pos, string t) {
|
|
||||||
position = pos;
|
|
||||||
type = t;
|
|
||||||
sound_handle = -1;
|
|
||||||
// Start looping item sound at position
|
|
||||||
sound_handle = p.play_1d("sounds/items/item.ogg", x, position, true);
|
|
||||||
if (sound_handle != -1) {
|
|
||||||
p.update_sound_positioning_values(sound_handle, -1.0, 3.0, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void update() {
|
|
||||||
if (sound_handle == -1 || !p.sound_is_active(sound_handle)) {
|
|
||||||
sound_handle = p.play_1d("sounds/items/item.ogg", x, position, true);
|
|
||||||
if (sound_handle != -1) {
|
|
||||||
p.update_sound_positioning_values(sound_handle, -1.0, 3.0, true);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Update source position for 1d sound
|
|
||||||
p.update_sound_1d(sound_handle, position);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void destroy() {
|
|
||||||
if (sound_handle != -1) {
|
|
||||||
p.destroy_sound(sound_handle);
|
|
||||||
sound_handle = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
WorldDrop@[] world_drops;
|
|
||||||
|
|
||||||
void add_world_drop(int pos, string type) {
|
|
||||||
WorldDrop@ d = WorldDrop(pos, type);
|
|
||||||
world_drops.insert_last(d);
|
|
||||||
}
|
|
||||||
|
|
||||||
void update_world_drops() {
|
|
||||||
for (uint i = 0; i < world_drops.length(); i++) {
|
|
||||||
world_drops[i].update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
WorldDrop@ get_drop_at(int pos) {
|
|
||||||
for (uint i = 0; i < world_drops.length(); i++) {
|
|
||||||
if (world_drops[i].position == pos) {
|
|
||||||
return @world_drops[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
void remove_drop_at(int pos) {
|
|
||||||
for (uint i = 0; i < world_drops.length(); i++) {
|
|
||||||
if (world_drops[i].position == pos) {
|
|
||||||
world_drops[i].destroy();
|
|
||||||
world_drops.remove_at(i);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void clear_world_drops() {
|
|
||||||
for (uint i = 0; i < world_drops.length(); i++) {
|
|
||||||
world_drops[i].destroy();
|
|
||||||
}
|
|
||||||
world_drops.resize(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool try_pickup_small_game(string game_type) {
|
|
||||||
if (inv_small_game >= get_personal_stack_limit()) {
|
|
||||||
speak_with_history("You can't carry any more small game.", true);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
inv_small_game++;
|
|
||||||
inv_small_game_types.insert_last(game_type);
|
|
||||||
speak_with_history("Picked up " + game_type + ".", true);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool try_pickup_world_drop(WorldDrop@ drop) {
|
|
||||||
if (get_flying_creature_config_by_drop_type(drop.type) !is null) {
|
|
||||||
return try_pickup_small_game(drop.type);
|
|
||||||
}
|
|
||||||
if (drop.type == "boar carcass") {
|
|
||||||
if (inv_boar_carcasses >= get_personal_stack_limit()) {
|
|
||||||
speak_with_history("You can't carry any more boar carcasses.", true);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
inv_boar_carcasses++;
|
|
||||||
speak_with_history("Picked up boar carcass.", true);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
speak_with_history("Picked up " + drop.type + ".", true);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
class WorldSnare {
|
|
||||||
int position;
|
|
||||||
bool has_catch;
|
|
||||||
string catch_type; // What type of small game was caught
|
|
||||||
int catch_chance;
|
|
||||||
int escape_chance;
|
|
||||||
int sound_handle;
|
|
||||||
timer minute_timer;
|
|
||||||
bool active; // To prevent immediate breakage on placement
|
|
||||||
|
|
||||||
WorldSnare(int pos) {
|
|
||||||
position = pos;
|
|
||||||
has_catch = false;
|
|
||||||
catch_type = "";
|
|
||||||
catch_chance = 5;
|
|
||||||
escape_chance = 5;
|
|
||||||
active = false; // Becomes active when player steps off
|
|
||||||
sound_handle = -1;
|
|
||||||
|
|
||||||
minute_timer.restart();
|
|
||||||
}
|
|
||||||
|
|
||||||
void update() {
|
|
||||||
// Activate if player moves away
|
|
||||||
if (!active && x != position) {
|
|
||||||
active = true;
|
|
||||||
minute_timer.restart();
|
|
||||||
}
|
|
||||||
|
|
||||||
int snare_distance = x - position;
|
|
||||||
if (snare_distance < 0) snare_distance = -snare_distance;
|
|
||||||
|
|
||||||
if (snare_distance <= SNARE_SOUND_RANGE) {
|
|
||||||
if (sound_handle == -1 || !p.sound_is_active(sound_handle)) {
|
|
||||||
sound_handle = p.play_1d("sounds/actions/set_snare.ogg", x, position, true);
|
|
||||||
if (sound_handle != -1) {
|
|
||||||
p.update_sound_positioning_values(sound_handle, SNARE_SOUND_PAN_STEP, SNARE_SOUND_VOLUME_STEP, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (sound_handle != -1) {
|
|
||||||
p.destroy_sound(sound_handle);
|
|
||||||
sound_handle = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Every minute logic (only when active)
|
|
||||||
if (active && minute_timer.elapsed >= 60000) {
|
|
||||||
minute_timer.restart();
|
|
||||||
|
|
||||||
if (has_catch) {
|
|
||||||
// Animal trying to escape
|
|
||||||
if (escape_chance < 95) escape_chance += 5;
|
|
||||||
|
|
||||||
int roll = random(1, 100);
|
|
||||||
if (roll <= escape_chance) {
|
|
||||||
// Animal escaped!
|
|
||||||
notify("A " + catch_type + " escaped from your snare at x " + position + " y 0!");
|
|
||||||
remove_snare_at(position);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Trying to catch small game
|
|
||||||
if (catch_chance < 75) catch_chance += 5;
|
|
||||||
|
|
||||||
int roll = random(1, 100);
|
|
||||||
if (roll <= catch_chance) {
|
|
||||||
// Caught something!
|
|
||||||
has_catch = true;
|
|
||||||
catch_type = get_random_small_game();
|
|
||||||
escape_chance = 5; // Reset escape chance
|
|
||||||
notify(catch_type + " caught in snare at x " + position + " y 0!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void destroy() {
|
|
||||||
if (sound_handle != -1) {
|
|
||||||
p.destroy_sound(sound_handle);
|
|
||||||
sound_handle = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
WorldSnare@[] world_snares;
|
|
||||||
|
|
||||||
class WorldFire {
|
|
||||||
int position;
|
|
||||||
int sound_handle;
|
|
||||||
timer fuel_timer;
|
|
||||||
int fuel_remaining;
|
|
||||||
bool low_fuel_warned;
|
|
||||||
|
|
||||||
WorldFire(int pos) {
|
|
||||||
position = pos;
|
|
||||||
sound_handle = -1;
|
|
||||||
fuel_remaining = 720000; // Start with 12 minutes (12 hours in-game)
|
|
||||||
low_fuel_warned = false;
|
|
||||||
fuel_timer.restart();
|
|
||||||
}
|
|
||||||
|
|
||||||
void add_fuel(int amount) {
|
|
||||||
fuel_remaining += amount;
|
|
||||||
low_fuel_warned = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_burning() {
|
|
||||||
return fuel_remaining > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void update() {
|
|
||||||
// Update fuel
|
|
||||||
if (fuel_remaining > 0) {
|
|
||||||
int elapsed = fuel_timer.elapsed;
|
|
||||||
fuel_timer.restart();
|
|
||||||
fuel_remaining -= elapsed;
|
|
||||||
|
|
||||||
// Warn when fuel is low (30 seconds remaining)
|
|
||||||
if (!low_fuel_warned && fuel_remaining <= 30000 && fuel_remaining > 0) {
|
|
||||||
low_fuel_warned = true;
|
|
||||||
notify("Fire at x " + position + " y " + y + " is getting low!");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fire went out
|
|
||||||
if (fuel_remaining <= 0) {
|
|
||||||
fuel_remaining = 0;
|
|
||||||
notify("Fire at x " + position + " y " + y + " has gone out.");
|
|
||||||
if (sound_handle != -1) {
|
|
||||||
p.destroy_sound(sound_handle);
|
|
||||||
sound_handle = -1;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hard cutoff for fire sound.
|
|
||||||
if (is_burning()) {
|
|
||||||
int fire_distance = x - position;
|
|
||||||
if (fire_distance < 0) fire_distance = -fire_distance;
|
|
||||||
if (fire_distance <= FIRE_SOUND_RANGE) {
|
|
||||||
if (sound_handle == -1 || !p.sound_is_active(sound_handle)) {
|
|
||||||
sound_handle = p.play_1d("sounds/items/fire.ogg", x, position, true);
|
|
||||||
if (sound_handle != -1) {
|
|
||||||
p.update_sound_positioning_values(sound_handle, -1.0, FIRE_SOUND_VOLUME_STEP, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (sound_handle != -1) {
|
|
||||||
p.destroy_sound(sound_handle);
|
|
||||||
sound_handle = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void destroy() {
|
|
||||||
if (sound_handle != -1) {
|
|
||||||
p.destroy_sound(sound_handle);
|
|
||||||
sound_handle = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
WorldFire@[] world_fires;
|
|
||||||
|
|
||||||
class WorldFirepit {
|
|
||||||
int position;
|
|
||||||
|
|
||||||
WorldFirepit(int pos) {
|
|
||||||
position = pos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
WorldFirepit@[] world_firepits;
|
|
||||||
|
|
||||||
class WorldHerbGarden {
|
|
||||||
int position;
|
|
||||||
|
|
||||||
WorldHerbGarden(int pos) {
|
|
||||||
position = pos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
WorldHerbGarden@[] world_herb_gardens;
|
|
||||||
|
|
||||||
class WorldStorage {
|
|
||||||
int position;
|
|
||||||
|
|
||||||
WorldStorage(int pos) {
|
|
||||||
position = pos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
WorldStorage@[] world_storages;
|
|
||||||
|
|
||||||
class WorldPasture {
|
|
||||||
int position;
|
|
||||||
|
|
||||||
WorldPasture(int pos) {
|
|
||||||
position = pos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
WorldPasture@[] world_pastures;
|
|
||||||
|
|
||||||
class WorldStable {
|
|
||||||
int position;
|
|
||||||
|
|
||||||
WorldStable(int pos) {
|
|
||||||
position = pos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
WorldStable@[] world_stables;
|
|
||||||
|
|
||||||
class WorldAltar {
|
|
||||||
int position;
|
|
||||||
|
|
||||||
WorldAltar(int pos) {
|
|
||||||
position = pos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
WorldAltar@[] world_altars;
|
|
||||||
|
|
||||||
class WorldStream {
|
|
||||||
int start_position;
|
|
||||||
int end_position;
|
|
||||||
int sound_handle;
|
|
||||||
int sound_position;
|
|
||||||
|
|
||||||
WorldStream(int start_pos, int width) {
|
|
||||||
start_position = start_pos;
|
|
||||||
end_position = start_pos + width - 1;
|
|
||||||
sound_handle = -1;
|
|
||||||
sound_position = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool contains_position(int pos) {
|
|
||||||
return pos >= start_position && pos <= end_position;
|
|
||||||
}
|
|
||||||
|
|
||||||
int get_width() {
|
|
||||||
return end_position - start_position + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int get_center_position() {
|
|
||||||
return (start_position + end_position) / 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
void update() {
|
|
||||||
int sound_pos = 0;
|
|
||||||
if (x < start_position) {
|
|
||||||
sound_pos = start_position;
|
|
||||||
} else if (x > end_position) {
|
|
||||||
sound_pos = end_position;
|
|
||||||
} else {
|
|
||||||
sound_pos = x;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Keep stream sound active so distance-based fade can work.
|
|
||||||
if (sound_handle == -1 || !p.sound_is_active(sound_handle)) {
|
|
||||||
sound_handle = p.play_1d("sounds/terrain/stream.ogg", x, sound_pos, true);
|
|
||||||
sound_position = sound_pos;
|
|
||||||
if (sound_handle != -1) {
|
|
||||||
p.update_sound_positioning_values(sound_handle, -1.0, STREAM_SOUND_VOLUME_STEP, true);
|
|
||||||
}
|
|
||||||
} else if (sound_position != sound_pos) {
|
|
||||||
p.update_sound_1d(sound_handle, sound_pos);
|
|
||||||
sound_position = sound_pos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void destroy() {
|
|
||||||
if (sound_handle != -1) {
|
|
||||||
p.destroy_sound(sound_handle);
|
|
||||||
sound_handle = -1;
|
|
||||||
}
|
|
||||||
sound_position = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
WorldStream@[] world_streams;
|
|
||||||
|
|
||||||
void add_world_snare(int pos) {
|
|
||||||
WorldSnare@ s = WorldSnare(pos);
|
|
||||||
world_snares.insert_last(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
void add_world_fire(int pos) {
|
|
||||||
WorldFire@ f = WorldFire(pos);
|
|
||||||
world_fires.insert_last(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
void add_world_firepit(int pos) {
|
|
||||||
WorldFirepit@ fp = WorldFirepit(pos);
|
|
||||||
world_firepits.insert_last(fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void add_world_storage(int pos) {
|
|
||||||
WorldStorage@ s = WorldStorage(pos);
|
|
||||||
world_storages.insert_last(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
void add_world_pasture(int pos) {
|
|
||||||
WorldPasture@ p = WorldPasture(pos);
|
|
||||||
world_pastures.insert_last(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
void add_world_stable(int pos) {
|
|
||||||
WorldStable@ s = WorldStable(pos);
|
|
||||||
world_stables.insert_last(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
void add_world_altar(int pos) {
|
|
||||||
WorldAltar@ a = WorldAltar(pos);
|
|
||||||
world_altars.insert_last(a);
|
|
||||||
}
|
|
||||||
|
|
||||||
WorldStorage@ get_storage_at(int pos) {
|
|
||||||
for (uint i = 0; i < world_storages.length(); i++) {
|
|
||||||
if (world_storages[i].position == pos) {
|
|
||||||
return @world_storages[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
WorldPasture@ get_pasture_at(int pos) {
|
|
||||||
for (uint i = 0; i < world_pastures.length(); i++) {
|
|
||||||
if (world_pastures[i].position == pos) {
|
|
||||||
return @world_pastures[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
WorldStable@ get_stable_at(int pos) {
|
|
||||||
for (uint i = 0; i < world_stables.length(); i++) {
|
|
||||||
if (world_stables[i].position == pos) {
|
|
||||||
return @world_stables[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
WorldAltar@ get_altar_at(int pos) {
|
|
||||||
for (uint i = 0; i < world_altars.length(); i++) {
|
|
||||||
if (world_altars[i].position == pos) {
|
|
||||||
return @world_altars[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
void update_world_objects() {
|
void update_world_objects() {
|
||||||
for (uint i = 0; i < world_snares.length(); i++) {
|
for (uint i = 0; i < world_snares.length(); i++) {
|
||||||
@@ -466,125 +19,9 @@ void update_world_objects() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WorldSnare@ get_snare_at(int pos) {
|
|
||||||
for (uint i = 0; i < world_snares.length(); i++) {
|
|
||||||
if (world_snares[i].position == pos) {
|
|
||||||
return @world_snares[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
void remove_snare_at(int pos) {
|
|
||||||
for (uint i = 0; i < world_snares.length(); i++) {
|
|
||||||
if (world_snares[i].position == pos) {
|
|
||||||
world_snares[i].destroy();
|
|
||||||
world_snares.remove_at(i);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Called when player moves onto a tile
|
|
||||||
void check_snare_collision(int player_x) {
|
|
||||||
WorldSnare@ s = get_snare_at(player_x);
|
|
||||||
if (s != null && s.active) {
|
|
||||||
// Break the snare
|
|
||||||
p.play_stationary("sounds/actions/break_snare.ogg", false);
|
|
||||||
|
|
||||||
if (s.has_catch) {
|
|
||||||
speak_with_history("You stepped on your snare! The " + s.catch_type + " escaped.", true);
|
|
||||||
} else {
|
|
||||||
speak_with_history("You stepped on your snare and broke it!", true);
|
|
||||||
}
|
|
||||||
|
|
||||||
remove_snare_at(player_x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void update_snares() {
|
|
||||||
for (int i = int(world_snares.length()) - 1; i >= 0; i--) {
|
|
||||||
world_snares[i].update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void update_streams() {
|
|
||||||
for (uint i = 0; i < world_streams.length(); i++) {
|
|
||||||
world_streams[i].update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void update_fires() {
|
|
||||||
// Update all fires and remove any that have burned out
|
|
||||||
for (uint i = 0; i < world_fires.length(); i++) {
|
|
||||||
world_fires[i].update();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove dead fires
|
|
||||||
for (uint i = 0; i < world_fires.length(); i++) {
|
|
||||||
if (!world_fires[i].is_burning()) {
|
|
||||||
world_fires[i].destroy();
|
|
||||||
world_fires.remove_at(i);
|
|
||||||
i--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
WorldFire@ get_fire_at(int pos) {
|
|
||||||
for (uint i = 0; i < world_fires.length(); i++) {
|
|
||||||
if (world_fires[i].position == pos) {
|
|
||||||
return @world_fires[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
WorldFire@ get_fire_near(int pos) {
|
|
||||||
// Check for fire at current position or adjacent tiles
|
|
||||||
for (int check_x = pos - 1; check_x <= pos + 1; check_x++) {
|
|
||||||
WorldFire@ fire = get_fire_at(check_x);
|
|
||||||
if (fire != null && fire.is_burning()) {
|
|
||||||
return @fire;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
WorldFire@ get_fire_within_range(int pos, int range) {
|
|
||||||
// Check for fire within specified range
|
|
||||||
for (int check_x = pos - range; check_x <= pos + range; check_x++) {
|
|
||||||
WorldFire@ fire = get_fire_at(check_x);
|
|
||||||
if (fire != null && fire.is_burning()) {
|
|
||||||
return @fire;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
WorldFirepit@ get_firepit_at(int pos) {
|
|
||||||
for (uint i = 0; i < world_firepits.length(); i++) {
|
|
||||||
if (world_firepits[i].position == pos) {
|
|
||||||
return @world_firepits[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
WorldFirepit@ get_firepit_near(int pos, int range) {
|
|
||||||
// Check for firepit within specified range
|
|
||||||
for (int check_x = pos - range; check_x <= pos + range; check_x++) {
|
|
||||||
WorldFirepit@ firepit = get_firepit_at(check_x);
|
|
||||||
if (firepit != null) {
|
|
||||||
return @firepit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
void add_world_herb_garden(int pos) {
|
|
||||||
WorldHerbGarden@ hg = WorldHerbGarden(pos);
|
|
||||||
world_herb_gardens.insert_last(hg);
|
|
||||||
}
|
|
||||||
|
|
||||||
void init_barricade() {
|
void init_barricade() {
|
||||||
if (barricade_initialized) {
|
if (barricade_initialized) {
|
||||||
@@ -611,46 +48,10 @@ int add_barricade_health(int amount) {
|
|||||||
|
|
||||||
// Zombie functions moved to src/enemies/undead.nvgt
|
// Zombie functions moved to src/enemies/undead.nvgt
|
||||||
|
|
||||||
WorldHerbGarden@ get_herb_garden_at(int pos) {
|
|
||||||
for (uint i = 0; i < world_herb_gardens.length(); i++) {
|
|
||||||
if (world_herb_gardens[i].position == pos) {
|
|
||||||
return @world_herb_gardens[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
WorldHerbGarden@ get_herb_garden_at_base() {
|
|
||||||
// Check if herb garden exists anywhere in base area (0-4)
|
|
||||||
for (uint i = 0; i < world_herb_gardens.length(); i++) {
|
|
||||||
if (world_herb_gardens[i].position <= BASE_END) {
|
|
||||||
return @world_herb_gardens[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bandit functions moved to src/enemies/bandit.nvgt
|
// Bandit functions moved to src/enemies/bandit.nvgt
|
||||||
// Boar/GroundGame functions moved to src/enemies/ground_game.nvgt
|
// Boar/GroundGame functions moved to src/enemies/ground_game.nvgt
|
||||||
|
|
||||||
// Stream Functions
|
|
||||||
void add_world_stream(int start_pos, int width) {
|
|
||||||
WorldStream@ s = WorldStream(start_pos, width);
|
|
||||||
world_streams.insert_last(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
WorldStream@ get_stream_at(int pos) {
|
|
||||||
for (uint i = 0; i < world_streams.length(); i++) {
|
|
||||||
if (world_streams[i].contains_position(pos)) {
|
|
||||||
return @world_streams[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_position_in_water(int pos) {
|
|
||||||
return get_stream_at(pos) != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mountain Range Class
|
// Mountain Range Class
|
||||||
class MountainRange {
|
class MountainRange {
|
||||||
|
|||||||
Reference in New Issue
Block a user