CleverRaven / Cataclysm-DDA

Cataclysm - Dark Days Ahead. A turn-based survival game set in a post-apocalyptic world.
http://cataclysmdda.org
Other
10.63k stars 4.17k forks source link

Bandit NPC Engagement and Evasion Behaviors #72387

Closed LucioMagno closed 5 months ago

LucioMagno commented 7 months ago

Is your feature request related to a problem? Please describe.

In the current state of CDDA, Bandit NPCs exhibit overly simplistic and unrealistic behaviors when engaging the player or being engaged. Specifically, they neither actively pursue the player in a realistic manner nor exhibit self-preservation tactics such as retreating or seeking cover when under fire. This lack of dynamic behavior undermines the realism and challenge of encounters, making engagements feel predictable and less immersive.

Solution you would like.

To address these issues, we propose the development and implementation of advanced engagement and evasion behaviors for Bandit NPCs. These behaviors would include seeking cover, attempting to break line of sight with the player, and employing more strategic approaches when deciding whether to engage or flee.

-Enhance Bandit NPCs' awareness of their surroundings, enabling them to identify potential cover, escape routes, and advantageous positions for engaging the player.

Describe alternatives you have considered.

A simpler alternative could involve static scripts for Bandit behavior based on health thresholds or fixed AI patterns. However, this approach would not offer the depth of realism and adaptability proposed here.

Additional context

The goal of implementing these advanced behaviors is to significantly enhance the player's tactical considerations during encounters, making each engagement with Bandit NPCs a unique and challenging experience. This improvement aims to contribute to the overall depth and immersion of the game world.

Here is a heavily simplified mock-up code that could represent how this would be implemented:

class BanditAI : public monster { public: BanditAI() : monster() { // Initialize Bandit NPC properties hp = 50; aggression = 0; morale = 100; engagement_range = 10; vision_range = 15; }

void on_load_npc() override {
    // Load additional properties for the Bandit NPC
    weapon = item("glock_19");
    add_item(weapon);
}

void update_npc() override {
    // Update the Bandit NPC's behavior based on the current situation
    player *const target = dynamic_cast<player *>(get_target());

    if (target != nullptr) {
        int distance = rl_dist(pos(), target->pos());

        if (distance <= engagement_range && sees(*target)) {
            if (is_fleeing) {
                // Continue fleeing
                flee();
            } else if (is_taking_cover) {
                // Continue taking cover
                take_cover();
            } else {
                // Engage the player
                engage_player();
            }
        } else {
            // Break engagement and decide on the next action
            disengage();

            if (should_flee()) {
                flee();
            } else if (should_take_cover()) {
                take_cover();
            } else {
                // Wander or patrol
                wander();
            }
        }
    }
}

private: item weapon; bool is_fleeing = false; bool is_taking_cover = false; int engagement_range; int vision_range;

bool should_flee() {
    // Determine if the Bandit NPC should flee based on health, morale, and other factors
    return hp < 20 || morale < 30;
}

bool should_take_cover() {
    // Determine if the Bandit NPC should take cover based on the environment and threat level
    return get_perceived_danger() > 50 && find_cover_spot() != tripoint_zero;
}

void engage_player() {
    // Engage the player using the equipped weapon
    melee_attack(*get_target(), false);
}

void disengage() {
    // Break engagement and reset flags
    is_fleeing = false;
    is_taking_cover = false;
}

void flee() {
    // Attempt to flee from the player
    is_fleeing = true;
    const tripoint escape_point = find_escape_route();
    move_to(escape_point);
}

void take_cover() {
    // Attempt to take cover from the player
    is_taking_cover = true;
    const tripoint cover_point = find_cover_spot();
    move_to(cover_point);
}

void wander() {
    // Wander or patrol the area
    const tripoint wander_point = find_wander_point();
    move_to(wander_point);
}

tripoint find_escape_route() {
    // Find a suitable escape route using pathfinding algorithms
    // Implement your pathfinding logic here
    return tripoint_zero;
}

tripoint find_cover_spot() {
    // Find a suitable cover spot using environmental analysis
    // Implement your cover spot detection logic here
    return tripoint_zero;
}

tripoint find_wander_point() {
    // Find a suitable wander point using predefined patrol routes or random selection
    // Implement your wander point selection logic here
    return tripoint_zero;
}

int get_perceived_danger() {
    // Calculate the perceived danger level based on various factors
    // Implement your danger assessment logic here
    return 0;
}

};

github-actions[bot] commented 6 months ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. Please do not bump or comment on this issue unless you are actively working on it. Stale issues, and stale issues that are closed are still considered.