New Forums

Please go vote on the new forums now. Let's get this shipped.

You are here

Placeable - to not be melee attacked

7 posts / 0 new
Last post
andgalf
Placeable - to not be melee attacked

On my journey to try to understand scripting I wanted to do this:

I have a placeable that is a dartboard. I would want it to be non-attackable when it comes to melee attack.

I thought that maybe I could do a script that was attached to On Melee Attack Script on the dartboard, that made the PC move away if he were to attack the thing with his fists, sword or axe etc. So I made a script that looked like this:

 

void main()
{

object oPC = GetLastAttacker();

if (!GetIsPC(oPC)) return;

AssignCommand(oPC, ActionMoveAwayFromObject(GetObjectByTag("jdar_tiro")));

}

 

No protest from compiling the script. However, it does nothing apparently when testing it in the game. I have found no explanation online as to exactly what you are supposed to put, and not put, script wise in the On Melee Attack Script, but I thought it to be logical that it would have to do with something happening when someone does a melee attack on the placeable.

  • up
    50%
  • down
    50%
TheBarbarian

Use ClearAllActions() first to clear the action queue before assigning the move-away command. As is, you're adding the "move away" action at the end of the player's queue, after the (continuous) attack action. So they *would* move away - once that action is first in the queue, which it won't be until the player manually ends the attack action.

Also, the placeable is OBJECT_SELF in an event fired by it, so you don't have to make the script get the object to move away from by it's tag; that way, the script works for any placeable it's attached to.

AssignCommand(oPC, ClearAllActions());
AssignCommand(oPC, ActionMoveAwayFromObject(OBJECT_SELF));
OnPhysicalAttacked doesn't just fire for melee attacks, though. As is, that'll happen for ranged attacks, too. ::headscratch:: Moreover, the first hit would still get in. You could check whether the attacking player has a ranged weapon equipped and abort the script if they do, but that's not going to stop the first hit from getting in. hm.
  • up
    50%
  • down
    50%
andgalf

Ah, that explains it. Thank you for the reply! You're right about OBJECT_SELF of course. I didn't think about that.

  • up
    100%
  • down
    0%
andgalf
OnPhysicalAttacked doesn't just fire for melee attacks, though. As is, that'll happen for ranged attacks, too. ::headscratch:: Moreover, the first hit would still get in. You could check whether the attacking player has a ranged weapon equipped and abort the script if they do, but that's not going to stop the first hit from getting in. hm.
Once again I think I understand scripting somewhat only to be proved I don't. Like you insinuated On Melee Attack Script fires for ranged attacks too, so I gave my script a new go, but I'm doing something wrong here. Usually I get help from Lilac's Script Editor to get me on the right path, but for this I can't find any help, so I'll have to try and figure it out. Please, what am I doing wrong? It's so frustrating:
 
void main()
{

object oPC = GetLastAttacker();
object oAttackedWith = GetLastWeaponUsed(oPC);

if (!GetIsPC(oPC)) return;

    if (!GetObjectByTag(oAttackedWith) = "dart_item") {

    AssignCommand(oPC, ClearAllActions());
    AssignCommand(oPC, ActionMoveAwayFromObject(OBJECT_SELF));
    }

}
  • up
    50%
  • down
    50%
Claudius33

if (GetTag(oAttackedWith) != "dart_item") ...

Beware that the onDamage script would be fired if the target was hit by the wrong weapon.

Unless you rely on the player's integrity you should remove all weapons except the dart from his/her inventory or (more simple) abort the trial if the player has cheated.

for instance :

if (GetTag(oAttackedWith) != "dart_item")  {

    AssignCommand(oPC, ClearAllActions());
    AssignCommand(oPC, ActionMoveAwayFromObject(OBJECT_SELF));

    SendMessageToPC(oPC, "You have cheated");

  SetLocalInt(GetObjectByTag("NPC_giving_quest"), "Cheated", 1);

}

 

 

 

 

  • up
    100%
  • down
    0%
TheBarbarian

Yep. And to fill in the blanks you're missing, to help with these kinds of problems in the future - you've basically got different types of lego pieces, and you can only compare pieces of the same type, and can only connect pieces that fit together. GetObjectByTag() needs a string and returns an object.

if (!GetObjectByTag(oAttackedWith) = "dart_item") {

vs

if (GetTag(oAttackedWith) != "dart_item")

Give GetTag an object, and it returns you the object's tag as a string, which you can then compare with another string. GetObjectByTag returns the nth object it finds that has the specified string as it's tag (by default the first).

 

Or you could use GetBaseItemType, which returns an integer.

if (GetBaseItemType(oAttackedWith) != BASE_ITEM_DART)

^- BASE_ITEM_DART here is the name of an integer constant which stands for a row number in baseitems.2da. This way, you wouldn't be checking for the item's tag, but rather for it's base item type, so any dart type item would qualify.

 

Read these two writs: 1 2. = and == mean very different things, too.

Also, plugging Tarot's Basics and newbie FAQ collection:

TR's Basics - Decisions

Just The FAQs, ma'am

I see I've strayed into the NWN2 section though. x_x I don't actually know whether all the events do the same things as in NWN1, here. I'd better inch back away to where I'm slightly less likely to horribly misinform people.

  • up
    50%
  • down
    50%
andgalf

OK. Thanks guys!

  • up
    50%
  • down
    50%