freeslot("sfx_spechq")
sfxinfo[sfx_spechq].caption = "q"
freeslot("sfx_spechw")
sfxinfo[sfx_spechw].caption = "w"
freeslot("sfx_speche")
sfxinfo[sfx_speche].caption = "e"
freeslot("sfx_spechr")
sfxinfo[sfx_spechr].caption = "r"
freeslot("sfx_specht")
sfxinfo[sfx_specht].caption = "t"
freeslot("sfx_spechy")
sfxinfo[sfx_spechy].caption = "y"
freeslot("sfx_spechu")
sfxinfo[sfx_spechu].caption = "u"
freeslot("sfx_spechi")
sfxinfo[sfx_spechi].caption = "i"
freeslot("sfx_specho")
sfxinfo[sfx_specho].caption = "o"
freeslot("sfx_spechp")
sfxinfo[sfx_spechp].caption = "p"

freeslot("sfx_specha")
sfxinfo[sfx_specha].caption = "a"
freeslot("sfx_spechs")
sfxinfo[sfx_spechs].caption = "s"
freeslot("sfx_spechd")
sfxinfo[sfx_spechd].caption = "d"
freeslot("sfx_spechf")
sfxinfo[sfx_spechf].caption = "f"
freeslot("sfx_spechg")
sfxinfo[sfx_spechg].caption = "g"
freeslot("sfx_spechh")
sfxinfo[sfx_spechh].caption = "h"
freeslot("sfx_spechj")
sfxinfo[sfx_spechj].caption = "j"
freeslot("sfx_spechk")
sfxinfo[sfx_spechk].caption = "k"
freeslot("sfx_spechl")
sfxinfo[sfx_spechl].caption = "l"

freeslot("sfx_spechz")
sfxinfo[sfx_spechz].caption = "z"
freeslot("sfx_spechx")
sfxinfo[sfx_spechx].caption = "x"
freeslot("sfx_spechc")
sfxinfo[sfx_spechc].caption = "c"
freeslot("sfx_spechv")
sfxinfo[sfx_spechv].caption = "v"
freeslot("sfx_spechb")
sfxinfo[sfx_spechb].caption = "b"
freeslot("sfx_spechn")
sfxinfo[sfx_spechn].caption = "n"
freeslot("sfx_spechm")
sfxinfo[sfx_spechm].caption = "m"

//numbers
freeslot("sfx_spech0")
sfxinfo[sfx_spech0].caption = "0"
freeslot("sfx_spech1")
sfxinfo[sfx_spech1].caption = "1"
freeslot("sfx_spech2")
sfxinfo[sfx_spech2].caption = "2"
freeslot("sfx_spech3")
sfxinfo[sfx_spech3].caption = "3"
freeslot("sfx_spech4")
sfxinfo[sfx_spech4].caption = "4"
freeslot("sfx_spech5")
sfxinfo[sfx_spech5].caption = "5"
freeslot("sfx_spech6")
sfxinfo[sfx_spech6].caption = "6"
freeslot("sfx_spech7")
sfxinfo[sfx_spech7].caption = "7"
freeslot("sfx_spech8")
sfxinfo[sfx_spech8].caption = "8"
freeslot("sfx_spech9")
sfxinfo[sfx_spech9].caption = "9"

//special
freeslot("sfx_spcilq")
sfxinfo[sfx_spcilq].caption = "?"
freeslot("sfx_spcile")
sfxinfo[sfx_spcile].caption = "!"
freeslot("sfx_spcild")
sfxinfo[sfx_spcild].caption = "..."

rawset(_G, "TEXTTOSPEECH", {})

TEXTTOSPEECH = {
	[0] = sfx_specha,
	[1] = sfx_spechb,
	[2] = sfx_spechc,
	[3] = sfx_spechd,
	[4] = sfx_speche,
	[5] = sfx_spechf,
	[6] = sfx_spechg,
	[7] = sfx_spechh,
	[8] = sfx_spechi,
	[9] = sfx_spechj,
	[10] = sfx_spechk,
	[11] = sfx_spechl,
	[12] = sfx_spechm,
	[13] = sfx_spechn,
	[14] = sfx_specho,
	[15] = sfx_spechp,
	[16] = sfx_spechq,
	[17] = sfx_spechr,
	[18] = sfx_spechs,
	[19] = sfx_specht,
	[20] = sfx_spechu,
	[21] = sfx_spechv,
	[22] = sfx_spechw,
	[23] = sfx_spechx,
	[24] = sfx_spechy,
	[25] = sfx_spechz,
	[26] = sfx_spech0,
	[27] = sfx_spech1,
	[28] = sfx_spech2,
	[29] = sfx_spech3,
	[30] = sfx_spech4,
	[31] = sfx_spech5,
	[32] = sfx_spech6,
	[33] = sfx_spech7,
	[34] = sfx_spech8,
	[35] = sfx_spech9
}

freeslot("MT_SPEECHBUBBLE")
freeslot("S_SPEECHBUBBLE")
freeslot("SPR_SPCH")

addHook("PlayerSpawn", function(p)
if p.mo != nil and p != nil
if p.mo.valid and p.valid then
A_resetvalues(p)
end
end
end)

addHook("PlayerThink", function(p)
if p.mo != nil and p != nil
if p.mo.valid and p.valid then

if p.spechstring != nil


if p.spechcooldown == 0
p.spechnumb = $ + 1
p.spechcooldown = p.desirecooldown
//checks if sentence is over
if p.spechnumb > string.len(p.spechstring)
if p.bubble.valid then
P_RemoveMobj(p.bubble)
end
A_resetvalues(p)
end

if p.sentence == true
 
local letter = string.lower(string.sub(p.spechstring, p.spechnumb, p.spechnumb))
//detect if its a number or letter
if tonumber(letter) == nil

if TEXTTOSPEECH[string.byte(letter) - 97] != nil then
S_StartSound(p.mo, TEXTTOSPEECH[string.byte(letter) - 97])
if letter == "y"
p.spechcooldown = $ + 2
end
if letter == "w"
p.spechcooldown = $ + 6
end


elseif TEXTTOSPEECH[string.byte(letter) - 97] == nil
p.spechcooldown = 5
end

//special characters
if letter == "!"
S_StartSound(p.mo, sfx_spcile)
end

if letter == "?"
S_StartSound(p.mo, sfx_spcilq)
end

if letter == "."
A_sentence(p, 0, 3)
if p.txtcheck == "..."
S_StartSound(p.mo, sfx_spcild)
p.spechnumb = $ + 2
end
end
//end

elseif tonumber(letter) != nil then
S_StartSound(p.mo, TEXTTOSPEECH[26 + tonumber(letter)])

end
end
end

if p.spechcooldown > 0
p.spechcooldown = $ - 1
end

end

end
end
end)

addHook("PlayerMsg", function(p, typ, tar, msg)
if p.mo != nil and p != nil
if p.mo.valid and p.valid then
if p.voice == true
p.spechstring = tostring(msg)
p.sentence = true
p.spechnumb = 0

if p.bubble == nil
local bubble = P_SpawnMobj(p.mo.x, p.mo.y, p.mo.z + p.mo.height, MT_SPEECHBUBBLE)
bubble.target = p.mo
p.bubble = bubble
end

end
end
end
end)

local function speechbubble(mobj)

if mobj.target == nil
P_RemoveMobj(mobj)
end
if mobj.valid then
P_SetOrigin(mobj, mobj.target.x, mobj.target.y, mobj.target.z + mobj.target.height + 5*FRACUNIT)
end
end

addHook("MobjThinker", speechbubble, MT_SPEECHBUBBLE)

function A_resetvalues(p)
p.spechnumb = 0
p.sentence = false
p.spechstring = nil
p.spechcooldown = 0
p.bubble = nil
p.txtcheck = nil
if p.desirecooldown == nil
p.desirecooldown = 10
p.voice = true
end
end

function A_sentence(p, bck, frnt)
p.txtcheck =  string.sub(p.spechstring, p.spechnumb + bck, p.spechnumb + frnt)
end