From 6084cd474ac680b8663a3098f91a9e3ec7b0b4bd Mon Sep 17 00:00:00 2001 From: Brandon Cornejo Date: Thu, 10 Jan 2019 15:49:42 -0600 Subject: [PATCH] Map Door Text parser, beta mission timers --- .gitignore | 2 + commands.txt | 7 + config.tin | 4 +- mdt | 9 + mdtconfig.json | 55 +++++ src/actions.tin | 15 ++ src/aliases.tin | 1 + src/combat.tin | 4 +- src/deadletter.tin | 16 ++ src/gmcp.tin | 16 +- src/mdtparse.py | 332 +++++++++++++++++++++++++++++ src/missiontimers.tin | 24 +++ src/missiontimers/letters.tin | 116 ++++++++++ src/missiontimers/sausage_lite.tin | 56 +++++ src/missiontimers/sausages.tin | 79 +++++++ src/{timers.tin => spottimers.tin} | 0 src/tpamonitor.tin | 7 + 17 files changed, 737 insertions(+), 6 deletions(-) create mode 100644 .gitignore create mode 100644 commands.txt create mode 100755 mdt create mode 100644 mdtconfig.json create mode 100644 src/mdtparse.py create mode 100644 src/missiontimers.tin create mode 100644 src/missiontimers/letters.tin create mode 100644 src/missiontimers/sausage_lite.tin create mode 100644 src/missiontimers/sausages.tin rename src/{timers.tin => spottimers.tin} (100%) diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3d9995f --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +logs/*.log +logs/active/*.log diff --git a/commands.txt b/commands.txt new file mode 100644 index 0000000..5af16ad --- /dev/null +++ b/commands.txt @@ -0,0 +1,7 @@ +minimap: + clear && watch -c -n 0.25 -t 'clear && cat logs/minimap.log' + +timers: + clear && watch -t -n 5 cat xptimers.log + + diff --git a/config.tin b/config.tin index 272b80d..868d1a6 100644 --- a/config.tin +++ b/config.tin @@ -18,13 +18,15 @@ #READ {src/prompt.tin}; #READ {src/xpmonitor.tin}; #READ {src/tpamonitor.tin}; -#READ {src/timers.tin}; +#READ {src/spottimers.tin}; #READ {src/combat.tin}; #READ {src/deadletter.tin}; #READ {src/quow.tin}; #READ {src/magic.tin}; +#READ {src/missiontimers.tin}; + #SESSION {discworld} {discworld.starturtle.net} {4242}; #FORMAT {log_file} {logs/active/%t.log} {%Y-%m-%d}; diff --git a/mdt b/mdt new file mode 100755 index 0000000..f985447 --- /dev/null +++ b/mdt @@ -0,0 +1,9 @@ +#!/bin/sh + +# clear && watch --color -t -n 0.4 'python src/mdtparse.py logs/mapdoortext.log | tail -n `tput lines`' +clear && while true; do + output=$(python src/mdtparse.py logs/mapdoortext.log | tail -n `tput lines`); + clear; + echo "$output"; + sleep 0.3; +done diff --git a/mdtconfig.json b/mdtconfig.json new file mode 100644 index 0000000..5940f7c --- /dev/null +++ b/mdtconfig.json @@ -0,0 +1,55 @@ +{ + "default_npc_value": 1, + "bonus_player_value": -1, + "minimum_room_value": 1, + "show_hidden_room_count": false, + "custom_matches": [ + ["string/regex, colour, point, is_regex"], + + ["zero out these entries so they do not weigh room values"], + [".*rats{0,1}$", "", 0, true], + [".*cats{0,1}$", "", 0, true], + [".*dogs{0,1}$", "", 0, true], + [".*pigeons{0,1}$", "", 0, true], + ["skeleton warrior", "", 0, false], + [" truffle pig", "", 0, false], + ["giant fruitbat", "", 0, false], + ["fireflies", "", 0, false], + ["small blue light", "", 0, false], + [" cloud", "", 0, false], + ["tortoise", "", 0, false], + ["cockroach", "", 0, false], + + ["Bes Pelargic Highlights"], + ["student", "", 3, false], + ["imperial guard", "orange", 5, false], + ["^(.+?) (tang|sung|mcsweeney|fang|hong) bodyguards{0,1}$", "orange", 4, true], + ["^(.+?) (tang|sung|mcsweeney|fang|hong) noblem(en|an)$", "orange", 3, true], + ["^(.+?) (tang|sung|mcsweeney|fang|hong) captain$", "orange", 3, true], + + ["Djelibeybi Highlights"], + ["^(.+?) pries(t|ts|tess|tesses)$", "", 0, true], + ["ceremonial guard", "orange", 5, false], + ["palace guard", "orange", 2, false], + ["soldier", "", 2, false], + ["recruit", "", 2, false], + ["d'reg", "", 2, false], + + ["Ephebe Highlights"], + ["hoplite", "orange", 4, false], + ["citadel guard", "orange", 4, false], + ["philosopher", "", 2, false], + ["lad(y|ies)", "", 2, true], + + ["Sto Plains Highlights"], + ["knight", "orange", 4, false], + ["little old ladies", "orange", 2, false], + ["hunter grflx", "", 3, false], + ["grflx mentor", "", 3, false], + ["grflx adolescent", "", 2, false], + ["grflx worker", "", 3, false], + ["grflx workleader", "", 3, false], + + ["Valid colours: orange, "] + ] +} diff --git a/src/actions.tin b/src/actions.tin index dcf01e4..7ca671e 100644 --- a/src/actions.tin +++ b/src/actions.tin @@ -28,6 +28,21 @@ #NOP ==[Command Color Highlighting]== #SUB {%w %w with a total of %* item} {<148>%1 %2<099> with a total of <148>%3<099> item} +#NOP ==[Truffle Found]== +#HIGHLIGHT {The young truffle pig unearths a truffle from the ground.} {bold green}; + +#NOP ==[Attention Soul(s)]== +#ACTION {^{(?!Ryattenoki).+} tugs on your sleeve in a desperate attempt to get some attention.$} { + #showme {\a}; +}; + +#NOP ==[Copperhead Mines]== +#HIGHLIGHT {Something doesn't smell right. You take a sniff but the faint odour of rotten eggs makes you cough.} {bold green underscore}; +#ACTION {Something doesn't smell right. You take a sniff but the faint odour of rotten eggs makes you cough.} { + #showme {\a}; +}; + +#NOP ==[End Session On Quit]== #ACTION {Thanks for playing. See you next time.} { #end; } diff --git a/src/aliases.tin b/src/aliases.tin index aa1ea68..c0c691a 100644 --- a/src/aliases.tin +++ b/src/aliases.tin @@ -1,4 +1,5 @@ #ALIAS {setsize} {rows 300;cols 110}; +#ALIAS {setmsize} {rows 300;cols 60}; #ALIAS {^clear$} { #system {tput clear}; diff --git a/src/combat.tin b/src/combat.tin index aaa429b..0ddfb36 100644 --- a/src/combat.tin +++ b/src/combat.tin @@ -8,7 +8,8 @@ #HIGHLIGHT {^You {viciously |messily |barely |neatly |}{thrust|snick|fillet|poke|chop up|chop|jab|scratch|boot|kick|hit|tickle|hack|prick|shred|nick|cut|stab|perforate|pierce|impale|slice|skewer|take} {a sliver off |into |}%1{'?s?} %2 {on|with} %3} {$my_attacks_color}; #HIGHLIGHT {^You {viciously |messily |barely |neatly |}stab %1 {deeply |}in %2 with %3} {$my_attacks_color}; #HIGHLIGHT {^You stab %1 right through %2's %3} {$my_attacks_color}; -#HIGHLIGHT {^You {viciously |messily |barely |neatly |}{poke|kick|punch|jab|boot|tickle} %1 in %2} {$my_attacks_color}; +#HIGHLIGHT {^You {viciously |messily |barely |neatly |}{poke|kick|punch|jab|boot|tickle|kick out} %1 in %2} {$my_attacks_color}; +#HIGHLIGHT {^You {punch|kick out} at %1 but {his|her} %2 absorbs {some|most} of the blow\.$} {$my_attacks_color}; #NOP ==[My Specials]== @@ -16,6 +17,7 @@ #HIGHLIGHT {^You prepare to {stab|slice|trip|shove|impale|kick|punch} %2} {bold green}; #HIGHLIGHT {^You attempt to launch a powerful attack. %1} {bold red}; #HIGHLIGHT {^You launch a powerful attack. %1} {bold green}; +#HIGHLIGHT {^You launch a powerful attack, landing a %1} {bold green}; #HIGHLIGHT {^You try to {trip|shove} %1} {bold red}; #HIGHLIGHT {^You shove %1} {bold green}; #HIGHLIGHT {^You trip %1} {bold green}; diff --git a/src/deadletter.tin b/src/deadletter.tin index 5c4d0f3..90c734b 100644 --- a/src/deadletter.tin +++ b/src/deadletter.tin @@ -1,6 +1,15 @@ #CLASS {deadletter} {kill}; #CLASS {deadletter} {open}; +#VAR {difficult_customer_targets} { + {Triad Boss}{Triad [Boss]} + {Queen Shelox}{Queen Shelox} + {Ice Giants}{Ice Giants} + {Security guards}{Security Guards} + {Smuggler Captain}{Smuggler Captain} + {The Clown}{Ha'pennywise the Clown} +}; + #VAR {distant_land_targets} { {Boy Willie}{Boy [Willie]} {Disembowel-Meself-Honourably Dibhala}{Disembowel-Meself-Honourably [Dibhala]} @@ -40,6 +49,13 @@ #echo {$letter_solution_line}; }; } + + #foreach {$difficult_customer_targets[]} {target} { + #regex {$target} {$current_match_line} { + #format {letter_solution_line} {%c[DC] %c*%c Deliver to %c%s%c.} {bold blue} {bold yellow} {bold blue} {bold green} {$difficult_customer_targets[$target]} {bold blue}; + #echo {$letter_solution_line}; + }; + } }; }; diff --git a/src/gmcp.tin b/src/gmcp.tin index 036c05c..c76e2bf 100644 --- a/src/gmcp.tin +++ b/src/gmcp.tin @@ -27,7 +27,7 @@ #VAR GMCP[vitals] {%0}; #math {hploss} {$GMCP[vitals][hp] - $GMCP[oldvitals][hp]}; - #if {$hploss < -100} { + #if {$hploss < -150} { #echo {<139>HP IS FALLING! CAREFUL!<099>}; #showme {\a\a}; } @@ -35,6 +35,12 @@ update_prompt; } +#EVENT {IAC SB GMCP char.info IAC SE} +{ + #IF {$debug} { #SHOWME %1 }; + #VAR GMCP[charinfo] {%0}; +} + #EVENT {IAC SB GMCP room.info IAC SE} { #IF {$debug} { #SHOWME %1 }; @@ -49,7 +55,7 @@ #REPLACE {minimap} {u001b} {}; #SYSTEM {rm logs/minimap.log && touch logs/minimap.log}; - #LINE {log} {logs/minimap.log} {\n\n $minimap \n\n}; + #LINE {log} {logs/minimap.log} {\n\n$minimap}; #SYSTEM {sed -i -e 's/^/ /' logs/minimap.log}; } @@ -57,7 +63,9 @@ { #IF {$debug} { #SHOWME %1 }; #VAR GMCP[room][mdt] {%0}; - #LINE {log} {logs/mapdoortext.log} {\n\n\n %0}; + #REPLACE {GMCP[room][mdt]} {\\n} {}; + #SYSTEM {rm logs/mapdoortext.log && touch logs/mapdoortext.log}; + #LINE {log} {logs/mapdoortext.log} {$GMCP[room][mdt]}; } #EVENT {IAC WILL GMCP} @@ -66,7 +74,7 @@ #SEND {$IAC$DO$GMCP\}; #nop #SEND {$IAC$SB$GMCP Core.Hello { "client": "$CLIENT_NAME", "version": "$CLIENT_VERSION" } $IAC$SE\}; #SEND {$IAC$SB$GMCP Core.Hello { "client": "TinTin++", "version": "2.01.2" } $IAC$SE\}; - #SEND {$IAC$SB$GMCP Core.Supports.Set ["Char.Vitals", "room.info", "room.map", "room.writtenmap"] $IAC$SE\} + #SEND {$IAC$SB$GMCP Core.Supports.Set ["Char.Vitals", "room.info", "room.map", "room.writtenmap", "char.info"] $IAC$SE\} } #EVENT {PROGRAM START} diff --git a/src/mdtparse.py b/src/mdtparse.py new file mode 100644 index 0000000..739cd91 --- /dev/null +++ b/src/mdtparse.py @@ -0,0 +1,332 @@ +#!/usr/bin/env python + +import os +import re +import sys +import math +import json + + +class MapDoorText: + number_map = { + "a ": 1, + "an ": 1, + "the ": 1, + "one ": 1, + "two ": 2, + "three ": 3, + "four ": 4, + "five ": 5, + "six ": 6, + "seven ": 7, + "eight ": 8, + "nine ": 9, + "ten ": 10, + "eleven ": 11, + "twelve ": 12, + "thirteen ": 13, + "fourteen ": 14, + "fifteen ": 15, + "sixteen ": 16, + "seventeen ": 17, + "eighteen ": 18, + "nineteen ": 19, + "twenty ": 20, + "twenty-one ": 21, + "twenty-two ": 22, + "twenty-three ": 23, + "twenty-four ": 24, + "twenty-five ": 25, + "twenty-six ": 26, + "twenty-seven ": 27, + "twenty-eight ": 28, + "twenty-nine ": 29, + "thirty ": 30, + } + + direction_map = { + "north": "n", + "northeast": "ne", + "east": "e", + "southeast": "se", + "south": "s", + "southwest": "sw", + "west": "w", + "northwest": "nw", + "n": "n", + "ne": "ne", + "e": "e", + "se": "se", + "s": "s", + "sw": "sw", + "w": "w", + "nw": "nw", + } + colour_map = { + # http://terminal-color-builder.mudasobwa.ru/ + "orange": "\033[01;38;05;214m", + "reset": "\033[00;39;49m" + } + + def __init__(self): + self.return_value = [] + self.custom_matches = [] + + # Load the JSON configuration file + with open('mdtconfig.json', 'r') as config_file: + config = json.load(config_file) + + # Strip comments from custom matches + for match in config['custom_matches']: + if len(match) > 1: + self.custom_matches.append(match) + + self.default_npc_value = config['default_npc_value'] + self.bonus_player_value = config['bonus_player_value'] + self.minimum_room_value = config['minimum_room_value'] + self.show_hidden_room_count = config['show_hidden_room_count'] + + @staticmethod + def explode(div, mdt): + if div == '': + return False + pos, fragments = 0, [] + for m in re.finditer(div, mdt): + fragments.append(mdt[pos:m.start()]) + pos = m.end() + fragments.append(mdt[pos:]) + return fragments + + def parse_mdt(self, mdt_line): + # Make lower case, do initial replacements + mdt_line = mdt_line.lower() + mdt_line = mdt_line.replace(" are ", " is ") + mdt_line = mdt_line.replace(" black and white ", " black white ") + mdt_line = mdt_line.replace(" brown and white ", " brown white ") + mdt_line = mdt_line.replace("the limit of your vision is ", "the limit of your vision:") + mdt_line = mdt_line.replace(" and ", ", ") + mdt_line = mdt_line.replace(" is ", ", ") + mdt_table = self.explode(', ', mdt_line) + + data = { + 'last_direction': '', + 'last_enemy_line': '', + 'last_count': 0, + 'last_was_dir': 0, + 'enemies_by_square': [], + 'ignoring_exits': False, + 'entity_table': [], + 'room_id': 1, + 'room_value': 0, + 'longest_direction': 0, + 'nothing': True, + 'next_color': '' + } + exit_strings = ['doors ', 'a door ', 'exits ', 'an exit ', 'a hard to see through exit '] + + for entry in mdt_table: + if entry != "" and ' of a ' not in entry: + if entry.startswith(tuple(exit_strings)): + # print('Special exit, ignore this line? next line is processed...') + data['ignoring_exits'] = True + elif entry.startswith('the limit of your vision:'): + if data['last_count'] > 0: + this_square = [data['last_count'], data['last_direction'], data['room_id'], int(math.floor(data['room_value']))] + data['enemies_by_square'].append(this_square) + data['nothing'] = False + data['next_color'] = '' + data['room_id'] = data['room_id'] + 1 + data['room_value'] = 0 + data['last_direction'] = '' + data['last_enemy_line'] = '' + data['last_count'] = 0 + data['last_was_dir'] = 0 + else: + # find the quantity first + quantity = 1 + for nm_key in self.number_map: + if entry.startswith(nm_key): + quantity = self.number_map[nm_key] + entry = entry[len(nm_key):] + break + + is_direction = 0 + this_direction = '' + + if entry.startswith("northeast"): + is_direction = 1 + this_direction = "northeast" + elif entry.startswith("northwest"): + is_direction = 1 + this_direction = "northwest" + elif entry.startswith("southeast"): + is_direction = 1 + this_direction = "southeast" + elif entry.startswith("southwest"): + is_direction = 1 + this_direction = "southwest" + elif entry.startswith("north"): + is_direction = 1 + this_direction = "north" + elif entry.startswith("east"): + is_direction = 1 + this_direction = "east" + elif entry.startswith("south"): + is_direction = 1 + this_direction = "south" + elif entry.startswith("west"): + is_direction = 1 + this_direction = "west" + + if is_direction == 1: + if not data['ignoring_exits']: + # print('[handling direction, not exits]') + data['last_was_dir'] = 1 + + if data['last_direction'] != '': + data['last_direction'] = '{}, '.format(data['last_direction']) + + data['last_direction'] = '{}{} {}'.format( + data['last_direction'], quantity, self.direction_map[this_direction] + ) + else: + # print('[ignoring exits direction line]') + pass + else: + data['ignoring_exits'] = False + if data['last_was_dir'] == 1: + # reset count + if data['last_count'] > 0: + this_square = [data['last_count'], data['last_direction'], data['room_id'], int(math.floor(data['room_value']))] + data['enemies_by_square'].append(this_square) + data['nothing'] = False + data['next_color'] = '' + data['room_id'] = data['room_id'] + 1 + data['room_value'] = 0 + data['last_direction'] = '' + data['last_enemy_line'] = '' + data['last_count'] = 0 + data['last_was_dir'] = 0 + + data['next_color'] = '' + add_player_value = False + + # Special GMCP MDT colour codes + if entry[0:6] == 'u001b[': + # u001b[38;5;37mRuhsbaaru001b[39;49mu001b[0m + here = entry.index('m') + data['next_color'] = entry[7:here] + # entry = entry[here + 1:-20] + # entry = entry.replace('u001b', '') + entry = entry.replace('u001b', '\033') + + # Might be a second colour code for PK + if entry[0:6] == 'u001b[': + here = entry.index('m') + data['next_color'] = entry[7:here] + entry = entry[here + 1:-20] + add_player_value = True + + this_value = self.default_npc_value + + for custom_match in self.custom_matches: + if custom_match[3]: + # This is a regex match + rexp = re.compile(custom_match[0]) + if rexp.match(entry): + if custom_match[1] and custom_match[1] in self.colour_map: + entry = '{}{}{}'.format( + self.colour_map[custom_match[1]], + entry, + self.colour_map['reset'] + ) + this_value = custom_match[2] + else: + # This is a regular string match + if custom_match[0] in entry: + if custom_match[1] and custom_match[1] in self.colour_map: + entry = '{}{}{}'.format( + self.colour_map[custom_match[1]], + entry, + self.colour_map['reset'] + ) + this_value = custom_match[2] + + if add_player_value == True: + this_value = this_value + self.bonus_player_value + + data['room_value'] = data['room_value'] + (this_value * quantity) + + if quantity > 1: + entry = '{} {}'.format(quantity, entry) + data['entity_table'].append([data['room_id'], entry, data['next_color']]) + + data['last_count'] = data['last_count'] + quantity + if data['last_enemy_line'] != '': + data['last_enemy_line'] = '{}, '.format(data['last_enemy_line']) + data['last_enemy_line'] = '{}{}'.format(data['last_enemy_line'], entry) + + if data['nothing']: + self.return_value.append('Nothing seen, try elsewhere!') + else: + done_here = False + rooms_ignored = 0 + + data['enemies_by_square'].sort(key=lambda square: square[3]) + + # Grab shortest + for square in data['enemies_by_square']: + # Only show if this room meets the minimum value + if square[3] >= self.minimum_room_value and len(square[1]) > data['longest_direction']: + data['longest_direction'] = len(square[1]) + + for square in data['enemies_by_square']: + # Only show if this room meets the minimum value + if square[3] >= self.minimum_room_value: + done_here = False + fstring = '{{:<{}}} [{{}}] '.format(data['longest_direction']) + output = fstring.format(square[1], square[3]) + for entity in data['entity_table']: + if entity[0] == square[2]: + if done_here: + output = '{}, '.format(output) + output = '{}{}'.format(output, entity[1]) + done_here = True + if square[0] < 2: + output = '{} [{} thing]'.format(output, square[0]) + else: + output = '{} [{} things]'.format(output, square[0]) + self.return_value.append(output) + else: + rooms_ignored = rooms_ignored + 1 + + square = None + + for entity in data['entity_table']: + entity = None + + if rooms_ignored > 0 and self.show_hidden_room_count: + output = '({} rooms below your value limit of {})'.format(rooms_ignored, self.minimum_room_value) + self.return_value.append(output) + + +if __name__ == '__main__': + if len(sys.argv) < 2: + print('[error] No input provided.') + sys.exit() + + argument, mdt_line = sys.argv.pop(1), None + + # Is this a file passed to us? + if os.path.exists(argument): + with open(argument, 'r') as f: + mdt_line = f.readline() + + else: + mdt_line = argument + + mdt = MapDoorText() + mdt.parse_mdt(mdt_line) + + for line in mdt.return_value: + print(line) diff --git a/src/missiontimers.tin b/src/missiontimers.tin new file mode 100644 index 0000000..e6b7d7e --- /dev/null +++ b/src/missiontimers.tin @@ -0,0 +1,24 @@ +#CLASS {missiontimers} {kill}; +#CLASS {missiontimers} {open}; + +#NOP ==[ Load Sausage Mission stuff ]== +#READ {src/missiontimers/sausage_lite.tin}; + +#ALIAS {missions} { + #if {&missions} { #echo {Mission Timers:}; } { #return; }; + + #if {&missions[sausage]} { + #foreach {$missions[sausage][active_list][%*]} {player} { + #showme {\t$player is cooling down on sausage missions.}; + }; + + #foreach {$missions[sausage][retry_list][%*]} {player} { + #showme {\t$player is not able to request a new sausage mission.}; + }; + }; +}; + +#nop "#event {RECEIVED OUTPUT} {%0}" catches all the things.... one event trigger +#nop and process a bunch of stuff? + +#CLASS {missiontimers} {close}; diff --git a/src/missiontimers/letters.tin b/src/missiontimers/letters.tin new file mode 100644 index 0000000..a33f832 --- /dev/null +++ b/src/missiontimers/letters.tin @@ -0,0 +1,116 @@ +#CLASS {missiontimers_letters} {kill}; +#CLASS {missiontimers_letters} {open}; + +#NOP [1 = Local, 2= Far Away, 3 = Distant Lands, 4 = Difficult Customer] +#VAR {dead_letter_rewards} { + {4 Ankh-Morpork dollars}{1} + {8 Ankh-Morpork dollars}{2} + {3 Djelian talents and 5 Djelian tooni}{3} + {4 Lancre crowns and 2 Lancre shillings}{3} + {7 Ephebian decadrachmae and 2 Ephebian stater}{3} + {2 Ankh-Morpork ten-dollars}{3} + {2 Genuan forins and 5 Genuan livres}{3} + {1 Klatchian ten dinar and 2 Klatchian two dinar coins}{3} + {1 Agatean Empire ten-rhinu and 5 Agatean Empire rhinu}{3} + {7 Lancre crowns and 5 Lancre shillings}{4} + {2 Agatean Empire ten-rhinu and 5 Agatean Empire rhinu}{4} + {6 Djelian talents and 5 Djelian tooni}{4} + {4 Genuan forins and 3 Genuan livres}{4} + {3 Ankh-Morpork ten-dollars and 2 Ankh-Morpork dollars}{4} + {1 Ephebian mina and 5 Ephebian decadrachmae}{4} + {1 Agatean Empire fifty-rhinu and 2 Agatean Empire ten-rhinu}{5} + {9 Ankh-Morpork ten-dollars}{5} + {1 Lancre sovereign and 1 Lancre tencrown}{5} + {3 Ephebian minae and 5 Ephebian decadrachmae}{5} + {1 Genuan ducat and 2 Genuan forins}{5} +} + +#var {missions[letter][active_list]} {}; +#var {missions[letter][retry_list]} {}; + +#ALIAS {/letter_returned} { + #list {missions[letter][retry_list]} {find} {$GMCP[charinfo][name]} {letter_current}; + #if {$letter_current == 0} { + #list {missions[letter][retry_list]} {add} {$GMCP[charinfo][name]}; + #line sub variable { + #delay {600} { + #nop Print message + #format {letter_retry_line} {%c[MH] %c*%c %s%c can now request a new letter from Frank.} {bold blue} {bold yellow} {bold green}{$GMCP[charinfo][name]} {bold blue}; + #echo {$letter_retry_line}; + #unvar {letter_retry_line}; + + #nop Remove player from state list + #list {missions[letter][retry_list]} {find} {$GMCP[charinfo][name]} {letter_current_inner}; + #list {missions[letter][retry_list]} {delete} {$letter_current_inner}; + }; + }; + }; + #unvar {letter_current}; +}; + +#ALIAS {return letter} { + #send {return letter}; + /letter_returned; +}; + +#ACTION {^You offer to give a letter to Frank} { + /letter_returned; +}; + +#ACTION {^You have been awarded %d experience points and given %+} { + #nop You have been awarded 60407 experience points and given 2 Agatean Empire ten-rhinu and 5 Agatean Empire rhinu. + + -- Last difficulty completion seen for future salute trigger + local iLastDifficultyCompleted = 0 + + -- Detected a reward string, record a difficulty level in preperation for the salute line + function QuowMissionReward (sName, sLine, wildcards) + sCashValue = wildcards[1] + if (sQuowRewards[sCashValue] ~= nil) then + iLastDifficultyCompleted = sQuowRewards[sCashValue] + else + -- See if we were waiting for an Ozzie pottery timer? + if (IsTimer("StoPotteryWaiting_" .. sCurrentCharacter) == 0) then + AddTimer ("StoLatPottery_" .. sCurrentCharacter, 1, 0, 0, "", 1061, "QuowMissionNotify") + elseif (IsTimer("OCPennieMission_" .. sCurrentCharacter) == 0) then + AddTimer ("OCPennieLaced_" .. sCurrentCharacter, 1, 0, 0, "", 1061, "QuowMissionNotify") + end + end + end +} + + + + + + +#ACTION {^You salute smartly as you deliver a letter} { +-- Saw a successful delivery mission, start a timer if we have a known difficulty completion value +function QuowLetterSuccess (sName, sLine, wildcards) + if (bNotificationTimers ~= true) then + return + end + if (iLastDifficultyCompleted == 1) then + AddTimer ("DeadLetterLocal_" .. sCurrentCharacter, 1, 0, 0, "", 1061, "QuowMissionNotify") + elseif (iLastDifficultyCompleted == 2) then + AddTimer ("DeadLetterCloseby_" .. sCurrentCharacter, 1, 0, 0, "", 1061, "QuowMissionNotify") + elseif (iLastDifficultyCompleted == 3) then + AddTimer ("DeadLetterFaraway_" .. sCurrentCharacter, 1, 0, 0, "", 1061, "QuowMissionNotify") + elseif (iLastDifficultyCompleted == 4) then + AddTimer ("DeadLetterDistant_" .. sCurrentCharacter, 1, 0, 0, "", 1061, "QuowMissionNotify") + elseif (iLastDifficultyCompleted == 5) then + AddTimer ("DeadLetterDifficult_" .. sCurrentCharacter, 1, 0, 0, "", 1061, "QuowMissionNotify") + end + iLastDifficultyCompleted = 0 +end +}; + +#CLASS {missiontimers_letters} {close}; diff --git a/src/missiontimers/sausage_lite.tin b/src/missiontimers/sausage_lite.tin new file mode 100644 index 0000000..1e9f51f --- /dev/null +++ b/src/missiontimers/sausage_lite.tin @@ -0,0 +1,56 @@ +#CLASS {missiontimers_sausages} {kill}; +#CLASS {missiontimers_sausages} {open}; + +#var {missions[sausage][active_list]} {}; +#var {missions[sausage][retry_list]} {}; + +#nop You have four hours to deliver 150 fresh - line to start it all? +#ACTION {^You have four hours to deliver %d fresh} { + + #action {^Sam Slager says to%+you: I'll have to take care of this one later} { + #nop [A mission started, start checking for resignations]; + #nop Are we already waiting on a timer for this character? + #list {missions[sausage][retry_list]} {find} {$GMCP[charinfo][name]} {sausage_current}; + #if {$sausage_current == 0} { + #list {missions[sausage][retry_list]} {add} {$GMCP[charinfo][name]}; + #line sub variable { + #delay {600} { + #nop Print message + #format {sausage_retry_line} {%c[MH] %c*%c %s%c can now try a new sausage mission from Sam Slager.} {bold blue} {bold yellow} {bold green}{$GMCP[charinfo][name]} {bold blue}; + #echo {$sausage_retry_line}; + #unvar {sausage_retry_line}; + + #nop Remove player from state list + #list {missions[sausage][retry_list]} {find} {$GMCP[charinfo][name]} {sausage_current_inner}; + #list {missions[sausage][retry_list]} {delete} {$sausage_current_inner}; + }; + }; + }; + #unvar {sausage_current}; + }; + + #action {^Sam Slager says to%+you: Thank you, that's all} { + #nop [A mission started, start checking for completions]; + #nop Are we already waiting on a timer for this character? + + #list {missions[sausage][active_list]} {find} {$GMCP[charinfo][name]} {sausage_current}; + #if {$sausage_current == 0} { + #list {missions[sausage][active_list]} {add} {$GMCP[charinfo][name]}; + #line sub variable { + #delay {3600} { + #nop Print message + #format {sausage_timer_line} {%c[MH] %c*%c %s can get full XP for a sausage mission.} {bold blue} {bold yellow} {bold blue} {$GMCP[charinfo][name]}; + #echo {$sausage_timer_line}; + #unvar {sausage_timer_line}; + + #nop Remove player from state list + #list {missions[sausage][active_list]} {find} {$GMCP[charinfo][name]} {sausage_current_inner}; + #list {missions[sausage][active_list]} {delete} {$sausage_current_inner}; + }; + }; + }; + #unvar {sausage_current}; + }; +}; + +#CLASS {missiontimers_sausages} {close}; diff --git a/src/missiontimers/sausages.tin b/src/missiontimers/sausages.tin new file mode 100644 index 0000000..876651f --- /dev/null +++ b/src/missiontimers/sausages.tin @@ -0,0 +1,79 @@ +#CLASS {missiontimers_sausages} {kill}; +#CLASS {missiontimers_sausages} {open}; + +#NOP ======================= +#NOP ===== VARIABLES ===== +#NOP ======================= +#VARIABLE {missions[sausage]} { + {current_difficulty}{1} + {current_primer}{1} +} + +#NOP ======================= +#NOP ===== Aliases ===== +#NOP ======================= +#ALIAS {/sausage_mission_start} { + #unaction {^You have four hours to deliver %1 fresh %2 sausages to Sam Slager.$}; + #var {missions[sausage][current_difficulty]} {$missions[sausage][current_primer]}; + + #nop [A mission started, start checking for resignations] + #action {^Sam Slager says to %1 I'll have to take care of this one later.$} { + #unaction {^You have four hours to deliver %1 fresh %2 sausages to Sam Slager.$}; + #unaction {^Sam Slager says to %1 I'll have to take care of this one later.$}; + #unaction {^Sam Slager gives you %1{dollar|pence}%3$}; + + #line sub variable { + #delay {600} { + #format {sausage_retry_line} {%c[MH] %c*%c %s%c can now try a new sausage mission from Sam Slager.} {bold blue} {bold yellow} {bold green}{$GMCP[charinfo][name]} {bold blue}; + #echo {$sausage_retry_line}; + #unvar {sausage_retry_line}; + }; + }; + }; + + #nop [A mission started, start checking for completions] + #action {^Sam Slager gives you %1{dollar|pence}%3$} { + #unaction {^You have four hours to deliver %1 fresh %2 sausages to Sam Slager.$}; + #unaction {^Sam Slager says to %1 I'll have to take care of this one later.$}; + #unaction {^Sam Slager gives you %1{dollar|pence}%3$}; + + #if {$missions[sausage][current_difficulty]} { + #format {delayname} {sausage_easy_%s} {$GMCP[charinfo][name]}; + #line sub variable { + #delay {$delayname} { + #format {sausage_timer_line} {%c[MH] %c*%c %s last finished an unspiced sausage mission.} {bold blue} {bold yellow} {bold blue} {$GMCP[charinfo][name]}; + #echo {$sausage_timer_line}; + #unvar {sausage_timer_line}; + } {3600}; + }; + #unvar {delayname}; + }; + #else { + #line sub variable { + #format {delayname} {sausage_hard_%s} {$GMCP[charinfo][name]}; + #delay {$delayname} { + #format {sausage_timer_line} {%c[MH] %c*%c %s last finished a spiced sausage mission.} {bold blue} {bold yellow} {bold blue} {$GMCP[charinfo][name]}; + #echo {$sausage_timer_line}; + #unvar {sausage_timer_line}; + } {3600}; + }; + #unvar {delayname}; + }; + }; +}; + +#NOP ======================= +#NOP ===== Actions ===== +#NOP ======================= + +#NOP ==[Sausage Missions]== +#ACTION {^Sam Slager asks you: So, you want to try filling a sausage order? You'll have four hours to hunt %1, gather spices to mix into the ground meat, make %2 sausages from it, and deliver them to me. Are you up to it?$} { + #var {missions[sausage][current_primer]} {2}; + #action {^You have four hours to deliver %1 fresh %2 sausages to Sam Slager.$} { /sausage_mission_start; }; +}; +#ACTION {^Sam Slager asks you: So, you want to try filling a sausage order? You'll have four hours to hunt %1, make %2 sausages from it, and deliver them to me. Are you up to it?$} { + #var {missions[sausage][current_primer]} {1}; + #action {^You have four hours to deliver %1 fresh %2 sausages to Sam Slager.$} { /sausage_mission_start; }; +}; + +#CLASS {missiontimers_sausages} {close}; diff --git a/src/timers.tin b/src/spottimers.tin similarity index 100% rename from src/timers.tin rename to src/spottimers.tin diff --git a/src/tpamonitor.tin b/src/tpamonitor.tin index 947c4b8..8c0256f 100644 --- a/src/tpamonitor.tin +++ b/src/tpamonitor.tin @@ -66,6 +66,13 @@ update_prompt; } +#nop ### alias to reset TPA status, if it breaks and we didn't catch it ### +#alias {tpareset} { + #unvar {tpa_start}; + #unvar {tpa_end}; + #var {tpa_status} {0}; +} + #var {tpa_status} {0}; #CLASS {tpamonitor} {close};