package script.library; import script.*; import java.util.Vector; public class pet_lib extends script.base_script { public pet_lib() { } public static final int CUSTOMIZATION_COUNT = 2000; public static final int MAX_NUMBER_OF_FRIENDS = 5; public static final int MAX_WAYPOINTS = 10; public static final int COMMAND_FOLLOW = 0; public static final int COMMAND_STAY = 1; public static final int COMMAND_GUARD = 2; public static final int COMMAND_FRIEND = 3; public static final int COMMAND_ATTACK = 4; public static final int COMMAND_PATROL = 5; public static final int COMMAND_SET_PATROL_POINT = 6; public static final int COMMAND_CLEAR_PATROL_POINTS = 7; public static final int COMMAND_ASSUME_FORMATION_1 = 8; public static final int COMMAND_ASSUME_FORMATION_2 = 9; public static final int COMMAND_TRANSFER = 10; public static final int COMMAND_RELEASE = 11; public static final int COMMAND_TRICK_1 = 12; public static final int COMMAND_TRICK_2 = 13; public static final int COMMAND_TRICK_3 = 14; public static final int COMMAND_TRICK_4 = 15; public static final int COMMAND_GROUP = 16; public static final int COMMAND_FOLLOW_OTHER = 17; public static final int COMMAND_SPECIALATTACK_ONE = 18; public static final int COMMAND_SPECIALATTACK_TWO = 19; public static final int COMMAND_RANGED_ATTACK = 20; public static final int COMMAND_TARGET_HARVEST = 21; public static final int COMMAND_TRAP_THROW_ONE = 22; public static final int NUM_COMMANDS = 23; public static final int PET_TYPE_NON_AGGRO = 0; public static final int PET_TYPE_AGGRO = 1; public static final int PET_TYPE_NPC = 2; public static final int PET_TYPE_DROID = 3; public static final int PET_TYPE_FAMILIAR = 4; public static final int PET_TYPE_MOUNT = 5; public static final int MAX_NPC_PETS = 1; public static final int MAX_DROID_PETS = 1; public static final int MAX_FAMILIAR_PETS = 1; public static final int MAX_MOUNT_PETS = 1; public static final int MAX_UNTRAINED_PETS = 1; public static final int MAX_UNTRAINED_STORED_PETS = 2; public static final int MAX_NONCH_PET_LEVEL = 10; public static final int MAX_REGEN_STAT = 4000; public static final int MAX_PET_LEVELS = 70; public static final int MAX_PET_LEVELS_ABOVE_CALLER = 5; public static final int MAX_PET_MOUNT_DISTANCE = 4; public static final int MAX_PET_MOUNT_OFFER_DISTANCE = 32; public static final int MAX_VITALITY_LOSS = 100; public static final int COMBATMODE_NONE = 0; public static final int COMBATMODE_DEFAULT = 1; public static final int COMBATMODE_EQUIPPED = 2; public static final int COMBATMODE_SPECIAL = 3; public static final int PET_ABILITY_INNATE = 1; public static final int PET_ABILITY_TRIGGERED = 2; public static final int PET_ABILITY_ACTION = 3; public static final float XP_CURVE_STEEPNESS = 2.2f; public static final float XP_LOW_END_REWARD = 100.0f; public static final String BATTERY = "object/tangible/droid_battery/battery.iff"; public static final int OUT_OF_POWER = 100; public static final float PET_GROWTH_CYCLE = 43200.0f; public static final String CREATURE_TABLE = "datatables/mob/creatures.iff"; public static final String PET_ABILITY_TABLE = "datatables/pet/pet_ability.iff"; public static final String WILD_ABILITY_TABLE = "datatables/pet/wild_ability.iff"; public static final String MENU_FILE = "pet/pet_menu"; public static final int CALL_DELAY = 0; public static final int BUTTON_MASHING_DELAY = 3; public static final int POST_COMBAT_DELAY = 30; public static final String COMBAT_ENDED = "player.combatEnded"; public static final String CALL_FINISH = "player.callFinish"; public static final int BASE_MAX_TRAP_LOAD = 20; public static final String VAR_PALVAR_BASE = "ai.pet.palvar"; public static final String VAR_PALVAR_VARS = VAR_PALVAR_BASE + ".vars"; public static final String VAR_PALVAR_CNT = VAR_PALVAR_BASE + ".cnt"; public static final String[] LIGHTING_EFFECTS = { "droid_effect_foam", "droid_effect_electric_fog", "droid_effect_confetti", "droid_effect_mind_bloom", "droid_effect_jawa_dance", "droid_effect_doves" }; public static final string_id SID_SYS_CANT_TAME = new string_id("pet/pet_menu", "sys_cant_tame"); public static final string_id SID_SYS_LACK_SKILL = new string_id("pet/pet_menu", "sys_lack_skill"); public static final string_id SID_MAX_PETS = new string_id("error_message", "too_many_pets"); public static final string_id SID_PET_DIED_MASTER = new string_id("error_message", "pet_died_master"); public static final string_id SID_PET_DIED_OTHER = new string_id("error_message", "pet_died_other"); public static final string_id SID_SYS_CANT_TRICK = new string_id("pet/pet_menu", "sys_cant_trick"); public static final string_id SID_SYS_LEARN_COMMAND = new string_id("pet/pet_menu", "pet_learn"); public static final string_id SID_SYS_CANT_LEARN = new string_id("pet/pet_menu", "pet_nolearn"); public static final string_id SID_SYS_NOT_HANDLER = new string_id("pet/pet_menu", "pet_nothandler"); public static final string_id SID_SYS_XFER_SUCCESS = new string_id("pet/pet_menu", "pet_transfer_succeed"); public static final string_id SID_SYS_TOO_MANY_PETS = new string_id("pet/pet_menu", "pet_too_many_pets"); public static final string_id SID_SYS_TOO_MANY_STORED_PETS = new string_id("pet/pet_menu", "sys_too_many_stored"); public static final string_id SID_PRIVATE_HOUSE = new string_id("pet/pet_menu", "private_house"); public static final string_id SID_INVALID_CRAFTED_PET = new string_id("pet/pet_menu", "invalid_crafted_pet"); public static final string_id SID_SYS_PATROL_ADDED = new string_id("pet/pet_menu", "patrol_added"); public static final string_id SID_SYS_PATROL_REMOVED = new string_id("pet/pet_menu", "patrol_removed"); public static final string_id SID_SYS_CANT_CALL = new string_id("pet/pet_menu", "cant_call"); public static final string_id SID_SYS_CANT_CALL_YET = new string_id("pet/pet_menu", "prose_cant_call_yet"); public static final string_id SID_SYS_CANT_CALL_LEVEL = new string_id("pet/pet_menu", "cant_call_level"); public static final string_id SID_SYS_CANT_GENERATE_YET = new string_id("pet/pet_menu", "prose_cant_generate_yet"); public static final string_id SID_SYS_CALL_DELAY_FINISH_VEHICLE = new string_id("pet/pet_menu", "call_delay_finish_vehicle"); public static final string_id SID_SYS_CALL_DELAY_FINISH_PET = new string_id("pet/pet_menu", "call_delay_finish_pet"); public static final string_id MOUNTED_CALL_WARNING = new string_id("pet/pet_menu", "mounted_call_warning"); public static final string_id SID_SYS_CANT_CALL_ANOTHER_RIDEABLE = new string_id("pet/pet_menu", "cannot_call_another_rideable"); public static final string_id SID_SYS_CANT_CALL_ANOTHER_FAMILIAR = new string_id("pet/pet_menu", "cannot_call_another_familiar"); public static final string_id SID_SYS_PACKED_DROID = new string_id("pet/pet_menu", "droid_packed"); public static final string_id SID_SYS_CANT_CALL_VEHICLE = new string_id("pet/pet_menu", "cant_call_vehicle"); public static final string_id SID_SYS_VEHICLE_RESTRICTED_SCENE = new string_id("pet/pet_menu", "vehicle_restricted_scene"); public static final string_id SID_SYS_MOUNT_RESTRICTED_SCENE = new string_id("pet/pet_menu", "mount_restricted_scene"); public static final string_id SID_SYS_CALL_VEHICLE_DELAY = new string_id("pet/pet_menu", "call_vehicle_delay"); public static final string_id SID_SYS_CALL_PET_DELAY = new string_id("pet/pet_menu", "call_pet_delay"); public static final string_id SID_SYS_CALL_MAX_DATAPAD = new string_id("pet/pet_menu", "max_npc_in_datapad"); public static final string_id SID_PET_HAS_NOTRADE = new string_id("pet/pet_menu", "pet_has_notrade"); public static final string_id SID_SYS_CANT_MOUNT = new string_id("pet/pet_menu", "cant_mount"); public static final string_id SID_SYS_CANT_DISMOUNT = new string_id("pet/pet_menu", "cant_dismount"); public static final String PET_CTRL_DEVICE_TEMPLATE = "object/intangible/pet/pet_control.iff"; public static final string_id SID_PET_INVITED = new string_id("pet/pet_menu", "pet_invited"); public static final string_id SID_PET_NO_GROUP_IN_SPACE = new string_id("pet/pet_menu", "pet_no_group_in_space"); public static final string_id SID_GROWTH_CHOICE_TITLE = new string_id("pet/pet_menu", "mount_growth_title"); public static final string_id SID_GROWTH_CHOICE_PROMPT = new string_id("pet/pet_menu", "mount_growth_prompt"); public static final string_id SID_SYS_CANT_MOUNT_VEHICLE_DISABLED = new string_id("pet/pet_menu", "cant_mount_veh_disabled"); public static final string_id SID_SYS_VEHICLE_DISABLED = new string_id("pet/pet_menu", "veh_disabled"); public static final String TEMPLATE_PREFIX = "object/mobile/"; public static final String CREATURE_NAME_FILE = "mob/creature_names"; public static final String NPC_CUSTOMIZATION_PREFIX = "datatables/npc_customization/"; public static final String DRESSED_NPC_TABLE = "datatables/npc_customization/dressed_species.iff"; public static final String MOUNT_VALID_SCALE_RANGE = "datatables/mount/valid_scale_range.iff"; public static final string_id SID_SYS_CUST_FADING = new string_id("pet/pet_menu", "customization_fading"); public static final string_id SID_SYS_CUST_GONE = new string_id("pet/pet_menu", "customization_gone"); public static final string_id SID_SYS_VEH_CUST_FADING = new string_id("pet/pet_menu", "customization_fading_veh"); public static final string_id SID_SYS_VEH_CUST_GONE = new string_id("pet/pet_menu", "customization_gone_veh"); public static final string_id SID_MOUNT_STATUS_CODE_ERROR = new string_id("pet/pet_menu", "mount_status_code_error"); public static final String DROID_COMBAT_TABLE = "datatables/combat/droid_combat_capabilities.iff"; public static final int MAX_DROID_COMBAT_VALUE = 880; public static final String PROBOT_DROID_NAME = "probot"; public static final String DZ70_DROID_NAME = "dz70_fugitive_tracker_droid"; public static final string_id SID_SYS_RANGED_ATTACK_TOGGLED = new string_id("pet/pet_menu", "ranged_attack_toggled"); public static final string_id SID_SYS_RANGED_ATTACK_TOGGLED_OFF = new string_id("pet/pet_menu", "ranged_attack_toggled_off"); public static final int DEFAULT_DROID_LEVEL = 1; public static final String TBL_MOB_STAT_BALANCE = "datatables/mob/stat_balance.iff"; public static final String TBL_DROID_COMBAT = "datatables/combat/droid_combat_capabilities.iff"; public static final String DROID_RANGED_WEAPON = "object/weapon/ranged/vehicle/droid_weapon.iff"; public static final int COMBAT_MODULE_PROTECT_LVL = 500; public static final int DEFENSE_MODULE_PROTECT_LVL = 1000; public static final int DETONATION_DROID_MIN_DAMAGE = 65; public static final int DETONATION_DROID_MAX_DAMAGE = 97; public static final String OBJVAR_PET_PATROL_POINTS = "pet.patrolPoints"; public static final String DROID_HARVEST_ARRAY = "droid.toHarvest"; public static final String[] MOUNTABILITY_STATUS_CODES = { "MSC_CREATURE_MOUNTABLE", "MSC_SPECIES_UNMOUNTABLE", "MSC_SPECIES_MOUNTABLE_SEATING_CAPACITY_UNSUPPORTED", "MSC_SPECIES_MOUNTABLE_SCALE_OUT_OF_RANGE", "MSC_SPECIES_MOUNTABLE_MISSING_RIDER_SLOT" }; public static final int HEALTH_DAMAGE = 0; public static final int ACTION_DAMAGE = 1; public static final int MIND_DAMAGE = 2; public static final int HEALTH_WOUND = 3; public static final int ACTION_WOUND = 4; public static final int MIND_WOUND = 5; public static final String FAMILAR_DATA_DATATABLE = "datatables/pet/non_combat_familiar.iff"; public static void petFollow(obj_id pet, obj_id master) throws InterruptedException { final float collisionRadius = getObjectCollisionRadius(pet) * 2.0f; ai_lib.aiFollow(pet, master, collisionRadius, collisionRadius); setMovementRun(pet); } public static void setUpPetControlDevice(obj_id petControlDevice, obj_id pet) throws InterruptedException { setObjVar(petControlDevice, "pet.creatureName", ai_lib.getCreatureName(pet)); callable.setCDCallable(petControlDevice, pet); callable.setCallableCD(pet, petControlDevice); attachScript(petControlDevice, "ai.pet_control_device"); setControllerName(petControlDevice, pet); int petType = getPetType(pet); setObjVar(petControlDevice, "ai.pet.type", petType); if (couldPetBeMadeMountable(pet) == MSC_SPECIES_UNMOUNTABLE) { setObjVar(petControlDevice, "ai.petAdvance.cannotBeMount", true); } markExpansionPets(petControlDevice, pet); } public static obj_id makeControlDevice(obj_id master, obj_id pet) throws InterruptedException { if (callable.hasCallableCD(pet)) { return callable.getCallableCD(pet); } obj_id datapad = utils.getPlayerDatapad(master); if (!isIdValid(datapad)) { return null; } String creatureName = ai_lib.getCreatureName(pet); if (creatureName == null || creatureName.equals("")) { return null; } String controlTemplate = "object/intangible/pet/" + utils.dataTableGetString(create.CREATURE_TABLE, creatureName, "template"); if (!controlTemplate.endsWith(".iff")) { controlTemplate = pet_lib.PET_CTRL_DEVICE_TEMPLATE; } obj_id petControlDevice = createObject(controlTemplate, datapad, ""); if (!isIdValid(petControlDevice)) { petControlDevice = createObject(pet_lib.PET_CTRL_DEVICE_TEMPLATE, datapad, ""); if (!isIdValid(petControlDevice)) { sendSystemMessage(master, pet_lib.SID_SYS_TOO_MANY_STORED_PETS); return null; } } setUpPetControlDevice(petControlDevice, pet); if (hasObjVar(pet, "ai.petAbility.wildAbility")) { String wildAbility = getStringObjVar(pet, "ai.petAbility.wildAbility"); int[] abilityList = new int[1]; abilityList[0] = getStringCrc(wildAbility.toLowerCase()); setObjVar(petControlDevice, "ai.petAbility.abilityList", abilityList); setObjVar(petControlDevice, "ai.petAbility.wildAbility", wildAbility); } if (hasObjVar(petControlDevice, "ai.petAdvance.growthStage")) { pet_lib.setPetStatsByGrowth(pet, getIntObjVar(petControlDevice, "ai.petAdvance.growthStage")); } else { pet_lib.setPetStatsByGrowth(pet, 10); } callable.setCallableCD(pet, petControlDevice); return petControlDevice; } public static void makePet(obj_id pet, obj_id master) throws InterruptedException { if (!isIdValid(pet) || !isIdValid(master) || !exists(pet) || !exists(master)) { return; } if (!hasScript(master, "ai.pet_master")) { attachScript(master, "ai.pet_master"); } dictionary params = new dictionary(); params.put("pet", pet); params.put("master", master); petFollow(pet, master); int petSpecies = ai_lib.aiGetSpecies(pet); if (petSpecies == -1) { return; } String masterFaction = factions.getFaction(master); if (masterFaction != null && (masterFaction.equals("Rebel") || masterFaction.equals("Imperial"))) { setObjVar(pet, factions.FACTION, masterFaction); } if (!utils.hasScriptVar(pet, "petBeingInitialized") || (callable.hasCallable(master, callable.getCallableType(pet)) && callable.getCallable(master, callable.getCallableType(pet)) != pet)) { return; } obj_id controlDevice = obj_id.NULL_ID; if (callable.hasCallableCD(pet)) { controlDevice = callable.getCallableCD(pet); } int petType = pet_lib.getPetType(pet); setObjVar(pet, "ai.pet.type", petType); if (!pet_lib.hasMaxPets(master, petType, pet) || (pet_lib.hasMaxPets(master, petType) && hasObjVar(controlDevice, "ai.pet.trainedMount"))) { controlDevice = makeControlDevice(master, pet); ai_lib.setDefaultCalmBehavior(pet, ai_lib.BEHAVIOR_STOP); if (!isIdValid(controlDevice) || !exists(controlDevice)) { return; } pet_lib.addToPetList(master, pet); params.put("controlDevice", controlDevice); messageTo(pet, "handleAddMaster", params, 0, false); } else { if (callable.hasCallableCD(pet)) { destroyObject(pet); } } if (isIdValid(controlDevice) && hasMountName(controlDevice)) { setName(pet, getMountName(controlDevice)); } } public static boolean hasMaster(obj_id pet) throws InterruptedException { if (!isIdValid(pet) || !exists(pet) || !isMob(pet) || isPlayer(pet)) { return false; } obj_id master = getMaster(pet); if (!isIdValid(master) || !exists(master)) { return false; } return true; } public static void removeFromPetList(obj_id pet) throws InterruptedException { if (!isIdValid(pet) || !hasMaster(pet)) { return; } obj_id master = getMaster(pet); int petSpecies = ai_lib.aiGetSpecies(pet); if (!isValidId(master) || !exists(master) || petSpecies == -1 || callable.getCallable(master, callable.getCallableType(pet)) != pet) { return; } callable.setCallable(master, null, callable.getCallableType(pet)); return; } public static void releasePet(obj_id pet) throws InterruptedException { dictionary params = new dictionary(); params.put("pet", pet); params.put("species", ai_lib.aiGetSpecies(pet)); String creatureName = getCreatureName(pet); if (creatureName != null) { params.put("ai.creatureName", creatureName); } if (callable.hasCallableCD(pet)) { obj_id controller = callable.getCallableCD(pet); if (isIdValid(controller)) { obj_id currentPet = callable.getCDCallable(controller); if (isIdValid(currentPet) && currentPet == pet) { savePetInfo(pet, controller); setObjVar(controller, "pet.timeStored", getGameTime()); } } } messageTo(pet, "handlePackRequest", null, 0, false); } public static int getMaxPets(obj_id master, int petType) throws InterruptedException { if (petType == PET_TYPE_NPC) { return MAX_NPC_PETS; } else if (petType == PET_TYPE_DROID) { return MAX_DROID_PETS; } else if (petType == PET_TYPE_FAMILIAR) { return MAX_FAMILIAR_PETS; } else if (petType == PET_TYPE_MOUNT) { return MAX_MOUNT_PETS; } return 1; } public static int countPetsOfType(obj_id master, int petType) throws InterruptedException { int petCount = 0; if (hasMaxPets(master, petType)) { petCount++; } return petCount; } public static boolean hasMaxPets(obj_id master, int petType) throws InterruptedException { return hasMaxPets(master, petType, obj_id.NULL_ID); } public static boolean hasMaxPets(obj_id master, int petType, obj_id pet) throws InterruptedException { int callableType = callable.CALLABLE_TYPE_COMBAT_PET; if (petType == PET_TYPE_FAMILIAR) { callableType = callable.CALLABLE_TYPE_FAMILIAR; } else if (petType == PET_TYPE_MOUNT) { callableType = callable.CALLABLE_TYPE_RIDEABLE; } if (!isIdValid(pet)) { if (callable.hasCallable(master, callableType)) { return true; } else { return false; } } else { if (callable.hasCallable(master, callableType, pet)) { return true; } else { return false; } } } public static void initializePetCommandList(obj_id pet, obj_id pcd) throws InterruptedException { dictionary petCommandList = new dictionary(); obj_var_list commandList = getObjVarList(pcd, "ai.pet.command"); if (commandList != null && commandList.getNumItems() > 0) { int numItems = commandList.getNumItems(); for (int i = 0; i < numItems; i++) { obj_var ov = commandList.getObjVar(i); petCommandList.put(ov.getStringData(), Integer.parseInt(ov.getName())); } } utils.setScriptVar(pet, "ai.pet.commandList", petCommandList); } public static int getDroidModuleCommandLevel(obj_id player, int modulePotency) throws InterruptedException { if (!isIdValid(player) || !isPlayer(player)) { return 0; } String profession = skill.getProfessionName(getSkillTemplate(player)); if(profession == null){ LOG("pet","Cannot get the profession for player (" + player + ") while getting droid command level."); return 0; } boolean isTrader = false; if (profession.equals("trader")) { isTrader = true; } int playerLevel = getLevel(player); int commandLevel = 0; if (modulePotency >= 100 && isTrader && playerLevel >= 60) { commandLevel = 3; } else if (modulePotency >= 50 && isTrader && playerLevel >= 30) { commandLevel = 2; } else if (modulePotency > 0) { commandLevel = 1; } return commandLevel; } public static void learnCommand(obj_id pet, int commandNum, String text, obj_id master) throws InterruptedException { if (utils.isExtendedASCII(text)) { sendSystemMessage(master, new string_id(MENU_FILE, "invalid_command")); return; } obj_id petControlDevice = callable.getCallableCD(pet); String command = getStringObjVar(petControlDevice, "ai.pet.command." + commandNum); String oldCommand = null; if (command == null || command.equals("")) { if (isCreaturePet(pet)) { String creatureName = getCreatureName(pet); if (creatureName == null) { return; } int petType = pet_lib.getPetType(pet); int tamingSkillMod = 0; if (petType == pet_lib.PET_TYPE_AGGRO) { tamingSkillMod = getEnhancedSkillStatisticModifier(master, "tame_aggro"); } else { tamingSkillMod = getEnhancedSkillStatisticModifier(master, "tame_non_aggro"); } float chance = 0; if (tamingSkillMod > 0) { chance = 50 + tamingSkillMod; chance -= getAdultLevel(pet) * 2; if (chance < 20) { chance = 20; } } int attempts = utils.getIntScriptVar(pet, "ai.pet.trainCommand" + commandNum); int roll = rand(1, 100); if (roll > chance && attempts < 3) { doConfusedEmote(pet); attempts++; sendSystemMessage(master, SID_SYS_CANT_LEARN); utils.setScriptVar(pet, "ai.pet.trainCommand" + commandNum, attempts); return; } } } else { oldCommand = getStringObjVar(petControlDevice, "ai.pet.command." + commandNum); } command = text; setObjVar(petControlDevice, "ai.pet.command." + commandNum, command); dictionary petCommandList = utils.getDictionaryScriptVar(pet, "ai.pet.commandList"); if (petCommandList == null) { petCommandList = new dictionary(); } petCommandList.put(command, commandNum); if (oldCommand != null) { petCommandList.remove(oldCommand); } utils.setScriptVar(pet, "ai.pet.commandList", petCommandList); utils.removeScriptVar(pet, "ai.pet.learnCommand"); if (!pet_lib.isSpeakingPet(pet) || pet_lib.isDroidPet(pet)) { if (!pet_lib.isDroidPet(pet)) { sendSystemMessage(master, SID_SYS_LEARN_COMMAND); pet_lib.openLearnCommandSui(pet, master); } color textColor = colors.SILVER; showFlyTextPrivate(pet, master, new string_id("npc_reaction/flytext", "threaten"), 0.75f, textColor.getR(), textColor.getG(), textColor.getB(), true); checkForName(pet, petControlDevice); } else { String myStringFile = "hireling/hireling"; if (hasObjVar(pet, "ai.diction")) { String myDiction = getStringObjVar(pet, "ai.diction"); if (myDiction != null && !myDiction.equals("townperson")) { myStringFile = "hireling/hireling" + "_" + myDiction; } } chat.chat(pet, new string_id(myStringFile, "end_convo")); } savePetInfo(pet, petControlDevice); } public static int getCommandNum(obj_id pet, String text) throws InterruptedException { if (!utils.hasScriptVar(pet, "ai.pet.commandList")) { return -1; } dictionary petCommandList = utils.getDictionaryScriptVar(pet, "ai.pet.commandList"); String myName = toLower(getName(pet)); int suffix = myName.indexOf(")"); if (suffix > 1) { myName = myName.substring(1, suffix); } int commandNum = -1; if (petCommandList.containsKey(text)) { commandNum = petCommandList.getInt(text); } else if (petCommandList.containsKey(myName + " " + text)) { commandNum = petCommandList.getInt(myName + " " + text); } if (callable.getCallableType(pet) == callable.CALLABLE_TYPE_RIDEABLE) { return -1; } if (commandNum > -1) { color textColor = colors.BLUE; showFlyTextPrivate(pet, getMaster(pet), new string_id("npc_reaction/flytext", "threaten"), 1.75f, textColor.getR(), textColor.getG(), textColor.getB(), true); } return commandNum; } public static void doCommand(obj_id pet, String text, obj_id master) throws InterruptedException { int commandNum = getCommandNum(pet, text); if (commandNum == -1) { return; } doCommandNum(pet, commandNum, master); } public static boolean doCommandNum(obj_id master, int commandNum) throws InterruptedException { obj_id pet = callable.getCallable(master, callable.CALLABLE_TYPE_COMBAT_PET); if (!isIdValid(pet) || !exists(pet) || !pet_lib.isDroidPet(pet)) { return false; } if (getMaster(pet) != master) { return false; } return doPetCommand(pet, commandNum, master); } public static void doCommandNum(obj_id pet, int commandNum, obj_id master) throws InterruptedException { doPetCommand(pet, commandNum, master); } public static boolean doPetCommand(obj_id pet, int commandNum, obj_id master) throws InterruptedException { if (ai_lib.isInCombat(pet)) { if (commandNum >= COMMAND_FOLLOW && commandNum < NUM_COMMANDS && commandNum != COMMAND_STAY && commandNum != COMMAND_FOLLOW && commandNum != COMMAND_FOLLOW_OTHER && commandNum != COMMAND_ATTACK && commandNum != COMMAND_SPECIALATTACK_ONE && commandNum != COMMAND_SPECIALATTACK_TWO) { return false; } } if (getMountsEnabled()) { obj_id petsCurrentRider = getRiderId(pet); if (isIdValid(petsCurrentRider)) { if (commandNum != COMMAND_TRICK_1 && commandNum != COMMAND_TRICK_2 && commandNum != COMMAND_RELEASE && commandNum != COMMAND_GROUP) { return false; } } } if (isDroidPet(pet)) { if (isLowOnPower(pet)) { color textColor = colors.MEDIUMPURPLE; showFlyTextPrivate(pet, master, new string_id("npc_reaction/flytext", "low_power"), 0.75f, textColor.getR(), textColor.getG(), textColor.getB(), true); if (commandNum != COMMAND_FOLLOW && commandNum != COMMAND_STAY && commandNum != COMMAND_RELEASE) { return false; } } } switch (commandNum) { case COMMAND_FOLLOW: doFollowCommand(pet, master); break; case COMMAND_FOLLOW_OTHER: doFollowOtherCommand(pet, master); break; case COMMAND_STAY: doStayCommand(pet, master); break; case COMMAND_GUARD: doGuardCommand(pet, master); break; case COMMAND_FRIEND: doFriendCommand(pet, master); break; case COMMAND_ATTACK: doAttackCommand(pet, master); break; case COMMAND_PATROL: doPatrol(pet, master); break; case COMMAND_SET_PATROL_POINT: doSetPatrolPoint(pet, master); break; case COMMAND_CLEAR_PATROL_POINTS: doClearPatrolPoints(pet, master); break; case COMMAND_ASSUME_FORMATION_1: doPetFormation(pet, master, ai_lib.FORMATION_COLUMN); break; case COMMAND_ASSUME_FORMATION_2: doPetFormation(pet, master, ai_lib.FORMATION_WEDGE); break; case COMMAND_RELEASE: doPetRelease(pet); break; case COMMAND_TRANSFER: doPetTransfer(pet, master); break; case COMMAND_TRICK_1: doStupidPetTrick(pet, master, COMMAND_TRICK_1); break; case COMMAND_TRICK_2: doStupidPetTrick(pet, master, COMMAND_TRICK_2); break; case COMMAND_TRICK_3: doStupidPetTrick(pet, master, COMMAND_TRICK_3); break; case COMMAND_TRICK_4: doStupidPetTrick(pet, master, COMMAND_TRICK_4); break; case COMMAND_GROUP: doPetGroup(pet, master); break; case COMMAND_SPECIALATTACK_ONE: doPetSpecialAttack(pet, master, 0); break; case COMMAND_SPECIALATTACK_TWO: doPetSpecialAttack(pet, master, 1); break; case COMMAND_TARGET_HARVEST: doTargetHarvest(pet, master); break; case COMMAND_TRAP_THROW_ONE: doPetThrowTrap(pet, master, commandNum); break; default: doTriggeredPetAbility(pet, master, commandNum); break; } return true; } public static void prepToLearn(obj_id pet, int commandNum) throws InterruptedException { if (!isIdValid(pet) || !exists(pet)) { return; } utils.setScriptVar(pet, "ai.pet.learnCommand", commandNum); if (!hasMaster(pet)) { return; } obj_id master = getMaster(pet); if (!pet_lib.isSpeakingPet(pet)) { color textColor = colors.GOLD; showFlyTextPrivate(pet, master, new string_id("npc_reaction/flytext", "alert"), 1.25f, textColor.getR(), textColor.getG(), textColor.getB(), true); } else { String myStringFile = "hireling/hireling"; if (hasObjVar(pet, "ai.diction")) { String myDiction = getStringObjVar(pet, "ai.diction"); if (myDiction != null && !myDiction.equals("townperson")) { myStringFile = "hireling/hireling" + "_" + myDiction; } } chat.chat(pet, new string_id(myStringFile, "start_convo_4")); } } public static String createLearnCommandListHeader(string_id header) throws InterruptedException { prose_package pp = new prose_package(); pp.stringId = new string_id("pet/pet_ability", "learn_command_list_header"); pp.actor.set(header); return " \0" + packOutOfBandProsePackage(null, pp); } public static String createLearnCommandListEntry(string_id entry, String command) throws InterruptedException { prose_package pp = new prose_package(); pp.stringId = new string_id("pet/pet_ability", "learn_command_list_entry"); pp.actor.set(entry); pp.target.set(command); return " \0" + packOutOfBandProsePackage(null, pp); } public static String getCommandString(obj_id pcd, int command) throws InterruptedException { return getCommandString(getObjVarList(pcd, "ai.pet.command"), command); } public static String getCommandString(obj_var_list commandList, int command) throws InterruptedException { String commandString = " "; if (commandList != null && commandList.hasObjVar("" + command)) { commandString = " - " + commandList.getStringObjVar("" + command); } return commandString; } public static boolean getLearnableCommandList(obj_id pet) throws InterruptedException { obj_id master = getMaster(pet); if (!isIdValid(master)) { return false; } obj_id pcd = callable.getCallableCD(pet); if (!isIdValid(pcd)) { return false; } int manageSkillMod = 100; if (!pet_lib.isDroidPet(pet)) { manageSkillMod = getSkillStatisticModifier(master, "private_creature_management"); } int empathySkillMod = 100; if (!pet_lib.isDroidPet(pet)) { empathySkillMod = getSkillStatisticModifier(master, "private_creature_empathy"); } int trainingSkillMod = 100; if (!pet_lib.isDroidPet(pet)) { trainingSkillMod = getSkillStatisticModifier(master, "private_creature_training"); } Vector commandNameList = new Vector(); commandNameList.setSize(0); Vector commandIndexList = new Vector(); commandIndexList.setSize(0); obj_var_list commandList = getObjVarList(pcd, "ai.pet.command"); commandIndexList = utils.addElement(commandIndexList, 0); commandNameList = utils.addElement(commandNameList, createLearnCommandListHeader(new string_id("obj_attr_n", "pet_command"))); { commandIndexList = utils.addElement(commandIndexList, menu_info_types.PET_RELEASE); commandNameList = utils.addElement(commandNameList, createLearnCommandListEntry(new string_id(MENU_FILE, "menu_release"), getCommandString(commandList, COMMAND_RELEASE))); if (hasSkill(master, "outdoors_creaturehandler_master")) { commandIndexList = utils.addElement(commandIndexList, menu_info_types.PET_TRANSFER); commandNameList = utils.addElement(commandNameList, createLearnCommandListEntry(new string_id(MENU_FILE, "menu_transfer"), getCommandString(commandList, COMMAND_TRANSFER))); } if (pet_lib.isCreaturePet(pet)) { if (empathySkillMod >= 30) { commandIndexList = utils.addElement(commandIndexList, menu_info_types.PET_TRICK_2); commandNameList = utils.addElement(commandNameList, createLearnCommandListEntry(new string_id(MENU_FILE, "menu_trick_2"), getCommandString(commandList, COMMAND_TRICK_2))); } if (empathySkillMod >= 10) { commandIndexList = utils.addElement(commandIndexList, menu_info_types.PET_TRICK_1); commandNameList = utils.addElement(commandNameList, createLearnCommandListEntry(new string_id(MENU_FILE, "menu_trick_1"), getCommandString(commandList, COMMAND_TRICK_1))); } } else if (ai_lib.aiGetSpecies(pet) == 215) { commandIndexList = utils.addElement(commandIndexList, menu_info_types.PET_TRICK_1); commandNameList = utils.addElement(commandNameList, createLearnCommandListEntry(new string_id(MENU_FILE, "menu_recharge_other"), getCommandString(commandList, COMMAND_TRICK_1))); } else if (ai_lib.aiGetSpecies(pet) == 212) { commandIndexList = utils.addElement(commandIndexList, menu_info_types.PET_TRICK_1); commandNameList = utils.addElement(commandNameList, createLearnCommandListEntry(new string_id(MENU_FILE, "menu_solicit_tip"), getCommandString(commandList, COMMAND_TRICK_1))); } if (!pet_lib.isCreaturePet(pet) && pet_lib.isRepairDroid(pet)) { commandIndexList = utils.addElement(commandIndexList, menu_info_types.PET_TRICK_2); commandNameList = utils.addElement(commandNameList, createLearnCommandListEntry(new string_id(MENU_FILE, "menu_repair_other"), getCommandString(commandList, COMMAND_TRICK_2))); } if (manageSkillMod >= 10) { commandIndexList = utils.addElement(commandIndexList, menu_info_types.PET_GROUP); commandNameList = utils.addElement(commandNameList, createLearnCommandListEntry(new string_id(MENU_FILE, "menu_group"), getCommandString(commandList, COMMAND_GROUP))); } if (trainingSkillMod >= 30) { commandIndexList = utils.addElement(commandIndexList, menu_info_types.PET_CLEAR_PATROL_POINTS); commandNameList = utils.addElement(commandNameList, createLearnCommandListEntry(new string_id(MENU_FILE, "menu_clear_patrol_points"), getCommandString(commandList, COMMAND_CLEAR_PATROL_POINTS))); commandIndexList = utils.addElement(commandIndexList, menu_info_types.PET_GET_PATROL_POINT); commandNameList = utils.addElement(commandNameList, createLearnCommandListEntry(new string_id(MENU_FILE, "menu_get_patrol_point"), getCommandString(commandList, COMMAND_SET_PATROL_POINT))); commandIndexList = utils.addElement(commandIndexList, menu_info_types.PET_PATROL); commandNameList = utils.addElement(commandNameList, createLearnCommandListEntry(new string_id(MENU_FILE, "menu_patrol"), getCommandString(commandList, COMMAND_PATROL))); } if (trainingSkillMod >= 40) { commandIndexList = utils.addElement(commandIndexList, menu_info_types.PET_ASSUME_FORMATION_1); commandNameList = utils.addElement(commandNameList, createLearnCommandListEntry(new string_id(MENU_FILE, "menu_assume_formation_1"), getCommandString(commandList, COMMAND_ASSUME_FORMATION_1))); commandIndexList = utils.addElement(commandIndexList, menu_info_types.PET_ASSUME_FORMATION_2); commandNameList = utils.addElement(commandNameList, createLearnCommandListEntry(new string_id(MENU_FILE, "menu_assume_formation_2"), getCommandString(commandList, COMMAND_ASSUME_FORMATION_2))); } if (manageSkillMod >= 30) { commandIndexList = utils.addElement(commandIndexList, menu_info_types.PET_FRIEND); commandNameList = utils.addElement(commandNameList, createLearnCommandListEntry(new string_id(MENU_FILE, "menu_friend"), getCommandString(commandList, COMMAND_FRIEND))); } if (!pet_lib.isDroidPet(pet) || pet_lib.isCombatDroid(pet)) { if (trainingSkillMod >= 20) { commandIndexList = utils.addElement(commandIndexList, menu_info_types.PET_GUARD); commandNameList = utils.addElement(commandNameList, createLearnCommandListEntry(new string_id(MENU_FILE, "menu_guard"), getCommandString(commandList, COMMAND_GUARD))); } commandIndexList = utils.addElement(commandIndexList, menu_info_types.PET_ATTACK); commandNameList = utils.addElement(commandNameList, createLearnCommandListEntry(new string_id(MENU_FILE, "menu_attack"), getCommandString(commandList, COMMAND_ATTACK))); } if (trainingSkillMod >= 10) { commandIndexList = utils.addElement(commandIndexList, menu_info_types.PET_STAY); commandNameList = utils.addElement(commandNameList, createLearnCommandListEntry(new string_id(MENU_FILE, "menu_stay"), getCommandString(commandList, COMMAND_STAY))); } if (manageSkillMod >= 20) { commandIndexList = utils.addElement(commandIndexList, menu_info_types.DICE_ROLL); commandNameList = utils.addElement(commandNameList, createLearnCommandListEntry(new string_id(MENU_FILE, "menu_follow_other"), getCommandString(commandList, COMMAND_FOLLOW_OTHER))); } commandIndexList = utils.addElement(commandIndexList, menu_info_types.PET_FOLLOW); commandNameList = utils.addElement(commandNameList, createLearnCommandListEntry(new string_id(MENU_FILE, "menu_follow"), getCommandString(commandList, COMMAND_FOLLOW))); if (getMountsEnabled() && (!hasObjVar(pcd, "ai.pet.trainedMount"))) { if (pet_lib.canTrainAsMount(pet, master)) { commandIndexList = utils.addElement(commandIndexList, menu_info_types.SERVER_PET_TRAIN_MOUNT); commandNameList = utils.addElement(commandNameList, createLearnCommandListEntry(new string_id(MENU_FILE, "menu_train_mount"), " ")); } } } commandIndexList = utils.addElement(commandIndexList, 0); commandNameList = utils.addElement(commandNameList, createLearnCommandListHeader(new string_id("obj_attr_n", "pet_ability"))); { int[] abilityList = getIntArrayObjVar(pcd, "ai.petAbility.abilityList"); if (abilityList != null && abilityList.length > 0) { for (int i1 : abilityList) { int row = dataTableSearchColumnForInt(i1, "abilityCrc", PET_ABILITY_TABLE); if (row == -1) { continue; } int type = dataTableGetInt(PET_ABILITY_TABLE, row, "type"); if (type == PET_ABILITY_TRIGGERED || type == PET_ABILITY_ACTION) { String abilityName = dataTableGetString(PET_ABILITY_TABLE, row, "abilityName"); commandIndexList = utils.addElement(commandIndexList, i1); commandNameList = utils.addElement(commandNameList, createLearnCommandListEntry(new string_id("pet/pet_ability", abilityName), getCommandString(commandList, i1))); } } } } if (commandIndexList.size() > 0 && commandNameList.size() > 0 && commandIndexList.size() == commandNameList.size()) { utils.setScriptVar(pet, "ai.learnCommand.commandIndexList", commandIndexList); utils.setScriptVar(pet, "ai.learnCommand.commandNameList", commandNameList); return true; } return false; } public static void learnPetCommand(obj_id pet, int command) throws InterruptedException { obj_id master = getMaster(pet); if (!isIdValid(master)) { return; } obj_id pcd = callable.getCallableCD(pet); if (!isIdValid(pcd)) { return; } if (command == 0) { sendSystemMessage(master, new string_id("pet/pet_ability", "learn_command_error")); return; } int manageSkillMod = 100; if (!pet_lib.isDroidPet(pet)) { manageSkillMod = getSkillStatisticModifier(master, "private_creature_management"); } int empathySkillMod = 100; if (!pet_lib.isDroidPet(pet)) { empathySkillMod = getSkillStatisticModifier(master, "private_creature_empathy"); } int trainingSkillMod = 100; if (!pet_lib.isDroidPet(pet)) { trainingSkillMod = getSkillStatisticModifier(master, "private_creature_training"); } if (command > menu_info_types.UNKNOWN && command < menu_info_types.MENU_LAST) { if (command == menu_info_types.SERVER_PET_TRAIN_MOUNT) { if (getMountsEnabled() && (!hasObjVar(pcd, "ai.pet.trainedMount"))) { if (pet_lib.canTrainAsMount(pet, master)) { pet_lib.trainMount(pet, master); } } } else if (command == menu_info_types.PET_FOLLOW) { pet_lib.prepToLearn(pet, pet_lib.COMMAND_FOLLOW); } else if (command == menu_info_types.DICE_ROLL && (manageSkillMod >= 20)) { pet_lib.prepToLearn(pet, pet_lib.COMMAND_FOLLOW_OTHER); } else if (command == menu_info_types.PET_STAY && (trainingSkillMod >= 10)) { pet_lib.prepToLearn(pet, pet_lib.COMMAND_STAY); } else if (command == menu_info_types.PET_RELEASE) { pet_lib.prepToLearn(pet, pet_lib.COMMAND_RELEASE); } else if (command == menu_info_types.PET_TRANSFER && (manageSkillMod >= 40)) { pet_lib.prepToLearn(pet, pet_lib.COMMAND_TRANSFER); } else if (command == menu_info_types.PET_TRICK_4) { pet_lib.prepToLearn(pet, pet_lib.COMMAND_TRICK_4); } else if (command == menu_info_types.PET_TRICK_3) { pet_lib.prepToLearn(pet, pet_lib.COMMAND_TRICK_3); } else if (command == menu_info_types.PET_TRICK_2 && (empathySkillMod >= 30)) { pet_lib.prepToLearn(pet, pet_lib.COMMAND_TRICK_2); } else if (command == menu_info_types.PET_TRICK_1 && (empathySkillMod >= 10)) { pet_lib.prepToLearn(pet, pet_lib.COMMAND_TRICK_1); } else if (command == menu_info_types.PET_GROUP && (manageSkillMod >= 10)) { pet_lib.prepToLearn(pet, pet_lib.COMMAND_GROUP); } else if (command == menu_info_types.PET_CLEAR_PATROL_POINTS && (trainingSkillMod >= 30)) { pet_lib.prepToLearn(pet, pet_lib.COMMAND_CLEAR_PATROL_POINTS); } else if (command == menu_info_types.PET_GET_PATROL_POINT && (trainingSkillMod >= 30)) { pet_lib.prepToLearn(pet, pet_lib.COMMAND_SET_PATROL_POINT); } else if (command == menu_info_types.PET_PATROL && (trainingSkillMod >= 30)) { pet_lib.prepToLearn(pet, pet_lib.COMMAND_PATROL); } else if (command == menu_info_types.PET_ASSUME_FORMATION_1 && (trainingSkillMod >= 40)) { pet_lib.prepToLearn(pet, pet_lib.COMMAND_ASSUME_FORMATION_1); } else if (command == menu_info_types.PET_ASSUME_FORMATION_2 && (trainingSkillMod >= 40)) { pet_lib.prepToLearn(pet, pet_lib.COMMAND_ASSUME_FORMATION_2); } else if (command == menu_info_types.PET_FRIEND && (manageSkillMod >= 30)) { pet_lib.prepToLearn(pet, pet_lib.COMMAND_FRIEND); } else if (command == menu_info_types.PET_GUARD && (trainingSkillMod >= 20)) { pet_lib.prepToLearn(pet, pet_lib.COMMAND_GUARD); } else if (command == menu_info_types.PET_ATTACK) { pet_lib.prepToLearn(pet, pet_lib.COMMAND_ATTACK); } else if (command == menu_info_types.PET_SPECIAL_ATTACK_ONE) { pet_lib.prepToLearn(pet, pet_lib.COMMAND_SPECIALATTACK_ONE); } else if (command == menu_info_types.PET_SPECIAL_ATTACK_TWO) { pet_lib.prepToLearn(pet, pet_lib.COMMAND_SPECIALATTACK_TWO); } } else { pet_lib.prepToLearn(pet, command); } } public static void doTriggeredPetAbility(obj_id pet, obj_id master, int commandNum) throws InterruptedException { int row = dataTableSearchColumnForInt(commandNum, "abilityCrc", PET_ABILITY_TABLE); if (row == -1) { return; } dictionary abilityData = dataTableGetRow(PET_ABILITY_TABLE, row); if (abilityData == null) { return; } int[] actionCost = combat.getActionCost(pet, getWeaponData(getCurrentWeapon(pet)), abilityData); if (combat.canDrainCombatActionAttributes(pet, actionCost)) { int type = abilityData.getInt("type"); if (type == PET_ABILITY_TRIGGERED) { combat.drainCombatActionAttributes(pet, actionCost); String selfBuff = abilityData.getString("selfBuffName"); String targetBuff = abilityData.getString("targetBuffName"); String masterBuff = abilityData.getString("masterBuffName"); int duration = abilityData.getInt("duration"); if (selfBuff != null && !selfBuff.equals("")) { if (duration > 0) { buff.applyBuff(pet, selfBuff, duration); } else { buff.applyBuff(pet, selfBuff); } } if (targetBuff != null && !targetBuff.equals("")) { obj_id target = getTarget(pet); if (isIdValid(target)) { if (duration > 0) { buff.applyBuff(target, targetBuff, duration); } else { buff.applyBuff(target, targetBuff); } } else { doConfusedEmote(pet); } } if (masterBuff != null && !masterBuff.equals("")) { if (isIdValid(master) && exists(master)) { if (duration > 0) { buff.applyBuff(master, masterBuff, duration); } else { buff.applyBuff(master, masterBuff); } } else { doConfusedEmote(pet); } } } else if (type == PET_ABILITY_ACTION) { obj_id target = getTarget(master); String actionName = abilityData.getString("actionName"); int idx = actionName.indexOf('_'); if (idx > 0) { actionName = actionName.substring(0, idx); } if (isIdValid(target) && pvpCanAttack(pet, target) && pvpCanAttack(master, target)) { setObjVar(pet, "ai.combat.forcedAction", actionName); if (!ai_lib.isInCombat(pet)) { startCombat(pet, target); } else { float hate = getMaxHate(pet) + 100; setHate(pet, target, hate); } } else { doConfusedEmote(pet); } } } else { doConfusedEmote(pet); } } public static void doFollowCommand(obj_id pet, obj_id master) throws InterruptedException { if (ai_lib.isInCombat(pet)) { utils.removeScriptVar(pet, "ai.combat.target"); utils.setScriptVar(pet, "petIgnoreAttacks", getGameTime()); utils.setScriptVar(pet, "pet.combatEnded", getGameTime()); stopCombat(pet); } ai_lib.clearPatrolPath(pet); removeObjVar(pet, "ai.inFormation"); removeObjVar(pet, "ai.formationType"); removeObjVar(pet, "ai.formationPosition"); utils.removeScriptVar(pet, "ai.pet.staying"); if (hasObjVar(pet, "ai.wounded")) { removeObjVar(pet, "ai.wounded"); } int myPosture = getPosture(pet); if (myPosture != POSTURE_UPRIGHT && myPosture != POSTURE_SITTING) { stop(pet); removeObjVar(pet, "ai.combat.moveMode"); queueCommand(pet, (-1465754503), pet, "", COMMAND_PRIORITY_FRONT); } petFollow(pet, master); } public static void doFollowOtherCommand(obj_id pet, obj_id master) throws InterruptedException { obj_id target = getIntendedTarget(master); if (isIdValid(target) == false || target == pet) { target = master; } if (ai_lib.isInCombat(pet)) { utils.removeScriptVar(pet, "ai.combat.target"); utils.setScriptVar(pet, "petIgnoreAttacks", getGameTime()); utils.setScriptVar(pet, "pet.combatEnded", getGameTime()); stopCombat(pet); } ai_lib.clearPatrolPath(pet); removeObjVar(pet, "ai.inFormation"); removeObjVar(pet, "ai.formationType"); removeObjVar(pet, "ai.formationPosition"); utils.removeScriptVar(pet, "ai.pet.staying"); setMovementRun(pet); ai_lib.aiFollow(pet, target); } public static void doStayCommand(obj_id pet, obj_id master) throws InterruptedException { ai_lib.clearPatrolPath(pet); removeObjVar(pet, "ai.inFormation"); removeObjVar(pet, "ai.formationType"); removeObjVar(pet, "ai.formationPosition"); setMovementWalk(pet); if (ai_lib.isInCombat(pet)) { utils.removeScriptVar(pet, "ai.combat.target"); utils.setScriptVar(pet, "petIgnoreAttacks", getGameTime()); utils.setScriptVar(pet, "pet.combatEnded", getGameTime()); stopCombat(pet); } utils.setScriptVar(pet, "ai.pet.staying", true); ai_lib.aiStopFollowing(pet); location myLoc = getLocation(pet); setHomeLocation(pet, myLoc); setMovementWalk(pet); if (ai_lib.isMonster(pet)) { doAnimationAction(pet, "vocalize"); ai_lib.setDefaultCalmMood(pet, "bored"); } else if (pet_lib.isDroidPet(pet)) { doAnimationAction(pet, "emt_nod_head_once"); } else { doAnimationAction(pet, "salute1"); } } public static void doGuardCommand(obj_id pet, obj_id master) throws InterruptedException { if (!isMob(master) && !isPlayer(master)) { doConfusedEmote(pet); return; } utils.removeScriptVar(pet, "ai.pet.staying"); utils.setScriptVar(pet, "ai.pet.guarding", master); setWantSawAttackTriggers(pet, true); } public static boolean isGuarding(obj_id pet, obj_id target) throws InterruptedException { if (!isIdValid(pet) || !exists(pet) || !isIdValid(target) || !exists(target) || !hasMaster(pet)) { return false; } obj_id guarding = utils.getObjIdScriptVar(pet, "ai.pet.guarding"); if (isIdValid(guarding) && exists(guarding)) { return (guarding == target); } return false; } public static void doFriendCommand(obj_id pet, obj_id master) throws InterruptedException { obj_id target = getIntendedTarget(master); if (isIdValid(target) == false || isPlayer(target) == false) { doConfusedEmote(pet); return; } Vector friendList = new Vector(); friendList.setSize(0); if (hasObjVar(pet, "ai.pet.friendList")) { friendList = getResizeableObjIdArrayObjVar(pet, "ai.pet.friendList"); } int indexNum = utils.getElementPositionInArray(friendList, target); if (indexNum != -1) { utils.removeElementAt(friendList, indexNum); return; } if (friendList.size() > MAX_NUMBER_OF_FRIENDS) { utils.removeElementAt(friendList, 0); } friendList = utils.addElement(friendList, target); setObjVar(pet, "ai.pet.friendList", friendList); } public static boolean isFriend(obj_id pet, obj_id target) throws InterruptedException { obj_id master = getMaster(pet); if (!isIdValid(master)) { return false; } if (master == target) { return true; } if (!hasObjVar(pet, "ai.pet.friendList")) { return false; } obj_id[] friendList = getObjIdArrayObjVar(pet, "ai.pet.friendList"); int indexNum = utils.getElementPositionInArray(friendList, target); if (indexNum != -1) { return true; } else { return false; } } public static void doConfusedEmote(obj_id pet) throws InterruptedException { if (!pet_lib.isSpeakingPet(pet)) { showFlyText(pet, new string_id("npc_reaction/flytext", "alert"), 3.0f, colors.COPPER); doAnimationAction(pet, "emt_stand_confused"); } else { String myStringFile = "hireling/hireling"; if (hasObjVar(pet, "ai.diction")) { String myDiction = getStringObjVar(pet, "ai.diction"); if (myDiction != null && !myDiction.equals("townperson")) { myStringFile = "hireling/hireling" + "_" + myDiction; } } chat.chat(pet, chat.CHAT_COMPLAIN, chat.MOOD_CONFUSED, new string_id(myStringFile, "confused")); } } public static void doAttackCommand(obj_id pet, obj_id master) throws InterruptedException { if (!isIdValid(master)) { return; } utils.removeScriptVar(pet, "petIgnoreAttacks"); obj_id target = getIntendedTarget(master); if (isIdValid(target) == false || target == pet) { doConfusedEmote(pet); return; } if (!pvpCanAttack(pet, target)) { doConfusedEmote(pet); return; } if (!pvpCanAttack(master, target)) { doConfusedEmote(pet); return; } if (master.isLoaded()) { setHomeLocation(pet, getLocation(master)); } else if (pet.isLoaded()) { setHomeLocation(pet, getLocation(pet)); } utils.removeScriptVar(pet, "ai.pet.staying"); chat.setBadMood(pet); if (!ai_lib.isInCombat(pet)) { if (!pet_lib.cancelAttackDueToFactionalRestrictions(pet, target)) { startCombat(pet, target); utils.setScriptVar(pet, "ai.combat.target", target); } } else if (!pet_lib.cancelAttackDueToFactionalRestrictions(pet, target)) { utils.setScriptVar(pet, "ai.combat.target", target); float maxHate = getMaxHate(pet); setHate(pet, target, maxHate + 5000); } } public static void doPatrol(obj_id pet, obj_id master) throws InterruptedException { if (!hasObjVar(pet, OBJVAR_PET_PATROL_POINTS)) { doConfusedEmote(pet); } else { removeObjVar(pet, "ai.inFormation"); removeObjVar(pet, "ai.formationType"); removeObjVar(pet, "ai.formationPosition"); location[] patrolLoc = getLocationArrayObjVar(pet, OBJVAR_PET_PATROL_POINTS); if (patrolLoc != null) { ai_lib.setPatrolPath(pet, patrolLoc); } utils.removeScriptVar(pet, "ai.pet.staying"); } } public static void doSetPatrolPoint(obj_id pet, obj_id master) throws InterruptedException { location[] patrolLoc = getLocationArrayObjVar(pet, OBJVAR_PET_PATROL_POINTS); if (patrolLoc == null) { patrolLoc = new location[1]; } else if (patrolLoc.length < MAX_WAYPOINTS) { location[] temp = new location[patrolLoc.length + 1]; for (int i = 0; i < patrolLoc.length; ++i) { temp[i] = patrolLoc[i]; } patrolLoc = temp; } else { doConfusedEmote(pet); return; } patrolLoc[patrolLoc.length - 1] = getLocation(master); setObjVar(pet, OBJVAR_PET_PATROL_POINTS, patrolLoc); sendSystemMessage(master, SID_SYS_PATROL_ADDED); } public static void doClearPatrolPoints(obj_id pet, obj_id master) throws InterruptedException { if (hasObjVar(pet, OBJVAR_PET_PATROL_POINTS)) { removeObjVar(pet, OBJVAR_PET_PATROL_POINTS); sendSystemMessage(master, SID_SYS_PATROL_REMOVED); ai_lib.clearPatrolPath(pet); stop(pet); messageTo(pet, "resumeDefaultCalmBehavior", null, 1, false); } else { doConfusedEmote(pet); } } public static void doPetFormation(obj_id pet, obj_id master, int formationType) throws InterruptedException { int position = 0; switch (callable.getCallableType(pet)) { case callable.CALLABLE_TYPE_COMBAT_OTHER: position = 0; break; case callable.CALLABLE_TYPE_COMBAT_PET: position = 1; break; case callable.CALLABLE_TYPE_FAMILIAR: position = 2; break; default: return; } setMovementRun(pet); ai_lib.followInFormation(pet, master, formationType, position); utils.removeScriptVar(pet, "ai.pet.staying"); } public static void doPetRelease(obj_id pet) throws InterruptedException { obj_id master = getMaster(pet); CustomerServiceLog("Pets", "*Pet Release: (" + master + " sid:" + getPlayerObject(master) + ") " + getName(master) + ": has requested that their pet, " + pet + getName(pet) + " be released. Script is attempting to do so."); if (isIdValid(master) && !wasInCombatRecently(pet, master, true)) { ai_lib.clearPatrolPath(pet); removeObjVar(pet, "ai.inFormation"); removeObjVar(pet, "ai.formationType"); removeObjVar(pet, "ai.formationPosition"); releasePet(pet); } } public static void doPetTransfer(obj_id pet, obj_id master) throws InterruptedException { obj_id target = getIntendedTarget(master); if (isIdValid(target) == false || !isPlayer(target)) { doConfusedEmote(pet); return; } if (!hasScript(target, "ai.pet_master")) { attachScript(target, "ai.pet_master"); } int petType = pet_lib.getPetType(pet); String creatureName = getCreatureName(pet); if (creatureName == null || creatureName.equals("")) { destroyObject(pet); return; } int niche = ai_lib.aiGetNiche(pet); if (niche == NICHE_NPC || niche == NICHE_VEHICLE) { sendSystemMessage(master, new string_id("pet/pet_menu", "bad_type")); sendSystemMessage(target, new string_id("pet/pet_menu", "bad_type")); return; } if (hasMaxPets(target, petType)) { sendSystemMessage(master, new string_id("pet/pet_menu", "targ_too_many")); sendSystemMessage(target, SID_SYS_TOO_MANY_PETS); doConfusedEmote(pet); return; } if (hasMaxStoredPetsOfType(target, petType)) { sendSystemMessage(master, new string_id("pet/pet_menu", "targ_too_many_stored")); sendSystemMessage(target, SID_SYS_TOO_MANY_STORED_PETS); doConfusedEmote(pet); return; } int petLevel = getLevel(pet); if (!pet_lib.canControlPetsOfLevel(target, petType, petLevel, creatureName)) { sendSystemMessage(master, new string_id("pet/pet_menu", "no_chance")); doConfusedEmote(pet); return; } obj_id pcd = null; if (callable.hasCallableCD(pet)) { pcd = callable.getCallableCD(pet); } obj_id[] petArray = null; if (isIdValid(pcd) && exists(pcd)) { petArray = new obj_id[2]; petArray[0] = pet; petArray[1] = pcd; } else { petArray = new obj_id[1]; petArray[0] = pet; } obj_id notradeItem = utils.findNoTradeItem(petArray, false); if (isIdValid(notradeItem)) { prose_package pp = new prose_package(); pp.stringId = SID_PET_HAS_NOTRADE; pp.target.id = notradeItem; sendSystemMessageProse(master, pp); doConfusedEmote(pet); return; } obj_id group = getGroupObject(pet); if (isIdValid(group)) { queueCommand(pet, (1348589140), group, "", COMMAND_PRIORITY_IMMEDIATE); } obj_id controller = null; if (callable.hasCallableCD(pet)) { controller = callable.getCallableCD(pet); obj_id newMasterPad = utils.getPlayerDatapad(target); if (!isIdValid(controller) || !isIdValid(newMasterPad)) { sendSystemMessage(master, new string_id("pet/pet_menu", "targ_too_many_stored")); sendSystemMessage(target, SID_SYS_TOO_MANY_STORED_PETS); doConfusedEmote(pet); return; } if (!putIn(controller, newMasterPad)) { sendSystemMessage(master, new string_id("pet/pet_menu", "targ_too_many_stored")); sendSystemMessage(target, SID_SYS_TOO_MANY_STORED_PETS); doConfusedEmote(pet); CustomerServiceLog("Pets", "***Pet Transfer: (" + master + " sid:" + getPlayerObject(master) + ") " + getName(master) + ": Pet FAILED to transfer " + target + " sid:" + getPlayerObject(target) + ") " + getName(target)); return; } } sendSystemMessage(master, SID_SYS_XFER_SUCCESS); sendSystemMessage(target, SID_SYS_XFER_SUCCESS); CustomerServiceLog("Pets", "***Pet Transferrer: Player " + getName(master) + "(" + master + ") StationId(" + getPlayerObject(master) + ") successfully transfered PetControlDevice " + getName(controller) + " (" + controller + ") of template: " + getTemplateName(controller) + " to receiving player " + getName(target) + "(" + target + ") StationId(" + getPlayerObject(target) + ")"); } public static void doStupidPetTrick(obj_id pet, obj_id master, int trickNum) throws InterruptedException { if (ai_lib.aiGetSpecies(pet) == SPECIES_POWERDROID && trickNum == COMMAND_TRICK_1) { rechargeOtherDroid(pet, master); return; } if (ai_lib.aiGetSpecies(pet) == SPECIES_POWERDROID && trickNum == COMMAND_TRICK_1) { solicitTipsForMaster(pet, master); return; } if (isRepairDroid(pet) && trickNum == COMMAND_TRICK_2) { repairOtherDroid(pet, master); return; } int myPosture = getPosture(pet); if (myPosture != POSTURE_UPRIGHT && myPosture != POSTURE_SITTING) { stop(pet); removeObjVar(pet, "ai.combat.moveMode"); queueCommand(pet, (-1465754503), pet, "", COMMAND_PRIORITY_FRONT); dictionary params = new dictionary(); params.put("master", master); params.put("trickNum", trickNum); messageTo(pet, "resumePetTrick", params, 2, false); return; } int action = getAttrib(master, ACTION); int actionCost = 100; if (action < actionCost) { sendSystemMessage(master, SID_SYS_CANT_TRICK); return; } drainAttributes(master, actionCost, 0); stop(pet); float maxHealing = 0.2f; switch (trickNum) { case COMMAND_TRICK_1: if (myPosture == POSTURE_SITTING) { doAnimationAction(pet, "sit_trick_1"); } else { doAnimationAction(pet, "trick_1"); } break; case COMMAND_TRICK_2: if (myPosture == POSTURE_SITTING) { doAnimationAction(pet, "sit_trick_2"); } else { doAnimationAction(pet, "trick_2"); } maxHealing = 0.4f; break; } healShockWound(pet, getShockWound(pet)); attribute[] maxAttribs = getUnmodifiedMaxAttribs(pet); int healAmount = (int)(maxAttribs[MIND].getValue() * maxHealing); addAttribModifier(pet, maxAttribs[MIND].getType(), healAmount, 0, 0, MOD_POOL); if (getBehavior(pet) == BEHAVIOR_CALM) { messageTo(pet, "resumeDefaultCalmBehavior", null, 8, false); } } public static void rechargeOtherDroid(obj_id pet, obj_id master) throws InterruptedException { obj_id target = getIntendedTarget(master); if (isIdValid(target) == false || !isDroidPet(target)) { doConfusedEmote(pet); return; } if (pet == target) { doConfusedEmote(pet); return; } if (getDistance(pet, target) > 10.0f) { doConfusedEmote(pet); return; } follow(pet, target, 1, 2); color textColor = colors.PURPLE; showFlyTextPrivate(pet, master, new string_id("npc_reaction/flytext", "recharged"), 0.75f, textColor.getR(), textColor.getG(), textColor.getB(), true); obj_id targetPetControlDevice = callable.getCallableCD(target); removeObjVar(targetPetControlDevice, "ai.pet.powerLevel"); healShockWound(target, getShockWound(target)); if (getBehavior(pet) == BEHAVIOR_CALM) { messageTo(pet, "resumeDefaultCalmBehavior", null, 8, false); } obj_id petControlDevice = callable.getCallableCD(pet); int powerLevel = getIntObjVar(petControlDevice, "ai.pet.powerLevel"); powerLevel++; if (powerLevel == pet_lib.OUT_OF_POWER) { messageTo(pet, "powerWarningText", null, 30, false); } if (powerLevel < pet_lib.OUT_OF_POWER) { setObjVar(petControlDevice, "ai.pet.powerLevel", powerLevel); } else { setObjVar(petControlDevice, "ai.pet.powerLevel", (pet_lib.OUT_OF_POWER + 1)); } } public static void repairOtherDroid(obj_id pet, obj_id master) throws InterruptedException { obj_id target = getIntendedTarget(master); if (isIdValid(target) == false || !isDroidPet(target)) { doConfusedEmote(pet); return; } if (pet == target) { doConfusedEmote(pet); return; } if (getDistance(pet, target) > 10.0f) { doConfusedEmote(pet); return; } follow(pet, target, 1, 2); showFlyText(target, new string_id("npc_reaction/flytext", "repaired"), 0.75f, colors.PURPLE); healShockWound(target, getShockWound(target)); if (getBehavior(pet) == BEHAVIOR_CALM) { messageTo(pet, "resumeDefaultCalmBehavior", null, 8, false); } } public static void solicitTipsForMaster(obj_id pet, obj_id master) throws InterruptedException { } public static void doPetGroup(obj_id pet, obj_id master) throws InterruptedException { if (group.isGrouped(pet)) { obj_id group = getGroupObject(pet); if (isIdValid(group)) { queueCommand(pet, (1348589140), group, "", COMMAND_PRIORITY_DEFAULT); } } else { obj_id groupLeader = group.getLeader(master); if (!isIdValid(groupLeader) || !exists(groupLeader)) { groupLeader = master; } queueCommand(groupLeader, (-2007999144), pet, "", COMMAND_PRIORITY_DEFAULT); messageTo(pet, "handleGroupInvite", null, 2, false); sendSystemMessage(master, SID_PET_INVITED); } } public static void checkForName(obj_id pet, obj_id pcd) throws InterruptedException { if (!isCreaturePet(pet) && !isDroidPet(pet)) { return; } obj_id master = getMaster(pet); if (!isIdValid(master)) { return; } Vector nameList = new Vector(); nameList.setSize(0); Vector nameCount = new Vector(); nameCount.setSize(0); obj_var_list commandList = getObjVarList(pcd, "ai.pet.command"); if (commandList != null && commandList.getNumItems() > 0) { int numItems = commandList.getNumItems(); for (int i = 0; i < numItems; i++) { obj_var ov = commandList.getObjVar(i); int commandNum = Integer.parseInt(ov.getName()); String commandName = ov.getStringData(); if (commandName.contains(" ")) { String name = commandName.substring(0, commandName.indexOf(" ")); int indexNum = utils.getElementPositionInArray(nameList, name); if (indexNum == -1) { nameList = utils.addElement(nameList, name); nameCount = utils.addElement(nameCount, 0); } else { nameCount.set(indexNum, (Integer) nameCount.get(indexNum) + 1); } } } } String highName = new String(); int highCount = 0; for (int i = 0; i < nameList.size(); i++) { if ((Integer) nameCount.get(i) > highCount) { highName = ((String)nameList.get(i)); highCount = (Integer) nameCount.get(i); } } if (highCount < 2 || highName == null) { return; } if (highName.length() < 2) { highName = highName.toUpperCase(); } else { String firstLetter = highName.substring(0, 1); firstLetter = firstLetter.toUpperCase(); String theName = highName.substring(1); highName = firstLetter + theName; } String oldName = getName(pet); int suffix = oldName.indexOf(")"); if (suffix > 2) { oldName = oldName.substring(1, suffix); } String learnedName = "(" + highName + ")"; if (highCount > 2 && !learnedName.equals(oldName) && !oldName.equals(highName) && isNameReserved(highName) == false) { setName(pet, learnedName); chat.thinkTo(pet, master, "?"); } } public static void feedPet(obj_id pet, obj_id master) throws InterruptedException { if (isDroidPet(pet)) { if (!eatBattery(master)) { color textColor = colors.YELLOW; showFlyTextPrivate(pet, master, new string_id("npc_reaction/flytext", "nobattery"), 0.75f, textColor.getR(), textColor.getG(), textColor.getB(), true); return; } color textColor = colors.MEDIUMPURPLE; showFlyTextPrivate(pet, master, new string_id("npc_reaction/flytext", "recharged"), 0.75f, textColor.getR(), textColor.getG(), textColor.getB(), true); obj_id petControlDevice = callable.getCallableCD(pet); removeObjVar(petControlDevice, "ai.pet.powerLevel"); } else { if (!isWounded(pet)) { color textColor = colors.YELLOW; showFlyTextPrivate(pet, master, new string_id("npc_reaction/flytext", "nothungry"), 0.75f, textColor.getR(), textColor.getG(), textColor.getB(), true); return; } if (!eatFood(master)) { color textColor = colors.YELLOW; showFlyTextPrivate(pet, master, new string_id("npc_reaction/flytext", "nofood"), 0.75f, textColor.getR(), textColor.getG(), textColor.getB(), true); return; } } stop(pet); faceTo(pet, master); faceTo(master, pet); doAnimationAction(master, "manipulate_medium"); if (isCreaturePet(pet)) { doAnimationAction(pet, "eat"); } healShockWound(pet, getShockWound(pet)); if (getBehavior(pet) == BEHAVIOR_CALM) { messageTo(pet, "resumeDefaultCalmBehavior", null, 8, false); } } public static boolean isWounded(obj_id pet) throws InterruptedException { if (getShockWound(pet) > 0) { return true; } return false; } public static boolean eatFood(obj_id master) throws InterruptedException { obj_id inv = utils.getInventoryContainer(master); if (!isIdValid(inv) || !exists(inv)) { return false; } obj_id[] contents = getContents(inv); for (obj_id content : contents) { int got = getGameObjectType(content); if (isGameObjectTypeOf(got, GOT_misc_food)) { consumable.decrementCharges(content, master); return true; } } return false; } public static boolean eatBattery(obj_id master) throws InterruptedException { obj_id inv = utils.getInventoryContainer(master); if (!isIdValid(inv) || !exists(inv)) { return false; } obj_id[] contents = getContents(inv); for (obj_id content : contents) { if ((getTemplateName(content)).equals(BATTERY)) { consumable.decrementCharges(content, master); return true; } } return false; } public static void storePet(obj_id pet) throws InterruptedException { storePet(pet, null); } public static void storePet(obj_id pet, obj_id master) throws InterruptedException { if (!isIdValid(pet) || !exists(pet)) { return; } obj_id petControlDevice = callable.getCallableCD(pet); if (isIdValid(petControlDevice) && petControlDevice.isLoaded()) { obj_id currentPet = callable.getCDCallable(petControlDevice); if (isIdValid(currentPet) && currentPet == pet && currentPet.isLoaded()) { savePetInfo(currentPet, petControlDevice); setObjVar(petControlDevice, "pet.timeStored", getGameTime()); callable.setCDCallable(petControlDevice, null); setCount(petControlDevice, 0); } } messageTo(pet, "handlePackRequest", null, 0, false); } public static boolean hasMaxStoredPetsOfType(obj_id player, int petType) throws InterruptedException { if (!isIdValid(player)) { return true; } int maxStored = getMaxStoredPetsOfType(player, petType); int numStored = getNumStoredPetsOfType(player, petType); return (numStored >= maxStored); } public static int getNumStoredPetsOfType(obj_id player, int petType) throws InterruptedException { obj_id datapad = utils.getPlayerDatapad(player); if (!isIdValid(datapad)) { return 0; } obj_id[] myStuff = getContents(datapad); if (myStuff == null) { return 0; } int callableType = callable.CALLABLE_TYPE_UNKNOWN; switch (petType) { case PET_TYPE_NON_AGGRO: case PET_TYPE_AGGRO: case PET_TYPE_NPC: case PET_TYPE_DROID: callableType = callable.CALLABLE_TYPE_COMBAT_PET; break; case PET_TYPE_FAMILIAR: callableType = callable.CALLABLE_TYPE_FAMILIAR; break; case PET_TYPE_MOUNT: callableType = callable.CALLABLE_TYPE_RIDEABLE; break; default: break; } if (callableType == callable.CALLABLE_TYPE_UNKNOWN) { return 0; } return callable.getNumStoredCDByType(player, callableType); } public static int getMaxStoredPetsOfType(obj_id master, int petType) throws InterruptedException { if (!isIdValid(master) || !exists(master)) { return 0; } switch (petType) { case PET_TYPE_NON_AGGRO: case PET_TYPE_AGGRO: case PET_TYPE_NPC: case PET_TYPE_DROID: return callable.MAX_STORED_COMBAT_PETS; case PET_TYPE_FAMILIAR: return callable.MAX_STORED_FAMILIARS; case PET_TYPE_MOUNT: return callable.getMaxAllowedStoredRideables(master); } return 0; } public static int getMaxStoredPets(obj_id pet) throws InterruptedException { obj_id master = getMaster(pet); if (!isIdValid(master)) { return 1; } int petType = pet_lib.getPetType(pet); return getMaxStoredPetsOfType(master, petType); } public static boolean isPet(obj_id npc) throws InterruptedException { if (isValidId(npc) && exists(npc)) { return hasObjVar(npc, "ai.pet"); } else { return false; } } public static boolean isCreaturePet(obj_id npc) throws InterruptedException { return (ai_lib.isMonster(npc) && hasObjVar(npc, "ai.pet")); } public static boolean isNpcPet(obj_id npc) throws InterruptedException { int niche = ai_lib.aiGetNiche(npc); if (niche == NICHE_VEHICLE) { niche = NICHE_NPC; } return (niche == NICHE_NPC && hasObjVar(npc, "ai.pet")); } public static boolean isVehiclePet(obj_id npc) throws InterruptedException { int niche = ai_lib.aiGetNiche(npc); return (niche == NICHE_VEHICLE && hasObjVar(npc, "ai.pet")); } public static boolean isMyPet(obj_id npc, obj_id player) throws InterruptedException { if (!isIdValid(npc) || !isIdValid(player) || !hasMaster(npc)) { return false; } return (getMaster(npc) == player); } public static boolean isDroidPet(obj_id npc) throws InterruptedException { int gotType = getGameObjectType(npc); int niche = ai_lib.aiGetNiche(npc); if (gotType == GOT_data_pet_control_device || gotType == GOT_data_droid_control_device) { if (hasObjVar(npc, "pet.creatureName")) { String creatureName = getStringObjVar(npc, "pet.creatureName"); int row = dataTableSearchColumnForString(creatureName, "creatureName", create.CREATURE_TABLE); if (row >= 0) { dictionary dict = dataTableGetRow(create.CREATURE_TABLE, row); niche = dict.getInt("niche"); } } } return ((niche == NICHE_DROID || niche == NICHE_ANDROID) && hasObjVar(npc, "ai.pet")); } public static boolean isSpeakingPet(obj_id npc) throws InterruptedException { if (pet_lib.getPetType(npc) == pet_lib.PET_TYPE_FAMILIAR) { return false; } if (isNpcPet(npc) || ai_lib.aiGetNiche(npc) == NICHE_VEHICLE) { return true; } if (isDroidPet(npc) && ai_lib.aiGetSpecies(npc) != -1) { int speaking = dataTableGetInt("datatables/ai/species.iff", ai_lib.aiGetSpecies(npc), "Speaking"); if (speaking == 1) { return true; } } return false; } public static boolean hasContainer(obj_id pet) throws InterruptedException { if (isDroidPet(pet)) { return (hasObjVar(pet, "ai.pet.hasContainer")); } return false; } public static boolean hasDatapad(obj_id pet) throws InterruptedException { if (isDroidPet(pet)) { return (hasObjVar(pet, "ai.pet.hasDatapad")); } return false; } public static boolean isCombatDroid(obj_id npc) throws InterruptedException { obj_id petControlDevice = callable.getCallableCD(npc); if (!isIdValid(npc) && exists(petControlDevice)) { return false; } if (ai_lib.aiGetNiche(npc) != NICHE_DROID && ai_lib.aiGetNiche(npc) != NICHE_ANDROID) { return false; } if (hasObjVar(petControlDevice, "pet.combatDroid")) { return true; } else if (hasObjVar(petControlDevice, "pet.creatureName")) { String creatureName = getStringObjVar(petControlDevice, "pet.creatureName"); if (creatureName.equals(PROBOT_DROID_NAME) || creatureName.equals(DZ70_DROID_NAME)) { if (hasObjVar(petControlDevice, "pet.nonCombatDroid")) { return false; } else { return true; } } return false; } else { return false; } } public static boolean isCombatDroidPCD(obj_id petControlDevice) throws InterruptedException { if (!isIdValid(petControlDevice)) { return false; } if (hasObjVar(petControlDevice, "pet.combatDroid")) { return true; } else if (hasObjVar(petControlDevice, "pet.creatureName")) { String creatureName = getStringObjVar(petControlDevice, "pet.creatureName"); if (creatureName.equals(PROBOT_DROID_NAME) || creatureName.equals(DZ70_DROID_NAME)) { if (hasObjVar(petControlDevice, "pet.nonCombatDroid")) { return false; } else { return true; } } return false; } else { return false; } } public static void openPetContainer(obj_id pet, obj_id master) throws InterruptedException { stop(pet); obj_id petControlDevice = callable.getCallableCD(pet); obj_id petInv = utils.getInventoryContainer(petControlDevice); if (!isIdValid(petInv) || !exists(petInv) || !isIdValid(master) || !exists(master)) { return; } setOwner(petInv, master); utils.requestContainerOpen(master, petInv); } public static void openPetDatapad(obj_id pet, obj_id master) throws InterruptedException { stop(pet); obj_id petControlDevice = callable.getCallableCD(pet); obj_id petDPad = utils.getDatapad(petControlDevice); if (!isIdValid(petDPad) || !exists(petDPad) || !isIdValid(master) || !exists(master)) { return; } if (isLowOnPower(pet)) { sendSystemMessage(master, new string_id("pet/pet_menu", "droid_out_of_power")); return; } setOwner(petDPad, master); utils.requestContainerOpen(master, petDPad); } public static boolean isLowOnPower(obj_id pet) throws InterruptedException { obj_id petControlDevice = callable.getCallableCD(pet); int powerLevel = getIntObjVar(petControlDevice, "ai.pet.powerLevel"); if (powerLevel >= OUT_OF_POWER) { return true; } return false; } public static boolean findMaster(obj_id pet) throws InterruptedException { if (!isIdValid(pet) || !exists(pet) || !pet.isLoaded() || !hasMaster(pet)) { return false; } obj_id master = getMaster(pet); if (!isIdValid(master) || !exists(master) || !master.isLoaded()) { return false; } return true; } public static void removeFromList(obj_id master, obj_id pet) throws InterruptedException { if (!isIdValid(master) || !exists(master) || !isIdValid(pet) || !exists(pet)) { return; } if (hasObjVar(master, "pet.petList")) { removeObjVar(master, "pet.petList"); } callable.setCallable(master, null, callable.getCallableType(pet)); } public static void addToPetList(obj_id master, obj_id pet) throws InterruptedException { if (!isIdValid(master) || !exists(master) || !isIdValid(pet) || !exists(pet)) { return; } if (hasObjVar(master, "pet.petList")) { removeObjVar(master, "pet.petList"); } if (callable.hasCallable(master, callable.getCallableType(pet), pet)) { callable.storeCallable(master, callable.getCallable(master, callable.getCallableType(pet))); } callable.setCallable(master, pet, callable.getCallableType(pet)); } public static void storeAllPets(obj_id master) throws InterruptedException { callable.storeCallables(master); } public static boolean isNearMedicalDroid(obj_id master, float range) throws InterruptedException { obj_id[] critters = getCreaturesInRange(getLocation(master), range); if (critters == null || critters.length <= 0) { return false; } for (obj_id critter : critters) { if (hasObjVar(critter, "medpower")) { if (isMyPet(critter, master) && isLowOnPower(critter) == false) { return true; } } } return false; } public static float getMedicalDroidMod(obj_id master, float range) throws InterruptedException { float medMod = 1.0f; obj_id[] critters = getCreaturesInRange(getLocation(master), range); if (critters == null || critters.length <= 0) { return medMod; } for (obj_id critter : critters) { if (hasObjVar(critter, "medpower")) { if (isMyPet(critter, master) && isLowOnPower(critter) == false) { medMod = getFloatObjVar(critter, "medpower"); return medMod; } } } return medMod; } public static void setupDefaultCommands(obj_id pet) throws InterruptedException { if (utils.hasScriptVar(pet, "ai.pet.commandList")) { return; } obj_id petControlDevice = callable.getCallableCD(pet); int restrictCommands = getIntObjVar(pet, "pet.petRestriction"); dictionary petCommandList = utils.getDictionaryScriptVar(pet, "ai.pet.commandList"); if (petCommandList == null) { petCommandList = new dictionary(); } setObjVar(petControlDevice, "ai.pet.command." + COMMAND_FOLLOW, "follow"); petCommandList.put("follow", COMMAND_FOLLOW); setObjVar(petControlDevice, "ai.pet.command." + COMMAND_STAY, "stay"); petCommandList.put("stay", COMMAND_STAY); if (!isNewPlayerHelperDroid(pet)) { if (restrictCommands > 0) { setObjVar(petControlDevice, "ai.pet.command." + COMMAND_PATROL, "patrol"); petCommandList.put("patrol", COMMAND_PATROL); setObjVar(petControlDevice, "ai.pet.command." + COMMAND_SET_PATROL_POINT, "get patrol point"); petCommandList.put("get patrol point", COMMAND_SET_PATROL_POINT); setObjVar(petControlDevice, "ai.pet.command." + COMMAND_CLEAR_PATROL_POINTS, "clear patrol point"); petCommandList.put("clear patrol point", COMMAND_CLEAR_PATROL_POINTS); setObjVar(petControlDevice, "ai.pet.command." + COMMAND_ASSUME_FORMATION_1, "column formation"); petCommandList.put("column formation", COMMAND_ASSUME_FORMATION_1); setObjVar(petControlDevice, "ai.pet.command." + COMMAND_ASSUME_FORMATION_2, "wedge formation"); petCommandList.put("wedge formation", COMMAND_ASSUME_FORMATION_2); setObjVar(petControlDevice, "ai.pet.command." + COMMAND_FOLLOW_OTHER, "chase"); petCommandList.put("chase", COMMAND_FOLLOW_OTHER); setObjVar(petControlDevice, "ai.pet.command." + COMMAND_FRIEND, "friend"); petCommandList.put("friend", COMMAND_FRIEND); setObjVar(petControlDevice, "ai.pet.command." + COMMAND_TRANSFER, "transfer"); petCommandList.put("transfer", COMMAND_TRANSFER); } setObjVar(petControlDevice, "ai.pet.command." + COMMAND_RELEASE, "release"); petCommandList.put("release", COMMAND_RELEASE); setObjVar(petControlDevice, "ai.pet.command." + COMMAND_GROUP, "group"); petCommandList.put("group", COMMAND_GROUP); } if (pet_lib.isRepairDroid(pet)) { setObjVar(petControlDevice, "ai.pet.command." + COMMAND_TRICK_2, "repair"); petCommandList.put("repair", COMMAND_TRICK_2); } if (isCombatDroid(pet) || !isDroidPet(pet)) { setObjVar(petControlDevice, "ai.pet.command." + COMMAND_ATTACK, "attack"); petCommandList.put("attack", COMMAND_ATTACK); setObjVar(petControlDevice, "ai.pet.command." + COMMAND_GUARD, "guard"); petCommandList.put("guard", COMMAND_GUARD); } utils.setScriptVar(pet, "ai.pet.commandList", petCommandList); setObjVar(pet, "alreadyTrained", true); } public static void setupOfficerPetCommands(obj_id pet) throws InterruptedException { obj_id petControlDevice = callable.getCallableCD(pet); dictionary petCommandList = utils.getDictionaryScriptVar(pet, "ai.pet.commandList"); if (petCommandList == null) { petCommandList = new dictionary(); } setObjVar(petControlDevice, "ai.pet.command." + COMMAND_ATTACK, "attack"); petCommandList.put("attack", COMMAND_ATTACK); setObjVar(petControlDevice, "ai.pet.command." + COMMAND_GUARD, "guard"); petCommandList.put("guard", COMMAND_GUARD); setObjVar(petControlDevice, "ai.pet.command." + COMMAND_FOLLOW, "follow"); petCommandList.put("follow", COMMAND_FOLLOW); setObjVar(petControlDevice, "ai.pet.command." + COMMAND_STAY, "stay"); petCommandList.put("stay", COMMAND_STAY); setObjVar(petControlDevice, "ai.pet.command." + COMMAND_RELEASE, "release"); petCommandList.put("release", COMMAND_RELEASE); setObjVar(petControlDevice, "ai.pet.command." + COMMAND_GROUP, "group"); petCommandList.put("group", COMMAND_GROUP); utils.setScriptVar(pet, "ai.pet.commandList", petCommandList); setObjVar(pet, "alreadyTrained", true); return; } public static void markExpansionPets(obj_id petControlDevice, obj_id pet) throws InterruptedException { if (hasObjVar(pet, "storageUnlimited")) { setObjVar(petControlDevice, "storageUnlimited", 1); } } public static boolean isExpansionPet(obj_id petControlDevice) throws InterruptedException { if (hasObjVar(petControlDevice, "storageUnlimited")) { return true; } return false; } public static boolean isMountPcd(obj_id pcd) throws InterruptedException { if (hasObjVar(pcd, "ai.pet.trainedMount")) { return true; } return false; } public static boolean isPetType(obj_id pcd, int petType) throws InterruptedException { int pcdsPetType = getPcdPetType(pcd); if (petType == pcdsPetType) { return true; } return false; } public static int getPcdPetType(obj_id pcd) throws InterruptedException { if (hasObjVar(pcd, "ai.pet.type")) { return getIntObjVar(pcd, "ai.pet.type"); } return -1; } public static int getPetType(obj_id pet) throws InterruptedException { return getPetType(pet, obj_id.NULL_ID); } public static int getPetType(obj_id pet, obj_id pcd) throws InterruptedException { if (isFamiliarPetType(pet)) { return PET_TYPE_FAMILIAR; } if (!isValidId(pcd)) { pcd = getPetControlDevice(pet); if (isValidId(pcd) && exists(pcd)) { if (hasObjVar(pcd, "ai.pet.trainedMount")) { return PET_TYPE_MOUNT; } } } if (ai_lib.isMonster(pet)) { String creatureName = getCreatureName(pet); if (creatureName == null) { return PET_TYPE_NPC; } if (utils.dataTableGetFloat(CREATURE_TABLE, creatureName, "aggressive") > 0.0f) { return PET_TYPE_AGGRO; } else { return PET_TYPE_NON_AGGRO; } } else if (pet_lib.isDroidPet(pet)) { return PET_TYPE_DROID; } return PET_TYPE_NPC; } public static int getPetType(String pet) throws InterruptedException { int niche = utils.dataTableGetInt(CREATURE_TABLE, pet, "niche"); if (niche == NICHE_DROID || niche == NICHE_ANDROID) { return PET_TYPE_DROID; } else if (niche == NICHE_MONSTER || niche == NICHE_HERBIVORE || niche == NICHE_CARNIVORE || niche == NICHE_PREDATOR) { if (utils.dataTableGetFloat(CREATURE_TABLE, pet, "aggressive") > 0.0f) { return PET_TYPE_AGGRO; } else { return PET_TYPE_NON_AGGRO; } } return PET_TYPE_NPC; } public static boolean isFamiliarPetType(obj_id pet) throws InterruptedException { if (hasObjVar(pet, "ai.pet.type")) { int petType = getIntObjVar(pet, "ai.pet.type"); if (petType == PET_TYPE_FAMILIAR) { return true; } } else { String creatureName = getCreatureName(pet); if (creatureName != null && creatureName.length() > 0) { if (isFamiliarPetTypeByCreatureName(creatureName)) { return true; } } } return false; } public static boolean isFamiliarPetTypeByCreatureName(String creatureName) throws InterruptedException { if (creatureName != null && creatureName.length() > 0) { int dataRow = dataTableSearchColumnForString(creatureName, "creatureName", FAMILAR_DATA_DATATABLE); if (dataRow >= 0) { return true; } } return false; } public static obj_id generatePetOfTypeFamiliar(String creatureName, obj_id player) throws InterruptedException { obj_id familiarControlDevice = obj_id.NULL_ID; dictionary familiarData = dataTableGetRow(FAMILAR_DATA_DATATABLE, creatureName); if (familiarData != null && !familiarData.isEmpty()) { obj_id playerDatapad = utils.getPlayerDatapad(player); if (isIdValid(playerDatapad)) { String controlDeviceTemplate = familiarData.getString("controlDeviceTemplate"); familiarControlDevice = createObject(controlDeviceTemplate, playerDatapad, ""); if (isIdValid(familiarControlDevice)) { setObjVar(familiarControlDevice, "pet.creatureName", creatureName); attachScript(familiarControlDevice, "ai.pet_control_device"); setName(familiarControlDevice, getString(new string_id("mob/creature_names", creatureName))); setObjVar(familiarControlDevice, "ai.pet.type", pet_lib.PET_TYPE_FAMILIAR); int hasTricks = familiarData.getInt("hasTricks"); if (hasTricks <= 0) { setObjVar(familiarControlDevice, "familiar_noTricks", true); } return familiarControlDevice; } } } return familiarControlDevice; } public static boolean isRepairDroid(obj_id pet) throws InterruptedException { return (hasObjVar(pet, "ai.pet.isRepairDroid")); } public static boolean hasTamingMenuOption(obj_id pet, obj_id player) throws InterruptedException { if (pet_lib.hasMaster(pet)) { return false; } if (utils.hasScriptVar(player, "pet.tameLoopNum")) { return false; } if (ai_lib.isInCombat(pet) || ai_lib.isAiDead(pet)) { return false; } if (!hasSkill(player, "outdoors_creaturehandler_novice")) { return false; } if (!ai_lib.isMonster(pet)) { detachScript(pet, "ai.pet_advance"); return false; } if (pet_lib.getChanceToTame(pet, player) <= 0) { return false; } return true; } public static boolean isInValidUnpackLocation(obj_id master) throws InterruptedException { if (isIdValid(space_transition.getContainingShip(master))) { if (space_utils.isInStation(master)) { return false; } } if (hasObjVar(master, "fasttame")) { if (isGod(master)) { sendSystemMessageTestingOnly(master, "GODMODE MSG: You can call a pet because you have the fasttame objvar set"); } return true; } return true; } public static boolean isInRestrictedScene(obj_id master) throws InterruptedException { String scene = getCurrentSceneName(); String restrictionTable = "datatables/vehicle/vehicle_restrictions.iff"; String[] restrictedScenes = dataTableGetStringColumn(restrictionTable, 0); int[] restrictions = dataTableGetIntColumn(restrictionTable, 2); if (isIdValid(instance.getAreaInstanceController(master)) && !instance.vehicleAllowedInInstance(instance.getAreaInstanceController(master))) { sendSystemMessage(master, new string_id("instance", "no_vehicle")); return true; } if (hasObjVar(master, space_dungeon.VAR_DUNGEON_ID) || (locations.isInRegion(master, "@dathomir_region_names:black_mesa") && buff.hasBuff(master, "death_troopers_no_vehicle"))) { return true; } for (int i = 0; i < restrictedScenes.length; i++) { if (restrictedScenes[i].equals(scene)) { if (restrictions[i] == 1) { if (isGod(master)) { sendSystemMessageTestingOnly(master, "GODMODE MSG: You are in a mount restricted scene."); } return true; } } } return false; } public static boolean canQuickUnpack(obj_id master) throws InterruptedException { if (isGod(master)) { sendSystemMessageTestingOnly(master, "GODMODE MSG: You can quickUnpack because you are in GOD MODE:"); return true; } if (hasObjVar(master, "fasttame")) { if (isGod(master)) { sendSystemMessageTestingOnly(master, "GODMODE MSG: You can call a pet because you have the fasttame objvar set"); } return true; } location yourLoc = getLocation(master); if (locations.isInMissionCity(yourLoc)) { if (isIdValid(yourLoc.cell) && !city.isInCity(yourLoc)) { return false; } if (isGod(master)) { sendSystemMessageTestingOnly(master, "GODMODE MSG: You can call a pet because locations.isInMissionCity() return TRUE"); } return true; } else if (isIdValid(yourLoc.cell)) { if (isGod(master)) { sendSystemMessageTestingOnly(master, "GODMODE MSG: You can call a pet because you are in a building, not in town"); } return true; } obj_id yourCamp = camping.getCurrentCamp(master); if (isIdValid(yourCamp) && yourCamp.isLoaded()) { if (isGod(master)) { sendSystemMessageTestingOnly(master, "GODMODE MSG: You can call a pet because camping.getCurrentCamp() return TRUE"); } return true; } if (isNearResidence(master)) { if (isGod(master)) { sendSystemMessageTestingOnly(master, "GODMODE MSG: You can call a pet because isNearResidence() returned true"); } return true; } return false; } public static int getChanceToTame(obj_id pet, obj_id player) throws InterruptedException { final String creatureName = getCreatureName(pet); int petType = pet_lib.getPetType(pet); int tamingSkillMod = 0; if (petType == pet_lib.PET_TYPE_AGGRO) { tamingSkillMod = getEnhancedSkillStatisticModifier(player, "tame_aggro"); } else { tamingSkillMod = getEnhancedSkillStatisticModifier(player, "tame_non_aggro"); } tamingSkillMod += getEnhancedSkillStatisticModifier(player, "tame_bonus"); if (tamingSkillMod > 80) { tamingSkillMod = 80; } if (tamingSkillMod <= 0) { return 0; } int tameLevelSkillMod = getMaxTameLevel(player); int level = create.calcCreatureLevel(creatureName); return getChanceToTame(level, tamingSkillMod, tameLevelSkillMod); } public static int getChanceToTame(String petName, obj_id player) throws InterruptedException { int petType = pet_lib.getPetType(petName); int tamingSkillMod = 0; if (petType == pet_lib.PET_TYPE_AGGRO) { LOG("creature_taming", "tame_aggro = " + tamingSkillMod); tamingSkillMod = getEnhancedSkillStatisticModifier(player, "tame_aggro"); } else { LOG("creature_taming", "tame_non_aggro = " + tamingSkillMod); tamingSkillMod = getEnhancedSkillStatisticModifier(player, "tame_non_aggro"); } tamingSkillMod += getEnhancedSkillStatisticModifier(player, "tame_bonus"); LOG("creature_taming", "final tamingSkillMod = " + tamingSkillMod); if (tamingSkillMod > 80) { tamingSkillMod = 80; } if (tamingSkillMod <= 0) { return 0; } int level = create.calcCreatureLevel(petName); LOG("creature_taming", "tamingSkillMod = " + tamingSkillMod); LOG("creature_taming", "creatureLevel = " + level); int tameLevelSkillMod = getMaxTameLevel(player); return getChanceToTame(level, tamingSkillMod, tameLevelSkillMod); } public static int getChanceToTame(int level, int petType, obj_id player) throws InterruptedException { int tamingSkillMod = 0; if (petType == pet_lib.PET_TYPE_AGGRO) { LOG("creature_taming", "tame_aggro = " + tamingSkillMod); tamingSkillMod = getEnhancedSkillStatisticModifier(player, "tame_aggro"); } else { LOG("creature_taming", "tame_non_aggro = " + tamingSkillMod); tamingSkillMod = getEnhancedSkillStatisticModifier(player, "tame_non_aggro"); } tamingSkillMod += getEnhancedSkillStatisticModifier(player, "tame_bonus"); LOG("creature_taming", "final tamingSkillMod = " + tamingSkillMod); if (tamingSkillMod > 80) { tamingSkillMod = 80; } if (tamingSkillMod <= 0) { return 0; } LOG("creature_taming", "tamingSkillMod = " + tamingSkillMod); LOG("creature_taming", "creatureLevel = " + level); int tameLevelSkillMod = getMaxTameLevel(player); return getChanceToTame(level, tamingSkillMod, tameLevelSkillMod); } public static int getChanceToTame(int level, int skillMod, int tameLevelSkillMod) throws InterruptedException { if (level > tameLevelSkillMod) { return 0; } float chance = 0; chance = 40 + (33 * (skillMod / 30.0f)); if (level > 30) { level *= 1.5; } chance -= level; if (chance < 5) { chance = 5; } LOG("creature_taming", "tameChance = " + chance); return (int)chance; } public static void setControllerName(obj_id petControlDevice, obj_id pet) throws InterruptedException { String myName = getAssignedName(pet); if (myName != null && !myName.equals("")) { if (!myName.equals("null")) { setName(petControlDevice, myName); } else { String crName = getCreatureName(pet); debugServerConsoleMsg(petControlDevice, "WARNING: " + crName + " has an assigned name of Null - why is that?"); } } else { if (!myName.equals("null")) { setName(petControlDevice, getString(getNameStringId(pet))); } else { String crName = getCreatureName(pet); debugServerConsoleMsg(petControlDevice, "WARNING: " + crName + " has an assigned name of Null - why is that?"); } } } public static void grantPetGrowthXp(obj_id pet, int xpTotal) throws InterruptedException { obj_id pcd = callable.getCallableCD(pet); int growthStage = 10; if (hasObjVar(pcd, "ai.petAdvance.growthStage")) { growthStage = getIntObjVar(pcd, "ai.petAdvance.growthStage"); } int curXp = getIntObjVar(pcd, "ai.petAdvance.xpEarned"); int xpToLevel = getPetXpForNextLevel(pet); curXp += xpTotal; if (curXp > xpToLevel) { curXp -= xpToLevel; growthStage += 1; if (growthStage >= 10) { removeObjVar(pcd, "ai.petAdvance.growthStage"); } else { setObjVar(pcd, "ai.petAdvance.growthStage", growthStage); } if (rand(0, 100) < growthStage * 10) { earnPetTrainingAbility(pet); } earnPetTrainingPoints(pet); } setObjVar(pcd, "ai.petAdvance.xpEarned", curXp); if (!hasObjVar(pcd, "pet.crafted")) { float chance = (growthStage * growthStage * growthStage) / 10.0f; if (rand(0.0f, 100.0f) < chance) { learnPetAbility(pet); } } } public static int getPetXpForNextLevel(obj_id pet) throws InterruptedException { int level = getLevel(pet); return getXpForNextLevel(level); } public static int getPcdXpForNextLevel(obj_id pcd) throws InterruptedException { String creatureName = getStringObjVar(pcd, "pet.creatureName"); int level = pet_lib.getAdultLevel(creatureName); if (hasObjVar(pcd, "creature_attribs.level")) { level = getIntObjVar(pcd, "creature_attribs.level"); } return getXpForNextLevel(level); } public static int getXpForNextLevel(int level) throws InterruptedException { float modifiedLevel = (level + 4) / 2.0f; float levelSquared = modifiedLevel * modifiedLevel; float total = levelSquared * 300; return (int)total - 500; } public static int getMaxAbilitySlots(int level) throws InterruptedException { return (int)((level + 25) / 8.0f + 0.5f); } public static void earnPetTrainingAbility(obj_id pet) throws InterruptedException { obj_id pcd = callable.getCallableCD(pet); int toBeEarned = getIntObjVar(pcd, "ai.petAbility.toBeEarned"); int available = getIntObjVar(pcd, "ai.petAbility.available"); if (toBeEarned == 0) { return; } toBeEarned--; available++; setObjVar(pcd, "ai.petAbility.toBeEarned", toBeEarned); setObjVar(pcd, "ai.petAbility.available", available); obj_id master = getMaster(pet); sendSystemMessage(master, new string_id("pet/pet_ability", "earn_new_ability")); } public static void earnPetTrainingPoints(obj_id pet) throws InterruptedException { obj_id pcd = callable.getCallableCD(pet); int available = getIntObjVar(pcd, "ai.petAbility.available"); int toBeEarned = getIntObjVar(pcd, "ai.petAbility.toBeEarned"); if (available == 0 && toBeEarned == 0) { return; } int level = getLevel(pet); int newPts = (int)((level + 55) / 8.0f + 0.5f); int trainingPts = getIntObjVar(pcd, "ai.petAbility.trainingPts"); trainingPts += newPts; setObjVar(pcd, "ai.petAbility.trainingPts", trainingPts); obj_id master = getMaster(pet); prose_package pp = new prose_package(); pp.stringId = new string_id("pet/pet_ability", "earn_training_points"); pp.digitInteger = newPts; sendSystemMessageProse(master, pp); } public static void learnPetAbility(obj_id pet) throws InterruptedException { obj_id pcd = callable.getCallableCD(pet); obj_id master = getMaster(pet); String petAbility = getStringObjVar(pcd, "ai.petAbility.wildAbility"); if (petAbility == null || petAbility.equals("")) { return; } int abilityCrc = getStringCrc(petAbility.toLowerCase()); int[] abilityList = getIntArrayObjVar(master, "ch.petAbility.abilityList"); int row = dataTableSearchColumnForString(petAbility, "abilityName", PET_ABILITY_TABLE); if (row == -1) { LOG("pet_ability", "pet_lib::learnPetAbility() - ERROR: Unable to find pet ability in datatable"); return; } int[] newAbilityList = null; if (abilityList != null && abilityList.length > 0) { if (utils.getElementPositionInArray(abilityList, abilityCrc) > -1) { return; } newAbilityList = new int[abilityList.length + 1]; for (int i = 0; i < abilityList.length; i++) { newAbilityList[i] = abilityList[i]; } newAbilityList[newAbilityList.length - 1] = abilityCrc; } else { newAbilityList = new int[1]; newAbilityList[0] = abilityCrc; } setObjVar(master, "ch.petAbility.abilityList", newAbilityList); removeObjVar(pcd, "ai.petAbility.wildAbility"); String msg = utils.packStringId(new string_id("pet/pet_ability", "learn_pet_ability_begin")); msg += " \\#pcontrast2 " + utils.packStringId(new string_id("pet/pet_ability", petAbility)); msg += " \\#. " + utils.packStringId(new string_id("pet/pet_ability", "learn_pet_ability_end")); sendSystemMessage(master, msg, null); } public static void initializeWildPetAbility(obj_id pet) throws InterruptedException { String creatureName = ai_lib.getCreatureName(pet); if (creatureName == null || creatureName.equals("")) { return; } String wildListName = dataTableGetString(create.CREATURE_TABLE, creatureName, "wildAbilityList"); if (wildListName == null || wildListName.equals("") || wildListName.equals("none")) { return; } dictionary abilityData = utils.dataTableGetRow(WILD_ABILITY_TABLE, wildListName); if (abilityData == null) { return; } float wildAbilityChance = abilityData.getFloat("wildAbilityChance"); if (rand(0.0f, 100.0f) < wildAbilityChance) { String wildAbilityList = abilityData.getString("wildAbilityList"); String[] wildList = split(wildAbilityList, ','); if (wildList != null && wildList.length > 0) { int idx = rand(0, wildList.length - 1); int row = dataTableSearchColumnForString(wildList[idx], "abilityName", PET_ABILITY_TABLE); if (row == -1) { return; } setObjVar(pet, "ai.petAbility.wildAbility", wildList[idx]); } } } public static void validateFollowTarget(obj_id pet, obj_id target) throws InterruptedException { obj_id master = getMaster(pet); if (target == master) { return; } if (stealth.hasServerCoverState(target)) { doStayCommand(pet, master); doConfusedEmote(pet); } return; } public static void trainPetAbility(obj_id pet, String abilityName) throws InterruptedException { int ability = getStringCrc(abilityName.toLowerCase()); trainPetAbility(pet, ability); } public static void trainPetAbility(obj_id pet, int ability) throws InterruptedException { if (!isIdValid(pet) || !exists(pet)) { sendSystemMessage(getSelf(), new string_id("pet/pet_ability", "train_ability_failed")); return; } obj_id pcd = callable.getCallableCD(pet); obj_id master = getMaster(pet); if (!hasSkill(master, "outdoors_creaturehandler_novice")) { sendSystemMessage(master, new string_id("pet/pet_ability", "train_ability_ch_only")); return; } int[] abilityList = getIntArrayObjVar(pcd, "ai.petAbility.abilityList"); if (abilityList == null) { abilityList = new int[0]; } if (utils.getElementPositionInArray(abilityList, ability) > -1) { sendSystemMessage(master, new string_id("pet/pet_ability", "train_ability_already_known")); return; } int row = dataTableSearchColumnForInt(ability, "abilityCrc", PET_ABILITY_TABLE); if (row == -1) { LOG("pet_ability", "pet_lib::trainPetAbility() - ERROR: Unable to find pet ability in datatable"); return; } dictionary abilityData = dataTableGetRow(PET_ABILITY_TABLE, row); int available = getIntObjVar(pcd, "ai.petAbility.available"); if (available < 1) { sendSystemMessage(master, new string_id("pet/pet_ability", "train_ability_no_slots")); return; } int trainingCost = abilityData.getInt("trainingCost"); int trainingPts = getIntObjVar(pcd, "ai.petAbility.trainingPts"); if (trainingPts < trainingCost) { sendSystemMessage(master, new string_id("pet/pet_ability", "train_ability_no_points")); return; } String prereq = abilityData.getString("prereq"); int[] newAbilityList = null; if (prereq == null || prereq.equals("")) { newAbilityList = new int[abilityList.length + 1]; for (int i = 0; i < abilityList.length; i++) { newAbilityList[i] = abilityList[i]; } newAbilityList[newAbilityList.length - 1] = ability; } else { int prereqCrc = getStringCrc(prereq.toLowerCase()); int idx = -1; for (int i = 0; i < abilityList.length; i++) { if (abilityList[i] == prereqCrc) { idx = i; } } if (idx == -1) { String msg = utils.packStringId(new string_id("pet/pet_ability", "need_prereq_begin")); msg += " \\#pcontrast2 " + utils.packStringId(new string_id("pet/pet_ability", prereq)); msg += " \\#. " + utils.packStringId(new string_id("pet/pet_ability", "need_prereq_end")); sendSystemMessage(master, msg, null); return; } newAbilityList = abilityList; newAbilityList[idx] = ability; } setObjVar(pcd, "ai.petAbility.abilityList", newAbilityList); setObjVar(pcd, "ai.petAbility.available", available - 1); setObjVar(pcd, "ai.petAbility.trainingPts", trainingPts - trainingCost); String msg = utils.packStringId(new string_id("pet/pet_ability", "train_ability_begin")); msg += " \\#pcontrast1 " + utils.packStringId(new string_id("pet/pet_ability", abilityData.getString("abilityName"))); msg += " \\#. " + utils.packStringId(new string_id("pet/pet_ability", "train_ability_end")); sendSystemMessage(master, msg, null); } public static String getPetAbilityFromCrc(int ability) throws InterruptedException { int row = dataTableSearchColumnForInt(ability, "abilityCrc", PET_ABILITY_TABLE); if (row == -1) { return ""; } return dataTableGetString(PET_ABILITY_TABLE, row, "abilityName"); } public static void initializeTrainedPetAbilities(obj_id pcd, obj_id pet) throws InterruptedException { obj_id master = getMaster(pet); int[] abilityList = getIntArrayObjVar(pcd, "ai.petAbility.abilityList"); if (abilityList == null) { return; } if (abilityList != null && abilityList.length > 0) { for (int i1 : abilityList) { int row = dataTableSearchColumnForInt(i1, "abilityCrc", PET_ABILITY_TABLE); if (row == -1) { continue; } dictionary abilityData = dataTableGetRow(PET_ABILITY_TABLE, row); if (abilityData == null) { continue; } switch (abilityData.getInt("type")) { case PET_ABILITY_INNATE: addInnateAbilityStatBonus(pet, abilityData); addInnateScriptVar(pet, abilityData); addInnateBuff(pet, abilityData); break; case PET_ABILITY_TRIGGERED: addTriggeredAbility(pet, abilityData); break; case PET_ABILITY_ACTION: addActionAbility(pet, abilityData); break; } } } } public static void addInnateAbilityStatBonus(obj_id pet, dictionary abilityData) throws InterruptedException { int stat = abilityData.getInt("statMod"); if (stat == -1) { return; } int statValBonus = abilityData.getInt("statModVal"); float statPctBonus = abilityData.getFloat("statModPct"); int curStat = getMaxAttrib(pet, stat); int newStat = curStat + (int)(curStat * statPctBonus) + statValBonus; setMaxAttrib(pet, stat, newStat); setAttrib(pet, stat, newStat); } public static void addInnateScriptVar(obj_id pet, dictionary abilityData) throws InterruptedException { String varName = abilityData.getString("scriptVar"); if (varName == null || varName.equals("")) { return; } float varValue = abilityData.getFloat("scriptVarVal"); deltadictionary dd = pet.getScriptVars(); if (pet.hasScriptVar(varName)) { Object curValue = dd.getObject(varName); if (curValue instanceof Integer) { int newValue = (Integer) curValue + (int)varValue; dd.put(varName, varValue); } else if (curValue instanceof Float) { float newValue = (Float) curValue + varValue; dd.put(varName, varValue); } else { LOG("pet_ability", "Scriptvar name already present with unknown type, leaving current scriptvar"); } } else { dd.put(varName, varValue); } } public static void addInnateBuff(obj_id pet, dictionary abilityData) throws InterruptedException { String buffName = abilityData.getString("selfBuffName"); if (buffName == null || buffName.equals("")) { return; } int duration = abilityData.getInt("duration"); if (duration > 0) { buff.applyBuff(pet, buffName, duration); } else { buff.applyBuff(pet, buffName); } } public static void addTriggeredAbility(obj_id pet, dictionary abilityData) throws InterruptedException { String actionName = abilityData.getString("actionName"); if (actionName != null && !actionName.equals("")) { grantCommand(pet, actionName); } } public static void addActionAbility(obj_id pet, dictionary abilityData) throws InterruptedException { String actionName = abilityData.getString("actionName"); if (actionName != null && !actionName.equals("")) { grantCommand(pet, actionName); } } public static int getPetAbilityHealthBonus(obj_id pcd, int baseHealth) throws InterruptedException { int healthBonus = 0; int[] abilityList = getIntArrayObjVar(pcd, "ai.petAbility.abilityList"); if (abilityList != null && abilityList.length > 0) { for (int i1 : abilityList) { int row = dataTableSearchColumnForInt(i1, "abilityCrc", PET_ABILITY_TABLE); if (row == -1) { continue; } dictionary abilityData = dataTableGetRow(PET_ABILITY_TABLE, row); if (abilityData == null) { continue; } if (abilityData.getInt("statMod") == HEALTH) { int statValBonus = abilityData.getInt("statModVal"); float statPctBonus = abilityData.getFloat("statModPct"); healthBonus += (int) (baseHealth * statPctBonus) + statValBonus; baseHealth += healthBonus; } } } return healthBonus; } public static int getPetAbilityRegenBonus(obj_id pcd, int baseRegen) throws InterruptedException { int regenBonus = 0; int[] abilityList = getIntArrayObjVar(pcd, "ai.petAbility.abilityList"); if (abilityList != null && abilityList.length > 0) { for (int i1 : abilityList) { int row = dataTableSearchColumnForInt(i1, "abilityCrc", PET_ABILITY_TABLE); if (row == -1) { continue; } dictionary abilityData = dataTableGetRow(PET_ABILITY_TABLE, row); if (abilityData == null) { continue; } if (abilityData.getInt("statMod") == CONSTITUTION) { int statValBonus = abilityData.getInt("statModVal"); float statPctBonus = abilityData.getFloat("statModPct"); regenBonus += (int) (baseRegen * statPctBonus) + statValBonus; baseRegen += regenBonus; } } } return regenBonus; } public static int[] getPetAbilityDamageBonus(obj_id pcd, int baseMinDamage, int baseMaxDamage) throws InterruptedException { int[] damageBonus = { 0, 0 }; float dmgPctBonus = 0.0f; int[] abilityList = getIntArrayObjVar(pcd, "ai.petAbility.abilityList"); if (abilityList != null && abilityList.length > 0) { for (int i1 : abilityList) { int row = dataTableSearchColumnForInt(i1, "abilityCrc", PET_ABILITY_TABLE); if (row == -1) { continue; } dictionary abilityData = dataTableGetRow(PET_ABILITY_TABLE, row); if (abilityData == null) { continue; } String scriptVar = abilityData.getString("scriptVar"); if (scriptVar != null && scriptVar.equals("ai.combat.damagePctBonus")) { dmgPctBonus += abilityData.getFloat("scriptVarVal"); } } } damageBonus[0] = (int)(baseMinDamage * dmgPctBonus); damageBonus[1] = (int)(baseMaxDamage * dmgPctBonus); return damageBonus; } public static float getPetAbilityAttackSpdBonus(obj_id pcd, float baseSpeed) throws InterruptedException { float speedBonus = 0.0f; float spdPctBonus = 0.0f; int[] abilityList = getIntArrayObjVar(pcd, "ai.petAbility.abilityList"); if (abilityList != null && abilityList.length > 0) { for (int i1 : abilityList) { int row = dataTableSearchColumnForInt(i1, "abilityCrc", PET_ABILITY_TABLE); if (row == -1) { continue; } dictionary abilityData = dataTableGetRow(PET_ABILITY_TABLE, row); if (abilityData == null) { continue; } String scriptVar = abilityData.getString("scriptVar"); if (scriptVar != null && scriptVar.equals("ai.combat.attackSpdPctBonus")) { spdPctBonus += abilityData.getFloat("scriptVarVal"); } } } speedBonus = -1 * (baseSpeed * spdPctBonus); return speedBonus; } public static boolean isPetFrenzied(obj_id pet) throws InterruptedException { return (utils.hasScriptVar(pet, "buff.petFrenzy_1.value") || utils.hasScriptVar(pet, "buff.petFrenzy_2.value") || utils.hasScriptVar(pet, "buff.petFrenzy_3.value")); } public static float getPetFrenzyAmount(obj_id pet) throws InterruptedException { if (utils.hasScriptVar(pet, "buff.petFrenzy_3.value")) { return utils.getFloatScriptVar(pet, "buff.petFrenzy_3.value"); } if (utils.hasScriptVar(pet, "buff.petFrenzy_2.value")) { return utils.getFloatScriptVar(pet, "buff.petFrenzy_2.value"); } if (utils.hasScriptVar(pet, "buff.petFrenzy_1.value")) { return utils.getFloatScriptVar(pet, "buff.petFrenzy_1.value"); } return 0.0f; } public static boolean isPetDefenseStance(obj_id pet) throws InterruptedException { return (utils.hasScriptVar(pet, "buff.petDefense_1.value") || utils.hasScriptVar(pet, "buff.petDefense_2.value") || utils.hasScriptVar(pet, "buff.petDefense_3.value")); } public static float getPetDefenseStanceAmount(obj_id pet) throws InterruptedException { if (utils.hasScriptVar(pet, "buff.petDefense_3.value")) { return utils.getFloatScriptVar(pet, "buff.petDefense_3.value"); } if (utils.hasScriptVar(pet, "buff.petDefense_2.value")) { return utils.getFloatScriptVar(pet, "buff.petDefense_2.value"); } if (utils.hasScriptVar(pet, "buff.petDefense_1.value")) { return utils.getFloatScriptVar(pet, "buff.petDefense_1.value"); } return 0.0f; } public static boolean isPetDefenseBreak(obj_id pet) throws InterruptedException { return (utils.hasScriptVar(pet, "buff.petDefenseBreakAttack.value") || utils.hasScriptVar(pet, "buff.petDefenseBreakAttack_1.value")); } public static float getPetDefenseBreakAmount(obj_id pet) throws InterruptedException { if (utils.hasScriptVar(pet, "buff.petDefenseBreakAttack_1.value")) { return utils.getFloatScriptVar(pet, "buff.petDefenseBreakAttack_1.value"); } if (utils.hasScriptVar(pet, "buff.petDefenseBreakAttack.value")) { return utils.getFloatScriptVar(pet, "buff.petDefenseBreakAttack.value"); } return 0.0f; } public static obj_id getShieldingPet(obj_id player) throws InterruptedException { float closestPet = 10.0f; obj_id pet = callable.getCallable(player, callable.CALLABLE_TYPE_COMBAT_PET); if (!isIdValid(pet) || !exists(pet) || !isPetShielding(pet)) { return null; } return pet; } public static boolean isPetShielding(obj_id pet) throws InterruptedException { return (utils.hasScriptVar(pet, "buff.petShield_1.value") || utils.hasScriptVar(pet, "buff.petShield_2.value") || utils.hasScriptVar(pet, "buff.petShield_3.value")); } public static float getPetShieldAmount(obj_id pet) throws InterruptedException { if (utils.hasScriptVar(pet, "buff.petShield_3.value")) { return utils.getFloatScriptVar(pet, "buff.petShield_3.value"); } if (utils.hasScriptVar(pet, "buff.petShield_2.value")) { return utils.getFloatScriptVar(pet, "buff.petShield_2.value"); } if (utils.hasScriptVar(pet, "buff.petShield_1.value")) { return utils.getFloatScriptVar(pet, "buff.petShield_1.value"); } return 0.0f; } public static void setPetStatsByGrowth(obj_id pet, int growthStage) throws InterruptedException { } public static void setCraftedPetStatsByGrowth(obj_id petControlDevice, obj_id pet, int growthStage) throws InterruptedException { setObjVar(pet, "combat.intCombatXP", 0); if (growthStage < 1) { growthStage = 1; } else if (growthStage > 10) { growthStage = 10; } String creatureName = getCreatureName(pet); if (creatureName == null) { return; } dictionary creatureDict = utils.dataTableGetRow(create.CREATURE_TABLE, creatureName); if (creatureDict == null) { return; } int level = getIntObjVar(petControlDevice, "creature_attribs.level"); if (level == 0) { level = getLevel(pet); } if (level < 1) { level = 1; } obj_id player = utils.getContainingPlayer(petControlDevice); int myHealth = getIntObjVar(petControlDevice, "creature_attribs." + create.MAXATTRIBNAMES[HEALTH]); int healthRegen = getIntObjVar(petControlDevice, "creature_attribs." + create.MAXATTRIBNAMES[CONSTITUTION]); int[] armorData = new int[10]; armorData[1] = getIntObjVar(petControlDevice, "creature_attribs.general_protection"); float stateResist = getFloatObjVar(petControlDevice, "creature_attribs.stateResist"); float critChance = getFloatObjVar(petControlDevice, "creature_attribs.critChance"); float critSave = getFloatObjVar(petControlDevice, "creature_attribs.critSave"); float aggroBonus = getFloatObjVar(petControlDevice, "creature_attribs.aggroBonus"); int toHit = getIntObjVar(petControlDevice, "creature_attribs.toHitChance") - 5; int defenseValue = getIntObjVar(petControlDevice, "creature_attribs.defenseValue") - 5; float wpnSpeed = getFloatObjVar(petControlDevice, "creature_attribs.attackSpeed"); float spdBonus = getPetAbilityAttackSpdBonus(petControlDevice, wpnSpeed); int minDamage = getIntObjVar(petControlDevice, "creature_attribs.minDamage"); int maxDamage = getIntObjVar(petControlDevice, "creature_attribs.maxDamage"); if (isIdValid(player) && exists(player)) { if (level > 60 && !craftinglib.isTrader(player)) { level = 60; } dictionary droidDefaultStatsDict = dataTableGetRow(TBL_MOB_STAT_BALANCE, level - 1); myHealth = droidDefaultStatsDict.getInt("HP"); toHit = droidDefaultStatsDict.getInt("ToHit") - 5; defenseValue = droidDefaultStatsDict.getInt("Def") - 5; float creatureAttribs_dps = droidDefaultStatsDict.getFloat("damagePerSecond"); minDamage = (int)creatureAttribs_dps; maxDamage = (int)creatureAttribs_dps * 3; } setLevel(pet, level); utils.setScriptVar(pet, "ai.level", level); if (hasObjVar(pet, "difficultyClass")) { removeObjVar(pet, "difficultyClass"); } if (myHealth < 1) { myHealth = 1; } setMaxAttrib(pet, HEALTH, myHealth); setAttrib(pet, HEALTH, myHealth); setMaxAttrib(pet, ACTION, 1000); setAttrib(pet, ACTION, 1000); setMaxAttrib(pet, MIND, 1000); setAttrib(pet, MIND, 1000); fixMinRegenStats(pet); if (!ai_lib.isDroid(pet) && !ai_lib.isAndroid(pet)) { if (healthRegen < 1) { healthRegen = 1; } setRegenRate(pet, CONSTITUTION, 150); } if (armorData != null) { create.initializeArmor(pet, armorData); } float baseScale = 1.0f; if (utils.hasScriptVar(pet, "ai.baseScale")) { baseScale = utils.getFloatScriptVar(pet, "ai.baseScale"); } float minScale = 0; float maxScale = 9999; float scaleAdjust = 1; if (hasObjVar(petControlDevice, "creature_attribs.scale")) { scaleAdjust = getFloatObjVar(petControlDevice, "creature_attribs.scale"); } else { minScale = creatureDict.getFloat("minScale"); maxScale = creatureDict.getFloat("maxScale"); scaleAdjust = (minScale + maxScale) / 2.0f; } float realScale = baseScale * scaleAdjust; float babyScale = realScale * 0.3f; float scaleIncrement = (realScale - babyScale) / 10.0f; float finalScale = babyScale + (scaleIncrement * growthStage); if (finalScale > maxScale) { finalScale = maxScale; } if (finalScale < babyScale) { finalScale = babyScale; } setScale(pet, finalScale); utils.setScriptVar(pet, "ai.combat.stateResist", stateResist); utils.setScriptVar(pet, "ai.combat.critChance", critChance); utils.setScriptVar(pet, "ai.combat.critSave", critSave); utils.setScriptVar(pet, "ai.combat.aggroBonus", aggroBonus); create.applySkillStatisticModifiers(pet, toHit, defenseValue); if (wpnSpeed <= 1.0f) { wpnSpeed = 1.0f; } wpnSpeed += spdBonus; int[] dmgBonus = getPetAbilityDamageBonus(petControlDevice, minDamage, maxDamage); minDamage += dmgBonus[0]; maxDamage += dmgBonus[1]; if (minDamage < 5) { minDamage = 5; } if (maxDamage < 10) { maxDamage = 10; } obj_id creatureWeapon = getCurrentWeapon(pet); setWeaponMaxDamage(creatureWeapon, maxDamage); setWeaponMinDamage(creatureWeapon, minDamage); setWeaponAttackSpeed(creatureWeapon, wpnSpeed); weapons.setWeaponData(creatureWeapon); creatureWeapon = aiGetPrimaryWeapon(pet); if (isIdValid(creatureWeapon)) { setWeaponMaxDamage(creatureWeapon, maxDamage); setWeaponMinDamage(creatureWeapon, minDamage); setWeaponAttackSpeed(creatureWeapon, wpnSpeed); weapons.setWeaponData(creatureWeapon); } creatureWeapon = aiGetSecondaryWeapon(pet); if (isIdValid(creatureWeapon)) { setWeaponMaxDamage(creatureWeapon, maxDamage); setWeaponMinDamage(creatureWeapon, minDamage); setWeaponAttackSpeed(creatureWeapon, wpnSpeed); weapons.setWeaponData(creatureWeapon); } String rangedWeaponName = getStringObjVar(petControlDevice, "creature_attribs." + bio_engineer.ATTRIB_DICT_RANGED_WEAPON); if (rangedWeaponName != null && !rangedWeaponName.equals("")) { obj_id inventory = getObjectInSlot(pet, "inventory"); if (isIdValid(inventory)) { obj_id rangedWeapon = createObject(rangedWeaponName, inventory, ""); if (isIdValid(rangedWeapon)) { setWeaponAttackSpeed(rangedWeapon, wpnSpeed); setWeaponMaxDamage(rangedWeapon, maxDamage); setWeaponMinDamage(rangedWeapon, minDamage); weapons.setWeaponData(rangedWeapon); } } } int[] specialAttacks = new int[2]; specialAttacks[0] = getIntObjVar(petControlDevice, "creature_attribs." + bio_engineer.ATTRIB_DICT_SPECIAL_ATTACK_1); specialAttacks[1] = getIntObjVar(petControlDevice, "creature_attribs." + bio_engineer.ATTRIB_DICT_SPECIAL_ATTACK_2); utils.setScriptVar(pet, "ai.combat.creatureSpecialAttacks", specialAttacks); if (!isNewPlayerHelperDroid(pet)) { int colorIdx = hue.getVarColorIndex(petControlDevice, hue.INDEX_1); if (hasObjVar(petControlDevice, "creature_attribs.hue")) { colorIdx = getIntObjVar(petControlDevice, "creature_attribs.hue"); } hue.setColor(pet, hue.INDEX_1, colorIdx); } } public static void fixMinRegenStats(obj_id pet) throws InterruptedException { int healthAttrib = 0; if (!ai_lib.isDroid(pet) && !ai_lib.isAndroid(pet)) { healthAttrib = calcRegenStat(getMaxAttrib(pet, HEALTH)); } setRegenRate(pet, CONSTITUTION, 150); setRegenRate(pet, STAMINA, 150); setRegenRate(pet, WILLPOWER, 150); } public static int calcRegenStat(int poolStat) throws InterruptedException { int regenStat = poolStat / 10; if (regenStat > MAX_REGEN_STAT) { regenStat = MAX_REGEN_STAT; } else if (regenStat < 1) { regenStat = 1; } return regenStat; } public static boolean isNearResidence(obj_id master) throws InterruptedException { obj_id yourHome = player_structure.getResidence(master); if (!isIdValid(yourHome)) { return false; } if (!yourHome.isLoaded()) { return false; } return (getDistance(master, yourHome) < 60.0f); } public static boolean wasInCombatRecently(obj_id currentPet, obj_id master, boolean systemMessage) throws InterruptedException { if (!utils.hasScriptVar(currentPet, "pet.combatEnded")) { return false; } int combatEnded = utils.getIntScriptVar(currentPet, "pet.combatEnded"); int canStoreAgain = combatEnded + 60; int currentTime = getGameTime(); if (currentTime >= canStoreAgain) { return false; } if (systemMessage) { int timeLeft = canStoreAgain - currentTime; if (timeLeft > 1) { prose_package pp = prose.getPackage(new string_id("pet/pet_menu", "prose_cant_store_yet"), timeLeft); sendSystemMessageProse(master, pp); } else { sendSystemMessage(master, new string_id("pet/pet_menu", "cant_store_1sec")); } } return true; } public static boolean wasInCombat(obj_id player) throws InterruptedException { if (!utils.hasScriptVar(player, COMBAT_ENDED)) { return false; } int combatEnded = utils.getIntScriptVar(player, COMBAT_ENDED); int callPetDelay = combatEnded + POST_COMBAT_DELAY; int currentTime = getGameTime(); if (currentTime >= callPetDelay) { return false; } int timeLeft = callPetDelay - currentTime; return true; } public static int modifyCallTime(obj_id player, String combatEnded, int callDelay, int combatDelay) throws InterruptedException { int combatEnd = utils.getIntScriptVar(player, combatEnded); int combatEndDifference = getGameTime() - combatEnd; int combatDelayDifference = combatDelay - combatEndDifference; if (combatDelayDifference < callDelay) { return callDelay; } if (combatDelayDifference > combatDelay) { return combatDelay; } return combatDelayDifference; } public static int getTimeLeft(obj_id player, String toCheckFor, String modifiedTime) throws InterruptedException { int currentTime = getGameTime(); int timeCalled = utils.getIntScriptVar(player, toCheckFor); if (timeCalled < 1) { return -1; } int timePenalty = utils.getIntScriptVar(player, modifiedTime); int timeDone = timeCalled + timePenalty; int timeLeft = timeDone - currentTime; return timeLeft; } public static int getCurrentPetLevels(obj_id master) throws InterruptedException { if (!isIdValid(master)) { return 0; } if (!isPlayer(master)) { return 0; } if (!callable.hasCallable(master, callable.CALLABLE_TYPE_COMBAT_PET)) { return 0; } obj_id pet = callable.getCallable(master, callable.CALLABLE_TYPE_COMBAT_PET); return getLevel(pet); } public static boolean canControlPetsOfLevel(obj_id player, int petType, int petLevel, String creatureName) throws InterruptedException { if (!hasSkill(player, "outdoors_creaturehandler_novice")) { return true; } if (petType != PET_TYPE_NON_AGGRO && petType != PET_TYPE_AGGRO) { return true; } if (creatureName == null) { return false; } int tameLevelSkillMod = getMaxTameLevel(player); int tamingSkillMod = 0; if (petType == pet_lib.PET_TYPE_AGGRO) { tamingSkillMod = getEnhancedSkillStatisticModifier(player, "tame_aggro"); } else { tamingSkillMod = getEnhancedSkillStatisticModifier(player, "tame_non_aggro"); } tamingSkillMod += getEnhancedSkillStatisticModifier(player, "tame_bonus"); int chanceToTame = getChanceToTame(petLevel, tamingSkillMod, tameLevelSkillMod); if (chanceToTame < 1) { sendSystemMessage(player, new string_id("pet/pet_menu", "sys_lack_skill")); return false; } int numOutNow = getCurrentPetLevels(player); if ((numOutNow + petLevel) > tameLevelSkillMod) { if (numOutNow == 0) { sendSystemMessage(player, new string_id("pet/pet_menu", "too_hard")); } else { sendSystemMessage(player, new string_id("pet/pet_menu", "control_exceeded")); } return false; } return true; } public static int getMaxTameLevel(obj_id player) throws InterruptedException { int baseTameLevel = getSkillStatMod(player, "tame_level"); int bonusTameLevel = getEnhancedSkillStatisticModifier(player, "tame_level_bonus"); int playerLevel = getLevel(player); if (baseTameLevel + bonusTameLevel > playerLevel) { if (baseTameLevel > playerLevel) { return baseTameLevel; } bonusTameLevel = playerLevel - baseTameLevel; if (bonusTameLevel < 0) { bonusTameLevel = 0; } } return (baseTameLevel + bonusTameLevel); } public static int getModifiedAttribDamage(obj_id target, int attrib) throws InterruptedException { int max = getWoundedMaxAttrib(target, attrib); int current = getAttrib(target, attrib); if (max == ATTRIB_ERROR || current == ATTRIB_ERROR) { return ATTRIB_ERROR; } return max - current; } public static void storeDamage(obj_id pet, obj_id petControlDevice) throws InterruptedException { if (!isIdValid(pet) || !isIdValid(petControlDevice)) { return; } int[] mainAttribs = new int[6]; mainAttribs[HEALTH_DAMAGE] = getModifiedAttribDamage(pet, HEALTH); mainAttribs[ACTION_DAMAGE] = getModifiedAttribDamage(pet, ACTION); mainAttribs[MIND_DAMAGE] = getModifiedAttribDamage(pet, MIND); mainAttribs[HEALTH_WOUND] = getAttribWound(pet, HEALTH); if (petControlDevice.isLoaded()) { setObjVar(petControlDevice, "ai.pet.currentStats", mainAttribs); setObjVar(petControlDevice, "pet.timeStored", getGameTime()); } else { dictionary parms = new dictionary(); parms.put("attribs", mainAttribs); parms.put("time", getGameTime()); messageTo(petControlDevice, "handleStatUpdate", parms, 0, true); } } public static void restoreDamage(obj_id pet, obj_id petControlDevice) throws InterruptedException { if (!isIdValid(pet) || !isIdValid(petControlDevice)) { return; } if (!hasObjVar(petControlDevice, "ai.pet.currentStats")) { return; } int[] mainAttribs = getIntArrayObjVar(petControlDevice, "ai.pet.currentStats"); int timeStored = getIntObjVar(petControlDevice, "pet.timeStored"); if (timeStored > 0) { timeStored = getGameTime() - timeStored; int amountHealed = (timeStored / 5) * 2; mainAttribs[HEALTH_DAMAGE] -= amountHealed; mainAttribs[ACTION_DAMAGE] -= amountHealed; mainAttribs[MIND_DAMAGE] -= amountHealed; removeObjVar(petControlDevice, "pet.timeStored"); } int currentHealth = getMaxAttrib(pet, HEALTH); if (mainAttribs[HEALTH_DAMAGE] > 0) { currentHealth = currentHealth - mainAttribs[HEALTH_DAMAGE]; if (currentHealth < 1) { currentHealth = 1; } setAttrib(pet, HEALTH, currentHealth); } int currentAction = getMaxAttrib(pet, ACTION); if (mainAttribs[ACTION_DAMAGE] > 0) { currentAction = currentAction - mainAttribs[ACTION_DAMAGE]; if (currentAction < 1) { currentAction = 1; } setAttrib(pet, ACTION, currentAction); } int currentMind = getMaxAttrib(pet, MIND); if (mainAttribs[MIND_DAMAGE] > 0) { currentMind = currentMind - mainAttribs[MIND_DAMAGE]; if (currentMind < 1) { currentMind = 1; } setAttrib(pet, MIND, currentMind); } } public static void killPet(obj_id pet) throws InterruptedException { obj_id petControlDevice = callable.getCallableCD(pet); if (isIdValid(petControlDevice)) { dictionary params = new dictionary(); params.put("killer", utils.getObjIdScriptVar(pet, "killer")); messageTo(petControlDevice, "handlePetDeathblow", params, 0, false); } else { pclib.coupDeGrace(pet, pet); } return; } public static void reduceStatsForVitality(obj_id pet, obj_id petControlDevice) throws InterruptedException { int maxVitality = 100 - getIntObjVar(petControlDevice, "pet.maxVitality"); int vitality = maxVitality - getIntObjVar(petControlDevice, "pet.vitality"); if (vitality == 100) { return; } if (vitality > 75) { return; } else if (vitality > 50) { vitality = 75; } else if (vitality > 25) { vitality = 50; } else { vitality = 25; } int currentHealth = getMaxAttrib(pet, HEALTH); setMaxAttrib(pet, HEALTH, getReducedStatValue(currentHealth, vitality)); int currentAction = getMaxAttrib(pet, ACTION); setMaxAttrib(pet, ACTION, getReducedStatValue(currentAction, vitality)); int currentMind = getMaxAttrib(pet, MIND); setMaxAttrib(pet, MIND, getReducedStatValue(currentMind, vitality)); } public static int getReducedStatValue(int oldValue, int vitality) throws InterruptedException { if (vitality == 100) { return oldValue; } if (vitality > 75) { return oldValue; } else if (vitality > 50) { vitality = 75; } else if (vitality > 25) { vitality = 50; } else { vitality = 25; } float reduction = vitality / 100.0f; int newValue = (int)(oldValue * reduction); return newValue; } public static boolean performVitalityHeal(obj_id player, obj_id pet, obj_id petControlDevice, obj_id pet_med) throws InterruptedException { if (!isIdValid(player) || !isIdValid(petControlDevice) || !isIdValid(pet_med)) { return false; } int vitality = getIntObjVar(petControlDevice, "pet.vitality"); int maxVitality = getIntObjVar(petControlDevice, "pet.maxVitality"); int strength = getIntObjVar(pet_med, "consumable.strength"); int tmpStrength = (int)strength / 25; if (tmpStrength < 1) { tmpStrength = 1; } int penalty = (int)vitality / 5; penalty = (int)((penalty / tmpStrength) + 0.99f); if (penalty < 1) { penalty = 1; } vitality = 0; maxVitality += penalty; if (maxVitality > MAX_VITALITY_LOSS) { maxVitality = MAX_VITALITY_LOSS; } setObjVar(petControlDevice, "pet.vitality", vitality); setObjVar(petControlDevice, "pet.maxVitality", maxVitality); if (isIdValid(pet)) { savePetInfo(pet, petControlDevice); int growthStage = 10; if (hasObjVar(petControlDevice, "ai.petAdvance.growthStage")) { growthStage = getIntObjVar(petControlDevice, "ai.petAdvance.growthStage"); } if (hasObjVar(petControlDevice, "pet.crafted")) { setCraftedPetStatsByGrowth(petControlDevice, pet, growthStage); } else { setPetStatsByGrowth(pet, growthStage); } initializeTrainedPetAbilities(petControlDevice, pet); reduceStatsForVitality(pet, petControlDevice); restoreDamage(pet, petControlDevice); } return true; } public static void savePetInfo(obj_id pet, obj_id petControlDevice) throws InterruptedException { if (!isIdValid(pet) || !isIdValid(petControlDevice)) { return; } if (!pet.isLoaded() || !petControlDevice.isLoaded()) { return; } obj_id master = getMaster(pet); if (isIdValid(master) && master.isLoaded()) { setHomeLocation(pet, getLocation(master)); } setName(petControlDevice, getAssignedName(pet)); setName(petControlDevice, getNameStringId(pet)); storeDamage(pet, petControlDevice); setObjVar(petControlDevice, "pet.timeStored", getGameTime()); if (!isNewPlayerHelperDroid(pet)) { ranged_int_custom_var[] ri = hue.getPalcolorVars(pet); if (ri != null && ri.length > 0) { boolean wasUpdated = false; for (ranged_int_custom_var ranged_int_custom_var : ri) { int val = ranged_int_custom_var.getValue(); if (val > -1) { String varpath = VAR_PALVAR_VARS + "." + ranged_int_custom_var.getVarName(); int cur = getIntObjVar(petControlDevice, varpath); if (cur != val) { setObjVar(petControlDevice, varpath, val); } } } if (utils.hasScriptVar(pet, "customizationUpdated")) { setObjVar(petControlDevice, VAR_PALVAR_CNT, CUSTOMIZATION_COUNT); } } int varValue = getRangedIntCustomVarValue(pet, "/private/index_texture_1"); setObjVar(petControlDevice, VAR_PALVAR_VARS + "./private/index_texture_1", varValue); } } public static void processSpeech(obj_id pet, obj_id master, String text) throws InterruptedException { if (!isIdValid(pet)) { return; } if (!isIdValid(master)) { return; } if (ai_lib.isAiDead(pet)) { return; } if (text.equals("")) { return; } if (master != getMaster(pet)) { if (!pet_lib.isFriend(pet, master)) { return; } } if (utils.hasScriptVar(pet, "stored")) { destroyObject(pet); return; } if (callable.hasCallableCD(pet)) { obj_id controller = callable.getCallableCD(pet); if (isIdValid(controller) && controller.isLoaded()) { obj_id currentPet = callable.getCDCallable(controller); if (isIdValid(currentPet) && currentPet != pet) { destroyObject(pet); return; } } } location masterLoc = getLocation(master); location petLoc = getLocation(pet); if (masterLoc == null || petLoc == null) { return; } if (((masterLoc.cell != null) && isIdValid(masterLoc.cell)) && ((petLoc.cell == null) || (!isIdValid(petLoc.cell)))) { return; } if (text == null || text.equals("")) { return; } if (text.length() > 30) { return; } if (utils.hasScriptVar(pet, "ai.pet.learnCommand")) { int commandNum = utils.getIntScriptVar(pet, "ai.pet.learnCommand"); pet_lib.learnCommand(pet, commandNum, text, master); } else if (isSameFaction(pet, master)) { pet_lib.doCommand(pet, text, master); } else { releasePet(pet); } return; } public static int getAdultLevel(obj_id pet) throws InterruptedException { String creatureName = getCreatureName(pet); if (creatureName != null) { int level = create.calcCreatureLevel(creatureName); return level; } return 1; } public static int getAdultLevel(String creatureName) throws InterruptedException { if (creatureName != null) { int level = create.calcCreatureLevel(creatureName); return level; } return 1; } public static boolean canTrainAsMount(obj_id pet, obj_id player) throws InterruptedException { if (!isIdValid(pet)) { debugServerConsoleMsg(player, "+++ PET_LIB . canTrainAsMount +++ isIdValid failed for(pet)"); return false; } if (!isIdValid(player)) { debugServerConsoleMsg(player, "+++ PET_LIB . canTrainAsMount +++ isIdValid failed for(player)"); return false; } obj_id petControlDevice = callable.getCallableCD(pet); if (!isIdValid(petControlDevice)) { debugServerConsoleMsg(player, "+++ PET_LIB . canTrainAsMount +++ isIdValid failed for(petControlDevice)"); return false; } if (hasObjVar(petControlDevice, "ai.pet.trainedMount")) { return false; } if (!(couldPetBeMadeMountable(pet) == MSC_CREATURE_MOUNTABLE)) { return false; } if (!hasSkill(player, "outdoors_creaturehandler_support_04")) { return false; } return true; } public static boolean trainMount(obj_id pet, obj_id player) throws InterruptedException { if (!isIdValid(pet)) { return false; } if (!isIdValid(player)) { return false; } if (!canTrainAsMount(pet, player)) { return false; } if (!makePetAMount(pet, player)) { return false; } return true; } public static boolean makePetAMount(obj_id pet, obj_id player) throws InterruptedException { if (!isIdValid(pet)) { return false; } if (!isIdValid(player)) { return false; } if (!(couldPetBeMadeMountable(pet) == 0)) { return false; } obj_id petControlDevice = callable.getCallableCD(pet); if (!isIdValid(petControlDevice)) { return false; } if (hasObjVar(petControlDevice, "ai.pet.trainedMount")) { return false; } if (!makePetMountable(pet)) { return false; } else { setObjVar(petControlDevice, "ai.pet.trainedMount", 1); } return true; } public static boolean mountablePetInit(obj_id pet, obj_id player) throws InterruptedException { if (!isIdValid(pet) || !isIdValid(player)) { return false; } obj_id petControlDevice = callable.getCallableCD(pet); if (!isIdValid(petControlDevice)) { return false; } if (!hasObjVar(petControlDevice, "ai.pet.trainedMount")) { return false; } int mountableFlag = couldPetBeMadeMountable(pet); if (mountableFlag != 0) { if (mountableFlag == 3) { String appearance = getAppearance(pet); int row = dataTableSearchColumnForString(appearance, "appearance_name", MOUNT_VALID_SCALE_RANGE); dictionary dict = dataTableGetRow(MOUNT_VALID_SCALE_RANGE, row); float validMinRange = dict.getFloat("valid_scale_min"); float validMaxRange = dict.getFloat("valid_scale_max"); float currentScale = getScale(pet); if (currentScale > validMaxRange) { setScale(pet, validMaxRange); } else if (currentScale < validMinRange) { setScale(pet, validMinRange); } mountableFlag = couldPetBeMadeMountable(pet); if (mountableFlag != 0) { if (isGod(player)) { prose_package pp = new prose_package(); prose.setTO(pp, MOUNTABILITY_STATUS_CODES[mountableFlag]); prose.setStringId(pp, SID_MOUNT_STATUS_CODE_ERROR); sendSystemMessageProse(player, pp); } return false; } else { if (!makePetMountable(pet)) { return false; } return true; } } if (isGod(player)) { prose_package pp = new prose_package(); prose.setTO(pp, MOUNTABILITY_STATUS_CODES[mountableFlag]); prose.setStringId(pp, SID_MOUNT_STATUS_CODE_ERROR); sendSystemMessageProse(player, pp); } return false; } if (!makePetMountable(pet)) { return false; } return true; } public static boolean isMount(obj_id pet) throws InterruptedException { if (!isIdValid(pet) || !exists(pet)) { return false; } obj_id petControlDevice = callable.getCallableCD(pet); if (!isIdValid(petControlDevice) || !hasObjVar(petControlDevice, "ai.pet.trainedMount")) { return false; } return true; } public static boolean canMount(obj_id pet, obj_id player) throws InterruptedException { if (!isIdValid(pet)) { debugServerConsoleMsg(player, "+++ PET_LIB.canMount +++ isIdValid failed for(pet)"); return false; } if (!isIdValid(player)) { debugServerConsoleMsg(player, "+++ PET_LIB.canMount +++ isIdValid failed for(player)"); return false; } obj_id playerCurrentMount = getMountId(player); if (isIdValid(playerCurrentMount)) { return false; } if (isDead(pet) || ai_lib.isIncapacitated(pet)) { return false; } int mountDistance = (int)(getDistance(pet, player)); int maxDistance = (getOwner(pet) == player) ? MAX_PET_MOUNT_DISTANCE : MAX_PET_MOUNT_OFFER_DISTANCE; if (mountDistance > maxDistance) { return false; } obj_id petControlDevice = callable.getCallableCD(pet); if (!isIdValid(petControlDevice)) { return false; } if (!hasObjVar(petControlDevice, "ai.pet.trainedMount")) { return false; } if (utils.hasScriptVar(player, "mountBlock")) { int blockTime = utils.getIntScriptVar(player, "mountBlock"); if (getPlayerPlayedTime(player) < blockTime) { return false; } } if (getMovementPercent(player) == 0.0f) { return false; } return true; } public static boolean isMountedOnCreatureQueried(obj_id pet, obj_id player) throws InterruptedException { if (!isIdValid(pet) || !exists(pet) || !isIdValid(player) || !exists(player)) { return false; } obj_id petControlDevice = callable.getCallableCD(pet); if (!isIdValid(petControlDevice) || !hasObjVar(petControlDevice, "ai.pet.trainedMount")) { return false; } obj_id playerCurrentMount = getMountId(player); if (!isIdValid(playerCurrentMount) || playerCurrentMount != pet) { return false; } return true; } public static boolean isSameFaction(obj_id pet, obj_id master) throws InterruptedException { String creatureName = getCreatureName(pet); if (creatureName == null || creatureName.equals("")) { return false; } String petFaction = utils.dataTableGetString(CREATURE_TABLE, creatureName, "pvpFaction"); if (petFaction == null || petFaction.equals("")) { return true; } if (!petFaction.equals("Imperial") && !petFaction.equals("Rebel")) { return true; } String masterFaction = factions.getFaction(master); if (masterFaction == null || !masterFaction.equals(petFaction)) { return false; } if (pvpGetType(master) == PVPTYPE_NEUTRAL) { return false; } return true; } public static boolean cancelAttackDueToFactionalRestrictions(obj_id pet, obj_id target) throws InterruptedException { obj_id master = getMaster(pet); if (!isIdValid(master) || !exists(master) || !master.isLoaded()) { return true; } String creatureName = getCreatureName(pet); if (creatureName == null || creatureName.equals("")) { return true; } if (!pvpCanAttack(pet, target)) { return true; } String petFaction = utils.dataTableGetString(CREATURE_TABLE, creatureName, "pvpFaction"); if (petFaction == null || petFaction.equals("")) { return false; } if (!petFaction.equals("Imperial") && !petFaction.equals("Rebel")) { return false; } int intAlignedFaction = pvpGetAlignedFaction(target); if (intAlignedFaction == 0) { return true; } if (!pvpCanAttack(master, target)) { return true; } return false; } public static int showGrowthChoiceSui(obj_id owner, obj_id target, String targetName) throws InterruptedException { if (!isIdValid(owner) || !isIdValid(target) || (targetName == null) || (targetName.equals(""))) { return -1; } obj_id petControlDevice = null; if (utils.hasScriptVar(target, "mountgrowthcheck.pcd")) { petControlDevice = utils.getObjIdScriptVar(target, "mountgrowthcheck.pcd"); } LOG("pet_lib.showGrowthChoiceSui", "calling mount-related show growth choice sui..."); String title = utils.packStringId(SID_GROWTH_CHOICE_TITLE); String prompt = utils.packStringId(SID_GROWTH_CHOICE_PROMPT); int pid = sui.msgbox(petControlDevice, target, prompt, sui.YES_NO, title, "handleGrowthChoice"); return pid; } public static int doMountOutOfScaleCheck(obj_id petControlDevice, String creatureName) throws InterruptedException { if (creatureName == null) { LOG("create", "create.createCreature called with NULL creatureName!"); return 13; } dictionary creatureDict = utils.dataTableGetRow(CREATURE_TABLE, creatureName); if (creatureDict == null) { debugServerConsoleMsg(null, "WARNING: Unable to spawn invalid creatureType: " + creatureName); return 13; } String templateName = creatureDict.getString("template"); if (templateName.equals("") || templateName == null) { debugServerConsoleMsg(null, "WARNING: Unable to spawn invalid creatureType: " + creatureName + " - bad templateName?"); return 13; } if (!templateName.endsWith(".iff")) { if (dataTableHasColumn(DRESSED_NPC_TABLE, templateName)) { String[] templateList = dataTableGetStringColumnNoDefaults(DRESSED_NPC_TABLE, templateName); if (templateList.length < 1 || templateList == null) { LOG("create", templateName + " column in dressed_species is empty!"); return 13; } templateName = templateList[rand(0, templateList.length - 1)]; } else { String[] templateList = dataTableGetStringColumnNoDefaults(NPC_CUSTOMIZATION_PREFIX + templateName + ".iff", rand(0, 1)); if (templateList == null) { debugServerConsoleMsg(null, "WARNING: Unable to spawn " + creatureName + " - bad templateName? " + templateName); LOG("create", templateName + " does not exist!"); return 13; } if (templateList.length == 0) { debugServerConsoleMsg(null, "WARNING: Unable to spawn " + creatureName + " - bad templateName? " + templateName); LOG("create", templateName + " File was Empty!"); return 13; } templateName = templateList[rand(0, templateList.length - 1)] + ".iff"; } } int growthStage = 10; if (hasObjVar(petControlDevice, "ai.petAdvance.growthStage")) { growthStage = getIntObjVar(petControlDevice, "ai.petAdvance.growthStage"); } float baseScale = getDefaultScaleFromObjectTemplate("object/mobile/" + templateName); float minScale = creatureDict.getFloat("minScale"); float maxScale = creatureDict.getFloat("maxScale"); float scaleAdjust = (minScale + maxScale) / 2.0f; float realScale = baseScale * scaleAdjust; float babyScale = realScale * 0.3f; float scaleIncrement = (realScale - babyScale) / 10.0f; float finalScale = babyScale + (scaleIncrement * growthStage); if (finalScale > maxScale) { finalScale = maxScale; } if (couldObjectTemplateBeMadeMountable("object/mobile/" + templateName, finalScale) != MSC_SPECIES_UNMOUNTABLE) { if (couldObjectTemplateBeMadeMountable("object/mobile/" + templateName, finalScale) == MSC_CREATURE_MOUNTABLE) { setObjVar(petControlDevice, "ai.petAdvance.rdyToMnt", 1); return 1; } else if ((couldObjectTemplateBeMadeMountable("object/mobile/" + templateName, finalScale) == MSC_SPECIES_MOUNTABLE_SCALE_OUT_OF_RANGE)) { while ((couldObjectTemplateBeMadeMountable("object/mobile/" + templateName, finalScale) == MSC_SPECIES_MOUNTABLE_SCALE_OUT_OF_RANGE) && (growthStage > 0)) { growthStage = growthStage - 1; finalScale = babyScale + (scaleIncrement * growthStage); } if ((couldObjectTemplateBeMadeMountable("object/mobile/" + templateName, finalScale) == MSC_CREATURE_MOUNTABLE)) { setObjVar(petControlDevice, "ai.petAdvance.lrgMnt", growthStage); return 2; } else { debugServerConsoleMsg(null, "Pet_Lib script: doMountOutOfScaleCheck: ** Was unable to find a smaller version that is ready to be a mount as of yet."); debugServerConsoleMsg(null, "Pet_Lib script: doMountOutOfScaleCheck: ** Since this pet IS mountable, it simply hasn't grown up enough yet."); debugServerConsoleMsg(null, "Pet_Lib script: doMountOutOfScaleCheck: ** We'll have to run this check again next time it's called."); return 3; } } else { debugServerConsoleMsg(null, "Pet_Lib script: doMountOutOfScaleCheck: ** I should NEVER see this message. It means that we've snuck through a hole in the possible results. "); } debugServerConsoleMsg(null, "Pet_Lib script: doMountOutOfScaleCheck: ** the template returned as MOUNTABLE-ScaleOutOfRange at the current finalScale, and has the ai.petAdvance.rdyToMnt objvar"); } else if (couldObjectTemplateBeMadeMountable("object/mobile/" + templateName, finalScale) == MSC_SPECIES_UNMOUNTABLE) { debugServerConsoleMsg(null, "Pet_Lib script: doMountOutOfScaleCheck: ** the template came in as UNMOUNTABLE, and not just OUT OF SCALE. It was all for naught! This is the Fall-Through case."); return 5; } return 13; } public static dictionary getMountMovementInfo(obj_id objMount) throws InterruptedException { String strSkeleton = ai_lib.getSkeleton(objMount); if (strSkeleton != null) { dictionary dctMountInfo = dataTableGetRow("datatables/mount/mount_movement_speeds.iff", strSkeleton); if (dctMountInfo != null) { return dctMountInfo; } } return null; } public static void setMountedMovementRate(obj_id objPlayer, obj_id objTarget) throws InterruptedException { dictionary dctMountInfo = getMountMovementInfo(objTarget); if (dctMountInfo != null) { float fltBaseRunSpeed = dctMountInfo.getFloat("fltBaseRunSpeed"); setBaseRunSpeed(objTarget, fltBaseRunSpeed); } } public static void setUnmountedMovementRate(obj_id self, obj_id objTarget) throws InterruptedException { dictionary dctMountInfo = getMountMovementInfo(objTarget); if (dctMountInfo != null) { float fltBurstRunSpeed = dctMountInfo.getFloat("fltBurstRunSpeed"); setBaseRunSpeed(objTarget, fltBurstRunSpeed); } } public static void setMountBurstRunMovementRate(obj_id objPlayer, obj_id objTarget) throws InterruptedException { dictionary dctMountInfo = getMountMovementInfo(objTarget); obj_id objControlDevice = callable.getCallableCD(objTarget); if (dctMountInfo != null) { float fltBurstRunSpeed = dctMountInfo.getFloat("fltBurstRunSpeed"); float fltBaseRunSpeed = dctMountInfo.getFloat("fltBaseRunSpeed"); float fltBurstRunDuration = dctMountInfo.getFloat("fltBurstRunDuration"); float fltBurstRunRecycleTime = dctMountInfo.getFloat("fltBurstRunRecycleTime"); LOG("pet", "setting run speed to " + fltBurstRunSpeed); LOG("pet", "fltBurstRunDuration is " + fltBurstRunDuration); LOG("pet", "fltBurstRunRecycleTiem is " + fltBurstRunRecycleTime); setBaseRunSpeed(objTarget, fltBurstRunSpeed); utils.setScriptVar(objControlDevice, "mount.intGalloping", 1); utils.setScriptVar(objControlDevice, "mount.intTired", 1); messageTo(objControlDevice, "removeGallop", null, fltBurstRunDuration, false); messageTo(objControlDevice, "removeGallopTired", null, fltBurstRunRecycleTime, false); string_id strSpam = new string_id("combat_effects", "gallop_start"); sendSystemMessage(objPlayer, strSpam); } } public static void setMountCombatMoveSpeed(obj_id objRider, obj_id objMount) throws InterruptedException { LOG("pet", "setting run speed of " + objMount + " to 6.0f"); setBaseRunSpeed(objMount, 6.0f); string_id strSpam = new string_id("combat_effects", "mount_slow_for_combat"); sendSystemMessage(objRider, strSpam); return; } public static boolean isGalloping(obj_id objCreature) throws InterruptedException { if (!isIdValid(objCreature) || !exists(objCreature)) { return false; } if (!callable.hasCallableCD(objCreature)) { return false; } obj_id objControlDevice = callable.getCallableCD(objCreature); if (!isIdValid(objControlDevice)) { return false; } if (utils.hasScriptVar(objControlDevice, "mount.intGalloping")) { return true; } return false; } public static boolean isTameable(obj_id objCreature) throws InterruptedException { final String strCreatureName = getCreatureName(objCreature); if (strCreatureName != null) { dictionary dctCreatureInfo = dataTableGetRow("datatables/mob/creatures.iff", strCreatureName); if (dctCreatureInfo != null) { float fltCanTame = dctCreatureInfo.getFloat("canTame"); if (fltCanTame > 0.0f) { return true; } return false; } else { return false; } } else { return false; } } public static void doPetSpecialAttack(obj_id pet, obj_id master, int attackNum) throws InterruptedException { debugServerConsoleMsg(null, "PET_LIB:doPetSpecialAttack *** entered doPetSpecialAttack "); switch (attackNum) { case 2: obj_id currentWeapon = getCurrentWeapon(pet); obj_id defaultWeapon = getDefaultWeapon(pet); int wpnType = getWeaponType(defaultWeapon); int crrntWpnType = getWeaponType(currentWeapon); String defaultWeaponTemplateName = getTemplateName(defaultWeapon); String currentWeaponTemplateName = getTemplateName(currentWeapon); debugServerConsoleMsg(null, "PET_LIB:doPetSpecialAttack *** defaultWeapon type comes in as :" + wpnType + " and being of template: " + defaultWeaponTemplateName); debugServerConsoleMsg(null, "PET_LIB:doPetSpecialAttack *** currentWeapon type comes in as :" + crrntWpnType + " and being of template: " + currentWeaponTemplateName); break; case 1: case 0: if (!ai_lib.isInCombat(pet)) { doAttackCommand(pet, master); } if (ai_lib.isInCombat(pet)) { final obj_id hateTarget = getHateTarget(pet); } break; } } public static boolean hasRangedAttack(obj_id pet) throws InterruptedException { if (isCombatDroid(pet)) { final String droidType = getCreatureName(pet); int droidRangedCapable = utils.dataTableGetInt(DROID_COMBAT_TABLE, droidType, "hasRangedAttack"); if (droidRangedCapable != 1) { return false; } } if (!ai_lib.isMonster(pet) && !isCombatDroid(pet)) { return false; } String creatureName = getCreatureName(pet); if (creatureName != null) { String weaponOne = dataTableGetString(CREATURE_TABLE, creatureName, "primary_weapon"); String weaponTwo = dataTableGetString(CREATURE_TABLE, creatureName, "secondary_weapon"); boolean rangedWeapon = false; if (weaponOne != null && !weaponOne.equals("") && weaponOne.contains("_spit_")) { rangedWeapon = true; } else if (weaponTwo != null && !weaponTwo.equals("") && weaponTwo.contains("_spit_")) { rangedWeapon = true; } else { obj_id pcd = callable.getCallableCD(pet); if (isIdValid(pcd) && hasObjVar(pcd, "pet.crafted")) { String rangedWeaponName = getStringObjVar(pcd, "creature_attribs." + bio_engineer.ATTRIB_DICT_RANGED_WEAPON); if (rangedWeaponName == null || rangedWeaponName.equals("")) { rangedWeapon = false; } else { rangedWeapon = true; } } else { rangedWeapon = false; } } return rangedWeapon; } return true; } public static void packAllCurrentPets(obj_id player, string_id optionalMsg) throws InterruptedException { callable.storeCallables(player); if (optionalMsg != null) { sendSystemMessage(player, optionalMsg); } } public static boolean doDismountNow(obj_id riderId, boolean notify) throws InterruptedException { if (!isIdValid(riderId)) { return false; } if (!getMountsEnabled()) { return false; } boolean dismountOccurred = false; obj_id playerCurrentMount = getMountId(riderId); if (isIdValid(playerCurrentMount) && exists(playerCurrentMount)) { queueClear(riderId); dismountCreature(riderId); dismountOccurred = true; if (hasScript(playerCurrentMount, "ai.mount_combat")) { detachScript(playerCurrentMount, "ai.mount_combat"); } int vehicleBuff = buff.getBuffOnTargetFromGroup(riderId, "vehicle"); if (vehicleBuff != 0) { buff.removeBuff(riderId, vehicleBuff); } int vehicleHasBuff = buff.getBuffOnTargetFromGroup(playerCurrentMount, "vehicle"); if (vehicleHasBuff != 0) { buff.removeBuff(playerCurrentMount, vehicleHasBuff); } int petType = getPetType(playerCurrentMount); if (isPetType(playerCurrentMount, PET_TYPE_MOUNT)) { storePet(playerCurrentMount); } } else { if (notify) { sendSystemMessage(riderId, pet_lib.SID_SYS_CANT_DISMOUNT); } } return dismountOccurred; } public static boolean doDismountNow(obj_id player) throws InterruptedException { return doDismountNow(player, true); } public static void initPCDCraftedStats(obj_id device, obj_id deed) throws InterruptedException { setObjVar(device, "creature_attribs.level", getIntObjVar(deed, "creature_attribs.level")); setObjVar(device, "creature_attribs.maxHealth", getIntObjVar(deed, "creature_attribs.maxHealth")); setObjVar(device, "creature_attribs.maxConstitution", getIntObjVar(deed, "creature_attribs.maxConstitution")); setObjVar(device, "creature_attribs.general_protection", getIntObjVar(deed, "creature_attribs.general_protection")); setObjVar(device, "creature_attribs.toHitChance", getIntObjVar(deed, "creature_attribs.toHitChance")); setObjVar(device, "creature_attribs.defenseValue", getIntObjVar(deed, "creature_attribs.defenseValue")); setObjVar(device, "creature_attribs.minDamage", getIntObjVar(deed, "creature_attribs.minDamage")); setObjVar(device, "creature_attribs.maxDamage", getIntObjVar(deed, "creature_attribs.maxDamage")); setObjVar(device, "creature_attribs.aggroBonus", getFloatObjVar(deed, "creature_attribs.aggroBonus")); setObjVar(device, "creature_attribs.critChance", getFloatObjVar(deed, "creature_attribs.critChance")); setObjVar(device, "creature_attribs.critSave", getFloatObjVar(deed, "creature_attribs.critSave")); setObjVar(device, "creature_attribs.scale", getFloatObjVar(deed, "creature_attribs.scale")); setObjVar(device, "creature_attribs.stateResist", getFloatObjVar(deed, "creature_attribs.stateResist")); setObjVar(device, "creature_attribs." + bio_engineer.ATTRIB_DICT_SPECIAL_ATTACK_1, getIntObjVar(deed, "creature_attribs." + bio_engineer.ATTRIB_DICT_SPECIAL_ATTACK_1)); setObjVar(device, "creature_attribs." + bio_engineer.ATTRIB_DICT_SPECIAL_ATTACK_2, getIntObjVar(deed, "creature_attribs." + bio_engineer.ATTRIB_DICT_SPECIAL_ATTACK_2)); setObjVar(device, "creature_attribs." + bio_engineer.ATTRIB_DICT_RANGED_WEAPON, getStringObjVar(deed, "creature_attribs." + bio_engineer.ATTRIB_DICT_RANGED_WEAPON)); setObjVar(device, "postCuPCD", 2); } public static void createPetFromData(obj_id petControlDevice) throws InterruptedException { createPetFromData(petControlDevice, null); } public static void createPetFromData(obj_id petControlDevice, obj_id objContainer) throws InterruptedException { String creatureName = getStringObjVar(petControlDevice, "pet.creatureName"); if (creatureName == null || creatureName.equals("")) { return; } obj_id datapad = getContainedBy(petControlDevice); if (!isIdValid(datapad)) { return; } obj_id master = getContainedBy(datapad); if (!isIdValid(master)) { return; } if (!hasScript(master, "ai.pet_master")) { attachScript(master, "ai.pet_master"); } if (getMountsEnabled() && (!hasObjVar(petControlDevice, "ai.petAdvance.cannotBeMount"))) { if (hasObjVar(petControlDevice, "ai.petAdvance.freezegrowth")) { int freezeGrowthValue = getIntObjVar(petControlDevice, "ai.petAdvance.freezegrowth"); if (freezeGrowthValue == 10) { debugServerConsoleMsg(null, "PCD script: createPetFromData: ** skipping growthstage objvar reset/rewrite, as this creature is an adult, with freezegrowth value of 10"); } else { setObjVar(petControlDevice, "ai.petAdvance.growthStage", freezeGrowthValue); } } if ((!hasObjVar(petControlDevice, "ai.petAdvance.letPetGrow")) && (!hasObjVar(petControlDevice, "ai.petAdvance.freezegrowth"))) { int mountOutOfScaleReturnValue = pet_lib.doMountOutOfScaleCheck(petControlDevice, creatureName); if (mountOutOfScaleReturnValue == 5) { setObjVar(petControlDevice, "ai.petAdvance.cannotBeMount", 1); } else if (mountOutOfScaleReturnValue == 2) { utils.setScriptVar(master, "mountgrowthcheck.pcd", petControlDevice); pet_lib.showGrowthChoiceSui(petControlDevice, master, creatureName); return; } else if (mountOutOfScaleReturnValue == 1) { if (!hasObjVar(petControlDevice, "ai.petAdvance.growthStage")) { setObjVar(petControlDevice, "ai.petAdvance.freezegrowth", 10); } } else if (mountOutOfScaleReturnValue == 3) { debugServerConsoleMsg(null, "PCD script: createPetFromData: ** pet_lib.doMountOutOfScaleCheck returned 3... the pet hasn't grown up enough yet to be a mount."); } else { debugServerConsoleMsg(null, "PCD script: createPetFromData: ** pet_lib.doMountOutOfScaleCheck FALLTHROUGH... Perhaps there was a data error. It didn't return 1, 2, 3, or 5."); } } } obj_id pet = null; if (getPosture(master) != POSTURE_UPRIGHT) { sendSystemMessage(master, SID_SYS_CANT_CALL); return; } if (!isIdValid(objContainer)) { location loc = getLocation(master); pet = create.object(creatureName, loc, true, true); } else { pet = create.object(creatureName, objContainer, false, true); } if (!isIdValid(pet)) { sendSystemMessage(master, pet_lib.SID_PRIVATE_HOUSE); return; } setObjVar(pet, "ai.pet", true); callable.setCallableCD(pet, petControlDevice); if (!hasScript(pet, "ai.pet")) { { attachScript(pet, "ai.pet"); } } sendDirtyObjectMenuNotification(petControlDevice); String masterFaction = factions.getFaction(master); if (masterFaction != null && !masterFaction.equals("")) { if (masterFaction.equals("Rebel") || masterFaction.equals("Imperial")) { setObjVar(pet, factions.FACTION, masterFaction); } } pet_lib.makePet(pet, master); if (hasObjVar(petControlDevice, "ai.petAdvance.growthStage")) { int growthStage = getIntObjVar(petControlDevice, "ai.petAdvance.growthStage"); if (hasObjVar(petControlDevice, "pet.crafted")) { pet_lib.setCraftedPetStatsByGrowth(petControlDevice, pet, growthStage); } else { pet_lib.setPetStatsByGrowth(pet, growthStage); } int level = getLevel(pet); utils.setScriptVar(pet, "ai.level", level); } else { if (hasObjVar(petControlDevice, "pet.crafted")) { setCraftedPetStatsByGrowth(petControlDevice, pet, 10); if (ai_lib.aiGetNiche(pet) == NICHE_DROID || ai_lib.aiGetNiche(pet) == NICHE_ANDROID) { initDroidCraftedInventoryDroid(pet, petControlDevice); initDroidCraftedDatapadDroid(pet, petControlDevice); initDroidPersonality(pet, petControlDevice); initDroidMedicalPower(pet, petControlDevice); initDroidCraftingPower(pet, petControlDevice, master); initDroidRepairPower(pet, petControlDevice); reviseCombatDroidPCD(petControlDevice, master, pet); } } else { setPetStatsByGrowth(pet, 10); } } initializeTrainedPetAbilities(petControlDevice, pet); pet_lib.reduceStatsForVitality(pet, petControlDevice); pet_lib.restoreDamage(pet, petControlDevice); if (hasObjVar(petControlDevice, "ai.pet.command")) { initializePetCommandList(pet, petControlDevice); } if (hasObjVar(petControlDevice, "alreadyTrained")) { setObjVar(pet, "alreadyTrained", true); } if (hasObjVar(petControlDevice, "ai.pet.trainedMount")) { pet_lib.mountablePetInit(pet, master); } if (!ai_lib.isDroid(pet) && !ai_lib.isAndroid(pet)) { restoreCustomization(pet, petControlDevice); } else if (hasObjVar(petControlDevice, pet_lib.VAR_PALVAR_BASE)) { restoreCustomization(pet, petControlDevice); if (hasObjVar(petControlDevice, pet_lib.VAR_PALVAR_CNT)) { int cnt = getIntObjVar(petControlDevice, pet_lib.VAR_PALVAR_CNT); if (cnt > -1) { cnt--; setObjVar(petControlDevice, pet_lib.VAR_PALVAR_CNT, cnt); if (cnt < 6) { switch (cnt) { case 5: customizationFadeToWhite(pet, 0.15f); sendSystemMessage(master, SID_SYS_CUST_FADING); break; case 4: customizationFadeToWhite(pet, 0.20f); sendSystemMessage(master, SID_SYS_CUST_FADING); break; case 3: customizationFadeToWhite(pet, 0.25f); sendSystemMessage(master, SID_SYS_CUST_FADING); break; case 2: customizationFadeToWhite(pet, 0.30f); sendSystemMessage(master, SID_SYS_CUST_FADING); break; case 1: customizationFadeToWhite(pet, 0.35f); sendSystemMessage(master, SID_SYS_CUST_FADING); break; case 0: customizationFadeToWhite(pet, 0.40f); sendSystemMessage(master, SID_SYS_CUST_GONE); removeObjVar(petControlDevice, pet_lib.VAR_PALVAR_CNT); break; } } } } } if (ai_lib.isDroid(pet) || ai_lib.isAndroid(pet)) { copyObjVar(petControlDevice, pet, "module_data"); if (hasObjVar(petControlDevice, "module_data.merchant_barker")) { attachScript(pet, "systems.crafting.droid.modules.merchant_barker"); } if (hasObjVar(petControlDevice, "module_data.bomb_level")) { attachScript(pet, "systems.crafting.droid.modules.droid_bomb"); } if (hasObjVar(petControlDevice, "module_data.stimpack_capacity")) { attachScript(pet, "systems.crafting.droid.modules.stimpack_dispensor"); } if (hasObjVar(petControlDevice, "module_data.auto_repair_power")) { attachScript(pet, "systems.crafting.droid.modules.auto_repair"); } if (hasObjVar(petControlDevice, "module_data.playback.modules")) { attachScript(pet, "systems.crafting.droid.modules.playback"); } if (hasObjVar(petControlDevice, "module_data.harvest_power")) { attachScript(pet, "systems.crafting.droid.modules.harvest_module"); } if (hasObjVar(petControlDevice, "module_data.entertainer_effects")) { attachScript(pet, "systems.crafting.droid.modules.entertainer_effect"); } if (hasObjVar(petControlDevice, "module_data.struct_maint")) { attachScript(pet, "systems.crafting.droid.modules.structure_maintenance"); } if (hasObjVar(petControlDevice, "module_data.trap_bonus")) { attachScript(pet, "systems.crafting.droid.modules.trap_thrower"); } if (hasObjVar(petControlDevice, "module_data.dancing_droid")) { attachScript(pet, "ai.dancing_droid"); } if (hasObjVar(petControlDevice, "module_data.sampling_power")) { attachScript(pet, "ai.hand_sampling"); } } String name = getAssignedName(petControlDevice); setName(pet, name); callable.setCallableLinks(master, petControlDevice, pet); } public static void customizationFadeToWhite(obj_id pet, float percent) throws InterruptedException { ranged_int_custom_var[] ricv = hue.getPalcolorVars(pet); Vector pcv = new Vector(); pcv.setSize(0); if (ricv == null || ricv.length == 0) { return; } for (ranged_int_custom_var ranged_int_custom_var : ricv) { if (ranged_int_custom_var.isPalColor()) { pcv = utils.addElement(pcv, (palcolor_custom_var) ranged_int_custom_var); } } if (pcv == null || pcv.size() == 0) { return; } for (Object o : pcv) { color old_color = ((palcolor_custom_var) o).getSelectedColor(); int old_r = old_color.getR(); int old_g = old_color.getG(); int old_b = old_color.getB(); int old_a = old_color.getA(); float d_r = (255 - old_r) * percent; float d_g = (255 - old_g) * percent; float d_b = (255 - old_b) * percent; float d_a = (255 - old_a) * percent; int new_r = old_r + (int) d_r; int new_g = old_g + (int) d_g; int new_b = old_b + (int) d_b; int new_a = old_a + (int) d_a; color new_color = new color(new_r, new_g, new_b, new_a); ((palcolor_custom_var) o).setToClosestColor(new_color); } } public static int modifyPaletteIndex(int idx) throws InterruptedException { int series_idx = idx % 8; if (series_idx == 0) { return idx; } return idx - 1; } public static void initDroidCraftedInventoryDroid(obj_id pet, obj_id petControlDevice) throws InterruptedException { obj_id inv = getObjectInSlot(petControlDevice, "inventory"); if (isIdValid(inv)) { setObjVar(pet, "ai.pet.hasContainer", true); } else { LOG("LOG_CHANNEL", "droid_deed::initDroidCraftedInventoryDroid -- No inventory detected on PCD intangible object."); } } public static void initDroidCraftedDatapadDroid(obj_id pet, obj_id petControlDevice) throws InterruptedException { obj_id dpad = getObjectInSlot(petControlDevice, "datapad"); if (isIdValid(dpad)) { setObjVar(pet, "ai.pet.hasDatapad", true); } } public static void initDroidPersonality(obj_id pet, obj_id petControlDevice) throws InterruptedException { if (hasObjVar(petControlDevice, "ai.diction")) { String personalityModuleType = getStringObjVar(petControlDevice, "ai.diction"); if (!personalityModuleType.equals("droid_default")) { setObjVar(pet, "ai.diction", personalityModuleType); } else { removeObjVar(petControlDevice, "ai.diction"); } } } public static void initDroidMedicalPower(obj_id pet, obj_id petControlDevice) throws InterruptedException { if (hasObjVar(petControlDevice, "medpower")) { float medModuleValue = getFloatObjVar(petControlDevice, "medpower"); setObjVar(pet, "medpower", medModuleValue); } } public static void initDroidCraftingPower(obj_id pet, obj_id petControlDevice, obj_id master) throws InterruptedException { if (hasObjVar(petControlDevice, "craftingStation")) { setObjVar(pet, "crafting.station", 1); setObjVar(pet, "crafting.private", 2); if (hasObjVar(petControlDevice, "craftingStationSpace")) { if (hasObjVar(pet, "crafting.type")) { int craftingTypeScratchpad = getIntObjVar(pet, "crafting.type"); setObjVar(pet, "crafting.type", craftingTypeScratchpad | CT_space | CT_reverseEngineering); } else { setObjVar(pet, "crafting.type", CT_space | CT_reverseEngineering); } } if (hasObjVar(petControlDevice, "craftingStationStructure")) { if (hasObjVar(pet, "crafting.type")) { int craftingTypeScratchpad = getIntObjVar(pet, "crafting.type"); setObjVar(pet, "crafting.type", craftingTypeScratchpad | CT_installation | CT_furniture); } else { setObjVar(pet, "crafting.type", CT_installation | CT_furniture); } } if (hasObjVar(petControlDevice, "craftingStationClothing")) { if (hasObjVar(pet, "crafting.type")) { int craftingTypeScratchpad = getIntObjVar(pet, "crafting.type"); setObjVar(pet, "crafting.type", craftingTypeScratchpad | CT_clothing | CT_armor); } else { setObjVar(pet, "crafting.type", CT_clothing | CT_armor); } } if (hasObjVar(petControlDevice, "craftingStationFood")) { if (hasObjVar(pet, "crafting.type")) { int craftingTypeScratchpad = getIntObjVar(pet, "crafting.type"); setObjVar(pet, "crafting.type", craftingTypeScratchpad | CT_food | CT_chemical); } else { setObjVar(pet, "crafting.type", CT_food | CT_chemical); } } if (hasObjVar(petControlDevice, "craftingStationWeapon")) { if (hasObjVar(pet, "crafting.type")) { int craftingTypeScratchpad = getIntObjVar(pet, "crafting.type"); setObjVar(pet, "crafting.type", craftingTypeScratchpad | CT_weapon | CT_droid | CT_misc); } else { setObjVar(pet, "crafting.type", CT_weapon | CT_droid | CT_misc); } } } } public static void initDroidRepairPower(obj_id pet, obj_id petControlDevice) throws InterruptedException { if (hasObjVar(petControlDevice, "ai.pet.isRepairDroid")) { setObjVar(pet, "ai.pet.isRepairDroid", true); } } public static void restoreCustomization(obj_id pet, obj_id petControlDevice) throws InterruptedException { if (hasObjVar(petControlDevice, pet_lib.VAR_PALVAR_BASE)) { obj_var_list ovl = getObjVarList(petControlDevice, pet_lib.VAR_PALVAR_VARS); if (ovl != null) { int numItem = ovl.getNumItems(); for (int i = 0; i < numItem; i++) { obj_var ov = ovl.getObjVar(i); String var = ov.getName(); int idx = ov.getIntData(); hue.setColor(pet, var, idx); } } int idx = getIntObjVar(petControlDevice, VAR_PALVAR_VARS + "./private/index_texture_1"); setRangedIntCustomVarValue(pet, "/private/index_texture_1", idx); } } public static void doTargetHarvest(obj_id pet, obj_id master) throws InterruptedException { dictionary parms = new dictionary(); parms.put("droid", pet); parms.put("player", master); parms.put("target", getLookAtTarget(master)); messageTo(pet, "doTargetHarvest", parms, 0, false); return; } public static void doPetThrowTrap(obj_id pet, obj_id master, int commandNum) throws InterruptedException { dictionary params = new dictionary(); params.put("droid", pet); params.put("player", master); params.put("trapNum", commandNum); messageTo(pet, "doPetThrowTrap", params, 0, false); return; } public static boolean isNewPlayerHelperDroid(obj_id pet) throws InterruptedException { if (isIdValid(pet)) { String name = getCreatureName(pet); if (name != null && name.equals("nhelper_droid")) { return true; } if (name.equals("tutorial_droid")) { return true; } } return false; } public static String[] getLightingEffects(obj_id droid) throws InterruptedException { if (!isIdValid(droid)) { return null; } if (!hasObjVar(droid, "module_data.entertainer_effects")) { return null; } int raw_effects = getIntObjVar(droid, "module_data.entertainer_effects"); if (raw_effects < 1) { return null; } int i = 1; Vector available_effects = new Vector(); available_effects.setSize(0); while (i <= LIGHTING_EFFECTS.length) { int result = (int)((raw_effects % StrictMath.pow(10, i)) / StrictMath.pow(10, i - 1)); if (result >= 1) { available_effects = utils.addElement(available_effects, LIGHTING_EFFECTS[i - 1]); } i++; } if (available_effects.size() < 1) { return null; } else { String[] _available_effects = new String[0]; if (available_effects != null) { _available_effects = new String[available_effects.size()]; available_effects.toArray(_available_effects); } return _available_effects; } } public static int calculateMaxTrapLoad(obj_id objItem) throws InterruptedException { if (hasObjVar(objItem, "module_data.trap_bonus")) { return (int)BASE_MAX_TRAP_LOAD + (getIntObjVar(objItem, "module_data.trap_bonus") / 4); } return (int)BASE_MAX_TRAP_LOAD + (getIntObjVar(callable.getCallableCD(objItem), "module_data.trap_bonus") / 4); } public static void cleanOldDroidDeed(obj_id deed) throws InterruptedException { if (hasObjVar(deed, "armorEffectiveness")) { removeObjVar(deed, "armorEffectiveness"); } if (hasObjVar(deed, "armorToughness")) { removeObjVar(deed, "armorToughness"); } for (int attribNum = 0; attribNum < NUM_ATTRIBUTES; attribNum++) { if (hasObjVar(deed, "creature_attribs." + create.MAXATTRIBNAMES[attribNum])) { if (("creature_attribs." + create.MAXATTRIBNAMES[attribNum]) != "creature_attribs.maxHealth") { removeObjVar(deed, "creature_attribs." + create.MAXATTRIBNAMES[attribNum]); } } } return; } public static int getDroidCapLevel(obj_id who, int level) throws InterruptedException { if (craftinglib.isTrader(who)) { return 90; } return 60; } public static void initDroidDefaultStats(obj_id deed) throws InterruptedException { dictionary droidDefaultStatsDict = dataTableGetRow(TBL_MOB_STAT_BALANCE, DEFAULT_DROID_LEVEL - 1); int creature_attribs_level = DEFAULT_DROID_LEVEL; int creature_attribs_maxHealth = droidDefaultStatsDict.getInt("HP"); int creature_attribs_maxConstitution = 0; int creature_attribs_toHitChance = droidDefaultStatsDict.getInt("ToHit"); int creature_attribs_defenseValue = droidDefaultStatsDict.getInt("Def"); float creatureAttribs_dps = droidDefaultStatsDict.getFloat("damagePerSecond"); int creature_attribs_minDamage = (int)creatureAttribs_dps; int creature_attribs_maxDamage = (int)creatureAttribs_dps * 3; float creature_attribs_scale = 1.0f; String creature_attribs_rangedWeapon = null; int creature_attribs_general_protection = getIntObjVar(deed, "creature_attribs.general_protection"); if (creature_attribs_general_protection == 0) { creature_attribs_general_protection = droidDefaultStatsDict.getInt("Elite_Armor"); } dictionary droidDeedStats = new dictionary(); droidDeedStats.put("creature_attribs.level", creature_attribs_level); droidDeedStats.put("creature_attribs.maxHealth", creature_attribs_maxHealth); droidDeedStats.put("creature_attribs.maxConstitution", creature_attribs_maxConstitution); droidDeedStats.put("creature_attribs.general_protection", creature_attribs_general_protection); droidDeedStats.put("creature_attribs.toHitChance", creature_attribs_toHitChance); droidDeedStats.put("creature_attribs.defenseValue", creature_attribs_defenseValue); droidDeedStats.put("creature_attribs.minDamage", creature_attribs_minDamage); droidDeedStats.put("creature_attribs.maxDamage", creature_attribs_maxDamage); droidDeedStats.put("creature_attribs.rangedWeapon", ""); writeOutNewDroidDeedAttribs(deed, droidDeedStats); } public static void initDroidCombatStats(obj_id deed, dictionary droidCombatStats) throws InterruptedException { int tempCreatureLevel = 0; int tempCreatureDamageLevel = 0; int tempCreatureDefenseLevel = 0; int tempCreatureProtectionLevel = 0; int tempArmorModule = droidCombatStats.getInt("armorModuleValue"); if (tempArmorModule > 0) { if (tempArmorModule <= 2) { tempCreatureLevel = 5; tempCreatureDefenseLevel = 5; tempCreatureProtectionLevel = DEFENSE_MODULE_PROTECT_LVL; } else if (tempArmorModule <= 4) { tempCreatureLevel = 10; tempCreatureDefenseLevel = 10; tempCreatureProtectionLevel = (2 * DEFENSE_MODULE_PROTECT_LVL); } else if (tempArmorModule <= 6) { tempCreatureLevel = 15; tempCreatureDefenseLevel = 15; tempCreatureProtectionLevel = (3 * DEFENSE_MODULE_PROTECT_LVL); } else if (tempArmorModule <= 8) { tempCreatureLevel = 20; tempCreatureDefenseLevel = 20; tempCreatureProtectionLevel = (4 * DEFENSE_MODULE_PROTECT_LVL); } else if (tempArmorModule <= 10) { tempCreatureLevel = 25; tempCreatureDefenseLevel = 25; tempCreatureProtectionLevel = (5 * DEFENSE_MODULE_PROTECT_LVL); } else { tempCreatureLevel = 30; tempCreatureDefenseLevel = 30; tempCreatureProtectionLevel = (6 * DEFENSE_MODULE_PROTECT_LVL); } } int tempCombatModule = droidCombatStats.getInt("combatModuleValue"); if (tempCombatModule > 0) { if (tempCombatModule <= 50) { tempCreatureLevel += 5; tempCreatureDamageLevel += 5; tempCreatureProtectionLevel += COMBAT_MODULE_PROTECT_LVL; } else { tempCreatureLevel += tempCombatModule / 10; tempCreatureDamageLevel += tempCombatModule / 10; tempCreatureProtectionLevel += (COMBAT_MODULE_PROTECT_LVL * (int)(tempCombatModule / 100)); } } if (tempCreatureLevel < 1 || tempCreatureDamageLevel < 0) { tempCreatureLevel = 1; tempCreatureDamageLevel = 1; } else if (tempCreatureLevel > 90 || tempCreatureDamageLevel > 90) { tempCreatureLevel = 90; tempCreatureDamageLevel = 90; } dictionary droidDefaultStatsDict = dataTableGetRow(TBL_MOB_STAT_BALANCE, tempCreatureLevel - 1); int creature_attribs_level = tempCreatureLevel; int creature_attribs_maxHealth = droidDefaultStatsDict.getInt("HP"); int creature_attribs_toHitChance = droidDefaultStatsDict.getInt("ToHit"); int creature_attribs_defenseValue = droidDefaultStatsDict.getInt("Def"); float creature_attribs_dps = droidDefaultStatsDict.getFloat("damagePerSecond"); int creature_attribs_minDamage = Math.round(creature_attribs_dps); int creature_attribs_maxDamage = Math.round(creature_attribs_dps * 3.0f); int creature_attribs_general_protection = droidCombatStats.getInt("creature_attribs.general_protection"); if (creature_attribs_general_protection == 0) { creature_attribs_general_protection = droidDefaultStatsDict.getInt("Elite_Armor"); } String creature_attribs_rangedWeapon = null; if (tempCreatureLevel > 1) { setObjVar(deed, "combatModule", tempCombatModule); creature_attribs_maxHealth = dataTableGetInt(TBL_MOB_STAT_BALANCE, tempCreatureLevel - 1, "HP"); if (tempCreatureDefenseLevel > 1) { int temp_droid_attribs_defenseValue = dataTableGetInt(TBL_MOB_STAT_BALANCE, tempCreatureDefenseLevel - 1, "Def"); if (temp_droid_attribs_defenseValue > creature_attribs_defenseValue) { creature_attribs_defenseValue = temp_droid_attribs_defenseValue; } } if (tempCreatureProtectionLevel > creature_attribs_general_protection) { creature_attribs_general_protection = tempCreatureProtectionLevel; } if (tempCreatureDamageLevel > 1) { if (hasObjVar(deed, "pet.nonCombatDroid")) { removeObjVar(deed, "pet.nonCombatDroid"); } setObjVar(deed, "pet.combatDroid", 1); String droidName = getStringObjVar(deed, "creature_attribs.type"); dictionary droidModDamageStatsDict = dataTableGetRow(TBL_MOB_STAT_BALANCE, tempCreatureDamageLevel - 1); int temp_droidMod_MinDamage = Math.round(droidModDamageStatsDict.getFloat("damagePerSecond")); if (temp_droidMod_MinDamage > creature_attribs_minDamage) { creature_attribs_minDamage = temp_droidMod_MinDamage; } int temp_droidMod_MaxDamage = Math.round(droidModDamageStatsDict.getFloat("damagePerSecond") * 3.0f); if (temp_droidMod_MaxDamage > creature_attribs_maxDamage) { creature_attribs_maxDamage = temp_droidMod_MaxDamage; } int temp_droidMod_ToHit = droidModDamageStatsDict.getInt("ToHit"); if (temp_droidMod_ToHit > creature_attribs_toHitChance) { creature_attribs_toHitChance = temp_droidMod_ToHit; } int droidRangedCapable = utils.dataTableGetInt(TBL_DROID_COMBAT, droidName, "hasRangedAttack"); if (droidRangedCapable == 1) { creature_attribs_rangedWeapon = DROID_RANGED_WEAPON; } } } else { setObjVar(deed, "pet.nonCombatDroid", 1); } dictionary droidDeedStats = new dictionary(); droidDeedStats.put("creature_attribs.level", creature_attribs_level); droidDeedStats.put("creature_attribs.maxHealth", creature_attribs_maxHealth); droidDeedStats.put("creature_attribs.general_protection", creature_attribs_general_protection); droidDeedStats.put("creature_attribs.toHitChance", creature_attribs_toHitChance); droidDeedStats.put("creature_attribs.defenseValue", creature_attribs_defenseValue); droidDeedStats.put("creature_attribs.minDamage", creature_attribs_minDamage); droidDeedStats.put("creature_attribs.maxDamage", creature_attribs_maxDamage); if (creature_attribs_rangedWeapon != null && !creature_attribs_rangedWeapon.equals("")) { droidDeedStats.put("creature_attribs.rangedWeapon", creature_attribs_rangedWeapon); } writeOutNewDroidDeedAttribs(deed, droidDeedStats); return; } public static void writeOutNewDroidDeedAttribs(obj_id deed, dictionary droidDeedStats) throws InterruptedException { int creature_attribs_level = droidDeedStats.getInt("creature_attribs.level"); int creature_attribs_maxHealth = droidDeedStats.getInt("creature_attribs.maxHealth"); int creature_attribs_general_protection = droidDeedStats.getInt("creature_attribs.general_protection"); int creature_attribs_toHitChance = droidDeedStats.getInt("creature_attribs.toHitChance"); int creature_attribs_defenseValue = droidDeedStats.getInt("creature_attribs.defenseValue"); int creature_attribs_minDamage = droidDeedStats.getInt("creature_attribs.minDamage"); int creature_attribs_maxDamage = droidDeedStats.getInt("creature_attribs.maxDamage"); String creature_attribs_rangedWeapon = droidDeedStats.getString("creature_attribs.rangedWeapon"); setObjVar(deed, "creature_attribs.level", creature_attribs_level); setObjVar(deed, "creature_attribs.maxHealth", creature_attribs_maxHealth); setObjVar(deed, "creature_attribs.maxConstitution", 0); setObjVar(deed, "creature_attribs.general_protection", creature_attribs_general_protection); setObjVar(deed, "creature_attribs.toHitChance", creature_attribs_toHitChance); setObjVar(deed, "creature_attribs.defenseValue", creature_attribs_defenseValue); setObjVar(deed, "creature_attribs.minDamage", creature_attribs_minDamage); setObjVar(deed, "creature_attribs.maxDamage", creature_attribs_maxDamage); setObjVar(deed, "creature_attribs.aggroBonus", 0.0f); setObjVar(deed, "creature_attribs.critChance", 0.0f); setObjVar(deed, "creature_attribs.critSave", 0.0f); setObjVar(deed, "creature_attribs.scale", 1.0f); setObjVar(deed, "creature_attribs.stateResist", 0.0f); if (creature_attribs_rangedWeapon != null && !creature_attribs_rangedWeapon.equals("")) { setObjVar(deed, "creature_attribs.rangedWeapon", creature_attribs_rangedWeapon); } return; } public static void reviseCombatDroidPCD(obj_id petControlDevice, obj_id master, obj_id pet) throws InterruptedException { if (!hasObjVar(petControlDevice, "postCuPCD")) { int combatStrength = 0; if (hasObjVar(petControlDevice, "pet.combatDroid")) { combatStrength = (int)(getFloatObjVar(petControlDevice, "pet.combatDroid")); cleanOldDroidDeed(petControlDevice); dictionary droidCombatStats = new dictionary(); if (hasObjVar(petControlDevice, "armorModule")) { droidCombatStats.put("armorModuleValue", getIntObjVar(petControlDevice, "armorModule")); } if (combatStrength > 0) { droidCombatStats.put("combatModuleValue", combatStrength); } initDroidCombatStats(petControlDevice, droidCombatStats); messageTo(pet, "handlePackRequest", null, 1, false); dictionary respawnParams = new dictionary(); respawnParams.put("master", master); messageTo(petControlDevice, "respawnDroid", respawnParams, 5, false); } else { initDroidDefaultStats(petControlDevice); } setObjVar(petControlDevice, "postCuPCD", 2); } else if (getIntObjVar(petControlDevice, "postCuPCD") == 1) { if (hasObjVar(petControlDevice, "pet.nonCombatDroid")) { dictionary droidCombatStats = new dictionary(); if (hasObjVar(petControlDevice, "armorModule")) { droidCombatStats.put("armorModuleValue", getIntObjVar(petControlDevice, "armorModule")); } droidCombatStats.put("combatModuleValue", 300); initDroidCombatStats(petControlDevice, droidCombatStats); messageTo(pet, "handlePackRequest", null, 1, false); dictionary respawnParams = new dictionary(); respawnParams.put("master", master); messageTo(petControlDevice, "respawnDroid", respawnParams, 5, false); } setObjVar(petControlDevice, "postCuPCD", 2); } return; } public static void openLearnCommandSui(obj_id pet, obj_id player) throws InterruptedException { if (!pet_lib.getLearnableCommandList(pet)) { sendSystemMessage(player, new string_id("pet/pet_Ability", "no_learnable_commands")); return; } String title = utils.packStringId(new string_id("pet/pet_ability", "learn_command_title")); String prompt = utils.packStringId(new string_id("pet/pet_ability", "learn_command_header")); int pid = createSUIPage(sui.SUI_LISTBOX, pet, player, "handleLearnCommandDialog"); setSUIProperty(pid, "", "Size", "450,575"); setSUIProperty(pid, sui.LISTBOX_TITLE, sui.PROP_TEXT, title); setSUIProperty(pid, sui.LISTBOX_PROMPT, sui.PROP_TEXT, prompt); sui.listboxButtonSetup(pid, sui.OK_CANCEL); setSUIProperty(pid, sui.LISTBOX_BTN_OK, sui.PROP_TEXT, "@train"); setSUIProperty(pid, sui.LISTBOX_BTN_CANCEL, sui.PROP_TEXT, "@cancel"); clearSUIDataSource(pid, sui.LISTBOX_DATASOURCE); Vector commandList = utils.getResizeableStringArrayScriptVar(pet, "ai.learnCommand.commandNameList"); for (int i = 0; i < commandList.size(); i++) { addSUIDataItem(pid, sui.LISTBOX_DATASOURCE, "" + i); setSUIProperty(pid, sui.LISTBOX_DATASOURCE + "." + i, sui.PROP_TEXT, ((String)commandList.get(i))); } subscribeToSUIProperty(pid, sui.LISTBOX_LIST, sui.PROP_SELECTEDROW); subscribeToSUIProperty(pid, sui.LISTBOX_TITLE, sui.PROP_TEXT); showSUIPage(pid); flushSUIPage(pid); utils.setScriptVar(pet, "ai.learnCommand.pid", pid); utils.setScriptVar(pet, "ai.learnCommand.pet", pet); } public static boolean hasPetControlDevice(obj_id pet) throws InterruptedException { if (isValidId(pet) && exists(pet)) { return callable.hasCallableCD(pet); } else { return false; } } public static obj_id getPetControlDevice(obj_id pet) throws InterruptedException { obj_id petControlDevice = obj_id.NULL_ID; if (exists(pet) && isValidId(pet) && callable.hasCallableCD(pet)) { petControlDevice = callable.getCallableCD(pet); } return petControlDevice; } public static void destroyOfficerPets(obj_id player) throws InterruptedException { obj_id datapad = utils.getPlayerDatapad(player); if (!isIdValid(datapad) || !exists(datapad)) { return; } obj_id[] dataItems = getContents(datapad); if (dataItems == null || dataItems.length < 1) { return; } for (obj_id dataItem : dataItems) { if (hasObjVar(dataItem, "pet.creatureName")) { if ((getStringObjVar(dataItem, "pet.creatureName")).startsWith("officer_reinforcement_")) { destroyObject(dataItem); } } } return; } public static void addToHarvestDroidArray(obj_id target, obj_id[] players) throws InterruptedException { if (!isIdValid(target) || players == null || players.length == 0) { return; } for (obj_id player : players) { if (callable.hasCallable(player, callable.CALLABLE_TYPE_COMBAT_PET)) { obj_id objCallable = callable.getCallable(player, callable.CALLABLE_TYPE_COMBAT_PET); if (!isIdValid(objCallable) || !exists(objCallable) || !hasScript(objCallable, "systems.crafting.droid.modules.harvest_module")) { continue; } Vector toHarvest = new Vector(); toHarvest.setSize(0); if (utils.hasScriptVar(objCallable, DROID_HARVEST_ARRAY)) { toHarvest = utils.getResizeableObjIdArrayScriptVar(objCallable, DROID_HARVEST_ARRAY); } utils.addElement(toHarvest, target); utils.setScriptVar(objCallable, DROID_HARVEST_ARRAY, toHarvest); messageTo(objCallable, "runHarvestRoutine", null, 1.0f, false); } } } public static boolean hasMountName(obj_id pcd) throws InterruptedException { if (!isIdValid(pcd) || !exists(pcd)) { return true; } if (!hasObjVar(pcd, "pet.mountName")) { return false; } return true; } public static void setMountName(obj_id pcd, String mountName) throws InterruptedException { if (!isIdValid(pcd) || !exists(pcd)) { return; } setName(pcd, mountName); setObjVar(pcd, "pet.mountName", mountName); obj_id yourPad = getContainedBy(pcd); obj_id player = getContainedBy(yourPad); if (!isIdValid(player) || !exists(player)) { return; } obj_id mount = callable.getCDCallable(pcd); if (!isIdValid(mount) || !exists(mount)) { return; } setName(mount, mountName); } public static String getMountName(obj_id pcd) throws InterruptedException { if (hasObjVar(pcd, "pet.mountName")) { return getStringObjVar(pcd, "pet.mountName"); } return null; } public static boolean isMounted(obj_id player) throws InterruptedException { if (isIdValid(player)) { if (getState(player, STATE_RIDING_MOUNT) > 0) { return true; } } return false; } public static obj_id[] getPcdsForType(obj_id master, int type) throws InterruptedException { obj_id pDataPad = utils.getPlayerDatapad(master); obj_id[] dPadContents = utils.getContents(pDataPad, false); Vector resizedContents = new Vector(); resizedContents.setSize(0); for (obj_id dPadContent : dPadContents) { if (isPetType(dPadContent, type)) { utils.addElement(resizedContents, dPadContent); } } obj_id[] pcdsForType = new obj_id[resizedContents.size()]; resizedContents.toArray(pcdsForType); return pcdsForType; } public static obj_id validateDroidCommand(obj_id player) throws InterruptedException { obj_id droid = callable.getCallable(player, callable.CALLABLE_TYPE_COMBAT_PET); if (!isIdValid(droid) || !exists(droid)) { return null; } if (!pet_lib.isDroidPet(droid)) { return null; } if (isIncapacitated(droid) || isDead(droid)) { return null; } obj_id petControlDevice = callable.getCallableCD(droid); if (!isIdValid(petControlDevice) || !exists(petControlDevice)) { return null; } int powerLevel = getIntObjVar(petControlDevice, "ai.pet.powerLevel"); if (powerLevel >= OUT_OF_POWER) { return null; } return droid; } }