diff --git a/.gitignore b/.gitignore index 8fb70016..582e43c8 100644 --- a/.gitignore +++ b/.gitignore @@ -42,3 +42,4 @@ profile/* logs/* private/* .DS_Store +patch/* diff --git a/README.md b/README.md index 11deb75d..013950cb 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,17 @@ +# AssaultCube+ + +## this is a fork of AssaultCube with very cool ass features + +changes: +match settings menu +speed display `showspeed`/`showspeedpos` +gun weight (heavier weapons slow you down) +unicode support (for russian larping) + + + + +original description below ## What is AssaultCube? AssaultCube is a **FREE**, multiplayer, first-person shooter game, based on the [CUBE engine](http://cubeengine.com/cube.php). diff --git a/ac.zip b/ac.zip new file mode 100644 index 00000000..82939f40 Binary files /dev/null and b/ac.zip differ diff --git a/build.sh b/build.sh new file mode 100755 index 00000000..11f16fe6 --- /dev/null +++ b/build.sh @@ -0,0 +1,3 @@ +cd ~/AC/source/src/ +make -j8 CXX=clang++ -j$(nproc) install +cd ~/AC/ diff --git a/config/font.cfg b/config/font.cfg index 87941035..115ce843 100644 --- a/config/font.cfg +++ b/config/font.cfg @@ -3,6 +3,7 @@ exec config/font_default.cfg // Must be executed! DO NOT MODIFY. exec config/font_monospace.cfg // Must be executed! DO NOT MODIFY. exec config/font_serif.cfg +exec config/font_unicode.cfg // extra glyphs (Latin-1/Ext-A, Greek, Cyrillic) for the fonts above; needs the "fontselect" and "fontcharu" commands // Then, in that file, define the font. To do this, first define the font file. // See: ./docs/reference.xml#identifier_font for the command to do this. diff --git a/config/font_unicode.cfg b/config/font_unicode.cfg new file mode 100644 index 00000000..f7f7f161 --- /dev/null +++ b/config/font_unicode.cfg @@ -0,0 +1,1015 @@ +// Extra glyphs for the built-in fonts: Latin-1, Latin Extended-A, Greek, Cyrillic, some punctuation. +// Generated by source/dev_tools/gen_unicode_fonts.py - do not edit by hand. +// "fontselect" makes an existing font the target of the following "fontcharu" commands (cp x y w h). + +fontselect default +fontcharu 161 1 510 23 64 // U+00A1 ¡ +fontcharu 162 25 510 40 64 // U+00A2 ¢ +fontcharu 163 66 510 42 64 // U+00A3 £ +fontcharu 164 109 510 43 64 // U+00A4 ¤ +fontcharu 165 153 510 50 64 // U+00A5 ¥ +fontcharu 166 204 510 19 64 // U+00A6 ¦ +fontcharu 167 224 510 39 64 // U+00A7 § +fontcharu 168 264 510 29 64 // U+00A8 ¨ +fontcharu 169 294 510 53 64 // U+00A9 © +fontcharu 170 348 510 34 64 // U+00AA ª +fontcharu 171 383 510 39 64 // U+00AB « +fontcharu 172 423 510 48 64 // U+00AC ¬ +fontcharu 174 472 510 53 64 // U+00AE ® +fontcharu 175 526 510 28 64 // U+00AF ¯ +fontcharu 176 555 510 30 64 // U+00B0 ° +fontcharu 177 586 510 48 64 // U+00B1 ± +fontcharu 178 635 510 31 64 // U+00B2 ² +fontcharu 179 667 510 31 64 // U+00B3 ³ +fontcharu 180 699 510 27 64 // U+00B4 ´ +fontcharu 181 727 510 47 66 // U+00B5 µ +fontcharu 182 775 510 40 64 // U+00B6 ¶ +fontcharu 183 816 510 23 64 // U+00B7 · +fontcharu 184 840 510 25 65 // U+00B8 ¸ +fontcharu 185 866 510 30 64 // U+00B9 ¹ +fontcharu 186 897 510 36 64 // U+00BA º +fontcharu 187 934 510 39 64 // U+00BB » +fontcharu 188 1 578 61 64 // U+00BC ¼ +fontcharu 189 63 578 63 64 // U+00BD ½ +fontcharu 190 127 578 61 64 // U+00BE ¾ +fontcharu 191 189 578 38 66 // U+00BF ¿ +fontcharu 192 228 578 46 64 // U+00C0 À +fontcharu 193 275 578 46 64 // U+00C1 Á +fontcharu 194 322 578 46 64 // U+00C2  +fontcharu 195 369 578 46 64 // U+00C3 à +fontcharu 196 416 578 46 64 // U+00C4 Ä +fontcharu 197 463 578 46 64 // U+00C5 Å +fontcharu 198 510 578 68 64 // U+00C6 Æ +fontcharu 199 579 578 46 64 // U+00C7 Ç +fontcharu 200 626 578 35 64 // U+00C8 È +fontcharu 201 662 578 35 64 // U+00C9 É +fontcharu 202 698 578 35 64 // U+00CA Ê +fontcharu 203 734 578 35 64 // U+00CB Ë +fontcharu 204 770 578 25 64 // U+00CC Ì +fontcharu 205 796 578 23 64 // U+00CD Í +fontcharu 206 820 578 29 64 // U+00CE Î +fontcharu 207 850 578 26 64 // U+00CF Ï +fontcharu 208 877 578 56 64 // U+00D0 Ð +fontcharu 209 934 578 41 64 // U+00D1 Ñ +fontcharu 210 976 578 46 64 // U+00D2 Ò +fontcharu 211 1 646 46 64 // U+00D3 Ó +fontcharu 212 48 646 46 64 // U+00D4 Ô +fontcharu 213 95 646 46 64 // U+00D5 Õ +fontcharu 214 142 646 46 64 // U+00D6 Ö +fontcharu 215 189 646 46 64 // U+00D7 × +fontcharu 216 236 646 53 64 // U+00D8 Ø +fontcharu 217 290 646 40 64 // U+00D9 Ù +fontcharu 218 331 646 40 64 // U+00DA Ú +fontcharu 219 372 646 40 64 // U+00DB Û +fontcharu 220 413 646 40 64 // U+00DC Ü +fontcharu 221 454 646 46 64 // U+00DD Ý +fontcharu 222 501 646 45 64 // U+00DE Þ +fontcharu 223 547 646 44 64 // U+00DF ß +fontcharu 224 592 646 40 64 // U+00E0 à +fontcharu 225 633 646 40 64 // U+00E1 á +fontcharu 226 674 646 40 64 // U+00E2 â +fontcharu 227 715 646 40 64 // U+00E3 ã +fontcharu 228 756 646 41 64 // U+00E4 ä +fontcharu 229 798 646 37 64 // U+00E5 å +fontcharu 230 836 646 65 64 // U+00E6 æ +fontcharu 231 902 646 39 65 // U+00E7 ç +fontcharu 232 942 646 42 64 // U+00E8 è +fontcharu 233 1 714 42 64 // U+00E9 é +fontcharu 234 44 714 42 64 // U+00EA ê +fontcharu 235 87 714 43 64 // U+00EB ë +fontcharu 236 131 714 26 64 // U+00EC ì +fontcharu 237 158 714 28 64 // U+00ED í +fontcharu 238 187 714 31 64 // U+00EE î +fontcharu 239 219 714 29 64 // U+00EF ï +fontcharu 240 249 714 44 64 // U+00F0 ð +fontcharu 241 294 714 40 64 // U+00F1 ñ +fontcharu 242 335 714 43 64 // U+00F2 ò +fontcharu 243 379 714 43 64 // U+00F3 ó +fontcharu 244 423 714 43 64 // U+00F4 ô +fontcharu 245 467 714 43 64 // U+00F5 õ +fontcharu 246 511 714 43 64 // U+00F6 ö +fontcharu 247 555 714 48 64 // U+00F7 ÷ +fontcharu 248 604 714 46 64 // U+00F8 ø +fontcharu 249 651 714 41 64 // U+00F9 ù +fontcharu 250 693 714 41 64 // U+00FA ú +fontcharu 251 735 714 41 64 // U+00FB û +fontcharu 252 777 714 40 64 // U+00FC ü +fontcharu 253 818 714 44 65 // U+00FD ý +fontcharu 254 863 714 43 65 // U+00FE þ +fontcharu 255 907 714 45 65 // U+00FF ÿ +fontcharu 256 953 714 46 64 // U+0100 Ā +fontcharu 257 1 782 41 64 // U+0101 ā +fontcharu 258 43 782 46 64 // U+0102 Ă +fontcharu 259 90 782 41 64 // U+0103 ă +fontcharu 260 132 782 55 65 // U+0104 Ą +fontcharu 261 188 782 43 65 // U+0105 ą +fontcharu 262 232 782 40 64 // U+0106 Ć +fontcharu 263 273 782 38 64 // U+0107 ć +fontcharu 264 312 782 40 64 // U+0108 Ĉ +fontcharu 265 353 782 37 64 // U+0109 ĉ +fontcharu 266 391 782 40 64 // U+010A Ċ +fontcharu 267 432 782 37 64 // U+010B ċ +fontcharu 268 470 782 40 64 // U+010C Č +fontcharu 269 511 782 37 64 // U+010D č +fontcharu 270 549 782 43 64 // U+010E Ď +fontcharu 271 593 782 56 64 // U+010F ď +fontcharu 272 650 782 56 64 // U+0110 Đ +fontcharu 273 707 782 47 64 // U+0111 đ +fontcharu 274 755 782 35 64 // U+0112 Ē +fontcharu 275 791 782 43 64 // U+0113 ē +fontcharu 276 835 782 35 64 // U+0114 Ĕ +fontcharu 277 871 782 43 64 // U+0115 ĕ +fontcharu 278 915 782 35 64 // U+0116 Ė +fontcharu 279 951 782 42 64 // U+0117 ė +fontcharu 280 1 850 41 65 // U+0118 Ę +fontcharu 281 43 850 45 65 // U+0119 ę +fontcharu 282 89 850 35 64 // U+011A Ě +fontcharu 283 125 850 42 64 // U+011B ě +fontcharu 284 168 850 43 64 // U+011C Ĝ +fontcharu 285 212 850 42 65 // U+011D ĝ +fontcharu 286 255 850 43 64 // U+011E Ğ +fontcharu 287 299 850 43 65 // U+011F ğ +fontcharu 288 343 850 43 64 // U+0120 Ġ +fontcharu 289 387 850 42 65 // U+0121 ġ +fontcharu 290 430 850 50 66 // U+0122 Ģ +fontcharu 291 481 850 43 65 // U+0123 ģ +fontcharu 292 525 850 41 64 // U+0124 Ĥ +fontcharu 293 567 850 41 64 // U+0125 ĥ +fontcharu 294 609 850 56 64 // U+0126 Ħ +fontcharu 295 666 850 45 64 // U+0127 ħ +fontcharu 296 712 850 28 64 // U+0128 Ĩ +fontcharu 297 741 850 30 64 // U+0129 ĩ +fontcharu 298 772 850 26 64 // U+012A Ī +fontcharu 299 799 850 29 64 // U+012B ī +fontcharu 300 829 850 27 64 // U+012C Ĭ +fontcharu 301 857 850 30 64 // U+012D ĭ +fontcharu 302 888 850 28 65 // U+012E Į +fontcharu 303 917 850 26 64 // U+012F į +fontcharu 304 944 850 21 64 // U+0130 İ +fontcharu 305 966 850 23 64 // U+0131 ı +fontcharu 306 1 918 43 65 // U+0132 IJ +fontcharu 307 45 918 40 65 // U+0133 ij +fontcharu 308 86 918 32 64 // U+0134 Ĵ +fontcharu 309 119 918 32 65 // U+0135 ĵ +fontcharu 310 152 918 52 65 // U+0136 Ķ +fontcharu 311 205 918 44 64 // U+0137 ķ +fontcharu 312 250 918 46 64 // U+0138 ĸ +fontcharu 313 297 918 35 64 // U+0139 Ĺ +fontcharu 314 333 918 25 64 // U+013A ĺ +fontcharu 315 359 918 41 65 // U+013B Ļ +fontcharu 316 401 918 24 64 // U+013C ļ +fontcharu 317 426 918 41 64 // U+013D Ľ +fontcharu 318 468 918 33 64 // U+013E ľ +fontcharu 319 502 918 41 64 // U+013F Ŀ +fontcharu 320 544 918 34 64 // U+0140 ŀ +fontcharu 321 579 918 49 64 // U+0141 Ł +fontcharu 322 629 918 34 64 // U+0142 ł +fontcharu 323 664 918 41 64 // U+0143 Ń +fontcharu 324 706 918 40 64 // U+0144 ń +fontcharu 325 747 918 48 65 // U+0145 Ņ +fontcharu 326 796 918 43 65 // U+0146 ņ +fontcharu 327 840 918 41 64 // U+0147 Ň +fontcharu 328 882 918 40 64 // U+0148 ň +fontcharu 329 923 918 59 64 // U+0149 ʼn +fontcharu 330 1 986 47 65 // U+014A Ŋ +fontcharu 331 49 986 43 66 // U+014B ŋ +fontcharu 332 93 986 46 64 // U+014C Ō +fontcharu 333 140 986 44 64 // U+014D ō +fontcharu 334 185 986 46 64 // U+014E Ŏ +fontcharu 335 232 986 43 64 // U+014F ŏ +fontcharu 336 276 986 46 64 // U+0150 Ő +fontcharu 337 323 986 43 64 // U+0151 ő +fontcharu 338 367 986 68 64 // U+0152 Œ +fontcharu 339 436 986 68 64 // U+0153 œ +fontcharu 340 505 986 41 64 // U+0154 Ŕ +fontcharu 341 547 986 34 64 // U+0155 ŕ +fontcharu 342 582 986 49 65 // U+0156 Ŗ +fontcharu 343 632 986 35 65 // U+0157 ŗ +fontcharu 344 668 986 41 64 // U+0158 Ř +fontcharu 345 710 986 33 64 // U+0159 ř +fontcharu 346 744 986 38 64 // U+015A Ś +fontcharu 347 783 986 38 64 // U+015B ś +fontcharu 348 822 986 38 64 // U+015C Ŝ +fontcharu 349 861 986 38 64 // U+015D ŝ +fontcharu 350 900 986 44 64 // U+015E Ş +fontcharu 351 945 986 41 65 // U+015F ş +fontcharu 352 1 1054 38 64 // U+0160 Š +fontcharu 353 40 1054 38 64 // U+0161 š +fontcharu 354 79 1054 50 65 // U+0162 Ţ +fontcharu 355 130 1054 37 65 // U+0163 ţ +fontcharu 356 168 1054 42 64 // U+0164 Ť +fontcharu 357 211 1054 37 64 // U+0165 ť +fontcharu 358 249 1054 50 64 // U+0166 Ŧ +fontcharu 359 300 1054 37 64 // U+0167 ŧ +fontcharu 360 338 1054 40 64 // U+0168 Ũ +fontcharu 361 379 1054 41 64 // U+0169 ũ +fontcharu 362 421 1054 40 64 // U+016A Ū +fontcharu 363 462 1054 41 64 // U+016B ū +fontcharu 364 504 1054 40 64 // U+016C Ŭ +fontcharu 365 545 1054 40 64 // U+016D ŭ +fontcharu 366 586 1054 40 64 // U+016E Ů +fontcharu 367 627 1054 38 64 // U+016F ů +fontcharu 368 666 1054 40 64 // U+0170 Ű +fontcharu 369 707 1054 41 64 // U+0171 ű +fontcharu 370 749 1054 47 65 // U+0172 Ų +fontcharu 371 797 1054 48 65 // U+0173 ų +fontcharu 372 846 1054 59 64 // U+0174 Ŵ +fontcharu 373 906 1054 56 64 // U+0175 ŵ +fontcharu 374 963 1054 46 64 // U+0176 Ŷ +fontcharu 375 1 1122 44 65 // U+0177 ŷ +fontcharu 376 46 1122 46 64 // U+0178 Ÿ +fontcharu 377 93 1122 40 64 // U+0179 Ź +fontcharu 378 134 1122 37 64 // U+017A ź +fontcharu 379 172 1122 40 64 // U+017B Ż +fontcharu 380 213 1122 37 64 // U+017C ż +fontcharu 381 251 1122 40 64 // U+017D Ž +fontcharu 382 292 1122 37 64 // U+017E ž +fontcharu 383 330 1122 35 64 // U+017F ſ +fontcharu 902 366 1122 51 64 // U+0386 Ά +fontcharu 904 418 1122 53 64 // U+0388 Έ +fontcharu 905 472 1122 59 64 // U+0389 Ή +fontcharu 906 532 1122 36 64 // U+038A Ί +fontcharu 908 569 1122 55 64 // U+038C Ό +fontcharu 910 625 1122 64 64 // U+038E Ύ +fontcharu 911 690 1122 58 64 // U+038F Ώ +fontcharu 912 749 1122 28 64 // U+0390 ΐ +fontcharu 913 778 1122 55 64 // U+0391 Α +fontcharu 914 834 1122 45 64 // U+0392 Β +fontcharu 915 880 1122 41 64 // U+0393 Γ +fontcharu 916 922 1122 55 64 // U+0394 Δ +fontcharu 917 978 1122 41 64 // U+0395 Ε +fontcharu 918 1 1190 48 64 // U+0396 Ζ +fontcharu 919 50 1190 48 64 // U+0397 Η +fontcharu 920 99 1190 53 64 // U+0398 Θ +fontcharu 921 153 1190 23 64 // U+0399 Ι +fontcharu 922 177 1190 52 64 // U+039A Κ +fontcharu 923 230 1190 55 64 // U+039B Λ +fontcharu 924 286 1190 57 64 // U+039C Μ +fontcharu 925 344 1190 48 64 // U+039D Ν +fontcharu 926 393 1190 38 64 // U+039E Ξ +fontcharu 927 432 1190 53 64 // U+039F Ο +fontcharu 928 486 1190 48 64 // U+03A0 Π +fontcharu 929 535 1190 45 64 // U+03A1 Ρ +fontcharu 931 581 1190 41 64 // U+03A3 Σ +fontcharu 932 623 1190 50 64 // U+03A4 Τ +fontcharu 933 674 1190 54 64 // U+03A5 Υ +fontcharu 934 729 1190 54 64 // U+03A6 Φ +fontcharu 935 784 1190 53 64 // U+03A7 Χ +fontcharu 936 838 1190 53 64 // U+03A8 Ψ +fontcharu 937 892 1190 55 64 // U+03A9 Ω +fontcharu 938 948 1190 26 64 // U+03AA Ϊ +fontcharu 939 975 1190 46 64 // U+03AB Ϋ +fontcharu 940 1 1258 43 64 // U+03AC ά +fontcharu 941 45 1258 35 64 // U+03AD έ +fontcharu 942 81 1258 40 65 // U+03AE ή +fontcharu 943 122 1258 27 64 // U+03AF ί +fontcharu 944 150 1258 35 64 // U+03B0 ΰ +fontcharu 945 186 1258 46 64 // U+03B1 α +fontcharu 946 233 1258 43 65 // U+03B2 β +fontcharu 947 277 1258 49 66 // U+03B3 γ +fontcharu 948 327 1258 44 64 // U+03B4 δ +fontcharu 949 372 1258 37 64 // U+03B5 ε +fontcharu 950 410 1258 39 65 // U+03B6 ζ +fontcharu 951 450 1258 43 66 // U+03B7 η +fontcharu 952 494 1258 44 64 // U+03B8 θ +fontcharu 953 539 1258 28 64 // U+03B9 ι +fontcharu 954 568 1258 44 64 // U+03BA κ +fontcharu 955 613 1258 43 64 // U+03BB λ +fontcharu 956 657 1258 47 66 // U+03BC μ +fontcharu 957 705 1258 47 64 // U+03BD ν +fontcharu 958 753 1258 39 65 // U+03BE ξ +fontcharu 959 793 1258 46 64 // U+03BF ο +fontcharu 960 840 1258 51 64 // U+03C0 π +fontcharu 961 892 1258 45 66 // U+03C1 ρ +fontcharu 962 938 1258 39 66 // U+03C2 ς +fontcharu 963 1 1326 50 64 // U+03C3 σ +fontcharu 964 52 1326 45 64 // U+03C4 τ +fontcharu 965 98 1326 43 64 // U+03C5 υ +fontcharu 966 142 1326 49 66 // U+03C6 φ +fontcharu 967 192 1326 46 66 // U+03C7 χ +fontcharu 968 239 1326 49 66 // U+03C8 ψ +fontcharu 969 289 1326 56 64 // U+03C9 ω +fontcharu 970 346 1326 30 64 // U+03CA ϊ +fontcharu 971 377 1326 42 64 // U+03CB ϋ +fontcharu 972 420 1326 43 64 // U+03CC ό +fontcharu 973 464 1326 41 64 // U+03CD ύ +fontcharu 974 506 1326 52 64 // U+03CE ώ +fontcharu 1024 559 1326 35 64 // U+0400 Ѐ +fontcharu 1025 595 1326 35 64 // U+0401 Ё +fontcharu 1026 631 1326 55 65 // U+0402 Ђ +fontcharu 1027 687 1326 35 64 // U+0403 Ѓ +fontcharu 1028 723 1326 46 64 // U+0404 Є +fontcharu 1029 770 1326 44 64 // U+0405 Ѕ +fontcharu 1030 815 1326 23 64 // U+0406 І +fontcharu 1031 839 1326 26 64 // U+0407 Ї +fontcharu 1032 866 1326 32 65 // U+0408 Ј +fontcharu 1033 899 1326 69 64 // U+0409 Љ +fontcharu 1034 1 1394 65 64 // U+040A Њ +fontcharu 1035 67 1394 55 64 // U+040B Ћ +fontcharu 1036 123 1394 44 64 // U+040C Ќ +fontcharu 1037 168 1394 41 64 // U+040D Ѝ +fontcharu 1038 210 1394 44 64 // U+040E Ў +fontcharu 1039 255 1394 48 64 // U+040F Џ +fontcharu 1040 304 1394 55 64 // U+0410 А +fontcharu 1041 360 1394 45 64 // U+0411 Б +fontcharu 1042 406 1394 45 64 // U+0412 В +fontcharu 1043 452 1394 41 64 // U+0413 Г +fontcharu 1044 494 1394 55 64 // U+0414 Д +fontcharu 1045 550 1394 41 64 // U+0415 Е +fontcharu 1046 592 1394 79 64 // U+0416 Ж +fontcharu 1047 672 1394 44 64 // U+0417 З +fontcharu 1048 717 1394 48 64 // U+0418 И +fontcharu 1049 766 1394 41 64 // U+0419 Й +fontcharu 1050 808 1394 52 64 // U+041A К +fontcharu 1051 861 1394 51 64 // U+041B Л +fontcharu 1052 913 1394 57 64 // U+041C М +fontcharu 1053 971 1394 48 64 // U+041D Н +fontcharu 1054 1 1462 53 64 // U+041E О +fontcharu 1055 55 1462 48 64 // U+041F П +fontcharu 1056 104 1462 45 64 // U+0420 Р +fontcharu 1057 150 1462 46 64 // U+0421 С +fontcharu 1058 197 1462 50 64 // U+0422 Т +fontcharu 1059 248 1462 52 64 // U+0423 У +fontcharu 1060 301 1462 62 64 // U+0424 Ф +fontcharu 1061 364 1462 53 64 // U+0425 Х +fontcharu 1062 418 1462 55 64 // U+0426 Ц +fontcharu 1063 474 1462 48 64 // U+0427 Ч +fontcharu 1064 523 1462 70 64 // U+0428 Ш +fontcharu 1065 594 1462 77 64 // U+0429 Щ +fontcharu 1066 672 1462 58 64 // U+042A Ъ +fontcharu 1067 731 1462 59 64 // U+042B Ы +fontcharu 1068 791 1462 46 64 // U+042C Ь +fontcharu 1069 838 1462 46 64 // U+042D Э +fontcharu 1070 885 1462 68 64 // U+042E Ю +fontcharu 1071 954 1462 47 64 // U+042F Я +fontcharu 1072 1 1530 43 64 // U+0430 а +fontcharu 1073 45 1530 44 64 // U+0431 б +fontcharu 1074 90 1530 41 64 // U+0432 в +fontcharu 1075 132 1530 36 64 // U+0433 г +fontcharu 1076 169 1530 51 64 // U+0434 д +fontcharu 1077 221 1530 45 64 // U+0435 е +fontcharu 1078 267 1530 66 64 // U+0436 ж +fontcharu 1079 334 1530 39 64 // U+0437 з +fontcharu 1080 374 1530 42 64 // U+0438 и +fontcharu 1081 417 1530 41 64 // U+0439 й +fontcharu 1082 459 1530 45 64 // U+043A к +fontcharu 1083 505 1530 45 64 // U+043B л +fontcharu 1084 551 1530 49 64 // U+043C м +fontcharu 1085 601 1530 42 64 // U+043D н +fontcharu 1086 644 1530 46 64 // U+043E о +fontcharu 1087 691 1530 42 64 // U+043F п +fontcharu 1088 734 1530 45 66 // U+0440 р +fontcharu 1089 780 1530 39 64 // U+0441 с +fontcharu 1090 820 1530 44 64 // U+0442 т +fontcharu 1091 865 1530 47 66 // U+0443 у +fontcharu 1092 913 1530 59 65 // U+0444 ф +fontcharu 1093 973 1530 47 64 // U+0445 х +fontcharu 1094 1 1598 47 64 // U+0446 ц +fontcharu 1095 49 1598 41 64 // U+0447 ч +fontcharu 1096 91 1598 62 64 // U+0448 ш +fontcharu 1097 154 1598 67 64 // U+0449 щ +fontcharu 1098 222 1598 51 64 // U+044A ъ +fontcharu 1099 274 1598 54 64 // U+044B ы +fontcharu 1100 329 1598 41 64 // U+044C ь +fontcharu 1101 371 1598 40 64 // U+044D э +fontcharu 1102 412 1598 59 64 // U+044E ю +fontcharu 1103 472 1598 42 64 // U+044F я +fontcharu 1104 515 1598 42 64 // U+0450 ѐ +fontcharu 1105 558 1598 43 64 // U+0451 ё +fontcharu 1106 602 1598 46 66 // U+0452 ђ +fontcharu 1107 649 1598 34 64 // U+0453 ѓ +fontcharu 1108 684 1598 39 64 // U+0454 є +fontcharu 1109 724 1598 41 64 // U+0455 ѕ +fontcharu 1110 766 1598 22 64 // U+0456 і +fontcharu 1111 789 1598 29 64 // U+0457 ї +fontcharu 1112 819 1598 28 65 // U+0458 ј +fontcharu 1113 848 1598 62 64 // U+0459 љ +fontcharu 1114 911 1598 59 64 // U+045A њ +fontcharu 1115 971 1598 46 64 // U+045B ћ +fontcharu 1116 1 1666 42 64 // U+045C ќ +fontcharu 1117 44 1666 39 64 // U+045D ѝ +fontcharu 1118 84 1666 45 65 // U+045E ў +fontcharu 1119 130 1666 42 64 // U+045F џ +fontcharu 1168 173 1666 37 64 // U+0490 Ґ +fontcharu 1169 211 1666 36 64 // U+0491 ґ +fontcharu 8211 248 1666 35 64 // U+2013 – +fontcharu 8212 284 1666 63 64 // U+2014 — +fontcharu 8216 348 1666 25 64 // U+2018 ‘ +fontcharu 8217 374 1666 25 64 // U+2019 ’ +fontcharu 8218 400 1666 24 64 // U+201A ‚ +fontcharu 8220 425 1666 38 64 // U+201C “ +fontcharu 8221 464 1666 38 64 // U+201D ” +fontcharu 8222 503 1666 38 64 // U+201E „ +fontcharu 8226 542 1666 33 64 // U+2022 • +fontcharu 8230 576 1666 59 64 // U+2026 … +fontcharu 8364 636 1666 47 64 // U+20AC € +fontcharu 8470 684 1666 73 64 // U+2116 № + +fontselect mono +fontcharu 161 1 512 37 54 // U+00A1 ¡ +fontcharu 162 39 512 37 54 // U+00A2 ¢ +fontcharu 163 77 512 37 51 // U+00A3 £ +fontcharu 164 115 512 37 51 // U+00A4 ¤ +fontcharu 165 153 512 37 51 // U+00A5 ¥ +fontcharu 166 191 512 37 55 // U+00A6 ¦ +fontcharu 167 229 512 37 51 // U+00A7 § +fontcharu 168 267 512 37 51 // U+00A8 ¨ +fontcharu 169 305 512 37 51 // U+00A9 © +fontcharu 170 343 512 37 51 // U+00AA ª +fontcharu 171 381 512 37 51 // U+00AB « +fontcharu 172 419 512 37 51 // U+00AC ¬ +fontcharu 174 457 512 37 51 // U+00AE ® +fontcharu 175 495 512 37 51 // U+00AF ¯ +fontcharu 176 533 512 37 51 // U+00B0 ° +fontcharu 177 571 512 37 51 // U+00B1 ± +fontcharu 178 609 512 37 51 // U+00B2 ² +fontcharu 179 647 512 37 51 // U+00B3 ³ +fontcharu 180 685 512 37 51 // U+00B4 ´ +fontcharu 181 723 512 37 55 // U+00B5 µ +fontcharu 182 761 512 37 51 // U+00B6 ¶ +fontcharu 183 799 512 37 51 // U+00B7 · +fontcharu 184 837 512 37 55 // U+00B8 ¸ +fontcharu 185 875 512 37 51 // U+00B9 ¹ +fontcharu 186 913 512 37 51 // U+00BA º +fontcharu 187 951 512 37 51 // U+00BB » +fontcharu 188 1 571 37 51 // U+00BC ¼ +fontcharu 189 39 571 37 51 // U+00BD ½ +fontcharu 190 77 571 37 51 // U+00BE ¾ +fontcharu 191 115 571 37 55 // U+00BF ¿ +fontcharu 192 153 571 37 51 // U+00C0 À +fontcharu 193 191 571 37 51 // U+00C1 Á +fontcharu 194 229 571 37 51 // U+00C2  +fontcharu 195 267 571 37 51 // U+00C3 à +fontcharu 196 305 571 37 51 // U+00C4 Ä +fontcharu 197 343 571 37 51 // U+00C5 Å +fontcharu 198 381 571 37 51 // U+00C6 Æ +fontcharu 199 419 571 37 55 // U+00C7 Ç +fontcharu 200 457 571 37 51 // U+00C8 È +fontcharu 201 495 571 37 51 // U+00C9 É +fontcharu 202 533 571 37 51 // U+00CA Ê +fontcharu 203 571 571 37 51 // U+00CB Ë +fontcharu 204 609 571 37 51 // U+00CC Ì +fontcharu 205 647 571 37 51 // U+00CD Í +fontcharu 206 685 571 37 51 // U+00CE Î +fontcharu 207 723 571 37 51 // U+00CF Ï +fontcharu 208 761 571 37 51 // U+00D0 Ð +fontcharu 209 799 571 37 51 // U+00D1 Ñ +fontcharu 210 837 571 37 51 // U+00D2 Ò +fontcharu 211 875 571 37 51 // U+00D3 Ó +fontcharu 212 913 571 37 51 // U+00D4 Ô +fontcharu 213 951 571 37 51 // U+00D5 Õ +fontcharu 214 1 630 37 51 // U+00D6 Ö +fontcharu 215 39 630 37 51 // U+00D7 × +fontcharu 216 77 630 37 51 // U+00D8 Ø +fontcharu 217 115 630 37 51 // U+00D9 Ù +fontcharu 218 153 630 37 51 // U+00DA Ú +fontcharu 219 191 630 37 51 // U+00DB Û +fontcharu 220 229 630 37 51 // U+00DC Ü +fontcharu 221 267 630 37 51 // U+00DD Ý +fontcharu 222 305 630 37 51 // U+00DE Þ +fontcharu 223 343 630 37 51 // U+00DF ß +fontcharu 224 381 630 37 51 // U+00E0 à +fontcharu 225 419 630 37 51 // U+00E1 á +fontcharu 226 457 630 37 51 // U+00E2 â +fontcharu 227 495 630 37 51 // U+00E3 ã +fontcharu 228 533 630 37 51 // U+00E4 ä +fontcharu 229 571 630 37 51 // U+00E5 å +fontcharu 230 609 630 37 51 // U+00E6 æ +fontcharu 231 647 630 37 55 // U+00E7 ç +fontcharu 232 685 630 37 51 // U+00E8 è +fontcharu 233 723 630 37 51 // U+00E9 é +fontcharu 234 761 630 37 51 // U+00EA ê +fontcharu 235 799 630 37 51 // U+00EB ë +fontcharu 236 837 630 37 51 // U+00EC ì +fontcharu 237 875 630 37 51 // U+00ED í +fontcharu 238 913 630 37 51 // U+00EE î +fontcharu 239 951 630 37 51 // U+00EF ï +fontcharu 240 1 689 37 51 // U+00F0 ð +fontcharu 241 39 689 37 51 // U+00F1 ñ +fontcharu 242 77 689 37 51 // U+00F2 ò +fontcharu 243 115 689 37 51 // U+00F3 ó +fontcharu 244 153 689 37 51 // U+00F4 ô +fontcharu 245 191 689 37 51 // U+00F5 õ +fontcharu 246 229 689 37 51 // U+00F6 ö +fontcharu 247 267 689 37 51 // U+00F7 ÷ +fontcharu 248 305 689 37 51 // U+00F8 ø +fontcharu 249 343 689 37 51 // U+00F9 ù +fontcharu 250 381 689 37 51 // U+00FA ú +fontcharu 251 419 689 37 51 // U+00FB û +fontcharu 252 457 689 37 51 // U+00FC ü +fontcharu 253 495 689 37 55 // U+00FD ý +fontcharu 254 533 689 37 55 // U+00FE þ +fontcharu 255 571 689 37 55 // U+00FF ÿ +fontcharu 256 609 689 37 51 // U+0100 Ā +fontcharu 257 647 689 37 51 // U+0101 ā +fontcharu 258 685 689 37 51 // U+0102 Ă +fontcharu 259 723 689 37 51 // U+0103 ă +fontcharu 260 761 689 37 55 // U+0104 Ą +fontcharu 261 799 689 37 55 // U+0105 ą +fontcharu 262 837 689 37 51 // U+0106 Ć +fontcharu 263 875 689 37 51 // U+0107 ć +fontcharu 264 913 689 37 51 // U+0108 Ĉ +fontcharu 265 951 689 37 51 // U+0109 ĉ +fontcharu 266 1 748 37 51 // U+010A Ċ +fontcharu 267 39 748 37 51 // U+010B ċ +fontcharu 268 77 748 37 51 // U+010C Č +fontcharu 269 115 748 37 51 // U+010D č +fontcharu 270 153 748 37 51 // U+010E Ď +fontcharu 271 191 748 37 51 // U+010F ď +fontcharu 272 229 748 37 51 // U+0110 Đ +fontcharu 273 267 748 37 51 // U+0111 đ +fontcharu 274 305 748 37 51 // U+0112 Ē +fontcharu 275 343 748 37 51 // U+0113 ē +fontcharu 276 381 748 37 51 // U+0114 Ĕ +fontcharu 277 419 748 37 51 // U+0115 ĕ +fontcharu 278 457 748 37 51 // U+0116 Ė +fontcharu 279 495 748 37 51 // U+0117 ė +fontcharu 280 533 748 37 55 // U+0118 Ę +fontcharu 281 571 748 37 55 // U+0119 ę +fontcharu 282 609 748 37 51 // U+011A Ě +fontcharu 283 647 748 37 51 // U+011B ě +fontcharu 284 685 748 37 51 // U+011C Ĝ +fontcharu 285 723 748 37 55 // U+011D ĝ +fontcharu 286 761 748 37 51 // U+011E Ğ +fontcharu 287 799 748 37 55 // U+011F ğ +fontcharu 288 837 748 37 51 // U+0120 Ġ +fontcharu 289 875 748 37 55 // U+0121 ġ +fontcharu 290 913 748 37 55 // U+0122 Ģ +fontcharu 291 951 748 37 55 // U+0123 ģ +fontcharu 292 1 807 37 51 // U+0124 Ĥ +fontcharu 293 39 807 37 51 // U+0125 ĥ +fontcharu 294 77 807 37 51 // U+0126 Ħ +fontcharu 295 115 807 37 51 // U+0127 ħ +fontcharu 296 153 807 37 51 // U+0128 Ĩ +fontcharu 297 191 807 37 51 // U+0129 ĩ +fontcharu 298 229 807 37 51 // U+012A Ī +fontcharu 299 267 807 37 51 // U+012B ī +fontcharu 300 305 807 37 51 // U+012C Ĭ +fontcharu 301 343 807 37 51 // U+012D ĭ +fontcharu 302 381 807 37 55 // U+012E Į +fontcharu 303 419 807 37 55 // U+012F į +fontcharu 304 457 807 37 51 // U+0130 İ +fontcharu 305 495 807 37 51 // U+0131 ı +fontcharu 306 533 807 37 51 // U+0132 IJ +fontcharu 307 571 807 37 55 // U+0133 ij +fontcharu 308 609 807 37 51 // U+0134 Ĵ +fontcharu 309 647 807 37 55 // U+0135 ĵ +fontcharu 310 685 807 37 54 // U+0136 Ķ +fontcharu 311 723 807 37 54 // U+0137 ķ +fontcharu 312 761 807 37 51 // U+0138 ĸ +fontcharu 313 799 807 37 51 // U+0139 Ĺ +fontcharu 314 837 807 37 51 // U+013A ĺ +fontcharu 315 875 807 37 54 // U+013B Ļ +fontcharu 316 913 807 37 54 // U+013C ļ +fontcharu 317 951 807 37 51 // U+013D Ľ +fontcharu 318 1 866 37 51 // U+013E ľ +fontcharu 319 39 866 37 51 // U+013F Ŀ +fontcharu 320 77 866 37 51 // U+0140 ŀ +fontcharu 321 115 866 37 51 // U+0141 Ł +fontcharu 322 153 866 37 51 // U+0142 ł +fontcharu 323 191 866 37 51 // U+0143 Ń +fontcharu 324 229 866 37 51 // U+0144 ń +fontcharu 325 267 866 37 54 // U+0145 Ņ +fontcharu 326 305 866 37 54 // U+0146 ņ +fontcharu 327 343 866 37 51 // U+0147 Ň +fontcharu 328 381 866 37 51 // U+0148 ň +fontcharu 329 419 866 37 51 // U+0149 ʼn +fontcharu 330 457 866 37 55 // U+014A Ŋ +fontcharu 331 495 866 37 55 // U+014B ŋ +fontcharu 332 533 866 37 51 // U+014C Ō +fontcharu 333 571 866 37 51 // U+014D ō +fontcharu 334 609 866 37 51 // U+014E Ŏ +fontcharu 335 647 866 37 51 // U+014F ŏ +fontcharu 336 685 866 37 51 // U+0150 Ő +fontcharu 337 723 866 37 51 // U+0151 ő +fontcharu 338 761 866 37 51 // U+0152 Œ +fontcharu 339 799 866 37 51 // U+0153 œ +fontcharu 340 837 866 37 51 // U+0154 Ŕ +fontcharu 341 875 866 37 51 // U+0155 ŕ +fontcharu 342 913 866 37 54 // U+0156 Ŗ +fontcharu 343 951 866 37 54 // U+0157 ŗ +fontcharu 344 1 925 37 51 // U+0158 Ř +fontcharu 345 39 925 37 51 // U+0159 ř +fontcharu 346 77 925 37 51 // U+015A Ś +fontcharu 347 115 925 37 51 // U+015B ś +fontcharu 348 153 925 37 51 // U+015C Ŝ +fontcharu 349 191 925 37 51 // U+015D ŝ +fontcharu 350 229 925 37 55 // U+015E Ş +fontcharu 351 267 925 37 55 // U+015F ş +fontcharu 352 305 925 37 51 // U+0160 Š +fontcharu 353 343 925 37 51 // U+0161 š +fontcharu 354 381 925 37 55 // U+0162 Ţ +fontcharu 355 419 925 37 55 // U+0163 ţ +fontcharu 356 457 925 37 51 // U+0164 Ť +fontcharu 357 495 925 37 51 // U+0165 ť +fontcharu 358 533 925 37 51 // U+0166 Ŧ +fontcharu 359 571 925 37 51 // U+0167 ŧ +fontcharu 360 609 925 37 51 // U+0168 Ũ +fontcharu 361 647 925 37 51 // U+0169 ũ +fontcharu 362 685 925 37 51 // U+016A Ū +fontcharu 363 723 925 37 51 // U+016B ū +fontcharu 364 761 925 37 51 // U+016C Ŭ +fontcharu 365 799 925 37 51 // U+016D ŭ +fontcharu 366 837 925 37 51 // U+016E Ů +fontcharu 367 875 925 37 51 // U+016F ů +fontcharu 368 913 925 37 51 // U+0170 Ű +fontcharu 369 951 925 37 51 // U+0171 ű +fontcharu 370 1 984 37 55 // U+0172 Ų +fontcharu 371 39 984 37 55 // U+0173 ų +fontcharu 372 77 984 37 51 // U+0174 Ŵ +fontcharu 373 115 984 37 51 // U+0175 ŵ +fontcharu 374 153 984 37 51 // U+0176 Ŷ +fontcharu 375 191 984 37 55 // U+0177 ŷ +fontcharu 376 229 984 37 51 // U+0178 Ÿ +fontcharu 377 267 984 37 51 // U+0179 Ź +fontcharu 378 305 984 37 51 // U+017A ź +fontcharu 379 343 984 37 51 // U+017B Ż +fontcharu 380 381 984 37 51 // U+017C ż +fontcharu 381 419 984 37 51 // U+017D Ž +fontcharu 382 457 984 37 51 // U+017E ž +fontcharu 383 495 984 37 51 // U+017F ſ +fontcharu 902 533 984 37 51 // U+0386 Ά +fontcharu 904 571 984 37 51 // U+0388 Έ +fontcharu 905 609 984 37 51 // U+0389 Ή +fontcharu 906 647 984 37 51 // U+038A Ί +fontcharu 908 685 984 37 51 // U+038C Ό +fontcharu 910 723 984 37 51 // U+038E Ύ +fontcharu 911 761 984 37 51 // U+038F Ώ +fontcharu 912 799 984 37 51 // U+0390 ΐ +fontcharu 913 837 984 37 51 // U+0391 Α +fontcharu 914 875 984 37 51 // U+0392 Β +fontcharu 915 913 984 37 51 // U+0393 Γ +fontcharu 916 951 984 37 51 // U+0394 Δ +fontcharu 917 1 1043 37 51 // U+0395 Ε +fontcharu 918 39 1043 37 51 // U+0396 Ζ +fontcharu 919 77 1043 37 51 // U+0397 Η +fontcharu 920 115 1043 37 51 // U+0398 Θ +fontcharu 921 153 1043 37 51 // U+0399 Ι +fontcharu 922 191 1043 37 51 // U+039A Κ +fontcharu 923 229 1043 37 51 // U+039B Λ +fontcharu 924 267 1043 37 51 // U+039C Μ +fontcharu 925 305 1043 37 51 // U+039D Ν +fontcharu 926 343 1043 37 51 // U+039E Ξ +fontcharu 927 381 1043 37 51 // U+039F Ο +fontcharu 928 419 1043 37 51 // U+03A0 Π +fontcharu 929 457 1043 37 51 // U+03A1 Ρ +fontcharu 931 495 1043 37 51 // U+03A3 Σ +fontcharu 932 533 1043 37 51 // U+03A4 Τ +fontcharu 933 571 1043 37 51 // U+03A5 Υ +fontcharu 934 609 1043 37 51 // U+03A6 Φ +fontcharu 935 647 1043 37 51 // U+03A7 Χ +fontcharu 936 685 1043 37 51 // U+03A8 Ψ +fontcharu 937 723 1043 37 51 // U+03A9 Ω +fontcharu 938 761 1043 37 51 // U+03AA Ϊ +fontcharu 939 799 1043 37 51 // U+03AB Ϋ +fontcharu 940 837 1043 37 51 // U+03AC ά +fontcharu 941 875 1043 37 51 // U+03AD έ +fontcharu 942 913 1043 37 55 // U+03AE ή +fontcharu 943 951 1043 37 51 // U+03AF ί +fontcharu 944 1 1102 37 51 // U+03B0 ΰ +fontcharu 945 39 1102 37 51 // U+03B1 α +fontcharu 946 77 1102 37 55 // U+03B2 β +fontcharu 947 115 1102 37 55 // U+03B3 γ +fontcharu 948 153 1102 37 51 // U+03B4 δ +fontcharu 949 191 1102 37 51 // U+03B5 ε +fontcharu 950 229 1102 37 55 // U+03B6 ζ +fontcharu 951 267 1102 37 55 // U+03B7 η +fontcharu 952 305 1102 37 51 // U+03B8 θ +fontcharu 953 343 1102 37 51 // U+03B9 ι +fontcharu 954 381 1102 37 51 // U+03BA κ +fontcharu 955 419 1102 37 51 // U+03BB λ +fontcharu 956 457 1102 37 55 // U+03BC μ +fontcharu 957 495 1102 37 51 // U+03BD ν +fontcharu 958 533 1102 37 55 // U+03BE ξ +fontcharu 959 571 1102 37 51 // U+03BF ο +fontcharu 960 609 1102 37 51 // U+03C0 π +fontcharu 961 647 1102 37 55 // U+03C1 ρ +fontcharu 962 685 1102 37 55 // U+03C2 ς +fontcharu 963 723 1102 37 51 // U+03C3 σ +fontcharu 964 761 1102 37 51 // U+03C4 τ +fontcharu 965 799 1102 37 51 // U+03C5 υ +fontcharu 966 837 1102 37 55 // U+03C6 φ +fontcharu 967 875 1102 37 55 // U+03C7 χ +fontcharu 968 913 1102 37 55 // U+03C8 ψ +fontcharu 969 951 1102 37 51 // U+03C9 ω +fontcharu 970 1 1161 37 51 // U+03CA ϊ +fontcharu 971 39 1161 37 51 // U+03CB ϋ +fontcharu 972 77 1161 37 51 // U+03CC ό +fontcharu 973 115 1161 37 51 // U+03CD ύ +fontcharu 974 153 1161 37 51 // U+03CE ώ +fontcharu 1024 191 1161 37 51 // U+0400 Ѐ +fontcharu 1025 229 1161 37 51 // U+0401 Ё +fontcharu 1026 267 1161 37 55 // U+0402 Ђ +fontcharu 1027 305 1161 37 51 // U+0403 Ѓ +fontcharu 1028 343 1161 37 51 // U+0404 Є +fontcharu 1029 381 1161 37 51 // U+0405 Ѕ +fontcharu 1030 419 1161 37 51 // U+0406 І +fontcharu 1031 457 1161 37 51 // U+0407 Ї +fontcharu 1032 495 1161 37 51 // U+0408 Ј +fontcharu 1033 533 1161 37 51 // U+0409 Љ +fontcharu 1034 571 1161 37 51 // U+040A Њ +fontcharu 1035 609 1161 37 51 // U+040B Ћ +fontcharu 1036 647 1161 37 51 // U+040C Ќ +fontcharu 1037 685 1161 37 51 // U+040D Ѝ +fontcharu 1038 723 1161 37 51 // U+040E Ў +fontcharu 1039 761 1161 37 55 // U+040F Џ +fontcharu 1040 799 1161 37 51 // U+0410 А +fontcharu 1041 837 1161 37 51 // U+0411 Б +fontcharu 1042 875 1161 37 51 // U+0412 В +fontcharu 1043 913 1161 37 51 // U+0413 Г +fontcharu 1044 951 1161 37 54 // U+0414 Д +fontcharu 1045 1 1220 37 51 // U+0415 Е +fontcharu 1046 39 1220 37 51 // U+0416 Ж +fontcharu 1047 77 1220 37 51 // U+0417 З +fontcharu 1048 115 1220 37 51 // U+0418 И +fontcharu 1049 153 1220 37 51 // U+0419 Й +fontcharu 1050 191 1220 37 51 // U+041A К +fontcharu 1051 229 1220 37 51 // U+041B Л +fontcharu 1052 267 1220 37 51 // U+041C М +fontcharu 1053 305 1220 37 51 // U+041D Н +fontcharu 1054 343 1220 37 51 // U+041E О +fontcharu 1055 381 1220 37 51 // U+041F П +fontcharu 1056 419 1220 37 51 // U+0420 Р +fontcharu 1057 457 1220 37 51 // U+0421 С +fontcharu 1058 495 1220 37 51 // U+0422 Т +fontcharu 1059 533 1220 37 51 // U+0423 У +fontcharu 1060 571 1220 37 51 // U+0424 Ф +fontcharu 1061 609 1220 37 51 // U+0425 Х +fontcharu 1062 647 1220 37 54 // U+0426 Ц +fontcharu 1063 685 1220 37 51 // U+0427 Ч +fontcharu 1064 723 1220 37 51 // U+0428 Ш +fontcharu 1065 761 1220 37 54 // U+0429 Щ +fontcharu 1066 799 1220 37 51 // U+042A Ъ +fontcharu 1067 837 1220 37 51 // U+042B Ы +fontcharu 1068 875 1220 37 51 // U+042C Ь +fontcharu 1069 913 1220 37 51 // U+042D Э +fontcharu 1070 951 1220 37 51 // U+042E Ю +fontcharu 1071 1 1279 37 51 // U+042F Я +fontcharu 1072 39 1279 37 51 // U+0430 а +fontcharu 1073 77 1279 37 51 // U+0431 б +fontcharu 1074 115 1279 37 51 // U+0432 в +fontcharu 1075 153 1279 37 51 // U+0433 г +fontcharu 1076 191 1279 37 53 // U+0434 д +fontcharu 1077 229 1279 37 51 // U+0435 е +fontcharu 1078 267 1279 37 51 // U+0436 ж +fontcharu 1079 305 1279 37 51 // U+0437 з +fontcharu 1080 343 1279 37 51 // U+0438 и +fontcharu 1081 381 1279 37 51 // U+0439 й +fontcharu 1082 419 1279 37 51 // U+043A к +fontcharu 1083 457 1279 37 51 // U+043B л +fontcharu 1084 495 1279 37 51 // U+043C м +fontcharu 1085 533 1279 37 51 // U+043D н +fontcharu 1086 571 1279 37 51 // U+043E о +fontcharu 1087 609 1279 37 51 // U+043F п +fontcharu 1088 647 1279 37 55 // U+0440 р +fontcharu 1089 685 1279 37 51 // U+0441 с +fontcharu 1090 723 1279 37 51 // U+0442 т +fontcharu 1091 761 1279 37 55 // U+0443 у +fontcharu 1092 799 1279 37 55 // U+0444 ф +fontcharu 1093 837 1279 37 51 // U+0445 х +fontcharu 1094 875 1279 37 53 // U+0446 ц +fontcharu 1095 913 1279 37 51 // U+0447 ч +fontcharu 1096 951 1279 37 51 // U+0448 ш +fontcharu 1097 1 1338 37 53 // U+0449 щ +fontcharu 1098 39 1338 37 51 // U+044A ъ +fontcharu 1099 77 1338 37 51 // U+044B ы +fontcharu 1100 115 1338 37 51 // U+044C ь +fontcharu 1101 153 1338 37 51 // U+044D э +fontcharu 1102 191 1338 37 51 // U+044E ю +fontcharu 1103 229 1338 37 51 // U+044F я +fontcharu 1104 267 1338 37 51 // U+0450 ѐ +fontcharu 1105 305 1338 37 51 // U+0451 ё +fontcharu 1106 343 1338 37 55 // U+0452 ђ +fontcharu 1107 381 1338 37 51 // U+0453 ѓ +fontcharu 1108 419 1338 37 51 // U+0454 є +fontcharu 1109 457 1338 37 51 // U+0455 ѕ +fontcharu 1110 495 1338 37 51 // U+0456 і +fontcharu 1111 533 1338 37 51 // U+0457 ї +fontcharu 1112 571 1338 37 55 // U+0458 ј +fontcharu 1113 609 1338 37 51 // U+0459 љ +fontcharu 1114 647 1338 37 51 // U+045A њ +fontcharu 1115 685 1338 37 51 // U+045B ћ +fontcharu 1116 723 1338 37 51 // U+045C ќ +fontcharu 1117 761 1338 37 51 // U+045D ѝ +fontcharu 1118 799 1338 37 55 // U+045E ў +fontcharu 1119 837 1338 37 54 // U+045F џ +fontcharu 1168 875 1338 37 51 // U+0490 Ґ +fontcharu 1169 913 1338 37 51 // U+0491 ґ +fontcharu 8211 951 1338 37 51 // U+2013 – +fontcharu 8212 1 1397 37 51 // U+2014 — +fontcharu 8216 39 1397 37 51 // U+2018 ‘ +fontcharu 8217 77 1397 37 51 // U+2019 ’ +fontcharu 8218 115 1397 37 53 // U+201A ‚ +fontcharu 8220 153 1397 37 51 // U+201C “ +fontcharu 8221 191 1397 37 51 // U+201D ” +fontcharu 8222 229 1397 37 53 // U+201E „ +fontcharu 8226 267 1397 37 51 // U+2022 • +fontcharu 8230 305 1397 37 51 // U+2026 … +fontcharu 8364 343 1397 37 51 // U+20AC € +fontcharu 8470 381 1397 37 51 // U+2116 № + +fontselect serif +fontcharu 161 1 669 16 64 // U+00A1 ¡ +fontcharu 162 18 669 38 64 // U+00A2 ¢ +fontcharu 163 57 669 40 64 // U+00A3 £ +fontcharu 164 98 669 41 64 // U+00A4 ¤ +fontcharu 165 140 669 46 64 // U+00A5 ¥ +fontcharu 166 187 669 11 64 // U+00A6 ¦ +fontcharu 167 199 669 34 64 // U+00A7 § +fontcharu 168 234 669 27 64 // U+00A8 ¨ +fontcharu 169 262 669 52 64 // U+00A9 © +fontcharu 170 315 669 33 64 // U+00AA ª +fontcharu 171 349 669 34 64 // U+00AB « +fontcharu 172 384 669 45 64 // U+00AC ¬ +fontcharu 174 430 669 52 64 // U+00AE ® +fontcharu 175 483 669 24 64 // U+00AF ¯ +fontcharu 176 508 669 26 64 // U+00B0 ° +fontcharu 177 535 669 45 64 // U+00B1 ± +fontcharu 178 581 669 27 64 // U+00B2 ² +fontcharu 179 609 669 28 64 // U+00B3 ³ +fontcharu 180 638 669 21 64 // U+00B4 ´ +fontcharu 181 660 669 48 64 // U+00B5 µ +fontcharu 182 709 669 37 64 // U+00B6 ¶ +fontcharu 183 747 669 17 64 // U+00B7 · +fontcharu 184 765 669 19 64 // U+00B8 ¸ +fontcharu 185 785 669 24 64 // U+00B9 ¹ +fontcharu 186 810 669 34 64 // U+00BA º +fontcharu 187 845 669 34 64 // U+00BB » +fontcharu 188 880 669 65 64 // U+00BC ¼ +fontcharu 189 946 669 64 64 // U+00BD ½ +fontcharu 190 1 741 67 64 // U+00BE ¾ +fontcharu 191 69 741 36 64 // U+00BF ¿ +fontcharu 192 106 741 46 64 // U+00C0 À +fontcharu 193 153 741 46 64 // U+00C1 Á +fontcharu 194 200 741 46 64 // U+00C2  +fontcharu 195 247 741 46 64 // U+00C3 à +fontcharu 196 294 741 46 64 // U+00C4 Ä +fontcharu 197 341 741 47 64 // U+00C5 Å +fontcharu 198 389 741 69 64 // U+00C6 Æ +fontcharu 199 459 741 50 64 // U+00C7 Ç +fontcharu 200 510 741 39 64 // U+00C8 È +fontcharu 201 550 741 39 64 // U+00C9 É +fontcharu 202 590 741 39 64 // U+00CA Ê +fontcharu 203 630 741 39 64 // U+00CB Ë +fontcharu 204 670 741 24 64 // U+00CC Ì +fontcharu 205 695 741 24 64 // U+00CD Í +fontcharu 206 720 741 24 64 // U+00CE Î +fontcharu 207 745 741 24 64 // U+00CF Ï +fontcharu 208 770 741 56 64 // U+00D0 Ð +fontcharu 209 827 741 48 64 // U+00D1 Ñ +fontcharu 210 876 741 46 64 // U+00D2 Ò +fontcharu 211 923 741 46 64 // U+00D3 Ó +fontcharu 212 970 741 46 64 // U+00D4 Ô +fontcharu 213 1 813 46 64 // U+00D5 Õ +fontcharu 214 48 813 46 64 // U+00D6 Ö +fontcharu 215 95 813 42 64 // U+00D7 × +fontcharu 216 138 813 54 64 // U+00D8 Ø +fontcharu 217 193 813 48 64 // U+00D9 Ù +fontcharu 218 242 813 48 64 // U+00DA Ú +fontcharu 219 291 813 48 64 // U+00DB Û +fontcharu 220 340 813 48 64 // U+00DC Ü +fontcharu 221 389 813 43 64 // U+00DD Ý +fontcharu 222 433 813 48 64 // U+00DE Þ +fontcharu 223 482 813 49 64 // U+00DF ß +fontcharu 224 532 813 41 64 // U+00E0 à +fontcharu 225 574 813 41 64 // U+00E1 á +fontcharu 226 616 813 41 64 // U+00E2 â +fontcharu 227 658 813 41 64 // U+00E3 ã +fontcharu 228 700 813 41 64 // U+00E4 ä +fontcharu 229 742 813 37 64 // U+00E5 å +fontcharu 230 780 813 62 64 // U+00E6 æ +fontcharu 231 843 813 38 64 // U+00E7 ç +fontcharu 232 882 813 38 64 // U+00E8 è +fontcharu 233 921 813 38 64 // U+00E9 é +fontcharu 234 960 813 38 64 // U+00EA ê +fontcharu 235 1 885 39 64 // U+00EB ë +fontcharu 236 41 885 26 64 // U+00EC ì +fontcharu 237 68 885 25 64 // U+00ED í +fontcharu 238 94 885 27 64 // U+00EE î +fontcharu 239 122 885 27 64 // U+00EF ï +fontcharu 240 150 885 41 64 // U+00F0 ð +fontcharu 241 192 885 45 64 // U+00F1 ñ +fontcharu 242 238 885 41 64 // U+00F2 ò +fontcharu 243 280 885 41 64 // U+00F3 ó +fontcharu 244 322 885 41 64 // U+00F4 ô +fontcharu 245 364 885 41 64 // U+00F5 õ +fontcharu 246 406 885 41 64 // U+00F6 ö +fontcharu 247 448 885 45 64 // U+00F7 ÷ +fontcharu 248 494 885 44 64 // U+00F8 ø +fontcharu 249 539 885 46 64 // U+00F9 ù +fontcharu 250 586 885 46 64 // U+00FA ú +fontcharu 251 633 885 46 64 // U+00FB û +fontcharu 252 680 885 46 64 // U+00FC ü +fontcharu 253 727 885 42 65 // U+00FD ý +fontcharu 254 770 885 46 64 // U+00FE þ +fontcharu 255 817 885 43 65 // U+00FF ÿ +fontcharu 1024 861 885 39 64 // U+0400 Ѐ +fontcharu 1025 901 885 39 64 // U+0401 Ё +fontcharu 1026 941 885 60 65 // U+0402 Ђ +fontcharu 1027 1 957 38 64 // U+0403 Ѓ +fontcharu 1028 40 957 50 64 // U+0404 Є +fontcharu 1029 91 957 43 64 // U+0405 Ѕ +fontcharu 1030 135 957 28 64 // U+0406 І +fontcharu 1031 164 957 24 64 // U+0407 Ї +fontcharu 1032 189 957 37 64 // U+0408 Ј +fontcharu 1033 227 957 77 64 // U+0409 Љ +fontcharu 1034 305 957 79 64 // U+040A Њ +fontcharu 1035 385 957 66 64 // U+040B Ћ +fontcharu 1036 452 957 49 64 // U+040C Ќ +fontcharu 1037 502 957 49 64 // U+040D Ѝ +fontcharu 1038 552 957 43 64 // U+040E Ў +fontcharu 1039 596 957 59 64 // U+040F Џ +fontcharu 1040 656 957 56 64 // U+0410 А +fontcharu 1041 713 957 53 64 // U+0411 Б +fontcharu 1042 767 957 52 64 // U+0412 В +fontcharu 1043 820 957 45 64 // U+0413 Г +fontcharu 1044 866 957 55 64 // U+0414 Д +fontcharu 1045 922 957 47 64 // U+0415 Е +fontcharu 1046 1 1029 88 64 // U+0416 Ж +fontcharu 1047 90 1029 44 64 // U+0417 З +fontcharu 1048 135 1029 59 64 // U+0418 И +fontcharu 1049 195 1029 47 64 // U+0419 Й +fontcharu 1050 243 1029 59 64 // U+041A К +fontcharu 1051 303 1029 57 64 // U+041B Л +fontcharu 1052 361 1029 70 64 // U+041C М +fontcharu 1053 432 1029 59 64 // U+041D Н +fontcharu 1054 492 1029 55 64 // U+041E О +fontcharu 1055 548 1029 59 64 // U+041F П +fontcharu 1056 608 1029 48 64 // U+0420 Р +fontcharu 1057 657 1029 50 64 // U+0421 С +fontcharu 1058 708 1029 51 64 // U+0422 Т +fontcharu 1059 760 1029 55 64 // U+0423 У +fontcharu 1060 816 1029 60 64 // U+0424 Ф +fontcharu 1061 877 1029 54 64 // U+0425 Х +fontcharu 1062 932 1029 60 64 // U+0426 Ц +fontcharu 1063 1 1101 58 64 // U+0427 Ч +fontcharu 1064 60 1101 81 64 // U+0428 Ш +fontcharu 1065 142 1101 82 64 // U+0429 Щ +fontcharu 1066 225 1101 63 64 // U+042A Ъ +fontcharu 1067 289 1101 75 64 // U+042B Ы +fontcharu 1068 365 1101 51 64 // U+042C Ь +fontcharu 1069 417 1101 50 64 // U+042D Э +fontcharu 1070 468 1101 80 64 // U+042E Ю +fontcharu 1071 549 1101 57 64 // U+042F Я +fontcharu 1072 607 1101 42 64 // U+0430 а +fontcharu 1073 650 1101 41 64 // U+0431 б +fontcharu 1074 692 1101 44 64 // U+0432 в +fontcharu 1075 737 1101 38 64 // U+0433 г +fontcharu 1076 776 1101 43 64 // U+0434 д +fontcharu 1077 820 1101 40 64 // U+0435 е +fontcharu 1078 861 1101 68 64 // U+0436 ж +fontcharu 1079 930 1101 41 64 // U+0437 з +fontcharu 1080 972 1101 48 64 // U+0438 и +fontcharu 1081 1 1173 44 64 // U+0439 й +fontcharu 1082 46 1173 48 64 // U+043A к +fontcharu 1083 95 1173 46 64 // U+043B л +fontcharu 1084 142 1173 56 64 // U+043C м +fontcharu 1085 199 1173 47 64 // U+043D н +fontcharu 1086 247 1173 43 64 // U+043E о +fontcharu 1087 291 1173 47 64 // U+043F п +fontcharu 1088 339 1173 46 64 // U+0440 р +fontcharu 1089 386 1173 38 64 // U+0441 с +fontcharu 1090 425 1173 39 64 // U+0442 т +fontcharu 1091 465 1173 45 65 // U+0443 у +fontcharu 1092 511 1173 58 65 // U+0444 ф +fontcharu 1093 570 1173 43 64 // U+0445 х +fontcharu 1094 614 1173 48 64 // U+0446 ц +fontcharu 1095 663 1173 47 64 // U+0447 ч +fontcharu 1096 711 1173 69 64 // U+0448 ш +fontcharu 1097 781 1173 70 64 // U+0449 щ +fontcharu 1098 852 1173 51 64 // U+044A ъ +fontcharu 1099 904 1173 64 64 // U+044B ы +fontcharu 1100 969 1173 43 64 // U+044C ь +fontcharu 1101 1 1245 39 64 // U+044D э +fontcharu 1102 41 1245 64 64 // U+044E ю +fontcharu 1103 106 1245 49 64 // U+044F я +fontcharu 1104 156 1245 38 64 // U+0450 ѐ +fontcharu 1105 195 1245 39 64 // U+0451 ё +fontcharu 1106 235 1245 48 66 // U+0452 ђ +fontcharu 1107 284 1245 36 64 // U+0453 ѓ +fontcharu 1108 321 1245 38 64 // U+0454 є +fontcharu 1109 360 1245 36 64 // U+0455 ѕ +fontcharu 1110 397 1245 25 64 // U+0456 і +fontcharu 1111 423 1245 27 64 // U+0457 ї +fontcharu 1112 451 1245 27 65 // U+0458 ј +fontcharu 1113 479 1245 64 64 // U+0459 љ +fontcharu 1114 544 1245 65 64 // U+045A њ +fontcharu 1115 610 1245 49 64 // U+045B ћ +fontcharu 1116 660 1245 46 64 // U+045C ќ +fontcharu 1117 707 1245 46 64 // U+045D ѝ +fontcharu 1118 754 1245 42 64 // U+045E ў +fontcharu 1119 797 1245 47 64 // U+045F џ +fontcharu 1168 845 1245 41 64 // U+0490 Ґ +fontcharu 1169 887 1245 38 64 // U+0491 ґ +fontcharu 8211 926 1245 30 64 // U+2013 – +fontcharu 8212 957 1245 62 64 // U+2014 — +fontcharu 8216 1 1317 19 64 // U+2018 ‘ +fontcharu 8217 21 1317 19 64 // U+2019 ’ +fontcharu 8218 41 1317 18 64 // U+201A ‚ +fontcharu 8220 60 1317 33 64 // U+201C “ +fontcharu 8221 94 1317 33 64 // U+201D ” +fontcharu 8222 128 1317 33 64 // U+201E „ +fontcharu 8226 162 1317 27 64 // U+2022 • +fontcharu 8230 190 1317 58 64 // U+2026 … +fontcharu 8364 249 1317 47 64 // U+20AC € +fontcharu 8470 297 1317 69 64 // U+2116 № diff --git a/config/menus_multiplayer.cfg b/config/menus_multiplayer.cfg index b05b0def..04cfc0c9 100644 --- a/config/menus_multiplayer.cfg +++ b/config/menus_multiplayer.cfg @@ -170,8 +170,12 @@ menuitemslider "Recoil Multiplier: " 50 500 "$matchrecoilmul" 10 [ matchrecoilmu menuitemslider "Spread Multiplier: " 50 500 "$matchspreadmul" 10 [ matchspreadmul $arg1 ] menuitemslider "Speed Multiplier: " 50 500 "$matchspeedmul" 10 [ matchspeedmul $arg1 ] menuitemslider "Gravity Multiplier: " 50 500 "$matchgravity" 10 [ matchgravity $arg1 ] +menuitemslider "Friction Multiplier: " 10 500 "$matchfriction" 10 [ matchfriction $arg1 ] menuitem "" -1 menuitemcheckbox "Enable Assists: " "$matchassist" [ matchassist $arg1 ] +menuitemcheckbox "Explosive Deaths: " "$matchdeathexplosion" [ matchdeathexplosion $arg1 ] +menuitemslider " Blast Radius %: " 10 300 "$matchdeathradius" 10 [ matchdeathradius $arg1 ] +menuitemslider " Blast Power %: " 10 500 "$matchdeathpower" 10 [ matchdeathpower $arg1 ] menuitem "" -1 menuitem "Friendly Fire\i\3" [ showmenu [Match Friendly Fire] ] menuitem "" -1 @@ -179,7 +183,7 @@ menuitem "Spawn Weapons\i\3" [ showmenu [Match Spawn Weapons] ] menuitem "" -1 menuitem "\f2Start Bot Match" [ startbotmap ] menuitem "" -1 -menuitem "Reset to defaults (100%)" [ matchrecoilmul 100; matchspreadmul 100; matchspeedmul 100; matchgravity 100; matchassist 1; matchfriendlyfire 1; matchspawnprimary 6; matchspawnsecondary 1; matchspawntertiary 0; matchspawnquaternary -1 ] +menuitem "Reset to defaults (100%)" [ matchrecoilmul 100; matchspreadmul 100; matchspeedmul 100; matchgravity 100; matchfriction 100; matchdeathradius 100; matchdeathpower 100; matchassist 1; matchfriendlyfire 1; matchdeathexplosion 0; matchspawnprimary -1; matchspawnsecondary -1; matchspawntertiary -1; matchspawnquaternary -1; showmenu [Match Settings] ] menuitem "Back" [ showmenu Mastermode ] //// In-Game admin > Match Settings > Friendly Fire //// @@ -196,7 +200,7 @@ menuitem "Back" [ showmenu [Match Settings] ] newmenu [Match Spawn Weapons] menuinit [ ] -menutitle "Select weapons to spawn with (order = priority)" +menutitle "Spawn weapons (primary = what you hold, others = extra guns)" menuitem "Primary Weapon\i\3" [ showmenu [Match Spawn Primary] ] menuitem "Secondary Weapon\i\3" [ showmenu [Match Spawn Secondary] ] menuitem "Tertiary Weapon\i\3" [ showmenu [Match Spawn Tertiary] ] @@ -208,6 +212,7 @@ menuitem "Back" [ showmenu [Match Settings] ] newmenu [Match Spawn Primary] menuinit [ ] +menuitem "Default (your own choice)" [ matchspawnprimary -1; showmenu [Match Spawn Weapons] ] menuitem "Knife" [ matchspawnprimary 0; showmenu [Match Spawn Weapons] ] menuitem "Pistol" [ matchspawnprimary 1; showmenu [Match Spawn Weapons] ] menuitem "Carbine" [ matchspawnprimary 2; showmenu [Match Spawn Weapons] ] @@ -216,7 +221,6 @@ menuitem "Subgun" [ matchspawnprimary 4; showmenu [Match Spawn Weapons] ] menuitem "Sniper" [ matchspawnprimary 5; showmenu [Match Spawn Weapons] ] menuitem "Assault" [ matchspawnprimary 6; showmenu [Match Spawn Weapons] ] menuitem "Grenade" [ matchspawnprimary 7; showmenu [Match Spawn Weapons] ] -menuitem "Akimbo" [ matchspawnprimary 8; showmenu [Match Spawn Weapons] ] menuitem "" -1 menuitem "Back" [ showmenu [Match Spawn Weapons] ] @@ -224,6 +228,7 @@ menuitem "Back" [ showmenu [Match Spawn Weapons] ] newmenu [Match Spawn Secondary] menuinit [ ] +menuitem "None" [ matchspawnsecondary -1; showmenu [Match Spawn Weapons] ] menuitem "Knife" [ matchspawnsecondary 0; showmenu [Match Spawn Weapons] ] menuitem "Pistol" [ matchspawnsecondary 1; showmenu [Match Spawn Weapons] ] menuitem "Carbine" [ matchspawnsecondary 2; showmenu [Match Spawn Weapons] ] @@ -232,7 +237,6 @@ menuitem "Subgun" [ matchspawnsecondary 4; showmenu [Match Spawn Weapons] menuitem "Sniper" [ matchspawnsecondary 5; showmenu [Match Spawn Weapons] ] menuitem "Assault" [ matchspawnsecondary 6; showmenu [Match Spawn Weapons] ] menuitem "Grenade" [ matchspawnsecondary 7; showmenu [Match Spawn Weapons] ] -menuitem "Akimbo" [ matchspawnsecondary 8; showmenu [Match Spawn Weapons] ] menuitem "" -1 menuitem "Back" [ showmenu [Match Spawn Weapons] ] @@ -240,6 +244,7 @@ menuitem "Back" [ showmenu [Match Spawn Weapons] ] newmenu [Match Spawn Tertiary] menuinit [ ] +menuitem "None" [ matchspawntertiary -1; showmenu [Match Spawn Weapons] ] menuitem "Knife" [ matchspawntertiary 0; showmenu [Match Spawn Weapons] ] menuitem "Pistol" [ matchspawntertiary 1; showmenu [Match Spawn Weapons] ] menuitem "Carbine" [ matchspawntertiary 2; showmenu [Match Spawn Weapons] ] @@ -248,7 +253,6 @@ menuitem "Subgun" [ matchspawntertiary 4; showmenu [Match Spawn Weapons] menuitem "Sniper" [ matchspawntertiary 5; showmenu [Match Spawn Weapons] ] menuitem "Assault" [ matchspawntertiary 6; showmenu [Match Spawn Weapons] ] menuitem "Grenade" [ matchspawntertiary 7; showmenu [Match Spawn Weapons] ] -menuitem "Akimbo" [ matchspawntertiary 8; showmenu [Match Spawn Weapons] ] menuitem "" -1 menuitem "Back" [ showmenu [Match Spawn Weapons] ] @@ -256,6 +260,7 @@ menuitem "Back" [ showmenu [Match Spawn Weapons] ] newmenu [Match Spawn Quaternary] menuinit [ ] +menuitem "None" [ matchspawnquaternary -1; showmenu [Match Spawn Weapons] ] menuitem "Knife" [ matchspawnquaternary 0; showmenu [Match Spawn Weapons] ] menuitem "Pistol" [ matchspawnquaternary 1; showmenu [Match Spawn Weapons] ] menuitem "Carbine" [ matchspawnquaternary 2; showmenu [Match Spawn Weapons] ] @@ -264,8 +269,6 @@ menuitem "Subgun" [ matchspawnquaternary 4; showmenu [Match Spawn Weapons menuitem "Sniper" [ matchspawnquaternary 5; showmenu [Match Spawn Weapons] ] menuitem "Assault" [ matchspawnquaternary 6; showmenu [Match Spawn Weapons] ] menuitem "Grenade" [ matchspawnquaternary 7; showmenu [Match Spawn Weapons] ] -menuitem "Akimbo" [ matchspawnquaternary 8; showmenu [Match Spawn Weapons] ] -menuitem "None" [ matchspawnquaternary -1; showmenu [Match Spawn Weapons] ] menuitem "" -1 menuitem "Back" [ showmenu [Match Spawn Weapons] ] diff --git a/packages/misc/chars_default.png b/packages/misc/chars_default.png index ae5a0cc3..33d00c0a 100644 Binary files a/packages/misc/chars_default.png and b/packages/misc/chars_default.png differ diff --git a/packages/misc/chars_monospace.png b/packages/misc/chars_monospace.png index d8250068..1001d21f 100644 Binary files a/packages/misc/chars_monospace.png and b/packages/misc/chars_monospace.png differ diff --git a/packages/misc/chars_serif.png b/packages/misc/chars_serif.png index 8e9f030e..377929be 100644 Binary files a/packages/misc/chars_serif.png and b/packages/misc/chars_serif.png differ diff --git a/source/dev_tools/gen_unicode_fonts.py b/source/dev_tools/gen_unicode_fonts.py new file mode 100644 index 00000000..86acb751 --- /dev/null +++ b/source/dev_tools/gen_unicode_fonts.py @@ -0,0 +1,157 @@ +#!/usr/bin/env python3 +""" +Appends extra glyphs (Latin-1, Latin Extended-A, Greek, Cyrillic, some punctuation) to the three built-in +AssaultCube font atlases and writes config/font_unicode.cfg with the matching "fontcharu" definitions. + +Run from the AssaultCube root folder: + + python3 source/dev_tools/gen_unicode_fonts.py [--fonts-dir /usr/share/fonts/truetype/dejavu] + +Requires Pillow and the DejaVu fonts (any TTF with the needed coverage works, see FONTS below). +The ASCII part of every atlas is never touched: the script cuts each png back to its original size first, so +running it repeatedly is safe. The new glyphs are appended below the old ones; the image gets wider, which is fine +because all fontchar coordinates are pixel based. +""" +import argparse, math, os, re, sys +from PIL import Image, ImageDraw, ImageFont + +# glyph sets: (first, last) inclusive +RANGES = [ + (0x00A1, 0x00AC), (0x00AE, 0x00FF), # Latin-1 supplement (no NBSP, no soft hyphen) + (0x0100, 0x017F), # Latin Extended-A (Polish, Czech, Hungarian, Turkish, Baltic, ...) + (0x0386, 0x0386), (0x0388, 0x038A), (0x038C, 0x038C), (0x038E, 0x03A1), (0x03A3, 0x03CE), # Greek + (0x0400, 0x045F), (0x0490, 0x0491), # Cyrillic: Russian, Ukrainian, Belarusian, Serbian, Macedonian, ... + (0x2013, 0x2014), (0x2018, 0x201A), (0x201C, 0x201E), (0x2022, 0x2022), (0x2026, 0x2026), + (0x20AC, 0x20AC), (0x2116, 0x2116), # dashes, quotes, bullet, ellipsis, euro, numero +] + +# the serif atlas is the largest per glyph, so it gets a smaller set (keeps the texture at 1024x2048) +RANGES_SMALL = [(0x00A1, 0x00AC), (0x00AE, 0x00FF), (0x0400, 0x045F), (0x0490, 0x0491), + (0x2013, 0x2014), (0x2018, 0x201A), (0x201C, 0x201E), (0x2022, 0x2022), (0x2026, 0x2026), (0x20AC, 0x20AC), (0x2116, 0x2116)] + +FONTS = { + # name: (png, cfg, ttf, outline px, original png size) + 'default': dict(png='chars_default.png', cfg='font_default.cfg', ttf='DejaVuSans-Bold.ttf', stroke=4, orig=(512, 512)), + 'mono': dict(png='chars_monospace.png', cfg='font_monospace.cfg', ttf='DejaVuSansMono-Bold.ttf', stroke=0, orig=(512, 512)), + 'serif': dict(png='chars_serif.png', cfg='font_serif.cfg', ttf='DejaVuSerif-Bold.ttf', stroke=0, orig=(690, 690), ranges=RANGES_SMALL), +} +NEWW = 1024 # width of the extended atlases (power of two; old glyph pixel coordinates stay valid) + + +def parse_cfg(path): + hdr, chars = None, [] + for line in open(path, encoding='utf-8'): + line = line.split('//')[0].strip() + if line.startswith('font '): + t = line.replace('"', ' ').split() + nums = [int(v) for v in t[3:]] + nums += [0] * (7 - len(nums)) + hdr = dict(name=t[1], png=t[2], dw=nums[0], dh=nums[1], ox=nums[2], oy=nums[3], ow=nums[4], oh=nums[5]) + elif line.startswith('fontchar '): + v = [int(x) for x in line.split()[1:]] + v += [0] * (4 - len(v)) + chars.append(v) + return hdr, chars + + +def alpha_bbox(im, thr=100): + return im.getchannel('A').point(lambda v: 255 if v > thr else 0).getbbox() + + +def main(): + ap = argparse.ArgumentParser() + ap.add_argument('--fonts-dir', default='/usr/share/fonts/truetype/dejavu') + ap.add_argument('--root', default='.') + a = ap.parse_args() + out_cfg = ['// Extra glyphs for the built-in fonts: Latin-1, Latin Extended-A, Greek, Cyrillic, some punctuation.', + '// Generated by source/dev_tools/gen_unicode_fonts.py - do not edit by hand.', + '// "fontselect" makes an existing font the target of the following "fontcharu" commands (cp x y w h).', ''] + for fname, fc in FONTS.items(): + cfgp = os.path.join(a.root, 'config', fc['cfg']) + pngp = os.path.join(a.root, 'packages', 'misc', fc['png']) + hdr, chars = parse_cfg(cfgp) + cps = [c for lo, hi in fc.get('ranges', RANGES) for c in range(lo, hi + 1)] + atlas = Image.open(pngp) + mode = atlas.mode + atlas = atlas.crop((0, 0) + fc['orig']).convert('RGBA') # cut back to original -> idempotent + # reference glyph 'H' defines size and baseline + hx, hy, hw, hh = chars[ord('H') - 33] + hw = hw or hdr['dw']; hh = hh or hdr['dh'] + crop = atlas.crop((hx + hdr['ox'], hy + hdr['oy'], hx + hw + hdr['ow'], hy + hh + hdr['oh'])) + l, t, r, b = alpha_bbox(crop) + ref_h, ref_w = b - t, r - l + crop_base = crop.size[1] # crop height of a normal glyph + maxcrop = crop_base + 4 # glyphs with descenders may be a bit taller (like 'g' in the original) + pad_total = hw - ref_w + stroke = fc['stroke'] + ttf = os.path.join(a.fonts_dir, fc['ttf']) + # fit font size so that the rendered 'H' (incl. outline) has the reference height + def render(ch, size, origin=(150, 250)): + f = ImageFont.truetype(ttf, size) + im = Image.new('RGBA', (400, 400), (0, 0, 0, 0)) + d = ImageDraw.Draw(im) + d.text(origin, ch, font=f, fill=(255, 255, 255, 255), stroke_width=stroke, stroke_fill=(0, 0, 0, 255), anchor='ls') + return im, alpha_bbox(im, 8), origin + size = 20 + for s in range(20, 120): + _, bb, _ = render('H', s) + if bb and bb[3] - bb[1] >= ref_h: size = s; break + base_y = b - stroke # row of the baseline inside the crop + mono = hdr['dw'] and fname == 'mono' + print('%s: ref H ink %dx%d, crop %dx%d, ttf size %d, baseline row %d' % (fname, ref_w, ref_h, crop.size[0], crop_base, size, base_y)) + + glyphs = [] # (cp, image (cell crop), w, crop_h) + for cp in cps: + ch = chr(cp) + im, bb, org = render(ch, size) + if not bb: continue + ext_above, ext_below = org[1] - bb[1], bb[3] - org[1] + sc = 1.0 + if ext_above > base_y - 1: sc = min(sc, (base_y - 1) / ext_above) + if ext_below > maxcrop - base_y - 1: sc = min(sc, (maxcrop - base_y - 1) / ext_below) + if sc < 1.0: + im, bb, org = render(ch, max(8, int(size * sc))) + ext_above, ext_below = org[1] - bb[1], bb[3] - org[1] + ink = im.crop((bb[0], 0, bb[2], im.size[1])) + ink_w = bb[2] - bb[0] + cell_w = hdr['dw'] if mono else ink_w + pad_total + if mono and ink_w > cell_w: # keep monospace cells fixed width + k = (cell_w - 1) / ink_w + ink = ink.resize((cell_w - 1, ink.size[1])); ink_w = cell_w - 1 + crop_h = max(crop_base, min(maxcrop, base_y + ext_below + 1)) + cell = Image.new('RGBA', (cell_w, crop_h), (0, 0, 0, 0)) + px = (cell_w - ink_w) // 2 + py = base_y - org[1] # paste so that baseline lands on base_y + cell.alpha_composite(ink, (px, py)) if py >= 0 else cell.alpha_composite(ink.crop((0, -py, ink_w, ink.size[1])), (px, 0)) + glyphs.append((cp, cell, cell_w, crop_h)) + + # pack into rows below the original atlas + pitch = maxcrop + 4 + x, row, placed = 1, 0, [] + for cp, cell, w, ch_ in glyphs: + if x + w + 1 > NEWW: x, row = 1, row + 1 + placed.append((cp, cell, x, row, w, ch_)); x += w + 1 + top0 = fc['orig'][1] + if fname == 'serif': top0 = max(top0, 700) + need = top0 + (row + 1) * pitch + newh = 1 << max(8, math.ceil(math.log2(need))) + big = Image.new('RGBA', (NEWW, newh), (0, 0, 0, 0)) + big.paste(atlas, (0, 0)) + out_cfg += ['fontselect %s' % hdr['name']] + for cp, cell, cx, crow, w, ch_ in placed: + ry = top0 + crow * pitch + big.paste(cell, (cx, ry)) + cfg_y = ry - hdr['oy'] + cfg_h = ch_ - (hdr['oh'] - hdr['oy']) + out_cfg.append('fontcharu %d %d %d %d %d\t// U+%04X %s' % (cp, cx - hdr['ox'], cfg_y, w, cfg_h, cp, chr(cp))) + out_cfg.append('') + if mode == 'LA': + big = Image.merge('LA', (big.convert('L'), big.getchannel('A'))) + big.save(pngp, optimize=True) + print(' wrote %s %dx%d, %d glyphs' % (pngp, NEWW, newh, len(placed))) + open(os.path.join(a.root, 'config', 'font_unicode.cfg'), 'w', encoding='utf-8').write('\n'.join(out_cfg)) + print('wrote config/font_unicode.cfg') + + +if __name__ == '__main__': + main() diff --git a/source/src/clientgame.cpp b/source/src/clientgame.cpp index f0f9228b..5b3255c8 100644 --- a/source/src/clientgame.cpp +++ b/source/src/clientgame.cpp @@ -23,6 +23,7 @@ struct serverstate servstate = { 0 }; extern int matchassist; extern int matchfriendlyfire; +extern int matchdeathexplosion; playerent *player1 = newplayerent(); // our client vector players; // other clients @@ -1028,6 +1029,9 @@ void dokill(playerent *pl, playerent *act, bool gib, int gun) } } } + + // explosive deaths: online the server applies the blast (and sends SV_DEATHBLAST), offline/bot games do it here + if(matchdeathexplosion && !m_mp(gamemode) && !m_demo) localdeathblast(pl); } void pstat_weap(int *cn) diff --git a/source/src/clients2c.cpp b/source/src/clients2c.cpp index e12f3d9c..78325984 100644 --- a/source/src/clients2c.cpp +++ b/source/src/clients2c.cpp @@ -749,6 +749,14 @@ void parsemessages(int cn, playerent *d, ucharbuf &p, bool demo = false) break; } + case SV_DEATHBLAST: // "explosive deaths": the damage comes as normal SV_DAMAGE messages, this is just the visual/sound + { + int cn = getint(p); + playerent *d = getclient(cn); + if(d) deathblasteffect(d->o); + break; + } + case SV_RESUME: { loopi(MAXCLIENTS) diff --git a/source/src/console.h b/source/src/console.h index 02e9b41c..751ca3e9 100644 --- a/source/src/console.h +++ b/source/src/console.h @@ -70,8 +70,9 @@ struct textinputbuffer { int len = (int)strlen(buf); if(pos<0) break; - memmove(&buf[pos], &buf[pos+1], len - pos); - if(pos>=len-1) pos = -1; + int cl = utf8charlen(&buf[pos]); // a multibyte character is removed as a whole + memmove(&buf[pos], &buf[pos+cl], len - pos - cl + 1); + if(pos>=len-cl) pos = -1; return true; } @@ -79,19 +80,24 @@ struct textinputbuffer { int len = (int)strlen(buf), i = pos>=0 ? pos : len; if(i<1) break; - memmove(&buf[i-1], &buf[i], len - i + 1); - if(pos>0) pos--; + int p = utf8prev(buf, i); // start of the character before the cursor + memmove(&buf[p], &buf[i], len - i + 1); + if(pos>0) pos = p; else if(!pos && len<=1) pos = -1; return true; } case SDLK_LEFT: - if(pos > 0) pos--; - else if(pos < 0) pos = (int)strlen(buf)-1; + if(pos > 0) pos = utf8prev(buf, pos); + else if(pos < 0) { int len = (int)strlen(buf); pos = len > 0 ? utf8prev(buf, len) : -1; } break; case SDLK_RIGHT: - if(pos>=0 && ++pos>=(int)strlen(buf)) pos = -1; + if(pos>=0) + { + pos += utf8charlen(&buf[pos]); + if(pos>=(int)strlen(buf)) pos = -1; + } break; case SDLK_v: diff --git a/source/src/entity.h b/source/src/entity.h index 6b80c019..e14587c7 100644 --- a/source/src/entity.h +++ b/source/src/entity.h @@ -81,6 +81,11 @@ enum { GUN_KNIFE = 0, GUN_PISTOL, GUN_CARBINE, GUN_SHOTGUN, GUN_SUBGUN, GUN_SNIP #define SGMAXDMGABS 105 #define SGMAXDMGLOC 84 #define EXPDAMRAD 10 +// "explosive deaths" match option. Defaults: radius of a grenade, 75% of a grenade's damage at the centre. +// matchdeathradius / matchdeathpower are percentages of those defaults (server.cpp). +extern int matchdeathradius, matchdeathpower; +#define DEATHBLASTRAD (EXPDAMRAD*matchdeathradius/100.0f) +#define DEATHBLASTDMG (guns[GUN_GRENADE].damage*3/4*matchdeathpower/100) struct itemstat { int add, start, max, sound; }; extern itemstat ammostats[NUMGUNS]; @@ -333,11 +338,34 @@ public: ammo[GUN_KNIFE] = mag[GUN_KNIFE] = 1; } + // match settings (defined in server.cpp): -1 = not set, use the normal behaviour + #define matchgunok(g) (valid_weapon(g) && (g) != GUN_AKIMBO) // akimbo is a timed pickup, it can't be a spawn weapon + + // gives a gun with its normal starting load (used for the match spawn loadout) + void givegun(int gun) + { + if(!matchgunok(gun)) return; + switch(gun) + { + case GUN_KNIFE: ammo[GUN_KNIFE] = mag[GUN_KNIFE] = 1; break; + case GUN_GRENADE: ammo[GUN_GRENADE] = 0; mag[GUN_GRENADE] = max(mag[GUN_GRENADE], 2); break; + default: + ammo[gun] = max(ammo[gun], ammostats[gun].start-magsize(gun)); + mag[gun] = magsize(gun); + break; + } + } + virtual void spawnstate(int gamemode) { + extern int matchspawnprimary, matchspawnsecondary, matchspawntertiary, matchspawnquaternary; + const bool fixedloadout = m_pistol || m_osok || m_lss; // these modes dictate the weapons + const bool matchprimary = !fixedloadout && matchgunok(matchspawnprimary); + if(m_pistol) primary = GUN_PISTOL; else if(m_osok) primary = GUN_SNIPER; else if(m_lss) primary = GUN_KNIFE; + else if(matchprimary) primary = matchspawnprimary; else primary = nextprimary; if(!m_nopistol) @@ -348,8 +376,19 @@ public: if(!m_noprimary) { - ammo[primary] = ammostats[primary].start-magsize(primary); - mag[primary] = magsize(primary); + if(matchprimary) givegun(primary); + else + { + ammo[primary] = ammostats[primary].start-magsize(primary); + mag[primary] = magsize(primary); + } + } + + if(!fixedloadout) // extra guns from the match settings: they can be switched to like the pistol/knife + { + givegun(matchspawnsecondary); + givegun(matchspawntertiary); + givegun(matchspawnquaternary); } gunselect = primary; diff --git a/source/src/physics.cpp b/source/src/physics.cpp index d8c5952d..3aaa8b55 100644 --- a/source/src/physics.cpp +++ b/source/src/physics.cpp @@ -397,6 +397,7 @@ FVARP(flyspeed, 1.0, 2.0, 5.0); extern int matchgravity; extern int matchspeedmul; +extern int matchfriction; void moveplayer(physent *pl, int moveres, bool local, int curtime) { @@ -458,7 +459,8 @@ void moveplayer(physent *pl, int moveres, bool local, int curtime) } const float speed = curtime/(water ? 2000.0f : 1000.0f)*pl->maxspeed*weaponspeedmul*(matchspeedmul ? matchspeedmul / 100.0f : 1.0f)*(crouching && pl->state != CS_EDITING ? chspeed : 1.0f)*(pl==player1 && isfly ? flyspeed : 1.0f); - const float friction = water ? 20.0f : (pl->onfloor || isfly ? 6.0f : (pl->onladder ? 1.5f : 30.0f)); + // the constants below are really "inertia" (higher = slides more), so more friction means dividing them + const float friction = (water ? 20.0f : (pl->onfloor || isfly ? 6.0f : (pl->onladder ? 1.5f : 30.0f))) * 100.0f / clamp(matchfriction, 10, 500); const float fpsfric = max(friction/curtime*20.0f, 1.0f); d.x = (float)(move*cosf(RAD*(pl->yaw-90))); diff --git a/source/src/protocol.cpp b/source/src/protocol.cpp index 658bf2eb..25070312 100644 --- a/source/src/protocol.cpp +++ b/source/src/protocol.cpp @@ -306,6 +306,7 @@ char *filtertext(char *dst, const char *src, int flags, int len) mapname = (flags & FTXT_MAPNAME) != 0, // only allows lowercase chars, digits, '_', '-' and '.'; probably should be used in combination with TOLOWER cropwhitelead = (flags & FTXT_CROPWHITE_LEAD) != 0, // removes leading whitespace cropwhitetrail = (flags & FTXT_CROPWHITE_TRAIL) != 0, // removes trailing whitespace + utf8 = (flags & FTXT_UTF8) != 0, // allows valid UTF-8 sequences (without control/format/bidi codepoints); the 7-bit rule applies to the rest pass = false; if(leet || mapname) nocolor = true; #ifdef FILENAMESALLLOWERCASE @@ -316,7 +317,20 @@ char *filtertext(char *dst, const char *src, int flags, int len) bool insidepointybrackets = false; for(int c = *src; c; c = *++src) { - c &= 0x7F; // 7-bit ascii. not negotiable. + if(utf8 && (c & 0x80) && !filename && !mapname && !safecs) + { // multibyte character: validate and copy as a whole, never cut it in half + int cl, cp = utf8decode(src, cl); + if(cp < 0 || (cp <= 0xA0) || (cp >= 0x200B && cp <= 0x200F) || (cp >= 0x2028 && cp <= 0x202E) || (cp >= 0x2060 && cp <= 0x206F) || cp == 0xFEFF || (cp >= 0xFFF0 && cp <= 0xFFFF)) continue; // invalid, C1 controls, zero-width/bidi/format chars + if(len < cl) break; // does not fit + loopi(cl) *dst++ = src[i]; + src += cl - 1; + lastwhite = NULL; + cropwhitelead = false; + len -= cl; + if(len <= 0) break; + continue; + } + c &= 0x7F; // 7-bit ascii. not negotiable (unless FTXT_UTF8 and a valid multibyte sequence, see above). pass = false; if(trans) { @@ -606,6 +620,7 @@ static const int msgsizes[] = // size inclusive message token, 0 f SV_MAPIDENT, 3, SV_DEMOCHECKSUM, 0, SV_DEMOSIGNATURE, 0, SV_PAUSEMODE, 1, SV_GETVITA, 2, SV_VITADATA, 0, + SV_DEATHBLAST, 2, -1 }; diff --git a/source/src/protocol.h b/source/src/protocol.h index 30137da5..cb6de117 100644 --- a/source/src/protocol.h +++ b/source/src/protocol.h @@ -7,7 +7,7 @@ #define CUBE_SERVINFO_PORT(serverport) (serverport+1) #define CUBE_SERVINFO_TO_SERV_PORT(servinfoport) (servinfoport-1) #define CLIENTIPCENSOR 12 // blank out the last 12 bits of client's IPs before telling them to others (compromise between "16" from AC 0.9x and "8" from AC 1.1) -#define PROTOCOL_VERSION 1301 // bump when protocol changes (use negative numbers for mods!) - FORK VERSION +#define PROTOCOL_VERSION 1302 // bump when protocol changes (use negative numbers for mods!) - FORK VERSION #define DEMO_VERSION 2 // bump when demo format changes #define DEMO_MAGIC "ASSAULTCUBE_DEMO" #define DEMO_MINTIME 10000 // don't keep demo recordings with less than 10 seconds @@ -51,6 +51,7 @@ enum SV_MAPIDENT, SV_DEMOCHECKSUM, SV_DEMOSIGNATURE, SV_PAUSEMODE, SV_GETVITA, SV_VITADATA, + SV_DEATHBLAST, SV_NUM }; @@ -213,6 +214,7 @@ enum #define FTXT_MAPNAME (1<<21) #define FTXT_CROPWHITE_LEAD (1<<22) #define FTXT_CROPWHITE_TRAIL (1<<23) +#define FTXT_UTF8 (1<<24) // let valid UTF-8 sequences pass (otherwise everything is forced to 7-bit ascii) // character classes #define FTXT__ALIAS (FTXT_NOWHITE | FTXT_NOCOLOR | FTXT_SAFECS | FTXT_MAPNAME) #define FTXT__SERVDESC (FTXT_NOWHITE | FTXT_ALLOWBLANKS | FTXT_TABTOBLANK) @@ -227,8 +229,8 @@ enum #define FTXT__SERVERINFOLINE (FTXT_ALLOWTAB | FTXT_CROPWHITE_LEAD | FTXT_CROPWHITE_TRAIL) #define FTXT__SERVERINFO (FTXT_ALLOWTAB | FTXT_ALLOWNL) #define FTXT__MOTD (FTXT_TABTOBLANK) -#define FTXT__CHAT (FTXT_NOWHITE | FTXT_ALLOWBLANKS | FTXT_NOCOLOR | FTXT_TABTOBLANK | FTXT_CROPWHITE_TRAIL) -#define FTXT__LOG (FTXT_NOCOLOR | FTXT_TABTOBLANK) +#define FTXT__CHAT (FTXT_NOWHITE | FTXT_ALLOWBLANKS | FTXT_NOCOLOR | FTXT_TABTOBLANK | FTXT_CROPWHITE_TRAIL | FTXT_UTF8) +#define FTXT__LOG (FTXT_NOCOLOR | FTXT_TABTOBLANK | FTXT_UTF8) #define FTXT__LOGIDENT (FTXT_NOCOLOR | FTXT_NOWHITE | FTXT_FILENAME) #define FTXT__PREFERENCES (FTXT_NOCOLOR | FTXT_NOWHITE | FTXT_FILENAME) #define FTXT__AUTH (FTXT_NOCOLOR | FTXT_NOWHITE) @@ -239,7 +241,7 @@ enum #define FTXT__MEDIAFILEPATH (FTXT_FILENAME | FTXT_ALLOWSLASH) #define FTXT__ZIPDESC (FTXT_NOWHITE | FTXT_ALLOWBLANKS | FTXT_TABTOBLANK | FTXT_NOCOLOR | FTXT_SAFECS) #define FTXT__CERTFILENAME (FTXT_MAPNAME | FTXT_ALLOWSLASH | FTXT_TOLOWER) -#define FTXT__CONSOLEPASTE (FTXT_TABTOBLANK) +#define FTXT__CONSOLEPASTE (FTXT_TABTOBLANK | FTXT_UTF8) #define FTXT__AUTOKEYMAPNAME (FTXT_SAFECS) #define FTXT__VITACOMMENT (FTXT_NOWHITE | FTXT_ALLOWBLANKS | FTXT_NOCOLOR | FTXT_TABTOBLANK) #define FTXT__VITACLAN (FTXT_NOWHITE | FTXT_NOCOLOR) diff --git a/source/src/protos.h b/source/src/protos.h index 949ed5fa..6a550585 100644 --- a/source/src/protos.h +++ b/source/src/protos.h @@ -561,6 +561,8 @@ extern void deathstate(playerent *pl); extern void spawnplayer(playerent *d); extern void dodamage(int damage, playerent *pl, playerent *actor, int gun = -1, bool gib = false, bool local = true); extern void dokill(playerent *pl, playerent *act, bool gib = false, int gun = 0); +extern void deathblasteffect(const vec &o); // "explosive deaths" match option: visuals + sound +extern void localdeathblast(playerent *victim); // ... and the damage for offline/bot games (online, the server does that) extern playerent *newplayerent(); extern botent *newbotent(); extern void freebotent(botent *d); @@ -705,10 +707,18 @@ struct font char *name; Texture *tex; - vector chars; + vector chars; // ascii glyphs, index = char - skip + hashtable uchars; // non-ascii glyphs (e.g. cyrillic), key = unicode codepoint, see "fontcharu" int defaultw, defaulth; int offsetx, offsety, offsetw, offseth; int skip; + + charinfo *getglyph(int cp) // NULL if the font has no glyph for this codepoint + { + if(cp < 0) return NULL; + if(cp < 0x80) return chars.inrange(cp - skip) ? &chars[cp - skip] : NULL; + return uchars.access(cp); + } }; #define VIRTH 1800 diff --git a/source/src/rendertext.cpp b/source/src/rendertext.cpp index fafe9b9e..eee8a5cb 100644 --- a/source/src/rendertext.cpp +++ b/source/src/rendertext.cpp @@ -26,6 +26,7 @@ void newfont(char *name, char *tex, int *defaultw, int *defaulth, int *offsetx, f->tex = _tex; f->chars.shrink(0); + f->uchars.clear(); f->defaultw = *defaultw; f->defaulth = *defaulth; f->offsetx = *offsetx; @@ -52,6 +53,27 @@ void fontchar(int *x, int *y, int *w, int *h) } COMMAND(fontchar, "iiii"); +void fontcharu(int *cp, int *x, int *y, int *w, int *h) // glyph for a unicode codepoint (non-ascii), same geometry rules as fontchar +{ + if(!fontdef || *cp < 0x80 || *cp > 0x10FFFF) return; + + font::charinfo &c = fontdef->uchars[*cp]; + c.w = *w ? *w : fontdef->defaultw; + c.h = *h ? *h : fontdef->defaulth; + c.left = (*x + fontdef->offsetx) / float(fontdef->tex->xs); + c.top = (*y + fontdef->offsety) / float(fontdef->tex->ys); + c.right = (*x + c.w + fontdef->offsetw) / float(fontdef->tex->xs); + c.bottom = (*y + c.h + fontdef->offseth) / float(fontdef->tex->ys); +} +COMMAND(fontcharu, "iiiii"); + +void fontselect(char *name) // make an already defined font the target of following fontchar/fontcharu/fontskip commands (does not touch its glyphs) +{ + font *f = fonts.access(name); + if(f) fontdef = f; +} +COMMAND(fontselect, "s"); + void fontskip(int *n) { if(!fontdef) return; @@ -102,7 +124,7 @@ void draw_textf(const char *fstr, int left, int top, ...) draw_text(str, left, top); } -inline int draw_char_contd(font &f, font::charinfo &info, int charcode, int x, int y) +inline int draw_char_contd(font &f, font::charinfo &info, int x, int y) { glTexCoord2f(info.left, info.top ); glVertex2f(x, y); glTexCoord2f(info.right, info.top ); glVertex2f(x + info.w, y); @@ -113,14 +135,9 @@ inline int draw_char_contd(font &f, font::charinfo &info, int charcode, int x, i return info.w; } -static int draw_char(int c, int x, int y) +static int draw_char(font::charinfo *info, int x, int y) { - if(curfont->chars.inrange(c-curfont->skip)) - { - font::charinfo &info = curfont->chars[c-curfont->skip]; - - return draw_char_contd(*curfont, info, c, x, y); - } + if(info) return draw_char_contd(*curfont, *info, x, y); return 0; } @@ -261,42 +278,52 @@ void text_endcolumns() else x = TABALIGN(x); +// decode the character at str[idx]; sets clen to the bytes used. Non-ascii bytes are handled as UTF-8 (invalid ones yield -1 and are skipped) +#define TEXTDECODE(str, idx, c, clen) \ + int c = (uchar)(str)[idx], clen = 1; \ + if(c >= 0x80) c = utf8decode((str) + (idx), clen); + #define TEXTSKELETON \ int y = 0, x = 0, col = 0, colx = 0;\ int i;\ + font::charinfo *glyph = NULL;\ for(i = 0; str[i]; i++)\ {\ TEXTINDEX(i)\ - int c = str[i];\ + TEXTDECODE(str, i, c, clen)\ if(c=='\t') { TEXTTAB(i); TEXTWHITE(i) }\ else if(c==' ') { x += curfont->defaultw; TEXTWHITE(i) }\ else if(c=='\n') { TEXTLINE(i) x = 0; y += FONTH; }\ else if(c=='\f') { if(str[i+1]) { i++; TEXTCOLOR(i) }}\ else if(c=='\1') { if(str[i+1]) { i++; TEXTIGRAPH(i) }}\ else if(c=='\a') { if(str[i+1]) { i++; }}\ - else if(curfont->chars.inrange(c-curfont->skip))\ + else if((glyph = curfont->getglyph(c)) != NULL)\ {\ + int ci = i; /* first byte of this character */\ if(maxwidth != -1)\ {\ int j = i;\ - int w = curfont->chars[c-curfont->skip].w;\ + int w = glyph->w;\ + i += clen - 1; /* i = last byte of the current character */\ for(; str[i+1]; i++)\ {\ - int c = str[i+1];\ - bool isig = c == '\1';\ - if(c=='\f') { if(str[i+2]) i++; continue; }\ + TEXTDECODE(str, i+1, c2, clen2)\ + bool isig = c2 == '\1';\ + if(c2=='\f') { if(str[i+2]) i++; continue; }\ if(i-j > 16) break;\ - if(!isig && !curfont->chars.inrange(c-curfont->skip)) break;\ - int cw = isig ? FONTH + 1 : curfont->chars[c-curfont->skip].w + 1;\ + font::charinfo *g2 = isig ? NULL : curfont->getglyph(c2);\ + if(!isig && !g2) break;\ + int cw = isig ? FONTH + 1 : g2->w + 1;\ if(isig && str[i + 2]) i++;\ if(w + cw >= maxwidth) break;\ w += cw;\ + i += clen2 - 1;\ }\ if(x + w >= maxwidth && j!=0) { TEXTLINE(j-1) x = 0; y += FONTH; }\ TEXTWORD\ }\ else\ - { TEXTCHAR(i) }\ + { TEXTCHAR(ci) i += clen - 1; }\ }\ } @@ -305,10 +332,11 @@ void text_endcolumns() for(; j <= i; j++)\ {\ TEXTINDEX(j)\ - int c = str[j];\ + int js = j; /* first byte of this character */\ + TEXTDECODE(str, j, c, clen)\ if(c=='\f') { if(str[j+1]) { j++; TEXTCOLOR(j) }}\ else if(c=='\1') { if(str[j+1]) { j++; TEXTIGRAPH(j) }}\ - else { TEXTCHAR(j) }\ + else if((glyph = curfont->getglyph(c)) != NULL) { j += clen - 1; TEXTCHAR(js) }\ } int text_visible(const char *str, int hitx, int hity, int maxwidth) @@ -319,7 +347,7 @@ int text_visible(const char *str, int hitx, int hity, int maxwidth) #define TEXTLINE(idx) if(y+FONTH > hity) return idx; #define TEXTCOLOR(idx) #define TEXTIGRAPH(idx) x += FONTH; TEXTWHITE(idx) - #define TEXTCHAR(idx) x += curfont->chars[c-curfont->skip].w+1; TEXTWHITE(idx) + #define TEXTCHAR(idx) x += glyph->w+1; TEXTWHITE(idx) #define TEXTWORD TEXTWORDSKELETON TEXTSKELETON #undef TEXTINDEX @@ -342,7 +370,7 @@ void text_pos(const char *str, int cursor, int &cx, int &cy, int maxwidth) #define TEXTLINE(idx) #define TEXTCOLOR(idx) #define TEXTIGRAPH(idx) x += FONTH; - #define TEXTCHAR(idx) x += curfont->chars[c-curfont->skip].w + 1; + #define TEXTCHAR(idx) x += glyph->w + 1; #define TEXTWORD TEXTWORDSKELETON if(i >= cursor) break; cx = INT_MIN; cy = 0; @@ -366,7 +394,7 @@ void text_bounds(const char *str, int &width, int &height, int maxwidth) #define TEXTLINE(idx) if(x > width) width = x; #define TEXTCOLOR(idx) #define TEXTIGRAPH(idx) x += FONTH + 1; - #define TEXTCHAR(idx) x += curfont->chars[c-curfont->skip].w + 1; + #define TEXTCHAR(idx) x += glyph->w + 1; #define TEXTWORD x += w + 1; width = 0; TEXTSKELETON @@ -384,13 +412,13 @@ void text_bounds(const char *str, int &width, int &height, int maxwidth) void draw_text(const char *str, int left, int top, int r, int g, int b, int a, int cursor, int maxwidth) { -#define TEXTINDEX(idx) if(idx == cursor) { cx = x; cy = y; cc = str[idx]; } +#define TEXTINDEX(idx) if(idx == cursor) { int cl_; cc = utf8decode(str + idx, cl_); if(cc <= 0) cc = ' '; cx = x; cy = y; } #define TEXTTAB(idx) TEXTGETCOLUMN #define TEXTWHITE(idx) #define TEXTLINE(idx) #define TEXTCOLOR(idx) text_color(str[idx], colorstack, sizeof(colorstack), colorpos, color, a); #define TEXTIGRAPH(idx) queue_igraph((uchar)str[idx], left+x, top+y), x += FONTH + 1; -#define TEXTCHAR(idx) x += draw_char(c, left+x, top+y) + 1; +#define TEXTCHAR(idx) x += draw_char(glyph, left+x, top+y) + 1; #define TEXTWORD TEXTWORDSKELETON char colorstack[10]; bvec color(r, g, b); @@ -407,7 +435,8 @@ void draw_text(const char *str, int left, int top, int r, int g, int b, int a, i { if(cx == INT_MIN) { cx = x; cy = y; } if(maxwidth != -1 && cx >= maxwidth) { cx = 0; cy += FONTH; } - int cw = curfont->chars.inrange(cc-33) ? curfont->chars[cc-33].w + 1 : curfont->defaultw; + font::charinfo *cg = curfont->getglyph(cc); + int cw = cg ? cg->w + 1 : curfont->defaultw; rendercursor(left+cx, top+cy, cw); } render_igraphs(); @@ -435,12 +464,19 @@ void cutcolorstring(char *text, int maxlen) maxlen *= curfont->defaultw; while(*text) { + int cl = 1; // bytes of the current character if(*text == '\f' && text[1]) text++; else if(*text == '\1' && text[1]) text++, len += FONTH + 1; else if(*text == '\t') len = TABALIGN(len); - else len += curfont->chars.inrange(*text - curfont->skip) ? curfont->chars[*text - curfont->skip].w : curfont->defaultw; + else + { + TEXTDECODE(text, 0, c, clen) + font::charinfo *g = curfont->getglyph(c); + len += g ? g->w : curfont->defaultw; + cl = clen; + } if(len > maxlen) { *text = '\0'; break; } - text++; + text += cl; } } @@ -450,9 +486,10 @@ bool filterunrenderables(char *s) char *d = s; while(*s) { - if(!curfont->chars.inrange(*s - curfont->skip) && *s != ' ') res = true; - else *d++ = *s; - s++; + TEXTDECODE(s, 0, c, clen) + if(c != ' ' && !curfont->getglyph(c)) res = true; // includes invalid UTF-8 + else loopi(clen) *d++ = s[i]; + s += clen; } *d = '\0'; return res; diff --git a/source/src/server.cpp b/source/src/server.cpp index ca3c639d..abf6f5d7 100644 --- a/source/src/server.cpp +++ b/source/src/server.cpp @@ -22,17 +22,27 @@ int matchassist = 1; // enable assist system (0=off, 1=on) extern int matchfriendlyfire; int matchfriendlyfire = 1; // friendly fire mode: 0=off (no damage), 1=on (damage), 2=off + no shoot teammates +// spawn weapons: -1 = default (the player's own choice of primary / no extra gun), otherwise a GUN_* value. +// primary replaces the weapon you spawn holding; secondary/tertiary/quaternary are extra guns you spawn with. extern int matchspawnprimary; -int matchspawnprimary = GUN_ASSAULT; // default primary weapon +int matchspawnprimary = -1; extern int matchspawnsecondary; -int matchspawnsecondary = GUN_PISTOL; // default secondary weapon +int matchspawnsecondary = -1; extern int matchspawntertiary; -int matchspawntertiary = GUN_KNIFE; // default tertiary weapon +int matchspawntertiary = -1; extern int matchspawnquaternary; -int matchspawnquaternary = -1; // default quaternary weapon (none) +int matchspawnquaternary = -1; + +// "explosive deaths" sub-gamemode: works on top of any gamemode, every death causes an explosion where the player died +extern int matchdeathexplosion; +int matchdeathexplosion = 0; +extern int matchdeathradius; +int matchdeathradius = 100; // blast radius, % of a grenade's +extern int matchdeathpower; +int matchdeathpower = 100; // blast damage, % of the default (75% of a grenade's damage at the centre) struct servergame { @@ -1901,6 +1911,13 @@ void checkitemspawns(int diff) } } +// explosive deaths (see matchdeathexplosion): blasts are queued while a death is processed and handled afterwards, +// so a chain reaction (a blast killing someone who then blows up too) never recurses inside serverdamage() +struct pendingblast { int cn; vec o; }; +static vector blastqueue; +static bool blastflushing = false; +void flushdeathblasts(); + void serverdamage(client *target, client *actor, int damage, int gun, bool gib, const vec &hitpush = vec(0, 0, 0)) { if ( m_arena && gun == GUN_GRENADE && sg->arenaroundstartmillis + 2000 > sg->gamemillis && target != actor ) return; @@ -2016,7 +2033,7 @@ void serverdamage(client *target, client *actor, int damage, int gun, bool gib, actor->state.frags += gib && gun != GUN_GRENADE && gun != GUN_SHOTGUN ? 2 : 1; actor->incrementvitacounter(VS_FRAGS, 1); } - else + else if(!blastflushing) // a death blast hitting a teammate is not a real teamkill (no penalty, no autokick/autoban) { actor->state.frags--; actor->state.teamkills++; @@ -2056,6 +2073,13 @@ void serverdamage(client *target, client *actor, int damage, int gun, bool gib, // don't issue respawn yet until DEATHMILLIS has elapsed // ts.respawn(); + if(matchdeathexplosion && !sg->interm) + { + pendingblast &b = blastqueue.add(); + b.cn = target->clientnum; + b.o = ts.o; + } + if(isdedicated && actor->type == ST_TCPIP && tk) { if( actor->state.frags < scl.banthreshold || @@ -2073,6 +2097,35 @@ void serverdamage(client *target, client *actor, int damage, int gun, bool gib, actor->state.frags < 4 * actor->state.teamkills ) ) disconnect_client(actor->clientnum, DISC_AUTOKICK); } } else if ( target!=actor && isteam(target->team, actor->team) ) check_ffire (target, actor, damage); // friendly fire counter + + if(blastqueue.length() && !blastflushing) flushdeathblasts(); +} + +void flushdeathblasts() +{ + blastflushing = true; + for(int n = 0; n < blastqueue.length(); n++) // blasts queued by chain reactions are appended and handled by this same loop + { + pendingblast b = blastqueue[n]; // copy: the queue can grow (and move) while we apply damage + if(!clients.inrange(b.cn)) continue; + client *victim = clients[b.cn]; + sendf(-1, 1, "ri2", SV_DEATHBLAST, b.cn); // clients draw the explosion + loopv(clients) + { + client *c = clients[i]; + if(c->type==ST_EMPTY || c==victim || c->state.state!=CS_ALIVE) continue; + vec dir(c->state.o); + dir.sub(b.o); + float dist = dir.magnitude(); + if(dist >= DEATHBLASTRAD) continue; + int damage = int(DEATHBLASTDMG*(1-dist/DEATHBLASTRAD)); + if(damage <= 0) continue; + if(dist > 0) dir.div(dist); + serverdamage(c, victim, damage, GUN_GRENADE, true, dir); // the player who died is credited with the blast + } + } + blastqueue.setsize(0); + blastflushing = false; } #include "serverevents.h" @@ -3111,7 +3164,7 @@ int checktype(int type, client *cl) SV_CALLVOTESUC, SV_CALLVOTEERR, SV_VOTERESULT, SV_SETTEAM, SV_TEAMDENY, SV_SERVERMODE, SV_IPLIST, SV_SENDDEMOLIST, SV_SENDDEMO, SV_DEMOPLAYBACK, - SV_CLIENT, SV_DEMOCHECKSUM, SV_PAUSEMODE }; + SV_CLIENT, SV_DEMOCHECKSUM, SV_PAUSEMODE, SV_DEATHBLAST }; // only allow edit messages in coop-edit mode static int edittypes[] = { SV_EDITENT, SV_EDITXY, SV_EDITARCH, SV_EDITBLOCK, SV_EDITD, SV_EDITE, SV_NEWMAP }; if(cl) diff --git a/source/src/server.h b/source/src/server.h index 9589cbff..545d0b3a 100644 --- a/source/src/server.h +++ b/source/src/server.h @@ -456,7 +456,8 @@ const char *messagenames[SV_NUM] = "SV_CLIENT", "SV_EXTENSION", "SV_MAPIDENT", "SV_DEMOCHECKSUM", "SV_DEMOSIGNATURE", - "SV_PAUSEMODE" + "SV_PAUSEMODE", + "SV_GETVITA", "SV_VITADATA", "SV_DEATHBLAST" }; const char *entnames[] = diff --git a/source/src/tools.h b/source/src/tools.h index 89909b67..9e18ce20 100644 --- a/source/src/tools.h +++ b/source/src/tools.h @@ -542,6 +542,45 @@ static inline bool htcmp(uint x, uint y) return x==y; } +// UTF-8 helpers (strings in the whole engine are plain char[]; text that may contain non-ASCII is kept as UTF-8) + +// decodes one UTF-8 sequence at s. Returns the codepoint, or -1 for an invalid/overlong/truncated sequence (len is 1 then). +// len receives the number of bytes consumed (0 at the terminating NUL). +static inline int utf8decode(const char *s, int &len) +{ + const uchar *u = (const uchar *)s; + int c = u[0], n, cp, minv; + if(!c) { len = 0; return 0; } + len = 1; + if(c < 0x80) return c; + if((c & 0xE0) == 0xC0) { n = 1; cp = c & 0x1F; minv = 0x80; } + else if((c & 0xF0) == 0xE0) { n = 2; cp = c & 0x0F; minv = 0x800; } + else if((c & 0xF8) == 0xF0) { n = 3; cp = c & 0x07; minv = 0x10000; } + else return -1; + for(int i = 1; i <= n; i++) + { + if((u[i] & 0xC0) != 0x80) return -1; + cp = (cp << 6) | (u[i] & 0x3F); + } + if(cp < minv || cp > 0x10FFFF || (cp >= 0xD800 && cp <= 0xDFFF)) return -1; + len = n + 1; + return cp; +} + +static inline int utf8charlen(const char *s) // bytes of the character starting at s (at least 1) +{ + int l; + utf8decode(s, l); + return l > 0 ? l : 1; +} + +static inline int utf8prev(const char *s, int i) // index of the start of the character before position i +{ + if(i <= 0) return 0; + do { i--; } while(i > 0 && ((uchar)s[i] & 0xC0) == 0x80); + return i; +} + template struct hashtable { typedef K key; diff --git a/source/src/weapon.cpp b/source/src/weapon.cpp index da8790a0..66ca5f35 100644 --- a/source/src/weapon.cpp +++ b/source/src/weapon.cpp @@ -647,15 +647,15 @@ float expdist(playerent *o, vec &dir, const vec &v) return dist; } -void radialeffect(playerent *o, vec &v, int qdam, playerent *at, int gun) +void radialeffect(playerent *o, vec &v, int qdam, playerent *at, int gun, float radius = EXPDAMRAD) { if(o->state!=CS_ALIVE) return; vec dir; float dist = expdist(o, dir, v); - if(disto); + vec o(victim->o); + radialeffect(player1, o, DEATHBLASTDMG, victim, GUN_GRENADE, DEATHBLASTRAD); + loopv(players) if(players[i] && players[i] != victim) radialeffect(players[i], o, DEATHBLASTDMG, victim, GUN_GRENADE, DEATHBLASTRAD); +} void weapon::renderhudmodel(int lastaction, int index) { @@ -1102,30 +1142,9 @@ void weapon::equipplayer(playerent *pl) pl->weapons[GUN_SNIPER] = new sniperrifle(pl); pl->weapons[GUN_SUBGUN] = new subgun(pl); pl->weapons[GUN_AKIMBO] = new akimbo(pl); - - // Use match settings for spawn weapons - int primary = valid_weapon(matchspawnprimary) ? matchspawnprimary : GUN_ASSAULT; - int secondary = valid_weapon(matchspawnsecondary) ? matchspawnsecondary : GUN_PISTOL; - int tertiary = valid_weapon(matchspawntertiary) ? matchspawntertiary : GUN_KNIFE; - int quaternary = valid_weapon(matchspawnquaternary) ? matchspawnquaternary : -1; - - pl->selectweapon(primary); - pl->setprimary(primary); - pl->setnextprimary(secondary); - - // Ensure tertiary and quaternary weapons have ammo and are in the weapon list - if(tertiary >= 0) - { - pl->ammo[tertiary] = max(pl->ammo[tertiary], guns[tertiary].magsize); - if(pl->weapons[tertiary]) pl->weapons[tertiary]->reset(); - } - if(quaternary >= 0) - { - pl->ammo[quaternary] = max(pl->ammo[quaternary], guns[quaternary].magsize); - if(pl->weapons[quaternary]) pl->weapons[quaternary]->reset(); - } - - // Note: tertiary/quaternary are available but not auto-selected; player can switch to them + // The match spawn weapons (matchspawn*) are applied in playerstate::spawnstate(), so the server and + // local games agree. (They used to be set here, which overwrote the player's nextprimary with the + // "secondary" weapon, and the server's ammo/weapon state then replaced it anyway.) } // grenadeent