Changes to MantellaSpell when switching to HTTP - Leidtier/Mantella-Spell GitHub Wiki
MantellaSpell using HTTP
This is a higher level overview of the changes to MantellaSpell for using HTTP transfer
Summary
- Requires SKSE_HTTP plugin
- No longer requires PapyrusUtil (if I havent overlooked a spot where it is used)
MantellaEffectScript
has been significantly reduced and only serves to trigger the changes in the actual conversation- New quest
MantellaConversation
now handles the actual conversation - Conversation is now event driven, meaning it only goes forward on actions of the player or when receiving a reply from MantellaSoftware
- There are no running while loops anymore and hopefull no scripts that can get stuck
- If an inferred Action is received, a global event for this specific Action is triggered. Examples of the usage can be found in
MantellaAction_OffendForgiveFollow.psc
- The player character can now be part of the conversation in both MantellaSpell and MantellaSoftware. There is no separate tracking of radiant conversations anymore. It is simply a conversation without the player character in it
MantellaConversation
This is still a slightly larger script with ca. 400 lines split into smaller functions that should be good to digest. The central part for a conversation is now a Quest:
- The Quest is started if a conversation is started
- The Quest is being stopped if the conversation end
- To check if a conversation is currently running, simply checking if it
IsRunning()
of the Quest should be enough:
MantellaConversation conversation = Quest.GetQuest("MantellaConversation") as MantellaConversation
if(conversation.IsRunning())
;Do something with the running conversation here
endIf
Utilising SKSE_HTTP
SKSE_HTTP has 3 main features:
- Creating strongly typed dictionaries in Papyrus. See here for an example
- Sending a request over HTTP using one of the dictionaries created before. This dictionary will get turned into JSON by SKSE_HTTP before sending
- Receiving replies from an HTTP server which will arrive in an event together with a strongly typed dictionary containing the JSON of the server reply
MantellaConversation.psc
starts out with registering for SKSE_HTTPs two main events in its OnInit()
:
event OnInit()
RegisterForModEvent("SKSE_HTTP_OnHttpReplyReceived","OnHttpReplyReceived")
RegisterForModEvent("SKSE_HTTP_OnHttpErrorReceived","OnHttpErrorReceived")
endEvent
- The first
RegisterForModEvent
registers for the event that is called if a HTTP reply is received - The second registers for the event that is called if there was an error in the HTTP communication (we use this to stop the conversation ingame)
Conversation Flow
- A conversation gets initiated by the player
MantellaEffectScript
starts the questMantellaConversation
MantellaEffectScript
callsMantellaConversation.StartConversation(Actor[] actorsToStartConversationWith)
using the caster and the target (so player character and NPC) as the two entries for theactorsToStartConversationWith
parameter. (MantellaEffectScript
already ends here)MantellaConversation
updates its internal list of participants in the conversation with the two Actors it just received for starting the conversation- A strongly typed dictionary is created containing the request type, the actors and the context:
{
mantella_request_type: "mantella_start_conversation",
mantella_actors: [
{
mantella_actor_id: 7,
mantella_actor_name: "Gurden",
mantella_actor_gender: 0,
mantella_actor_race: "Nord", // <- Or however that actually comes out of the game
mantella_actor_is_player: true,
mantella_actor_relationshiprank: 5, // <- Or however the relationship rank with yourself is
mantella_actor_voicetype: "MaleNord",
mantella_actor_is_in_combat: false,
mantella_actor_is_enemy: false,
mantella_custom_values:{
// other mods or games can put additional values here Skyrim does not use it
// Fallout4 should put the position of characters here
}
},
{
mantella_actor_id: 666772,
mantella_actor_name: "Lydia",
mantella_actor_gender: 1,
mantella_actor_race: "Nord", // <- Or however that actually comes out of the game
mantella_actor_is_player: false,
mantella_actor_relationshiprank: 4,
mantella_actor_voicetype: "FemaleEvenToned",
mantella_actor_is_in_combat: false,
mantella_actor_is_enemy: false,
mantella_custom_values:{
// other mods or games can put additional values here Skyrim does not use it
// Fallout4 should put the position of characters here
}
}
],
mantella_context:{
mantella_location: "Skyrim" // <- Not sending empty strings anymore. I felt it should be the duty of the client to provide correct values to the server
mantella_time: 1234 // <- Or however that actually comes out of the game
mantella_ingame_events: [
"Lydia sat down on a bench",
"The player picked up a purple mountain flower",
"The player gifted Lydia a purple mountain flower"
],
custom_context_values: [
// other mods or games can put additional values here Skyrim does not use it
// Fallout4 should put the position of the player character here, because that would be needed even if the character is not participating in the conversation
]
}
}
- This dictionary is sent to MantellaSoftware
- At some point a reply is received which triggers the
OnHttpReplyReceived(int typedDictionaryHandle)
event we subscribed to inOnInit()
. ALL succesful replies arrive at this event
The dictionary received must always contain a string value calledmantella_reply_type
which indicates to MantellaSpell what to do with the reply
The possible reply types and what they indicate are:
mantella_start_conversation_completed
-> conversation has started on side of MantellaSoftwaremantella_npc_talk
-> reply contains a sentence for an NPC to speakmantella_player_talk
-> player should now provide input. It is now the sole duty of MantellaSpell to determine if via text or micmantella_tts
-> reply contains transcribe of a STTmantella_end_conversation
-> conversation has ended on side of MantellaSoftware
- Receiving
mantella_start_conversation_completed
triggers an immediateContinueConversation
http request from MantellaSpell to MantellaSoftware This will request the next thing that happens in the conversation from MantellaSoftware
The request is nearly identical to themantella_start_conversation
request earlier, but the request type is nowmantella_continue_conversation
This will again send along all actors in the conversation with their current stats and the context in its current state. MantellaSoftware will update its own context at once using these information (for example if a new chaarcter has joined the conversation) - If receiving a
mantella_npc_talk
reply, the reply will also contain the information needed to play it. The dictionary received looks like this:
{
mantella_request_type: "mantella_npc_talk",
mantella_npc_talk: {
mantella_actor_speaker: "Lydia",
mantella_actor_line_to_speak: "A flower? Really?",
mantella_actor_voice_file: "Mantellaxxxx.wav",
mantella_actor_line_duration: 1.7,
mantella_actor_actions: [
"Offend", "Follow"
]
}
}
MantellaConversation
will then trigger all Actions in the received list, make the NPC speak their line, wait for the duration of the audio and then issue a new ContinueConversation
request to the server.
- If receiving a
mantella_player_talk
,MantellaSpell
will decide on the spot if it should use text or voice input.
If text input, it will unlock the text input box for the player. Once a text input is entered, a new request is sent to the server that contains:
mantella_request_type: "mantella_player_input"
mantella_player_input: "Oh Lydia, I didn't mean to offend you, I'm sorry."
- All current actors in the conversation with their current stats
- Current context
If voice input, it will send a request to the server to start a STT and display the "Listening..." message
- If receiving a
mantella_tts
this will also contain the transcribe of the voice input. This transcrivbe is then used like text input in step - If receiving
mantella_end_conversation
theMantellaConversation
quest will be stopped.
MantellaEffectScript
This has been massively cut down cause most of its functionality is now in MantellaConversation
This now only reacts if it is invoked by Spell, Shout or Hotkey and either starts a conversation or add the actors to it.
Actions
For every Action that is received with a mantella_npc_talk
reply a unique global event is called.
It is possible to subscribe to this event from everywhere.
For example the Offend, Forgive and Follow Actions have been moved to a new separate Quest called MantellaAction_OffendForgiveFollow
This Quest now implements the existing Actions in a nice simple way and serves as a blueprint for additional actions in the future. https://github.com/Leidtier/Mantella-Spell/blob/http-integration/Scripts/Source/MantellaAction_OffendForgiveFollow.psc