Get Started - Learn How To Make Your Bot!GuidesCode SnippetsGet methodsPost methodsWeb APIUseful linksList of all currently Free ItemsList of EmotesHighrise Bot SDK Changelog
Concept
This Code Snippet is about how to make an emote loop!
To do that we will use the 📬 Command Handler, note that this use is optional, you can implement this function directly on your main code or directly on your on_chat method.
Methods/Functions used:
Required Libraries
- highrise-bot-sdk
- asyncio
Code
First of all, let’s create a new file called loop_emote.py inside of our functions folder:
Here’s what we will need to import into our loop_emote.py file:
from highrise import * from highrise.models import * import asyncio from asyncio import Task
Let’s proceed to our functions definitions, since we’re using the command handler for this example, your function name will be the command that you will use in the chat to call it, I will name mines as loop and stop_loop.
Since we want that the bot continuously follows us, this function has to be an loop and be asynchronously executed. For that, we will be using the buit-in Highrise taskgroup, and we will make a function called loop_emote to be inserted in this taskgroup, we will also create an emote_list to use as reference for emote names and ids.
from highrise import * from highrise.models import * import asyncio emote_list : list[tuple[str, str]] = [('Rest', 'sit-idle-cute'), ('Zombie', 'idle_zombie'), ('Relaxed', 'idle_layingdown2'), ('Attentive', 'idle_layingdown'), ('Sleepy', 'idle-sleep'), ('Pouty Face', 'idle-sad'), ('Posh', 'idle-posh'), ('Sleepy', 'idle-loop-tired'), ('Tap Loop', 'idle-loop-tapdance'), ('Sit', 'idle-loop-sitfloor'), ('Shy', 'idle-loop-shy'), ('Bummed', 'idle-loop-sad'), ("Chillin'", 'idle-loop-happy'), ('Annoyed', 'idle-loop-annoyed'), ('Aerobics', 'idle-loop-aerobics'), ('Ponder', 'idle-lookup'), ('Hero Pose', 'idle-hero'), ('Relaxing', 'idle-floorsleeping2'), ('Cozy Nap', 'idle-floorsleeping'), ('Enthused', 'idle-enthusiastic'), ('Boogie Swing', 'idle-dance-swinging'), ('Feel The Beat', 'idle-dance-headbobbing'), ('Irritated', 'idle-angry'), ('Yes', 'emote-yes'), ('I Believe I Can Fly', 'emote-wings'), ('The Wave', 'emote-wave'), ('Tired', 'emote-tired'), ('Think', 'emote-think'), ('Theatrical', 'emote-theatrical'), ('Tap Dance', 'emote-tapdance'), ('Super Run', 'emote-superrun'), ('Super Punch', 'emote-superpunch'), ('Sumo Fight', 'emote-sumo'), ('Thumb Suck', 'emote-suckthumb'), ('Splits Drop', 'emote-splitsdrop'), ('Snowball Fight!', 'emote-snowball'), ('Snow Angel', 'emote-snowangel'), ('Shy', 'emote-shy'), ('Secret Handshake', 'emote-secrethandshake'), ('Sad', 'emote-sad'), ('Rope Pull', 'emote-ropepull'), ('Roll', 'emote-roll'), ('ROFL!', 'emote-rofl'), ('Robot', 'emote-robot'), ('Rainbow', 'emote-rainbow'), ('Proposing', 'emote-proposing'), ('Peekaboo!', 'emote-peekaboo'), ('Peace', 'emote-peace'), ('Panic', 'emote-panic'), ('No', 'emote-no'), ('Ninja Run', 'emote-ninjarun'), ('Night Fever', 'emote-nightfever'), ('Monster Fail', 'emote-monster_fail'), ('Model', 'emote-model'), ('Flirty Wave', 'emote-lust'), ('Level Up!', 'emote-levelup'), ('Amused', 'emote-laughing2'), ('Laugh', 'emote-laughing'), ('Kiss', 'emote-kiss'), ('Super Kick', 'emote-kicking'), ('Jump', 'emote-jumpb'), ('Judo Chop', 'emote-judochop'), ('Imaginary Jetpack', 'emote-jetpack'), ('Hug Yourself', 'emote-hugyourself'), ('Sweating', 'emote-hot'), ('Hero Entrance', 'emote-hero'), ('Hello', 'emote-hello'), ('Headball', 'emote-headball'), ('Harlem Shake', 'emote-harlemshake'), ('Happy', 'emote-happy'), ('Handstand', 'emote-handstand'), ('Greedy Emote', 'emote-greedy'), ('Graceful', 'emote-graceful'), ('Moonwalk', 'emote-gordonshuffle'), ('Ghost Float', 'emote-ghost-idle'), ('Gangnam Style', 'emote-gangnam'), ('Frolic ', 'emote-frollicking'), ('Faint', 'emote-fainting'), ('Clumsy', 'emote-fail2'), ('Fall', 'emote-fail1'), ('Face Palm', 'emote-exasperatedb'), ('Exasperated', 'emote-exasperated'), ('Elbow Bump', 'emote-elbowbump'), ('Disco', 'emote-disco'), ('Blast Off', 'emote-disappear'), ('Faint Drop', 'emote-deathdrop'), ('Collapse', 'emote-death2'), ('Revival', 'emote-death'), ('Dab', 'emote-dab'), ('Curtsy', 'emote-curtsy'), ('Confusion', 'emote-confused'), ('Cold', 'emote-cold'), ('Charging', 'emote-charging'), ('Bunny Hop', 'emote-bunnyhop'), ('Bow', 'emote-bow'), ('Boo', 'emote-boo'), ('Home Run!', 'emote-baseball'), ('Falling Apart', 'emote-apart'), ('Thumbs Up', 'emoji-thumbsup'), ('Point', 'emoji-there'), ('Sneeze', 'emoji-sneeze'), ('Smirk', 'emoji-smirking'), ('Sick', 'emoji-sick'), ('Gasp', 'emoji-scared'), ('Punch', 'emoji-punch'), ('Pray', 'emoji-pray'), ('Stinky', 'emoji-poop'), ('Naughty', 'emoji-naughty'), ('Mind Blown', 'emoji-mind-blown'), ('Lying', 'emoji-lying'), ('Levitate', 'emoji-halo'), ('Fireball Lunge', 'emoji-hadoken'), ('Give Up', 'emoji-give-up'), ('Tummy Ache', 'emoji-gagging'), ('Flex', 'emoji-flex'), ('Stunned', 'emoji-dizzy'), ('Cursing Emote', 'emoji-cursing'), ('Sob', 'emoji-crying'), ('Clap', 'emoji-clapping'), ('Raise The Roof', 'emoji-celebrate'), ('Arrogance', 'emoji-arrogance'), ('Angry', 'emoji-angry'), ('Vogue Hands', 'dance-voguehands'), ('Savage Dance', 'dance-tiktok8'), ("Don't Start Now", 'dance-tiktok2'), ('Yoga Flow', 'dance-spiritual'), ('Smoothwalk', 'dance-smoothwalk'), ('Ring on It', 'dance-singleladies'), ("Let's Go Shopping", 'dance-shoppingcart'), ('Russian Dance', 'dance-russian'), ('Robotic', 'dance-robotic'), ("Penny's Dance", 'dance-pennywise'), ('Orange Juice Dance', 'dance-orangejustice'), ('Rock Out', 'dance-metal'), ('Karate', 'dance-martial-artist'), ('Macarena', 'dance-macarena'), ('Hands in the Air', 'dance-handsup'), ('Floss', 'dance-floss'), ('Duck Walk', 'dance-duckwalk'), ('Breakdance', 'dance-breakdance'), ('K-Pop Dance', 'dance-blackpink'), ('Push Ups', 'dance-aerobics')] async def follow(self: BaseBot, user: User, message: str) -> None: async def loop_emote(self: BaseBot, user: User, emote_name: str) -> None: pass pass async def stop_loop(self: BaseBot, user: User, message: str) -> None: pass
Finally, let’s implement the functions and after it you will see a detailed step by step guide on how the code works:
from highrise import * from highrise.models import * import asyncio from asyncio import Task emote_list : list[tuple[str, str]] = [('Rest', 'sit-idle-cute'), ('Zombie', 'idle_zombie'), ('Relaxed', 'idle_layingdown2'), ('Attentive', 'idle_layingdown'), ('Sleepy', 'idle-sleep'), ('Pouty Face', 'idle-sad'), ('Posh', 'idle-posh'), ('Sleepy', 'idle-loop-tired'), ('Tap Loop', 'idle-loop-tapdance'), ('Sit', 'idle-loop-sitfloor'), ('Shy', 'idle-loop-shy'), ('Bummed', 'idle-loop-sad'), ("Chillin'", 'idle-loop-happy'), ('Annoyed', 'idle-loop-annoyed'), ('Aerobics', 'idle-loop-aerobics'), ('Ponder', 'idle-lookup'), ('Hero Pose', 'idle-hero'), ('Relaxing', 'idle-floorsleeping2'), ('Cozy Nap', 'idle-floorsleeping'), ('Enthused', 'idle-enthusiastic'), ('Boogie Swing', 'idle-dance-swinging'), ('Feel The Beat', 'idle-dance-headbobbing'), ('Irritated', 'idle-angry'), ('Yes', 'emote-yes'), ('I Believe I Can Fly', 'emote-wings'), ('The Wave', 'emote-wave'), ('Tired', 'emote-tired'), ('Think', 'emote-think'), ('Theatrical', 'emote-theatrical'), ('Tap Dance', 'emote-tapdance'), ('Super Run', 'emote-superrun'), ('Super Punch', 'emote-superpunch'), ('Sumo Fight', 'emote-sumo'), ('Thumb Suck', 'emote-suckthumb'), ('Splits Drop', 'emote-splitsdrop'), ('Snowball Fight!', 'emote-snowball'), ('Snow Angel', 'emote-snowangel'), ('Shy', 'emote-shy'), ('Secret Handshake', 'emote-secrethandshake'), ('Sad', 'emote-sad'), ('Rope Pull', 'emote-ropepull'), ('Roll', 'emote-roll'), ('ROFL!', 'emote-rofl'), ('Robot', 'emote-robot'), ('Rainbow', 'emote-rainbow'), ('Proposing', 'emote-proposing'), ('Peekaboo!', 'emote-peekaboo'), ('Peace', 'emote-peace'), ('Panic', 'emote-panic'), ('No', 'emote-no'), ('Ninja Run', 'emote-ninjarun'), ('Night Fever', 'emote-nightfever'), ('Monster Fail', 'emote-monster_fail'), ('Model', 'emote-model'), ('Flirty Wave', 'emote-lust'), ('Level Up!', 'emote-levelup'), ('Amused', 'emote-laughing2'), ('Laugh', 'emote-laughing'), ('Kiss', 'emote-kiss'), ('Super Kick', 'emote-kicking'), ('Jump', 'emote-jumpb'), ('Judo Chop', 'emote-judochop'), ('Imaginary Jetpack', 'emote-jetpack'), ('Hug Yourself', 'emote-hugyourself'), ('Sweating', 'emote-hot'), ('Hero Entrance', 'emote-hero'), ('Hello', 'emote-hello'), ('Headball', 'emote-headball'), ('Harlem Shake', 'emote-harlemshake'), ('Happy', 'emote-happy'), ('Handstand', 'emote-handstand'), ('Greedy Emote', 'emote-greedy'), ('Graceful', 'emote-graceful'), ('Moonwalk', 'emote-gordonshuffle'), ('Ghost Float', 'emote-ghost-idle'), ('Gangnam Style', 'emote-gangnam'), ('Frolic ', 'emote-frollicking'), ('Faint', 'emote-fainting'), ('Clumsy', 'emote-fail2'), ('Fall', 'emote-fail1'), ('Face Palm', 'emote-exasperatedb'), ('Exasperated', 'emote-exasperated'), ('Elbow Bump', 'emote-elbowbump'), ('Disco', 'emote-disco'), ('Blast Off', 'emote-disappear'), ('Faint Drop', 'emote-deathdrop'), ('Collapse', 'emote-death2'), ('Revival', 'emote-death'), ('Dab', 'emote-dab'), ('Curtsy', 'emote-curtsy'), ('Confusion', 'emote-confused'), ('Cold', 'emote-cold'), ('Charging', 'emote-charging'), ('Bunny Hop', 'emote-bunnyhop'), ('Bow', 'emote-bow'), ('Boo', 'emote-boo'), ('Home Run!', 'emote-baseball'), ('Falling Apart', 'emote-apart'), ('Thumbs Up', 'emoji-thumbsup'), ('Point', 'emoji-there'), ('Sneeze', 'emoji-sneeze'), ('Smirk', 'emoji-smirking'), ('Sick', 'emoji-sick'), ('Gasp', 'emoji-scared'), ('Punch', 'emoji-punch'), ('Pray', 'emoji-pray'), ('Stinky', 'emoji-poop'), ('Naughty', 'emoji-naughty'), ('Mind Blown', 'emoji-mind-blown'), ('Lying', 'emoji-lying'), ('Levitate', 'emoji-halo'), ('Fireball Lunge', 'emoji-hadoken'), ('Give Up', 'emoji-give-up'), ('Tummy Ache', 'emoji-gagging'), ('Flex', 'emoji-flex'), ('Stunned', 'emoji-dizzy'), ('Cursing Emote', 'emoji-cursing'), ('Sob', 'emoji-crying'), ('Clap', 'emoji-clapping'), ('Raise The Roof', 'emoji-celebrate'), ('Arrogance', 'emoji-arrogance'), ('Angry', 'emoji-angry'), ('Vogue Hands', 'dance-voguehands'), ('Savage Dance', 'dance-tiktok8'), ("Don't Start Now", 'dance-tiktok2'), ('Yoga Flow', 'dance-spiritual'), ('Smoothwalk', 'dance-smoothwalk'), ('Ring on It', 'dance-singleladies'), ("Let's Go Shopping", 'dance-shoppingcart'), ('Russian Dance', 'dance-russian'), ('Robotic', 'dance-robotic'), ("Penny's Dance", 'dance-pennywise'), ('Orange Juice Dance', 'dance-orangejustice'), ('Rock Out', 'dance-metal'), ('Karate', 'dance-martial-artist'), ('Macarena', 'dance-macarena'), ('Hands in the Air', 'dance-handsup'), ('Floss', 'dance-floss'), ('Duck Walk', 'dance-duckwalk'), ('Breakdance', 'dance-breakdance'), ('K-Pop Dance', 'dance-blackpink'), ('Push Ups', 'dance-aerobics')] async def loop(self: BaseBot, user: User, message: str) -> None: # Defining the loop_emote method locally so it cann't be accessed from the command handler. async def loop_emote(self: BaseBot, user: User, emote_name: str) -> None: emote_id = "" for emote in emote_list: if emote[0].lower() == emote_name.lower(): emote_id = emote[1] break if emote_id == "": await self.highrise.chat("Invalid emote") return user_position = None user_in_room = False room_users = (await self.highrise.get_room_users()).content for room_user, position in room_users: if room_user.id == user.id: user_position = position start_position = position user_in_room = True break if user_position == None: await self.highrise.chat("User not found") return await self.highrise.chat(f"@{user.username} is looping {emote_name}") while start_position == user_position: try: await self.highrise.send_emote(emote_id, user.id) except: await self.highrise.chat(f"Sorry, @{user.username}, this emote isn't free or you don't own it.") return await asyncio.sleep(10) room_users = (await self.highrise.get_room_users()).content user_in_room = False for room_user, position in room_users: if room_user.id == user.id: user_position = position user_in_room = True break if user_in_room == False: break try: splited_message = message.split(" ") # The emote name is every string after the first one emote_name = " ".join(splited_message[1:]) except: await self.highrise.chat("Invalid command format. Please use '/loop <emote name>.") return else: taskgroup = self.highrise.tg task_list : list[Task] = list(taskgroup._tasks) for task in task_list: if task.get_name() == user.username: # Removes the task from the task group task.cancel() room_users = (await self.highrise.get_room_users()).content user_list = [] for room_user, pos in room_users: user_list.append(room_user.username) taskgroup.create_task(coro=loop_emote(self, user, emote_name)) task_list : list[Task] = list(taskgroup._tasks) for task in task_list: if task.get_coro().__name__ == "loop_emote" and not (task.get_name() in user_list): task.set_name(user.username) async def stop_loop(self: BaseBot, user: User, message: str) -> None: taskgroup = self.highrise.tg task_list : list[Task] = list(taskgroup._tasks) for task in task_list: print(task.get_name()) if task.get_name() == user.username: task.cancel() await self.highrise.chat(f"Stopping your emote loop, {user.username}!") return await self.highrise.chat(f"You're not looping any emotes, {user.username}") return
Let's break down the code step by step:
- Import Statements:
- The code begins with several import statements, importing modules and classes necessary for the functionality of the chatbot. These include modules from a library called
highrise
and its related components.
emote_list
:- This is a list of tuples, where each tuple contains two strings: an emote name and its corresponding identifier. It appears to map human-readable emote names to identifiers used within the game.
loop
Function:- This asynchronous function is designed to start a loop of performing emotes.
- Parameters:
self
: An instance of a class (presumably the chatbot itself).user
: An object representing the user initiating the emote loop.message
: A string containing a command from the user.- The
loop
function first defines a nested asynchronous functionloop_emote
, which performs the actual emote loop. loop_emote
Parameters:self
: Same as the outer function, representing the chatbot.user
: Same as the outer function, representing the user.emote_name
: A string representing the name of the emote to be looped.- Inside
loop_emote
: - It searches for the
emote_id
associated with the providedemote_name
by iterating through theemote_list
. - If the emote name is not found, it sends a message indicating that the emote is invalid.
- It checks the user's position in the game and ensures they are in a room.
- It sends a chat message indicating that the user is looping a specific emote.
- It enters a loop where it repeatedly sends the specified emote to the user every 10 seconds, as long as the user remains in the same position within the room.
- If the user moves to a different position or leaves the room, the loop is terminated.
- Parsing the Command:
- The
loop
function attempts to parse the user's command to extract the emote name. - If the command is not in the expected format, it sends a message indicating that the format is invalid.
- Cancel Existing Tasks:
- It checks if the user already has an emote loop task running and cancels it to prevent multiple concurrent loops.
- Creating a New Task:
- It creates a new asynchronous task using the
create_task
method, passing in theloop_emote
function and the user's information. The task is given the user's username as its name.
stop_loop
Function:- This asynchronous function is designed to stop an ongoing emote loop initiated by the user.
- Parameters:
self
: Same as in theloop
function.user
: Same as in theloop
function.message
: A string containing a command from the user.- It checks if the user has an emote loop task running and cancels it if found, sending a confirmation message. If no loop is found, it sends a message indicating that the user is not currently looping any emotes.