CleverRaven / CleverRaven/Cataclysm-DDA
Early steps for better monster factional aggression
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 13.2k
- Forks
- 4.6k
- Avg merge
- 2d 1h
- Merged PRs (30d)
- 205
Description
Is your feature request related to a problem? Please describe.
There are many outstanding issues related to monsters becoming aggressive to the player for incorrect triggers (#59495 recently eg), I will try to find and link some here for examples.
Solution you would like.
Eventually we do need a full factional aggression system and monster-related AI attributes to determine how smart they are at identifying that the player is not on the same team as the bandits. This post provides a possible easily-implemented framework that could get this started, and solve a majority of monster aggro problems quickly.
- Ensure all aggression triggers track the source of the aggression trigger. This is already done for HURT/FRIEND_ATTACKED/FRIEND_DIED. The rest are in monmove.cpp and probably need it added.
- Add a new boolean variable, "aggro_characters". For start-hostile monsters this sets to true, but monsters that start as neutral or friendly default it to false.
- When an aggression source increases a monster's aggro, check to see if the source of anger was a monster or a character. If it was a monster, behave normally. If it was a character, do the following steps:
- Perform a random check to see if aggro_characters should flip to true. The chance of this happening is influenced by the monster's current anger level and the severity of the trigger. At high levels of anger the chance should be 100%. For a first pass, we could just always have the trigger flip.
- (Optional: If aggro_characters is true?) increase anger by whatever it would normally have increased by. See below for details on optional bit
- Set a time variable, "last_aggro_character", to the current time.
- Every ten minutes, check if
last_aggro_character> 1 hour. If so, set aggro_character to false. Later we can make this an attribute of the monster, so some monsters stay angry longer.
If aggro_characters is false, the monster will not attack characters (player and NPCs) regardless of anger level.
Later steps:
- We should have ways to propagate the aggro_characters flag to nearby friendly faction monsters, so if you make a turret angry, it will signal nearby turrets to attack you. This should be added pretty early. I would suggest that at first this happen close to instantly, within radius of like 20 sq. Later we could add propagation time and range, so some creatures take longer to signal their compatriots to come to their aid, or can't spread the signal as far out, and possibly add monster attributes to determine if they need to be able to see or hear to help their friends. A blinded, deaf monster might not be able to recognize that its friend has aggro'd against you. We can probably avoid doing LoS calculations here...?
- In the future instead of aggro_characters we should use this same framework, but have a dynamically generated array of factions that the monster can be aggro to, so that anger towards the player faction doesn't make a turret angry to the free merchants for example.
- As noted above we could use some AI attributes on the monster here, such as time to reset aggro, and some details around aggro likelihood in the random chance bit - some monsters like exodii quads should be less likely to turn on characters than, say, wild animals, which should go aggro pretty readily.
- when we do introduce factions to this we'll need to have some smart ways to determine what factions the npc is smart enough to distinguish. An exodii quad can tell you apart from a bandit, but a wild dog cannot.
- Individual AI attributes should have a role in maybe determining if "friendly fire" type aggro triggers that don't trigger aggro_character should still increase anger, or if they should only increase it by a small amount. This will change the balance of anger triggers, so it should be done carefully: for example, this would mean that if you're the only one attacking an exodii quad, it only increases anger if it decides you're doing it on purpose, which is a random flag. That could mean it lets you get several shots off before it gets annoyed. We might want some smarter checks here, like having the monster check if there's anything else going on before it gets mad at you.
Thoughts on why this should work:
- by making this a boolean tied to anger, we don't have to track anger for each faction as a separate int which is nice. Also it models the monsters becoming enraged from other sources and being more likely to turn.
- By making the chance to turn aggro random, it becomes much harder to metagame. For example you can try to kill an exodii quad by luring zombies to it, which will not draw aggro, but if you try to weaken it so that they have a better chance, it is not really possible to predict when your attacks may be recognized as "hey that's not friendly fire", so there will always be risk.
Describe alternatives you have considered.
We could track anger separately per faction but I think that's harder, and doesn't do significantly better.
Additional context
@Venera3 seems to be taking a look at this after our discord discussion.
While doing this we may also want to ensure that self-origin (maybe also friendly faction origin) attacks do not increase anger, since that becomes easier when we're tracking attack origin.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading monmove.cpp and the existing HURT, FRIEND_ATTACKED, and FRIEND_DIED aggression triggers to see how trigger sources are currently tracked. The issue describes a broad factional-aggression framework with several optional and future steps, so establish a narrowly scoped first step and its tests before implementation. Done is not defined for the full proposal.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- ai, game-dev
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100