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

1768 lines
43 KiB
Plaintext

/**
* Title: utils.scriptlib
* Description: A library containing public general utility functions.
*/
/***** INCLUDES ********************************************************/
include library.loot;
include library.utils;
include library.prose;
include library.colors;
include library.resource;
include library.session;
include library.static_item;
/***** CONSTANTS *******************************************************/
const string SCRIPT_FISHING_PLAYER = "fishing.player";
const string SCRIPT_FISHING_NPC = "fishing.npc";
const string SCRIPT_FISHING_POLE = "fishing.pole";
const int ROLL_FISH_OR_JUNK = 94;
const string VAR_FISH_BASE = "fish";
const string VAR_FISH_NAME = VAR_FISH_BASE + ".name";
const string VAR_FISH_LENGTH = VAR_FISH_BASE + ".length";
const string VAR_FISH_LOCATION = VAR_FISH_BASE + ".location";
const string VAR_FISH_STAMP = VAR_FISH_BASE + ".stamp";
const string VAR_FISH_TIME_STAMP = VAR_FISH_BASE + ".time";
const string VAR_FISH_CATCHER = VAR_FISH_BASE + ".catcher";
const float FISHING_TICK = 7f;
const float SPOOL_RANGE = 20f;
const string SPLASH_EFFECT = "object/tangible/fishing/splash.iff";
const string TBL_TEMPLATE = "datatables/fishing/fish/fish_template.iff";
const string COL_NAME = "name";
const string COL_TEMPLATE = "template";
const string COL_HUE1 = "hueColor1";
const string COL_HUE2 = "hueColor2";
const string COL_LENGTH_NORM = "lengthNorm";
const string COL_LENGTH_MIN = "lengthMin";
const string COL_LENGTH_MAX = "lengthMax";
const string COL_RESOURCE_TYPE = "resourceType";
const string COL_RESOURCE_NORM = "resourceNorm";
const string COL_RESOURCE_MIN = "resourceMin";
const string COL_RESOURCE_MAX = "resourceMax";
const string COL_CHUM_NORM = "chumNorm";
const string COL_TROPHY_TEMPLATE = "trophyTemplate";
//STRING FILE
const string STF_FISH = "fishing";
const string_id SID_START_FISHING = new string_id(STF_FISH, "start_fishing");
const string_id SID_STOP_FISHING = new string_id(STF_FISH, "stop_fishing");
const string_id SID_BAD_CAST = new string_id(STF_FISH, "bad_cast");
const string_id SID_LOCATION_UNFISHABLE = new string_id(STF_FISH, "loc_unfishable");
const string_id PROSE_TOSS_BAIT = new string_id(STF_FISH, "prose_toss_bait");
const string_id SID_TOSS_BAIT = new string_id(STF_FISH, "toss_bait");
const string_id SID_FS_NIBBLE = new string_id(STF_FISH, "fs_nibble");
const string_id SID_FS_BITE = new string_id(STF_FISH, "fs_bite");
const string_id SID_FS_CAUGHT = new string_id(STF_FISH, "fs_caught");
const string_id SID_FS_SNAG = new string_id(STF_FISH, "fs_snag");
const string_id SID_FS_LOOT = new string_id(STF_FISH, "fs_loot");
const string_id SID_LINE_FREE = new string_id(STF_FISH, "line_free");
const string_id SID_LINE_SNAP = new string_id(STF_FISH, "line_snap");
const string_id SID_HARD_NIBBLE = new string_id(STF_FISH, "hard_nibble");
const string_id SID_HARD_BITE = new string_id(STF_FISH, "hard_bite");
const string_id SID_LOST_BAIT = new string_id(STF_FISH, "lost_bait");
const string_id SID_LOST_CATCH = new string_id(STF_FISH, "lost_catch");
const string_id SID_REEL_IN = new string_id(STF_FISH, "reel_in");
const string_id SID_LINE_SPOOLED = new string_id(STF_FISH, "line_spooled");
const string_id SID_FISH_FIGHT_EASY = new string_id(STF_FISH, "fish_fight_easy");
const string_id SID_FISH_FIGHT_HARD = new string_id(STF_FISH, "fish_fight_hard");
const string_id SID_FISH_FIGHT_AWAY = new string_id(STF_FISH, "fish_fight_away");
const string_id SID_FISH_FIGHT_CLOSER = new string_id(STF_FISH, "fish_fight_closer");
const string_id SID_FISH_RUN = new string_id(STF_FISH, "fish_run");
const string_id SID_FISH_CHARGE = new string_id(STF_FISH, "fish_charge");
const string_id SID_LOOT_BEACHED = new string_id(STF_FISH, "loot_beached");
const string_id SID_REEL_LOOT = new string_id(STF_FISH, "reel_loot");
const string_id PROSE_NOTIFY_CATCH = new string_id(STF_FISH, "prose_notify_catch");
//FLY STRING IDS
const string_id FLY_NIBBLE = new string_id(STF_FISH, "fly_nibble");
const string_id FLY_BITE = new string_id(STF_FISH, "fly_bite");
const string_id FLY_CATCH = new string_id(STF_FISH, "fly_catch");
const string_id FLY_SNAG = new string_id(STF_FISH, "fly_snag");
//PLAYER DATA
const string SCRIPTVAR_OLD_MOOD = "fishing.oldMood";
const string SCRIPTVAR_STATUS = "fishing.status";
const string SCRIPTVAR_SUI = "fishing.sui";
const string SCRIPTVAR_POLE = "fishing.pole";
const string SCRIPTVAR_LOCATION = "fishing.location";
const string SCRIPTVAR_ACTION = "fishing.action";
const string SCRIPTVAR_BONUS = "fishing.bonus";
const string SCRIPTVAR_CAUGHT = "fishing.caught";
const string SCRIPTVAR_MARKER = "fishing.marker";
const string TEMPLATE_MARKER = "object/tangible/fishing/marker.iff";
//FISHING STATUS
const int FS_NONE = 0;
const int FS_CAST = 1;
const int FS_WAIT = 2;
const int FS_NIBBLE = 3;
const int FS_BITE = 4;
const int FS_CAUGHT = 5;
const int FS_SNAG = 6;
const int FS_LOOT = 7;
const string[] FISHING_STATUS = {
"None",
"Just Cast Line...",
"Waiting.....",
"Nibble...",
"BITE!",
"CAUGHT SOMETHING!",
"Line Snagged?",
"CAUGHT SOMETHING!"
};
//FISHING ACTIONS
const int FA_NONE = 0;
const int FA_TUG_UP = 1;
const int FA_TUG_RIGHT = 2;
const int FA_TUG_LEFT = 3;
const int FA_SMALL_REEL = 4;
const int FA_STOP_FISHING = 5;
const int FA_MAX = 5; //same as last number
const string[] FISHING_ACTIONS = {
"None",
"Tug Up",
"Tug Right",
"Tug Left",
"Small Reel",
"Stop Fishing"
};
const string[] ENCODED_FISHING_ACTIONS = {
//"@" + STF_FISH + ":fa_none",
"@" + STF_FISH + ":fa_tug_up",
"@" + STF_FISH + ":fa_tug_right",
"@" + STF_FISH + ":fa_tug_left",
"@" + STF_FISH + ":fa_small_reel",
"@" + STF_FISH + ":fa_stop"
};
//POLE DATA
const string SCRIPTVAR_IN_USE = "fishing.inUse";
const string VAR_FISHING_BAIT_BASE = "fishing.bait";
const string VAR_FISHING_BAIT_STATUS = VAR_FISHING_BAIT_BASE + ".status";
//BAIT STATUS
const int BS_NONE = 0;
const int BS_FRESH = 1;
const int BS_SOGGY = 2;
const int BS_MUSH = 3;
const string[] BAIT_STATUS = {
"None",
"Fresh",
"Soggy",
"Mush"
};
//PLAYER HANDLERS
const string HANDLER_FISHING_TICK = "handleFishingTick";
const string HANDLER_FISHING_SUI = "handleFishingSui";
const string HANDLER_PLAY_CAST_SPLASH = "handlePlayCastSplash";
const string HANDLER_REEL_IN = "handleReelIn";
const string HANDLER_CAUGHT_SOMETHING = "handleCaughtSomething";
//POLE HANDLERS
const string HANDLER_BAIT_SUI = "handleBaitSui";
/***** FISHING *******************************************************/
boolean startFishing(obj_id target)
{
LOG("fishing","************ startFishing: now = " + getGameTime() + " ****************");
LOG("fishing","startFishing: entered... target = " + target);
if ( !isIdValid(target) )
return false;
if ( isFishing(target) )
return false;
obj_id pole = getObjectInSlot(target, "hold_r");
if ( !isIdValid(pole) )
return false;
if ( !isFishingPole(pole) )
{
sendSystemMessage(target, new string_id(STF_FISH, "must_have_pole")); // To fish, you must first have a fishing pole equipped.
return false;
}
if ( !isFishingPoleBaited(pole) )
{
sendSystemMessage(target, new string_id(STF_FISH, "bait_your_pole")); // To fish, you must first bait your pole.
return false;
}
obj_id playerCurrentMount = getMountId (target);
boolean isMounted = isIdValid(playerCurrentMount);
boolean isOnYodaChair = false;
if(isMounted)
{
string template = getTemplateName(playerCurrentMount);
if(!template.equals("object/mobile/vehicle/hover_chair.iff"))
{
sendSystemMessage(target, new string_id(STF_FISH, "not_this_vehicle")); // To fish, you must first bait your pole.
return false;
}
else
isOnYodaChair = true;
}
if(getState(target, STATE_SWIMMING) == 1 && !isOnYodaChair)
{
sendSystemMessage(target, new string_id(STF_FISH, "no_fish_swim")); // To fish, you must first bait your pole.
return false;
}
location castLoc = getFishingCastLocation(target);
if ( castLoc == null )
return false;
if ( isPlayer(target) )
{
attachScript(target, SCRIPT_FISHING_PLAYER);
sendSystemMessage(target, new string_id(STF_FISH, "cast_line")); // You cast your line and begin fishing...
}
else
{
attachScript(target, SCRIPT_FISHING_NPC);
}
LOG("fishing","startFishing: casting line...");
float range = getDistance(getLocation(target), castLoc);
float castTime = getFishingCastTime(range);
LOG("fishing","startFishing: casting range = " + range + " time = " + castTime);
if ( castTime < 0f )
return false;
session.logActivity(target, session.ACTIVITY_FISHING);
utils.setScriptVar(pole, SCRIPTVAR_IN_USE, target);
chat.setTempAnimationMood(target, "fishing");
doAnimationAction(target, "fishing_cast");
LOG("fishing","startFishing: setting initial state to FS_CAST");
setFishingState(target, FS_CAST);
//store cast data...
LOG("fishing","startFishing: storing initial data...");
initializeFishingData(target, pole, castLoc);
dictionary params = new dictionary();
params.put("pole", pole);
params.put("castLoc", castLoc);
LOG("fishing","startFishing: messaging HANDLER_PLAY_CAST_SPLASH...");
messageTo(target, HANDLER_PLAY_CAST_SPLASH, params, castTime, false);
return true;
}
void stopFishing(obj_id target, boolean animate)
{
LOG("fishing","************ stopFishing: now = " + getGameTime() + " ****************");
LOG("fishing","stopFishing: entered... target = " + target);
if ( !isIdValid(target) )
return;
//debug
if ( utils.hasScriptVar(target, SCRIPTVAR_MARKER) )
{
obj_id marker = utils.getObjIdScriptVar(target, SCRIPTVAR_MARKER);
if ( isIdValid(marker) )
destroyObject(marker);
utils.removeScriptVar(target, SCRIPTVAR_MARKER);
}
//end debug
if ( isPlayer(target) )
{
if ( !animate )
utils.setScriptVar(target, "noAnimate", true);
detachScript(target, SCRIPT_FISHING_PLAYER);
sendSystemMessage(target, new string_id(STF_FISH, "stop_fishing")); // You reel-in your line and stop fishing...
}
else
{
detachScript(target, SCRIPT_FISHING_NPC);
}
}
void stopFishing(obj_id target)
{
stopFishing(target, true);
}
boolean isPoleInUse(obj_id pole)
{
if ( !isIdValid(pole) )
return false;
return utils.hasScriptVar(pole, SCRIPTVAR_IN_USE);
}
void playCastSplash(obj_id target, dictionary params)
{
if ( !isIdValid(target) || (params == null) || (params.isEmpty()) )
return;
location castLoc = params.getLocation("castLoc");
if ( castLoc == null )
return;
//This is never getting cleaned up - changing it to a particle effect
/*
obj_id splash = createObject(SPLASH_EFFECT, castLoc);
if ( isIdValid(splash) )
{
dictionary cleanup = new dictionary();
cleanup.put("id", splash);
messageTo(target, "handleSplashCleanup", cleanup, 5, false);
}
*/
playClientEffectLoc(getPlayerCreaturesInRange(castLoc, 100.0f), "appearance/pt_splash.prt", castLoc, 0.0f);
// Clean up the old marker.
if ( utils.hasScriptVar(target, SCRIPTVAR_MARKER) )
{
obj_id marker = utils.getObjIdScriptVar(target, SCRIPTVAR_MARKER);
if ( isIdValid(marker) )
destroyObject(marker);
utils.removeScriptVar(target, SCRIPTVAR_MARKER);
}
obj_id marker = createObject(TEMPLATE_MARKER, castLoc);
if ( isIdValid(marker) )
{
setLocation(marker, castLoc);
faceTo(marker, target);
utils.setScriptVar(target, SCRIPTVAR_MARKER, marker);
}
}
void initializeFishingData(obj_id target, obj_id pole, location castLoc)
{
if ( !isIdValid(target) || !isIdValid(pole) || (castLoc == null) )
return;
LOG("fishing","initializeFishingData: setting initial fishing scriptvars on target...");
utils.setScriptVar(target, SCRIPTVAR_STATUS, FS_CAST);
utils.setScriptVar(target, SCRIPTVAR_POLE, pole);
utils.setScriptVar(target, SCRIPTVAR_LOCATION, castLoc);
obj_id bait = getBait(pole);
LOG("fishing","initializeFishingData: bait = " + bait);
if ( !isIdValid(bait) )
return;
if ( !hasObjVar(bait, VAR_FISHING_BAIT_STATUS) )
{
LOG("fishing","initializeFishingData: bait lacks objvar VAR_FISHING_BAIT_STATUS. initializing...");
setObjVar(bait, VAR_FISHING_BAIT_STATUS, BS_FRESH);
}
}
void cleanupFishing(obj_id target) //must be called by target!!
{
if ( !isIdValid(target) )
return;
obj_id pole = utils.getObjIdScriptVar(target, SCRIPTVAR_POLE);
if ( isIdValid(pole) )
{
cleanupBait(target, pole);
utils.removeScriptVar(pole, SCRIPTVAR_IN_USE);
}
if ( !utils.hasScriptVar(target, "noAnimate") )
{
doAnimationAction(target, "fishing_reel");
}
else
{
utils.removeScriptVar(target, "noAnimate");
}
if ( utils.hasScriptVar(target, SCRIPTVAR_MARKER) )
{
obj_id marker = utils.getObjIdScriptVar(target, SCRIPTVAR_MARKER);
if ( isIdValid(marker) )
destroyObject(marker);
}
utils.removeScriptVar(target, SCRIPTVAR_STATUS);
utils.removeScriptVar(target, SCRIPTVAR_POLE);
utils.removeScriptVar(target, SCRIPTVAR_LOCATION);
utils.removeScriptVar(target, SCRIPTVAR_ACTION);
utils.removeScriptVar(target, SCRIPTVAR_BONUS);
utils.removeScriptVar(target, SCRIPTVAR_CAUGHT);
utils.removeScriptVar(target, SCRIPTVAR_MARKER);
utils.removeScriptVar(target, SCRIPTVAR_OLD_MOOD);
closeFishingSui(target);
chat.resetTempAnimationMood(target);
}
boolean isFishing(obj_id target)
{
if ( !isIdValid(target) )
return false;
return hasScript(target, SCRIPT_FISHING_PLAYER) || hasScript(target, SCRIPT_FISHING_NPC);
}
boolean isFishingPole(obj_id target)
{
if ( !isIdValid(target) )
return false;
/*if ( getGameObjectType(target) != GOT_misc_fishing_pole )
return false;*/
if ( !hasScript(target, SCRIPT_FISHING_POLE) )
return false;
return true;
}
void updateBaitStatus(obj_id target)
{
LOG("fishing","updateBaitStatus: entering...");
if ( !isIdValid(target) )
return;
if ( !isFishing(target) )
return;
LOG("fishing","updateBaitStatus: getting target's (" + target + ") fishing pole");
obj_id pole = utils.getObjIdScriptVar(target, SCRIPTVAR_POLE);
if ( !isIdValid(pole) )
return;
if ( !isFishingPole(pole) )
return;
LOG("fishing","updateBaitStatus: target = " + target);
obj_id bait = getBait(pole);
if ( !isIdValid(bait) )
return;
LOG("fishing","updateBaitStatus: bait = " + bait);
if ( !hasObjVar(bait, VAR_FISHING_BAIT_STATUS) )
return;
int status = getIntObjVar(bait, VAR_FISHING_BAIT_STATUS);
LOG("fishing","updateBaitStatus: bait status = " + status);
int roll = rand(0,100);
if(isGod(target))
{
roll = 100;
debugSpeakMsg(target, "God Mode is keeping your bait fresh!");
}
LOG("fishing","updateBaitStatus: roll = " + roll);
if ( roll < 20 )
status++;
if ( status > BS_MUSH )
{
LOG("fishing","updateBaitStatus: bait just went from mush to nothing...");
lostBait(target);
}
else
{
setObjVar(bait, VAR_FISHING_BAIT_STATUS, status);
}
}
void cleanupBait(obj_id target, obj_id pole)
{
if ( !isIdValid(target) || !isIdValid(pole) )
return;
if ( !isFishingPole(pole) )
return;
obj_id bait = getBait(pole);
if ( !isIdValid(bait) )
return;
int baitStatus = getIntObjVar(pole, VAR_FISHING_BAIT_STATUS);
if ( baitStatus > BS_FRESH )
{
incrementCount(bait, -1);
string stringStatus = getEncodedBaitStatus(baitStatus);
if ( stringStatus != null )
{
prose_package ppTossBait = prose.getPackage(PROSE_TOSS_BAIT, bait, stringStatus);
sendSystemMessageProse(target, ppTossBait);
}
else
{
sendSystemMessage(target, SID_TOSS_BAIT);
}
if ( getCount(bait) < 1 )
{
sendSystemMessage(target, new string_id(STF_FISH, "out_of_bait")); // You have run out of bait in your tackle...
destroyObject(bait);
}
}
else if ( baitStatus == BS_NONE )
{
removeObjVar(bait, VAR_FISHING_BAIT_STATUS);
}
}
boolean isFishingPoleBaited(obj_id pole)
{
if ( !isIdValid(pole) )
return false;
obj_id bait = getBait(pole);
if ( isIdValid(bait) )
{
return true;
}
return false;
}
obj_id getBait(obj_id pole)
{
if ( !isIdValid(pole) )
return null;
obj_id[] contents = getContents(pole);
if ( contents != null && contents.length == 1 )
{
return contents[0];
}
return null;
}
int getBaitStatus(obj_id target)
{
if ( !isIdValid(target) )
return -1;
if ( !isFishing(target) )
return -1;
obj_id pole = utils.getObjIdScriptVar(target, SCRIPTVAR_POLE);
if ( !isIdValid(pole) )
return -1;
if ( !isFishingPole(pole) )
return -1;
obj_id bait = getBait(pole);
if ( !isIdValid(bait) )
return -1;
if ( !hasObjVar(bait, VAR_FISHING_BAIT_STATUS) )
return -1;
return getIntObjVar(bait, VAR_FISHING_BAIT_STATUS);
}
string getEncodedBaitStatus(int status)
{
if ( status < 0 || status > BAIT_STATUS.length - 1 )
return null;
string baitStatus = BAIT_STATUS[status];
string_id sidStatus = new string_id(STF_FISH, baitStatus);
return utils.packStringId(sidStatus);
}
location getFishingCastLocation(obj_id target)
{
if ( !isIdValid(target) )
return null;
location here = getLocation(target);
float yaw = getYaw(target);
float min = Float.POSITIVE_INFINITY;
float max = Float.NEGATIVE_INFINITY;
for ( int i = 2; i < 10; i++ )
{
float range = i + 0.5f;
location testLoc = utils.rotatePointXZ(here, range, yaw);
testLoc.y = getHeightAtLocation(testLoc.x, testLoc.z);
if ( isLocationFishable(testLoc) )
{
if ( range < min )
min = range;
if ( range > max )
max = range;
}
else
{
if ( i == 2 )
{
sendSystemMessage(target, new string_id(STF_FISH, "too_far")); // You must be within 2 meters of fishable water and facing it to start fishing.
return null;
}
}
}
if ( min == Float.POSITIVE_INFINITY )
{
sendSystemMessage(target, new string_id(STF_FISH, "invalid_location")); // Unable to determine valid fishing location ahead of you.
return null;
}
LOG("fishing","getFishingCastLocation: range min = " + min + " max = " + max);
float castRange = rand(min, max);
LOG("fishing","getFishingCastLocation: randomized cast range = " + castRange);
location there = utils.rotatePointXZ(here, castRange, yaw);
LOG("fishing","getFishingCastLocation: straight cast loc = " + there);
location castLoc = utils.getRandomLocationInRing(there, 0f, 0.5f);
LOG("fishing","getFishingCastLocation: ringed cast loc = " + castLoc);
if ( !isLocationFishable(castLoc) )
{
sendSystemMessage(target, SID_BAD_CAST);
return null;
}
castLoc.y = getWaterTableHeight(castLoc);
return castLoc;
}
float getFishingCastTime(float range)
{
if ( range < 0f )
return -1f;
return 3f;
}
boolean isLocationFishable(location loc)
{
if ( loc != null )
{
location testLoc = (location)loc.clone();
testLoc.y = getHeightAtLocation(loc.x, loc.z);
return isBelowWater(testLoc); //temp hack
}
return false;
}
int showFishingSui(obj_id target)
{
if ( !isIdValid(target) || !isPlayer(target) || !isFishing(target) )
return -1;
closeFishingSui(target);
int status = utils.getIntScriptVar(target, SCRIPTVAR_STATUS);
obj_id pole = utils.getObjIdScriptVar(target, SCRIPTVAR_POLE);
obj_id marker = utils.getObjIdScriptVar(target, SCRIPTVAR_MARKER);
if ( !isIdValid(pole) || !isIdValid(marker) )
{
cleanupFishing(target);
return -1;
}
location loc = getLocation(marker);
if ( loc == null )
{
cleanupFishing(target);
return -1;
}
float lineRange = getDistance(getLocation(target), loc);
obj_id bait = getBait(pole);
if ( !isIdValid(bait) || !hasObjVar(bait, VAR_FISHING_BAIT_STATUS) )
{
LOG("fishing","showFishingSui: bad bait data... stop fishing!");
LOG("fishing","showFishingSui: - bait = " + bait);
stopFishing(target);
return -1;
}
int baitStatus = getIntObjVar(bait, VAR_FISHING_BAIT_STATUS);
int action = utils.getIntScriptVar(target, SCRIPTVAR_ACTION);
string title = "@" + STF_FISH + ":sui_title";
string prompt = "";
prompt += "STATUS : " + FISHING_STATUS[status] + "\n";
prompt += "BAIT STATUS : " + BAIT_STATUS[baitStatus] + "\n";
if ( lineRange >= 10f )
prompt += "LINE RANGE : " + (String.valueOf(lineRange)).substring(0,5) + " \n";
else
prompt += "LINE RANGE : " + (String.valueOf(lineRange)).substring(0,4) + " \n";
prompt += "FISH DENSITY: " + getStars(getFishEfficiency(loc)) + "\n";
//prompt += "FISH DENSITY: " + getFishEfficiency(loc) + "\n";
prompt += "VEGETATION : " + getStars(getVegetationSnagFactor(loc)) + "\n";
//prompt += "VEGETATION : " + getVegetationSnagFactor(loc) + "\n";
//prompt += "BONUS : " + utils.getFloatScriptVar(target, SCRIPTVAR_BONUS) + "\n";
prompt += "NEXT ACTION : " + FISHING_ACTIONS[action] + "\n";
int pid = sui.listbox(target, prompt, title, ENCODED_FISHING_ACTIONS, HANDLER_FISHING_SUI);
if ( pid > -1 )
{
utils.setScriptVar(target, SCRIPTVAR_SUI, pid);
}
return pid;
}
string getStars(float eff)
{
if ( eff < 0.16f )
return "";
else if ( eff < 0.32f )
return "*";
else if ( eff < 0.48f )
return "**";
else if ( eff < 0.64f )
return "***";
else if ( eff < 0.80f )
return "****";
return "*****";
}
void closeFishingSui(obj_id target)
{
if ( utils.hasScriptVar(target, SCRIPTVAR_SUI) )
{
int pid = utils.getIntScriptVar(target, SCRIPTVAR_SUI);
forceCloseSUIPage(pid);
utils.removeScriptVar(target, SCRIPTVAR_SUI);
}
}
void defaultFishingUpdate(obj_id target, int action)
{
if ( !isIdValid(target) )
return;
int status = utils.getIntScriptVar(target, SCRIPTVAR_STATUS);
boolean setWait = true;
switch ( action )
{
case FA_TUG_UP:
case FA_TUG_RIGHT:
case FA_TUG_LEFT:
if ( status == FS_NIBBLE )
{
if ( checkForBite(target, -0.25f) )
setWait = false;
}
else if ( status == FS_BITE )
{
if ( checkForCatch(target, -0.25f) )
setWait = false;
}
case FA_SMALL_REEL:
updateFishingLocation(target, action);
break;
case FA_NONE:
default:
updateFishingWaitState(target);
break;
}
if ( setWait )
utils.setScriptVar(target, SCRIPTVAR_STATUS, FS_WAIT);
}
void updateFishingLocation(obj_id target, int action, boolean caught)
{
LOG("fishing","updateFishingLocation: entered...");
if ( !isIdValid(target) )
return;
location here = getLocation(target);
obj_id marker = utils.getObjIdScriptVar(target, SCRIPTVAR_MARKER);
if ( !isIdValid(marker) )
{
stopFishing(target);
return;
}
location there = getLocation(marker);
if ( there == null )
{
stopFishing(target);
return;
}
float currentDistance = getDistance(here, there);
LOG("fishing","updateFishingLocation: here = " + here.toString());
LOG("fishing","updateFishingLocation: there = " + there.toString());
LOG("fishing","updateFishingLocation: pre-update distance = " + currentDistance);
float dist = 0f;
switch ( action )
{
case FA_TUG_UP:
case FA_TUG_RIGHT:
case FA_TUG_LEFT:
dist = 0.25f;
break;
case FA_SMALL_REEL:
default:
dist = 0.75f;
break;
}
switch ( action )
{
case FA_TUG_UP:
doAnimationAction(target, "fishing_tug_back");
break;
case FA_TUG_RIGHT:
doAnimationAction(target, "fishing_tug_right");
break;
case FA_TUG_LEFT:
doAnimationAction(target, "fishing_tug_left");
break;
case FA_SMALL_REEL:
doAnimationAction(target, "fishing_reel");
break;
}
LOG("fishing","updateFishingLocation: action distance = " + dist);
if ( currentDistance < dist && !caught )
{
LOG("fishing","updateFishingLocation: current distance > action distance & caught = false... stop fishing!");
stopFishing(target);
return;
}
//float theta = utils.getHeadingToLocation(there, here); //degree measure
float theta = getYaw(marker);
float dTheta = 0f;
switch ( action )
{
case FA_TUG_RIGHT:
dTheta = rand(-45f, -15f);
break;
case FA_TUG_LEFT:
dTheta = rand(15f, 45f);
break;
case FA_TUG_UP:
case FA_SMALL_REEL:
default:
dTheta = rand(-5f, 5f);
break;
}
LOG("fishing","updateFishingLocation: heading to player = " + theta);
LOG("fishing","updateFishingLocation: action heading delta = " + dTheta);
theta += dTheta;
LOG("fishing","updateFishingLocation: revised heading = " + theta);
location loc = utils.rotatePointXZ(there, dist, theta);
if ( loc == null )
{
LOG("fishing","updateFishingLocation: revised location = null");
stopFishing(target);
return;
}
loc.y = getWaterTableHeight(loc);
LOG("fishing","updateFishingLocation: revised location = " + loc.toString());
if ( !isLocationFishable(loc) )
{
LOG("fishing","updateFishingLocation: revised location not fishable.. stop fishing...");
sendSystemMessage(target, SID_LOCATION_UNFISHABLE);
stopFishing(target);
return;
}
LOG("fishing","updateFishingLocation: updating scriptvar location ...");
setLocation(marker, loc);
faceTo(marker, target);
checkForSnag(target, loc);
}
void updateFishingLocation(obj_id target, int action)
{
updateFishingLocation(target, action, false);
}
void setFishingState(obj_id target, int state)
{
LOG("fishing","setFishingState: entered... target = " + target + " state = " + state);
if ( !isIdValid(target) )
return;
utils.setScriptVar(target, SCRIPTVAR_STATUS, state);
switch ( state )
{
case FS_WAIT:
//utils.removeScriptVar(target, SCRIPTVAR_BONUS);
break;
case FS_NIBBLE:
markerFlyText(target, FLY_NIBBLE, colors.GREEN);
sendSystemMessage(target, SID_FS_NIBBLE);
break;
case FS_BITE:
markerFlyText(target, FLY_BITE, colors.SALMON);
sendSystemMessage(target, SID_FS_BITE);
break;
case FS_CAUGHT:
markerFlyText(target, FLY_CATCH, colors.GOLDYELLOW);
sendSystemMessage(target, SID_FS_CAUGHT);
break;
case FS_SNAG:
markerFlyText(target, FLY_SNAG, colors.ORANGERED);
sendSystemMessage(target, SID_FS_SNAG);
break;
case FS_LOOT:
markerFlyText(target, FLY_CATCH, colors.GOLDYELLOW);
sendSystemMessage(target, SID_FS_LOOT);
break;
default:
break;
}
if ( state == FS_LOOT || state == FS_CAUGHT )
utils.setScriptVar(target, SCRIPTVAR_CAUGHT, true);
}
void updateFishingWaitState(obj_id target)
{
if ( !isIdValid(target) )
return;
float bonus = 0f;
if ( utils.hasScriptVar(target, SCRIPTVAR_BONUS) )
bonus = utils.getFloatScriptVar(target, SCRIPTVAR_BONUS);
bonus += rand(0f, 0.05f);
utils.setScriptVar(target, SCRIPTVAR_BONUS, bonus);
}
boolean checkForNibble(obj_id target)
{
if ( !isIdValid(target) )
return false;
int baitStatus = getBaitStatus(target);
if ( baitStatus <= BS_NONE )
return false;
//TO DO: check for nibble and update state is necessary
float bonus = 0f;
if ( utils.hasScriptVar(target, SCRIPTVAR_BONUS) )
bonus = utils.getFloatScriptVar(target, SCRIPTVAR_BONUS);
obj_id marker = utils.getObjIdScriptVar(target, SCRIPTVAR_MARKER);
if ( !isIdValid(marker) )
{
stopFishing(target);
return false;
}
location there = getLocation(marker);
if ( there == null )
{
stopFishing(target);
return false;
}
float eff = getFishEfficiency(there);
float chance = eff + bonus;
float roll = rand(0f, 1f);
if ( roll == 0f )
{
bonus += rand(0.1f, 0.2f);
utils.setScriptVar(target, SCRIPTVAR_BONUS, bonus);
if ( !checkForBite(target, 0.3f) )
{
sendSystemMessage(target, SID_HARD_NIBBLE);
utils.setScriptVar(target, SCRIPTVAR_STATUS, FS_NIBBLE);
}
return true;
}
if ( roll < chance )
{
bonus += rand(0.05f, 0.1f);
utils.setScriptVar(target, SCRIPTVAR_BONUS, bonus);
setFishingState(target, FS_NIBBLE);
return true;
}
return false;
}
boolean checkForBite(obj_id target, float superBonus)
{
if ( !isIdValid(target) )
return false;
int baitStatus = getBaitStatus(target);
if ( baitStatus <= BS_NONE )
return false;
//TO DO: check for nibble and update state is necessary
float bonus = 0f;
if ( utils.hasScriptVar(target, SCRIPTVAR_BONUS) )
bonus = utils.getFloatScriptVar(target, SCRIPTVAR_BONUS);
obj_id marker = utils.getObjIdScriptVar(target, SCRIPTVAR_MARKER);
if ( !isIdValid(marker) )
{
stopFishing(target);
return false;
}
location there = getLocation(marker);
if ( there == null )
{
stopFishing(target);
return false;
}
float eff = getFishEfficiency(there);
float poleBonus = getPoleBonus(target);
float chance = eff + bonus + superBonus + poleBonus;
float roll = rand(0f, 1f);
if ( roll < 0.05f )
{
sendSystemMessage(target, SID_HARD_BITE);
//set bonus to POSTITIVE_INFINITY so cant fail catch
utils.setScriptVar(target, SCRIPTVAR_BONUS, Float.POSITIVE_INFINITY);
utils.setScriptVar(target, SCRIPTVAR_STATUS, FS_BITE);
return true;
}
if ( roll < chance )
{
bonus += rand(0.05f, 0.1f);
utils.setScriptVar(target, SCRIPTVAR_BONUS, bonus);
setFishingState(target, FS_BITE);
return true;
}
return false;
}
boolean checkForBite(obj_id target)
{
return checkForBite(target, 0f);
}
boolean checkForCatch(obj_id target, float superBonus)
{
if ( !isIdValid(target) )
return false;
int baitStatus = getBaitStatus(target);
if ( baitStatus <= BS_NONE )
return false;
//TO DO: check for nibble and update state is necessary
float bonus = 0f;
if ( utils.hasScriptVar(target, SCRIPTVAR_BONUS) )
bonus = utils.getFloatScriptVar(target, SCRIPTVAR_BONUS);
boolean caughtFish = false;
if ( bonus == Float.POSITIVE_INFINITY )
{
caughtFish = true;
}
else
{
float poleBonus = getPoleBonus(target);
float chance = 0.25f + bonus + superBonus + poleBonus;
float roll = rand(0f, 1f);
if ( roll < chance )
{
caughtFish = true;
}
}
if ( caughtFish )
{
setFishingState(target, FS_CAUGHT);
return true;
}
return false;
}
boolean checkForCatch(obj_id target)
{
return checkForCatch(target, 0f);
}
boolean checkForSnag(obj_id target, location loc)
{
if ( !isIdValid(target) || loc == null )
return false;
float eff = getVegetationSnagFactor(loc);
if ( eff > rand(0.3f, 1f) )
{
setFishingState(target, FS_SNAG);
utils.setScriptVar(target, SCRIPTVAR_BONUS, eff);
return true;
}
return false;
}
float getFishEfficiency(location loc)
{
if ( loc == null )
return -1f;
//string rType = "seafood_fish";
string rType = "seafood_fish_" + loc.area;
LOG("fishing","getFishEfficiency: rType = " + rType);
obj_id resourceId = pickRandomNonDepeletedResource(rType);
if ( (resourceId == null) || (resourceId == obj_id.NULL_ID) )
{
return -1f;
}
return getResourceEfficiency( resourceId, loc );
}
float getVegetationSnagFactor(location loc)
{
if ( loc == null )
return -1f;
obj_id resourceId = pickRandomNonDepeletedResource("vegetable_greens");
if ( (resourceId == null) || (resourceId == obj_id.NULL_ID) )
{
return -1f;
}
return getResourceEfficiency( resourceId, loc );
}
void freeSnaggedLine(obj_id target)
{
if ( !isIdValid(target) )
return;
sendSystemMessage(target, SID_LINE_FREE);
setFishingState(target, FS_WAIT);
utils.removeScriptVar(target, SCRIPTVAR_BONUS);
}
void snapFishingLine(obj_id target)
{
if ( !isIdValid(target) )
return;
sendSystemMessage(target, SID_LINE_SNAP);
decrementBait(target);
stopFishing(target);
}
void spoolFishingLine(obj_id target)
{
if ( !isIdValid(target) )
return;
sendSystemMessage(target, SID_LINE_SPOOLED);
decrementBait(target);
stopFishing(target);
}
void caughtLoot(obj_id target)
{
if ( !isIdValid(target) )
return;
setFishingState(target, FS_LOOT);
utils.removeScriptVar(target, SCRIPTVAR_BONUS);
}
void lostBait(obj_id target)
{
if ( !isIdValid(target) )
return;
if ( !isFishing(target) )
return;
decrementBait(target);
sendSystemMessage(target, SID_LOST_BAIT);
stopFishing(target);
}
void decrementBait(obj_id target)
{
if ( !isIdValid(target) )
return;
if ( !isFishing(target) )
return;
obj_id pole = utils.getObjIdScriptVar(target, SCRIPTVAR_POLE);
if ( !isIdValid(pole) )
return;
if ( !isFishingPole(pole) )
return;
obj_id bait = getBait(pole);
if ( !isIdValid(bait) )
return;
if ( !hasObjVar(bait, VAR_FISHING_BAIT_STATUS) )
return;
int baitStatus = getIntObjVar(bait, VAR_FISHING_BAIT_STATUS);
if ( baitStatus != BS_NONE )
{
setObjVar(bait, VAR_FISHING_BAIT_STATUS, BS_NONE);
incrementCount(bait, -1);
if ( getCount(bait) < 1 )
{
sendSystemMessage(target, new string_id(STF_FISH, "out_of_bait")); // You have run out of bait in your tackle...
destroyObject(bait);
}
}
}
int[] getGoodActions()
{
int numActions = rand(1, 2);
int[] ret = new int[numActions];
for ( int i = 0; i < numActions; i++ )
{
ret[i] = rand(FA_TUG_UP, FA_TUG_LEFT);
}
return ret;
}
void confirmReelIn(obj_id target, location castLoc)
{
if ( !isIdValid(target) || (castLoc == null) )
return;
if ( !isFishing(target) )
return;
int status = utils.getIntScriptVar(target, SCRIPTVAR_STATUS);
if ( status != FS_CAUGHT && status != FS_LOOT )
return;
int base_chance = 40;
float bonus = utils.getFloatScriptVar(target, SCRIPTVAR_BONUS);
int chance = base_chance + (int)(bonus*100);
boolean lostCatch = false;
int roll = rand(0,100);
if(isGod(target))
{
roll = 1;
debugSpeakMsg(target, "Bypassing -minigame.loseCatch- due to God Mode!");
}
if ( roll > 98 ) //standard % lose catch chance
{
lostCatch = true;
}
if ( lostCatch )
{
//lost catch!
loseCatch(target);
return;
}
else
{
//do caught something stuff here
sendSystemMessage(target, SID_REEL_IN);
float delay = rand(1.5f, 5f);
dictionary params = new dictionary();
params.put("castLoc", castLoc);
messageTo(target, HANDLER_REEL_IN, params, delay, false);
}
}
void loseCatch(obj_id target)
{
if ( !isIdValid(target) )
return;
sendSystemMessage(target, SID_LOST_CATCH);
lostBait(target);
}
void markerFlyText(obj_id target, string_id sid, color textColor)
{
if ( !isIdValid(target) )
return;
if ( sid == null )
return;
if ( textColor == null )
return;
obj_id marker = utils.getObjIdScriptVar(target, SCRIPTVAR_MARKER);
if ( !isIdValid(marker) )
return;
showFlyText(marker, sid, 1.0f, textColor);
}
float getPoleBonus(obj_id target)
{
if ( !isIdValid(target) )
return 0f;
obj_id pole = utils.getObjIdScriptVar(target, SCRIPTVAR_POLE);
if ( !isIdValid(pole) )
return 0f;
if ( !isFishingPole(pole) )
return 0f;
int useModifier = getIntObjVar(pole, "useModifier");
float bonus = useModifier/500f;
return bonus;
}
obj_id spawnFishingFish(obj_id target, location castLoc)
{
LOG("fishingLog", "target = " + target);
if(!isIdValid(target) || castLoc == null)
return null;
obj_id inv = utils.getInventoryContainer(target);
if (!isIdValid(inv))
return null;
int volFree = getVolumeFree(inv);
if(volFree < 1)
{
sendSystemMessage(target, new string_id(STF_FISH, "inventory_full")); // Since your inventory is full, you toss the fish back...
return null;
}
//queueCommand(target, ##"kneel", null, "", COMMAND_PRIORITY_DEFAULT);
dictionary row = getFishData(target, castLoc);
if(row == null || row.isEmpty())
{
//debugSpeakMsg(target, "getFishData() returned null...");
createVegetation(target, inv, castLoc);
return null;
}
obj_id fish = obj_id.NULL_ID;
string fishName = row.getString("generic");
LOG("fishingLog", "fishName = " + fishName);
if(static_item.isStaticItem(fishName))
{
//debugSpeakMsg(target, "static item creation");
fish = static_item.createNewItemFunction(fishName, inv); // failed somehow
LOG("fishingLog", "Static Fish= " + fish);
}
else
{
// get template name from datatables/fishing/fish/fish_template.iff
dictionary templateRow = dataTableGetRow(TBL_TEMPLATE, fishName);
string templateFish = templateRow.getString("template");
LOG("fishingLog", "this is the templateFish - non-static -= "+templateFish);
//string template = row.getString(COL_TEMPLATE);
if(templateFish == null || templateFish.equals(""))
{
createVegetation(target, inv, castLoc);
return null;
}
fish = createObject(templateFish, inv, "");
LOG("fishingLog", "this is the fish created - "+ fish);
}
//string path = "object/tangible/fishing/fish/" + template; //
//obj_id fish = createObject(path, inv, "");
if(!isIdValid(fish))
{
//debugSpeakMsg(target, "unable to create fish from template: ");
sendSystemMessage(target, new string_id(STF_FISH, "size_matters")); // The fish was too small, so you toss it back...
return null;
}
row = dataTableGetRow(TBL_TEMPLATE, fishName);
if(row == null)
{
LOG("fishingLog", "row is null...wtf");
}
LOG("fishingLog", "datatable ROW - " + row);
setFishData(fish, row, target, castLoc);
// Award Wilderness Survival xp for this catch.
//int fish_xp = utils.getIntScriptVar( fish, "fish_xp" );
//xp.grant( target, xp.SCOUT, fish_xp, true );
//queueCommand(target, ##"stand", null, "", COMMAND_PRIORITY_DEFAULT);
return fish;
}
dictionary getFishData(obj_id target, location castLoc)
{
if ( !isIdValid(target) )
{
return null;
}
if ( castLoc == null )
{
return null;
}
int tableChance = rand(1,100); // roll for which table to loot from
string fishLootTable = "";
if(tableChance <= ROLL_FISH_OR_JUNK) // loot from fish table
{
string planetName = getCurrentSceneName();
fishLootTable = "datatables/fishing/fish/" + planetName + ".iff";
}
else // loot from generic table (fish tank parts and treasure maps)
{
fishLootTable = "datatables/fishing/loot/generic.iff";
}
string[] names = dataTableGetStringColumnNoDefaults(fishLootTable, "generic");
string name = "";
if ( names == null || names.length == 0 )
{
name = "fish_generic";
return null;
}
int idx = rand(0, names.length - 1);
name = names[idx];
if ( name == null || name.equals("") )
name = "fish_generic";
return dataTableGetRow(fishLootTable, name);
}
boolean setFishData(obj_id fish, dictionary params, obj_id player, location castLoc)
{
LOG("fishingLog", "static fish - after passing to SetFishData - " + fish);
LOG("fishingLog", "params? - " + params);
if ( !isIdValid(fish) || !isIdValid(player) )
return false;
if ( params == null || params.isEmpty() )
return false;
if ( castLoc == null )
castLoc = getLocation(player);
string name = params.getString(COL_NAME);
if ( name == null || name.equals("") )
return false;
string_id sid_name = new string_id("fish_n",name);
if ( getString(sid_name) != null )
setName(fish, sid_name);
int timeCaught = getCalendarTime();
if(timeCaught > 0)
{
setObjVar(fish, VAR_FISH_TIME_STAMP, timeCaught);
}
string playerName = getPlayerFullName(player);
if(playerName != null || playerName != "")
{
setObjVar(fish, VAR_FISH_CATCHER, playerName);
}
setObjVar(fish, VAR_FISH_NAME, name);
setObjVar(fish, VAR_FISH_LOCATION, castLoc);
setObjVar(fish, VAR_FISH_STAMP, getGameTime());
float lengthMin = params.getFloat(COL_LENGTH_MIN);
float lengthNorm = params.getFloat(COL_LENGTH_NORM);
float absoluteLengthMax = params.getFloat(COL_LENGTH_MAX);
float dLength = lengthNorm - lengthMin;
float lengthMax = lengthNorm + dLength;
float length = rand(lengthMin, lengthMax);
float lengthPercentile = 1.0f;
if ( lengthMin != lengthMax )
{
lengthPercentile = (length - lengthMin)/(lengthMax - lengthMin);
if ( lengthPercentile > 0.95f )
{
float dPercentile = 0f;
do
{
float toAdd = rand(0f, dLength);
length += toAdd;
dPercentile = toAdd/dLength;
} while ( dPercentile > 0.95f && length < absoluteLengthMax );
}
}
if ( length > absoluteLengthMax )
length = absoluteLengthMax;
setObjVar(fish, VAR_FISH_LENGTH, length);
// Assign an xp value based on the fish length.
int xp = (int) (90.f * (length / lengthNorm));
utils.setScriptVar( fish, "fish_xp", xp );
int resourceMin = params.getInt(COL_RESOURCE_MIN);
int resourceNorm = params.getInt(COL_RESOURCE_NORM);
int absoluteResourceMax = params.getInt(COL_RESOURCE_MAX);
int dResource = resourceNorm - resourceMin;
int resourceMax = resourceNorm + dResource;
int resourceAmt = rand(resourceMin, resourceMax);
float resourcePercentile = 1.0f;
if ( resourceMin != resourceMax )
{
resourcePercentile = (resourceAmt - resourceMin)/(resourceMax - resourceMin);
if ( resourcePercentile > 0.95f )
{
float dPercentile = 0f;
do
{
int toAdd = rand(0, dResource);
resourceAmt += toAdd;
dPercentile = toAdd/dResource;
} while ( dPercentile > 0.95f && resourceAmt < absoluteResourceMax );
}
}
if ( resourceAmt > absoluteResourceMax )
resourceAmt = absoluteResourceMax;
if ( resourceAmt > 0 )
{
string resourceType = params.getString(COL_RESOURCE_TYPE);
if ( resourceType != null && !resourceType.equals("") )
{
resource.createRandom(resourceType, resourceAmt, castLoc, fish, player, 1);
}
}
int chumNorm = params.getInt(COL_CHUM_NORM);
int chumAmt = chumNorm;
if ( resourceMax != resourceMin)
{
float percentile = (resourceAmt - resourceMin)/(resourceMax - resourceMin);
chumAmt = chumNorm + (int)rand(-percentile, percentile);
}
if ( chumAmt > 0 )
{
obj_id chum = createObject("object/tangible/fishing/bait/bait_chum.iff", fish, "");
if ( isIdValid(chum) )
setCount(chum, chumAmt);
}
int hue1 = params.getInt(COL_HUE1);
if ( hue1 > -1 )
hue.setColor(fish, 1, hue1);
int hue2 = params.getInt(COL_HUE2);
if ( hue2 > -1 )
hue.setColor(fish, 2, hue2);
return true;
}
boolean filetFish(obj_id target, obj_id fish)
{
if ( !isIdValid(target) || !isIdValid(fish) )
return false;
obj_id[] contents = getContents(fish);
if ( contents == null || contents.length == 0 )
{
sendSystemMessage(target, new string_id(STF_FISH, "already_fileted")); // But this fish has already been fileted.
return false;
}
obj_id inv = utils.getInventoryContainer(target);
if ( !isIdValid(inv) )
return false;
int volFree = getVolumeFree(inv);
if ( volFree < contents.length )
{
sendSystemMessageProse(target, prose.getPackage(new string_id (STF_FISH, "units_inventory"), contents.length)); // You require %DI units of available space in your inventory to filet this fish.
return false;
}
int cec = moveContents(fish, inv);
if ( cec == CEC_SUCCESS || cec == CEC_ADD_SELF )
sendSystemMessage(target, new string_id(STF_FISH, "good_filet")); // You successfully filet the fish.
else
{
//debugSpeakMsg(target, "CEC = " + cec);
sendSystemMessage(target, new string_id(STF_FISH, "no_resource")); // There was no salvagable resource to harvest.
}
return trophyFish(target, fish);
}
boolean trophyFish(obj_id target, obj_id fish)
{
if ( !isIdValid(target) || !isIdValid(fish) )
return false;
//sendSystemMessageTestingOnly(target, "Make Trophy functionality not implemented... yet!");
return true;
}
void createVegetation(obj_id target, obj_id inv, location castLoc)
{
if ( !isIdValid(target) || !isIdValid(inv) || castLoc == null )
return;
sendSystemMessage(target, new string_id(STF_FISH, "shucks_veggies")); // Shucks... It was really just a handful of vegetation.
resource.createRandom("vegetable_greens", 2, castLoc, inv, target, 1);
}
obj_id[] spawnFishingLoot(obj_id target, location castLoc)
{
if ( !isIdValid(target) || castLoc == null )
return null;
obj_id inv = utils.getInventoryContainer(target);
if ( !isIdValid(inv) )
return null;
int volFree = getVolumeFree(inv);
if ( volFree < 1 )
{
sendSystemMessage(target, new string_id(STF_FISH, "toss_trash")); // Since your inventory is full, you toss the trash back in the water...
return null;
}
int lvl = rand(1,10);
while ( lvl % 10 == 0 )
{
lvl += rand(1,10);
}
return null;
}