Aller au contenu

Photo

Bizarre behaviour when activating friendly creatures


  • Veuillez vous connecter pour répondre
47 réponses à ce sujet

#1
FergusM

FergusM
  • Members
  • 460 messages
I have a team of _Friendly creatures set as inactive in my area; when a certain event is triggered they appear with UT_TeamAppears(). However, they are acting very oddly. They will attack enemies, but they will not (usually) move from the spot where they first appeared. Sometimes they will chase after an enemy, but often they will just stand in place, switching to ranged attacks if possible or just sitting there (clearly in combat) if they don't. I also witnessed one of them chase after an enemy and begin fighting him, only to run back to his original location and briefly become untargetable (that is, the blue circle around his feet disappeared).

This issue does not occur when I use UT_TeamAppears() to wake up a team of hostile creatures; they act perfectly normally.

Any ideas on how to get them moving?

#2
Craig Graff

Craig Graff
  • Members
  • 608 messages
How far away from the player are you spawning the friendlies?

#3
FergusM

FergusM
  • Members
  • 460 messages
Not very far. Most of the battle (except a few archers maybe) is visible on screen at the same time, top down.

#4
FergusM

FergusM
  • Members
  • 460 messages
On further investigation, this behaviour occurs even if the friendlies are just set to active in the area editor, without using scripts to activate them.



Sometimes they do run and attack enemies, but inevitably they will just stop at some point in the fight and just sit in place bobbing around. Even the ones which use ranged attacks will eventually stop.



Some more information. The hostiles in this encounter are all on the same team. Basically, the friendlies are activated next to one batch of enemies (who are activated in a similar manner at the same tim), and then there is a short distance to the other clump of enemies (who are already active but only turn hostile when the script triggers). The friendlies will usually keep fighting until the first group is defeated, but this often involves them just standing on the spot. They will fight enemies from the second group, but as I've mentioned they inevitably just stop at some point, even if an enemy is right next to them. I tried using UT_CombatStart between a random friendly and a random enemy from the second group, but that didn't seem to help (I did not investigate this very thoroughly, however.



I also just tried removing the group of enemies that spawn in (leaving only the second clump), and the friendlies do correctly move to attack them, both moving in to melee combat and repositioning for ranged combat when appropriate. They do seem to favour ranged combat pretty strongly though.

#5
Magic

Magic
  • Members
  • 187 messages
How many creatures are participating in the combat at the same time? Is this a performance problem maybe? I'm having performance issues at around 16 combatants already (events triggering seconds later).

#6
FergusM

FergusM
  • Members
  • 460 messages
Yeah, there are about 20 creatures involved in the combat, I'm starting to think something like that may be the problem. But a lot of the fights towards the end of the singleplayer campaign especially have way, way more enemies than that.

I'm thinking maybe it's something like they have too many targets to fit in their threat table (hostiles rarely have to fight more than 4 player characters + ~6ish allies). Or, since on reflection that actually sounds a little unlikely, perhaps just some general threat table bug. I might try putting half the enemies on a separate team, clearing the friendlies' threat table when that team dies and then manually starting combat with the other team.

Modifié par FergusM, 20 février 2010 - 08:15 .


#7
Challseus

Challseus
  • Members
  • 1 032 messages
What are the classes of these friendly creatures, and more important, what AI packages are you using? The game should at least be able to handle 24 combatants, according to this line in rules_core.nss:

// -----------------------------------------------------------------------------
// Max creatures in combat at the same time we can support.
// -----------------------------------------------------------------------------
const int MAX_CREATURES_IN_COMBAT = 24;

Also, I currently have a huge fight that occurs between about 10 hostiles (half using ranged attacks, melee up close), 12 friendlys (half using ranged attacks, melee up close), and 2 party members (melee). The only time I run into the problem you are suggesting is when the targets get too far away. I alleviated the issue by just re-arranging people pre-fight, so they sort of stay within a decent boundary for the AI to handle.

Modifié par Challseus, 20 février 2010 - 10:59 .


#8
FergusM

FergusM
  • Members
  • 460 messages
They're all pretty much duplicates of creatures from single player, so the AIPs are just standard ones. Humanoid Sword and Shielf this, Darkspawn Archer that, etc.

I'll look into repositioning (perhaps there are some line of sight issues?) or changing their AI.

Fun fact, I have exactly 24 creatures including party members.

EDIT: I tried giving them all melee weapons and melee packages, no change. I also tried moving all the combatants so they were all very close to each other, but still towards the end of the fight I'd have 3 or 4 friendlies with melee weapons just sitting in place (in combat), not attacking the hostiles who were fighting me only metres away.

If there aren't any suggestions, my next step will probably be to write a script to manually set their threat halfway through the fight.

Modifié par FergusM, 20 février 2010 - 11:31 .


#9
Magic

Magic
  • Members
  • 187 messages
I just encountered the problem as well at the end of the fight where only 1 enemy was left. Before the game crashed, I could find out that the last hostile creature is at 0 threat, therefore will not be returned by GetThreatEnemy(oCreature, 0) in AI_Threat_UpdateCreatureThreat() of ai_threat_h.nss. => No new target will be selected, NPC is standing around taunting. If all remaining hostiles are at 0 threat, there's no sanity check to reacquire a target unless the hostile actually generates threat.

Now finding a solution in this huge script system will be more difficult, I guess ... Doing some more testing now.

#10
Magic

Magic
  • Members
  • 187 messages
If anyone is interested to see the problem, please add



int nThreatCount = GetThreatTableSize(OBJECT_SELF);

int nPerceivedCount = GetArraySize(GetPerceivedCreatureList(OBJECT_SELF,TRUE));

string sName = IntToString(nThreatCount)+"/"+IntToString(nPerceivedCount);

SetName(OBJECT_SELF,sName);



at the beginning of main() of rules_core.nss. Not all perceived hostiles are on the threat table, and if those, who are, are killed fast enough so the table is empty, observed situation will happen. The NPC will not engage in combat until threatened again.

#11
Magic

Magic
  • Members
  • 187 messages
Ok, several things. The threat table size is limited to 5 for me - "exceptions" of 6 are possible. Not sure if that's the same for everyone.

object[] oEnemies = GetNearestObjectByHostility(OBJECT_SELF,TRUE,OBJECT_TYPE_CREATURE,5,TRUE,TRUE);
int nEnemyCount = GetArraySize(oEnemies);
int i;
for (i = 0; i<nEnemyCount; i++) {
    if (GetThreatValueByObjectID(OBJECT_SELF,oEnemies[i])==0.0) {
        AI_Threat_UpdateEnemyAppeared(OBJECT_SELF,oEnemies[i]);
    }
}

This code will update the threat table for the nearest 5 enemies. A place to put would be rules_core.nss, line 796, right before the call of AI_DetermineCombatRound() for EVENT_TYPE_COMMAND_COMPLETE. I chose this place because people who don't want to modify core scripts have the option of using custom AI. Event redirection would work, too, of course. The code is a compromise for several reasons. An official update would be best.

By the way, there's a small bug in the called function. In line 351 of ai_threat_h.nss the chest item is compared against weapon types. The impact is minor, but it should read:

    if( GetGameDifficulty() < 3 && // extra threat only for difficulty lower than nightmare
        nWeaponItemType != BASE_ITEM_TYPE_LONGBOW && nWeaponItemType != BASE_ITEM_TYPE_SHORTBOW && nWeaponItemType != 21
        && nWeaponItemType != BASE_ITEM_TYPE_STAFF)
        fThreatChange += AI_THREAT_PERCEIVED_WEAPON_MELEE;

#12
Craig Graff

Craig Graff
  • Members
  • 608 messages
One thing to keep in mind for those larger combats in the main campaign is that they generally have most creatures with lightweight AI. (Local variable AI_LIGHT_ACTIVE set to 1.)

#13
FergusM

FergusM
  • Members
  • 460 messages
Your code works great, Magic. Cheers!

#14
Magic

Magic
  • Members
  • 187 messages
Small update! Recalculating threat on every combat action was overkill performance-wise. A better method is doing the update on EVENT_TYPE_PERCEPTION_DISAPPEAR. This event can also be handled in a custom event script without modifying the core, yay. A line was added to reduce unnecessary updates further.

// If a hostile creature disappeared, update the threat table with the remaining perceived enemies
if (IsObjectHostile(OBJECT_SELF,GetEventObject(ev,0))) {
    int i;                                          
    object[] oEnemies = GetNearestObjectByHostility(OBJECT_SELF,TRUE,OBJECT_TYPE_CREATURE,AI_THREAT_SIZE,TRUE,TRUE);
    int nEnemyCount = GetArraySize(oEnemies);                      
    if (GetThreatTableSize(OBJECT_SELF)<nEnemyCount) {
        for (i = 0; i<nEnemyCount; i++) {
            if (GetThreatValueByObjectID(OBJECT_SELF,oEnemies[i])==0.0) {
                AI_Threat_UpdateEnemyAppeared(OBJECT_SELF,oEnemies[i]);
            }
        }
    }
}

Modifié par Magic, 21 février 2010 - 10:52 .


#15
FergusM

FergusM
  • Members
  • 460 messages
Even better.

#16
Challseus

Challseus
  • Members
  • 1 032 messages

Craig Graff wrote...

One thing to keep in mind for those larger combats in the main campaign is that they generally have most creatures with lightweight AI. (Local variable AI_LIGHT_ACTIVE set to 1.)


What's the drawback to this, Craig? Will they still run the AI from their tactics tables?

@ Magic

This is good code, man. I'll be integrating it into my systems later this afternoon. Thanks!

#17
FergusM

FergusM
  • Members
  • 460 messages
Actually, with the second code snippet, I'm still having this issue occur. Only about half as many creatures are effected but it's definitely happening. I'm not sure what the issue could be.

EDIT: I've decided to use your first bit of code. To alleviate potential performance issues, I removed the loop and simply have it update one target with more threat. A bit of a dumber model perhaps, but it's enough to get them back into combat.

Modifié par FergusM, 21 février 2010 - 09:01 .


#18
Magic

Magic
  • Members
  • 187 messages
Interesting. Does this happen when many creatures "disappear" at the same time? I'm using the disappear version, so maybe I'll encounter the same sometime. It's hard to test else. Your workaround does the job, you're right. Before I found the limit AI_THREAT_SIZE, I was thinking the same, actually. The NPC stays in combat so it can gain threat from other sources. That's the more important part.

It's still a workaround after all. The best place would probably be whenever a creature leaves the threat table and makes room for another. But that's deep in the core scripts. Maybe Craig can give us an official version in the future. :)

Modifié par Magic, 21 février 2010 - 10:05 .


#19
FergusM

FergusM
  • Members
  • 460 messages
It's hard for me to say exactly when it occurs. I thought it might be related to line of sight (eg what the creature can see when his current targets disappear) but after some further testing there didn't seem to be much correlation. I don't think it's to do with a lot dying at once, as you'll have a situation when (as far as I remember) 4 friendlies are attacking 1 hostile, and then 2 of them move on to new targets while 2 of them don't do anything. However, it's difficult to say for certain as the combat tends to be pretty hectic with this many creatures and it's hardly a controlled experiment. :)

#20
Challseus

Challseus
  • Members
  • 1 032 messages

Magic wrote...

Small update! Recalculating threat on every combat action was overkill performance-wise. A better method is doing the update on EVENT_TYPE_PERCEPTION_DISAPPEAR. This event can also be handled in a custom event script without modifying the core, yay. A line was added to reduce unnecessary updates further.

// If a hostile creature disappeared, update the threat table with the remaining perceived enemies
if (IsObjectHostile(OBJECT_SELF,GetEventObject(ev,0))) {
    int i;                                          
    object[] oEnemies = GetNearestObjectByHostility(OBJECT_SELF,TRUE,OBJECT_TYPE_CREATURE,AI_THREAT_SIZE,TRUE,TRUE);
    int nEnemyCount = GetArraySize(oEnemies);                      
    if (GetThreatTableSize(OBJECT_SELF)<nEnemyCount) {
        for (i = 0; i<nEnemyCount; i++) {
            if (GetThreatValueByObjectID(OBJECT_SELF,oEnemies[i])==0.0) {
                AI_Threat_UpdateEnemyAppeared(OBJECT_SELF,oEnemies[i]);
            }
        }
    }
}


Just wanted to confirm that on my end, this seems to have cleared up the issue which I initally attributed to the enemies being too far away. Once I added this in, all friendly's tracked down all hostiles, no matter how far away they were.

I'll let you know if I have any issues with it going further.

#21
Magic

Magic
  • Members
  • 187 messages
Thanks for the feedback. There's little I can do at the moment. It's working properly for me now. Please keep in mind that the threat updates depend on event progression (while the perception list does not). I'm avoiding many creatures at the same time right now (unfortunately). Otherwise, it's hard to tell when what exactly happens.

#22
RecklezzRogue

RecklezzRogue
  • Members
  • 193 messages
see next post...

Modifié par RecklezzRogue, 12 avril 2010 - 11:57 .


#23
RecklezzRogue

RecklezzRogue
  • Members
  • 193 messages
obsolete

Modifié par RecklezzRogue, 17 avril 2010 - 06:32 .


#24
Magic

Magic
  • Members
  • 187 messages
I didn't get it. Are you saying your friendlies are doing nothing because their threat table is full? Maybe full of invalid targets? That shouldn't happen ... Maybe you can check this, for example using the code from my third post.



I'm not overriding core scripts or redirecting events either (and I'm regularly regretting this ^^) but the threat update doesn't require such anyway. EVENT_TYPE_PERCEPTION_DISAPPEAR is sent to the creature script.

#25
RecklezzRogue

RecklezzRogue
  • Members
  • 193 messages
Magic - I am not sure why ClearThreatTable has any impact at all - I was wildly guessing that a completely empty threat table would allow for a nice clean start on the following wave, and it certainly did improve things - very obviously - but - it did not completely remove the problem. Now that I understand I should be modifying the creature script, I suspect I am going to have more luck...I was putting your code in the area script, and toying with updating line 7xx of rules_core as you suggested (before refining your advice).



I will try that, and add your '3rd' post lines tonight when I get back from the office. Report back in a a few hours...



Sorry - still a rookie but getting there...so many moving parts to this beast...but I like it...