//------------------------------------------------ // 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; }