Author Topic: KMdS's content creations  (Read 1240 times)

Legacy_KMdS!

  • Sr. Member
  • ****
  • Posts: 364
  • Karma: +0/-0
KMdS's content creations
« on: May 25, 2016, 04:38:31 am »


               

Hey all,


 


I am still having difficulties connecting the the new vault so I think I will collect the work I have submitted to the forum here in this thread as well as work I have in my archives, at least until I can finally submit my material to the Vault or to my own nearly restored forums.



               
               

               
            

Legacy_KMdS!

  • Sr. Member
  • ****
  • Posts: 364
  • Karma: +0/-0
KMdS's content creations
« Reply #1 on: May 25, 2016, 04:56:06 am »


               
A simple area despawner. You can merge this into your own area hb, enter, exit event scripts, or you can just place and ExecuteScript on your area's hb,enter,exit events. Set to a default of 5 minutes of continually not finding any PC in the area. Modify the variable int HB_Count_Delay to modify the delay.

 

The despawner checks for PC in an area

 

Here they are.


// k_on_area_enter.nss
 
void main()
{
    int nPCCount = GetLocalInt(OBJECT_SELF, "PC_COUNT");
    object oObject = GetEnteringObject();
    if(GetIsPC(oObject))
        SetLocalInt(OBJECT_SELF, "PC_COUNT", ++nPCCount);
}
 
 
// k_on_area_exit.nss
 
void main()
{
    int nPCCount = GetLocalInt(OBJECT_SELF, "PC_COUNT");
    object oObject = GetExitingObject();
    if(GetIsPC(oObject))
        SetLocalInt(OBJECT_SELF, "PC_COUNT", --nPCCount);
}
 
 
// k_area_hb.nss
 
// Set this to the number of heartbeats between processing of an area
// Default is 50HB's, 300 seconds (5 minutes) after not finding any PC's in the area for the entire time
int HB_Count_Delay = 50;
 
void main()
{
    int bPROCESS_ONLY_ENCOUNTER_SPAWNS = TRUE;
 
    string sTag = GetTag(OBJECT_SELF);
    int nIteration = GetLocalInt(OBJECT_SELF, "ITERATION_"+sTag);
    int nPCCount = GetLocalInt(OBJECT_SELF, "PC_COUNT");
    if(nPCCount==FALSE)
    {
        if(nIteration<HB_Count_Delay )
            SetLocalInt(OBJECT_SELF, "ITERATION_"+sTag, ++nIteration);
        // destroy only encounter spawns
        else if(bPROCESS_ONLY_ENCOUNTER_SPAWNS)
        {
            object oCreature = GetFirstObjectInArea();
            while(oCreature != OBJECT_INVALID)
            {
                if(GetIsEncounterCreature(oCreature))
                {
                    AssignCommand(oCreature, SetIsDestroyable(1,0,0));
                    DestroyObject(oCreature);
                }
                oCreature = GetNextObjectInArea();
            }
        }
        // destroy all creatures, not just encounter spawns
        else
        {
            object oCreature = GetFirstObjectInArea();
            while(oCreature != OBJECT_INVALID)
            {
                if(GetObjectType(oCreature) == OBJECT_TYPE_CREATURE)
                {
                    AssignCommand(oCreature, SetIsDestroyable(1,0,0));
                    DestroyObject(oCreature);
                }
                oCreature = GetNextObjectInArea();
            }
        }
    }
    //ERROR-Reset the PC count
    else if(nPCCount<0)
    {
        nPCCount = 0;
        object oPC = GetFirstPC();
        while(oPC != OBJECT_INVALID)
        {
            if(GetArea(oPC) == OBJECT_SELF)
                ++nPCCount;
            oPC = GetNextPC();
        }
        SetLocalInt(OBJECT_SELF, "PC_COUNT", nPCCount);
    }
    // PC's are in the area, reset the iteration count
    else
    {
        if(nIteration)
            SetLocalInt(OBJECT_SELF, "ITERATION_"+sTag, 0);
    }
}


               
               

               
            

Legacy_KMdS!

  • Sr. Member
  • ****
  • Posts: 364
  • Karma: +0/-0
KMdS's content creations
« Reply #2 on: May 25, 2016, 05:08:52 am »


               

This will search for any living, seen, enemies of the caller of this method and return a preferred target object. By default Wizards and Sorcerers have priority followed by Clerics and Druids. Dominated creatures and Henchmen are checked to find mages and priests. Summons', Familiars and companions are not checked against. Should no mage or priest be found the method returns OBJECT_INVALID.

 

Place a call to this function/method from an the method/function DetermineCombatRound in nw_i0_generic.nss.  Modify the code

 


    if (GetIsObjectValid(oIntruder) == FALSE)

        oIntruder = bkAcquireTarget();

 

to this

 


    if (GetIsObjectValid(oIntruder) == FALSE)

        oIntruder = PriorityTarget();

    if (GetIsObjectValid(oIntruder) == FALSE)

        oIntruder = bkAcquireTarget();

 



and add an include to whatever file you place the PriorityTarget function/method

to prioritize the search for the next enemy to attack.

 


// Will only return a target if they have mage or priest levels, are alive,
// can be seen, and are an enemy. Otherwise returns OBJECTINVALID.
// Mage levels are weighted for.
// Only PC's, Henchmen, and Dominated types are concidered.
object PriorityTarget()
{
    object oTarget = OBJECT_INVALID;
    int nCount = 1;
    object oCantidate = GetNearestCreature(CREATURE_TYPE_IS_ALIVE, TRUE, nCount, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN, CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY );
    while(GetIsObjectValid(oCantidate))
    {
        int PriorityLevel = 0;
        if(GetMaster(oCantidate) == OBJECT_INVALID || GetAssociateType(oCantidate) == ASSOCIATE_TYPE_HENCHMAN|| GetAssociateType(oCantidate) == ASSOCIATE_TYPE_DOMINATED)
        {
            int SorcerorLavels  = GetLevelByClass(CLASS_TYPE_SORCERER)*2;
            int WizardLavels    = GetLevelByClass(CLASS_TYPE_WIZARD)*2;
            int ClericLevels    = GetLevelByClass(CLASS_TYPE_CLERIC);
            int DruidLavels     = GetLevelByClass(CLASS_TYPE_DRUID);
 
            int CandidatePriorityLevel = SorcerorLavels+WizardLavels+ClericLevels+DruidLavels;
            if(CandidatePriorityLevel > PriorityLevel)
                oTarget = oCantidate;
        }
        oCantidate = GetNearestCreature(CREATURE_TYPE_IS_ALIVE, TRUE, ++nCount, CREATURE_TYPE_PERCEPTION, PERCEPTION_SEEN, CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY );
    }
    return oTarget;
}


               
               

               
            

Legacy_KMdS!

  • Sr. Member
  • ****
  • Posts: 364
  • Karma: +0/-0
KMdS's content creations
« Reply #3 on: May 25, 2016, 05:43:15 am »


               
As documented in the code, this will return the center of a specific tile where oObject is located.

 


// Will return the center of the specific tileset tile the oObject object is located
vector TileCenter(object oObject)
{
    vector vObject = GetPosition(oObject);
    float fX,fY;
 
    float fX = vObject.x;
    float  fY= vObject.y;
 
    // Store the decimal value if fX
    float fX1 = fX-FloatToInt(fX);
    // Get the value of the ones column of fX
    int iX1 = FloatToInt(fX)%10;
    // The x coordinate within the specific tile
    float fX2 = fX1+iX1;
    // The x value for the distance to the center of the specific tile from the oWaypoint object
    float fX3 = (((10.0-fX2)-fX2)/2)+fX2;
    // The x value for center of the tile the oWaypoint object is located within the global environment
    float fX4= fX-fX2+fX3;
 
 
    // Store the decimal value if fY
    float fY1 = fY-FloatToInt(fY);
    // Get the value of the ones column of fY
    int iY1 = FloatToInt(fY)%10;
    // The y coordinate within the specific tile
    float fY2 = fY1+iY1;
    // The y value for the distance to the center of the specific tile from the oWaypoint object
    float fY3 = (((10.0-fY2)-fY2)/2)+fY2;
    // The y value for center of the tile the oWaypoint object is located within the global environment
    float fY4= fY-fY2+fY3;
 
    return Vector(fX4, fY4, 0.0);
}


               
               

               
            

Legacy_KMdS!

  • Sr. Member
  • ****
  • Posts: 364
  • Karma: +0/-0
KMdS's content creations
« Reply #4 on: May 25, 2016, 06:06:14 am »


               
 

This is an aura creation script that will create a lightning aura effect on an object. The script is designed to be called from within a heartbeat run on the aura possessing object. It is a fun little effect that as coded will hit all objects in a 5 meter radius with a bolt of lightning causing 2d6 of electrical damage to all hit.

It will produse a maximum of 3 randomly located strikes if less than 3 targets are found.

 


// Aura for lightning Azer, onHeartbeat
 
vector RandomVector(int iMeterRadius = 5)
{
    //OBJECT_SELF should be the bolt creating object
    vector vVector = GetPosition(OBJECT_SELF);
    // Will generate a value for x anf y between -5.00 to 5.00
    // a Value of 0.0, 0.0 should occur only once in a million
    float fX = IntToFloat(Random((iMeterRadius*200)+1)-(iMeterRadius*100))/100;
    float fY = IntToFloat(Random((iMeterRadius*200)+1)-(iMeterRadius*100))/100;
 
    // This is the new random vector for the strike location up to 5m away and one meter high.
    return Vector(vVector.x +fX, vVector.y +fY, 0.0);
}
 
 
void main()
{
    effect eVFX;
    location lSelf = GetLocation(OBJECT_SELF);
    {
        int iCount=0;
        object oZap = GetFirstObjectInShape(SHAPE_SPHERE, 5.0, lSelf , TRUE, OBJECT_TYPE_ALL);
        eVFX = EffectVisualEffect(VFX_BEAM_LIGHTNING);
        while(GetIsObjectValid(oZap))
        {
            if(oZap == OBJECT_SELF)
            {
                oZap = GetNextObjectInShape(SHAPE_SPHERE, 5.0, lSelf , TRUE, OBJECT_TYPE_ALL);
                continue;
            }
            ++iCount;
            ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eVFX, oZap, 1.0);
            effect eElectric = EffectDamage(d6(2), DAMAGE_TYPE_ELECTRICAL);
            ApplyEffectToObject(DURATION_TYPE_INSTANT, eElectric, oZap);
            oZap = GetNextObjectInShape(SHAPE_SPHERE, 5.0, lSelf , TRUE, OBJECT_TYPE_ALL);
        }
        int i;
        object oRandomTarget = OBJECT_INVALID;
        for(i=0; i<(-iCount+3); i++)
        {
            oRandomTarget = CreateObject(OBJECT_TYPE_PLACEABLE, "plc_invisobj", Location(GetArea(OBJECT_SELF), RandomVector(), 0.0));
            ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eVFX, oRandomTarget, 1.0);
            SetIsDestroyable(1,0,0);
            DestroyObject(oRandomTarget, 1.0);
        }
    }
}


               
               

               
            

Legacy_KMdS!

  • Sr. Member
  • ****
  • Posts: 364
  • Karma: +0/-0
KMdS's content creations
« Reply #5 on: May 25, 2016, 06:13:22 am »


               

Here is a scripted xp method that replicates the official xp tables. With this method you do not need to use the xp tables 2da. The only thing is that because the required use of floats, the return values may occasionally be off by 1 xp when compared to the standard xp table. Look at the notes in the script for any info.


 


You do need to set the modules default xp award to "0" and call the XPFromAnEncounter int function to return the proper xp amount from any on death script you wish to award xp's from.


 


Note that the party level is the suggested determiner for xp amount awarded. The method does not modify xp's awarded for favored class or unbalanced multiclass levels, that should be done to the returned amount from whatever method calling this function.


 


Any Preferred class/Multi-class bonuses/penalties must by applied to the returned int value


 


/*::////////////////////////////////////////////////////////////////////////////
//:: Name: KMdS PNP Hard Core Rule Set 1.0
//:: System: KMdS NESS D&D 3rd ed XP Tables
//:: FileName: KMdS_XP_Table
//:: Copyright (c) 2005 Michael Careaga
//::////////////////////////////////////////////////////////////////////////////
 
    This is a scripted recreation of the 3rd ed D&D experience point table.
    There are 2 values returned that do not match the XP table.  It seems they
    didn't actually trust their own numbers so they fudged two of their xp
    table entries.  Looking at it from a purely mathmatical perspective, mine
    is the corrected version.
    KMdS
 
    note*
         Due to the necessary use of floats, and their conversion into int's,
         the actual xp value returned may occasionally be off by 1 XPwhen compared
         to the official 3rd ed D&D experience point tables.
 
//::////////////////////////////////////////////////////////////////////////////
//:: Created By: Kilr Mik d Spik
//:: Created On: 05/01/2005
//:://////////////////////////////////////////////////////////////////////////*/
 
//  ----------------------------------------------------------------------------
//  PUBLIC PROTOTYPES
//  ----------------------------------------------------------------------------
 
// This is the actual mathmatical formula for the D&D 3rd ed experience tables.
// Enter the level of the party involved in the kill and the CR of the
// creature killed.  You may adjust the base amount of experience to be awarded
// up or down by setting the percent awarded float to any positive float value.
int XPFromAnEncounter(int nPartyLevel, float fCreatureCR, float fPercentAwarded = 100.0f);
 
//  ----------------------------------------------------------------------------
//  FUNCTIONS
//  ----------------------------------------------------------------------------
 
// This divisor is used for encounters with creatures of less than CR1 , ie 1/8, 1/4, 1/3, 1/2,
// to proportionately adjust the XP's given based on the creatures CR.  Default return value = 1.
int Divisor(float fCreatureCR)
{
    int nDivisor;
    if      (fCreatureCR<0.25f)     nDivisor=8;
    else if (fCreatureCR<0.33f)     nDivisor=4;
    else if (fCreatureCR<0.50f)     nDivisor=3;
    else if (fCreatureCR<1.00f)     nDivisor=2;
    else                            nDivisor=1;
    return nDivisor;
}
 
// This is the multiplier used when determining XP's based on the difference in a
// PC's level vs a creatures CR.
float Multiplier(int nCreatureCR, int nPartyLvl)
{
    int nDeterminerValue = abs(nCreatureCR-nPartyLvl);
    float fMultiplier;
    if      (nDeterminerValue == 7) fMultiplier =12.0f;
    else if (nDeterminerValue == 6) fMultiplier = 8.0f;
    else if (nDeterminerValue == 5) fMultiplier = 6.0f;
    else if (nDeterminerValue == 4) fMultiplier = 4.0f;
    else if (nDeterminerValue == 3) fMultiplier = 3.0f;
    else if (nDeterminerValue == 2) fMultiplier = 2.0f;
    else if (nDeterminerValue == 1) fMultiplier = 1.5f;
    else if (nDeterminerValue == 0) fMultiplier = 1.0f;
    return fMultiplier;
}
 
// This base value adjustment to XP's awarded is needed to duplicate the XP values
// given in the 3rd ed D&D XP tables.
float BaseAwardAdjustment(int nCreatureCR, int nPartyLvl)
{
    int nCRDifference = nCreatureCR-nPartyLvl;
    float fBaseAwardAdjustment;
    if      (nCRDifference ==  7) fBaseAwardAdjustment = -25200.0f;
    else if (nCRDifference ==  6) fBaseAwardAdjustment = -14400.0f;
    else if (nCRDifference ==  5) fBaseAwardAdjustment =  -9000.0f;
    else if (nCRDifference ==  4) fBaseAwardAdjustment =  -4800.0f;
    else if (nCRDifference ==  3) fBaseAwardAdjustment =  -2700.0f;
    else if (nCRDifference ==  2) fBaseAwardAdjustment =  -1200.0f;
    else if (nCRDifference ==  1) fBaseAwardAdjustment =   -450.0f;
    else if (nCRDifference ==  0) fBaseAwardAdjustment =      0.0f;
    else if (nCRDifference == -1) fBaseAwardAdjustment =    200.0f;
    else if (nCRDifference == -2) fBaseAwardAdjustment =    300.0f;
    else if (nCRDifference == -3) fBaseAwardAdjustment =    300.0f;
    else if (nCRDifference == -4) fBaseAwardAdjustment =    300.0f;
    else if (nCRDifference == -5) fBaseAwardAdjustment =    275.0f;
    else if (nCRDifference == -6) fBaseAwardAdjustment =    250.0f;
    else if (nCRDifference == -7) fBaseAwardAdjustment =    237.5f;
    return fBaseAwardAdjustment;
}
 
int XPFromAnEncounter(int nPartyLevel, float fCreatureCR, float fPercentAwarded = 100.0f)
{
    // PNP D&D XP tables are set to a base experience of 300.
    int BASEEXPERIENCE = 300;
    int nDivisor = Divisor(fCreatureCR);
 
    // The minimum CR for figuring xp award is 1.0.  If less than that, set to 1.0 by default.
    if(fCreatureCR<1.0f) fCreatureCR=1.0f;
 
    int nCreatureCR = FloatToInt(fCreatureCR);
    int nCreatureCRvsPartyLevel = nCreatureCR-nPartyLevel;
    int nXpsToAwardForTheKill = BASEEXPERIENCE * nCreatureCR;
    float fXpsToAwardForTheKill;
 
 
    // If the difference between the CR and player levels is greater than 7, return no xp's awarded.
    if      (abs(nCreatureCRvsPartyLevel) > 7) return 0;
    // Otherwise, if the creatures CR is equal to or greater than the party's level
    else if (nCreatureCRvsPartyLevel >= 0)
        fXpsToAwardForTheKill = nXpsToAwardForTheKill * Multiplier(nCreatureCR, nPartyLevel);
    // The creatures CR is less than the party's level
    else
        fXpsToAwardForTheKill = nXpsToAwardForTheKill / Multiplier(nCreatureCR, nPartyLevel);
 
    fXpsToAwardForTheKill += BaseAwardAdjustment(nCreatureCR, nPartyLevel);
    nXpsToAwardForTheKill = FloatToInt(fXpsToAwardForTheKill);
 
    fPercentAwarded/=100.0;
    nXpsToAwardForTheKill/=nDivisor;
    return nXpsToAwardForTheKill = FloatToInt((nXpsToAwardForTheKill * fPercentAwarded)+0.01);
}

               
               

               
            

Legacy_KMdS!

  • Sr. Member
  • ****
  • Posts: 364
  • Karma: +0/-0
KMdS's content creations
« Reply #6 on: May 25, 2016, 06:29:32 am »


               

I created a system that is based on the loot creation tables from D&D. he example below is for weapon generation. it uses a base weapon and applied item properties to it on the fly. Also gives a basic descriptive name to the item. Let me post a piece of it here. If you think it worth the effort I can pull it from my server and post to vault...I have never release any of my work before, but there is much I would share now.


 


A call to any of the methods included in the void main will generate a totally custom item on the fly.


 


Create the required base weapon items for the system in the toolset. Look at the GetIs* meathods/functions to see what the required resrefs are for the base weapon items and have some fun.


 


/*::////////////////////////////////////////////////////////////////////////////
//:: Name: KMdS PNP Hard Core Rule Set 1.0
//:: System: KMdS AD&D Treasure System
//:: FileName Gen_My_Weapons
//:: Copyright (c) 2004 Michael Careaga
//::////////////////////////////////////////////////////////////////////////////
 
    This script controls what type of magical/mundane weapons are created on a spawned
    monster based on the loot table used in the spawn_cfg_loot.nss script for
    any encounter.
 
    You may add any custom weapons here if you so chose.  To do this
    you must use the ResRef's for all custom items.  All you need for any
    original NWN weapons is the TAG of the weapons.  It is as true to the pen and
    paper d&d system as is possible given the scripting and item possibilities
    of NWN and is designed for use with the NESS 8.3 spawn system.
 
    Files incuded in this system are the following.....
    Gen_My_Mundane              Gen_My_Magic
    Gen_My_Armor                Gen_My_Bags
    Gen_My_Belts                Gen_My_Boots
    Gen_My_Cloaks               Gen_My_Neck
    Gen_My_Potions              Gen_My_Rings
    Gen_My_Rods                 Gen_My_Scrolls
    Gen_My_Staffs               Gen_My_Weapons
    Gen_My_Wands                Gen_My_Art
    Scrolls_Struct              Init_Scroll_Cnt
    Init_Wand_Cnt               Gen_My_Magic_Inc
    Wands_Struct
 
//::////////////////////////////////////////////////////////////////////////////
//:: Created By: Kilr Mik d Spik
//:: Created On: 12/18/2005
//:://////////////////////////////////////////////////////////////////////////*/
 
//  ----------------------------------------------------------------------------
//  LIBRARIES
//  ----------------------------------------------------------------------------
 
#include "x2_inc_itemprop"
 
//  ----------------------------------------------------------------------------
//  PROTOTYPES
//  ----------------------------------------------------------------------------
 
// The total number of properties to be placed upon an item with a base minimum
// of one property and a maximum of two properties.  Set nChance to the base
// percent roll needed for multiple properties to exist on an item.  If no there
// is no possible chance for more than 1 property, set nChance to 101 or more.
int DoesWeaponHaveOneOrTwoProperties(int nChance);
 
int GetIsSlashingWeapon(object oWeapon);
 
int GetIsBludgeoningWeapon(object oWeapon);
 
int GetIsPiercingWeapon(object oWeapon);
 
int GetIsThrownWeapon(object oWeapon);
 
int GetIsNonThrownRangedWeapon(object oWeapon);
 
int GetWeaponDamageType(object oWeapon);
 
string AmmunitionType();
 
string CommonWeaponType();
 
string UncommonWeaponType();
 
string CommonRangedWeaponType();
 
string WeaponTypeDeterimination(int iRoll = FALSE);
 
void CreateBaneWeapon(object oWeapon, int nAttackBonus = 0);
 
void AddBanePropertyToWeapon(object oWeapon, int nRacialType, int nDamageBonus, int nAttackBonus = 0);
 
void MinorWeaponItemProperties(object oWeapon);
 
void MediumWeaponItemProperties(object oWeapon);
 
void MajorWeaponItemProperties(object oWeapon);
 
void WeaponLight(object oWeapon);
 
void GenerateMundaneWeapon(object oSpawned, int nQty = 1, int nWeapon = FALSE);
 
void GenerateMasterworkCommonWeapon(object oSpawned, int nQty = 1);
 
void GenerateMasterworkUncommonWeapon(object oSpawned, int nQty = 1);
 
void GenerateMasterworkRangedWeapon(object oSpawned, int nQty = 1);
 
void GenerateMinorMagicWeapon(object oSpawned, int nQty = 1, int nWeapon = FALSE);
 
void GenerateMediumMagicWeapon(object oSpawned, int nQty = 1, int nWeapon = FALSE);
 
void GenerateMajorMagicWeapon(object oSpawned, int nQty = 1, int nWeapon = FALSE);
 
//  ----------------------------------------------------------------------------
//  FUNCTIONS
//  ----------------------------------------------------------------------------
 
int DoesWeaponHaveOneOrTwoProperties(int nChance)
{
    int nProperties = 1;
    int nRoll = d100();
    if (nRoll >= nChance) nProperties = 2;
    return nProperties;
}
 
int GetIsSlashingWeapon(object oWeapon)
{
    int bIsSlashingWeapon = TestStringAgainstPattern("**¬"+GetStringLowerCase(GetTag(oWeapon))+"¬**",
        "¬dwarvenwaraxe¬bastardsword¬scimitar¬longsword¬kama¬greatsword¬greataxe¬throwingaxe¬twobladedsword¬scythe¬"+
        "sickle¬whip¬kukri¬katana¬handaxe¬halberd¬battleaxe¬doubleaxe¬");
    return bIsSlashingWeapon;
}
 
int GetIsBludgeoningWeapon(object oWeapon)
{
    int bIsBludgeoningWeapon = TestStringAgainstPattern("**¬"+GetStringLowerCase(GetTag(oWeapon))+"¬**",
        "¬club¬heavyflail¬lightflail¬lighthammer¬warhammer¬mace¬morningstar¬diremace¬quarterstaff¬bullet¬");
    return bIsBludgeoningWeapon;
}
 
int GetIsPiercingWeapon(object oWeapon)
{
    int bIsPiercingWeapon = TestStringAgainstPattern("**¬"+GetStringLowerCase(GetTag(oWeapon))+"¬**",
        "¬bastardsword¬longsword¬greatsword¬scythe¬katana¬halberd¬doubleaxe¬shuriken¬dart¬spear¬"+
        "rapier¬dagger¬bolt¬arrow¬");
    return bIsPiercingWeapon;
}
 
int GetIsThrownWeapon(object oWeapon)
{
    int bIsThrowingWeapon = TestStringAgainstPattern("**¬"+GetStringLowerCase(GetTag(oWeapon))+"¬**",
        "¬shuriken¬dart¬throwingaxe¬");
    return bIsThrowingWeapon;
}
 
int GetIsNonThrownRangedWeapon(object oWeapon)
{
    int bIsThrowingWeapon = TestStringAgainstPattern("**¬"+GetStringLowerCase(GetResRef(oWeapon))+"¬**",
        "¬compositelbow004¬compositelbow003¬compositelbow002¬compositelbow001¬compositelbow¬longbow¬sling¬compositesbow002¬compositesbow001¬compositesbow¬"+
        "shortbow¬lightcrossbow¬heavycrossbow¬");
    return bIsThrowingWeapon;
}
 
int GetWeaponDamageType(object oWeapon)
{
    int nDamageType;
    if      (GetIsSlashingWeapon(oWeapon)    == TRUE)   nDamageType = IP_CONST_DAMAGETYPE_SLASHING;
    else if (GetIsBludgeoningWeapon(oWeapon) == TRUE)   nDamageType = IP_CONST_DAMAGETYPE_BLUDGEONING;
    else                                                nDamageType = IP_CONST_DAMAGETYPE_PIERCING;
    return nDamageType;
}
 
string CommonWeaponType()
{
    string sTemplate;
    int nRoll = Random(92)+1;
    if      (nRoll >=82) sTemplate = "dwarvenwaraxe";
    else if (nRoll >=77) sTemplate = "shortsword";
    else if (nRoll >=67) sTemplate = "bastardsword";
    else if (nRoll >=63) sTemplate = "spear";
    else if (nRoll >=58) sTemplate = "scimitar";
    else if (nRoll >=54) sTemplate = "rapier";
    else if (nRoll >=51) sTemplate = "quarterstaff";
    else if (nRoll >=42) sTemplate = "mace";
    else if (nRoll >=29) sTemplate = "longsword";
    else if (nRoll >=25) sTemplate = "kama";
    else if (nRoll >=15) sTemplate = "greatsword";
    else if (nRoll >= 5) sTemplate = "greataxe";
    else                 sTemplate = "dagger";
 
    return sTemplate;
}
 
string UncommonWeaponType()
{
    string sTemplate;
    int nRoll = Random(52)+1;
    if      (nRoll >=50) sTemplate = "whip";
    else if (nRoll >=47) sTemplate = "warhammer";
    else if (nRoll >=44) sTemplate = "twobladedsword";
    else if (nRoll >=41) sTemplate = "sickle";
    else if (nRoll >=39) sTemplate = "shuriken";
    else if (nRoll >=37) sTemplate = "scythe";
    else if (nRoll >=35) sTemplate = "morningstar";
    else if (nRoll >=32) sTemplate = "kukri";
    else if (nRoll >=29) sTemplate = "katana";
    else if (nRoll >=27) sTemplate = "handaxe";
    else if (nRoll >=25) sTemplate = "lighthammer";
    else if (nRoll >=22) sTemplate = "halberd";
    else if (nRoll >=18) sTemplate = "lightflail";
    else if (nRoll >=13) sTemplate = "heavyflail";
    else if (nRoll >=10) sTemplate = "diremace";
    else if (nRoll >= 8) sTemplate = "club";
    else if (nRoll >= 4) sTemplate = "battleaxe";
    else                 sTemplate = "doubleaxe";
 
    return sTemplate;
}
 
string CommonRangedWeaponType()
{
    string sTemplate;
    int nRoll = Random(98)+1;
    if      (nRoll >=94) sTemplate = "compositelbow004";
    else if (nRoll >=89) sTemplate = "compositelbow003";
    else if (nRoll >=84) sTemplate = "compositelbow002";
    else if (nRoll >=79) sTemplate = "compositelbow001";
    else if (nRoll >=74) sTemplate = "compositelbow";
    else if (nRoll >=64) sTemplate = "longbow";
    else if (nRoll >=60) sTemplate = "sling";
    else if (nRoll >=55) sTemplate = "compositesbow002";
    else if (nRoll >=50) sTemplate = "compositesbow001";
    else if (nRoll >=45) sTemplate = "compositesbow";
    else if (nRoll >=40) sTemplate = "shortbow";
    else if (nRoll >=36) sTemplate = "dart";
    else if (nRoll >=26) sTemplate = "lightcrossbow";
    else if (nRoll >=16) sTemplate = "heavycrossbow";
    else if (nRoll >=11) sTemplate = "throwingaxe";
    else                 sTemplate = AmmunitionType();
 
    return sTemplate;
}
 
string AmmunitionType()
{
    string sTemplate;
    int nRoll = Random(100)+1;
    if      (nRoll >=81) sTemplate = "bullet";
    else if (nRoll >=51) sTemplate = "bolt";
    else                 sTemplate = "arrow";
 
    return sTemplate;
}
 
string WeaponTypeDeterimination(int iRoll = FALSE)
{
    string sTemplate;
    if(iRoll == FALSE)
        iRoll = d100();
    if      (iRoll >= 81)   sTemplate = CommonRangedWeaponType();
    else if (iRoll >= 71)   sTemplate = UncommonWeaponType();
    else                    sTemplate = CommonWeaponType();
 
    return sTemplate;
}
 
void CreateBaneWeapon(object oWeapon, int nAttackBonus = 0)
{
    string sName = "";
    int nRacialType;
    int iRoll = d100();
    if      (iRoll >= 95) {
        if (FindSubString(GetName(oWeapon), "Aberration Bane") != -1)
            CreateBaneWeapon(oWeapon, nAttackBonus);
        else{
            nRacialType = IP_CONST_RACIALTYPE_ABERRATION;
            sName = "Aberration Bane ";
        }
    }
    else if (iRoll >= 92) {
        if (FindSubString(GetName(oWeapon), "Animal Bane") != -1)
            CreateBaneWeapon(oWeapon, nAttackBonus);
        else{
            nRacialType = IP_CONST_RACIALTYPE_ANIMAL;
            sName = "Animal Bane ";
        }
    }
    else if (iRoll >= 87) {
        if (FindSubString(GetName(oWeapon), "Beast Bane") != -1)
            CreateBaneWeapon(oWeapon, nAttackBonus);
        else{
            nRacialType = IP_CONST_RACIALTYPE_BEAST;
            sName = "Beast Bane ";
        }
    }
    else if (iRoll >= 80) {
        if (FindSubString(GetName(oWeapon), "Construct Bane") != -1)
            CreateBaneWeapon(oWeapon, nAttackBonus);
        else{
            nRacialType = IP_CONST_RACIALTYPE_CONSTRUCT;
            sName = "Construct Bane ";
            }
        }
    else if (iRoll >= 75) {
        if (FindSubString(GetName(oWeapon), "Dragon Bane") != -1)
            CreateBaneWeapon(oWeapon, nAttackBonus);
        else{
            nRacialType = IP_CONST_RACIALTYPE_DRAGON;
            sName = "Dragon Bane ";
        }
    }
    else if (iRoll >= 74) {
        if (FindSubString(GetName(oWeapon), "Dwarf Bane") != -1)
            CreateBaneWeapon(oWeapon, nAttackBonus);
        else{
            nRacialType = IP_CONST_RACIALTYPE_DWARF;
            sName = "Dwarf Bane ";
        }
    }
    else if (iRoll >= 69) {
        if (FindSubString(GetName(oWeapon), "Elemental Bane") != -1)
            CreateBaneWeapon(oWeapon, nAttackBonus);
        else{
            nRacialType = IP_CONST_RACIALTYPE_ELEMENTAL;
            sName = "Elemental Bane ";
        }
    }
    else if (iRoll >= 68) {
        if (FindSubString(GetName(oWeapon), "Elf Bane") != -1)
            CreateBaneWeapon(oWeapon, nAttackBonus);
        else{
            nRacialType = IP_CONST_RACIALTYPE_ELF;
            sName = "Elf Bane ";
        }
    }
    else if (iRoll >= 63) {
        if (FindSubString(GetName(oWeapon), "Fey Bane") != -1)
            CreateBaneWeapon(oWeapon, nAttackBonus);
        else{
            nRacialType = IP_CONST_RACIALTYPE_FEY;
            sName = "Fey Bane ";
        }
    }
    else if (iRoll >= 58) {
        if (FindSubString(GetName(oWeapon), "Giant Bane") != -1)
            CreateBaneWeapon(oWeapon, nAttackBonus);
        else{
            nRacialType = IP_CONST_RACIALTYPE_GIANT;
            sName = "Giant Bane ";
        }
    }
    else if (iRoll >= 57) {
        if (FindSubString(GetName(oWeapon), "Gnome Bane") != -1)
            CreateBaneWeapon(oWeapon, nAttackBonus);
        else{
            nRacialType = IP_CONST_RACIALTYPE_GNOME;
            sName = "Gnome Bane ";
        }
    }
    else if (iRoll >= 56) {
        if (FindSubString(GetName(oWeapon), "Half-Elf Bane") != -1)
            CreateBaneWeapon(oWeapon, nAttackBonus);
        else{
            nRacialType = IP_CONST_RACIALTYPE_HALFELF;
            sName = "Half-Elf Bane ";
        }
    }
    else if (iRoll >= 55) {
        if (FindSubString(GetName(oWeapon), "Halfling Bane") != -1)
            CreateBaneWeapon(oWeapon, nAttackBonus);
        else{
            nRacialType = IP_CONST_RACIALTYPE_HALFLING;
            sName = "Halfling Bane ";
        }
    }
    else if (iRoll >= 54) {
        if (FindSubString(GetName(oWeapon), "Half-Orc Bane") != -1)
            CreateBaneWeapon(oWeapon, nAttackBonus);
        else{
            nRacialType = IP_CONST_RACIALTYPE_HALFORC;
            sName = "Half-Orc Bane ";
        }
    }
    else if (iRoll >= 53) {
        if (FindSubString(GetName(oWeapon), "Human Bane") != -1)
            CreateBaneWeapon(oWeapon, nAttackBonus);
        else{
            nRacialType = IP_CONST_RACIALTYPE_HUMAN;
            sName = "Human Bane ";
        }
    }
    else if (iRoll >= 52) {
        if (FindSubString(GetName(oWeapon), "Goblin Bane") != -1)
            CreateBaneWeapon(oWeapon, nAttackBonus);
        else{
            nRacialType = IP_CONST_RACIALTYPE_HUMANOID_GOBLINOID;
            sName = "Goblin Bane ";
        }
    }
    else if (iRoll >= 47) {
        if (FindSubString(GetName(oWeapon), "Monstrous Humaniod Bane") != -1)
            CreateBaneWeapon(oWeapon, nAttackBonus);
        else{
            nRacialType = IP_CONST_RACIALTYPE_HUMANOID_MONSTROUS;
            sName = "Monstrous Humaniod Bane ";
        }
    }
    else if (iRoll >= 46) {
        if (FindSubString(GetName(oWeapon), "Orc Bane") != -1)
            CreateBaneWeapon(oWeapon, nAttackBonus);
        else{
            nRacialType = IP_CONST_RACIALTYPE_HUMANOID_ORC;
            sName = "Orc Bane ";
        }
    }
    else if (iRoll >= 45) {
        if (FindSubString(GetName(oWeapon), "Reptilian Bane") != -1)
            CreateBaneWeapon(oWeapon, nAttackBonus);
        else{
            nRacialType = IP_CONST_RACIALTYPE_HUMANOID_REPTILIAN;
            sName = "Reptilian Bane ";
        }
    }
    else if (iRoll >= 40) {
        if (FindSubString(GetName(oWeapon), "Magical Beast Bane") != -1)
            CreateBaneWeapon(oWeapon, nAttackBonus);
        else{
            nRacialType = IP_CONST_RACIALTYPE_MAGICAL_BEAST;
            sName = "Magical Beast Bane ";
        }
    }
    else if (iRoll >= 18) {
        if (FindSubString(GetName(oWeapon), "Outsider Bane") != -1)
            CreateBaneWeapon(oWeapon, nAttackBonus);
        else{
            nRacialType = IP_CONST_RACIALTYPE_OUTSIDER;
            sName = "Outsider Bane ";
        }
    }
    else if (iRoll >= 10) {
        if (FindSubString(GetName(oWeapon), "Shapchanger Bane") != -1)
            CreateBaneWeapon(oWeapon, nAttackBonus);
        else{
            nRacialType = IP_CONST_RACIALTYPE_SHAPECHANGER;
            sName = "Shapchanger Bane ";
        }
    }
    else if (iRoll >=  3) {
        if (FindSubString(GetName(oWeapon), "Undead Bane") != -1)
            CreateBaneWeapon(oWeapon, nAttackBonus);
        else{
            nRacialType = IP_CONST_RACIALTYPE_UNDEAD;
            sName = "Undead Bane ";
        }
    }
    else {
        if (FindSubString(GetName(oWeapon), "Vermin Bane") != -1)
            CreateBaneWeapon(oWeapon, nAttackBonus);
        else{
            nRacialType = IP_CONST_RACIALTYPE_VERMIN;
            sName = "Vermin Bane ";
        }
    }
    AddBanePropertyToWeapon(oWeapon, nRacialType, IP_CONST_DAMAGEBONUS_2d6, nAttackBonus);
    SetName(oWeapon, sName+GetName(oWeapon));
}
 
void AddBanePropertyToWeapon(object oWeapon, int nRacialType, int nDamageBonus, int nAttackBonus = 0)
{
    itemproperty ipAdd;
    if (GetIsThrownWeapon(oWeapon) == TRUE || IPGetIsMeleeWeapon(oWeapon) == TRUE)
    {
        ipAdd = ItemPropertyEnhancementBonusVsRace(nRacialType,IPGetWeaponEnhancementBonus(oWeapon) + 2);
        IPSafeAddItemProperty(oWeapon, ipAdd);
    }
    if (GetIsThrownWeapon(oWeapon) == TRUE || IPGetIsMeleeWeapon(oWeapon) == TRUE || IPGetIsProjectile(oWeapon) == TRUE)
    {
        ipAdd = ItemPropertyDamageBonusVsRace(nRacialType,GetWeaponDamageType(oWeapon),nDamageBonus);
        IPSafeAddItemProperty(oWeapon, ipAdd);
    }
    if (nAttackBonus >=1)
    {
        ipAdd = ItemPropertyAttackBonusVsRace(nRacialType, nAttackBonus + 2);
        IPSafeAddItemProperty(oWeapon, ipAdd);
    }
}
 
 
void MinorWeaponItemProperties(object oWeapon)
{
    if (GetIsNonThrownRangedWeapon(oWeapon) == TRUE)
        return;
 
    int nChanceOfMultipleItemProperties = 100;
 
    if (IPGetIsProjectile(oWeapon) == TRUE)
        nChanceOfMultipleItemProperties = 101;
 
    string sName = "";
    itemproperty ipAdd;
    int nProperties = DoesWeaponHaveOneOrTwoProperties(nChanceOfMultipleItemProperties);
    int iRoll = Random(100)+1;
    if (iRoll >= 86)
    {
        int i;
        for (i = 0; i < nProperties; i++)
        {
            iRoll = Random(55)+1;
            if      (iRoll >= 46)
            {
                if (FindSubString(GetName(oWeapon), "Fire") != -1)
                    i--;
                else{
                    ipAdd = ItemPropertyDamageBonus(IP_CONST_DAMAGETYPE_FIRE, IP_CONST_DAMAGEBONUS_1d6);
                    if (i == 0) sName = " of Fire";         if (i == 1) sName = " and Fire";
                    IPSafeAddItemProperty(oWeapon, ipAdd);
                }
            }
            else if (iRoll >= 36)
            {
                if (FindSubString(GetName(oWeapon), "Ice") != -1)
                    i--;
                else{
                    ipAdd = ItemPropertyDamageBonus(IP_CONST_DAMAGETYPE_COLD, IP_CONST_DAMAGEBONUS_1d6);
                    if (i == 0) sName = " of Ice";         if (i == 1) sName = " and Ice";
                    IPSafeAddItemProperty(oWeapon, ipAdd);
                }
            }
            else if (iRoll >= 26)
            {
                if (FindSubString(GetName(oWeapon), "Electricity") != -1)
                    i--;
                else{
                    ipAdd = ItemPropertyDamageBonus(IP_CONST_DAMAGETYPE_ELECTRICAL, IP_CONST_DAMAGEBONUS_1d6);
                    if (i == 0) sName = " of Electricity";         if (i == 1) sName = " and Electricity";
                    IPSafeAddItemProperty(oWeapon, ipAdd);
                }
            }
            else if (iRoll >= 11)
            {
                if (GetIsSlashingWeapon(oWeapon) == TRUE && IPGetIsMeleeWeapon(oWeapon) == TRUE)
                {
                    if (FindSubString(GetName(oWeapon), "Keen") != -1)
                        i--;
                    else{
                        ipAdd = ItemPropertyKeen();
                        sName = "Keen ";
                        IPSafeAddItemProperty(oWeapon, ipAdd);
                    }
                }
                else i--;
            }
            else
            {
                if (IPGetIsMeleeWeapon(oWeapon) == TRUE)
                {
                    if (FindSubString(GetName(oWeapon), "Cleaving") != -1)
                        i--;
                    else{
                        ipAdd = ItemPropertyBonusFeat(IP_CONST_FEAT_CLEAVE);
                        sName = "Cleaving ";
                        IPSafeAddItemProperty(oWeapon, ipAdd);
                    }
                }
                else i--;
            }
            if (sName == "Keen " || sName == "Cleaving ")
                SetName(oWeapon, sName+GetName(oWeapon));
            else
                SetName(oWeapon, GetName(oWeapon)+sName);
        }
    }
}
 
void MediumWeaponItemProperties(object oWeapon)
{
    if (GetIsNonThrownRangedWeapon(oWeapon) == TRUE)
        return;
 
    int nChanceOfMultipleItemProperties = 96;
 
    if (IPGetIsProjectile(oWeapon) == TRUE)
        nChanceOfMultipleItemProperties = 99;
 
    string sName = "";
    itemproperty ipAdd1;
    itemproperty ipAdd2;
    int nProperties = DoesWeaponHaveOneOrTwoProperties(nChanceOfMultipleItemProperties);
    int iRoll = Random(100)+1;
    if (iRoll >= 69)
    {
        int i;
        for (i = 0; i < nProperties; i++)
        {
            iRoll = Random(61)+1;
            if      (iRoll >= 57)
            {
                if (FindSubString(GetName(oWeapon), "Fire") != -1){
                    i--;
                }
                else{
                    ipAdd1 = ItemPropertyDamageBonus(IP_CONST_DAMAGETYPE_FIRE, IP_CONST_DAMAGEBONUS_1d6);
                    if (i == 0) sName = " of Fire";         if (i == 1) sName = " and Fire";
                    IPSafeAddItemProperty(oWeapon, ipAdd1);
                }
            }
            else if (iRoll >= 52)
            {
                if (FindSubString(GetName(oWeapon), "Ice") != -1){
                    i--;
                }
                else{
                    ipAdd1 = ItemPropertyDamageBonus(IP_CONST_DAMAGETYPE_COLD, IP_CONST_DAMAGEBONUS_1d6);
                    if (i == 0) sName = " of Ice";         if (i == 1) sName = " and Ice";
                    IPSafeAddItemProperty(oWeapon, ipAdd1);
                }
            }
            else if (iRoll >= 47)
            {
                if (FindSubString(GetName(oWeapon), "Electricity") != -1){
                    i--;
                }
                else{
                    ipAdd1 = ItemPropertyDamageBonus(IP_CONST_DAMAGETYPE_ELECTRICAL, IP_CONST_DAMAGEBONUS_1d6);
                    if (i == 0) sName = " of Electricity";         if (i == 1) sName = " and Electricity";
                    IPSafeAddItemProperty(oWeapon, ipAdd1);
                }
            }
            else if (iRoll >= 37)
            {
                if (GetIsSlashingWeapon(oWeapon) == TRUE)
                {
                    if (FindSubString(GetName(oWeapon), "Keen") != -1){
                        i--;
                    }
                    else{
                        ipAdd1 = ItemPropertyKeen();
                        sName = "Keen ";
                        IPSafeAddItemProperty(oWeapon, ipAdd1);
                    }
                }
                else i--;
            }
            else if (iRoll >=  27)
            {
                if (IPGetIsMeleeWeapon(oWeapon) == TRUE)
                {
                    if (FindSubString(GetName(oWeapon), "Cleaving") != -1){
                        i--;
                    }
                    else{
                        ipAdd1 = ItemPropertyBonusFeat(FEAT_GREAT_CLEAVE);
                        sName = "Cleaving ";
                        IPSafeAddItemProperty(oWeapon, ipAdd1);
                    }
                }
                else i--;
            }
            else if (iRoll >=  24)
            {
                CreateBaneWeapon(oWeapon);
            }
            else if (iRoll >=  21)
            {
                if (GetIsBludgeoningWeapon(oWeapon) == TRUE && IPGetIsProjectile(oWeapon) == FALSE)
                {
                    if (FindSubString(GetName(oWeapon), "Undead Slaying") != -1){
                        i--;
                    }
                    else{
                        ipAdd1 = ItemPropertyOnHitProps(IP_CONST_ONHIT_SLAYRACE, 14, IP_CONST_RACIALTYPE_UNDEAD);
                        if (i == 0) sName = " of Undead Slaying";         if (i == 1) sName = " and Undead Slaying";
                        IPSafeAddItemProperty(oWeapon, ipAdd1);
                    }
                }
                else i--;
            }
            else if (iRoll >=  16)
            {
                if (FindSubString(GetName(oWeapon), "Sonic") != -1){
                    i--;
                }
                else{
                    ipAdd1 = ItemPropertyDamageBonus(IP_CONST_DAMAGETYPE_SONIC, IP_CONST_DAMAGEBONUS_1d6);
                    sName = "Sonic ";
                    IPSafeAddItemProperty(oWeapon, ipAdd1);
                }
            }
            else if (iRoll >=  13)
            {
                if ( IPGetIsProjectile(oWeapon) == FALSE)
                {
                    if (FindSubString(GetName(oWeapon), "Wounding") != -1){
                        i--;
                    }
                    else{
                        ipAdd1 = ItemPropertyOnHitProps(IP_CONST_ONHIT_WOUNDING, IP_CONST_ONHIT_SAVEDC_16);
                        if (i == 0) sName = " of Wounding";         if (i == 1) sName = " and Wounding";
                        IPSafeAddItemProperty(oWeapon, ipAdd1);
                    }
                }
            }
            else if (iRoll >=  10)
            {
                if (FindSubString(GetName(oWeapon), "Holy") != -1){
                    i--;
                }
                else{
                    ipAdd1 = ItemPropertyDamageBonusVsAlign(IP_CONST_ALIGNMENTGROUP_EVIL, GetWeaponDamageType(oWeapon), IP_CONST_DAMAGEBONUS_2d6);
                    ipAdd2 = ItemPropertyLimitUseByAlign(IP_CONST_ALIGNMENTGROUP_GOOD);
                    sName = "Holy ";
                    IPSafeAddItemProperty(oWeapon, ipAdd1);
                    IPSafeAddItemProperty(oWeapon, ipAdd2);
                }
            }
            else if (iRoll >=  7)
            {
                if (FindSubString(GetName(oWeapon), "UnHoly") != -1){
                    i--;
                }
                else{
                    ipAdd1 = ItemPropertyDamageBonusVsAlign(IP_CONST_ALIGNMENTGROUP_GOOD, GetWeaponDamageType(oWeapon), IP_CONST_DAMAGEBONUS_2d6);
                    ipAdd2 = ItemPropertyLimitUseByAlign(IP_CONST_ALIGNMENTGROUP_EVIL);
                    sName = "UnHoly ";
                    IPSafeAddItemProperty(oWeapon, ipAdd1);
                    IPSafeAddItemProperty(oWeapon, ipAdd2);
                }
            }
            else if (iRoll >=  4)
            {
                if (FindSubString(GetName(oWeapon), "Lawful") != -1){
                    i--;
                }
                else{
                    ipAdd1 = ItemPropertyDamageBonusVsAlign(IP_CONST_ALIGNMENTGROUP_CHAOTIC, GetWeaponDamageType(oWeapon), IP_CONST_DAMAGEBONUS_2d6);
                    ipAdd2 = ItemPropertyLimitUseByAlign(IP_CONST_ALIGNMENTGROUP_LAWFUL);
                    sName = "Lawful ";
                    IPSafeAddItemProperty(oWeapon, ipAdd1);
                    IPSafeAddItemProperty(oWeapon, ipAdd2);
                }
            }
            else
            {
                if (FindSubString(GetName(oWeapon), "Chaotic") != -1){
                    i--;
                }
                else{
                    ipAdd1 = ItemPropertyDamageBonusVsAlign(IP_CONST_ALIGNMENTGROUP_LAWFUL, GetWeaponDamageType(oWeapon), IP_CONST_DAMAGEBONUS_2d6);
                    ipAdd2 = ItemPropertyLimitUseByAlign(IP_CONST_ALIGNMENTGROUP_CHAOTIC);
                    sName = "Chaotic ";
                    IPSafeAddItemProperty(oWeapon, ipAdd1);
                    IPSafeAddItemProperty(oWeapon, ipAdd2);
                }
            }
            if (sName == "Keen " || sName == "Cleaving " || sName == "Sonic " || sName == "Holy " ||
              sName == "UnHoly " || sName == "Lawful " ||sName == "Chaotic ")
                SetName(oWeapon, sName+GetName(oWeapon));
            else
                SetName(oWeapon, GetName(oWeapon)+sName);
        }
    }
}
 
void MajorWeaponItemProperties(object oWeapon)
{
    if (GetIsNonThrownRangedWeapon(oWeapon) == TRUE)
        return;
 
    int nChanceOfMultipleItemProperties = 81;
 
    if (IPGetIsProjectile(oWeapon) == TRUE)
        nChanceOfMultipleItemProperties = 98;
 
    string sName = "";
    itemproperty ipAdd1;
    itemproperty ipAdd2;
    int nProperties = DoesWeaponHaveOneOrTwoProperties(nChanceOfMultipleItemProperties);
    int iRoll = Random(100)+1;
    if (iRoll >= 64)
    {
        int i;
        for (i = 0; i < nProperties; i++)
        {
            iRoll = Random(50)+1;
            if      (iRoll >= 48)
            {
                if (FindSubString(GetName(oWeapon), "Fire") != -1){
                    i--;
                }
                else{
                    ipAdd1 = ItemPropertyDamageBonus(IP_CONST_DAMAGETYPE_FIRE, IP_CONST_DAMAGEBONUS_1d6);
                    if (i == 0) sName = " of Fire";         if (i == 1) sName = " and Fire";
                    IPSafeAddItemProperty(oWeapon, ipAdd1);
                }
            }
            else if (iRoll >= 45)
            {
                if (FindSubString(GetName(oWeapon), "Ice") != -1){
                    i--;
                }
                else{
                    ipAdd1 = ItemPropertyDamageBonus(IP_CONST_DAMAGETYPE_COLD, IP_CONST_DAMAGEBONUS_1d6);
                    if (i == 0) sName = " of Ice";         if (i == 1) sName = " and Ice";
                    IPSafeAddItemProperty(oWeapon, ipAdd1);
                }
            }
            else if (iRoll >= 42)
            {
                if (FindSubString(GetName(oWeapon), "Electricity") != -1){
                    i--;
                }
                else{
                    ipAdd1 = ItemPropertyDamageBonus(IP_CONST_DAMAGETYPE_ELECTRICAL, IP_CONST_DAMAGEBONUS_1d6);
                    if (i == 0) sName = " of Electricity";         if (i == 1) sName = " and Electricity";
                    IPSafeAddItemProperty(oWeapon, ipAdd1);
                }
            }
            else if (iRoll >=  37)
            {
                if (IPGetIsMeleeWeapon(oWeapon) == TRUE)
                {
                    if (FindSubString(GetName(oWeapon), "Great Cleaving") != -1){
                        i--;
                    }
                    else{
                        ipAdd1 = ItemPropertyBonusFeat(FEAT_GREAT_CLEAVE);
                        sName = "Great Cleaving ";
                        IPSafeAddItemProperty(oWeapon, ipAdd1);
                    }
                }
                else i--;
            }
            else if (iRoll >=  32)
            {
                CreateBaneWeapon(oWeapon);
            }
            else if (iRoll >=  29)
            {
                if (GetIsBludgeoningWeapon(oWeapon) == TRUE && IPGetIsProjectile(oWeapon) == FALSE)
                {
                    if (FindSubString(GetName(oWeapon), "Undead Slaying") != -1){
                        i--;
                    }
                    else{
                        ipAdd1 = ItemPropertyOnHitProps(IP_CONST_ONHIT_SLAYRACE, 14, IP_CONST_RACIALTYPE_UNDEAD);
                        if (i == 0) sName = " of Undead Slaying";   if (i == 1) sName = " and Undead Slaying";
                        IPSafeAddItemProperty(oWeapon, ipAdd1);
                    }
                }
                else i--;
            }
            else if (iRoll >=  26)
            {
                if (FindSubString(GetName(oWeapon), "Sonic") != -1){
                    i--;
                }
                else{
                    ipAdd1 = ItemPropertyDamageBonus(IP_CONST_DAMAGETYPE_SONIC, IP_CONST_DAMAGEBONUS_1d6);
                    sName = "Sonic ";
                    IPSafeAddItemProperty(oWeapon, ipAdd1);
                }
            }
            else if (iRoll >=  24)
            {
                if ( IPGetIsProjectile(oWeapon) == FALSE)
                {
                    if (FindSubString(GetName(oWeapon), "Wounding") != -1){
                        i--;
                    }
                    else{
                        ipAdd1 = ItemPropertyOnHitProps(IP_CONST_ONHIT_WOUNDING, IP_CONST_ONHIT_SAVEDC_16);
                        if (i == 0) sName = " of Wounding";   if (i == 1) sName = " and Wounding";
                        IPSafeAddItemProperty(oWeapon, ipAdd1);
                    }
                }
            }
            else if (iRoll >=  19)
            {
                if (FindSubString(GetName(oWeapon), "Holy") != -1){
                    i--;
                }
                else{
                    ipAdd1 = ItemPropertyDamageBonusVsAlign(IP_CONST_ALIGNMENTGROUP_EVIL, GetWeaponDamageType(oWeapon), IP_CONST_DAMAGEBONUS_2d6);
                    ipAdd2 = ItemPropertyLimitUseByAlign(IP_CONST_ALIGNMENTGROUP_GOOD);
                    sName = "Holy ";
                    IPSafeAddItemProperty(oWeapon, ipAdd1);
                    IPSafeAddItemProperty(oWeapon, ipAdd2);
                }
            }
            else if (iRoll >=  14)
            {
                if (FindSubString(GetName(oWeapon), "UnHoly") != -1){
                    i--;
                }
                else{
                    ipAdd1 = ItemPropertyDamageBonusVsAlign(IP_CONST_ALIGNMENTGROUP_GOOD, GetWeaponDamageType(oWeapon), IP_CONST_DAMAGEBONUS_2d6);
                    ipAdd2 = ItemPropertyLimitUseByAlign(IP_CONST_ALIGNMENTGROUP_EVIL);
                    sName = "UnHoly ";
                    IPSafeAddItemProperty(oWeapon, ipAdd1);
                    IPSafeAddItemProperty(oWeapon, ipAdd2);
                }
            }
            else if (iRoll >=  9)
            {
                if (FindSubString(GetName(oWeapon), "Lawfull") != -1){
                    i--;
                }
                else{
                    ipAdd1 = ItemPropertyDamageBonusVsAlign(IP_CONST_ALIGNMENTGROUP_CHAOTIC, GetWeaponDamageType(oWeapon), IP_CONST_DAMAGEBONUS_2d6);
                    ipAdd2 = ItemPropertyLimitUseByAlign(IP_CONST_ALIGNMENTGROUP_LAWFUL);
                    sName = "Lawfull ";
                    IPSafeAddItemProperty(oWeapon, ipAdd1);
                    IPSafeAddItemProperty(oWeapon, ipAdd2);
                }
            }
            else if (iRoll >=  4)
            {
                if (FindSubString(GetName(oWeapon), "Chaotic") != -1){
                    i--;
                }
                else{
                    ipAdd1 = ItemPropertyDamageBonusVsAlign(IP_CONST_ALIGNMENTGROUP_LAWFUL, GetWeaponDamageType(oWeapon), IP_CONST_DAMAGEBONUS_2d6);
                    ipAdd2 = ItemPropertyLimitUseByAlign(IP_CONST_ALIGNMENTGROUP_CHAOTIC);
                    sName = "Chaotic ";
                    IPSafeAddItemProperty(oWeapon, ipAdd1);
                    IPSafeAddItemProperty(oWeapon, ipAdd2);
                }
            }
            else
            {
                if (GetIsSlashingWeapon(oWeapon) == TRUE)
                {
                    if (FindSubString(GetName(oWeapon), "Vorpal") != -1){
                        i--;
                    }
                    else{
                        ipAdd1 = ItemPropertyOnHitProps(IP_CONST_ONHIT_VORPAL,IP_CONST_ONHIT_SAVEDC_26);
                        sName = "Vorpal ";
                        IPSafeAddItemProperty(oWeapon, ipAdd1);
                    }
                }
                else i--;
            }
            if (sName == "Keen " || sName == "Great Cleaving " || sName == "Sonic " || sName == "Holy " ||
              sName == "UnHoly " || sName == "Lawful " ||sName == "Chaotic " ||sName == "Vorpal ")
                SetName(oWeapon, sName+GetName(oWeapon));
            else
                SetName(oWeapon, GetName(oWeapon)+sName);
        }
    }
}
 
void WeaponLight(object oWeapon)
{
    if (IPGetIsProjectile(oWeapon) == TRUE)
        return;
 
    int nRoll = d100();
    int nBrightness = IP_CONST_LIGHTBRIGHTNESS_BRIGHT;
    int nColor;
    if (nRoll >= 71)
    {
        //Get the first itemproperty on the helmet
        itemproperty ipLoop=GetFirstItemProperty(oWeapon);
 
        //Loop for as long as the ipLoop variable is valid unill the first unique property is found for light.
        while (GetIsItemPropertyValid(ipLoop))
        {
            if (IPGetIsProjectile(oWeapon) == FALSE)
            {
                if      (GetItemPropertyType(ipLoop)==ITEM_PROPERTY_DAMAGE_BONUS && GetItemPropertySubType(ipLoop) == IP_CONST_DAMAGETYPE_ACID)
                    {nColor = IP_CONST_LIGHTCOLOR_GREEN;break;}
                else if (GetItemPropertyType(ipLoop)==ITEM_PROPERTY_DAMAGE_BONUS && GetItemPropertySubType(ipLoop) == IP_CONST_DAMAGETYPE_COLD)
                    {nColor = IP_CONST_LIGHTCOLOR_BLUE;break;}
                else if (GetItemPropertyType(ipLoop)==ITEM_PROPERTY_DAMAGE_BONUS && GetItemPropertySubType(ipLoop) == IP_CONST_DAMAGETYPE_DIVINE)
                    {nColor = IP_CONST_LIGHTCOLOR_WHITE;break;}
                else if (GetItemPropertyType(ipLoop)==ITEM_PROPERTY_DAMAGE_BONUS && GetItemPropertySubType(ipLoop) == IP_CONST_DAMAGETYPE_ELECTRICAL)
                    {nColor = IP_CONST_LIGHTCOLOR_PURPLE;break;}
                else if (GetItemPropertyType(ipLoop)==ITEM_PROPERTY_DAMAGE_BONUS && GetItemPropertySubType(ipLoop) == IP_CONST_DAMAGETYPE_FIRE)
                    {nColor = IP_CONST_LIGHTCOLOR_ORANGE;break;}
                else if (GetItemPropertyType(ipLoop)==ITEM_PROPERTY_DAMAGE_BONUS && GetItemPropertySubType(ipLoop) == IP_CONST_DAMAGETYPE_MAGICAL)
                    {nColor = IP_CONST_LIGHTCOLOR_WHITE;break;}
                else if (GetItemPropertyType(ipLoop)==ITEM_PROPERTY_DAMAGE_BONUS && GetItemPropertySubType(ipLoop) == IP_CONST_DAMAGETYPE_NEGATIVE)
                    {nColor = IP_CONST_LIGHTCOLOR_RED;break;}
                else if (GetItemPropertyType(ipLoop)==ITEM_PROPERTY_DAMAGE_BONUS && GetItemPropertySubType(ipLoop) == IP_CONST_DAMAGETYPE_POSITIVE)
                    {nColor = IP_CONST_LIGHTCOLOR_BLUE;break;}
                else if (GetItemPropertyType(ipLoop)==ITEM_PROPERTY_DAMAGE_BONUS && GetItemPropertySubType(ipLoop) == IP_CONST_DAMAGETYPE_SONIC)
                    {nColor = IP_CONST_LIGHTCOLOR_WHITE;break;}
                else if (GetItemPropertyType(ipLoop)==ITEM_PROPERTY_DAMAGE_BONUS_VS_ALIGNMENT_GROUP && GetItemPropertySubType(ipLoop) == IP_CONST_ALIGNMENTGROUP_CHAOTIC)
                    {nColor = IP_CONST_LIGHTCOLOR_PURPLE;break;}
                else if (GetItemPropertyType(ipLoop)==ITEM_PROPERTY_DAMAGE_BONUS_VS_ALIGNMENT_GROUP && GetItemPropertySubType(ipLoop) == IP_CONST_ALIGNMENTGROUP_EVIL)
                    {nColor = IP_CONST_LIGHTCOLOR_WHITE;break;}
                else if (GetItemPropertyType(ipLoop)==ITEM_PROPERTY_DAMAGE_BONUS_VS_ALIGNMENT_GROUP && GetItemPropertySubType(ipLoop) == IP_CONST_ALIGNMENTGROUP_GOOD)
                    {nColor = IP_CONST_LIGHTCOLOR_RED;break;}
                else if (GetItemPropertyType(ipLoop)==ITEM_PROPERTY_DAMAGE_BONUS_VS_ALIGNMENT_GROUP && GetItemPropertySubType(ipLoop) == IP_CONST_ALIGNMENTGROUP_LAWFUL)
                    {nColor = IP_CONST_LIGHTCOLOR_ORANGE;break;}
                else if (IPGetItemHasItemOnHitPropertySubType(oWeapon, 24)) //Vorpal
                    {nColor = IP_CONST_LIGHTCOLOR_ORANGE;break;}
                else if (IPGetItemHasItemOnHitPropertySubType(oWeapon, 25)) //Wounding
                    {nColor = IP_CONST_LIGHTCOLOR_RED;break;}
                else
                    nColor = IP_CONST_LIGHTCOLOR_YELLOW;
            }
 
            //Next itemproperty on the list...
            ipLoop=GetNextItemProperty(oWeapon);
        }
        itemproperty ipAdd = ItemPropertyLight(nBrightness, nColor);
        IPSafeAddItemProperty(oWeapon, ipAdd);
    }
}
 
void GenerateMundaneWeapon(object oSpawned, int nQty = 1, int nWeapon = FALSE)
{
    int i;
    for(i=0; i<nQty; i++){
        int nQty = 1;
        string sTemplate = WeaponTypeDeterimination();
        if (sTemplate == "bullet" || sTemplate == "arrow" || sTemplate == "bolt") nQty = 99;
        if (sTemplate == "shuriken" || sTemplate == "throwingaxe" || sTemplate == "dart") nQty = 50;
        object oWeapon = CreateItemOnObject(sTemplate, oSpawned, nQty);
    }
}
 
void GenerateMasterworkCommonWeapon(object oSpawned, int nQty = 1)
{
    int i;
    for(i=0; i<nQty; i++){
        string sTemplate = CommonWeaponType();
        object oWeapon = CreateItemOnObject(sTemplate, oSpawned, 1);
 
        if (GetIsObjectValid(oWeapon) == FALSE) return;
 
        itemproperty ipAdd = ItemPropertyAttackBonus(1);
        IPSafeAddItemProperty(oWeapon, ipAdd);
        SetName(oWeapon, "Masterwork "+GetName(oWeapon));
    }
}
 
void GenerateMasterworkUncommonWeapon(object oSpawned, int nQty = 1)
{
    int i;
    for(i=0; i<nQty; i++){
        int nQty = 1;
        string sTemplate = UncommonWeaponType();
        if (sTemplate == "bullet" || sTemplate == "arrow" || sTemplate == "bolt") nQty = 99;
        if (sTemplate == "shuriken" || sTemplate == "throwingaxe" || sTemplate == "dart") nQty = 50;
        object oWeapon = CreateItemOnObject(sTemplate, oSpawned, nQty);
 
        if (GetIsObjectValid(oWeapon) == FALSE) return;
 
        itemproperty ipAdd = ItemPropertyAttackBonus(1);
        IPSafeAddItemProperty(oWeapon, ipAdd);
        SetName(oWeapon, "Masterwork "+GetName(oWeapon));
    }
}
 
void GenerateMasterworkRangedWeapon(object oSpawned, int nQty = 1)
{
    int i;
    for(i=0; i<nQty; i++){
        int nQty = 1;
        string sTemplate = CommonRangedWeaponType();
        if (sTemplate == "bullet" || sTemplate == "arrow" || sTemplate == "bolt") nQty = 99;
        if (sTemplate == "shuriken" || sTemplate == "throwingaxe" || sTemplate == "dart") nQty = 50;
        object oWeapon = CreateItemOnObject(sTemplate, oSpawned, nQty);
 
        if (GetIsObjectValid(oWeapon) == FALSE) return;
 
        itemproperty ipAdd = ItemPropertyAttackBonus(1);
        if (IPGetIsProjectile(oWeapon) == TRUE)
            ipAdd = ItemPropertyDamageBonus(GetWeaponDamageType(oWeapon), IP_CONST_DAMAGEBONUS_1);
        IPSafeAddItemProperty(oWeapon, ipAdd);
        SetName(oWeapon, "Masterwork "+GetName(oWeapon));
    }
}
 
void GenerateMinorMagicWeapon(object oSpawned, int nQty = 1, int nWeapon = FALSE)
{
    int i;
    for(i=0; i<nQty; i++){
        string sName = "";
        int nQty = 1;
        string sTemplate = WeaponTypeDeterimination();
        if (sTemplate == "bullet" || sTemplate == "arrow" || sTemplate == "bolt") nQty = 99;
        if (sTemplate == "shuriken" || sTemplate == "throwingaxe" || sTemplate == "dart") nQty = 50;
        object oWeapon = CreateItemOnObject(sTemplate, oSpawned, nQty);
        int nEnchantmentBonus;
        int iRoll;
        itemproperty ipAdd;
        int nDamageType;
 
        if (GetIsObjectValid(oWeapon) == FALSE) return;
 
        if (IPGetIsProjectile(oWeapon) == FALSE && GetIsNonThrownRangedWeapon(oWeapon) == FALSE)
        {
            iRoll = Random(85)+1;
            nEnchantmentBonus = 1;
            if (iRoll >= 71) nEnchantmentBonus = 2;
            ipAdd = ItemPropertyEnhancementBonus(nEnchantmentBonus);
            SetName(oWeapon, GetName(oWeapon)+" +"+IntToString(nEnchantmentBonus));
            IPSafeAddItemProperty(oWeapon, ipAdd);
        }
 
        else if (IPGetIsProjectile(oWeapon) == TRUE)// (bolt, arrow, etc)
        {
            iRoll = Random(85)+1;
            nDamageType = IP_CONST_DAMAGETYPE_PIERCING;
            sName = " of Piercing";
            if(GetStringLowerCase(GetTag(oWeapon))=="bullet"){
                nDamageType = IP_CONST_DAMAGETYPE_BLUDGEONING;
                sName = " of Bludgeoning";
            }
            nEnchantmentBonus = IP_CONST_DAMAGEBONUS_1;
            if (iRoll >= 71)
                nEnchantmentBonus = IP_CONST_DAMAGEBONUS_2;
            sName += (" +"+IntToString(nEnchantmentBonus));
            SetName(oWeapon, GetName(oWeapon)+sName);
            ipAdd = ItemPropertyDamageBonus(nDamageType, nEnchantmentBonus);
            IPSafeAddItemProperty(oWeapon, ipAdd);
        }
 
        else if (GetIsNonThrownRangedWeapon(oWeapon) == TRUE)
        {
            iRoll = Random(85)+1;
            nEnchantmentBonus = 1;
            if (iRoll >= 71) nEnchantmentBonus = 2;
            SetName(oWeapon, GetName(oWeapon)+" +"+IntToString(nEnchantmentBonus));
            ipAdd = ItemPropertyAttackBonus(nEnchantmentBonus);
            IPSafeAddItemProperty(oWeapon, ipAdd);
        }
        if (GetIsNonThrownRangedWeapon(oWeapon) == FALSE)
            MinorWeaponItemProperties(oWeapon);
        WeaponLight(oWeapon);
    }
}
 
void GenerateMediumMagicWeapon(object oSpawned, int nQty = 1, int nWeapon = FALSE)
{
    int i;
    for(i=0; i<nQty; i++){
        string sName = "";
        int nQty = 1;
        string sTemplate = WeaponTypeDeterimination();
        if (sTemplate == "bullet" || sTemplate == "arrow" || sTemplate == "bolt") nQty = 99;
        if (sTemplate == "shuriken" || sTemplate == "throwingaxe" || sTemplate == "dart") nQty = 50;
        object oWeapon = CreateItemOnObject(sTemplate, oSpawned, nQty);
        int nEnchantmentBonus;
        int iRoll;
        itemproperty ipAdd;
        int nDamageType;
 
        if (GetIsObjectValid(oWeapon) == FALSE) return;
 
        if (IPGetIsProjectile(oWeapon) == FALSE && GetIsNonThrownRangedWeapon(oWeapon) == FALSE)
        {
            iRoll = Random(62)+1;
            nEnchantmentBonus = 1;
            if      (iRoll >= 59) nEnchantmentBonus = 4;
            else if (iRoll >= 21) nEnchantmentBonus = 3;
            else if (iRoll >= 11) nEnchantmentBonus = 2;
            ipAdd = ItemPropertyEnhancementBonus(nEnchantmentBonus);
            SetName(oWeapon, GetName(oWeapon)+" +"+IntToString(nEnchantmentBonus));
            IPSafeAddItemProperty(oWeapon, ipAdd);
        }
 
        else if (IPGetIsProjectile(oWeapon) == TRUE)
        {
            iRoll = Random(62)+1;
            nDamageType = IP_CONST_DAMAGETYPE_PIERCING;
            sName = " of Piercing";
            if(GetStringLowerCase(GetTag(oWeapon))=="bullet"){
                nDamageType = IP_CONST_DAMAGETYPE_BLUDGEONING;
                sName = " of Bludgeoning";
            }
            nEnchantmentBonus = IP_CONST_DAMAGEBONUS_1;
            if      (iRoll >= 59) nEnchantmentBonus = IP_CONST_DAMAGEBONUS_4;
            else if (iRoll >= 21) nEnchantmentBonus = IP_CONST_DAMAGEBONUS_3;
            else if (iRoll >= 11) nEnchantmentBonus = IP_CONST_DAMAGEBONUS_2;
            sName += (" +"+IntToString(nEnchantmentBonus));
            SetName(oWeapon, GetName(oWeapon)+sName);
            ipAdd = ItemPropertyDamageBonus(nDamageType, nEnchantmentBonus);
            IPSafeAddItemProperty(oWeapon, ipAdd);
        }
 
        else if (GetIsNonThrownRangedWeapon(oWeapon) == TRUE)
        {
            iRoll = Random(62)+1;
            nEnchantmentBonus = 1;
            if      (iRoll >= 59) nEnchantmentBonus = 4;
            else if (iRoll >= 21) nEnchantmentBonus = 3;
            else if (iRoll >= 11) nEnchantmentBonus = 2;
            SetName(oWeapon, GetName(oWeapon)+" +"+IntToString(nEnchantmentBonus));
            ipAdd = ItemPropertyAttackBonus(nEnchantmentBonus);
            IPSafeAddItemProperty(oWeapon, ipAdd);
            iRoll = d100();
            if (iRoll >= 69) CreateBaneWeapon(oWeapon, nEnchantmentBonus);
        }
        if (GetIsNonThrownRangedWeapon(oWeapon) == FALSE)
            MediumWeaponItemProperties(oWeapon);
        WeaponLight(oWeapon);
    }
}
 
void GenerateMajorMagicWeapon(object oSpawned, int nQty = 1, int nWeapon = FALSE)
{
    int i;
    for(i=0; i<nQty; i++){
        string sName = "";
        int nQty = 1;
        string sTemplate = WeaponTypeDeterimination();
        if (sTemplate == "bullet" || sTemplate == "arrow" || sTemplate == "bolt") nQty = 99;
        if (sTemplate == "shuriken" || sTemplate == "throwingaxe" || sTemplate == "dart") nQty = 50;
        object oWeapon = CreateItemOnObject(sTemplate, oSpawned, nQty);
        int nEnchantmentBonus;
        int iRoll;
        itemproperty ipAdd;
        int nDamageType;
 
        if (GetIsObjectValid(oWeapon) == FALSE) return;
 
        if (IPGetIsProjectile(oWeapon) == FALSE && GetIsNonThrownRangedWeapon(oWeapon) == FALSE)
        {
            iRoll = Random(49)+1;
            nEnchantmentBonus = 3;
            if      (iRoll >= 39) nEnchantmentBonus = 5;
            else if (iRoll >= 21) nEnchantmentBonus = 4;
            ipAdd = ItemPropertyEnhancementBonus(nEnchantmentBonus);
            SetName(oWeapon, GetName(oWeapon)+" +"+IntToString(nEnchantmentBonus));
            IPSafeAddItemProperty(oWeapon, ipAdd);
        }
 
        else if (IPGetIsProjectile(oWeapon) == TRUE)
        {
            iRoll = Random(49)+1;
            nDamageType = IP_CONST_DAMAGETYPE_PIERCING;
            sName = " of Piercing";
            if(GetStringLowerCase(GetTag(oWeapon))=="bullet"){
                nDamageType = IP_CONST_DAMAGETYPE_BLUDGEONING;
                sName = " of Bludgeoning";
            }
            nEnchantmentBonus = IP_CONST_DAMAGEBONUS_3;
            if      (iRoll >= 39) nEnchantmentBonus = IP_CONST_DAMAGEBONUS_5;
            else if (iRoll >= 21) nEnchantmentBonus = IP_CONST_DAMAGEBONUS_4;
            sName += (" +"+IntToString(nEnchantmentBonus));
            SetName(oWeapon, GetName(oWeapon)+sName);
            ipAdd = ItemPropertyDamageBonus(nDamageType, nEnchantmentBonus);
            IPSafeAddItemProperty(oWeapon, ipAdd);
        }
 
        else if (GetIsNonThrownRangedWeapon(oWeapon) == TRUE)
        {
            iRoll = Random(62)+1;
            nEnchantmentBonus = 3;
            if      (iRoll >= 39) nEnchantmentBonus = 5;
            else if (iRoll >= 21) nEnchantmentBonus = 4;
            SetName(oWeapon, GetName(oWeapon)+" +"+IntToString(nEnchantmentBonus));
            ipAdd = ItemPropertyAttackBonus(nEnchantmentBonus);
            IPSafeAddItemProperty(oWeapon, ipAdd);
            iRoll = d100();
            if (iRoll >= 64) CreateBaneWeapon(oWeapon, nEnchantmentBonus);
        }
        if (GetIsNonThrownRangedWeapon(oWeapon) == FALSE)
            MajorWeaponItemProperties(oWeapon);
        WeaponLight(oWeapon);
    }
}
/* For compiling
void main()
{
    GenerateMajorMagicWeapon(OBJECT_SELF);
    GenerateMediumMagicWeapon(OBJECT_SELF);
    GenerateMinorMagicWeapon(OBJECT_SELF);
    GenerateMasterworkRangedWeapon(OBJECT_SELF);
    GenerateMasterworkUncommonWeapon(OBJECT_SELF);
    GenerateMasterworkCommonWeapon(OBJECT_SELF);
    GenerateMundaneWeapon(OBJECT_SELF);
}
// Naming conventions done for NWN v1.67

               
               

               
            

Legacy_KMdS!

  • Sr. Member
  • ****
  • Posts: 364
  • Karma: +0/-0
KMdS's content creations
« Reply #7 on: May 25, 2016, 06:38:30 am »


               

Here is a simple Function to teleport a PC to any valid location you may pass using the lDest variable.


 


void Transport(object oPC, location lDest)
{
    if (!GetIsObjectValid(oPC))
        return;
    if (!GetIsObjectValid(GetArea(oPC)))
    {
        DelayCommand(1.0, Transport(oPC));
    }
    else if(GetTag(GetArea(oPC)) != "Tag of area desired")
    {
        AssignCommand(oPC, JumpToLocation(lDest));    
    }
}

 


Because of the AssignCommand,It will jump the player to the location after the algorythm terminate and will reattempt every 1.0 seconds until the PC is in a valid location. You can call this from either the onenter module event or the onenter area event.


 


As to implementation from your areas onenter, but best is to place in your modules onenter event as it is the first event to fire on a pc. You can create an include script something like HCR had.


 


// inc_on_ae
 
int preEvent()
{
    Transport(oPC, lDest);
return TRUE;
}
 
void postEvent()
{
    return TRUE;
}

 


Place an include into the event script you desire affected and place preEvent() as the very first call in your void main  and the postEvent() as the last call. Place any routine you wish to run within those functions and you can affect all event scripts containing the include. If you wish not to affect a certain area, just place a conditional pertaining to the area as a check.

 

I set an area check in the include script example above to make sure the PC is only jumped once. If not exactly what you need, I can modify if I know more about what you need.

 

If you don't want the pc to see anything until they arrive on destination a black out and fade from black can be set up as well.


               
               

               
            

Legacy_KMdS!

  • Sr. Member
  • ****
  • Posts: 364
  • Karma: +0/-0
KMdS's content creations
« Reply #8 on: May 25, 2016, 06:46:56 am »


               

The hard coded game can equip it to the CARMOUR slot but you cannot equip a skin to the proper slot w/o scripting it. Here is a  function/method that will equip a skin on a PC. Checks are included for an existing equipped skin against the specific skin desired.


Documentation is located within the script code.


void EquipCArmorSlot(object oPC)
{
    // The resref of the skin you want equiped
    string sSkinResRef = "whatever resref you want";
    // Retrieve any existing item is slot CARMOUR
object oSkin = GetItemInSlot(INVENTORY_SLOT_CARMOUR, oPC);
 
    // Check if anything is equipped in the creature armor slot
    int bSlotEquipped = oSkin!=OBJECT_INVALID;
    // if not, equip them
    if(!bSlotEquipped)
    {
        oSkin = CreateItemOnObject(sSkinResRef, oPC);
        AssignCommand(oPC, ActionEquipItem(oSkin,INVENTORY_SLOT_CARMOUR));
    }
    // Check to see if they have the skin I want them to have, if not....
    else if(GetResRef(oSkin) != sSkinResRef)
    {
        //Prepare to destroy the existing skin
        SetPlotFlag(oSkin, FALSE);
        AssignCommand(oSkin, SetIsDestroyable(TRUE, FALSE));
        //Destroy the skin 0.0 seconds after we complete this algorythm
        DestroyObject(oSkin);
        // create and equip the new skin
        oSkin = CreateItemOnObject(sSkinResRef, oPC);
        AssignCommand(oPC, ActionEquipItem(oSkin,INVENTORY_SLOT_CARMOUR));
    }
 
}


               
               

               
            

Legacy_KMdS!

  • Sr. Member
  • ****
  • Posts: 364
  • Karma: +0/-0
KMdS's content creations
« Reply #9 on: May 25, 2016, 06:52:12 am »


               

I created this for a forum member and though it might be something others might like.



// encounter_oe
 
/*
 
    A quick simple spawn system I created for a forum menber that gives you the
    option to have random spawn locations.  To implement, place in your generic triggers
    on enter event and give your generic trigger a uniquie tag. Give your spawn waypoints
    the same tag but append a consecutive numeric value to the tag
 
    Example, generic trigger tag...
        MOBSPAWN
 
    Associated waypoint tags...
        MOBSPAWN1
        MOBSPAWN2
        etc....
 
    Set a local int named "NUMOFWPS' on WP#1 with the number of waypoints
    to be chosen from for the spawn location. This system will randomly
    pick between WP#1 and the qty to set as the spawn location.
 
    Set a local int named "QTY' on on WP#1 with the total number of creatures
    to be spawned.
 
    Set a local string named "RESREF" on WP#1 with the base resref of the
    creature to be spawned. Give all the creatures you want to spawn the
    same resref and append a consecutive numeric value
 
    Example stored "RESREF" value
    monster
 
    Example Creature resrefs...
    monster1
    monster2
    etc...
 
    Set a local int named "CREATURETYPES' on WP#1 with the numer of diferent creatures to
    be spawned. Using the resref examples above that list only 2 resrefs, monster1
    and monster2, set CREATURETYPES = 2 and you will get equal amounts of both in
    the spawn
 
    Set a local int named "PERCENT_CHANCE' on WP#1 for the chance of a spawn occurring.
 
    Set a local float named "DELAY' on WP#1 for the time before the trigger is active again.
    This is so that you can't activate the trigger again untill the passing in seconds
    of whatever delay you set. There is a default value of 20.0 seconds
 
    I think I covered it all. Have fun.... I like it so much I think I'll post it to
    the forum. Modify to suit your needs :)
 
*/
//  Set "QTY' with thE total number of creatures to be spawned
//  Set "CREATURETYPES' with the numer of diferent creature to be spawned
//  Set "RESREF' with the base resref
//  Set "NUMOFWPS' with the number of waypoints to be chosen from for the spawn location
//  Set "PERCENT_CHANCE' for the chance of a spawn occurring
void spawncreatures(int iQty, int iCreatureTypes, string sBaseTag, string sResRef, int nNbrOfWypnts, int iChance = 100);
void spawncreatures(int iQty, int iCreatureTypes, string sBaseTag, string sResRef, int nNbrOfWypnts, int iChance = 100)
{
    if(d100()<=iChance)
    {
        string sWPTag = sBaseTag+IntToString(Random(nNbrOfWypnts)+1);
        object oSpawnWP = GetWaypointByTag(sWPTag);
        location lSpawnPoint = GetLocation(oSpawnWP);
 
        int i;
        for(i=0;i<iQty;i++)
        {
            object oSpawn = CreateObject(OBJECT_TYPE_CREATURE, sResRef+IntToString((i%iCreatureTypes)+1), lSpawnPoint);
        }
    }
}
 
void ResetEncounter(float fDelay, object oRepository)
{
    DelayCommand(fDelay, SetLocalInt(oRepository, "ACTIVATED", FALSE));
}
 
void main()
{
    object oPC = GetEnteringObject();
    if(GetIsPC(oPC))
    {
        string sBaseTag = GetTag(OBJECT_SELF);
        object oRepository = GetObjectByTag(sBaseTag+"1");
 
        int bDoNotProcess = GetLocalInt(oRepository, "ACTIVATED");
        if(bDoNotProcess==FALSE)
        {
            int iQty =   GetLocalInt(oRepository, "QTY");
            int iCTypes = GetLocalInt(oRepository, "CREATURETYPES");
            string sResRef = GetLocalString(oRepository, "RESREF");
            int iWPs = GetLocalInt(oRepository, "NUMOFWPS");
            int iPctChance = GetLocalInt(oRepository, "PERCENT_CHANCE");
 
            spawncreatures(iQty, iCTypes, sBaseTag, sResRef, iWPs, iPctChance);
            SetLocalInt(oRepository, "ACTIVATED", TRUE);
            float fDelay =   GetLocalFloat(oRepository, "DELAY");
            if(fDelay == 0.0)
                fDelay = 20.0;
            AssignCommand(GetModule(), ResetEncounter(fDelay, oRepository));
        }
    }
}


               
               

               
            

Legacy_KMdS!

  • Sr. Member
  • ****
  • Posts: 364
  • Karma: +0/-0
KMdS's content creations
« Reply #10 on: May 25, 2016, 07:21:50 am »


               

Here is one of the various unique items I have created for my Orlanthia server from the AD&D pnp rulebooks. This replicated the rod of electrification.


 


This is a tag based script for the rod a copy of which can be downloaded at http://www.orlanthia...trification.uti. Download and insert the uti file and add the code below into a script file into your mod. Enable tag based scripts or include code to run the code below from any relevant module events.


 


ONHITCAST


EQUIP


UNEQUIP


UNACQUIRE


SPELLCAST_AT


 


As this is a "rod" by definition, I have a specific tool to allow the equi0ping of this item should the character not have the proficiency to weild a mace. I will see about adding the item to this repository.


 


/*::////////////////////////////////////////////////////////////////////////////
//:: Name: KMdS PNP Hard Core Rule Set 1.0
//:: System: KMdS Magic Systems
//:: SubSystem: KMdS AD&D Magic Items
//:: FileName: Electrification
//:: Copyright: (c) 2005 Michael Careaga
//::////////////////////////////////////////////////////////////////////////////
 
    This is a tag based script for reproducing the pnp rod of electrification.
    On any successful hit the rod will do 1d4+1 points of electrical damage and
    use 1 charge to do so.  The rod may be recharged by placing the rod on the
    ground and casting a lightning bolt spell at it.  The rod will recharge 1
    point per hit die of damage done by the lightning bolt.
 
    FILES INCLUDED IN THIS SUBSYSTEM PACKAGE
    Viper             Withering             Wizardry
    KMdS_Inc_Spells   Spell_Suggestion      Diplomacy
    Electrification   Spell_Entangle        Spell_Web
    Spell_HoldMons    Flailing              Spell_MageArmor
    LordlyMight       Ranike                Spell_Resurrect
    Smiting           Splendor              Equip_A_Rod
    ThunderLightning  Spell_DeafClang       x2_s3_DeafClng
    Spell_SoundBurst  Spell_ThndrLtng       Invisibility
 
//::////////////////////////////////////////////////////////////////////////////
//:: Created By: Kilr Mik d Spik
//:: Created On: 08/19/2005
//:://////////////////////////////////////////////////////////////////////////*/
 
//  ----------------------------------------------------------------------------
//  LIBRARIES
//  ----------------------------------------------------------------------------
 
#include "X0_I0_SPELLS"
#include "x2_inc_switches"
#include "nw_i0_generic"
 
//  ----------------------------------------------------------------------------
//  PROTOTYPES
//  ----------------------------------------------------------------------------
 
// Recharges an items charges.  Defauly increase is 1 charge.
void RechargeSpellCastingItem(object oItem, int nAdditionalCharges = 1);
 
//  ----------------------------------------------------------------------------
//  FUNCTIONS
//  ----------------------------------------------------------------------------
 
void RechargeSpellCastingItem(object oItem, int nAdditionalCharges = 1)
{
    SetItemCharges(oItem, GetItemCharges(oItem) + nAdditionalCharges);
}//  ----------------------------------------------------------------------------
//  MAIN
//  ----------------------------------------------------------------------------
 
void main()
{
    int nEvent = GetUserDefinedItemEventNumber(), nCharges;
    object oPC, oItem, oTarget;
    effect eVis, eBad;
 
//   SendMessageToPC(GetFirstPC(),IntToString(nEvent));
 
    // * This code runs when the item has the OnHitCastSpell: Unique power property
    // * and it hits a target(weapon) or is being hit (armor)
    // * Note that this event fires for non PC creatures as well.
    if (nEvent ==X2_ITEM_EVENT_ONHITCAST)
    {
        // The item casting triggering this spellscript
        oItem  =  GetSpellCastItem();
        object oSpellOrigin = OBJECT_SELF ;
        object oSpellTarget = GetSpellTargetObject();
        oPC = OBJECT_SELF;
 
        eVis = EffectVisualEffect(VFX_IMP_LIGHTNING_S);
        eBad = EffectDamage(d4()+1, DAMAGE_TYPE_ELECTRICAL);
        nCharges =  GetItemCharges(oItem);
 
        // This is me... used to debug        
        object oKMdS = GetLocalObject(GetModule(),"KMdS") ;
        if(oKMdS != OBJECT_INVALID && GetLocalInt(GetModule(),"DEBUG"))
            SendMessageToPC(oKMdS ,"The onhitcast event fired for the rod of electrification.  Item charges were "+IntToString(nCharges));
 
        if(nCharges)
        {
            SetItemCharges(oItem, nCharges -1);
            SignalEvent(oTarget, EventSpellCastAt(oPC, SPELL_ELECTRIC_JOLT));
            ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oSpellTarget);
            ApplyEffectToObject(DURATION_TYPE_INSTANT, eBad, oSpellTarget);
        }
    }
 
    // * This code runs when the Unique Power property of the item is used
    // * Note that this event fires PCs only
    else if (nEvent ==  X2_ITEM_EVENT_ACTIVATE)
    {
 
        oPC   = GetItemActivator();
        oItem = GetItemActivated();
        oTarget = GetItemActivatedTarget();
 
    }
 
    // * This code runs when the item is equipped
    // * Note that this event fires PCs only
    else if (nEvent ==X2_ITEM_EVENT_EQUIP)
    {
 
        oPC = GetPCItemLastEquippedBy();
        oItem = GetPCItemLastEquipped();
        object oPlayerSkin = GetItemInSlot(17, oPC);
 
        itemproperty ipProp1 = ItemPropertyBonusFeat(IP_CONST_FEAT_WEAPON_PROF_SIMPLE);
        IPSafeAddItemProperty(oPlayerSkin, ipProp1);
    }
 
    // * This code runs when the item is unequipped
    // * Note that this event fires PCs only
    else if (nEvent ==X2_ITEM_EVENT_UNEQUIP)
    {
 
        oPC    = GetPCItemLastUnequippedBy();
        oItem  = GetPCItemLastUnequipped();
        object oPlayerSkin = GetItemInSlot(17, oPC);
 
        IPRemoveMatchingItemProperties(oPlayerSkin, ITEM_PROPERTY_BONUS_FEAT, DURATION_TYPE_PERMANENT, IP_CONST_FEAT_WEAPON_PROF_SIMPLE);
    }
 
    // * This code runs when the item is acquired
    // * Note that this event fires PCs only
    else if (nEvent == X2_ITEM_EVENT_ACQUIRE)
    {
        oPC = GetModuleItemAcquiredBy();
        oItem  = GetModuleItemAcquired();
 
    }
 
 
    // * This code runs when the item is unaquired
    // * Note that this event fires PCs only
    else if (nEvent == X2_ITEM_EVENT_UNACQUIRE)
    {
 
        oPC = GetModuleItemLostBy();
        oItem  = GetModuleItemLost();
        object oPlayerSkin = GetItemInSlot(17, oPC);
 
        IPRemoveMatchingItemProperties(oPlayerSkin, ITEM_PROPERTY_BONUS_FEAT, DURATION_TYPE_PERMANENT, IP_CONST_FEAT_WEAPON_PROF_SIMPLE);
    }
 
    //* This code runs when a PC or DM casts a spell from one of the
    //* standard spellbooks on the item
    else if (nEvent == X2_ITEM_EVENT_SPELLCAST_AT)
    {
 
        oPC = GetModuleItemLostBy();
        oItem  = GetModuleItemLost();
        nCharges =  GetItemCharges(oItem);
        int nMaxCharges = 50 - nCharges;
        if(GetSpellId() == 101 && GetItemPossessor(oItem) == OBJECT_INVALID)
        {
            int nCasterLevel = GetCasterLevel(oPC);
            if(nCasterLevel >10) nCasterLevel = 10;
 
            nCharges = GetCasterLevel(oPC);
            if(nCharges > nMaxCharges) nCharges = nMaxCharges;
 
            RechargeSpellCastingItem(oItem, nCharges);
        }
    }
}


               
               

               
            

Legacy_KMdS!

  • Sr. Member
  • ****
  • Posts: 364
  • Karma: +0/-0
KMdS's content creations
« Reply #11 on: May 27, 2016, 03:42:45 am »


               

This is an alternate method to return the number of a specific item in an objects inventory.


If the Set bProcess is set to 1(TRUE) the searched for items will be stored locally on the object being searched to enable processing of the items without having to perform another loop to locate and process them. Only the instance is stored, to avoid any exploit in stacked items have whatever method you run count the number in the stack to reverify the count.


 


 


// Return the number of items with the tag provided.
 
// Set bProcess = TRUE to store the item instance for processing outside of this method
// and the total count of instances found.
// Retrieve an instance of an object by retrieving the local object "ITEM_NUMBER_*") stored
// on the target object, the * must be a number between 1 and the total count of instances stored in
/// the local variable int "ITEM_COUNT".
// Retrieve the total number of item instances by retrieving the local variable int "ITEM_COUNT"
// stored on the target object.
int GetNumberOfItemsInInventory(object oTarget,string sItemTag, int bProcess = FALSE);
int GetNumberOfItemsInInventory(object oTarget,string sItemTag, int bProcess = FALSE)
{
    int nNumItems = 0;
    int iIteration = 0;
 
    object oItem = GetFirstItemInInventory(oTarget);
    while (oItem != OBJECT_INVALID)
    {
        if (GetTag(oItem) == sItemTag)
        {
            nNumItems += GetNumStackedItems(oItem);
            if(bProcess)
            {
                // Store the item for retrieval outside this method
                SetLocalObject(oTarget, "ITEM_NUMBER_"+IntToString(++iIteration), oItem);
                /***Place whatever additional processing you want one here**/
            }
        }
        oItem = GetNextItemInInventory(oTarget);
    }
    if(bProcess)
    {
        // Store the number of instances found for retrieval outside this method
        SetLocalInt(oTarget, "ITEM_COUNT", iIteration);
        /***Place whatever additional processing you want one here**/
    }
 
   return nNumItems;
}

               
               

               
            

Legacy_KMdS!

  • Sr. Member
  • ****
  • Posts: 364
  • Karma: +0/-0
KMdS's content creations
« Reply #12 on: June 08, 2016, 07:14:30 pm »


               

Modified the random magic weapon creation methods....


 


Found holes in the code that allowed for double naming of an item property in an items name, missed adding "continue" to code in loop to avoid processing the item naming section of code...hey, gimme a break, I made this code about a decade ago, back when I was only an exceptional coder..... '<img'>  '<img'>  '<img'>  '<img'>