Alangara_PRC8/_module/nss/zep_inc_craft.nss
Jaysyn904 86feb9ca6f Initial commit
Initial commit.
2024-06-05 21:21:06 -04:00

1248 lines
51 KiB
Plaintext

//:://////////////////////////////////////////////
//:: Completely redone Armor and Weapon redesign functions
//:: Further redone by Loki Hakanin
//:: zep_inc_craft
//:://////////////////////////////////////////////
/*
This is a complete rework of the Armor- and Weaponcrafting skill
No existing scripts are overridden or replaced, only the conversation
x0_skill_ctrap needs to be replaced to activate the custom crafting.
Original scripts written by SartriX
Modified for inclusion in the CEP by Loki Hakanin
Note from Loki: In general, all comments I've added
will be labeled as "Note from Loki".
Additions to the original Bioware scripts:
- Bugs fixed
- Enhanced performance
- Support for custom armor- and weaponmodels
- Helmet and Shield crafting added
Note from Loki: Do not have a decent server handy to
test the below out on. If the zep_cr_nocheat script is
used either as an "OnEnter" script for a module/server,
or executed therein, it should stop this exploit. This
function is 100% SartriX's original, as since I have not
tested it, I do not know if it needs modification.
- Counters the 'double item' exploit !
Note from Loki: Optional Features: Can be enabled
by enabling flags. Bottom 2 use SartriX's original
code, but just with renamed variables and the like to
conform to CEP naming convention.
- Reworked Cost and DC
- Use of crafting placeables (like Forge)
- Use of NPC crafters
Modifications and enhancements by Loki Hakanin-
- Fixed errors in logic of conditional statements
causing them not to function when a PC attempts
crafting by themselves (with the "require
placble" flag set to FALSE).
- Added code to next/previous cyclying segments to
enhance robustness-functions can now handle
irregular inputs-that is to say, custom models
that aren't all 100% identical to Bioware
numbering conventions (e.g. more than 3
appearances/colors for a given shield index, more
than 4 for weapons).
- Fixed coding error causing shield alterations to require
dyes.
- Added support for new CEP weapon types.
- Fixed error causing incorrect display of leg options
- Fixed glitch preventing remodelling of hand axes.
To be Added Later:
- Built in color selection for armor and helmets (optional flag)
Note from Loki: Note that the code for coloring and
the like is still here, I have merely temporarily
disabled it, by and large For CEP R1, we wanted
things to work just like Bioware's code where we were
replacing/updating code to work with custom content.
Also, as the dynamic color alteration requires
addiitonal item blueprints (the full dyeset), there
was concern this would make default Bioware dyes
useless, violating the CEP's "harm no existing content"
rule. This code and these items will be re-worked in a
later release to integrate with the original Bioware
dyes.
This crafting system was originally made by SartriX
His original scriptset has been posted on nwvault:
- http://nwvault.ign.com/Files/scripts/data/1071920548260.shtml
*/
//:://////////////////////////////////////////////
//:: Created By: SartriX(original version)
//:: Modified by Loki Hakanin
//:: Created On(original version): 16-dec-2003
//:: Updated On(original version): 16-jan-2004
//:: Updated/Modified by Loki: 26-Feb-2004
//:://////////////////////////////////////////////
#include "x2_inc_craft"
#include "zep_inc_main"
#include "prc_inc_racial"
#include "prc_misc_const"
// Set to FALSE to disable the requirement of the proper placeable to be near the PC
const int ZEP_CR_REQUIRE_PLACEABLE = FALSE;
//Tag of crafting placeable
const string ZEP_CR_PLACEABLE_TAG = "zep_cr_craftplace";
// Maximum distance to a crafting placeable
const float ZEP_CR_REQUIRED_DISTANCE = 4.0f;
// Set to FALSE to disable the requirement and use of dyes when recolouring
const int ZEP_CR_REQUIRE_DYES = FALSE;
// Maximum cost in percent of the item's original valie at all times regardless of any other settings
const int ZEP_CR_MAXCOST = 90;
// Percentage of cost for each part of a weapon (3 parts max) or a helmet/shield (1 part max)
const int ZEP_CR_PARTCOST = 20;
// Added percentage of cost for dye changes by NPC
const int ZEP_CR_NPCDYECOST = 1;
// Percentage it costs to craft one self compared to what a NPC would ask for the same
// NPC cost is always 100% of the CraftCost in des_crft_aparts.2da
const int ZEP_CR_SELFCRAFT = 70;
// The DC that's added to craft magical items. This DC is added for each magical property it has
const int ZEP_CR_DCADD = 2;
// Tag of the backup container
// One is supplied as custom placeable (custom -> special -> custom5 -> zep_cr_backup)
// and should be placed on a preferrably inaccessible location. If the container can not be found,
// the backup item will be added to the PC's inventory, it won't break the entire script.
// Note from Loki: I've altered this implementatoin as well.
// Following Bioware's example, I spawn and make invisible a crafting container
// if I find none in the module. Difference being, I delete
// it at the end of crafting, for completeness's sake.
const string ZEP_CR_BACKUP_PLACEABLE = "zep_cr_backup";
// Internal constants, do not touch!
const int ZEP_CR_DONE_SUCCESS = 1;
const int ZEP_CR_DONE_FAILED = 2;
const int ZEP_CR_DONE_NOGOLD = 3;
const int ZEP_CR_DONE_NODYE = 4;
const int ZEP_CR_PART_NEXT = 0;
const int ZEP_CR_PART_PREV = 1;
const int ZEP_CR_COLOR_NEXT = 3;
const int ZEP_CR_COLOR_PREV = 4;
const int ZEP_CR_TOKENBASE = 20000;
const int ZEP_CR_HELMET = 8888;
const int ZEP_CR_SHIELD = 8889;
//Note from Loki: Above constants were all from
//the original script. Have simply been renamed to
//keep them consistent with CEP nomenclature.
//Constants declared below are my own additions:
//This constant controls whether SartriX's modified
//DC and costs are used. By default, it is FALSE
//(using Bioware defaults instead). Re-enabling it
//will use the costs in the des_crft_aparts.2da
//file instead.
const int ZEP_USE_OPTIONAL_DC_COST = FALSE;
//Following constants added when we removed the NumParts
//alterations from the des_crafts_aparts.2da file. This was
//done so people using the default NWN crafting system with
//the CEP would not have a very long set of armors that
//would have blank entries (all the lines in the armor
//2DA files from the last Bioware to the first CEP entry).
//These constants define the max "numparts" in place of the
//2DA files
//Note that weapons and helmets still read the baseitems
//file correctly, or have no problems with the default Bioware
//craft system. Shields, of course, are only craftable with
//a custom script, so they are not included as the below is
//a "legacy compatibility" change.
const int ZEP_MAX_PARTS_NECK = 255;
const int ZEP_MAX_PARTS_SHOULDER = 255;
const int ZEP_MAX_PARTS_BICEP = 255;
const int ZEP_MAX_PARTS_FOREARM = 255;
const int ZEP_MAX_PARTS_HAND = 255;
const int ZEP_MAX_PARTS_TORSO = 255;
const int ZEP_MAX_PARTS_BELT = 255;
const int ZEP_MAX_PARTS_PELVIS = 255;
const int ZEP_MAX_PARTS_THIGH = 255;
const int ZEP_MAX_PARTS_SHIN = 255;
const int ZEP_MAX_PARTS_FOOT = 255;
const int ZEP_MAX_PARTS_ROBE = 255;
// - End of constants - //
// Sets up everything for oPC to start crafting on oItem
void ZEP_StartCraft(object oPC, object oItem);
// Tries to let oPC perform the crafting of his current item
// Will set the localvar ZEP_CR_DONE on success or fail with one
// of the following values to check with a conditional script:
// ZEP_CR_DONE_SUCCESS
// ZEP_CR_DONE_FAILED
// ZEP_CR_DONE_NOGOLD
// ZEP_CR_DONE_NODYE
void ZEP_AttemptCraft(object oPC);
// Stops crafting and cleans up everything set by the crafting script
// When nExecute is FALSE, it will abort the craft,
// when it's TRUE, it will replace the old item with the new one.
void ZEP_StopCraft(object oPC, int nExecute=FALSE);
// Sets the current part oPC is working on
// It accepts all 4 partseries ITEM_APPR_ARMOR_MODEL_*,
// ITEM_APPR_WEAPON_MODEL_*, ITEM_APPR_ARMOR_COLOR_*, ITEM_APPR_WEAPON_COLOR_*
// as long as the proper item has been set to craft on
// Focusses the camery on the selected part (if applicable)
void ZEP_SetPart(object oPC, int nPart, int nStrRef);
// Gets the cost to modify oItem into oNew
// Calls the default bioware routines for this, edit this function to override
int ZEP_GetModificationCost(object oItem, object oNew, int nNPC=FALSE);
// Gets the DC to modify oItem into oNew
// Calls the default bioware routines for this, edit this function to override
int ZEP_GetModificationDC(object oItem, object oNew, int nNPC=FALSE);
// Remakes and equips the item oPC is working, having the currently set part
// cycled either forward or backward
// nMode: ZEP_CR_PART_NEXT - cycle forward
// nMode: ZEP_CR_PART_PREV - cycle backward
void ZEP_RemakeItem(object oPC, int nMode);
// Remakes and equips the item oPC is working, having the currently set color
// cycled either forward or backward
// nMode: ZEP_CR_COLOR_NEXT - cycle forward
// nMode: ZEP_CR_COLOR_PREV - cycle backward
void ZEP_RecolorItem(object oPC, int nMode);
//Function Added by Loki
//Decided to do container checks dynamically and have it
//construct a work container as necessary. This closely
//mirrors Bioware's Own implementation.
object ZEP_GetZEPWorkContainer(object oCaller);
//Function added by Loki
//Below function used as a substitution for the
//IPGetNumberOfArmorAppearances function in the CEP code.
//This is done because the max NumParts is coded as a
//constant to ensure compatibility with "vanilla' NWN.
int ZEP_GetNumberOfArmorAppearances(int nPart);
//Will check if item oItem owned by oPC is a crafting duplicate.
//If so will destroy item and Notify all DMs, as well as
//logging this fact. nIsEntering should be set to TRUE if
//this function is called as part of an OnEnter script, or
//to FALSE otherwise.
void ZEP_PurifyItem(object oItem, object oPC, int nIsEntering);
//Following function is basically just an iterative version
//of the above PurifyItem function. In other words, ir will
//cycle through oPCs inventory and Purify all items (as well
//as all appropriate equipable slots).
void ZEP_PurifyAllItems(object oPC, int nIsEntering=FALSE,int nDeleteTempVars=FALSE);
// - Implementation - //
// Sets up everything for oPC to start crafting on oItem
void ZEP_StartCraft(object oPC, object oItem) {
// Immobilize player while crafting
effect eImmob = EffectCutsceneImmobilize();
eImmob = ExtraordinaryEffect(eImmob);
ApplyEffectToObject(DURATION_TYPE_PERMANENT,eImmob,oPC);
// Make the camera float near the PC
StoreCameraFacing();
float fFacing = GetFacing(oPC) + 180.0;
if (fFacing >= 360.0) fFacing -=360.0;
SetCameraFacing(fFacing, 3.5f, 75.0, CAMERA_TRANSITION_TYPE_FAST);
// Make backup
// Note from Loki: Changed implemenation to stash item in container ALWAYS.
// ZEP_GetZEPWorkContainer will create container if needs be.
object oBackup = CopyItem(oItem, ZEP_GetZEPWorkContainer(OBJECT_SELF), TRUE);
SetLocalObject(oPC, "ZEP_CR_BACKUP", oBackup);
// Mark temporary item
SetStolenFlag(oItem, TRUE);
SetLocalInt(oItem, "ZEP_CR_TEMPITEM", TRUE);
SetLocalObject(oPC, "ZEP_CR_ITEM", oItem);
// Preset settings
SetLocalInt(oPC, "ZEP_CR_STARTED", 1);
SetLocalInt(oPC, "ZEP_CR_COST", 0);
SetLocalInt(oPC, "ZEP_CR_DC", 0);
SetLocalInt(oPC, "ZEP_CR_DONE", 0);
SetLocalInt(oPC, "ZEP_CR_CHANGED", FALSE);
SetCustomToken(ZEP_CR_TOKENBASE, "");
SetCustomToken(ZEP_CR_TOKENBASE+1, "0");
SetCustomToken(ZEP_CR_TOKENBASE+2, "0");
SetCustomToken(ZEP_CR_TOKENBASE+3, "");
}
// - private -
// Checks if the color for nIndex has changed, if not returns TRUE
// if it has, checks if oPC has the new dye and returns TRUE when he has
// returns FALSE and sets CUSTOM20003 when the required dye is not present
int ZEP_ColorCheck(object oPC, object oItem, object oBackup, int nType, int nIndex) {
// if required dyes are disabled, always return TRUE
if (!ZEP_CR_REQUIRE_DYES) return TRUE;
// get new color
int nColor = GetItemAppearance(oItem, nType, nIndex);
string sDyeTag = "Dye";
if (nColor != GetItemAppearance(oBackup, nType, nIndex)) {
// color has changed, build the tag for the required dye
if (nType == ITEM_APPR_TYPE_ARMOR_COLOR) {
switch(nIndex) {
case ITEM_APPR_ARMOR_COLOR_CLOTH1:
case ITEM_APPR_ARMOR_COLOR_CLOTH2: sDyeTag+= "C"; break;
case ITEM_APPR_ARMOR_COLOR_LEATHER1:
case ITEM_APPR_ARMOR_COLOR_LEATHER2: sDyeTag+= "L"; break;
case ITEM_APPR_ARMOR_COLOR_METAL1:
case ITEM_APPR_ARMOR_COLOR_METAL2: sDyeTag+= "M";
if (nColor>55 && nColor<60) nColor-=4; break; // translate missing/double metal colors
}
if (nColor<10) sDyeTag+= "0";
sDyeTag+= IntToString(nColor);
} else {
switch (nColor) {
case 1: sDyeTag+= "M01"; break; // Steel
case 2: sDyeTag+= "M13"; break; // Gold
case 3: sDyeTag+= "M21"; break; // Copper
case 4: sDyeTag+= "M02"; break; // Dark Steel
}
}
if (GetIsObjectValid(GetItemPossessedBy(oPC, sDyeTag))) {
// oPC has the dye, so this color is alright
SetLocalString(oPC, "ZEP_CR_DYES", GetLocalString(oPC, "ZEP_CR_DYES") + sDyeTag + ":");
return TRUE;
} else {
// oPC does not have the dye, tell which dye is missing
if (GetName(GetObjectByTag(sDyeTag))=="") SpeakString("Missing dye/name: "+sDyeTag);
SetCustomToken(ZEP_CR_TOKENBASE+3, GetName(GetObjectByTag(sDyeTag)));
return FALSE;
}
}
return TRUE;
}
// Tries to let oPC perform the crafting of his current item
// Will set the localvar ZEP_CR_DONE on success or fail with one
// of the following values to check with a conditional script:
// ZEP_CR_DONE_SUCCESS
// ZEP_CR_DONE_FAILED
// ZEP_CR_DONE_NOGOLD
// ZEP_CR_DONE_NODYE
void ZEP_AttemptCraft(object oPC) {
// don't reattempt a previously craftattempt
if (GetLocalInt(oPC, "ZEP_CR_DONE")>0) return;
// get current item and backup
object oItem = GetLocalObject(oPC, "ZEP_CR_ITEM");
object oBackup = GetLocalObject(oPC, "ZEP_CR_BACKUP");
int nNPC = GetIsObjectValid(GetLocalObject(oPC, "ZEP_CR_NPC"));
int nCost = ZEP_GetModificationCost(oBackup, oItem, nNPC);
int nDC = ZEP_GetModificationDC(oBackup, oItem, nNPC);
int nSkill;
if (GetGold(oPC)<nCost) {
// player has insufficent gold, cancel
SetLocalInt(oPC, "ZEP_CR_DONE", ZEP_CR_DONE_NOGOLD);
return;
}
// check if all dyes are present and set the skill to be used
if (GetBaseItemType(oItem)==BASE_ITEM_ARMOR || GetBaseItemType(oItem)==BASE_ITEM_HELMET) {
if (!nNPC) {
if (!(ZEP_ColorCheck(oPC, oItem, oBackup, ITEM_APPR_TYPE_ARMOR_COLOR, ITEM_APPR_ARMOR_COLOR_CLOTH1)
&& ZEP_ColorCheck(oPC, oItem, oBackup, ITEM_APPR_TYPE_ARMOR_COLOR, ITEM_APPR_ARMOR_COLOR_CLOTH2)
&& ZEP_ColorCheck(oPC, oItem, oBackup, ITEM_APPR_TYPE_ARMOR_COLOR, ITEM_APPR_ARMOR_COLOR_LEATHER1)
&& ZEP_ColorCheck(oPC, oItem, oBackup, ITEM_APPR_TYPE_ARMOR_COLOR, ITEM_APPR_ARMOR_COLOR_LEATHER2)
&& ZEP_ColorCheck(oPC, oItem, oBackup, ITEM_APPR_TYPE_ARMOR_COLOR, ITEM_APPR_ARMOR_COLOR_METAL1)
&& ZEP_ColorCheck(oPC, oItem, oBackup, ITEM_APPR_TYPE_ARMOR_COLOR, ITEM_APPR_ARMOR_COLOR_METAL2))) {
SetLocalInt(oPC, "ZEP_CR_DONE", ZEP_CR_DONE_NODYE);
return;
}
}
nSkill = SKILL_CRAFT_ARMOR;
} else
{
/*Next bit was part of else*/ //if ((GetBaseItemType(oItem) != BASE_ITEM_LARGESHIELD) && (GetBaseItemType(oItem) != BASE_ITEM_SMALLSHIELD) && (GetBaseItemType(oItem) != BASE_ITEM_TOWERSHIELD)) {
// if (!nNPC) {
// if (!(ZEP_ColorCheck(oPC, oItem, oBackup, ITEM_APPR_TYPE_WEAPON_COLOR, ITEM_APPR_WEAPON_COLOR_TOP)
// && ZEP_ColorCheck(oPC, oItem, oBackup, ITEM_APPR_TYPE_WEAPON_COLOR, ITEM_APPR_WEAPON_COLOR_MIDDLE)
// && ZEP_ColorCheck(oPC, oItem, oBackup, ITEM_APPR_TYPE_WEAPON_COLOR, ITEM_APPR_WEAPON_COLOR_BOTTOM))) {
// SetLocalInt(oPC, "ZEP_CR_DONE", ZEP_CR_DONE_NODYE);
// return;
// }
// }
nSkill = SKILL_CRAFT_WEAPON;
}
// take gold
TakeGoldFromCreature(nCost, oPC, TRUE);
// take dyes
string sDyes = GetLocalString(oPC, "ZEP_CR_DYES");
string sDyeTag;
int nLen = GetStringLength(sDyes);
int n;
while (sDyes!="") {
n = FindSubString(sDyes, ":");
sDyeTag = GetSubString(sDyes, 0, n);
sDyes = GetSubString(sDyes, n+1, nLen);
DestroyObject(GetItemPossessedBy(oPC, sDyeTag));
}
// roll DC
if (nNPC || GetIsSkillSuccessful(oPC, nSkill, nDC)) {
SetLocalInt(oPC, "ZEP_CR_DONE", ZEP_CR_DONE_SUCCESS);
return;
}
SetLocalInt(oPC, "ZEP_CR_DONE", ZEP_CR_DONE_FAILED);
}
// Stops crafting and cleans up everything set by the crafting script
// When nExecute is FALSE, it will abort the craft,
// when it's TRUE, it will replace the old item with the new one.
void ZEP_StopCraft(object oPC, int nExecute) {
// Get and equip correct item (backup when not successfull or cancelled)
object oItem = GetLocalObject(oPC, "ZEP_CR_ITEM");
object oBackup = GetLocalObject(oPC, "ZEP_CR_BACKUP");
if (nExecute) {
DestroyObject(oBackup);
SetStolenFlag(oItem, FALSE);
DeleteLocalInt(oItem, "ZEP_CR_TEMPITEM");
} else {
DestroyObject(oItem);
oItem = CopyItem(oBackup, oPC, TRUE);
DestroyObject(oBackup);
}
AssignCommand(oPC, ClearAllActions(TRUE));
if (GetBaseItemType(oItem)==BASE_ITEM_ARMOR) {
AssignCommand(oPC, ActionEquipItem(oItem, INVENTORY_SLOT_CHEST));
} else if (GetBaseItemType(oItem)==BASE_ITEM_HELMET) {
AssignCommand(oPC, ActionEquipItem(oItem, INVENTORY_SLOT_HEAD));
} else {
AssignCommand(oPC, ActionEquipItem(oItem, INVENTORY_SLOT_RIGHTHAND));
}
// Postclean settings
DeleteLocalInt(oPC, "ZEP_CR_COST");
DeleteLocalInt(oPC, "ZEP_CR_DC");
DeleteLocalInt(oPC, "ZEP_CR_PART");
DeleteLocalInt(oPC, "ZEP_CR_DONE");
DeleteLocalInt(oPC, "ZEP_CR_CHANGED");
DeleteLocalObject(oPC, "ZEP_CR_ITEM");
DeleteLocalObject(oPC, "ZEP_CR_BACKUP");
DeleteLocalObject(oPC, "ZEP_CR_NPC");
DeleteLocalObject(oPC, "ZEP_CR_PLACEABLE");
// Remove custscene immobilize and light from player
//Note from Loki: Doesn't seem to be any light. [FUTURE FIX]
effect eEff = GetFirstEffect(oPC);
while (GetIsEffectValid(eEff)) {
if (GetEffectType(eEff) == EFFECT_TYPE_CUTSCENEIMMOBILIZE)
RemoveEffect(oPC,eEff);
eEff = GetNextEffect(oPC);
}
RestoreCameraFacing();
}
// - private -
void ZEP_SetColorToken(int nIndex, int nColor) {
string sDyeTag = "Dye";
switch(nIndex) {
case ITEM_APPR_ARMOR_COLOR_CLOTH1:
case ITEM_APPR_ARMOR_COLOR_CLOTH2: sDyeTag+= "C"; break;
case ITEM_APPR_ARMOR_COLOR_LEATHER1:
case ITEM_APPR_ARMOR_COLOR_LEATHER2: sDyeTag+= "L"; break;
case ITEM_APPR_ARMOR_COLOR_METAL1:
case ITEM_APPR_ARMOR_COLOR_METAL2: sDyeTag+= "M";
if (nColor>55 && nColor<60) nColor-=4; break; // translate missing/double metal colors
}
if (nColor<10) sDyeTag+= "0";
sDyeTag+= IntToString(nColor);
SetCustomToken(ZEP_CR_TOKENBASE+3, GetName(GetObjectByTag(sDyeTag)));
}
// Sets the current part oPC is working on
// It accepts all 4 partseries ITEM_APPR_ARMOR_MODEL_*,
// ITEM_APPR_WEAPON_MODEL_*, ITEM_APPR_ARMOR_COLOR_*, ITEM_APPR_WEAPON_COLOR_*
// as long as the proper item has been set to craft on
// Focusses the camera on the selected part (if applicable)
void ZEP_SetPart(object oPC, int nPart, int nStrRef) {
SetLocalInt(oPC, "ZEP_CR_PART", nPart);
object oItem = GetLocalObject(oPC, "ZEP_CR_ITEM");
// * Make the camera float near the PC
float fFacing = GetFacing(oPC) + 180.0;
float fPitch = 75.0;
float fDistance= 3.5;
if (GetBaseItemType(oItem)==BASE_ITEM_ARMOR) {
switch (nPart) {
case ITEM_APPR_ARMOR_MODEL_LBICEP:
case ITEM_APPR_ARMOR_MODEL_LFOREARM:
case ITEM_APPR_ARMOR_MODEL_LHAND:
case ITEM_APPR_ARMOR_MODEL_LSHOULDER:
case ITEM_APPR_ARMOR_MODEL_LTHIGH:
case ITEM_APPR_ARMOR_MODEL_LSHIN:
case ITEM_APPR_ARMOR_MODEL_LFOOT: fFacing += 60.0; break;
case ITEM_APPR_ARMOR_MODEL_RBICEP:
case ITEM_APPR_ARMOR_MODEL_RFOREARM:
case ITEM_APPR_ARMOR_MODEL_RHAND:
case ITEM_APPR_ARMOR_MODEL_RSHOULDER:
case ITEM_APPR_ARMOR_MODEL_RTHIGH:
case ITEM_APPR_ARMOR_MODEL_RSHIN:
case ITEM_APPR_ARMOR_MODEL_RFOOT: fFacing -= 60.0; break;
}
switch (nPart) {
case ITEM_APPR_ARMOR_MODEL_LBICEP:
case ITEM_APPR_ARMOR_MODEL_RBICEP:
case ITEM_APPR_ARMOR_MODEL_LFOOT:
case ITEM_APPR_ARMOR_MODEL_RFOOT: fDistance = 3.5; fPitch = 47.0; break;
case ITEM_APPR_ARMOR_MODEL_LFOREARM:
case ITEM_APPR_ARMOR_MODEL_RFOREARM:
case ITEM_APPR_ARMOR_MODEL_LHAND:
case ITEM_APPR_ARMOR_MODEL_RHAND: fDistance = 2.0; fPitch = 60.0; break;
case ITEM_APPR_ARMOR_MODEL_LSHIN:
case ITEM_APPR_ARMOR_MODEL_RSHIN: fDistance = 3.5; fPitch = 95.0; break;
case ITEM_APPR_ARMOR_MODEL_LSHOULDER:
case ITEM_APPR_ARMOR_MODEL_RSHOULDER: fDistance = 3.0; fPitch = 50.0; break;
case ITEM_APPR_ARMOR_MODEL_LTHIGH:
case ITEM_APPR_ARMOR_MODEL_RTHIGH: fDistance = 2.5; fPitch = 65.0; break;
case ITEM_APPR_ARMOR_MODEL_NECK: fPitch = 90.0; break;
case ITEM_APPR_ARMOR_MODEL_BELT:
case ITEM_APPR_ARMOR_MODEL_PELVIS: fDistance = 2.0; break;
}
} else if (nPart==ZEP_CR_HELMET) {
fDistance = 2.5;
fPitch = 85.0;
} else if (nPart==ZEP_CR_SHIELD) {
fFacing += 60.0;
fDistance = 3.0;
fPitch = 65.0;
} else {
fFacing -= 60.0;
fDistance = 3.0;
fPitch = 65.0;
}
if (fFacing >= 360.0) fFacing -=360.0;
if (MyPRCGetRacialType(oPC) == RACIAL_TYPE_HALFORC) fDistance += 1.0f;
SetCameraFacing(fFacing, fDistance, fPitch, CAMERA_TRANSITION_TYPE_VERY_FAST);
int nCost = GetLocalInt(oPC, "ZEP_CR_COST");
int nDC = GetLocalInt(oPC, "ZEP_CR_DC");
SetCustomToken(ZEP_CR_TOKENBASE, GetStringByStrRef(nStrRef));
SetCustomToken(ZEP_CR_TOKENBASE+1, IntToString(nCost));
SetCustomToken(ZEP_CR_TOKENBASE+2, IntToString(nDC));
ZEP_SetColorToken(nPart, GetItemAppearance(oItem, ITEM_APPR_TYPE_ARMOR_COLOR, nPart));
}
// - private -
// Gets the cost to modify oItem into oNew
int ZEP_GetModificationCost(object oItem, object oNew, int nNPC=FALSE) {
int nCost = 0;
int nChanges = -1;
int nPart;
float fFactor;
//Note from Loki: Below segment's logical flow modified
//from original. As SartriX had used differing DC and
//cost values from Bioware, defined in des_crft_aparts.2da,
//this conflicted with the CEP's "play nice with Bioware"
//policy.
//I have left this functionality in, but you must enable
//a flag in the constants section of this file to turn it
//on. Otherwise, default Bioware costs will be used.
//Note that helmets and shields will ALWAYS default to
//using this case, as there is no Bioware code to emulate
//in their case.
if ((ZEP_USE_OPTIONAL_DC_COST == TRUE) || (GetBaseItemType(oItem)==BASE_ITEM_HELMET) || (GetBaseItemType(oItem)== BASE_ITEM_LARGESHIELD) || (GetBaseItemType(oItem)== BASE_ITEM_SMALLSHIELD) || (GetBaseItemType(oItem)== BASE_ITEM_TOWERSHIELD) )
{
// Find and count changes
if (GetBaseItemType(oItem)==BASE_ITEM_ARMOR) {
for (nPart = 0; nPart<=ITEM_APPR_ARMOR_MODEL_ROBE; nPart++) {
if (GetItemAppearance(oItem, ITEM_APPR_TYPE_ARMOR_MODEL, nPart) != GetItemAppearance(oNew, ITEM_APPR_TYPE_ARMOR_MODEL, nPart)) {
// Part changed, add price factor
nCost += StringToInt(Get2DAString("des_crft_aparts", "CraftCost", nPart));
nChanges++;
}
}
} else {
for (nPart = 0; nPart<3; nPart++) {
if (GetItemAppearance(oItem, ITEM_APPR_TYPE_WEAPON_MODEL, nPart) != GetItemAppearance(oNew, ITEM_APPR_TYPE_WEAPON_MODEL, nPart)) {
// Part changed, add price factor
nCost += ZEP_CR_PARTCOST;
nChanges++;
}
}
nChanges *= 5;
}
// More as 1 part changed, give a 'discount'
if (nChanges>0) nCost -= nChanges;
// Reworked item may not cost more as 90% of a brand new one
if (nCost>ZEP_CR_MAXCOST) nCost = ZEP_CR_MAXCOST;
if (nNPC) {
// If made by a NPC, charge for the dyes
if (GetBaseItemType(oItem)==BASE_ITEM_ARMOR) {
for (nPart = 0; nPart<=ITEM_APPR_ARMOR_MODEL_ROBE; nPart++) {
if (GetItemAppearance(oItem, ITEM_APPR_TYPE_ARMOR_COLOR, nPart) != GetItemAppearance(oNew, ITEM_APPR_TYPE_ARMOR_COLOR, nPart)) {
// Part changed, add price factor
nCost += ZEP_CR_NPCDYECOST;
}
}
} else {
for (nPart = 0; nPart<3; nPart++) {
if (GetItemAppearance(oItem, ITEM_APPR_TYPE_WEAPON_COLOR, nPart) != GetItemAppearance(oNew, ITEM_APPR_TYPE_WEAPON_COLOR, nPart)) {
// Part changed, add price factor
nCost += ZEP_CR_NPCDYECOST;
}
}
}
fFactor = IntToFloat(nCost) / 100.0;
} else {
// If made by the PC himself, the price is 70% of what an NPC would ask him
fFactor = IntToFloat(nCost * ZEP_CR_SELFCRAFT) / 10000.0;
}
// Calculate and return final cost
nCost = FloatToInt(IntToFloat(GetGoldPieceValue(oItem)) * fFactor);
if (nCost<1) nCost=1;
}
else //Use base Bioware costs for armor and weapons unless told otherwise.
{
int nItemType=GetBaseItemType(oItem);
if (nItemType == BASE_ITEM_ARMOR)
{
nPart=GetLocalInt(GetPCSpeaker(),"ZEP_CR_PART");
if (nPart==ITEM_APPR_ARMOR_MODEL_ROBE)
nCost=0;
else nCost=CIGetArmorModificationCost(oItem,oNew);
}
else nCost=CIGetWeaponModificationCost(oItem,oNew);
}
return nCost;
}
// - private -
// Gets the DC to modify oItem into oNew
int ZEP_GetModificationDC(object oItem, object oNew, int nNPC=FALSE) {
if (nNPC) return 0;
int nDC=0;
int nChanges = -1;
int nPart;
float fFactor;
//Note from Loki: Below segment's logical flow modified
//from original. As SartriX had used differing DC and
//cost values from Bioware, defined in des_crft_aparts.2da,
//this conflicted with the CEP's "play nice with Bioware"
//policy.
//I have left this functionality in, but you must enable
//a flag in the constants section of this file to turn it
//on. Otherwise, default Bioware costs/DC will be used.
//Note that helmets and shields will ALWAYS default to
//using this case, as there is no Bioware code to emulate
//in their case.
if ((ZEP_USE_OPTIONAL_DC_COST == TRUE) || (GetBaseItemType(oItem)==BASE_ITEM_HELMET) || (GetBaseItemType(oItem)== BASE_ITEM_LARGESHIELD) || (GetBaseItemType(oItem)== BASE_ITEM_SMALLSHIELD) || (GetBaseItemType(oItem)== BASE_ITEM_TOWERSHIELD) )
{
// Find and count changes
if (GetBaseItemType(oItem)==BASE_ITEM_ARMOR) {
for (nPart = 0; nPart<=ITEM_APPR_ARMOR_MODEL_ROBE; nPart++) {
if (GetItemAppearance(oItem, ITEM_APPR_TYPE_ARMOR_MODEL, nPart) != GetItemAppearance(oNew, ITEM_APPR_TYPE_ARMOR_MODEL, nPart)) {
// Part changed, add DC factor
nDC += StringToInt(Get2DAString("des_crft_aparts", "CraftDC", nPart));
nChanges++;
}
}
} else {
for (nPart = 0; nPart<3; nPart++) {
if (GetItemAppearance(oItem, ITEM_APPR_TYPE_WEAPON_MODEL, nPart) != GetItemAppearance(oNew, ITEM_APPR_TYPE_WEAPON_MODEL, nPart)) {
// Part changed, add DC factor
nDC += 6;
nChanges++;
}
}
nChanges *= 2;
}
// More as 1 part changed, give a 'discount'
if (nChanges>0) nDC -= nChanges;
itemproperty iP = GetFirstItemProperty(oItem);
while (GetIsItemPropertyValid(iP)) {
nDC += ZEP_CR_DCADD;
iP = GetNextItemProperty(oItem);
}
}
else
{
if (GetBaseItemType(oItem)==BASE_ITEM_ARMOR)
{
nPart=GetLocalInt(GetPCSpeaker(),"ZEP_CR_PART");
if (nPart==ITEM_APPR_ARMOR_MODEL_ROBE)
nDC=0;
else nDC=CIGetArmorModificationDC(oItem,oNew);
}
else nDC=15; //This value pulled directly from Bioware scripts.
}
return nDC;
}
// - private -
// Reverses a : seperated stringlist
string ZEP_ListReverse(string s) {
string sCache;
int n;
int l = GetStringLength(s);
s = GetSubString(s, 1, l);
while (s!="") {
// take string upto next seperator and put this in front of cache
n = FindSubString(s, ":")+1;
sCache = GetStringLeft(s, n) + sCache;
s = GetSubString(s, n, l);
}
return ":"+sCache;
}
// - private -
// Prereads the parts_chest.2da-file for sAC and puts all used ID's in a : seperated stringlist
string ZEP_PreReadArmorACList(string sAC) {
// pick the right 2da to read the parts from
string s2DA = "parts_chest";
string sCache= ":";
string sLine;
// get the maxID used (not the amount of ID's !!!)
//int nMax = IPGetNumberOfArmorAppearances(ITEM_APPR_ARMOR_MODEL_TORSO);
//Note from Loki: Below line changed to make use of
//backward compatibility function. Was previously the
//preceding line.
int nMax = ZEP_GetNumberOfArmorAppearances(ITEM_APPR_ARMOR_MODEL_TORSO);
int n=1;
sAC = GetStringLeft(sAC, 1);
while (n<=nMax) {
// Verify validity of the ID and add to the list
sLine = Get2DAString(s2DA, "ACBONUS", n);
if (GetStringLeft(sLine, 1)==sAC) {
sCache+= IntToString(n)+":";
}
n++;
}
// Store the list in a modulestring, once normal, once reversed, both with ID 0 added as first index for cycling
SetLocalString(GetModule(), "ZEP_IDPreReadAC_"+GetStringLeft(sAC,1), sCache);
SetLocalString(GetModule(), "ZEP_IDPreReadACR_"+GetStringLeft(sAC,1), ZEP_ListReverse(sCache));
return sCache;
}
// - private -
// Prereads the 2da-file for nPart and puts all used ID's in a : seperated stringlist
string ZEP_PreReadArmorPartList(int nPart) {
// pick the right 2da to read the parts from
string s2DA = "parts_";
switch (nPart) {
case ITEM_APPR_ARMOR_MODEL_LBICEP:
case ITEM_APPR_ARMOR_MODEL_RBICEP: s2DA+= "bicep"; break;
case ITEM_APPR_ARMOR_MODEL_LFOOT:
case ITEM_APPR_ARMOR_MODEL_RFOOT: s2DA+= "foot"; break;
case ITEM_APPR_ARMOR_MODEL_LFOREARM:
case ITEM_APPR_ARMOR_MODEL_RFOREARM: s2DA+= "forearm"; break;
case ITEM_APPR_ARMOR_MODEL_LHAND:
case ITEM_APPR_ARMOR_MODEL_RHAND: s2DA+= "hand"; break;
case ITEM_APPR_ARMOR_MODEL_LSHIN:
case ITEM_APPR_ARMOR_MODEL_RSHIN: s2DA+= "shin"; break;
case ITEM_APPR_ARMOR_MODEL_LSHOULDER:
case ITEM_APPR_ARMOR_MODEL_RSHOULDER: s2DA+= "shoulder"; break;
case ITEM_APPR_ARMOR_MODEL_LTHIGH:
case ITEM_APPR_ARMOR_MODEL_RTHIGH: s2DA+= "legs"; break;
case ITEM_APPR_ARMOR_MODEL_NECK: s2DA+= "neck"; break;
case ITEM_APPR_ARMOR_MODEL_BELT: s2DA+= "belt"; break;
case ITEM_APPR_ARMOR_MODEL_PELVIS: s2DA+= "pelvis"; break;
case ITEM_APPR_ARMOR_MODEL_ROBE: s2DA+= "robe"; break;
}
string sCache= ":";
string sLine;
// get the maxID used (not the amount of ID's !!!)
//int nMax = StringToInt(Get2DAString("des_crft_aparts", "NumParts", nPart));
//Note from Loki: Below line changed to make use of
//backward compatibility function. Was previously the
//preceding line.
int nMax = ZEP_GetNumberOfArmorAppearances(nPart);
int n=1;
while (n<=nMax) {
// Verify validity of the ID and add to the list
sLine = Get2DAString(s2DA, "ACBONUS", n);
if (sLine!="") {
sCache+= IntToString(n)+":";
}
n++;
}
// Store the list in a modulestring, once normal, once reversed, both with ID 0 added as first index for cycling
SetLocalString(GetModule(), "ZEP_IDPreRead_"+IntToString(nPart), ":0"+sCache);
SetLocalString(GetModule(), "ZEP_IDPreReadR_"+IntToString(nPart), ":0"+ZEP_ListReverse(sCache));
return sCache;
}
// Remakes and equips the item oPC is working, having the currently set part
// cycled either forward or backward
// nMode: ZEP_CR_PART_NEXT - cycle forward
// nMode: ZEP_CR_PART_PREV - cycle backward
void ZEP_RemakeItem(object oPC, int nMode) {
SetLocalInt(oPC, "ZEP_CR_CHANGED", TRUE);
object oItem = GetLocalObject(oPC, "ZEP_CR_ITEM");
int nPart = GetLocalInt(oPC, "ZEP_CR_PART");
int nCurrApp, nSlot, nCost, nDC;
string sPreRead;
object oNew;
if (GetBaseItemType(oItem)==BASE_ITEM_ARMOR) {
// Handle Armor change
nCurrApp = GetItemAppearance(oItem, ITEM_APPR_TYPE_ARMOR_MODEL, nPart);
if (nPart == ITEM_APPR_ARMOR_MODEL_TORSO) {
string sAC = Get2DAString("parts_chest", "ACBONUS", nCurrApp);
// Fetch the stringlist that holds the ID's for this part
sPreRead = GetLocalString(GetModule(), "ZEP_IDPreReadAC_"+GetStringLeft(sAC,1));
if (sPreRead=="") // list didn't exist yet, so generate it
sPreRead = ZEP_PreReadArmorACList(sAC);
if (nMode==ZEP_CR_PART_PREV)
sPreRead = GetLocalString(GetModule(), "ZEP_IDPreReadACR_"+GetStringLeft(sAC,1));
} else {
// Fetch the stringlist that holds the ID's for this part
sPreRead = GetLocalString(GetModule(), "ZEP_IDPreRead_"+IntToString(nPart));
if (sPreRead=="") // list didn't exist yet, so generate it
sPreRead = ZEP_PreReadArmorPartList(nPart);
if (nMode==ZEP_CR_PART_PREV) sPreRead = GetLocalString(GetModule(), "ZEP_IDPreReadR_"+IntToString(nPart));
}
// Find the current ID in the stringlist and pick the one coming after that
string sID;
string sCurrApp = IntToString(nCurrApp);
int n = FindSubString(sPreRead, ":"+sCurrApp+":");
sID = GetSubString(sPreRead, n+GetStringLength(sCurrApp)+2, 5);
n = FindSubString(sID, ":");
sID = GetStringLeft(sID, n);
if (sID=="" && nPart == ITEM_APPR_ARMOR_MODEL_TORSO) {
sID = GetSubString(sPreRead, 1, 5);
n = FindSubString(sID, ":");
sID = GetStringLeft(sID, n);
}
nCurrApp = StringToInt(sID);
oNew = CopyItemAndModify(oItem, ITEM_APPR_TYPE_ARMOR_MODEL, nPart, nCurrApp, TRUE);
nSlot = INVENTORY_SLOT_CHEST;
} else if (nPart == ZEP_CR_HELMET) {
// Handle Helmet change
nCurrApp = GetItemAppearance(oItem, ITEM_APPR_TYPE_ARMOR_MODEL, 0);
int nMin = 1;
int nMax = StringToInt(Get2DAString("baseitems", "MaxRange", BASE_ITEM_HELMET));
//Note from Loki: Below code added in Do/while loop to
//allow for scaling of helmets within reason without
//needing to constantly reset the baseitems.2da file
//parameters
do {
if (nMode == ZEP_CR_PART_NEXT) {
if (++nCurrApp>nMax) nCurrApp = nMin;
} else {
if (--nCurrApp<nMin) nCurrApp = nMax;
}
oNew = CopyItemAndModify(oItem, ITEM_APPR_TYPE_ARMOR_MODEL, 0, nCurrApp, TRUE);
} while (!GetIsObjectValid(oNew));
nSlot = INVENTORY_SLOT_HEAD;
} else if (nPart == ZEP_CR_SHIELD) {
// Handle Shield change
nCurrApp = GetItemAppearance(oItem, ITEM_APPR_TYPE_SIMPLE_MODEL, 0);
int nBaseType = GetBaseItemType(oItem);
int nMin = StringToInt(Get2DAString("baseitems", "MinRange", nBaseType));
int nMax = StringToInt(Get2DAString("baseitems", "MaxRange", nBaseType));
//Note from Loki: This code i nthe Do/While may look a
//bit odd. This is because it does not follow the
//standard method in the rest of this code for
//changing appearance with one variable and color with
//another. Since shields do not have colors per se,
//and CEP shields are not all numbered as the Bioware
//shields are (only using appearanes **1-**3, always
//contiguous in their appearance indexes), treating
//them as if they did seemed to be inefficient. Hence,
//the loop updates it's counter a single index at a time
//and searches for the next valid model. This allows
//for shields with one's digits of over 3, as well as
//those starting at odd places (not having a **1
//appearance, for example).
do {
if (nMode == ZEP_CR_PART_NEXT)
{
if (++nCurrApp > nMax) nCurrApp=nMin;
}
else
{
if (--nCurrApp < nMin) nCurrApp=nMax;
}
oNew = CopyItemAndModify(oItem, ITEM_APPR_TYPE_SIMPLE_MODEL, 0, nCurrApp, TRUE);
} while (!GetIsObjectValid(oNew));
nSlot = INVENTORY_SLOT_LEFTHAND;
} else {
// Handle Weapon change
nCurrApp = GetItemAppearance(oItem, ITEM_APPR_TYPE_WEAPON_MODEL, nPart);
int nBaseType = GetBaseItemType(oItem);
int nMin = StringToInt(Get2DAString("baseitems", "MinRange", nBaseType)) /10;
int nMax = StringToInt(Get2DAString("baseitems", "MaxRange", nBaseType)) /10;
//Once again, Do/While loop added to accomodate the fact that
//CEP models are not all contiguous with each other. This
//allows the code to rapidly skip over gaps in the weapon
//models to the next valid index.
do {
if (nMode == ZEP_CR_PART_NEXT) {
if (++nCurrApp>nMax) nCurrApp = nMin;
} else {
if (--nCurrApp<nMin) nCurrApp = nMax;
}
oNew = CopyItemAndModify(oItem, ITEM_APPR_TYPE_WEAPON_MODEL, nPart, nCurrApp, TRUE);
} while (!GetIsObjectValid(oNew));
nSlot = INVENTORY_SLOT_RIGHTHAND;
}
if (GetIsObjectValid(oNew)) {
// new object is valid
// get cost and DC
int nNPC = GetIsObjectValid(GetLocalObject(oPC, "ZEP_CR_NPC"));
object oBackup = GetLocalObject(oPC, "ZEP_CR_BACKUP");
nCost = ZEP_GetModificationCost(oBackup, oNew, nNPC);
nDC = ZEP_GetModificationDC(oBackup, oNew, nNPC);
SetLocalInt(oPC, "ZEP_CR_COST", nCost);
SetLocalInt(oPC, "ZEP_CR_DC", nDC);
SetCustomToken(ZEP_CR_TOKENBASE+1, IntToString(nCost));
SetCustomToken(ZEP_CR_TOKENBASE+2, IntToString(nDC));
// replace old current object with new one
DestroyObject(oItem);
//DestroyObject(oBackup);
//oItem = oNew;
SetLocalObject(oPC, "ZEP_CR_ITEM", oNew);
SetLocalInt(oNew, "ZEP_CR_TEMPITEM", TRUE);
SetStolenFlag(oNew,TRUE);
AssignCommand(oPC, ClearAllActions(TRUE));
AssignCommand(oPC, ActionEquipItem(oNew, nSlot));
}
}
//Note from Loki: Below function is currently not used,
//except on weapons, as we have not yet fully converted
//SartriX's implementation of preview-able dye-ing of
//armor and weapons into something compatible with
//Bioware's existing system. This function
//subject to heavy change and gutting in future releases.
//[FUTURE FIX]
// Remakes and equips the item oPC is working, having the currently set color
// cycled either forward or backward
// nMode: ZEP_CR_COLOR_NEXT - cycle forward
// nMode: ZEP_CR_COLOR_PREV - cycle backward
void ZEP_RecolorItem(object oPC, int nMode) {
SetLocalInt(oPC, "ZEP_CR_CHANGED", TRUE);
object oItem = GetLocalObject(oPC, "ZEP_CR_ITEM");
int nPart = GetLocalInt(oPC, "ZEP_CR_PART");
int nCurrApp, nSlot, nCost, nDC;
object oNew;
if (GetBaseItemType(oItem)==BASE_ITEM_ARMOR || GetBaseItemType(oItem)==BASE_ITEM_HELMET) {
// Handle Armor change
nCurrApp = GetItemAppearance(oItem, ITEM_APPR_TYPE_ARMOR_COLOR, nPart);
int nMin = 0;
int nMax = 63; //64 colors in NWN Palette-Loki
if (nMode == ZEP_CR_COLOR_NEXT) {
if (++nCurrApp>nMax) nCurrApp = nMin;
} else {
if (--nCurrApp<nMin) nCurrApp = nMax;
}
ZEP_SetColorToken(nPart, nCurrApp);
oNew = CopyItemAndModify(oItem, ITEM_APPR_TYPE_ARMOR_COLOR, nPart, nCurrApp, TRUE);
nSlot = INVENTORY_SLOT_CHEST;
if (GetBaseItemType(oItem)==BASE_ITEM_HELMET)
nSlot = INVENTORY_SLOT_HEAD;
} else if (nPart == ZEP_CR_SHIELD) {
// Handle Weapon change
nCurrApp = GetItemAppearance(oItem, ITEM_APPR_TYPE_SIMPLE_MODEL, 0);
int nMod = (nCurrApp/10)*10;
nCurrApp-= nMod;
int nMin = 1;
int nMax = 9; //Shield models final digit can range from 1-9 (techniclly 0 is included, but there are no index 0 models)
do {
if (nMode == ZEP_CR_COLOR_NEXT) {
if (++nCurrApp>nMax) nCurrApp = nMin;
} else {
if (--nCurrApp<nMin) nCurrApp = nMax;
}
nCurrApp += nMod;
//
oNew = CopyItemAndModify(oItem, ITEM_APPR_TYPE_SIMPLE_MODEL, 0, nCurrApp, TRUE);
} while (!GetIsObjectValid(oNew));
nSlot = INVENTORY_SLOT_LEFTHAND;
} else {
// Handle Weapon change- Addition of Do/While and indexes over 4 not tested yet [FUTURE FIX]
nCurrApp = GetItemAppearance(oItem, ITEM_APPR_TYPE_WEAPON_COLOR, nPart);
int nMin = 1;
int nMax = 3; //Only 3 colors supported in R1 of CEP, until we get 4th colors for all weapons.
// do {
if (nMode == ZEP_CR_COLOR_NEXT)
{
if (++nCurrApp>nMax) nCurrApp = nMin;
}
else {
if (--nCurrApp<nMin) nCurrApp = nMax;
}
oNew = CopyItemAndModify(oItem, ITEM_APPR_TYPE_WEAPON_COLOR, nPart, nCurrApp, TRUE);
// } while (!GetIsObjectValid(oNew));
nSlot = INVENTORY_SLOT_RIGHTHAND;
}
if (GetIsObjectValid(oNew)) {
// new object is valid
// get cost and DC
int nNPC = GetIsObjectValid(GetLocalObject(oPC, "ZEP_CR_NPC"));
object oBackup = GetLocalObject(oPC, "ZEP_CR_BACKUP");
nCost = ZEP_GetModificationCost(oBackup, oNew, nNPC);
nDC = ZEP_GetModificationDC(oBackup, oNew, nNPC);
SetLocalInt(oPC, "ZEP_CR_COST", nCost);
SetLocalInt(oPC, "ZEP_CR_DC", nDC);
SetCustomToken(ZEP_CR_TOKENBASE+1, IntToString(nCost));
SetCustomToken(ZEP_CR_TOKENBASE+2, IntToString(nDC));
// replace old current object with new one
DestroyObject(oItem);
oItem = oNew;
SetLocalObject(oPC, "ZEP_CR_ITEM", oItem);
AssignCommand(oPC, ClearAllActions(TRUE));
AssignCommand(oPC, ActionEquipItem(oItem, nSlot));
}
}
int ZEP_GetIsWeapon(object oWeapon) {
int iType = GetBaseItemType(oWeapon);
switch (iType) {
case BASE_ITEM_BASTARDSWORD:
case BASE_ITEM_BATTLEAXE:
case BASE_ITEM_DAGGER:
case BASE_ITEM_DIREMACE:
case BASE_ITEM_DOUBLEAXE:
case BASE_ITEM_DWARVENWARAXE:
case BASE_ITEM_GREATAXE:
case BASE_ITEM_GREATSWORD:
case BASE_ITEM_HALBERD:
case BASE_ITEM_HANDAXE:
case BASE_ITEM_HEAVYFLAIL:
case BASE_ITEM_KAMA:
case BASE_ITEM_KATANA:
case BASE_ITEM_KUKRI:
case BASE_ITEM_LIGHTFLAIL:
case BASE_ITEM_LIGHTHAMMER:
case BASE_ITEM_LIGHTMACE:
case BASE_ITEM_LONGSWORD:
case BASE_ITEM_MORNINGSTAR:
case BASE_ITEM_RAPIER:
case BASE_ITEM_SCIMITAR:
case BASE_ITEM_SCYTHE:
case BASE_ITEM_SHORTSPEAR:
case BASE_ITEM_SHORTSWORD:
case BASE_ITEM_SICKLE:
case BASE_ITEM_THROWINGAXE:
case BASE_ITEM_TWOBLADEDSWORD:
case BASE_ITEM_WARHAMMER:
case BASE_ITEM_CLUB:
case BASE_ITEM_HEAVYCROSSBOW:
case BASE_ITEM_LIGHTCROSSBOW:
case BASE_ITEM_LONGBOW:
case BASE_ITEM_MAGICSTAFF:
case BASE_ITEM_QUARTERSTAFF:
case BASE_ITEM_SHORTBOW:
case BASE_ITEM_SLING:
case BASE_ITEM_WHIP:
//Note from Loki: Following cases are custom CEP weapon types
case BASE_ITEM_TRIDENT:
case BASE_ITEM_HEAVY_PICK:
case BASE_ITEM_LIGHT_PICK:
case BASE_ITEM_SAI:
case BASE_ITEM_NUNCHAKU:
//case BASE_ITEM_FALCHION1:
case BASE_ITEM_SAP:
case BASE_ITEM_DAGGERASSASSIN:
case BASE_ITEM_KATAR:
case BASE_ITEM_LIGHTMACE2:
case BASE_ITEM_KUKRI2:
case BASE_ITEM_FALCHION2:
case BASE_ITEM_HEAVY_MACE:
case BASE_ITEM_MAUL:
case BASE_ITEM_MERCURIALLONGSWORD:
case BASE_ITEM_MERCURIALGREATSWORD:
case BASE_ITEM_DOUBLE_SCIMITAR:
case BASE_ITEM_GOAD:
case BASE_ITEM_WINDFIREWHEEL: return TRUE;
}
return FALSE;
}
int ZEP_GetIsShield(object oShield) {
int iType = GetBaseItemType(oShield);
if (iType==BASE_ITEM_SMALLSHIELD || iType==BASE_ITEM_LARGESHIELD || iType==BASE_ITEM_TOWERSHIELD)
return TRUE;
return FALSE;
}
//Below script by Loki...basically just a copy of Bioware's
//script for X2 to get the local crafting work container, if
//it exists, and if not, to create it and render it invisble
//and unselectable.
object ZEP_GetZEPWorkContainer(object oCaller)
{
//First try to get the container.
object oContainer = GetObjectByTag(ZEP_CR_BACKUP_PLACEABLE);
//If it's not valid, we make one.
if (!GetIsObjectValid(oContainer))
{
oContainer = CreateObject(OBJECT_TYPE_PLACEABLE,ZEP_CR_BACKUP_PLACEABLE,GetLocation(oCaller));
// SetLocalInt(oContainer,"DYNAMICALLY_CREATED",1);
effect eCutsceneInvis = EffectVisualEffect( VFX_DUR_CUTSCENE_INVISIBILITY);
eCutsceneInvis = ExtraordinaryEffect(eCutsceneInvis);
ApplyEffectToObject(DURATION_TYPE_PERMANENT,eCutsceneInvis,oContainer);
}
return oContainer;
}
//Below function by Loki
//Below function used as a substitution for the
//IPGetNumberOfArmorAppearances function in the CEP code.
//This is done because the max NumParts is coded as a
//constant to ensure compatibility with "vanilla' NWN.
int ZEP_GetNumberOfArmorAppearances(int nPart)
{
int nReturn;
switch (nPart)
{
case ITEM_APPR_ARMOR_MODEL_RFOOT:
case ITEM_APPR_ARMOR_MODEL_LFOOT: nReturn=ZEP_MAX_PARTS_FOOT;
case ITEM_APPR_ARMOR_MODEL_RSHIN:
case ITEM_APPR_ARMOR_MODEL_LSHIN: nReturn=ZEP_MAX_PARTS_SHIN;
case ITEM_APPR_ARMOR_MODEL_LTHIGH:
case ITEM_APPR_ARMOR_MODEL_RTHIGH: nReturn=ZEP_MAX_PARTS_THIGH;
case ITEM_APPR_ARMOR_MODEL_PELVIS: nReturn=ZEP_MAX_PARTS_PELVIS;
case ITEM_APPR_ARMOR_MODEL_TORSO: nReturn=ZEP_MAX_PARTS_TORSO;
case ITEM_APPR_ARMOR_MODEL_BELT: nReturn=ZEP_MAX_PARTS_BELT;
case ITEM_APPR_ARMOR_MODEL_NECK: nReturn=ZEP_MAX_PARTS_NECK;
case ITEM_APPR_ARMOR_MODEL_RFOREARM:
case ITEM_APPR_ARMOR_MODEL_LFOREARM: nReturn=ZEP_MAX_PARTS_FOREARM;
case ITEM_APPR_ARMOR_MODEL_RBICEP:
case ITEM_APPR_ARMOR_MODEL_LBICEP: nReturn=ZEP_MAX_PARTS_BICEP;
case ITEM_APPR_ARMOR_MODEL_RSHOULDER:
case ITEM_APPR_ARMOR_MODEL_LSHOULDER: nReturn=ZEP_MAX_PARTS_SHOULDER;
case ITEM_APPR_ARMOR_MODEL_RHAND:
case ITEM_APPR_ARMOR_MODEL_LHAND: nReturn=ZEP_MAX_PARTS_HAND;
case ITEM_APPR_ARMOR_MODEL_ROBE: nReturn=ZEP_MAX_PARTS_ROBE;
}
return nReturn;
}
//Below function heavily modified by Loki
//This is a retooled version of SartriX's PurifyItem function.
//It has been enhanced to create a message to log the name
//of any duplicate found, as well as the player posessing it,
//and send this information to all DMs as well as log it to
//the server log file.
//Arguments
// oItem is the object to test.
// oPC is the PC Owner of the item
// nIsEntering is a TRUE/FALSE flag that tells the function
// if it is being called in an OnEnter script or not.
// If so, it notes this in the Log file message, saying
// the item was found on an entering player. Logs
// without this message mean the item was on an
// already logged-on player, indicating recent duping.
void ZEP_PurifyItem(object oItem, object oPC, int nIsEntering)
{
string sDupeReport;
if (GetLocalInt(oItem, "ZEP_CR_TEMPITEM"))
{
//SendMessageToPC(oPC,("Destroyed: "+GetName(oItem)+"Crafting Duplicate"));
//Note from Loki: The following block of code checks if
//the function is being run as part of an "OnEnter"
//script (as indicated y the function argument "nIsEntering".
//If so, we note this in the log file. Otherwise we send a
//slightly shorter message.
if (nIsEntering)
sDupeReport="Crafting Duplicate '"+GetName(oItem)+"' Detected on entering player: "+GetName(oPC)+". Item Destroyed.";
else sDupeReport="Crafting Duplicate '"+GetName(oItem)+"' Detected on player: "+GetName(oPC)+". Item Destroyed.";
DestroyObject(oItem);
WriteTimestampedLogEntry(sDupeReport);
SendMessageToAllDMs(sDupeReport);
}
}
//Below Function a modification of SartriX's original nocheat
//code. I felt it would be better to encapsulate such
//functionality into a function, to make it easier to
//integrate into the OnEnter event hooks of existing modules
//and PWs.
//Argument explanation:
// oPC - PCs whos items we want ot check for crafting
// duplicates
// nIsEntering -
// Variable determines whether to flag potential
// DM Alert messages as "entering" or not.
// Should be TRUE in an OnEnter script, FALSE
// otherwise.
// nDeleteTempVars -
// When set to true, function will delete
// crafting-associated local variables from the
// PC in question.
void ZEP_PurifyAllItems(object oPC, int nIsEntering=FALSE,int nDeleteTempVars=FALSE)
{
ZEP_PurifyItem(GetItemInSlot(INVENTORY_SLOT_CHEST, oPC),oPC,nIsEntering);
ZEP_PurifyItem(GetItemInSlot(INVENTORY_SLOT_HEAD, oPC),oPC,nIsEntering);
ZEP_PurifyItem(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC),oPC,nIsEntering);
ZEP_PurifyItem(GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oPC),oPC,nIsEntering);
object oItem = GetFirstItemInInventory(oPC);
while (GetIsObjectValid(oItem))
{
ZEP_PurifyItem(oItem,oPC,TRUE);
oItem = GetNextItemInInventory(oPC);
}
if (nDeleteTempVars == FALSE)
return;
DeleteLocalInt(oPC, "ZEP_CR_STARTED");
}
//:: void main (){}