-
Notifications
You must be signed in to change notification settings - Fork 1
/
etools.lua
323 lines (301 loc) · 9.01 KB
/
etools.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
setInfo({
version = 1,
hotreload = true,
home = "https://github.com/wildrun0/etools"
})
-- API documentation: https://docs.igvx.ru/
function delcommands()
command.remove("Clear")
command.remove("Tp")
command.remove("TpPos")
command.remove("AFK")
command.remove("Announce")
command.remove("Clients")
end
preReload = delcommands
function onStop()
delcommands()
client.iterall(function(players)
players:setdispname(players:getname())
players:update()
end)
end
function tpPlayers(caller, args)
if not args then
return "&cUsage: /Tp <to> or /Tp <whom> <to>"
end
local targ, subj = caller, nil
local u1, u2 = args:match("^(.-)%s(.-)$")
if u1 then
targ, subj = client.getbyname(u1, u2)
else
subj = client.getbyname(args)
end
if not (targ and subj) then
return "&cPlayer not found"
end
local succText = u1 and ("&e%s &awas teleported to &e%s"):format(targ:getname(), subj:getname()) or
("&aTeleported to &e%s"):format(subj:getname())
local targWrld, subjWrld = targ:getworld(), subj:getworld()
local subjPos = subj:getposition()
if targWrld ~= subjWrld then
if not u1 then targ:chat("&eTeleporting to player's world") end
targ:gotoworld(subjWrld)
end
if pAfkList[subj].isAfk then
pLastActivity[subj].washit = true
end
if pAfkList[targ].isAfk then
pLastActivity[targ].washit = true
end
targ:teleport(subjPos, targ:getrotation())
return(succText)
end
function tpPosition(caller, args)
if not args then
return "&cUsage: /TpPos <x> <y> <z> or /TpPos <whom> <x> <y> <z>"
end
local player = caller
local playerName, x, y, z = args:match(coordsPattern)
if not x then
return "&cUsage: /TpPos <x> <y> <z> or /TpPos <whom> <x> <y> <z>"
end
if #playerName > 0 then
player = client.getbyname(playerName)
if not player then
return "&cPlayer not found"
end
end
local succText = #playerName == 0 and ("&aTeleported to %.3f %.3f %.3f"):format(x,y,z) or
("&e%s &awas teleported to %.3f %.3f %.3f"):format(player:getname(), x,y,z)
player:teleport(vector.float(x, y+1, z), player:getrotation())
return (succText)
end
function switchAFK(player, mode)
local timestamp = os.time()
if mode == nil then
if timestamp - pAfkList[player].callTime <= AFK_TIMEOUT then
return ("&cYou should wait before using &e/AFK&c again")
end
if pLastActivity[player].isMoving then
return ("&cYou can't use this command while moving!")
end
mode = true
pLastActivity[player].time = (timestamp - AFK_TIME) -- чтобы его из афк не выкинуло
pAfkList[player].callTime = timestamp
end
if (pAfkList[player].isAfk) and (not mode) then
pAfkList[player].isAfk = false
client.broadcast:chat(("%s&d is no longer afk"):format(pAfkList[player].name))
pLastActivity[player].time = timestamp
player:setdispname(pAfkList[player].name)
pAfkList[player].name = nil
if AFK_SAFE_MODE then
player:setpvp(pAfkList[player].pvpmode)
end
player:update()
elseif (not pAfkList[player].isAfk) and (mode) then
pAfkList[player].isAfk = true
pAfkList[player].name = player:getdispname()
if not pAfkList[player].name:match("&%a+.+") then -- гандон без цветного ника фуу лох
pAfkList[player].name = "&f"..pAfkList[player].name
end
client.broadcast:chat(("%s&d went afk"):format(pAfkList[player].name))
player:setdispname("&d[AFK] " .. pAfkList[player].name)
if AFK_SAFE_MODE then
pAfkList[player].pvpmode = player:isinpvp()
player:setpvp(false)
end
player:update()
end
end
function onTick(tick)
timer = timer + tick
for player, lastActivity in pairs(pLastActivity) do
local timestamp = os.time()
if timestamp % 1 == 0 then
switchAFK(player, (timestamp - lastActivity.time >= AFK_TIME))
end
if lastActivity.isMoving then
if timer - lastActivity.lastTickMovement > 500 then
lastActivity.isMoving = false
if lastActivity.washit then
lastActivity.washit = false
end
end
end
end
end
function onRotate(player)
if player:isbot() then return end
pLastActivity[player].time = os.time()
end
function onMove(player)
if player:isbot() then return end
local playerMovements = pLastActivity[player]
playerMovements.pastvec:set(playerMovements.currentvec:get())
player:getposition(playerMovements.currentvec)
playerMovements.isMoving = true
playerMovements.lastTickMovement = timer
if (not pAfkList[player].isAfk) then
playerMovements.time = os.time()
end
local function calculate_coords(axis)
local coord_diff = playerMovements.currentvec[axis] - playerMovements.pastvec[axis]
if (coord_diff < 0) and (axis == "y") then
return 0
end
return math.abs(coord_diff)
end
if (not playerMovements.washit) and (pAfkList[player].isAfk) then
if (calculate_coords("x") > PLAYER_AFK_THRESHOLD) or (calculate_coords("y") > PLAYER_AFK_THRESHOLD) or (calculate_coords("z") > PLAYER_AFK_THRESHOLD) then
switchAFK(player, false)
end
end
end
function onPlayerClick(_, args)
local enemyTarget = args.target
if enemyTarget and enemyTarget:isbot() then return end
if (enemyTarget) and (pAfkList[enemyTarget].isAfk) then
pLastActivity[enemyTarget].washit = true
end
end
function makeAnnounce(_, args)
client.broadcast:chat(MESSAGE_TYPE_ANNOUNCE, args)
end
function onMessage(cl)
pLastActivity[cl].time = os.time()
if pAfkList[cl].isAfk then
cl:setdispname(pAfkList[cl].name)
end
end
function clientsCmd()
local str = "&7Players using: \r\n"
for k, v in pairs(clients) do
str = str .. ("&7 %s: &f%s\r\n"):format(k, table.concat(v, ", "))
end
return str
end
function addClient(player)
local playerName, playerApp = player:getname(), player:getappname()
if clients[playerApp] then
table.insert(clients[playerApp], playerName)
else
clients[playerApp] = {playerName}
end
end
function onDisconnect(player)
pAfkList[player] = nil
pLastActivity[player] = nil
if player:isinstate(CLIENT_STATE_INITIAL) then return end
local playerName, playerApp = player:getname(), player:getappname()
if not clients[playerApp] then return end
for clientIndex, clientPlayer in ipairs(clients[playerApp]) do
if clientPlayer == playerName then
table.remove(clients[playerApp], clientIndex)
if #clients[playerApp] == 0 then
clients[playerApp] = nil
end
end
end
end
function onConnect(player)
pAfkList[player] = {
isAfk = false,
callTime = 0
}
pLastActivity[player] = {
lastTickMovement = timer, washit = false,
pastvec = vector.float(), time = os.time(),
currentvec = vector.float()
}
end
function onHandshake(cl)
if cl:isop() then
cl:setdispname("&c" .. cl:getname())
end
addClient(cl)
end
function onUserTypeChange(cl)
local playerName = cl:getname()
if cl:isop() then
if pAfkList[cl].isAfk then
pAfkList[cl].name ="&c"..playerName
cl:setdispname("&d[AFK] &c".. playerName)
else
cl:setdispname("&c".. playerName)
end
cl:chat("&eYou have been added to the OPs list")
else
if pAfkList[cl].isAfk then
pAfkList[cl].name = "&f" .. playerName
cl:setdispname("&d[AFK] &f".. playerName)
else
cl:setdispname("&f" .. playerName)
end
cl:chat("&eYou have been removed from the OPs list")
end
cl:update()
end
function clearChat(caller)
for i=1, 12 do
caller:chat(" ")
end
end
function onStart()
command.add("Clear", "Clear chat", CMDF_CLIENT, clearChat)
command.add("Tp", "Teleport to player", CMDF_OP, tpPlayers)
command.add("TpPos", "Teleport to specific coords", CMDF_OP, tpPosition)
command.add("AFK", "Went to afk", CMDF_CLIENT, switchAFK)
command.add("Announce", "Make an announcement", CMDF_OP, makeAnnounce)
command.add("Clients", "List of the clients player are using, and who uses which client", CMDF_NONE, clientsCmd)
coordsPattern = "^(.-)%s?([-+]?%d*%.?%d*)%s+([-+]?%d*%.?%d*)%s+([-+]?%d*%.?%d*)$"
clients = {}
pAfkList = pAfkList or {}
pLastActivity = pLastActivity or {}
plSettings = config.new{
name = "etools.cfg",
items = {
{
name = "afk-time",
comment = "Amount of seconds after which the player will be set AFK (in seconds)",
type = CONFIG_TYPE_INT,
default = 90
},
{
name = "afk-timeout",
comment = "Timeout after a command call (in seconds)",
type = CONFIG_TYPE_INT,
default = 15
},
{
name = "afk-safe-mode",
comment = "Disable pvp for player who's AFK (requires cs-survival plugin)",
type = CONFIG_TYPE_BOOL,
default = true
}
}
}
plSettings:save(not plSettings:load())
AFK_TIME = plSettings:get("afk-time")
AFK_TIMEOUT = plSettings:get("afk-timeout")
AFK_SAFE_MODE = plSettings:get("afk-safe-mode")
PLAYER_AFK_THRESHOLD = 0.0625
timer = timer or 0
client.iterall(function(player)
pLastActivity[player] = pLastActivity[player] or {lastTickMovement = timer, washit = false, pastvec = vector.float(), currentvec = vector.float(), time = os.time()}
pAfkList[player] = pAfkList[player] or {isAfk = false, callTime = 0}
if player:isop() then onUserTypeChange(player) end
addClient(player)
end)
if survival then
survival.safe(true)
survival.init()
end
end
function postStart()
if AFK_SAFE_MODE and (not survival or not survival.isready()) then
print("ETools: afk-safe-mode requires a cs-survival plugin (not detected)")
AFK_SAFE_MODE = false
end
end