freeslot(
	"S_MAIMY_THOUGHTBUBBLE",
	"S_MAIMY_THOUGHTBUBBLE_ICON",
	"MT_MAIMY_THOUGHTBUBBLE",
	"MT_MAIMY_THOUGHTBUBBLE_ICON",
	"SPR_MBUB"
)

/*
	hey you, you wanna give Maimy more icons?
	the stuff here is what you need!
	copy-paste and edit until (example end)
*/


local iconinfo = {
	{"ponic", SPR_MBUB, C}, 
	{"fails", SPR_MBUB, B},
	{"buckles", SPR_MBUB, D}
}
--{sprite, frame} (not needed for skins, maimy handles those herself)

--needed to merge tables together
if not maimy_iconinfo
	rawset(_G, "maimy_iconinfo", {}) --this is the var used globally
end

local maimy_iconinfo = _G.maimy_iconinfo -- speed

for k, v in pairs(iconinfo) --the name of your local table
    maimy_iconinfo[k] = v --we add them to the global table for maimy to use!
end

--example end

local function GetMaimySkinTable()
    local skintable = {} --make our table
    for skin in skins.iterate --go through all the skins loaded
        if skin.name != "maimy" --not maimy, does she think of herself?
            table.insert(skintable, {skin.name, SPR_PLAY, A}) --add it to the table
        end
    end
	for i = 1, #maimy_iconinfo  --go through extra icons
		table.insert(skintable, maimy_iconinfo[i]) --add them to the table
	end
	return skintable --now we can use the prepared table
end

local function GetMaimyIcon(mo)
	if mo and mo.valid --make sure the mobj exists
		local sprites = GetMaimySkinTable() --prepare a table
		local icon = sprites[P_RandomRange(1, #sprites)][1] --pick a random entry in the table
		local extrasprite = false
		for i = 1, #sprites --go through the table
			if icon == sprites[i][1] --do the names match?
				if sprites[i][2] == SPR_PLAY --is it a player sprite?
					local skin = skins[icon]
					mo.sprite = sprites[i][2]
					mo.skin = icon 
					mo.sprite2 = SPR2_LIFE 
					mo.frame = sprites[i][3] 
					mo.color = skin.prefcolor
				else
					mo.sprite = sprites[i][2]
					mo.frame = sprites[i][3]
				end
			end
		end
	end
end

local function A_GetMaimySprite(mo)
	if mo and mo.valid --object exists?
		local icon = P_SpawnMobjFromMobj(mo, 0,0,0, MT_MAIMY_THOUGHTBUBBLE_ICON) --make our icon
		icon.tracer = mo --link it to the mobj
		mo.target = icon --the other way around too
		GetMaimyIcon(icon) --give it the icon
	end
end

states[S_MAIMY_THOUGHTBUBBLE] = {SPR_MBUB, A, -1, A_GetMaimySprite, 0, 0, S_NULL}
states[S_MAIMY_THOUGHTBUBBLE_ICON] = {SPR_MBUB, A, -1, nil, 0, 0, S_NULL}

mobjinfo[MT_MAIMY_THOUGHTBUBBLE] = {
	spawnstate = S_MAIMY_THOUGHTBUBBLE,
	radius = FRACUNIT,
	height = FRACUNIT,
	flags = MF_NOCLIP|MF_NOCLIPHEIGHT|MF_SCENERY|MF_RUNSPAWNFUNC|MF_NOGRAVITY
}

mobjinfo[MT_MAIMY_THOUGHTBUBBLE_ICON] = {
	spawnstate = S_MAIMY_THOUGHTBUBBLE_ICON,
	radius = FRACUNIT,
	height = FRACUNIT,
	dispoffset = 3,
	flags = MF_NOCLIP|MF_NOCLIPHEIGHT|MF_SCENERY|MF_NOGRAVITY
}

local function mgravitycheck(mo, offset) --because it sucks, i dont wanna explain
	offset = tonumber($)
	local flip = P_MobjFlip(mo)
	if offset --make sure it exists
		if flip == 1
			return mo.height + offset
		else
			return -offset
		end
	end
end

local function followtracer(mo)
	if mo and mo.valid
	and mo.tracer and mo.tracer.valid
		local t = mo.tracer --shorten
		local offset = mo.type == MT_MAIMY_THOUGHTBUBBLE and 10*t.scale or t.scale
		local sine = mo.type == MT_MAIMY_THOUGHTBUBBLE and 2*sin(mo.angle) or 0
		mo.angle = $+FixedAngle(FRACUNIT*2)
		P_TeleportMove(mo, t.x, t.y, t.z+mgravitycheck(t, offset)+sine)
		mo.scale = t.scale
		mo.eflags = (P_MobjFlip(t) == -1) and ($ | MFE_VERTICALFLIP) or ($ & ~MFE_VERTICALFLIP)
	end
end

addHook("MobjThinker", followtracer, MT_MAIMY_THOUGHTBUBBLE_ICON)
addHook("MobjThinker", followtracer, MT_MAIMY_THOUGHTBUBBLE)

addHook("PlayerThink", function(p)
	if p.mo and p.mo.valid and p.mo.skin == "maimy"
		if not p.mo.maimy --no table?
			local maimyvars = { --make one!
				idletimer = TICRATE*2,
				bubble = nil
			}
			p.mo.maimy = maimyvars
		end
		local maimy = p.mo.maimy --shorten
		if p.mo.state == S_PLAY_WAIT
			maimy.idletimer = $-1 or 0 --stop decrementing the timer when it hits 0
			if not maimy.idletimer
			and not maimy.bubble
				maimy.bubble = P_SpawnMobjFromMobj(p.mo, 0, 0, mgravitycheck(p.mo, 10), MT_MAIMY_THOUGHTBUBBLE)
				maimy.bubble.tracer = p.mo
			end
		else
			maimy.idletimer = TICRATE*2
			if maimy.bubble and maimy.bubble.valid --remove mobjs when not needed
				maimy.bubble.target.fuse = 1
				maimy.bubble.fuse = 1
				maimy.bubble = nil
			end
		end
	else
		-- reverbal: fixed validity issue (checking for p.mo)
		if p.mo and p.mo.maimy
			if p.mo.maimy.bubble and p.mo.maimy.bubble.valid --remove mobjs when not needed
				p.mo.maimy.bubble.target.fuse = 1
				p.mo.maimy.bubble.fuse = 1
				p.mo.maimy.bubble = nil
			end
			p.mo.maimy = nil --remove our table
		end
	end
end)