• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) ๐Ÿ”—Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans ๐Ÿ”—Click here to read the full interview.
  • The Hive's 22nd Icon Contest: Creep Abilities is now concluded, time to vote for your favourite set of icons! Click here to vote!
  • โœ… The POLL for Hive's Texturing Contest #34 is OPEN! Vote for the TOP 3 SKINS! ๐Ÿ”—Click here to cast your vote!
  • โœ… The POLL for Hive's Techtree Contest #20 is OPEN! Vote for the TOP 3 FACTIONS! ๐Ÿ”—Click here to cast your vote!

Emoji Chat System

This bundle is marked as pending. It has not been reviewed by a staff member yet.
Ladies and gentlemen , I present to you the merger between the lands of Warcraft and Discordia...

๐Ÿ˜๐Ÿ†๐Ÿ’ฆ THE EMOJI CHAT SYSTEM ๐Ÿ˜‚๐Ÿ”ฅ๐Ÿ’ฏ

Have you ever wanted to Pog at your teamates play? Perhaps LUL at his failure? Or simply dropping a naughty little Trollface after commiting a play so bad god had to awert his gaze?

Well now,
YOU CAN!
Image emojis and stickers of any variety, punch them in, and your players can express all their desired emotions in chat just like they do on our favourite social app
(Disclaimer: The author of this system is aware that people are unpredictable individuals or downright devious freaks. The author of this system does not take any responsibility for the inevitable NSFW imagery that will be added to maps by developers using this system. The author of this system, however, recognizes that it's based and poggers and really funny to do that, however, the author of this system would like to remain unbanned on Battle.net and The Hive Workshop , so for that reason, the author of this system must pretend that he condones this behavior.)




The system supports .blp images added to the game via import manager. The files are recommended to be uploaded with the resolution of max. 200x200px, simply for optimization purposes. These files can be so small that you can have hundreds of these chat emojis in your map without adding more than a megabyte of filesize. It's very compact. as long as you don't import unreasonably large images. They will look all the same when shrinked to the chat font size.

Detailed guide on how to import working emojis is inside the map file, but it's very easy. One only needs to copy 2 lines of code over and over, and change the "string" that triggers the desired Emoji display.


Code:
library CustomImageChat initializer Init

globals
    private constant real CHAT_X          = 0.020
    private constant real CHAT_BOTTOM_Y   = 0.220
    private constant real CHAT_LINE_H     = 0.0145
    private constant real CHAT_TEXT_W     = 0.430
    private constant real CHAT_TEXT_H     = 0.018
    private constant real CHAT_FONT_SIZE  = 0.011

    private constant integer CHAT_MAX_LINES   = 24
    private constant integer CHAT_MAX_ENTRIES = 40

    private constant real CHAT_IMAGE_W = CHAT_LINE_H * 3.00
    private constant real CHAT_IMAGE_H = CHAT_LINE_H * 3.00

    private constant real CHAT_DURATION = 15.00
    private constant real CHAT_FADE_TIME = 2.00

    constant integer CHAT_MAX_IMAGE_TYPES = 20

    private framehandle array ChatText
    private framehandle array ChatImage

    private string array EntryText
    private string array EntryImagePath
    private real array EntryAge
    private boolean array EntryIsImage
    private integer array EntryLines
    private integer EntryCount = 0

    private string array ImagePath
    string array ChatImageCommand
    integer ChatImageCommandCount = 0

    private boolean array PlayerAllChat

    private trigger ChatTrig = null
    private trigger ChatModeTrig = null
    private trigger SyncTrig = null
    private timer ChatTimer = null
endglobals

//settting up colors and sizes
//the colors are based on native player colors
//sourced from this thread: https://www.hiveworkshop.com/threads/24-1-player-color-codes.322502/
private function GetColoredPlayerName takes player p returns string
    local integer id = GetPlayerId(p)

    if id == 0 then
        return "|cffff0303" + GetPlayerName(p)
    elseif id == 1 then
        return "|cff0042ff" + GetPlayerName(p)
    elseif id == 2 then
        return "|cff1be7ba" + GetPlayerName(p)
    elseif id == 3 then
        return "|cff550081" + GetPlayerName(p)
    elseif id == 4 then
        return "|cfffefc00" + GetPlayerName(p)
    elseif id == 5 then
        return "|cfffe890d" + GetPlayerName(p)
    elseif id == 6 then
        return "|cff21bf00" + GetPlayerName(p)
    elseif id == 7 then
        return "|cffe45caf" + GetPlayerName(p)
    elseif id == 8 then
        return "|cff939596" + GetPlayerName(p)
    elseif id == 9 then
        return "|cff7ebff1" + GetPlayerName(p)
    elseif id == 10 then
        return "|cff106247" + GetPlayerName(p)
    elseif id == 11 then
        return "|cff4f2b05" + GetPlayerName(p)
    elseif id == 12 then
        return "|cff9c0000" + GetPlayerName(p)
    elseif id == 13 then
        return "|cff0000c3" + GetPlayerName(p)
    elseif id == 14 then
        return "|cff00ebff" + GetPlayerName(p)
    elseif id == 15 then
        return "|cffbd00ff" + GetPlayerName(p)
    elseif id == 16 then
        return "|cffecce87" + GetPlayerName(p)
    elseif id == 17 then
        return "|cfff7a58b" + GetPlayerName(p)
    elseif id == 18 then
        return "|cffbfff81" + GetPlayerName(p)
    elseif id == 19 then
        return "|cffdbb8eb" + GetPlayerName(p)
    elseif id == 20 then
        return "|cff4f5055" + GetPlayerName(p)
    elseif id == 21 then
        return "|cffecf0ff" + GetPlayerName(p)
    elseif id == 22 then
        return "|cff00781e" + GetPlayerName(p)
    elseif id == 23 then
        return "|cffa56f34" + GetPlayerName(p)
    endif

    return "|cffffffff" + GetPlayerName(p)
endfunction

private function CharWidth takes string c returns real
    if c == "i" or c == "l" or c == "." or c == ":" or c == "'" or c == " " or c == "!" then
        return 0.0022
    endif
    if c == "m" or c == "w" or c == "M" or c == "W" then
        return 0.0058
    endif
    return 0.0041
endfunction

private function TextWidth takes string s returns real
    local integer i = 0
    local real w = 0.000
    local string c

    loop
        exitwhen i >= StringLength(s)

        set c = SubString(s, i, i + 1)

        if c == "|" and SubString(s, i + 1, i + 2) == "c" then
            set i = i + 10
        elseif c == "|" and SubString(s, i + 1, i + 2) == "r" then
            set i = i + 2
        else
            set w = w + CharWidth(c)
            set i = i + 1
        endif
    endloop

    return w
endfunction

private function EstimateTextLines takes string s returns integer
    local real width = TextWidth(s) * 1.45
    local real maxWidth = 0.390
    local integer lines = R2I(width / maxWidth) + 1

    if lines < 1 then
        return 1
    endif

    return lines
endfunction

private function GetPrefix takes player p returns string
    if PlayerAllChat[GetConvertedPlayerId(p)] then
        return "|cffffffff[All] |r" + GetColoredPlayerName(p) + ":|r "
    endif

    return GetColoredPlayerName(p) + ":|r "
endfunction

private function GetEntryAlpha takes integer entryIndex returns integer
    local real fadeAge
    local integer alpha

    if EntryAge[entryIndex] < CHAT_DURATION - CHAT_FADE_TIME then
        return 255
    endif

    set fadeAge = EntryAge[entryIndex] - (CHAT_DURATION - CHAT_FADE_TIME)
    set alpha = 255 - R2I((fadeAge / CHAT_FADE_TIME) * 255.00)

    if alpha < 0 then
        return 0
    endif

    if alpha > 255 then
        return 255
    endif

    return alpha
endfunction

private function LocalPlayerShouldSee takes player sender returns boolean
    local player localPlayer = GetLocalPlayer()
    local integer senderPid = GetConvertedPlayerId(sender)

    if PlayerAllChat[senderPid] then
        set localPlayer = null
        return true
    endif

    if localPlayer == sender then
        set localPlayer = null
        return true
    endif

    if IsPlayerAlly(localPlayer, sender) then
        set localPlayer = null
        return true
    endif

    set localPlayer = null
    return false
endfunction

private function IsEmojiCommand takes string s returns boolean
    local integer i = 1

    loop
        exitwhen i > ChatImageCommandCount

        if s == ChatImageCommand[i] then
            return true
        endif

        set i = i + 1
    endloop

    return false
endfunction

private function HideAllFrames takes nothing returns nothing
    local integer i = 1

    loop
        exitwhen i > CHAT_MAX_ENTRIES
        call BlzFrameSetVisible(ChatText[i], false)
        call BlzFrameSetVisible(ChatImage[i], false)
        set i = i + 1
    endloop
endfunction

//chat renderer, frames move upwards to replicate native chat
//Image frames (emojis) use 3 |n lines worth of space and get moved respectively
//delete frames when they move too high as in natural chat function
private function RenderChat takes nothing returns nothing
    local integer i
    local integer usedLines = 0
    local real y
    local real imgX

    call HideAllFrames()

    set i = EntryCount

    loop
        exitwhen i <= 0
        exitwhen usedLines >= CHAT_MAX_LINES

        if usedLines + EntryLines[i] <= CHAT_MAX_LINES then
            set y = CHAT_BOTTOM_Y + I2R(usedLines) * CHAT_LINE_H

            if EntryIsImage[i] then
                set y = y + (CHAT_LINE_H * 2.00)
            else
                set y = y + ((CHAT_LINE_H - 0.0005) * I2R(EntryLines[i] - 1))
            endif

            call BlzFrameClearAllPoints(ChatText[i])
            call BlzFrameSetAbsPoint(ChatText[i], FRAMEPOINT_TOPLEFT, CHAT_X, y)
            call BlzFrameSetSize(ChatText[i], CHAT_TEXT_W, CHAT_TEXT_H * I2R(EntryLines[i]))
            call BlzFrameSetText(ChatText[i], EntryText[i])
            call BlzFrameSetAlpha(ChatText[i], GetEntryAlpha(i))
            call BlzFrameSetVisible(ChatText[i], true)

            if EntryIsImage[i] then
                set imgX = CHAT_X + (TextWidth(EntryText[i]) * 1.45) - 0.004

                call BlzFrameClearAllPoints(ChatImage[i])
                call BlzFrameSetAbsPoint(ChatImage[i], FRAMEPOINT_TOPLEFT, imgX, y)
                call BlzFrameSetSize(ChatImage[i], CHAT_IMAGE_W, CHAT_IMAGE_H)
                call BlzFrameSetTexture(ChatImage[i], EntryImagePath[i], 0, true)
                call BlzFrameSetAlpha(ChatImage[i], GetEntryAlpha(i))
                call BlzFrameSetVisible(ChatImage[i], true)
            endif

            set usedLines = usedLines + EntryLines[i]
        endif

        set i = i - 1
    endloop
endfunction

private function ShiftLeft takes nothing returns nothing
    local integer i = 1

    loop
        exitwhen i >= EntryCount

        set EntryText[i] = EntryText[i + 1]
        set EntryImagePath[i] = EntryImagePath[i + 1]
        set EntryAge[i] = EntryAge[i + 1]
        set EntryIsImage[i] = EntryIsImage[i + 1]
        set EntryLines[i] = EntryLines[i + 1]

        set i = i + 1
    endloop

    set EntryText[EntryCount] = ""
    set EntryImagePath[EntryCount] = ""
    set EntryAge[EntryCount] = 0.00
    set EntryIsImage[EntryCount] = false
    set EntryLines[EntryCount] = 0

    set EntryCount = EntryCount - 1
endfunction

private function AddTextEntry takes player sender, string msg returns nothing
        if not LocalPlayerShouldSee(sender) then
            return
        endif

        if EntryCount >= CHAT_MAX_ENTRIES then
            call ShiftLeft()
        endif

    set EntryCount = EntryCount + 1
    set EntryText[EntryCount] = GetPrefix(sender) + msg
    set EntryImagePath[EntryCount] = ""
    set EntryAge[EntryCount] = 0.00
    set EntryIsImage[EntryCount] = false
    set EntryLines[EntryCount] = EstimateTextLines(EntryText[EntryCount])

    call RenderChat()
endfunction

private function AddImageEntry takes player sender, string path returns nothing
        if not LocalPlayerShouldSee(sender) then
            return
        endif

        if EntryCount >= CHAT_MAX_ENTRIES then
            call ShiftLeft()
        endif

    set EntryCount = EntryCount + 1
    set EntryText[EntryCount] = GetPrefix(sender)
    set EntryImagePath[EntryCount] = path
    set EntryAge[EntryCount] = 0.00
    set EntryIsImage[EntryCount] = true
    set EntryLines[EntryCount] = 3

    call RenderChat()
endfunction

private function ChatPeriodic takes nothing returns nothing
    local integer i = 1

    loop
        exitwhen i > EntryCount

        set EntryAge[i] = EntryAge[i] + 0.05

            if EntryAge[i] >= CHAT_DURATION then
                call ShiftLeft()
                set i = i - 1
            endif

        set i = i + 1
    endloop

    call RenderChat()
endfunction

//commands that dont display a message when they are written
private function ChatConditions takes nothing returns boolean
    local string s = GetEventPlayerChatString()

        if s == "-allchat" then
            return false
        endif

        if s == "-allychat" then
            return false
        endif

        if IsEmojiCommand(s) then
            return false
        endif

    return true
endfunction

private function ChatActions takes nothing returns nothing
    call AddTextEntry(GetTriggerPlayer(), GetEventPlayerChatString())
endfunction

private function ChatModeActions takes nothing returns nothing
    local player p = GetTriggerPlayer()
    local string s = GetEventPlayerChatString()
    local integer pid = GetConvertedPlayerId(p)

        if s == "-allchat" then
            set PlayerAllChat[pid] = true
        elseif s == "-allychat" then
            set PlayerAllChat[pid] = false
        endif

    set p = null
endfunction

private function OnImageSync takes nothing returns nothing
    local integer id = S2I(BlzGetTriggerSyncData())

        if id > 0 and id <= CHAT_MAX_IMAGE_TYPES then
            call AddImageEntry(GetTriggerPlayer(), ImagePath[id])
        endif
endfunction

//variable setup for image paths
function CustomChat_RegisterImage takes integer id, string path returns nothing
    set ImagePath[id] = path
endfunction

//register caller
function CustomChat_RegisterCommand takes integer id, string command, string texture returns nothing
    set ChatImageCommand[id] = command
    call CustomChat_RegisterImage(id, texture)

        if id > ChatImageCommandCount then
            set ChatImageCommandCount = id
        endif
endfunction

//caller for entries
function CustomChat_SendImage takes player sender, integer imageId returns nothing
        if imageId > 0 and imageId <= CHAT_MAX_IMAGE_TYPES then
            call AddImageEntry(sender, ImagePath[imageId])
        endif
endfunction

//caller for sender
function ChatImageSend takes player sender, integer imageId returns nothing
    call CustomChat_SendImage(sender, imageId)
endfunction

//Creates the actual Frames that are used as chat system
//the chat system does not use native chat or game message
//the entire chat is made from Text frames to put in the images
private function Init takes nothing returns nothing
    local integer i = 0

    set ChatTrig = CreateTrigger()
    set ChatModeTrig = CreateTrigger()
    set SyncTrig = CreateTrigger()
    set ChatTimer = CreateTimer()

    set i = 1
    loop
        exitwhen i > CHAT_MAX_ENTRIES

        set ChatText[i] = BlzCreateFrameByType("TEXT", "CustomChatText", BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0), "", 0)
        call BlzFrameSetSize(ChatText[i], CHAT_TEXT_W, CHAT_TEXT_H)
        call BlzFrameSetFont(ChatText[i], "Fonts\\FRIZQT__.TTF", CHAT_FONT_SIZE, 0)
        call BlzFrameSetTextAlignment(ChatText[i], TEXT_JUSTIFY_LEFT, TEXT_JUSTIFY_TOP)
        call BlzFrameSetAlpha(ChatText[i], 255)
        call BlzFrameSetVisible(ChatText[i], false)

        set ChatImage[i] = BlzCreateFrameByType("BACKDROP", "CustomChatImage", BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0), "", 0)
        call BlzFrameSetAlpha(ChatImage[i], 255)
        call BlzFrameSetVisible(ChatImage[i], false)

        set i = i + 1
    endloop

    set i = 0
    loop
        exitwhen i >= bj_MAX_PLAYERS

        call TriggerRegisterPlayerChatEvent(ChatTrig, Player(i), "", false)

        call TriggerRegisterPlayerChatEvent(ChatModeTrig, Player(i), "-allchat", true)
        call TriggerRegisterPlayerChatEvent(ChatModeTrig, Player(i), "-allychat", true)

        call BlzTriggerRegisterPlayerSyncEvent(SyncTrig, Player(i), "CIMG", false)

        set i = i + 1
    endloop

    call TriggerAddCondition(ChatTrig, Condition(function ChatConditions))
    call TriggerAddAction(ChatTrig, function ChatActions)

    call TriggerAddAction(ChatModeTrig, function ChatModeActions)

    call TriggerAddAction(SyncTrig, function OnImageSync)

    call TimerStart(ChatTimer, 0.05, true, function ChatPeriodic)
endfunction

endlibrary


//=====================================================


library ChatImageCommands initializer Init requires CustomImageChat

globals
    private trigger ChatImageCommandTrig = null
endglobals

private function CommandActions takes nothing returns nothing
    local player p = GetTriggerPlayer()
    local string s = GetEventPlayerChatString()
    local integer i = 1

    loop
        exitwhen i > ChatImageCommandCount

        if s == ChatImageCommand[i] then
            call CustomChat_SendImage(p, i)
            set p = null
            return
        endif

        set i = i + 1
    endloop

    set p = null
endfunction


////////////////////////////////////////////////////
//              ๐—˜๐— ๐—ข๐—๐—œ ๐—ฆ๐—˜๐—ง๐—จ๐—ฃ ๐—›๐—˜๐—ฅ๐—˜                    //
//                                                 //
//                                                 //
//            ๐—–๐—ผ๐—บ๐—บ๐—ฎ๐—ป๐—ฑ ๐—น๐—ถ๐—ป๐—ฒ๐˜€ ๐˜๐—ผ ๐—ฐ๐—ผ๐—ฝ๐˜†                 //
//         ๐—ฎ๐—ฟ๐—ฒ ๐˜„๐—ฟ๐—ถ๐˜๐˜๐—ฒ๐—ป ๐—ถ๐—ป ๐˜๐—ฟ๐—ถ๐—ด๐—ด๐—ฒ๐—ฟ ๐—ฐ๐—ผ๐—บ๐—บ๐—ฒ๐—ป๐˜              //
//                                                //
//                                                //
////////////////////////////////////////////////////
private function Init takes nothing returns nothing
    local integer i = 0

    //Important: Remember that all import paths need to have double slash here if they have a slash in the import editor
    //Example: ๐˜„๐—ฎ๐—ฟ๐Ÿฏ๐—บ๐—ฎ๐—ฝ๐—œ๐—บ๐—ฝ๐—ผ๐—ฟ๐˜๐—ฒ๐—ฑ\๐—ž๐—˜๐—ž๐—ช.๐—ฏ๐—น๐—ฝ = ๐˜„๐—ฎ๐—ฟ๐Ÿฏ๐—บ๐—ฎ๐—ฝ๐—œ๐—บ๐—ฝ๐—ผ๐—ฟ๐˜๐—ฒ๐—ฑ\\๐—ž๐—˜๐—ž๐—ช.๐—ฏ๐—น๐—ฝ
    call CustomChat_RegisterCommand(1, "KEKW", "war3mapImported\\KEKW.blp")
    call CustomChat_RegisterCommand(2, "Sadge", "war3mapImported\\Sadge.blp")
    call CustomChat_RegisterCommand(3, "Poggers", "war3mapImported\\Poggers.blp")
    call CustomChat_RegisterCommand(4, "Trollface", "war3mapImported\\Trollface.blp")

    set ChatImageCommandTrig = CreateTrigger()

    loop
        exitwhen i >= bj_MAX_PLAYERS

        //these lines add the actual message detection into the trigger as an event
        //they read the string from above where you write which phrase becomes an emoji
        call TriggerRegisterPlayerChatEvent(ChatImageCommandTrig, Player(i), ChatImageCommand[1], true)
        call TriggerRegisterPlayerChatEvent(ChatImageCommandTrig, Player(i), ChatImageCommand[2], true)
        call TriggerRegisterPlayerChatEvent(ChatImageCommandTrig, Player(i), ChatImageCommand[3], true)
        call TriggerRegisterPlayerChatEvent(ChatImageCommandTrig, Player(i), ChatImageCommand[4], true)

        set i = i + 1
    endloop

    call TriggerAddAction(ChatImageCommandTrig, function CommandActions)
    //hide natural chat origin frame
    //do not touch this, crucial function
    //without this line, you get double chat
    call BlzFrameSetVisible(BlzGetOriginFrame(ORIGIN_FRAME_CHAT_MSG, 0), false)
endfunction

endlibrary
Contents

Emoji Chat System (Map)

Ahem, it's does not condone, since condone means accept/tolerate ๐Ÿ˜‚

Anyway, 5/5 based system!
omg thank u Daffa. What a throwback, last time you commented on my thing was 2 years ago when you told me about why it was lacking, and i didnt know how to use GUI indexer... and now 2 years later, you are 5/5 rating my Chat system... oh the journey :peasant-cheers-back:
 
Back
Top