TouchAttackMelee script

This is the first time I have worked with this function and have had some mixed success. It’s almost there but I’m having some strange results. First some context.

The script is an activation script for a pot of pepper which can be thrown into the face of a creature, causing blindness for 12 seconds on a hit, doubling to 24 seconds on a crit.

In my latest test, the script correctly distinguishes a valid target (creature), but the result when used on a creature is ALWAYS a hit (1 / TOUCH_ATTACK_RESULT_HIT). No misses, no crits in a test run of 30 activations.

I’m guessing there is a hole in the way I have written this, or I have overlooked/misunderstood part of the function. Any takers for some pepper in the face?

Here’s the code:

void main()
{
    object oPC      = GetItemActivator();
    object oItem    = GetItemActivated();
    object oTarget  = GetItemActivatedTarget();
    location lTarget = GetItemActivatedTargetLocation();

 	//Your code goes here
	effect eBlind = EffectBlindness();
	effect eVFX = EffectNWN2SpecialEffectFile("fx_dust_cone_mouth");
	int nAttack = TouchAttackMelee(oTarget, TRUE, 0);

	// Target must be a creature	
	int nType = GetObjectType(oTarget);
	if (nType != OBJECT_TYPE_CREATURE)
	{
	SendMessageToPC(oPC, "Target must be a creature.");
	return;
	}

				if (nAttack = TOUCH_ATTACK_RESULT_MISS)
				{
				SendMessageToPC(oPC, "The pepper cloud misses the target.");
				ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eVFX, oPC, 2.0);
				return;
				}
				
					if (nAttack = TOUCH_ATTACK_RESULT_HIT)
					{
					ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eBlind, oTarget, 12.0);
					SendMessageToPC(oPC, "The pepper cloud engulfs the target, temporarily blinding them.");
					ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eVFX, oPC, 2.0);
					return;
					}
					
						if (nAttack = TOUCH_ATTACK_RESULT_CRITICAL)
						{
						ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eBlind, oTarget, 24.0);
						SendMessageToPC(oPC, "The pepper hits your target right in the face. They will be blinded for some time");
						ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eVFX, oPC, 2.0);
						return;
						}
}

I believe TouchAttackRanged and TouchAttackMelee should be run on a creature instead of an item.

You might be able to get this to work by assigning a command to execute the script onto an invisible, script hidden creature that has the desired attack value (by level and/or dex/str).

3 Likes

what about

int nAttack = AssignCommand(oPC, TouchAttackMelee(oTarget, TRUE, 0));
2 Likes

Thanks both. The fact it’s the item calling the attack and not the character was completely overlooked. It’s always the simplest solutions isn’t it… :wink:

I’ll pick this back up tomorrow and see if things progress.

1 Like

This might work, but the TouchAttackMelee needs to wrapped into another function to evaluate the results. 0 parameter value would need to modified to handle the desired base attack and you would have to account for equipped melee/ranged weapons adjusting the value.

I think the TouchAttack** prints out the attacker in the combat log. It might be better to use another creature that is named the same as the pepper item (in addition to not having to deal with the melee/range attack bonus issue).

1 Like

hm yeh, AssignCommand() is probably going to want a void-returning function inside …

besides the other things you mention, Tony, maybe this can start things out →

// run with PC as OBJECT_SELF
void GetTouchResult(object oTarget)
{
    int iResult = TouchAttackMelee(oTarget, TRUE, 0);
    SetLocalInt(oTarget, "temp_touch_result", iResult);
}

then call it like

    AssignCommand(oPC, GetTouchResult(oTarget));
    int iResult = GetLocalInt(oTarget, "temp_touch_result");
    DeleteLocalInt(oTarget, "temp_touch_result");

 
modify GetTouchResult() to adjust bonuses etc … anyway, its a try

1 Like

Getting the result after the AssignCommand won’t work because the AssignCommand function is run after the calling script completes. Handling the touch attack results must be done in the helper function.

2 Likes

Maybe use a save to simulate the attack since it is a grenade-like attack:

void main()
{
	object oPC = GetItemActivator();
	object oTarget  = GetItemActivatedTarget();

	// Target must be a creature	
	if (GetObjectType(oTarget) != OBJECT_TYPE_CREATURE)
	{
		SendMessageToPC(oPC, "Target must be a creature.");
		return;
	}

	effect eVFX = EffectNWN2SpecialEffectFile("fx_dust_cone_mouth");
	
	ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eVFX, oPC, 2.0);	
	
	if (FortitudeSave(oTarget, 15) == SAVING_THROW_CHECK_FAILED)
	{
		effect eBlind = EffectBlindness();
	
		if (d20() == 20)	// crit check
		{
			ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eBlind, oTarget, 24.0);
			SendMessageToPC(oPC, "The pepper hits your target right in the face. They will be blinded for some time");
		}
		
		else
		{
			ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eBlind, oTarget, 12.0);
			SendMessageToPC(oPC, "The pepper cloud engulfs the target, temporarily blinding them.");
		}
	}	

	else
	{
		SendMessageToPC(oPC, "The pepper cloud misses the target.");
	}
}
3 Likes

@Kevlar

If you do something like this in your script … E.g. alb_grenade in my own usage.

SetLocalObject(oPC, "FLASKTARGET", oTarget);
ExecuteScript("alb_grenade", oPC);

Then, I believe, you can have the script that is executed do your grenade like stuff, which should fire the TouchAttackMelee OK. That’s how I currently have it in my own campaign, and I believe it worked OK. NOTE: You regain the target from FLASKTARGET in the script executed.

Triggered from an item property that does cast spell: long range and uses item tagged based scripting. (Adjust your property accordingly, but basically have the item tag basis as the script to fire, which then calls the script that has the PC execute the script you need the function to work from.)

2 Likes

Thanks everyone for being so generous with your time! On reflection, this is very much a grenade-like item, although I see it as being very short range, so I experimented with the item property, opting for Activate Item (Touch) to force the activation at melee range - this works fine.

I liked @travus solution by making it saving throw based. Fits well with a grenade-like approach so I gave that a go. Everything seems to be working just fine now, after coating an unfortunate Jackal with pepper…


Pepper Pot description


Hit/Fort save fail


Miss / Fort save pass

I wasn’t lucky enough to get a crit, but will keep an eye out for it. Thanks for all the help and suggestions. Walked away doing something slightly different, but hopefully wiser for it :smiley:

4 Likes

Personally i would change the description to “On a hit, there’s a 5% chance of a critical success,…” instead of using the phrase “critical fail”. Fail sounds like the thrower/user could fumble, smearing the pepper in his own eyes blinding himself. At least that’s what i thought after reading the text.

2 Likes

Good catch, agreed!