Bizarre behaviour when activating friendly creatures
#1
Posté 20 février 2010 - 06:32
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
Posté 20 février 2010 - 07:59
#3
Posté 20 février 2010 - 09:21
#4
Posté 20 février 2010 - 11:29
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
Posté 20 février 2010 - 12:15
#6
Posté 20 février 2010 - 08:01
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
Posté 20 février 2010 - 10:57
// ----------------------------------------------------------------------------- // 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
Posté 20 février 2010 - 11:09
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
Posté 20 février 2010 - 11:44
Now finding a solution in this huge script system will be more difficult, I guess ... Doing some more testing now.
#10
Posté 21 février 2010 - 12:22
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
Posté 21 février 2010 - 01:49
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
Posté 21 février 2010 - 01:57
#13
Posté 21 février 2010 - 06:17
#14
Posté 21 février 2010 - 10:09
// 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
Posté 21 février 2010 - 10:43
#16
Posté 21 février 2010 - 03:18
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
Posté 21 février 2010 - 08:34
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
Posté 21 février 2010 - 10:03
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
Posté 21 février 2010 - 11:06
#20
Posté 22 février 2010 - 12:49
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
Posté 22 février 2010 - 08:26
#22
Posté 12 avril 2010 - 07:44
Modifié par RecklezzRogue, 12 avril 2010 - 11:57 .
#23
Posté 12 avril 2010 - 11:04
Modifié par RecklezzRogue, 17 avril 2010 - 06:32 .
#24
Posté 13 avril 2010 - 05:36
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
Posté 13 avril 2010 - 08:36
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...





Retour en haut







