Skip to main content

Emotion Balloons and Emotes

An emotion balloon is the small animated bubble that pops over a character's head: the exclamation mark when a trainer spots you, a heart over your follower, a question mark over a confused NPC. MCE ships 14 balloons of its own, original drawings that every game has, and lets a game bring its own set on top of them.

The same balloons serve four different callers:

CallerHow it asks for a balloon
The playerFunction-key hotkeys (F1 to F12, Shift+F1, Shift+F2)
A scriptThe PlayEmotion node in a CommandGraph
The followerA heart while it growls at you (MonsterFollowerController)
Other playersIn the MMORPG layer, a balloon shown over a remote avatar: see Online Emotes

All of them ask by name.

The 14 Engine Balloons​

The names live in EmotionBalloonNames (namespace OpenMon.MCE.Characters.Followers.Talk). EmotionBalloonNames.All lists them in the order the hotkeys use:

NameHotkey
exclamation_markF1
question_markF2
heartF3
music_noteF4
angerF5
sweat_dropF6
sleepF7
happyF8
sadF9
shockedF10
ideaF11
ellipsisF12
sparkleShift+F1
determinedShift+F2

The engine's own set is a ScriptableObject at Resources/Characters/EmotionBalloons/DefaultEmotionBalloons, so any game finds it without wiring anything.

Player Hotkeys​

PlayerCharacter adds a PlayerEmoteInput component to itself as soon as it starts receiving input. From then on the hotkeys above show the matching balloon over the player.

A hotkey only fires when the player is free to act:

  • the player is not interacting (no dialog, menu or cutscene holds it),
  • the game is running (time scale above zero),
  • the previous balloon has finished -- there is one balloon at a time.

Whenever the local player shows a balloon, PlayerEmotes.Played is raised with the balloon's name. That event is how the online layer learns that it has to tell the other players; you can listen to it too:

using OpenMon.MCE.Characters;

PlayerEmotes.Played += name => Debug.Log($"The player showed '{name}'.");

PlayerEmotes.NameForHotkey(functionKey, shift) maps a key to its balloon name (it returns null for a key that carries none).

Showing a Balloon From a Script​

Add a PlayEmotion node (Create Command / Animations / PlayEmotion) to any graph:

FieldMeaning
EmotionThe balloon's name (default heart). A name that nobody has plays nothing, not even a sound.
TargetThe character that shows it. Empty: the actor that runs the graph.
On PlayerShow it over the player instead.
WaitHold the graph until the balloon is gone (on by default). Off, the graph goes on while the balloon plays.

PlayExclamation is the older, single-purpose sibling: it shows the exclamation over a character or over the player, using the game's own exclamation when its set has one.

The Follower's Heart​

A follower that has no talk table of its own (a game that did not import one) shows the engine's heart over itself while it growls when you talk to it. Code can ask the follower for any balloon:

// follower is the MonsterFollowerController of the player's follower
StartCoroutine(follower.ShowEmotion(EmotionBalloonNames.Sparkle));

Bringing Your Own Balloons​

A game replaces or extends the engine's balloons with an Emotion Balloon Set (Create > MCE > Characters > Emotion Balloon Set):

FieldMeaning
balloonsThe balloons: each has a name, its sprites, the sprite shown on every update (spriteByUpdate) and the height of the jump on every update (heightByUpdate). Timelines run at 60 updates per second; 16 map units make one tile.
aliasesAnother name for a balloon -- a script's name for one the cartridge calls differently.
soundThe sound a balloon makes when it pops up. Empty: silent.

Assign the set to the Emotion Balloons field of your MCESettings asset. When anything asks for a balloon, EmotionBalloonSet.Resolve(gameSet, name) looks in this order:

  1. the game's own set, by name or alias;
  2. the engine's own set (EmotionBalloonSet.Default).

So a game that defines heart gets its heart everywhere -- hotkey, script, follower, and balloons that other players see -- and a game that defines nothing still has all 14.

Games imported from a cartridge (see Imported Games and Game Profiles) get their own set built by the importer, and the game profile assigns it to MCESettings (and gives it back when the profile is restored).

Over Any Body​

A popup (CharacterPopUpController) draws the balloon over the player and over every actor. For anything that has no popup -- a follower, another player's avatar, your own prop -- use EmotionBubbleOverBody:

StartCoroutine(EmotionBubbleOverBody.Play(someTransform, balloon, clock: null));

It hangs a temporary object from the body, sits it over the highest of the body's sprites, centers it on all of them and follows the balloon's jump on every update. When the balloon ends the object goes. A balloon with nothing to draw, or a body without sprites, does nothing.

Reference​

TypeNamespaceRole
EmotionBalloonNamesOpenMon.MCE.Characters.Followers.TalkThe 14 names and All
EmotionBalloonSetOpenMon.MCE.Characters.Followers.TalkA set of balloons, Default, Resolve, Find
EmotionBubbleOverBodyOpenMon.MCE.Characters.Followers.TalkDraw a balloon over any body
PlayerEmotesOpenMon.MCE.CharactersHotkey mapping and the Played event
PlayerEmoteInputOpenMon.MCE.CharactersReads the hotkeys
CharacterPopUpControllerOpenMon.MCE.ActorsPlayEmotion(name), PlayBalloon(balloon, sound)
PlayEmotionOpenMon.MCE.Actors.CommandGraph.AnimationsThe script node