#!/usr/bin/env python from evennia import ( Command, CmdSet, TICKER_HANDLER, syscmdkeys, create_script, ) from evennia.prototypes.spawner import spawn from enum import Enum from urllib.request import urlopen from typeclasses.objects import Object from typeclasses.characters import Character from typeclasses.npcs import CarriableNPC from utils.scoring import Scores from utils.word_list import routput import random import requests class Fishing(Enum): "The acceptable states of fishing." CAST = True REEL = False class CmdThrowFish(Command): """ Throw the fish, if you are holding one, back in the water. A helper can escort the fish to the nearest body of water if you aren't adjacent to one. """ key = "throw" locks = "holds(fish)" def func(self): self.obj.do_delete(self.caller) class CmdSetFish(CmdSet): def at_cmdset_creation(self): self.add(CmdThrowFish) class CmdCast(Command): """ Cast the pole. """ key = "cast" locks = "holds(pole)" def func(self): self.obj.do_cast(self.caller) class CmdReel(Command): """ Reel the pole. """ key = "reel" locks = "holds(pole)" def func(self): self.obj.do_reel(self.caller) class CmdSetFishing(CmdSet): def at_cmdset_creation(self): self.add(CmdCast) self.add(CmdReel) class Fish(CarriableNPC): """ Everyone wants a fish that tells dad jokes, right!? """ # The number of seconds to check for the time for a message: fish_tick = 3 def at_object_creation(self): self.cmdset.add_default(CmdSetFish) self.db.name = Fish.get_name() self.db.spoken = 0 TICKER_HANDLER.add(interval=self.fish_tick, callback=self.do_speak) def at_heard_say(self, message, from_obj): """ A simple listener and response. This makes it easy to change for subclasses of NPCs reacting differently to says. """ return "say", "What was that? I must have water in my ear." def at_say(self, message): """ Spoken out loud to the world, even if owned. """ owner = self.location if owner.is_typeclass(Character) and owner.is_connected: self.location.announce_action(f"$Your() fish says, \"{message}\"") def do_speak(self): """ Called at a repeatable sequence by the ticker, and it calls at_say() in order to do a type of monologue. """ if self.db.spoken == 1: self.at_say("Whew! Thanks for removing the sharp hook. Not sure how I got stuck on that.") elif self.db.spoken == 5: self.at_say(f"My name's {self.db.name}. What's yours?") self.db.desc = f"{self.db.name}. {self.db.desc}" elif self.db.spoken == 10: self.at_say("Did you say something? I think I have water in my ears, as I can't hear a thing.") elif self.db.spoken == 20: self.at_say("So... how're you getting along?") elif self.db.spoken == 30: self.at_say("Right, right. Still can't hear. Hrm.") elif self.db.spoken == 60: self.at_say("Do you know why we fish are so easy to weigh? ") elif self.db.spoken == 63: self.at_say("Because we have are own scales.") elif self.db.spoken == 70: self.at_say("I suppose you could |gthrow|n me back in the water at any time.") elif self.db.spoken == 120: self.at_say("I suppose I should pay you back for helping me out with that hook thing. I guess you know I keep all my money at ... the riverbank.") elif self.db.spoken == 200: self.at_say("You know the easiest way to catch a fish, right?") elif self.db.spoken == 201: self.at_say("Have someone toss it to you.") elif self.db.spoken == 205: self.at_say("Ouch. Tough crowd.") elif self.db.spoken == 300: self.at_say("Me and my friends started a musical band.") elif self.db.spoken == 301: self.at_say("We all play bass.") elif self.db.spoken == 302: self.at_say("Alright guys, I said, drop the instruments. We are singing aquapella.") elif self.db.spoken == 400: self.at_say("Did you meet the owners of that new fishing store?") elif self.db.spoken == 401: self.at_say("Their names are Rod and Annette.") elif self.db.spoken == 800: self.at_say("I'm not that smart.") elif self.db.spoken == 801: self.at_say("My friends tell me I'm a dumb bass.") elif self.db.spoken == 803: self.at_say("Sorry for all the puns. I feel so GILL-ty.") # Let's attempt to tell a bad joke once a day: elif self.db.spoken > 1000 and self.db.spoken % (24 * 60 * 60 / self.fish_tick) == 0: self.at_say(get_joke()) self.db.spoken += 1 def do_delete(self, fisher): """ A visual way to delete the fish. """ if fisher.location == fisher.search("Lazy Dock", quiet=True): fisher.msg(routput("You <> the fish back into the <>.")) fisher.msg(routput("The fish says, \"Bye for now. If you want to talk again, just drop me a line!\"")) else: fisher.msg(routput("You <> the fish, and an << eagle ^ hawk >> swoops << down ^ >> and snatches it. I'm sure it will carry the fish back to the sea for you.")) self.delete() def get_name(): return random.choice([ "Bennie", "Flipper", "Finegan", "Count Bassie" ]) def get_desc(): return routput(random.choice([ "A walleye with big bulbous eyes that clearly doesn't get no respect.", "A bass with amazing neck confidence giving it a most excellent head bob.", "A rainbow trout missing the <> from its iridescent stripe.", "A brown trout colored <>.", # "A spiny perch", # "A salmon", # "A pike", ])) def get_joke(): "Fetch a random joke from the internet." r = requests.get("https://icanhazdadjoke.com/", headers={'Accept':'text/plain'}) return r.text class FishingPole(Object): """ Can produce a Fish. """ failure_msgs = [ "You reel in an empty line.", "You didn't catch anything.", "Caught nothing but a bit of weeds, yeck.", "Caught nothing, but this sure is enjoyable.", "Did you catch a boot? Nah, it isn't even that good.", "Anything better that sitting on the dock of the bay?", ] def at_object_creation(self): self.cmdset.add_default(CmdSetFishing) def do_cast(self, fisher): if fisher.location.key != "Lazy Dock": fisher.msg("You can't do that without being near the water.") elif fisher.db.fishing == Fishing.CAST: fisher.msg("You need to reel the line in first.") else: fisher.db.fishing = Fishing.CAST fisher.msg(routput(random.choice([ "You cast out far into the <>.", "You cast close to the <>.", "You cast off to the <> where you <> see a dark pocket.", ]))) def do_reel(self, fisher): if fisher.db.fishing != Fishing.CAST: fisher.msg("You need to |gcast|n before you can reel the line back in.") else: fisher.db.fishing = Fishing.REEL if random.randint(1, 100) < 35: self.give_fish(fisher) else: fisher.msg(random.choice(self.failure_msgs)) def give_fish(self, fisher): fish = spawn({ "typeclass": self.db.make_class or "typeclasses.fishing.Fish", "key": "fish", "aliases": [Fish.get_name()], "desc": Fish.get_desc(), })[0] fish.location = fisher fisher.msg(f"You caught a fish!") fisher.score(Scores.catch_fish)