Damage type - every sort of magic

I’m trying to come up with a script that checks if a creature has been damaged by any sort of magic by the PC. My guts say that this should be easy to check with some sort of while or for loop (and I’m not particularly good with those unfortunately). My first thought was to do a function like this:

if(GetDamageDealtByType(DAMAGE_TYPE_MAGICAL) >0)
		{
			
		SetGlobalInt("PCIsMagicUser",1);
		
		}

But when looking into it, damage type magical isn’t the same as every kind of spell it seems to the the NWN2Wiki. I could do a very convoluted function going through every type of magic type damge like electrical, divine and so forth, but I reckon this could be done in a very slick and compact way. Is there anyone of you script masters out there who could help me with this perhaps? Thanks!

GetDamageDealtByType() should be used only in the OnDamaged handler …

GetDamageDealtByType(int) - NWN Lexicon

Is that okay? Can you describe what you want to happen ?

Yes, I thought to use it on OnDamaged on a creature. If the creature is attacked by some sort of magic, then a global int is set.

I tried with looking at a script by travus but I couldn’t quite work it out. I thought something along the lines like this. (I know this doesn’t work but maybe one could modify it to make it work…or something):

	int n = GetDamageDealtByType();
		
		for (n = DAMAGE_TYPE_MAGICAL; n <= DAMAGE_TYPE_SONIC; n++)
		{
		
			SetGlobalInt("PCIsMagicUser",1);
		
		}

Do you really want to know if creature is damaged by a PC(party) magic-user ?

because things other than magic-users can (and will) deal damage by type …

// Gets if a given object is PC-faction and has arcane spells.
int GetIsPartyMagicUser(object oCreature)
{
	if (GetObjectType(oCreature) == OBJECT_TYPE_CREATURE
		&& GetIsObjectValid(GetFactionLeader(oCreature)))
	{
		int pos = 1;
		do
		{
			int iClass = GetClassByPosition(pos, oCreature);

			if (iClass == CLASS_TYPE_INVALID)
				break;

			if (Get2DAString("classes", "HasArcane", iClass) == "1")
				return TRUE;
		}
		while (++pos != 5);
	}

	return FALSE;
}

ps. But i think maybe use the OnSpellCastAt event … depends if the creature must be damaged before the global_int gets set

Yes, maybe I should use that instead.

I understand what you’re saying here, kevL_s, and even though I think in this situation there won’t be any magic weapons doing damage…Well, still, maybe I should use OnSpellCastAt instead.

If I modify the nw_c2_defaultb like this and save under another name, and put it on OnSpellCastAt on the creature, would that work?

//::///////////////////////////////////////////////
//:: Default: On Spell Cast At
//:: NW_C2_DEFAULTB
//:: Copyright (c) 2001 Bioware Corp.
//:://////////////////////////////////////////////
/*
    This determines if the spell just cast at the
    target is harmful or not.
*/
//:://////////////////////////////////////////////
//:: Created By: Preston Watamaniuk
//:: Created On: Dec 6, 2001
//:://////////////////////////////////////////////

#include "hench_i0_ai"
#include "ginc_behavior"


void main()
{

    int iFocused = GetIsFocused();

	// spell cast at me so no longer partially focused
	if (iFocused == FOCUSED_PARTIAL)
	{
		SetLocalInt(OBJECT_SELF, VAR_FOCUSED, FOCUSED_STANDARD); // no longer focused
	}

    if (iFocused == FOCUSED_FULL)
	{
        // remain focused
    }
    else if(GetLastSpellHarmful())
    {
			object oPC = GetFirstPC();
			object oCaster = GetLastSpellCaster();
       // ------------------------------------------------------------------
        // If I was hurt by someone in my own faction
        // Then clear any hostile feelings I have against them
        // After all, we're all just trying to do our job here
        // if we singe some eyebrow hair, oh well.
        // ------------------------------------------------------------------
		if(oCaster == oPC)
		{
		
		SetGlobalInt("PCIsMagicUser",1);
		
		}
		
		
        if (GetFactionEqual(oCaster, OBJECT_SELF))
        {
            ClearPersonalReputation(oCaster, OBJECT_SELF);
            // Send the user-defined event as appropriate
            if(GetSpawnInCondition(NW_FLAG_SPELL_CAST_AT_EVENT))
            {
                SignalEvent(OBJECT_SELF, EventUserDefined(EVENT_SPELL_CAST_AT));
            }
            return;
        }
		CheckRemoveStealth();
        if(!GetIsFighting(OBJECT_SELF) && GetIsValidRetaliationTarget(oCaster))
        {
            if(GetBehaviorState(NW_FLAG_BEHAVIOR_SPECIAL))
            {
                HenchDetermineSpecialBehavior(oCaster);
            }
            else
            {
                HenchDetermineCombatRound(oCaster);
            }
        }
    }
    if(GetSpawnInCondition(NW_FLAG_SPELL_CAST_AT_EVENT))
    {
        SignalEvent(OBJECT_SELF, EventUserDefined(EVENT_SPELL_CAST_AT));
    }
}

yep that looks good :)

note i think it can be refactored like →

1 Like

(
ps. The DAMAGE_TYPE_* constants are bitwised so it would require a bit of jiggery to loop over them.

int i;
for (i = 8; i <= 2048; i *= 2) // start at DAMAGE_TYPE_MAGICAL and stop at DAMAGE_TYPE_SONIC
{}

)

Yes, I noticed they jumped and doubled all the time, and I too thought that maybe it would be a lot of calculations doing the loop thing on them.

Yeah, that’s better. Skipping the step with oPC altogether. I think I’ll use that then.

1 Like

binary →

  8 = 0000 1000
 16 = 0001 0000
 32 = 0010 0000
 64 = 0100 0000
128 = 1000 0000

...

Each bitwise value just shifts the 1 around …

1 Like