├── fxmanifest.lua ├── README.md └── client.lua /fxmanifest.lua: -------------------------------------------------------------------------------- 1 | fx_version 'bodacious' 2 | game 'gta5' 3 | 4 | author 'Elio / Sheamle' 5 | description '/me command but it\'s 3D printed' 6 | version '1.0' 7 | 8 | client_scripts { 9 | 'animations.lua', 10 | 'client.lua' 11 | } 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Animenu 2 | This "menu" allows you to play almost any animation that is in GTA 5. 3 | 4 | 5 | 6 | ## Credits 7 | Thanks to Alexguirre for providing the list of every animations (see https://alexguirre.github.io/animations-list/). 8 | 9 | ## Usage 10 | 11 | To open the menu type `/animations` in the chat. 12 | Once the menu is opened, you can interact with it. 13 | 14 | | Input control | Action | 15 | |---|---| 16 | | Scroll up/Scroll down | Navigate through the animations. | 17 | | E | Print the animation informations in the console. | 18 | | Alt | Cancel the animation. | 19 | | Enter | Play the selected animation. | 20 | | Spacebar | Search for an animation. | 21 | 22 | *Note that once you've entered the searching term you will have to scroll to trigger the search. Also note that it consummes a lot of RAM.* 23 | -------------------------------------------------------------------------------- /client.lua: -------------------------------------------------------------------------------- 1 | -- ############################################ 2 | -- -------------------------------------------- 3 | -- Animenu : a "menu" to play any animation 4 | -- Author : Elio 5 | -- -------------------------------------------- 6 | -- ############################################ 7 | 8 | local find = string.find 9 | 10 | -- -------------------------------------------- 11 | -- Variables 12 | -- -------------------------------------------- 13 | 14 | local index = 1 15 | local draw = false 16 | local searching = false 17 | local searchingString = "" 18 | 19 | -- -------------------------------------------- 20 | -- Display functions 21 | -- -------------------------------------------- 22 | 23 | -- OBJ : display text on screen 24 | -- PARAMETERS : 25 | -- - x : x coordinate of the text 26 | -- - y : y coordinate of the text 27 | -- - text : text to display 28 | local function DrawTextAdvanced(x, y, text) 29 | SetTextFont(0) 30 | SetTextScale(0.4, 0.4) 31 | SetTextColour(230, 230, 230, 255) 32 | SetTextDropshadow(0, 0, 0, 0, 255) 33 | SetTextEdge(2, 0, 0, 0, 150) 34 | SetTextDropShadow() 35 | SetTextEntry("STRING") 36 | SetTextCentre(1) 37 | AddTextComponentString(text) 38 | DrawText(x,y) 39 | end 40 | 41 | -- OBJ : display instructionnal buttons 42 | -- PARAMETERS : 43 | -- - buttons : array of the buttons and their names 44 | local function InstructionnalButtons(buttons) 45 | local instructionScaleform = RequestScaleformMovie("instructional_buttons") 46 | 47 | while not HasScaleformMovieLoaded(instructionScaleform) do 48 | Wait(0) 49 | end 50 | 51 | PushScaleformMovieFunction(instructionScaleform, "CLEAR_ALL") 52 | PushScaleformMovieFunction(instructionScaleform, "TOGGLE_MOUSE_BUTTONS") 53 | PushScaleformMovieFunctionParameterBool(0) 54 | PopScaleformMovieFunctionVoid() 55 | 56 | for buttonIndex, buttonValues in ipairs(buttons) do 57 | PushScaleformMovieFunction(instructionScaleform, "SET_DATA_SLOT") 58 | PushScaleformMovieFunctionParameterInt(buttonIndex - 1) 59 | 60 | PushScaleformMovieMethodParameterButtonName(GetControlInstructionalButton(0, buttonValues.button, 0)) 61 | PushScaleformMovieFunctionParameterString(buttonValues.name) 62 | PopScaleformMovieFunctionVoid() 63 | end 64 | 65 | PushScaleformMovieFunction(instructionScaleform, "DRAW_INSTRUCTIONAL_BUTTONS") 66 | PushScaleformMovieFunctionParameterInt(-1) 67 | PopScaleformMovieFunctionVoid() 68 | DrawScaleformMovieFullscreen(instructionScaleform, 255, 255, 255, 255) 69 | end 70 | 71 | -- OBJ : get the input of a user 72 | -- PARAMETERS : 73 | -- - windowTitle : the title of the windowTitle 74 | -- - defaultText : the text to display by default 75 | -- - maxInputLength : the maximum length of the input 76 | local function GetUserInput(windowTitle, defaultText, maxInputLength) 77 | 78 | windowTitle = windowTitle or "" 79 | defaultText = defaultText or "" 80 | maxInputLength = maxInputLength or 128 81 | 82 | AddTextEntry("ANIM_WINDOW_TITLE", windowTitle .. " (MAX. LENGTH : " .. maxInputLength .. ") :") 83 | DisplayOnscreenKeyboard(1, "ANIM_WINDOW_TITLE", "", defaultText, "", "", "", maxInputLength) 84 | 85 | while UpdateOnscreenKeyboard() == 0 do 86 | Wait(100) 87 | end 88 | 89 | local result = GetOnscreenKeyboardResult() 90 | 91 | return result 92 | 93 | end 94 | 95 | -- OBJ : send a native notification 96 | -- PARAMETERS : 97 | -- - text : the text to display 98 | function SendNotification(text) 99 | BeginTextCommandThefeedPost('STRING') 100 | AddTextComponentString(text) 101 | EndTextCommandThefeedPostTicker(true, true) 102 | end 103 | 104 | -- -------------------------------------------- 105 | -- Fundamental functions 106 | -- DO NOT TOUCH 107 | -- -------------------------------------------- 108 | 109 | local function GoUpInAnimations(deepness) 110 | deepness = deepness or 1 111 | 112 | if index == 1 then 113 | index = #Animations 114 | else 115 | index = index - 1 116 | end 117 | 118 | if deepness <= #Animations then 119 | if searching then 120 | if not find(Animations[index][1]..Animations[index][2], searchingString) then 121 | GoUpInAnimations(deepness + 1) 122 | end 123 | end 124 | else 125 | SendNotification("~r~~h~ERROR ~h~~w~: No results found. Your research parameter got deleted.") 126 | searching = false 127 | searchingString = "" 128 | end 129 | end 130 | 131 | local function GoDownInAnimations(deepness) 132 | deepness = deepness or 1 133 | 134 | if index == #Animations then 135 | index = 1 136 | else 137 | index = index + 1 138 | end 139 | 140 | if deepness <= #Animations then 141 | if searching then 142 | if not find(Animations[index][1]..Animations[index][2], searchingString) then 143 | GoDownInAnimations(deepness + 1) 144 | end 145 | end 146 | else 147 | SendNotification("~r~~h~ERROR ~h~~w~: No results found. Your research parameters got deleted.") 148 | searching = false 149 | searchingString = "" 150 | end 151 | end 152 | 153 | local function PlayAnimation() 154 | local playerPed = PlayerPedId() 155 | RequestAnimDict(Animations[index][1]) 156 | local j = 0 157 | while not HasAnimDictLoaded(Animations[index][1]) and j <= 50 do 158 | Citizen.Wait(100) 159 | j = j + 1 160 | end 161 | 162 | if j >= 50 then 163 | SendNotification("~r~~h~ERROR ~h~~w~: The animation dictionnary took too long to load.") 164 | else 165 | TaskPlayAnim(playerPed, Animations[index][1], Animations[index][2], 8.0, 1.0, -1, 1) 166 | RemoveAnimDict(Animations[index][1]) 167 | end 168 | end 169 | 170 | local function SearchAnimation() 171 | searchingString = GetUserInput("Animation name", "", 32):lower() 172 | searching = searchingString ~= "" and searchingString ~= nil 173 | end 174 | 175 | local function CancelAnimation() 176 | ClearPedTasksImmediately(PlayerPedId()) 177 | end 178 | 179 | local function PrintAnimation() 180 | print("-----------------------------------------") 181 | print("Animation :") 182 | print(" - Dict : " .. Animations[index][1]) 183 | print(" - Clip : " .. Animations[index][2]) 184 | print("-----------------------------------------") 185 | end 186 | 187 | -- -------------------------------------------- 188 | -- Parameters 189 | -- -------------------------------------------- 190 | 191 | local options = { 192 | { button = 17, name = "Go up in animations", func = GoUpInAnimations }, 193 | { button = 16, name = "Go down in animations", func = GoDownInAnimations }, 194 | { button = 201, name = "Play animation", func = PlayAnimation }, 195 | { button = 22, name = "Search for an animation", func = SearchAnimation }, 196 | { button = 19, name = "Cancel animation", func = CancelAnimation }, 197 | { button = 51, name = "Print animation informations", func = PrintAnimation }, 198 | } 199 | 200 | -- -------------------------------------------- 201 | -- Command 202 | -- -------------------------------------------- 203 | 204 | RegisterCommand('animation', function() 205 | draw = not draw 206 | end) 207 | 208 | -- -------------------------------------------- 209 | -- Main thread 210 | -- -------------------------------------------- 211 | 212 | Citizen.CreateThread(function() 213 | while true do 214 | 215 | if draw then 216 | DrawTextAdvanced(0.5, 0.77, "Animation n°" .. index .. " :") 217 | DrawTextAdvanced(0.5, 0.8, Animations[index][1] .. " / " .. Animations[index][2]) 218 | 219 | InstructionnalButtons(options) 220 | 221 | for i = 1, #options do 222 | DisableControlAction(0, options[i].button, true) 223 | 224 | if IsDisabledControlJustPressed(1, options[i].button) then 225 | options[i].func() 226 | end 227 | 228 | end 229 | 230 | end 231 | 232 | Wait(0) 233 | end 234 | end) 235 | --------------------------------------------------------------------------------