Aller au contenu

Photo

GetDamageDeltByType


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

#1
Shaun the Crazy One

Shaun the Crazy One
  • Members
  • 183 messages
Awhile back I made a script to "fix" object hardness to work by 3.5 rules, by healing the placeable as it was damage to a max of it's hardness each hit.  Since materials take more damage from some weapon types then others I used the GetDamageDealtByType function to add up the total effective amount of damage a placeable was being delt.  Play testing has revealed that the script doesn't work.  I set it up with some debug indicators and it looks like the GetDamageDealtByType is returning a -1 every time for all damage types.  I used the constants DAMAGE_TYPE_BLUDGEONING, DAMAGE_TYPE_SLASHING, ect. from the global constants list.  Not sure what I'm doing wrong.

#2
Dann-J

Dann-J
  • Members
  • 3 161 messages
I seem to recall that function being a bit buggy for physical damage. I've used it successfully for fire, cold or magical damage though, so it would seem to work fine for non-physical damage.

There are additional notes about the function here (for NWN1):
http://www.nwnlexico...ealtbytype.html

Modifié par DannJ, 14 février 2012 - 02:49 .


#3
Shaun the Crazy One

Shaun the Crazy One
  • Members
  • 183 messages
Thanks Dann, that's extremely helpful. I don't understand why it returns a negative -1 instead of a 0. I'm going to try toying around with the constants.

I'm hoping to make it difficult or impossible for players to break placeables with range weapons (there are a few areas where this can break the game or cause problems), I'm gonna try toying around with the constants to see if I can get it to work.

On reflection I don't think NWN2 has piercing, bludgeoning, or slashing damage types. NWN1 did but in NWN2 I think it all goes under the category of physical. I'll do a bit or trial and error and see what does and does not work.

#4
Dann-J

Dann-J
  • Members
  • 3 161 messages
It seems to get a mention in the Broken Functions thread (which is probably where I remember the bug from):

http://social.biowar...4/index/3120333

You might have to resort to a combination of GetLastWeaponUsed and GetWeaponRanged to exclude ranged weapons (or apply a damage penalty).

Modifié par DannJ, 14 février 2012 - 04:03 .


#5
Dann-J

Dann-J
  • Members
  • 3 161 messages
[Duplicado Deleto]

Modifié par DannJ, 14 février 2012 - 09:36 .


#6
Kaldor Silverwand

Kaldor Silverwand
  • Members
  • 1 598 messages
I posted scripts for this sort of thing back in April 2010 in the gone-but-not-forgotten forums when someone wanted a way to chop down trees. The script I wrote bb_ondamaged_restrict_type can be used to restrict the dame by type. You are correct though that the piercing, bludgeoning, and slashing damage types do not work.

Here is the script:

// bb_ondamaged_restrict_type
// by Brendan Bellina
// April, 2010

// Used as a replacement onDamaged script for placeables that should be damaged by only certain types of damage.
// Since only creatures can have immortality, set the max hp and current hp on the placable to be very high (like 9999).

// Required Placeable variables:
// int ReqDmgType - the type of damage (use DAMAGE_TYPE_* values) that is required to damage the placeable (only one type can be specified)
// Valid values:
// 1 - Combat Damage - Bludgeoning
// 2 - Combat Damage - Piercing
// 4 - Combat Damage - Slashing
// 8 - Magical
// 16 - Acid
// 32 - Cold
// 64 - Divine
// 128 - Electrical
// 256 - Fire
// 512 - Negative
// 1024 - Positive (not an implemented damage type)
// 2048 - Sonic
// int ReqDmg - the number of points of damage of type ReqDmgType required to destroy the placeable
// string DeathScript - optional script to execute when ReqDmg drops to 0. If the DeathScript does not
// destroy the placeable then this script will after executing DeathScript.

// All damage that is done is healed. The destruction of the item is based on the RqdDmg variable, not HP.

// To be selectable an object should:
// - have no walkmesh cutter around it (be in the valid walkmesh) (needed to allow walking through the place after it is destroyed)
// - have hit points (set the current hp and max hp to something like 9999 so that it cannot be destroyed by a normal attack)
// - not be static (needed to allow destroying)
// - be useable (needed to allow attacking)
// - be hostile faction (needed to allow attacking)
// - have dynamic collisions (needed to prevent running through the placeable)
// - not be plot (needed to allow damaging)

//////////////// Function Prototypes

// Returns the damage done for a single damage type. Unlike GetDamageDealtByType this can only take
// a single value of DAMAGE_TYPE_* and will return only a positive integer or 0 (when no damage).
// By default it checks fire damage.
// Note: Due to limitations in the GetDamageDealtByType function, this WILL NOT WORK for bludgeoning,
// piercing, and slashing damage. Because GetDamageDealtByType does not properly hande DAMAGE_TYPE_ALL
// either, if you specify DAMAGE_TYPE_ALL or pass "-1" then the function GetTotalDamageDealt() will be used to calculate the total damage.
// By Brendan Bellina, March 2010
int GetDamageDealtBySingleType(int nDamageType = DAMAGE_TYPE_FIRE); // default to fire

// Returns the Combat Damage dealt
// By Brendan Bellina, March 2010
int GetCombatDamageDealt();

// Debugging routine for printing out the damage being done to a placeable. Use DAMAGE_TYPE_* values.
// Note: Due to limitations in the GetDamageDealtByType function, this WILL NOT WORK for bludgeoning,
// piercing, and slashing damage. Damage Type ALL doesn't work either. To display the total damage
// dealt pass the value "-1" and the GetTotalDamageDealt() function will be used to calculate the damage.
// By Brendan Bellina, March 2010
void displayDmgDealtByType(int nDamageType = -1); // default to total damage

// Returns TRUE if the weapon does slashing dmg based on its BASE_ITEM_TYPE
// by Brendan Bellina, March 2010
int IsSlashingWeapon(object oWeapon);

// Returns TRUE if the weapon does piercing dmg based on its BASE_ITEM_TYPE
// by Brendan Bellina, March 2010
int IsPiercingWeapon(object oWeapon);

// Returns TRUE if the weapon does bludgeoning dmg based on its BASE_ITEM_TYPE
// by Brendan Bellina, March 2010
int IsBludgeoningWeapon(object oWeapon);

//////////////// Functions

// Returns the damage done for a single damage type. Unlike GetDamageDealtByType this can only take
// a single value of DAMAGE_TYPE_* and will return only a positive integer or 0 (when no damage).
// By default it checks fire damage.
// Note: Due to limitations in the GetDamageDealtByType function, this WILL NOT WORK for bludgeoning,
// piercing, and slashing damage. Because GetDamageDealtByType does not properly hande DAMAGE_TYPE_ALL
// either, if you specify DAMAGE_TYPE_ALL or pass "-1" then the function GetTotalDamageDealt() will be used to calculate the total damage.
// By Brendan Bellina, March 2010
int GetDamageDealtBySingleType(int nDamageType)
{
int nDamage;
if (nDamageType == DAMAGE_TYPE_ALL || nDamageType == -1)
{
nDamage = GetTotalDamageDealt();
}
else
{
int nDamage = GetDamageDealtByType(nDamageType);
if (nDamage < 1)
nDamage = 0;
}
return nDamage;
}

// Returns the Combat Damage dealt
// By Brendan Bellina, March 2010
int GetCombatDamageDealt()
{
int nDmg = GetTotalDamageDealt();
int nNonCombatDmg = GetDamageDealtByType(DAMAGE_TYPE_ACID || DAMAGE_TYPE_COLD
|| DAMAGE_TYPE_DIVINE || DAMAGE_TYPE_ELECTRICAL || DAMAGE_TYPE_FIRE || DAMAGE_TYPE_MAGICAL
|| DAMAGE_TYPE_NEGATIVE || DAMAGE_TYPE_POSITIVE || DAMAGE_TYPE_SONIC);

if (nNonCombatDmg > 0)
nDmg -= nNonCombatDmg;

return nDmg;
}

// Debugging routine for printing out the damage being done to a placeable. Use DAMAGE_TYPE_* values.
// Note: Due to limitations in the GetDamageDealtByType function, this WILL NOT WORK for bludgeoning,
// piercing, and slashing damage. Damage Type ALL doesn't work either. To display the total damage
// dealt pass the value "-1" and the GetTotalDamageDealt() function will be used to calculate the damage.
// By Brendan Bellina, March 2010
void displayDmgDealtByType(int nDamageType)
{
string sDamageType = "TOTAL";

if (nDamageType == 0)
sDamageType = "ALL (broken)";
else if (nDamageType == 16)
sDamageType = "ACID";
else if (nDamageType == 1)
sDamageType = "BLUDGEONING (broken)";
else if (nDamageType == 32)
sDamageType = "COLD";
else if (nDamageType == 64)
sDamageType = "DIVINE";
else if (nDamageType == 128)
sDamageType = "ELECTRICAL";
else if (nDamageType == 256)
sDamageType = "FIRE";
else if (nDamageType == 8)
sDamageType = "MAGICAL";
else if (nDamageType == 512)
sDamageType = "NEGATIVE";
else if (nDamageType == 2)
sDamageType = "PIERCING (broken)";
else if (nDamageType == 1024)
sDamageType = "POSITIVE (not implemented)";
else if (nDamageType == 4)
sDamageType = "SLASHING (broken)";
else if (nDamageType == 2048)
sDamageType = "SONIC";

if (nDamageType == -1)
{
int nDmgDealt = GetTotalDamageDealt();
AssignCommand(GetFirstPC(), SpeakString(IntToString(nDmgDealt) + " " + sDamageType + " damage dealt", TALKVOLUME_TALK));
}
else
{
int nDmgDealt = GetDamageDealtByType(nDamageType);
AssignCommand(GetFirstPC(), SpeakString(IntToString(nDmgDealt) + " " + sDamageType + " (" + IntToString(nDamageType) + ") damage", TALKVOLUME_TALK));
}
}

// Returns TRUE if the weapon does slashing dmg based on its BASE_ITEM_TYPE
// by Brendan Bellina, March 2010
int IsSlashingWeapon(object oWeapon)
{
if (!GetIsObjectValid(oWeapon))
return FALSE;

int nType = GetBaseItemType(oWeapon);
// Check all slashing weapons
return (nType == BASE_ITEM_CSLASHWEAPON ||
nType == BASE_ITEM_ALLUSE_SWORD ||
nType == BASE_ITEM_BASTARDSWORD ||
nType == BASE_ITEM_BATTLEAXE ||
nType == BASE_ITEM_CGIANT_AXE ||
nType == BASE_ITEM_CGIANT_SWORD ||
nType == BASE_ITEM_DOUBLEAXE ||
nType == BASE_ITEM_DWARVENWARAXE ||
nType == BASE_ITEM_FALCHION ||
nType == BASE_ITEM_GREATAXE ||
nType == BASE_ITEM_GREATSWORD ||
nType == BASE_ITEM_HALBERD ||
nType == BASE_ITEM_HANDAXE ||
nType == BASE_ITEM_KAMA ||
nType == BASE_ITEM_KATANA ||
nType == BASE_ITEM_KUKRI ||
nType == BASE_ITEM_LONGSWORD ||
nType == BASE_ITEM_SCIMITAR ||
nType == BASE_ITEM_SCYTHE ||
nType == BASE_ITEM_SICKLE ||
nType == BASE_ITEM_THROWINGAXE ||
nType == BASE_ITEM_TWOBLADEDSWORD ||
nType == BASE_ITEM_WHIP );
}

// Returns TRUE if the weapon does piercing dmg based on its BASE_ITEM_TYPE
// by Brendan Bellina, March 2010
int IsPiercingWeapon(object oWeapon)
{
if (!GetIsObjectValid(oWeapon))
return FALSE;

int nType = GetBaseItemType(oWeapon);
// Check all piercing weapons
return (nType == BASE_ITEM_CPIERCWEAPON ||
nType == BASE_ITEM_ARROW ||
nType == BASE_ITEM_BOLT ||
nType == BASE_ITEM_DAGGER ||
nType == BASE_ITEM_DART ||
nType == BASE_ITEM_HEAVYCROSSBOW ||
nType == BASE_ITEM_LIGHTCROSSBOW ||
nType == BASE_ITEM_LONGBOW ||
nType == BASE_ITEM_RAPIER ||
nType == BASE_ITEM_SHORTBOW ||
nType == BASE_ITEM_SHORTSPEAR ||
nType == BASE_ITEM_SHORTSWORD ||
nType == BASE_ITEM_SHURIKEN ||
nType == BASE_ITEM_SPEAR );
}

// Returns TRUE if the weapon does bludgeoning dmg based on its BASE_ITEM_TYPE
// by Brendan Bellina, March 2010
int IsBludgeoningWeapon(object oWeapon)
{
if (!GetIsObjectValid(oWeapon))
return FALSE;

int nType = GetBaseItemType(oWeapon);
// Check all bludgeoning weapons
return (nType == BASE_ITEM_CBLUDGWEAPON ||
nType == BASE_ITEM_BULLET ||
nType == BASE_ITEM_CLUB ||
nType == BASE_ITEM_DIREMACE ||
nType == BASE_ITEM_FLAIL ||
nType == BASE_ITEM_GREATCLUB ||
nType == BASE_ITEM_HEAVYFLAIL ||
nType == BASE_ITEM_LIGHTFLAIL ||
nType == BASE_ITEM_LIGHTHAMMER ||
nType == BASE_ITEM_LIGHTMACE ||
nType == BASE_ITEM_MACE ||
nType == BASE_ITEM_MORNINGSTAR ||
nType == BASE_ITEM_QUARTERSTAFF ||
nType == BASE_ITEM_SLING ||
nType == BASE_ITEM_TRAINING_CLUB ||
nType == BASE_ITEM_WARHAMMER ||
nType == BASE_ITEM_WARMACE );
}

//////////////// End of Functions

void main()
{
int debugmode = FALSE; // set to TRUE to turn on debug

int nRqdDmgType = GetLocalInt(OBJECT_SELF, "RqdDmgType");
int nRqdDmg = GetLocalInt(OBJECT_SELF, "RqdDmg");
object oDamager = GetLastDamager();
int nTotalDamageDealt = GetTotalDamageDealt();
int nDmgDealt = 0;

if (debugmode)
{
displayDmgDealtByType(-1); // display total damage
displayDmgDealtByType(DAMAGE_TYPE_ALL); // 0 - deprecated by GetTotalDamageDealt function, always returns 0
displayDmgDealtByType(DAMAGE_TYPE_ACID); // 16
displayDmgDealtByType(DAMAGE_TYPE_BLUDGEONING); // 1 - broken, always returns -1
displayDmgDealtByType(DAMAGE_TYPE_COLD); // 32
displayDmgDealtByType(DAMAGE_TYPE_DIVINE); // 64
displayDmgDealtByType(DAMAGE_TYPE_ELECTRICAL); // 128
displayDmgDealtByType(DAMAGE_TYPE_FIRE); // 256
displayDmgDealtByType(DAMAGE_TYPE_MAGICAL); // 8
displayDmgDealtByType(DAMAGE_TYPE_NEGATIVE); // 512
displayDmgDealtByType(DAMAGE_TYPE_PIERCING); // 2 - broken, always returns -1
displayDmgDealtByType(DAMAGE_TYPE_POSITIVE); // 1024 - not implemented
displayDmgDealtByType(DAMAGE_TYPE_SLASHING); // 4 - broken, always returns -1
displayDmgDealtByType(DAMAGE_TYPE_SONIC); // 2048

int nLeftHandItemType = GetBaseItemType(GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oDamager));
AssignCommand(GetFirstPC(), SpeakString("Left Hand Weapon type: " + IntToString(nLeftHandItemType), TALKVOLUME_TALK));
int nRightHandItemType = GetBaseItemType(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oDamager));
AssignCommand(GetFirstPC(), SpeakString("Right Hand Weapon type: " + IntToString(nRightHandItemType), TALKVOLUME_TALK));

}

// if RqdDmgType is specified and it is one that works, then prevent damage
// except by that type and subtract the damage from RqdDmg until it is 0 and destroyed.
// This will allow a placeable to be destroyed only by a certain type of non-combat damage - like fire or electrical.
// Make certain to set the actual HP of the placeable so high that a single hit cannot reduce the HP to 0.
if (nRqdDmgType > 0 &&
(nRqdDmgType == DAMAGE_TYPE_ACID ||
nRqdDmgType == DAMAGE_TYPE_COLD ||
nRqdDmgType == DAMAGE_TYPE_DIVINE ||
nRqdDmgType == DAMAGE_TYPE_ELECTRICAL ||
nRqdDmgType == DAMAGE_TYPE_FIRE ||
nRqdDmgType == DAMAGE_TYPE_COLD ||
nRqdDmgType == DAMAGE_TYPE_MAGICAL ||
nRqdDmgType == DAMAGE_TYPE_NEGATIVE ||
nRqdDmgType == DAMAGE_TYPE_POSITIVE ||
nRqdDmgType == DAMAGE_TYPE_SONIC)
)
{
nDmgDealt = GetDamageDealtByType(nRqdDmgType);
if (nDmgDealt < 1)
{
nDmgDealt = 0;
}
}
else if (nRqdDmgType == DAMAGE_TYPE_SLASHING)
{
// check the hands of the LastDamager for any slashing weaponry
// Obviously this is not perfect because we do not know which weapon
// did the damage when wielding two. We also cannot tell if wielding two
// weapons which damage was caused by one combat type vs. another.
// This also will not work well for the last item being thrown because the hands
// will be empty at that time.
int nNumberOfSlashingWeapons;
object oLeftHandItem = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oDamager);
if (GetIsObjectValid(oLeftHandItem) && IsSlashingWeapon(oLeftHandItem))
{
nNumberOfSlashingWeapons++;
nDmgDealt += GetCombatDamageDealt();
}

object oRightHandItem = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oDamager);
if (GetIsObjectValid(oRightHandItem) && IsSlashingWeapon(oRightHandItem))
{
nNumberOfSlashingWeapons++;
nDmgDealt += GetCombatDamageDealt();
}

if (nNumberOfSlashingWeapons)
{
nDmgDealt /= nNumberOfSlashingWeapons; // adjust for wielding two weapons of the same damage type
}
}
else if (nRqdDmgType == DAMAGE_TYPE_PIERCING)
{
// check the hands of the LastDamager for any piercing weaponry
// Obviously this is not perfect because we do not know which weapon
// did the damage when wielding two. We also cannot tell if wielding two
// weapons which damage was caused by one combat type vs. another.
// This also will not work well for the last item being thrown because the hands
// will be empty at that time.
int nNumberOfPiercingWeapons;
object oLeftHandItem = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oDamager);
if (GetIsObjectValid(oLeftHandItem) && IsPiercingWeapon(oLeftHandItem))
{
nNumberOfPiercingWeapons++;
nDmgDealt += GetCombatDamageDealt();
}

object oRightHandItem = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oDamager);
if (GetIsObjectValid(oRightHandItem) && IsPiercingWeapon(oRightHandItem))
{
nNumberOfPiercingWeapons++;
nDmgDealt += GetCombatDamageDealt();
}

if (nNumberOfPiercingWeapons)
{
nDmgDealt /= nNumberOfPiercingWeapons; // adjust for wielding two weapons of the same damage type
}
}
else if (nRqdDmgType == DAMAGE_TYPE_BLUDGEONING)
{
// check the hands of the LastDamager for any bludgeoning weaponry or empty hands
// Obviously this is not perfect because we do not know which weapon
// did the damage when wielding two. We also cannot tell if wielding two
// weapons which damage was caused by one combat type vs. another.
// This also will not work well for the last item being thrown because the hands
// will be empty at that time.
int nNumberOfBludgeoningWeapons;
object oLeftHandItem = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oDamager);
if (GetIsObjectValid(oLeftHandItem) && IsBludgeoningWeapon(oLeftHandItem))
{
nNumberOfBludgeoningWeapons++;
nDmgDealt += GetCombatDamageDealt();
}

object oRightHandItem = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oDamager);
if (GetIsObjectValid(oRightHandItem) && IsBludgeoningWeapon(oRightHandItem))
{
nNumberOfBludgeoningWeapons++;
nDmgDealt += GetCombatDamageDealt();
}

if (nNumberOfBludgeoningWeapons)
{
nDmgDealt /= nNumberOfBludgeoningWeapons; // adjust for wielding two weapons of the same damage type
}

// if the right hand is empty then the left hand is either empty also or contains
// something other than a weapon (like a torch or shield). Either way, if the right
// hand is empty then the attack does not involve a weapon and is considered bludgeoning.
if (!GetIsObjectValid(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oDamager)))
{
// not wielding any weapons, and fist damage is bludgeoning, so...
nDmgDealt += GetCombatDamageDealt();
}
}
else // invalid or no damage type specified, so apply total damage dealt
{
nDmgDealt = nTotalDamageDealt; // use total damage
}

if (nDmgDealt)
{
if (debugmode)
{
object oPC = GetFirstPC();
AssignCommand(oPC, SpeakString("bb_ondamaged_restrict_type " + IntToString(nDmgDealt) + " damage done", TALKVOLUME_TALK));
}

nRqdDmg -= nDmgDealt; // reduce nRqdDmg by the damage dealt

if (nRqdDmg < 1) // if no more damage can be taken then destroy
{
// Check for additional death script
string sDeathScript = GetLocalString( OBJECT_SELF, "DeathScript" );
if ( sDeathScript != "" )
{
// Save killer on object in case it is needed by DeathScript
SetLocalObject( OBJECT_SELF, "oKiller", oDamager );
ExecuteScript( sDeathScript, OBJECT_SELF );
}

// if still here, then destroy me now
if (GetIsObjectValid(OBJECT_SELF))
DestroyObject(OBJECT_SELF, 0.1, TRUE);
}
else // otherwise save the reduced damage value
{
SetLocalInt(OBJECT_SELF, "RqdDmg", nRqdDmg);
}
}
else // any damage done was not allowable, indicate the weapon had no effect
{
// if the right hand is empty then the left hand is either empty also or contains
// something other than a weapon (like a torch or shield). Either way, if the right
// hand is empty then the attack does not involve a weapon.
if (GetIsObjectValid(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oDamager)))
{
AssignCommand(oDamager, SpeakString("My weapon had no effect!", TALKVOLUME_TALK));
}
else
{
AssignCommand(oDamager, SpeakString("My attack had no effect!", TALKVOLUME_TALK));
}
}

// Heal the placeable of all damage
effect eFX = EffectHeal(nTotalDamageDealt);
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eFX, OBJECT_SELF);
}

And here is the choppable trees script:

// bb_ondeath_choppabletree
// by Brendan Bellina
// April, 2010

// Use this as the DeathScript for a tree you are chopping down.
// See the script bb_ondamaged_restrict_type for more information.

// Makes an explosion, spawn in a stump, and give the killer a wooden plank.
// The standard stump does not have Dynamic Collision on, so the stump can be run through.
// If you would rather the stump be solid then copy the stump blueprint, set Dynamic Collisions to
// true on the new blueprint, and spawn a stump from that blueprint instead of the standard blueprint.

void main()
{
object oKiller = GetLocalObject(OBJECT_SELF, "oKiller");

// Create explode effect
effect eExplode = EffectNWN2SpecialEffectFile( "fx_wooden_explosion_big");
ApplyEffectToObject(DURATION_TYPE_INSTANT, eExplode, OBJECT_SELF);

// Spawn in a stump
location locStump = GetLocation(OBJECT_SELF);
object oStump = CreateObject(OBJECT_TYPE_PLACEABLE,"plc_nf_tstump1",locStump,0);

// Reward the killer with a wooden plank (if valid)
if (GetIsObjectValid(oKiller))
{
object oWood = CreateItemOnObject("n2_crft_plkwood", oKiller, 1, "", 0);
}
}

Regards

#7
painofdungeoneternal

painofdungeoneternal
  • Members
  • 1 799 messages
This is pretty similar to what Kaldor has posted.

/**  
* This gets just the physical damage dealt, since for example: GetDamageDealtByType(DAMAGE_TYPE_SLASHING) returns -1 when the damage type is slashing
* You should use other functions to determine when this function is of use based on the weapon held ( using GetLastWeaponUsed )
* @author based on comments by OEI, with input from Vanes and J.O.G
* @replaces GetDamageDealtByType
*/
int CSLGetPhysicalDamageDealt()
{
	int iDamage = GetTotalDamageDealt();			
	int i;	
	for ( i = DAMAGE_TYPE_MAGICAL; i <= DAMAGE_TYPE_SONIC; i <<= 1 ) 
	{
		if (GetDamageDealtByType(i) > 0 )
		{
			iDamage -= GetDamageDealtByType(i);
		}
	}
	return iDamage;
}

Combine that with something like.
object oCreature = GetLastAttacker(OBJECT_SELF);
object oWeapon =  GetLastWeaponUsed(oCreature); or checking what is in the right hand.

Probably should refer to Kaldors code above as this is just guesswork, but it's a bit simpler which might help a bit as well. My csl libraries have code which does the weapon types too.

#8
Dann-J

Dann-J
  • Members
  • 3 161 messages
It really makes you appreciate the functions that *do* work when you see how many hoops you have to jump through for scripting work-arounds.

#9
Shaun the Crazy One

Shaun the Crazy One
  • Members
  • 183 messages
So you can tell this was a function not made to work in the NWN2 system. Kaldor, as much as I appreciate you posting that script, it honestly terrifies me. I think I'm going try DannJ's suggestiong of GetLastWeaponUsed and GetWeaponRanged and use painofdungeoneternal's script to determine physical damage.

#10
Kaldor Silverwand

Kaldor Silverwand
  • Members
  • 1 598 messages
Sure. One thing to keep in mind is that if the ranged weapon being used is a thrown weapon, then after the last one is thrown you may not be able to tell what weapon was used.

Regards

#11
Shaun the Crazy One

Shaun the Crazy One
  • Members
  • 183 messages
So I ended up making a patchwork script with my old program and much of what was given here. The new program makes hardness work pretty much like it should in 3.5

Thanks everyone for the help.

//object_hardness

/*
	Use for a doors or placables with a hardness rating.  Set this as the "On Dameged Script"
	This script subtracts the object's hardness from the damege delt in acordance to D&D 3.5
	rules.  The objects hit points must be greater than it's hardness for this script to
	work properly.
	
	You can assign a material by creating a local string variable on the object called 
	"Material".  The object will take different amounts of damege for differnt energy types
	based on it's material.  If no material is assigned the program will use a generic set of
	proporties for the material.
	
	string Material = object material (for determing damage resistances)
		"wood" = double damege from fire, half damege from acid and cold, quarter damege from
			electricity, and normal damege from sonic
		"stone" = *1.5 damege from sonic, half damege from fire and electricity, quarter 
			damege from cold, and normal damege from acid
		"iron" = *1.5 damege from acid, half damege from fire and electricity, quarter damege
			from cold, and normal damege from sonic
		"magical" = only takes damage from melee weapons
		(Default) = half damege from fire and electricity, quarter damege from cold, and normal
			damege from acid and sonic (D&D 3.5 standard)
			(edit 2/14/12 changed acid and sonic to *1.5 since 3.5 rules say to bypass harness
			with acid or sonic damage and this script only determines rather damage will bypass
			the object's hardness)
		
	All materials take normal damage from magic, devine or negative energy and half from 
	peircing.  Items take no physical damage from ranged weapons.
*/

//Shaun H. 6/15/10

//Check
int IsPiercingWeapon(object oWeapon);

void main()
{
	int iHardness = GetHardness(OBJECT_SELF);
	string sMaterial = GetLocalString(OBJECT_SELF,"Material");
	int iHeal = GetTotalDamageDealt();
	object oDamager = GetLastDamager();
	
	//Get physical damage
	int iDamage = GetTotalDamageDealt();
	int i;
	for ( i = DAMAGE_TYPE_MAGICAL; i <= DAMAGE_TYPE_SONIC; i <<= 1 )
		if (GetDamageDealtByType(i) > 0 ) iDamage -= GetDamageDealtByType(i);
	//range weapons deal no physical damage
	if(GetWeaponRanged(GetLastWeaponUsed(oDamager)) == TRUE) iDamage = 0;
	//convert to float for type modifiers
	float fDamage = IntToFloat(iDamage);
	//non-ranged peircing wepons do half damage
	if(IsPiercingWeapon(GetLastWeaponUsed(oDamager)) == TRUE) fDamage = fDamage/2;
	
	
	//Determine damage from other damage types
	if(GetDamageDealtByType(DAMAGE_TYPE_DIVINE) > 0)
		fDamage += IntToFloat(GetDamageDealtByType(DAMAGE_TYPE_DIVINE));
	if(GetDamageDealtByType(DAMAGE_TYPE_NEGATIVE) > 0)
		fDamage += IntToFloat(GetDamageDealtByType(DAMAGE_TYPE_NEGATIVE));
	if(GetDamageDealtByType(DAMAGE_TYPE_MAGICAL) > 0)
		fDamage += IntToFloat(GetDamageDealtByType(DAMAGE_TYPE_MAGICAL));
	
	float fACID = 0.0;
	float fCOLD = 0.0;
	float fELECTRICAL = 0.0;
	float fFIRE = 0.0;
	float fSONIC = 0.0;
	if(GetDamageDealtByType(DAMAGE_TYPE_ACID) > 0)
		fACID = IntToFloat(GetDamageDealtByType(DAMAGE_TYPE_ACID));
	if(GetDamageDealtByType(DAMAGE_TYPE_COLD) > 0)
		fCOLD = IntToFloat(GetDamageDealtByType(DAMAGE_TYPE_COLD));
	if(GetDamageDealtByType(DAMAGE_TYPE_ELECTRICAL) > 0)
		fELECTRICAL = IntToFloat(GetDamageDealtByType(DAMAGE_TYPE_ELECTRICAL));
	if(GetDamageDealtByType(DAMAGE_TYPE_FIRE) > 0)
		fFIRE = IntToFloat(GetDamageDealtByType(DAMAGE_TYPE_FIRE));
	if(GetDamageDealtByType(DAMAGE_TYPE_SONIC) > 0)
		fSONIC = IntToFloat(GetDamageDealtByType(DAMAGE_TYPE_SONIC));
	
	//Determin effects of material on damage
	if (sMaterial == "wood") fDamage += fACID/2 + fCOLD/2 + fELECTRICAL/4 + fFIRE*2 + fSONIC;
	else if (sMaterial == "stone") fDamage += fACID + fCOLD/4 + fELECTRICAL/2 + fFIRE/2 + fSONIC*1.5;
	else if (sMaterial == "iron") fDamage += fACID*1.5 + fCOLD/4 + fELECTRICAL/2 + fFIRE/2 + fSONIC;
	else if (sMaterial == "magical") fDamage = IntToFloat(iDamage);
	else fDamage += fACID*1.5 + fCOLD/4 + fELECTRICAL/2 + fFIRE/2 + fSONIC*1.5;
	
	iDamage = FloatToInt(fDamage);
	
	if (iHardness < iDamage) iHeal += iHardness - iDamage;
	if (iHeal < 0) iHeal = 0;
	ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectHeal(iHeal),OBJECT_SELF);
	
	if((iDamage < 1) && (GetIsPC(oDamager)))
	{
		AssignCommand(oDamager, ClearAllActions());
		AssignCommand(oDamager, SpeakString("Weapon ineffective"));
		AssignCommand(oDamager, PlayVoiceChat(VOICE_CHAT_WEAPONSUCKS, oDamager));
	}
}

// Returns TRUE if the weapon does piercing and is not ranged dmg based on its BASE_ITEM_TYPE
// by Brendan Bellina, March 2010
// modifed by Shaun Hentchel for use in Hack and Slash Heaven 2/14/12
int IsPiercingWeapon(object oWeapon)
{
	if (!GetIsObjectValid(oWeapon))
	return FALSE;
	
	int nType = GetBaseItemType(oWeapon);
	// Check all piercing weapons
	return (nType == BASE_ITEM_CPIERCWEAPON || nType == BASE_ITEM_DAGGER || nType == BASE_ITEM_RAPIER || 
		nType == BASE_ITEM_SHORTSPEAR || nType == BASE_ITEM_SHORTSWORD || nType == BASE_ITEM_SPEAR );
}