@@ -1,5 +1,5 @@
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				// Take a look at the .d.ts for comments. 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				export  const  version  =  '108 .13.1 ' 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				export  const  version  =  '107 .13.0 ' 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				const  W  =  window ,  D  =  W . document ,  /**fuck money*/ $  =  undefined ,  /**@type {''}*/ $S  =  '' ,  /**@type {{}}*/ $O  =  { } ,  /**@type {Set<string>}*/ $Ss  =  new  Set ( )  // /**@type {readonly []}*/$A = [], 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				const /**@type {TextDictionaryEntry}*/ MISSING _PLAYER _DIALOG  =  { Tag :  'MISSING TEXT IN "Interface.csv": ' ,  Text :  '\u200C' }  // Zero-width non-joiner, used to break up ligatures, does nothing here, but an empty string is a falsey value 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
	
		
			
				
					
					
						
					 
				
			
			 
			 
			
				@@ -158,9 +158,7 @@ const/**@type {Utils}*/U = { remove_loader_hook: $, RGB: {Polly: '#81b1e7', Mute
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						return  $Ss 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					} ) } , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					replace _me :  ( _ ,  _ _ ,  whole )  =>  cur ( whole . slice ( 1 ) ,  t  =>  ` ${ U . ACT } < ${ U . cid ( W . Player ) } :>SourceCharacter ${ t . startsWith ( '\'' )  ||  t . startsWith ( ' ' )  ?  $S  :  ' ' } ` ) , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					scroll :  ( )  =>  yes ( void  W .  ElementScrollToEnd(  'TextAreaChatLog') ) , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					get  scrolled ( )  { return  W . ElementIsScrolledToEnd ( 'TextAreaChatLog' ) } , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					rescroll :  f  =>  cur ( U . scrolled ,  s  =>  yes ( f ,  s  &&  U . scroll ( ) ) ) , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					//pad_chat: c => loo(100, _ => c.scrollHeight <= c.clientHeight, _ => yes(void c.prepend(U.mkdiv('\u061C')))) && void W. ElementScrollToEnd( 'TextAreaChatLog') 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				} 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				const /**@type {SUBCOMMANDS}*/ SUBCOMMANDS _MBCHC  =  { 
 
			
		 
		
	
	
		
			
				
					
					
						
					 
				
			
			 
			 
			
				@@ -180,7 +178,7 @@ const/**@type {Complete}*/C = { S_OPTS: {behavior: 'instant'},
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					hint :  cs  =>  m _t ( cs )  ||  yes ( _  =>  { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						yes ( C . e . style . display  =  'block' )  &&  C . div ? . replaceChildren ( ... [ ... cs ] . sort ( ) . reverse ( ) . map ( U . mkdiv ) ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						W . ElementSetDataAttribute ( C . e . id ,  'colortheme' ,  W . Player . ChatSettings ? . ColorTheme  ? ?  'Light' ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						U . rescroll ( _  =>  void  W . ChatRoomResize ( false ) ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						cur ( W . ElementIsScrolledToEnd ( 'TextAreaChatLog' ) ,  r  =>  yes ( void  W . ChatRoomResize ( false ) )  &&  r  &&  void  W . ElementScrollToEnd ( 'TextAreaChatLog' ) ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						C . div ? . lastElementChild ? . scrollIntoView ( C . S _OPTS ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					} ) , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					get  hidden ( )  { return  C . e . parentElement  ===  null  ||  C . e . style . display  ===  'none' } , 
 
			
		 
		
	
	
		
			
				
					
					
						
					 
				
			
			 
			 
			
				@@ -205,13 +203,8 @@ const/**@type {Complete}*/C = { S_OPTS: {behavior: 'instant'},
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				} 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				const /**@type {InputHistory}*/ H  =  {  input :  undefined ,  ids :  undefined ,  bottom :  undefined ,  // FIXME ids don't need to be a set, but I'm too tired right now 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	key :  { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					 	Escape :  ( _ ,  ic )  =>  yes ( val ( H . input ,  i  =>  ic . value  =  i ) ) , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						ArrowLeft :  ( _ ,  ic )  =>  yes ( void  ic . setSelectionRange ( 0 ,  0 ) ) , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					} , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					icro :  ( ic ,  ro )  =>  yes ( ic . readOnly  =  ro ,  val ( ic . parentElement ? . parentElement ? . dataset ,  d  =>  ro  ?  d [ 'mbchcMode' ]  =  'h'  :  del ( d ,  'mbchcMode' ) ) ) , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					enter :  ( ic ,  i ,  b ,  is )  =>  yes ( H . input  =  i ,  H . bottom  =  b ,  H . ids  =  is ,  H . icro ( ic ,  true ) ,  b  &&  U . scroll ( ) ) , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					exit :  ( ic ,  e )  =>  yes ( H . icro ( ic ,  false ) ,  H . key [ e . key ] ? . ( e ,  ic ) ,  val ( H . bottom ,  b  =>  b  &&  U . scroll ( ) ) ,  W . ChatRoomLastMessageIndex  =  W . ChatRoomLastMessage . length ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	enter :  ( ic ,  i ,  b ,  is )  =>  yes ( H . input  =  i ,  H . bottom  =  b ,  H . ids  =  is ,  ic . readOnly  =  true ,  val ( ic . parentElement ? . parentElement ? . dataset ,  d  =>  d [ 'mbchcMode' ]  =  'h' ) ,  b  &&  void  W . ElementScrollToEnd ( 'TextAreaChatLog' ) ) , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					exit :  ( ic ,  r )  =>  yes ( ic . readOnly  =  false ,  val ( ic . parentElement ? . parentElement ? . dataset ,  d  =>  del ( d ,  'mbchcMode' ) ) ,  r  &&  val ( H . input ,  i  =>  ic . value  =  i ) ,  val ( H . bottom ,  b  =>  b  &&  void  W . ElementScrollToEnd ( 'TextAreaChatLog' ) ) ,  W . ChatRoomLastMessageIndex  =  W . ChatRoomLastMessage . length ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				} 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				ass ( 'MBCHC found, aborting loading' ,  W . MBCHC  ===  $ ) 
 
			
		 
		
	
	
		
			
				
					
					
						
					 
				
			
			 
			 
			
				@@ -229,17 +222,21 @@ const/**@type {SDK.Hook}*/after = (name, f) => mod.hookFunction(name, 0, (na, n)
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					version ,  /** Just in case someone used it for anything @deprecated*/ VERSION :  version , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					Settings ,  TZ , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					SUBCOMMANDS _MBCHC ,  H ,  U ,  // debug, will go away 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					NEXT _MESSAGE :  1 , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					LOG _MESSAGES :  false , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					LOADED :  false , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					AUTOHACK _ENABLED :  false , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					/**@type {number | undefined}*/ LAST _HACKED :  $ , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					//HISTORY_MODE: false, 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	RE _PREF _ACTIVITY _ME :  /^@/ , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					RE _PREF _ACTIVITY :  /^@@/ , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					RE _ACT _CIDS :  /^<(\d+)?:(\d+)?>/ , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					RE _LAST _WORD :  /(^|\s)(\S*)$/ , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					RE _LAST _LETTER :  /\w$/ , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					RE _ACTIVITY :  new  RegExp ( ` ^ ${ CommandsKey } activity  ` ) , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					//PREF_ACTIVITY: `${CommandsKey}activity `, 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	UTC _OFFSET :  new  Date ( ) . getTimezoneOffset ( )  *  60  *  1000 , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					MAP _ACTIONS :  {  // ActivityFemale3DCG 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 		// Action 
 
			
		 
		
	
	
		
			
				
					
					
						
					 
				
			
			 
			 
			
				@@ -448,6 +445,127 @@ const/**@type {SDK.Hook}*/after = (name, f) => mod.hookFunction(name, 0, (na, n)
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							mbchc . run _activity ( char ,  /**@type {AssetGroupItemName}*/ ( ag ) ,  /**@type {ActivityName}*/ ( action ) ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						}  catch  ( x )  {  U . report ( x )  } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					} , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					//complete(options, space = true) { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	if (m_t(options)) return void U.bell() 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	if (options.length > 1) { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//		const width = Math.max(...options.map(o => o.length)) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//		let pref = null 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//		for (let i = width; i > 0; i -= 1) { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//			const test = options[0].slice(0, i) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//			if (options.every(o => o.startsWith(test))) { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//				pref = test 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//				break 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//			} 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//		} 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					//		if (pref) this.complete([pref], false) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//		this.comp_hint(options) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	} else W.ElementValue('InputChat', W.ElementValue('InputChat').replace(this.RE_LAST_WORD, `$1${options[0]}${space ? ' ' : $S}`)) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//}, 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					///** 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	// * Displays strings as completion hint 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	// * @param {string[]} options List of words to display. The order will be modified without copy. 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	// * @returns {undefined} 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	// */ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//comp_hint(options) { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	if (m_t(options)) return 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	this.COMP_HINT.innerHTML = '<div>' + options.sort().reverse().map(s => `<div>${s}</div>`).join($S) + '</div>' 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	this.COMP_HINT.style.display = 'block' 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	W.ElementSetDataAttribute(this.COMP_HINT.id, 'colortheme', (W.Player.ChatSettings?.ColorTheme || 'Light')) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	const rescroll = W.ElementIsScrolledToEnd('TextAreaChatLog') 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	W.ChatRoomResize(false) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	if (rescroll) W.ElementScrollToEnd('TextAreaChatLog') 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	this.COMP_HINT.firstChild?.lastChild?.scrollIntoView({behaviour: 'instant'}) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//}, 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					///** 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	// * Returns true if the completion box is attached to body and its display isn't none 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	// * @returns {boolean} 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	// */ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//comp_hint_visible() { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	return this.COMP_HINT.parentElement && this.COMP_HINT.style.display !== 'none' 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//}, 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//comp_hint_hide() { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	if (!this.comp_hint_visible()) return 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	this.COMP_HINT.style.display = 'none' 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	W.ChatRoomResize(false) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//}, 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//char2targets(/**@type {Character}*/char) { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	const/**@type {Set<string>}*/result = new Set() 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	val(U.cid(char)?.toString(), id => result.add(id).add(`=${id}`)) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	for (const t of U.split(char.Name)) { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//		result.add(t) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//		result.add(`@${t}`) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	} 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					//	if (char.Nickname !== $) for (const t of U.split(char.Nickname)) { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//		result.add(t) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//		result.add(`@${t}`) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	} 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					//	return result 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//}, 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//complete_target(/**@type {string}*/token, me2 = true, check_perms = false) { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	const [locase, found] = [token.toLocaleLowerCase(), new Set()] 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	for (const c of U.crc) { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//		if ((c.IsPlayer() && !me2) || (check_perms && !W.ServerChatRoomGetAllowItem(W.Player, c))) continue 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//		for (const s of this.char2targets(c)) { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//			if (s.toLocaleLowerCase().startsWith(locase)) found.add(s) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//		} 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	} 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					//	//this.complete(Array.from(found)) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//}, 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//complete_common() { // w.ElementValue('InputChat') will strip the trailing whitespace 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	const E = D.querySelector('#InputChat') 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	ass('somehow #InputChat is broken', E instanceof HTMLTextAreaElement) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	return [this, E.value, U.split(E.value)] 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//}, 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//complete_mbchc(_args, _locase, _cmdline) { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	const [mbchc, _input, tokens] = W.MBCHC.complete_common(); // `this` is command object 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	if (m_t(tokens)) return 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	if (tokens.length < 2) return //mbchc.complete([`${CommandsKey}${this.Tag}`]) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	const subname = tokens[1].toLocaleLowerCase() 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	if (tokens.length < 3) return //mbchc.complete(Object.keys(SUBCOMMANDS_MBCHC).filter(c => c.startsWith(subname))) // Complete subcommand name 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	const sub = SUBCOMMANDS_MBCHC[subname] 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	if (sub && sub.args) { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//		const argname = Object.keys(sub.args)[tokens.length - 3] 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//		if (argname === 'TARGET') return mbchc.complete_target(tokens.at(-1), false) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//		if (argname === '[TARGET]') return mbchc.complete_target(tokens.at(-1)) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	} 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//}, 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//complete_fbc_anim(_args, _locase, _cmdline) { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	const [mbchc, _input, tokens] = W.MBCHC.complete_common(); // `this` is command object 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	if (m_t(tokens)) return 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	if (tokens.length < 2) return mbchc.complete([`${CommandsKey}${this.Tag}`]) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	if (tokens.length > 2) return void U.bell() 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	const anim = tokens[1].toLocaleLowerCase() 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	return mbchc.complete(Object.keys(W.bce_EventExpressions).filter(a => a.toLocaleLowerCase().startsWith(anim))) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//}, 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//complete_fbc_pose(_args, _locase, _cmdline) { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	const [mbchc, _input, tokens] = W.MBCHC.complete_common(); // `this` is command object 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	if (m_t(tokens)) return 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	if (tokens.length < 2) return mbchc.complete([`${CommandsKey}${this.Tag}`]) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	const pose = tokens.at(-1).toLocaleLowerCase() 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	return mbchc.complete(W.PoseFemale3DCG.map(p => p.Name).filter(p => p.toLocaleLowerCase().startsWith(pose))) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//}, 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//focus_chat_checks() { // we only want to catch chat log and canvas (no map though) keypresses 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	if (D.activeElement === D.body) return true 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	if (D.activeElement?.id !== 'MainCanvas') return false 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	return !W.ChatRoomMapViewIsActive() 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//}, 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//focus_chat_whitelist(/**@type {KeyboardEvent}*/event) { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	if (event.ctrlKey && event.key === 'v') return true // Ctrl+V should paste 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	return false 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//}, 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//focus_chat(/**@type {KeyboardEvent}*/event) { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	if (event.repeat) return // Only unique presses please 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	if (!this.focus_chat_checks()) return 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	if ([event.altKey, event.ctrlKey, event.metaKey].some(Boolean) && !this.focus_chat_whitelist(event)) return // Alt, ctrl and meta should all be false 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	if (U.style('#InputChat', s => s.display) !== 'inline') return // Input chat missing 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//	W.ElementFocus('InputChat') 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	//}, 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 	loader ( )  { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						U . remove _loader _hook  ===  $  ||  yes ( void  U . remove _loader _hook ( ) ,  U . remove _loader _hook  =  $ ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						if  ( this . LOADED )  return 
 
			
		 
		
	
	
		
			
				
					
					
						
					 
				
			
			 
			 
			
				@@ -459,22 +577,18 @@ const/**@type {SDK.Hook}*/after = (name, f) => mod.hookFunction(name, 0, (na, n)
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							{ Tag :  'activity' ,  Description :  '[Message]: Send a custom activity (or "@@Message", or "@Message" as yourself)' ,  Action :  this . command _activity } , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							{ Tag :  'do' ,  Description :  ': Do an activity, as if clicked on its button ("/do" for help)' ,  Action :  this . command _do ,  AutoComplete :  U . complete _do } , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						] 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						const /**@type (e: Event) => void*/ css _hook  =  e  =>  void  cur ( /**@type {HTMLStyl eElement}*/ ( e . target ) ,  css   =>  U . scroll ( )  &&  void   css  . removeEventListener ( 'load' ,  css _hook ) ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						mut ( D . createElement ( 'style' ) ,  c  =>  void  D . head . append ( c ) ,  c  =>  void  c . addEventListener ( 'load' ,  css _hook ) ,  c  =>  c . textContent  =  ` 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						mut ( D . creat eElement( 'style' ) ,  c  =>  void  D . head . append ( c ) ,  c  =>   c . textContent  =  ` 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							#TextAreaChatLog .mbchc { background-color:  ${ U . RGB . Polly } ; margin-left: -0.4em; padding-left: 0.4em; } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							#TextAreaChatLog[data-colortheme^="dark"] .mbchc { background-color:  ${ U . RGB . Mute } ; } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							# ${ C . e . id }  { display: none; text-align: right; } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							# ${ C . e . id }  > div { overflow: auto; position: absolute; bottom: 0; right: 0; max-height: 100%; padding: 0 0.5ex; background-color:  ${ U . RGB . Polly } ; color: black; } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							# ${ C . e . id } [data-colortheme^="dark"] > div { background-color:  ${ U . RGB . Mute } ; color: white; } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							# ${ C . e . id }  > div div { margin: 0.25ex 0; } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							#chat-room-div #TextAreaChatLog::before { content: ''; display: block; height: 100%; background: repeating-linear-gradient(135deg, transparent 0 20px, #333 2px 22px);  } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							#chat-room-div[data-mbchc-mode="h"] #TextAreaChatLog::after { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
								content: '⟨𝘗𝘨𝘜𝘱/𝘋 𝘯  /↕⟩ 𝗌 𝖼 𝗋 𝗈 𝗅 𝗅   ⇅ ⟨𝘌𝘯𝘵𝘦𝘳⟩ 𝗌 𝖾 𝗇 𝖽   ↵ ⟨𝘛𝘢𝘣/↔/⌫⟩ 𝖾 𝖽 𝗂 𝗍   ⌨ ⟨𝘌𝘴𝘤⟩ 𝖺 𝖻 𝗈 𝗋 𝗍   ⟲ \\ A' attr(data-mbchc-h-h); whitespace: pre; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
								display: block; position: sticky; z-index: 1; bottom: 0; background: black; color: orange; padding: 0 0.2ex; animation: 0.2s cubic-bezier(0.19, 1, 0.22, 1) mbchc_hh_show; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							} 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							#chat-room-div #TextAreaChatLog::before { content: ''; display: block; height: 100%; } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							#chat-room-div[data-mbchc-mode="h"] #TextAreaChatLog::after { content: '𝗵 𝗶 𝘀 𝘁 𝗼 𝗿 𝘆   ⟨𝘗𝘨𝘜𝘱/𝘋𝘯⟩ 𝗌 𝖼 𝗋 𝗈 𝗅 𝗅   ⇅ ⟨𝘌𝘯𝘵𝘦𝘳⟩ 𝗌 𝖾 𝗇 𝖽   ↵ ⟨𝘛𝘢𝘣⟩ 𝖾 𝖽 𝗂 𝗍   ⌨ ⟨𝘌𝘴𝘤⟩ 𝖺 𝖻 𝗈 𝗋 𝗍   ⟲'; display: block; position: sticky; bottom: 0; background: black; color: orange; padding: 0 0.2ex; animation: 0.2s cubic-bezier(0.19, 1, 0.22, 1) mbchc_hist_hint_show; }  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							#InputChat:read-only { background: black; color: orange; } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							@keyframes mbchc_hh _show { from {transform: translateX(-100%);} to {transform: translateX(0);} } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						 ` )  // will always scroll the chat on CSS load, I can't be fucked to make it conditional  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							@keyframes mbchc_hist_hint _show { from {transform: translateX(-100%);} to {transform: translateX(0);} } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						 ` ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						// Actions 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 		this . calculate _maps ( ) 
 
			
		 
		
	
	
		
			
				
					
					
						
					 
				
			
			 
			 
			
				@@ -489,6 +603,14 @@ const/**@type {SDK.Hook}*/after = (name, f) => mod.hookFunction(name, 0, (na, n)
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							} 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						} ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						prior ( 'ChatRoomSendChat' ,  ( )  =>  val ( U . ic ,  ic  =>  ! ic . value . startsWith ( '@@@' )  &&  ic . value . startsWith ( '@' )  &&  ( ic . value  =  ic . value . replace ( U . RE [ '@' ] [ 1 ] ,  U . ACT ) . replace ( U . RE [ '@' ] [ 0 ] ,  U . replace _me ) ) ) ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						//{ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 		//	let input = W.ElementValue('InputChat') 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 		//	if (!input.startsWith('@@@') && input.startsWith('@')) { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 		//		input = input.replace(this.RE_PREF_ACTIVITY, this.PREF_ACTIVITY) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 		//		input = input.replace(this.RE_PREF_ACTIVITY_ME, this.replace_me) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 		//		W.ElementValue('InputChat', input) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 		//	} 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 		//}) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 		after ( 'ChatRoomSendChat' ,  ( )  =>  {  // FIXME actually make history a ring buffer of a given size. clear the array and push every string into it, compacting sequential equal strings into one. 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 			const  history  =  W . ChatRoomLastMessage 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							if  ( ( history . length  >  1 )  &&  ( history . at ( - 1 )  ===  history . at ( - 2 ) ) )  { 
 
			
		 
		
	
	
		
			
				
					
					
						
					 
				
			
			 
			 
			
				@@ -507,34 +629,45 @@ const/**@type {SDK.Hook}*/after = (name, f) => mod.hookFunction(name, 0, (na, n)
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						const /**@type {(this: HTMLTextAreaElement, e: KeyboardEvent) => void}*/ ickd  =  function ( e )  { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							C . hide ( ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							const  ic  =  this  // eslint-disable-line unicorn/no-this-assignment,@typescript-eslint/no-this-alias 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 			if  ( ic . readOnly  &&  ! e . repeat  )  switch  ( e . key )  {  // FIXME maybe deal with modifiers  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 				case  'ArrowUp ' :  case  'ArrowDown' :  W . ChatRoomScrollHistory ( e . key  ===  'ArrowUp' ) ;  break  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
								case  'Escape' :  case  'Tab' :  case  'ArrowRight' :  case  'ArrowLeft' : 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 			if  ( ic . readOnly )  switch  ( e . key )  { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
								case  'Tab ' :  case  'Escape' :  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
									e . stopImmediatePropagation ( ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
									e . preventDefault ( )  // falls through 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 				case  'Enter' :  case  'Backspace' :  H . exit ( ic ,  e )  // no default  
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 				case  'Enter' : 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
									H . exit ( ic ,  e . key  ===  'Escape' )  // no default 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 			} 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						} 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						after ( 'ChatRoomCreateElement' ,  ( )  =>  {  // This thing runs on every frame actually. 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 			C . e . parentElement  ? ?  D . body . append ( C . e ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							val ( U . ic ,  ic  =>  ic . dataset [ 'mbchc' ]  ? ?  void  ic . addEventListener ( 'keydown' ,  ickd )  ? ?  ( ic . dataset [ 'mbchc' ]  =  'yes' ) ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							//val(asa(HTMLDivElement, D.querySelector('#TextAreaChatLog')), c => c.scrollHeight > c.clientHeight || void U.pad_chat(c)) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 		} ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						prior ( 'ChatRoomClearAllElements' ,  ( )  =>  C . hide ( )  &&  void  C . e . remove ( ) ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						D . addEventListener ( 'click' ,  _  =>  C . hide ( ) )  // downstream handlers can capture clicks, but I can't be fucked to be honest 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 		//after('ChatRoomResize', () => { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 		//	if (W.CharacterGetCurrent() === null && W.CurrentScreen === 'ChatRoom' && D.querySelector('#InputChat') && D.querySelector('#TextAreaChatLog') && this.comp_hint_visible()) { // Upstream 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 		//		const fontsize = ChatRoomFontSize 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 		//		//w.ElementPositionFix('TextAreaChatLog', fontsize, 1005, 66, 988, 630) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 		//		//w.ElementPositionFix(this.COMP_HINT.id, fontsize, 1005, 701, 988, 200) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 		//		W.ElementPositionFix(this.COMP_HINT.id, fontsize, 800, 65, 200, 835) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 		//		//this.COMP_HINT.style.display = 'flex' 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 		//	} 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 		//}) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 		after ( 'ChatRoomResize' ,  ( )  =>  { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							if  ( W . CharacterGetCurrent ( )  ===  null  &&  W . CurrentScreen  ===  'ChatRoom'  &&  U . ic  !==  $  &&  D . querySelector ( '#TextAreaChatLog' )  !==  null  &&  ! C . hidden )  {  // Upstream 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 				W . ElementPositionFix ( C . e . id ,  ChatRoomFontSize ,  800 ,  65 ,  200 ,  835 ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							} 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						} ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						//D.addEventListener('keydown', event => void this.focus_chat(event)) // Looks like the club got better at this 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
						mod . hookFunction ( 'ChatRoomScrollHistory' ,  0 ,  ( [ up ] )  =>  void  val ( U . ic ,  ic  =>  {  const  input  =  ic . value ,  history  =  W . ChatRoomLastMessage 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							// FIXME we'll make it better when the history is a proper ring buffer 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 			if  ( ! ic . readOnly )  { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
								const /**@type {Map<string,number>}*/ map  =  new  Map ( ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
								const /**@type {(l: string, i: number, I: string) => boolean}*/  cond  =  m _t ( input )  ?  ( _ ,  i ,  _ _ )  =>  i  >  0  :  ( l ,  _ ,  i )  =>  l  !==  i  &&  l . startsWith ( i ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
								if  ( m _t ( history . reduce ( ( ax ,  l ,  i )  =>  cond ( l ,  i ,  input )  ?  ax . set ( l ,  i )  :  ax ,  map ) ) )  return  U . bell ( ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
								val ( asa ( HTMLDivElemen t,  D . querySelector ( '# TextAreaChatLog' ) ) ,  t  =>  t . dataset [ 'mbchcHH' ]  =  ` 𝗵 𝗶 𝘀 𝘁 𝗼 𝗿 𝘆  : ${ m _t ( input )  ?  'Everything'  :  ` Prefix:  ${ input } ` } ` ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
								H . enter ( ic ,  input ,  U . scrolled ,  new  Set ( map . values ( ) ) ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
								H . enter ( ic ,  inpu t,  W . ElementIsScrolledToEnd ( 'TextAreaChatLog' ) ,  new  Set ( map . values ( ) ) ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							} 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
							if  ( ic . readOnly )  {  // this can't be an else, because we mutate state above. To be honest, this will always be true, but I want to make sure. 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 				if  ( H . ids  ===  $ )  return  U . bell ( )  // shouldn't happen?