Aller au contenu

Photo

New Custom Feat Script


  • Veuillez vous connecter pour répondre
30 réponses à ce sujet

#1
Laugh out loud

Laugh out loud
  • Members
  • 109 messages

I am making a new customer feat that will detect the "Mighty" attribute of a bow and the strength modifier of the character wielding it and make the "Mighty" attribute be equal to the strength modifier if it is lower.  I am writing a script for it but thus far I cannot get it to compile.  Can someone give me some advise?  This is what I have thus far;

 

 

 

object oPC = GetFirstPC(FALSE);
int IsBowEquipped(object oPC)
{
    // get the type of item wielded in the right hand
    object oItem = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC);
    int nType = GetBaseItemType(oItem);
         // check if (holding a bow and (having the right feat)
    if (((nType == BASE_ITEM_LONGBOW) || (nType == BASE_ITEM_SHORTBOW) && (GetHasFeat(FEAT_SHARPSHOOT_MODIFY_BOW, oPC))))
    {
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}
    int oStr = GetAbilityModifier(ABILITY_STRENGTH, oPC);
    int oMight = GetItemPropertyType(ITEM_PROPERTY_MIGHTY, oItem);
 
    if (oMight < oStr)
    {
    oMight = oStr;
    }
 
 
void main()
{
     if (IsBowEquipped(oPC)&& (GetLocalInt(oPC,"FEAT_SHARPSHOOT_MODIFY_BOW") <1))
     {
     SetLocalInt(oPC,"FEAT_SHARPSHOOT_MODIFY_BOW",1);
     effect eEffect = ApplyEffectToObject(SupernaturalEffect(ItemPropertyMaxRangeStrengthMod(oMight, oItem)));
     ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eEffect, oPC, HoursToSeconds(12));
     }
     else
     {
     SetLocalInt(oPC,"FEAT_SHARPSHOOT_MODIFY_BOW",0);
     }
}


#2
rjshae

rjshae
  • Members
  • 4 491 messages

Why aren't you setting oPC in main?



#3
Loki_999

Loki_999
  • Members
  • 430 messages

Also, you are not returning any value from your IsBowEquipped function, even though it has a return type, plus in main() you have no place to capture this value.

 

In main() you are trying to use oMight but you have not definied it within the scope of main(), same goes for oItem.  Not got the toolset open at the moment but i'm fairly sure you should be passing the Strength modifier you want to ItemPropertyMaxRangeStrengthMod, not two objects.

 

I guess you are using the local ints to control whether the effect should be applied, not sure that is needed at all.

 

On top of that you are applying the effect to the object without checking for an existing properties. As you might be adding a property to an item which may have an existing property of the same time you would be best served by using the function called something like IP_SafeAddItemProperty (sorry, can't remember, not had first coffee of the day yet), I think you will need to include x2_inc_itemprops at the top of your script

 

eg: #include "x2_inc_itemprops"

 

Possibly got the name wrong... mmmm, coffee.  You can find the right name, just go to open scripts from the toolset and search for itemprop, should show you the right include file you need. 



#4
Loki_999

Loki_999
  • Members
  • 430 messages

I guess the first thing you need to learn is about scope.

 

Scope is the area within which something is visible, in this particular case we are talking about variables.

 

Just because you define a variable called oStr in your function, does not make it visible in main(). Your script will not even compile due to you failing to define variables before using them.

 

A value with the same name does not carry over between functions. They are just labels, it doesn't make them the same variable.  You need to define each variable that exists within each function.  If you want that variable to be accessible to the function calling the function in which it resides, then you have to "return" the value.

 

Basic script to show this:

int SumOfTwo(int iFirst, int iSecond)
{
 return iFirst + iSecond;
}

void main()
{
 object oPC = GetFirstPC();
 int iResult = SumOfTwo(3, 5);
 if (iResult > 5)
   SendMessageToPC(oPC, "The number " + IntToString(iResult) + " is bigger than 5");
 else
   SendMessageToPC(oPC, "Your nose looks like a banana"); // don't ask me why!
}

PS: A word on naming conventions.  Calling an int value oStr is highly confusing. we use o for Object, s for String, and most people seem to use n for Int, although i personally use i for Int.  f for Float, l for location, e for effect.



#5
Laugh out loud

Laugh out loud
  • Members
  • 109 messages

Why aren't you setting oPC in main?

I did not use oPC because I want anyone with the feat to be able to use it.  Not just the PC.



#6
Laugh out loud

Laugh out loud
  • Members
  • 109 messages

I guess the first thing you need to learn is about scope.

 

Scope is the area within which something is visible, in this particular case we are talking about variables.

 

Just because you define a variable called oStr in your function, does not make it visible in main(). Your script will not even compile due to you failing to define variables before using them.

 

A value with the same name does not carry over between functions. They are just labels, it doesn't make them the same variable.  You need to define each variable that exists within each function.  If you want that variable to be accessible to the function calling the function in which it resides, then you have to "return" the value.

 

Basic script to show this:

int SumOfTwo(int iFirst, int iSecond)
{
 return iFirst + iSecond;
}

void main()
{
 object oPC = GetFirstPC();
 int iResult = SumOfTwo(3, 5);
 if (iResult > 5)
   SendMessageToPC(oPC, "The number " + IntToString(iResult) + " is bigger than 5");
 else
   SendMessageToPC(oPC, "Your nose looks like a banana"); // don't ask me why!
}

PS: A word on naming conventions.  Calling an int value oStr is highly confusing. we use o for Object, s for String, and most people seem to use n for Int, although i personally use i for Int.  f for Float, l for location, e for effect.

Well I could use a modified flame weapon spell script to deliver the effect but I cannot find a version of the "IPGetTargetedOrEquippedMeleeWeapon" command that will target a ranged weapon.  After I find that I can adjust the rest of the script myself (I hope.)



#7
Loki_999

Loki_999
  • Members
  • 430 messages

I did not use oPC because I want anyone with the feat to be able to use it.  Not just the PC.

 

Its irrelevant. You don't control things happening by the names of things. oPC is just a label, it doesn't mean PC. You could call it XYZabcSuckmyass, it doesn't matter.



#8
Loki_999

Loki_999
  • Members
  • 430 messages

Well I could use a modified flame weapon spell script to deliver the effect but I cannot find a version of the "IPGetTargetedOrEquippedMeleeWeapon" command that will target a ranged weapon.  After I find that I can adjust the rest of the script myself (I hope.)

 

Sometimes you have to come up with your own functions to get what you want.

 

I'm sure several of us could fix your script, but its always much better for you to figure out the problem for yourself, with of course, help from the more experienced people.

 

Let's see what you can come up with given the information you have got so far ;)  



#9
Laugh out loud

Laugh out loud
  • Members
  • 109 messages

Sometimes you have to come up with your own functions to get what you want.

 

I'm sure several of us could fix your script, but its always much better for you to figure out the problem for yourself, with of course, help from the more experienced people.

 

Let's see what you can come up with given the information you have got so far ;)  

This is what I was able to come up with so far:

 

#include "x2_inc_itemprop"
const int FEAT_SSHOOT_BOW_MOD = 2839;
 
object oPC = GetFirstPC(FALSE);
 
int IsBowEquipped(object oPC)
{
    // get the type of item wielded in the left hand
    object oItem = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, OBJECT_SELF);
    int nType = GetBaseItemType(oItem);
         // check if (holding a bow and (having the right feat)
    if (((nType == BASE_ITEM_LONGBOW) || (nType == BASE_ITEM_SHORTBOW) && (GetHasFeat(FEAT_SSHOOT_BOW_MOD, oPC))))
    {
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}
 
int AddMightToWeapon(object oMyWeapon)
{
    object oMyWeapon = IsBowEquipped();
    int iStr = GetAbilityModifier(ABILITY_STRENGTH, OBJECT_SELF);
    int iMight = GetItemPropertyType(ITEM_PROPERTY_MIGHTY, oMyWeapon);
 
    if (iMight < iStr)
    {
        return iStr;
}
else
    {
   return iMight;
}
}
void main()
{
     if (IsBowEquipped(OBJECT_SELF) && (GetLocalInt(oPC,"FEAT_SSHOOT_BOW_MOD") <1))
     {
     SetLocalInt(oPC,"FEAT_SSHOOT_BOW_MOD",1);
itemproperty ipMight = ItemPropertyMaxRangeStrengthMod(AddMightToWeapon);
IPSafeAddItemProperty(oMyWeapon, ipMight, (DURATION_TYPE_TEMPORARY(HoursToSeconds(72))), X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, FALSE, FALSE);
FloatingTextStringOnCreature("Sharpshooter's bow adjusted", OBJECT_SELF);
     }
     else
     {
     SetLocalInt(oPC,"FEAT_SSHOOT_BOW_MOD",0);
     }
}
I think that I am getting closer but, I do not want it to add the sum of both the bows might and the players strength mod.  I want it to automatically detect it when the players strength mod is greater than the bow's might and increase the bow's might to match.  If the bow already has a stronger might then the bow's might should remain unchanged.


#10
Loki_999

Loki_999
  • Members
  • 430 messages

You still have oPC being defined out of scope of any function at the top.  Move it into main().  Also you are passing OBJECT_SELF into IsBowEquipped - which is fine if it is the PC, but then you are defining oPC, so might as well use that for consistency.

 

As for only applying if larger, that's a little tricky.  You have to loop through the item properties to find the one that is mighty and then check the value. This involves using the functions that end in Param and Cost (sorry, can't remember their actual names right now).  You need to find which values correspond to Mighty and where the value is set, will take a little experimenting or looking at the approproiate IPRP_*.2das

 

A much easier way is just to simply remove the old property and replace with a new every time it is equipped, therefore always equaling the characters str mod.



#11
Laugh out loud

Laugh out loud
  • Members
  • 109 messages

Forget it.  This was intended to be a custom class feat for a new presige class I was going to call the sharpshooter.  The new class was intended to be a weapon master that specialized in bows but there is no way to add a longbow or shortbow "weapon of choice" feat to the game as weapon of choice feats are hard-wired into the program.



#12
Loki_999

Loki_999
  • Members
  • 430 messages

Well, there is a way you could hack it.

 

Create new base item types (in baseitems.2da) and give them the improved critical values that they would get if wielding the appropriate launcher.

 

When they equip a bow, give them a clone of it (ie: properties) of the new type of bow, and when unequip, revert it to the original.

 

There would be a few situations you would need to code for (ie: server crashes and stuff) but its possible.



#13
Morbane

Morbane
  • Members
  • 1 883 messages

Google: "scripting NWN2 feats" or 

 

Read: "NWN2 Toolset Notes" from the neverwinter vault, also there is a "scripting for noobs" or something similar

 

scripting Feats is not just your basic code crunching - it is, simply put "advanced scripting"

 

dont give up on your idea man, a sharpshooter sounds cool. understanding the limitations of NWN2 scripting comes before breaking the rules (hacking the code like Loki_999 said)

 

for example; i scripted 3 stages of a werewolf Feat progression, where the PC is first cursed, then he begins to learn to control the Feat (stage 2) then stage 3 where he finds he is part of a subculture of shapeshifters that range from weredemons to wereangels. It was tough but i got it to work.

 

it is amazing how much you learn and how quickly when you have an original idea to smash



#14
Laugh out loud

Laugh out loud
  • Members
  • 109 messages

Google: "scripting NWN2 feats" or 

 

Read: "NWN2 Toolset Notes" from the neverwinter vault, also there is a "scripting for noobs" or something similar

 

scripting Feats is not just your basic code crunching - it is, simply put "advanced scripting"

 

dont give up on your idea man, a sharpshooter sounds cool. understanding the limitations of NWN2 scripting comes before breaking the rules (hacking the code like Loki_999 said)

 

for example; i scripted 3 stages of a werewolf Feat progression, where the PC is first cursed, then he begins to learn to control the Feat (stage 2) then stage 3 where he finds he is part of a subculture of shapeshifters that range from weredemons to wereangels. It was tough but i got it to work.

 

it is amazing how much you learn and how quickly when you have an original idea to smash

Thanks.  I have already finished my Privateer class but in truth scripting and programming is a hobby for me.  I still wish to finish my Sharpshooter class, I just see a major hurdle coming on the next stage.



#15
Loki_999

Loki_999
  • Members
  • 430 messages

Scripting gets boring when everything is simple ;)

 

Its finding the creative solutions and hacks that is fun :D



#16
Laugh out loud

Laugh out loud
  • Members
  • 109 messages

Scripting gets boring when everything is simple ;)

 

Its finding the creative solutions and hacks that is fun :D

Yes but you are talking way above my level and I do not understand what you are talking about.  I was asking for help and need someone to bring it a little closer to my level.



#17
Loki_999

Loki_999
  • Members
  • 430 messages

If you are having problems with specifics, just ask.



#18
Laugh out loud

Laugh out loud
  • Members
  • 109 messages

If you are having problems with specifics, just ask.

How do I get the script to add the greater score to the bow?  I checked the Param and it is #45.



#19
Loki_999

Loki_999
  • Members
  • 430 messages

Simple (inelegant) way is to not even bother checking what already exists.  IIRC the safe add item property has a true/false for overwriting existing properties, so simply just apply a new mighty property based off the wielders STR.

 

The more elegant way is to not only check the Param but also the Cost (or CostValue probably). That should have whether its +1, +2, etc.



#20
Laugh out loud

Laugh out loud
  • Members
  • 109 messages

OK, I have got the scritp to compile and fire but I cannot yet get the character's strength mod to add to the bow in their hand.  Take a look at my script and give please give me a clue as to why the score is not being added?

 

#include "x2_inc_itemprop"
 
object oPC = GetFirstPC(FALSE);
 
int IsBowEquipped(object oPC)
{
    // get the type of item wielded in the left hand
    object oItem = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, OBJECT_SELF);
    int nType = GetBaseItemType(oItem);
         // check if (holding a bow and (having the right feat)
    if (((nType == BASE_ITEM_LONGBOW) || (nType == BASE_ITEM_SHORTBOW)))
    {
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}
 
void main()
{
 
     if (IsBowEquipped(OBJECT_SELF))
     {
     oPC = GetItemActivator();
 
     object oTarget;
     object oItem;
     int iStr = GetAbilityModifier(ABILITY_STRENGTH, oPC);
     oTarget = OBJECT_SELF;
 
     oItem = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oTarget);
 
     itemproperty ipAdd;
     ipAdd = ItemPropertyMaxRangeStrengthMod(iStr);
 
     IPSafeAddItemProperty(oItem, ipAdd);
SendMessageToPC(GetFirstPC(), "Bow adjusted.");
 
     }
else
     {
     SendMessageToPC(GetFirstPC(), "Bow already adjusted.");
     }
}


#21
Laugh out loud

Laugh out loud
  • Members
  • 109 messages

I got this script to compile but I cannot get it to add the player's strength modifier to the bow as a mighty property.  Please I cannot find what to do anywhere.

 

#include "x2_inc_itemprop"
const int FEAT_SSHOOT_BOW_MOD = 2839;
 
object oPC = GetFirstPC(FALSE);
 
int IsBowEquipped(object oPC)
{
    // get the type of item wielded in the left hand
    object oItem = GetItemInSlot((INVENTORY_SLOT_RIGHTHAND)||(INVENTORY_SLOT_LEFTHAND), OBJECT_SELF);
    int nType = GetBaseItemType(oItem);
         // check if (holding a bow and (having the right feat)
    if (((nType == BASE_ITEM_LONGBOW) || (nType == BASE_ITEM_SHORTBOW)))
    {
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}
 
void main()
{
 
if (!GetIsPC(GetItemActivatedTarget()))
{
 
  SendMessageToPC(GetItemActivator(), "Bow already adjusted.");
  return;}
 
  oPC = GetItemActivator();
 
  object oTarget;
  object oItem;
  int iStr = GetAbilityModifier(ABILITY_STRENGTH, OBJECT_SELF);
  oTarget = OBJECT_SELF;
 
  oItem = GetItemInSlot((INVENTORY_SLOT_RIGHTHAND)||(INVENTORY_SLOT_LEFTHAND), oTarget);
 
  itemproperty ipAdd;
  ipAdd = ItemPropertyMaxRangeStrengthMod(iStr);
 
  IPSafeAddItemProperty(oItem, ipAdd);
  SendMessageToPC(GetItemActivator(),"Bow adjusted");
}


#22
Dann-J

Dann-J
  • Members
  • 3 161 messages

I'm not sure that GetItemInSlot() will work with the parameters you're trying to use. It may be defaulting to slot zero (the head slot) out of confusion. I have a script that checks whether there's a ranged weapon equipped, and GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oTarget) always returns the weapon correctly.

 

 

You're also using a lot more parentheses than I would. For instance, you could replace

if (((nType == BASE_ITEM_LONGBOW) || (nType == BASE_ITEM_SHORTBOW)))

with

if (nType == BASE_ITEM_LONGBOW || nType == BASE_ITEM_SHORTBOW)

 

 

There's also no need to have 'object oPC = GetFirstPC(FALSE)' at the top of the script. You might as well define the object as 'object oPC = GetItemActivator()' where it is first used in the main void.



#23
kevL

kevL
  • Members
  • 4 061 messages

is this a spellscript fired from a feat, or a tag-based script ?



#24
Laugh out loud

Laugh out loud
  • Members
  • 109 messages

is this a spellscript fired from a feat, or a tag-based script ?

This is a spell script for a feat.  I have tried many things in order to get it to work.



#25
Laugh out loud

Laugh out loud
  • Members
  • 109 messages

I'm not sure that GetItemInSlot() will work with the parameters you're trying to use. It may be defaulting to slot zero (the head slot) out of confusion. I have a script that checks whether there's a ranged weapon equipped, and GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oTarget) always returns the weapon correctly.

 

 

You're also using a lot more parentheses than I would. For instance, you could replace

if (((nType == BASE_ITEM_LONGBOW) || (nType == BASE_ITEM_SHORTBOW)))

with

if (nType == BASE_ITEM_LONGBOW || nType == BASE_ITEM_SHORTBOW)

 

 

There's also no need to have 'object oPC = GetFirstPC(FALSE)' at the top of the script. You might as well define the object as 'object oPC = GetItemActivator()' where it is first used in the main void.

What is the script that checks to see if you have a ranged weapon equipped?