Sanja Alone
Цитата:
Поскольку у различных персонажей разные действия, для обработки этой ситуации мне пришлось влепить Switch. А как бы вызывать действия случайным образом (ес-но имеющиеся у конкретного персонажа).
|
Можно занести эти действия в массив, и перебирать его по Random (я также в примере сократил немного Switch

) :
Код:

With $AgentControl.Characters($fig)
.Show
Switch StringLower($fig)
Case 'offcat', 'dot', 'logo', 'rocky'
$PlayArr = StringSplit("Greeting|RestPose", "|")
.Play($PlayArr[Random(1, $PlayArr[0], 1)])
Case 'clippit', 'mnature'
$PlayArr = StringSplit("Congratulate|RestPose", "|")
.Play($PlayArr[Random(1, $PlayArr[0], 1)])
Case 'qmark'
$PlayArr = StringSplit("Welcome|RestPose", "|")
.Play($PlayArr[Random(1, $PlayArr[0], 1)])
Case 'angel'
$PlayArr = StringSplit("Halo|Glow|Glowoff", "|")
.Play($PlayArr[Random(1, $PlayArr[0], 1)])
Case 'blonde fem a'
$PlayArr = StringSplit("Blink|Wink|RestPose", "|")
.Play($PlayArr[Random(1, $PlayArr[0], 1)])
Case 'candy', 'max'
$PlayArr = StringSplit("Blink|RestPose", "|")
.Play($PlayArr[Random(1, $PlayArr[0], 1)])
Case 'paige'
.Play("Pointleftreturn")
Case 'reaper'
$PlayArr = StringSplit("Smile|RestPose", "|")
.Play($PlayArr[Random(1, $PlayArr[0], 1)])
Case 'scientist'
$PlayArr = StringSplit("Blackboard|Entropy|RestPose", "|")
.Play($PlayArr[Random(1, $PlayArr[0], 1)])
Case 'sharky'
;
Case Else
$PlayArr = StringSplit("Greet|RestPose", "|")
.Play($PlayArr[Random(1, $PlayArr[0], 1)])
EndSwitch
While _KeyPressed()=0
.MoveTo(Random(180,@DesktopWidth-180,1), Random(260,@DesktopHeight-260,1))
.Speak($msg)
WEnd
.Hide
.StopAll
Endwith
И ещё, цикл который удерживает персонажа, вызывает большую загрузку ЦП, я поставил паузу в 10 мc, и загрузки нет

-А что, при использовании Switch учитывается регистр букв? (я про StringLower).
Цитата:
Даже после Unload-а персонажа, в памяти продолжает висеть процесс AgentSvr.exe
|
Странно, у меня он (процесс) выгружается спустя пару секунд после Unload'а.
Цитата:
Если агент был запущен из бесконечного цикла, то, пока он не будет Unload-ен, основной цикл стоит на паузе.
|
Тоже заметил, поэтому я использовал AdlibEnable() до вызова функции с загрузкой персонажа.
Кстати, в системе есть более одного персонажа, благодаря
этой статье, я значительно улучшил скрипт - Я написал функцию которая собирает в массив пути к этим персонажам (если они найдены) -
_FiguresListToArray(), и затем на основе этих путей, методом случайного перебора (Random естественно), вызывается персонаж...
А также удалось осуществить “убийство” персонажа при любой активности пользователя (это я реализовал на основе наводок твоего примера - спасибо).
У меня такие вопросы:
1. Где можно узнать список действий определённого персонажа? (желательно средствами AutoIt'а выявить список действии для указанного персонажа).
2. Как можно, и можно ли вообще, регулировать скорость произношения речи? (или хотябы скорость печатания букв).
Вот новый скрипт -
Детектер лени - Я пока не знаю какой из существующих персонажей что умеет делать, поэтому присвоил им всем одинаковые действия (ошибку вроде не выдаёт) - можно было ещё перебирать оффисные персонажи (как и
в статье указанно), но я посчитал это лишнее, хватит пока и 4-ёх

.
Код:

HotKeySet("^e", "Quit")
TraySetIcon("shell32.dll", 160)
TraySetToolTip("Laziness Detecter (!)")
Dim $MessagesArr[11]
$MessagesArr[0] = 10
$MessagesArr[1] = "You are been lazy for a long time <%n>"
$MessagesArr[2] = "This is enough, start doing something >:( - you are lazy to much (%n)"
$MessagesArr[3] = "Hello!? Any one is home? why you are so lazy so long time? <%n> do somthing!"
$MessagesArr[4] = "Hi! Don't you fill like cow? Laziness is reason number 1 of why people die"
$MessagesArr[5] = "It's been over a <%n> time sense you touch your computer, touch it now!"
$MessagesArr[6] = "I can not wait for you so long (%n), I am going to shutdown myself.... beep.. beeep.. beeeeeep"
$MessagesArr[7] = "Hey man, are you forgot about me? Fine! I want to divorced"
$MessagesArr[8] = "You have no check your email for <%n> time, maybe there something intersteing?"
$MessagesArr[9] = "There is a virus on your computer! (it exists there for a long time <%n>) perform virus checking immediately!"
$MessagesArr[10] = "Hi! What's up dog? Don't pay attention; I am just stupid character that doesn't need attention! >:("
$MessagesFile = "LazyMessages.dat"
If FileExists($MessagesFile) And FileRead($MessagesFile) <> "" Then $MessagesArr = StringSplit(FileRead($MessagesFile), @LF)
$Idle = 0
$TotalTime = 0
$MinLaziness = 10
$MaxLaziness = 60
$LazyLimit = Random($MinLaziness, $MaxLaziness, 1)
$TimeStamp = TimerInit()
AdlibEnable("CheckLaziness", 10)
While 1
$Idle = _IdleWaitCommit(0)
TraySetIcon("shell32.dll", 160)
TrayTip("", "", 0)
$TimeStamp = TimerInit()
$Idle = 0
$TotalTime = 0
WEnd
Func CheckLaziness()
$TimeDiff = Round(TimerDiff($TimeStamp)/1000)
If $TimeDiff > $LazyLimit And $Idle = 0 Then
TraySetIcon("shell32.dll", 111)
$TotalTime += $TimeDiff
$LazyTime = _SecsToTime($TotalTime, ":")
$TextToSay = StringReplace($MessagesArr[Random(1, $MessagesArr[0], 1)], "%n", $LazyTime)
$SleepTime = Round((StringLen($TextToSay)/7)*1000)
If StringLen($TextToSay) < 7 Then $SleepTime = 5000
CharacterMsg($TextToSay, Random(100, @DesktopWidth-100, 1), Random(10, @DesktopHeight-150, 1), $SleepTime)
If @error Then TrayTip("You are lazy", $TextToSay, 5, 1)
$LazyLimit = Random($MinLaziness, $MaxLaziness, 1)
$TimeStamp = TimerInit()
EndIf
If $TimeDiff >= ($LazyLimit/2) Then TrayTip("", "", 0)
If $TimeDiff >= 5 And $LazyLimit > 5 Then TraySetIcon("shell32.dll", 111)
EndFunc
Func _SecsToTime($iTicks, $Delim)
If Number($iTicks) >= 0 Then
$iHours = Int($iTicks / 3600)
$iTicks = Mod($iTicks, 3600)
$iMins = Int($iTicks / 60)
$iSecs = Round(Mod($iTicks, 60))
If StringLen($iHours) = 1 Then $iHours = "0" & $iHours
If StringLen($iMins) = 1 Then $iMins = "0" & $iMins
If StringLen($iSecs) = 1 Then $iSecs = "0" & $iSecs
$Time = $iHours & $Delim & $iMins & $Delim & $iSecs
Return $Time
Else
SetError(1)
Return 0
EndIf
EndFunc
Func _IdleWaitCommit($idlesec, $TimeInit=0, $SleepTime=0)
Local $iSave, $LastInputInfo = DllStructCreate ("uint;dword")
DllStructSetData ($LastInputInfo, 1, DllStructGetSize ($LastInputInfo))
DllCall ("user32.dll", "int", "GetLastInputInfo", "ptr", DllStructGetPtr ($LastInputInfo))
Do
$iSave = DllStructGetData ($LastInputInfo, 2)
Sleep(100)
DllCall ("user32.dll", "int", "GetLastInputInfo", "ptr", DllStructGetPtr ($LastInputInfo))
If $SleepTime <> 0 And TimerDiff($TimeInit) >= $SleepTime Then ExitLoop
Until (DllStructGetData ($LastInputInfo, 2)-$iSave) > $idlesec
Return DllStructGetData ($LastInputInfo, 2)-$iSave
EndFunc
Func CharacterMsg($TextToSay, $MovexX=200, $MoveY=200, $Sleep=5000)
If $TextToSay = "" Then $TextToSay = "Oops! there was an Error!"
$FiguresArr = _FiguresListToArray()
If Not IsArray($FiguresArr) Then Return SetError(1)
$RandomFigure = Random(1, $FiguresArr[0], 1)
$FigurePath = $FiguresArr[$RandomFigure]
$FigureName = StringTrimRight(StringRegExpReplace($FigurePath, '^.*\\', ''), 4)
If Not FileExists($FigurePath) Then Return SetError(2)
$AgentControl = ObjCreate("Agent.Control.1")
$SinkObject = ObjEvent($AgentControl, "event_")
If Not Isobj($AgentControl) Then Return SetError(3)
$AgentControl.Connected = True
$AgentControl.Characters.Load($FigureName, $FigurePath)
$hCharacter = $AgentControl.Characters($FigureName)
With $hCharacter
.MoveTo($MovexX, $MoveY, 0)
.Show
.Speak($TextToSay)
.Play("Greet")
.Play("RestPose")
$SleepInit = TimerInit()
While TimerDiff($SleepInit) < $Sleep
If _IdleWaitCommit(0, $SleepInit, $Sleep) <> 0 Then ExitLoop
WEnd
.Hide
.StopAll
EndWith
$AgentControl.Characters.Unload($FigureName)
EndFunc
Func _FiguresListToArray()
$FiguresPath1 = @WindowsDir & "\MSAGENT\CHARS\"
$FiguresPath2 = @WindowsDir & "\srchasst\chars\"
If Not FileExists($FiguresPath1) And Not FileExists($FiguresPath2) Then Return SetError(1)
Local $FiguresArr[1]
;If FileExists($FiguresPath1 & "*.acs") Then
Local $FigureFind1 = FileFindFirstFile($FiguresPath1 & "*.acs")
If $FigureFind1 <> -1 Then
While 1
$CurrentFigure = FileFindNextFile($FigureFind1)
If @error Then ExitLoop
ReDim $FiguresArr[UBound($FiguresArr)+1]
$FiguresArr[0] += 1
$FiguresArr[UBound($FiguresArr)-1] = $FiguresPath1 & $CurrentFigure
WEnd
EndIf
FileClose($FigureFind1)
;EndIf
;If FileExists($FiguresPath2 & "*.acs") Then
Local $FigureFind2 = FileFindFirstFile($FiguresPath2 & "*.acs")
If $FigureFind2 <> -1 Then
While 1
$CurrentFigure = FileFindNextFile($FigureFind2)
If @error Then ExitLoop
ReDim $FiguresArr[UBound($FiguresArr)+1]
$FiguresArr[0] += 1
$FiguresArr[UBound($FiguresArr)-1] = $FiguresPath2 & $CurrentFigure
WEnd
EndIf
FileClose($FigureFind2)
;EndIf
Return $FiguresArr
EndFunc
Func Quit()
Exit
EndFunc
Напомню, что в данном примере (где $MinLaziness = 10, а $MaxLaziness = 60), нужно ничего не делать как минимум от 10-ти до 60-ти секунд чтобы увидеть результат этого скрипта

.