first commit

This commit is contained in:
Jonny_Bro (Nikita) 2023-11-16 15:01:19 +05:00
commit e4d5311906
2340 changed files with 508209 additions and 0 deletions

2
.github/FUNDING.yml vendored Normal file
View file

@ -0,0 +1,2 @@
custom:
- https://octothorp.team/shop/chips

21
.gitignore vendored Normal file
View file

@ -0,0 +1,21 @@
/docker/runtime-data
config.ts
# ignore assets
*.jpg
*.png
*.xcf
*.mdl
*.phy
*.vtx
*.vvd
*.vmt
*.vtf
*.wav
*.mp3
*.ogg
*.eot
*.svg
*.ttf
*.woff
*.otf

26
.gitlab-ci.yml Normal file
View file

@ -0,0 +1,26 @@
image: 'octoteam/gmod-test:latest'
services:
- mariadb:latest
variables:
GIT_SUBMODULE_STRATEGY: recursive
MYSQL_DATABASE: gmod_dbg_dev
MYSQL_ROOT_PASSWORD: octoteam ci/cd
stages:
- test
test:
stage: test
script:
# copy repo into gmod server
- cp -R * /opt/server
# move ci configs
- cd /opt/server
- cp config.ci.ts config.ts
- cp server.ci.cfg garrysmod/cfg/server.cfg
# run octolib scripts
- cd octolib && npm i
- npm run setup
- npm run test server

View file

@ -0,0 +1,32 @@
### Что наблюдается?
Опиши подробно, что именно происходит на момент написания репорта
Пример: Кнопка не нажимается, ничего не происходит...
### Как это должно работать?
Как, по твоему мнению, это должно работать, что нужно изменить
Пример: После нажатия кнопки должно открываться меню!
### Как это повторить?
Пошагово опиши, как повторить эту ошибку
Пример:
1. Открыть меню на клавишу X
2. Нажать на кнопку ABC
3. ???
### Ошибки в консоли
Если при этом в консоли появлялись какие-то ошибки, скопируй их сюда
Пример:
```
[dobrograd] addons/octoteam/devteam:42: developers not found (work expected, got nil)
1. Work - [C]:-1
2. unknown - addons/octoteam/devteam:42
```
### Обратная связь
Если нам понадобится что-то уточнить, как с тобой связаться?
Пример: Discord - username#1234

3
.gitmodules vendored Normal file
View file

@ -0,0 +1,3 @@
[submodule "octolib"]
path = octolib
url = ../../gmod/addons/octolib

60
README.md Normal file
View file

@ -0,0 +1,60 @@
# Сочные сливы Доброград 13.06.2022 (repack by chelog) сенсация 2023
Поскольку за последнее время я устал от разного рода сообщений в ЛС по поводу слитой сборки сервера, я решил залить ее самостоятельно. И так известно, что ресурсам на сайтах и в Telegram-каналах со сливами не стоит доверять, так как легко словить какой-нибудь бэкдур или вирус, поэтому вот вам чистая сборка ровно той же версии
Пользуйтесь на здоровье и развивайтесь, я буду очень рад, если это кому-то поможет научиться разработке, как на наших успехах, так и ошибках. Этот код никак не зарегистрирован юридически и скорей всего я никого не смогу остановить, но хочу чисто по-человечески попросить вас не использовать целые системы, аддоны или сборку в коммерческих целях
Честно говоря, я сам в шоке, насколько сильно изменилась структура и статус проекта всего за один год (к примеру, у нас уже нет TS в проекте, октолиба и развертка очень повзрослели и многое другое), но выкладывать самую новую версию по понятным причинам не буду :^) Этот проект был почти самым первым, что я начал делать в Garry's Mod, и понятное дело, здесь есть код из далекого 2017, баги и недоработки, которые на сегодняшный день мы уже исправили (а может и нет), но это было очень крутое путешествие и старт моей карьеры в геймдеве! В любом случае я буду очень благодарен вашим сообщениям о любых находках, в идеале открывайте MR или issue
**Dmitry Antonov** aka **[chelog](https://t.me/chelog)**
*Далее следует оригинальный, старый Readme:*
---
# [-> Справка по разработке <-](https://wiki.octothorp.team/ru/code)
# Установка
```sh
# если работаем под Windows, все запускаем внутри WSL
# скопируем репозиторий к себе на устройство
git clone --recurse-submodules https://gitlab.octo.gg/public-projects/dobrograd-13-06-2022 dobrograd
cd dobrograd
# скопируем и настроим конфиг сервера
cp config.example.ts config.ts
# исправим разрешения у папок, иначе контейнеры не будут иметь доступа
# если команда setfacl не найдена, надо установить "acl" через apt
chmod 777 $(find . -type d)
setfacl -dm u::rwx,g::rwx,o::rwx $(find . -type d)
```
# Работа
В скриптах проект называется "gmod" для того, чтобы сервер использовал общий кэш загрузки аддонов, таким образом несколько серверов переиспользуют скачанный контент, чтобы не использовать лишнее место на диске
```sh
# все скрипты выполняются в WSL в корневой папке проекта
# запустить проект и все связанные с ним сервисы
docker compose -p gmod up
# прикрепить терминал к консоли сервера, чтобы в него можно было слать команды
docker attach dbg_game
# остановить контейнеры
docker compose -p gmod stop
# остановить и удалить контейнеры (для обновления конфигов, данные при этом останутся)
docker compose -p gmod down
# полный сброс кэша docker если что-то сломалось, перед этим надо прописать скрипт с down
docker system prune -a
```
Подключиться к серверу можно по адресу, полученному из `wsl hostname -I`, или же можно поставить `wsl2host`, про который говорится в [настройке окружения](https://wiki.octothorp.team/ru/code)
Для некоторых скриптов есть поддержка прямо в расширении VS Code, но сначала надо хотя бы раз вручную запустить `up`-скрипт через терминал:
![](https://i.imgur.com/0318kXb.png) ![](https://i.imgur.com/WpVzAEc.png)

22
config.ci.ts Normal file
View file

@ -0,0 +1,22 @@
import base from './config.example'
const config = Object.assign({}, base)
config.port = 28015
config.hibernateThink = true
config.octoservicesURL = 'https://octothorp.team/api'
config.keys.services = ''
config.db = {
host: 'mariadb',
user: 'root',
pass: 'octoteam ci/cd',
port: 3306,
main: 'gmod_dbg_dev',
admin: 'gmod_dbg_dev',
shop: 'gmod_dbg_dev',
}
export default config

58
config.example.ts Normal file
View file

@ -0,0 +1,58 @@
import Config from './octolib/core/config'
export interface DobrogradConfig extends Config {
defaultHostName?: string
adminMention?: string
testEnabled?: boolean
disableGCrash?: boolean
requireLauncher?: boolean
}
const config: DobrogradConfig = {
dev: true,
serverGroupID: 'dbg_dev',
serverID: 'dbg_dev',
tickrate: 16,
port: 27015,
language: 'ru',
workshopCollection: 570795184,
gamemode: 'darkrp',
map: 'rp_evocity_dbg_230226',
maxPlayers: 16,
hibernateThink: true,
octoservicesURL: 'https://octothorp.team/api',
serverAccount: '',
steamKey: '',
imgurKey: '',
keys: {
services: '',
cats: '',
logs: '',
test: '',
},
webhooks: {},
db: {
host: 'mariadb',
user: 'root',
pass: '',
port: 3306,
main: 'gmod_dobrograd',
admin: 'gmod_dobrograd',
shop: 'gmod_dobrograd',
},
disableGCrash: true,
testEnabled: false,
defaultHostName: 'DBG DEV',
adminMention: '',
requireLauncher: false,
}
export default config

59
docker-compose.yml Normal file
View file

@ -0,0 +1,59 @@
networks:
default:
labels: &labels
- project=dobrograd
volumes:
steam-cache:
game-cache:
services:
mariadb:
labels: *labels
container_name: dbg_db
image: mariadb:10.7
environment:
MARIADB_ALLOW_EMPTY_ROOT_PASSWORD: true
MARIADB_DATABASE: gmod_dobrograd
volumes:
- ./docker/runtime-data/mysql:/var/lib/mysql
ports:
- '3306:3306'
healthcheck:
test: ['CMD', 'mysqladmin', 'ping', '--silent']
interval: 2s
retries: 15
gameserver:
labels: *labels
container_name: dbg_game
stdin_open: true
tty: true
build:
context: .
dockerfile: ./docker/Dockerfile.local
labels: *labels
target: setup-gameserver
environment:
STARTUP: ./gameserver-entrypoint.sh
ports:
- '8888:8888' # web interface for code runner
- '27099:27099' # luadev
- '27015:27015/tcp'
- '27015:27015/udp'
volumes:
- steam-cache:/home/container/gameserver/steam_cache
- game-cache:/home/container/gameserver/garrysmod/cache
- ./gameserver-entrypoint.sh:/home/container/gameserver-entrypoint.sh
- ./docker/runtime-data/garrysmod-data:/home/container/gameserver/garrysmod/data
- ./garrysmod/addons:/home/container/gameserver/garrysmod/addons
- ./garrysmod/gamemodes/darkrp:/home/container/gameserver/garrysmod/gamemodes/darkrp
- ./octolib:/home/container/gameserver/octolib
- ./config.example.ts:/home/container/gameserver/config.example.ts
- ./config.ts:/home/container/gameserver/config.ts
- ./server.cfg:/home/container/gameserver/garrysmod/cfg/server.cfg
depends_on:
mariadb:
condition: service_healthy
restart: unless-stopped

72
docker/Dockerfile.local Normal file
View file

@ -0,0 +1,72 @@
FROM ubuntu:18.04 AS base
LABEL author='Dmitry Antonov' maintainer='chelog@octothorp.team'
RUN dpkg --add-architecture i386 \
&& apt update \
&& apt upgrade -y \
&& apt install -y \
ca-certificates \
curl \
gcc \
gdb \
git \
iproute2 \
lib32gcc1 \
lib32stdc++6 \
lib32tinfo5 \
lib32z1 \
libstdc++6 \
lua5.1 \
net-tools \
unzip \
zlib1g \
zlibc \
&& curl -sL https://deb.nodesource.com/setup_16.x | bash - \
&& apt install -y nodejs \
&& groupadd -g 999 container \
&& useradd -m -d /home/container -u 999 -g container container \
&& mkdir -p /home/container/gameserver/steam_cache \
&& mkdir -p /home/container/gameserver/garrysmod/cache \
&& chown -R container:container /home/container/gameserver \
&& chmod 777 -R /home/container/gameserver
# GAME SETUP
FROM base AS install-gameserver
WORKDIR /home/container
USER container
ENV USER=container HOME=/home/container
ENV LD_LIBRARY_PATH=/home/container/gameserver/bin
RUN curl -o ./steamcmd_linux.tar.gz https://steamcdn-a.akamaihd.net/client/installer/steamcmd_linux.tar.gz \
&& mkdir ./steamcmd \
&& tar -xvzf steamcmd_linux.tar.gz -C ./steamcmd \
&& rm steamcmd_linux.tar.gz \
&& ./steamcmd/steamcmd.sh +quit \
&& mkdir -p ./.steam/sdk32 \
&& cp -v ./steamcmd/linux32/steamclient.so ./.steam/sdk32/steamclient.so \
&& mkdir -p ./.steam/sdk64 \
&& cp -v ./steamcmd/linux64/steamclient.so ./.steam/sdk64/steamclient.so
RUN ./steamcmd/steamcmd.sh \
+force_install_dir /home/container/gameserver \
+login anonymous +app_update 4020 \
-validate \
-beta NONE \
+quit
FROM install-gameserver AS setup-gameserver
RUN curl -o ./luabin.zip https://cloud.octo.gg/s/oKHm9xXjcLDXwpf/download \
&& mkdir -p ./gameserver/garrysmod/lua/bin \
&& unzip -j ./luabin.zip -d ./gameserver/garrysmod/lua/bin \
&& rm ./luabin.zip
RUN curl -o ./content.zip -L https://www.dropbox.com/s/al7ruvnda4m8qgf/content.zip?dl=1 \
&& mkdir -p ./content/cstrike \
&& unzip ./content.zip -d ./content/cstrike \
&& rm ./content.zip \
&& echo '"mountcfg" {"cstrike" "/home/contrainer/cstrike"}' > /home/container/gameserver/garrysmod/cfg/mount.cfg
EXPOSE 27015/tcp 27015/udp
COPY ./docker/entrypoint.sh /entrypoint.sh
CMD ["/bin/bash", "/entrypoint.sh"]

13
docker/entrypoint.sh Normal file
View file

@ -0,0 +1,13 @@
#!/bin/bash
cd /home/container
sleep 1
# Make internal Docker IP address available to processes.
export INTERNAL_IP=`ip route get 1 | awk '{print $NF;exit}'`
# Replace Startup Variables
MODIFIED_STARTUP=`eval echo $(echo ${STARTUP} | sed -e 's/{{/${/g' -e 's/}}/}/g')`
echo ":/home/container$ ${MODIFIED_STARTUP}"
# Run the Server
eval ${MODIFIED_STARTUP}

6
gameserver-entrypoint.sh Normal file
View file

@ -0,0 +1,6 @@
#!/bin/bash
cd /home/container/gameserver/octolib
npm i
npm run setup
npm run dev

2
garrysmod/addons/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
# ignore local addons
local-*

View file

@ -0,0 +1,3 @@
octogui.cmenu.registerCategory('other', {
order = math.huge,
})

View file

@ -0,0 +1 @@
octogui.cmenu.registerCategory('rp')

View file

@ -0,0 +1,46 @@
octogui.cmenu.registerItem('other', 'idea', {
text = L.idea,
icon = octolib.icons.silk16('lightbulb'),
say = '/dbg_getidea',
})
octogui.cmenu.registerItem('other', 'nrp', {
text = L.nonrp_actions,
icon = octolib.icons.silk16('world'),
options = {
{
text = L.applications_and_ticket,
icon = octolib.icons.silk16('page_error'),
url = 'https://forum.octothorp.team/c/5',
}, {
text = L.send_pm,
icon = octolib.icons.silk16('email'),
build = function(sm)
local ply = LocalPlayer()
local _players = player.GetAll()
table.sort(_players, function(a, b) return a:GetName() < b:GetName() end)
for _, v in ipairs(_players) do
if v ~= ply then
local name = v:Name()
sm:AddOption(v:SteamName() .. ' (' .. name .. ')', octolib.fStringRequest(L.send_pm_hint .. v:SteamName() .. ' (' .. name .. ')', L.send_text, '', function(s)
octochat.say('/pm', ('"%s"'):format(name), s)
end, nil, L.ok, L.cancel)):SetColor(v:getJobTable().color)
end
end
end,
}, {
text = L.links,
icon = octolib.icons.silk16('link'),
options = {
{text = L.start, url = 'https://wiki.octothorp.team/dobrograd/start' },
{text = L.site, url = 'https://octothorp.team' },
{text = L.wiki, url = 'https://wiki.octothorp.team' },
{text = L.forum, url = 'http://forum.octothorp.team' },
{text = L.group_vk, url = 'https://vk.com/octoteam' },
{text = L.group_steam, url = 'https://steamcommunity.com/groups/octothorp-team' },
{text = L.rules, url = 'https://wiki.octothorp.team/dobrograd/rules' },
},
}
},
})

View file

@ -0,0 +1,11 @@
octogui.cmenu.registerItem('rp', 'chance', {
text = L.chance,
icon = octolib.icons.silk16('dice'),
options = {
{text = L.pull_card, icon = octolib.icons.silk16('bullet_green'), say = '/card'},
{text = L.roll_the_dice, icon = octolib.icons.silk16('bullet_yellow'), say = '/dice'},
{text = L.get_chance, icon = octolib.icons.silk16('bullet_blue'), say = '/roll'},
{text = L.rock_paper_scissors, icon = octolib.icons.silk16('bullet_red'), say = '/rockpaperscissors'},
{text = 'Подбросить монетку', icon = octolib.icons.silk16('bullet_purple'), say = '/coin'},
},
})

View file

@ -0,0 +1,154 @@
--[[------------------------------------------
A.P.G. - a lightweight Anti Prop Griefing solution (v2.2.0)
Made by :
- While True (http://steamcommunity.com/id/76561197972967270)
- LuaTenshi (http://steamcommunity.com/id/76561198096713277)
Licensed to : http://steamcommunity.com/id/76561198136465722
====================================================================================
/!\ READ ME /!\ /!\ READ ME /!\ /!\ READ ME /!\
====================================================================================
This file is the default config file.
If you want to configure APG to fit your server needs, you can either modify this file
or edit the config ingame ( using the chat command : !apg ).
You can now also use "apg" in console!
]]--------------------------------------------
APG.cfg = APG.cfg or {}
APG.modules = APG.modules or {}
--[[----------
Your very own custom function
This function will run whenever lag is detected on your server!
]]------------
function APG.customFunc( notify )
-- Do something
end
--[[----------
Avalaible premade functions - THIS IS INFORMATIVE PURPOSE ONLY !
]]------------
if CLIENT then
APG_lagFuncs = { -- THIS IS INFORMATIVE PURPOSE ONLY !
"cleanup_all", -- Cleanup every props/ents protected by APG (not worldprops nor vehicles)
"cleanup_unfrozen", -- Cleanup only unfrozen stuff
"ghost_unfrozen", -- Ghost unfrozen stuff
"freeze_unfrozen", -- Freeze unfrozen stuff
"smart_cleanup", -- Cleanup unfrozen fading doors, freeze unfrozens, remove large stacks
"custom_function" -- Your custom function (see APG.customFunc)
} -- THIS IS INFORMATIVE PURPOSE ONLY !
end
--[[------------------------------------------
DEFAULT SETTINGS -- You CAN edit this part, but you SHOULDN'T
]]--------------------------------------------
local defaultSettings = {}
defaultSettings.modules = { -- Set to true of false to enable/disable module
["ghosting"] = true,
["stack_detection"] = true,
["lag_detection"] = true,
["misc"] = true,
["misc2"] = true,
}
defaultSettings.cfg = {
--[[----------
Ghosting module
]]------------
ghost_color = { value = Color(34, 34, 34, 220) ,desc = "Color set on ghosted props" },
bad_ents = {
value = {
["prop_physics"] = true,
["wire_"] = false,
["keypad"] = false,
},
desc = "Entities to ghost/control/secure (true if exact name, false if it is a pattern"},
alwaysFrozen = { value = false , desc = "Set to true to auto freeze props on physgun drop (aka APA_FreezeOnDrop)" },
--[[----------
Stack detection module
]]------------
stackMax = { value = 20, desc = "Max amount of entities stacked in a small area"},
stackArea = { value = 15, desc = "Sphere radius for stack detection (gmod units)"},
--[[----------
Lag detection module
]]------------
lagTrigger = { value = 75, desc = "[Default: 75%] Differential threshold between current lag and average lag."},
lagsCount = { value = 8, desc = "Number of consectuives laggy frames in order to run a cleanup."},
bigLag = { value = 2, desc = "Maximum time (seconds) between 2 frames to trigger a cleanup"},
lagFunc = { value = "ghost_unfrozen", desc = "Function ran on lag detected, see APG_lagFuncs." },
lagFuncTime = { value = 20, desc = "Time (seconds) between 2 anti lag function (avoid spam)"},
lagFuncNotify = { value = 2, desc = "Notify : 0 - Disabled, 1 - Everyone, 2 - Admins only"}, -- Available soon
--[[----------
MISC
]]------------
--[[ Vehicles ]]--
vehDamage = { value = false, desc = "True to disable vehicles damages, false to enable." },
vehNoCollide = { value = false, desc = "True to disable collisions between vehicles and players"},
vehIncludeWAC = { value = true, desc = "Check for WAC vehicles."},
--[[ Props related ]]--
blockPhysgunReload = { value = false, desc = "Block players from using physgun reload"},
autoFreeze = { value = false, desc = "Freeze every unfrozen prop each X seconds" },
autoFreezeTime = { value = 120, desc = "Auto freeze timer (seconds)"},
thFadingDoors = { value = true, desc = "Inject custom hooks into Fading Doors" },
FadingDoorGhosting = { value = true, desc = "Activate fading door ghosting" },
frzr9k = { value = false, desc = "Activate FRZR9K (Sleepy Physics)" },
AllowPK = { value = false, desc = "Allow prop killing (Won't work well with ghosting)" }
}
--[[------------------------------------------
LOADING SAVED SETTINGS -- DO NOT EDIT THIS PART
]]--------------------------------------------
if SERVER and file.Exists( "apg/settings.txt", "DATA" ) then
table.Merge( APG, defaultSettings ) -- Load the default settings first!
local settings = file.Read( "apg/settings.txt", "DATA" )
settings = util.JSONToTable( settings )
if not settings.modules or not settings.cfg then
ErrorNoHalt("Your custom settings have not been loaded because you have a misconfigured settings file! The default settings were used instead!")
return
end
local removedSetting = {}
for k, v in next, settings.modules do
if defaultSettings.modules[k] == nil then
settings.modules[k] = nil
table.insert(removedSetting, k)
end
end
for k, v in next, settings.cfg do
if defaultSettings.cfg[k] == nil then
settings.cfg[k] = nil
table.insert(removedSetting, k)
end
end
if next(removedSetting) then
print("[APG] Settings File Updated. (Conflicts Resolved)")
print("[APG] The Following Settings Have Been Removed: ")
for _,v in next, removedSetting do
print("\t> \""..tostring(v).."\" has been removed.")
end
removedSetting = nil
file.Write("apg/settings.txt", util.TableToJSON(settings))
end
table.Merge( APG, settings )
else
table.Merge( APG, defaultSettings )
end

View file

@ -0,0 +1,202 @@
carDealer.sellPrice = 0.75
carDealer.defaultDeposit = 25000
carDealer.plateSymbols = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
carDealer.plateLength = 7
carDealer.maxCars = {
rp_riverden_dbg_220313 = 12,
default = 10,
}
carDealer.despawnDistance = 300
carDealer.notify = octolib.notify.send
function carDealer.formatMoney(amount)
return DarkRP.formatMoney(amount)
end
function carDealer.addMoney(ply, amount)
ply:BankAdd(amount)
end
function carDealer.hasMoney(ply, amount)
return ply:BankHas(amount)
end
carDealer.civilSpawns = {
rp_evocity_dbg_220222 = {
{ Vector(-4656, -7535, 225), Angle(0,-90,0) }, -- douglas
{ Vector(-4656, -7210, 225), Angle(0,-90,0) },
{ Vector(-4656, -6885, 225), Angle(0,-90,0) },
{ Vector(-4656, -6560, 225), Angle(0,-90,0) },
{ Vector(-4656, -6235, 225), Angle(0,-90,0) },
{ Vector(-6649, -3711, 105), Angle(0,90,0) },
{ Vector(-6848, -3712, 105), Angle(0,90,0) },
{ Vector(-7038, -3709, 105), Angle(0,90,0) },
{ Vector(-7229, -3704, 105), Angle(0,90,0) },
{ Vector(-10196, -12573, 125), Angle(0,90,0) }, -- roosevelt
{ Vector(-10196, -13121, 125), Angle(0,90,0) },
{ Vector(-8614, 9807, 125), Angle(0,180,0) }, -- hospital
{ Vector(-8614, 9659, 125), Angle(0,180,0) },
{ Vector(-8617, 9515, 125), Angle(0,180,0) },
{ Vector(-8620, 9368, 125), Angle(0,180,0) },
{ Vector(-8623, 9224, 125), Angle(0,180,0) },
{ Vector(-8629, 8934, 125), Angle(0,180,0) },
},
rp_eastcoast_v4c = {
{ Vector(-3610, 2935, 50), Angle(0,-90,0) }, -- spawn
{ Vector(-3610, 2710, 50), Angle(0,-90,0) },
{ Vector(-3610, 2491, 50), Angle(0,-90,0) },
{ Vector(3410, -1615, 15), Angle(0,0,0) }, -- church
{ Vector(3410, -1742, 15), Angle(0,0,0) },
{ Vector(3410, -1874, 15), Angle(0,0,0) },
{ Vector(3410, -2004, 15), Angle(0,0,0) },
{ Vector(3410, -2134, 15), Angle(0,0,0) },
{ Vector(3410, -2394, 15), Angle(0,0,0) },
},
rp_truenorth_v1a = {
{ Vector(10800, 2825, -225), Angle(0, 180, 0) },
{ Vector(10800, 2625, -225), Angle(0, 180, 0) },
{ Vector(10800, 2425, -225), Angle(0, 180, 0) },
{ Vector(10800, 2225, -225), Angle(0, 180, 0) },
{ Vector(10800, 2025, -225), Angle(0, 180, 0) },
{ Vector(12000, 2825, -225), Angle(0, 180, 0) },
{ Vector(12000, 2625, -225), Angle(0, 180, 0) },
{ Vector(12000, 2425, -225), Angle(0, 180, 0) },
{ Vector(12000, 2225, -225), Angle(0, 180, 0) },
{ Vector(12000, 2025, -225), Angle(0, 180, 0) },
},
rp_riverden_dbg_220313 = {
{ Vector(-13222.8, 12256.7, 32.0593), Angle(0, 0, 0) },
{ Vector(-13223.4, 12641.8, 33.3913), Angle(0, 0, 0) },
{ Vector(-11782.2, 12956.9, 29.947), Angle(-0, 90, 0) },
{ Vector(-8721.59, 14412.8, 162.303), Angle(-0, 90, 0) },
{ Vector(-9608.99, 14898.1, 162.87), Angle(-0, -90, 0) },
{ Vector(-10335.6, 14413.3, 292), Angle(-0, 90, 0) },
{ Vector(-8905.67, 14893.9, 290.42), Angle(-0, -90, 0) },
{ Vector(-10077, 8046.36, -227.332), Angle(-0, -90, 0) },
{ Vector(-11037.4, 4706.57, -232.694), Angle(0, 0, 0) },
{ Vector(-11034.7, 5272.99, -231.204), Angle(0, 0, 0) },
{ Vector(-9210.54, -13671, -231.101), Angle(-0, 90, 0) },
{ Vector(12482.3, -8619.35, 804.961), Angle(-0, 90, 0) },
{ Vector(-6446.69, 13275.5, 24.4091), Angle(0, 0, 0) },
},
}
carDealer.policeSpawns = {
rp_evocity_dbg_220222 = {
{ Vector(-8050, -8715, 125), Angle(0,180,0) }, -- pd
{ Vector(-8050, -8880, 125), Angle(0,180,0) },
{ Vector(-8050, -9045, 125), Angle(0,180,0) },
{ Vector(-8050, -9210, 125), Angle(0,180,0) },
{ Vector(-8050, -9375, 125), Angle(0,180,0) },
{ Vector(-8050, -9540, 125), Angle(0,180,0) },
{ Vector(-8050, -9705, 125), Angle(0,180,0) },
},
rp_eastcoast_v4c = {
{ Vector(1590, 1215, 20), Angle(0,180,0) }, -- pd
{ Vector(1590, 1338, 20), Angle(0,180,0) },
},
rp_truenorth_v1a = {
{ Vector(2273, 3900, 40), Angle(0, 90, 0) },
{ Vector(2467, 3900, 40), Angle(0, 90, 0) },
{ Vector(2661, 3900, 40), Angle(0, 90, 0) },
{ Vector(2853, 3900, 40), Angle(0, 90, 0) },
{ Vector(3044, 3900, 40), Angle(0, 90, 0) },
{ Vector(3234, 3900, 40), Angle(0, 90, 0) },
},
rp_riverden_dbg_220313 = {
{ Vector(-8318.34, 8205.45, -214.671), Angle(0, 90, 0) },
{ Vector(-8126.12, 8205.15, -215.018), Angle(0, 90, 0) },
{ Vector(-7940.62, 8203.81, -215.73), Angle(0, 90, 0) },
{ Vector(-8511.8, 8205.09, -215.258), Angle(0, 90, 0) },
{ Vector(-8705.17, 8203.01, -216.215), Angle(0, 90, 0) },
},
}
carDealer.checks = {
civil = function(ply)
local job = ply:getJobTable()
if (ply:isCP() and not ply:isMayor()) or job.noCivilCars then return false, 'Доступно только гражданским' end
if job.hobo then return false, L.hobo_car end
end,
dobro = function(ply)
if not ply:IsSuperAdmin() and not ply:GetNetVar('os_dobro') then
return false, 'Этот автомобиль доступен только Добродеям'
end
end,
superadmin = function(ply)
if not ply:IsSuperAdmin() then return false, 'Доступно только старшей администрации' end
end,
no = function() return false end,
}
carDealer.tags = {
dobro = {octolib.icons.silk16('heart'), 'Только для Добродеев', true},
halloween = {octolib.icons.silk16('emotion_pumpkin'), 'Эксклюзивное авто с Хэллоуина', true},
truck = {octolib.icons.silk16('lorry'), 'Подойдет для перевозки грузов', true},
timed = {octolib.icons.silk16('time'), 'Ограниченное предложение'},
new = {octolib.icons.silk16('fire'), 'Новая модель'},
}
carDealer.limits = {
police = carDealer.limitedSpawn(game.GetMap():find('riverden') and 6 or 4, 'police', 'В городе уже много полицейских автомобилей, найди напарника или попробуй чуть позже'),
medic = carDealer.limitedSpawn(2, 'medic', 'В городе уже много медицинских автомобилей, найди напарника или попробуй чуть позже'),
fire = carDealer.limitedSpawn(2, 'fire', 'В городе уже много пожарных автомобилей, найди напарника или попробуй чуть позже'),
coroner = carDealer.limitedSpawn(2, 'coroner', 'В городе уже много автомобилей коронеров, найди напарника или попробуй чуть позже'),
mech = carDealer.limitedSpawn(1, 'mech', 'В городе уже есть автомобиль механика, найди напарника или попробуй чуть позже'),
}
carDealer.policeRadioStations = {
{
id = '-ENq6uQd',
title = 'Police Channel 1',
}, {
id = '16z4iZFY',
title = 'Police Channel 2',
}, {
id = '1BUEnRoy',
title = 'Police Channel 3',
}, {
id = 'dRTMFCjv',
title = 'Police & Fire Channel 4',
}, {
id = 'QDBlRQl4',
title = 'Police & Fire Channel 5',
}, {
id = 'pLwbQSYC',
title = 'Police & Fire Channel 6',
}, {
id = 'N4UujOAb',
title = 'Police & Fire Channel 7',
}, {
id = 'eBZbJcRO',
title = 'Police, Sheriff, Fire & EMS Channel 8',
},
}
carDealer.emsRadioStations = {
{
id = 'N4UujOAb',
title = 'Police & Fire Channel 1',
}, {
id = 'pLwbQSYC',
title = 'Police & Fire Channel 2',
}, {
id = 'dRTMFCjv',
title = 'Police & Fire Channel 3',
}, {
id = 'eBZbJcRO',
title = 'Police, Sheriff, Fire & EMS Channel 4',
},
}
octolib.shared('cars/pickups')
octolib.shared('cars/4doors')
octolib.shared('cars/2doors')
octolib.shared('cars/large')
octolib.shared('cars/sports')
octolib.shared('cars/police')
octolib.shared('cars/mech')

View file

@ -0,0 +1,192 @@
carDealer.addCategory('2doors', {
name = 'Двухдверные',
icon = 'octoteam/icons-16/user.png',
queue = true,
canUse = carDealer.checks.civil,
spawns = carDealer.civilSpawns,
})
-- carDealer.addVeh('faction2', {
-- name = 'Faction',
-- simfphysID = 'sim_fphys_gta4_faction',
-- price = 0,
-- bodygroups = {
-- [1] = {
-- name = 'Крыша',
-- variants = {
-- { 'Заводская', 1000 },
-- { 'Стекло', 35000 },
-- },
-- },
-- [2] = {
-- name = 'Капот',
-- variants = {
-- { 'Заводской', 1000 },
-- { 'С выступом', 50000 },
-- },
-- },
-- },
-- })
carDealer.addVeh('fortune2', {
name = 'Fortune',
simfphysID = 'sim_fphys_gta4_fortune',
price = 950000,
})
carDealer.addVeh('vigero2', {
name = 'Vigero',
simfphysID = 'sim_fphys_gta4_vigero',
price = 1250000,
})
carDealer.addVeh('rhapsody2', {
name = 'Rhapsody',
simfphysID = 'sim_fphys_tlad_rhapsody',
price = 2150000,
tags = { carDealer.tags.new },
})
carDealer.addVeh('sabre2', {
name = 'Sabre',
simfphysID = 'sim_fphys_gta4_sabre',
price = 2350000,
})
carDealer.addVeh('manana2', {
name = 'Manana',
simfphysID = 'sim_fphys_gta4_manana',
price = 2500000,
bodygroups = {
[1] = {
name = 'Крыша',
variants = {
{ 'Заводская', 1000 },
{ 'Закрытая', 190000 },
},
},
},
})
carDealer.addVeh('ruiner2', {
name = 'Ruiner',
simfphysID = 'sim_fphys_gta4_ruiner',
price = 2600000,
tags = { carDealer.tags.new },
default = {
bg = { [2] = 1, [3] = 1 },
},
bodygroups = {
[1] = {
name = 'Капот',
variants = {
{ 'Заводской', 1000 },
{ 'С вентиляцией', 75000 },
},
},
[2] = {
name = 'Крыша',
variants = {
{ 'Панорамная', 175000 },
{ 'Заводская', 1000 },
},
},
[3] = {
name = 'Багажник',
variants = {
{ 'Открытый', 80000 },
{ 'Заводской', 1000 },
},
},
},
})
carDealer.addVeh('sabregt2', {
name = 'Sabre GT',
simfphysID = 'sim_fphys_gta4_sabregt',
price = 2850000,
tags = { carDealer.tags.new },
bodygroups = {
[1] = {
name = 'Капот',
variants = {
{ 'Заводской', 1000 },
{ 'С воздухозаборником', 125000 },
{ 'С выступом', 45000 },
},
},
},
})
carDealer.addVeh('futo2', {
name = 'Futo',
simfphysID = 'sim_fphys_gta4_futo',
price = 3100000,
bodygroups = {
[1] = {
name = 'Бампер',
variants = {
{ 'Заводской', 1000 },
{ 'Тюнер', 75000 },
},
},
[2] = {
name = 'Тюнинг',
variants = {
{ 'Заводской', 1000 },
{ 'Рама, пороги, труба и сидение', 235000 },
},
},
[3] = {
name = 'Спойлер',
variants = {
{ 'Заводской', 1000 },
{ 'Тюнер', 95000 },
},
},
[4] = {
name = 'Капот',
variants = {
{ 'Заводской', 1000 },
{ 'Карбон', 160000 },
},
},
},
})
--
-- EVENT
--
carDealer.addVeh('halloween_sedan', {
name = 'Peyote',
simfphysID = 'sim_fphys_gta4_peyote',
price = 0,
tags = { carDealer.tags.halloween },
canSee = carDealer.checks.no,
canUse = carDealer.checks.civil,
bodygroups = {
[1] = {
name = 'Крыша',
variants = {
{ 'Заводская', 1000 },
{ 'Закрытая', 320000 },
},
},
[2] = {
name = 'Заднее крепление',
variants = {
{ 'Ничего', 1000 },
{ 'Запаска', 185000 },
},
},
[3] = {
name = 'Сидения',
variants = {
{ 'Заводские', 1000 },
{ 'Зебра', 210000 },
{ 'Черные', 75000 },
},
},
},
})

View file

@ -0,0 +1,198 @@
carDealer.addCategory('4doors', {
name = 'Четырехдверные',
icon = 'octoteam/icons-16/user.png',
queue = true,
canUse = carDealer.checks.civil,
spawns = carDealer.civilSpawns,
})
carDealer.addVeh('premier2', {
name = 'Premier',
simfphysID = 'sim_fphys_gta4_premier',
price = 450000,
})
carDealer.addVeh('esperanto2', {
name = 'Esperanto',
simfphysID = 'sim_fphys_gta4_esperanto',
price = 600000,
})
carDealer.addVeh('dilettante2', {
name = 'Dilettante',
simfphysID = 'sim_fphys_gta4_dilettante',
price = 700000,
})
carDealer.addVeh('merit2', {
name = 'Merit',
simfphysID = 'sim_fphys_gta4_merit',
price = 850000,
})
carDealer.addVeh('df2', {
name = 'DF8-90',
simfphysID = 'sim_fphys_gta4_df8',
price = 1350000,
bodygroups = {
[1] = {
name = 'Спойлер',
variants = {
{ 'Заводской', 1000 },
{ 'Высокий', 180000 },
{ 'Низкий', 120000 },
},
},
},
})
carDealer.addVeh('emperor2', {
name = 'Emperor',
simfphysID = 'sim_fphys_gta4_emperor',
price = 1450000,
})
carDealer.addVeh('schafter2', {
name = 'Schafter',
simfphysID = 'sim_fphys_gta4_schafter',
price = 2000000,
default = {
bg = { [1] = 1 },
},
bodygroups = {
[1] = {
name = 'Решетка',
variants = {
{ 'Частая', 95000 },
{ 'Заводская', 1000 },
},
},
[2] = {
name = 'Передний бампер',
variants = {
{ 'Заводской', 1000 },
{ 'Тюнер', 120000 },
},
},
[3] = {
name = 'Пороги',
variants = {
{ 'Заводские', 1000 },
{ 'Тюнер', 90000 },
},
},
[4] = {
name = 'Задний бампер',
variants = {
{ 'Заводской', 1000 },
{ 'Тюнер', 135000 },
},
},
},
})
carDealer.addVeh('vincent2', {
name = 'Vincent',
simfphysID = 'sim_fphys_gta4_vincent',
price = 2200000,
tags = { carDealer.tags.new },
bodygroups = {
[1] = {
name = 'Спойлер',
variants = {
{ 'Заводской', 1000 },
{ 'Спортивный', 115000 },
},
},
},
})
carDealer.addVeh('admiral2', {
name = 'Admiral',
simfphysID = 'sim_fphys_gta4_admiral',
price = 3200000,
})
carDealer.addVeh('cognoscenti2', {
name = 'Cognoscenti',
simfphysID = 'sim_fphys_gta4_cognoscenti',
price = 5250000,
})
carDealer.addVeh('superdiamond2', {
name = 'Super Diamond',
simfphysID = 'sim_fphys_tbogt_superd',
price = 5800000,
tags = { carDealer.tags.new },
})
carDealer.addVeh('superdiamond-coupe2', {
name = 'Super Diamond Coupe',
simfphysID = 'sim_fphys_tbogt_superd2',
price = 6000000,
tags = { carDealer.tags.new },
bodygroups = {
[1] = {
name = 'Крыша',
variants = {
{ 'Заводская', 1000 },
{ 'Мягкая', 450000 },
},
},
},
})
--
-- DOBRO
--
carDealer.addVeh('hakumai2', {
name = 'Hakumai',
simfphysID = 'sim_fphys_gta4_hakumai',
price = 2250000,
bodygroups = {
[1] = {
name = 'Пороги',
variants = {
{ 'Заводские', 1000 },
{ 'Тюнер', 140000 },
},
},
[2] = {
name = 'Спойлер',
variants = {
{ 'Заводской', 1000 },
{ 'Тюнер', 180000 },
},
},
[3] = {
name = 'Передний бампер',
variants = {
{ 'Заводской', 1000 },
{ 'Тюнер', 145000 },
},
},
[4] = {
name = 'Огни',
variants = {
{ 'Заводские', 1000 },
{ 'Противотуманки', 95000 },
},
},
},
canUse = carDealer.checks.dobro,
tags = { carDealer.tags.dobro },
})
--
-- EVENT
--
carDealer.addVeh('halloween_pickup', {
name = 'Regina',
simfphysID = 'sim_fphys_tlad_regina',
price = 0,
tags = { carDealer.tags.halloween },
canSee = carDealer.checks.no,
canUse = carDealer.checks.civil,
})

View file

@ -0,0 +1,41 @@
carDealer.addVeh('halloween_sedan', {
name = 'Peyote',
simfphysID = 'sim_fphys_gta4_peyote',
price = 0,
tags = { carDealer.tags.halloween },
canSee = carDealer.checks.no,
canUse = carDealer.checks.civil,
bodygroups = {
[1] = {
name = 'Крыша',
variants = {
{ 'Заводская', 1000 },
{ 'Закрытая', 320000 },
},
},
[2] = {
name = 'Заднее крепление',
variants = {
{ 'Ничего', 1000 },
{ 'Запаска', 185000 },
},
},
[3] = {
name = 'Сидения',
variants = {
{ 'Заводские', 1000 },
{ 'Зебра', 210000 },
{ 'Черные', 75000 },
},
},
},
})
carDealer.addVeh('halloween_pickup', {
name = 'Regina',
simfphysID = 'sim_fphys_tlad_regina',
price = 0,
tags = { carDealer.tags.halloween },
canSee = carDealer.checks.no,
canUse = carDealer.checks.civil,
})

View file

@ -0,0 +1,198 @@
carDealer.addCategory('large', {
name = 'Большие',
icon = 'octoteam/icons-16/user.png',
queue = true,
canUse = carDealer.checks.civil,
spawns = carDealer.civilSpawns,
})
carDealer.addVeh('ingot2', {
name = 'Ingot',
simfphysID = 'sim_fphys_gta4_ingot',
price = 1000000,
tags = { carDealer.tags.new },
bodygroups = {
[1] = {
name = 'Передний бампер',
variants = {
{ 'Заводской', 1000 },
{ 'С решеткой', 45000 },
},
},
[2] = {
name = 'Пороги',
variants = {
{ 'Заводские', 1000 },
{ 'Увеличенные', 35000 },
},
},
[3] = {
name = 'Решетка радиатора',
variants = {
{ 'Заводская', 1000 },
{ 'Без эмблемы', 25000 },
},
},
[4] = {
name = 'Крыша',
variants = {
{ 'Заводская', 1000 },
{ 'С рейлингами', 40000 },
},
},
},
})
carDealer.addVeh('rebla2', {
name = 'Rebla',
simfphysID = 'sim_fphys_gta4_rebla',
price = 1750000,
bodygroups = {
[1] = {
name = 'Пороги',
variants = {
{ 'Заводские', 1000 },
{ 'Тюнер', 85000 },
},
},
[2] = {
name = 'Передний бампер',
variants = {
{ 'Заводской', 1000 },
{ 'Тюнер', 115000 },
},
},
[3] = {
name = 'Задний бампер',
variants = {
{ 'Заводской', 1000 },
{ 'Тюнер', 130000 },
},
},
[4] = {
name = 'Спойлер',
variants = {
{ 'Заводской', 1000 },
{ 'Тюнер', 75000 },
},
},
[5] = {
name = 'Выхлоп',
variants = {
{ 'Заводской', 1000 },
{ 'Тюнер', 120000 },
},
},
},
})
carDealer.addVeh('habanero2', {
name = 'Habanero',
simfphysID = 'sim_fphys_gta4_habanero',
price = 2600000,
})
carDealer.addVeh('pony2', {
name = 'Pony',
simfphysID = 'sim_fphys_gta4_pony',
price = 3500000,
bodygroups = {
[1] = {
name = 'Крыша',
variants = {
{ 'Заводская', 1000 },
{ 'Рейлинги', 120000 },
},
},
},
})
carDealer.addVeh('moonbeam2', {
name = 'Moonbeam',
simfphysID = 'sim_fphys_gta4_moonbeam',
price = 3600000,
bodygroups = {
[1] = {
name = 'Крыша',
variants = {
{ 'Заводская', 1000 },
{ 'Рейлинги', 95000 },
{ 'Багажник', 650000 },
},
},
[2] = {
name = 'Пороги',
variants = {
{ 'Заводские', 1000 },
{ 'Спортивные', 135000 },
{ 'Металлические', 110000 },
{ 'Со вставками', 140000 },
},
},
[3] = {
name = 'Окна',
variants = {
{ 'Заводские', 1000 },
{ 'Закрытые', 60000 },
},
},
[4] = {
name = 'Аксессуары',
variants = {
{ 'Заводские', 1000 },
{ 'Запаска + лестница', 120000 },
},
},
[5] = {
name = 'Решетка',
variants = {
{ 'Заводская', 1000 },
{ 'Во всю ширину', 200000 },
},
},
},
})
carDealer.addVeh('huntley2', {
name = 'Huntley',
simfphysID = 'sim_fphys_gta4_huntley',
price = 4000000,
bodygroups = {
[1] = {
name = 'Тюнинг',
variants = {
{ 'Заводской', 1000 },
{ 'Выхлоп + решетка', 250000 },
},
},
},
})
carDealer.addVeh('mule2', {
name = 'Mule',
simfphysID = 'sim_fphys_gta4_mule',
price = 4400000,
customFOV = 38,
})
carDealer.addVeh('patriot2', {
name = 'Patriot',
simfphysID = 'sim_fphys_gta4_patriot',
price = 4850000,
bodygroups = {
[1] = {
name = 'Тюнинг',
variants = {
{ 'Заводской', 1000 },
{ 'Выхлоп + огни', 320000 },
},
},
[2] = {
name = 'Бампер',
variants = {
{ 'Заводской', 1000 },
{ 'Кунгурятник', 180000 },
},
},
},
})

View file

@ -0,0 +1,16 @@
carDealer.addCategory('mech', {
name = 'Механики',
icon = octolib.icons.silk16('wrench'),
canUse = function(ply) return ply:Team() == TEAM_MECH, 'Доступно только механикам' end,
spawns = carDealer.civilSpawns,
spawnCheck = carDealer.limits.mech,
limitGroup = 'mech',
})
carDealer.addVeh('towtruck', {
category = 'mech',
name = 'Tow Truck',
simfphysID = 'sim_fphys_gta4_bobcat_towtruck',
price = 30000,
deposit = true,
})

View file

@ -0,0 +1,86 @@
carDealer.addCategory('pickups', {
name = 'Пикапы',
icon = 'octoteam/icons-16/user.png',
queue = true,
canUse = carDealer.checks.civil,
spawns = carDealer.civilSpawns,
})
carDealer.addVeh('bobcat2', {
name = 'Bobcat',
simfphysID = 'sim_fphys_gta4_bobcat',
price = 550000,
bodygroups = {
[1] = {
name = 'Стойка',
variants = {
{ 'Заводская', 1000 },
[5] = { 'Укрепленная', 145000 },
},
},
[2] = {
name = 'Багажник',
variants = {
{ 'Заводской', 1000 },
{ 'Маленький', 90000 },
{ 'Полный', 265000 },
},
},
[3] = {
name = 'Бампер',
variants = {
{ 'Заводской', 1000 },
{ 'Кенгурятник', 80000 },
},
},
},
})
carDealer.addVeh('rancher2', {
name = 'Rancher',
simfphysID = 'sim_fphys_gta4_rancher',
price = 1200000,
bodygroups = {
[1] = {
name = 'Кузов',
variants = {
{ 'Заводской', 1000 },
{ 'Короб', 550000 },
{ 'Стойка', 180000 },
},
},
[2] = {
name = 'Бампер',
variants = {
{ 'Заводской', 1000 },
{ 'Кенгурятник', 90000 },
{ 'Фонари', 95000 },
},
},
},
})
carDealer.addVeh('contender2', {
name = 'Contender',
simfphysID = 'sim_fphys_gta4_e109',
price = 3500000,
bodygroups = {
[1] = {
name = 'Кузов',
variants = {
{ 'Заводской', 1000 },
{ 'Козырек + покрытие', 325000 },
{ 'Жеское покрытие', 280000 },
{ 'Козырек', 65000 },
{ 'Стойка + покрытие', 450000 },
},
},
[2] = {
name = 'Бампер',
variants = {
{ 'Заводской', 1000 },
{ 'Кенгурятник', 145000 },
},
},
},
})

View file

@ -0,0 +1,71 @@
carDealer.addCategory('police', {
name = 'Полицейские',
ems = true,
icon = 'octoteam/icons-16/user_policeman_white.png',
canUse = function(ply) return ply:isCP() and ply:Team() ~= TEAM_FBI and ply:Team() ~= TEAM_WCSO and ply:Team() ~= TEAM_MAYOR, 'Доступно только полиции' end,
spawns = carDealer.policeSpawns,
spawnCheck = carDealer.limits.police,
limitGroup = 'police',
})
carDealer.addVeh('police-vapid', {
category = 'police',
name = 'Police Vapid',
simfphysID = 'sim_fphys_gta4_police',
price = 30000,
deposit = true,
police = true,
radioWhitelist = carDealer.policeRadioStations,
})
carDealer.addVeh('police-merit', {
category = 'police',
name = 'Police Merit',
simfphysID = 'sim_fphys_gta4_police2',
price = 40000,
deposit = true,
police = true,
radioWhitelist = carDealer.policeRadioStations,
})
-- carDealer.addVeh('police-patriot', {
-- category = 'police',
-- name = 'Police Patriot',
-- simfphysID = 'sim_fphys_gta4_polpatriot',
-- price = 50000,
-- deposit = true,
-- police = true,
-- canUse = carDealer.checks.dobro,
-- tags = { carDealer.tags.dobro },
-- radioWhitelist = carDealer.policeRadioStations,
-- })
carDealer.addVeh('police-buffalo', {
category = 'police',
name = 'Police Buffalo',
simfphysID = 'sim_fphys_tbogt_police3',
price = 75000,
deposit = true,
police = true,
canUse = function(ply)
if ply:Team() == TEAM_DPD then return true end
if ply:isCP() and ply:Team() ~= TEAM_FBI and ply:Team() ~= TEAM_MAYOR then return carDealer.checks.dobro(ply) end
return false
end,
tags = { carDealer.tags.dobro },
radioWhitelist = carDealer.policeRadioStations,
})
-- carDealer.addVeh('police-enforcer', {
-- category = 'police',
-- name = 'Enforcer',
-- simfphysID = 'sim_fphys_gta4_nstockade',
-- price = 55000,
-- customFOV = 38,
-- deposit = true,
-- police = true,
-- bulletproof = true,
-- canUse = carDealer.checks.dobro,
-- tags = { carDealer.tags.dobro },
-- radioWhitelist = carDealer.policeRadioStations,
-- })

View file

@ -0,0 +1,76 @@
carDealer.addCategory('sports', {
name = 'Спортивные',
icon = 'octoteam/icons-16/user.png',
queue = true,
canUse = carDealer.checks.civil,
spawns = carDealer.civilSpawns,
})
carDealer.addVeh('feltzer2', {
name = 'Feltzer',
simfphysID = 'sim_fphys_gta4_feltzer',
price = 3850000,
bodygroups = {
[1] = {
name = 'Крыша',
variants = {
{ 'Заводская', 1000 },
{ 'Мягкая', 275000 },
{ 'Жесткая', 240000 },
},
},
},
})
carDealer.addVeh('comet2', {
name = 'Comet',
simfphysID = 'sim_fphys_gta4_comet',
price = 5000000,
})
carDealer.addVeh('banshee2', {
name = 'Banshee',
simfphysID = 'sim_fphys_gta4_banshee',
price = 5800000,
default = {
bg = { [2] = 1 },
},
bodygroups = {
[1] = {
name = 'Крыша',
variants = {
{ 'Заводская', 1000 },
{ 'Рама', 85000 },
{ 'Закрытая', 325000 },
},
},
[2] = {
name = 'Капот',
variants = {
{ 'С вентиляцией', 145000 },
{ 'Заводской', 1000 },
},
},
},
})
--
-- DOBRO
--
carDealer.addVeh('sultanrs2', {
name = 'Sultan RS',
simfphysID = 'sim_fphys_gta4_sultanrs',
price = 3000000,
bodygroups = {
[1] = {
name = 'Капот',
variants = {
{ 'Заводской', 1000 },
{ 'Воздухозаборник', 235000 },
},
},
},
canUse = carDealer.checks.dobro,
tags = { carDealer.tags.dobro },
})

View file

@ -0,0 +1,5 @@
dbgCerts.certTitles = {
npd = 'Удостоверение члена партии НПД',
investigator = 'Удостоверение сотрудника отдела расследований',
iad = 'Удостоверение инспектора отдела внутренних расследований',
}

View file

@ -0,0 +1,107 @@
--
-- dobrograd
--
resource.AddWorkshop '1407179012' -- rp_eastcoast_v4c
resource.AddWorkshop '2778554124' -- rp_evocity_dbg_220222
if game.GetMap():find('truenorth') then
resource.AddWorkshop '1601428630' -- rp_truenorth_v1a
resource.AddWorkshop '1601425051' -- rp_truenorth_v1a content 1
resource.AddWorkshop '1601404123' -- rp_truenorth_v1a content 2
end
if game.GetMap():find('riverden') then
resource.AddWorkshop '2778572819' -- rp_riverden_dbg
end
resource.AddWorkshop '1975435190' -- dbg content
resource.AddWorkshop '2507121628' -- transport content
resource.AddWorkshop '2558543740' -- characters content
resource.AddWorkshop '2532822854' -- props content 1
resource.AddWorkshop '2532517900' -- props content 2
resource.AddWorkshop '2534082994' -- props content 3
resource.AddWorkshop '1548302260' -- halloween stuff
resource.AddWorkshop '1238652515' -- new year stuff
resource.AddWorkshop '242776816' -- adv part contr
resource.AddFile 'resource/fonts/Roboto-Black.ttf'
resource.AddFile 'resource/fonts/Roboto-BlackItalic.ttf'
resource.AddFile 'resource/fonts/Roboto-Bold.ttf'
resource.AddFile 'resource/fonts/Roboto-BoldCondensed.ttf'
resource.AddFile 'resource/fonts/Roboto-BoldCondensedItalic.ttf'
resource.AddFile 'resource/fonts/Roboto-BoldItalic.ttf'
resource.AddFile 'resource/fonts/Roboto-Condensed.ttf'
resource.AddFile 'resource/fonts/Roboto-CondensedItalic.ttf'
resource.AddFile 'resource/fonts/Roboto-Italic.ttf'
resource.AddFile 'resource/fonts/Roboto-Light.ttf'
resource.AddFile 'resource/fonts/Roboto-LightItalic.ttf'
resource.AddFile 'resource/fonts/Roboto-Medium.ttf'
resource.AddFile 'resource/fonts/Roboto-MediumItalic.ttf'
resource.AddFile 'resource/fonts/Roboto-Regular.ttf'
resource.AddFile 'resource/fonts/Roboto-Thin.ttf'
resource.AddFile 'resource/fonts/Roboto-ThinItalic.ttf'
--
-- octolib
--
resource.AddWorkshop '1394544550' -- icons
resource.AddFile 'resource/fonts/arial.ttf'
resource.AddFile 'resource/fonts/arialbd.ttf'
resource.AddFile 'resource/fonts/arialbi.ttf'
resource.AddFile 'resource/fonts/arialblk.ttf'
resource.AddFile 'resource/fonts/ariali.ttf'
resource.AddFile 'resource/fonts/blogger.ttf'
resource.AddFile 'resource/fonts/bloggerb.ttf'
resource.AddFile 'resource/fonts/bloggerbi.ttf'
resource.AddFile 'resource/fonts/bloggeri.ttf'
resource.AddFile 'resource/fonts/bloggerl.ttf'
resource.AddFile 'resource/fonts/bloggerli.ttf'
resource.AddFile 'resource/fonts/bloggerm.ttf'
resource.AddFile 'resource/fonts/bloggermi.ttf'
resource.AddFile 'resource/fonts/fontawesome-webfont.ttf'
--
-- serverguard
--
resource.AddWorkshop '685130934'
--
-- simfphys
--
resource.AddWorkshop '771487490'
--
-- stormfox
--
resource.AddWorkshop '2447979470'
--
-- atm
--
resource.AddFile 'materials/newcity/atm.png'
resource.AddFile 'models/props_unique/atm01.mdl'
resource.AddSingleFile 'models/props_unique/atm01.dx80.vtx'
resource.AddSingleFile 'models/props_unique/atm01.dx90.vtx'
resource.AddSingleFile 'models/props_unique/atm01.mdl'
resource.AddSingleFile 'models/props_unique/atm01.phy'
resource.AddSingleFile 'models/props_unique/atm01.vtx'
resource.AddSingleFile 'models/props_unique/atm01.vvt'
resource.AddFile 'materials/models/props_unique/atm.vmt'
resource.AddSingleFile 'materials/models/props_unique/atm.vmt'
resource.AddSingleFile 'materials/models/props_unique/atm.vtf'
resource.AddSingleFile 'materials/models/props_unique/atm_ref.vtf'
--
-- fadmin (darkrp)
--
local function AddDir(dir)
local files, folders = file.Find(dir .. "/*", "GAME")
for _, fdir in pairs(folders) do
if fdir ~= ".svn" then AddDir(dir .. "/" .. fdir) end
end
for k, v in pairs(files) do resource.AddFile(dir .. "/" .. v) end
end
AddDir("materials/fadmin")

View file

@ -0,0 +1,50 @@
simpleOrgs.orgs = simpleOrgs.orgs or {}
local reloadUpstream = octolib.func.debounce(function()
hook.Run('octolib.event:reloadOrgs')
hook.Run('dbg-orgs.listLoaded')
end, 1)
function simpleOrgs.addOrg(id, data)
simpleOrgs.orgs[id] = data
data.members = {}
data.owners = {}
data.flyer = data.flyer or ''
data.url = ''
dbgDoorGroups.registerGroup(id, data.name or utf8.upper(id))
if data.rankOrder then
local dict = {}
for i, v in ipairs(data.rankOrder) do
dict[v] = i
end
data._rankOrder = dict
end
reloadUpstream()
end
local files, folders = file.Find('config/groups/*', 'LUA')
for _, v in ipairs(files) do
octolib.shared('config/groups/' .. string.StripExtension(v))
end
for _, v in ipairs(folders) do
local cats = file.Find('config/groups/' .. v .. '/cmenu/categories/*.lua', 'LUA')
for _, cat in ipairs(cats) do
octolib.client('config/groups/' .. v .. '/cmenu/categories/' .. cat:StripExtension())
end
local items = file.Find('config/groups/' .. v .. '/cmenu/items/*.lua', 'LUA')
for _, item in ipairs(items) do
octolib.client('config/groups/' .. v .. '/cmenu/items/' .. item:StripExtension())
end
octolib.shared('config/groups/' .. v .. '/init')
end
hook.Run('simple-orgs.load')
for _, org in pairs(simpleOrgs.orgs) do
org.members = {}
org.flyer = org.flyer or ''
org.url = ''
end
reloadUpstream()

View file

@ -0,0 +1,234 @@
local clothesData = {
icon = 'lock',
['models/player/octo_alpha/'] = {{
sm = 'Головной убор',
icon = 'hat',
bodygroup = 1,
vals = {
[0] = { 'Без головного убора', 'cross', '/me снимает головной убор' },
[2] = { 'Кепка', 'cap', '/me надевает кепку' },
},
},{
sm = 'Перчатки',
icon = 'hand',
bodygroup = 3,
vals = {
[0] = { 'Снять', 'cross', '/me снимает перчатки' },
[1] = { 'Надеть', 'bullet_black', '/me надевает перчатки' },
},
},{
sm = 'Кобура',
icon = 'gun',
bodygroup = 6,
vals = {
[0] = { 'Надеть на пояс', 'arrow_up', '/me надевает кобуру на пояс' },
[1] = { 'Надеть на ногу', 'arrow_down', '/me надевает кобуру на ногу' },
[2] = { 'Снять', 'cross', '/me снимает кобуру' },
},
},{
sm = 'Кобура тазера',
icon = 'lightning',
bodygroup = 7,
vals = {
[0] = { 'Надеть', 'bullet_blue', '/me вешает кобуру с тазером обратно на пояс' },
[1] = { 'Снять', 'cross', '/me снимает кобуру с тазером с пояса' },
},
},{
sm = 'Дубинка',
icon = 'baton',
bodygroup = 8,
vals = {
[0] = { 'Надеть', 'bullet_blue', '/me вешает дубинку обратно на пояс' },
[1] = { 'Снять', 'cross', '/me снимает дубинку с пояса' },
},
},{
sm = 'Наручники',
icon = 'radio_button',
bodygroup = 9,
vals = {
[0] = { 'Надеть одну пару', 'bullet_blue', '/me надевает одну пару наручников обратно на пояс' },
[1] = { 'Надеть две пары', 'bullet_black', '/me надевает две пары наручников обратно на пояс' },
[2] = { 'Снять', 'cross', '/me снимает наручники с пояса' },
},
},{
sm = 'Рация',
icon = 'radio_modern',
bodygroup = 10,
vals = {
[0] = { 'Надеть', 'bullet_blue', '/me надевает рацию обратно на пояс' },
[1] = { 'Снять', 'cross', '/me снимает рацию с пояса' },
},
},
},
}
local modelNums = {1, 2, 3, 4, 5, 6, 8, 9}
local bgsData = {
[1] = {
name = 'Головной убор',
vals = {
{'Без головного убора', 0, true},
{'Кепка', 2},
},
},
[2] = {
name = 'Гарнитура',
vals = {
{'Проводная', 0, true},
{'Снять', 2},
},
},
[4] = {
name = 'Верх',
vals = {
{'Строгая рубашка', 0, true},
{'Строгая рубашка и куртка', 1},
{'Поло', 2},
{'Поло и куртка', 3},
{'Поло и куртка с бронежилетом', 4},
},
},
[5] = {
name = 'Бронежилет',
vals = {
{'Без бронежилета', 0, true},
{'Без магазинов', 1},
},
},
[11] = {
name = 'Нашивка',
vals = {
{'Без нашивки', 0, true},
{'S.S.U.', 1},
{'King', 2},
{'Zero', 3},
{'Siesta', 4},
{'Yankee', 5},
{'Alpha', 6},
{'Ricardo', 7},
{'Union', 8},
},
},
[12] = {
name = 'Патч',
vals = {
{'Без патча', 0, true},
{'DMC', 1},
{'Золотой орел', 2},
{'Череп', 3},
{'Орел со звездой', 4},
{'Sabaton', 5},
{'Снежинка', 6},
{'Вялоухий', 7},
{'Легионер', 8},
{'Нептун', 9},
{'ДУХ АХАХАХ', 10},
},
}
}
local skinData = {
name = 'Низ',
vals = {
{'Темные брюки', 0, true},
{'Светлые брюки', 4},
},
}
local models = {}
for i, v in ipairs(modelNums) do
models[#models + 1] = {
name = 'Охранник ' .. i,
model = ('models/player/octo_alpha/male_%02d.mdl'):format(v),
bgs = bgsData,
skin = skinData,
}
end
simpleOrgs.addOrg('alpha', {
name = 'Alpha',
title = 'Alpha Corporation | Делаем вашу жизнь безопаснее',
shortTitle = 'Alpha',
clothes = clothesData,
team = 'alpha',
mdls = models,
talkieFreq = 'alpha',
})
local plateCol = {
bg = Color(123, 0, 28),
border = Color(40, 40, 40),
title = Color(255, 255, 255),
txt = Color(179, 179, 179),
}
carDealer.addCategory('alpha', {
name = 'Alpha',
icon = 'icon16/lightning.png',
queue = true,
ems = true,
bulletproof = true,
doNotEvacuate = true,
spawns = carDealer.civilSpawns,
canUse = function(ply) return ply:Team() == TEAM_ALPHA, 'Доступно только Alpha' end,
})
carDealer.addVeh('alpha_merit', {
name = 'Merit',
simfphysID = 'sim_fphys_gta4_merit_alpha',
plateCol = plateCol,
price = 12000,
deposit = true,
police = true,
default = {
mats = {
[14] = 'models/alpha_cars/alpha_car_04',
},
},
})
local function canUse(ply)
return DarkRP.isTaxist(ply) or ply:Team() == TEAM_ALPHA
end
if SERVER then
local leaveMeAloneID = 0
octochat.registerCommand('/alphabutton', {
cooldown = 60,
log = true,
execute = function(ply)
local job, jobname = ply:getJobTable()
if job then jobname = job.name end
local customJob = ply:GetNetVar('customJob')
if customJob then jobname = unpack(customJob) end
ply:DoEmote('{name} нажимает кнопку паники')
local msg = ('%s %s передает свое местоположение, используя тревожную кнопку!'):format(jobname, ply:Name())
local marker = {
id = 'cpPanicBtn' .. leaveMeAloneID,
group = 'cpPanicBtn',
txt = 'Кнопка паники',
pos = ply:GetPos() + Vector(0,0,40),
col = Color(102,170,170),
des = {'timedist', { 600, 300 }},
icon = 'octoteam/icons-32/exclamation.png',
size = 32,
}
for _,v in ipairs(player.GetAll()) do
if v:Team() == TEAM_ALPHA then
v:Notify('warning', msg)
v:EmitSound('npc/attack_helicopter/aheli_damaged_alarm1.wav', 45, 100, 0.5)
v:AddMarker(marker)
end
end
leaveMeAloneID = leaveMeAloneID + 1
end,
check = canUse,
})
else
octochat.defineCommand('/alphabutton', canUse)
end

View file

@ -0,0 +1,164 @@
local bankSubMats = {
[27] = {
name = 'Форма',
vals = {
{'Костюм "D\'Anglere"', 'models/humans/modern/octo/suit1_sheet'},
{'Черный деловой костюм', 'models/humans/modern/octo/suit2_sheet'},
{'Белый деловой костюм', 'models/humans/modern/octo/suit3_sheet'},
{'Серый деловой костюм', 'models/humans/modern/octo/suit4_sheet'},
{'Зеленый деловой костюм', 'models/humans/modern/octo/suit5_sheet'},
{'Голубой деловой костюм', 'models/humans/modern/octo/suit6_sheet'},
{'Черный пиджак', 'models/humans/modern/octo/suit7_sheet'},
{'Синий пиджак', 'models/humans/modern/octo/suit8_sheet'},
},
},
}
local models = octolib.table.mapSequential({
'models/humans/octo/male_01_01.mdl',
'models/humans/octo/male_01_02.mdl',
'models/humans/octo/male_01_03.mdl',
'models/humans/octo/male_02_01.mdl',
'models/humans/octo/male_02_02.mdl',
'models/humans/octo/male_02_03.mdl',
'models/humans/octo/male_03_01.mdl',
'models/humans/octo/male_03_02.mdl',
'models/humans/octo/male_03_03.mdl',
'models/humans/octo/male_03_04.mdl',
'models/humans/octo/male_03_05.mdl',
'models/humans/octo/male_03_06.mdl',
'models/humans/octo/male_03_07.mdl',
'models/humans/octo/male_04_01.mdl',
'models/humans/octo/male_04_02.mdl',
'models/humans/octo/male_04_03.mdl',
'models/humans/octo/male_04_04.mdl',
'models/humans/octo/male_05_01.mdl',
'models/humans/octo/male_05_02.mdl',
'models/humans/octo/male_05_03.mdl',
'models/humans/octo/male_05_04.mdl',
'models/humans/octo/male_05_05.mdl',
'models/humans/octo/male_06_01.mdl',
'models/humans/octo/male_06_02.mdl',
'models/humans/octo/male_06_03.mdl',
'models/humans/octo/male_06_04.mdl',
'models/humans/octo/male_06_05.mdl',
'models/humans/octo/male_07_01.mdl',
'models/humans/octo/male_07_02.mdl',
'models/humans/octo/male_07_03.mdl',
'models/humans/octo/male_07_04.mdl',
'models/humans/octo/male_07_05.mdl',
'models/humans/octo/male_07_06.mdl',
'models/humans/octo/male_08_01.mdl',
'models/humans/octo/male_08_02.mdl',
'models/humans/octo/male_08_03.mdl',
'models/humans/octo/male_08_04.mdl',
'models/humans/octo/male_09_01.mdl',
'models/humans/octo/male_09_02.mdl',
'models/humans/octo/male_09_03.mdl',
'models/humans/octo/male_09_04.mdl',
}, function(v, i)
return {
name = 'Внешность ' .. i,
male = true,
model = v,
subMaterials = bankSubMats,
requiredSkin = 23,
}
end)
models[#models + 1] = {
name = 'Сотрудник охраны',
model = 'models/player/camo_09.mdl',
male = true,
bgs = {
[1] = {
name = 'Базовый бронежилет',
},
[2] = {
name = 'Кепка',
},
[3] = {
name = 'Пояс',
},
[5] = {
name = 'Полный бронежилет',
},
[6] = {
name = 'Шлем',
}
},
requiredBgs = {[4] = 1}
}
simpleOrgs.addOrg('bank', {
name = 'Sevilas Bank',
title = 'Sevilas Bank | Лучший банк штата Мичиган',
shortTitle = 'Sevilas Bank',
team = 'bank',
mdls = models,
talkieFreq = 'bank',
})
carDealer.addCategory('bank', {
name = 'Банк',
icon = 'icon16/money.png',
queue = true,
bulletproof = true,
doNotEvacuate = true,
spawns = carDealer.civilSpawns,
canUse = function(ply) return ply:Team() == TEAM_BANK, 'Доступно только сотрудникам банка' end,
})
local plateCol = {
bg = Color(30, 30, 30),
border = Color(40, 40, 40),
title = Color(255, 255, 255),
txt = Color(255, 255, 255),
}
carDealer.addVeh('bank_stockade', {
name = 'Stockade',
simfphysID = 'sim_fphys_gta4_stockade',
price = 0,
bulletproof = true,
deposit = true,
police = true,
plateCol = plateCol,
})
carDealer.addVeh('bank_dilettante', {
name = 'Dilettante',
simfphysID = 'sim_fphys_gta4_dilettante',
price = 0,
deposit = true,
plateCol = plateCol,
default = {
col = { Color(30, 30, 30), Color(30, 30, 30), Color(0,0,0), Color(30, 30, 30) },
},
})
carDealer.addVeh('bank_habanero', {
name = 'Habanero',
simfphysID = 'sim_fphys_gta4_habanero',
price = 0,
deposit = true,
plateCol = plateCol,
default = {
col = { Color(30, 30, 30), Color(30, 30, 30), Color(0,0,0), Color(30, 30, 30) },
},
})
local toStrip = {'weapon_octo_p228', 'weapon_octo_m4a1', 'weapon_octo_mp5', 'weapon_cuff_police', 'stunstick', 'med_kit', 'stungun'}
hook.Add('OnPlayerChangedTeam', 'dbg-orgs.bank', function(ply, old, new)
if not SERVER then return end
if new == TEAM_BANK then
timer.Simple(0, function()
if ply:GetModel() ~= 'models/player/camo_09.mdl' then
for _, v in ipairs(toStrip) do
ply:SetNetVar('HasGunlicense')
ply:StripWeapon(v)
end
end
end)
end
end)

View file

@ -0,0 +1,28 @@
--
-- CONVARD
--
simpleOrgs.addOrg('convard', {
name = 'ConVard HotDogs',
title = '',
shortTitle = '',
secret = true,
owners = {},
})
-- carDealer.addCategory('convard', {
-- name = 'ConVard',
-- icon = 'octoteam/icons-16/hamburger.png',
-- doNotEvacuate = true,
-- canUse = function(ply)
-- if not ply:IsOrgMember('convard') then
-- return false, 'Доступно только для ConVard HotDogs'
-- end
-- end,
-- })
-- carDealer.addVeh('convard_hotdog', {
-- name = 'HotDog',
-- simfphysID = 'simfphys_gta_sa_hotdog',
-- price = 0,
-- deposit = true,
-- })

View file

@ -0,0 +1,136 @@
local clothesData = {
icon = 'user_medical',
['models/kerry/plats_medical_'] = {
{
bodygroup = 2,
vals = {
[0] = { 'Снять перчатки', 'cross', '/me снимает перчатки с рук' },
[1] = { 'Надеть перчатки', 'bullet_blue', '/me надевает перчатки на руки' },
},
},
},
}
local uniform = {
[4] = {
name = 'Форма',
vals = {
{'Обычная форма', 'models/medic/coroner_jbib'},
{'Специальная форма', 'models/medic/coroner_SU'},
},
},
}
local coroners = {}
for i = 1, 11 do
coroners[#coroners + 1] = {
model = ('models/kerry/plats_medical_%02i.mdl'):format(i),
male = true,
name = 'Коронер ' .. i,
subMaterials = uniform,
requiredMats = {
[6] = 'null',
[7] = 'null',
[8] = 'null',
[11] = 'models/merriweather/lowr_diff_000_a_uni',
[16] = 'models/medic/uppr_diff_024_a_whi',
},
}
coroners[#coroners + 1] = {
model = ('models/kerry/plats_medical_%02i.mdl'):format(i),
male = true,
name = 'Теплая форма ' .. i,
requiredBgs = {[1] = 1},
requiredMats = {
[6] = 'null',
[7] = 'null',
[8] = 'models/coroner/cid',
[11] = 'models/merriweather/lowr_diff_000_a_uni',
[12] = 'models/coroner/cwinter',
[16] = 'models/medic/uppr_diff_024_a_whi',
},
}
end
for i = 10, 11 do
coroners[#coroners + 1] = {
model = ('models/kerry/plats_medical_%02i.mdl'):format(i),
male = false,
name = 'Коронер ' .. (i-9),
subMaterials = uniform,
requiredMats = {
[8] = 'null',
[9] = 'null',
[10] = 'null',
[15] = 'models/merriweather/lowr_diff_000_a_uni',
[16] = 'models/medic/uppr_diff_024_a_whi',
},
}
end
if SERVER then
netstream.Hook('coroners.gloves', function(ply, value)
if ply:getJobTable().command == 'coroner' and octolib.math.inRange(value, 0, 1) then
ply:SetBodygroup(2, value)
end
end)
end
simpleOrgs.addOrg('coroners', {
name = 'Коронеры',
title = 'Коронеры',
shortTitle = 'Коронеры',
team = 'coroner',
mdls = coroners,
clothes = clothesData,
talkieFreq = 'medic',
})
carDealer.addCategory('coroners', {
name = 'Коронеры',
ems = true,
doNotEvacuate = true,
icon = 'octoteam/icons-16/hospital.png',
canUse = function(ply) return ply:Team() == TEAM_CORONER, 'Доступно только коронерам' end,
spawns = {
rp_evocity_dbg_220222 = {
{ Vector(-11295, 9344, 125), Angle(0,-90,0) }, -- hospital
{ Vector(-11111, 9344, 125), Angle(0,-90,0) },
},
rp_eastcoast_v4c = carDealer.civilSpawns.rp_eastcoast_v4c,
rp_truenorth_v1a = {
{ Vector(11667, 12990, 128), Angle(0, -90, 0) },
{ Vector(11876, 12990, 128), Angle(0, -90, 0) },
},
rp_riverden_dbg_220313 = {
{ Vector(-5453.52, 1579.42, -220.133), Angle(-0, -90, 0) },
{ Vector(-5453.98, 2185.43, -219.886), Angle(-0, -90, 0) },
},
},
spawnCheck = carDealer.limits.coroner,
limitGroup = 'coroner',
})
carDealer.addVeh('coroners_pony', {
category = 'coroners',
name = 'Pony',
simfphysID = 'sim_fphys_gta4_pony_coroner',
price = 0,
deposit = true,
default = {
mats = {
[1] = 'octoteam/models/vehicles/moonbeam/livery1',
},
},
})
carDealer.addVeh('coroners_moonbeam', {
category = 'coroners',
name = 'Moonbeam',
simfphysID = 'sim_fphys_gta4_moonbeam',
price = 0,
deposit = true,
default = {
mats = {
[4] = 'octoteam/models/vehicles/moonbeam/coroner_livery2',
},
col = { Color(36,36,36), Color(36,36,36), Color(0,0,0), Color(36,36,36) },
},
})

View file

@ -0,0 +1,157 @@
local models = {}
-- ELECTRICIANS
local electricianBgs = {
[2] = {
name = 'Головной убор',
vals = {
{ 'Нет', 0 },
{ 'Шлем', 2 },
{ 'Шлем + Наушники', 1 },
},
},
[3] = {
name = 'Жилет',
},
[4] = {
name = 'Очки',
},
}
for i = 1, 9 do
models[#models + 1] = {
name = 'Электрик ' .. i,
male = true,
model = ('models/player/supernek/workers/electricians/electrician_male%02d.mdl'):format(i),
bgs = electricianBgs,
}
end
-- HANDYMEN
local handymanBgs = {
[2] = {
name = 'Жилет',
},
}
for i = 1, 9 do
models[#models + 1] = {
name = 'Мастер ' .. i,
male = true,
model = ('models/player/supernek/workers/handymen/handyman_male%02d.mdl'):format(i),
bgs = handymanBgs,
}
end
-- PLUMBERS
local plumberBgs = {
[2] = {
name = 'Кепка',
},
[3] = {
name = 'Жилет',
},
}
for i = 1, 9 do
models[#models + 1] = {
name = 'Сантехник ' .. i,
male = true,
model = ('models/player/supernek/workers/plumbers/plumber_male%02d.mdl'):format(i),
bgs = plumberBgs,
}
end
-- SCAVENGERS
local scavengerBgs = {
[2] = {
name = 'Жилет',
},
}
for i = 1, 9 do
models[#models + 1] = {
name = 'Мусорщик ' .. i,
male = true,
model = ('models/player/supernek/workers/scavengers/scavenger_male%02d.mdl'):format(i),
bgs = scavengerBgs,
}
end
-- INSPECTORS
for i = 1, 7 do
models[#models + 1] = {
model = ('models/player/kerry/medic/medic_%02i.mdl'):format(i),
male = true,
name = 'Инспектор ' .. i,
requiredMats = {
[4] = 'models/debug/debugwhite',
[7] = 'null',
}
}
if i == 7 then continue end
models[#models + 1] = {
model = ('models/player/kerry/medic/medic_%02i_f.mdl'):format(i),
male = false,
name = 'Инспектор ' .. i,
requiredMats = {
[4] = 'models/debug/debugwhite',
[5] = 'dev/dev_tvmonitor1a',
}
}
end
simpleOrgs.addOrg('csd', {
name = 'Городская служба',
title = 'Городская служба',
shortTitle = 'Городская служба',
team = 'csd',
mdls = models,
talkieFreq = 'csd',
})
carDealer.addCategory('csd', {
name = 'Городская служба',
icon = 'octoteam/icons-16/wrench.png',
ems = true,
queue = true,
doNotEvacuate = true,
canUse = function(ply) return ply:Team() == TEAM_CSD, 'Доступно только городской службе' end,
spawns = {
rp_riverden_dbg_220313 = {
{ Vector(27.1625, 11166.7, 29.3211), Angle(0, 0, 0) },
{ Vector(28.6012, 10978.4, 30.8232), Angle(0, 0, 0) },
{ Vector(26.1124, 11999.1, 28.3349), Angle(0, 0, 0) },
},
},
})
carDealer.addVeh('csd_burrito', {
category = 'csd',
name = 'Burrito',
simfphysID = 'sim_fphys_gta4_burrito_csd',
price = 0,
deposit = true,
default = {
bg = { [1] = 4 },
mats = {
[1] = 'octoteam/models/vehicles/burrito/burritocsd_livery_1',
},
},
})
carDealer.addVeh('csd_rancher', {
category = 'csd',
name = 'Rancher',
simfphysID = 'sim_fphys_gta4_rancher',
price = 0,
deposit = true,
default = {
col = { Color(0, 88, 139), Color(0, 88, 139) },
bg = { [1] = 1 },
},
})
carDealer.addVeh('csd_moonbeam', {
category = 'csd',
name = 'Moonbeam',
simfphysID = 'sim_fphys_gta4_moonbeam',
price = 0,
deposit = true,
default = {
col = { Color(0,88,139), Color(0,88,139), Color(0,0,0), Color(0,88,139) },
},
})

View file

@ -0,0 +1,249 @@
hook.Add('car-dealer.priceOverride', 'dbg-police.dpd', function(ply, class)
local cdData = carDealer.vehicles[class]
if ply:Team() == TEAM_DPD and cdData.police and cdData.deposit then return 0 end
end)
--
-- STANDARD
--
carDealer.addCategory('dpd', {
name = 'DPD',
ems = true,
icon = 'octoteam/icons-16/user_policeman_white.png',
canUse = function(ply) return ply:Team() == TEAM_DPD, 'Доступно только DPD' end,
spawns = carDealer.policeSpawns,
spawnCheck = carDealer.limitedSpawn(3, 'dpd', 'В городе уже много автомобилей DPD, найди напарника или попробуй чуть позже'),
limitGroup = 'dpd',
})
carDealer.addVeh('dpd-vapid', {
category = 'dpd',
name = 'DPD Vapid',
simfphysID = 'sim_fphys_gta4_police',
price = 30000,
deposit = true,
police = true,
radioWhitelist = carDealer.policeRadioStations,
})
carDealer.addVeh('dpd-merit', {
category = 'dpd',
name = 'DPD Merit',
simfphysID = 'sim_fphys_gta4_police2',
price = 40000,
deposit = true,
police = true,
radioWhitelist = carDealer.policeRadioStations,
})
carDealer.addVeh('dpd-buffalo', {
category = 'dpd',
name = 'DPD Buffalo',
simfphysID = 'sim_fphys_tbogt_police3',
price = 75000,
deposit = true,
police = true,
canUse = function(ply)
if ply:Team() == TEAM_DPD or ply:Team() == TEAM_WCSO then return true end
if ply:isCP() and ply:Team() ~= TEAM_FBI and ply:Team() ~= TEAM_MAYOR then return carDealer.checks.dobro(ply) end
return false
end,
tags = { carDealer.tags.dobro },
radioWhitelist = carDealer.policeRadioStations,
})
--
-- NOMARK
--
local ranks = octolib.array.toKeys {'swat', 'dec1', 'se1', 'se2', 'dec2', 'dec3', 'lie', 'cap', 'cmd', 'asch', 'asc', 'chi'}
carDealer.addCategory('nomark', {
name = 'Немаркированные',
icon = 'icon16/user_suit.png',
ems = true,
doNotEvacuate = true,
canUse = function(ply) return ply:Team() == TEAM_DPD and ranks[ply:GetActiveRank('dpd') or ''] or false, 'Доступно только детективам, либо сержанту и выше' end,
spawns = {
rp_evocity_dbg_220222 = {
{ Vector(-4656, -7516, 225), Angle(0,-90,0) }, -- Duglas
{ Vector(-4656, -7211, 225), Angle(0,-90,0) },
{ Vector(-4656, -6906, 225), Angle(0,-90,0) },
{ Vector(-4656, -6601, 225), Angle(0,-90,0) },
{ Vector(-4656, -6296, 225), Angle(0,-90,0) },
},
rp_eastcoast_v4c = carDealer.policeSpawns.rp_eastcoast_v4c,
rp_truenorth_v1a = carDealer.policeSpawns.rp_truenorth_v1a,
},
spawnCheck = carDealer.limits.police,
limitGroup = 'police',
})
local randomColorTags = { {'icon16/color_wheel.png', 'Случайный цвет'} }
local function randomColor()
local colData = table.Random(carDealer.defaultCarColors)
local _, r, g, b = unpack(colData)
local col = Color(r, g, b)
return { col, col, Color(0,0,0), col }
end
local plateCol = {
bg = Color(255, 255, 255),
border = Color(40, 40, 40),
title = Color(255, 255, 255),
text = Color(0, 0, 0),
}
carDealer.addVeh('nomark_premier', {
name = 'Premier',
simfphysID = 'sim_fphys_gta4_premier',
price = 0,
police = true,
deposit = true,
tags = randomColorTags,
default = {
col = randomColor,
},
plateCol = plateCol,
})
carDealer.addVeh('nomark_dilettante', {
name = 'Dilettante',
simfphysID = 'sim_fphys_gta4_dilettante',
price = 0,
police = true,
deposit = true,
tags = randomColorTags,
default = {
col = randomColor,
},
plateCol = plateCol,
})
carDealer.addVeh('nomark_buffalo', {
name = 'Buffalo',
simfphysID = 'sim_fphys_gta4_fbi',
price = 0,
police = true,
deposit = true,
tags = randomColorTags,
default = {
col = randomColor,
},
plateCol = plateCol,
})
carDealer.addVeh('nomark_admiral', {
name = 'Admiral',
simfphysID = 'sim_fphys_gta4_admiral',
price = 0,
police = true,
deposit = true,
tags = randomColorTags,
default = {
col = randomColor,
},
plateCol = plateCol,
})
carDealer.addVeh('nomark_taxi', {
name = 'Taxi',
simfphysID = 'sim_fphys_gta4_taxi2',
price = 8000,
police = true,
deposit = true,
default = {
col = { Color(215,142,16), Color(215,142,16), Color(0,0,0), Color(215,142,16) },
},
plateCol = plateCol,
})
carDealer.addVeh('nomark_cabbie', {
name = 'Cabby',
simfphysID = 'sim_fphys_gta4_cabby',
price = 15000,
police = true,
deposit = true,
default = {
col = { Color(215,142,16), Color(215,142,16), Color(0,0,0), Color(215,142,16) },
},
plateCol = plateCol,
})
--
-- SWAT
--
carDealer.addCategory('swat', {
name = 'S.W.A.T',
icon = 'icon16/lightning.png',
ems = true,
bulletproof = true,
doNotEvacuate = true,
canUse = function(ply) return ply:Team() == TEAM_DPD and ply:GetActiveRank('dpd') == 'swat', 'Доступно только S.W.A.T' end,
spawnCheck = carDealer.limitedSpawn(2, 'swat', 'В городе уже много автомобилей SWAT, найди напарника или попробуй чуть позже'),
limitGroup = 'swat',
spawns = carDealer.policeSpawns,
})
carDealer.addVeh('swat_moonbeam', {
name = 'Moonbeam',
simfphysID = 'sim_fphys_gta4_moonbeam',
price = 0,
deposit = true,
default = {
col = { Color(15,15,15), Color(15,15,15), Color(0,0,0), Color(15,15,15)},
},
})
carDealer.addVeh('swat_huntley', {
name = 'Huntley',
simfphysID = 'sim_fphys_gta4_huntley',
price = 0,
deposit = true,
police = true,
glauncher = true,
default = {
col = { Color(15,15,15), Color(15,15,15), Color(0,0,0), Color(15,15,15)},
},
})
carDealer.addVeh('swat_enforcer', {
name = 'Enforcer',
simfphysID = 'sim_fphys_gta4_nstockade',
price = 0,
bulletproof = true,
deposit = true,
police = true,
glauncher = true,
radioWhitelist = carDealer.policeRadioStations,
})
carDealer.addVeh('swat_bearcat', {
name = 'BearCat',
simfphysID = 'sim_fphys_gta4_bearcat',
previewOffset = Vector(0, 10, -30),
SpawnAngleOffset = Angle(0,90,0),
price = 0,
bulletproof = true,
deposit = true,
police = true,
glauncher = true,
radioWhitelist = carDealer.policeRadioStations,
})
carDealer.addVeh('swat_bearcat_rescue', {
name = 'BearCat Medevac',
simfphysID = 'sim_fphys_gta4_bearcat',
previewOffset = Vector(0, 10, -30),
SpawnAngleOffset = Angle(0,90,0),
price = 0,
default = {
skin = 2,
},
bulletproof = true,
deposit = true,
police = true,
glauncher = true,
radioWhitelist = carDealer.policeRadioStations,
})

View file

@ -0,0 +1,3 @@
octolib.shared('models')
octolib.shared('cars')
octolib.server('octoinv/items')

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,52 @@
local function throw(ply, ent, expire)
local force = 300
local pos, ang, vel = ply:GetBonePosition(ply:LookupBone('ValveBiped.Bip01_L_Hand') or 16)
local tr = util.TraceLine { start = ply:GetShootPos(), endpos = pos, filter = ply }
if tr.Hit then
pos = tr.HitPos + tr.HitNormal * 5
vel = tr.HitNormal * force * 0.4
else
vel = ply:GetAimVector()
vel = (vel + VectorRand() * math.random() * 0.1) * force
end
ent:SetPos(pos)
ent:SetAngles(ang)
ent:Spawn()
ent:Activate()
ent.owner = ply
ent.expire = expire
ply:LinkEntity(ent)
local phys = ent:GetPhysicsObject()
if IsValid(phys) then
phys:Wake()
phys:SetVelocity(vel)
end
end
octoinv.registerItem('spike_strips', {
name = 'Полицейские шипы',
icon = 'octoteam/icons/spike_strips.png',
mass = 1.5,
volume = 1.5,
model = 'models/props_junk/cardboard_box001a.mdl',
desc = 'Шипы, применяемые при погонях для быстрой остановки подозреваемого',
nostack = true,
use = {
function(ply, item)
if not (ply:Team() == TEAM_DPD or ply:Team() == TEAM_WCSO) then return end
return 'Бросить', 'octoteam/icons/hand.png', function(ply, item)
ply:DoAnimation(ACT_GMOD_GESTURE_ITEM_THROW)
timer.Simple(0.88, function()
local ent = ents.Create('ent_dbg_spike_strips')
if not IsValid(ent) then return end
throw(ply, ent, item:GetData('expire'))
end)
return 1
end
end,
},
})

View file

@ -0,0 +1,71 @@
simpleOrgs.addOrg('elsec', {
name = 'Elegant Security',
title = 'Elegant Security',
shortTitle = 'Elegant Security',
team = 'elsec',
mdls = {
{
name = 'Сотрудник',
model = 'models/player/camo_09.mdl',
bgs = {
[1] = {
name = 'Базовый бронежилет',
},
[2] = {
name = 'Кепка',
},
[3] = {
name = 'Пояс',
},
[5] = {
name = 'Полный бронежилет',
},
[6] = {
name = 'Шлем',
}
},
requiredBgs = {[4] = 1}
}
},
talkieFreq = 'elsec',
})
local plateCol = {
bg = Color(30, 30, 30),
border = Color(255, 191, 0),
title = Color(255, 191, 0),
txt = Color(255, 191, 0),
}
carDealer.addCategory('elsec', {
name = 'Elegant Security',
icon = 'icon16/lightning.png',
queue = true,
ems = true,
bulletproof = true,
doNotEvacuate = true,
spawns = carDealer.civilSpawns,
canUse = function(ply) return ply:Team() == TEAM_ELSEC, 'Доступно только Elegant Security' end,
})
carDealer.addVeh('elsec_moonbeam', {
name = 'Moonbeam',
simfphysID = 'sim_fphys_gta4_moonbeam',
plateCol = plateCol,
price = 12000,
deposit = true,
default = {
col = { Color(36,36,36), Color(36,36,36), Color(0,0,0), Color(36,36,36) },
},
})
carDealer.addVeh('elsec_premier', {
name = 'Premier',
simfphysID = 'sim_fphys_gta4_premier',
plateCol = plateCol,
price = 25000,
deposit = true,
default = {
col = { Color(36,36,36), Color(0,0,0), Color(0,0,0), Color(36,36,36) },
},
})

View file

@ -0,0 +1,131 @@
local fbiSubMats = {
[27] = 'models/humans/male/group01/fbi',
}
local models = octolib.table.mapSequential({
'models/humans/octo/male_01_01.mdl',
'models/humans/octo/male_01_02.mdl',
'models/humans/octo/male_01_03.mdl',
'models/humans/octo/male_02_01.mdl',
'models/humans/octo/male_02_02.mdl',
'models/humans/octo/male_02_03.mdl',
'models/humans/octo/male_03_01.mdl',
'models/humans/octo/male_03_02.mdl',
'models/humans/octo/male_03_03.mdl',
'models/humans/octo/male_03_04.mdl',
'models/humans/octo/male_03_05.mdl',
'models/humans/octo/male_03_06.mdl',
'models/humans/octo/male_03_07.mdl',
'models/humans/octo/male_04_01.mdl',
'models/humans/octo/male_04_02.mdl',
'models/humans/octo/male_04_03.mdl',
'models/humans/octo/male_04_04.mdl',
'models/humans/octo/male_05_01.mdl',
'models/humans/octo/male_05_02.mdl',
'models/humans/octo/male_05_03.mdl',
'models/humans/octo/male_05_04.mdl',
'models/humans/octo/male_05_05.mdl',
'models/humans/octo/male_06_01.mdl',
'models/humans/octo/male_06_02.mdl',
'models/humans/octo/male_06_03.mdl',
'models/humans/octo/male_06_04.mdl',
'models/humans/octo/male_06_05.mdl',
'models/humans/octo/male_07_01.mdl',
'models/humans/octo/male_07_02.mdl',
'models/humans/octo/male_07_03.mdl',
'models/humans/octo/male_07_04.mdl',
'models/humans/octo/male_07_05.mdl',
'models/humans/octo/male_07_06.mdl',
'models/humans/octo/male_08_01.mdl',
'models/humans/octo/male_08_02.mdl',
'models/humans/octo/male_08_03.mdl',
'models/humans/octo/male_08_04.mdl',
'models/humans/octo/male_09_01.mdl',
'models/humans/octo/male_09_02.mdl',
'models/humans/octo/male_09_03.mdl',
'models/humans/octo/male_09_04.mdl',
}, function(v, i)
return {
name = 'Внешность ' .. i,
male = true,
model = v,
requiredMats = fbiSubMats,
requiredSkin = 23,
}
end)
simpleOrgs.addOrg('fbi', {
name = 'ФБР',
title = '',
shortTitle = '',
team = 'fbi',
mdls = models,
talkieFreq = 'fbi',
})
carDealer.addCategory('fbi', {
name = 'FBI',
icon = 'octoteam/icons-16/emotion_daddy_cool.png',
ems = true,
doNotEvacuate = true,
canUse = function(ply) return ply:Team() == TEAM_FBI, 'Доступно только FBI' end,
spawns = carDealer.civilSpawns,
spawnCheck = carDealer.limitedSpawn(1, 'fbi', 'В городе уже есть автомобиль FBI, найди напарника или попробуй чуть позже'),
limitGroup = 'fbi',
})
local fbiPlateCol = {
bg = Color(75, 86, 208),
border = Color(40, 40, 40),
title = Color(255, 255, 255),
txt = Color(255, 255, 255),
}
carDealer.addVeh('fbi_admiral', {
name = 'Admiral',
simfphysID = 'sim_fphys_gta4_admiral',
price = 0,
police = true,
deposit = true,
default = {
col = { Color(30,30,30), Color(30,30,30), Color(0,0,0), Color(30,30,30) },
},
plateCol = {}, -- reset plates
})
carDealer.addVeh('fbi_emperor', {
name = 'Emperor',
simfphysID = 'sim_fphys_gta4_emperor',
price = 0,
police = true,
deposit = true,
default = {
col = { Color(30,30,30), Color(30,30,30), Color(0,0,0), Color(30,30,30) },
},
plateCol = {}, -- reset plates
})
carDealer.addVeh('fbi_manana', {
name = 'Manana',
simfphysID = 'sim_fphys_gta4_manana',
price = 0,
police = true,
deposit = true,
default = {
col = { Color(30,30,30), Color(30,30,30), Color(0,0,0), Color(30,30,30) },
bg = { [1] = 1 },
},
plateCol = {}, -- reset plates
})
carDealer.addVeh('fbi_buffalo', {
name = 'Buffalo',
simfphysID = 'sim_fphys_gta4_fbi',
price = 0,
police = true,
deposit = true,
default = {
col = { Color(30,30,30), Color(30,30,30), Color(0,0,0), Color(30,30,30) },
},
plateCol = fbiPlateCol,
})

View file

@ -0,0 +1,123 @@
carDealer.addCategory('fire', {
name = 'Пожарные',
icon = octolib.icons.silk16('fire'),
ems = true,
doNotEvacuate = true,
canUse = function(ply) return ply:Team() == TEAM_FIREFIGHTER and ply:GetActiveRank('fire') ~= 'cad' or false, 'Доступно только пожарным' end,
spawns = {
rp_evocity_dbg_220222 = {
{ Vector(-3650, -7671, 265), Angle(0,180,0) },
{ Vector(-3650, -7953, 265), Angle(0,180,0) },
{ Vector(-3650, -8245, 265), Angle(0,180,0) },
},
rp_eastcoast_v4c = carDealer.civilSpawns.rp_eastcoast_v4c,
rp_truenorth_v1a = {
{ Vector(13090, 12190, 75), Angle(0, 180, 0) },
{ Vector(13090, 11926, 75), Angle(0, 180, 0) },
{ Vector(13090, 11680, 75), Angle(0, 180, 0) },
{ Vector(13090, 11421, 75), Angle(0, 180, 0) },
},
rp_riverden_dbg_220313 = {
{ Vector(-12195.1, 1425.92, -202.995), Angle(-0, 90, 0) },
{ Vector(-12446.4, 1424.97, -203.212), Angle(-0, 90, 0) },
},
},
spawnCheck = carDealer.limits.fire,
limitGroup = 'fire',
})
local seniorsStaff = octolib.array.toKeys {'lie', 'cap', 'bc', 'rchi', 'ass', 'dep', 'chi'}
local highStaff = octolib.array.toKeys {'bc', 'rchi', 'ass', 'dep', 'chi'}
local function isSeniors(ply)
return seniorsStaff[ply:GetActiveRank('fire') or ''] or false, 'Доступно только старшему пожарному составу'
end
local function isHigh(ply)
return highStaff[ply:GetActiveRank('fire') or ''] or false, 'Доступно только высшему пожарному составу'
end
local plateCol = {
bg = Color(255, 54, 54),
border = Color(40, 40, 40),
title = Color(255, 255, 255),
txt = Color(255, 255, 255),
}
carDealer.addVeh('fireambulance', {
category = 'fire',
name = 'Ambulance',
simfphysID = 'sim_fphys_gta4_ambulance',
price = 0,
deposit = true,
customFOV = 42,
default = {
col = { Color(255,255,255), Color(255,0,0), Color(0,0,0), Color(255,255,255) },
bg = { [1] = 1 },
},
radioWhitelist = carDealer.emsRadioStations,
})
carDealer.addVeh('firetruck', {
category = 'fire',
name = 'Fire Truck',
simfphysID = 'sim_fphys_gta4_firetruk',
price = 0,
deposit = true,
customFOV = 45,
plateCol = plateCol,
radioWhitelist = carDealer.emsRadioStations,
})
carDealer.addVeh('ladder', {
name = 'Fire Truck Ladder',
simfphysID = 'sim_fphys_l4d_fire_truck',
price = 0,
deposit = true,
customFOV = 52,
plateCol = plateCol,
radioWhitelist = carDealer.emsRadioStations,
})
carDealer.addVeh('battalion', {
name = 'Battalion',
simfphysID = 'sim_fphys_gta4_battalion',
price = 0,
deposit = true,
customFOV = 35,
plateCol = plateCol,
radioWhitelist = carDealer.emsRadioStations,
canUse = isHigh,
canSee = function(ply)
return highStaff[ply:GetActiveRank('fire') or ''] or false
end,
})
carDealer.addVeh('battalion_inv', {
name = 'Battalion Investigator',
simfphysID = 'sim_fphys_gta4_battalion',
price = 0,
deposit = true,
customFOV = 35,
plateCol = plateCol,
radioWhitelist = carDealer.emsRadioStations,
canUse = isSeniors,
canSee = function(ply)
return seniorsStaff[ply:GetActiveRank('fire') or ''] or false
end,
default = {
mats = {
[4] = 'octoteam/models/vehicles/landstalker/landstalkerdfd_exterior_invest',
},
},
})
-- carDealer.addVeh('fireranch', {
-- category = 'fire',
-- name = 'Fire Rancher',
-- simfphysID = 'simfphys_gta_sa_fdranch',
-- price = 0,
-- deposit = true,
-- plateCol = plateCol,
-- radioWhitelist = carDealer.emsRadioStations,
-- })

View file

@ -0,0 +1 @@
octogui.cmenu.registerCategory('fire')

View file

@ -0,0 +1,37 @@
local function checkUniform(ply)
if not ply:GetModel():find('models/gta5/fire') then return end
local bgs = {}
for i, v in ipairs(ply:GetBodyGroups()) do
local id = v.id
bgs[id] = ply:GetBodygroup(id)
end
return bgs[2] == 1
end
octogui.cmenu.registerItem('fire', 'lightbulb', {
icon = octolib.icons.silk16('lightbulb'),
text = function(ply)
local mask = ply:GetNetVar('fire.flashlight')
return ('%s фонарик'):format(mask and 'Выключить' or 'Включить')
end,
check = function(ply)
return ply:Team() == TEAM_FIREFIGHTER and checkUniform(ply)
end,
action = function()
netstream.Start('fire.flashlight', LocalPlayer())
end,
})
octogui.cmenu.registerItem('fire', 'scba', {
icon = octolib.icons.silk16('cancel'),
text = function(ply)
local mask = ply:GetNetVar('fire.scba')
return ('%s кнопку тревоги'):format(mask and 'Выключить' or 'Включить')
end,
check = function(ply)
return ply:Team() == TEAM_FIREFIGHTER and checkUniform(ply)
end,
action = function()
netstream.Start('fire.scba', LocalPlayer())
end,
})

View file

@ -0,0 +1,77 @@
local SwitchSound = Sound('HL2Player.FlashLightOn')
local function killLight(ply)
if IsValid(ply.projectedlight) then
SafeRemoveEntity(ply.projectedlight)
end
end
local function createFlashlight(ply)
if IsValid(ply.projectedlight) then return end
local light = ents.Create('env_projectedtexture')
light:SetParent(ply)
light:SetPos(ply:GetShootPos())
light:SetAngles(ply:GetAngles())
light:SetKeyValue('enableshadows', 1)
light:SetKeyValue('nearz', 7)
light:SetKeyValue('farz', 750.0)
light:SetKeyValue('lightcolor','255 255 255 255')
light:SetKeyValue('lightfov', 70)
light:Spawn()
light:Input('SpotlightTexture', NULL, NULL, 'effects/flashlight001')
light:Fire('setparentattachment','chest', 0.01)
ply.projectedlight = light
end
local function checkUniform(ply)
if not ply:GetModel():find('models/gta5/fire') then return end
local bgs = {}
for i, v in ipairs(ply:GetBodyGroups()) do
local id = v.id
bgs[id] = ply:GetBodygroup(id)
end
return bgs[2] == 1
end
netstream.Hook('fire.scba', function(ply)
if not (ply:Team() == TEAM_FIREFIGHTER and checkUniform(ply)) then return end
if ply:GetNetVar('fire.scba') then
ply:SetNetVar('fire.scba')
if IsValid(ply.scba) then
ply.scba:Stop()
ply.scba = nil
end
return
end
ply:SetNetVar('fire.scba', true)
ply.scba = CreateSound(ply, 'scba.wav')
ply.scba:Play()
end)
local function removeSCBA(ply)
if IsValid(ply) and ply:GetNetVar('fire.scba') and IsValid(ply.scba) then
ply.scba:Stop()
ply.scba = nil
ply:SetNetVar('fire.scba')
end
end
hook.Add('PlayerDeath', 'fire.scba', removeSCBA)
hook.Add('PlayerSpawn', 'fire.scba', removeSCBA)
netstream.Hook('fire.flashlight', function(ply)
if not (ply:Team() == TEAM_FIREFIGHTER and checkUniform(ply)) then return end
ply:EmitSound(SwitchSound)
if ply:GetNetVar('fire.flashlight') then
killLight(ply)
ply:SetNetVar('fire.flashlight')
else
createFlashlight(ply)
ply:SetNetVar('fire.flashlight', true)
end
end)
hook.Add('PlayerDeath', 'fire.flashlight', killLight)
hook.Add('PlayerDisconnected', 'fire.flashlight', killLight)
hook.Add('PlayerSpawn', 'fire.flashlight', killLight)
hook.Add('simple-orgs.handOver', 'fire.flashlight', killLight)

View file

@ -0,0 +1,3 @@
octolib.shared('models')
octolib.shared('cars')
octolib.server('config/groups/fire/cmenu/server')

View file

@ -0,0 +1,213 @@
--[[
РАНГИ:
cad. Пожарный кадет
tra. Пожарный стажер
ff1. Пожарный I
emt. EMT пожарных
ff2. Пожарный II
prm. Парамедик пожарных
lie. Пожарный лейтенант
cap. Пожарный капитан
bc. Пожарный командир батальона
rchi. Пожарный районный шеф
ass. Помощник заместителя шефа
dep. Заместитель пожарного шефа
chi. Шеф пожарного департамента
]]
local clothesData = {
icon = 'user_firefighter',
['models/gta5/fire'] = {
{
bodygroup = 1,
vals = {
[0] = { 'Надеть шлем', 'bullet_blue', '/me надевает шлем на голову' },
[1] = { 'Снять шлем', 'cross', '/me снимает шлем с головы' },
},
},{
bodygroup = 2,
vals = {
[0] = { 'Снять кислородный баллон', 'cross', '/me снимает кислородный баллон с плеч' },
[1] = { 'Надеть кислородный баллон', 'bullet_blue', '/me надевает кислородный баллон на плечи' },
},
},{
bodygroup = 3,
vals = {
[0] = { 'Снять кислородную маску', 'cross', '/me снимает кислородную маску с лица' },
[1] = { 'Надеть кислородную маску', 'bullet_blue', '/me надевает кислородную маску на лицо' },
},
},
},
['models/taggart/police02/'] = {
{
bodygroup = 1,
vals = {
[0] = { 'Надеть кепку', 'bullet_blue', '/me надевает кепку на голову' },
[1] = { 'Снять кепку', 'cross', '/me снимает кепку с головы' },
},
},
},
}
local everydayMats = {
[4] = 'models/taggart/police02/securityguard1',
}
local everydayMats_hq = {
[4] = 'models/taggart/police02/securityguard2',
}
local firemenBgs = {
[1] = {
name = 'Снять шлем',
},
[2] = {
name = 'Газовый баллон',
},
[3] = {
name = 'Маска',
},
}
local models = {}
for i = 1, 9 do
models[#models + 1] = {
name = 'Офисная форма ' .. i,
model = ('models/taggart/police02/male_%02i.mdl'):format(i),
unisex = true,
everyday = true,
bgs = {
[1] = {
name = 'Снять кепку',
},
},
}
if i > 7 then continue end
models[#models + 1] = {
name = 'Пожарный ' .. i,
model = ('models/gta5/fire%s.mdl'):format(i),
unisex = true,
bgs = firemenBgs,
}
end
simpleOrgs.addOrg('fire', {
name = 'Пожарный Департамент',
title = 'Работа в Пожарном Департаменте',
shortTitle = 'Работа в Департаменте',
team = 'firefighter',
clothes = clothesData,
talkieFreq = 'ems',
rankOrder = {'cad', 'tra', 'ff1', 'emt', 'ff2', 'prm', 'lie', 'cap', 'bc', 'rchi', 'ass', 'dep', 'chi'},
multirank = true,
ranks = {
cad = { -- Cadet
shortName = 'Кадет',
name = 'Пожарный кадет',
mdls = models,
everydayMats = everydayMats,
icon = octolib.icons.silk16('user_firefighter'),
skin = 2,
},
tra = { -- Trainee
shortName = 'Стажер',
name = 'Пожарный стажер',
mdls = models,
everydayMats = everydayMats,
icon = octolib.icons.silk16('user_firefighter'),
skin = 2,
},
ff1 = { -- FireFighter I
shortName = 'Пожарный I',
name = 'Пожарный I',
mdls = models,
everydayMats = everydayMats,
icon = octolib.icons.silk16('user_firefighter'),
skin = 0,
},
emt = { -- Fire EMT
shortName = 'EMT',
name = 'EMT пожарных',
mdls = models,
everydayMats = everydayMats,
icon = octolib.icons.silk16('user_medical'),
skin = 0,
},
ff2 = { -- FireFighter II
shortName = 'Пожарный II',
name = 'Пожарный II',
mdls = models,
everydayMats = everydayMats,
icon = octolib.icons.silk16('user_firefighter'),
skin = 0,
},
prm = { -- Paramedic
shortName = 'Парамедик',
name = 'Парамедик пожарных',
mdls = models,
everydayMats = everydayMats,
icon = octolib.icons.silk16('user_medical'),
skin = 0,
},
lie = { -- Lieutenant
shortName = 'Лейтенант',
name = 'Пожарный лейтенант',
mdls = models,
everydayMats = everydayMats_hq,
icon = octolib.icons.silk16('user_firefighter'),
skin = 1,
},
cap = { -- Captain
shortName = 'Капитан',
name = 'Пожарный капитан',
mdls = models,
everydayMats = everydayMats_hq,
icon = octolib.icons.silk16('user_firefighter'),
skin = 1,
},
bc = { -- Battalion Commander
shortName = 'Шеф батальона',
name = 'Пожарный шеф батальона',
mdls = models,
icon = octolib.icons.silk16('user_firefighter'),
skin = 3,
},
rchi = { -- District Chief
shortName = 'Районный шеф',
name = 'Пожарный районный шеф',
mdls = models,
icon = octolib.icons.silk16('user_firefighter'),
skin = 3,
},
ass = { -- Assistant Chief
shortName = 'Помощник заместителя шефа',
name = 'Помощник заместителя шефа',
mdls = models,
icon = octolib.icons.silk16('lightning'),
skin = 3,
},
dep = { -- Deputy Chief
shortName = 'Заместитель пожарного шефа',
name = 'Заместитель пожарного шефа',
mdls = models,
icon = octolib.icons.silk16('user_firefighter'),
skin = 3,
},
chi = { -- Chief
shortName = 'Шеф',
name = 'Шеф пожарного департамента',
mdls = models,
icon = octolib.icons.silk16('user_firefighter'),
skin = 3,
},
},
})
-- fuck that shit
local toChange = octolib.array.toKeys({'male_02.mdl','male_05.mdl','male_06.mdl','male_07.mdl','male_08.mdl'})
hook.Add('EntitySubMaterialChange', 'dbg-orgs.fire', function(ent, index, mat)
local mdl = ent:GetModel()
if not mdl:find('taggart/police02') or not toChange[mdl:gsub('.+%/', '')] then return end
if index == 4 then ent:SetSubMaterial(5, mat) return true end
end)

View file

@ -0,0 +1,76 @@
local suit = 'models/humans/modern/octo/suit1_sheet'
local models = octolib.table.mapSequential({
{ 'models/humans/octo/male_01_01.mdl', 3},
{ 'models/humans/octo/male_01_02.mdl', 3},
{ 'models/humans/octo/male_01_03.mdl', 3},
{ 'models/humans/octo/male_02_01.mdl', 2},
{ 'models/humans/octo/male_02_02.mdl', 2},
{ 'models/humans/octo/male_02_03.mdl', 2},
{ 'models/humans/octo/male_03_01.mdl', 4},
{ 'models/humans/octo/male_03_02.mdl', 4},
{ 'models/humans/octo/male_03_03.mdl', 4},
{ 'models/humans/octo/male_03_04.mdl', 4},
{ 'models/humans/octo/male_03_05.mdl', 4},
{ 'models/humans/octo/male_03_06.mdl', 4},
{ 'models/humans/octo/male_03_07.mdl', 4},
{ 'models/humans/octo/male_04_01.mdl', 4},
{ 'models/humans/octo/male_04_02.mdl', 4},
{ 'models/humans/octo/male_04_03.mdl', 4},
{ 'models/humans/octo/male_04_04.mdl', 4},
{ 'models/humans/octo/male_05_01.mdl', 4},
{ 'models/humans/octo/male_05_02.mdl', 4},
{ 'models/humans/octo/male_05_03.mdl', 4},
{ 'models/humans/octo/male_05_04.mdl', 4},
{ 'models/humans/octo/male_05_05.mdl', 4},
{ 'models/humans/octo/male_06_01.mdl', 4},
{ 'models/humans/octo/male_06_02.mdl', 4},
{ 'models/humans/octo/male_06_03.mdl', 4},
{ 'models/humans/octo/male_06_04.mdl', 4},
{ 'models/humans/octo/male_06_05.mdl', 4},
{ 'models/humans/octo/male_07_01.mdl', 4},
{ 'models/humans/octo/male_07_02.mdl', 4},
{ 'models/humans/octo/male_07_03.mdl', 4},
{ 'models/humans/octo/male_07_04.mdl', 4},
{ 'models/humans/octo/male_07_05.mdl', 4},
{ 'models/humans/octo/male_07_06.mdl', 4},
{ 'models/humans/octo/male_08_01.mdl', 0},
{ 'models/humans/octo/male_08_02.mdl', 0},
{ 'models/humans/octo/male_08_03.mdl', 0},
{ 'models/humans/octo/male_08_04.mdl', 0},
{ 'models/humans/octo/male_09_01.mdl', 2},
{ 'models/humans/octo/male_09_02.mdl', 2},
{ 'models/humans/octo/male_09_03.mdl', 2},
{ 'models/humans/octo/male_09_04.mdl', 2},
}, function(v,i)
return {
name = 'Внешность ' .. i,
male = true,
model = v[1],
requiredMats = { [v[2]] = suit },
}
end)
simpleOrgs.addOrg('gov', {
name = 'Мэрия',
title = 'Работа в Мэрии',
shortTitle = 'Работа в Мэрии',
team = 'mayor',
talkieFreq = 'gov',
rankOrder = { 'worker', 'mayor' },
multirank = true,
ranks = {
worker = {
shortName = 'Сотрудник',
name = 'Сотрудник Мэрии',
mdls = models,
icon = octolib.icons.silk16('draw_star'),
},
mayor = {
shortName = 'Мэр',
name = 'Мэр',
mdls = models,
icon = octolib.icons.silk16('star'),
},
}
})

View file

@ -0,0 +1,115 @@
local clothesData = {
icon = 'user_medical',
['models/kerry/plats_medical_'] = {
{
bodygroup = 2,
vals = {
[0] = { 'Снять перчатки', 'cross', '/me снимает перчатки с рук' },
[1] = { 'Надеть перчатки', 'bullet_blue', '/me надевает перчатки на руки' },
},
},
},
}
local medicBgs = {
[1] = {
name = 'Форма',
vals = {
{'Парамедик', 0},
{'Врач', 1},
{'Хирург', 2},
}
},
[2] = {
name = 'Перчатки',
},
}
local medics = {}
for i = 1, 9 do
medics[#medics + 1] = {
model = ('models/kerry/plats_medical_%02i.mdl'):format(i),
male = true,
name = 'Медик ' .. i,
bgs = medicBgs,
}
if i == 6 then continue end
medics[#medics + 1] = {
model = ('models/player/kerry/plats_medic/male_%02i_medic.mdl'):format(i),
male = true,
name = 'Тёплая форма ' .. i,
}
end
for i = 10, 11 do
medics[#medics + 1] = {
model = ('models/kerry/plats_medical_%02i.mdl'):format(i),
male = false,
name = 'Медик ' .. i,
bgs = medicBgs,
}
end
for i = 1, 6 do
medics[#medics + 1] = {
model = ('models/player/kerry/plats_medic/female_%02i_medic.mdl'):format(i),
male = false,
name = 'Тёплая форма ' .. i,
}
end
simpleOrgs.addOrg('medic', {
name = 'Медицинский центр',
title = 'Работа в медицинском центре',
shortTitle = 'Работа в мед. центре',
team = 'paramedic',
mdls = medics,
clothes = clothesData,
talkieFreq = 'ems',
})
carDealer.addCategory('medic', {
name = 'Медики',
icon = octolib.icons.silk16('user_medical'),
ems = true,
doNotEvacuate = true,
canUse = function(ply) return ply:Team() == TEAM_DOCTOR, 'Доступно только медикам' end,
spawns = {
rp_evocity_dbg_220222 = {
{ Vector(-11295, 9344, 125), Angle(0,-90,0) }, -- hospital
{ Vector(-11111, 9344, 125), Angle(0,-90,0) },
},
rp_eastcoast_v4c = carDealer.civilSpawns.rp_eastcoast_v4c,
rp_truenorth_v1a = {
{ Vector(11667, 12990, 128), Angle(0, -90, 0) },
{ Vector(11876, 12990, 128), Angle(0, -90, 0) },
},
rp_riverden_dbg_220313 = {
{ Vector(-5453.52, 1579.42, -220.133), Angle(-0, -90, 0) },
{ Vector(-5453.98, 2185.43, -219.886), Angle(-0, -90, 0) },
},
},
spawnCheck = carDealer.limits.medic,
limitGroup = 'medic',
})
carDealer.addVeh('medicambulance', {
category = 'medic',
name = 'Ambulance',
simfphysID = 'sim_fphys_gta4_ambulance',
price = 0,
deposit = true,
customFOV = 42,
default = {
col = { Color(255,255,255), Color(23,11,192), Color(0,0,0), Color(255,255,255) },
bg = { [1] = 1 },
},
radioWhitelist = carDealer.emsRadioStations,
})
hook.Add('OnPlayerChangedTeam', 'orgs.medic', function(ply, old, new)
local job = RPExtraTeams[old]
local mask = ply:GetNetVar('hMask')
if job and job.medic and mask and mask[1] == 'medical_mask' then
ply:SetNetVar('hMask', nil)
end
end)

View file

@ -0,0 +1,147 @@
local clothesData = {
icon = 'user_police_england',
['models/player/octo_guard/'] = {
{
bodygroup = 2,
vals = {
[0] = { 'Снять бронежилет', 'cross', '/me снимает бронежилет' },
[1] = { 'Надеть бронежилет', 'bullet_blue', '/me надевает бронежилет на тело' },
},
},{
bodygroup = 3,
vals = {
[0] = { 'Снять шлем', 'cross', '/me снимает шлем с головы' },
[1] = { 'Надеть шлем', 'bullet_blue', '/me надевает шлем на голову' },
},
},
},
}
local maleBgs = {
[1] = {
name = 'Звание',
vals = {
{'Нет', 4},
{'Офицер I', 0},
{'Офицер II', 1},
{'Офицер III', 2},
{'Сержант', 3},
},
},
[2] = {
name = 'Бронежилет',
},
[3] = {
name = 'Шлем',
},
[4] = {
name = 'Короткие рукава',
},
}
local femaleBgs = {
[1] = {
name = 'Звание',
vals = {
{'Нет', 4},
{'Офицер I', 0},
{'Офицер II', 1},
{'Офицер III', 2},
{'Сержант', 3},
},
},
[2] = {
name = 'Бронежилет',
},
[3] = {
name = 'Шлем',
},
}
local models = {}
for i = 1, 9 do
models[#models + 1] = {
name = 'Форма ' .. i,
male = true,
model = ('models/player/octo_guard/male_%02i.mdl'):format(i),
bgs = maleBgs,
}
if i >= 7 then continue end
models[#models + 1] = {
name = 'Форма ' .. i,
male = false,
model = ('models/player/octo_guard/female_%02i.mdl'):format(i),
bgs = femaleBgs,
}
end
simpleOrgs.addOrg('prison', {
name = 'Тюрьма',
title = 'Тюрьма',
shortTitle = 'Тюрьма',
team = 'prison',
mdls = models,
clothes = clothesData,
talkieFreq = 'prison',
})
local ply = FindMetaTable 'Player'
function ply:SetPrisonClothes(val)
if self:IsMale() then
if val then
local mat = 'models/humans/modern/octo/prisoner1_sheet'
for i, original in ipairs(self:GetMaterials()) do
if string.match(original, '.+/sheet_%d+') then
self:SetSubMaterial(i - 1, mat)
end
end
else
local clothes = self:GetDBVar('customClothes') or nil
self:SetClothes(clothes)
end
end
end
local spawns = table.Copy(carDealer.policeSpawns)
spawns['rp_riverden_dbg_220313'] = {
{ Vector(11254, -10915, 820), Angle(0, 0, 0) },
{ Vector(11254, -11105, 820), Angle(0, 0, 0) },
{ Vector(11254, -11295, 820), Angle(0, 0, 0) },
{ Vector(11254, -11485, 820), Angle(0, 0, 0) },
{ Vector(11254, -12010, 820), Angle(0, 0, 0) },
{ Vector(11254, -12220, 820), Angle(0, 0, 0) },
{ Vector(11254, -12430, 820), Angle(0, 0, 0) },
{ Vector(11254, -12640, 820), Angle(0, 0, 0) },
}
carDealer.addCategory('prison', {
name = 'Тюрьма',
icon = octolib.icons.silk16('user_police_england'),
canUse = function(ply) return ply:Team() == TEAM_PRISON, 'Доступно только сотрудникам тюрьмы' end,
spawns = spawns,
spawnCheck = carDealer.limitedSpawn(1, 'prison', 'В городе уже есть тюремный транспорт'),
limitGroup = 'prison',
})
carDealer.addVeh('prison-bus', {
name = 'Автобус',
simfphysID = 'sim_fphys_tlad_pbus',
price = 0,
deposit = true,
customFOV = 42,
default = {
col = { Color(63,79,127), Color(255,255,255), Color(0,0,0), Color(255,255,255) },
},
radioWhitelist = carDealer.emsRadioStations,
})
carDealer.addVeh('prison-bobcat', {
name = 'Bobcat',
simfphysID = 'sim_fphys_gta4_bobcat',
price = 0,
deposit = true,
default = {
col = { Color(71,75,78), Color(255,255,255), Color(0,0,0), Color(255,255,255) },
},
})

View file

@ -0,0 +1,138 @@
local uniform = {
[5] = {
name = 'Форма',
vals = {
{'Работник склада', 'models/humans/modern/octo/ra2_sheet'},
{'Работник RA', 'models/humans/modern/octo/ra1_sheet'},
},
},
}
local models = octolib.table.mapSequential({
'models/humans/octo/male_01_01.mdl',
'models/humans/octo/male_01_02.mdl',
'models/humans/octo/male_01_03.mdl',
'models/humans/octo/male_02_01.mdl',
'models/humans/octo/male_02_02.mdl',
'models/humans/octo/male_02_03.mdl',
'models/humans/octo/male_03_01.mdl',
'models/humans/octo/male_03_02.mdl',
'models/humans/octo/male_03_03.mdl',
'models/humans/octo/male_03_04.mdl',
'models/humans/octo/male_03_05.mdl',
'models/humans/octo/male_03_06.mdl',
'models/humans/octo/male_03_07.mdl',
'models/humans/octo/male_04_01.mdl',
'models/humans/octo/male_04_02.mdl',
'models/humans/octo/male_04_03.mdl',
'models/humans/octo/male_04_04.mdl',
'models/humans/octo/male_05_01.mdl',
'models/humans/octo/male_05_02.mdl',
'models/humans/octo/male_05_03.mdl',
'models/humans/octo/male_05_04.mdl',
'models/humans/octo/male_05_05.mdl',
'models/humans/octo/male_06_01.mdl',
'models/humans/octo/male_06_02.mdl',
'models/humans/octo/male_06_03.mdl',
'models/humans/octo/male_06_04.mdl',
'models/humans/octo/male_06_05.mdl',
'models/humans/octo/male_07_01.mdl',
'models/humans/octo/male_07_02.mdl',
'models/humans/octo/male_07_03.mdl',
'models/humans/octo/male_07_04.mdl',
'models/humans/octo/male_07_05.mdl',
'models/humans/octo/male_07_06.mdl',
'models/humans/octo/male_08_01.mdl',
'models/humans/octo/male_08_02.mdl',
'models/humans/octo/male_08_03.mdl',
'models/humans/octo/male_08_04.mdl',
'models/humans/octo/male_09_01.mdl',
'models/humans/octo/male_09_02.mdl',
'models/humans/octo/male_09_03.mdl',
'models/humans/octo/male_09_04.mdl',
}, function(v, i)
return {
name = 'Внешность ' .. i,
male = true,
model = v,
requiredSkin = 1,
subMaterials = uniform,
}
end)
simpleOrgs.addOrg('ra', {
name = 'Richardson Atlantics',
title = 'Работа в Richardson Atlantics',
shortTitle = 'Richardson Atlantics',
team = 'ra',
mdls = models,
})
local carsColor = { Color(81,117,56), Color(81,117,56), Color(0,0,0), Color(81,117,56) }
carDealer.addCategory('ra', {
name = 'RA',
icon = 'octoteam/icons-16/lorry.png',
queue = true,
doNotEvacuate = true,
spawns = carDealer.civilSpawns,
canUse = function(ply)
if not ply:IsOrgMember('ra') then
return false, 'Доступно только для Richardson Atlantics'
end
end,
})
carDealer.addVeh('ra_pony', {
name = 'Pony',
simfphysID = 'sim_fphys_gta4_pony',
price = 5000,
deposit = true,
default = {
col = carsColor,
},
})
carDealer.addVeh('ra_packer', {
name = 'Packer',
simfphysID = 'sim_fphys_gta4_packer',
price = 15000,
deposit = true,
customFOV = 42,
default = {
col = carsColor,
},
})
carDealer.addVeh('ra_boxville', {
name = 'Boxville',
simfphysID = 'sim_fphys_gta4_boxville',
price = 20000,
deposit = true,
customFOV = 38,
default = {
col = carsColor,
},
})
carDealer.addVeh('ra_yankee', {
name = 'Yankee',
simfphysID = 'sim_fphys_gta4_yankee',
price = 25000,
deposit = true,
customFOV = 42,
default = {
col = carsColor,
skin = 3,
},
})
carDealer.addVeh('ra_flatbed', {
name = 'Flatbed',
simfphysID = 'sim_fphys_gta4_flatbed',
price = 30000,
deposit = true,
customFOV = 45,
default = {
col = carsColor,
},
})

View file

@ -0,0 +1,135 @@
local maleSubMats = {
[27] = {
name = 'Форма',
vals = {
{'Бежевый костюм', 'models/blairs/bs_suit_beige'},
{'Черный костюм', 'models/blairs/bs_suit_blackf'},
{'Светло-черный костюм', 'models/blairs/bs_suit_blacks'},
{'Синий костюм', 'models/blairs/bs_suit_blue'},
{'Серый костюм', 'models/blairs/bs_suit_gray'},
{'Зеленый костюм', 'models/blairs/bs_suit_green'},
{'Белый костюм', 'models/blairs/bs_suit_white'},
},
},
}
local femaleSubMats = {
[18] = 'models/blairs/bs_suite_femwhite',
}
local models = octolib.table.mapSequential({
'models/humans/octo/male_01_01.mdl',
'models/humans/octo/male_01_02.mdl',
'models/humans/octo/male_01_03.mdl',
'models/humans/octo/male_02_01.mdl',
'models/humans/octo/male_02_02.mdl',
'models/humans/octo/male_02_03.mdl',
'models/humans/octo/male_03_01.mdl',
'models/humans/octo/male_03_02.mdl',
'models/humans/octo/male_03_03.mdl',
'models/humans/octo/male_03_04.mdl',
'models/humans/octo/male_03_05.mdl',
'models/humans/octo/male_03_06.mdl',
'models/humans/octo/male_03_07.mdl',
'models/humans/octo/male_04_01.mdl',
'models/humans/octo/male_04_02.mdl',
'models/humans/octo/male_04_03.mdl',
'models/humans/octo/male_04_04.mdl',
'models/humans/octo/male_05_01.mdl',
'models/humans/octo/male_05_02.mdl',
'models/humans/octo/male_05_03.mdl',
'models/humans/octo/male_05_04.mdl',
'models/humans/octo/male_05_05.mdl',
'models/humans/octo/male_06_01.mdl',
'models/humans/octo/male_06_02.mdl',
'models/humans/octo/male_06_03.mdl',
'models/humans/octo/male_06_04.mdl',
'models/humans/octo/male_06_05.mdl',
'models/humans/octo/male_07_01.mdl',
'models/humans/octo/male_07_02.mdl',
'models/humans/octo/male_07_03.mdl',
'models/humans/octo/male_07_04.mdl',
'models/humans/octo/male_07_05.mdl',
'models/humans/octo/male_07_06.mdl',
'models/humans/octo/male_08_01.mdl',
'models/humans/octo/male_08_02.mdl',
'models/humans/octo/male_08_03.mdl',
'models/humans/octo/male_08_04.mdl',
'models/humans/octo/male_09_01.mdl',
'models/humans/octo/male_09_02.mdl',
'models/humans/octo/male_09_03.mdl',
'models/humans/octo/male_09_04.mdl',
}, function(v, i)
return {
name = 'Внешность ' .. i,
male = true,
model = v,
subMaterials = maleSubMats,
requiredSkin = 23,
}
end)
for num, i in ipairs({ 1, 2, 3, 4, 6, 7 }) do
models[#models + 1] = {
name = 'Внешность ' .. num,
male = false,
model = ('models/humans/octo/female_%02i.mdl'):format(i),
requiredMats = femaleSubMats,
requiredSkin = 29,
}
end
simpleOrgs.addOrg('taxi', {
name = 'Такси',
title = 'Работа в такси',
shortTitle = 'Работа в такси',
team = 'taxi',
mdls = models,
talkieFreq = 'taxi',
})
carDealer.addCategory('taxi', {
name = 'Таксисты',
icon = octolib.icons.silk16('car_taxi'),
queue = true,
canUse = function(ply) return ply:Team() == TEAM_TAXI, 'Доступно только таксистам' end,
spawns = carDealer.civilSpawns,
-- spawnCheck = carDealer.limitedSpawn(2, 'taxi', 'В городе уже достаточно машин такси'),
-- limitGroup = 'taxi',
})
carDealer.addVeh('taxi_taxi', {
name = 'Merit',
simfphysID = 'sim_fphys_gta4_taxi2',
price = 0,
deposit = true,
default = {
bg = { [1] = 2 },
col = { Color(215,142,16), Color(215,142,16), Color(0,0,0), Color(215,142,16) },
skin = 1,
},
})
carDealer.addVeh('taxi_cabbie', {
name = 'Cabby',
simfphysID = 'sim_fphys_gta4_cabby',
price = 0,
deposit = true,
default = {
col = { Color(215,142,16), Color(215,142,16), Color(0,0,0), Color(215,142,16) },
skin = 1,
},
})
carDealer.addVeh('taxi_vapid', {
name = 'Vapid',
simfphysID = 'sim_fphys_gta4_taxi',
price = 0,
deposit = true,
default = {
bg = { [1] = 2 },
col = { Color(215,142,16), Color(215,142,16), Color(0,0,0), Color(215,142,16) },
skin = 1,
},
})

View file

@ -0,0 +1,257 @@
hook.Add('car-dealer.priceOverride', 'dbg-police.wcso', function(ply, class)
local cdData = carDealer.vehicles[class]
if ply:Team() == TEAM_WCSO and cdData.police and cdData.deposit then return 0 end
end)
carDealer.addCategory('wcso', {
name = 'Офис Шерифа',
icon = octolib.icons.silk16('sheriff'),
ems = true,
doNotEvacuate = true,
canUse = function(ply) return ply:Team() == TEAM_WCSO, 'Доступно только сотрудникам Офиса Шерифа на службе' end,
spawns = carDealer.policeSpawns,
spawnCheck = carDealer.limits.police,
limitGroup = 'police',
})
carDealer.addVeh('wcso-vapid', {
category = 'wcso',
name = 'Police Vapid',
simfphysID = 'sim_fphys_gta4_police',
price = 30000,
deposit = true,
police = true,
radioWhitelist = carDealer.policeRadioStations,
default = {
mats = {
[1] = 'octoteam/models/vehicles/stainer/sheriff_livery_clr_1',
},
},
})
carDealer.addVeh('wcso-merit', {
category = 'wcso',
name = 'Police Merit',
simfphysID = 'sim_fphys_gta4_police2',
price = 40000,
deposit = true,
police = true,
radioWhitelist = carDealer.policeRadioStations,
default = {
mats = {
[14] = 'octoteam/models/vehicles/merit/sheriff2_livery_clr_1',
},
},
})
carDealer.addVeh('wcso-buffalo', {
category = 'wcso',
name = 'Police Buffalo',
simfphysID = 'sim_fphys_tbogt_police3',
price = 75000,
deposit = true,
police = true,
radioWhitelist = carDealer.policeRadioStations,
default = {
mats = {
[6] = 'octoteam/models/vehicles/buffalo/sheriff3_livery_clr_1',
},
},
})
local ranks = octolib.array.toKeys {'srg', 'lie', 'cap', 'ass', 'she', 'seb'}
carDealer.addCategory('wcso_nomark', {
name = 'Немаркированные',
icon = 'icon16/user_suit.png',
ems = true,
doNotEvacuate = true,
canUse = function(ply) return ply:Team() == TEAM_WCSO and ranks[ply:GetActiveRank('wcso') or ''] or false, 'Доступно только сержанту и старше' end,
spawns = {
rp_evocity_dbg_220222 = {
{ Vector(-4656, -7516, 225), Angle(0,-90,0) }, -- Duglas
{ Vector(-4656, -7211, 225), Angle(0,-90,0) },
{ Vector(-4656, -6906, 225), Angle(0,-90,0) },
{ Vector(-4656, -6601, 225), Angle(0,-90,0) },
{ Vector(-4656, -6296, 225), Angle(0,-90,0) },
},
rp_eastcoast_v4c = carDealer.policeSpawns.rp_eastcoast_v4c,
rp_truenorth_v1a = carDealer.policeSpawns.rp_truenorth_v1a,
},
spawnCheck = carDealer.limits.police,
limitGroup = 'police',
})
local randomColorTags = { {'icon16/color_wheel.png', 'Случайный цвет'} }
local function randomColor()
local colData = table.Random(carDealer.defaultCarColors)
local _, r, g, b = unpack(colData)
local col = Color(r, g, b)
return { col, col, Color(0,0,0), col }
end
local plateCol = {
bg = Color(255, 255, 255),
border = Color(40, 40, 40),
title = Color(255, 255, 255),
text = Color(0, 0, 0),
}
carDealer.addVeh('wcso_nomark_premier', {
name = 'Premier',
simfphysID = 'sim_fphys_gta4_premier',
price = 0,
police = true,
deposit = true,
tags = randomColorTags,
default = {
col = randomColor,
},
plateCol = plateCol,
})
carDealer.addVeh('wcso_nomark_dilettante', {
name = 'Dilettante',
simfphysID = 'sim_fphys_gta4_dilettante',
price = 0,
police = true,
deposit = true,
tags = randomColorTags,
default = {
col = randomColor,
},
plateCol = plateCol,
})
carDealer.addVeh('wcso_nomark_buffalo', {
name = 'Buffalo',
simfphysID = 'sim_fphys_gta4_fbi',
price = 0,
police = true,
deposit = true,
tags = randomColorTags,
default = {
col = randomColor,
},
plateCol = plateCol,
})
carDealer.addVeh('wcso_nomark_admiral', {
name = 'Admiral',
simfphysID = 'sim_fphys_gta4_admiral',
price = 0,
police = true,
deposit = true,
tags = randomColorTags,
default = {
col = randomColor,
},
plateCol = plateCol,
})
carDealer.addVeh('wcso_nomark_huntley', {
name = 'Huntley',
simfphysID = 'sim_fphys_gta4_huntley',
price = 0,
police = true,
deposit = true,
tags = randomColorTags,
default = {
col = randomColor,
},
plateCol = plateCol,
})
local function isSeb(ply)
return ply:GetActiveRank('wcso') == 'seb', 'Доступно только S.E.B.'
end
carDealer.addVeh('wcso_nomark_mule', {
name = 'Mule',
simfphysID = 'sim_fphys_gta4_mule',
price = 0,
police = true,
deposit = true,
tags = randomColorTags,
default = {
col = randomColor,
},
plateCol = plateCol,
canUse = isSeb,
})
carDealer.addVeh('wcso_nomark_burrito', {
name = 'Burrito',
simfphysID = 'sim_fphys_gta4_burrito',
price = 0,
police = true,
deposit = true,
tags = randomColorTags,
default = {
col = randomColor,
},
plateCol = plateCol,
canUse = isSeb,
})
carDealer.addVeh('wcso_nomark_moonbeam', {
name = 'Moonbeam',
simfphysID = 'sim_fphys_gta4_moonbeam',
price = 0,
police = true,
deposit = true,
tags = randomColorTags,
default = {
col = randomColor,
},
plateCol = plateCol,
canUse = isSeb,
})
carDealer.addVeh('wcso_nomark_taxi', {
name = 'Taxi',
simfphysID = 'sim_fphys_gta4_taxi2',
price = 8000,
police = true,
deposit = true,
default = {
col = { Color(215,142,16), Color(215,142,16), Color(0,0,0), Color(215,142,16) },
},
plateCol = plateCol,
canUse = isSeb,
})
carDealer.addVeh('wcso_nomark_cabbie', {
name = 'Cabby',
simfphysID = 'sim_fphys_gta4_cabby',
price = 15000,
police = true,
deposit = true,
default = {
col = { Color(215,142,16), Color(215,142,16), Color(0,0,0), Color(215,142,16) },
},
plateCol = plateCol,
canUse = isSeb,
})
-- SEB
carDealer.addVeh('seb_enforcer', {
name = 'Enforcer',
category = 'wcso',
simfphysID = 'sim_fphys_gta4_nstockade',
customFOV = 38,
price = 0,
bulletproof = true,
deposit = true,
police = true,
canUse = isSeb,
glauncher = true,
canSee = function(ply)
return ply:GetActiveRank('wcso') == 'seb'
end,
default = {
skin = 1,
},
radioWhitelist = carDealer.policeRadioStations,
})

View file

@ -0,0 +1,2 @@
octolib.shared('models')
octolib.shared('cars')

View file

@ -0,0 +1,373 @@
local clothesData = {
icon = 'sheriff',
['models/player/octo_sheriff/'] = {
{
sm = 'Головной убор',
icon = 'hat',
bodygroup = 3,
vals = {
[0] = { 'Надеть шляпу', 'bullet_blue', '/me надевает шляпу на голову' },
[1] = { 'Надеть шлем', 'bullet_black', '/me надевает шлем на голову' },
[2] = { 'Снять убор', 'cross', '/me снимает головной убор' },
},
},{
sm = 'Перчатки',
icon = 'hand',
bodygroup = 6,
vals = {
[0] = { 'Снять', 'cross', '/me снимает перчатки' },
[1] = { 'Надеть черные перчатки', 'bullet_black', '/me надевает черные перчатки' },
[2] = { 'Надеть белые перчатки', 'bullet_white', '/me надевает белые перчатки' },
},
},{
sm = 'Кобура тазера',
icon = 'gun',
bodygroup = 2,
vals = {
[0] = { 'Надеть кобуру тазера слева', 'arrow_left', '/me надевает кобуру с тазером слева' },
[1] = { 'Надеть кобуру тазера справа', 'arrow_right', '/me надевает кобуру с тазером справа' },
[2] = { 'Снять кобуру с тазером', 'cross', '/me снимает шлем с головы' },
},
},{
bodygroup = 7,
vals = {
[0] = { 'Надеть рацию', 'bullet_blue', '/me надевает рацию себе на грудь' },
[1] = { 'Снять рацию', 'cross', '/me снимает рацию с груди' },
},
},{
bodygroup = 5,
vals = {
[0] = { 'Надеть дубинку', 'bullet_blue', '/me вешает дубинку обратно на пояс' },
[1] = { 'Снять дубинку', 'cross', '/me снимает дубинку с пояса' },
},
},{
bodygroup = 4,
vals = {
[0] = { 'Надеть галстук', 'bullet_blue', '/me надевает галстук себе на шею, плотно его затягивая' },
[1] = { 'Снять галстук', 'cross', '/me снимает галстук, расслабяя воротник' },
},
},
},
['models/player/octo_swat_team/'] = {
{
bodygroup = 1,
vals = {
[0] = { 'Надеть бронежилет с разгрузками', 'bullet_blue', '/me надевает бронежилет на тело' },
[1] = { 'Снять бронежилет с разгрузками', 'cross', '/me снимает бронежилет с груди' },
},
},{
bodygroup = 2,
vals = {
[0] = { 'Снарядить низ', 'bullet_blue', '/me нацепляет снаряжения на ноги' },
[1] = { 'Снять всё с ног', 'cross', '/me снимает все снаряжение с ног' },
},
},{
bodygroup = 3,
vals = {
[0] = { 'Распрямить рукава', 'arrow_down', '/me распрямляет рукава' },
[1] = { 'Засучить рукава', 'arrow_up', '/me засучивает рукава' },
},
},{
bodygroup = 4,
vals = {
[0] = { 'Снять перчатки', 'cross', '/me снимает тактические перчатки с рук' },
[1] = { 'Надеть перчатки', 'bullet_blue', '/me надевает перчатки на руки' },
},
},{
bodygroup = 5,
vals = {
[0] = { 'Снять часы', 'cross', '/me снимает часы с рук' },
[1] = { 'Надеть часы', 'bullet_blue', '/me застегивает часы на руке' },
},
},{
bodygroup = 9,
vals = {
[0] = { 'Надеть шлем', 'bullet_blue', '/me надевает шлем на голову' },
[1] = { 'Снять шлем', 'cross', '/me снимает шлем с головы' },
},
},{
bodygroup = 10,
vals = {
[0] = { 'Надеть наушники', 'bullet_blue', '/me надевает наушники' },
[1] = { 'Снять наушники', 'cross', '/me снимает наушники' },
},
},{
bodygroup = 11,
vals = {
[0] = { 'Надеть прозрачные очки', 'bullet_white', '/me надевает прозрачные тактические очки на глаза' },
[1] = { 'Надеть затемненные очки', 'bullet_black', '/me надевает затемненные тактические очки на глаза' },
[2] = { 'Снять очки', 'cross', '/me снимает тактические очки с глаз' },
},
},{
bodygroup = 12,
vals = {
[0] = { 'Надеть камеру на шлем', 'bullet_blue', '/me надевает камеру на шлем' },
[1] = { 'Снять камеру со шлема', 'cross', '/me снимает камеру со шлема' },
},
},
},
}
local wcsoBgs = {
[1] = {
name = 'Внешний бронежилет',
},
[2] = {
name = 'Тазер',
vals = {
{ 'Слева', 0, true },
{ 'Справа', 1 },
{ 'Снять', 2 },
},
},
[3] = {
name = 'Головной убор',
vals = {
{ 'Шляпа', 0, true },
{ 'Шлем', 1 },
{ 'Снять', 2 },
},
},
[4] = {
name = 'Форма',
vals = {
{ 'Строгая', 0, true },
{ 'Повседневная', 1 },
{ 'Легкая', 2 },
},
},
[5] = {
name = 'Снять дубинку',
},
[6] = {
name = 'Перчатки',
vals = {
{ 'Без перчаток', 0, true },
{ 'Черные', 1 },
{ 'Белые', 2 },
},
},
[7] = {
name = 'Снять рацию',
},
}
local mdls = {}
for i, v in ipairs({1, 2, 3, 4, 5, 6, 8, 9}) do
mdls[#mdls + 1] = {
name = '%s ' .. i,
model = ('models/player/octo_sheriff/male_%02i.mdl'):format(v),
unisex = true,
bgs = wcsoBgs,
}
end
local sebNames = {
{'Westbrook', 0},
{'Sandstorm', 1},
{'Moore', 2},
{'Miller', 3},
{'Bartels', 4},
{'Marler', 5},
{'Mckenney', 6},
{'Rain', 7},
{'Thompson', 8},
{'Rose', 9},
{'Cramble', 10},
{'Phillips', 11},
{'Nelson', 12},
{'Anderson', 13},
{'Kertis', 14},
{'Campbell', 15},
{'Bradley', 16},
{'Archuleta', 17},
{'Murphy', 18},
{'Rumberger', 19},
{'Ter Stegen', 20},
{'Gvidichi', 21},
{'Coleman', 22},
{'Без имени', 26},
}
local sebBgs = {
[7] = {
name = 'Позывной',
vals = sebNames,
},
[13] = {
name = 'Патч на шлеме',
vals = {
{'Без патча', 0},
{'Патч "Punisher Thin Blue Line"', 1},
{'Патч 715 Team', 2},
{'Патч "Bang one, bang em\' all"', 3},
{'Патч "My idea of help"', 4},
{'Патч "Respect all, fear none', 5},
},
},
[11] = {
name = 'Очки',
vals = {
{'Прозрачные очки', 0},
{'Затемненные очки', 1},
{'Без очков', 2},
},
},
[1] = {
name = 'Стандартный вверх',
},
[2] = {
name = 'Стандартный низ',
},
[3] = {
name = 'Засученные рукава',
},
[4] = {
name = 'Тактические перчатки',
},
[5] = {
name = 'Часы',
},
[6] = {
name = 'Медицинский патч на разгрузку',
},
[9] = {
name = 'Снять шлем',
},
[10] = {
name = 'Снять наушники',
},
[12] = {
name = 'Снять камеру на шлеме',
},
}
local sebMdls = {}
local skins = {[1] = 2, [2] = 2, [3] = 6, [4] = 3, [5] = 4, [6] = 4, [7] = 5, [8] = 4, [9] = 3}
for i = 1, 9 do
sebMdls[#sebMdls + 1] = {
name = 'Форма ' .. i,
male = true,
model = ('models/player/octo_swat_team/male_%02i.mdl'):format(i),
bgs = sebBgs,
requiredMats = {
[4] = 'models/octo_swat_team/body_01_seb',
[5] = 'models/octo_swat_team/armor_seb',
[6] = 'models/octo_swat_team/patch_seb',
[7] = 'models/octo_swat_team/lowr_01_seb',
[11] = 'models/octo_swat_team/hlem_seb',
},
skin = {
name = 'Внешность',
vals = {},
},
}
for n = 0, skins[i] do
sebMdls[i].skin.vals[#sebMdls[i].skin.vals + 1] = { 'Внешность ' .. (n + 1), n }
end
end
table.Add(sebMdls, mdls)
simpleOrgs.addOrg('wcso', {
name = 'Офис Шерифа',
title = 'Работа в Офисе Шерифа',
shortTitle = 'Работа в WCSO',
team = 'wcso',
police = true,
talkieFreq = 'ems',
clothes = clothesData,
rankOrder = { 'cad', 'ins', 'ds1', 'ds2', 'crp', 'srg', 'lie', 'cap', 'ass', 'she', 'seb' },
multirank = true,
ranks = {
cad = { -- Cadet
shortName = 'Кадет',
name = 'Кадет офиса Шерифа',
mdls = mdls,
icon = octolib.icons.silk16('sheriff'),
weps = { 'weapon_octo_air_glock17', 'weapon_octo_air_m4a1', 'weapon_octo_air_m3' },
skin = 0,
},
ins = { -- Instructor
shortName = 'Инструктор',
name = 'Инструктор офиса Шерифа',
mdls = mdls,
icon = octolib.icons.silk16('sheriff'),
weps = { 'weapon_octo_air_glock17', 'weapon_octo_air_m4a1', 'weapon_octo_air_m3' },
skin = 3,
},
ds1 = { -- Deputy Sheriff I
shortName = 'Помощник Шерифа I',
name = 'Помощник Шерифа I',
mdls = mdls,
icon = octolib.icons.silk16('sheriff'),
skin = 0,
},
ds2 = { -- Deputy Sheriff II
shortName = 'Помощник Шерифа II',
name = 'Помощник Шерифа II',
mdls = mdls,
icon = octolib.icons.silk16('sheriff'),
skin = 1,
},
crp = { -- Corporal
shortName = 'Капрал',
name = 'Капрал офиса Шерифа',
mdls = mdls,
icon = octolib.icons.silk16('sheriff'),
skin = 2,
},
srg = { -- Sergeant
shortName = 'Сержант',
name = 'Сержант офиса Шерифа',
mdls = mdls,
icon = octolib.icons.silk16('sheriff'),
skin = 3,
},
lie = { -- Lieutenant
shortName = 'Лейтенант',
name = 'Лейтенант офиса Шерифа',
mdls = mdls,
icon = octolib.icons.silk16('sheriff'),
skin = 4,
},
cap = { -- Captain
shortName = 'Капитан',
name = 'Капитан офиса Шерифа',
mdls = mdls,
icon = octolib.icons.silk16('sheriff'),
skin = 5,
},
ass = { -- Assistant Sheriff
shortName = 'Ассистент Шерифа',
name = 'Ассистент Шерифа',
mdls = mdls,
icon = octolib.icons.silk16('sheriff'),
skin = 6,
},
she = { -- Sheriff
shortName = 'Шериф',
name = 'Шериф',
mdls = mdls,
icon = octolib.icons.silk16('sheriff'),
skin = 7,
},
seb = { -- S. E. B.
shortName = 'Оператор S.E.B.',
name = 'Оператор S.E.B.',
armor = 100,
mdls = sebMdls,
icon = octolib.icons.silk16('lightning'),
weps = {'weapon_octo_m4a1', 'weapon_octo_usps', 'weapon_octo_xm1014', 'weapon_octo_sg550', 'weapon_octo_beanbag', 'weapon_octo_p90', 'weapon_octo_tmp', 'door_ram', 'dbg_shield'},
excludeWeps = {'weapon_octo_glock17', 'dbg_speedometer'},
},
}
})
netstream.Hook('wcso.gloves', function(ply, val)
if not (ply:GetActiveRank('wcso') and octolib.math.inRange(val, 0, 2)) then return end
ply:SetBodygroup(6, val)
end)

View file

@ -0,0 +1,88 @@
if game.GetMap() == 'rp_truenorth_v1a' then
local function createSSEnt(ent, class)
local pos, ang = ent:GetPos(), ent:GetAngles()
ent:Remove()
ent = ents.Create(class)
ent:SetPos(pos)
ent:SetAngles(ang)
ent:Spawn()
ent:GetPhysicsObject():EnableMotion(false)
end
local toRem = {2699, 2700, 3838}
local function makeDobrograd()
for _,v in ipairs(ents.GetAll()) do
if v:GetName() == 'speed50' then
v:SetSkin(5)
elseif v:GetName() == 'speed80' then
v:SetSkin(6)
elseif v:GetName() == 'speed100' then
v:SetSkin(7)
elseif v:GetName() == 'flagpole' then
v:SetSkin(1)
elseif v:GetName() == 'hwyca' or v:GetName() == 'pumps' then
v:Remove()
elseif v:GetName() == 'hwyus' then
v:Fire('TurnOn', 1, 0)
if v:GetModel() == 'models/props_street/mail_dropbox.mdl' then
createSSEnt(v, 'octoinv_mailbox')
end
elseif v:GetModel() == 'models/props_unique/atm01.mdl' then
createSSEnt(v, 'brax_atm')
end
end
for _,v in ipairs(toRem) do
ents.GetMapCreatedEntity(v):Remove()
end
end
hook.Add('InitPostEntity', 'dbg-cleanthemap', makeDobrograd)
hook.Add('PostCleanupMap', 'dbg-cleanthemap', makeDobrograd)
end
local function setupWeather()
if game.GetMap():find('evocity') then
local lightspots, sprites, spots, lights, nlights1, nlights3 = {}, {}, {}, {}, {}, {}
for _, ent in ipairs(ents.GetAll()) do
local name = ent:GetName()
if name == 'street_lightspot' then lightspots[#lightspots + 1] = ent
elseif name == 'street_sprite' then sprites[#sprites + 1] = ent
elseif name == 'street_spot' then spots[#spots + 1] = ent
elseif name == 'street_light' then lights[#lights + 1] = ent
elseif name == 'nightlight1' then nlights1[#nlights1 + 1] = ent
elseif name == 'nightlight3' then nlights3[#nlights3 + 1] = ent end
end
local lastLight = -1
timer.Create('dbg-weather', 1, 0, function()
local curLight = StormFox2.Weather.GetLuminance()
local turnOn = curLight < 125
if lastLight >= 0 and turnOn == (lastLight < 125) then return end
lastLight = curLight
for _, ent in ipairs(lightspots) do ent:Fire(turnOn and 'LightOn' or 'LightOff') end
for _, ent in ipairs(sprites) do ent:Fire(turnOn and 'ShowSprite' or 'HideSprite') end
for _, ent in ipairs(spots) do ent:Fire(turnOn and 'TurnOn' or 'TurnOff') end
for _, ent in ipairs(lights) do ent:Fire(turnOn and 'TurnOn' or 'TurnOff') end
for _, ent in ipairs(nlights1) do ent:Fire(turnOn and 'TurnOn' or 'TurnOff') end
for _, ent in ipairs(nlights3) do ent:Fire(turnOn and 'TurnOn' or 'TurnOff') end
end)
end
end
hook.Add('InitPostEntity', 'dbg-weather', setupWeather)
hook.Add('PostCleanupMap', 'dbg-weather', setupWeather)
setupWeather()
hook.Add('InitPostEntity', 'dbg-doors', function()
for _,v in ipairs(ents.GetAll()) do
if v:IsDoor() then
v.defaultSkin = v:GetSkin()
v.defaultBGs = {}
for _,bg in ipairs(v:GetBodyGroups()) do
v.defaultBGs[bg.id] = v:GetBodygroup(bg.id)
end
end
end
end)

View file

@ -0,0 +1,558 @@
CFG.masks = {
cleaver = {
name = L.mask_cleaver,
mdl = 'models/props_lab/Cleaver.mdl',
pos = Vector(-3.1, 6.7, 5.2),
ang = Angle(0, 85, 0),
scale = 0.6,
},
monkey = {
name = L.mask_monkey,
mdl = 'models/sal/halloween/monkey.mdl',
pos = Vector(-4.1, 0, -2.2),
hideName = true,
},
zombie = {
name = L.mask_zombie,
mdl = 'models/sal/halloween/zombie.mdl',
pos = Vector(-3.7, 0, -2),
hideName = true,
},
hockey = {
name = L.mask_hockey,
mdl = 'models/sal/acc/fix/mask_2.mdl',
pos = Vector(-4, 0, -1.9),
hideName = true,
},
gingerbread = {
name = L.mask_gingerbread,
mdl = 'models/sal/gingerbread.mdl',
pos = Vector(-4.2, 0, -2),
ang = Angle(-2.8, 0, 0),
hideName = true,
},
pumpkin = {
name = L.mask_pumpkin,
mdl = 'models/halloween2015/pumbkin_n_f01.mdl',
pos = Vector(-2.9, 0, 0.7),
ang = Angle(11, 0, 0),
scale = 0.4,
hideName = true,
},
top_hat = {
name = L.mask_top_hat,
mdl = 'models/player/items/humans/top_hat.mdl',
pos = Vector(-3.1, 0, -3.6),
},
doctor = {
name = L.mask_doctor,
mdl = 'models/sal/halloween/doctor.mdl',
pos = Vector(-5, 0, -2),
hideName = true,
},
pig = {
name = L.mask_pig,
mdl = 'models/sal/pig.mdl',
pos = Vector(-4.2, 0, -2.4),
hideName = true,
},
bear = {
name = L.mask_bear,
mdl = 'models/sal/bear.mdl',
pos = Vector(-4.3, 0, -1.7),
ang = Angle(-5.6, 0, 0),
hideName = true,
},
turtle = {
name = L.mask_turtle,
mdl = 'models/props/de_tides/vending_turtle.mdl',
pos = Vector(-3.2, 0.1, 3.8),
ang = Angle(-1.3, -95.9, -3.8),
scale = 0.61,
},
deer = {
name = L.mask_deer,
mdl = 'models/monstermash/gibs/head_deerhaunter.mdl',
pos = Vector(-5.1, 0, -6.6),
ang = Angle(-3.4, 1.5, -2.9),
scale = 1.3,
skin = 1,
hideName = true,
},
mummy = {
name = L.mask_mummy,
mdl = 'models/monstermash/gibs/head_mummy.mdl',
pos = Vector(0, 0, -7),
ang = Angle(0, 95.1, -18.6),
scale = 1.02,
hideName = true,
},
santa = {
name = 'Новогодний колпак',
icon = 'octoteam/icons/xmas_hat.png',
mdl = 'models/cloud/kn_santahat.mdl',
pos = Vector(-4.6, 0, -3.8),
ang = Angle(0.8, -85.2, 81.1),
scale = 1.02,
},
gasmask = {
name = L.mask_gasmask,
icon = 'octoteam/icons/gasmask.png',
desc = L.desc_gasmask,
mdl = 'models/splinks/kf2/cosmetics/gas_mask.mdl',
pos = Vector(-4.4, 0, -2.7),
ang = Angle(0, 0, 0),
hideName = true,
},
cap_dobrograd = {
name = L.cap_dobrograd,
icon = 'octoteam/icons/clothes_cap.png',
desc = L.cap_dobrograd_desc,
noDrop = true,
mdl = 'models/modified/hat08.mdl',
pos = Vector(-3.7, 0, 1.1),
skin = 1,
},
orangecap = {
name = 'Оранжевая кепка',
icon = 'octoteam/icons/clothes_cap.png',
desc = 'Обычная оранжевая кепка с каким-то логотипом',
mdl = 'models/modified/hat08.mdl',
pos = Vector(-3.7, 0, 1.1),
skin = 0,
price = 12000,
},
redcap = {
name = 'Красная кепка',
icon = 'octoteam/icons/clothes_cap.png',
desc = 'Классическая красная кепка с каким-то логотипом',
mdl = 'models/modified/hat08.mdl',
pos = Vector(-3.7, 0, 1.1),
skin = 4,
price = 14000,
},
cap_meteorite = {
name = 'Кепка "Meteorite"',
icon = 'octoteam/icons/clothes_cap.png',
desc = 'Классическая кепка черного цвета с логотипом "Meteorite"',
mdl = 'models/modified/hat08.mdl',
pos = Vector(-3.7, 0, 1.1),
skin = 8,
price = 12000,
},
cap_monkey = {
name = 'Кепка "Orang-O-Tang"',
icon = 'octoteam/icons/clothes_cap.png',
desc = 'Классическая кепка коричневого цвета с логотипом "Orang-O-Tang" и обезьянкой',
mdl = 'models/modified/hat08.mdl',
pos = Vector(-3.7, 0, 1.1),
skin = 11,
price = 14000,
},
cap_quests = {
name = 'Кепка "Лига Квестов"',
icon = 'octoteam/icons/clothes_cap.png',
desc = 'Фирменная кепка Лиги Квестов',
mdl = 'models/leeetov/quest_cap.mdl',
pos = Vector(-3.6, -0.19, 1.8),
},
mask_hoffman = {
name = 'Маска с эмблемой короны',
desc = L.mask_hoffman,
noDrop = true,
mdl = 'models/sal/acc/fix/mask_2.mdl',
pos = Vector(-3.8, 0, -1.9),
ang = Angle(0, 0, 0),
skin = 5,
hideName = true,
},
hoff_widesmile = {
name = 'Пакет на голову',
desc = '"Звериный скал"',
noDrop = true,
mdl = 'models/sal/halloween/bag.mdl',
pos = Vector(-3.3, 0, -1.5),
ang = Angle(0, 0, 0),
skin = 1,
hideName = true,
},
hoff_tears = {
name = 'Пакет на голову',
desc = '"Плак-плак"',
noDrop = true,
mdl = 'models/sal/halloween/bag.mdl',
pos = Vector(-3.3, 0, -1.5),
ang = Angle(0, 0, 0),
skin = 2,
hideName = true,
},
hoff_tinysmile = {
name = 'Пакет на голову',
desc = '"Легкий скал"',
noDrop = true,
mdl = 'models/sal/halloween/bag.mdl',
pos = Vector(-3.3, 0, -1.5),
ang = Angle(0, 0, 0),
skin = 3,
hideName = true,
},
hoff_dude = {
name = 'Пакет на голову',
desc = '"Чувак"',
noDrop = true,
mdl = 'models/sal/halloween/bag.mdl',
pos = Vector(-3.3, 0, -1.5),
ang = Angle(0, 0, 0),
skin = 5,
hideName = true,
},
hoff_killme = {
name = 'Пакет на голову',
desc = '"Пожалуйста, убейте"',
noDrop = true,
mdl = 'models/sal/halloween/bag.mdl',
pos = Vector(-3.3, 0, -1.5),
ang = Angle(0, 0, 0),
skin = 8,
hideName = true,
},
hoff_helpme = {
name = 'Пакет на голову',
desc = '"Помогите"',
noDrop = true,
mdl = 'models/sal/halloween/bag.mdl',
pos = Vector(-3.3, 0, -1.5),
ang = Angle(0, 0, 0),
skin = 18,
hideName = true,
},
hardhat = {
name = 'Строительная каска',
noDrop = true,
mdl = 'models/props_junk/hardhat.mdl',
pos = Vector(-3.5, 0, 1.2),
ang = Angle(-5, 0, 0),
scale = 0.73,
},
peakless = {
name = 'Бескозырка',
desc = 'Удобная бескозырка, только без острия',
icon = 'octoteam/icons/peaky_hat.png',
mdl = 'models/modified/hat06.mdl',
pos = Vector(-4.5, -0.2, 2.2),
ang = Angle(0, 4.1, 0),
scale = 1.01,
price = 34000,
},
ninja = {
name = 'Балаклава',
desc = 'Маска, закрывающая не только лицо, но и часть головы и шею',
icon = 'octoteam/icons/robber.png',
mdl = 'models/sal/halloween/ninja.mdl',
pos = Vector(-4.2, 0.21, -2),
scale = 1.042,
hideName = true,
},
balaclava = {
name = 'Черная балаклава',
desc = 'Маска, закрывающая не только лицо, но и часть головы и шею',
icon = 'octoteam/icons/robber.png',
mdl = 'models/modified/balaclava.mdl',
pos = Vector(-3.8, 0.0, 1),
price = 10000,
hideName = true,
},
balaclava_g = {
name = 'Зеленая балаклава',
desc = 'Маска, закрывающая не только лицо, но и часть головы и шею',
icon = 'octoteam/icons/robber.png',
mdl = 'models/modified/balaclava_g.mdl',
pos = Vector(-2.3, 0.0, 2.2),
price = 10000,
hideName = true,
},
baseball = {
name = 'Классическая бейсболка',
desc = 'Бейсболка с логотипом лиги бейсбола',
icon = 'octoteam/icons/clothes_cap.png',
mdl = 'models/modified/hat07.mdl',
pos = Vector(-4, -0.19, 1.8),
ang = Angle(-7.2, 0, 0),
skin = 10,
price = 19000,
},
baseball_jordan = {
name = 'Бейсболка Jordan',
desc = 'Черная бейсболка с характерной баскетбольной символикой',
icon = 'octoteam/icons/clothes_cap.png',
mdl = 'models/modified/hat07.mdl',
pos = Vector(-4, -0.19, 1.8),
ang = Angle(-7.2, 0, 0),
skin = 0,
price = 20000,
},
yellowbaseball = {
name = 'Желтая бейсболка',
desc = 'Бейсболка желтого цвета с вышитой надписью',
icon = 'octoteam/icons/clothes_cap.png',
mdl = 'models/modified/hat07.mdl',
pos = Vector(-4, -0.19, 1.8),
ang = Angle(-7.2, 0, 0),
skin = 1,
price = 15000,
},
baseball_stetson = {
name = 'Бейсболка Stetson',
desc = 'Бейсболка в классическом американском стиле',
icon = 'octoteam/icons/clothes_cap.png',
mdl = 'models/modified/hat07.mdl',
pos = Vector(-4, -0.19, 1.8),
ang = Angle(-7.2, 0, 0),
skin = 3,
price = 24000,
},
baseball_detroit = {
name = 'Бейсболка Detroit',
desc = 'Классическая бейсболка темно-синего цвета с вышитым на передней части логотипом города',
icon = 'octoteam/icons/clothes_cap.png',
mdl = 'models/modified/hat07.mdl',
pos = Vector(-4, -0.19, 1.8),
ang = Angle(-7.2, 0, 0),
skin = 6,
price = 18000,
},
bandana = {
name = 'Черная бандана',
desc = 'Небольшой кусок ткани, служащий для сокрытия лица',
icon = 'octoteam/icons/bandana.png',
mdl = 'models/octoteam/accessory/bandana.mdl',
pos = Vector(-3.95, 0.1, -4),
ang = Angle(0.2, 0, 0),
scale = 1.03,
skin = 5,
price = 5000,
hideName = true,
},
redbandana = {
name = 'Красная бандана',
desc = 'Небольшой кусок ткани, служащий для сокрытия лица',
icon = 'octoteam/icons/bandana.png',
mdl = 'models/octoteam/accessory/bandana.mdl',
pos = Vector(-3.95, 0.1, -4),
ang = Angle(0.2, 0, 0),
scale = 1.03,
skin = 1,
price = 5000,
hideName = true,
},
yellowbandana = {
name = 'Желтая бандана',
desc = 'Небольшой кусок ткани, служащий для сокрытия лица',
icon = 'octoteam/icons/bandana.png',
mdl = 'models/octoteam/accessory/bandana.mdl',
pos = Vector(-3.95, 0.1, -4),
ang = Angle(0.2, 0, 0),
scale = 1.03,
skin = 2,
price = 5000,
hideName = true,
},
greenbandana = {
name = 'Зеленая бандана',
desc = 'Небольшой кусок ткани, служащий для сокрытия лица',
icon = 'octoteam/icons/bandana.png',
mdl = 'models/octoteam/accessory/bandana.mdl',
pos = Vector(-3.95, 0.1, -4),
ang = Angle(0.2, 0, 0),
scale = 1.03,
skin = 3,
price = 5000,
hideName = true,
},
bluebandana = {
name = 'Синяя бандана',
desc = 'Небольшой кусок ткани, служащий для сокрытия лица',
icon = 'octoteam/icons/bandana.png',
mdl = 'models/octoteam/accessory/bandana.mdl',
pos = Vector(-3.95, 0.1, -4),
ang = Angle(0.2, 0, 0),
scale = 1.03,
skin = 4,
price = 5000,
hideName = true,
},
medical_mask = {
name = 'Медицинская маска',
desc = 'Сейчас это актуально как никогда',
icon = 'octoteam/icons/medical_mask.png',
mdl = 'models/dean/gtaiv/mask.mdl',
pos = Vector(-3.5, 0, -3.1),
ang = Angle(11.2, 0, 0),
scale = 1.01,
hideName = true,
},
blackglasses = {
name = 'Черные очки',
desc = 'Самые стандартные очки с дешевой черной оправой',
icon = 'octoteam/icons/glasses_classic.png',
mdl = 'models/modified/glasses02.mdl',
pos = Vector(-3.9, 0, -0.13),
skin = 3,
price = 7000,
},
glasses = {
name = 'Классические очки',
desc = 'Самые стандартные очки с дешевой оправой',
icon = 'octoteam/icons/glasses_classic.png',
mdl = 'models/modified/glasses02.mdl',
pos = Vector(-3.9, 0, -0.13),
skin = 0,
price = 7000,
},
redglasses = {
name = 'Красные очки',
desc = 'Самые стандартные очки с дешевой красной оправой',
icon = 'octoteam/icons/glasses_classic.png',
mdl = 'models/modified/glasses02.mdl',
pos = Vector(-3.9, 0, -0.13),
skin = 1,
price = 7000,
},
whiteglasses = {
name = 'Белые очки',
desc = 'Самые стандартные очки с дешевой белой оправой',
icon = 'octoteam/icons/glasses_classic.png',
mdl = 'models/modified/glasses02.mdl',
pos = Vector(-3.9, 0, -0.13),
skin = 2,
price = 7000,
},
brownglasses = {
name = 'Коричневые очки',
desc = 'Самые стандартные очки с дешевой коричневой оправой',
icon = 'octoteam/icons/glasses_classic.png',
mdl = 'models/modified/glasses02.mdl',
pos = Vector(-3.9, 0, -0.13),
skin = 4,
price = 7000,
},
modelli = {
name = 'Очки LQB "Modelli"',
desc = 'Фирменные очки LQB, позолоченные дужки которых выполнены в виде специального узора',
icon = 'octoteam/icons/sun_glasses.png',
mdl = 'models/modified/lqb_glass2.mdl',
pos = Vector(-3.9, 0, -0.13),
},
rettelinee = {
name = 'Очки Gucci "Rette Linee"',
desc = 'Очки Gucci с фирменным узором на дужках',
icon = 'octoteam/icons/glasses_aviator.png',
mdl = 'models/modified/lqb_glass1.mdl',
pos = Vector(-3.9, 0, -0.13),
},
aviator = {
name = 'Черные авиаторы',
desc = 'Стильные очки "капельки" черного цвета, имеющие достаточно удобную форму оправы и линз',
icon = 'octoteam/icons/glasses_aviator.png',
mdl = 'models/modified/glasses01.mdl',
pos = Vector(-4.35, 0, -0.1),
skin = 0,
price = 12000,
},
greenaviator = {
name = 'Зеленые авиаторы',
desc = 'Стильные очки "капельки" зеленого цвета, имеющие достаточно удобную форму оправы и линз',
icon = 'octoteam/icons/glasses_aviator.png',
mdl = 'models/modified/glasses01.mdl',
pos = Vector(-4.35, 0, -0.1),
skin = 2,
price = 12000,
},
brownaviator = {
name = 'Коричневые авиаторы',
desc = 'Стильные очки "капельки" коричневого цвета, имеющие достаточно удобную форму оправы и линз',
icon = 'octoteam/icons/glasses_aviator.png',
mdl = 'models/modified/glasses01.mdl',
pos = Vector(-4.35, 0, -0.1),
skin = 3,
price = 12000,
},
orangeaviator = {
name = 'Оранжевые авиаторы',
desc = 'Стильные очки "капельки" оранжевого цвета, имеющие достаточно удобную форму оправы и линз',
icon = 'octoteam/icons/glasses_aviator.png',
mdl = 'models/modified/glasses01.mdl',
pos = Vector(-4.35, 0, -0.1),
skin = 4,
price = 12000,
},
greyaviator = {
name = 'Серые авиаторы',
desc = 'Стильные очки "капельки" серого цвета, имеющие достаточно удобную форму оправы и линз',
icon = 'octoteam/icons/glasses_aviator.png',
mdl = 'models/modified/glasses01.mdl',
pos = Vector(-4.35, 0, -0.1),
skin = 5,
price = 12000,
},
greyfedora = {
name = 'Серая федора',
desc = 'Легкая шляпка серого цвета, обвитая лентой',
icon = 'octoteam/icons/detective_hat.png',
mdl = 'models/modified/hat01_fix.mdl',
pos = Vector(-4.1, 0, 1.8),
ang = Angle(0, 0, 0),
scale = 0.96,
skin = 0,
price = 46000,
},
fedora = {
name = 'Черная федора',
desc = 'Легкая шляпка черного цвета, обвитая лентой',
icon = 'octoteam/icons/detective_hat.png',
mdl = 'models/modified/hat01_fix.mdl',
pos = Vector(-4.1, 0, 1.8),
ang = Angle(0, 0, 0),
scale = 0.96,
skin = 1,
price = 46000,
},
whitefedora = {
name = 'Белая федора',
desc = 'Легкая шляпка белого цвета, обвитая лентой',
icon = 'octoteam/icons/detective_hat.png',
mdl = 'models/modified/hat01_fix.mdl',
pos = Vector(-4.1, 0, 1.8),
ang = Angle(0, 0, 0),
scale = 0.96,
skin = 2,
price = 46000,
},
beigefedora = {
name = 'Бежевая федора',
desc = 'Легкая шляпка бежевого цвета, обвитая лентой',
icon = 'octoteam/icons/detective_hat.png',
mdl = 'models/modified/hat01_fix.mdl',
pos = Vector(-4.1, 0, 1.8),
ang = Angle(0, 0, 0),
scale = 0.96,
skin = 3,
price = 46000,
},
smartglasses = {
name = 'R&C SmartGlasses',
desc = 'Умные очки от компании R&C, выполненные из алюминия черного цвета. На боковой панельке очков есть сенсорная панель управления. На правой линзе выведено изображение с доступом к приложениям',
icon = octolib.icons.color('rc_glasses'),
mdl = 'models/rnc/acessories/rnc_smart_glasses01.mdl',
pos = Vector(-2.6, 0.1, -0.2),
ang = Angle(0, 0, 0),
scale = 0.92,
},
}

View file

@ -0,0 +1,33 @@
octochat.defineCommand('/spectate', {
permission = 'FSpectate',
aliases = {'!spectate', '~spectate'},
})
octochat.defineCommand('/spawn', {
check = DarkRP.isAdmin,
aliases = {'/respawn'},
})
octochat.defineCommand('!invisible', {
aliases = {'~invisible', '/invisible', '!cloak', '~cloak', '/cloak'},
permission = 'Invisible',
})
local adminData = {check = DarkRP.isAdmin}
octochat.defineCommand('/resetname', adminData)
octochat.defineCommand('/resetdesc', adminData)
octochat.defineCommand('/forceunlock', adminData)
octochat.defineCommand('/forcelock', adminData)
octochat.defineCommand('/forceown', adminData)
octochat.defineCommand('/forceunown', adminData)
octochat.defineCommand('/admintell', adminData)
octochat.defineCommand('/admintellall', adminData)
octochat.defineCommand('/teamban', adminData)
octochat.defineCommand('/teamunban', adminData)
local superAdminData = {check = DarkRP.isSuperAdmin}
octochat.defineCommand('/addjailpos', superAdminData)
octochat.defineCommand('/clearjailpos', superAdminData)
octochat.defineCommand('/groupown', superAdminData)
octochat.defineCommand('/groupunown', superAdminData)
octochat.defineCommand('/jobown', superAdminData)
octochat.defineCommand('/jobunown', superAdminData)

View file

@ -0,0 +1,279 @@
octochat.registerCommand('/spectate', {
cooldown = 1.5,
execute = function(ply, txt) ply:ConCommand('FSpectate ' .. txt) end,
aliases = {'!spectate', '~spectate'},
permission = 'FSpectate',
})
octochat.registerCommand('/spawn', {
cooldown = 1.5,
log = true,
consoleFriendly = true,
execute = function(ply, txt)
local target = txt == '' and ply or util.FindPlayer(txt)
if not IsValid(target) then return L.player_not_found end
if target:Alive() then target:KillSilent() end
target:SetNetVar('_SpawnTime', CurTime())
target:Notify(L.you_rescued:format(octochat.safePlayerName(ply)))
octochat.safeNotify(ply, L.you_rescued_by:format(target:Nick()))
end,
aliases = {'/respawn'},
check = DarkRP.isAdmin,
})
octochat.registerCommand('/addjailpos', {
execute = function(ply)
dbgPolice.addJailPos(ply:GetPos())
ply:Notify('Позиция тюрьмы добавлена')
end,
check = DarkRP.isSuperAdmin,
})
octochat.registerCommand('/clearjailpos', {
execute = function(ply)
dbgPolice.clearJailPos()
ply:Notify('Позиции тюрьмы очищены')
end,
check = DarkRP.isSuperAdmin,
})
octochat.registerCommand('/resetname', {
log = true,
consoleFriendly = true,
execute = function(ply, txt)
local target = txt == '' and ply or util.FindPlayer(txt)
if not IsValid(target) then return L.player_not_found end
local name = L.names[1][math.random(#L.names[1])] .. ' ' .. L.names[2][math.random(#L.names[2])]
target:SetName(name)
target:Notify('ooc', 'Администрация посчитала твое ролевое имя нарушающим правила и сбросила его. Ты можешь поставить новое и сменить персонажа')
target:ConCommand('dbg_name "' .. name .. '"')
octochat.safeNotify(ply, 'hint', 'Ролевое имя игрока сменено на ' .. name)
end,
check = DarkRP.isAdmin,
})
octochat.registerCommand('/resetdesc', {
log = true,
consoleFriendly = true,
execute = function(ply, txt)
local target = txt == '' and ply or util.FindPlayer(txt)
if not IsValid(target) then return L.player_not_found end
target:SetNetVar('dbgDesc')
target:Notify('ooc', 'Администрация посчитала твое описание внешности нарушающим правила и сбросила его. Ты можешь поставить новое и сменить персонажа')
octochat.safeNotify(ply, 'hint', 'Описание внешности игрока "' .. target:Name() .. '" сброшено')
end,
check = DarkRP.isAdmin,
})
octochat.registerCommand('/forceunlock', {
execute = function(ply)
local door = ply:GetEyeTrace().Entity
if not IsValid(door) or not door:IsDoor() then
return L.must_be_looking_at:format(L.door)
end
door:DoUnlock()
ply:Notify('Открыто')
end,
check = DarkRP.isAdmin,
})
octochat.registerCommand('/forcelock', {
execute = function(ply)
local door = ply:GetEyeTrace().Entity
if not IsValid(door) or not door:IsDoor() then
return L.must_be_looking_at:format(L.door)
end
door:DoLock()
ply:Notify('Закрыто')
end,
check = DarkRP.isAdmin,
})
octochat.registerCommand('/forceown', {
execute = function(ply, _, args)
if not args[1] or args[1] == '' then return 'Формат: /forceown "Ник игрока"' end
local door = ply:GetEyeTrace().Entity
if not IsValid(door) or not door:IsDoor() then
return L.must_be_looking_at:format(L.door)
end
local tgt = octochat.findPlayer(args[1])
if not tgt then return 'Укажи ник игрока' end
door:SetPlayerOwner(tgt)
ply:Notify('Теперь ' .. tgt:Name() .. ' владеет помещением')
end,
check = DarkRP.isAdmin,
})
octochat.registerCommand('/forceunown', {
execute = function(ply)
local door = ply:GetEyeTrace().Entity
if not IsValid(door) or not door:IsDoor() then
return L.must_be_looking_at:format(L.door)
end
local cur = door:GetPlayerOwner()
if not cur then return 'Этой дверью не владеет игрок' end
door:RemoveOwner(cur)
local tgt = player.GetBySteamID(cur)
ply:Notify('Теперь ' .. (IsValid(tgt) and tgt:Name() or cur) .. ' не владеет помещением')
end,
check = DarkRP.isAdmin,
})
octochat.registerCommand('/groupown', {
execute = function(ply, id)
local door = ply:GetEyeTrace().Entity
if not IsValid(door) or not door:IsDoor() then
return L.must_be_looking_at:format(L.door)
end
if not dbgDoorGroups.groups[id] then return 'Такой группы не существует' end
if door:AddGroupOwner(id) then
ply:Notify('Теперь ' .. dbgDoorGroups.groups[id] .. ' владеет помещением')
end
end,
check = DarkRP.isSuperAdmin,
})
octochat.registerCommand('/groupunown', {
execute = function(ply, id)
local door = ply:GetEyeTrace().Entity
if not IsValid(door) or not door:IsDoor() then
return L.must_be_looking_at:format(L.door)
end
if not dbgDoorGroups.groups[id] then return 'Такой группы не существует' end
if door:RemoveOwner('g:' .. id) then
ply:Notify('Теперь ' .. dbgDoorGroups.groups[id] .. ' не владеет помещением')
end
end,
check = DarkRP.isSuperAdmin,
})
octochat.registerCommand('/jobown', {
execute = function(ply, cmd)
local door = ply:GetEyeTrace().Entity
if not IsValid(door) or not door:IsDoor() then
return L.must_be_looking_at:format(L.door)
end
local job = DarkRP.getJobByCommand(cmd)
if not job then return 'Такой профессии не существует' end
if door:AddJobOwner(cmd) then
ply:Notify('Теперь ' .. job.name .. ' владеет помещением')
end
end,
check = DarkRP.isSuperAdmin,
})
octochat.registerCommand('/jobunown', {
execute = function(ply, cmd)
local door = ply:GetEyeTrace().Entity
if not IsValid(door) or not door:IsDoor() then
return L.must_be_looking_at:format(L.door)
end
local job = DarkRP.getJobByCommand(cmd)
if not job then return 'Такой професии не существует' end
if door:RemoveOwner('j:' .. cmd) then
ply:Notify('Теперь ' .. job.name .. ' не владеет помещением')
end
end,
check = DarkRP.isSuperAdmin,
})
--
-- INVISIBILITY
--
octochat.registerCommand('!invisible', {
cooldown = 1.5,
execute = function(ply)
local val = not ply:IsInvisible()
ply.manualInvisibility = val or nil
ply:MakeInvisible(val)
end,
aliases = {'~invisible', '/invisible', '!cloak', '~cloak', '/cloak'},
permission = 'Invisible',
})
--
-- ADMINTELL
--
local function fillInForm(ply, target, time, title, msg)
local isPlayer = target ~= nil
octolib.request.send(ply, {
{name = L.request_player, desc = 'Оставь заголовок и текст уведомления пустыми, если хочешь скрыть текущее уведомление у игрока'},
{type = 'numSlider', min = 3, max = 120, dec = 0, txt = L.time, default = time or 10},
{type = 'strShort', ph = L.title2, default = title},
{type = 'strLong', ph = L.trigger_text, default = msg},
}, function(data)
if not istable(data) then return end
if not (isnumber(data[2]) and isstring(data[3]) and isstring(data[4])) then return end
if not IsValid(target) and isPlayer then
if IsValid(ply) then ply:Notify('warning', 'Игрок вышел') end
return
end
hook.Run('dbg-admin.tell', ply, data[2], data[3], data[4], target)
octolib.notify.send(target, 'admin', data[2], data[3], data[4])
end)
end
octochat.registerCommand('/admintell', {
consoleFriendly = true,
execute = function(ply, _, args)
local target, txt = octochat.pickOutTarget(args)
if not IsValid(target) then return txt or 'Не удалось найти такого игрока' end
args = octochat.explodeArg(txt)
local time, title, msg = tonumber(args[2] or ''), args[3] or '', table.concat(args, ' ', 4) or ''
if not time or (title == '' and msg == '') then
if not IsValid(ply) then return 'Формат: /admintell "Ник игрока" Время "Заголовок" "Сообщение"' end
fillInForm(ply, target, time, title, msg)
else
hook.Run('dbg-admin.tell', ply, time, title, msg, target)
octolib.notify.send(target, 'admin', time, title, msg)
end
end,
check = DarkRP.isAdmin,
})
octochat.registerCommand('/admintellall', {
consoleFriendly = true,
execute = function(ply, _, args)
local time, title, msg = tonumber(args[1] or ''), args[2] or '', table.concat(args, ' ', 3) or ''
if not time or (title == '' and msg == '') then
if not IsValid(ply) then return 'Формат: /admintellall Время "Заголовок" "Сообщение"' end
fillInForm(ply, nil, time, title, msg)
else
hook.Run('dbg-admin.tell', ply, time, title, msg)
octolib.notify.sendAll('admin', time, title, msg)
end
end,
check = DarkRP.isAdmin,
})
--
-- TEAM BAN/UNBAN
--
octochat.registerCommand('/teamban', {
execute = function()
return 'Команда временно не работает'
end,
check = DarkRP.isAdmin,
})
octochat.registerCommand('/teamunban', {
execute = function()
return 'Команда временно не работает'
end,
check = DarkRP.isAdmin,
})

View file

@ -0,0 +1,3 @@
local emsData = {check = DarkRP.isGov}
octochat.defineCommand('/gr', emsData)
octochat.defineCommand('/panicbutton', emsData)

View file

@ -0,0 +1,57 @@
octochat.registerCommand('/gr', {
cooldown = 1.5,
log = true,
execute = function(ply, txt)
if txt == '' then return 'Формат: /gr Текст сообщения' end
local veh
for _, ent in ipairs(ents.FindInSphere(ply:GetPos(), 100)) do
if ent.IsSimfphyscar and not ent.preventEms then veh = ent break end
end
if not IsValid(veh) then
return 'Рядом должен находиться служебный автомобиль'
end
octochat.talkToRange(ply, 1500, Color(13, 134, 255), L.megaphone, color_white, txt)
veh:EmitSound('ambient/chatter/cb_radio_chatter_' .. math.random(1,3) .. '.wav', 130, 100, 1)
end,
check = DarkRP.isGov,
})
local leaveMeAloneID = 1
octochat.registerCommand('/panicbutton', {
cooldown = 60,
log = true,
execute = function(ply)
local job, jobname = ply:getJobTable()
if job then jobname = job.name end
local customJob = ply:GetNetVar('customJob')
if customJob then jobname = unpack(customJob) end
ply:DoEmote('{name} нажимает кнопку паники')
local msg = ('%s %s передает свое местоположение, используя тревожную кнопку!'):format(jobname, ply:Name())
local marker = {
id = 'cpPanicBtn' .. leaveMeAloneID,
group = 'cpPanicBtn',
txt = 'Кнопка паники',
pos = ply:GetPos() + Vector(0,0,40),
col = Color(102,170,170),
des = {'timedist', { 600, 300 }},
icon = 'octoteam/icons-32/exclamation.png',
size = 32,
}
for _,v in ipairs(player.GetAll()) do
if v:isCP() then
v:Notify('warning', msg)
v:EmitSound('npc/attack_helicopter/aheli_damaged_alarm1.wav', 45, 100, 0.5)
v:AddMarker(marker)
end
end
leaveMeAloneID = leaveMeAloneID + 1
end,
check = DarkRP.isGov,
})

View file

@ -0,0 +1,38 @@
octochat.defineCommand('/whisper', {
aliases = {'/w'},
})
octochat.defineCommand('/yell', {
aliases = {'/y'},
})
octochat.defineCommand('/me', true)
octochat.defineCommand('/it', true)
octochat.defineCommand('/pit', true)
octochat.defineCommand('/toit', true)
octochat.defineCommand('/whispertoit', {
aliases = {'/wtoit'},
})
octochat.defineCommand('/yelltoit', {
aliases = {'/ytoit'},
})
octochat.defineCommand('//it', {
permission = 'DBG: Глобальный IT',
})
octochat.defineCommand('/d', true)
octochat.defineCommand('/sms', true)
octochat.defineCommand('/roll', true)
octochat.defineCommand('/dice', true)
octochat.defineCommand('/coin', true)
octochat.defineCommand('/card', true)
octochat.defineCommand('/rockpaperscissors', true)
octochat.defineCommand('/dbg_getidea', true)
octochat.defineCommand('/give', true)
octochat.defineCommand('/dropmoney', {
aliases = {'/moneydrop'},
})
octochat.defineCommand('/putmoney', {
aliases = {'/moneyput'},
})

View file

@ -0,0 +1,407 @@
octochat.registerCommand('/whisper', {
cooldown = 1.5,
log = true,
execute = function(ply, txt) octochat.genericSayFunc(ply, txt, 90, ' шепчет: ') end,
aliases = {'/w'},
})
octochat.registerCommand('/yell', {
cooldown = 1.5,
log = true,
execute = function(ply, txt)
if txt == '' then return end
if txt:sub(-1) ~= '!' then txt = txt .. '!' end
octochat.genericSayFunc(ply, txt, 550, ' кричит: ')
end,
aliases = {'/y'},
})
octochat.registerCommand('/me', {
cooldown = 1.5,
log = true,
execute = function(ply, txt)
if txt == '' then return 'Формат: /me действие от третьего лица' end
ply:DoEmote('{name} ' .. utf8.lower(utf8.sub(txt, 1, 1)) .. utf8.sub(txt, 2))
end,
})
octochat.registerCommand('/it', {
cooldown = 1.5,
log = true,
execute = function(ply, txt)
if txt == '' then return 'Формат: /it Описание обстановки от третьего лица' end
octochat.talkToRange(ply, 250, octochat.textColors.rp, utf8.upper(utf8.sub(txt, 1, 1)) .. utf8.sub(txt, 2) .. ' ({name})' % {name = ply:Name()})
end,
})
octochat.registerCommand('/pit', {
cooldown = 1.5,
log = true,
execute = function(ply, _, args)
local target, txt = octochat.pickOutTarget(args)
if not target then return txt or 'Формат: /pit "Имя игрока" Текст обстановки' end
if txt == '' then return 'Формат: /pit "Имя игрока" Текст обстановки' end
octochat.talkTo(target, octochat.textColors.rp, '[Приватный IT, ', ply:Name(), '] ', txt)
octochat.talkTo(ply, octochat.textColors.rp, '[Приватный IT, ', target:Name(), '] ', txt)
end,
})
local function toit(ply, txt, radius, action)
local args = string.Explode(' * ', txt)
if not args[1] or args[1] == '' or not args[2] or args[2] == '' then return 'Формат: /toit действие * Фраза' end
action = action or txt:sub(-1) == '?' and 'спрашивает:' or 'говорит:'
octochat.genericSayFunc(ply, args[2], radius, (' %s, %s'):format(args[1], action))
if ply:GetNetVar('os_govorilka') and not ply:IsGovorilkaMuted() then
ply:DoVoice(args[2], ply:GetVoice(), heard)
end
end
octochat.registerCommand('/toit', {
cooldown = 1.5,
log = true,
execute = function(ply, txt)
toit(ply, txt, 250)
end,
})
octochat.registerCommand('/whispertoit', {
cooldown = 1.5,
log = true,
execute = function(ply, txt)
toit(ply, txt, 90, 'шепчет: ')
end,
aliases = {'/wtoit'},
})
octochat.registerCommand('/yelltoit', {
cooldown = 1.5,
log = true,
execute = function(ply, txt)
toit(ply, txt, 550, 'кричит: ')
end,
aliases = {'/ytoit'},
})
octochat.registerCommand('//it', {
cooldown = 1.5,
log = true,
execute = function(_, txt)
octochat.talkTo(nil, octochat.textColors.rp, txt)
end,
permission = 'DBG: Глобальный IT',
})
-- LOTTERY
local function lotterySay(ply, msg, all)
if all then
local receivers = octolib.array.filter(player.GetAll(), function(ply) return ply:HasPhone() end)
for i, receiver in ipairs(receivers) do
receiver:SendSMS(octochat.textColors.rp, 'Лотерейное бюро', L.owner_sms, Color(250,250,200), msg)
end
return
else
if not ply:HasPhone() then return end
ply:SendSMS(octochat.textColors.rp, 'Лотерейное бюро', L.owner_sms, Color(250,250,200), msg)
end
end
local function lotteryFilterValid(sid)
local ply = player.GetBySteamID(sid)
return IsValid(ply) and ply or nil
end
local entries = {}
local lotteryStarted, lotteryAmount = false, 0
local function startLottery()
if player.GetCount() <= 5 then return end
lotteryAmount = math.Round(math.random(GAMEMODE.Config.minlotterycost, GAMEMODE.Config.maxlotterycost))
hook.Run('lotteryStarted', lotteryAmount)
lotterySay(nil, L.lottery_started:format(DarkRP.formatMoney(lotteryAmount)), true)
lotteryStarted = true
timer.Simple(300, function()
local online = octolib.array.map(entries, lotteryFilterValid)
if not online[1] then
lotterySay(nil, L.lottery_noone_entered, true)
return hook.Run('lotteryEnded', entries)
end
local chosen = octolib.array.random(online)
local sum = math.Round((#entries * lotteryAmount) * 0.95)
hook.Run('lotteryEnded', entries, chosen, sum)
chosen:BankAdd(sum)
lotterySay(chosen, L.lottery_won:format(DarkRP.formatMoney(sum)))
entries, lotteryAmount, lotteryStarted = {}, 0, false
end)
end
timer.Create('dbg-lottery', octolib.time.toSeconds(1, 'hour'), 0, startLottery)
local function joinLottery(ply, args)
if not lotteryStarted then return lotterySay(ply, 'Лотерея сейчас не идёт!') end
table.remove(args, 1)
local txt = string.Trim(string.Implode(' ', args))
if not ply:BankHas(lotteryAmount) then
return false, L.cant_afford:format('участия в лотерее'), 'warning'
end
for _, v in ipairs(entries) do
if ply:SteamID() == v then
return lotterySay(ply, 'Вы уже участвуете в лотерее!')
end
end
ply:BankAdd(-lotteryAmount)
entries[#entries + 1] = ply:SteamID()
lotterySay(ply, L.lottery_entered)
hook.Run('playerEnteredLottery', ply)
end
local groups = { 'dpd', 'medic', 'fire', 'coroners', 'prison', 'wcso', 'csd', 'fbi', 'gov' }
local function isInDepartment(ply)
if ply:Team() == TEAM_ADMIN then return true end
for _, groupID in ipairs(groups) do
if ply.currentOrg == groupID then
return true
end
end
return false
end
octochat.registerCommand('/d', {
cooldown = 1.5,
log = true,
execute = function(ply, txt)
octochat.talkTo(octolib.array.filter(player.GetAll(), isInDepartment), octochat.textColors.rp, ply:Name(), ' передает на рацию департаментов: ', color_white, txt)
end,
check = isInDepartment,
})
octochat.registerCommand('/sms', {
cooldown = 1.5,
log = true,
phone = true,
execute = function(ply, _, args)
if not ply:Alive() or ply:IsGhost() then
return L.death_cannot_do_this
end
if ply:isArrested() then
return L.you_arrested
end
if ply:IsHandcuffed() then
return L.handcuffed_cannot_do_this
end
if txt == '' then return 'Формат: /sms "Имя игрока" Текст сообщения' end
if args[1] == 'lottery' then
joinLottery(ply, args)
return
end
local target, txt = octochat.pickOutTarget(args)
if not target then return txt or 'Формат: /sms "Имя игрока" Текст сообщения' end
if not target:HasPhone() then return L.abonent_unavailable end
ply:DoEmote('{name} отправляет SMS')
if not target:IsHandcuffed() then
target:SendSMS(octochat.textColors.rp, ply:Name(), L.owner_sms, Color(250,250,200), txt)
else
target:Notify('Тебе пришло SMS от ' .. ply:Name() .. ', но ты не можешь его прочитать, так как руки связаны')
end
ply:SendSMS(octochat.textColors.rp, target:Name(), L.target_sms, Color(250,250,200), txt)
end,
})
octochat.registerCommand('/roll', {
cooldown = 1.5,
log = true,
execute = function(ply, _, args)
local roll = ply:IsSuperAdmin() and tonumber(args[1] or '') or math.random(100)
ply:TalkToRange(350, octochat.textColors.rp, L.have_chance:format(ply:Name()), color_white, L.out_of_100:format(roll))
end,
})
octochat.registerCommand('/dice', {
cooldown = 1.5,
log = true,
execute = function(ply, _, args)
local roll1 = ply:IsSuperAdmin() and tonumber(args[1] or '') or math.random(6)
local roll2 = ply:IsSuperAdmin() and tonumber(args[2] or '') or math.random(6)
ply:TalkToRange(350, octochat.textColors.rp, L.threw_the_dice:format(ply:Name()), color_white, L.dice_and:format(roll1, roll2))
end,
})
octochat.registerCommand('/coin', {
cooldown = 1.5,
log = true,
execute = function(ply, _, args)
local roll = ply:IsSuperAdmin() and tonumber(args[1] or '') or math.random(2)
ply:TalkToRange(350, octochat.textColors.rp, ply:Name(), ' подбрасывает монетку: ', color_white, roll == 1 and 'орел' or 'решка')
end,
})
local cards = {}
for _, w1 in ipairs(L.card_parts1) do
for _, w2 in ipairs(L.card_parts2) do
cards[#cards + 1] = ('%s %s'):format(w1, w2)
end
end
octochat.registerCommand('/card', {
cooldown = 1.5,
log = true,
execute = function(ply, txt)
local card = ply:IsSuperAdmin() and txt ~= '' and string.lower(txt) or table.Random(cards)
local found = false
for _,v in ipairs(cards) do
if v == card then
found = true
break
end
end
if not found then card = table.Random(cards) end
ply:TalkToRange(350, octochat.textColors.rp, L.randomcard:format(ply:Name()), color_white, card)
end,
})
octochat.registerCommand('/rockpaperscissors', {
cooldown = 1.5,
log = true,
execute = function(ply, txt)
local gest = ply:IsSuperAdmin() and txt ~= '' and string.lower(txt) or table.Random(L.rps)
local found = false
for _,v in ipairs(L.rps) do
if v == gest then
found = true
break
end
end
if not found then gest = table.Random(L.rps) end
ply:TalkToRange(350, octochat.textColors.rp, L.gesture_showed:format(ply:Name()), color_white, gest)
end,
})
octochat.registerCommand('/dbg_getidea', {
cooldown = 1.5,
execute = function(ply) ply:Notify(L.ideas[math.random(#L.ideas)]) end,
})
octochat.registerCommand('/give', {
execute = function(ply, amount)
amount = amount:gsub('[^0-9]', '')
if amount == '' then return 'Формат: /give количество' end
amount = tonumber(amount)
if not amount then return 'Формат: /give количество' end
amount = math.floor(amount)
if amount <= 0 then return 'Укажи положительное число' end
if not ply:canAfford(amount) then return 'У тебя нет столько денег' end
local target = octolib.use.getTrace(ply).Entity
if not IsValid(target) or not target:IsPlayer() then return L.must_be_looking_at:format('игрока') end
if target:getJobTable().notHuman then return L.must_be_looking_at:format('живого человека') end
ply:DoAnimation(ACT_GMOD_GESTURE_ITEM_GIVE)
ply:addMoney(-amount)
ply:Notify(L.you_gave:format(target:Name(), DarkRP.formatMoney(amount)))
timer.Simple(1.2, function()
if not IsValid(ply) or not IsValid(target) then return end
target:addMoney(amount)
target:Notify(L.has_given:format(ply:Name(), DarkRP.formatMoney(amount)))
end)
hook.Run('DarkRP.payPlayer', ply, target, amount or 1)
end,
})
octochat.registerCommand('/dropmoney', {
cooldown = 3,
execute = function(ply, amount)
amount = amount:gsub('[^0-9]', '')
if amount == '' then return 'Формат: /dropmoney количество' end
amount = tonumber(amount)
if not amount then return 'Формат: /dropmoney количество' end
amount = math.floor(amount)
if amount <= 0 then return 'Укажи положительное число' end
if amount >= 10000000 then return 'Ты не можешь выбросить больше ' .. DarkRP.formatMoney(10000000) end
if not ply:canAfford(amount) then return 'У тебя нет столько денег' end
local taken = ply:addMoney(-amount)
if (taken or 0) < 1 then return end
ply:DoAnimation(ACT_GMOD_GESTURE_ITEM_GIVE)
timer.Simple(0.88, function()
if not IsValid(ply) then return end
local bonePos, boneAng = ply:GetBonePosition(ply:LookupBone('ValveBiped.Bip01_L_Hand') or 16)
local spawnPos, spawnAng = LocalToWorld(Vector(0,0,0), Angle(0,60,-15), bonePos, boneAng)
local drop = DarkRP.createMoneyBag(spawnPos, taken, ply)
drop:SetAngles(spawnAng)
drop.droppedBy = ply
local phys = drop:GetPhysicsObject()
if phys then
local dir = ply:GetAimVector()
dir.z = 0
phys:SetVelocity(dir * 200)
end
end)
end,
aliases = {'/moneydrop'},
})
octochat.registerCommand('/putmoney', {
cooldown = 3,
execute = function(ply, amount)
amount = amount:gsub('[^0-9]', '')
if amount == '' then return 'Формат: /putmoney количество' end
amount = tonumber(amount)
if not amount then return 'Формат: /putmoney количество' end
amount = math.floor(amount)
if amount <= 0 then return 'Укажи положительное число' end
if amount >= 10000000 then return 'Ты не можешь выбросить больше ' .. DarkRP.formatMoney(10000000) end
if not ply:canAfford(amount) then return 'У тебя нет столько денег' end
local taken = ply:addMoney(-amount)
if (taken or 0) < 1 then return end
ply:DoAnimation(ACT_GMOD_GESTURE_ITEM_GIVE)
timer.Simple(0.88, function()
if not IsValid(ply) then return end
local tr = util.TraceLine({
start = ply:EyePos(),
endpos = ply:EyePos() + ply:GetAimVector() * 85,
filter = ply,
})
local drop = DarkRP.createMoneyBag(tr.HitPos, taken, ply)
drop.droppedBy = ply
end)
end,
aliases = {'/moneyput'},
})

View file

@ -0,0 +1,20 @@
local mayorData = {check = DarkRP.isMayor}
octochat.defineCommand('/broadcast', mayorData)
octochat.defineCommand('/addlaw', mayorData)
octochat.defineCommand('/removelaw', mayorData)
octochat.defineCommand('/resetlaws', mayorData)
octochat.defineCommand('/lockdown', mayorData)
octochat.defineCommand('/unlockdown', mayorData)
octochat.defineCommand('/renamecity', mayorData)
octochat.defineCommand('/resetcity', true)
local function updateGMFuncs()
if not DarkRP then return end
function DarkRP.getLaws()
return netvars.GetNetVar('laws')
end
end
hook.Add('darkrp.loadModules', 'dbg-commands.mayor', updateGMFuncs)
updateGMFuncs()

View file

@ -0,0 +1,249 @@
octochat.registerCommand('/broadcast', {
cooldown = 1.5,
log = true,
execute = function(_, txt)
if txt == '' then return 'Формат: /broadcast Текст объявления' end
octochat.talkTo(nil, Color(214,74,65), L.broadcast_text, Color(250,250,200), unpack(octolib.string.splitByUrl(txt)))
end,
check = DarkRP.isMayor,
})
-- LAWS
octochat.registerCommand('/addlaw', {
log = true,
execute = function(ply, txt)
local can, why = hook.Run('canEditLaws', ply, 'addLaw', txt)
if can == false then
return why or 'Ты не можешь изменять законы'
end
if txt == '' then return 'Формат: /addlaw Текст закона' end
if utf8.len(txt) < 10 then
return L.law_too_short
end
local laws = netvars.GetNetVar('laws')
if #laws >= 20 then
return L.laws_full
end
laws[#laws + 1] = txt
netvars.SetNetVar('laws', laws)
hook.Run('addLaw', #laws, txt, ply)
ply:Notify(L.law_added)
end,
check = DarkRP.isMayor,
})
octochat.registerCommand('/removelaw', {
log = true,
execute = function(ply, _, args)
local can, why = hook.Run('canEditLaws', ply, 'removeLaw', txt)
if can == false then
return why or 'Ты не можешь изменять законы'
end
local laws = netvars.GetNetVar('laws')
local i = tonumber(args[1])
if not i or not laws[i] then
return 'Неверный номер закона'
end
if GAMEMODE.Config.DefaultLaws[i] then
return L.default_law_change_denied
end
local law = laws[i]
table.remove(laws, i)
netvars.SetNetVar('laws', laws)
hook.Run('removeLaw', i, law, ply)
ply:Notify(L.law_removed)
end,
check = DarkRP.isMayor,
})
octochat.registerCommand('/resetlaws', {
consoleFriendly = true,
log = true,
execute = function(ply)
if IsValid(ply) then
local can, why = hook.Run('canEditLaws', ply, 'resetLaws')
if can == false then
return why or 'Ты не можешь изменять законы'
end
end
hook.Run('resetLaws', ply)
DarkRP.resetLaws()
octochat.safeNotify(ply, L.law_reset)
end,
check = DarkRP.isMayor,
})
local function updateGMFuncs()
if not DarkRP then return end
function DarkRP.resetLaws()
netvars.SetNetVar('laws', table.Copy(GAMEMODE and GAMEMODE.Config.DefaultLaws or {}))
end
DarkRP.resetLaws()
function DarkRP.getLaws()
return netvars.GetNetVar('laws')
end
end
hook.Add('darkrp.loadModules', 'dbg-commands.laws', updateGMFuncs)
updateGMFuncs()
-- LOCKDOWN
local lastLockdown = -math.huge
local function updateGMFuncs()
if not DarkRP then return end
function DarkRP.lockdown()
for _,v in ipairs(player.GetAll()) do
v:ConCommand('play ' .. GAMEMODE.Config.lockdownsound .. '\n')
end
netvars.SetNetVar('lockdown', true)
octolib.notify.sendAll('warning', L.lockdown_started)
end
function DarkRP.unLockdown()
netvars.SetNetVar('lockdown', nil)
lastLockdown = CurTime()
octolib.notify.sendAll('hint', L.lockdown_ended)
end
end
hook.Add('darkrp.loadModules', 'dbg-commands.lockdown', updateGMFuncs)
updateGMFuncs()
octochat.registerCommand('/lockdown', {
execute = function(_, txt)
if netvars.GetNetVar('lockdown') then
return 'Комендантский час уже введен. Выполни /unlockdown, чтобы отменить его'
end
if not GAMEMODE.Config.lockdown then
return 'Комендантский час отключен'
end
if lastLockdown > CurTime() - GAMEMODE.Config.lockdowndelay then
return 'Комендантский час уже недавно вводился'
end
txt = string.Trim(txt)
if txt ~= '' then
octochat.talkTo(nil, Color(214,74,65), L.broadcast_text, Color(250,250,200), unpack(octolib.string.splitByUrl(txt)))
end
DarkRP.lockdown()
end,
check = DarkRP.isMayor,
})
octochat.registerCommand('/unlockdown', {
execute = function()
if not netvars.GetNetVar('lockdown') then
return 'Сейчас не объявлен комендантский час. Выполни /lockdown, чтобы ввести его'
end
if not GAMEMODE.Config.lockdown then
return 'Комендантский час отключен'
end
DarkRP.unLockdown()
end,
check = DarkRP.isMayor,
})
--
-- DOBROGRAD NAME
--
local names = L.town_names
local function updateServerName()
if CFG.dev then
RunConsoleCommand('hostname', CFG.defaultHostName or (L.build_town .. netvars.GetNetVar('cityName', L.dobrograd)))
else
local name = netvars.GetNetVar('cityName', L.dobrograd)
if name == L.dobrograd then
RunConsoleCommand('hostname', CFG.defaultHostName or names[game.GetMap()] or names.rp_eastcoast_v4c)
else
RunConsoleCommand('hostname', L.history_town .. name)
end
end
end
timer.Simple(5, updateServerName)
local function renameCity(name)
name = name or L.dobrograd
netvars.SetNetVar('cityName', name)
octolib.notify.sendAll('ooc', L.name_town_change:format(name))
updateServerName()
end
local function cleanUpAfterMayorLeft()
if netvars.GetNetVar('cityName', L.dobrograd) ~= L.dobrograd then
renameCity()
end
if netvars.GetNetVar('lockdown') then
DarkRP.unLockdown()
end
end
hook.Add('OnPlayerChangedTeam', 'dbg-mayor.resetCity', function(ply, before)
if before ~= TEAM_MAYOR then return end
if not ply:Alive() or ply:IsGhost() then return end
cleanUpAfterMayorLeft()
end)
hook.Add('PlayerDeath', 'dbg-mayor.resetCity', function(ply)
if not ply:isMayor() then
ply:changeTeam(1, true, true)
cleanUpAfterMayorLeft()
end
end)
hook.Add('PlayerDisconnected', 'dbg-mayor.recetCity', function(ply)
if ply:isMayor() then cleanUpAfterMayorLeft() end
end)
octochat.registerCommand('/renamecity', {
cooldown = 1.5,
log = true,
execute = function(ply, name)
if not ply:GetNetVar('os_dobro') then return L.this_feature_only_dobro end
if not ply:canAfford(5000) then return L.not_enough_money2 end
if name == '' then return 'Формат: /renamecity Название' end
if utf8.len(name) > 31 then return L.title_too_long end
renameCity(name)
ply:addMoney(-5000)
end,
check = DarkRP.isMayor,
})
octochat.registerCommand('/resetcity', {
cooldown = 1.5,
log = true,
consoleFriendly = true,
execute = function(ply) renameCity() end,
check = function(ply)
return DarkRP.isMayor(ply) or ply:IsSuperAdmin(), L.can_do_only_mayor
end,
})

View file

@ -0,0 +1,121 @@
octochat.defineCommand('/advert', {
aliases = {'/ad'},
})
octochat.defineCommand('/radio', {
aliases = {'/r'},
})
octochat.defineCommand('/wradio', {
aliases = {'/wr'},
})
octochat.defineCommand('/yradio', {
aliases = {'/yr'},
})
octochat.defineCommand('/lradio', {
aliases = {'/lr'},
})
octochat.defineCommand('/callmed', true)
octochat.defineCommand('/callmech', true)
octochat.defineCommand('/callfire', true)
octochat.defineCommand('/callworker', true)
octochat.defineCommand('/givecert', true)
octochat.defineCommand('/delcert', true)
octochat.defineCommand('/ammo', true)
octochat.defineCommand('/bank', true)
octochat.defineCommand('/getbank', true)
octochat.defineCommand('/time', true)
-- rewards
octochat.defineCommand('/rewards', true)
octochat.defineCommand('/forum', true)
octochat.defineCommand('/title', true)
octochat.defineCommand('/write', true)
octochat.defineCommand('/removewrite', true)
octochat.defineCommand('/removewrites', true)
octochat.defineCommand('/dropweapon', {
aliases = {'/drop'},
})
octochat.defineCommand('/holsterweapon', {
aliases = {'/holster'},
})
local function niceTime(time)
local h, m, s
h = math.floor(time / 60 / 60)
m = math.floor(time / 60) % 60
s = math.floor(time) % 60
return string.format("%02i:%02i:%02i", h, m, s)
end
local textRules = [[<font=dbg-test.normal>Правила использования команды /advert</font>
Этот чат используется исключительно для рекламы и объявлений, стоимость публикации - 250Р
Реклама или объявления, поданные через этот чат, не могут быть анонимными, являться "слухами", содержать в себе нелегальные новости или услуги, а также любую неролевую информацию
За несоблюдение правил пользования чатом тебе может быть выдано наказание]]
netstream.Hook('octochat.advert', function(text, timeLeft)
local f = vgui.Create 'DFrame'
f:SetSize(400, 355)
f:SetTitle('Отправить рекламу')
f:Center()
f:MakePopup()
local e = octolib.textEntry(f, 'Текст сообщения')
e:SetTall(100)
e:SetDrawLanguageID(false)
e:SetContentAlignment(7)
e:SetText(text)
e:SetMultiline(true)
e:DockMargin(5,5,5,5)
e.PaintOffset = 5
local cont = f:Add 'DScrollPanel'
cont:Dock(TOP)
cont:DockMargin(0, 5, 0, 5)
cont:SetTall(150)
cont:SetPaintBackground(true)
local rules = cont:Add 'DMarkup'
rules:DockMargin(5, 5, 5, 5)
rules:Dock(TOP)
rules:SetText(textRules)
timeLeft = timeLeft or 15
local b = octolib.button(f, '...', function()
netstream.Start('octochat.advert', e:GetValue())
f:Remove()
end)
b:SetTall(27)
b:SetEnabled(false)
local function updateName()
b:SetText('Сообщение можно будет отправить через ' .. niceTime(timeLeft))
end
updateName()
timer.Create('octochat.advert.confirm', 1, 0, function()
if not IsValid(f) then return timer.Remove('octochat.advert.confirm') end
timeLeft = timeLeft - 1
if timeLeft <= 0 then
timer.Remove('octochat.advert.confirm')
b:SetEnabled(true)
b:SetText('Отправить сообщение')
else
updateName()
end
end)
end)

View file

@ -0,0 +1,534 @@
local advertPrice = 250
octochat.registerCommand('/advert', {
log = true,
phone = true,
execute = function(ply, txt)
if not ply:Alive() or ply:IsGhost() then
return L.death_cannot_do_this
end
if ply:isArrested() then
return L.you_arrested
end
if ply:IsHandcuffed() then
return L.handcuffed_cannot_do_this
end
if not ply:BankHas(advertPrice) then
return L.advert_money:format(DarkRP.formatMoney(advertPrice))
end
netstream.Start(ply, 'octochat.advert', txt, ply:GetCooldown('advert') and math.ceil(ply:GetCooldown('advert') - CurTime()) or 0)
end,
aliases = {'/ad'},
})
netstream.Hook('octochat.advert', function(ply, txt)
local nextAdvert = ply:GetCooldown('advert')
if nextAdvert then return ply:Notify('warning', 'Следующую рекламу можно будет отправить через ' .. niceTime(nextAdvert - CurTime())) end
if txt == '' then return ply:Notify('warning', 'Формат: /advert Текст сообщения') end
txt = txt:gsub('\n', ' ')
ply:BankAdd(-advertPrice)
for _, v in ipairs(player.GetAll()) do
if v:HasPhone() then
octochat.talkTo(v, octochat.textColors.rp, L.advert_hint, ply:Name(), ': ', Color(250,250,200), unpack(octolib.string.splitByUrl(txt)))
end
end
ply:TriggerCooldown('advert', 5 * 60)
end)
local function sayThroughRadio(ply, txt, distance, action, color, noTalk)
if txt == '' then return end
if not ply:Alive() or ply:IsGhost() then
return L.death_cannot_do_this
end
if ply:isArrested() then
return L.you_arrested
end
if ply:IsHandcuffed() then
return L.handcuffed_cannot_do_this
end
if not ply:HasTalkie() then
return L.you_dont_have_radio
end
if ply:IsTalkieDisabled() then
return 'Твоя рация отключена'
end
local freq = ply:GetFrequency()
if not ply:CanSpeakToChannel(freq, true) then
return 'Микрофон твоей рации сломан'
end
local sources = {ply}
for _, v in ipairs(player.GetAll()) do
if v == ply then continue end
if not v:HasTalkie() or v:IsTalkieDisabled() then continue end
local vFreq = v:GetFrequency()
if vFreq ~= freq then
if v:GetNetVar('NoTalkieParenting') then continue end
local chan = talkie.channels[vFreq]
if not chan or not chan.parent or chan.parent ~= freq then continue end
end
if v:CanListenToChannel(vFreq, true) then sources[#sources + 1] = v end
end
local heard = octolib.array.toKeys(sources)
local shouldTalk, voice, hideTalkieMessage = not noTalk and ply:GetNetVar('os_govorilka') and not ply:IsGovorilkaMuted(), ply:GetVoice(), hook.Run('dbg-talkie.hideTalkieMessage', ply)
local hearsFunc = function(v)
if v:IsPlayer() and not heard[v] then
heard[v] = true
return true
else return false end
end
for _, source in ipairs(sources) do
if source ~= ply then
source:EmitSound('npc/combine_soldier/vo/off' .. math.random(1,2) .. '.wav', 45)
end
local hears = octolib.array.filter(ents.FindInSphere(source:GetShootPos(), distance), hearsFunc)
if source ~= ply then
if not hideTalkieMessage then
octochat.talkTo(hears, color or octochat.textColors.rp, 'Кто-то', action .. ' из рации: ', color_white, txt)
end
octochat.talkTo(source, color or octochat.textColors.rp, ply:Name(), action .. ' из рации: ', color_white, txt)
else
octochat.talkTo(hears, color or octochat.textColors.rp, ply:Name(), action .. ' в рацию: ', color_white, txt)
octochat.talkTo(source, color or octochat.textColors.rp, ply:Name(), action .. ' в рацию: ', color_white, txt)
end
if shouldTalk then
hears[#hears + 1] = source
source:DoVoice(txt, voice, hears)
end
end
end
octochat.registerCommand('/radio', {
cooldown = 1.5,
log = true,
execute = function(ply, txt)
sayThroughRadio(ply, txt, CFG.radioChatDistance, ' говорит')
end,
aliases = {'/r'},
})
octochat.registerCommand('/wradio', {
cooldown = 1.5,
log = true,
execute = function(ply, txt)
sayThroughRadio(ply, txt, CFG.radioChatDistance * 0.36, ' шепчет')
end,
aliases = {'/wr'},
})
octochat.registerCommand('/yradio', {
cooldown = 1.5,
log = true,
execute = function(ply, txt)
if txt == '' then return end
if txt:sub(-1) ~= '!' then txt = txt .. '!' end
sayThroughRadio(ply, txt, CFG.radioChatDistance * 2.2, ' кричит')
end,
aliases = {'/yr'},
})
octochat.registerCommand('/lradio', {
cooldown = 1.5,
log = true,
execute = function(ply, txt)
if txt == '' then return end
sayThroughRadio(ply, txt, CFG.radioChatDistance, ' говорит', octochat.textColors.ooc, true)
end,
aliases = {'/lr'},
})
local leaveMeAloneID = 1
local function callTeam(ply, who, emote, txt, group, icon, filterFunc)
local people = octolib.array.filter(player.GetAll(), filterFunc)
if not people[1] then ply:Notify('warning', ('В городе сейчас нет %s, поэтому реагировать на вызов некому'):format(who)) return end
local msg = L.prefix_request:format(DarkRP.nextEMSRequest, ply:Name())
local marker = {
id = group .. leaveMeAloneID,
group = group,
txt = L.police_call .. DarkRP.nextEMSRequest,
pos = ply:GetPos() + Vector(0,0,40),
col = Color(235,120,120),
des = {'timedist', {600, 300}},
icon = octolib.icons.silk16(icon),
}
octolib.request.send(ply, {{
type = 'check',
name = 'Вызов ' .. who,
desc = msg .. txt,
txt = 'Отправить координаты вызова',
}}, function(data)
local sendPos = tobool(data and data[1])
ply:DoEmote(emote)
octochat.talkTo(ply, octochat.textColors.rp, msg, color_red, txt)
for _, v in ipairs(people) do
octochat.talkTo(v, octochat.textColors.rp, msg, color_red, txt)
if sendPos then v:AddMarker(marker) end
v:EmitSound('ambient/chatter/cb_radio_chatter_' .. math.random(1,3) .. '.wav', 45, 100, 0.5)
end
ply.nextEMSRequest = CurTime() + 10
leaveMeAloneID = leaveMeAloneID + 1
end)
return true
end
octochat.registerCommand('/callmed', {
cooldown = 60,
log = true,
phone = true,
execute = function(ply, txt)
callTeam(ply, 'медицинских работников', '{name} вызывает врача', txt, 'med', 'asterisk_orange', DarkRP.isMedic)
end,
})
octochat.registerCommand('/callmech', {
cooldown = 60,
log = true,
phone = true,
execute = function(ply, txt)
callTeam(ply, 'автомехаников', L.call_mech_hint, txt, 'mech', 'wrench', DarkRP.isMech)
end,
})
octochat.registerCommand('/callfire', {
cooldown = 0,
log = true,
phone = true,
execute = function(ply, txt)
callTeam(ply, 'спасателей', '{name} вызывает пожарных', txt, 'fire', 'fire', DarkRP.isFirefighter)
end,
})
octochat.registerCommand('/callworker', {
cooldown = 60,
log = true,
phone = true,
execute = function(ply, txt)
callTeam(ply, 'городских рабочих', '{name} вызывает городского рабочего', txt, 'worker', 'wrench', DarkRP.isWorker)
end,
})
octochat.registerCommand('/calltaxi', {
cooldown = 60,
log = true,
phone = true,
execute = function(ply, txt)
callTeam(ply, 'таксистов', '{name} вызывает такси', txt, 'taxi', 'car_taxi', DarkRP.isTaxist)
end,
})
octochat.registerCommand('/givecert', {
cooldown = 15,
log = true,
execute = function(ply)
local tgt = octolib.use.getTrace(ply).Entity
if not IsValid(tgt) or not tgt:IsPlayer() then tgt = ply end
local curCert, allowed = tgt:GetDBVar('cert'), ply:GetDBVar('allowedCert')
if not allowed then
return 'Ты не можешь выдавать удостоверения'
end
if curCert and curCert.id ~= allowed.id then
return 'Этот игрок уже имеет удостоверение другой организации'
end
if not allowed.title then
allowed.title = dbgCerts.certTitles[allowed.id] or 'Удостоверение'
ply:SetDBVar('allowedCert', allowed)
end
local issue, rem = os.time(), os.time() + allowed.period * 24 * 60 * 60
octolib.request.send(ply, {
{
name = 'Доп. поле',
type = 'strShort',
ph = 'Отсутствует',
default = curCert and curCert.add or 'Код ' .. math.random(100000, 999999),
}, {
name = 'Кому выдано',
type = 'strShort',
desc = '(' .. tgt:Name() .. ' в дательном падеже)',
ph = 'Не показывать',
default = curCert and curCert.em or '',
}, {
name = 'Должность',
type = 'strShort',
ph = 'Отсутствует',
default = curCert and curCert.pos or '',
}, {
name = 'Дата выдачи',
desc = os.date('%d.%m.%Y', issue),
}, {
name = 'Действ. до',
desc = os.date('%d.%m.%Y', rem),
}, {
desc = 'Пожалуйста, внимательно пересмотри ВСЕ пункты!',
},
}, function(data)
if not IsValid(tgt) then
return ply:Notify('Игрок вышел :(')
end
for i = 1, #data do
data[i] = string.Trim(data[i])
data[i] = data[i] ~= '' and data[i] or nil
end
if dbgCerts.give(tgt, allowed.id, allowed.title, data[1], data[2], data[3], issue, rem) then
ply:Notify('Выдано удостоверение:')
dbgCerts.show(tgt, ply, true, true)
dbgCerts.show(tgt, tgt, true, true)
else ply:Notify('warning', 'Не получилось выдать удостоверение') end
end)
end,
})
octochat.registerCommand('/delcert', {
cooldown = 15,
log = true,
execute = function(ply)
local tgt = octolib.use.getTrace(ply).Entity
if not IsValid(tgt) then
return L.must_be_looking_at:format('игрока')
end
local cert, allowed = tgt:GetDBVar('cert'), ply:GetDBVar('allowedCert')
if not allowed and ply:Team() ~= TEAM_ADMIN then
return 'Ты не можешь выдавать удостоверения'
end
if not cert then
return 'У этого игрока нет удостоверения'
end
if cert.vthru < os.time() or not dbgCerts.certTitles[cert.id] then
tgt:SetDBVar('cert', nil)
return 'У этого игрока нет удостоверения'
end
if cert.id ~= allowed.id and ply:Team() ~= TEAM_ADMIN then
return 'Этот игрок имеет удостоверение другой организации'
end
local sid = tgt:SteamID()
octolib.request.send(ply, {
{
name = 'Вид',
desc = dbgCerts.certTitles[cert.id],
}, {
name = 'Доп. поле',
desc = cert.add or 'Отсутствует'
}, {
name = 'Кому выдано',
desc = cert.em or 'Не указано',
}, {
name = 'Должность',
desc = cert.pos or 'Не указана',
}, {
name = 'Дата выдачи',
desc = os.date('%d.%m.%Y', cert.iss),
}, {
name = 'Действ. до',
desc = os.date('%d.%m.%Y', cert.vthru),
}, {
desc = 'Удалить удостоверение игрока?',
},
}, function()
octolib.setDBVar(sid, 'cert', nil)
ply:Notify('Удостоверение удалено')
end)
end,
})
octochat.registerCommand('/ammo', {
cooldown = 1.5,
execute = function(ply)
local wep = ply:GetActiveWeapon()
if not IsValid(wep) or wep:Clip1() == -1 then
return 'Для этого нужно держать в руках оружие'
end
ply:DoEmote('{name} проверяет магазин')
timer.Simple(1, function()
if not IsValid(wep) then return 'Для этого нужно держать в руках оружие' end
ply:Notify('Патронов в магазине: ' .. wep:Clip1())
if wep:HasAmmo() then
ply:Notify('Патронов в запасе: ' .. wep:Ammo1())
end
end)
end,
})
octochat.registerCommand('/getbank', {
cooldown = 1.5,
phone = true,
execute = function(ply)
ply:DoEmote('{name} проверяет счет в банке')
timer.Simple(1, function()
ply:Notify('Твой баланс в банке: ' .. DarkRP.formatMoney(BraxBank.PlayerMoney(ply)))
end)
end,
aliases = {'/bank'},
})
octochat.registerCommand('/time', {
cooldown = 1.5,
execute = function(ply)
ply:DoEmote(L.see_time_hint)
timer.Simple(1, function()
ply:Notify(L.the_clock_shows:format(CWI.TimeToString()))
end)
end,
})
octochat.registerCommand('/title', {
log = true,
execute = function(ply, title)
local door = ply:GetEyeTrace().Entity
if not IsValid(door) or not door:IsDoor() then
return L.must_be_looking_at:format(L.door)
end
if door:NearestPoint(ply:GetShootPos()):DistToSqr(ply:GetShootPos()) > CFG.useDistSqr then
return L.must_be_looking_at:format(L.door)
end
if door:GetPlayerOwner() ~= ply:SteamID() and not ply:IsSuperAdmin() then
return L.this_is_not_your_door
end
if title == '' then title = nil end
door:SetTitle(title)
end,
})
octochat.registerCommand('/write', {
cooldown = 10,
execute = function(ply)
if ply:GetLetterCount() >= 3 then return L.too_much_letter end
local letter = ents.Create 'letter'
letter:SetNetVar('Owner', ply)
letter:SetPos(octolib.use.getTrace(ply).HitPos)
letter.nodupe = true
letter:Spawn()
letter.SID = ply.SID
end,
})
octochat.registerCommand('/removewrite', {
cooldown = 10,
execute = function(ply)
local ent = octolib.use.getTrace(ply).Entity
if IsValid(ent) and ent:GetClass() == 'letter' and (ent:GetNetVar('Owner') == ply or ply:IsAdmin()) then
ent:Remove()
end
end,
})
octochat.registerCommand('/removewrites', {
cooldown = 10,
execute = function(ply)
for _,v in ipairs(ents.FindByClass('letter')) do
if v:GetNetVar('Owner') == ply then
v:Remove()
end
end
end,
})
octochat.registerCommand('/dropweapon', {
execute = function(ply)
local ent = ply:GetActiveWeapon()
if not IsValid(ent) or not ent:GetModel() or ent:GetModel() == '' then
return L.cannot_drop_weapon
end
if not hook.Run('canDropWeapon', ply, ent) then return L.cannot_drop_weapon end
ply:DoAnimation(ACT_GMOD_GESTURE_ITEM_DROP)
timer.Simple(0.88, function()
if not IsValid(ply) or not IsValid(ent) or not ent:GetModel() or ent:GetModel() == '' then return end
local pos, ang = ply:GetBonePosition(ply:LookupBone('ValveBiped.Bip01_L_Hand') or 16)
local vel = ply:GetAimVector()
vel.z = 0
ply:dropDRPWeapon(ent, pos, ang, vel * 200)
end)
end,
aliases = {'/drop'},
cooldown = 1,
})
octochat.registerCommand('/holsterweapon', {
execute = function(ply)
local ent = ply:GetActiveWeapon()
if not IsValid(ent) or not ent:GetModel() or ent:GetModel() == '' then
return L.cannot_drop_weapon
end
if not hook.Run('canDropWeapon', ply, ent) then return L.cannot_drop_weapon end
ply:DoAnimation(ACT_GMOD_GESTURE_ITEM_DROP)
timer.Simple(0.88, function()
if IsValid(ply) and IsValid(ent) and ent:GetModel() and ent:GetModel() ~= '' and ent:GetOwner() == ply then
ply:HolsterWeapon(ent)
end
end)
end,
aliases = {'/holster'},
cooldown = 1,
})
local function wearMask(ply, class)
local mask = ply:GetNetVar('hMask')
if mask and mask[1] ~= class then return 'Нужно снять аксессуар' end
if mask then ply:SetNetVar('hMask') return end
ply:SetNetVar('hMask', {class, unequip = true})
end
octochat.registerCommand('/gasmask', {
cooldown = 1.5,
execute = function(ply)
wearMask(ply, 'gasmask')
end,
check = function(ply)
return ply:GetActiveRank('dpd') == 'swat' or ply:GetActiveRank('wcso') == 'seb'
end,
})
octochat.registerCommand('/medmask', {
cooldown = 1.5,
execute = function(ply)
wearMask(ply, 'medical_mask')
end,
check = function(ply)
return ply:isMedic()
end,
})

View file

@ -0,0 +1,2 @@
octochat.defineCommand('/forum', true)
octochat.defineCommand('/rewards', true)

View file

@ -0,0 +1,9 @@
octochat.registerCommand('/forum', {
cooldown = 5,
execute = octolib.rewardCommands.forum,
})
octochat.registerCommand('/rewards', {
cooldown = 60,
execute = octolib.rewardCommands.rewards,
})

View file

@ -0,0 +1,84 @@
octochat.defineCommand('/ooc', {
aliases = {'//', '/a'},
cooldownBypass = 'DBG: Нет ограничения на OOC',
})
octochat.defineCommand('/looc', {
aliases = {'/'}
})
octochat.defineCommand('/pm', true)
octochat.defineCommand('/demote', true)
local function niceTime(time)
local h, m, s
h = math.floor(time / 60 / 60)
m = math.floor(time / 60) % 60
s = math.floor(time) % 60
return string.format("%02i:%02i:%02i", h, m, s)
end
local textRules = [[<font=dbg-test.normal>Правила использования OOC-чата</font>
В глобальный ООС-чат можно писать не чаще одного раза в 30 минут
Его можно использовать только для того, чтобы узнать, закончилась ли с игроком ролевая ситуация, а также статус ролевой ситуации, в которой погиб твой персонаж
Если у тебя имеется какой-либо вопрос, то попробуй обратиться к администрации через @
Когда администраторов нет в игре, ты можешь попробовать найти ответ на свой вопрос с помощью справочного материала по адресу wiki.octothorp.team; чтобы было проще найти что-то конкретное, можно использовать поиск
Нарушение правил использования ООС-чата приведет к длительному муту]]
netstream.Hook('octochat.ooc', function(text, timeLeft)
local f = vgui.Create 'DFrame'
f:SetSize(400, 355)
f:SetTitle('Отправить глобальное ООС-сообщение')
f:Center()
f:MakePopup()
local e = octolib.textEntry(f, 'Текст сообщения')
e:SetTall(100)
e:SetDrawLanguageID(false)
e:SetContentAlignment(7)
e:SetText(text)
e:SetMultiline(true)
e:DockMargin(5,5,5,5)
e.PaintOffset = 5
local cont = f:Add 'DScrollPanel'
cont:Dock(TOP)
cont:DockMargin(0, 5, 0, 5)
cont:SetTall(150)
cont:SetPaintBackground(true)
local rules = cont:Add 'DMarkup'
rules:DockMargin(5, 5, 5, 5)
rules:Dock(TOP)
rules:SetText(textRules)
timeLeft = timeLeft or 15
local b = octolib.button(f, '...', function()
netstream.Start('octochat.ooc', e:GetValue())
f:Remove()
end)
b:SetTall(27)
b:SetEnabled(false)
local function updateName()
b:SetText('Сообщение можно будет отправить через ' .. niceTime(timeLeft))
end
updateName()
timer.Create('octochat.ooc.confirm', 1, 0, function()
if not IsValid(f) then return timer.Remove('octochat.ooc.confirm') end
timeLeft = timeLeft - 1
if timeLeft <= 0 then
timer.Remove('octochat.ooc.confirm')
b:SetEnabled(true)
b:SetText('Отправить сообщение')
else
updateName()
end
end)
end)

View file

@ -0,0 +1,129 @@
local function niceTime(time)
local h, m, s
h = math.floor(time / 60 / 60)
m = math.floor(time / 60) % 60
s = math.floor(time) % 60
return string.format("%02i:%02i:%02i", h, m, s)
end
local function sendOOC(ply, txt)
txt = txt:gsub('\n', ' ')
if ply:IsAdmin() then
octochat.talkTo(nil, octochat.textColors.ooc, ('[OOC] %s (%s): '):format(ply:SteamName(), ply:Name()), color_white, unpack(octolib.string.splitByUrl(txt)))
else
octochat.talkTo(nil, octochat.textColors.ooc, ('[OOC] %s (%s): '):format(ply:SteamName(), ply:Name()), color_white, txt)
end
end
octochat.registerCommand('/ooc', {
log = true,
execute = function(ply, txt, _, cmd)
local can, why = hook.Run('PlayerCanOOC', ply, txt)
if can == false then
return why or false
end
netstream.Start(ply, 'octochat.ooc', txt, ply:GetCooldown('ooc') and math.ceil(ply:GetCooldown('ooc') - CurTime()) or 0)
end,
aliases = {'//', '/a'},
})
netstream.Hook('octochat.ooc', function(ply, txt)
local nextOOC = ply:GetCooldown('ooc')
if nextOOC then return ply:Notify('warning', 'Следующее сообщение в ООС-чат можно будет отправить через ' .. niceTime(nextOOC - CurTime())) end
if txt == '' then return ply:Notify('warning', 'Формат: ' .. cmd .. ' Текст сообщения') end
sendOOC(ply, txt)
if not ply:query('DBG: Нет ограничения на OOC') then
ply:TriggerCooldown('ooc', 30 * 60)
end
end)
octochat.registerCommand('/looc', {
cooldown = 1.5,
log = true,
cooldownBypass = 'DBG: Нет ограничения на OOC',
execute = function(ply, txt, _, cmd)
if txt == '' then return 'Формат: ' .. cmd .. ' Текст сообщения' end
if ply:IsAdmin() then
octochat.talkToRange(ply, 250, octochat.textColors.ooc, ('[LOOC] %s (%s): '):format(ply:SteamName(), ply:Name()), color_white, unpack(octolib.string.splitByUrl(txt)))
else
octochat.talkToRange(ply, 250, octochat.textColors.ooc, ('[LOOC] %s (%s): '):format(ply:SteamName(), ply:Name()), color_white, txt)
end
end,
aliases = {'/'},
})
octochat.registerCommand('/pm', {
cooldown = 3,
log = true,
cooldownBypass = 'DBG: Нет ограничения на OOC',
execute = function(ply, _, args)
local target, txt = octochat.pickOutTarget(args)
if not target then return txt or 'Формат: /pm "Имя игрока" Текст сообщения' end
if txt == '' then return 'Формат: /pm "Имя игрока" Текст сообщения' end
if ply:IsAdmin() then
octochat.talkTo(target, octochat.textColors.ooc, ('[PM] от %s (%s): '):format(ply:SteamName(), ply:Name()), Color(250,250,200), unpack(octolib.string.splitByUrl(txt)))
octochat.talkTo(ply, octochat.textColors.ooc, ('[PM] для %s (%s): '):format(target:SteamName(), target:Name()), Color(250,250,200), unpack(octolib.string.splitByUrl(txt)))
else
octochat.talkTo(target, octochat.textColors.ooc, ('[PM] от %s (%s): '):format(ply:SteamName(), ply:Name()), Color(250,250,200), txt)
octochat.talkTo(ply, octochat.textColors.ooc, ('[PM] для %s (%s): '):format(target:SteamName(), target:Name()), Color(250,250,200), txt)
end
end,
})
octochat.registerCommand('/demote', {
cooldown = 80,
execute = function(ply, _, args)
if not args[1] or args[1] == '' or not args[2] or args[2] == '' then
return 'Формат: /demote "Ник игрока" Причина увольнения'
end
local target, reason = octochat.pickOutTarget(args)
if not IsValid(target) then return reason or 'Такой игрок не найден' end
if target == ply then return L.cant_demote_self end
if utf8.len(reason) > 100 then return L.unable:format('указать такую причину', 'Она должна быть покороче') end
local canDemote, message = hook.Run('canDemote', ply, target, reason)
if canDemote == false then return message or L.unable:format('уволить этого игрока', '') end
if target:getJobTable().candemote == false then return L.unable:format('уволить этого игрока', '') end
local recipients = octolib.array.filter(player.GetAll(), function(v) return v ~= p and v ~= ply end)
target.IsBeingDemoted = octolib.questions.start({
text = L.demote_vote_text:format(ply:Name(), target:Name(), reason),
recipients = recipients,
spectators = {ply, target},
time = 20,
onFinish = function(result)
if not IsValid(target) then return end
target.IsBeingDemoted = nil
if result > 0 then
if target:Alive() then
target:changeTeam(GAMEMODE.DefaultTeam, true)
if target:isArrested() then
target:arrest()
end
else
target.demotedWhileDead = true
end
hook.Run('onPlayerDemoted', ply, target, reason)
octolib.notify.sendAll(L.demoted:format(target:Nick()))
else
octolib.notify.sendAll('warning', L.demoted_not:format(target:Nick()))
end
end,
})
octolib.notify.sendAll(L.demote_vote_started:format(ply:Nick(), target:Nick()))
end,
})

View file

@ -0,0 +1,11 @@
local copData = {check = DarkRP.isCop}
octochat.defineCommand('/callhelp', copData)
octochat.defineCommand('/panicbutton', copData)
octochat.defineCommand('/warrant', copData)
octochat.defineCommand('/wanted', copData)
octochat.defineCommand('/unwanted', copData)
octochat.defineCommand('/givelicense', copData)
octochat.defineCommand('/takelicense', copData)
octochat.defineCommand('/carcheck', copData)
octochat.defineCommand('/cr', true)

View file

@ -0,0 +1,238 @@
local leaveMeAloneID = 0
octochat.registerCommand('/callhelp', {
cooldown = 60,
log = true,
execute = function(ply, txt)
if txt == '' then return 'Формат: /callhelp Текст сообщения' end
ply:DoEmote('{name} запрашивает подкрепление')
local marker = {
id = 'cpSupport' .. leaveMeAloneID,
group = 'cpSupport',
txt = 'Подкрепление',
pos = ply:GetPos() + Vector(0,0,40),
col = Color(102,170,170),
des = {'timedist', { 600, 300 }},
icon = 'octoteam/icons-16/exclamation.png',
}
for _,v in ipairs(player.GetAll()) do
if v:isEMS() then
octochat.talkTo(v, octochat.textColors.rp, '[Подкрепление] ', ply:Name(), ': ', color_red, txt)
v:EmitSound('ambient/chatter/cb_radio_chatter_' .. math.random(1,3) .. '.wav', 45, 100, 0.5)
v:AddMarker(marker)
end
end
leaveMeAloneID = leaveMeAloneID + 1
end,
check = DarkRP.isCop,
})
octochat.registerCommand('/cr', {
cooldown = 30,
phone = true,
execute = function(ply, txt)
if txt == '' then return 'Формат: /cr Текст вызова' end
local ph = ply:AtStationaryPhone()
DarkRP.callEMS(ply, ph and ph:GetNick() or ply:Name(), txt)
end,
})
octochat.registerCommand('/warrant', {
execute = function(ply, _, args)
local target, txt = octochat.pickOutTarget(args)
if not IsValid(target) then return txt or 'Такой игрок не найден' end
if utf8.len(txt) < 10 then return 'Укажи причину обыска' end
if target.warranted then return L.already_a_warrant end
local can, message = hook.Run('canRequestWarrant', target, ply, txt)
if can == false then return message or 'Ты не можешь получить ордер на обыск этого игрока' end
if not ply:getJobTable().mayor then -- No need to search through all the teams if the player is a mayor
local mayors = {}
for _,v in ipairs(player.GetAll()) do
if v:getJobTable().mayor then
mayors[#mayors + 1] = v
end
end
if mayors[1] then
octolib.questions.start({
text = L.warrant_request:format(ply:Nick(), target:Nick(), txt),
recipients = mayors,
left = 'Одобрить',
right = 'Отклонить',
sound = 'Town.d1_town_02_elevbell1',
time = 40,
onFinish = function(res)
if res <= 0 then
ply:Notify('warning', L.warrant_denied)
elseif IsValid(target) then
target:warrant(txt)
end
end,
})
end
else target:warrant(reason) end
end,
check = DarkRP.isCop,
})
octochat.registerCommand('/wanted', {
execute = function(ply, _, args)
local target, txt = octochat.pickOutTarget(args)
if not IsValid(target) then return txt or 'Такой игрок не найден' end
if utf8.len(txt) < 10 then return 'Укажи причину подачи в розыск' end
if target:isWanted() then return L.already_wanted end
if not target:Alive() or target:IsGhost() then return L.suspect_must_be_alive_to_do_x:format(L.make_someone_wanted) end
if target:isArrested() then return L.suspect_already_arrested end
local can, message = hook.Run('canWanted', target, ply, txt)
if can == false then return message or 'Ты не можешь подать в розыск на этого игрока' end
target:wanted(ply, txt)
end,
check = DarkRP.isCop,
})
octochat.registerCommand('/unwanted', {
execute = function(ply, _, args)
if not args[1] or args[1] == '' then return 'Ты не указал имя игрока!\nФормат: /unwanted "Ник игрока" "Причина"' end
if not args[2] or args[2] == '' then return 'Ты не указал причину!\nФормат: /unwanted "Ник игрока" "Причина"' end
local target, txt = octochat.pickOutTarget(args)
if not IsValid(target) then return txt or 'Такой игрок не найден' end
if not target:isWanted() then return L.not_wanted end
local can, message = hook.Run('canUnwanted', target, ply)
if can == false then return message or 'Ты не можешь отозвать розыск на этого игрока' end
target:unWanted(ply, table.concat(args, ' ', 2))
end,
check = DarkRP.isCop,
})
local function isInCharge(msg)
return function(ply)
local mayor, chief, serg, cop
for _,v in ipairs(player.GetAll()) do
if v:isMayor() or v:GetActiveRank('gov') == 'worker' then
mayor = true
break
elseif v:isChief() then
chief = true
elseif v:getJobTable().command == 'cop2' then
serg = true
elseif v:isCP() then cop = true end
end
if mayor then
if not (ply:isMayor() or ply:GetActiveRank('gov') == 'worker') then return false, 'Сейчас ' .. msg .. ' может мэр' end
elseif chief then
if not ply:isChief() then return false, 'Сейчас ' .. msg .. ' может лейтенант полиции' end
elseif serg then
if ply:getJobTable().command ~= 'cop2' then return false, 'Сейчас ' .. msg .. ' может сержант полиции' end
elseif cop then
if not ply:isCP() then return false, 'Сейчас ' .. msg .. ' может сотрудник полиции' end
elseif not ply:IsAdmin() then
return false, 'Сейчас ' .. msg .. ' может только администратор'
end
return true
end
end
octochat.registerCommand('/givelicense', {
execute = function(ply, txt)
local target = octolib.use.getTrace(ply).Entity
if not IsValid(target) or not target:IsPlayer() then
return L.must_be_looking_at:format('игрока')
end
target:Notify(L.gunlicense_granted:format(ply:Name(), target:Name()))
ply:Notify(L.gunlicense_granted:format(ply:Name(), target:Name()))
target:SetNetVar('HasGunlicense', txt or '')
hook.Run('DarkRPGiveLicence', ply, target, txt or '')
end,
check = isInCharge('выдавать лицензии'),
})
octochat.registerCommand('/takelicense', {
cooldown = 1.5,
execute = function(ply)
local target = octolib.use.getTrace(ply).Entity
if not IsValid(target) or not target:IsPlayer() then
return L.must_be_looking_at:format('игрока')
end
target:Notify(L.gunlicense_taken:format(ply:Name(), target:Name()))
ply:Notify(L.gunlicense_taken:format(ply:Name(), target:Name()))
target:SetNetVar('HasGunlicense')
hook.Run('DarkRPTakeLicence', ply, target)
end,
check = isInCharge('отзывать лицензии'),
})
octochat.registerCommand('/carcheck', {
cooldown = 1.5,
execute = function(ply)
octolib.request.send(ply, {{
type = 'strShort',
name = 'Номер автомобиля',
desc = '6 или 7 символов. Только латинские буквы и цифры, без пробелов и дефисов',
ph = carDealer.randomPlate(carDealer.plateLength),
required = true,
}}, function(data)
local plate = data[1]
if not isstring(plate) then return end
if string.gsub(plate, '^[0-9a-zA-Z]+$', '') ~= '' then
ply:Notify('warning', 'Только латинские буквы и цифры')
return
end
if #plate < 6 or #plate > 7 then
ply:Notify('warning', '6 или 7 символов')
return
end
ply:DoEmote(L.emote_check)
ply:DelayedAction('car_check', L.check_action, {
time = 10,
check = function() return IsValid(ply) and ply:isCP() end,
succ = function()
carDealer.getVehByPlate(plate, function(veh)
if not IsValid(ply) then return end
if not veh then
return ply:Notify('Совпадений в базе не обнаружено')
end
if not octolib.string.isSteamID(veh.garage) then
return ply:Notify('ooc', 'Эта машина не принадлежит игроку (скажи разработчикам)')
end
local msg = 'Владелец автомобиля с номером ' .. string.upper(plate) .. ': '
octolib.getDBVar(veh.garage, 'lastRPName'):Then(function(var)
if not IsValid(ply) then return end
ply:Notify(msg .. var) -- to be tested
end)
end)
end,
})
end)
end,
check = DarkRP.isCop,
})

View file

@ -0,0 +1,4 @@
octochat.defineCommand('!radio', {
aliases = {'~radio', '/radio'},
check = DarkRP.isSuperAdmin,
})

View file

@ -0,0 +1,164 @@
local stationIdSymbols = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
local function id(station)
return station.id
end
local function escape(str)
return octolib.db:escape(str)
end
octochat.registerCommand('!radio', {
aliases = {'~radio', '/radio'},
check = DarkRP.isSuperAdmin,
log = true,
execute = function(ply)
if ply.radioCollecting then return 'Команда еще в работе' end
ply.radioCollecting = true
octolib.func.chain({
function(nxt)
local response, offset, first = {}, 0, true
octolib.func.loop(function(again, stations)
if not IsValid(ply) then return end
if istable(stations) then
for _, v in ipairs(stations) do
response[#response + 1] = v
end
offset = offset + #stations
if #stations < 25 then return nxt(response) end
elseif not first then
return nxt(response)
end
first = false
octoradio.getByPlace('Dobrograd MI', 'United States', offset, again)
end)
end,
function(nxt, stations)
local response, page = {}, 1
octolib.func.loop(function(again, ans)
if not IsValid(ply) then return end
if ans then
if not istable(ans) then return nxt(response) end
for _, v in ipairs(ans) do
response[#response + 1] = v
end
if #ans < 25 then return nxt(response) end
end
octoradio.getById(octolib.table.mapSequential(octolib.array.page(stations, 25, page), id), again)
end)
end,
function(nxt, stations)
ply.radioCollecting = nil
for _, v in ipairs(stations) do
v.placeId, v.placeName, v.country = nil
v.id = v.id:sub(3)
end
octolib.entries.gui(ply, 'Радиостанции', {
fields = {
id = {
name = 'Идентификатор',
desc = '6 латинских символов и цифр. Должен быть уникальным',
type = 'strShort',
len = 6,
required = true,
},
title = {
name = 'Название',
type = 'strShort',
len = 50,
required = true,
},
playbackUrl = {
name = 'Ссылка',
desc = 'Прямая ссылка на онлайн-стрим. Если сомневаешься, обратись к разработчикам',
type = 'strShort',
len = 255,
required = true,
},
},
labelIndex = 'title',
entries = stations,
maxEntries = 1000,
}, function(res)
if not istable(res) then return end
local stations = {}
local ids = {}
for i, v in ipairs(res) do
local title = v.title
if not (title and octolib.math.inRange(utf8.len(title), 4, 50)) then
ply:Notify('warning', ('Запись #%i: неправильное название (%s)'):format(i, tostring(title)))
return
end
local id = v.id
if not (id and utf8.len(id) == 6) then
ply:Notify('warning', ('Запись #%i (%s): длина идентификатора не равна 6'):format(i, tostring(title)))
return
end
if id:find('[^' .. stationIdSymbols .. ']') then
ply:Notify('warning', ('Запись #%i: (%s): в идентификаторе есть неподходящие символы'):format(i, tostring(title)))
return
end
if ids[id] then
ply:Notify('warning', ('Запись #%i: (%s): идентификатор уже использовался в записи #%i (%s)')
:format(i, tostring(title), ids[i][1], tostring(ids[i][2]))
)
return
end
ids[id] = { #stations, name }
local playbackUrl = v.playbackUrl
if not (playbackUrl and playbackUrl:len() <= 255 and octolib.string.isUrl(playbackUrl)) then
ply:Notify('warning', ('Запись #%i: (%s): неверная ссылка'):format(i, tostring(title)))
end
stations[#stations + 1] = ('(\'%s\',\'%s\',\'%s\',\'%s\',\'%s\',\'%s\')'):format(unpack(octolib.table.mapSequential({
'##' .. id, title, '########', 'Dobrograd MI', 'United States', playbackUrl
}, escape)))
end
nxt(stations)
end)
end,
function(nxt, q)
octolib.db:RunQuery([[DELETE FROM `dbg_radio` WHERE `id` LIKE '##%']], function()
nxt(q)
end)
end,
function(nxt, q)
local qSize = #q
local iMax = math.ceil(qSize / 10)
for i = 1, iMax do
local values = table.concat(q, ',', (i-1) * 10 + 1, math.min(i * 10, qSize))
local query = [[REPLACE INTO `dbg_radio` (`id`, `title`, `placeId`, `placeName`, `country`, `playbackUrl`) VALUES ]] .. values
if i == iMax then
octolib.db:RunQuery(query, nxt)
else
octolib.db:RunQuery(query)
end
end
end,
function()
hook.Run('octoradio.updated')
if IsValid(ply) then
ply:Notify('hint', 'Радиостанции сохранены')
end
end,
})
end,
})

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,559 @@
local function run()
if not GAMEMODE then return end
hook.Add('Think', 'dbg-score', function()
if not IsValid(LocalPlayer()) then return end
if IsValid(dbgScore) then dbgScore:Remove() end
local maxH = ScrH() - 80
local p = vgui.Create 'DFrame'
dbgScore = p
local icons = {}
local function updateIcons()
for rank, data in pairs(serverguard.ranks.stored) do
icons[rank] = Material(data.texture)
end
end
hook.Add('PlayerIsLoaded', 'dbg-score', updateIcons)
local function convert_rank_to_img(ply)
local icon = icons[ply:GetUserGroup()]
if not icon then
updateIcons()
return convert_rank_to_img(ply)
end
return icon
end
local function niceMinutes(num)
local word = L.minutes_hint
if num < 5 or (num % 100) > 20 then
local lastDigit = num % 10
if lastDigit == 1 then
word = word .. 'у'
elseif lastDigit > 1 and lastDigit < 5 then
word = word .. 'ы'
end
end
return num .. word
end
local function canSeeHisJob(ply)
local lp = LocalPlayer()
if ply == lp then return true end
local job = ply:getJobTable()
local myJob = lp:getJobTable()
if myJob.admin ~= 0 then return true end
if job.command == 'fbi' and myJob.command ~= 'fbi' then return false end
if myJob.police ~= job.police then return false end
if not myJob.police then return false end
return true
end
local function canSeeHisLicense(ply)
local lp, license = LocalPlayer(), ply:GetNetVar('HasGunlicense')
if not license then return false end
if ply == lp then return true end
local myJob = lp:getJobTable()
if myJob.admin ~= 0 then return true end
if myJob.seesLicense then return true end
if myJob.police then return true end
return false
end
surface.CreateFont('dbg-score.large', {
font = 'Calibri',
extended = true,
size = 27,
weight = 350,
})
surface.CreateFont('dbg-score.normal', {
font = 'Calibri',
extended = true,
size = 22,
weight = 350,
})
surface.CreateFont('dbg-score.small', {
font = 'Calibri',
extended = true,
size = 18,
weight = 350,
})
p:SetSize(800, 600)
p:Center()
p:MakePopup()
p:SetMouseInputEnabled(true)
p:SetKeyboardInputEnabled(false)
p:SetTitle('')
p:DockPadding(0,0,0,0)
p:ShowCloseButton(false)
p.canvas = vgui.Create 'DScrollPanel'
p.canvas:SetParent(p)
p.canvas:Dock(FILL)
p.canvas:SetPaintBackground(false)
p.canvas.VBar.btnUp.Paint = function() end
p.canvas.VBar.btnDown.Paint = function() end
p.canvas.VBar.Paint = function(self, w, h)
draw.RoundedBox(4, w/2 - 3, 18, 6, h - 36, Color(43,34,43, 180))
end
p.canvas.VBar.btnGrip.Paint = function(self, w, h)
local col = (self.Hovered or self.Depressed) and Color(238,238,238, 255) or Color(238,238,238, 100)
draw.RoundedBox(4, w/2 - 4, 0, 8, h, col)
end
p.al = 0
p.playerNum = 0
local function ease( t, b, c, d )
t = t / d;
return -c * t * (t - 2) + b
end
local function paintTag(self, w, h)
surface.SetDrawColor(255,255,255, 255)
surface.SetMaterial(self.icon)
surface.DrawTexturedRect(4, 4, 16, 16)
end
local vipMat = Material(octolib.icons.silk16('heart'))
local function paintButton(self, w, h)
local al = self.anim
local ply = self.ply
local col = Color(43,34,43, 180 + al * 70)
draw.RoundedBox(4, 0, 0, w, h, col)
surface.SetDrawColor(255,255,255, 255)
surface.SetMaterial(convert_rank_to_img(ply))
surface.DrawTexturedRect(12, 12, 16, 16)
-- draw.SimpleText(team.GetName(ply:Team()), 'dbg-score.normal', w - 10, h/2 - 1, Color(238,238,238), TEXT_ALIGN_RIGHT, TEXT_ALIGN_CENTER)
draw.SimpleText(ply:Name(), 'dbg-score.large', 38, h/2 - 1, Color(238,238,238), TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER)
if al > 0 then
al = ease(al, 0, 1, 1)
local tw, th = surface.GetTextSize(ply:Name())
local x, y = math.floor(28 + tw + al * 20), h/2
if ply:GetNetVar('os_dobro') then
surface.SetDrawColor(255,255,255, al*150)
surface.SetMaterial(vipMat)
surface.DrawTexturedRect(x, y-7, 16, 16)
x = x + 20
end
draw.SimpleText(ply:SteamName(), 'dbg-score.small', x, y, Color(238,238,238, al * 150), TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER)
end
end
local function thinkButton(self)
if not IsValid(self.ply) then return self:Remove() end
local steamID = self.ply:SteamID()
if self.Hovered or self:IsChildHovered(true) then
self.anim = math.Approach( self.anim, 1, FrameTime() / 0.1 )
else
self.anim = math.Approach( self.anim, 0, FrameTime() / 0.2 )
end
-- job
local name, icon, overridden
local job = self.ply:getJobTable()
if job.displayAs and not canSeeHisJob(self.ply) then
job = DarkRP.getJobByCommand(job.displayAs)
overridden = true
end
if job then name, icon = job.name, octolib.icons.silk16(job.icon or 'error') end
if not overridden then
local customJob = self.ply:GetNetVar('customJob')
if customJob then name, icon = unpack(customJob) end
end
if self.j and (self.j.hint ~= name or self.j.iconPath ~= icon) then
self.j.hint = name
self.j.icon = Material(icon)
self.j.iconPath = icon
end
-- friend
if self.fs then
if FPP.Buddies[steamID] == nil then
self.fs[2]:Remove()
self.fs = nil
end
elseif FPP.Buddies[steamID] ~= nil then
local fs = vgui.Create 'DPanel'
fs:SetParent(self)
fs:Dock(RIGHT)
fs:SetWide(24)
fs:SetCursor('hand')
fs.icon = Material(octolib.icons.silk16('personals'))
fs.Paint = paintTag
fs:AddHint(L.your_friend)
fs.DoClick = function(fs)
self:DoClick()
end
self.fs = {true, fs}
end
-- afk
local isAFK = self.ply:IsAFK()
if self.afk then
if not isAFK then
self.afk[2]:Remove()
self.afk = nil
end
elseif isAFK then
local afk = vgui.Create 'DPanel'
afk:SetParent(self)
afk:Dock(RIGHT)
afk:SetWide(24)
afk:SetCursor('hand')
afk.icon = Material(octolib.icons.silk16('time'))
afk.Paint = paintTag
afk:AddHint(function() return 'AFK: ' .. niceMinutes(math.floor(self.ply:GetAFKTime() / 60)) end)
afk.DoClick = function(afk)
self:DoClick()
end
self.afk = {true, afk}
end
-- gun license
local license = self.ply:GetNetVar('HasGunlicense')
if self.gl then
if not license or not canSeeHisLicense(self.ply) then
self.gl[2]:Remove()
self.gl = nil
end
elseif canSeeHisLicense(self.ply) then
local gl = vgui.Create 'DPanel'
gl:SetParent(self)
gl:Dock(RIGHT)
gl:SetWide(24)
gl:SetCursor('hand')
gl.icon = Material(octolib.icons.silk16('page_white_text'))
gl.Paint = paintTag
gl:AddHint(function() local l = self.ply:GetNetVar('HasGunlicense') return (isstring(l) and string.Trim(l) ~= '') and L.license_hint2 .. l or L.have_license end)
gl.DoClick = function(gl)
self:DoClick()
end
self.gl = {true, gl}
end
-- police
local isPolice = self.ply:GetNetVar('dbg-police.job', '') ~= '' and canSeeHisJob(self.ply)
if self.pj then
if not isPolice then
self.pj[2]:Remove()
self.pj = nil
end
elseif isPolice then
local pj = vgui.Create 'DPanel'
pj:SetParent(self)
pj:Dock(RIGHT)
pj:SetWide(24)
pj:SetCursor('hand')
pj.icon = Material(octolib.icons.silk16('baton'))
pj.Paint = paintTag
pj:AddHint(L.working_in_police)
pj.DoClick = function(pj)
self:DoClick()
end
self.pj = {true, pj}
end
-- wanted
if self.w then
if not self.ply:GetNetVar('wanted') then
self.w[2]:Remove()
self.w = nil
end
elseif self.ply:GetNetVar('wanted') then
local w = vgui.Create 'DPanel'
w:SetParent(self)
w:Dock(RIGHT)
w:SetWide(24)
w:SetCursor('hand')
w.icon = Material(octolib.icons.silk16('exclamation'))
w.Paint = paintTag
local reason = self.ply:GetNetVar('wanted')
w:AddHint(L.wanted_hint:format(reason))
w.DoClick = function(w)
self:DoClick()
end
self.w = {true, w}
end
end
p.Paint = function(self, w, h)
if h == maxH then
local drawUpper = self.canvas.VBar:GetScroll() ~= 0
local drawLower = self.canvas.VBar:GetScroll() ~= self.canvas.VBar.CanvasSize
surface.DisableClipping(true)
surface.SetDrawColor(0,0,0, 100)
if drawUpper then surface.DrawLine(-5, -1, w - 11, -1) end
if drawLower then surface.DrawLine(-5, h, w - 11, h) end
surface.DisableClipping(false)
end
end
p.UpdatePlayerList = function(self)
self.canvas:Clear()
local plys = player.GetAll()
table.sort(plys, function(a, b)
return a:Name() < b:Name()
end)
for i, ply in ipairs(plys) do
if hook.Run('dbg-score.hidePlayer', ply) == true then continue end
local b = vgui.Create 'DButton'
b:SetParent(self.canvas)
b:Dock(TOP)
b:DockMargin(0,0,0,5)
b:DockPadding(8,8,8,8)
b:SetText('')
b:SetTall(40)
b.ply = ply
b.anim = 0
b.Paint = paintButton
b.Think = thinkButton
b.DoClick = function(self)
local steamID = ply:SteamID()
local menu = DermaMenu()
if ply ~= LocalPlayer() then
local types = {'physgun','gravgun','toolgun','playeruse','entitydamage'}
if FPP.Buddies[steamID] ~= nil then
menu:AddOption(L.remove_friend, function()
for k, acessType in pairs( types ) do
FPP.SaveBuddy(steamID, ply:Name(), acessType, 0)
end
end):SetIcon(octolib.icons.silk16('heart_delete'))
else
menu:AddOption(L.add_friend, function()
for k, acessType in pairs( types ) do
FPP.SaveBuddy(steamID, ply:Name(), acessType, 1)
end
end):SetIcon(octolib.icons.silk16('heart'))
end
end
menu:AddSpacer()
hook.Run('dbg-admin.getActions', menu, ply, 'score')
menu:Open()
end
local r = vgui.Create 'DPanel'
r:SetParent(b)
r:Dock(LEFT)
r:SetWide(24)
r:SetCursor('hand')
r.icon = convert_rank_to_img(ply)
r.Paint = paintTag
r:AddHint(serverguard.ranks.stored[ply:GetUserGroup()].name)
r.DoClick = function()
b:DoClick()
end
local job = ply:getJobTable()
if job.displayAs and not canSeeHisJob(ply) then
job = DarkRP.getJobByCommand(job.displayAs)
end
local j = vgui.Create 'DPanel'
j:SetParent(b)
j:Dock(RIGHT)
j:SetWide(24)
j:SetCursor('hand')
j.icon = Material(octolib.icons.silk16(job and job.icon or 'error'))
j.Paint = paintTag
j:AddHint(function()
return j.hint
end)
j.DoClick = function()
b:DoClick()
end
b.j = j
end
self:SetTall(math.min(player.GetCount() * 45 - 5, maxH))
self:Center()
end
p.PerformLayout = function() end
p.Think = function( self )
if self.playerNum ~= player.GetCount() then
self:UpdatePlayerList()
self.playerNum = player.GetCount()
end
self.al = math.Approach( self.al, self.active and 1 or 0, FrameTime() / 0.3 )
self:SetAlpha(self.al * 255)
if self:IsVisible() and self.al == 0 then
self:SetVisible(false)
end
if LocalPlayer():IsAdmin() and not IsValid(self.adminBut1) then
local b1 = vgui.Create 'DButton'
b1:SetText('')
b1:SetSize(24,24)
b1:SetPos(ScrW() / 2 - 40, ScrH() - 32)
b1.icon = Material(octolib.icons.silk16('shield'))
b1.Paint = paintTag
b1.Think = function(self2)
self2:SetAlpha(self.al * 255)
end
b1:AddHint(L.admin_mode)
function b1:DoClick()
RunConsoleCommand('dbg_admin')
end
local b2 = vgui.Create 'DButton'
b2:SetText('')
b2:SetSize(24,24)
b2:SetPos(ScrW() / 2 - 12, ScrH() - 32)
b2.icon = Material(octolib.icons.silk16('gear_in'))
b2.Paint = paintTag
b2.Think = function(self2)
self2:SetAlpha(self.al * 255)
end
b2:AddHint(L.admin_menu)
function b2:DoClick()
RunConsoleCommand('serverguard_menu_toggle')
end
local b3 = vgui.Create 'DButton'
b3:SetText('')
b3:SetSize(24,24)
b3:SetPos(ScrW() / 2 + 16, ScrH() - 32)
b3.icon = Material(octolib.icons.silk16('page_white_magnify'))
b3.Paint = paintTag
b3.Think = function(self2)
self2:SetAlpha(self.al * 255)
end
b3:AddHint(L.hud_logs)
function b3:DoClick()
octoesc.OpenURL('https://octothorp.team/logs')
end
self.adminBut1 = b1
self.adminBut2 = b2
self.adminBut3 = b3
self.OnRemove = function()
b1:Remove()
b2:Remove()
b3:Remove()
end
end
end
netstream.Hook('dbg-score.update', function()
p.playerNum = -1
end)
function GAMEMODE:ScoreboardShow()
p.active = true
p.holding = true
p:SetMouseInputEnabled(true)
p:SetVisible(true)
end
function GAMEMODE:ScoreboardHide()
if not p.active then return end
p.active = false
p.holding = false
p:SetMouseInputEnabled(false)
end
local blur = Material( 'pp/blurscreen' )
local colors = CFG.skinColors
hook.Add( 'RenderScreenspaceEffects', 'dbg-scoreboard', function()
local state = p.al
local a = 1 - math.pow( 1 - state, 2 )
if a > 0 then
local colMod = {
['$pp_colour_addr'] = 0,
['$pp_colour_addg'] = 0,
['$pp_colour_addb'] = 0,
['$pp_colour_mulr'] = 0,
['$pp_colour_mulg'] = 0,
['$pp_colour_mulb'] = 0,
['$pp_colour_brightness'] = -a * 0.2,
['$pp_colour_contrast'] = 1 + 0.5 * a,
['$pp_colour_colour'] = 1 - a,
}
if GetConVar('octolib_blur'):GetBool() then
DrawColorModify(colMod)
surface.SetDrawColor( 255, 255, 255, a * 255 )
surface.SetMaterial( blur )
for i = 1, 3 do
blur:SetFloat( '$blur', a * i * 2 )
blur:Recompute()
render.UpdateScreenEffectTexture()
surface.DrawTexturedRect( -1, -1, ScrW() + 2, ScrH() + 2 )
end
else
colMod['$pp_colour_brightness'] = -0.4 * a
colMod['$pp_colour_contrast'] = 1 + 0.2 * a
DrawColorModify(colMod)
end
draw.NoTexture()
local col = colors.bg
surface.SetDrawColor(col.r, col.g, col.b, a * 100)
surface.DrawRect(-1, -1, ScrW() + 1, ScrH() + 1)
end
end)
hook.Remove('Think', 'dbg-score')
end)
end
hook.Add('darkrp.loadModules', 'dbg-score', run)
run()

View file

@ -0,0 +1,87 @@
octoinv.registerCollector('pickaxe', {
name = 'Кирка',
icon = octolib.icons.color('crowbar'),
hold = 'melee2',
interval = 1.5,
delay = 0.15,
power = 10,
health = 500,
sounds = {
{'physics/concrete/concrete_impact_hard1.wav', 75},
{'physics/concrete/concrete_impact_hard2.wav', 75},
{'physics/concrete/concrete_impact_hard3.wav', 75},
},
worldModel = {
model = 'models/weapons/hl2meleepack/w_pickaxe.mdl',
pos = Vector(-1.9, -0.6, -0.7),
ang = Angle(168.6, -100.5, -4),
scale = 0.8
},
})
octoinv.registerCollectable('stone', {
name = 'Камень',
collectors = {'pickaxe'},
period = {10, 90},
max = 25,
health = 50,
effects = {
hit = 'StunstickImpact',
hitSounds = {'Rock.ImpactSoft'},
collect = 'GlassImpact',
collectSounds = {'Boulder.ImpactHard'},
},
models = {
'models/props_lab/bigrock.mdl',
'models/props_wasteland/rockgranite02a.mdl',
'models/props_wasteland/rockgranite02b.mdl',
'models/props_wasteland/rockgranite02c.mdl',
'models/props_wasteland/rockgranite03b.mdl',
'models/props_wasteland/rockgranite03c.mdl',
'models/props/cs_militia/militiarock05.mdl',
},
dropsAmount = 3,
drops = {
{1, {'stone', 1}},
{0.1, {'craft_coal', 1}},
{0.14, {'ore_iron', 1}},
{0.14, {'ore_steel', 1}},
-- {0.05, {'ore_copper', 1}},
-- {0.04, {'ore_bronze', 1}},
{0.03, {'ore_gold', 1}},
{0.01, {'ore_silver', 1}},
{0.0015, {'jewelry_diamond', 1}},
{0.0015, {'jewelry_ruby', 1}},
{0.0015, {'jewelry_sapphire', 1}},
{0.0015, {'jewelry_topaz', 1}},
{0.0015, {'jewelry_emerald', 1}},
},
})
octoinv.registerCraft('collector_pickaxe', {
name = 'Кирка',
icon = octolib.icons.color('crowbar'),
conts = {'workbench'},
soundTime = 2,
time = 30,
tools = {
{'tool_saw', 1},
{'tool_hammer', 1},
{'tool_screwer', 1},
},
ings = {
{'craft_stick', 2},
{'ingot_iron', 5},
{'craft_nail', 2},
{'craft_screw', 4},
},
finish = {
{'collector', {
name = 'Кирка',
icon = octolib.icons.color('crowbar'),
collector = 'pickaxe',
maxhealth = 500,
health = 500,
}},
},
})

View file

@ -0,0 +1,28 @@
octoinv.registerCraft('id', { -- Уникальный ID крафта.
name = '', -- Не уникальное имя крафта.
desc = '', -- Описание крафта ( Опционально ).
icon = '', -- Установка иконки. ( Опционально. )
time = '', -- Время для проведения крафта. ( Опционально. )
sound = '', -- string звука при крафтинге.
soundTime = 1, -- через сколько секнуд проигрывать звуки
conts = {'',''}, -- Контейнер, в котором крафтится предмет.
jobs = {'job','job'}, -- Работы, которым доступен крафт
tools = { -- Проверка чего-либо у игрока. ( Опционально, от предметов в инвентаре до функции с результатом. )
{'item', amount} or
function(ply)
return result, 'error message'
end
},
ings = { -- Рецепт создания чего-либо.
{'item', amount},
{'item', amount}
},
finish = { -- Что будет по выполнению крафта ( Опционально, предметы в инвентарь, либо функция.)
{'item', amount} or
function(ply)
return result
end
},
})

View file

@ -0,0 +1,330 @@
------------------------------------------------
--
-- BENCHES
--
------------------------------------------------
local drillSounds = {
'ambient/machines/pneumatic_drill_1.wav',
'ambient/machines/pneumatic_drill_2.wav',
'ambient/machines/pneumatic_drill_4.wav',
}
octoinv.registerCraft('bpd_stove', {
name = L.stove,
desc = L.desc_bpd_stove,
icon = 'octoteam/icons/box3.png',
conts = {'_hand'},
sound = drillSounds,
soundTime = 2,
time = 30,
tools = {
{'tool_screwer', 1},
{'tool_wrench', 1},
{'tool_solder', 1},
{'tool_drill', 1},
},
ings = {
{'craft_cable', 4},
{'craft_bulb', 4},
{'craft_sheet', 2},
{'craft_plug', 1},
{'craft_gauge', 1},
{'craft_relay', 2},
{'craft_transistor', 4},
{'craft_resistor', 2},
},
finish = {
{'bpd_stove', 1},
},
}) octoinv.registerCraft('cont_stove', {
name = L.stove,
desc = L.desc_cont_stove,
icon = 'octoteam/icons/stove.png',
previewModel = 'models/props_c17/furniturestove001a.mdl',
conts = {'_hand'},
sound = drillSounds,
soundTime = 2,
time = 30,
tools = {
{'tool_craft', 1},
},
ings = {
{'bp_stove', 1},
{'bpd_stove', 1},
{'craft_battery', 1},
},
finish = octoinv.spawnProd({
mdl = 'models/props_c17/furniturestove001a.mdl',
conts = {
stove = { name = L.stove, volume = 40, icon = octolib.icons.color('stove'), craft = true, prod = true },
oven = { name = L.oven, volume = 60, icon = octolib.icons.color('stove'), craft = true },
},
prod = 'stove',
}),
})
octoinv.registerCraft('bpd_fridge', {
name = L.fridge,
desc = L.desc_bpd_fridge,
icon = 'octoteam/icons/box3.png',
conts = {'_hand'},
sound = drillSounds,
soundTime = 2,
time = 30,
tools = {
{'tool_screwer', 1},
{'tool_drill', 1},
{'tool_solder', 1},
},
ings = {
{'craft_cable', 3},
{'craft_spring', 2},
{'craft_sheet', 1},
{'craft_pulley', 2},
{'craft_plug', 1},
{'craft_bulb', 4},
{'craft_transistor', 2},
{'craft_resistor', 2},
{'craft_relay', 4},
},
finish = {
{'bpd_fridge', 1},
},
}) octoinv.registerCraft('cont_fridge', {
name = L.fridge,
desc = L.desc_cont_fridge,
icon = 'octoteam/icons/fridge.png',
previewModel = 'models/props_c17/furniturefridge001a.mdl',
conts = {'_hand'},
sound = drillSounds,
soundTime = 2,
time = 30,
tools = {
{'tool_craft', 1},
},
ings = {
{'bp_fridge', 1},
{'bpd_fridge', 1},
{'craft_battery', 1},
},
finish = octoinv.spawnProd({
mdl = 'models/props_c17/furniturefridge001a.mdl',
conts = {
fridge = { name = L.fridge, volume = 60, icon = octolib.icons.color('fridge'), prod = true },
},
prod = 'fridge',
}),
})
octoinv.registerCraft('bpd_machine', {
name = L.machine,
desc = L.desc_bpd_machine,
icon = 'octoteam/icons/box3.png',
conts = {'_hand'},
sound = drillSounds,
soundTime = 2,
time = 30,
tools = {
{'tool_caliper', 1},
{'tool_solder', 1},
{'tool_screwer', 1},
{'tool_drill', 1},
{'tool_wrench', 1},
},
ings = {
{'craft_cable', 3},
{'craft_piston', 2},
{'craft_spring', 4},
{'craft_sheet', 2},
{'craft_pulley', 2},
{'craft_plug', 1},
{'craft_engine', 1},
{'craft_gauge', 2},
},
finish = {
{'bpd_machine', 1},
},
}) octoinv.registerCraft('cont_machine', {
name = L.machine,
desc = L.desc_cont_machine,
icon = 'octoteam/icons/machine.png',
previewModel = 'models/codeandmodeling_samgaze_gta/gr_prop_gr_vertmill_01c.mdl',
conts = {'_hand'},
sound = drillSounds,
soundTime = 2,
time = 30,
tools = {
{'tool_craft', 1},
},
ings = {
{'bp_machine', 1},
{'bpd_machine', 1},
{'craft_battery', 1},
},
finish = octoinv.spawnProd({
mdl = 'models/codeandmodeling_samgaze_gta/gr_prop_gr_vertmill_01c.mdl',
conts = {
machine_tray = { name = L.machine_tray, volume = 60, icon = octolib.icons.color('machine'), prod = true },
machine = { name = L.machine, volume = 60, icon = octolib.icons.color('machine') },
},
prod = 'machine'
}),
})
octoinv.registerCraft('bpd_workbench', {
name = L.workbench,
desc = L.desc_bpd_workbench,
icon = 'octoteam/icons/box3.png',
conts = {'_hand'},
sound = drillSounds,
soundTime = 2,
time = 30,
tools = {
{'tool_caliper', 1},
{'tool_solder', 1},
{'tool_wrench', 1},
{'tool_hammer', 1},
{'tool_drill', 1},
},
ings = {
{'craft_cable', 2},
{'craft_piston', 4},
{'craft_spring', 4},
{'craft_bulb', 2},
{'craft_plank', 2},
{'craft_pulley', 2},
{'craft_plug', 1},
{'craft_engine', 1},
},
finish = {
{'bpd_workbench', 1},
},
}) octoinv.registerCraft('cont_workbench', {
name = L.workbench,
desc = L.cont_workbench,
icon = 'octoteam/icons/table.png',
previewModel = 'models/codeandmodeling_samgaze_gta/prop_tool_bench02.mdl',
conts = {'_hand'},
sound = drillSounds,
soundTime = 2,
time = 30,
tools = {
{'tool_craft', 1},
},
ings = {
{'bp_workbench', 1},
{'bpd_workbench', 1},
},
finish = octoinv.spawnCont('models/codeandmodeling_samgaze_gta/prop_tool_bench02.mdl', {
workbench = { name = L.workbench, volume = 100, icon = octolib.icons.color('table'), craft = true },
},{
destruct = {
{'bpd_workbench', 1},
},
}),
})
octoinv.registerCraft('bpd_refinery', {
name = L.refinery,
desc = L.desc_bpd_refinery,
icon = 'octoteam/icons/box3.png',
conts = {'_hand'},
sound = drillSounds,
soundTime = 2,
time = 30,
tools = {
{'tool_drill', 1},
{'tool_screwer', 1},
{'tool_caliper', 1},
},
ings = {
{'craft_cable', 2},
{'craft_sheet', 2},
{'craft_pulley', 2},
{'craft_plug', 1},
{'craft_chip2', 2},
{'craft_resistor', 2},
{'craft_gauge', 4},
{'craft_engine', 1},
},
finish = {
{'bpd_refinery', 1},
},
}) octoinv.registerCraft('cont_refinery', {
name = L.refinery,
desc = L.desc_refinery,
icon = 'octoteam/icons/chem_plant.png',
previewModel = 'models/mark2580/gtav/garage_stuff/sand_blaster_01a.mdl',
previewRotation = 90,
conts = {'_hand'},
sound = drillSounds,
soundTime = 2,
time = 30,
tools = {
{'tool_craft', 1},
},
ings = {
{'bp_refinery', 1},
{'bpd_refinery', 1},
},
finish = octoinv.spawnProd({
mdl = 'models/mark2580/gtav/garage_stuff/sand_blaster_01a.mdl',
conts = {
refinery_fuel = { name = L.refinery_fuel, volume = 100, icon = octolib.icons.color('chem_plant'), prod = true },
refinery = { name = L.refinery, volume = 100, icon = octolib.icons.color('chem_plant') },
},
prod = 'refinery',
rotate = 90,
}),
})
octoinv.registerCraft('bpd_smelter', {
name = L.smelter,
desc = L.desc_bpd_smelter,
icon = 'octoteam/icons/box3.png',
conts = {'_hand'},
sound = drillSounds,
soundTime = 2,
time = 30,
tools = {
{'tool_drill', 1},
{'tool_screwer', 1},
{'tool_caliper', 1},
},
ings = {
{'ingot_iron', 1},
{'craft_sheet', 2},
{'craft_pulley', 2},
{'craft_gauge', 2},
},
finish = {
{'bpd_smelter', 1},
},
}) octoinv.registerCraft('cont_smelter', {
name = L.smelter,
desc = L.desc_smelter,
icon = 'octoteam/icons/smelter.png',
previewModel = 'models/props/de_train/processor.mdl',
previewRotation = 90,
conts = {'_hand'},
sound = drillSounds,
soundTime = 2,
time = 30,
tools = {
{'tool_craft', 1},
},
ings = {
{'bp_smelter', 1},
{'bpd_smelter', 1},
},
finish = octoinv.spawnProd({
mdl = 'models/props/de_train/processor.mdl',
conts = {
smelter_fuel = { name = L.smelter_fuel, volume = 100, icon = octolib.icons.color('smelter'), prod = true },
smelter = { name = L.smelter, volume = 100, icon = octolib.icons.color('smelter') },
},
prod = 'smelter',
rotate = 90,
}),
})

View file

@ -0,0 +1,73 @@
local woodsounds = {
'physics/wood/wood_box_impact_bullet1.wav',
'physics/wood/wood_box_impact_bullet2.wav',
'physics/wood/wood_box_impact_bullet3.wav',
'physics/wood/wood_box_impact_bullet4.wav',
'physics/wood/wood_box_impact_hard1.wav',
'physics/wood/wood_box_impact_hard2.wav',
'physics/wood/wood_box_impact_hard3.wav',
}
------------------------------------------------
--
-- CONTAINERS
--
------------------------------------------------
-- octoinv.registerCraft('bpd_vend', {
-- name = L.vend,
-- desc = L.desc_bpd_vend,
-- icon = 'octoteam/icons/box3.png',
-- conts = {'_hand'},
-- sound = drillSounds,
-- soundTime = 2,
-- time = 30,
-- tools = {
-- {'tool_solder', 1},
-- {'tool_drill', 1},
-- },
-- ings = {
-- {'craft_cable', 4},
-- {'craft_bulb', 5},
-- {'craft_sheet', 2},
-- {'craft_plug', 1},
-- {'craft_relay', 1},
-- {'craft_transistor', 8},
-- {'craft_resistor', 8},
-- },
-- finish = {
-- {'bpd_vend', 1},
-- },
-- }) octoinv.registerCraft('cont_vend', {
-- name = L.vend,
-- desc = L.desc_cont_vend,
-- icon = 'octoteam/icons/machine_vend.png',
-- conts = {'_hand'},
-- sound = drillSounds,
-- soundTime = 2,
-- time = 30,
-- tools = {
-- {'tool_craft', 1},
-- },
-- ings = {
-- {'bp_vend', 1},
-- {'bpd_vend', 1},
-- {'craft_battery', 1},
-- },
-- finish = function(ply, cont)
-- local ent = ents.Create 'octoinv_vend'
-- ent.dt = ent.dt or {}
-- ent.dt.owning_ent = ply
-- ent.DestructParts = {
-- {'bpd_vend', 1},
-- }
-- ent.SID = ply.SID
-- ent:Spawn()
-- ply:BringEntity(ent)
-- ent:SetPlayer(ply)
-- ent:SetLocked(false)
-- return true
-- end,
-- })

View file

@ -0,0 +1,377 @@
------------------------------------------------
--
-- COOKING
--
------------------------------------------------
local cookSounds = {
'physics/flesh/flesh_squishy_impact_hard1.wav',
'physics/flesh/flesh_squishy_impact_hard2.wav',
'physics/flesh/flesh_squishy_impact_hard3.wav',
'physics/flesh/flesh_squishy_impact_hard4.wav',
'physics/plastic/plastic_box_impact_soft1.wav',
'physics/plastic/plastic_box_impact_soft2.wav',
'physics/plastic/plastic_box_impact_soft3.wav',
'physics/plastic/plastic_box_impact_soft4.wav',
'physics/plastic/plastic_box_break1.wav',
'physics/plastic/plastic_box_break2.wav',
}
--
-- INGREDIENTS
--
octoinv.registerCraft('ing_dough1', {
name = L.dough1,
desc = L.desc_dough1,
conts = {'stove'},
sound = cookSounds,
time = 15,
ings = {
{'ing_flour', 1},
{'ing_salt', 1},
{'ing_milk', 1},
{'ing_egg', 2},
},
finish = {
{'ing_dough1', 1},
}
})
octoinv.registerCraft('ing_dough2', {
name = L.dough2,
desc = L.desc_dough2,
conts = {'stove'},
sound = cookSounds,
time = 15,
ings = {
{'ing_flour', 1},
{'ing_sugar', 1},
{'ing_egg', 2},
},
finish = {
{'ing_dough2', 1},
}
})
octoinv.registerCraft('ing_icecream', {
name = L.ing_icecream2,
desc = L.desc_ing_icecream,
conts = {'stove'},
sound = cookSounds,
time = 5,
tools = {
{'tool_scoop', 1},
},
ings = {
{'ing_cream', 2},
{'ing_sugar', 2},
},
finish = {
{'ing_icecream', 1},
}
})
octoinv.registerCraft('ing_potatomash', {
name = L.potatomash,
desc = L.desc_potatomash,
conts = {'stove'},
sound = cookSounds,
time = 10,
tools = {
{'tool_pot', 1},
},
ings = {
{'ing_potato2', 2},
{'ing_oil', 1},
{'ing_salt', 1},
{'ing_milk', 1},
},
finish = {
{'ing_potatomash', 1},
},
})
--
-- DISHES
--
octoinv.registerCraft('food_meatpotato', {
name = L.meatpotato,
desc = L.desc_meatpotato,
conts = {'stove'},
sound = cookSounds,
time = 4,
ings = {
{'tool_foodcont', 1},
{'ing_potatomash', 1},
{'ing_meatball', 1},
},
finish = {
{'food', {
name = L.meatpotato,
icon = 'octoteam/icons/food_mashed_potato_with_cutlet.png',
energy = 70,
}},
}
})
octoinv.registerCraft('food_okroshka', {
name = L.okroshka,
desc = L.desc_okroshka,
conts = {'stove'},
sound = cookSounds,
time = 10,
tools = {
{'tool_pot', 1},
},
ings = {
{'tool_foodcont', 1},
{'ing_egg', 2},
{'ing_salt', 1},
{'ing_cucumber', 2},
{'ing_potato2', 3},
},
finish = {
{'food', {
name = L.okroshka,
icon = 'octoteam/icons/food_soup.png',
energy = 65,
}},
}
})
octoinv.registerCraft('food_sandwitch', {
name = L.sandwitch,
desc = L.desc_sandwitch,
conts = {'stove', '_hand'},
sound = cookSounds,
time = 10,
ings = {
{'ing_sausage2', 1},
{'ing_bread', 1},
},
finish = {
{'food', {
name = L.sandwitch,
icon = 'octoteam/icons/food_sandwich_simple.png',
energy = 15,
}},
}
})
-- octoinv.registerCraft('food_sushi', {
-- name = L.sushi,
-- desc = L.desc_sushi,
-- conts = {'stove'},
-- sound = cookSounds,
-- time = 10,
-- tools = {
-- {'tool_scoop', 1},
-- },
-- ings = {
-- {'tool_foodcont', 1},
-- {'ing_fish1', 2},
-- {'ing_rice', 2},
-- },
-- finish = {
-- {'food', {
-- name = L.sushi,
-- icon = 'octoteam/icons/food_sushi.png',
-- energy = 35,
-- }},
-- }
-- })
octoinv.registerCraft('food_wrap', {
name = L.wrap,
desc = L.desc_wrap,
conts = {'stove'},
sound = cookSounds,
time = 10,
ings = {
{'tool_foodcont', 1},
{'ing_roastmeat', 2},
{'ing_lettuce', 1},
{'ing_salt', 1},
{'ing_pita', 1},
{'ing_tomato', 1},
},
finish = {
{'food', {
name = L.wrap,
icon = 'octoteam/icons/food_wrap.png',
energy = 60,
}},
}
})
octoinv.registerCraft('food_cake_med', {
name = L.cake_med,
desc = L.desc_cake_med,
conts = {'stove'},
sound = cookSounds,
time = 10,
ings = {
{'tool_foodcont', 1},
{'ing_dough3', 1},
{'ing_sugar', 2},
{'ing_cocoa', 2},
{'ing_cream', 1},
{'ing_honey', 2},
},
finish = {
{'food', {
name = L.cake_med,
icon = 'octoteam/icons/food_honey_cake.png',
energy = 100,
}},
}
})
octoinv.registerCraft('food_ceasar', {
name = L.ceasar,
desc = L.desc_ceasar,
conts = {'stove'},
sound = cookSounds,
time = 10,
ings = {
{'tool_foodcont', 1},
{'ing_roastmeat', 1},
{'ing_salt', 1},
{'ing_oil', 1},
{'ing_egg', 2},
{'ing_lettuce', 1},
{'ing_cheese', 1},
{'ing_tomato', 2},
},
finish = {
{'food', {
name = L.ceasar,
icon = 'octoteam/icons/food_caesar_salad.png',
energy = 65,
}},
}
})
octoinv.registerCraft('food_burger1', {
name = L.burger,
desc = L.desc_burger,
conts = {'stove'},
sound = cookSounds,
time = 10,
ings = {
{'tool_foodcont', 1},
{'ing_bread', 2},
{'ing_sauce', 1},
{'ing_meatball', 1},
},
finish = {
{'food', {
name = L.burger,
icon = 'octoteam/icons/food_hamburger.png',
energy = 35,
}},
}
})
octoinv.registerCraft('food_burger2', {
name = L.burger2,
desc = L.desc_burger2,
conts = {'stove'},
sound = cookSounds,
time = 10,
ings = {
{'tool_foodcont', 1},
{'ing_bread', 2},
{'ing_sauce', 1},
{'ing_meatball', 1},
{'ing_lettuce', 1},
{'ing_cheese', 1},
},
finish = {
{'food', {
name = L.burger2,
icon = 'octoteam/icons/food_cheeseburger.png',
energy = 45,
}},
}
})
octoinv.registerCraft('food_burger3', {
name = L.burger3,
desc = L.desc_burger3,
conts = {'stove'},
sound = cookSounds,
time = 10,
ings = {
{'tool_foodcont', 1},
{'ing_bread', 2},
{'ing_sauce', 1},
{'ing_meatball', 2},
{'ing_lettuce', 1},
{'ing_cheese', 1},
{'ing_tomato', 2},
{'ing_onion', 1},
{'ing_cucumber', 2},
},
finish = {
{'food', {
name = L.burger3,
icon = 'octoteam/icons/food_bigmack.png',
energy = 100,
}},
}
})
octoinv.registerCraft('food_coffeetail', {
name = L.coffeetail2,
conts = {'stove'},
sound = cookSounds,
time = 10,
tools = {
{'tool_shaker', 1},
},
ings = {
{'tool_foodcont', 1},
{'drug_booze2', 1},
{'ing_water', 1},
{'ing_coffee', 2},
{'ing_sugar', 4},
},
finish = {
{'food', {
name = L.coffeetail2,
icon = 'octoteam/icons/food_cocktail.png',
energy = 15,
drink = true,
}},
}
})
octoinv.registerCraft('food_coffeetail', {
name = L.coffeetail,
conts = {'stove'},
sound = cookSounds,
time = 15,
tools = {
{'tool_pot', 1},
{'tool_shaker', 1},
},
ings = {
{'tool_foodcont', 1},
{'ing_milk', 1},
{'ing_egg', 1},
{'ing_sugar', 4},
{'ing_honey', 1},
{'ing_salt', 1},
},
finish = {
{'food', {
name = L.coffeetail,
icon = 'octoteam/icons/food_gogol_mogul.png',
energy = 30,
drink = true,
}},
}
})

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,116 @@
local function checkPrinterLimit(ply)
local prods = octolib.getLinkedEnts(ply:SteamID(), {'octoinv_prod'})
local hasPrinters = octolib.table.count(prods, function(ent)
local inv = IsValid(ent) and ent.inv
return inv and inv.conts and inv.conts.printer or false
end)
if hasPrinters >= 2 then
return false, 'Достигнут лимит принтеров'
end
return true
end
------------------------------------------------
--
-- OTHER
--
------------------------------------------------
-- octoinv.registerCraft('printer', {
-- name = L.printer,
-- desc = L.desc_printer,
-- icon = 'octoteam/icons/atm.png',
-- conts = {'_hand'},
-- sound = drillSounds,
-- soundTime = 2,
-- time = 25,
-- tools = {
-- {'tool_screwer', 1},
-- {'tool_wrench', 1},
-- },
-- ings = {
-- {'bp_printer', 1},
-- {'craft_screw2', 20},
-- {'craft_screwnut', 20},
-- {'craft_engine', 1},
-- {'craft_cable', 3},
-- {'craft_cnc', 1},
-- {'craft_sheet', 2},
-- },
-- finish = octoinv.spawnProd({
-- mdl = 'models/props_c17/consolebox01a.mdl',
-- conts = {
-- printer_cart = { name = L.printer_cart, volume = 3 },
-- printer = { name = L.printer, volume = 5, prod = true },
-- },
-- prod = 'printer',
-- check = checkPrinterLimit,
-- other = {
-- CanBeOwnedBy = function(_, ply)
-- return checkPrinterLimit(ply)
-- end,
-- },
-- }),
-- })
-- octoinv.registerCraft('craft_paper2', {
-- name = L.craft_paper2,
-- icon = 'octoteam/icons/paper_stack.png',
-- conts = {'workbench'},
-- time = 5,
-- ings = {
-- {'craft_paper', 10}
-- },
-- finish = {
-- {'craft_paper2', 1}
-- },
-- })
octoinv.registerCraft('craft_radio', {
name = L.talkie,
icon = 'octoteam/icons/radio.png',
conts = {'workbench'},
jobs = {'gun', 'gun2'},
time = 15,
tools = {
{'tool_screwer', 1},
{'tool_solder', 1},
},
ings = {
{'craft_resistor', 5},
{'craft_chip2', 1},
{'craft_bulb', 3},
{'craft_relay', 5},
{'craft_glue', 1},
{'craft_cable', 10},
{'craft_sheet', 2},
{'craft_screwnut', 8},
{'craft_screw2', 8},
{'craft_transistor', 5},
},
finish = {
{'radio', 1}
},
})
octoinv.registerCraft('craft_binoculars', {
name = L.craft_binoculars,
icon = 'octoteam/icons/binoculars.png',
conts = {'workbench'},
jobs = {'gun', 'gun2'},
time = 20,
tools = {
{'tool_screwer', 1},
{'tool_hammer', 1},
},
ings = {
{'craft_sheet', 2},
{'craft_glue', 1},
{'craft_sight', 4},
{'craft_spring', 2},
{'craft_piston', 2},
},
finish = {
{'binoculars', 1}
},
})

View file

@ -0,0 +1,54 @@
octoinv.registerItem('weapon', { -- [string] item ID
name = 'Оружие', -- [string] print name
class = 'spawned_weapon', -- [string] (class of dropped ent)
model = 'models/weapons/w_pist_glock18.mdl', -- [string] (model of dropped ent)
icon = 'octoteam/icons/gun_pistol.png', -- [string] icon for vgui
mass = 1, -- [float] item mass
volume = 1, -- [float] item volume
nostack = true, -- [bool] (whether this item is not stackable)
nodespawn = true, -- [bool] (whether this item should never despawn when dropped)
pickup = function(ply, ent) -- [function(Player, Entity)] (pickup function, returns table to override data in item)
local class = ent:GetWeaponClass()
local name = ent.itemName or weapons.Get(class).PrintName or weapons.Get(class).Name
return {
name = name,
icon = ent.itemIcon,
model = ent:GetModel(),
ent = {
class = class,
amount = ent:Getamount(),
clip1 = ent.clip1,
clip2 = ent.clip2,
ammo = ent.ammoadd,
}
}
end,
drop = function(ply, item, amount, posData) -- [function(Player, Item, int, table(Vector pos, Angles ang, Vector vel))]
local ent = ents.Create('spawned_weapon') -- (drop function, return false or nil to prevent drop, otherwise created Entity)
ent:SetPos(posData.pos)
ent:SetAngles(posData.ang)
ent:SetModel(item:GetData('model'))
local data = item:GetData('ent')
ent:Setamount(data.amount)
ent:SetWeaponClass(data.class)
if data.clip1 then ent.clip1 = data.clip1 end
if data.clip2 then ent.clip2 = data.clip2 end
if data.ammoadd then ent.ammoadd = data.ammo end
if item.name then ent.itemName = item.name end
if item.icon then ent.itemIcon = item.icon end
ent:Spawn()
ent:Activate()
local phys = ent:GetPhysicsObject()
if IsValid(phys) then
phys:Wake()
phys:SetVelocity(posData.vel)
end
return ent, 1
end,
})
-- more to come

View file

@ -0,0 +1,141 @@
local descBP = L.descBP
local descBPD = L.descBDP
------------------------------------------------
--
-- BLUEPRINTS
--
------------------------------------------------
--
-- benches
--
octoinv.registerItem('bp_stove', {
name = L.stove,
icon = 'octoteam/icons/blueprint.png',
mass = 0.1,
volume = 0.1,
nostack = true,
desc = descBP,
}) octoinv.registerItem('bpd_stove', {
name = L.stove,
icon = 'octoteam/icons/parts_stove.png',
mass = 40,
volume = 35,
nostack = true,
desc = descBPD,
})
octoinv.registerItem('bp_fridge', {
name = L.fridge,
icon = 'octoteam/icons/blueprint.png',
mass = 0.1,
volume = 0.1,
nostack = true,
desc = descBP,
}) octoinv.registerItem('bpd_fridge', {
name = L.fridge,
icon = 'octoteam/icons/parts_fridge.png',
mass = 50,
volume = 40,
nostack = true,
desc = descBPD,
})
octoinv.registerItem('bp_vend', {
name = L.vend,
icon = 'octoteam/icons/blueprint.png',
mass = 0.1,
volume = 0.1,
desc = descBP,
}) octoinv.registerItem('bpd_vend', {
name = L.vend,
icon = 'octoteam/icons/parts_vending.png',
mass = 40,
volume = 30,
desc = descBPD,
})
octoinv.registerItem('bp_workbench', {
name = L.workbench,
icon = 'octoteam/icons/blueprint.png',
mass = 0.1,
volume = 0.1,
nostack = true,
desc = descBP,
}) octoinv.registerItem('bpd_workbench', {
name = L.workbench,
icon = 'octoteam/icons/parts_workbench.png',
mass = 45,
volume = 50,
nostack = true,
desc = descBPD,
})
octoinv.registerItem('bp_machine', {
name = L.machine,
icon = 'octoteam/icons/blueprint.png',
mass = 0.1,
volume = 0.1,
nostack = true,
desc = descBP,
}) octoinv.registerItem('bpd_machine', {
name = L.machine,
icon = 'octoteam/icons/parts_machine.png',
mass = 60,
volume = 45,
nostack = true,
desc = descBPD,
})
octoinv.registerItem('bp_refinery', {
name = L.refinery,
icon = 'octoteam/icons/blueprint.png',
mass = 0.1,
volume = 0.1,
nostack = true,
desc = descBP,
}) octoinv.registerItem('bpd_refinery', {
name = L.refinery,
icon = 'octoteam/icons/parts_refinery.png',
mass = 80,
volume = 55,
nostack = true,
desc = descBPD,
})
octoinv.registerItem('bp_smelter', {
name = L.smelter,
icon = 'octoteam/icons/blueprint.png',
mass = 0.1,
volume = 0.1,
nostack = true,
desc = descBP,
}) octoinv.registerItem('bpd_smelter', {
name = L.smelter,
icon = 'octoteam/icons/parts_smelter.png',
mass = 60,
volume = 50,
nostack = true,
desc = descBPD,
})
--
-- other
--
octoinv.registerItem('bp_printer', {
name = L.printer,
icon = 'octoteam/icons/blueprint.png',
mass = 0.1,
volume = 0.1,
nostack = true,
desc = descBP,
}) octoinv.registerItem('bpd_printer', {
name = L.printer,
icon = 'octoteam/icons/box3.png',
mass = 18,
volume = 15,
nostack = true,
desc = descBPD,
})

View file

@ -0,0 +1,491 @@
------------------------------------------------
--
-- CAR STUFF
--
------------------------------------------------
octoinv.registerItem('tool_susp', {
name = L.tool_susp,
icon = 'octoteam/icons/tool_suspension.png',
mass = 2,
volume = 1.5,
desc = L.desc_tool_susp,
nodespawn = true,
})
octoinv.registerItem('car_kit', {
name = L.car_kit,
icon = 'octoteam/icons/tool_repair.png',
mass = 5,
volume = 6,
desc = L.desc_car_kit,
nodespawn = true,
use = {
function(ply, item)
if ply:Team() ~= TEAM_MECH then return false, L.this_only_mech end
return L.repair_car, 'octoteam/icons/repair.png', function(ply, item)
local ent = octolib.use.getTrace(ply).Entity
if not IsValid(ent) or ent:GetClass() ~= 'gmod_sent_vehicle_fphysics_base' or ent:GetCurHealth() >= ent:GetMaxHealth() then
ply:Notify('warning', L.repair_car_hint)
return 0
end
ply:DelayedAction('repair', L.repair_action, {
time = 20,
check = function() return octolib.use.check(ply, ent) and ply:HasItem('car_kit') > 0 end,
succ = function()
ply:TakeItem('car_kit', 1)
local MaxHealth = ent:GetMaxHealth()
local NewHealth = math.min(ent:GetCurHealth() + 450, MaxHealth)
if NewHealth > (MaxHealth * 0.6) then
ent:SetOnFire( false )
ent:SetOnSmoke( false )
end
if NewHealth > MaxHealth * 0.3 then
ent:SetOnFire( false )
if NewHealth <= MaxHealth * 0.6 then
ent:SetOnSmoke( true )
end
end
ent:SetCurHealth(NewHealth)
net.Start('simfphys_lightsfixall')
net.WriteEntity(ent)
net.Broadcast()
local effect = ents.Create('env_spark')
effect:SetKeyValue('targetname', 'target')
effect:SetPos(ent:GetPos())
effect:SetAngles(Angle())
effect:Spawn()
effect:SetKeyValue('spawnflags','128')
effect:SetKeyValue('Magnitude',2)
effect:SetKeyValue('TrailLength',0.5)
effect:Fire( 'SparkOnce' )
effect:Fire('kill','',0.5)
timer.Simple(1, function() carDealer.saveVeh(ent) end)
end,
}, {
time = 1.5,
inst = true,
action = function()
ply:DoAnimation(ACT_GMOD_GESTURE_ITEM_DROP + math.random(0,1))
ply:EmitSound("weapons/357/357_reload".. math.random(1, 4) ..".wav")
end,
})
return 0
end
end
},
})
octoinv.registerItem('car_wheel', {
name = L.car_wheel,
icon = 'octoteam/icons/wheel_flat.png',
model = 'models/props_vehicles/carparts_tire01a.mdl',
mass = 3,
volume = 3,
nostack = true,
nodespawn = true,
desc = L.desc_car_wheel,
use = {
function(ply, item)
if ply:Team() ~= TEAM_MECH then return false, L.this_only_mech end
return L.repair_wheel, 'octoteam/icons/wheel_flat.png', function(ply, item)
local ent = octolib.use.getTrace(ply).Entity
if not IsValid(ent) or ent:GetClass() ~= 'gmod_sent_vehicle_fphysics_wheel' or not ent:GetDamaged() then
ply:Notify('warning', L.repair_wheel_hint)
return 0
end
if ent.deposit then return ply:Notify('warning', 'Арендованные автомобили нельзя изменять') end
ply:DelayedAction('repair', L.repair_action, {
time = 15,
check = function() return octolib.use.check(ply, ent) and ply:HasItem('car_wheel') > 0 end,
succ = function()
ply:TakeItem('car_wheel', 1)
local effect = ents.Create('env_spark')
effect:SetKeyValue('targetname', 'target')
effect:SetPos(ent:GetPos())
effect:SetAngles(Angle())
effect:Spawn()
effect:SetKeyValue('spawnflags','128')
effect:SetKeyValue('Magnitude',1)
effect:SetKeyValue('TrailLength',0.2)
effect:Fire( 'SparkOnce' )
effect:Fire('kill','',0.08)
local w = ent.GhostEnt
if IsValid(w) then
local gib = ents.Create 'gmod_sent_vehicle_fphysics_gib'
gib:SetModel(w:GetModel())
gib:SetPos(w:GetPos() - ply:GetAimVector():GetNormalized())
gib:SetAngles(w:GetAngles())
gib:Spawn()
gib:Activate()
gib:GetPhysicsObject():SetMass(20)
gib.DoNotDuplicate = true
gib.NoFire = true
else
local gib = ents.Create 'gmod_sent_vehicle_fphysics_gib'
gib:SetModel('models/props_vehicles/tire001c_car.mdl')
gib:SetPos(ent:GetPos() - ply:GetAimVector():GetNormalized())
gib:SetAngles(ent:GetAngles())
gib:Spawn()
gib:Activate()
gib:GetPhysicsObject():SetMass(20)
gib.DoNotDuplicate = true
gib.NoFire = true
end
ent:SetDamaged(false)
end,
}, {
time = 1.5,
inst = true,
action = function()
ply:DoAnimation(ACT_GMOD_GESTURE_ITEM_DROP + math.random(0,1))
ply:EmitSound("weapons/357/357_reload".. math.random(1, 4) ..".wav")
end,
})
return 0
end
end
},
})
octoinv.registerItem('car_fuel', {
name = 'Канистра',
icon = 'octoteam/icons/gas_can.png',
mass = 5,
volume = 6,
desc = 'Используется для заправки автомобиля',
nodespawn = true,
use = {
function(ply, item)
return 'Заправить машину', 'octoteam/icons/gas_can.png', function(ply, item)
local ent = octolib.use.getTrace(ply).Entity
if not IsValid(ent) or ent:GetClass() ~= 'gmod_sent_vehicle_fphysics_base' or ent:GetFuel() >= ent:GetMaxFuel() then
ply:Notify('warning', 'Нужно смотреть на незаправленную машину')
return 0
end
ply:DelayedAction('repair', 'Заправка', {
time = 20,
check = function() return octolib.use.check(ply, ent) and ply:HasItem('car_fuel') > 0 end,
succ = function()
ply:TakeItem('car_fuel', 1)
local newFuel = ent:GetFuel() + 10
ent:SetFuel(newFuel)
ent:SetNetVar('Fuel', newFuel)
end,
}, {
time = 1.5,
inst = true,
action = function()
ply:DoAnimation(ACT_GMOD_GESTURE_ITEM_DROP + math.random(0,1))
ply:EmitSound("vehicles/jetski/jetski_no_gas_start.wav")
end,
})
return 0
end
end
},
})
octoinv.registerItem('car_paint', {
name = L.car_paint,
icon = 'octoteam/icons/bucket.png',
mass = 3,
volume = 2,
nostack = true,
nodespawn = true,
desc = L.desc_car_paint,
use = {
function(ply, item)
if ply:Team() ~= TEAM_MECH then return false, L.this_only_mech end
local ent = octolib.use.getTrace(ply).Entity
if not IsValid(ent) or ent:GetClass() ~= 'gmod_sent_vehicle_fphysics_base' then return false, L.see_car end
if ent.police then return false, L.car_not_paint end
if ent.deposit then return ply:Notify('warning', 'Арендованные автомобили нельзя изменять') end
local can, why = simfphys.CanPlayerTune(ply, ent)
if not can then return false, why end
return L.painting_car, 'octoteam/icons/blood.png', function(ply, item)
local ent = octolib.use.getTrace(ply).Entity
if not IsValid(ent) or ent:GetClass() ~= 'gmod_sent_vehicle_fphysics_base' or ent.police or ent.deposit then return 0 end
octolib.request.send(ply, {
{
name = L.car_color,
desc = L.desc_car_color,
type = 'color',
},
}, function(data)
local col = data[1] or Color(255,255,255)
col.a = 255
local playSound = true
ply:DelayedAction('paint', L.paint, {
time = 20,
check = function() return octolib.use.check(ply, ent) and tobool(ply:HasItem(item)) end,
succ = function()
ply:TakeItem(item)
ply:StopSound('d1_town.GasJet')
ent:SetProxyColors({ col, col, CFG.reflectionTint, col })
ent:RemoveAllDecals()
if ent.atts then
for k, attEnt in pairs(ent.atts) do if not attEnt.noPaint then attEnt:SetColor(col) end end
end
timer.Simple(1, function() carDealer.saveVeh(ent) end)
end,
fail = function()
ply:StopSound('d1_town.GasJet')
end,
}, {
time = 1.5,
inst = true,
action = function()
if playSound then
ply:EmitSound('d1_town.GasJet')
playSound = false
end
ply:DoAnimation(ACT_GMOD_GESTURE_ITEM_DROP + math.random(0,1))
end,
})
end)
return 0
end
end
},
})
octoinv.registerItem('car_part', {
name = L.car_part,
icon = 'octoteam/icons/cogs.png',
mass = 1,
volume = 1,
nostack = true,
nodespawn = true,
desc = L.desc_car_part,
use = {
function(ply, item)
if ply:Team() ~= TEAM_MECH then return false, L.this_only_mech end
if not item:GetData('car') or not item:GetData('bgnum') or not item:GetData('bgval') then return false, L.item_break end
local ent
for i, v in ipairs(ents.FindInSphere(ply:GetShootPos(), 120)) do
if v:GetClass() == 'gmod_sent_vehicle_fphysics_base' then ent = v break end
end
if not IsValid(ent) then return false, L.see_car end
if ent.deposit then return ply:Notify('warning', 'Арендованные автомобили нельзя изменять') end
if ent.VehicleName ~= item:GetData('car') then return false, L.item_does_not_fit end
local bgn, bgv = item:GetData('bgnum'), item:GetData('bgval')
if ent:GetBodygroup(bgn) == bgv then return false, L.detail_already_set end
local can, why = simfphys.CanPlayerTune(ply, ent)
if not can then return false, why end
return L.set_detail, 'octoteam/icons/wrench.png', function(ply, item)
local ent = octolib.use.getTrace(ply).Entity
if not IsValid(ent) or ent:GetClass() ~= 'gmod_sent_vehicle_fphysics_base' then return 0 end
if ent.VehicleName ~= item:GetData('car') then return 0 end
local bgn, bgv = item:GetData('bgnum'), item:GetData('bgval')
if ent:GetBodygroup(bgn) == bgv then return 0 end
ply:DelayedAction('car_mount', L.set_hint, {
time = 20,
check = function() return octolib.use.check(ply, ent) and tobool(ply:HasItem(item)) end,
succ = function()
ply:TakeItem(item)
ent:SetBodygroup(bgn, bgv)
ent:UpdateInventory()
timer.Simple(1, function() carDealer.saveVeh(ent) end)
end,
}, {
time = 1.5,
inst = true,
action = function()
ply:EmitSound("ambient/machines/pneumatic_drill_".. math.random(1, 4) ..".wav")
ply:DoAnimation(ACT_GMOD_GESTURE_ITEM_DROP + math.random(0,1))
end,
})
return 0
end
end
},
})
octoinv.registerItem('car_rims', {
name = L.car_rims,
icon = 'octoteam/icons/wheel.png',
mass = 1,
volume = 1,
nostack = true,
nodespawn = true,
desc = L.desc_car_rims,
use = {
function(ply, item)
if ply:Team() ~= TEAM_MECH then return false, L.this_only_mech end
local ent
for i, v in ipairs(ents.FindInSphere(ply:GetShootPos(), 120)) do
if v:GetClass() == 'gmod_sent_vehicle_fphysics_base' then ent = v break end
end
if not IsValid(ent) then return false, L.see_car end
if ent.deposit then return false, 'Арендованные автомобили нельзя изменять' end
local mdl = item:GetData('model')
if ent.wModelF == mdl then return false, L.detail_already_set end
local can, why = simfphys.CanPlayerTune(ply, ent)
if not can then return false, why end
return L.set_discs, 'octoteam/icons/wrench.png', function(ply, item)
local ent = octolib.use.getTrace(ply).Entity
if not IsValid(ent) or ent:GetClass() ~= 'gmod_sent_vehicle_fphysics_base' then return 0 end
if ent.wModelF == mdl then return 0 end
ply:DelayedAction('car_mount', L.set_hint, {
time = 20,
check = function() return octolib.use.check(ply, ent) and tobool(ply:HasItem(item)) end,
succ = function()
ply:TakeItem(item)
simfphys.ApplyWheel(ent, ent.camber or 0, mdl)
timer.Simple(1, function() carDealer.saveVeh(ent) end)
end,
}, {
time = 1.5,
inst = true,
action = function()
ply:EmitSound('ambient/machines/pneumatic_drill_' .. math.random(1, 4) .. '.wav')
ply:DoAnimation(ACT_GMOD_GESTURE_ITEM_DROP + math.random(0,1))
end,
})
return 0
end
end
},
})
octoinv.registerItem('car_att', {
name = L.car_att,
icon = 'octoteam/icons/cogs.png',
mass = 1,
volume = 1,
nostack = true,
nodespawn = true,
desc = L.desc_car_att,
use = {
function(ply, item)
if item:GetData('att') then
return 'Конвертировать', 'octoteam/icons/sparkler.png', function(ply, item)
local cont = item:GetParent()
item:Remove()
local attData = simfphys.attachments[item:GetData('att')]
if not attData then return end
cont:AddItem('car_att', {
name = attData.name,
desc = attData.desc,
icon = attData.icon,
mass = attData.mass,
volume = attData.volume,
colorable = not attData.noPaint or nil,
attmdl = attData.mdl,
model = attData.mdl,
skin = attData.skin,
scale = attData.scale,
})
return 0
end
end
local veh = ply:GetVehicle()
if not IsValid(veh) or not veh.base or veh.base:GetDriverSeat() ~= veh then
return false, 'Нужно быть на водительском сидении'
end
return L.set_detail, 'octoteam/icons/wrench.png', function(ply, item)
local car = veh.base
local carRadius = car:GetModelRadius()
local posDelta = (car:GetForward() + car:GetUp() * 0.8):GetNormalized()
local vPos = car:GetPos() + posDelta * carRadius
local vAng = (-posDelta):Angle()
octolib.flyEdit(ply, {
parent = car,
props = {{
model = item:GetData('attmdl'),
skin = item:GetData('skin'),
scale = item:GetData('scale'),
colorable = item:GetData('colorable'),
col = item:GetData('colorable') and car:GetProxyColors()[1]:ToColor() or item:GetData('col') or nil,
name = item:GetData('name'),
icon = item:GetData('icon'),
limits = item:GetData('limits') or { scale = {0.1, 3} },
}},
space = octolib.flyEditor.SPACE_PARENT,
vPos = vPos,
vAng = vAng,
maxDist = carRadius * 1.2,
anchorEnt = car,
noCopy = true,
noRemove = true,
}, function(changed, options)
if not ply:HasItem(item) or not IsValid(car) then return end
local atts = car:GetNetVar('atts', {})
for ent, data in pairs(changed) do
if not options.props[ent] or options.props[ent].model ~= data.model then continue end
-- local pos, ang = WorldToLocal(data.pos, data.ang, car:GetPos(), car:GetAngles())
data.size.x = math.Clamp(data.size.x, 0.1, 3)
data.size.y = math.Clamp(data.size.y, 0.1, 3)
data.size.z = math.Clamp(data.size.z, 0.1, 3)
local att = {
model = data.model,
pos = data.pos,
ang = data.ang,
col = data.col,
skin = data.skin,
mat = data.mat,
bgs = data.bgs,
size = data.size,
name = item:GetData('name'),
icon = item:GetData('icon'),
mass = item:GetData('mass'),
volume = item:GetData('volume'),
colorable = item:GetData('colorable'),
}
octolib.table.strip(att, octolib.entDefaults)
att.col = data.col
att.pos = att.pos or Vector()
att.ang = att.ang or Angle()
atts[#atts + 1] = att
ply:TakeItem(item)
ply:EmitSound('ambient/machines/pneumatic_drill_' .. math.random(1, 4) .. '.wav')
break
end
car:SetNetVar('atts', atts)
timer.Simple(1, function() carDealer.saveVeh(car) end)
end)
return 0
end
end
},
})

View file

@ -0,0 +1,206 @@
octoinv.registerItem('collector', {
name = 'Инструмент',
icon = octolib.icons.color('crowbar'),
nostack = true,
mass = 5,
volume = 5,
desc = 'Используется для сбора ресурсов',
model = 'models/weapons/hl2meleepack/w_pickaxe.mdl',
leftField = 'health',
leftMaxField = 'maxhealth',
nodespawn = true,
use = {
function(ply, item)
local collector = octoinv.collectors[item:GetData('collector') or '']
if not collector then return false, 'Неизвестный тип инструмента' end
return L.take_in_hand, octolib.icons.color('crowbar'), function(ply, item)
local wep = ents.Create('octoinv_collector')
if not wep:IsValid() then return 0 end
if not wep:IsWeapon() then wep:Remove() return 0 end
if not hook.Call('PlayerCanPickupWeapon', GAMEMODE, ply, wep) then return 0 end
wep:Remove()
local wep = ply:Give('octoinv_collector')
wep:SetShouldPlayPickupSound(false)
wep.itemData = item:Export()
wep.itemCont = item:GetParent().id
wep:SetCollectorID(item:GetData('collector'))
wep.health = item:GetData('health') or collector.health
if not wep.itemData.name or not wep.itemData.maxhealth then
wep.itemData.name = collector.name
wep.itemData.icon = collector.icon
wep.itemData.maxhealth = collector.health
end
timer.Simple(0, function()
ply:SelectWeapon('octoinv_collector')
end)
return 1
end
end,
},
})
--
-- RESOURCES
--
octoinv.registerItem('ore_iron', {
name = L.ore_iron,
icon = 'octoteam/icons/ore_iron.png',
model = 'models/un/ore_un_un.mdl',
modelColor = Color(90,90,90),
mass = 3,
volume = 2,
desc = L.descOre,
})
octoinv.registerItem('ore_steel', {
name = L.ore_steel,
icon = 'octoteam/icons/ore_steel.png',
model = 'models/un/ore_un_un.mdl',
modelColor = Color(185,185,185),
mass = 3,
volume = 2,
desc = L.descOre,
})
octoinv.registerItem('ore_silver', {
name = L.ore_silver,
icon = 'octoteam/icons/ore_silver.png',
model = 'models/un/ore_un_un.mdl',
modelColor = Color(255,255,255),
mass = 3,
volume = 2,
desc = L.descOre,
})
octoinv.registerItem('ore_bronze', {
name = L.ore_bronze,
icon = 'octoteam/icons/ore_bronze.png',
model = 'models/un/ore_un_un.mdl',
modelColor = Color(214,157,0),
mass = 3,
volume = 2,
desc = L.descOre,
})
octoinv.registerItem('ore_gold', {
name = L.ore_gold,
icon = 'octoteam/icons/ore_gold.png',
model = 'models/un/ore_un_un.mdl',
modelColor = Color(255,207,77),
mass = 3,
volume = 2,
desc = L.descOre,
})
octoinv.registerItem('ore_copper', {
name = L.ore_copper,
icon = 'octoteam/icons/ore_copper.png',
model = 'models/un/ore_un_un.mdl',
modelColor = Color(79,255,77),
mass = 3,
volume = 2,
desc = L.descOre,
})
octoinv.registerItem('stone', {
name = L.stone,
icon = 'octoteam/icons/rock.png',
model = 'models/un/ore_un_un.mdl',
modelMaterial = 'models/props/CS_militia/militiarock',
mass = 5,
volume = 3,
desc = 'Остатки горной породы, можно попробовать раздробить в очистителе',
})
octoinv.registerItem('rubble', {
name = L.rubble,
icon = 'octoteam/icons/rubble.png',
model = 'models/props_marines/sandbag_static.mdl',
mass = 5,
volume = 2.5,
desc = 'Дробленые куски горной породы среднего размера',
})
octoinv.registerItem('sand', {
name = L.sand,
icon = 'octoteam/icons/sand.png',
model = 'models/props_marines/sandbag_static.mdl',
mass = 5,
volume = 2,
desc = 'Очень мелкие частицы горной породы',
})
octoinv.registerItem('sulfur', {
name = L.sulfur,
icon = 'octoteam/icons/sulfur.png',
model = 'models/un/ore_un_un.mdl',
modelMaterial = 'models/props/cs_assault/pylon',
mass = 0.8,
volume = 0.5,
desc = 'Грубые кристаллы серы',
})
octoinv.registerItem('ingot_iron', {
name = L.ingot_iron,
icon = 'octoteam/icons/ingot_iron.png',
mass = 1,
volume = 0.5,
desc = L.descIngot,
})
octoinv.registerItem('ingot_steel', {
name = L.ingot_steel,
icon = 'octoteam/icons/ingot_steel.png',
mass = 1,
volume = 0.5,
desc = L.descIngot,
})
octoinv.registerItem('ingot_silver', {
name = L.ingot_silver,
icon = 'octoteam/icons/ingot_silver.png',
mass = 1,
volume = 0.5,
desc = L.descIngot,
})
octoinv.registerItem('ingot_bronze', {
name = L.ingot_bronze,
icon = 'octoteam/icons/ingot_bronze.png',
mass = 1,
volume = 0.5,
desc = L.descIngot,
})
octoinv.registerItem('ingot_gold', {
name = L.ingot_gold,
icon = 'octoteam/icons/ingot_gold.png',
mass = 1,
volume = 0.5,
desc = L.descIngot,
})
octoinv.registerItem('ingot_copper', {
name = L.ingot_copper,
icon = 'octoteam/icons/ingot_copper.png',
mass = 1,
volume = 0.5,
desc = L.descIngot,
})
octoinv.registerItem('craft_coal', {
name = L.craft_coal,
icon = 'octoteam/icons/coal.png',
model = 'models/un/ore_un_un.mdl',
modelMaterial = 'models/gibs/metalgibs/metal_gibs',
mass = 3,
volume = 3,
randomWeight = 0.25,
desc = L.descFuel,
})

View file

@ -0,0 +1,696 @@
------------------------------------------------
--
-- TOOLS
--
------------------------------------------------
octoinv.registerItem('tool_foodcont', {
name = L.tool_foodcont,
icon = 'octoteam/icons/inbox.png',
mass = 0.1,
volume = 0.05,
randomWeight = 0.1,
desc = L.desc_tool_foodcont,
})
local descTool = L.descfoodtool
octoinv.registerItem('tool_pan', {
name = L.tool_pan,
icon = 'octoteam/icons/pan.png',
mass = 0.8,
volume = 1,
randomWeight = 0.5,
desc = descTool,
})
octoinv.registerItem('tool_pot', {
name = L.tool_pot,
icon = 'octoteam/icons/pot.png',
mass = 1,
volume = 3,
randomWeight = 0.5,
desc = descTool,
})
octoinv.registerItem('tool_scoop', {
name = L.tool_scoop,
icon = 'octoteam/icons/scoop.png',
mass = 0.5,
volume = 0.25,
randomWeight = 0.25,
desc = descTool,
})
octoinv.registerItem('tool_shaker', {
name = L.tool_shaker,
icon = 'octoteam/icons/cocktail_shaker.png',
mass = 0.5,
volume = 1,
randomWeight = 0.5,
desc = descTool,
})
octoinv.registerItem('tool_oventray', {
name = L.tool_oventray,
icon = 'octoteam/icons/oventray.png',
mass = 1,
volume = 2,
randomWeight = 0.5,
desc = descTool,
})
octoinv.registerItem('tool_pastrybag', {
name = L.tool_pastrybag,
icon = 'octoteam/icons/pastry_bag.png',
mass = 0.3,
volume = 0.5,
randomWeight = 0.25,
desc = descTool,
})
octoinv.registerItem('tool_teapot', {
name = L.tool_teapot,
icon = 'octoteam/icons/pot_tea.png',
mass = 0.5,
volume = 1,
randomWeight = 0.5,
desc = descTool,
})
octoinv.registerItem('tool_coffeepot', {
name = L.tool_coffeepot,
icon = 'octoteam/icons/pot_coffee.png',
mass = 0.5,
volume = 1,
randomWeight = 0.5,
desc = descTool,
})
------------------------------------------------
--
-- RESOURCES
--
------------------------------------------------
local descIng = L.descing
octoinv.registerItem('ing_water', {
name = L.ing_water,
icon = 'octoteam/icons/bottle.png',
mass = 0.5,
volume = 0.5,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_egg', {
name = L.ing_egg,
icon = 'octoteam/icons/food_egg.png',
mass = 0.08,
volume = 0.1,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_oil', {
name = L.ing_oil,
icon = 'octoteam/icons/food_oil.png',
mass = 0.4,
volume = 0.5,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_salt', {
name = L.ing_salt,
icon = 'octoteam/icons/food_salt.png',
mass = 0.05,
volume = 0.1,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_potato', {
name = L.ing_potato,
icon = 'octoteam/icons/food_potato.png',
mass = 0.12,
volume = 0.15,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_cheese', {
name = L.ing_cheese,
icon = 'octoteam/icons/food_cheese.png',
mass = 0.2,
volume = 0.2,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_flour', {
name = L.ing_flour,
icon = 'octoteam/icons/food_flour.png',
mass = 0.2,
volume = 0.2,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_onion', {
name = L.ing_onion,
icon = 'octoteam/icons/food_onion.png',
mass = 0.08,
volume = 0.1,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_milk', {
name = L.ing_milk,
icon = 'octoteam/icons/food_milk.png',
mass = 1,
volume = 1,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_cream', {
name = L.ing_cream,
icon = 'octoteam/icons/food_milk2.png',
mass = 0.3,
volume = 0.3,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_meat', {
name = L.ing_meat,
icon = 'octoteam/icons/food_meat4.png',
mass = 0.25,
volume = 0.25,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_carrot', {
name = L.ing_carrot,
icon = 'octoteam/icons/food_carrot.png',
mass = 0.12,
volume = 0.1,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_tomato', {
name = L.ing_tomato,
icon = 'octoteam/icons/food_tomato.png',
mass = 0.12,
volume = 0.15,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_sugar', {
name = L.ing_sugar,
icon = 'octoteam/icons/food_sugar.png',
mass = 0.1,
volume = 0.1,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_mushroom', {
name = L.ing_mushroom,
icon = 'octoteam/icons/food_mushroom.png',
mass = 0.05,
volume = 0.05,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_sausage', {
name = L.ing_sausage,
icon = 'octoteam/icons/food_sausage.png',
mass = 0.1,
volume = 0.1,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_sausage2', {
name = L.ing_sausage2,
icon = 'octoteam/icons/food_sausage2.png',
mass = 0.15,
volume = 0.15,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_bread', {
name = L.ing_bread,
icon = 'octoteam/icons/food_bread.png',
mass = 0.15,
volume = 0.5,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_honey', {
name = L.ing_honey,
icon = 'octoteam/icons/food_honey.png',
mass = 0.3,
volume = 0.2,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_spice', {
name = L.ing_spice,
icon = 'octoteam/icons/food_spice.png',
mass = 0.05,
volume = 0.1,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_kvas', {
name = L.ing_kvas,
icon = 'octoteam/icons/food_kvas.png',
mass = 0.5,
volume = 0.5,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_cucumber', {
name = L.ing_cucumber,
icon = 'octoteam/icons/food_cucumber.png',
mass = 0.15,
volume = 0.15,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_rice', {
name = L.ing_rice,
icon = 'octoteam/icons/food_rice.png',
mass = 0.2,
volume = 0.2,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_nut', {
name = L.ing_nut,
icon = 'octoteam/icons/food_nut.png',
mass = 0.1,
volume = 0.1,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_apple', {
name = L.ing_apple,
icon = 'octoteam/icons/food_apple.png',
mass = 0.15,
volume = 0.15,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_corn', {
name = L.ing_corn,
icon = 'octoteam/icons/food_corn.png',
mass = 0.2,
volume = 0.2,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_celery', {
name = L.ing_celery,
icon = 'octoteam/icons/food_celery.png',
mass = 0.2,
volume = 0.2,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_bacon', {
name = L.ing_bacon,
icon = 'octoteam/icons/food_bacon.png',
mass = 0.15,
volume = 0.15,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_olive', {
name = L.ing_olive,
icon = 'octoteam/icons/food_olive.png',
mass = 0.15,
volume = 0.15,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_chili', {
name = L.ing_chili,
icon = 'octoteam/icons/food_chili.png',
mass = 0.1,
volume = 0.1,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_broccoli', {
name = L.ing_broccoli,
icon = 'octoteam/icons/food_broccoli.png',
mass = 0.15,
volume = 0.15,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_pineapple', {
name = L.ing_pineapple,
icon = 'octoteam/icons/food_pineapple.png',
mass = 0.5,
volume = 0.5,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_pumpkin', {
name = L.ing_pumpkin,
icon = 'octoteam/icons/food_pumpkin.png',
mass = 0.8,
volume = 0.8,
randomWeight = 0.1,
desc = descIng,
})
-- octoinv.registerItem('ing_fish', {
-- name = L.ing_fish,
-- icon = 'octoteam/icons/food_fish.png',
-- mass = 0.3,
-- volume = 0.3,
-- randomWeight = 0.1,
-- desc = descIng,
-- })
octoinv.registerItem('ing_strawberry', {
name = L.ing_strawberry,
icon = 'octoteam/icons/food_strawberry.png',
mass = 0.3,
volume = 0.3,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_watermelon', {
name = L.ing_watermelon,
icon = 'octoteam/icons/food_watermelon.png',
mass = 1.5,
volume = 1.5,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_melon', {
name = L.ing_melon,
icon = 'octoteam/icons/food_melon.png',
mass = 1.5,
volume = 1.5,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_soy', {
name = L.ing_soy,
icon = 'octoteam/icons/food_soy.png',
mass = 0.3,
volume = 0.3,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_peas', {
name = L.ing_peas,
icon = 'octoteam/icons/food_peas.png',
mass = 0.3,
volume = 0.3,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_lettuce', {
name = L.ing_lettuce,
icon = 'octoteam/icons/food_lettuce.png',
mass = 0.2,
volume = 0.2,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_cabbage', {
name = L.ing_cabbage,
icon = 'octoteam/icons/food_cabbage.png',
mass = 0.5,
volume = 0.5,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_beet', {
name = L.ing_beet,
icon = 'octoteam/icons/food_beet.png',
mass = 0.2,
volume = 0.2,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_redish', {
name = L.ing_redish,
icon = 'octoteam/icons/food_redish.png',
mass = 0.2,
volume = 0.2,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_eggplant', {
name = L.ing_eggplant,
icon = 'octoteam/icons/food_eggplant.png',
mass = 0.4,
volume = 0.4,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_prawn', {
name = L.ing_prawn,
icon = 'octoteam/icons/food_prawn.png',
mass = 0.2,
volume = 0.2,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_avocado', {
name = L.ing_avocado,
icon = 'octoteam/icons/food_avocado.png',
mass = 0.3,
volume = 0.3,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_pita', {
name = L.ing_pita,
icon = 'octoteam/icons/food_pita.png',
mass = 0.2,
volume = 0.2,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_cocoa', {
name = L.ing_cocoa,
icon = 'octoteam/icons/food_cocoa.png',
mass = 0.2,
volume = 0.2,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_choco', {
name = L.ing_choco,
icon = 'octoteam/icons/food_choco.png',
mass = 0.2,
volume = 0.2,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_coffee', {
name = L.ing_coffee,
icon = 'octoteam/icons/food_coffee.png',
mass = 0.1,
volume = 0.1,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_tea', {
name = L.ing_tea,
icon = 'octoteam/icons/leaves.png',
mass = 0.1,
volume = 0.1,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_banana', {
name = L.ing_banana,
icon = 'octoteam/icons/food_banana.png',
mass = 0.25,
volume = 0.25,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_orange', {
name = L.ing_orange,
icon = 'octoteam/icons/food_orange.png',
mass = 0.2,
volume = 0.25,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_lemon', {
name = L.ing_lemon,
icon = 'octoteam/icons/food_lemon.png',
mass = 0.15,
volume = 0.2,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_sauce', {
name = L.ing_sauce,
icon = 'octoteam/icons/food_sauce.png',
mass = 0.2,
volume = 0.15,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_pasta', {
name = L.ing_pasta,
icon = 'octoteam/icons/food_pasta.png',
mass = 0.5,
volume = 0.8,
randomWeight = 0.25,
desc = descIng,
})
------------------------------------------------
--
-- CRAFTED RESOURCES
--
------------------------------------------------
octoinv.registerItem('ing_potato2', {
name = L.ing_potato2,
icon = 'octoteam/icons/food_potato_boiled.png',
mass = 0.12,
volume = 0.15,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_meatball', {
name = L.ing_meatball,
icon = 'octoteam/icons/food_cutlet.png',
mass = 0.15,
volume = 0.15,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_roastmeat', {
name = L.ing_roastmeat,
icon = 'octoteam/icons/food_meat5.png',
mass = 0.15,
volume = 0.15,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_potatomash', {
name = L.ing_potatomash,
icon = 'octoteam/icons/food_porrige.png',
mass = 0.15,
volume = 0.15,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_soup', {
name = L.ing_soup,
icon = 'octoteam/icons/food_bouillon.png',
mass = 0.5,
volume = 0.5,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_icecream', {
name = L.ing_icecream,
icon = 'octoteam/icons/food_icecream2.png',
mass = 0.1,
volume = 0.1,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_dough1', {
name = L.dough1,
icon = 'octoteam/icons/food_pita.png',
mass = 0.2,
volume = 0.2,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_dough2', {
name = L.dough2,
icon = 'octoteam/icons/food_pita.png',
mass = 0.2,
volume = 0.2,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_dough3', {
name = L.ing_dough3,
icon = 'octoteam/icons/food_pita.png',
mass = 0.2,
volume = 0.2,
randomWeight = 0.1,
desc = descIng,
})
octoinv.registerItem('ing_pizza_base', {
name = L.ing_pizza_base,
icon = 'octoteam/icons/food_pizza_base.png',
mass = 0.5,
volume = 0.5,
randomWeight = 0.1,
desc = descIng,
})

View file

@ -0,0 +1,468 @@
local descTool = L.descTool
local descCraft = L.descCraft
local descFuel = L.descFuel
local descCraftFuel = L.descCraftFuel
------------------------------------------------
--
-- TOOLS
--
------------------------------------------------
octoinv.registerItem('tool_screwer', {
name = L.tool_screwer,
icon = 'octoteam/icons/screwdriver.png',
mass = 0.2,
volume = 0.15,
randomWeight = 0.25,
desc = descTool,
})
octoinv.registerItem('tool_hammer', {
name = L.tool_hammer,
icon = 'octoteam/icons/hammer.png',
mass = 0.2,
volume = 0.15,
randomWeight = 0.25,
desc = descTool,
})
octoinv.registerItem('tool_wrench', {
name = L.tool_wrench,
icon = 'octoteam/icons/wrench.png',
mass = 0.35,
volume = 0.2,
randomWeight = 0.25,
desc = descTool,
})
octoinv.registerItem('tool_solder', {
name = L.tool_solder,
icon = 'octoteam/icons/solder.png',
mass = 0.5,
volume = 0.3,
randomWeight = 0.25,
desc = descTool,
})
octoinv.registerItem('tool_ruler', {
name = L.tool_ruler,
icon = 'octoteam/icons/ruler.png',
mass = 0.35,
volume = 0.2,
randomWeight = 0.25,
desc = descTool,
})
octoinv.registerItem('tool_caliper', {
name = L.tool_caliper,
icon = 'octoteam/icons/caliper.png',
mass = 0.35,
volume = 0.2,
randomWeight = 0.25,
desc = descTool,
})
octoinv.registerItem('tool_knife_stanley', {
name = L.tool_knife_stanley,
icon = 'octoteam/icons/knife_stanley.png',
mass = 0.1,
volume = 0.1,
randomWeight = 0.25,
desc = descTool,
})
octoinv.registerItem('tool_drill', {
name = L.tool_drill,
icon = 'octoteam/icons/drill.png',
mass = 1.5,
volume = 1,
randomWeight = 0.25,
desc = descTool,
})
octoinv.registerItem('tool_saw', {
name = L.tool_saw,
icon = 'octoteam/icons/saw.png',
mass = 1.5,
volume = 1,
randomWeight = 0.25,
desc = descTool,
})
octoinv.registerItem('tool_pump', {
name = L.tool_pump,
icon = 'octoteam/icons/pump_hand.png',
mass = 0.8,
volume = 0.4,
randomWeight = 0.25,
desc = descTool,
})
octoinv.registerItem('tool_craft', {
name = L.tool_craft,
icon = 'octoteam/icons/tool_craft.png',
mass = 1.5,
volume = 1,
randomWeight = 0.25,
desc = descTool,
})
------------------------------------------------
--
-- BUILD RESOURCES
--
------------------------------------------------
octoinv.registerItem('craft_screw', {
name = L.craft_screw,
icon = 'octoteam/icons/screw.png',
mass = 0.01,
volume = 0.01,
randomWeight = 0.1,
desc = descCraft,
})
octoinv.registerItem('craft_screw2', {
name = L.craft_screw2,
icon = 'octoteam/icons/screw2.png',
mass = 0.01,
volume = 0.01,
randomWeight = 0.1,
desc = descCraft,
})
octoinv.registerItem('craft_screwnut', {
name = L.craft_screwnut,
icon = 'octoteam/icons/screwnut.png',
mass = 0.01,
volume = 0.01,
randomWeight = 0.1,
desc = descCraft,
})
octoinv.registerItem('craft_nail', {
name = L.craft_nail,
icon = 'octoteam/icons/nail.png',
mass = 0.01,
volume = 0.01,
randomWeight = 0.1,
desc = descCraft,
})
octoinv.registerItem('craft_stick', {
name = L.craft_stick,
icon = 'octoteam/icons/stick.png',
mass = 0.5,
volume = 1,
randomWeight = 0.1,
desc = descCraft,
})
octoinv.registerItem('craft_plank', {
name = L.craft_plank,
icon = 'octoteam/icons/wood.png',
mass = 2,
volume = 3,
randomWeight = 0.1,
desc = descCraft,
})
octoinv.registerItem('craft_pallet', {
name = L.craft_pallet,
icon = 'octoteam/icons/pallet.png',
mass = 2,
volume = 5,
randomWeight = 0.1,
desc = descCraft,
})
octoinv.registerItem('craft_sheet', {
name = L.craft_sheet,
icon = 'octoteam/icons/metal_sheet.png',
mass = 1,
volume = 0.5,
randomWeight = 0.1,
desc = descCraft,
})
octoinv.registerItem('craft_spring', {
name = L.craft_spring,
icon = 'octoteam/icons/metal_spring.png',
mass = 0.1,
volume = 0.1,
randomWeight = 0.1,
desc = descCraft,
})
octoinv.registerItem('craft_pulley', {
name = L.craft_pulley,
icon = 'octoteam/icons/pulley.png',
mass = 0.2,
volume = 0.2,
randomWeight = 0.1,
desc = descCraft,
})
octoinv.registerItem('craft_cable', {
name = L.craft_cable,
icon = 'octoteam/icons/cable.png',
mass = 0.2,
volume = 0.2,
randomWeight = 0.1,
desc = descCraft,
})
octoinv.registerItem('craft_plug', {
name = L.craft_plug,
icon = 'octoteam/icons/plug.png',
mass = 0.1,
volume = 0.1,
randomWeight = 0.1,
desc = descCraft,
})
octoinv.registerItem('craft_socket', {
name = L.craft_socket,
icon = 'octoteam/icons/socket.png',
mass = 0.1,
volume = 0.2,
randomWeight = 0.1,
desc = descCraft,
})
octoinv.registerItem('craft_piston', {
name = L.craft_piston,
icon = 'octoteam/icons/piston.png',
mass = 0.5,
volume = 0.5,
randomWeight = 0.1,
desc = descCraft,
})
octoinv.registerItem('craft_engine', {
name = L.craft_engine,
icon = 'octoteam/icons/engine.png',
mass = 1,
volume = 0.5,
randomWeight = 0.1,
desc = descCraft,
})
octoinv.registerItem('craft_bulb', {
name = L.craft_bulb,
icon = 'octoteam/icons/bulb.png',
mass = 0.1,
volume = 0.3,
randomWeight = 0.1,
desc = descCraft,
})
octoinv.registerItem('craft_chip1', {
name = L.craft_chip1,
icon = 'octoteam/icons/chip1.png',
mass = 0.1,
volume = 0.1,
randomWeight = 0.1,
desc = descCraft,
})
octoinv.registerItem('craft_chip2', {
name = L.craft_chip2,
icon = 'octoteam/icons/chip2.png',
mass = 0.05,
volume = 0.05,
randomWeight = 0.1,
desc = descCraft,
})
octoinv.registerItem('craft_cnc', {
name = L.craft_cnc,
icon = 'octoteam/icons/machine_cnc.png',
mass = 0.15,
volume = 0.15,
randomWeight = 0.1,
desc = descCraft,
})
octoinv.registerItem('craft_relay', {
name = L.craft_relay,
icon = 'octoteam/icons/relay.png',
mass = 0.02,
volume = 0.02,
randomWeight = 0.1,
desc = descCraft,
})
octoinv.registerItem('craft_resistor', {
name = L.craft_resistor,
icon = 'octoteam/icons/resistor.png',
mass = 0.02,
volume = 0.02,
randomWeight = 0.1,
desc = descCraft,
})
octoinv.registerItem('craft_transistor', {
name = L.craft_transistor,
icon = 'octoteam/icons/transistor.png',
mass = 0.02,
volume = 0.02,
randomWeight = 0.1,
desc = descCraft,
})
octoinv.registerItem('craft_solar', {
name = L.craft_solar,
icon = 'octoteam/icons/solar_panel.png',
mass = 1,
volume = 1,
randomWeight = 0.1,
desc = descCraft,
})
octoinv.registerItem('craft_gauge', {
name = L.craft_gauge,
icon = 'octoteam/icons/speed.png',
mass = 0.5,
volume = 0.5,
randomWeight = 0.1,
desc = descCraft,
})
octoinv.registerItem('craft_scotch', {
name = L.craft_scotch,
icon = 'octoteam/icons/scotch.png',
mass = 0.1,
volume = 0.1,
randomWeight = 0.1,
desc = descCraft,
})
octoinv.registerItem('craft_glue', {
name = L.craft_glue,
icon = 'octoteam/icons/glue.png',
mass = 0.15,
volume = 0.15,
randomWeight = 0.1,
desc = descCraft,
})
octoinv.registerItem('craft_ink', {
name = L.craft_ink,
icon = 'octoteam/icons/ink.png',
mass = 0.1,
volume = 0.1,
randomWeight = 0.1,
desc = descCraft,
})
octoinv.registerItem('craft_paper', {
name = L.craft_paper,
icon = 'octoteam/icons/paper.png',
mass = 0.005,
volume = 0.01,
randomWeight = 0.1,
desc = descCraft,
})
octoinv.registerItem('craft_paper2', {
name = L.craft_paper2,
icon = 'octoteam/icons/paper_stack.png',
mass = 0.05,
volume = 0.05,
randomWeight = 0.1,
desc = descCraft,
})
octoinv.registerItem('saltpeter', {
name = L.saltpeter,
icon = 'octoteam/icons/saltpeter.png',
model = 'models/props_lab/chemjar01.mdl',
mass = 0.4,
volume = 0.3,
desc = descCraft,
})
octoinv.registerItem('gunpowder', {
name = L.gunpowder,
icon = 'octoteam/icons/gunpowder.png',
model = 'models/props_lab/chemjar01.mdl',
mass = 0.4,
volume = 0.3,
desc = descCraft,
})
------------------------------------------------
--
-- FUEL
--
------------------------------------------------
octoinv.registerItem('craft_fuel', {
name = L.craft_fuel,
icon = 'octoteam/icons/fuel_barrel.png',
mass = 1,
volume = 1,
randomWeight = 0.25,
desc = descFuel,
})
octoinv.registerItem('craft_gas', {
name = L.craft_gas,
icon = 'octoteam/icons/fuel_tank.png',
mass = 15,
volume = 15,
randomWeight = 0.25,
desc = descFuel,
})
------------------------------------------------
--
-- HYBRID RESOURCES
--
------------------------------------------------
octoinv.registerItem('craft_battery', {
name = L.craft_battery,
icon = 'octoteam/icons/battery_car.png',
mass = 3.5,
volume = 2.5,
nostack = true,
randomWeight = 0.5,
desc = descCraftFuel,
})
octoinv.registerItem('craft_battery2', {
name = L.craft_battery2,
icon = 'octoteam/icons/battery_charge.png',
mass = 0.15,
volume = 0.1,
nostack = false,
randomWeight = 0.5,
desc = descCraftFuel,
})
------------------------------------------------
--
-- TRASH
--
------------------------------------------------
octoinv.registerItem('craft_bottle', {
name = L.craft_bottle,
icon = 'octoteam/icons/bottle_empty.png',
mass = 0.2,
volume = 0.5,
randomWeight = 0.25,
desc = descCraft,
})
octoinv.registerItem('craft_glass', {
name = L.craft_glass,
icon = 'octoteam/icons/glass.png',
mass = 0.3,
volume = 0.3,
randomWeight = 0.25,
desc = descCraft,
})

View file

@ -0,0 +1,336 @@
------------------------------------------------
--
-- DARKRP STUFF
--
------------------------------------------------
octoinv.registerItem('money', {
name = L.money,
model = 'models/props/cs_assault/money.mdl',
icon = 'octoteam/icons/money_pack.png',
mass = 0.00001,
volume = 0.00001,
randomWeight = 0.001,
desc = L.desc_money,
})
local function isDriver(ply)
local seat = ply:GetVehicle()
if not IsValid(seat) or not IsValid(seat:GetParent()) then return false end
return seat:GetParent().GetDriverSeat and seat:GetParent():GetDriverSeat() == seat
end
local function equipWeapon(text, doSound)
return function(ply, item)
if doSound and ply:KeyDown(IN_WALK) then return end
local wep = ply:GetActiveWeapon()
if not IsValid(wep) or wep:GetClass() ~= 'dbg_hands' then return false, L.take_weapon end
if isDriver(ply) then return false, L.hands_busy_driver end
if not item:GetData('wepclass') then return false, L.unknown_type_weapon end
if ply:HasWeapon(item:GetData('wepclass')) then return false, L.you_already_take_weapon end
return text, item:GetData('icon'), function(ply, item)
local class = item:GetData('wepclass')
if octoinv.gunBlacklist[class] then
ply:Notify('warning', 'Это оружие запрещено использовать на сервере. Стоит рассказать администрации, как ты его заполучил')
return 1
end
local wep = ents.Create(class)
if not wep:IsValid() then return 0 end
if not wep:IsWeapon() then wep:Remove() return 0 end
if not hook.Call("PlayerCanPickupWeapon", GAMEMODE, ply, wep) then return 0 end
local ammoT = wep:GetPrimaryAmmoType()
local ammo = ply:GetAmmoCount(ammoT)
wep:Remove()
local wep = ply:Give(class)
wep:SetClip1(item:GetData('clip1') or 0)
wep:SetClip2(item:GetData('clip2') or -1)
wep:SetShouldPlayPickupSound(false)
wep.WorldModel = item:GetData('model') or wep.WorldModel
wep:Initialize()
ammo = math.Clamp(ammo + (item:GetData('ammoadd') or 0), 0, wep.Primary.ClipSize * 3)
ply:SetAmmo(ammo, ammoT)
wep.itemData = item:Export()
wep.itemCont = item:GetParent().id
wep.civil = true
if item:GetData('expire') then
wep.expireId = 'octoinv.expireWep' .. octolib.string.uuid()
timer.Create(wep.expireId, item:GetData('expire') - os.time(), 1, function()
if not IsValid(ply) then return end
local active = ply:GetActiveWeapon() == wep
if IsValid(wep) then
wep:Remove()
ply:Notify('У оружия истек срок годности')
end
if active then ply:ConCommand('lastinv') end
end)
end
timer.Simple(0, function()
if not doSound then ply.silentEquip = true end
ply:SelectWeapon(class)
ply.silentEquip = nil
end)
return 1
end
end
end
octoinv.registerItem('weapon', {
name = L.weapons,
model = 'models/weapons/w_pist_glock18.mdl',
icon = 'octoteam/icons/gun_pistol.png',
mass = 1,
volume = 1,
nostack = true,
desc = L.desc_weapon,
leftField = 'clip1',
leftMaxField = 'ammoadd',
nodespawn = true,
use = {
equipWeapon(L.take_in_hand, true),
equipWeapon(L.silient_take_in_hand, false),
},
})
octoinv.registerItem('ammo', {
name = L.item_ammo,
model = 'models/Items/BoxSRounds.mdl',
icon = 'octoteam/icons/gun_bullet2.png',
mass = 0.01,
volume = 1,
nostack = true,
nodespawn = true,
randomWeight = 0.25,
desc = L.desc_item_ammo,
use = {
function(ply, item)
local t = item:GetData('ammotype')
if not t then return false, L.unknown_type_ammo end
local wep = ply:GetActiveWeapon()
if not IsValid(wep) or wep.Primary.Ammo ~= t then return false, 'Нужно держать совместимое оружие' end
if wep:Ammo1() >= wep.Primary.ClipSize * 3 then return false, 'Это оружие максимально заряжено' end
return L.charge, 'octoteam/icons/gun_bullet.png', function(ply, item)
if not IsValid(wep) or wep.Primary.Ammo ~= t then return end
if wep:Ammo1() >= wep.Primary.ClipSize * 3 then return end
local amount = math.Clamp(item:GetData('ammocount') or 1, 0, wep.Primary.ClipSize * 3 - wep:Ammo1())
ply:GiveAmmo(amount, t)
ply:EmitSound('items/itempickup.wav', 60)
return 1
end
end,
},
})
local function eat(ply, item, part, partText)
if ply:GetNetVar('Energy') == 100 then return false, L.max_hunger_hint end
local name = item:GetData('drink') and L.drink or L.eat
local icon = item:GetData('drink') and 'octoteam/icons/bottle.png' or 'octoteam/icons/food_meal2.png'
return name .. partText, icon, function(ply, item)
if ply.eating then
ply:Notify('warning', 'Поспешишь - людей насмешишь, как говорится. Не торопись')
return
end
local addEnergy = math.floor(item:GetData('energy') * part)
ply.eating = true
ply:DelayedAction('eating', 'Употребление: ' .. item:GetData('name'), {
time = addEnergy / 10,
check = function() return ply.inv and tobool(ply:HasItem(item)) and not ply:IsSprinting() end,
succ = function()
local newVal = math.Clamp((ply:GetNetVar('Energy') or 100) + addEnergy, 0, item:GetData('maxenergy'))
ply.eating = nil
if newVal > ply:GetNetVar('Energy') then
ply:SetLocalVar('Energy', newVal)
end
ply:EmitSound('physics/wood/wood_strain' .. math.random(1,2) .. '.wav', 65)
local mul = 1 - part
if not item:GetData('leftMax') then item:SetData('leftMax', item:GetData('energy')) end
item:SetData('energy', math.floor(item:GetData('energy') * mul))
item:SetData('mass', math.max(item:GetData('mass') * mul, 0.05))
item:SetData('volume', math.max(item:GetData('volume') * mul, 0.05))
if item:GetData('energy') <= 0 and not item:GetData('trash') then item:Remove() end
end,
fail = function()
ply.eating = nil
end,
}, {
time = 1.5,
inst = true,
action = function()
ply:EmitSound('physics/plastic/plastic_box_strain' .. math.random(1,3) .. '.wav', 60, 150)
ply:DoAnimation(ACT_GMOD_GESTURE_BECON)
end
})
return 0
end
end
octoinv.registerItem('food', {
name = L.item_food,
model = 'models/props_junk/garbage_takeoutcarton001a.mdl',
icon = 'octoteam/icons/food_meal2.png',
mass = 0.2,
volume = 0.25,
nostack = true,
randomWeight = 0.33,
desc = L.desc_item_food,
energy = 0,
maxenergy = 100,
leftField = 'energy',
leftMaxField = 'energy',
use = {
function(ply, item) if item:GetData('energy') > 0 then return eat(ply, item, 1, ' полностью') end end,
function(ply, item) if item:GetData('energy') >= 10 then return eat(ply, item, 0.5, ' половину') end end,
function(ply, item) if item:GetData('energy') >= 20 then return eat(ply, item, 0.25, ' немного') end end,
},
})
octoinv.registerItem('armor', {
name = L.armor,
model = 'models/combine_vests/bluevest.mdl',
icon = 'octoteam/icons/armor.png',
mass = 3,
volume = 5,
nostack = true,
nodespawn = true,
desc = L.desc_armor2,
use = {
function(ply, item)
local amount = item:GetData('armor') or 12
if ply:Armor() >= amount then return false, L.you_already_have_armor end
return L.wear, 'octoteam/icons/armor.png', function(ply, item)
ply.armorItem = item:Export()
ply.armorItem.armor = amount
ply:SetArmor(amount)
ply:SetLocalVar('armor', amount)
ply:EmitSound('npc/combine_soldier/gear3.wav', 55)
return 1
end
end,
},
})
octoinv.registerItem('radio', {
name = L.talkie,
model = 'models/handfield_radio.mdl',
icon = 'octoteam/icons/radio.png',
mass = 1,
volume = 0.8,
nostack = true,
nodespawn = true,
desc = L.desc_talkie,
})
octoinv.registerItem('lockpick', {
name = L.gun_lockpick,
model = 'models/props_c17/tools_pliers01a.mdl',
icon = 'octoteam/icons/lockpick.png',
mass = 0.3,
volume = 0.25,
randomWeight = 0.5,
nodespawn = true,
desc = L.desc_lockpick,
})
octoinv.registerItem('lockpick_broken', {
name = L.gun_broken_lockpick,
model = 'models/props_c17/tools_pliers01a.mdl',
icon = 'octoteam/icons/lockpick_broken.png',
mass = 0.3,
volume = 0.25,
randomWeight = 0.5,
nodespawn = true,
desc = L.desc_broken_lockpick,
})
octoinv.registerItem('throwable', {
name = 'Метательный предмет',
icon = 'octoteam/icons/dynamite.png',
mass = 0.5,
volume = 0.4,
usesLeft = 5,
model = 'models/Items/BoxBuckshot.mdl',
desc = '',
nodespawn = true,
nostack = true,
gc = 'ent_dbg_throwable',
leftField = 'usesLeft',
leftMaxField = 'usesLeft',
use = {
function()
return 'Сильно метнуть', 'octoteam/icons/explosion.png', function(ply, item)
ply:DoAnimation(ACT_GMOD_GESTURE_ITEM_THROW)
local gc = item:GetData('gc')
if not gc then return end
timer.Simple(0.88, function()
local ent = ents.Create(item:GetData('gc'))
if not IsValid(ent) then return end
ent:Throw(ply, 1)
end)
if not item:GetData('leftMax') then item:SetData('leftMax', item:GetData('usesLeft')) end
item:SetData('usesLeft', (item:GetData('usesLeft') or 5) - 1)
item:SetData('mass', 0.5 * item:GetData('usesLeft'))
item:SetData('volume', 0.4 * item:GetData('usesLeft'))
return item:GetData('usesLeft') <= 0 and 1 or 0
end
end,
function()
return 'Слабо метнуть', 'octoteam/icons/explosion.png', function(ply, item)
ply:DoAnimation(ACT_GMOD_GESTURE_ITEM_PLACE)
local gc = item:GetData('gc')
if not gc then return end
timer.Simple(0.88, function()
local ent = ents.Create(item:GetData('gc'))
if not IsValid(ent) then return end
ent:Throw(ply, 0.5)
end)
if not item:GetData('leftMax') then item:SetData('leftMax', item:GetData('usesLeft')) end
item:SetData('usesLeft', (item:GetData('usesLeft') or 5) - 1)
item:SetData('mass', 0.5 * item:GetData('usesLeft'))
item:SetData('volume', 0.4 * item:GetData('usesLeft'))
return item:GetData('usesLeft') <= 0 and 1 or 0
end
end,
function()
return 'Положить', 'octoteam/icons/explosion.png', function(ply, item)
ply:DoAnimation(ACT_GMOD_GESTURE_ITEM_PLACE)
timer.Simple(0.88, function()
local ent = ents.Create(item:GetData('gc'))
if not IsValid(ent) then return end
ent:Throw(ply, 0.1)
timer.Simple(0.75, function()
if not (IsValid(ent) and IsValid(ent:GetPhysicsObject())) then return end
local phys = ent:GetPhysicsObject()
phys:SetVelocity(0)
phys:Sleep()
end)
end)
if not item:GetData('leftMax') then item:SetData('leftMax', item:GetData('usesLeft')) end
item:SetData('usesLeft', (item:GetData('usesLeft') or 5) - 1)
item:SetData('mass', 0.5 * item:GetData('usesLeft'))
item:SetData('volume', 0.4 * item:GetData('usesLeft'))
return item:GetData('usesLeft') <= 0 and 1 or 0
end
end,
},
})

View file

@ -0,0 +1,209 @@
------------------------------------------------
--
-- DRUGS
--
------------------------------------------------
local function useDrugFunction(buffName, buffLength, sound)
return function()
return L.drugs_use, 'octoteam/icons/drug.png', function(ply)
if ply:HasBuff('Overdose') then
ply:Notify('warning', L.overdose_hint)
return 0
end
if ply.bleeding then
ply:Notify('warning', 'Ты при смерти')
return 0
end
ply:AddBuff(buffName, buffLength)
ply:EmitSound(sound, 75, 100)
return 1
end
end
end
octoinv.registerItem('drug_vitalex', {
name = L.vitalex,
icon = 'octoteam/icons/pills2.png',
mass = 0.2,
volume = 0.2,
nostack = true,
nodespawn = true,
model = 'models/props_lab/jar01b.mdl',
desc = L.description_vitalex,
use = { useDrugFunction('HealthRecovery', 45, 'npc/barnacle/barnacle_gulp2.wav') },
})
octoinv.registerItem('drug_painkiller', {
name = L.painkiller,
icon = 'octoteam/icons/medicine_morphy_pen.png',
mass = 0.1,
volume = 0.2,
nostack = true,
nodespawn = true,
model = 'models/props_lab/jar01b.mdl',
desc = L.description_painkiller,
use = {
function()
return L.drugs_use, 'octoteam/icons/drug.png', function(ply)
if ply:HasBuff('Overdose') then
ply:Notify('warning', L.overdose_hint)
return 0
end
ply:AddBuff('Painkillers', 80)
ply:SetHealth(math.min(ply:Health() + 5, ply:GetMaxHealth()))
ply:EmitSound('npc/barnacle/barnacle_gulp2.wav', 75, 100)
return 1
end
end,
},
})
octoinv.registerItem('drug_relaxant', {
name = L.relaxant,
icon = 'octoteam/icons/drug.png',
mass = 0.1,
volume = 0.2,
nostack = true,
nodespawn = true,
model = 'models/props_lab/jar01b.mdl',
desc = L.description_relaxant,
use = { useDrugFunction('Muscle Relaxant', 80, 'npc/barnacle/barnacle_gulp2.wav') },
})
octoinv.registerItem('drug_vampire', {
name = L.vampire,
icon = 'octoteam/icons/drug.png',
mass = 0.1,
volume = 0.2,
nostack = true,
nodespawn = true,
model = 'models/props_lab/jar01b.mdl',
desc = L.description_vampire,
use = { useDrugFunction('Vampire', 120, 'npc/barnacle/barnacle_gulp2.wav') },
})
octoinv.registerItem('drug_dextradose', {
name = L.dextradose,
icon = 'octoteam/icons/drug.png',
mass = 0.1,
volume = 0.2,
nostack = true,
nodespawn = true,
model = 'models/cocn.mdl',
desc = L.description_dextradose,
use = { useDrugFunction('Dextradose', 120, 'player/suit_sprint.wav') },
})
octoinv.registerItem('drug_roids', {
name = L.roids,
icon = 'octoteam/icons/drug.png',
mass = 0.1,
volume = 0.2,
nostack = true,
nodespawn = true,
model = 'models/cocn.mdl',
desc = L.description_roids,
use = { useDrugFunction('Steroids', 80, 'player/suit_sprint.wav') },
})
octoinv.registerItem('drug_bouncer', {
name = L.cocaine,
icon = 'octoteam/icons/drug.png',
mass = 0.1,
volume = 0.2,
nostack = true,
nodespawn = true,
model = 'models/cocn.mdl',
desc = L.description_cocaine,
use = { useDrugFunction('DoubleJump', 80, 'player/suit_sprint.wav') },
})
octoinv.registerItem('drug_antitoxin', {
name = L.antitoxin,
icon = 'octoteam/icons/medicine_antidote_pen.png',
mass = 0.1,
volume = 0.2,
nostack = true,
nodespawn = true,
model = 'models/props_lab/jar01b.mdl',
desc = L.description_antitoxin,
use = {
function(ply, item)
return L.drugs_use, 'octoteam/icons/drug.png', function(ply, item)
if ply:HasBuff('Overdose') then
ply:Notify('warning', L.overdose_hint)
return 0
end
ply:ClearBuffs()
ply:MoveModifier('drug', nil)
ply:MoveModifier('drug2', nil)
ply:EmitSound('npc/barnacle/barnacle_gulp2.wav', 75, 100)
return 1
end
end,
},
})
octoinv.registerItem('drug_weed', {
name = L.marijuana,
icon = 'octoteam/icons/drugs_marijuana.png',
mass = 0.2,
volume = 0.2,
nostack = true,
nodespawn = true,
model = 'models/katharsmodels/contraband/zak_wiet/zak_wiet.mdl',
desc = L.description_marijuana,
use = { useDrugFunction('Weed', 35, 'player/suit_sprint.wav') },
})
octoinv.registerItem('drug_pingaz', {
name = L.pingaz,
icon = 'octoteam/icons/drugs_methamphetamine.png',
mass = 0.1,
volume = 0.2,
nostack = true,
nodespawn = true,
model = 'models/katharsmodels/contraband/metasync/blue_sky.mdl',
desc = L.description_pingaz,
use = { useDrugFunction('Pingaz', 120, 'player/suit_sprint.wav') },
})
octoinv.registerItem('drug_preserver', {
name = L.preserver,
icon = 'octoteam/icons/medicine_adrenaline_pen.png',
mass = 0.1,
volume = 0.2,
nostack = true,
nodespawn = true,
model = 'models/katharsmodels/syringe_out/syringe_out.mdl',
desc = L.description_preserver,
use = { useDrugFunction('Preserver', 120, 'ambient/levels/canals/toxic_slime_gurgle8.wav') },
})
octoinv.registerItem('drug_meth', {
name = L.steroids,
icon = 'octoteam/icons/drug.png',
mass = 0.1,
volume = 0.2,
nostack = true,
nodespawn = true,
model = 'models/katharsmodels/syringe_out/syringe_out.mdl',
desc = L.description_steroids,
use = {
function(ply, item)
do return false, L.temporary_disable end -- TEMP
if ply:HasBuff('Overdose') then return false, L.overdose_hint end
return L.drugs_use, 'octoteam/icons/drug.png', function(ply, item)
ply:AddBuff('Meth', 120)
ply:EmitSound('ambient/levels/canals/toxic_slime_gurgle8.wav', 75, 100)
return 1
end
end,
},
})

View file

@ -0,0 +1,525 @@
------------------------------------------------
--
-- GUNS THAT CANNOT BE CONVERTED TO ITEMS
--
------------------------------------------------
octoinv.gunBlacklist = octolib.array.toKeys{
'weapon_357','weapon_pistol','weapon_bugbait','weapon_crossbow','weapon_crowbar','weapon_frag',
'weapon_physcannon','weapon_ar2','weapon_rpg','weapon_slam','weapon_shotgun','weapon_smg1','weapon_stunstick',
'manhack_welder','weapon_medkit','weapon_simrepair','weapon_simremote','med_kit','stunstick','dbg_dog',
'weapon_cuff_police','dbg_shield','dbg_punisher','weapon_keypadchecker','lightning_gun','sf2_tool', 'weapon_flashlight_uv', 'weapon_fire_hose'
}
local descCraft = L.desc_gun_Craft
local descBP = L.desc_gun_BP
------------------------------------------------
--
-- GUNS MATERIALS
--
------------------------------------------------
octoinv.registerItem('craft_shutter', {
name = L.gun_ing_shutter,
icon = 'octoteam/icons/gun_part_shutter.png',
mass = 0.2,
volume = 0.2,
randomWeight = 0.5,
desc = descCraft,
})
octoinv.registerItem('craft_barrel', {
name = L.gun_ing_barrel,
icon = 'octoteam/icons/gun_part_barrel.png',
mass = 0.25,
volume = 0.25,
randomWeight = 0.5,
desc = descCraft,
})
octoinv.registerItem('craft_grip', {
name = L.gun_ing_grip,
icon = 'octoteam/icons/gun_part_handle.png',
mass = 0.15,
volume = 0.15,
randomWeight = 0.5,
desc = descCraft,
})
octoinv.registerItem('craft_sight', {
name = L.crosshair,
icon = 'octoteam/icons/gun_part_sight.png',
mass = 0.15,
volume = 0.15,
randomWeight = 0.5,
desc = descCraft,
})
octoinv.registerItem('craft_aim', {
name = L.gun_ing_sight,
icon = 'octoteam/icons/gun_part_aim.png',
mass = 0.05,
volume = 0.05,
randomWeight = 0.5,
desc = descCraft,
})
octoinv.registerItem('craft_drummer', {
name = L.gun_ing_aim,
icon = 'octoteam/icons/gun_part_drummer.png',
mass = 0.1,
volume = 0.1,
randomWeight = 0.5,
desc = descCraft,
})
octoinv.registerItem('craft_trigger', {
name = L.gun_ing_drummer,
icon = 'octoteam/icons/gun_part_trigger.png',
mass = 0.03,
volume = 0.03,
randomWeight = 0.5,
desc = descCraft,
})
octoinv.registerItem('craft_stopper', {
name = L.gun_ing_trigger,
icon = 'octoteam/icons/gun_part_stopper.png',
mass = 0.08,
volume = 0.08,
randomWeight = 0.5,
desc = descCraft,
})
octoinv.registerItem('craft_clip', {
name = L.shop,
icon = 'octoteam/icons/gun_riflemag.png',
mass = 0.4,
volume = 0.3,
randomWeight = 0.5,
desc = descCraft,
})
octoinv.registerItem('craft_silencer', {
name = L.silencer,
icon = 'octoteam/icons/gun_part_silencer.png',
mass = 0.5,
volume = 0.5,
randomWeight = 0.5,
desc = descCraft,
})
------------------------------------------------
--
-- GUNS BLUEPRINTS
--
------------------------------------------------
octoinv.registerItem('bp_shutter', {
name = L.gun_ing_shutter,
icon = 'octoteam/icons/microsd.png',
mass = 0.02,
volume = 0.02,
randomWeight = 0.1,
desc = descBP,
})
octoinv.registerItem('bp_barrel', {
name = L.gun_ing_barrel,
icon = 'octoteam/icons/microsd.png',
mass = 0.02,
volume = 0.02,
randomWeight = 0.1,
desc = descBP,
})
octoinv.registerItem('bp_grip', {
name = L.gun_ing_grip,
icon = 'octoteam/icons/microsd.png',
mass = 0.02,
volume = 0.02,
randomWeight = 0.1,
desc = descBP,
})
-- not use in prod
-- octoinv.registerItem('bp_sight', {
-- name = 'Прицел',
-- icon = 'octoteam/icons/microsd.png',
-- mass = 0.02,
-- volume = 0.02,
-- randomWeight = 0.1,
-- desc = descBP,
-- })
octoinv.registerItem('bp_aim', {
name = L.gun_ing_sight,
icon = 'octoteam/icons/microsd.png',
mass = 0.02,
volume = 0.02,
randomWeight = 0.1,
desc = descBP,
})
octoinv.registerItem('bp_drummer', {
name = L.gun_ing_aim,
icon = 'octoteam/icons/microsd.png',
mass = 0.02,
volume = 0.02,
randomWeight = 0.1,
desc = descBP,
})
octoinv.registerItem('bp_trigger', {
name = L.gun_ing_drummer,
icon = 'octoteam/icons/microsd.png',
mass = 0.02,
volume = 0.02,
randomWeight = 0.1,
desc = descBP,
})
octoinv.registerItem('bp_stopper', {
name = L.gun_ing_trigger,
icon = 'octoteam/icons/microsd.png',
mass = 0.02,
volume = 0.02,
randomWeight = 0.1,
desc = descBP,
})
octoinv.registerItem('bp_clip', {
name = L.shop,
icon = 'octoteam/icons/microsd.png',
mass = 0.02,
volume = 0.02,
randomWeight = 0.1,
desc = descBP,
})
------------------------------------------------
--
-- OTHER BLUEPRINTS
--
------------------------------------------------
octoinv.registerItem('bp_screw', {
name = L.craft_screw,
icon = 'octoteam/icons/microsd.png',
mass = 0.02,
volume = 0.02,
randomWeight = 0.1,
desc = descBP,
})
octoinv.registerItem('bp_screw2', {
name = L.craft_screw2,
icon = 'octoteam/icons/microsd.png',
mass = 0.02,
volume = 0.02,
randomWeight = 0.1,
desc = descBP,
})
octoinv.registerItem('bp_screwnut', {
name = L.craft_screwnut,
icon = 'octoteam/icons/microsd.png',
mass = 0.02,
volume = 0.02,
randomWeight = 0.1,
desc = descBP,
})
octoinv.registerItem('bp_nail', {
name = L.craft_nail,
icon = 'octoteam/icons/microsd.png',
mass = 0.02,
volume = 0.02,
randomWeight = 0.1,
desc = descBP,
})
octoinv.registerItem('bp_spring', {
name = L.craft_spring,
icon = 'octoteam/icons/microsd.png',
mass = 0.02,
volume = 0.02,
randomWeight = 0.1,
desc = descBP,
})
octoinv.registerItem('bp_pulley', {
name = L.craft_pulley,
icon = 'octoteam/icons/microsd.png',
mass = 0.02,
volume = 0.02,
randomWeight = 0.1,
desc = descBP,
})
octoinv.registerItem('bp_piston', {
name = L.craft_piston,
icon = 'octoteam/icons/microsd.png',
mass = 0.02,
volume = 0.02,
randomWeight = 0.1,
desc = descBP,
})
octoinv.registerItem('bp_bulb', {
name = L.craft_bulb,
icon = 'octoteam/icons/microsd.png',
mass = 0.02,
volume = 0.02,
randomWeight = 0.1,
desc = descBP,
})
octoinv.registerItem('bp_gauge', {
name = L.craft_gauge,
icon = 'octoteam/icons/microsd.png',
mass = 0.02,
volume = 0.02,
randomWeight = 0.1,
desc = descBP,
})
------------------------------------------------
--
-- GUN ITEM DATA BY GUN CLASSES
--
------------------------------------------------
octoinv.gunsItemData = {
weapon_octo_knife = {
name = L.knife,
model = 'models/weapons/w_knife_t.mdl',
icon = 'octoteam/icons/knife.png',
mass = 0.8,
volume = 0.5,
},
weapon_octo_axe = {
name = L.axe,
model = 'models/weapons/HL2meleepack/w_axe.mdl',
icon = 'octoteam/icons/gun_axe.png',
mass = 2,
volume = 1.5,
},
weapon_octo_shovel = {
name = L.shovel,
model = 'models/weapons/HL2meleepack/w_shovel.mdl',
icon = 'octoteam/icons/shovel.png',
mass = 2,
volume = 1.5,
},
weapon_octo_hook = {
name = L.hook,
model = 'models/weapons/HL2meleepack/w_hook.mdl',
icon = 'octoteam/icons/crowbar.png',
mass = 3,
volume = 2,
},
keypad_cracker = {
name = L.keypad_cracker,
model = 'models/weapons/w_c4.mdl',
icon = 'octoteam/icons/keypad_cracker.png',
mass = 2,
volume = 1.5,
},
weapon_octo_glock = {
name = 'Glock',
model = 'models/weapons/w_pist_glock18.mdl',
icon = 'octoteam/icons/gun_pistol.png',
mass = 1.5,
volume = 1.5,
},
weapon_octo_usp = {
name = 'USP',
model = 'models/weapons/w_pist_usp.mdl',
icon = 'octoteam/icons/gun_pistol.png',
mass = 2.5,
volume = 2.5,
},
weapon_octo_usps = {
name = 'USP-S',
model = 'models/weapons/w_pist_usp_silencer.mdl',
icon = 'octoteam/icons/gun_pistol.png',
mass = 3,
volume = 3,
},
weapon_octo_p228 = {
name = 'P228',
model = 'models/weapons/w_pist_p228.mdl',
icon = 'octoteam/icons/gun_pistol.png',
mass = 2,
volume = 2,
},
weapon_octo_fiveseven = {
name = 'FiveseveN',
model = 'models/weapons/w_pist_fiveseven.mdl',
icon = 'octoteam/icons/gun_pistol.png',
mass = 2,
volume = 2,
},
weapon_octo_deagle = {
name = 'Desert Eagle',
model = 'models/weapons/w_pist_deagle.mdl',
icon = 'octoteam/icons/gun_pistol.png',
mass = 4,
volume = 3,
},
weapon_octo_357 = {
name = 'Colt .357',
model = 'models/weapons/w_357.mdl',
icon = 'octoteam/icons/gun_pistol.png',
mass = 3.5,
volume = 3,
},
weapon_octo_dualelites = {
name = 'Dual Elites',
model = 'models/weapons/w_pist_elite.mdl',
icon = 'octoteam/icons/gun_pistol.png',
mass = 4,
volume = 4,
},
weapon_octo_mp5 = {
name = 'MP5',
model = 'models/weapons/w_smg_mp5.mdl',
icon = 'octoteam/icons/gun_smg.png',
mass = 4.5,
volume = 4.5,
},
weapon_octo_ump45 = {
name = 'UMP45',
model = 'models/weapons/w_smg_ump45.mdl',
icon = 'octoteam/icons/gun_smg.png',
mass = 4.3,
volume = 4.3,
},
weapon_octo_mac10 = {
name = 'MAC10',
model = 'models/weapons/w_smg_mac10.mdl',
icon = 'octoteam/icons/gun_smg.png',
mass = 3,
volume = 3,
},
weapon_octo_tmp = {
name = 'TMP',
model = 'models/weapons/w_smg_tmp.mdl',
icon = 'octoteam/icons/gun_smg.png',
mass = 4.8,
volume = 4.8,
},
weapon_octo_m3 = {
name = 'M3',
model = 'models/weapons/w_shot_m3super90.mdl',
icon = 'octoteam/icons/gun_shotgun.png',
mass = 6.5,
volume = 6.5,
},
weapon_octo_p90 = {
name = 'P90',
model = 'models/weapons/w_smg_p90.mdl',
icon = 'octoteam/icons/gun_smg.png',
mass = 5,
volume = 5,
},
weapon_octo_galil = {
name = 'Galil',
model = 'models/weapons/w_rif_galil.mdl',
icon = 'octoteam/icons/gun_rifle.png',
mass = 6.45,
volume = 6.45,
},
weapon_octo_scout = {
name = 'Scout',
model = 'models/weapons/w_snip_scout.mdl',
icon = 'octoteam/icons/gun_sniper.png',
mass = 6.3,
volume = 6.3,
},
weapon_octo_famas = {
name = 'FAMAS',
model = 'models/weapons/w_rif_famas.mdl',
icon = 'octoteam/icons/gun_rifle.png',
mass = 6.6,
volume = 6.6,
},
weapon_octo_xm1014 = {
name = 'XM1014',
model = 'models/weapons/w_shot_xm1014.mdl',
icon = 'octoteam/icons/gun_shotgun.png',
mass = 6.4,
volume = 6.4,
},
weapon_octo_ak = {
name = 'AK',
model = 'models/weapons/w_rif_ak47.mdl',
icon = 'octoteam/icons/gun_rifle.png',
mass = 6.4,
volume = 6.4,
},
weapon_octo_m4a1 = {
name = 'M4A1',
model = 'models/weapons/w_rif_m4a1.mdl',
icon = 'octoteam/icons/gun_rifle.png',
mass = 6.7,
volume = 6.7,
},
weapon_octo_aug = {
name = 'AUG',
model = 'models/weapons/w_rif_aug.mdl',
icon = 'octoteam/icons/gun_sniper.png',
mass = 7.6,
volume = 7.6,
},
weapon_octo_sg552 = {
name = 'SG552',
model = 'models/weapons/w_rif_sg552.mdl',
icon = 'octoteam/icons/gun_sniper.png',
mass = 9.4,
volume = 9.4,
},
weapon_octo_awp = {
name = 'AWP',
model = 'models/weapons/w_snip_awp.mdl',
icon = 'octoteam/icons/gun_sniper.png',
mass = 9.1,
volume = 9.1,
},
weapon_octo_g3sg1 = {
name = 'G3SG1',
model = 'models/weapons/w_snip_g3sg1.mdl',
icon = 'octoteam/icons/gun_sniper.png',
mass = 8.7,
volume = 8.7,
},
weapon_octo_sg550 = {
name = 'SG550',
model = 'models/weapons/w_snip_sg550.mdl',
icon = 'octoteam/icons/gun_sniper.png',
mass = 8.6,
volume = 8.6,
},
weapon_octo_m249 = {
name = 'M249',
model = 'models/weapons/w_mach_m249para.mdl',
icon = 'octoteam/icons/gun_rifle.png',
mass = 15,
volume = 12.3,
},
}
-- some data was snipped to shorten code, let's fill it
for k,v in pairs(octoinv.gunsItemData) do
v.wepclass = v.wepclass or k
v.ammoadd = v.ammoadd or 0
v.clip1 = v.clip1 or 0
v.clip2 = v.clip2 or 0
-- local swep = weapons.GetStored(v.wepclass)
-- if swep then
-- v.leftMax = swep.Primary.ClipSize
-- end
end

View file

@ -0,0 +1,90 @@
local tastes = {
{'арбуз', 'банан', 'виноград', 'вишня', 'груша', 'ежевика', 'зеленое яблоко', 'ириска', 'клубника', 'мармелад', 'мед', 'Тутти-фрутти', 'шоколад'},
{'баклажан', 'бекон', 'брокколи', 'грейпфрут', 'гренка', 'гриб', 'жареные бобы', 'печенка', 'пицца', 'помидор', 'попкорн', 'рыба', 'картофельное пюре', 'кетчуп', 'кофе', 'сосиска', 'тост', 'тыква'},
{'газонная трава', 'грязный носок', 'грязь', 'дождевой червь', 'перепревшая капуста', 'рвота', 'сопли', 'лук', 'мыло', 'тухлое яйцо', 'ушная сера', 'хрен'},
}
local reactions = {
{'Вкуснятина!', 'Аж тает во рту!', 'Ням-ням!', 'М-м-м-м-м!', 'Повезло!'},
{'Ну, сойдет', 'Эм, ну ладно', 'Ну-у-у-у...', 'Ну, хоть так', 'Могло быть и хуже'},
{'Фу, гадость какая!', 'О боже...', 'Тьфу, нужно чем-то запить!', 'Черт, как это можно есть?!', 'Фу-у-у-у-у...'},
}
local msg = 'На вкус как... %s. %s'
octoinv.registerItem('h20_sweets', {
name = 'Загадочная конфета',
icon = octolib.icons.color('food_doughnut'),
desc = 'Конфета со случайным вкусом. С каким? Не узнаешь, пока не попробуешь!\n\nВосстанавливает случайное количество сытости, в том числе отрицательное',
mass = 0.01,
volume = 0.01,
use = {
function()
return 'Съесть', octolib.icons.color('food_meal2'), function(ply, item)
if ply.eating then
ply:Notify('warning', 'Поспешишь - людей насмешишь, как говорится. Не торопись')
return
end
ply.eating = true
ply:DelayedAction('eating', 'Употребление: ' .. item:GetData('name'), {
time = 2,
check = function() return ply.inv and tobool(ply:HasItem(item)) and not ply:IsSprinting() end,
succ = function()
ply.eating = nil
local add = math.random(-30, 50)
if add >= 25 then
ply:Notify('hint', msg:format(tastes[1][math.random(#tastes[1])], reactions[1][math.random(#reactions[1])]))
elseif add >= 0 then
ply:Notify('rp', msg:format(tastes[2][math.random(#tastes[2])], reactions[2][math.random(#reactions[2])]))
else
ply:Notify('warning', msg:format(tastes[3][math.random(#tastes[3])], reactions[3][math.random(#reactions[3])]))
end
local newVal = math.Clamp(ply:GetNetVar('Energy', 100) + add, 0, 100)
ply:SetHunger(newVal)
item:SetData('amount', item:GetData('amount') - 1)
if item:GetData('amount') <= 0 then item:Remove() end
end,
fail = function()
ply.eating = nil
end,
}, {
time = 1.5,
inst = true,
action = function()
ply:EmitSound('physics/plastic/plastic_box_strain' .. math.random(1,3) .. '.wav', 60, 150)
ply:DoAnimation(ACT_GMOD_GESTURE_BECON)
end
})
end
end,
}
})
-- octoinv.registerItem('h20_case', {
-- name = 'Загадочная коробочка',
-- icon = octolib.icons.color('gift_question'),
-- desc = 'Так и хочется ее открыть!',
-- mass = 1,
-- volume = 1,
-- nostack = true,
-- use = {
-- function(_, item)
-- if not item.cid then return end
-- local case = halloween.cases[item.cid]
-- if not case or not case.items then return end
-- return 'Открыть', octolib.icons.color('box3_open'), function(ply, item)
-- local id = octolib.array.randomWeighted(case.items)
-- local caseItem = halloween.caseItems[id]
-- if not caseItem or not caseItem.give then
-- ErrorNoHalt(id .. ' was not registered correctly')
-- end
-- timer.Simple(0, function() caseItem.give(ply, item:GetParent()) end)
-- ply:Notify(('Ты открываешь загадочную коробочку, а в ней %s!'):format(caseItem.name))
-- octologs.createLog()
-- :Add(octologs.ply(ply), ' got ', octologs.string(caseItem.name), ' from Halloween case')
-- :Save()
-- return 1
-- end
-- end,
-- }
-- })

View file

@ -0,0 +1,110 @@
local doll = {
icon = 'octoteam/icons/bust.png',
mass = 0.15,
volume = 0.05,
model = 'models/props_lab/huladoll.mdl',
}
local trash = {
-- {chance, {class, amount or data}}
{500, {'craft_screw2', 5}},
{500, {'craft_paper', 8}},
{500, {'craft_bottle', 1}},
{500, {'craft_screwnut', 3}},
{500, {'craft_nail', 4}},
{500, {'craft_plank', 1}},
{500, {'craft_spring', 3}},
{500, {'craft_bulb', 2}},
{500, {'tool_hammer', 1}},
{500, {'tool_wrench', 1}},
{250, {'tool_foodcont', 3}},
{250, {'money', 50}},
{200, {'craft_chip2', 1}},
{200, {'money', 100}},
{160, {'craft_battery', 1}},
{160, {'craft_cnc', 1}},
{160, {'food', {
name = L.trash_food_wrap,
energy = 25,
maxenergy = 75,
}}},
{160, {'food', {
name = L.trash_food_donut,
energy = 20,
maxenergy = 75,
}}},
{160, {'food', {
name = L.trash_food_sandwich,
energy = 15,
maxenergy = 75,
}}},
{160, {'food', {
name = L.trash_food_pizza,
energy = 20,
maxenergy = 75,
}}},
{160, {'food', {
name = L.trash_food_pie,
energy = 15,
maxenergy = 75,
}}},
{135, {'tool_pastrybag', 1}},
{105, {'tool_scoop', 1}},
{100, {'tool_coffeepot', 1}},
{100, {'drug_booze', 1}},
{100, {'ore_iron', 1}},
{100, {'tool_craft', 1}},
{75, {'money', 500}},
{75, {'craft_ink', 1}},
{70, {'tool_teapot', 1}},
{60, {'tool_pan', 1}},
{50, {'ent_dbg_cigarette', 1}},
{50, {'ore_steel', 1}},
{50, {'drug_booze2', 1}},
{50, {'money', 1000}},
{45, {'tool_pot', 1}},
{45, {'tool_shaker', 1}},
{40, {'tool_oventray', 1}},
{35, {'bpd_fridge', 1}},
{30, {'bpd_workbench', 1}},
{23, {'bpd_machine', 1}},
{23, {'bpd_stove', 1}},
{20, {'bpd_refinery', 1}},
{20, {'radio', 1}},
{16, {'car_kit', 1}},
{5, {'money', 10000}},
{2, {'souvenir', table.Merge(table.Copy(doll), {name = L.statuette_chelog})}},
{2, {'souvenir', table.Merge(table.Copy(doll), {name = L.statuette_quillin})}},
{2, {'souvenir', table.Merge(table.Copy(doll), {name = L.statuette_artis})}},
{2, {'souvenir', table.Merge(table.Copy(doll), {name = L.statuette_nayzer})}},
{2, {'souvenir', table.Merge(table.Copy(doll), {name = L.statuette_youlas})}},
{2, {'souvenir', table.Merge(table.Copy(doll), {name = L.statuette_glitch})}},
{2, {'souvenir', table.Merge(table.Copy(doll), {name = L.statuette_google})}},
{2, {'souvenir', table.Merge(table.Copy(doll), {name = L.statuette_queeboy})}},
{2, {'souvenir', table.Merge(table.Copy(doll), {name = L.statuette_benri})}},
{2, {'souvenir', table.Merge(table.Copy(doll), {name = L.statuette_direded})}},
{2, {'souvenir', table.Merge(table.Copy(doll), {name = L.statuette_bellash})}},
{2, {'souvenir', table.Merge(table.Copy(doll), {name = L.statuette_drinda})}},
{2, {'souvenir', table.Merge(table.Copy(doll), {name = L.statuette_arthas})}},
{2, {'souvenir', table.Merge(table.Copy(doll), {name = L.statuette_wayzer})}},
{2, {'souvenir', table.Merge(table.Copy(doll), {name = L.statuette_hellcom})}},
{2, {'souvenir', table.Merge(table.Copy(doll), {name = L.statuette_hoffman})}},
{2, {'souvenir', table.Merge(table.Copy(doll), {name = L.statuette_sighty})}},
{2, {'souvenir', table.Merge(table.Copy(doll), {name = 'Фигурка Ванички'})}},
{2, {'souvenir', table.Merge(table.Copy(doll), {name = 'Фигурка Кило'})}},
{1, {'car_att', {
name = L.statuette_ermak,
icon = 'octoteam/icons/bust.png',
att = 'skull',
model = 'models/Gibs/HGIBS.mdl',
desc = L.desc_statuette_ermak,
}}},
}
for _,v in ipairs(trash) do
octoinv.registerLoot(v[1], {
mode = 'trash',
item = v[2],
})
end

View file

@ -0,0 +1,957 @@
------------------------------------------------
--
-- TOOLS
--
------------------------------------------------
local descTemp = L.descTemp
octoinv.registerItem('tool_pen', {
name = L.tool_pen,
icon = 'octoteam/icons/pen.png',
mass = 0.1,
volume = 0.1,
randomWeight = 0.25,
desc = descTemp,
})
octoinv.registerItem('tool_pencil', {
name = L.tool_pencil,
icon = 'octoteam/icons/pencil.png',
mass = 0.05,
volume = 0.05,
randomWeight = 0.25,
desc = descTemp,
})
octoinv.registerItem('souvenir', {
name = L.tool_souvenir,
icon = 'octoteam/icons/coin.png',
mass = 0.1,
volume = 0.05,
nostack = true,
model = 'models/props_phx/misc/egg.mdl',
})
------------------------------------------------
--
-- FOOD / DRUGS / SIMILAR
--
------------------------------------------------
local function drink(_, _, part, partText)
return L.drink .. partText, 'octoteam/icons/bottle.png', function(ply, item)
if ply:HasBuff('Overdose') then
ply:Notify('warning', L.overdose_hint)
return 0
end
local drunkTime = item:GetData('drunkTime') * item:GetData('part') * part
if drunkTime >= 180 then
ply:SetLocalVar('frost', math.max(ply:GetNetVar('frost', 0) - 50, 0))
end
ply:AddBuff('Drunk', drunkTime)
ply:EmitSound('npc/barnacle/barnacle_gulp2.wav', 75, 100)
item:SetData('part', item:GetData('part') * (1 - part))
item:SetData('desc', ('%s\nОсталось примерно %s%%'):format(
item:GetData('desc'):gsub('\nОсталось примерно.+', ''),
math.floor(item:GetData('part') * 100)
))
if item:GetData('part') <= 0 then item:Remove() end
return 0
end
end
octoinv.registerItem('drug_booze', {
name = L.drugbooze,
icon = 'octoteam/icons/food_beer.png',
mass = 1.5,
volume = 1.5,
nostack = true,
model = 'models/props_junk/garbage_glassbottle002a.mdl',
desc = L.description_drugbooze,
part = 1,
drunkTime = 120,
use = {
function(ply, item) return drink(ply, item, 1, ' полностью') end,
function(ply, item)
if item:GetData('drunkTime') * item:GetData('part') >= 30 then return drink(ply, item, 0.5, ' половину') end
end,
function(ply, item)
if item:GetData('drunkTime') * item:GetData('part') >= 60 then return drink(ply, item, 0.25, ' немного') end
end,
},
})
octoinv.registerItem('drug_booze2', {
name = L.drugbooze2,
icon = 'octoteam/icons/bottle_vodka.png',
mass = 1.5,
volume = 1,
nostack = true,
model = 'models/props_junk/glassbottle01a.mdl',
desc = L.description_drugbooze2,
part = 1,
drunkTime = 240,
use = {
function(ply, item) return drink(ply, item, 1, ' полностью') end,
function(ply, item)
if item:GetData('drunkTime') * item:GetData('part') >= 30 then return drink(ply, item, 0.5, ' половину') end
end,
function(ply, item)
if item:GetData('drunkTime') * item:GetData('part') >= 60 then return drink(ply, item, 0.25, ' немного') end
end,
},
})
octoinv.registerItem('ent_dbg_cigarette', {
name = L.cigarettes,
icon = 'octoteam/icons/cigarette.png',
mass = 0.1,
volume = 0.2,
nostack = true,
model = 'models/boxopencigshib.mdl',
desc = L.desc_cigarette,
cigsLeft = 20,
leftField = 'cigsLeft',
leftMaxField = 'cigsLeft',
use = {
function(ply, item)
if ply:HasWeapon('dbg_cigarette') then return false, L.have_cigarette end
return L.use_cigarette, 'octoteam/icons/cigarette.png', function(ply, item)
if ply.bleeding then
ply:Notify('warning', 'Ты при смерти')
return 0
end
local left = (item:GetData('cigsLeft') or 20) - 1
ply:Give('dbg_cigarette')
if not item:GetData('leftMax') then item:SetData('leftMax', item:GetData('cigsLeft')) end
item:SetData('cigsLeft', left)
item:GetParent():QueueSync()
return left == 0 and 1 or 0
end
end,
},
})
octoinv.registerItem('bandage', {
name = L.bandage,
icon = 'octoteam/icons/bandage.png',
mass = 0.1,
volume = 0.08,
model = 'models/props/cs_office/file_box_gib2.mdl',
randomWeight = 0.2,
desc = L.desc_bandage,
use = {
function(ply, item)
if ply:Health() < 80 then return false, L.you_cant_plaster end
if ply:Health() >= 100 then return false, L.are_you_okay end
return L.seal_bruises, 'octoteam/icons/medkit.png', function(ply, item)
ply:SetHealth(math.min(ply:Health() + 5, 100))
return 1
end
end,
},
})
octoinv.registerItem('clothes', {
name = L.clothes,
icon = 'octoteam/icons/clothes_warm.png',
mass = 0.5,
volume = 1.5,
model = 'models/props_junk/cardboard_box003a.mdl',
desc = L.desc_clothes,
use = {
function(ply, item)
if ply:isCP() then return false, L.need_unwear_police_form end
if ply:GetLocalVar('customClothes') then return false, 'Нужно снять текущую одежду' end
return L.wear2, 'octoteam/icons/clothes_warm.png', function(ply, item)
EventMakeRefugee(ply, function(ok)
if ok then
ply:TakeItem('clothes', 1)
ply:EmitSound('npc/combine_soldier/gear5.wav', 65)
ply.warmClothes = true
elseif tonumber(ply:HasItem('clothes')) <= 0 then
ply:Notify('warning', 'У тебя нет теплой одежды')
else
ply:Notify('warning', 'Теплая одежда не подошла по размеру... Попробуй сменить персонажа')
end
end, function()
return tonumber(ply:HasItem('clothes')) > 0
end)
end
end,
},
})
local ply = FindMetaTable 'Player'
function ply:SetClothes(clothes)
local mat = clothes and clothes.mat or nil
for i, original in ipairs(self:GetMaterials()) do
if string.match(original, '.+/sheet_%d+') then
self:SetSubMaterial(i - 1, mat)
end
end
local top = self.inv and self.inv:GetContainer('top')
if top then
top.icon = clothes and clothes.icon or octoinv.defaultInventory.top.icon
top:QueueSync()
end
ply.warmClothes = clothes and clothes.warm or nil
local old = self:GetDBVar('customClothes')
self:SetLocalVar('customClothes', clothes)
self:SetDBVar('customClothes', clothes)
hook.Run('dbg-clothes.update', self, clothes, old)
end
octoinv.registerItem('clothes_custom', {
name = 'Одежда',
icon = 'octoteam/icons/clothes_tshirt.png',
desc = 'Выделяйся из толпы!',
mass = 0.5,
volume = 1.5,
nostack = true,
model = 'models/props_junk/cardboard_box003a.mdl',
use = {
function(ply, item)
local matsToReplace = octolib.table.count(ply:GetMaterials(), function(v) return string.match(v, '.+/sheet_%d+') end)
if matsToReplace < 1 then return false, 'Ты не можешь это надеть сейчас' end
if ply:GetNetVar('customClothes') then return false, 'Нужно снять текущую одежду' end
local gender = item:GetData('gender')
if gender then
local isFemale = ply:GetInfo('dbg_model'):find('female')
if gender == 'male' and isFemale then return false, 'Это мужская одежда' end
if gender == 'female' and not isFemale then return false, 'Это женская одежда' end
end
return L.wear2, 'octoteam/icons/clothes_coat.png', function(ply, item)
ply:SetClothes(item:Export())
ply:EmitSound('npc/combine_soldier/gear5.wav', 65)
return 1
end
end,
},
})
concommand.Add('dbg_clothesoff', function(ply)
if not IsValid(ply) then return end
local clothes = ply:GetNetVar('customClothes')
if not clothes then return ply:Notify('warning', 'На тебе нет одежды, которую можно снять') end
local mats = ply:GetMaterials()
for i = 0, #mats - 1 do
if ply:GetSubMaterial(i) == clothes.mat then
local amount = ply:AddItem(clothes.class or 'clothes_custom', clothes)
if not amount or amount == 0 then
return ply:Notify('warning', 'В руках недостаточно места')
end
ply:SetClothes(nil)
break
end
end
end)
hook.Add('dbg-char.spawn', 'clothes', function(ply)
ply:SetClothes(ply:GetDBVar('customClothes'))
end)
------------------------------------------------
--
-- CONTAINERS
--
------------------------------------------------
local function spawnCont(ply, data)
local ent = ents.Create 'octoinv_cont'
ent.dt = ent.dt or {}
ent.dt.owning_ent = ply
ent.Model = data.model
ent.Skin = istable(data.skin) and math.random(data.skin[1], data.skin[2]) or data.skin or ent.Skin or 0
ent.Mass = data.mass
ent.Containers = data.conts
ent.DestructParts = data.destruct
ent.SID = ply.SID
ent:Spawn()
ply:BringEntity(ent)
ent:SetPlayer(ply)
ent:SetLocked(false)
timer.Simple(3, function()
if IsValid(ent) and IsValid(ply) then
APG.entUnGhost(ent, ply)
end
end)
return ent
end
octoinv.registerItem('cont', {
name = L.container,
icon = 'octoteam/icons/box1.png',
mass = 1,
volume = 1,
nostack = true,
use = {
function(ply, item)
local t = item:GetData('contdata')
if not t then return false, L.item_break end
return L.collect, 'octoteam/icons/box3_go.png', function(ply, item)
return IsValid(spawnCont(ply, t)) and 1 or 0
end
end,
},
})
local lockCont = {'func_door', 'func_door_rotating', 'prop_door_rotating', 'func_movelinear', 'prop_dynamic', 'octoinv_cont', 'octoinv_prod', 'octoinv_vend', 'octoinv_storage'}
octoinv.registerItem('lock_cont', {
name = L.item_lock_cont,
icon = 'octoteam/icons/lock.png',
model = 'models/props_wasteland/prison_padlock001a.mdl',
mass = 1,
volume = 1,
nostack = true,
desc = L.desc_lock,
use = {
function(ply, item)
local pass = item:GetData('password')
if pass then return end
return 'Настроить', 'octoteam/icons/wrench.png', function(ply, item)
local oldCont = item:GetParent()
octolib.request.send(ply, {{
type = 'strLong',
name = 'Пароль',
desc = 'Кодовая фраза. Этот замок можно будет открыть только ключом, пароль которого совпадает с собственным. Можно установить только один раз',
default = math.random(1000, 9999),
required = true,
}}, function(data)
if not item or item:GetParent() ~= oldCont then return end
local pass = tostring(data[1] or ''):sub(1, 32)
item:SetData('password', pass)
end)
end
end,
function(ply, item)
local num, pass = item:GetData('num'), item:GetData('password')
if not num then return false, L.item_break end
if not pass then return end
local ent = octolib.use.getTrace(ply).Entity
if not IsValid(ent) or (not table.HasValue(lockCont, ent:GetClass()) and not ent.lootable) then return false, L.need_see_on_item end
if ent:IsDoor() and ent:GetPlayerOwner() ~= ply:SteamID() then return false, L.this_is_not_your_door end
return L.set, 'octoteam/icons/wrench.png', function(ply, item)
ply:DelayedAction('lock_mount', L.set_hint, {
time = 5,
check = function() return octolib.use.check(ply, ent) and tobool(ply:HasItem(item)) end,
succ = function()
ply:TakeItem(item)
ent.lockNum = num
if pass then
ent.password = pass
end
end,
}, {
time = 1.5,
inst = true,
action = function()
ply:EmitSound('ambient/machines/pneumatic_drill_'.. math.random(1, 4) ..'.wav')
ply:DoAnimation(ACT_GMOD_GESTURE_ITEM_DROP + math.random(0,1))
end,
})
end
end,
},
})
octoinv.registerItem('key', {
name = 'Ключ',
desc = 'Используется для открывания замков. На бирке написано: {tag}',
icon = 'octoteam/icons/key.png',
model = 'models/bull/buttons/key_switch.mdl',
mass = 0.02,
volume = 0.01,
nodespawn = true,
nostack = true,
tag = '*пусто*',
use = {
function(ply, item)
local pass = item:GetData('password')
if pass then return end
return 'Настроить', 'octoteam/icons/wrench.png', function(ply, item)
local oldCont = item:GetParent()
octolib.request.send(ply, {{
type = 'strLong',
name = 'Пароль',
desc = 'Кодовая фраза. Этот ключ сможет открывать все замки, пароль которых совпадает с собственным. Можно установить только один раз',
default = math.random(1000, 9999),
required = true,
}}, function(data)
if not item or item:GetParent() ~= oldCont then return end
local pass = tostring(data[1] or ''):sub(1, 32)
item:SetData('password', pass)
end)
end
end,
function(ply, item)
return 'Подписать', 'octoteam/icons/pencil.png', function(ply, item)
local oldCont = item:GetParent()
octolib.request.send(ply, {{
type = 'strLong',
name = 'Текст',
default = '',
required = true,
}}, function(data)
if not item or item:GetParent() ~= oldCont then return end
local name = utf8.sub(tostring(data[1] or ''), 1, 128)
item:SetData('tag', name)
item:GetParent():Sync()
end)
end
end,
},
})
local function canLock(ply, ent)
if ent.password then
local key = ply:FindItem({ class = 'key', password = ent.password })
if key then
return true
else
return false
end
end
end
hook.Add('canKeysLock', 'octoinv.keys', canLock)
hook.Add('canKeysUnlock', 'octoinv.keys', canLock)
hook.Add('octoinv.canLock', 'octoinv.keys', canLock)
hook.Add('octoinv.canUnlock', 'octoinv.keys', canLock)
hook.Add('dbg-doors.unowned', 'octoinv.keys', function(ent)
ent.password = nil
end)
------------------------------------------------
--
-- EVENT ITEMS
--
------------------------------------------------
local desc = L.descEvent
octoinv.registerItem('coupon_ammo', {
name = L.coupon_ammo,
icon = 'octoteam/icons/coupon_red.png',
model = 'models/props/cs_assault/money.mdl',
desc = desc,
mass = 0.01,
volume = 0.01,
})
octoinv.registerItem('coupon_food', {
name = L.coupon_food,
icon = 'octoteam/icons/coupon_green.png',
model = 'models/props/cs_assault/money.mdl',
desc = desc,
mass = 0.01,
volume = 0.01,
})
octoinv.registerItem('coupon_exit', {
name = L.coupon_exit,
icon = 'octoteam/icons/coupon_blue.png',
model = 'models/props/cs_assault/money.mdl',
desc = desc,
mass = 0.01,
volume = 0.01,
})
octoinv.registerItem('petard', {
name = L.petards,
icon = 'octoteam/icons/dynamite.png',
mass = 0.5,
volume = 0.4,
usesLeft = 5,
model = 'models/Items/BoxBuckshot.mdl',
desc = L.desc_petards,
nostack = true,
use = {
function()
return 'Конвертировать', 'octoteam/icons/sparkler.png', function(ply, item)
local cont = item:GetParent()
local mass, volume, usesLeft = item:GetData('mass'), item:GetData('volume'), item:GetData('usesLeft')
item:Remove()
if usesLeft <= 0 then return end
cont:AddItem('throwable', {
name = 'Петарды',
desc = 'Это еще что за шутки?!',
icon = 'octoteam/icons/dynamite.png',
usesLeft = usesLeft,
mass = mass,
volume = volume,
gc = 'ent_dbg_petard',
})
end
end,
},
})
octoinv.registerItem('fireworks', {
name = L.salute,
icon = 'octoteam/icons/firework.png',
mass = 1,
volume = 0.8,
model = 'models/Items/BoxSRounds.mdl',
desc = L.desc_salute,
nostack = true,
use = {
function(ply, item)
return L.to_put, 'octoteam/icons/explosion.png', function(ply, item)
ply:DoAnimation(ACT_GMOD_GESTURE_ITEM_PLACE)
timer.Simple(0.88, function()
local pos, ang, vel = ply:GetBonePosition(ply:LookupBone('ValveBiped.Bip01_L_Hand') or 16)
local tr = util.TraceLine { start = ply:GetShootPos(), endpos = pos, filter = ply }
if tr.Hit then
pos = tr.HitPos + tr.HitNormal * 5
vel = tr.HitNormal * 100
elseif not vel then
vel = Vector()
end
ang = ply:EyeAngles()
ang.p = 0
local ent = ents.Create 'ent_dbg_fireworks'
ent:SetPos(pos)
ent:SetAngles(ang)
ent:SetCollisionGroup(COLLISION_GROUP_INTERACTIVE)
ent:Spawn()
ent:Activate()
ply:LinkEntity(ent)
local phys = ent:GetPhysicsObject()
if IsValid(phys) then
phys:Wake()
phys:SetVelocity(vel)
end
end)
return 1
end
end,
},
})
octoinv.registerItem('soccer', {
name = L.soccer,
desc = L.soccerballdesc,
icon = 'octoteam/icons/ball_soccer.png',
mass = 0.5,
volume = 0.5,
nostack = true,
use = {
function(ply, item)
if ply:HasItem('tool_pump') < 1 then return false, L.need_pump end
return L.pump_up, 'octoteam/icons/box3_go.png', function(ply, item)
local sid = ply:SteamID()
local count = 0
for _, v in ipairs(ents.FindByClass('sent_soccerball')) do
if octolib.linkedCache[v] == sid then count = count + 1 end
end
if count >= 3 then
return ply:Notify('warning', 'Зачем тебе столько мячей?')
end
local ent = ents.Create 'sent_soccerball'
if not IsValid(ent) then return end
ent:Spawn()
ply:LinkEntity(ent)
ply:BringEntity(ent)
return 1
end
end,
},
})
octoinv.registerItem('body_mat', {
name = L.body_mat,
desc = 'Собрал: {collector}\n\n{signature}Жертва: {corpse}{criminalsStr}',
icon = 'octoteam/icons/body_material.png',
mass = 0.2,
volume = 0.5,
nostack = true,
nodespawn = true,
collector = '???',
signature = '\n',
corpse = '???',
criminalsStr = '???',
use = {
function(ply, item)
if item.corpse and ply:isCP() then
return 'Подписать', 'octoteam/icons/pencil.png', function()
octolib.request.send(ply, {{
type = 'strLong',
name = 'Подпись',
desc = 'Переносы строк конвертируются в пробелы',
default = utf8.sub(item.signature or '\n\n', 1, -3),
}}, function(data)
if not istable(data) then return end
local txt = string.Replace(data[1] or '', '\n', ' ')
if data[1] ~= nil and string.Trim(utf8.sub(txt, 1, 256)) ~= '' then
item:SetData('signature', string.Trim(utf8.sub(txt, 1, 256)) .. '\n\n')
else item:SetData('signature', '') end
end)
end
end
end,
function(ply, item)
local cont = item:GetParent()
if not cont then return end
if ply:isCP() and cont.id == 'utilizer' then
local own = cont:GetParent():GetOwner()
if own.utilizerBusy then return false, 'Утилизатор уже работает' end
return 'Запустить утилизацию', 'octoteam/icons/explosion.png', function()
own:NextItem()
end
end
end,
},
})
octoinv.registerItem('binoculars', {
name = L.craft_binoculars,
icon = 'octoteam/icons/binoculars.png',
mass = 1.2,
volume = 1,
nostack = true,
})
hook.Add('closelook.canZoom', 'binoculars', function(ply)
if ply.inv and ply.inv.conts._hand and ply.inv.conts._hand:HasItem('binoculars') > 0 then
return true, true
end
end)
octoinv.registerItem('phone', {
name = L.phone,
icon = 'octoteam/icons/phone_old.png',
mass = 0.35,
volume = 0.5,
model = 'models/lt_c/tech/cellphone.mdl',
desc = L.desc_phone,
nostack = true,
on = false,
status = 'ВЫКЛ',
vibration = false,
notification = false,
use = {
function(ply, item)
if not item.on then return end
if ply:GetNetVar('ScareState', 0) > 0.6 then
return false, 'Ты трясешься от страха'
end
return L.use, 'octoteam/icons-16/phone.png', function(ply, item)
netstream.Start(ply, 'dbg-phone.open')
end
end,
function(ply, item)
return item.on and 'Выключить' or 'Включить', 'octoteam/icons/button_power.png', function(ply, item)
local on = not item.on
item:SetData('on', on)
item:SetData('status', on and 'ВКЛ' or 'ВЫКЛ')
ply:EmitSound('buttons/button24.wav')
end
end,
function(ply, item)
if not item.on then return end
return (item.notification and 'Выключить' or 'Включить') .. ' звук', 'octoteam/icons/phone_notification.png', function(ply, item)
local on = not item.notification
item:SetData('notification', on)
if item.notification then ply:EmitSound('phone/phone_notification.wav', 38) end
end
end,
function(ply, item)
if not item.on then return end
return (item.vibration and 'Выключить' or 'Включить') .. ' вибрацию', 'octoteam/icons/phone_vibration.png', function(ply, item)
local on = not item.vibration
item:SetData('vibration', on)
if item.vibration then ply:EmitSound('phone/phone_vibration.wav', 25) end
end
end,
},
})
octoinv.registerItem('phone_st', {
name = 'Домашний телефон',
icon = 'octoteam/icons/phone_office.png',
mass = 1.5,
volume = 5.5,
model = 'models/props/cs_office/phone.mdl',
desc = 'Средство связи, которое можно поставить у себя дома или на работе',
nostack = true,
class = 'ent_dbg_phone',
drop = function(ply, item, amount, posData)
local pos, ang, vel, put =
posData.pos or Vector(),
posData.ang or Angle(),
posData.vel or Vector(),
posData.put
local ent = ents.Create('ent_dbg_phone')
ent.Model = item:GetData('model', true) or 'models/props/cs_office/phone.mdl'
ent:Spawn()
ent:SetPos(pos)
ent:SetAngles(ang)
ent.owned = true
if put then
local a,b = ent:GetCollisionBounds()
pos:Sub(Vector(0,0,math.min(a.z, b.z)))
ent:SetPos(pos)
end
if not IsValid(ent) then return nil, 0 end
local ph = ent:GetPhysicsObject()
if IsValid(ph) then
ph:Wake()
ph:SetVelocity(vel)
end
ent:SetCollisionGroup(COLLISION_GROUP_INTERACTIVE)
if IsValid(ply) and ply:IsPlayer() then
ply:LinkEntity(ent)
ent.owner = ply
end
ent.off = true
return ent, 1
end,
pickup = function(ply, ent)
if not ent.owned or not ent.off then return false end
end,
})
octoinv.registerItem('player', {
name = L.radio,
icon = 'octoteam/icons/boombox.png',
mass = 2.5,
volume = 2,
model = 'models/props/cs_office/radio.mdl',
desc = L.desc_radio,
nostack = true,
class = 'ent_dbg_radio',
drop = function(ply, item, amount, posData)
local pos, ang, vel, put =
posData.pos or Vector(),
posData.ang or Angle(),
posData.vel or Vector(),
posData.put
local ent = ents.Create('ent_dbg_radio')
ent.Model = item:GetData('model') or ent.Model
ent:SetPos(pos)
ent:SetAngles(ang)
ent:Spawn()
if put then
local a,b = ent:GetCollisionBounds()
pos:Sub(Vector(0,0,math.min(a.z, b.z)))
ent:SetPos(pos)
end
if not IsValid(ent) then return nil, 0 end
local ph = ent:GetPhysicsObject()
if IsValid(ph) then
ph:Wake()
ph:SetVelocity(vel)
end
ent:SetCollisionGroup(COLLISION_GROUP_INTERACTIVE)
ent.radioPlayer = true
ent.owner = ply
if IsValid(ply) and ply:IsPlayer() then
ply:LinkEntity(ent)
end
return ent, 1
end,
pickup = function(ply, ent)
if not ent.radioPlayer then return false end
if ent.pinned then return false end
end,
})
octoinv.registerItem('zip', {
name = 'ZIP-пакет',
desc = 'Собрал: {collector}{signature}Содержимое:\n{storedStr}',
mass = 0.2,
volume = 0.2,
nodespawn = true,
nostack = true,
icon = 'octoteam/icons/zip_evidence.png',
model = 'models/weapons/w_package.mdl',
use = {
function(ply, item)
if item.storedStr then
return 'Подписать', 'octoteam/icons/pencil.png', function()
octolib.request.send(ply, {{
type = 'strLong',
name = 'Подпись',
desc = 'Переносы строк конвертируются в пробелы',
default = utf8.sub(item.signature or '\n\n', 1, -3),
}}, function(data)
if not istable(data) then return end
local txt = string.Replace(data[1] or '', '\n', ' ')
if data[1] ~= nil and string.Trim(utf8.sub(txt, 1, 256)) ~= '' then
item:SetData('signature', string.Trim(utf8.sub(txt, 1, 256)) .. '\n\n')
else item:SetData('signature', '') end
end)
end
end
end,
},
})
octoinv.registerItem('h_mask', {
name = L.mask,
icon = 'octoteam/icons/comedy.png',
mass = 0.3,
volume = 0.5,
desc = L.desc_mask,
nodespawn = true,
nostack = true,
use = {
function(ply, item)
local mask = item:GetData('mask')
if not mask then return false, L.item_break end
if ply:GetNetVar('hMask') then return false, 'На тебе уже надет аксессуар' end
return L.wear, 'octoteam/icons/key.png', function(ply, item)
ply:Unmask()
local expire = item:GetData('expire')
if expire then
ply.maskExpireUid = 'octoinv.maskExpire' .. octolib.string.uuid()
timer.Create(ply.maskExpireUid, expire - os.time(), 1, function()
if not IsValid(ply) then return end
ply:SetNetVar('hMask')
ply:SetDBVar('hMask')
ply:Notify('У твоего аксессуара закончился срок годности')
end)
end
ply:SetNetVar('hMask', {mask, item:GetData('expire')})
ply:SetDBVar('hMask', {mask, item:GetData('expire')})
return 1
end
end,
},
})
------------------------------------------------
--
-- DOOR AND DETAILS
--
------------------------------------------------
octoinv.registerItem('door', {
name = 'Дверь',
icon = 'octoteam/icons/door.png',
model = 'models/props_junk/cardboard_box001a.mdl',
mass = 7.5,
volume = 7.5,
nostack = true,
desc = L.desc_door,
use = {
function(ply, item)
local door_skin = item:GetData('skin')
local ent = octolib.use.getTrace(ply).Entity
if not IsValid(ent) or 'prop_door_rotating' ~= ent:GetClass() then return false, 'Нужно смотреть на дверь' end
if not ent:GetModel():find('models/props_c17/door01') then return false, 'Эту дверь нельзя заменить' end
if ent:GetPlayerOwner() ~= ply:SteamID() then return false, L.this_is_not_your_door end
if ent:GetSkin() == door_skin then return false, 'Нет смысла заменять дверь на точно такую же' end
return L.set, 'octoteam/icons/wrench.png', function(ply, item)
ply:DelayedAction('replace_door', L.replace, {
time = 3,
check = function() return octolib.use.check(ply, ent) and tobool(ply:HasItem(item)) end,
succ = function()
ply:TakeItem(item)
ent:SetSkin(door_skin)
end,
}, {
time = 1.5,
inst = true,
action = function()
ply:EmitSound('ambient/machines/pneumatic_drill_'.. math.random(1, 4) ..'.wav')
ply:DoAnimation(ACT_GMOD_GESTURE_ITEM_DROP + math.random(0,1))
end,
})
end
end,
},
})
octoinv.registerItem('door_handle', {
name = L.item_door_handle,
icon = 'octoteam/icons/door_handle.png',
model = 'models/props_junk/cardboard_box004a.mdl',
mass = .75,
volume = .75,
nostack = true,
desc = L.desc_door_handle,
use = {
function(ply, item)
local door_handle = item:GetData('handle')
local ent = octolib.use.getTrace(ply).Entity
if not IsValid(ent) or 'prop_door_rotating' ~= ent:GetClass() then return false, 'Нужно смотреть на дверь' end
if not ent:GetModel():find('models/props_c17/door01') then return false, 'Ручку на этой двери нельзя заменить' end
if ent:GetPlayerOwner() ~= ply:SteamID() then return false, L.this_is_not_your_door end
if ent:GetBodygroup(1) == door_handle then return false, 'На двери уже установлена такая ручка' end
return L.set, 'octoteam/icons/wrench.png', function(ply, item)
ply:DelayedAction('replace_door_handle', L.replace, {
time = 3,
check = function() return octolib.use.check(ply, ent) and tobool(ply:HasItem(item)) end,
succ = function()
ply:TakeItem(item)
ent:SetBodygroup(1, door_handle)
end,
}, {
time = 2,
inst = true,
action = function()
ply:EmitSound('ambient/machines/pneumatic_drill_'.. math.random(1, 4) ..'.wav')
ply:DoAnimation(ACT_GMOD_GESTURE_ITEM_DROP + math.random(0,1))
end,
})
end
end,
},
})
hook.Add('dbg-doors.unowned', 'dbg-doors.custom', function(ent)
ent:SetSkin(ent.defaultSkin or 0)
for k,v in pairs(ent.defaultBGs or {}) do
ent:SetBodygroup(k, v)
end
end)

View file

@ -0,0 +1,7 @@
octoinv.registerMarketItem('glock', { -- [string] market item ID
name = 'Glock', -- [string] print name
icon = 'octoteam/icons/gun_pistol.png', -- [string] icon for vgui
parent = 'weapon', -- [string] parent class, must be registered before current item
})
-- more to come

View file

@ -0,0 +1,23 @@
octoinv.registerMarketItem('cat_cars', {
name = L.to_car,
icon = 'octoteam/icons/car2.png',
})
octoinv.registerMarketItem('car_rims', {
parent = 'cat_cars',
name = 'Диски',
nostack = true,
})
octoinv.registerMarketItem('car_att', {
parent = 'cat_cars',
name = 'Аксессуары',
icon = 'octoteam/icons/bust.png',
nostack = true,
})
octoinv.registerMarketItem('car_part', {
parent = 'cat_cars',
name = 'Детали кузова',
nostack = true,
})

View file

@ -0,0 +1,32 @@
octoinv.registerMarketItem('cat_collector', {
name = 'Добыча ресурсов',
icon = octolib.icons.color('crowbar'),
nostack = true,
})
octoinv.registerMarketItem('collector_pickaxe', {
name = 'Кирка',
parent = 'cat_collector',
nostack = true,
matches = function(item)
return item.class == 'collector' and item.collector == 'pickaxe' and item.health and item.health > 0
end,
retain = {
sell = {
amount = 5,
price = 14500,
getOrderInfo = function()
local health = math.random(15, 500)
local price = 2000 + health * 25 + math.random(-100, 100) * 10
return price, {
class = 'collector',
name = 'Кирка',
icon = octolib.icons.color('crowbar'),
collector = 'pickaxe',
maxhealth = 500,
health = health,
}
end,
},
},
})

View file

@ -0,0 +1,17 @@
-- octoinv.registerMarketItem('food', {
-- name = 'Еда',
-- nostack = true,
-- matches = function(item)
-- return item.class == 'food' and item.trash
-- end,
-- })
octoinv.registerMarketItem('cat_ings', {
name = L.ings,
icon = 'octoteam/icons/food_ingredients.png',
})
octoinv.registerMarketItem('ing_fish1', { parent = 'cat_ings' })
octoinv.registerMarketItem('ing_fish2', { parent = 'cat_ings' })
octoinv.registerMarketItem('ing_fish3', { parent = 'cat_ings' })
octoinv.registerMarketItem('ing_fish4', { parent = 'cat_ings' })

Some files were not shown because too many files have changed in this diff Show more