/** * Copyright (C)2000-2002 Sony Online Entertainment Inc. * All Rights Reserved * * Title: utils.scriptlib * Description: A library containing public general utility functions. * @author $Author: rpalacio $ * @version $Revision: #13 $ */ /***** 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 = loc; 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; }