Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| guide:communication [2023/11/27 04:55] – Moved during guide overhaul, originally written by Cherry and Levidre ulde3 | guide:communication [2025/11/05 16:45] (current) – [Sending and receiving external SHIORI Events] Fix broken syntax ulde3 | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| ====== Communication ====== | ====== Communication ====== | ||
| - | {{page> | ||
| <WRAP right> | <WRAP right> | ||
| ^ Communication | ^ Communication | ||
| ^ Type | Guide | | ^ Type | Guide | | ||
| - | ^ Category | AYA/ | + | ^ Category | Other | |
| </ | </ | ||
| - | ===== The back and forth method ===== | + | Communication in the context of this guide refers |
| - | I figured out code on how to get two ghosts | + | |
| - | For debugging purposes at least, I have a menu option to Start conversation with the target ghost. | + | Note that this guide is not exhaustive, nor is it rules about how you //must// do things. There are some recommendations for how certain methods are best used, but you may find solutions that fit your ghost' |
| - | < | + | |
| - | “\n\n[half]\![*]\q[Start Ghost Convo, | + | |
| - | Then this function | + | |
| - | < | + | {{SIDETOC width18}} |
| - | Select.InitiateGhostConvo | + | |
| + | ===== Important considerations ===== | ||
| + | ==== Ghost name vs. sakura name ==== | ||
| + | One of the most important things to know about ghost communication is that some types of communication use the __ghost name__ of the ghost you want to communicate with, while many others use the __sakura name__. For a ghost such as [[ghost: | ||
| + | |||
| + | Which name is used where seems arbitrary at times, but it has to be maintained as-is to preserve compatibility for older ghosts. Any time you're working with communication, | ||
| + | |||
| + | ==== SHIORI-agnostic ==== | ||
| + | Communication is completely SHIORI-agnostic. Because communication is handled by the baseware through SHIORI events and SakuraScript tags, any ghost may communicate with any other ghost, regardless of what programming language is used to make them. YAYA ghosts can communicate with Kawari ghosts, Satori ghosts, etc., and vice versa. The only exception to this is that not all SHIORI may provide a way to send a message to others via the OnCommunicate event, in which case other methods of communication would need to be used. | ||
| + | |||
| + | |||
| + | ===== Styles | ||
| + | While not in any official documentation, | ||
| + | |||
| + | " | ||
| + | |||
| + | " | ||
| + | |||
| + | Passive communication tends to be easier to set up and may be implemented more broadly, while active communication tends to be much more involved and have hand-crafted responses for each group of characters that are interacting. | ||
| + | |||
| + | |||
| + | ===== Passive communication ===== | ||
| + | Passive communication is generally a much easier form of communication to set up. Usually it involves | ||
| + | |||
| + | The major benefit of passive communication is that it can be implemented independently by developers, without the need to actively coordinate | ||
| + | |||
| + | The potential downside is that this style of communication can become so broad that interactions may feel generic, depending on how they are implemented. Interactions with a " | ||
| + | |||
| + | |||
| + | ==== Sending and receiving external SHIORI Events ===== | ||
| + | This is communication at its most basic. This method is much the same as the way that ukagaka works in general, so much so that you can often find these kinds of events listed on [[https:// | ||
| + | |||
| + | The way ukagaka works is that the baseware sends events, and if the ghost responds with a script, then that response script is displayed. The same is true of this kind of communication as well: a ghost sends out a SHIORI event using the '' | ||
| + | |||
| + | See the [[https:// | ||
| + | |||
| + | |||
| + | === Raise vs Notify === | ||
| + | Events that are called | ||
| + | |||
| + | In general, " | ||
| + | |||
| + | For example, you might use a raise event to tell other open ghosts that your ghost has just told a bad joke, and prompt them to laugh. You might use a notify event if your ghost has a function like a music player, and you want other ghosts to be able to tell what song is currently playing. | ||
| + | |||
| + | |||
| + | === Target === | ||
| + | raiseother and notifyother tags can either send their events to specific targets, or they may use ''< | ||
| + | |||
| + | For example, if your ghost has a music player function and you want other ghosts to be able to tell what song is playing, it's probably best to send that information to every open ghost at once with ''< | ||
| + | |||
| + | On the other hand, for a function like [[ghost: | ||
| + | |||
| + | |||
| + | ==== Listening to another ghost' | ||
| + | It is possible for your ghost to listen to the dialogues of another ghost, and react to things within it. This is how machine translation ghosts such as [[ghost: | ||
| + | |||
| + | In order to do this, your ghost must run the tag '' | ||
| + | |||
| + | Take caution with this event: if there are many ghosts open at once, this event may be called rapidly. | ||
| + | |||
| + | OnOtherGhostTalk provides various information as references. This includes the name of the ghost (and the ghost' | ||
| + | |||
| + | This can be used for many things because of all the information sent as references. Usually, though, it will be used in one of two ways: responding to a particular event that occurred in a ghost, or responding to a specific dialogue in a ghost. | ||
| + | |||
| + | As an example of responding to a particular event in a ghost, the ghost [[ghost: | ||
| + | |||
| + | Noodle is also an example of responding to a particular dialogue in a ghost. If both Needle and Noodle are open, Noodle will react to specific dialogues from Needle and add commentary or additional context. | ||
| + | |||
| + | |||
| + | ==== Commenting on the presence or installation status of another ghost ==== | ||
| + | Some ghosts, particularly if they are related to each other in some way, may have special comments or behavior if they detect that a particular other ghost is installed, or is running at the same time as them. | ||
| + | |||
| + | This is done through a couple of SHIORI events. Note that these event names do not begin with " | ||
| + | |||
| + | [[https:// | ||
| + | |||
| + | To make use of these events, you may wish to save the lists they generate to a variable, or you may wish to process the list within the event and set some variables there. Either way, once you have the information, | ||
| + | |||
| + | It's important to note that installedghostname lists ghosts by their ghost name, while otherghostname uses the name of the sakura character in that ghost. | ||
| + | |||
| + | A basic implementation in YAYA might look something like this (note that in YAYA, '' | ||
| + | |||
| + | < | ||
| + | On_otherghostname | ||
| + | { | ||
| + | MrExampleOpen = 0 | ||
| + | foreach reference.raw; _ref | ||
| + | { | ||
| + | if _ref[0, | ||
| + | } | ||
| + | } | ||
| + | |||
| + | //Elsewhere in RandomTalk... | ||
| + | if MrExampleOpen | ||
| + | { | ||
| + | "Hey, it's Mr. Example!" | ||
| + | } | ||
| + | elseif ASEARCH(" | ||
| { | { | ||
| - | "\0\s[0]* yo TARGETGHOSTNAME that you? | + | "You've met Mr. Example, right? He's a friend of mine, maybe we can all hang out sometime." |
| } | } | ||
| </ | </ | ||
| - | ==== Now, add this in commu.dic for each ghost: ==== | + | |
| - | The **OnCommunicate** function needs this bolded | + | ==== Reacting to another ghost being opened, closed, uninstalled, |
| - | < | + | On the topic of noticing when other ghosts are open or installed, etc., there are also some basic SHIORI events that could be considered a form of passive communication. There are a whole range of them [[https:// |
| - | OnCommunicate | + | |
| + | You can use these to react to the user changing to other ghosts, calling other ghosts, closing other ghosts, and more. | ||
| + | |||
| + | You might also consider events such as [[https:// | ||
| + | |||
| + | How you use these events is up to you, but they are a quick and easy way of interacting with other ghosts. On their face they may seem like they' | ||
| + | |||
| + | For example, a ghost with a café setting could use the OnOtherGhostBooted event to have a diagetic dialogue implying that the booted ghost entered through the café' | ||
| + | |||
| + | |||
| + | ===== Active communication ===== | ||
| + | Active communication tends to be more intricate and involve hand-crafted interactions between different ghosts. " | ||
| + | |||
| + | The upside of this kind of communication is that it can be a very immersive experience, and can involve new content shared between the ghosts that the user can't see anywhere else. Contrast this with generic responses to events like OnOtherGhostBooted, | ||
| + | |||
| + | The major downside of this is that it involves coordinating multiple ghosts, and often collaboration between multiple developers. This means it is vastly more work than passive communication styles, and it also cannot be used with older ghosts whose developers no longer maintain them. Another potential issue is that if the user updates one ghost but not the other(s), they will not be able to use the communication features and may encounter buggy behavior. All in all, this is a much more difficult form of communication to implement. | ||
| + | |||
| + | |||
| + | ==== Some notes on back and forth conversation ==== | ||
| + | Back and forth communication can be achieved in a number of ways. The event made expressly | ||
| + | |||
| + | |||
| + | === Difficulty if the first part of a conversation is missed === | ||
| + | Regardless of the method used, one of the potential problems with this kind of direct interaction is that if there are multiple responses back and forth, and the user is not closely watching their ghosts, they might miss earlier responses since the balloon is reset each time. There have been some attempts to solve this, such as the " | ||
| + | |||
| + | The following is an example of what a back and forth conversation looks like with no extra processing: | ||
| + | |||
| + | {{guide: | ||
| + | |||
| + | The following is with the " | ||
| + | |||
| + | {{guide: | ||
| + | |||
| + | (The ghosts in the above gifs are [[ghost: | ||
| + | |||
| + | |||
| + | === New information changing a ghost' | ||
| + | Another thing to consider with back and forth conversations is that this is best used between ghosts for whom it will not introduce //new information// | ||
| + | |||
| + | This has been an issue speculated about for certain styles of ghost, where if they learn certain information about the user, they might become withdrawn/ | ||
| + | |||
| + | The issue this causes is that in order for such an interaction to be meaningful, it might make the most sense for the ghost in question to use a completely different pool of dialogue than what they used before, or otherwise change their behavior permanently. This is potentially a vast amount of work, and may be a poor user experience. | ||
| + | |||
| + | This concept could be executed well, especially if it is planned from the outset and is a core feature of the ghost, but it isn't usually what developers have in mind when they want to add conversations with other ghosts. | ||
| + | |||
| + | |||
| + | === Number of ghosts involved === | ||
| + | Typically, back and forth conversations will only take place between two ghosts. However, there is nothing stopping you from writing conversations that take place between more than 2 ghosts, other than the increasing difficulty of coordinating multiple ghosts together, and getting the user to run that many ghosts at once in order to see the content. | ||
| + | |||
| + | It is entirely possible to create an interaction that involves conversation between many ghosts, but it is likely that such an approach would be best for ghosts which were made with this feature in mind from the start, and have a large emphasis placed on it. | ||
| + | |||
| + | |||
| + | ==== OnCommunicate | ||
| + | [[https:// | ||
| + | |||
| + | With OnCommunicate, | ||
| + | |||
| + | In order to determine what part of a conversation the ghost is in and how to respond, it may be useful to include some additional data in scripts that can be checked for. It is common in some ghosts to include some text after a '' | ||
| + | |||
| + | How OnCommunicate is initiated depends on the SHIORI. | ||
| + | |||
| + | === AYA / YAYA === | ||
| + | In AYA and YAYA, communication can sent by specifying the sakura name of the target ghost in the variable '' | ||
| + | |||
| + | res_reference0 = " | ||
| + | |||
| + | === Satori === | ||
| + | In Satori, communication can be sent by specifying the sakura name of the target ghost with Value0. | ||
| + | |||
| + | $Value0【タブ】Someone | ||
| + | |||
| + | === Kawari === | ||
| + | More information about how to initiate communication in Kawari can be found [[https:// | ||
| + | |||
| + | === Aosora === | ||
| + | In Aosora, communication can be sent by specifying the sakura name of the target ghost in Shiori.ResponseReference. | ||
| + | |||
| + | Shiori.ResponseReference.Add(" | ||
| + | |||
| + | === Misaka === | ||
| + | In Misaka, communication can be sent by specifying the sakura name of the target ghost in the variable '' | ||
| + | |||
| + | {$to=Someone} | ||
| + | |||
| + | Note that Misaka has special setup for ghost communication. Communication from other ghosts is received with the event '' | ||
| + | |||
| + | === Usage example === | ||
| + | A back and forth conversation between two ghosts using the OnCommunicate method could look like this. This example assumes both ghosts are written in YAYA: | ||
| + | |||
| + | < | ||
| + | //In Ghost A's files: | ||
| + | //Somewhere else in the code, maybe in a menu choice or in RandomTalk (using a separately raised event so that res_reference0 only triggers for this dialogue), conversation is started with this script: "Hey Ghost B, good to see you!\w8" | ||
| + | OnConversation.GhostB | ||
| { | { | ||
| - | if reference0 | + | res_reference0 |
| - | { | + | |
| - | | + | _dialogue_tag |
| - | } | + | if _dialogue_tag |
| - | -- | + | { |
| - | if reference0 == "user" | + | "How have things been with you? |
| - | | + | } |
| - | // | + | elseif _dialogue_tag == " |
| - | | + | { |
| - | } | + | " |
| - | else | + | } |
| - | | + | |
| - | // | + | |
| - | ReplyToGhost | + | |
| - | | + | |
| } | } | ||
| </ | </ | ||
| - | (tbh that's probably not the best spot to drop it in OnCommunicate, | ||
| - | Put this anywhere in Commu.dic: | + | < |
| - | < | + | //In Ghost B's files: |
| - | // This function handles incoming and outgoing dialogue for the specified ghost. | + | OnConversation.GhostA |
| - | TalkToSpecificGhost | + | |
| { | { | ||
| - | case reference1 // | + | res_reference0 = "A's sakura" |
| - | { | + | |
| - | when "greeting" | + | _dialogue_tag = SPLIT(reference1, |
| - | { | + | if _dialogue_tag == "response 1" |
| - | | + | { |
| - | } | + | "Hey Ghost A! Fancy meeting you here.\w8\e:response2" |
| - | | + | } |
| - | { | + | elseif _dialogue_tag == "response 3" |
| - | | + | { |
| - | } | + | "Oh, not bad, you?\w8\e:response 4" |
| - | | + | } |
| - | { | + | elseif _dialogue_tag == "end" |
| - | | + | { |
| - | } | + | res_reference0 = "" |
| - | | + | "Alright then, see you!" |
| - | { | + | } |
| - | | + | |
| - | } | + | |
| - | when " | + | |
| - | { | + | |
| - | " | + | |
| - | } | + | |
| - | when " | + | |
| - | { | + | |
| - | " | + | |
| - | //\0\![raiseother, | + | |
| - | } | + | |
| - | } | + | |
| } | } | ||
| </ | </ | ||
| - | Remember, the above text needs to be added for BOTH ghosts, and replace the SPEAKER/ | ||
| - | This is surely not the best way to implement it, but it’s what I got to work so far, and is mainly just to share with [[dev: | ||
| - | ===== The communicate method | + | ==== raiseother |
| - | The advantage of the back and forth method is that the ghost can call any function that starts by On and not only OnCommunicate. It calls the function specified in the raiseother | + | The [[https:// |
| - | The " | + | In the case of active |
| - | ==== How to implement the communicate method ==== | + | Note that when an event is raised with the raiseother tag, there will be SSTP text in the balloon |
| - | Starting a communication with an other ghost is simple. You just need to put **res_reference0=" | + | |
| - | The advantages of this method, in plus that a shorter command, are being able to have more information. The information given by the back and forth method are only the references sent through the command when the communicate method already gives all the information | + | A back and forth conversation between two ghosts using the raiseother |
| - | A little example (keep in mind that ReplyToGhost is called in OnCommunicate, | + | <code c> |
| - | <code> | + | //In Ghost A's files: |
| - | ReplyToGhost | + | //Somewhere else in the code, maybe in RandomTalk, conversation is started with the script "Hey Ghost B, good to see you!\w8\![raiseother, |
| + | OnConversation.GhostB | ||
| { | { | ||
| - | | + | if reference0 == "response 2" |
| - | | + | { |
| - | if reference0==" | + | " |
| - | | + | } |
| - | "\0\s[0]* Hello a_ghost. | + | elseif |
| - | } | + | { |
| - | | + | "Fine! I've got to go now, though, so I'll see you around!\w8\![raiseother,Ghost B, |
| - | { | + | } |
| - | "\0\s[0]* Hello, how are you ?\e" | + | |
| - | | + | |
| - | | + | |
| - | | + | |
| - | "\0\s[0]* | + | |
| - | } | + | |
| - | | + | |
| - | { | + | |
| - | "\0\s[0]* Hello %(reference0), I didn't recognized you nor understood what you said.\e" | + | |
| - | | + | |
| } | } | ||
| </ | </ | ||
| - | With this method, modifying the two ghosts isn't needed. You can just check for particular dialogues and put responses to them. You can do both general and precise stuffs. | ||
| - | {{tag>AYA Guide YAYA wiki.needs style revision}} | + | <code c> |
| + | //In Ghost B's files: | ||
| + | OnConversation.GhostA | ||
| + | { | ||
| + | if reference0 == " | ||
| + | { | ||
| + | "Hey Ghost A! Fancy meeting you here.\w8\![raiseother, | ||
| + | } | ||
| + | elseif reference0 == " | ||
| + | { | ||
| + | "Oh, not bad, you? | ||
| + | } | ||
| + | elseif reference0 == " | ||
| + | { | ||
| + | " | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | |||
| + | |||
| + | |||
| + | ==== OnOtherGhostTalk ==== | ||
| + | Since I mentioned it in a [[# | ||
| + | |||
| + | A potential upside of this method is that a conversation could be built up over time, without needing ghost developers to directly coordinate and synchronize updates. Theoretically, | ||
| + | |||
| + | With OnCommunicate or raiseother, the first ghost to speak initiates it by specifically " | ||
| + | |||
| + | With OnOtherGhostTalk, | ||
| + | |||
| + | These different methods //can// achieve the same thing, but the reactionary approach could lend itself to different styles of interaction. For example, a conversation could be built up between two ghosts over time by simply adding more reactions to an existing conversation. This may help with issues such as one ghost not being updated, etc. (Although this is not a guarantee and depends on the way this is implemented in the ghost.) | ||
| + | |||
| + | |||
| + | ==== Other types of active communication ==== | ||
| + | Back and forth conversation is not the only thing active communication can be used for, although it is likely the most common since other types of communication could be achieved passively. Even so, the only limit here is your imagination. | ||
| + | |||
| + | It is possible to set up ghosts that coordinate with each other in any number of ways, whether it's trading information back and forth, affecting each other' | ||
| + | |||
| + | |||
| + | ===== Communicating through external means (plugins, etc.) ===== | ||
| + | Direct communication between ghosts isn't the only way to communicate, | ||
| + | |||
| + | |||
| + | ==== 共有変数プラグイン (Shared value plugin) ==== | ||
| + | The plugin " | ||
| + | |||
| + | |||
| + | ==== Inventory ==== | ||
| + | The plugin [[https:// | ||
| + | |||
| + | This could be done passively, by one ghost storing some sort of item and leaving it up to other developers if they want to make use of that item, or it could be done actively by different ghosts coordinating to share specific items between them. Either way, the inventory is maintained plugin-side, | ||
| + | |||
| + | Another intended use of the plugin is that certain ghosts may give the user a special item after a special event such as completing their story, etc. When the user clicks on the item in the plugin' | ||
| + | |||
| + | |||
| + | ==== Wallet of UNYU ==== | ||
| + | The plugin [[https:// | ||
| + | |||
| + | While this isn't direct communication, | ||
| + | |||
| + | |||
| + | ===== Ghosts with communication features ===== | ||
| + | The following is not an exhaustive list, but may be useful as a jumping off point for studying ghosts which make use of communication features. Please feel free to add more ghosts to this list. | ||
| + | |||
| + | Ghosts that send external events: | ||
| + | * [[ghost: | ||
| + | * [[ghost: | ||
| + | * [[ghost: | ||
| + | * [[ghost: | ||
| + | * [[ghost: | ||
| + | * [[ghost: | ||
| + | |||
| + | Ghosts with back and forth conversations: | ||
| + | * [[ghost: | ||
| + | * [[ghost: | ||
| + | * [[ghost: | ||
| + | * [[ghost:Dr. W.D. Gaster]] and [[ghost: | ||
| + | * [[ghost:S the Skeleton]] and [[ghost: | ||
| + | * [[ghost:S the Skeleton]] and [[ghost: | ||
| + | |||
| + | Ghosts that react to the dialogue of other ghosts: | ||
| + | * [[ghost: | ||
| + | * [[ghost: | ||
| + | * [[ghost:S the Skeleton]] (reacts to [[ghost:Dr. W.D. Gaster]]) | ||
| + | |||
| + | Ghosts that comment on the presence or installation status of other ghosts: | ||
| + | * [[ghost: | ||
| + | * [[ghost: | ||
| + | * [[ghost: | ||
| + | * [[ghost: | ||
| + | * [[ghost:S the Skeleton]] | ||
| + | |||
| + | |||
| + | {{tag> | ||