Files
dsrc/sku.0/sys.server/compiled/game/script/library/loot.java
T
AconiteX 8a35cd9085 Refractor approach to special creature DNA loot
The point of this change is to get rid of all of the unnecessary DNA loot roll chance scripts located at script.item.dna.* and instead replace it with a proper implementation. There are 2 new columns in creatures.tab (dnaChancePct and dnaItemName) which are parsed during createCreature() and loot events to properly roll for loot chance of the DNA and to add it to a creature's inventory container.
2021-07-13 02:29:08 -04:00

2637 lines
115 KiB
Java
Executable File

package script.library;
import script.*;
import java.util.Enumeration;
import java.util.Vector;
public class loot extends script.base_script
{
public loot()
{
}
public static final int COL_LOOT_MULTIPLIER_ON = 1;
public static final String TBL_CREATURES = "datatables/mob/creatures.iff";
public static final String TBL_COMPONENT_DATA = "datatables/loot/component_data.iff";
public static final String VAR_DENY_LOOT = "denyLoot";
public static final String VAR_LOOT_QUALITY = "loot.loot_quality";
public static final String CHRONICLES_LOOT_TOGGLE_OBJVAR = "chroniclesLoot_toggledOff";
public static final String TBL_EXCLUSION = "datatables/loot/exclusion.iff";
public static final String COL_TEMPLATE = "TEMPLATE";
public static final String COL_EXCLUDE = "EXCLUDE";
public static final String DATA_ITEM = "dataItem";
public static final String DATA_ITEM_FACTION = DATA_ITEM + ".faction";
public static final String DATA_ITEM_VALUE = DATA_ITEM + ".value";
public static final String TBL_DATA_ITEM_VALUE = "datatables/data_item/redeem_value.iff";
public static final String ENCODED_DISK = "object/tangible/encoded_disk/encoded_disk_base.iff";
public static final String SPECIAL_LOOT = "datatables/loot/npc_special_loot.iff";
public static final String COLLECTIBLE_LOOT = "datatables/loot/npc_collectible_loot.iff";
public static final String CASH_ITEM_TEMPLATE = "object/tangible/item/loot_cash.iff";
public static final String MEATLUMP_LUMP = "item_meatlump_lump_01_01";
public static final String MEATLUMP_LOOT_TABLE = "datatables/loot/dungeon/meatlump_dungeon_container_loot.iff";
public static final String CREATURES_TABLE = "datatables/mob/creatures.iff";
public static final String COLLECTIONS_LOOT_TABLE = "datatables/loot/loot_items/collectible/collection_loot.iff";
public static final String COLLECTIONS_PVP_RANK_TABLE = "datatables/loot/loot_items/collectible/collection_pvp_rank.iff";
public static final String COLLECTIONS_PVP_LOOT_TABLE = "datatables/loot/loot_items/collectible/collection_pvp_loot.iff";
public static final int MIN_CREATURE_LEVEL = 1;
public static final int MAX_CREATURE_LEVEL = 85;
public static final float MAX_ALLOWED_WEAPON_INTENSITY = 0.90f;
public static final float MIN_ALLOWED_WEAPON_INTENSITY = 0.35f;
public static final int BASE_CHANCE_FOR_CASH = 40;
public static final int BASE_CHANCE_FOR_RESOURCES = 40;
public static final int BASE_CHANCE_FOR_ENZYME = 25;
public static final string_id SID_REWARD_ITEM = new string_id("collection", "reward_item");
public static final int COLLECTION_PVP_ROLL = 80;
public static final String FORAGE_LOGGING_CATEGORY = "foraging";
public static final boolean FORAGE_LOGGING_ON = false;
public static final int RARE_COMPONENT_DIVISOR = 10;
public static final int SUPER_RARE_COMPONENT_DIVISOR = 5;
public static final int WORM_ROLL_INT = 80;
public static final int ENZYME = 0;
public static final int WORM = 1;
public static final int COMPONENT = 2;
public static final int TREASURE = 3;
public static final int BAIT = 99;
public static final int NOTHING = 98;
public static final int FORAGE_BASE_ONE = 14;
public static final int FORAGE_BASE_TWO = 28;
public static final int PLAYER_DEFAULT_FORAGE_CHANCE = 0;
public static final int DEFAULT_ENZYME_CHANCE = 40;
public static final int DEFAULT_WORM_CHANCE = 40;
public static final int DEFAULT_TREASURE_CHANCE = 0;
public static final int DEFAULT_COMPONENT_CHANCE = 40;
public static final float ENZYME_MODIFIER = 0.0f;
public static final float TREASURE_MODIFIER = 0.0f;
public static final float PLAYER_DEFAULT_FIND_MODIFIER = 0.0f;
public static final float LUCKY_FIND_MODIFIER = 6.0f;
public static final String FORAGING_RARE_TABLE = "datatables/foraging/forage_global_rare.iff";
public static final String FORAGING_ENEMY_TABLE = "datatables/foraging/forage_enemy.iff";
public static final String FORAGING_LOOT_ROLL_TABLE = "datatables/foraging/foraging_loot_roll.iff";
public static final String LOOT_LOW_COL = "low";
public static final String LOOT_HIGH_COL = "high";
public static final String LOOT_ENZYME = "enzyme";
public static final String LOOT_COMPONENT = "component";
public static final String LOOT_WORM = "worm";
public static final String LOOT_BAIT = "bait";
public static final String LOOT_TREASURE = "treasure";
public static final String FORAGE_ENEMY_SCRIPT = "creature.foraging_enemy";
public static final String FORAGING_STF = "player/player_utility";
public static final string_id FOUND_TREASURE = new string_id("player/player_utility", "forage_found_treasure");
public static final string_id TREASURE_BONUS_ROLL = new string_id("player/player_utility", "treasure_buff_extra_roll");
public static final string_id TREASURE_BONUS = new string_id("player/player_utility", "treasure_map_buff_bonus");
public static final string_id SID_FULL_INVENTORY = new string_id("player/player_utility", "forage_full_inventory");
public static final string_id FOUND_NOTHING = new string_id("player/player_utility", "forage_found_nothing");
public static final string_id FOUND_SOMETHING = new string_id("player/player_utility", "forage_found_something");
public static final string_id FOUND_WORM = new string_id("player/player_utility", "forage_found_worm");
public static final string_id FOUND_COMPONENT = new string_id("player/player_utility", "forage_found_component");
public static final string_id FOUND_ENZYME = new string_id("player/player_utility", "forage_found_enzyme");
public static final string_id ENZYME_BONUS_ROLL = new string_id("player/player_utility", "enzyme_buff_extra_roll");
public static final string_id ENZYME_BONUS = new string_id("player/player_utility", "truffle_pig_buff_bonus");
public static final string_id FORAGE_BONUS = new string_id("player/player_utility", "ice_cream_buff_bonus");
public static final string_id LUCK_BONUS = new string_id("player/player_utility", "luck_buff_bonus");
public static final String[] COMPONENT_PLANETS =
{
"corellia",
"dantooine",
"dathomir",
"endor",
"naboo",
"tatooine",
"yavin4"
};
public static final String[] CHEST_TYPES = {
"rare",
"exceptional",
"legendary"
};
private static final String CHEST_BASE = "rare_loot_chest_quality_";
private static final String RLS_EFFECT = "appearance/pt_rare_chest.prt";
private static final String RLS_SOUND = "sound/rare_loot_chest.snd";
private static final boolean RLS_DISABLED = utils.checkConfigFlag("GameServer", "rlsDisabled");
private static final boolean RLS_MACROS_DISABLED = utils.checkConfigFlag("GameServer", "rlsDropChanceDisableMacros");
private static final int RLS_DROP_CHANCE = utils.getIntConfigSetting("GameServer", "rlsDropChance", 1);
private static final int RLS_RARE_CHOICE_CHANCE = utils.getIntConfigSetting("GameServer", "rlsRareDropChance", 70);
private static final int RLS_EXCEPTIONAL_CHOICE_CHANCE = utils.getIntConfigSetting("GameServer", "rlsExceptionalDropChance", 25);
private static final int RLS_LEGENDARY_CHOICE_CHANCE = utils.getIntConfigSetting("GameServer", "rlsLegendaryDropChance", 5);
private static final int RLS_TIME_BETWEEN_AWARDS = utils.getIntConfigSetting("GameServer", "rlsMinTimeBetweenAwards", 900);
private static final int RLS_LOWER_LEVEL_BAND = utils.getIntConfigSetting("GameServer", "rlsMaxLevelsBelowPlayerLevel", 6);
private static final int RLS_UPPER_LEVEL_BAND = utils.getIntConfigSetting("GameServer", "rlsMaxLevelsAbovePlayerLevel", 6);
private static final int RLS_MIN_DIST_FROM_LAST_LOOT = utils.getIntConfigSetting("GameServer", "rlsMinDistanceFromLastLoot", 5);
public static final String OBJVAR_RLS_LAST_LOOT_TIME = "loot.rls.lastChestAwardTime";
public static final String OBJVAR_RLS_LAST_LOOT_LOCATION = "loot.rls.lastLootedLocation";
public static final String OBJVAR_RLS_LAST_LOOT_CHEST = "loot.rls.lastLootedChest";
public static final String OBJVAR_DNA_LOOT_CHANCE = "loot.dnaLootChance";
public static final String OBJVAR_DNA_LOOT_ITEM_NAME = "loot.dnaLootItemName";
public static boolean addLoot(obj_id target) throws InterruptedException
{
if (!isIdValid(target))
{
return false;
}
if (hasObjVar(target, VAR_DENY_LOOT))
{
return false;
}
boolean hasLoot = false;
obj_id inv = utils.getInventoryContainer(target);
if (inv == null)
{
return false;
}
String mobType = ai_lib.getCreatureName(target);
if (mobType == null || mobType.length() < 1)
{
String err = "WARNING: loot::addLoot(" + target + ") returning false because getCreatureName failed. Template=" + getTemplateName(target) + ", IsAuthoritative=" + target.isAuthoritative() + ". Stack Trace as follows:";
CustomerServiceLog("creatureNameErrors", err);
debugServerConsoleMsg(target, err);
Thread.dumpStack();
return false;
}
if (!hasObjVar(target, "storytellerid"))
{
int cash = getNpcMoney(target);
if (addCashAsLoot(target, cash))
{
hasLoot = true;
}
}
hasLoot |= setupLootItems(target);
hasLoot |= addCollectionLoot(target);
hasLoot |= addRareLoot(target);
int niche = ai_lib.aiGetNiche(mobType);
if (niche == NICHE_MONSTER || niche == NICHE_HERBIVORE || niche == NICHE_CARNIVORE || niche == NICHE_PREDATOR)
{
int[] hasResource = corpse.hasResource(mobType);
if (hasResource != null && hasResource.length > 0)
{
setObjVar(target, corpse.VAR_HAS_RESOURCE, hasResource);
}
if (isInTutorialArea(target))
{
return false;
}
hasLoot |= addBeastEnzymes(target);
}
return hasLoot;
}
public static int getCashForLevel(String mobType, int level) throws InterruptedException
{
if (mobType == null || mobType.equals("") || level < 1)
{
return 0;
}
int lbound = dataTableGetInt(TBL_CREATURES, mobType, "minCash");
int ubound = dataTableGetInt(TBL_CREATURES, mobType, "maxCash");
if (ubound == 0)
{
return 0;
}
if (lbound > 0 && ubound > 0)
{
return rand(lbound, ubound);
}
int minCash = level;
if (lbound > 0 && minCash < lbound)
{
minCash = lbound;
}
int maxCash = level * 17;
if (ubound > 0 && maxCash > ubound)
{
maxCash = ubound;
}
return rand(minCash, maxCash);
}
public static boolean addResourceLoot(obj_id target) throws InterruptedException
{
if (rand(1, 100) > BASE_CHANCE_FOR_RESOURCES)
{
return false;
}
String mobType = ai_lib.getCreatureName(target);
int niche = ai_lib.aiGetNiche(mobType);
if (niche != NICHE_MONSTER && niche != NICHE_HERBIVORE && niche != NICHE_CARNIVORE && niche != NICHE_PREDATOR)
{
return false;
}
int[] hasResource = corpse.hasResource(mobType);
if (hasResource == null || hasResource.length == 0)
{
return false;
}
obj_id inv = utils.getInventoryContainer(target);
dictionary resourceData = corpse.getRandomHarvestCorpseResources(obj_id.NULL_ID, target);
java.util.Enumeration keys = resourceData.keys();
int finalAmount = 0;
while (keys.hasMoreElements())
{
String resourceType = (String)(keys.nextElement());
int amt = resourceData.getInt(resourceType);
if (amt <= 0)
{
continue;
}
String sceneName = getCurrentSceneName();
String rsrcMapTable = "datatables/creature_resource/resource_scene_map.iff";
String correctedPlanetName = dataTableGetString(rsrcMapTable, sceneName, 1);
if (correctedPlanetName == null || correctedPlanetName.equals(""))
{
correctedPlanetName = "tatooine";
}
resourceType = resourceType + "_" + correctedPlanetName;
int useDistMap = dataTableGetInt(rsrcMapTable, sceneName, "useDistributionMap");
location worldLoc = getWorldLocation(target);
if (useDistMap == 0)
{
worldLoc.area = correctedPlanetName;
}
finalAmount += corpse.extractCorpseResource(resourceType, amt, worldLoc, obj_id.NULL_ID, inv, 1);
}
return (finalAmount > 0);
}
public static int getCalculatedAttribute(int minVal, int maxVal, int creatureLevel, int minDropLevel, int maxDropLevel) throws InterruptedException
{
return Math.round(getCalculatedAttribute((float)minVal, maxVal, creatureLevel, minDropLevel, maxDropLevel));
}
public static float getCalculatedAttribute(float minVal, float maxVal, int creatureLevel, int minDropLevel, int maxDropLevel) throws InterruptedException
{
float rank = (float)(creatureLevel - minDropLevel) / (maxDropLevel - minDropLevel);
if (rank < -1.0f)
{
rank = -1.0f;
}
else if (rank > 2.0f)
{
rank = 2.0f;
}
float rslt = random.distributedRand(minVal, maxVal, rank);
LOG("loot", "getCalculatedAttribute: -> returning " + rslt);
return rslt;
}
public static int getCalculatedAttribute(int minVal, int maxVal, int creatureLevel) throws InterruptedException
{
return getCalculatedAttribute(minVal, maxVal, creatureLevel, MIN_CREATURE_LEVEL, MAX_CREATURE_LEVEL);
}
public static float getCalculatedAttribute(float minVal, float maxVal, int creatureLevel) throws InterruptedException
{
return getCalculatedAttribute(minVal, maxVal, creatureLevel, MIN_CREATURE_LEVEL, MAX_CREATURE_LEVEL);
}
public static int getRowIndexForComponent(String componentTemplate) throws InterruptedException
{
if (componentTemplate == null || componentTemplate.equals(""))
{
return -1;
}
return dataTableSearchColumnForString(componentTemplate, "template", TBL_COMPONENT_DATA);
}
public static dictionary getComponentData(obj_id component) throws InterruptedException
{
return getComponentData(getTemplateName(component));
}
public static dictionary getComponentData(String componentTemplate) throws InterruptedException
{
int startRow = getRowIndexForComponent(componentTemplate);
if (startRow < 0)
{
return null;
}
dictionary dat = new dictionary();
int totalRows = dataTableGetNumRows(TBL_COMPONENT_DATA);
if (totalRows < startRow + 1)
{
trace.log("loot", "loot::getComponentData: -> Gave starting row of " + startRow + ", but " + TBL_COMPONENT_DATA + " only has " + totalRows + " rows.", null, trace.TL_ERROR_LOG);
return null;
}
String templateString = "";
for (int i = startRow; i < totalRows; i++)
{
templateString = dataTableGetString(TBL_COMPONENT_DATA, i, "template");
if (!templateString.equals(componentTemplate) && !templateString.equals(""))
{
trace.log("loot", "loot::getComponentData: -> Done fetching data for this object. Stopped at data table row " + i);
break;
}
dat.put(dataTableGetString(TBL_COMPONENT_DATA, i, "stringArg"), new float[]
{
dataTableGetFloat(TBL_COMPONENT_DATA, i, "min"),
dataTableGetFloat(TBL_COMPONENT_DATA, i, "max")
});
}
trace.log("loot", "loot:getComponentData: -> Component data has " + dat.size() + " elements.");
return dat;
}
public static boolean redeemFactionCoupon(obj_id redeemer, obj_id player, obj_id coupon) throws InterruptedException
{
if ((redeemer == null) || (player == null) || (coupon == null))
{
return false;
}
if (!isFactionalDataItem(coupon))
{
return false;
}
String rFaction = getStringObjVar(redeemer, "faction");
if ((rFaction == null) || (rFaction.equals("")))
{
return false;
}
int val = getFactionCouponValue(redeemer, coupon);
if (val < 0)
{
return false;
}
factions.awardFactionStanding(player, rFaction, val);
return destroyObject(coupon);
}
public static int getFactionCouponValue(obj_id redeemer, obj_id coupon) throws InterruptedException
{
if ((redeemer == null) || (coupon == null))
{
return -1;
}
if (!isFactionalDataItem(coupon))
{
return -1;
}
if (!hasObjVar(redeemer, factions.FACTION))
{
return -1;
}
String rFaction = getStringObjVar(redeemer, factions.FACTION);
String cFaction = getStringObjVar(coupon, DATA_ITEM_FACTION);
int base_value = getIntObjVar(coupon, DATA_ITEM_VALUE);
if (!dataTableOpen(TBL_DATA_ITEM_VALUE))
{
return -1;
}
float multiplier = utils.dataTableGetFloat(TBL_DATA_ITEM_VALUE, rFaction, cFaction);
if (multiplier < 0)
{
return -1;
}
int point_value = (int)(base_value * multiplier);
return point_value;
}
public static boolean isFactionalDataItem(obj_id item) throws InterruptedException
{
if ((item == null) || (item == obj_id.NULL_ID))
{
return false;
}
return getGameObjectType(item) == GOT_data_fictional;
}
public static obj_id[] getFactionalDataItems(obj_id target, String faction) throws InterruptedException
{
if ((target == null) || (target == obj_id.NULL_ID))
{
return null;
}
Vector ret = new Vector();
ret.setSize(0);
obj_id dp = utils.getDatapad(target);
if ((dp == null) || (dp == obj_id.NULL_ID))
{
return null;
}
else
{
obj_id[] contents = getContents(dp);
if ((contents == null) || (contents.length == 0))
{
return null;
}
else
{
for (obj_id item : contents) {
if (isFactionalDataItem(item)) {
if (faction.equals("")) {
ret = utils.addElement(ret, item);
} else {
String ifac = getStringObjVar(item, DATA_ITEM_FACTION);
if (ifac != null) {
if (ifac.equals(faction)) {
ret = utils.addElement(ret, item);
}
}
}
}
}
}
}
if ((ret == null) || (ret.size() == 0))
{
return null;
}
else
{
obj_id[] _ret = new obj_id[0];
if (ret != null)
{
_ret = new obj_id[ret.size()];
ret.toArray(_ret);
}
return _ret;
}
}
public static obj_id[] getFactionalDataItems(obj_id target) throws InterruptedException
{
return getFactionalDataItems(target, "");
}
public static boolean randomizeWeapon(obj_id weapon, int creatureLevel) throws InterruptedException
{
if (!isIdValid(weapon))
{
return false;
}
float percentOfMax = getCalculatedAttribute(MIN_ALLOWED_WEAPON_INTENSITY, MAX_ALLOWED_WEAPON_INTENSITY, creatureLevel);
dictionary weaponCraftingData = weapons.getWeaponDat(weapon);
if (weaponCraftingData == null)
{
return false;
}
weapons.setWeaponAttributes(weapon, weaponCraftingData, percentOfMax);
return true;
}
public static boolean randomizeArmor(obj_id item, int level) throws InterruptedException
{
LOG("loot", "loot:randomizeArmor: -> Randomizing " + item);
if (!isIdValid(item))
{
return false;
}
String template = getTemplateName(item);
int armorCat = armor.getArmorCategoryByTemplate(template);
if (armorCat < 0 || armorCat > AC_max)
{
return false;
}
if (!armor.setArmorDataPercent(item, getCalculatedAttribute(0, AL_max - 1, level), armorCat, getCalculatedAttribute(0.4f, 0.9f, level), getCalculatedAttribute(0.4f, 1.0f, level)))
{
return false;
}
if (armorCat == 0)
{
armor.setArmorSpecialProtectionPercent(item, armor.DATATABLE_RECON_LAYER, 1.0f);
}
if (armorCat == 2)
{
armor.setArmorSpecialProtectionPercent(item, armor.DATATABLE_ASSAULT_LAYER, 1.0f);
}
if (!armor.isValidArmor(item))
{
LOG("loot", "loot:randomizeArmor: -> Not valid armor.");
return false;
}
return true;
}
public static boolean randomizeMedicine(obj_id item, int level) throws InterruptedException
{
if (!isIdValid(item))
{
return false;
}
if (hasObjVar(item, consumable.VAR_CONSUMABLE_MODS))
{
attrib_mod[] am = getAttribModArrayObjVar(item, consumable.VAR_CONSUMABLE_MODS);
attrib_mod[] am_new = new attrib_mod[am.length];
for (int i = 0; i < am.length; i++)
{
int attrib = am[i].getAttribute();
int val = am[i].getValue();
float duration = am[i].getDuration();
float atk = am[i].getAttack();
float decay = am[i].getDecay();
attrib_mod tmp;
if (healing.isBuffMedicine(item))
{
tmp = new attrib_mod(attrib, getCalculatedAttribute(600, 900, level), getCalculatedAttribute(9000, 12000, level), atk, decay);
}
else
{
tmp = new attrib_mod(attrib, getCalculatedAttribute(150, 400, level), duration, atk, decay);
}
am_new[i] = tmp;
}
if (am_new.length == 0)
{
return false;
}
setObjVar(item, consumable.VAR_CONSUMABLE_MODS, am_new);
}
if (healing.isCureDotMedicine(item) || healing.isApplyDotMedicine(item))
{
setObjVar(item, healing.VAR_HEALING_DOT_POWER, getCalculatedAttribute(40, 100, level));
if (healing.isApplyDotMedicine(item))
{
int potency = healing.getDotPotency(item);
setObjVar(item, healing.VAR_HEALING_DOT_POTENCY, getCalculatedAttribute(70, 150, level));
int duration = healing.getDotDuration(item);
setObjVar(item, healing.VAR_HEALING_DOT_DURATION, getCalculatedAttribute(400, 800, level));
}
}
setCount(item, getCalculatedAttribute(5, 25, level));
return true;
}
public static float[] validateComponentVals(float[] dat) throws InterruptedException
{
float[] defaultVal = new float[]
{
0.0f,
0.0f
};
if (dat == null)
{
return defaultVal;
}
switch (dat.length)
{
case 1:
return new float[]
{
dat[0],
dat[0]
};
case 2:
return dat;
}
return defaultVal;
}
public static boolean randomizeComponent(obj_id item, int level, obj_id container) throws InterruptedException
{
if (!isIdValid(item))
{
return false;
}
if (!isIdValid(container))
{
return false;
}
String template = getTemplateName(item);
dictionary componentData = getComponentData(template);
if (componentData == null)
{
return false;
}
int minToDrop = 1;
int maxToDrop = 1;
float[] fVals = null;
int minCreatureLevelDrop = MIN_CREATURE_LEVEL;
int maxCreatureLevelDrop = MAX_CREATURE_LEVEL;
if (componentData.containsKey("level"))
{
fVals = validateComponentVals(componentData.getFloatArray("level"));
minCreatureLevelDrop = (int)fVals[0];
maxCreatureLevelDrop = (int)fVals[1];
componentData.remove("level");
}
Enumeration keys = componentData.keys();
boolean hasAttribBonus = false;
int[] attribBonus = null;
while (keys.hasMoreElements())
{
String key = (String)keys.nextElement();
fVals = validateComponentVals(componentData.getFloatArray(key));
key = key.trim();
LOG("loot", "loot::randomizeComponent: -> processing key '" + key + "' where data[0]=" + fVals[0] + ", data[1]=" + fVals[1]);
if (key.equals("amount"))
{
LOG("loot", "loot::randomizeComponent: -> Grabbing amount from dataset");
minToDrop = (int)fVals[0];
maxToDrop = (int)fVals[1];
}
else if (key.startsWith("attribute.bonus."))
{
String strAttrib = key.substring(key.length() - 1);
int intAttrib = utils.stringToInt(strAttrib);
LOG("loot", "loot:randomizeComponent: -> Processing Attributes : " + intAttrib);
if (intAttrib < 0 || intAttrib >= NUM_ATTRIBUTES)
{
LOG("loot", "loot:randomizeComponent: -> IntAttrib Out of Range : " + intAttrib);
continue;
}
if (attribBonus == null)
{
attribBonus = new int[NUM_ATTRIBUTES];
}
attribBonus[intAttrib] = getCalculatedAttribute((int)fVals[0], (int)fVals[1], level, minCreatureLevelDrop, maxCreatureLevelDrop);
hasAttribBonus = true;
}
else if (key.startsWith("combat_critical"))
{
int val = rand((int)fVals[0], (int)fVals[1]);
LOG("loot", "loot:randomizeComponent: -> Not an attribute modifier or armor modifier : " + key);
setObjVar(item, craftinglib.COMPONENT_ATTRIBUTE_OBJVAR_NAME + "." + key, val);
LOG("loot", "loot:randomizeComponent: -> setting objvar : " + craftinglib.COMPONENT_ATTRIBUTE_OBJVAR_NAME + "." + key);
}
else
{
float val = getCalculatedAttribute(fVals[0], fVals[1], level, minCreatureLevelDrop, maxCreatureLevelDrop);
if (key.equals("armorCategory") || key.equals("armorLevel"))
{
setObjVar(item, craftinglib.COMPONENT_ATTRIBUTE_OBJVAR_NAME + "." + key, (int)val);
int armorCat = armor.getArmorCategory(item);
if (armorCat == 0)
{
armor.setArmorSpecialProtectionPercent(item, armor.DATATABLE_RECON_LAYER, 1.0f);
}
if (armorCat == 2)
{
armor.setArmorSpecialProtectionPercent(item, armor.DATATABLE_ASSAULT_LAYER, 1.0f);
}
}
else
{
setObjVar(item, craftinglib.COMPONENT_ATTRIBUTE_OBJVAR_NAME + "." + key, key.equals("attackSpeed") || key.equals("attackCost") ? val * -1 : val);
}
}
}
if (hasAttribBonus && attribBonus != null && attribBonus.length == NUM_ATTRIBUTES)
{
LOG("loot", "loot:randomizeComponent: -> Calling Set Attributes : " + attribBonus.toString());
for (int i = 0; i < attribBonus.length; i++)
{
LOG("loot", "loot:randomizeComponent: -> Attribute " + i + " = " + attribBonus[i]);
}
setAttributeBonuses(item, attribBonus);
}
LOG("loot", "loot:randomizeComponent: -> Amount to drop : " + minToDrop + "/" + maxToDrop);
setCraftedId(item, container);
setCrafter(item, container);
int numDropped = 1;
if (minToDrop <= maxToDrop)
{
numDropped = rand(minToDrop, maxToDrop);
}
LOG("loot", "loot:randomizeComponent: -> Dropping " + numDropped + " " + template);
if (numDropped > 1)
{
setObjVar(item, "unstack.serialNumber", container);
setCount(item, numDropped);
attachScript(item, "object.onewayunstack");
}
return true;
}
public static String getCreatureType(String name) throws InterruptedException
{
return dataTableGetString("datatables/mob/creatures.iff", name, "lootList");
}
public static int getAdjustedCreatureLevel(obj_id target, String name) throws InterruptedException
{
int level = getLevel(target);
int difficultyClass = dataTableGetInt("datatables/mob/creatures.iff", name, "difficultyClass");
if (difficultyClass > 0)
{
float levelMod = 0.4f * difficultyClass;
level += (int)(level * levelMod);
}
return level;
}
public static boolean generateTheftLootRare(obj_id container, obj_id mark, int maxItems, obj_id thief) throws InterruptedException
{
String name = getCreatureName(mark);
String type = getCreatureType(name);
if (type == null || type.equals("none"))
{
return false;
}
String strTreasureTable = "treasure/treasure_";
String treasureLevel = "1_10";
int intLevel = getIntObjVar(mark, "intCombatDifficulty");
if (intLevel <= 10)
{
treasureLevel = "1_10";
}
else if (intLevel <= 20)
{
treasureLevel = "11_20";
}
else if (intLevel <= 30)
{
treasureLevel = "21_30";
}
else if (intLevel <= 40)
{
treasureLevel = "31_40";
}
else if (intLevel <= 50)
{
treasureLevel = "41_50";
}
else if (intLevel <= 60)
{
treasureLevel = "51_60";
}
else if (intLevel <= 70)
{
treasureLevel = "61_70";
}
else if (intLevel <= 80)
{
treasureLevel = "71_80";
}
else if (intLevel <= 90)
{
treasureLevel = "81_90";
}
else
{
return false;
}
String strTable = strTreasureTable + treasureLevel;
utils.setScriptVar(container, "theft_in_progress", 1);
return makeLootInContainer(container, strTable, 1, intLevel);
}
public static boolean generateTheftLoot(obj_id container, obj_id mark, float chanceMod, int maxItems) throws InterruptedException
{
String name = getCreatureName(mark);
String type = getCreatureType(name);
if (type == null || type.equals("none"))
{
return false;
}
int level = getAdjustedCreatureLevel(mark, name);
String strTable = getStringObjVar(mark, "loot.lootTable");
int intLevel = getIntObjVar(mark, "intCombatDifficulty");
utils.setScriptVar(container, "theft_in_progress", 1);
return makeLootInContainer(container, strTable, 1, intLevel);
}
public static int getNpcMoney(obj_id target) throws InterruptedException
{
String mobType = ai_lib.getCreatureName(target);
if (mobType == null)
{
return -1;
}
int niche = ai_lib.aiGetNiche(target);
if (niche != NICHE_NPC)
{
return -1;
}
int level = ai_lib.getLevel(target);
int cash = getCashForLevel(mobType, level);
if (cash < 1)
{
cash = rand(1, 10);
cash = cash * level;
}
return cash;
}
public static boolean addCashAsLoot(obj_id target, int cash) throws InterruptedException
{
if (cash < 1)
{
return false;
}
obj_id inv = utils.getInventoryContainer(target);
if (inv == null)
{
return false;
}
obj_id cashItem = createObject(CASH_ITEM_TEMPLATE, inv, "");
if (!isIdValid(cashItem))
{
return false;
}
setObjVar(cashItem, "loot.cashAmount", cash);
setName(cashItem, formatCashAmount(cash));
return true;
}
public static String formatCashAmount(int cash) throws InterruptedException
{
final java.text.DecimalFormat CASH_NAME_FORMAT = new java.text.DecimalFormat("#,### cr");
return CASH_NAME_FORMAT.format(cash);
}
public static boolean isCashLootItem(obj_id item) throws InterruptedException
{
String template = getTemplateName(item);
if (template.equals(CASH_ITEM_TEMPLATE))
{
return hasObjVar(item, "loot.cashAmount");
}
return false;
}
public static boolean doGroupLooting(obj_id corpseId, obj_id transferer, obj_id item) throws InterruptedException
{
obj_id leader = group.getLeader(transferer);
obj_id team = getGroupObject(transferer);
int groupLootType = getGroupLootRule(team);
obj_id[] objMembersWhoExist = utils.getLocalGroupMemberIds(team);
obj_id corpseInv = utils.getInventoryContainer(corpseId);
obj_id[] contents = getContents(corpseInv);
int numContents = contents.length;
if (objMembersWhoExist == null)
{
return false;
}
if (groupLootType == 0)
{
setGroupLootRule(team, group.FREE_FOR_ALL);
return true;
}
if (groupLootType == 1)
{
obj_id master = getGroupMasterLooterId(team);
String masterName = getEncodedName(master);
if (transferer != master)
{
prose_package pp = new prose_package();
string_id masterMsg = new string_id(group.GROUP_STF, "master_only");
pp = prose.setStringId(pp, masterMsg);
pp = prose.setTO(pp, masterName);
sendSystemMessageProse(transferer, pp);
return false;
}
}
if (groupLootType == 2)
{
if (hasObjVar(corpseId, "autoLootComplete"))
{
return true;
}
int numWindows = 0;
if (hasObjVar(corpseId, "numWindowsOpen"))
{
numWindows = getIntObjVar(corpseId, "numWindowsOpen");
}
else
{
for (obj_id objMemberWhoExists : objMembersWhoExist) {
if (numContents > 0 && !(numContents == 1 && isCashLootItem(contents[0]))) {
openLotteryWindow(objMemberWhoExists, corpseInv);
} else if (numContents == 1 && isCashLootItem(contents[0])) {
return true;
} else {
string_id emptyCorpse = new string_id(group.GROUP_STF, "corpse_empty");
sendSystemMessage(objMemberWhoExists, emptyCorpse);
lootAiCorpse(transferer, corpseId);
return false;
}
}
numWindows = objMembersWhoExist.length;
setObjVar(corpseId, "numWindowsOpen", numWindows);
}
if (numWindows > 0)
{
dictionary lotto = new dictionary();
lotto.put("player", transferer);
lotto.put("corpseInv", corpseInv);
messageTo(corpseId, "fireLotteryPulse", lotto, 2, true);
return false;
}
}
if (groupLootType == 3)
{
return true;
}
return true;
}
public static boolean doGroupLootAllCheck(obj_id player, obj_id corpseId) throws InterruptedException
{
if (player != null && corpseId != null)
{
obj_id leader = group.getLeader(player);
obj_id team = group.getGroupObject(leader);
int lootType = getGroupLootRule(team);
obj_id[] objMembersWhoExist = utils.getLocalGroupMemberIds(team);
if (objMembersWhoExist == null)
{
return true;
}
int number = objMembersWhoExist.length;
if (number < 1)
{
return true;
}
obj_id corpseInv = utils.getInventoryContainer(corpseId);
if (corpseInv == null)
{
return false;
}
obj_id[] contents = getContents(corpseInv);
if (contents == null)
{
return false;
}
int numContents = contents.length;
if (lootType == 0)
{
setGroupLootRule(team, group.FREE_FOR_ALL);
return true;
}
if (lootType == 1)
{
obj_id master = getGroupMasterLooterId(team);
String masterName = getEncodedName(master);
if (master == player)
{
return true;
}
else if (!isIdValid(master))
{
return true;
}
else
{
prose_package pp = new prose_package();
string_id masterMsg = new string_id(group.GROUP_STF, "master_only");
pp = prose.setStringId(pp, masterMsg);
pp = prose.setTO(pp, masterName);
sendSystemMessageProse(player, pp);
return false;
}
}
else if (lootType == 2)
{
if (hasObjVar(corpseId, "autoLootComplete"))
{
return true;
}
if (hasObjVar(corpseId, "numWindowsOpen"))
{
return false;
}
for (obj_id objMemberWhoExists : objMembersWhoExist) {
if (numContents > 0 && !(numContents == 1 && isCashLootItem(contents[0]))) {
openLotteryWindow(objMemberWhoExists, corpseInv);
} else if (numContents == 1 && isCashLootItem(contents[0])) {
return true;
} else {
string_id emptyCorpse = new string_id(group.GROUP_STF, "corpse_empty");
sendSystemMessage(objMemberWhoExists, emptyCorpse);
lootAiCorpse(player, corpseId);
return false;
}
}
setObjVar(corpseId, "numWindowsOpen", objMembersWhoExist.length);
dictionary lotto = new dictionary();
lotto.put("player", player);
lotto.put("corpseInv", corpseInv);
messageTo(corpseId, "fireLotteryPulse", lotto, 2, true);
return false;
}
else if (lootType == 3)
{
return true;
}
else
{
string_id cantLoot = new string_id(group.GROUP_STF, "no_loot_group");
sendSystemMessage(player, cantLoot);
return false;
}
}
return false;
}
public static void sendGroupLootSystemMessage(obj_id item, obj_id winner, String stf, String message) throws InterruptedException
{
sendGroupLootSystemMessage(item, winner, stf, message, false);
}
public static void sendGroupLootSystemMessage(obj_id item, obj_id winner, String stf, String message, boolean skipWinner) throws InterruptedException
{
if (group.isGrouped(winner)) {
obj_id team = getGroupObject(winner);
obj_id[] objMembersWhoExist = utils.getLocalGroupMemberIds(team);
prose_package pp = new prose_package();
string_id lootMsg = new string_id(stf, message);
pp = prose.setStringId(pp, lootMsg);
pp = prose.setTO(pp, item);
pp = prose.setTT(pp, winner);
if(objMembersWhoExist != null) {
if (!skipWinner) {
for (obj_id objMemberWhoExists : objMembersWhoExist) {
sendSystemMessageProse(objMemberWhoExists, pp);
}
} else {
for (obj_id objMemberWhoExists : objMembersWhoExist) {
if (objMemberWhoExists != winner) {
sendSystemMessageProse(objMemberWhoExists, pp);
}
}
}
}
}
}
public static void setAutoLootComplete(obj_id winner, obj_id corpse, obj_id item) throws InterruptedException
{
setObjVar(corpse, "autoLootComplete", 1);
setObjVar(item, "pickupable", winner);
}
public static obj_id chooseRandomLootPlayerFromGroup(obj_id corpse, obj_id player) throws InterruptedException
{
obj_id team = getGroupObject(player);
obj_id[] objMembersWhoExist = utils.getLocalGroupMemberIds(team);
if(objMembersWhoExist != null) {
int teamNumber = objMembersWhoExist.length;
if (hasObjVar(corpse, "autoLootComplete")) {
obj_id corpseInv = utils.getInventoryContainer(corpse);
queueCommand(player, (1880585606), corpseInv, "", COMMAND_PRIORITY_DEFAULT);
}
if (teamNumber > 0) {
int which = rand(0, teamNumber - 1);
player = objMembersWhoExist[which];
}
}
return player;
}
public static boolean isMasterLooter(obj_id toTest, boolean sendMessage) throws InterruptedException
{
obj_id team = getGroupObject(toTest);
if (team != null)
{
obj_id masterLooter = getGroupMasterLooterId(team);
String masterName = getEncodedName(masterLooter);
if (toTest == masterLooter)
{
return true;
}
else if (sendMessage)
{
prose_package pp = new prose_package();
string_id masterMsg = new string_id(group.GROUP_STF, "master_only");
pp = prose.setStringId(pp, masterMsg);
pp = prose.setTO(pp, masterName);
sendSystemMessageProse(toTest, pp);
}
}
return false;
}
public static void lootAiCorpse(obj_id self, obj_id target) throws InterruptedException
{
if (isIdValid(target)
&& isMob(target)
&& isIncapacitated(target)
&& !isIncapacitated(self)
&& !pet_lib.isPet(target)
&& hasObjVar(target, "readyToLoot")
&& corpse.hasLootPermissions(target, self)
&& corpse.lootAICorpse(self, target)) {
messageTo(target, "handleCorpseEmpty", null, 0, true);
}
}
public static obj_id findItemToStack(obj_id item) throws InterruptedException
{
obj_id container = getContainedBy(item);
if (!isIdValid(container))
{
return null;
}
String itemStaticName = getStaticItemName(item);
if (itemStaticName == null)
{
itemStaticName = "";
}
obj_id[] likeItemsInContainer = utils.getAllItemsInContainerByTemplate(container, getTemplateName(item), false);
if ((likeItemsInContainer != null) && (likeItemsInContainer.length > 0))
{
for (obj_id likeItem : likeItemsInContainer) {
String curItemStaticName = getStaticItemName(likeItem);
if (curItemStaticName == null) {
curItemStaticName = "";
}
if (item != likeItem && curItemStaticName.equals(itemStaticName)) {
return likeItem;
}
}
}
return null;
}
public static void stackItem(obj_id objSourceItem, obj_id objDestinationItem) throws InterruptedException
{
int sourceCount = getCount(objSourceItem);
if (sourceCount == 0)
{
sourceCount = 1;
}
int intCount = getCount(objDestinationItem);
if (intCount == 0)
{
intCount = 1;
}
intCount = intCount + sourceCount;
setCount(objDestinationItem, intCount);
destroyObject(objSourceItem);
obj_id container = getContainedBy(objDestinationItem);
if (utils.hasScriptVar(container, "theft_in_progress"))
{
notifyThiefOfItemStolen(container, objDestinationItem);
}
}
public static boolean setupLootItems(obj_id objCreature) throws InterruptedException
{
obj_id objContainer = utils.getInventoryContainer(objCreature);
if (!hasObjVar(objCreature, "loot.lootTable"))
{
LOG("npe", "No Loot Table on " + objCreature + " of template " + getTemplateName(objCreature));
return false;
}
String strTable = getStringObjVar(objCreature, "loot.lootTable");
int intLevel = getIntObjVar(objCreature, "intCombatDifficulty");
int intItems = getIntObjVar(objCreature, "loot.numItems");
rollForSpecialDnaLoot(objCreature, objContainer);
return makeLootInContainer(objContainer, strTable, intItems, intLevel);
}
public static boolean setupLootItems(obj_id objCreature, int intItems) throws InterruptedException
{
obj_id objContainer = utils.getInventoryContainer(objCreature);
if (!hasObjVar(objCreature, "loot.lootTable"))
{
LOG("npe", "No Loot Table on " + objCreature + " of template " + getTemplateName(objCreature));
return false;
}
String strTable = getStringObjVar(objCreature, "loot.lootTable");
int intLevel = getIntObjVar(objCreature, "intCombatDifficulty");
rollForSpecialDnaLoot(objCreature, objContainer);
return makeLootInContainer(objContainer, strTable, intItems, intLevel);
}
public static boolean makeLootInContainer(obj_id objContainer, String strTable, int intItems, int intLevel) throws InterruptedException
{
boolean boolMadeLoot = false;
String strRootItems = "datatables/loot/loot_items/";
String[] parse = split(strTable, ':');
strTable = parse[0];
strTable = "datatables/loot/loot_types/" + strTable + ".iff";
String strItemsHeader = "strItems";
if (parse.length == 2)
{
strItemsHeader = parse[1];
}
String[] strLootTypes = dataTableGetStringColumnNoDefaults(strTable, strItemsHeader);
String[] strRequiredItems = null;
if (dataTableHasColumn(strTable, "strRequiredItems"))
{
strRequiredItems = dataTableGetStringColumnNoDefaults(strTable, "strRequiredItems");
}
if ((strLootTypes == null) || (strLootTypes.length == 0))
{
return false;
}
for (int intI = 0; intI < intItems; intI++)
{
String strItemTable = strLootTypes[rand(0, strLootTypes.length - 1)];
String[] parseItem = split(strItemTable, ':');
strItemTable = parseItem[0];
strItemTable = strRootItems + strItemTable + ".iff";
String strItemTypeHeader = "strItemType";
if (parseItem.length == 2)
{
strItemTypeHeader = parseItem[1];
}
if (dataTableOpen(strItemTable)) {
String[] strItems = dataTableGetStringColumnNoDefaults(strItemTable, strItemTypeHeader);
if (strItems != null && strItems.length > 0)
{
String strLootToMake = strItems[rand(0, strItems.length - 1)];
createLootItem(objContainer, strLootToMake, intLevel);
boolMadeLoot = true;
}
}
}
if (strRequiredItems != null && strRequiredItems.length > 0)
{
for (String strRequiredItem : strRequiredItems) {
createLootItem(objContainer, strRequiredItem, intLevel);
boolMadeLoot = true;
}
}
return boolMadeLoot;
}
public static obj_id makeRareLootItem(obj_id objContainer, String strTable) throws InterruptedException
{
String strRootItems = "datatables/loot/loot_items/";
String[] parse = split(strTable, ':');
strTable = parse[0];
strTable = "datatables/loot/loot_types/" + strTable + ".iff";
String strItemsHeader = "strItems";
if (parse.length == 2) {
strItemsHeader = parse[1];
}
String[] strLootTypes = dataTableGetStringColumnNoDefaults(strTable, strItemsHeader);
String strItemTable = strLootTypes[rand(0, strLootTypes.length - 1)];
String[] parseItem = split(strItemTable, ':');
strItemTable = parseItem[0];
strItemTable = strRootItems + strItemTable + ".iff";
String strItemTypeHeader = "strItemType";
if (parseItem.length == 2)
{
strItemTypeHeader = parseItem[1];
}
if (dataTableOpen(strItemTable)) {
String[] strItems = dataTableGetStringColumnNoDefaults(strItemTable, strItemTypeHeader);
if (strItems != null && strItems.length > 0)
{
String strLootToMake = strItems[rand(0, strItems.length - 1)];
obj_id lootItem = createLootItem(objContainer, strLootToMake, 1);
attachScript(lootItem, "systems.loot.rare_item");
return lootItem;
}
}
return null;
}
public static obj_id createLootItem(obj_id objContainer, String strLootToMake, int intLevel) throws InterruptedException
{
int intIndex = strLootToMake.indexOf(".iff");
if (intIndex > -1)
{
obj_id lootItem = createObject(strLootToMake, objContainer, "");
int got = getGameObjectType(lootItem);
if (isGameObjectTypeOf(got, GOT_clothing) || got == GOT_armor_foot || got == GOT_armor_hand)
{
hue.hueObject(lootItem);
}
else if (isGameObjectTypeOf(got, GOT_weapon))
{
randomizeWeapon(lootItem, intLevel);
}
else if (got >= GOT_armor && got <= GOT_armor_arm)
{
randomizeArmor(lootItem, intLevel);
}
else if (got == GOT_misc_pharmaceutical)
{
randomizeMedicine(lootItem, intLevel);
}
else if ((got >= GOT_component && got <= GOT_component_weapon_ranged) || (got >= GOT_armor_layer && got <= GOT_armor_core) || got == GOT_component_new_armor)
{
randomizeComponent(lootItem, intLevel, objContainer);
}
if (utils.hasScriptVar(objContainer, "theft_in_progress"))
{
notifyThiefOfItemStolen(objContainer, lootItem);
}
return lootItem;
}
else if (strLootToMake.startsWith("loot_items/"))
{
String[] parseItem = split(strLootToMake, ':');
if (parseItem.length == 2)
{
String itemDatatable = "datatables/loot/" + parseItem[0] + ".iff";
String lootColumnHeader = parseItem[1];
if (dataTableOpen(itemDatatable)) {
String[] lootList = dataTableGetStringColumnNoDefaults(itemDatatable, lootColumnHeader);
if (lootList != null && lootList.length > 0)
{
String lootItemsLoot = lootList[rand(0, lootList.length - 1)];
return createLootItem(objContainer, lootItemsLoot, intLevel);
}
}
}
}
else if (strLootToMake.startsWith("dynamic_"))
{
static_item.makeDynamicObject(strLootToMake, objContainer, intLevel);
}
else if (strLootToMake.startsWith("resource"))
{
utils.removeScriptVar(objContainer, "theft_in_progress");
}
else
{
obj_id lootItem = static_item.createNewItemFunction(strLootToMake, objContainer);
if (utils.hasScriptVar(objContainer, "theft_in_progress"))
{
notifyThiefOfItemStolen(objContainer, lootItem);
}
return lootItem;
}
return null;
}
public static boolean addMilkOrEgg(obj_id objCreature) throws InterruptedException
{
if (rand(1, 100) > 20)
{
return false;
}
String mobType = ai_lib.getCreatureName(objCreature);
int niche = ai_lib.aiGetNiche(mobType);
if (niche != NICHE_NPC)
{
return false;
}
String[] groceryItems =
{
"milk_domesticated",
"milk_wild",
"meat_egg",
"meat_egg"
};
obj_id objContainer = utils.getInventoryContainer(objCreature);
int randItem = rand(0, 3);
location here = getLocation(objCreature);
int level = getLevel(objCreature);
int amount = (int)(rand(1, 20) + (level * rand(1.0f, 2.0f)));
resource.createRandom(groceryItems[randItem], amount, here, objContainer);
return true;
}
public static void notifyThiefOfItemStolen(obj_id objContainer, obj_id loot) throws InterruptedException
{
if (utils.hasScriptVar(objContainer, "theft_in_progress"))
{
obj_id thief = getContainedBy(objContainer);
if (isPlayer(thief))
{
prose_package pp = new prose_package();
pp = prose.setStringId(pp, new string_id("spam", "stolen_item"));
pp = prose.setTT(pp, loot);
sendSystemMessageProse(thief, pp);
}
utils.removeScriptVar(objContainer, "theft_in_progress");
}
}
public static boolean addBeastEnzymes(obj_id creature) throws InterruptedException
{
if (storyteller.isStorytellerNpc(creature))
{
return false;
}
int chanceSpawn = rand(1, 100);
if (chanceSpawn >= BASE_CHANCE_FOR_ENZYME && !hasObjVar(creature, "qa.makeEnzyme"))
{
return false;
}
int type = 1;
obj_id inv = utils.getInventoryContainer(creature);
obj_id enzyme = createObject("object/tangible/loot/beast/enzyme_" + type + ".iff", inv, "");
int level = ai_lib.getLevel(creature);
if (isIdValid(enzyme) && exists(enzyme))
{
setObjVar(enzyme, "beast.enzyme.level", level);
return true;
}
else
{
return false;
}
}
public static boolean addChronicleLoot(obj_id target) throws InterruptedException
{
String creatureName = ai_lib.getCreatureName(target);
if (creatureName == null || creatureName.length() < 1)
{
return false;
}
dictionary creatureRow = dataTableGetRow(CREATURES_TABLE, creatureName);
if(creatureRow == null){
CustomerServiceLog("chroniclesLoot", "FIX ME: Add creature (" + creatureName + ") to the creatures table (" + CREATURES_TABLE + ")!");
return false;
}
int mobLevel = getIntObjVar(target, "intCombatDifficulty");
obj_id mobInv = utils.getInventoryContainer(target);
int chronicleLootChance = utils.getIntConfigSetting("GameServer", "chroniclesLootChanceOverride", creatureRow.getInt("chronicleLootChance"));
int chronicleLootRoll = rand(1, 100);
if (chronicleLootRoll <= chronicleLootChance)
{
String lootCatergoryChoice = "";
int relicCount = rand(1, 3);
String chronicleLootData = creatureRow.getString("chronicleLootCategory");
if (chronicleLootData != null && chronicleLootData.length() > 0 && !chronicleLootData.equals("no_loot"))
{
String[] rawChronicleLootCategories = split(chronicleLootData, ',');
Vector chronicleLootCategories = new Vector();
chronicleLootCategories.setSize(0);
for (String rawChronicleLootCategory : rawChronicleLootCategories) {
if (!rawChronicleLootCategory.equals("rare")) {
utils.addElement(chronicleLootCategories, rawChronicleLootCategory);
}
}
int lootOptions = chronicleLootCategories.size();
int rareLootRoll = rand(1, 100);
if (rareLootRoll == 1)
{
lootCatergoryChoice = "rare";
}
else if (rareLootRoll < 6)
{
lootCatergoryChoice = "comm_message";
relicCount = rand(6, 9);
}
else if (rareLootRoll < 10)
{
lootCatergoryChoice = "goto_task";
relicCount = rand(6, 9);
}
else
{
int lootCategoryChoiceRoll = rand(0, lootOptions - 1);
lootCatergoryChoice = ((String)chronicleLootCategories.get(lootCategoryChoiceRoll));
}
}
if (lootCatergoryChoice.length() > 0)
{
String relicName = getChronicleRelicLootOfCategory(lootCatergoryChoice);
if (relicName != null && relicName.length() > 0)
{
obj_id relic = static_item.createNewItemFunction(relicName, mobInv, relicCount);
pgc_quests.logRelic(obj_id.NULL_ID, obj_id.NULL_ID, "Chronicles Relic loot created on creature=(" + target + "," + creatureName + "," + getName(target) + "); relic=(" + relicName + ", count:" + relicCount + ").");
return true;
}
}
}
int fragmentLootChance = utils.getIntConfigSetting("GameServer", "fragmentLootChanceOverride", pgc_quests.PGC_CHRONICLE_BASE_FRAGEMENT_CHANCE);
int fragmentLootRoll = rand(1, 100);
if (fragmentLootRoll <= fragmentLootChance)
{
int fragmentCount = 1 + rand(0, mobLevel / 10);
obj_id fragment = static_item.createNewItemFunction(pgc_quests.PGC_CHRONICLES_RELIC_FRAGMENT, mobInv, fragmentCount);
pgc_quests.logRelic(obj_id.NULL_ID, obj_id.NULL_ID, "Chronicles Relic Fragment loot created on creature=(" + target + "," + creatureName + "," + getName(target) + "); fragment=" + pgc_quests.PGC_CHRONICLES_RELIC_FRAGMENT + ", count:" + fragmentCount + ").");
return true;
}
return false;
}
public static String getChronicleRelicLootOfCategory(String lootCategoryChoice) throws InterruptedException
{
String relic = "";
Vector tokenReferences = new Vector();
tokenReferences.setSize(0);
int num_items = dataTableGetNumRows(storyteller.STORYTELLER_DATATABLE);
for (int i = 0; i < num_items; i++)
{
dictionary row = dataTableGetRow(storyteller.STORYTELLER_DATATABLE, i);
if (row != null && !row.isEmpty())
{
String row_lootCategory = row.getString("relicLootCatergory");
String[] relicLootCategories = split(row_lootCategory, ',');
for (String relicCategory : relicLootCategories) {
if (relicCategory.equals(lootCategoryChoice)) {
tokenReferences = utils.addElement(tokenReferences, row.getString("name"));
}
}
}
}
if (tokenReferences != null && tokenReferences.size() > 0)
{
relic = ((String)tokenReferences.get(rand(0, tokenReferences.size() - 1)));
}
if (lootCategoryChoice.equals("goto_task"))
{
int genericChance = rand(1, 3);
if (genericChance == 3)
{
relic = pgc_quests.PGC_RELIC_OBJ_GOTO_GENERIC_LOC;
}
}
return relic;
}
public static obj_id chroniclesCraftingLootDrop(obj_id player) throws InterruptedException
{
if (hasToggledChroniclesLootOff(player))
{
return obj_id.NULL_ID;
}
return chroniclesNonCorpseLootDrop(player, "crafting", pgc_quests.PGC_CHRONICLE_BASE_CRAFTING_LOOT_CHANCE, "crafting");
}
public static obj_id chroniclesPvpLootDrop(obj_id player) throws InterruptedException
{
if (hasToggledChroniclesLootOff(player))
{
return obj_id.NULL_ID;
}
return chroniclesNonCorpseLootDrop(player, "pvp", pgc_quests.PGC_CHRONICLE_BASE_PVP_LOOT_CHANCE, "pvping");
}
public static obj_id chroniclesNonCorpseLootDrop(obj_id player, String relicCategory, int relicChance, String activityType) throws InterruptedException
{
int chance = utils.getIntConfigSetting("GameServer", "chroniclesLootChanceOverride", relicChance);
int lootRoll = rand(1, 100);
if (lootRoll <= chance)
{
String relicName = getChronicleRelicLootOfCategory(relicCategory);
if (relicName != null && relicName.length() > 0)
{
int relicCount = rand(1, 3);
obj_id playerInv = utils.getInventoryContainer(player);
obj_id relic = static_item.createNewItemFunction(relicName, playerInv, relicCount);
if (isIdValid(relic))
{
pgc_quests.sendPlacedInInventorySystemMessage(player, relic);
pgc_quests.logRelic(player, obj_id.NULL_ID, "Player looted a Chronicles Relic while " + activityType + ": relic name:" + relicName + " and count: " + relicCount);
}
return relic;
}
}
return obj_id.NULL_ID;
}
public static boolean hasToggledChroniclesLootOff(obj_id player) throws InterruptedException
{
return hasObjVar(player, CHRONICLES_LOOT_TOGGLE_OBJVAR);
}
public static void disableChroniclesLoot(obj_id player) throws InterruptedException
{
setObjVar(player, CHRONICLES_LOOT_TOGGLE_OBJVAR, true);
}
public static void enableChroniclesLoot(obj_id player) throws InterruptedException
{
removeObjVar(player, CHRONICLES_LOOT_TOGGLE_OBJVAR);
}
public static boolean addCollectionLoot(obj_id target) throws InterruptedException
{
return addCollectionLoot(target, false, null);
}
public static boolean addCollectionLoot(obj_id target, boolean theftBool, obj_id thief) throws InterruptedException
{
String creatureName = ai_lib.getCreatureName(target);
int collectionLootChance = rand(1, 100);
dictionary creatureRow = dataTableGetRow(CREATURES_TABLE, creatureName);
if(creatureRow == null || creatureRow.isEmpty()){
CustomerServiceLog("chroniclesLoot", "FIX ME: Add creature (" + creatureName + ") to the creatures table (" + CREATURES_TABLE + ")!");
return false;
}
int rollBaseChance = creatureRow.getInt("collectionRoll");
rollBaseChance *= COL_LOOT_MULTIPLIER_ON;
if (creatureRow.isEmpty())
{
return false;
}
if (collectionLootChance <= rollBaseChance)
{
String myCollectionLoot = creatureRow.getString("collectionLoot");
if (myCollectionLoot == null || myCollectionLoot.equals("no_loot"))
{
return false;
}
else
{
String[] collectionsInColumn = split(myCollectionLoot, ',');
int collectionIndex = rand(0, (collectionsInColumn.length - 1));
myCollectionLoot = collectionsInColumn[collectionIndex];
String[] lootArray = dataTableGetStringColumnNoDefaults(COLLECTIONS_LOOT_TABLE, myCollectionLoot);
int max = lootArray.length - 1;
int idx = rand(0, max);
String lootToGrant = lootArray[idx];
if (theftBool)
{
if (isIdValid(thief))
{
obj_id thiefInv = utils.getInventoryContainer(thief);
utils.setScriptVar(thiefInv, "theft_in_progress", 1);
obj_id lootItem = static_item.createNewItemFunction(lootToGrant, thiefInv);
notifyThiefOfItemStolen(thiefInv, lootItem);
return true;
}
return false;
}
obj_id mobInv = utils.getInventoryContainer(target);
obj_id lootItem = static_item.createNewItemFunction(lootToGrant, mobInv);
if (isIdValid(lootItem) && exists(lootItem))
{
CustomerServiceLog("CollectionLootChannel: ", "LootSuccessful: " + creatureName + "(" + target + ")" + " successfully dropped: " + lootToGrant + "(" + lootItem + ")");
return true;
}
else
{
CustomerServiceLog("CollectionLootChannel: ", "BrokenLoot: " + creatureName + "(" + target + ")" + " is having an issue dropping: " + lootToGrant + " Invalid ID or Does not exist.");
return false;
}
}
}
return false;
}
public static String getFactionalCollectionItem(String faction) throws InterruptedException
{
blog("getFactionalCollectionItem - arrival in function. Faction of winner is: " + faction);
if (faction == null || faction.equals(""))
{
return null;
}
blog("getFactionalCollectionItem - Faction check 1: " + faction + "*");
if (!faction.equals("Rebel") && !faction.equals("Imperial"))
{
return null;
}
blog("getFactionalCollectionItem - Faction check 2");
Vector factionCols = new Vector();
factionCols.setSize(0);
int randColInt = 0;
String randColStr = "";
String[] allLootColumns = dataTableGetColumnNames(COLLECTIONS_PVP_LOOT_TABLE);
if (allLootColumns == null || allLootColumns.length <= 0)
{
return null;
}
blog("getFactionalCollectionItem - allLootColumns.length: " + allLootColumns.length);
for (String lootColumn : allLootColumns) {
if (lootColumn.startsWith(toLower(faction))) {
blog("getFactionalCollectionItem - found a column I am adding to col list");
utils.addElement(factionCols, lootColumn);
}
}
blog("getFactionalCollectionItem - factionCols.length: " + factionCols.size());
if (factionCols.size() <= 0)
{
return null;
}
if (factionCols.size() == 1)
{
blog("getFactionalCollectionItem - randColStr: " + factionCols.get(randColInt));
randColStr = ((String)factionCols.get(randColInt));
}
else
{
randColInt = rand(0, factionCols.size() - 1);
blog("getFactionalCollectionItem - randColInt: " + randColInt);
randColStr = ((String)factionCols.get(randColInt));
blog("getFactionalCollectionItem - randColStr: " + randColStr);
}
if (randColStr == null || randColStr.equals(""))
{
return null;
}
String[] colLoot = dataTableGetStringColumnNoDefaults(COLLECTIONS_PVP_LOOT_TABLE, randColStr);
if (colLoot == null || colLoot.length <= 0)
{
return null;
}
blog("getFactionalCollectionItem - colLoot.length: " + colLoot.length);
if (colLoot.length == 1)
{
return colLoot[0];
}
int randLootInt = rand(0, colLoot.length - 1);
blog("getFactionalCollectionItem - randLootInt: " + randLootInt);
blog("getFactionalCollectionItem - RETURNING: " + colLoot[randLootInt]);
return colLoot[randLootInt];
}
public static String getAppropriatePvpRankCollectible(String faction, int rank) throws InterruptedException
{
blog("getAppropriatePvpRankCollectible - arrival in function. Faction: " + faction + " rank: " + rank);
if (faction == null || faction.equals(""))
{
return null;
}
blog("getAppropriatePvpRankCollectible - Faction checked 1: " + faction + "*");
if (!faction.equals("Rebel") && !faction.equals("Imperial"))
{
return null;
}
blog("getAppropriatePvpRankCollectible - Faction checked 2");
if (rank < 6 || rank > 12)
{
return null;
}
blog("getFactionalCollectionItem - faction: " + faction);
blog("getFactionalCollectionItem - faction: " + rank);
Vector pvpCols = new Vector();
pvpCols.setSize(0);
int randColInt = 0;
String randColStr = "";
String[] allLootColumns = dataTableGetColumnNames(COLLECTIONS_PVP_RANK_TABLE);
if (allLootColumns == null || allLootColumns.length <= 0)
{
return null;
}
blog("getFactionalCollectionItem - allLootColumns.length: " + allLootColumns.length);
for (String lootColumn : allLootColumns) {
if (lootColumn.startsWith(toLower(faction))) {
blog("getFactionalCollectionItem - found a column I wanted: ");
utils.addElement(pvpCols, lootColumn);
}
}
if (pvpCols.size() <= 0)
{
return null;
}
blog("getFactionalCollectionItem - pvpCols.length: " + pvpCols.size());
if (pvpCols.size() == 1)
{
randColStr = ((String)pvpCols.get(randColInt));
}
else
{
randColInt = rand(0, pvpCols.size() - 1);
randColStr = ((String)pvpCols.get(randColInt));
}
blog("getFactionalCollectionItem - pvpCols[randColInt]: " + pvpCols.get(randColInt));
blog("getFactionalCollectionItem - randColStr: " + randColStr);
switch (rank)
{
case 7:
return dataTableGetString(COLLECTIONS_PVP_RANK_TABLE, 0, randColStr);
case 8:
return dataTableGetString(COLLECTIONS_PVP_RANK_TABLE, 1, randColStr);
case 9:
return dataTableGetString(COLLECTIONS_PVP_RANK_TABLE, 2, randColStr);
case 10:
return dataTableGetString(COLLECTIONS_PVP_RANK_TABLE, 3, randColStr);
case 11:
return dataTableGetString(COLLECTIONS_PVP_RANK_TABLE, 4, randColStr);
case 12:
return dataTableGetString(COLLECTIONS_PVP_RANK_TABLE, 5, randColStr);
default:
return null;
}
}
public static boolean rollRandomFactionalCollectible(obj_id victim, obj_id winner, int victimRank) throws InterruptedException
{
blog("rollRandomFactionalCollectible - arrival in rollRandomFactionalCollectible function");
if (isIdNull(winner) || isIdNull(victim))
{
return false;
}
if (victimRank <= 0)
{
return false;
}
blog("rollRandomFactionalCollectible - about to roll.");
int roll = rand(1, 100);
int rollNeeded = COLLECTION_PVP_ROLL;
if (isGod(winner))
{
rollNeeded = 101;
}
if (roll <= rollNeeded)
{
return false;
}
blog("rollRandomFactionalCollectible - won roll.");
int rewardFunction = 1;
if (victimRank > 6)
{
rewardFunction = rand(1, 2);
blog("rollRandomFactionalCollectible - victim is officer.");
}
String faction = factions.getFaction(victim);
String rewardItem = "";
switch (rewardFunction)
{
case 1:
blog("rollRandomFactionalCollectible - send to getFactionalCollectionItem.");
rewardItem = getFactionalCollectionItem(faction);
break;
case 2:
blog("rollRandomFactionalCollectible - send to getAppropriatePvpRankCollectible.");
rewardItem = getAppropriatePvpRankCollectible(faction, victimRank);
break;
}
if (rewardItem == null || rewardItem.equals(""))
{
blog("rollRandomFactionalCollectible - reward function returned a NULL.");
return false;
}
blog("rollRandomFactionalCollectible - grant reward.");
grantFactionalCollectible(winner, rewardItem);
return true;
}
public static boolean grantFactionalCollectible(obj_id winner, String staticItem) throws InterruptedException
{
blog("grantFactionalCollectible - arrival in grantFactionalCollectible function");
if (isIdNull(winner)
|| staticItem == null
|| staticItem.equals("")
|| !static_item.isStaticItem(staticItem))
{
return false;
}
obj_id pInv = utils.getInventoryContainer(winner);
obj_id itemId = static_item.createNewItemFunction(staticItem, pInv);
if (!isValidId(itemId) || !exists(itemId))
{
blog("grantFactionalCollectible - FAILED TO CREATE ITEM IN INVENTORY.");
CustomerServiceLog("CollectionLootChannel", "Player " + getFirstName(winner) + "(" + winner + ") has failed to receive item: " + staticItem + ".");
return false;
}
Vector items = new Vector();
items.setSize(0);
utils.addElement(items, itemId);
blog("grantFactionalCollectible - SUCCESS, creating item in inventory.");
prose_package pp = new prose_package();
prose.setStringId(pp, SID_REWARD_ITEM);
prose.setTT(pp, new string_id("static_item_n", getStaticItemName(itemId)));
sendSystemMessageProse(winner, pp);
CustomerServiceLog("CollectionLootChannel", "Player " + getFirstName(winner) + "(" + winner + ") has received item: " + staticItem + ".");
return true;
}
public static obj_id addMeatlumpLumpsAsLoot(obj_id target, obj_id targetInventory, int cash) throws InterruptedException
{
if (cash < 1
|| !isValidId(target)
|| !exists(target)
|| !isValidId(targetInventory)
|| !exists(targetInventory))
{
return null;
}
obj_id inv = utils.getInventoryContainer(target);
if (inv == null)
{
return null;
}
obj_id cashItem = static_item.createNewItemFunction(MEATLUMP_LUMP, inv);
if (!isIdValid(cashItem))
{
return null;
}
incrementCount(cashItem, cash);
return cashItem;
}
public static boolean giveMeatlumpPuzzleLoot(obj_id player, boolean puzzleThreshold, boolean puzzleBuff) throws InterruptedException
{
if (!isValidId(player) || !exists(player))
{
return false;
}
obj_id pInv = utils.getInventoryContainer(player);
if (!isValidId(pInv) || !exists(pInv))
{
return false;
}
boolean luckyPlayer = luck.isLucky(player, 0.01f);
int lumpAmount = rand(0, 2);
blog("giveMeatlumpPuzzleLoot - lumpAmount: " + lumpAmount);
if (luckyPlayer)
{
int lumpRoll = rand(0, 100);
if (lumpRoll < 51)
{
lumpAmount++;
}
else if (lumpRoll < 91)
{
lumpAmount += 2;
}
else
{
lumpAmount += 3;
}
}
Vector items = new Vector();
items.setSize(0);
blog("giveMeatlumpPuzzleLoot - lucky player lumpAmount: " + lumpAmount);
if (lumpAmount > 0)
{
obj_id lumpsReceived = addMeatlumpLumpsAsLoot(player, pInv, lumpAmount);
blog("giveMeatlumpPuzzleLoot - lumpsReceived: " + lumpsReceived);
if (lumpsReceived == null)
{
return false;
}
utils.addElement(items, lumpsReceived);
}
int lootItemAmount = rand(1, 3);
if (rand(0, 100) > 99)
{
lootItemAmount += rand(0, 1);
}
if (luckyPlayer)
{
lootItemAmount += rand(0, 1);
}
else if (puzzleThreshold && (rand(0,100) > 95 || puzzleBuff))
{
lootItemAmount += rand(0,1);
}
for (int i = 0; i < lootItemAmount; i++)
{
int cols = 1;
int randCol = rand(0, 100);
if (randCol >= 70 && randCol <= 90)
{
cols = 3;
}
else if (randCol > 90)
{
cols = 5;
}
blog("giveMeatlumpPuzzleLoot - randCols: " + randCol);
blog("giveMeatlumpPuzzleLoot - TOTAL cols: " + cols);
String[] strLootItems = dataTableGetStringColumnNoDefaults(MEATLUMP_LOOT_TABLE, rand(0, cols));
if (strLootItems == null || strLootItems.length == 0)
{
return false;
}
blog("giveMeatlumpPuzzleLoot - strLootItems.length: " + strLootItems.length);
blog("giveMeatlumpPuzzleLoot - strLootItems.length: " + strLootItems.length);
String strLootToMake = strLootItems[rand(0, strLootItems.length - 1)];
if (strLootToMake == null || strLootToMake.equals(""))
{
return false;
}
blog("giveMeatlumpPuzzleLoot - strLootToMake: " + strLootToMake);
obj_id lootItem = createLootItem(pInv, strLootToMake, 0);
if (!isValidId(lootItem))
{
return false;
}
utils.addElement(items, lootItem);
blog("giveMeatlumpPuzzleLoot - createLootItem success");
}
blog("giveMeatlumpPuzzleLoot - items.size(): " + items.size());
obj_id[] finalLootList = new obj_id[items.size()];
items.toArray(finalLootList);
showLootBox(player, finalLootList);
return true;
}
public static boolean playerForaging(obj_id player) throws InterruptedException
{
if (!isValidId(player) || !exists(player))
{
CustomerServiceLog("foraging", "Foraging System could not complete because player OID: " + player + " is invalid or no longer exists.");
return false;
}
CustomerServiceLog("foraging", "Player: " + getName(player) + " OID: " + player + " is about to start foraging rolls.");
obj_id pInv = utils.getInventoryContainer(player);
if (!isValidId(pInv) || !exists(pInv))
{
CustomerServiceLog("foraging", "Foraging System could not find inventory for player OID: " + player + ". Inventory container is invalid or no longer exists.");
return false;
}
if (getVolumeFree(pInv) <= 0)
{
CustomerServiceLog("foraging", "Player: " + getName(player) + " OID: " + player + " has a full inventory, foraging rolls aborted.");
sendSystemMessage(player, SID_FULL_INVENTORY);
return false;
}
location curLoc = getLocation(player);
String scene = getCurrentSceneName();
forage_blog("scene: " + scene);
Vector newListOfLocs = new Vector();
newListOfLocs.setSize(0);
int something = 50;
int nothing = 50;
int somethingMod = 0;
int lootMod = 0;
String bonusMessage = "";
if (buff.hasBuff(player, "bm_truffle_pig"))
{
CustomerServiceLog("foraging", "Player: " + getName(player) + " OID: " + player + " has buff bm_truffle_pig and is receiving bonus to avoid getting nothing during forage session.");
float trufflePigVal = buff.getEffectValue("bm_truffle_pig", 2);
bonusMessage += " Pet";
forage_blog("playerForaging: bm_truffle_pig increased somethingMod from: " + somethingMod + " to: " + (somethingMod + trufflePigVal));
somethingMod += (int)trufflePigVal;
}
if (buff.hasBuff(player, "ice_cream_forage_buff"))
{
CustomerServiceLog("foraging", "Player: " + getName(player) + " OID: " + player + " has buff ice_cream_forage_buff and is receiving bonus to avoid getting nothing during forage session.");
float iceCreamVal = buff.getEffectValue("ice_cream_forage_buff", 2);
if (bonusMessage.equals(""))
{
bonusMessage += " Ice Cream";
}
else
{
bonusMessage += ", Ice Cream";
}
forage_blog("playerForaging: ice_cream_forage_buff increased somethingMod from: " + somethingMod + " to: " + (somethingMod + iceCreamVal));
somethingMod += (int)iceCreamVal;
}
if (buff.hasBuff(player, "treasure_forage"))
{
CustomerServiceLog("foraging", "Player: " + getName(player) + " OID: " + player + " has buff treasure_forage and is receiving bonus to avoid getting nothing during forage session.");
float treasureVal = buff.getEffectValue("treasure_forage", 1);
if (bonusMessage.equals(""))
{
bonusMessage += " Kommerken Steak";
}
else
{
bonusMessage += ", Kommerken Steak";
}
forage_blog("playerForaging: treasure_forage increased somethingMod from: " + somethingMod + " to: " + (somethingMod + treasureVal));
somethingMod += (int)treasureVal;
}
boolean isLuckyPlayer = luck.isLucky(player, 0.10f);
if (isLuckyPlayer)
{
CustomerServiceLog("foraging", "Player: " + getName(player) + " OID: " + player + " got really lucking and is receiving bonus to avoid getting nothing during forage session.");
if (bonusMessage.equals(""))
{
bonusMessage += " Luck";
}
else
{
bonusMessage += ", Luck";
}
forage_blog("playerForaging: isLuckyPlayer increased somethingMod from: " + somethingMod + " to: " + (somethingMod + LUCKY_FIND_MODIFIER));
somethingMod += (int)LUCKY_FIND_MODIFIER;
}
if (!bonusMessage.equals(""))
{
prose_package pp = new prose_package();
string_id msg = new string_id(FORAGING_STF, "forage_bonus_mesage");
pp = prose.setStringId(pp, msg);
pp = prose.setTO(pp, bonusMessage);
sendSystemMessageProse(player, pp);
}
if (somethingMod > 0)
{
CustomerServiceLog("foraging", "Player: " + getName(player) + " OID: " + player + " has one or more buffs and/or luck modifiers. The forage system is modifying the players chance of receiving nothing.");
nothing -= somethingMod;
if (nothing < 0)
{
nothing = 0;
}
something += somethingMod;
if (something > 100)
{
something = 100;
}
forage_blog("playerForaging: Nothing: " + nothing);
forage_blog("playerForaging: Something: " + something);
CustomerServiceLog("foraging", "Player: " + getName(player) + " OID: " + player + " has a " + nothing + "% chance of receiving nothing within the foraging system.");
CustomerServiceLog("foraging", "Player: " + getName(player) + " OID: " + player + " has a " + something + "% chance of receiving something within the foraging system.");
}
int initialRoll = rand(1, 100);
forage_blog("playerForaging: initialRoll: " + initialRoll);
CustomerServiceLog("foraging", "Player: " + getName(player) + " OID: " + player + " has rolled a " + initialRoll + ". If this number is less than " + nothing + " the player gets nothing from the foraging system.");
if (initialRoll <= nothing)
{
CustomerServiceLog("foraging", "Player: " + getName(player) + " OID: " + player + " has rolled a " + initialRoll + " and gets nothing from the foraging system.");
forage_blog("YOU ROLLED: " + initialRoll + " on initial roll and get nothing. You needed to get higher than: " + nothing);
sendSystemMessage(player, FOUND_NOTHING);
saveForageLocationOnPlayer(player, newListOfLocs, curLoc);
return true;
}
CustomerServiceLog("foraging", "Player: " + getName(player) + " OID: " + player + " has rolled a " + initialRoll + " and gets some yet to be determined item from the foraging system.");
forage_blog("playerForaging: YOU GET SOMETHING");
int enzymeMod = 0;
int treasMod = 0;
String buffMsg = "";
if (buff.hasBuff(player, "bm_truffle_pig"))
{
CustomerServiceLog("foraging", "Player: " + getName(player) + " OID: " + player + " has the bm_truffle_pig buff and will receive an extra roll for ENZYMES within the foraging system.");
float enzymeBuff = buff.getEffectValue("bm_truffle_pig", 3);
forage_blog("playerForaging: bm_truffle_pig increased enzymeMod score from: " + enzymeMod + " to: " + (enzymeMod + enzymeBuff));
enzymeMod += (int)enzymeBuff;
}
if (buff.hasBuff(player, "treasure_forage"))
{
CustomerServiceLog("foraging", "Player: " + getName(player) + " OID: " + player + " has the treasure_forage buff and will receive an extra roll for TREASURE MAPS within the foraging system.");
float treasureValMap = buff.getEffectValue("treasure_forage", 2);
treasMod += (int)treasureValMap;
}
boolean buffRoll = false;
if (enzymeMod > 0)
{
CustomerServiceLog("foraging", "Player: " + getName(player) + " OID: " + player + " is NOW receiving their extra roll for ENZYMES within the foraging system.");
forage_blog("Player receives extra roll because of buffs for: enzyme");
buffMsg += " Plant Enzymes";
int enzymRoll = rand(1, 100);
CustomerServiceLog("foraging", "Player: " + getName(player) + " OID: " + player + " rolled " + enzymRoll + ". If this number is less than, or equal to " + enzymeMod + ", the player will get an enzyme.");
if (enzymRoll <= enzymeMod)
{
CustomerServiceLog("foraging", "Player: " + getName(player) + " OID: " + player + " rolled " + enzymRoll + " and received an enzyme.");
forage_blog("rareObject reward: enzyme");
obj_id enzyme = createObject("object/tangible/loot/beast/enzyme_2.iff", pInv, "");
sendSystemMessage(player, FOUND_ENZYME);
saveForageLocationOnPlayer(player, newListOfLocs, curLoc);
buffRoll = true;
}
}
if (treasMod > 0)
{
CustomerServiceLog("foraging", "Player: " + getName(player) + " OID: " + player + " is NOW receiving their extra roll for TREASURE MAPS within the foraging system.");
forage_blog("Player receives extra roll because of buffs for: treasure map");
if (buffMsg.equals(""))
{
buffMsg += " Treasure Map";
}
else
{
buffMsg += ", Treasure Map";
}
int treasureRoll = rand(1, 100);
if (treasureRoll <= 0)
{
treasureRoll = 0;
}
CustomerServiceLog("foraging", "Player: " + getName(player) + " OID: " + player + " rolled " + treasureRoll + ". If this number is less than, or equal to " + treasMod + ", the player will get an enzyme.");
if (treasureRoll <= treasMod)
{
CustomerServiceLog("foraging", "Player: " + getName(player) + " OID: " + player + " rolled " + treasureRoll + " and received a treasure map.");
forage_blog("rareObject reward: treasure");
boolean objectReceived = loot.getRareForagedTreasureMap(player, pInv);
sendSystemMessage(player, FOUND_TREASURE);
saveForageLocationOnPlayer(player, newListOfLocs, curLoc);
buffRoll = true;
}
}
if (!buffMsg.equals(""))
{
prose_package pp = new prose_package();
string_id msg = new string_id(FORAGING_STF, "forage_buff_roll_mesage");
pp = prose.setStringId(pp, msg);
pp = prose.setTO(pp, buffMsg);
sendSystemMessageProse(player, pp);
}
if (buffRoll)
{
CustomerServiceLog("foraging", "Player: " + getName(player) + " OID: " + player + " has received either an ENZYME AND/OR a TREASURE MAP because of their buffs. The forage system is now exiting.");
return true;
}
CustomerServiceLog("foraging", "Player: " + getName(player) + " OID: " + player + " has not received an enzyme or treasure map as a result of a buf so we will continue through the forage system.");
forage_blog("Player moves on to get basic rolls");
int enzLow = dataTableGetInt(FORAGING_LOOT_ROLL_TABLE, LOOT_ENZYME, LOOT_LOW_COL);
int enzHigh = dataTableGetInt(FORAGING_LOOT_ROLL_TABLE, LOOT_ENZYME, LOOT_HIGH_COL);
int compLow = dataTableGetInt(FORAGING_LOOT_ROLL_TABLE, LOOT_COMPONENT, LOOT_LOW_COL);
int compHigh = dataTableGetInt(FORAGING_LOOT_ROLL_TABLE, LOOT_COMPONENT, LOOT_HIGH_COL);
int wormLow = dataTableGetInt(FORAGING_LOOT_ROLL_TABLE, LOOT_WORM, LOOT_LOW_COL);
int wormHigh = dataTableGetInt(FORAGING_LOOT_ROLL_TABLE, LOOT_WORM, LOOT_HIGH_COL);
int baitLow = dataTableGetInt(FORAGING_LOOT_ROLL_TABLE, LOOT_BAIT, LOOT_LOW_COL);
int baitHigh = dataTableGetInt(FORAGING_LOOT_ROLL_TABLE, LOOT_BAIT, LOOT_HIGH_COL);
int treasLow = dataTableGetInt(FORAGING_LOOT_ROLL_TABLE, LOOT_TREASURE, LOOT_LOW_COL);
int treasHigh = dataTableGetInt(FORAGING_LOOT_ROLL_TABLE, LOOT_TREASURE, LOOT_HIGH_COL);
if (enzLow < 0 || enzHigh < 0 || compLow < 0 || compHigh < 0 || wormLow < 0 || wormHigh < 0 || baitLow < 0 || baitHigh < 0 || treasLow < 0 || treasHigh < 0)
{
CustomerServiceLog("foraging", "Player: " + getName(player) + " OID: " + player + " has corrupted data for one or more of the foraging data. Contact development.");
return false;
}
CustomerServiceLog("foraging", "Player: " + getName(player) + " OID: " + player + " will receive an enzyme if they roll between " + enzLow + " and " + enzHigh + ".");
CustomerServiceLog("foraging", "Player: " + getName(player) + " OID: " + player + " will receive a component (ice cream fryer food) if they roll between " + compLow + " and " + compHigh + ".");
CustomerServiceLog("foraging", "Player: " + getName(player) + " OID: " + player + " will receive a worm or theif enemy if they roll between " + wormLow + " and " + wormHigh + ".");
CustomerServiceLog("foraging", "Player: " + getName(player) + " OID: " + player + " will receive a bait or bugs if they roll between " + baitLow + " and " + baitHigh + ".");
CustomerServiceLog("foraging", "Player: " + getName(player) + " OID: " + player + " will receive a treasure map if they roll between " + treasLow + " and " + treasHigh + ".");
int lootRoll = rand(1, 100);
CustomerServiceLog("foraging", "Player: " + getName(player) + " OID: " + player + " rolled " + lootRoll + ". The system will now attempt to reward the player with the specific item won.");
forage_blog("YOU ROLLED: " + lootRoll);
if (lootRoll >= enzLow && lootRoll <= enzHigh)
{
CustomerServiceLog("foraging", "Player: " + getName(player) + " OID: " + player + " rolled " + lootRoll + " and has received an ENZYME.");
forage_blog("rareObject reward: enzyme");
obj_id enzyme = createObject("object/tangible/loot/beast/enzyme_2.iff", pInv, "");
sendSystemMessage(player, FOUND_ENZYME);
}
else if (lootRoll >= compLow && lootRoll <= compHigh)
{
CustomerServiceLog("foraging", "Player: " + getName(player) + " OID: " + player + " rolled " + lootRoll + " and has received a COMPONENT.");
forage_blog("rareObject reward: component");
if (giveForagedCollectionObject(player, pInv, scene))
{
sendSystemMessage(player, FOUND_COMPONENT);
}
}
else if (lootRoll >= wormLow && lootRoll <= wormHigh)
{
CustomerServiceLog("foraging", "Player: " + getName(player) + " OID: " + player + " rolled " + lootRoll + " and has received a WORM/THEIF ENEMY.");
forage_blog("rareObject reward: worm");
int mobLevel = getLevel(player);
String invis = stealth.getInvisBuff(player);
if (invis != null)
{
stealth.checkForAndMakeVisibleNoRecourse(player);
}
String[] enemyList = dataTableGetStringColumnNoDefaults(FORAGING_ENEMY_TABLE, "enemy");
int idx = rand(0, (enemyList.length - 1));
obj_id mob = create.object(enemyList[idx], curLoc, mobLevel);
setObjVar(mob, "player", player);
attachScript(mob, FORAGE_ENEMY_SCRIPT);
sendSystemMessage(player, FOUND_WORM);
}
else if (lootRoll >= treasLow && lootRoll <= treasHigh)
{
CustomerServiceLog("foraging", "Player: " + getName(player) + " OID: " + player + " rolled " + lootRoll + " and has received a TREASURE MAP.");
forage_blog("rareObject reward: treasure map");
loot.getRareForagedTreasureMap(player, pInv);
sendSystemMessage(player, FOUND_TREASURE);
}
else
{
CustomerServiceLog("foraging", "Player: " + getName(player) + " OID: " + player + " rolled " + lootRoll + " and has received BAIT.");
forage_blog("reward: bait");
String[] bait = dataTableGetStringColumnNoDefaults(FORAGING_RARE_TABLE, "ITEM_TANGIBLE");
int itemIndex = rand(0, (bait.length - 1));
forage_blog("Won BAIT: object/tangible/bait" + itemIndex);
createObjectOverloaded("object/tangible/" + bait[itemIndex], pInv);
sendSystemMessage(player, FOUND_SOMETHING);
}
CustomerServiceLog("foraging", "Player: " + getName(player) + " OID: " + player + " should have received a reward object. The forage location will be stored and the forage session will be completed.");
saveForageLocationOnPlayer(player, newListOfLocs, curLoc);
return true;
}
public static int getRandomRareForagedLoot(obj_id self, int enzymeChance, int wormChance, int treasureMapChance, int componentChance) throws InterruptedException
{
forage_blog("getRandomRareForagedLoot init");
forage_blog("getRandomRareForagedLoot:treasureMapChance: " + treasureMapChance);
Vector rareItemList = new Vector();
rareItemList.setSize(0);
utils.addElement(rareItemList, ENZYME);
utils.addElement(rareItemList, WORM);
utils.addElement(rareItemList, TREASURE);
utils.addElement(rareItemList, COMPONENT);
forage_blog("getRandomRareForagedLoot:treasureMapChance: " + treasureMapChance);
if (enzymeChance > 0)
{
int division = enzymeChance / RARE_COMPONENT_DIVISOR;
for (int i = 0; i < division; ++i)
{
utils.addElement(rareItemList, ENZYME);
}
}
if (wormChance > 0)
{
int division = wormChance / RARE_COMPONENT_DIVISOR;
for (int i = 0; i < division; ++i)
{
utils.addElement(rareItemList, WORM);
}
}
if (treasureMapChance > 0)
{
int division = treasureMapChance / SUPER_RARE_COMPONENT_DIVISOR;
for (int i = 0; i < division; ++i)
{
utils.addElement(rareItemList, TREASURE);
}
}
if (componentChance > 0)
{
int division = componentChance / RARE_COMPONENT_DIVISOR;
for (int i = 0; i < division; ++i)
{
utils.addElement(rareItemList, COMPONENT);
}
}
int listSize = rareItemList.size();
forage_blog("rareItemList.size(): " + listSize);
int randNum = rand(0, listSize - 1);
forage_blog("randNum: " + randNum);
forage_blog("Random return: " + rareItemList.get(randNum));
CustomerServiceLog("foraging", "Player: " + getName(self) + " OID: " + self + "rolled against a foraging rare item list and received rare loot item category: " + rareItemList.get(randNum));
forage_blog("getRandomRareForagedLoot do we have the scriptvar: " + utils.hasScriptVar(self, "qa.give_forage_data"));
if (utils.hasScriptVar(self, "qa.give_forage_data") && isGod(self))
{
StringBuilder strForageFeedBack = new StringBuilder(utils.getStringScriptVar(self, "qa.strForageFeedBack"));
strForageFeedBack.append("Categories: Enzyme = 0, Worm/Thief = 1, Component = 2, Treasure Map = 3\n\r");
strForageFeedBack.append("Rare Item List Length: ").append(listSize).append("\n\r");
for (int i = 0; i < listSize; ++i)
{
strForageFeedBack.append("Rare Item Number ").append(i).append(" is category: ").append(rareItemList.get(i)).append("\n\r");
}
strForageFeedBack.append("Winning Item Category: ").append(rareItemList.get(randNum)).append("\n\r\n\r");
strForageFeedBack.append("Check Constants - The values should never change.\n\r");
strForageFeedBack.append("DEFAULT_ENZYME_CHANCE: (40) " + DEFAULT_ENZYME_CHANCE + "\n\r");
strForageFeedBack.append("DEFAULT_WORM_CHANCE: (40) " + DEFAULT_WORM_CHANCE + "\n\r");
strForageFeedBack.append("DEFAULT_TREASURE_CHANCE: (0) " + DEFAULT_TREASURE_CHANCE + "\n\r");
strForageFeedBack.append("DEFAULT_COMPONENT_CHANCE: (40) " + DEFAULT_COMPONENT_CHANCE + "\n\r");
strForageFeedBack.append("ENZYME_MODIFIER: (0) " + ENZYME_MODIFIER + "\n\r");
strForageFeedBack.append("TREASURE_MODIFIER: (0) " + TREASURE_MODIFIER + "\n\r");
strForageFeedBack.append("PLAYER_DEFAULT_FIND_MODIFIER: (0) " + PLAYER_DEFAULT_FIND_MODIFIER + "\n\r");
strForageFeedBack.append("LUCKY_FIND_MODIFIER: (6) " + LUCKY_FIND_MODIFIER + "\n\r");
utils.setScriptVar(self, "qa.strForageFeedBack", strForageFeedBack.toString());
utils.setScriptVar(self, "qa.strForageFeedBackCategory", (Integer) rareItemList.get(randNum));
}
return (Integer) rareItemList.get(randNum);
}
public static boolean getRareForagedTreasureMap(obj_id player, obj_id pInv) throws InterruptedException
{
forage_blog("getRareForagedTreasureMap init");
if (!isIdValid(player) || !exists(player))
{
return false;
}
else if (!isIdValid(pInv) || !exists(pInv))
{
return false;
}
CustomerServiceLog("foraging", "Player: " + getName(player) + " OID: " + player + " is rolling for a treasure map.");
forage_blog("getRareForagedTreasureMap - rareObject reward: treasure map");
String treasureMap = getPlayerTreasureMapString(player);
if (treasureMap != null && !treasureMap.equals(""))
{
static_item.createNewItemFunction(treasureMap, pInv);
}
else
{
forage_blog("getRareForagedTreasureMap - rareObject reward ERROR: treasure map level not found");
static_item.createNewItemFunction("item_treasure_map_1_10", pInv);
}
CustomerServiceLog("foraging", "Player: " + getName(player) + " OID: " + player + " has won treasure map: " + treasureMap);
forage_blog("getRareForagedTreasureMap do we have the scriptvar: " + utils.hasScriptVar(player, "qa.give_forage_data"));
return true;
}
public static String getPlayerTreasureMapString(obj_id player) throws InterruptedException
{
if (!isValidId(player))
{
return null;
}
int playerLvl = getLevel(player);
if (playerLvl <= 0)
{
return null;
}
String mapPrefix = "item_treasure_map_";
String mapAppend = "1_10";
if (playerLvl >= 81 && playerLvl <= 90)
{
mapAppend = "81_90";
}
else if (playerLvl >= 71 && playerLvl <= 80)
{
mapAppend = "71_80";
}
else if (playerLvl >= 61 && playerLvl <= 70)
{
mapAppend = "61_70";
}
else if (playerLvl >= 51 && playerLvl <= 60)
{
mapAppend = "51_60";
}
else if (playerLvl >= 41 && playerLvl <= 50)
{
mapAppend = "41_50";
}
else if (playerLvl >= 31 && playerLvl <= 40)
{
mapAppend = "31_40";
}
else if (playerLvl >= 21 && playerLvl <= 30)
{
mapAppend = "21_30";
}
else if (playerLvl >= 11 && playerLvl <= 20)
{
mapAppend = "11_20";
}
return mapPrefix + mapAppend;
}
public static boolean giveForagedCollectionObject(obj_id self, obj_id pInv, String scene) throws InterruptedException
{
if (!isIdValid(self))
{
return false;
}
if ((scene == null) || scene.equals(""))
{
return false;
}
forage_blog("rareObject reward: IN giveCollectionObject");
forage_blog("rareObject reward: scene: " + scene);
boolean componentPlanet = false;
for (String COMPONENT_PLANET : COMPONENT_PLANETS) {
if (scene.startsWith(COMPONENT_PLANET)) {
componentPlanet = true;
break;
}
}
if (!componentPlanet)
{
sendSystemMessage(self, FOUND_NOTHING);
return false;
}
String[] component = dataTableGetStringColumnNoDefaults(FORAGING_RARE_TABLE, scene);
if (component == null || component.length == 0)
{
return false;
}
forage_blog("rareObject reward: IN giveCollectionObject");
int itemIndex = rand(0, (component.length - 1));
forage_blog("rareObject reward: IN giveCollectionObject - itemIndex: " + itemIndex);
String objTemplate = dataTableGetString(FORAGING_RARE_TABLE, itemIndex, scene);
forage_blog("rareObject reward: IN giveCollectionObject - objTemplate: " + objTemplate);
createObjectOverloaded(objTemplate, pInv);
return true;
}
public static boolean saveForageLocationOnPlayer(obj_id self, Vector newListOfLocs, location curLoc) throws InterruptedException
{
if (utils.hasScriptVar(self, "forage.listOfAlreadyForagedLocs"))
{
location[] oldListOfLocs = utils.getLocationArrayScriptVar(self, "forage.listOfAlreadyForagedLocs");
for (location loc : oldListOfLocs) {
utils.addElement(newListOfLocs, loc);
}
}
utils.addElement(newListOfLocs, curLoc);
utils.setScriptVar(self, "forage.listOfAlreadyForagedLocs", newListOfLocs);
utils.setScriptVar(self, "forage.lastLocation", curLoc);
return true;
}
public static boolean logForageData(obj_id player) throws InterruptedException
{
if (!isValidId(player) || !exists(player))
{
return false;
}
int loopSeed = 1;
if (utils.hasScriptVar(player, "qa.loopseed"))
{
loopSeed = utils.getIntScriptVar(player, "qa.loopseed");
}
String strForageFeedBackLog = utils.getStringScriptVar(player, "qa.strForageFeedBack");
if (strForageFeedBackLog == null || strForageFeedBackLog.equals(""))
{
sendSystemMessageTestingOnly(player, "The log was blank");
return false;
}
int strForageFeedBackCategoryLog = utils.getIntScriptVar(player, "qa.strForageFeedBackCategory");
if (strForageFeedBackCategoryLog < 0)
{
sendSystemMessageTestingOnly(player, "The Category Number was invalid");
return false;
}
String categoryName = "";
switch (strForageFeedBackCategoryLog)
{
case loot.ENZYME:
categoryName = "ENZYME";
break;
case loot.WORM:
categoryName = "WORMTHIEF";
break;
case loot.COMPONENT:
categoryName = "COMPONENT";
break;
case loot.TREASURE:
categoryName = "TREASURE" + getPlayerTreasureMapString(player);
break;
case loot.BAIT:
categoryName = "BAIT";
break;
case loot.NOTHING:
categoryName = "NOTHING";
break;
default:
break;
}
if (categoryName.equals(""))
{
sendSystemMessageTestingOnly(player, "The Category Name was blank");
return false;
}
int number = getGameTime() + loopSeed + rand(1, 100) + rand(1, 100);
String title = "foraged" + categoryName + number;
loopSeed++;
utils.setScriptVar(player, "qa.loopseed", loopSeed);
saveTextOnClient(player, title + ".txt", strForageFeedBackLog);
return true;
}
public static boolean blog(String msg) throws InterruptedException
{
LOG("minigame", msg);
return true;
}
public static boolean forage_blog(String msg) throws InterruptedException
{
if (FORAGE_LOGGING_ON)
{
LOG(FORAGE_LOGGING_CATEGORY, msg);
}
return true;
}
public static boolean addRareLoot(obj_id target) throws InterruptedException
{
// make sure system is on before we do anything else
if(RLS_DISABLED) {
return false;
}
// get the attacker who did the most damage.
obj_id player = getObjIdObjVar(target, xp.VAR_TOP_GROUP);
// make sure the attacker is a player.
if(!isValidId(player) || !isPlayer(player)){
return false;
}
// player must be ATK
if(isAwayFromKeyBoard(player)) {
return false;
}
// if enabled player must have provided user input (not macros) in last 15 mins to get RLC
if(RLS_MACROS_DISABLED && !isPlayerActive(player)) {
return false;
}
// variance between mob level and player level must be within acceptable range (default is +/- 6)
int playerLevel = getLevel(player);
int mobLevel = getLevel(target);
if(mobLevel < (playerLevel - RLS_LOWER_LEVEL_BAND) || mobLevel > (playerLevel + RLS_UPPER_LEVEL_BAND)) {
return false;
}
location playerLoc = getLocation(player);
location targetLoc = getLocation(target);
// variance between your last kill location and current kill location must show you've moved (> 5m is default)
if(hasObjVar(player, OBJVAR_RLS_LAST_LOOT_LOCATION) && RLS_MIN_DIST_FROM_LAST_LOOT > 0) {
location lastLocation = getLocationObjVar(player, OBJVAR_RLS_LAST_LOOT_LOCATION);
if(getDistance(playerLoc, lastLocation) < RLS_MIN_DIST_FROM_LAST_LOOT) {
return false;
}
}
// at least X amount of time must have passed between chest loots (default is 15 min)
if(hasObjVar(player, OBJVAR_RLS_LAST_LOOT_TIME) && RLS_TIME_BETWEEN_AWARDS > 0) {
int currentTime = getGameTime();
int lastTime = getIntObjVar(player, OBJVAR_RLS_LAST_LOOT_TIME);
if(currentTime < (lastTime + RLS_TIME_BETWEEN_AWARDS)) {
return false;
}
}
// roll to see if we've won a chest, default chance is 1%
int roll = rand(1, 100);
if(roll <= RLS_DROP_CHANCE) {
return false;
}
// We've won a chest, let's decide which type
LOG("rare_loot", "Player (" + player + ") qualified for an RLS chest (chance: " + RLS_DROP_CHANCE + " roll: " + roll + ")");
int bonus = 0;
// make sure the player has an extremely more difficult time to loot a chest if they're still going through the tutorial
if (hasObjVar(player, "npe")) {
bonus -= 500;
}
// give the player a bonus if the mob is higher than their own level, lower bonus if mob is a lower level
bonus += 10 * (mobLevel - playerLevel);
// give the player a bonus if the mob is a silver or gold - only if they're equal to or higher than player's level
if (mobLevel >= playerLevel) {
LOG("rare_loot", "Player (" + player + ") killed an NPC that is equal to or greater than their level and is being evaluated for an RLS award!");
String creatureName = ai_lib.getCreatureName(target);
if (creatureName.equals("")) return false;
switch (dataTableGetInt("datatables/mob/creatures.iff", creatureName, "difficultyClass")) {
case 1:
if (creatureName.startsWith("heroic_")) {
LOG("rare_loot", "Player (" + player + ") killed a silver NPC and is being evaluated for an RLS award!");
bonus += 10;
}
break;
case 2:
if (creatureName.startsWith("heroic_")) {
LOG("rare_loot", "Player (" + player + ") killed a gold NPC and is being evaluated for an RLS award!");
bonus += 50;
}
break;
}
}
LOG("rare_loot", "Player (" + player + ") has a bonus of " + bonus + " and is applying that to their RLS award roll");
double rareLootRoll = (rand(1, 1000 - bonus) / 10);
LOG("rare_loot", "Player (" + player + ") just rolled a " + rareLootRoll + " value toward their RLS award (*with bonus*)!");
// now determine what kind of chest is dropped - default to rare quality.
// DEFAULTS:
// RARE: 70% chance.
// EXCEPTIONAL: 25% chance.
// LEGENDARY: 5% chance.
int lootType = 1;
String type = "RARE";
// evaluate Legendary drop chance first, then Exceptional... if it's not either of those two, then it's Rare.
if (rareLootRoll <= RLS_LEGENDARY_CHOICE_CHANCE) {
lootType = 3;
type = "LEGENDARY";
}
else if (rareLootRoll <= RLS_EXCEPTIONAL_CHOICE_CHANCE) {
lootType = 2;
type = "EXCEPTIONAL";
}
LOG("rare_loot", "Player (" + player + ") just qualified for a " + type + " RLS chest!");
obj_id chest = createRareLootChest(target, lootType);
setObjVar(player, OBJVAR_RLS_LAST_LOOT_TIME, getGameTime());
setObjVar(player, OBJVAR_RLS_LAST_LOOT_CHEST, chest);
setObjVar(player, OBJVAR_RLS_LAST_LOOT_LOCATION, playerLoc);
playClientEffectLoc(target, RLS_EFFECT, targetLoc, 1.0f);
playClientEffectLoc(target, RLS_SOUND, targetLoc, 1.0f);
return true;
}
public static obj_id createRareLootChest(obj_id creature, int lootType) throws InterruptedException {
obj_id chest = static_item.createNewItemFunction(CHEST_BASE + lootType, utils.getInventoryContainer(creature));
LOG("rare_loot", "Just created item #" + chest + " in the inventory of creature " + creature);
return chest;
}
/**
* Rolls for granting special DNA loot during loot grant process.
*
* This replaces a series of scripts that were at item.dna.* for a more
* generic process. Specify the DNA roll chance and DNA roll item name
* in the creatures.iff data table, which are added as ObjVars if they
* are valid during the create.createCreature() process.
*
* @param creature the creature who will hold the loot items
* @param container the container of that creature
*/
public static void rollForSpecialDnaLoot(obj_id creature, obj_id container) throws InterruptedException
{
if(isIdValid(creature) && isIdValid(container))
{
if(hasObjVar(creature, OBJVAR_DNA_LOOT_CHANCE) && hasObjVar(creature, OBJVAR_DNA_LOOT_ITEM_NAME))
{
if(rand(1, 100) > getFloatObjVar(creature, OBJVAR_DNA_LOOT_CHANCE))
{
static_item.createNewItemFunction(getStringObjVar(creature, OBJVAR_DNA_LOOT_ITEM_NAME), container);
}
}
}
}
}