- #include "gs_inc_common"
- #include "mi_log"
- // The PropertyStruct is used to pass information about properties between functions.
- struct PropertyStruct
- {
- // The id corresponds to one of the constants below, depending on gear type.
- int id;
- // The modifiers are used to store each property value.
- // The first modifier is usually the type of property, e.g. cold resistance.
- int mod1;
- // The second modifier is usually the amount of the property, e.g. +3.
- int mod2;
- };
- // The ProperyVarNameStruct is used to pass the string names for each index so that
- // they can be accesses in a consistent way using Get/SetLocalVariable.
- struct PropertyVarNameStruct
- {
- string id;
- string mod1;
- string mod2;
- };
- // The max number of properties that can be spawned on an artifact.
- const int MAX_PROPERTY_COUNT = 4;
- const int WEAPON_PROPERTY_COUNT = 10;
- const int WEAPON_ENH_BONUS = 0;
- const int WEAPON_AB_BONUS = 1;
- const int WEAPON_ENH_BONUS_VS_RACE = 2;
- const int WEAPON_ELEMENTAL_DAMAGE = 3;
- const int WEAPON_ABILITY_BONUS = 4;
- const int WEAPON_SKILL_BONUS = 5;
- const int WEAPON_MASSIVE_CRITICALS = 6;
- const int WEAPON_MISC_BONUSES = 7;
- const int WEAPON_AMMO_OR_VAMP_REGEN = 8;
- const int WEAPON_USAGE_RESTRICTION = 9;
- const int ARMOUR_PROPERTY_COUNT = 8;
- const int ARMOUR_AC_BONUS = 0;
- const int ARMOUR_AC_BONUS_VS_RACE = 1;
- const int ARMOUR_SAVE_BONUS = 2;
- const int ARMOUR_SPECIFIC_SAVE_BONUS = 3;
- const int ARMOUR_ELEMENTAL_DR = 4;
- const int ARMOUR_ABILITY_BONUS = 5;
- const int ARMOUR_SKILL_BONUS = 6;
- const int ARMOUR_USAGE_RESTRICTION = 7;
- const int GEAR_PROPERTY_COUNT = 8;
- const int GEAR_AC_BONUS = 0;
- const int GEAR_AC_BONUS_VS_RACE = 1;
- const int GEAR_SAVE_BONUS = 2;
- const int GEAR_SPECIFIC_SAVE_BONUS = 3;
- const int GEAR_ELEMENTAL_DR = 4;
- const int GEAR_ABILITY_BONUS = 5;
- const int GEAR_SKILL_BONUS = 6;
- const int GEAR_USAGE_RESTRICTION = 7;
- const int USAGE_RESTRICTION_CLASS = 0;
- const int USAGE_RESTRICTION_RACE = 1;
- const int MISC_BONUS_VISUAL = 1;
- const int MISC_BONUS_FREEDOM = 2;
- const int MISC_BONUS_FEAR = 3;
- const int MISC_BONUS_LIGHT = 4;
- const int ITEM_TYPE_WEAPON = 0;
- const int ITEM_TYPE_ARMOUR = 1;
- const int ITEM_TYPE_GEAR = 2;
- const int INVALID_PROPERTY = -1;
- // The maximum amount of gold that can spawn in an artifact chest.
- const int PICKUP_GOLD_LIMIT = 1000;
- // The lowest possible value of an artifact.
- // This is set to 250 by default to avoid the useless artifacts that are generated with
- // only one property, which is a restriction property.
- const int GOLD_FLOOR = 250;
- // Creates a weapon of a random type on OBJECT_SELF and returns it.
- object createWeapon();
- // Creates armour of a random type on OBJECT_SELF and returns it.
- object createArmour();
- // Creates gear of a random type on OBJECT_SELF and returns it.
- object createGear();
- // Applies randomly generated properties suitable for a weapon to an item.
- // If ranged is true, can generate unlimited ammo, otherwise, can generate vamp regen.
- void applyWeaponStats(object weapon, int ranged);
- // Applies randomly generated properties suitable for armour to an item.
- void applyArmourStats(object armour);
- // Applies randomly generated properties suitable for gear to an item.
- void applyGearStats(object gear);
- // Applies the generic artifact name and "found at <x>" description to the item.
- void applyDescription(object item);
- // Fetches the property with the given index from the current object's variable list.
- struct PropertyStruct getProperty(int index);
- // Sets the property with the given index from the current object's variable list.
- void setProperty(int index, struct PropertyStruct property);
- // Returns a unique property that is not already present on the item.
- struct PropertyStruct getUniqueWeaponProperty(int ranged);
- // Returns a unique property that is not already present on the item.
- struct PropertyStruct getUniqueArmourProperty();
- // Returns a unique property that is not already present on the item.
- struct PropertyStruct getUniqueGearProperty();
- // Returns true if the provided property is valid and unique, or false otherwise.
- int isWeaponPropertyValid(struct PropertyStruct property);
- // Returns true if the provided property is valid and unique, or false otherwise.
- int isArmourPropertyValid(struct PropertyStruct property);
- // Returns true if the provided property is valid and unique, or false otherwise.
- int isGearPropertyValid(struct PropertyStruct property);
- // Checks if the property with the given index from the current object's variable list is set.
- int isPropertyUsed(int property);
- // Locates and returns the property with the provided id.
- // Optionally, provide a second integer to skip n hits.
- struct PropertyStruct findProperty(int propertyId, int nth = 0);
- // Returns a struct of property var names for the given index, to acces with Get/SetLocalVariable.
- struct PropertyVarNameStruct getPropertyVarNames(int index);
- // Unsets the variables 0 -> MAX_PROPERTY_COUNT.
- void cleanupPropertyVars();
- // Outputs the generated properties to a log file.
- void writePropertiesToLog(int propertyCount, int itemType);
- // Utility method to return a basic object resref of the provided type.
- string getResRefByItemType(int itemType);
- void main()
- {
- if (GetLocalInt(OBJECT_SELF, "GS_ENABLED") || GetIsObjectValid(GetFirstItemInInventory()))
- {
- return;
- }
- cleanupPropertyVars();
- object item = OBJECT_INVALID;
- string containerTag = GetTag(OBJECT_SELF);
- do
- {
- if (containerTag == "GS_WEAPON_UNIQUE")
- {
- item = createWeapon();
- if (!GetIsObjectValid(item))
- {
- return;
- }
- int itemType = GetBaseItemType(item);
- // Only count ranged weapons that consume separate ammunition as ranged.
- int ranged = itemType == BASE_ITEM_HEAVYCROSSBOW ||
- itemType == BASE_ITEM_LIGHTCROSSBOW ||
- itemType == BASE_ITEM_LONGBOW ||
- itemType == BASE_ITEM_SHORTBOW ||
- itemType == BASE_ITEM_SLING;
- applyWeaponStats(item, ranged);
- }
- else if (containerTag == "GS_ARMOR_UNIQUE")
- {
- item = createArmour();
- if (!GetIsObjectValid(item))
- {
- return;
- }
- applyArmourStats(item);
- }
- else if (containerTag == "GS_TREASURE_UNIQUE")
- {
- item = createGear();
- if (!GetIsObjectValid(item))
- {
- return;
- }
- applyGearStats(item);
- }
- if (GetGoldPieceValue(item) < GOLD_FLOOR)
- {
- DestroyObject(item);
- item = OBJECT_INVALID;
- }
- } while (item == OBJECT_INVALID);
- applyDescription(item);
- SetIdentified(item, FALSE);
- gsCMCreateGold(Random(PICKUP_GOLD_LIMIT) + 1);
- if (!GetIsObjectValid(GetLastKiller()))
- {
- SetLocalInt(OBJECT_SELF, "GS_ENABLED", TRUE);
- }
- }
- object createWeapon()
- {
- int itemType = 0;
- switch(Random(36))
- {
- case 0: itemType = BASE_ITEM_SHORTSWORD; break;
- case 1: itemType = BASE_ITEM_LONGSWORD; break;
- case 2: itemType = BASE_ITEM_BATTLEAXE; break;
- case 3: itemType = BASE_ITEM_BASTARDSWORD; break;
- case 4: itemType = BASE_ITEM_LIGHTFLAIL; break;
- case 5: itemType = BASE_ITEM_WARHAMMER; break;
- case 6: itemType = BASE_ITEM_HEAVYCROSSBOW; break;
- case 7: itemType = BASE_ITEM_LIGHTCROSSBOW; break;
- case 8: itemType = BASE_ITEM_LONGBOW; break;
- case 9: itemType = BASE_ITEM_LIGHTMACE; break;
- case 10: itemType = BASE_ITEM_HALBERD; break;
- case 11: itemType = BASE_ITEM_SHORTBOW; break;
- case 12: itemType = BASE_ITEM_TWOBLADEDSWORD; break;
- case 13: itemType = BASE_ITEM_GREATSWORD; break;
- case 14: itemType = BASE_ITEM_GREATAXE; break;
- case 15: itemType = BASE_ITEM_DAGGER; break;
- case 16: itemType = BASE_ITEM_CLUB; break;
- case 17: itemType = BASE_ITEM_DIREMACE; break;
- case 18: itemType = BASE_ITEM_DOUBLEAXE; break;
- case 19: itemType = BASE_ITEM_HEAVYFLAIL; break;
- case 20: itemType = BASE_ITEM_LIGHTHAMMER; break;
- case 21: itemType = BASE_ITEM_HANDAXE; break;
- case 22: itemType = BASE_ITEM_KAMA; break;
- case 23: itemType = BASE_ITEM_KATANA; break;
- case 24: itemType = BASE_ITEM_KUKRI; break;
- case 25: itemType = BASE_ITEM_MORNINGSTAR; break;
- case 26: itemType = BASE_ITEM_QUARTERSTAFF; break;
- case 27: itemType = BASE_ITEM_RAPIER; break;
- case 28: itemType = BASE_ITEM_SCIMITAR; break;
- case 29: itemType = BASE_ITEM_SCYTHE; break;
- case 30: itemType = BASE_ITEM_SHORTSPEAR; break;
- case 31: itemType = BASE_ITEM_SICKLE; break;
- case 32: itemType = BASE_ITEM_SLING; break;
- case 33: itemType = BASE_ITEM_TRIDENT; break;
- case 34: itemType = BASE_ITEM_DWARVENWARAXE; break;
- case 35: itemType = BASE_ITEM_WHIP; break;
- default: break;
- }
- return CreateItemOnObject(getResRefByItemType(itemType), OBJECT_SELF);
- }
- object createArmour()
- {
- int itemType = 0;
- switch (Random(8))
- {
- case 0:
- case 1:
- case 2:
- case 3:
- itemType = BASE_ITEM_ARMOR;
- break;
- case 4:
- itemType = BASE_ITEM_HELMET;
- break;
- case 5:
- itemType = BASE_ITEM_SMALLSHIELD;
- break;
- case 6:
- itemType = BASE_ITEM_LARGESHIELD;
- break;
- case 7:
- itemType = BASE_ITEM_TOWERSHIELD;
- break;
- default: break;
- }
- return CreateItemOnObject(getResRefByItemType(itemType), OBJECT_SELF);
- }
- object createGear()
- {
- int itemType = 0;
- switch (Random(8))
- {
- case 0:
- itemType = BASE_ITEM_AMULET;
- break;
- case 1:
- itemType = BASE_ITEM_BELT;
- break;
- case 2:
- itemType = BASE_ITEM_BRACER;
- break;
- case 3:
- itemType = BASE_ITEM_CLOAK;
- break;
- case 4:
- itemType = BASE_ITEM_GLOVES;
- break;
- case 5:
- case 6:
- itemType = BASE_ITEM_RING;
- break;
- case 7:
- itemType = BASE_ITEM_BOOTS;
- break;
- default: break;
- }
- return CreateItemOnObject(getResRefByItemType(itemType), OBJECT_SELF);
- }
- void applyWeaponStats(object weapon, int ranged)
- {
- int propertyCount = Random(MAX_PROPERTY_COUNT) + 1;
- int i;
- for (i = 0; i < propertyCount; i++)
- {
- struct PropertyStruct property = getUniqueWeaponProperty(ranged);
- setProperty(i, property);
- switch (property.id)
- {
- case WEAPON_ENH_BONUS:
- AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyEnhancementBonus(property.mod1), weapon);
- break;
- case WEAPON_AB_BONUS:
- AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyAttackBonus(property.mod1), weapon);
- break;
- case WEAPON_ENH_BONUS_VS_RACE:
- AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyEnhancementBonusVsRace(property.mod1, property.mod2), weapon);
- break;
- case WEAPON_ELEMENTAL_DAMAGE:
- AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyDamageBonus(property.mod1, property.mod2), weapon);
- break;
- case WEAPON_ABILITY_BONUS:
- AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyAbilityBonus(property.mod1, property.mod2), weapon);
- break;
- case WEAPON_SKILL_BONUS:
- AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertySkillBonus(property.mod1, property.mod2), weapon);
- break;
- case WEAPON_MASSIVE_CRITICALS:
- AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyMassiveCritical(property.mod1), weapon);
- break;
- case WEAPON_MISC_BONUSES:
- switch (property.mod1)
- {
- case MISC_BONUS_VISUAL:
- AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyVisualEffect(property.mod2), weapon);
- break;
- case MISC_BONUS_FREEDOM:
- AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyFreeAction(), weapon);
- break;
- case MISC_BONUS_FEAR:
- AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyImmunityMisc(property.mod2), weapon);
- break;
- case MISC_BONUS_LIGHT:
- AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyLight(property.mod2, Random(7)), weapon);
- break;
- }
- break;
- case WEAPON_AMMO_OR_VAMP_REGEN:
- if (ranged)
- {
- AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyUnlimitedAmmo(property.mod1), weapon);
- }
- else
- {
- AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyVampiricRegeneration(property.mod1), weapon);
- }
- break;
- case WEAPON_USAGE_RESTRICTION:
- switch (property.mod1)
- {
- case USAGE_RESTRICTION_CLASS:
- AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyLimitUseByClass(property.mod2), weapon);
- break;
- case USAGE_RESTRICTION_RACE:
- AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyLimitUseByRace(property.mod2), weapon);
- break;
- }
- break;
- default: break;
- }
- }
- writePropertiesToLog(propertyCount, ITEM_TYPE_WEAPON);
- }
- void applyArmourStats(object armour)
- {
- int propertyCount = Random(MAX_PROPERTY_COUNT) + 1;
- int i;
- for (i = 0; i < propertyCount; i++)
- {
- struct PropertyStruct property = getUniqueArmourProperty();
- setProperty(i, property);
- switch (property.id)
- {
- case ARMOUR_AC_BONUS:
- AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyACBonus(property.mod1), armour);
- break;
- case ARMOUR_AC_BONUS_VS_RACE:
- AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyACBonusVsRace(property.mod1, property.mod2), armour);
- break;
- case ARMOUR_SAVE_BONUS:
- AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyBonusSavingThrowVsX(property.mod1, property.mod2), armour);
- break;
- case ARMOUR_SPECIFIC_SAVE_BONUS:
- AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyBonusSavingThrow(property.mod1, property.mod2), armour);
- break;
- case ARMOUR_ELEMENTAL_DR:
- AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyDamageResistance(property.mod1, property.mod2), armour);
- break;
- case ARMOUR_ABILITY_BONUS:
- AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyAbilityBonus(property.mod1, property.mod2), armour);
- break;
- case ARMOUR_SKILL_BONUS:
- AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertySkillBonus(property.mod1, property.mod2), armour);
- break;
- case ARMOUR_USAGE_RESTRICTION:
- switch (property.mod1)
- {
- case USAGE_RESTRICTION_CLASS:
- AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyLimitUseByClass(property.mod2), armour);
- break;
- case USAGE_RESTRICTION_RACE:
- AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyLimitUseByRace(property.mod2), armour);
- break;
- }
- break;
- default: break;
- }
- }
- writePropertiesToLog(propertyCount, ITEM_TYPE_ARMOUR);
- }
- void applyGearStats(object gear)
- {
- int propertyCount = Random(MAX_PROPERTY_COUNT) + 1;
- int i;
- for (i = 0; i < propertyCount; i++)
- {
- struct PropertyStruct property = getUniqueGearProperty();
- setProperty(i, property);
- switch (property.id)
- {
- case GEAR_AC_BONUS:
- AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyACBonus(property.mod1), gear);
- break;
- case GEAR_AC_BONUS_VS_RACE:
- AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyACBonusVsRace(property.mod1, property.mod2), gear);
- break;
- case GEAR_SAVE_BONUS:
- AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyBonusSavingThrowVsX(property.mod1, property.mod2), gear);
- break;
- case GEAR_SPECIFIC_SAVE_BONUS:
- AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyBonusSavingThrow(property.mod1, property.mod2), gear);
- break;
- case GEAR_ELEMENTAL_DR:
- AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyDamageResistance(property.mod1, property.mod2), gear);
- break;
- case GEAR_ABILITY_BONUS:
- AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyAbilityBonus(property.mod1, property.mod2), gear);
- break;
- case GEAR_SKILL_BONUS:
- AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertySkillBonus(property.mod1, property.mod2), gear);
- break;
- case GEAR_USAGE_RESTRICTION:
- switch (property.mod1)
- {
- case USAGE_RESTRICTION_CLASS:
- AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyLimitUseByClass(property.mod2), gear);
- break;
- case USAGE_RESTRICTION_RACE:
- AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyLimitUseByRace(property.mod2), gear);
- break;
- }
- break;
- default: break;
- }
- }
- writePropertiesToLog(propertyCount, ITEM_TYPE_GEAR);
- }
- void applyDescription(object item)
- {
- SetName(item, "Artefact");
- object discoverer = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_IS_PC);
- string area = GetSubString(GetName(GetArea(OBJECT_SELF)), 0, FindSubString(GetName(GetArea(OBJECT_SELF)), "(") -1);
- SetDescription(item, "A curious artefact of unknown origin, discovered by " + GetName(discoverer) + " in the " + area + ".");
- }
- struct PropertyStruct getProperty(int index)
- {
- struct PropertyStruct property;
- if (index >= MAX_PROPERTY_COUNT)
- {
- property.id = 0;
- return property;
- }
- struct PropertyVarNameStruct varNames = getPropertyVarNames(index);
- property.id = GetLocalInt(OBJECT_SELF, varNames.id);
- property.mod1 = GetLocalInt(OBJECT_SELF, varNames.mod1);
- property.mod2 = GetLocalInt(OBJECT_SELF, varNames.mod2);
- return property;
- }
- void setProperty(int index, struct PropertyStruct property)
- {
- if (index >= MAX_PROPERTY_COUNT)
- {
- return;
- }
- struct PropertyVarNameStruct varNames = getPropertyVarNames(index);
- SetLocalInt(OBJECT_SELF, varNames.id, property.id);
- SetLocalInt(OBJECT_SELF, varNames.mod1, property.mod1);
- SetLocalInt(OBJECT_SELF, varNames.mod2, property.mod2);
- }
- int isPropertyUsed(int property)
- {
- int i;
- for (i = 0; i < MAX_PROPERTY_COUNT; ++i)
- {
- if (getProperty(i).id == property)
- {
- return TRUE;
- }
- }
- return FALSE;
- }
- struct PropertyStruct findProperty(int propertyId, int nth)
- {
- int hit = 0;
- struct PropertyStruct property;
- int i;
- for (i = 0; i < MAX_PROPERTY_COUNT; ++i)
- {
- property = getProperty(i);
- if (property.id == propertyId)
- {
- if (hit == nth)
- {
- return property;
- }
- else
- {
- ++hit;
- }
- }
- }
- property.id = INVALID_PROPERTY;
- return property;
- }
- struct PropertyStruct getUniqueWeaponProperty(int ranged)
- {
- struct PropertyStruct property;
- do
- {
- property.id = Random(WEAPON_PROPERTY_COUNT);
- switch (property.id)
- {
- // +1d4 enhancement.
- case WEAPON_ENH_BONUS:
- // Enhancement bonus.
- property.mod1 = d4();
- break;
- // +1d4 attack.
- case WEAPON_AB_BONUS:
- // Attack bonus.
- property.mod1 = d4();
- break;
- // +1d6 enh vs race.
- case WEAPON_ENH_BONUS_VS_RACE:
- // Race.
- property.mod1 = Random(26);
- // Enhancement bonus.
- property.mod2 = d6();
- break;
- // +1d10 elemental damage.
- case WEAPON_ELEMENTAL_DAMAGE:
- // Element.
- property.mod1 = d8() + 5;
- // Damage bonus.
- property.mod2 = d10();
- break;
- // +1d4 to an ability.
- case WEAPON_ABILITY_BONUS:
- // Ability.
- property.mod1 = Random(6);
- // Ability bonus.
- property.mod2 = d4();
- break;
- // +1d10 to a skill.
- case WEAPON_SKILL_BONUS:
- // Skill.
- property.mod1 = Random(28);
- // Skill bonus.
- property.mod2 = d10();
- break;
- // +1d10 massive criticals.
- case WEAPON_MASSIVE_CRITICALS:
- // Massive crit bonus.
- property.mod1 = d10();
- break;
- // glowy appearance or freedom or fear immunity or light.
- case WEAPON_MISC_BONUSES:
- switch (Random(4))
- {
- case MISC_BONUS_VISUAL:
- // This index.
- property.mod1 = MISC_BONUS_VISUAL;
- // Glowy appearance type.
- property.mod2 = Random(7);
- break;
- case MISC_BONUS_FREEDOM:
- // This index.
- property.mod1 = MISC_BONUS_FREEDOM;
- break;
- case MISC_BONUS_FEAR:
- // This index.
- property.mod1 = MISC_BONUS_FEAR;
- // Fear immunity constant.
- property.mod2 = IP_CONST_IMMUNITYMISC_FEAR;
- break;
- case MISC_BONUS_LIGHT:
- // This index.
- property.mod1 = MISC_BONUS_LIGHT;
- // Brightness.
- property.mod2 = d4();
- break;
- }
- break;
- // unlimited ammo (if ranged) or vamp regen (if not).
- case WEAPON_AMMO_OR_VAMP_REGEN:
- if (ranged)
- {
- // Element type.
- property.mod1 = d3() + 1;
- }
- else
- {
- // Vamp regen amount.
- property.mod1 = d6();
- }
- break;
- // usage restriction (class or race).
- case WEAPON_USAGE_RESTRICTION:
- switch (Random(2))
- {
- case USAGE_RESTRICTION_CLASS:
- // This index.
- property.mod1 = USAGE_RESTRICTION_CLASS;
- // Which class.
- property.mod2 = Random(11);
- break;
- case USAGE_RESTRICTION_RACE:
- // This index.
- property.mod1 = USAGE_RESTRICTION_RACE;
- // Which race.
- property.mod2 = Random(7);
- break;
- }
- break;
- default: break;
- }
- } while (!isWeaponPropertyValid(property));
- return property;
- }
- struct PropertyStruct getUniqueArmourProperty()
- {
- struct PropertyStruct property;
- do
- {
- property.id = Random(ARMOUR_PROPERTY_COUNT);
- switch (property.id)
- {
- // +1d4 AC.
- case ARMOUR_AC_BONUS:
- // AC bonus.
- property.mod1 = d4();
- break;
- // +1d6 AC vs race.
- case ARMOUR_AC_BONUS_VS_RACE:
- // Race.
- property.mod1 = Random(26);
- // AC bonus.
- property.mod2 = d6();
- break;
- // +1d4 save bonus.
- case ARMOUR_SAVE_BONUS:
- // Uni saves constant.
- property.mod1 = IP_CONST_SAVEVS_UNIVERSAL;
- // Save bonus.
- property.mod2 = d4();
- break;
- // +1d4 specific save bonus.
- case ARMOUR_SPECIFIC_SAVE_BONUS:
- // Save type.
- property.mod1 = d3();
- // Save bonus.
- property.mod2 = d4();
- break;
- // 5/- to 20/- elemental damage resistance.
- case ARMOUR_ELEMENTAL_DR:
- // Element.
- property.mod1 = d8() + 5;
- // Resistance bonus.
- property.mod2 = d4();
- break;
- // +1d4 to an ability.
- case ARMOUR_ABILITY_BONUS:
- // Ability.
- property.mod1 = Random(6);
- // Ability bonus.
- property.mod2 = d4();
- break;
- // +1d10 to a skill.
- case ARMOUR_SKILL_BONUS:
- // Skill.
- property.mod1 = Random(28);
- // Skill bonus.
- property.mod2 = d10();
- break;
- // usage restriction (class or race).
- case ARMOUR_USAGE_RESTRICTION:
- switch (Random(2))
- {
- case USAGE_RESTRICTION_CLASS:
- // This index.
- property.mod1 = USAGE_RESTRICTION_CLASS;
- // Which class.
- property.mod2 = Random(11);
- break;
- case USAGE_RESTRICTION_RACE:
- // This index.
- property.mod1 = USAGE_RESTRICTION_RACE;
- // Which race.
- property.mod2 = Random(7);
- break;
- }
- break;
- default: break;
- }
- } while (!isArmourPropertyValid(property));
- return property;
- }
- struct PropertyStruct getUniqueGearProperty()
- {
- struct PropertyStruct property;
- do
- {
- property.id = Random(GEAR_PROPERTY_COUNT);
- switch (property.id)
- {
- // +1d4 AC.
- case ARMOUR_AC_BONUS:
- // AC bonus.
- property.mod1 = d4();
- break;
- // +1d6 AC vs race.
- case ARMOUR_AC_BONUS_VS_RACE:
- // Race.
- property.mod1 = Random(26);
- // AC bonus.
- property.mod2 = d6();
- break;
- // +1d2 save bonus.
- case ARMOUR_SAVE_BONUS:
- // Uni saves constant.
- property.mod1 = IP_CONST_SAVEVS_UNIVERSAL;
- // Save bonus.
- property.mod2 = d2();
- break;
- // +1d4 specific save bonus.
- case ARMOUR_SPECIFIC_SAVE_BONUS:
- // Save type.
- property.mod1 = d3();
- // Save bonus.
- property.mod2 = d4();
- break;
- // 5/- to 20/- elemental damage resistance.
- case ARMOUR_ELEMENTAL_DR:
- // Element.
- property.mod1 = d8() + 5;
- // Resistance bonus.
- property.mod2 = d4();
- break;
- // +1d2 to an ability.
- case ARMOUR_ABILITY_BONUS:
- // Ability.
- property.mod1 = Random(6);
- // Ability bonus.
- property.mod2 = d2();
- break;
- // +1d6 to a skill.
- case ARMOUR_SKILL_BONUS:
- // Skill.
- property.mod1 = Random(28);
- // Skill bonus.
- property.mod2 = d6();
- break;
- // usage restriction (class or race).
- case GEAR_USAGE_RESTRICTION:
- switch (Random(2))
- {
- case USAGE_RESTRICTION_CLASS:
- // This index.
- property.mod1 = USAGE_RESTRICTION_CLASS;
- // Which class.
- property.mod2 = Random(11);
- break;
- case USAGE_RESTRICTION_RACE:
- // This index.
- property.mod1 = USAGE_RESTRICTION_RACE;
- // Which race.
- property.mod2 = Random(7);
- break;
- }
- break;
- default: break;
- }
- } while (!isGearPropertyValid(property));
- return property;
- }
- int isWeaponPropertyValid(struct PropertyStruct property)
- {
- int i;
- for (i = 0; i < MAX_PROPERTY_COUNT; ++i)
- {
- struct PropertyStruct otherProperty = getProperty(i);
- if (property.id == otherProperty.id)
- {
- switch (property.id)
- {
- case WEAPON_ENH_BONUS: return FALSE;
- case WEAPON_AB_BONUS: return FALSE;
- case WEAPON_ENH_BONUS_VS_RACE: if (property.mod1 == otherProperty.mod1) return FALSE; break;
- case WEAPON_ELEMENTAL_DAMAGE: if (property.mod1 == otherProperty.mod1) return FALSE; break;
- case WEAPON_ABILITY_BONUS: if (property.mod1 == otherProperty.mod1) return FALSE; break;
- case WEAPON_SKILL_BONUS: if (property.mod1 == otherProperty.mod1) return FALSE; break;
- case WEAPON_MASSIVE_CRITICALS: return FALSE;
- case WEAPON_MISC_BONUSES:
- switch (property.mod1)
- {
- case MISC_BONUS_VISUAL: return FALSE;
- case MISC_BONUS_FREEDOM: return FALSE;
- case MISC_BONUS_FEAR: return FALSE;
- case MISC_BONUS_LIGHT: return FALSE;
- }
- break;
- case WEAPON_AMMO_OR_VAMP_REGEN: return FALSE;
- case WEAPON_USAGE_RESTRICTION:
- switch (property.mod1)
- {
- case USAGE_RESTRICTION_CLASS: if (property.mod2 == otherProperty.mod2) return FALSE; break;
- case USAGE_RESTRICTION_RACE: if (property.mod2 == otherProperty.mod2) return FALSE; break;
- }
- break;
- default: break;
- }
- }
- int j;
- switch (property.id)
- {
- case WEAPON_AB_BONUS:
- otherProperty = findProperty(WEAPON_ENH_BONUS);
- for (j = 0; otherProperty.id != INVALID_PROPERTY; ++j)
- {
- int abBonus = property.mod1;
- int enhBonus = otherProperty.mod1;
- // Ensure that the ab bonus is greater than any existing enh bonus.
- if (!(abBonus > enhBonus))
- {
- return FALSE;
- }
- otherProperty = findProperty(WEAPON_ENH_BONUS, j);
- }
- break;
- case WEAPON_ENH_BONUS:
- otherProperty = findProperty(WEAPON_ENH_BONUS_VS_RACE);
- for (j = 0; otherProperty.id != INVALID_PROPERTY; ++j)
- {
- int enhBonus = property.mod1;
- int enhBonusVsRace = otherProperty.mod2;
- // Ensure that the enh bonus is lower than any existing enh bonus vs race.
- if (!(enhBonus < enhBonusVsRace))
- {
- return FALSE;
- }
- otherProperty = findProperty(WEAPON_ENH_BONUS_VS_RACE, j);
- }
- break;
- case WEAPON_ENH_BONUS_VS_RACE:
- otherProperty = findProperty(WEAPON_ENH_BONUS);
- for (j = 0; otherProperty.id != INVALID_PROPERTY; ++j)
- {
- int enhBonus = otherProperty.mod1;
- int enhBonusVsRace = property.mod2;
- // Ensure that the specific bonus vs race is higher than the existing enh bonus.
- if (!(enhBonusVsRace > enhBonus))
- {
- return FALSE;
- }
- otherProperty = findProperty(WEAPON_ENH_BONUS, j);
- }
- break;
- default: break;
- }
- }
- return TRUE;
- }
- int isArmourPropertyValid(struct PropertyStruct property)
- {
- int i;
- for (i = 0; i < MAX_PROPERTY_COUNT; ++i)
- {
- struct PropertyStruct otherProperty = getProperty(i);
- if (property.id == otherProperty.id)
- {
- switch (property.id)
- {
- case ARMOUR_AC_BONUS: return FALSE;
- case ARMOUR_AC_BONUS_VS_RACE: if (property.mod1 == otherProperty.mod1) return FALSE; break;
- case ARMOUR_SAVE_BONUS: return FALSE;
- case ARMOUR_SPECIFIC_SAVE_BONUS: if (property.mod1 == otherProperty.mod1) return FALSE; break;
- case ARMOUR_ELEMENTAL_DR: if (property.mod1 == otherProperty.mod1) return FALSE; break;
- case ARMOUR_ABILITY_BONUS: if (property.mod1 == otherProperty.mod1) return FALSE; break;
- case ARMOUR_SKILL_BONUS: if (property.mod1 == otherProperty.mod1) return FALSE; break;
- case ARMOUR_USAGE_RESTRICTION:
- switch (property.mod1)
- {
- case USAGE_RESTRICTION_CLASS: if (property.mod2 == otherProperty.mod2) return FALSE; break;
- case USAGE_RESTRICTION_RACE: if (property.mod2 == otherProperty.mod2) return FALSE; break;
- }
- break;
- default: break;
- }
- }
- int j;
- switch (property.id)
- {
- case ARMOUR_AC_BONUS:
- otherProperty = findProperty(ARMOUR_AC_BONUS_VS_RACE);
- for (j = 0; otherProperty.id != INVALID_PROPERTY; ++j)
- {
- int acBonus = property.mod1;
- int acBonusVsRace = otherProperty.mod2;
- // Ensure that the AC bonus is less than any existing AC bonus vs race.
- if (!(acBonus < acBonusVsRace))
- {
- return FALSE;
- }
- otherProperty = findProperty(ARMOUR_AC_BONUS_VS_RACE, j);
- }
- break;
- case ARMOUR_AC_BONUS_VS_RACE:
- otherProperty = findProperty(ARMOUR_AC_BONUS);
- for (j = 0; otherProperty.id != INVALID_PROPERTY; ++j)
- {
- int acBonus = otherProperty.mod1;
- int acBonusVsRace = property.mod2;
- // Ensure that the AC bonus vs race is greater than any existing AC bonus.
- if (!(acBonusVsRace > acBonus))
- {
- return FALSE;
- }
- otherProperty = findProperty(ARMOUR_AC_BONUS, j);
- }
- break;
- case ARMOUR_SAVE_BONUS:
- otherProperty = findProperty(ARMOUR_SPECIFIC_SAVE_BONUS);
- for (j = 0; otherProperty.id != INVALID_PROPERTY; ++j)
- {
- int uniSave = property.mod2;
- int specificSave = otherProperty.mod2;
- // Ensure that the uni save is less than any existing specific saves.
- if (!(uniSave < specificSave))
- {
- return FALSE;
- }
- otherProperty = findProperty(ARMOUR_SPECIFIC_SAVE_BONUS, j);
- }
- break;
- case ARMOUR_SPECIFIC_SAVE_BONUS:
- otherProperty = findProperty(ARMOUR_SAVE_BONUS);
- for (j = 0; otherProperty.id != INVALID_PROPERTY; ++j)
- {
- int uniSave = otherProperty.mod2;
- int specificSave = property.mod2;
- // Ensure that the specific save is greater than any existing uni save.
- if (!(specificSave > uniSave))
- {
- return FALSE;
- }
- otherProperty = findProperty(ARMOUR_SAVE_BONUS, j);
- }
- break;
- default: break;
- }
- }
- return TRUE;
- }
- int isGearPropertyValid(struct PropertyStruct property)
- {
- int i;
- for (i = 0; i < MAX_PROPERTY_COUNT; ++i)
- {
- struct PropertyStruct otherProperty = getProperty(i);
- if (property.id == otherProperty.id)
- {
- switch (property.id)
- {
- case GEAR_AC_BONUS: return FALSE;
- case GEAR_AC_BONUS_VS_RACE: if (property.mod1 == otherProperty.mod1) return FALSE; break;
- case GEAR_SAVE_BONUS: return FALSE;
- case GEAR_SPECIFIC_SAVE_BONUS: if (property.mod1 == otherProperty.mod1) return FALSE; break;
- case GEAR_ELEMENTAL_DR: if (property.mod1 == otherProperty.mod1) return FALSE; break;
- case GEAR_ABILITY_BONUS: if (property.mod1 == otherProperty.mod1) return FALSE; break;
- case GEAR_SKILL_BONUS: if (property.mod1 == otherProperty.mod1) return FALSE; break;
- case GEAR_USAGE_RESTRICTION:
- switch (property.mod1)
- {
- case USAGE_RESTRICTION_CLASS: if (property.mod2 == otherProperty.mod2) return FALSE; break;
- case USAGE_RESTRICTION_RACE: if (property.mod2 == otherProperty.mod2) return FALSE; break;
- }
- break;
- default: break;
- }
- }
- int j;
- switch (property.id)
- {
- case GEAR_AC_BONUS:
- otherProperty = findProperty(GEAR_AC_BONUS_VS_RACE);
- for (j = 0; otherProperty.id != INVALID_PROPERTY; ++j)
- {
- int acBonus = property.mod1;
- int acBonusVsRace = otherProperty.mod2;
- // Ensure that the AC bonus is less than any existing AC bonus vs race.
- if (!(acBonus < acBonusVsRace))
- {
- return FALSE;
- }
- otherProperty = findProperty(GEAR_AC_BONUS_VS_RACE, j);
- }
- break;
- case GEAR_AC_BONUS_VS_RACE:
- otherProperty = findProperty(GEAR_AC_BONUS);
- for (j = 0; otherProperty.id != INVALID_PROPERTY; ++j)
- {
- int acBonus = otherProperty.mod1;
- int acBonusVsRace = property.mod2;
- // Ensure that the AC bonus vs race is greater than any existing AC bonux.
- if (!(acBonusVsRace > acBonus))
- {
- return FALSE;
- }
- otherProperty = findProperty(GEAR_AC_BONUS, j);
- }
- break;
- case GEAR_SAVE_BONUS:
- otherProperty = findProperty(GEAR_SPECIFIC_SAVE_BONUS);
- for (j = 0; otherProperty.id != INVALID_PROPERTY; ++j)
- {
- int uniSave = property.mod2;
- int specificSave = otherProperty.mod2;
- // Ensure that the uni save is less than any existing specific saves.
- if (!(uniSave < specificSave))
- {
- return FALSE;
- }
- otherProperty = findProperty(GEAR_SPECIFIC_SAVE_BONUS, j);
- }
- break;
- case GEAR_SPECIFIC_SAVE_BONUS:
- otherProperty = findProperty(GEAR_SAVE_BONUS);
- for (j = 0; otherProperty.id != INVALID_PROPERTY; ++j)
- {
- int uniSave = otherProperty.mod2;
- int specificSave = property.mod2;
- // Ensure that the specific save is greater than any existing uni save.
- if (!(specificSave > uniSave))
- {
- return FALSE;
- }
- otherProperty = findProperty(GEAR_SAVE_BONUS, j);
- }
- break;
- default: break;
- }
- }
- return TRUE;
- }
- void cleanupPropertyVars()
- {
- int i;
- for (i = 0; i < MAX_PROPERTY_COUNT; ++i)
- {
- struct PropertyVarNameStruct varNames = getPropertyVarNames(i);
- SetLocalInt(OBJECT_SELF, varNames.id, INVALID_PROPERTY);
- SetLocalInt(OBJECT_SELF, varNames.mod1, INVALID_PROPERTY);
- SetLocalInt(OBJECT_SELF, varNames.mod2, INVALID_PROPERTY);
- }
- }
- struct PropertyVarNameStruct getPropertyVarNames(int index)
- {
- string propertyArrBase = "PROPERTY_ARR_" + IntToString(index);
- struct PropertyVarNameStruct varNames;
- varNames.id = propertyArrBase + "_ID";
- varNames.mod1 = propertyArrBase + "_MOD1";
- varNames.mod2 = propertyArrBase + "_MOD2";
- return varNames;
- }
- void writePropertiesToLog(int propertyCount, int itemType)
- {
- object nearestPlayer = GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR, PLAYER_CHAR_IS_PC);
- string logOutput = "Generated item type " + IntToString(itemType) + " " +
- "in " + GetTag(GetArea(OBJECT_SELF)) + " " +
- "by " + GetName(nearestPlayer) + " " +
- "[" + GetPCPublicCDKey(nearestPlayer) + "] " +
- "with property Count: " + IntToString(propertyCount) + " ( ";
- int i;
- for (i = 0; i < propertyCount; ++i)
- {
- struct PropertyStruct property = getProperty(i);
- logOutput += "Property " + IntToString(i) + ": [" +
- "id=" + IntToString(property.id) + ", " +
- "mod1=" + IntToString(property.mod1) + ", " +
- "mod2=" + IntToString(property.mod2) + "] ";
- }
- Log("ARTIFACT", logOutput + ")");
- }
- string getResRefByItemType(int itemType)
- {
- switch (itemType)
- {
- case BASE_ITEM_AMULET: return "gs_item209";
- case BASE_ITEM_ARMOR:
- {
- switch (Random(4))
- {
- case 0: return "nw_cloth027";
- case 1: return "nw_aarcl001";
- case 2: return "nw_aarcl003";
- case 3: return "nw_aarcl007";
- }
- }
- case BASE_ITEM_BASTARDSWORD: return "nw_wswbs001";
- case BASE_ITEM_BATTLEAXE: return "nw_waxbt001";
- case BASE_ITEM_BELT: return "gs_item258";
- case BASE_ITEM_BOOTS: return "gs_item311";
- case BASE_ITEM_BRACER: return "gs_item270";
- case BASE_ITEM_CLOAK: return "gs_item284";
- case BASE_ITEM_CLUB: return "nw_wblcl001";
- case BASE_ITEM_DAGGER: return "nw_wswdg001";
- case BASE_ITEM_DIREMACE: return "nw_wdbma001";
- case BASE_ITEM_DOUBLEAXE: return "nw_wdbax001";
- case BASE_ITEM_DWARVENWARAXE: return "x2_wdwraxe001";
- case BASE_ITEM_GLOVES: return "gs_item294";
- case BASE_ITEM_GREATAXE: return "nw_waxgr001";
- case BASE_ITEM_GREATSWORD: return "nw_wswgs001";
- case BASE_ITEM_HALBERD: return "nw_wplhb001";
- case BASE_ITEM_HANDAXE: return "nw_waxhn001";
- case BASE_ITEM_HEAVYCROSSBOW: return "nw_wbwxh001";
- case BASE_ITEM_HEAVYFLAIL: return "nw_wblfh001";
- case BASE_ITEM_HELMET: return "x2_it_arhelm03";
- case BASE_ITEM_KAMA: return "nw_wspka001";
- case BASE_ITEM_KATANA: return "nw_wswka001";
- case BASE_ITEM_KUKRI: return "nw_wspku001";
- case BASE_ITEM_LARGESHIELD: return "nw_ashlw001";
- case BASE_ITEM_LIGHTCROSSBOW: return "nw_wbwxl001";
- case BASE_ITEM_LIGHTFLAIL: return "nw_wblfl001";
- case BASE_ITEM_LIGHTHAMMER: return "nw_wblhl001";
- case BASE_ITEM_LIGHTMACE: return "nw_wblml001";
- case BASE_ITEM_LONGBOW: return "nw_wbwln001";
- case BASE_ITEM_LONGSWORD: return "nw_wswls001";
- case BASE_ITEM_MORNINGSTAR: return "nw_wblms001";
- case BASE_ITEM_QUARTERSTAFF: return "nw_wdbqs001";
- case BASE_ITEM_RAPIER: return "nw_wswrp001";
- case BASE_ITEM_RING: return "gs_item252";
- case BASE_ITEM_SCIMITAR: return "nw_wswsc001";
- case BASE_ITEM_SCYTHE: return "nw_wplsc001";
- case BASE_ITEM_SHORTBOW: return "nw_wbwsh001";
- case BASE_ITEM_SHORTSPEAR: return "nw_wplss001";
- case BASE_ITEM_SHORTSWORD: return "nw_wswss001";
- case BASE_ITEM_SICKLE: return "nw_wspsc001";
- case BASE_ITEM_SLING: return "nw_wbwsl001";
- case BASE_ITEM_SMALLSHIELD: return "nw_ashsw001";
- case BASE_ITEM_TOWERSHIELD: return "nw_ashto001";
- case BASE_ITEM_TRIDENT: return "nw_wpltr001";
- case BASE_ITEM_TWOBLADEDSWORD: return "nw_wdbsw001";
- case BASE_ITEM_WARHAMMER: return "nw_wblhw001";
- case BASE_ITEM_WHIP: return "x2_it_wpwhip";
- default: break;
- }
- return "";
- }