Oh wow, I thought I already pushed some of this stuff. Let's see if I can remember it all. Undead residents added. Whights added, Vampyrs added. Bandit Hideout adventure added.
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "src/bosses/adventure_combat.nvgt"
|
||||
#include "src/bosses/unicorn/unicorn_boss.nvgt"
|
||||
#include "src/bosses/bandit_hideout.nvgt"
|
||||
|
||||
void check_adventure_menu(int player_x) {
|
||||
if (key_pressed(KEY_TAB)) {
|
||||
@@ -26,13 +27,18 @@ void run_adventure_menu(int player_x) {
|
||||
|
||||
// Check available adventures based on terrain
|
||||
string[] options;
|
||||
int[] adventure_ids; // 1 = Unicorn
|
||||
int[] adventure_ids; // 1 = Unicorn, 2 = Bandit's Hideout
|
||||
|
||||
if (mountain !is null) {
|
||||
// Mountain terrain
|
||||
options.insert_last("Unicorn Hunt (Mountain Boss)");
|
||||
adventure_ids.insert_last(1);
|
||||
}
|
||||
|
||||
if (mountain is null && (terrain == "forest" || terrain == "deep_forest")) {
|
||||
options.insert_last("Bandit's Hideout");
|
||||
adventure_ids.insert_last(ADVENTURE_BANDIT_HIDEOUT);
|
||||
}
|
||||
|
||||
if (options.length() == 0) {
|
||||
speak_with_history("No adventures found in this area.", true);
|
||||
@@ -78,5 +84,7 @@ void start_adventure(int adventure_id) {
|
||||
last_adventure_day = current_day;
|
||||
if (adventure_id == 1) {
|
||||
run_unicorn_adventure();
|
||||
} else if (adventure_id == ADVENTURE_BANDIT_HIDEOUT) {
|
||||
run_bandit_hideout_adventure();
|
||||
}
|
||||
}
|
||||
|
||||
669
src/bosses/bandit_hideout.nvgt
Normal file
669
src/bosses/bandit_hideout.nvgt
Normal file
@@ -0,0 +1,669 @@
|
||||
// Bandit's Hideout Adventure logic
|
||||
// Terrain: Forest / Deep Forest
|
||||
// Objective: Break the barricade at the enemy base.
|
||||
|
||||
const int ADVENTURE_BANDIT_HIDEOUT = 2;
|
||||
const int BANDIT_HIDEOUT_MAP_SIZE = 100;
|
||||
const int BANDIT_HIDEOUT_SEGMENT_MIN = 5;
|
||||
const int BANDIT_HIDEOUT_SEGMENT_MAX = 10;
|
||||
const int BANDIT_HIDEOUT_BANDIT_COUNT = 5;
|
||||
const int BANDIT_HIDEOUT_BASE_SPAWN_RANGE = 10;
|
||||
const int BANDIT_HIDEOUT_START_SPAWN_RANGE = 10;
|
||||
const int BANDIT_HIDEOUT_BARRICADE_HP_PER_DAY = 34;
|
||||
const int BANDIT_HIDEOUT_BARRICADE_HP_MAX = 500;
|
||||
const double BANDIT_HIDEOUT_FAVOR_PER_KILL = 0.2;
|
||||
const double BANDIT_HIDEOUT_BASE_FAVOR = 3.0;
|
||||
const double BANDIT_HIDEOUT_FAVOR_MAX = 10.0;
|
||||
|
||||
class HideoutBandit {
|
||||
int position;
|
||||
int health;
|
||||
string alertSound;
|
||||
string weaponType; // "spear" or "axe"
|
||||
int soundHandle;
|
||||
bool inWeaponRange;
|
||||
timer moveTimer;
|
||||
timer attackTimer;
|
||||
int moveInterval;
|
||||
|
||||
HideoutBandit(int pos, const string&in alert, const string&in weapon, int interval) {
|
||||
position = pos;
|
||||
health = BANDIT_HEALTH;
|
||||
alertSound = alert;
|
||||
weaponType = weapon;
|
||||
moveInterval = interval;
|
||||
soundHandle = -1;
|
||||
inWeaponRange = false;
|
||||
moveTimer.restart();
|
||||
attackTimer.restart();
|
||||
}
|
||||
}
|
||||
|
||||
HideoutBandit@[] hideoutBandits;
|
||||
string[] hideoutTerrain;
|
||||
int hideoutPlayerX = 0;
|
||||
int hideoutPlayerFacing = 1; // 0 = west, 1 = east
|
||||
int hideoutBaseX = BANDIT_HIDEOUT_MAP_SIZE - 1;
|
||||
int hideoutBarricadeHealth = 0;
|
||||
int hideoutBarricadeMax = 0;
|
||||
int hideoutBanditsKilled = 0;
|
||||
timer hideoutWalkTimer;
|
||||
timer hideoutAttackTimer;
|
||||
timer hideoutSearchTimer;
|
||||
timer hideoutSearchDelayTimer;
|
||||
bool hideoutSearching = false;
|
||||
|
||||
string pick_hideout_terrain() {
|
||||
int roll = random(0, 2);
|
||||
if (roll == 0) return "grass";
|
||||
if (roll == 1) return "gravel";
|
||||
return "stone";
|
||||
}
|
||||
|
||||
void build_hideout_terrain() {
|
||||
hideoutTerrain.resize(BANDIT_HIDEOUT_MAP_SIZE);
|
||||
int index = 0;
|
||||
while (index < BANDIT_HIDEOUT_MAP_SIZE) {
|
||||
int segmentLength = random(BANDIT_HIDEOUT_SEGMENT_MIN, BANDIT_HIDEOUT_SEGMENT_MAX);
|
||||
string terrain = pick_hideout_terrain();
|
||||
for (int i = 0; i < segmentLength && index < BANDIT_HIDEOUT_MAP_SIZE; i++) {
|
||||
hideoutTerrain[index] = terrain;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
if (hideoutBaseX >= 0 && hideoutBaseX < int(hideoutTerrain.length())) {
|
||||
hideoutTerrain[hideoutBaseX] = "stone";
|
||||
}
|
||||
}
|
||||
|
||||
string get_hideout_terrain_at(int pos) {
|
||||
if (pos < 0 || pos >= int(hideoutTerrain.length())) return "grass";
|
||||
string terrain = hideoutTerrain[pos];
|
||||
if (terrain == "") return "grass";
|
||||
return terrain;
|
||||
}
|
||||
|
||||
string get_hideout_footstep_sound(int pos) {
|
||||
string terrain = get_hideout_terrain_at(pos);
|
||||
if (terrain == "stone") return "sounds/terrain/stone.ogg";
|
||||
if (terrain == "gravel") return "sounds/terrain/gravel.ogg";
|
||||
return "sounds/terrain/grass.ogg";
|
||||
}
|
||||
|
||||
void play_hideout_player_footstep() {
|
||||
string soundFile = get_hideout_footstep_sound(hideoutPlayerX);
|
||||
if (file_exists(soundFile)) {
|
||||
p.play_stationary(soundFile, false);
|
||||
}
|
||||
}
|
||||
|
||||
void play_hideout_positional_footstep(int listenerX, int stepX, int maxDistance, float volumeStep) {
|
||||
if (abs(stepX - listenerX) > maxDistance) return;
|
||||
string soundFile = get_hideout_footstep_sound(stepX);
|
||||
if (file_exists(soundFile)) {
|
||||
play_1d_with_volume_step(soundFile, listenerX, stepX, false, volumeStep);
|
||||
}
|
||||
}
|
||||
|
||||
void clear_hideout_bandits() {
|
||||
for (uint i = 0; i < hideoutBandits.length(); i++) {
|
||||
if (hideoutBandits[i].soundHandle != -1) {
|
||||
p.destroy_sound(hideoutBandits[i].soundHandle);
|
||||
hideoutBandits[i].soundHandle = -1;
|
||||
}
|
||||
hideoutBandits[i].inWeaponRange = false;
|
||||
}
|
||||
hideoutBandits.resize(0);
|
||||
}
|
||||
|
||||
HideoutBandit@ get_hideout_bandit_at(int pos) {
|
||||
for (uint i = 0; i < hideoutBandits.length(); i++) {
|
||||
if (hideoutBandits[i].position == pos) {
|
||||
return @hideoutBandits[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
int clamp_hideout_spawn_start(int startX) {
|
||||
if (startX < 0) return 0;
|
||||
if (startX >= BANDIT_HIDEOUT_MAP_SIZE) return BANDIT_HIDEOUT_MAP_SIZE - 1;
|
||||
return startX;
|
||||
}
|
||||
|
||||
int clamp_hideout_spawn_end(int endX) {
|
||||
if (endX < 0) return 0;
|
||||
if (endX >= BANDIT_HIDEOUT_MAP_SIZE) return BANDIT_HIDEOUT_MAP_SIZE - 1;
|
||||
return endX;
|
||||
}
|
||||
|
||||
int pick_hideout_spawn_position(int startX, int endX) {
|
||||
int startClamp = clamp_hideout_spawn_start(startX);
|
||||
int endClamp = clamp_hideout_spawn_end(endX);
|
||||
if (startClamp > endClamp) {
|
||||
int swapTemp = startClamp;
|
||||
startClamp = endClamp;
|
||||
endClamp = swapTemp;
|
||||
}
|
||||
|
||||
int spawnX = -1;
|
||||
for (int attempt = 0; attempt < 20; attempt++) {
|
||||
int candidate = random(startClamp, endClamp);
|
||||
if (candidate == hideoutPlayerX) continue;
|
||||
if (get_hideout_bandit_at(candidate) != null) continue;
|
||||
spawnX = candidate;
|
||||
break;
|
||||
}
|
||||
if (spawnX == -1) {
|
||||
spawnX = random(startClamp, endClamp);
|
||||
}
|
||||
return spawnX;
|
||||
}
|
||||
|
||||
void spawn_hideout_bandit_in_range(int startX, int endX) {
|
||||
int spawnX = pick_hideout_spawn_position(startX, endX);
|
||||
string alertSound = pick_invader_alert_sound("bandit");
|
||||
if (alertSound == "") alertSound = "sounds/enemies/bandit1.ogg";
|
||||
string weaponType = (random(0, 1) == 0) ? "spear" : "axe";
|
||||
int moveInterval = random(BANDIT_MOVE_INTERVAL_MIN, BANDIT_MOVE_INTERVAL_MAX);
|
||||
|
||||
HideoutBandit@ bandit = HideoutBandit(spawnX, alertSound, weaponType, moveInterval);
|
||||
hideoutBandits.insert_last(bandit);
|
||||
bandit.soundHandle = play_1d_with_volume_step(bandit.alertSound, hideoutPlayerX, bandit.position, true, BANDIT_SOUND_VOLUME_STEP);
|
||||
}
|
||||
|
||||
void spawn_hideout_bandits_initial() {
|
||||
int baseSpawnStart = hideoutBaseX - (BANDIT_HIDEOUT_BASE_SPAWN_RANGE - 1);
|
||||
int baseSpawnEnd = hideoutBaseX;
|
||||
for (int i = 0; i < BANDIT_HIDEOUT_BANDIT_COUNT; i++) {
|
||||
spawn_hideout_bandit_in_range(baseSpawnStart, baseSpawnEnd);
|
||||
}
|
||||
}
|
||||
|
||||
void respawn_hideout_bandit() {
|
||||
int startSpawnStart = 0;
|
||||
int startSpawnEnd = BANDIT_HIDEOUT_START_SPAWN_RANGE - 1;
|
||||
if (startSpawnEnd > hideoutBaseX) startSpawnEnd = hideoutBaseX;
|
||||
|
||||
int baseSpawnStart = hideoutBaseX - (BANDIT_HIDEOUT_BASE_SPAWN_RANGE - 1);
|
||||
int baseSpawnEnd = hideoutBaseX;
|
||||
|
||||
int roll = random(0, 1);
|
||||
if (roll == 0) {
|
||||
spawn_hideout_bandit_in_range(startSpawnStart, startSpawnEnd);
|
||||
} else {
|
||||
spawn_hideout_bandit_in_range(baseSpawnStart, baseSpawnEnd);
|
||||
}
|
||||
}
|
||||
|
||||
void init_bandit_hideout_adventure() {
|
||||
reset_adventure_combat_state();
|
||||
hideoutPlayerX = 0;
|
||||
hideoutPlayerFacing = 1;
|
||||
hideoutBaseX = BANDIT_HIDEOUT_MAP_SIZE - 1;
|
||||
hideoutBanditsKilled = 0;
|
||||
|
||||
int barricadeBase = current_day * BANDIT_HIDEOUT_BARRICADE_HP_PER_DAY;
|
||||
if (barricadeBase < BANDIT_HIDEOUT_BARRICADE_HP_PER_DAY) barricadeBase = BANDIT_HIDEOUT_BARRICADE_HP_PER_DAY;
|
||||
if (barricadeBase > BANDIT_HIDEOUT_BARRICADE_HP_MAX) barricadeBase = BANDIT_HIDEOUT_BARRICADE_HP_MAX;
|
||||
hideoutBarricadeMax = barricadeBase;
|
||||
hideoutBarricadeHealth = barricadeBase;
|
||||
|
||||
build_hideout_terrain();
|
||||
clear_hideout_bandits();
|
||||
spawn_hideout_bandits_initial();
|
||||
}
|
||||
|
||||
void cleanup_bandit_hideout_adventure() {
|
||||
clear_hideout_bandits();
|
||||
reset_adventure_combat_state();
|
||||
p.destroy_all();
|
||||
}
|
||||
|
||||
void run_bandit_hideout_adventure() {
|
||||
// Stop main game sounds
|
||||
p.destroy_all();
|
||||
|
||||
init_bandit_hideout_adventure();
|
||||
|
||||
string[] intro;
|
||||
intro.insert_last("=== Bandit's Hideout ===");
|
||||
intro.insert_last("");
|
||||
intro.insert_last("You find a hidden bandit base deep in the forest.");
|
||||
intro.insert_last("The base lies far to the east, guarded by a barricade.");
|
||||
intro.insert_last("");
|
||||
intro.insert_last("Objective:");
|
||||
intro.insert_last(" - Reach the base and destroy the barricade");
|
||||
intro.insert_last("");
|
||||
intro.insert_last("Bandits will, of course, not take this lying down.");
|
||||
text_reader_lines(intro, "Adventure", true);
|
||||
|
||||
while (true) {
|
||||
wait(5);
|
||||
|
||||
if (key_pressed(KEY_ESCAPE)) {
|
||||
cleanup_bandit_hideout_adventure();
|
||||
speak_with_history("You flee the hideout.", true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Standard game keys
|
||||
check_quick_slot_keys();
|
||||
check_notification_keys();
|
||||
check_speech_history_keys();
|
||||
|
||||
if (key_pressed(KEY_H)) {
|
||||
speak_with_history(player_health + " health of " + max_health, true);
|
||||
}
|
||||
|
||||
if (key_pressed(KEY_X)) {
|
||||
int distanceToBase = hideoutBaseX - hideoutPlayerX;
|
||||
if (distanceToBase < 0) distanceToBase = 0;
|
||||
string terrain = get_hideout_terrain_at(hideoutPlayerX);
|
||||
speak_with_history("x " + hideoutPlayerX + ", terrain " + terrain + ". Base " + distanceToBase + " tiles east. Barricade " + hideoutBarricadeHealth + " of " + hideoutBarricadeMax + ".", true);
|
||||
}
|
||||
|
||||
handle_hideout_player_movement();
|
||||
handle_hideout_player_actions();
|
||||
update_hideout_search();
|
||||
|
||||
update_hideout_bandits();
|
||||
adventure_update_bow_shot(hideoutPlayerX);
|
||||
|
||||
if (hideoutBarricadeHealth <= 0) {
|
||||
cleanup_bandit_hideout_adventure();
|
||||
p.play_stationary("sounds/actions/break_snare.ogg", false);
|
||||
give_bandit_hideout_rewards();
|
||||
return;
|
||||
}
|
||||
|
||||
if (player_health <= 0) {
|
||||
cleanup_bandit_hideout_adventure();
|
||||
speak_with_history("The bandits cut you down.", true);
|
||||
return;
|
||||
}
|
||||
|
||||
p.update_listener_1d(hideoutPlayerX);
|
||||
}
|
||||
}
|
||||
|
||||
void handle_hideout_player_movement() {
|
||||
if (key_pressed(KEY_LEFT) && hideoutPlayerFacing != 0) {
|
||||
hideoutPlayerFacing = 0;
|
||||
speak_with_history("west", true);
|
||||
hideoutWalkTimer.restart();
|
||||
}
|
||||
if (key_pressed(KEY_RIGHT) && hideoutPlayerFacing != 1) {
|
||||
hideoutPlayerFacing = 1;
|
||||
speak_with_history("east", true);
|
||||
hideoutWalkTimer.restart();
|
||||
}
|
||||
|
||||
if (hideoutWalkTimer.elapsed > walk_speed) {
|
||||
if (key_down(KEY_LEFT) && hideoutPlayerX > 0) {
|
||||
hideoutPlayerFacing = 0;
|
||||
hideoutPlayerX--;
|
||||
hideoutWalkTimer.restart();
|
||||
if (player_health > 0) play_hideout_player_footstep();
|
||||
} else if (key_down(KEY_RIGHT) && hideoutPlayerX < hideoutBaseX) {
|
||||
hideoutPlayerFacing = 1;
|
||||
hideoutPlayerX++;
|
||||
hideoutWalkTimer.restart();
|
||||
if (player_health > 0) play_hideout_player_footstep();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void handle_hideout_player_actions() {
|
||||
bool ctrlDown = (key_down(KEY_LCTRL) || key_down(KEY_RCTRL));
|
||||
|
||||
// Bow draw detection
|
||||
if (bow_equipped) {
|
||||
if (ctrlDown && !bow_drawing) {
|
||||
if (get_personal_count(ITEM_ARROWS) > 0) {
|
||||
bow_drawing = true;
|
||||
bow_draw_timer.restart();
|
||||
p.play_stationary("sounds/weapons/bow_draw.ogg", false);
|
||||
} else {
|
||||
speak_ammo_blocked("No arrows.");
|
||||
}
|
||||
}
|
||||
|
||||
if (bow_drawing && !ctrlDown) {
|
||||
adventure_release_bow_attack(hideoutPlayerX, hideoutPlayerFacing, @bandit_hideout_ranged_attack);
|
||||
bow_drawing = false;
|
||||
}
|
||||
}
|
||||
if (!bow_equipped && bow_drawing) {
|
||||
bow_drawing = false;
|
||||
}
|
||||
|
||||
// Sling charge detection
|
||||
if (!bow_equipped && sling_equipped && ctrlDown && !sling_charging) {
|
||||
if (get_personal_count(ITEM_STONES) > 0) {
|
||||
sling_charging = true;
|
||||
sling_charge_timer.restart();
|
||||
sling_sound_handle = p.play_stationary("sounds/weapons/sling_swing.ogg", true);
|
||||
last_sling_stage = -1;
|
||||
} else {
|
||||
speak_ammo_blocked("No stones.");
|
||||
}
|
||||
}
|
||||
|
||||
if (sling_charging && ctrlDown) {
|
||||
update_sling_charge();
|
||||
}
|
||||
|
||||
if (sling_charging && !ctrlDown) {
|
||||
adventure_release_sling_attack(hideoutPlayerX, hideoutPlayerFacing, @bandit_hideout_ranged_attack);
|
||||
sling_charging = false;
|
||||
safe_destroy_sound(sling_sound_handle);
|
||||
}
|
||||
|
||||
if (!bow_equipped && !bow_drawing && !sling_equipped && !sling_charging) {
|
||||
if (fishing_pole_equipped) return;
|
||||
int weaponType = get_hideout_melee_weapon_type();
|
||||
if (weaponType == -1) return;
|
||||
|
||||
int attackCooldown = 1000;
|
||||
if (weaponType == ADVENTURE_WEAPON_SPEAR) attackCooldown = 800;
|
||||
if (weaponType == ADVENTURE_WEAPON_AXE) attackCooldown = 1600;
|
||||
|
||||
if (ctrlDown && hideoutAttackTimer.elapsed > attackCooldown) {
|
||||
hideoutAttackTimer.restart();
|
||||
play_hideout_melee_swing(weaponType);
|
||||
if (hideout_melee_hit(weaponType)) {
|
||||
play_hideout_melee_hit(weaponType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void update_hideout_search() {
|
||||
bool shiftDown = (key_down(KEY_LSHIFT) || key_down(KEY_RSHIFT));
|
||||
if (shiftDown) {
|
||||
if (key_pressed(KEY_COMMA) || key_pressed(KEY_PERIOD)) {
|
||||
hideoutSearching = false;
|
||||
hideoutSearchDelayTimer.restart();
|
||||
}
|
||||
}
|
||||
|
||||
bool searchKeyDown = shiftDown || key_down(KEY_SLASH) || key_down(KEY_Z);
|
||||
if (!searchKeyDown && !hideoutSearching) {
|
||||
hideoutSearchTimer.restart();
|
||||
}
|
||||
|
||||
int searchTime = apply_rune_gather_bonus(2000);
|
||||
if (searchKeyDown && hideoutSearchTimer.elapsed > searchTime && !hideoutSearching) {
|
||||
hideoutSearching = true;
|
||||
hideoutSearchDelayTimer.restart();
|
||||
}
|
||||
|
||||
if (hideoutSearching && hideoutSearchDelayTimer.elapsed >= 1000) {
|
||||
hideoutSearching = false;
|
||||
hideoutSearchTimer.restart();
|
||||
perform_hideout_search();
|
||||
}
|
||||
}
|
||||
|
||||
void perform_hideout_search() {
|
||||
if (random(1, 100) <= 10) {
|
||||
speak_with_history("Found nothing.", true);
|
||||
return;
|
||||
}
|
||||
|
||||
string terrain = get_hideout_terrain_at(hideoutPlayerX);
|
||||
if (terrain == "stone" || terrain == "gravel") {
|
||||
if (try_search_for_terrain(terrain)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
speak_with_history("Found nothing.", true);
|
||||
}
|
||||
|
||||
int get_hideout_melee_weapon_type() {
|
||||
if (spear_equipped) return ADVENTURE_WEAPON_SPEAR;
|
||||
if (axe_equipped) return ADVENTURE_WEAPON_AXE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void play_hideout_melee_swing(int weaponType) {
|
||||
if (weaponType == ADVENTURE_WEAPON_SPEAR) {
|
||||
p.play_stationary("sounds/weapons/spear_swing.ogg", false);
|
||||
} else if (weaponType == ADVENTURE_WEAPON_AXE) {
|
||||
p.play_stationary("sounds/weapons/axe_swing.ogg", false);
|
||||
}
|
||||
}
|
||||
|
||||
void play_hideout_melee_hit(int weaponType) {
|
||||
if (weaponType == ADVENTURE_WEAPON_SPEAR) {
|
||||
p.play_stationary("sounds/weapons/spear_hit.ogg", false);
|
||||
} else if (weaponType == ADVENTURE_WEAPON_AXE) {
|
||||
p.play_stationary("sounds/weapons/axe_hit.ogg", false);
|
||||
}
|
||||
}
|
||||
|
||||
bool hideout_melee_hit(int weaponType) {
|
||||
int range = (weaponType == ADVENTURE_WEAPON_SPEAR) ? 1 : 0;
|
||||
int damage = (weaponType == ADVENTURE_WEAPON_SPEAR) ? SPEAR_DAMAGE : AXE_DAMAGE;
|
||||
|
||||
for (int offset = -range; offset <= range; offset++) {
|
||||
int targetX = hideoutPlayerX + offset;
|
||||
if (damage_hideout_bandit_at(targetX, damage)) {
|
||||
play_creature_hit_sound("sounds/enemies/zombie_hit.ogg", hideoutPlayerX, targetX, BANDIT_SOUND_VOLUME_STEP);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (abs(hideoutPlayerX - hideoutBaseX) <= range) {
|
||||
if (apply_hideout_barricade_damage(damage)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool apply_hideout_barricade_damage(int damage) {
|
||||
if (damage <= 0) return false;
|
||||
if (hideoutBarricadeHealth <= 0) return false;
|
||||
hideoutBarricadeHealth -= damage;
|
||||
if (hideoutBarricadeHealth < 0) hideoutBarricadeHealth = 0;
|
||||
play_1d_with_volume_step("sounds/weapons/axe_hit.ogg", hideoutPlayerX, hideoutBaseX, false, BANDIT_SOUND_VOLUME_STEP);
|
||||
return true;
|
||||
}
|
||||
|
||||
int find_hideout_ranged_target(int playerX, int direction, int range) {
|
||||
for (int dist = 1; dist <= range; dist++) {
|
||||
int checkX = playerX + (dist * direction);
|
||||
if (checkX < 0 || checkX >= BANDIT_HIDEOUT_MAP_SIZE) break;
|
||||
|
||||
if (get_hideout_bandit_at(checkX) != null) {
|
||||
return checkX;
|
||||
}
|
||||
|
||||
if (hideoutBarricadeHealth > 0 && checkX == hideoutBaseX) {
|
||||
return checkX;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int bandit_hideout_ranged_attack(int playerX, int direction, int range, int weaponType, int damage) {
|
||||
int targetX = find_hideout_ranged_target(playerX, direction, range);
|
||||
if (targetX == -1) return -1;
|
||||
|
||||
if (targetX == hideoutBaseX) {
|
||||
apply_hideout_barricade_damage(damage);
|
||||
return targetX;
|
||||
}
|
||||
|
||||
if (damage_hideout_bandit_at(targetX, damage)) {
|
||||
return targetX;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool damage_hideout_bandit_at(int pos, int damage) {
|
||||
for (uint i = 0; i < hideoutBandits.length(); i++) {
|
||||
if (hideoutBandits[i].position == pos) {
|
||||
hideoutBandits[i].health -= damage;
|
||||
if (hideoutBandits[i].health <= 0) {
|
||||
if (hideoutBandits[i].soundHandle != -1) {
|
||||
p.destroy_sound(hideoutBandits[i].soundHandle);
|
||||
hideoutBandits[i].soundHandle = -1;
|
||||
}
|
||||
if (hideoutBandits[i].inWeaponRange) {
|
||||
play_weapon_range_sound("sounds/enemies/exit_range.ogg", hideoutBandits[i].position);
|
||||
}
|
||||
play_creature_death_sounds("sounds/enemies/enemy_falls.ogg", hideoutBandits[i].alertSound, hideoutPlayerX, pos, BANDIT_SOUND_VOLUME_STEP);
|
||||
hideoutBandits.remove_at(i);
|
||||
hideoutBanditsKilled++;
|
||||
respawn_hideout_bandit();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool try_hideout_bandit_attack_player(HideoutBandit@ bandit) {
|
||||
if (player_health <= 0) return false;
|
||||
if (abs(bandit.position - hideoutPlayerX) > 1) return false;
|
||||
if (bandit.attackTimer.elapsed < BANDIT_ATTACK_INTERVAL) return false;
|
||||
|
||||
bandit.attackTimer.restart();
|
||||
|
||||
if (bandit.weaponType == "spear") {
|
||||
play_creature_attack_sound("sounds/weapons/spear_swing.ogg", hideoutPlayerX, bandit.position, BANDIT_SOUND_VOLUME_STEP);
|
||||
} else {
|
||||
play_creature_attack_sound("sounds/weapons/axe_swing.ogg", hideoutPlayerX, bandit.position, BANDIT_SOUND_VOLUME_STEP);
|
||||
}
|
||||
|
||||
int damage = random(BANDIT_DAMAGE_MIN, BANDIT_DAMAGE_MAX);
|
||||
player_health -= damage;
|
||||
if (player_health < 0) player_health = 0;
|
||||
|
||||
if (bandit.weaponType == "spear") {
|
||||
play_creature_attack_sound("sounds/weapons/spear_hit.ogg", hideoutPlayerX, bandit.position, BANDIT_SOUND_VOLUME_STEP);
|
||||
} else {
|
||||
play_creature_attack_sound("sounds/weapons/axe_hit.ogg", hideoutPlayerX, bandit.position, BANDIT_SOUND_VOLUME_STEP);
|
||||
}
|
||||
play_player_damage_sound();
|
||||
return true;
|
||||
}
|
||||
|
||||
void update_hideout_bandit_audio(HideoutBandit@ bandit) {
|
||||
if (bandit.soundHandle != -1 && p.sound_is_active(bandit.soundHandle)) {
|
||||
p.update_sound_1d(bandit.soundHandle, bandit.position);
|
||||
return;
|
||||
}
|
||||
if (bandit.soundHandle != -1) {
|
||||
p.destroy_sound(bandit.soundHandle);
|
||||
}
|
||||
bandit.soundHandle = play_1d_with_volume_step(bandit.alertSound, hideoutPlayerX, bandit.position, true, BANDIT_SOUND_VOLUME_STEP);
|
||||
}
|
||||
|
||||
void update_hideout_bandit(HideoutBandit@ bandit) {
|
||||
update_weapon_range_audio_with_listener(hideoutPlayerX, bandit.position, bandit.inWeaponRange);
|
||||
|
||||
if (try_hideout_bandit_attack_player(bandit)) {
|
||||
update_hideout_bandit_audio(bandit);
|
||||
return;
|
||||
}
|
||||
|
||||
if (bandit.moveTimer.elapsed < bandit.moveInterval) {
|
||||
update_hideout_bandit_audio(bandit);
|
||||
return;
|
||||
}
|
||||
bandit.moveTimer.restart();
|
||||
|
||||
int direction = 0;
|
||||
if (hideoutPlayerX > bandit.position) direction = 1;
|
||||
else if (hideoutPlayerX < bandit.position) direction = -1;
|
||||
|
||||
if (direction != 0) {
|
||||
int targetX = bandit.position + direction;
|
||||
if (targetX >= 0 && targetX < BANDIT_HIDEOUT_MAP_SIZE) {
|
||||
if (get_hideout_bandit_at(targetX) == null) {
|
||||
bandit.position = targetX;
|
||||
play_hideout_positional_footstep(hideoutPlayerX, bandit.position, BANDIT_FOOTSTEP_MAX_DISTANCE, BANDIT_SOUND_VOLUME_STEP);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
update_hideout_bandit_audio(bandit);
|
||||
}
|
||||
|
||||
void update_hideout_bandits() {
|
||||
for (uint i = 0; i < hideoutBandits.length(); i++) {
|
||||
update_hideout_bandit(hideoutBandits[i]);
|
||||
}
|
||||
}
|
||||
|
||||
int add_hideout_storage_item(int itemType, int amount) {
|
||||
if (amount <= 0) return 0;
|
||||
int capacity = BASE_STORAGE_MAX - get_storage_count(itemType);
|
||||
if (capacity <= 0) return 0;
|
||||
int addedAmount = amount;
|
||||
if (addedAmount > capacity) addedAmount = capacity;
|
||||
if (addedAmount <= 0) return 0;
|
||||
|
||||
add_storage_count(itemType, addedAmount);
|
||||
|
||||
if (itemType == ITEM_SMALL_GAME) {
|
||||
for (int i = 0; i < addedAmount; i++) {
|
||||
storage_small_game_types.insert_last("small game");
|
||||
}
|
||||
}
|
||||
if (itemType == ITEM_FISH) {
|
||||
for (int i = 0; i < addedAmount; i++) {
|
||||
add_storage_fish_weight(get_default_fish_weight());
|
||||
}
|
||||
}
|
||||
|
||||
return addedAmount;
|
||||
}
|
||||
|
||||
void give_bandit_hideout_rewards() {
|
||||
speak_with_history("Victory!", true);
|
||||
|
||||
string[] rewards;
|
||||
rewards.insert_last("=== Victory Rewards ===");
|
||||
rewards.insert_last("");
|
||||
rewards.insert_last("Bandits defeated: " + hideoutBanditsKilled + ".");
|
||||
|
||||
if (world_altars.length() > 0) {
|
||||
double favorReward = BANDIT_HIDEOUT_BASE_FAVOR + (hideoutBanditsKilled * BANDIT_HIDEOUT_FAVOR_PER_KILL);
|
||||
if (favorReward > BANDIT_HIDEOUT_FAVOR_MAX) favorReward = BANDIT_HIDEOUT_FAVOR_MAX;
|
||||
if (favorReward < BANDIT_HIDEOUT_BASE_FAVOR) favorReward = BANDIT_HIDEOUT_BASE_FAVOR;
|
||||
favor += favorReward;
|
||||
rewards.insert_last("Favor awarded: " + format_favor(favorReward) + ".");
|
||||
} else {
|
||||
rewards.insert_last("Altar not built. No favor awarded.");
|
||||
}
|
||||
|
||||
rewards.insert_last("");
|
||||
|
||||
if (world_storages.length() == 0) {
|
||||
rewards.insert_last("Storage not built. No item rewards.");
|
||||
} else {
|
||||
rewards.insert_last("Storage rewards:");
|
||||
bool anyItems = false;
|
||||
for (int itemType = 0; itemType < ITEM_COUNT; itemType++) {
|
||||
int roll = random(0, 9);
|
||||
if (roll <= 0) continue;
|
||||
int addedAmount = add_hideout_storage_item(itemType, roll);
|
||||
if (addedAmount <= 0) continue;
|
||||
rewards.insert_last(get_item_display_name(itemType) + ": +" + addedAmount + ".");
|
||||
anyItems = true;
|
||||
}
|
||||
if (!anyItems) {
|
||||
rewards.insert_last("No items were recovered.");
|
||||
}
|
||||
}
|
||||
|
||||
text_reader_lines(rewards, "Bandit's Hideout", true);
|
||||
}
|
||||
Reference in New Issue
Block a user