# Terry Fisherman's Friend 1.5.3 # Terry Donahugh (terrydonahugh@gmail.com) # Selling this software (verbatim or modified) is NOT allowed # Distributing modified versions of this software is NOT allowed # No warranties of any kind! # Copyright holders will bear no liability for any use of this software import gaiaonline import getpass import random import time import md5 import sys def selectFish(tod, rareEnabled, level, human): rareFish = None if tod == "night": rareFish = 8 elif tod == "day": rareFish = 4 elif tod in ["sunset", "twilight"]: rareFish = 9 large = [10,11,14] medium = [2,3,13] small = [0,1,12] trash = [5,6,7] rare = [rareFish] fish = [trash, small, medium, large, rare] x = 0 if rareEnabled: x = 1 toFish = [] fishCount = [ [0, 0, 9-x, 9, x], [0, 4-x, 11, 3, x], [0, 11-x, 6, 1, x] ] fishMax = [ [18, 54, 18, 9, x], [32, 54, 11, 3, x], [51, 42, 6, 1, x] ] # select maximum possible if not human: counts = fishCount[level] print counts for class_, count in enumerate(counts): for i in xrange(count): toFish.append(random.choice(fish[class_])) # a human like fishing thingo if human: print "using human mode" totalFish = 0 maximums = fishMax[level][:] while len(toFish) != 18: class_ = random.randint(0,4) if maximums[class_] != 0: toFish.append( random.choice( fish[class_] )) maximums[class_] -= 1 print "tofish:", toFish return toFish class Fisher(gaiaonline.GameClient): def __init__(self, session, gameSession, networkThread, level = "durem"): gaiaonline.GameClient.__init__(self, gameSession, networkThread) self.session = session self.roomMethod = "fishinggame" self.level = "durem" self.gameName = "gaiafishing003" self.logonSession = "5" # this is the 4.10 key self.gameMD5 = "fdb92f1dc388cd886f8e5e5e7c78fb79" self.baitString = "baitf" self.fishGameReady = False self.initFishNames() self.timeOfDayStrings = ["day", "sunset", "night", "twilight"] self.avatarString = "http://avatar2.gaiaonline.com/gaia/members/" + self.gameSession.getAvatar() + ".swf" self.round = 0 self.human = False def displayProgress(self): if self.printFunc == sys.stdout.write: sys.stdout.write("\r[ ") for i in self.status: sys.stdout.write(i) sys.stdout.write(" ] ") sys.stdout.write("%i/18" % (self.fishIdx+1)) sys.stdout.flush() else: fishName = self.fishNames[self.toFish[self.fishIdx]] self._print("Round %i: [%i/18] %s %s" % (self.round, self.fishIdx+1, self.baitDisplay, fishName)) def startFishing(self): #print "starting fishing" self.fishGameReady = False self.round+=1 print "Round", self.round self.lastFish = "0" self.fishIdx = 0 self.myFish = [0, 0 , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] self.callPlugin("G_FISH_PLUGIN", ["501", self.gameMD5, self.gameSession.getSessionID()], self.selectBait) self.status = ["."] * 18 def selectBait(self, msg): sushi = msg.decoded[0][3] if sushi[1] != chr(0x05): self.emergency("Could not fetch bait/rod information.") return baitTypes = sushi[2].split("|") baitTypes = [ x.split(":") for x in baitTypes ] self.baitTypes = baitTypes rodTypes = [] try: rodTypes = sushi[3].split("|") except: print "you don't have a rod" self.quit() return timeOfDay = sushi[4] self.styleSheetID = int(sushi[5]) bait = None count = None try: bait, count = random.choice(baitTypes) except: self.emergency("Out of bait!", self.Fatal) return baitStrings = { "100001" : "baitf", "100002" : "baitd", "100003" : "baita" } #print baitTypes #print bait self.baitString = baitStrings[bait] print "Using bait:", self.baitString[-1]+".", self.baitDisplay = "" print "Bait left:", for idx, b in enumerate(baitTypes): self.baitDisplay+="["+baitStrings[b[0]][-1]+":"+b[1]+"]" print "["+baitStrings[b[0]][-1]+":"+b[1]+"]", print self.bait = bait self.callPlugin("G_FISH_PLUGIN", ["500", self.bait, # bait type "0", # save flag self.gameSession.getSessionID()], self.getFishInfo) def getFishInfo(self, message): sushi = message.decoded[0][3] sushiCommand = sushi[0] sushiStatus = sushi[1] if sushiCommand == "E": self.emergency("Server side error, try again.") #print "server side error :(" elif sushiStatus == chr(0x06): #print "saved game in progress" self.callPlugin("G_FISH_PLUGIN", ["500", self.bait, # bait type "1", # save flag self.gameSession.getSessionID()], self.getFishInfo) elif sushiStatus == chr(0x05): #print "got fish info" self.fishSID1 = sushi[2] self.fishSID2 = sushi[3] self.timeOfDay = sushi[4] self.timeOfDayString = self.timeOfDayStrings[int(self.timeOfDay)] level = 2 keyMap = { "0bec1093f7a3de5a1fb0481a90c72387" : (0, False), "8537b11bae00996495118be7a6cb899d" : (0, True), "2d4c488e581879c8bfc0664c35cb2ccc" : (1, False), "af9d30069c67e56b93c621d4ccb611c4" : (1, True), "c90b2f8da134c0889936adec6466d290" : (2, False) } level, rare = keyMap[self.fishSID1] print "self.human", self.human self.toFish = selectFish(self.timeOfDayString, rare, level, self.human) assert(len(self.toFish) == 18) # shuffle the fishies random.shuffle(self.toFish) self.fishGameReady = True def calculateSecurityNumber(self, saveMsg): styleSheetID = int(self.styleSheetID) userID = int(self.gameSession.getUserID()) number = 0 if styleSheetID != 0: number = userID % styleSheetID number += int(self.clientID) idx = 1 while idx < len(saveMsg): token = str(saveMsg[idx]) number += len(token) number += token.find("1") number += token.find("2") number += token.find("4") number += token.find("5") idx += 1 return number def saveGame(self): print m = md5.new() userID = str(self.gameSession.getUserID()) m.update(self.fishSID1 + userID + self.fishSID2) sum1 = m.hexdigest() fishIDs = self.fishIDs myFish = self.myFish fishStr= "" fishCheckStr = "" for fishID, count in enumerate(myFish): if count > 0: fishCheckStr+=str(fishIDs[fishID])+str(count) fishStr+=str(fishIDs[fishID])+":"+str(count)+"|" m = md5.new() m.update(fishCheckStr+self.fishSID2) sum2 = m.hexdigest() saveData = ["510", "2", fishStr, sum1, sum2, self.gameSession.getSessionID()] sn = self.calculateSecurityNumber(saveData) print "security number", sn self.callPlugin("G_FISH_PLUGIN", ["510", "2", fishStr, sum1, sum2, self.gameSession.getSessionID(), sn], self.getSaveInfo) self.fishing = False self.saveDone = False def getSaveInfo(self, msg): sushi = msg.decoded[0][3] #print sushi if sushi[1] == chr(0x05): print "Game saved succesfully" elif sushi[1] == chr(0x06): print "debug:", msg.decoded if sushi[2] == -4: self.emergency("Session expired.") else: print "Game save failed!" print "debug:", msg.decoded self.emergency("Game save failed.") self.saveDone = True def initFishNames(self): if self.level == "durem": self.fishNames = ["White Pebbo Feeder", #0 "Brown Pebbo Feeder", #1 "Blue Stone Biter", #2 "Black Rocque Biter", #3 "Diamondback king", #4 "Can", #5 "Boot",#6 "Tire", #7 "Emeralback Lion", #8 "Rubyback Lion", #9 "Stone Boldur", #10 "Sand Boldur", #11 "Black Pebbo Feeder", #12 "Pyrite Biter", # 13 "Slate Boldur", # 14 "!! ERROR !!"] #white brown blue black diamond can boot tire emerald rubyback stone sand black pyrite slate #pebbo pebbo stone rocque back back lion boldur boldur pebbo biter boldur #feeder feeder biter biter king lion feeder self.fishIDs = [100014, 100015, 100016, 100017, 100018, 100021, 100020, 100019, 100033, 100032, 100026, 100027, 100038, 100039, 100042, 0] def playStep(self): StartGame, WaitForGame, Sync, WaitForSync, Hook, WaitAfterHook, Sync2, WaitForSync2, WaitForFish, Fish, Restart = range(11) if self.playStage == StartGame: self.startFishing() self.playStage = WaitForGame elif self.playStage == WaitForGame: if self.fishGameReady: self.playStage = Sync elif self.playStage == Sync: if time.time() - self.syncTime > 30.0: self.sync() self.playStage = WaitForSync else: self.playStage = Hook elif self.playStage == WaitForSync: if not self.syncReady: if time.time() - self.syncTime > 10.0: self.emergency("Sync signal timed out. This happens often when the server is very busy.") self.playStage = Hook elif self.syncReady: self.playStage = Hook elif self.playStage == Hook: self.hook() self.displayProgress() self.hookTime = time.time() self.hookWait = random.random()*2.0 + 4.0 self.playStage = WaitAfterHook elif self.playStage == WaitAfterHook: if time.time() - self.hookTime > self.hookWait: self.playStage = WaitForFish elif self.playStage == WaitForFish: self.gotone(self.toFish[self.fishIdx]) self.displayProgress() self.fishIdx+=1 if self.fishIdx == 18: self.saveGame() self.playStage = Restart else: self.playStage = Fish self.catchTime = time.time() self.catchWait = random.random()*4.0 + 2.0 elif self.playStage == Fish: if time.time() - self.catchTime > self.catchWait: self.playStage = Sync elif self.playStage == Restart: if self.saveDone: self.playStage = StartGame def hook(self): self.status[self.fishIdx]="!" self.sendSushi([["6", self.clientID, self.avatarString, "1", "0", "126.5", "112.4","1",self.baitString,"hooked",self.lastFish,"0"]],False) def escape(self): self.stats[self.fishIx]="X" self.sendSushi([["6", self.clientID, self.avatarString, # avatar url "1", # player number "0", # update type "126.5", # map x "112.4", # map y "1", # rod type self.baitString, # bait type "escape", # bubble type self.lastFish, # bubble fish "0" # ? ]],False) def gotone(self, fishID): self.myFish[int(fishID)]+=1 self.status[self.fishIdx]="=" fishID = str(int(fishID)+10) self.sendSushi([["6", self.clientID, self.avatarString, # avatar url "1", # player number "0", # update type "126.5", # map x "112.4", # map y "1", # rod type self.baitString, # bait type "gotone", # bubble type fishID, # bubble fish "0" # ? ]],False) self.lastFish = fishID if __name__ == "__main__": import sys username = "" password = "" product = "Terry's Fisherman's Friend" version = "1.5.3" email = "terrydonahugh@gmail.com" print product, version print email if len(sys.argv) != 3: print "usage", sys.argv[0], " " print sys.stdout.write("enter username: ") username = sys.stdin.readline().strip() if len(username) == 0: sys.exit(0) password = getpass.getpass("enter password: ") if len(password) == 0: sys.exit(0) else: username = sys.argv[1] password = sys.argv[2] session = gaiaonline.Session() session.logon(username, password) gameSession = gaiaonline.GameSession() gameSession.logon(username, password) while True: serverPool = [("72.5.72.56", "Demonic"), ("72.5.72.55", "Angelic"), ("72.5.72.102","Grunny")] #server = random.choice(serverPool) server = serverPool[0] print "Server:", server[1] networkThread = gaiaonline.GameNetworkThread(server[0]) networkThread.start() fisher = Fisher(session, gameSession, networkThread) quitStatus = fisher.run() if quitStatus == fisher.Fatal: print "Fatal Error! Halting" break if quitStatus == fisher.Restart: print "Restarting in 30 seconds" time.sleep(30) if quitStatus == fisher.QuitRequest: print "Quiting" break