Adding fire to a weapon in steps

// Set fire Bonus on Weapon OnUse
#include “x2_inc_itemprop”

// Make duration permnent
float fDuration = 0.0;
// VFX to use on item.
int nFlaming = ITEM_VISUAL_FIRE;
// Damage Type to use on item.
int nFire = IP_CONST_DAMAGETYPE_FIRE;

void main()
{
// Damage bonuses to use on item.
int nDice1 = IP_CONST_DAMAGEBONUS_1;
int nDice2 = IP_CONST_DAMAGEBONUS_2;
int nDice3 = IP_CONST_DAMAGEBONUS_1d4;
int nDice4 = IP_CONST_DAMAGEBONUS_1d6;
int nDice5 = IP_CONST_DAMAGEBONUS_1d8;
int nDice6 = IP_CONST_DAMAGEBONUS_1d10;
int nDice7 = IP_CONST_DAMAGEBONUS_2d6;
int nDice8 = IP_CONST_DAMAGEBONUS_2d8;
int nDice9 = IP_CONST_DAMAGEBONUS_2d10;
int nDice10 = IP_CONST_DAMAGEBONUS_2d12;
int nDie = 0;
// Get the creature who triggered this event.
object oPC = GetLastUsedBy();
// Object to add fire to.
object oItem = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND,oPC);
// Check for ranged weapon.
int nRanged = IPGetIsRangedWeapon(oItem);
if(nRanged == TRUE){ActionSpeakString(“Only melee weapons benefit from this lever”);return;}
// Get the weapons current fire bonus.
int nFireCount = IPGetWeaponEnhancementBonus(oItem,IP_CONST_DAMAGETYPE_FIRE);
// Find weapons current fire bonus
if (nFireCount < nDice1 && nFireCount != 1){nDie = nDice1;}
else if (nFireCount == 1){nDie = nDice2;}
// Item property
itemproperty ipFire = ItemPropertyDamageBonus(nFire,nDie);
IPSafeAddItemProperty(oItem,ipFire,fDuration);
}

ATM this will add +1 fire damage and then do nothing after that. I’d like it to prgressivley add the next tier of fire damage on each pull up to 2d12.

I read that maybe IPGetWeaponEnhancementType doesnt work with this type of damage bonus?
If not what does? Any help is appreciated as usual. Thanks guys!

// Set fire Bonus on Weapon OnUse
#include "x2_inc_itemprop"

int GetNewDamageBonus(int iFireCount)
{
	int iNewBonus;
	switch (iFireCount)
	{
		case 0:                         iNewBonus = IP_CONST_DAMAGEBONUS_1;    break;
		case IP_CONST_DAMAGEBONUS_1:    iNewBonus = IP_CONST_DAMAGEBONUS_2;    break;
		case IP_CONST_DAMAGEBONUS_2:    iNewBonus = IP_CONST_DAMAGEBONUS_1d4;  break;
		case IP_CONST_DAMAGEBONUS_1d4:  iNewBonus = IP_CONST_DAMAGEBONUS_1d6;  break;
		case IP_CONST_DAMAGEBONUS_1d6:  iNewBonus = IP_CONST_DAMAGEBONUS_1d8;  break;
		case IP_CONST_DAMAGEBONUS_1d8:  iNewBonus = IP_CONST_DAMAGEBONUS_1d10; break;
		case IP_CONST_DAMAGEBONUS_1d10: iNewBonus = IP_CONST_DAMAGEBONUS_2d6;  break;
		case IP_CONST_DAMAGEBONUS_2d6:  iNewBonus = IP_CONST_DAMAGEBONUS_2d8;  break;
		case IP_CONST_DAMAGEBONUS_2d8:  iNewBonus = IP_CONST_DAMAGEBONUS_2d10; break;
		case IP_CONST_DAMAGEBONUS_2d10: iNewBonus = IP_CONST_DAMAGEBONUS_2d12; break;
		default:                        iNewBonus = -1;                        break;
	}

	return iNewBonus;
}

void main()
{
	// Get the creature who triggered this event.
	object oPC = GetLastUsedBy();

	// Object to add fire to.
	object oItem = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC);

	if (GetIsObjectValid(oItem))
	{
		// Check for ranged weapon.
		int nRanged = IPGetIsRangedWeapon(oItem);
		if (nRanged)
		{
			ActionSpeakString("Only melee weapons benefit from this lever");
			return;
		}
	}
	else
	{
		ActionSpeakString("You have no weapon in your main hand");
		return;
	}

	int iFireCount;
	itemproperty ip = GetFirstItemProperty(oItem);

	while (GetIsItemPropertyValid(ip))
	{
		if (GetItemPropertyType(ip) == ITEM_PROPERTY_DAMAGE_BONUS
		 &&	GetItemPropertySubType(ip) == IP_CONST_DAMAGETYPE_FIRE)
		{
			iFireCount = GetItemPropertyCostTableValue(ip);
			break;
		}
		ip = GetNextItemProperty(oItem);
	}

	int iDie = GetNewDamageBonus(iFireCount);

	//Check if we haven't already had the max damage bonus or
	//our damage is higher
	if (iDie != -1)
	{
		itemproperty ipFire = ItemPropertyDamageBonus(IP_CONST_DAMAGETYPE_FIRE, iDie);
		IPSafeAddItemProperty(oItem, ipFire, 0.0);
	}
	else
	{
		ActionSpeakString("Your fire damage bonus is already at max");
	}
}

I haven’t tested it. Let me know if you find any problems.

1 Like

Holy crap.
Is there a reason why a simple add fire code needs to be this intense?

I’m curious as to why there is no function to directly grab the fire bonus and compare it to another.

I haven’t used type/sub type etc not do I totally understand the method.

Thank you!
I’ll try it out and read it through to comprehend it.

Ugh, just realised this is in NWN 2… does this still apply for nwn1?

Can a mod mor this to nwn1?

Sorry!

It should work in NWN1 too, AFAIK.
If it won’t compile for you and give you an error, just tell me and I’ll try to fix it.

1 Like

there’s a couple holes in there Aq

  • check for durationtype permanent
  • remove the old ip
  • account for a weapon that can have a rogue damagebonus constant

re WeaponType: I think it’s possible to have a baseitem-type that’s not a ranged weapon but has no “DieToRoll” value in BaseItems.2da – ie, it’s not a weapon but can be equipped in the righthand … but not sure about that (the engine could assign default-damage to any item that’s equippable in the righthand slot)

 
aw heck, mix & match:

// 'heavymetal2000_ipbonus'
/*
    Placeable OnUsed event
    IP fire-bonus (progressive) on weapon.
*/

#include "x2_inc_itemprop"

int GetIsMelee(object oItem);
int GetHigherBonus(int iFire);

//
void main()
{
    object oPc = GetLastUsedBy();

    object oItem = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPc);
    if (GetIsObjectValid(oItem))
    {
        if (GetIsMelee(oItem))
        {
            int iFire = 0;

            itemproperty ipScan = GetFirstItemProperty(oItem);
            while (GetIsItemPropertyValid(ipScan))
            {
                if (GetItemPropertyType(ipScan) == ITEM_PROPERTY_DAMAGE_BONUS
                    && GetItemPropertyDurationType(ipScan) == DURATION_TYPE_PERMANENT
                    && GetItemPropertySubType(ipScan) == IP_CONST_DAMAGETYPE_FIRE)
                {
                    iFire = GetItemPropertyCostTableValue(ipScan);
                    iFire = GetHigherBonus(iFire);

                    if (!iFire)
                    {
                        ActionSpeakString("Your fire damage bonus is already at max");
                        return;
                    }

                    RemoveItemProperty(oItem, ipScan);
                    break;
                }
                ipScan = GetNextItemProperty(oItem);
            }

            if (!iFire)
                iFire = IP_CONST_DAMAGEBONUS_1;

            itemproperty ipFire = ItemPropertyDamageBonus(IP_CONST_DAMAGETYPE_FIRE, iFire);
            IPSafeAddItemProperty(oItem, ipFire, 0.f);
        }
        else
            ActionSpeakString("Only melee weapons benefit from this lever");
    }
    else
        ActionSpeakString("You have no weapon in your main hand");
}


// Checks if 'oItem' is not a ranged weapon and is capable of delivering damage.
int GetIsMelee(object oItem)
{
//  int iType = GetBaseItemType(oItem);
//  return Get2DAString("baseitems", "RangedWeapon", iType) == ""
//      && Get2DAString("baseitems", "DieToRoll", iType) != "";

    return !GetWeaponRanged(oItem)
        && Get2DAString("baseitems", "DieToRoll", GetBaseItemType(oItem)) != "";
}

// Gets the next teir for the DamageBonus.
int GetHigherBonus(int iFire)
{
    switch (iFire)
    {                                       // average:
        case IP_CONST_DAMAGEBONUS_1:        // 1
            return IP_CONST_DAMAGEBONUS_2;

        case IP_CONST_DAMAGEBONUS_2:        // 2
            return IP_CONST_DAMAGEBONUS_1d4;

        case IP_CONST_DAMAGEBONUS_1d4:      // 2.5
        case IP_CONST_DAMAGEBONUS_3:        // 3
            return IP_CONST_DAMAGEBONUS_1d6;

        case IP_CONST_DAMAGEBONUS_1d6:      // 3.5
        case IP_CONST_DAMAGEBONUS_4:        // 4
            return IP_CONST_DAMAGEBONUS_1d8;

        case IP_CONST_DAMAGEBONUS_1d8:      // 4.5
        case IP_CONST_DAMAGEBONUS_5:        // 5
        case IP_CONST_DAMAGEBONUS_2d4:      // 5
            return IP_CONST_DAMAGEBONUS_1d10;

        case IP_CONST_DAMAGEBONUS_1d10:     // 5.5
        case IP_CONST_DAMAGEBONUS_6:        // 6
        case IP_CONST_DAMAGEBONUS_1d12:     // 6.5
        case IP_CONST_DAMAGEBONUS_7:        // 7
            return IP_CONST_DAMAGEBONUS_2d6;

        case IP_CONST_DAMAGEBONUS_2d6:      // 7
        case IP_CONST_DAMAGEBONUS_8:        // 8
        case IP_CONST_DAMAGEBONUS_9:        // 9
            return IP_CONST_DAMAGEBONUS_2d8;

        case IP_CONST_DAMAGEBONUS_2d8:      // 9
        case IP_CONST_DAMAGEBONUS_10:       // 10
        case IP_CONST_DAMAGEBONUS_3d6:      // 10.5
            return IP_CONST_DAMAGEBONUS_2d10;

        case IP_CONST_DAMAGEBONUS_2d10:     // 11
            return IP_CONST_DAMAGEBONUS_2d12;

//      case IP_CONST_DAMAGEBONUS_2d12:     // 13
//      case IP_CONST_DAMAGEBONUS_4d6:      // 14
//      case IP_CONST_DAMAGEBONUS_3d10:     // 16.5
//      case IP_CONST_DAMAGEBONUS_5d6:      // 17.5
//      case IP_CONST_DAMAGEBONUS_4d8:      // 18
//      case IP_CONST_DAMAGEBONUS_3d12:     // 19.5
//      case IP_CONST_DAMAGEBONUS_6d6:      // 21
//      case IP_CONST_DAMAGEBONUS_4d10:     // 22
//      case IP_CONST_DAMAGEBONUS_4d12:     // 26
//      case IP_CONST_DAMAGEBONUS_5d12:     // 32.5
//      case IP_CONST_DAMAGEBONUS_6d12:     // 39
    }

    return 0;
}
1 Like

A musical instrument comes to mind, must be equipped but has no damage properties.

1 Like

I’m going to try these this evening now that I’m off.
Out of curiosity is there a reason why acquiring and supplementing fire bonus damage is so much more complicated?

more complicated than incrementing an Enhancement bonus?

because getter/setter functions are already written for Enhancement bonus in ‘x2_inc_itemprop’
and damagebonus has a subtype (Fire)
and because EB is a simple +1 progression while DamageBonus constants are haphazard

1 Like

Yeh I’m seeing that for sure, learned a lot the last couple days too. Thank you for all the help!
I appreciate it.

2 Likes

So I finally sat down with this tonight.
Last week was hectic and I totally blanked.

I opted to use kevL_s but I’m stuck.
Its giving me a no right bracket on expression at the “while” section of the code.

Why, I’m not sure.
I’ve been reading it over and over so long my eyes are bleeding and i cant figure out why.
If theres any tips lmk.

tip, use Skywing’s Advanced Script Compiler plugin for the toolset:
https://neverwintervault.org/project/nwn2/other/tool/advanced-script-compiler-nwn2

tip2, a compiler error gives a line #
the error is either on that line or at the end of the line immediately above it. (usually…)

Gonna go over it again.
Also I’m using nwn1 with its toolset not nwn2 so I’m not sure how that’ll work.

oh, uh not (as) advisable then

but if you post your version of the script in the Nwn1 forum …

1 Like

Yeh if I cant figure it out myself (I’d like to as I need the practice) I’ll see if they can help me out.
Thanks again for all the help kev.

1 Like