Please Help - Attack script

The situation is this - a golem stands guard next to a doorway. If the PC crosses the threshold of the door, the golem is supposed to turn hostile, move to the PC, and attack him. Seems simple and straightforward enough.

The problem is that while the golem does turn red - it just keeps standing there, doing nothing. Only if the PC attacks it, does it then move to the PC and attack back.

Here is the script for the trigger I’ve been using:

void main()
{
object oPC = GetEnteringObject();
if ( GetIsPC(oPC) ) {
object oNPC = GetObjectByTag(“GolemGuard”);
AdjustReputation(oPC, oNPC, -100);
AssignCommand(oNPC, ActionMoveToObject(oPC, TRUE));
AssignCommand(oNPC, ActionAttack(oPC));
DestroyObject( OBJECT_SELF );
}
}

What happens if you add the:

ChangeToStandardFaction(oNPC,STANDARD_FACTION_HOSTILE);

EDIT: It might be that you also need to put a delay on the DestroyObject function.

Maybe try something like this:

void main()
{

object oPC = GetEnteringObject();

    if (GetIsPC(oPC))
    {
    object oNPC = GetObjectByTag("GolemGuard");
    AdjustReputation(oPC, oNPC, -100);
    ChangeToStandardFaction(oNPC,STANDARD_FACTION_HOSTILE);
    AssignCommand(oNPC, ActionMoveToObject(oPC, TRUE));
    AssignCommand(oNPC, ActionAttack(oPC));
    DelayCommand(1.0,DestroyObject( OBJECT_SELF ));
    }


}

Or maybe this (just changed and added some more code that may or may not help)

#include "nw_i0_generic"

void main()
{

 object oPC = GetEnteringObject();

    if (GetIsPC(oPC))
    {
    object oNPC = GetObjectByTag("GolemGuard");
    AdjustReputation(oPC, oNPC, -100);

    ChangeToStandardFaction(oNPC,STANDARD_FACTION_HOSTILE);
    SetIsTemporaryEnemy(oPC, oNPC);

    AssignCommand(oNPC, ActionForceMoveToObject(oPC, TRUE));
    AssignCommand(oNPC, ActionAttack(oPC));
    AssignCommand(oNPC, DetermineCombatRound(oPC));
    DelayCommand(6.0,DestroyObject( OBJECT_SELF ));
    }


}

No, sorry - I tried both scripts and neither one worked.

The strange thing is the first time I tested either one - it did work. But then when I went back and tested it again to be sure - it never worked after that.

I’ve had similar problems in the past.

Assuming the golem can see the PC at the time, rather than issue all those actions, I simply assign DetermineCombatRound(oPC).

I suspect that’s the main problem here.

Like other contributors, I’m nervous about destroying the trigger while it’s issuing instructions, even though in theory the golem’s action queue should get set up first (IIRC only delayed commands die with the issuer).

A safe method is to set a one-time flag on the trigger, so that it only fires once, but isn’t destroyed.

Yeah, I seldom destroy triggers too, and like you @Proleric I tend to use the one-time thing, in my case with a SetLocalInt. Maybe also just remove the ActionMoveToObject thing? Or maybe it’s enough to just use DetermineCombatRound. As I work with NWN2, I don’t know if this works exactly the same in both games, but I believe it does in this case. I think I’ve also had cases where the enemies don’t attack at once, but for me that’s not a big deal since the most important thing for me is that they turn hostile.

1 Like

I tried @Proleric 's method of just using DetermineCombatRound, and removing the Attack and MoveTo commands, with the script below. Tested it in NWN2 three times and it worked everytime:

#include "nw_i0_generic"

void main()
{

 object oPC = GetEnteringObject();
 
 if(!GetIsPC(oPC)) return;

    if (!GetLocalInt(OBJECT_SELF,"Done"))
    {
    
	SetLocalInt(OBJECT_SELF,"Done",TRUE);
	
	object oNPC = GetObjectByTag("GolemGuard");
    AdjustReputation(oPC, oNPC, -100);

    ChangeToStandardFaction(oNPC,STANDARD_FACTION_HOSTILE);
    SetIsTemporaryEnemy(oPC, oNPC);

    AssignCommand(oNPC, DetermineCombatRound(oPC));
    
    }


} 

I had a need to make sure that at the end of a conversation a creature (actually 4 but irrelevant for now) so I took a “boots and braces” (ignore association with skinheads, this saying predates them by several decades) approach. Here is the relevant section of code using your variables -

#include "nw_i0_generic" //needed for commands used

then in the body of the function -

    ChangeToStandardFaction(oNPC, STANDARD_FACTION_HOSTILE);
    SetIsTemporaryEnemy(oPC, oNPC);
    AssignCommand(oNPC, ActionAttack(oPC));
    AssignCommand(oNPC, DetermineCombatRound(oPC));

which works everytime in my module.

TR

One other little thing. Seems you haven’t got a copy of the downloadable version of the Lexicon (link to online version of the Lexicon is under related projects on the project page) otherwise you wouldn’t be using DelayCommand() to run DestroyObject(). DestroyObject() actually has 2 parameters the second of which has a default value. Here is the definition for DestroyObject() -

void DestroyObject(object oDestroy, float fDelay = 0.0f);

As you can see the second parameter delays the actual destruction of the object so if you want to destroy the trigger while allowing the action queue to complete you just give a reasonable delay, say 10 seconds as the second parameter of DestroyObject() -

    DestroyObject(OBJECT_SELF, 10.0f);

FWIW, I have used such code to make things one shot myself.

TR

I’ve tried out the various suggestions and it still won’t work. What’s weird is occasionally it will work. But when I try it again, without any sort of modification, it wont work. Which leads me to believe there might be some other factor that is the cause.

Does it work if you move the trigger away from the door? Just to be sure it’s not an area configuration problem (like, the golem cannot pass through the doorframe, or doesn’t notice the PC because they’re not in the golem’s line of sight).

First thing to check is the shape of the trigger in the doorway. Is it 100% visible? If not redraw it so that it is. Or if it is totally visible is it large enough that the PC has to walk through it to go through the door.

Does it look like a rectangle or a box. If like a box redraw it so that it looks 2D. I’ve found that for some reason triggers that look like boxes just don’t fire consistently.

TR

Yeah, I tried moving the trigger to see if that was possibly the issue. But it is still happening. The door is one of those extra wide doors that even large creatures can easily fit through. So that isn’t the problem. And the golem is standing right across from the door. So the PC is well in its line of sight.

Like I said, it does work once in a great while. So physical issues don’t seem to be a problem.

I did tried redoing the trigger, thinking that might be the issue. But I’m still having the same problem. The golem is turning red. So the trigger and the script are activating. It just isn’t attacking the PC.

The odd thing is that even after the golem turns hostile - it never attacks the PC unless attacked first. I try to move the PC back and forth and around the golem. And it just keeps showing hostile but never makes a move.

Not sure if this will help, but could you perhaps do a short movie of how it looks ingame for you, and maybe a screenshot from the Toolset? Someone might notice something perhaps…

Could it be that this particular creature has some script on it that makes it behave this way?

1 Like

This is a strange sentence. You had a need to make sure a creature did what?

Very strange. I’ve double-checked that DetermineCombatRound() by itself will always cause a hostile creature to attack.

Be aware that not attacking is expected behaviour. At the point at which the golem turns hostile, OnPerception has already fired, therefore some other event (such as the PC attacking) needs to happen before the golem will attack. In my experience, DetermineCombatRound() invariably overcomes that.

So if DetermineCombatRound() isn’t working, something else must be preventing the golem from acting. You could try ClearAllActions(TRUE) first, in case it’s playing an animation or some other incomplete action - otherwise, as previously suggested, some script affects it?

Incidentally, you’re not running the EE Development release .21 or .22, are you? That has all kinds of bugs involving actions and doors.

BTW, DCR issues CAA only if the creature is doing random walking. I’d call CAA every time before it and every time when issuing immediate orders.

It might also be a good idea (per @andgalf’s suggestion) to check if other scripts are not interfering. Test 1: try painting a normal enemy (say, a goblin), make it neutral and use its tag instead of the golem.

@hartunga, you could also share a screesnhot showing the door arrangement, but perception should not be an issue here.

For code improvements, I’d do a sanity check if oNPC exists before locking out the trigger.

I finally got it to work. What I did is I remade the golem from scratch and it started working.

The funny thing is I hadn’t used any special scripting on the original golem or anything like that. Just crafted it using the Creature Wizard. The only thing I can think of is I originally crafted the creature some months ago and am getting around to playtesting it’s part now. So maybe when I crafted it during a previous NWN version it gave it some sort of bug?

But thanks to everyone for their assistance. I really appreciate it.