190 lines
6.2 KiB
Plaintext
190 lines
6.2 KiB
Plaintext
void perform_attack(int current_x) {
|
|
if (sling_equipped) {
|
|
perform_sling_attack(current_x);
|
|
} else if (spear_equipped) {
|
|
perform_spear_attack(current_x);
|
|
} else if (axe_equipped) {
|
|
perform_axe_attack(current_x);
|
|
} else {
|
|
// Optional: Punch logic
|
|
// p.play_stationary("sounds/weapons/fist_swing.ogg", false);
|
|
}
|
|
}
|
|
|
|
int attack_enemy_ranged(int start_x, int end_x, int damage) {
|
|
for (int check_x = start_x; check_x <= end_x; check_x++) {
|
|
// Check for bandits first (priority during daytime)
|
|
if (damage_bandit_at(check_x, damage)) {
|
|
return check_x;
|
|
}
|
|
// Then check zombies
|
|
if (damage_zombie_at(check_x, damage)) {
|
|
return check_x;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
bool attack_enemy(int target_x, int damage) {
|
|
// Check for bandits first
|
|
if (damage_bandit_at(target_x, damage)) {
|
|
return true;
|
|
}
|
|
// Then check zombies
|
|
return damage_zombie_at(target_x, damage);
|
|
}
|
|
|
|
void perform_spear_attack(int current_x) {
|
|
p.play_stationary("sounds/weapons/spear_swing.ogg", false);
|
|
|
|
int hit_pos = attack_enemy_ranged(current_x - 1, current_x + 1, SPEAR_DAMAGE);
|
|
if (hit_pos != -1) {
|
|
p.play_stationary("sounds/weapons/spear_hit.ogg", false);
|
|
// Play hit sound based on enemy type (both use same hit sound for now)
|
|
if (get_bandit_at(hit_pos) != null) {
|
|
play_1d_with_volume_step("sounds/enemies/zombie_hit.ogg", x, hit_pos, false, BANDIT_SOUND_VOLUME_STEP);
|
|
} else {
|
|
play_1d_with_volume_step("sounds/enemies/zombie_hit.ogg", x, hit_pos, false, ZOMBIE_SOUND_VOLUME_STEP);
|
|
}
|
|
return;
|
|
}
|
|
|
|
// Hit tree with spear (sound only, 0 damage)
|
|
hit_tree_with_spear(current_x);
|
|
}
|
|
|
|
void perform_axe_attack(int current_x) {
|
|
p.play_stationary("sounds/weapons/axe_swing.ogg", false);
|
|
|
|
if (attack_enemy(current_x, AXE_DAMAGE)) {
|
|
p.play_stationary("sounds/weapons/axe_hit.ogg", false);
|
|
// Play hit sound based on enemy type
|
|
if (get_bandit_at(current_x) != null) {
|
|
play_1d_with_volume_step("sounds/enemies/zombie_hit.ogg", x, current_x, false, BANDIT_SOUND_VOLUME_STEP);
|
|
} else {
|
|
play_1d_with_volume_step("sounds/enemies/zombie_hit.ogg", x, current_x, false, ZOMBIE_SOUND_VOLUME_STEP);
|
|
}
|
|
return;
|
|
}
|
|
|
|
// Axe Attack Logic
|
|
// Range: current_x (0 distance)
|
|
// Damage: 4
|
|
// Target: Trees
|
|
damage_tree(current_x, 4);
|
|
}
|
|
|
|
void perform_sling_attack(int current_x) {
|
|
// Sling uses charge/release mechanism, not direct attack
|
|
// This function is called from main loop when sling is released
|
|
release_sling_attack(current_x);
|
|
}
|
|
|
|
void hit_tree_with_spear(int target_x) {
|
|
Tree@ target = get_tree_at(target_x);
|
|
if (@target != null && !target.is_chopped) {
|
|
p.play_stationary("sounds/weapons/spear_hit.ogg", false);
|
|
}
|
|
}
|
|
|
|
void update_sling_charge() {
|
|
int elapsed = sling_charge_timer.elapsed;
|
|
int cycle_time = 1500; // 1.5 seconds
|
|
int stage_duration = 500; // 0.5 seconds per stage
|
|
|
|
// Loop the charge cycle
|
|
int time_in_cycle = elapsed % cycle_time;
|
|
|
|
// Determine stage: 0=low, 1=in-range, 2=high
|
|
int current_stage = time_in_cycle / stage_duration;
|
|
|
|
// Play stage indicator sounds (only once per stage change)
|
|
if (current_stage != last_sling_stage) {
|
|
if (current_stage == 1) {
|
|
// Entering in-range window
|
|
p.play_stationary("sounds/weapons/sling_low_range.ogg", false);
|
|
} else if (current_stage == 2) {
|
|
// Entering too-high window
|
|
p.play_stationary("sounds/weapons/sling_high_range.ogg", false);
|
|
}
|
|
last_sling_stage = current_stage;
|
|
}
|
|
}
|
|
|
|
void release_sling_attack(int player_x) {
|
|
// Consume stone
|
|
inv_stones--;
|
|
|
|
int elapsed = sling_charge_timer.elapsed;
|
|
int cycle_time = 1500;
|
|
int time_in_cycle = elapsed % cycle_time;
|
|
int stage = time_in_cycle / 500; // 0=low, 1=in-range, 2=high
|
|
|
|
// Only hit if released during in-range window (stage 1)
|
|
if (stage != 1) {
|
|
screen_reader_speak("Stone missed.", true);
|
|
return;
|
|
}
|
|
|
|
// Find target in facing direction
|
|
int search_direction = (facing == 1) ? 1 : -1;
|
|
int target_x = -1;
|
|
bool hit_bandit = false;
|
|
|
|
// Priority: Find nearest enemy (bandit or zombie) first
|
|
for (int dist = 1; dist <= SLING_RANGE; dist++) {
|
|
int check_x = player_x + (dist * search_direction);
|
|
if (check_x < 0 || check_x >= MAP_SIZE) break;
|
|
|
|
// Check for bandit first
|
|
Bandit@ bandit = get_bandit_at(check_x);
|
|
if (bandit != null) {
|
|
target_x = check_x;
|
|
hit_bandit = true;
|
|
break;
|
|
}
|
|
|
|
// Then check for zombie
|
|
Zombie@ zombie = get_zombie_at(check_x);
|
|
if (zombie != null) {
|
|
target_x = check_x;
|
|
hit_bandit = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// If no enemy found, check for trees (but don't damage them)
|
|
if (target_x == -1) {
|
|
for (int dist = 1; dist <= SLING_RANGE; dist++) {
|
|
int check_x = player_x + (dist * search_direction);
|
|
if (check_x < 0 || check_x >= MAP_SIZE) break;
|
|
Tree@ tree = get_tree_at(check_x);
|
|
if (tree != null && !tree.is_chopped) {
|
|
// Stone hits tree but doesn't damage it
|
|
p.play_1d("sounds/weapons/sling_hit.ogg", player_x, check_x, false);
|
|
screen_reader_speak("Stone hit tree at " + check_x + ".", true);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
// No target found
|
|
if (target_x == -1) {
|
|
screen_reader_speak("Stone missed.", true);
|
|
return;
|
|
}
|
|
|
|
int damage = random(SLING_DAMAGE_MIN, SLING_DAMAGE_MAX);
|
|
|
|
// Damage the correct enemy type
|
|
if (hit_bandit) {
|
|
damage_bandit_at(target_x, damage);
|
|
p.play_1d("sounds/weapons/sling_hit.ogg", player_x, target_x, false);
|
|
play_1d_with_volume_step("sounds/enemies/zombie_hit.ogg", player_x, target_x, false, BANDIT_SOUND_VOLUME_STEP);
|
|
} else {
|
|
damage_zombie_at(target_x, damage);
|
|
p.play_1d("sounds/weapons/sling_hit.ogg", player_x, target_x, false);
|
|
play_1d_with_volume_step("sounds/enemies/zombie_hit.ogg", player_x, target_x, false, ZOMBIE_SOUND_VOLUME_STEP);
|
|
}
|
|
}
|