HumanoidDescription:GetEmotes(), but for all owned emotes?

Hi! So my game has a custom R15 rig (for aesthetic and texturing purposes) with the use of StarterCharacter and I’d love to allow players to use emotes they own on the actual site.

In normal games, you can use all the owned emotes by chatting their name.
“/e power blast” should work flawlessly.
In the test game, it sadly doesn’t work.

I noticed HumanoidDescription:GetEmotes() is limited, because it only gets equipped emotes.
Yep. Not the whole emote list. Just ones you have equipped.
I’m not sure if it’s a bug or not, since DOCUMENTATION IS GREAT!


Simple example of my (prototype) script can be seen there:

local players = game:GetService("Players")

local function PlayerJoined(player)
	local og = players:GetHumanoidDescriptionFromUserId(player.UserId)
	local ownedEmotes = og:GetEmotes()
	local equippedEmotes = og:GetEquippedEmotes()
	
	for i,v in pairs(ownedEmotes) do -- Reminder, it prints GetEmotes.
		print(i,v)
	end
	
	local function Update(character)
		local desc = character:WaitForChild("Humanoid").HumanoidDescription
		desc:SetEmotes(ownedEmotes)
		desc:SetEquippedEmotes(equippedEmotes)
	end
	player.CharacterAdded:Connect(Update)
	if player.Character then Update(player.Character) end
end

players.PlayerAdded:Connect(PlayerJoined)

I don’t want to scan the whole catalog for the love of god :frowning:
If someone has any idea on how could I replicate the behavior in actual games, that’d help.

1 Like

After some fishing around I found a inventory endpoint for getting owned items of an asset type.
According to the AssetType Enumeration documentation, emote animations’ asset type id is 61.

Therefore, if I wanted to get my owned emote animations, the link would be:

https://inventory.roblox.com/v2/users/1100961460/inventory/61?sortOrder=Asc&limit=10
Response body
{
  "previousPageCursor": null,
  "nextPageCursor": null,
  "data": [
    {
      "assetName": "Hype Dance",
      "userAssetId": 45337742167,
      "assetId": 3696757129,
      "owner": {
        "userId": 1100961460,
        "username": "ReturnedTrue",
        "buildersClubMembershipType": 0
      },
      "created": "2019-08-28T08:35:42.02",
      "updated": "2019-08-28T08:35:42.02"
    },
    {
      "assetName": "Tilt",
      "userAssetId": 45337762336,
      "assetId": 3360692915,
      "owner": {
        "userId": 1100961460,
        "username": "ReturnedTrue",
        "buildersClubMembershipType": 0
      },
      "created": "2019-08-28T08:35:58.907",
      "updated": "2019-08-28T08:35:58.907"
    },
    {
      "assetName": "Superhero Reveal",
      "userAssetId": 45337796194,
      "assetId": 3696759798,
      "owner": {
        "userId": 1100961460,
        "username": "ReturnedTrue",
        "buildersClubMembershipType": 0
      },
      "created": "2019-08-28T08:36:27.753",
      "updated": "2019-08-28T08:36:27.753"
    },
    {
      "assetName": "Shrug",
      "userAssetId": 45337816396,
      "assetId": 3576968026,
      "owner": {
        "userId": 1100961460,
        "username": "ReturnedTrue",
        "buildersClubMembershipType": 0
      },
      "created": "2019-08-28T08:36:46.103",
      "updated": "2019-08-28T08:36:46.103"
    },
    {
      "assetName": "Heisman Pose",
      "userAssetId": 45337834617,
      "assetId": 3696763549,
      "owner": {
        "userId": 1100961460,
        "username": "ReturnedTrue",
        "buildersClubMembershipType": 0
      },
      "created": "2019-08-28T08:37:02.41",
      "updated": "2019-08-28T08:37:02.41"
    },
    {
      "assetName": "Stadium",
      "userAssetId": 45337855379,
      "assetId": 3360686498,
      "owner": {
        "userId": 1100961460,
        "username": "ReturnedTrue",
        "buildersClubMembershipType": 0
      },
      "created": "2019-08-28T08:37:20.687",
      "updated": "2019-08-28T08:37:20.687"
    },
    {
      "assetName": "Cha-Cha",
      "userAssetId": 45337884723,
      "assetId": 3696764866,
      "owner": {
        "userId": 1100961460,
        "username": "ReturnedTrue",
        "buildersClubMembershipType": 0
      },
      "created": "2019-08-28T08:37:47.257",
      "updated": "2019-08-28T08:37:47.257"
    },
    {
      "assetName": "Salute",
      "userAssetId": 45337907757,
      "assetId": 3360689775,
      "owner": {
        "userId": 1100961460,
        "username": "ReturnedTrue",
        "buildersClubMembershipType": 0
      },
      "created": "2019-08-28T08:38:06.97",
      "updated": "2019-08-28T08:38:06.97"
    },
    {
      "assetName": "Hello",
      "userAssetId": 45337929402,
      "assetId": 3576686446,
      "owner": {
        "userId": 1100961460,
        "username": "ReturnedTrue",
        "buildersClubMembershipType": 0
      },
      "created": "2019-08-28T08:38:27.2",
      "updated": "2019-08-28T08:38:27.2"
    },
    {
      "assetName": "Point2",
      "userAssetId": 45338048253,
      "assetId": 3576823880,
      "owner": {
        "userId": 1100961460,
        "username": "ReturnedTrue",
        "buildersClubMembershipType": 0
      },
      "created": "2019-08-28T08:40:12.913",
      "updated": "2019-08-28T08:40:12.913"
    }
  ]
}

Since Roblox block requests to their APIs from HttpService, you’ll need to use a proxy (ie. rprxy.xyz) or create your own application (possibly with express.js).

1 Like

For now I will write a module which should handle this, hopefully.
If I do finish it - I will use it until there’s an official method.

I tested once again, but if inventory is hidden - it will give nil.

local SITE = {"https://inventory.rprxy.xyz/v2/users/", "/inventory/61?sortOrder=Asc&limit=10"}
local httpService = game:GetService("HttpService")

return function(ID)
	local response, data
	pcall(function()
		response = httpService:GetAsync(SITE[1]..ID..SITE[2])
		data = httpService:JSONDecode(response)
	end)
	if data then -- just test
		for i, v in pairs(data) do
			print(i,v)
		end
	end
	return data
end

There’s no way around that sadly, you could prompt the user to change the setting for access to the functionality.

1 Like

Yeah, for now it can be a good workaround. I hope this issue gets addressed soon.

local module = require(script.ModuleScript)
-- blah blah
local ownedEmotes = module(ID) or og:GetEmotes()