mirror of
https://github.com/jimathy/jim-consumables.git
synced 2026-08-17 14:36:03 +01:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
762240b500 | ||
|
|
0a0f60468a | ||
|
|
9b189d89f5 | ||
|
|
62db9f6900 | ||
|
|
6317dee667 | ||
|
|
15bb54c206 | ||
|
|
94023857ff | ||
|
|
daa70a8844 | ||
|
|
25e8d99839 | ||
|
|
2c2a486a41 | ||
|
|
16e957116e | ||
|
|
b4d65ff043 | ||
|
|
9d866c88ee | ||
|
|
018dcca6cc | ||
|
|
e27b840a5e |
12
.gitattributes
vendored
Normal file
12
.gitattributes
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
# VCS / CI noise
|
||||
.gitattributes export-ignore
|
||||
.gitignore export-ignore
|
||||
.github/** export-ignore
|
||||
.gitmodules export-ignore
|
||||
|
||||
# Dev tooling/config
|
||||
.vscode/** export-ignore
|
||||
*.code-workspace export-ignore
|
||||
.editorconfig export-ignore
|
||||
.eslintrc* export-ignore
|
||||
.prettier* export-ignore
|
||||
15
.github/workflows/notify-discord.yml
vendored
15
.github/workflows/notify-discord.yml
vendored
@@ -3,15 +3,16 @@ name: Discord Commit Notifier
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- '*' # triggers on all branches
|
||||
- '*'
|
||||
|
||||
jobs:
|
||||
notify:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Discord Commits
|
||||
uses: Sniddl/discord-commits@v1.6
|
||||
with:
|
||||
webhook: ${{ secrets.DISCORD_WEBHOOK }}
|
||||
template: "avatar-with-link"
|
||||
include-extras: true
|
||||
- name: Send commit payload to Discord Bot
|
||||
env:
|
||||
URL: http://${{ secrets.DISCORDBOT }}:3000/github-commits
|
||||
run: |
|
||||
curl -sS -X POST "$URL" \
|
||||
-H 'Content-Type: application/json' \
|
||||
--data-binary "@$GITHUB_EVENT_PATH"
|
||||
71
.github/workflows/notify-release.yml
vendored
Normal file
71
.github/workflows/notify-release.yml
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
name: Discord Release Notifier
|
||||
|
||||
on:
|
||||
# Manual or UI-published releases
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
# Releases created by your tag-driven workflow
|
||||
workflow_run:
|
||||
workflows: ["Package & Release"] # must match the 'name:' in release.yml
|
||||
types: [completed]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
# 1) Handle manual / UI / non-workflow-created releases
|
||||
notify-from-release:
|
||||
if: github.event_name == 'release' && github.event.action == 'published'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Send release payload to Discord Bot
|
||||
env:
|
||||
URL: http://${{ secrets.DISCORDBOT }}:3000/github-releases
|
||||
run: |
|
||||
curl -sS -X POST "$URL" \
|
||||
-H 'Content-Type: application/json' \
|
||||
--data-binary "@$GITHUB_EVENT_PATH"
|
||||
|
||||
# 2) Handle releases created by your 'Package & Release' workflow
|
||||
# (which won’t trigger `on: release` when using GITHUB_TOKEN)
|
||||
notify-from-workflow-run:
|
||||
if: >
|
||||
github.event_name == 'workflow_run' &&
|
||||
github.event.workflow_run.conclusion == 'success'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Install jq
|
||||
run: sudo apt-get update && sudo apt-get install -y jq
|
||||
|
||||
- name: Fetch release JSON by tag
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
OWNER="${GITHUB_REPOSITORY%/*}"
|
||||
REPO="${GITHUB_REPOSITORY#*/}"
|
||||
TAG="${{ github.event.workflow_run.head_branch }}"
|
||||
# head_branch is the tag name for a tag push workflow_run
|
||||
curl -fsSL -H "Authorization: Bearer $GH_TOKEN" \
|
||||
-H "Accept: application/vnd.github+json" \
|
||||
"https://api.github.com/repos/$OWNER/$REPO/releases/tags/$TAG" \
|
||||
> release.json
|
||||
|
||||
- name: Wrap as 'release' event payload & notify bot
|
||||
env:
|
||||
URL: http://${{ secrets.DISCORDBOT }}:3000/github-releases
|
||||
run: |
|
||||
set -euo pipefail
|
||||
jq -n --slurpfile rel release.json \
|
||||
--arg repo "$GITHUB_REPOSITORY" \
|
||||
--arg repo_url "https://github.com/$GITHUB_REPOSITORY" \
|
||||
--arg action "published" '
|
||||
{ action: $action,
|
||||
repository: { full_name: $repo, html_url: $repo_url },
|
||||
release: $rel[0],
|
||||
sender: { login: "github-actions[bot]" } }' > payload.json
|
||||
|
||||
curl -sS -X POST "$URL" \
|
||||
-H 'Content-Type: application/json' \
|
||||
--data-binary "@payload.json"
|
||||
88
.github/workflows/release.yml
vendored
Normal file
88
.github/workflows/release.yml
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
name: Package & Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "v*"
|
||||
- "*.*.*"
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout (full history)
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Derive vars
|
||||
id: vars
|
||||
shell: bash
|
||||
run: |
|
||||
echo "name=${GITHUB_REPOSITORY##*/}" >> $GITHUB_OUTPUT # e.g. jim_bridge
|
||||
echo "version=${GITHUB_REF_NAME#v}" >> $GITHUB_OUTPUT # strip leading v
|
||||
|
||||
- name: Build zip with folder prefix
|
||||
shell: bash
|
||||
run: |
|
||||
NAME='${{ steps.vars.outputs.name }}'
|
||||
VER='${{ steps.vars.outputs.version }}'
|
||||
git archive --format=zip --prefix="${NAME}/" -o "${NAME}-${VER}.zip" "$GITHUB_REF_NAME"
|
||||
ls -lh "${NAME}-${VER}.zip"
|
||||
|
||||
# --- Patch notes generation (commit titles + links) -------------------
|
||||
- name: Find previous tag (SemVer aware)
|
||||
id: prev
|
||||
shell: bash
|
||||
run: |
|
||||
CUR="${GITHUB_REF_NAME}"
|
||||
# Sort tags by version desc, drop the current, take the next newest
|
||||
PREV=$(git tag --sort=-v:refname | grep -v -x "$CUR" | head -n 1 || true)
|
||||
echo "prev=$PREV" >> $GITHUB_OUTPUT
|
||||
echo "Previous tag: ${PREV:-<none>}"
|
||||
|
||||
- name: Generate RELEASE_NOTES.md from commits
|
||||
shell: bash
|
||||
run: |
|
||||
REPO="${{ github.repository }}"
|
||||
CUR="${GITHUB_REF_NAME}"
|
||||
PREV='${{ steps.prev.outputs.prev }}'
|
||||
|
||||
if [ -n "$PREV" ]; then
|
||||
RANGE="$PREV..$CUR"
|
||||
HEADER="## Changes in $CUR"
|
||||
else
|
||||
# First release: include all commits
|
||||
ROOT=$(git rev-list --max-parents=0 HEAD | tail -n 1)
|
||||
RANGE="$ROOT..$CUR"
|
||||
HEADER="## Changes"
|
||||
fi
|
||||
|
||||
{
|
||||
echo "$HEADER"
|
||||
echo
|
||||
# Oldest → newest, subject only, skip merge commits
|
||||
# Escape '[' and ']' so markdown doesn't break on rare titles
|
||||
git log --reverse --no-merges --pretty=format:'- ['%h'] - %s' "$RANGE" \
|
||||
| perl -pe 's/([\[\]])/\\$1/g'
|
||||
} > RELEASE_NOTES.md
|
||||
|
||||
echo "--- RELEASE_NOTES.md ---"
|
||||
cat RELEASE_NOTES.md
|
||||
echo "------------------------"
|
||||
|
||||
- name: Create / Update GitHub Release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
tag_name: ${{ github.ref_name }}
|
||||
name: ${{ github.ref_name }}
|
||||
files: |
|
||||
*.zip
|
||||
body_path: RELEASE_NOTES.md # attach our generated notes
|
||||
# If you wanted GitHub's auto notes instead, set:
|
||||
# generate_release_notes: true
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
144
README.md
144
README.md
@@ -1,5 +1,6 @@
|
||||
# Jim-Consumables
|
||||
Consumables script for QBCore
|
||||
|
||||
## FiveM MultiFrameork Consumables script
|
||||
|
||||
# What is this?
|
||||
This script WAS designed as a replacement/override for food and drink consumables in `qb-smallresources`
|
||||
@@ -12,140 +13,13 @@ Though if your players are cancelling all animations when consuming, it's recomm
|
||||
|
||||
# THIS DOESN'T USE DPEMOTES OR RPEMOTES OR SCULLYS EMOTEMENU
|
||||
|
||||
# Installation
|
||||
---
|
||||
|
||||
- I always recommend starting my scripts **AFTER** `[qb]` not inside it as it can mess with any dependancies on server load
|
||||
- I have a separate folder called `[jimextras]` (that is also in the resources folder) that starts before any scripts would use it.
|
||||
- This ensure's it has everything it requires before trying to load
|
||||
- Example of my load order:
|
||||
```CSS
|
||||
# QBCore & Extra stuff
|
||||
ensure qb-core
|
||||
ensure [qb]
|
||||
ensure [standalone]
|
||||
ensure [voice]
|
||||
ensure [defaultmaps]
|
||||
ensure [vehicles]
|
||||
# Installation and Previews:
|
||||
## [JixelPatterns GitBook Documentation](https://jixelpatterns.gitbook.io/docs)
|
||||
|
||||
# Extra Jim Stuff
|
||||
ensure [jimextras]
|
||||
ensure [jim]
|
||||
```
|
||||
### If you need support I have a discord server available, it helps me keep track of issues and give better support.
|
||||
## [JixelPatterns Discord](https://discord.gg/9pCDHmjYwd)
|
||||
|
||||
## QB-SmallResources
|
||||
|
||||
- It should already take control of default qbcore food, drink and drugs.
|
||||
- If it fails to do this and attempts to use qb-smallresources still you will need to:
|
||||
- `[qb]` > `qb-smallresources` > `server` > `consumables.lua`
|
||||
- Remove or comment out the `CreateUseableItem` events for *alcohol*, *eat*, *drink* and *drug* in this file
|
||||
- Not all of them! (such as armour related items)
|
||||
- This ***should*** stop `qb-smallresources` taking control and confusing `jim-consumables`
|
||||
|
||||
## New Items
|
||||
To add an item, you only need to add a new item table in the Config.Consumables like this:
|
||||
```lua
|
||||
heartstopper = {
|
||||
emote = "burger", -- Select an emote from below, it has to be in here
|
||||
time = math.random(5000, 6000), -- Amount of time it takes to consume the item
|
||||
stress = math.random(1,2), -- Amount of stress relief, can be 0
|
||||
heal = 0, -- Set amount to heal by after consuming
|
||||
armor = 5, -- Amount of armor to add
|
||||
type = "food", -- Type: "alcohol" / "drink" / "food"
|
||||
canRun = true, -- If true player can run while using the item, not to it will cancel the event
|
||||
|
||||
stats = {
|
||||
screen = "thermal", -- The screen effect to be played when after consuming the item "rampage" "turbo" "focus" "weed" "trevor" "nightvision" "thermal"
|
||||
effect = "heal", -- The status effect given by the item, "heal" / "stamina"
|
||||
-- This supports ps-buffs effects "armor" "stress" "swimming" "hacking" "intelligence" "luck" "strength"
|
||||
time = 10000, -- How long the effect should last (if not added it will default to 10000)
|
||||
amount = 6, -- How much the value is changed by per second
|
||||
hunger = math.random(10, 20), -- The hunger/thirst stats of the item, if not found in the items.lua
|
||||
thirst = math.random(10, 20), -- The hunger/thirst stats of the item, if not found in the items.lua
|
||||
canOD = true, -- This creates an OD Effect, killing the user if they have too much
|
||||
},
|
||||
--Reward Items Variables
|
||||
-- These can be the only thing in a consumable table and the item will still work
|
||||
amounttogive = 3, -- Used for "RewardItems", tells the script how many to give
|
||||
rewards = {
|
||||
[1] = {
|
||||
item = "plastic", -- prize item name
|
||||
max = 10, -- max amount to give (this is put into math.random(1, max) )
|
||||
rarity = 1, -- the rarity system, 1 being rarest, 4 being most common
|
||||
},
|
||||
},
|
||||
},
|
||||
```
|
||||
Consuming an item can also manually activate screen effects
|
||||
|
||||
The example above uses `rampage` as this is what the effect is named after, you can use it for any item you think best
|
||||
```lua
|
||||
--The current list of screen effects are:
|
||||
"turbo"
|
||||
"focus"
|
||||
"rampage"
|
||||
"weed"
|
||||
"trevor"
|
||||
"nightvision"
|
||||
"thermal"
|
||||
```
|
||||
|
||||
You can also now create "Box" items, when setting type to "pack", it will act as if you user is opening a box
|
||||
|
||||
Examples:
|
||||
- Ammo boxes that give clips
|
||||
- Packets of cigarretes
|
||||
- Crates of beer
|
||||
|
||||
How to set up these:
|
||||
```lua
|
||||
-- Example Box Item
|
||||
["9_box"] = { -- Name of the box item in the shared items
|
||||
emote = "uncuff", -- The emote than should run when "unboxing"
|
||||
canRun = true, -- If true player can run while using the item, not to it will cancel the event
|
||||
time = 3500, -- How long it takes to use the item
|
||||
type = "pack", -- Designate it as a "pack" to the script knows what to do
|
||||
pack = {
|
||||
item = "9_ammo", -- The item to give from the box when complete
|
||||
amount = 20 -- How many of the item to give
|
||||
},
|
||||
},
|
||||
```
|
||||
|
||||
## PS-Buffs Support
|
||||
This scripts can be expanded with ps-buffs (https://github.com/Project-Sloth/ps-buffs)
|
||||
|
||||
If this script is enabled it will automatically try to use their system to apply buffs:
|
||||
|
||||
```lua
|
||||
--The extra buffs that can be set include:
|
||||
"heal" -- Health recovery buff
|
||||
"stamina" -- Stamina recovery buff
|
||||
"swimming" -- Swimming speed buff
|
||||
"stress" -- Stress recovery buff
|
||||
"armor" -- Armour recovery buff
|
||||
"hacking" -- Hacking effect
|
||||
"intelligence" -- Intelligence effect
|
||||
"luck" -- Luck effect
|
||||
"strength" -- Strength effect
|
||||
```
|
||||
|
||||
This script supports dpemotes style emotes, so if you have some that you want to be triggered when eating or drinking drop it in the Config.Emotes section.
|
||||
|
||||
|
||||
## Add consumables from external scripts
|
||||
|
||||
A small example of a server-sided snippet for this imports the item and the emote, then syncs it to players before and after they connect.
|
||||
|
||||
```lua
|
||||
local foodTable = {
|
||||
["shotfries"] = { emote = "bsfries", canRun = false, time = math.random(5000, 6000), stress = math.random(2, 4), heal = 0, armor = 0, type = "food", stats = { hunger = math.random(55,65), }},
|
||||
}
|
||||
|
||||
local emoteTable = {
|
||||
["bsfries"] = {"mp_player_inteat@burger", "mp_player_int_eat_burger_fp", "Fries", AnimationOptions = { Prop = "prop_food_bs_chips", PropBone = 18905, PropPlacement = {0.09, -0.06, 0.05, 300.0, 150.0}, EmoteMoving = true, EmoteLoop = true, }},
|
||||
}
|
||||
|
||||
for k, v in pairs(foodTable) do TriggerEvent("jim-consumables:server:syncAddItem", k, v) end
|
||||
for k, v in pairs(emoteTable) do TriggerEvent("jim-consumables:server:syncAddEmote", k, v) end
|
||||
```
|
||||
This will grab the `shotfries` item info and add it to the `Config.Consumables` while the servers running and the same with the built-in emote system
|
||||
### If you think I did a good job here, consider donating as it keeps by lights on and my cat round:
|
||||
## [JixelPatterns Kofi](https://ko-fi.com/jixelpatterns)
|
||||
@@ -38,6 +38,7 @@ AddStateBagChangeHandler("jimConsumableItems", nil, function(bagName, key, value
|
||||
debugPrint("^5Statebag^7: ^2Synced ^6"..newItemCount.." ^2new Consumables^7")
|
||||
end
|
||||
end)
|
||||
|
||||
AddStateBagChangeHandler("jimConsumableEmotes", nil, function(bagName, key, value, _unused)
|
||||
if type(value) == "table" then
|
||||
local newEmoteCount = 0
|
||||
@@ -62,7 +63,7 @@ RegisterNetEvent(getScript()..':Consume', function(itemName)
|
||||
|
||||
if requiredItem then
|
||||
if not hasItem(requiredItem, 1) then
|
||||
triggerNotify(nil, "You need a "..Items[requiredItem].label, "error")
|
||||
triggerNotify(nil, "You need a "..getItemLabel(requiredItem), "error")
|
||||
return
|
||||
else
|
||||
-- if requiredItem == "lighter" then breakTool({ item = "lighter", damage = math.random(0, 1) }) end
|
||||
@@ -72,6 +73,7 @@ RegisterNetEvent(getScript()..':Consume', function(itemName)
|
||||
debugPrint("^5Debug^7: ^3Consume^7: ^2Starting event, locking inventory and grabbing data^7..")
|
||||
tempLockInv(true)
|
||||
local Player = PlayerPedId()
|
||||
local pedCoords = GetEntityCoords(Player)
|
||||
local emote = Emotes[consumable.emote] or Emotes["crisps"]
|
||||
if isAnimal then --- Animal ped adjustments
|
||||
local presets = {
|
||||
@@ -127,25 +129,23 @@ RegisterNetEvent(getScript()..':Consume', function(itemName)
|
||||
}
|
||||
end
|
||||
|
||||
local returnItem = consumable.returnItem or nil
|
||||
local animDict, anim = tostring(emote[1]), tostring(emote[2])
|
||||
local model, model2, bone, bone2, drugeffect, stress
|
||||
local P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12 = table.unpack({0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}) -- Default placement coord cariable
|
||||
local RewardItem = consumable.rewards or nil
|
||||
local type = consumable.type or ""
|
||||
local pack = consumable.pack or nil
|
||||
local string = "Using "
|
||||
local canRun = consumable.canRun
|
||||
local stats = consumable.stats
|
||||
|
||||
local time, stress, heal, armor, needStats = GenerateRandomValues({
|
||||
local time, heal, armor, needStats = GenerateRandomValues({
|
||||
time = consumable.time or { 5000, 6000 },
|
||||
stress = consumable.stress or 0,
|
||||
heal = consumable.heal or 0,
|
||||
armor = consumable.armor or 0,
|
||||
hunger = consumable.stats and consumable.stats.hunger or 0,
|
||||
thirst = consumable.stats and consumable.stats.thirst or 0,
|
||||
stress = consumable.stress or 0,
|
||||
})
|
||||
|
||||
if emote.AnimationOptions.Prop then
|
||||
model = emote.AnimationOptions.Prop
|
||||
bone = GetPedBoneIndex(Player, emote.AnimationOptions.PropBone)
|
||||
@@ -210,7 +210,7 @@ RegisterNetEvent(getScript()..':Consume', function(itemName)
|
||||
CreateThread(function()
|
||||
if progressBar({
|
||||
time = time,
|
||||
label = string..Items[itemName].label.."..",
|
||||
label = string..getItemLabel(itemName).."..",
|
||||
dead = false,
|
||||
disableMovement = false,
|
||||
disableCombat = true,
|
||||
@@ -222,7 +222,7 @@ RegisterNetEvent(getScript()..':Consume', function(itemName)
|
||||
end
|
||||
end)
|
||||
else
|
||||
triggerNotify(nil, string..Items[itemName].label.."..", "success")
|
||||
triggerNotify(nil, string..getItemLabel(itemName).."..", "success")
|
||||
end
|
||||
|
||||
consuming = true
|
||||
@@ -232,11 +232,11 @@ RegisterNetEvent(getScript()..':Consume', function(itemName)
|
||||
if model then
|
||||
if IsModelValid(model) == 1 then
|
||||
debugPrint("^5Debug^7: ^3PropSpawn^7: ^2Spawning consumable prop^7...")
|
||||
attachProp = makeProp({ prop = model, coords = vector4(0.0,0.0,0.0,0.0)}, 1, 1)
|
||||
attachProp = makeProp({ prop = model, coords = vec4(pedCoords.x, pedCoords.y, pedCoords.z, 0.0)}, 1, 1, true)
|
||||
AttachEntityToEntity(attachProp, Player, bone, P1, P2, P3, P4, P5, P6, true, true, false, true, 1, true)
|
||||
if model2 then
|
||||
if IsModelValid(model2) == 1 then
|
||||
attachProp2 = makeProp({ prop = model2, coords = vector4(0.0,0.0,0.0,0.0)}, 1, 1)
|
||||
attachProp2 = makeProp({ prop = model2, coords = vec4(pedCoords.x, pedCoords.y, pedCoords.z, 0.0)}, 1, 1)
|
||||
AttachEntityToEntity(attachProp2, Player, bone2, P7, P8, P9, P10, P11, P12, true, true, false, true, 1, true)
|
||||
else
|
||||
print("^5Debug^7: ^3PropSpawn^7: ^2Second prop model isn't valid/found^7.")
|
||||
@@ -250,7 +250,7 @@ RegisterNetEvent(getScript()..':Consume', function(itemName)
|
||||
if DoesEntityExist(attachProp2) then
|
||||
destroyProp(attachProp2)
|
||||
attachProp2 = nil
|
||||
end
|
||||
end
|
||||
else
|
||||
print("^5Debug^7: ^3PropSpawn^7: ^2Prop model isn't valid/found^7.")
|
||||
end
|
||||
@@ -264,14 +264,14 @@ RegisterNetEvent(getScript()..':Consume', function(itemName)
|
||||
"Type: "..(type or ""),
|
||||
"Hunger: "..(needStats.hunger or 0).."%",
|
||||
"Thirst: "..(needStats.thirst or 0).."%",
|
||||
"Stress: "..(stress or 0).."%",
|
||||
"Stress: "..(needStats.stress or 0).."%",
|
||||
"Heal: "..(heal or 0).."%",
|
||||
"Armour: "..(armor or 0).."%",
|
||||
}, nil, nil)
|
||||
end
|
||||
makeInstructionalButtons({
|
||||
{ keys = { 194 }, text = "Stop Consuming" },
|
||||
})
|
||||
})
|
||||
if time <= 0 then
|
||||
consuming = false
|
||||
end
|
||||
@@ -285,76 +285,19 @@ RegisterNetEvent(getScript()..':Consume', function(itemName)
|
||||
else
|
||||
triggerNotify(nil, "Cancelled "..string, "error")
|
||||
end
|
||||
TriggerServerEvent(getScript()..":server:stopConsume")
|
||||
end
|
||||
Wait(0)
|
||||
time -= 12
|
||||
end
|
||||
StopEntityAnim(Player, anim, animDict, 1.0)
|
||||
unloadAnimDict(animDict)
|
||||
|
||||
if not cancelled then
|
||||
hideText()
|
||||
removeItem(itemName, 1)
|
||||
if returnItem ~= nil then
|
||||
debugPrint("returnItem detected")
|
||||
currentToken = triggerCallback(AuthEvent)
|
||||
addItem(returnItem.item, returnItem.amount)
|
||||
end
|
||||
|
||||
-- Reward Item calculations
|
||||
CreateThread(function()
|
||||
if RewardItem then
|
||||
debugPrint("Reward Item detected")
|
||||
for i = 1, consumable.amounttogive do
|
||||
local rarity = math.random(1, 4) -- rarity calculation
|
||||
while true do
|
||||
local item = math.random(1, countTable(RewardItem)) -- random item in the list to pick
|
||||
if RewardItem[item].rarity >= rarity then
|
||||
currentToken = triggerCallback(AuthEvent)
|
||||
addItem(RewardItem[item].item, math.random(1, RewardItem[item].max or 1))
|
||||
debugPrint("^5Debug^7: ^2Given reward prize^7: '^6"..RewardItem[item].item.."^7'")
|
||||
break
|
||||
end
|
||||
Wait(100)
|
||||
end
|
||||
Wait(1500)
|
||||
end
|
||||
end
|
||||
end)
|
||||
if needStats then
|
||||
jsonPrint(needStats)
|
||||
if needStats.hunger > 0 then
|
||||
local hunger = 0
|
||||
if Core and Core.Functions then
|
||||
hunger = (Core.Functions.GetPlayerData().metadata["hunger"] or 0) + needStats.hunger
|
||||
hunger = hunger > 100 and 100 or hunger
|
||||
TriggerServerEvent(getScript()..":server:finishConsume", needStats)
|
||||
|
||||
elseif ESX and ESX.GetPlayerData then
|
||||
hunger = (needStats.hunger / 100) * 1000000
|
||||
hunger = hunger > 1000000 and 1000000 or hunger
|
||||
end
|
||||
|
||||
TriggerServerEvent(getScript()..":server:setNeed", "hunger", hunger)
|
||||
end
|
||||
|
||||
if needStats.thirst > 0 then
|
||||
local thirst = 0
|
||||
if Core and Core.Functions then
|
||||
thirst = (Core.Functions.GetPlayerData().metadata["thirst"] or 0) + needStats.thirst
|
||||
thirst = thirst > 100 and 100 or thirst
|
||||
|
||||
elseif ESX and ESX.GetPlayerData then
|
||||
thirst = (needStats.thirst / 100) * 1000000
|
||||
thirst = thirst > 1000000 and 1000000 or thirst
|
||||
end
|
||||
|
||||
TriggerServerEvent(getScript()..":server:setNeed", "thirst", thirst)
|
||||
end
|
||||
end
|
||||
debugPrint("^5Debug^7: ^2Hunger^7: [^6"..(needStats.hunger or 0).."^7] ^2Thrist^7: [^6"..(needStats.thirst or 0).."^7]" )
|
||||
if stress and stress ~= 0 then
|
||||
debugPrint("^5Debug^7: ^3Consume^7: ^2Relieving ^6"..stress.." ^2stress^7.")
|
||||
TriggerServerEvent('hud:server:RelieveStress', stress)
|
||||
end
|
||||
if heal and heal ~= 0 then
|
||||
debugPrint("^5Debug^7: ^3Consume^7: ^2Healing player by^7: ^6"..heal)
|
||||
SetEntityHealth(Player, GetEntityHealth(Player) + heal)
|
||||
@@ -364,20 +307,42 @@ RegisterNetEvent(getScript()..':Consume', function(itemName)
|
||||
TriggerServerEvent('hospital:server:SetArmor', (GetPedArmour(Player) + armor)) SetPedArmour(Player, (GetPedArmour(Player) + armor))
|
||||
end
|
||||
if type == "alcohol" then
|
||||
alcoholCount += 1
|
||||
debugPrint("^5Debug^7: ^3Consume^7: ^2Current ^4alcoholCount^7: ^6"..alcoholCount)
|
||||
if alcoholCount > 1 and alcoholCount < 4 then
|
||||
TriggerEvent("evidence:client:SetStatus", "alcohol", 200)
|
||||
elseif alcoholCount >= 4 then
|
||||
TriggerEvent("evidence:client:SetStatus", "heavyalcohol", 200)
|
||||
CreateThread(function()
|
||||
AlienEffect()
|
||||
end) -- Used as overdosing/too drunk effect
|
||||
if checkExportExists("jim_bridge", "addAlcoholCount") then
|
||||
exports.jim_bridge:addAlcoholCount(1, stats.canOD)
|
||||
else
|
||||
alcoholCount = alcoholCount + 1
|
||||
debugPrint("^5Debug^7: ^3Consume^7: ^2Current ^4alcoholCount^7: ^6"..alcoholCount)
|
||||
if alcoholCount > 1 and alcoholCount <= 4 then
|
||||
TriggerEvent("evidence:client:SetStatus", "alcohol", 200)
|
||||
elseif alcoholCount >= 4 then
|
||||
TriggerEvent("evidence:client:SetStatus", "heavyalcohol", 200)
|
||||
CreateThread(function()
|
||||
AlienEffect()
|
||||
end)
|
||||
end
|
||||
|
||||
if stats.canOD and alcoholCount >= 5 then
|
||||
SetEntityHealth(Player, GetEntityHealth(Player) - math.random(5, 10))
|
||||
end
|
||||
end
|
||||
end
|
||||
if pack then
|
||||
currentToken = triggerCallback(AuthEvent)
|
||||
addItem(pack.item, pack.amount)
|
||||
if type == "drug" then
|
||||
if checkExportExists("jim_bridge", "addDrugCount") then
|
||||
exports.jim_bridge:addDrugCount(1, stats.canOD or false)
|
||||
else
|
||||
drugCount = drugCount + 1
|
||||
debugPrint("^5Debug^7: ^3Consume^7: ^2Current ^4drugCount^7: ^6"..drugCount)
|
||||
if drugCount > 3 and drugCount < 7 then
|
||||
|
||||
elseif drugCount >= 7 then
|
||||
CreateThread(function()
|
||||
AlienEffect()
|
||||
end)
|
||||
end
|
||||
if stats.canOD and drugCount >= 4 then
|
||||
SetEntityHealth(Player, GetEntityHealth(Player) - math.random(5, 10))
|
||||
end
|
||||
end
|
||||
end
|
||||
if stats then
|
||||
if stats.screen then -- Screen effect activation
|
||||
@@ -398,14 +363,8 @@ RegisterNetEvent(getScript()..':Consume', function(itemName)
|
||||
end
|
||||
end
|
||||
if stats.canOD then
|
||||
drugCount += 1
|
||||
debugPrint("^5Debug^7: ^3Consume^7: ^2Current ^4drugCount^7: ^6"..drugCount)
|
||||
if drugCount >= 4 then
|
||||
debugPrint("^5Debug^7: ^3Consume^7: ^2Current ^4drugCount^7: ^6"..drugCount.."^7 - ^2 removing health")
|
||||
SetEntityHealth(PlayerPedId(), GetEntityHealth(Player) - math.random(10, 15))
|
||||
if drugCount >= 7 then
|
||||
CreateThread(function() AlienEffect() end) -- If too many drugs, if not dead will make you stumble
|
||||
end
|
||||
if drugCount >= 4 or alcoholCount >= 5 then
|
||||
SetEntityHealth(Player, GetEntityHealth(Player) - math.random(5, 10))
|
||||
end
|
||||
end
|
||||
if stats.effect then
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
name "Jim-Consumables"
|
||||
author "Jimathy"
|
||||
version "2.0.05"
|
||||
version "2.0.08"
|
||||
description "Consumables Script"
|
||||
fx_version "cerulean"
|
||||
game "gta5"
|
||||
|
||||
@@ -1,13 +1,50 @@
|
||||
local Consumables = Config.Consumables
|
||||
local Emotes = Config.Emotes
|
||||
local isConsuming = {}
|
||||
|
||||
local function massMakeUseable()
|
||||
for k, v in pairs(Config.Consumables) do
|
||||
createUseableItem(k, function(source, item)
|
||||
local src = source
|
||||
if not isConsuming[src] and hasItem(item.name, 1, src) then
|
||||
|
||||
registerConsume(src, item.name)
|
||||
TriggerClientEvent(getScript()..':Consume', src, item.name)
|
||||
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
function registerConsume(src, item)
|
||||
-- Start building server sided item return table
|
||||
local consumable = Consumables[item]
|
||||
isConsuming[src] = {
|
||||
item = item,
|
||||
rewardItem = checkReward(consumable) or nil,
|
||||
returnItem = checkReturnItem(consumable) or nil,
|
||||
packItem = checkPackItem(consumable) or nil
|
||||
}
|
||||
debugPrint("^5Debug^7: ^2Player ^3"..src.." ^2started consuming ^7'^2"..item.."^7'")
|
||||
end
|
||||
|
||||
RegisterNetEvent(getScript()..":RegisterConsuming", function(item)
|
||||
local src = source
|
||||
registerConsume(src, item)
|
||||
end)
|
||||
|
||||
onResourceStart(function()
|
||||
for k, v in pairs(Config.Consumables) do
|
||||
createUseableItem(k, function(source, item) TriggerClientEvent(getScript()..':Consume', source, item.name) end)
|
||||
if not Items[k] then print("^1Debug^7: ^2Item check ^7- '^1"..k.."^7' ^2not found in the shared lua^7") end
|
||||
if not Config.Emotes[v.emote] then print("^1Debug^7: ^2Emote check ^7- '^1"..k.."^7' ^2requested emote ^7'^6"..v.emote.."^7' - ^2not found in config^7.^2lua^7") end
|
||||
if not Items[k] then
|
||||
print("^1Debug^7: ^2Item check ^7- '^1"..k.."^7' ^2not found in the shared lua^7")
|
||||
end
|
||||
if not Config.Emotes[v.emote] then
|
||||
print("^1Debug^7: ^2Emote check ^7- '^1"..k.."^7' ^2requested emote ^7'^6"..v.emote.."^7' - ^2not found in config^7.^2lua^7")
|
||||
end
|
||||
end
|
||||
|
||||
massMakeUseable()
|
||||
|
||||
--Export Import System--
|
||||
GlobalState.jimConsumableItems = Consumables
|
||||
GlobalState.jimConsumableEmotes = Emotes
|
||||
@@ -21,6 +58,7 @@ end)
|
||||
local syncScheduled = false
|
||||
function syncConsumables()
|
||||
debugPrint("^5Statebag^7: ^2Sending ^6"..countTable(Consumables).." ^3Consumables ^2to all clients^7")
|
||||
massMakeUseable()
|
||||
GlobalState.jimConsumableItems = Consumables
|
||||
syncScheduled = false
|
||||
end
|
||||
@@ -32,6 +70,101 @@ function syncEmotes()
|
||||
emoteSyncScheduled = false
|
||||
end
|
||||
|
||||
-- Return item
|
||||
function checkPackItem(consumable)
|
||||
local result = nil
|
||||
if consumable.pack then
|
||||
result = { item = consumable.pack.item, amount = consumable.pack.amount }
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
-- Return item
|
||||
function checkReturnItem(consumable)
|
||||
local result = nil
|
||||
if consumable.returnItem then
|
||||
result = { item = consumable.returnItem.item, amount = consumable.returnItem.amount }
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
-- Reward items
|
||||
function checkReward(consumable)
|
||||
local result = nil
|
||||
local rewardItem = consumable.rewards or nil
|
||||
if rewardItem then
|
||||
debugPrint("Reward Item detected")
|
||||
for i = 1, consumable.amounttogive or 1 do
|
||||
local rarity = math.random(1, 4) -- rarity calculation
|
||||
while true do
|
||||
local item = math.random(1, countTable(rewardItem)) -- random item in the list to pick
|
||||
if rewardItem[item].rarity >= rarity then
|
||||
result = result or {}
|
||||
result[#result+1] = { item = rewardItem[item].item, amount = math.random(1, rewardItem[item].max or 1) }
|
||||
debugPrint("^5Debug^7: ^2Cachced reward prize^7: '^6"..rewardItem[item].item.."^7'")
|
||||
break
|
||||
end
|
||||
Wait(10)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
RegisterNetEvent(getScript()..":server:finishConsume", function(needTypes)
|
||||
local src = source
|
||||
|
||||
if isConsuming[src] ~= nil then
|
||||
|
||||
removeItem(isConsuming[src].item, 1, src)
|
||||
if isConsuming[src].rewardItem then
|
||||
debugPrint("^5Debug^7: ^2Giving player ^3"..src.." ^2reward items^7")
|
||||
for i = 1, #isConsuming[src].rewardItem do
|
||||
local item = isConsuming[src].rewardItem[i]
|
||||
addItem(item.item, item.amount, nil, src)
|
||||
end
|
||||
end
|
||||
if isConsuming[src].returnItem then
|
||||
debugPrint("^5Debug^7: ^2Giving player ^3"..src.." ^2return item^7")
|
||||
for i = 1, #isConsuming[src].returnItem do
|
||||
local item = isConsuming[src].returnItem[i]
|
||||
addItem(item.item, item.amount, nil, src)
|
||||
end
|
||||
end
|
||||
if isConsuming[src].packItem then
|
||||
for i = 1, #isConsuming[src].packItem do
|
||||
debugPrint("^5Debug^7: ^2Giving player ^3"..src.." ^2Pack items^7")
|
||||
local item = isConsuming[src].packItem[i]
|
||||
addItem(item.item, item.amount, nil, src)
|
||||
end
|
||||
end
|
||||
|
||||
-- Needs
|
||||
if needTypes.thirst then
|
||||
debugPrint("^5Debug^7: ^2Thrist^7: [^6"..(needTypes.thirst or 0).."^7]")
|
||||
setThirst(src, needTypes.thirst)
|
||||
end
|
||||
if needTypes.hunger then
|
||||
debugPrint("^5Debug^7: ^2Hunger^7: [^6"..(needTypes.hunger or 0).."^7]")
|
||||
setHunger(src, needTypes.hunger)
|
||||
end
|
||||
if needTypes.stress then
|
||||
debugPrint("^5Debug^7: ^2Stress^7: [^6"..(needTypes.stress or 0).."^7]")
|
||||
setStress(src, needTypes.stress)
|
||||
end
|
||||
isConsuming[src] = nil
|
||||
else
|
||||
return
|
||||
end
|
||||
end)
|
||||
|
||||
RegisterNetEvent(getScript()..":server:stopConsume", function()
|
||||
local src = source
|
||||
debugPrint("^5Player stopped consuming early^7", src)
|
||||
isConsuming[src] = nil
|
||||
end)
|
||||
|
||||
RegisterNetEvent(getScript()..':server:syncAddItem', function(itemName, data)
|
||||
if not Consumables[itemName] then
|
||||
Consumables[itemName] = data
|
||||
|
||||
@@ -47,7 +47,7 @@ Config.Consumables = {
|
||||
-- heal = 0, -- Set amount to heal by after consuming
|
||||
-- armor = 5, -- Amount of armor to add
|
||||
-- type = "food", -- Type: "alcohol" / "drink" / "food"
|
||||
-- canRun = true, -- If true player can run while using the item, not to it will cancel the event
|
||||
-- canRun = true, -- If true player can run while using the item, if not it will cancel the event
|
||||
--
|
||||
-- stats = {
|
||||
-- screen = "thermal", -- The screen effect to be played when after consuming the item "rampage" "turbo" "focus" "weed" "trevor" "nightvision" "thermal"
|
||||
@@ -74,7 +74,7 @@ Config.Consumables = {
|
||||
-- Example Box Item
|
||||
-- ["9_box"] = { -- Name of the box item in the shared
|
||||
-- emote = "uncuff", -- The emote than should run when "unboxing"
|
||||
-- canRun = true, -- If true player can run while using the item, not to it will cancel the event
|
||||
-- canRun = true, -- If true player can run while using the item, if not it will cancel the event
|
||||
-- time = 3500, -- How long it takes to use the item
|
||||
-- type = "pack", -- Designate it as a "pack" to the script knows what to do
|
||||
-- pack = {
|
||||
@@ -83,4 +83,18 @@ Config.Consumables = {
|
||||
-- },
|
||||
-- },
|
||||
|
||||
-- Example Cigar Item wiht requirements
|
||||
-- ["cigar"] = { -- Name of the item in your shared items
|
||||
-- emote = "smokecigar", -- The emote than should run when "smoking"
|
||||
-- canRun = true, -- If true player can run while using the item, if not it will cancel the event
|
||||
-- time = math.random(5000, 6000), -- How long it takes to use the item
|
||||
-- type = "smoke", -- Designate it as a "smoke" to the script knows what to do
|
||||
-- requiredItem = "lighter", -- Set a required item making it unsable if they don't have it
|
||||
-- stats = {
|
||||
-- effect = "stress",
|
||||
-- time = 5000,
|
||||
-- amount = math.random(10, 15),
|
||||
-- canOD = false
|
||||
-- }
|
||||
-- },
|
||||
}
|
||||
@@ -15,9 +15,23 @@ function GenerateRandomValues(data)
|
||||
transData[k] = v
|
||||
end
|
||||
end
|
||||
return transData["time"],
|
||||
transData["stress"],
|
||||
transData["heal"],
|
||||
transData["armor"],
|
||||
{ hunger = transData["hunger"], thirst = transData["thirst"] }
|
||||
if transData.hunger > 0 then
|
||||
transData.hunger = transData.hunger > 100 and 100 or transData.hunger
|
||||
end
|
||||
|
||||
if transData.thirst > 0 then
|
||||
transData.thirst = transData.thirst > 100 and 100 or transData.thirst
|
||||
end
|
||||
|
||||
if transData.stress > 0 then
|
||||
transData.stress = transData.stress > 100 and 100 or transData.stress
|
||||
end
|
||||
return transData["time"],
|
||||
transData["heal"],
|
||||
transData["armor"],
|
||||
{
|
||||
hunger = transData["hunger"],
|
||||
thirst = transData["thirst"],
|
||||
stress = transData["stress"]
|
||||
}
|
||||
end
|
||||
@@ -1,6 +1,7 @@
|
||||
2.0.05
|
||||
2.0.08
|
||||
|
||||
- Fix ESX Hunger events
|
||||
- Fix minor progressBar option issues
|
||||
- Fix issues with stress calculations
|
||||
- Separates "drug control" from canOD boolean
|
||||
- Adds support for jim_bridge built-in synchronized alcohol/drug effects
|
||||
|
||||
https://github.com/jimathy/jim-consumables
|
||||
https://github.com/jimathy/jim-consumables/releases/latest
|
||||
Reference in New Issue
Block a user