Created
December 10, 2020 16:01
-
-
Save EdGruberman/b92d15cee0e6845546a4f5850a82e7a8 to your computer and use it in GitHub Desktop.
mIRC TFC Server Management Script
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
on *:START:{ sentinel.load } | |
on *:EXIT:{ sentinel.unload } | |
on *:CONNECT:{ if ( $hget(sentinel.general,autoactivate) == 1 && $hget(sentinel.general.status,activated) != 1 ) sentinel.activate } | |
alias sentinel.load { | |
;--Load settings from ini file into hash tables | |
hmake sentinel.irc 5 | |
hload -i sentinel.irc sentinel.ini irc | |
if ( $hget(sentinel.irc,admin) == $null ) hadd sentinel.irc admin #clan.private password | |
if ( $hget(sentinel.irc,tv) == $null ) hadd sentinel.irc tv #clan.tv | |
if ( $hget(sentinel.irc,monitor) == $null ) hadd sentinel.irc monitor #clan | |
hmake sentinel.general 5 | |
hload -i sentinel.general sentinel.ini general | |
hadd sentinel.general version v0.5.0b - 2008/06/11 by EdGruberman | |
hadd sentinel.general url http://sentinel.rjump.com | |
if ( $hget(sentinel.general,port.type) == $null ) hadd sentinel.general port.type dynamic | |
if ( $hget(sentinel.general,port.log) == $null ) hadd sentinel.general port.log 49889 | |
if ( $hget(sentinel.general,show.connects) == $null ) hadd sentinel.general show.connects 1 | |
if ( $hget(sentinel.general,show.sayteam) == $null ) hadd sentinel.general show.sayteam 1 | |
.fullname Sentinel Bot $hget(sentinel.general,version) | |
hmake sentinel.server 5 | |
hload -i sentinel.server sentinel.ini server | |
if ( $hget(sentinel.server,address) == $null ) hadd sentinel.server address 127.0.0.1 | |
if ( $hget(sentinel.server,rcon_password) == $null ) hadd sentinel.server rcon_password password | |
hmake sentinel.log 5 | |
hload -i sentinel.log sentinel.ini log | |
hmake sentinel.teams 20 | |
hload -i sentinel.teams sentinel.ini teams | |
if ( $hget(sentinel.teams,0).item == 0 ) { | |
hadd sentinel.teams Blue 12 | |
hadd sentinel.teams Red 04 | |
hadd sentinel.teams Green 03 | |
hadd sentinel.teams Yellow 08 | |
hadd sentinel.teams Spectator 14 | |
hadd sentinel.teams Console 07 | |
hadd sentinel.teams Unassigned 15 | |
} | |
hmake sentinel.rules.default 5 | |
hload -i sentinel.rules.default sentinel.ini rules.default | |
if ( $hget(sentinel.rules.default,players) == $null ) hadd sentinel.rules.default players $ctime Default 8 | |
if ( $hget(sentinel.rules.default,max) == $null ) hadd sentinel.rules.default max $ctime Default 900 | |
if ( $hget(sentinel.rules.default,min) == $null ) hadd sentinel.rules.default min $ctime Default 300 | |
if ( $hget(sentinel.rules.default,type) == $null ) hadd sentinel.rules.default type $ctime Default ignore | |
if ( $hget(sentinel.rules.default,maps) == $null ) hadd sentinel.rules.default maps $ctime Default cp_badlands cp_dustbowl cp_granary cp_gravelpit cp_well ctf_2fort ctf_well pl_goldrush tc_hydro | |
hmake sentinel.invited 5 | |
hload -i sentinel.invited sentinel.ini invited | |
;--Load the rules for any invited channels | |
var %i = 1 | |
while ( %i <= $hget(sentinel.invited,0).item ) { | |
hmake [ sentinel.rules. $+ [ $hget(sentinel.invited,%i).item ] ] 5 | |
hload -i [ sentinel.rules. $+ [ $hget(sentinel.invited,%i).item ] ] sentinel.ini [ rules. $+ [ $hget(sentinel.invited,%i).item ] ] | |
inc %i | |
} | |
} | |
alias sentinel.unload { sentinel.deactivate | hfree -w sentinel.* } | |
alias sentinel.activate { | |
if ( $hget(sentinel.general.status,activated) == 1 ) return | |
hadd -m sentinel.general.status activated 1 | |
;--Join monitor and admin irc channels | |
join $hget(sentinel.irc,monitor) | |
if ( ($gettok($hget(sentinel.irc,monitor),2,32) != $null) ) .timersentinel.monitor.pw 1 2 mode #$gettok($hget(sentinel.irc,monitor),1,32) +k $gettok($hget(sentinel.irc,monitor),2,32) | |
join $hget(sentinel.irc,admin) | |
if ( ($gettok($hget(sentinel.irc,admin),2,32) != $null) ) .timersentinel.admin.pw 1 2 mode #$gettok($hget(sentinel.irc,admin),1,32) +k $gettok($hget(sentinel.irc,admin),2,32) | |
;--Join invited irc channels | |
var %i = 1 | |
while ( %i <= $hget(sentinel.invited,0).item ) { | |
join $hget(sentinel.invited,%i).item $gettok($hget(sentinel.invited,%i).data,3,32) | |
inc %i | |
} | |
sentinel.server.open | |
} | |
alias sentinel.deactivate { | |
if ( $hget(sentinel.general.status,activated) != 1) return | |
hadd sentinel.general.status activated 0 | |
sentinel.server.close | |
;--Depart invited channels | |
var %i = 1 | |
while ( %i <= $hget(sentinel.invited,0).item ) { | |
part $gettok($hget(sentinel.invited,%i).item,1,32) 5Bot Deactivated | |
inc %i | |
} | |
;--Depart irc channels | |
part $gettok($hget(sentinel.irc,admin),1,32) 5Bot Deactivated | |
part $gettok($hget(sentinel.irc,monitor),1,32) 5Bot Deactivated | |
;--Clean-up yer mess! | |
hfree -w sentinel.server.* | |
hfree -w sentinel.rcon.* | |
timers off | |
} | |
alias sentinel.server.open { | |
;--Join the tv channel and then open the log socket. | |
hmake sentinel.server.status 5 | |
join $hget(sentinel.irc,tv) | |
if ( ($gettok($hget(sentinel.irc,tv),2,32) != $null) ) .timersentinel.tv.pw 1 2 mode #$gettok($hget(sentinel.irc,tv),1,32) +k $gettok($hget(sentinel.irc,tv),2,32) | |
sentinel.rcon status | |
.timersentinel.rcon 1 3 sentinel.rcon sv_visiblemaxplayers | |
.timersentinel.log.open 1 3 sentinel.log.open | |
} | |
alias sentinel.server.close { | |
;--Close the log socket and leave the tv channel. | |
hfree sentinel.server.status | |
sentinel.log.close | |
if ( ($gettok($hget(sentinel.irc,tv),1,32) != $gettok($hget(sentinel.irc,admin),1,32)) $& | |
&& ($gettok($hget(sentinel.irc,tv),1,32) != $gettok($hget(sentinel.irc,monitor),1,32)) ) $& | |
part $gettok($hget(sentinel.irc,tv),1,32) 5Server Closed | |
else msg $gettok($hget(sentinel.irc,tv),1,32) 5Server Closed | |
} | |
alias sentinel.server.address { | |
var %address = $hget(sentinel.server,address) | |
if ( $pos(%address,:,0) == 0 ) var %address = %address $+ :27015 | |
return $replace(%address,:,$chr(32)) | |
} | |
alias sentinel.port { | |
var %port = $hget(sentinel.general,$1) | |
if ( $hget(sentinel.general,port.type) == dynamic ) return $null | |
else return %port | |
} | |
alias sentinel.log.open { | |
hadd sentinel.general.status log.status Open | |
sockudp -k sentinel.socket.log $sentinel.port(port.log) $sentinel.server.address | |
sentinel.rcon logaddress_add $ip $+ : $+ $sock(sentinel.socket.log).port | |
} | |
alias sentinel.log.close { | |
hadd sentinel.general.status log.status Closed | |
sentinel.rcon logaddress_del $ip $+ : $+ $sock(sentinel.socket.log).port | |
sockclose sentinel.socket.log | |
} | |
alias sentinel.log.check { | |
;--If log has been explicitly closed, don't re-open it! | |
if ( $hget(sentinel.general.status,log.status) == Closed ) return | |
;--If no log entry for over 5 mins, check status which will generate a log entry for the rcon. | |
if ( $sock(sentinel.socket.log).lr > $calc(5 * 60) ) sentinel.rcon status | |
;--If no log entry still in over 15 mins, attempt to reopen the log. | |
if ( $sock(sentinel.socket.log).lr > $calc(15 * 60) ) sentinel.log.open | |
} | |
alias sentinel.log.address { | |
var %address = $hget(sentinel.log,address) | |
if ( $pos(%address,:,0) == 0 ) var %address = %address $+ :28888 | |
return $replace(%address,:,$chr(32)) | |
} | |
alias sentinel.rcon { | |
var %cmd = $1- | |
if ( $1 == =rcon ) var %cmd = $2- | |
;--Save command in the rcon queue. | |
var %request_id = $sentinel.rcon.queue(%cmd) | |
;--If this is an =rcon request, associate the request_id with the response target. | |
if ( $1 == =rcon ) set -u10 %sentinel.rcon.response %sentinel.rcon.response %request_id | |
;--If the socket is already attempting to authenticate, just let it do it's thing. | |
if ( %sentinel.socket.rcon.status == authenticating ) return | |
if ( $sock(sentinel.socket.rcon).to == $null ) { | |
set -u15 %sentinel.socket.rcon.status authenticating | |
sockclose sentinel.socket.rcon | |
sockopen sentinel.socket.rcon $sentinel.server.address | |
} | |
else { sentinel.rcon.write %request_id } | |
return %request_id | |
} | |
alias sentinel.rcon.queue { | |
var %id = $hget(sentinel.rcon.queue,$hget(sentinel.rcon.queue,0).item).item + 1 | |
hadd -m sentinel.rcon.queue %id $1- | |
return %id | |
} | |
alias sentinel.rcon.queue.check { | |
if ( $hget(sentinel.rcon.queue,$1) != $null ) sentinel.rcon.write $1 | |
} | |
on *:SOCKOPEN:sentinel.socket.rcon:{ | |
;--Set 15 second connection timeout. | |
.timersentinel.socket.rcon.timeout 1 15 sockclose sentinel.socket.rcon | |
;--Send the initial authentication request. | |
sentinel.rcon.write 0 | |
unset %sentinel.rcon.request_id | |
} | |
alias sentinel.rcon.write { | |
;--Retrieve command in rcon queue. | |
var %request_id = $1 | |
var %cmd = $hget(sentinel.rcon.queue,%request_id) | |
var %type = 2 | |
;--If request_id is 0, this needs to be an authentication request. | |
if ( %request_id == 0 ) { | |
var %type = 3 | |
var %cmd = $hget(sentinel.server,rcon_password) | |
} | |
var %packet_size = $calc(10 + $len(%cmd)) | |
;--Compile packet data to be sent. | |
bset &packet 1 %packet_size | |
bset &packet 5 %request_id | |
bset &packet 9 %type | |
bset -t &packet 13 %cmd | |
bset &packet $calc(13 + $len(%cmd)) 0 0 | |
;--Debug output. | |
if ( %sentinel.rcon.debug == 2 ) debug.binvar &packet RCON TCP OUT $chr($asc(|)) FROM: $sock(sentinel.socket.rcon).bindip $+ : $+ $sock(sentinel.socket.rcon).bindport $chr($asc(|)) TO: $sock(sentinel.socket.rcon).ip $+ : $+ $sock(sentinel.socket.rcon).port | |
if ( %sentinel.rcon.debug >= 1 ) { | |
echo -s $timestamp RCON TCP OUT $chr($asc(|)) FROM: $sock(sentinel.socket.rcon).bindip $+ : $+ $sock(sentinel.socket.rcon).bindport $chr($asc(|)) TO: $sock(sentinel.socket.rcon).ip $+ : $+ $sock(sentinel.socket.rcon).port | |
echo -si11 ---------- Packet Size: %packet_size -- Request ID: %request_id -- Request Type: %type | |
echo -si11 ---------- %cmd | |
} | |
;--Actual socket write. | |
sockwrite sentinel.socket.rcon &packet | |
[ .timersentinel.rcon.queue $+ [ %request_id ] ] 1 10 sentinel.rcon.queue.check %request_id | |
} | |
on *:SOCKREAD:sentinel.socket.rcon:{ | |
;--Reset 15 second connection timeout. | |
.timersentinel.socket.rcon.timeout 1 15 sockclose sentinel.socket.rcon | |
sockread $sock(sentinel.socket.rcon).rq &data | |
if ( %sentinel.rcon.debug == 2 ) debug.binvar &data RCON TCP IN $chr($asc(|)) FROM: $sock(sentinel.socket.rcon).ip $+ : $+ $sock(sentinel.socket.rcon).port $chr($asc(|)) TO: $sock(sentinel.socket.rcon).bindip $+ : $+ $sock(sentinel.socket.rcon).bindport | |
;--Might be more than one packet of data. Seperate each packet by finding the double null at the end of the packet. | |
var %i = 1 | |
while (%i <= $bvar(&data,0)) { | |
var %eop = $bfind(&data,$calc(%i + 12),0) + 1 | |
if ( %eop == 1 ) var %eop = $bvar(&data,0) | |
bcopy -c &packet 1 &data %i $calc(%eop - %i + 1) | |
sentinel.rcon.parsePacket &packet | |
var %i = %eop + 1 | |
} | |
} | |
alias sentinel.rcon.parsePacket { | |
var %packet_size = $calc($bvar($1,1) + $bvar($1, 2) * 256 + $bvar($1, 3) * (256 ^ 2) + $bvar($1, 4) * (256 ^ 3)) | |
var %request_id = $calc($bvar($1,5) + $bvar($1, 6) * 256 + $bvar($1, 7) * (256 ^ 2) + $bvar($1, 8) * (256 ^ 3)) | |
var %type = $calc($bvar($1,9) + $bvar($1,10) * 256 + $bvar($1,11) * (256 ^ 2) + $bvar($1,12) * (256 ^ 3)) | |
;--Parse strings seperated by linefeeds into a hash table. | |
var %i = 13 | |
var %j = 1 | |
while (%i <= $calc($bvar($1,0) - 2)) { | |
var %len = $calc($bfind($1,%i,10) - %i) | |
if ( %len < 0 ) var %len = $calc($bvar($1,0) - %i - 2) | |
if ( %len >= 0 ) { | |
hadd -m sentinel.rcon.string1 %j $bvar($1,%i,%len).text | |
inc %j | |
} | |
var %i = $calc(%i + %len + 1) | |
} | |
;--Debug output | |
if ( %sentinel.rcon.debug >= 1 ) { | |
echo -s $timestamp RCON TCP IN $chr($asc(|)) FROM: $sock(sentinel.socket.rcon).ip $+ : $+ $sock(sentinel.socket.rcon).port $chr($asc(|)) TO: $sock(sentinel.socket.rcon).bindip $+ : $+ $sock(sentinel.socket.rcon).bindport | |
echo -si11 ---------- Packet Size: %packet_size -- Request ID: %request_id -- Response Type: %type | |
var %i = 1 | |
while ( %i <= $hget(sentinel.rcon.string1,0).item ) { | |
echo -si11 ---------- String 1: $hget(sentinel.rcon.string1,%i) | |
inc %i | |
} | |
} | |
if ( %type == 2 ) { | |
;--SERVERDATA_AUTH_RESPONSE | |
;--If a request_id is 0xFFFFFFFF(4294967295) or not matching any request_id we've sent, then it's an error. | |
;--The exception is that when we first open or close and reopen the rcon socket, we send the authentication as request_id = 0. | |
if ( (%request_id != 4294967295) && (($hget(sentinel.rcon.queue,%request_id) != $null) || (%request_id == 0)) ) { | |
unset %sentinel.socket.rcon.status | |
;--Send every command that built up in the rcon queue while authenticating now. | |
;--As the queue may start emptying before we finish stepping through it, save out a list of request ids first. | |
var %i = 1 | |
while ( %i <= $hget(sentinel.rcon.queue,0).item ) { | |
var %id_list = %id_list $hget(sentinel.rcon.queue,%i).item | |
inc %i | |
} | |
var %i = 1 | |
while ( %i <= $numtok(%id_list,32) ) { | |
sentinel.rcon.write $gettok(%id_list,%i,32) | |
inc %i | |
} | |
} | |
else { echo 4 -s RCON Authentication Error: %request_id } | |
} | |
elseif ( %type == 0 ) { | |
;--SERVERDATA_RESPONSE_VALUE | |
if ( %request_id != 0 ) { | |
;--Not an authentication request response. So, remove request from the rcon queue and parse the data. | |
hdel sentinel.rcon.queue %request_id | |
if ( $hget(sentinel.rcon.string1,0).item > 0 ) sentinel.rcon.parse %request_id | |
} | |
} | |
else echo 4 -s Unrecognized RCON Response Type: %type | |
hfree -w sentinel.rcon.string1 | |
} | |
alias sentinel.rcon.parse { | |
;--Here is where we do meaningful manipulation of the data in the packets we got. | |
var %lines = $hget(sentinel.rcon.string1,0).item | |
;--If this is the response to an =rcon command, then show the results back | |
if ( $1 == $gettok(%sentinel.rcon.response,2,32) ) { | |
var %i = 1 | |
while ( %i <= %lines ) { | |
;--Frequently rcon responses end with two linefeeds resulting in an empty line following the response. | |
;--No reason to relay an empty line at the end in IRC. | |
if ( (%i == $hget(sentinel.rcon.string1,0).item) && ($hget(sentinel.rcon.string1,%i) == $null) ) { } | |
else msg $gettok(%sentinel.rcon.response,1,32) RCON: $hget(sentinel.rcon.string1,%i) | |
inc %i | |
} | |
unset %sentinel.rcon.response | |
} | |
;--"status" response; Example: | |
;hostname: EdGruberman's Test Server | |
;version : 1.0.3.1/14 3504 secure | |
;udp/ip : 192.168.1.103:27015 | |
;map : cp_roswell at: 0 x, 0 y, 0 z | |
;players : 2 (24 max) | |
; | |
;# userid name uniqueid connected ping loss state adr | |
;# 1 "EdGruberman" STEAM_0:0:204432 54:06 69 0 active 192.168.1.11:27005 | |
;# 2 "Player" BOT active | |
if ( $gettok($hget(sentinel.rcon.string1,1),1,32) == hostname: ) { | |
;hfree -w sentinel.server.status | |
hadd -m sentinel.server.status hostname $gettok($hget(sentinel.rcon.string1,1),2-,32) | |
hadd -m sentinel.server.status map $gettok($hget(sentinel.rcon.string1,4),3,32) | |
hadd -m sentinel.server.status player.max $mid($gettok($hget(sentinel.rcon.string1,5),4,32),2) | |
;--Verify TV channel topic | |
var %tv = $gettok($hget(sentinel.irc,tv),1,32) | |
if ( $chan(%tv).topic != MAP: $+ $hget(sentinel.server.status,map) $+ on $hget(sentinel.server.status,hostname) at $hget(sentinel.server,address) ) $& | |
topic %tv MAP: $+ $hget(sentinel.server.status,map) $+ on $hget(sentinel.server.status,hostname) at $hget(sentinel.server,address) | |
;--Clean out/reset old player information | |
hfree -w sentinel.rcon.status | |
hadd -m sentinel.server.status player.count 0 | |
hadd -m sentinel.server.status bot.count 0 | |
;--Loop through player list | |
var %i = 8 | |
while ( %i <= %lines ) { | |
var %line = $hget(sentinel.rcon.string1,%i) | |
;--Example: # 1 "EdGruberman" STEAM:0:1:204432 25:09 19 0 active 192.168.1.11:27005 | |
;--Example: #68 "Player" BOT active | |
var %p_name = $gettok(%line,2,$asc(")) | |
var %p_stats = $gettok(%line,3,$asc(")) | |
var %p_uniqueid = $gettok(%p_stats,1,32) | |
var %p_userid = $mid($gettok(%line,1,$asc(")),2) | |
if ( %p_uniqueid == BOT ) hinc -m sentinel.server.status bot.count | |
elseif ( $left(%p_uniqueid,4) == hltv ) hinc -m sentinel.server.status hltv.count | |
else { | |
;--.rcon.status = ID1 time2 ping3 loss4 adr5 state6 name7- | |
hinc -m sentinel.server.status player.count | |
hadd -m sentinel.rcon.status %p_userid %p_uniqueid $gettok(%p_stats,2-4,32) $gettok(%p_stats,6,32) $gettok(%p_stats,5,32) %p_name | |
} | |
inc %i | |
} | |
;--Since we've just processed the current status, might as well check to see if anyone wants to be updated | |
sentinel.notify | |
} | |
;--Server variable response; Example: "maxplayers" is "12" | |
elseif ( $left($hget(sentinel.rcon.string1,1),1) == " ) { | |
tokenize $asc(") $hget(sentinel.rcon.string1,1) | |
hadd -m sentinel.server.status $1 $3 | |
} | |
;--server_game_time response; Example: Server game time: 499.919983 | |
elseif ( $gettok($hget(sentinel.rcon.string1,1),1-3,32) == Server game time: ) { | |
tokenize 32 $hget(sentinel.rcon.string1,1) | |
hadd -m sentinel.server.status server_game_time $gettok($4,1,$asc(.)) | |
} | |
;--logaddress_add response; Example: logaddress_add: 1.2.3.4:49889 | |
elseif ( $gettok($hget(sentinel.rcon.string1,1),1,32) == logaddress_add: ) { | |
if ( $gettok($hget(sentinel.rcon.string1,1),2,32) == $ip $+ : $+ $sock(sentinel.socket.log).port ) $& | |
msg $gettok($hget(sentinel.irc,tv),1,32) 5Server Opened | |
} | |
else { } | |
} | |
on *:UDPREAD:sentinel.socket.log:{ | |
;--Only accept data from our designated server. | |
if ( $sock(sentinel.socket.log).saddr != $gettok($sentinel.server.address,1,32) ) return | |
sockread $sock(sentinel.socket.log).rq &packet | |
if ($sockbr == 0) return | |
if (%sentinel.log.debug == 2) debug.binvar &packet LOG UDP IN $chr($asc(|)) FROM: $sock(sentinel.socket.log).saddr $+ : $+ $sock(sentinel.socket.log).sport $chr($asc(|)) TO: $sock(sentinel.socket.log).ip $+ : $+ $sock(sentinel.socket.log).port | |
sentinel.log.parsePacket &packet | |
} | |
alias sentinel.log.parsePacket { | |
var %line = $bvar($1,1,$bvar($1,0)).text | |
if ( %sentinel.log.debug >= 1 ) { | |
echo -s $timestamp LOG UDP IN $chr($asc(|)) FROM: $sock(sentinel.socket.log).saddr $+ : $+ $sock(sentinel.socket.log).sport $chr($asc(|)) TO: $sock(sentinel.socket.log).ip $+ : $+ $sock(sentinel.socket.log).port | |
echo -si11 ---------- %line | |
} | |
;--Strip the header and the last character which is always a linefeed. | |
if ( $left(%line,6) == ÿÿÿÿRL ) sentinel.log.parse $left($mid(%line,6),$calc($len($mid(%line,6)) - 1)) | |
} | |
alias sentinel.log.parse { | |
var %tv = $gettok($hget(sentinel.irc,tv),1,32) | |
var %monitor = $gettok($hget(sentinel.irc,monitor),1,32) | |
var %admin = $gettok($hget(sentinel.irc,admin),1,32) | |
;--Reset 1min timer to check if still open | |
.timersentinel.log.check -o 0 60 sentinel.log.check | |
;--Record to log file if desired | |
if ( $hget(sentinel.log,file) != $null ) { write $shortfn($hget(sentinel.log,file)) $+ $replace($hget(sentinel.server,address),:,.) $+ .log $1- } | |
;--Example: L 07/09/2003 - 23:34:02: Kick: "EdGruberman<5><204432><>" was kicked by "Console" (message "spawn camping") | |
;--Example: L 07/09/2003 - 23:34:02: Kick: "EdGruberman<6><204432><>" was kicked by "Console" | |
if ( $5 == Kick: ) { | |
tokenize $asc(") $1- | |
msg %tv * $sentinel.format.player($2) was kicked. $iif($len($6) > 0,Reason: 07 $+ $6) | |
} | |
;--Example: L 07/09/2003 - 22:49:21: Started map "avanti" (CRC "-2138426516") | |
elseif ( $5-6 == Started map ) { | |
set -u120 %sentinel.status mapchange | |
sentinel.rcon status | |
;--We know all players start out as Unassigned at a map change. | |
var %i = 1 | |
while ( %i <= $hget(sentinel.rcon.status,0).item ) { | |
hadd -m sentinel.players Unassigned $gettok($hget(sentinel.players,%i).data,2,32) | |
inc %i | |
} | |
tokenize $asc(") $1- | |
msg %tv ¯¯¯¯¯¯¯¯¯¯ Map changed to " $+ $2 $+ " ¯¯¯¯¯¯¯¯¯¯ | |
topic %tv MAP: $+ $2 $+ on $hget(sentinel.server.status,hostname) at $hget(sentinel.server,address) | |
} | |
;--Example: L 07/09/2003 - 23:21:40: Team "Blue" scored "0" with "1" player (kills "0") (kills_unaccounted "0") | |
elseif ( ($5 = Team) && ($7 == scored) ) { | |
tokenize $asc(") $1- | |
msg %tv ===== $sentinel.format.team($2) scored $4 $+ pts with $6 players on $hget(sentinel.server.status,map) $+ . ===== | |
} | |
;--Example: L 06/15/2008 - 21:01:22: Team "Blue" triggered "pointcaptured" (cp "0") (cpname "Courtyard") (numcappers "4") (player1 "^N^BlueInGreen<53><STEAM_0:0:17012120><Blue>") (position1 "921 2765 -152") (player2 "BladeGamer[cnlm]<62><STEAM_0:1:17491723><Blue>") (position2 "886 2866 -152") (player3 "Swashbuckler<94><STEAM_0:1:5199409><Blue>") (position3 "892 2745 -152") (player4 "ScorpioZ<108><STEAM_0:1:7492850><Blue>") (position4 "866 2812 -152") | |
elseif ( ($5 = Team) && ($7 == triggered) ) { | |
tokenize $asc(") $1- | |
if ( $4 == pointcaptured ) msg %tv ===== $sentinel.format.team($2) captured $8 $+ with $10 cappers on $hget(sentinel.server.status,map) $+ . ===== | |
} | |
;--Example: L 06/18/2008 - 10:59:42: server_message: "quit" | |
elseif ( $5-6 == server_message: "quit" ) { | |
msg %tv Server shutdown. | |
} | |
;--Player event... parse type of event | |
elseif ( $left($5,1) == " ) { | |
var %playerinfo = $mid($1-,27,$calc($pos($1-,",2) - 27)) | |
var %team = $replace($mid($gettok(%playerinfo,-1,$asc(>)),2),$chr(32),_) | |
var %player = $left(%playerinfo,$calc($pos(%playerinfo,<,$calc($pos(%playerinfo,<,0) - 2)) - 1)) | |
var %userid_tok = $gettok(%playerinfo,$calc($numtok(%playerinfo,$asc(<)) - 2),$asc(<)) | |
var %userid = $left(%userid_tok,$calc($len(%userid_tok) - 1)) | |
;--Ensure players hash is up to date on team status for player. | |
hadd -m sentinel.players %userid %team $gettok($hget(sentinel.players,%userid),2,32) | |
var %event_start = $calc($pos($1-,",2) + 2) | |
var %event_end = $calc($pos($1-,",3) - 1) | |
if ( %event_end == -1 ) { var %event_end = $calc($len($1-) + 1) } | |
var %event = $mid($1-,%event_start,$calc(%event_end - %event_start)) | |
;--Example: L 06/14/2008 - 16:14:04: "CYBER<69><STEAM_0:1:1485814><Red>" say_team "sry" | |
;--Example: L 06/14/2008 - 00:28:01: "Console<0><Console><Console>" say "#sentinel.tv | EdGruberman : hi" | |
if ( %event == say || ( (%event == say_team) && ($hget(sentinel.general,show.sayteam) == 1) ) ) { | |
var %text_start = $pos($1-,",3) + 1 | |
var %text_end = $len($1-) | |
var %text = $mid($1-,%text_start,$calc(%text_end - %text_start)) | |
var %admin = $mid(%text,$pos(%text,admin,1),5) | |
if ( %event == say_team ) { | |
if ( %team != Spectator ) var %playerinfo = $chr(40) $+ TEAM $+ $chr(41) %playerinfo | |
else var %playerinfo = $chr(40) $+ Spectator $+ $chr(41) %playerinfo | |
} | |
if ( (%event == say) && (%team == Spectator) ) { var %playerinfo = *SPEC* %playerinfo } | |
if ( (%team == Unassigned) && (%event == say) ) var %playerinfo = *DEAD* %playerinfo | |
if ( (%team == Unassigned) && (%event == say_team) ) var %playerinfo = *DEAD* $+ %playerinfo | |
var %message = $sentinel.format.player(%playerinfo) : $replace(%text,admin, $+ %admin $+ ) | |
msg %tv %message | |
if ( admin isin %text ) { msg %monitor 07 $+ %tv $chr($asc(|)) %message } | |
} | |
;--Example: L 07/09/2003 - 10:17:54: "EdGruberman<1><204432><>" connected, address "1.2.3.4:27005" | |
elseif ( %event == connected, address ) { | |
if ( $hget(sentinel.general,show.connects) == 1 ) { | |
tokenize $asc(") $1- | |
msg %tv * $sentinel.format.player(%playerinfo) $+ < $+ $mid($gettok(%playerinfo,-2,$asc(>)),2) $+ > is trying to connect $& | |
$iif($hget(sentinel.general,show.ip) == 1,from $4,) | |
} | |
} | |
;--Example: L 07/09/2003 - 23:07:42: "EdGruberman<2><204432><>" entered the game | |
elseif ( %event == entered the game ) { | |
if ( ($hget(sentinel.general,show.connects) == 1) && (%sentinel.status != mapchange) ) { | |
msg %tv * $sentinel.format.player(%playerinfo) $+ < $+ $mid($gettok(%playerinfo,-2,$asc(>)),2) $+ > has entered the game. | |
sentinel.rcon status | |
} | |
else { | |
.timersentinel.enteredthegame 1 15 sentinel.rcon status | |
.timersentinel.players 1 30 sentinel.players %tv | |
} | |
} | |
;--Example: L 06/15/2008 - 22:01:51: "EdGruberman<111><STEAM_0:0:204432><Blue>" disconnected (reason "Disconnect by user.") | |
elseif ( %event == disconnected $chr(40) $+ reason ) { | |
if ( $hget(sentinel.general,show.connects) == 1 ) { | |
tokenize $asc(") $1- | |
var %reason = $4 | |
if ($right(%reason,1) = $chr(10)) var %reason = $mid(%reason,1,$calc($len(%reason) - 1)) | |
msg %tv * $sentinel.format.player(%playerinfo) $+ < $+ $mid($gettok(%playerinfo,-2,$asc(>)),2) $+ > disconnected. $chr(40) $+ %reason $+ $chr(41) | |
} | |
sentinel.rcon status | |
} | |
;--Example: L 07/09/2003 - 23:21:54: "EdGruberman<3><204432><Blue>" changed name to "Luka" | |
elseif ( %event == changed name to ) { | |
tokenize $asc(") $1- | |
msg %tv * $sentinel.format.player(%playerinfo) changed name to " $+ $4 $+ ". | |
} | |
;--Example: L 07/09/2003 - 23:35:39: "EdGruberman<6><204432><SPECTATOR>" joined team "Blue" | |
elseif ( %event == joined team ) { | |
tokenize $asc(") $1- | |
hadd -m sentinel.players %userid $4 $gettok($hget(sentinel.players,%userid),2,32) | |
} | |
else { } | |
} | |
else { } | |
} | |
alias sentinel.format.weapon { | |
;--Returns an irc formatted, ascii art representation of a weapon | |
if ( $1 == axe ) { return 14.04/14` } | |
elseif ( $1 == caltrop ) { return 15¸ } | |
elseif ( $1 == medikit ) { return 15,00[04,00+15,00] } | |
elseif ( $1 == spanner ) { return 14©==C } | |
else { return $null } | |
} | |
alias sentinel.format.player { | |
;--Returns the player name passed to it colored according to it's team as per the ini | |
;--Color is left open, must terminate in calling function if so desired | |
;--Example: EdGruberman<4><204432><#Dustbowl_team1> | |
;--Example: Console<0><Console><Console> | |
var %team = $replace($mid($gettok($1,-1,$asc(>)),2),$chr(32),_) | |
var %color = $gettok($hget(sentinel.teams,%team),1,32) | |
var %player = $left($1-,$calc($pos($1-,<,$calc($pos($1-,<,0) - 2)) - 1)) | |
if ( %color == $null && %team != $null ) { var %color = 01 $+ < $+ %team $+ > } | |
if ( %color != $null ) { var %color = $+ %color } | |
return %color $+ %player | |
} | |
alias sentinel.format.team { | |
;--Returns the team name passed to it colored as per the ini | |
;--Color is left open, must terminate in calling function if so desired | |
var %color = $gettok($hget(sentinel.teams,$replace($1,$chr(32),_)),1,32) | |
var %team = $gettok($hget(sentinel.teams,$replace($1,$chr(32),_)),2,32) | |
if ( %team == $null ) { var %team = $1 } | |
if ( %color == $null ) { return " $+ %team $+ " } | |
else { return $+ %color $+ %team } | |
} | |
on *:INVITE:#:{ | |
join $chan | |
.timersentinel.invite.check 1 5 sentinel.invite.check $nick $chan | |
} | |
alias sentinel.invite.check { | |
;--If invited to the admin channel, just say there so the =activate command can be used correctly. | |
if ( $2 == $gettok($hget(sentinel.irc,admin),1,32) ) return | |
;--Force users to use /invite so the bot can record who exactly invited it | |
if ( $1 = ChanServ ) { msg $2 rawr! you need to use the following command to invite me: /invite $me $2 | part $2 | return } | |
;--If ChanServ is not a part of channel, don't stick around | |
if ( ChanServ !isop $2 ) { msg $2 i will only stay in a registered channel, sorry... :~( | part $2 | return } | |
;--Notify the monitor channel then join and introduce yerself! | |
msg $gettok($hget(sentinel.irc,monitor),1,32) rawr! i just got invited to $2 by $1 $+ ! i feel teh 4<3 ;)~ | |
msg $2 rawr! i'm a Sentinel bot! | |
msg $1 i've just added $2 to my list of auto-joins because you invited me. all ops in $2 can use =rules to change my channel notification settings. use =rules help to get started! | |
;--Save invited information to ini | |
hadd sentinel.invited $2 $ctime $1 | |
hsave -i sentinel.invited sentinel.ini invited | |
} | |
on *:KICK:#:{ | |
;--For the GameSurge IRC network, after netsplits ChanServ will kick you with the reason of "Net Rider" for channel management purposes. | |
;--Simply rejoining the channel is acceptable. The trick is make sure we have the password or not. | |
if ( ( $knick == $me ) && ( $1- == Net Rider ) ) { | |
if ( $chan == $gettok($hget(sentinel.irc,monitor),1,32) ) { var %rejoin = $hget(sentinel.irc,monitor) } | |
elseif ( $chan == $gettok($hget(sentinel.irc,admin),1,32) ) { var %rejoin = $hget(sentinel.irc,admin) } | |
elseif ( $chan == $gettok($hget(sentinel.irc,tv),1,32) ) { var %rejoin = $hget(sentinel.irc,tv) } | |
else { var %rejoin = $chan } | |
join %rejoin | |
return | |
} | |
;--If this is the admin channel, just leave as expected to. | |
if ( $2 == $gettok($hget(sentinel.irc,admin),1,32) ) return | |
;--Else it looks like this really is a goodbye. :~( | |
if ( $knick == $me ) { | |
part $chan 5Sentinel Bot: Removed from service. | |
notice $nick thx for having me! i won't come back to $chan unless someone invites me again... | |
msg $gettok($hget(sentinel.irc,monitor),1,32) $+ $nick just kicked me outta $chan ... :~( i fear they might not wub me anymore *sniff* | |
;--Remove this channel from the invited list | |
hdel sentinel.invited $chan | |
hsave -i sentinel.invited sentinel.ini invited | |
;--Remove all the rules for this channel | |
hfree [ sentinel.rules. $+ [ $chan ] ] | |
remini sentinel.ini [ rules. $+ [ $chan ] ] | |
} | |
} | |
on *:TEXT:=rules*:#:{ | |
if ( $nick !isop $chan ) { [ .timersentinel.denied 1 1 notice $nick Denied: You lack operator status in $chan $+ . } | |
else { | |
if ( $2 == $null ) { | |
;--Get channel rules | |
var %players = $hget([ sentinel.rules. $+ [ $chan ] ],players) | |
var %maps = $hget([ sentinel.rules. $+ [ $chan ] ],maps) | |
var %type = $hget([ sentinel.rules. $+ [ $chan ] ],type) | |
var %min = $hget([ sentinel.rules. $+ [ $chan ] ],min) | |
var %max = $hget([ sentinel.rules. $+ [ $chan ] ],max) | |
;--If a rule is not defined for a channel, use the default | |
if ( %players == $null ) { var %players = $hget(sentinel.rules.default,players) } | |
if ( %maps == $null ) { var %maps = $hget(sentinel.rules.default,maps) } | |
if ( %type == $null ) { var %type = $hget(sentinel.rules.default,type) } | |
if ( %min == $null ) { var %min = $hget(sentinel.rules.default,min) } | |
if ( %max == $null ) { var %max = $hget(sentinel.rules.default,max) } | |
;--Give the user the info | |
notice $nick $chan $+ : Players = $gettok(%players,3,32) $+ $chr(40) $+ Default: $gettok($hget(sentinel.rules.default,players),3,32) $+ $chr(41) $chr($asc(|)) Min number of players, bots are not counted. | |
notice $nick $chan $+ : Min = $gettok(%min,3,32) $+ $chr(40) $+ Default: $gettok($hget(sentinel.rules.default,min),3,32) $+ $chr(41) $chr($asc(|)) Shortest time in seconds before bot can notify again. | |
notice $nick $chan $+ : Max = $gettok(%max,3,32) $+ $chr(40) $+ Default: $gettok($hget(sentinel.rules.default,max),3,32) $+ $chr(41) $chr($asc(|)) Longest time in seconds bot will wait before notifying again. | |
notice $nick $chan $+ : Type = $gettok(%type,3,32) $+ $chr(40) $+ Default: $gettok($hget(sentinel.rules.default,type),3,32) $+ $chr(41) $chr($asc(|)) If notify, Maps contains maps to notify if played. If ignore, Maps contains maps that no notifications will occur on. | |
notice $nick $chan $+ : Maps = $gettok(%maps,3-,32) | |
} | |
else { | |
;--Verify the parameter is one this function accepts | |
var %params = players min max forced type maps help | |
if ( $findtok(%params,$lower($2),0,32) == 0 ) { [ .timersentinel. $+ [ $nick ] ] 1 1 notice $nick Error: I don't understand the $2 parameter. See =rules help for more info. } | |
elseif ( $lower($2) == help ) { | |
[ .timersentinel. $+ [ $nick ] $+ 1 ] 1 1 notice $nick =rules ( View/change/reset channel notification rules for all servers with this command. ) | |
[ .timersentinel. $+ [ $nick ] $+ 2 ] 1 1 notice $nick Syntax: =rules $chr($asc([)) $+ <rule_name> $+ $chr($asc([)) <rule_value> $+ $chr($asc(])) $+ $chr($asc(])) | |
[ .timersentinel. $+ [ $nick ] $+ 3 ] 1 1 notice $nick To view the channel's current rules, do not include any parameters. Example: =rules | |
[ .timersentinel. $+ [ $nick ] $+ 4 ] 1 1 notice $nick To edit a rule, include the <rule_name> and the <rule_value> parameters. Example: =rules min 120 | |
[ .timersentinel. $+ [ $nick ] $+ 5 ] 1 1 notice $nick To reset a rule to default, only put the <rule_name> parameter. Example: =rules min | |
} | |
else { | |
;--Edit hash entry if param $3- isn't null, else del the hash entry | |
var %old = $gettok($hget([ sentinel.rules. $+ [ $chan ] ],$2),3-,32) | |
if ( %old == $null ) { var %old = $gettok($hget(sentinel.rules.default,$2),3-,32) } | |
if ( $3- != $null ) { hadd -m [ sentinel.rules. $+ [ $chan ] ] $2 $ctime $nick $3- } | |
else { hdel [ sentinel.rules. $+ [ $chan ] ] $2 } | |
hsave -i [ sentinel.rules. $+ [ $chan ] ] sentinel.ini [ rules. $+ [ $chan ] ] | |
if ( $3- != $null ) { [ .timersentinel. $+ [ $nick ] ] 1 1 notice $nick $+ $2 rule changed for $chan $+ from " $+ %old $+ " to " $+ $3- $+ " } | |
else { [ .timersentinel. $+ [ $nick ] ] 1 1 notice $nick $+ $2 rule reset to default for $chan $+ from " $+ %old $+ " to " $+ $gettok($hget(sentinel.rules.default,$2),3-,32) $+ " } | |
} | |
} | |
} | |
} | |
on *:TEXT:=help:*:{ | |
var %adminop = $iif($nick isop $gettok($hget(sentinel.irc,admin),1,32),$true,$false) | |
var %monitorop = $iif($nick isop $gettok($hget(sentinel.irc,monitor),1,32) || $nick isop $gettok($hget(sentinel.irc,tv),1,32),$true,$false) | |
var %status = You $iif(%adminop,are,are not) an op in the admin channel ( $+ $gettok($hget(sentinel.irc,admin),1,32) $+ ) and you $iif(%monitorop,are,are not) an op in the monitor ( $+ $gettok($hget(sentinel.irc,monitor),1,32) $+ ) or tv ( $+ $gettok($hget(sentinel.irc,tv),1,32) $+ ) channel. | |
[ .timersentinel. $+ [ $nick ] $+ 1 ] 1 1 notice $nick %status $iif(%adminop || %monitorop,With your current status you can use the following commands:,) | |
if ( ( $nick isop $chan ) && ( $chan != $gettok($hget(sentinel.irc,tv),1,32) ) ) { [ .timersentinel. $+ [ $nick ] $+ 2 ] 1 1 notice $nick =rules help :: Adjusts channel notification criteria. :: Usable in any channel except $gettok($hget(sentinel.irc,tv),1,32) by Ops in calling channel } | |
if ( $nick isop $gettok($hget(sentinel.irc,monitor),1,32) || $nick isop $gettok($hget(sentinel.irc,tv),1,32)$nick isop $gettok($hget(sentinel.irc,admin),1,32) ) { | |
[ .timersentinel. $+ [ $nick ] $+ 3 ] 1 1 notice $nick =chat <message> :: Sends <message> into game public chat. :: Usable only in $gettok($hget(sentinel.irc,tv),1,32) by Ops in $gettok($hget(sentinel.irc,monitor),1,32) or $gettok($hget(sentinel.irc,tv),1,32) | |
[ .timersentinel. $+ [ $nick ] $+ 4 ] 1 1 notice $nick =status :: Displays current game status on server. :: Usable in any channel by Ops in $gettok($hget(sentinel.irc,monitor),1,32) or $gettok($hget(sentinel.irc,tv),1,32) | |
[ .timersentinel. $+ [ $nick ] $+ 5 ] 1 1 notice $nick =players[ <player_name>] :: Lists current player names or detailed player info if <player_name> matches a current player. :: Usable in any channel by Ops in $gettok($hget(sentinel.irc,monitor),1,32) or $gettok($hget(sentinel.irc,tv),1,32) | |
[ .timersentinel. $+ [ $nick ] $+ 6 ] 1 1 notice $nick =invited :: Lists channels bot has been invited into. :: Usable in any channel by Ops in $gettok($hget(sentinel.irc,monitor),1,32) or $gettok($hget(sentinel.irc,tv),1,32) | |
} | |
if ( $nick isop $gettok($hget(sentinel.irc,admin),1,32) ) { | |
[ .timersentinel. $+ [ $nick ] $+ 7 ] 1 1 notice $nick =close :: Closes server log/rcon interaction with bot but keeps bot available in irc to open. :: Usable in any channel by Ops in $gettok($hget(sentinel.irc,admin),1,32) | |
[ .timersentinel. $+ [ $nick ] $+ 8 ] 1 1 notice $nick =open :: Opens server log/rcon interaction with bot. :: Usable in any channel by Ops in $gettok($hget(sentinel.irc,admin),1,32) | |
if ( $hget(sentinel.general,allowrcon) == 1 ) { [ .timersentinel. $+ [ $nick ] $+ 9 ] 1 1 notice $nick =rcon <cmd> :: Issues RCON command <cmd> to server. :: Usable in any channel by Ops in $gettok($hget(sentinel.irc,admin),1,32) } | |
} | |
[ .timersentinel. $+ [ $nick ] $+ 9 ] 1 1 notice $nick Sentinel Bot $hget(sentinel.general,version) :: $hget(sentinel.general,url) | |
} | |
on *:TEXT:=rcon *:*:{ | |
if ( $nick !isop $gettok($hget(sentinel.irc,admin),1,32) ) { .timersentinel.denied 1 1 notice $nick Denied: You lack operator status in $gettok($hget(sentinel.irc,admin),1,32) $+ . | return } | |
if ( $hget(sentinel.general,allowrcon) != 1 ) { .timersentinel.disabled 1 1 notice $nick Feature Disabled: RCON access not allowed. | return } | |
if ( %sentinel.rcon.response != $null ) { [ .timersentinel. $+ [ $nick ] ] 1 1 notice $nick RCON Temporarily Unavailable. Currently in use $iif($left(%sentinel.rcon.response,1) == $chr($asc(#)),in,by) %sentinel.rcon.response $+ . Please try again in a few seconds. } | |
set -u10 %sentinel.rcon.response $iif($chan != $null,$chan,$nick) | |
sentinel.rcon =rcon $2- | |
} | |
on *:TEXT:=chat *:#:{ | |
if ( $chan != $gettok($hget(sentinel.irc,tv),1,32) ) return | |
if ( $nick !isop $gettok($hget(sentinel.irc,monitor),1,32) && $nick !isop $gettok($hget(sentinel.irc,tv),1,32) && $nick !isop $gettok($hget(sentinel.irc,admin),1,32) ) return | |
var %message = $strip($2-) | |
if ( %message == $null ) return | |
var %message = $chan $chr($asc(|)) $nick : %message | |
sentinel.rcon say %message | |
} | |
on *:TEXT:=close:*:{ if ( $nick isop $gettok($hget(sentinel.irc,admin),1,32) ) sentinel.server.close } | |
on *:TEXT:=open:*:{ if ( $nick isop $gettok($hget(sentinel.irc,admin),1,32) ) sentinel.server.open } | |
on *:TEXT:=activate:*:{ if ( $nick isop $gettok($hget(sentinel.irc,admin),1,32) ) sentinel.activate } | |
on *:TEXT:=deactivate:*:{ if ( $nick isop $gettok($hget(sentinel.irc,admin),1,32) ) sentinel.deactivate } | |
alias sentinel.servers { msg $1 $+ %i $+ $chr(40) $+ $+ %closed $+ $+ $chr(41) $chr($asc(|)) $+ 1,15 $hget([ server $+ [ %i ] $+ .status ],hostName) $+ $chr(40) $+ $hget([ server $+ [ %i ] ],ip) $+ : $+ $hget([ server $+ [ %i ] ],port) $+ $chr(41) $+ $chr($asc(|)) $hget([ server $+ [ %i ] ],tv) $+ $chr($asc(|)) $+ 1,15 $hget([ server $+ [ %i ] $+ .status ],map) $+ $chr(40) $+ $hget([ server $+ [ %i ] $+ .status ],playerCount) $+ $chr($asc(/)) $+ $hget([ server $+ [ %i ] $+ .status ],playerMax) $+ $chr(41) } | |
on *:TEXT:=invited:*:{ | |
echo -s chan: $chan nick: $nick | |
if ( $nick !isop $gettok($hget(sentinel.irc,monitor),1,32) && $nick !isop $gettok($hget(sentinel.irc,tv),1,32) && $nick !isop $gettok($hget(sentinel.irc,admin),1,32) ) { return } | |
[ .timersentinel.invited. $+ [ $chan ] ] 1 2 sentinel.invited $iif($chan != $null,$chan,$nick) | |
} | |
alias sentinel.invited { | |
if ($hget(sentinel.invited,0).item == 0) { | |
msg $1 Nobody has invited me. :~( | |
return | |
} | |
var %i = 1 | |
while ( %i <= $hget(sentinel.invited,0).item ) { | |
var %invited = $hget(sentinel.invited,%i).item $hget(sentinel.invited,%i).data | |
msg $1 $gettok(%invited,1,32) $chr($asc(|)) $+ 1,15 $gettok(%invited,3,32) $+ $chr($asc(|)) $asctime($gettok(%invited,2,32),m/d/yy @ h:mmtt) | |
inc %i | |
} | |
} | |
on *:TEXT:=status:*:{ | |
if ( $nick !isop $gettok($hget(sentinel.irc,monitor),1,32) && $nick !isop $gettok($hget(sentinel.irc,tv),1,32) && $nick !isop $gettok($hget(sentinel.irc,admin),1,32) ) { return } | |
if ( $timer(sentinel.status) == $null ) { | |
sentinel.rcon server_game_time | |
.timersentinel.rcon.mp_timelimit 1 1 sentinel.rcon mp_timelimit | |
.timersentinel.rcon.sm_nextmap 1 1 sentinel.rcon sm_nextmap | |
} | |
.timersentinel.status 1 3 sentinel.status $iif($chan != $null,$chan,$nick) | |
} | |
alias sentinel.status { | |
if ($hget(sentinel.server.status,sv_visiblemaxplayers) == -1) var %max = $hget(sentinel.server.status,player.max) | |
else var %max = $hget(sentinel.server.status,sv_visiblemaxplayers) | |
hadd -m sentinel.server.status playersNbots $hget(sentinel.server.status,player.count) $+ / $+ %max players | |
if ( $hget(sentinel.server.status,bot.count) > 0 ) { hadd -m sentinel.server.status playersNbots $hget(sentinel.server.status,playersNbots) $chr($asc(|)) + $+ $hget(sentinel.server.status,bot.count) bots } | |
if ( $hget(sentinel.server.status,mp_timelimit) = 0 ) var %timeleft = No Time Limit | |
else { | |
var %timeleft = $calc($hget(sentinel.server.status,mp_timelimit) * 60 - $hget(sentinel.server.status,server_game_time)) | |
if (%timeleft < 0) var %timeleft = 0 | |
var %timeleft = $duration(%timeleft) left | |
} | |
var %status = 14 $+ $hget(sentinel.server.status,hostname) $+ $chr($asc(|)) 5Status: $hget(sentinel.server.status,map) :: $hget(sentinel.server.status,playersNbots) :: %timeleft | |
if ($hget(sentinel.server.status,sm_nextmap) != $null) var %status = %status :: Next map is " $+ $hget(sentinel.server.status,sm_nextmap) $+ " | |
var %status = %status :: steam://connect/ $+ $hget(sentinel.server,address) | |
msg $1 %status | |
} | |
on *:TEXT:=players*:*:{ | |
if ( $nick !isop $gettok($hget(sentinel.irc,monitor),1,32) && $nick !isop $gettok($hget(sentinel.irc,tv),1,32) && $nick !isop $gettok($hget(sentinel.irc,admin),1,32) ) { return } | |
.timersentinel.players 1 3 sentinel.players $iif($chan != $null,$chan,$nick) $2- | |
} | |
alias sentinel.players { | |
;--Remove the mapchange status at this point | |
unset %sentinel.status | |
if ( $hget(sentinel.rcon.status,0).item == 0 ) { msg $1 5Players: None :~( | return } | |
if ( $2 != $null ) { | |
var %i = 1 | |
while ( %i <= $hget(sentinel.rcon.status,0).item ) { | |
if ( $gettok($hget(sentinel.rcon.status,%i).data,7-,32) == $2- ) { | |
tokenize 32 $1 $hget(sentinel.rcon.status,%i).data | |
;--sentinel.rcon.status = ID2 time3 ping4 loss5 adr6 state7 name8- | |
var %team = $hget(sentinel.players,$hget(sentinel.rcon.status,%i).item) | |
var %pinfo = $8- $+ $chr($asc(<)) $+ 0 $+ $chr($asc(>)) $+ $chr($asc(<)) $+ 0 $+ $chr($asc(>)) $+ $chr($asc(<)) $+ %team $+ $chr($asc(>)) | |
msg $1 5Player Info: $sentinel.format.player(%pinfo) $+ $chr($asc(|)) $2 $chr($asc(|)) $4 $+ ms $+ $chr(40) $+ loss= $+ $5 $+ $chr(41) $chr($asc(|)) $3 $iif($7 != active,$chr($asc(|)) $7,) | |
} | |
inc %i | |
} | |
} | |
else { | |
var %i = 1 | |
:nextplayer | |
tokenize 32 $1 $hget(sentinel.rcon.status,%i).data | |
;--sentinel.rcon.status = ID2 time3 ping4 loss5 adr6 state7 name8- | |
var %team = $hget(sentinel.players,$hget(sentinel.rcon.status,%i).item) | |
var %pinfo = $8- $+ $chr($asc(<)) $+ 0 $+ $chr($asc(>)) $+ $chr($asc(<)) $+ 0 $+ $chr($asc(>)) $+ $chr($asc(<)) $+ %team $+ $chr($asc(>)) | |
var %names = %names " $+ $sentinel.format.player(%pinfo) $+ $+ " | |
if ( $gettok($calc(%i / 5),2,$asc(.)) == $null ) { | |
msg $1 5Players: %names | |
var %names = $null | |
} | |
inc %i | |
if ( $hget(sentinel.rcon.status,%i).data != $null ) { | |
if ( %names != $null ) var %names = %names $+ , | |
goto nextplayer | |
} | |
else { | |
if ( %names != $null ) msg $1 5Players: %names | |
var %names = $null | |
} | |
} | |
} | |
alias sentinel.notify { | |
;--Check individual channel notification rules | |
var %i = -1 | |
while ( %i <= $hget(sentinel.invited,0).item ) { | |
if ( %i == -1 ) { var %chan = $gettok($hget(sentinel.irc,monitor),1,32) } | |
elseif ( %i == 0 ) { var %chan = $gettok($hget(sentinel.irc,admin),1,32) } | |
else { var %chan = $hget(sentinel.invited,%i).item } | |
;--Setup status and channel rule variables | |
var %status.map = $hget(sentinel.server.status,map) | |
var %status.player.count = $hget(sentinel.server.status,player.count) | |
var %status.hostname = $hget(sentinel.server.status,hostname) | |
if ($hget(sentinel.server.status,sv_visiblemaxplayers) == -1) var %max = $hget(sentinel.server.status,player.max) | |
else var %max = $hget(sentinel.server.status,sv_visiblemaxplayers) | |
var %status.player.max = %max | |
var %rules.players = $gettok($hget([ sentinel.rules. $+ [ %chan ] ],players),3,32) | |
var %rules.maps = $gettok($hget([ sentinel.rules. $+ [ %chan ] ],maps),3-,32) | |
var %rules.type = $gettok($hget([ sentinel.rules. $+ [ %chan ] ],type),3,32) | |
var %rules.max = $gettok($hget([ sentinel.rules. $+ [ %chan ] ],max),3,32) | |
var %rules.min = $gettok($hget([ sentinel.rules. $+ [ %chan ] ],min),3,32) | |
var %rules.default.players = $gettok($hget(sentinel.rules.default,players),3,32) | |
var %rules.default.maps = $gettok($hget(sentinel.rules.default,maps),3-,32) | |
var %rules.default.type = $gettok($hget(sentinel.rules.default,type),3,32) | |
var %rules.default.max = $gettok($hget(sentinel.rules.default,max),3,32) | |
var %rules.default.min = $gettok($hget(sentinel.rules.default,min),3,32) | |
if ( %rules.players == $null ) { var %rules.players = %rules.default.players } | |
if ( %rules.maps == $null ) { var %rules.maps = %rules.default.maps } | |
if ( %rules.type == $null ) { var %rules.type = %rules.default.type } | |
if ( %rules.max == $null ) { var %rules.max = %rules.default.max } | |
if ( %rules.min == $null ) { var %rules.min = %rules.default.min } | |
;--Compare status to rules for channel, if a rule is broken, the loop continues on the next channel | |
if ( %status.player.count < %rules.players ) { inc %i | continue } | |
if ( %rules.type != notify ) { if ( $findtok($lower(%rules.maps),$lower(%status.map),1,32) != $null ) { inc %i | continue } } | |
else { if ( $findtok($lower(%rules.maps),$lower(%status.map),1,32) == $null ) { inc %i | continue } } | |
var %last.ctime = $hget([ sentinel.notify. $+ [ %chan ] ],last.ctime) | |
var %last.player.count = $hget([ sentinel.notify. $+ [ %chan ] ],last.player.count) | |
if ( $calc($ctime - %last.ctime) < %rules.min ) { inc %i | continue } | |
if ( (%status.players <= %last.player.count) && ($calc($ctime - %last.ctime) < %rules.max) ) { inc %i | continue } | |
;--All rules met with current status, send out the alert | |
var %info = 5 $+ %status.map is being played on 12 $+ %status.hostname $+ $chr(40) $hget(sentinel.server,address) $chr(41) 5with %status.player.count $+ $chr($asc(/)) $+ %status.player.max players! Join in on the carnage!! | |
msg %chan %info | |
hadd -m [ sentinel.notify. $+ [ %chan ] ] last.ctime $ctime | |
hadd -m [ sentinel.notify. $+ [ %chan ] ] last.player.count %status.player.count | |
inc %i | |
} | |
} | |
dialog sentinel.options { | |
title "Sentinel Bot Options" | |
size -1 -1 186 168 | |
option dbu | |
tab "General", 29, 1 0 182 149 | |
check "Automatically activate Sentinel Bot on IRC connection", 9, 6 17 144 10, tab 29 | |
edit "", 14, 29 37 50 10, tab 29 autohs | |
edit "", 18, 128 37 50 10, tab 29 autohs | |
edit "", 15, 29 48 50 10, tab 29 autohs | |
edit "", 21, 128 48 50 10, tab 29 autohs | |
edit "", 16, 29 59 50 10, tab 29 autohs | |
edit "", 22, 128 59 50 10, tab 29 autohs | |
edit "", 4, 50 85 67 10, tab 29 autohs | |
edit "", 5, 50 96 67 10, tab 29 autohs | |
edit "", 26, 30 121 138 10, tab 29 autohs | |
edit "", 27, 30 132 67 10, tab 29 autohs | |
box "IRC Channels", 10, 4 29 178 45, tab 29 | |
text "Admin:", 11, 7 39 22 8, tab 29 right | |
text "Admin Password:", 17, 81 39 47 8, tab 29 right | |
text "TV Password:", 19, 81 50 47 8, tab 29 right | |
text "TV:", 12, 7 50 22 8, tab 29 right | |
text "Monitor:", 13, 7 61 22 8, tab 29 right | |
text "Monitor Password:", 20, 81 61 47 8, tab 29 right | |
box "Server", 1, 4 77 178 34, tab 29 | |
text "Address:", 2, 7 87 43 8, tab 29 right | |
text "RCON Password:", 3, 7 98 43 8, tab 29 right | |
text "Example: 1.2.3.4:27015", 8, 118 87 60 8, disable tab 29 | |
text "File:", 24, 7 123 23 8, tab 29 right | |
text "Address:", 25, 7 134 23 8, tab 29 right | |
box "Logging", 23, 4 114 178 33, tab 29 | |
text "Example: 1.2.3.4:28888", 28, 98 134 60 8, disable tab 29 | |
button "...", 53, 169 122 9 8, tab 29 | |
tab "Default Rules", 30 | |
edit "", 43, 31 18 21 10, tab 30 autohs | |
edit "", 42, 31 29 21 10, tab 30 autohs | |
edit "", 41, 31 40 21 10, tab 30 autohs | |
edit "", 37, 9 63 71 10, tab 30 autohs right | |
list 36, 9 73 71 63, tab 30 sort size extsel | |
button "Add", 38, 81 63 30 10, tab 30 | |
button "Remove", 39, 81 74 30 10, tab 30 | |
radio "Ignore when Maps are played", 40, 89 105 82 10, tab 30 | |
radio "Notify when Maps are played", 47, 89 116 82 10, tab 30 | |
text "Minimum number of players, bots are not counted.", 44, 53 20 124 8, tab 30 | |
text "Shortest time in seconds before bot notifies again.", 45, 53 31 124 8, tab 30 | |
text "Longest time in seconds before bot notifies again.", 46, 53 42 124 8, tab 30 | |
box "Maps", 48, 4 53 178 94, tab 30 | |
text "Players:", 31, 6 20 25 8, tab 30 right | |
text "Type:", 33, 88 96 27 8, tab 30 | |
text "Min:", 34, 6 31 25 8, tab 30 right | |
text "Max:", 35, 6 42 25 8, tab 30 right | |
text ":Selected", 32, 19 136 23 8, tab 30 | |
text "0", 50, 7 136 12 8, tab 30 right | |
text ":Total", 51, 58 136 15 8, tab 30 | |
text "0", 52, 45 136 13 8, tab 30 right | |
tab "Features", 300 | |
box "TV Channel Display", 58, 4 17 178 59, tab 300 | |
check "Player connects and disconnects", 305, 9 26 92 10, tab 300 | |
check "Player IP and ID information upon connection", 310, 18 38 122 10, tab 300 | |
check "Team chat (say_team / mm2)", 315, 9 50 158 10, tab 300 | |
check "Allow RCON access to Ops in Admin channel", 325, 9 81 118 10, tab 300 | |
tab "Advanced", 59 | |
radio "Dynamic", 61, 9 26 33 10, tab 59 | |
radio "Static", 62, 9 38 32 10, tab 59 | |
box "Port Options", 68, 4 17 178 60, tab 59 | |
text "Preferrably in the Private Port range of 49152 through 65535", 60, 72 53 78 14, disable tab 59 | |
text "Log:", 66, 24 61 18 8, disable tab 59 right | |
edit "", 64, 42 60 23 10, disable tab 59 limit 5 | |
link "v0.0.0b - YYYY/MM/DD by EdGruberman", 49, 3 156 98 8 | |
button "OK", 6, 105 154 37 12, ok | |
button "Cancel", 7, 146 154 37 12, default cancel | |
} | |
on *:DIALOG:sentinel.options:sclick:53:{ | |
var %folder = $sdir($iif($did(26) != $null,$did(26),.),Select Log File Location) | |
did -ra sentinel.options 26 $iif(%folder != $null,%folder,$did(26)) | |
} | |
on *:DIALOG:sentinel.options:sclick:49:{ url -an $hget(sentinel.general,url) } | |
on *:DIALOG:sentinel.options:sclick:36:{ sentinel.options.update } | |
alias sentinel.options.update { | |
did -ra sentinel.options 50 $did(sentinel.options,36,0).sel | |
did -ra sentinel.options 52 $did(sentinel.options,36).lines | |
} | |
on *:DIALOG:sentinel.options:sclick:38:{ | |
;--Add entered map to list | |
var %map = $replace($did(37),$chr(32),$null) | |
if ( %map == $null ) { return } | |
did -i sentinel.options 36 1 %map | |
did -r sentinel.options 37 | |
sentinel.options.update | |
} | |
on *:DIALOG:sentinel.options:sclick:39:{ | |
;--Remove selected maps from list | |
var %i = $did(36,0).sel | |
while ( %i > 0 ) { | |
var %sel = $did(36,%i).sel | |
did -ra sentinel.options 37 $did(36,%sel) | |
did -d sentinel.options 36 %sel | |
dec %i | |
} | |
sentinel.options.update | |
} | |
on *:DIALOG:sentinel.options:sclick:61:{ | |
;--Dynamic ports selected | |
did -b sentinel.options 60,64,66 | |
} | |
on *:DIALOG:sentinel.options:sclick:62:{ | |
;--Static ports selected | |
did -e sentinel.options 60,64,66 | |
} | |
on *:DIALOG:sentinel.options:sclick:305:{ | |
;--Connects/Disconnects display toggled | |
if ( $did(305).state == 1 ) { did -e sentinel.options 310 } | |
else { did -b sentinel.options 310 } | |
} | |
on *:DIALOG:sentinel.options:init:0:{ | |
;--General Tab | |
if ( $hget(sentinel.general,autoactivate) == 1 ) { did -c sentinel.options 9 } | |
did -ra sentinel.options 14 $gettok($hget(sentinel.irc,admin),1,32) | |
did -ra sentinel.options 18 $gettok($hget(sentinel.irc,admin),2,32) | |
did -ra sentinel.options 15 $gettok($hget(sentinel.irc,tv),1,32) | |
did -ra sentinel.options 21 $gettok($hget(sentinel.irc,tv),2,32) | |
did -ra sentinel.options 16 $gettok($hget(sentinel.irc,monitor),1,32) | |
did -ra sentinel.options 22 $gettok($hget(sentinel.irc,monitor),2,32) | |
did -ra sentinel.options 4 $hget(sentinel.server,address) | |
did -ra sentinel.options 5 $hget(sentinel.server,rcon_password) | |
did -ra sentinel.options 26 $hget(sentinel.log,file) | |
did -ra sentinel.options 27 $hget(sentinel.log,address) | |
;--Default Rules Tab | |
didtok sentinel.options 36 32 $gettok($hget(sentinel.rules.default,maps),3-,32) | |
sentinel.options.update | |
did -ra sentinel.options 43 $gettok($hget(sentinel.rules.default,players),3,32) | |
did -ra sentinel.options 42 $gettok($hget(sentinel.rules.default,min),3,32) | |
did -ra sentinel.options 41 $gettok($hget(sentinel.rules.default,max),3,32) | |
if ( $gettok($hget(sentinel.rules.default,type),3,32) == ignore ) { did -c sentinel.options 40 } | |
else { did -c sentinel.options 47 } | |
;--Features Tab | |
if ( $hget(sentinel.general,show.connects) == 1 ) { did -c sentinel.options 305 } | |
else { did -b sentinel.options 310 } | |
if ( $hget(sentinel.general,show.ip) == 1 ) { did -c sentinel.options 310 } | |
if ( $hget(sentinel.general,show.sayteam) == 1 ) { did -c sentinel.options 315 } | |
if ( $hget(sentinel.general,allowrcon) == 1 ) { did -c sentinel.options 325 } | |
;--Advanced Tab | |
if ( $hget(sentinel.general,port.type) == dynamic ) { | |
did -c sentinel.options 61 | |
did -b sentinel.options 60,64,66 | |
} | |
else { | |
did -c sentinel.options 62 | |
did -e sentinel.options 60,64,66 | |
} | |
did -ra sentinel.options 64 $hget(sentinel.general,port.log) | |
;--Link | |
did -ra sentinel.options 49 $hget(sentinel.general,version) | |
;--If bot is activated, disable disruptive settings | |
if ( $hget(sentinel.general.status,activated) == 1 ) { did -b sentinel.options 14,15,16,4,61,62,64 } | |
} | |
on *:DIALOG:sentinel.options:sclick:6:{ | |
;--OK clicked, update all hash tables and save to ini file | |
hadd sentinel.general autoactivate $did(9).state | |
hadd sentinel.general show.connects $did(305).state | |
hadd sentinel.general show.ip $did(310).state | |
hadd sentinel.general show.sayteam $did(315).state | |
hadd sentinel.general allowrcon $did(325).state | |
hadd sentinel.general port.type $iif($did(62).state == 1,static,dynamic) | |
hadd sentinel.general port.log $did(64) | |
hsave -i sentinel.general sentinel.ini general | |
hadd sentinel.irc admin $did(14) $did(18) | |
hadd sentinel.irc tv $did(15) $did(21) | |
hadd sentinel.irc monitor $did(16) $did(22) | |
hsave -i sentinel.irc sentinel.ini irc | |
hadd sentinel.server address $did(4) | |
hadd sentinel.server rcon_password $did(5) | |
hsave -i sentinel.server sentinel.ini server | |
hadd sentinel.log file $did(26) | |
hadd sentinel.log address $did(27) | |
hsave -i sentinel.log sentinel.ini log | |
hadd sentinel.rules.default players $ctime Default $did(43) | |
hadd sentinel.rules.default min $ctime Default $did(42) | |
hadd sentinel.rules.default max $ctime Default $did(41) | |
hadd sentinel.rules.default type $ctime Default $iif($did(40).state == 1,ignore,notify) | |
var %i = 1 | |
hadd sentinel.rules.default maps $ctime Default | |
while ( %i <= $did(36).lines ) { | |
hadd sentinel.rules.default maps $ctime Default $gettok($hget(sentinel.rules.default,maps),3-,32) $did(36,%i) | |
inc %i | |
} | |
hsave -i sentinel.rules.default sentinel.ini rules.default | |
} | |
menu status,channel,menubar { | |
Sentinel Bot | |
.$iif($status != connected || $hget(sentinel.general.status,activated) == 1,$style(2)) Activate:sentinel.activate | |
.$iif($hget(sentinel.general.status,activated) != 1,$style(2)) Deactivate:sentinel.deactivate | |
.- | |
.Options...:{ if ( $dialog(sentinel.options).hwnd == $null ) { dialog -am sentinel.options sentinel.options } | dialog -v sentinel.options } | |
} | |
alias debug.binvar { | |
;--This is a generic routine that will output the contents of a binary variable to the status window | |
;--much like a network packet analyzer commonly displays such binary information. | |
var %header = _OFFSET__00 01 02 03 04 05 06 07___08 09 0A 0B 0C 0D 0E 0F___01234567 89ABCDEF | |
echo -s $str(_,$len(%header)) | |
echo -s $timestamp $2- | |
echo -s %header | |
var %offset = 0 | |
var %i = 1 | |
while (%i <= $bvar($1,0)) { | |
var %line = %line $+ $chr(32) $+ $base($bvar($1,%i),10,16,2) | |
var %char = $bvar($1,%i).text | |
if (($bvar($1,%i) < 33) || ($bvar($1,%i) > 126)) var %char = . | |
if ($calc((%i - 9) % 8) == 0) { | |
var %text = %text $+ $chr(32) $+ %char | |
} | |
else { var %text = %text $+ %char } | |
if (($calc(%i % 8) == 0) && ($calc(%i % 16) != 0)) { var %line = %line $+ $chr(32) $+ _ } | |
if (($calc(%i % 16) == 0) || (%i == $bvar($1,0))) { | |
if ((%i = $bvar($1,0)) && ($calc($bvar($1,0) % 16) > 0)) { | |
var %line = %line $+ $str($chr(32) $+ __,$calc(16 - ($bvar($1,0) % 16) - 8)) | |
if ($calc(16 - ($bvar($1,0) % 16) - 8) > 0) var %line = %line _ | |
var %ext = $calc(16 - ($bvar($1,0) % 16)) | |
if ( %ext > 8) var %ext = 8 | |
var %line = %line $str($chr(32) $+ __,%ext) | |
} | |
echo -s $base(%offset,10,16,8) %line _ %text | |
var %line, %text | |
var %offset = %offset + 16 | |
} | |
inc %i | |
} | |
echo -s $str(¯,$len(%header)) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment