Aller au contenu

Photo

Getting Effect SubTypes ... Is It Possible?


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

#1
Lance Botelle

Lance Botelle
  • Members
  • 1 480 messages

Hi All,

I know we can test to see if a PC has effects like EffectDamageResistance and EffectDamageImmunityIncrease, but is it possible to determine the subcategory protection that this type of effect offers?

E.g. If testing just for a resistance or immunity versus fire? i.e. A sub value of the main effect type.

Thanks in advance,
Lance.



#2
kevL

kevL
  • Members
  • 4 056 messages
hey Lance,
prepare yerself, get a Coffee.

GetEffectSubType(eEffect) gets the "subtype" ( inside a GetFirst/NextEffect(oCreature) loop ). the returns:
int SUBTYPE_MAGICAL       = 8;
int SUBTYPE_SUPERNATURAL  = 16;
int SUBTYPE_EXTRAORDINARY = 24;
.... But i doubt that's quite what you're looking for. Instead, GetEffectInteger() is the cookie. Have a look through the testing script below (it runs from the console on a targetted creature, with an (int)Effect_Type passed in on the command line); the return from GetEffectInteger() is either a constant (scripted or literal) or a reference to a row# in a .2da ...

An effect has one or more 'effect integers' depending on how many are needed for its construction.
 
// 'testeffect'

//
void Tell(string sTell) { SendMessageToPC(GetFirstPC(FALSE), sTell); }

// ___________
// ** MAIN ***
void main(int iEffType)
{
    object oTest = GetPlayerCurrentTarget(OBJECT_SELF);
    if (!GetIsObjectValid(oTest)
        || GetObjectType(oTest) != OBJECT_TYPE_CREATURE)
    {
        oTest = OBJECT_SELF;
    }

    Tell("\nrun ( testeffect ) on " + GetName(oTest));

    effect eEffect = GetFirstEffect(oTest);
    while (GetIsEffectValid(eEffect))
    {
        if (GetEffectType(eEffect) == iEffType)
        {
            Tell(". Creator : "       + GetName(GetEffectCreator(eEffect)) + " ( "
                                          + GetTag(GetEffectCreator(eEffect)) + " )");
            Tell(". Type : "          + IntToString(GetEffectType(eEffect)));
            Tell(". Sub Type : "      + IntToString(GetEffectSubType(eEffect)));
            Tell(". Duration Type : " + IntToString(GetEffectDurationType(eEffect)));
            Tell(". Spell ID : "      + IntToString(GetEffectSpellId(eEffect)));
            Tell(". Integer 0 : "     + IntToString(GetEffectInteger(eEffect, 0)));
            Tell(". Integer 1 : "     + IntToString(GetEffectInteger(eEffect, 1)));
            Tell(". Integer 2 : "     + IntToString(GetEffectInteger(eEffect, 2)));
            Tell(". Integer 3 : "     + IntToString(GetEffectInteger(eEffect, 3)));
            Tell(". Integer 4 : "     + IntToString(GetEffectInteger(eEffect, 4)));
            Tell(". Integer 5 : "     + IntToString(GetEffectInteger(eEffect, 5)));
            Tell(". Integer 6 : "     + IntToString(GetEffectInteger(eEffect, 6)));
            Tell(". Integer 7 : "     + IntToString(GetEffectInteger(eEffect, 7)) + "\n");
        }
        else
        {
            Tell(". found Other Effect : " + IntToString(GetEffectType(eEffect)) + "\n");
        }

        eEffect = GetNextEffect(oTest);
    }
}
here's an example,

apply test effect:
    object oTarget = GetPlayerCurrentTarget(OBJECT_SELF);

    effect eEffect = EffectDamageResistance(DAMAGE_TYPE_ELECTRICAL, 10, 100); // EFFECT_TYPE_DAMAGE_RESISTANCE #1
    ApplyEffectToObject(DURATION_TYPE_PERMANENT, eEffect, oTarget);
and here is the output from

rs testeffect(1)
Creator      : Calen Wyle
Type         : 1   // EFFECT_TYPE_DAMAGE_RESISTANCE
SubType      : 8   // SUBTYPE_MAGICAL
DurationType : 2   // DURATION_TYPE_PERMANENT
Spell ID     : -1  // no spell ID
Integer0     : 128 // DAMAGE_TYPE_ELECTRICAL
Integer1     : 10  // 10 pts resistance
Integer2     : 100 // up to 100 pts total.

Ps. subtypes of itemproperties are what you were thinking of, but subtypes of effects are a different animal

#3
Lance Botelle

Lance Botelle
  • Members
  • 1 480 messages

hey Lance,
prepare yerself, get a Coffee.

GetEffectSubType(eEffect) gets the "subtype" ( inside a GetFirst/NextEffect(oCreature) loop ). the returns:




int SUBTYPE_MAGICAL       = 8;
int SUBTYPE_SUPERNATURAL  = 16;
int SUBTYPE_EXTRAORDINARY = 24;
.... But i doubt that's quite what you're looking for. Instead, GetEffectInteger() is the cookie. Have a look through the testing script below (it runs from the console on a targetted creature, with an (int)Effect_Type passed in on the command line); the return from GetEffectInteger() is either a constant (scripted or literal) or a reference to a row# in a .2da ...

An effect has one or more 'effect integers' depending on how many are needed for its construction.
 
// 'testeffect'

//
void Tell(string sTell) { SendMessageToPC(GetFirstPC(FALSE), sTell); }

// ___________
// ** MAIN ***
void main(int iEffType)
{
    object oTest = GetPlayerCurrentTarget(OBJECT_SELF);
    if (!GetIsObjectValid(oTest)
        || GetObjectType(oTest) != OBJECT_TYPE_CREATURE)
    {
        oTest = OBJECT_SELF;
    }

    Tell("\nrun ( testeffect ) on " + GetName(oTest));

    effect eEffect = GetFirstEffect(oTest);
    while (GetIsEffectValid(eEffect))
    {
        if (GetEffectType(eEffect) == iEffType)
        {
            Tell(". Creator : "       + GetName(GetEffectCreator(eEffect)) + " ( "
                                          + GetTag(GetEffectCreator(eEffect)) + " )");
            Tell(". Type : "          + IntToString(GetEffectType(eEffect)));
            Tell(". Sub Type : "      + IntToString(GetEffectSubType(eEffect)));
            Tell(". Duration Type : " + IntToString(GetEffectDurationType(eEffect)));
            Tell(". Spell ID : "      + IntToString(GetEffectSpellId(eEffect)));
            Tell(". Integer 0 : "     + IntToString(GetEffectInteger(eEffect, 0)));
            Tell(". Integer 1 : "     + IntToString(GetEffectInteger(eEffect, 1)));
            Tell(". Integer 2 : "     + IntToString(GetEffectInteger(eEffect, 2)));
            Tell(". Integer 3 : "     + IntToString(GetEffectInteger(eEffect, 3)));
            Tell(". Integer 4 : "     + IntToString(GetEffectInteger(eEffect, 4)));
            Tell(". Integer 5 : "     + IntToString(GetEffectInteger(eEffect, 5)));
            Tell(". Integer 6 : "     + IntToString(GetEffectInteger(eEffect, 6)));
            Tell(". Integer 7 : "     + IntToString(GetEffectInteger(eEffect, 7)) + "\n");
        }
        else
        {
            Tell(". found Other Effect : " + IntToString(GetEffectType(eEffect)) + "\n");
        }

        eEffect = GetNextEffect(oTest);
    }
}
here's an example,

apply test effect:
    object oTarget = GetPlayerCurrentTarget(OBJECT_SELF);

    effect eEffect = EffectDamageResistance(DAMAGE_TYPE_ELECTRICAL, 10, 100); // EFFECT_TYPE_DAMAGE_RESISTANCE #1
    ApplyEffectToObject(DURATION_TYPE_PERMANENT, eEffect, oTarget);
and here is the output from

rs testeffect(1)
Creator      : Calen Wyle
Type         : 1   // EFFECT_TYPE_DAMAGE_RESISTANCE
SubType      : 8   // SUBTYPE_MAGICAL
DurationType : 2   // DURATION_TYPE_PERMANENT
Spell ID     : -1  // no spell ID
Integer0     : 128 // DAMAGE_TYPE_ELECTRICAL
Integer1     : 10  // 10 pts resistance
Integer2     : 100 // up to 100 pts total.
Ps. subtypes of itemproperties are what you were thinking of, but subtypes of effects are a different animal

 


Hi KevL,

Yes, I believe this is what I was after. i.e. "Subtypes of effects", as in my example. So, thanks for this! (Just me not knowing the correct terminology the engine uses.)

I did not know that "sub types" of effects were referenced with the GetEffectInteger functions. Again, naming could have been better. Now you have pointed it out though, perhaps I will be able to get my head around this some more ... later. ;)

 

Just out of interest, is there a maximum limit to the number of integers recognised? i.e. I see you have 0-7 ... Is that just to get a sample return, or are there some effects that use all 7 integers?

Much thanks again!

Lance.



#4
kevL

kevL
  • Members
  • 4 056 messages
the maximum quantity of effect-integers i've ever come across is about five, at most.

But there -could- be more

#5
Lance Botelle

Lance Botelle
  • Members
  • 1 480 messages
Hi KevL,

OK, I spent a little more time looking at your testing function (which worked great by the way) and now realise that ...

int iDAMTYPE = GetEffectInteger(eEffect, 0);

.... is what I was after .... where iDAMTYPE takes the value of the standard DAMAGE_TYPE_**** values, where DAMAGE_TYPE_FIRE = 256.

This is the exact thing I was looking for, and so will make a quick function up to check for these values, based on this knowledge now.

Many Thanks,
Lance.

#6
kevL

kevL
  • Members
  • 4 056 messages
sweet,

extra: test script for Itemproperties
// 'testip'

//
void Tell(string sTell) { SendMessageToPC(GetFirstPC(FALSE), sTell); }


void main()
{
    Tell("\nrun ( testip ) " + GetName(OBJECT_SELF));

    object oItem = GetPlayerCurrentTarget(OBJECT_SELF);
    if (!GetIsObjectValid(oItem)
        || GetObjectType(oItem) != OBJECT_TYPE_ITEM)
    {
        Tell(". error : An item must be targetted.");
        return;
    }

    itemproperty ipTest = GetFirstItemProperty(oItem);
    while (GetIsItemPropertyValid(ipTest))
    {
        int iType           = GetItemPropertyType(ipTest);
        int iDurType        = GetItemPropertyDurationType(ipTest);
        int iSubType        = GetItemPropertySubType(ipTest);
        int iCostTable      = GetItemPropertyCostTable(ipTest);
        int iCostTableValue = GetItemPropertyCostTableValue(ipTest);
        int iParam1         = GetItemPropertyParam1(ipTest);
        int iParam1Value    = GetItemPropertyParam1Value(ipTest);

        Tell(". Type = " + IntToString(iType));
        Tell(". DurType = " + IntToString(iDurType));
        Tell(". SubType = " + IntToString(iSubType));
        Tell(". CostTable = " + IntToString(iCostTable));
        Tell(". CostTableValue = " + IntToString(iCostTableValue));
        Tell(". Param1 = " + IntToString(iParam1));
        Tell(". Param1Value = " + IntToString(iParam1Value));

        Tell("\n");

        ipTest = GetNextItemProperty(oItem);
    }
}
stash t'in thy toolkit,

#7
Lance Botelle

Lance Botelle
  • Members
  • 1 480 messages

sweet,

extra: test script for Itemproperties






// 'testip'

//
void Tell(string sTell) { SendMessageToPC(GetFirstPC(FALSE), sTell); }


void main()
{
    Tell("\nrun ( testip ) " + GetName(OBJECT_SELF));

    object oItem = GetPlayerCurrentTarget(OBJECT_SELF);
    if (!GetIsObjectValid(oItem)
        || GetObjectType(oItem) != OBJECT_TYPE_ITEM)
    {
        Tell(". error : An item must be targetted.");
        return;
    }

    itemproperty ipTest = GetFirstItemProperty(oItem);
    while (GetIsItemPropertyValid(ipTest))
    {
        int iType           = GetItemPropertyType(ipTest);
        int iDurType        = GetItemPropertyDurationType(ipTest);
        int iSubType        = GetItemPropertySubType(ipTest);
        int iCostTable      = GetItemPropertyCostTable(ipTest);
        int iCostTableValue = GetItemPropertyCostTableValue(ipTest);
        int iParam1         = GetItemPropertyParam1(ipTest);
        int iParam1Value    = GetItemPropertyParam1Value(ipTest);

        Tell(". Type = " + IntToString(iType));
        Tell(". DurType = " + IntToString(iDurType));
        Tell(". SubType = " + IntToString(iSubType));
        Tell(". CostTable = " + IntToString(iCostTable));
        Tell(". CostTableValue = " + IntToString(iCostTableValue));
        Tell(". Param1 = " + IntToString(iParam1));
        Tell(". Param1Value = " + IntToString(iParam1Value));

        Tell("\n");

        ipTest = GetNextItemProperty(oItem);
    }
}
stash t'in thy toolkit,


Twill doest!

By the way, I have *NOT* tested to see if the DAMAGE_TYPE_XXX are *always* at integer 0 (zero) for every effect type. e.g. I don't know if the same integer 0 (zero) is where the DAMAGE_TYPE_XXX is stored when checking for Damage Resistance, as opposed to the Damage Immunity checked for last time.

Which brings me to my next point ... I thought (had hoped) that *items* which bestowed Damage Resistance and/or Damage Immunity, would return the same information when using your "testeffect" function on a PC that wore such an item. It appears, however, that this implementation of said Resistance/Immunity is not returned when tested on the PC wearing the item. Now, I am guessing the item itself will return the values (if tested, which I have not done yet), BUT this means a function to *TEST* for a PC having a certain elemental type of protection on them requires both a test on the PC themselves ... and a cycle through equipped items that may be bestowing such a property.

KEVL: Do you fancy writing such a function to test for such elemental protections on a PC? (I had started to modify your testeffect function for such a purpose, but have currently stopped when I realised this "limitation" when wearing items.)

The idea is that a conditional function (used in a conversation most likely) will return TRUE if a PC has a certain elemental protection vs a certain damage type on them. E.g. A PC wearing a ring with Damage Resistance 10 v FIRE does not return any values when the PC is tested at the moment ... which would with the correct function.

I can (and will) write the function myself if I have to, but notice you knock them out quicker than I do, especially as I am trying to alpha test the module and am trying to keep new scripting to a minimum at the moment.

Anyway, thanks for the extra testing function. DO let me know if you fancy having a go at writing that script/function ... just so I know if I am going to have to prepare it myself. ;)

Cheers,
Lance.

HERE IS WHAT I STARTED WITH (Before I realised items did not return the value on the PC:-
 
// CHECK FOR ANY RESISTANCES VERSUS "DAMAGE TYPE" CONDITION (VIA INTEGER 0):-
// RETURNS TRUE IF TEST SUBJECT HAS *ANY* IMMUNITY OR RESISTANCE TO TESTED DAMAGE TYPE.
// oTESTSUBJECT is the subject to test if they have some sort of resistance or immunity to DAMAGE_TYPE_XXXXX
// DAMAGE_TYPE_VERSUS CAN BE ONE OF THE STANDARD DAMAGE_TYPE_XXXXX VALUES (E.g. FIRE = 256)

int StartingConditional(object oTESTSUBJECT, int DAMAGE_TYPE_VERSUS = 0)
{
	int iFOUND = 0;
	
	effect eEffect = GetFirstEffect(oTESTSUBJECT);
	
    while (GetIsEffectValid(eEffect))
    {
        int iEffType = GetEffectType(eEffect);
		
		// DAMAGE RESISTANCE (1) AND DAMAGE IMMUNITY (44) USE THE SAME INTEGER (0) TO RETURN DAMAGE TYPE
		// NOT TESTED IF EFFECTS RETURN THE SAME VALUE AT INTEGER ZERO
		if (iEffType == 44 || iEffType == 1)
        {
            // GATHER ALL DATA ANYWAY (JUST IN CASE I WILL EXPAND THIS FUNCTION)
			object oCreator = GetEffectCreator(eEffect);
			string sCreatorTag = GetTag(oCreator);
			string sCreatorName = GetName(oCreator);
            
			string sType = IntToString(GetEffectType(eEffect));
            string sSubType = IntToString(GetEffectSubType(eEffect));
            string sDurationType = IntToString(GetEffectDurationType(eEffect));
            string sSpellID = IntToString(GetEffectSpellId(eEffect));
            
			int iInteger0 = GetEffectInteger(eEffect, 0);
            int iInteger1 = GetEffectInteger(eEffect, 1);
            int iInteger2 = GetEffectInteger(eEffect, 2);
            int iInteger3 = GetEffectInteger(eEffect, 3);
            int iInteger4 = GetEffectInteger(eEffect, 4);
            int iInteger5 = GetEffectInteger(eEffect, 5);
            int iInteger6 = GetEffectInteger(eEffect, 6);
            int iInteger7 = GetEffectInteger(eEffect, 7);
			
			if(iInteger0 == DAMAGE_TYPE_VERSUS){iFOUND = 1; break;}
        }

        eEffect = GetNextEffect(oTESTSUBJECT);
    }
	
	return iFOUND;
}


#8
Tchos

Tchos
  • Members
  • 5 042 messages

Twill doest!

 

N.B.: The Early Modern English first person conjugation of "do" is simply "do" (2nd person = "dost", 3rd person = "doth").



#9
Lance Botelle

Lance Botelle
  • Members
  • 1 480 messages

N.B.: The Early Modern English first person conjugation of "do" is simply "do" (2nd person = "dost", 3rd person = "doth").


I was using "Old Althéa" .... ;)

Will post alpha-testing stuff in a bit.

Cheers,
Lance.

#10
kevL

kevL
  • Members
  • 4 056 messages

Twill doest!

By the way, I have *NOT* tested to see if the DAMAGE_TYPE_XXX are *always* at integer 0 (zero) for every effect type. e.g. I don't know if the same integer 0 (zero) is where the DAMAGE_TYPE_XXX is stored when checking for Damage Resistance, as opposed to the Damage Immunity checked for last time.


i doubt it *has* to always be at int_0 (see notes). Further, a check should be made to ensure that the integer really pertains to an increase (or immunity), and not perhaps a vulnerability ... or whatever. ( There is a way to determine these things more logically - ie. by just studying code - but i think that code is buried in some crafting include, and I'm sure it would be more of an exercise than anything practical regardless ....)

note: I did quick tests and it looks the same for both effectTypes.
note2: but am sure, in these cases, it is.

 

Which brings me to my next point ... I thought (had hoped) that *items* which bestowed Damage Resistance and/or Damage Immunity, would return the same information when using your "testeffect" function on a PC that wore such an item. It appears, however, that this implementation of said Resistance/Immunity is not returned when tested on the PC wearing the item. Now, I am guessing the item itself will return the values (if tested, which I have not done yet), BUT this means a function to *TEST* for a PC having a certain elemental type of protection on them requires both a test on the PC themselves ... and a cycle through equipped items that may be bestowing such a property.


... and Feats ?
no, an itemproperty is an "itemproperty" and an effect is an "effect" -- totally different animals.
and a feat is a feat

The GetSpellResistance() function is a very handy one-off that examines all three types, but i don't believe there is anything else like that, such as GetElementalModifier(oTarget)

note: I did quick tests and it looks the same for both Itemproperty types, too.

 

KEVL: Do you fancy writing such a function to test for such elemental protections on a PC? (I had started to modify your testeffect function for such a purpose, but have currently stopped when I realised this "limitation" when wearing items.)

The idea is that a conditional function (used in a conversation most likely) will return TRUE if a PC has a certain elemental protection vs a certain damage type on them. E.g. A PC wearing a ring with Damage Resistance 10 v FIRE does not return any values when the PC is tested at the moment ... which would with the correct function.

I can (and will) write the function myself if I have to, but notice you knock them out quicker than I do, especially as I am trying to alpha test the module and am trying to keep new scripting to a minimum at the moment.


correction: i *post* them quicker. Time spent scratching my head ... doesn't count. /heh

anyway, here's a quick one:
// 'gc_fireresist'
//
// Returns TRUE if oTarget has Resistance/Immunity as an effect or an equipped itemproperty.
// Valid values for iType:
//      0 - magical
//      1 - acid
//      2 - cold
//      3 - divine
//      4 - electrical
//      5 - fire
//      6 - negative
//      7 - positive
//      8 - sonic

int StartingConditional(int iType)
{
    object oTarget = GetPCSpeaker(); // kiss

    // convert iType into constants
    int
        iEfType,
        iIpType;

    switch (iType)
    {
        default:
        case 0:
            iEfType = DAMAGE_TYPE_MAGICAL;
            iIpType = IP_CONST_DAMAGETYPE_MAGICAL;
        break;
        case 1:
            iEfType = DAMAGE_TYPE_ACID;
            iIpType = IP_CONST_DAMAGETYPE_ACID;
        break;
        case 2:
            iEfType = DAMAGE_TYPE_COLD;
            iIpType = IP_CONST_DAMAGETYPE_COLD;
        break;
        case 3:
            iEfType = DAMAGE_TYPE_DIVINE;
            iIpType = IP_CONST_DAMAGETYPE_DIVINE;
        break;
        case 4:
            iEfType = DAMAGE_TYPE_ELECTRICAL;
            iIpType = IP_CONST_DAMAGETYPE_ELECTRICAL;
        break;
        case 5:
            iEfType = DAMAGE_TYPE_FIRE;
            iIpType = IP_CONST_DAMAGETYPE_FIRE;
        break;
        case 6:
            iEfType = DAMAGE_TYPE_NEGATIVE;
            iIpType = IP_CONST_DAMAGETYPE_NEGATIVE;
        break;
        case 7:
            iEfType = DAMAGE_TYPE_POSITIVE;
            iIpType = IP_CONST_DAMAGETYPE_POSITIVE;
        break;
        case 8:
            iEfType = DAMAGE_TYPE_SONIC;
            iIpType = IP_CONST_DAMAGETYPE_SONIC;
        break;
    }


    // check effects
    effect eEffect = GetFirstEffect(oTarget);
    while (GetIsEffectValid(eEffect))
    {
        if ((GetEffectType(eEffect) == EFFECT_TYPE_DAMAGE_RESISTANCE                // EffectDamageResistance()
                || GetEffectType(eEffect) == EFFECT_TYPE_DAMAGE_IMMUNITY_INCREASE)  // EffectDamageImmunityIncrease()
            && GetEffectInteger(eEffect, 0) == iEfType)
        {
            return TRUE;
        }

        eEffect = GetNextEffect(oTarget);
    }

    // check itemproperties equipped
    object oEquip;
    itemproperty ipProp;

    int iSlot;
    for (iSlot = 0; iSlot != NUM_INVENTORY_SLOTS; ++iSlot)
    {
        oEquip = GetItemInSlot(iSlot, oTarget);
        if (GetIsObjectValid(oEquip))
        {
            ipProp = GetFirstItemProperty(oEquip);
            while (GetIsItemPropertyValid(ipProp))
            {
                if ((GetItemPropertyType(ipProp) == ITEM_PROPERTY_DAMAGE_RESISTANCE             // Damage Resistance / ItemPropertyDamageResistance()
                        || GetItemPropertyType(ipProp) == ITEM_PROPERTY_IMMUNITY_DAMAGE_TYPE)   // Immunity:Damage Type / ItemPropertyDamageImmunity()
                    && GetItemPropertySubType(ipProp) == iIpType)
                {
                    return TRUE;
                }

                ipProp = GetNextItemProperty(oEquip);
            }
        }
    }

    return FALSE;
}


#11
Lance Botelle

Lance Botelle
  • Members
  • 1 480 messages

<SNIP>

correction: i *post* them quicker. Time spent scratching my head ... doesn't count. /heh

anyway, here's a quick one:







// 'gc_fireresist'
//
// Returns TRUE if oTarget has Resistance/Immunity as an effect or an equipped itemproperty.
// Valid values for iType:
//      0 - magical
//      1 - acid
//      2 - cold
//      3 - divine
//      4 - electrical
//      5 - fire
//      6 - negative
//      7 - positive
//      8 - sonic

int StartingConditional(int iType)
{
    object oTarget = GetPCSpeaker(); // kiss

    // convert iType into constants
    int
        iEfType,
        iIpType;

    switch (iType)
    {
        default:
        case 0:
            iEfType = DAMAGE_TYPE_MAGICAL;
            iIpType = IP_CONST_DAMAGETYPE_MAGICAL;
        break;
        case 1:
            iEfType = DAMAGE_TYPE_ACID;
            iIpType = IP_CONST_DAMAGETYPE_ACID;
        break;
        case 2:
            iEfType = DAMAGE_TYPE_COLD;
            iIpType = IP_CONST_DAMAGETYPE_COLD;
        break;
        case 3:
            iEfType = DAMAGE_TYPE_DIVINE;
            iIpType = IP_CONST_DAMAGETYPE_DIVINE;
        break;
        case 4:
            iEfType = DAMAGE_TYPE_ELECTRICAL;
            iIpType = IP_CONST_DAMAGETYPE_ELECTRICAL;
        break;
        case 5:
            iEfType = DAMAGE_TYPE_FIRE;
            iIpType = IP_CONST_DAMAGETYPE_FIRE;
        break;
        case 6:
            iEfType = DAMAGE_TYPE_NEGATIVE;
            iIpType = IP_CONST_DAMAGETYPE_NEGATIVE;
        break;
        case 7:
            iEfType = DAMAGE_TYPE_POSITIVE;
            iIpType = IP_CONST_DAMAGETYPE_POSITIVE;
        break;
        case 8:
            iEfType = DAMAGE_TYPE_SONIC;
            iIpType = IP_CONST_DAMAGETYPE_SONIC;
        break;
    }


    // check effects
    effect eEffect = GetFirstEffect(oTarget);
    while (GetIsEffectValid(eEffect))
    {
        if ((GetEffectType(eEffect) == EFFECT_TYPE_DAMAGE_RESISTANCE                // EffectDamageResistance()
                || GetEffectType(eEffect) == EFFECT_TYPE_DAMAGE_IMMUNITY_INCREASE)  // EffectDamageImmunityIncrease()
            && GetEffectInteger(eEffect, 0) == iEfType)
        {
            return TRUE;
        }

        eEffect = GetNextEffect(oTarget);
    }

    // check itemproperties equipped
    object oEquip;
    itemproperty ipProp;

    int iSlot;
    for (iSlot = 0; iSlot != NUM_INVENTORY_SLOTS; ++iSlot)
    {
        oEquip = GetItemInSlot(iSlot, oTarget);
        if (GetIsObjectValid(oEquip))
        {
            ipProp = GetFirstItemProperty(oEquip);
            while (GetIsItemPropertyValid(ipProp))
            {
                if ((GetItemPropertyType(ipProp) == ITEM_PROPERTY_DAMAGE_RESISTANCE             // Damage Resistance / ItemPropertyDamageResistance()
                        || GetItemPropertyType(ipProp) == ITEM_PROPERTY_IMMUNITY_DAMAGE_TYPE)   // Immunity:Damage Type / ItemPropertyDamageImmunity()
                    && GetItemPropertySubType(ipProp) == iIpType)
                {
                    return TRUE;
                }

                ipProp = GetNextItemProperty(oEquip);
            }
        }
    }

    return FALSE;
}


Hi KevL,

What a star! (I reckon posting them sooner is good too. ;) )

By the way, I reckon this will be a very handy function. Useful for the builder to be able to test for such things I reckon!

Thanks for this, I will give it a go in a while. I have to have a small op/procedure at the hospital now, but see how I feel when I get back.

I look forward to giving it a try though ... As you probably guessed, I do already have a place I need to use this.

Many Thanks,
Lance.

PS. Are there any feats that allow damage resistance or immunity then? (Just want to make sure I have them covered.) And more to the point, I suppose (if there are any) it all depends upon how the feat applies the resistance or immunity. After all, I am unaware of any other means of inferring resistances//immunities outside of the two functions we are already testing for. E.g. Even spells (like Resist ELements) uses one of the functions the testing script now checks. i.e. I think that it may only have been the items that give the protection that was over and above the standard tests we would need to check for regarding such resistances/immunities.

#12
kevL

kevL
  • Members
  • 4 056 messages
there may be some feat-resistances that are hardcoded

http://nwn2.wikia.com/wiki/Feat_List(apparently incomplete)

from The stock list at the wiki ... look for spellscripts for Celestial Resistance, Infernal Resistance, Fiendish Resistance, Divine Resistance, etc. I think it'd be better to look through your/ Althea's Feat.2da

Those that don't have a SPELLID, to apply an effect, are hard-coded and should be checked for under the appropriate cases of the switch(), exiting with an early return TRUE

It looks like the Epic Energy Resistances are all hardcoded. If you write up a list of feats that should be checked for, along with the type of energy they resist, i can likely find a decent place in the script ....


/stay well,
my advice: drink water

#13
Lance Botelle

Lance Botelle
  • Members
  • 1 480 messages

there may be some feat-resistances that are hardcoded

http://nwn2.wikia.com/wiki/Feat_List(apparently incomplete)

from The stock list at the wiki ... look for spellscripts for Celestial Resistance, Infernal Resistance, Fiendish Resistance, Divine Resistance, etc. I think it'd be better to look through your/ Althea's Feat.2da

Those that don't have a SPELLID, to apply an effect, are hard-coded and should be checked for under the appropriate cases of the switch(), exiting with an early return TRUE

It looks like the Epic Energy Resistances are all hardcoded. If you write up a list of feats that should be checked for, along with the type of energy they resist, i can likely find a decent place in the script ....


/stay well,
my advice: drink water


Hi KevL,

First, I have certainly been drinking water ... feel a bit better than I did earlier. ;)

You have probably already guessed the feats that would need checking ... basically the elemental protection types, so any that you feel would be worth adding to your function, I would certainly be happy with that. :)

My Althéa feat.2da is the same as the OC 2da, but with lines added later on if I recall correctly. So, any code you are able to add, should work fine with my existing 2da.

As you can probably guess, I am taking it a bit easier today because of the procedure. It went smoothly enough; I just take longer to recover than most due to suffering from M.E.

I'll catch you later. If you do get time to update your script/function, I will of course, grab it to use. :)

Many Thanks,
Lance.

#14
kevL

kevL
  • Members
  • 4 056 messages
and just as i get my ports working the way I want,

oxc_150713134812_640px.png


here's a longer one:
// 'gc_fireresist'
//
// Returns TRUE if oTarget has Resistance/Immunity as an effect or an equipped itemproperty.
// Valid values for iType:
//      0 - magical (default)
//      1 - acid
//      2 - cold
//      3 - divine
//      4 - electrical
//      5 - fire
//      6 - negative
//      7 - positive
//      8 - sonic
//
// 2015 jul 13
//  - also tests for feats.

// helper
int hasFeat(object oTarget, int iType);


//____________
// * MAIN * //
int StartingConditional(int iType)
{
    object oTarget = GetPCSpeaker(); // kiss

    // check feats
    if (hasFeat(oTarget, iType))
        return TRUE;

    // convert iType into constants
    int
        iEfType,
        iIpType;

    switch (iType)
    {
        default:
        case 0:
            iEfType = DAMAGE_TYPE_MAGICAL;
            iIpType = IP_CONST_DAMAGETYPE_MAGICAL;
        break;
        case 1:
            iEfType = DAMAGE_TYPE_ACID;
            iIpType = IP_CONST_DAMAGETYPE_ACID;
        break;
        case 2:
            iEfType = DAMAGE_TYPE_COLD;
            iIpType = IP_CONST_DAMAGETYPE_COLD;
        break;
        case 3:
            iEfType = DAMAGE_TYPE_DIVINE;
            iIpType = IP_CONST_DAMAGETYPE_DIVINE;
        break;
        case 4:
            iEfType = DAMAGE_TYPE_ELECTRICAL;
            iIpType = IP_CONST_DAMAGETYPE_ELECTRICAL;
        break;
        case 5:
            iEfType = DAMAGE_TYPE_FIRE;
            iIpType = IP_CONST_DAMAGETYPE_FIRE;
        break;
        case 6:
            iEfType = DAMAGE_TYPE_NEGATIVE;
            iIpType = IP_CONST_DAMAGETYPE_NEGATIVE;
        break;
        case 7:
            iEfType = DAMAGE_TYPE_POSITIVE;
            iIpType = IP_CONST_DAMAGETYPE_POSITIVE;
        break;
        case 8:
            iEfType = DAMAGE_TYPE_SONIC;
            iIpType = IP_CONST_DAMAGETYPE_SONIC;
        break;
    }


    // check effects
    effect eEffect = GetFirstEffect(oTarget);
    while (GetIsEffectValid(eEffect))
    {
        if (GetEffectInteger(eEffect, 0) == iEfType
            && (GetEffectType(eEffect) == EFFECT_TYPE_DAMAGE_RESISTANCE             // EffectDamageResistance()
                || GetEffectType(eEffect) == EFFECT_TYPE_DAMAGE_IMMUNITY_INCREASE)) // EffectDamageImmunityIncrease()
        {
            return TRUE;
        }

        eEffect = GetNextEffect(oTarget);
    }

    // check itemproperties equipped
    object oEquip;
    itemproperty ipProp;

    int iSlot;
    for (iSlot = 0; iSlot != NUM_INVENTORY_SLOTS; ++iSlot)
    {
        oEquip = GetItemInSlot(iSlot, oTarget);
        if (GetIsObjectValid(oEquip))
        {
            ipProp = GetFirstItemProperty(oEquip);
            while (GetIsItemPropertyValid(ipProp))
            {
                if (GetItemPropertySubType(ipProp) == iIpType
                    && (GetItemPropertyType(ipProp) == ITEM_PROPERTY_DAMAGE_RESISTANCE          // Damage Resistance / ItemPropertyDamageResistance()
                        || GetItemPropertyType(ipProp) == ITEM_PROPERTY_IMMUNITY_DAMAGE_TYPE))  // Immunity:Damage Type / ItemPropertyDamageImmunity()
                {
                    return TRUE;
                }

                ipProp = GetNextItemProperty(oEquip);
            }
        }
    }

    return FALSE;
}


// helper
int hasFeat(object oTarget, int iType)
{
    int iFeat;

    switch (iType)
    {
//      case 0: // magical
//          if (GetHasFeat(int nFeat, oTarget, TRUE))
//              return TRUE;
//      break;

        case 1: // acid
            if (GetHasFeat(FEAT_AASIMAR_RESISTANCE, oTarget, TRUE)
                || GetHasFeat(1785, oTarget, TRUE)  // FEAT_WARLOCK_ENERGY_RESISTANCE_ACID
                || GetHasFeat(1790, oTarget, TRUE)  // FEAT_WARLOCK_IMPROVED_ENERGY_RESISTANCE_ACID
                || GetHasFeat(1869, oTarget, TRUE)  // FEAT_EARTH_GENASI_RESISTANCE
                || GetHasFeat(1943, oTarget, TRUE)  // FEAT_WARLOCK_EPIC_ENERGY_RESISTANCE_ACID
                || GetHasFeat(2082, oTarget, TRUE)  // FEAT_FAVORED_SOUL_ENERGY_RESISTANCE_ACID
                || GetHasFeat(2114, oTarget, TRUE)  // FEAT_RACIAL_RESIST_ACID_10
                || GetHasFeat(2189, oTarget, TRUE)) // FEAT_FIENDISH_RESISTANCE
            {
                return TRUE;
            }

            iFeat = FEAT_EPIC_ENERGY_RESISTANCE_ACID_1;
            while (iFeat <= FEAT_EPIC_ENERGY_RESISTANCE_ACID_10)
            {
                if (GetHasFeat(iFeat, oTarget, TRUE))
                    return TRUE;

                ++iFeat;
            }
        break;

        case 2: // cold
            if (GetHasFeat(FEAT_AASIMAR_RESISTANCE, oTarget, TRUE)
                || GetHasFeat(FEAT_TIEFLING_RESISTANCE, oTarget, TRUE)
                || GetHasFeat(FEAT_DIVINE_RESISTANCE, oTarget, TRUE)
                || GetHasFeat(1786, oTarget, TRUE)  // FEAT_WARLOCK_ENERGY_RESISTANCE_COLD
                || GetHasFeat(1791, oTarget, TRUE)  // FEAT_WARLOCK_IMPROVED_ENERGY_RESISTANCE_COLD
                || GetHasFeat(1871, oTarget, TRUE)  // FEAT_WATER_GENASI_RESISTANCE
                || GetHasFeat(1944, oTarget, TRUE)  // FEAT_WARLOCK_EPIC_ENERGY_RESISTANCE_COLD
                || GetHasFeat(2083, oTarget, TRUE)  // FEAT_FAVORED_SOUL_ENERGY_RESISTANCE_COLD
                || GetHasFeat(2115, oTarget, TRUE)) // FEAT_RACIAL_RESIST_COLD_10
            {
                return TRUE;
            }

            iFeat = FEAT_EPIC_ENERGY_RESISTANCE_COLD_1;
            while (iFeat <= FEAT_EPIC_ENERGY_RESISTANCE_COLD_10)
            {
                if (GetHasFeat(iFeat, oTarget, TRUE))
                    return TRUE;

                ++iFeat;
            }
        break;

//      case 3: // divine
//          if (GetHasFeat(int nFeat, oTarget, TRUE))
//              return TRUE;
//      break;

        case 4: // electrical
            if (GetHasFeat(FEAT_AASIMAR_RESISTANCE, oTarget, TRUE)
                || GetHasFeat(FEAT_TIEFLING_RESISTANCE, oTarget, TRUE)
                || GetHasFeat(FEAT_DIVINE_RESISTANCE, oTarget, TRUE)
                || GetHasFeat(1787, oTarget, TRUE)  // FEAT_WARLOCK_ENERGY_RESISTANCE_ELECTRICAL
                || GetHasFeat(1792, oTarget, TRUE)  // FEAT_WARLOCK_IMPROVED_ENERGY_RESISTANCE_ELECTRICAL
                || GetHasFeat(1868, oTarget, TRUE)  // FEAT_AIR_GENASI_RESISTANCE
                || GetHasFeat(1945, oTarget, TRUE)  // FEAT_WARLOCK_EPIC_ENERGY_RESISTANCE_ELECTRICAL
                || GetHasFeat(2041, oTarget, TRUE)  // FEAT_STORMLORD_RESISTANCE_TO_ELECTRICITY_5
                || GetHasFeat(2042, oTarget, TRUE)  // FEAT_STORMLORD_RESISTANCE_TO_ELECTRICITY_10
                || GetHasFeat(2043, oTarget, TRUE)  // FEAT_STORMLORD_RESISTANCE_TO_ELECTRICITY_15
                || GetHasFeat(2044, oTarget, TRUE)  // FEAT_STORMLORD_IMMUNITY_TO_ELECTRICITY
                || GetHasFeat(2084, oTarget, TRUE)  // FEAT_FAVORED_SOUL_ENERGY_RESISTANCE_ELECTRICAL
                || GetHasFeat(2116, oTarget, TRUE)) // FEAT_RACIAL_RESIST_ELECTRICITY_10
            {
                return TRUE;
            }

            iFeat = FEAT_EPIC_ENERGY_RESISTANCE_ELECTRICAL_1;
            while (iFeat <= FEAT_EPIC_ENERGY_RESISTANCE_ELECTRICAL_10)
            {
                if (GetHasFeat(iFeat, oTarget, TRUE))
                    return TRUE;

                ++iFeat;
            }
        break;

        case 5: // fire
            if (GetHasFeat(FEAT_TIEFLING_RESISTANCE, oTarget, TRUE)
                || GetHasFeat(FEAT_DIVINE_RESISTANCE, oTarget, TRUE)
                || GetHasFeat(1788, oTarget, TRUE)  // FEAT_WARLOCK_ENERGY_RESISTANCE_FIRE
                || GetHasFeat(1793, oTarget, TRUE)  // FEAT_WARLOCK_IMPROVED_ENERGY_RESISTANCE_FIRE
                || GetHasFeat(1870, oTarget, TRUE)  // FEAT_FIRE_GENASI_RESISTANCE
                || GetHasFeat(1946, oTarget, TRUE)  // FEAT_WARLOCK_EPIC_ENERGY_RESISTANCE_FIRE
                || GetHasFeat(2085, oTarget, TRUE)  // FEAT_FAVORED_SOUL_ENERGY_RESISTANCE_FIRE
                || GetHasFeat(2189, oTarget, TRUE)) // FEAT_FIENDISH_RESISTANCE
            {
                return TRUE;
            }

            iFeat = FEAT_EPIC_ENERGY_RESISTANCE_FIRE_1;
            while (iFeat <= FEAT_EPIC_ENERGY_RESISTANCE_FIRE_10)
            {
                if (GetHasFeat(iFeat, oTarget, TRUE))
                    return TRUE;

                ++iFeat;
            }
        break;

//      case 6: // negative
//          if (GetHasFeat(int nFeat, oTarget, TRUE))
//              return TRUE;
//      break;

//      case 7: // positive
//          if (GetHasFeat(int nFeat, oTarget, TRUE))
//              return TRUE;
//      break;

        case 8: // sonic
            if (GetHasFeat(1789, oTarget, TRUE)     // FEAT_WARLOCK_ENERGY_RESISTANCE_SONIC
                || GetHasFeat(1794, oTarget, TRUE)  // FEAT_WARLOCK_IMPROVED_ENERGY_RESISTANCE_SONIC
                || GetHasFeat(1947, oTarget, TRUE)  // FEAT_WARLOCK_EPIC_ENERGY_RESISTANCE_SONIC
                || GetHasFeat(2086, oTarget, TRUE)) // FEAT_FAVORED_SOUL_ENERGY_RESISTANCE_SONIC
            {
                return TRUE;
            }

            iFeat = FEAT_EPIC_ENERGY_RESISTANCE_SONIC_1;
            while (iFeat <= FEAT_EPIC_ENERGY_RESISTANCE_SONIC_10)
            {
                if (GetHasFeat(iFeat, oTarget, TRUE))
                    return TRUE;

                ++iFeat;
            }
        break;
    }

    return FALSE;
}


#15
Lance Botelle

Lance Botelle
  • Members
  • 1 480 messages

and just as i get my ports working the way I want,

oxc_150713134812_640px.png


here's a longer one:




// 'gc_fireresist'
//
// Returns TRUE if oTarget has Resistance/Immunity as an effect or an equipped itemproperty.
// Valid values for iType:
//      0 - magical (default)
//      1 - acid
//      2 - cold
//      3 - divine
//      4 - electrical
//      5 - fire
//      6 - negative
//      7 - positive
//      8 - sonic
//
// 2015 jul 13
//  - also tests for feats.

// helper
int hasFeat(object oTarget, int iType);


//____________
// * MAIN * //
int StartingConditional(int iType)
{
    object oTarget = GetPCSpeaker(); // kiss

    // check feats
    if (hasFeat(oTarget, iType))
        return TRUE;

    // convert iType into constants
    int
        iEfType,
        iIpType;

    switch (iType)
    {
        default:
        case 0:
            iEfType = DAMAGE_TYPE_MAGICAL;
            iIpType = IP_CONST_DAMAGETYPE_MAGICAL;
        break;
        case 1:
            iEfType = DAMAGE_TYPE_ACID;
            iIpType = IP_CONST_DAMAGETYPE_ACID;
        break;
        case 2:
            iEfType = DAMAGE_TYPE_COLD;
            iIpType = IP_CONST_DAMAGETYPE_COLD;
        break;
        case 3:
            iEfType = DAMAGE_TYPE_DIVINE;
            iIpType = IP_CONST_DAMAGETYPE_DIVINE;
        break;
        case 4:
            iEfType = DAMAGE_TYPE_ELECTRICAL;
            iIpType = IP_CONST_DAMAGETYPE_ELECTRICAL;
        break;
        case 5:
            iEfType = DAMAGE_TYPE_FIRE;
            iIpType = IP_CONST_DAMAGETYPE_FIRE;
        break;
        case 6:
            iEfType = DAMAGE_TYPE_NEGATIVE;
            iIpType = IP_CONST_DAMAGETYPE_NEGATIVE;
        break;
        case 7:
            iEfType = DAMAGE_TYPE_POSITIVE;
            iIpType = IP_CONST_DAMAGETYPE_POSITIVE;
        break;
        case 8:
            iEfType = DAMAGE_TYPE_SONIC;
            iIpType = IP_CONST_DAMAGETYPE_SONIC;
        break;
    }


    // check effects
    effect eEffect = GetFirstEffect(oTarget);
    while (GetIsEffectValid(eEffect))
    {
        if (GetEffectInteger(eEffect, 0) == iEfType
            && (GetEffectType(eEffect) == EFFECT_TYPE_DAMAGE_RESISTANCE             // EffectDamageResistance()
                || GetEffectType(eEffect) == EFFECT_TYPE_DAMAGE_IMMUNITY_INCREASE)) // EffectDamageImmunityIncrease()
        {
            return TRUE;
        }

        eEffect = GetNextEffect(oTarget);
    }

    // check itemproperties equipped
    object oEquip;
    itemproperty ipProp;

    int iSlot;
    for (iSlot = 0; iSlot != NUM_INVENTORY_SLOTS; ++iSlot)
    {
        oEquip = GetItemInSlot(iSlot, oTarget);
        if (GetIsObjectValid(oEquip))
        {
            ipProp = GetFirstItemProperty(oEquip);
            while (GetIsItemPropertyValid(ipProp))
            {
                if (GetItemPropertySubType(ipProp) == iIpType
                    && (GetItemPropertyType(ipProp) == ITEM_PROPERTY_DAMAGE_RESISTANCE          // Damage Resistance / ItemPropertyDamageResistance()
                        || GetItemPropertyType(ipProp) == ITEM_PROPERTY_IMMUNITY_DAMAGE_TYPE))  // Immunity:Damage Type / ItemPropertyDamageImmunity()
                {
                    return TRUE;
                }

                ipProp = GetNextItemProperty(oEquip);
            }
        }
    }

    return FALSE;
}


// helper
int hasFeat(object oTarget, int iType)
{
    int iFeat;

    switch (iType)
    {
//      case 0: // magical
//          if (GetHasFeat(int nFeat, oTarget, TRUE))
//              return TRUE;
//      break;

        case 1: // acid
            if (GetHasFeat(FEAT_AASIMAR_RESISTANCE, oTarget, TRUE)
                || GetHasFeat(1785, oTarget, TRUE)  // FEAT_WARLOCK_ENERGY_RESISTANCE_ACID
                || GetHasFeat(1790, oTarget, TRUE)  // FEAT_WARLOCK_IMPROVED_ENERGY_RESISTANCE_ACID
                || GetHasFeat(1869, oTarget, TRUE)  // FEAT_EARTH_GENASI_RESISTANCE
                || GetHasFeat(1943, oTarget, TRUE)  // FEAT_WARLOCK_EPIC_ENERGY_RESISTANCE_ACID
                || GetHasFeat(2082, oTarget, TRUE)  // FEAT_FAVORED_SOUL_ENERGY_RESISTANCE_ACID
                || GetHasFeat(2114, oTarget, TRUE)  // FEAT_RACIAL_RESIST_ACID_10
                || GetHasFeat(2189, oTarget, TRUE)) // FEAT_FIENDISH_RESISTANCE
            {
                return TRUE;
            }

            iFeat = FEAT_EPIC_ENERGY_RESISTANCE_ACID_1;
            while (iFeat <= FEAT_EPIC_ENERGY_RESISTANCE_ACID_10)
            {
                if (GetHasFeat(iFeat, oTarget, TRUE))
                    return TRUE;

                ++iFeat;
            }
        break;

        case 2: // cold
            if (GetHasFeat(FEAT_AASIMAR_RESISTANCE, oTarget, TRUE)
                || GetHasFeat(FEAT_TIEFLING_RESISTANCE, oTarget, TRUE)
                || GetHasFeat(FEAT_DIVINE_RESISTANCE, oTarget, TRUE)
                || GetHasFeat(1786, oTarget, TRUE)  // FEAT_WARLOCK_ENERGY_RESISTANCE_COLD
                || GetHasFeat(1791, oTarget, TRUE)  // FEAT_WARLOCK_IMPROVED_ENERGY_RESISTANCE_COLD
                || GetHasFeat(1871, oTarget, TRUE)  // FEAT_WATER_GENASI_RESISTANCE
                || GetHasFeat(1944, oTarget, TRUE)  // FEAT_WARLOCK_EPIC_ENERGY_RESISTANCE_COLD
                || GetHasFeat(2083, oTarget, TRUE)  // FEAT_FAVORED_SOUL_ENERGY_RESISTANCE_COLD
                || GetHasFeat(2115, oTarget, TRUE)) // FEAT_RACIAL_RESIST_COLD_10
            {
                return TRUE;
            }

            iFeat = FEAT_EPIC_ENERGY_RESISTANCE_COLD_1;
            while (iFeat <= FEAT_EPIC_ENERGY_RESISTANCE_COLD_10)
            {
                if (GetHasFeat(iFeat, oTarget, TRUE))
                    return TRUE;

                ++iFeat;
            }
        break;

//      case 3: // divine
//          if (GetHasFeat(int nFeat, oTarget, TRUE))
//              return TRUE;
//      break;

        case 4: // electrical
            if (GetHasFeat(FEAT_AASIMAR_RESISTANCE, oTarget, TRUE)
                || GetHasFeat(FEAT_TIEFLING_RESISTANCE, oTarget, TRUE)
                || GetHasFeat(FEAT_DIVINE_RESISTANCE, oTarget, TRUE)
                || GetHasFeat(1787, oTarget, TRUE)  // FEAT_WARLOCK_ENERGY_RESISTANCE_ELECTRICAL
                || GetHasFeat(1792, oTarget, TRUE)  // FEAT_WARLOCK_IMPROVED_ENERGY_RESISTANCE_ELECTRICAL
                || GetHasFeat(1868, oTarget, TRUE)  // FEAT_AIR_GENASI_RESISTANCE
                || GetHasFeat(1945, oTarget, TRUE)  // FEAT_WARLOCK_EPIC_ENERGY_RESISTANCE_ELECTRICAL
                || GetHasFeat(2041, oTarget, TRUE)  // FEAT_STORMLORD_RESISTANCE_TO_ELECTRICITY_5
                || GetHasFeat(2042, oTarget, TRUE)  // FEAT_STORMLORD_RESISTANCE_TO_ELECTRICITY_10
                || GetHasFeat(2043, oTarget, TRUE)  // FEAT_STORMLORD_RESISTANCE_TO_ELECTRICITY_15
                || GetHasFeat(2044, oTarget, TRUE)  // FEAT_STORMLORD_IMMUNITY_TO_ELECTRICITY
                || GetHasFeat(2084, oTarget, TRUE)  // FEAT_FAVORED_SOUL_ENERGY_RESISTANCE_ELECTRICAL
                || GetHasFeat(2116, oTarget, TRUE)) // FEAT_RACIAL_RESIST_ELECTRICITY_10
            {
                return TRUE;
            }

            iFeat = FEAT_EPIC_ENERGY_RESISTANCE_ELECTRICAL_1;
            while (iFeat <= FEAT_EPIC_ENERGY_RESISTANCE_ELECTRICAL_10)
            {
                if (GetHasFeat(iFeat, oTarget, TRUE))
                    return TRUE;

                ++iFeat;
            }
        break;

        case 5: // fire
            if (GetHasFeat(FEAT_TIEFLING_RESISTANCE, oTarget, TRUE)
                || GetHasFeat(FEAT_DIVINE_RESISTANCE, oTarget, TRUE)
                || GetHasFeat(1788, oTarget, TRUE)  // FEAT_WARLOCK_ENERGY_RESISTANCE_FIRE
                || GetHasFeat(1793, oTarget, TRUE)  // FEAT_WARLOCK_IMPROVED_ENERGY_RESISTANCE_FIRE
                || GetHasFeat(1870, oTarget, TRUE)  // FEAT_FIRE_GENASI_RESISTANCE
                || GetHasFeat(1946, oTarget, TRUE)  // FEAT_WARLOCK_EPIC_ENERGY_RESISTANCE_FIRE
                || GetHasFeat(2085, oTarget, TRUE)  // FEAT_FAVORED_SOUL_ENERGY_RESISTANCE_FIRE
                || GetHasFeat(2189, oTarget, TRUE)) // FEAT_FIENDISH_RESISTANCE
            {
                return TRUE;
            }

            iFeat = FEAT_EPIC_ENERGY_RESISTANCE_FIRE_1;
            while (iFeat <= FEAT_EPIC_ENERGY_RESISTANCE_FIRE_10)
            {
                if (GetHasFeat(iFeat, oTarget, TRUE))
                    return TRUE;

                ++iFeat;
            }
        break;

//      case 6: // negative
//          if (GetHasFeat(int nFeat, oTarget, TRUE))
//              return TRUE;
//      break;

//      case 7: // positive
//          if (GetHasFeat(int nFeat, oTarget, TRUE))
//              return TRUE;
//      break;

        case 8: // sonic
            if (GetHasFeat(1789, oTarget, TRUE)     // FEAT_WARLOCK_ENERGY_RESISTANCE_SONIC
                || GetHasFeat(1794, oTarget, TRUE)  // FEAT_WARLOCK_IMPROVED_ENERGY_RESISTANCE_SONIC
                || GetHasFeat(1947, oTarget, TRUE)  // FEAT_WARLOCK_EPIC_ENERGY_RESISTANCE_SONIC
                || GetHasFeat(2086, oTarget, TRUE)) // FEAT_FAVORED_SOUL_ENERGY_RESISTANCE_SONIC
            {
                return TRUE;
            }

            iFeat = FEAT_EPIC_ENERGY_RESISTANCE_SONIC_1;
            while (iFeat <= FEAT_EPIC_ENERGY_RESISTANCE_SONIC_10)
            {
                if (GetHasFeat(iFeat, oTarget, TRUE))
                    return TRUE;

                ++iFeat;
            }
        break;
    }

    return FALSE;
}

Hi KevL,

Many thanks!

This will save me a lot of time, which is much appreciated. Thank you for your time and patience looking into this!

I am sure there sill be quite a few who find this helpful. At least, I would be surprised if it wasn't put to some use by others.

EDIT: I had absolutely no idea that there were so many feats offering elemental protection of sorts! :o

PORTS: Is this a game you are playing then? :)

Cheers,
Lance.



#16
kevL

kevL
  • Members
  • 4 056 messages
"ports" is what I call the xcom interception windows: viewports.

the sourcecode, and builds, are available through Openxcom.org (anyone interested still needs a legit copy of the original game, though, for the sound & graphic resources etc.)


anyway, keep your eyes open for more feats -- i think I got most of them but, odds are, I missed some.

#17
Lance Botelle

Lance Botelle
  • Members
  • 1 480 messages

"ports" is what I call the xcom interception windows: viewports.

the sourcecode, and builds, are available through Openxcom.org (anyone interested still needs a legit copy of the original game, though, for the sound & graphic resources etc.)


anyway, keep your eyes open for more feats -- i think I got most of them but, odds are, I missed some.


Hi KevL,

OK, I'll let you know if I see any others, but I doubt I will. After all, I had no idea of that lot!

Cheers,
Lance.