36 uses uMisc, uStore, uConsts, SDLh, uConsole, uKeys, uTeams; |
36 uses uMisc, uStore, uConsts, SDLh, uConsole, uKeys, uTeams; |
37 |
37 |
38 const MaxStrIndex = 27; |
38 const MaxStrIndex = 27; |
39 |
39 |
40 type TChatLine = record |
40 type TChatLine = record |
41 Tex: PTexture; |
41 Tex: PTexture; |
42 Time: Longword; |
42 Time: Longword; |
43 Width: LongInt; |
43 Width: LongInt; |
44 s: shortstring; |
44 s: shortstring; |
45 end; |
45 end; |
46 |
46 |
47 var Strs: array[0 .. MaxStrIndex] of TChatLine; |
47 var Strs: array[0 .. MaxStrIndex] of TChatLine; |
48 lastStr: LongWord; |
48 lastStr: LongWord; |
49 visibleCount: LongWord; |
49 visibleCount: LongWord; |
50 InputStr: TChatLine; |
50 InputStr: TChatLine; |
51 InputStrL: array[0..260] of char; // for full str + 4-byte utf-8 char |
51 InputStrL: array[0..260] of char; // for full str + 4-byte utf-8 char |
52 |
52 |
53 const colors: array[#1..#4] of TSDL_Color = ( |
53 const colors: array[#1..#4] of TSDL_Color = ( |
54 (r:$FF; g:$FF; b:$FF; unused:$FF), // chat message [White] |
54 (r:$FF; g:$FF; b:$FF; unused:$FF), // chat message [White] |
55 (r:$FF; g:$00; b:$FF; unused:$FF), // action message [Purple] |
55 (r:$FF; g:$00; b:$FF; unused:$FF), // action message [Purple] |
56 (r:$90; g:$FF; b:$90; unused:$FF), // join/leave message [Lime] |
56 (r:$90; g:$FF; b:$90; unused:$FF), // join/leave message [Lime] |
57 (r:$FF; g:$FF; b:$A0; unused:$FF) // team message [Light Yellow] |
57 (r:$FF; g:$FF; b:$A0; unused:$FF) // team message [Light Yellow] |
58 ); |
58 ); |
59 |
59 |
60 procedure SetLine(var cl: TChatLine; str: shortstring; isInput: boolean); |
60 procedure SetLine(var cl: TChatLine; str: shortstring; isInput: boolean); |
61 var strSurface, resSurface: PSDL_Surface; |
61 var strSurface, resSurface: PSDL_Surface; |
62 w, h: LongInt; |
62 w, h: LongInt; |
63 color: TSDL_Color; |
63 color: TSDL_Color; |
64 font: THWFont; |
64 font: THWFont; |
65 begin |
65 begin |
66 if cl.Tex <> nil then |
66 if cl.Tex <> nil then |
67 FreeTexture(cl.Tex); |
67 FreeTexture(cl.Tex); |
68 |
68 |
69 |
69 |
70 cl.s:= str; |
70 cl.s:= str; |
71 |
71 |
72 if isInput then |
72 if isInput then |
73 begin |
73 begin |
74 // [Light Blue] |
74 // [Light Blue] |
75 color.r:= $00; |
75 color.r:= $00; |
76 color.g:= $FF; |
76 color.g:= $FF; |
77 color.b:= $FF; |
77 color.b:= $FF; |
78 color.unused:= $FF; |
78 color.unused:= $FF; |
79 str:= UserNick + '> ' + str + '_' |
79 str:= UserNick + '> ' + str + '_' |
80 end |
80 end |
81 else |
81 else |
82 begin |
82 begin |
83 color:= colors[str[1]]; |
83 color:= colors[str[1]]; |
84 delete(str, 1, 1) |
84 delete(str, 1, 1) |
85 end; |
85 end; |
86 |
86 |
87 font:= CheckCJKFont(str, fnt16); |
87 font:= CheckCJKFont(str, fnt16); |
88 TTF_SizeUTF8(Fontz[font].Handle, Str2PChar(str), w, h); |
88 TTF_SizeUTF8(Fontz[font].Handle, Str2PChar(str), w, h); |
89 |
89 |
109 inc(visibleCount) |
109 inc(visibleCount) |
110 end; |
110 end; |
111 |
111 |
112 procedure DrawChat; |
112 procedure DrawChat; |
113 var i, t, cnt: Longword; |
113 var i, t, cnt: Longword; |
114 r: TSDL_Rect; |
114 r: TSDL_Rect; |
115 begin |
115 begin |
116 cnt:= 0; |
116 cnt:= 0; |
117 t:= 0; |
117 t:= 0; |
118 i:= lastStr; |
118 i:= lastStr; |
119 |
119 |
120 r.x:= 6 - cScreenWidth div 2; |
120 r.x:= 6 - cScreenWidth div 2; |
121 r.y:= (visibleCount - t) * 16 + 10; |
121 r.y:= (visibleCount - t) * 16 + 10; |
122 r.h:= 16; |
122 r.h:= 16; |
123 |
123 |
124 if (GameState = gsChat) |
124 if (GameState = gsChat) |
125 and (InputStr.Tex <> nil) then |
125 and (InputStr.Tex <> nil) then |
126 begin |
126 begin |
127 r.w:= InputStr.Width; |
127 r.w:= InputStr.Width; |
128 DrawFillRect(r); |
128 DrawFillRect(r); |
129 DrawTexture(8 - cScreenWidth div 2, visibleCount * 16 + 10, InputStr.Tex); |
129 DrawTexture(8 - cScreenWidth div 2, visibleCount * 16 + 10, InputStr.Tex); |
130 end; |
130 end; |
131 |
131 |
132 dec(r.y, 16); |
132 dec(r.y, 16); |
133 |
133 |
134 while |
134 while |
135 ( |
135 ( |
136 ((t < 7) and (Strs[i].Time > RealTicks)) |
136 ((t < 7) and (Strs[i].Time > RealTicks)) |
137 or |
137 or |
138 ((t < MaxStrIndex) and showAll) |
138 ((t < MaxStrIndex) and showAll) |
139 ) |
139 ) |
140 and |
140 and |
141 (Strs[i].Tex <> nil) do |
141 (Strs[i].Tex <> nil) do |
142 begin |
142 begin |
143 r.w:= Strs[i].Width; |
143 r.w:= Strs[i].Width; |
144 DrawFillRect(r); |
144 DrawFillRect(r); |
145 DrawTexture(8 - cScreenWidth div 2, (visibleCount - t) * 16 - 6, Strs[i].Tex); |
145 DrawTexture(8 - cScreenWidth div 2, (visibleCount - t) * 16 - 6, Strs[i].Tex); |
146 dec(r.y, 16); |
146 dec(r.y, 16); |
147 |
147 |
148 if i = 0 then i:= MaxStrIndex else dec(i); |
148 if i = 0 then i:= MaxStrIndex else dec(i); |
149 inc(cnt); |
149 inc(cnt); |
150 inc(t) |
150 inc(t) |
151 end; |
151 end; |
152 |
152 |
153 visibleCount:= cnt; |
153 visibleCount:= cnt; |
154 end; |
154 end; |
155 |
155 |
156 procedure AcceptChatString(s: shortstring); |
156 procedure AcceptChatString(s: shortstring); |
214 begin |
214 begin |
215 ParseCommand(s, true); |
215 ParseCommand(s, true); |
216 exit |
216 exit |
217 end; |
217 end; |
218 if (s[1] = '/') and (copy(s, 1, 4) <> '/me ') then |
218 if (s[1] = '/') and (copy(s, 1, 4) <> '/me ') then |
219 begin |
219 begin |
220 if CurrentTeam^.ExtDriven then exit; |
220 if CurrentTeam^.ExtDriven then exit; |
221 |
221 |
222 for i:= Low(TWave) to High(TWave) do |
222 for i:= Low(TWave) to High(TWave) do |
223 if (s = Wavez[i].cmd) then |
223 if (s = Wavez[i].cmd) then |
224 begin |
224 begin |
225 ParseCommand('/taunt ' + char(i), true); |
225 ParseCommand('/taunt ' + char(i), true); |
226 exit |
226 exit |
227 end; |
227 end; |
228 if (s = '/newgrave') then |
228 if (s = '/newgrave') then |
229 begin |
229 begin |
230 ParseCommand('/newgrave', true); |
230 ParseCommand('/newgrave', true); |
231 exit |
231 exit |
232 end; |
232 end; |
233 end |
233 end |
234 else |
234 else |
235 ParseCommand('/say ' + s, true); |
235 ParseCommand('/say ' + s, true); |
236 end; |
236 end; |
237 |
237 |
238 procedure KeyPressChat(Key: Longword); |
238 procedure KeyPressChat(Key: Longword); |
239 const firstByteMark: array[1..4] of byte = (0, $C0, $E0, $F0); |
239 const firstByteMark: array[1..4] of byte = (0, $C0, $E0, $F0); |
240 var i, btw: integer; |
240 var i, btw: integer; |
241 utf8: shortstring; |
241 utf8: shortstring; |
242 begin |
242 begin |
243 |
243 |
244 if Key <> 0 then |
244 if Key <> 0 then |
245 case Key of |
245 case Key of |
246 {Backspace} |
246 {Backspace} |
247 8, 127: if Length(InputStr.s) > 0 then |
247 8, 127: if Length(InputStr.s) > 0 then |
248 begin |
248 begin |
249 InputStr.s[0]:= InputStrL[byte(InputStr.s[0])]; |
249 InputStr.s[0]:= InputStrL[byte(InputStr.s[0])]; |
250 SetLine(InputStr, InputStr.s, true) |
250 SetLine(InputStr, InputStr.s, true) |
251 end; |
251 end; |
252 {Esc} |
252 {Esc} |
253 27: SetLine(InputStr, '', true); |
253 27: SetLine(InputStr, '', true); |
254 {Return} |
254 {Return} |
255 3, 13, 271: begin |
255 3, 13, 271: begin |
256 if Length(InputStr.s) > 0 then |
256 if Length(InputStr.s) > 0 then |
257 begin |
257 begin |
258 AcceptChatString(InputStr.s); |
258 AcceptChatString(InputStr.s); |
259 SetLine(InputStr, '', false) |
259 SetLine(InputStr, '', false) |
260 end; |
260 end; |
261 FreezeEnterKey; |
261 FreezeEnterKey; |
262 GameState:= gsGame |
262 GameState:= gsGame |
263 end; |
263 end; |
264 else |
264 else |
265 if (Key < $80) then btw:= 1 |
265 if (Key < $80) then btw:= 1 |
266 else if (Key < $800) then btw:= 2 |
266 else if (Key < $800) then btw:= 2 |
267 else if (Key < $10000) then btw:= 3 |
267 else if (Key < $10000) then btw:= 3 |
268 else btw:= 4; |
268 else btw:= 4; |
269 |
269 |
270 utf8:= ''; |
270 utf8:= ''; |
271 |
271 |
272 for i:= btw downto 2 do |
272 for i:= btw downto 2 do |
273 begin |
273 begin |
274 utf8:= char((Key or $80) and $BF) + utf8; |
274 utf8:= char((Key or $80) and $BF) + utf8; |
275 Key:= Key shr 6 |
275 Key:= Key shr 6 |
276 end; |
276 end; |
277 |
277 |
278 utf8:= char(Key or firstByteMark[btw]) + utf8; |
278 utf8:= char(Key or firstByteMark[btw]) + utf8; |
279 |
279 |
280 if byte(InputStr.s[0]) + btw > 240 then exit; |
280 if byte(InputStr.s[0]) + btw > 240 then exit; |
281 |
281 |
282 InputStrL[byte(InputStr.s[0]) + btw]:= InputStr.s[0]; |
282 InputStrL[byte(InputStr.s[0]) + btw]:= InputStr.s[0]; |
283 SetLine(InputStr, InputStr.s + utf8, true) |
283 SetLine(InputStr, InputStr.s + utf8, true) |
284 end |
284 end |
285 end; |
285 end; |
286 |
286 |
287 procedure init_uChat; |
287 procedure init_uChat; |
288 begin |
288 begin |
289 lastStr:= 0; |
289 lastStr:= 0; |