Huge bug in how "hearing" is handled

I’ve created a feedback for this:

The problem is even bigger than I initially thought.
As some of you may know, there are 3 states for an “actor” on the tactical view:

  • hidden
  • located: the enemy knows there is someone there - it appears as a ping
  • revealed: at least one enemy sees you (with line of sight and within perception range - affected by stealth)

The problem lies in how the code handles the “located” status. You become located if:

  • you shoot or bash with a “non silent” weapon (BIG PROBLEM - and I’ll explain why)
  • you suffer a DoT (SAME BIG PROBLEM)
  • you open a door or break a window (SAME BIG PROBLEM)
  • you are within 5 tiles of an enemy (there’s a mutation or equipment that makes it bigger)
    • the problem with this one is that a dead enemy still hears you :wink:

So, now with the BIG PROBLEM. Nowhere in the code have I found a place where the “located” state is reset. Meaning that once you are located, the enemy knows where you are all the time and sees you moving (as a ping but still he knows where you are).

Chirons target based on the “located” state. Which means that once you are located, the ChIrons will be relentless to throw all they have at you (if alerted). Even if no one sees you, they hear you, even on the other side of the map, they still hear you. That’s a big part of why the Chirons are so deadly and hated … they cheat (not willingly - granted - but they do).

I’ve tried resetting the state in the same place that “revealed” is “reset” (in the onMoved method) and miracle, Chirons sent me stuff only if I had an enemy the saw me or if I was in hearing range.

So why is this reset missing ? The reason is probably that when you do a noise (shoot, bash, break glass, open door, suffer), it sets your “located” state but once you move it would disappear. Therefore you would just have to move after shooting and they wouldn’t know where you are.

That’s because they set the “located” flag on the “actor”, rather than creating a “virtual” actor that would show the location the sound came from without following all your movements.


Ways to fix it ?

  1. Sounds (shoot, bash, break glass, open door, suffer) shouldn’t set the “located” state on the actor himself but on a “virtual” actor that doesn’t move and gets revealed like dead tritons.
  2. Reset the “located” known state when moving like it is for “revealed”.
  3. Dead enemies shouldn’t be able to hear us.

If you cap stealth at 75%, reveal of those “virtual” actors can be done without bumping into the cell.


The same goes the other way. It is shame that we hear the enemy all the time after initial ‘discovery’.

‘Revealed’ and ‘located’ should be checked each time when enemy is moving to next tile (maybe also in other situations). Not just in the moment enemy starts to move. Because when we see or hear enemy one time during his turn we will see him till the end of the turn, no matter the line of sight or perception range. That is strange and way different than original X-COM. I would say it is immersion breaking and this is one of the reasons why there is no TERROR feeling in this game.

First of all I have to say I admire your coding skills and dedication, @pantolomin!
It is good you’ve located the reason of Chiron’s unnatural precision and caught the AI cheating!

However I am not sure if straightforward fixing this “located” flag behaivour is possible. Wouldn’t it become too easy for players to exploit it? To send the enemy team catching ghosts while our troops go for mission goal having zero opposition? Will the AI be able to remember the position of our soldiers and predict their movement without the “located” flag on them?
You know there is reason why AI is cheating in so many games… (sigh)

Upvoted! :smiley: :+1:

1 Like

How about you reset “located” at the start of the turn? It’ll still let bad guys figure out where you are when you do something noisy but not have radar sense indefinitely?

Anyways, yes those bloody living artillery emplacements…

Yes, it works both ways and I have always found the fact of being able to follow their moves strange.

1 Like

Yes, it is not a straightforward change because the AI will have to be smarter to avoid chasing ghosts and not waste it’s artillery on nothing.

1 Like

I guess an other factor is that they didn’t want the whole map to be covered with “blips”.
But this one can be solved by giving them a life-time of 1 turn. They get removed once you start your new turn.

1 Like

How you tested that? Pre last updates I used often exploit of not being located even with Shoot against Chirons was almost prove this was wrong. I can’t say with last patch. If it’s been removed I’m 100% on adding it back even if it makes silent a pointless feature for weapons for now.

Do you ever try not move against Chiron? There was three main tools but since last patch I’m not sure:

  • Not move and at next turn Chiron don’t see you, and you can shoot.
  • Cover from top and from heights but it’s complicate, I won’t enter in details, it’s still powerful tool.
  • More targets located will be the Chiron target, sometimes there’s perhaps a bit of exploit behind that. In that case top cover that can’t be reach with splash are ignored, but it seems heights doesn’t remove the targets count.

I checked the code after the last patch, but haven’t tested much in game with the last patch.
I didn’t have lots of time to play lately and spent most of my free time reading the inner workings.

I know that when the Chiron gets alerted, there is no way to escape its shots even with no one around.
I need to test with crossbows to see if it changes anything.

Making a “mod” to change all this is a daunting task.

Did you checked Chiron code?

There’s a lot of code and I haven’t looked into the AI. I don’t have that much free time :wink:.

It’s more about identifying what’s specific to Chiron then find all places where it is used to generate specific AI behavior, you are right it’s about AI.

EDIT: I think it should be related to throw attacks, the problem looks different with crabs because of the very different ranges. But I suspect it’s the point of trigger.

Why not start simple? You already tried resetting it every step, I suggested doing it at the beginning of the turn to get some (unrealistic) tracking for the enemy/your turn.

Resetting it at every step is very easy (1 line).
Making dead actors not hear is very easy (4 lines because of formatting but less code).
The part that builds a “virtual” actor is difficult. Making sure it doesn’t break anything is difficult. Cleaning the next turn I don’t know (haven’t checked where the code for “start of turn” is).

I might as well take an other approach and patch methods that check “located” actors. I’ll see if I can put some time on it this week-end as it’s an interesting problem.

So, basically, modding the perception values (which should be for eyes only, not sounds) would be rather useless until this “sound thing” works better?
Good catch btw.

I think that leaving that virtual actor idea for an another date would allow a quick fix that’s a whole lot better than what we’ve got now. I can’t help you with locating the start-of-turn but I’d imagine it’s a 1 line fix as well once you find the right place.

Well maybe I could help, I can do C and C++ but diving into the code blindly is a “slightly” daunting task. How do you even extract the code?

I’m not the right person to talk about these things but programs like JustDecomiler or Dnspy should be what you’re searching for. I’m a noob but I can tell you that through one of them you can see a lot of things.

ps JustDecomiler was suggested to me by Pantolomin