Just Happy To See You

Getting Control of Your Text Balloon

Now with BotBot Support!
(see the "Costume Group")

An ongoing problem for people with large avatars is that the text balloons always come from the center prop area. Hence large-sized portraits have come to be known as "nose talkers" and all sorts of interesting and sometimes embarrassing body parts have been seen to be the source of speech and thought. Believe me, those jokes have already been made.

Before After
Before After

You could use "msay" to bypass regular speech and force it to come out of your head, mouth, loudspeaker, whatever. This is more than a bit tedious, since you have to remember to always prepend "msay" onto everything you type.
Cyborg to the rescue!
First, in the ON SIGNON block, we declare the following global variables, and a couple of functions.

    autoPos	GLOBAL
    autoX	GLOBAL
    autoY	GLOBAL
    0		autoPos	=
    0		autoX	=
    0		autoY	=

; <string> auto_pos EXEC -- prepend positioning information to a string
    auto_pos	GLOBAL
    {
	autoPos 	GLOBAL
	autoX		GLOBAL
	autoY		GLOBAL
	debugOn		GLOBAL
	"\x20" fc =
	{
	    DUP tmp =
	    {
		"$1" GREPSUB fc =
	    } tmp "^(.)" GREPSTR IF
	    {
		"@"
		POSX autoX + ITOA &
		"," &
		POSY autoY + ITOA &
		" " &
		SWAP &
	    } fc "\x60" == NOT
	      fc "\x40" == NOT AND
	      fc "\x3b" == NOT AND
	      fc "\x7e" == NOT AND
	      WHOTARGET WHOME == NOT AND IF
	} autoPos IF
    } auto_pos DEF
; Hex Codes Used: 3b=; 60=` 40=@ 7e=~ 22=" 20=SPACE

; set autoPos values....    <x> <y> aps EXEC
    aps GLOBAL
    {
	autoPos GLOBAL
	autoX	GLOBAL
	autoY	GLOBAL
	autoY		=
	autoX		=
	1 autoPos	=
    } aps DEF

; set props by rootname and count -   n_prop
	n_prop GLOBAL
	{
		ct	=
		nm	=
		1 i =
		[
			{
				nm i ITOA &
				i ++
			} { i ct <= } WHILE
		] SETPROPS
	} n_prop DEF

The meat of the whole deal is in the auto_pos function. What auto_pos does is take a string in (usually CHATSTR) and spit a string out. The new string will have an "@" screen position prepended to it, based on the current position; that is, unless:

(To easily pass values to auto_pos, use the BotBot "ap" command, e.g. "ap 0 -50")

To use auto_pos we put the following snippet at the end out our ON OUTCHAT block...

;	be sure to declare auto_pos GLOBAL
    {
	CHATSTR auto_pos EXEC CHATSTR =
    } CHATSTR "" == NOT IF

So it catches any line that we've typed (that wasn't erased along the way because it was a command). If autoPos is turned on, the text is repositioned automatically! No one ever again need accuse you of thinking with your ritz cracker instead of your head.

Pile on the Props

The aps function lets us easily turn on the autoPos flag and load x and y offsets into the appropriate variables.
The n_prop function is a shortcut for building large avatars made from props named "1, 2, 3..." as in
[ "name1" "name2" "name3" "name4" "name5" "name6" ] SETPROPS
which is equivalent to
"name" 6 n_prop EXEC
(Or using the BotBot "np" command, e.g. "np name 6")
But where do the values for auto_pos come from? Do you have to figure them out for every single avatar you want to use it with?
Well, yeah. But you only need do it once, and only on av's that genuinely use it. Instead of macros, I usually use a somewhat-larger version of the following OUTCHAT script to switch avatar pictures (except in Cyborg-Free rooms):

;
; COSTUME CHANGES
;
; uses GLOBALs autoPos autoX autoY burning aps n_prop
;	-- be sure to declare them!
;
    {
	"$1" GREPSUB	cost	=
	0	autoPos	=
	0	autoX	=
	0	autoY	=
	0	burning	=
	{ [ "Xhairman" ] SETPROPS 4 SETCOLOR } cost "frank" == IF
	{ [ "SammyBaby" ] SETPROPS 4 SETCOLOR } cost "sammy" == IF
	{ [ "dinoBaby" ] SETPROPS 4 SETCOLOR } cost "dino" == IF
	{ "w3xb" 6 n_prop EXEC 4 SETCOLOR 5 -48 aps EXEC } cost "bike" == IF
	{ "murph" 6 n_prop EXEC 0 -44 aps EXEC } cost "murph" == IF
	{ "qn3." 7 n_prop EXEC 2 SETCOLOR -20 -2 aps EXEC } cost "qn3" == IF
	{ "Available costumes:" STATUSMSG
	    "frank/sammy/dino"	STATUSMSG
	    "bike/murph/qn3"	STATUSMSG
	} cost "?" == IF
	""	CHATSTR =
    } CHATSTR "\x3bcost (.*)" GREPSTR IF

So I can type ";cost sammy" to change my avatar to Sammy Davis, Jr., without autopositioning, or ";cost bike" to change to a guy on a bike with autopositioning, or ";cost ?" to get a list of the currently-available "costumes." A hidden side effect of this (some might call it a bug, but of course they would be wrong) is that just typing ";cost " will turn autopositioning off.