357 lines
		
	
	
		
			No EOL
		
	
	
		
			12 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			357 lines
		
	
	
		
			No EOL
		
	
	
		
			12 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
| --[[
 | |
| 
 | |
| 	These are the tables for all the info we will need when dealing with the functions.
 | |
| 
 | |
| 	["Handle"] = {      			First we name it, this is the string that will be put in the command to be used with ToggleClothing, or ToggleProps.
 | |
| 		Drawable = 11,  			Then we assign its drawable/prop id. 
 | |
| 		Table = Variations.Jackets,	Then we assign its table found in Variations, if it has one, alternatively we can do.
 | |
| 									Table = {
 | |
| 										Standalone = true,
 | |
| 										Male = 34,
 | |
| 										Female = 35
 | |
| 									},
 | |
| 									Which makes it standalone, this example is for shoes, now when the player does the command it checks if they are currently wearing id 34.
 | |
| 									If they are not it takes the drawable off and saves the one they had equipped.
 | |
| 
 | |
| 		Emote = {  							Hey lets do the Emote, Pretty self explanatory.
 | |
| 			Dict = "missmic4",				This is the dict of the emote.
 | |
| 			Anim = "michael_tux_fidget",	Anim of the emote.
 | |
| 			Move = 51,						The move type of the emote, 51 is upper body only so you can move, 0 does not allow you to move.
 | |
| 			Dur = 1500						Duration of the emote.
 | |
| 											Alternatively for the props theres a seperate emote for taking off/putting on the prop.
 | |
| 		}
 | |
| 	},
 | |
| 
 | |
| ]]--
 | |
| 
 | |
| local Drawables = {
 | |
| 	["Top"] = {
 | |
| 		Drawable = 11,
 | |
| 		Table = Variations.Jackets,
 | |
| 		Emote = {Dict = "missmic4", Anim = "michael_tux_fidget", Move = 51, Dur = 1500}
 | |
| 	},
 | |
| 	["Gloves"] = {
 | |
| 		Drawable = 3,
 | |
| 		Table = Variations.Gloves,
 | |
| 		Remember = true,
 | |
| 		Emote = {Dict = "nmt_3_rcm-10", Anim = "cs_nigel_dual-10", Move = 51, Dur = 1200}
 | |
| 	},
 | |
| 	["Shoes"] = {
 | |
| 		Drawable = 6,
 | |
| 		Table = {Standalone = true, Male = 34, Female = 35},
 | |
| 		Emote = {Dict = "random@domestic", Anim = "pickup_low", Move = 0, Dur = 1200}
 | |
| 	},
 | |
| 	["Neck"] = {
 | |
| 		Drawable = 7,
 | |
| 		Table = {Standalone = true, Male = 0, Female = 0 },
 | |
| 		Emote = {Dict = "clothingtie", Anim = "try_tie_positive_a", Move = 51, Dur = 2100}
 | |
| 	},
 | |
| 	["Vest"] = {
 | |
| 		Drawable = 9,
 | |
| 		Table = {Standalone = true, Male = 0, Female = 0 },
 | |
| 		Emote = {Dict = "clothingtie", Anim = "try_tie_negative_a", Move = 51, Dur = 1200}
 | |
| 	},
 | |
| 	["Bag"] = {
 | |
| 		Drawable = 5,
 | |
| 		Table = Variations.Bags,
 | |
| 		Emote = {Dict = "anim@heists@ornate_bank@grab_cash", Anim = "intro", Move = 51, Dur = 1600}
 | |
| 	},
 | |
| 	["Mask"] = {
 | |
| 		Drawable = 1,
 | |
| 		Table = {Standalone = true, Male = 0, Female = 0 },
 | |
| 		Emote = {Dict = "mp_masks@standard_car@ds@", Anim = "put_on_mask", Move = 51, Dur = 800}
 | |
| 	},
 | |
| 	["Hair"] = {
 | |
| 		Drawable = 2,
 | |
| 		Table = Variations.Hair,
 | |
| 		Remember = true,
 | |
| 		Emote = {Dict = "clothingtie", Anim = "check_out_a", Move = 51, Dur = 2000}
 | |
| 	},
 | |
| }
 | |
| 
 | |
| local Extras = {
 | |
| 	["Shirt"] = {
 | |
| 		Drawable = 11,
 | |
| 		Table = {
 | |
| 			Standalone = true, Male = 252, Female = 74,
 | |
| 			Extra = { 
 | |
| 						{Drawable = 8, Id = 15, Tex = 0, Name = "Extra Undershirt"},
 | |
| 			 			{Drawable = 3, Id = 15, Tex = 0, Name = "Extra Gloves"},
 | |
| 			 			{Drawable = 10, Id = 0, Tex = 0, Name = "Extra Decals"},
 | |
| 			  		}
 | |
| 			},
 | |
| 		Emote = {Dict = "clothingtie", Anim = "try_tie_negative_a", Move = 51, Dur = 1200}
 | |
| 	},
 | |
| 	["Pants"] = {
 | |
| 		Drawable = 4,
 | |
| 		Table = {Standalone = true, Male = 61, Female = 14},
 | |
| 		Emote = {Dict = "re@construction", Anim = "out_of_breath", Move = 51, Dur = 1300}
 | |
| 	},
 | |
| 	["Bagoff"] = {
 | |
| 		Drawable = 5,
 | |
| 		Table = {Standalone = true, Male = 0, Female = 0},
 | |
| 		Emote = {Dict = "clothingtie", Anim = "try_tie_negative_a", Move = 51, Dur = 1200}
 | |
| 	},
 | |
| }
 | |
| 
 | |
| local Props = {
 | |
| 	["Visor"] = {
 | |
| 		Prop = 0,
 | |
| 		Variants = Variations.Visor,
 | |
| 		Emote = {
 | |
| 			On = {Dict = "mp_masks@standard_car@ds@", Anim = "put_on_mask", Move = 51, Dur = 600},
 | |
| 			Off = {Dict = "missheist_agency2ahelmet", Anim = "take_off_helmet_stand", Move = 51, Dur = 1200}
 | |
| 		}
 | |
| 	},
 | |
| 	["Hat"] = {
 | |
| 		Prop = 0,
 | |
| 		Emote = {
 | |
| 			On = {Dict = "mp_masks@standard_car@ds@", Anim = "put_on_mask", Move = 51, Dur = 600},
 | |
| 			Off = {Dict = "missheist_agency2ahelmet", Anim = "take_off_helmet_stand", Move = 51, Dur = 1200}
 | |
| 		}
 | |
| 	},
 | |
| 	["Glasses"] = {
 | |
| 		Prop = 1,
 | |
| 		Emote = {
 | |
| 			On = {Dict = "clothingspecs", Anim = "take_off", Move = 51, Dur = 1400},
 | |
| 			Off = {Dict = "clothingspecs", Anim = "take_off", Move = 51, Dur = 1400}
 | |
| 		}
 | |
| 	},
 | |
| 	["Ear"] = {
 | |
| 		Prop = 2,
 | |
| 		Emote = {
 | |
| 			On = {Dict = "mp_cp_stolen_tut", Anim = "b_think", Move = 51, Dur = 900},
 | |
| 			Off = {Dict = "mp_cp_stolen_tut", Anim = "b_think", Move = 51, Dur = 900}
 | |
| 		}
 | |
| 	},
 | |
| 	["Watch"] = {
 | |
| 		Prop = 6,
 | |
| 		Emote = {
 | |
| 			On = {Dict = "nmt_3_rcm-10", Anim = "cs_nigel_dual-10", Move = 51, Dur = 1200},
 | |
| 			Off = {Dict = "nmt_3_rcm-10", Anim = "cs_nigel_dual-10", Move = 51, Dur = 1200}
 | |
| 		}
 | |
| 	},
 | |
| 	["Bracelet"] = {
 | |
| 		Prop = 7,
 | |
| 		Emote = {
 | |
| 			On = {Dict = "nmt_3_rcm-10", Anim = "cs_nigel_dual-10", Move = 51, Dur = 1200},
 | |
| 			Off = {Dict = "nmt_3_rcm-10", Anim = "cs_nigel_dual-10", Move = 51, Dur = 1200}
 | |
| 		}
 | |
| 	},
 | |
| }
 | |
| 
 | |
| LastEquipped = {}
 | |
| Cooldown = false
 | |
| 
 | |
| local function PlayToggleEmote(e, cb)
 | |
| 	local Ped = PlayerPedId()
 | |
| 	while not HasAnimDictLoaded(e.Dict) do RequestAnimDict(e.Dict) Wait(100) end
 | |
| 	if IsPedInAnyVehicle(Ped) then e.Move = 51 end
 | |
| 	TaskPlayAnim(Ped, e.Dict, e.Anim, 3.0, 3.0, e.Dur, e.Move, 0, false, false, false)
 | |
| 	local Pause = e.Dur-500 if Pause < 500 then Pause = 500 end
 | |
| 	IncurCooldown(Pause)
 | |
| 	Wait(Pause) -- Lets wait for the emote to play for a bit then do the callback.
 | |
| 	cb()
 | |
| end
 | |
| 
 | |
| function ResetClothing(anim)
 | |
| 	local Ped = PlayerPedId()
 | |
| 	local e = Drawables.Top.Emote
 | |
| 	if anim then TaskPlayAnim(Ped, e.Dict, e.Anim, 3.0, 3.0, 3000, e.Move, 0, false, false, false) end
 | |
| 	for k,v in pairs(LastEquipped) do
 | |
| 		if v then
 | |
| 			if v.Drawable then SetPedComponentVariation(Ped, v.Id, v.Drawable, v.Texture, 0)
 | |
| 			elseif v.Prop then ClearPedProp(Ped, v.Id) SetPedPropIndex(Ped, v.Id, v.Prop, v.Texture, true) end
 | |
| 		end
 | |
| 	end
 | |
| 	LastEquipped = {}
 | |
| end
 | |
| 
 | |
| function ToggleClothing(which, extra)
 | |
| 	if Cooldown then return end
 | |
| 	local Toggle = Drawables[which] if extra then Toggle = Extras[which] end
 | |
| 	local Ped = PlayerPedId()
 | |
| 	local Cur = { -- Lets check what we are currently wearing.
 | |
| 		Drawable = GetPedDrawableVariation(Ped, Toggle.Drawable), 
 | |
| 		Id = Toggle.Drawable,
 | |
| 		Ped = Ped,
 | |
| 		Texture = GetPedTextureVariation(Ped, Toggle.Drawable),
 | |
| 	}
 | |
| 	local Gender = IsMpPed(Ped)
 | |
| 	if which ~= "Mask" then
 | |
| 		if not Gender then Notify(Lang("NotAllowedPed")) return false end -- We cancel the command here if the person is not using a multiplayer model.
 | |
| 	end
 | |
| 	local Table = Toggle.Table[Gender]
 | |
| 	if not Toggle.Table.Standalone then -- "Standalone" is for things that dont require a variant, like the shoes just need to be switched to a specific drawable. Looking back at this i should have planned ahead, but it all works so, meh!
 | |
| 		for k,v in pairs(Table) do
 | |
| 			if not Toggle.Remember then
 | |
| 				if k == Cur.Drawable then
 | |
| 					PlayToggleEmote(Toggle.Emote, function() SetPedComponentVariation(Ped, Toggle.Drawable, v, Cur.Texture, 0) end) return true
 | |
| 				end
 | |
| 			else
 | |
| 				if not LastEquipped[which] then
 | |
| 					if k == Cur.Drawable then
 | |
| 						PlayToggleEmote(Toggle.Emote, function() LastEquipped[which] = Cur SetPedComponentVariation(Ped, Toggle.Drawable, v, Cur.Texture, 0) end) return true
 | |
| 					end
 | |
| 				else
 | |
| 					local Last = LastEquipped[which]
 | |
| 					PlayToggleEmote(Toggle.Emote, function() SetPedComponentVariation(Ped, Toggle.Drawable, Last.Drawable, Last.Texture, 0) LastEquipped[which] = false end) return true
 | |
| 				end
 | |
| 			end
 | |
| 		end
 | |
| 		Notify(Lang("NoVariants")) return
 | |
| 	else
 | |
| 		if not LastEquipped[which] then
 | |
| 			if Cur.Drawable ~= Table then 
 | |
| 				PlayToggleEmote(Toggle.Emote, function()
 | |
| 					LastEquipped[which] = Cur
 | |
| 					SetPedComponentVariation(Ped, Toggle.Drawable, Table, 0, 0)
 | |
| 					if Toggle.Table.Extra then
 | |
| 						local Extras = Toggle.Table.Extra
 | |
| 						for k,v in pairs(Extras) do
 | |
| 							local ExtraCur = {Drawable = GetPedDrawableVariation(Ped, v.Drawable),  Texture = GetPedTextureVariation(Ped, v.Drawable), Id = v.Drawable}
 | |
| 							SetPedComponentVariation(Ped, v.Drawable, v.Id, v.Tex, 0)
 | |
| 							LastEquipped[v.Name] = ExtraCur
 | |
| 						end
 | |
| 					end
 | |
| 				end)
 | |
| 				return true
 | |
| 			end
 | |
| 		else
 | |
| 			local Last = LastEquipped[which]
 | |
| 			PlayToggleEmote(Toggle.Emote, function()
 | |
| 				SetPedComponentVariation(Ped, Toggle.Drawable, Last.Drawable, Last.Texture, 0)
 | |
| 				LastEquipped[which] = false
 | |
| 				if Toggle.Table.Extra then
 | |
| 					local Extras = Toggle.Table.Extra
 | |
| 					for k,v in pairs(Extras) do
 | |
| 						if LastEquipped[v.Name] then
 | |
| 							local Last = LastEquipped[v.Name]
 | |
| 							SetPedComponentVariation(Ped, Last.Id, Last.Drawable, Last.Texture, 0)
 | |
| 							LastEquipped[v.Name] = false
 | |
| 						end
 | |
| 					end
 | |
| 				end
 | |
| 			end)
 | |
| 			return true
 | |
| 		end
 | |
| 	end
 | |
| 	Notify(Lang("AlreadyWearing")) return false
 | |
| end
 | |
| 
 | |
| function ToggleProps(which)
 | |
| 	if Cooldown then return end
 | |
| 	local Prop = Props[which]
 | |
| 	local Ped = PlayerPedId()
 | |
| 	local Gender = IsMpPed(Ped)
 | |
| 	local Cur = { -- Lets get out currently equipped prop.
 | |
| 		Id = Prop.Prop,
 | |
| 		Ped = Ped,
 | |
| 		Prop = GetPedPropIndex(Ped, Prop.Prop), 
 | |
| 		Texture = GetPedPropTextureIndex(Ped, Prop.Prop),
 | |
| 	}
 | |
| 	if not Prop.Variants then
 | |
| 		if Cur.Prop ~= -1 then -- If we currently are wearing this prop, remove it and save the one we were wearing into the LastEquipped table.
 | |
| 			PlayToggleEmote(Prop.Emote.Off, function() LastEquipped[which] = Cur ClearPedProp(Ped, Prop.Prop) end) return true
 | |
| 		else
 | |
| 			local Last = LastEquipped[which] -- Detect that we have already taken our prop off, lets put it back on.
 | |
| 			if Last then
 | |
| 				PlayToggleEmote(Prop.Emote.On, function() SetPedPropIndex(Ped, Prop.Prop, Last.Prop, Last.Texture, true) end) LastEquipped[which] = false return true
 | |
| 			end
 | |
| 		end
 | |
| 		Notify(Lang("NothingToRemove")) return false
 | |
| 	else
 | |
| 		local Gender = IsMpPed(Ped)
 | |
| 		if not Gender then Notify(Lang("NotAllowedPed")) return false end -- We dont really allow for variants on ped models, Its possible, but im pretty sure 95% of ped models dont really have variants.
 | |
| 		local Variations = Prop.Variants[Gender]
 | |
| 		for k,v in pairs(Variations) do
 | |
| 			if Cur.Prop == k then
 | |
| 				PlayToggleEmote(Prop.Emote.On, function() SetPedPropIndex(Ped, Prop.Prop, v, Cur.Texture, true) end) return true
 | |
| 			end
 | |
| 		end
 | |
| 		Notify(Lang("NoVariants")) return false
 | |
| 	end
 | |
| end
 | |
| 
 | |
| function DrawDev() -- Draw text for all the stuff we are wearing, to make grabbing the variants of stuff much simpler for people.
 | |
| 	local Entries = {}
 | |
| 	for k,v in PairsKeys(Drawables) do table.insert(Entries, { Name = k, Drawable = v.Drawable }) end
 | |
| 	for k,v in PairsKeys(Extras) do table.insert(Entries, { Name = k, Drawable = v.Drawable }) end
 | |
| 	for k,v in PairsKeys(Props) do table.insert(Entries, { Name = k, Prop = v.Prop }) end
 | |
| 	for k,v in pairs(Entries) do
 | |
| 		local Ped = PlayerPedId() local Cur
 | |
| 		if v.Drawable then
 | |
| 			Cur = { Id = GetPedDrawableVariation(Ped, v.Drawable),  Texture = GetPedTextureVariation(Ped, v.Drawable) }
 | |
| 		elseif v.Prop then
 | |
| 			Cur = { Id = GetPedPropIndex(Ped, v.Prop),  Texture = GetPedPropTextureIndex(Ped, v.Prop) }
 | |
| 		end
 | |
| 		Text(0.2, 0.8*k/18, 0.30, "~o~"..v.Name.."~w~ = \n     ("..Cur.Id.." , "..Cur.Texture..")", false, 1)
 | |
| 		DrawRect(0.23, 0.8*k/18+0.025, 0.07, 0.045, 0, 0, 0, 150)
 | |
| 	end
 | |
| end
 | |
| 
 | |
| local TestThreadActive = nil
 | |
| function DevTestVariants(d) -- If debug mode is enabled we can try all the variants to check for scuff.
 | |
| 	if not TestThreadActive then
 | |
| 		Citizen.CreateThread(function()
 | |
| 			TestThreadActive = true
 | |
| 			local Ped = PlayerPedId()
 | |
| 			local Drawable = Drawables[d]
 | |
| 			local Prop = Props[d]
 | |
| 			local Gender = IsMpPed(Ped)
 | |
| 			if Drawable then
 | |
| 				if Drawable.Table then
 | |
| 					if type(Drawable.Table[Gender]) == "table" then
 | |
| 						for k,v in PairsKeys(Drawable.Table[Gender]) do
 | |
| 							Notify(d.." : ~o~"..k)
 | |
| 							SoundPlay("Open")
 | |
| 							SetPedComponentVariation(Ped, Drawable.Drawable, k, 0, 0)
 | |
| 							Wait(300)
 | |
| 							Notify(d.." : ~b~"..v)
 | |
| 							SoundPlay("Close")
 | |
| 							SetPedComponentVariation(Ped, Drawable.Drawable, v, 0, 0)
 | |
| 							Wait(300)
 | |
| 						end
 | |
| 					end
 | |
| 				end
 | |
| 			elseif Prop then
 | |
| 				if Prop.Variants then
 | |
| 					for k,v in PairsKeys(Prop.Variants[Gender]) do
 | |
| 						Notify(d.." : ~o~"..k)
 | |
| 						SoundPlay("Open")
 | |
| 						SetPedPropIndex(Ped, Prop.Prop, k, 0, true)
 | |
| 						Wait(300)
 | |
| 						Notify(d.." : ~b~"..v)
 | |
| 						SoundPlay("Close")
 | |
| 						SetPedPropIndex(Ped, Prop.Prop, v, 0, true)
 | |
| 						Wait(300)
 | |
| 						ClearPedProp(Ped, Prop.Prop)
 | |
| 						Wait(200)
 | |
| 					end
 | |
| 				end
 | |
| 			end
 | |
| 			TestThreadActive = false
 | |
| 		end)
 | |
| 	else
 | |
| 		Notify("Already testing variants.")
 | |
| 	end
 | |
| end
 | |
| 
 | |
| for k,v in pairs(Config.Commands) do
 | |
| 	RegisterCommand(k, v.Func)
 | |
| 	--log("Created /"..k.." ("..v.Desc..")") -- Useful for translation checking.
 | |
| 	TriggerEvent("chat:addSuggestion", "/"..k, v.Desc)
 | |
| end
 | |
| if Config.ExtrasEnabled then
 | |
| 	for k,v in pairs(Config.ExtraCommands) do
 | |
| 		RegisterCommand(k, v.Func)
 | |
| 		--log("Created /"..k.." ("..v.Desc..")") -- Useful for translation checking.
 | |
| 		TriggerEvent("chat:addSuggestion", "/"..k, v.Desc)
 | |
| 	end
 | |
| end
 | |
| 
 | |
| AddEventHandler('onResourceStop', function(resource) -- Mostly for development, restart the resource and it will put all the clothes back on.
 | |
| 	if resource == GetCurrentResourceName() then
 | |
| 		ResetClothing()
 | |
| 	end
 | |
| end) | 
