mirror of
https://github.com/SWG-Source/dsrc.git
synced 2026-07-31 00:15:54 -04:00
590 lines
13 KiB
Plaintext
590 lines
13 KiB
Plaintext
/**********************************************************************
|
|
* Title: magic_item.scriptlib
|
|
* Description: magic item reference
|
|
**********************************************************************/
|
|
|
|
/***** INCLUDES ********************************************************/
|
|
|
|
include library.utils;
|
|
include java.util.Arrays;
|
|
include java.util.Vector;
|
|
|
|
/***** CONSTANTS *******************************************************/
|
|
|
|
const float PT_DELTA = 0.15f;
|
|
|
|
const string TBL_COST = "datatables/magic_item/mod_cost.iff";
|
|
|
|
const string COL_MAX = "MAX";
|
|
|
|
/***** FUNCTIONS **************************************************/
|
|
/***** GENERAL FUNCTION ************************************/
|
|
/************************************************************
|
|
* @brief attempts to convert the target item to a magic item
|
|
*
|
|
* @param obj_id item
|
|
* @param int mobLevel
|
|
*
|
|
* @return boolean; false on error
|
|
************************************************************/
|
|
boolean convertToMagicItem(obj_id item, int mobLevel)
|
|
{
|
|
LOG("magic_item","**************** convertToMagicItem: " + getGameTime() + " **************");
|
|
if ( !isIdValid(item) )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if ( mobLevel < 1 )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
LOG("magic_item","params: item = " + item + " mobLevel = " + mobLevel);
|
|
|
|
int total = getBuyPoints(mobLevel);
|
|
if ( total < 1 )
|
|
{
|
|
return false;
|
|
}
|
|
LOG("magic_item","buy points = " + total);
|
|
|
|
resizeable string[] mods = new string[0];
|
|
|
|
int got = getGameObjectType(item);
|
|
LOG("magic_item","GOT = " + got);
|
|
|
|
string apr = getAppearance(item);
|
|
if ( (apr == null) || (apr.equals("")) )
|
|
{
|
|
return false;
|
|
}
|
|
LOG("magic_item","FULL appearance = " + apr);
|
|
|
|
//string "appearance/"
|
|
apr = apr.substring(11);
|
|
LOG("magic_item","SHORT appearance = " + apr);
|
|
|
|
java.util.StringTokenizer st = new java.util.StringTokenizer(apr, "_");
|
|
int tokenCount = st.countTokens();
|
|
LOG("magic_item","token count = " + tokenCount);
|
|
if ( tokenCount < 2 )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
string tbl = "";
|
|
/*
|
|
if ( isGameObjectTypeOf(got, GOT_armor) )
|
|
{
|
|
string armr = st.nextToken();
|
|
string tblName = st.nextToken();
|
|
tbl = "datatables/magic_item/armor/" + tblName + ".iff";
|
|
}
|
|
else*/ if ( isGameObjectTypeOf(got, GOT_clothing) || got == GOT_misc_container_wearable )
|
|
{
|
|
string tblName = st.nextToken();
|
|
if ( tblName.equals("wke") )
|
|
{
|
|
tblName = st.nextToken();
|
|
}
|
|
|
|
tbl = "datatables/magic_item/wearable/" + tblName + ".iff";
|
|
}
|
|
else if (isGameObjectTypeOf (got, GOT_weapon))
|
|
{
|
|
// Weapons
|
|
int weapon_type = getWeaponType(item);
|
|
switch (weapon_type)
|
|
{
|
|
case 0:
|
|
// rifle
|
|
tbl = "datatables/magic_item/weapon/rifle.iff";
|
|
break;
|
|
case 1:
|
|
// carbine
|
|
tbl = "datatables/magic_item/weapon/carbine.iff";
|
|
break;
|
|
case 2:
|
|
// pistol
|
|
tbl = "datatables/magic_item/weapon/pistol.iff";
|
|
break;
|
|
case 3:
|
|
// heavy weapon
|
|
tbl = "datatables/magic_item/weapon/heavy_ranged.iff";
|
|
break;
|
|
|
|
case 4:
|
|
// 1-handed melee
|
|
tbl = "datatables/magic_item/weapon/1handed_melee.iff";
|
|
break;
|
|
case 5:
|
|
// 2-handed melee
|
|
tbl = "datatables/magic_item/weapon/2handed_melee.iff";
|
|
break;
|
|
case 6:
|
|
// unarmed weapon
|
|
tbl = "datatables/magic_item/weapon/unarmed_melee.iff";
|
|
break;
|
|
case 7:
|
|
// polearm
|
|
tbl = "datatables/magic_item/weapon/polearm_melee.iff";
|
|
break;
|
|
default:
|
|
LOG("magic_item","unsupported weapon type: " + weapon_type);
|
|
return false;
|
|
}
|
|
}
|
|
else if ( got >= GOT_armor && got <= GOT_armor_foot)
|
|
{
|
|
// Armor
|
|
tbl = "datatables/magic_item/armor/armor.iff";
|
|
}
|
|
else
|
|
{
|
|
LOG("magic_item","GOT not defined in magic_item.convertToMagicItem()!");
|
|
return false;
|
|
}
|
|
|
|
LOG("magic_item","tbl = " + tbl);
|
|
|
|
mods = getAppearanceMagicMods(tbl, apr);
|
|
if ( (mods == null) || (mods.length == 0) )
|
|
{
|
|
return false;
|
|
}
|
|
LOG("magic_item","retrieved appearance magic mods...");
|
|
|
|
int numMods = getNumMods(mobLevel);
|
|
LOG("magic_item","calculated num mods = " + numMods);
|
|
if ( numMods > mods.length )
|
|
{
|
|
LOG("magic_item","truncated num mods to " + mods.length);
|
|
numMods = mods.length;
|
|
}
|
|
|
|
float spent = 0;
|
|
resizeable int[] pts = new int[0];
|
|
if ( numMods == 1 )
|
|
{
|
|
pts = utils.addElement(pts, 100);
|
|
spent = 100;
|
|
LOG("magic_item","pts[0] = 100");
|
|
}
|
|
else
|
|
{
|
|
int shares = 0;
|
|
for ( int i = 0; i < numMods; i++ )
|
|
{
|
|
shares += (i+1);
|
|
}
|
|
|
|
LOG("magic_item","total calculated shared = " + shares);
|
|
|
|
for ( int i = 0; i < numMods; i++ )
|
|
{
|
|
LOG("magic_item","*** WEIGHTING: " + i + " ******");
|
|
float pivot = 100f-spent;
|
|
float cntLeft = (float)(numMods-i);
|
|
LOG("magic_item","pivot = " + pivot + " cntLeft = " + cntLeft);
|
|
|
|
int wt = (int)pivot;
|
|
if ( cntLeft > 1 )
|
|
{
|
|
float min = pivot/cntLeft;
|
|
float max = pivot*2f/3f;
|
|
LOG("magic_item","min = " + min + " max = " + max);
|
|
wt = rand((int)min, (int)max);
|
|
}
|
|
|
|
spent += wt;
|
|
|
|
LOG("magic_item","pts[" + i + "] = " + wt);
|
|
pts = utils.addElement(pts, wt);
|
|
}
|
|
}
|
|
|
|
if ( (pts != null) && (pts.length > 0) )
|
|
{
|
|
LOG("magic_item","pts.length = " + pts.length);
|
|
|
|
boolean litmus = true;
|
|
boolean appliedMod = false;
|
|
for ( int i = 0; i < pts.length; i++ )
|
|
{
|
|
LOG("magic_item","*** APPLYING: " + i + " ******");
|
|
LOG("magic_item","mods.length = " + mods.length);
|
|
int idx = rand(0, mods.length-1);
|
|
LOG("magic_item","idx = " + idx);
|
|
string myMod = mods[idx];
|
|
if ( (myMod != null) && (!myMod.equals("")) )
|
|
{
|
|
LOG("magic_item","attempting to apply mod: " + myMod);
|
|
boolean applyNegative = false;
|
|
|
|
if ( myMod.startsWith("-") )
|
|
{
|
|
myMod = myMod.substring(1);
|
|
applyNegative = true;
|
|
}
|
|
|
|
int tmp = pts[i];
|
|
int cost = getMagicModCost(myMod);
|
|
LOG("magic_item","mod cost = " + cost);
|
|
if ( cost > 0 )
|
|
{
|
|
LOG("magic_item","wt = " + tmp);
|
|
|
|
float perc = (float)(tmp)/100f;
|
|
LOG("magic_item","perc = " + perc);
|
|
|
|
int buyPts = (int)(perc * (float)total);
|
|
LOG("magic_item","buyPts = " + buyPts);
|
|
|
|
int modVal = buyPts/cost;
|
|
LOG("magic_item","resulting mod value = " + modVal);
|
|
|
|
int modValMax = dataTableGetInt(TBL_COST, myMod, COL_MAX);
|
|
if ( modVal > modValMax )
|
|
{
|
|
modVal = modValMax;
|
|
}
|
|
|
|
if ( modVal > 0 )
|
|
{
|
|
if ( applyNegative )
|
|
{
|
|
litmus &= setSkillModBonus(item, myMod, -modVal);
|
|
}
|
|
else
|
|
{
|
|
litmus &= setSkillModBonus(item, myMod, modVal);
|
|
}
|
|
|
|
appliedMod = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
mods = utils.removeElementAt(mods, idx);
|
|
if ( (mods == null) || (mods.length == 0) )
|
|
{
|
|
LOG("magic_item", "ran out of mods... breaking out...");
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( litmus && appliedMod )
|
|
{
|
|
setCondition(item, CONDITION_MAGIC_ITEM);
|
|
}
|
|
|
|
return litmus;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/************************************************************
|
|
* @brief algorithm for converting mob level in magic item pts
|
|
*
|
|
* @param int mobLevel
|
|
*
|
|
* @return int; -1 on error
|
|
************************************************************/
|
|
int getBuyPoints(int mobLevel)
|
|
{
|
|
if ( mobLevel < 1 )
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
int ret = (int)((float)mobLevel * rand(1f-PT_DELTA, 1f+PT_DELTA));
|
|
|
|
return ret;
|
|
}
|
|
|
|
/************************************************************
|
|
* @brief algorithm for determining number of mods to apply
|
|
*
|
|
* @param int mobLevel
|
|
*
|
|
* @return int; 1
|
|
************************************************************/
|
|
int getNumMods(int pivot)
|
|
{
|
|
if ( pivot < 20 )
|
|
return 1;
|
|
|
|
if ( pivot < 40 )
|
|
return rand(1,2);
|
|
|
|
if ( pivot < 60 )
|
|
return rand(1,3);
|
|
|
|
return rand(2,3);
|
|
}
|
|
|
|
/************************************************************
|
|
* @brief algorithm for determining number of mods to apply
|
|
*
|
|
* @param int mobLevel
|
|
*
|
|
* @return int; 1
|
|
************************************************************/
|
|
int getMagicModCost(string modName)
|
|
{
|
|
if ( (modName == null) || (modName.equals("")) )
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
int val = dataTableGetInt(TBL_COST, modName, "COST");
|
|
if ( val > 0 )
|
|
{
|
|
return val;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
/************************************************************
|
|
* @brief retrieves explicit mod list; otherwise attempts to return generic list
|
|
*
|
|
* @param string tbl //datatable
|
|
* @param string apr //appearance name
|
|
*
|
|
* @return string[]; null on error
|
|
************************************************************/
|
|
Vector getAppearanceMagicMods(string tbl, string apr)
|
|
{
|
|
if ( (tbl == null) || (tbl.equals("")) )
|
|
{
|
|
return null;
|
|
}
|
|
|
|
if ( (apr == null) || (apr.equals("")) )
|
|
{
|
|
return null;
|
|
}
|
|
|
|
string[] cols = dataTableGetColumnNames(tbl);
|
|
if ( (cols == null) || (cols.length == 0) )
|
|
{
|
|
return null;
|
|
}
|
|
|
|
string[] mods = new string[0];
|
|
for ( int i = 0; i < cols.length; i++ )
|
|
{
|
|
if ( apr.startsWith(cols[i]) )
|
|
{
|
|
mods = dataTableGetStringColumnNoDefaults(tbl, cols[i]);
|
|
}
|
|
}
|
|
|
|
if ( (mods == null) || (mods.length == 0) )
|
|
{
|
|
mods = dataTableGetStringColumnNoDefaults(tbl, "generic");
|
|
}
|
|
|
|
if ( (mods == null) || (mods.length == 0) )
|
|
{
|
|
return null;
|
|
}
|
|
|
|
return new Vector(Arrays.asList(mods));
|
|
}
|
|
|
|
/************************************************************
|
|
* @brief attempts to convert the target item to a magic item
|
|
*
|
|
* @param obj_id item
|
|
* @param int mobLevel
|
|
*
|
|
* @return boolean; false on error
|
|
************************************************************/
|
|
obj_id makeGem(obj_id targetContainer, string gemType, int mobLevel)
|
|
{
|
|
LOG("magic_item","**************** makeGem: " + getGameTime() + " **************");
|
|
if ( !isIdValid(targetContainer) )
|
|
return null;
|
|
|
|
obj_id item = createObject("object/tangible/gem/" + gemType + ".iff",targetContainer,"");
|
|
if ( !isIdValid(item) )
|
|
return null;
|
|
|
|
if ( mobLevel < 1 )
|
|
return null;
|
|
|
|
LOG("magic_item","params: item = " + item + " mobLevel = " + mobLevel);
|
|
|
|
int total = getBuyPoints(mobLevel);
|
|
if ( total < 1 )
|
|
return null;
|
|
|
|
LOG("magic_item","buy points = " + total);
|
|
|
|
string[] allmods = getGemMods(gemType);
|
|
|
|
if ( allmods == null || allmods.length == 0 )
|
|
return null;
|
|
|
|
Vector mods = new Vector(Arrays.asList(allmods));
|
|
if ( (mods == null) || (mods.size() == 0) )
|
|
return null;
|
|
|
|
LOG("magic_item","retrieved appearance magic mods...");
|
|
|
|
int numMods = getNumMods(mobLevel);
|
|
LOG("magic_item","calculated num mods = " + numMods);
|
|
if ( numMods > mods.size() )
|
|
{
|
|
LOG("magic_item","truncated num mods to " + mods.size());
|
|
numMods = mods.size();
|
|
}
|
|
|
|
float spent = 0;
|
|
resizeable int[] pts = new int[0];
|
|
if ( numMods == 1 )
|
|
{
|
|
pts = utils.addElement(pts, 100);
|
|
spent = 100;
|
|
LOG("magic_item","pts[0] = 100");
|
|
}
|
|
else
|
|
{
|
|
int shares = 0;
|
|
for ( int i = 0; i < numMods; i++ )
|
|
{
|
|
shares += (i+1);
|
|
}
|
|
|
|
LOG("magic_item","total calculated shared = " + shares);
|
|
|
|
for ( int i = 0; i < numMods; i++ )
|
|
{
|
|
LOG("magic_item","*** WEIGHTING: " + i + " ******");
|
|
float pivot = 100f-spent;
|
|
float cntLeft = (float)(numMods-i);
|
|
LOG("magic_item","pivot = " + pivot + " cntLeft = " + cntLeft);
|
|
|
|
int wt = (int)pivot;
|
|
if ( cntLeft > 1 )
|
|
{
|
|
float min = pivot/cntLeft;
|
|
float max = pivot*2f/3f;
|
|
LOG("magic_item","min = " + min + " max = " + max);
|
|
wt = rand((int)min, (int)max);
|
|
}
|
|
|
|
spent += wt;
|
|
|
|
LOG("magic_item","pts[" + i + "] = " + wt);
|
|
pts = utils.addElement(pts, wt);
|
|
}
|
|
}
|
|
|
|
if ( (pts != null) && (pts.length > 0) )
|
|
{
|
|
LOG("magic_item","pts.length = " + pts.length);
|
|
|
|
boolean litmus = true;
|
|
boolean appliedMod = false;
|
|
for ( int i = 0; i < pts.length; i++ )
|
|
{
|
|
LOG("magic_item","*** APPLYING: " + i + " ******");
|
|
LOG("magic_item","mods.length = " + mods.size());
|
|
int idx = rand(0, mods.size()-1);
|
|
LOG("magic_item","idx = " + idx);
|
|
string myMod = (String)mods.elementAt(idx);
|
|
if ( (myMod != null) && (!myMod.equals("")) )
|
|
{
|
|
LOG("magic_item","attempting to apply mod: " + myMod);
|
|
|
|
int tmp = pts[i];
|
|
int cost = getMagicModCost(myMod);
|
|
LOG("magic_item","mod cost = " + cost);
|
|
if ( cost > 0 )
|
|
{
|
|
LOG("magic_item","wt = " + tmp);
|
|
|
|
float perc = (float)(tmp)/100f;
|
|
LOG("magic_item","perc = " + perc);
|
|
|
|
int buyPts = (int)(perc * (float)total);
|
|
LOG("magic_item","buyPts = " + buyPts);
|
|
|
|
int modVal = buyPts/cost;
|
|
LOG("magic_item","resulting mod value = " + modVal);
|
|
|
|
int modValMax = dataTableGetInt(TBL_COST, myMod, COL_MAX);
|
|
if ( modVal > modValMax )
|
|
{
|
|
modVal = modValMax;
|
|
}
|
|
|
|
if ( modVal < 1 && i == 0 )
|
|
modVal = 1;
|
|
|
|
if ( modVal > 0 )
|
|
{
|
|
litmus &= setSkillModBonus(item, myMod, modVal);
|
|
appliedMod = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
mods.removeElementAt(idx);
|
|
if ( (mods == null) || (mods.size() == 0) )
|
|
{
|
|
LOG("magic_item", "ran out of mods... breaking out...");
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( litmus && appliedMod )
|
|
{
|
|
setCondition(item, CONDITION_MAGIC_ITEM);
|
|
}
|
|
|
|
return item;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
obj_id makeGem(obj_id targetContainer, int mobLevel)
|
|
{
|
|
return makeGem(targetContainer, "default", mobLevel);
|
|
}
|
|
|
|
string[] getGemMods(string gemType)
|
|
{
|
|
if ( gemType == null || gemType.equals("") )
|
|
return null;
|
|
|
|
string[] allMods = dataTableGetStringColumn(TBL_COST, "MOD");
|
|
if ( allMods == null || allMods.length == 0 )
|
|
return null;
|
|
|
|
if ( gemType.equals("clothing") || gemType.equals("default") )
|
|
{
|
|
return allMods;
|
|
}
|
|
else if ( gemType.equals("armor") )
|
|
{
|
|
resizeable string[] armorMods = new string[0];
|
|
for ( int i = 0; i < allMods.length; i++ )
|
|
{
|
|
if ( dataTableGetInt(TBL_COST, allMods[i], "ARMOR_ATTACHMENT_MODS") != 0 )
|
|
armorMods = utils.addElement(armorMods, allMods[i]);
|
|
}
|
|
|
|
if ( armorMods != null && armorMods.length > 0 )
|
|
return armorMods;
|
|
}
|
|
|
|
return null;
|
|
}
|