ShaDoOoW wrote...
Funky, I did that exactly and then I went playtesting. I had an creature that couldnt see me (i was outside of his visual range) and then I cast BBoD into his vision range, this creature then attacked BBoD and doesnt changed target even after I came closer. Then I tried to come closer in order this npc would attack me and then I casted BBoD into his path, the BBoD then attacked him and since I was farther than BBoD creature switched target in OnAttack script to BBoD and then bkAcquireTarget WASNT called at all!
You're right about it not working when oIntruder is passed into DCR. I guess we haven't noticed any issues from that due to style of play (not doing what you did in your test) and pre-existing code in events where that happens. Here, for example, is our dialogue script:
#include "nw_i0_generic"
void main () {
object oSelf = OBJECT_SELF;
if (GetSpawnInCondition(NW_FLAG_ON_DIALOGUE_EVENT))
SignalEvent(oSelf, EventUserDefined(EVENT_DIALOGUE));
int nUptime = GetLocalInt(GetModule(), "uptime");
int nEvtime = GetLocalInt(oSelf, "AI_Uptime_Dialogue");
if (nUptime > 0 && nUptime == nEvtime)
return;
SetLocalInt(oSelf, "AI_Uptime_Dialogue", nUptime);
DelayCommand(1.0, SetLocalInt(oSelf, "AI_Uptime_Dialogue", -1));
object oSpeaker = GetLastSpeaker();
if (!GetIsPC(oSpeaker) && GetListenPatternNumber() == 1) {
int bDCR = FALSE;
object oTarget, oHostile = GetLastHostileActor(oSpeaker);
if (GetIsObjectValid(oHostile)) {
int bIgnoreBBoD = Random(4);
oTarget = GetAttemptedAttackTarget();
if (!GetIsObjectValid(oTarget) || (bIgnoreBBoD && GetResRef(oTarget) == "x2_s_bblade")) {
oTarget = GetAttemptedSpellTarget();
if (!GetIsObjectValid(oTarget) || (bIgnoreBBoD && GetResRef(oTarget) == "x2_s_bblade")) {
bDCR = TRUE;
oTarget = GetLastHostileActor(oSelf);
if (!GetIsObjectValid(oTarget) || (bIgnoreBBoD && GetResRef(oTarget) == "x2_s_bblade"))
SetLastHostileActor(oSelf, oHostile);
}
}
} else {
if (!GetIsObjectValid(GetAttemptedAttackTarget()) &&
!GetIsObjectValid(GetAttemptedSpellTarget()))
bDCR = TRUE;
}
if (bDCR)
DetermineCombatRound(oHostile);
}
}
And, searching by that resref, we have a LOT of pre-existing bbod-handling code:
abo_endcombat (245): if (GetLocalInt(oSelf, "NoBBoD") && GetResRef(oPC) == "x2_s_bblade") {
aby_boss_heart (426): if (GetIsObjectValid(oTarget = GetNearestObjectByTag("x2_s_bblade", oSelf)))
aby_boss_heart (487): if (GetIsObjectValid(oTarget = GetNearestObjectByTag("x2_s_bblade", oSelf)))
aby_boss_heart (527): if (GetIsObjectValid(oTarget = GetNearestObjectByTag("x2_s_bblade", oSelf)))
aby_boss_heart (589): if (GetIsObjectValid(oTarget = GetNearestObjectByTag("x2_s_bblade", oSelf)))
aby_boss_heart (720): if (GetIsObjectValid(oTarget = GetNearestObjectByTag("x2_s_bblade", oSelf)))
aby_endcombat (147): } else if (GetResRef(oTarget) == "x2_s_bblade") {
aby_endcombat (874): if (GetLocalInt(oSelf, "NoBBoD") && GetResRef(oPC) == "x2_s_bblade")
aby_endcombat (3394): if (GetResRef(oPC) == "x2_s_bblade") {
aby_enter (1683): if (GetIsDM(oPC) || !(GetIsPC(oPC) || GetIsPC(GetMaster(oPC))) || GetResRef(oPC) == "x2_s_bblade")
aby_onhit (206): if (GetResRef(oTarget) == "x2_s_bblade")
dul_endcombat (178): if (GetLocalInt(oSelf, "NoBBoD") && GetResRef(oPC) == "x2_s_bblade")
ele_endcombat (105): if (GetLocalInt(oSelf, "NoBBoD") && GetResRef(oPC) == "x2_s_bblade")
ely_endcombat (156): if (GetResRef(oPC) == "x2_s_bblade") {
fey_endcombat (82): if (GetLocalInt(oSelf, "NoBBoD") && GetResRef(oPC) == "x2_s_bblade")
fky_3endcmb_hell (366): if (GetResRef(oPC) == "x2_s_bblade")
fky_3endcmb_hell (439): if (GetResRef(oPC) == "x2_s_bblade")
fky_3endcmb_hell (501): if (GetResRef(oPC) == "x2_s_bblade")
fky_3endcmb_hell (621): if (GetResRef(oPC) == "x2_s_bblade") {
fky_3endcmb_hell (1544): if (GetResRef(oPC) == "x2_s_bblade") {
fky_ai_4dialogue (28): if (!GetIsObjectValid(oTarget) || (bIgnoreBBoD && GetResRef(oTarget) == "x2_s_bblade")) {
fky_ai_4dialogue (31): if (!GetIsObjectValid(oTarget) || (bIgnoreBBoD && GetResRef(oTarget) == "x2_s_bblade")) {
fky_ai_4dialogue (35): if (!GetIsObjectValid(oTarget) || (bIgnoreBBoD && GetResRef(oTarget) == "x2_s_bblade"))
fky_ai_target (13): } else if (GetResRef(oLastTarget) == "x2_s_bblade") {//skip bbod if boss or smart enough, unless caster with Mord
fky_ai_target (162): if (sRes == "x2_s_bblade") {//skip bbod if boss or smart enough, unless caster with Mord
gen_endcombat (185): if (GetLocalInt(ei.self, "NoBBoD") && GetResRef(ei.opp) == "x2_s_bblade")
had_enter (274): if (GetIsDM(oPC) || GetLocalInt(oPC, "PlotSummons") || GetResRef(oPC) == "x2_s_bblade")
had_enter (298): if (GetIsDM(oPC) || !(GetIsPC(oPC) || GetIsPC(GetMaster(oPC))) || GetResRef(oPC) == "x2_s_bblade")
hellenter (96): if (GetResRef(oPC) == "x2_s_bblade") {
hellenter (131): if (GetIsDM(oPC) || !(GetIsPC(oPC) || GetIsPC(GetMaster(oPC))) || GetResRef(oPC) == "x2_s_bblade")
hell_boss_spawn (18): AssignCommand(oArea, DelayCommand(6.0, DestroyObjectsByTag(oNear, "x2_s_bblade")));
hg_area_exit (154): if (GetResRef(oPC) != "x2_s_bblade" && !GetLocalInt(oPC, "FKY_CHAT_INVULN") && !GetLocalInt(oPC, "PlotSummons"))
hg_attack_inc (769): if (GetResRef(oTarget) == "x2_s_bblade") {
hiv_endcombat (167): if (GetLocalInt(oSelf, "NoBBoD") && GetResRef(oPC) == "x2_s_bblade")
loc_endcombat (112): if (GetLocalInt(oSelf, "NoBBoD") && GetResRef(oPC) == "x2_s_bblade")
loc_endcombat (403): } else if (GetResRef(oPC) == "x2_s_bblade") {
mol_endcombat (153): if (GetLocalInt(oSelf, "NoBBoD") && GetResRef(oPC) == "x2_s_bblade") {
toy_endcombat (124): if (GetLocalInt(oSelf, "NoBBoD") && GetResRef(oPC) == "x2_s_bblade")
toy_onhit (17): if (GetResRef(oTarget) == "x2_s_bblade")
x2_inc_spellhook (223): if(GetTag(oAssoc) == "x2_s_bblade") // black blade of disaster
x2_s0_blckblde (10): if (GetResRef(oSummon) == "x2_s_bblade") {
x2_s0_blckblde (35): effect eSummon = EffectSummonCreature("x2_s_bblade");
Nothing in onattacked, though. I guess that scenario just isn't coming up much. Surveying the default ai scripts, it looks like it's occurences are limited to onspellcastat, ondialogue, and ondamaged.
nw_c2_default2 (39): DetermineCombatRound();
nw_c2_default2 (58): DetermineCombatRound();
nw_c2_default3 (23): DetermineCombatRound();
nw_c2_default3 (28): }else{DetermineCombatRound();}
nw_c2_default5 (39): DetermineCombatRound();
nw_c2_default6 (72): DetermineCombatRound();
nw_c2_default6 (79): ActionDoCommand(DetermineCombatRound());
nw_c2_default6 (102): DetermineCombatRound(oAttacker);
nw_c2_default8 (28): DetermineCombatRound(oTarget);
nw_c2_default9 (64): DetermineCombatRound();
nw_c2_defaultb (21): DetermineCombatRound(oCaster);
And, surveying my ai, which is mostly based on the default (with the x2 revisions), it comes up even less:
fky_3endcmb_hell (2368): DetermineCombatRound();
fky_ai_2percept (27): DetermineCombatRound();
fky_ai_4dialogue (46): DetermineCombatRound(oHostile);
fky_ai_5attacked (15): DetermineCombatRound();
fky_ai_5spellat (18): DetermineCombatRound();
fky_ai_6ondamage (380): DetermineCombatRound(oDamager);
fky_ai_6ondamage (385): ActionDoCommand(DetermineCombatRound());
fky_ai_9spawn (37): DetermineCombatRound();
though my ai includes mw_c2_default8 (ondisturbed), which does pass oIntruder.
I have to wonder if simply removing the check for oIntruder's validity and running bkAcq all the time isn't the best solution. Here's my onspellcastat (replacing defaultb) , by way of comparison:
#include "nw_i0_generic"
void main() {
object oSelf = OBJECT_SELF;
if (GetSpawnInCondition(NW_FLAG_SPELL_CAST_AT_EVENT))
SignalEvent(oSelf, EventUserDefined(EVENT_SPELL_CAST_AT));
if (!GetLastSpellHarmful())
return;
if (GetIsObjectValid(GetAttemptedAttackTarget()) || GetIsObjectValid(GetAttemptedSpellTarget()))
return;
object oHostile = GetLastSpellCaster();
if (GetArea(oHostile) == GetArea(oSelf)) {
DetermineCombatRound();
if (!GetIsObjectValid(GetLastHostileActor(oSelf)))
SetLastHostileActor(oSelf, oHostile);
SpeakString("NW_I_WAS_ATTACKED", TALKVOLUME_SILENT_TALK);
}
}
}
Thoughts? I ran your test with spawing out of sight and got the same result, by the way, save that the creature switched to me as soon as I attacked it with a sling, despite being much further away than the BBoD. The script events on the creature in question:
OnBlocked=nw_c2_defaulte
OnDamaged=fky_ai_6ondamage
OnDeath=fky_ai_7death
OnConversation=fky_ai_4dialogue
OnDisturbed=nw_c2_default8
OnCombatRoundEnd=fky_3endcmb_hell
OnHeartbeat=fky_1heart_hellb
OnPhysicalAttacked=fky_ai_5attacked
OnPerception=fky_ai_2percept
OnRested=nw_c2_defaulta
OnSpawn=fky_ai_9spawn
OnSpellCast=fky_ai_5spellat
OnUserDefined=
Kinda tempted to throw in debug to see just how often DCR fires in various scenarios.
Funky
Modifié par FunkySwerve, 29 octobre 2011 - 05:56 .