• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[Snippet] BlizzardMessage

Level 16
Joined
Dec 15, 2011
Messages
1,423
JASS:
library BlizzardMessage /* v1.0.0.4
*************************************************************************************
*
*   For creating Blizzard-like messages with a variety of sounds.
*
*************************************************************************************
*
*   Credits
*
*       Vexorian
*       -----------------------
*
*           The original SimError
*
*
*       Maker
*       -----------------------
*
*           Sound label help
*
************************************************************************************
*
*   Function
*   -----------------------
*
*        function BlizzardMessage takes string msg, string colorCode, integer soundLabel, player forPlayer returns nothing
*
*   Description
*   -----------------------
*
*       This function creates a Blizzard-like message with a sound for a player.
*
*   Takes
*   -----------------------
*
*       string msg
*           -   The message to be displayed.
*
*       string colorCode
*           -   Adds a color for the message through an ARBG color code. A null value creates a normal white text.
*       
*       integer soundLabel
*           -   The sound to be played.
*
*       player forPlayer
*           -   The player that receives the message.
*
*   Returns
*   -----------------------
*
*       nothing
*
*************************************************************************************
*
*   Function
*   -----------------------
*
*        function BlizzardMessageTimed takes string msg, string colorCode, real dur, integer soundLabel, player forPlayer returns nothing
*
*   Description
*   -----------------------
*
*       This function creates a timed Blizzard-like message with a sound for a player.
*
*   Takes
*   -----------------------
*
*       string msg
*           -   The message to be displayed.
*
*       string colorCode
*           -   Adds a color for the message through an ARBG color code. A null value creates a normal white text.
* 
*       real dur
*           -   The duration of the message.
*
*       integer soundLabel
*           -   The sound to be played.
*
*       player forPlayer
*           -   The player that receives the message.
*
*   Returns
*   -----------------------
*
*       nothing
*
*************************************************************************************
*
*   SETTINGS
*   -----------------------
*
*/
    globals
    
        constant real MSG_DURATION = 2.00 //Message Duration
    
        /*************************************************************************************
        *
        *   Sound Labels
        *
        *************************************************************************************/
        
        constant integer ALLY_HERO_DIES_HUMAN = 0
        constant integer ALLY_HERO_DIES_NAGA = 1
        constant integer ALLY_HERO_DIES_NIGHTELF = 2
        constant integer ALLY_HERO_DIES_ORC = 3
        constant integer ALLY_HERO_DIES_UNDEAD = 4
        constant integer ALLY_TOWN_UNDER_ATTACK_HUMAN = 5
        constant integer ALLY_TOWN_UNDER_ATTACK_NAGA = 6
        constant integer ALLY_TOWN_UNDER_ATTACK_NIGHTELF = 7
        constant integer ALLY_TOWN_UNDER_ATTACK_ORC = 8
        constant integer ALLY_TOWN_UNDER_ATTACK_UNDEAD = 9
        constant integer ALLY_UNDER_ATTACK_HUMAN = 10
        constant integer ALLY_UNDER_ATTACK_NAGA = 11
        constant integer ALLY_UNDER_ATTACK_NIGHTELF = 12
        constant integer ALLY_UNDER_ATTACK_ORC = 13
        constant integer ALLY_UNDER_ATTACK_UNDEAD = 14
        constant integer ARRANGED_TEAM_INVITATION = 15
        constant integer AUTO_CAST_BUTTON_CLICK = 16
        constant integer CANT_PLACE_HUMAN = 17
        constant integer CANT_PLACE_NAGA = 18
        constant integer CANT_PLACE_NIGHTELF = 19
        constant integer CANT_PLACE_ORC = 20
        constant integer CANT_PLACE_UNDEAD = 21
        constant integer CANT_ROOT_NIGHTELF = 22
        constant integer CHATROOM_TIMER_TICK = 23
        constant integer CLAN_INVITATION = 24
        constant integer CONSTRUCTING_BUILDING_DEFAULT = 25
        constant integer CONSTRUCTING_BUILDING_NAGA = 26
        constant integer CONSTRUCTING_BUILDING_NIGHTELF = 27
        constant integer CONSTRUCTING_BUILDING_ORC = 28
        constant integer CONSTRUCTING_BUILDING_UNDEAD = 29
        constant integer CREEP_AGGRO = 30
        constant integer ERROR_MESSAGE = 31
        constant integer GAME_FOUND = 32
        constant integer GLUE_SCREEN_CLICK = 33
        constant integer GOLD_MINE_COLLAPSE_HUMAN = 34
        constant integer GOLD_MINE_COLLAPSE_NAGA = 35
        constant integer GOLD_MINE_COLLAPSE_NIGHTELF = 36
        constant integer GOLD_MINE_COLLAPSE_ORC = 37
        constant integer GOLD_MINE_COLLAPSE_UNDEAD = 38
        constant integer GOLD_MINE_LOW_GENERIC = 39
        constant integer GOLD_MINE_LOW_HUMAN = 40
        constant integer GOLD_MINE_LOW_NAGA = 41
        constant integer GOLD_MINE_LOW_NIGHTELF = 42
        constant integer GOLD_MINE_LOW_ORC = 43
        constant integer GOLD_MINE_LOW_UNDEAD = 44
        constant integer GOOD_JOB = 45
        constant integer HERO_DIES_GENERIC = 46
        constant integer HERO_DIES_HUMAN = 47
        constant integer HERO_DIES_NAGA = 48
        constant integer HERO_DIES_NIGHTELF = 49
        constant integer HERO_DIES_ORC = 50
        constant integer HERO_DIES_UNDEAD = 51
        constant integer HINT = 52
        constant integer IN_GAME_CHAT_WHAT = 53
        constant integer INTERFACE_CLICK = 54
        constant integer INTERFACE_ERROR = 55
        constant integer INVENTORY_FULL_HUMAN = 56
        constant integer INVENTORY_FULL_NAGA = 57
        constant integer INVENTORY_FULL_NIGHTELF = 58
        constant integer INVENTORY_FULL_ORC = 59
        constant integer INVENTORY_FULL_UNDEAD = 60
        constant integer ITEM_DROP = 61
        constant integer ITEM_GET = 62
        constant integer ITEM_REWARD = 63
        constant integer JOB_DONE_SOUND_HUMAN = 64
        constant integer JOB_DONE_SOUND_NAGA = 65
        constant integer JOB_DONE_SOUND_NIGHTELF = 66
        constant integer JOB_DONE_SOUND_ORC = 67
        constant integer JOB_DONE_SOUND_UNDEAD = 68
        constant integer MAP_PING = 69
        constant integer MENU_BUTTON_CLICK = 70
        constant integer NEW_TOURNAMENT = 71
        constant integer NO_FOOD_HUMAN = 72
        constant integer NO_FOOD_NAGA = 73
        constant integer NO_FOOD_NIGHTELF = 74
        constant integer NO_FOOD_ORC = 75
        constant integer NO_FOOD_UNDEAD = 76
        constant integer NO_GOLD_GENERIC = 77
        constant integer NO_GOLD_HUMAN = 78
        constant integer NO_GOLD_NAGA = 79
        constant integer NO_GOLD_NIGHTELF = 80
        constant integer NO_GOLD_ORC = 81
        constant integer NO_GOLD_UNDEAD = 82
        constant integer NO_LUMBER_HUMAN = 83
        constant integer NO_LUMBER_NAGA = 84
        constant integer NO_LUMBER_NIGHTELF = 85
        constant integer NO_LUMBER_ORC = 86
        constant integer NO_LUMBER_UNDEAD = 87
        constant integer NO_MANA_GENERIC = 88
        constant integer NO_MANA_HUMAN = 89
        constant integer NO_MANA_NAGA = 90
        constant integer NO_MANA_NIGHTELF = 91
        constant integer NO_MANA_ORC = 92
        constant integer NO_MANA_UNDEAD = 93
        constant integer OFF_BLIGHT_UNDEAD = 94
        constant integer PAUSE_GAME = 95
        constant integer PLACE_BUILDING_DEFAULT = 96
        constant integer QUEST_COMPLETED = 97
        constant integer QUEST_FAILED = 98
        constant integer QUEST_LOG_MODIFIED = 99
        constant integer QUEST_NEW = 100
        constant integer QUEST_UPDATE = 101
        constant integer RALLY_POINT_PLACE = 102
        constant integer RESCUE = 103
        constant integer RESEARCH_COMPLETE_GENERIC = 104
        constant integer RESEARCH_COMPLETE_HUMAN = 105
        constant integer RESEARCH_COMPLETE_NAGA = 106
        constant integer RESEARCH_COMPLETE_NIGHTELF = 107
        constant integer RESEARCH_COMPLETE_ORC = 108
        constant integer RESEARCH_COMPLETE_UNDEAD = 109
        constant integer SCORE_SCREEN_TAB_CLICK = 110
        constant integer SECRET_FOUND = 111
        constant integer SUB_GROUP_SELECTION_CHANGE = 112
        constant integer TOWN_ATTACK_GENERIC = 113
        constant integer TOWN_ATTACK_HUMAN = 114
        constant integer TOWN_ATTACK_NAGA = 115
        constant integer TOWN_ATTACK_NIGHTELF = 116
        constant integer TOWN_ATTACK_ORC = 117
        constant integer TOWN_ATTACK_UNDEAD = 118
        constant integer UNDER_ATTACK_HUMAN = 119
        constant integer UNDER_ATTACK_NAGA = 120
        constant integer UNDER_ATTACK_NIGHTELF = 121
        constant integer UNDER_ATTACK_ORC = 122
        constant integer UNDER_ATTACK_UNDEAD = 123
        constant integer UPGRADE_COMPLETE_GENERIC = 124
        constant integer UPGRADE_COMPLETE_HUMAN = 125
        constant integer UPGRADE_COMPLETE_NAGA = 126
        constant integer UPGRADE_COMPLETE_NIGHTELF = 127
        constant integer UPGRADE_COMPLETE_ORC = 128
        constant integer UPGRADE_COMPLETE_UNDEAD = 129
        constant integer UPKEEP_LEVEL = 130
        constant integer WARNING = 131
        constant integer WAYPOINT = 132
    
        /* private */ string array SOUND_LABEL
    endglobals
    
/*
************************************************************************************
*/

    function BlizzardMessage takes string msg, string colorCode, integer soundLabel, player forPlayer returns nothing
        local sound snd
        local string s
    
        debug if soundLabel >= 0 and soundLabel <= 132 and forPlayer != null then
        
            set snd = CreateSoundFromLabel (SOUND_LABEL[soundLabel], false, false, false, 10, 10)
            
            if colorCode != null then
                set s = "|r"
            else
                set colorCode = ""
                set s = ""
            endif
            
            if GetLocalPlayer () == forPlayer then
                call ClearTextMessages ()
                call DisplayTimedTextToPlayer (forPlayer, 0.52, 0.96, MSG_DURATION, "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n" + colorCode + msg + s)
                call StartSound (snd)
            endif
            
            if s != null then
                set s = ""
            endif
            
            set snd = null
            
        debug else
            debug if msg == null
                debug call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "[BlizzardMessage] [BlizzardMessage] Null message")
            debug endif            
            debug if forPlayer == null
                debug call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "[BlizzardMessage] [BlizzardMessage] Null forPlayer")
            debug endif
            debug if soundLabel < 0 or soundLabel > 132
                debug call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "[BlizzardMessage] [BlizzardMessage] Invalid sound label")
            debug endif
        debug endif
    endfunction
    
    function BlizzardMessageTimed takes string msg, string colorCode, real dur, integer soundLabel, player forPlayer returns nothing
        local sound snd
        local string s
    
        debug if soundLabel >= 0 and soundLabel <= 132 and forPlayer != null then
        
            set snd = CreateSoundFromLabel (SOUND_LABEL[soundLabel], false, false, false, 10, 10)
            
            if colorCode != null then
                set s = "|r"
            else
                set colorCode = ""
                set s = ""
            endif
            
            if GetLocalPlayer () == forPlayer then
                call ClearTextMessages ()
                call DisplayTimedTextToPlayer (forPlayer, 0.52, 0.96, dur, "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n" + colorCode + msg + s)
                call StartSound (snd)
            endif
            
            if s != null then
                set s = ""
            endif
            
            set snd = null
            
        debug else
            debug if msg == null
                debug call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "[BlizzardMessage] [BlizzardMessage] Null message")
            debug endif            
            debug if forPlayer == null
                debug call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "[BlizzardMessage] [BlizzardMessage] Null forPlayer")
            debug endif
            debug if soundLabel < 0 or soundLabel > 132
                debug call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "[BlizzardMessage] [BlizzardMessage] Invalid sound label")
            debug endif
        debug endif
    endfunction

    private module BMInit
        private static method onInit takes nothing returns nothing
            call init()
        endmethod
    endmodule
    
    private struct InitStruct extends array
        private static method init takes nothing returns nothing
            set SOUND_LABEL[0] = "AllyHeroDiesHuman"
            set SOUND_LABEL[1] = "AllyHeroDiesNaga"
            set SOUND_LABEL[2] = "AllyHeroDiesNightElf"
            set SOUND_LABEL[3] = "AllyHeroDiesOrc"
            set SOUND_LABEL[4] = "AllyHeroDiesUndead"
            set SOUND_LABEL[5] = "AllyTownUnderAttackHuman"
            set SOUND_LABEL[6] = "AllyTownUnderAttackNaga"
            set SOUND_LABEL[7] = "AllyTownUnderAttackNightElf"
            set SOUND_LABEL[8] = "AllyTownUnderAttackOrc"
            set SOUND_LABEL[9] = "AllyTownUnderAttackUndead"
            set SOUND_LABEL[10] = "AllyUnderAttackHuman"
            set SOUND_LABEL[11] = "AllyUnderAttackNaga"
            set SOUND_LABEL[12] = "AllyUnderAttackNightElf"
            set SOUND_LABEL[13] = "AllyUnderAttackOrc"
            set SOUND_LABEL[14] = "AllyUnderAttackUndead"
            set SOUND_LABEL[15] = "ArrangedTeamInvitation"
            set SOUND_LABEL[16] = "AutoCastButtonClick"
            set SOUND_LABEL[17] = "CantPlaceHuman"
            set SOUND_LABEL[18] = "CantPlaceNaga"
            set SOUND_LABEL[19] = "CantPlaceNightElf"
            set SOUND_LABEL[20] = "CantPlaceOrc"
            set SOUND_LABEL[21] = "CantPlaceUndead"
            set SOUND_LABEL[22] = "CantRootNightElf"
            set SOUND_LABEL[23] = "ChatroomTimerTick"
            set SOUND_LABEL[24] = "ClanInvitation"
            set SOUND_LABEL[25] = "ConstructingBuildingDefault"
            set SOUND_LABEL[26] = "ConstructingBuildingNaga"
            set SOUND_LABEL[27] = "ConstructingBuildingNightElf"
            set SOUND_LABEL[28] = "ConstructingBuildingOrc"
            set SOUND_LABEL[29] = "ConstructingBuildingUndead"
            set SOUND_LABEL[30] = "CreepAggro"
            set SOUND_LABEL[31] = "ErrorMessage"
            set SOUND_LABEL[32] = "GameFound"
            set SOUND_LABEL[33] = "GlueScreenClick"
            set SOUND_LABEL[34] = "GoldMineCollapseHuman"
            set SOUND_LABEL[35] = "GoldMineCollapseNaga"
            set SOUND_LABEL[36] = "GoldMineCollapseNightElf"
            set SOUND_LABEL[37] = "GoldMineCollapseOrc"
            set SOUND_LABEL[38] = "GoldMineCollapseUndead"
            set SOUND_LABEL[39] = "GoldMineLowGeneric"
            set SOUND_LABEL[40] = "GoldMineLowHuman"
            set SOUND_LABEL[41] = "GoldMineLowNaga"
            set SOUND_LABEL[42] = "GoldMineLowNightElf"
            set SOUND_LABEL[43] = "GoldMineLowOrc"
            set SOUND_LABEL[44] = "GoldMineLowUndead"
            set SOUND_LABEL[45] = "GoodJob"
            set SOUND_LABEL[46] = "HeroDiesGeneric"
            set SOUND_LABEL[47] = "HeroDiesHuman"
            set SOUND_LABEL[48] = "HeroDiesNaga"
            set SOUND_LABEL[49] = "HeroDiesNightElf"
            set SOUND_LABEL[50] = "HeroDiesOrc"
            set SOUND_LABEL[51] = "HeroDiesUndead"
            set SOUND_LABEL[52] = "Hint"
            set SOUND_LABEL[53] = "InGameChatWhat"
            set SOUND_LABEL[54] = "InterfaceClick"
            set SOUND_LABEL[55] = "InterfaceError"
            set SOUND_LABEL[56] = "InventoryFullHuman"
            set SOUND_LABEL[57] = "InventoryFullNaga"
            set SOUND_LABEL[58] = "InventoryFullNightElf"
            set SOUND_LABEL[59] = "InventoryFullOrc"
            set SOUND_LABEL[60] = "InventoryFullUndead"
            set SOUND_LABEL[61] = "ItemDrop"
            set SOUND_LABEL[62] = "ItemGet"
            set SOUND_LABEL[63] = "ItemReward"
            set SOUND_LABEL[64] = "JobDoneSoundHuman"
            set SOUND_LABEL[65] = "JobDoneSoundNaga"
            set SOUND_LABEL[66] = "JobDoneSoundNightElf"
            set SOUND_LABEL[67] = "JobDoneSoundOrc"
            set SOUND_LABEL[68] = "JobDoneSoundUndead"
            set SOUND_LABEL[69] = "MapPing"
            set SOUND_LABEL[70] = "MenuButtonClick"
            set SOUND_LABEL[71] = "NewTournament"
            set SOUND_LABEL[72] = "NoFoodHuman"
            set SOUND_LABEL[73] = "NoFoodNaga"
            set SOUND_LABEL[74] = "NoFoodNightElf"
            set SOUND_LABEL[75] = "NoFoodOrc"
            set SOUND_LABEL[76] = "NoFoodUndead"
            set SOUND_LABEL[77] = "NoGoldGeneric"
            set SOUND_LABEL[78] = "NoGoldHuman"
            set SOUND_LABEL[79] = "NoGoldNaga"
            set SOUND_LABEL[80] = "NoGoldNightElf"
            set SOUND_LABEL[81] = "NoGoldOrc"
            set SOUND_LABEL[82] = "NoGoldUndead"
            set SOUND_LABEL[83] = "NoLumberHuman"
            set SOUND_LABEL[84] = "NoLumberNaga"
            set SOUND_LABEL[85] = "NoLumberNightElf"
            set SOUND_LABEL[86] = "NoLumberOrc"
            set SOUND_LABEL[87] = "NoLumberUndead"
            set SOUND_LABEL[88] = "NoManaGeneric"
            set SOUND_LABEL[89] = "NoManaHuman"
            set SOUND_LABEL[90] = "NoManaNaga"
            set SOUND_LABEL[91] = "NoManaNightElf"
            set SOUND_LABEL[92] = "NoManaOrc"
            set SOUND_LABEL[93] = "NoManaUndead"
            set SOUND_LABEL[94] = "OffBlightUndead"
            set SOUND_LABEL[95] = "PauseGame"
            set SOUND_LABEL[96] = "PlaceBuildingDefault"
            set SOUND_LABEL[97] = "QuestCompleted"
            set SOUND_LABEL[98] = "QuestFailed"
            set SOUND_LABEL[99] = "QuestLogModified"
            set SOUND_LABEL[100] = "QuestNew"
            set SOUND_LABEL[101] = "QuestUpdate"
            set SOUND_LABEL[102] = "RallyPointPlace"
            set SOUND_LABEL[103] = "Rescue"
            set SOUND_LABEL[104] = "ResearchCompleteGeneric"
            set SOUND_LABEL[105] = "ResearchCompleteHuman"
            set SOUND_LABEL[106] = "ResearchCompleteNaga"
            set SOUND_LABEL[107] = "ResearchCompleteNightElf"
            set SOUND_LABEL[108] = "ResearchCompleteOrc"
            set SOUND_LABEL[109] = "ResearchCompleteUndead"
            set SOUND_LABEL[110] = "ScoreScreenTabClick"
            set SOUND_LABEL[111] = "SecretFound"
            set SOUND_LABEL[112] = "SubGroupSelectionChange"
            set SOUND_LABEL[113] = "TownAttackGeneric"
            set SOUND_LABEL[114] = "TownAttackHuman"
            set SOUND_LABEL[115] = "TownAttackNaga"
            set SOUND_LABEL[116] = "TownAttackNightElf"
            set SOUND_LABEL[117] = "TownAttackOrc"
            set SOUND_LABEL[118] = "TownAttackUndead"
            set SOUND_LABEL[119] = "UnderAttackHuman"
            set SOUND_LABEL[120] = "UnderAttackNaga"
            set SOUND_LABEL[121] = "UnderAttackNightElf"
            set SOUND_LABEL[122] = "UnderAttackOrc"
            set SOUND_LABEL[123] = "UnderAttackUndead"
            set SOUND_LABEL[124] = "UpgradeCompleteGeneric"
            set SOUND_LABEL[125] = "UpgradeCompleteHuman"
            set SOUND_LABEL[126] = "UpgradeCompleteNaga"
            set SOUND_LABEL[127] = "UpgradeCompleteNightElf"
            set SOUND_LABEL[128] = "UpgradeCompleteOrc"
            set SOUND_LABEL[129] = "UpgradeCompleteUndead"
            set SOUND_LABEL[130] = "UpkeepLevel"
            set SOUND_LABEL[131] = "Warning"
            set SOUND_LABEL[132] = "WayPoint"
        endmethod
    
        implement BMInit
    endstruct
endlibrary

Demo
JASS:
struct Test extends array

    static integer i = 0
    
    static method onEsc takes nothing returns nothing
        call BlizzardMessage ("Sound label #" + I2S (i) + " " + SOUND_LABEL[i], "|cffffcc00", i, Player (0))
        
        if i < 132 then
            set i = i + 1
        else
            set i = 0
        endif
    endmethod

    static method onInit takes nothing returns nothing
        local trigger t = CreateTrigger()
        call TriggerRegisterPlayerEvent(t, Player(0), EVENT_PLAYER_END_CINEMATIC)
        call TriggerAddAction(t, function thistype.onEsc)
        set t = null
    endmethod
    
endstruct

I apologize if this script is unpolished. This is my first submission in the JASS section and I hope to receive constructive feedback from everyone. Thank you in advance.
 

Attachments

  • Blizzard Message.w3x
    23.9 KB · Views: 199
Last edited:
Level 16
Joined
Dec 15, 2011
Messages
1,423
Okay so I attempted to add SoundTools but then I noticed that the sound labels isn't the file name of the sounds themselves. Therefore I will have to add another 133 strings if SoundTools is to be used. I figured that it would be a bad move so I decided to not update the resource. Again, if I am wrong, please show me.
 
Level 33
Joined
Apr 24, 2012
Messages
5,113
I must say that remove the API below the function and move it to the header. or you can just move the function line below the comment to make it more readable.
Also, This must improve your initialization(example):
JASS:
private module Init
    private static method onInit takes nothing returns nothing
        call init()
    endmethod
endmodule

private struct InitSys extends array
    private static method init takes nothing returns nothing
        // code
    endmethod
    implement Init
endstruct

Also, for the one-liner comments, its either you use:
//haha
or
JASS:
/*
    haha
*/
This makes the comment more readable.

Also, you must indent the giant blocks of comments with 0 spaces.

Btw,
JASS:
************************************************************************************
*
*    Functions
*
*        function BlizzardMessage takes string msg, string colorCode, integer soundLabel, player forPlayer returns nothing
*            -   Create a message with a sound for a player
*
************************************************************************************
*
*
************************************************************************************
*
I noticed two things:
1) You can replace "Functions" with API, also, you can remove the "s" from "Functions" because it is only consisted of one function :D
2) That giant block of empty comment

Other than that good job :D, a nice beginning attempt :D


Btw, I just saw this first with TeamViewer controlling Mag's PC for testing his Game Engine, I thought Mag coded this stuff :D
 
Top