diff --git a/sku.0/sys.server/compiled/game/datatables/buildout/tatooine/tatooine_6_2.tab b/sku.0/sys.server/compiled/game/datatables/buildout/tatooine/tatooine_6_2.tab index 52271e14b..cea5b3b39 100755 --- a/sku.0/sys.server/compiled/game/datatables/buildout/tatooine/tatooine_6_2.tab +++ b/sku.0/sys.server/compiled/game/datatables/buildout/tatooine/tatooine_6_2.tab @@ -1325,4 +1325,4 @@ i i h i f f f f f f f s p 1187928 1187917 object/cell/cell.iff 11 0 0 0 1 0 0 0 $| 1187929 1187917 object/cell/cell.iff 12 0 0 0 1 0 0 0 $| -19844656 0 object/tangible/planet_map_location/city.iff 0 1570.98 5 1342.91 0.938444 0 0.345432 0 $| --990069 0 object/tangible/ground_spawning/patrol_waypoint.iff 0 1469.301 4 1334.822 1 0 0 0 fishing.master_object $| +-90069420 0 object/tangible/theme_park/invisible_object.iff 0 1475.19 5 1371.49 1 0 0 0 fishing.controller $| diff --git a/sku.0/sys.server/compiled/game/script/fishing/controller.java b/sku.0/sys.server/compiled/game/script/fishing/controller.java new file mode 100644 index 000000000..edd7e78a0 --- /dev/null +++ b/sku.0/sys.server/compiled/game/script/fishing/controller.java @@ -0,0 +1,64 @@ +package script.fishing; + +import script.dictionary; +import script.library.fishing; +import script.location; +import script.obj_id; + +public class controller extends script.base_script { + + public controller() + { + } + + /* + * The purpose of the controller is really only to spawn and setup the master object + * Everything fishing related that is stored or updated should be going in the master object via messageTo fishing.getMasterFishingObject() + */ + + public static final String CONTROLLER = "object/tangible/ground_spawning/patrol_waypoint.iff"; + + public int OnInitialize(obj_id self) throws InterruptedException { + setName(self, "Fishing Controller"); + location selfLoc = getLocation(self); + obj_id objects[] = getObjectsInRange(selfLoc, 0.1f); + boolean exists = false; + if (objects != null || objects.length > 0) + { + for (obj_id object : objects) { + if ((getTemplateName(object)).equals(CONTROLLER)) { + exists = true; + } + } + } + if (!exists) + { + createMasterObject(self); + } + return SCRIPT_CONTINUE; + } + + // Make sure CSRs can't take the master object on a stroll down Amidala's Beach when they should be home doing their homework + public int OnAboutToBeTransferred(obj_id self, obj_id destContainer, obj_id transferer) throws InterruptedException { + sendSystemMessageTestingOnly(transferer, "You cannot move this item!"); + return SCRIPT_OVERRIDE; + } + + public int createMasterObject(obj_id self, dictionary params) throws InterruptedException { + createMasterObject(self); + return SCRIPT_CONTINUE; + } + + /** + * createMasterObject + * Spawns the fishing master object and persists it to the database + * We need to persist this object because it contains records of fishing (e.g. leaderboard) + * and should not be deleted at restart (that would be very bad) + */ + public void createMasterObject(obj_id self) throws InterruptedException { + obj_id object = createObject(CONTROLLER, getLocation(self)); + attachScript(object, "fishing.master_object"); + persistObject(object); + } + +} diff --git a/sku.0/sys.server/compiled/game/script/fishing/master_object.java b/sku.0/sys.server/compiled/game/script/fishing/master_object.java index c8da38155..34cad52f1 100644 --- a/sku.0/sys.server/compiled/game/script/fishing/master_object.java +++ b/sku.0/sys.server/compiled/game/script/fishing/master_object.java @@ -13,41 +13,92 @@ public class master_object extends script.base_script { public static final String OBJVAR_LEADERBOARD_UPDATE_TIME = "leaderboards_last_updated"; public static final String OBJVAR_CONTROLLER_SETUP_TIME = "master_fishing_object_created"; - public int OnInitialize(obj_id self) throws InterruptedException { - if(!hasObjVar(self, OBJVAR_CONTROLLER_SETUP_TIME)) { - messageTo(self, "handleSetupMasterFishingObject", null, 3, true); - } - setName(self, "Master Fishing Object [do not move]"); + public int OnAttach(obj_id self) throws InterruptedException { + messageTo(self, "handleControllerInitialization", null, 120f, true); + return SCRIPT_CONTINUE; + } + public int OnInitialize(obj_id self) throws InterruptedException { + messageTo(self, "handleControllerInitialization", null, 120f, true); + return SCRIPT_CONTINUE; + } + + // Make sure CSRs can't take the master object on a stroll down Amidala's Beach when they should be home doing their homework + public int OnAboutToBeTransferred(obj_id self, obj_id destContainer, obj_id transferer) throws InterruptedException { + sendSystemMessageTestingOnly(transferer, "You cannot move this item!"); + return SCRIPT_OVERRIDE; + } + + /** + * handleControllerInitialization + * Handles the setup of the controller and triggers updates to critical functions + */ + public int handleControllerInitialization(obj_id self, dictionary params) throws InterruptedException { + + setName(self, "Master Fishing Object"); + if(!hasObjVar(self, OBJVAR_CONTROLLER_SETUP_TIME)) { + messageTo(self, "handleSetupMasterFishingObject", null, 20f, true); + } // Update the leader board weekly, and force update if 7-days have passed since last update (in case of offline fails to trigger update) createWeeklyAlarmClock(self, "handleUpdateLeaderboards", null, DAY_OF_WEEK_THU, 19, 0,0); if (!hasObjVar(self, OBJVAR_LEADERBOARD_UPDATE_TIME)) { - messageTo(self, "handleUpdateLeaderboards", null, 120, false); + messageTo(self, "handleWeeklyUpdateLeaderboards", null, 20f, true); } if(getCalendarTime() > getIntObjVar(self, OBJVAR_LEADERBOARD_UPDATE_TIME) + 604800) { - messageTo(self, "handleUpdateLeaderboards", null, 120, false); + messageTo(self, "handleWeeklyUpdateLeaderboards", null, 20f, true); } return SCRIPT_CONTINUE; } + /** + * handleSetupMasterFishingObject + * Handles all required setup for the Fishing Object, intended to only be called on a fresh server once + */ public int handleSetupMasterFishingObject(obj_id self, dictionary params) throws InterruptedException { - if(!hasObjVar(self, OBJVAR_CONTROLLER_SETUP_TIME)) { - if (isIdValid(self)) { - setObjVar(getPlanetByName("tatooine"), "master_fishing_object", self); - setObjVar(self, OBJVAR_CONTROLLER_SETUP_TIME, getCalendarTime()); - fishing.handleConstructElusiveFishTable(self); - LOG("fishing", "Created Master Fishing Object ("+ self +") and attached to Tatooine Planet Object."); - } else { - LOG("fishing", "[ERROR FEATURE-FATAL]: Attempted to create Master Fishing Object but it failed."); - } + setObjVar(getPlanetByName("tatooine"), fishing.OBJVAR_PLANET_OBJECT_REFERENCE, self); + setObjVar(self, OBJVAR_CONTROLLER_SETUP_TIME, getCalendarTime()); + String[] elusiveFishTable = dataTableGetStringColumn(fishing.ELUSIVE_FISH_TABLE, "fish"); + for (String fish : elusiveFishTable) { + setObjVar(self, fishing.OBJVAR_ELUSIVE_FISH_COUNT_TABLE_TREE+fish, 0); + } + setObjVar(self, fishing.OBJVAR_ELUSIVE_FISH_COUNT_TOTAL, 0); + setObjVar(self, fishing.OBJVAR_ELUSIVE_FISH_COUNT_TABLE_MADE, 1); + LOG("fishing", "Created Master Fishing Object ("+ self +") and completed setupMasterFishingObject."); + return SCRIPT_CONTINUE; + } + + /** + * handleUpdateElusiveFishLeaderboard + * Adds an array of information to the elusive fish leaderboard as passed in fishing.giveElusiveFishRewards + */ + public int handleUpdateElusiveFishLeaderboard(obj_id self, dictionary params) throws InterruptedException { + String[] fishInfo = params.getStringArray("elusiveFishLeaderboardItems"); + String fishType = params.getString("fishType"); + // update total elusive fish caught count + setObjVar(self, fishing.OBJVAR_ELUSIVE_FISH_COUNT_TOTAL, getIntObjVar(self, fishing.OBJVAR_ELUSIVE_FISH_COUNT_TOTAL)+1); + // update specific elusive fish caught count + setObjVar(self, fishing.OBJVAR_ELUSIVE_FISH_COUNT_TABLE_TREE+fishType, getIntObjVar(self, fishing.OBJVAR_ELUSIVE_FISH_COUNT_TABLE_TREE+fishType)+1); + // add leaderboard entry + if(!hasObjVar(self, fishing.OBJVAR_ELUSIVE_FISH_LEADERBOARD_COUNT_TOTAL)) { + setObjVar(self, fishing.OBJVAR_ELUSIVE_FISH_LEADERBOARD_COUNT_TOTAL, 1); + setObjVar(self, fishing.OBJVAR_ELUSIVE_FISH_LEADERBOARD_TREE+"0", fishInfo); + } else { + int leaderboardEntries = getIntObjVar(self, fishing.OBJVAR_ELUSIVE_FISH_LEADERBOARD_COUNT_TOTAL); + setObjVar(self, fishing.OBJVAR_ELUSIVE_FISH_LEADERBOARD_TREE+leaderboardEntries, fishInfo); + setObjVar(self, fishing.OBJVAR_ELUSIVE_FISH_LEADERBOARD_COUNT_TOTAL, ++leaderboardEntries); } return SCRIPT_CONTINUE; } - public int handleUpdateLeaderboards(obj_id self, dictionary params) throws InterruptedException { + /** + * handleWeeklyUpdateLeaderboards + * Called when it is time to update all of the fishing leaderboards (does not include elusive fish as that is lifetime per galaxy) + */ + public int handleWeeklyUpdateLeaderboards(obj_id self, dictionary params) throws InterruptedException { // placeholder for weekly updated leaderboards setObjVar(self, OBJVAR_LEADERBOARD_UPDATE_TIME, getCalendarTime()); return SCRIPT_CONTINUE; } + } diff --git a/sku.0/sys.server/compiled/game/script/fishing/pole.java b/sku.0/sys.server/compiled/game/script/fishing/pole.java index 18e9d903a..1af1a88f4 100755 --- a/sku.0/sys.server/compiled/game/script/fishing/pole.java +++ b/sku.0/sys.server/compiled/game/script/fishing/pole.java @@ -81,7 +81,7 @@ public class pole extends script.base_script } if(item == menu_info_types.SERVER_MENU30) { if(fishing.getElusiveFishRewardedCount() > 0) { - fishing.showElusiveFishLeaderboard(player, null); + fishing.showElusiveFishLeaderboard(player); } else { sendSystemMessageTestingOnly(player, "No ELUSIVE Fish have been captured yet so the Leaderboard is empty."); } diff --git a/sku.0/sys.server/compiled/game/script/library/fishing.java b/sku.0/sys.server/compiled/game/script/library/fishing.java index 00de7836e..a2f2925e5 100644 --- a/sku.0/sys.server/compiled/game/script/library/fishing.java +++ b/sku.0/sys.server/compiled/game/script/library/fishing.java @@ -27,22 +27,23 @@ public class fishing extends script.base_script { public static final int ELUSIVE_FISH_MAX_GALAXY = 70; public static final double ELUSIVE_FISH_CHANCE = 0.005d; // 1% chance default public static final String ELUSIVE_FISH_TABLE = "datatables/fishing/fish/elusive_fish.iff"; - public static final obj_id FISHING_OBJECT = getObjIdObjVar(getPlanetByName("tatooine"), "master_fishing_object"); public static final String OBJVAR_ELUSIVE_FISH_PLAYER_CAUGHT_COUNT = "fishing.elusive_fish_caught"; // count also used for guild/city travel point perk public static final String OBJVAR_ELUSIVE_FISH_LEADERBOARD_COUNT_TOTAL = "elusive_fish.leaderboard_total"; public static final String OBJVAR_ELUSIVE_FISH_LEADERBOARD_TREE = "elusive_fish.leaderboard.e_"; public static final String OBJVAR_ELUSIVE_FISH_COUNT_TABLE_TREE = "elusive_fish.count_table.fish_"; public static final String OBJVAR_ELUSIVE_FISH_COUNT_TABLE_MADE = "elusive_fish.count_table_made"; public static final String OBJVAR_ELUSIVE_FISH_COUNT_TOTAL= "elusive_fish.count_rewarded_total"; + public static final String OBJVAR_PLANET_OBJECT_REFERENCE = "master_fishing_object"; /** * getMasterFishingObject * The Master Fishing Object is an invisible ghost object which exists in the world to store information about fishing records and data (as ObjVars). - * It is in the tatooine_5_5 buildout and initialized via fishing.master_object script + * A controller in tatooine_5_5 buildout uses fishing.controller script to handle MFO creation. + * The controller spawns the master object if it doesn't exist OnInitialize, attaches fishing.master_object, and persists to the world * @return The obj_id of the master fishing object */ public static obj_id getMasterFishingObject() throws InterruptedException { - return getObjIdObjVar(getPlanetByName("tatooine"), "master_fishing_object"); + return getObjIdObjVar(getPlanetByName("tatooine"), OBJVAR_PLANET_OBJECT_REFERENCE); } /** @@ -171,18 +172,18 @@ public class fishing extends script.base_script { */ public static boolean hasElusiveFishBeenCollected(obj_id fish) throws InterruptedException { String fishType = getStringObjVar(fish, "fish.name"); - return getIntObjVar(FISHING_OBJECT, OBJVAR_ELUSIVE_FISH_COUNT_TABLE_TREE+fishType) >= 1; + return getIntObjVar(getMasterFishingObject(), OBJVAR_ELUSIVE_FISH_COUNT_TABLE_TREE+fishType) >= 1; } /** - * isWinningElusiveFish - To be initiated by fishing process when player catches a fish + * handleElusiveFishRollAndWin - To be initiated by fishing process when player catches a fish * This is triggered at the point of the fish actually being caught and transferred to the player, then the system rolls to * decide if it should make this an elusive fish. * @param player the player fishing * @param fish the fish the player caught */ public static void handleElusiveFishRollAndWin(obj_id player, obj_id fish) throws InterruptedException { - if(!isIdValid(FISHING_OBJECT)) { + if(!isIdValid(player) || !isIdValid(fish)) { return; } if(!utils.checkConfigFlag("Fishing", "elusiveFishEnabled")) { @@ -213,21 +214,19 @@ public class fishing extends script.base_script { */ public static void giveElusiveFishRewards(obj_id player, obj_id fish) throws InterruptedException { + obj_id masterFishingObject = getMasterFishingObject(); + dictionary d = new dictionary(); String fishType = getStringObjVar(fish, "fish.name"); if(!badge.hasBadge(player, "bdg_fishing_elusive_fish_"+fishType)) { badge.grantBadge(player, "bdg_fishing_elusive_fish_"+fishType); } // make the fish elusive attachScript(fish, "fishing.elusive_fish"); - // count this specific fish as caught - setObjVar(FISHING_OBJECT, OBJVAR_ELUSIVE_FISH_COUNT_TABLE_TREE+fishType, getIntObjVar(FISHING_OBJECT, OBJVAR_ELUSIVE_FISH_COUNT_TABLE_TREE+fishType)+1); - // count the overall number of elusive fish caught - setObjVar(FISHING_OBJECT, OBJVAR_ELUSIVE_FISH_COUNT_TOTAL, getIntObjVar(FISHING_OBJECT, OBJVAR_ELUSIVE_FISH_COUNT_TOTAL)+1); // update the player's personal count of caught elusive fish (this is also used for granting travel point perks) if(!hasObjVar(player, OBJVAR_ELUSIVE_FISH_PLAYER_CAUGHT_COUNT)) { setObjVar(player, OBJVAR_ELUSIVE_FISH_PLAYER_CAUGHT_COUNT, 1); } else { - setObjVar(player, OBJVAR_ELUSIVE_FISH_PLAYER_CAUGHT_COUNT, getIntObjVar(player, "elusive_fish_caught")+1); + setObjVar(player, OBJVAR_ELUSIVE_FISH_PLAYER_CAUGHT_COUNT, getIntObjVar(player, OBJVAR_ELUSIVE_FISH_PLAYER_CAUGHT_COUNT)+1); } // pack fish information and send to leaderboard, then log the catch String species = getFishSpecies(fish); @@ -240,12 +239,14 @@ public class fishing extends script.base_script { (int)getFishCaughtLocation(fish).x+", "+(int)getFishCaughtLocation(fish).z, getFishCaughtTimeReadable(fish), }; + d.put("fishType", fishType); + d.put("elusiveFishLeaderboardItems", elusiveFishLeaderboardItems); if(hasElusiveFishBeenCollected(fish)) { if (utils.checkConfigFlag("Fishing", "elusiveFishShowDuplicatesOnLeaderboard")) { - handleUpdateElusiveFishLeaderboard(elusiveFishLeaderboardItems); + messageTo(masterFishingObject, "handleUpdateElusiveFishLeaderboard", d, 6f, true); } } else { - handleUpdateElusiveFishLeaderboard(elusiveFishLeaderboardItems); + messageTo(masterFishingObject, "handleUpdateElusiveFishLeaderboard", d, 6f, true); } CustomerServiceLog("elusive_fish", getPlayerName(player)+" ("+player+") caught elusive fish "+fishType+" ("+fish+")"); } @@ -276,7 +277,7 @@ public class fishing extends script.base_script { * @return the number of elusive fish that have been caught on the cluster */ public static int getElusiveFishRewardedCount() throws InterruptedException { - return getIntObjVar(FISHING_OBJECT, OBJVAR_ELUSIVE_FISH_COUNT_TOTAL); + return getIntObjVar(getMasterFishingObject(), OBJVAR_ELUSIVE_FISH_COUNT_TOTAL); } /** @@ -285,23 +286,22 @@ public class fishing extends script.base_script { * @param fish the name of the elusive fish (reference elusive fish datatable) e.g. bluefish_dantooine */ public static int getCountOfSpecificElusiveFishRewarded(String fish) throws InterruptedException { - return getIntObjVar(FISHING_OBJECT, OBJVAR_ELUSIVE_FISH_COUNT_TABLE_TREE+fish); + return getIntObjVar(getMasterFishingObject(), OBJVAR_ELUSIVE_FISH_COUNT_TABLE_TREE+fish); } /** * showElusiveFishLeaderboard * Constructs and then shows the player a SUI Table containing the Elusive Fish Leaderboard * @param player the player who should get the SUI window - * @param params currently unused dictionary of params for future implementation */ - public static void showElusiveFishLeaderboard(obj_id player, dictionary params) throws InterruptedException { + public static void showElusiveFishLeaderboard(obj_id player) throws InterruptedException { int fishCount = getElusiveFishRewardedCount(); String prompt = "Showing all caught ELUSIVE Fish on the " + getClusterName() + " Galaxy as of " + getCalendarTimeStringGMT(getCalendarTime()) + "\n\n"; String[] columns = { "Type", "Planet", "Length", "Angler", "Location", "Time Caught" }; String[] columnTypes = { "text", "text", "text", "text", "text", "text" }; String[][] leaderboardData = new String[fishCount][columns.length]; for (int i = 0; i < fishCount; i++) { - String[] leaderboardEntry = getStringArrayObjVar(FISHING_OBJECT, OBJVAR_ELUSIVE_FISH_LEADERBOARD_TREE+i); + String[] leaderboardEntry = getStringArrayObjVar(getMasterFishingObject(), OBJVAR_ELUSIVE_FISH_LEADERBOARD_TREE+i); for (int a = 0; a < leaderboardEntry.length; a++) { leaderboardData[i][a] = leaderboardEntry[a]; } @@ -309,38 +309,6 @@ public class fishing extends script.base_script { sui.table(player, player, sui.OK_ONLY, "ELUSIVE Fish Leaderboard", "noHandler", prompt, columns, columnTypes, leaderboardData, true, true); } - /** - * handleUpdateElusiveFishLeaderboard - * Adds an array of information to the elusive fish leaderboard as passed in giveElusiveFishRewards - * @param fishInfo the packaged array of fish info to add to the leaderboard - */ - public static void handleUpdateElusiveFishLeaderboard(String[] fishInfo) throws InterruptedException { - if(!hasObjVar(FISHING_OBJECT, OBJVAR_ELUSIVE_FISH_LEADERBOARD_COUNT_TOTAL)) { - setObjVar(FISHING_OBJECT, OBJVAR_ELUSIVE_FISH_LEADERBOARD_COUNT_TOTAL, 1); - setObjVar(FISHING_OBJECT, OBJVAR_ELUSIVE_FISH_LEADERBOARD_TREE+"0", fishInfo); - } else { - int leaderboardEntries = getIntObjVar(FISHING_OBJECT, OBJVAR_ELUSIVE_FISH_LEADERBOARD_COUNT_TOTAL); - setObjVar(FISHING_OBJECT, OBJVAR_ELUSIVE_FISH_LEADERBOARD_TREE+leaderboardEntries, fishInfo); - setObjVar(FISHING_OBJECT, OBJVAR_ELUSIVE_FISH_LEADERBOARD_COUNT_TOTAL, ++leaderboardEntries); - } - } - - /** - * handleConstructElusiveFishTable - * This is used to setup the ObjVars for all elusive fish (as a part of master fish object creation) - */ - public static void handleConstructElusiveFishTable(obj_id masterObject) throws InterruptedException { - if(hasObjVar(masterObject, OBJVAR_ELUSIVE_FISH_COUNT_TABLE_MADE)) { - return; - } - String[] elusiveFishTable = dataTableGetStringColumn(ELUSIVE_FISH_TABLE, "fish"); - for (String fish : elusiveFishTable) { - setObjVar(masterObject, OBJVAR_ELUSIVE_FISH_COUNT_TABLE_TREE+fish, 0); - } - setObjVar(masterObject, OBJVAR_ELUSIVE_FISH_COUNT_TOTAL, 0); - setObjVar(masterObject, OBJVAR_ELUSIVE_FISH_COUNT_TABLE_MADE, 1); - } - /** * getElusiveFishCountTableTree * Returns a dictionary containing the counts of each elusive fish capture @@ -354,23 +322,4 @@ public class fishing extends script.base_script { return d; } - /** - * clearElusiveFishLeaderboardAndTableDebugTestingOnly (for debug use only) - * Resets the Elusive Fish table and leaderboard as though you're on a brand new server - */ - public static void clearElusiveFishLeaderboardAndTableDebugTestingOnly() throws InterruptedException { - String[] elusiveFishTable = dataTableGetStringColumn(ELUSIVE_FISH_TABLE, "fish"); - for (String fish : elusiveFishTable) { - setObjVar(FISHING_OBJECT, OBJVAR_ELUSIVE_FISH_COUNT_TABLE_TREE+fish, 0); - } - setObjVar(FISHING_OBJECT, OBJVAR_ELUSIVE_FISH_COUNT_TOTAL, 0); - setObjVar(FISHING_OBJECT, OBJVAR_ELUSIVE_FISH_COUNT_TABLE_MADE, 1); - int leaderboardEntries = getIntObjVar(FISHING_OBJECT, OBJVAR_ELUSIVE_FISH_LEADERBOARD_COUNT_TOTAL); - for (int i = 0; i <= leaderboardEntries; i++) { - removeObjVar(FISHING_OBJECT, OBJVAR_ELUSIVE_FISH_LEADERBOARD_TREE+i); - } - removeObjVar(FISHING_OBJECT, OBJVAR_ELUSIVE_FISH_LEADERBOARD_COUNT_TOTAL); - } - - }