TF - tracking script

by Unknown

Back to Mechanic's Corner.

Unknown2005-05-07 05:06:01
Over the past week I've spent a substantial amount of time learning TF a bit better. I've learned quite a bit, this tracking script is the product of that work. I'll list the features first, then the code. I don't think the code will be extremely useful to anyone "out of the box" without my other scripts. This script takes advantage of an "array.tf" file I found online that adds array variables to TF, also includes macros for accessing, altering, and examining them.

I'm going to add a separate topic to the Mechanic's section with a link so you can download all of my TF script files. That set of files will be much more helpful to you. Im posting this file separatly because it does some interesting things, and I figure some people might learn a few things from it (worst case scenario it's a nice code example to learn from).

I designed this script in a way that allows others to easily customize it for their own needs. All of the real complicated and difficult work is done in a few macros (/def's), whose purpose is commented well with the syntax needed to use them. These macros are intended for use in aliases you create to do what you need to get done. The macros are tools for you to use, more or less. You shouldn't really need to mess with the macros at all. This method hides all of the complicated details, giving you the power to create some real nifty things with simple code. It makes it easier to update and maintain your aliases too, because they're simple. Reading through the comments in the code, and the aliases I created for myself, will give you a better idea of what I mean.

player highlighting and stack management
This script revolves around a set of stacks (implemented by a variable of space separated words - stack-q.tf). Each stack is related to a type of players I wish to track. There are two type of stacks, dynamic and static. Dynamic stacks are always changing. These stacks have associated /def's that automatically populate them with values, and are executed every so many minutes. One defines my citymates, one my guildmates, and the other my cityenemies. Static stacks are ones that are not updated automatically in this way. I have one for official enemies, allies, suppliers, and marks.

The player highlighting is on a priority system. You can have one person in multiple lists. For example, I might have one person in my citymates, guildmates, and marked lists. When his name is seen in TF he will appear as a mark, because I gave it a higher priority than citymates and guildmates. If he wasn't marked, he'd be colored as a guildmate because I gave it a higher priority than citymates. And so on.

All of the highlighting is logged nicely by the colored logger I wrote (check my next post for the file of all my scripts).

- Ability to save/load stacks to files (2 macros do the work, aliases were created for each stack type).
- Macros for use in CONNECT/DISCONNECT hooks to automatically load/save stacks for you when you start/close TF.
- Macros to add, remove, and list highlighted players. Aliases were created for each stack type to facilitate adding/removing players (enemy/unenemy, citymate/uncitymate, mark/unmark, etc).
- Macros to populate dynamic stacks (citymates, guildmates, cityenemies), and a macro to have them automatically repopulated every x number of seconds.

player locating
Thirdeye is a great skill, this section of the script gives you many commands to really take advantage of it.

- Macro to locate one or more players (space separated list of names as argument)
- Macro to list all players at a location (partial or full name as argument)
- Macro to list location of a specified player, and all those at his/her location (single name as argument)
- There are then a slew of aliases to take advantage of these three macros. Since they accept lists of names as arguments, it's very easy to just throw them the player highlighting stacks to locate a group of people. Examples: "loce" locates all enemies, "locc" locates all citymates, etc.

This probably isn't as much detail as you'd like as far as features go, but I don't feel like writing about it anymore! I've got other code/ideas I'm working on, and Daevos and Ixion are going to be pissed if I don't start playing more often. The code is commented pretty well, and I use long macro/variable names to make the code very readable...well...as readable as TF code can be. If you're looking to use this script as-is, I'd STRONGLY recommend checking out my next post to obtain all of the files and start with that. Taking this file on it's own without the others is like remove the engine and tires from your car...not very smart and a pain in the ass. smile.gif

Here's the code, you can see a syntax highlighted copy of it on my website at http://www.bwbettin.com/files/tracking.tf.html
CODE
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;               player highlighting stack management              ;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

/set stack_unofficial_enemy=
/set stack_official_enemy=
/set stack_ally=
/set stack_supplier=
/set stack_citymate=
/set stack_guildmate=
/set stack_mark=



;;; write the contents of a player highlighting stack variable to a file
;;; syntax: /save_player_highlight_stack
;;; note: stack variables should be named "stack_", files should be named ".txt"
/def save_player_highlight_stack = \\
   /if ({#} > 0) \\
       /let stack_name=$ %; \\
       /let stack_value= %; \\
       /test stack_value:=%{stack_name} %; \\
       /let stack_filename=$ %; \\
       /let stack_file=$ %; \\
       /test tfwrite({stack_file},{stack_value}) %; \\
       /test tfclose({stack_file}) %; \\
       /echol BCcyan 0 <<<< the contents of your %{1} list were saved. >>>> %; \\
   /else \\
       /echol BCcyan 0 <<<< stack_save error: you must provide a highlight type. >>>> %; \\
   /endif

;;; load the contents of a player highlighting stack variable from a file
;;; syntax: /load_player_highlight_stack
;;; note: stack variables should be named "stack_", files should be named ".txt"
/def load_player_highlight_stack = \\
   /if ({#} > 0) \\
       /let stack_name=$ %; \\
       /let stack_filename=$ %; \\
       /let stack_file=$ %; \\
       /test tfread({stack_file},%{stack_name}) %; \\
       /test tfclose({stack_file}) %; \\
       /echol BCcyan 0 <<<< the contents of your %{1} list were loaded. >>>> %; \\
   /else \\
       /echol BCcyan 0 <<<< stack_load error: you must provide a highlight type. >>>> %; \\
   /endif

;;; save the contents of all non-dynamic player highlighting stacks (intended for use with DISCONNECT hooks)
;;; note: non-dynamic stacks are those that do not have /define macros for use with /repeat
/def save_nondynamic_player_highlight_stacks = \\
   /save_player_highlight_stack official_enemy %; \\
   /save_player_highlight_stack ally %; \\
   /save_player_highlight_stack supplier %; \\
   /save_player_highlight_stack mark

;;; load the contents of all non-dynamic player highlighting stacks (intended for use with CONNECT hooks)
;;; note: non-dynamic stacks are those that do not have /define macros for use with /repeat
/def load_nondynamic_player_highlight_stacks = \\
   /load_player_highlight_stack official_enemy %; \\
   /load_player_highlight_stack ally %; \\
   /load_player_highlight_stack supplier %; \\
   /load_player_highlight_stack mark

;;; add an entry to a player highlighting stack
;;; syntax: /player_highlight_add
;;; note: stack variables should be named "stack_"
/def player_highlight_add = \\
   /if ({#} > 4) \\
       /let stack_name=$ %; \\
       /let stack_value= %; \\
       /test stack_value:=%{stack_name} %; \\
       /let stack_players=%{-4} %; \\
       /while ({stack_players} !~ "") \\
           /let current_player=$(/pop stack_players) %; \\
           /if (regmatch(strcat("\\\\b",{current_player},"\\\\b"),{stack_value}) == 0) \\
               /def -mregexp -n0 -p%{3} -F -P1x%{4} -t"\\\\b(%{current_player})\\\\b" highlight_%{2}_%{current_player} %; \\
               /push %{current_player} %{stack_name} %; \\
               /if ({1} == 0) \\
                   /echol BCcyan 0 <<<< %{current_player} is %{2} highlighted. >>>> %; \\
               /endif %; \\
           /else \\
               /if ({1} == 0) \\
                   /echol BCcyan 0 <<<< %{current_player} is already %{2} highlighted. >>>> %; \\
               /endif %; \\
           /endif %; \\
       /done %; \\
   /else \\
       /if ({1} == 0) \\
           /echol BCcyan 0 <<<< player_highlight_add error: correct arguments are . >>>> %; \\
       /endif %; \\
   /endif

;;; remove an entry to a player highlighting stack
;;; syntax: /player_highlight_remove
;;; note: stack variables should be named "stack_"
/def player_highlight_remove = \\
   /if ({#} > 2) \\
       /let stack_name=$ %; \\
       /let stack_value= %; \\
       /test stack_value:=%{stack_name} %; \\
       /let stack_players=%{-2} %; \\
       /while ({stack_players} !~ "") \\
           /let current_player=$(/pop stack_players) %; \\
           /if (regmatch(strcat("\\\\b",{current_player},"\\\\b"),{stack_value}) > 0) \\
               /undef highlight_%{2}_%{current_player} %; \\
               /set %{stack_name}=$(/remove %{current_player} %{stack_value}) %; \\
               /test stack_value:=%{stack_name} %; \\
               /if ({1} == 0) \\
                   /echol BCcyan 0 <<<< %{current_player} is no longer %{2} highlighted. >>>> %; \\
               /endif %; \\
           /else \\
               /if ({1} == 0) \\
                   /echol BCcyan 0 <<<< %{current_player} is not %{2} highlighted. >>>> %; \\
               /endif %; \\
           /endif %; \\
       /done %; \\
   /else \\
       /if ({1} == 0) \\
           /echol BCcyan 0 <<<< player_highlight_remove error: correct arguments are . >>>> %; \\
       /endif %; \\
   /endif

;;; list the entries in a player highlighting stack
;;; syntax: /player_highlight_list
;;; note: stack variables should be named "stack_"
/def player_highlight_list = \\
   /if ({#} == 1) \\
       /let stack_name=$ %; \\
       /let stack_value= %; \\
       /test stack_value:=%{stack_name} %; \\
       /echol BCcyan 0 <<<< %{1}: %{stack_value} >>>> %; \\
   /else \\
       /echol BCcyan 0 <<<< player_highlight_list error: you must provide the highlight type. >>>> %; \\
   /endif

;;; utility macros for dealing with lists (intended for use with /mapcar)
/def sendl_enemy = /sendl enemy %{1}
/def sendl_unenemy = /sendl unenemy %{1}
/def sendl_ally = /sendl ally %{1}
/def sendl_unally = /sendl unally %{1}

;;; aliases to save/load the contents of a non-dynamic player highlighting list
/alias saveenemy /save_player_highlight_stack official_enemy
/alias loadenemy /load_player_highlight_stack official_enemy
/alias saveally /save_player_highlight_stack ally
/alias loadally /load_player_highlight_stack ally
/alias savesupplier /save_player_highlight_stack supplier
/alias loadsupplier /load_player_highlight_stack supplier
/alias savemark /save_player_highlight_stack mark
/alias loadmark /load_player_highlight_stack mark

;;; add/remove unofficial enemy highlights
;;; syntax: enemyh
;;;         unenemyh
/alias enemyh \\
   /if ({#} > 0) \\
       /player_highlight_add 0 unofficial_enemy 220 Cred %{*} %; \\
   /else \\
       /player_highlight_list unofficial_enemy%; \\
   /endif
/alias unenemyh \\
   /if ({#} > 0) \\
       /if ({1} =~ "all") \\
           /player_highlight_remove 0 unofficial_enemy %{stack_unofficial_enemy} %; \\
       /else \\
           /player_highlight_remove 0 unofficial_enemy %{*} %; \\
       /endif %; \\
   /else \\
       /echol BCcyan 0 <<<< unenemyh error: you must supply a list of players. >>>> %; \\
   /endif

;;; add/remove official enemy highlights
;;; syntax: enemy
;;;         unenemy
/alias enemy \\
   /if ({#} > 0) \\
       /mapcar /sendl_enemy %{*} %; \\
       /player_highlight_add 0 official_enemy 219 BCred %{*} %; \\
   /else \\
       /player_highlight_list official_enemy%; \\
   /endif
/alias unenemy \\
   /if ({#} > 0) \\
       /if ({1} =~ "all") \\
           /mapcar /sendl_unenemy %{stack_official_enemy} %; \\
           /player_highlight_remove 0 official_enemy %{stack_official_enemy} %; \\
       /else \\
           /mapcar /sendl_unenemy %{*} %; \\
           /player_highlight_remove 0 official_enemy %{*} %; \\
       /endif %; \\
   /else \\
       /echol BCcyan 0 <<<< unenemyh error: you must supply a list of players. >>>> %; \\
   /endif

;;; add/remove ally highlights
;;; syntax: ally
;;;         unally
/alias ally \\
   /if ({#} > 0) \\
       /mapcar /sendl_ally %{*} %; \\
       /player_highlight_add 0 ally 218 Cblue %{*} %; \\
   /else \\
       /player_highlight_list ally%; \\
   /endif
/alias unally \\
   /if ({#} > 0) \\
       /if ({1} =~ "all") \\
           /mapcar /sendl_unally %{stack_ally} %; \\
           /player_highlight_remove 0 ally %{stack_ally} %; \\
       /else \\
           /mapcar /sendl_unally %{*} %; \\
           /player_highlight_remove 0 ally %{*} %; \\
       /endif %; \\
   /else \\
       /echol BCcyan 0 <<<< unallyh error: you must supply a list of players. >>>> %; \\
   /endif

;;; add/remove supplier highlight
;;; syntax: supplier
;;;         unsupplier
/alias supplier \\
   /if ({#} > 0) \\
       /player_highlight_add 0 supplier 217 Cyellow %{*} %; \\
   /else \\
       /player_highlight_list supplier%; \\
   /endif
/alias unsupplier \\
   /if ({#} > 0) \\
       /if ({1} =~ "all") \\
           /player_highlight_remove 0 supplier %{stack_supplier} %; \\
       /else \\
           /player_highlight_remove 0 supplier %{*} %; \\
       /endif %; \\
   /else \\
       /echol BCcyan 0 <<<< unsupplier error: you must supply a list of players. >>>> %; \\
   /endif

;;; add/remove citymate highlight
;;; syntax: citymate
;;;         uncitymate
/alias citymate \\
   /if ({#} > 0) \\
       /player_highlight_add 0 citymate 216 BCmagenta %{*} %; \\
   /else \\
       /player_highlight_list citymate%; \\
   /endif
/alias uncitymate \\
   /if ({#} > 0) \\
       /if ({1} =~ "all") \\
           /player_highlight_remove 0 citymate %{stack_citymate} %; \\
       /else \\
           /player_highlight_remove 0 citymate %{*} %; \\
       /endif %; \\
   /else \\
       /echol BCcyan 0 <<<< uncitymate error: you must supply a list of players. >>>> %; \\
   /endif

;;; add/remove guildmate highlight
;;; syntax: guildmate
;;;         unguildmate
/alias guildmate \\
   /if ({#} > 0) \\
       /player_highlight_add 0 guildmate 215 BCcyan %{*} %; \\
   /else \\
       /player_highlight_list guildmate%; \\
   /endif
/alias unguildmate \\
   /if ({#} > 0) \\
       /if ({1} =~ "all") \\
           /player_highlight_remove 0 guildmate %{stack_guildmate} %; \\
       /else \\
           /player_highlight_remove 0 guildmate %{*} %; \\
       /endif %; \\
   /else \\
       /echol BCcyan 0 <<<< unguildmate error: you must supply a list of players. >>>> %; \\
   /endif

;;; add/remove mark highlight
;;; syntax: mark
;;;         unmark
/alias mark \\
   /if ({#} > 0) \\
       /player_highlight_add 0 mark 214 Cgreen %{*} %; \\
   /else \\
       /player_highlight_list mark%; \\
   /endif
/alias unmark \\
   /if ({#} > 0) \\
       /if ({1} =~ "all") \\
           /player_highlight_remove 0 mark %{stack_mark} %; \\
       /else \\
           /player_highlight_remove 0 mark %{*} %; \\
       /endif %; \\
   /else \\
       /echol BCcyan 0 <<<< unmark error: you must supply a list of players. >>>> %; \\
   /endif



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;       automaticly define dynamic player highlighting stacks     ;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;; redefines all player highlights automatically every so many seconds (intended for use in CONNECT hooks)
;;; syntax: /redefine_all_automatically
;;; note: this should ONLY be called ONCE per session.  more than that will spawn multiple copies of the code, could cause problems.
;;;       if you need to kill the repeat, to stop it or restart it, use /PS and /KILL.
/def redefine_all_automatically = \\
   /if ({#} > 1) \\
       /if ({1} == 0) \\
           /define_citymates %; \\
       /elseif ({1} == 1) \\
           /define_guildmates %; \\
       /elseif ({1} == 2) \\
           /define_cityenemies %; \\
       /endif %; \\
       /if ({1} == 2) \\
           /repeat -%{2} 1 /redefine_all_automatically 0 %{2} %; \\
       /else \\
           /repeat -30 1 /redefine_all_automatically $ %{2} %; \\
       /endif %; \\
   /else \\
       /echol BCcyan <<<< redefine_all_automatically error: you must specify a step number and time in seconds. >>>> %; \\
   /endif

;;; define citymate highlights based on CW (silent, intended for use with /repeat)    
;;; syntax: /define_citymates
/def define_citymates = \\
   /def -mregexp -n1 -p150 -ag -t"^Your current pagelength: 250\\\\b" define_citymates_pagelength_250 = \\
       /def -mregexp -n1 -p152 -ag -t"^Total Citizens: \\\\\\\\d+" define_citymates_done = \\
           /undef define_citymates_catch_all %%%; \\
           /undef define_citymates_catch_members %%; \\
       /def -mregexp -n1 -p151 -ag -t"^Your current pagelength: 25\\\\\\\\b" define_citymates_pagelength_25 %%; \\
       /def -mregexp -n1 -p151 -ag -t"^Citizen" define_citymates_erroneous_line1 %%; \\
       /def -mregexp -n1 -p151 -ag -t"^Druthalus" define_citymates_erroneous_line2 %%; \\
       /def -mregexp -n0 -p150 -F -t"^(\\\\\\\\w+) " define_citymates_catch_members = \\
           /let current_citymate=$$$ %%%; \\
           /player_highlight_add 1 citymate 216 BCmagenta %%%{current_citymate} %%; \\
       /def -mregexp -n0 -p149 -ag -t".*" define_citymates_catch_all %%; \\
       /player_highlight_remove 1 citymate %%{stack_citymate} %; \\
   config pagelength 250 %; \\
   cw %; \\
   config pagelength 25
 
;;; define guildmate highlights based on GW (silent, intended for use with /repeat)
;;; syntax: /define_guildmates
/def define_guildmates = \\
   /def -mregexp -n1 -p150 -ag -t"^Your current pagelength: 250\\\\b" define_guildmates_pagelength_250 = \\
       /def -mregexp -n1 -p152 -ag -t"^Total Guildmembers: \\\\\\\\d+" define_guildmates_done = \\
           /undef define_guildmates_catch_all %%%; \\
           /undef define_guildmates_catch_members %%; \\
       /def -mregexp -n1 -p151 -ag -t"^Your current pagelength: 25\\\\\\\\b" define_guildmates_pagelength_25 %%; \\
       /def -mregexp -n1 -p151 -ag -t"^Guildmember" define_guildmates_erroneous_line1 %%; \\
       /def -mregexp -n1 -p151 -ag -t"^Druthalus" define_guildmates_erroneous_line2 %%; \\
       /def -mregexp -n0 -p150 -F -t"^(\\\\\\\\w+) " define_guildmates_catch_members = \\
           /let current_guildmate=$$$ %%%; \\
           /player_highlight_add 1 guildmate 215 BCcyan %%%{current_guildmate} %%; \\
       /def -mregexp -n0 -p149 -ag -t".*" define_guildmates_catch_all %%; \\
       /player_highlight_remove 1 guildmate %%{stack_guildmate} %; \\
   config pagelength 250 %; \\
   gw %; \\
   config pagelength 25

;;; define city enemies based on CITYENEMIES (silent, intended for use with /repeat)
;;; syntax: /define_cityenemies
/def define_cityenemies = \\
   /def -mregexp -n1 -p150 -ag -t"^Your current pagelength: 250\\\\b" define_cityenemies_pagelength_250 = \\
       /def -mregexp -n1 -p152 -ag -t"^Total: \\\\\\\\d+" define_cityenemies_done = /undef define_cityenemies_catch_all %%; \\
       /def -mregexp -n1 -p151 -ag -t"^Your current pagelength: 25\\\\\\\\b" define_cityenemies_pagelength_25 %%; \\
       /def -mregexp -n1 -p151 -ag -t"^Enemies of the Mighty Empire of Magnagora:" define_cityenemies_erroneous_line1 %%; \\
       /def -mregexp -n0 -p149 -ag -t".*" define_cityenemies_catch_all = \\
           /let current_cityenemy_row=$$$ %%%; \\
           /let current_cityenemy_row=$$$ %%%; \\
           /player_highlight_add 1 unofficial_enemy 220 Cred %%%{current_cityenemy_row} %%; \\
       /player_highlight_remove 1 unofficial_enemy %%{stack_unofficial_enemy} %; \\
   config pagelength 250 %; \\
   cityenemies %; \\
   config pagelength 25



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;                         player locating                         ;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

/set stack_locating=
/aclear array_located



;;; locate players based on WHO (with THIRDEYE)
;;; syntax: /locate_players
/def locate_players = \\
   /if ({#} > 0) \\
       /set stack_locating=%{*} %; \\
       /aclear array_located %; \\
       /def -mregexp -n1 -p150 -ag -t"^Your current pagelength: 250\\\\b" locate_players_pagelength_250 = \\
           /let local_stack_locating=%%{stack_locating} %%; \\
           /while ({local_stack_locating} !~ "") \\
               /let current_player=$$(/pop local_stack_locating) %%; \\
               /def -mregexp -n0 -p221 -F -P1xBCwhite -t".*\\\\\\\\b(%%{current_player})\\\\\\\\b.*" locate_players_highlight_%%{current_player} %%; \\
               /def -mregexp -n0 -p150 -ag -t".*\\\\\\\\b%%{current_player}\\\\\\\\b.*" locate_players_%%{current_player} = \\
                   /aput array_located $$$ $$$ %%; \\
           /done %%; \\
           /def -mregexp -n0 -p149 -ag -t".*" locate_players_catch_all %%; \\
           /def -mregexp -n1 -p151 -ag -t"^Your current pagelength: 25\\\\\\\\b" locate_players_pagelength_25 = \\
               /undef locate_players_catch_all %%%; \\
               /let local_stack_locating=%%{stack_locating} %%%; \\
               /while ({local_stack_locating} !~ "") \\
                   /let current_player=$$$(/pop local_stack_locating) %%%; \\
                   /undef locate_players_%%%{current_player} %%%; \\
                   /undef locate_players_highlight_%%%{current_player} %%%; \\
               /done %%%; \\
               /aforEach array_located /echol none 1 %%%; \\
               /set stack_locating= %%%; \\
               /aclear array_located %; \\
       config pagelength 250 %; \\
       who %; \\
       config pagelength 25 %; \\
   /else \\
       who %; \\
   /endif

;;; locate all players at a location,  based on WHO (with THIRDEYE)
;;; syntax: /locate_location
/def locate_location = \\
   /if ({#} > 0) \\
       /aclear array_located %; \\
       /def -mregexp -n1 -p150 -ag -t"^Your current pagelength: 250\\\\b" locate_location_pagelength_250 = \\
           /def -mregexp -n0 -p221 -F -P1xBCwhite -t".*\\\\\\\\(.*(%{*}).*\\\\\\\\).*" locate_location_highlight %%; \\
           /def -mregexp -n0 -p150 -ag -t".*\\\\\\\\(.*%{*}.*\\\\\\\\).*" locate_location_player_catch = \\
               /aput array_located $$$ $$$ %%; \\
           /def -mregexp -n0 -p149 -ag -t".*" locate_location_catch_all %%; \\
           /def -mregexp -n1 -p151 -ag -t"^Your current pagelength: 25\\\\\\\\b" locate_location_pagelength_25 = \\
               /undef locate_location_catch_all %%%; \\
               /undef locate_location_player_catch %%%; \\
               /undef locate_location_highlight %%%; \\
               /aforEach array_located /echol none 1 %%%; \\
               /aclear array_located %; \\
       config pagelength 250 %; \\
       who %; \\
       config pagelength 25 %; \\
   /else \\
       /echol BCcyan 0 <<<< locate_location error: you must supply the name of a location. >>>> %; \\
   /endif

;;; locate a player and their party, based on WHO (with THIRDEYE)
;;; syntax: /locate_party
/def locate_party = \\
   /if ({#} > 0) \\
       /aclear array_located %; \\
       /def -mregexp -n1 -p150 -ag -t"^Your current pagelength: 250\\\\b" locate_party_pagelength_250 = \\
           /def -mregexp -n0 -p221 -F -P1xBCwhite;2BCwhite -t".*\\\\\\\\b(%{1})\\\\\\\\b.*(\\\\\\\\(.*\\\\\\\\)).*" locate_party_highlight_player %%; \\
           /def -mregexp -n1 -p151 -ag -t"^Your current pagelength: 25\\\\\\\\b" locate_party_pagelength_25_undefine = \\
               /undef locate_party_catch_all %%%; \\
               /undef locate_party_highlight_player %%%; \\
               /undef locate_party_player %%; \\
           /def -mregexp -n0 -p150 -ag -t".*\\\\\\\\b%{1}\\\\\\\\b.*(\\\\\\\\(.*\\\\\\\\)).*" locate_party_player = \\
               /echol none 1 $$$ %%%; \\
               /def -mregexp -n1 -p152 -F -t"^Your current pagelength: 25\\\\\\\\\\\\\\\\b" locate_party_pagelength_25_listplayers = \\
                   /let array_located_current=$$$$ %%%%;\\
                   /let array_located_length=$$$$ %%%%;\\
                   /while (++{array_located_current} <= {array_located_length}) \\
                       /let current_element=$$$$ %%%%; \\
                       /if (regmatch("%%%{P1}",{current_element}) > 0) \\
                           /echol none 1 %%%%{current_element} %%%%; \\
                       /endif %%%%; \\
                   /done %%%%; \\
                   /aclear array_located %%; \\
           /def -mregexp -n0 -p149 -ag -t".*" locate_party_catch_all = \\
               /aput array_located $$$ $$$ %; \\
       config pagelength 250 %; \\
       who %; \\
       config pagelength 25 %; \\
   /else \\
       /echol BCcyan 0 <<<< locate_party error: you must supply the name of a player. >>>> %; \\
   /endif

;;; locate list of players
;;; syntax: loc
/alias loc /locate_players %{*}

;;; locate all players at a location
;;; syntax: locl
/alias locl /locate_location %{*}

;;; locate a player and their party
;;; syntax: locp
/alias locp /locate_party %{*}

;;; locate target
;;; syntax: loct
/alias loct \\
   /if ({target} !~ "") \\
       /locate_players %{target} %; \\
   /else \\
       /echol BCcyan 0 <<<< you have no target. >>>> %; \\
   /endif

;;; locate target and their party
;;; syntax: loctp
/alias loctp \\
   /if ({target} !~ "") \\
       /locate_party %{target} %; \\
   /else \\
       /echol BCcyan 0 <<<< you have no target. >>>> %; \\
   /endif

;;; locate enemies
;;; syntax: loce
/alias loce \\
   /if (strcat({stack_official_enemy},{stack_unofficial_enemy}) !~ "") \\
       /let stack_temp_official_enemy=%{stack_official_enemy} %; \\
       /let stack_temp_unofficial_enemy=%{stack_unofficial_enemy} %; \\
       /while ({stack_temp_official_enemy} !~ "") \\
           /let current_official_enemy=$(/pop stack_temp_official_enemy) %; \\
           /let stack_temp_unofficial_enemy=$ %; \\
       /done %; \\
       /locate_players %{stack_temp_unofficial_enemy} %{stack_official_enemy} %; \\
   /else \\
       /echol BCcyan 0 <<<< you have no enemies. >>>> %; \\
   /endif

;;; locate allies
;;; syntax: loca
/alias loca \\
   /if ({stack_ally} !~ "") \\
       /locate_players %{stack_ally} %; \\
   /else \\
       /echol BCcyan 0 <<<< you have no allies. >>>> %; \\
   /endif

;;; locate suppliers
;;; syntax: locs
/alias locs \\
   /if ({stack_supplier} !~ "") \\
       /locate_players %{stack_supplier} %; \\
   /else \\
       /echol BCcyan 0 <<<< you have no suppliers. >>>> %; \\
   /endif

;;; locate citymates
;;; syntax: locc
/alias locc \\
   /if ({stack_citymate} !~ "") \\
       /locate_players %{stack_citymate} %; \\
   /else \\
       /echol BCcyan 0 <<<< you have no citymates. >>>> %; \\
   /endif

;;; locate guildmates
;;; syntax: locg
/alias locg \\
   /if ({stack_guildmate} !~ "") \\
       /locate_players %{stack_guildmate} %; \\
   /else \\
       /echol BCcyan 0 <<<< you have no guildmates. >>>> %; \\
   /endif

;;; locate marks
;;; syntax: locm
/alias locm \\
   /if ({stack_mark} !~ "") \\
       /locate_players %{stack_mark} %; \\
   /else \\
       /echol BCcyan 0 <<<< you have no marks. >>>> %; \\
   /endif
Narsrim2005-05-07 05:07:09
People like you scare me...
Unknown2005-05-07 05:11:57
Thank you for the compliment cool.gif

I certainly can't scare you in the realms yet, at least I can do it IRL biggrin.gif tongue.gif
Alger2005-05-08 04:41:34
druth i think you overlapped your enemy and ally command with the builtin commands. I dont think thats such a good idea have to change that alias name or work around the limitations of the enemy and ally lists
Unknown2005-05-08 05:25:39
QUOTE(Alger @ May 7 2005, 11:41 PM)
druth i think you overlapped your enemy and ally command with the builtin commands.  I dont think thats such a good idea have to change that alias name ...
114972



Well, yes, I have aliases named "enemy, unenemy, ally, and unally". Yes, these overlap with the Lusternian built-in commands of the same name. However, that's the point. I wanted to expand on what the Lusternian built-in commands did. As I enemy people, I also want them highlighted a certain way. My version of the Lusternian built-in commands do the highlighting, then call the Lusternian built-in commands to adjust the player's enemy/ally status in game.

I use my "enemy" alias as an example (the others are almost identical):
CODE
;;; add/remove official enemy highlights
;;; syntax: enemy
;;;         unenemy
/alias enemy \\
  /if ({#} > 0) \\
      /mapcar /sendl_enemy %{*} %; \\
      /player_highlight_add 0 official_enemy 219 BCred %{*} %; \\
  /else \\
      /player_highlight_list official_enemy%; \\
  /endif


The user of this alias can type "enemy player1 player2 player3..." or "enemy". Just typing "enemy" by itself will print the list of players you have enemied to your screen. Giving the enemy command a list of players will enemy all of those players, then add highlights for them so that their names are colored in TF.

The key line here that addresses your concern is "/mapcar /sendl_enemy %{*} %; \\". What "/mapcar" does is apply the command on the right (/sendl_enemy) to every name you passed to the enemy alias. So if you typed "enemy player1 player2 player3", that /mapcar command will execute

/sendl_enemy player1
/sendl_enemy player2
/sendl_enemy player3

The sendl_enemy code is also included in the tracking script:
CODE
/def sendl_enemy = /sendl enemy %{1}


It seems rather pointless at first, why have one 1-line command simply call another 1-line command? The answer is that /mapcar only allows you to use a single-word command. The command I wanted to run on each name sent to the "enemy" alias had more than one word. The code for "/sendl" is not included in the tracking script posted here, it's in my logging script (which is why I posted all of those files in another post right after this one).

Here is the "/sendl" code:
CODE
;;; /send replacement to allow sent commands to be logged but not trigger the my_alias.tf SEND hook
;;; syntax: /sendl
/def sendl = \\
   /send %{*} %; \\
   /test tfwrite({worldlog},strcat("SENT: ",{*})) %; \\
   /test tfwrite({combatlog},strcat("SENT: ",{*}))


The way my logging script logs sent commands is through SEND hooks. Normally if you typed enemy/ally it would get sent to the mud, and logged. However, because I wanted my aliases to replace those commands, I had to use a /send command to send "enemy" and "ally" to lusternia. /send commands DO NOT trigger SEND hooks, and thus the commands wouldn't be logged in my colored log. /sendl is my work-around for that. It sends the enemy/ally command to Lusternia, and then writes the entry to my logs itself (since the all-encompassing SEND hook won't catch it).

In the end, my "enemy" and "ally" aliases don't really overlap with the Lusternian built-ins, it's more like they wrap around the built-ins...adding functionality to them. When you type enemy/ally in with my script, you're still executing the same commands you always did, but the highlighting now comes along with it.

I'll end up doing this same thing to other commands, such as DEF. I add more functionality to the commands that exist. This way of doing things makes it easier for myself and others to use my system, because the built-in commands they've always used are still there...just better. cool.gif
Unknown2005-05-08 05:33:59
QUOTE(Alger @ May 7 2005, 11:41 PM)
...or work around the limitations of the enemy and ally lists
114972



What are the limitations of my alias/stack replacements for the built-in commands? I don't really use them all that much, so I'm certainly not an expert on the built-ins. The built-ins let you enemy one person at a time, unenemy one person at a time, or unenemy everyone at once. Mine does the same, but also lets you enemy a list of people at once.

After messing with it a bit I do notice one slight performance hit in the unenemy alias. If you do "unenemy all" it unenemies each player one at a time. It would make more sense to just send "unenemy all" to lusternia and do them all at once. I think I'll probably leave it as-is; I like to see who I'm unenemying and not just a generic "You feel forgiving and unenemy everyone" message. Are there any other problems with the aliases I missed?