1
+ addon .name = ' lschat' ;
2
+ addon .author = ' K0D3R' ;
3
+ addon .version = ' 1.0' ;
4
+ addon .desc = ' Outputs Linkshell Chat to a Window' ;
5
+ addon .link = ' ' ;
6
+
7
+ require (' common' );
8
+ local imgui = require (' imgui' );
9
+
10
+ -- Chat Variables
11
+ local chat = {
12
+ messages = T { },
13
+ is_open = { true , },
14
+ };
15
+
16
+ -- Color Window Variable
17
+ local colorWindowOpen = { false , }
18
+
19
+ -- Add new variables for the input buffers
20
+ local usernameBuffer = {' ' }
21
+ local colorBuffer = {' ' }
22
+
23
+ -- Table to store the usernames and colors
24
+ local userColors = {}
25
+
26
+ ---- ----------------------------
27
+ -- Load User Colors From File --
28
+ ---- ----------------------------
29
+ local function loadUserColors ()
30
+ local file = io.open (addon .path :append (' \\ usercolors.txt' ), ' r' );
31
+ if file then
32
+ for line in file :lines () do
33
+ local username , color = line :match (' (%w+): ({[^}]+})' )
34
+ local r , g , b , a = color :match (' {(%d+%.?%d*), (%d+%.?%d*), (%d+%.?%d*), (%d+%.?%d*)}' )
35
+ userColors [username ] = {tonumber (r ), tonumber (g ), tonumber (b ), tonumber (a )}
36
+ end
37
+ file :close ()
38
+ end
39
+ end
40
+
41
+ -- Call the function to load User Colors
42
+ loadUserColors ()
43
+
44
+ ---- ------------------
45
+ -- Clean Up Strings --
46
+ ---- ------------------
47
+ local function clean_str (str )
48
+ -- Parse the strings auto-translate tags..
49
+ str = AshitaCore :GetChatManager ():ParseAutoTranslate (str , true );
50
+
51
+ -- Strip FFXI-specific color and translate tags..
52
+ str = str :strip_colors ();
53
+ str = str :strip_translate (true );
54
+
55
+ -- Strip line breaks..
56
+ while (true ) do
57
+ local hasN = str :endswith (' \n ' );
58
+ local hasR = str :endswith (' \r ' );
59
+
60
+ if (not hasN and not hasR ) then
61
+ break ;
62
+ end
63
+
64
+ if (hasN ) then str = str :trimend (' \n ' ); end
65
+ if (hasR ) then str = str :trimend (' \r ' ); end
66
+ end
67
+
68
+ -- Replace mid-linebreaks..
69
+ return (str :gsub (string.char (0x07 ), ' \n ' ));
70
+ end
71
+
72
+ ---- --------------------------
73
+ -- Check for slash commands --
74
+ ---- --------------------------
75
+ ashita .events .register (' command' , ' command_cb' , function (e )
76
+ -- Parse the command arguments..
77
+ local args = e .command :args ();
78
+ if (# args == 0 or not args [1 ]:any (' /lschat' )) then
79
+ return ;
80
+ end
81
+
82
+ -- Block all related commands..
83
+ e .blocked = true ;
84
+
85
+ -- Toggle the chat window..
86
+ chat .is_open [1 ] = not chat .is_open [1 ];
87
+ end );
88
+
89
+ ---- -----------------------
90
+ -- Read Incoming Packets --
91
+ ---- -----------------------
92
+ ashita .events .register (' packet_in' , ' packet_in_cb' , function (e )
93
+ -- Packet: Linkshell Message
94
+ if (e .id == 0x017 ) then
95
+ local msgType = struct .unpack (' B' , e .data , 0x04 + 1 );
96
+ if (msgType == 5 ) or (msgType == 27 ) then
97
+ local character = struct .unpack (' c15' , e .data_modified , 0x08 + 1 ):trimend (' \x00 ' );
98
+ local msg = struct .unpack (' s' , e .data_modified , 0x17 + 0x01 );
99
+
100
+ -- Replace percent signs with double percent signs
101
+ msg = string.gsub (msg , " %%" , " %%%%" );
102
+ msg = clean_str (msg );
103
+
104
+ local fullMsg = character .. " : " .. msg ;
105
+ if (not chat .messages :hasval (fullMsg )) then
106
+ chat .messages :append (fullMsg );
107
+ -- Play a sound file when a new message is added
108
+ ashita .misc .play_sound (addon .path :append (' \\ sounds\\ message.wav' ));
109
+ end
110
+ end
111
+ end
112
+ end );
113
+
114
+ ---- -----------------------
115
+ -- Read Outgoing Packets --
116
+ ---- -----------------------
117
+ ashita .events .register (' packet_out' , ' outgoing_packet' , function (e )
118
+ if (e .id == 0x0B5 ) then
119
+ local msgType = struct .unpack (' B' , e .data , 0x04 + 1 );
120
+ if (msgType == 5 ) or (msgType == 27 ) then
121
+ local msg = struct .unpack (' s' , e .data_modified , 0x06 + 0x01 );
122
+
123
+ -- Replace percent signs with double percent signs
124
+ msg = string.gsub (msg , " %%" , " %%%%" );
125
+ msg = clean_str (msg );
126
+
127
+ local character = AshitaCore :GetMemoryManager ():GetParty ():GetMemberName (0 ) or ' Unknown' ;
128
+ local fullMsg = character .. " : " .. msg ;
129
+ if (not chat .messages :hasval (fullMsg )) then
130
+ chat .messages :append (fullMsg );
131
+ end
132
+ end
133
+ end
134
+ end );
135
+
136
+ ---- -------------
137
+ -- Form Design --
138
+ ---- -------------
139
+ ashita .events .register (' d3d_present' , ' present_cb' , function ()
140
+ if (chat .is_open [1 ]) then
141
+ imgui .SetNextWindowSize ({ 400 , 400 , }, ImGuiCond_FirstUseEver );
142
+ if (imgui .Begin (' Linkshell Chat' , chat .is_open )) then
143
+ if (imgui .Button (' Clear Chat' )) then
144
+ chat .messages :clear ();
145
+ end
146
+
147
+ imgui .Separator ();
148
+
149
+ if (imgui .BeginChild (' MessagesWindow' , {0 , - imgui .GetFrameHeightWithSpacing () + 20 })) then
150
+ chat .messages :each (function (v , k )
151
+ local username , message = string.match (v , " (%w+): (.*)" )
152
+ local color = userColors [username ] or {0.0 , 1.0 , 0.0 , 1.0 } -- Default color is Green
153
+
154
+ imgui .TextColored (color , username .. " :" )
155
+ imgui .SameLine ()
156
+ imgui .TextWrapped (message )
157
+ end );
158
+ imgui .SetScrollHereY (1.0 ); -- Scrolls to the bottom
159
+ end
160
+ imgui .EndChild ();
161
+ end
162
+ imgui .End ();
163
+ end
164
+ end );
0 commit comments