Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- =begin
- SAlert by SpiffyJr
- author: SpiffyJr
- name: SpiffyAlert
- tags: scripting, alert
- changelog:
- 2018.03.14 - initial rewrite version
- =end
- require 'xmpp4r'
- if $SAFE > 0
- echo "error: This script needs to be trusted to work. (;trust #{script.name})"
- exit
- end
- # <pushBold/>A <a exist="92672744" noun="brigand">giantman brigand</a><popBold/> slashes with a troll-claw at you!
- class SAlert
- @@version = '2018.03.14'
- @@attack = '(?:(?:make a precise )?attempt|gesture|trace|aim|fire|swing|slash|charge|snaps at|thrust|spins a web|punch|weave|concentrate|channel|hurl|stomp|pound|bite|tries to ensare|claw)e?s?'
- def SAlert.version
- @@version
- end
- def initialize(settings)
- @attack_started = false
- @wait_for_prompt = false
- @respond_cmd = false
- @buffer = []
- @last_send = Time.now.to_f
- @client = nil
- @settings = settings
- end
- def remove_line(line)
- if (line === 'all')
- @settings[:lines] = {}
- return true
- end
- line = self.clean_xml(line)
- if not @settings[:lines][self.clean_xml(line)]
- return false
- end
- @settings[:lines].delete(self.clean_xml(line))
- return true
- end
- def handle_message(msg)
- echo("received message: #{msg.body}")
- if msg.type == :error
- echo('error, invalid message received')
- elsif msg.body =~ /^,([^\s]+)(?:\s(.*))?/
- cmd = $1
- args = $2
- if cmd =~ /clear/i
- res = self.remove_line(args)
- if args === 'all'
- self.message('cleared all lines')
- elsif res
- self.message('line cleared')
- else
- self.message('line not found')
- end
- elsif cmd =~ /save/i
- @settings[:lines_saved] = @settings[:lines].clone
- self.message('lines saved for future use')
- elsif cmd =~ /restore/i
- @settings[:lines] = @settings[:lines_saved].clone
- self.message('saved lines restored')
- elsif cmd =~ /town/i
- self.go2_town()
- elsif cmd =~ /chat/i
- self.message("sending \"chat #{args}\" to lnet")
- send_to_script('lnet', "chat #{args}")
- else
- self.message("unknown command: #{cmd}")
- end
- elsif msg.body !~ /^;/
- self.message("> #{msg.body}")
- clear()
- @respond_cmd = true
- put(msg.body)
- end
- true
- end
- def clean_xml(xml)
- # strip any "a" links first which should remove all the npcs, characters, random lewt, etc.
- xml.gsub!(/(?:some |an? )?<a exist="[^"]+" noun="[^"]+">[^<]+<\/a>/i, '')
- # strip any xml characters
- xml.gsub!(/<[^>]+>/, '')
- # lower-case only
- xml.downcase!
- # replace some generic words
- xml.gsub!(/(?:north|east|south|west|up|down|out)/i, '')
- # strip non-alpha chars
- xml.gsub!(/[^a-zA-Z]/, '')
- xml.strip
- end
- def disconnect()
- return if @settings[:debug]
- if not @client
- return
- end
- @client.close()
- @client = nil
- echo('info: disconnected')
- end
- def connect()
- return if @settings[:debug]
- if @client
- return
- end
- echo('info: connecting to remote server')
- begin
- @client = Jabber::Client::new(Jabber::JID::new(@settings[:username]))
- @client.keepalive_interval = 30
- @client.connect
- @client.auth(@settings[:password])
- @client.send(Jabber::Presence.new.set_type(:available))
- rescue
- @client = nil
- echo("info: failed to connect: #{$!}")
- return
- end
- # handle received messages
- @client.add_message_callback { |msg| self.handle_message(msg) }
- echo('info: connected')
- end
- def message(msg)
- if $frontend == 'stormfront'
- fam_window_begin = "<pushStream id=\"familiar\" ifClosedStyle=\"watching\"/>"
- fam_window_end = "<popStream/>\r\n"
- else
- fam_window_begin = "\034GSe\r\n"
- fam_window_end = "\034GSf\r\n"
- end
- puts("#{fam_window_begin}#{msg}\r\n#{fam_window_end}")
- return if @settings[:debug]
- @buffer.push(msg)
- end
- def process(input)
- xml = input[:xml].clone
- line = xml.gsub(/<[^>]+>/, '').strip
- # skip if the line is empty after xml is stripped
- return if line.length === 0
- # check player attack lines
- if @attack_started
- if xml =~ /Roundtime:? \d/i
- @attack_started = false
- end
- return
- elsif xml =~ /You #{@@attack}.*<pushBold\/>(?:The|An?) <a exist="[^"]+" noun="[^"]+">[^<]+<\/a><popBold\/>/i
- @attack_started = true
- return
- end
- # some things require waiting on the next prompt line from the game
- if @wait_for_prompt
- if xml =~ /<prompt time="[^"]+">/
- @wait_for_prompt = false
- end
- return
- elsif xml =~ /flies out of the shadows toward/
- @wait_for_prompt = true
- return
- elsif xml =~ /You search (?:the|an?) <a exist="[^"]+" noun="[^"]+">[^<]+<\/a><popBold\/>/i
- # NPC searches
- @wait_for_prompt = true
- return
- elsif xml =~ /<pushBold\/>(?:The|An?) <a exist="[^"]+" noun="[^"]+">[^<]+<\/a><popBold\/> #{@@attack}/i
- # NPC attacks
- @wait_for_prompt = true
- return
- elsif xml =~ /<a exist="-\d+" noun="[^"]+">[^<]+<\/a> #{@@attack}.*<pushBold\/>(?:The|An?) <a exist="[^"]+" noun="[^"]+">[^<]+<\/a><popBold\/>/i
- # Player attacks
- @wait_for_prompt = true
- return
- end
- # skip anything with inventory as an id
- if input[:inv].length > 0
- return if xml =~ /<a exist="#{input[:inv].reject { |i| i.id.nil? }.collect { |i| i.id }.join('|')}" noun="([^"]+)">([^<]+)<\/a>/
- end
- # skip other GameObj based lines
- if xml =~ /<a exist="(-?\d+)" noun="([^"]+)">([^<]+)<\/a>/
- id = $1
- noun = $2
- name = $3
- # check npcs now
- if not (obj = input[:npcs].find { |npc| npc.id == id })
- obj = GameObj.new(id, noun, name)
- end
- # skip aggressive npcs, escorts, companions, passive npcs, etc.
- return if obj.type =~ /aggressive|escort|passive|familiar|companion/
- # check if they're a pc and skip unless they're speaking
- if obj.id.to_i < 0 and obj.id.to_s.length === 9
- if xml =~ /<pushStream id="speech"/i
- # we alert here we just don't store it because it's speech
- self.message(line)
- end
- return
- end
- end
- # private messages from LNet get sent directly (alert, but don't store)
- if xml =~ /\[Private\]-(\w+):(\w+): "([^"]+)"/
- self.message("[Private]-#{$1}:#{$2}: \"#{$3}\"")
- return
- end
- # skip the Zul Logoth carts
- if input[:room] == 19547
- return
- end
- # skip certain rooms
- if Room[input[:room]]
- room = Room[input[:room]]
- # Voln rooms
- return if room.title.include?('[Path to Enlightenment]')
- # Room tags that match
- return if room.tags.any? { |t| @settings[:ignore_tags].include?(t) }
- end
- # skip when certain scripts are running
- return if input[:scripts].any? { |s| @settings[:ignore_scripts].include?(s) }
- # skip prompts (don't move me around - stuff above checks for prompts to know when to stop)
- return if xml =~ /<prompt time="\d+">[^<]+<\/prompt>/
- # skip room titles and descriptions
- return if xml =~ /(?:<style id="roomDesc|roomName" \/>|<compDef id='room desc|room objs'>)/
- # skip pushStreams
- return if xml =~ /<pushStream/i
- # skip our own talk lines
- return if xml =~ /<preset id='speech'>[^<]+<a exist="[^"]+" coord="[^"]+" noun="help">[^<]+<\/a>/
- if (cleaned = self.clean_xml(xml.clone)).length == 0
- return
- end
- if not @settings[:lines][cleaned]
- self.message(line)
- @settings[:lines][cleaned] = true
- end
- end
- def send()
- if @buffer.empty? or Time.now.to_f - @last_send < 1.0
- return
- end
- # take the next 25 lines and send at once
- line = @buffer.shift(25).join("\n")
- msg = Jabber::Message::new(@settings[:receiver], line)
- msg.type = :chat
- if not @client
- self.connect()
- end
- begin
- @client.send(msg)
- rescue
- echo("info: failed to send: #{$!}")
- echo("info: retrying once")
- self.disconnect()
- self.connect()
- @client.send(msg)
- end
- @last_send = Time.now.to_f
- end
- def run()
- loop do
- xml = get?
- self.send()
- if xml
- if @respond_cmd
- if xml =~ /<prompt time="\d+">[^<]+<\/prompt>/
- @respond_cmd = false
- clear()
- else
- self.message(xml.gsub(/<[^>]+>/, '').strip)
- end
- else
- self.process({
- :inv => [GameObj.left_hand] + [GameObj.right_hand] + GameObj.inv.to_a.clone,
- :npcs => GameObj.npcs.to_a,
- :pcs => GameObj.pcs.to_a,
- :room => Room.current.id,
- :scripts => Script.running.collect { |s| s.name },
- :xml => xml,
- })
- end
- end
- sleep(0.10)
- end
- end
- end
- default_settings = {
- :lines => [{}, ''],
- :lines_saved => [{}, ''],
- :debug => [false, 'enable debug mode (no sending messages)'],
- :ignore_scripts => [['sloot', 'slootbeta', 'useherbs'], 'scripts to ignore'],
- :ignore_tags => [['town', 'consignment', 'pawnshop', 'locksmith', 'gemshop', 'herbalist', 'bank', 'furrier', 'chronomage', 'advguard', 'advguild', 'advguild2'], 'room tags to ignore'],
- :password => ['', 'password to login to XMPP with'],
- :receiver => ['', 'who to send alerts to'],
- :username => ['', 'username to login to XMPP with'],
- }
- settings = CharSettings.to_hash
- default_settings.each do |k, v|
- if settings[k].nil?
- settings[k] = v[0]
- end
- end
- settings.delete_if { |setting, value| default_settings[setting].nil? }
- if script.vars[1] == 'help'
- print_option = proc do |option, msg, eg = "", pad = 2|
- if eg != ""
- msg = sprintf("%-40s #{$lich_char}#{script.name} #{eg}", msg)
- end
- respond(sprintf(" %s%-25s %s", " " * pad, option, msg))
- end
- respond("SAlert #{SAlert.version} by SpiffyJr (Kips)")
- respond("")
- respond("SAlert is a script to alert you to messages you haven't seen before.")
- respond("")
- respond("Basic usage: #{$lich_char}#{script.name}")
- respond("")
- respond("Extra commands:")
- print_option.call("help", "show this help message")
- print_option.call("list", "list current settings")
- elsif script.vars[1] == 'list'
- respond('======================')
- respond('SAlert settings')
- respond('======================')
- settings.sort.each do |k, v|
- if k == :lines or k == :lines_saved
- # skip showing lines
- elsif v.class == Array
- puts("#{monsterbold_start}#{k}#{monsterbold_end}: #{v.sort.join(', ')}")
- else
- puts("#{monsterbold_start}#{k}#{monsterbold_end}: #{v}")
- end
- end
- elsif script.vars[0] =~ /^([^\s]+)(.*)?$/ and not settings[$1.downcase.strip.to_sym].nil?
- setting = $1.downcase.to_sym
- value = $2.strip.downcase
- action = nil
- if not defined?(settings[setting]) or settings[setting].nil?
- echo "** setting \"#{setting}\" does not exist"
- exit
- end
- if value =~ /^([+-])(.*)$/
- action = $1
- value = $2.strip.downcase
- end
- if settings[setting].class == Array
- settings[setting].delete(value)
- if action == '-'
- echo "-- \"#{value}\" removed from \"#{setting}\""
- else
- settings[setting].push(value)
- echo "-- \"#{value}\" added to \"#{setting}\""
- end
- echo "-- \"#{setting}\" is now \"#{settings[setting].sort.join(', ')}\""
- else
- if settings[setting].class == FalseClass or settings[setting].class == TrueClass
- value = (value =~ /^true|1|yes|on/) ? true : false
- elsif settings[setting].class == Fixnum
- value = value.to_i
- end
- echo "-- set \"#{setting}\" to \"#{value}\""
- settings[setting] = value
- end
- elsif script.vars[1] == 'clear'
- $salert = SAlert.new(settings)
- res = $salert.remove_line(script.vars[2])
- if script.vars[2] === 'all'
- echo '-- cleared all lines'
- elsif res
- echo '-- line cleared'
- else
- echo '-- line not found'
- end
- elsif script.vars[1] == 'update'
- Script.run('repository', 'download salert')
- echo '-- updated'
- elsif not script.vars[1].nil?
- echo "** You're doing it wrong! Try #{$lich_char}#{script.name} help"
- else
- script.want_downstream = false
- script.want_downstream_xml = true
- $salert = SAlert.new(settings)
- $salert.connect()
- Thread.new do
- loop do
- wait_until { bleeding? }
- $salert.message('You are bleeding!')
- wait_while { bleeding? }
- $salert.message('You are no longer bleeding!')
- end
- end
- Thread.new do
- loop do
- if dead?
- $salert.message('You just died! Exiting game in 5 seconds...')
- sleep(5)
- fput "quit"
- end
- if not $favor.nil?
- favor_to_step = (Society.rank*100)+(((XMLData.level**2)*(((Society.rank+2)/3)*5))/3)
- favor_percent = $favor[:step]/favor_to_step.to_f*100
- if favor_percent > 100
- $salert.message('You are ready for your next voln step')
- wait_while { $favor[:step]/favor_to_step.to_f*100 > 100 }
- end
- end
- sleep(1)
- end
- end
- $salert.run()
- end
Add Comment
Please, Sign In to add comment