Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import evennia
- from typeclasses.characters import Character
- from evennia import DefaultCharacter
- from evennia.scripts.tickerhandler import TICKER_HANDLER
- from evennia import create_script
- import random
- from typeclasses import exits
- from evennia import logger
- class CMob(DefaultCharacter):
- """
- TO DO:
- Create attack function
- Create death function
- Plug in fight script
- """
- def at_object_creation(self):
- # BASICS DB
- self.db.states = ["state_idle", "state_wander", "state_job", "state_hunt", "state_attack", "state_death"]
- self.db.ticker_interval = random.randint(60,90)
- self.db.default_state = "state_idle"
- self.db.current_state = "state_idle"
- self.db.profession = 3
- self.db.race = 3
- self.db.level = 81
- self.db.curhp = 100
- self.db.maxhp = 100
- self.db.resources = 0
- self.db.curres = 0
- self.db.desc = "An average person."
- # INTERACTION DB
- self.db.current_target = None
- self.db.greets = True
- self.db.greetmsg = [f"Good day to you," ,f"Hello, there," ,f"Greetings,"]
- self.db.custom_response = "|mGuy|n says, \"|gGreat! You'll learn more about |cgreet|n|ging later in the tutorial.|n\""
- self.db.greet_name = True
- self.db.cangive = False
- # MOVEMENT DB
- self.db.mobile = False # If Mob, make sure this is set to FALSE when combat begins!
- self.db.zone = "anubian_farm"
- self.db.spawn_location = "spawn room" # This will be used by the spawner script
- self.db.idle = True
- self.db.idle_list = [
- 'whistles a merry tune.', 'looks around cheerfully.', 'hums to himself.', 'pauses to scratch his groin.',\
- 'checks his watch.', 'bops his head to an imaginary beat.', 'asks, |G"anyone play a good video game lately?"|g.']
- # COMBAT DB
- self.db.is_aggressive = False
- self.db.is_suspicious = False
- self.db.is_fighting = False
- self.db.can_die = False
- self.db.can_loot = False
- self.db.loot = []
- self.db.credits = random.randint(2, 12) # random number for credits in loot
- self.db.dead = False
- self.db.spawn_location = "spawn room" # assign this by the spawner script
- self.db.ticker_despawn = random.randint(120, 180)
- # JOBS DB
- self.db.hasjob = True
- self.db.job_script = None
- # TICKER CONTROLS
- self.ticker_start()
- def ticker_start(self):
- """
- This just gets the ticker going. The same ticker is used for all states.
- """
- TICKER_HANDLER.add(interval=self.db.ticker_interval, callback=self.do_action, idstring="npc_ticker")
- def ticker_stop(self):
- """
- Stops the ticker. Good for things like when combat starts.
- """
- TICKER_HANDLER.remove(interval=self.db.ticker_interval, callback=self.do_action, idstring="npc_ticker")
- def do_action(self):
- current_state = self.db.current_state
- try:
- # find a method on this class with the same name as the state, like "state_idle".
- state_method = getattr(self, current_state)
- except AttributeError:
- logger.log_trace(f"Erroneous state for NPC {self.key}")
- return
- try:
- # we fire the state-method we just dug out
- state_method()
- except Exception:
- logger.log_trace(f"Error when running the {state_method}() on NPC {self.key}")
- # SET STATE
- def set_state(self, statename, target=None):
- """
- This is something we should be able to set with a custom Command, something like
- setstate <npcname> = idle
- setstate <npcname> = idle:target
- Args:
- statename (str): The name of the state. Must be one of the allowed states.
- target (Object): If this state has a target, the Command should get that and
- supply it here as well.
- Raises:
- RuntimeError: On invalid input. The calling command can catch and show this
- to the user.
- """
- statename = statename.lower() # make case not matter
- if not statename in self.db.states:
- raise RuntimeError("This is not a valid state")
- self.db.current_state = statename
- self.db.current_target = target
- # WANDER STATE
- def state_wander(self):
- zone = self.db.zone
- move_chance = random.randint(1,5)
- if self.db.mobile:
- if move_chance >= 4:
- exit_list = [myexit for myexit in self.location.exits if self.check_zone(myexit.destination)]
- if exit_list:
- new_exit = random.choice(exit_list)
- self.location.msg_contents(f"|m{self.name}|n creeps away.")
- self.move_to(new_exit.destination)
- self.location.msg_contents(f"|m{self.name}|n scans the area.")
- else:
- self.location.msg_contents(f"|m{self.name}|n sneaks away.")
- self.move_to(self.home)
- self.location.msg_contents(f"|m{self.name}|n scans the area.")
- if self.db.aggressive:
- self.set_state("state_hunt")
- elif self.db.idle:
- self.set_state("state_idle")
- # IDLE STATE
- def state_idle(self):
- idle_msg = random.choice(self.db.idle_list)
- self.location.msg_contents(f"|m{self.name}|n {idle_msg}")
- # JOB STATE
- def state_job(self, target):
- self.db.current_target = target
- if self.db.hasjob:
- logger.log_trace(f"{self.key} has a job.")
- if not self.db.job_script: # No script created yet, make it
- script = "typeclasses.jobs_script"
- try:
- create_script(script, obj=self, persistent=True)
- self.db.job_script = script
- target.db.jobs_doing.append(script)
- logger.log_trace(f"{self.key} created {script} Attenpting to access...")
- typeclasses.jobs_script.JobScript.asked_for_job(self)
- except:
- logger.log_trace(f"{self.key} failed to create {script}.")
- elif self.db.job_script: # Script exists, just check it now.
- logger.log_trace(f"{self.key} attempting to access: typeclasses.jobs_script.JobScript.asked_for_job(self).")
- typeclasses.jobs_script.JobScript.asked_for_job(self)
- elif not self.db.hasjob:
- target.msg(f"|m{self.name}|n thinks for a moment, then says, |g\"I'm afraid I don't have anything for you, {target.name}.\"|n")
- logger.log_trace(f"{self.key} has no jobs.")
- script.JobGive.asked_for_job(target)
- else:
- logger.log_trace(f"{self.key} does not have a job for {target}.")
- # inform player that the npc has no job for them.
- getstate = self.db.default_state
- self.set_state(getstate)
- # HUNT STATE
- def hunt(self):
- if not self.db.dead and self.db.aggressive:
- target = self.get_target(self.location)
- if target:
- target.msg(f"|m{self.name}|n moves to attack you!")
- self.set_state("state_attack")
- elif self.db.idle:
- self.set_state("state_idle")
- def get_target(self, location):
- targets = [obj for obj in location.contents_get(exclude=self) if obj.has_account and not obj.is_superuser]
- return targets[0] if targets else None
- # ATTACK STATE
- def state_attack(self, target):
- """
- Start attack setup, then call the fighting script.
- """
- #if flee:
- #if mobile:
- #self.set_ticker(interval=self.db.ticker_interval, callback=self.wander, idstring="wandering_mob", persistent=True)
- # DEATH STATE
- def state_death(self):
- self.location.msg_contents(f"|m|m{self.name}|n|n has died!")
- self.location.msg_contents(f"|m{self.name}|n falls to the ground, lifeless.")
- #set a timer to destroy
- self.db.mobile = False
- self.db.dead = True
- self.db.canloot = True
- self.set_ticker(self.db.ticker_despawn, "remove_mob")
- # CHECK ZONE
- def check_zone(self, destination):
- dest = destination.tags.get(category="pverooms") # destination is the actual object 'room'
- if dest is not None:
- return True
- else:
- return False
- # CHARACTER ENTERED ROOM
- def at_char_entered(self, character):
- """
- Character entered the same room as the mob
- Check if the character is a player by running get_target()
- Check if mob is aggressive
- If mob is aggressive, run the attack function
- If the mob is not aggressive but suspicious,
- just look at the target.
- """
- target = self.get_target(self.location)
- if self.db.aggressive:
- if target:
- TICKER_HANDLER.remove(idstring="wandering_npc")
- target.msg(f"|m{self.name}|n attacks you!")
- self.start_attacking(self, target)
- return
- elif self.db.is_suspicious:
- self.location.msg_contents(f"|m{self.name}|n looks at {character}.", exclude=target)
- target.msg(f"|m{self.name}|n looks at you.")
- pass
- # REMOVE SELF (DEATH)
- def remove_mob(self, *args, **kwargs):
- TICKER_HANDLER.remove(idstring="wandering_mob")
- # RETURN APPEARANCE
- def return_appearance(self, looker):
- text = super().return_appearance(looker)
- lvl = int(self.db.level)
- if not self.db.dead:
- if lvl < 5:
- cinfo = "\n|YThey are very frail looking.|n"
- elif lvl < 10:
- cinfo = "\n|YThey look pretty weak.|n"
- elif lvl < 20:
- cinfo = "\n|YThey don't seem terribly strong.|n"
- elif lvl < 30:
- cinfo = "\n|YThey look somewhat skilled.|n"
- elif lvl < 40:
- cinfo = "\n|YThey seem like they could hold their own.|n"
- elif lvl < 50:
- cinfo = "\n|YThey appear decently skilled.|n"
- elif lvl < 60:
- cinfo = "\n|YThey look fairly strong.|n"
- elif lvl < 70:
- cinfo = "\n|YThey seem pretty tough.|n"
- elif lvl < 80:
- cinfo = "\n|YSomething tells you they're very skilled.|n"
- elif lvl < 90:
- cinfo = "\n|YThey have a powerful air to them.|n"
- elif lvl < 100:
- cinfo = "\n|YThey are God-like in power.|n"
- else:
- cinfo = "\n|yThey lay lifeless upon the ground, very dead.|n"
- if "\n" in text:
- # text is multi-line, add details after first line
- first_line, rest = text.split("\n", 1)
- text = first_line + cinfo + "\n" + rest
- else:
- # text is only one line; add details to end
- text += cinfo
- return text
- # RESPOND TO GREET
- def greeting(self, target):
- logger.log_trace(f"{target} greeted {self.name}.")
- self.db.current_target = target
- response = random.choice(self.db.greetmsg)
- customresponse = self.db.custom_response
- if self.db.greet_name:
- text = (f"|m{self.name}|n says, |g'") + (response) + (f" {target}.'|n")
- target.msg(text)
- else:
- text = "f" + (customresponse)
- target.msg(text)
Add Comment
Please, Sign In to add comment