1199 lines
47 KiB
Plaintext
1199 lines
47 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
|
|
//:://////////////////////////////////////////////
|
|
//:: The Krit modified shield crafting on 10-Oct-2008.
|
|
//:: (Also restored support for CEP tridents, and
|
|
//:: fixed bug in ZEP_GetNumberOfArmorAppearances().)
|
|
//:://////////////////////////////////////////////
|
|
|
|
#include "prc_x2_craft"
|
|
#include "prc_misc_const"
|
|
|
|
//#include "x2_inc_craft"
|
|
//#include "zep_inc_main"
|
|
|
|
// 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 camera 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);
|
|
|
|
|
|
// - 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;
|
|
int iHitDice = GetHitDice(oPC);
|
|
int iCraftCost = iHitDice*(100);
|
|
string sAreaTag = GetTag(GetArea(oPC));
|
|
|
|
if (sAreaTag == "SignesDressingroom")
|
|
{
|
|
SetLocalInt(oPC, "ZEP_CR_DONE", ZEP_CR_DONE_SUCCESS);
|
|
}
|
|
else if (GetGold(oPC) >= iCraftCost)
|
|
{
|
|
SetLocalInt(oPC, "ZEP_CR_DONE", ZEP_CR_DONE_SUCCESS);
|
|
TakeGoldFromCreature(iCraftCost, oPC, TRUE);
|
|
}
|
|
else
|
|
{
|
|
SetLocalInt(oPC, "ZEP_CR_DONE", ZEP_CR_DONE_NOGOLD);
|
|
}
|
|
}
|
|
|
|
// 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_CHANGED");
|
|
DeleteLocalInt(oPC, "ZEP_CR_COST");
|
|
DeleteLocalInt(oPC, "ZEP_CR_DC");
|
|
DeleteLocalInt(oPC, "ZEP_CR_DONE");
|
|
DeleteLocalInt(oPC, "ZEP_CR_PART");
|
|
DeleteLocalString(oPC, "ZEP_CR_PARTNAME");
|
|
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);
|
|
string sPartName = GetStringByStrRef(nStrRef);
|
|
SetLocalString(oPC, "ZEP_CR_PARTNAME", sPartName);
|
|
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 (GetRacialType(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, sPartName);
|
|
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 up to the 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));
|
|
|
|
// Krit replacing Loki's code since 1.69 seems to have broken
|
|
// the old way of determining which shield models exist:
|
|
string sTest = "";
|
|
int nStartApp = nCurrApp; // Safety precaution against infinite loops.
|
|
|
|
// Determine the column in cepshieldmodel.2da to consult.
|
|
string sColumn = "BASE_ITEM_";
|
|
switch ( nBaseType )
|
|
{
|
|
case BASE_ITEM_SMALLSHIELD: sColumn += "SMALLSHIELD"; break;
|
|
case BASE_ITEM_LARGESHIELD: sColumn += "LARGESHIELD"; break;
|
|
case BASE_ITEM_TOWERSHIELD: sColumn += "TOWERSHIELD"; break;
|
|
}
|
|
|
|
// Set the direction of the scan.
|
|
// (Separate loops for run-time efficiency.)
|
|
if ( nMode == ZEP_CR_PART_NEXT )
|
|
// Find the next available shield model.
|
|
do
|
|
{
|
|
if ( ++nCurrApp > nMax )
|
|
nCurrApp = nMin;
|
|
sTest = Get2DAString("cepshieldmodel", sColumn, nCurrApp);
|
|
}
|
|
while ( sTest == "" && nCurrApp != nStartApp );
|
|
else
|
|
// Find the previous available shield model.
|
|
do
|
|
{
|
|
if ( --nCurrApp < nMin )
|
|
nCurrApp = nMax;
|
|
sTest = Get2DAString("cepshieldmodel", sColumn, nCurrApp);
|
|
}
|
|
while ( sTest == "" && nCurrApp != nStartApp );
|
|
|
|
// Create the new item.
|
|
oNew = CopyItemAndModify(oItem, ITEM_APPR_TYPE_SIMPLE_MODEL, 0, nCurrApp, TRUE);
|
|
nSlot = INVENTORY_SLOT_LEFTHAND;
|
|
// End Krit's modification.
|
|
|
|
}
|
|
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;
|
|
|
|
|
|
//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));
|
|
// Restore the part name (for multiplayer).
|
|
SetCustomToken(ZEP_CR_TOKENBASE, GetLocalString(oPC, "ZEP_CR_PARTNAME"));
|
|
|
|
// replace old current object with new one
|
|
DestroyObject(oItem);
|
|
// DestroyObject(oBackup);
|
|
//oItem = oNew;
|
|
SetLocalObject(oPC, "ZEP_CR_ITEM", oNew);
|
|
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));
|
|
// Restore the part name (for multiplayer).
|
|
SetCustomToken(ZEP_CR_TOKENBASE, GetLocalString(oPC, "ZEP_CR_PARTNAME"));
|
|
|
|
// 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:
|
|
case BASE_ITEM_TRIDENT:
|
|
//Note from Loki: Following cases are custom CEP weapon types
|
|
case BASE_ITEM_HEAVY_PICK:
|
|
case BASE_ITEM_LIGHT_PICK:
|
|
case BASE_ITEM_SAI:
|
|
case BASE_ITEM_NUNCHAKU:
|
|
case BASE_ITEM_FALCHION:
|
|
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;
|
|
}
|
|
|
|
// Returns TRUE if oShield is a shield.
|
|
int ZEP_GetIsShield(object oShield)
|
|
{
|
|
int iType = GetBaseItemType(oShield);
|
|
|
|
return iType == BASE_ITEM_SMALLSHIELD ||
|
|
iType == BASE_ITEM_LARGESHIELD ||
|
|
iType == BASE_ITEM_TOWERSHIELD;
|
|
}
|
|
|
|
//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)
|
|
{
|
|
switch ( nPart )
|
|
{
|
|
case ITEM_APPR_ARMOR_MODEL_BELT: return ZEP_MAX_PARTS_BELT;
|
|
case ITEM_APPR_ARMOR_MODEL_NECK: return ZEP_MAX_PARTS_NECK;
|
|
case ITEM_APPR_ARMOR_MODEL_PELVIS: return ZEP_MAX_PARTS_PELVIS;
|
|
case ITEM_APPR_ARMOR_MODEL_ROBE: return ZEP_MAX_PARTS_ROBE;
|
|
case ITEM_APPR_ARMOR_MODEL_TORSO: return ZEP_MAX_PARTS_TORSO;
|
|
|
|
case ITEM_APPR_ARMOR_MODEL_RFOOT:
|
|
case ITEM_APPR_ARMOR_MODEL_LFOOT: return ZEP_MAX_PARTS_FOOT;
|
|
|
|
case ITEM_APPR_ARMOR_MODEL_RSHIN:
|
|
case ITEM_APPR_ARMOR_MODEL_LSHIN: return ZEP_MAX_PARTS_SHIN;
|
|
|
|
case ITEM_APPR_ARMOR_MODEL_LTHIGH:
|
|
case ITEM_APPR_ARMOR_MODEL_RTHIGH: return ZEP_MAX_PARTS_THIGH;
|
|
|
|
case ITEM_APPR_ARMOR_MODEL_RHAND:
|
|
case ITEM_APPR_ARMOR_MODEL_LHAND: return ZEP_MAX_PARTS_HAND;
|
|
|
|
case ITEM_APPR_ARMOR_MODEL_RFOREARM:
|
|
case ITEM_APPR_ARMOR_MODEL_LFOREARM: return ZEP_MAX_PARTS_FOREARM;
|
|
|
|
case ITEM_APPR_ARMOR_MODEL_RBICEP:
|
|
case ITEM_APPR_ARMOR_MODEL_LBICEP: return ZEP_MAX_PARTS_BICEP;
|
|
|
|
case ITEM_APPR_ARMOR_MODEL_RSHOULDER:
|
|
case ITEM_APPR_ARMOR_MODEL_LSHOULDER: return ZEP_MAX_PARTS_SHOULDER;
|
|
}
|
|
|
|
// Unrecognized part.
|
|
return 0;
|
|
}
|
|
|
|
//:: void main (){}
|