Files
dsrc/sku.0/sys.server/compiled/game/script/library/bio_engineer.scriptlib
T

2550 lines
101 KiB
Plaintext

//------------------------------------------------
// Includes
//------------------------------------------------
include java.lang.Math;
include ai.ai_combat;
include library.ai_lib;
include library.callable;
include library.corpse;
include library.create;
include library.skill;
include library.utils;
include library.xp;
include library.sui;
//------------------------------------------------
// Constants
//------------------------------------------------
const float DNA_HARVEST_CHECK_FRENZY = 0.3f;
const float DNA_HARVEST_CHECK_ATTACK = 0.7f;
const float CREATURE_MIN_TO_HIT_MOD = -0.25f;
const float CREATURE_MAX_TO_HIT_MOD = 0.25f;
const float CREATURE_MIN_WEAPON_SPEED_MOD = 0.25f;
const float CREATURE_MAX_WEAPON_SPEED_MOD = -0.25f;
const float CREATURE_MIN_DAMAGE_MOD = -0.25f;
const float CREATURE_MAX_DAMAGE_MOD = 0.25f;
const float CREATURE_MIN_HEALTH_REGEN = 0.75f;
const float CREATURE_MAX_HEALTH_REGEN = 1.25f;
const float CREATURE_MIN_FEROCITY_MOD = -0.25f;
const float CREATURE_MAX_FEROCITY_MOD = 0.25f;
const int HARVEST_TIME = 10;
const int DNA_V_LOW_QUALITY = 1;
const int DNA_LOW_QUALITY = 2;
const int DNA_B_AVG_QUALITY = 3;
const int DNA_AVG_QUALITY = 4;
const int DNA_A_AVG_QUALITY = 5;
const int DNA_HIGH_QUALITY = 6;
const int DNA_V_HIGH_QUALITY = 7;
const int DNA_V_LOW_QUALITY_THRESHOLD = 0;
const int DNA_LOW_QUALITY_THRESHOLD = 15;
const int DNA_B_AVG_QUALITY_THRESHOLD = 35;
const int DNA_AVG_QUALITY_THRESHOLD = 60;
const int DNA_A_AVG_QUALITY_THRESHOLD = 90;
const int DNA_HIGH_QUALITY_THRESHOLD = 115;
const int DNA_V_HIGH_QUALITY_THRESHOLD = 135;
const int BIO_COMP_EFFECT_FOOD = 0;
const int BIO_COMP_EFFECT_DURATION = 1;
const int BIO_COMP_EFFECT_FLAVOR = 2;
const int BIO_COMP_EFFECT_HEALTH_MOD = 3;
const int BIO_COMP_EFFECT_CON_MOD = 4;
const int BIO_COMP_EFFECT_ACTION_MOD = 5;
const int BIO_COMP_EFFECT_STAM_MOD = 6;
const int BIO_COMP_EFFECT_MIND_MOD = 7;
const int BIO_COMP_EFFECT_WILL_MOD = 8;
const int BIO_COMP_EFFECT_CLOTHING = 100;
const int BIO_COMP_EFFECT_HEALING_ABILITY = 101;
const int BIO_COMP_EFFECT_HEALING_INJURY_TREATMENT = 102;
const int BIO_COMP_EFFECT_HEALING_WOUND_TREATMENT = 103;
const int BIO_COMP_EFFECT_TAME_NON_AGGRO = 104;
const int BIO_COMP_EFFECT_TAME_AGGRO = 105;
const int BIO_COMP_EFFECT_CREATURE_TRAINING = 106;
const int BIO_COMP_EFFECT_CREATURE_EMPATHY = 107;
const int BIO_COMP_EFFECT_HEALING_MUSIC_WOUND = 108;
const int BIO_COMP_EFFECT_HEALING_DANCE_WOUND = 109;
const int BIO_COMP_EFFECT_BUSINESS_ACCUMEN = 110;
const int BIO_COMP_EFFECT_CAMOUFLAGE = 111;
const int BIO_COMP_EFFECT_COVER = 112;
const int BIO_COMP_EFFECT_TAKE_COVER = 113;
const int BIO_COMP_EFFECT_COMBAT_BLEEDING_DEFENSE = 114;
const int BIO_COMP_EFFECT_STUN_DEFENSE = 115;
const int BIO_COMP_EFFECT_MELEE_DEFENSE = 116;
const int BIO_COMP_EFFECT_INTIMIDATION = 117;
const int BIO_COMP_EFFECT_WARCRY = 118;
const int BIO_COMP_EFFECT_MASK_SCENT = 119;
const string[] DNA_COMP_QUALITY_ATTRIB = {
"very_high",
"high",
"above_average",
"average",
"below_average",
"low",
"very_low"
};
const string[] BIO_COMP_EFFECT_FOOD_MODS = {
"duration",
"flavor",
"health_mod",
"con_mod",
"action_mod",
"stam_mod",
"mind_mod",
"will_mod"
};
const string[] BIO_COMP_EFFECT_SKILL_MODS = {
"debuffing_efficiency", //unused
"augmentation_efficiency",
"cure_efficiency",
"tame_non_aggro",
"tame_aggro",
"creature_training", //unused
"creature_empathy", //unused
"healing_music_shock",
"healing_dance_shock",
"business_accumen", //unused
"camouflage",
"creature_harvesting",
"surveying",
"healing_efficiency",
"ranged_defense",
"melee_defense",
"slope_move",
"unarmed_damage",
"mask_scent"
};
const int[] CREATURE_SPECIAL_ATTACK_LIST = {
##"postureDownAttack",
##"knockdownAttack",
##"intimidationAttack",
##"blindAttack",
##"dizzyAttack",
##"stunAttack",
##"mildDisease",
##"mediumDisease",
##"strongDisease",
##"mildPoison",
##"mediumPoison",
##"strongPoison"
};
const string[] DNA_TEMPLATE_SLOT_NAMES = {
"aggression_profile",
"psychological_profile",
"mental_profile",
"prowess_profile",
"physique_profile"
};
const string CREATURE_DICT_NAME = "creatureName";
const string CREATURE_DICT_MIN_HEALTH = "minHealth";
const string CREATURE_DICT_MAX_HEALTH = "maxHealth";
const string CREATURE_DICT_MIN_CONSTITUTION = "minConstitution";
const string CREATURE_DICT_MAX_CONSTITUTION = "maxConstitution";
const string CREATURE_DICT_MIN_ACTION = "minAction";
const string CREATURE_DICT_MAX_ACTION = "maxAction";
const string CREATURE_DICT_MIN_STAMINA = "minStamina";
const string CREATURE_DICT_MAX_STAMINA = "maxStamina";
const string CREATURE_DICT_MIN_MIND = "minMind";
const string CREATURE_DICT_MAX_MIND = "maxMind";
const string CREATURE_DICT_MIN_WILLPOWER = "minWillpower";
const string CREATURE_DICT_MAX_WILLPOWER = "maxWillpower";
const string CREATURE_DICT_MIN_SCALE = "minScale";
const string CREATURE_DICT_MAX_SCALE = "maxScale";
const string CREATURE_DICT_CRAFTED_PET = "craftedPet";
const string CREATURE_DICT_MEAT = "meatType";
const string CREATURE_DICT_NICHE = "niche";
const string CREATURE_DICT_LEVEL = "level";
const string CREATURE_DICT_HEALTH_REGEN = "healthRegen";
const string CREATURE_DICT_TO_HIT = "toHit";
const string CREATURE_DICT_DEFENSE_VALUE = "defenseValue";
const string CREATURE_DICT_MIN_DAMAGE = "minDamage";
const string CREATURE_DICT_MAX_DAMAGE = "maxDamage";
const string CREATURE_DICT_STATE_RESIST = "stateResist";
const string CREATURE_DICT_ARMOR_BASE = "armorBase";
const string CREATURE_DICT_RANGED_WEAPON = "rangedWeapon";
const string CREATURE_DICT_SPECIAL_ATTACK_1 = "specialAttack1";
const string CREATURE_DICT_SPECIAL_ATTACK_2 = "specialAttack2";
const string PROFILE_DICT_MIN_HARDINESS = "minHardiness";
const string PROFILE_DICT_MAX_HARDINESS = "maxHardiness";
const string PROFILE_DICT_MIN_FORTITUDE = "minFortitude";
const string PROFILE_DICT_MAX_FORTITUDE = "maxFortitude";
const string PROFILE_DICT_MIN_DEXTERITY = "minDexterity";
const string PROFILE_DICT_MAX_DEXTERITY = "maxDexterity";
const string PROFILE_DICT_MIN_ENDURANCE = "minEndurance";
const string PROFILE_DICT_MAX_ENDURANCE = "maxEndurance";
const string PROFILE_DICT_MIN_INTELLECT = "minIntellect";
const string PROFILE_DICT_MAX_INTELLECT = "maxIntellect";
const string PROFILE_DICT_MIN_CLEVERNESS = "minCleverness";
const string PROFILE_DICT_MAX_CLEVERNESS = "maxCleverness";
const string PROFILE_DICT_MIN_DEPENDABILITY = "minDependability";
const string PROFILE_DICT_MAX_DEPENDABILITY = "maxDependability";
const string PROFILE_DICT_MIN_COURAGE = "minCourage";
const string PROFILE_DICT_MAX_COURAGE = "maxCourage";
const string PROFILE_DICT_MIN_FIERCENESS = "minFierceness";
const string PROFILE_DICT_MAX_FIERCENESS = "maxFierceness";
const string PROFILE_DICT_MIN_POWER = "minPower";
const string PROFILE_DICT_MAX_POWER = "maxPower";
const string OBJ_VAR_ATTRIB_PREFIX = "dna_attributes.";
const string ATTRIB_DICT_QUALITY = "quality";
const string ATTRIB_DICT_SOURCE = "source";
const string ATTRIB_DICT_HARDINESS = "hardiness";
const string ATTRIB_DICT_FORTITUDE = "fortitude";
const string ATTRIB_DICT_DEXTERITY = "dexterity";
const string ATTRIB_DICT_ENDURANCE = "endurance";
const string ATTRIB_DICT_INTELLECT = "intellect";
const string ATTRIB_DICT_CLEVERNESS = "cleverness";
const string ATTRIB_DICT_DEPENDABILITY = "dependability";
const string ATTRIB_DICT_COURAGE = "courage";
const string ATTRIB_DICT_FIERCENESS = "fierceness";
const string ATTRIB_DICT_POWER = "power";
const string ATTRIB_DICT_MEAT = "meatType";
const string ATTRIB_DICT_LEVEL = "level";
const string ATTRIB_DICT_HEALTH_REGEN = "healthRegen";
const string ATTRIB_DICT_TO_HIT = "toHit";
const string ATTRIB_DICT_MIN_DAMAGE = "minDamage";
const string ATTRIB_DICT_MAX_DAMAGE = "maxDamage";
const string ATTRIB_DICT_ARMOR_BASE = "armorBase";
const string ATTRIB_DICT_ARMOR_DATA = "armorData";
const string ATTRIB_DICT_RANGED_WEAPON = "rangedWeapon";
const string ATTRIB_DICT_SPECIAL_ATTACK_1 = "specialAttack1";
const string ATTRIB_DICT_SPECIAL_ATTACK_2 = "specialAttack2";
const int CREATURE_ATTRIB_HARDINESS = 0;
const int CREATURE_ATTRIB_FORTITUDE = 1;
const int CREATURE_ATTRIB_DEXTERITY = 2;
const int CREATURE_ATTRIB_ENDURANCE = 3;
const int CREATURE_ATTRIB_INTELLECT = 4;
const int CREATURE_ATTRIB_CLEVERNESS = 5;
const int CREATURE_ATTRIB_DEPENDABILITY = 6;
const int CREATURE_ATTRIB_COURAGE = 7;
const int CREATURE_ATTRIB_FIERCENESS = 8;
const int CREATURE_ATTRIB_POWER = 9;
const int CREATURE_ATTRIB_QUALITY = 10;
const int CREATURE_ATTRIB_NUM = 11;
const string[] CREATURE_ATTRIB_OBJVAR_NAMES = {
ATTRIB_DICT_HARDINESS,
ATTRIB_DICT_FORTITUDE,
ATTRIB_DICT_DEXTERITY,
ATTRIB_DICT_ENDURANCE,
ATTRIB_DICT_INTELLECT,
ATTRIB_DICT_CLEVERNESS,
ATTRIB_DICT_DEPENDABILITY,
ATTRIB_DICT_COURAGE,
ATTRIB_DICT_FIERCENESS,
ATTRIB_DICT_POWER,
ATTRIB_DICT_QUALITY
};
const int CREATURE_ATTRIB_WEIGHT_HEALTH = 0;
const int CREATURE_ATTRIB_WEIGHT_CONSTITUTION = 1;
const int CREATURE_ATTRIB_WEIGHT_DEFENSE = 2;
const int CREATURE_ATTRIB_WEIGHT_STAMINA = 3;
const int CREATURE_ATTRIB_WEIGHT_STATE_RESIST = 4;
const int CREATURE_ATTRIB_WEIGHT_WILLPOWER = 5;
const int CREATURE_ATTRIB_WEIGHT_HEALTH_REGEN = 6;
const int CREATURE_ATTRIB_WEIGHT_TO_HIT = 7;
const int CREATURE_ATTRIB_WEIGHT_SKITTISHNESS = 8;
const int CREATURE_ATTRIB_WEIGHT_SKITTISH_CURVE = 9;
const int CREATURE_ATTRIB_WEIGHT_SAVE = 10;
const int CREATURE_ATTRIB_WEIGHT_CRIT = 11;
const int CREATURE_ATTRIB_WEIGHT_AGGRO = 12;
const int CREATURE_ATTRIB_WEIGHT_DAMAGE = 13;
const int CREATURE_ATTRIB_WEIGHT_ARMOR = 14;
const int CREATURE_ATTRIB_WEIGHT_COUNT = 15;
const int [][] CREATURE_ATTRIB_WEIGHTS = { // Attrib_1, Wt, Attrib_2, Wt
{ CREATURE_ATTRIB_HARDINESS, 10, CREATURE_ATTRIB_DEXTERITY, 2 }, // HEALTH
{ CREATURE_ATTRIB_HARDINESS, 10, CREATURE_ATTRIB_FORTITUDE, 0 }, // CONSTITUTION
{ CREATURE_ATTRIB_DEXTERITY, 10, CREATURE_ATTRIB_INTELLECT, 2 }, // ACTION
{ CREATURE_ATTRIB_DEXTERITY, 10, CREATURE_ATTRIB_ENDURANCE, 0 }, // STAMINA
{ CREATURE_ATTRIB_INTELLECT, 10, CREATURE_ATTRIB_HARDINESS, 2 }, // MIND
{ CREATURE_ATTRIB_INTELLECT, 10, CREATURE_ATTRIB_CLEVERNESS, 0 }, // WILLPOWER
{ CREATURE_ATTRIB_ENDURANCE, 10, CREATURE_ATTRIB_DEPENDABILITY, 2 }, // HEALTH REGEN
{ CREATURE_ATTRIB_CLEVERNESS, 10, CREATURE_ATTRIB_INTELLECT, 0 }, // TO_HIT
{ CREATURE_ATTRIB_DEPENDABILITY, 10, CREATURE_ATTRIB_COURAGE, 0 }, // SKITTISHNESS
{ CREATURE_ATTRIB_DEPENDABILITY, 10, CREATURE_ATTRIB_COURAGE, 0 }, // SKITTISH_CURVE
{ CREATURE_ATTRIB_DEPENDABILITY, 10, CREATURE_ATTRIB_ENDURANCE, 0 }, // FLEE
{ CREATURE_ATTRIB_FIERCENESS, 10, CREATURE_ATTRIB_POWER, 0 }, // FEROCITY
{ CREATURE_ATTRIB_COURAGE, 10, CREATURE_ATTRIB_CLEVERNESS, 0 }, // ATTACK_SPEED
{ CREATURE_ATTRIB_POWER, 10, CREATURE_ATTRIB_COURAGE, 0 }, // DAMAGE
{ CREATURE_ATTRIB_FORTITUDE, 10, CREATURE_ATTRIB_ENDURANCE, 0 } // ARMOR
};
const string DNA_V_HIGH_QUALITY_OBJ_TEMPLATE = "object/tangible/component/dna/dna_sample_very_high.iff";
const string DNA_HIGH_QUALITY_OBJ_TEMPLATE = "object/tangible/component/dna/dna_sample_high.iff";
const string DNA_A_AVG_QUALITY_OBJ_TEMPLATE = "object/tangible/component/dna/dna_sample_above_average.iff";
const string DNA_AVG_QUALITY_OBJ_TEMPLATE = "object/tangible/component/dna/dna_sample_average.iff";
const string DNA_B_AVG_QUALITY_OBJ_TEMPLATE = "object/tangible/component/dna/dna_sample_below_average.iff";
const string DNA_LOW_QUALITY_OBJ_TEMPLATE = "object/tangible/component/dna/dna_sample_low.iff";
const string DNA_V_LOW_QUALITY_OBJ_TEMPLATE = "object/tangible/component/dna/dna_sample_very_low.iff";
const string DATATABLE_GENE_PROFILE_TABLE = "datatables/bio_engineer/gene_profiles.iff";
const string DATATABLE_COL_CREATURE_PROFILE = "geneProfile";
const string VAR_DNA_HARVEST_COUNT = "bioEngineer.dnaHarvestCount";
const string_id SID_HARVEST_DNA = new string_id("sui", "harvest_dna");
const string_id SID_HARVEST_DNA_SUCCEED = new string_id("error_message","harvest_dna_succeed");
const string_id PROSE_HARVEST_DNA_SUCCEED = new string_id("error_message","prose_harvest_dna_succeed");
const string_id SID_HARVEST_DNA_FAILED = new string_id("error_message","harvest_dna_failed");
const string_id PROSE_HARVEST_DNA_FAILED = new string_id("error_message","prose_harvest_dna_failed");
const string_id SID_HARVEST_ALREADY_HARVESTING = new string_id ("bio_engineer", "harvest_dna_already_harvesting");
const string_id SID_HARVEST_NEED_TARGET = new string_id ("bio_engineer", "harvest_dna_need_target");
const string_id SID_HARVEST_SKILL_TOO_LOW = new string_id ("bio_engineer", "harvest_dna_skill_too_low");
const string_id SID_HARVEST_CREATURE_IN_COMBAT = new string_id ("bio_engineer", "harvest_dna_creature_in_combat");
const string_id SID_HARVEST_FAILED = new string_id ("bio_engineer", "harvest_dna_failed");
const string_id SID_HARVEST_SUCCEED = new string_id ("bio_engineer", "harvest_dna_succeed");
const string_id SID_HARVEST_INVALID_TARGET = new string_id ("bio_engineer", "harvest_dna_invalid_target");
const string_id SID_HARVEST_TARGET_CORPSE = new string_id ("bio_engineer", "harvest_dna_target_corpse");
const string_id SID_HARVEST_TARGET_PET = new string_id ("bio_engineer", "harvest_dna_target_pet");
const string_id SID_HARVEST_TARGET_BABY = new string_id ("bio_engineer", "harvest_dna_target_baby");
const string_id SID_HARVEST_CANT_HARVEST = new string_id ("bio_engineer", "harvest_dna_cant_harvest");
const string_id SID_HARVEST_OUT_OF_RANGE = new string_id ("bio_engineer", "harvest_dna_out_of_range");
const string_id SID_HARVEST_ATTRIB_TOO_LOW = new string_id ("bio_engineer", "harvest_dna_attrib_too_low");
const string_id SID_HARVEST_BEGIN_HARVEST = new string_id ("bio_engineer", "harvest_dna_begin_harvest");
const string_id SID_NEW_LEVEL_TOO_HIGH = new string_id ("bio_engineer", "pet_sui_level_too_high");
const string_id SID_PET_SUI_TITLE = new string_id ("bio_engineer", "pet_sui_title");
const string_id SID_PET_SUI_TEXT = new string_id ("bio_engineer", "pet_sui_text");
const string_id SID_PET_SUI_FIX_LEVEL = new string_id ("bio_engineer", "pet_sui_fix_level");
const string_id SID_PET_SUI_FIX_STATS = new string_id ("bio_engineer", "pet_sui_fix_stats");
const string_id SID_PET_SUI_ABORT = new string_id ("bio_engineer", "pet_sui_abort");
const string_id SID_PET_SUI_LEVEL_FIXED = new string_id ("bio_engineer", "pet_sui_level_fixed");
const string_id SID_PET_SUI_STATS_FIXED = new string_id ("bio_engineer", "pet_sui_stats_fixed");
const string_id SID_PET_SUI_FIX_ERROR = new string_id ("bio_engineer", "pet_sui_fix_error");
const string COMPONENT_RESOURCE_ATTRIB_OBJVAR_NAME = "crafting_component_resource_attribs";
//------------------------------------------------
// Library Functions
//------------------------------------------------
boolean harvestCreatureDNA (obj_id player, obj_id creature)
{
deltadictionary dctScriptVars = player.getScriptVars();
if ( dctScriptVars == null )
return false;
// Double check the player has the needed skill
int skillMod = getSkillStatisticModifier (player, "dna_harvesting");
if (skillMod < 1)
{
//LOG ("dna_harvest", "FAILED: No dna_harvest skill");
sendSystemMessage (player, SID_HARVEST_SKILL_TOO_LOW);
return false;
}
// Can't harvest dna if we are already doing so.
int harvesting = dctScriptVars.getInt("bio_engineer.harvest_dna.harvesting");
if (harvesting == 1)
{
int harvestTime = dctScriptVars.getInt("bio_engineer.harvest_dna.harvest_time");
if ((getGameTime() - harvestTime) <= HARVEST_TIME)
{
sendSystemMessage(player, SID_HARVEST_ALREADY_HARVESTING );
return false;
}
}
// Check there's a valid target
if (!isIdValid (creature))
{
//LOG ("dna_harvest", "FAILED: Invalid target");
sendSystemMessage (player, SID_HARVEST_NEED_TARGET);
return false;
}
// Check if creature is someone's pet
if (pet_lib.hasMaster(creature))
{
//LOG ("dna_harvest", "FAILED: Can't sample from pets");
sendSystemMessage (player, SID_HARVEST_TARGET_PET);
return false;
}
// Check to see if the creature is a baby
if (hasScript(creature, "ai.pet_advance"))
{
//LOG ("dna_harvest", "FAILED: Target is a baby");
sendSystemMessage (player, SID_HARVEST_TARGET_BABY);
return false;
}
// Check if creature is dead
if (hasScript(creature, "corpse.ai_corpse"))
{
//LOG ("dna_harvest", "FAILED: Target is a corpse");
sendSystemMessage (player, SID_HARVEST_TARGET_CORPSE);
return false;
}
// Get the creature's geneProfile entry from creatures.tab
string mobType = ai_lib.getCreatureName(creature);
if (mobType == null || mobType.equals(""))
{
string err = "WARNING: bui_engineer::harvestCreatureDNA(" + creature + ") returning false because getCreatureName failed. Template=" + getTemplateName(creature) + ", IsAuthoritative=" + creature.isAuthoritative() + ". Stack Trace as follows:";
CustomerServiceLog("creatureNameErrors", err);
debugServerConsoleMsg(creature, err);
Thread.dumpStack();
sendSystemMessage (player, SID_HARVEST_INVALID_TARGET);
return false;
}
string creatureProfile = dataTableGetString(create.CREATURE_TABLE, mobType, DATATABLE_COL_CREATURE_PROFILE);
if (creatureProfile == null || creatureProfile.equals("") || creatureProfile.equals("none"))
{
//LOG ("dna_harvest", "FAILED: No geneProfile entry for creature.");
sendSystemMessage (player, SID_HARVEST_CANT_HARVEST);
return false;
}
// Read in the geneProfile from gene_profiles.tab
dictionary profileDict = dataTableGetRow(DATATABLE_GENE_PROFILE_TABLE, creatureProfile);
if (profileDict == null)
{
LOG ("dna_harvest", "ERROR: Invalid geneProfile, doesn't exist in gene_profile.tab");
sendSystemMessage (player, SID_HARVEST_INVALID_TARGET);
return false;
}
// Read in creature stats from creatures.tab
dictionary creatureDict = dataTableGetRow(create.CREATURE_TABLE, mobType);
if (creatureDict == null)
{
LOG ("dna_harvest", "ERROR: Unable to read creature entry in Creature Table.");
sendSystemMessage (player, SID_HARVEST_INVALID_TARGET);
return false;
}
// Check to see if the creature is in combat with someone else
if (ai_lib.isInCombat(creature))
{
//LOG ("dna_harvest", "FAILED: Creature in combat");
sendSystemMessage (player, SID_HARVEST_CREATURE_IN_COMBAT);
return false;
}
// assign attribute costs
int action = getAttrib(player, ACTION );
int mind = getAttrib(player, MIND );
int actioncost = 100;
int mindcost = 250;
if ( (action < actioncost) || (mind < mindcost) )
{
sendSystemMessage(player, SID_HARVEST_ATTRIB_TOO_LOW);
return false;
}
drainAttributes(player, actioncost, mindcost);
sendSystemMessage(player, SID_HARVEST_BEGIN_HARVEST);
// Get the harvesting location.
location loc = getLocation(player);
// Save the script vars
dctScriptVars.put("bio_engineer.harvest_dna.harvesting", 1);
dctScriptVars.put("bio_engineer.harvest_dna.harvest_time", getGameTime());
dctScriptVars.put("bio_engineer.harvest_dna.creature", creature);
dctScriptVars.put("bio_engineer.harvest_dna.loc", loc);
dctScriptVars.put("bio_engineer.harvest_dna.mobType", mobType);
dctScriptVars.put("bio_engineer.harvest_dna.creatureProfile", creatureProfile);
dctScriptVars.put("bio_engineer.harvest_dna.profileDict", profileDict);
dctScriptVars.put("bio_engineer.harvest_dna.creatureDict", creatureDict);
// Schedule completion message
int harvestTime = HARVEST_TIME;
if (hasObjVar(player, "quick_dna_sample"))
harvestTime = 1;
messageTo(player, "completeHarvestDNA", null, harvestTime, false );
if (!hasScript(creature, "ai.pet"))
setMaster( creature, player );//to make un-attackable
doAnimationAction (player, "heal_other");
return true;
}
boolean harvestCreatureDeedDNA (obj_id player, obj_id creatureDeed)
{
deltadictionary dctScriptVars = player.getScriptVars();
if ( dctScriptVars == null )
return false;
// Double check the player has the needed skill
int skillMod = getSkillStatisticModifier (player, "dna_harvesting");
if (skillMod < 1)
{
//LOG ("dna_harvest", "FAILED: No dna_harvest skill");
sendSystemMessage (player, SID_HARVEST_SKILL_TOO_LOW);
return false;
}
// Can't harvest dna if we are already doing so.
int harvesting = dctScriptVars.getInt("bio_engineer.harvest_dna.harvesting");
if (harvesting == 1)
{
int harvestTime = dctScriptVars.getInt("bio_engineer.harvest_dna.harvest_time");
if ((getGameTime() - harvestTime) <= HARVEST_TIME)
{
sendSystemMessage(player, SID_HARVEST_ALREADY_HARVESTING );
return false;
}
}
// Check there's a valid target
if (!isIdValid (creatureDeed))
{
//LOG ("dna_harvest", "FAILED: Invalid target");
sendSystemMessage (player, SID_HARVEST_NEED_TARGET);
return false;
}
// Get the creature's geneProfile entry from creatures.tab
string mobType = getStringObjVar(creatureDeed, "creature_attribs.type");
if (mobType == null || mobType.equals(""))
{
//LOG ("dna_harvest", "FAILED: Invalid target");
sendSystemMessage (player, SID_HARVEST_INVALID_TARGET);
return false;
}
string creatureProfile = dataTableGetString(create.CREATURE_TABLE, mobType, DATATABLE_COL_CREATURE_PROFILE);
if (creatureProfile == null || creatureProfile.equals("") || creatureProfile.equals("none"))
{
//LOG ("dna_harvest", "FAILED: No geneProfile entry for creature.");
sendSystemMessage (player, SID_HARVEST_CANT_HARVEST);
return false;
}
// Read in the geneProfile from gene_profiles.tab
dictionary profileDict = dataTableGetRow(DATATABLE_GENE_PROFILE_TABLE, creatureProfile);
if (profileDict == null)
{
LOG ("dna_harvest", "ERROR: Invalid geneProfile, doesn't exist in gene_profile.tab");
sendSystemMessage (player, SID_HARVEST_INVALID_TARGET);
return false;
}
// Read in creature stats from creatures.tab
dictionary creatureDict = dataTableGetRow(create.CREATURE_TABLE, mobType);
if (creatureDict == null)
{
LOG ("dna_harvest", "ERROR: Unable to read creature entry in Creature Table.");
sendSystemMessage (player, SID_HARVEST_INVALID_TARGET);
return false;
}
// assign attribute costs
int action = getAttrib(player, ACTION );
int mind = getAttrib(player, MIND );
int actioncost = 100;
int mindcost = 250;
if ( (action < actioncost) || (mind < mindcost) )
{
sendSystemMessage(player, SID_HARVEST_ATTRIB_TOO_LOW);
return false;
}
drainAttributes(player, actioncost, mindcost);
sendSystemMessage(player, SID_HARVEST_BEGIN_HARVEST);
// Get the harvesting location.
location loc = getLocation(player);
// Save the script vars
dctScriptVars.put("bio_engineer.harvest_dna.harvesting", 1);
dctScriptVars.put("bio_engineer.harvest_dna.harvest_time", getGameTime());
dctScriptVars.put("bio_engineer.harvest_dna.creatureDeed", creatureDeed);
dctScriptVars.put("bio_engineer.harvest_dna.loc", loc);
dctScriptVars.put("bio_engineer.harvest_dna.mobType", mobType);
dctScriptVars.put("bio_engineer.harvest_dna.creatureProfile", creatureProfile);
dctScriptVars.put("bio_engineer.harvest_dna.profileDict", profileDict);
dctScriptVars.put("bio_engineer.harvest_dna.creatureDict", creatureDict);
// Schedule completion message
int harvestTime = HARVEST_TIME;
if (hasObjVar(player, "quick_dna_sample"))
harvestTime = 1;
messageTo(player, "completeHarvestDNA", null, harvestTime, false );
return true;
}
boolean completeHarvest (obj_id player)
{
boolean failed = false;
boolean error = false;
boolean creatureSurvived = true;
int harvestCount = 0;
int survivalCheck = 0;
// Load up the script vars
deltadictionary dctScriptVars = player.getScriptVars();
if ( dctScriptVars == null )
return false;
obj_id creature = dctScriptVars.getObjId("bio_engineer.harvest_dna.creature");
obj_id creatureDeed = dctScriptVars.getObjId("bio_engineer.harvest_dna.creatureDeed");
location loc = dctScriptVars.getLocation("bio_engineer.harvest_dna.loc");
string mobType = dctScriptVars.getString("bio_engineer.harvest_dna.mobType");
string creatureProfile = dctScriptVars.getString("bio_engineer.harvest_dna.creatureProfile");
dictionary profileDict = dctScriptVars.getDictionary("bio_engineer.harvest_dna.profileDict");
dictionary creatureDict = dctScriptVars.getDictionary("bio_engineer.harvest_dna.creatureDict");
boolean deed = false;
if (!isIdValid(creature) || !exists(creature))
{
if (isIdValid(creatureDeed) && exists(creatureDeed))
{
creature = creatureDeed;
deed = true;
}
else
{
failed = true;
}
}
int targetDiff = 0;
if (deed)
{
targetDiff = getIntObjVar(creatureDeed, "creature_attribs.level");
}
else
{
targetDiff = getLevel(creature);
}
// Harvesting Logic
LOG ("dna_harvest", "************************* HARVESTING CREATURE DNA *************************");
// Check if creature is dead
if (!failed && hasScript(creature, "corpse.ai_corpse"))
{
//LOG ("dna_harvest", "FAILED: Target is a corpse");
sendSystemMessage (player, SID_HARVEST_TARGET_CORPSE);
failed = true;
}
// Check to see if the creature is in combat with someone else
if (!failed && ai_lib.isInCombat(creature))
{
//LOG ("dna_harvest", "FAILED: Creature in combat");
sendSystemMessage (player, SID_HARVEST_CREATURE_IN_COMBAT);
failed = true;
}
// Check the range to the creature
if (!failed && !deed && getDistance(player, creature) > 16)
{
//LOG ("dna_harvest", "FAILED: Target is too far away");
sendSystemMessage (player, SID_HARVEST_OUT_OF_RANGE);
failed = true;
}
if (!deed)
{
if(!isIdValid(creature))
return false;
if (!hasScript(creature, "ai.pet"))
setMaster(creature, null);
doAnimationAction (player, "heal_other");
}
// Skill check to see if player suceeded in harvesting DNA
float skillMod = getSkillStatisticModifier (player, "dna_harvesting");
float levelMod = targetDiff - (skillMod / 1.5f);
if (levelMod < 0) levelMod = 0;
float difficulty = ((skillMod / 1.5f) + 35) - (levelMod * (skillMod / 10));
if (difficulty > 85) difficulty = 85;
if (difficulty < 0) difficulty = 0;
int dieRoll = rand(1, 100);
if (dieRoll > difficulty || failed)
{
failed = true;
}
else
{
LOG ("dna_harvest", "Creature: " + mobType);
LOG ("dna_harvest", "geneProfile: " + creatureProfile);
// Calculate DNA stats from creatures stats, skill_mod and profile data
dictionary creatureStats = null;
if (deed)
creatureStats = getCreatureDeedStats(creature);
else
creatureStats = getCreatureStats(creature);
if (creatureStats == null)
{
LOG ("dna_harvest", "ERROR: Failed creation of DNA dictionary.");
error = true;
}
dictionary attributeDict = calculateDNAAttributes (player, creatureStats, profileDict, -1);
if (attributeDict == null)
{
LOG ("dna_harvest", "ERROR: Failed creation of DNA dictionary.");
error = true;
}
// Create new DNA object
obj_id inventory = utils.getInventoryContainer(player);
if (inventory == null || inventory == obj_id.NULL_ID)
{
LOG ("dna_harvest", "ERROR: Failed to find the player's inventory.");
error = true;
}
obj_id DNA_obj = createDNAComponent (player, inventory, attributeDict);
if (DNA_obj == null || DNA_obj == obj_id.NULL_ID)
{
LOG ("dna_harvest", "ERROR: Failed creation of DNA object.");
// Can't sample, inventory is full.
error = true;
}
if (!error)
{
// Track harvest count and check survivability
harvestCount = getIntObjVar (creature, VAR_DNA_HARVEST_COUNT);
if (harvestCount < 0) harvestCount = 0;
harvestCount++;
setObjVar (creature, VAR_DNA_HARVEST_COUNT, harvestCount);
survivalCheck = (int) ((skillMod - targetDiff) * ((100 - (harvestCount * 10)) / 100f) * 2);
if (survivalCheck < 0) survivalCheck = 0;
if (survivalCheck > 100) survivalCheck = 100;
dieRoll = rand (1, 100);
if (dieRoll > survivalCheck)
{
// Creature didn't survive the harvest proceedure
//LOG ("dna_harvest", "Creature killed during harvest.");
creatureSurvived = false;
if (deed)
{
destroyObject(creature);
}
else
{
if (pet_lib.hasMaster(creature))
{
setMaster(creature, null);
pet_lib.releasePet(creature);
}
attacker_results cbtAttackerResults = new attacker_results();
cbtAttackerResults.endPosture = POSTURE_DEAD;
cbtAttackerResults.id = creature;
doCombatResults("posture_scramble", cbtAttackerResults, null);
attachScript(creature, corpse.SCRIPT_AI_CORPSE);
//messageTo(creature, corpse.HANDLER_CORPSE_EXPIRE, null, corpse.AI_CORPSE_EXPIRATION_TIME, isObjectPersisted(creature));
}
}
}
}
if (creatureSurvived && !error)
{
// Creature's still alive, check to see reaction of creature(s)
float attackCheck = ((8 - (skillMod / 30f)) * (harvestCount - 1) / 4f);
attackCheck = 10 + (attackCheck * attackCheck);
if (attackCheck > 100) attackCheck = 100;
float frenzyCheck = ((8 - (skillMod / 15f)) * (harvestCount - 1));
frenzyCheck = 30 + (frenzyCheck * frenzyCheck);
if (frenzyCheck > 100) frenzyCheck = 100;
dieRoll = rand (1, 100);
if (dieRoll < attackCheck)
{
if (deed)
{
destroyObject(creature);
}
else
{
//LOG ("dna_harvest", "Creature attacked during harvest.");
if (pet_lib.hasMaster(creature))
{
setMaster(creature, null);
pet_lib.releasePet(creature);
}
startCombat(creature, player);
}
}
else if (dieRoll < frenzyCheck)
{
//LOG ("dna_harvest", "Creature spooked during harvest.");
if (!deed)
{
addToMentalStateToward(creature, player, FEAR, 45.0f);
}
}
//sendSystemMessageTestingOnly(player, "[/sampleDna] Survival = " + survivalCheck + "; Attack = " + attackCheck + "; Frenzy = " + frenzyCheck + "; DieRoll = " + dieRoll);
}
// Clear script vars
dctScriptVars.remove("bio_engineer.harvest_dna.harvesting");
dctScriptVars.remove("bio_engineer.harvest_dna.harvest_time");
dctScriptVars.remove("bio_engineer.harvest_dna.creature");
dctScriptVars.remove("bio_engineer.harvest_dna.creatureDeed");
dctScriptVars.remove("bio_engineer.harvest_dna.loc");
dctScriptVars.remove("bio_engineer.harvest_dna.mobType");
dctScriptVars.remove("bio_engineer.harvest_dna.creatureProfile");
dctScriptVars.remove("bio_engineer.harvest_dna.profileDict");
dctScriptVars.remove("bio_engineer.harvest_dna.creatureDict");
if (failed || error)
{
LOG ("dna_harvest", "FAILED: Failed skill check.");
sendSystemMessage (player, SID_HARVEST_FAILED);
return false;
}
else
{
sendSystemMessage (player, SID_HARVEST_SUCCEED);
// Award XP
int xpAmount = 0;
xpAmount = (int) (Math.pow(targetDiff, 1.2f) * 5f) + 50;
if (xpAmount > 2500 ) // Cap it.
xpAmount = 2500;
if (deed)
xpAmount = xpAmount / 4;
if (xpAmount > 0)
xp.grant(player, xp.BIO_ENGINEER_DNA_HARVESTING, xpAmount);
LOG ("dna_harvest", "SUCCESS: " + xpAmount + " XP awarded.");
}
return true;
}
boolean quickHarvest (obj_id player, string creatureName)
{
// Read crature entry from creatures.tab
dictionary creatureDict = dataTableGetRow(create.CREATURE_TABLE, creatureName);
if (creatureDict == null)
{
LOG ("dna_harvest", "ERROR: Unable to read creature entry in Creature Table.");
sendSystemMessage (player, SID_HARVEST_INVALID_TARGET);
return false;
}
// Get geneProfile
string creatureProfile = creatureDict.getString(DATATABLE_COL_CREATURE_PROFILE);
if (creatureProfile == null || creatureProfile.equals("") || creatureProfile.equals("none"))
{
//LOG ("dna_harvest", "FAILED: No geneProfile entry for creature.");
sendSystemMessage (player, SID_HARVEST_CANT_HARVEST);
return false;
}
// Read in the geneProfile from gene_profiles.tab
dictionary profileDict = dataTableGetRow(DATATABLE_GENE_PROFILE_TABLE, creatureProfile);
if (profileDict == null)
{
LOG ("dna_harvest", "ERROR: Invalid geneProfile, doesn't exist in gene_profile.tab");
sendSystemMessage (player, SID_HARVEST_INVALID_TARGET);
return false;
}
// Get level settings
int baseLevel = creatureDict.getInt("BaseLevel");
int dmgLevel = baseLevel + creatureDict.getInt("Damagelevelmodifier");
int statLevel = baseLevel + creatureDict.getInt("StatLevelModifier");
int toHitLevel = baseLevel + creatureDict.getInt("ToHitLevelModifier");
int armorLevel = baseLevel + creatureDict.getInt("ArmorLevelModifier");
// Cap levels
if (dmgLevel <= 0) dmgLevel = 1;
if (statLevel <= 0) statLevel = 1;
if (toHitLevel <= 0) toHitLevel = 1;
if (armorLevel <= 0) armorLevel = 1;
// Generate creatureStats
dictionary creatureStats = new dictionary();
int avgAttrib = dataTableGetInt(create.STAT_BALANCE_TABLE, statLevel - 1, "HP");
int minAttrib = minAttrib = (int)(avgAttrib * 0.9f);
int maxAttrib = maxAttrib = (int)(avgAttrib * 1.1f);
float minScale = creatureDict.getFloat( "minScale" );
float maxScale = creatureDict.getFloat( "maxScale" );
float dps = dataTableGetFloat(create.STAT_BALANCE_TABLE, dmgLevel -1 , "damagePerSecond");
int minDamage = Math.round((dps * 2.0f) * 0.5f);
int maxDamage = Math.round((dps * 2.0f) * 1.5f);
creatureStats.put(CREATURE_DICT_NAME, ("mob/creature_names:" + creatureName));
creatureStats.put(CREATURE_DICT_LEVEL, create.calcCreatureLevel(statLevel, dmgLevel, toHitLevel, armorLevel));
creatureStats.put(CREATURE_DICT_MAX_HEALTH, rand(minAttrib, maxAttrib));
creatureStats.put(CREATURE_DICT_HEALTH_REGEN, dataTableGetInt(create.STAT_BALANCE_TABLE, statLevel - 1, "HealthRegen"));
creatureStats.put(CREATURE_DICT_TO_HIT, dataTableGetInt(create.STAT_BALANCE_TABLE, toHitLevel - 1, "ToHit"));
creatureStats.put(CREATURE_DICT_DEFENSE_VALUE, dataTableGetInt(create.STAT_BALANCE_TABLE, toHitLevel - 1, "Def" ));
creatureStats.put(CREATURE_DICT_ARMOR_BASE, dataTableGetInt(create.STAT_BALANCE_TABLE, armorLevel - 1, "Armor"));
creatureStats.put(CREATURE_DICT_MIN_DAMAGE, minDamage);
creatureStats.put(CREATURE_DICT_MAX_DAMAGE, maxDamage);
creatureStats.put(CREATURE_DICT_RANGED_WEAPON, "");
//creatureStats.put(CREATURE_DICT_SPECIAL_ATTACK_1, 0);
//creatureStats.put(CREATURE_DICT_SPECIAL_ATTACK_2, 0);
creatureStats.put(CREATURE_DICT_MAX_SCALE, rand(minScale, maxScale));
creatureStats.put(CREATURE_DICT_NICHE, creatureDict.getInt("niche"));
creatureStats.put(CREATURE_DICT_MEAT, creatureDict.getString("meatType"));
// Calculate DNA attributes
dictionary attributeDict = calculateDNAAttributes (player, creatureStats, profileDict, -1);
if (attributeDict == null)
{
LOG ("dna_harvest", "ERROR: Failed creation of DNA dictionary.");
sendSystemMessage (player, SID_HARVEST_FAILED);
return false;
}
// Create new DNA object
obj_id inventory = utils.getInventoryContainer(player);
if (inventory == null || inventory == obj_id.NULL_ID)
{
LOG ("dna_harvest", "ERROR: Failed to find the player's inventory.");
sendSystemMessage (player, SID_HARVEST_FAILED);
return false;
}
obj_id DNA_obj = createDNAComponent (player, inventory, attributeDict);
if (DNA_obj == null || DNA_obj == obj_id.NULL_ID)
{
LOG ("dna_harvest", "ERROR: Failed creation of DNA object.");
sendSystemMessage (player, SID_HARVEST_FAILED);
return false;
}
sendSystemMessage (player, SID_HARVEST_SUCCEED);
return true;
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////
//// DNA Sampling Functions
////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
dictionary getCreatureStats(obj_id creature)
{
dictionary creatureStats = new dictionary();
string creatureName = getNameStringId(creature).toString();
char openParen = '(';
if ( creatureName.indexOf(openParen) != -1)
{
creatureName = creatureName.substring(0, (creatureName.indexOf(openParen) - 1));
}
creatureStats.put(CREATURE_DICT_NAME, creatureName);
creatureStats.put(CREATURE_DICT_MAX_HEALTH, getMaxHealth(creature));
creatureStats.put(CREATURE_DICT_HEALTH_REGEN, getMaxConst(creature));
creatureStats.put(CREATURE_DICT_LEVEL, getLevel(creature));
creatureStats.put(CREATURE_DICT_NICHE, dataTableGetInt(create.CREATURE_TABLE, creatureName, "niche"));
creatureStats.put(CREATURE_DICT_MEAT, dataTableGetString(create.CREATURE_TABLE, creatureName, "meatType"));
if(callable.hasCallableCD(creature))
{
creatureStats.put(CREATURE_DICT_CRAFTED_PET, 1);
obj_id pcd = callable.getCallableCD(creature);
creatureStats.put(CREATURE_DICT_TO_HIT, getIntObjVar(pcd, "creature_attribs.toHitChance"));
creatureStats.put(CREATURE_DICT_DEFENSE_VALUE, getIntObjVar(pcd, "creature_attribs.defenseValue"));
creatureStats.put(CREATURE_DICT_ARMOR_BASE, getIntObjVar(pcd, "creature_attribs.general_protection"));
creatureStats.put(CREATURE_DICT_MIN_DAMAGE, getIntObjVar(pcd, "creature_attribs." + ATTRIB_DICT_MIN_DAMAGE));
creatureStats.put(CREATURE_DICT_MAX_DAMAGE, getIntObjVar(pcd, "creature_attribs." + ATTRIB_DICT_MAX_DAMAGE));
creatureStats.put(CREATURE_DICT_RANGED_WEAPON, getStringObjVar(pcd, "creature_attribs." + ATTRIB_DICT_RANGED_WEAPON));
//creatureStats.put(CREATURE_DICT_SPECIAL_ATTACK_1, getIntObjVar(pcd, "creature_attribs." + ATTRIB_DICT_SPECIAL_ATTACK_1));
//creatureStats.put(CREATURE_DICT_SPECIAL_ATTACK_2, getIntObjVar(pcd, "creature_attribs." + ATTRIB_DICT_SPECIAL_ATTACK_2));
creatureStats.put(CREATURE_DICT_MAX_SCALE, getFloatObjVar(pcd, "creature_attribs.scale"));
}
else
{
obj_id primaryWeapon = aiGetPrimaryWeapon(creature);
creatureStats.put(CREATURE_DICT_TO_HIT, getSkillStatMod(creature, "toHitChance"));
creatureStats.put(CREATURE_DICT_DEFENSE_VALUE, getSkillStatMod(creature, "ranged_defense"));
creatureStats.put(CREATURE_DICT_ARMOR_BASE, (int)getFloatObjVar(creature, armor.OBJVAR_ARMOR_BASE + "." + armor.OBJVAR_GENERAL_PROTECTION));
creatureStats.put(CREATURE_DICT_MIN_DAMAGE, getWeaponMinDamage(primaryWeapon));
creatureStats.put(CREATURE_DICT_MAX_DAMAGE, getWeaponMaxDamage(primaryWeapon));
creatureStats.put(CREATURE_DICT_RANGED_WEAPON, "");
//creatureStats.put(CREATURE_DICT_SPECIAL_ATTACK_1, getIntObjVar(pcd, "creature_attribs." + ATTRIB_DICT_SPECIAL_ATTACK_1));
//creatureStats.put(CREATURE_DICT_SPECIAL_ATTACK_2, getIntObjVar(pcd, "creature_attribs." + ATTRIB_DICT_SPECIAL_ATTACK_2));
float baseScale = 1f;
if (utils.hasScriptVar(creature, "ai.baseScale"))
{
baseScale = utils.getFloatScriptVar(creature, "ai.baseScale");
}
creatureStats.put(CREATURE_DICT_MAX_SCALE, getScale(creature) / baseScale);
}
return creatureStats;
}
dictionary getCreatureDeedStats(obj_id creatureDeed)
{
dictionary creatureStats = new dictionary();
string creatureName = "mob/creature_names:" + getStringObjVar(creatureDeed, "creature_attribs.type");
creatureStats.put(CREATURE_DICT_CRAFTED_PET, 1);
creatureStats.put(CREATURE_DICT_NAME, creatureName);
creatureStats.put(CREATURE_DICT_MAX_HEALTH, getIntObjVar(creatureDeed, "creature_attribs.maxHealth" ));
creatureStats.put(CREATURE_DICT_HEALTH_REGEN, getIntObjVar(creatureDeed, "creature_attribs.maxConstitution" ));
creatureStats.put(CREATURE_DICT_LEVEL, getIntObjVar(creatureDeed, "creature_attribs." + ATTRIB_DICT_LEVEL));
creatureStats.put(CREATURE_DICT_TO_HIT, getIntObjVar(creatureDeed, "creature_attribs.toHitChance"));
creatureStats.put(CREATURE_DICT_DEFENSE_VALUE, getIntObjVar(creatureDeed, "creature_attribs.defenseValue"));
creatureStats.put(CREATURE_DICT_ARMOR_BASE, getIntObjVar(creatureDeed, "creature_attribs.general_protection"));
creatureStats.put(CREATURE_DICT_MIN_DAMAGE, getIntObjVar(creatureDeed, "creature_attribs." + ATTRIB_DICT_MIN_DAMAGE));
creatureStats.put(CREATURE_DICT_MAX_DAMAGE, getIntObjVar(creatureDeed, "creature_attribs." + ATTRIB_DICT_MAX_DAMAGE));
creatureStats.put(CREATURE_DICT_RANGED_WEAPON, getStringObjVar(creatureDeed, "creature_attribs." + ATTRIB_DICT_RANGED_WEAPON));
//creatureStats.put(CREATURE_DICT_SPECIAL_ATTACK_1, getIntObjVar(creatureDeed, "creature_attribs." + ATTRIB_DICT_SPECIAL_ATTACK_1));
//creatureStats.put(CREATURE_DICT_SPECIAL_ATTACK_2, getIntObjVar(creatureDeed, "creature_attribs." + ATTRIB_DICT_SPECIAL_ATTACK_2));
creatureStats.put(CREATURE_DICT_MAX_SCALE, getFloatObjVar(creatureDeed, "creature_attribs.scale"));
return creatureStats;
}
dictionary calculateDNAAttributes (obj_id player, dictionary creatureStats, dictionary profileDict, int qualityOverride)
{
// Collect information about the creature to be harvested
string creatureName = creatureStats.getString(CREATURE_DICT_NAME);
int level = creatureStats.getInt(CREATURE_DICT_LEVEL);
int health = creatureStats.getInt(CREATURE_DICT_MAX_HEALTH);
float healthRegen = creatureStats.getInt(CREATURE_DICT_HEALTH_REGEN);
int toHit = creatureStats.getInt(CREATURE_DICT_TO_HIT);
int defenseValue = creatureStats.getInt(CREATURE_DICT_DEFENSE_VALUE);
int minDamage = creatureStats.getInt(CREATURE_DICT_MIN_DAMAGE);
int maxDamage = creatureStats.getInt(CREATURE_DICT_MAX_DAMAGE);
int armorBase = creatureStats.getInt(CREATURE_DICT_ARMOR_BASE);
string rangedWeapon = creatureStats.getString(CREATURE_DICT_RANGED_WEAPON);
int specialAttack1 = 0; //= creatureStats.getInt(CREATURE_DICT_SPECIAL_ATTACK_1);
int specialAttack2 = 0; //= creatureStats.getInt(CREATURE_DICT_SPECIAL_ATTACK_2);
float maxScale = creatureStats.getFloat(CREATURE_DICT_MAX_SCALE);
int niche = creatureStats.getInt(CREATURE_DICT_NICHE);
string meat = creatureStats.getString(CREATURE_DICT_MEAT);
LOG ("creature_dna", "healthRegen = " + healthRegen);
LOG ("creature_dna", "toHit = " + toHit);
LOG ("creature_dna", "defenseValue = " + defenseValue);
LOG ("creature_dna", "minDamage = " + minDamage);
LOG ("creature_dna", "maxDamage = " + maxDamage);
LOG ("creature_dna", "armorBase = " + armorBase);
LOG ("creature_dna", "rangedWeapon = " + rangedWeapon);
//LOG ("creature_dna", "special1 = " + specialAttack1);
//LOG ("creature_dna", "special2 = " + specialAttack2);
if (rangedWeapon == null) rangedWeapon = "";
// Perform a skill check to see what quality of DNA was harvested
int skillMod = 0;
if (player != null) skillMod = getSkillStatisticModifier (player, "dna_harvesting");
int qualityRoll = rand (0, 50) + skillMod;
int qualityRank = 0;
if (qualityRoll > DNA_V_LOW_QUALITY_THRESHOLD) qualityRank = DNA_V_LOW_QUALITY;
if (qualityRoll > DNA_LOW_QUALITY_THRESHOLD) qualityRank = DNA_LOW_QUALITY;
if (qualityRoll > DNA_B_AVG_QUALITY_THRESHOLD) qualityRank = DNA_B_AVG_QUALITY;
if (qualityRoll > DNA_AVG_QUALITY_THRESHOLD) qualityRank = DNA_AVG_QUALITY;
if (qualityRoll > DNA_A_AVG_QUALITY_THRESHOLD) qualityRank = DNA_A_AVG_QUALITY;
if (qualityRoll > DNA_HIGH_QUALITY_THRESHOLD) qualityRank = DNA_HIGH_QUALITY;
if (qualityRoll > DNA_V_HIGH_QUALITY_THRESHOLD) qualityRank = DNA_V_HIGH_QUALITY;
if (qualityOverride >= 0) qualityRank = qualityOverride;
LOG ("dna_harvest", "DNA Harvesting: +" + skillMod);
LOG ("dna_harvest", "DNA Quality: " + qualityRank);
// int minQualityMod = (qualityRank - 5) * 5;
// int maxQualityMod = (qualityRank - 3) * 5;
int minQualityMod = (qualityRank - 6) * 5;
int maxQualityMod = (qualityRank - 4) * 5;
// Calculate the DNA Attributes
// Working values:
int Hardiness = calcDnaHardiness (health) + rand(minQualityMod, maxQualityMod);
int Fortitude = calcDnaFortitude (armorBase) + rand(minQualityMod, maxQualityMod);
int Cleverness = calcDnaCleverness (toHit) + rand(minQualityMod, maxQualityMod);
int Dexterity = calcDnaDexterity (defenseValue) + rand(minQualityMod, maxQualityMod);
int Power = calcDnaPower (((maxDamage + minDamage) / 2)) + rand(minQualityMod, maxQualityMod);
int Endurance = calcDnaEndurance (healthRegen) + rand(minQualityMod, maxQualityMod);
int Intellect = calcDnaIntellect (maxScale) + rand(minQualityMod, maxQualityMod);
int Fierceness = calcDnaFierceness (level,niche) + rand(minQualityMod, maxQualityMod);
int Dependability = calcDnaDependability (level,niche) + rand(minQualityMod, maxQualityMod);
int Courage = calcDnaCourage (level,meat) + rand(minQualityMod, maxQualityMod);
// Cap the DNA attributes
if (Hardiness < 0) Hardiness = 0;
if (Hardiness > 1000) Hardiness = 1000;
if (Fortitude < 0) Fortitude = 0;
if (Fortitude > 1000) Fortitude = 1000;
if (Dexterity < 0) Dexterity = 0;
if (Dexterity > 1000) Dexterity = 1000;
if (Endurance < 0) Endurance = 0;
if (Endurance > 1000) Endurance = 1000;
if (Intellect < 0) Intellect = 0;
if (Intellect > 1000) Intellect = 1000;
if (Cleverness < 0) Cleverness = 0;
if (Cleverness > 1000) Cleverness = 1000;
if (Dependability < 0) Dependability = 0;
if (Dependability > 1000) Dependability = 1000;
if (Courage < 0) Courage = 0;
if (Courage > 1000) Courage = 1000;
if (Fierceness < 0) Fierceness = 0;
if (Fierceness > 1000) Fierceness = 1000;
if (Power < 0) Power = 0;
if (Power > 1000) Power = 1000;
// Save the DNA attributes
dictionary attributeDict = new dictionary();
attributeDict.put(ATTRIB_DICT_QUALITY, qualityRank);
attributeDict.put(ATTRIB_DICT_SOURCE, creatureName);
attributeDict.put(ATTRIB_DICT_HARDINESS, Hardiness);
attributeDict.put(ATTRIB_DICT_FORTITUDE, Fortitude);
attributeDict.put(ATTRIB_DICT_DEXTERITY, Dexterity);
attributeDict.put(ATTRIB_DICT_ENDURANCE, Endurance);
attributeDict.put(ATTRIB_DICT_INTELLECT, Intellect);
attributeDict.put(ATTRIB_DICT_CLEVERNESS, Cleverness);
attributeDict.put(ATTRIB_DICT_DEPENDABILITY, Dependability);
attributeDict.put(ATTRIB_DICT_COURAGE, Courage);
attributeDict.put(ATTRIB_DICT_FIERCENESS, Fierceness);
attributeDict.put(ATTRIB_DICT_POWER, Power);
attributeDict.put(ATTRIB_DICT_RANGED_WEAPON, rangedWeapon);
//attributeDict.put(ATTRIB_DICT_SPECIAL_ATTACK_1, specialAttack1);
//attributeDict.put(ATTRIB_DICT_SPECIAL_ATTACK_2, specialAttack2);
return attributeDict;
}
int calcDnaHardiness(int health)
{
const int minHealth = 50;
const int maxHealth = 8000;
int hardiness = (int) (((float)(health - minHealth) / (float)(maxHealth - minHealth)) * 1000f);
//LOG ("dna_harvest", "Hardiness: " + hardiness + " [health = " + health + "(" + minHealth + "/" + maxHealth + ")]");
return hardiness;
}
int calcDnaFortitude(int armorBase)
{
const int minArmorBase = 0;
const int maxArmorBase = 6000;
int fortitude = (int) (((float)(armorBase - minArmorBase) / (float)(maxArmorBase - minArmorBase)) * 1000f);
return fortitude;
}
/*
int calcDnaDexterity(int action)
{
const int minAction = 50;
const int maxAction = 18000;
int dexterity = (int) (((float)(action - minAction) / (float)(maxAction - minAction)) * 1000f);
//LOG ("dna_harvest", "Dexterity: " + dexterity + " [action = " + action + "(" + minAction + "/" + maxAction + ")]");
return dexterity;
}
*/
int calcDnaDexterity(float defenseValue)
{
const int minDefense = 5;
const int maxDefense = 209;
int dexterity = (int) (((defenseValue - minDefense) / (maxDefense - minDefense)) * 1000f);
//LOG ("dna_harvest", "Dexterity: " + dexterity + " [fleeRate = " + fleeRate + "(" + minFleeRate + "/" + maxFleeRate + ")]");
return dexterity;
}
int calcDnaEndurance(float healthRegen)
{
/*
const float minMoveSpeed = 0.8f;
const float maxMoveSpeed = 1.2f;
const int minArmorModCount = 0;
const int maxArmorModCount = 5;
const int minArmorModValue = 0;
const int maxArmorModValue = 100;
int endurance = (int) (((moveSpeed - minMoveSpeed) / (maxMoveSpeed - minMoveSpeed)) * 1000f);
//LOG ("dna_harvest", "Endurance: " + endurance + " [moveSpeed = " + moveSpeed + "(" + minMoveSpeed + "/" + maxMoveSpeed + ")]");
return endurance;
*/
const float minHealthRegen = 12;
const float maxHealthRegen = 859;
int endurance = (int) (((healthRegen - minHealthRegen) / (maxHealthRegen - minHealthRegen)) * 1000f);
return endurance;
}
int calcDnaIntellect(float scale)
{
const float minScale = 0.5f;
const float maxScale = 5.0f;
if ( scale < minScale )
scale = minScale;
else if ( scale > maxScale )
scale = maxScale;
int intellect = (int) (((float)(scale - minScale) / (float)(maxScale - minScale)) * 1000f);
return intellect;
}
int calcDnaCleverness(float toHit)
{
const int minToHit = 5;
const int maxToHit = 209;
int cleverness = (int) (((toHit - minToHit) / (maxToHit - minToHit)) * 1000f);
//LOG ("dna_harvest", "Cleverness: " + cleverness + " [toHit = " + toHit + "(" + minToHit + "/" + maxToHit + ")]");
return cleverness;
}
int calcDnaDependability(int level,int niche)
{
const int minDepend = 1;
const int maxDepend = 100;
float flevel = (float) level;
if ( niche != 7 )
flevel /= 2;
if ( flevel > maxDepend )
flevel = maxDepend;
int dependability = (int) (((flevel - minDepend) / (maxDepend - minDepend)) * 1000f);
LOG ("dna_harvest", "Dependability: " + dependability + " [level = " + level + "(" + minDepend + "/" + maxDepend + ")]");
return dependability;
}
int calcDnaCourage(int level, string meat)
{
const int minLevel = 1;
const int maxLevel = 100;
float flevel = (float) level;
if ( meat == null || meat == "" )
flevel /= 5;
else if ( meat == "meat_wild" || meat == "meat_avian" )
flevel /= 4;
else if ( meat == "meat_herbivore" )
flevel /= 3;
else if ( meat == "meat_carnivore" || meat == "meat_reptilian" )
flevel /= 2;
// Insect meat gives max level in courage.
if ( flevel > maxLevel )
flevel = maxLevel;
int courage = (int) (((flevel - minLevel) / (maxLevel - minLevel)) * 1000f);
//LOG ("dna_harvest", "Courage: " + courage + " [attackSpeed = " + attackSpeed + "(" + minAttackSpeed + "/" + maxAttackSpeed + ")]");
return courage;
}
int calcDnaFierceness(int level,int niche)
{
const int minFerocity = 1;
const int maxFerocity = 100;
float flevel = (float) level;
if ( niche != 8 )
flevel /= 2;
if ( flevel > maxFerocity )
flevel = maxFerocity;
int fierceness = (int) (((float)(flevel - minFerocity) / (float)(maxFerocity - minFerocity)) * 1000f);
//LOG ("dna_harvest", "Fierceness: " + fierceness + " [ferocity = " + ferocity + "(" + minFerocity + "/" + maxFerocity + ")]");
return fierceness;
}
int calcDnaPower(int avgDamage)
{
const int minBaseDamage = 17;
const int maxBaseDamage = 431;
int power = (int) (((float)(avgDamage - minBaseDamage) / (float)(maxBaseDamage - minBaseDamage)) * 1000f);
//LOG ("dna_harvest", "Power: " + power + " [avgDamage = " + avgDamage + "(" + minBaseDamage + "/" + maxBaseDamage + ")]");
return power;
}
obj_id createDNAComponent (obj_id player, obj_id inventory, dictionary attributeDict)
{
obj_id DNA_obj = null;
// Create new object
switch (attributeDict.getInt(ATTRIB_DICT_QUALITY))
{
case DNA_V_LOW_QUALITY:
DNA_obj = createObject(DNA_V_LOW_QUALITY_OBJ_TEMPLATE, inventory, "");
break;
case DNA_LOW_QUALITY:
DNA_obj = createObject(DNA_LOW_QUALITY_OBJ_TEMPLATE, inventory, "");
break;
case DNA_B_AVG_QUALITY:
DNA_obj = createObject(DNA_B_AVG_QUALITY_OBJ_TEMPLATE, inventory, "");
break;
case DNA_AVG_QUALITY:
DNA_obj = createObject(DNA_AVG_QUALITY_OBJ_TEMPLATE, inventory, "");
break;
case DNA_A_AVG_QUALITY:
DNA_obj = createObject(DNA_A_AVG_QUALITY_OBJ_TEMPLATE, inventory, "");
break;
case DNA_HIGH_QUALITY:
DNA_obj = createObject(DNA_HIGH_QUALITY_OBJ_TEMPLATE, inventory, "");
break;
case DNA_V_HIGH_QUALITY:
DNA_obj = createObject(DNA_V_HIGH_QUALITY_OBJ_TEMPLATE, inventory, "");
break;
}
// Store attributes on object
if (DNA_obj != null)
{
setCraftedId(DNA_obj, DNA_obj);
//LOG ("dna_harvest", "-------- Creating new DNA Sample --------");
//LOG ("dna_harvest", " " + COMPONENT_RESOURCE_ATTRIB_OBJVAR_NAME + "." + ATTRIB_DICT_QUALITY +" = "+ attributeDict.getInt(ATTRIB_DICT_QUALITY));
setObjVar (DNA_obj, COMPONENT_RESOURCE_ATTRIB_OBJVAR_NAME + "." + ATTRIB_DICT_QUALITY, attributeDict.getInt(ATTRIB_DICT_QUALITY));
//LOG ("dna_harvest", " " + COMPONENT_RESOURCE_ATTRIB_OBJVAR_NAME + "." + ATTRIB_DICT_SOURCE +" = "+ attributeDict.getString(ATTRIB_DICT_SOURCE));
setObjVar (DNA_obj, COMPONENT_RESOURCE_ATTRIB_OBJVAR_NAME + "." + ATTRIB_DICT_SOURCE, attributeDict.getString(ATTRIB_DICT_SOURCE));
//LOG ("dna_harvest", " " + COMPONENT_RESOURCE_ATTRIB_OBJVAR_NAME + "." + ATTRIB_DICT_HARDINESS +" = "+ attributeDict.getInt(ATTRIB_DICT_HARDINESS));
setObjVar (DNA_obj, COMPONENT_RESOURCE_ATTRIB_OBJVAR_NAME + "." + ATTRIB_DICT_HARDINESS, attributeDict.getInt(ATTRIB_DICT_HARDINESS));
//LOG ("dna_harvest", " " + COMPONENT_RESOURCE_ATTRIB_OBJVAR_NAME + "." + ATTRIB_DICT_FORTITUDE +" = "+ attributeDict.getInt(ATTRIB_DICT_FORTITUDE));
setObjVar (DNA_obj, COMPONENT_RESOURCE_ATTRIB_OBJVAR_NAME + "." + ATTRIB_DICT_FORTITUDE, attributeDict.getInt(ATTRIB_DICT_FORTITUDE));
//LOG ("dna_harvest", " " + COMPONENT_RESOURCE_ATTRIB_OBJVAR_NAME + "." + ATTRIB_DICT_DEXTERITY +" = "+ attributeDict.getInt(ATTRIB_DICT_DEXTERITY));
setObjVar (DNA_obj, COMPONENT_RESOURCE_ATTRIB_OBJVAR_NAME + "." + ATTRIB_DICT_DEXTERITY, attributeDict.getInt(ATTRIB_DICT_DEXTERITY));
//LOG ("dna_harvest", " " + COMPONENT_RESOURCE_ATTRIB_OBJVAR_NAME + "." + ATTRIB_DICT_ENDURANCE +" = "+ attributeDict.getInt(ATTRIB_DICT_ENDURANCE));
setObjVar (DNA_obj, COMPONENT_RESOURCE_ATTRIB_OBJVAR_NAME + "." + ATTRIB_DICT_ENDURANCE, attributeDict.getInt(ATTRIB_DICT_ENDURANCE));
//LOG ("dna_harvest", " " + COMPONENT_RESOURCE_ATTRIB_OBJVAR_NAME + "." + ATTRIB_DICT_INTELLECT +" = "+ attributeDict.getInt(ATTRIB_DICT_INTELLECT));
setObjVar (DNA_obj, COMPONENT_RESOURCE_ATTRIB_OBJVAR_NAME + "." + ATTRIB_DICT_INTELLECT, attributeDict.getInt(ATTRIB_DICT_INTELLECT));
//LOG ("dna_harvest", " " + COMPONENT_RESOURCE_ATTRIB_OBJVAR_NAME + "." + ATTRIB_DICT_CLEVERNESS +" = "+ attributeDict.getInt(ATTRIB_DICT_CLEVERNESS));
setObjVar (DNA_obj, COMPONENT_RESOURCE_ATTRIB_OBJVAR_NAME + "." + ATTRIB_DICT_CLEVERNESS, attributeDict.getInt(ATTRIB_DICT_CLEVERNESS));
//LOG ("dna_harvest", " " + COMPONENT_RESOURCE_ATTRIB_OBJVAR_NAME + "." + ATTRIB_DICT_DEPENDABILITY +" = "+ attributeDict.getInt(ATTRIB_DICT_DEPENDABILITY));
setObjVar (DNA_obj, COMPONENT_RESOURCE_ATTRIB_OBJVAR_NAME + "." + ATTRIB_DICT_DEPENDABILITY, attributeDict.getInt(ATTRIB_DICT_DEPENDABILITY));
//LOG ("dna_harvest", " " + COMPONENT_RESOURCE_ATTRIB_OBJVAR_NAME + "." + ATTRIB_DICT_COURAGE +" = "+ attributeDict.getInt(ATTRIB_DICT_COURAGE));
setObjVar (DNA_obj, COMPONENT_RESOURCE_ATTRIB_OBJVAR_NAME + "." + ATTRIB_DICT_COURAGE, attributeDict.getInt(ATTRIB_DICT_COURAGE));
//LOG ("dna_harvest", " " + COMPONENT_RESOURCE_ATTRIB_OBJVAR_NAME + "." + ATTRIB_DICT_FIERCENESS +" = "+ attributeDict.getInt(ATTRIB_DICT_FIERCENESS));
setObjVar (DNA_obj, COMPONENT_RESOURCE_ATTRIB_OBJVAR_NAME + "." + ATTRIB_DICT_FIERCENESS, attributeDict.getInt(ATTRIB_DICT_FIERCENESS));
//LOG ("dna_harvest", " " + COMPONENT_RESOURCE_ATTRIB_OBJVAR_NAME + "." + ATTRIB_DICT_POWER +" = "+ attributeDict.getInt(ATTRIB_DICT_POWER));
setObjVar (DNA_obj, COMPONENT_RESOURCE_ATTRIB_OBJVAR_NAME + "." + ATTRIB_DICT_POWER, attributeDict.getInt(ATTRIB_DICT_POWER));
//LOG ("dna_harvest", " " + COMPONENT_RESOURCE_ATTRIB_OBJVAR_NAME + "." + ATTRIB_DICT_RANGED_WEAPON +" = "+ attributeDict.getString(ATTRIB_DICT_RANGED_WEAPON));
setObjVar (DNA_obj, COMPONENT_RESOURCE_ATTRIB_OBJVAR_NAME + "." + ATTRIB_DICT_RANGED_WEAPON, attributeDict.getString(ATTRIB_DICT_RANGED_WEAPON));
//LOG ("dna_harvest", " " + COMPONENT_RESOURCE_ATTRIB_OBJVAR_NAME + "." + ATTRIB_DICT_SPECIAL_ATTACK_1 +" = "+ attributeDict.getInt(ATTRIB_DICT_SPECIAL_ATTACK_1));
//setObjVar (DNA_obj, COMPONENT_RESOURCE_ATTRIB_OBJVAR_NAME + "." + ATTRIB_DICT_SPECIAL_ATTACK_1, attributeDict.getInt(ATTRIB_DICT_SPECIAL_ATTACK_1));
//LOG ("dna_harvest", " " + COMPONENT_RESOURCE_ATTRIB_OBJVAR_NAME + "." + ATTRIB_DICT_SPECIAL_ATTACK_2 +" = "+ attributeDict.getInt(ATTRIB_DICT_SPECIAL_ATTACK_2));
//setObjVar (DNA_obj, COMPONENT_RESOURCE_ATTRIB_OBJVAR_NAME + "." + ATTRIB_DICT_SPECIAL_ATTACK_2, attributeDict.getInt(ATTRIB_DICT_SPECIAL_ATTACK_2));
}
return DNA_obj;
}
int grantTemplateCraftingExperience(int level)
{
return level*10;
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////
//// Creature Crafting - Stat Calc Functions
////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
int calcCreatureAttrib(int attrib, int[] dnaAttributes)
{
// Read creature attrib range
const int minAttrib = 50;
const int maxAttrib = 8000;
int attribRange = maxAttrib - minAttrib;
// Calculate weighted dna values
float dnaAttrib = (((dnaAttributes[CREATURE_ATTRIB_WEIGHTS[attrib][0]] * CREATURE_ATTRIB_WEIGHTS[attrib][1]) +
(dnaAttributes[CREATURE_ATTRIB_WEIGHTS[attrib][2]] * CREATURE_ATTRIB_WEIGHTS[attrib][3])) /
(CREATURE_ATTRIB_WEIGHTS[attrib][1] + CREATURE_ATTRIB_WEIGHTS[attrib][3]));
// Calculate final attrib
int newAttrib = (int) ((attribRange * dnaAttrib) / 1000) + minAttrib;
LOG ("creature_crafting", "Attribute: " + create.MINATTRIBNAMES[attrib]);
LOG ("creature_crafting", " minVal: " + minAttrib);
LOG ("creature_crafting", " maxVal: " + maxAttrib);
LOG ("creature_crafting", " Range: " + attribRange);
LOG ("creature_crafting", " dnaVal: " + dnaAttrib);
LOG ("creature_crafting", " dnaCalc = (((" + dnaAttributes[CREATURE_ATTRIB_WEIGHTS[attrib][0]] + " * " +
CREATURE_ATTRIB_WEIGHTS[attrib][1] + ") + (" +
dnaAttributes[CREATURE_ATTRIB_WEIGHTS[attrib][2]] + " * " +
CREATURE_ATTRIB_WEIGHTS[attrib][3] + ")) / (" +
CREATURE_ATTRIB_WEIGHTS[attrib][1] + " + " +
CREATURE_ATTRIB_WEIGHTS[attrib][3] + "))");
LOG ("creature_crafting", " endVal: " + newAttrib);
return newAttrib;
}
int calcCreatureToHit(int[] dnaAttributes)
{
const int minToHit = 5;
const int maxToHit = 209;
float toHitChance = 0;
LOG ("creature_crafting", "Attribute: To Hit");
LOG ("creature_crafting", " minVal: " + minToHit);
LOG ("creature_crafting", " maxVal: " + maxToHit);
// Calculate weighted dna value
float dnaAttrib = (((dnaAttributes[CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_TO_HIT][0]] * CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_TO_HIT][1]) +
(dnaAttributes[CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_TO_HIT][2]] * CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_TO_HIT][3])) /
(CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_TO_HIT][1] + CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_TO_HIT][3]));
// Calculate final to hit
toHitChance = minToHit + (((maxToHit - minToHit) * dnaAttrib) / 1000);
LOG ("creature_crafting", " dnaToHit: " + dnaAttrib);
LOG ("creature_crafting", " dnaCalc = (((" + dnaAttributes[CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_TO_HIT][0]] + " * " +
CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_TO_HIT][1] + ") + (" +
dnaAttributes[CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_TO_HIT][2]] + " * " +
CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_TO_HIT][3] + ")) / (" +
CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_TO_HIT][1] + " + " +
CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_TO_HIT][3] + "))");
LOG ("creature_crafting", " endToHit: " + toHitChance);
return (int)toHitChance;
}
float calcCreatureCritChance(int[] dnaAttributes)
{
// const int minLevel = 5;
// const int maxToHit = 209;
float critChance = 0;
LOG ("creature_crafting", "Attribute: Crit Chance");
// LOG ("creature_crafting", " minVal: " + minToHit);
// LOG ("creature_crafting", " maxVal: " + maxToHit);
// Calculate weighted dna value
float dnaAttrib = (((dnaAttributes[CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_CRIT][0]] * CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_CRIT][1]) +
(dnaAttributes[CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_CRIT][2]] * CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_CRIT][3])) /
(CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_CRIT][1] + CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_CRIT][3]));
// Calculate final to hit
// toHitChance = minToHit + (((maxToHit - minToHit) * dnaAttrib) / 1000);
critChance = 0.08f * (dnaAttrib / 1000.f);
LOG ("creature_crafting", " dnaCrit: " + dnaAttrib);
LOG ("creature_crafting", " dnaCalc = (((" + dnaAttributes[CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_CRIT][0]] + " * " +
CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_CRIT][1] + ") + (" +
dnaAttributes[CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_CRIT][2]] + " * " +
CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_CRIT][3] + ")) / (" +
CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_CRIT][1] + " + " +
CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_CRIT][3] + "))");
LOG ("creature_crafting", " endCrit: " + critChance);
return critChance;
}
float calcCreatureCritSave(int[] dnaAttributes)
{
float critSave = 0;
LOG ("creature_crafting", "Attribute: Crit Save");
// Calculate weighted dna value
float dnaAttrib = (((dnaAttributes[CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_SAVE][0]] * CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_SAVE][1]) +
(dnaAttributes[CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_SAVE][2]] * CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_SAVE][3])) /
(CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_SAVE][1] + CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_SAVE][3]));
critSave = 0.08f * (dnaAttrib / 1000.f);
LOG ("creature_crafting", " dnaSave: " + dnaAttrib);
LOG ("creature_crafting", " dnaCalc = (((" + dnaAttributes[CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_SAVE][0]] + " * " +
CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_SAVE][1] + ") + (" +
dnaAttributes[CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_SAVE][2]] + " * " +
CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_SAVE][3] + ")) / (" +
CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_SAVE][1] + " + " +
CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_SAVE][3] + "))");
LOG ("creature_crafting", " endSave: " + critSave);
return critSave;
}
float calcCreatureAggroBonus(int[] dnaAttributes)
{
float aggroBonus = 0;
LOG ("creature_crafting", "Attribute: Aggro Bonus");
// Calculate weighted dna value
float dnaAttrib = (((dnaAttributes[CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_AGGRO][0]] * CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_AGGRO][1]) +
(dnaAttributes[CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_AGGRO][2]] * CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_AGGRO][3])) /
(CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_AGGRO][1] + CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_AGGRO][3]));
aggroBonus = 0.25f * (dnaAttrib / 1000.f);
LOG ("creature_crafting", " dnaAggro: " + dnaAttrib);
LOG ("creature_crafting", " dnaCalc = (((" + dnaAttributes[CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_AGGRO][0]] + " * " +
CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_AGGRO][1] + ") + (" +
dnaAttributes[CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_AGGRO][2]] + " * " +
CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_AGGRO][3] + ")) / (" +
CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_AGGRO][1] + " + " +
CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_AGGRO][3] + "))");
LOG ("creature_crafting", " endAggro: " + aggroBonus);
return aggroBonus;
}
float calcCreatureStateResist(int[] dnaAttributes)
{
float stateResist = 0;
LOG ("creature_crafting", "Attribute: State Resist");
// Calculate weighted dna value
float dnaAttrib = (((dnaAttributes[CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_STATE_RESIST][0]] * CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_STATE_RESIST][1]) +
(dnaAttributes[CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_STATE_RESIST][2]] * CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_STATE_RESIST][3])) /
(CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_STATE_RESIST][1] + CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_STATE_RESIST][3]));
// Calculate final state resist
stateResist = dnaAttrib / 1000;
LOG ("creature_crafting", " dnaStateResist: " + dnaAttrib);
LOG ("creature_crafting", " dnaCalc = (((" + dnaAttributes[CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_STATE_RESIST][0]] + " * " +
CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_STATE_RESIST][1] + ") + (" +
dnaAttributes[CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_STATE_RESIST][2]] + " * " +
CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_STATE_RESIST][3] + ")) / (" +
CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_STATE_RESIST][1] + " + " +
CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_STATE_RESIST][3] + "))");
LOG ("creature_crafting", " endStateResist: " + stateResist);
return stateResist;
}
float calcCreatureMaxScale(int[] dnaAttributes)
{
const float minScalef = 0.5f;
const float maxScalef = 5.0f;
// Pull from state resist.
float dnaAttrib = (((dnaAttributes[CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_STATE_RESIST][0]] * CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_STATE_RESIST][1]) +
(dnaAttributes[CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_STATE_RESIST][2]] * CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_STATE_RESIST][3])) /
(CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_STATE_RESIST][1] + CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_STATE_RESIST][3]));
float maxScale = minScalef + (((maxScalef - minScalef) * dnaAttrib) / 1000);
return maxScale;
}
int[] calcCreatureDamage(int[] dnaAttributes)
{
const int minBaseDamage = 17;
const int maxBaseDamage = 431;
int baseDamage = 0;
LOG ("creature_crafting", "Attribute: Damage");
LOG ("creature_crafting", " minBaseDamage: " + minBaseDamage);
LOG ("creature_crafting", " maxBaseDamage: " + maxBaseDamage);
// Calculate weighted dna value
float dnaAttrib = (((dnaAttributes[CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_DAMAGE][0]] * CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_DAMAGE][1]) +
(dnaAttributes[CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_DAMAGE][2]] * CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_DAMAGE][3])) /
(CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_DAMAGE][1] + CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_DAMAGE][3]));
baseDamage = (int) (minBaseDamage + (((maxBaseDamage - minBaseDamage) * dnaAttrib) / 1000));
/*
int[] minDamageList = dataTableGetIntColumn("datatables/mob/stat_balance.iff", "MinDmg");
int[] maxDamageList = dataTableGetIntColumn("datatables/mob/stat_balance.iff", "MaxDmg");
int idx = 0;
while (idx < minDamageList.length && baseDamage > ((minDamageList[idx] + maxDamageList[idx])/2))
{
idx++;
}
*/
// Calculate final damage range
int[] damage = new int[2];
damage[0] = minBaseDamage;
damage[1] = maxBaseDamage;
LOG ("creature_crafting", " dnaDamage: " + dnaAttrib);
LOG ("creature_crafting", " dnaCalc = (((" + dnaAttributes[CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_DAMAGE][0]] + " * " +
CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_DAMAGE][1] + ") + (" +
dnaAttributes[CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_DAMAGE][2]] + " * " +
CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_DAMAGE][3] + ")) / (" +
CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_DAMAGE][1] + " + " +
CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_DAMAGE][3] + "))");
LOG ("creature_crafting", " endBaseDmg: " + baseDamage);
LOG ("creature_crafting", " minDamage: " + damage[0]);
LOG ("creature_crafting", " maxDamage: " + damage[1]);
return damage;
}
int calcCreatureHealthRegen(int[] dnaAttributes)
{
const float minHealthRegen = 12f;
const float maxHealthRegen = 859f;
LOG ("creature_crafting", "Attribute: Health Regen");
LOG ("creature_crafting", " minVal: " + minHealthRegen);
LOG ("creature_crafting", " maxVal: " + maxHealthRegen);
// Calculate weighted dna value
float dnaAttrib = (((dnaAttributes[CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_HEALTH_REGEN][0]] * CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_HEALTH_REGEN][1]) +
(dnaAttributes[CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_HEALTH_REGEN][2]] * CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_HEALTH_REGEN][3])) /
(CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_HEALTH_REGEN][1] + CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_HEALTH_REGEN][3]));
// Calculate final attack speed
float healthRegen = minHealthRegen + (((maxHealthRegen - minHealthRegen) * dnaAttrib) / 1000);
LOG ("creature_crafting", " dnaHealthRegen: " + dnaAttrib);
LOG ("creature_crafting", " dnaCalc = (((" + dnaAttributes[CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_HEALTH_REGEN][0]] + " * " +
CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_HEALTH_REGEN][1] + ") + (" +
dnaAttributes[CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_HEALTH_REGEN][2]] + " * " +
CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_HEALTH_REGEN][3] + ")) / (" +
CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_HEALTH_REGEN][1] + " + " +
CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_HEALTH_REGEN][3] + "))");
LOG ("creature_crafting", " endHealthRegen: " + healthRegen);
return (int) healthRegen;
/*
const float minMoveSpeed = 0.8f;
const float maxMoveSpeed = 1.2f;
LOG ("creature_crafting", "Attribute: Move Speed");
LOG ("creature_crafting", " minVal: " + minMoveSpeed);
LOG ("creature_crafting", " maxVal: " + maxMoveSpeed);
// Calculate weighted dna value
float dnaAttrib = (((dnaAttributes[CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_MOVE_SPEED][0]] * CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_MOVE_SPEED][1]) +
(dnaAttributes[CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_MOVE_SPEED][2]] * CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_MOVE_SPEED][3])) /
(CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_MOVE_SPEED][1] + CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_MOVE_SPEED][3]));
// Calculate final attack speed
float moveSpeed = minMoveSpeed + (((maxMoveSpeed - minMoveSpeed) * dnaAttrib) / 1000);
LOG ("creature_crafting", " dnaMoveSpeed: " + dnaAttrib);
LOG ("creature_crafting", " dnaCalc = (((" + dnaAttributes[CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_MOVE_SPEED][0]] + " * " +
CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_MOVE_SPEED][1] + ") + (" +
dnaAttributes[CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_MOVE_SPEED][2]] + " * " +
CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_MOVE_SPEED][3] + ")) / (" +
CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_MOVE_SPEED][1] + " + " +
CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_MOVE_SPEED][3] + "))");
LOG ("creature_crafting", " endMoveSpeed: " + moveSpeed);
return moveSpeed;
*/
}
int calcCreatureDefenseValue(int[] dnaAttributes)
{
const int minDefense = 5;
const int maxDefense = 209;
float defenseValue = 0;
LOG ("creature_crafting", "Attribute: Defense Value");
LOG ("creature_crafting", " minVal: " + minDefense);
LOG ("creature_crafting", " maxVal: " + maxDefense);
// Calculate weighted dna value
float dnaAttrib = (((dnaAttributes[CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_DEFENSE][0]] * CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_DEFENSE][1]) +
(dnaAttributes[CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_DEFENSE][2]] * CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_DEFENSE][3])) /
(CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_DEFENSE][1] + CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_DEFENSE][3]));
// Calculate final defense value
defenseValue = minDefense + (((maxDefense - minDefense) * dnaAttrib) / 1000);
LOG ("creature_crafting", " dnaDefense: " + dnaAttrib);
LOG ("creature_crafting", " dnaCalc = (((" + dnaAttributes[CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_DEFENSE][0]] + " * " +
CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_DEFENSE][1] + ") + (" +
dnaAttributes[CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_DEFENSE][2]] + " * " +
CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_DEFENSE][3] + ")) / (" +
CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_DEFENSE][1] + " + " +
CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_DEFENSE][3] + "))");
LOG ("creature_crafting", " endDefenseValue: " + defenseValue);
return (int)defenseValue;
}
int calcCreatureArmor(int[] dnaAttributes)
{
const int minArmorBase = 0;
const int maxArmorBase = 6000;
int armorBase = 0;
LOG ("creature_crafting", "Attribute: Armor");
LOG ("creature_crafting", " minVal: " + minArmorBase);
LOG ("creature_crafting", " maxVal: " + maxArmorBase);
// Calculate weighted dna value
float dnaAttrib = (((dnaAttributes[CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_ARMOR][0]] * CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_ARMOR][1]) +
(dnaAttributes[CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_ARMOR][2]] * CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_ARMOR][3])) /
(CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_ARMOR][1] + CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_ARMOR][3]));
// Calculate final attack speed
armorBase = (int) (minArmorBase + (((maxArmorBase - minArmorBase) * dnaAttrib) / 1000));
LOG ("creature_crafting", " dnaArmor: " + dnaAttrib);
LOG ("creature_crafting", " dnaCalc = (((" + dnaAttributes[CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_ARMOR][0]] + " * " +
CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_ARMOR][1] + ") + (" +
dnaAttributes[CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_ARMOR][2]] + " * " +
CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_ARMOR][3] + ")) / (" +
CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_ARMOR][1] + " + " +
CREATURE_ATTRIB_WEIGHTS[CREATURE_ATTRIB_WEIGHT_ARMOR][3] + "))");
LOG ("creature_crafting", " endArmorBase: " + armorBase);
return armorBase;
}
int calcCreature(int[] dnaAttributes)
{
return 0;
}
// CREATURE_ATTRIB_WEIGHT_SKITTISHNESS
// CREATURE_ATTRIB_WEIGHT_SKITTISH_CURVE
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////
//// Creature Crafting - Level Calc Functions
////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
int getCraftedCreatureLevel(dictionary creatureDict)
{
int statLevel = calcCraftedStatLevel(creatureDict);
int dmgLevel = calcDmgLevel(creatureDict);
int regenLevel = calcRegenLevel(creatureDict);
int toHitLevel = calcToHitLevel(creatureDict);
// Adjust newly crafted pet base level to reduce the error margin on final level calcs
if (creatureDict.getInt("BaseLevel") == 0)
{
int tempLevel = (int) ((((statLevel*6) + (regenLevel*2) + (dmgLevel*10) + (toHitLevel*1)) / 19f) + 0.5f);
creatureDict.put("BaseLevel", tempLevel);
}
int armorLevel = calcArmorLevel(creatureDict);
int defenseLevel = calcDefenseLevel(creatureDict);
LOG ("creature_balance_calcs", "Level: " + (int) ((((statLevel*6) + (regenLevel*2) + (dmgLevel*10) + (toHitLevel*1) + (defenseLevel*1) + (armorLevel*2)) / 22f) + 0.5f) + " (" + statLevel + "/" + regenLevel + "/" + dmgLevel + "/" + toHitLevel + "/" + defenseLevel + "/" + armorLevel + ")");
return (int) ((((statLevel*6) + (regenLevel*2) + (dmgLevel*10) + (toHitLevel*1) + (defenseLevel*1) + (armorLevel*2)) / 22f) + 0.5f);
}
int getCreatureLevel(dictionary creatureDict)
{
int statLevel = calcStatLevel(creatureDict);
int dmgLevel = calcDmgLevel(creatureDict);
int regenLevel = calcRegenLevel(creatureDict);
int toHitLevel = calcToHitLevel(creatureDict);
int armorLevel = calcArmorLevel(creatureDict);
int defenseLevel = calcDefenseLevel(creatureDict);
LOG ("creature_balance_calcs", "Level: " + (int) ((((statLevel*6) + (regenLevel*2) + (dmgLevel*10) + (defenseLevel*1) + (toHitLevel*1) + (armorLevel*2)) / 22f) + 0.5f) + " (" + statLevel + "/" + regenLevel + "/" + dmgLevel + "/" + toHitLevel + "/" + defenseLevel + "/" + armorLevel + ")");
return (int) ((((statLevel*6) + (dmgLevel*10) + (regenLevel*2) + (toHitLevel*1) + (defenseLevel*1) + (armorLevel*2)) / 22f) + 0.5f);
}
int calcCraftedStatLevel(dictionary creatureDict)
{
int[] hitpoints = dataTableGetIntColumn("datatables/mob/stat_balance.iff", "HP");
int health = creatureDict.getInt("maxHealth");
// int action = creatureDict.getInt("maxAction");
// int mind = creatureDict.getInt("maxMind");
// int avgStat = health;
int level = 0;
while (level < hitpoints.length && health > hitpoints[level])
{
level++;
}
LOG ("creature_balance_calcs", "StatLevel = " + (level+1) + ": Health - (" + health + ")" );
return (level + 1);
}
int calcStatLevel(dictionary creatureDict)
{
int[] hitpoints = dataTableGetIntColumn("datatables/mob/stat_balance.iff", "HP");
int minHealth = creatureDict.getInt("minHealth");
int maxHealth = creatureDict.getInt("maxHealth");
// int minAction = creatureDict.getInt("minAction");
// int maxAction = creatureDict.getInt("maxAction");
// int minMind = creatureDict.getInt("minMind");
// int maxMind = creatureDict.getInt("maxMind");
// int avgStat = (minHealth + maxHealth + minAction + maxAction + minMind + maxMind) / 6;
int avgStat = (minHealth + maxHealth) / 2;
int level = 0;
while (level < hitpoints.length && avgStat > hitpoints[level])
{
level++;
}
LOG ("creature_balance_calcs", "StatLevel = " + (level+1) + ": Health - (" + minHealth + "-" + maxHealth + ")");
return (level + 1);
}
int calcDmgLevel(dictionary creatureDict)
{/*
int[] minDamageList = dataTableGetIntColumn("datatables/mob/stat_balance.iff", "MinDmg");
int[] maxDamageList = dataTableGetIntColumn("datatables/mob/stat_balance.iff", "MaxDmg");
int minDmg = creatureDict.getInt("minDamage");
int maxDmg = creatureDict.getInt("maxDamage");
int dmgSum = minDmg + maxDmg;
int level = 0;
while (level < minDamageList.length && dmgSum > minDamageList[level] + maxDamageList[level])
{
level++;
}
LOG ("creature_balance_calcs", "DmgLevel = " + (level+1) + ": Damage - (" + minDmg + "-" + maxDmg + "), Average - (" + dmgSum/2 + ")");
*/
return 1;
}
int calcRegenLevel(dictionary creatureDict)
{
int[] regenList = dataTableGetIntColumn("datatables/mob/stat_balance.iff", "HealthRegen");
int healthRegen = creatureDict.getInt("healthRegen");
int baseLevel = creatureDict.getInt("BaseLevel");
int level = 0;
while (level < regenList.length && healthRegen > regenList[level])
{
level++;
}
level += 1;
LOG ("creature_balance_calcs", "RegenLevel = " + level + ": healthRegen - (" + healthRegen + ")");
return level;
}
int calcToHitLevel(dictionary creatureDict)
{
int[] toHitList = dataTableGetIntColumn("datatables/mob/stat_balance.iff", "ToHit");
int toHit = creatureDict.getInt("toHitChance");
int baseLevel = creatureDict.getInt("BaseLevel");
int level = 0;
while (level < toHitList.length && toHit > toHitList[level])
{
level++;
}
level += 1;
/* if (level < baseLevel)
{
int levelRange = level;
while (levelRange < toHitList.length && toHitList[levelRange] == toHitList[level])
{
levelRange++;
}
levelRange += 1;
if (levelRange < baseLevel)
level = levelRange;
else
level = baseLevel;
}*/
LOG ("creature_balance_calcs", "ToHitLevel = " + level + ": ToHit - (" + toHit + ")");
return level;
}
int calcOldToHitLevel(dictionary creatureDict)
{
int[] toHitList = dataTableGetIntColumn("datatables/mob/stat_balance.iff", "ToHit");
int toHit = creatureDict.getInt("toHitChanceOld");
int baseLevel = creatureDict.getInt("BaseLevel");
int level = 0;
while (level < toHitList.length && toHit > toHitList[level])
{
level++;
}
level += 1;
if (level < baseLevel)
{
int levelRange = level;
while (levelRange < toHitList.length && toHitList[levelRange] == toHitList[level])
{
levelRange++;
}
levelRange += 1;
if (levelRange < baseLevel)
level = levelRange;
else
level = baseLevel;
}
LOG ("creature_balance_calcs", "ToHitLevel = " + level + ": ToHit - (" + toHit + ")");
return level;
}
int calcDefenseLevel(dictionary creatureDict)
{
int[] defenseList = dataTableGetIntColumn("datatables/mob/stat_balance.iff", "Def");
int defenseValue = creatureDict.getInt("defenseValue");
int baseLevel = creatureDict.getInt("BaseLevel");
int level = 0;
while (level < defenseList.length && defenseValue > defenseList[level])
{
level++;
}
level += 1;
/* if (level < baseLevel)
{
int levelRange = level;
while (levelRange < toHitList.length && toHitList[levelRange] == toHitList[level])
{
levelRange++;
}
levelRange += 1;
if (levelRange < baseLevel)
level = levelRange;
else
level = baseLevel;
}*/
LOG ("creature_balance_calcs", "DefenseLevel = " + level + ": defenseValue - (" + defenseValue + ")");
return level;
}
int calcAttackSpeedLevel(dictionary creatureDict)
{
return 0;
}
int calcArmorLevel(dictionary creatureDict)
{
int[] baseEffectiveness = dataTableGetIntColumn("datatables/mob/stat_balance.iff", "Armor");
int baseLevel = creatureDict.getInt("BaseLevel");
int armorEffectiveness = creatureDict.getInt("armorEffectiveness");
int level = 0;
while ( level < baseEffectiveness.length && armorEffectiveness > baseEffectiveness[level] )
{
level++;
}
level += 1;
if (level < baseLevel)
{
int levelRange = level;
while ( levelRange < baseEffectiveness.length && baseEffectiveness[levelRange] == baseEffectiveness[level] )
{
levelRange++;
}
levelRange += 1;
if (levelRange < baseLevel)
level = levelRange;
else
level = baseLevel;
}
return level;
}
int calcOldArmorLevel(dictionary creatureDict)
{
int[] baseRating = dataTableGetIntColumn("datatables/mob/stat_balance.iff", "BaseArmor"); //This is no good, but I'm told it won't be called anymore, and I don't know what to change it to anyhow
int[] baseEffectiveness = dataTableGetIntColumn("datatables/mob/stat_balance.iff", "Armor");
int baseLevel = creatureDict.getInt("BaseLevel");
int armorRating = creatureDict.getInt("armorRatingOld");
int armorEffectiveness = creatureDict.getInt("armorEffectivenessOld");
int armorKinetic = creatureDict.getInt("armorKineticOld");
int armorEnergy = creatureDict.getInt("armorEnergyOld");
int armorBlast = creatureDict.getInt("armorBlastOld");
int armorHeat = creatureDict.getInt("armorHeatOld");
int armorCold = creatureDict.getInt("armorColdOld");
int armorElectric = creatureDict.getInt("armorElectricOld");
int armorAcid = creatureDict.getInt("armorAcidOld");
int armorStun = creatureDict.getInt("armorStunOld");
int level = 0;
float resistanceLevel = 0;
while (level < baseRating.length && armorRating >= baseRating[level] && (armorRating > baseRating[level] || armorEffectiveness > baseEffectiveness[level]))
{
level++;
}
level += 1;
if (level < baseLevel)
{
int levelRange = level;
while (levelRange < baseRating.length && baseRating[levelRange] == baseRating[level] && baseEffectiveness[levelRange] == baseEffectiveness[level])
{
levelRange++;
}
levelRange += 1;
if (levelRange < baseLevel)
level = levelRange;
else
level = baseLevel;
}
if (armorKinetic > 0)
resistanceLevel += Math.max((armorKinetic - ((armorRating * 25) + (armorEffectiveness / (armorRating + 1)))), 0) * 3;
else
resistanceLevel += armorKinetic * (((armorRating * 25) + (armorEffectiveness / (armorRating + 1))) * 6);
if (armorEnergy > 0)
resistanceLevel += Math.max((armorEnergy - ((armorRating * 25) + (armorEffectiveness / (armorRating + 1)))), 0) * 3;
else
resistanceLevel += armorEnergy * (((armorRating * 25) + (armorEffectiveness / (armorRating + 1))) * 6);
if (armorBlast > 0)
resistanceLevel += Math.max((armorBlast - ((armorRating * 25) + (armorEffectiveness / (armorRating + 1)))), 0) / 2f;
else
resistanceLevel += armorBlast * ((armorRating * 25) + (armorEffectiveness / (armorRating + 1)));
if (armorHeat > 0)
resistanceLevel += Math.max((armorHeat - ((armorRating * 25) + (armorEffectiveness / (armorRating + 1)))), 0) / 2f;
else
resistanceLevel += armorHeat * ((armorRating * 25) + (armorEffectiveness / (armorRating + 1)));
if (armorCold > 0)
resistanceLevel += Math.max((armorCold - ((armorRating * 25) + (armorEffectiveness / (armorRating + 1)))), 0) / 2f;
else
resistanceLevel += armorCold * ((armorRating * 25) + (armorEffectiveness / (armorRating + 1)));
if (armorElectric > 0)
resistanceLevel += Math.max((armorElectric - ((armorRating * 25) + (armorEffectiveness / (armorRating + 1)))), 0) / 2f;
else
resistanceLevel += armorElectric * ((armorRating * 25) + (armorEffectiveness / (armorRating + 1)));
if (armorAcid > 0)
resistanceLevel += Math.max((armorAcid - ((armorRating * 25) + (armorEffectiveness / (armorRating + 1)))), 0) / 2f;
else
resistanceLevel += armorAcid * ((armorRating * 25) + (armorEffectiveness / (armorRating + 1)));
if (armorStun > 0)
resistanceLevel += Math.max((armorStun - ((armorRating * 25) + (armorEffectiveness / (armorRating + 1)))), 0) / 2f;
else
resistanceLevel += armorStun * ((armorRating * 25) + (armorEffectiveness / (armorRating + 1)));
level += (int) (resistanceLevel / 10f);
LOG ("creature_balance_calcs", "ArmorLevel = " + level + ": Rating - (" + armorRating + "); Effect - (" + armorEffectiveness + "); Resistances - ("+armorKinetic+", "+armorEnergy+", "+armorBlast+", "+armorHeat+", "+armorCold+", "+armorElectric+", "+armorAcid+", "+armorStun+")");
return level;
}
int calcSpecialAttackLevel(dictionary creatureDict)
{
return 0;
}
int calcRangedAttackLevel(dictionary creatureDict)
{
return 0;
}
int getCalcLevelFromPcd(obj_id pcd)
{
dictionary creatureDict = new dictionary();
creatureDict.put("BaseLevel", getIntObjVar(pcd, "creature_attribs.level" ));
creatureDict.put(CREATURE_DICT_MAX_HEALTH, getIntObjVar(pcd, "creature_attribs.maxHealth" ));
creatureDict.put(CREATURE_DICT_HEALTH_REGEN, getIntObjVar(pcd, "creature_attribs.maxConstitution" ));
creatureDict.put(CREATURE_DICT_TO_HIT, getIntObjVar(pcd, "creature_attribs.toHitChance"));
creatureDict.put(CREATURE_DICT_DEFENSE_VALUE, getIntObjVar(pcd, "creature_attribs.defenseValue"));
creatureDict.put(CREATURE_DICT_ARMOR_BASE, getIntObjVar(pcd, "creature_attribs.general_protection"));
creatureDict.put(CREATURE_DICT_MIN_DAMAGE, getIntObjVar(pcd, "creature_attribs." + ATTRIB_DICT_MIN_DAMAGE));
creatureDict.put(CREATURE_DICT_MAX_DAMAGE, getIntObjVar(pcd, "creature_attribs." + ATTRIB_DICT_MAX_DAMAGE));
creatureDict.put(CREATURE_DICT_MAX_SCALE, getFloatObjVar(pcd, "creature_attribs.scale"));
// Calculate level
int calcLevel = getCraftedCreatureLevel(creatureDict);
return calcLevel;
}
void stripOldStats( obj_id pcd )
{
if ( hasObjVar( pcd, "creature_attribs.armorData" ) )
removeObjVar( pcd, "creature_attribs.armorData" );
if ( hasObjVar( pcd, "creature_attribs.armorBase" ) )
removeObjVar( pcd, "creature_attribs.armorBase" );
if ( hasObjVar( pcd, "creature_attribs.armorBase" ) )
removeObjVar( pcd, "creature_attribs.armorBase" );
if ( hasObjVar( pcd, "creature_attribs." + create.MAXATTRIBNAMES[ACTION] ) )
removeObjVar(pcd, "creature_attribs." + create.MAXATTRIBNAMES[ACTION] );
if ( hasObjVar( pcd, "creature_attribs." + create.MAXATTRIBNAMES[MIND] ) )
removeObjVar(pcd, "creature_attribs." + create.MAXATTRIBNAMES[MIND] );
}
boolean validatePcdLevel(obj_id pcd, obj_id player)
{
// Calculate level
int level = getIntObjVar(pcd, "creature_attribs.level");
int health = getIntObjVar(pcd, "creature_attribs." + create.MAXATTRIBNAMES[HEALTH]);
int minDamage = getIntObjVar(pcd, "creature_attribs.minDamage");
int maxDamage = getIntObjVar(pcd, "creature_attribs.maxDamage");
int toHit = getIntObjVar(pcd, "creature_attribs.toHitChance");
int defenseValue = getIntObjVar(pcd, "creature_attribs.defenseValue");
int general_protection = getIntObjVar(pcd, "creature_attribs.general_protection");
// Remove any old armor values.
stripOldStats( pcd );
// Add any missing values.
if ( !hasObjVar( pcd, "creature_attribs.toHitChance" ) )
setObjVar( pcd, "creature_attribs.toHitChance", dataTableGetInt("datatables/mob/stat_balance.iff", level-1, "ToHit") );
if ( !hasObjVar( pcd, "creature_attribs.defenseValue" ) )
setObjVar( pcd, "creature_attribs.defenseValue", dataTableGetInt("datatables/mob/stat_balance.iff", level-1, "Def") );
if ( !hasObjVar( pcd, "creature_attribs.general_protection" ) )
setObjVar( pcd, "creature_attribs.general_protection", dataTableGetInt("datatables/mob/stat_balance.iff", level-1, "Elite_Armor") );
if ( !hasObjVar( pcd, "creature_attribs.critChance" ) )
setObjVar( pcd, "creature_attribs.critChance", 0.0f );
if ( !hasObjVar( pcd, "creature_attribs.critSave" ) )
setObjVar( pcd, "creature_attribs.critSave", 0.0f );
if ( !hasObjVar( pcd, "creature_attribs.stateResist" ) )
setObjVar( pcd, "creature_attribs.stateResist", 0.0f );
if ( !hasObjVar( pcd, "creature_attribs.aggroBonus" ) )
setObjVar( pcd, "creature_attribs.aggroBonus", 0.0f );
if (level == 0)
return true;
int calcLevel = getCalcLevelFromPcd(pcd);
// Validate Level
if (level >= (calcLevel * 0.85f))
{
return true;
}
else
{
CustomerServiceLog("be_clone_validation", "Invalid Pet Found: "+getName(player)+"("+player+") "+getEncodedName(pcd)+"(pcd-"+pcd+
") Level("+level+") calcLevel("+calcLevel+
") H("+health+") Dam("+minDamage+"-"+maxDamage+") toHit("+toHit+
") DV("+defenseValue+") GP("+general_protection+
")");
showBrokenPetDialog(pcd, player);
return false;
}
}
int showBrokenPetDialog(obj_id pcd, obj_id player)
{
// Create the dialog page.
int pid = sui.createSUIPage( sui.SUI_MSGBOX, pcd, player, "handlePetFixDialog" );
// Add elements text.
setSUIProperty(pid, "", "Size", "450,375");
setSUIProperty(pid, sui.MSGBOX_TITLE, sui.PROP_TEXT, localize(SID_PET_SUI_TITLE) );
setSUIProperty(pid, sui.MSGBOX_PROMPT, sui.PROP_TEXT, localize(SID_PET_SUI_TEXT) );
// Add buttons.
sui.msgboxButtonSetup(pid, sui.YES_NO_CANCEL);
setSUIProperty(pid, sui.MSGBOX_BTN_REVERT, sui.PROP_TEXT, "@"+SID_PET_SUI_FIX_LEVEL.toString() );
setSUIProperty(pid, sui.MSGBOX_BTN_OK, sui.PROP_TEXT, "@"+SID_PET_SUI_FIX_STATS.toString() );
setSUIProperty(pid, sui.MSGBOX_BTN_CANCEL, sui.PROP_TEXT, "@"+SID_PET_SUI_ABORT.toString() );
setSUIProperty(pid, sui.MSGBOX_BTN_REVERT, "OnPress", "RevertWasPressed=1\r\nparent.btnOk.press=t");
subscribeToSUIProperty(pid, sui.MSGBOX_BTN_REVERT, "RevertWasPressed");
// Show dialog.
sui.showSUIPage( pid );
return pid;
}
void adjustBrokenPetLevel(obj_id pcd, obj_id player)
{
// Calculate level
int oldLevel = getIntObjVar(pcd, "creature_attribs.level");
int level = getCalcLevelFromPcd(pcd);
if (level < 1)
{
CustomerServiceLog("be_clone_validation", "ERROR - Unable to adjust pet: "+getName(player)+"("+player+") "+
getEncodedName(pcd)+"(pcd-"+pcd+")");
sendSystemMessage(player, SID_PET_SUI_FIX_ERROR);
return;
}
if (level > 75)
{
prose_package pp = prose.getPackage( SID_NEW_LEVEL_TOO_HIGH, level );
sendSystemMessageProse( player, pp );
adjustBrokenPetStats( pcd, player );
return;
}
// Store new level
stripOldStats( pcd );
setObjVar(pcd, "creature_attribs.level", level);
// Notify player of the change
prose_package proseMsg = prose.getPackage(SID_PET_SUI_LEVEL_FIXED, level);
sendSystemMessageProse(player, proseMsg);
// Log the change
CustomerServiceLog("be_clone_validation", "Invalid Pet Fixed: "+getName(player)+"("+player+") "+getEncodedName(pcd)+"(pcd-"+pcd+
") oldLevel("+oldLevel+") newLevel("+level+")");
}
void adjustBrokenPetStats(obj_id pcd, obj_id player)
{
int level = getIntObjVar(pcd, "creature_attribs.level");
if (level < 1)
{
CustomerServiceLog("be_clone_validation", "ERROR - Unable to adjust pet: "+getName(player)+"("+player+") "+
getEncodedName(pcd)+"(pcd-"+pcd+")");
sendSystemMessage(player, SID_PET_SUI_FIX_ERROR);
return;
}
// Calculate new stats
int health = dataTableGetInt("datatables/mob/stat_balance.iff", level-1, "HP");;
int iconst = dataTableGetInt("datatables/mob/stat_balance.iff", level-1, "HealthRegen");
float dps = dataTableGetFloat("datatables/mob/stat_balance.iff", level-1, "damagePerSecond");
int minDamage = Math.round((dps * 2.0f) * 0.5f);
int maxDamage = Math.round((dps * 2.0f) * 1.5f);
int toHit = dataTableGetInt("datatables/mob/stat_balance.iff", level-1, "ToHit");
int defenseValue= dataTableGetInt("datatables/mob/stat_balance.iff", level-1, "Def");
int general_protection = dataTableGetInt("datatables/mob/stat_balance.iff", level-1, "Armor");
// Revalidate Level
dictionary creatureDict = new dictionary();
creatureDict.put("BaseLevel", level);
creatureDict.put("maxHealth", health);
creatureDict.put("healthRegen", iconst);
creatureDict.put("minDamage", minDamage);
creatureDict.put("maxDamage", maxDamage);
creatureDict.put("toHitChance", toHit);
creatureDict.put("defenseValue", defenseValue);
creatureDict.put("armorEffectiveness", general_protection);
int calcLevel = getCraftedCreatureLevel(creatureDict);
if (calcLevel != level)
{
CustomerServiceLog("be_clone_validation", "ERROR - Unable to adjust pet: "+getName(player)+"("+player+") "+
getEncodedName(pcd)+"(pcd-"+pcd+")");
sendSystemMessage(player, SID_PET_SUI_FIX_ERROR);
return;
}
// Store new stats
stripOldStats( pcd );
setObjVar(pcd, "creature_attribs." + create.MAXATTRIBNAMES[HEALTH], health);
setObjVar(pcd, "creature_attribs." + create.MAXATTRIBNAMES[CONSTITUTION], iconst);
setObjVar(pcd, "creature_attribs.minDamage", minDamage);
setObjVar(pcd, "creature_attribs.maxDamage", maxDamage);
setObjVar(pcd, "creature_attribs.toHitChance", toHit);
setObjVar(pcd, "creature_attribs.defenseValue", defenseValue);
setObjVar(pcd, "creature_attribs.general_protection", general_protection);
// Notify player of the change
prose_package proseMsg = prose.getPackage(SID_PET_SUI_STATS_FIXED, level);
sendSystemMessageProse(player, proseMsg);
// Log the change
CustomerServiceLog("be_clone_validation", "Invalid Pet Fixed: "+getName(player)+"("+player+") "+getEncodedName(pcd)+"(pcd-"+pcd+
") Level("+level+") NewStats: H("+health+
") Dam("+minDamage+"-"+maxDamage+") toHit("+toHit+
") DV("+defenseValue+") GP("+general_protection+
")");
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////
//// Template Crafting - Sample Conversion Functions
////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
boolean validateCreatureSpecialAttack(int attack)
{
for (int i = 0; i < CREATURE_SPECIAL_ATTACK_LIST.length; i++)
{
if (attack == CREATURE_SPECIAL_ATTACK_LIST[i])
return true;
}
return false;
}
string convertSampleTypeToCreature(string sampleType)
{
java.util.StringTokenizer st = new java.util.StringTokenizer(sampleType, ":");
if ( st.countTokens() != 2 )
{
LOG ("creature_crafting", "ERROR: Unable to convert Sample Type to creature name.");
return "eopie";
}
string creature = st.nextToken();
creature = st.nextToken();
LOG ("creature_crafting", "Converted Sample: " + sampleType + " to Creature: " + creature);
return creature;
}
string convertTemplateToCreature(string templateName)
{
java.util.StringTokenizer st = new java.util.StringTokenizer(templateName, "/");
string creature = st.nextToken();
while (st.hasMoreTokens())
{
creature = st.nextToken();
}
creature = creature.substring(13); // remove "dna_template_" from beginning
st = new java.util.StringTokenizer(creature, ".");
creature = st.nextToken();
LOG ("creature_crafting", "Converted Template: " + templateName + " to Creature: " + creature);
return creature;
}
int translateDnaSampleAttributes(string attribName, int attribValue, string sampleType, string templateName)
{
LOG ("creature_crafting", "Translating DNA Sample Attribute to DNA Template relative values");
LOG ("creature_crafting", "Attribute Name = " + attribName);
// convert the dna template name into a valid creature name
string sampleCreature = convertSampleTypeToCreature(sampleType);
// load up the creature attribs for the dna sample
dictionary sampleCreatureDict = dataTableGetRow(create.CREATURE_TABLE, sampleCreature);
if (sampleCreatureDict == null)
{
LOG ("creature_crafting", "ERROR: Unable to read creature entry in Creature Table.");
return attribValue;
}
// convert the dna template name into a valid creature name
string templateCreature = convertTemplateToCreature(templateName);
// load up the creature attribs for the dna template
dictionary templateCreatureDict = dataTableGetRow(create.CREATURE_TABLE, templateCreature);
if (templateCreatureDict == null)
{
LOG ("creature_crafting", "ERROR: Unable to read creature entry in Creature Table.");
return attribValue;
}
int newValue = convertDnaAttributes(attribName, attribValue, sampleCreatureDict, templateCreatureDict);
LOG ("creature_crafting", "DNA Sample Type = " + sampleCreature);
LOG ("creature_crafting", "DNA Sample Attribute Value = " + attribValue);
LOG ("creature_crafting", "DNA Template Name = " + templateCreature);
LOG ("creature_crafting", "DNA Template Attribute Value = " + newValue);
return newValue;
}
int convertDnaAttributes(string attribName, int attribValue, dictionary sampleCreatureDict, dictionary templateCreatureDict)
{
int minSampleAttrib = 0;
int maxSampleAttrib = 0;
int minTemplateAttrib = 0;
int maxTemplateAttrib = 0;
int sampleAttribRange = 0;
int templateAttribRange = 0;
int attribWeight = 0;
int newAttribValue = 0;
for (int i = 0; i < (CREATURE_ATTRIB_WEIGHT_WILLPOWER + 1); i++)
{
if (attribName.equals(CREATURE_ATTRIB_OBJVAR_NAMES[CREATURE_ATTRIB_WEIGHTS[i][0]]))
{
minSampleAttrib = sampleCreatureDict.getInt(create.MINATTRIBNAMES[i]);
maxSampleAttrib = sampleCreatureDict.getInt(create.MAXATTRIBNAMES[i]);
sampleAttribRange = maxSampleAttrib - minSampleAttrib;
minTemplateAttrib += templateCreatureDict.getInt(create.MINATTRIBNAMES[i]) * CREATURE_ATTRIB_WEIGHTS[i][1];
maxTemplateAttrib += templateCreatureDict.getInt(create.MAXATTRIBNAMES[i]) * CREATURE_ATTRIB_WEIGHTS[i][1];
attribWeight += CREATURE_ATTRIB_WEIGHTS[i][1];
newAttribValue += ((int) ((sampleAttribRange * newAttribValue) / 1000f) + minSampleAttrib) * CREATURE_ATTRIB_WEIGHTS[i][1];
}
if (attribName.equals(CREATURE_ATTRIB_OBJVAR_NAMES[CREATURE_ATTRIB_WEIGHTS[i][2]]))
{
minSampleAttrib = sampleCreatureDict.getInt(create.MINATTRIBNAMES[i]);
maxSampleAttrib = sampleCreatureDict.getInt(create.MAXATTRIBNAMES[i]);
sampleAttribRange = maxSampleAttrib - minSampleAttrib;
minTemplateAttrib += templateCreatureDict.getInt(create.MINATTRIBNAMES[i]) * CREATURE_ATTRIB_WEIGHTS[i][2];
maxTemplateAttrib += templateCreatureDict.getInt(create.MAXATTRIBNAMES[i]) * CREATURE_ATTRIB_WEIGHTS[i][2];
attribWeight += CREATURE_ATTRIB_WEIGHTS[i][2];
newAttribValue += ((int) ((sampleAttribRange * newAttribValue) / 1000f) + minSampleAttrib) * CREATURE_ATTRIB_WEIGHTS[i][2];
}
}
if (attribWeight == 0)
{
LOG("creature_crafting", "ERROR: No attribute weights found!");
return attribValue;
}
newAttribValue = newAttribValue / attribWeight;
LOG("creature_crafting", "Weighted Sample Attribute = " + newAttribValue);
minTemplateAttrib = minTemplateAttrib / attribWeight;
maxTemplateAttrib = maxTemplateAttrib / attribWeight;
templateAttribRange = (maxTemplateAttrib - minTemplateAttrib) / 2;
LOG("creature_crafting", "Weighted Template Attribute = " + (minTemplateAttrib + templateAttribRange));
int attribDiff = newAttribValue - (minTemplateAttrib + templateAttribRange);
if ((attribDiff > -templateAttribRange) && (attribDiff < templateAttribRange))
{
LOG("creature_crafting", "New Attrib within Template Range.");
return attribValue;
}
LOG("creature_crafting", "Attrib Diff = " + attribDiff);
if (attribDiff < 0)
{
float diffFactor = 1 + (-(attribDiff + templateAttribRange) / (float) templateAttribRange);
newAttribValue = (int) (attribValue / diffFactor);
LOG("creature_crafting", "Diff Factor = " + diffFactor);
LOG("creature_crafting", "Attrib Value = " + attribValue);
LOG("creature_crafting", "New Value = " + newAttribValue);
}
else
{
float diffFactor = 1 + ((attribDiff - templateAttribRange) / (float) templateAttribRange);
if (diffFactor > 20) diffFactor = 20;
diffFactor /= 100f;
newAttribValue = (int) (attribValue * (1 + diffFactor));
LOG("creature_crafting", "Diff Factor = " + diffFactor);
LOG("creature_crafting", "Attrib Value = " + attribValue);
LOG("creature_crafting", "New Value = " + newAttribValue);
}
return newAttribValue;
}