SHOW:
|
|
- or go back to the newest paste.
| 1 | - | local print = epoe.Print |
| 1 | + | |
| 2 | - | local me = me |
| 2 | + | local sounddict = {
|
| 3 | - | -- config / gmod specific |
| 3 | + | ["hi"] = "", |
| 4 | ["hi there"] = "", | |
| 5 | - | local SOUNDS = {
|
| 5 | + | ["eat me"] = "", |
| 6 | - | hi = "ambient/levels/prison/radio_random11.wav", |
| 6 | + | ["eat"] = "", |
| 7 | - | oh = "ambient/energy/spark3.wav", |
| 7 | + | ["an eye for an eye"] = "", |
| 8 | - | boop = "buttons/button16.wav", |
| 8 | + | ["an eye for an apple or banana"] = "", |
| 9 | - | kick = "weapons/crossbow/hitbod1.wav", |
| 9 | + | ["orange"] = "", |
| 10 | - | beep = "npc/attack_helicopter/aheli_crash_alert2.wav", |
| 10 | + | ["cactus"] = "", |
| 11 | - | snare = "physics/flesh/flesh_strider_impact_bullet3.wav", |
| 11 | + | ["cactus please"] = "", |
| 12 | - | wood = "physics/wood/wood_box_impact_bullet4.wav" |
| 12 | + | ["no sir"] = "", |
| 13 | } | |
| 14 | ||
| 15 | - | local MODIFIERS = {
|
| 15 | + | local testphraselist = {
|
| 16 | - | ["&"] = {
|
| 16 | + | "hello", |
| 17 | - | args = {
|
| 17 | + | "say hi", |
| 18 | - | function(dsp) return math.Clamp(tonumber(dsp) or 0, 0, 128) end |
| 18 | + | "hi there", |
| 19 | - | }, |
| 19 | + | "oh hi there", |
| 20 | - | |
| 20 | + | "an eye for an eye for an eye for an apple or banana", |
| 21 | - | start = function(self, dsp) |
| 21 | + | "an eye for an apple or banana", |
| 22 | - | LocalPlayer():SetDSP(dsp) |
| 22 | + | "cactus orange no sir", |
| 23 | - | end, |
| 23 | + | "eat me hi", |
| 24 | - | |
| 24 | + | |
| 25 | - | stop = function(self, dsp) |
| 25 | + | |
| 26 | - | LocalPlayer():SetDSP(0) |
| 26 | + | local soundtree = {}
|
| 27 | - | end, |
| 27 | + | local soundtree_filekey = newproxy and newproxy() or {}
|
| 28 | - | }, |
| 28 | + | for sound_patt, sound_file in pairs(sounddict) do |
| 29 | - | ["=="] = {
|
| 29 | + | local currnode = soundtree |
| 30 | - | args = {
|
| 30 | + | for part in string.gmatch(sound_patt, "([a-z_]+)") do |
| 31 | - | function(time) return tonumber(time) or 1 end |
| 31 | + | -- TODO: preprocess part to ignore case and such |
| 32 | - | }, |
| 32 | + | currnode[part] = currnode[part] or {}
|
| 33 | - | |
| 33 | + | currnode = currnode[part] |
| 34 | - | init = function(self, time) |
| 34 | + | end |
| 35 | - | self.duration = time |
| 35 | + | currnode[soundtree_filekey] = string.gsub(sound_patt, " ", "_")..".wav" |
| 36 | - | end, |
| 36 | + | |
| 37 | - | }, |
| 37 | + | |
| 38 | - | ["--"] = {
|
| 38 | + | function stuff(soundtree, phrase) |
| 39 | - | args = {
|
| 39 | + | -- TODO: preprocess phrase to ignore case and such |
| 40 | - | function(stop_percent) return tonumber(stop_percent) or 100 end |
| 40 | + | |
| 41 | - | }, |
| 41 | + | local foundlist = {}
|
| 42 | - | |
| 42 | + | |
| 43 | - | init = function(self, stop_percent) |
| 43 | + | local stack_i = 0 |
| 44 | - | self.duration = self.duration * (stop_percent / 100) |
| 44 | + | local stack_eposlist = { [0] = 1 }
|
| 45 | - | end, |
| 45 | + | local stack_nodelist = { [0] = soundtree }
|
| 46 | - | }, |
| 46 | + | local complete, atend = false, false |
| 47 | - | ["="] = {
|
| 47 | + | local backtrack = false |
| 48 | - | args = {
|
| 48 | + | repeat |
| 49 | - | function(time) return tonumber(time) or 0 end |
| 49 | + | local spos = stack_eposlist[stack_i] |
| 50 | - | }, |
| 50 | + | local node = stack_nodelist[stack_i] |
| 51 | - | |
| 51 | + | stack_i = stack_i+1 |
| 52 | - | init = function(self, time) |
| 52 | + | -- get next word |
| 53 | - | self.duration = time |
| 53 | + | local word_s, word_e, mods = string.find(phrase, "([a-z_]+)(%p%d)+", spos, true) |
| 54 | - | end, |
| 54 | + | if word_s then |
| 55 | - | }, |
| 55 | + | -- we have a next word |
| 56 | - | ["%"] = {
|
| 56 | + | local word = string.sub(phrase, word_s, word_e) |
| 57 | - | args = {
|
| 57 | + | local subnode = node[word] -- (you could do pattern matching here) |
| 58 | - | function(pitch) return math.Clamp(tonumber(pitch) or 100, 0, 255) end, |
| 58 | + | if subnode then |
| 59 | - | function(time) return tonumber(time) or 0 end, |
| 59 | + | -- we have a pattern that matches this next word |
| 60 | - | }, |
| 60 | + | -- (could be first, middle or last word in pattern!) |
| 61 | - | |
| 61 | + | stack_eposlist[stack_i] = word_e+1 |
| 62 | - | init = function(self, pitch, time) |
| 62 | + | stack_nodelist[stack_i] = subnode |
| 63 | - | self.duration = self.duration / (pitch / 100) |
| 63 | + | -- continue |
| 64 | - | self.duration = self.duration + time |
| 64 | + | else |
| 65 | - | end, |
| 65 | + | -- there is no continuing pattern that matches this word |
| 66 | - | |
| 66 | + | if stack_i == 1 then |
| 67 | - | think = function(self, pitch, time) |
| 67 | + | -- this is the first word or next unmatched word and no pattern starts with it |
| 68 | - | if self.csp then |
| 68 | + | -- so jump to next word |
| 69 | - | self.csp:ChangePitch(pitch, time) |
| 69 | + | stack_i = 0 |
| 70 | - | end |
| 70 | + | stack_eposlist[0] = word_e+1 |
| 71 | - | end, |
| 71 | + | else |
| 72 | - | }, |
| 72 | + | -- we were matching a pattern, see what comes of it |
| 73 | - | ["^"] = {
|
| 73 | + | -- (this word did not continue any pattern, so it's not considered) |
| 74 | - | args = {
|
| 74 | + | backtrack = true |
| 75 | - | function(volume) return math.Clamp(tonumber(volume) or 100, 0, 100) end, |
| 75 | + | end |
| 76 | - | function(time) return tonumber(time) or 0 end, |
| 76 | + | end |
| 77 | - | }, |
| 77 | + | else |
| 78 | - | |
| 78 | + | -- there is no next word, check for patterns |
| 79 | - | think = function(self, volume, time) |
| 79 | + | -- (last few words may be rechecked if there is no sound for their nodes) |
| 80 | - | if self.csp then |
| 80 | + | atend = true |
| 81 | - | if self.source_entity == LocalPlayer() then |
| 81 | + | backtrack = true |
| 82 | - | volume = volume / 2 |
| 82 | + | end |
| 83 | - | end |
| 83 | + | if backtrack then |
| 84 | - | |
| 84 | + | -- find the longest pattern on the stack that has a sound associated |
| 85 | - | self.csp:ChangeVolume(volume / 100, time) |
| 85 | + | for stack_j = stack_i-1, 1, -1 do |
| 86 | - | end |
| 86 | + | -- work backwards through each word to see if it has a sound |
| 87 | - | end, |
| 87 | + | local node = stack_nodelist[stack_j] |
| 88 | - | } |
| 88 | + | local soundfile = node[soundtree_filekey] |
| 89 | if soundfile then | |
| 90 | -- this word has a sound | |
| 91 | - | local function PLAY_SOUND(self) |
| 91 | + | table.insert(foundlist, soundfile) |
| 92 | - | local csp = CreateSound(me, self.path) |
| 92 | + | -- TODO: handle mods here |
| 93 | - | csp:PlayEx(1, 0) |
| 93 | + | |
| 94 | - | self.source_entity = me |
| 94 | + | if stack_j == stack_i and atend then |
| 95 | - | self.csp = csp |
| 95 | + | -- we consumed the last word |
| 96 | complete = true | |
| 97 | else | |
| 98 | - | local function STOP_SOUND(self) |
| 98 | + | -- start searching for new patterns |
| 99 | - | if self.csp then |
| 99 | + | stack_i = 0 |
| 100 | - | self.csp:Stop() |
| 100 | + | -- resume from word after longest pattern with a sound |
| 101 | - | end |
| 101 | + | stack_eposlist[0] = stack_eposlist[stack_j+1] |
| 102 | end | |
| 103 | -- stop backtracking | |
| 104 | - | local function GET_DURATION(self) |
| 104 | + | break |
| 105 | - | return SoundDuration(self.path) or 0 |
| 105 | + | end |
| 106 | end | |
| 107 | backtrack, atend = false, false | |
| 108 | - | -- |
| 108 | + | end |
| 109 | - | local cache = {}
|
| 109 | + | until complete |
| 110 | ||
| 111 | - | local function parse(str) |
| 111 | + | return foundlist |
| 112 | - | if cache[str] then return cache[str] end |
| 112 | + | |
| 113 | - | |
| 113 | + | |
| 114 | - | local out = {}
|
| 114 | + | for testphrase_i = 1, #testphraselist do |
| 115 | - | |
| 115 | + | local testphrase = testphraselist[testphrase_i] |
| 116 | - | -- lowercase it so we don't have to deal with case sensitivity |
| 116 | + | local out = stuff(soundtree, testphrase) |
| 117 | - | str = str:lower() |
| 117 | + | for sound_i = 1, #out do |
| 118 | - | |
| 118 | + | print(out[sound_i]) |
| 119 | - | -- add a last space so it matches the end as well |
| 119 | + | end |
| 120 | - | str = str .. " " |
| 120 | + | end |