irswat Posted November 4, 2016 Share Posted November 4, 2016 I am brainstorming a mod that expands upon the work of Skyvoice. I envision a skyrim where many of the functions can fluidly be controlled by voice. In order to accomplish this I plan to use a speech to text engine like that built into windows. When the engine recognizes words it will append them to a output file sequentially. For example Equip Ebony Armor set would do just that, or saying "Fus ro dah" would equip and cast unrelenting force, drink health potion, equip orcish arrow, etc...I also want to incorporate ez spell casting like Grimy pulled off in Grimy tools, the sort of spell casting that does not require you to unequip weapons to equip the spell and cast it. A player would say cast bind wounds in the middle of a fight and the engine would cast bind wounds.I know there are some mods out there already like SkyVoice that enables the microphone, but they use hotkeys which is something I don't want for this mod. I have a good idea how to accomplish this and I can do a lot of the scripting myself, but I could definitely use someone who is a good all around modder to help me with this project. Compiling lists of phonetics to make this as compatible as possible will be time consuming for one person, especially if I'm trying to do this at the same time as writing a c++ parser to handle the microphone output, and the papyrus script to interface with the parser output. Link to comment Share on other sites More sharing options...
irswat Posted November 5, 2016 Author Share Posted November 5, 2016 (edited) Scriptname SkyrimVoiceEngine extends quest FormList Property ShoutFormList Auto FormList Property SpellFormList Auto FormList Property CommandFormList Auto FormList Property ArmorFormList Auto FormList Property ArrowFormList Auto FormList Property WeaponFormList Auto FormList Property SummonFormList Auto Actor Property PlayerRef Auto Actor Property TargetRef Auto function Dump_PO() ;shoutout to MinionMaster for helping me understand the syntax and find the right functions in MiscUtil.psc ;this function is his work string SVE_PO="/not null" string sDatafileName = "SVE_ParserOutput.txt" if MiscUtil.FileExists(sDatafileName) SVE_PO = MiscUtil.ReadFromFile (sDatafileName) MiscUtil.WriteToFile(sDatafileName, "/delete", true, false) endif endfunction function GetNumLines() ;find out how many distinct lines are in the string int LineCountParserIndex=0 int LineCounter=0 int LineCount=0 LineCounter=MiscUtil.Find(SVE_PO, "/n", LineCountParserIndex) if LineCounter!=-1 LineCount+=1 LineCountParserIndex+=1 elseif LineCounter==1 ;stopcountingline endif endFunction function GetLine() ;;for x=1;x<=LineCount;x++ int EndOfLine=0 int LineParserStart=0 string LineReturn ;get length of first line [0]-"/n" EndOfLine=(StringUtil.Find(SVE_PO, "/n", LineParserStart)-2) ;accounting for carriage return ;gets the content of a line LineReturn=Substring(SVE_PO, LineParserStart, EndOfLine) ;updates parser starting index LineParserStart=EndOfLine+2 ;accounting for carriage return endFunction function GetNumWords() ;find out how many words are on the line int WordCountParserIndex=0 ;beginning of the word index int WordCounter=0 ;end of the word index int WordCount=0 ;number of words on a line WordCounter=StringUtil.Find(SVE_PO, " ", WordCountParserIndex) if WordCounter!=-1 WordCount+=1 WordCountParserIndex+=1 elseif WordCounter==1 ;stopcountingline endif endFunction function GetWord() int EndOfWord=0 int WordParserStart=0 string WordReturn ;parse distinct words from first line [x]-' '\ ;for x=1;x<=WordCount;x++ EndOfWord=(StringUtil.Find(LineReturn, " ", WordParserStart)-1) ;accounting for space WordReturn=Substring(LineReturn, WordParserStart, EndOfWord) LineParserStart=EndOfWord+1 endFunction ;check what distinct words are (e.g. is it a shout, is it a command, is it non sense) ;process shouts and commands ;goto next line ;at delete->repeat if ShoutFormList.HasForm(WordReturn) DoShout() elseif SpellFormList.HasForm(WordReturn) CastSpell() elseif CommandFormList.HasForm(WordReturn) IssueCommand() endIf ;modified clever function from SkyVoice by jeanlou ;skyvoice can be found at http://www.nexusmods.com/skyrim/mods/28448/? function DoShout(string ToShout) int i=ShoutFormList.Find(ToShout) ShoutForm=ShoutFormList.GetAt(i) PlayerREF.EquipShout(ShoutForm) ShoutKey = Input.GetMappedKey("Shout",0x00) Input.HoldKey(ShoutKey) Utility.wait(0.06) Input.ReleaseKey(ShoutKey) EndFunction function CastSpell(string SpellToCast) int i=SpellFormList.Find(SpellToCase) SpellForm=SpellFormList.GetAt(i) ;where is cursor pointing ;is spell beneficient? if PlayerRef.IsInCombat() TargetRef = Game.GetPlayer().GetCombatTarget() SpellForm.cast(PlayerRef, TargetRef) elseif !PlayerRef.IsInCombat() TargetRef=PlayerRef.GetActorReference() SpellForm.cast(PlayerRef, TargetRef) if TargetRef==None SpellForm.cast(PlayerRef, PlayerRef) endif endif ;if not cast at object reference in cursor endFunction function IssueCommand(string CmdToProcess) if CmdToProcess=="Use" ;get item(nextword) if ItemFormList.HasForm(WordReturn) ;if player has x items in inventory ;use x items endif elseif WeaponFormList.HasForm(WordReturn) elseif ArmorFormList.HasForm(WordReturn) endif elseif ArrowFormList.HasForm(WordReturn) endFunction I guess I thought I'd share the progress I've made thus far. I figure I will write the papyrus script, then the parser. If anyone wants to help me with this mod please send me a pm:someone who can help me fill various formlists in creation kit. (Shout formlists, spell formlists, item formlists, weapon formlists, etc)someone who is decent with C++ and wants to write a simple parsing engine that would be wonderful. Edited November 5, 2016 by irswat Link to comment Share on other sites More sharing options...
irswat Posted November 6, 2016 Author Share Posted November 6, 2016 update: code from last night was garbage. update: revising functions to parse words from voice recognition dump. Scriptname SkyrimVoiceEngine extends quest FormList Property ShoutFormList Auto FormList Property SpellFormList Auto FormList Property CommandFormList Auto FormList Property ArmorFormList Auto FormList Property ArrowFormList Auto FormList Property WeaponFormList Auto FormList Property SummonFormList Auto Actor Property PlayerRef Auto Actor Property TargetRef Auto string CurrentDump string CurrentLine int DumpLineCount int LoopCounter=1 function Main() if SVE_DumpArray[0]!="initialized" SVE_DumpArray(new string[31]) SVE_DumpArray[1]="initialized" endif ;implement "mic" button CurrentDump=Dump_PO() DumpLineCount=GetNumLines(CurrentDump) while (LoopCounter<=DumpLineCount) CurrentLine=GetLine(CurrentDump,LineCount) int WordsOnCurrentLine=GetNumWords(CurrentLine) CurrentWordIndex=1 while(CurrentWordIndex<=WordsOnLine) SVE_DumpArray[LoopCounter+1]=GetWord(CurrentLine, CurrentWordIndex) CurrentWordIndex+=1 endWhile endWhile ArrayParser() endfunction function Dump_PO() ;shoutout to MinionMaster for helping me understand the syntax and find the right functions in MiscUtil.psc ;this function is his work string SVE_PO="/not null" string sDatafileName = "SVE_ParserOutput.txt" if MiscUtil.FileExists(sDatafileName) SVE_PO = MiscUtil.ReadFromFile (sDatafileName) MiscUtil.WriteToFile(sDatafileName, "/delete", true, false) endif return SVE_PO endfunction function GetNumLines(SVE_PO) ;find out how many distinct lines are in the string int LineCountParserIndex=0 int LineCounter=0 int LineCount=0 int SVE_PO_End while (SVE_PO_End==-1) ;delete not found on this line LineCounter=StringUtil.Find(SVE_PO, "/n", LineCountParserIndex) ;end of line if (LineCounter==-1) ;redundancy check for end of dump SVE_PO_End=StringUtil.Find(SVE_PO, "/delete", LineCountParserIndex) ;end of dump file endif if (SVE_PO_End==-1) LineCount+=1 LineCountParserIndex=LineCounter+3 endif endWhile if SVE_PO_END!=-1 ;end of dump return LineCount endif endFunction function GetLine(SVE_PO) int EndOfLine=0 int LineParserStart=0 string LineReturn ;get length of first line [0]-"/n" EndOfLine=(StringUtil.Find(SVE_PO, "/n", LineParserStart)-2) ;accounting for carriage return ;gets the content of a line LineReturn=Substring(SVE_PO, LineParserStart, EndOfLine) ;updates parser starting index to next line (e.g "/n +3") LineParserStart=EndOfLine+3 ;accounting for carriage return return LineReturn endFunction function GetNumWords(SVE_CurrentLine) ;find out how many words are on the line int WordCountParserIndex=0 ;beginning of the word index int WordCounter=0 ;end of the word index int WordCount=0 ;number of words on a line WordCounter=StringUtil.Find(SVE_CurrentLine, " ", WordCountParserIndex) if WordCounter!=-1 WordCount+=1 WordCountParserIndex+=1 elseif WordCounter==1 ;stopcountingline endif endFunction function GetWord() int EndOfWord=0 int WordParserStart=0 string WordReturn ;parse distinct words from first line [x]-' '\ ;for x=1;x<=WordCount;x++ EndOfWord=(StringUtil.Find(LineReturn, " ", WordParserStart)-1) ;accounting for space WordReturn=Substring(LineReturn, WordParserStart, EndOfWord) LineParserStart=EndOfWord+1 endFunction ;check what distinct words are (e.g. is it a shout, is it a command, is it non sense) ;process shouts and commands ;goto next line ;at delete->repeat ;check for whether the player has shout ;check for how many words the player knows ;shout words known if ShoutFormList.HasForm(WordReturn) DoShout() elseif SpellFormList.HasForm(WordReturn) CastSpell() elseif CommandFormList.HasForm(WordReturn) IssueCommand() endIf ;modified clever function from SkyVoice by jeanlou ;skyvoice can be found at http://www.nexusmods.com/skyrim/mods/28448/? function DoShout(string ToShout) ;check if the shout is known, and how many words of the shout are known int i=ShoutFormList.Find(ToShout) ShoutForm=ShoutFormList.GetAt(i) PlayerREF.EquipShout(ShoutForm) ShoutKey = Input.GetMappedKey("Shout",0x00) Input.HoldKey(ShoutKey) Utility.wait(0.065) Input.ReleaseKey(ShoutKey) EndFunction ;Int Function GetSpellType(Spell akSpell ) Global Native ; Returns the type of the spell. IE Spell, Ability, Lesser Power, etc. ; 0 = spell, 2 = power, 3 = lesser power ;Int Function GetSpellCastType(Spell akSpell ) Global Native ; Returns the cast type, IE Concentration, fire forget, etc ; 1 = fire and forget, 2 = concentration, 0 = constant effect ;Int Function GetSpellDelivery(Spell akSpell ) Global Native ; returns the delivery ; 0 = self, 1 = Contact, 2 = aimed, 3 = Target Actor, 4 = target location function CastSpell(string SpellToCast) ;considerations: ;does the player have the spell being cast? ;is the spell hostile or beneficient? ;what kind of spell is it? (summon, fire and forget, concentration, contact, etc) ;does the spell need to charge? ;does the player have enough magick to cast said spell? ;how is the spell cast? ;what is the target? (self, targetref, aimed) int i=SpellFormList.Find(SpellToCase) int HostileSpell=1 SpellForm=SpellFormList.GetAt(i) ;break out of function is the spell being cast has not been learned if !PlayerRef.HasSpell(SpellForm) return 0 endif If SpellForm.IsHostile()==0 if GrimyTools.GetSpellDelivery(SpellForm)==0 ;beneficient self targetted spell SpellForm.cast(PlayerRef) endif if GrimyTools.GetSpellType(SpellForm)==0 if GrimyTools.GetSpellDelivery(SpellForm)==3 ;beneficient targetted spell TargetRef=PlayerRef.GetReference() SpellForm.cast(PlayerRef, TargetRef) endIf endif ;ObjectReference Function GetCurrentCrosshairRef() global native ;if GrimyTools.GetSpellType(SpellForm)==0 ; if GrimyTools.GetSpellDelivery(SpellForm)==2 ;beneficient aimed spell ; TargetRef=PlayerRef.GetReference() ; SpellForm.cast(TargetRef) ; endIf ;endif if SpellForm.IsHostile() if PlayerRef.IsInCombat() if GrimyTools.GetSpellType(SpellForm)==0 ;spell if GrimyTools.GetSpellDelivery(SpellForm) > 1 ;contact, aimed, target actor, or target location TargetRef = Game.GetPlayer().GetCombatTarget() if ((TargetRef) && (TargetRef.IsHostile())) SpellForm.cast(PlayerRef, TargetRef) endIf endIf endIf endIf endIf endFunction function IssueCommand(string CmdToProcess) if CmdToProcess=="Use" ;get item(nextword) if ItemFormList.HasForm(WordReturn) ;if player has x items in inventory ;use x items endif elseif WeaponFormList.HasForm(WordReturn) elseif ArmorFormList.HasForm(WordReturn) endif elseif ArrowFormList.HasForm(WordReturn) endFunction Link to comment Share on other sites More sharing options...
Recommended Posts