Compare commits
1957 Commits
continuous
...
vulkan
Author | SHA1 | Date |
---|---|---|
Ivan Avdeev | f5eb2dada8 | |
Ivan Avdeev | 0980493bb2 | |
Ivan Avdeev | 660513fd5f | |
Ivan Avdeev | fcd9c77bea | |
Ivan Avdeev | 14ab0662df | |
Ivan Avdeev | c3a41f9097 | |
Ivan Avdeev | 2d49b9f983 | |
Ivan Avdeev | ca72c8991b | |
Ivan Avdeev | 8a648619c4 | |
Ivan Avdeev | 68c076bce3 | |
Ivan Avdeev | bc294977fd | |
Ivan Avdeev | a205f3fe3e | |
nilsoncore | 3c7481a7cb | |
nilsoncore | 4d2a6c0e1d | |
nilsoncore | 4bac2cc96f | |
nilsoncore | 790bf25263 | |
nilsoncore | 8363cedf93 | |
Ivan Avdeev | 2b19a8ca50 | |
Ivan Avdeev | cf966b38cb | |
Ivan Avdeev | f9c77060d7 | |
Ivan Avdeev | e5a33ea0c3 | |
Ivan Avdeev | 9fc1f85bcd | |
Ivan Avdeev | 30f2b6372b | |
Ivan Avdeev | a2661fe95d | |
Ivan Avdeev | 5ed4839a31 | |
Ivan 'provod' Avdeev | cba60f7953 | |
Ivan Avdeev | 67ea7af5bb | |
Ivan Avdeev | 315073a564 | |
Ivan Avdeev | aaa6de330c | |
Ivan Avdeev | a56e6a42a5 | |
Ivan Avdeev | 5d6c1d4bfc | |
Ivan Avdeev | 1f8e9fe0c2 | |
Ivan Avdeev | ae3f79c67a | |
Ivan Avdeev | be8da3252a | |
Ivan Avdeev | a578becdd9 | |
Ivan Avdeev | 6169734f91 | |
Ivan Avdeev | cf59921c41 | |
Ivan Avdeev | e8400398bd | |
Ivan Avdeev | 579b9e00ac | |
Ivan Avdeev | 6d58ad8df0 | |
Ivan Avdeev | 18269ebf81 | |
Ivan Avdeev | 7e7351c599 | |
Ivan Avdeev | b01fa98c8b | |
Ivan Avdeev | c7bf03c260 | |
Ivan Avdeev | 8359a04750 | |
Ivan Avdeev | d20bbe1761 | |
Ivan Avdeev | 6e2a3d9004 | |
Ivan Avdeev | e12b2c47b4 | |
Ivan Avdeev | 6ee8af040e | |
Ivan Avdeev | 073dbc55f8 | |
Ivan 'provod' Avdeev | 344c804468 | |
Ivan 'provod' Avdeev | 5f3a0c233b | |
Ivan Avdeev | 6a7cb77809 | |
Ivan Avdeev | 0e4e754fdb | |
Ivan Avdeev | e22f30608a | |
Ivan Avdeev | e808fa0d9d | |
Ivan Avdeev | 0e403e119f | |
Ivan Avdeev | de60cde7ab | |
Ivan Avdeev | 93cc0b5dd7 | |
Ivan Avdeev | 7ef9bb87a9 | |
Ivan Avdeev | e7ff1f3d3a | |
Ivan Avdeev | 9f1b034769 | |
Ivan Avdeev | 2cc2ca3965 | |
Ivan Avdeev | 2507a629cf | |
Ivan Avdeev | f157762043 | |
Ivan Avdeev | 70b0f33f45 | |
Ivan 'provod' Avdeev | dc6cca0d7f | |
Ivan Avdeev | 065bab855a | |
Ivan Avdeev | e398fe5ef3 | |
Ivan Avdeev | 0fd97e2544 | |
Ivan Avdeev | aac4983069 | |
Ivan 'provod' Avdeev | 5a89649917 | |
Ivan 'provod' Avdeev | 3153a83621 | |
Ivan 'provod' Avdeev | 02afc7b320 | |
Ivan 'provod' Avdeev | dd17dee35d | |
Ivan 'provod' Avdeev | 8f5b5657ce | |
Ivan Avdeev | 107c4fb048 | |
Ivan Avdeev | 8248d1d9b3 | |
Ivan Avdeev | 2961ad5b1a | |
Ivan Avdeev | c64000195d | |
Ivan Avdeev | a147c89a53 | |
Ivan 'provod' Avdeev | 20e9af6496 | |
Ivan 'provod' Avdeev | 64520ef5a1 | |
Ivan 'provod' Avdeev | dee067c771 | |
Ivan 'provod' Avdeev | 62fd27ad65 | |
Ivan 'provod' Avdeev | 96b4ea6345 | |
Ivan 'provod' Avdeev | a5086486fa | |
Ivan Avdeev | 5906f72e0d | |
Ivan Avdeev | 0bc585eddc | |
Ivan Avdeev | 55fe48659e | |
Ivan Avdeev | 54cbc85da5 | |
Ivan Avdeev | e12a53fb81 | |
Ivan Avdeev | 6a04888a3c | |
Ivan Avdeev | e9b05ff849 | |
Ivan Avdeev | 5544b99db9 | |
Ivan Avdeev | 88b24ad3bd | |
Ivan Avdeev | 6ffaad02f2 | |
Ivan Avdeev | 9088ab3dc4 | |
Ivan Avdeev | 84babdfff8 | |
Ivan Avdeev | 3bc293d8aa | |
Ivan Avdeev | 1028564eec | |
Ivan Avdeev | 46e95f1255 | |
Ivan Avdeev | 310ecff585 | |
Ivan Avdeev | 180f3ed9cb | |
Ivan Avdeev | caac371681 | |
Ivan Avdeev | 59f7d264c2 | |
Ivan Avdeev | 57fcd5aea8 | |
Aty_0 | c60d851ad8 | |
NightFox | 0a6b40e0ab | |
Ivan Avdeev | 4b605810f3 | |
Ivan Avdeev | c3d4d0fbe9 | |
Ivan Avdeev | e33185c04c | |
Ivan Avdeev | 239d7bc362 | |
Ivan Avdeev | 7d7535c5c5 | |
Ivan Avdeev | d52d44e0ce | |
NightFox | fc1a553bc7 | |
Ivan Avdeev | a0b36a4301 | |
Ivan Avdeev | 7e0553d408 | |
Ivan Avdeev | 5659fb0b6f | |
Ivan Avdeev | 6d79e84f5b | |
Ivan Avdeev | bec1e0f558 | |
Ivan Avdeev | 356f7bdf71 | |
Ivan Avdeev | 2776373652 | |
Ivan Avdeev | b1b333f74a | |
Ivan Avdeev | 6a11c6e64f | |
Ivan Avdeev | 6fc318143e | |
Ivan Avdeev | 3cbc11a8f0 | |
nilsoncore | a06998321e | |
nilsoncore | cba1b02103 | |
nilsoncore | ceb4437f8c | |
nilsoncore | 05ac770c81 | |
nilsoncore | 1117c5969e | |
Ivan Avdeev | 9a0ff43a97 | |
NightFox | 726572b78c | |
NightFox | 0d3c9ba88d | |
Ivan Avdeev | f3f14ac968 | |
NightFox | 852b7c28ba | |
NightFox | 1a9f97bb14 | |
NightFox | e1868c752f | |
Ivan Avdeev | 5c42f34654 | |
Ivan Avdeev | 4ac62076bb | |
Ivan Avdeev | c8123952a2 | |
Ivan Avdeev | 20da50ca7b | |
NightFox | e89e44d94a | |
Ivan Avdeev | b6af3a6b56 | |
NightFox | b22d87ae82 | |
Ivan Avdeev | db4c3c50c7 | |
NightFox | 20cbe33f2f | |
NightFox | 1bec8ad9b9 | |
Ivan Avdeev | 80b524d643 | |
Ivan Avdeev | 6cb45dda77 | |
Ivan Avdeev | e00f758594 | |
Ivan Avdeev | dc0b968028 | |
NightFox | 58572380ab | |
NightFox | de3f350bb4 | |
NightFox | 23c059baac | |
Ivan Avdeev | eba28376d9 | |
Ivan Avdeev | f244aaaddf | |
Ivan Avdeev | 4fc6db36b4 | |
Ivan Avdeev | 84f6d7d10b | |
Ivan Avdeev | 0549822d53 | |
Ivan Avdeev | 2986e128c4 | |
Ivan Avdeev | 9fed89a835 | |
NightFox | 4f988fcb78 | |
NightFox | cdb1532979 | |
Ivan Avdeev | b06081047a | |
Ivan Avdeev | 4fd70777b7 | |
Ivan Avdeev | 4d1b64bb19 | |
Ivan Avdeev | 605647aecc | |
Ivan Avdeev | bde036fc45 | |
Ivan Avdeev | 32f05816e1 | |
Ivan Avdeev | c9b485f8a7 | |
Ivan Avdeev | 7417cfa06f | |
Ivan Avdeev | 73d320f51f | |
Ivan Avdeev | d5f8b593f9 | |
Ivan Avdeev | 40a270cff8 | |
Ivan Avdeev | a0fbb12efb | |
NightFox | 8d5638ef6b | |
NightFox | 36a6e56ee1 | |
Ivan Avdeev | dd21e665b1 | |
Ivan Avdeev | e9dc10a503 | |
Ivan Avdeev | 735260a3c5 | |
Ivan Avdeev | bbd96b3e0e | |
Ivan Avdeev | 016cdeaa6c | |
Ivan Avdeev | 2fbe477dd2 | |
Ivan Avdeev | 2139b32f75 | |
Ivan Avdeev | 036379707d | |
Ivan Avdeev | f11461772a | |
Ivan Avdeev | 4897f97726 | |
Ivan Avdeev | 1ac00a8792 | |
Ivan Avdeev | 27ed4b157a | |
Ivan Avdeev | 9953a47397 | |
Ivan Avdeev | 4897da4f45 | |
Ivan Avdeev | 2a2aaecd92 | |
Ivan Avdeev | a6fe7cc3a6 | |
Ivan Avdeev | 17267fd8c3 | |
Ivan Avdeev | 6b1eeee26b | |
NightFox | 5a3912dcb0 | |
NightFox | 7e3e847b43 | |
NightFox | acc103221a | |
NightFox | e67232e4bf | |
Ivan Avdeev | 7c3448cd15 | |
NightFox | 38fa218340 | |
NightFox | cc764e66d7 | |
Ivan Avdeev | f57a7feea0 | |
Ivan Avdeev | 16de17527a | |
Ivan Avdeev | f0b80887e8 | |
Ivan Avdeev | de80c0da64 | |
Ivan Avdeev | 7d8d59d338 | |
NightFox | 174d601ba6 | |
Ivan Avdeev | 414c43f7a2 | |
Ivan Avdeev | 9b18ffbc02 | |
Ivan Avdeev | 85fbe15f65 | |
NightFox | 8858433928 | |
NightFox | c23404cfa1 | |
Ivan Avdeev | 4def45125c | |
Ivan Avdeev | dc1ea9cb44 | |
Ivan Avdeev | 5f83cb1ef1 | |
Ivan Avdeev | b21a8240ec | |
Ivan Avdeev | f535020f94 | |
Ivan Avdeev | e4d7858330 | |
Ivan Avdeev | 1040a9608d | |
Ivan Avdeev | a3c52a8001 | |
Ivan Avdeev | 78548960e7 | |
Ivan Avdeev | d802404d1c | |
Ivan Avdeev | 70fe5af12e | |
Ivan Avdeev | f6c19527d5 | |
Ivan Avdeev | 4145969198 | |
Ivan Avdeev | 5c3be09161 | |
Ivan Avdeev | 738fcec129 | |
Ivan Avdeev | 2fdd6e719e | |
NightFox | 840d618e4d | |
Ivan Avdeev | 7f3fa2285a | |
Ivan Avdeev | 3e9f6bc7a4 | |
Ivan Avdeev | c575cb6cfd | |
Ivan Avdeev | 2c0e7033ed | |
Ivan Avdeev | c6c58a9842 | |
Ivan Avdeev | 266f57e8a5 | |
Ivan Avdeev | 9eff6fa907 | |
Ivan Avdeev | a18ed8ddc6 | |
Ivan Avdeev | a25bf841ac | |
Ivan Avdeev | 4509e2075d | |
Ivan Avdeev | f8c0baf78d | |
Ivan Avdeev | dfcfd786a9 | |
Ivan Avdeev | d5ee8ba750 | |
NightFox | fd356e6124 | |
NightFox | 6963c158a4 | |
NightFox | 42dfd56f87 | |
NightFox | 0927e25ce2 | |
Ivan Avdeev | 365fffacca | |
Ivan Avdeev | 6e56c8c78d | |
Ivan Avdeev | a42e5051b7 | |
Ivan Avdeev | 3a7d047f09 | |
Ivan Avdeev | 28eec97cbf | |
Ivan Avdeev | 0ba85e3f08 | |
Ivan Avdeev | 2a3f48fd50 | |
Ivan Avdeev | dfa240a4db | |
Ivan Avdeev | 1a5edc8271 | |
Ivan Avdeev | c869223690 | |
Ivan Avdeev | 1f9b489bdc | |
Alibek Omarov | a464c3dd66 | |
Alibek Omarov | bd969f3594 | |
Alibek Omarov | fb87d7c0b3 | |
Alibek Omarov | a69fc87940 | |
Alibek Omarov | e481e1d73e | |
Alibek Omarov | 6c0eed1b2b | |
Alibek Omarov | a6c67fdf9f | |
Alibek Omarov | 03f838e37e | |
Alibek Omarov | e21fa4a910 | |
Alibek Omarov | 46889ed453 | |
Alibek Omarov | 882fcc152c | |
Alibek Omarov | a41902bd46 | |
Alibek Omarov | a6af32dafd | |
Alibek Omarov | d6dfb83be7 | |
Alibek Omarov | 597429cf41 | |
Alibek Omarov | 5ea074a1fd | |
Ivan Avdeev | 6fda8bd977 | |
Ivan 'provod' Avdeev | 5698746f42 | |
Ivan Avdeev | f1c8b3ef2f | |
Ivan Avdeev | a9df5cd86f | |
Ivan Avdeev | 737d1324e8 | |
Ivan Avdeev | effbf3ea3d | |
Ivan Avdeev | 36c06a514e | |
Ivan Avdeev | 5962290b9d | |
Ivan Avdeev | 67f336b3c8 | |
NightFox | 6f40adab98 | |
Alibek Omarov | 29c9393da3 | |
Alibek Omarov | bf6829189e | |
Alibek Omarov | a62a9429c9 | |
mittorn | f2c080e736 | |
Ivan 'provod' Avdeev | 23341c144c | |
Ivan Avdeev | df3c0e30ba | |
Ivan Avdeev | 1f043a90a6 | |
Ivan Avdeev | 8c37b25b31 | |
Ivan Avdeev | 97a889cabb | |
Alibek Omarov | ea55e78855 | |
NightFox | 114015c208 | |
Alibek Omarov | f7c536b81c | |
Alibek Omarov | 6c40104c66 | |
Alibek Omarov | 4d7d592918 | |
Alibek Omarov | c5e91f299b | |
Alibek Omarov | cff276db71 | |
Alibek Omarov | 30d1492b93 | |
Alibek Omarov | f07eea5073 | |
Alibek Omarov | fe407fbe00 | |
Alibek Omarov | 78bc177e05 | |
Alibek Omarov | 8fb908e3d4 | |
Alibek Omarov | d8b261370a | |
Alibek Omarov | a2c9ac5b1f | |
Alibek Omarov | 7f9025e178 | |
Alibek Omarov | 8647110a10 | |
Ivan Avdeev | bc26e8150a | |
Ivan Avdeev | 96864cf0bd | |
Ivan 'provod' Avdeev | eab46bfe20 | |
Ivan Avdeev | ef65ba56ba | |
Alibek Omarov | 48e44f0057 | |
Alibek Omarov | e3934af7d1 | |
Ivan Avdeev | 7d53458ea3 | |
Ivan 'provod' Avdeev | bf9ca596eb | |
Alibek Omarov | a5ee631191 | |
Alibek Omarov | ce39255ef0 | |
Alibek Omarov | 5aac5d2a52 | |
Alibek Omarov | 061b50404d | |
Alibek Omarov | 279cec5ae9 | |
Alibek Omarov | 83a5648335 | |
Alibek Omarov | a8fc9a4c5a | |
Alibek Omarov | 6f6ddbce28 | |
Alibek Omarov | 4cb425d2bb | |
mittorn | bf5fd40d64 | |
mittorn | 6bc613bdb4 | |
mittorn | a982562658 | |
Alibek Omarov | 96a9172e36 | |
Ivan Avdeev | 7eb1bedc9b | |
Ivan Avdeev | a5e3adf518 | |
Ivan Avdeev | d37020806a | |
Ivan Avdeev | ee35b02a5d | |
Ivan Avdeev | 063b3d5246 | |
Ivan Avdeev | afd98e50c9 | |
Ivan Avdeev | 67e5109b4a | |
Alibek Omarov | 34d7664342 | |
Alibek Omarov | b0a79df86f | |
Ivan Avdeev | 718d6d2592 | |
Ivan Avdeev | beddef8831 | |
Ivan Avdeev | c36080c982 | |
Alibek Omarov | 9e107e900c | |
Ivan Avdeev | b016de0c83 | |
Alibek Omarov | 8f819a2fde | |
Alibek Omarov | 3251b68df5 | |
Alibek Omarov | 3ac8ad9484 | |
Alibek Omarov | b9ca0d4563 | |
mittorn | dcb3da53b0 | |
mittorn | e68b19ed1a | |
mittorn | 14c7a84482 | |
mittorn | c1d1aa6787 | |
mittorn | bee81e9723 | |
mittorn | 1bfb6c560a | |
mittorn | 24d6f1788a | |
mittorn | fb95cc9a97 | |
mittorn | b949da291e | |
Alibek Omarov | 2ecbe5b67e | |
Andrey Akhmichin | 6634e0487c | |
Alibek Omarov | 7d61b5317c | |
Alibek Omarov | 201258dc9e | |
Alibek Omarov | 0330569537 | |
Alibek Omarov | a1ab84a2ca | |
Alibek Omarov | 2d79f3ef7a | |
Alibek Omarov | 99a7e9ad87 | |
Alibek Omarov | 02b8037f33 | |
Andrey Akhmichin | fc55a685e3 | |
Ivan Avdeev | b0a7a13c19 | |
Ivan Avdeev | ab6f18fc32 | |
Ivan Avdeev | af032bd2be | |
Alibek Omarov | b76a75d6b4 | |
Ivan Avdeev | b315f463cf | |
Ivan Avdeev | c4935e483c | |
Ivan Avdeev | 18261da713 | |
Ivan Avdeev | a251600c8a | |
Andrey Akhmichin | c551aefd77 | |
Ivan 'provod' Avdeev | fd97dc2c24 | |
Ivan Avdeev | e1d478fa28 | |
Ivan Avdeev | 806932b949 | |
Ivan Avdeev | aa44ab71e5 | |
Ivan Avdeev | 2f7b9d5d14 | |
Ivan Avdeev | bd07444d6e | |
Ivan Avdeev | 2f365b7f97 | |
Ivan Avdeev | c5b6599be7 | |
Ivan Avdeev | 1d90bb1835 | |
Ivan Avdeev | 1834f388b8 | |
Ivan Avdeev | ee81a7228d | |
Ivan Avdeev | d9a4d9d562 | |
Ivan Avdeev | 405934f860 | |
Ivan 'provod' Avdeev | 9dbde6d547 | |
Andrey Akhmichin | f343f0da41 | |
Andrey Akhmichin | 6d318a4102 | |
mittorn | a2b992d865 | |
mittorn | ddf3f2ffdb | |
Alibek Omarov | 2454e87509 | |
mittorn | 0dc44249a2 | |
mittorn | 150cbfa4de | |
mittorn | c0b068d81b | |
mittorn | fbc312b6cf | |
mittorn | 342e0d3e2e | |
mittorn | 202b228691 | |
mittorn | c9c1286803 | |
mittorn | eab98b0eda | |
mittorn | 35be80fc21 | |
mittorn | 6041bb0a43 | |
mittorn | c7dd9d6437 | |
mittorn | d378878c91 | |
mittorn | 4a2f8cafcd | |
mittorn | d254bac16b | |
mittorn | e23b632ce5 | |
mittorn | 2f321b1471 | |
mittorn | 0265e88d8f | |
mittorn | 4114d2f24d | |
mittorn | 8124035763 | |
mittorn | 96127c6eb0 | |
mittorn | cf65a39b83 | |
mittorn | 0341f96b70 | |
mittorn | c95d91cfe3 | |
mittorn | cbd10c6279 | |
mittorn | 5df9e57743 | |
mittorn | c178022fb5 | |
mittorn | 724c29d711 | |
mittorn | 74a2dbeb91 | |
mittorn | 5d20d24ebc | |
mittorn | 0e2fc277c8 | |
mittorn | 1505740b73 | |
mittorn | 6bad07b39d | |
mittorn | f85437dfc5 | |
mittorn | c765261db6 | |
mittorn | 73087ead2d | |
mittorn | 8c88e82709 | |
mittorn | 40dd6e0234 | |
mittorn | eb23b226cc | |
mittorn | 676526a518 | |
mittorn | 7e0bd86b65 | |
mittorn | 97489635af | |
mittorn | a9ea3976a7 | |
Alibek Omarov | 5501ca927a | |
Andrey Akhmichin | a19fb82d66 | |
Andrey Akhmichin | 9d032e953f | |
Andrey Akhmichin | 38587151a9 | |
Andrey Akhmichin | 02d5bab04b | |
Andrey Akhmichin | d8f3e53b1f | |
Andrey Akhmichin | 877ed8a92a | |
Andrey Akhmichin | 487a652aa8 | |
Andrey Akhmichin | 64c5d141af | |
Andrey Akhmichin | 16db8a8008 | |
Andrey Akhmichin | b6b14da102 | |
Andrey Akhmichin | a575605c75 | |
Andrey Akhmichin | a205a3e878 | |
Ivan 'provod' Avdeev | f5d99dab41 | |
Andrey Akhmichin | 26ef3e274c | |
Alibek Omarov | 33be1b7591 | |
Alibek Omarov | de19d78571 | |
mittorn | 287381d5ca | |
Ivan Avdeev | 1b1d79cbd6 | |
Ivan 'provod' Avdeev | 2e2e17b008 | |
Ivan 'provod' Avdeev | b64d8865fd | |
Valery Klachkov | 61d32cd384 | |
Ivan Avdeev | 91e20382ad | |
Ivan Avdeev | a7a7026fdc | |
Ivan Avdeev | 3ac5e88b59 | |
Ivan Avdeev | a0e1dfe4cd | |
Ivan Avdeev | 7cbd34ebdb | |
Ivan Avdeev | 0a5f061ba3 | |
Ivan Avdeev | 8ba7b3649e | |
Ivan Avdeev | 4158234fb2 | |
Ivan Avdeev | 4efbb11178 | |
Ivan Avdeev | 90119ae84a | |
Ivan Avdeev | 726fcee3f7 | |
Alibek Omarov | 4acd0e5304 | |
Ivan Avdeev | 9ca7aad276 | |
Ivan Avdeev | 5ba5fc4831 | |
NightFox | ecdb68370b | |
Ivan Avdeev | 7396403984 | |
Ivan Avdeev | 82dea7a86b | |
Ivan Avdeev | fc36fb7c13 | |
Ivan Avdeev | 7b69988e41 | |
Ivan Avdeev | bf403027c6 | |
Ivan Avdeev | fadde2ea0d | |
Alibek Omarov | cb1063c305 | |
Alibek Omarov | 59bfc8c32f | |
Alibek Omarov | 23494f4e20 | |
Alibek Omarov | b58fbc0c94 | |
Alibek Omarov | 46f38c84b5 | |
Alibek Omarov | 99f290b622 | |
Alibek Omarov | 680ecfefab | |
Alibek Omarov | 7222c74000 | |
Alibek Omarov | 1e43cb734b | |
Ivan 'provod' Avdeev | 4fa614d35b | |
Ivan Avdeev | d76d6429d0 | |
Ivan Avdeev | 7bfba01954 | |
Ivan Avdeev | 9843f53cde | |
Ivan Avdeev | 57093d7198 | |
Ivan Avdeev | 2ec92eea0d | |
Ivan Avdeev | 3b40469a87 | |
Ivan Avdeev | 1d2da5831e | |
Alibek Omarov | cb19fa2f6d | |
Alibek Omarov | 73fcb84b62 | |
Alibek Omarov | 3584d3d1a6 | |
Alibek Omarov | e95139af94 | |
Alibek Omarov | 962f88d31b | |
nilsoncore | 79e0e52061 | |
Ivan Avdeev | c5bbcae242 | |
Alibek Omarov | 3f505103e1 | |
Alibek Omarov | 2c520a6a55 | |
Alibek Omarov | fcc6bba88a | |
Ivan Avdeev | 9b9e89adec | |
Ivan Avdeev | 60f83245ee | |
Ivan Avdeev | 41ac5fa0eb | |
Ivan Avdeev | 96e9ef20ab | |
Alibek Omarov | a738b2a50b | |
NightFox | 56737fd05f | |
Ivan Avdeev | ab53aae359 | |
Ivan Avdeev | 7e3f8785f7 | |
Ivan Avdeev | 9b90e920a7 | |
Alibek Omarov | 34fa1b5ec8 | |
NightFox | e04a19a0af | |
NightFox | 206fd528d8 | |
Ivan Avdeev | 0d6f6d26af | |
Alibek Omarov | 2fdd080eef | |
Ivan Avdeev | 6bfa4c90fa | |
Ivan Avdeev | 1bbcf44864 | |
Ivan Avdeev | b740e0848d | |
NightFox | bdc66ba52b | |
Ivan Avdeev | 737cd944bb | |
NightFox | bd98fdd1d7 | |
Ivan Avdeev | 8ff89bd5ef | |
Ivan Avdeev | 4e01947b6b | |
Ivan Avdeev | e97691b27c | |
Ivan Avdeev | 7839792964 | |
Alibek Omarov | 95f87e24ee | |
Ivan Avdeev | 1f82f352f9 | |
NightFox | 884a4ad97e | |
Ivan Avdeev | b07c5c3740 | |
Ivan 'provod' Avdeev | f63dcd14ce | |
Ivan 'provod' Avdeev | 02efba3902 | |
Ivan Avdeev | acd87043fb | |
Ivan Avdeev | b549ac76f6 | |
Ivan Avdeev | 3aae128e61 | |
nilsoncore | e3d86af5ab | |
nilsoncore | 95223077b6 | |
NightFox | 24c0faca99 | |
Ivan Avdeev | 26224b4aca | |
Ivan Avdeev | e8a09c85e5 | |
Ivan Avdeev | e26ce740f1 | |
nilsoncore | 985ebd23c2 | |
nilsoncore | aebc730b35 | |
nilsoncore | c7f8a2a8f6 | |
nilsoncore | f515228142 | |
Ivan Avdeev | 9ac7340974 | |
Ivan Avdeev | 638bd163af | |
nilsoncore | a909f7bcab | |
nilsoncore | 4f6d9b8e1e | |
nilsoncore | 5a745249e1 | |
Ivan Avdeev | dce0598962 | |
Ivan Avdeev | cd4014766b | |
Ivan Avdeev | 07f1bac938 | |
Ivan Avdeev | 258c3ec48e | |
nilsoncore | 02604cd901 | |
nilsoncore | 977eda258a | |
nilsoncore | 37600be985 | |
nilsoncore | e939d3eab6 | |
nilsoncore | d5df2d2791 | |
nilsoncore | 79c2d5768f | |
nilsoncore | b4aa0fcaf1 | |
nilsoncore | 6659c83c6d | |
Alibek Omarov | bfe17fa241 | |
sofakng | a94a5f1f29 | |
nilsoncore | c07fe8cd9c | |
nilsoncore | d2b71eb3f7 | |
Alibek Omarov | dc71456174 | |
Ivan Avdeev | e28b87beb3 | |
Ivan Avdeev | e27bfdc682 | |
Alibek Omarov | c6b6938e14 | |
Ivan Avdeev | 2e1cb8173e | |
Ivan Avdeev | 54717e60e1 | |
Ivan Avdeev | 755b2d59a9 | |
Ivan 'provod' Avdeev | 06a7de02a8 | |
Ivan 'provod' Avdeev | 7d115168ae | |
Ivan Avdeev | 3333d03a7b | |
Ivan Avdeev | 9ceb129576 | |
Ivan Avdeev | 40a79d7280 | |
Alibek Omarov | 2823a6d269 | |
Alibek Omarov | bee35a1873 | |
Ivan Avdeev | 5767ddb30c | |
Ivan 'provod' Avdeev | 64e1a9b763 | |
Alibek Omarov | e4ae386964 | |
Alibek Omarov | 36831555b9 | |
Alibek Omarov | 8eef212726 | |
Ivan Avdeev | a1cae92a2c | |
Ivan Avdeev | d9207963f9 | |
Ivan Avdeev | 26a4fff486 | |
Ivan Avdeev | 48b7fcb153 | |
Ivan Avdeev | 49bfd28d3c | |
NightFox | f3b55c63bb | |
NightFox | 9c7d8a6ee0 | |
Velaron | 1589defda1 | |
Velaron | df921d8664 | |
Velaron | f3949474b9 | |
Ivan Avdeev | 4944b5eb05 | |
Ivan 'provod' Avdeev | 6d749ea8d0 | |
Ivan Avdeev | 13eef5dda2 | |
Ivan Avdeev | b8eb6156a8 | |
Ivan Avdeev | 29508cd324 | |
Ivan Avdeev | bdbfbef8a2 | |
Ivan Avdeev | f42ea011f1 | |
Ivan Avdeev | 58ed5e7277 | |
Ivan Avdeev | 61416cfc66 | |
Ivan Avdeev | d8d5019971 | |
Ivan Avdeev | 0856e9e70d | |
Ivan Avdeev | a9dcf94f1b | |
Alibek Omarov | 706ef65208 | |
Ivan Avdeev | 883ccff13f | |
Ivan Avdeev | 1d9b987379 | |
Ivan Avdeev | 9c4fd15e65 | |
Ivan Avdeev | 3e14591082 | |
Alibek Omarov | 435b95fc5a | |
Alibek Omarov | aeece35291 | |
Emil Tomczyk | abd7f3dca3 | |
Alibek Omarov | 1c9f333420 | |
Ivan Avdeev | ea1a98716d | |
Ivan Avdeev | 0ccc107859 | |
Ivan Avdeev | 6d3c5bfa3e | |
Alibek Omarov | 75e5da071c | |
Alibek Omarov | 52bd923d9d | |
Ivan Avdeev | e978871470 | |
Ivan Avdeev | ffa9603747 | |
Ivan 'provod' Avdeev | 2dc68544d6 | |
Ivan 'provod' Avdeev | 45a141aa36 | |
Ivan 'provod' Avdeev | 03fc537d54 | |
Ivan 'provod' Avdeev | c42cf2088c | |
Ivan 'provod' Avdeev | 567d014ada | |
Ivan 'provod' Avdeev | 9636b541c5 | |
Ivan Avdeev | 47cc51d9b1 | |
Ivan Avdeev | 09d8534b01 | |
Ivan Avdeev | f99d43ec4c | |
Alibek Omarov | ab5a9eec53 | |
Alibek Omarov | 88916fdac4 | |
Alibek Omarov | 22f60d50ac | |
Alibek Omarov | 4ed562697b | |
Alibek Omarov | 64166c7d82 | |
Alibek Omarov | 0df89bddeb | |
Alibek Omarov | 3168e5ccf0 | |
Alibek Omarov | 72fe214f49 | |
Alibek Omarov | e1cbf96100 | |
Alibek Omarov | 1d6f695749 | |
Alibek Omarov | 08a2d431da | |
Alibek Omarov | 8bdb49516d | |
Alibek Omarov | e7f5cb6910 | |
Alibek Omarov | 9968b192c3 | |
Alibek Omarov | 79f2c69963 | |
Alibek Omarov | 2067667c9c | |
Alibek Omarov | e017b9145f | |
Alibek Omarov | c1c27c5f18 | |
Alibek Omarov | 87a56a5fa1 | |
Alibek Omarov | aee99f6094 | |
Alibek Omarov | bf03f739bb | |
Alibek Omarov | e23580c1de | |
Alibek Omarov | e49848d090 | |
Alibek Omarov | 1bfc6e6705 | |
Alibek Omarov | e7c41759fb | |
Alibek Omarov | a07f81820c | |
Alibek Omarov | b39378a6da | |
Alibek Omarov | 5c6b9d3235 | |
Alibek Omarov | 3d49ca25b3 | |
Alibek Omarov | 43fde38d88 | |
Alibek Omarov | 6461fa5042 | |
Alibek Omarov | 788bc820c8 | |
Alibek Omarov | 36ff819daf | |
Alibek Omarov | 8905883225 | |
Alibek Omarov | 4031f5cb01 | |
Alibek Omarov | cd46ad19a3 | |
Alibek Omarov | 6f7b1695d7 | |
Alibek Omarov | 28a4b51939 | |
Alibek Omarov | 5e878aae89 | |
Alibek Omarov | 7e05562c14 | |
Alibek Omarov | 777dd3a03c | |
Alibek Omarov | 9977cb20c0 | |
Alibek Omarov | 5661766c79 | |
Alibek Omarov | 60d65d368a | |
Alibek Omarov | 031594cc99 | |
Alibek Omarov | d4bf57c7c2 | |
Alibek Omarov | 8e16c0e410 | |
Alibek Omarov | d5f4b409e8 | |
Alibek Omarov | 88c560aac4 | |
Alibek Omarov | c3a6cad0c1 | |
Alibek Omarov | a862446072 | |
Alibek Omarov | 8d04ae8802 | |
Alibek Omarov | 0de0615eeb | |
Alibek Omarov | ea24b5f3ca | |
Alibek Omarov | eb7f19d3cf | |
Alibek Omarov | ca134a85ee | |
Alibek Omarov | 00765f1ff2 | |
Alibek Omarov | 013bfe5c34 | |
Alibek Omarov | 5f625bb6e1 | |
Alibek Omarov | 547a862024 | |
Alibek Omarov | 6ea8d141d9 | |
Alibek Omarov | bdc2390d41 | |
Alibek Omarov | acc113309c | |
Alibek Omarov | 5afda72290 | |
Alibek Omarov | 6a7b330463 | |
Alibek Omarov | f5b9826fd9 | |
Alibek Omarov | 82addf11bb | |
Alibek Omarov | aee5e46516 | |
Alibek Omarov | 40e248aa63 | |
fgsfds | 24ee3ae318 | |
fgsfds | f79aaf93f8 | |
Alibek Omarov | 0d89849cab | |
Alibek Omarov | d962255ebe | |
Alibek Omarov | 21b47dff32 | |
Alibek Omarov | 1905782c41 | |
Alibek Omarov | b29b3d5859 | |
Alibek Omarov | 3533b0d284 | |
Alibek Omarov | 7e06d049f5 | |
Alibek Omarov | 5a4c443c79 | |
Alibek Omarov | 4bbd1e59a4 | |
Alibek Omarov | 0809453b2c | |
Alibek Omarov | 8350d81c18 | |
Alibek Omarov | 57499dea33 | |
Alibek Omarov | 6b223f1325 | |
Alibek Omarov | 03a85e0caa | |
Alibek Omarov | 01ad3dda2a | |
Alibek Omarov | 2a05624615 | |
Alibek Omarov | f3ed9b21c0 | |
Alibek Omarov | 16c87ae2c9 | |
Alibek Omarov | c16a10e6f3 | |
Alibek Omarov | c7d748e8df | |
Alibek Omarov | 0e16110c3a | |
Alibek Omarov | c966589a50 | |
Alibek Omarov | 4c02c25506 | |
Alibek Omarov | a4997d0647 | |
Alibek Omarov | 243c3cc80f | |
Ivan Avdeev | f691b4b4b0 | |
Alibek Omarov | a8dbec56c3 | |
Alibek Omarov | 9c62fa901f | |
Ivan Avdeev | d13c0d4748 | |
Ivan Avdeev | 5dda220751 | |
Ivan Avdeev | c72ff1d0c5 | |
Ivan Avdeev | 0b47621f69 | |
Ivan Avdeev | 046ae3d7f3 | |
Alibek Omarov | 996897e30e | |
Alibek Omarov | 93ee5b9446 | |
Alibek Omarov | c0c8119040 | |
jeefo | 61c75b9809 | |
jeefo | 868d10a842 | |
jeefo | 699f3579fe | |
jeefo | 873ce0ce48 | |
Alibek Omarov | 450f77443d | |
Alibek Omarov | 278ff22ba9 | |
jeefo | d9ef1d4608 | |
Ivan Avdeev | 6583ed0c31 | |
Ivan 'provod' Avdeev | ba041fce36 | |
Ivan 'provod' Avdeev | cadf3dbdfc | |
Alibek Omarov | 58df771c9e | |
Alibek Omarov | a6ecc778fc | |
Alibek Omarov | 37e890f326 | |
Alibek Omarov | 0d6137ee40 | |
Alibek Omarov | 653eb00cc6 | |
Ivan Avdeev | 406a5f9d4b | |
Ivan Avdeev | 4409e57a8d | |
Ivan Avdeev | 0b8fe6fe33 | |
Alibek Omarov | b84aba68fa | |
Ivan Avdeev | e6bf0c452a | |
Ivan Avdeev | 789982277d | |
Ivan Avdeev | 98f8300ca2 | |
Ivan Avdeev | 8e0a9ac4d4 | |
Ivan Avdeev | c105d45265 | |
Ivan Avdeev | 0e13ed38c1 | |
Ivan Avdeev | c271078196 | |
Alibek Omarov | 1855fab80b | |
Alibek Omarov | 23f1c43282 | |
Alibek Omarov | a7c76ac0bf | |
Alibek Omarov | 26959cd280 | |
Ivan Avdeev | 3e2e5e7cb2 | |
Alibek Omarov | 1fdf6180e6 | |
Alibek Omarov | d2237fa144 | |
Alibek Omarov | febdfacbd3 | |
Alibek Omarov | ef663a8790 | |
Alibek Omarov | ba039b8e71 | |
Alibek Omarov | 02ce80981c | |
Ivan 'provod' Avdeev | a2b0164e03 | |
Alibek Omarov | a40a325d3c | |
Ivan Avdeev | df102994c4 | |
Alibek Omarov | 85cc942a3c | |
Alibek Omarov | a23e17c6d7 | |
Alibek Omarov | 59412f3d92 | |
Alibek Omarov | 0a15cc389d | |
Alibek Omarov | 13f8a02cdf | |
Alibek Omarov | 8caa2d142f | |
Alibek Omarov | 3b8009917a | |
Alibek Omarov | e2e14945e4 | |
Ivan Avdeev | c34c56e203 | |
Ivan Avdeev | 3bbca26087 | |
Ivan Avdeev | 72acf4882d | |
Ivan Avdeev | edb151bd1b | |
Ivan Avdeev | 8f47115a01 | |
Ivan Avdeev | ed4d0070f8 | |
Ivan 'provod' Avdeev | 32cb4f73be | |
Ivan 'provod' Avdeev | dd8f06ae60 | |
Ivan 'provod' Avdeev | 8b50ebb035 | |
Ivan Avdeev | e9ea962bc0 | |
Ivan 'provod' Avdeev | c157c9acfc | |
Ivan Avdeev | 0853f1c182 | |
Alibek Omarov | 16595bf2c0 | |
Alibek Omarov | f49a2bc8f3 | |
Alibek Omarov | d994c6df9a | |
Alibek Omarov | 3a57f26351 | |
Alibek Omarov | 7fd1534753 | |
Alibek Omarov | bd52a9ec2d | |
Alibek Omarov | 9e0d389d9e | |
Alibek Omarov | 8680757844 | |
Alibek Omarov | 95a8d2f51f | |
Alibek Omarov | 70b26a13c2 | |
Alibek Omarov | 6a1f96a2c6 | |
Alibek Omarov | 4ce2475602 | |
Alibek Omarov | e7ece41ba0 | |
Alibek Omarov | 05579927a5 | |
Alibek Omarov | 2f5b359c99 | |
Alibek Omarov | 214fc7e827 | |
Alibek Omarov | df173a83ed | |
Alibek Omarov | 3918bcd71c | |
Alibek Omarov | f19ed1c1c2 | |
Alibek Omarov | 03ec2f603b | |
Alibek Omarov | 1ee01163b7 | |
Alibek Omarov | b1d60c248d | |
Alibek Omarov | d9cbf1fa89 | |
Alibek Omarov | cd022bdac7 | |
Alibek Omarov | 5d7d5319fd | |
Alibek Omarov | d4470402ee | |
Alibek Omarov | 05560c7607 | |
Alibek Omarov | 81c752da2b | |
Alibek Omarov | fd2ad447a8 | |
Alibek Omarov | 18d55c1de2 | |
Alibek Omarov | d0d09c878f | |
Alibek Omarov | e791d44dd8 | |
Alibek Omarov | 152f6d154c | |
Alibek Omarov | 5627dbbf34 | |
Alibek Omarov | 9cd9744407 | |
Alibek Omarov | f13c285287 | |
Ivan Avdeev | 7ee16cd82f | |
Alibek Omarov | cca7744f1c | |
Alibek Omarov | 31ae22961b | |
Ivan Avdeev | d24961db15 | |
Alibek Omarov | a3603f497d | |
Alibek Omarov | d36cb62a2e | |
Alibek Omarov | 2ca6029e03 | |
Alibek Omarov | dee5cae5f3 | |
Alibek Omarov | ef4bc2acf2 | |
Alibek Omarov | eb61bcf76a | |
Alibek Omarov | cb43df43ef | |
Alibek Omarov | 356f78ee81 | |
Alibek Omarov | 275cd73ade | |
Ivan Avdeev | 9200cbfc25 | |
Ivan Avdeev | 8724efd748 | |
Velaron | bb1b9dad23 | |
Velaron | e27ac6b092 | |
Alibek Omarov | 7333ddc1d9 | |
Alibek Omarov | fbd7d8f58a | |
Alibek Omarov | 3415185dde | |
Alibek Omarov | 551ea71906 | |
Alibek Omarov | 1d965d7543 | |
Alibek Omarov | 1d62df0e2d | |
Ivan Avdeev | 322e7bc419 | |
Ivan Avdeev | b5f79f3815 | |
Ivan Avdeev | e55e411639 | |
Ivan Avdeev | b65f84793a | |
Ivan Avdeev | 4af9f65cd0 | |
Ivan Avdeev | 7060a86662 | |
Ivan Avdeev | 14a648d16c | |
Alibek Omarov | b0f52236bc | |
Alibek Omarov | 7dcddc559c | |
Alibek Omarov | 277bead9b7 | |
Alibek Omarov | d8093ec587 | |
Alibek Omarov | 323626c308 | |
Alibek Omarov | 68ff265e8d | |
Alibek Omarov | a3ab04e0cb | |
Ivan Avdeev | 7d6c12218f | |
Ivan Avdeev | e54913f8af | |
Ivan Avdeev | 091c61a45f | |
Ivan Avdeev | e49f517dc0 | |
Alibek Omarov | 7d2bf93c72 | |
Alibek Omarov | 04107d384e | |
Alibek Omarov | 3a0f1763fb | |
Alibek Omarov | 377dd9a255 | |
Alibek Omarov | 8961e37d7c | |
Alibek Omarov | de1e53311a | |
Alibek Omarov | 19582cdf11 | |
Alibek Omarov | fa0e7e4369 | |
Alibek Omarov | 2378331e47 | |
Alibek Omarov | 5549e7301c | |
Alibek Omarov | 5ab7d09a00 | |
Alibek Omarov | c54e1625d1 | |
Alibek Omarov | d0127e5e14 | |
Andrey Akhmichin | 0f643f1f87 | |
Andrey Akhmichin | 16eb12b1e0 | |
NightFox | c91db96008 | |
NightFox | e86e16235c | |
NightFox | a2c6e3b444 | |
NightFox | 596d35ddfa | |
NightFox | b49dca536d | |
NightFox | d2f45c53a0 | |
NightFox | 48f9813edd | |
Alibek Omarov | 4856a3c084 | |
Ivan Avdeev | babfbb08ab | |
Ivan Avdeev | 4f43b316a6 | |
Ivan Avdeev | 481aa651c6 | |
Ivan Avdeev | 0b6ef9fd65 | |
Ivan 'provod' Avdeev | 58433a2221 | |
Alibek Omarov | 78e239d883 | |
Alibek Omarov | 5a7b68fcc1 | |
Alibek Omarov | c33a384975 | |
Ivan Avdeev | 2dcc5073aa | |
Ivan Avdeev | 528a715c76 | |
Ivan Avdeev | 3affb12574 | |
Ivan 'provod' Avdeev | 1cfb183cbd | |
Ivan Avdeev | 0d8a7f76f5 | |
Ivan Avdeev | 54d909b715 | |
Ivan Avdeev | 209bf1faa2 | |
Alibek Omarov | 5b582b744a | |
Alibek Omarov | c96f8ba722 | |
Alibek Omarov | 9f92e2a1f7 | |
Alibek Omarov | 710b234493 | |
Alibek Omarov | 75759530e3 | |
Alibek Omarov | 5162ab62fd | |
Alibek Omarov | 3e2a215c15 | |
Alibek Omarov | e2540bd446 | |
Alibek Omarov | 07fd4f37ef | |
Alibek Omarov | 92b72a7d33 | |
Alibek Omarov | 6cc3832582 | |
Alibek Omarov | 12dbfb467a | |
Ivan Avdeev | b93ef2e52c | |
Ivan 'provod' Avdeev | e1d250e8da | |
Ivan 'provod' Avdeev | f722f38617 | |
Ivan 'provod' Avdeev | 52f99ec329 | |
Ivan Avdeev | b17c00654b | |
Ivan Avdeev | 3447dfc5d6 | |
Alibek Omarov | 62590dd2a9 | |
Alibek Omarov | e5e2a63ba2 | |
Alibek Omarov | a117338435 | |
Alibek Omarov | d75dcd358e | |
Alibek Omarov | c4757058e1 | |
Alibek Omarov | cb3b16e2ec | |
Alibek Omarov | bd3dc71f39 | |
Ivan Avdeev | 8ac1a76259 | |
Ivan Avdeev | 847777fb6b | |
Ivan Avdeev | 0b8b5b571b | |
Ivan Avdeev | b79a65f8a1 | |
Ivan Avdeev | 449bcc4db9 | |
Ivan Avdeev | ae510dd3ff | |
Ivan 'provod' Avdeev | d6a41bc041 | |
Ivan 'provod' Avdeev | d576818550 | |
Ivan 'provod' Avdeev | 3800d6559e | |
Ivan 'provod' Avdeev | 1ebc1d207c | |
Ivan 'provod' Avdeev | 5b370509fe | |
Alibek Omarov | 48176233bd | |
Alibek Omarov | a292d2fd53 | |
Alibek Omarov | 27aad9f4a0 | |
Alibek Omarov | 71a3cedba8 | |
Alibek Omarov | ec2951cf45 | |
Alibek Omarov | ff436ae100 | |
Alibek Omarov | cfdfdd5c93 | |
Alibek Omarov | 8b96e7ca87 | |
Alibek Omarov | 1603b8028c | |
Alibek Omarov | 8c7db8499f | |
Alibek Omarov | fbdd79644b | |
Alibek Omarov | ac39090f6e | |
Alibek Omarov | 8f207362a5 | |
Alibek Omarov | b16fa8eddc | |
Alibek Omarov | 2261b0dcab | |
Alibek Omarov | 9eb49fc673 | |
Alibek Omarov | c61c84ad4f | |
Alibek Omarov | 71c9fd2772 | |
Alibek Omarov | 1464e1e2be | |
Alibek Omarov | cf557d191a | |
Alibek Omarov | b72033eb74 | |
Alibek Omarov | cec903fd10 | |
Alibek Omarov | b333edeefe | |
Alibek Omarov | 76c7273600 | |
Alibek Omarov | 096ee34f67 | |
Ivan Avdeev | aab689a37b | |
Ivan Avdeev | 935c2e7f5e | |
Ivan Avdeev | 41b033efbd | |
Alibek Omarov | 5b52a9a19f | |
Ivan Avdeev | e9f15edbd5 | |
Ivan Avdeev | d7660cf358 | |
Ivan Avdeev | ca2a794341 | |
Ivan Avdeev | 7c6e22bb2c | |
Alibek Omarov | cacfff008f | |
Alibek Omarov | 398cec626e | |
Alibek Omarov | cadad6ce34 | |
Alibek Omarov | 588d080a63 | |
Alibek Omarov | 1affc36f06 | |
Alibek Omarov | 8d6ac3fad4 | |
Alibek Omarov | 0d5d30398b | |
Alibek Omarov | eb0686fca1 | |
Alibek Omarov | 41025c0049 | |
Tim Schumacher | 6518a5cf8b | |
Alibek Omarov | 49936120ca | |
Alibek Omarov | e4a5b95e81 | |
Alibek Omarov | 84fc8d4281 | |
Alibek Omarov | e9da3e2976 | |
Alibek Omarov | c1252b5642 | |
Alibek Omarov | 7d54952422 | |
Alibek Omarov | b28d10f69f | |
Alibek Omarov | 6cb3b2f01a | |
Alibek Omarov | 248be5458f | |
Alibek Omarov | 2e7306e96a | |
Ivan Avdeev | cfddb75bc5 | |
Ivan Avdeev | b4dde5bafd | |
Alibek Omarov | 558ded6d6a | |
Alibek Omarov | c52dc69360 | |
Alibek Omarov | ba1648c689 | |
Alibek Omarov | 101a7a1240 | |
Alibek Omarov | 25d6b2b069 | |
Alibek Omarov | f67b97e63c | |
Alibek Omarov | 9a24cb8c96 | |
Alibek Omarov | c157b7def3 | |
Alibek Omarov | de88aec958 | |
Alibek Omarov | 7f31871b5a | |
Alibek Omarov | f55ef63e26 | |
Ivan Avdeev | 2dd4059704 | |
Alibek Omarov | 824a34ee1e | |
Ivan Avdeev | b894337d0e | |
Ivan Avdeev | 1b0c8c763e | |
Ivan Avdeev | b5e5d699bc | |
Ivan Avdeev | b3ffd911bb | |
Alibek Omarov | 46e2ccd2bf | |
Alibek Omarov | 339c08d89f | |
Alibek Omarov | 2db2375b4d | |
Alibek Omarov | d86ab19351 | |
Alibek Omarov | db40d58208 | |
Alibek Omarov | 33ff7bbd61 | |
Ivan Avdeev | 90591cfb3d | |
Ivan Avdeev | 1fd9e49f63 | |
Ivan Avdeev | 9116b0268e | |
Ivan Avdeev | 51318fc77f | |
Alibek Omarov | 4d4162336a | |
Jonathan Poncelet | 372514151d | |
Jonathan Poncelet | 6c9ce478a9 | |
Jonathan Poncelet | 78555ab125 | |
Ivan Avdeev | 139807a559 | |
Ivan Avdeev | c917c7a818 | |
Ivan Avdeev | 93153dd87e | |
Ivan Avdeev | 084874c5c8 | |
Ivan Avdeev | a38f990ef5 | |
Ivan 'provod' Avdeev | fdab0f7536 | |
Ivan Avdeev | 92ce698292 | |
Ivan Avdeev | f6201e460f | |
Ivan Avdeev | 6d43e02dd3 | |
Ivan Avdeev | 1bf6f6ee74 | |
Ivan Avdeev | 73a6cf596a | |
Ivan Avdeev | 4bd62ccbc0 | |
Andrey Akhmichin | f2c671d809 | |
Alibek Omarov | 4bce193645 | |
Alibek Omarov | 129de871e3 | |
Alibek Omarov | c24a1fafc5 | |
Alibek Omarov | cee3757e6f | |
Alibek Omarov | 12ed092446 | |
Alibek Omarov | 2fb19a0cfd | |
Alibek Omarov | 79624fa400 | |
Alibek Omarov | 550ced9c36 | |
Alibek Omarov | fd795d5612 | |
Alibek Omarov | dc0982932b | |
Alibek Omarov | 5d387101b9 | |
Alibek Omarov | eef1e1868a | |
Alibek Omarov | 4005ef831a | |
Alibek Omarov | b0c71c598f | |
Alibek Omarov | d7848b7b8d | |
Alibek Omarov | 9cdce1ce69 | |
Alibek Omarov | 84edd9d0c4 | |
Alibek Omarov | d8355a651f | |
Alibek Omarov | 004ac8105e | |
Alibek Omarov | 2e8ab13242 | |
Alibek Omarov | 27d9fc0afe | |
Alibek Omarov | 192d510924 | |
Alibek Omarov | 3614cfa878 | |
Alibek Omarov | 12efcf1c44 | |
Alibek Omarov | a8de11643c | |
Alibek Omarov | 597027277c | |
Alibek Omarov | 48988e66bd | |
Alibek Omarov | 37e3cf7e86 | |
Alibek Omarov | 01e0542223 | |
Alibek Omarov | 93a7ccd14f | |
Alibek Omarov | 892e5c59eb | |
Alibek Omarov | c2992afb4a | |
Alibek Omarov | b99e7a6304 | |
Alibek Omarov | 8888b456df | |
Alibek Omarov | 53987f47e2 | |
Ivan Avdeev | 5c7bd9d285 | |
Ivan Avdeev | cea37acfd2 | |
Ivan 'provod' Avdeev | b5dfef5574 | |
Ivan Avdeev | adab64b797 | |
Ivan Avdeev | 33aa4bc259 | |
Ivan Avdeev | af96609c04 | |
Ivan Avdeev | 2b2e69da72 | |
Alibek Omarov | 7cac1d290d | |
Alibek Omarov | 55b048aab9 | |
Alibek Omarov | 881a7edb9f | |
Alibek Omarov | 6c62136f11 | |
Alibek Omarov | f34b35be5a | |
Alibek Omarov | 4b5ee87de1 | |
Alibek Omarov | 67903b55cc | |
Alibek Omarov | 55bf0e8a53 | |
Alibek Omarov | f1487cf576 | |
Alibek Omarov | 29e32310cf | |
Alibek Omarov | 2ea549f250 | |
SNMetamorph | b2ea8c9d18 | |
Alibek Omarov | 6e27926a10 | |
Alibek Omarov | 96c30371b7 | |
Alibek Omarov | 9a42f4149f | |
Alibek Omarov | dca4226e4b | |
Alibek Omarov | b3c1c173a9 | |
Alibek Omarov | 3e67445ef3 | |
Alibek Omarov | 127bd89b44 | |
SNMetamorph | 3361e74f54 | |
SNMetamorph | 48e199bfa1 | |
SNMetamorph | 575179dbf5 | |
SNMetamorph | e024a67436 | |
SNMetamorph | e3103249f4 | |
SNMetamorph | 0746cb5365 | |
Alibek Omarov | fcda7517fe | |
Alibek Omarov | 2c77f4c566 | |
Ivan Avdeev | 8afd23a2d4 | |
Ivan Avdeev | 1ae3ae4774 | |
Ivan Avdeev | 89f49276a5 | |
Ivan Avdeev | 68761fbbbb | |
Ivan Avdeev | 2976f753e1 | |
Ivan Avdeev | 2db83a22a5 | |
Ivan Avdeev | f2ebcd663b | |
Ivan Avdeev | 8ecfae5bf0 | |
Ivan Avdeev | cdc2a1258a | |
Ivan Avdeev | 3b47c7315a | |
Ivan Avdeev | 160a69d2cc | |
Ivan Avdeev | e0e9305628 | |
Ivan Avdeev | 576b4163b9 | |
Alibek Omarov | 1caa276531 | |
Alibek Omarov | e673fe9a02 | |
Ivan 'provod' Avdeev | 5f38f3467d | |
Alibek Omarov | 3ccbc7a28c | |
Alibek Omarov | 8bb5ec5e26 | |
Alibek Omarov | 35ff062407 | |
Alibek Omarov | ec355a83d1 | |
Alibek Omarov | 182d8edb42 | |
Alibek Omarov | 762e4da7a0 | |
Ivan 'provod' Avdeev | 4a5fc186ea | |
Ivan Avdeev | e1afb2a9de | |
Ivan Avdeev | 5d23494cfc | |
Ivan Avdeev | 9d8ec1bc9d | |
Ivan Avdeev | 55af70c422 | |
Ivan Avdeev | bcb1d367b9 | |
Ivan Avdeev | 2b8f74ff0e | |
Ivan 'provod' Avdeev | b4b63492f2 | |
Ivan Avdeev | 22d4202ad9 | |
Ivan Avdeev | a66c44a266 | |
Ivan 'provod' Avdeev | 93a539df74 | |
Ivan 'provod' Avdeev | be95b65b22 | |
Ivan 'provod' Avdeev | 9a5e1fec4a | |
Ivan Avdeev | 2872b4d237 | |
Ivan Avdeev | 1c9ff300a9 | |
Ivan Avdeev | be59d1d8e9 | |
Ivan Avdeev | 39f2d78199 | |
Alibek Omarov | 098c4c009b | |
Alibek Omarov | f8cf2c8953 | |
Alibek Omarov | cc6838ec97 | |
Alibek Omarov | dca637d4bb | |
Alibek Omarov | 3949422430 | |
Alibek Omarov | 2c8488f07a | |
Alibek Omarov | 1df1fc32df | |
SNMetamorph | eac8c116a8 | |
SNMetamorph | a03019f5e4 | |
SNMetamorph | 714b4f45e4 | |
SNMetamorph | 68be8157ea | |
Alibek Omarov | ea2a8b6785 | |
NightFox | 190a691c6d | |
NightFox | e5658f59cd | |
Alibek Omarov | 8c80d3b85d | |
Alibek Omarov | 33c0764e65 | |
Alibek Omarov | d085c5a843 | |
Alibek Omarov | 4ada40e8a8 | |
Alibek Omarov | 1630d87c0d | |
Alibek Omarov | 3a956a1ad3 | |
Alibek Omarov | 774ced312f | |
Alibek Omarov | fec3d33dcf | |
Alibek Omarov | d4610e30fd | |
Alibek Omarov | 885cda971d | |
Alibek Omarov | ef0b227967 | |
Alibek Omarov | 19a785a98a | |
Alibek Omarov | b96bfcfe7a | |
Alibek Omarov | 412c635499 | |
Alibek Omarov | da5ec56567 | |
Alibek Omarov | e664e80b27 | |
Alibek Omarov | d177b6f528 | |
Alibek Omarov | 2ef3d78d9f | |
Alibek Omarov | 5ea5e1167b | |
Alibek Omarov | 116a605248 | |
Alibek Omarov | 9690fe9334 | |
Alibek Omarov | a81fa84321 | |
Alibek Omarov | 5ef97ae99e | |
Alibek Omarov | d667845777 | |
Alibek Omarov | b12b2aaf79 | |
Alibek Omarov | 6b62f9c1b9 | |
Alibek Omarov | ba1cf25314 | |
Alibek Omarov | fb2ba6a6e2 | |
Alibek Omarov | fb6e310eab | |
Alibek Omarov | bcbd1a59c6 | |
Alibek Omarov | 8e45a43ad2 | |
Alibek Omarov | 115ed82c19 | |
Alibek Omarov | 5c1e06ae74 | |
SNMetamorph | f9205825b6 | |
Andrey Akhmichin | 9040c34f48 | |
Andrey Akhmichin | 9e9703e6de | |
Andrey Akhmichin | 6486533355 | |
Andrey Akhmichin | 34160151a4 | |
Andrey Akhmichin | daaaa324bd | |
Andrey Akhmichin | af5c74981b | |
Andrey Akhmichin | 249ce6bca1 | |
Andrey Akhmichin | b648c74815 | |
Andrey Akhmichin | a2d459ae84 | |
Andrey Akhmichin | 573781b45d | |
Andrey Akhmichin | 3299999f3d | |
Alibek Omarov | 91be4f6521 | |
fgsfds | f2f21b24a1 | |
fgsfds | 9ef43a4794 | |
fgsfds | fc02a69686 | |
fgsfds | b10a0dc5c5 | |
fgsfds | e5f0d1557c | |
fgsfds | d8a3f4850a | |
fgsfds | 882d957b5c | |
fgsfds | afd1727898 | |
fgsfds | 70a73e47a7 | |
fgsfds | fe3f15ad33 | |
fgsfds | 66f625f840 | |
fgsfds | 3e1833722f | |
fgsfds | 4b8e11f561 | |
fgsfds | 0d04c20578 | |
fgsfds | 41c819f3d3 | |
fgsfds | 957154f097 | |
fgsfds | fad506ef03 | |
fgsfds | 9150bbdfd8 | |
fgsfds | aa4e2f0ae4 | |
fgsfds | 2bacc91922 | |
fgsfds | 458aa6d8b8 | |
fgsfds | 6963741020 | |
fgsfds | b55aa982b0 | |
fgsfds | 492481eea8 | |
fgsfds | 76bff9cd4b | |
fgsfds | 47a6be86b1 | |
fgsfds | 287688d985 | |
fgsfds | 610d528042 | |
fgsfds | 89ec39821e | |
fgsfds | 82cfd3ecc3 | |
fgsfds | 5a3e3b3977 | |
fgsfds | 9cf6e421cb | |
fgsfds | 5c56b51044 | |
fgsfds | 577add56f1 | |
fgsfds | adc5aa4659 | |
fgsfds | 5beed5ab29 | |
fgsfds | 34dd52ca90 | |
fgsfds | 6304b51f32 | |
fgsfds | 97a7de3377 | |
fgsfds | 7424b29e56 | |
Alibek Omarov | 3c64d2ad80 | |
Alibek Omarov | 1274fa13c8 | |
Alibek Omarov | 3765686077 | |
SNMetamorph | 9fffd7a270 | |
SNMetamorph | e37c07f44f | |
SNMetamorph | 214a3cce73 | |
Andrey Akhmichin | d738b07660 | |
Ivan Avdeev | 01de5957d8 | |
Ivan 'provod' Avdeev | 6d7fd41494 | |
Ivan 'provod' Avdeev | 21534c044b | |
Ivan 'provod' Avdeev | 62392ac4b6 | |
Ivan 'provod' Avdeev | c1483216ef | |
Ivan 'provod' Avdeev | 78a1b24e11 | |
Ivan 'provod' Avdeev | dc698c16dc | |
NightFox | 8ed23cb40f | |
Ivan Avdeev | d1376a89e4 | |
Ivan Avdeev | c47c314512 | |
Ivan Avdeev | 4f2eb7680b | |
Ivan Avdeev | a284567002 | |
Ivan Avdeev | 58c9a9920e | |
Alibek Omarov | 48ca8f9a70 | |
Alibek Omarov | c565b0a505 | |
NightFox | ed9a06cae1 | |
Ivan 'provod' Avdeev | 8a457a17c2 | |
Alibek Omarov | 474833a3bf | |
Alibek Omarov | 602f23fbdf | |
Ivan Avdeev | bd2bda9a41 | |
Ivan 'provod' Avdeev | 6b1e84308a | |
Ivan 'provod' Avdeev | 59e8a8c4c3 | |
Ivan Avdeev | 149dc7cade | |
LifeKILLED | 2f050a6618 | |
LifeKILLED | f4b0f5016b | |
LifeKILLED | 5fbee4a97a | |
LifeKILLED | 70c52622e7 | |
LifeKILLED | ed69eeb5af | |
Ivan Avdeev | da447d9e5b | |
NightFox | 429fb82f52 | |
Ivan Avdeev | 19603722ed | |
Ivan 'provod' Avdeev | c8e4ce0619 | |
Ivan 'provod' Avdeev | d87690876f | |
Ivan Avdeev | 421c0ea733 | |
Ivan 'provod' Avdeev | 30334db159 | |
Ivan 'provod' Avdeev | 2daa130453 | |
Ivan 'provod' Avdeev | cf5d3d9d47 | |
Ivan 'provod' Avdeev | a118e12e01 | |
Ivan 'provod' Avdeev | ee4def1141 | |
Ivan 'provod' Avdeev | 1fadbce860 | |
Ivan 'provod' Avdeev | e4ad18f220 | |
Ivan 'provod' Avdeev | f2182bb255 | |
Ivan Avdeev | 26ad10483f | |
Ivan 'provod' Avdeev | 1d17e55101 | |
Ivan 'provod' Avdeev | 3e2689b7f8 | |
Ivan 'provod' Avdeev | 9f72a804e0 | |
Ivan 'provod' Avdeev | ce27bdb1b1 | |
Ivan 'provod' Avdeev | cd524c20cf | |
Ivan 'provod' Avdeev | 03efb6ce83 | |
Ivan 'provod' Avdeev | 487c94662a | |
Ivan 'provod' Avdeev | 005b7c84eb | |
Ivan 'provod' Avdeev | 92b1e78d85 | |
Alibek Omarov | 7e9d46689c | |
Ivan 'provod' Avdeev | a5b977c8a3 | |
Ivan 'provod' Avdeev | 41809b8952 | |
Ivan 'provod' Avdeev | 4f6d51c368 | |
Ivan Avdeev | d6d9011dcc | |
Ivan Avdeev | ad5e1b2b86 | |
Ivan Avdeev | 8514e2c7b8 | |
Ivan 'provod' Avdeev | 1a6e967ddb | |
Alibek Omarov | b6347d17c9 | |
Alibek Omarov | 8293bc91d4 | |
Alibek Omarov | fb0f184d6b | |
Alibek Omarov | 58e95c7d6f | |
Alibek Omarov | 7a5381e658 | |
Alibek Omarov | 375c06400c | |
Ivan Avdeev | 55ff27c5d4 | |
Ivan Avdeev | e61b45b8b6 | |
Ivan Avdeev | ac1665558f | |
Ivan Avdeev | 053d26e870 | |
Ivan Avdeev | 604bd702d4 | |
Alibek Omarov | e481c86ba2 | |
Ivan Avdeev | 1f774c6400 | |
Ivan 'provod' Avdeev | 4dd793569c | |
Alibek Omarov | 21b9f07323 | |
Alibek Omarov | 0bff62e696 | |
Alibek Omarov | 858597832d | |
Alibek Omarov | 9b0ac7cb32 | |
Alibek Omarov | 3c27384b6b | |
Alibek Omarov | 1e8c26a527 | |
Alibek Omarov | f4069de7f2 | |
Alibek Omarov | e95161aa14 | |
Ivan Avdeev | eaf8b3c55a | |
Ivan 'provod' Avdeev | 64ac964dfc | |
Ivan 'provod' Avdeev | 218bd0a9c2 | |
Ivan 'provod' Avdeev | e9712f36e3 | |
Alibek Omarov | 0984368a31 | |
Alibek Omarov | f4961d9da7 | |
Alibek Omarov | f42a174482 | |
Alibek Omarov | 13bf607031 | |
Alibek Omarov | 3cfdb1213b | |
Alibek Omarov | d58105d64d | |
Alibek Omarov | 1bdd844860 | |
Alibek Omarov | 11f3d97cd7 | |
Alibek Omarov | fccf044976 | |
Alibek Omarov | c23396f533 | |
Alibek Omarov | 33c9f7118b | |
Alibek Omarov | c741ec223f | |
Alibek Omarov | d6d98bd297 | |
Alibek Omarov | 5e1b5d89f7 | |
Alibek Omarov | a0edfd28b2 | |
Alibek Omarov | 555fd02407 | |
Alibek Omarov | f7f9cfecfc | |
Alibek Omarov | 2aeee59a31 | |
Ivan Avdeev | 780b225735 | |
Ivan Avdeev | a46d82f3b5 | |
Ivan 'provod' Avdeev | 3ecd21a25b | |
Ivan 'provod' Avdeev | c5a1343fc6 | |
Ivan 'provod' Avdeev | 5b59c387c1 | |
Ivan 'provod' Avdeev | 62720a7ed3 | |
Ivan 'provod' Avdeev | 19c4e2a1d8 | |
Alibek Omarov | 12b8965a8c | |
Alibek Omarov | b5b6b8b785 | |
fgsfds | 35e073ceff | |
fgsfds | b2cc96cf0d | |
fgsfds | f7489a3747 | |
fgsfds | 0e7ebf6d44 | |
fgsfds | 69607d7890 | |
fgsfds | 4e87eb068a | |
Alibek Omarov | 03a7c67731 | |
Alibek Omarov | 5ba2449d10 | |
fgsfds | 0ee2fd8a8a | |
fgsfds | 080b9b30a1 | |
fgsfds | 749ac5ed54 | |
fgsfds | 6c8b9af6bb | |
fgsfds | 07922c0239 | |
fgsfds | 1a54ec92e0 | |
fgsfds | 663b574b8b | |
fgsfds | 430c51b71a | |
Ivan 'provod' Avdeev | ea7879bff8 | |
fgsfds | 20bcd03f19 | |
fgsfds | dab959fc32 | |
fgsfds | eff75e5d50 | |
fgsfds | d103f022b4 | |
fgsfds | 72b8246969 | |
Ivan 'provod' Avdeev | 7188711451 | |
fgsfds | 030d05f018 | |
fgsfds | 59cd5493e7 | |
fgsfds | 98a7f6fa3f | |
Ivan Avdeev | 3edcb7c007 | |
fgsfds | 65095df124 | |
fgsfds | ee370ea007 | |
Alibek Omarov | 05016f8639 | |
Alibek Omarov | 12154de6f5 | |
Alibek Omarov | 3fca567b81 | |
Ivan 'provod' Avdeev | 0573186334 | |
Alibek Omarov | 634574f249 | |
fgsfds | f782d444a8 | |
fgsfds | b68def2b9c | |
fgsfds | d944301a60 | |
fgsfds | 15ba932046 | |
fgsfds | b73c16c216 | |
fgsfds | 0ba4ef678c | |
fgsfds | 919d510f63 | |
fgsfds | 6557ac7fb4 | |
Alibek Omarov | 87c307f47e | |
fgsfds | f3e50b5500 | |
fgsfds | 705f252ed8 | |
fgsfds | cb28101732 | |
fgsfds | f87863b8bc | |
fgsfds | 25fb89f717 | |
fgsfds | 36e7856b9c | |
Alibek Omarov | 34b0cdc125 | |
fgsfds | 25a1cb8ce7 | |
Alibek Omarov | a610b1545b | |
Alibek Omarov | 30b698067a | |
Alibek Omarov | f63f1a0dc6 | |
Alibek Omarov | 9cb867a7d4 | |
Alibek Omarov | 00ddd95c27 | |
Alibek Omarov | 0ffd1b9ff1 | |
Alibek Omarov | 2109d49aa3 | |
Alibek Omarov | f910f4896c | |
Alibek Omarov | 6eae3471cf | |
Ivan Avdeev | 5da5a1bc94 | |
Alibek Omarov | c0fa91bec9 | |
Alibek Omarov | ba6dd3c751 | |
Alibek Omarov | fd63018fb5 | |
Alibek Omarov | 2225915702 | |
Alibek Omarov | d14e486721 | |
Ivan Avdeev | 18a7c61505 | |
Ivan 'provod' Avdeev | 51641234ab | |
Ivan 'provod' Avdeev | de6da4f03f | |
Ivan 'provod' Avdeev | c615b9355a | |
Ivan 'provod' Avdeev | 8ec8502a53 | |
Alibek Omarov | 82b6da493a | |
Alibek Omarov | bec0b36bb9 | |
Alibek Omarov | e2c2821191 | |
Alibek Omarov | a19d34035d | |
Alibek Omarov | 77ea03a62c | |
Alibek Omarov | 402a0f129d | |
Ivan Avdeev | 3ebfb72819 | |
Ivan 'provod' Avdeev | 395d5c4fcb | |
Alibek Omarov | d7116afc92 | |
Alibek Omarov | d5fe491c14 | |
Ivan Avdeev | 00732cd0c1 | |
LifeKILLED | 889846f774 | |
LifeKILLED | 1d0ebbcc33 | |
LifeKILLED | b1b644564f | |
Alibek Omarov | 92138428c5 | |
Alibek Omarov | f3ff942ea9 | |
Alibek Omarov | ced6e8869a | |
Alibek Omarov | d7af50ea6c | |
Alibek Omarov | f7d4e5a2ea | |
Alibek Omarov | 2e3788f23d | |
Alibek Omarov | eaf9a9283a | |
Alibek Omarov | ae66291272 | |
Alibek Omarov | 4f78ec01cf | |
Alibek Omarov | be084d5603 | |
Alibek Omarov | aac0be1ab3 | |
Alibek Omarov | 6282acc825 | |
Ivan 'provod' Avdeev | c1cfe1008d | |
Ivan Avdeev | be5e50d50b | |
Ivan Avdeev | 71f7449a8e | |
LifeKILLED | 615a10c005 | |
LifeKILLED | 9ed9eb5451 | |
LifeKILLED | 164259d6b1 | |
Ivan 'provod' Avdeev | 3a87934415 | |
Ivan 'provod' Avdeev | a5abde2162 | |
LifeKILLED | 571fc16c3b | |
LifeKILLED | 73c750020f | |
LifeKILLED | 2627cb97af | |
Ivan 'provod' Avdeev | 3cb9ca0579 | |
Ivan 'provod' Avdeev | 858e3eed55 | |
Alibek Omarov | 39fd30a472 | |
Alibek Omarov | 279e391949 | |
Alibek Omarov | 6df25392b8 | |
Alibek Omarov | 327372e253 | |
Andrey Akhmichin | 801dbaa387 | |
Andrey Akhmichin | ffd5c2d3d0 | |
Alibek Omarov | 84c14b32ec | |
Alibek Omarov | c481e52558 | |
LifeKILLED | c4881f57c9 | |
Ivan Avdeev | 308e0962a3 | |
Ivan Avdeev | ab59393909 | |
Ivan 'provod' Avdeev | 28f40d5ca0 | |
Ivan Avdeev | 9f3735240c | |
Ivan 'provod' Avdeev | 9df38a6487 | |
Ivan 'provod' Avdeev | 8709f668c4 | |
LifeKILLED | 4d370b072c | |
Ivan 'provod' Avdeev | d0fc84b7dd | |
Ivan 'provod' Avdeev | 3b77a84746 | |
Ivan 'provod' Avdeev | 3e194c7c6d | |
Ivan Avdeev | 59b3bbec08 | |
Ivan 'provod' Avdeev | 1ef9526aff | |
Alibek Omarov | b946ed4625 | |
Alibek Omarov | ef1572b15b | |
Alibek Omarov | aaeb18f433 | |
Alibek Omarov | dd1d86c289 | |
Alibek Omarov | 16b162f7bb | |
Alibek Omarov | 500ca54550 | |
Ivan 'provod' Avdeev | fbf2d7096d | |
Ivan 'provod' Avdeev | d96917c693 | |
Alibek Omarov | 5313dc9475 | |
Alibek Omarov | 9c0c1a802c | |
Alibek Omarov | fbedbdca7d | |
Alibek Omarov | 6232e288e1 | |
Alibek Omarov | a6475f530b | |
Alibek Omarov | de84df99f3 | |
Alibek Omarov | a5d5c1f60b | |
Alibek Omarov | 6ac3156a82 | |
Alibek Omarov | 2705e77a4e | |
Alibek Omarov | a09aa31b7a | |
Xav101 | 9466461ce0 | |
Alibek Omarov | 74ce7e9b10 | |
Alibek Omarov | 10481a4ecc | |
Alibek Omarov | acd86ce490 | |
Alibek Omarov | 1119a9ac22 | |
Alibek Omarov | 171c0c8d3b | |
Alibek Omarov | 9b5e0fef01 | |
Alibek Omarov | 2f5e3b0aea | |
Ivan Avdeev | 8d484d9205 | |
Alibek Omarov | ca3b0e6246 | |
Alibek Omarov | eb0459a045 | |
Alibek Omarov | 5d98e13fb8 | |
Alibek Omarov | 113904ea91 | |
Alibek Omarov | 1dc3cc2d57 | |
Alibek Omarov | 15a5975abf | |
Alibek Omarov | 65debeb738 | |
Alibek Omarov | 209a03a12a | |
Alibek Omarov | c28aeb2362 | |
Alibek Omarov | 9152bbf106 | |
Alibek Omarov | 40ba0238f8 | |
Alibek Omarov | 4a3efa511c | |
Alibek Omarov | 2479d28cd5 | |
Alibek Omarov | 787d3bc5dd | |
Alibek Omarov | 0bec78a958 | |
Alibek Omarov | e305b81df0 | |
Alibek Omarov | 4cb109abe0 | |
Alibek Omarov | 49a65edfc3 | |
Alibek Omarov | c6bfc82019 | |
Alibek Omarov | a4865fd2fc | |
Alibek Omarov | 4bbd0cc404 | |
Alibek Omarov | 4684f174ee | |
Alibek Omarov | 34eb258cae | |
Alibek Omarov | b4c0ccbede | |
Alibek Omarov | 51b5d7a41d | |
Alibek Omarov | 15846a8ea8 | |
Alibek Omarov | e694081626 | |
Alibek Omarov | cb9605430d | |
Alibek Omarov | 80507b2eca | |
Alibek Omarov | ed47346ef1 | |
Alibek Omarov | 75ccd2283b | |
Alibek Omarov | 409edf5a70 | |
Alibek Omarov | d047dfc319 | |
Alibek Omarov | 13ed2742b2 | |
Alibek Omarov | 03a3fb83b6 | |
Alibek Omarov | df1c9a5029 | |
Alibek Omarov | 07e622f224 | |
Alibek Omarov | aa3a0fa392 | |
Alibek Omarov | c1287b3950 | |
Alibek Omarov | e5763e2e9a | |
Alibek Omarov | 42a3c7b059 | |
Alibek Omarov | e621c98602 | |
Alibek Omarov | eb7eb4acbc | |
Alibek Omarov | e5b32fe8ac | |
Alibek Omarov | 52061621ac | |
Alibek Omarov | 339711c3c7 | |
Alibek Omarov | 256fe7ede9 | |
Alibek Omarov | 2febe632c5 | |
Alibek Omarov | c454e37064 | |
Alibek Omarov | fe1aba3561 | |
Alibek Omarov | 41aa867a21 | |
Alibek Omarov | b36ebc294f | |
Alibek Omarov | 3d71e5d111 | |
Alibek Omarov | ac59f25375 | |
Alibek Omarov | 3393e2d95c | |
Alibek Omarov | e1ea3387ee | |
Alibek Omarov | 071638794a | |
Alibek Omarov | 953dd3d1a7 | |
Andrey Akhmichin | 12bb0ca44b | |
MoeMod Server #2 | 499cd48e83 | |
Andrey Akhmichin | 444e08f59a | |
Andrey Akhmichin | 9450c08eec | |
Alibek Omarov | 18e68f1ab3 | |
Andrey Akhmichin | 7555fefc18 | |
Andrey Akhmichin | f4fb8b4ac2 | |
Andrey Akhmichin | 0d5cd89144 | |
Andrey Akhmichin | e273e09fc9 | |
Alibek Omarov | 327017421c | |
Alibek Omarov | 6e179346c9 | |
Ivan Avdeev | 3f6171bfa9 | |
Alibek Omarov | ee218f36e0 | |
Alibek Omarov | f3400c983e | |
Alibek Omarov | 9397301a73 | |
Alibek Omarov | f1ec612819 | |
Alibek Omarov | 08f834cd82 | |
Alibek Omarov | 48c17d08d9 | |
Alibek Omarov | f20fddee1c | |
Alibek Omarov | 754d55beef | |
Alibek Omarov | cd813bbfbe | |
Alibek Omarov | 07afbd64d4 | |
Alibek Omarov | af7d6f6fa8 | |
Alibek Omarov | cb0f513bf0 | |
Alibek Omarov | a3ef6c955c | |
Alibek Omarov | 60e7a7aa23 | |
Alibek Omarov | e1431e1040 | |
Alibek Omarov | b794f2fda0 | |
Alibek Omarov | 934d9ba69a | |
Alibek Omarov | 9e54ddfd55 | |
Alibek Omarov | a86a24d33d | |
Alibek Omarov | fe9ed0ac9b | |
Alibek Omarov | 18c94b6ec4 | |
SNMetamorph | 8fa0290e25 | |
SNMetamorph | 080cd146dd | |
SNMetamorph | b1d910a3a5 | |
SNMetamorph | 840283d6e5 | |
SNMetamorph | d72481e5ac | |
SNMetamorph | dbe9309475 | |
Alibek Omarov | 9fa4de6ee8 | |
Alibek Omarov | fd3c5e8384 | |
Alibek Omarov | d50ed1c087 | |
Alibek Omarov | e48133bf4b | |
Alibek Omarov | ea3bfd969c | |
Alibek Omarov | 7469d6a248 | |
Alibek Omarov | 859f36afce | |
Alibek Omarov | 436a788ac8 | |
Velaron | 5098e24806 | |
Alibek Omarov | 1d8acc16f1 | |
Alibek Omarov | 802c7a86a9 | |
Alibek Omarov | 406eb828da | |
Alibek Omarov | 0e9106685b | |
Alibek Omarov | 9b001987e9 | |
Alibek Omarov | 5c2c02c317 | |
Alibek Omarov | 21c898d796 | |
Alibek Omarov | e48b708fa6 | |
Alibek Omarov | ccf7619ae5 | |
Alibek Omarov | eabbd0061f | |
Alibek Omarov | 7d0d6b8e0d | |
Alibek Omarov | eb36fe0155 | |
Alibek Omarov | 9381a40506 | |
SNMetamorph | a19270a0dc | |
SNMetamorph | c34ce2d9e1 | |
SNMetamorph | 58465c3727 | |
Andrey Akhmichin | 177ed2c603 | |
Andrey Akhmichin | 7bb994f7bc | |
Andrey Akhmichin | 0c4f35e2d0 | |
Andrey Akhmichin | 3287501f97 | |
Andrey Akhmichin | 2454594a18 | |
Alibek Omarov | 4daab23e2d | |
Alibek Omarov | 51161004eb | |
Alibek Omarov | 6477f1656e | |
Alibek Omarov | 270e2a76a8 | |
Alibek Omarov | c61442e960 | |
Alibek Omarov | d0928af355 | |
Alibek Omarov | 674093517e | |
Alibek Omarov | ebf3877cda | |
Alibek Omarov | e97310c441 | |
Alibek Omarov | cbe3e608b6 | |
Alibek Omarov | f30f23ba51 | |
Alibek Omarov | 1ba117a8e9 | |
Alibek Omarov | d9a245dcb5 | |
Alibek Omarov | 9cbf5ab6a6 | |
Alibek Omarov | c9e4e62474 | |
Alibek Omarov | aa6a1db0a9 | |
Alibek Omarov | e9d66be10a | |
Alibek Omarov | 8b6f12418e | |
Alibek Omarov | 7013d447ca | |
Alibek Omarov | 93b2f535e2 | |
Alibek Omarov | 591d572870 | |
SNMetamorph | 3ab749cc2e | |
SNMetamorph | 084fac3606 | |
Alibek Omarov | f377461fdf | |
Ivan 'provod' Avdeev | b112567552 | |
Ivan 'provod' Avdeev | c94314d15a | |
Ivan Avdeev | 096f123e85 | |
SNMetamorph | a2971ce939 | |
SNMetamorph | 65671d8788 | |
Andrey Akhmichin | 809d5f1aa8 | |
SNMetamorph | 49fc6143ab | |
SNMetamorph | 8717843333 | |
SNMetamorph | f6d8996968 | |
Alibek Omarov | 9389305072 | |
Alibek Omarov | b6bd4bc6f8 | |
Alibek Omarov | 4c6fbafd20 | |
Velaron | 43c6175918 | |
Velaron | fcd741e2b8 | |
Velaron | 89807250e5 | |
Velaron | 24f7db19d8 | |
SNMetamorph | 49d93c0e76 | |
SNMetamorph | 707c93c32c | |
SNMetamorph | e204f05726 | |
SNMetamorph | 3bd8ad50d2 | |
Ivan 'provod' Avdeev | cc85a191f1 | |
Ivan Avdeev | 2aeac9ac4a | |
Ivan Avdeev | b8bfe3b3a8 | |
Andrey Akhmichin | 3488d4e65f | |
Alibek Omarov | 3da736a1eb | |
Alibek Omarov | e30c61c0e2 | |
Alibek Omarov | 64e97124c3 | |
Alibek Omarov | 46979419ae | |
Alibek Omarov | 30d9b6d844 | |
Alibek Omarov | 88045ce3be | |
Alibek Omarov | dd881d3da9 | |
Alibek Omarov | 76d0608ee1 | |
Alibek Omarov | a894ca60c6 | |
Alibek Omarov | 023f6712f9 | |
Alibek Omarov | 42740149ac | |
Alibek Omarov | 7b74015c4d | |
Alibek Omarov | 57c71efe53 | |
Alibek Omarov | 45de874598 | |
Alibek Omarov | aa702f0678 | |
Alibek Omarov | 927dccc71d | |
Alibek Omarov | c2a24fbbce | |
SNMetamorph | ae94a6aeba | |
Alibek Omarov | e9da43666c | |
Ivan Avdeev | e5abf365dd | |
Ivan 'provod' Avdeev | 45d5565898 | |
Ivan Avdeev | 9de9620135 | |
Ivan 'provod' Avdeev | df2546514e | |
Ivan Avdeev | 9ddf9c243b | |
Ivan Avdeev | 8849ebfe75 | |
Ivan Avdeev | 09823beed8 | |
Ivan Avdeev | d49b0907b9 | |
Ivan Avdeev | 5d5b595529 | |
Ivan Avdeev | f2697fc7e6 | |
Alibek Omarov | d27dd68072 | |
Alibek Omarov | b1ee27a3f3 | |
SNMetamorph | 32372654c2 | |
Alibek Omarov | 17d0b19f9e | |
Alibek Omarov | d13f7f06e4 | |
Alibek Omarov | f469b56b93 | |
Alibek Omarov | ef74f86ce2 | |
Alibek Omarov | 616cbdb1eb | |
Alibek Omarov | 0a49e69818 | |
Alibek Omarov | adb8ec1da8 | |
SNMetamorph | 5d73c6cb84 | |
SNMetamorph | afa1d429fe | |
SNMetamorph | d1309c3aeb | |
SNMetamorph | b35cf6e30c | |
SNMetamorph | 8cbe0e5b30 | |
Andrey Akhmichin | c1fe547925 | |
Ivan Avdeev | f607be0831 | |
Ivan Avdeev | 7d591c46dd | |
Ivan Avdeev | 84cdbdb331 | |
Ivan 'provod' Avdeev | f5779956c9 | |
Ivan 'provod' Avdeev | 9fded1e4ca | |
Andrey Akhmichin | 1064b41ab2 | |
Andrey Akhmichin | 2a6c2e5db4 | |
Bien Pham | 816337a7bb | |
Andrey Akhmichin | d237114962 | |
Ivan Avdeev | 3f01b95459 | |
Ivan Avdeev | 31a1aef6ab | |
Ivan 'provod' Avdeev | a5d5167f1d | |
Ivan 'provod' Avdeev | c2e4f199ec | |
Ivan 'provod' Avdeev | 6cc8bb2f46 | |
Ivan 'provod' Avdeev | 2f45e38e62 | |
Ivan 'provod' Avdeev | 1500cea931 | |
Ivan 'provod' Avdeev | 556440df27 | |
Ivan 'provod' Avdeev | 6f80bc0015 | |
Ivan Avdeev | 42b909fdc7 | |
Andrey Akhmichin | c1ca2c1a95 | |
SNMetamorph | 44a43c2c09 | |
SNMetamorph | ee8098839e | |
NightFox | af8702ecb3 | |
Ivan Avdeev | c2cf738483 | |
Ivan 'provod' Avdeev | 2252731073 | |
Ivan 'provod' Avdeev | c1cc5f56f6 | |
Ivan 'provod' Avdeev | dcc96fe7ed | |
Ivan 'provod' Avdeev | 5600ce7569 | |
Ivan 'provod' Avdeev | d4114b8423 | |
Alibek Omarov | 305b2579eb | |
Ivan Avdeev | b63c328ed5 | |
Ivan Avdeev | ca296d7a4e | |
Ivan Avdeev | 141cc5de64 | |
Ivan Avdeev | 7f80985124 | |
Ivan Avdeev | ecac9a1f48 | |
Ivan Avdeev | cb406f14c5 | |
Ivan 'provod' Avdeev | cb0d09557d | |
Ivan 'provod' Avdeev | f2f712b1a8 | |
Ivan 'provod' Avdeev | c6d29213ec | |
Ivan 'provod' Avdeev | f7c04760e3 | |
Ivan Avdeev | 99489cf05c | |
Ivan 'provod' Avdeev | 09b0e0f8ff | |
Ivan Avdeev | 9c679c39b8 | |
Ivan Avdeev | 9478c870e3 | |
Ivan Avdeev | 9366a6ffda | |
Ivan Avdeev | 3aa9b4bf3c | |
Alibek Omarov | 1a09d297ee | |
Alibek Omarov | d45e6e0ad1 | |
Alibek Omarov | 2d2523df4a | |
Alibek Omarov | 5a0fcfffb0 | |
Ivan 'provod' Avdeev | 78ec2e2c93 | |
Ivan Avdeev | e849754fae | |
Ivan Avdeev | e506158ac1 | |
Ivan Avdeev | 5d37985ec5 | |
Alibek Omarov | f252161d90 | |
Alibek Omarov | e0216e2658 | |
Alibek Omarov | 0f2bb5720b | |
Ivan 'provod' Avdeev | 3f52f46f7d | |
Alibek Omarov | 0621e365ff | |
Alibek Omarov | 8ea455def7 | |
Alibek Omarov | 8cf822c426 | |
Alibek Omarov | 4a009c1c2c | |
Alibek Omarov | 360dc4f7ed | |
Alibek Omarov | ffe43e1f22 | |
Alibek Omarov | a52d901f25 | |
Alibek Omarov | 5bae2f06ad | |
Alibek Omarov | 69b0954007 | |
Alibek Omarov | 0645402946 | |
Владислав Сухов | c59b244d04 | |
Alibek Omarov | 5678d9a253 | |
dettlaff | a520d245a6 | |
Alibek Omarov | b56f6fa330 | |
Alibek Omarov | f141869ce3 | |
Alibek Omarov | 807f3852bd | |
Alibek Omarov | 084089b919 | |
Alibek Omarov | f571a41cf3 | |
Alibek Omarov | 686a966ff7 | |
Alibek Omarov | c29eb458ea | |
Alibek Omarov | 234c843f60 | |
Alibek Omarov | 7ed0499aa9 | |
Alibek Omarov | 401b145040 | |
Alibek Omarov | 3853ff5435 | |
Alibek Omarov | 744c6b2680 | |
Alibek Omarov | 030a17fc58 | |
Alibek Omarov | b1e2e84a11 | |
Alibek Omarov | 12a6088912 | |
Alibek Omarov | fe9f3f78a0 | |
Alibek Omarov | 327eb330ed | |
Alibek Omarov | 470121512a | |
Alibek Omarov | dedc144b8b | |
Alibek Omarov | 6d37398fad | |
Alibek Omarov | 3c8fe508f0 | |
Alibek Omarov | 8ffb3aac8a | |
Alibek Omarov | 0ed9391969 | |
Alibek Omarov | e54289f811 | |
Alibek Omarov | 17b091e5a9 | |
Alibek Omarov | 61c142e2db | |
Alibek Omarov | 7e664679a0 | |
Andrey Akhmichin | fd152e82e8 | |
Alibek Omarov | 0c50e43663 | |
Alibek Omarov | 7a2ac4a9c0 | |
Andrey Akhmichin | e6bb9d980d | |
Alibek Omarov | 45cc7e5bcc | |
Alibek Omarov | 4be4870982 | |
Alibek Omarov | 19c2061831 | |
Alibek Omarov | 3a8c58d192 | |
Alibek Omarov | 24763f9b07 | |
Alibek Omarov | 0d7a2e7bad | |
Alibek Omarov | 82ab06efdd | |
Alibek Omarov | 4110ee0928 | |
Alibek Omarov | 4b05cf4399 | |
Alibek Omarov | f29a9f5f58 | |
Alibek Omarov | 28001ea150 | |
Alibek Omarov | f633b3dbf6 | |
Alibek Omarov | bebfa611fc | |
Alibek Omarov | 3e9f2df2bf | |
Alibek Omarov | fce8afabfb | |
Alibek Omarov | 9d49985100 | |
Alibek Omarov | a7d4cafe10 | |
Alibek Omarov | ca2a6635b6 | |
Alibek Omarov | 7f1bb9b4a6 | |
Alibek Omarov | 7341a6b020 | |
Alibek Omarov | ac05acf6dc | |
Alibek Omarov | 3e1db432df | |
Alibek Omarov | 3c682507e7 | |
SNMetamorph | e9ae6d08b5 | |
Alibek Omarov | f435a81c97 | |
Alibek Omarov | cb34c23844 | |
SNMetamorph | 9f9141823a | |
Владислав Сухов | d3437c70bd | |
Alibek Omarov | 8630ef2c67 | |
Alibek Omarov | 0b50678912 | |
Alibek Omarov | 22ff45f5d0 | |
Alibek Omarov | 905bbf1515 | |
Alibek Omarov | 88c1b1400d | |
SNMetamorph | 8e48a98d48 | |
SNMetamorph | 76dbefb9ec | |
Alibek Omarov | 327dcc0293 | |
Alibek Omarov | e6c55107c7 | |
Alibek Omarov | c5dbbea9ef | |
SNMetamorph | 74707551ae | |
SNMetamorph | 2f5f5ef0a6 | |
SNMetamorph | f7dc9d8e72 | |
Alibek Omarov | 238162bb79 | |
Alibek Omarov | 1fda8753bd | |
SNMetamorph | a688bed79f | |
SNMetamorph | b0ff51d5a0 | |
SNMetamorph | 68f633e9cd | |
SNMetamorph | a520af42e8 | |
SNMetamorph | 0a6885e02d | |
SNMetamorph | aa5a509316 | |
SNMetamorph | 97879430e9 | |
SNMetamorph | ae97eae42f | |
SNMetamorph | c5d7e3c783 | |
SNMetamorph | 9bcd36cc24 | |
SNMetamorph | c6881a425f | |
SNMetamorph | 8d0209b122 | |
SNMetamorph | 279894cfd4 | |
SNMetamorph | 169ee14724 | |
SNMetamorph | 8866d5cfd6 | |
SNMetamorph | 3b9a7910d0 | |
SNMetamorph | b5885d4107 | |
SNMetamorph | a254a342b1 | |
SNMetamorph | 0db95d76a8 | |
Alibek Omarov | 69a9211fc9 | |
Alibek Omarov | 44cd03f464 | |
Velaron | 9242a0a510 | |
Velaron | 2b9e050f57 | |
Alibek Omarov | 9d4fe707bb | |
Alibek Omarov | 0d2552c3f6 | |
Alibek Omarov | b3c9637422 | |
Alibek Omarov | 01a3321d63 | |
Alibek Omarov | 5a5e72c424 | |
Alibek Omarov | b8dc7494eb | |
Alibek Omarov | 532cd779a7 | |
Alibek Omarov | d202a6c572 | |
Alibek Omarov | 6e864e4f8f | |
Alibek Omarov | 6ef76fe665 | |
Alibek Omarov | 314672d82c | |
Alibek Omarov | 1d558b33d6 | |
Alibek Omarov | 911385d019 | |
SNMetamorph | 5b97c2135a | |
Alibek Omarov | 365f24e1fe | |
Alibek Omarov | 7157c3b441 | |
Alibek Omarov | 2b8b3e1993 | |
Alibek Omarov | b0a889d1a1 | |
Alibek Omarov | bd1bfea695 | |
Alibek Omarov | a1299e1dfe | |
Alibek Omarov | 1a5a76a201 | |
Alibek Omarov | b072b627a2 | |
Alibek Omarov | 5d18c6d678 | |
Alibek Omarov | 59fba30a52 | |
Alibek Omarov | 193cde83b6 | |
Alibek Omarov | 12bfb8f795 | |
Alibek Omarov | 9ae72dbc47 |
|
@ -1,5 +1,13 @@
|
|||
name: Build & Deploy Engine
|
||||
on: [push, pull_request]
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
- 'ref/vk/data/**'
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
- 'ref/vk/data/**'
|
||||
jobs:
|
||||
# cleanup:
|
||||
# runs-on: self-hosted
|
||||
|
@ -13,27 +21,34 @@ jobs:
|
|||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-18.04
|
||||
- os: ubuntu-20.04
|
||||
targetos: linux
|
||||
targetarch: amd64
|
||||
- os: ubuntu-18.04
|
||||
- os: ubuntu-20.04
|
||||
targetos: linux
|
||||
targetarch: i386
|
||||
# TODO enable and test ref_vk for it too
|
||||
# - os: ubuntu-aarch64-20.04
|
||||
# targetos: linux
|
||||
# targetarch: aarch64
|
||||
|
||||
# - os: ubuntu-18.04
|
||||
# targetos: android
|
||||
# targetarch: 32
|
||||
# - os: ubuntu-18.04
|
||||
# targetos: android
|
||||
# targetarch: 64
|
||||
# - os: ubuntu-20.04
|
||||
# targetos: android
|
||||
# targetarch: 32
|
||||
# - os: ubuntu-20.04
|
||||
# targetos: android
|
||||
# targetarch: 64
|
||||
|
||||
# - os: ubuntu-18.04
|
||||
# targetos: motomagx
|
||||
# targetarch: armv6
|
||||
# - os: ubuntu-20.04
|
||||
# targetos: motomagx
|
||||
# targetarch: armv6
|
||||
|
||||
# - os: ubuntu-20.04
|
||||
# targetos: nswitch
|
||||
# targetarch: arm64
|
||||
# - os: ubuntu-20.04
|
||||
# targetos: psvita
|
||||
# targetarch: armv7hf
|
||||
- os: windows-latest
|
||||
targetos: win32
|
||||
targetarch: amd64
|
||||
|
@ -41,33 +56,84 @@ jobs:
|
|||
targetos: win32
|
||||
targetarch: i386
|
||||
env:
|
||||
SDL_VERSION: 2.0.14
|
||||
VULKAN_SDK_VERSION: 1.2.176.1
|
||||
SDL_VERSION: 2.26.2
|
||||
VULKAN_SDK_VERSION: 1.3.239
|
||||
GH_CPU_ARCH: ${{ matrix.targetarch }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
ANDROID_SDK_TOOLS_VER: 4333796
|
||||
UPLOADTOOL_ISPRERELEASE: true
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Checkout xash-extras
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: FWGS/xash-extras
|
||||
path: xash-extras
|
||||
|
||||
- name: Install dependencies
|
||||
run: bash scripts/gha/deps_${{ matrix.targetos }}.sh
|
||||
|
||||
- name: Build engine
|
||||
run: bash scripts/gha/build_${{ matrix.targetos }}.sh
|
||||
|
||||
- name: Upload engine (prereleases)
|
||||
run: bash scripts/continious_upload.sh artifacts/*
|
||||
- name: Upload engine (artifacts)
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: artifact-${{ matrix.targetos }}-${{ matrix.targetarch }}
|
||||
path: artifacts/*
|
||||
# See https://github.com/w23/xash3d-fwgs/issues/430
|
||||
# flatpak:
|
||||
# name: "Flatpak"
|
||||
# runs-on: ubuntu-latest
|
||||
# strategy:
|
||||
# matrix:
|
||||
# include:
|
||||
# - app: su.xash.Engine.Compat.i386
|
||||
# container:
|
||||
# image: bilelmoussaoui/flatpak-github-actions:freedesktop-22.08
|
||||
# options: --privileged
|
||||
# env:
|
||||
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
# UPLOADTOOL_ISPRERELEASE: true
|
||||
# steps:
|
||||
# - name: Checkout
|
||||
# uses: actions/checkout@v3
|
||||
# with:
|
||||
# submodules: recursive
|
||||
# - name: Build flatpak (Compat.i386)
|
||||
# uses: FWGS/flatpak-github-actions/flatpak-builder@v5
|
||||
# with:
|
||||
# bundle: ${{ matrix.app }}.flatpak
|
||||
# manifest-path: scripts/flatpak/${{ matrix.app }}.yml
|
||||
# - name: Upload engine (prereleases)
|
||||
# run: bash scripts/continious_upload.sh ${{ matrix.app }}.flatpak
|
||||
|
||||
# Completely disable uplodaing, as it does not make any sense for Vulkan branch for now
|
||||
# release:
|
||||
# name: "Upload releases"
|
||||
# runs-on: ubuntu-latest
|
||||
# needs: [build, flatpak]
|
||||
# if: ${{ github.event_name == 'push' }}
|
||||
# steps:
|
||||
# - name: Remove old release
|
||||
# uses: FWGS/delete-tag-and-release@v0.2.1-dev
|
||||
# with:
|
||||
# tag_name: ${{ github.ref_name == 'master' && 'continuous' || format('continuous-{0}', github.ref_name) }}
|
||||
# delete_release: true
|
||||
# github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
# - name: Fetch artifacts
|
||||
# uses: actions/download-artifact@v3.0.1
|
||||
# with:
|
||||
# path: artifacts/
|
||||
# - name: Repackage binaries and allow GitHub to process removed release for few seconds
|
||||
# run: |
|
||||
# cd artifacts/
|
||||
# for i in artifact-* su.xash.Engine.*; do
|
||||
# mv "$i"/* .
|
||||
# rm -rf "$i"
|
||||
# done
|
||||
# ls -R .
|
||||
# cd ../
|
||||
# sleep 20s
|
||||
# - name: Upload new release
|
||||
# uses: FWGS/action-gh-release@v0.1.15
|
||||
# with:
|
||||
# name: Xash3D FWGS Continuous ${{ github.ref_name }} Build
|
||||
# tag_name: ${{ github.ref_name == 'master' && 'continuous' || format('continuous-{0}', github.ref_name) }}
|
||||
# prerelease: true
|
||||
# token: ${{ secrets.GITHUB_TOKEN }}
|
||||
# files: artifacts/*
|
||||
# draft: false
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
name: Pass through for ignored files
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- '**.md'
|
||||
- 'ref/vk/data/**'
|
||||
pull_request:
|
||||
paths:
|
||||
- '**.md'
|
||||
- 'ref/vk/data/**'
|
||||
jobs:
|
||||
check:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Always pass
|
||||
run: echo "OK"
|
|
@ -60,6 +60,7 @@ Makefile.dep
|
|||
ALL_BUILD.*
|
||||
INSTALL.*
|
||||
ZERO_CHECK.*
|
||||
CMakeLists.txt
|
||||
|
||||
# Visual Studio
|
||||
*.obj
|
||||
|
@ -216,7 +217,7 @@ publish/
|
|||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
# TODO: Comment the next line if you want to checkin your web deploy settings
|
||||
# TODO: Comment the next line if you want to checkin your web deploy settings
|
||||
# but database connection strings (with potential passwords) will be unencrypted
|
||||
*.pubxml
|
||||
*.publishproj
|
||||
|
@ -338,3 +339,7 @@ core
|
|||
*.code-workspace
|
||||
.history/*
|
||||
.cache/*
|
||||
enc_temp_folder/
|
||||
|
||||
# KDevelop4
|
||||
*.kdev4
|
||||
|
|
|
@ -1,16 +1,21 @@
|
|||
[submodule "mainui"]
|
||||
path = mainui
|
||||
url = https://github.com/zgdump/mainui_cpp
|
||||
branch = vk_menu
|
||||
path = 3rdparty/mainui
|
||||
url = https://github.com/FWGS/mainui_cpp
|
||||
[submodule "ref_gl/nanogl"]
|
||||
path = ref_gl/nanogl
|
||||
path = 3rdparty/nanogl
|
||||
url = https://github.com/FWGS/nanogl
|
||||
[submodule "ref_gl/gl-wes-v2"]
|
||||
path = ref_gl/gl-wes-v2
|
||||
path = 3rdparty/gl-wes-v2
|
||||
url = https://github.com/FWGS/gl-wes-v2
|
||||
[submodule "ref_gl/gl4es"]
|
||||
path = ref_gl/gl4es
|
||||
path = 3rdparty/gl4es/gl4es
|
||||
url = https://github.com/ptitSeb/gl4es
|
||||
[submodule "vgui_support"]
|
||||
path = vgui_support
|
||||
path = 3rdparty/vgui_support
|
||||
url = https://github.com/FWGS/vgui_support
|
||||
[submodule "opus"]
|
||||
path = 3rdparty/opus/opus
|
||||
url = https://github.com/xiph/opus
|
||||
[submodule "3rdparty/xash-extras"]
|
||||
path = 3rdparty/extras/xash-extras
|
||||
url = https://github.com/FWGS/xash-extras
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
#! /usr/bin/env python
|
||||
# encoding: utf-8
|
||||
|
||||
import os
|
||||
|
||||
def options(opt):
|
||||
pass
|
||||
|
||||
def configure(conf):
|
||||
if not conf.path.find_dir('xash-extras'):
|
||||
conf.fatal('Can\'t find xash-extras submodule.')
|
||||
return
|
||||
|
||||
conf.load('zip')
|
||||
|
||||
def build(bld):
|
||||
srcdir = bld.path.find_dir('xash-extras')
|
||||
|
||||
if bld.env.DEST_OS in ['android']:
|
||||
install_path = bld.env.PREFIX
|
||||
else:
|
||||
install_path = os.path.join(bld.env.SHAREDIR, bld.env.GAMEDIR)
|
||||
|
||||
bld(features='zip',
|
||||
name = 'extras.pk3',
|
||||
files = srcdir.ant_glob('**/*'),
|
||||
relative_to = srcdir,
|
||||
compresslevel = 0,
|
||||
install_path = install_path)
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 853f633be18892499a86e7f57fecf34640bd64f2
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 7ba4631bf5e921284100d10923b6980af66d98e8
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 5226f5f9370eebe874dae0525ad5d878a3b66faf
|
|
@ -0,0 +1,24 @@
|
|||
#! /usr/bin/env python
|
||||
# encoding: utf-8
|
||||
|
||||
import os
|
||||
|
||||
def options(opt):
|
||||
pass
|
||||
|
||||
def configure(conf):
|
||||
if not conf.path.find_dir('gl4es') or not conf.path.find_dir('gl4es/src'):
|
||||
conf.fatal('Can\'t find gl4es submodule. Run `git submodule update --init --recursive`.')
|
||||
return
|
||||
|
||||
def build(bld):
|
||||
gl4es_srcdir = bld.path.find_node('gl4es/src')
|
||||
|
||||
bld.stlib(source = gl4es_srcdir.ant_glob(['gl/*.c', 'gl/*/*.c', 'glx/hardext.c']),
|
||||
target = 'gl4es',
|
||||
features = 'c',
|
||||
includes = ['gl4es/src', 'gl4es/src/gl', 'gl4es/src/glx', 'gl4es/include'],
|
||||
defines = ['NOX11', 'NO_GBM', 'NO_INIT_CONSTRUCTOR', 'DEFAULT_ES=2', 'NOEGL', 'EXTERNAL_GETPROCADDRESS=GL4ES_GetProcAddress', 'NO_LOADER', 'STATICLIB'],
|
||||
cflags = ['-w', '-fvisibility=hidden', '-std=gnu99'],
|
||||
subsystem = bld.env.MSVC_SUBSYSTEM,
|
||||
export_includes = '.')
|
|
@ -0,0 +1 @@
|
|||
Subproject commit e456555cf159d2e858694b53fa92717c84e8870e
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 6b6a947ee0c32abceea3e111364b0225af36df61
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 8cf872a186b96085b1bb3a547afd598354ebeb87
|
|
@ -0,0 +1,40 @@
|
|||
#! /usr/bin/env python
|
||||
# encoding: utf-8
|
||||
|
||||
import os
|
||||
|
||||
def options(opt):
|
||||
pass
|
||||
|
||||
def configure(conf):
|
||||
if not conf.path.find_dir('opus') or not conf.path.find_dir('opus/src'):
|
||||
conf.fatal('Can\'t find opus submodule. Run `git submodule update --init --recursive`.')
|
||||
return
|
||||
|
||||
# TODO: ARM/x86 intrinsics detection
|
||||
# TODO: maybe call autotools/cmake/meson instead?
|
||||
|
||||
def build(bld):
|
||||
sources = bld.path.ant_glob([
|
||||
'opus/src/*.c',
|
||||
'opus/celt/*.c',
|
||||
'opus/silk/*.c',
|
||||
'opus/silk/float/*.c'
|
||||
], excl = [
|
||||
'opus/src/repacketizer_demo.c',
|
||||
'opus/src/opus_demo.c',
|
||||
'opus/src/opus_compare.c',
|
||||
'opus/celt/opus_custom_demo.c'
|
||||
])
|
||||
includes = ['opus/include/', 'opus/celt/', 'opus/silk/', 'opus/silk/float/']
|
||||
defines = ['USE_ALLOCA', 'OPUS_BUILD', 'FLOAT_APPROX', 'PACKAGE_VERSION="1.3.1"', 'CUSTOM_MODES']
|
||||
|
||||
bld.stlib(
|
||||
source = sources,
|
||||
target = 'opus',
|
||||
features = 'c',
|
||||
includes = includes,
|
||||
defines = defines,
|
||||
subsystem = bld.env.MSVC_SUBSYSTEM,
|
||||
export_includes = ['opus/include/']
|
||||
)
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 521cf5cb6c3ee0804e5478d8858ec3fba67c1377
|
|
@ -1,3 +1,42 @@
|
|||
# Specific instructions for this fork
|
||||
|
||||
## Introduction
|
||||
1. This fork's only concern is the `ref_vk` Vulkan/RT renderer. Engine and other renderers issues and functionality are absolutely out of scope, unless directly and specifically related to `ref_vk`.
|
||||
2. Primary focus is Ray Tracing with PBR materials. "Traditional" (triangle rasterization) mode is low proirity and has quite a few known issues and deficiencies.
|
||||
3. The primary development branch is `vulkan`, it should contain the latest working and stable code. Other branches (including `master`) are not supported.
|
||||
4. Check out the upstream xash3d-fwgs CONTRIBUTING.md too.
|
||||
|
||||
## Reporting issues
|
||||
1. Precondition: you're supposed to know how to build and run stuff manually. It is not ready to be used by non-developers.
|
||||
2. This is a very actively developing project. There are lots of known issues. Search them first.
|
||||
3. Run with `-dev 2 -log -vkdebug -vkvalidate -vkverboselogs` and provide `engine.log`.
|
||||
4. Specify detailed steps to reproduce. A savefile might be helpful too.
|
||||
5. Although it is deducible from the log, provide the following information explicitly: map, location, OS, GPU, driver version.
|
||||
6. Attach a screenshot if possible (i.e. if it is not a crash at init time)
|
||||
|
||||
## Contributing code
|
||||
We are very glad to hear that you want to help. And there are certainly quite a few issues that could be worked on in parallel.
|
||||
The renderer code is being mostly written as a for-fun-only hobby project by a single person who has neither mental capacity nor time to make and maintain a comprehensive documentation or development structure.
|
||||
Making it a collaboration effort with multiple active participants would require a completely different approach to development, communication, and progress tracking. We might or might not be able to get there eventually.
|
||||
|
||||
That said, we are still happy to hear that you'd like to help. Your involvement might be instrumental to reorganize and allow more collaborators.
|
||||
|
||||
Strongly suggested checklist for contributing anything, **before you start writing any code that you'd like to land here**:
|
||||
1. Find an existing issue (e.g. with `good first issue` label), or suggest your own.
|
||||
2. Let us know that you'd want to work on it, e.g. by leaving a comment on it. **Why:** any given issue might be stale, no longer relevant, being actively worked on as part of something else, or conflicting with some other approach being deliberated.
|
||||
3. Work with us on a design review for the issue. **Why:** this is live C codebase, it is rather fragile and is constantly changing. There are no good practices or stable building blocks. It is also a bit idiosyncratic in places. We just know more context about where are we going to, and where we might be heading. You might also get into surprising conflicts with things that we're working on. There are unfortunately no stable scaffolding or guardrails that would allow for easy independent collaboration yet. Working on a design review means that we'll suggest a compatible way of doing things, and will schedule our work to minimize conflicts with yours.
|
||||
4. Open a draft PR as early as possible, even if it is not ready yet. That way we can coordinate effort, suggest things and anwer any questions.
|
||||
|
||||
## Code and PR
|
||||
1. Do not worry that much about code style. Be reasonable, try to either imitate the surrounding code (which has no strict style yet), or follow upstream recommendations listed below under `Code style` section.
|
||||
2. Try to limit your changes, e.g. don't re-format lines which are not crucial to your change.
|
||||
3. Ping us in the PR if you're not hearing any feedback for a couple of days. I'm usually way too busy *with life* to be on the internets all the time, but a little nudge might be able to allocate some attention.
|
||||
|
||||
|
||||
---------------------------------------------
|
||||
# UPSTREAM XASH3D-FWGS CONTRIBUTING.md FOLLOWS
|
||||
---------------------------------------------
|
||||
|
||||
## If you are reporting bugs
|
||||
|
||||
1. Check you are using latest version. You can build latest Xash3D FWGS for yourself, look to README.md.
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
# Bug-compatibility in Xash3D FWGS
|
||||
|
||||
Xash3D FWGS has special mode for games that rely on original engine bugs.
|
||||
|
||||
In this mode, we emulate the behaviour of selected functions that may help running mods relying on engine bugs, but enabling them by default may break majority of other games.
|
||||
|
||||
At this time, we only have implemented GoldSrc bug-compatibility. It can be enabled with `-bugcomp` command line switch.
|
||||
|
||||
## GoldSrc bug-compatibility
|
||||
|
||||
### Emulated bugs
|
||||
|
||||
* `pfnPEntityOfEntIndex` in GoldSrc returns NULL for last player due to incorrect player index comparison
|
||||
|
||||
### Games and mods that require this
|
||||
|
||||
* Counter-Strike: Condition Zero - Deleted Scenes
|
|
@ -0,0 +1,9 @@
|
|||
# Cross-compiling for Windows with Wine
|
||||
|
||||
This can be useful to test engine in Wine without using virtual machines or dual-booting to Windows.
|
||||
|
||||
0. Clone and install https://github.com/mstorsjo/msvc-wine (you can skip CMake part)
|
||||
1. Set environment variable MSVC_WINE_PATH to the path to installed MSVC toolchain
|
||||
2. Pre-load wine: `wineserver -k; wineserver -p; wine64 wineboot`
|
||||
3. Run `./waf configure -T <build-type> --enable-wine-msvc --sdl2=../SDL2_VC`. Configuration step will take more time than usual.
|
||||
4. .. other typical steps to build from console ...
|
|
@ -0,0 +1,10 @@
|
|||
# Debugging your mod using minidump files (Windows only)
|
||||
Minidump files is awesome instrument for debugging your mod after it's being released, or for catch specific crashes which are presented only in one specific configuration, but doesn't happens in other configurations or even on developer machine. It contains a lot of information useful for debugging, and therefore it size is not so small: around hundreds or even thousands of megabytes. But this is not a problem, since minidump files compresses very effectively using common algorithms.
|
||||
There are short algorithm, explaining how to use this debugging instrument:
|
||||
|
||||
1. User starts your mod with `-minidumps` startup parameter
|
||||
2. Finally, crash happened on user's machine, and minidump file being written. This file has `.mdmp` extension and located in same folder, where mod folder located
|
||||
3. User packs this minidump file to .zip/.7z archive, and somehow sends it to developer
|
||||
4. Developer just opens minidump file in Visual Studio, then a virtual debugging session is opened and now reasons of crash is pretty easy to detect: you can see call stack, local function variables and global variables, information about exception and a lot of other information
|
||||
|
||||
You can find more information about minidumps in this [awesome article](https://learn.microsoft.com/en-us/windows/win32/dxtecharts/crash-dump-analysis?source=recommendations#writing-a-minidump).
|
|
@ -0,0 +1,24 @@
|
|||
# Developers donation page
|
||||
|
||||
On this page you can find links where you can support each developer individually, who has provided public sponsorship information.
|
||||
|
||||
### [a1batross](https://github.com/a1batross)
|
||||
|
||||
* Initial Xash3D SDL2/Linux port author, Xash3D FWGS engine maintainer, creator of non-commercial Flying With Gauss organization.
|
||||
* Boosty page: https://boosty.to/a1ba
|
||||
|
||||
### [nekonomicon](https://github.com/nekonomicon)
|
||||
|
||||
* [hlsdk-portable](https://github.com/FWGS/hlsdk-portable), [mdldec](../utils/mdldec), [opensource-mods.md](opensource-mods.md) maintainer and Xash3D FWGS [contributor](https://github.com/FWGS/xash3d-fwgs/commits?author=nekonomicon) (*BSD/clang port, PNG support, etc).
|
||||
* Boosty page: https://boosty.to/nekonomicon
|
||||
|
||||
### [Velaron](https://github.com/Velaron)
|
||||
* [cs16-client](https://github.com/Velaron/cs16-client) & [tf15-client](https://github.com/Velaron/tf15-client) maintainer and Xash3D FWGS [contributor](https://github.com/FWGS/xash3d-fwgs/commits?author=Velaron) (Android port, voice chat, etc).
|
||||
* BuyMeACoffee page: https://www.buymeacoffee.com/velaron
|
||||
|
||||
### [SNMetamorph](https://github.com/SNMetamorph)
|
||||
* [PrimeXT](https://github.com/SNMetamorph/PrimeXT) & [GoldSrc Monitor](https://github.com/SNMetamorph/goldsrc-monitor) maintainer and Xash3D FWGS [contributor](https://github.com/FWGS/xash3d-fwgs/commits?author=SNMetamorph) (Windows port, voice chat, etc).
|
||||
* BTC: `16GAzK3qei5AwBW7sggXp3yNcFHBtdpxXj`
|
||||
* ETH (ERC20): `0xb580eeca9756e3881f9d6d026e28db28eb72a383`
|
||||
* USDT (ERC20): `0xb580eeca9756e3881f9d6d026e28db28eb72a383`
|
||||
* USDC (ERC20): `0xb580eeca9756e3881f9d6d026e28db28eb72a383`
|
|
@ -0,0 +1,150 @@
|
|||
# There are few new commands availiable in xash3d fork:
|
||||
|
||||
## Commands:
|
||||
### ent_create
|
||||
Create entity with specified classname and key/values
|
||||
|
||||
`ent_create <classname> <key> <value> <key> <value> ...`
|
||||
|
||||
for example:
|
||||
|
||||
`ent_create monster_zombie targetname zomb1`
|
||||
|
||||
after creating entity, ent_last_xxx cvars are set to new entity and ent_last_cb called, look at ent_getvars description
|
||||
|
||||
### ent_fire
|
||||
|
||||
Make some actions on entity
|
||||
|
||||
`ent_fire <pattern> <command> <args>`
|
||||
Availiavle commands:
|
||||
* Set fields (Only set entity field, does not call any functions):
|
||||
* health
|
||||
* gravity
|
||||
* movetype
|
||||
* solid
|
||||
* rendermode
|
||||
* rendercolor (vector)
|
||||
* renderfx
|
||||
* renderamt
|
||||
* hullmin (vector)
|
||||
* hullmax (vector)
|
||||
* Actions
|
||||
* rename: set entity targetname
|
||||
* settarget: set entity target (only targetnames)
|
||||
* setmodel: set entity model (does not update)
|
||||
* set: set key/value by server library
|
||||
* See game FGD to get list.
|
||||
* command takes two arguments
|
||||
* touch: touch entity by current player.
|
||||
* use: use entity by current player.
|
||||
* movehere: place entity in player fov.
|
||||
* drop2floor: place entity to nearest floor surface
|
||||
* moveup: move entity to 25 units up
|
||||
* moveup (value): move by y axis relatively to specified value
|
||||
* Flags (Set/clear specified flag bit, arg is bit number):
|
||||
* setflag
|
||||
* clearflag
|
||||
* setspawnflag
|
||||
* clearspawnflag
|
||||
|
||||
### ent_info
|
||||
Print information about entity by identificator
|
||||
|
||||
`ent_info <identificator>`
|
||||
|
||||
### ent_getvars
|
||||
Set client cvars containing entity information (useful for [[Scripting]]) and call ent_last_cb
|
||||
|
||||
`ent_getvars <identificator>`
|
||||
|
||||
These cvars are set:
|
||||
```
|
||||
ent_last_name
|
||||
ent_last_num
|
||||
ent_last_inst
|
||||
ent_last_origin
|
||||
ent_last_class
|
||||
```
|
||||
|
||||
### ent_list
|
||||
Print short information about antities, filtered by pattern
|
||||
|
||||
`ent_list <pattern>`
|
||||
|
||||
## Syntax description
|
||||
|
||||
### \<identificator\>
|
||||
|
||||
* !cross: entity under aim
|
||||
* Instance code: !\<number\>_\<seria\l>
|
||||
* set by ent_getvars command
|
||||
* Entity index
|
||||
* targetname pattern
|
||||
|
||||
### \<pattern\>
|
||||
|
||||
Pattern is like identificator, but may filter many entities by classname
|
||||
|
||||
### (vector)
|
||||
|
||||
used by ent_fire command. vector means three float values, entered without quotes
|
||||
|
||||
### key/value
|
||||
|
||||
All entities parameters may be set by specifiing key and value strings.
|
||||
|
||||
Originally, this mechanizm is used in map/bsp format, but it can be used in enttools too.
|
||||
|
||||
Keys and values are passed to server library and processed by entity keyvalue function, setting edict and entity owns parameters.
|
||||
|
||||
If value contains spaces, it must be put in quotes:
|
||||
|
||||
`ent_fire !cross set origin "0 0 0"`
|
||||
|
||||
## Using with scripting
|
||||
|
||||
ent_create and ent_getvars commands are setting cvars on client
|
||||
|
||||
It can be used with ent_last_cb alias that is executed after setting cvars.
|
||||
|
||||
Simple example:
|
||||
|
||||
```
|
||||
ent_create weapon_c4
|
||||
alias ent_last_cb "ent_fire \$ent_last_inst use"
|
||||
```
|
||||
|
||||
Use weapon_c4 after creating it.
|
||||
|
||||
Note that you cannot use many dfferent callbacks at the same time.
|
||||
|
||||
You can set entity name by by pattern and create special script, contatning all callbacks.
|
||||
|
||||
Example:
|
||||
|
||||
example.cfg
|
||||
```
|
||||
alias ent_last_cb exec entity_cb.cfg
|
||||
ent create \<class\> targetname my_ent1_$name
|
||||
ent_create \<class\> targetname my_ent2_$name
|
||||
```
|
||||
entity_cb.cfg
|
||||
```
|
||||
if $ent_last_name == my_ent1_$name
|
||||
:(ent1 actions)
|
||||
if $ent_last_name == my_ent2_$name
|
||||
:(ent2 actions)
|
||||
```
|
||||
Note that scripting cannot be blocking. You cannot wait for server answer and continue. But you can use small scripts, connected with ent_last_cb command. The best usage is user interaction. You can add touch buttons to screen or call user command menu actions by callbacks.
|
||||
## Server side
|
||||
|
||||
To enable entity tools on server, set sv_enttools_enable to 1
|
||||
|
||||
To change maximum number of entities, touched by ent_fire, change sv_enttools_maxfire to required number.
|
||||
|
||||
To enable actions on players, set sv_enttools_players to 1.
|
||||
|
||||
To enable entity tools for player by nickname, set sv_enttools_godplayer to nickname. Useful to temporary enable from rcon.
|
||||
|
||||
To prevent crash on some actions, set host_mapdesign_fatal to 0
|
|
@ -0,0 +1,8 @@
|
|||
# Expanded structures that used by engine and mods
|
||||
To make porting and developing mods on 64-bit platforms less painful, we decided to expand size of several structures.
|
||||
This information important in case you are using codebase like XashXT, Paranoia 2: Savior and want to compile your mod for platform with 64-bit pointer size: you should replace old definitions with new ones, otherwise your mod will not work with Xash3D FWGS (typically, it's just crashing when starting map).
|
||||
| Structure name | Locates in file | Original size on 64-bit | Current size on 64-bit |
|
||||
|----------------|-----------------|-------------------------|------------------------|
|
||||
|`mfaceinfo_t` | `common/com_model.h` | 176 bytes | 304 bytes |
|
||||
|`decal_s` | `common/com_model.h` | 72 bytes | 88 bytes |
|
||||
|`mextrasurf_t` | `common/com_model.h` | 376 bytes | 504 bytes |
|
|
@ -31,11 +31,14 @@ Issue #0. Inconsistency between ABI and Q_buildarch.\
|
|||
Resolution: Change Q_buildarch return value to use Debian-styled architectures list: https://www.debian.org/ports/, which includes a special naming for big/little-endian and hard/soft-float ARM.
|
||||
|
||||
Issue #1: Build-system integration.\
|
||||
Resolution: implemented as [LibraryNaming.cmake](https://github.com/FWGS/hlsdk-xash3d/blob/master/cmake/LibraryNaming.cmake) and [library_naming.py](https://github.com/FWGS/hlsdk-xash3d/blob/master/scripts/waifulib/library_naming.py) extensions, see
|
||||
Resolution: implemented as [LibraryNaming.cmake](https://github.com/FWGS/hlsdk-portable/blob/master/cmake/LibraryNaming.cmake) and [library_naming.py](https://github.com/FWGS/hlsdk-portable/blob/master/scripts/waifulib/library_naming.py) extensions, see
|
||||
|
||||
Issue #2(related to #0): Which ARM flavours we actually need to handle?\
|
||||
Resolution: Little-endian only, as there is no known big-endian ARM platforms in the wild.
|
||||
Architecture is coded this way:
|
||||
* ```armvxy```, where `x` is ARM instruction set level and `y` is hard-float ABI presence: `hf` where hard float ABI used, otherwise `l`.
|
||||
|
||||
Issue #3: Some mods (like The Specialists, Tyrian, ...) already apply suffixes _i386, _i686 to the gamedll path:\
|
||||
Resolution: On x86 on **Win/Lin/Mac**, don't change anything. Otherwise, strip the _i?86 part and follow the usual scheme.
|
||||
|
||||
See discussion: https://github.com/FWGS/xash3d-fwgs/issues/39
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
## Looping MP3 extension
|
||||
|
||||
It is now possible to loop MP3 file in Xash3D FWGS by adding a custom text tag with `LOOP_START` or `LOOPSTART` in description and time point (in raw samples) in value.
|
||||
|
||||
### Example with foobar2000
|
||||
1. Open Foobar2000
|
||||
2. Add your .mp3 file to playlist
|
||||
3. Right click to newly added file and select Properties
|
||||
4. In Metadata tab, at the bottom of the table, select "+add new"
|
||||
5. In newly added line replace `«input field name»` with `LOOP_START` (without any symbols).
|
||||
6. Press Tab and enter loop time point in raw samples. For example, `0` will replay sound file from beginning to end indefinitely.
|
||||
|
||||
### Possible alternatives
|
||||
1. Classic WAV files looping. HQ WAV files can take too much disk space, and recommended software supporting cue points is paid, outdated and can't run on modern systems. (Although there is alternative that's proven to work with idTech-based engines called LoopAuditioneer.)
|
||||
2. Vorbis looping through comment. Engine doesn't support Vorbis but this extension was highly inspired by this hack.
|
||||
|
||||
### Known bugs and limitations
|
||||
1. At this time using MP3 as SFX requires complete decoding. This can cause noticeable stutters, so keep MP3 file length in mind.
|
||||
2. We deliberately only support modern ID3v2.3 and ID3v2.4 tags. Using ID3v1 is not possible.
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
# Game definition and information file
|
||||
|
||||
gameinfo.txt is an essential part of any Xash3D based game. It allows basic customization for games creators, like setting game title, DLL paths, etc.
|
||||
|
||||
This document defines gameinfo.txt syntax, supported keys and liblist.gam conversion rules for the latest version of the engine. Note for engine developers, keep this document in sync with an implementation.
|
||||
|
||||
## gameinfo.txt syntax
|
||||
|
||||
* gameinfo.txt is a simple list of keys and values, separated by newline.
|
||||
* You can add single line comments using double slashes (//).
|
||||
* Keys can accept integer, float, string or boolean values.
|
||||
* Boolean keys use 0 as false and 1 as true value.
|
||||
* To have spaces in string values, you must enclose them in double quotes. Then, to have double quotes, you must escape it with backslash, and to have a backslash you need to use double backslashes.
|
||||
|
||||
The example:
|
||||
```
|
||||
// this is a comment :)
|
||||
// this is another comment
|
||||
some_integer_key 123
|
||||
|
||||
this_is_float_key 13.37 // optional comment
|
||||
|
||||
enable_feature 1 // boolean, 1 to enable, 0 to disable
|
||||
|
||||
example_string_key string_value
|
||||
example_spaces "string with spaces"
|
||||
example_title "Fate\\Stay Night" // engine will parse it as Fate\Stay Night
|
||||
```
|
||||
|
||||
## gameinfo.txt keys
|
||||
|
||||
This is a list of all gameinfo.txt keys supported by the engine. Be aware that the engine will silently skip all unrecognized keys.
|
||||
|
||||
| Key | Type | Default value | Description |
|
||||
| ---------------- | ---------- | --------------- | ----------- |
|
||||
| `ambient0` | string | Empty string | Automatic ambient sound |
|
||||
| `ambient1` | string | Empty string | Automatic ambient sound |
|
||||
| `ambient2` | string | Empty string | Automatic ambient sound |
|
||||
| `ambient3` | string | Empty string | Automatic ambient sound |
|
||||
| `basedir` | string | `valve` | Game base directory, used to share assets between games |
|
||||
| `date` | string | Empty string | Game release date. Unused. |
|
||||
| `dllpath` | string | `cl_dlls` | Game DLL path. Engine will search custom DLLs (client or menu, for example) in this directory, except `gamedll`, see below. |
|
||||
| `fallback_dir` | string | Empty string | Additional game base directory |
|
||||
| `gamedir` | string | Current gamedir | Game directory, ignored in FWGS, as game directory is defined by the game directory name |
|
||||
| `gamedll` | string | `dlls/hl.dll` | Game server DLL for 32-bit x86 Windows (see LibraryNaming.md for details) |
|
||||
| `gamemode` | string | Empty string | Game type. When set to `singleplayer_only` or `multiplayer_only` marks the game as SP or MP only respectively, hiding the option in game UI. Omitting this key or using custom values mark the game as both MP and SP compatible. |
|
||||
| `icon` | string | `game.ico` | Game icon. Engine will automatically append .ico and may automatically switch to .tga icon as well |
|
||||
| `max_beams` | integer | 128 | Beams limit, 64 min, 512 max |
|
||||
| `max_edicts` | integer | 900 | Entities limit, 600 min, 8192 max (protocol limit). In FWGS, minimum is 64. |
|
||||
| `max_particles` | integer | 4096 | Particles limit, 1024 min, 131072 max |
|
||||
| `max_tempents` | integer | 500 | Temporary entities limit. 300 min, 2048 max |
|
||||
| `mp_entity` | string | `info_player_deathmatch` | Entity used to mark maps as multiplayer |
|
||||
| `mp_filter` | string | Empty string | When set, used to filter multiplayer maps instead of `mp_entity`.<br>If the map name starts with the same characters as this filter, it's considered a multiplayer map |
|
||||
| `nomodels` | boolean | 0 | When set to 1, disallows changing player model in UI |
|
||||
| `noskills` | boolean | 0 | When set to 1, disallows selection of game difficulty |
|
||||
| `secure` | boolean | 0 | When set to 1, original Unkle Mike's engine will completely disable developer mode. FWGS ignores but preserves this value for compatibility. |
|
||||
| `size` | integer | 0 | Game directory size in bytes, used in Change Game dialog only |
|
||||
| `startmap` | string | `c0a0` | The name of the map used in new game |
|
||||
| `sp_entity` | string | `info_player_start` | Entity used to mark map as single player. Used in map validation |
|
||||
| `title` | string | `New Game` | Game title, used in window title, default server name, etc. |
|
||||
| `trainmap` | string | `t0a0` | The name of the training map (Hazard Course) |
|
||||
| `type` | string | Empty string | Game type, used in Change Game UI. |
|
||||
| `url_info` | string | Empty string | Game homepage URL, used in Change Game UI |
|
||||
| `url_update` | string | Empty string | Game updates URL, used in Settings UI |
|
||||
| `version` | float | 1.0 | Game version, used in Change Game dialog and in server info |
|
||||
|
||||
## FWGS-specific gameinfo.txt keys
|
||||
|
||||
These strings are specific to Xash3D FWGS.
|
||||
|
||||
| Key | Type | Default value | Description |
|
||||
| ----------------------- | ---------- | ------------------------ | ----------- |
|
||||
| `autosave_aged_count` | integer | 2 | Auto saves limit used in saves rotation |
|
||||
| `gamedll_linux` | string | Generated from `gamedll` | Game server DLL for 32-bit x86 Linux (see LibraryNaming.md for details) |
|
||||
| `gamedll_osx` | string | Generated from `gamedll` | Game server DLL for 32-bit x86 macOS (see LibraryNaming.md for details) |
|
||||
| `internal_vgui_support` | boolean | 0 | Only for programmers! Required to be set as 1 for PrimeXT!<br>When set to 1, the engine will not load vgui_support DLL, as VGUI support is done (or intentionally ignored) on the game side. |
|
||||
| `render_picbutton_text` | boolean | 0 | When set to 1, the UI will not use prerendered `btns_main.bmp` and dynamically render them instead |
|
||||
| `quicksave_aged_count` | integer | 2 | Quick saves limit used in saves rotation |
|
||||
|
||||
## Note on GoldSrc liblist.gam support
|
||||
|
||||
As Xash3D accidentally supports GoldSrc games, it also supports parsing liblist.gam.\
|
||||
Xash3D will use this file if gameinfo.txt is absent, or if its modification timestamp is older than liblist.gam.
|
||||
|
||||
For game creators who plan supporting only Xash3D, using this file is not recommended.
|
||||
|
||||
The table below defines conversion rules from liblist.gam to gameinfo.txt. Some keys' interpretation does differ from `gameinfo.txt`, in this case a note will be left. If `liblist.gam` key isn't present in this table, it's ignored.
|
||||
|
||||
| `liblist.gam` key | `gameinfo.txt` key | Note |
|
||||
| ----------------- | ------------------ | ---- |
|
||||
| `edicts` | `max_edicts` | |
|
||||
| `fallback_dir` | `fallback_dir` | |
|
||||
| `game` | `title` | |
|
||||
| `gamedir` | `gamedir` | |
|
||||
| `gamedll` | `gamedll` | |
|
||||
| `gamedll_linux` | `gamedll_linux` | |
|
||||
| `gamedll_osx` | `gamedll_osx` | |
|
||||
| `icon` | `icon` | |
|
||||
| `mpentity` | `mp_entity` | |
|
||||
| `mpfilter` | `mp_filter` | |
|
||||
| `nomodels` | `nomodels` | |
|
||||
| `secure` | `secure` | In GoldSrc it's used to mark the multiplayer game as anti-cheat enabled.<br>Original Xash3D misinterprets its value for disallowing console and developer mode.<br>FWGS ignores this key but preserves for compatibility. |
|
||||
| `startmap` | `startmap` | |
|
||||
| `size` | `size` | |
|
||||
| `trainingmap` | `trainmap` | |
|
||||
| `trainmap` | `trainmap` | |
|
||||
| `type` | `type` & `gamemode`| In `liblist.gam` this key works as both `type` and `gamemode`.<br>If value is `singleplayer_only` or `multiplayer_only` the game is marked as SP or MP only, and `gameinfo.txt` type set to `Single` or `Multiplayer`.<br>Any custom value will mark the game as both SP and MP compatible, and type is set to whatever custom value. |
|
||||
| `url_dl` | `url_update` | |
|
||||
| `url_info` | `url_info` | |
|
||||
| `version` | `version` | |
|
||||
|
||||
|
|
@ -1,7 +1,40 @@
|
|||
# Server porting
|
||||
# Self-made port
|
||||
## Compatibility with RISC architectures
|
||||
### Unaligned access
|
||||
Unaligned access on **i386** causes only performance penalty, but on **RISC** it can cause unstable work.
|
||||
|
||||
For HLSDK at least you need such patches in util.cpp:
|
||||
- https://github.com/FWGS/halflife/commit/7bfefe86e35d67867ae7af830ac1fc38f2908360
|
||||
- https://github.com/FWGS/hlsdk-portable/commit/617d75545f2ecb9b2d46cc30728dc37c9eb6d35e
|
||||
|
||||
### Signed chars
|
||||
`char` type defined as **signed** for **x86** and as **unsigned** for **arm**.
|
||||
|
||||
And sometimes such difference can break logic.
|
||||
|
||||
As a solution you can use `signed char` type in code directly or use `-fsigned-char` option for gcc/clang compilers.
|
||||
|
||||
For HLSDK at least you need such [fix](https://github.com/FWGS/hlsdk-portable/commit/1ca34fcb4381682bd517612b530db22a1354a795) in nodes.cpp/.h.
|
||||
|
||||
## Compatibility with 64bit architectures
|
||||
You need list of patches for Studio Model Render, MAKE_STRING macro and nodes:
|
||||
- https://github.com/FWGS/hlsdk-portable/commit/d287ed446332e615ab5fb25ca81b99fa14d18a73
|
||||
- https://github.com/FWGS/hlsdk-portable/commit/3bce17e3a04f8af10a927a07ceb8ab0f09152ec4
|
||||
- https://github.com/FWGS/hlsdk-portable/commit/9ebfc981773ec4c7a89ffe52d9c249e1fbef9634
|
||||
- https://github.com/FWGS/hlsdk-portable/commit/00833188dab87ef5746286479ba5aeb9d83b4a0c
|
||||
- https://github.com/FWGS/hlsdk-portable/commit/4661b5c1a5245b27a5532745c11e44b5540e4172
|
||||
- https://github.com/FWGS/hlsdk-portable/commit/2b61380146b1d58a8c465f0e312c061b12bda115
|
||||
- https://github.com/FWGS/hlsdk-portable/commit/8ef6cb2427ee16a763103bd3f315f38e2f01cfe2
|
||||
|
||||
## Mobility API
|
||||
Xash3D FWGS has special extended interface in `mobility_int.h` which adds some new features like vibration on mobile platforms.
|
||||
|
||||
## Porting server-side code
|
||||
Original valve's server code was compatible with linux and gcc 2.x.
|
||||
|
||||
Newer gcc versions have restriction which breaks build.
|
||||
Now, to make it building with gcc 4.x, you need do following:
|
||||
|
||||
Now, to make it building with gcc 4.x+ or clang, you need to do following:
|
||||
* Go to cbase.h and redefine macros as following
|
||||
```
|
||||
#define SetThink( a ) m_pfnThink = static_cast <void (CBaseEntity::*)(void)> (&a)
|
||||
|
@ -18,58 +51,60 @@ Now, to make it building with gcc 4.x, you need do following:
|
|||
* Replace all SetThink(NULL), SetTouch(NULL), setUse(NULL) and SetBlocked(NULL) by ResetThink(), ResetTouch(), ResetUse() and ResetBlocked()
|
||||
* Sometimes you may need to add #include <ctype.h> if functions tolower or isspace are missing
|
||||
|
||||
# Client porting
|
||||
## Porting client-side code
|
||||
|
||||
## VGUI library
|
||||
|
||||
Valve's client uses vgui library which is available only on x86 systems and has big amount of mistakes in headers. The best and simplest way of porting is removing VGUI dependency at all.
|
||||
Most singleplayer mods don't really use VGUI at all. It is used in multiplayer only to show score table and MOTD window
|
||||
|
||||
## Porting
|
||||
|
||||
### First strategy: full port
|
||||
|
||||
#### Basic port (Stage 1)
|
||||
* First, remove all files and headers which use vgui (contains "vgui" in file name).
|
||||
* After that, try to build it and remove vgui includes.
|
||||
* Remove all gViewPort usings.
|
||||
* Remove all CVoiceManager usings (xash3d does not support voice)
|
||||
* Redefine all DLLEXPORT defines as empty field (Place it under _WIN32 macro if you want to keep windows compatibility).
|
||||
* Remove hud_servers.cpp and Servers_Init/Servers_Shutdown from hud.cpp
|
||||
* Remove hud_servers.cpp and Servers_Init/Servers_Shutdown from hud.cpp.
|
||||
* Fix CAPS filenames in includes (like STDIO.H, replace by stdio.h).
|
||||
* Replace broken macros as DECLARE_MESSAGE, DECLARE_COMMAND by fixed examples from our hlsdk-xash3d port (cl_util.h)
|
||||
* Add ctype.h where it is need (tolower, isspace functions)
|
||||
* Add string.h where it is need (memcpy, strcpy, etc)
|
||||
* Use in_defs.h from hlsdk_client
|
||||
* Add scoreboard_stub.cpp and input_stub.cpp from hlsdk-xash3d to fix linking.
|
||||
Now your client should be able to build and work correctly. Add input_xash3d.cpp from hlsdk-xash3d project to fix input.
|
||||
* Replace broken macros as DECLARE_MESSAGE, DECLARE_COMMAND by fixed examples from our hlsdk-portable port (cl_util.h).
|
||||
* Add ctype.h where is needed (tolower, isspace functions).
|
||||
* Add string.h where is needed (memcpy, strcpy, etc).
|
||||
* Use in_defs.h from hlsdk-portable.
|
||||
* Add input_xash3d.cpp from hlsdk-portable project to fix input.
|
||||
|
||||
#### Multiplayer fix (Stage 2)
|
||||
Look at hlsdk-xash3d project.
|
||||
Now your client should be able to build and work correctly.
|
||||
|
||||
Main changes are:
|
||||
* Add MOTD.cpp, scoreboard.cpp and input_xash3d.cpp
|
||||
* Add missing functions to hud_redraw.cpp, hud.cpp and tri.cpp, fix class defination in hud.h
|
||||
* Remove duplicate functions from hud.cpp and HOOK_MESSAGE's for it
|
||||
* Remove +showscores/-showscores hooks from input.h
|
||||
* Fix cl_util.h
|
||||
# Porting mod to hlsdk-portable
|
||||
Look at changes which was made.
|
||||
|
||||
### Second way: move mod to hlsdk-xash3d
|
||||
Look at changes you made in client.
|
||||
If there are not too much changes (for example, only some weapons was added), add these changes in hlsdk-portable.
|
||||
|
||||
If there are not much changes (for example, only some weapons was add), add these changes in hlsdk-xash3d.
|
||||
|
||||
You may use diff with original HLSDK you used and apply it as patch to hlsdk-xash3d.
|
||||
You can use diff with original HLSDK and apply it as patch to hlsdk-portable.
|
||||
|
||||
```
|
||||
NOTE: Many an old mods was made on HLSDK 2.0-2.1 and some rare mods on HLSDK 1.0.
|
||||
So you need to have different versions of HLSDK to make diffs.
|
||||
Plus different Spirit of Half-Life versions if mod was made on it.
|
||||
Also, weapons in old HLSDK versions does not use client weapon prediction system and you may be need to port standart half-life weapons to server side.
|
||||
```
|
||||
Files must have same line endings (use dos2unix on all files).
|
||||
|
||||
I recommend to enable ignoring space changes in diff.
|
||||
### Writing Makefiles
|
||||
We recommend to enable ignoring space changes in diff.
|
||||
|
||||
Use Makefile from hlsdk-xash3d as Makefile example.
|
||||
Move all new files to separate directories.
|
||||
|
||||
Get .c and .cpp file lists from Visual Studio project and fill SRCS and SRCS_C variables to Makefile.
|
||||
# Possible replacements for non-portable external dependencies
|
||||
1. If mod uses **fmod.dll** or **base.dll** to play mp3/ogg on client-side or to precache sounds on server-side, you can replace it with:
|
||||
- [pfnPrimeMusicStream](https://github.com/FWGS/hlsdk-portable/blob/master/engine/cdll_int.h#L293=) engine callback;
|
||||
- [miniaudio](https://github.com/mackron/miniaudio);
|
||||
- [phonon](https://community.kde.org/Phonon).
|
||||
|
||||
Remove all files containing vgui in name from list, add missing include dirs.
|
||||
2. If mod uses **OpenGL**, porting code to Xash3D render interface is recommended.
|
||||
|
||||
3. If mod uses **cg.dll**, you can try to port code to [NVFX](https://github.com/tlorach/nvFX).
|
||||
|
||||
4. If mod uses detours, comment code or try to find replacement somehow by yourself.
|
||||
|
||||
# Additional recommendations
|
||||
1. If mod uses STL, you can replace it with [MiniUTL](https://github.com/FWGS/MiniUTL).
|
||||
2. Avoid to use dynamic casts to make small size binaries.
|
||||
3. Avoid to use exceptions to make small size binaries.
|
||||
|
||||
# Writing build scripts
|
||||
|
||||
Use wscript/CMakeLists.txt files from hlsdk-portable as build scripts example.
|
||||
|
||||
Get .c and .cpp file lists from Visual Studio project.
|
||||
|
||||
Add missing include dirs.
|
||||
|
||||
Do same for Android.mk if you are building for android.
|
||||
|
|
|
@ -17,7 +17,7 @@ Mirrored on github - https://github.com/JoelTroch/am_src_rebirth
|
|||
Mirrored on github - https://github.com/nekonomicon/BattleGrounds
|
||||
|
||||
## Bubblemod
|
||||
Download page on official site - http://www.bubblemod.org/dl_default.php (dead link!)
|
||||
Download page on official site(WM snapshot) - [http://www.bubblemod.org/dl_default.php](https://web.archive.org/web/20130717133158/http://www.bubblemod.org/dl_default.php)
|
||||
|
||||
Mirrored on github - https://github.com/HLSources/BubbleMod
|
||||
|
||||
|
@ -85,6 +85,9 @@ Official gitlab repository - https://gitlab.com/Sockman/hltopdown
|
|||
## Half-Life: Update
|
||||
Official github repository - https://github.com/Fograin/hl-subsmod-ex
|
||||
|
||||
## Half-Life: Rally
|
||||
Official gitlab repository - https://gitlab.com/hlrally/src
|
||||
|
||||
## Half-Life: Weapon Edition
|
||||
Available on ModDB - https://www.moddb.com/mods/half-life-weapon-edition/downloads/half-life-weapon-edition-1508-alpha-open-src
|
||||
|
||||
|
@ -127,22 +130,11 @@ Official github repository - https://github.com/unknownworlds/NS
|
|||
## Overturn
|
||||
Available in mod archive on ModDB - https://www.moddb.com/mods/overturn
|
||||
|
||||
## Spirit of Half-Life
|
||||
[Logic&Trick's](https://github.com/LogicAndTrick) mirror - https://files.logic-and-trick.com/#/Half-Life/Mods/Spirit%20of%20Half-Life
|
||||
|
||||
## Threewave CTF
|
||||
*Unfinished mod by Valve Software*
|
||||
|
||||
Available in Valve's Half-Life repository with Deathmatch Classic sources - https://github.com/ValveSoftware/halflife/tree/master/dmc
|
||||
|
||||
## Trinity Render
|
||||
Available on ModDB: https://www.moddb.com/mods/half-life-episode-two/downloads/trinity-rendering-engine-v308f
|
||||
|
||||
## Tyrian: Ground Assault
|
||||
Available on ModDB: https://www.moddb.com/mods/tyriangroundassault/downloads/tyrianga-v1-0-src
|
||||
## Oz Deathmatch
|
||||
Mirrored on github - https://github.com/nekonomicon/OZDM
|
||||
|
||||
## Paranoia
|
||||
Available on ModDB: https://www.moddb.com/mods/paranoia/downloads/paranoia-toolkit
|
||||
Available on ModDB - https://www.moddb.com/mods/paranoia/downloads/paranoia-toolkit
|
||||
|
||||
## Paranoia 2: The Savior
|
||||
Prealpha, mirrored on github - https://github.com/a1batross/Paranoia2_ancient
|
||||
|
@ -157,12 +149,37 @@ Was found on HLFX - http://hlfx.ru/forum/showthread.php?s=2c892dfc52f72be52a89c3
|
|||
## Ricochet
|
||||
Available in Valve's Half-Life repository - https://github.com/ValveSoftware/halflife/tree/master/ricochet
|
||||
|
||||
## Spirit of Half-Life
|
||||
[Logic&Trick's](https://github.com/LogicAndTrick) mirror - https://files.logic-and-trick.com/#/Half-Life/Mods/Spirit%20of%20Half-Life
|
||||
|
||||
## The Wastes
|
||||
Version 1.5: mirrored on code.idtech.space - https://code.idtech.space/vera/halflife-thewastes-sdk
|
||||
|
||||
## Threewave CTF
|
||||
*Unfinished mod by Valve Software*
|
||||
|
||||
Available in Valve's Half-Life repository with Deathmatch Classic sources - https://github.com/ValveSoftware/halflife/tree/master/dmc
|
||||
|
||||
## Trinity Render
|
||||
Available on ModDB - https://www.moddb.com/mods/half-life-episode-two/downloads/trinity-rendering-engine-v308f
|
||||
|
||||
## Tyrian: Ground Assault
|
||||
Available on ModDB - https://www.moddb.com/mods/tyriangroundassault/downloads/tyrianga-v1-0-src
|
||||
|
||||
## Wasteland
|
||||
Mirrored on code.idtech.space - https://code.idtech.space/vera/halflife-wasteland-sdk
|
||||
|
||||
## Wizard Wars
|
||||
Download page on official site - http://www.thothie.com/ww/
|
||||
|
||||
## XashXT
|
||||
Mirrored on github - https://github.com/a1batross/XashXT_original
|
||||
|
||||
## Xen-Warrior
|
||||
*Source code is a part of Spirit of Half-Life 1.0-1.2 under XENWARRIOR macro*
|
||||
|
||||
[Logic&Trick's](https://github.com/LogicAndTrick) mirror - https://files.logic-and-trick.com/#/Half-Life/Mods/Spirit%20of%20Half-Life
|
||||
|
||||
## Zombie-X
|
||||
Available in mod archive on ModDB - https://www.moddb.com/mods/zombie-x-10-final/downloads/zombie-x-10-dle-beta6-last-version
|
||||
|
||||
|
@ -184,12 +201,12 @@ malortie's recreation - https://github.com/malortie/hl-aom
|
|||
Branch **aom** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/aom
|
||||
|
||||
## Afraid of Monsters: Director's cut
|
||||
Reverse-engineered code, branch **aomdc** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/aomdc
|
||||
Reverse-engineered code: branch **aomdc** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/aomdc
|
||||
|
||||
## Azure Sheep
|
||||
malortie's recreation - https://github.com/malortie/hl-asheep
|
||||
|
||||
Reverse-engineered code, branch **asheep** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/asheep
|
||||
Reverse-engineered code: branch **asheep** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/asheep
|
||||
|
||||
## Big Lolly
|
||||
malortie's recreation - https://github.com/malortie/hl-biglolly
|
||||
|
@ -226,12 +243,17 @@ Recreation by lostgamer aka nillerusr - https://github.com/LostGamerHL/crack_lif
|
|||
## Escape from the Darkness
|
||||
malortie's recreation - https://github.com/malortie/hl-eftd
|
||||
|
||||
Reverse-engineered code, branch **eftd** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/eftd
|
||||
Reverse-engineered code: branch **eftd** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/eftd
|
||||
|
||||
## Half-Life: Black Guard
|
||||
*This mod uses dlls from Cleaner's Adventures*
|
||||
|
||||
Branch **CAd** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/CAd
|
||||
|
||||
## Half-Life: Blue Shift
|
||||
Unkle Mike's recreation - https://hlfx.ru/forum/showthread.php?s=&threadid=5253
|
||||
|
||||
Reverse-engineered code, branch **bshift** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/bshift
|
||||
Reverse-engineered code: branch **bshift** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/bshift
|
||||
|
||||
## Half-Life: Induction
|
||||
Branch **induction** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/induction
|
||||
|
@ -239,12 +261,12 @@ Branch **induction** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/
|
|||
## Half-Life: Opposing Force
|
||||
Recreation by lostgamer aka nillerusr - https://github.com/LostGamerHL/hlsdk-xash3d
|
||||
|
||||
Reverse-engineered code, clean branch **opfor** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/opfor
|
||||
Reverse-engineered code: clean branch **opfor** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/opfor
|
||||
|
||||
Spirit of Half Life: Opposing-Force Edition - https://github.com/Hammermaps-DEV/SOHL-V1.9-Opposing-Force-Edition
|
||||
|
||||
## Half-Life: Rebellion
|
||||
Reverse-engineered code, branch **rebellion** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/rebellion
|
||||
Reverse-engineered code: branch **rebellion** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/rebellion
|
||||
|
||||
## Half-Life: Urbicide
|
||||
Branch **hl_urbicide** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/hl_urbicide
|
||||
|
@ -252,7 +274,7 @@ Branch **hl_urbicide** in hlsdk-portable - https://github.com/FWGS/hlsdk-portabl
|
|||
## Half-Life: Visitors
|
||||
malortie's recreation - https://github.com/malortie/hl-visitors
|
||||
|
||||
Reverse-engineered code, branch **visitors** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/visitors
|
||||
Reverse-engineered code: branch **visitors** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/visitors
|
||||
|
||||
## Half-Secret
|
||||
Branch **half-secret** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/half-secret
|
||||
|
@ -265,18 +287,18 @@ Branch **noffice** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tr
|
|||
## Poke 646
|
||||
malortie's recreation - https://github.com/malortie/hl-poke646
|
||||
|
||||
Reverse-engineered code, branch **poke646** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/poke646
|
||||
Reverse-engineered code: branch **poke646** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/poke646
|
||||
|
||||
## Poke 646: Vendetta
|
||||
malortie's recreation - https://github.com/malortie/hl-poke646-vendetta
|
||||
|
||||
Reverse-engineered code, branch **poke646_vendetta** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/poke646_vendetta
|
||||
Reverse-engineered code: branch **poke646_vendetta** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/poke646_vendetta
|
||||
|
||||
## Residual Life
|
||||
Reverse-engineered code, branch **residual_point** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/residual_point
|
||||
Reverse-engineered code: branch **residual_point** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/residual_point
|
||||
|
||||
## Residual Point
|
||||
Reverse-engineered code, branch **residual_point** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/residual_point
|
||||
Reverse-engineered code: branch **residual_point** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/residual_point
|
||||
|
||||
## Sewer Beta
|
||||
Branch **sewer_beta** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/sewer_beta
|
||||
|
@ -287,12 +309,12 @@ Reverse-engineered code by Velaron - https://github.com/Velaron/tf15-client
|
|||
## The Gate
|
||||
malortie's recreation - https://github.com/malortie/hl-thegate
|
||||
|
||||
Reverse-engineered code, branch **thegate** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/thegate
|
||||
Reverse-engineered code: branch **thegate** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/thegate
|
||||
|
||||
## They Hunger
|
||||
malortie's recreation - https://github.com/malortie/hl-theyhunger
|
||||
|
||||
Reverse-engineered code, branch **theyhunger** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/theyhunger
|
||||
Reverse-engineered code: branch **theyhunger** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/theyhunger
|
||||
|
||||
They Hunger: Tactical - https://www.moddb.com/mods/they-hunger-tactical/downloads/tht-source-code-documentation
|
||||
|
||||
|
@ -335,16 +357,22 @@ Branch **half-screwed** in hlsdk-portable - https://github.com/FWGS/hlsdk-portab
|
|||
Port to Linux - https://github.com/fmoraw/NS
|
||||
|
||||
## Spirit of Half-Life
|
||||
Version 1.2, branch **sohl1.2** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/sohl1.2
|
||||
Version 1.2: branch **sohl1.2** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/sohl1.2
|
||||
|
||||
## Swiss Cheese Halloween 2002
|
||||
Just more playable version by malortie - https://github.com/malortie/hl-shall
|
||||
|
||||
Branch **halloween** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/halloween
|
||||
|
||||
## The Wastes
|
||||
Version 1.5: Port to Linux - https://git.mentality.rip/a1batross/halflife-thewastes-sdk
|
||||
|
||||
## Threewave CTF
|
||||
Branch **dmc** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/dmc
|
||||
|
||||
## Xen-Warrior
|
||||
Branch **sohl1.2** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/sohl1.2
|
||||
|
||||
## Zombie-X
|
||||
Branch **zombie-x** in hlsdk-portable - https://github.com/FWGS/hlsdk-portable/tree/zombie-x
|
||||
|
||||
|
|
|
@ -2,37 +2,32 @@ Xash3D FWGS is intended to be easily ported to specific platform, however main i
|
|||
|
||||
This page is about merged ports to main source tree and responsible for it developers.
|
||||
|
||||
For porting guidelines, look here(TODO!)
|
||||
For porting guidelines, look engine-porting-guide.md.
|
||||
|
||||
Status:
|
||||
* **Supported**: active, confirmed to be fully functional.
|
||||
* **Supported**: active, was confirmed to be fully functional.
|
||||
* **In progress**: active, under development.
|
||||
* **Incomplete**: not active, but some work was accepted to main repository before
|
||||
* **Old Engine**: port was for old engine fork
|
||||
* **Not maintained**: lack of human resources
|
||||
* **Not merged**: was done in third-party fork, real status unknown
|
||||
* **Deprecated**: not supported anymore
|
||||
|
||||
Table is sorted by status.
|
||||
Table is sorted by status and platform.
|
||||
|
||||
| Platform | Status | Maintainer | Note
|
||||
| -------- | ------ | ---------- | ----
|
||||
| Windows | Supported | @a1batross, @SNMetamorph |
|
||||
| Android | Supported | @Velaron |
|
||||
| *BSD | Supported | @nekonomicon |
|
||||
| GNU/Linux(x86, amd64, arm) | Supported | @a1batross, @mittorn |
|
||||
| Android | Supported | @a1batross, @mittorn |
|
||||
| MotoMAGX | Supported | @a1batross |
|
||||
| GNU/Linux(elbrus) | Supported | @a1batross, @mittorn | Rare and eventual access to e2k machine
|
||||
| Haiku | Supported | not maintained | Was added by #478 and #483
|
||||
| DOS4GW | Supported | @mittorn |
|
||||
| GNU/Linux(mipsel) | Supported | @mittorn |
|
||||
| Switch | In progress | @fgsfdsfgs | [GitHub Repository](https://github.com/fgsfdsfgs/xash3d-fwgs/tree/switch_new)
|
||||
| Wii | In progress | Collaborative effort | [GitHub Repository](https://github.com/saucesaft/xash3d-wii)
|
||||
| GNU/Linux | Supported | @a1batross, @mittorn |
|
||||
| Haiku | Supported | not maintained | Was added by #478 and #483
|
||||
| macOS | Supported | @sofakng |
|
||||
| MotoMAGX | Supported | @a1batross |
|
||||
| PSVita | Supported | @fgsfdsfgs |
|
||||
| Switch | Supported | @fgsfdsfgs |
|
||||
| Windows | Supported | @a1batross, @SNMetamorph |
|
||||
| PSP | In progress | @Crow_bar, @Velaron | [GitHub Repository](https://github.com/Crow-bar/xash3d-fwgs)
|
||||
| Wii | In progress | Collaborative effort | [GitHub Repository](https://github.com/saucesaft/xash3d-wii)
|
||||
| Emscripten | Old Engine | not maintained |
|
||||
| Oculus Quest | Old Engine fork | @DrBeef | [GitHub Repository](https://github.com/DrBeef/Lambda1VR)
|
||||
| PSVita | Old Engine fork | not maintained | [GitHub Repository](https://github.com/fgsfdsfgs/vitaXash3D)
|
||||
| Switch | Old Engine fork | not maintained | [GitHub Repository](https://github.com/switchports/xash3d-switch)
|
||||
| 3DS | Old Engine fork | not maintained | [GitHub Repository](https://github.com/masterfeizz/Xash3DS)
|
||||
| macOS | Deprecated | not maintained | See GitHub issue #61
|
||||
| Oculus Quest | Old Engine fork | @DrBeef | [GitHub Repository](https://github.com/DrBeef/Lambda1VR)
|
||||
| iOS | Deprecated | not maintained | See GitHub issue #61
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
## PlayStation Vita port
|
||||
|
||||
### Prerequisites
|
||||
1. Make sure your PSVita is [set up to run homebrew applications](https://vita.hacks.guide/).
|
||||
2. Install [kubridge](https://github.com/TheOfficialFloW/kubridge/releases/) by copying `kubridge.suprx` to your taiHEN plugins folder (usually `ux0:/tai`) and add it to your `config.txt`, for example:
|
||||
```
|
||||
*KERNEL
|
||||
ux0:tai/kubridge.skprx
|
||||
```
|
||||
3. Install `libshacccg.suprx` by following [this guide](https://cimmerian.gitbook.io/vita-troubleshooting-guide/shader-compiler/extract-libshacccg.suprx).
|
||||
|
||||
### Installation
|
||||
1. If you have an old vitaXash3D install, remove it.
|
||||
2. Get `xash3d-fwgs-psvita.7z` from the latest [automatic build](https://github.com/FWGS/xash3d-fwgs/releases/tag/continuous).
|
||||
3. Install `xash.vpk` from the 7z archive onto your PSVita.
|
||||
4. Copy the `data` directory from the 7z archive to the root of your PSVita's SD card.
|
||||
5. Copy the valve folder and any other mod folders from your Half-Life install to `ux0:/data/xash3d/` (you can use other mountpoints instead of `ux0`). **Do not overwrite anything.**
|
||||
|
||||
### Build instructions
|
||||
1. Install [VitaSDK](https://vitasdk.org/).
|
||||
2. Build and install [vitaGL](https://github.com/Rinnegatamante/vitaGL):
|
||||
```
|
||||
git clone https://github.com/Rinnegatamante/vitaGL.git
|
||||
make -C vitaGL NO_TEX_COMBINER=1 HAVE_UNFLIPPED_FBOS=1 HAVE_PTHREAD=1 SINGLE_THREADED_GC=1 MATH_SPEEDHACK=1 DRAW_SPEEDHACK=1 HAVE_CUSTOM_HEAP=1 -j2 install
|
||||
```
|
||||
3. Build and install [vita-rtld](https://github.com/fgsfdsfgs/vita-rtld):
|
||||
```
|
||||
git clone https://github.com/fgsfdsfgs/vita-rtld.git && cd vita-rtld
|
||||
mkdir build && cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=Release ..
|
||||
make -j2 install
|
||||
```
|
||||
4. Build and install [this SDL2 fork](https://github.com/Northfear/SDL) with vitaGL integration:
|
||||
```
|
||||
git clone https://github.com/Northfear/SDL.git && cd SDL
|
||||
mkdir build && cd build
|
||||
cmake -DCMAKE_TOOLCHAIN_FILE=${VITASDK}/share/vita.toolchain.cmake -DCMAKE_BUILD_TYPE=Release -DVIDEO_VITA_VGL=ON ..
|
||||
make -j2 install
|
||||
```
|
||||
5. Use `waf`:
|
||||
```
|
||||
./waf configure -T release --psvita
|
||||
./waf build
|
||||
```
|
||||
6. Copy all the resulting `.so` files into a single folder:
|
||||
```
|
||||
./waf install --destdir=xash3d
|
||||
```
|
||||
7. `xash.vpk` is located in `build/engine/`.
|
66
README.md
66
README.md
|
@ -2,31 +2,32 @@
|
|||
[![GitHub Actions Status](https://github.com/w23/xash3d-fwgs/actions/workflows/c-cpp.yml/badge.svg)](https://github.com/w23/xash3d-fwgs/actions/workflows/c-cpp.yml)
|
||||
|
||||
## TL;DR
|
||||
- ![image](https://github.com/w23/xash3d-fwgs/assets/321361/12200b56-df80-4d33-b433-71f5690fb4f5)
|
||||
- This fork adds Vulkan renderer to Xash3D-FWGS engine.
|
||||
- This is work-in-progress. It is in very early stages and is not ready for unsupervised usage.
|
||||
- This is work-in-progress. It is in early stages and is not ready for unsupervised usage.
|
||||
- Vulkan renderer targets two different modes:
|
||||
- Traditional rasterizer. It is intended to produce pixel-perfect identical frames to existing GL renderer as possible.
|
||||
- Ray tracing. It implements real time path traced global illumination lighting with PBR materials. It will look noticeably different from original game.
|
||||
- It is intended to be merged back into upstream/master when it gets mature and stable enough.
|
||||
- It primarily focuses Half-Life 1 game. Mods compatibility is not being considered at this time. This may change with maturity of the new renderer.
|
||||
- Ray tracing requires 64-bit build. 32-bit drivers do not expose vulkan ray tracing extensions.
|
||||
- For more information, check out the [wiki](https://github.com/w23/xash3d-fwgs/wiki).
|
||||
- [Page on Mod DB](https://www.moddb.com/mods/half-life-rtx) (screenshots, etc).
|
||||
|
||||
## Current status
|
||||
- Not ready for any use.
|
||||
- See Issues and [ref_vk/TODO.md](ref_vk/TODO.md)
|
||||
- Traditional rasterizer works with some issues.
|
||||
- See [issues](https://github.com/w23/xash3d-fwgs/issues) and [project](https://github.com/users/w23/projects/2/views/12)
|
||||
- Traditional rasterizer mostly works:
|
||||
- Works on Windows and Linux with any Vulkan GPU (and at some point it worked on Raspberry Pi 4 even).
|
||||
- It is slower than OpenGL renderer (1. I suck at Vulkan. 2. No visibility culling is performed).
|
||||
- Some features are not implemented yet: most of blending modes, some studio models features, sprites, beams, decals, tri api, etc)
|
||||
- Some features are not implemented yet, like decals, dynamic lighting is different and way off, etc.
|
||||
- Ray tracer mostly works too, with dynamic GI and stuff.
|
||||
- It misses roughly the same set of features as traditional rasterizer (code is the same for the most part).
|
||||
- It also requires material remaster (i.e. newer textures for PBR parameters) and missing RAD files for most of the game maps. Work on these haven't been started yet.
|
||||
- It also requires material remaster (i.e. newer textures for PBR parameters) and missing RAD files for most of the game maps.
|
||||
- Works under both Windows and Linux.
|
||||
- Works on both AMD and Nvidia GPUs.
|
||||
- If you feel adventurous, you can follow [build instructions](https://github.com/w23/xash3d-fwgs/wiki/64-bit-build-on-Windows). Note that they might be slightly out of date, kek.
|
||||
- Works on Steam Deck with _interactive framerates_.
|
||||
- If you feel adventurous, you can follow [build instructions](https://github.com/w23/xash3d-fwgs/wiki/How-to-build-a-64bit). Note that they might be slightly out of date, kek.
|
||||
|
||||
## Follow development
|
||||
This project is 99.999% developed live on stream. I'm not a graphcis programmer, and have no idea what I'm doing. I'm essentially learning Vulkan, game engine renderer development, linear algebra, and ray tracing techniques while getting hands dirty with this. This is all for your amusement.
|
||||
This project is 99% developed live on stream. I'm not a graphics programmer, and have no idea what I'm doing. I'm essentially learning Vulkan, game engine renderer development, linear algebra, and ray tracing techniques while getting hands dirty with this. This is all for your amusement.
|
||||
|
||||
You can watch me making a fool of myself publicly here:
|
||||
- [Archive playlist on YouTube/floba23](https://www.youtube.com/playlist?list=PLP0z1CQXyu5CrDa522FklxbOC0SM_Manl)
|
||||
|
@ -38,39 +39,36 @@ Regular upstream Xash3D README.md follows.
|
|||
|
||||
---
|
||||
|
||||
# Xash3D FWGS Engine
|
||||
# Xash3D FWGS Engine <img align="right" width="128" height="128" src="https://github.com/FWGS/xash3d-fwgs/raw/master/game_launch/icon-xash-material.png" alt="Xash3D FWGS icon" />
|
||||
[![GitHub Actions Status](https://github.com/FWGS/xash3d-fwgs/actions/workflows/c-cpp.yml/badge.svg)](https://github.com/FWGS/xash3d-fwgs/actions/workflows/c-cpp.yml) [![FreeBSD Build Status](https://img.shields.io/cirrus/github/FWGS/xash3d-fwgs?label=freebsd%20build)](https://cirrus-ci.com/github/FWGS/xash3d-fwgs) [![Discord Server](https://img.shields.io/discord/355697768582610945.svg)](http://fwgsdiscord.mentality.rip/) \
|
||||
[![Download Stable](https://img.shields.io/badge/download-stable-yellow)](https://github.com/FWGS/xash3d-fwgs/releases/latest) [![Download Testing](https://img.shields.io/badge/downloads-testing-orange)](https://github.com/FWGS/xash3d-fwgs/releases/tag/continuous)
|
||||
[![Download Stable](https://img.shields.io/badge/download-stable-yellow)](https://github.com/FWGS/xash3d-fwgs/releases/latest) [![Download Testing](https://img.shields.io/badge/downloads-testing-orange)](https://github.com/FWGS/xash3d-fwgs/releases/tag/continuous)
|
||||
|
||||
Xash3D FWGS is a fork of Xash3D Engine by Unkle Mike with extended features and crossplatform.
|
||||
Xash3D FWGS is a game engine, aimed to provide compatibility with Half-Life Engine and extend it, as well as to give game developers well known workflow.
|
||||
|
||||
```
|
||||
Xash3D is a game engine, aimed to provide compatibility with Half-Life Engine,
|
||||
as well as to give game developers well known workflow and extend it.
|
||||
Read more about Xash3D on ModDB: https://www.moddb.com/engines/xash3d-engine
|
||||
```
|
||||
Xash3D FWGS is a heavily modified fork of an original [Xash3D Engine](https://www.moddb.com/engines/xash3d-engine) by Unkle Mike.
|
||||
|
||||
## Donate
|
||||
[![Donate to FWGS button](https://img.shields.io/badge/Donate_to_FWGS-%3C3-magenta)](Documentation/donate.md) \
|
||||
If you like Xash3D FWGS, consider supporting individual engine maintainers. By supporting us, you help to continue developing this game engine further. The sponsorship links are available in [documentation](Documentation/donate.md).
|
||||
|
||||
## Fork features
|
||||
* HLSDK 2.4 support.
|
||||
* Crossplatform: supported x86 and ARM on Windows/Linux/BSD/Android. ([see docs for more info](Documentation/ports.md))
|
||||
* Modern compilers support: say no more to MSVC6.
|
||||
* Better multiplayer support: multiple master servers, headless dedicated server.
|
||||
* Mobility API: allows better game integration on mobile devices(vibration, touch controls)
|
||||
* Different input methods: touch, gamepad and classic mouse & keyboard.
|
||||
* Steam Half-Life (HLSDK 2.4) support.
|
||||
* Crossplatform and modern compilers support: supports Windows, Linux, BSD & Android on x86 & ARM and [many more](Documentation/ports.md).
|
||||
* Better multiplayer support: multiple master servers, headless dedicated server, voice chat and IPv6 support.
|
||||
* Multiple renderers support: OpenGL, GLESv1, GLESv2 and Software.
|
||||
* Advanced virtual filesystem: `.pk3` and `.pk3dir` support, compatibility with GoldSrc FS module, fast case-insensitivity emulation for crossplatform.
|
||||
* Mobility API: better game integration on mobile devices (vibration, touch controls)
|
||||
* Different input methods: touch and gamepad in addition to mouse & keyboard.
|
||||
* TrueType font rendering, as a part of mainui_cpp.
|
||||
* Multiple renderers support: OpenGL, GLESv1, GLESv2, Software
|
||||
* A set of small improvements, without broken compatibility.
|
||||
|
||||
## Planned fork features
|
||||
* Virtual Reality support and game API
|
||||
* Voice support
|
||||
* Vulkan renderer
|
||||
* External VGUI support module.
|
||||
* PNG & KTX2 image format support.
|
||||
* [A set of small improvements](Documentation/), without broken compatibility.
|
||||
|
||||
## Installation & Running
|
||||
0) Get Xash3D FWGS binaries: you can use [testing](https://github.com/FWGS/xash3d-fwgs/releases/tag/continuous) build or you can compile engine from source code.
|
||||
1) Copy engine binaries to some directory.
|
||||
2) Copy `valve` directory from [Half-Life](https://store.steampowered.com/app/70/HalfLife/) to directory with engine binaries.
|
||||
If your CPU is NOT x86 compatible or you're running 64-bit version of the engine, you may want to compile [Half-Life SDK](https://github.com/FWGS/hlsdk-xash3d).
|
||||
If your CPU is NOT x86 compatible or you're running 64-bit version of the engine, you may want to compile [Half-Life SDK](https://github.com/FWGS/hlsdk-portable).
|
||||
This repository contains our fork of HLSDK and restored source code for some of the mods. Not all of them, of course.
|
||||
You still needed to copy `valve` directory as all game resources located there.
|
||||
3) Run the main executable (`xash3d.exe` or AppImage).
|
||||
|
@ -89,10 +87,10 @@ NOTE: NEVER USE GitHub's ZIP ARCHIVES. GitHub doesn't include external dependenc
|
|||
|
||||
### Prerequisites
|
||||
|
||||
If your CPU is x86 compatible, we are building 32-bit code by default. This was dont for keeping compatibility with Steam releases of Half-Life and based on it's engine games.
|
||||
If your CPU is x86 compatible, we are building 32-bit code by default. This was done to maintain compatibility with Steam releases of Half-Life and based on it's engine games.
|
||||
Even if Xash3D FWGS does support targetting 64-bit, you can't load games without recompiling them from source code!
|
||||
|
||||
If your CPU is NOT x86 compatible or you decided build 64-bit version of engine, you may want to compile [Half-Life SDK](https://github.com/FWGS/hlsdk-xash3d).
|
||||
If your CPU is NOT x86 compatible or you decided build 64-bit version of engine, you may want to compile [Half-Life SDK](https://github.com/FWGS/hlsdk-portable).
|
||||
This repository contains our fork of HLSDK and restored source code for some of the mods. Not all of them, of course.
|
||||
|
||||
#### Windows (Visual Studio)
|
||||
|
|
|
@ -18,27 +18,17 @@ GNU General Public License for more details.
|
|||
// video backends (XASH_VIDEO)
|
||||
#define VIDEO_NULL 0
|
||||
#define VIDEO_SDL 1
|
||||
#define VIDEO_ANDROID 2
|
||||
#define VIDEO_FBDEV 3
|
||||
#define VIDEO_DOS 4
|
||||
|
||||
|
||||
// audio backends (XASH_SOUND)
|
||||
#define SOUND_NULL 0
|
||||
#define SOUND_SDL 1
|
||||
#define SOUND_OPENSLES 2
|
||||
#define SOUND_ALSA 3
|
||||
|
||||
// crash handler (XASH_CRASHHANDLER)
|
||||
#define CRASHHANDLER_NULL 0
|
||||
#define CRASHHANDLER_UCONTEXT 1
|
||||
#define CRASHHANDLER_DBGHELP 2
|
||||
#define CRASHHANDLER_WIN32 3
|
||||
|
||||
// input (XASH_INPUT)
|
||||
#define INPUT_NULL 0
|
||||
#define INPUT_SDL 1
|
||||
#define INPUT_ANDROID 2
|
||||
#define INPUT_EVDEV 3
|
||||
|
||||
// timer (XASH_TIMER)
|
||||
|
@ -51,9 +41,8 @@ GNU General Public License for more details.
|
|||
// messageboxes (XASH_MESSAGEBOX)
|
||||
#define MSGBOX_STDERR 0
|
||||
#define MSGBOX_SDL 1
|
||||
#define MSGBOX_ANDROID 2
|
||||
#define MSGBOX_WIN32 3
|
||||
|
||||
#define MSGBOX_NSWITCH 4
|
||||
|
||||
// library loading (XASH_LIB)
|
||||
#define LIB_NULL 0
|
||||
|
@ -61,5 +50,4 @@ GNU General Public License for more details.
|
|||
#define LIB_WIN32 2
|
||||
#define LIB_STATIC 3
|
||||
|
||||
|
||||
#endif /* BACKENDS_H */
|
||||
|
|
|
@ -61,23 +61,27 @@ BRUSH MODELS
|
|||
#define LS_UNUSED 0xFE
|
||||
#define LS_NONE 0xFF
|
||||
|
||||
#define MAX_MAP_CLIPNODES_HLBSP 32767
|
||||
#define MAX_MAP_CLIPNODES_BSP2 524288
|
||||
|
||||
// these limis not using by modelloader but only for displaying 'mapstats' correctly
|
||||
#ifdef SUPPORT_BSP2_FORMAT
|
||||
#define MAX_MAP_MODELS 2048 // embedded models
|
||||
#define MAX_MAP_ENTSTRING 0x200000 // 2 Mb should be enough
|
||||
#define MAX_MAP_PLANES 131072 // can be increased without problems
|
||||
#define MAX_MAP_NODES 262144 // can be increased without problems
|
||||
#define MAX_MAP_CLIPNODES 524288 // can be increased without problems
|
||||
#define MAX_MAP_CLIPNODES MAX_MAP_CLIPNODES_BSP2 // can be increased without problems
|
||||
#define MAX_MAP_LEAFS 131072 // CRITICAL STUFF to run ad_sepulcher!!!
|
||||
#define MAX_MAP_VERTS 524288 // can be increased without problems
|
||||
#define MAX_MAP_FACES 262144 // can be increased without problems
|
||||
#define MAX_MAP_MARKSURFACES 524288 // can be increased without problems
|
||||
#else
|
||||
#define MAX_MAP_MODELS 768 // embedded models
|
||||
// increased to match PrimeXT compilers
|
||||
#define MAX_MAP_MODELS 1024 // embedded models
|
||||
#define MAX_MAP_ENTSTRING 0x100000 // 1 Mb should be enough
|
||||
#define MAX_MAP_PLANES 65536 // can be increased without problems
|
||||
#define MAX_MAP_NODES 32767 // because negative shorts are leafs
|
||||
#define MAX_MAP_CLIPNODES 32767 // because negative shorts are contents
|
||||
#define MAX_MAP_CLIPNODES MAX_MAP_CLIPNODES_HLBSP // because negative shorts are contents
|
||||
#define MAX_MAP_LEAFS 32767 // signed short limit
|
||||
#define MAX_MAP_VERTS 65535 // unsigned short limit
|
||||
#define MAX_MAP_FACES 65535 // unsigned short limit
|
||||
|
|
|
@ -9,7 +9,20 @@ NOTE: number at end of pixelformat name it's a total bitscount e.g. PF_RGB_24 ==
|
|||
========================================================================
|
||||
*/
|
||||
#define ImageRAW( type ) (type == PF_RGBA_32 || type == PF_BGRA_32 || type == PF_RGB_24 || type == PF_BGR_24 || type == PF_LUMINANCE)
|
||||
#define ImageDXT( type ) (type == PF_DXT1 || type == PF_DXT3 || type == PF_DXT5 || type == PF_ATI2 || type == PF_BC6H_SIGNED || type == PF_BC6H_UNSIGNED || type == PF_BC7)
|
||||
#define ImageCompressed( type ) \
|
||||
( type == PF_DXT1 \
|
||||
|| type == PF_DXT3 \
|
||||
|| type == PF_DXT5 \
|
||||
|| type == PF_ATI2 \
|
||||
|| type == PF_BC4_SIGNED \
|
||||
|| type == PF_BC4_UNSIGNED \
|
||||
|| type == PF_BC5_SIGNED \
|
||||
|| type == PF_BC5_UNSIGNED \
|
||||
|| type == PF_BC6H_SIGNED \
|
||||
|| type == PF_BC6H_UNSIGNED \
|
||||
|| type == PF_BC7_UNORM \
|
||||
|| type == PF_BC7_SRGB \
|
||||
|| type == PF_KTX2_RAW )
|
||||
|
||||
typedef enum
|
||||
{
|
||||
|
@ -25,9 +38,15 @@ typedef enum
|
|||
PF_DXT3, // s3tc DXT3/BC2 format
|
||||
PF_DXT5, // s3tc DXT5/BC3 format
|
||||
PF_ATI2, // latc ATI2N/BC5 format
|
||||
PF_BC4_SIGNED,
|
||||
PF_BC4_UNSIGNED,
|
||||
PF_BC5_SIGNED,
|
||||
PF_BC5_UNSIGNED,
|
||||
PF_BC6H_SIGNED, // bptc BC6H signed FP16 format
|
||||
PF_BC6H_UNSIGNED, // bptc BC6H unsigned FP16 format
|
||||
PF_BC7, // bptc BC7 format
|
||||
PF_BC7_UNORM, // bptc BC7 format
|
||||
PF_BC7_SRGB,
|
||||
PF_KTX2_RAW, // Raw KTX2 data, used for yet unsupported KTX2 subformats
|
||||
PF_TOTALCOUNT, // must be last
|
||||
} pixformat_t;
|
||||
|
||||
|
@ -49,6 +68,8 @@ typedef enum
|
|||
IL_DDS_HARDWARE = BIT(4), // DXT compression is support
|
||||
IL_LOAD_DECAL = BIT(5), // special mode for load gradient decals
|
||||
IL_OVERVIEW = BIT(6), // overview required some unque operations
|
||||
IL_LOAD_PLAYER_DECAL = BIT(7), // special mode for player decals
|
||||
IL_KTX2_RAW = BIT(8), // renderer can consume raw KTX2 files (e.g. ref_vk)
|
||||
} ilFlags_t;
|
||||
|
||||
// goes into rgbdata_t->encode
|
||||
|
|
|
@ -105,7 +105,7 @@ typedef struct
|
|||
|
||||
vec3_t mins, maxs; // terrain bounds (fill by user)
|
||||
|
||||
int reserved[32]; // just for future expansions or mod-makers
|
||||
intptr_t reserved[32]; // just for future expansions or mod-makers
|
||||
} mfaceinfo_t;
|
||||
|
||||
typedef struct
|
||||
|
@ -173,8 +173,8 @@ struct decal_s
|
|||
short entityIndex; // Entity this is attached to
|
||||
// Xash3D specific
|
||||
vec3_t position; // location of the decal center in world space.
|
||||
glpoly_t *polys; // precomputed decal vertices
|
||||
int reserved[4]; // just for future expansions or mod-makers
|
||||
glpoly_t *polys; // precomputed decal vertices
|
||||
intptr_t reserved[4]; // just for future expansions or mod-makers
|
||||
};
|
||||
|
||||
typedef struct mleaf_s
|
||||
|
@ -228,7 +228,7 @@ typedef struct mextrasurf_s
|
|||
unsigned short numverts; // world->vertexes[]
|
||||
int firstvertex; // fisrt look up in tr.tbn_vectors[], then acess to world->vertexes[]
|
||||
|
||||
int reserved[32]; // just for future expansions or mod-makers
|
||||
intptr_t reserved[32]; // just for future expansions or mod-makers
|
||||
} mextrasurf_t;
|
||||
|
||||
struct msurface_s
|
||||
|
|
|
@ -47,29 +47,11 @@ SETUP BACKENDS DEFINITIONS
|
|||
#endif // XASH_TIMER
|
||||
|
||||
#ifndef XASH_MESSAGEBOX
|
||||
#define XASH_MESSAGEBOX MSGBOX_SDL
|
||||
#if !XASH_NSWITCH // SDL2 messageboxes not available
|
||||
#define XASH_MESSAGEBOX MSGBOX_SDL
|
||||
#endif
|
||||
#endif // XASH_MESSAGEBOX
|
||||
#endif
|
||||
#elif XASH_ANDROID
|
||||
// we are building for Android platform, use Android APIs
|
||||
#ifndef XASH_VIDEO
|
||||
#define XASH_VIDEO VIDEO_ANDROID
|
||||
#endif // XASH_VIDEO
|
||||
|
||||
#ifndef XASH_INPUT
|
||||
#define XASH_INPUT INPUT_ANDROID
|
||||
#endif // XASH_INPUT
|
||||
|
||||
#ifndef XASH_SOUND
|
||||
#define XASH_SOUND SOUND_OPENSLES
|
||||
#endif // XASH_SOUND
|
||||
|
||||
#ifndef XASH_MESSAGEBOX
|
||||
#define XASH_MESSAGEBOX MSGBOX_ANDROID
|
||||
#endif // XASH_MESSAGEBOX
|
||||
|
||||
#define XASH_USE_EVDEV
|
||||
#define XASH_DYNAMIC_DLADDR
|
||||
#elif XASH_LINUX
|
||||
// we are building for Linux without SDL2, can draw only to framebuffer yet
|
||||
#ifndef XASH_VIDEO
|
||||
|
@ -84,7 +66,7 @@ SETUP BACKENDS DEFINITIONS
|
|||
#define XASH_SOUND SOUND_ALSA
|
||||
#endif // XASH_SOUND
|
||||
|
||||
#define XASH_USE_EVDEV
|
||||
#define XASH_USE_EVDEV 1
|
||||
#elif XASH_DOS4GW
|
||||
#ifndef XASH_VIDEO
|
||||
#define XASH_VIDEO VIDEO_DOS
|
||||
|
@ -105,22 +87,13 @@ SETUP BACKENDS DEFINITIONS
|
|||
#ifndef XASH_MESSAGEBOX
|
||||
#if XASH_WIN32
|
||||
#define XASH_MESSAGEBOX MSGBOX_WIN32
|
||||
#elif XASH_NSWITCH
|
||||
#define XASH_MESSAGEBOX MSGBOX_NSWITCH
|
||||
#else // !XASH_WIN32
|
||||
#define XASH_MESSAGEBOX MSGBOX_STDERR
|
||||
#endif // !XASH_WIN32
|
||||
#endif // XASH_MESSAGEBOX
|
||||
|
||||
//
|
||||
// select crashhandler based on defines
|
||||
//
|
||||
#ifndef XASH_CRASHHANDLER
|
||||
#if XASH_WIN32 && defined(DBGHELP)
|
||||
#define XASH_CRASHHANDLER CRASHHANDLER_DBGHELP
|
||||
#elif XASH_LINUX || XASH_BSD
|
||||
#define XASH_CRASHHANDLER CRASHHANDLER_UCONTEXT
|
||||
#endif // !(XASH_LINUX || XASH_BSD || XASH_WIN32)
|
||||
#endif
|
||||
|
||||
//
|
||||
// no timer - no xash
|
||||
//
|
||||
|
@ -157,10 +130,6 @@ SETUP BACKENDS DEFINITIONS
|
|||
#define XASH_INPUT INPUT_NULL
|
||||
#endif // XASH_INPUT
|
||||
|
||||
#ifndef XASH_CRASHHANDLER
|
||||
#define XASH_CRASHHANDLER CRASHHANDLER_NULL
|
||||
#endif // XASH_CRASHHANDLER
|
||||
|
||||
/*
|
||||
=========================================================================
|
||||
|
||||
|
@ -169,27 +138,55 @@ Default build-depended cvar and constant values
|
|||
=========================================================================
|
||||
*/
|
||||
|
||||
#if XASH_MOBILE_PLATFORM
|
||||
#define DEFAULT_TOUCH_ENABLE "1"
|
||||
#define DEFAULT_M_IGNORE "1"
|
||||
#else // !XASH_MOBILE_PLATFORM
|
||||
// Platform overrides
|
||||
#if XASH_NSWITCH
|
||||
#define DEFAULT_TOUCH_ENABLE "0"
|
||||
#define DEFAULT_M_IGNORE "0"
|
||||
#endif // !XASH_MOBILE_PLATFORM
|
||||
#define DEFAULT_M_IGNORE "1"
|
||||
#define DEFAULT_MODE_WIDTH 1280
|
||||
#define DEFAULT_MODE_HEIGHT 720
|
||||
#define DEFAULT_ALLOWCONSOLE 1
|
||||
#elif XASH_PSVITA
|
||||
#define DEFAULT_TOUCH_ENABLE "0"
|
||||
#define DEFAULT_M_IGNORE "1"
|
||||
#define DEFAULT_MODE_WIDTH 960
|
||||
#define DEFAULT_MODE_HEIGHT 544
|
||||
#define DEFAULT_ALLOWCONSOLE 1
|
||||
#elif XASH_ANDROID
|
||||
#define DEFAULT_TOUCH_ENABLE "1"
|
||||
#elif XASH_MOBILE_PLATFORM
|
||||
#define DEFAULT_TOUCH_ENABLE "1"
|
||||
#define DEFAULT_M_IGNORE "1"
|
||||
#endif // !XASH_MOBILE_PLATFORM && !XASH_NSWITCH
|
||||
|
||||
#if XASH_ANDROID || XASH_IOS || XASH_EMSCRIPTEN
|
||||
#define XASH_INTERNAL_GAMELIBS
|
||||
// this means that libraries are provided with engine, but not in game data
|
||||
// You need add library loading code to library.c when adding new platform
|
||||
// this means that libraries are provided with engine, but not in game data
|
||||
// You need add library loading code to library.c when adding new platform
|
||||
#define XASH_INTERNAL_GAMELIBS
|
||||
#endif // XASH_ANDROID || XASH_IOS || XASH_EMSCRIPTEN
|
||||
|
||||
// allow override for developer/debug builds
|
||||
// Defaults
|
||||
#ifndef DEFAULT_TOUCH_ENABLE
|
||||
#define DEFAULT_TOUCH_ENABLE "0"
|
||||
#endif // DEFAULT_TOUCH_ENABLE
|
||||
|
||||
#ifndef DEFAULT_M_IGNORE
|
||||
#define DEFAULT_M_IGNORE "0"
|
||||
#endif // DEFAULT_M_IGNORE
|
||||
|
||||
#ifndef DEFAULT_JOY_DEADZONE
|
||||
#define DEFAULT_JOY_DEADZONE "4096"
|
||||
#endif // DEFAULT_JOY_DEADZONE
|
||||
|
||||
#ifndef DEFAULT_DEV
|
||||
#define DEFAULT_DEV 0
|
||||
#endif // DEFAULT_DEV
|
||||
|
||||
#ifndef DEFAULT_ALLOWCONSOLE
|
||||
#define DEFAULT_ALLOWCONSOLE 0
|
||||
#endif // DEFAULT_ALLOWCONSOLE
|
||||
|
||||
#ifndef DEFAULT_FULLSCREEN
|
||||
#define DEFAULT_FULLSCREEN 1
|
||||
#define DEFAULT_FULLSCREEN "1" // must be a string
|
||||
#endif // DEFAULT_FULLSCREEN
|
||||
|
||||
#endif // DEFAULTS_H
|
||||
|
|
|
@ -16,22 +16,61 @@
|
|||
#ifndef NETADR_H
|
||||
#define NETADR_H
|
||||
|
||||
#include "build.h"
|
||||
#include STDINT_H
|
||||
|
||||
typedef enum
|
||||
{
|
||||
NA_UNUSED,
|
||||
NA_UNUSED = 0,
|
||||
NA_LOOPBACK,
|
||||
NA_BROADCAST,
|
||||
NA_IP,
|
||||
NA_IPX,
|
||||
NA_BROADCAST_IPX
|
||||
NA_BROADCAST_IPX,
|
||||
NA_IP6,
|
||||
NA_MULTICAST_IP6, // all nodes multicast
|
||||
} netadrtype_t;
|
||||
|
||||
// Original structure:
|
||||
// typedef struct netadr_s
|
||||
// {
|
||||
// netadrtype_t type;
|
||||
// unsigned char ip[4];
|
||||
// unsigned char ipx[10];
|
||||
// unsigned short port;
|
||||
// } netadr_t;
|
||||
|
||||
#pragma pack( push, 1 )
|
||||
typedef struct netadr_s
|
||||
{
|
||||
netadrtype_t type;
|
||||
unsigned char ip[4];
|
||||
unsigned char ipx[10];
|
||||
unsigned short port;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32_t type;
|
||||
union
|
||||
{
|
||||
uint8_t ip[4];
|
||||
uint32_t ip4;
|
||||
};
|
||||
uint8_t ipx[10];
|
||||
};
|
||||
struct
|
||||
{
|
||||
#if XASH_LITTLE_ENDIAN
|
||||
uint16_t type6;
|
||||
uint8_t ip6[16];
|
||||
#elif XASH_BIG_ENDIAN
|
||||
uint8_t ip6_0[2];
|
||||
uint16_t type6;
|
||||
uint8_t ip6_2[14];
|
||||
#endif
|
||||
};
|
||||
};
|
||||
uint16_t port;
|
||||
} netadr_t;
|
||||
#pragma pack( pop )
|
||||
|
||||
STATIC_ASSERT( sizeof( netadr_t ) == 20, "invalid netadr_t size" );
|
||||
|
||||
#endif//NETADR_H
|
||||
|
|
|
@ -39,16 +39,20 @@ GNU General Public License for more details.
|
|||
|
||||
#if XASH_POSIX
|
||||
#include <unistd.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#define PATH_SPLITTER "/"
|
||||
#define HAVE_DUP
|
||||
|
||||
#define O_BINARY 0
|
||||
#define O_TEXT 0
|
||||
#if XASH_NSWITCH
|
||||
#define SOLDER_LIBDL_COMPAT
|
||||
#include <solder.h>
|
||||
#elif XASH_PSVITA
|
||||
#define VRTLD_LIBDL_COMPAT
|
||||
#include <vrtld.h>
|
||||
#define O_BINARY 0
|
||||
#else
|
||||
#include <dlfcn.h>
|
||||
#define HAVE_DUP
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
#define O_TEXT 0
|
||||
#define _mkdir( x ) mkdir( x, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH )
|
||||
#elif XASH_DOS4GW
|
||||
#define PATH_SPLITTER "\\"
|
||||
#endif
|
||||
|
||||
typedef void* HANDLE;
|
||||
|
@ -59,7 +63,6 @@ GNU General Public License for more details.
|
|||
int x, y;
|
||||
} POINT;
|
||||
#else // WIN32
|
||||
#define PATH_SPLITTER "\\"
|
||||
#ifdef __MINGW32__
|
||||
#define _inline static inline
|
||||
#define FORCEINLINE inline __attribute__((always_inline))
|
||||
|
|
|
@ -162,7 +162,7 @@ struct ref_viewpass_s;
|
|||
typedef struct render_api_s
|
||||
{
|
||||
// Get renderer info (doesn't changes engine state at all)
|
||||
int (*RenderGetParm)( int parm, int arg ); // generic
|
||||
intptr_t (*RenderGetParm)( int parm, int arg ); // generic
|
||||
void (*GetDetailScaleForTexture)( int texture, float *xScale, float *yScale );
|
||||
void (*GetExtraParmsForTexture)( int texture, byte *red, byte *green, byte *blue, byte *alpha );
|
||||
lightstyle_t* (*GetLightStyle)( int number );
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
synctype.h -- shared synctype_t definition
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
Copyright (C) 2023 Alibek Omarov
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#ifndef SYNCTYPE_H
|
||||
#define SYNCTYPE_H
|
||||
typedef enum {ST_SYNC=0, ST_RAND } synctype_t;
|
||||
#endif
|
|
@ -4,12 +4,17 @@
|
|||
|
||||
#include "build.h"
|
||||
|
||||
#if XASH_IRIX
|
||||
#include <port.h>
|
||||
#endif
|
||||
|
||||
#if XASH_WIN32
|
||||
#include <wchar.h> // off_t
|
||||
#endif // _WIN32
|
||||
|
||||
#include <sys/types.h> // off_t
|
||||
#include STDINT_H
|
||||
#include <assert.h>
|
||||
|
||||
typedef unsigned char byte;
|
||||
typedef int sound_t;
|
||||
|
@ -22,7 +27,12 @@ typedef byte rgba_t[4]; // unsigned byte colorpack
|
|||
typedef byte rgb_t[3]; // unsigned byte colorpack
|
||||
typedef vec_t matrix3x4[3][4];
|
||||
typedef vec_t matrix4x4[4][4];
|
||||
|
||||
#if XASH_64BIT
|
||||
typedef uint32_t poolhandle_t;
|
||||
#else
|
||||
typedef void* poolhandle_t;
|
||||
#endif
|
||||
|
||||
#undef true
|
||||
#undef false
|
||||
|
@ -40,12 +50,14 @@ typedef uint64_t longtime_t;
|
|||
#define MAX_SERVERINFO_STRING 512 // server handles too many settings. expand to 1024?
|
||||
#define MAX_LOCALINFO_STRING 32768 // localinfo used on server and not sended to the clients
|
||||
#define MAX_SYSPATH 1024 // system filepath
|
||||
#define MAX_VA_STRING 1024 // string length returned by va()
|
||||
#define MAX_PRINT_MSG 8192 // how many symbols can handle single call of Con_Printf or Con_DPrintf
|
||||
#define MAX_TOKEN 2048 // parse token length
|
||||
#define MAX_MODS 512 // environment games that engine can keep visible
|
||||
#define MAX_USERMSG_LENGTH 2048 // don't modify it's relies on a client-side definitions
|
||||
|
||||
#define BIT( n ) ( 1U << ( n ))
|
||||
#define BIT64( n ) ( 1ULL << ( n ))
|
||||
#define GAMMA ( 2.2f ) // Valve Software gamma
|
||||
#define INVGAMMA ( 1.0f / 2.2f ) // back to 1.0
|
||||
#define TEXGAMMA ( 0.9f ) // compensate dim textures
|
||||
|
@ -75,16 +87,19 @@ typedef uint64_t longtime_t;
|
|||
#endif
|
||||
#define _format(x) __attribute__((format(printf, x, x+1)))
|
||||
#define NORETURN __attribute__((noreturn))
|
||||
#define NONNULL __attribute__((nonnull))
|
||||
#elif defined(_MSC_VER)
|
||||
#define EXPORT __declspec( dllexport )
|
||||
#define GAME_EXPORT
|
||||
#define _format(x)
|
||||
#define NORETURN
|
||||
#define NONNULL
|
||||
#else
|
||||
#define EXPORT
|
||||
#define GAME_EXPORT
|
||||
#define _format(x)
|
||||
#define NORETURN
|
||||
#define NONNULL
|
||||
#endif
|
||||
|
||||
#if ( __GNUC__ >= 3 )
|
||||
|
@ -103,6 +118,11 @@ typedef uint64_t longtime_t;
|
|||
#define likely(x) (x)
|
||||
#endif
|
||||
|
||||
#if defined( static_assert ) // C11 static_assert
|
||||
#define STATIC_ASSERT static_assert
|
||||
#else
|
||||
#define STATIC_ASSERT( x, y ) extern int _static_assert_##__LINE__[( x ) ? 1 : -1]
|
||||
#endif
|
||||
|
||||
#ifdef XASH_BIG_ENDIAN
|
||||
#define LittleLong(x) (((int)(((x)&255)<<24)) + ((int)((((x)>>8)&255)<<16)) + ((int)(((x)>>16)&255)<<8) + (((x) >> 24)&255))
|
||||
|
@ -161,6 +181,7 @@ typedef struct dll_info_s
|
|||
} dll_info_t;
|
||||
|
||||
typedef void (*setpair_t)( const char *key, const void *value, const void *buffer, void *numpairs );
|
||||
typedef void *(*pfnCreateInterface_t)( const char *, int * );
|
||||
|
||||
// config strings are a general means of communication from
|
||||
// the server to all connected clients.
|
||||
|
|
|
@ -1,206 +0,0 @@
|
|||
#############################################
|
||||
# Makefile.linux - linux makefile
|
||||
# Copyright (C) 2017 mittorn
|
||||
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
##############################################
|
||||
|
||||
# Default options - optimized to debug on local machine
|
||||
CC ?= gcc
|
||||
CXX ?= g++
|
||||
CFLAGS ?= -g -O1 -fsigned-char -Wall -Wextra -Wsign-compare -Wno-unknown-pragmas -Wno-missing-field-initializers -Wno-unused-parameter -Wno-unused-but-set-variable
|
||||
LDFLAGS =
|
||||
LBITS := $(shell getconf LONG_BIT)
|
||||
DEPS :=
|
||||
|
||||
XASH_COMMIT := $(firstword $(shell git rev-parse --short=6 HEAD) unknown)
|
||||
|
||||
ifeq ($(XASH_COMMIT),unknown)
|
||||
$(warning You seems to build xash3d without git)
|
||||
$(warning Please use git if you are going to publish your build)
|
||||
endif
|
||||
|
||||
# Pass 64BIT=1 to make arguments to allow amd64 builds
|
||||
ifneq ($(64BIT),1)
|
||||
ifeq ($(LBITS),64)
|
||||
LDFLAGS += -m32
|
||||
CFLAGS += -m32
|
||||
endif
|
||||
endif
|
||||
|
||||
TOPDIR = $(PWD)/..
|
||||
INCLUDES :=
|
||||
XASH_SINGLE_BINARY ?= 1
|
||||
INSTALL_DIR ?= ./install/
|
||||
ifeq ($(NANOGL),1)
|
||||
INCLUDES += -Inanogl -Inanogl/GL
|
||||
endif
|
||||
INCLUDES += -I/usr/include/SDL2 -Icommon -I../common -I. -I../pm_shared -Iclient -Iserver -Iclient/vgui -Icommon/sdl
|
||||
|
||||
#############################
|
||||
# Preprocessor defines:
|
||||
#############################
|
||||
DEFINES =
|
||||
|
||||
# Specify commit hash in version string
|
||||
DEFINES += -DXASH_BUILD_COMMIT=\"$(XASH_COMMIT)\"
|
||||
|
||||
|
||||
# Only SDL backend exists on linux
|
||||
ifeq ($(XASH_DEDICATED),1)
|
||||
DEFINES += -DXASH_DEDICATED
|
||||
else
|
||||
DEFINES += -DXASH_SDL
|
||||
LIBS += -lSDL2
|
||||
endif
|
||||
|
||||
#############################################
|
||||
# GL/GLES translators.
|
||||
# You need clone it to engine folder to use
|
||||
# Only one translator should be enabled
|
||||
#############################################
|
||||
ifeq ($(NANOGL),1)
|
||||
DEFINES += -DXASH_NANOGL -D__MULTITEXTURE_SUPPORT__ -DEGL_LIB=\"libEGL.so\"
|
||||
endif
|
||||
|
||||
ifeq ($(WES),1)
|
||||
DEFINES += -DXASH_WES -D__MULTITEXTURE_SUPPORT__ -DEGL_LIB=\"libEGL.so\"
|
||||
endif
|
||||
|
||||
ifeq ($(REGAL),1)
|
||||
DEFINES += -DXASH_REGAL -D__MULTITEXTURE_SUPPORT__ -DEGL_LIB=\"regal/lib/linux-32/libRegal.so\"
|
||||
LIBS += regal/lib/linux-32/libRegal.so
|
||||
endif
|
||||
|
||||
# Some libc implementations cannot use libdl in static builds, so disable it by default
|
||||
ifeq ($(XASH_STATIC),1)
|
||||
|
||||
ifneq ($(XASH_STATIC_LIBDL),1)
|
||||
DEFINES += -DNO_LIBDL
|
||||
endif
|
||||
|
||||
XASH_SINGLE_BINARY := 1
|
||||
endif
|
||||
|
||||
ifneq ($(XASH_STATIC),1)
|
||||
LIBS += -ldl
|
||||
endif
|
||||
|
||||
ifeq ($(XASH_STATIC_LIBDL),1)
|
||||
LIBS += -ldl
|
||||
endif
|
||||
|
||||
LIBS += -lm -pthread
|
||||
|
||||
|
||||
ifeq ($(XASH_SINGLE_BINARY),1)
|
||||
DEFINES += -DSINGLE_BINARY
|
||||
endif
|
||||
|
||||
# Collect files
|
||||
SRCS_CPP =
|
||||
SRCS = $(wildcard server/*.c) $(wildcard client/vgui/*.c) $(wildcard client/avi/*.c) $(wildcard common/*.c) $(wildcard common/imagelib/*.c) $(wildcard common/soundlib/*.c) $(wildcard common/soundlib/libmpg/*.c)
|
||||
ifneq ($(XASH_DEDICATED),1)
|
||||
SRCS += $(wildcard client/*.c)
|
||||
SRCS += $(wildcard platform/sdl/*.c)
|
||||
ifeq ($(WES),1)
|
||||
SRCS += $(wildcard gl-wes-v2/src/*.c)
|
||||
endif
|
||||
ifeq ($(NANOGL),1)
|
||||
SRCS_CPP += $(wildcard nanogl/*.cpp)
|
||||
endif
|
||||
endif
|
||||
OBJS = $(patsubst %.c,obj/%.o,$(SRCS))
|
||||
OBJS_CPP = $(patsubst %.cpp,obj/%.o,$(SRCS_CPP))
|
||||
|
||||
#################################
|
||||
# Windows DLL loader
|
||||
# Should be enabled only on i386 builds
|
||||
#################################
|
||||
LOADER :=
|
||||
ifeq ($(XASH_DLL_LOADER),1)
|
||||
DEFINES += -DDLL_LOADER
|
||||
ifeq ($(XASH_SINGLE_BINARY),1)
|
||||
LOADER = libloader.a
|
||||
else
|
||||
LOADER = libloader.so
|
||||
endif
|
||||
DEPS += $(LOADER)
|
||||
LIBS += $(LOADER)
|
||||
endif
|
||||
|
||||
# Rules for binaries
|
||||
ifeq ($(XASH_SINGLE_BINARY),0)
|
||||
BINARIES = libxash.so
|
||||
libxash.so : $(OBJS) $(OBJS_CPP) $(DEPS)
|
||||
$(CC) -fvisibility=hidden -o libxash.so $(LDFLAGS) -shared $(OBJS) $(OBJS_CPP) $(LIBS)
|
||||
|
||||
else
|
||||
BINARIES = xash
|
||||
xash: $(OBJS) $(OBJS_CPP) $(DEPS)
|
||||
ifeq ($(XASH_STATIC),1)
|
||||
$(CC) -o xash -static $(LDFLAGS) $(OBJS) $(OBJS_CPP) $(LIBS)
|
||||
else
|
||||
$(CC) -o xash -fvisibility=hidden $(LDFLAGS) $(OBJS) $(OBJS_CPP) $(LIBS)
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
ifeq ($(XASH_DLL_LOADER),1)
|
||||
$(LOADER):
|
||||
$(MAKE) -f ../loader/Makefile.linux -C ../loader $(LOADER)
|
||||
cp ../loader/$(LOADER) .
|
||||
endif
|
||||
|
||||
# Create dirs for object files
|
||||
DIRS := obj obj/server obj/client/avi obj/client/vgui obj/common/sdl obj/common/imagelib obj/common/soundlib/libmpg obj/platform/sdl obj/nanogl
|
||||
$(OBJS): | $(DIRS)
|
||||
|
||||
$(DIRS) :
|
||||
mkdir -p $(DIRS)
|
||||
|
||||
# Object rules
|
||||
obj/%.o : %.c
|
||||
$(CC) $(CFLAGS) $(INCLUDES) $(DEFINES) -c "$<" -o "$@" -Wno-unused-result -fvisibility=hidden
|
||||
|
||||
obj/%.o : %.cpp
|
||||
$(CXX) $(CFLAGS) $(INCLUDES) $(DEFINES) -c "$<" -o "$@"
|
||||
|
||||
|
||||
default: $(BINARIES)
|
||||
|
||||
.PHONY: depend clean list install
|
||||
|
||||
clean:
|
||||
$(RM) $(OBJS) $(OBJS_CPP) $(BINARIES) ../loader/*.o ../loader/*.a ../loader/*.so $(LOADER)
|
||||
|
||||
list:
|
||||
@echo Sources:
|
||||
@echo $(SRCS)
|
||||
@echo C++ Sources:
|
||||
@echo $(SRCS_CPP)
|
||||
@echo Objects:
|
||||
@echo $(OBJS) $(OBJS_CPP)
|
||||
@echo Dirs:
|
||||
@echo $(DIRS)
|
||||
@echo Dependencies:
|
||||
@echo $(DEPS)
|
||||
|
||||
# Simple install rule
|
||||
install: $(BINARIES)
|
||||
mkdir -p $(INSTALL_DIR)
|
||||
|
||||
ifeq ($(XASH_SINGLE_BINARY),1)
|
||||
cp xash $(INSTALL_DIR)/xash_bin
|
||||
else
|
||||
cp libxash.so $(INSTALL_DIR)/
|
||||
cp libloader.so $(INSTALL_DIR)/
|
||||
endif
|
|
@ -1,269 +0,0 @@
|
|||
**Table of Contents** *generated with [DocToc](http://doctoc.herokuapp.com/)*
|
||||
|
||||
- [Building](#building)
|
||||
- [Manual build (without CMake)](#manual-build-without-cmake)
|
||||
- [Building Engine](#building-engine)
|
||||
- [Building launch binary](#building-launch-binary)
|
||||
- [Building on Windows](#building-on-windows)
|
||||
- [Visual Studio 2013 (recommended for Windows)](#visual-studio-2013-recommended-for-windows)
|
||||
- [Visual Studio 6](#visual-studio-6)
|
||||
- [MinGW](#mingw)
|
||||
- [Building Game mods](#building-game-mods)
|
||||
- [Linux](#linux)
|
||||
- [microndk](#microndk)
|
||||
- [Makefile.linux](#makefile-linux)
|
||||
- [Windows](#windows)
|
||||
- [Running](#running)
|
||||
- [Manual running](#manual-running)
|
||||
- [Running with GDB](#running-with-gdb)
|
||||
- [Using DLL Loader](#using-dll-loader)
|
||||
- [Running MinGW builds](#running-mingw-builds)
|
||||
- [Running MinGW builds under GDB](#running-mingw-builds-under-gdb)
|
||||
|
||||
# Building
|
||||
|
||||
## Manual build (without CMake)
|
||||
|
||||
### Building engine
|
||||
|
||||
Clone Xash3D repository using git:
|
||||
|
||||
git clone https://github.com/FWGS/xash3d
|
||||
|
||||
Move to the Xash3D folder:
|
||||
|
||||
cd xash3d/engine
|
||||
|
||||
make -f Makefile.linux XASH_VGUI=1
|
||||
|
||||
or same for dedicated
|
||||
|
||||
make -f Makefile.linux XASH_DEDICATED=1
|
||||
|
||||
To enable dll support on linux, build loader library:
|
||||
|
||||
cd ../loader
|
||||
make -f Makefile.linux libloader.so libloader.a
|
||||
cp libloader.so libloader.a ../engine/
|
||||
|
||||
And built engine with XASH_DLL_LOADER=1:
|
||||
|
||||
cd ../engine
|
||||
make -f Makefile.linux XASH_VGUI=1 XASH_SDL=1 XASH_DLL_LOADER=1
|
||||
|
||||
or same for dedicated server
|
||||
|
||||
cd ../engine
|
||||
make -f Makefile.linux XASH_DEDICATED=1 XASH_DLL_LOADER=1
|
||||
|
||||
### Building engine in separate library
|
||||
|
||||
Some old distros does not support hidden symbol visibility
|
||||
This results in crash when loading server library
|
||||
|
||||
Building launch binary
|
||||
|
||||
cd (xash3d)/game_launch
|
||||
gcc xash.c -o xash -ldl -lrt -lm
|
||||
|
||||
Building engine library:
|
||||
|
||||
make -f Makefile.linux XASH_SINGLE_BINARY=0
|
||||
|
||||
## Building on Windows
|
||||
|
||||
### Visual Studio 2013 (recommended for Windows)
|
||||
|
||||
Download latest prebuilt SDL2 from
|
||||
|
||||
https://www.libsdl.org/release/SDL2-devel-2.0.4-VC.zip
|
||||
|
||||
Unzip and rename `SDL2-2.0.4` folder to `SDL2` and put it next to xash3d project folder.
|
||||
|
||||
..\xash3d\
|
||||
..\SDL2\
|
||||
|
||||
Open `xash.sln` with Visual Studio 2013 and make a build. After building, copy contents of `Debug` or
|
||||
`Release` folder to directory you choose. Copy `valve` folder and `vgui.dll` from your Half Life game
|
||||
installation folder and `SDL2.dll` form `\SDL2\lib\x86\` to it.
|
||||
Move `vgui_support.dll` into `valve` folder.
|
||||
|
||||
..\valve\
|
||||
..\valve\vgui_support.dll
|
||||
..\menu.dll
|
||||
..\SDL2.dll
|
||||
..\vgui.dll
|
||||
..\xash.dll
|
||||
..\xash.exe
|
||||
|
||||
Now you good to go, just run `xash.exe`.
|
||||
|
||||
### Visual Studio 6
|
||||
|
||||
This is legacy configuration, but msvc6 seems to generate more stable and more effective code
|
||||
|
||||
Setup your msvc6 enviroment, unpack SDL2-2.0.4 to xash3d folder and do:
|
||||
|
||||
cd (xash3d)\engine
|
||||
..\msvc6\build.bat
|
||||
cd (xash3d)\game_launch
|
||||
..\msvc6\build_launch.bat
|
||||
|
||||
### MinGW
|
||||
|
||||
The most effective configuration, but maybe unstable.
|
||||
Setup your MinGW environment and run:
|
||||
|
||||
cd (xash3d)\engine\
|
||||
CC=gcc mingw32-make -f Makefile.mingw
|
||||
|
||||
engine will be built to single exe binary
|
||||
|
||||
## Building game mods
|
||||
|
||||
### Linux
|
||||
|
||||
#### microndk
|
||||
|
||||
All mods that ported to android may be build to linux using Android.mk with microndk:
|
||||
|
||||
[https://github.com/SDLash3D/microndk]
|
||||
|
||||
Clone microndk repo somewhere, change xash3d_config to preffered configuration (change arch to x86
|
||||
for example)
|
||||
|
||||
Go to dlls folder if you are building server or cl_dlls if you are building client and do:
|
||||
|
||||
make -f /path/to/microndk/microndk.mk -j4
|
||||
|
||||
Do:
|
||||
|
||||
make -f /path/to/microndk/microndk.mk -j4 clean
|
||||
|
||||
every time when you build client after building server
|
||||
|
||||
#### Makefile.linux
|
||||
|
||||
### Windows
|
||||
|
||||
On windows common way is using Visual Studio as many mods does not correctly work with mingw.
|
||||
|
||||
Just open project and build it.
|
||||
|
||||
Other is using mingw and microndk, but it was not tested yet.
|
||||
|
||||
hlsdk-xash3d based mods may work fine with mingw.
|
||||
|
||||
You may use microndk to build it. Build process is very similar to linux one.
|
||||
|
||||
After setting up MinGW enviroment, do:<br>
|
||||
`mingw32-make -f \path\to\microndk\Microndk.mk`
|
||||
|
||||
to build 64-bit library, use:<br>
|
||||
`mingw32-make -f \path\to\microndk\Microndk.mk 64BIT=1`
|
||||
|
||||
Edit xash3d_config.mk to set optimal CFLAGS if you are running server
|
||||
|
||||
# Running
|
||||
|
||||
Copy **valve** folder from Half-Life:
|
||||
|
||||
cp -r $HOME/.steam/steam/steamapps/common/Half-Life/valve $HOME/Games/Xash3D
|
||||
|
||||
**NOTE**: If you build with CMake, you can now use `make install`. It will install binaries where
|
||||
they must be located. So just run `xash3d` from command line in directory where is gamedata is located.
|
||||
For additional info look to the CMakeLists.txt in repo root and xash3d.sh script.
|
||||
|
||||
After a successful build, copy the next files to some other directory where you want to run Xash3D:
|
||||
|
||||
cp engine/libxash.so game_launch/xash3d mainui/libxashmenu.so $HOME/Games/Xash3D
|
||||
|
||||
If you built it with XASH_VGUI, also copy vgui.so:
|
||||
|
||||
cp ../hlsdk/linux/vgui.so vgui_support/libvgui_support.so $HOME/Games/Xash3D
|
||||
|
||||
Copy script:
|
||||
|
||||
cp ../xash3d.sh $HOME/Games/Xash3D
|
||||
|
||||
Run:
|
||||
|
||||
cd $HOME/Games/Xash3D
|
||||
./xash3d.sh
|
||||
|
||||
## Manual running
|
||||
|
||||
Put xash3d binaries and vgui(optionally) to you game data directory and run:
|
||||
|
||||
LD_LIBRARY_PATH=. ./xash -dev 5
|
||||
|
||||
## Running under GDB
|
||||
|
||||
LD_LIBRARY_PATH=. gdb --args ./xash -dev 5
|
||||
|
||||
## Using DLL Loader
|
||||
|
||||
Put vgui_support.dll from windows build to your game data folder and run:
|
||||
|
||||
LD_LIBRARY_PATH=. ./xash -dev 5 -vguilib vgui.dll -clientlib valve/cl_dlls/client.dll -dll dlls/hl.dll
|
||||
|
||||
## Running MinGW builds
|
||||
|
||||
Put exe file to your game data directory
|
||||
|
||||
cd (game)\
|
||||
xash_bin -dev 5
|
||||
|
||||
### Running MinGW builds under GDB
|
||||
|
||||
gdb --args ./xash_bin.exe -dev 5
|
||||
|
||||
# Useful GDB commands
|
||||
|
||||
Start or restart process:
|
||||
|
||||
(gdb) r
|
||||
|
||||
Show backtrace:
|
||||
|
||||
(gdb) bt
|
||||
|
||||
Full backtrace:
|
||||
|
||||
(gdb) bt full
|
||||
|
||||
Continue execution:
|
||||
|
||||
(gdb) c
|
||||
|
||||
Recover from segmentation fault:
|
||||
|
||||
Skipping function:
|
||||
|
||||
(gdb) handle SIGSEGV nopass
|
||||
(gdb) ret
|
||||
(gdb) c
|
||||
|
||||
Restart frame for beginning:
|
||||
|
||||
(gdb) handle SIGSEGV nopass
|
||||
(gdb) jump *Host_AbortCurrentFrame
|
||||
Anti-Crash script (useful for scripting servers):
|
||||
```
|
||||
cd /path/to/rootdir
|
||||
file xash
|
||||
set args xash -dev 5 -nowcon
|
||||
handle SIGSEGV nopass
|
||||
catch signal SIGSEGV
|
||||
set $crashes=0
|
||||
commands
|
||||
print $crashes++
|
||||
if $crashes > 500
|
||||
set $crashes=0
|
||||
run
|
||||
else
|
||||
jump *Host_AbortCurrentFrame
|
||||
end
|
||||
end
|
||||
run
|
||||
```
|
|
@ -1,7 +0,0 @@
|
|||
#!/bin/sh
|
||||
SCRIPTDIR=$(dirname "$0")
|
||||
TOPDIR=$SCRIPTDIR/../../
|
||||
cp $SCRIPTDIR/Makefile.dllloader $TOPDIR/loader/
|
||||
cp $SCRIPTDIR/Makefile.emscripten $TOPDIR/engine/
|
||||
cp $SCRIPTDIR/Makefile.linux $TOPDIR/engine/
|
||||
cp $SCRIPTDIR/wscript $TOPDIR/engine/
|
|
@ -1,73 +0,0 @@
|
|||
#! /usr/bin/env python
|
||||
# encoding: utf-8
|
||||
# mittorn, 2018
|
||||
|
||||
VERSION='0.99'
|
||||
APPNAME='xash3d-fwgs'
|
||||
|
||||
top = '.'
|
||||
|
||||
def options(opt):
|
||||
opt.load('compiler_c')
|
||||
# opt.load('msvs')
|
||||
opt.add_option('--dedicated', action = 'store_true', help = 'build dedicated server only' )
|
||||
opt.add_option('--64bits', dest = 'amd64', action = 'store_true', help = 'build 64-bit engine on x86_64' )
|
||||
|
||||
|
||||
|
||||
def configure(conf):
|
||||
conf.load('compiler_c')
|
||||
conf.env.append_unique('CFLAGS', '-O2')
|
||||
conf.env.append_unique('DEFINES', 'SINGLE_BINARY')
|
||||
conf.env.append_value('LINKFLAGS', '-ldl')
|
||||
conf.env.append_value('LINKFLAGS', '-lm')
|
||||
conf.env.append_value('LINKFLAGS', '-pthread')
|
||||
|
||||
# check for 64-bit builds
|
||||
# TODO: check 32-bit toolchain and dependencies
|
||||
if conf.env.DEST_CPU == 'x86_64' and not conf.options.amd64:
|
||||
conf.env.append_value('LINKFLAGS', '-m32')
|
||||
conf.env.append_value('CFLAGS', '-m32')
|
||||
print('NOTE: will build engine with 64-bit toolchain using -m32')
|
||||
else:
|
||||
print('Warning: 64bit engine may be unstable')
|
||||
|
||||
# check for dedicated server build
|
||||
if conf.options.dedicated:
|
||||
conf.env.append_unique('DEFINES', 'XASH_DEDICATED')
|
||||
conf.env.dedicated = True
|
||||
else:
|
||||
# TODO: add way to specify SDL2 path, move to separate function
|
||||
try:
|
||||
conf.check_cfg(path='sdl2-config', args='--cflags --libs', package='', msg='Checking for SDL2', uselib_store='SDL2')
|
||||
except conf.errors.ConfigurationError:
|
||||
conf.fatal('SDL2 not availiable! If you want to build dedicated server, specify --dedicated')
|
||||
conf.env.append_unique('DEFINES', 'XASH_SDL')
|
||||
|
||||
def build(bld):
|
||||
# basic build: dedicated only, no dependencies
|
||||
use = [];
|
||||
source = bld.path.ant_glob([
|
||||
'common/*.c',
|
||||
'common/imagelib/*.c',
|
||||
'common/soundlib/*.c',
|
||||
'common/soundlib/libmpg/*.c',
|
||||
'server/*.c'])
|
||||
|
||||
# add client files and sdl2 library
|
||||
if not bld.env.dedicated:
|
||||
use += ['SDL2']
|
||||
source += bld.path.ant_glob([
|
||||
'client/*.c',
|
||||
'client/vgui/*.c',
|
||||
'client/avi/*.c',
|
||||
'platform/sdl/*.c'])
|
||||
|
||||
|
||||
bld(
|
||||
target = 'xash',
|
||||
features = 'c cprogram',
|
||||
includes = ['../common', '../pm_shared', 'common', 'server', 'client', 'client/vgui', '.' ],
|
||||
source = source,
|
||||
use = use
|
||||
)
|
|
@ -16,6 +16,10 @@
|
|||
#ifndef ALIAS_H
|
||||
#define ALIAS_H
|
||||
|
||||
#include "build.h"
|
||||
#include STDINT_H
|
||||
#include "synctype.h"
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
|
@ -39,16 +43,6 @@ Alias models are position independent, so the cache manager can move them.
|
|||
#define ALIAS_TRACER2 0x0040 // orange split trail + rotate
|
||||
#define ALIAS_TRACER3 0x0080 // purple trail
|
||||
|
||||
// must match definition in sprite.h
|
||||
#ifndef SYNCTYPE_T
|
||||
#define SYNCTYPE_T
|
||||
typedef enum
|
||||
{
|
||||
ST_SYNC = 0,
|
||||
ST_RAND
|
||||
} synctype_t;
|
||||
#endif
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ALIAS_SINGLE = 0,
|
||||
|
@ -63,36 +57,42 @@ typedef enum
|
|||
|
||||
typedef struct
|
||||
{
|
||||
int ident;
|
||||
int version;
|
||||
int32_t ident;
|
||||
int32_t version;
|
||||
vec3_t scale;
|
||||
vec3_t scale_origin;
|
||||
float boundingradius;
|
||||
vec3_t eyeposition;
|
||||
int numskins;
|
||||
int skinwidth;
|
||||
int skinheight;
|
||||
int numverts;
|
||||
int numtris;
|
||||
int numframes;
|
||||
synctype_t synctype;
|
||||
int flags;
|
||||
int32_t numskins;
|
||||
int32_t skinwidth;
|
||||
int32_t skinheight;
|
||||
int32_t numverts;
|
||||
int32_t numtris;
|
||||
int32_t numframes;
|
||||
uint32_t synctype; // was synctype_t
|
||||
int32_t flags;
|
||||
float size;
|
||||
} daliashdr_t;
|
||||
|
||||
STATIC_ASSERT( sizeof( daliashdr_t ) == 84, "invalid daliashdr_t size" );
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int onseam;
|
||||
int s;
|
||||
int t;
|
||||
int32_t onseam;
|
||||
int32_t s;
|
||||
int32_t t;
|
||||
} stvert_t;
|
||||
|
||||
STATIC_ASSERT( sizeof( stvert_t ) == 12, "invalid stvert_t size" );
|
||||
|
||||
typedef struct dtriangle_s
|
||||
{
|
||||
int facesfront;
|
||||
int vertindex[3];
|
||||
int32_t facesfront;
|
||||
int32_t vertindex[3];
|
||||
} dtriangle_t;
|
||||
|
||||
STATIC_ASSERT( sizeof( dtriangle_t ) == 16, "invalid dtriangle_t size" );
|
||||
|
||||
#define DT_FACES_FRONT 0x0010
|
||||
#define ALIAS_ONSEAM 0x0020
|
||||
|
||||
|
@ -103,36 +103,50 @@ typedef struct
|
|||
char name[16]; // frame name from grabbing
|
||||
} daliasframe_t;
|
||||
|
||||
STATIC_ASSERT( sizeof( daliasframe_t ) == 24, "invalid daliasframe_t size" );
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int numframes;
|
||||
int32_t numframes;
|
||||
trivertex_t bboxmin; // lightnormal isn't used
|
||||
trivertex_t bboxmax; // lightnormal isn't used
|
||||
} daliasgroup_t;
|
||||
|
||||
STATIC_ASSERT( sizeof( daliasgroup_t ) == 12, "invalid daliasgrou_t size" );
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int numskins;
|
||||
int32_t numskins;
|
||||
} daliasskingroup_t;
|
||||
|
||||
STATIC_ASSERT( sizeof( daliasskingroup_t ) == 4, "invalid daliasskingroup_t size" );
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float interval;
|
||||
} daliasinterval_t;
|
||||
|
||||
STATIC_ASSERT( sizeof( daliasinterval_t ) == 4, "invalid daliasinterval_t size" );
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float interval;
|
||||
} daliasskininterval_t;
|
||||
|
||||
STATIC_ASSERT( sizeof( daliasskininterval_t ) == 4, "invalid daliasskininterval_t size" );
|
||||
|
||||
typedef struct
|
||||
{
|
||||
aliasframetype_t type;
|
||||
uint32_t type; // was aliasframetype_t
|
||||
} daliasframetype_t;
|
||||
|
||||
STATIC_ASSERT( sizeof( daliasframetype_t ) == 4, "invalid daliasframetype_t size" );
|
||||
|
||||
typedef struct
|
||||
{
|
||||
aliasskintype_t type;
|
||||
uint32_t type; // was aliasskintype_t
|
||||
} daliasskintype_t;
|
||||
|
||||
STATIC_ASSERT( sizeof( daliasskintype_t ) == 4, "invalid daliasskintype_t size" );
|
||||
|
||||
#endif//ALIAS_H
|
||||
|
|
|
@ -27,7 +27,6 @@ int AVI_GetAudioChunk( movie_state_t *Avi, char *audiodata, int offset, int leng
|
|||
void AVI_OpenVideo( movie_state_t *Avi, const char *filename, qboolean load_audio, int quiet );
|
||||
movie_state_t *AVI_LoadVideo( const char *filename, qboolean load_audio );
|
||||
int AVI_TimeToSoundPosition( movie_state_t *Avi, int time );
|
||||
int AVI_GetVideoFrameCount( movie_state_t *Avi );
|
||||
void AVI_CloseVideo( movie_state_t *Avi );
|
||||
qboolean AVI_IsActive( movie_state_t *Avi );
|
||||
void AVI_FreeVideo( movie_state_t *Avi );
|
||||
|
|
|
@ -57,11 +57,6 @@ int AVI_TimeToSoundPosition( movie_state_t *Avi, int time )
|
|||
return 0;
|
||||
}
|
||||
|
||||
int AVI_GetVideoFrameCount( movie_state_t *Avi )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AVI_CloseVideo( movie_state_t *Avi )
|
||||
{
|
||||
;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
avi_win.c - playing AVI files (based on original AVIKit code, Win32 version)
|
||||
Copyright (c) 2003-2004, Ruari O'Sullivan
|
||||
Copyright (C) 2010 Uncle Mike
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
|
@ -63,7 +64,7 @@ static int (_stdcall *pAVIStreamTimeToSample)( PAVISTREAM pavi, LONG lTime );
|
|||
static void* (_stdcall *pAVIStreamGetFrame)( PGETFRAME pg, LONG lPos );
|
||||
static int (_stdcall *pAVIStreamGetFrameClose)( PGETFRAME pg );
|
||||
static dword (_stdcall *pAVIStreamRelease)( PAVISTREAM pavi );
|
||||
static int (_stdcall *pAVIFileOpen)( PAVIFILE *ppfile, LPCSTR szFile, UINT uMode, LPCLSID lpHandler );
|
||||
static int (_stdcall *pAVIFileOpenW)( PAVIFILE *ppfile, LPCWSTR szFile, UINT uMode, LPCLSID lpHandler );
|
||||
static int (_stdcall *pAVIFileGetStream)( PAVIFILE pfile, PAVISTREAM *ppavi, DWORD fccType, LONG lParam );
|
||||
static int (_stdcall *pAVIStreamReadFormat)( PAVISTREAM pavi, LONG lPos,LPVOID lpFormat, LONG *lpcbFormat );
|
||||
static int (_stdcall *pAVIStreamStart)( PAVISTREAM pavi );
|
||||
|
@ -76,7 +77,7 @@ static dllfunc_t avifile_funcs[] =
|
|||
{ "AVIFileExit", (void **) &pAVIFileExit },
|
||||
{ "AVIFileGetStream", (void **) &pAVIFileGetStream },
|
||||
{ "AVIFileInit", (void **) &pAVIFileInit },
|
||||
{ "AVIFileOpenA", (void **) &pAVIFileOpen },
|
||||
{ "AVIFileOpenW", (void **) &pAVIFileOpenW },
|
||||
{ "AVIFileRelease", (void **) &pAVIFileRelease },
|
||||
{ "AVIStreamGetFrame", (void **) &pAVIStreamGetFrame },
|
||||
{ "AVIStreamGetFrameClose", (void **) &pAVIStreamGetFrameClose },
|
||||
|
@ -278,14 +279,6 @@ int AVI_GetVideoFrameNumber( movie_state_t *Avi, float time )
|
|||
return (time * Avi->video_fps);
|
||||
}
|
||||
|
||||
int AVI_GetVideoFrameCount( movie_state_t *Avi )
|
||||
{
|
||||
if( !Avi->active )
|
||||
return 0;
|
||||
|
||||
return Avi->video_frames;
|
||||
}
|
||||
|
||||
int AVI_TimeToSoundPosition( movie_state_t *Avi, int time )
|
||||
{
|
||||
if( !Avi->active || !Avi->audio_stream )
|
||||
|
@ -493,6 +486,7 @@ void AVI_OpenVideo( movie_state_t *Avi, const char *filename, qboolean load_audi
|
|||
AVISTREAMINFO stream_info;
|
||||
int opened_streams = 0;
|
||||
LONG hr;
|
||||
wchar_t pathBuffer[MAX_PATH];
|
||||
|
||||
// default state: non-working.
|
||||
Avi->active = false;
|
||||
|
@ -501,8 +495,15 @@ void AVI_OpenVideo( movie_state_t *Avi, const char *filename, qboolean load_audi
|
|||
// can't load Video For Windows :-(
|
||||
if( !avi_initialized ) return;
|
||||
|
||||
// convert to wide char
|
||||
if( MultiByteToWideChar( CP_UTF8, 0, filename, -1, pathBuffer, ARRAYSIZE( pathBuffer )) <= 0 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "filename buffer limit exceeded\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
// load the AVI
|
||||
hr = pAVIFileOpen( &Avi->pfile, filename, OF_SHARE_DENY_WRITE, 0L );
|
||||
hr = pAVIFileOpenW( &Avi->pfile, pathBuffer, OF_SHARE_DENY_WRITE, 0L );
|
||||
|
||||
if( hr != 0 ) // error opening AVI:
|
||||
{
|
||||
|
@ -657,7 +658,7 @@ movie_state_t *AVI_LoadVideo( const char *filename, qboolean load_audio )
|
|||
|
||||
// open cinematic
|
||||
Q_snprintf( path, sizeof( path ), "media/%s", filename );
|
||||
COM_DefaultExtension( path, ".avi" );
|
||||
COM_DefaultExtension( path, ".avi", sizeof( path ));
|
||||
fullpath = FS_GetDiskPath( path, false );
|
||||
|
||||
if( FS_FileExists( path, false ) && !fullpath )
|
||||
|
|
|
@ -145,7 +145,7 @@ void CL_PlayCDTrack_f( void )
|
|||
CL_ScreenshotGetName
|
||||
==================
|
||||
*/
|
||||
qboolean CL_ScreenshotGetName( int lastnum, char *filename )
|
||||
static qboolean CL_ScreenshotGetName( int lastnum, char *filename, size_t size )
|
||||
{
|
||||
if( lastnum < 0 || lastnum > 9999 )
|
||||
{
|
||||
|
@ -153,9 +153,7 @@ qboolean CL_ScreenshotGetName( int lastnum, char *filename )
|
|||
return false;
|
||||
}
|
||||
|
||||
Q_sprintf( filename, "scrshots/%s_shot%04d.png", clgame.mapname, lastnum );
|
||||
|
||||
return true;
|
||||
return Q_snprintf( filename, size, "scrshots/%s_shot%04d.png", clgame.mapname, lastnum ) > 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -163,7 +161,7 @@ qboolean CL_ScreenshotGetName( int lastnum, char *filename )
|
|||
CL_SnapshotGetName
|
||||
==================
|
||||
*/
|
||||
qboolean CL_SnapshotGetName( int lastnum, char *filename )
|
||||
static qboolean CL_SnapshotGetName( int lastnum, char *filename, size_t size )
|
||||
{
|
||||
if( lastnum < 0 || lastnum > 9999 )
|
||||
{
|
||||
|
@ -172,9 +170,7 @@ qboolean CL_SnapshotGetName( int lastnum, char *filename )
|
|||
return false;
|
||||
}
|
||||
|
||||
Q_sprintf( filename, "../%s_%04d.png", clgame.mapname, lastnum );
|
||||
|
||||
return true;
|
||||
return Q_snprintf( filename, size, "../%s_%04d.png", clgame.mapname, lastnum ) > 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -196,7 +192,12 @@ void CL_ScreenShot_f( void )
|
|||
int i;
|
||||
string checkname;
|
||||
|
||||
if( CL_IsDevOverviewMode() == 1 )
|
||||
if ( Cmd_Argc() > 1)
|
||||
{
|
||||
Q_strncpy( cls.shotname, Cmd_Argv( 1 ), sizeof( cls.shotname ));
|
||||
cls.scrshot_action = scrshot_normal; // build new frame for screenshot
|
||||
}
|
||||
else if( CL_IsDevOverviewMode() == 1 )
|
||||
{
|
||||
// special case for write overview image and script file
|
||||
Q_snprintf( cls.shotname, sizeof( cls.shotname ), "overviews/%s.bmp", clgame.mapname );
|
||||
|
@ -207,10 +208,10 @@ void CL_ScreenShot_f( void )
|
|||
// scan for a free filename
|
||||
for( i = 0; i < 9999; i++ )
|
||||
{
|
||||
if( !CL_ScreenshotGetName( i, checkname ))
|
||||
if( !CL_ScreenshotGetName( i, checkname, sizeof( checkname )))
|
||||
return; // no namespace
|
||||
|
||||
if( !FS_FileExists( checkname, false ))
|
||||
if( !FS_FileExists( checkname, true ))
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -247,10 +248,10 @@ void CL_SnapShot_f( void )
|
|||
// scan for a free filename
|
||||
for( i = 0; i < 9999; i++ )
|
||||
{
|
||||
if( !CL_SnapshotGetName( i, checkname ))
|
||||
if( !CL_SnapshotGetName( i, checkname, sizeof( checkname )))
|
||||
return; // no namespace
|
||||
|
||||
if( !FS_FileExists( checkname, false ))
|
||||
if( !FS_FileExists( checkname, true ))
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -278,7 +279,7 @@ void CL_EnvShot_f( void )
|
|||
return;
|
||||
}
|
||||
|
||||
Q_sprintf( cls.shotname, "gfx/env/%s", Cmd_Argv( 1 ));
|
||||
Q_snprintf( cls.shotname, sizeof( cls.shotname ), "gfx/env/%s", Cmd_Argv( 1 ));
|
||||
cls.scrshot_action = scrshot_envshot; // build new frame for envshot
|
||||
cls.envshot_vieworg = NULL; // no custom view
|
||||
cls.envshot_viewsize = 0;
|
||||
|
@ -299,7 +300,7 @@ void CL_SkyShot_f( void )
|
|||
return;
|
||||
}
|
||||
|
||||
Q_sprintf( cls.shotname, "gfx/env/%s", Cmd_Argv( 1 ));
|
||||
Q_snprintf( cls.shotname, sizeof( cls.shotname ),"gfx/env/%s", Cmd_Argv( 1 ));
|
||||
cls.scrshot_action = scrshot_skyshot; // build new frame for skyshot
|
||||
cls.envshot_vieworg = NULL; // no custom view
|
||||
cls.envshot_viewsize = 0;
|
||||
|
@ -323,7 +324,8 @@ void CL_LevelShot_f( void )
|
|||
// check for exist
|
||||
if( cls.demoplayback && ( cls.demonum != -1 ))
|
||||
{
|
||||
Q_sprintf( cls.shotname, "levelshots/%s_%s.bmp", cls.demoname, refState.wideScreen ? "16x9" : "4x3" );
|
||||
Q_snprintf( cls.shotname, sizeof( cls.shotname ),
|
||||
"levelshots/%s_%s.bmp", cls.demoname, refState.wideScreen ? "16x9" : "4x3" );
|
||||
Q_snprintf( filename, sizeof( filename ), "%s.dem", cls.demoname );
|
||||
|
||||
// make sure what levelshot is newer than demo
|
||||
|
@ -332,7 +334,8 @@ void CL_LevelShot_f( void )
|
|||
}
|
||||
else
|
||||
{
|
||||
Q_sprintf( cls.shotname, "levelshots/%s_%s.bmp", clgame.mapname, refState.wideScreen ? "16x9" : "4x3" );
|
||||
Q_snprintf( cls.shotname, sizeof( cls.shotname ),
|
||||
"levelshots/%s_%s.bmp", clgame.mapname, refState.wideScreen ? "16x9" : "4x3" );
|
||||
|
||||
// make sure what levelshot is newer than bsp
|
||||
ft1 = FS_FileTime( cl.worldmodel->name, false );
|
||||
|
@ -360,7 +363,7 @@ void CL_SaveShot_f( void )
|
|||
return;
|
||||
}
|
||||
|
||||
Q_sprintf( cls.shotname, DEFAULT_SAVE_DIRECTORY "%s.bmp", Cmd_Argv( 1 ));
|
||||
Q_snprintf( cls.shotname, sizeof( cls.shotname ), DEFAULT_SAVE_DIRECTORY "%s.bmp", Cmd_Argv( 1 ));
|
||||
cls.scrshot_action = scrshot_savegame; // build new frame for saveshot
|
||||
}
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ qboolean CL_CheckFile( sizebuf_t *msg, resource_t *pResource )
|
|||
}
|
||||
|
||||
MSG_BeginClientCmd( msg, clc_stringcmd );
|
||||
MSG_WriteString( msg, va( "dlfile %s", filepath ));
|
||||
MSG_WriteStringf( msg, "dlfile %s", filepath );
|
||||
host.downloadcount++;
|
||||
|
||||
return false;
|
||||
|
|
|
@ -25,70 +25,6 @@ GNU General Public License for more details.
|
|||
#define MSG_COUNT 32 // last 32 messages parsed
|
||||
#define MSG_MASK (MSG_COUNT - 1)
|
||||
|
||||
const char *svc_strings[svc_lastmsg+1] =
|
||||
{
|
||||
"svc_bad",
|
||||
"svc_nop",
|
||||
"svc_disconnect",
|
||||
"svc_event",
|
||||
"svc_changing",
|
||||
"svc_setview",
|
||||
"svc_sound",
|
||||
"svc_time",
|
||||
"svc_print",
|
||||
"svc_stufftext",
|
||||
"svc_setangle",
|
||||
"svc_serverdata",
|
||||
"svc_lightstyle",
|
||||
"svc_updateuserinfo",
|
||||
"svc_deltatable",
|
||||
"svc_clientdata",
|
||||
"svc_resource",
|
||||
"svc_pings",
|
||||
"svc_particle",
|
||||
"svc_restoresound",
|
||||
"svc_spawnstatic",
|
||||
"svc_event_reliable",
|
||||
"svc_spawnbaseline",
|
||||
"svc_temp_entity",
|
||||
"svc_setpause",
|
||||
"svc_signonnum",
|
||||
"svc_centerprint",
|
||||
"svc_unused27",
|
||||
"svc_unused28",
|
||||
"svc_unused29",
|
||||
"svc_intermission",
|
||||
"svc_finale",
|
||||
"svc_cdtrack",
|
||||
"svc_restore",
|
||||
"svc_cutscene",
|
||||
"svc_weaponanim",
|
||||
"svc_bspdecal",
|
||||
"svc_roomtype",
|
||||
"svc_addangle",
|
||||
"svc_usermessage",
|
||||
"svc_packetentities",
|
||||
"svc_deltapacketentities",
|
||||
"svc_choke",
|
||||
"svc_resourcelist",
|
||||
"svc_deltamovevars",
|
||||
"svc_resourcerequest",
|
||||
"svc_customization",
|
||||
"svc_crosshairangle",
|
||||
"svc_soundfade",
|
||||
"svc_filetxferfailed",
|
||||
"svc_hltv",
|
||||
"svc_director",
|
||||
"svc_voiceinit",
|
||||
"svc_voicedata",
|
||||
"svc_deltapacketbones",
|
||||
"svc_unused55",
|
||||
"svc_resourcelocation",
|
||||
"svc_querycvarvalue",
|
||||
"svc_querycvarvalue2",
|
||||
"svc_exec",
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int command;
|
||||
|
@ -109,7 +45,7 @@ const char *CL_MsgInfo( int cmd )
|
|||
{
|
||||
static string sz;
|
||||
|
||||
Q_strcpy( sz, "???" );
|
||||
Q_strncpy( sz, "???", sizeof( sz ));
|
||||
|
||||
if( cmd >= 0 && cmd <= svc_lastmsg )
|
||||
{
|
||||
|
|
|
@ -372,7 +372,7 @@ void CL_WriteDemoHeader( const char *name )
|
|||
demo.header.id = IDEMOHEADER;
|
||||
demo.header.dem_protocol = DEMO_PROTOCOL;
|
||||
demo.header.net_protocol = cls.legacymode ? PROTOCOL_LEGACY_VERSION : PROTOCOL_VERSION;
|
||||
demo.header.host_fps = bound( MIN_FPS, host_maxfps->value, MAX_FPS );
|
||||
demo.header.host_fps = bound( MIN_FPS, host_maxfps.value, MAX_FPS );
|
||||
Q_strncpy( demo.header.mapname, clgame.mapname, sizeof( demo.header.mapname ));
|
||||
Q_strncpy( demo.header.comment, clgame.maptitle, sizeof( demo.header.comment ));
|
||||
Q_strncpy( demo.header.gamedir, FS_Gamedir(), sizeof( demo.header.gamedir ));
|
||||
|
@ -518,14 +518,26 @@ CL_ReadDemoCmdHeader
|
|||
read the demo command
|
||||
=================
|
||||
*/
|
||||
void CL_ReadDemoCmdHeader( byte *cmd, float *dt )
|
||||
qboolean CL_ReadDemoCmdHeader( byte *cmd, float *dt )
|
||||
{
|
||||
// read the command
|
||||
FS_Read( cls.demofile, cmd, sizeof( byte ));
|
||||
Assert( *cmd >= 1 && *cmd <= dem_lastcmd );
|
||||
// HACKHACK: skip NOPs
|
||||
do
|
||||
{
|
||||
FS_Read( cls.demofile, cmd, sizeof( byte ));
|
||||
} while( *cmd == dem_unknown );
|
||||
|
||||
if( *cmd > dem_lastcmd )
|
||||
{
|
||||
Con_Printf( S_ERROR "Demo cmd %d > %d, file offset = %d\n", *cmd, dem_lastcmd, (int)FS_Tell( cls.demofile ));
|
||||
CL_DemoCompleted();
|
||||
return false;
|
||||
}
|
||||
|
||||
// read the timestamp
|
||||
FS_Read( cls.demofile, dt, sizeof( float ));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -636,11 +648,13 @@ void CL_DemoStartPlayback( int mode )
|
|||
{
|
||||
if( cls.changedemo )
|
||||
{
|
||||
int maxclients = cl.maxclients;
|
||||
|
||||
S_StopAllSounds( true );
|
||||
SCR_BeginLoadingPlaque( false );
|
||||
|
||||
CL_ClearState ();
|
||||
CL_InitEdicts (); // re-arrange edicts
|
||||
CL_ClearState( );
|
||||
CL_InitEdicts( maxclients ); // re-arrange edicts
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -686,7 +700,7 @@ void CL_DemoAborted( void )
|
|||
cls.demofile = NULL;
|
||||
cls.demonum = -1;
|
||||
|
||||
Cvar_SetValue( "v_dark", 0.0f );
|
||||
Cvar_DirectSet( &v_dark, "0" );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -704,7 +718,7 @@ void CL_DemoCompleted( void )
|
|||
if( !CL_NextDemo() && !cls.changedemo )
|
||||
UI_SetActiveMenu( true );
|
||||
|
||||
Cvar_SetValue( "v_dark", 0.0f );
|
||||
Cvar_DirectSet( &v_dark, "0" );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -913,7 +927,8 @@ qboolean CL_DemoReadMessage( byte *buffer, size_t *length )
|
|||
if( !cls.demofile ) break;
|
||||
curpos = FS_Tell( cls.demofile );
|
||||
|
||||
CL_ReadDemoCmdHeader( &cmd, &demo.timestamp );
|
||||
if( !CL_ReadDemoCmdHeader( &cmd, &demo.timestamp ))
|
||||
return false;
|
||||
|
||||
fElapsedTime = CL_GetDemoPlaybackClock() - demo.starttime;
|
||||
if( !cls.timedemo ) bSkipMessage = ((demo.timestamp - cl_serverframetime()) >= fElapsedTime) ? true : false;
|
||||
|
@ -1109,7 +1124,10 @@ void CL_FinishTimeDemo( void )
|
|||
time = host.realtime - cls.td_starttime;
|
||||
if( !time ) time = 1.0;
|
||||
|
||||
Con_Printf( "%i frames %5.3f seconds %5.3f fps\n", frames, time, frames / time );
|
||||
Con_Printf( "timedemo result: %i frames %5.3f seconds %5.3f fps\n", frames, time, frames / time );
|
||||
|
||||
if( Sys_CheckParm( "-timedemo" ))
|
||||
CL_Quit_f();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1293,7 +1311,7 @@ void CL_CheckStartupDemos( void )
|
|||
}
|
||||
|
||||
// run demos loop in background mode
|
||||
Cvar_SetValue( "v_dark", 1.0f );
|
||||
Cvar_DirectSet( &v_dark, "1" );
|
||||
cls.demos_pending = false;
|
||||
cls.demonum = 0;
|
||||
CL_NextDemo ();
|
||||
|
@ -1304,16 +1322,16 @@ void CL_CheckStartupDemos( void )
|
|||
CL_DemoGetName
|
||||
==================
|
||||
*/
|
||||
static void CL_DemoGetName( int lastnum, char *filename )
|
||||
static void CL_DemoGetName( int lastnum, char *filename, size_t size )
|
||||
{
|
||||
if( lastnum < 0 || lastnum > 9999 )
|
||||
{
|
||||
// bound
|
||||
Q_strcpy( filename, "demo9999" );
|
||||
Q_strncpy( filename, "demo9999", size );
|
||||
return;
|
||||
}
|
||||
|
||||
Q_sprintf( filename, "demo%04d", lastnum );
|
||||
Q_snprintf( filename, size, "demo%04d", lastnum );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1367,8 +1385,10 @@ void CL_Record_f( void )
|
|||
// scan for a free filename
|
||||
for( n = 0; n < 10000; n++ )
|
||||
{
|
||||
CL_DemoGetName( n, demoname );
|
||||
if( !FS_FileExists( va( "%s.dem", demoname ), true ))
|
||||
CL_DemoGetName( n, demoname, sizeof( demoname ));
|
||||
Q_snprintf( demopath, sizeof( demopath ), "%s.dem", demoname );
|
||||
|
||||
if( !FS_FileExists( demopath, true ))
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1381,7 +1401,7 @@ void CL_Record_f( void )
|
|||
else Q_strncpy( demoname, name, sizeof( demoname ));
|
||||
|
||||
// open the demo file
|
||||
Q_sprintf( demopath, "%s.dem", demoname );
|
||||
Q_snprintf( demopath, sizeof( demopath ), "%s.dem", demoname );
|
||||
|
||||
// make sure that old demo is removed
|
||||
if( FS_FileExists( demopath, false ))
|
||||
|
@ -1408,7 +1428,7 @@ void CL_PlayDemo_f( void )
|
|||
|
||||
if( Cmd_Argc() < 2 )
|
||||
{
|
||||
Con_Printf( S_USAGE "playdemo <demoname>\n" );
|
||||
Con_Printf( S_USAGE "%s <demoname>\n", Cmd_Argv( 0 ));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1455,7 +1475,7 @@ void CL_PlayDemo_f( void )
|
|||
{
|
||||
int c, neg = false;
|
||||
|
||||
demo.header.host_fps = host_maxfps->value;
|
||||
demo.header.host_fps = host_maxfps.value;
|
||||
|
||||
while(( c = FS_Getc( cls.demofile )) != '\n' )
|
||||
{
|
||||
|
@ -1535,12 +1555,6 @@ timedemo <demoname>
|
|||
*/
|
||||
void CL_TimeDemo_f( void )
|
||||
{
|
||||
if( Cmd_Argc() != 2 )
|
||||
{
|
||||
Con_Printf( S_USAGE "timedemo <demoname>\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
CL_PlayDemo_f ();
|
||||
|
||||
// cls.td_starttime will be grabbed at the second frame of the demo, so
|
||||
|
|
|
@ -33,46 +33,6 @@ static mnode_t *r_pefragtopnode;
|
|||
static vec3_t r_emins, r_emaxs;
|
||||
static cl_entity_t *r_addent;
|
||||
|
||||
/*
|
||||
================
|
||||
R_RemoveEfrags
|
||||
|
||||
Call when removing an object from the world or moving it to another position
|
||||
================
|
||||
*/
|
||||
void R_RemoveEfrags( cl_entity_t *ent )
|
||||
{
|
||||
efrag_t *ef, *old, *walk, **prev;
|
||||
|
||||
ef = ent->efrag;
|
||||
|
||||
while( ef )
|
||||
{
|
||||
prev = &ef->leaf->efrags;
|
||||
while( 1 )
|
||||
{
|
||||
walk = *prev;
|
||||
if( !walk ) break;
|
||||
|
||||
if( walk == ef )
|
||||
{
|
||||
// remove this fragment
|
||||
*prev = ef->leafnext;
|
||||
break;
|
||||
}
|
||||
else prev = &walk->leafnext;
|
||||
}
|
||||
|
||||
old = ef;
|
||||
ef = ef->entnext;
|
||||
|
||||
// put it on the free list
|
||||
old->entnext = clgame.free_efrags;
|
||||
clgame.free_efrags = old;
|
||||
}
|
||||
ent->efrag = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
R_SplitEntityOnNode
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include "r_efx.h"
|
||||
#include "cl_tent.h"
|
||||
#include "pm_local.h"
|
||||
#define PART_SIZE Q_max( 0.5f, cl_draw_particles->value )
|
||||
#define PART_SIZE Q_max( 0.5f, cl_draw_particles.value )
|
||||
|
||||
/*
|
||||
==============================================================
|
||||
|
@ -21,9 +21,9 @@ static int ramp2[8] = { 0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x68, 0x66 };
|
|||
static int ramp3[6] = { 0x6d, 0x6b, 6, 5, 4, 3 };
|
||||
static int gSparkRamp[9] = { 0xfe, 0xfd, 0xfc, 0x6f, 0x6e, 0x6d, 0x6c, 0x67, 0x60 };
|
||||
|
||||
convar_t *tracerspeed;
|
||||
convar_t *tracerlength;
|
||||
convar_t *traceroffset;
|
||||
static CVAR_DEFINE_AUTO( tracerspeed, "6000", 0, "tracer speed" );
|
||||
static CVAR_DEFINE_AUTO( tracerlength, "0.8", 0, "tracer length factor" );
|
||||
static CVAR_DEFINE_AUTO( traceroffset, "30", 0, "tracer starting offset" );
|
||||
|
||||
particle_t *cl_active_particles;
|
||||
particle_t *cl_active_tracers;
|
||||
|
@ -100,9 +100,9 @@ void CL_InitParticles( void )
|
|||
cl_avelocities[i][2] = COM_RandomFloat( 0.0f, 2.55f );
|
||||
}
|
||||
|
||||
tracerspeed = Cvar_Get( "tracerspeed", "6000", 0, "tracer speed" );
|
||||
tracerlength = Cvar_Get( "tracerlength", "0.8", 0, "tracer length factor" );
|
||||
traceroffset = Cvar_Get( "traceroffset", "30", 0, "tracer starting offset" );
|
||||
Cvar_RegisterVariable( &tracerspeed );
|
||||
Cvar_RegisterVariable( &tracerlength );
|
||||
Cvar_RegisterVariable( &traceroffset );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -140,26 +140,6 @@ void CL_FreeParticles( void )
|
|||
cl_particles = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
CL_FreeParticle
|
||||
|
||||
move particle to freelist
|
||||
================
|
||||
*/
|
||||
void CL_FreeParticle( particle_t *p )
|
||||
{
|
||||
if( p->deathfunc )
|
||||
{
|
||||
// call right the deathfunc before die
|
||||
p->deathfunc( p );
|
||||
p->deathfunc = NULL;
|
||||
}
|
||||
|
||||
p->next = cl_free_particles;
|
||||
cl_free_particles = p;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
CL_AllocParticleFast
|
||||
|
@ -191,7 +171,7 @@ particle_t * GAME_EXPORT R_AllocParticle( void (*callback)( particle_t*, float )
|
|||
{
|
||||
particle_t *p;
|
||||
|
||||
if( !cl_draw_particles->value )
|
||||
if( !cl_draw_particles.value )
|
||||
return NULL;
|
||||
|
||||
// never alloc particles when we not in game
|
||||
|
@ -242,7 +222,7 @@ particle_t *R_AllocTracer( const vec3_t org, const vec3_t vel, float life )
|
|||
{
|
||||
particle_t *p;
|
||||
|
||||
if( !cl_draw_tracers->value )
|
||||
if( !cl_draw_tracers.value )
|
||||
return NULL;
|
||||
|
||||
// never alloc particles when we not in game
|
||||
|
@ -269,7 +249,7 @@ particle_t *R_AllocTracer( const vec3_t org, const vec3_t vel, float life )
|
|||
VectorCopy( org, p->org );
|
||||
VectorCopy( vel, p->vel );
|
||||
p->die = cl.time + life;
|
||||
p->ramp = tracerlength->value;
|
||||
p->ramp = tracerlength.value;
|
||||
p->color = 4; // select custom color
|
||||
p->packedColor = 255; // alpha
|
||||
|
||||
|
@ -1111,9 +1091,13 @@ R_ParticleExplosion2
|
|||
void GAME_EXPORT R_ParticleExplosion2( const vec3_t org, int colorStart, int colorLength )
|
||||
{
|
||||
int i, j;
|
||||
int colorMod = 0;
|
||||
int colorMod = 0, packedColor;
|
||||
particle_t *p;
|
||||
|
||||
if( FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
|
||||
packedColor = 255; // use old code for blob particles
|
||||
else packedColor = 0;
|
||||
|
||||
for( i = 0; i < 512; i++ )
|
||||
{
|
||||
p = R_AllocParticle( NULL );
|
||||
|
@ -1121,7 +1105,7 @@ void GAME_EXPORT R_ParticleExplosion2( const vec3_t org, int colorStart, int col
|
|||
|
||||
p->die = cl.time + 0.3f;
|
||||
p->color = colorStart + ( colorMod % colorLength );
|
||||
p->packedColor = 255; // use old code for blob particles
|
||||
p->packedColor = packedColor;
|
||||
colorMod++;
|
||||
|
||||
p->type = pt_blob;
|
||||
|
@ -1143,15 +1127,19 @@ R_BlobExplosion
|
|||
void GAME_EXPORT R_BlobExplosion( const vec3_t org )
|
||||
{
|
||||
particle_t *p;
|
||||
int i, j;
|
||||
int i, j, packedColor;
|
||||
|
||||
if( FBitSet( host.features, ENGINE_QUAKE_COMPATIBLE ))
|
||||
packedColor = 255; // use old code for blob particles
|
||||
else packedColor = 0;
|
||||
|
||||
for( i = 0; i < 1024; i++ )
|
||||
{
|
||||
p = R_AllocParticle( NULL );
|
||||
if( !p ) return;
|
||||
|
||||
p->die = cl.time + COM_RandomFloat( 2.0f, 2.4f );
|
||||
p->packedColor = 255; // use old code for blob particles
|
||||
p->die = cl.time + COM_RandomFloat( 1.0f, 1.4f );
|
||||
p->packedColor = packedColor;
|
||||
|
||||
if( i & 1 )
|
||||
{
|
||||
|
@ -1248,12 +1236,15 @@ R_BloodStream
|
|||
particle spray 2
|
||||
===============
|
||||
*/
|
||||
void GAME_EXPORT R_BloodStream( const vec3_t org, const vec3_t dir, int pcolor, int speed )
|
||||
void GAME_EXPORT R_BloodStream( const vec3_t org, const vec3_t ndir, int pcolor, int speed )
|
||||
{
|
||||
particle_t *p;
|
||||
int i, j;
|
||||
float arc;
|
||||
int accel = speed; // must be integer due to bug in GoldSrc
|
||||
vec3_t dir;
|
||||
|
||||
VectorNormalize2( ndir, dir );
|
||||
|
||||
for( arc = 0.05f, i = 0; i < 100; i++ )
|
||||
{
|
||||
|
@ -1816,14 +1807,14 @@ void GAME_EXPORT R_TracerEffect( const vec3_t start, const vec3_t end )
|
|||
float len, speed;
|
||||
float offset;
|
||||
|
||||
speed = Q_max( tracerspeed->value, 3.0f );
|
||||
speed = Q_max( tracerspeed.value, 3.0f );
|
||||
|
||||
VectorSubtract( end, start, dir );
|
||||
len = VectorLength( dir );
|
||||
if( len == 0.0f ) return;
|
||||
|
||||
VectorScale( dir, 1.0f / len, dir ); // normalize
|
||||
offset = COM_RandomFloat( -10.0f, 9.0f ) + traceroffset->value;
|
||||
offset = COM_RandomFloat( -10.0f, 9.0f ) + traceroffset.value;
|
||||
VectorScale( dir, offset, vel );
|
||||
VectorAdd( start, vel, pos );
|
||||
VectorScale( dir, speed, vel );
|
||||
|
@ -2079,16 +2070,16 @@ void CL_FreeDeadBeams( void )
|
|||
void CL_DrawEFX( float time, qboolean fTrans )
|
||||
{
|
||||
CL_FreeDeadBeams();
|
||||
if( CVAR_TO_BOOL( cl_draw_beams ))
|
||||
if( cl_draw_beams.value )
|
||||
ref.dllFuncs.CL_DrawBeams( fTrans, cl_active_beams );
|
||||
|
||||
if( fTrans )
|
||||
{
|
||||
R_FreeDeadParticles( &cl_active_particles );
|
||||
if( CVAR_TO_BOOL( cl_draw_particles ))
|
||||
if( cl_draw_particles.value )
|
||||
ref.dllFuncs.CL_DrawParticles( time, cl_active_particles, PART_SIZE );
|
||||
R_FreeDeadParticles( &cl_active_tracers );
|
||||
if( CVAR_TO_BOOL( cl_draw_tracers ))
|
||||
if( cl_draw_tracers.value )
|
||||
ref.dllFuncs.CL_DrawTracers( time, cl_active_tracers );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,7 +84,7 @@ void CL_DescribeEvent( event_info_t *ei, int slot )
|
|||
con_nprint_t info;
|
||||
string origin_str = { 0 }; //, angles_str = { 0 };
|
||||
|
||||
if( !cl_showevents->value )
|
||||
if( !cl_showevents.value )
|
||||
return;
|
||||
|
||||
info.time_to_live = 1.0f;
|
||||
|
@ -225,6 +225,18 @@ qboolean CL_FireEvent( event_info_t *ei, int slot )
|
|||
|
||||
if( ev->index == ei->index )
|
||||
{
|
||||
name = cl.event_precache[ei->index];
|
||||
|
||||
if( cl_trace_events.value )
|
||||
{
|
||||
Con_Printf( "^3EVENT %s AT %.2f %.2f %.2f\n" // event name
|
||||
"\t%.2f %.2f %i %i %s %s\n", // bool params
|
||||
name, ei->args.origin[0], ei->args.origin[1], ei->args.origin[2],
|
||||
ei->args.fparam1, ei->args.fparam2,
|
||||
ei->args.iparam1, ei->args.iparam2,
|
||||
ei->args.bparam1 ? "TRUE" : "FALSE", ei->args.bparam2 ? "TRUE" : "FALSE" );
|
||||
}
|
||||
|
||||
if( ev->func )
|
||||
{
|
||||
CL_DescribeEvent( ei, slot );
|
||||
|
@ -232,7 +244,6 @@ qboolean CL_FireEvent( event_info_t *ei, int slot )
|
|||
return true;
|
||||
}
|
||||
|
||||
name = cl.event_precache[ei->index];
|
||||
Con_Reportf( S_ERROR "CL_FireEvent: %s not hooked\n", name );
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,350 @@
|
|||
/*
|
||||
cl_font.c - bare bones engine font manager
|
||||
Copyright (C) 2023 Alibek Omarov
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
#include "filesystem.h"
|
||||
#include "client.h"
|
||||
#include "qfont.h"
|
||||
|
||||
qboolean CL_FixedFont( cl_font_t *font )
|
||||
{
|
||||
return font && font->valid && font->type == FONT_FIXED;
|
||||
}
|
||||
|
||||
static int CL_LoadFontTexture( const char *fontname, uint texFlags, int *width )
|
||||
{
|
||||
int font_width;
|
||||
int tex;
|
||||
|
||||
if( !g_fsapi.FileExists( fontname, false ))
|
||||
return 0;
|
||||
|
||||
tex = ref.dllFuncs.GL_LoadTexture( fontname, NULL, 0, texFlags );
|
||||
if( !tex )
|
||||
return 0;
|
||||
|
||||
font_width = REF_GET_PARM( PARM_TEX_WIDTH, tex );
|
||||
if( !font_width )
|
||||
{
|
||||
ref.dllFuncs.GL_FreeTexture( tex );
|
||||
return 0;
|
||||
}
|
||||
|
||||
*width = font_width;
|
||||
return tex;
|
||||
}
|
||||
|
||||
qboolean Con_LoadFixedWidthFont( const char *fontname, cl_font_t *font, float scale, int rendermode, uint texFlags )
|
||||
{
|
||||
int font_width, i;
|
||||
|
||||
if( font->valid )
|
||||
return true; // already loaded
|
||||
|
||||
font->hFontTexture = CL_LoadFontTexture( fontname, texFlags, &font_width );
|
||||
if( !font->hFontTexture )
|
||||
return false;
|
||||
|
||||
font->type = FONT_FIXED;
|
||||
font->valid = true;
|
||||
font->scale = scale;
|
||||
font->nearest = FBitSet( texFlags, TF_NEAREST );
|
||||
font->rendermode = rendermode;
|
||||
font->charHeight = Q_rint( font_width / 16 * scale );
|
||||
|
||||
for( i = 0; i < ARRAYSIZE( font->fontRc ); i++ )
|
||||
{
|
||||
font->fontRc[i].left = ( i * font_width / 16 ) % font_width;
|
||||
font->fontRc[i].right = font->fontRc[i].left + font_width / 16;
|
||||
font->fontRc[i].top = ( i / 16 ) * ( font_width / 16 );
|
||||
font->fontRc[i].bottom = font->fontRc[i].top + font_width / 16;
|
||||
|
||||
font->charWidths[i] = Q_rint( font_width / 16 * scale );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
qboolean Con_LoadVariableWidthFont( const char *fontname, cl_font_t *font, float scale, int rendermode, uint texFlags )
|
||||
{
|
||||
fs_offset_t length;
|
||||
qfont_t src;
|
||||
byte *pfile;
|
||||
int font_width, i;
|
||||
|
||||
if( font->valid )
|
||||
return true;
|
||||
|
||||
pfile = g_fsapi.LoadFile( fontname, &length, false );
|
||||
if( !pfile )
|
||||
return false;
|
||||
|
||||
if( length < sizeof( src ))
|
||||
{
|
||||
Mem_Free( pfile );
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy( &src, pfile, sizeof( src ));
|
||||
Mem_Free( pfile );
|
||||
|
||||
font->hFontTexture = CL_LoadFontTexture( fontname, texFlags, &font_width );
|
||||
if( !font->hFontTexture )
|
||||
return false;
|
||||
|
||||
font->type = FONT_VARIABLE;
|
||||
font->valid = true;
|
||||
font->scale = scale;
|
||||
font->nearest = FBitSet( texFlags, TF_NEAREST );
|
||||
font->rendermode = rendermode;
|
||||
font->charHeight = Q_rint( src.rowheight * scale );
|
||||
|
||||
for( i = 0; i < ARRAYSIZE( font->fontRc ); i++ )
|
||||
{
|
||||
const charinfo *ci = &src.fontinfo[i];
|
||||
|
||||
font->fontRc[i].left = (word)ci->startoffset % font_width;
|
||||
font->fontRc[i].right = font->fontRc[i].left + ci->charwidth;
|
||||
font->fontRc[i].top = (word)ci->startoffset / font_width;
|
||||
font->fontRc[i].bottom = font->fontRc[i].top + src.rowheight;
|
||||
|
||||
font->charWidths[i] = Q_rint( src.fontinfo[i].charwidth * scale );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CL_FreeFont( cl_font_t *font )
|
||||
{
|
||||
if( !font || !font->valid )
|
||||
return;
|
||||
|
||||
ref.dllFuncs.GL_FreeTexture( font->hFontTexture );
|
||||
memset( font, 0, sizeof( *font ));
|
||||
}
|
||||
|
||||
static int CL_CalcTabStop( const cl_font_t *font, int x )
|
||||
{
|
||||
int space = font->charWidths[' '];
|
||||
int tab = space * 6; // 6 spaces
|
||||
int stop = tab - x % tab;
|
||||
|
||||
if( stop < space )
|
||||
return tab * 2 - x % tab; // select next
|
||||
|
||||
return stop;
|
||||
}
|
||||
|
||||
int CL_DrawCharacter( float x, float y, int number, rgba_t color, cl_font_t *font, int flags )
|
||||
{
|
||||
wrect_t *rc;
|
||||
float w, h;
|
||||
float s1, t1, s2, t2, half = 0.5f;
|
||||
int texw, texh;
|
||||
|
||||
if( !font || !font->valid || y < -font->charHeight )
|
||||
return 0;
|
||||
|
||||
// check if printable
|
||||
if( number <= 32 )
|
||||
{
|
||||
if( number == ' ' )
|
||||
return font->charWidths[' '];
|
||||
else if( number == '\t' )
|
||||
return CL_CalcTabStop( font, x );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( FBitSet( flags, FONT_DRAW_UTF8 ))
|
||||
number = Con_UtfProcessChar( number & 255 );
|
||||
else number &= 255;
|
||||
|
||||
if( !number || !font->charWidths[number])
|
||||
return 0;
|
||||
|
||||
R_GetTextureParms( &texw, &texh, font->hFontTexture );
|
||||
if( !texw || !texh )
|
||||
return font->charWidths[number];
|
||||
|
||||
rc = &font->fontRc[number];
|
||||
if( font->nearest || font->scale <= 1.0f )
|
||||
half = 0;
|
||||
|
||||
s1 = ((float)rc->left + half ) / texw;
|
||||
t1 = ((float)rc->top + half ) / texh;
|
||||
s2 = ((float)rc->right - half ) / texw;
|
||||
t2 = ((float)rc->bottom - half ) / texh;
|
||||
w = ( rc->right - rc->left ) * font->scale;
|
||||
h = ( rc->bottom - rc->top ) * font->scale;
|
||||
|
||||
if( FBitSet( flags, FONT_DRAW_HUD ))
|
||||
SPR_AdjustSize( &x, &y, &w, &h );
|
||||
|
||||
if( !FBitSet( flags, FONT_DRAW_NORENDERMODE ))
|
||||
ref.dllFuncs.GL_SetRenderMode( font->rendermode );
|
||||
|
||||
// don't apply color to fixed fonts it's already colored
|
||||
if( font->type != FONT_FIXED || REF_GET_PARM( PARM_TEX_GLFORMAT, font->hFontTexture ) == 0x8045 ) // GL_LUMINANCE8_ALPHA8
|
||||
ref.dllFuncs.Color4ub( color[0], color[1], color[2], color[3] );
|
||||
else ref.dllFuncs.Color4ub( 255, 255, 255, color[3] );
|
||||
ref.dllFuncs.R_DrawStretchPic( x, y, w, h, s1, t1, s2, t2, font->hFontTexture );
|
||||
|
||||
return font->charWidths[number];
|
||||
}
|
||||
|
||||
int CL_DrawString( float x, float y, const char *s, rgba_t color, cl_font_t *font, int flags )
|
||||
{
|
||||
rgba_t current_color;
|
||||
int draw_len = 0;
|
||||
|
||||
if( !font || !font->valid )
|
||||
return 0;
|
||||
|
||||
if( FBitSet( flags, FONT_DRAW_UTF8 ))
|
||||
Con_UtfProcessChar( 0 ); // clear utf state
|
||||
|
||||
if( !FBitSet( flags, FONT_DRAW_NORENDERMODE ))
|
||||
ref.dllFuncs.GL_SetRenderMode( font->rendermode );
|
||||
|
||||
Vector4Copy( color, current_color );
|
||||
|
||||
while( *s )
|
||||
{
|
||||
if( *s == '\n' )
|
||||
{
|
||||
s++;
|
||||
|
||||
if( !*s )
|
||||
break;
|
||||
|
||||
// some client functions ignore newlines
|
||||
if( !FBitSet( flags, FONT_DRAW_NOLF ))
|
||||
{
|
||||
draw_len = 0;
|
||||
y += font->charHeight;
|
||||
}
|
||||
|
||||
if( FBitSet( flags, FONT_DRAW_RESETCOLORONLF ))
|
||||
Vector4Copy( color, current_color );
|
||||
continue;
|
||||
}
|
||||
|
||||
if( IsColorString( s ))
|
||||
{
|
||||
// don't copy alpha
|
||||
if( !FBitSet( flags, FONT_DRAW_FORCECOL ))
|
||||
VectorCopy( g_color_table[ColorIndex(*( s + 1 ))], current_color );
|
||||
|
||||
s += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
// skip setting rendermode, it was changed for this string already
|
||||
draw_len += CL_DrawCharacter( x + draw_len, y, (byte)*s, current_color, font, flags | FONT_DRAW_NORENDERMODE );
|
||||
|
||||
s++;
|
||||
}
|
||||
|
||||
return draw_len;
|
||||
}
|
||||
|
||||
int CL_DrawStringf( cl_font_t *font, float x, float y, rgba_t color, int flags, const char *fmt, ... )
|
||||
{
|
||||
va_list va;
|
||||
char buf[MAX_VA_STRING];
|
||||
|
||||
va_start( va, fmt );
|
||||
Q_vsnprintf( buf, sizeof( buf ), fmt, va );
|
||||
va_end( va );
|
||||
|
||||
return CL_DrawString( x, y, buf, color, font, flags );
|
||||
}
|
||||
|
||||
void CL_DrawCharacterLen( cl_font_t *font, int number, int *width, int *height )
|
||||
{
|
||||
if( !font || !font->valid ) return;
|
||||
if( width )
|
||||
{
|
||||
if( number == '\t' )
|
||||
*width = CL_CalcTabStop( font, 0 ); // at least return max tabstop
|
||||
else *width = font->charWidths[number & 255];
|
||||
}
|
||||
if( height ) *height = font->charHeight;
|
||||
}
|
||||
|
||||
void CL_DrawStringLen( cl_font_t *font, const char *s, int *width, int *height, int flags )
|
||||
{
|
||||
int draw_len = 0;
|
||||
|
||||
if( !font || !font->valid )
|
||||
return;
|
||||
|
||||
if( height )
|
||||
*height = font->charHeight;
|
||||
|
||||
if( width )
|
||||
*width = 0;
|
||||
|
||||
if( !COM_CheckString( s ))
|
||||
return;
|
||||
|
||||
if( FBitSet( flags, FONT_DRAW_UTF8 ))
|
||||
Con_UtfProcessChar( 0 ); // reset utf state
|
||||
|
||||
while( *s )
|
||||
{
|
||||
int number;
|
||||
|
||||
if( *s == '\n' )
|
||||
{
|
||||
// BUG: no check for end string here
|
||||
// but high chances somebody's relying on this
|
||||
s++;
|
||||
draw_len = 0;
|
||||
if( !FBitSet( flags, FONT_DRAW_NOLF ))
|
||||
{
|
||||
if( height )
|
||||
*height += font->charHeight;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else if( *s == '\t' )
|
||||
{
|
||||
draw_len += CL_CalcTabStop( font, 0 ); // at least return max tabstop
|
||||
s++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if( IsColorString( s ))
|
||||
{
|
||||
s += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
if( FBitSet( flags, FONT_DRAW_UTF8 ))
|
||||
number = Con_UtfProcessChar( (byte)*s );
|
||||
else number = (byte)*s;
|
||||
|
||||
if( number )
|
||||
{
|
||||
draw_len += font->charWidths[number];
|
||||
|
||||
if( draw_len > *width )
|
||||
*width = draw_len;
|
||||
}
|
||||
|
||||
s++;
|
||||
}
|
||||
}
|
|
@ -134,7 +134,7 @@ some ents will be ignore lerping
|
|||
*/
|
||||
qboolean CL_EntityIgnoreLerp( cl_entity_t *e )
|
||||
{
|
||||
if( cl_nointerp->value > 0.f )
|
||||
if( cl_nointerp.value > 0.f )
|
||||
return true;
|
||||
|
||||
if( e->model && e->model->type == mod_alias )
|
||||
|
@ -241,7 +241,7 @@ CL_GetStudioEstimatedFrame
|
|||
|
||||
====================
|
||||
*/
|
||||
float CL_GetStudioEstimatedFrame( cl_entity_t *ent )
|
||||
static float CL_GetStudioEstimatedFrame( cl_entity_t *ent )
|
||||
{
|
||||
studiohdr_t *pstudiohdr;
|
||||
mstudioseqdesc_t *pseqdesc;
|
||||
|
@ -255,7 +255,7 @@ float CL_GetStudioEstimatedFrame( cl_entity_t *ent )
|
|||
{
|
||||
sequence = bound( 0, ent->curstate.sequence, pstudiohdr->numseq - 1 );
|
||||
pseqdesc = (mstudioseqdesc_t *)((byte *)pstudiohdr + pstudiohdr->seqindex) + sequence;
|
||||
return ref.dllFuncs.R_StudioEstimateFrame( ent, pseqdesc );
|
||||
return ref.dllFuncs.R_StudioEstimateFrame( ent, pseqdesc, cl.time );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -464,13 +464,13 @@ int CL_InterpolateModel( cl_entity_t *e )
|
|||
if( cl.maxclients <= 1 )
|
||||
return 1;
|
||||
|
||||
if( e->model->type == mod_brush && !cl_bmodelinterp->value )
|
||||
if( e->model->type == mod_brush && !cl_bmodelinterp.value )
|
||||
return 1;
|
||||
|
||||
if( cl.local.moving && cl.local.onground == e->index )
|
||||
return 1;
|
||||
|
||||
t = cl.time - cl_interp->value;
|
||||
t = cl.time - cl_interp.value;
|
||||
CL_FindInterpolationUpdates( e, t, &ph0, &ph1 );
|
||||
|
||||
if( ph0 == NULL || ph1 == NULL )
|
||||
|
@ -534,10 +534,10 @@ void CL_ComputePlayerOrigin( cl_entity_t *ent )
|
|||
vec3_t origin;
|
||||
vec3_t angles;
|
||||
|
||||
if( !ent->player || ent->index == ( cl.playernum + 1 ))
|
||||
if( !ent->player )
|
||||
return;
|
||||
|
||||
if( cl_nointerp->value > 0.f )
|
||||
if( cl_nointerp.value > 0.f )
|
||||
{
|
||||
VectorCopy( ent->curstate.angles, ent->angles );
|
||||
VectorCopy( ent->curstate.origin, ent->origin );
|
||||
|
@ -555,7 +555,7 @@ void CL_ComputePlayerOrigin( cl_entity_t *ent )
|
|||
return;
|
||||
}
|
||||
|
||||
targettime = cl.time - cl_interp->value;
|
||||
targettime = cl.time - cl_interp.value;
|
||||
CL_PureOrigin( ent, targettime, origin, angles );
|
||||
|
||||
VectorCopy( angles, ent->angles );
|
||||
|
@ -654,6 +654,24 @@ FRAME PARSING
|
|||
|
||||
=========================================================================
|
||||
*/
|
||||
static qboolean CL_ParseEntityNumFromPacket( sizebuf_t *msg, int *newnum )
|
||||
{
|
||||
if( cls.legacymode )
|
||||
{
|
||||
*newnum = MSG_ReadWord( msg );
|
||||
if( *newnum == 0 )
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
*newnum = MSG_ReadUBitLong( msg, MAX_ENTITY_BITS );
|
||||
if( *newnum == LAST_EDICT )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
CL_FlushEntityPacket
|
||||
|
@ -674,8 +692,8 @@ void CL_FlushEntityPacket( sizebuf_t *msg )
|
|||
// read it all, but ignore it
|
||||
while( 1 )
|
||||
{
|
||||
newnum = MSG_ReadUBitLong( msg, MAX_ENTITY_BITS );
|
||||
if( newnum == LAST_EDICT ) break; // done
|
||||
if( !CL_ParseEntityNumFromPacket( msg, &newnum ))
|
||||
break; // done
|
||||
|
||||
if( MSG_CheckOverflow( msg ))
|
||||
Host_Error( "CL_FlushEntityPacket: overflow\n" );
|
||||
|
@ -847,21 +865,12 @@ int CL_ParsePacketEntities( sizebuf_t *msg, qboolean delta )
|
|||
|
||||
while( 1 )
|
||||
{
|
||||
int lastedict;
|
||||
if( cls.legacymode )
|
||||
{
|
||||
newnum = MSG_ReadWord( msg );
|
||||
lastedict = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
newnum = MSG_ReadUBitLong( msg, MAX_ENTITY_BITS );
|
||||
lastedict = LAST_EDICT;
|
||||
}
|
||||
if( !CL_ParseEntityNumFromPacket( msg, &newnum ))
|
||||
break; // done
|
||||
|
||||
if( newnum == lastedict ) break; // end of packet entities
|
||||
if( MSG_CheckOverflow( msg ))
|
||||
Host_Error( "CL_ParsePacketEntities: overflow\n" );
|
||||
|
||||
player = CL_IsPlayerIndex( newnum );
|
||||
|
||||
while( oldnum < newnum )
|
||||
|
@ -970,9 +979,25 @@ all the visible entities should pass this filter
|
|||
*/
|
||||
qboolean CL_AddVisibleEntity( cl_entity_t *ent, int entityType )
|
||||
{
|
||||
qboolean draw_player = true;
|
||||
|
||||
if( !ent || !ent->model )
|
||||
return false;
|
||||
|
||||
// don't add the player in firstperson mode
|
||||
if( RP_LOCALCLIENT( ent ))
|
||||
{
|
||||
cl.local.apply_effects = true;
|
||||
|
||||
if( !CL_IsThirdPerson( ) && ( ent->index == cl.viewentity ))
|
||||
{
|
||||
// we don't draw player in default renderer in firstperson mode
|
||||
// but let the client.dll know about player entity anyway
|
||||
// for use in custom renderers
|
||||
draw_player = false;
|
||||
}
|
||||
}
|
||||
|
||||
// check for adding this entity
|
||||
if( !clgame.dllFuncs.pfnAddEntity( entityType, ent, ent->model->name ))
|
||||
{
|
||||
|
@ -982,14 +1007,8 @@ qboolean CL_AddVisibleEntity( cl_entity_t *ent, int entityType )
|
|||
return false;
|
||||
}
|
||||
|
||||
// don't add the player in firstperson mode
|
||||
if( RP_LOCALCLIENT( ent ))
|
||||
{
|
||||
cl.local.apply_effects = true;
|
||||
|
||||
if( !CL_IsThirdPerson( ) && ( ent->index == cl.viewentity ))
|
||||
return false;
|
||||
}
|
||||
if( !draw_player )
|
||||
return false;
|
||||
|
||||
if( entityType == ET_BEAM )
|
||||
{
|
||||
|
@ -1094,6 +1113,9 @@ void CL_LinkPlayers( frame_t *frame )
|
|||
|
||||
if ( i == cl.playernum )
|
||||
{
|
||||
// using interpolation only for local player angles
|
||||
CL_ComputePlayerOrigin( ent );
|
||||
|
||||
if( cls.demoplayback == DEMO_QUAKE1 )
|
||||
VectorLerp( ent->prevstate.origin, cl.lerpFrac, ent->curstate.origin, cl.simorg );
|
||||
VectorCopy( cl.simorg, ent->origin );
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -310,7 +310,7 @@ static void GAME_EXPORT UI_DrawLogo( const char *filename, float x, float y, flo
|
|||
|
||||
// run cinematic if not
|
||||
Q_snprintf( path, sizeof( path ), "media/%s", filename );
|
||||
COM_DefaultExtension( path, ".avi" );
|
||||
COM_DefaultExtension( path, ".avi", sizeof( path ));
|
||||
fullpath = FS_GetDiskPath( path, false );
|
||||
|
||||
if( FS_FileExists( path, false ) && !fullpath )
|
||||
|
@ -422,54 +422,6 @@ static void UI_ConvertGameInfo( GAMEINFO *out, gameinfo_t *in )
|
|||
out->flags |= GFL_RENDER_PICBUTTON_TEXT;
|
||||
}
|
||||
|
||||
static qboolean PIC_Scissor( float *x, float *y, float *width, float *height, float *u0, float *v0, float *u1, float *v1 )
|
||||
{
|
||||
float dudx, dvdy;
|
||||
|
||||
// clip sub rect to sprite
|
||||
if(( width == 0 ) || ( height == 0 ))
|
||||
return false;
|
||||
|
||||
if( *x + *width <= gameui.ds.scissor_x )
|
||||
return false;
|
||||
if( *x >= gameui.ds.scissor_x + gameui.ds.scissor_width )
|
||||
return false;
|
||||
if( *y + *height <= gameui.ds.scissor_y )
|
||||
return false;
|
||||
if( *y >= gameui.ds.scissor_y + gameui.ds.scissor_height )
|
||||
return false;
|
||||
|
||||
dudx = (*u1 - *u0) / *width;
|
||||
dvdy = (*v1 - *v0) / *height;
|
||||
|
||||
if( *x < gameui.ds.scissor_x )
|
||||
{
|
||||
*u0 += (gameui.ds.scissor_x - *x) * dudx;
|
||||
*width -= gameui.ds.scissor_x - *x;
|
||||
*x = gameui.ds.scissor_x;
|
||||
}
|
||||
|
||||
if( *x + *width > gameui.ds.scissor_x + gameui.ds.scissor_width )
|
||||
{
|
||||
*u1 -= (*x + *width - (gameui.ds.scissor_x + gameui.ds.scissor_width)) * dudx;
|
||||
*width = gameui.ds.scissor_x + gameui.ds.scissor_width - *x;
|
||||
}
|
||||
|
||||
if( *y < gameui.ds.scissor_y )
|
||||
{
|
||||
*v0 += (gameui.ds.scissor_y - *y) * dvdy;
|
||||
*height -= gameui.ds.scissor_y - *y;
|
||||
*y = gameui.ds.scissor_y;
|
||||
}
|
||||
|
||||
if( *y + *height > gameui.ds.scissor_y + gameui.ds.scissor_height )
|
||||
{
|
||||
*v1 -= (*y + *height - (gameui.ds.scissor_y + gameui.ds.scissor_height)) * dvdy;
|
||||
*height = gameui.ds.scissor_y + gameui.ds.scissor_height - *y;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
PIC_DrawGeneric
|
||||
|
@ -488,10 +440,10 @@ static void PIC_DrawGeneric( float x, float y, float width, float height, const
|
|||
if( prc )
|
||||
{
|
||||
// calc user-defined rectangle
|
||||
s1 = (float)prc->left / (float)w;
|
||||
t1 = (float)prc->top / (float)h;
|
||||
s2 = (float)prc->right / (float)w;
|
||||
t2 = (float)prc->bottom / (float)h;
|
||||
s1 = prc->left / (float)w;
|
||||
t1 = prc->top / (float)h;
|
||||
s2 = prc->right / (float)w;
|
||||
t2 = prc->bottom / (float)h;
|
||||
|
||||
if( width == -1 && height == -1 )
|
||||
{
|
||||
|
@ -512,10 +464,9 @@ static void PIC_DrawGeneric( float x, float y, float width, float height, const
|
|||
}
|
||||
|
||||
// pass scissor test if supposed
|
||||
if( gameui.ds.scissor_test && !PIC_Scissor( &x, &y, &width, &height, &s1, &t1, &s2, &t2 ))
|
||||
if( !CL_Scissor( &gameui.ds.scissor, &x, &y, &width, &height, &s1, &t1, &s2, &t2 ))
|
||||
return;
|
||||
|
||||
PicAdjustSize( &x, &y, &width, &height );
|
||||
ref.dllFuncs.R_DrawStretchPic( x, y, width, height, s1, t1, s2, t2, gameui.ds.gl_texturenum );
|
||||
ref.dllFuncs.Color4ub( 255, 255, 255, 255 );
|
||||
}
|
||||
|
@ -660,11 +611,7 @@ static void GAME_EXPORT pfnPIC_EnableScissor( int x, int y, int width, int heigh
|
|||
width = bound( 0, width, gameui.globals->scrWidth - x );
|
||||
height = bound( 0, height, gameui.globals->scrHeight - y );
|
||||
|
||||
gameui.ds.scissor_x = x;
|
||||
gameui.ds.scissor_width = width;
|
||||
gameui.ds.scissor_y = y;
|
||||
gameui.ds.scissor_height = height;
|
||||
gameui.ds.scissor_test = true;
|
||||
CL_EnableScissor( &gameui.ds.scissor, x, y, width, height );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -675,11 +622,7 @@ pfnPIC_DisableScissor
|
|||
*/
|
||||
static void GAME_EXPORT pfnPIC_DisableScissor( void )
|
||||
{
|
||||
gameui.ds.scissor_x = 0;
|
||||
gameui.ds.scissor_width = 0;
|
||||
gameui.ds.scissor_y = 0;
|
||||
gameui.ds.scissor_height = 0;
|
||||
gameui.ds.scissor_test = false;
|
||||
CL_DisableScissor( &gameui.ds.scissor );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -700,6 +643,17 @@ static void GAME_EXPORT pfnFillRGBA( int x, int y, int width, int height, int r,
|
|||
ref.dllFuncs.Color4ub( 255, 255, 255, 255 );
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
pfnCvar_RegisterVariable
|
||||
|
||||
=============
|
||||
*/
|
||||
static cvar_t *GAME_EXPORT pfnCvar_RegisterGameUIVariable( const char *szName, const char *szValue, int flags )
|
||||
{
|
||||
return (cvar_t *)Cvar_Get( szName, szValue, flags|FCVAR_GAMEUIDLL, Cvar_BuildAutoDescription( szName, flags|FCVAR_GAMEUIDLL ));
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
pfnClientCmd
|
||||
|
@ -767,7 +721,7 @@ static void GAME_EXPORT pfnDrawCharacter( int ix, int iy, int iwidth, int iheigh
|
|||
t2 = t1 + size;
|
||||
|
||||
// pass scissor test if supposed
|
||||
if( gameui.ds.scissor_test && !PIC_Scissor( &x, &y, &width, &height, &s1, &t1, &s2, &t2 ))
|
||||
if( !CL_Scissor( &gameui.ds.scissor, &x, &y, &width, &height, &s1, &t1, &s2, &t2 ))
|
||||
return;
|
||||
|
||||
ref.dllFuncs.GL_SetRenderMode( kRenderTransTexture );
|
||||
|
@ -896,7 +850,7 @@ send client connect
|
|||
*/
|
||||
static void GAME_EXPORT pfnClientJoin( const netadr_t adr )
|
||||
{
|
||||
Cbuf_AddText( va( "connect %s\n", NET_AdrToString( adr )));
|
||||
Cbuf_AddTextf( "connect %s\n", NET_AdrToString( adr ));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1029,28 +983,21 @@ pfnCheckGameDll
|
|||
*/
|
||||
int GAME_EXPORT pfnCheckGameDll( void )
|
||||
{
|
||||
string dllpath;
|
||||
void *hInst;
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
// loading server library drains too many ram
|
||||
// so 512MB iPod Touch cannot even connect to
|
||||
// to servers in cstrike
|
||||
#ifdef XASH_INTERNAL_GAMELIBS
|
||||
return true;
|
||||
#endif
|
||||
#else
|
||||
string dllpath;
|
||||
|
||||
if( svgame.hInstance )
|
||||
return true;
|
||||
|
||||
COM_GetCommonLibraryPath( LIBRARY_SERVER, dllpath, sizeof( dllpath ));
|
||||
|
||||
if(( hInst = COM_LoadLibrary( dllpath, true, false )) != NULL )
|
||||
{
|
||||
COM_FreeLibrary( hInst ); // don't increase linker's reference counter
|
||||
if( FS_FileExists( dllpath, false ))
|
||||
return true;
|
||||
}
|
||||
Con_Reportf( S_WARN "Could not load server library: %s\n", COM_GetLibraryError() );
|
||||
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1264,6 +1211,7 @@ static ui_extendedfuncs_t gExtendedfuncs =
|
|||
Sys_DoubleTime,
|
||||
pfnParseFileSafe,
|
||||
NET_AdrToString,
|
||||
NET_CompareAdrSort,
|
||||
R_GetRenderDevice
|
||||
};
|
||||
|
||||
|
@ -1276,12 +1224,12 @@ void UI_UnloadProgs( void )
|
|||
|
||||
Cvar_FullSet( "host_gameuiloaded", "0", FCVAR_READ_ONLY );
|
||||
|
||||
Cvar_Unlink( FCVAR_GAMEUIDLL );
|
||||
Cmd_Unlink( CMD_GAMEUIDLL );
|
||||
|
||||
COM_FreeLibrary( gameui.hInstance );
|
||||
Mem_FreePool( &gameui.mempool );
|
||||
memset( &gameui, 0, sizeof( gameui ));
|
||||
|
||||
Cvar_Unlink( FCVAR_GAMEUIDLL );
|
||||
Cmd_Unlink( CMD_GAMEUIDLL );
|
||||
}
|
||||
|
||||
qboolean UI_LoadProgs( void )
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -20,14 +20,17 @@ GNU General Public License for more details.
|
|||
#include "input.h"
|
||||
#include "platform/platform.h"
|
||||
|
||||
mobile_engfuncs_t *gMobileEngfuncs;
|
||||
static mobile_engfuncs_t *gMobileEngfuncs;
|
||||
|
||||
convar_t *vibration_length;
|
||||
convar_t *vibration_enable;
|
||||
static CVAR_DEFINE_AUTO( vibration_length, "1.0", FCVAR_ARCHIVE | FCVAR_PRIVILEGED, "vibration length" );
|
||||
static CVAR_DEFINE_AUTO( vibration_enable, "1", FCVAR_ARCHIVE | FCVAR_PRIVILEGED, "enable vibration" );
|
||||
|
||||
static cl_font_t g_scaled_font;
|
||||
static float g_font_scale;
|
||||
|
||||
static void pfnVibrate( float life, char flags )
|
||||
{
|
||||
if( !vibration_enable->value )
|
||||
if( !vibration_enable.value )
|
||||
return;
|
||||
|
||||
if( life < 0.0f )
|
||||
|
@ -39,7 +42,7 @@ static void pfnVibrate( float life, char flags )
|
|||
//Con_Reportf( "Vibrate: %f %d\n", life, flags );
|
||||
|
||||
// here goes platform-specific backends
|
||||
Platform_Vibrate( life * vibration_length->value, flags );
|
||||
Platform_Vibrate( life * vibration_length.value, flags );
|
||||
}
|
||||
|
||||
static void Vibrate_f( void )
|
||||
|
@ -60,37 +63,28 @@ static void pfnEnableTextInput( int enable )
|
|||
|
||||
static int pfnDrawScaledCharacter( int x, int y, int number, int r, int g, int b, float scale )
|
||||
{
|
||||
int width = clgame.scrInfo.charWidths[number] * scale * hud_scale->value;
|
||||
int height = clgame.scrInfo.iCharHeight * scale * hud_scale->value;
|
||||
// this call is very ineffective and possibly broken!
|
||||
rgba_t color = { r, g, b, 255 };
|
||||
int flags = FONT_DRAW_HUD;
|
||||
|
||||
if( !cls.creditsFont.valid )
|
||||
return 0;
|
||||
if( hud_utf8.value )
|
||||
SetBits( flags, FONT_DRAW_UTF8 );
|
||||
|
||||
x *= hud_scale->value;
|
||||
y *= hud_scale->value;
|
||||
if( fabs( g_font_scale - scale ) > 0.1f ||
|
||||
g_scaled_font.hFontTexture != cls.creditsFont.hFontTexture )
|
||||
{
|
||||
int i;
|
||||
|
||||
number &= 255;
|
||||
number = Con_UtfProcessChar( number );
|
||||
g_scaled_font = cls.creditsFont;
|
||||
g_scaled_font.scale *= scale;
|
||||
g_scaled_font.charHeight *= scale;
|
||||
for( i = 0; i < ARRAYSIZE( g_scaled_font.charWidths ); i++ )
|
||||
g_scaled_font.charWidths[i] *= scale;
|
||||
|
||||
if( number < 32 )
|
||||
return 0;
|
||||
g_font_scale = scale;
|
||||
}
|
||||
|
||||
if( y < -height )
|
||||
return 0;
|
||||
|
||||
pfnPIC_Set( cls.creditsFont.hFontTexture, r, g, b, 255 );
|
||||
pfnPIC_DrawAdditive( x, y, width, height, &cls.creditsFont.fontRc[number] );
|
||||
|
||||
return width;
|
||||
}
|
||||
|
||||
static void *pfnGetNativeObject( const char *obj )
|
||||
{
|
||||
if( !obj )
|
||||
return NULL;
|
||||
|
||||
// Backend should consider that obj is case-sensitive
|
||||
return Platform_GetNativeObject( obj );
|
||||
return CL_DrawCharacter( x, y, number, color, &g_scaled_font, flags );
|
||||
}
|
||||
|
||||
static void pfnTouch_HideButtons( const char *name, byte state )
|
||||
|
@ -121,7 +115,7 @@ static mobile_engfuncs_t gpMobileEngfuncs =
|
|||
Touch_ResetDefaultButtons,
|
||||
pfnDrawScaledCharacter,
|
||||
Sys_Warn,
|
||||
pfnGetNativeObject,
|
||||
Sys_GetNativeObject,
|
||||
ID_SetCustomClientID,
|
||||
pfnParseFileSafe
|
||||
};
|
||||
|
@ -139,8 +133,8 @@ qboolean Mobile_Init( void )
|
|||
success = true;
|
||||
|
||||
Cmd_AddCommand( "vibrate", (xcommand_t)Vibrate_f, "Vibrate for specified time");
|
||||
vibration_length = Cvar_Get( "vibration_length", "1.0", FCVAR_ARCHIVE | FCVAR_PRIVILEGED, "Vibration length");
|
||||
vibration_enable = Cvar_Get( "vibration_enable", "1", FCVAR_ARCHIVE | FCVAR_PRIVILEGED, "Enable vibration");
|
||||
Cvar_RegisterVariable( &vibration_length );
|
||||
Cvar_RegisterVariable( &vibration_enable );
|
||||
|
||||
return success;
|
||||
}
|
||||
|
|
|
@ -33,12 +33,12 @@ GNU General Public License for more details.
|
|||
#define NETGRAPH_NET_COLORS 5
|
||||
#define NUM_LATENCY_SAMPLES 8
|
||||
|
||||
convar_t *net_graph;
|
||||
static convar_t *net_graphpos;
|
||||
static convar_t *net_graphwidth;
|
||||
static convar_t *net_graphheight;
|
||||
static convar_t *net_graphsolid;
|
||||
static convar_t *net_scale;
|
||||
CVAR_DEFINE_AUTO( net_graph, "0", FCVAR_ARCHIVE, "draw network usage graph" );
|
||||
static CVAR_DEFINE_AUTO( net_graphpos, "1", FCVAR_ARCHIVE, "network usage graph position" );
|
||||
static CVAR_DEFINE_AUTO( net_scale, "5", FCVAR_ARCHIVE, "network usage graph scale level" );
|
||||
static CVAR_DEFINE_AUTO( net_graphwidth, "192", FCVAR_ARCHIVE, "network usage graph width" );
|
||||
static CVAR_DEFINE_AUTO( net_graphheight, "64", FCVAR_ARCHIVE, "network usage graph height" );
|
||||
static CVAR_DEFINE_AUTO( net_graphsolid, "1", FCVAR_ARCHIVE, "fill segments in network usage graph" );
|
||||
|
||||
static struct packet_latency_t
|
||||
{
|
||||
|
@ -211,7 +211,7 @@ static void NetGraph_GetFrameData( float *latency, int *latency_count )
|
|||
else
|
||||
{
|
||||
int frame_latency = Q_min( 1.0f, f->latency );
|
||||
p->latency = (( frame_latency + 0.1f ) / 1.1f ) * ( net_graphheight->value - NETGRAPH_LERP_HEIGHT - 2 );
|
||||
p->latency = (( frame_latency + 0.1f ) / 1.1f ) * ( net_graphheight.value - NETGRAPH_LERP_HEIGHT - 2 );
|
||||
|
||||
if( i > cls.netchan.incoming_sequence - NUM_LATENCY_SAMPLES )
|
||||
{
|
||||
|
@ -260,7 +260,7 @@ static void NetGraph_DrawTimes( wrect_t rect, int x, int w )
|
|||
for( a = 0; a < w; a++ )
|
||||
{
|
||||
i = ( cls.netchan.outgoing_sequence - a ) & NET_TIMINGS_MASK;
|
||||
h = Q_min(( netstat_cmdinfo[i].cmd_lerp / 3.0f ) * NETGRAPH_LERP_HEIGHT, net_graphheight->value * 0.7f);
|
||||
h = Q_min(( netstat_cmdinfo[i].cmd_lerp / 3.0f ) * NETGRAPH_LERP_HEIGHT, net_graphheight.value * 0.7f);
|
||||
|
||||
fill.left = x + w - a - 1;
|
||||
fill.right = fill.bottom = 1;
|
||||
|
@ -273,7 +273,7 @@ static void NetGraph_DrawTimes( wrect_t rect, int x, int w )
|
|||
h -= extrap_point;
|
||||
fill.top -= extrap_point;
|
||||
|
||||
if( !net_graphsolid->value )
|
||||
if( !net_graphsolid.value )
|
||||
{
|
||||
fill.top -= (h - 1);
|
||||
start = (h - 1);
|
||||
|
@ -281,7 +281,10 @@ static void NetGraph_DrawTimes( wrect_t rect, int x, int w )
|
|||
|
||||
for( j = start; j < h; j++ )
|
||||
{
|
||||
NetGraph_DrawRect( &fill, netcolors[NETGRAPH_NET_COLORS + j + extrap_point] );
|
||||
int color = NETGRAPH_NET_COLORS + j + extrap_point;
|
||||
color = Q_min( color, ARRAYSIZE( netcolors ) - 1 );
|
||||
|
||||
NetGraph_DrawRect( &fill, netcolors[color] );
|
||||
fill.top--;
|
||||
}
|
||||
}
|
||||
|
@ -292,12 +295,15 @@ static void NetGraph_DrawTimes( wrect_t rect, int x, int w )
|
|||
fill.top -= h;
|
||||
h = extrap_point - h;
|
||||
|
||||
if( !net_graphsolid->value )
|
||||
if( !net_graphsolid.value )
|
||||
h = 1;
|
||||
|
||||
for( j = 0; j < h; j++ )
|
||||
{
|
||||
NetGraph_DrawRect( &fill, netcolors[NETGRAPH_NET_COLORS + j + oldh] );
|
||||
int color = NETGRAPH_NET_COLORS + j + oldh;
|
||||
color = Q_min( color, ARRAYSIZE( netcolors ) - 1 );
|
||||
|
||||
NetGraph_DrawRect( &fill, netcolors[color] );
|
||||
fill.top--;
|
||||
}
|
||||
}
|
||||
|
@ -328,7 +334,7 @@ NetGraph_DrawHatches
|
|||
*/
|
||||
static void NetGraph_DrawHatches( int x, int y )
|
||||
{
|
||||
int ystep = (int)( 10.0f / net_scale->value );
|
||||
int ystep = (int)( 10.0f / net_scale.value );
|
||||
byte colorminor[4] = { 0, 63, 63, 200 };
|
||||
byte color[4] = { 0, 200, 0, 255 };
|
||||
wrect_t hatch = { x, 4, y, 1 };
|
||||
|
@ -336,9 +342,9 @@ static void NetGraph_DrawHatches( int x, int y )
|
|||
|
||||
ystep = Q_max( ystep, 1 );
|
||||
|
||||
for( starty = hatch.top; hatch.top > 0 && ((starty - hatch.top) * net_scale->value < (maxmsgbytes + 50)); hatch.top -= ystep )
|
||||
for( starty = hatch.top; hatch.top > 0 && ((starty - hatch.top) * net_scale.value < (maxmsgbytes + 50)); hatch.top -= ystep )
|
||||
{
|
||||
if(!((int)((starty - hatch.top) * net_scale->value ) % 50 ))
|
||||
if(!((int)((starty - hatch.top) * net_scale.value ) % 50 ))
|
||||
{
|
||||
NetGraph_DrawRect( &hatch, color );
|
||||
}
|
||||
|
@ -358,19 +364,20 @@ NetGraph_DrawTextFields
|
|||
static void NetGraph_DrawTextFields( int x, int y, int w, wrect_t rect, int count, float avg, int packet_loss, int packet_choke, int graphtype )
|
||||
{
|
||||
static int lastout;
|
||||
cl_font_t *font = Con_GetFont( 0 );
|
||||
rgba_t colors = { 0.9 * 255, 0.9 * 255, 0.7 * 255, 255 };
|
||||
int ptx = Q_max( x + w - NETGRAPH_LERP_HEIGHT - 1, 1 );
|
||||
int pty = Q_max( rect.top + rect.bottom - NETGRAPH_LERP_HEIGHT - 3, 1 );
|
||||
int out, i = ( cls.netchan.outgoing_sequence - 1 ) & NET_TIMINGS_MASK;
|
||||
int j = cls.netchan.incoming_sequence & NET_TIMINGS_MASK;
|
||||
int last_y = y - net_graphheight->value;
|
||||
int last_y = y - net_graphheight.value;
|
||||
|
||||
if( count > 0 )
|
||||
{
|
||||
avg = avg / (float)( count - ( host.frametime * FRAMERATE_AVG_FRAC ));
|
||||
|
||||
if( cl_updaterate->value > 0.0f )
|
||||
avg -= 1000.0f / cl_updaterate->value;
|
||||
if( cl_updaterate.value > 0.0f )
|
||||
avg -= 1000.0f / cl_updaterate.value;
|
||||
|
||||
// can't be below zero
|
||||
avg = Q_max( 0.0f, avg );
|
||||
|
@ -379,16 +386,17 @@ static void NetGraph_DrawTextFields( int x, int y, int w, wrect_t rect, int coun
|
|||
|
||||
// move rolling average
|
||||
framerate = FRAMERATE_AVG_FRAC * host.frametime + ( 1.0f - FRAMERATE_AVG_FRAC ) * framerate;
|
||||
Con_SetFont( 0 );
|
||||
|
||||
ref.dllFuncs.GL_SetRenderMode( font->rendermode );
|
||||
|
||||
if( framerate > 0.0f )
|
||||
{
|
||||
y -= net_graphheight->value;
|
||||
y -= net_graphheight.value;
|
||||
|
||||
Con_DrawString( x, y, va( "%.1f fps" , 1.0f / framerate ), colors );
|
||||
CL_DrawStringf( font, x, y, colors, FONT_DRAW_NORENDERMODE, "%.1f fps" , 1.0f / framerate);
|
||||
|
||||
if( avg > 1.0f )
|
||||
Con_DrawString( x + 75, y, va( "%i ms" , (int)avg ), colors );
|
||||
CL_DrawStringf( font, x + 75, y, colors, FONT_DRAW_NORENDERMODE, "%i ms" , (int)avg );
|
||||
|
||||
y += 15;
|
||||
|
||||
|
@ -396,10 +404,12 @@ static void NetGraph_DrawTextFields( int x, int y, int w, wrect_t rect, int coun
|
|||
if( !out ) out = lastout;
|
||||
else lastout = out;
|
||||
|
||||
Con_DrawString( x, y, va( "in : %i %.2f kb/s", netstat_graph[j].msgbytes, cls.netchan.flow[FLOW_INCOMING].avgkbytespersec ), colors );
|
||||
CL_DrawStringf( font, x, y, colors, FONT_DRAW_NORENDERMODE,
|
||||
"in : %i %.2f kb/s", netstat_graph[j].msgbytes, cls.netchan.flow[FLOW_INCOMING].avgkbytespersec );
|
||||
y += 15;
|
||||
|
||||
Con_DrawString( x, y, va( "out: %i %.2f kb/s", out, cls.netchan.flow[FLOW_OUTGOING].avgkbytespersec ), colors );
|
||||
CL_DrawStringf( font, x, y, colors, FONT_DRAW_NORENDERMODE,
|
||||
"out: %i %.2f kb/s", out, cls.netchan.flow[FLOW_OUTGOING].avgkbytespersec );
|
||||
y += 15;
|
||||
|
||||
if( graphtype > 2 )
|
||||
|
@ -407,16 +417,14 @@ static void NetGraph_DrawTextFields( int x, int y, int w, wrect_t rect, int coun
|
|||
int loss = (int)(( packet_loss + PACKETLOSS_AVG_FRAC ) - 0.01f );
|
||||
int choke = (int)(( packet_choke + PACKETCHOKE_AVG_FRAC ) - 0.01f );
|
||||
|
||||
Con_DrawString( x, y, va( "loss: %i choke: %i", loss, choke ), colors );
|
||||
CL_DrawStringf( font, x, y, colors, FONT_DRAW_NORENDERMODE, "loss: %i choke: %i", loss, choke );
|
||||
}
|
||||
}
|
||||
|
||||
if( graphtype < 3 )
|
||||
Con_DrawString( ptx, pty, va( "%i/s", (int)cl_cmdrate->value ), colors );
|
||||
CL_DrawStringf( font, ptx, pty, colors, FONT_DRAW_NORENDERMODE, "%i/s", (int)cl_cmdrate.value );
|
||||
|
||||
Con_DrawString( ptx, last_y, va( "%i/s" , (int)cl_updaterate->value ), colors );
|
||||
|
||||
Con_RestoreFont();
|
||||
CL_DrawStringf( font, ptx, last_y, colors, FONT_DRAW_NORENDERMODE, "%i/s" , (int)cl_updaterate.value );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -427,12 +435,12 @@ NetGraph_DrawDataSegment
|
|||
*/
|
||||
static int NetGraph_DrawDataSegment( wrect_t *fill, int bytes, byte r, byte g, byte b, byte a )
|
||||
{
|
||||
float h = bytes / net_scale->value;
|
||||
float h = bytes / net_scale.value;
|
||||
byte colors[4] = { r, g, b, a };
|
||||
|
||||
fill->top -= (int)h;
|
||||
|
||||
if( net_graphsolid->value )
|
||||
if( net_graphsolid.value )
|
||||
fill->bottom = (int)h;
|
||||
else fill->bottom = 1;
|
||||
|
||||
|
@ -490,7 +498,7 @@ NetGraph_DrawDataUsage
|
|||
static void NetGraph_DrawDataUsage( int x, int y, int w, int graphtype )
|
||||
{
|
||||
int a, i, h, lastvalidh = 0, ping;
|
||||
int pingheight = net_graphheight->value - NETGRAPH_LERP_HEIGHT - 2;
|
||||
int pingheight = net_graphheight.value - NETGRAPH_LERP_HEIGHT - 2;
|
||||
wrect_t fill = { 0 };
|
||||
byte color[4];
|
||||
|
||||
|
@ -546,7 +554,7 @@ static void NetGraph_DrawDataUsage( int x, int y, int w, int graphtype )
|
|||
continue;
|
||||
|
||||
color[0] = color[1] = color[2] = color[3] = 255;
|
||||
fill.top = y - net_graphheight->value - 1;
|
||||
fill.top = y - net_graphheight.value - 1;
|
||||
fill.bottom = 1;
|
||||
|
||||
if( NetGraph_AtEdge( a, w ))
|
||||
|
@ -581,7 +589,7 @@ static void NetGraph_DrawDataUsage( int x, int y, int w, int graphtype )
|
|||
if( !NetGraph_DrawDataSegment( &fill, netstat_graph[i].voicebytes, 255, 255, 255, 255 ))
|
||||
continue;
|
||||
|
||||
fill.top = y - net_graphheight->value - 1;
|
||||
fill.top = y - net_graphheight.value - 1;
|
||||
fill.bottom = 1;
|
||||
fill.top -= 2;
|
||||
|
||||
|
@ -590,7 +598,7 @@ static void NetGraph_DrawDataUsage( int x, int y, int w, int graphtype )
|
|||
}
|
||||
|
||||
if( graphtype >= 2 )
|
||||
NetGraph_DrawHatches( x, y - net_graphheight->value - 1 );
|
||||
NetGraph_DrawHatches( x, y - net_graphheight.value - 1 );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -605,12 +613,12 @@ static void NetGraph_GetScreenPos( wrect_t *rect, int *w, int *x, int *y )
|
|||
rect->right = refState.width;
|
||||
rect->bottom = refState.height;
|
||||
|
||||
*w = Q_min( NET_TIMINGS, net_graphwidth->value );
|
||||
*w = Q_min( NET_TIMINGS, net_graphwidth.value );
|
||||
if( rect->right < *w + 10 )
|
||||
*w = rect->right - 10;
|
||||
|
||||
// detect x and y position
|
||||
switch( (int)net_graphpos->value )
|
||||
switch( (int)net_graphpos.value )
|
||||
{
|
||||
case 1: // right sided
|
||||
*x = rect->left + rect->right - 5 - *w;
|
||||
|
@ -653,16 +661,16 @@ void SCR_DrawNetGraph( void )
|
|||
{
|
||||
graphtype = 2;
|
||||
}
|
||||
else if( net_graph->value != 0.0f )
|
||||
else if( net_graph.value != 0.0f )
|
||||
{
|
||||
graphtype = (int)net_graph->value;
|
||||
graphtype = (int)net_graph.value;
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if( net_scale->value <= 0 )
|
||||
if( net_scale.value <= 0 )
|
||||
Cvar_SetValue( "net_scale", 0.1f );
|
||||
|
||||
NetGraph_GetScreenPos( &rect, &w, &x, &y );
|
||||
|
@ -689,12 +697,12 @@ void SCR_DrawNetGraph( void )
|
|||
|
||||
void CL_InitNetgraph( void )
|
||||
{
|
||||
net_graph = Cvar_Get( "net_graph", "0", FCVAR_ARCHIVE, "draw network usage graph" );
|
||||
net_graphpos = Cvar_Get( "net_graphpos", "1", FCVAR_ARCHIVE, "network usage graph position" );
|
||||
net_scale = Cvar_Get( "net_scale", "5", FCVAR_ARCHIVE, "network usage graph scale level" );
|
||||
net_graphwidth = Cvar_Get( "net_graphwidth", "192", FCVAR_ARCHIVE, "network usage graph width" );
|
||||
net_graphheight = Cvar_Get( "net_graphheight", "64", FCVAR_ARCHIVE, "network usage graph height" );
|
||||
net_graphsolid = Cvar_Get( "net_graphsolid", "1", FCVAR_ARCHIVE, "fill segments in network usage graph" );
|
||||
Cvar_RegisterVariable( &net_graph );
|
||||
Cvar_RegisterVariable( &net_graphpos );
|
||||
Cvar_RegisterVariable( &net_scale );
|
||||
Cvar_RegisterVariable( &net_graphwidth );
|
||||
Cvar_RegisterVariable( &net_graphheight );
|
||||
Cvar_RegisterVariable( &net_graphsolid );
|
||||
packet_loss = packet_choke = 0.0;
|
||||
|
||||
NetGraph_InitColors();
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,705 @@
|
|||
/*
|
||||
cl_parse.c - parse a message received from the server
|
||||
Copyright (C) 2008 Uncle Mike
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
#include "client.h"
|
||||
#include "net_encode.h"
|
||||
#include "particledef.h"
|
||||
#include "cl_tent.h"
|
||||
#include "shake.h"
|
||||
#include "hltv.h"
|
||||
#include "input.h"
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
CL_ParseStaticEntity
|
||||
|
||||
static client entity
|
||||
==================
|
||||
*/
|
||||
void CL_LegacyParseStaticEntity( sizebuf_t *msg )
|
||||
{
|
||||
int i;
|
||||
entity_state_t state;
|
||||
cl_entity_t *ent;
|
||||
|
||||
memset( &state, 0, sizeof( state ));
|
||||
state.modelindex = MSG_ReadShort( msg );
|
||||
state.sequence = MSG_ReadByte( msg );
|
||||
state.frame = MSG_ReadByte( msg );
|
||||
state.colormap = MSG_ReadWord( msg );
|
||||
state.skin = MSG_ReadByte( msg );
|
||||
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
state.origin[i] = MSG_ReadCoord( msg );
|
||||
state.angles[i] = MSG_ReadBitAngle( msg, 16 );
|
||||
}
|
||||
|
||||
state.rendermode = MSG_ReadByte( msg );
|
||||
|
||||
if( state.rendermode != kRenderNormal )
|
||||
{
|
||||
state.renderamt = MSG_ReadByte( msg );
|
||||
state.rendercolor.r = MSG_ReadByte( msg );
|
||||
state.rendercolor.g = MSG_ReadByte( msg );
|
||||
state.rendercolor.b = MSG_ReadByte( msg );
|
||||
state.renderfx = MSG_ReadByte( msg );
|
||||
}
|
||||
|
||||
i = clgame.numStatics;
|
||||
if( i >= MAX_STATIC_ENTITIES )
|
||||
{
|
||||
Con_Printf( S_ERROR "MAX_STATIC_ENTITIES limit exceeded!\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
ent = &clgame.static_entities[i];
|
||||
clgame.numStatics++;
|
||||
|
||||
// all states are same
|
||||
ent->baseline = ent->curstate = ent->prevstate = state;
|
||||
ent->index = 0; // static entities doesn't has the numbers
|
||||
|
||||
// statics may be respawned in game e.g. for demo recording
|
||||
if( cls.state == ca_connected || cls.state == ca_validate )
|
||||
ent->trivial_accept = INVALID_HANDLE;
|
||||
|
||||
// setup the new static entity
|
||||
VectorCopy( ent->curstate.origin, ent->origin );
|
||||
VectorCopy( ent->curstate.angles, ent->angles );
|
||||
ent->model = CL_ModelHandle( state.modelindex );
|
||||
ent->curstate.framerate = 1.0f;
|
||||
CL_ResetLatchedVars( ent, true );
|
||||
|
||||
if( ent->curstate.rendermode == kRenderNormal && ent->model != NULL )
|
||||
{
|
||||
// auto 'solid' faces
|
||||
if( FBitSet( ent->model->flags, MODEL_TRANSPARENT ) && Host_IsQuakeCompatible( ))
|
||||
{
|
||||
ent->curstate.rendermode = kRenderTransAlpha;
|
||||
ent->curstate.renderamt = 255;
|
||||
}
|
||||
}
|
||||
|
||||
R_AddEfrags( ent ); // add link
|
||||
}
|
||||
|
||||
void CL_LegacyParseSoundPacket( sizebuf_t *msg, qboolean is_ambient )
|
||||
{
|
||||
vec3_t pos;
|
||||
int chan, sound;
|
||||
float volume, attn;
|
||||
int flags, pitch, entnum;
|
||||
sound_t handle = 0;
|
||||
|
||||
flags = MSG_ReadWord( msg );
|
||||
if( flags & SND_LEGACY_LARGE_INDEX )
|
||||
{
|
||||
sound = MSG_ReadWord( msg );
|
||||
flags &= ~SND_LEGACY_LARGE_INDEX;
|
||||
}
|
||||
else
|
||||
sound = MSG_ReadByte( msg );
|
||||
chan = MSG_ReadByte( msg );
|
||||
|
||||
if( FBitSet( flags, SND_VOLUME ))
|
||||
volume = (float)MSG_ReadByte( msg ) / 255.0f;
|
||||
else volume = VOL_NORM;
|
||||
|
||||
if( FBitSet( flags, SND_ATTENUATION ))
|
||||
attn = (float)MSG_ReadByte( msg ) / 64.0f;
|
||||
else attn = ATTN_NONE;
|
||||
|
||||
if( FBitSet( flags, SND_PITCH ))
|
||||
pitch = MSG_ReadByte( msg );
|
||||
else pitch = PITCH_NORM;
|
||||
|
||||
// entity reletive
|
||||
entnum = MSG_ReadWord( msg );
|
||||
|
||||
// positioned in space
|
||||
MSG_ReadVec3Coord( msg, pos );
|
||||
|
||||
if( FBitSet( flags, SND_SENTENCE ))
|
||||
{
|
||||
char sentenceName[32];
|
||||
|
||||
//if( FBitSet( flags, SND_SEQUENCE ))
|
||||
//Q_snprintf( sentenceName, sizeof( sentenceName ), "!#%i", sound + MAX_SOUNDS );
|
||||
//else
|
||||
Q_snprintf( sentenceName, sizeof( sentenceName ), "!%i", sound );
|
||||
|
||||
handle = S_RegisterSound( sentenceName );
|
||||
}
|
||||
else handle = cl.sound_index[sound]; // see precached sound
|
||||
|
||||
if( !cl.audio_prepped )
|
||||
return; // too early
|
||||
|
||||
// g-cont. sound and ambient sound have only difference with channel
|
||||
if( is_ambient )
|
||||
{
|
||||
S_AmbientSound( pos, entnum, handle, volume, attn, pitch, flags );
|
||||
}
|
||||
else
|
||||
{
|
||||
S_StartSound( pos, entnum, chan, handle, volume, attn, pitch, flags );
|
||||
}
|
||||
}
|
||||
/*
|
||||
================
|
||||
CL_PrecacheSound
|
||||
|
||||
prceache sound from server
|
||||
================
|
||||
*/
|
||||
void CL_LegacyPrecacheSound( sizebuf_t *msg )
|
||||
{
|
||||
int soundIndex;
|
||||
|
||||
soundIndex = MSG_ReadUBitLong( msg, MAX_SOUND_BITS );
|
||||
|
||||
if( soundIndex < 0 || soundIndex >= MAX_SOUNDS )
|
||||
Host_Error( "CL_PrecacheSound: bad soundindex %i\n", soundIndex );
|
||||
|
||||
Q_strncpy( cl.sound_precache[soundIndex], MSG_ReadString( msg ), sizeof( cl.sound_precache[0] ));
|
||||
|
||||
// when we loading map all resources is precached sequentially
|
||||
//if( !cl.audio_prepped ) return;
|
||||
|
||||
cl.sound_index[soundIndex] = S_RegisterSound( cl.sound_precache[soundIndex] );
|
||||
}
|
||||
|
||||
void CL_LegacyPrecacheModel( sizebuf_t *msg )
|
||||
{
|
||||
int modelIndex;
|
||||
string model;
|
||||
|
||||
modelIndex = MSG_ReadUBitLong( msg, MAX_LEGACY_MODEL_BITS );
|
||||
|
||||
if( modelIndex < 0 || modelIndex >= MAX_MODELS )
|
||||
Host_Error( "CL_PrecacheModel: bad modelindex %i\n", modelIndex );
|
||||
|
||||
Q_strncpy( model, MSG_ReadString( msg ), MAX_STRING );
|
||||
//Q_strncpy( cl.model_precache[modelIndex], BF_ReadString( msg ), sizeof( cl.model_precache[0] ));
|
||||
|
||||
// when we loading map all resources is precached sequentially
|
||||
//if( !cl.video_prepped ) return;
|
||||
if( modelIndex == 1 && !cl.worldmodel )
|
||||
{
|
||||
CL_ClearWorld ();
|
||||
|
||||
cl.models[modelIndex] = cl.worldmodel = Mod_LoadWorld( model, true );
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
//Mod_RegisterModel( cl.model_precache[modelIndex], modelIndex );
|
||||
|
||||
cl.models[modelIndex] = Mod_ForName( model, false, false );
|
||||
cl.nummodels = Q_max( cl.nummodels, modelIndex );
|
||||
}
|
||||
|
||||
void CL_LegacyPrecacheEvent( sizebuf_t *msg )
|
||||
{
|
||||
int eventIndex;
|
||||
|
||||
eventIndex = MSG_ReadUBitLong( msg, MAX_EVENT_BITS );
|
||||
|
||||
if( eventIndex < 0 || eventIndex >= MAX_EVENTS )
|
||||
Host_Error( "CL_PrecacheEvent: bad eventindex %i\n", eventIndex );
|
||||
|
||||
Q_strncpy( cl.event_precache[eventIndex], MSG_ReadString( msg ), sizeof( cl.event_precache[0] ));
|
||||
|
||||
// can be set now
|
||||
CL_SetEventIndex( cl.event_precache[eventIndex], eventIndex );
|
||||
}
|
||||
|
||||
#if XASH_LOW_MEMORY == 0
|
||||
#define MAX_LEGACY_RESOURCES 2048
|
||||
#elif XASH_LOW_MEMORY == 2
|
||||
#define MAX_LEGACY_RESOURCES 1
|
||||
#elif XASH_LOW_MEMORY == 1
|
||||
#define MAX_LEGACY_RESOURCES 512
|
||||
#endif
|
||||
/*
|
||||
==============
|
||||
CL_ParseResourceList
|
||||
|
||||
==============
|
||||
*/
|
||||
void CL_LegacyParseResourceList( sizebuf_t *msg )
|
||||
{
|
||||
int i = 0;
|
||||
static struct
|
||||
{
|
||||
int rescount;
|
||||
int restype[MAX_LEGACY_RESOURCES];
|
||||
char resnames[MAX_LEGACY_RESOURCES][MAX_QPATH];
|
||||
} reslist;
|
||||
|
||||
memset( &reslist, 0, sizeof( reslist ));
|
||||
reslist.rescount = MSG_ReadWord( msg ) - 1;
|
||||
|
||||
if( reslist.rescount > MAX_LEGACY_RESOURCES )
|
||||
Host_Error("MAX_RESOURCES reached\n");
|
||||
|
||||
for( i = 0; i < reslist.rescount; i++ )
|
||||
{
|
||||
reslist.restype[i] = MSG_ReadWord( msg );
|
||||
Q_strncpy( reslist.resnames[i], MSG_ReadString( msg ), MAX_QPATH );
|
||||
}
|
||||
|
||||
if( CL_IsPlaybackDemo() )
|
||||
return;
|
||||
|
||||
if( !cl_allow_download.value )
|
||||
{
|
||||
Con_DPrintf( "Refusing new resource, cl_allow_download set to 0\n" );
|
||||
reslist.rescount = 0;
|
||||
}
|
||||
|
||||
if( cls.state == ca_active && !cl_download_ingame.value )
|
||||
{
|
||||
Con_DPrintf( "Refusing new resource, cl_download_ingame set to 0\n" );
|
||||
reslist.rescount = 0;
|
||||
}
|
||||
|
||||
HTTP_ResetProcessState();
|
||||
|
||||
host.downloadcount = 0;
|
||||
|
||||
for( i = 0; i < reslist.rescount; i++ )
|
||||
{
|
||||
char soundpath[MAX_VA_STRING];
|
||||
const char *path;
|
||||
|
||||
if( reslist.restype[i] == t_sound )
|
||||
{
|
||||
Q_snprintf( soundpath, sizeof( soundpath ), DEFAULT_SOUNDPATH "%s", reslist.resnames[i] );
|
||||
|
||||
path = soundpath;
|
||||
}
|
||||
else path = reslist.resnames[i];
|
||||
|
||||
if( FS_FileExists( path, false ))
|
||||
continue; // already exists
|
||||
|
||||
host.downloadcount++;
|
||||
HTTP_AddDownload( path, -1, true );
|
||||
}
|
||||
|
||||
if( !host.downloadcount )
|
||||
{
|
||||
MSG_WriteByte( &cls.netchan.message, clc_stringcmd );
|
||||
MSG_WriteString( &cls.netchan.message, "continueloading" );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
CL_ParseLegacyServerMessage
|
||||
|
||||
dispatch messages
|
||||
=====================
|
||||
*/
|
||||
void CL_ParseLegacyServerMessage( sizebuf_t *msg, qboolean normal_message )
|
||||
{
|
||||
size_t bufStart, playerbytes;
|
||||
int cmd, param1, param2;
|
||||
int old_background;
|
||||
const char *s;
|
||||
|
||||
cls.starting_count = MSG_GetNumBytesRead( msg ); // updates each frame
|
||||
CL_Parse_Debug( true ); // begin parsing
|
||||
|
||||
if( normal_message )
|
||||
{
|
||||
// assume no entity/player update this packet
|
||||
if( cls.state == ca_active )
|
||||
{
|
||||
cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK].valid = false;
|
||||
cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK].choked = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
CL_ResetFrame( &cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK] );
|
||||
}
|
||||
}
|
||||
|
||||
// parse the message
|
||||
while( 1 )
|
||||
{
|
||||
if( MSG_CheckOverflow( msg ))
|
||||
{
|
||||
Host_Error( "CL_ParseServerMessage: overflow!\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
// mark start position
|
||||
bufStart = MSG_GetNumBytesRead( msg );
|
||||
|
||||
// end of message (align bits)
|
||||
if( MSG_GetNumBitsLeft( msg ) < 8 )
|
||||
break;
|
||||
|
||||
cmd = MSG_ReadServerCmd( msg );
|
||||
|
||||
// record command for debugging spew on parse problem
|
||||
CL_Parse_RecordCommand( cmd, bufStart );
|
||||
|
||||
// other commands
|
||||
switch( cmd )
|
||||
{
|
||||
case svc_bad:
|
||||
Host_Error( "svc_bad\n" );
|
||||
break;
|
||||
case svc_nop:
|
||||
// this does nothing
|
||||
break;
|
||||
case svc_disconnect:
|
||||
CL_Drop ();
|
||||
Host_AbortCurrentFrame ();
|
||||
break;
|
||||
case svc_legacy_event:
|
||||
CL_ParseEvent( msg );
|
||||
cl.frames[cl.parsecountmod].graphdata.event += MSG_GetNumBytesRead( msg ) - bufStart;
|
||||
break;
|
||||
case svc_legacy_changing:
|
||||
old_background = cl.background;
|
||||
if( MSG_ReadOneBit( msg ))
|
||||
{
|
||||
int maxclients = cl.maxclients;
|
||||
|
||||
cls.changelevel = true;
|
||||
S_StopAllSounds( true );
|
||||
|
||||
Con_Printf( "Server changing, reconnecting\n" );
|
||||
|
||||
if( cls.demoplayback )
|
||||
{
|
||||
SCR_BeginLoadingPlaque( cl.background );
|
||||
cls.changedemo = true;
|
||||
}
|
||||
|
||||
CL_ClearState( );
|
||||
|
||||
// a1ba: need to restore cl.maxclients because engine chooses
|
||||
// frame backups count depending on this value
|
||||
// In general, it's incorrect to call CL_InitEdicts right after
|
||||
// CL_ClearState because of this bug. Some time later this logic
|
||||
// should be re-done.
|
||||
CL_InitEdicts( maxclients ); // re-arrange edicts
|
||||
}
|
||||
else Con_Printf( "Server disconnected, reconnecting\n" );
|
||||
|
||||
if( cls.demoplayback )
|
||||
{
|
||||
cl.background = (cls.demonum != -1) ? true : false;
|
||||
cls.state = ca_connected;
|
||||
}
|
||||
else
|
||||
{
|
||||
// g-cont. local client skip the challenge
|
||||
if( SV_Active( ))
|
||||
cls.state = ca_disconnected;
|
||||
else cls.state = ca_connecting;
|
||||
cl.background = old_background;
|
||||
cls.connect_time = MAX_HEARTBEAT;
|
||||
cls.connect_retry = 0;
|
||||
}
|
||||
break;
|
||||
case svc_setview:
|
||||
CL_ParseViewEntity( msg );
|
||||
break;
|
||||
case svc_sound:
|
||||
CL_LegacyParseSoundPacket( msg, false );
|
||||
cl.frames[cl.parsecountmod].graphdata.sound += MSG_GetNumBytesRead( msg ) - bufStart;
|
||||
break;
|
||||
case svc_legacy_ambientsound:
|
||||
CL_LegacyParseSoundPacket( msg, true );
|
||||
cl.frames[cl.parsecountmod].graphdata.sound += MSG_GetNumBytesRead( msg ) - bufStart;
|
||||
|
||||
break;
|
||||
case svc_time:
|
||||
CL_ParseServerTime( msg );
|
||||
break;
|
||||
case svc_print:
|
||||
Con_Printf( "%s", MSG_ReadString( msg ));
|
||||
break;
|
||||
case svc_stufftext:
|
||||
s = MSG_ReadString( msg );
|
||||
#ifdef HACKS_RELATED_HLMODS
|
||||
// disable Cry Of Fear antisave protection
|
||||
if( !Q_strnicmp( s, "disconnect", 10 ) && cls.signon != SIGNONS )
|
||||
break; // too early
|
||||
#endif
|
||||
|
||||
Con_Reportf( "Stufftext: %s", s );
|
||||
Cbuf_AddFilteredText( s );
|
||||
break;
|
||||
case svc_setangle:
|
||||
CL_ParseSetAngle( msg );
|
||||
break;
|
||||
case svc_serverdata:
|
||||
Cbuf_Execute(); // make sure any stuffed commands are done
|
||||
CL_ParseServerData( msg, true );
|
||||
break;
|
||||
case svc_lightstyle:
|
||||
CL_ParseLightStyle( msg );
|
||||
break;
|
||||
case svc_updateuserinfo:
|
||||
CL_UpdateUserinfo( msg, true );
|
||||
break;
|
||||
case svc_deltatable:
|
||||
Delta_ParseTableField( msg );
|
||||
break;
|
||||
case svc_clientdata:
|
||||
CL_ParseClientData( msg );
|
||||
cl.frames[cl.parsecountmod].graphdata.client += MSG_GetNumBytesRead( msg ) - bufStart;
|
||||
break;
|
||||
case svc_resource:
|
||||
CL_ParseResource( msg );
|
||||
break;
|
||||
case svc_pings:
|
||||
CL_UpdateUserPings( msg );
|
||||
break;
|
||||
case svc_particle:
|
||||
CL_ParseParticles( msg );
|
||||
break;
|
||||
case svc_restoresound:
|
||||
CL_ParseRestoreSoundPacket( msg );
|
||||
cl.frames[cl.parsecountmod].graphdata.sound += MSG_GetNumBytesRead( msg ) - bufStart;
|
||||
break;
|
||||
case svc_spawnstatic:
|
||||
CL_LegacyParseStaticEntity( msg );
|
||||
break;
|
||||
case svc_event_reliable:
|
||||
CL_ParseReliableEvent( msg );
|
||||
cl.frames[cl.parsecountmod].graphdata.event += MSG_GetNumBytesRead( msg ) - bufStart;
|
||||
break;
|
||||
case svc_spawnbaseline:
|
||||
CL_ParseBaseline( msg, true );
|
||||
break;
|
||||
case svc_temp_entity:
|
||||
CL_ParseTempEntity( msg );
|
||||
cl.frames[cl.parsecountmod].graphdata.tentities += MSG_GetNumBytesRead( msg ) - bufStart;
|
||||
break;
|
||||
case svc_setpause:
|
||||
cl.paused = ( MSG_ReadOneBit( msg ) != 0 );
|
||||
break;
|
||||
case svc_signonnum:
|
||||
CL_ParseSignon( msg );
|
||||
break;
|
||||
case svc_centerprint:
|
||||
CL_CenterPrint( MSG_ReadString( msg ), 0.25f );
|
||||
break;
|
||||
case svc_intermission:
|
||||
cl.intermission = 1;
|
||||
break;
|
||||
case svc_legacy_modelindex:
|
||||
CL_LegacyPrecacheModel( msg );
|
||||
break;
|
||||
case svc_legacy_soundindex:
|
||||
CL_LegacyPrecacheSound( msg );
|
||||
break;
|
||||
case svc_cdtrack:
|
||||
param1 = MSG_ReadByte( msg );
|
||||
param1 = bound( 1, param1, MAX_CDTRACKS ); // tracknum
|
||||
param2 = MSG_ReadByte( msg );
|
||||
param2 = bound( 1, param2, MAX_CDTRACKS ); // loopnum
|
||||
S_StartBackgroundTrack( clgame.cdtracks[param1-1], clgame.cdtracks[param2-1], 0, false );
|
||||
break;
|
||||
case svc_restore:
|
||||
CL_ParseRestore( msg );
|
||||
break;
|
||||
case svc_legacy_eventindex:
|
||||
CL_LegacyPrecacheEvent(msg);
|
||||
break;
|
||||
case svc_weaponanim:
|
||||
param1 = MSG_ReadByte( msg ); // iAnim
|
||||
param2 = MSG_ReadByte( msg ); // body
|
||||
CL_WeaponAnim( param1, param2 );
|
||||
break;
|
||||
case svc_bspdecal:
|
||||
CL_ParseStaticDecal( msg );
|
||||
break;
|
||||
case svc_roomtype:
|
||||
param1 = MSG_ReadShort( msg );
|
||||
Cvar_SetValue( "room_type", param1 );
|
||||
break;
|
||||
case svc_addangle:
|
||||
CL_ParseAddAngle( msg );
|
||||
break;
|
||||
case svc_usermessage:
|
||||
CL_RegisterUserMessage( msg );
|
||||
break;
|
||||
case svc_packetentities:
|
||||
playerbytes = CL_ParsePacketEntities( msg, false );
|
||||
cl.frames[cl.parsecountmod].graphdata.players += playerbytes;
|
||||
cl.frames[cl.parsecountmod].graphdata.entities += MSG_GetNumBytesRead( msg ) - bufStart - playerbytes;
|
||||
break;
|
||||
case svc_deltapacketentities:
|
||||
playerbytes = CL_ParsePacketEntities( msg, true );
|
||||
cl.frames[cl.parsecountmod].graphdata.players += playerbytes;
|
||||
cl.frames[cl.parsecountmod].graphdata.entities += MSG_GetNumBytesRead( msg ) - bufStart - playerbytes;
|
||||
break;
|
||||
case svc_legacy_chokecount:
|
||||
{
|
||||
int i, j;
|
||||
i = MSG_ReadByte( msg );
|
||||
j = cls.netchan.incoming_acknowledged - 1;
|
||||
for( ; i > 0 && j > cls.netchan.outgoing_sequence - CL_UPDATE_BACKUP; j-- )
|
||||
{
|
||||
if( cl.frames[j & CL_UPDATE_MASK].receivedtime != -3.0 )
|
||||
{
|
||||
cl.frames[j & CL_UPDATE_MASK].choked = true;
|
||||
cl.frames[j & CL_UPDATE_MASK].receivedtime = -2.0;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
//cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK].choked = true;
|
||||
//cl.frames[cls.netchan.incoming_sequence & CL_UPDATE_MASK].receivedtime = -2.0;
|
||||
break;
|
||||
case svc_resourcelist:
|
||||
CL_LegacyParseResourceList( msg );
|
||||
break;
|
||||
case svc_deltamovevars:
|
||||
CL_ParseMovevars( msg );
|
||||
break;
|
||||
case svc_resourcerequest:
|
||||
CL_ParseResourceRequest( msg );
|
||||
break;
|
||||
case svc_customization:
|
||||
CL_ParseCustomization( msg );
|
||||
break;
|
||||
case svc_crosshairangle:
|
||||
CL_ParseCrosshairAngle( msg );
|
||||
break;
|
||||
case svc_soundfade:
|
||||
CL_ParseSoundFade( msg );
|
||||
break;
|
||||
case svc_filetxferfailed:
|
||||
CL_ParseFileTransferFailed( msg );
|
||||
break;
|
||||
case svc_hltv:
|
||||
CL_ParseHLTV( msg );
|
||||
break;
|
||||
case svc_director:
|
||||
CL_ParseDirector( msg );
|
||||
break;
|
||||
case svc_resourcelocation:
|
||||
CL_ParseResLocation( msg );
|
||||
break;
|
||||
case svc_querycvarvalue:
|
||||
CL_ParseCvarValue( msg, false );
|
||||
break;
|
||||
case svc_querycvarvalue2:
|
||||
CL_ParseCvarValue( msg, true );
|
||||
break;
|
||||
default:
|
||||
CL_ParseUserMessage( msg, cmd );
|
||||
cl.frames[cl.parsecountmod].graphdata.usr += MSG_GetNumBytesRead( msg ) - bufStart;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cl.frames[cl.parsecountmod].graphdata.msgbytes += MSG_GetNumBytesRead( msg ) - cls.starting_count;
|
||||
CL_Parse_Debug( false ); // done
|
||||
|
||||
// we don't know if it is ok to save a demo message until
|
||||
// after we have parsed the frame
|
||||
if( !cls.demoplayback )
|
||||
{
|
||||
if( cls.demorecording && !cls.demowaiting )
|
||||
{
|
||||
CL_WriteDemoMessage( false, cls.starting_count, msg );
|
||||
}
|
||||
else if( cls.state != ca_active )
|
||||
{
|
||||
CL_WriteDemoMessage( true, cls.starting_count, msg );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CL_LegacyPrecache_f( void )
|
||||
{
|
||||
int spawncount, i;
|
||||
model_t *mod;
|
||||
|
||||
if( !cls.legacymode )
|
||||
return;
|
||||
|
||||
spawncount = Q_atoi( Cmd_Argv( 1 ));
|
||||
|
||||
Con_Printf( "Setting up renderer...\n" );
|
||||
|
||||
// load tempent sprites (glowshell, muzzleflashes etc)
|
||||
CL_LoadClientSprites ();
|
||||
|
||||
// invalidate all decal indexes
|
||||
memset( cl.decal_index, 0, sizeof( cl.decal_index ));
|
||||
cl.video_prepped = true;
|
||||
cl.audio_prepped = true;
|
||||
if( clgame.entities )
|
||||
clgame.entities->model = cl.worldmodel;
|
||||
|
||||
// update the ref state.
|
||||
R_UpdateRefState ();
|
||||
|
||||
// tell rendering system we have a new set of models.
|
||||
ref.dllFuncs.R_NewMap ();
|
||||
|
||||
CL_SetupOverviewParams();
|
||||
|
||||
// release unused SpriteTextures
|
||||
for( i = 1, mod = clgame.sprites; i < MAX_CLIENT_SPRITES; i++, mod++ )
|
||||
{
|
||||
if( mod->needload == NL_UNREFERENCED && COM_CheckString( mod->name ))
|
||||
Mod_FreeModel( mod );
|
||||
}
|
||||
|
||||
// Mod_FreeUnused ();
|
||||
|
||||
if( host_developer.value <= DEV_NONE )
|
||||
Con_ClearNotify(); // clear any lines of console text
|
||||
|
||||
// done with all resources, issue prespawn command.
|
||||
// Include server count in case server disconnects and changes level during d/l
|
||||
MSG_BeginClientCmd( &cls.netchan.message, clc_stringcmd );
|
||||
MSG_WriteStringf( &cls.netchan.message, "begin %i", spawncount );
|
||||
cls.signon = SIGNONS;
|
||||
}
|
||||
|
||||
void CL_LegacyUpdateInfo( void )
|
||||
{
|
||||
if( !cls.legacymode )
|
||||
return;
|
||||
|
||||
if( cls.state != ca_active )
|
||||
return;
|
||||
|
||||
MSG_BeginClientCmd( &cls.netchan.message, clc_legacy_userinfo );
|
||||
MSG_WriteString( &cls.netchan.message, cls.userinfo );
|
||||
}
|
||||
|
||||
qboolean CL_LegacyMode( void )
|
||||
{
|
||||
return cls.legacymode;
|
||||
}
|
|
@ -26,20 +26,6 @@ GNU General Public License for more details.
|
|||
#define MIN_PREDICTION_EPSILON 0.5f // complain if error is > this and we have cl_showerror set
|
||||
#define MAX_PREDICTION_ERROR 64.0f // above this is assumed to be a teleport, don't smooth, etc.
|
||||
|
||||
/*
|
||||
=============
|
||||
CL_ClearPhysEnts
|
||||
|
||||
=============
|
||||
*/
|
||||
void CL_ClearPhysEnts( void )
|
||||
{
|
||||
clgame.pmove->numtouch = 0;
|
||||
clgame.pmove->numvisent = 0;
|
||||
clgame.pmove->nummoveent = 0;
|
||||
clgame.pmove->numphysent = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
CL_PushPMStates
|
||||
|
@ -100,7 +86,7 @@ CL_IsPredicted
|
|||
*/
|
||||
qboolean CL_IsPredicted( void )
|
||||
{
|
||||
if( cl_nopred->value || cl.intermission )
|
||||
if( cl_nopred.value || cl.intermission )
|
||||
return false;
|
||||
|
||||
// never predict the quake demos
|
||||
|
@ -197,7 +183,7 @@ void CL_SetIdealPitch( void )
|
|||
}
|
||||
|
||||
if( steps < 2 ) return;
|
||||
cl.local.idealpitch = -dir * cl_idealpitchscale->value;
|
||||
cl.local.idealpitch = -dir * cl_idealpitchscale.value;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -208,7 +194,7 @@ check for instant movement in case
|
|||
we don't want interpolate this
|
||||
==================
|
||||
*/
|
||||
qboolean CL_PlayerTeleported( local_state_t *from, local_state_t *to )
|
||||
static qboolean CL_PlayerTeleported( local_state_t *from, local_state_t *to )
|
||||
{
|
||||
int len, maxlen;
|
||||
vec3_t delta;
|
||||
|
@ -248,7 +234,7 @@ void CL_CheckPredictionError( void )
|
|||
// save the prediction error for interpolation
|
||||
if( dist > MAX_PREDICTION_ERROR )
|
||||
{
|
||||
if( cl_showerror->value && host_developer.value )
|
||||
if( cl_showerror.value && host_developer.value )
|
||||
Con_NPrintf( 10 + ( ++pos & 3 ), "^3player teleported:^7 %.3f units\n", dist );
|
||||
|
||||
// a teleport or something or gamepaused
|
||||
|
@ -256,7 +242,7 @@ void CL_CheckPredictionError( void )
|
|||
}
|
||||
else
|
||||
{
|
||||
if( cl_showerror->value && dist > MIN_PREDICTION_EPSILON && host_developer.value )
|
||||
if( cl_showerror.value && dist > MIN_PREDICTION_EPSILON && host_developer.value )
|
||||
Con_NPrintf( 10 + ( ++pos & 3 ), "^1prediction error:^7 %.3f units\n", dist );
|
||||
|
||||
VectorCopy( cl.frames[cmd].playerstate[cl.playernum].origin, cl.local.predicted_origins[frame] );
|
||||
|
@ -267,7 +253,7 @@ void CL_CheckPredictionError( void )
|
|||
// GoldSrc checks for singleplayer
|
||||
// we would check for local server
|
||||
if( dist > MIN_CORRECTION_DISTANCE && !SV_Active() )
|
||||
cls.correction_time = cl_smoothtime->value;
|
||||
cls.correction_time = cl_smoothtime.value;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -547,7 +533,7 @@ void GAME_EXPORT CL_SetSolidPlayers( int playernum )
|
|||
physent_t *pe;
|
||||
int i;
|
||||
|
||||
if( !cl_solid_players->value )
|
||||
if( !cl_solid_players.value )
|
||||
return;
|
||||
|
||||
for( i = 0; i < MAX_CLIENTS; i++ )
|
||||
|
@ -713,33 +699,7 @@ static int GAME_EXPORT pfnTestPlayerPosition( float *pos, pmtrace_t *ptrace )
|
|||
|
||||
static void GAME_EXPORT pfnStuckTouch( int hitent, pmtrace_t *tr )
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i = 0; i < clgame.pmove->numtouch; i++ )
|
||||
{
|
||||
if( clgame.pmove->touchindex[i].ent == hitent )
|
||||
return;
|
||||
}
|
||||
|
||||
if( clgame.pmove->numtouch >= MAX_PHYSENTS )
|
||||
return;
|
||||
|
||||
VectorCopy( clgame.pmove->velocity, tr->deltavelocity );
|
||||
tr->ent = hitent;
|
||||
|
||||
clgame.pmove->touchindex[clgame.pmove->numtouch++] = *tr;
|
||||
}
|
||||
|
||||
static int GAME_EXPORT pfnPointContents( float *p, int *truecontents )
|
||||
{
|
||||
int cont, truecont;
|
||||
|
||||
truecont = cont = PM_PointContents( clgame.pmove, p );
|
||||
if( truecontents ) *truecontents = truecont;
|
||||
|
||||
if( cont <= CONTENTS_CURRENT_0 && cont >= CONTENTS_CURRENT_DOWN )
|
||||
cont = CONTENTS_WATER;
|
||||
return cont;
|
||||
PM_StuckTouch( clgame.pmove, hitent, tr );
|
||||
}
|
||||
|
||||
static int GAME_EXPORT pfnTruePointContents( float *p )
|
||||
|
@ -747,101 +707,19 @@ static int GAME_EXPORT pfnTruePointContents( float *p )
|
|||
return PM_TruePointContents( clgame.pmove, p );
|
||||
}
|
||||
|
||||
static int GAME_EXPORT pfnHullPointContents( struct hull_s *hull, int num, float *p )
|
||||
{
|
||||
return PM_HullPointContents( hull, num, p );
|
||||
}
|
||||
|
||||
static pmtrace_t GAME_EXPORT pfnPlayerTrace( float *start, float *end, int traceFlags, int ignore_pe )
|
||||
{
|
||||
return PM_PlayerTraceExt( clgame.pmove, start, end, traceFlags, clgame.pmove->numphysent, clgame.pmove->physents, ignore_pe, NULL );
|
||||
}
|
||||
|
||||
pmtrace_t *PM_TraceLine( float *start, float *end, int flags, int usehull, int ignore_pe )
|
||||
{
|
||||
static pmtrace_t tr;
|
||||
int old_usehull;
|
||||
|
||||
old_usehull = clgame.pmove->usehull;
|
||||
clgame.pmove->usehull = usehull;
|
||||
|
||||
switch( flags )
|
||||
{
|
||||
case PM_TRACELINE_PHYSENTSONLY:
|
||||
tr = PM_PlayerTraceExt( clgame.pmove, start, end, 0, clgame.pmove->numphysent, clgame.pmove->physents, ignore_pe, NULL );
|
||||
break;
|
||||
case PM_TRACELINE_ANYVISIBLE:
|
||||
tr = PM_PlayerTraceExt( clgame.pmove, start, end, 0, clgame.pmove->numvisent, clgame.pmove->visents, ignore_pe, NULL );
|
||||
break;
|
||||
}
|
||||
|
||||
clgame.pmove->usehull = old_usehull;
|
||||
|
||||
return &tr;
|
||||
}
|
||||
|
||||
static hull_t *pfnHullForBsp( physent_t *pe, float *offset )
|
||||
static void *pfnHullForBsp( physent_t *pe, float *offset )
|
||||
{
|
||||
return PM_HullForBsp( pe, clgame.pmove, offset );
|
||||
}
|
||||
|
||||
static float GAME_EXPORT pfnTraceModel( physent_t *pe, float *start, float *end, trace_t *trace )
|
||||
{
|
||||
int old_usehull;
|
||||
vec3_t start_l, end_l;
|
||||
vec3_t offset, temp;
|
||||
qboolean rotated;
|
||||
matrix4x4 matrix;
|
||||
hull_t *hull;
|
||||
|
||||
PM_InitTrace( trace, end );
|
||||
|
||||
old_usehull = clgame.pmove->usehull;
|
||||
clgame.pmove->usehull = 2;
|
||||
|
||||
hull = PM_HullForBsp( pe, clgame.pmove, offset );
|
||||
|
||||
clgame.pmove->usehull = old_usehull;
|
||||
|
||||
if( pe->solid == SOLID_BSP && !VectorIsNull( pe->angles ))
|
||||
rotated = true;
|
||||
else rotated = false;
|
||||
|
||||
if( rotated )
|
||||
{
|
||||
Matrix4x4_CreateFromEntity( matrix, pe->angles, offset, 1.0f );
|
||||
Matrix4x4_VectorITransform( matrix, start, start_l );
|
||||
Matrix4x4_VectorITransform( matrix, end, end_l );
|
||||
}
|
||||
else
|
||||
{
|
||||
VectorSubtract( start, offset, start_l );
|
||||
VectorSubtract( end, offset, end_l );
|
||||
}
|
||||
|
||||
PM_RecursiveHullCheck( hull, hull->firstclipnode, 0, 1, start_l, end_l, (pmtrace_t *)trace );
|
||||
trace->ent = NULL;
|
||||
|
||||
if( rotated )
|
||||
{
|
||||
VectorCopy( trace->plane.normal, temp );
|
||||
Matrix4x4_TransformPositivePlane( matrix, temp, trace->plane.dist, trace->plane.normal, &trace->plane.dist );
|
||||
}
|
||||
|
||||
VectorLerp( start, trace->fraction, end, trace->endpos );
|
||||
|
||||
return trace->fraction;
|
||||
}
|
||||
|
||||
static const char *pfnTraceTexture( int ground, float *vstart, float *vend )
|
||||
{
|
||||
physent_t *pe;
|
||||
|
||||
if( ground < 0 || ground >= clgame.pmove->numphysent )
|
||||
return NULL; // bad ground
|
||||
|
||||
pe = &clgame.pmove->physents[ground];
|
||||
return PM_TraceTexture( pe, vstart, vend );
|
||||
return PM_TraceModel( clgame.pmove, pe, start, end, trace );
|
||||
}
|
||||
|
||||
static void GAME_EXPORT pfnPlaySound( int channel, const char *sample, float volume, float attenuation, int fFlags, int pitch )
|
||||
|
@ -870,25 +748,7 @@ static int GAME_EXPORT pfnTestPlayerPositionEx( float *pos, pmtrace_t *ptrace, p
|
|||
|
||||
static pmtrace_t *pfnTraceLineEx( float *start, float *end, int flags, int usehull, pfnIgnore pmFilter )
|
||||
{
|
||||
static pmtrace_t tr;
|
||||
int old_usehull;
|
||||
|
||||
old_usehull = clgame.pmove->usehull;
|
||||
clgame.pmove->usehull = usehull;
|
||||
|
||||
switch( flags )
|
||||
{
|
||||
case PM_TRACELINE_PHYSENTSONLY:
|
||||
tr = PM_PlayerTraceExt( clgame.pmove, start, end, 0, clgame.pmove->numphysent, clgame.pmove->physents, -1, pmFilter );
|
||||
break;
|
||||
case PM_TRACELINE_ANYVISIBLE:
|
||||
tr = PM_PlayerTraceExt( clgame.pmove, start, end, 0, clgame.pmove->numvisent, clgame.pmove->visents, -1, pmFilter );
|
||||
break;
|
||||
}
|
||||
|
||||
clgame.pmove->usehull = old_usehull;
|
||||
|
||||
return &tr;
|
||||
return PM_TraceLineEx( clgame.pmove, start, end, flags, usehull, pmFilter );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -928,23 +788,23 @@ void CL_InitClientMove( void )
|
|||
clgame.pmove->Con_Printf = Con_Printf;
|
||||
clgame.pmove->Sys_FloatTime = Sys_DoubleTime;
|
||||
clgame.pmove->PM_StuckTouch = pfnStuckTouch;
|
||||
clgame.pmove->PM_PointContents = pfnPointContents;
|
||||
clgame.pmove->PM_PointContents = (void*)PM_CL_PointContents;
|
||||
clgame.pmove->PM_TruePointContents = pfnTruePointContents;
|
||||
clgame.pmove->PM_HullPointContents = pfnHullPointContents;
|
||||
clgame.pmove->PM_HullPointContents = (void*)PM_HullPointContents;
|
||||
clgame.pmove->PM_PlayerTrace = pfnPlayerTrace;
|
||||
clgame.pmove->PM_TraceLine = PM_TraceLine;
|
||||
clgame.pmove->PM_TraceLine = PM_CL_TraceLine;
|
||||
clgame.pmove->RandomLong = COM_RandomLong;
|
||||
clgame.pmove->RandomFloat = COM_RandomFloat;
|
||||
clgame.pmove->PM_GetModelType = pfnGetModelType;
|
||||
clgame.pmove->PM_GetModelBounds = pfnGetModelBounds;
|
||||
clgame.pmove->PM_HullForBsp = (void*)pfnHullForBsp;
|
||||
clgame.pmove->PM_HullForBsp = pfnHullForBsp;
|
||||
clgame.pmove->PM_TraceModel = pfnTraceModel;
|
||||
clgame.pmove->COM_FileSize = COM_FileSize;
|
||||
clgame.pmove->COM_LoadFile = COM_LoadFile;
|
||||
clgame.pmove->COM_FreeFile = COM_FreeFile;
|
||||
clgame.pmove->memfgets = COM_MemFgets;
|
||||
clgame.pmove->PM_PlaySound = pfnPlaySound;
|
||||
clgame.pmove->PM_TraceTexture = pfnTraceTexture;
|
||||
clgame.pmove->PM_TraceTexture = PM_CL_TraceTexture;
|
||||
clgame.pmove->PM_PlaybackEventFull = pfnPlaybackEventFull;
|
||||
clgame.pmove->PM_PlayerTraceEx = pfnPlayerTraceEx;
|
||||
clgame.pmove->PM_TestPlayerPositionEx = pfnTestPlayerPositionEx;
|
||||
|
@ -955,21 +815,10 @@ void CL_InitClientMove( void )
|
|||
clgame.dllFuncs.pfnPlayerMoveInit( clgame.pmove );
|
||||
}
|
||||
|
||||
static void PM_CheckMovingGround( clientdata_t *cd, entity_state_t *state, float frametime )
|
||||
static void CL_SetupPMove( playermove_t *pmove, const local_state_t *from, const usercmd_t *ucmd, qboolean runfuncs, double time )
|
||||
{
|
||||
if(!( cd->flags & FL_BASEVELOCITY ))
|
||||
{
|
||||
// apply momentum (add in half of the previous frame of velocity first)
|
||||
VectorMA( cd->velocity, 1.0f + (frametime * 0.5f), state->basevelocity, cd->velocity );
|
||||
VectorClear( state->basevelocity );
|
||||
}
|
||||
cd->flags &= ~FL_BASEVELOCITY;
|
||||
}
|
||||
|
||||
void CL_SetupPMove( playermove_t *pmove, local_state_t *from, usercmd_t *ucmd, qboolean runfuncs, double time )
|
||||
{
|
||||
entity_state_t *ps;
|
||||
clientdata_t *cd;
|
||||
const entity_state_t *ps;
|
||||
const clientdata_t *cd;
|
||||
|
||||
ps = &from->playerstate;
|
||||
cd = &from->client;
|
||||
|
@ -986,13 +835,13 @@ void CL_SetupPMove( playermove_t *pmove, local_state_t *from, usercmd_t *ucmd, q
|
|||
VectorCopy( ps->basevelocity, pmove->basevelocity );
|
||||
VectorCopy( cd->view_ofs, pmove->view_ofs );
|
||||
VectorClear( pmove->movedir );
|
||||
pmove->flDuckTime = cd->flDuckTime;
|
||||
pmove->flDuckTime = (float)cd->flDuckTime;
|
||||
pmove->bInDuck = cd->bInDuck;
|
||||
pmove->usehull = ps->usehull;
|
||||
pmove->flTimeStepSound = cd->flTimeStepSound;
|
||||
pmove->iStepLeft = ps->iStepLeft;
|
||||
pmove->flFallVelocity = ps->flFallVelocity;
|
||||
pmove->flSwimTime = cd->flSwimTime;
|
||||
pmove->flSwimTime = (float)cd->flSwimTime;
|
||||
VectorCopy( cd->punchangle, pmove->punchangle );
|
||||
pmove->flNextPrimaryAttack = 0.0f; // not used by PM_ code
|
||||
pmove->effects = ps->effects;
|
||||
|
@ -1000,7 +849,7 @@ void CL_SetupPMove( playermove_t *pmove, local_state_t *from, usercmd_t *ucmd, q
|
|||
pmove->gravity = ps->gravity;
|
||||
pmove->friction = ps->friction;
|
||||
pmove->oldbuttons = ps->oldbuttons;
|
||||
pmove->waterjumptime = cd->waterjumptime;
|
||||
pmove->waterjumptime = (float)cd->waterjumptime;
|
||||
pmove->dead = (cl.local.health <= 0);
|
||||
pmove->deadflag = cd->deadflag;
|
||||
pmove->spectator = (cls.spectator != 0);
|
||||
|
@ -1027,7 +876,7 @@ void CL_SetupPMove( playermove_t *pmove, local_state_t *from, usercmd_t *ucmd, q
|
|||
Q_strncpy( pmove->physinfo, cls.physinfo, MAX_INFO_STRING );
|
||||
}
|
||||
|
||||
void CL_FinishPMove( playermove_t *pmove, local_state_t *to )
|
||||
const void CL_FinishPMove( const playermove_t *pmove, local_state_t *to )
|
||||
{
|
||||
entity_state_t *ps;
|
||||
clientdata_t *cd;
|
||||
|
@ -1038,7 +887,7 @@ void CL_FinishPMove( playermove_t *pmove, local_state_t *to )
|
|||
cd->flags = pmove->flags;
|
||||
cd->bInDuck = pmove->bInDuck;
|
||||
cd->flTimeStepSound = pmove->flTimeStepSound;
|
||||
cd->flDuckTime = pmove->flDuckTime;
|
||||
cd->flDuckTime = (int)pmove->flDuckTime;
|
||||
cd->flSwimTime = (int)pmove->flSwimTime;
|
||||
cd->waterjumptime = (int)pmove->waterjumptime;
|
||||
cd->watertype = pmove->watertype;
|
||||
|
@ -1051,7 +900,7 @@ void CL_FinishPMove( playermove_t *pmove, local_state_t *to )
|
|||
VectorCopy( pmove->angles, ps->angles );
|
||||
VectorCopy( pmove->basevelocity, ps->basevelocity );
|
||||
VectorCopy( pmove->punchangle, cd->punchangle );
|
||||
ps->oldbuttons = pmove->cmd.buttons;
|
||||
ps->oldbuttons = (uint)pmove->cmd.buttons;
|
||||
ps->friction = pmove->friction;
|
||||
ps->movetype = pmove->movetype;
|
||||
ps->onground = pmove->onground;
|
||||
|
@ -1159,13 +1008,9 @@ void CL_PredictMovement( qboolean repredicting )
|
|||
{
|
||||
runcmd_t *to_cmd = NULL, *from_cmd;
|
||||
local_state_t *from = NULL, *to = NULL;
|
||||
uint current_command;
|
||||
uint current_command_mod;
|
||||
frame_t *frame = NULL;
|
||||
frame_t *frame = NULL;
|
||||
uint i, stoppoint;
|
||||
qboolean runfuncs;
|
||||
double f = 1.0;
|
||||
cl_entity_t *ent;
|
||||
double time;
|
||||
|
||||
if( cls.state != ca_active || cls.spectator )
|
||||
|
@ -1176,7 +1021,7 @@ void CL_PredictMovement( qboolean repredicting )
|
|||
|
||||
CL_SetUpPlayerPrediction( false, false );
|
||||
|
||||
if( cls.state != ca_active || !cl.validsequence )
|
||||
if( !cl.validsequence )
|
||||
return;
|
||||
|
||||
if(( cls.netchan.outgoing_sequence - cls.netchan.incoming_acknowledged ) >= CL_UPDATE_MASK )
|
||||
|
@ -1217,6 +1062,10 @@ void CL_PredictMovement( qboolean repredicting )
|
|||
|
||||
for( i = 1; i < CL_UPDATE_MASK && cls.netchan.incoming_acknowledged + i < cls.netchan.outgoing_sequence + stoppoint; i++ )
|
||||
{
|
||||
uint current_command;
|
||||
uint current_command_mod;
|
||||
qboolean runfuncs;
|
||||
|
||||
current_command = cls.netchan.incoming_acknowledged + i;
|
||||
current_command_mod = current_command & CL_UPDATE_MASK;
|
||||
|
||||
|
@ -1256,7 +1105,7 @@ void CL_PredictMovement( qboolean repredicting )
|
|||
cl.local.onground = frame->playerstate[cl.playernum].onground;
|
||||
else cl.local.onground = -1;
|
||||
|
||||
if( !repredicting || !CVAR_TO_BOOL( cl_lw ))
|
||||
if( !repredicting || !cl_lw.value )
|
||||
cl.local.viewmodel = to->client.viewmodel;
|
||||
cl.local.repredicting = false;
|
||||
cl.local.moving = false;
|
||||
|
@ -1288,12 +1137,12 @@ void CL_PredictMovement( qboolean repredicting )
|
|||
|
||||
cl.local.waterlevel = to->client.waterlevel;
|
||||
cl.local.usehull = to->playerstate.usehull;
|
||||
if( !repredicting || !CVAR_TO_BOOL( cl_lw ))
|
||||
if( !repredicting || !cl_lw.value )
|
||||
cl.local.viewmodel = to->client.viewmodel;
|
||||
|
||||
if( FBitSet( to->client.flags, FL_ONGROUND ))
|
||||
{
|
||||
ent = CL_GetEntityByIndex( cl.local.lastground );
|
||||
cl_entity_t *ent = CL_GetEntityByIndex( cl.local.lastground );
|
||||
cl.local.onground = cl.local.lastground;
|
||||
cl.local.moving = false;
|
||||
|
||||
|
@ -1315,27 +1164,27 @@ void CL_PredictMovement( qboolean repredicting )
|
|||
else
|
||||
{
|
||||
cl.local.onground = -1;
|
||||
cl.local.moving = 0;
|
||||
cl.local.moving = false;
|
||||
}
|
||||
|
||||
if( cls.correction_time > 0 && !cl_nosmooth->value && cl_smoothtime->value )
|
||||
if( cls.correction_time > 0 && !cl_nosmooth.value && cl_smoothtime.value )
|
||||
{
|
||||
vec3_t delta;
|
||||
float frac;
|
||||
vec3_t delta;
|
||||
float frac;
|
||||
|
||||
// only decay timer once per frame
|
||||
if( !repredicting )
|
||||
cls.correction_time -= host.frametime;
|
||||
|
||||
// Make sure smoothtime is postive
|
||||
if( cl_smoothtime->value <= 0.0f )
|
||||
Cvar_DirectSet( cl_smoothtime, "0.1" );
|
||||
if( cl_smoothtime.value <= 0.0f )
|
||||
Cvar_DirectSet( &cl_smoothtime, "0.1" );
|
||||
|
||||
// Clamp from 0 to cl_smoothtime.value
|
||||
cls.correction_time = bound( 0.0, cls.correction_time, cl_smoothtime->value );
|
||||
cls.correction_time = bound( 0.0, cls.correction_time, cl_smoothtime.value );
|
||||
|
||||
// Compute backward interpolation fraction along full correction
|
||||
frac = 1.0f - cls.correction_time / cl_smoothtime->value;
|
||||
frac = 1.0f - cls.correction_time / cl_smoothtime.value;
|
||||
|
||||
// Determine how much error we still have to make up for
|
||||
VectorSubtract( cl.simorg, cl.local.lastorigin, delta );
|
||||
|
|
|
@ -232,14 +232,10 @@ static void CL_ParseQuakeServerInfo( sizebuf_t *msg )
|
|||
// loading user settings
|
||||
CSCR_LoadDefaultCVars( "user.scr" );
|
||||
|
||||
if( r_decals->value > mp_decals.value )
|
||||
Cvar_SetValue( "r_decals", mp_decals.value );
|
||||
if( r_decals.value > mp_decals.value )
|
||||
Cvar_DirectSet( &r_decals, mp_decals.string );
|
||||
}
|
||||
else Cvar_Reset( "r_decals" );
|
||||
|
||||
// re-init mouse
|
||||
if( cl.background )
|
||||
host.mouse_visible = false;
|
||||
else Cvar_DirectSet( &r_decals, NULL );
|
||||
|
||||
if( cl.background ) // tell the game parts about background state
|
||||
Cvar_FullSet( "cl_background", "1", FCVAR_READ_ONLY );
|
||||
|
@ -262,7 +258,7 @@ static void CL_ParseQuakeServerInfo( sizebuf_t *msg )
|
|||
Q_strncpy( gameui.globals->maptitle, clgame.maptitle, sizeof( gameui.globals->maptitle ));
|
||||
|
||||
if( !cls.changelevel && !cls.changedemo )
|
||||
CL_InitEdicts (); // re-arrange edicts
|
||||
CL_InitEdicts( cl.maxclients ); // re-arrange edicts
|
||||
|
||||
// Quake just have a large packet of initialization data
|
||||
for( i = 1; i < MAX_MODELS; i++ )
|
||||
|
@ -306,9 +302,9 @@ static void CL_ParseQuakeServerInfo( sizebuf_t *msg )
|
|||
else Cvar_Set( "cl_levelshot_name", va( "levelshots/%s_%s", clgame.mapname, refState.wideScreen ? "16x9" : "4x3" ));
|
||||
Cvar_SetValue( "scr_loading", 0.0f ); // reset progress bar
|
||||
|
||||
if(( cl_allow_levelshots->value && !cls.changelevel ) || cl.background )
|
||||
if(( cl_allow_levelshots.value && !cls.changelevel ) || cl.background )
|
||||
{
|
||||
if( !FS_FileExists( va( "%s.bmp", cl_levelshot_name->string ), true ))
|
||||
if( !FS_FileExists( va( "%s.bmp", cl_levelshot_name.string ), true ))
|
||||
Cvar_Set( "cl_levelshot_name", "*black" ); // render a black screen
|
||||
cls.scrshot_request = scrshot_plaque; // request levelshot even if exist (check filetime)
|
||||
}
|
||||
|
@ -698,17 +694,13 @@ static void CL_ParseQuakeBaseline( sizebuf_t *msg )
|
|||
cl_entity_t *ent;
|
||||
int newnum;
|
||||
|
||||
memset( &state, 0, sizeof( state ));
|
||||
newnum = MSG_ReadWord( msg ); // entnum
|
||||
|
||||
if( newnum >= clgame.maxEntities )
|
||||
Host_Error( "CL_AllocEdict: no free edicts\n" );
|
||||
|
||||
ent = CL_EDICT_NUM( newnum );
|
||||
memset( &ent->prevstate, 0, sizeof( ent->prevstate ));
|
||||
ent->index = newnum;
|
||||
|
||||
// parse baseline
|
||||
memset( &state, 0, sizeof( state ));
|
||||
state.modelindex = MSG_ReadByte( msg );
|
||||
state.frame = MSG_ReadByte( msg );
|
||||
state.colormap = MSG_ReadByte( msg );
|
||||
|
@ -719,8 +711,10 @@ static void CL_ParseQuakeBaseline( sizebuf_t *msg )
|
|||
state.angles[1] = MSG_ReadAngle( msg );
|
||||
state.origin[2] = MSG_ReadCoord( msg );
|
||||
state.angles[2] = MSG_ReadAngle( msg );
|
||||
ent->player = CL_IsPlayerIndex( newnum );
|
||||
|
||||
ent = CL_EDICT_NUM( newnum );
|
||||
ent->index = newnum;
|
||||
ent->player = CL_IsPlayerIndex( newnum );
|
||||
memcpy( &ent->baseline, &state, sizeof( entity_state_t ));
|
||||
memcpy( &ent->prevstate, &state, sizeof( entity_state_t ));
|
||||
}
|
||||
|
|
|
@ -41,11 +41,24 @@ CL_CmpStudioTextures
|
|||
return true if equal
|
||||
====================
|
||||
*/
|
||||
qboolean CL_CmpStudioTextures( int numtexs, mstudiotexture_t *p1, mstudiotexture_t *p2 )
|
||||
static qboolean CL_CmpStudioTextures( int numtexs, mstudiotexture_t *p1, remap_info_t *remap )
|
||||
{
|
||||
int i;
|
||||
mstudiotexture_t *p2;
|
||||
|
||||
if( !p1 || !p2 ) return false;
|
||||
if( !p1 ) // no textures
|
||||
return false;
|
||||
|
||||
if( !remap ) // current model has no remap
|
||||
return false;
|
||||
|
||||
if( !remap->textures ) // shouldn't happen, just in case
|
||||
return false;
|
||||
|
||||
if( numtexs != remap->numtextures ) // amount of textures differs, it's a different model
|
||||
return false;
|
||||
|
||||
p2 = remap->ptexture;
|
||||
|
||||
for( i = 0; i < numtexs; i++, p1++, p2++ )
|
||||
{
|
||||
|
@ -157,7 +170,7 @@ void CL_UpdateStudioTexture( cl_entity_t *entity, mstudiotexture_t *ptexture, in
|
|||
|
||||
// build name of original texture
|
||||
Q_strncpy( mdlname, entity->model->name, sizeof( mdlname ));
|
||||
COM_FileBase( ptexture->name, name );
|
||||
COM_FileBase( ptexture->name, name, sizeof( name ));
|
||||
COM_StripExtension( mdlname );
|
||||
|
||||
Q_snprintf( texname, sizeof( texname ), "#%s/%s.mdl", mdlname, name );
|
||||
|
@ -282,10 +295,9 @@ void CL_AllocRemapInfo( cl_entity_t *entity, model_t *model, int topcolor, int b
|
|||
if( !phdr ) return; // bad model?
|
||||
|
||||
src = (mstudiotexture_t *)(((byte *)phdr) + phdr->textureindex);
|
||||
dst = (clgame.remap_info[i] ? clgame.remap_info[i]->ptexture : NULL);
|
||||
|
||||
// NOTE: we must copy all the structures 'mstudiotexture_t' for easy access when model is rendering
|
||||
if( !CL_CmpStudioTextures( phdr->numtextures, src, dst ) || clgame.remap_info[i]->model != model )
|
||||
if( !CL_CmpStudioTextures( phdr->numtextures, src, clgame.remap_info[i] ) || clgame.remap_info[i]->model != model )
|
||||
{
|
||||
// this code catches studiomodel change with another studiomodel with remap textures
|
||||
// e.g. playermodel 'barney' with playermodel 'gordon'
|
||||
|
|
|
@ -133,7 +133,7 @@ const char *CL_GenericHandle( int fileindex )
|
|||
return cl.files_precache[fileindex];
|
||||
}
|
||||
|
||||
int CL_RenderGetParm( const int parm, const int arg, const qboolean checkRef )
|
||||
intptr_t CL_RenderGetParm( const int parm, const int arg, const qboolean checkRef )
|
||||
{
|
||||
switch( parm )
|
||||
{
|
||||
|
@ -161,9 +161,17 @@ int CL_RenderGetParm( const int parm, const int arg, const qboolean checkRef )
|
|||
case PARM_WATER_ALPHA:
|
||||
return FBitSet( world.flags, FWORLD_WATERALPHA );
|
||||
case PARM_DELUXEDATA:
|
||||
return *(int *)&world.deluxedata;
|
||||
return (intptr_t)world.deluxedata;
|
||||
case PARM_SHADOWDATA:
|
||||
return *(int *)&world.shadowdata;
|
||||
return (intptr_t)world.shadowdata;
|
||||
case PARM_FULLSCREEN:
|
||||
return refState.fullScreen;
|
||||
case PARM_WIDESCREEN:
|
||||
return refState.wideScreen;
|
||||
case PARM_SCREEN_WIDTH:
|
||||
return refState.width;
|
||||
case PARM_SCREEN_HEIGHT:
|
||||
return refState.height;
|
||||
default:
|
||||
// indicates call from client.dll
|
||||
if( checkRef )
|
||||
|
@ -204,7 +212,7 @@ int CL_RenderGetParm( const int parm, const int arg, const qboolean checkRef )
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int pfnRenderGetParm( int parm, int arg )
|
||||
static intptr_t pfnRenderGetParm( int parm, int arg )
|
||||
{
|
||||
return CL_RenderGetParm( parm, arg, true );
|
||||
}
|
||||
|
|
|
@ -20,18 +20,18 @@ GNU General Public License for more details.
|
|||
#include "input.h"
|
||||
#include "library.h"
|
||||
|
||||
convar_t *scr_centertime;
|
||||
convar_t *scr_loading;
|
||||
convar_t *scr_download;
|
||||
convar_t *scr_viewsize;
|
||||
convar_t *cl_testlights;
|
||||
convar_t *cl_allow_levelshots;
|
||||
convar_t *cl_levelshot_name;
|
||||
static convar_t *cl_envshot_size;
|
||||
convar_t *v_dark;
|
||||
static convar_t *net_speeds;
|
||||
static convar_t *cl_showfps;
|
||||
static convar_t *cl_showpos;
|
||||
CVAR_DEFINE_AUTO( scr_centertime, "2.5", 0, "centerprint hold time" );
|
||||
CVAR_DEFINE_AUTO( scr_loading, "0", 0, "loading bar progress" );
|
||||
CVAR_DEFINE_AUTO( scr_download, "-1", 0, "downloading bar progress" );
|
||||
CVAR_DEFINE( scr_viewsize, "viewsize", "120", FCVAR_ARCHIVE, "screen size (quake only)" );
|
||||
CVAR_DEFINE_AUTO( cl_testlights, "0", 0, "test dynamic lights" );
|
||||
CVAR_DEFINE( cl_allow_levelshots, "allow_levelshots", "0", FCVAR_ARCHIVE, "allow engine to use indivdual levelshots instead of 'loading' image" );
|
||||
CVAR_DEFINE_AUTO( cl_levelshot_name, "*black", 0, "contains path to current levelshot" );
|
||||
static CVAR_DEFINE_AUTO( cl_envshot_size, "256", FCVAR_ARCHIVE, "envshot size of cube side" );
|
||||
CVAR_DEFINE_AUTO( v_dark, "0", 0, "starts level from dark screen" );
|
||||
static CVAR_DEFINE_AUTO( net_speeds, "0", FCVAR_ARCHIVE, "show network packets" );
|
||||
static CVAR_DEFINE_AUTO( cl_showfps, "0", FCVAR_ARCHIVE, "show client fps" );
|
||||
static CVAR_DEFINE_AUTO( cl_showpos, "0", FCVAR_ARCHIVE, "show local player position and velocity" );
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
@ -59,7 +59,7 @@ void SCR_DrawFPS( int height )
|
|||
char fpsstring[64];
|
||||
int offset;
|
||||
|
||||
if( cls.state != ca_active || !cl_showfps->value || cl.background )
|
||||
if( cls.state != ca_active || !cl_showfps.value || cl.background )
|
||||
return;
|
||||
|
||||
switch( cls.scrshot_action )
|
||||
|
@ -95,7 +95,7 @@ void SCR_DrawFPS( int height )
|
|||
if( curfps < minfps ) minfps = curfps;
|
||||
if( curfps > maxfps ) maxfps = curfps;
|
||||
|
||||
if( cl_showfps->value == 2 )
|
||||
if( cl_showfps.value == 2 )
|
||||
Q_snprintf( fpsstring, sizeof( fpsstring ), "fps: ^1%4i min, ^3%4i cur, ^2%4i max", minfps, curfps, maxfps );
|
||||
else Q_snprintf( fpsstring, sizeof( fpsstring ), "%4i fps", curfps );
|
||||
MakeRGBA( color, 255, 255, 255, 255 );
|
||||
|
@ -119,7 +119,7 @@ void SCR_DrawPos( void )
|
|||
cl_entity_t *ent;
|
||||
rgba_t color;
|
||||
|
||||
if( cls.state != ca_active || !cl_showpos->value || cl.background )
|
||||
if( cls.state != ca_active || !cl_showpos.value || cl.background )
|
||||
return;
|
||||
|
||||
ent = CL_GetLocalPlayer();
|
||||
|
@ -150,8 +150,7 @@ same as r_speeds but for network channel
|
|||
void SCR_NetSpeeds( void )
|
||||
{
|
||||
static char msg[MAX_SYSPATH];
|
||||
int x, y, height;
|
||||
char *p, *start, *end;
|
||||
int x, y;
|
||||
float time = cl.mtime[0];
|
||||
static int min_svfps = 100;
|
||||
static int max_svfps = 0;
|
||||
|
@ -160,11 +159,12 @@ void SCR_NetSpeeds( void )
|
|||
static int max_clfps = 0;
|
||||
int cur_clfps = 0;
|
||||
rgba_t color;
|
||||
cl_font_t *font = Con_GetCurFont();
|
||||
|
||||
if( !host.allow_console )
|
||||
return;
|
||||
|
||||
if( !net_speeds->value || cls.state != ca_active )
|
||||
if( !net_speeds.value || cls.state != ca_active )
|
||||
return;
|
||||
|
||||
// prevent to get too big values at max
|
||||
|
@ -196,25 +196,11 @@ void SCR_NetSpeeds( void )
|
|||
Q_memprint( cls.netchan.total_sended )
|
||||
);
|
||||
|
||||
x = refState.width - 320;
|
||||
x = refState.width - 320 * font->scale;
|
||||
y = 384;
|
||||
|
||||
Con_DrawStringLen( NULL, NULL, &height );
|
||||
MakeRGBA( color, 255, 255, 255, 255 );
|
||||
|
||||
p = start = msg;
|
||||
|
||||
do
|
||||
{
|
||||
end = Q_strchr( p, '\n' );
|
||||
if( end ) msg[end-start] = '\0';
|
||||
|
||||
Con_DrawString( x, y, p, color );
|
||||
y += height;
|
||||
|
||||
if( end ) p = end + 1;
|
||||
else break;
|
||||
} while( 1 );
|
||||
CL_DrawString( x, y, msg, color, font, FONT_DRAW_RESETCOLORONLF );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -231,31 +217,15 @@ void SCR_RSpeeds( void )
|
|||
|
||||
if( ref.dllFuncs.R_SpeedsMessage( msg, sizeof( msg )))
|
||||
{
|
||||
int x, y, height;
|
||||
char *p, *start, *end;
|
||||
int x, y;
|
||||
rgba_t color;
|
||||
cl_font_t *font = Con_GetCurFont();
|
||||
|
||||
x = refState.width - 340;
|
||||
x = refState.width - 340 * font->scale;
|
||||
y = 64;
|
||||
|
||||
Con_DrawStringLen( NULL, NULL, &height );
|
||||
MakeRGBA( color, 255, 255, 255, 255 );
|
||||
|
||||
p = start = msg;
|
||||
do
|
||||
{
|
||||
end = Q_strchr( p, '\n' );
|
||||
if( end ) msg[end-start] = '\0';
|
||||
|
||||
Con_DrawString( x, y, p, color );
|
||||
y += height;
|
||||
|
||||
// handle '\n\n'
|
||||
if( *p == '\n' )
|
||||
y += height;
|
||||
if( end ) p = end + 1;
|
||||
else break;
|
||||
} while( 1 );
|
||||
CL_DrawString( x, y, msg, color, font, FONT_DRAW_RESETCOLORONLF );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -320,7 +290,7 @@ void SCR_MakeScreenShot( void )
|
|||
|
||||
if( cls.envshot_viewsize > 0 )
|
||||
viewsize = cls.envshot_viewsize;
|
||||
else viewsize = cl_envshot_size->value;
|
||||
else viewsize = cl_envshot_size.value;
|
||||
|
||||
switch( cls.scrshot_action )
|
||||
{
|
||||
|
@ -374,9 +344,9 @@ SCR_DrawPlaque
|
|||
*/
|
||||
void SCR_DrawPlaque( void )
|
||||
{
|
||||
if(( cl_allow_levelshots->value && !cls.changelevel ) || cl.background )
|
||||
if(( cl_allow_levelshots.value && !cls.changelevel ) || cl.background )
|
||||
{
|
||||
int levelshot = ref.dllFuncs.GL_LoadTexture( cl_levelshot_name->string, NULL, 0, TF_IMAGE );
|
||||
int levelshot = ref.dllFuncs.GL_LoadTexture( cl_levelshot_name.string, NULL, 0, TF_IMAGE );
|
||||
ref.dllFuncs.GL_SetRenderMode( kRenderNormal );
|
||||
ref.dllFuncs.R_DrawStretchPic( 0, 0, refState.width, refState.height, 0, 0, 1, 1, levelshot );
|
||||
if( !cl.background ) CL_DrawHUD( CL_LOADING );
|
||||
|
@ -396,7 +366,7 @@ void SCR_BeginLoadingPlaque( qboolean is_background )
|
|||
cl.video_prepped = false;
|
||||
|
||||
if( !Host_IsDedicated() )
|
||||
oldclear = gl_clear->value;
|
||||
oldclear = gl_clear.value;
|
||||
|
||||
if( CL_IsInMenu( ) && !cls.changedemo && !is_background )
|
||||
{
|
||||
|
@ -412,7 +382,7 @@ void SCR_BeginLoadingPlaque( qboolean is_background )
|
|||
return;
|
||||
|
||||
if( !Host_IsDedicated() )
|
||||
gl_clear->value = 0.0f;
|
||||
gl_clear.value = 0.0f;
|
||||
|
||||
if( is_background ) IN_MouseSavePos( );
|
||||
cls.draw_changelevel = !is_background;
|
||||
|
@ -421,7 +391,7 @@ void SCR_BeginLoadingPlaque( qboolean is_background )
|
|||
cl.background = is_background; // set right state before svc_serverdata is came
|
||||
|
||||
if( !Host_IsDedicated() )
|
||||
gl_clear->value = oldclear;
|
||||
gl_clear.value = oldclear;
|
||||
|
||||
// SNDDMA_LockSound();
|
||||
}
|
||||
|
@ -472,7 +442,7 @@ void SCR_TileClear( void )
|
|||
int i, top, bottom, left, right;
|
||||
dirty_t clear;
|
||||
|
||||
if( scr_viewsize->value >= 120 )
|
||||
if( scr_viewsize.value >= 120 )
|
||||
return; // full screen rendering
|
||||
|
||||
// erase rect will be the union of the past three frames
|
||||
|
@ -577,77 +547,6 @@ void SCR_UpdateScreen( void )
|
|||
V_PostRender();
|
||||
}
|
||||
|
||||
qboolean SCR_LoadFixedWidthFont( const char *fontname )
|
||||
{
|
||||
int i, fontWidth;
|
||||
|
||||
if( cls.creditsFont.valid )
|
||||
return true; // already loaded
|
||||
|
||||
if( !FS_FileExists( fontname, false ))
|
||||
return false;
|
||||
|
||||
cls.creditsFont.hFontTexture = ref.dllFuncs.GL_LoadTexture( fontname, NULL, 0, TF_IMAGE|TF_KEEP_SOURCE );
|
||||
R_GetTextureParms( &fontWidth, NULL, cls.creditsFont.hFontTexture );
|
||||
cls.creditsFont.charHeight = clgame.scrInfo.iCharHeight = fontWidth / 16;
|
||||
cls.creditsFont.type = FONT_FIXED;
|
||||
cls.creditsFont.valid = true;
|
||||
|
||||
// build fixed rectangles
|
||||
for( i = 0; i < 256; i++ )
|
||||
{
|
||||
cls.creditsFont.fontRc[i].left = (i * (fontWidth / 16)) % fontWidth;
|
||||
cls.creditsFont.fontRc[i].right = cls.creditsFont.fontRc[i].left + fontWidth / 16;
|
||||
cls.creditsFont.fontRc[i].top = (i / 16) * (fontWidth / 16);
|
||||
cls.creditsFont.fontRc[i].bottom = cls.creditsFont.fontRc[i].top + fontWidth / 16;
|
||||
cls.creditsFont.charWidths[i] = clgame.scrInfo.charWidths[i] = fontWidth / 16;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
qboolean SCR_LoadVariableWidthFont( const char *fontname )
|
||||
{
|
||||
int i, fontWidth;
|
||||
byte *buffer;
|
||||
fs_offset_t length;
|
||||
qfont_t *src;
|
||||
|
||||
if( cls.creditsFont.valid )
|
||||
return true; // already loaded
|
||||
|
||||
if( !FS_FileExists( fontname, false ))
|
||||
return false;
|
||||
|
||||
cls.creditsFont.hFontTexture = ref.dllFuncs.GL_LoadTexture( fontname, NULL, 0, TF_IMAGE );
|
||||
R_GetTextureParms( &fontWidth, NULL, cls.creditsFont.hFontTexture );
|
||||
|
||||
// half-life font with variable chars witdh
|
||||
buffer = FS_LoadFile( fontname, &length, false );
|
||||
|
||||
// setup creditsfont
|
||||
if( buffer && length >= sizeof( qfont_t ))
|
||||
{
|
||||
src = (qfont_t *)buffer;
|
||||
cls.creditsFont.charHeight = clgame.scrInfo.iCharHeight = src->rowheight;
|
||||
cls.creditsFont.type = FONT_VARIABLE;
|
||||
|
||||
// build rectangles
|
||||
for( i = 0; i < 256; i++ )
|
||||
{
|
||||
cls.creditsFont.fontRc[i].left = (word)src->fontinfo[i].startoffset % fontWidth;
|
||||
cls.creditsFont.fontRc[i].right = cls.creditsFont.fontRc[i].left + src->fontinfo[i].charwidth;
|
||||
cls.creditsFont.fontRc[i].top = (word)src->fontinfo[i].startoffset / fontWidth;
|
||||
cls.creditsFont.fontRc[i].bottom = cls.creditsFont.fontRc[i].top + src->rowheight;
|
||||
cls.creditsFont.charWidths[i] = clgame.scrInfo.charWidths[i] = src->fontinfo[i].charwidth;
|
||||
}
|
||||
cls.creditsFont.valid = true;
|
||||
}
|
||||
if( buffer ) Mem_Free( buffer );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
SCR_LoadCreditsFont
|
||||
|
@ -657,22 +556,41 @@ INTERNAL RESOURCE
|
|||
*/
|
||||
void SCR_LoadCreditsFont( void )
|
||||
{
|
||||
const char *path = "gfx/creditsfont.fnt";
|
||||
dword crc;
|
||||
cl_font_t *const font = &cls.creditsFont;
|
||||
qboolean success = false;
|
||||
float scale = hud_fontscale.value;
|
||||
dword crc = 0;
|
||||
|
||||
// replace default gfx.wad textures by current charset's font
|
||||
if( !CRC32_File( &crc, "gfx.wad" ) || crc == 0x49eb9f16 )
|
||||
{
|
||||
const char *path2 = va("creditsfont_%s.fnt", Cvar_VariableString( "con_charset" ) );
|
||||
if( FS_FileExists( path2, false ) )
|
||||
path = path2;
|
||||
string charsetFnt;
|
||||
|
||||
if( Q_snprintf( charsetFnt, sizeof( charsetFnt ),
|
||||
"creditsfont_%s.fnt", Cvar_VariableString( "con_charset" )) > 0 )
|
||||
{
|
||||
if( FS_FileExists( charsetFnt, false ))
|
||||
success = Con_LoadVariableWidthFont( charsetFnt, font, scale, kRenderTransAdd, TF_FONT );
|
||||
}
|
||||
}
|
||||
|
||||
if( !SCR_LoadVariableWidthFont( path ))
|
||||
if( !success )
|
||||
success = Con_LoadVariableWidthFont( "gfx/creditsfont.fnt", font, scale, kRenderTransAdd, TF_FONT );
|
||||
|
||||
if( !success )
|
||||
success = Con_LoadFixedWidthFont( "gfx/conchars", font, scale, kRenderTransAdd, TF_FONT );
|
||||
|
||||
// copy font size for client.dll
|
||||
if( success )
|
||||
{
|
||||
if( !SCR_LoadFixedWidthFont( "gfx/conchars" ))
|
||||
Con_DPrintf( S_ERROR "failed to load HUD font\n" );
|
||||
int i;
|
||||
|
||||
clgame.scrInfo.iCharHeight = cls.creditsFont.charHeight;
|
||||
|
||||
for( i = 0; i < ARRAYSIZE( cls.creditsFont.charWidths ); i++ )
|
||||
clgame.scrInfo.charWidths[i] = cls.creditsFont.charWidths[i];
|
||||
}
|
||||
else Con_DPrintf( S_ERROR "failed to load HUD font\n" );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -734,13 +652,13 @@ void SCR_RegisterTextures( void )
|
|||
|
||||
if( FS_FileExists( "gfx/lambda.lmp", false ))
|
||||
{
|
||||
if( cl_allow_levelshots->value )
|
||||
if( cl_allow_levelshots.value )
|
||||
cls.loadingBar = ref.dllFuncs.GL_LoadTexture( "gfx/lambda.lmp", NULL, 0, TF_IMAGE|TF_LUMINANCE );
|
||||
else cls.loadingBar = ref.dllFuncs.GL_LoadTexture( "gfx/lambda.lmp", NULL, 0, TF_IMAGE );
|
||||
}
|
||||
else if( FS_FileExists( "gfx/loading.lmp", false ))
|
||||
{
|
||||
if( cl_allow_levelshots->value )
|
||||
if( cl_allow_levelshots.value )
|
||||
cls.loadingBar = ref.dllFuncs.GL_LoadTexture( "gfx/loading.lmp", NULL, 0, TF_IMAGE|TF_LUMINANCE );
|
||||
else cls.loadingBar = ref.dllFuncs.GL_LoadTexture( "gfx/loading.lmp", NULL, 0, TF_IMAGE );
|
||||
}
|
||||
|
@ -757,7 +675,7 @@ Keybinding command
|
|||
*/
|
||||
void SCR_SizeUp_f( void )
|
||||
{
|
||||
Cvar_SetValue( "viewsize", Q_min( scr_viewsize->value + 10, 120 ));
|
||||
Cvar_SetValue( "viewsize", Q_min( scr_viewsize.value + 10, 120 ));
|
||||
}
|
||||
|
||||
|
||||
|
@ -770,7 +688,7 @@ Keybinding command
|
|||
*/
|
||||
void SCR_SizeDown_f( void )
|
||||
{
|
||||
Cvar_SetValue( "viewsize", Q_max( scr_viewsize->value - 10, 30 ));
|
||||
Cvar_SetValue( "viewsize", Q_max( scr_viewsize.value - 10, 30 ));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -780,7 +698,6 @@ SCR_VidInit
|
|||
*/
|
||||
void SCR_VidInit( void )
|
||||
{
|
||||
string libpath;
|
||||
if( !ref.initialized ) // don't call VidInit too soon
|
||||
return;
|
||||
|
||||
|
@ -795,8 +712,11 @@ void SCR_VidInit( void )
|
|||
gameui.globals->scrHeight = refState.height;
|
||||
}
|
||||
|
||||
COM_GetCommonLibraryPath( LIBRARY_CLIENT, libpath, sizeof( libpath ));
|
||||
VGui_Startup( libpath, refState.width, refState.height );
|
||||
// notify vgui about screen size change
|
||||
if( clgame.hInstance )
|
||||
{
|
||||
VGui_Startup( refState.width, refState.height );
|
||||
}
|
||||
|
||||
CL_ClearSpriteTextures(); // now all hud sprites are invalid
|
||||
|
||||
|
@ -806,6 +726,7 @@ void SCR_VidInit( void )
|
|||
|
||||
// restart console size
|
||||
Con_VidInit ();
|
||||
Touch_NotifyResize();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -817,18 +738,18 @@ void SCR_Init( void )
|
|||
{
|
||||
if( scr_init ) return;
|
||||
|
||||
scr_centertime = Cvar_Get( "scr_centertime", "2.5", 0, "centerprint hold time" );
|
||||
cl_levelshot_name = Cvar_Get( "cl_levelshot_name", "*black", 0, "contains path to current levelshot" );
|
||||
cl_allow_levelshots = Cvar_Get( "allow_levelshots", "0", FCVAR_ARCHIVE, "allow engine to use indivdual levelshots instead of 'loading' image" );
|
||||
scr_loading = Cvar_Get( "scr_loading", "0", 0, "loading bar progress" );
|
||||
scr_download = Cvar_Get( "scr_download", "-1", 0, "downloading bar progress" );
|
||||
cl_testlights = Cvar_Get( "cl_testlights", "0", 0, "test dynamic lights" );
|
||||
cl_envshot_size = Cvar_Get( "cl_envshot_size", "256", FCVAR_ARCHIVE, "envshot size of cube side" );
|
||||
v_dark = Cvar_Get( "v_dark", "0", 0, "starts level from dark screen" );
|
||||
scr_viewsize = Cvar_Get( "viewsize", "120", FCVAR_ARCHIVE, "screen size" );
|
||||
net_speeds = Cvar_Get( "net_speeds", "0", FCVAR_ARCHIVE, "show network packets" );
|
||||
cl_showfps = Cvar_Get( "cl_showfps", "1", FCVAR_ARCHIVE, "show client fps" );
|
||||
cl_showpos = Cvar_Get( "cl_showpos", "0", FCVAR_ARCHIVE, "show local player position and velocity" );
|
||||
Cvar_RegisterVariable( &scr_centertime );
|
||||
Cvar_RegisterVariable( &cl_levelshot_name );
|
||||
Cvar_RegisterVariable( &cl_allow_levelshots );
|
||||
Cvar_RegisterVariable( &scr_loading );
|
||||
Cvar_RegisterVariable( &scr_download );
|
||||
Cvar_RegisterVariable( &cl_testlights );
|
||||
Cvar_RegisterVariable( &cl_envshot_size );
|
||||
Cvar_RegisterVariable( &v_dark );
|
||||
Cvar_RegisterVariable( &scr_viewsize );
|
||||
Cvar_RegisterVariable( &net_speeds );
|
||||
Cvar_RegisterVariable( &cl_showfps );
|
||||
Cvar_RegisterVariable( &cl_showpos );
|
||||
|
||||
// register our commands
|
||||
Cmd_AddCommand( "skyname", CL_SetSky_f, "set new skybox by basename" );
|
||||
|
|
|
@ -405,12 +405,15 @@ static cldll_func_dst_t cldllFuncDst =
|
|||
|
||||
void CL_GetSecuredClientAPI( CL_EXPORT_FUNCS F )
|
||||
{
|
||||
cldll_func_src_t cldllFuncSrc = { 0 };
|
||||
modfuncs_t modFuncs = { 0 };
|
||||
|
||||
// secured client dlls need these
|
||||
*(cldll_func_dst_t **)&cldllFuncSrc.pfnVidInit = &cldllFuncDst;
|
||||
*(modfuncs_t **)&cldllFuncSrc.pfnInitialize = &modFuncs;
|
||||
cldll_func_src_t cldllFuncSrc =
|
||||
{
|
||||
(void *)&modFuncs,
|
||||
NULL,
|
||||
(void *)&cldllFuncDst
|
||||
};
|
||||
|
||||
// trying to fill interface now
|
||||
F( &cldllFuncSrc );
|
||||
|
|
|
@ -1037,7 +1037,7 @@ void GAME_EXPORT R_BreakModel( const vec3_t pos, const vec3_t size, const vec3_t
|
|||
vecSpot[1] = pos[1] + COM_RandomFloat( -0.5f, 0.5f ) * size[1];
|
||||
vecSpot[2] = pos[2] + COM_RandomFloat( -0.5f, 0.5f ) * size[2];
|
||||
|
||||
if( CL_PointContents( vecSpot ) != CONTENTS_SOLID )
|
||||
if( PM_CL_PointContents( vecSpot, NULL ) != CONTENTS_SOLID )
|
||||
break; // valid spot
|
||||
}
|
||||
|
||||
|
@ -1245,37 +1245,28 @@ apply params for exploding sprite
|
|||
*/
|
||||
void GAME_EXPORT R_Sprite_Explode( TEMPENTITY *pTemp, float scale, int flags )
|
||||
{
|
||||
if( !pTemp ) return;
|
||||
qboolean noadditive, drawalpha, rotate;
|
||||
|
||||
if( FBitSet( flags, TE_EXPLFLAG_NOADDITIVE ))
|
||||
{
|
||||
// solid sprite
|
||||
pTemp->entity.curstate.rendermode = kRenderNormal;
|
||||
pTemp->entity.curstate.renderamt = 255;
|
||||
}
|
||||
else if( FBitSet( flags, TE_EXPLFLAG_DRAWALPHA ))
|
||||
{
|
||||
// alpha sprite (came from hl2)
|
||||
pTemp->entity.curstate.rendermode = kRenderTransAlpha;
|
||||
pTemp->entity.curstate.renderamt = 180;
|
||||
}
|
||||
else
|
||||
{
|
||||
// additive sprite
|
||||
pTemp->entity.curstate.rendermode = kRenderTransAdd;
|
||||
pTemp->entity.curstate.renderamt = 180;
|
||||
}
|
||||
if( !pTemp )
|
||||
return;
|
||||
|
||||
if( FBitSet( flags, TE_EXPLFLAG_ROTATE ))
|
||||
{
|
||||
// came from hl2
|
||||
pTemp->entity.angles[2] = COM_RandomLong( 0, 360 );
|
||||
}
|
||||
noadditive = FBitSet( flags, TE_EXPLFLAG_NOADDITIVE );
|
||||
drawalpha = FBitSet( flags, TE_EXPLFLAG_DRAWALPHA );
|
||||
rotate = FBitSet( flags, TE_EXPLFLAG_ROTATE );
|
||||
|
||||
pTemp->entity.curstate.renderfx = kRenderFxNone;
|
||||
pTemp->entity.baseline.origin[2] = 8;
|
||||
pTemp->entity.origin[2] += 10;
|
||||
pTemp->entity.curstate.scale = scale;
|
||||
pTemp->entity.baseline.origin[2] = 8.0f;
|
||||
pTemp->entity.origin[2] = pTemp->entity.origin[2] + 10.0f;
|
||||
if( rotate )
|
||||
pTemp->entity.angles[2] = COM_RandomFloat( 0.0, 360.0f );
|
||||
|
||||
pTemp->entity.curstate.rendermode = noadditive ? kRenderNormal :
|
||||
drawalpha ? kRenderTransAlpha : kRenderTransAdd;
|
||||
pTemp->entity.curstate.renderamt = noadditive ? 0xff : 0xb4;
|
||||
pTemp->entity.curstate.renderfx = 0;
|
||||
pTemp->entity.curstate.rendercolor.r = 0;
|
||||
pTemp->entity.curstate.rendercolor.g = 0;
|
||||
pTemp->entity.curstate.rendercolor.b = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1974,6 +1965,9 @@ void CL_ParseTempEntity( sizebuf_t *msg )
|
|||
pos[1] = MSG_ReadCoord( &buf );
|
||||
pos[2] = MSG_ReadCoord( &buf );
|
||||
R_BlobExplosion( pos );
|
||||
|
||||
hSound = S_RegisterSound( cl_explode_sounds[0] );
|
||||
S_StartSound( pos, -1, CHAN_AUTO, hSound, VOL_NORM, 1.0f, PITCH_NORM, 0 );
|
||||
break;
|
||||
case TE_SMOKE:
|
||||
pos[0] = MSG_ReadCoord( &buf );
|
||||
|
@ -2027,7 +2021,7 @@ void CL_ParseTempEntity( sizebuf_t *msg )
|
|||
dl->decay = 300;
|
||||
|
||||
hSound = S_RegisterSound( cl_explode_sounds[0] );
|
||||
S_StartSound( pos, 0, CHAN_STATIC, hSound, VOL_NORM, 0.6f, PITCH_NORM, 0 );
|
||||
S_StartSound( pos, -1, CHAN_AUTO, hSound, VOL_NORM, 0.6f, PITCH_NORM, 0 );
|
||||
break;
|
||||
case TE_BSPDECAL:
|
||||
case TE_DECAL:
|
||||
|
@ -2635,7 +2629,7 @@ void CL_UpdateFlashlight( cl_entity_t *ent )
|
|||
vec3_t forward, view_ofs;
|
||||
vec3_t vecSrc, vecEnd;
|
||||
float falloff;
|
||||
pmtrace_t *trace;
|
||||
pmtrace_t trace;
|
||||
cl_entity_t *hit;
|
||||
dlight_t *dl;
|
||||
|
||||
|
@ -2666,28 +2660,26 @@ void CL_UpdateFlashlight( cl_entity_t *ent )
|
|||
VectorAdd( ent->origin, view_ofs, vecSrc );
|
||||
VectorMA( vecSrc, FLASHLIGHT_DISTANCE, forward, vecEnd );
|
||||
|
||||
trace = CL_VisTraceLine( vecSrc, vecEnd, PM_STUDIO_BOX );
|
||||
trace = CL_TraceLine( vecSrc, vecEnd, PM_STUDIO_BOX );
|
||||
|
||||
// update flashlight endpos
|
||||
dl = CL_AllocDlight( ent->index );
|
||||
#if 1
|
||||
hit = CL_GetEntityByIndex( clgame.pmove->visents[trace->ent].info );
|
||||
hit = CL_GetEntityByIndex( clgame.pmove->visents[trace.ent].info );
|
||||
if( hit && hit->model && ( hit->model->type == mod_alias || hit->model->type == mod_studio ))
|
||||
VectorCopy( hit->origin, dl->origin );
|
||||
else VectorCopy( trace->endpos, dl->origin );
|
||||
else VectorCopy( trace.endpos, dl->origin );
|
||||
#else
|
||||
VectorCopy( trace->endpos, dl->origin );
|
||||
#endif
|
||||
// compute falloff
|
||||
falloff = trace->fraction * FLASHLIGHT_DISTANCE;
|
||||
falloff = trace.fraction * FLASHLIGHT_DISTANCE;
|
||||
if( falloff < 500.0f ) falloff = 1.0f;
|
||||
else falloff = 500.0f / falloff;
|
||||
falloff *= falloff;
|
||||
|
||||
// apply brigthness to dlight
|
||||
dl->color.r = bound( 0, falloff * 255, 255 );
|
||||
dl->color.g = bound( 0, falloff * 255, 255 );
|
||||
dl->color.b = bound( 0, falloff * 255, 255 );
|
||||
dl->color.r = dl->color.g = dl->color.b = bound( 0, falloff * 255, 255 );
|
||||
dl->die = cl.time + 0.01f; // die on next frame
|
||||
dl->radius = 80;
|
||||
}
|
||||
|
@ -2852,10 +2844,10 @@ void CL_TestLights( void )
|
|||
float f, r;
|
||||
dlight_t *dl;
|
||||
|
||||
if( !CVAR_TO_BOOL( cl_testlights ))
|
||||
if( !cl_testlights.value )
|
||||
return;
|
||||
|
||||
numLights = bound( 1, cl_testlights->value, MAX_DLIGHTS );
|
||||
numLights = bound( 1, cl_testlights.value, MAX_DLIGHTS );
|
||||
AngleVectors( cl.viewangles, forward, right, NULL );
|
||||
|
||||
for( i = 0; i < numLights; i++ )
|
||||
|
@ -2928,7 +2920,15 @@ void CL_PlayerDecal( int playernum, int customIndex, int entityIndex, float *pos
|
|||
{
|
||||
if( !pCust->nUserData1 )
|
||||
{
|
||||
const char *decalname = va( "player%dlogo%d", playernum, customIndex );
|
||||
int sprayTextureIndex;
|
||||
char decalname[MAX_VA_STRING];
|
||||
|
||||
Q_snprintf( decalname, sizeof( decalname ), "player%dlogo%d", playernum, customIndex );
|
||||
sprayTextureIndex = ref.dllFuncs.GL_FindTexture( decalname );
|
||||
if( sprayTextureIndex != 0 )
|
||||
{
|
||||
ref.dllFuncs.GL_FreeTexture( sprayTextureIndex );
|
||||
}
|
||||
pCust->nUserData1 = GL_LoadTextureInternal( decalname, pCust->pInfo, TF_DECAL );
|
||||
}
|
||||
textureIndex = pCust->nUserData1;
|
||||
|
|
|
@ -209,7 +209,7 @@ qboolean SCR_PlayCinematic( const char *arg )
|
|||
|
||||
if( FS_FileExists( arg, false ) && !fullpath )
|
||||
{
|
||||
Con_Printf( S_ERROR "Couldn't load %s from packfile. Please extract it\n", path );
|
||||
Con_Printf( S_ERROR "Couldn't load %s from packfile. Please extract it\n", arg );
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ void V_CalcViewRect( void )
|
|||
{
|
||||
// intermission is always full screen
|
||||
if( cl.intermission ) size = 120.0f;
|
||||
else size = scr_viewsize->value;
|
||||
else size = scr_viewsize.value;
|
||||
|
||||
if( size >= 120.0f )
|
||||
sb_lines = 0; // no status bar at all
|
||||
|
@ -47,12 +47,12 @@ void V_CalcViewRect( void )
|
|||
sb_lines = 24; // no inventory
|
||||
else sb_lines = 48;
|
||||
|
||||
if( scr_viewsize->value >= 100.0f )
|
||||
if( scr_viewsize.value >= 100.0f )
|
||||
{
|
||||
full = true;
|
||||
size = 100.0f;
|
||||
}
|
||||
else size = scr_viewsize->value;
|
||||
else size = scr_viewsize.value;
|
||||
|
||||
if( cl.intermission )
|
||||
{
|
||||
|
@ -144,7 +144,7 @@ void V_SetRefParams( ref_params_t *fd )
|
|||
VectorCopy( cl.viewangles, fd->cl_viewangles );
|
||||
fd->health = cl.local.health;
|
||||
VectorCopy( cl.crosshairangle, fd->crosshairangle );
|
||||
fd->viewsize = scr_viewsize->value;
|
||||
fd->viewsize = scr_viewsize.value;
|
||||
|
||||
VectorCopy( cl.punchangle, fd->punchangle );
|
||||
fd->maxclients = cl.maxclients;
|
||||
|
@ -229,6 +229,53 @@ void V_RefApplyOverview( ref_viewpass_t *rvp )
|
|||
ref.dllFuncs.GL_OrthoBounds( mins, maxs );
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
V_CalcFov
|
||||
====================
|
||||
*/
|
||||
static float V_CalcFov( float *fov_x, float width, float height )
|
||||
{
|
||||
float x, half_fov_y;
|
||||
|
||||
if( *fov_x < 1.0f || *fov_x > 179.0f )
|
||||
*fov_x = 90.0f; // default value
|
||||
|
||||
x = width / tan( DEG2RAD( *fov_x ) * 0.5f );
|
||||
half_fov_y = atan( height / x );
|
||||
|
||||
return RAD2DEG( half_fov_y ) * 2;
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
V_AdjustFov
|
||||
====================
|
||||
*/
|
||||
static void V_AdjustFov( float *fov_x, float *fov_y, float width, float height, qboolean lock_x )
|
||||
{
|
||||
float x, y;
|
||||
|
||||
if( width * 3 == 4 * height || width * 4 == height * 5 )
|
||||
{
|
||||
// 4:3 or 5:4 ratio
|
||||
return;
|
||||
}
|
||||
|
||||
if( lock_x )
|
||||
{
|
||||
*fov_y = 2 * atan((width * 3) / (height * 4) * tan( *fov_y * M_PI_F / 360.0f * 0.5f )) * 360 / M_PI_F;
|
||||
return;
|
||||
}
|
||||
|
||||
y = V_CalcFov( fov_x, 640, 480 );
|
||||
x = *fov_x;
|
||||
|
||||
*fov_x = V_CalcFov( &y, height, width );
|
||||
if( *fov_x < x ) *fov_x = x;
|
||||
else *fov_y = y;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
V_GetRefParams
|
||||
|
@ -264,7 +311,7 @@ void V_GetRefParams( ref_params_t *fd, ref_viewpass_t *rvp )
|
|||
rvp->fov_y = V_CalcFov( &rvp->fov_x, clgame.viewport[2], clgame.viewport[3] );
|
||||
|
||||
// adjust FOV for widescreen
|
||||
if( refState.wideScreen && r_adjust_fov->value )
|
||||
if( refState.wideScreen && r_adjust_fov.value )
|
||||
V_AdjustFov( &rvp->fov_x, &rvp->fov_y, clgame.viewport[2], clgame.viewport[3], false );
|
||||
|
||||
rvp->flags = 0;
|
||||
|
@ -286,16 +333,13 @@ qboolean V_PreRender( void )
|
|||
if( !ref.initialized )
|
||||
return false;
|
||||
|
||||
if( host.status == HOST_NOFOCUS )
|
||||
return false;
|
||||
|
||||
if( host.status == HOST_SLEEP )
|
||||
return false;
|
||||
|
||||
// if the screen is disabled (loading plaque is up)
|
||||
if( cls.disable_screen )
|
||||
{
|
||||
if(( host.realtime - cls.disable_screen ) > cl_timeout->value )
|
||||
if(( host.realtime - cls.disable_screen ) > cl_timeout.value )
|
||||
{
|
||||
Con_Reportf( "V_PreRender: loading plaque timed out\n" );
|
||||
cls.disable_screen = 0.0f;
|
||||
|
@ -320,11 +364,13 @@ V_RenderView
|
|||
*/
|
||||
void V_RenderView( void )
|
||||
{
|
||||
ref_params_t rp;
|
||||
// HACKHACK: make ref params static
|
||||
// not really critical but allows client.dll to take address of refdef and don't trigger ASan
|
||||
static ref_params_t rp;
|
||||
ref_viewpass_t rvp;
|
||||
int viewnum = 0;
|
||||
|
||||
if( !cl.video_prepped || ( !ui_renderworld->value && UI_IsVisible() && !cl.background ))
|
||||
if( !cl.video_prepped || ( !ui_renderworld.value && UI_IsVisible() && !cl.background ))
|
||||
return; // still loading
|
||||
|
||||
V_CalcViewRect (); // compute viewport rectangle
|
||||
|
@ -428,7 +474,7 @@ void R_ShowTree( void )
|
|||
float y = NODE_INTERVAL_Y(1.0f);
|
||||
mleaf_t *viewleaf;
|
||||
|
||||
if( !cl.worldmodel || !CVAR_TO_BOOL( r_showtree ))
|
||||
if( !cl.worldmodel || !r_showtree.value )
|
||||
return;
|
||||
|
||||
world.recursion_level = 0;
|
||||
|
|
|
@ -33,6 +33,7 @@ GNU General Public License for more details.
|
|||
#include "net_api.h"
|
||||
#include "world.h"
|
||||
#include "ref_common.h"
|
||||
#include "voice.h"
|
||||
|
||||
// client sprite types
|
||||
#define SPR_CLIENT 0 // client sprite for temp-entities or user-textures
|
||||
|
@ -107,7 +108,6 @@ extern int CL_UPDATE_BACKUP;
|
|||
#define MIN_UPDATERATE 10.0f
|
||||
#define MAX_UPDATERATE 102.0f
|
||||
|
||||
#define MIN_EX_INTERP 0.005f
|
||||
#define MAX_EX_INTERP 0.1f
|
||||
|
||||
#define CL_MIN_RESEND_TIME 1.5f // mininum time gap (in seconds) before a subsequent connection request is sent.
|
||||
|
@ -138,7 +138,7 @@ typedef struct
|
|||
int light_level;
|
||||
int waterlevel;
|
||||
int usehull;
|
||||
int moving;
|
||||
qboolean moving;
|
||||
int pushmsec;
|
||||
int weapons;
|
||||
float maxspeed;
|
||||
|
@ -210,7 +210,7 @@ typedef struct
|
|||
// a lerp point for other data
|
||||
double oldtime; // previous cl.time, time-oldtime is used
|
||||
// to decay light values and smooth step ups
|
||||
float timedelta; // floating delta between two updates
|
||||
double timedelta; // floating delta between two updates
|
||||
|
||||
char serverinfo[MAX_SERVERINFO_STRING];
|
||||
player_info_t players[MAX_CLIENTS]; // collected info about all other players include himself
|
||||
|
@ -318,32 +318,46 @@ typedef struct
|
|||
pfnEventHook func; // user-defined function
|
||||
} cl_user_event_t;
|
||||
|
||||
#define FONT_FIXED 0
|
||||
#define FONT_VARIABLE 1
|
||||
#define FONT_FIXED 0
|
||||
#define FONT_VARIABLE 1
|
||||
|
||||
#define FONT_DRAW_HUD BIT( 0 ) // pass to drawing function to apply hud_scale
|
||||
#define FONT_DRAW_UTF8 BIT( 1 ) // call UtfProcessChar
|
||||
#define FONT_DRAW_FORCECOL BIT( 2 ) // ignore colorcodes
|
||||
#define FONT_DRAW_NORENDERMODE BIT( 3 ) // ignore font's default rendermode
|
||||
#define FONT_DRAW_NOLF BIT( 4 ) // ignore \n
|
||||
#define FONT_DRAW_RESETCOLORONLF BIT( 5 ) // yet another flag to simulate consecutive Con_DrawString calls...
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int hFontTexture; // handle to texture
|
||||
wrect_t fontRc[256]; // rectangles
|
||||
byte charWidths[256];
|
||||
int charHeight;
|
||||
int type;
|
||||
qboolean valid; // all rectangles are valid
|
||||
int hFontTexture; // handle to texture
|
||||
wrect_t fontRc[256]; // tex coords
|
||||
float scale; // scale factor
|
||||
byte charWidths[256]; // scaled widths
|
||||
int charHeight; // scaled height
|
||||
int type; // fixed width font or variable
|
||||
int rendermode; // default rendermode
|
||||
qboolean nearest; // nearest filtering enabled
|
||||
qboolean valid; // all rectangles are valid
|
||||
} cl_font_t;
|
||||
|
||||
typedef struct scissor_state_s
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
int width;
|
||||
int height;
|
||||
qboolean test;
|
||||
} scissor_state_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// scissor test
|
||||
scissor_state_t scissor;
|
||||
|
||||
// temp handle
|
||||
const model_t *pSprite; // pointer to current SpriteTexture
|
||||
|
||||
// scissor test
|
||||
int scissor_x;
|
||||
int scissor_y;
|
||||
int scissor_width;
|
||||
int scissor_height;
|
||||
qboolean scissor_test;
|
||||
qboolean adjust_size; // allow to adjust scale for fonts
|
||||
|
||||
int renderMode; // override kRenderMode from TriAPI
|
||||
TRICULLSTYLE cullMode; // override CULL FACE from TriAPI
|
||||
|
||||
|
@ -370,14 +384,10 @@ typedef struct cl_predicted_player_s
|
|||
|
||||
typedef struct
|
||||
{
|
||||
int gl_texturenum; // this is a real texnum
|
||||
|
||||
// scissor test
|
||||
int scissor_x;
|
||||
int scissor_y;
|
||||
int scissor_width;
|
||||
int scissor_height;
|
||||
qboolean scissor_test;
|
||||
scissor_state_t scissor;
|
||||
|
||||
int gl_texturenum; // this is a real texnum
|
||||
|
||||
// holds text color
|
||||
rgba_t textColor;
|
||||
|
@ -413,13 +423,6 @@ typedef struct
|
|||
float applied_angle;
|
||||
} screen_shake_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
NET_REQUEST_CANCEL = 0, // request was cancelled for some reasons
|
||||
NET_REQUEST_GAMEUI, // called from GameUI
|
||||
NET_REQUEST_CLIENT, // called from Client
|
||||
} net_request_type_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
net_response_t resp;
|
||||
|
@ -481,9 +484,7 @@ typedef struct
|
|||
client_textmessage_t *titles; // title messages, not network messages
|
||||
int numTitles;
|
||||
|
||||
net_request_type_t request_type; // filter the requests
|
||||
net_request_t net_requests[MAX_REQUESTS]; // no reason to keep more
|
||||
net_request_t *master_request; // queued master request
|
||||
|
||||
efrag_t *free_efrags; // linked efrags
|
||||
cl_entity_t viewent; // viewmodel
|
||||
|
@ -617,7 +618,10 @@ typedef struct
|
|||
file_t *demofile;
|
||||
file_t *demoheader; // contain demo startup info in case we record a demo on this level
|
||||
qboolean internetservers_wait; // internetservers is waiting for dns request
|
||||
qboolean internetservers_pending; // internetservers is waiting for dns request
|
||||
qboolean internetservers_pending; // if true, clean master server pings
|
||||
uint32_t internetservers_key; // compare key to validate master server reply
|
||||
char internetservers_query[512]; // cached query
|
||||
uint32_t internetservers_query_len;
|
||||
|
||||
// legacy mode support
|
||||
qboolean legacymode; // one-way 48 protocol compatibility
|
||||
|
@ -649,45 +653,47 @@ extern convar_t cl_logocolor;
|
|||
extern convar_t cl_allow_download;
|
||||
extern convar_t cl_allow_upload;
|
||||
extern convar_t cl_download_ingame;
|
||||
extern convar_t *cl_nopred;
|
||||
extern convar_t *cl_timeout;
|
||||
extern convar_t *cl_nodelta;
|
||||
extern convar_t *cl_interp;
|
||||
extern convar_t *cl_nointerp;
|
||||
extern convar_t *cl_showerror;
|
||||
extern convar_t *cl_nosmooth;
|
||||
extern convar_t *cl_smoothtime;
|
||||
extern convar_t *cl_crosshair;
|
||||
extern convar_t *cl_testlights;
|
||||
extern convar_t *cl_cmdrate;
|
||||
extern convar_t *cl_updaterate;
|
||||
extern convar_t *cl_solid_players;
|
||||
extern convar_t *cl_idealpitchscale;
|
||||
extern convar_t *cl_allow_levelshots;
|
||||
extern convar_t *cl_lightstyle_lerping;
|
||||
extern convar_t *cl_draw_particles;
|
||||
extern convar_t *cl_draw_tracers;
|
||||
extern convar_t *cl_levelshot_name;
|
||||
extern convar_t *cl_draw_beams;
|
||||
extern convar_t *cl_clockreset;
|
||||
extern convar_t *cl_fixtimerate;
|
||||
extern convar_t *hud_scale;
|
||||
extern convar_t *gl_showtextures;
|
||||
extern convar_t *cl_bmodelinterp;
|
||||
extern convar_t *cl_lw; // local weapons
|
||||
extern convar_t *cl_charset;
|
||||
extern convar_t *cl_trace_messages;
|
||||
extern convar_t *hud_utf8;
|
||||
extern convar_t *cl_showevents;
|
||||
extern convar_t *scr_centertime;
|
||||
extern convar_t *scr_viewsize;
|
||||
extern convar_t *scr_loading;
|
||||
extern convar_t *v_dark; // start from dark
|
||||
extern convar_t *net_graph;
|
||||
extern convar_t *rate;
|
||||
extern convar_t *m_ignore;
|
||||
extern convar_t *r_showtree;
|
||||
extern convar_t *ui_renderworld;
|
||||
extern convar_t cl_nopred;
|
||||
extern convar_t cl_timeout;
|
||||
extern convar_t cl_nodelta;
|
||||
extern convar_t cl_interp;
|
||||
extern convar_t cl_nointerp;
|
||||
extern convar_t cl_showerror;
|
||||
extern convar_t cl_nosmooth;
|
||||
extern convar_t cl_smoothtime;
|
||||
extern convar_t cl_crosshair;
|
||||
extern convar_t cl_testlights;
|
||||
extern convar_t cl_cmdrate;
|
||||
extern convar_t cl_updaterate;
|
||||
extern convar_t cl_solid_players;
|
||||
extern convar_t cl_idealpitchscale;
|
||||
extern convar_t cl_allow_levelshots;
|
||||
extern convar_t cl_lightstyle_lerping;
|
||||
extern convar_t cl_draw_particles;
|
||||
extern convar_t cl_draw_tracers;
|
||||
extern convar_t cl_levelshot_name;
|
||||
extern convar_t cl_draw_beams;
|
||||
extern convar_t cl_clockreset;
|
||||
extern convar_t cl_fixtimerate;
|
||||
extern convar_t hud_fontscale;
|
||||
extern convar_t hud_scale;
|
||||
extern convar_t r_showtextures;
|
||||
extern convar_t cl_bmodelinterp;
|
||||
extern convar_t cl_lw; // local weapons
|
||||
extern convar_t cl_charset;
|
||||
extern convar_t cl_trace_messages;
|
||||
extern convar_t cl_trace_events;
|
||||
extern convar_t hud_utf8;
|
||||
extern convar_t cl_showevents;
|
||||
extern convar_t scr_centertime;
|
||||
extern convar_t scr_viewsize;
|
||||
extern convar_t scr_loading;
|
||||
extern convar_t v_dark; // start from dark
|
||||
extern convar_t net_graph;
|
||||
extern convar_t rate;
|
||||
extern convar_t m_ignore;
|
||||
extern convar_t r_showtree;
|
||||
extern convar_t ui_renderworld;
|
||||
|
||||
//=============================================================================
|
||||
|
||||
|
@ -794,6 +800,20 @@ void CL_ResetEvent( event_info_t *ei );
|
|||
word CL_EventIndex( const char *name );
|
||||
void CL_FireEvents( void );
|
||||
|
||||
//
|
||||
// cl_font.c
|
||||
//
|
||||
qboolean CL_FixedFont( cl_font_t *font );
|
||||
qboolean Con_LoadFixedWidthFont( const char *fontname, cl_font_t *font, float scale, int rendermode, uint texFlags );
|
||||
qboolean Con_LoadVariableWidthFont( const char *fontname, cl_font_t *font, float scale, int rendermode, uint texFlags );
|
||||
void CL_FreeFont( cl_font_t *font );
|
||||
int CL_DrawCharacter( float x, float y, int number, rgba_t color, cl_font_t *font, int flags );
|
||||
int CL_DrawString( float x, float y, const char *s, rgba_t color, cl_font_t *font, int flags );
|
||||
void CL_DrawCharacterLen( cl_font_t *font, int number, int *width, int *height );
|
||||
void CL_DrawStringLen( cl_font_t *font, const char *s, int *width, int *height, int flags );
|
||||
int CL_DrawStringf( cl_font_t *font, float x, float y, rgba_t color, int flags, const char *fmt, ... ) _format( 6 );
|
||||
|
||||
|
||||
//
|
||||
// cl_game.c
|
||||
//
|
||||
|
@ -804,37 +824,35 @@ void CL_LinkUserMessage( char *pszName, const int svc_num, int iSize );
|
|||
void CL_ParseFinaleCutscene( sizebuf_t *msg, int level );
|
||||
void CL_ParseTextMessage( sizebuf_t *msg );
|
||||
void CL_DrawHUD( int state );
|
||||
void CL_InitEdicts( void );
|
||||
void CL_InitEdicts( int maxclients );
|
||||
void CL_FreeEdicts( void );
|
||||
void CL_ClearWorld( void );
|
||||
void CL_DrawCenterPrint( void );
|
||||
void CL_ClearSpriteTextures( void );
|
||||
void CL_FreeEntity( cl_entity_t *pEdict );
|
||||
void CL_CenterPrint( const char *text, float y );
|
||||
void CL_TextMessageParse( byte *pMemFile, int fileSize );
|
||||
client_textmessage_t *CL_TextMessageGet( const char *pName );
|
||||
int pfnDecalIndexFromName( const char *szDecalName );
|
||||
int pfnIndexFromTrace( struct pmtrace_s *pTrace );
|
||||
model_t *CL_ModelHandle( int modelindex );
|
||||
void NetAPI_CancelAllRequests( void );
|
||||
int CL_FindModelIndex( const char *m );
|
||||
cl_entity_t *CL_GetLocalPlayer( void );
|
||||
model_t *CL_LoadClientSprite( const char *filename );
|
||||
model_t *CL_LoadModel( const char *modelname, int *index );
|
||||
HSPRITE EXPORT pfnSPR_Load( const char *szPicName );
|
||||
HSPRITE pfnSPR_LoadExt( const char *szPicName, uint texFlags );
|
||||
void PicAdjustSize( float *x, float *y, float *w, float *h );
|
||||
void SPR_AdjustSize( float *x, float *y, float *w, float *h );
|
||||
void SPR_AdjustTexCoords( float width, float height, float *s1, float *t1, float *s2, float *t2 );
|
||||
int CL_GetScreenInfo( SCREENINFO *pscrinfo );
|
||||
void CL_FillRGBA( int x, int y, int width, int height, int r, int g, int b, int a );
|
||||
void CL_PlayerTrace( float *start, float *end, int traceFlags, int ignore_pe, pmtrace_t *tr );
|
||||
void CL_PlayerTraceExt( float *start, float *end, int traceFlags, int (*pfnIgnore)( physent_t *pe ), pmtrace_t *tr );
|
||||
void CL_SetTraceHull( int hull );
|
||||
pmtrace_t *PM_CL_TraceLine( float *start, float *end, int flags, int usehull, int ignore_pe );
|
||||
const char *PM_CL_TraceTexture( int ground, float *vstart, float *vend );
|
||||
int PM_CL_PointContents( const float *p, int *truecontents );
|
||||
void CL_GetMousePosition( int *mx, int *my ); // TODO: move to input
|
||||
cl_entity_t* CL_GetViewModel( void );
|
||||
void pfnGetScreenFade( struct screenfade_s *fade );
|
||||
physent_t *pfnGetPhysent( int idx );
|
||||
struct msurface_s *pfnTraceSurface( int ground, float *vstart, float *vend );
|
||||
movevars_t *pfnGetMoveVars( void );
|
||||
void CL_EnableScissor( scissor_state_t *scissor, int x, int y, int width, int height );
|
||||
void CL_DisableScissor( scissor_state_t *scissor );
|
||||
qboolean CL_Scissor( const scissor_state_t *scissor, float *x, float *y, float *width, float *height, float *u0, float *v0, float *u1, float *v1 );
|
||||
|
||||
_inline cl_entity_t *CL_EDICT_NUM( int n )
|
||||
{
|
||||
|
@ -854,18 +872,45 @@ _inline cl_entity_t *CL_EDICT_NUM( int n )
|
|||
//
|
||||
// cl_parse.c
|
||||
//
|
||||
void CL_ParseSetAngle( sizebuf_t *msg );
|
||||
void CL_ParseServerData( sizebuf_t *msg, qboolean legacy );
|
||||
void CL_ParseLightStyle( sizebuf_t *msg );
|
||||
void CL_UpdateUserinfo( sizebuf_t *msg, qboolean legacy );
|
||||
void CL_ParseResource( sizebuf_t *msg );
|
||||
void CL_ParseClientData( sizebuf_t *msg );
|
||||
void CL_UpdateUserPings( sizebuf_t *msg );
|
||||
void CL_ParseParticles( sizebuf_t *msg );
|
||||
void CL_ParseRestoreSoundPacket( sizebuf_t *msg );
|
||||
void CL_ParseBaseline( sizebuf_t *msg, qboolean legacy );
|
||||
void CL_ParseSignon( sizebuf_t *msg );
|
||||
void CL_ParseRestore( sizebuf_t *msg );
|
||||
void CL_ParseStaticDecal( sizebuf_t *msg );
|
||||
void CL_ParseAddAngle( sizebuf_t *msg );
|
||||
void CL_RegisterUserMessage( sizebuf_t *msg );
|
||||
void CL_ParseMovevars( sizebuf_t *msg );
|
||||
void CL_ParseResourceRequest( sizebuf_t *msg );
|
||||
void CL_ParseCustomization( sizebuf_t *msg );
|
||||
void CL_ParseCrosshairAngle( sizebuf_t *msg );
|
||||
void CL_ParseSoundFade( sizebuf_t *msg );
|
||||
void CL_ParseFileTransferFailed( sizebuf_t *msg );
|
||||
void CL_ParseHLTV( sizebuf_t *msg );
|
||||
void CL_ParseDirector( sizebuf_t *msg );
|
||||
void CL_ParseResLocation( sizebuf_t *msg );
|
||||
void CL_ParseCvarValue( sizebuf_t *msg, const qboolean ext );
|
||||
void CL_ParseServerMessage( sizebuf_t *msg, qboolean normal_message );
|
||||
void CL_ParseLegacyServerMessage( sizebuf_t *msg, qboolean normal_message );
|
||||
void CL_LegacyPrecache_f( void );
|
||||
|
||||
void CL_ParseTempEntity( sizebuf_t *msg );
|
||||
void CL_StartResourceDownloading( const char *pszMessage, qboolean bCustom );
|
||||
qboolean CL_DispatchUserMessage( const char *pszName, int iSize, void *pbuf );
|
||||
qboolean CL_RequestMissingResources( void );
|
||||
void CL_RegisterResources ( sizebuf_t *msg );
|
||||
void CL_ParseViewEntity( sizebuf_t *msg );
|
||||
void CL_ParseServerTime( sizebuf_t *msg );
|
||||
|
||||
//
|
||||
// cl_parse_48.c
|
||||
//
|
||||
void CL_ParseLegacyServerMessage( sizebuf_t *msg, qboolean normal_message );
|
||||
void CL_LegacyPrecache_f( void );
|
||||
|
||||
//
|
||||
// cl_scrn.c
|
||||
//
|
||||
|
@ -910,10 +955,8 @@ void CL_PredictMovement( qboolean repredicting );
|
|||
void CL_CheckPredictionError( void );
|
||||
qboolean CL_IsPredicted( void );
|
||||
int CL_TruePointContents( const vec3_t p );
|
||||
int CL_PointContents( const vec3_t p );
|
||||
int CL_WaterEntity( const float *rgflPos );
|
||||
cl_entity_t *CL_GetWaterEntity( const float *rgflPos );
|
||||
void CL_SetupPMove( playermove_t *pmove, local_state_t *from, usercmd_t *ucmd, qboolean runfuncs, double time );
|
||||
int CL_TestLine( const vec3_t start, const vec3_t end, int flags );
|
||||
pmtrace_t *CL_VisTraceLine( vec3_t start, vec3_t end, int flags );
|
||||
pmtrace_t CL_TraceLine( vec3_t start, vec3_t end, int flags );
|
||||
|
@ -922,7 +965,6 @@ void CL_PopTraceBounds( void );
|
|||
void CL_MoveSpectatorCamera( void );
|
||||
void CL_SetLastUpdate( void );
|
||||
void CL_RedoPrediction( void );
|
||||
void CL_ClearPhysEnts( void );
|
||||
void CL_PushPMStates( void );
|
||||
void CL_PopPMStates( void );
|
||||
void CL_SetUpPlayerPrediction( int dopred, int bIncludeLocalClient );
|
||||
|
@ -963,7 +1005,7 @@ void CL_ClearAllRemaps( void );
|
|||
// cl_render.c
|
||||
//
|
||||
qboolean R_InitRenderAPI( void );
|
||||
int CL_RenderGetParm( const int parm, const int arg, const qboolean checkRef );
|
||||
intptr_t CL_RenderGetParm( const int parm, const int arg, const qboolean checkRef );
|
||||
lightstyle_t *CL_GetLightStyle( int number );
|
||||
int R_FatPVS( const vec3_t org, float radius, byte *visbuffer, qboolean merge, qboolean fullvis );
|
||||
const ref_overview_t *GL_GetOverviewParms( void );
|
||||
|
@ -973,12 +1015,10 @@ const ref_overview_t *GL_GetOverviewParms( void );
|
|||
//
|
||||
void R_StoreEfrags( efrag_t **ppefrag, int framecount );
|
||||
void R_AddEfrags( cl_entity_t *ent );
|
||||
void R_RemoveEfrags( cl_entity_t *ent );
|
||||
//
|
||||
// cl_tent.c
|
||||
//
|
||||
struct particle_s;
|
||||
int CL_AddEntity( int entityType, cl_entity_t *pEnt );
|
||||
void CL_WeaponAnim( int iAnim, int body );
|
||||
void CL_ClearEffects( void );
|
||||
void CL_ClearEfrags( void );
|
||||
|
@ -1012,7 +1052,7 @@ void CL_RunLightStyles( void );
|
|||
//
|
||||
// console.c
|
||||
//
|
||||
extern convar_t *con_fontsize;
|
||||
extern convar_t con_fontsize;
|
||||
int Con_Visible( void );
|
||||
qboolean Con_FixedFont( void );
|
||||
void Con_VidInit( void );
|
||||
|
@ -1027,13 +1067,13 @@ int Con_UtfProcessChar( int in );
|
|||
int Con_UtfProcessCharForce( int in );
|
||||
int Con_UtfMoveLeft( char *str, int pos );
|
||||
int Con_UtfMoveRight( char *str, int pos, int length );
|
||||
void Con_DrawStringLen( const char *pText, int *length, int *height );
|
||||
int Con_DrawString( int x, int y, const char *string, rgba_t setColor );
|
||||
int Con_DrawCharacter( int x, int y, int number, rgba_t color );
|
||||
void Con_DrawCharacterLen( int number, int *width, int *height );
|
||||
void Con_DefaultColor( int r, int g, int b );
|
||||
void Con_InvalidateFonts( void );
|
||||
void Con_SetFont( int fontNum );
|
||||
cl_font_t *Con_GetCurFont( void );
|
||||
cl_font_t *Con_GetFont( int num );
|
||||
void Con_DrawCharacterLen( int number, int *width, int *height );
|
||||
int Con_DrawString( int x, int y, const char *string, rgba_t setColor ); // legacy, use cl_font.c
|
||||
void GAME_EXPORT Con_DrawStringLen( const char *pText, int *length, int *height ); // legacy, use cl_font.c
|
||||
void Con_CharEvent( int key );
|
||||
void Con_RestoreFont( void );
|
||||
void Key_Console( int key );
|
||||
|
@ -1128,7 +1168,6 @@ void CL_PlayVideo_f( void );
|
|||
// keys.c
|
||||
//
|
||||
int Key_IsDown( int keynum );
|
||||
const char *Key_IsBind( int keynum );
|
||||
void Key_Event( int key, int down );
|
||||
void Key_Init( void );
|
||||
void Key_WriteBindings( file_t *f );
|
||||
|
|
|
@ -22,13 +22,14 @@ GNU General Public License for more details.
|
|||
#include "wadfile.h"
|
||||
#include "input.h"
|
||||
|
||||
convar_t *con_notifytime;
|
||||
convar_t *scr_conspeed;
|
||||
convar_t *con_fontsize;
|
||||
convar_t *con_charset;
|
||||
convar_t *con_fontscale;
|
||||
convar_t *con_fontnum;
|
||||
convar_t *con_color;
|
||||
static CVAR_DEFINE_AUTO( scr_conspeed, "600", FCVAR_ARCHIVE, "console moving speed" );
|
||||
static CVAR_DEFINE_AUTO( con_notifytime, "3", FCVAR_ARCHIVE, "notify time to live" );
|
||||
CVAR_DEFINE_AUTO( con_fontsize, "1", FCVAR_ARCHIVE, "console font number (0, 1 or 2)" );
|
||||
static CVAR_DEFINE_AUTO( con_charset, "cp1251", FCVAR_ARCHIVE, "console font charset (only cp1251 supported now)" );
|
||||
static CVAR_DEFINE_AUTO( con_fontscale, "1.0", FCVAR_ARCHIVE, "scale font texture" );
|
||||
static CVAR_DEFINE_AUTO( con_fontnum, "-1", FCVAR_ARCHIVE, "console font number (0, 1 or 2), -1 for autoselect" );
|
||||
static CVAR_DEFINE_AUTO( con_color, "240 180 24", FCVAR_ARCHIVE, "set a custom console color" );
|
||||
|
||||
|
||||
static int g_codepage = 0;
|
||||
static qboolean g_utf8 = false;
|
||||
|
@ -116,7 +117,7 @@ typedef struct
|
|||
|
||||
// console fonts
|
||||
cl_font_t chars[CON_NUMFONTS];// fonts.wad/font1.fnt
|
||||
cl_font_t *curFont, *lastUsedFont;
|
||||
cl_font_t *curFont;
|
||||
|
||||
// console input
|
||||
field_t input;
|
||||
|
@ -162,14 +163,13 @@ Con_SetColor
|
|||
*/
|
||||
static void Con_SetColor( void )
|
||||
{
|
||||
vec3_t color;
|
||||
int r, g, b;
|
||||
int num;
|
||||
|
||||
if( !FBitSet( con_color->flags, FCVAR_CHANGED ))
|
||||
if( !FBitSet( con_color.flags, FCVAR_CHANGED ))
|
||||
return;
|
||||
|
||||
num = sscanf( con_color->string, "%i %i %i", &r, &g, &b );
|
||||
num = sscanf( con_color.string, "%i %i %i", &r, &g, &b );
|
||||
|
||||
switch( num )
|
||||
{
|
||||
|
@ -180,11 +180,11 @@ static void Con_SetColor( void )
|
|||
Con_DefaultColor( r, g, b );
|
||||
break;
|
||||
default:
|
||||
Cvar_DirectSet( con_color, con_color->def_string );
|
||||
Cvar_DirectSet( &con_color, con_color.def_string );
|
||||
break;
|
||||
}
|
||||
|
||||
ClearBits( con_color->flags, FCVAR_CHANGED );
|
||||
ClearBits( con_color.flags, FCVAR_CHANGED );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -213,37 +213,6 @@ void Con_ClearTyping( void )
|
|||
Cmd_AutoCompleteClear();
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
Con_StringLength
|
||||
|
||||
skipped color prefixes
|
||||
============
|
||||
*/
|
||||
int Con_StringLength( const char *string )
|
||||
{
|
||||
int len;
|
||||
const char *p;
|
||||
|
||||
if( !string ) return 0;
|
||||
|
||||
len = 0;
|
||||
p = string;
|
||||
|
||||
while( *p )
|
||||
{
|
||||
if( IsColorString( p ))
|
||||
{
|
||||
p += 2;
|
||||
continue;
|
||||
}
|
||||
len++;
|
||||
p++;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
Con_MessageMode_f
|
||||
|
@ -555,89 +524,9 @@ Con_FixedFont
|
|||
*/
|
||||
qboolean Con_FixedFont( void )
|
||||
{
|
||||
if( con.curFont && con.curFont->valid && con.curFont->type == FONT_FIXED )
|
||||
return true;
|
||||
return false;
|
||||
return CL_FixedFont( con.curFont );
|
||||
}
|
||||
|
||||
static qboolean Con_LoadFixedWidthFont( const char *fontname, cl_font_t *font )
|
||||
{
|
||||
int i, fontWidth;
|
||||
|
||||
if( font->valid )
|
||||
return true; // already loaded
|
||||
|
||||
if( !FS_FileExists( fontname, false ))
|
||||
return false;
|
||||
|
||||
// keep source to print directly into conback image
|
||||
font->hFontTexture = ref.dllFuncs.GL_LoadTexture( fontname, NULL, 0, TF_FONT|TF_KEEP_SOURCE );
|
||||
R_GetTextureParms( &fontWidth, NULL, font->hFontTexture );
|
||||
|
||||
if( font->hFontTexture && fontWidth != 0 )
|
||||
{
|
||||
font->charHeight = fontWidth / 16 * con_fontscale->value;
|
||||
font->type = FONT_FIXED;
|
||||
|
||||
// build fixed rectangles
|
||||
for( i = 0; i < 256; i++ )
|
||||
{
|
||||
font->fontRc[i].left = (i * (fontWidth / 16)) % fontWidth;
|
||||
font->fontRc[i].right = font->fontRc[i].left + fontWidth / 16;
|
||||
font->fontRc[i].top = (i / 16) * (fontWidth / 16);
|
||||
font->fontRc[i].bottom = font->fontRc[i].top + fontWidth / 16;
|
||||
font->charWidths[i] = fontWidth / 16 * con_fontscale->value;
|
||||
}
|
||||
font->valid = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static qboolean Con_LoadVariableWidthFont( const char *fontname, cl_font_t *font )
|
||||
{
|
||||
int i, fontWidth;
|
||||
byte *buffer;
|
||||
fs_offset_t length;
|
||||
qfont_t *src;
|
||||
|
||||
if( font->valid )
|
||||
return true; // already loaded
|
||||
|
||||
if( !FS_FileExists( fontname, false ))
|
||||
return false;
|
||||
|
||||
font->hFontTexture = ref.dllFuncs.GL_LoadTexture( fontname, NULL, 0, TF_FONT|TF_NEAREST );
|
||||
R_GetTextureParms( &fontWidth, NULL, font->hFontTexture );
|
||||
|
||||
// setup consolefont
|
||||
if( font->hFontTexture && fontWidth != 0 )
|
||||
{
|
||||
// half-life font with variable chars witdh
|
||||
buffer = FS_LoadFile( fontname, &length, false );
|
||||
|
||||
if( buffer && length >= sizeof( qfont_t ))
|
||||
{
|
||||
src = (qfont_t *)buffer;
|
||||
font->charHeight = src->rowheight * con_fontscale->value;
|
||||
font->type = FONT_VARIABLE;
|
||||
|
||||
// build rectangles
|
||||
for( i = 0; i < 256; i++ )
|
||||
{
|
||||
font->fontRc[i].left = (word)src->fontinfo[i].startoffset % fontWidth;
|
||||
font->fontRc[i].right = font->fontRc[i].left + src->fontinfo[i].charwidth;
|
||||
font->fontRc[i].top = (word)src->fontinfo[i].startoffset / fontWidth;
|
||||
font->fontRc[i].bottom = font->fontRc[i].top + src->rowheight;
|
||||
font->charWidths[i] = src->fontinfo[i].charwidth * con_fontscale->value;
|
||||
}
|
||||
font->valid = true;
|
||||
}
|
||||
if( buffer ) Mem_Free( buffer );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
|
@ -648,32 +537,46 @@ INTERNAL RESOURCE
|
|||
*/
|
||||
static void Con_LoadConsoleFont( int fontNumber, cl_font_t *font )
|
||||
{
|
||||
const char *path = NULL;
|
||||
dword crc = 0;
|
||||
qboolean success = false;
|
||||
float scale = con_fontscale.value;
|
||||
|
||||
if( font->valid ) return; // already loaded
|
||||
|
||||
// replace default fonts.wad textures by current charset's font
|
||||
if( !CRC32_File( &crc, "fonts.wad" ) || crc == 0x3c0a0029 )
|
||||
{
|
||||
const char *path2 = va("font%i_%s.fnt", fontNumber, Cvar_VariableString( "con_charset" ) );
|
||||
if( FS_FileExists( path2, false ) )
|
||||
path = path2;
|
||||
}
|
||||
if( font->valid )
|
||||
return; // already loaded
|
||||
|
||||
// loading conchars
|
||||
if( Sys_CheckParm( "-oldfont" ))
|
||||
Con_LoadVariableWidthFont( "gfx/conchars.fnt", font );
|
||||
{
|
||||
success = Con_LoadVariableWidthFont( "gfx/conchars.fnt", font, scale, kRenderTransTexture, TF_FONT|TF_NEAREST );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !path )
|
||||
path = va( "fonts/font%i", fontNumber );
|
||||
string path;
|
||||
dword crc = 0;
|
||||
|
||||
Con_LoadVariableWidthFont( path, font );
|
||||
// replace default fonts.wad textures by current charset's font
|
||||
if( !CRC32_File( &crc, "fonts.wad" ) || crc == 0x3c0a0029 )
|
||||
{
|
||||
if( Q_snprintf( path, sizeof( path ),
|
||||
"font%i_%s.fnt", fontNumber, Cvar_VariableString( "con_charset" )) > 0 )
|
||||
{
|
||||
success = Con_LoadVariableWidthFont( path, font, scale, kRenderTransTexture, TF_FONT|TF_NEAREST );
|
||||
}
|
||||
}
|
||||
|
||||
if( !success )
|
||||
{
|
||||
Q_snprintf( path, sizeof( path ), "fonts/font%i", fontNumber );
|
||||
success = Con_LoadVariableWidthFont( path, font, scale, kRenderTransTexture, TF_FONT|TF_NEAREST );
|
||||
}
|
||||
}
|
||||
|
||||
// quake fixed font as fallback
|
||||
if( !font->valid ) Con_LoadFixedWidthFont( "gfx/conchars", font );
|
||||
if( !success )
|
||||
{
|
||||
// quake fixed font as fallback
|
||||
// keep source to print directly into conback image
|
||||
if( !Con_LoadFixedWidthFont( "gfx/conchars", font, scale, kRenderTransTexture, TF_FONT|TF_KEEP_SOURCE ))
|
||||
Con_DPrintf( S_ERROR "failed to load console font\n" );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -690,8 +593,8 @@ static void Con_LoadConchars( void )
|
|||
Con_LoadConsoleFont( i, con.chars + i );
|
||||
|
||||
// select properly fontsize
|
||||
if( con_fontnum->value >= 0 && con_fontnum->value <= CON_NUMFONTS - 1 )
|
||||
fontSize = con_fontnum->value;
|
||||
if( con_fontnum.value >= 0 && con_fontnum.value <= CON_NUMFONTS - 1 )
|
||||
fontSize = con_fontnum.value;
|
||||
else if( refState.width <= 640 )
|
||||
fontSize = 0;
|
||||
else if( refState.width >= 1280 )
|
||||
|
@ -702,7 +605,7 @@ static void Con_LoadConchars( void )
|
|||
fontSize = CON_NUMFONTS - 1;
|
||||
|
||||
// sets the current font
|
||||
con.lastUsedFont = con.curFont = &con.chars[fontSize];
|
||||
con.curFont = &con.chars[fontSize];
|
||||
}
|
||||
|
||||
// CP1251 table
|
||||
|
@ -875,129 +778,25 @@ static void Con_DrawCharToConback( int num, const byte *conchars, byte *dest )
|
|||
|
||||
/*
|
||||
====================
|
||||
Con_TextAdjustSize
|
||||
Con_GetFont
|
||||
|
||||
draw charcters routine
|
||||
====================
|
||||
*/
|
||||
static void Con_TextAdjustSize( int *x, int *y, int *w, int *h )
|
||||
cl_font_t *Con_GetFont( int num )
|
||||
{
|
||||
float xscale, yscale;
|
||||
|
||||
if( !x && !y && !w && !h ) return;
|
||||
|
||||
// scale for screen sizes
|
||||
xscale = (float)refState.width / (float)clgame.scrInfo.iWidth;
|
||||
yscale = (float)refState.height / (float)clgame.scrInfo.iHeight;
|
||||
|
||||
if( x ) *x *= xscale;
|
||||
if( y ) *y *= yscale;
|
||||
if( w ) *w *= xscale;
|
||||
if( h ) *h *= yscale;
|
||||
num = bound( 0, num, CON_NUMFONTS - 1 );
|
||||
return &con.chars[num];
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
Con_DrawGenericChar
|
||||
Con_GetCurFont
|
||||
|
||||
draw console single character
|
||||
====================
|
||||
*/
|
||||
static int Con_DrawGenericChar( int x, int y, int number, rgba_t color )
|
||||
cl_font_t *Con_GetCurFont( void )
|
||||
{
|
||||
int width, height;
|
||||
float s1, t1, s2, t2;
|
||||
wrect_t *rc;
|
||||
|
||||
number &= 255;
|
||||
|
||||
if( !con.curFont || !con.curFont->valid )
|
||||
return 0;
|
||||
|
||||
number = Con_UtfProcessChar(number);
|
||||
if( !number )
|
||||
return 0;
|
||||
|
||||
if( y < -con.curFont->charHeight )
|
||||
return 0;
|
||||
|
||||
rc = &con.curFont->fontRc[number];
|
||||
R_GetTextureParms( &width, &height, con.curFont->hFontTexture );
|
||||
|
||||
if( !width || !height )
|
||||
return con.curFont->charWidths[number];
|
||||
|
||||
// don't apply color to fixed fonts it's already colored
|
||||
if( con.curFont->type != FONT_FIXED || REF_GET_PARM( PARM_TEX_GLFORMAT, con.curFont->hFontTexture ) == 0x8045 ) // GL_LUMINANCE8_ALPHA8
|
||||
ref.dllFuncs.Color4ub( color[0], color[1], color[2], color[3] );
|
||||
else ref.dllFuncs.Color4ub( 255, 255, 255, color[3] );
|
||||
|
||||
// calc rectangle
|
||||
s1 = (float)rc->left / width;
|
||||
t1 = (float)rc->top / height;
|
||||
s2 = (float)rc->right / width;
|
||||
t2 = (float)rc->bottom / height;
|
||||
width = ( rc->right - rc->left ) * con_fontscale->value;
|
||||
height = ( rc->bottom - rc->top ) * con_fontscale->value;
|
||||
|
||||
if( clgame.ds.adjust_size )
|
||||
Con_TextAdjustSize( &x, &y, &width, &height );
|
||||
ref.dllFuncs.R_DrawStretchPic( x, y, width, height, s1, t1, s2, t2, con.curFont->hFontTexture );
|
||||
ref.dllFuncs.Color4ub( 255, 255, 255, 255 ); // don't forget reset color
|
||||
|
||||
return con.curFont->charWidths[number];
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
Con_SetFont
|
||||
|
||||
choose font size
|
||||
====================
|
||||
*/
|
||||
void Con_SetFont( int fontNum )
|
||||
{
|
||||
fontNum = bound( 0, fontNum, CON_NUMFONTS - 1 );
|
||||
con.curFont = &con.chars[fontNum];
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
Con_RestoreFont
|
||||
|
||||
restore auto-selected console font
|
||||
(that based on screen resolution)
|
||||
====================
|
||||
*/
|
||||
void Con_RestoreFont( void )
|
||||
{
|
||||
con.curFont = con.lastUsedFont;
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
Con_DrawCharacter
|
||||
|
||||
client version of routine
|
||||
====================
|
||||
*/
|
||||
int Con_DrawCharacter( int x, int y, int number, rgba_t color )
|
||||
{
|
||||
ref.dllFuncs.GL_SetRenderMode( kRenderTransTexture );
|
||||
return Con_DrawGenericChar( x, y, number, color );
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
Con_DrawCharacterLen
|
||||
|
||||
returns character sizes in screen pixels
|
||||
====================
|
||||
*/
|
||||
void Con_DrawCharacterLen( int number, int *width, int *height )
|
||||
{
|
||||
if( width && con.curFont ) *width = con.curFont->charWidths[number];
|
||||
if( height && con.curFont ) *height = con.curFont->charHeight;
|
||||
return con.curFont;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1009,105 +808,7 @@ compute string width and height in screen pixels
|
|||
*/
|
||||
void GAME_EXPORT Con_DrawStringLen( const char *pText, int *length, int *height )
|
||||
{
|
||||
int curLength = 0;
|
||||
|
||||
if( !con.curFont )
|
||||
return;
|
||||
if( height )
|
||||
*height = con.curFont->charHeight;
|
||||
if (!length)
|
||||
return;
|
||||
|
||||
*length = 0;
|
||||
|
||||
while( *pText )
|
||||
{
|
||||
byte c = *pText;
|
||||
|
||||
if( *pText == '\n' )
|
||||
{
|
||||
pText++;
|
||||
curLength = 0;
|
||||
}
|
||||
|
||||
// skip color strings they are not drawing
|
||||
if( IsColorString( pText ))
|
||||
{
|
||||
pText += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// Convert to unicode
|
||||
c = Con_UtfProcessChar( c );
|
||||
|
||||
if( c )
|
||||
curLength += con.curFont->charWidths[c];
|
||||
|
||||
pText++;
|
||||
|
||||
if( curLength > *length )
|
||||
*length = curLength;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
Con_DrawString
|
||||
|
||||
Draws a multi-colored string, optionally forcing
|
||||
to a fixed color.
|
||||
==================
|
||||
*/
|
||||
int Con_DrawGenericString( int x, int y, const char *string, rgba_t setColor, qboolean forceColor, int hideChar )
|
||||
{
|
||||
rgba_t color;
|
||||
int drawLen = 0;
|
||||
int numDraws = 0;
|
||||
const char *s;
|
||||
|
||||
if( !con.curFont ) return 0; // no font set
|
||||
|
||||
Con_UtfProcessChar( 0 );
|
||||
|
||||
// draw the colored text
|
||||
memcpy( color, setColor, sizeof( color ));
|
||||
s = string;
|
||||
|
||||
while( *s )
|
||||
{
|
||||
if( *s == '\n' )
|
||||
{
|
||||
s++;
|
||||
if( !*s ) break; // at end the string
|
||||
drawLen = 0; // begin new row
|
||||
y += con.curFont->charHeight;
|
||||
}
|
||||
|
||||
if( IsColorString( s ))
|
||||
{
|
||||
if( !forceColor )
|
||||
{
|
||||
memcpy( color, g_color_table[ColorIndex(*(s+1))], sizeof( color ));
|
||||
color[3] = setColor[3];
|
||||
}
|
||||
|
||||
s += 2;
|
||||
numDraws++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// hide char for overstrike mode
|
||||
if( hideChar == numDraws )
|
||||
drawLen += con.curFont->charWidths[*s];
|
||||
else drawLen += Con_DrawCharacter( x + drawLen, y, *s, color );
|
||||
|
||||
numDraws++;
|
||||
s++;
|
||||
}
|
||||
|
||||
ref.dllFuncs.Color4ub( 255, 255, 255, 255 );
|
||||
return drawLen;
|
||||
CL_DrawStringLen( con.curFont, pText, length, height, FONT_DRAW_UTF8 );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1119,10 +820,9 @@ client version of routine
|
|||
*/
|
||||
int Con_DrawString( int x, int y, const char *string, rgba_t setColor )
|
||||
{
|
||||
return Con_DrawGenericString( x, y, string, setColor, false, -1 );
|
||||
return CL_DrawString( x, y, string, setColor, con.curFont, FONT_DRAW_UTF8 );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
Con_Init
|
||||
|
@ -1130,19 +830,17 @@ Con_Init
|
|||
*/
|
||||
void Con_Init( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
if( host.type == HOST_DEDICATED )
|
||||
return; // dedicated server already have console
|
||||
|
||||
// must be init before startup video subsystem
|
||||
scr_conspeed = Cvar_Get( "scr_conspeed", "600", FCVAR_ARCHIVE, "console moving speed" );
|
||||
con_notifytime = Cvar_Get( "con_notifytime", "3", FCVAR_ARCHIVE, "notify time to live" );
|
||||
con_fontsize = Cvar_Get( "con_fontsize", "1", FCVAR_ARCHIVE, "console font number (0, 1 or 2)" );
|
||||
con_charset = Cvar_Get( "con_charset", "cp1251", FCVAR_ARCHIVE, "console font charset (only cp1251 supported now)" );
|
||||
con_fontscale = Cvar_Get( "con_fontscale", "1.0", FCVAR_ARCHIVE, "scale font texture" );
|
||||
con_fontnum = Cvar_Get( "con_fontnum", "-1", FCVAR_ARCHIVE, "console font number (0, 1 or 2), -1 for autoselect" );
|
||||
con_color = Cvar_Get( "con_color", "240 180 24", FCVAR_ARCHIVE, "set a custom console color" );
|
||||
Cvar_RegisterVariable( &scr_conspeed );
|
||||
Cvar_RegisterVariable( &con_notifytime );
|
||||
Cvar_RegisterVariable( &con_fontsize );
|
||||
Cvar_RegisterVariable( &con_charset );
|
||||
Cvar_RegisterVariable( &con_fontscale );
|
||||
Cvar_RegisterVariable( &con_fontnum );
|
||||
Cvar_RegisterVariable( &con_color );
|
||||
|
||||
// init the console buffer
|
||||
con.bufsize = CON_TEXTSIZE;
|
||||
|
@ -1499,7 +1197,7 @@ void Field_KeyDownEvent( field_t *edit, int key )
|
|||
return;
|
||||
}
|
||||
|
||||
if( key == K_BACKSPACE )
|
||||
if( key == K_BACKSPACE || key == K_X_BUTTON )
|
||||
{
|
||||
if( edit->cursor > 0 )
|
||||
{
|
||||
|
@ -1511,7 +1209,7 @@ void Field_KeyDownEvent( field_t *edit, int key )
|
|||
return;
|
||||
}
|
||||
|
||||
if( key == K_RIGHTARROW )
|
||||
if( key == K_RIGHTARROW || key == K_DPAD_RIGHT )
|
||||
{
|
||||
if( edit->cursor < len ) edit->cursor = Con_UtfMoveRight( edit->buffer, edit->cursor, edit->widthInChars );
|
||||
if( edit->cursor >= edit->scroll + edit->widthInChars && edit->cursor <= len )
|
||||
|
@ -1519,7 +1217,7 @@ void Field_KeyDownEvent( field_t *edit, int key )
|
|||
return;
|
||||
}
|
||||
|
||||
if( key == K_LEFTARROW )
|
||||
if( key == K_LEFTARROW || key == K_DPAD_LEFT )
|
||||
{
|
||||
if( edit->cursor > 0 ) edit->cursor = Con_UtfMoveLeft( edit->buffer, edit->cursor );
|
||||
if( edit->cursor < edit->scroll ) edit->scroll--;
|
||||
|
@ -1614,7 +1312,7 @@ Field_DrawInputLine
|
|||
void Field_DrawInputLine( int x, int y, field_t *edit )
|
||||
{
|
||||
int len, cursorChar;
|
||||
int drawLen, hideChar = -1;
|
||||
int drawLen;
|
||||
int prestep, curPos;
|
||||
char str[MAX_SYSPATH];
|
||||
byte *colorDefault;
|
||||
|
@ -1651,35 +1349,23 @@ void Field_DrawInputLine( int x, int y, field_t *edit )
|
|||
// save char for overstrike
|
||||
cursorChar = str[edit->cursor - prestep];
|
||||
|
||||
if( host.key_overstrike && cursorChar && !((int)( host.realtime * 4 ) & 1 ))
|
||||
hideChar = edit->cursor - prestep; // skip this char
|
||||
|
||||
// draw it
|
||||
Con_DrawGenericString( x, y, str, colorDefault, false, hideChar );
|
||||
CL_DrawString( x, y, str, colorDefault, con.curFont, FONT_DRAW_UTF8 );
|
||||
|
||||
// draw the cursor
|
||||
if((int)( host.realtime * 4 ) & 1 ) return; // off blink
|
||||
|
||||
// calc cursor position
|
||||
str[edit->cursor - prestep] = 0;
|
||||
Con_DrawStringLen( str, &curPos, NULL );
|
||||
Con_UtfProcessChar( 0 );
|
||||
CL_DrawStringLen( con.curFont, str, &curPos, NULL, FONT_DRAW_UTF8 );
|
||||
|
||||
if( host.key_overstrike && cursorChar )
|
||||
if( host.key_overstrike )
|
||||
{
|
||||
// overstrike cursor
|
||||
#if 0
|
||||
pglEnable( GL_BLEND );
|
||||
pglDisable( GL_ALPHA_TEST );
|
||||
pglBlendFunc( GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA );
|
||||
pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||
#endif
|
||||
Con_DrawGenericChar( x + curPos, y, cursorChar, colorDefault );
|
||||
CL_DrawCharacter( x + curPos, y, '|', colorDefault, con.curFont, 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
Con_UtfProcessChar( 0 );
|
||||
Con_DrawCharacter( x + curPos, y, '_', colorDefault );
|
||||
CL_DrawCharacter( x + curPos, y, '_', colorDefault, con.curFont, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1793,6 +1479,10 @@ static void Con_SaveHistory( con_history_t *self )
|
|||
int historyStart = self->next - CON_HISTORY, i;
|
||||
file_t *f;
|
||||
|
||||
// do not save history if nothing was executed
|
||||
if( self->next == 0 )
|
||||
return;
|
||||
|
||||
if( historyStart < 0 )
|
||||
historyStart = 0;
|
||||
|
||||
|
@ -1828,8 +1518,8 @@ void Key_Console( int key )
|
|||
return;
|
||||
}
|
||||
|
||||
// enter finishes the line
|
||||
if( key == K_ENTER || key == K_KP_ENTER )
|
||||
// enter or A finish the line
|
||||
if( key == K_ENTER || key == K_KP_ENTER || key == K_A_BUTTON )
|
||||
{
|
||||
// backslash text are commands, else chat
|
||||
if( con.input.buffer[0] == '\\' || con.input.buffer[0] == '/' )
|
||||
|
@ -1856,7 +1546,7 @@ void Key_Console( int key )
|
|||
}
|
||||
|
||||
// command completion
|
||||
if( key == K_TAB )
|
||||
if( key == K_TAB || key == K_L2_BUTTON )
|
||||
{
|
||||
Con_CompleteCommand( &con.input );
|
||||
Con_Bottom();
|
||||
|
@ -1877,13 +1567,13 @@ void Key_Console( int key )
|
|||
}
|
||||
|
||||
// console scrolling
|
||||
if( key == K_PGUP )
|
||||
if( key == K_PGUP || key == K_DPAD_UP )
|
||||
{
|
||||
Con_PageUp( 1 );
|
||||
return;
|
||||
}
|
||||
|
||||
if( key == K_PGDN )
|
||||
if( key == K_PGDN || key == K_DPAD_DOWN )
|
||||
{
|
||||
Con_PageDown( 1 );
|
||||
return;
|
||||
|
@ -1919,6 +1609,23 @@ void Key_Console( int key )
|
|||
return;
|
||||
}
|
||||
|
||||
// enable the OSK with button press
|
||||
if( key == K_Y_BUTTON )
|
||||
{
|
||||
Key_EnableTextInput( true, true );
|
||||
return;
|
||||
}
|
||||
|
||||
// exit the console by pressing MINUS on NSwitch
|
||||
// or both Back(Select)/Start buttons for everyone else
|
||||
if( key == K_BACK_BUTTON || key == K_START_BUTTON )
|
||||
{
|
||||
if( cls.state == ca_active && !cl.background )
|
||||
Key_SetKeyDest( key_game );
|
||||
else UI_SetActiveMenu( true );
|
||||
return;
|
||||
}
|
||||
|
||||
// pass to the normal editline routine
|
||||
Field_KeyDownEvent( &con.input, key );
|
||||
}
|
||||
|
@ -1934,14 +1641,14 @@ void Key_Message( int key )
|
|||
{
|
||||
char buffer[MAX_SYSPATH];
|
||||
|
||||
if( key == K_ESCAPE )
|
||||
if( key == K_ESCAPE || key == K_BACK_BUTTON )
|
||||
{
|
||||
Key_SetKeyDest( key_game );
|
||||
Con_ClearField( &con.chat );
|
||||
return;
|
||||
}
|
||||
|
||||
if( key == K_ENTER || key == K_KP_ENTER )
|
||||
if( key == K_ENTER || key == K_KP_ENTER || key == K_A_BUTTON )
|
||||
{
|
||||
if( con.chat.buffer[0] && cls.state == ca_active )
|
||||
{
|
||||
|
@ -1983,7 +1690,7 @@ void Con_DrawInput( int lines )
|
|||
return;
|
||||
|
||||
y = lines - ( con.curFont->charHeight * 2 );
|
||||
Con_DrawCharacter( con.curFont->charWidths[' '], y, ']', g_color_table[7] );
|
||||
CL_DrawCharacter( con.curFont->charWidths[' '], y, ']', g_color_table[7], con.curFont, 0 );
|
||||
Field_DrawInputLine( con.curFont->charWidths[' ']*2, y, &con.input );
|
||||
}
|
||||
|
||||
|
@ -1996,30 +1703,37 @@ Custom debug messages
|
|||
*/
|
||||
int Con_DrawDebugLines( void )
|
||||
{
|
||||
notify_t *notify = con.notify;
|
||||
int i, count = 0;
|
||||
int defaultX;
|
||||
int y = 20;
|
||||
int fontTall;
|
||||
|
||||
if( !con.curFont || !con.curFont->valid )
|
||||
return 0;
|
||||
|
||||
defaultX = refState.width / 4;
|
||||
fontTall = con.curFont->charHeight + 1;
|
||||
|
||||
for( i = 0; i < MAX_DBG_NOTIFY; i++ )
|
||||
for( i = 0; i < ARRAYSIZE( con.notify ); i++, notify++ )
|
||||
{
|
||||
if( host.realtime < con.notify[i].expire && con.notify[i].key_dest == cls.key_dest )
|
||||
{
|
||||
int x, len;
|
||||
int fontTall = 0;
|
||||
int x, len;
|
||||
|
||||
Con_DrawStringLen( con.notify[i].szNotify, &len, &fontTall );
|
||||
x = refState.width - Q_max( defaultX, len ) - 10;
|
||||
fontTall += 1;
|
||||
if( host.realtime > notify->expire )
|
||||
continue;
|
||||
|
||||
if( y + fontTall > refState.height - 20 )
|
||||
return count;
|
||||
if( notify->key_dest != cls.key_dest )
|
||||
continue;
|
||||
|
||||
count++;
|
||||
y = 20 + fontTall * i;
|
||||
Con_DrawString( x, y, con.notify[i].szNotify, con.notify[i].color );
|
||||
}
|
||||
Con_DrawStringLen( notify->szNotify, &len, NULL );
|
||||
x = refState.width - Q_max( defaultX, len ) - 10;
|
||||
|
||||
if( y + fontTall > refState.height - 20 )
|
||||
return count;
|
||||
|
||||
count++;
|
||||
y += fontTall;
|
||||
CL_DrawString( x, y, notify->szNotify, notify->color, con.curFont, FONT_DRAW_UTF8 | FONT_DRAW_NOLF );
|
||||
}
|
||||
|
||||
return count;
|
||||
|
@ -2038,20 +1752,24 @@ void Con_DrawDebug( void )
|
|||
string dlstring;
|
||||
int x, y;
|
||||
|
||||
if( scr_download->value != -1.0f )
|
||||
if( scr_download.value != -1.0f )
|
||||
{
|
||||
int length;
|
||||
Q_snprintf( dlstring, sizeof( dlstring ), "Downloading [%d remaining]: ^2%s^7 %5.1f%% time %.f secs",
|
||||
host.downloadcount, host.downloadfile, scr_download->value, Sys_DoubleTime() - timeStart );
|
||||
x = refState.width - 500;
|
||||
host.downloadcount, host.downloadfile, scr_download.value, Sys_DoubleTime() - timeStart );
|
||||
|
||||
Con_DrawStringLen( dlstring, &length, NULL );
|
||||
length = Q_max( length, 500 );
|
||||
x = refState.width - length * 1.05f;
|
||||
y = con.curFont->charHeight * 1.05f;
|
||||
Con_DrawString( x, y, dlstring, g_color_table[7] );
|
||||
}
|
||||
else
|
||||
{
|
||||
timeStart = Sys_DoubleTime();
|
||||
timeStart = host.realtime;
|
||||
}
|
||||
|
||||
if( !host_developer.value || Cvar_VariableInteger( "cl_background" ) || Cvar_VariableInteger( "sv_background" ))
|
||||
if( !host.allow_console || Cvar_VariableInteger( "cl_background" ) || Cvar_VariableInteger( "sv_background" ))
|
||||
return;
|
||||
|
||||
if( con.draw_notify && !Con_Visible( ))
|
||||
|
@ -2077,13 +1795,13 @@ void Con_DrawNotify( void )
|
|||
|
||||
x = con.curFont->charWidths[' ']; // offset one space at left screen side
|
||||
|
||||
if( host_developer.value && ( !Cvar_VariableInteger( "cl_background" ) && !Cvar_VariableInteger( "sv_background" )))
|
||||
if( host.allow_console && ( !Cvar_VariableInteger( "cl_background" ) && !Cvar_VariableInteger( "sv_background" )))
|
||||
{
|
||||
for( i = CON_LINES_COUNT - con.num_times; i < CON_LINES_COUNT; i++ )
|
||||
{
|
||||
con_lineinfo_t *l = &CON_LINES( i );
|
||||
|
||||
if( l->addtime < ( time - con_notifytime->value ))
|
||||
if( l->addtime < ( time - con_notifytime.value ))
|
||||
continue;
|
||||
|
||||
Con_DrawString( x, y, l->start, g_color_table[7] );
|
||||
|
@ -2128,7 +1846,11 @@ int Con_DrawConsoleLine( int y, int lineno )
|
|||
return 0; // this string will be shown only at notify
|
||||
|
||||
if( y >= con.curFont->charHeight )
|
||||
Con_DrawGenericString( con.curFont->charWidths[' '], y, li->start, g_color_table[7], false, -1 );
|
||||
{
|
||||
float x = con.curFont->charWidths[' '];
|
||||
|
||||
CL_DrawString( x, y, li->start, g_color_table[7], con.curFont, FONT_DRAW_UTF8 );
|
||||
}
|
||||
|
||||
return con.curFont->charHeight;
|
||||
}
|
||||
|
@ -2195,17 +1917,15 @@ void Con_DrawSolidConsole( int lines )
|
|||
// draw current version
|
||||
memcpy( color, g_color_table[7], sizeof( color ));
|
||||
|
||||
Q_snprintf( curbuild, MAX_STRING, "%s %i/%s (%s-%s build %i)", XASH_ENGINE_NAME, PROTOCOL_VERSION, XASH_VERSION, Q_buildos(), Q_buildarch(), Q_buildnum( ));
|
||||
Q_snprintf( curbuild, MAX_STRING, XASH_ENGINE_NAME " %i/" XASH_VERSION " (%s-%s build %i)", PROTOCOL_VERSION, Q_buildos(), Q_buildarch(), Q_buildnum( ));
|
||||
|
||||
Con_DrawStringLen( curbuild, &stringLen, &charH );
|
||||
start = refState.width - stringLen;
|
||||
stringLen = Con_StringLength( curbuild );
|
||||
|
||||
start = refState.width - stringLen;
|
||||
fraction = lines / (float)refState.height;
|
||||
color[3] = Q_min( fraction * 2.0f, 1.0f ) * 255; // fadeout version number
|
||||
|
||||
for( i = 0; i < stringLen; i++ )
|
||||
width += Con_DrawCharacter( start + width, 0, curbuild[i], color );
|
||||
Con_DrawString( start, 0, curbuild, color );
|
||||
|
||||
// draw the text
|
||||
if( CON_LINES_COUNT > 0 )
|
||||
|
@ -2222,7 +1942,7 @@ void Con_DrawSolidConsole( int lines )
|
|||
|
||||
// draw red arrows to show the buffer is backscrolled
|
||||
for( x = 0; x < con.linewidth; x += 4 )
|
||||
Con_DrawCharacter(( x + 1 ) * start, y, '^', g_color_table[1] );
|
||||
CL_DrawCharacter( ( x + 1 ) * start, y, '^', g_color_table[1], con.curFont, 0 );
|
||||
y -= con.curFont->charHeight;
|
||||
}
|
||||
x = lastline;
|
||||
|
@ -2263,7 +1983,7 @@ void Con_DrawConsole( void )
|
|||
|
||||
if( cls.state == ca_connecting || cls.state == ca_connected )
|
||||
{
|
||||
if( !cl_allow_levelshots->value )
|
||||
if( !cl_allow_levelshots.value && !cls.timedemo )
|
||||
{
|
||||
if(( Cvar_VariableInteger( "cl_background" ) || Cvar_VariableInteger( "sv_background" )) && cls.key_dest != key_console )
|
||||
con.vislines = con.showlines = 0;
|
||||
|
@ -2273,7 +1993,7 @@ void Con_DrawConsole( void )
|
|||
{
|
||||
con.showlines = 0;
|
||||
|
||||
if( host_developer.value >= DEV_EXTENDED )
|
||||
if( host_developer.value >= DEV_EXTENDED && !cls.timedemo )
|
||||
Con_DrawNotify(); // draw notify lines
|
||||
}
|
||||
}
|
||||
|
@ -2305,7 +2025,7 @@ void Con_DrawConsole( void )
|
|||
{
|
||||
if( con.vislines )
|
||||
Con_DrawSolidConsole( con.vislines );
|
||||
else if( cls.state == ca_active && ( cls.key_dest == key_game || cls.key_dest == key_message ))
|
||||
else if( cls.state == ca_active && ( cls.key_dest == key_game || cls.key_dest == key_message ) && !cls.timedemo )
|
||||
Con_DrawNotify(); // draw notify lines
|
||||
}
|
||||
break;
|
||||
|
@ -2325,7 +2045,7 @@ void Con_DrawVersion( void )
|
|||
{
|
||||
// draws the current build
|
||||
byte *color = g_color_table[7];
|
||||
int i, stringLen, width = 0, charH = 0;
|
||||
int stringLen, charH = 0;
|
||||
int start, height = refState.height;
|
||||
qboolean draw_version = false;
|
||||
string curbuild;
|
||||
|
@ -2338,26 +2058,21 @@ void Con_DrawVersion( void )
|
|||
break;
|
||||
}
|
||||
|
||||
if( !host.force_draw_version )
|
||||
{
|
||||
if(( cls.key_dest != key_menu && !draw_version ) || CL_IsDevOverviewMode() == 2 || net_graph->value )
|
||||
return;
|
||||
}
|
||||
|
||||
if( host.force_draw_version_time > host.realtime )
|
||||
host.force_draw_version = false;
|
||||
draw_version = true;
|
||||
|
||||
if( host.force_draw_version || draw_version )
|
||||
Q_snprintf( curbuild, MAX_STRING, "%s v%i/%s (%s-%s build %i)", XASH_ENGINE_NAME, PROTOCOL_VERSION, XASH_VERSION, Q_buildos(), Q_buildarch(), Q_buildnum( ));
|
||||
else Q_snprintf( curbuild, MAX_STRING, "v%i/%s (%s-%s build %i)", PROTOCOL_VERSION, XASH_VERSION, Q_buildos(), Q_buildarch(), Q_buildnum( ));
|
||||
if(( cls.key_dest != key_menu && !draw_version ) || CL_IsDevOverviewMode() == 2 || net_graph.value )
|
||||
return;
|
||||
|
||||
if( draw_version )
|
||||
Q_snprintf( curbuild, MAX_STRING, XASH_ENGINE_NAME " v%i/" XASH_VERSION " (%s-%s build %i)", PROTOCOL_VERSION, Q_buildos(), Q_buildarch(), Q_buildnum( ));
|
||||
else Q_snprintf( curbuild, MAX_STRING, "v%i/" XASH_VERSION " (%s-%s build %i)", PROTOCOL_VERSION, Q_buildos(), Q_buildarch(), Q_buildnum( ));
|
||||
|
||||
Con_DrawStringLen( curbuild, &stringLen, &charH );
|
||||
start = refState.width - stringLen * 1.05f;
|
||||
stringLen = Con_StringLength( curbuild );
|
||||
height -= charH * 1.05f;
|
||||
|
||||
for( i = 0; i < stringLen; i++ )
|
||||
width += Con_DrawCharacter( start + width, height, curbuild[i], color );
|
||||
Con_DrawString( start, height, curbuild, color );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2382,7 +2097,7 @@ void Con_RunConsole( void )
|
|||
}
|
||||
else con.showlines = 0; // none visible
|
||||
|
||||
lines_per_frame = fabs( scr_conspeed->value ) * host.realframetime;
|
||||
lines_per_frame = fabs( scr_conspeed.value ) * host.realframetime;
|
||||
|
||||
if( con.showlines < con.vislines )
|
||||
{
|
||||
|
@ -2397,28 +2112,35 @@ void Con_RunConsole( void )
|
|||
con.vislines = con.showlines;
|
||||
}
|
||||
|
||||
if( FBitSet( con_charset->flags, FCVAR_CHANGED ) ||
|
||||
FBitSet( con_fontscale->flags, FCVAR_CHANGED ) ||
|
||||
FBitSet( con_fontnum->flags, FCVAR_CHANGED ) ||
|
||||
FBitSet( cl_charset->flags, FCVAR_CHANGED ) )
|
||||
if( FBitSet( con_charset.flags, FCVAR_CHANGED ) ||
|
||||
FBitSet( con_fontscale.flags, FCVAR_CHANGED ) ||
|
||||
FBitSet( con_fontnum.flags, FCVAR_CHANGED ) ||
|
||||
FBitSet( cl_charset.flags, FCVAR_CHANGED ))
|
||||
{
|
||||
// update codepage parameters
|
||||
g_codepage = 0;
|
||||
if( !Q_stricmp( con_charset->string, "cp1251" ) )
|
||||
if( !Q_stricmp( con_charset.string, "cp1251" ))
|
||||
{
|
||||
g_codepage = 1251;
|
||||
else if( !Q_stricmp( con_charset->string, "cp1252" ) )
|
||||
}
|
||||
else if( !Q_stricmp( con_charset.string, "cp1252" ))
|
||||
{
|
||||
g_codepage = 1252;
|
||||
}
|
||||
else
|
||||
{
|
||||
Con_Printf( S_WARN "Unknown charset %s, defaulting to cp1252", con_charset.string );
|
||||
|
||||
g_utf8 = !Q_stricmp( cl_charset->string, "utf-8" );
|
||||
Cvar_DirectSet( &con_charset, "cp1252" );
|
||||
g_codepage = 1252;
|
||||
}
|
||||
|
||||
g_utf8 = !Q_stricmp( cl_charset.string, "utf-8" );
|
||||
Con_InvalidateFonts();
|
||||
Con_LoadConchars();
|
||||
cls.creditsFont.valid = false;
|
||||
SCR_LoadCreditsFont();
|
||||
ClearBits( con_charset->flags, FCVAR_CHANGED );
|
||||
ClearBits( con_fontnum->flags, FCVAR_CHANGED );
|
||||
ClearBits( con_fontscale->flags, FCVAR_CHANGED );
|
||||
ClearBits( cl_charset->flags, FCVAR_CHANGED );
|
||||
|
||||
ClearBits( con_charset.flags, FCVAR_CHANGED );
|
||||
ClearBits( con_fontnum.flags, FCVAR_CHANGED );
|
||||
ClearBits( con_fontscale.flags, FCVAR_CHANGED );
|
||||
ClearBits( cl_charset.flags, FCVAR_CHANGED );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2553,8 +2275,10 @@ Con_InvalidateFonts
|
|||
*/
|
||||
void Con_InvalidateFonts( void )
|
||||
{
|
||||
memset( con.chars, 0, sizeof( con.chars ));
|
||||
con.curFont = con.lastUsedFont = NULL;
|
||||
int i;
|
||||
for( i = 0; i < ARRAYSIZE( con.chars ); i++ )
|
||||
CL_FreeFont( &con.chars[i] );
|
||||
con.curFont = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -44,22 +44,25 @@ static struct joy_axis_s
|
|||
short prevval;
|
||||
} joyaxis[MAX_AXES] = { 0 };
|
||||
static byte currentbinding; // add posibility to remap keys, to place it in joykeys[]
|
||||
convar_t *joy_enable;
|
||||
static convar_t *joy_pitch;
|
||||
static convar_t *joy_yaw;
|
||||
static convar_t *joy_forward;
|
||||
static convar_t *joy_side;
|
||||
static convar_t *joy_found;
|
||||
static convar_t *joy_index;
|
||||
static convar_t *joy_lt_threshold;
|
||||
static convar_t *joy_rt_threshold;
|
||||
static convar_t *joy_side_deadzone;
|
||||
static convar_t *joy_forward_deadzone;
|
||||
static convar_t *joy_side_key_threshold;
|
||||
static convar_t *joy_forward_key_threshold;
|
||||
static convar_t *joy_pitch_deadzone;
|
||||
static convar_t *joy_yaw_deadzone;
|
||||
static convar_t *joy_axis_binding;
|
||||
static qboolean joy_initialized;
|
||||
|
||||
static CVAR_DEFINE_AUTO( joy_pitch, "100.0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "joystick pitch sensitivity" );
|
||||
static CVAR_DEFINE_AUTO( joy_yaw, "100.0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "joystick yaw sensitivity" );
|
||||
static CVAR_DEFINE_AUTO( joy_side, "1.0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "joystick side sensitivity. Values from -1.0 to 1.0" );
|
||||
static CVAR_DEFINE_AUTO( joy_forward, "1.0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "joystick forward sensitivity. Values from -1.0 to 1.0" );
|
||||
static CVAR_DEFINE_AUTO( joy_lt_threshold, "16384", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "left trigger threshold. Value from 0 to 32767");
|
||||
static CVAR_DEFINE_AUTO( joy_rt_threshold, "16384", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "right trigger threshold. Value from 0 to 32767" );
|
||||
static CVAR_DEFINE_AUTO( joy_side_key_threshold, "24576", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "side axis key event emit threshold. Value from 0 to 32767" );
|
||||
static CVAR_DEFINE_AUTO( joy_forward_key_threshold, "24576", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "forward axis key event emit threshold. Value from 0 to 32767");
|
||||
static CVAR_DEFINE_AUTO( joy_side_deadzone, DEFAULT_JOY_DEADZONE, FCVAR_ARCHIVE | FCVAR_FILTERABLE, "side axis deadzone. Value from 0 to 32767" );
|
||||
static CVAR_DEFINE_AUTO( joy_forward_deadzone, DEFAULT_JOY_DEADZONE, FCVAR_ARCHIVE | FCVAR_FILTERABLE, "forward axis deadzone. Value from 0 to 32767");
|
||||
static CVAR_DEFINE_AUTO( joy_pitch_deadzone, DEFAULT_JOY_DEADZONE, FCVAR_ARCHIVE | FCVAR_FILTERABLE, "pitch axis deadzone. Value from 0 to 32767");
|
||||
static CVAR_DEFINE_AUTO( joy_yaw_deadzone, DEFAULT_JOY_DEADZONE, FCVAR_ARCHIVE | FCVAR_FILTERABLE, "yaw axis deadzone. Value from 0 to 32767" );
|
||||
static CVAR_DEFINE_AUTO( joy_axis_binding, "sfpyrl", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "axis hardware id to engine inner axis binding, "
|
||||
"s - side, f - forward, y - yaw, p - pitch, r - left trigger, l - right trigger" );
|
||||
static CVAR_DEFINE_AUTO( joy_found, "0", FCVAR_READ_ONLY, "is joystick is connected" );
|
||||
static CVAR_DEFINE_AUTO( joy_index, "0", FCVAR_READ_ONLY, "current active joystick" );
|
||||
CVAR_DEFINE_AUTO( joy_enable, "1", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "enable joystick" );
|
||||
|
||||
/*
|
||||
============
|
||||
|
@ -68,7 +71,7 @@ Joy_IsActive
|
|||
*/
|
||||
qboolean Joy_IsActive( void )
|
||||
{
|
||||
return joy_found->value && joy_enable->value;
|
||||
return joy_found.value && joy_enable.value;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -93,7 +96,7 @@ void Joy_HatMotionEvent( byte hat, byte value )
|
|||
};
|
||||
int i;
|
||||
|
||||
if( !joy_found->value )
|
||||
if( !joy_found.value )
|
||||
return;
|
||||
|
||||
for( i = 0; i < ARRAYSIZE( keys ); i++ )
|
||||
|
@ -124,11 +127,11 @@ static void Joy_ProcessTrigger( const engineAxis_t engineAxis, short value )
|
|||
{
|
||||
case JOY_AXIS_RT:
|
||||
trigButton = K_JOY2;
|
||||
trigThreshold = joy_rt_threshold->value;
|
||||
trigThreshold = joy_rt_threshold.value;
|
||||
break;
|
||||
case JOY_AXIS_LT:
|
||||
trigButton = K_JOY1;
|
||||
trigThreshold = joy_lt_threshold->value;
|
||||
trigThreshold = joy_lt_threshold.value;
|
||||
break;
|
||||
default:
|
||||
Con_Reportf( S_ERROR "Joy_ProcessTrigger: invalid axis = %i", engineAxis );
|
||||
|
@ -158,12 +161,12 @@ static int Joy_GetHatValueForAxis( const engineAxis_t engineAxis )
|
|||
switch( engineAxis )
|
||||
{
|
||||
case JOY_AXIS_SIDE:
|
||||
threshold = joy_side_key_threshold->value;
|
||||
threshold = joy_side_key_threshold.value;
|
||||
negative = JOY_HAT_LEFT;
|
||||
positive = JOY_HAT_RIGHT;
|
||||
break;
|
||||
case JOY_AXIS_FWD:
|
||||
threshold = joy_side_key_threshold->value;
|
||||
threshold = joy_side_key_threshold.value;
|
||||
negative = JOY_HAT_UP;
|
||||
positive = JOY_HAT_DOWN;
|
||||
break;
|
||||
|
@ -197,10 +200,10 @@ static void Joy_ProcessStick( const engineAxis_t engineAxis, short value )
|
|||
|
||||
switch( engineAxis )
|
||||
{
|
||||
case JOY_AXIS_FWD: deadzone = joy_forward_deadzone->value; break;
|
||||
case JOY_AXIS_SIDE: deadzone = joy_side_deadzone->value; break;
|
||||
case JOY_AXIS_PITCH: deadzone = joy_pitch_deadzone->value; break;
|
||||
case JOY_AXIS_YAW: deadzone = joy_yaw_deadzone->value; break;
|
||||
case JOY_AXIS_FWD: deadzone = joy_forward_deadzone.value; break;
|
||||
case JOY_AXIS_SIDE: deadzone = joy_side_deadzone.value; break;
|
||||
case JOY_AXIS_PITCH: deadzone = joy_pitch_deadzone.value; break;
|
||||
case JOY_AXIS_YAW: deadzone = joy_yaw_deadzone.value; break;
|
||||
default:
|
||||
Con_Reportf( S_ERROR "Joy_ProcessStick: invalid axis = %i", engineAxis );
|
||||
break;
|
||||
|
@ -235,7 +238,7 @@ Axis events
|
|||
*/
|
||||
void Joy_AxisMotionEvent( byte axis, short value )
|
||||
{
|
||||
if( !joy_found->value )
|
||||
if( !joy_found.value )
|
||||
return;
|
||||
|
||||
if( axis >= MAX_AXES )
|
||||
|
@ -244,7 +247,7 @@ void Joy_AxisMotionEvent( byte axis, short value )
|
|||
return;
|
||||
}
|
||||
|
||||
return Joy_KnownAxisMotionEvent( joyaxesmap[axis], value );
|
||||
Joy_KnownAxisMotionEvent( joyaxesmap[axis], value );
|
||||
}
|
||||
|
||||
void Joy_KnownAxisMotionEvent( engineAxis_t engineAxis, short value )
|
||||
|
@ -270,7 +273,7 @@ Trackball events. UNDONE
|
|||
*/
|
||||
void Joy_BallMotionEvent( byte ball, short xrel, short yrel )
|
||||
{
|
||||
//if( !joy_found->value )
|
||||
//if( !joy_found.value )
|
||||
// return;
|
||||
}
|
||||
|
||||
|
@ -283,7 +286,7 @@ Button events
|
|||
*/
|
||||
void Joy_ButtonEvent( byte button, byte down )
|
||||
{
|
||||
if( !joy_found->value )
|
||||
if( !joy_found.value )
|
||||
return;
|
||||
|
||||
// generic game button code.
|
||||
|
@ -308,7 +311,7 @@ Called when joystick is removed. For future expansion
|
|||
*/
|
||||
void Joy_RemoveEvent( void )
|
||||
{
|
||||
if( joy_found->value )
|
||||
if( joy_found.value )
|
||||
Cvar_FullSet( "joy_found", "0", FCVAR_READ_ONLY );
|
||||
}
|
||||
|
||||
|
@ -321,7 +324,7 @@ Called when joystick is removed. For future expansion
|
|||
*/
|
||||
void Joy_AddEvent( void )
|
||||
{
|
||||
if( joy_enable->value && !joy_found->value )
|
||||
if( joy_enable.value && !joy_found.value )
|
||||
Cvar_FullSet( "joy_found", "1", FCVAR_READ_ONLY );
|
||||
}
|
||||
|
||||
|
@ -337,9 +340,9 @@ void Joy_FinalizeMove( float *fw, float *side, float *dpitch, float *dyaw )
|
|||
if( !Joy_IsActive() )
|
||||
return;
|
||||
|
||||
if( FBitSet( joy_axis_binding->flags, FCVAR_CHANGED ) )
|
||||
if( FBitSet( joy_axis_binding.flags, FCVAR_CHANGED ) )
|
||||
{
|
||||
const char *bind = joy_axis_binding->string;
|
||||
const char *bind = joy_axis_binding.string;
|
||||
size_t i;
|
||||
|
||||
for( i = 0; bind[i]; i++ )
|
||||
|
@ -356,18 +359,18 @@ void Joy_FinalizeMove( float *fw, float *side, float *dpitch, float *dyaw )
|
|||
}
|
||||
}
|
||||
|
||||
ClearBits( joy_axis_binding->flags, FCVAR_CHANGED );
|
||||
ClearBits( joy_axis_binding.flags, FCVAR_CHANGED );
|
||||
}
|
||||
|
||||
*fw -= joy_forward->value * (float)joyaxis[JOY_AXIS_FWD ].val/(float)SHRT_MAX; // must be form -1.0 to 1.0
|
||||
*side += joy_side->value * (float)joyaxis[JOY_AXIS_SIDE].val/(float)SHRT_MAX;
|
||||
*fw -= joy_forward.value * (float)joyaxis[JOY_AXIS_FWD ].val/(float)SHRT_MAX; // must be form -1.0 to 1.0
|
||||
*side += joy_side.value * (float)joyaxis[JOY_AXIS_SIDE].val/(float)SHRT_MAX;
|
||||
#if !defined(XASH_SDL)
|
||||
*dpitch += joy_pitch->value * (float)joyaxis[JOY_AXIS_PITCH].val/(float)SHRT_MAX * host.realframetime; // abs axis rotate is frametime related
|
||||
*dyaw -= joy_yaw->value * (float)joyaxis[JOY_AXIS_YAW ].val/(float)SHRT_MAX * host.realframetime;
|
||||
*dpitch += joy_pitch.value * (float)joyaxis[JOY_AXIS_PITCH].val/(float)SHRT_MAX * host.realframetime; // abs axis rotate is frametime related
|
||||
*dyaw -= joy_yaw.value * (float)joyaxis[JOY_AXIS_YAW ].val/(float)SHRT_MAX * host.realframetime;
|
||||
#else
|
||||
// HACKHACK: SDL have inverted look axis.
|
||||
*dpitch -= joy_pitch->value * (float)joyaxis[JOY_AXIS_PITCH].val/(float)SHRT_MAX * host.realframetime;
|
||||
*dyaw += joy_yaw->value * (float)joyaxis[JOY_AXIS_YAW ].val/(float)SHRT_MAX * host.realframetime;
|
||||
*dpitch -= joy_pitch.value * (float)joyaxis[JOY_AXIS_PITCH].val/(float)SHRT_MAX * host.realframetime;
|
||||
*dyaw += joy_yaw.value * (float)joyaxis[JOY_AXIS_YAW ].val/(float)SHRT_MAX * host.realframetime;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -380,40 +383,43 @@ Main init procedure
|
|||
*/
|
||||
void Joy_Init( void )
|
||||
{
|
||||
joy_pitch = Cvar_Get( "joy_pitch", "100.0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "joystick pitch sensitivity" );
|
||||
joy_yaw = Cvar_Get( "joy_yaw", "100.0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "joystick yaw sensitivity" );
|
||||
joy_side = Cvar_Get( "joy_side", "1.0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "joystick side sensitivity. Values from -1.0 to 1.0" );
|
||||
joy_forward = Cvar_Get( "joy_forward", "1.0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "joystick forward sensitivity. Values from -1.0 to 1.0" );
|
||||
Cvar_RegisterVariable( &joy_pitch );
|
||||
Cvar_RegisterVariable( &joy_yaw );
|
||||
Cvar_RegisterVariable( &joy_side );
|
||||
Cvar_RegisterVariable( &joy_forward );
|
||||
|
||||
joy_lt_threshold = Cvar_Get( "joy_lt_threshold", "16384", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "left trigger threshold. Value from 0 to 32767");
|
||||
joy_rt_threshold = Cvar_Get( "joy_rt_threshold", "16384", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "right trigger threshold. Value from 0 to 32767" );
|
||||
Cvar_RegisterVariable( &joy_lt_threshold );
|
||||
Cvar_RegisterVariable( &joy_rt_threshold );
|
||||
|
||||
// emit a key event at 75% axis move
|
||||
joy_side_key_threshold = Cvar_Get( "joy_side_key_threshold", "24576", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "side axis key event emit threshold. Value from 0 to 32767" );
|
||||
joy_forward_key_threshold = Cvar_Get( "joy_forward_key_threshold", "24576", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "forward axis key event emit threshold. Value from 0 to 32767");
|
||||
Cvar_RegisterVariable( &joy_side_key_threshold );
|
||||
Cvar_RegisterVariable( &joy_forward_key_threshold );
|
||||
|
||||
// by default, we rely on deadzone detection come from system, but some glitchy devices report false deadzones
|
||||
joy_side_deadzone = Cvar_Get( "joy_side_deadzone", "0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "side axis deadzone. Value from 0 to 32767" );
|
||||
joy_forward_deadzone = Cvar_Get( "joy_forward_deadzone", "0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "forward axis deadzone. Value from 0 to 32767");
|
||||
joy_pitch_deadzone = Cvar_Get( "joy_pitch_deadzone", "0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "pitch axis deadzone. Value from 0 to 32767");
|
||||
joy_yaw_deadzone = Cvar_Get( "joy_yaw_deadzone", "0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "yaw axis deadzone. Value from 0 to 32767" );
|
||||
Cvar_RegisterVariable( &joy_side_deadzone );
|
||||
Cvar_RegisterVariable( &joy_forward_deadzone );
|
||||
Cvar_RegisterVariable( &joy_pitch_deadzone );
|
||||
Cvar_RegisterVariable( &joy_yaw_deadzone );
|
||||
|
||||
joy_axis_binding = Cvar_Get( "joy_axis_binding", "sfpyrl", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "axis hardware id to engine inner axis binding, "
|
||||
"s - side, f - forward, y - yaw, p - pitch, r - left trigger, l - right trigger" );
|
||||
joy_found = Cvar_Get( "joy_found", "0", FCVAR_READ_ONLY, "is joystick is connected" );
|
||||
Cvar_RegisterVariable( &joy_axis_binding );
|
||||
Cvar_RegisterVariable( &joy_found );
|
||||
// we doesn't loaded config.cfg yet, so this cvar is not archive.
|
||||
// change by +set joy_index in cmdline
|
||||
joy_index = Cvar_Get( "joy_index", "0", FCVAR_READ_ONLY, "current active joystick" );
|
||||
Cvar_RegisterVariable( &joy_index );
|
||||
|
||||
joy_enable = Cvar_Get( "joy_enable", "1", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "enable joystick" );
|
||||
Cvar_RegisterVariable( &joy_enable );
|
||||
|
||||
if( Sys_CheckParm( "-nojoy" ))
|
||||
// renamed from -nojoy to -noenginejoy to not conflict with
|
||||
// client.dll's joystick support
|
||||
if( Sys_CheckParm( "-noenginejoy" ))
|
||||
{
|
||||
Cvar_FullSet( "joy_enable", "0", FCVAR_READ_ONLY );
|
||||
return;
|
||||
}
|
||||
|
||||
Cvar_FullSet( "joy_found", va( "%d", Platform_JoyInit( joy_index->value )), FCVAR_READ_ONLY );
|
||||
Cvar_FullSet( "joy_found", va( "%d", Platform_JoyInit( joy_index.value )), FCVAR_READ_ONLY );
|
||||
|
||||
joy_initialized = true;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -425,5 +431,8 @@ Shutdown joystick code
|
|||
*/
|
||||
void Joy_Shutdown( void )
|
||||
{
|
||||
Cvar_FullSet( "joy_found", 0, FCVAR_READ_ONLY );
|
||||
if( joy_initialized )
|
||||
{
|
||||
Cvar_FullSet( "joy_found", 0, FCVAR_READ_ONLY );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,7 +87,7 @@ typedef struct touchbuttonlist_s
|
|||
touch_button_t *last;
|
||||
} touchbuttonlist_t;
|
||||
|
||||
struct touch_s
|
||||
static struct touch_s
|
||||
{
|
||||
qboolean initialized;
|
||||
qboolean config_loaded;
|
||||
|
@ -132,6 +132,8 @@ struct touch_s
|
|||
int whitetexture;
|
||||
int joytexture; // touch indicator
|
||||
qboolean configchanged;
|
||||
float actual_aspect_ratio; // maximum aspect ratio from launch, or aspect ratio when entering editor
|
||||
float config_aspect_ratio; // aspect ratio set by command from config or after entering editor
|
||||
} touch;
|
||||
|
||||
// private to the engine flags
|
||||
|
@ -140,41 +142,70 @@ struct touch_s
|
|||
touchdefaultbutton_t g_DefaultButtons[256];
|
||||
int g_LastDefaultButton;
|
||||
|
||||
convar_t *touch_pitch;
|
||||
convar_t *touch_yaw;
|
||||
convar_t *touch_forwardzone;
|
||||
convar_t *touch_sidezone;
|
||||
convar_t *touch_nonlinear_look;
|
||||
convar_t *touch_pow_mult;
|
||||
convar_t *touch_pow_factor;
|
||||
convar_t *touch_exp_mult;
|
||||
convar_t *touch_grid_enable;
|
||||
convar_t *touch_grid_count;
|
||||
convar_t *touch_config_file;
|
||||
convar_t *touch_enable;
|
||||
convar_t *touch_in_menu;
|
||||
convar_t *touch_joy_radius;
|
||||
convar_t *touch_dpad_radius;
|
||||
convar_t *touch_move_indicator;
|
||||
convar_t *touch_highlight_r;
|
||||
convar_t *touch_highlight_g;
|
||||
convar_t *touch_highlight_b;
|
||||
convar_t *touch_highlight_a;
|
||||
convar_t *touch_precise_amount;
|
||||
convar_t *touch_joy_texture;
|
||||
convar_t *touch_emulate;
|
||||
static CVAR_DEFINE_AUTO( touch_in_menu, "0", FCVAR_FILTERABLE, "draw touch in menu (for internal use only)" );
|
||||
static CVAR_DEFINE_AUTO( touch_forwardzone, "0.06", FCVAR_FILTERABLE, "forward touch zone" );
|
||||
static CVAR_DEFINE_AUTO( touch_sidezone, "0.06", FCVAR_FILTERABLE, "side touch zone" );
|
||||
static CVAR_DEFINE_AUTO( touch_pitch, "90", FCVAR_FILTERABLE, "touch pitch sensitivity" );
|
||||
static CVAR_DEFINE_AUTO( touch_yaw, "120", FCVAR_FILTERABLE, "touch yaw sensitivity" );
|
||||
static CVAR_DEFINE_AUTO( touch_nonlinear_look, "0", FCVAR_FILTERABLE, "enable nonlinear touch look" );
|
||||
static CVAR_DEFINE_AUTO( touch_pow_factor, "1.3", FCVAR_FILTERABLE, "set > 1 to enable" );
|
||||
static CVAR_DEFINE_AUTO( touch_pow_mult, "400.0", FCVAR_FILTERABLE, "power multiplier, usually 200-1000" );
|
||||
static CVAR_DEFINE_AUTO( touch_exp_mult, "0", FCVAR_FILTERABLE, "exponent multiplier, usually 20-200, 0 to disable" );
|
||||
static CVAR_DEFINE_AUTO( touch_grid_count, "50", FCVAR_FILTERABLE, "touch grid count" );
|
||||
static CVAR_DEFINE_AUTO( touch_grid_enable, "1", FCVAR_FILTERABLE, "enable touch grid" );
|
||||
static CVAR_DEFINE_AUTO( touch_config_file, "touch.cfg", FCVAR_ARCHIVE | FCVAR_PRIVILEGED, "current touch profile file" );
|
||||
static CVAR_DEFINE_AUTO( touch_precise_amount, "0.5", FCVAR_FILTERABLE, "sensitivity multiplier for precise-look" );
|
||||
static CVAR_DEFINE_AUTO( touch_highlight_r, "1.0", 0, "highlight r color" );
|
||||
static CVAR_DEFINE_AUTO( touch_highlight_g, "1.0", 0, "highlight g color" );
|
||||
static CVAR_DEFINE_AUTO( touch_highlight_b, "1.0", 0, "highlight b color" );
|
||||
static CVAR_DEFINE_AUTO( touch_highlight_a, "1.0", 0, "highlight alpha" );
|
||||
static CVAR_DEFINE_AUTO( touch_dpad_radius, "1.0", FCVAR_FILTERABLE, "dpad radius multiplier" );
|
||||
static CVAR_DEFINE_AUTO( touch_joy_radius, "1.0", FCVAR_FILTERABLE, "joy radius multiplier" );
|
||||
static CVAR_DEFINE_AUTO( touch_move_indicator, "0.0", FCVAR_FILTERABLE, "indicate move events (0 to disable)" );
|
||||
static CVAR_DEFINE_AUTO( touch_joy_texture, "touch_default/joy", FCVAR_FILTERABLE, "texture for move indicator");
|
||||
CVAR_DEFINE_AUTO( touch_enable, DEFAULT_TOUCH_ENABLE, FCVAR_ARCHIVE | FCVAR_FILTERABLE, "enable touch controls" );
|
||||
CVAR_DEFINE_AUTO( touch_emulate, "0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "emulate touch with mouse" );
|
||||
|
||||
// code looks smaller with it
|
||||
#define B(x) (button->x)
|
||||
#define SCR_W ((float)refState.width)
|
||||
#define SCR_H ((float)refState.height)
|
||||
#define TO_SCRN_Y(x) (refState.height * (x))
|
||||
#define TO_SCRN_Y(x) (refState.width * (x) * Touch_AspectRatio())
|
||||
#define TO_SCRN_X(x) (refState.width * (x))
|
||||
|
||||
static void IN_TouchCheckCoords( float *x1, float *y1, float *x2, float *y2 );
|
||||
static void IN_TouchEditClear( void );
|
||||
static void Touch_InitConfig( void );
|
||||
|
||||
void Touch_NotifyResize( void )
|
||||
{
|
||||
if( refState.width && refState.height && ( !touch.configchanged || !touch.actual_aspect_ratio ))
|
||||
{
|
||||
float aspect_ratio = SCR_H/SCR_W;
|
||||
if( aspect_ratio < 0.99 && aspect_ratio > touch.actual_aspect_ratio )
|
||||
touch.actual_aspect_ratio = aspect_ratio;
|
||||
}
|
||||
}
|
||||
|
||||
static inline float Touch_AspectRatio( void )
|
||||
{
|
||||
if( touch.config_aspect_ratio )
|
||||
return touch.config_aspect_ratio;
|
||||
else if( touch.actual_aspect_ratio )
|
||||
return touch.actual_aspect_ratio;
|
||||
else if( refState.width && refState.height )
|
||||
return SCR_H/SCR_W;
|
||||
else
|
||||
return 9.0f / 16.0f;
|
||||
}
|
||||
|
||||
|
||||
static void Touch_ConfigAspectRatio_f( void )
|
||||
{
|
||||
touch.config_aspect_ratio = Q_atof( Cmd_Argv( 1 ));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==========================
|
||||
Touch_ExportButtonToConfig
|
||||
|
@ -206,7 +237,7 @@ static inline int Touch_ExportButtonToConfig( file_t *f, touch_button_t *button,
|
|||
|
||||
if( keepAspect )
|
||||
{
|
||||
float aspect = ( B(y2) - B(y1) ) / ( ( B(x2) - B(x1) ) /(SCR_H/SCR_W) );
|
||||
float aspect = ( B(y2) - B(y1) ) / ( ( B(x2) - B(x1) ) /(Touch_AspectRatio()) );
|
||||
FS_Printf( f, " %f\n", aspect );
|
||||
}
|
||||
else FS_Printf( f, "\n" );
|
||||
|
@ -214,6 +245,76 @@ static inline int Touch_ExportButtonToConfig( file_t *f, touch_button_t *button,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Touch_DumpConfig
|
||||
|
||||
Dump config to file
|
||||
=================
|
||||
*/
|
||||
qboolean Touch_DumpConfig( const char *name, const char *profilename )
|
||||
{
|
||||
file_t *f;
|
||||
touch_button_t *button;
|
||||
|
||||
f = FS_Open( name, "w", true );
|
||||
|
||||
if( !f )
|
||||
{
|
||||
Con_Printf( S_ERROR "Couldn't write %s.\n", name );
|
||||
return false;
|
||||
}
|
||||
|
||||
FS_Printf( f, "//=======================================================================\n");
|
||||
FS_Printf( f, "//\tCopyright FWGS & XashXT group %s (c)\n", Q_timestamp( TIME_YEAR_ONLY ));
|
||||
FS_Printf( f, "//\t\t\ttouchscreen config\n" );
|
||||
FS_Printf( f, "//=======================================================================\n" );
|
||||
FS_Printf( f, "\ntouch_config_file \"%s\"\n", profilename );
|
||||
FS_Printf( f, "\n// touch cvars\n" );
|
||||
FS_Printf( f, "\n// sensitivity settings\n" );
|
||||
FS_Printf( f, "touch_pitch \"%f\"\n", touch_pitch.value );
|
||||
FS_Printf( f, "touch_yaw \"%f\"\n", touch_yaw.value );
|
||||
FS_Printf( f, "touch_forwardzone \"%f\"\n", touch_forwardzone.value );
|
||||
FS_Printf( f, "touch_sidezone \"%f\"\n", touch_sidezone.value );
|
||||
FS_Printf( f, "touch_nonlinear_look \"%d\"\n", touch_nonlinear_look.value ? 1 : 0 );
|
||||
FS_Printf( f, "touch_pow_factor \"%f\"\n", touch_pow_factor.value );
|
||||
FS_Printf( f, "touch_pow_mult \"%f\"\n", touch_pow_mult.value );
|
||||
FS_Printf( f, "touch_exp_mult \"%f\"\n", touch_exp_mult.value );
|
||||
FS_Printf( f, "\n// grid settings\n" );
|
||||
FS_Printf( f, "touch_grid_count \"%d\"\n", (int)touch_grid_count.value );
|
||||
FS_Printf( f, "touch_grid_enable \"%d\"\n", touch_grid_enable.value ? 1 : 0 );
|
||||
FS_Printf( f, "\n// global overstroke (width, r, g, b, a)\n" );
|
||||
FS_Printf( f, "touch_set_stroke %d %d %d %d %d\n", touch.swidth, touch.scolor[0], touch.scolor[1], touch.scolor[2], touch.scolor[3] );
|
||||
FS_Printf( f, "\n// highlight when pressed\n" );
|
||||
FS_Printf( f, "touch_highlight_r \"%f\"\n", touch_highlight_r.value );
|
||||
FS_Printf( f, "touch_highlight_g \"%f\"\n", touch_highlight_g.value );
|
||||
FS_Printf( f, "touch_highlight_b \"%f\"\n", touch_highlight_b.value );
|
||||
FS_Printf( f, "touch_highlight_a \"%f\"\n", touch_highlight_a.value );
|
||||
FS_Printf( f, "\n// _joy and _dpad options\n" );
|
||||
FS_Printf( f, "touch_dpad_radius \"%f\"\n", touch_dpad_radius.value );
|
||||
FS_Printf( f, "touch_joy_radius \"%f\"\n", touch_joy_radius.value );
|
||||
FS_Printf( f, "\n// how much slowdown when Precise Look button pressed\n" );
|
||||
FS_Printf( f, "touch_precise_amount \"%f\"\n", touch_precise_amount.value );
|
||||
FS_Printf( f, "\n// enable/disable move indicator\n" );
|
||||
FS_Printf( f, "touch_move_indicator \"%f\"\n", touch_move_indicator.value );
|
||||
|
||||
FS_Printf( f, "\n// reset menu state when execing config\n" );
|
||||
FS_Printf( f, "touch_setclientonly 0\n" );
|
||||
FS_Printf( f, "\n// touch buttons\n" );
|
||||
FS_Printf( f, "touch_removeall\n" );
|
||||
FS_Printf( f, "touch_aspectratio %f\n", Touch_AspectRatio());
|
||||
|
||||
|
||||
for( button = touch.list_user.first; button; button = button->next )
|
||||
{
|
||||
Touch_ExportButtonToConfig( f, button, false );
|
||||
}
|
||||
|
||||
FS_Close( f );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Touch_WriteConfig
|
||||
|
@ -232,66 +333,19 @@ void Touch_WriteConfig( void )
|
|||
if( Sys_CheckParm( "-nowriteconfig" ) || !touch.configchanged || !touch.config_loaded )
|
||||
return;
|
||||
|
||||
Con_DPrintf( "Touch_WriteConfig(): %s\n", touch_config_file->string );
|
||||
Con_DPrintf( "Touch_WriteConfig(): %s\n", touch_config_file.string );
|
||||
|
||||
Q_snprintf( newconfigfile, sizeof( newconfigfile ), "%s.new", touch_config_file->string );
|
||||
Q_snprintf( oldconfigfile, sizeof( oldconfigfile ), "%s.bak", touch_config_file->string );
|
||||
Q_snprintf( newconfigfile, sizeof( newconfigfile ), "%s.new", touch_config_file.string );
|
||||
Q_snprintf( oldconfigfile, sizeof( oldconfigfile ), "%s.bak", touch_config_file.string );
|
||||
|
||||
f = FS_Open( newconfigfile, "w", true );
|
||||
if( f )
|
||||
if( Touch_DumpConfig( newconfigfile, touch_config_file.string ))
|
||||
{
|
||||
touch_button_t *button;
|
||||
FS_Printf( f, "//=======================================================================\n");
|
||||
FS_Printf( f, "//\tCopyright FWGS & XashXT group %s (c)\n", Q_timestamp( TIME_YEAR_ONLY ));
|
||||
FS_Printf( f, "//\t\t\ttouchscreen config\n" );
|
||||
FS_Printf( f, "//=======================================================================\n" );
|
||||
FS_Printf( f, "\ntouch_config_file \"%s\"\n", touch_config_file->string );
|
||||
FS_Printf( f, "\n// touch cvars\n" );
|
||||
FS_Printf( f, "\n// sensitivity settings\n" );
|
||||
FS_Printf( f, "touch_pitch \"%f\"\n", touch_pitch->value );
|
||||
FS_Printf( f, "touch_yaw \"%f\"\n", touch_yaw->value );
|
||||
FS_Printf( f, "touch_forwardzone \"%f\"\n", touch_forwardzone->value );
|
||||
FS_Printf( f, "touch_sidezone \"%f\"\n", touch_sidezone->value );
|
||||
FS_Printf( f, "touch_nonlinear_look \"%d\"\n", CVAR_TO_BOOL(touch_nonlinear_look));
|
||||
FS_Printf( f, "touch_pow_factor \"%f\"\n", touch_pow_factor->value );
|
||||
FS_Printf( f, "touch_pow_mult \"%f\"\n", touch_pow_mult->value );
|
||||
FS_Printf( f, "touch_exp_mult \"%f\"\n", touch_exp_mult->value );
|
||||
FS_Printf( f, "\n// grid settings\n" );
|
||||
FS_Printf( f, "touch_grid_count \"%d\"\n", (int)touch_grid_count->value );
|
||||
FS_Printf( f, "touch_grid_enable \"%d\"\n", CVAR_TO_BOOL(touch_grid_enable));
|
||||
FS_Printf( f, "\n// global overstroke (width, r, g, b, a)\n" );
|
||||
FS_Printf( f, "touch_set_stroke %d %d %d %d %d\n", touch.swidth, touch.scolor[0], touch.scolor[1], touch.scolor[2], touch.scolor[3] );
|
||||
FS_Printf( f, "\n// highlight when pressed\n" );
|
||||
FS_Printf( f, "touch_highlight_r \"%f\"\n", touch_highlight_r->value );
|
||||
FS_Printf( f, "touch_highlight_g \"%f\"\n", touch_highlight_g->value );
|
||||
FS_Printf( f, "touch_highlight_b \"%f\"\n", touch_highlight_b->value );
|
||||
FS_Printf( f, "touch_highlight_a \"%f\"\n", touch_highlight_a->value );
|
||||
FS_Printf( f, "\n// _joy and _dpad options\n" );
|
||||
FS_Printf( f, "touch_dpad_radius \"%f\"\n", touch_dpad_radius->value );
|
||||
FS_Printf( f, "touch_joy_radius \"%f\"\n", touch_joy_radius->value );
|
||||
FS_Printf( f, "\n// how much slowdown when Precise Look button pressed\n" );
|
||||
FS_Printf( f, "touch_precise_amount \"%f\"\n", touch_precise_amount->value );
|
||||
FS_Printf( f, "\n// enable/disable move indicator\n" );
|
||||
FS_Printf( f, "touch_move_indicator \"%f\"\n", touch_move_indicator->value );
|
||||
|
||||
FS_Printf( f, "\n// reset menu state when execing config\n" );
|
||||
FS_Printf( f, "touch_setclientonly 0\n" );
|
||||
FS_Printf( f, "\n// touch buttons\n" );
|
||||
FS_Printf( f, "touch_removeall\n" );
|
||||
|
||||
for( button = touch.list_user.first; button; button = button->next )
|
||||
{
|
||||
Touch_ExportButtonToConfig( f, button, false );
|
||||
}
|
||||
|
||||
FS_Close( f );
|
||||
|
||||
FS_Delete( oldconfigfile );
|
||||
FS_Rename( touch_config_file->string, oldconfigfile );
|
||||
FS_Delete( touch_config_file->string );
|
||||
FS_Rename( newconfigfile, touch_config_file->string );
|
||||
FS_Rename( touch_config_file.string, oldconfigfile );
|
||||
|
||||
FS_Delete( touch_config_file.string );
|
||||
FS_Rename( newconfigfile, touch_config_file.string );
|
||||
}
|
||||
else Con_Printf( S_ERROR "Couldn't write %s.\n", touch_config_file->string );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -303,8 +357,8 @@ export current touch configuration into profile
|
|||
*/
|
||||
static void Touch_ExportConfig_f( void )
|
||||
{
|
||||
file_t *f;
|
||||
const char *name;
|
||||
string profilename, profilebase;
|
||||
|
||||
if( Cmd_Argc() != 2 )
|
||||
{
|
||||
|
@ -316,65 +370,15 @@ static void Touch_ExportConfig_f( void )
|
|||
|
||||
name = Cmd_Argv( 1 );
|
||||
|
||||
Con_Reportf( "Exporting config to %s\n", name );
|
||||
f = FS_Open( name, "w", true );
|
||||
if( f )
|
||||
if( Q_strstr( name, "touch_presets/" ))
|
||||
{
|
||||
string profilename, profilebase;
|
||||
touch_button_t *button;
|
||||
|
||||
if( Q_strstr( name, "touch_presets/" ) )
|
||||
{
|
||||
COM_FileBase( name, profilebase );
|
||||
Q_snprintf( profilename, sizeof( profilebase ), "touch_profiles/%s (copy).cfg", profilebase );
|
||||
}
|
||||
else Q_strncpy( profilename, name, sizeof( profilename ));
|
||||
FS_Printf( f, "//=======================================================================\n");
|
||||
FS_Printf( f, "//\tCopyright FWGS & XashXT group %s (c)\n", Q_timestamp( TIME_YEAR_ONLY ));
|
||||
FS_Printf( f, "//\t\t\ttouchscreen preset\n" );
|
||||
FS_Printf( f, "//=======================================================================\n" );
|
||||
FS_Printf( f, "\ntouch_config_file \"%s\"\n", profilename );
|
||||
FS_Printf( f, "\n// touch cvars\n" );
|
||||
FS_Printf( f, "\n// sensitivity settings\n" );
|
||||
FS_Printf( f, "touch_pitch \"%f\"\n", touch_pitch->value );
|
||||
FS_Printf( f, "touch_yaw \"%f\"\n", touch_yaw->value );
|
||||
FS_Printf( f, "touch_forwardzone \"%f\"\n", touch_forwardzone->value );
|
||||
FS_Printf( f, "touch_sidezone \"%f\"\n", touch_sidezone->value );
|
||||
FS_Printf( f, "touch_nonlinear_look \"%d\"\n", CVAR_TO_BOOL(touch_nonlinear_look) );
|
||||
FS_Printf( f, "touch_pow_factor \"%f\"\n", touch_pow_factor->value );
|
||||
FS_Printf( f, "touch_pow_mult \"%f\"\n", touch_pow_mult->value );
|
||||
FS_Printf( f, "touch_exp_mult \"%f\"\n", touch_exp_mult->value );
|
||||
FS_Printf( f, "\n// grid settings\n" );
|
||||
FS_Printf( f, "touch_grid_count \"%d\"\n", (int)touch_grid_count->value );
|
||||
FS_Printf( f, "touch_grid_enable \"%d\"\n", CVAR_TO_BOOL(touch_grid_enable) );
|
||||
FS_Printf( f, "\n// global overstroke (width, r, g, b, a)\n" );
|
||||
FS_Printf( f, "touch_set_stroke %d %d %d %d %d\n", touch.swidth, touch.scolor[0], touch.scolor[1], touch.scolor[2], touch.scolor[3] );
|
||||
FS_Printf( f, "\n// highlight when pressed\n" );
|
||||
FS_Printf( f, "touch_highlight_r \"%f\"\n", touch_highlight_r->value );
|
||||
FS_Printf( f, "touch_highlight_g \"%f\"\n", touch_highlight_g->value );
|
||||
FS_Printf( f, "touch_highlight_b \"%f\"\n", touch_highlight_b->value );
|
||||
FS_Printf( f, "touch_highlight_a \"%f\"\n", touch_highlight_a->value );
|
||||
FS_Printf( f, "\n// _joy and _dpad options\n" );
|
||||
FS_Printf( f, "touch_dpad_radius \"%f\"\n", touch_dpad_radius->value );
|
||||
FS_Printf( f, "touch_joy_radius \"%f\"\n", touch_joy_radius->value );
|
||||
FS_Printf( f, "\n// how much slowdown when Precise Look button pressed\n" );
|
||||
FS_Printf( f, "touch_precise_amount \"%f\"\n", touch_precise_amount->value );
|
||||
FS_Printf( f, "\n// enable/disable move indicator\n" );
|
||||
FS_Printf( f, "touch_move_indicator \"%f\"\n", touch_move_indicator->value );
|
||||
|
||||
FS_Printf( f, "\n// reset menu state when execing config\n" );
|
||||
FS_Printf( f, "touch_setclientonly 0\n" );
|
||||
FS_Printf( f, "\n// touch buttons\n" );
|
||||
FS_Printf( f, "touch_removeall\n" );
|
||||
for( button = touch.list_user.first; button; button = button->next )
|
||||
{
|
||||
Touch_ExportButtonToConfig( f, button, true );
|
||||
}
|
||||
FS_Printf( f, "\n// round button coordinates to grid\n" );
|
||||
FS_Printf( f, "touch_roundall\n" );
|
||||
FS_Close( f );
|
||||
COM_FileBase( name, profilebase, sizeof( profilebase ));
|
||||
Q_snprintf( profilename, sizeof( profilebase ), "touch_profiles/%s (copy).cfg", profilebase );
|
||||
}
|
||||
else Con_Printf( S_ERROR "Couldn't write %s.\n", name );
|
||||
else Q_strncpy( profilename, name, sizeof( profilename ));
|
||||
|
||||
Con_Reportf( "Exporting config to \"%s\", profile name \"%s\"\n", name, profilename );
|
||||
Touch_DumpConfig( name, profilename );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -405,7 +409,7 @@ static void Touch_GenerateCode_f( void )
|
|||
if( FBitSet( flags, TOUCH_FL_DEF_HIDE ))
|
||||
SetBits( flags, TOUCH_FL_HIDE );
|
||||
|
||||
aspect = ( B(y2) - B(y1) ) / ( ( B(x2) - B(x1) ) /(SCR_H/SCR_W) );
|
||||
aspect = ( B(y2) - B(y1) ) / ( ( B(x2) - B(x1) ) /(Touch_AspectRatio()) );
|
||||
if( memcmp( &c, &B(color), sizeof( rgba_t ) ) )
|
||||
{
|
||||
Con_Printf( "unsigned char color[] = { %d, %d, %d, %d };\n", B(color[0]), B(color[1]), B(color[2]), B(color[3]) );
|
||||
|
@ -421,7 +425,7 @@ static void Touch_RoundAll_f( void )
|
|||
{
|
||||
touch_button_t *button;
|
||||
|
||||
if( !touch_grid_enable->value )
|
||||
if( !touch_grid_enable.value )
|
||||
return;
|
||||
|
||||
for( button = touch.list_user.first; button; button = button->next )
|
||||
|
@ -497,8 +501,8 @@ static touch_button_t *Touch_FindFirst( touchbuttonlist_t *list, const char *nam
|
|||
|
||||
void Touch_SetClientOnly( byte state )
|
||||
{
|
||||
// TODO: fix clash with vgui cursors
|
||||
touch.clientonly = state;
|
||||
host.mouse_visible = state;
|
||||
|
||||
touch.move_finger = touch.look_finger = -1;
|
||||
touch.forward = touch.side = 0;
|
||||
|
@ -578,6 +582,7 @@ static void Touch_RemoveAll_f( void )
|
|||
{
|
||||
IN_TouchEditClear();
|
||||
Touch_ClearList( &touch.list_user );
|
||||
touch.config_aspect_ratio = 0.0f;
|
||||
}
|
||||
|
||||
static void Touch_SetColor( touchbuttonlist_t *list, const char *name, byte *color )
|
||||
|
@ -755,6 +760,8 @@ static void Touch_SetCommand_f( void )
|
|||
Con_Printf( S_USAGE "touch_setcommand <name> <command>\n" );
|
||||
}
|
||||
|
||||
static void Touch_LoadDefaults_f( void );
|
||||
|
||||
static void Touch_ReloadConfig_f( void )
|
||||
{
|
||||
touch.state = state_none;
|
||||
|
@ -764,8 +771,15 @@ static void Touch_ReloadConfig_f( void )
|
|||
touch.selection->finger = -1;
|
||||
touch.edit = touch.selection = NULL;
|
||||
touch.resize_finger = touch.move_finger = touch.look_finger = touch.wheel_finger = -1;
|
||||
|
||||
Cbuf_AddText( va("exec %s\n", touch_config_file->string ) );
|
||||
if( FS_FileExists( touch_config_file.string, true ) )
|
||||
{
|
||||
Cbuf_AddTextf( "exec \"%s\"\n", touch_config_file.string );
|
||||
}
|
||||
else
|
||||
{
|
||||
Touch_LoadDefaults_f();
|
||||
touch.configchanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
static touch_button_t *Touch_AddButton( touchbuttonlist_t *list,
|
||||
|
@ -813,7 +827,7 @@ void Touch_AddClientButton( const char *name, const char *texture, const char *c
|
|||
IN_TouchCheckCoords( &x1, &y1, &x2, &y2 );
|
||||
if( round == round_aspect )
|
||||
{
|
||||
y2 = y1 + ( x2 - x1 ) * (SCR_W/SCR_H) * aspect;
|
||||
y2 = y1 + ( x2 - x1 ) / (Touch_AspectRatio()) * aspect;
|
||||
}
|
||||
button = Touch_AddButton( &touch.list_user, name, texture, command, x1, y1, x2, y2, color, true );
|
||||
button->flags |= flags | TOUCH_FL_CLIENT | TOUCH_FL_NOEDIT;
|
||||
|
@ -838,7 +852,7 @@ static void Touch_LoadDefaults_f( void )
|
|||
if( g_DefaultButtons[i].texturefile[0] == '#' )
|
||||
y2 = y1 + ( (float)clgame.scrInfo.iCharHeight / (float)clgame.scrInfo.iHeight ) * g_DefaultButtons[i].aspect + touch.swidth*2/SCR_H;
|
||||
else
|
||||
y2 = y1 + ( x2 - x1 ) * (SCR_W/SCR_H) * g_DefaultButtons[i].aspect;
|
||||
y2 = y1 + (( x2 - x1 ) / Touch_AspectRatio()) * g_DefaultButtons[i].aspect;
|
||||
}
|
||||
|
||||
IN_TouchCheckCoords( &x1, &y1, &x2, &y2 );
|
||||
|
@ -846,6 +860,7 @@ static void Touch_LoadDefaults_f( void )
|
|||
button->flags |= g_DefaultButtons[i].flags;
|
||||
button->aspect = g_DefaultButtons[i].aspect;
|
||||
}
|
||||
touch.configchanged = true;
|
||||
}
|
||||
|
||||
// Add default button from client
|
||||
|
@ -938,7 +953,7 @@ static void Touch_AddButton_f( void )
|
|||
if( aspect )
|
||||
{
|
||||
if( B( texturefile )[0] != '#' )
|
||||
B( y2 ) = B( y1 ) + ( B( x2 ) - B( x1 )) * ( SCR_W / SCR_H ) * aspect;
|
||||
B( y2 ) = B( y1 ) + (( B( x2 ) - B( x1 )) / Touch_AspectRatio() ) * aspect;
|
||||
B( aspect ) = aspect;
|
||||
}
|
||||
}
|
||||
|
@ -946,11 +961,39 @@ static void Touch_AddButton_f( void )
|
|||
|
||||
static void Touch_EnableEdit_f( void )
|
||||
{
|
||||
touch_button_t *button;
|
||||
float current_ratio = SCR_H/SCR_W;
|
||||
if( touch.state == state_none )
|
||||
touch.state = state_edit;
|
||||
touch.resize_finger = touch.move_finger = touch.look_finger = touch.wheel_finger = -1;
|
||||
touch.move_button = NULL;
|
||||
touch.configchanged = true;
|
||||
/* try determine the best ratio
|
||||
* User enters editor. Window now have correct size. Need to fix aspect ratio in some cases */
|
||||
// Case A: no config was loaded, touch was generated with lower height, but window was resized higher, reset it to actual size
|
||||
if( touch.actual_aspect_ratio > current_ratio )
|
||||
touch.actual_aspect_ratio = current_ratio;
|
||||
if( !touch.config_aspect_ratio )
|
||||
touch.config_aspect_ratio = touch.actual_aspect_ratio;
|
||||
// Case B: config was loaded, but window may be resized later, so keep y coordinate as is
|
||||
touch.actual_aspect_ratio = current_ratio;
|
||||
// convert coordinates to actual aspect ratio after it was updated
|
||||
if( touch.config_aspect_ratio != touch.actual_aspect_ratio )
|
||||
{
|
||||
for( button = touch.list_user.first; button; button = button->next )
|
||||
{
|
||||
B(y1) /= touch.actual_aspect_ratio / touch.config_aspect_ratio;
|
||||
B(y2) /= touch.actual_aspect_ratio / touch.config_aspect_ratio;
|
||||
|
||||
// clamp positions to make buttons visible by user
|
||||
if( B(y2) > 1.0f )
|
||||
{
|
||||
B(y1) -= B(y2) - 1.0f;
|
||||
B(y2) -= B(y2) - 1.0f;
|
||||
}
|
||||
}
|
||||
touch.config_aspect_ratio = touch.actual_aspect_ratio;
|
||||
}
|
||||
}
|
||||
|
||||
static void Touch_DisableEdit_f( void )
|
||||
|
@ -963,7 +1006,7 @@ static void Touch_DisableEdit_f( void )
|
|||
touch.edit = touch.selection = NULL;
|
||||
touch.resize_finger = touch.move_finger = touch.look_finger = touch.wheel_finger = -1;
|
||||
|
||||
if( CVAR_TO_BOOL( touch_in_menu ))
|
||||
if( touch_in_menu.value )
|
||||
{
|
||||
Cvar_Set( "touch_in_menu", "0" );
|
||||
}
|
||||
|
@ -985,7 +1028,7 @@ static void Touch_DeleteProfile_f( void )
|
|||
|
||||
static void Touch_InitEditor( void )
|
||||
{
|
||||
float x = 0.1f * (SCR_H/SCR_W);
|
||||
float x = 0.1f * (Touch_AspectRatio());
|
||||
float y = 0.05f;
|
||||
touch_button_t *temp;
|
||||
rgba_t color;
|
||||
|
@ -994,7 +1037,7 @@ static void Touch_InitEditor( void )
|
|||
|
||||
Touch_ClearList( &touch.list_edit );
|
||||
|
||||
temp = Touch_AddButton( &touch.list_edit, "close", "touch_default/edit_close.tga", "touch_disableedit", 0, y, x, y + 0.1f, color, true );
|
||||
temp = Touch_AddButton( &touch.list_edit, "close", "touch_default/edit_close", "touch_disableedit", 0, y, x, y + 0.1f, color, true );
|
||||
SetBits( temp->flags, TOUCH_FL_NOEDIT );
|
||||
|
||||
temp = Touch_AddButton( &touch.list_edit, "close", "#Close and save", "", x, y, x + 0.2f, y + 0.1f, color, true );
|
||||
|
@ -1002,7 +1045,7 @@ static void Touch_InitEditor( void )
|
|||
|
||||
y += 0.2f;
|
||||
|
||||
temp = Touch_AddButton( &touch.list_edit, "cancel", "touch_default/edit_reset.tga", "touch_reloadconfig", 0, y, x, y + 0.1f, color, true );
|
||||
temp = Touch_AddButton( &touch.list_edit, "cancel", "touch_default/edit_reset", "touch_reloadconfig", 0, y, x, y + 0.1f, color, true );
|
||||
SetBits( temp->flags, TOUCH_FL_NOEDIT );
|
||||
|
||||
temp = Touch_AddButton( &touch.list_edit, "close", "#Cancel and reset", "", x, y, x + 0.2f, y + 0.1f, color, true );
|
||||
|
@ -1010,7 +1053,7 @@ static void Touch_InitEditor( void )
|
|||
|
||||
y += 0.2f;
|
||||
|
||||
touch.hidebutton = Touch_AddButton( &touch.list_edit, "showhide", "touch_default/edit_hide.tga", "touch_toggleselection", 0, y, x, y + 0.1f, color, true );
|
||||
touch.hidebutton = Touch_AddButton( &touch.list_edit, "showhide", "touch_default/edit_hide", "touch_toggleselection", 0, y, x, y + 0.1f, color, true );
|
||||
SetBits( touch.hidebutton->flags, TOUCH_FL_HIDE | TOUCH_FL_NOEDIT );
|
||||
}
|
||||
|
||||
|
@ -1038,24 +1081,24 @@ void Touch_Init( void )
|
|||
MakeRGBA( color, 255, 255, 255, 255 );
|
||||
Touch_AddDefaultButton( "look", "", "_look", 0.500000, 0.000000, 1.000000, 1, color, 0, 0, 0 );
|
||||
Touch_AddDefaultButton( "move", "", "_move", 0.000000, 0.000000, 0.500000, 1, color, 0, 0, 0 );
|
||||
Touch_AddDefaultButton( "invnext", "touch_default/next_weap.tga", "invnext", 0.000000, 0.530200, 0.120000, 0.757428, color, 2, 1, 0 );
|
||||
Touch_AddDefaultButton( "invprev", "touch_default/prev_weap.tga", "invprev", 0.000000, 0.075743, 0.120000, 0.302971, color, 2, 1, 0 );
|
||||
Touch_AddDefaultButton( "use", "touch_default/use.tga", "+use", 0.880000, 0.454457, 1.000000, 0.681685, color, 2, 1, 0 );
|
||||
Touch_AddDefaultButton( "jump", "touch_default/jump.tga", "+jump", 0.880000, 0.227228, 1.000000, 0.454457, color, 2, 1, 0 );
|
||||
Touch_AddDefaultButton( "attack", "touch_default/shoot.tga", "+attack", 0.760000, 0.530200, 0.880000, 0.757428, color, 2, 1, 0 );
|
||||
Touch_AddDefaultButton( "attack2", "touch_default/shoot_alt.tga", "+attack2", 0.760000, 0.302971, 0.880000, 0.530200, color, 2, 1, 0 );
|
||||
Touch_AddDefaultButton( "loadquick", "touch_default/load.tga", "loadquick", 0.760000, 0.000000, 0.840000, 0.151486, color, 2, 1, 16 );
|
||||
Touch_AddDefaultButton( "savequick", "touch_default/save.tga", "savequick", 0.840000, 0.000000, 0.920000, 0.151486, color, 2, 1, 16 );
|
||||
Touch_AddDefaultButton( "messagemode", "touch_default/keyboard.tga", "messagemode", 0.840000, 0.000000, 0.920000, 0.151486, color, 2, 1, 8 );
|
||||
Touch_AddDefaultButton( "reload", "touch_default/reload.tga", "+reload", 0.000000, 0.302971, 0.120000, 0.530200, color, 2, 1, 0 );
|
||||
Touch_AddDefaultButton( "flashlight", "touch_default/flash_light_filled.tga", "impulse 100", 0.920000, 0.000000, 1.000000, 0.151486, color, 2, 1, 0 );
|
||||
Touch_AddDefaultButton( "scores", "touch_default/map.tga", "+showscores", 0.760000, 0.000000, 0.840000, 0.151486, color, 2, 1, 8 );
|
||||
Touch_AddDefaultButton( "show_numbers", "touch_default/show_weapons.tga", "exec touch_default/numbers.cfg", 0.440000, 0.833171, 0.520000, 0.984656, color, 2, 1, 0 );
|
||||
Touch_AddDefaultButton( "duck", "touch_default/crouch.tga", "+duck", 0.880000, 0.757428, 1.000000, 0.984656, color, 2, 1, 0 );
|
||||
Touch_AddDefaultButton( "tduck", "touch_default/tduck.tga", ";+duck", 0.560000, 0.833171, 0.620000, 0.946785, color, 2, 1, 0 );
|
||||
Touch_AddDefaultButton( "edit", "touch_default/settings.tga", "touch_enableedit", 0.420000, 0.000000, 0.500000, 0.151486, color, 2, 1, 32 );
|
||||
Touch_AddDefaultButton( "menu", "touch_default/menu.tga", "escape", 0.000000, 0.833171, 0.080000, 0.984656, color, 2, 1, 0 );
|
||||
|
||||
Touch_AddDefaultButton( "invnext", "touch_default/next_weap", "invnext", 0.000000, 0.530200, 0.120000, 0.757428, color, 2, 1, 0 );
|
||||
Touch_AddDefaultButton( "invprev", "touch_default/prev_weap", "invprev", 0.000000, 0.075743, 0.120000, 0.302971, color, 2, 1, 0 );
|
||||
Touch_AddDefaultButton( "use", "touch_default/use", "+use", 0.880000, 0.454457, 1.000000, 0.681685, color, 2, 1, 0 );
|
||||
Touch_AddDefaultButton( "jump", "touch_default/jump", "+jump", 0.880000, 0.227228, 1.000000, 0.454457, color, 2, 1, 0 );
|
||||
Touch_AddDefaultButton( "attack", "touch_default/shoot", "+attack", 0.760000, 0.530200, 0.880000, 0.757428, color, 2, 1, 0 );
|
||||
Touch_AddDefaultButton( "attack2", "touch_default/shoot_alt", "+attack2", 0.760000, 0.302971, 0.880000, 0.530200, color, 2, 1, 0 );
|
||||
Touch_AddDefaultButton( "loadquick", "touch_default/load", "loadquick", 0.680000, 0.000000, 0.760000, 0.151486, color, 2, 1, 16 );
|
||||
Touch_AddDefaultButton( "savequick", "touch_default/save", "savequick", 0.760000, 0.000000, 0.840000, 0.151486, color, 2, 1, 16 );
|
||||
Touch_AddDefaultButton( "messagemode", "touch_default/keyboard", "messagemode", 0.760000, 0.000000, 0.840000, 0.151486, color, 2, 1, 8 );
|
||||
Touch_AddDefaultButton( "reload", "touch_default/reload", "+reload", 0.000000, 0.302971, 0.120000, 0.530200, color, 2, 1, 0 );
|
||||
Touch_AddDefaultButton( "flashlight", "touch_default/flash_light_filled", "impulse 100", 0.920000, 0.000000, 1.000000, 0.151486, color, 2, 1, 0 );
|
||||
Touch_AddDefaultButton( "scores", "touch_default/map", "+showscores", 0.680000, 0.000000, 0.760000, 0.151486, color, 2, 1, 8 );
|
||||
Touch_AddDefaultButton( "show_numbers", "touch_default/show_weapons", "exec touch_default/numbers.cfg", 0.440000, 0.833171, 0.520000, 0.984656, color, 2, 1, 0 );
|
||||
Touch_AddDefaultButton( "duck", "touch_default/crouch", "+duck", 0.880000, 0.757428, 1.000000, 0.984656, color, 2, 1, 0 );
|
||||
Touch_AddDefaultButton( "tduck", "touch_default/tduck", ";+duck", 0.560000, 0.833171, 0.620000, 0.946785, color, 2, 1, 0 );
|
||||
Touch_AddDefaultButton( "edit", "touch_default/settings", "touch_enableedit", 0.420000, 0.000000, 0.500000, 0.151486, color, 2, 1, 32 );
|
||||
Touch_AddDefaultButton( "menu", "touch_default/menu", "escape", 0.000000, 0.833171, 0.080000, 0.984656, color, 2, 1, 0 );
|
||||
Touch_AddDefaultButton( "spray", "touch_default/spray", "impulse 201", 0.840000, 0.000000, 0.920000, 0.151486, color, 2, 1, 0 );
|
||||
|
||||
Cmd_AddCommand( "touch_addbutton", Touch_AddButton_f, "add native touch button" );
|
||||
Cmd_AddCommand( "touch_removebutton", IN_TouchRemoveButton_f, "remove native touch button" );
|
||||
|
@ -1080,40 +1123,46 @@ void Touch_Init( void )
|
|||
Cmd_AddRestrictedCommand( "touch_generate_code", Touch_GenerateCode_f, "create code sample for mobility API" );
|
||||
Cmd_AddCommand( "touch_fade", Touch_Fade_f, "start fade animation for selected buttons" );
|
||||
Cmd_AddRestrictedCommand( "touch_toggleselection", Touch_ToggleSelection_f, "toggle vidibility on selected button in editor" );
|
||||
Cmd_AddRestrictedCommand( "touch_aspectratio", Touch_ConfigAspectRatio_f, "set current aspect ratio" );
|
||||
|
||||
// not saved, just runtime state for scripting
|
||||
touch_in_menu = Cvar_Get( "touch_in_menu", "0", FCVAR_FILTERABLE, "draw touch in menu (for internal use only)" );
|
||||
Cvar_RegisterVariable( &touch_in_menu );
|
||||
|
||||
// sensitivity configuration
|
||||
touch_forwardzone = Cvar_Get( "touch_forwardzone", "0.06", FCVAR_FILTERABLE, "forward touch zone" );
|
||||
touch_sidezone = Cvar_Get( "touch_sidezone", "0.06", FCVAR_FILTERABLE, "side touch zone" );
|
||||
touch_pitch = Cvar_Get( "touch_pitch", "90", FCVAR_FILTERABLE, "touch pitch sensitivity" );
|
||||
touch_yaw = Cvar_Get( "touch_yaw", "120", FCVAR_FILTERABLE, "touch yaw sensitivity" );
|
||||
touch_nonlinear_look = Cvar_Get( "touch_nonlinear_look", "0", FCVAR_FILTERABLE, "enable nonlinear touch look" );
|
||||
touch_pow_factor = Cvar_Get( "touch_pow_factor", "1.3", FCVAR_FILTERABLE, "set > 1 to enable" );
|
||||
touch_pow_mult = Cvar_Get( "touch_pow_mult", "400.0", FCVAR_FILTERABLE, "power multiplier, usually 200-1000" );
|
||||
touch_exp_mult = Cvar_Get( "touch_exp_mult", "0", FCVAR_FILTERABLE, "exponent multiplier, usually 20-200, 0 to disable" );
|
||||
Cvar_RegisterVariable( &touch_forwardzone );
|
||||
Cvar_RegisterVariable( &touch_sidezone );
|
||||
Cvar_RegisterVariable( &touch_pitch );
|
||||
Cvar_RegisterVariable( &touch_yaw );
|
||||
Cvar_RegisterVariable( &touch_nonlinear_look );
|
||||
Cvar_RegisterVariable( &touch_pow_factor );
|
||||
Cvar_RegisterVariable( &touch_pow_mult );
|
||||
Cvar_RegisterVariable( &touch_exp_mult );
|
||||
|
||||
// touch.cfg
|
||||
touch_grid_count = Cvar_Get( "touch_grid_count", "50", FCVAR_FILTERABLE, "touch grid count" );
|
||||
touch_grid_enable = Cvar_Get( "touch_grid_enable", "1", FCVAR_FILTERABLE, "enable touch grid" );
|
||||
touch_config_file = Cvar_Get( "touch_config_file", "touch.cfg", FCVAR_ARCHIVE | FCVAR_PRIVILEGED, "current touch profile file" );
|
||||
touch_precise_amount = Cvar_Get( "touch_precise_amount", "0.5", FCVAR_FILTERABLE, "sensitivity multiplier for precise-look" );
|
||||
touch_highlight_r = Cvar_Get( "touch_highlight_r", "1.0", 0, "highlight r color" );
|
||||
touch_highlight_g = Cvar_Get( "touch_highlight_g", "1.0", 0, "highlight g color" );
|
||||
touch_highlight_b = Cvar_Get( "touch_highlight_b", "1.0", 0, "highlight b color" );
|
||||
touch_highlight_a = Cvar_Get( "touch_highlight_a", "1.0", 0, "highlight alpha" );
|
||||
touch_dpad_radius = Cvar_Get( "touch_dpad_radius", "1.0", FCVAR_FILTERABLE, "dpad radius multiplier" );
|
||||
touch_joy_radius = Cvar_Get( "touch_joy_radius", "1.0", FCVAR_FILTERABLE, "joy radius multiplier" );
|
||||
touch_move_indicator = Cvar_Get( "touch_move_indicator", "0.0", FCVAR_FILTERABLE, "indicate move events (0 to disable)" );
|
||||
touch_joy_texture = Cvar_Get( "touch_joy_texture", "touch_default/joy.tga", FCVAR_FILTERABLE, "texture for move indicator");
|
||||
Cvar_RegisterVariable( &touch_grid_count );
|
||||
Cvar_RegisterVariable( &touch_grid_enable );
|
||||
Cvar_RegisterVariable( &touch_config_file );
|
||||
Cvar_RegisterVariable( &touch_precise_amount );
|
||||
Cvar_RegisterVariable( &touch_highlight_r );
|
||||
Cvar_RegisterVariable( &touch_highlight_g );
|
||||
Cvar_RegisterVariable( &touch_highlight_b );
|
||||
Cvar_RegisterVariable( &touch_highlight_a );
|
||||
Cvar_RegisterVariable( &touch_dpad_radius );
|
||||
Cvar_RegisterVariable( &touch_joy_radius );
|
||||
Cvar_RegisterVariable( &touch_move_indicator );
|
||||
Cvar_RegisterVariable( &touch_joy_texture );
|
||||
|
||||
// input devices cvar
|
||||
touch_enable = Cvar_Get( "touch_enable", DEFAULT_TOUCH_ENABLE, FCVAR_ARCHIVE | FCVAR_FILTERABLE, "enable touch controls" );
|
||||
touch_emulate = Cvar_Get( "touch_emulate", "0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "emulate touch with mouse" );
|
||||
Cvar_RegisterVariable( &touch_enable );
|
||||
Cvar_RegisterVariable( &touch_emulate );
|
||||
|
||||
/// TODO: touch sdl platform
|
||||
// SDL_SetHint( SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH, "1" );
|
||||
// TODO: touch platform
|
||||
#if SDL_VERSION_ATLEAST( 2, 0, 10 )
|
||||
SDL_SetHint( SDL_HINT_MOUSE_TOUCH_EVENTS, "0" );
|
||||
SDL_SetHint( SDL_HINT_TOUCH_MOUSE_EVENTS, "0" );
|
||||
#elif defined(SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH)
|
||||
SDL_SetHint( SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH, "1" );
|
||||
#endif
|
||||
|
||||
touch.initialized = true;
|
||||
}
|
||||
|
@ -1132,12 +1181,18 @@ static void Touch_InitConfig( void )
|
|||
|
||||
/// TODO: hud font
|
||||
//pfnGetScreenInfo( NULL ); //HACK: update hud screen parameters like iHeight
|
||||
if( FS_FileExists( touch_config_file->string, true ) )
|
||||
Cbuf_AddText( va( "exec \"%s\"\n", touch_config_file->string ) );
|
||||
else Touch_LoadDefaults_f( );
|
||||
if( FS_FileExists( touch_config_file.string, true ) )
|
||||
{
|
||||
Cbuf_AddTextf( "exec \"%s\"\n", touch_config_file.string );
|
||||
Cbuf_Execute();
|
||||
}
|
||||
else
|
||||
{
|
||||
Touch_LoadDefaults_f();
|
||||
}
|
||||
|
||||
Touch_InitEditor();
|
||||
touch.joytexture = ref.dllFuncs.GL_LoadTexture( touch_joy_texture->string, NULL, 0, TF_NOMIPMAP );
|
||||
touch.joytexture = ref.dllFuncs.GL_LoadTexture( touch_joy_texture.string, NULL, 0, TF_NOMIPMAP );
|
||||
touch.whitetexture = R_GetBuiltinTexture( REF_WHITE_TEXTURE );
|
||||
touch.configchanged = false;
|
||||
touch.config_loaded = true;
|
||||
|
@ -1187,10 +1242,10 @@ static void Touch_DrawTexture ( float x1, float y1, float x2, float y2, int text
|
|||
0, 0, 1, 1, texture );
|
||||
}
|
||||
|
||||
#define GRID_COUNT_X ((int)touch_grid_count->value)
|
||||
#define GRID_COUNT_Y (((int)touch_grid_count->value) * SCR_H / SCR_W)
|
||||
#define GRID_COUNT_X ((int)touch_grid_count.value)
|
||||
#define GRID_COUNT_Y (((int)touch_grid_count.value) * Touch_AspectRatio())
|
||||
#define GRID_X (1.0f/GRID_COUNT_X)
|
||||
#define GRID_Y (SCR_W/SCR_H/GRID_COUNT_X)
|
||||
#define GRID_Y (1.0f/Touch_AspectRatio()/GRID_COUNT_X)
|
||||
#define GRID_ROUND_X(x) ((float)round( x * GRID_COUNT_X ) / GRID_COUNT_X)
|
||||
#define GRID_ROUND_Y(x) ((float)round( x * GRID_COUNT_Y ) / GRID_COUNT_Y)
|
||||
|
||||
|
@ -1209,7 +1264,7 @@ static void IN_TouchCheckCoords( float *x1, float *y1, float *x2, float *y2 )
|
|||
*y1 -= *y2 - 1, *y2 = 1;
|
||||
if( *x2 > 1 )
|
||||
*x1 -= *x2 - 1, *x2 = 1;
|
||||
if( CVAR_TO_BOOL( touch_grid_enable ))
|
||||
if( touch_grid_enable.value )
|
||||
{
|
||||
*x1 = GRID_ROUND_X( *x1 );
|
||||
*x2 = GRID_ROUND_X( *x2 );
|
||||
|
@ -1268,7 +1323,7 @@ static float Touch_DrawText( float x1, float y1, float x2, float y2, const char
|
|||
{
|
||||
while( *s && ( *s != '\n' ) && ( *s != ';' ) && ( x1 < maxx ) )
|
||||
x1 += Touch_DrawCharacter( x1, y1, *s++, size );
|
||||
y1 += cls.creditsFont.charHeight / 1024.f * size / SCR_H * SCR_W;
|
||||
y1 += cls.creditsFont.charHeight / 1024.f * size / Touch_AspectRatio();
|
||||
|
||||
if( y1 >= maxy )
|
||||
break;
|
||||
|
@ -1305,10 +1360,10 @@ static void Touch_DrawButtons( touchbuttonlist_t *list )
|
|||
|
||||
if( ( B( finger ) != -1 ) && !FBitSet( B( flags ), TOUCH_FL_CLIENT ) )
|
||||
{
|
||||
color[0] = bound( 0,(float) color[0] * touch_highlight_r->value, 255 );
|
||||
color[1] = bound( 0,(float) color[1] * touch_highlight_g->value, 255 );
|
||||
color[2] = bound( 0,(float) color[2] * touch_highlight_b->value, 255 );
|
||||
color[3] = bound( 0,(float) color[3] * touch_highlight_a->value, 255 );
|
||||
color[0] = bound( 0,(float) color[0] * touch_highlight_r.value, 255 );
|
||||
color[1] = bound( 0,(float) color[1] * touch_highlight_g.value, 255 );
|
||||
color[2] = bound( 0,(float) color[2] * touch_highlight_b.value, 255 );
|
||||
color[3] = bound( 0,(float) color[3] * touch_highlight_a.value, 255 );
|
||||
}
|
||||
|
||||
color[3] *= B( fade );
|
||||
|
@ -1372,20 +1427,21 @@ void Touch_Draw( void )
|
|||
{
|
||||
touch_button_t *button;
|
||||
|
||||
if( !touch.initialized || (!CVAR_TO_BOOL(touch_enable) && !touch.clientonly) )
|
||||
if( !touch.initialized || ( !touch_enable.value && !touch.clientonly ))
|
||||
return;
|
||||
|
||||
if( cls.key_dest != key_game && !touch_in_menu.value )
|
||||
return;
|
||||
|
||||
Touch_InitConfig();
|
||||
|
||||
if( cls.key_dest != key_game && !CVAR_TO_BOOL(touch_in_menu) )
|
||||
return;
|
||||
|
||||
ref.dllFuncs.GL_SetRenderMode( kRenderTransTexture );
|
||||
|
||||
if( touch.state >= state_edit && CVAR_TO_BOOL(touch_grid_enable) )
|
||||
if( touch.state >= state_edit && touch_grid_enable.value )
|
||||
{
|
||||
float x;
|
||||
if( CVAR_TO_BOOL(touch_in_menu) )
|
||||
if( touch_in_menu.value )
|
||||
Touch_DrawTexture( 0, 0, 1, 1, touch.whitetexture, 32, 32, 32, 255 );
|
||||
else
|
||||
Touch_DrawTexture( 0, 0, 1, 1, touch.whitetexture, 0, 0, 0, 112 );
|
||||
|
@ -1446,19 +1502,19 @@ void Touch_Draw( void )
|
|||
|
||||
ref.dllFuncs.Color4ub( 255, 255, 255, 255 );
|
||||
|
||||
if( ( touch.move_finger != -1 ) && touch.move_button && touch_move_indicator->value )
|
||||
if( ( touch.move_finger != -1 ) && touch.move_button && touch_move_indicator.value )
|
||||
{
|
||||
float width;
|
||||
float height;
|
||||
if( FBitSet( touch_joy_texture->flags, FCVAR_CHANGED ) )
|
||||
if( FBitSet( touch_joy_texture.flags, FCVAR_CHANGED ) )
|
||||
{
|
||||
ClearBits( touch_joy_texture->flags, FCVAR_CHANGED );
|
||||
touch.joytexture = ref.dllFuncs.GL_LoadTexture( touch_joy_texture->string, NULL, 0, TF_NOMIPMAP );
|
||||
ClearBits( touch_joy_texture.flags, FCVAR_CHANGED );
|
||||
touch.joytexture = ref.dllFuncs.GL_LoadTexture( touch_joy_texture.string, NULL, 0, TF_NOMIPMAP );
|
||||
}
|
||||
if( touch.move_button->type == touch_move )
|
||||
{
|
||||
width = touch_sidezone->value;
|
||||
height = touch_forwardzone->value;
|
||||
width = touch_sidezone.value;
|
||||
height = touch_forwardzone.value;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1466,13 +1522,13 @@ void Touch_Draw( void )
|
|||
height = (touch.move_button->y2 - touch.move_button->y1)/2;
|
||||
}
|
||||
ref.dllFuncs.Color4ub( 255, 255, 255, 128 );
|
||||
ref.dllFuncs.R_DrawStretchPic( TO_SCRN_X( touch.move_start_x - GRID_X * touch_move_indicator->value ),
|
||||
TO_SCRN_Y( touch.move_start_y - GRID_Y * touch_move_indicator->value ),
|
||||
TO_SCRN_X( GRID_X * 2 * touch_move_indicator->value ), TO_SCRN_Y( GRID_Y * 2 * touch_move_indicator->value ), 0, 0, 1, 1, touch.joytexture );
|
||||
ref.dllFuncs.R_DrawStretchPic( TO_SCRN_X( touch.move_start_x - GRID_X * touch_move_indicator.value ),
|
||||
TO_SCRN_Y( touch.move_start_y - GRID_Y * touch_move_indicator.value ),
|
||||
TO_SCRN_X( GRID_X * 2 * touch_move_indicator.value ), TO_SCRN_Y( GRID_Y * 2 * touch_move_indicator.value ), 0, 0, 1, 1, touch.joytexture );
|
||||
ref.dllFuncs.Color4ub( 255, 255, 255, 255 );
|
||||
ref.dllFuncs.R_DrawStretchPic( TO_SCRN_X( touch.move_start_x + touch.side * width - GRID_X * touch_move_indicator->value ),
|
||||
TO_SCRN_Y( touch.move_start_y - touch.forward * height - GRID_Y * touch_move_indicator->value ),
|
||||
TO_SCRN_X( GRID_X * 2 * touch_move_indicator->value ), TO_SCRN_Y( GRID_Y * 2 * touch_move_indicator->value ), 0, 0, 1, 1, touch.joytexture );
|
||||
ref.dllFuncs.R_DrawStretchPic( TO_SCRN_X( touch.move_start_x + touch.side * width - GRID_X * touch_move_indicator.value ),
|
||||
TO_SCRN_Y( touch.move_start_y - touch.forward * height - GRID_Y * touch_move_indicator.value ),
|
||||
TO_SCRN_X( GRID_X * 2 * touch_move_indicator.value ), TO_SCRN_Y( GRID_Y * 2 * touch_move_indicator.value ), 0, 0, 1, 1, touch.joytexture );
|
||||
|
||||
}
|
||||
|
||||
|
@ -1515,9 +1571,9 @@ static void Touch_EditMove( touchEventType type, int fingerID, float x, float y,
|
|||
touch.hidebutton->flags &= ~TOUCH_FL_HIDE;
|
||||
|
||||
if( FBitSet( button->flags, TOUCH_FL_HIDE ))
|
||||
Q_strcpy( touch.hidebutton->texturefile, "touch_default/edit_show.tga" );
|
||||
Q_strncpy( touch.hidebutton->texturefile, "touch_default/edit_show", sizeof( touch.hidebutton->texturefile ));
|
||||
else
|
||||
Q_strcpy( touch.hidebutton->texturefile, "touch_default/edit_hide.tga" );
|
||||
Q_strncpy( touch.hidebutton->texturefile, "touch_default/edit_hide", sizeof( touch.hidebutton->texturefile ));
|
||||
}
|
||||
}
|
||||
if( type == event_motion ) // shutdown button move
|
||||
|
@ -1581,28 +1637,28 @@ static void Touch_Motion( touchEventType type, int fingerID, float x, float y, f
|
|||
if( fingerID == touch.move_finger )
|
||||
{
|
||||
// check bounds
|
||||
if( touch_forwardzone->value <= 0 )
|
||||
if( touch_forwardzone.value <= 0 )
|
||||
Cvar_SetValue( "touch_forwardzone", 0.5 );
|
||||
if( touch_sidezone->value <= 0 )
|
||||
if( touch_sidezone.value <= 0 )
|
||||
Cvar_SetValue( "touch_sidezone", 0.3 );
|
||||
|
||||
if( !touch.move_button || touch.move_button->type == touch_move )
|
||||
{
|
||||
// move relative to touch start
|
||||
touch.forward = ( touch.move_start_y - y ) / touch_forwardzone->value;
|
||||
touch.side = ( x - touch.move_start_x ) / touch_sidezone->value;
|
||||
touch.forward = ( touch.move_start_y - y ) / touch_forwardzone.value;
|
||||
touch.side = ( x - touch.move_start_x ) / touch_sidezone.value;
|
||||
}
|
||||
else if( touch.move_button->type == touch_joy )
|
||||
{
|
||||
// move relative to joy center
|
||||
touch.forward = ( ( touch.move_button->y2 + touch.move_button->y1 ) - y * 2 ) / ( touch.move_button->y2 - touch.move_button->y1 ) * touch_joy_radius->value;
|
||||
touch.side = ( x * 2 - ( touch.move_button->x2 + touch.move_button->x1 ) ) / ( touch.move_button->x2 - touch.move_button->x1 ) * touch_joy_radius->value;
|
||||
touch.forward = ( ( touch.move_button->y2 + touch.move_button->y1 ) - y * 2 ) / ( touch.move_button->y2 - touch.move_button->y1 ) * touch_joy_radius.value;
|
||||
touch.side = ( x * 2 - ( touch.move_button->x2 + touch.move_button->x1 ) ) / ( touch.move_button->x2 - touch.move_button->x1 ) * touch_joy_radius.value;
|
||||
}
|
||||
else if( touch.move_button->type == touch_dpad )
|
||||
{
|
||||
// like joy, but without acceleration. useful for bhop
|
||||
touch.forward = round( ( (touch.move_button->y2 + touch.move_button->y1) - y * 2 ) / ( touch.move_button->y2 - touch.move_button->y1 ) * touch_dpad_radius->value );
|
||||
touch.side = round( ( x * 2 - (touch.move_button->x2 + touch.move_button->x1) ) / ( touch.move_button->x2 - touch.move_button->x1 ) * touch_dpad_radius->value );
|
||||
touch.forward = round( ( (touch.move_button->y2 + touch.move_button->y1) - y * 2 ) / ( touch.move_button->y2 - touch.move_button->y1 ) * touch_dpad_radius.value );
|
||||
touch.side = round( ( x * 2 - (touch.move_button->x2 + touch.move_button->x1) ) / ( touch.move_button->x2 - touch.move_button->x1 ) * touch_dpad_radius.value );
|
||||
}
|
||||
|
||||
touch.forward = bound( -1, touch.forward, 1 );
|
||||
|
@ -1613,9 +1669,9 @@ static void Touch_Motion( touchEventType type, int fingerID, float x, float y, f
|
|||
if( fingerID == touch.look_finger )
|
||||
{
|
||||
if( touch.precision )
|
||||
dx *= touch_precise_amount->value, dy *= touch_precise_amount->value;
|
||||
dx *= touch_precise_amount.value, dy *= touch_precise_amount.value;
|
||||
|
||||
if( CVAR_TO_BOOL(touch_nonlinear_look) )
|
||||
if( touch_nonlinear_look.value )
|
||||
{
|
||||
float dabs, dcos, dsin;
|
||||
|
||||
|
@ -1628,11 +1684,11 @@ static void Touch_Motion( touchEventType type, int fingerID, float x, float y, f
|
|||
dcos = dx / dabs;
|
||||
dsin = dy / dabs;
|
||||
|
||||
if( touch_exp_mult->value > 1 )
|
||||
dabs = ( exp( dabs * touch_exp_mult->value ) - 1 ) / touch_exp_mult->value;
|
||||
if( touch_exp_mult.value > 1 )
|
||||
dabs = ( exp( dabs * touch_exp_mult.value ) - 1 ) / touch_exp_mult.value;
|
||||
|
||||
if( touch_pow_mult->value > 1 && touch_pow_factor->value > 1 )
|
||||
dabs = pow( dabs * touch_pow_mult->value, touch_pow_factor->value ) / touch_pow_mult->value;
|
||||
if( touch_pow_mult.value > 1 && touch_pow_factor.value > 1 )
|
||||
dabs = pow( dabs * touch_pow_mult.value, touch_pow_factor.value ) / touch_pow_mult.value;
|
||||
|
||||
dx = dabs * dcos;
|
||||
dy = dabs * dsin;
|
||||
|
@ -1643,7 +1699,7 @@ static void Touch_Motion( touchEventType type, int fingerID, float x, float y, f
|
|||
return;
|
||||
|
||||
// accumulate
|
||||
touch.yaw -= dx * touch_yaw->value, touch.pitch += dy * touch_pitch->value;
|
||||
touch.yaw -= dx * touch_yaw.value, touch.pitch += dy * touch_pitch.value;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1966,15 +2022,17 @@ static int Touch_ControlsEvent( touchEventType type, int fingerID, float x, floa
|
|||
|
||||
int IN_TouchEvent( touchEventType type, int fingerID, float x, float y, float dx, float dy )
|
||||
{
|
||||
|
||||
y *= SCR_H/SCR_W/Touch_AspectRatio();
|
||||
// Con_Printf("%f %f\n", TO_SCRN_X(x), TO_SCRN_Y(y));
|
||||
// simulate menu mouse click
|
||||
if( cls.key_dest != key_game && !CVAR_TO_BOOL(touch_in_menu) )
|
||||
if( cls.key_dest != key_game && !touch_in_menu.value )
|
||||
{
|
||||
touch.move_finger = touch.resize_finger = touch.look_finger = -1;
|
||||
// Hack for keyboard, hope it help
|
||||
if( cls.key_dest == key_console || cls.key_dest == key_message )
|
||||
{
|
||||
Key_EnableTextInput( true, true );
|
||||
if ( type == event_down ) // don't pop it again on event_up
|
||||
Key_EnableTextInput( true, true );
|
||||
if( cls.key_dest == key_console )
|
||||
{
|
||||
static float y1 = 0;
|
||||
|
@ -2011,25 +2069,20 @@ int IN_TouchEvent( touchEventType type, int fingerID, float x, float y, float dx
|
|||
{
|
||||
VGui_MouseMove( TO_SCRN_X(x), TO_SCRN_Y(y) );
|
||||
|
||||
if( type != event_motion )
|
||||
VGui_KeyEvent( K_MOUSE1, type == event_down ? 1 : 0 );
|
||||
|
||||
// allow scoreboard scroll
|
||||
if( host.mouse_visible && type == event_motion )
|
||||
return 0;
|
||||
switch( type )
|
||||
{
|
||||
case event_down:
|
||||
VGui_MouseEvent( K_MOUSE1, 1 );
|
||||
break;
|
||||
case event_up:
|
||||
VGui_MouseEvent( K_MOUSE1, 0 );
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
if( !touch.initialized || (!CVAR_TO_BOOL(touch_enable) && !touch.clientonly) )
|
||||
{
|
||||
#if 0
|
||||
if( type == event_down )
|
||||
Key_Event( K_MOUSE1, true );
|
||||
if( type == event_up )
|
||||
Key_Event( K_MOUSE1, false );
|
||||
Android_AddMove( dx * (float)refState.width, dy * (float)refState.height );
|
||||
#endif
|
||||
if( !touch.initialized || ( !touch_enable.value && !touch.clientonly ))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( clgame.dllFuncs.pfnTouchEvent && clgame.dllFuncs.pfnTouchEvent( type, fingerID, x, y, dx, dy ) )
|
||||
return true;
|
||||
|
@ -2048,35 +2101,65 @@ void Touch_GetMove( float *forward, float *side, float *yaw, float *pitch )
|
|||
|
||||
void Touch_KeyEvent( int key, int down )
|
||||
{
|
||||
int xi, yi;
|
||||
float x, y;
|
||||
static float lx, ly;
|
||||
static int kidNamedFinger = -1;
|
||||
touchEventType event;
|
||||
float x, y;
|
||||
int finger, xi, yi;
|
||||
|
||||
if( !CVAR_TO_BOOL(touch_emulate) )
|
||||
if( !touch_emulate.value )
|
||||
{
|
||||
if( CVAR_TO_BOOL(touch_enable) )
|
||||
if( touch_enable.value )
|
||||
return;
|
||||
|
||||
if( !touch.clientonly )
|
||||
return;
|
||||
}
|
||||
|
||||
Platform_GetMousePos( &xi, &yi );
|
||||
|
||||
x = xi/SCR_W;
|
||||
y = yi/SCR_H;
|
||||
|
||||
if( cls.key_dest == key_menu && down < 2 && key == K_MOUSE1 )
|
||||
if( !key )
|
||||
{
|
||||
UI_MouseMove( xi, yi );
|
||||
UI_KeyEvent( key, down );
|
||||
if( kidNamedFinger < 0 )
|
||||
return;
|
||||
|
||||
finger = kidNamedFinger;
|
||||
event = event_motion;
|
||||
}
|
||||
else
|
||||
{
|
||||
finger = key == K_MOUSE1 ? 0 : 1;
|
||||
if( down )
|
||||
{
|
||||
event = event_down;
|
||||
kidNamedFinger = finger;
|
||||
}
|
||||
else
|
||||
{
|
||||
event = event_up;
|
||||
kidNamedFinger = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if( down == 1 )
|
||||
Touch_ControlsEvent( event_down, key == K_MOUSE1?0:1, x, y, 0, 0 );
|
||||
else
|
||||
Touch_ControlsEvent( down? event_motion: event_up, key == K_MOUSE1?0:1, x, y, x-lx, y-ly );
|
||||
lx = x, ly = y;
|
||||
// don't deactivate mouse in game
|
||||
// checking a case when mouse and touchscreen
|
||||
// can be used simultaneously
|
||||
Platform_SetCursorType( dc_arrow );
|
||||
Platform_GetMousePos( &xi, &yi );
|
||||
|
||||
x = xi / SCR_W;
|
||||
y = yi / SCR_H;
|
||||
|
||||
Con_DPrintf( "event %d %.2f %.2f %.2f %.2f\n",
|
||||
event, x, y, x - lx, y - ly );
|
||||
|
||||
IN_TouchEvent( event, finger, x, y, x - lx, y - ly );
|
||||
|
||||
lx = x;
|
||||
ly = y;
|
||||
}
|
||||
|
||||
qboolean Touch_WantVisibleCursor( void )
|
||||
{
|
||||
return ( touch_enable.value && touch_emulate.value ) || touch.clientonly;
|
||||
}
|
||||
|
||||
void Touch_Shutdown( void )
|
||||
|
|
|
@ -36,18 +36,15 @@ static struct inputstate_s
|
|||
float lastpitch, lastyaw;
|
||||
} inputstate;
|
||||
|
||||
extern convar_t *vid_fullscreen;
|
||||
convar_t *m_pitch;
|
||||
convar_t *m_yaw;
|
||||
CVAR_DEFINE_AUTO( m_pitch, "0.022", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "mouse pitch value" );
|
||||
CVAR_DEFINE_AUTO( m_yaw, "0.022", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "mouse yaw value" );
|
||||
CVAR_DEFINE_AUTO( m_ignore, DEFAULT_M_IGNORE, FCVAR_ARCHIVE | FCVAR_FILTERABLE, "ignore mouse events" );
|
||||
static CVAR_DEFINE_AUTO( look_filter, "0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "filter look events making it smoother" );
|
||||
static CVAR_DEFINE_AUTO( m_rawinput, "1", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "enable mouse raw input" );
|
||||
|
||||
convar_t *m_ignore;
|
||||
convar_t *cl_forwardspeed;
|
||||
convar_t *cl_sidespeed;
|
||||
convar_t *cl_backspeed;
|
||||
convar_t *look_filter;
|
||||
convar_t *m_rawinput;
|
||||
|
||||
static qboolean s_bRawInput, s_bMouseGrab;
|
||||
static CVAR_DEFINE_AUTO( cl_forwardspeed, "400", FCVAR_ARCHIVE | FCVAR_CLIENTDLL | FCVAR_FILTERABLE, "Default forward move speed" );
|
||||
static CVAR_DEFINE_AUTO( cl_backspeed, "400", FCVAR_ARCHIVE | FCVAR_CLIENTDLL | FCVAR_FILTERABLE, "Default back move speed" );
|
||||
static CVAR_DEFINE_AUTO( cl_sidespeed, "400", FCVAR_ARCHIVE | FCVAR_CLIENTDLL | FCVAR_FILTERABLE, "Default side move speed" );
|
||||
|
||||
/*
|
||||
================
|
||||
|
@ -60,10 +57,10 @@ uint IN_CollectInputDevices( void )
|
|||
{
|
||||
uint ret = 0;
|
||||
|
||||
if( !m_ignore->value ) // no way to check is mouse connected, so use cvar only
|
||||
if( !m_ignore.value ) // no way to check is mouse connected, so use cvar only
|
||||
ret |= INPUT_DEVICE_MOUSE;
|
||||
|
||||
if( CVAR_TO_BOOL(touch_enable) )
|
||||
if( touch_enable.value )
|
||||
ret |= INPUT_DEVICE_TOUCH;
|
||||
|
||||
if( Joy_IsActive() ) // connected or enabled
|
||||
|
@ -88,19 +85,19 @@ player is connected to the server
|
|||
*/
|
||||
void IN_LockInputDevices( qboolean lock )
|
||||
{
|
||||
extern convar_t *joy_enable; // private to input system
|
||||
extern convar_t joy_enable; // private to input system
|
||||
|
||||
if( lock )
|
||||
{
|
||||
SetBits( m_ignore->flags, FCVAR_READ_ONLY );
|
||||
SetBits( joy_enable->flags, FCVAR_READ_ONLY );
|
||||
SetBits( touch_enable->flags, FCVAR_READ_ONLY );
|
||||
SetBits( m_ignore.flags, FCVAR_READ_ONLY );
|
||||
SetBits( joy_enable.flags, FCVAR_READ_ONLY );
|
||||
SetBits( touch_enable.flags, FCVAR_READ_ONLY );
|
||||
}
|
||||
else
|
||||
{
|
||||
ClearBits( m_ignore->flags, FCVAR_READ_ONLY );
|
||||
ClearBits( joy_enable->flags, FCVAR_READ_ONLY );
|
||||
ClearBits( touch_enable->flags, FCVAR_READ_ONLY );
|
||||
ClearBits( m_ignore.flags, FCVAR_READ_ONLY );
|
||||
ClearBits( joy_enable.flags, FCVAR_READ_ONLY );
|
||||
ClearBits( touch_enable.flags, FCVAR_READ_ONLY );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -112,12 +109,12 @@ IN_StartupMouse
|
|||
*/
|
||||
void IN_StartupMouse( void )
|
||||
{
|
||||
m_ignore = Cvar_Get( "m_ignore", DEFAULT_M_IGNORE, FCVAR_ARCHIVE | FCVAR_FILTERABLE, "ignore mouse events" );
|
||||
Cvar_RegisterVariable( &m_ignore );
|
||||
|
||||
m_pitch = Cvar_Get( "m_pitch", "0.022", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "mouse pitch value" );
|
||||
m_yaw = Cvar_Get( "m_yaw", "0.022", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "mouse yaw value" );
|
||||
look_filter = Cvar_Get( "look_filter", "0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "filter look events making it smoother" );
|
||||
m_rawinput = Cvar_Get( "m_rawinput", "1", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "enable mouse raw input" );
|
||||
Cvar_RegisterVariable( &m_pitch );
|
||||
Cvar_RegisterVariable( &m_yaw );
|
||||
Cvar_RegisterVariable( &look_filter );
|
||||
Cvar_RegisterVariable( &m_rawinput );
|
||||
|
||||
// You can use -nomouse argument to prevent using mouse from client
|
||||
// -noenginemouse will disable all mouse input
|
||||
|
@ -173,7 +170,29 @@ Called when key_dest is changed
|
|||
*/
|
||||
void IN_ToggleClientMouse( int newstate, int oldstate )
|
||||
{
|
||||
if( newstate == oldstate ) return;
|
||||
if( newstate == oldstate )
|
||||
return;
|
||||
if( m_ignore.value )
|
||||
return;
|
||||
|
||||
// since SetCursorType controls cursor visibility
|
||||
// execute it first, and then check mouse grab state
|
||||
if( newstate == key_menu || newstate == key_console )
|
||||
{
|
||||
Platform_SetCursorType( dc_arrow );
|
||||
|
||||
#if XASH_USE_EVDEV
|
||||
Evdev_SetGrab( false );
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
Platform_SetCursorType( dc_none );
|
||||
|
||||
#if XASH_USE_EVDEV
|
||||
Evdev_SetGrab( true );
|
||||
#endif
|
||||
}
|
||||
|
||||
if( oldstate == key_game )
|
||||
{
|
||||
|
@ -183,35 +202,21 @@ void IN_ToggleClientMouse( int newstate, int oldstate )
|
|||
{
|
||||
IN_ActivateMouse();
|
||||
}
|
||||
|
||||
if( ( newstate == key_menu || newstate == key_console || newstate == key_message ) && ( !CL_IsBackgroundMap() || CL_IsBackgroundDemo( )))
|
||||
{
|
||||
#if XASH_ANDROID
|
||||
Android_ShowMouse( true );
|
||||
#endif
|
||||
#ifdef XASH_USE_EVDEV
|
||||
Evdev_SetGrab( false );
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#if XASH_ANDROID
|
||||
Android_ShowMouse( false );
|
||||
#endif
|
||||
#ifdef XASH_USE_EVDEV
|
||||
Evdev_SetGrab( true );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void IN_CheckMouseState( qboolean active )
|
||||
{
|
||||
static qboolean s_bRawInput, s_bMouseGrab;
|
||||
|
||||
#if XASH_WIN32
|
||||
qboolean useRawInput = CVAR_TO_BOOL( m_rawinput ) && clgame.client_dll_uses_sdl || clgame.dllFuncs.pfnLookEvent;
|
||||
qboolean useRawInput = ( m_rawinput.value && clgame.client_dll_uses_sdl ) || clgame.dllFuncs.pfnLookEvent != NULL;
|
||||
#else
|
||||
qboolean useRawInput = true; // always use SDL code
|
||||
#endif
|
||||
|
||||
if( m_ignore.value )
|
||||
return;
|
||||
|
||||
if( active && useRawInput && !host.mouse_visible && cls.state == ca_active )
|
||||
{
|
||||
if( !s_bRawInput )
|
||||
|
@ -308,25 +313,25 @@ IN_MouseMove
|
|||
*/
|
||||
void IN_MouseMove( void )
|
||||
{
|
||||
POINT current_pos;
|
||||
int x, y;
|
||||
|
||||
if( !in_mouseinitialized )
|
||||
return;
|
||||
|
||||
if( touch_emulate.value )
|
||||
{
|
||||
// touch emulation overrides all input
|
||||
Touch_KeyEvent( 0, 0 );
|
||||
return;
|
||||
}
|
||||
|
||||
// find mouse movement
|
||||
Platform_GetMousePos( ¤t_pos.x, ¤t_pos.y );
|
||||
Platform_GetMousePos( &x, &y );
|
||||
|
||||
VGui_MouseMove( current_pos.x, current_pos.y );
|
||||
|
||||
// HACKHACK: show cursor in UI, as mainui doesn't call
|
||||
// platform-dependent SetCursor anymore
|
||||
#if XASH_SDL
|
||||
if( UI_IsVisible() )
|
||||
SDL_ShowCursor( SDL_TRUE );
|
||||
#endif
|
||||
VGui_MouseMove( x, y );
|
||||
|
||||
// if the menu is visible, move the menu cursor
|
||||
UI_MouseMove( current_pos.x, current_pos.y );
|
||||
UI_MouseMove( x, y );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -336,8 +341,6 @@ IN_MouseEvent
|
|||
*/
|
||||
void IN_MouseEvent( int key, int down )
|
||||
{
|
||||
int i;
|
||||
|
||||
if( !in_mouseinitialized )
|
||||
return;
|
||||
|
||||
|
@ -345,10 +348,15 @@ void IN_MouseEvent( int key, int down )
|
|||
SetBits( in_mstate, BIT( key ));
|
||||
else ClearBits( in_mstate, BIT( key ));
|
||||
|
||||
if( cls.key_dest == key_game )
|
||||
// touch emulation overrides all input
|
||||
if( touch_emulate.value )
|
||||
{
|
||||
Touch_KeyEvent( K_MOUSE1 + key, down );
|
||||
}
|
||||
else if( cls.key_dest == key_game )
|
||||
{
|
||||
// perform button actions
|
||||
VGui_KeyEvent( K_MOUSE1 + key, down );
|
||||
VGui_MouseEvent( K_MOUSE1 + key, down );
|
||||
|
||||
// don't do Key_Event here
|
||||
// client may override IN_MouseEvent
|
||||
|
@ -363,6 +371,23 @@ void IN_MouseEvent( int key, int down )
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
IN_MWheelEvent
|
||||
|
||||
direction is negative for wheel down, otherwise wheel up
|
||||
==============
|
||||
*/
|
||||
void IN_MWheelEvent( int y )
|
||||
{
|
||||
int b = y > 0 ? K_MWHEELUP : K_MWHEELDOWN;
|
||||
|
||||
VGui_MWheelEvent( y );
|
||||
|
||||
Key_Event( b, true );
|
||||
Key_Event( b, false );
|
||||
}
|
||||
|
||||
/*
|
||||
===========
|
||||
IN_Shutdown
|
||||
|
@ -372,7 +397,7 @@ void IN_Shutdown( void )
|
|||
{
|
||||
IN_DeactivateMouse( );
|
||||
|
||||
#ifdef XASH_USE_EVDEV
|
||||
#if XASH_USE_EVDEV
|
||||
Evdev_Shutdown();
|
||||
#endif
|
||||
|
||||
|
@ -387,9 +412,9 @@ IN_Init
|
|||
*/
|
||||
void IN_Init( void )
|
||||
{
|
||||
cl_forwardspeed = Cvar_Get( "cl_forwardspeed", "400", FCVAR_ARCHIVE | FCVAR_CLIENTDLL | FCVAR_FILTERABLE, "Default forward move speed" );
|
||||
cl_backspeed = Cvar_Get( "cl_backspeed", "400", FCVAR_ARCHIVE | FCVAR_CLIENTDLL | FCVAR_FILTERABLE, "Default back move speed" );
|
||||
cl_sidespeed = Cvar_Get( "cl_sidespeed", "400", FCVAR_ARCHIVE | FCVAR_CLIENTDLL | FCVAR_FILTERABLE, "Default side move speed" );
|
||||
Cvar_RegisterVariable( &cl_forwardspeed );
|
||||
Cvar_RegisterVariable( &cl_backspeed );
|
||||
Cvar_RegisterVariable( &cl_sidespeed );
|
||||
|
||||
if( !Host_IsDedicated() )
|
||||
{
|
||||
|
@ -399,7 +424,7 @@ void IN_Init( void )
|
|||
|
||||
Touch_Init();
|
||||
|
||||
#ifdef XASH_USE_EVDEV
|
||||
#if XASH_USE_EVDEV
|
||||
Evdev_Init();
|
||||
#endif
|
||||
}
|
||||
|
@ -426,8 +451,8 @@ static void IN_JoyAppendMove( usercmd_t *cmd, float forwardmove, float sidemove
|
|||
{
|
||||
static uint moveflags = T | S;
|
||||
|
||||
if( forwardmove ) cmd->forwardmove = forwardmove * cl_forwardspeed->value;
|
||||
if( sidemove ) cmd->sidemove = sidemove * cl_sidespeed->value;
|
||||
if( forwardmove ) cmd->forwardmove = forwardmove * cl_forwardspeed.value;
|
||||
if( sidemove ) cmd->sidemove = sidemove * cl_sidespeed.value;
|
||||
|
||||
if( forwardmove )
|
||||
{
|
||||
|
@ -502,10 +527,10 @@ static void IN_CollectInput( float *forward, float *side, float *pitch, float *y
|
|||
{
|
||||
float x, y;
|
||||
Platform_MouseMove( &x, &y );
|
||||
*pitch += y * m_pitch->value;
|
||||
*yaw -= x * m_yaw->value;
|
||||
*pitch += y * m_pitch.value;
|
||||
*yaw -= x * m_yaw.value;
|
||||
|
||||
#ifdef XASH_USE_EVDEV
|
||||
#if XASH_USE_EVDEV
|
||||
IN_EvdevMove( yaw, pitch );
|
||||
#endif
|
||||
}
|
||||
|
@ -513,7 +538,7 @@ static void IN_CollectInput( float *forward, float *side, float *pitch, float *y
|
|||
Joy_FinalizeMove( forward, side, yaw, pitch );
|
||||
Touch_GetMove( forward, side, yaw, pitch );
|
||||
|
||||
if( look_filter->value )
|
||||
if( look_filter.value )
|
||||
{
|
||||
*pitch = ( inputstate.lastpitch + *pitch ) / 2;
|
||||
*yaw = ( inputstate.lastyaw + *yaw ) / 2;
|
||||
|
@ -563,7 +588,7 @@ void IN_EngineAppendMove( float frametime, void *cmd1, qboolean active )
|
|||
|
||||
void IN_Commands( void )
|
||||
{
|
||||
#ifdef XASH_USE_EVDEV
|
||||
#if XASH_USE_EVDEV
|
||||
IN_EvdevFrame();
|
||||
#endif
|
||||
|
||||
|
@ -571,7 +596,7 @@ void IN_Commands( void )
|
|||
{
|
||||
float forward = 0, side = 0, pitch = 0, yaw = 0;
|
||||
|
||||
IN_CollectInput( &forward, &side, &pitch, &yaw, in_mouseinitialized && !CVAR_TO_BOOL( m_ignore ) );
|
||||
IN_CollectInput( &forward, &side, &pitch, &yaw, in_mouseinitialized && !m_ignore.value );
|
||||
|
||||
if( cls.key_dest == key_game )
|
||||
{
|
||||
|
|
|
@ -34,6 +34,7 @@ void IN_Init( void );
|
|||
void Host_InputFrame( void );
|
||||
void IN_Shutdown( void );
|
||||
void IN_MouseEvent( int key, int down );
|
||||
void IN_MWheelEvent( int direction );
|
||||
void IN_ActivateMouse( void );
|
||||
void IN_DeactivateMouse( void );
|
||||
void IN_MouseSavePos( void );
|
||||
|
@ -45,8 +46,8 @@ uint IN_CollectInputDevices( void );
|
|||
void IN_LockInputDevices( qboolean lock );
|
||||
void IN_EngineAppendMove( float frametime, void *cmd, qboolean active );
|
||||
|
||||
extern convar_t *m_yaw;
|
||||
extern convar_t *m_pitch;
|
||||
extern convar_t m_yaw;
|
||||
extern convar_t m_pitch;
|
||||
//
|
||||
// in_touch.c
|
||||
//
|
||||
|
@ -57,8 +58,8 @@ typedef enum
|
|||
event_motion
|
||||
} touchEventType;
|
||||
|
||||
extern convar_t *touch_enable;
|
||||
extern convar_t *touch_emulate;
|
||||
extern convar_t touch_enable;
|
||||
extern convar_t touch_emulate;
|
||||
|
||||
void Touch_Draw( void );
|
||||
void Touch_SetClientOnly( byte state );
|
||||
|
@ -73,6 +74,8 @@ void Touch_GetMove( float * forward, float *side, float *yaw, float *pitch );
|
|||
void Touch_ResetDefaultButtons( void );
|
||||
int IN_TouchEvent( touchEventType type, int fingerID, float x, float y, float dx, float dy );
|
||||
void Touch_KeyEvent( int key, int down );
|
||||
qboolean Touch_WantVisibleCursor( void );
|
||||
void Touch_NotifyResize( void );
|
||||
|
||||
//
|
||||
// in_joy.c
|
||||
|
|
|
@ -104,9 +104,9 @@ keyname_t keynames[] =
|
|||
{"B_BUTTON", K_B_BUTTON, "+use"},
|
||||
{"X_BUTTON", K_X_BUTTON, "+reload"},
|
||||
{"Y_BUTTON", K_Y_BUTTON, "impulse 100"}, // Flashlight
|
||||
{"BACK", K_BACK_BUTTON, "cancelselect"}, // Menu
|
||||
{"BACK", K_BACK_BUTTON, "pause"}, // Menu
|
||||
{"MODE", K_MODE_BUTTON, ""},
|
||||
{"START", K_START_BUTTON, "pause"},
|
||||
{"START", K_START_BUTTON, "escape"},
|
||||
{"STICK1", K_LSTICK, "+speed"},
|
||||
{"STICK2", K_RSTICK, "+duck"},
|
||||
{"L1_BUTTON", K_L1_BUTTON, "+duck"},
|
||||
|
@ -123,13 +123,13 @@ keyname_t keynames[] =
|
|||
{"JOY4" , K_JOY4 , ""},
|
||||
{"C_BUTTON", K_C_BUTTON, ""},
|
||||
{"Z_BUTTON", K_Z_BUTTON, ""},
|
||||
{"AUX20", K_AUX20, ""}, // generic
|
||||
{"AUX21", K_AUX21, ""},
|
||||
{"AUX22", K_AUX22, ""},
|
||||
{"AUX23", K_AUX23, ""},
|
||||
{"AUX24", K_AUX24, ""},
|
||||
{"AUX25", K_AUX25, ""},
|
||||
{"AUX26", K_AUX26, ""},
|
||||
{"MISC_BUTTON", K_MISC_BUTTON, ""},
|
||||
{"PADDLE1", K_PADDLE1_BUTTON, ""},
|
||||
{"PADDLE2", K_PADDLE2_BUTTON, ""},
|
||||
{"PADDLE3", K_PADDLE3_BUTTON, ""},
|
||||
{"PADDLE4", K_PADDLE4_BUTTON, ""},
|
||||
{"TOUCHPAD", K_TOUCHPAD, ""},
|
||||
{"AUX26", K_AUX26, ""}, // generic
|
||||
{"AUX27", K_AUX27, ""},
|
||||
{"AUX28", K_AUX28, ""},
|
||||
{"AUX29", K_AUX29, ""},
|
||||
|
@ -144,8 +144,8 @@ keyname_t keynames[] =
|
|||
|
||||
static void OSK_EnableTextInput( qboolean enable, qboolean force );
|
||||
static qboolean OSK_KeyEvent( int key, int down );
|
||||
static convar_t *osk_enable;
|
||||
static convar_t *key_rotate;
|
||||
static CVAR_DEFINE_AUTO( osk_enable, "0", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "enable built-in on-screen keyboard" );
|
||||
static CVAR_DEFINE_AUTO( key_rotate, "0", FCVAR_ARCHIVE|FCVAR_FILTERABLE, "rotate arrow keys (0-3)" );
|
||||
|
||||
/*
|
||||
===================
|
||||
|
@ -159,18 +159,6 @@ int GAME_EXPORT Key_IsDown( int keynum )
|
|||
return keys[keynum].down;
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
Key_GetBind
|
||||
===================
|
||||
*/
|
||||
const char *Key_IsBind( int keynum )
|
||||
{
|
||||
if( keynum == -1 || !keys[keynum].binding )
|
||||
return NULL;
|
||||
return keys[keynum].binding;
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
Key_StringToKeynum
|
||||
|
@ -374,7 +362,7 @@ void Key_Unbindall_f( void )
|
|||
{
|
||||
int i;
|
||||
|
||||
for( i = 0; i < 256; i++ )
|
||||
for( i = 0; i < ARRAYSIZE( keys ); i++ )
|
||||
{
|
||||
if( keys[i].binding )
|
||||
Key_SetBinding( i, "" );
|
||||
|
@ -382,6 +370,7 @@ void Key_Unbindall_f( void )
|
|||
|
||||
// set some defaults
|
||||
Key_SetBinding( K_ESCAPE, "escape" );
|
||||
Key_SetBinding( K_START_BUTTON, "escape" );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -395,7 +384,7 @@ void Key_Reset_f( void )
|
|||
int i;
|
||||
|
||||
// clear all keys first
|
||||
for( i = 0; i < 256; i++ )
|
||||
for( i = 0; i < ARRAYSIZE( keys ); i++ )
|
||||
{
|
||||
if( keys[i].binding )
|
||||
Key_SetBinding( i, "" );
|
||||
|
@ -445,8 +434,8 @@ void Key_Bind_f( void )
|
|||
|
||||
for( i = 2; i < c; i++ )
|
||||
{
|
||||
Q_strcat( cmd, Cmd_Argv( i ));
|
||||
if( i != ( c - 1 )) Q_strcat( cmd, " " );
|
||||
Q_strncat( cmd, Cmd_Argv( i ), sizeof( cmd ));
|
||||
if( i != ( c - 1 )) Q_strncat( cmd, " ", sizeof( cmd ));
|
||||
}
|
||||
|
||||
Key_SetBinding( b, cmd );
|
||||
|
@ -524,8 +513,8 @@ void Key_Init( void )
|
|||
// setup default binding. "unbindall" from config.cfg will be reset it
|
||||
for( kn = keynames; kn->name; kn++ ) Key_SetBinding( kn->keynum, kn->binding );
|
||||
|
||||
osk_enable = Cvar_Get( "osk_enable", "0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "enable built-in on-screen keyboard" );
|
||||
key_rotate = Cvar_Get( "key_rotate", "0", FCVAR_ARCHIVE | FCVAR_FILTERABLE, "rotate arrow keys (0-3)" );
|
||||
Cvar_RegisterVariable( &osk_enable );
|
||||
Cvar_RegisterVariable( &key_rotate );
|
||||
|
||||
}
|
||||
|
||||
|
@ -552,8 +541,8 @@ void Key_AddKeyCommands( int key, const char *kb, qboolean down )
|
|||
if( button[0] == '+' )
|
||||
{
|
||||
// button commands add keynum as a parm
|
||||
if( down ) Q_sprintf( cmd, "%s %i\n", button, key );
|
||||
else Q_sprintf( cmd, "-%s %i\n", button + 1, key );
|
||||
if( down ) Q_snprintf( cmd, sizeof( cmd ), "%s %i\n", button, key );
|
||||
else Q_snprintf( cmd, sizeof( cmd ), "-%s %i\n", button + 1, key );
|
||||
Cbuf_AddText( cmd );
|
||||
}
|
||||
else if( down )
|
||||
|
@ -601,7 +590,7 @@ static qboolean Key_IsAllowedAutoRepeat( int key )
|
|||
|
||||
static int Key_Rotate( int key )
|
||||
{
|
||||
if( key_rotate->value == 1.0f ) // CW
|
||||
if( key_rotate.value == 1.0f ) // CW
|
||||
{
|
||||
if( key == K_UPARROW )
|
||||
key = K_LEFTARROW;
|
||||
|
@ -613,7 +602,7 @@ static int Key_Rotate( int key )
|
|||
key = K_RIGHTARROW;
|
||||
}
|
||||
|
||||
else if( key_rotate->value == 3.0f ) // CCW
|
||||
else if( key_rotate.value == 3.0f ) // CCW
|
||||
{
|
||||
if( key == K_UPARROW )
|
||||
key = K_RIGHTARROW;
|
||||
|
@ -625,7 +614,7 @@ static int Key_Rotate( int key )
|
|||
key = K_LEFTARROW;
|
||||
}
|
||||
|
||||
else if( key_rotate->value == 2.0f )
|
||||
else if( key_rotate.value == 2.0f )
|
||||
{
|
||||
if( key == K_UPARROW )
|
||||
key = K_DOWNARROW;
|
||||
|
@ -712,7 +701,6 @@ void GAME_EXPORT Key_Event( int key, int down )
|
|||
}
|
||||
|
||||
VGui_KeyEvent( key, down );
|
||||
Touch_KeyEvent( key, down );
|
||||
|
||||
// console key is hardcoded, so the user can never unbind it
|
||||
if( key == '`' || key == '~' )
|
||||
|
@ -731,10 +719,10 @@ void GAME_EXPORT Key_Event( int key, int down )
|
|||
switch( cls.key_dest )
|
||||
{
|
||||
case key_game:
|
||||
if( CVAR_TO_BOOL( gl_showtextures ))
|
||||
if( r_showtextures.value )
|
||||
{
|
||||
// close texture atlas
|
||||
Cvar_SetValue( "r_showtextures", 0.0f );
|
||||
Cvar_DirectSet( &r_showtextures, "0" );
|
||||
return;
|
||||
}
|
||||
else if( host.mouse_visible && cls.state != ca_cinematic )
|
||||
|
@ -809,7 +797,7 @@ Key_EnableTextInput
|
|||
*/
|
||||
void Key_EnableTextInput( qboolean enable, qboolean force )
|
||||
{
|
||||
if( CVAR_TO_BOOL( osk_enable ) )
|
||||
if( osk_enable.value )
|
||||
{
|
||||
OSK_EnableTextInput( enable, force );
|
||||
return;
|
||||
|
@ -842,7 +830,9 @@ void GAME_EXPORT Key_SetKeyDest( int key_dest )
|
|||
cls.key_dest = key_menu;
|
||||
break;
|
||||
case key_console:
|
||||
#if !XASH_NSWITCH && !XASH_PSVITA // if we don't disable this, pops up the keyboard during load
|
||||
Key_EnableTextInput( true, false );
|
||||
#endif
|
||||
cls.key_dest = key_console;
|
||||
break;
|
||||
case key_message:
|
||||
|
@ -1005,7 +995,7 @@ struct osk_s
|
|||
|
||||
static qboolean OSK_KeyEvent( int key, int down )
|
||||
{
|
||||
if( !osk.enable || !CVAR_TO_BOOL( osk_enable ) )
|
||||
if( !osk.enable || !osk_enable.value )
|
||||
return false;
|
||||
|
||||
if( osk.sending )
|
||||
|
@ -1065,7 +1055,7 @@ static qboolean OSK_KeyEvent( int key, int down )
|
|||
break;
|
||||
}
|
||||
|
||||
if( !Q_stricmp( cl_charset->string, "utf-8" ) )
|
||||
if( !Q_stricmp( cl_charset.string, "utf-8" ) )
|
||||
ch = (unsigned char)osk.curbutton.val;
|
||||
else
|
||||
ch = Con_UtfProcessCharForce( (unsigned char)osk.curbutton.val );
|
||||
|
@ -1149,7 +1139,7 @@ Draw button with symbol on it
|
|||
*/
|
||||
static void OSK_DrawSymbolButton( int symb, float x, float y, float width, float height )
|
||||
{
|
||||
char str[] = {symb & 255, 0};
|
||||
cl_font_t *font = Con_GetCurFont();
|
||||
byte color[] = { 255, 255, 255, 255 };
|
||||
int x1 = x * refState.width,
|
||||
y1 = y * refState.height,
|
||||
|
@ -1157,14 +1147,15 @@ static void OSK_DrawSymbolButton( int symb, float x, float y, float width, float
|
|||
h = height * refState.height;
|
||||
|
||||
if( symb == osk.curbutton.val )
|
||||
{
|
||||
ref.dllFuncs.FillRGBABlend( x1, y1, w, h, 255, 160, 0, 100 );
|
||||
}
|
||||
|
||||
if( !symb || symb == ' ' || (symb >= OSK_TAB && symb < OSK_SPECKEY_LAST ) )
|
||||
return;
|
||||
|
||||
Con_DrawCharacter( x1 + 1, y1, symb, color );
|
||||
CL_DrawCharacter(
|
||||
x1 + width * 0.4 * refState.width,
|
||||
y1 + height * 0.4 * refState.height,
|
||||
symb, color, font, 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1178,7 +1169,11 @@ static void OSK_DrawSpecialButton( const char *name, float x, float y, float wid
|
|||
{
|
||||
byte color[] = { 0, 255, 0, 255 };
|
||||
|
||||
Con_DrawString( x * refState.width, y * refState.height, name, color );
|
||||
Con_DrawString(
|
||||
x * refState.width + width * 0.4 * refState.width,
|
||||
y * refState.height + height * 0.4 * refState.height,
|
||||
name,
|
||||
color );
|
||||
}
|
||||
|
||||
|
||||
|
@ -1195,7 +1190,7 @@ void OSK_Draw( void )
|
|||
float x, y;
|
||||
int i, j;
|
||||
|
||||
if( !osk.enable || !CVAR_TO_BOOL(osk_enable) || !osk.curbutton.val )
|
||||
if( !osk.enable || !osk_enable.value || !osk.curbutton.val )
|
||||
return;
|
||||
|
||||
// draw keyboard
|
||||
|
|
|
@ -659,7 +659,7 @@ static void make_hull_windings( hull_t *hull, hull_model_t *model )
|
|||
Con_Reportf( "%i hull polys\n", model->num_polys );
|
||||
}
|
||||
|
||||
void Mod_InitDebugHulls( void )
|
||||
void Mod_InitDebugHulls( model_t *loadmodel )
|
||||
{
|
||||
int i;
|
||||
|
||||
|
|
|
@ -8,15 +8,15 @@
|
|||
struct ref_state_s ref;
|
||||
ref_globals_t refState;
|
||||
|
||||
convar_t *gl_vsync;
|
||||
convar_t *gl_showtextures;
|
||||
convar_t *r_decals;
|
||||
convar_t *r_adjust_fov;
|
||||
convar_t *r_showtree;
|
||||
convar_t *gl_msaa_samples;
|
||||
convar_t *gl_clear;
|
||||
convar_t *r_refdll;
|
||||
convar_t *r_refdll_loaded;
|
||||
CVAR_DEFINE_AUTO( gl_vsync, "0", FCVAR_ARCHIVE, "enable vertical syncronization" );
|
||||
CVAR_DEFINE_AUTO( r_showtextures, "0", FCVAR_CHEAT, "show all uploaded textures" );
|
||||
CVAR_DEFINE_AUTO( r_adjust_fov, "1", FCVAR_ARCHIVE, "making FOV adjustment for wide-screens" );
|
||||
CVAR_DEFINE_AUTO( r_decals, "4096", FCVAR_ARCHIVE, "sets the maximum number of decals" );
|
||||
CVAR_DEFINE_AUTO( gl_msaa_samples, "0", FCVAR_GLCONFIG, "samples number for multisample anti-aliasing" );
|
||||
CVAR_DEFINE_AUTO( gl_clear, "0", FCVAR_ARCHIVE, "clearing screen after each frame" );
|
||||
CVAR_DEFINE_AUTO( r_showtree, "0", FCVAR_ARCHIVE, "build the graph of visible BSP tree" );
|
||||
static CVAR_DEFINE_AUTO( r_refdll, "", FCVAR_RENDERINFO, "choose renderer implementation, if supported" );
|
||||
static CVAR_DEFINE_AUTO( r_refdll_loaded, "", FCVAR_READ_ONLY, "currently loaded renderer" );
|
||||
|
||||
void R_GetTextureParms( int *w, int *h, int texnum )
|
||||
{
|
||||
|
@ -56,12 +56,11 @@ void GL_RenderFrame( const ref_viewpass_t *rvp )
|
|||
|
||||
VectorCopy( rvp->vieworigin, refState.vieworg );
|
||||
VectorCopy( rvp->viewangles, refState.viewangles );
|
||||
AngleVectors( refState.viewangles, refState.vforward, refState.vright, refState.vup );
|
||||
|
||||
ref.dllFuncs.GL_RenderFrame( rvp );
|
||||
}
|
||||
|
||||
static int pfnEngineGetParm( int parm, int arg )
|
||||
static intptr_t pfnEngineGetParm( int parm, int arg )
|
||||
{
|
||||
return CL_RenderGetParm( parm, arg, false ); // prevent recursion
|
||||
}
|
||||
|
@ -76,16 +75,6 @@ static void pfnStudioEvent( const mstudioevent_t *event, const cl_entity_t *e )
|
|||
clgame.dllFuncs.pfnStudioEvent( event, e );
|
||||
}
|
||||
|
||||
static efrag_t* pfnGetEfragsFreeList( void )
|
||||
{
|
||||
return clgame.free_efrags;
|
||||
}
|
||||
|
||||
static void pfnSetEfragsFreeList( efrag_t *list )
|
||||
{
|
||||
clgame.free_efrags = list;
|
||||
}
|
||||
|
||||
static model_t *pfnGetDefaultSprite( enum ref_defaultsprite_e spr )
|
||||
{
|
||||
switch( spr )
|
||||
|
@ -110,16 +99,6 @@ static void *pfnMod_Extradata( int type, model_t *m )
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static model_t *pfnMod_GetCurrentLoadingModel( void )
|
||||
{
|
||||
return loadmodel;
|
||||
}
|
||||
|
||||
static void pfnMod_SetCurrentLoadingModel( model_t *m )
|
||||
{
|
||||
loadmodel = m;
|
||||
}
|
||||
|
||||
static void pfnGetPredictedOrigin( vec3_t v )
|
||||
{
|
||||
VectorCopy( cl.simorg, v );
|
||||
|
@ -152,7 +131,7 @@ static player_info_t *pfnPlayerInfo( int index )
|
|||
if( index == -1 ) // special index for menu
|
||||
return &gameui.playerinfo;
|
||||
|
||||
if( index < 0 || index > cl.maxclients )
|
||||
if( index < 0 || index >= cl.maxclients )
|
||||
return NULL;
|
||||
|
||||
return &cl.players[index];
|
||||
|
@ -226,7 +205,7 @@ static qboolean R_DoResetGamma( void )
|
|||
static qboolean R_Init_Video_( const int type )
|
||||
{
|
||||
host.apply_opengl_config = true;
|
||||
Cbuf_AddText( va( "exec %s.cfg", ref.dllFuncs.R_GetConfigName()));
|
||||
Cbuf_AddTextf( "exec %s.cfg", ref.dllFuncs.R_GetConfigName());
|
||||
Cbuf_Execute();
|
||||
host.apply_opengl_config = false;
|
||||
|
||||
|
@ -243,7 +222,7 @@ static ref_api_t gEngfuncs =
|
|||
Cvar_VariableString,
|
||||
Cvar_SetValue,
|
||||
Cvar_Set,
|
||||
(void*)Cvar_RegisterVariable,
|
||||
Cvar_RegisterVariable,
|
||||
Cvar_FullSet,
|
||||
|
||||
Cmd_AddRefCommand,
|
||||
|
@ -280,9 +259,6 @@ static ref_api_t gEngfuncs =
|
|||
Mod_PointInLeaf,
|
||||
Mod_CreatePolygonsForHull,
|
||||
|
||||
R_StudioSlerpBones,
|
||||
R_StudioCalcBoneQuaternion,
|
||||
R_StudioCalcBonePosition,
|
||||
R_StudioGetAnim,
|
||||
pfnStudioEvent,
|
||||
|
||||
|
@ -297,8 +273,6 @@ static ref_api_t gEngfuncs =
|
|||
Mod_ForName,
|
||||
pfnMod_Extradata,
|
||||
CL_ModelHandle,
|
||||
pfnMod_GetCurrentLoadingModel,
|
||||
pfnMod_SetCurrentLoadingModel,
|
||||
|
||||
CL_GetRemapInfoForEntity,
|
||||
CL_AllocRemapInfo,
|
||||
|
@ -360,7 +334,7 @@ static ref_api_t gEngfuncs =
|
|||
|
||||
pfnGetPhysent,
|
||||
pfnTraceSurface,
|
||||
PM_TraceLine,
|
||||
PM_CL_TraceLine,
|
||||
CL_VisTraceLine,
|
||||
CL_TraceLine,
|
||||
pfnGetMoveVars,
|
||||
|
@ -398,14 +372,14 @@ static void R_UnloadProgs( void )
|
|||
|
||||
Cvar_FullSet( "host_refloaded", "0", FCVAR_READ_ONLY );
|
||||
|
||||
Cvar_Unlink( FCVAR_RENDERINFO | FCVAR_GLCONFIG );
|
||||
Cmd_Unlink( CMD_REFDLL );
|
||||
|
||||
COM_FreeLibrary( ref.hInstance );
|
||||
ref.hInstance = NULL;
|
||||
|
||||
memset( &refState, 0, sizeof( refState ));
|
||||
memset( &ref.dllFuncs, 0, sizeof( ref.dllFuncs ));
|
||||
|
||||
Cvar_Unlink( FCVAR_RENDERINFO | FCVAR_GLCONFIG );
|
||||
Cmd_Unlink( CMD_REFDLL );
|
||||
}
|
||||
|
||||
static void CL_FillTriAPIFromRef( triangleapi_t *dst, const ref_interface_t *src )
|
||||
|
@ -531,7 +505,7 @@ static void R_GetRendererName( char *dest, size_t size, const char *opt )
|
|||
else
|
||||
{
|
||||
// full path
|
||||
Q_strcpy( dest, opt );
|
||||
Q_strncpy( dest, opt, size );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -569,77 +543,75 @@ static void SetWidthAndHeightFromCommandLine( void )
|
|||
return;
|
||||
}
|
||||
|
||||
R_SaveVideoMode( width, height, width, height );
|
||||
R_SaveVideoMode( width, height, width, height, false );
|
||||
}
|
||||
|
||||
static void SetFullscreenModeFromCommandLine( void )
|
||||
{
|
||||
#if !XASH_MOBILE_PLATFORM
|
||||
if ( Sys_CheckParm("-fullscreen") )
|
||||
{
|
||||
Cvar_Set( "fullscreen", "1" );
|
||||
}
|
||||
else if ( Sys_CheckParm( "-windowed" ) )
|
||||
{
|
||||
Cvar_Set( "fullscreen", "0" );
|
||||
}
|
||||
#endif
|
||||
if( Sys_CheckParm( "-borderless" ))
|
||||
Cvar_DirectSet( &vid_fullscreen, "2" );
|
||||
else if( Sys_CheckParm( "-fullscreen" ))
|
||||
Cvar_DirectSet( &vid_fullscreen, "1" );
|
||||
else if( Sys_CheckParm( "-windowed" ))
|
||||
Cvar_DirectSet( &vid_fullscreen, "0" );
|
||||
}
|
||||
|
||||
void R_CollectRendererNames( void )
|
||||
static void R_CollectRendererNames( void )
|
||||
{
|
||||
const char *renderers[] = DEFAULT_RENDERERS;
|
||||
int i, cur;
|
||||
|
||||
cur = 0;
|
||||
for( i = 0; i < DEFAULT_RENDERERS_LEN; i++ )
|
||||
// ordering is important!
|
||||
static const char *shortNames[] =
|
||||
{
|
||||
string temp;
|
||||
void *dll, *pfn;
|
||||
#if XASH_REF_GL_ENABLED
|
||||
"gl",
|
||||
#endif
|
||||
#if XASH_REF_NANOGL_ENABLED
|
||||
"gles1",
|
||||
#endif
|
||||
#if XASH_REF_GLWES_ENABLED
|
||||
"gles2",
|
||||
#endif
|
||||
#if XASH_REF_GL4ES_ENABLED
|
||||
"gl4es",
|
||||
#endif
|
||||
#if XASH_REF_SOFT_ENABLED
|
||||
"soft",
|
||||
#endif
|
||||
#if XASH_REF_VULKAN_ENABLED
|
||||
"vk"
|
||||
#endif
|
||||
};
|
||||
|
||||
R_GetRendererName( temp, sizeof( temp ), renderers[i] );
|
||||
// ordering is important here too!
|
||||
static const char *readableNames[ARRAYSIZE( shortNames )] =
|
||||
{
|
||||
#if XASH_REF_GL_ENABLED
|
||||
"OpenGL",
|
||||
#endif
|
||||
#if XASH_REF_NANOGL_ENABLED
|
||||
"GLES1 (NanoGL)",
|
||||
#endif
|
||||
#if XASH_REF_GLWES_ENABLED
|
||||
"GLES2 (gl-wes-v2)",
|
||||
#endif
|
||||
#if XASH_REF_GL4ES_ENABLED
|
||||
"GL4ES",
|
||||
#endif
|
||||
#if XASH_REF_SOFT_ENABLED
|
||||
"Software",
|
||||
#endif
|
||||
#if XASH_REF_VULKAN_ENABLED
|
||||
"Vulkan"
|
||||
#endif
|
||||
};
|
||||
|
||||
dll = COM_LoadLibrary( temp, false, true );
|
||||
if( !dll )
|
||||
{
|
||||
Con_Reportf( "R_CollectRendererNames: can't load library %s: %s\n", temp, COM_GetLibraryError() );
|
||||
continue;
|
||||
}
|
||||
|
||||
pfn = COM_GetProcAddress( dll, GET_REF_API );
|
||||
if( !pfn )
|
||||
{
|
||||
Con_Reportf( "R_CollectRendererNames: can't find API entry point in %s\n", temp );
|
||||
COM_FreeLibrary( dll );
|
||||
continue;
|
||||
}
|
||||
|
||||
Q_strncpy( ref.shortNames[cur], renderers[i], sizeof( ref.shortNames[cur] ));
|
||||
|
||||
pfn = COM_GetProcAddress( dll, GET_REF_HUMANREADABLE_NAME );
|
||||
if( !pfn ) // just in case
|
||||
{
|
||||
Con_Reportf( "R_CollectRendererNames: can't find GetHumanReadableName export in %s\n", temp );
|
||||
Q_strncpy( ref.readableNames[cur], renderers[i], sizeof( ref.readableNames[cur] ));
|
||||
}
|
||||
else
|
||||
{
|
||||
REF_HUMANREADABLE_NAME GetHumanReadableName = (REF_HUMANREADABLE_NAME)pfn;
|
||||
|
||||
GetHumanReadableName( ref.readableNames[cur], sizeof( ref.readableNames[cur] ));
|
||||
}
|
||||
|
||||
Con_Printf( "Found renderer %s: %s\n", ref.shortNames[cur], ref.readableNames[cur] );
|
||||
|
||||
cur++;
|
||||
COM_FreeLibrary( dll );
|
||||
}
|
||||
ref.numRenderers = cur;
|
||||
ref.numRenderers = ARRAYSIZE( shortNames );
|
||||
ref.shortNames = shortNames;
|
||||
ref.readableNames = readableNames;
|
||||
}
|
||||
|
||||
const ref_device_t *R_GetRenderDevice( unsigned int idx )
|
||||
{
|
||||
if( !Q_stricmp( r_refdll_loaded->string, "vk" ))
|
||||
if( !Q_stricmp( r_refdll_loaded.string, "vk" ))
|
||||
{
|
||||
if( !ref.dllFuncs.pfnGetVulkanRenderDevice )
|
||||
return NULL;
|
||||
|
@ -673,10 +645,10 @@ static void R_GetRenderDevices_f( void )
|
|||
int i = 0;
|
||||
const ref_device_t *device = NULL;
|
||||
|
||||
if( Q_stricmp( r_refdll_loaded->string, "vk" ) ||
|
||||
if( Q_stricmp( r_refdll_loaded.string, "vk" ) ||
|
||||
!ref.dllFuncs.pfnGetVulkanRenderDevice )
|
||||
{
|
||||
Con_Printf( "Renderer %s doesn't implement this!\n", r_refdll_loaded->string );
|
||||
Con_Printf( "Renderer %s doesn't implement this!\n", r_refdll_loaded.string );
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -701,15 +673,15 @@ qboolean R_Init( void )
|
|||
qboolean success = false;
|
||||
string requested;
|
||||
|
||||
gl_vsync = Cvar_Get( "gl_vsync", "0", FCVAR_ARCHIVE, "enable vertical syncronization" );
|
||||
gl_showtextures = Cvar_Get( "r_showtextures", "0", FCVAR_CHEAT, "show all uploaded textures" );
|
||||
r_adjust_fov = Cvar_Get( "r_adjust_fov", "1", FCVAR_ARCHIVE, "making FOV adjustment for wide-screens" );
|
||||
r_decals = Cvar_Get( "r_decals", "4096", FCVAR_ARCHIVE, "sets the maximum number of decals" );
|
||||
gl_msaa_samples = Cvar_Get( "gl_msaa_samples", "0", FCVAR_GLCONFIG, "samples number for multisample anti-aliasing" );
|
||||
gl_clear = Cvar_Get( "gl_clear", "0", FCVAR_ARCHIVE, "clearing screen after each frame" );
|
||||
r_showtree = Cvar_Get( "r_showtree", "0", FCVAR_ARCHIVE, "build the graph of visible BSP tree" );
|
||||
r_refdll = Cvar_Get( "r_refdll", "", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "choose renderer implementation, if supported" );
|
||||
r_refdll_loaded = Cvar_Get( "r_refdll_loaded", "", FCVAR_READ_ONLY, "currently loaded renderer" );
|
||||
Cvar_RegisterVariable( &gl_vsync );
|
||||
Cvar_RegisterVariable( &r_showtextures );
|
||||
Cvar_RegisterVariable( &r_adjust_fov );
|
||||
Cvar_RegisterVariable( &r_decals );
|
||||
Cvar_RegisterVariable( &gl_msaa_samples );
|
||||
Cvar_RegisterVariable( &gl_clear );
|
||||
Cvar_RegisterVariable( &r_showtree );
|
||||
Cvar_RegisterVariable( &r_refdll );
|
||||
Cvar_RegisterVariable( &r_refdll_loaded );
|
||||
|
||||
// cvars that are expected to exist
|
||||
Cvar_Get( "r_speeds", "0", FCVAR_ARCHIVE, "shows renderer speeds" );
|
||||
|
@ -750,36 +722,34 @@ qboolean R_Init( void )
|
|||
// 1. Command line `-ref` argument.
|
||||
// 2. `ref_dll` cvar.
|
||||
// 3. Detected renderers in `DEFAULT_RENDERERS` order.
|
||||
requested[0] = '\0';
|
||||
if( !Sys_GetParmFromCmdLine( "-ref", requested ) && COM_CheckString( r_refdll->string ) )
|
||||
// r_refdll is set to empty by default, so we can change hardcoded defaults just in case
|
||||
Q_strncpy( requested, r_refdll->string, sizeof( requested ) );
|
||||
requested[0] = 0;
|
||||
|
||||
if ( requested[0] )
|
||||
if( !success && Sys_GetParmFromCmdLine( "-ref", requested ))
|
||||
success = R_LoadRenderer( requested );
|
||||
|
||||
if( !success && COM_CheckString( r_refdll.string ))
|
||||
{
|
||||
Q_strncpy( requested, r_refdll.string, sizeof( requested ));
|
||||
success = R_LoadRenderer( requested );
|
||||
}
|
||||
|
||||
if( !success )
|
||||
{
|
||||
int i;
|
||||
|
||||
// cycle through renderers that we collected in CollectRendererNames
|
||||
for( i = 0; i < ref.numRenderers; i++ )
|
||||
for( i = 0; i < ref.numRenderers && !success; i++ )
|
||||
{
|
||||
// skip renderer that was requested but failed to load
|
||||
if( !Q_strcmp( requested, ref.shortNames[i] ) )
|
||||
if( !Q_strcmp( requested, ref.shortNames[i] ))
|
||||
continue;
|
||||
|
||||
success = R_LoadRenderer( ref.shortNames[i] );
|
||||
|
||||
// yay, found working one
|
||||
if( success )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( !success )
|
||||
{
|
||||
Host_Error( "Can't initialize any renderer. Check your video drivers!" );
|
||||
Host_Error( "Can't initialize any renderer. Check your video drivers!\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,9 +27,10 @@ struct ref_state_s
|
|||
HINSTANCE hInstance;
|
||||
ref_interface_t dllFuncs;
|
||||
|
||||
// depends on build configuration
|
||||
int numRenderers;
|
||||
string shortNames[DEFAULT_RENDERERS_LEN];
|
||||
string readableNames[DEFAULT_RENDERERS_LEN];
|
||||
const char **shortNames;
|
||||
const char **readableNames;
|
||||
};
|
||||
|
||||
extern struct ref_state_s ref;
|
||||
|
@ -40,14 +41,14 @@ void R_GetTextureParms( int *w, int *h, int texnum );
|
|||
#define REF_GET_PARM( parm, arg ) ref.dllFuncs.RefGetParm( (parm), (arg) )
|
||||
#define GL_LoadTextureInternal( name, pic, flags ) ref.dllFuncs.GL_LoadTextureFromBuffer( (name), (pic), (flags), false )
|
||||
#define GL_UpdateTextureInternal( name, pic, flags ) ref.dllFuncs.GL_LoadTextureFromBuffer( (name), (pic), (flags), true )
|
||||
#define R_GetBuiltinTexture( name ) ref.dllFuncs.GL_LoadTexture( (name), 0, 0, 0 )
|
||||
#define R_GetBuiltinTexture( name ) ref.dllFuncs.GL_FindTexture( (name) )
|
||||
|
||||
void GL_RenderFrame( const struct ref_viewpass_s *rvp );
|
||||
|
||||
// common engine and renderer cvars
|
||||
extern convar_t *r_decals;
|
||||
extern convar_t *r_adjust_fov;
|
||||
extern convar_t *gl_clear;
|
||||
extern convar_t r_decals;
|
||||
extern convar_t r_adjust_fov;
|
||||
extern convar_t gl_clear;
|
||||
|
||||
qboolean R_Init( void );
|
||||
void R_Shutdown( void );
|
||||
|
|
|
@ -78,7 +78,7 @@ typedef struct dly_s
|
|||
int *lpdelayline;
|
||||
} dly_t;
|
||||
|
||||
const sx_preset_t rgsxpre[] =
|
||||
static const sx_preset_t rgsxpre[] =
|
||||
{
|
||||
// -------reverb-------- -------delay--------
|
||||
// lp mod size refl rvblp delay feedback dlylp left
|
||||
|
@ -115,7 +115,7 @@ const sx_preset_t rgsxpre[] =
|
|||
|
||||
// 0x0045dca8 enginegl.exe
|
||||
// SHA256: 42383d32cd712e59ee2c1bd78b7ba48814e680e7026c4223e730111f34a60d66
|
||||
const sx_preset_t rgsxpre_hlalpha052[] =
|
||||
static const sx_preset_t rgsxpre_hlalpha052[] =
|
||||
{
|
||||
// -------reverb-------- -------delay--------
|
||||
// lp mod size refl rvblp delay feedback dlylp left
|
||||
|
@ -150,51 +150,50 @@ const sx_preset_t rgsxpre_hlalpha052[] =
|
|||
{ 0.0, 0.0, 0.001, 0.999, 0.0, 0.2, 0.8, 2.0, 0.05 }, // 28
|
||||
};
|
||||
|
||||
const sx_preset_t *ptable = rgsxpre;
|
||||
static const sx_preset_t *ptable = rgsxpre;
|
||||
|
||||
// cvars
|
||||
convar_t *dsp_off; // disable dsp
|
||||
convar_t *roomwater_type; // water room_type
|
||||
convar_t *room_type; // current room type
|
||||
convar_t *hisound; // DSP quality
|
||||
static CVAR_DEFINE_AUTO( dsp_off, "0", FCVAR_ARCHIVE, "disable DSP processing" );
|
||||
static CVAR_DEFINE_AUTO( dsp_coeff_table, "0", FCVAR_ARCHIVE, "select DSP coefficient table: 0 for release or 1 for alpha 0.52" );
|
||||
static CVAR_DEFINE_AUTO( room_type, "0", 0, "current room type preset" );
|
||||
|
||||
static CVAR_DEFINE( roomwater_type, "waterroom_type", "14", 0, "water room type" );
|
||||
static CVAR_DEFINE( hisound, "room_hires", "2", FCVAR_ARCHIVE, "dsp quality. 1 for 22k, 2 for 44k(recommended) and 3 for 96k" );
|
||||
|
||||
// underwater/special fx modulations
|
||||
convar_t *sxmod_mod;
|
||||
convar_t *sxmod_lowpass;
|
||||
static CVAR_DEFINE( sxmod_mod, "room_mod", "0", 0, "stereo amptitude modulation for room" );
|
||||
static CVAR_DEFINE( sxmod_lowpass, "room_lp", "0", 0, "for water fx, lowpass for entire room" );
|
||||
|
||||
// stereo delay(no feedback)
|
||||
convar_t *sxste_delay; // straight left delay
|
||||
static CVAR_DEFINE( sxste_delay, "room_left", "0", 0, "left channel delay time" );
|
||||
|
||||
// mono reverb
|
||||
convar_t *sxrvb_lp; // lowpass
|
||||
convar_t *sxrvb_feedback; // reverb decay. Higher -- longer
|
||||
convar_t *sxrvb_size; // room size. Higher -- larger
|
||||
static CVAR_DEFINE( sxrvb_lp, "room_rvblp", "1", 0, "reverb: low pass filtering level" );
|
||||
static CVAR_DEFINE( sxrvb_feedback, "room_refl", "0", 0, "reverb: decay time" );
|
||||
static CVAR_DEFINE( sxrvb_size, "room_size", "0", 0, "reverb: initial reflection size" );
|
||||
|
||||
// mono delay
|
||||
convar_t *sxdly_lp; // lowpass
|
||||
convar_t *sxdly_feedback; // cycles
|
||||
convar_t *sxdly_delay; // current delay in seconds
|
||||
static CVAR_DEFINE( sxdly_lp, "room_dlylp", "1", 0, "mono delay: low pass filtering level" );
|
||||
static CVAR_DEFINE( sxdly_feedback, "room_feedback", "0.2", 0, "mono delay: decay time" );
|
||||
static CVAR_DEFINE( sxdly_delay, "room_delay", "0.8", 0, "mono delay: delay time" );
|
||||
|
||||
convar_t *dsp_room; // for compability
|
||||
|
||||
convar_t *dsp_coeff_table; // use release or 0.52 style
|
||||
int idsp_dma_speed;
|
||||
static int idsp_dma_speed;
|
||||
int idsp_room;
|
||||
int room_typeprev;
|
||||
static int room_typeprev;
|
||||
|
||||
// routines
|
||||
int sxamodl, sxamodr; // amplitude modulation values
|
||||
int sxamodlt, sxamodrt; // modulation targets
|
||||
int sxmod1cur, sxmod2cur;
|
||||
int sxmod1, sxmod2;
|
||||
int sxhires;
|
||||
static int sxamodl, sxamodr; // amplitude modulation values
|
||||
static int sxamodlt, sxamodrt; // modulation targets
|
||||
static int sxmod1cur, sxmod2cur;
|
||||
static int sxmod1, sxmod2;
|
||||
static int sxhires;
|
||||
|
||||
portable_samplepair_t *paintto = NULL;
|
||||
static portable_samplepair_t *paintto = NULL;
|
||||
|
||||
dly_t rgsxdly[MAXDLY]; // stereo is last
|
||||
int rgsxlp[MAXLP];
|
||||
static dly_t rgsxdly[MAXDLY]; // stereo is last
|
||||
static int rgsxlp[MAXLP];
|
||||
|
||||
void SX_Profiling_f( void );
|
||||
static void SX_Profiling_f( void );
|
||||
|
||||
/*
|
||||
============
|
||||
|
@ -202,14 +201,12 @@ SX_ReloadRoomFX
|
|||
|
||||
============
|
||||
*/
|
||||
void SX_ReloadRoomFX( void )
|
||||
static void SX_ReloadRoomFX( void )
|
||||
{
|
||||
if( !dsp_room ) return; // not initialized
|
||||
|
||||
SetBits( sxste_delay->flags, FCVAR_CHANGED );
|
||||
SetBits( sxrvb_feedback->flags, FCVAR_CHANGED );
|
||||
SetBits( sxdly_delay->flags, FCVAR_CHANGED );
|
||||
SetBits( room_type->flags, FCVAR_CHANGED );
|
||||
SetBits( sxste_delay.flags, FCVAR_CHANGED );
|
||||
SetBits( sxrvb_feedback.flags, FCVAR_CHANGED );
|
||||
SetBits( sxdly_delay.flags, FCVAR_CHANGED );
|
||||
SetBits( room_type.flags, FCVAR_CHANGED );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -227,36 +224,33 @@ void SX_Init( void )
|
|||
sxamodr = sxamodl = sxamodrt = sxamodlt = 255;
|
||||
idsp_dma_speed = SOUND_11k;
|
||||
|
||||
hisound = Cvar_Get( "room_hires", "2", FCVAR_ARCHIVE, "dsp quality. 1 for 22k, 2 for 44k(recommended) and 3 for 96k" );
|
||||
Cvar_RegisterVariable( &hisound );
|
||||
sxhires = 2;
|
||||
|
||||
sxmod1cur = sxmod1 = 350 * ( idsp_dma_speed / SOUND_11k );
|
||||
sxmod2cur = sxmod2 = 450 * ( idsp_dma_speed / SOUND_11k );
|
||||
|
||||
dsp_off = Cvar_Get( "dsp_off", "0", FCVAR_ARCHIVE, "disable DSP processing" );
|
||||
dsp_coeff_table = Cvar_Get( "dsp_coeff_table", "0", FCVAR_ARCHIVE, "select DSP coefficient table: 0 for release or 1 for alpha 0.52" );
|
||||
Cvar_RegisterVariable( &dsp_off );
|
||||
Cvar_RegisterVariable( &dsp_coeff_table );
|
||||
|
||||
roomwater_type = Cvar_Get( "waterroom_type", "14", 0, "water room type" );
|
||||
room_type = Cvar_Get( "room_type", "0", 0, "current room type preset" );
|
||||
Cvar_RegisterVariable( &roomwater_type );
|
||||
Cvar_RegisterVariable( &room_type );
|
||||
|
||||
sxmod_lowpass = Cvar_Get( "room_lp", "0", 0, "for water fx, lowpass for entire room" );
|
||||
sxmod_mod = Cvar_Get( "room_mod", "0", 0, "stereo amptitude modulation for room" );
|
||||
Cvar_RegisterVariable( &sxmod_lowpass );
|
||||
Cvar_RegisterVariable( &sxmod_mod );
|
||||
|
||||
sxrvb_size = Cvar_Get( "room_size", "0", 0, "reverb: initial reflection size" );
|
||||
sxrvb_feedback = Cvar_Get( "room_refl", "0", 0, "reverb: decay time" );
|
||||
sxrvb_lp = Cvar_Get( "room_rvblp", "1", 0, "reverb: low pass filtering level" );
|
||||
Cvar_RegisterVariable( &sxrvb_size );
|
||||
Cvar_RegisterVariable( &sxrvb_feedback );
|
||||
Cvar_RegisterVariable( &sxrvb_lp );
|
||||
|
||||
sxdly_delay = Cvar_Get( "room_delay", "0.8", 0, "mono delay: delay time" );
|
||||
sxdly_feedback = Cvar_Get( "room_feedback", "0.2", 0, "mono delay: decay time" );
|
||||
sxdly_lp = Cvar_Get( "room_dlylp", "1", 0, "mono delay: low pass filtering level" );
|
||||
Cvar_RegisterVariable( &sxdly_delay );
|
||||
Cvar_RegisterVariable( &sxdly_feedback );
|
||||
Cvar_RegisterVariable( &sxdly_lp );
|
||||
|
||||
sxste_delay = Cvar_Get( "room_left", "0", 0, "left channel delay time" );
|
||||
Cvar_RegisterVariable( &sxste_delay );
|
||||
|
||||
Cmd_AddCommand( "dsp_profile", SX_Profiling_f, "dsp stress-test, first argument is room_type" );
|
||||
|
||||
// for compability
|
||||
dsp_room = room_type;
|
||||
|
||||
SX_ReloadRoomFX();
|
||||
}
|
||||
|
||||
|
@ -267,7 +261,7 @@ DLY_Free
|
|||
Free memory allocated for DSP
|
||||
===========
|
||||
*/
|
||||
void DLY_Free( int idelay )
|
||||
static void DLY_Free( int idelay )
|
||||
{
|
||||
Assert( idelay >= 0 && idelay < MAXDLY );
|
||||
|
||||
|
@ -303,7 +297,7 @@ DLY_Init
|
|||
Initialize dly
|
||||
===========
|
||||
*/
|
||||
int DLY_Init( int idelay, float delay )
|
||||
static int DLY_Init( int idelay, float delay )
|
||||
{
|
||||
dly_t *cur;
|
||||
|
||||
|
@ -355,12 +349,12 @@ DLY_CheckNewStereoDelayVal
|
|||
Update stereo processor settings if we are in new room
|
||||
=============
|
||||
*/
|
||||
void DLY_CheckNewStereoDelayVal( void )
|
||||
static void DLY_CheckNewStereoDelayVal( void )
|
||||
{
|
||||
dly_t *const dly = &rgsxdly[STEREODLY];
|
||||
float delay = sxste_delay->value;
|
||||
float delay = sxste_delay.value;
|
||||
|
||||
if( !FBitSet( sxste_delay->flags, FCVAR_CHANGED ))
|
||||
if( !FBitSet( sxste_delay.flags, FCVAR_CHANGED ))
|
||||
return;
|
||||
|
||||
if( delay == 0 )
|
||||
|
@ -403,7 +397,7 @@ DLY_DoStereoDelay
|
|||
Do stereo processing
|
||||
=============
|
||||
*/
|
||||
void DLY_DoStereoDelay( int count )
|
||||
static void DLY_DoStereoDelay( int count )
|
||||
{
|
||||
int delay, samplexf;
|
||||
dly_t *const dly = &rgsxdly[STEREODLY];
|
||||
|
@ -468,12 +462,12 @@ DLY_CheckNewDelayVal
|
|||
Update delay processor settings if we are in new room
|
||||
=============
|
||||
*/
|
||||
void DLY_CheckNewDelayVal( void )
|
||||
static void DLY_CheckNewDelayVal( void )
|
||||
{
|
||||
float delay = sxdly_delay->value;
|
||||
float delay = sxdly_delay.value;
|
||||
dly_t *const dly = &rgsxdly[MONODLY];
|
||||
|
||||
if( FBitSet( sxdly_delay->flags, FCVAR_CHANGED ))
|
||||
if( FBitSet( sxdly_delay.flags, FCVAR_CHANGED ))
|
||||
{
|
||||
if( delay == 0 )
|
||||
{
|
||||
|
@ -503,8 +497,8 @@ void DLY_CheckNewDelayVal( void )
|
|||
}
|
||||
}
|
||||
|
||||
dly->lp = sxdly_lp->value;
|
||||
dly->delayfeedback = 255 * sxdly_feedback->value;
|
||||
dly->lp = sxdly_lp.value;
|
||||
dly->delayfeedback = 255 * sxdly_feedback.value;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -514,7 +508,7 @@ DLY_DoDelay
|
|||
Do delay processing
|
||||
=============
|
||||
*/
|
||||
void DLY_DoDelay( int count )
|
||||
static void DLY_DoDelay( int count )
|
||||
{
|
||||
dly_t *const dly = &rgsxdly[MONODLY];
|
||||
portable_samplepair_t *paint = paintto;
|
||||
|
@ -565,7 +559,7 @@ RVB_SetUpDly
|
|||
Set up dly for reverb
|
||||
===========
|
||||
*/
|
||||
void RVB_SetUpDly( int pos, float delay, int kmod )
|
||||
static void RVB_SetUpDly( int pos, float delay, int kmod )
|
||||
{
|
||||
int samples;
|
||||
|
||||
|
@ -601,13 +595,13 @@ RVB_CheckNewReverbVal
|
|||
Update reverb settings if we are in new room
|
||||
===========
|
||||
*/
|
||||
void RVB_CheckNewReverbVal( void )
|
||||
static void RVB_CheckNewReverbVal( void )
|
||||
{
|
||||
dly_t *const dly1 = &rgsxdly[REVERBPOS];
|
||||
dly_t *const dly2 = &rgsxdly[REVERBPOS + 1];
|
||||
float delay = sxrvb_size->value;
|
||||
float delay = sxrvb_size.value;
|
||||
|
||||
if( FBitSet( sxrvb_size->flags, FCVAR_CHANGED ))
|
||||
if( FBitSet( sxrvb_size.flags, FCVAR_CHANGED ))
|
||||
{
|
||||
if( delay == 0.0f )
|
||||
{
|
||||
|
@ -616,13 +610,13 @@ void RVB_CheckNewReverbVal( void )
|
|||
}
|
||||
else
|
||||
{
|
||||
RVB_SetUpDly( REVERBPOS, sxrvb_size->value, 500 );
|
||||
RVB_SetUpDly( REVERBPOS+1, sxrvb_size->value * 0.71f, 700 );
|
||||
RVB_SetUpDly( REVERBPOS, sxrvb_size.value, 500 );
|
||||
RVB_SetUpDly( REVERBPOS+1, sxrvb_size.value * 0.71f, 700 );
|
||||
}
|
||||
}
|
||||
|
||||
dly1->lp = dly2->lp = sxrvb_lp->value;
|
||||
dly1->delayfeedback = dly2->delayfeedback = (int)(255 * sxrvb_feedback->value);
|
||||
dly1->lp = dly2->lp = sxrvb_lp.value;
|
||||
dly1->delayfeedback = dly2->delayfeedback = (int)(255 * sxrvb_feedback.value);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -632,7 +626,7 @@ RVB_DoReverbForOneDly
|
|||
Do reverberation for one dly
|
||||
===========
|
||||
*/
|
||||
int RVB_DoReverbForOneDly( dly_t *dly, const int vlr, const portable_samplepair_t *samplepair )
|
||||
static int RVB_DoReverbForOneDly( dly_t *dly, const int vlr, const portable_samplepair_t *samplepair )
|
||||
{
|
||||
int delay;
|
||||
int samplexf;
|
||||
|
@ -706,7 +700,7 @@ RVB_DoReverb
|
|||
Do reverberation processing
|
||||
===========
|
||||
*/
|
||||
void RVB_DoReverb( int count )
|
||||
static void RVB_DoReverb( int count )
|
||||
{
|
||||
dly_t *const dly1 = &rgsxdly[REVERBPOS];
|
||||
dly_t *const dly2 = &rgsxdly[REVERBPOS+1];
|
||||
|
@ -723,7 +717,7 @@ void RVB_DoReverb( int count )
|
|||
voutm = RVB_DoReverbForOneDly( dly1, vlr, paint );
|
||||
voutm += RVB_DoReverbForOneDly( dly2, vlr, paint );
|
||||
|
||||
if( dsp_coeff_table->value == 1.0f )
|
||||
if( dsp_coeff_table.value == 1.0f )
|
||||
voutm /= 6; // alpha
|
||||
else voutm = (11 * voutm) >> 6;
|
||||
|
||||
|
@ -739,18 +733,18 @@ RVB_DoAMod
|
|||
Do amplification modulation processing
|
||||
===========
|
||||
*/
|
||||
void RVB_DoAMod( int count )
|
||||
static void RVB_DoAMod( int count )
|
||||
{
|
||||
portable_samplepair_t *paint = paintto;
|
||||
|
||||
if( !sxmod_lowpass->value && !sxmod_mod->value )
|
||||
if( !sxmod_lowpass.value && !sxmod_mod.value )
|
||||
return;
|
||||
|
||||
for( ; count; count--, paint++ )
|
||||
{
|
||||
portable_samplepair_t res = *paint;
|
||||
|
||||
if( sxmod_lowpass->value )
|
||||
if( sxmod_lowpass.value )
|
||||
{
|
||||
res.left = rgsxlp[0] + rgsxlp[1] + rgsxlp[2] + rgsxlp[3] + rgsxlp[4] + res.left;
|
||||
res.right = rgsxlp[5] + rgsxlp[6] + rgsxlp[7] + rgsxlp[8] + rgsxlp[9] + res.right;
|
||||
|
@ -772,7 +766,7 @@ void RVB_DoAMod( int count )
|
|||
rgsxlp[8] = rgsxlp[9];
|
||||
}
|
||||
|
||||
if( sxmod_mod->value )
|
||||
if( sxmod_mod.value )
|
||||
{
|
||||
if( --sxmod1cur < 0 )
|
||||
sxmod1cur = sxmod1;
|
||||
|
@ -814,7 +808,7 @@ DSP_Process
|
|||
*/
|
||||
void DSP_Process( int idsp, portable_samplepair_t *pbfront, int sampleCount )
|
||||
{
|
||||
if( dsp_off->value )
|
||||
if( dsp_off.value )
|
||||
return;
|
||||
|
||||
// don't process DSP while in menu
|
||||
|
@ -852,12 +846,12 @@ CheckNewDspPresets
|
|||
*/
|
||||
void CheckNewDspPresets( void )
|
||||
{
|
||||
if( dsp_off->value != 0.0f )
|
||||
if( dsp_off.value != 0.0f )
|
||||
return;
|
||||
|
||||
if( FBitSet( dsp_coeff_table->flags, FCVAR_CHANGED ))
|
||||
if( FBitSet( dsp_coeff_table.flags, FCVAR_CHANGED ))
|
||||
{
|
||||
switch( (int)dsp_coeff_table->value )
|
||||
switch( (int)dsp_coeff_table.value )
|
||||
{
|
||||
case 0: // release
|
||||
ptable = rgsxpre;
|
||||
|
@ -873,20 +867,20 @@ void CheckNewDspPresets( void )
|
|||
SX_ReloadRoomFX();
|
||||
room_typeprev = -1;
|
||||
|
||||
ClearBits( dsp_coeff_table->flags, FCVAR_CHANGED );
|
||||
ClearBits( dsp_coeff_table.flags, FCVAR_CHANGED );
|
||||
}
|
||||
|
||||
if( s_listener.waterlevel > 2 )
|
||||
idsp_room = roomwater_type->value;
|
||||
else idsp_room = room_type->value;
|
||||
idsp_room = roomwater_type.value;
|
||||
else idsp_room = room_type.value;
|
||||
|
||||
// don't pass invalid presets
|
||||
idsp_room = bound( 0, idsp_room, MAX_ROOM_TYPES );
|
||||
|
||||
if( FBitSet( hisound->flags, FCVAR_CHANGED ))
|
||||
if( FBitSet( hisound.flags, FCVAR_CHANGED ))
|
||||
{
|
||||
sxhires = hisound->value;
|
||||
ClearBits( hisound->flags, FCVAR_CHANGED );
|
||||
sxhires = hisound.value;
|
||||
ClearBits( hisound.flags, FCVAR_CHANGED );
|
||||
}
|
||||
|
||||
if( idsp_room == room_typeprev && idsp_room == 0 )
|
||||
|
@ -915,15 +909,15 @@ void CheckNewDspPresets( void )
|
|||
DLY_CheckNewDelayVal( );
|
||||
DLY_CheckNewStereoDelayVal();
|
||||
|
||||
ClearBits( sxrvb_size->flags, FCVAR_CHANGED );
|
||||
ClearBits( sxdly_delay->flags, FCVAR_CHANGED );
|
||||
ClearBits( sxste_delay->flags, FCVAR_CHANGED );
|
||||
ClearBits( sxrvb_size.flags, FCVAR_CHANGED );
|
||||
ClearBits( sxdly_delay.flags, FCVAR_CHANGED );
|
||||
ClearBits( sxste_delay.flags, FCVAR_CHANGED );
|
||||
}
|
||||
|
||||
void SX_Profiling_f( void )
|
||||
static void SX_Profiling_f( void )
|
||||
{
|
||||
portable_samplepair_t testbuffer[512];
|
||||
float oldroom = room_type->value;
|
||||
float oldroom = room_type.value;
|
||||
double start, end;
|
||||
int i, calls;
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ GNU General Public License for more details.
|
|||
*/
|
||||
|
||||
#include "common.h"
|
||||
#include "client.h"
|
||||
#include "sound.h"
|
||||
|
||||
// during registration it is possible to have more sounds
|
||||
|
@ -28,7 +29,6 @@ static sfx_t s_knownSfx[MAX_SFX];
|
|||
static sfx_t *s_sfxHashList[MAX_SFX_HASH];
|
||||
static string s_sentenceImmediateName; // keep dummy sentence name
|
||||
qboolean s_registering = false;
|
||||
int s_registration_sequence = 0;
|
||||
|
||||
/*
|
||||
=================
|
||||
|
@ -54,7 +54,7 @@ void S_SoundList_f( void )
|
|||
|
||||
if( sc->loopStart >= 0 ) Con_Printf( "L" );
|
||||
else Con_Printf( " " );
|
||||
if( sfx->name[0] == '*' )
|
||||
if( sfx->name[0] == '*' || !Q_strncmp( sfx->name, DEFAULT_SOUNDPATH, sizeof( DEFAULT_SOUNDPATH ) - 1 ))
|
||||
Con_Printf( " (%2db) %s : %s\n", sc->width * 8, Q_memprint( sc->size ), sfx->name );
|
||||
else Con_Printf( " (%2db) %s : " DEFAULT_SOUNDPATH "%s\n", sc->width * 8, Q_memprint( sc->size ), sfx->name );
|
||||
totalSfx++;
|
||||
|
@ -199,7 +199,7 @@ sfx_t *S_FindName( const char *pname, int *pfInCache )
|
|||
*pfInCache = ( sfx->cache != NULL ) ? true : false;
|
||||
}
|
||||
// prolonge registration
|
||||
sfx->servercount = s_registration_sequence;
|
||||
sfx->servercount = cl.servercount;
|
||||
return sfx;
|
||||
}
|
||||
}
|
||||
|
@ -219,7 +219,7 @@ sfx_t *S_FindName( const char *pname, int *pfInCache )
|
|||
memset( sfx, 0, sizeof( *sfx ));
|
||||
if( pfInCache ) *pfInCache = false;
|
||||
Q_strncpy( sfx->name, name, MAX_STRING );
|
||||
sfx->servercount = s_registration_sequence;
|
||||
sfx->servercount = cl.servercount;
|
||||
sfx->hashValue = COM_HashKey( sfx->name, MAX_SFX_HASH );
|
||||
|
||||
// link it in
|
||||
|
@ -273,7 +273,6 @@ void S_BeginRegistration( void )
|
|||
{
|
||||
int i;
|
||||
|
||||
s_registration_sequence++;
|
||||
snd_ambient = false;
|
||||
|
||||
// check for automatic ambient sounds
|
||||
|
@ -309,7 +308,7 @@ void S_EndRegistration( void )
|
|||
if( !sfx->name[0] || !Q_stricmp( sfx->name, "*default" ))
|
||||
continue; // don't release default sound
|
||||
|
||||
if( sfx->servercount != s_registration_sequence )
|
||||
if( sfx->servercount != cl.servercount )
|
||||
S_FreeSound( sfx ); // don't need this sound
|
||||
}
|
||||
|
||||
|
@ -349,7 +348,7 @@ sound_t S_RegisterSound( const char *name )
|
|||
sfx = S_FindName( name, NULL );
|
||||
if( !sfx ) return -1;
|
||||
|
||||
sfx->servercount = s_registration_sequence;
|
||||
sfx->servercount = cl.servercount;
|
||||
if( !s_registering ) S_LoadSound( sfx );
|
||||
|
||||
return sfx - s_knownSfx;
|
||||
|
|
|
@ -159,7 +159,7 @@ void S_UpdateSoundFade( void )
|
|||
}
|
||||
|
||||
// spline it.
|
||||
f = SimpleSpline( f );
|
||||
f = -( cos( M_PI * f ) - 1 ) / 2;
|
||||
f = bound( 0.0f, f, 1.0f );
|
||||
|
||||
soundfade.percent = soundfade.initial_percent * f;
|
||||
|
@ -197,6 +197,65 @@ qboolean SND_FStreamIsPlaying( sfx_t *sfx )
|
|||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
SND_GetChannelTimeLeft
|
||||
|
||||
TODO: this function needs to be removed after whole sound subsystem rewrite
|
||||
=================
|
||||
*/
|
||||
static int SND_GetChannelTimeLeft( const channel_t *ch )
|
||||
{
|
||||
int remaining;
|
||||
|
||||
if( ch->pMixer.finished || !ch->sfx || !ch->sfx->cache )
|
||||
return 0;
|
||||
|
||||
if( ch->isSentence ) // sentences are special, count all remaining words
|
||||
{
|
||||
int i;
|
||||
|
||||
if( !ch->currentWord )
|
||||
return 0;
|
||||
|
||||
// current word
|
||||
remaining = ch->currentWord->forcedEndSample - ch->currentWord->sample;
|
||||
|
||||
// here we count all remaining words, stopping if no sfx or sound file is available
|
||||
// see VOX_LoadWord
|
||||
for( i = ch->wordIndex + 1; i < ARRAYSIZE( ch->words ); i++ )
|
||||
{
|
||||
wavdata_t *sc;
|
||||
int end;
|
||||
|
||||
// don't continue with broken sentences
|
||||
if( !ch->words[i].sfx )
|
||||
break;
|
||||
|
||||
if( !( sc = S_LoadSound( ch->words[i].sfx )))
|
||||
break;
|
||||
|
||||
end = ch->words[i].end;
|
||||
|
||||
if( end )
|
||||
remaining += sc->samples * 0.01f * end;
|
||||
else remaining += sc->samples;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int curpos;
|
||||
int samples;
|
||||
|
||||
// handle position looping
|
||||
samples = ch->sfx->cache->samples;
|
||||
curpos = S_ConvertLoopedPosition( ch->sfx->cache, ch->pMixer.sample, ch->use_loop );
|
||||
remaining = bound( 0, samples - curpos, samples );
|
||||
}
|
||||
|
||||
return remaining;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
SND_PickDynamicChannel
|
||||
|
@ -246,11 +305,7 @@ channel_t *SND_PickDynamicChannel( int entnum, int channel, sfx_t *sfx, qboolean
|
|||
continue;
|
||||
|
||||
// try to pick the sound with the least amount of data left to play
|
||||
timeleft = 0;
|
||||
if( ch->sfx )
|
||||
{
|
||||
timeleft = 1; // ch->end - paintedtime
|
||||
}
|
||||
timeleft = SND_GetChannelTimeLeft( ch );
|
||||
|
||||
if( timeleft < life_left )
|
||||
{
|
||||
|
@ -533,8 +588,6 @@ void S_StartSound( const vec3_t pos, int ent, int chan, sound_t handle, float fv
|
|||
// spatialize
|
||||
memset( target_chan, 0, sizeof( *target_chan ));
|
||||
|
||||
pitch *= (sys_timescale.value + 1) / 2;
|
||||
|
||||
VectorCopy( pos, target_chan->origin );
|
||||
target_chan->staticsound = ( ent == 0 ) ? true : false;
|
||||
target_chan->use_loop = (flags & SND_STOP_LOOPING) ? false : true;
|
||||
|
@ -1129,7 +1182,7 @@ static uint S_RawSamplesStereo( portable_samplepair_t *rawsamples, uint rawend,
|
|||
S_RawEntSamples
|
||||
===================
|
||||
*/
|
||||
static void S_RawEntSamples( int entnum, uint samples, uint rate, word width, word channels, const byte *data, int snd_vol )
|
||||
void S_RawEntSamples( int entnum, uint samples, uint rate, word width, word channels, const byte *data, int snd_vol )
|
||||
{
|
||||
rawchan_t *ch;
|
||||
|
||||
|
@ -1239,36 +1292,6 @@ void S_StreamAviSamples( void *Avi, int entnum, float fvol, float attn, float sy
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
S_GetRawSamplesLength
|
||||
===================
|
||||
*/
|
||||
uint S_GetRawSamplesLength( int entnum )
|
||||
{
|
||||
rawchan_t *ch;
|
||||
|
||||
if( !( ch = S_FindRawChannel( entnum, false )))
|
||||
return 0;
|
||||
|
||||
return ch->s_rawend <= paintedtime ? 0 : (float)(ch->s_rawend - paintedtime) * DMA_MSEC_PER_SAMPLE;
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
S_ClearRawChannel
|
||||
===================
|
||||
*/
|
||||
void S_ClearRawChannel( int entnum )
|
||||
{
|
||||
rawchan_t *ch;
|
||||
|
||||
if( !( ch = S_FindRawChannel( entnum, false )))
|
||||
return;
|
||||
|
||||
ch->s_rawend = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
S_FreeIdleRawChannels
|
||||
|
@ -1288,6 +1311,9 @@ static void S_FreeIdleRawChannels( void )
|
|||
|
||||
if( ch->s_rawend >= paintedtime )
|
||||
continue;
|
||||
|
||||
if ( ch->entnum > 0 )
|
||||
SND_ForceCloseMouth( ch->entnum );
|
||||
|
||||
if(( paintedtime - ch->s_rawend ) / SOUND_DMA_SPEED >= S_RAW_SOUND_IDLE_SEC )
|
||||
{
|
||||
|
@ -1786,8 +1812,12 @@ void S_Music_f( void )
|
|||
|
||||
for( i = 0; i < 2; i++ )
|
||||
{
|
||||
const char *intro_path = va( "media/%s.%s", intro, ext[i] );
|
||||
const char *main_path = va( "media/%s.%s", main, ext[i] );
|
||||
char intro_path[MAX_VA_STRING];
|
||||
char main_path[MAX_VA_STRING];
|
||||
char track_path[MAX_VA_STRING];
|
||||
|
||||
Q_snprintf( intro_path, sizeof( intro_path ), "media/%s.%s", intro, ext[i] );
|
||||
Q_snprintf( main_path, sizeof( main_path ), "media/%s.%s", main, ext[i] );
|
||||
|
||||
if( FS_FileExists( intro_path, false ) && FS_FileExists( main_path, false ))
|
||||
{
|
||||
|
@ -1795,7 +1825,10 @@ void S_Music_f( void )
|
|||
S_StartBackgroundTrack( intro, main, 0, false );
|
||||
break;
|
||||
}
|
||||
else if( FS_FileExists( va( "media/%s.%s", track, ext[i] ), false ))
|
||||
|
||||
Q_snprintf( track_path, sizeof( track_path ), "media/%s.%s", track, ext[i] );
|
||||
|
||||
if( FS_FileExists( track_path, false ))
|
||||
{
|
||||
// single non-looped theme
|
||||
S_StartBackgroundTrack( track, NULL, 0, false );
|
||||
|
@ -1850,7 +1883,7 @@ S_SoundInfo_f
|
|||
*/
|
||||
void S_SoundInfo_f( void )
|
||||
{
|
||||
Con_Printf( "Audio: DirectSound\n" );
|
||||
Con_Printf( "Audio backend: %s\n", dma.backendName );
|
||||
Con_Printf( "%5d channel(s)\n", 2 );
|
||||
Con_Printf( "%5d samples\n", dma.samples );
|
||||
Con_Printf( "%5d bits/sample\n", 16 );
|
||||
|
@ -1860,6 +1893,33 @@ void S_SoundInfo_f( void )
|
|||
S_PrintBackgroundTrackState ();
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
S_VoiceRecordStart_f
|
||||
=================
|
||||
*/
|
||||
void S_VoiceRecordStart_f( void )
|
||||
{
|
||||
if( cls.state != ca_active || cls.legacymode )
|
||||
return;
|
||||
|
||||
Voice_RecordStart();
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
S_VoiceRecordStop_f
|
||||
=================
|
||||
*/
|
||||
void S_VoiceRecordStop_f( void )
|
||||
{
|
||||
if( cls.state != ca_active || !Voice_IsRecording() )
|
||||
return;
|
||||
|
||||
CL_AddVoiceToDatagram();
|
||||
Voice_RecordStop();
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
S_Init
|
||||
|
@ -1894,11 +1954,12 @@ qboolean S_Init( void )
|
|||
Cmd_AddCommand( "soundlist", S_SoundList_f, "display loaded sounds" );
|
||||
Cmd_AddCommand( "s_info", S_SoundInfo_f, "print sound system information" );
|
||||
Cmd_AddCommand( "s_fade", S_SoundFade_f, "fade all sounds then stop all" );
|
||||
Cmd_AddCommand( "+voicerecord", Cmd_Null_f, "start voice recording (non-implemented)" );
|
||||
Cmd_AddCommand( "-voicerecord", Cmd_Null_f, "stop voice recording (non-implemented)" );
|
||||
Cmd_AddCommand( "+voicerecord", S_VoiceRecordStart_f, "start voice recording" );
|
||||
Cmd_AddCommand( "-voicerecord", S_VoiceRecordStop_f, "stop voice recording" );
|
||||
Cmd_AddCommand( "spk", S_SayReliable_f, "reliable play a specified sententce" );
|
||||
Cmd_AddCommand( "speak", S_Say_f, "playing a specified sententce" );
|
||||
|
||||
dma.backendName = "None";
|
||||
if( !SNDDMA_Init( ) )
|
||||
{
|
||||
Con_Printf( "Audio: sound system can't be initialized\n" );
|
||||
|
|
|
@ -117,13 +117,6 @@ _inline void MIX_ActivatePaintbuffer( int ipaintbuffer )
|
|||
paintbuffers[ipaintbuffer].factive = true;
|
||||
}
|
||||
|
||||
// don't mix into this paintbuffer
|
||||
_inline void MIX_DeactivatePaintbuffer( int ipaintbuffer )
|
||||
{
|
||||
Assert( ipaintbuffer < CPAINTBUFFERS );
|
||||
paintbuffers[ipaintbuffer].factive = false;
|
||||
}
|
||||
|
||||
_inline void MIX_SetCurrentPaintbuffer( int ipaintbuffer )
|
||||
{
|
||||
Assert( ipaintbuffer < CPAINTBUFFERS );
|
||||
|
@ -169,12 +162,6 @@ _inline void MIX_ResetPaintbufferFilterCounters( void )
|
|||
paintbuffers[i].ifilter = FILTERTYPE_NONE;
|
||||
}
|
||||
|
||||
_inline void MIX_ResetPaintbufferFilterCounter( int ipaintbuffer )
|
||||
{
|
||||
Assert( ipaintbuffer < CPAINTBUFFERS );
|
||||
paintbuffers[ipaintbuffer].ifilter = 0;
|
||||
}
|
||||
|
||||
// return pointer to front paintbuffer pbuf, given index
|
||||
_inline portable_samplepair_t *MIX_GetPFrontFromIPaint( int ipaintbuffer )
|
||||
{
|
||||
|
@ -619,7 +606,9 @@ void MIX_MixChannelsToPaintbuffer( int endtime, int rate, int outputRate )
|
|||
ch->pitch = VOX_ModifyPitch( ch, ch->basePitch * 0.01f );
|
||||
else ch->pitch = ch->basePitch * 0.01f;
|
||||
|
||||
if( CL_GetEntityByIndex( ch->entnum ) && ( ch->entchannel == CHAN_VOICE ))
|
||||
ch->pitch *= ( sys_timescale.value + 1 ) / 2;
|
||||
|
||||
if( CL_GetEntityByIndex( ch->entnum ) && ( ch->entchannel == CHAN_VOICE || ch->entchannel == CHAN_STREAM ))
|
||||
{
|
||||
if( pSource->width == 1 )
|
||||
SND_MoveMouth8( ch, pSource, sampleCount );
|
||||
|
@ -895,43 +884,13 @@ void S_MixUpsample( int sampleCount, int filtertype )
|
|||
ppaint->ifilter++;
|
||||
}
|
||||
|
||||
void MIX_MixStreamBuffer( int end )
|
||||
{
|
||||
portable_samplepair_t *pbuf;
|
||||
rawchan_t *ch;
|
||||
|
||||
pbuf = MIX_GetPFrontFromIPaint( ISTREAMBUFFER );
|
||||
ch = S_FindRawChannel( S_RAW_SOUND_BACKGROUNDTRACK, false );
|
||||
|
||||
// clear the paint buffer
|
||||
if( s_listener.paused || !ch || ch->s_rawend < paintedtime )
|
||||
{
|
||||
memset( pbuf, 0, (end - paintedtime) * sizeof( portable_samplepair_t ));
|
||||
}
|
||||
else
|
||||
{
|
||||
int i, stop;
|
||||
|
||||
// copy from the streaming sound source
|
||||
stop = (end < ch->s_rawend) ? end : ch->s_rawend;
|
||||
|
||||
for( i = paintedtime; i < stop; i++ )
|
||||
{
|
||||
pbuf[i-paintedtime].left = ( ch->rawsamples[i & ( ch->max_samples - 1 )].left * ch->leftvol ) >> 8;
|
||||
pbuf[i-paintedtime].right = ( ch->rawsamples[i & ( ch->max_samples - 1 )].right * ch->rightvol ) >> 8;
|
||||
}
|
||||
|
||||
for( ; i < end; i++ )
|
||||
pbuf[i-paintedtime].left = pbuf[i-paintedtime].right = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void MIX_MixRawSamplesBuffer( int end )
|
||||
{
|
||||
portable_samplepair_t *pbuf;
|
||||
portable_samplepair_t *pbuf, *roombuf, *streambuf;
|
||||
uint i, j, stop;
|
||||
|
||||
pbuf = MIX_GetCurrentPaintbufferPtr()->pbuf;
|
||||
roombuf = MIX_GetPFrontFromIPaint( IROOMBUFFER );
|
||||
streambuf = MIX_GetPFrontFromIPaint( ISTREAMBUFFER );
|
||||
|
||||
if( s_listener.paused ) return;
|
||||
|
||||
|
@ -939,16 +898,19 @@ void MIX_MixRawSamplesBuffer( int end )
|
|||
for( i = 0; i < MAX_RAW_CHANNELS; i++ )
|
||||
{
|
||||
// copy from the streaming sound source
|
||||
rawchan_t *ch = raw_channels[i];
|
||||
rawchan_t *ch = raw_channels[i];
|
||||
qboolean stream;
|
||||
|
||||
// background track should be mixing into another buffer
|
||||
if( !ch || ch->entnum == S_RAW_SOUND_BACKGROUNDTRACK )
|
||||
if( !ch )
|
||||
continue;
|
||||
|
||||
// not audible
|
||||
if( !ch->leftvol && !ch->rightvol )
|
||||
continue;
|
||||
|
||||
stream = ch->entnum == S_RAW_SOUND_BACKGROUNDTRACK || CL_IsPlayerIndex( ch->entnum );
|
||||
pbuf = stream ? streambuf : roombuf;
|
||||
|
||||
stop = (end < ch->s_rawend) ? end : ch->s_rawend;
|
||||
|
||||
for( j = paintedtime; j < stop; j++ )
|
||||
|
@ -956,6 +918,9 @@ void MIX_MixRawSamplesBuffer( int end )
|
|||
pbuf[j-paintedtime].left += ( ch->rawsamples[j & ( ch->max_samples - 1 )].left * ch->leftvol ) >> 8;
|
||||
pbuf[j-paintedtime].right += ( ch->rawsamples[j & ( ch->max_samples - 1 )].right * ch->rightvol ) >> 8;
|
||||
}
|
||||
|
||||
if( ch->entnum > 0 )
|
||||
SND_MoveMouthRaw( ch, &ch->rawsamples[paintedtime & ( ch->max_samples - 1 )], stop - paintedtime );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -965,9 +930,6 @@ void MIX_MixRawSamplesBuffer( int end )
|
|||
// caller also remixes all into final IPAINTBUFFER output.
|
||||
void MIX_UpsampleAllPaintbuffers( int end, int count )
|
||||
{
|
||||
// process stream buffer
|
||||
MIX_MixStreamBuffer( end );
|
||||
|
||||
// 11khz sounds are mixed into 3 buffers based on distance from listener, and facing direction
|
||||
// These buffers are facing, facingaway, room
|
||||
// These 3 mixed buffers are then each upsampled to 22khz.
|
||||
|
@ -1009,7 +971,6 @@ void MIX_UpsampleAllPaintbuffers( int end, int count )
|
|||
#endif
|
||||
|
||||
// mix raw samples from the video streams
|
||||
MIX_SetCurrentPaintbuffer( IROOMBUFFER );
|
||||
MIX_MixRawSamplesBuffer( end );
|
||||
|
||||
MIX_DeactivateAllPaintbuffers();
|
||||
|
|
|
@ -24,17 +24,7 @@ void SND_InitMouth( int entnum, int entchannel )
|
|||
{
|
||||
if(( entchannel == CHAN_VOICE || entchannel == CHAN_STREAM ) && entnum > 0 )
|
||||
{
|
||||
cl_entity_t *clientEntity;
|
||||
|
||||
// init mouth movement vars
|
||||
clientEntity = CL_GetEntityByIndex( entnum );
|
||||
|
||||
if( clientEntity )
|
||||
{
|
||||
clientEntity->mouth.mouthopen = 0;
|
||||
clientEntity->mouth.sndcount = 0;
|
||||
clientEntity->mouth.sndavg = 0;
|
||||
}
|
||||
SND_ForceInitMouth( entnum );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -42,15 +32,7 @@ void SND_CloseMouth( channel_t *ch )
|
|||
{
|
||||
if( ch->entchannel == CHAN_VOICE || ch->entchannel == CHAN_STREAM )
|
||||
{
|
||||
cl_entity_t *clientEntity;
|
||||
|
||||
clientEntity = CL_GetEntityByIndex( ch->entnum );
|
||||
|
||||
if( clientEntity )
|
||||
{
|
||||
// shut mouth
|
||||
clientEntity->mouth.mouthopen = 0;
|
||||
}
|
||||
SND_ForceCloseMouth( ch->entnum );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -150,3 +132,68 @@ void SND_MoveMouth16( channel_t *ch, wavdata_t *pSource, int count )
|
|||
pMouth->sndcount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void SND_ForceInitMouth( int entnum )
|
||||
{
|
||||
cl_entity_t *clientEntity;
|
||||
|
||||
clientEntity = CL_GetEntityByIndex( entnum );
|
||||
|
||||
if( clientEntity )
|
||||
{
|
||||
clientEntity->mouth.mouthopen = 0;
|
||||
clientEntity->mouth.sndavg = 0;
|
||||
clientEntity->mouth.sndcount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void SND_ForceCloseMouth( int entnum )
|
||||
{
|
||||
cl_entity_t *clientEntity;
|
||||
|
||||
clientEntity = CL_GetEntityByIndex( entnum );
|
||||
|
||||
if( clientEntity )
|
||||
clientEntity->mouth.mouthopen = 0;
|
||||
}
|
||||
|
||||
void SND_MoveMouthRaw( rawchan_t *ch, portable_samplepair_t *pData, int count )
|
||||
{
|
||||
cl_entity_t *clientEntity;
|
||||
mouth_t *pMouth = NULL;
|
||||
int savg, data;
|
||||
int scount = 0;
|
||||
uint i;
|
||||
|
||||
clientEntity = CL_GetEntityByIndex( ch->entnum );
|
||||
if( !clientEntity ) return;
|
||||
|
||||
pMouth = &clientEntity->mouth;
|
||||
|
||||
if( pData == NULL )
|
||||
return;
|
||||
|
||||
i = 0;
|
||||
scount = pMouth->sndcount;
|
||||
savg = 0;
|
||||
|
||||
while ( i < count && scount < CAVGSAMPLES )
|
||||
{
|
||||
data = pData[i].left; // mono sound anyway
|
||||
data = ( bound( -32767, data, 0x7ffe ) >> 8 );
|
||||
savg += abs( data );
|
||||
|
||||
i += 80 + ( (byte)data & 0x1F );
|
||||
scount++;
|
||||
}
|
||||
|
||||
pMouth->sndavg += savg;
|
||||
pMouth->sndcount = (byte)scount;
|
||||
|
||||
if ( pMouth->sndcount >= CAVGSAMPLES )
|
||||
{
|
||||
pMouth->mouthopen = pMouth->sndavg / CAVGSAMPLES;
|
||||
pMouth->sndavg = 0;
|
||||
pMouth->sndcount = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -95,7 +95,7 @@ void S_StartBackgroundTrack( const char *introTrack, const char *mainTrack, int
|
|||
else Q_strncpy( s_bgTrack.loopName, mainTrack, sizeof( s_bgTrack.loopName ));
|
||||
|
||||
// open stream
|
||||
s_bgTrack.stream = FS_OpenStream( va( "media/%s", introTrack ));
|
||||
s_bgTrack.stream = FS_OpenStream( introTrack );
|
||||
Q_strncpy( s_bgTrack.current, introTrack, sizeof( s_bgTrack.current ));
|
||||
memset( &musicfade, 0, sizeof( musicfade )); // clear any soundfade
|
||||
s_bgTrack.source = cls.key_dest;
|
||||
|
@ -242,7 +242,7 @@ void S_StreamBackgroundTrack( void )
|
|||
if( s_bgTrack.loopName[0] )
|
||||
{
|
||||
FS_FreeStream( s_bgTrack.stream );
|
||||
s_bgTrack.stream = FS_OpenStream( va( "media/%s", s_bgTrack.loopName ));
|
||||
s_bgTrack.stream = FS_OpenStream( s_bgTrack.loopName );
|
||||
Q_strncpy( s_bgTrack.current, s_bgTrack.loopName, sizeof( s_bgTrack.current ));
|
||||
|
||||
if( !s_bgTrack.stream ) return;
|
||||
|
|
|
@ -16,7 +16,6 @@ GNU General Public License for more details.
|
|||
#include "common.h"
|
||||
#include "sound.h"
|
||||
#include "const.h"
|
||||
#include "sequence.h"
|
||||
#include <ctype.h>
|
||||
|
||||
static int cszrawsentences = 0;
|
||||
|
@ -142,7 +141,7 @@ static const char *VOX_GetDirectory( char *szpath, const char *psz, int nsize )
|
|||
|
||||
if( !p )
|
||||
{
|
||||
Q_strcpy( szpath, "vox/" );
|
||||
Q_strncpy( szpath, "vox/", nsize );
|
||||
return psz;
|
||||
}
|
||||
|
||||
|
@ -165,23 +164,11 @@ static const char *VOX_LookupString( const char *pszin )
|
|||
int i = -1, len;
|
||||
const char *c;
|
||||
|
||||
// check if we are a CSCZ or immediate sentence
|
||||
// check if we are an immediate sentence
|
||||
if( *pszin == '#' )
|
||||
{
|
||||
// Q_atoi is too smart and allows negative values
|
||||
// so check with Q_isdigit beforehand
|
||||
if( Q_isdigit( pszin + 1 ))
|
||||
{
|
||||
sentenceEntry_s *sentenceEntry;
|
||||
i = Q_atoi( pszin + 1 );
|
||||
if(( sentenceEntry = Sequence_GetSentenceByIndex( i )))
|
||||
return sentenceEntry->data;
|
||||
}
|
||||
else
|
||||
{
|
||||
// immediate sentence, probably coming from "speak" command
|
||||
return pszin + 1;
|
||||
}
|
||||
// immediate sentence, probably coming from "speak" command
|
||||
return pszin + 1;
|
||||
}
|
||||
|
||||
// check if we received an index
|
||||
|
|
|
@ -113,10 +113,11 @@ typedef struct snd_format_s
|
|||
typedef struct
|
||||
{
|
||||
snd_format_t format;
|
||||
int samples; // mono samples in buffer
|
||||
int samplepos; // in mono samples
|
||||
byte *buffer;
|
||||
int samples; // mono samples in buffer
|
||||
int samplepos; // in mono samples
|
||||
byte *buffer;
|
||||
qboolean initialized; // sound engine is active
|
||||
const char *backendName;
|
||||
} dma_t;
|
||||
|
||||
#include "vox.h"
|
||||
|
@ -202,7 +203,7 @@ typedef struct
|
|||
|
||||
#define MAX_DYNAMIC_CHANNELS (60 + NUM_AMBIENTS)
|
||||
#define MAX_CHANNELS (256 + MAX_DYNAMIC_CHANNELS) // Scourge Of Armagon has too many static sounds on hip2m4.bsp
|
||||
#define MAX_RAW_CHANNELS 16
|
||||
#define MAX_RAW_CHANNELS 48
|
||||
#define MAX_RAW_SAMPLES 8192
|
||||
|
||||
extern sound_t ambient_sfx[NUM_AMBIENTS];
|
||||
|
@ -218,7 +219,6 @@ extern dma_t dma;
|
|||
|
||||
extern convar_t s_musicvolume;
|
||||
extern convar_t s_lerping;
|
||||
extern convar_t *dsp_off;
|
||||
extern convar_t s_test; // cvar to testify new effects
|
||||
extern convar_t s_samplecount;
|
||||
extern convar_t snd_mute_losefocus;
|
||||
|
@ -271,11 +271,10 @@ int S_GetCurrentStaticSounds( soundlist_t *pout, int size );
|
|||
int S_GetCurrentDynamicSounds( soundlist_t *pout, int size );
|
||||
sfx_t *S_GetSfxByHandle( sound_t handle );
|
||||
rawchan_t *S_FindRawChannel( int entnum, qboolean create );
|
||||
void S_RawEntSamples( int entnum, uint samples, uint rate, word width, word channels, const byte *data, int snd_vol );
|
||||
void S_RawSamples( uint samples, uint rate, word width, word channels, const byte *data, int entnum );
|
||||
void S_StopSound( int entnum, int channel, const char *soundname );
|
||||
void S_UpdateFrame( struct ref_viewpass_s *rvp );
|
||||
uint S_GetRawSamplesLength( int entnum );
|
||||
void S_ClearRawChannel( int entnum );
|
||||
void S_StopAllSounds( qboolean ambient );
|
||||
void S_FreeSounds( void );
|
||||
|
||||
|
@ -283,9 +282,12 @@ void S_FreeSounds( void );
|
|||
// s_mouth.c
|
||||
//
|
||||
void SND_InitMouth( int entnum, int entchannel );
|
||||
void SND_ForceInitMouth( int entnum );
|
||||
void SND_MoveMouth8( channel_t *ch, wavdata_t *pSource, int count );
|
||||
void SND_MoveMouth16( channel_t *ch, wavdata_t *pSource, int count );
|
||||
void SND_MoveMouthRaw( rawchan_t *ch, portable_samplepair_t *pData, int count );
|
||||
void SND_CloseMouth( channel_t *ch );
|
||||
void SND_ForceCloseMouth( int entnum );
|
||||
|
||||
//
|
||||
// s_stream.c
|
||||
|
@ -301,6 +303,7 @@ void S_FadeMusicVolume( float fadePercent );
|
|||
//
|
||||
int S_ZeroCrossingAfter( wavdata_t *pWaveData, int sample );
|
||||
int S_ZeroCrossingBefore( wavdata_t *pWaveData, int sample );
|
||||
int S_ConvertLoopedPosition( wavdata_t *pSource, int samplePosition, qboolean use_loop );
|
||||
int S_GetOutputData( wavdata_t *pSource, void **pData, int samplePosition, int sampleCount, qboolean use_loop );
|
||||
void S_SetSampleStart( channel_t *pChan, wavdata_t *pSource, int newPosition );
|
||||
void S_SetSampleEnd( channel_t *pChan, wavdata_t *pSource, int newEndPosition );
|
||||
|
|
|
@ -218,6 +218,7 @@ void CL_TextMessageParse( byte *pMemFile, int fileSize )
|
|||
client_textmessage_t textMessages[MAX_MESSAGES];
|
||||
int i, nameHeapSize, textHeapSize, messageSize, nameOffset;
|
||||
int messageCount, lastNamePos;
|
||||
size_t textHeapSizeRemaining;
|
||||
|
||||
lastNamePos = 0;
|
||||
lineNumber = 0;
|
||||
|
@ -252,7 +253,7 @@ void CL_TextMessageParse( byte *pMemFile, int fileSize )
|
|||
Con_Reportf( "TextMessage: unexpected '}' found, line %d\n", lineNumber );
|
||||
return;
|
||||
}
|
||||
Q_strcpy( currentName, trim );
|
||||
Q_strncpy( currentName, trim, sizeof( currentName ));
|
||||
break;
|
||||
case MSGFILE_TEXT:
|
||||
if( IsEndOfText( trim ))
|
||||
|
@ -266,7 +267,7 @@ void CL_TextMessageParse( byte *pMemFile, int fileSize )
|
|||
return;
|
||||
}
|
||||
|
||||
Q_strcpy( nameHeap + lastNamePos, currentName );
|
||||
Q_strncpy( nameHeap + lastNamePos, currentName, sizeof( nameHeap ) - lastNamePos );
|
||||
|
||||
// terminate text in-place in the memory file
|
||||
// (it's temporary memory that will be deleted)
|
||||
|
@ -329,15 +330,20 @@ void CL_TextMessageParse( byte *pMemFile, int fileSize )
|
|||
|
||||
|
||||
// copy text & fixup pointers
|
||||
textHeapSizeRemaining = textHeapSize;
|
||||
pCurrentText = pNameHeap + nameHeapSize;
|
||||
|
||||
for( i = 0; i < messageCount; i++ )
|
||||
{
|
||||
size_t currentTextSize = Q_strlen( clgame.titles[i].pMessage ) + 1;
|
||||
|
||||
clgame.titles[i].pName = pNameHeap; // adjust name pointer (parallel buffer)
|
||||
Q_strcpy( pCurrentText, clgame.titles[i].pMessage ); // copy text over
|
||||
Q_strncpy( pCurrentText, clgame.titles[i].pMessage, textHeapSizeRemaining ); // copy text over
|
||||
clgame.titles[i].pMessage = pCurrentText;
|
||||
|
||||
pNameHeap += Q_strlen( pNameHeap ) + 1;
|
||||
pCurrentText += Q_strlen( pCurrentText ) + 1;
|
||||
pCurrentText += currentTextSize;
|
||||
textHeapSizeRemaining -= currentTextSize;
|
||||
}
|
||||
|
||||
if(( pCurrentText - (char *)clgame.titles ) != ( textHeapSize + nameHeapSize + messageSize ))
|
||||
|
|
|
@ -23,93 +23,101 @@ GNU General Public License for more details.
|
|||
#include "input.h"
|
||||
#include "platform/platform.h"
|
||||
|
||||
static enum VGUI_KeyCode s_pVirtualKeyTrans[256];
|
||||
static VGUI_DefaultCursor s_currentCursor;
|
||||
static HINSTANCE s_pVGuiSupport; // vgui_support library
|
||||
static convar_t *vgui_utf8 = NULL;
|
||||
CVAR_DEFINE_AUTO( vgui_utf8, "0", FCVAR_ARCHIVE, "enable utf-8 support for vgui text" );
|
||||
|
||||
void GAME_EXPORT *VGUI_EngineMalloc(size_t size)
|
||||
static void GAME_EXPORT *VGUI_EngineMalloc( size_t size );
|
||||
static void GAME_EXPORT VGUI_GetMousePos( int *, int * );
|
||||
static void GAME_EXPORT VGUI_CursorSelect( VGUI_DefaultCursor );
|
||||
static byte GAME_EXPORT VGUI_GetColor( int, int );
|
||||
static int GAME_EXPORT VGUI_UtfProcessChar( int in );
|
||||
static qboolean GAME_EXPORT VGUI_IsInGame( void );
|
||||
|
||||
static struct
|
||||
{
|
||||
qboolean initialized;
|
||||
vguiapi_t dllFuncs;
|
||||
VGUI_DefaultCursor cursor;
|
||||
|
||||
HINSTANCE hInstance;
|
||||
|
||||
enum VGUI_KeyCode virtualKeyTrans[256];
|
||||
} vgui =
|
||||
{
|
||||
false,
|
||||
{
|
||||
false, // Not initialized yet
|
||||
NULL, // VGUI_DrawInit,
|
||||
NULL, // VGUI_DrawShutdown,
|
||||
NULL, // VGUI_SetupDrawingText,
|
||||
NULL, // VGUI_SetupDrawingRect,
|
||||
NULL, // VGUI_SetupDrawingImage,
|
||||
NULL, // VGUI_BindTexture,
|
||||
NULL, // VGUI_EnableTexture,
|
||||
NULL, // VGUI_CreateTexture,
|
||||
NULL, // VGUI_UploadTexture,
|
||||
NULL, // VGUI_UploadTextureBlock,
|
||||
NULL, // VGUI_DrawQuad,
|
||||
NULL, // VGUI_GetTextureSizes,
|
||||
NULL, // VGUI_GenerateTexture,
|
||||
VGUI_EngineMalloc,
|
||||
VGUI_CursorSelect,
|
||||
VGUI_GetColor,
|
||||
VGUI_IsInGame,
|
||||
Key_EnableTextInput,
|
||||
VGUI_GetMousePos,
|
||||
VGUI_UtfProcessChar,
|
||||
Platform_GetClipboardText,
|
||||
Platform_SetClipboardText,
|
||||
Platform_GetKeyModifiers,
|
||||
},
|
||||
-1
|
||||
};
|
||||
|
||||
static void GAME_EXPORT *VGUI_EngineMalloc( size_t size )
|
||||
{
|
||||
return Z_Malloc( size );
|
||||
}
|
||||
|
||||
qboolean GAME_EXPORT VGUI_IsInGame( void )
|
||||
static qboolean GAME_EXPORT VGUI_IsInGame( void )
|
||||
{
|
||||
return cls.state == ca_active && cls.key_dest == key_game;
|
||||
}
|
||||
|
||||
void GAME_EXPORT VGUI_GetMousePos( int *_x, int *_y )
|
||||
static void GAME_EXPORT VGUI_GetMousePos( int *_x, int *_y )
|
||||
{
|
||||
float xscale = (float)refState.width / (float)clgame.scrInfo.iWidth;
|
||||
float yscale = (float)refState.height / (float)clgame.scrInfo.iHeight;
|
||||
int x, y;
|
||||
|
||||
Platform_GetMousePos( &x, &y );
|
||||
*_x = x / xscale, *_y = y / yscale;
|
||||
*_x = x / xscale;
|
||||
*_y = y / yscale;
|
||||
}
|
||||
|
||||
void GAME_EXPORT VGUI_CursorSelect( VGUI_DefaultCursor cursor )
|
||||
static void GAME_EXPORT VGUI_CursorSelect( VGUI_DefaultCursor cursor )
|
||||
{
|
||||
Platform_SetCursorType( cursor );
|
||||
s_currentCursor = cursor;
|
||||
if( vgui.cursor != cursor )
|
||||
Platform_SetCursorType( cursor );
|
||||
}
|
||||
|
||||
byte GAME_EXPORT VGUI_GetColor( int i, int j)
|
||||
static byte GAME_EXPORT VGUI_GetColor( int i, int j )
|
||||
{
|
||||
return g_color_table[i][j];
|
||||
}
|
||||
|
||||
// Define and initialize vgui API
|
||||
int GAME_EXPORT VGUI_UtfProcessChar( int in )
|
||||
static int GAME_EXPORT VGUI_UtfProcessChar( int in )
|
||||
{
|
||||
if( CVAR_TO_BOOL( vgui_utf8 ))
|
||||
if( vgui_utf8.value )
|
||||
return Con_UtfProcessCharForce( in );
|
||||
else
|
||||
return in;
|
||||
return in;
|
||||
}
|
||||
|
||||
vguiapi_t vgui =
|
||||
{
|
||||
false, // Not initialized yet
|
||||
NULL, // VGUI_DrawInit,
|
||||
NULL, // VGUI_DrawShutdown,
|
||||
NULL, // VGUI_SetupDrawingText,
|
||||
NULL, // VGUI_SetupDrawingRect,
|
||||
NULL, // VGUI_SetupDrawingImage,
|
||||
NULL, // VGUI_BindTexture,
|
||||
NULL, // VGUI_EnableTexture,
|
||||
NULL, // VGUI_CreateTexture,
|
||||
NULL, // VGUI_UploadTexture,
|
||||
NULL, // VGUI_UploadTextureBlock,
|
||||
NULL, // VGUI_DrawQuad,
|
||||
NULL, // VGUI_GetTextureSizes,
|
||||
NULL, // VGUI_GenerateTexture,
|
||||
VGUI_EngineMalloc,
|
||||
VGUI_CursorSelect,
|
||||
VGUI_GetColor,
|
||||
VGUI_IsInGame,
|
||||
NULL,
|
||||
VGUI_GetMousePos,
|
||||
VGUI_UtfProcessChar,
|
||||
Platform_GetClipboardText,
|
||||
Platform_SetClipboardText,
|
||||
Platform_GetKeyModifiers,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
qboolean VGui_IsActive( void )
|
||||
{
|
||||
return vgui.initialized;
|
||||
}
|
||||
|
||||
void VGui_FillAPIFromRef( vguiapi_t *to, const ref_interface_t *from )
|
||||
static void VGui_FillAPIFromRef( vguiapi_t *to, const ref_interface_t *from )
|
||||
{
|
||||
to->DrawInit = from->VGUI_DrawInit;
|
||||
to->DrawShutdown = from->VGUI_DrawShutdown;
|
||||
|
@ -126,137 +134,86 @@ void VGui_FillAPIFromRef( vguiapi_t *to, const ref_interface_t *from )
|
|||
to->GenerateTexture = from->VGUI_GenerateTexture;
|
||||
}
|
||||
|
||||
void VGui_RegisterCvars( void )
|
||||
{
|
||||
Cvar_RegisterVariable( &vgui_utf8 );
|
||||
}
|
||||
|
||||
qboolean VGui_LoadProgs( HINSTANCE hInstance )
|
||||
{
|
||||
void (*F)( vguiapi_t* );
|
||||
qboolean client = hInstance != NULL;
|
||||
|
||||
// not loading interface from client.dll, load vgui_support.dll instead
|
||||
if( !client )
|
||||
{
|
||||
string vguiloader, vguilib;
|
||||
|
||||
// HACKHACK: try to load path from custom path
|
||||
// to support having different versions of VGUI
|
||||
if( Sys_GetParmFromCmdLine( "-vguilib", vguilib ) && !COM_LoadLibrary( vguilib, false, false ))
|
||||
{
|
||||
Con_Reportf( S_WARN "VGUI preloading failed. Default library will be used! Reason: %s", COM_GetLibraryError());
|
||||
}
|
||||
|
||||
if( !Sys_GetParmFromCmdLine( "-vguiloader", vguiloader ))
|
||||
{
|
||||
Q_strncpy( vguiloader, VGUI_SUPPORT_DLL, sizeof( vguiloader ));
|
||||
}
|
||||
|
||||
hInstance = vgui.hInstance = COM_LoadLibrary( vguiloader, false, false );
|
||||
|
||||
if( !vgui.hInstance )
|
||||
{
|
||||
if( FS_FileExists( vguiloader, false ))
|
||||
Con_Reportf( S_ERROR "Failed to load vgui_support library: %s\n", COM_GetLibraryError() );
|
||||
else Con_Reportf( "vgui_support: not found\n" );
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// try legacy API first
|
||||
F = COM_GetProcAddress( hInstance, client ? "InitVGUISupportAPI" : "InitAPI" );
|
||||
|
||||
if( F )
|
||||
{
|
||||
VGui_FillAPIFromRef( &vgui.dllFuncs, &ref.dllFuncs );
|
||||
F( &vgui.dllFuncs );
|
||||
|
||||
vgui.initialized = vgui.dllFuncs.initialized = true;
|
||||
Con_Reportf( "vgui_support: initialized legacy API in %s module\n", client ? "client" : "support" );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Con_Reportf( S_ERROR "Failed to find VGUI support API entry point in %s module\n", client ? "client" : "support" );
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
VGui_Startup
|
||||
|
||||
Load vgui_support library and call VGui_Startup
|
||||
================
|
||||
*/
|
||||
void VGui_Startup( const char *clientlib, int width, int height )
|
||||
void VGui_Startup( int width, int height )
|
||||
{
|
||||
static qboolean failed = false;
|
||||
|
||||
void (*F) ( vguiapi_t * );
|
||||
char vguiloader[256];
|
||||
char vguilib[256];
|
||||
|
||||
vguiloader[0] = vguilib[0] = '\0';
|
||||
|
||||
if( failed )
|
||||
// vgui not initialized from both support and client modules, skip
|
||||
if( !vgui.initialized )
|
||||
return;
|
||||
|
||||
if( !vgui.initialized )
|
||||
{
|
||||
vgui_utf8 = Cvar_Get( "vgui_utf8", "0", FCVAR_ARCHIVE, "enable utf-8 support for vgui text" );
|
||||
height = Q_max( 480, height );
|
||||
|
||||
VGui_FillAPIFromRef( &vgui, &ref.dllFuncs );
|
||||
if( width <= 640 ) width = 640;
|
||||
else if( width <= 800 ) width = 800;
|
||||
else if( width <= 1024 ) width = 1024;
|
||||
else if( width <= 1152 ) width = 1152;
|
||||
else if( width <= 1280 ) width = 1280;
|
||||
else if( width <= 1600 ) width = 1600;
|
||||
|
||||
s_pVGuiSupport = COM_LoadLibrary( clientlib, false, false );
|
||||
|
||||
if( s_pVGuiSupport )
|
||||
{
|
||||
F = COM_GetProcAddress( s_pVGuiSupport, "InitVGUISupportAPI" );
|
||||
if( F )
|
||||
{
|
||||
F( &vgui );
|
||||
vgui.initialized = true;
|
||||
Con_Reportf( "vgui_support: found internal client support\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
COM_FreeLibrary( s_pVGuiSupport );
|
||||
}
|
||||
}
|
||||
|
||||
if( !vgui.initialized )
|
||||
{
|
||||
// HACKHACK: load vgui with correct path first if specified.
|
||||
// it will be reused while resolving vgui support and client deps
|
||||
if( Sys_GetParmFromCmdLine( "-vguilib", vguilib ))
|
||||
{
|
||||
if( Q_strstr( vguilib, ".dll" ))
|
||||
Q_strncpy( vguiloader, "vgui_support.dll", 256 );
|
||||
else
|
||||
Q_strncpy( vguiloader, VGUI_SUPPORT_DLL, 256 );
|
||||
|
||||
if( !COM_LoadLibrary( vguilib, false, false ))
|
||||
Con_Reportf( S_WARN "VGUI preloading failed. Default library will be used! Reason: %s\n", COM_GetLibraryError() );
|
||||
}
|
||||
|
||||
if( Q_strstr( clientlib, ".dll" ))
|
||||
Q_strncpy( vguiloader, "vgui_support.dll", 256 );
|
||||
|
||||
if( !vguiloader[0] && !Sys_GetParmFromCmdLine( "-vguiloader", vguiloader ))
|
||||
Q_strncpy( vguiloader, VGUI_SUPPORT_DLL, 256 );
|
||||
|
||||
s_pVGuiSupport = COM_LoadLibrary( vguiloader, false, false );
|
||||
|
||||
if( !s_pVGuiSupport )
|
||||
{
|
||||
s_pVGuiSupport = COM_LoadLibrary( va( "../%s", vguiloader ), false, false );
|
||||
}
|
||||
|
||||
if( !s_pVGuiSupport )
|
||||
{
|
||||
if( FS_FileExists( vguiloader, false ))
|
||||
{
|
||||
Con_Reportf( S_ERROR "Failed to load vgui_support library: %s\n", COM_GetLibraryError() );
|
||||
}
|
||||
else
|
||||
{
|
||||
Con_Reportf( "vgui_support: not found\n" );
|
||||
}
|
||||
failed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
F = COM_GetProcAddress( s_pVGuiSupport, "InitAPI" );
|
||||
if( F )
|
||||
{
|
||||
F( &vgui );
|
||||
vgui.initialized = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Con_Reportf( S_ERROR "Failed to find vgui_support library entry point!\n" );
|
||||
failed = true;
|
||||
COM_FreeLibrary( s_pVGuiSupport );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( height < 480 )
|
||||
height = 480;
|
||||
|
||||
if( width <= 640 )
|
||||
width = 640;
|
||||
else if( width <= 800 )
|
||||
width = 800;
|
||||
else if( width <= 1024 )
|
||||
width = 1024;
|
||||
else if( width <= 1152 )
|
||||
width = 1152;
|
||||
else if( width <= 1280 )
|
||||
width = 1280;
|
||||
else if( width <= 1600 )
|
||||
width = 1600;
|
||||
#ifdef XASH_DLL_LOADER
|
||||
else if ( Q_strstr( vguiloader, ".dll" ) )
|
||||
width = 1600;
|
||||
#endif
|
||||
|
||||
|
||||
if( vgui.initialized )
|
||||
{
|
||||
//host.mouse_visible = true;
|
||||
vgui.Startup( width, height );
|
||||
}
|
||||
else if ( COM_CheckString( clientlib ) )
|
||||
{
|
||||
failed = true;
|
||||
}
|
||||
if( vgui.dllFuncs.Startup )
|
||||
vgui.dllFuncs.Startup( width, height );
|
||||
}
|
||||
|
||||
|
||||
|
@ -270,214 +227,223 @@ Unload vgui_support library and call VGui_Shutdown
|
|||
*/
|
||||
void VGui_Shutdown( void )
|
||||
{
|
||||
if( vgui.Shutdown )
|
||||
vgui.Shutdown();
|
||||
if( vgui.dllFuncs.Shutdown )
|
||||
vgui.dllFuncs.Shutdown();
|
||||
|
||||
if( s_pVGuiSupport )
|
||||
COM_FreeLibrary( s_pVGuiSupport );
|
||||
s_pVGuiSupport = NULL;
|
||||
if( vgui.hInstance )
|
||||
COM_FreeLibrary( vgui.hInstance );
|
||||
|
||||
vgui.hInstance = NULL;
|
||||
vgui.initialized = false;
|
||||
}
|
||||
|
||||
|
||||
void VGUI_InitKeyTranslationTable( void )
|
||||
static void VGUI_InitKeyTranslationTable( void )
|
||||
{
|
||||
static qboolean bInitted = false;
|
||||
static qboolean initialized = false;
|
||||
|
||||
if( bInitted )
|
||||
return;
|
||||
bInitted = true;
|
||||
if( initialized ) return;
|
||||
|
||||
initialized = true;
|
||||
|
||||
// set virtual key translation table
|
||||
memset( s_pVirtualKeyTrans, -1, sizeof( s_pVirtualKeyTrans ) );
|
||||
memset( vgui.virtualKeyTrans, -1, sizeof( vgui.virtualKeyTrans ) );
|
||||
|
||||
s_pVirtualKeyTrans['0'] = KEY_0;
|
||||
s_pVirtualKeyTrans['1'] = KEY_1;
|
||||
s_pVirtualKeyTrans['2'] = KEY_2;
|
||||
s_pVirtualKeyTrans['3'] = KEY_3;
|
||||
s_pVirtualKeyTrans['4'] = KEY_4;
|
||||
s_pVirtualKeyTrans['5'] = KEY_5;
|
||||
s_pVirtualKeyTrans['6'] = KEY_6;
|
||||
s_pVirtualKeyTrans['7'] = KEY_7;
|
||||
s_pVirtualKeyTrans['8'] = KEY_8;
|
||||
s_pVirtualKeyTrans['9'] = KEY_9;
|
||||
s_pVirtualKeyTrans['A'] = s_pVirtualKeyTrans['a'] = KEY_A;
|
||||
s_pVirtualKeyTrans['B'] = s_pVirtualKeyTrans['b'] = KEY_B;
|
||||
s_pVirtualKeyTrans['C'] = s_pVirtualKeyTrans['c'] = KEY_C;
|
||||
s_pVirtualKeyTrans['D'] = s_pVirtualKeyTrans['d'] = KEY_D;
|
||||
s_pVirtualKeyTrans['E'] = s_pVirtualKeyTrans['e'] = KEY_E;
|
||||
s_pVirtualKeyTrans['F'] = s_pVirtualKeyTrans['f'] = KEY_F;
|
||||
s_pVirtualKeyTrans['G'] = s_pVirtualKeyTrans['g'] = KEY_G;
|
||||
s_pVirtualKeyTrans['H'] = s_pVirtualKeyTrans['h'] = KEY_H;
|
||||
s_pVirtualKeyTrans['I'] = s_pVirtualKeyTrans['i'] = KEY_I;
|
||||
s_pVirtualKeyTrans['J'] = s_pVirtualKeyTrans['j'] = KEY_J;
|
||||
s_pVirtualKeyTrans['K'] = s_pVirtualKeyTrans['k'] = KEY_K;
|
||||
s_pVirtualKeyTrans['L'] = s_pVirtualKeyTrans['l'] = KEY_L;
|
||||
s_pVirtualKeyTrans['M'] = s_pVirtualKeyTrans['m'] = KEY_M;
|
||||
s_pVirtualKeyTrans['N'] = s_pVirtualKeyTrans['n'] = KEY_N;
|
||||
s_pVirtualKeyTrans['O'] = s_pVirtualKeyTrans['o'] = KEY_O;
|
||||
s_pVirtualKeyTrans['P'] = s_pVirtualKeyTrans['p'] = KEY_P;
|
||||
s_pVirtualKeyTrans['Q'] = s_pVirtualKeyTrans['q'] = KEY_Q;
|
||||
s_pVirtualKeyTrans['R'] = s_pVirtualKeyTrans['r'] = KEY_R;
|
||||
s_pVirtualKeyTrans['S'] = s_pVirtualKeyTrans['s'] = KEY_S;
|
||||
s_pVirtualKeyTrans['T'] = s_pVirtualKeyTrans['t'] = KEY_T;
|
||||
s_pVirtualKeyTrans['U'] = s_pVirtualKeyTrans['u'] = KEY_U;
|
||||
s_pVirtualKeyTrans['V'] = s_pVirtualKeyTrans['v'] = KEY_V;
|
||||
s_pVirtualKeyTrans['W'] = s_pVirtualKeyTrans['w'] = KEY_W;
|
||||
s_pVirtualKeyTrans['X'] = s_pVirtualKeyTrans['x'] = KEY_X;
|
||||
s_pVirtualKeyTrans['Y'] = s_pVirtualKeyTrans['y'] = KEY_Y;
|
||||
s_pVirtualKeyTrans['Z'] = s_pVirtualKeyTrans['z'] = KEY_Z;
|
||||
// TODO: engine keys are not enough here!
|
||||
// make crossplatform way to pass SDL keys here
|
||||
|
||||
s_pVirtualKeyTrans[K_KP_5 - 5] = KEY_PAD_0;
|
||||
s_pVirtualKeyTrans[K_KP_5 - 4] = KEY_PAD_1;
|
||||
s_pVirtualKeyTrans[K_KP_5 - 3] = KEY_PAD_2;
|
||||
s_pVirtualKeyTrans[K_KP_5 - 2] = KEY_PAD_3;
|
||||
s_pVirtualKeyTrans[K_KP_5 - 1] = KEY_PAD_4;
|
||||
s_pVirtualKeyTrans[K_KP_5 - 0] = KEY_PAD_5;
|
||||
s_pVirtualKeyTrans[K_KP_5 + 1] = KEY_PAD_6;
|
||||
s_pVirtualKeyTrans[K_KP_5 + 2] = KEY_PAD_7;
|
||||
s_pVirtualKeyTrans[K_KP_5 + 3] = KEY_PAD_8;
|
||||
s_pVirtualKeyTrans[K_KP_5 + 4] = KEY_PAD_9;
|
||||
s_pVirtualKeyTrans[K_KP_SLASH] = KEY_PAD_DIVIDE;
|
||||
s_pVirtualKeyTrans['*'] = KEY_PAD_MULTIPLY;
|
||||
s_pVirtualKeyTrans[K_KP_MINUS] = KEY_PAD_MINUS;
|
||||
s_pVirtualKeyTrans[K_KP_PLUS] = KEY_PAD_PLUS;
|
||||
s_pVirtualKeyTrans[K_KP_ENTER] = KEY_PAD_ENTER;
|
||||
//s_pVirtualKeyTrans[K_KP_DECIMAL] = KEY_PAD_DECIMAL;
|
||||
s_pVirtualKeyTrans['['] = KEY_LBRACKET;
|
||||
s_pVirtualKeyTrans[']'] = KEY_RBRACKET;
|
||||
s_pVirtualKeyTrans[';'] = KEY_SEMICOLON;
|
||||
s_pVirtualKeyTrans['\''] = KEY_APOSTROPHE;
|
||||
s_pVirtualKeyTrans['`'] = KEY_BACKQUOTE;
|
||||
s_pVirtualKeyTrans[','] = KEY_COMMA;
|
||||
s_pVirtualKeyTrans['.'] = KEY_PERIOD;
|
||||
s_pVirtualKeyTrans[K_KP_SLASH] = KEY_SLASH;
|
||||
s_pVirtualKeyTrans['\\'] = KEY_BACKSLASH;
|
||||
s_pVirtualKeyTrans['-'] = KEY_MINUS;
|
||||
s_pVirtualKeyTrans['='] = KEY_EQUAL;
|
||||
s_pVirtualKeyTrans[K_ENTER] = KEY_ENTER;
|
||||
s_pVirtualKeyTrans[K_SPACE] = KEY_SPACE;
|
||||
s_pVirtualKeyTrans[K_BACKSPACE] = KEY_BACKSPACE;
|
||||
s_pVirtualKeyTrans[K_TAB] = KEY_TAB;
|
||||
s_pVirtualKeyTrans[K_CAPSLOCK] = KEY_CAPSLOCK;
|
||||
s_pVirtualKeyTrans[K_KP_NUMLOCK] = KEY_NUMLOCK;
|
||||
s_pVirtualKeyTrans[K_ESCAPE] = KEY_ESCAPE;
|
||||
//s_pVirtualKeyTrans[K_KP_SCROLLLOCK] = KEY_SCROLLLOCK;
|
||||
s_pVirtualKeyTrans[K_INS] = KEY_INSERT;
|
||||
s_pVirtualKeyTrans[K_DEL] = KEY_DELETE;
|
||||
s_pVirtualKeyTrans[K_HOME] = KEY_HOME;
|
||||
s_pVirtualKeyTrans[K_END] = KEY_END;
|
||||
s_pVirtualKeyTrans[K_PGUP] = KEY_PAGEUP;
|
||||
s_pVirtualKeyTrans[K_PGDN] = KEY_PAGEDOWN;
|
||||
s_pVirtualKeyTrans[K_PAUSE] = KEY_BREAK;
|
||||
//s_pVirtualKeyTrans[K_SHIFT] = KEY_RSHIFT;
|
||||
s_pVirtualKeyTrans[K_SHIFT] = KEY_LSHIFT; // SHIFT -> left SHIFT
|
||||
//s_pVirtualKeyTrans[SDLK_RALT] = KEY_RALT;
|
||||
s_pVirtualKeyTrans[K_ALT] = KEY_LALT; // ALT -> left ALT
|
||||
//s_pVirtualKeyTrans[SDLK_RCTRL] = KEY_RCONTROL;
|
||||
s_pVirtualKeyTrans[K_CTRL] = KEY_LCONTROL; // CTRL -> left CTRL
|
||||
s_pVirtualKeyTrans[K_WIN] = KEY_LWIN;
|
||||
//s_pVirtualKeyTrans[SDLK_APPLICATION] = KEY_RWIN;
|
||||
//s_pVirtualKeyTrans[K_WIN] = KEY_APP;
|
||||
s_pVirtualKeyTrans[K_UPARROW] = KEY_UP;
|
||||
s_pVirtualKeyTrans[K_LEFTARROW] = KEY_LEFT;
|
||||
s_pVirtualKeyTrans[K_DOWNARROW] = KEY_DOWN;
|
||||
s_pVirtualKeyTrans[K_RIGHTARROW] = KEY_RIGHT;
|
||||
s_pVirtualKeyTrans[K_F1] = KEY_F1;
|
||||
s_pVirtualKeyTrans[K_F2] = KEY_F2;
|
||||
s_pVirtualKeyTrans[K_F3] = KEY_F3;
|
||||
s_pVirtualKeyTrans[K_F4] = KEY_F4;
|
||||
s_pVirtualKeyTrans[K_F5] = KEY_F5;
|
||||
s_pVirtualKeyTrans[K_F6] = KEY_F6;
|
||||
s_pVirtualKeyTrans[K_F7] = KEY_F7;
|
||||
s_pVirtualKeyTrans[K_F8] = KEY_F8;
|
||||
s_pVirtualKeyTrans[K_F9] = KEY_F9;
|
||||
s_pVirtualKeyTrans[K_F10] = KEY_F10;
|
||||
s_pVirtualKeyTrans[K_F11] = KEY_F11;
|
||||
s_pVirtualKeyTrans[K_F12] = KEY_F12;
|
||||
vgui.virtualKeyTrans['0'] = KEY_0;
|
||||
vgui.virtualKeyTrans['1'] = KEY_1;
|
||||
vgui.virtualKeyTrans['2'] = KEY_2;
|
||||
vgui.virtualKeyTrans['3'] = KEY_3;
|
||||
vgui.virtualKeyTrans['4'] = KEY_4;
|
||||
vgui.virtualKeyTrans['5'] = KEY_5;
|
||||
vgui.virtualKeyTrans['6'] = KEY_6;
|
||||
vgui.virtualKeyTrans['7'] = KEY_7;
|
||||
vgui.virtualKeyTrans['8'] = KEY_8;
|
||||
vgui.virtualKeyTrans['9'] = KEY_9;
|
||||
vgui.virtualKeyTrans['A'] = vgui.virtualKeyTrans['a'] = KEY_A;
|
||||
vgui.virtualKeyTrans['B'] = vgui.virtualKeyTrans['b'] = KEY_B;
|
||||
vgui.virtualKeyTrans['C'] = vgui.virtualKeyTrans['c'] = KEY_C;
|
||||
vgui.virtualKeyTrans['D'] = vgui.virtualKeyTrans['d'] = KEY_D;
|
||||
vgui.virtualKeyTrans['E'] = vgui.virtualKeyTrans['e'] = KEY_E;
|
||||
vgui.virtualKeyTrans['F'] = vgui.virtualKeyTrans['f'] = KEY_F;
|
||||
vgui.virtualKeyTrans['G'] = vgui.virtualKeyTrans['g'] = KEY_G;
|
||||
vgui.virtualKeyTrans['H'] = vgui.virtualKeyTrans['h'] = KEY_H;
|
||||
vgui.virtualKeyTrans['I'] = vgui.virtualKeyTrans['i'] = KEY_I;
|
||||
vgui.virtualKeyTrans['J'] = vgui.virtualKeyTrans['j'] = KEY_J;
|
||||
vgui.virtualKeyTrans['K'] = vgui.virtualKeyTrans['k'] = KEY_K;
|
||||
vgui.virtualKeyTrans['L'] = vgui.virtualKeyTrans['l'] = KEY_L;
|
||||
vgui.virtualKeyTrans['M'] = vgui.virtualKeyTrans['m'] = KEY_M;
|
||||
vgui.virtualKeyTrans['N'] = vgui.virtualKeyTrans['n'] = KEY_N;
|
||||
vgui.virtualKeyTrans['O'] = vgui.virtualKeyTrans['o'] = KEY_O;
|
||||
vgui.virtualKeyTrans['P'] = vgui.virtualKeyTrans['p'] = KEY_P;
|
||||
vgui.virtualKeyTrans['Q'] = vgui.virtualKeyTrans['q'] = KEY_Q;
|
||||
vgui.virtualKeyTrans['R'] = vgui.virtualKeyTrans['r'] = KEY_R;
|
||||
vgui.virtualKeyTrans['S'] = vgui.virtualKeyTrans['s'] = KEY_S;
|
||||
vgui.virtualKeyTrans['T'] = vgui.virtualKeyTrans['t'] = KEY_T;
|
||||
vgui.virtualKeyTrans['U'] = vgui.virtualKeyTrans['u'] = KEY_U;
|
||||
vgui.virtualKeyTrans['V'] = vgui.virtualKeyTrans['v'] = KEY_V;
|
||||
vgui.virtualKeyTrans['W'] = vgui.virtualKeyTrans['w'] = KEY_W;
|
||||
vgui.virtualKeyTrans['X'] = vgui.virtualKeyTrans['x'] = KEY_X;
|
||||
vgui.virtualKeyTrans['Y'] = vgui.virtualKeyTrans['y'] = KEY_Y;
|
||||
vgui.virtualKeyTrans['Z'] = vgui.virtualKeyTrans['z'] = KEY_Z;
|
||||
|
||||
vgui.virtualKeyTrans[K_KP_5 - 5] = KEY_PAD_0;
|
||||
vgui.virtualKeyTrans[K_KP_5 - 4] = KEY_PAD_1;
|
||||
vgui.virtualKeyTrans[K_KP_5 - 3] = KEY_PAD_2;
|
||||
vgui.virtualKeyTrans[K_KP_5 - 2] = KEY_PAD_3;
|
||||
vgui.virtualKeyTrans[K_KP_5 - 1] = KEY_PAD_4;
|
||||
vgui.virtualKeyTrans[K_KP_5 - 0] = KEY_PAD_5;
|
||||
vgui.virtualKeyTrans[K_KP_5 + 1] = KEY_PAD_6;
|
||||
vgui.virtualKeyTrans[K_KP_5 + 2] = KEY_PAD_7;
|
||||
vgui.virtualKeyTrans[K_KP_5 + 3] = KEY_PAD_8;
|
||||
vgui.virtualKeyTrans[K_KP_5 + 4] = KEY_PAD_9;
|
||||
vgui.virtualKeyTrans[K_KP_SLASH] = KEY_PAD_DIVIDE;
|
||||
vgui.virtualKeyTrans['*'] = KEY_PAD_MULTIPLY;
|
||||
vgui.virtualKeyTrans[K_KP_MINUS] = KEY_PAD_MINUS;
|
||||
vgui.virtualKeyTrans[K_KP_PLUS] = KEY_PAD_PLUS;
|
||||
vgui.virtualKeyTrans[K_KP_ENTER] = KEY_PAD_ENTER;
|
||||
vgui.virtualKeyTrans[K_KP_NUMLOCK] = KEY_NUMLOCK;
|
||||
vgui.virtualKeyTrans['['] = KEY_LBRACKET;
|
||||
vgui.virtualKeyTrans[']'] = KEY_RBRACKET;
|
||||
vgui.virtualKeyTrans[';'] = KEY_SEMICOLON;
|
||||
vgui.virtualKeyTrans['`'] = KEY_BACKQUOTE;
|
||||
vgui.virtualKeyTrans[','] = KEY_COMMA;
|
||||
vgui.virtualKeyTrans['.'] = KEY_PERIOD;
|
||||
vgui.virtualKeyTrans['-'] = KEY_MINUS;
|
||||
vgui.virtualKeyTrans['='] = KEY_EQUAL;
|
||||
vgui.virtualKeyTrans['/'] = KEY_SLASH;
|
||||
vgui.virtualKeyTrans['\\'] = KEY_BACKSLASH;
|
||||
vgui.virtualKeyTrans['\''] = KEY_APOSTROPHE;
|
||||
vgui.virtualKeyTrans[K_TAB] = KEY_TAB;
|
||||
vgui.virtualKeyTrans[K_ENTER] = KEY_ENTER;
|
||||
vgui.virtualKeyTrans[K_SPACE] = KEY_SPACE;
|
||||
vgui.virtualKeyTrans[K_CAPSLOCK] = KEY_CAPSLOCK;
|
||||
vgui.virtualKeyTrans[K_BACKSPACE] = KEY_BACKSPACE;
|
||||
vgui.virtualKeyTrans[K_ESCAPE] = KEY_ESCAPE;
|
||||
vgui.virtualKeyTrans[K_INS] = KEY_INSERT;
|
||||
vgui.virtualKeyTrans[K_DEL] = KEY_DELETE;
|
||||
vgui.virtualKeyTrans[K_HOME] = KEY_HOME;
|
||||
vgui.virtualKeyTrans[K_END] = KEY_END;
|
||||
vgui.virtualKeyTrans[K_PGUP] = KEY_PAGEUP;
|
||||
vgui.virtualKeyTrans[K_PGDN] = KEY_PAGEDOWN;
|
||||
vgui.virtualKeyTrans[K_PAUSE] = KEY_BREAK;
|
||||
vgui.virtualKeyTrans[K_SHIFT] = KEY_LSHIFT; // SHIFT -> left SHIFT
|
||||
vgui.virtualKeyTrans[K_ALT] = KEY_LALT; // ALT -> left ALT
|
||||
vgui.virtualKeyTrans[K_CTRL] = KEY_LCONTROL; // CTRL -> left CTRL
|
||||
vgui.virtualKeyTrans[K_WIN] = KEY_LWIN;
|
||||
vgui.virtualKeyTrans[K_UPARROW] = KEY_UP;
|
||||
vgui.virtualKeyTrans[K_LEFTARROW] = KEY_LEFT;
|
||||
vgui.virtualKeyTrans[K_DOWNARROW] = KEY_DOWN;
|
||||
vgui.virtualKeyTrans[K_RIGHTARROW] = KEY_RIGHT;
|
||||
vgui.virtualKeyTrans[K_F1] = KEY_F1;
|
||||
vgui.virtualKeyTrans[K_F2] = KEY_F2;
|
||||
vgui.virtualKeyTrans[K_F3] = KEY_F3;
|
||||
vgui.virtualKeyTrans[K_F4] = KEY_F4;
|
||||
vgui.virtualKeyTrans[K_F5] = KEY_F5;
|
||||
vgui.virtualKeyTrans[K_F6] = KEY_F6;
|
||||
vgui.virtualKeyTrans[K_F7] = KEY_F7;
|
||||
vgui.virtualKeyTrans[K_F8] = KEY_F8;
|
||||
vgui.virtualKeyTrans[K_F9] = KEY_F9;
|
||||
vgui.virtualKeyTrans[K_F10] = KEY_F10;
|
||||
vgui.virtualKeyTrans[K_F11] = KEY_F11;
|
||||
vgui.virtualKeyTrans[K_F12] = KEY_F12;
|
||||
}
|
||||
|
||||
enum VGUI_KeyCode VGUI_MapKey( int keyCode )
|
||||
static enum VGUI_KeyCode VGUI_MapKey( int keyCode )
|
||||
{
|
||||
VGUI_InitKeyTranslationTable();
|
||||
|
||||
if( keyCode < 0 || keyCode >= (int)sizeof( s_pVirtualKeyTrans ) / (int)sizeof( s_pVirtualKeyTrans[0] ))
|
||||
{
|
||||
//Assert( false );
|
||||
return (enum VGUI_KeyCode)-1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return s_pVirtualKeyTrans[keyCode];
|
||||
}
|
||||
if( keyCode >= 0 && keyCode < ARRAYSIZE( vgui.virtualKeyTrans ))
|
||||
return vgui.virtualKeyTrans[keyCode];
|
||||
|
||||
return (enum VGUI_KeyCode)-1;
|
||||
}
|
||||
|
||||
void VGui_KeyEvent( int key, int down )
|
||||
void VGui_MouseEvent( int key, int clicks )
|
||||
{
|
||||
if( !vgui.initialized )
|
||||
enum VGUI_MouseAction mact;
|
||||
enum VGUI_MouseCode code;
|
||||
|
||||
if( !vgui.dllFuncs.Mouse )
|
||||
return;
|
||||
|
||||
switch( key )
|
||||
{
|
||||
case K_MOUSE1:
|
||||
if( down && host.mouse_visible ) {
|
||||
Key_EnableTextInput(true, false);
|
||||
}
|
||||
vgui.Mouse( down ? MA_PRESSED : MA_RELEASED, MOUSE_LEFT );
|
||||
return;
|
||||
case K_MOUSE2:
|
||||
vgui.Mouse( down ? MA_PRESSED : MA_RELEASED, MOUSE_RIGHT );
|
||||
return;
|
||||
case K_MOUSE3:
|
||||
vgui.Mouse( down ? MA_PRESSED : MA_RELEASED, MOUSE_MIDDLE );
|
||||
return;
|
||||
case K_MWHEELDOWN:
|
||||
vgui.Mouse( MA_WHEEL, 1 );
|
||||
return;
|
||||
case K_MWHEELUP:
|
||||
vgui.Mouse( MA_WHEEL, -1 );
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
case K_MOUSE1: code = MOUSE_LEFT; break;
|
||||
case K_MOUSE2: code = MOUSE_RIGHT; break;
|
||||
case K_MOUSE3: code = MOUSE_MIDDLE; break;
|
||||
default: return;
|
||||
}
|
||||
|
||||
if( down == 2 )
|
||||
vgui.Key( KA_TYPED, VGUI_MapKey( key ) );
|
||||
if( clicks >= 2 )
|
||||
mact = MA_DOUBLE;
|
||||
else if( clicks == 1 )
|
||||
mact = MA_PRESSED;
|
||||
else
|
||||
vgui.Key( down?KA_PRESSED:KA_RELEASED, VGUI_MapKey( key ) );
|
||||
//Msg("VGui_KeyEvent %d %d %d\n", key, VGUI_MapKey( key ), down );
|
||||
mact = MA_RELEASED;
|
||||
|
||||
vgui.dllFuncs.Mouse( mact, code );
|
||||
}
|
||||
|
||||
void VGui_MWheelEvent( int y )
|
||||
{
|
||||
if( !vgui.dllFuncs.Mouse )
|
||||
return;
|
||||
|
||||
vgui.dllFuncs.Mouse( MA_WHEEL, y );
|
||||
}
|
||||
|
||||
void VGui_KeyEvent( int key, int down )
|
||||
{
|
||||
enum VGUI_KeyCode code;
|
||||
|
||||
if( !vgui.dllFuncs.Key )
|
||||
return;
|
||||
|
||||
if(( code = VGUI_MapKey( key )) < 0 )
|
||||
return;
|
||||
|
||||
if( down )
|
||||
{
|
||||
vgui.dllFuncs.Key( KA_PRESSED, code );
|
||||
vgui.dllFuncs.Key( KA_TYPED, code );
|
||||
}
|
||||
else vgui.dllFuncs.Key( KA_RELEASED, code );
|
||||
}
|
||||
|
||||
void VGui_MouseMove( int x, int y )
|
||||
{
|
||||
float xscale = (float)refState.width / (float)clgame.scrInfo.iWidth;
|
||||
float yscale = (float)refState.height / (float)clgame.scrInfo.iHeight;
|
||||
if( vgui.initialized )
|
||||
vgui.MouseMove( x / xscale, y / yscale );
|
||||
if( vgui.dllFuncs.MouseMove )
|
||||
{
|
||||
float xscale = (float)refState.width / (float)clgame.scrInfo.iWidth;
|
||||
float yscale = (float)refState.height / (float)clgame.scrInfo.iHeight;
|
||||
vgui.dllFuncs.MouseMove( x / xscale, y / yscale );
|
||||
}
|
||||
}
|
||||
|
||||
void VGui_Paint( void )
|
||||
{
|
||||
if( vgui.initialized )
|
||||
vgui.Paint();
|
||||
if( vgui.dllFuncs.Paint )
|
||||
vgui.dllFuncs.Paint();
|
||||
}
|
||||
|
||||
void VGui_RunFrame( void )
|
||||
void VGui_UpdateInternalCursorState( VGUI_DefaultCursor cursorType )
|
||||
{
|
||||
//stub
|
||||
vgui.cursor = cursorType;
|
||||
}
|
||||
|
||||
|
||||
void *GAME_EXPORT VGui_GetPanel( void )
|
||||
{
|
||||
if( vgui.initialized )
|
||||
return vgui.GetPanel();
|
||||
if( vgui.dllFuncs.GetPanel )
|
||||
return vgui.dllFuncs.GetPanel();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void VGui_ReportTextInput( const char *text )
|
||||
{
|
||||
if ( vgui.initialized )
|
||||
vgui.TextInput( text );
|
||||
if( vgui.dllFuncs.TextInput )
|
||||
vgui.dllFuncs.TextInput( text );
|
||||
}
|
||||
|
||||
|
|
|
@ -16,25 +16,22 @@ GNU General Public License for more details.
|
|||
#ifndef VGUI_DRAW_H
|
||||
#define VGUI_DRAW_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "port.h"
|
||||
|
||||
//
|
||||
// vgui_draw.c
|
||||
//
|
||||
void VGui_Startup( const char *clientlib, int width, int height );
|
||||
void VGui_RegisterCvars( void );
|
||||
qboolean VGui_LoadProgs( HINSTANCE hInstance );
|
||||
void VGui_Startup( int width, int height );
|
||||
void VGui_Shutdown( void );
|
||||
void VGui_Paint( void );
|
||||
void VGui_RunFrame( void );
|
||||
void VGui_MouseEvent( int key, int clicks );
|
||||
void VGui_MWheelEvent( int y );
|
||||
void VGui_KeyEvent( int key, int down );
|
||||
void VGui_MouseMove( int x, int y );
|
||||
qboolean VGui_IsActive( void );
|
||||
void *VGui_GetPanel( void );
|
||||
void VGui_ReportTextInput( const char *text );
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif//VGUI_DRAW_H
|
||||
void VGui_UpdateInternalCursorState( VGUI_DefaultCursor cursorType );
|
||||
|
||||
#endif // VGUI_DRAW_H
|
||||
|
|
|
@ -20,22 +20,22 @@ GNU General Public License for more details.
|
|||
#include "vid_common.h"
|
||||
#include "platform/platform.h"
|
||||
|
||||
#define WINDOW_NAME XASH_ENGINE_NAME " Window" // Half-Life
|
||||
convar_t *vid_displayfrequency;
|
||||
convar_t *vid_fullscreen;
|
||||
convar_t *vid_mode;
|
||||
convar_t *vid_brightness;
|
||||
convar_t *vid_gamma;
|
||||
convar_t *vid_highdpi;
|
||||
static CVAR_DEFINE( window_width, "width", "0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "screen width" );
|
||||
static CVAR_DEFINE( window_height, "height", "0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "screen height" );
|
||||
static CVAR_DEFINE( vid_brightness, "brightness", "0.0", FCVAR_ARCHIVE, "brightness factor" );
|
||||
static CVAR_DEFINE( vid_gamma, "gamma", "2.5", FCVAR_ARCHIVE, "gamma amount" );
|
||||
static CVAR_DEFINE_AUTO( vid_mode, "0", FCVAR_RENDERINFO, "current video mode index (used only for storage)" );
|
||||
static CVAR_DEFINE_AUTO( vid_rotate, "0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "screen rotation (0-3)" );
|
||||
static CVAR_DEFINE_AUTO( vid_scale, "1.0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "pixel scale" );
|
||||
|
||||
CVAR_DEFINE_AUTO( vid_highdpi, "1", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "enable High-DPI mode" );
|
||||
CVAR_DEFINE_AUTO( vid_maximized, "0", FCVAR_RENDERINFO, "window maximized state, read-only" );
|
||||
CVAR_DEFINE( vid_fullscreen, "fullscreen", "0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "fullscreen state (0 windowed, 1 fullscreen, 2 borderless)" );
|
||||
CVAR_DEFINE( window_xpos, "_window_xpos", "-1", FCVAR_RENDERINFO, "window position by horizontal" );
|
||||
CVAR_DEFINE( window_ypos, "_window_ypos", "-1", FCVAR_RENDERINFO, "window position by vertical" );
|
||||
|
||||
glwstate_t glw_state;
|
||||
|
||||
convar_t *window_xpos;
|
||||
convar_t *window_ypos;
|
||||
|
||||
convar_t *vid_rotate;
|
||||
convar_t *vid_scale;
|
||||
|
||||
/*
|
||||
=================
|
||||
VID_StartupGamma
|
||||
|
@ -43,10 +43,10 @@ VID_StartupGamma
|
|||
*/
|
||||
void VID_StartupGamma( void )
|
||||
{
|
||||
BuildGammaTable( vid_gamma->value, vid_brightness->value );
|
||||
Con_Reportf( "VID_StartupGamma: gamma %g brightness %g\n", vid_gamma->value, vid_brightness->value );
|
||||
ClearBits( vid_brightness->flags, FCVAR_CHANGED );
|
||||
ClearBits( vid_gamma->flags, FCVAR_CHANGED );
|
||||
BuildGammaTable( vid_gamma.value, vid_brightness.value );
|
||||
Con_Reportf( "VID_StartupGamma: gamma %g brightness %g\n", vid_gamma.value, vid_brightness.value );
|
||||
ClearBits( vid_brightness.flags, FCVAR_CHANGED );
|
||||
ClearBits( vid_gamma.flags, FCVAR_CHANGED );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -67,19 +67,31 @@ void VID_InitDefaultResolution( void )
|
|||
R_SaveVideoMode
|
||||
=================
|
||||
*/
|
||||
void R_SaveVideoMode( int w, int h , int render_w, int render_h )
|
||||
void R_SaveVideoMode( int w, int h, int render_w, int render_h, qboolean maximized )
|
||||
{
|
||||
if( !w || !h || !render_w || !render_h )
|
||||
{
|
||||
host.renderinfo_changed = false;
|
||||
return;
|
||||
}
|
||||
|
||||
host.window_center_x = w / 2;
|
||||
host.window_center_y = h / 2;
|
||||
|
||||
Cvar_SetValue( "width", w );
|
||||
Cvar_SetValue( "height", h );
|
||||
Cvar_DirectSet( &vid_maximized, maximized ? "1" : "0" );
|
||||
|
||||
// immediately drop changed state or we may trigger
|
||||
// video subsystem to reapply settings
|
||||
host.renderinfo_changed = false;
|
||||
|
||||
if( refState.width == render_w && refState.height == render_h )
|
||||
return;
|
||||
|
||||
refState.width = render_w;
|
||||
refState.height = render_h;
|
||||
|
||||
host.renderinfo_changed = false;
|
||||
|
||||
// check for 4:3 or 5:4
|
||||
if( render_w * 3 != render_h * 4 && render_w * 4 != render_h * 5 )
|
||||
refState.wideScreen = true;
|
||||
|
@ -114,11 +126,11 @@ check vid modes and fullscreen
|
|||
*/
|
||||
void VID_CheckChanges( void )
|
||||
{
|
||||
if( FBitSet( cl_allow_levelshots->flags, FCVAR_CHANGED ))
|
||||
if( FBitSet( cl_allow_levelshots.flags, FCVAR_CHANGED ))
|
||||
{
|
||||
//GL_FreeTexture( cls.loadingBar );
|
||||
SCR_RegisterTextures(); // reload 'lambda' image
|
||||
ClearBits( cl_allow_levelshots->flags, FCVAR_CHANGED );
|
||||
ClearBits( cl_allow_levelshots.flags, FCVAR_CHANGED );
|
||||
}
|
||||
|
||||
if( host.renderinfo_changed )
|
||||
|
@ -135,6 +147,36 @@ void VID_CheckChanges( void )
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
VID_SetDisplayTransform
|
||||
|
||||
notify ref dll about screen transformations
|
||||
===============
|
||||
*/
|
||||
void VID_SetDisplayTransform( int *render_w, int *render_h )
|
||||
{
|
||||
uint rotate = vid_rotate.value;
|
||||
|
||||
if( ref.dllFuncs.R_SetDisplayTransform( rotate, 0, 0, vid_scale.value, vid_scale.value ))
|
||||
{
|
||||
if( rotate & 1 )
|
||||
{
|
||||
int swap = *render_w;
|
||||
|
||||
*render_w = *render_h;
|
||||
*render_h = swap;
|
||||
}
|
||||
|
||||
*render_h /= vid_scale.value;
|
||||
*render_w /= vid_scale.value;
|
||||
}
|
||||
else
|
||||
{
|
||||
Con_Printf( S_WARN "failed to setup screen transform\n" );
|
||||
}
|
||||
}
|
||||
|
||||
static void VID_Mode_f( void )
|
||||
{
|
||||
int w, h;
|
||||
|
@ -167,26 +209,25 @@ static void VID_Mode_f( void )
|
|||
return;
|
||||
}
|
||||
|
||||
R_ChangeDisplaySettings( w, h, Cvar_VariableInteger( "fullscreen" ) );
|
||||
R_ChangeDisplaySettings( w, h, bound( 0, vid_fullscreen.value, WINDOW_MODE_COUNT - 1 ));
|
||||
}
|
||||
|
||||
void VID_Init( void )
|
||||
{
|
||||
// system screen width and height (don't suppose for change from console at all)
|
||||
Cvar_Get( "width", "0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "screen width" );
|
||||
Cvar_Get( "height", "0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "screen height" );
|
||||
Cvar_RegisterVariable( &window_width );
|
||||
Cvar_RegisterVariable( &window_height );
|
||||
|
||||
window_xpos = Cvar_Get( "_window_xpos", "130", FCVAR_RENDERINFO, "window position by horizontal" );
|
||||
window_ypos = Cvar_Get( "_window_ypos", "48", FCVAR_RENDERINFO, "window position by vertical" );
|
||||
|
||||
vid_gamma = Cvar_Get( "gamma", "2.5", FCVAR_ARCHIVE, "gamma amount" );
|
||||
vid_brightness = Cvar_Get( "brightness", "0.0", FCVAR_ARCHIVE, "brightness factor" );
|
||||
vid_displayfrequency = Cvar_Get ( "vid_displayfrequency", "0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "fullscreen refresh rate" );
|
||||
vid_fullscreen = Cvar_Get( "fullscreen", "0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "enable fullscreen mode" );
|
||||
vid_mode = Cvar_Get( "vid_mode", "0", FCVAR_RENDERINFO, "current video mode index (used just for storage)" );
|
||||
vid_highdpi = Cvar_Get( "vid_highdpi", "1", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "enable High-DPI mode" );
|
||||
vid_rotate = Cvar_Get( "vid_rotate", "0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "screen rotation (0-3)" );
|
||||
vid_scale = Cvar_Get( "vid_scale", "1.0", FCVAR_RENDERINFO|FCVAR_VIDRESTART, "pixel scale" );
|
||||
Cvar_RegisterVariable( &vid_mode );
|
||||
Cvar_RegisterVariable( &vid_highdpi );
|
||||
Cvar_RegisterVariable( &vid_rotate );
|
||||
Cvar_RegisterVariable( &vid_scale );
|
||||
Cvar_RegisterVariable( &vid_fullscreen );
|
||||
Cvar_RegisterVariable( &vid_maximized );
|
||||
Cvar_RegisterVariable( &vid_brightness );
|
||||
Cvar_RegisterVariable( &vid_gamma );
|
||||
Cvar_RegisterVariable( &window_xpos );
|
||||
Cvar_RegisterVariable( &window_ypos );
|
||||
|
||||
// a1ba: planned to be named vid_mode for compability
|
||||
// but supported mode list is filled by backends, so numbers are not portable any more
|
||||
|
|
|
@ -9,6 +9,13 @@ typedef struct vidmode_s
|
|||
int height;
|
||||
} vidmode_t;
|
||||
|
||||
typedef enum window_mode_e
|
||||
{
|
||||
WINDOW_MODE_WINDOWED = 0,
|
||||
WINDOW_MODE_FULLSCREEN,
|
||||
WINDOW_MODE_BORDERLESS,
|
||||
WINDOW_MODE_COUNT,
|
||||
} window_mode_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
@ -28,14 +35,15 @@ extern glwstate_t glw_state;
|
|||
#define VID_MIN_HEIGHT 200
|
||||
#define VID_MIN_WIDTH 320
|
||||
|
||||
extern convar_t *vid_fullscreen;
|
||||
extern convar_t *vid_displayfrequency;
|
||||
extern convar_t *vid_highdpi;
|
||||
extern convar_t *vid_rotate;
|
||||
extern convar_t *vid_scale;
|
||||
extern convar_t vid_fullscreen;
|
||||
extern convar_t vid_maximized;
|
||||
extern convar_t vid_highdpi;
|
||||
extern convar_t window_xpos;
|
||||
extern convar_t window_ypos;
|
||||
extern convar_t gl_msaa_samples;
|
||||
|
||||
extern convar_t *gl_msaa_samples;
|
||||
void R_SaveVideoMode( int w, int h, int render_w, int render_h );
|
||||
void R_SaveVideoMode( int w, int h, int render_w, int render_h, qboolean maximized );
|
||||
void VID_SetDisplayTransform( int *render_w, int *render_h );
|
||||
void VID_CheckChanges( void );
|
||||
const char *VID_GetModeString( int vid_mode );
|
||||
void VID_StartupGamma( void );
|
||||
|
|
|
@ -0,0 +1,635 @@
|
|||
/*
|
||||
voice.c - voice chat implementation
|
||||
Copyright (C) 2022 Velaron
|
||||
Copyright (C) 2022 SNMetamorph
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#define CUSTOM_MODES 1 // required to correctly link with Opus Custom
|
||||
#include <opus_custom.h>
|
||||
#include "common.h"
|
||||
#include "client.h"
|
||||
#include "voice.h"
|
||||
|
||||
voice_state_t voice = { 0 };
|
||||
|
||||
CVAR_DEFINE_AUTO( voice_enable, "1", FCVAR_PRIVILEGED|FCVAR_ARCHIVE, "enable voice chat" );
|
||||
CVAR_DEFINE_AUTO( voice_loopback, "0", FCVAR_PRIVILEGED, "loopback voice back to the speaker" );
|
||||
CVAR_DEFINE_AUTO( voice_scale, "1.0", FCVAR_PRIVILEGED|FCVAR_ARCHIVE, "incoming voice volume scale" );
|
||||
CVAR_DEFINE_AUTO( voice_avggain, "0.5", FCVAR_PRIVILEGED|FCVAR_ARCHIVE, "automatic voice gain control (average)" );
|
||||
CVAR_DEFINE_AUTO( voice_maxgain, "5.0", FCVAR_PRIVILEGED|FCVAR_ARCHIVE, "automatic voice gain control (maximum)" );
|
||||
CVAR_DEFINE_AUTO( voice_inputfromfile, "0", FCVAR_PRIVILEGED, "input voice from voice_input.wav" );
|
||||
|
||||
static void Voice_ApplyGainAdjust( int16_t *samples, int count );
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
OPUS INTEGRATION
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
=========================
|
||||
Voice_InitOpusDecoder
|
||||
|
||||
=========================
|
||||
*/
|
||||
static qboolean Voice_InitOpusDecoder( void )
|
||||
{
|
||||
int err;
|
||||
|
||||
voice.width = sizeof( opus_int16 );
|
||||
voice.samplerate = VOICE_OPUS_CUSTOM_SAMPLERATE;
|
||||
voice.frame_size = VOICE_OPUS_CUSTOM_FRAME_SIZE;
|
||||
|
||||
voice.custom_mode = opus_custom_mode_create( SOUND_44k, voice.frame_size, &err );
|
||||
if( !voice.custom_mode )
|
||||
{
|
||||
Con_Printf( S_ERROR "Can't create Opus Custom mode: %s\n", opus_strerror( err ));
|
||||
return false;
|
||||
}
|
||||
|
||||
voice.decoder = opus_custom_decoder_create( voice.custom_mode, VOICE_PCM_CHANNELS, &err );
|
||||
if( !voice.decoder )
|
||||
{
|
||||
Con_Printf( S_ERROR "Can't create Opus encoder: %s\n", opus_strerror( err ));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
=========================
|
||||
Voice_InitOpusEncoder
|
||||
|
||||
=========================
|
||||
*/
|
||||
static qboolean Voice_InitOpusEncoder( int quality )
|
||||
{
|
||||
int err;
|
||||
|
||||
voice.encoder = opus_custom_encoder_create( voice.custom_mode, VOICE_PCM_CHANNELS, &err );
|
||||
if( !voice.encoder )
|
||||
{
|
||||
Con_Printf( S_ERROR "Can't create Opus encoder: %s\n", opus_strerror( err ));
|
||||
return false;
|
||||
}
|
||||
|
||||
switch( quality )
|
||||
{
|
||||
case 1: // 6 kbps
|
||||
opus_custom_encoder_ctl( voice.encoder, OPUS_SET_BITRATE( 6000 ));
|
||||
break;
|
||||
case 2: // 12 kbps
|
||||
opus_custom_encoder_ctl( voice.encoder, OPUS_SET_BITRATE( 12000 ));
|
||||
break;
|
||||
case 4: // 64 kbps
|
||||
opus_custom_encoder_ctl( voice.encoder, OPUS_SET_BITRATE( 64000 ));
|
||||
break;
|
||||
case 5: // 96 kbps
|
||||
opus_custom_encoder_ctl( voice.encoder, OPUS_SET_BITRATE( 96000 ));
|
||||
break;
|
||||
default: // 36 kbps
|
||||
opus_custom_encoder_ctl( voice.encoder, OPUS_SET_BITRATE( 36000 ));
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
=========================
|
||||
Voice_ShutdownOpusDecoder
|
||||
|
||||
=========================
|
||||
*/
|
||||
static void Voice_ShutdownOpusDecoder( void )
|
||||
{
|
||||
if( voice.decoder )
|
||||
{
|
||||
opus_custom_decoder_destroy( voice.decoder );
|
||||
voice.decoder = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=========================
|
||||
Voice_ShutdownOpusEncoder
|
||||
|
||||
=========================
|
||||
*/
|
||||
static void Voice_ShutdownOpusEncoder( void )
|
||||
{
|
||||
if( voice.encoder )
|
||||
{
|
||||
opus_custom_encoder_destroy( voice.encoder );
|
||||
voice.encoder = NULL;
|
||||
}
|
||||
|
||||
if( voice.custom_mode )
|
||||
{
|
||||
opus_custom_mode_destroy( voice.custom_mode );
|
||||
voice.custom_mode = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=========================
|
||||
Voice_GetOpusCompressedData
|
||||
|
||||
=========================
|
||||
*/
|
||||
static uint Voice_GetOpusCompressedData( byte *out, uint maxsize, uint *frames )
|
||||
{
|
||||
uint ofs = 0, size = 0;
|
||||
uint frame_size_bytes = voice.frame_size * voice.width;
|
||||
|
||||
if( voice.input_file )
|
||||
{
|
||||
uint numbytes;
|
||||
double updateInterval, curtime = Sys_DoubleTime();
|
||||
|
||||
updateInterval = curtime - voice.start_time;
|
||||
voice.start_time = curtime;
|
||||
|
||||
numbytes = updateInterval * voice.samplerate * voice.width * VOICE_PCM_CHANNELS;
|
||||
numbytes = Q_min( numbytes, voice.input_file->size - voice.input_file_pos );
|
||||
numbytes = Q_min( numbytes, sizeof( voice.input_buffer ) - voice.input_buffer_pos );
|
||||
|
||||
memcpy( voice.input_buffer + voice.input_buffer_pos, voice.input_file->buffer + voice.input_file_pos, numbytes );
|
||||
voice.input_buffer_pos += numbytes;
|
||||
voice.input_file_pos += numbytes;
|
||||
}
|
||||
|
||||
if( !voice.input_file )
|
||||
VoiceCapture_Lock( true );
|
||||
|
||||
for( ofs = 0; voice.input_buffer_pos - ofs >= frame_size_bytes && ofs <= voice.input_buffer_pos; ofs += frame_size_bytes )
|
||||
{
|
||||
int bytes;
|
||||
|
||||
#if 1
|
||||
if( !voice.input_file )
|
||||
{
|
||||
// adjust gain before encoding, but only for input from voice
|
||||
Voice_ApplyGainAdjust((opus_int16*)(voice.input_buffer + ofs), voice.frame_size);
|
||||
}
|
||||
#endif
|
||||
|
||||
bytes = opus_custom_encode( voice.encoder, (const opus_int16 *)( voice.input_buffer + ofs ),
|
||||
voice.frame_size, out + size + sizeof( uint16_t ), maxsize );
|
||||
|
||||
if( bytes > 0 )
|
||||
{
|
||||
// write compressed frame size
|
||||
*((uint16_t *)&out[size]) = bytes;
|
||||
|
||||
size += bytes + sizeof( uint16_t );
|
||||
maxsize -= bytes + sizeof( uint16_t );
|
||||
|
||||
(*frames)++;
|
||||
}
|
||||
else
|
||||
{
|
||||
Con_Printf( S_ERROR "%s: failed to encode frame: %s\n", __func__, opus_strerror( bytes ));
|
||||
}
|
||||
}
|
||||
|
||||
// did we compress anything? update counters
|
||||
if( ofs )
|
||||
{
|
||||
fs_offset_t remaining = voice.input_buffer_pos - ofs;
|
||||
|
||||
// move remaining samples to the beginning of buffer
|
||||
memmove( voice.input_buffer, voice.input_buffer + ofs, remaining );
|
||||
|
||||
voice.input_buffer_pos = remaining;
|
||||
}
|
||||
|
||||
if( !voice.input_file )
|
||||
VoiceCapture_Lock( false );
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
VOICE CHAT INTEGRATION
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
=========================
|
||||
Voice_ApplyGainAdjust
|
||||
|
||||
=========================
|
||||
*/
|
||||
static void Voice_ApplyGainAdjust( int16_t *samples, int count )
|
||||
{
|
||||
float gain, modifiedMax;
|
||||
int average, adjustedSample, blockOffset = 0;
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
int i, localMax = 0, localSum = 0;
|
||||
int blockSize = Q_min( count - ( blockOffset + voice.autogain.block_size ), voice.autogain.block_size );
|
||||
|
||||
if( blockSize < 1 )
|
||||
break;
|
||||
|
||||
for( i = 0; i < blockSize; ++i )
|
||||
{
|
||||
int sample = samples[blockOffset + i];
|
||||
int absSample = abs( sample );
|
||||
|
||||
if( absSample > localMax )
|
||||
localMax = absSample;
|
||||
|
||||
localSum += absSample;
|
||||
|
||||
gain = voice.autogain.current_gain + i * voice.autogain.gain_multiplier;
|
||||
adjustedSample = Q_min( SHRT_MAX, Q_max(( int )( sample * gain ), SHRT_MIN ));
|
||||
samples[blockOffset + i] = adjustedSample;
|
||||
}
|
||||
|
||||
if( blockOffset % voice.autogain.block_size == 0 )
|
||||
{
|
||||
average = localSum / blockSize;
|
||||
modifiedMax = average + ( localMax - average ) * voice_avggain.value;
|
||||
|
||||
voice.autogain.current_gain = voice.autogain.next_gain * voice_scale.value;
|
||||
voice.autogain.next_gain = Q_min( (float)SHRT_MAX / modifiedMax, voice_maxgain.value ) * voice_scale.value;
|
||||
voice.autogain.gain_multiplier = ( voice.autogain.next_gain - voice.autogain.current_gain ) / ( voice.autogain.block_size - 1 );
|
||||
}
|
||||
blockOffset += blockSize;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=========================
|
||||
Voice_Status
|
||||
|
||||
Notify user dll aboit voice transmission
|
||||
=========================
|
||||
*/
|
||||
static void Voice_Status( int entindex, qboolean bTalking )
|
||||
{
|
||||
if( cls.state == ca_active && clgame.dllFuncs.pfnVoiceStatus )
|
||||
clgame.dllFuncs.pfnVoiceStatus( entindex, bTalking );
|
||||
}
|
||||
|
||||
/*
|
||||
=========================
|
||||
Voice_StatusTimeout
|
||||
|
||||
Waits few milliseconds and if there was no
|
||||
voice transmission, sends notification
|
||||
=========================
|
||||
*/
|
||||
static void Voice_StatusTimeout( voice_status_t *status, int entindex, double frametime )
|
||||
{
|
||||
if( status->talking_ack )
|
||||
{
|
||||
status->talking_timeout += frametime;
|
||||
if( status->talking_timeout > 0.2 )
|
||||
{
|
||||
status->talking_ack = false;
|
||||
Voice_Status( entindex, false );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=========================
|
||||
Voice_StatusAck
|
||||
|
||||
Sends notification to user dll and
|
||||
zeroes timeouts for this client
|
||||
=========================
|
||||
*/
|
||||
void Voice_StatusAck( voice_status_t *status, int playerIndex )
|
||||
{
|
||||
if( !status->talking_ack )
|
||||
Voice_Status( playerIndex, true );
|
||||
|
||||
status->talking_ack = true;
|
||||
status->talking_timeout = 0.0;
|
||||
}
|
||||
|
||||
/*
|
||||
=========================
|
||||
Voice_IsRecording
|
||||
|
||||
=========================
|
||||
*/
|
||||
qboolean Voice_IsRecording( void )
|
||||
{
|
||||
return voice.is_recording;
|
||||
}
|
||||
|
||||
/*
|
||||
=========================
|
||||
Voice_RecordStop
|
||||
|
||||
=========================
|
||||
*/
|
||||
void Voice_RecordStop( void )
|
||||
{
|
||||
if( voice.input_file )
|
||||
{
|
||||
FS_FreeSound( voice.input_file );
|
||||
voice.input_file = NULL;
|
||||
}
|
||||
|
||||
VoiceCapture_Activate( false );
|
||||
voice.is_recording = false;
|
||||
|
||||
Voice_Status( VOICE_LOCALCLIENT_INDEX, false );
|
||||
|
||||
voice.input_buffer_pos = 0;
|
||||
memset( voice.input_buffer, 0, sizeof( voice.input_buffer ));
|
||||
}
|
||||
|
||||
/*
|
||||
=========================
|
||||
Voice_RecordStart
|
||||
|
||||
=========================
|
||||
*/
|
||||
void Voice_RecordStart( void )
|
||||
{
|
||||
Voice_RecordStop();
|
||||
|
||||
if( voice_inputfromfile.value )
|
||||
{
|
||||
voice.input_file = FS_LoadSound( "voice_input.wav", NULL, 0 );
|
||||
|
||||
if( voice.input_file )
|
||||
{
|
||||
Sound_Process( &voice.input_file, voice.samplerate, voice.width, SOUND_RESAMPLE );
|
||||
voice.input_file_pos = 0;
|
||||
|
||||
voice.start_time = Sys_DoubleTime();
|
||||
voice.is_recording = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
FS_FreeSound( voice.input_file );
|
||||
voice.input_file = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if( !Voice_IsRecording() )
|
||||
voice.is_recording = VoiceCapture_Activate( true );
|
||||
|
||||
if( Voice_IsRecording() )
|
||||
Voice_Status( VOICE_LOCALCLIENT_INDEX, true );
|
||||
}
|
||||
|
||||
/*
|
||||
=========================
|
||||
Voice_Disconnect
|
||||
|
||||
We're disconnected from server
|
||||
stop recording and notify user dlls
|
||||
=========================
|
||||
*/
|
||||
void Voice_Disconnect( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
Voice_RecordStop();
|
||||
|
||||
if( voice.local.talking_ack )
|
||||
{
|
||||
Voice_Status( VOICE_LOOPBACK_INDEX, false );
|
||||
voice.local.talking_ack = false;
|
||||
}
|
||||
|
||||
for( i = 0; i < MAX_CLIENTS; i++ )
|
||||
{
|
||||
if( voice.players_status[i].talking_ack )
|
||||
{
|
||||
Voice_Status( i, false );
|
||||
voice.players_status[i].talking_ack = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=========================
|
||||
Voice_StartChannel
|
||||
|
||||
Feed the decoded data to engine sound subsystem
|
||||
=========================
|
||||
*/
|
||||
static void Voice_StartChannel( uint samples, byte *data, int entnum )
|
||||
{
|
||||
SND_ForceInitMouth( entnum );
|
||||
S_RawEntSamples( entnum, samples, voice.samplerate, voice.width, VOICE_PCM_CHANNELS, data, 255 );
|
||||
}
|
||||
|
||||
/*
|
||||
=========================
|
||||
Voice_AddIncomingData
|
||||
|
||||
Received encoded voice data, decode it
|
||||
=========================
|
||||
*/
|
||||
void Voice_AddIncomingData( int ent, const byte *data, uint size, uint frames )
|
||||
{
|
||||
int samples = 0;
|
||||
int ofs = 0;
|
||||
|
||||
if( !voice.decoder )
|
||||
return;
|
||||
|
||||
// decode frame by frame
|
||||
for( ;; )
|
||||
{
|
||||
int frame_samples;
|
||||
uint16_t compressed_size;
|
||||
|
||||
// no compressed size mark
|
||||
if( ofs + sizeof( uint16_t ) > size )
|
||||
break;
|
||||
|
||||
compressed_size = *(const uint16_t *)(data + ofs);
|
||||
ofs += sizeof( uint16_t );
|
||||
|
||||
// no frame data
|
||||
if( ofs + compressed_size > size )
|
||||
break;
|
||||
|
||||
frame_samples = opus_custom_decode( voice.decoder, data + ofs, compressed_size,
|
||||
(opus_int16*)voice.decompress_buffer + samples, voice.frame_size );
|
||||
|
||||
ofs += compressed_size;
|
||||
samples += frame_samples;
|
||||
}
|
||||
|
||||
if( samples > 0 )
|
||||
Voice_StartChannel( samples, voice.decompress_buffer, ent );
|
||||
}
|
||||
|
||||
/*
|
||||
=========================
|
||||
CL_AddVoiceToDatagram
|
||||
|
||||
Encode our voice data and send it to server
|
||||
=========================
|
||||
*/
|
||||
void CL_AddVoiceToDatagram( void )
|
||||
{
|
||||
uint size, frames = 0;
|
||||
|
||||
if( cls.state != ca_active || !Voice_IsRecording() || !voice.encoder )
|
||||
return;
|
||||
|
||||
size = Voice_GetOpusCompressedData( voice.output_buffer, sizeof( voice.output_buffer ), &frames );
|
||||
|
||||
if( size > 0 && MSG_GetNumBytesLeft( &cls.datagram ) >= size + 32 )
|
||||
{
|
||||
MSG_BeginClientCmd( &cls.datagram, clc_voicedata );
|
||||
MSG_WriteByte( &cls.datagram, voice_loopback.value != 0 );
|
||||
MSG_WriteByte( &cls.datagram, frames );
|
||||
MSG_WriteShort( &cls.datagram, size );
|
||||
MSG_WriteBytes( &cls.datagram, voice.output_buffer, size );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=========================
|
||||
Voice_RegisterCvars
|
||||
|
||||
Register voice related cvars and commands
|
||||
=========================
|
||||
*/
|
||||
void Voice_RegisterCvars( void )
|
||||
{
|
||||
Cvar_RegisterVariable( &voice_enable );
|
||||
Cvar_RegisterVariable( &voice_loopback );
|
||||
Cvar_RegisterVariable( &voice_scale );
|
||||
Cvar_RegisterVariable( &voice_avggain );
|
||||
Cvar_RegisterVariable( &voice_maxgain );
|
||||
Cvar_RegisterVariable( &voice_inputfromfile );
|
||||
}
|
||||
|
||||
/*
|
||||
=========================
|
||||
Voice_Shutdown
|
||||
|
||||
Completely shutdown the voice subsystem
|
||||
=========================
|
||||
*/
|
||||
static void Voice_Shutdown( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
Voice_RecordStop();
|
||||
Voice_ShutdownOpusEncoder();
|
||||
Voice_ShutdownOpusDecoder();
|
||||
VoiceCapture_Shutdown();
|
||||
|
||||
if( voice.local.talking_ack )
|
||||
Voice_Status( VOICE_LOOPBACK_INDEX, false );
|
||||
|
||||
for( i = 0; i < MAX_CLIENTS; i++ )
|
||||
{
|
||||
if( voice.players_status[i].talking_ack )
|
||||
Voice_Status( i, false );
|
||||
}
|
||||
|
||||
memset( &voice, 0, sizeof( voice ));
|
||||
}
|
||||
|
||||
/*
|
||||
=========================
|
||||
Voice_Idle
|
||||
|
||||
Run timeout for all clients
|
||||
=========================
|
||||
*/
|
||||
void Voice_Idle( double frametime )
|
||||
{
|
||||
int i;
|
||||
|
||||
if( FBitSet( voice_enable.flags, FCVAR_CHANGED ) && !voice_enable.value )
|
||||
{
|
||||
Voice_Shutdown();
|
||||
return;
|
||||
}
|
||||
|
||||
// update local player status first
|
||||
Voice_StatusTimeout( &voice.local, VOICE_LOOPBACK_INDEX, frametime );
|
||||
|
||||
for( i = 0; i < MAX_CLIENTS; i++ )
|
||||
Voice_StatusTimeout( &voice.players_status[i], i, frametime );
|
||||
}
|
||||
|
||||
/*
|
||||
=========================
|
||||
Voice_Init
|
||||
|
||||
Initialize the voice subsystem
|
||||
=========================
|
||||
*/
|
||||
qboolean Voice_Init( const char *pszCodecName, int quality )
|
||||
{
|
||||
if( !voice_enable.value )
|
||||
return false;
|
||||
|
||||
if( Q_strcmp( pszCodecName, VOICE_OPUS_CUSTOM_CODEC ))
|
||||
{
|
||||
Con_Printf( S_ERROR "Server requested unsupported codec: %s\n", pszCodecName );
|
||||
return false;
|
||||
}
|
||||
|
||||
// reinitialize only if codec parameters are different
|
||||
if( !Q_strcmp( voice.codec, pszCodecName ) && voice.quality == quality )
|
||||
return true;
|
||||
|
||||
Voice_Shutdown();
|
||||
|
||||
voice.autogain.block_size = 128;
|
||||
|
||||
if( !Voice_InitOpusDecoder( ))
|
||||
{
|
||||
// no reason to init encoder and open audio device
|
||||
// if we can't hear other players
|
||||
Con_Printf( S_ERROR "Voice chat disabled.\n" );
|
||||
Voice_Shutdown();
|
||||
return false;
|
||||
}
|
||||
|
||||
// we can hear others players, so it's fine to fail now
|
||||
voice.initialized = true;
|
||||
Q_strncpy( voice.codec, pszCodecName, sizeof( voice.codec ));
|
||||
|
||||
if( !Voice_InitOpusEncoder( quality ))
|
||||
{
|
||||
Con_Printf( S_WARN "Other players will not be able to hear you.\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
voice.quality = quality;
|
||||
|
||||
if( !VoiceCapture_Init( ))
|
||||
Con_Printf( S_WARN "No microphone is available.\n" );
|
||||
|
||||
return true;
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
voice.h - voice chat implementation
|
||||
Copyright (C) 2022 Velaron
|
||||
Copyright (C) 2022 SNMetamorph
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef VOICE_H
|
||||
#define VOICE_H
|
||||
|
||||
#include "common.h"
|
||||
#include "protocol.h" // MAX_CLIENTS
|
||||
#include "sound.h"
|
||||
|
||||
typedef struct OpusCustomEncoder OpusCustomEncoder;
|
||||
typedef struct OpusCustomDecoder OpusCustomDecoder;
|
||||
typedef struct OpusCustomMode OpusCustomMode;
|
||||
|
||||
#define VOICE_LOOPBACK_INDEX (-2)
|
||||
#define VOICE_LOCALCLIENT_INDEX (-1)
|
||||
|
||||
#define VOICE_PCM_CHANNELS 1 // always mono
|
||||
|
||||
// never change these parameters when using opuscustom
|
||||
#define VOICE_OPUS_CUSTOM_SAMPLERATE SOUND_44k
|
||||
// must follow opus custom requirements
|
||||
// also be divisible with MAX_RAW_SAMPLES
|
||||
#define VOICE_OPUS_CUSTOM_FRAME_SIZE 1024
|
||||
#define VOICE_OPUS_CUSTOM_CODEC "opus_custom_44k_512"
|
||||
|
||||
// a1ba: do not change, we don't have any re-encoding support now
|
||||
#define VOICE_DEFAULT_CODEC VOICE_OPUS_CUSTOM_CODEC
|
||||
|
||||
typedef struct voice_status_s
|
||||
{
|
||||
qboolean talking_ack;
|
||||
double talking_timeout;
|
||||
} voice_status_t;
|
||||
|
||||
typedef struct voice_state_s
|
||||
{
|
||||
string codec;
|
||||
int quality;
|
||||
|
||||
qboolean initialized;
|
||||
qboolean is_recording;
|
||||
double start_time;
|
||||
|
||||
voice_status_t local;
|
||||
voice_status_t players_status[MAX_CLIENTS];
|
||||
|
||||
// opus stuff
|
||||
OpusCustomMode *custom_mode;
|
||||
OpusCustomEncoder *encoder;
|
||||
OpusCustomDecoder *decoder;
|
||||
|
||||
// audio info
|
||||
uint width;
|
||||
uint samplerate;
|
||||
uint frame_size; // in samples
|
||||
|
||||
// buffers
|
||||
byte input_buffer[MAX_RAW_SAMPLES];
|
||||
byte output_buffer[MAX_RAW_SAMPLES];
|
||||
byte decompress_buffer[MAX_RAW_SAMPLES];
|
||||
fs_offset_t input_buffer_pos; // in bytes
|
||||
|
||||
// input from file
|
||||
wavdata_t *input_file;
|
||||
fs_offset_t input_file_pos; // in bytes
|
||||
|
||||
// automatic gain control
|
||||
struct {
|
||||
int block_size;
|
||||
float current_gain;
|
||||
float next_gain;
|
||||
float gain_multiplier;
|
||||
} autogain;
|
||||
} voice_state_t;
|
||||
|
||||
extern voice_state_t voice;
|
||||
|
||||
void CL_AddVoiceToDatagram( void );
|
||||
|
||||
void Voice_RegisterCvars( void );
|
||||
qboolean Voice_Init( const char *pszCodecName, int quality );
|
||||
void Voice_Idle( double frametime );
|
||||
qboolean Voice_IsRecording( void );
|
||||
void Voice_RecordStop( void );
|
||||
void Voice_RecordStart( void );
|
||||
void Voice_Disconnect( void );
|
||||
void Voice_AddIncomingData( int ent, const byte *data, uint size, uint frames );
|
||||
void Voice_StatusAck( voice_status_t *status, int playerIndex );
|
||||
|
||||
#endif // VOICE_H
|
|
@ -17,10 +17,20 @@ GNU General Public License for more details.
|
|||
#include "base_cmd.h"
|
||||
#include "cdll_int.h"
|
||||
|
||||
// TODO: use another hash function, as COM_HashKey depends on string length
|
||||
#define HASH_SIZE 128 // 128 * 4 * 4 == 2048 bytes
|
||||
|
||||
typedef struct base_command_hashmap_s
|
||||
{
|
||||
base_command_t *basecmd; // base command: cvar, alias or command
|
||||
const char *name; // key for searching
|
||||
base_command_type_e type; // type for faster searching
|
||||
struct base_command_hashmap_s *next;
|
||||
} base_command_hashmap_t;
|
||||
|
||||
static base_command_hashmap_t *hashed_cmds[HASH_SIZE];
|
||||
|
||||
#define BaseCmd_HashKey( x ) COM_HashKey( name, HASH_SIZE )
|
||||
|
||||
/*
|
||||
============
|
||||
BaseCmd_FindInBucket
|
||||
|
@ -28,7 +38,7 @@ BaseCmd_FindInBucket
|
|||
Find base command in bucket
|
||||
============
|
||||
*/
|
||||
base_command_hashmap_t *BaseCmd_FindInBucket( base_command_hashmap_t *bucket, base_command_type_e type, const char *name )
|
||||
static base_command_hashmap_t *BaseCmd_FindInBucket( base_command_hashmap_t *bucket, base_command_type_e type, const char *name )
|
||||
{
|
||||
base_command_hashmap_t *i = bucket;
|
||||
for( ; i && ( i->type != type || Q_stricmp( name, i->name ) ); // filter out
|
||||
|
@ -44,9 +54,9 @@ BaseCmd_GetBucket
|
|||
Get bucket which contain basecmd by given name
|
||||
============
|
||||
*/
|
||||
base_command_hashmap_t *BaseCmd_GetBucket( const char *name )
|
||||
static base_command_hashmap_t *BaseCmd_GetBucket( const char *name )
|
||||
{
|
||||
return hashed_cmds[ COM_HashKey( name, HASH_SIZE ) ];
|
||||
return hashed_cmds[ BaseCmd_HashKey( name ) ];
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -73,7 +83,7 @@ BaseCmd_Find
|
|||
Find every type of base command and write into arguments
|
||||
============
|
||||
*/
|
||||
void BaseCmd_FindAll(const char *name, base_command_t **cmd, base_command_t **alias, base_command_t **cvar)
|
||||
void BaseCmd_FindAll( const char *name, base_command_t **cmd, base_command_t **alias, base_command_t **cvar )
|
||||
{
|
||||
base_command_hashmap_t *base = BaseCmd_GetBucket( name );
|
||||
base_command_hashmap_t *i = base;
|
||||
|
@ -101,7 +111,6 @@ void BaseCmd_FindAll(const char *name, base_command_t **cmd, base_command_t **al
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -113,41 +122,23 @@ Add new typed base command to hashmap
|
|||
*/
|
||||
void BaseCmd_Insert( base_command_type_e type, base_command_t *basecmd, const char *name )
|
||||
{
|
||||
uint hash = COM_HashKey( name, HASH_SIZE );
|
||||
base_command_hashmap_t *elem;
|
||||
base_command_hashmap_t *elem, *cur, *find;
|
||||
uint hash = BaseCmd_HashKey( name );
|
||||
|
||||
elem = Z_Malloc( sizeof( base_command_hashmap_t ) );
|
||||
elem->basecmd = basecmd;
|
||||
elem->type = type;
|
||||
elem->name = name;
|
||||
elem->next = hashed_cmds[hash];
|
||||
hashed_cmds[hash] = elem;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
BaseCmd_Replace
|
||||
// link the variable in alphanumerical order
|
||||
for( cur = NULL, find = hashed_cmds[hash];
|
||||
find && Q_strcmp( find->name, elem->name ) < 0;
|
||||
cur = find, find = find->next );
|
||||
|
||||
Used in case, when basecmd has been registered, but gamedll wants to register it's own
|
||||
============
|
||||
*/
|
||||
qboolean BaseCmd_Replace( base_command_type_e type, base_command_t *basecmd, const char *name )
|
||||
{
|
||||
base_command_hashmap_t *i = BaseCmd_GetBucket( name );
|
||||
if( cur ) cur->next = elem;
|
||||
else hashed_cmds[hash] = elem;
|
||||
|
||||
for( ; i && ( i->type != type || Q_stricmp( name, i->name ) ) ; // filter out
|
||||
i = i->next );
|
||||
|
||||
if( !i )
|
||||
{
|
||||
Con_Reportf( S_ERROR "BaseCmd_Replace: couldn't find %s\n", name);
|
||||
return false;
|
||||
}
|
||||
|
||||
i->basecmd = basecmd;
|
||||
i->name = name; // may be freed after
|
||||
|
||||
return true;
|
||||
elem->next = find;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -159,7 +150,7 @@ Remove base command from hashmap
|
|||
*/
|
||||
void BaseCmd_Remove( base_command_type_e type, const char *name )
|
||||
{
|
||||
uint hash = COM_HashKey( name, HASH_SIZE );
|
||||
uint hash = BaseCmd_HashKey( name );
|
||||
base_command_hashmap_t *i, *prev;
|
||||
|
||||
for( prev = NULL, i = hashed_cmds[hash]; i &&
|
||||
|
@ -221,23 +212,27 @@ void BaseCmd_Stats_f( void )
|
|||
|
||||
if( len > maxsize )
|
||||
maxsize = len;
|
||||
|
||||
}
|
||||
|
||||
Con_Printf( "Base command stats:\n");
|
||||
Con_Printf( "Bucket minimal length: %d\n", minsize );
|
||||
Con_Printf( "Bucket maximum length: %d\n", maxsize );
|
||||
Con_Printf( "Empty buckets: %d\n", empty );
|
||||
Con_Printf( "min length: %d, max length: %d, empty: %d\n", minsize, maxsize, empty );
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
qboolean valid;
|
||||
int lookups;
|
||||
} basecmd_test_stats_t;
|
||||
|
||||
static void BaseCmd_CheckCvars( const char *key, const char *value, const void *unused, void *ptr )
|
||||
{
|
||||
base_command_t *v = BaseCmd_Find( HM_CVAR, key );
|
||||
qboolean *invalid = ptr;
|
||||
basecmd_test_stats_t *stats = ptr;
|
||||
|
||||
if( !v )
|
||||
stats->lookups++;
|
||||
if( !BaseCmd_Find( HM_CVAR, key ))
|
||||
{
|
||||
Con_Printf( "Cvar %s is missing in basecmd\n", key );
|
||||
*invalid = true;
|
||||
stats->valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -250,38 +245,51 @@ testing order matches cbuf execute
|
|||
*/
|
||||
void BaseCmd_Test_f( void )
|
||||
{
|
||||
void *cmd;
|
||||
cmdalias_t *a;
|
||||
qboolean invalid = false;
|
||||
basecmd_test_stats_t stats;
|
||||
double start, end, dt;
|
||||
int i;
|
||||
|
||||
// Cmd_LookupCmds don't allows to check alias, so just iterate
|
||||
for( a = Cmd_AliasGetList(); a; a = a->next )
|
||||
stats.valid = true;
|
||||
stats.lookups = 0;
|
||||
|
||||
start = Sys_DoubleTime() * 1000;
|
||||
|
||||
for( i = 0; i < 1000; i++ )
|
||||
{
|
||||
base_command_t *v = BaseCmd_Find( HM_CMDALIAS, a->name );
|
||||
cmdalias_t *a;
|
||||
void *cmd;
|
||||
|
||||
if( !v )
|
||||
// Cmd_LookupCmds don't allows to check alias, so just iterate
|
||||
for( a = Cmd_AliasGetList(); a; a = a->next, stats.lookups++ )
|
||||
{
|
||||
Con_Printf( "Alias %s is missing in basecmd\n", a->name );
|
||||
invalid = true;
|
||||
if( !BaseCmd_Find( HM_CMDALIAS, a->name ))
|
||||
{
|
||||
Con_Printf( "Alias %s is missing in basecmd\n", a->name );
|
||||
stats.valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
for( cmd = Cmd_GetFirstFunctionHandle(); cmd;
|
||||
cmd = Cmd_GetNextFunctionHandle( cmd ), stats.lookups++ )
|
||||
{
|
||||
if( !BaseCmd_Find( HM_CMD, Cmd_GetName( cmd )))
|
||||
{
|
||||
Con_Printf( "Command %s is missing in basecmd\n", Cmd_GetName( cmd ));
|
||||
stats.valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
Cvar_LookupVars( 0, NULL, &stats.valid, (setpair_t)BaseCmd_CheckCvars );
|
||||
}
|
||||
|
||||
for( cmd = Cmd_GetFirstFunctionHandle(); cmd;
|
||||
cmd = Cmd_GetNextFunctionHandle( cmd ) )
|
||||
{
|
||||
base_command_t *v = BaseCmd_Find( HM_CMD, Cmd_GetName( cmd ) );
|
||||
end = Sys_DoubleTime() * 1000;
|
||||
|
||||
if( !v )
|
||||
{
|
||||
Con_Printf( "Command %s is missing in basecmd\n", Cmd_GetName( cmd ) );
|
||||
invalid = true;
|
||||
}
|
||||
}
|
||||
dt = end - start;
|
||||
|
||||
Cvar_LookupVars( 0, NULL, &invalid, (setpair_t)BaseCmd_CheckCvars );
|
||||
|
||||
if( !invalid )
|
||||
{
|
||||
if( !stats.valid )
|
||||
Con_Printf( "BaseCmd is valid\n" );
|
||||
}
|
||||
|
||||
Con_Printf( "Test took %.3f ms, %d lookups, %.3f us/lookup\n", dt, stats.lookups, dt / stats.lookups * 1000 );
|
||||
|
||||
BaseCmd_Stats_f();
|
||||
}
|
||||
|
|
|
@ -17,8 +17,6 @@ GNU General Public License for more details.
|
|||
#ifndef BASE_CMD_H
|
||||
#define BASE_CMD_H
|
||||
|
||||
// TODO: Find cases when command hashmap works incorrect
|
||||
// and maybe disable it
|
||||
#define XASH_HASHED_VARS
|
||||
|
||||
#ifdef XASH_HASHED_VARS
|
||||
|
@ -33,23 +31,13 @@ typedef enum base_command_type
|
|||
|
||||
typedef void base_command_t;
|
||||
|
||||
typedef struct base_command_hashmap_s
|
||||
{
|
||||
base_command_t *basecmd; // base command: cvar, alias or command
|
||||
const char *name; // key for searching
|
||||
base_command_type_e type; // type for faster searching
|
||||
struct base_command_hashmap_s *next;
|
||||
} base_command_hashmap_t;
|
||||
|
||||
|
||||
void BaseCmd_Init( void );
|
||||
base_command_hashmap_t *BaseCmd_GetBucket( const char *name );
|
||||
base_command_hashmap_t *BaseCmd_FindInBucket( base_command_hashmap_t *bucket, base_command_type_e type, const char *name );
|
||||
base_command_t *BaseCmd_Find( base_command_type_e type, const char *name );
|
||||
void BaseCmd_FindAll( const char *name,
|
||||
base_command_t **cmd, base_command_t **alias, base_command_t **cvar );
|
||||
void BaseCmd_Insert ( base_command_type_e type, base_command_t *basecmd, const char *name );
|
||||
qboolean BaseCmd_Replace( base_command_type_e type, base_command_t *basecmd, const char *name ); // only if same name
|
||||
void BaseCmd_Remove ( base_command_type_e type, const char *name );
|
||||
void BaseCmd_Stats_f( void ); // to be registered later
|
||||
void BaseCmd_Test_f( void ); // to be registered later
|
||||
|
|
|
@ -29,7 +29,7 @@ typedef struct
|
|||
int maxsize;
|
||||
} cmdbuf_t;
|
||||
|
||||
qboolean cmd_wait;
|
||||
int cmd_wait;
|
||||
cmdbuf_t cmd_text, filteredcmd_text;
|
||||
byte cmd_text_buf[MAX_CMD_BUFFER];
|
||||
byte filteredcmd_text_buf[MAX_CMD_BUFFER];
|
||||
|
@ -120,6 +120,18 @@ void Cbuf_AddText( const char *text )
|
|||
Cbuf_AddTextToBuffer( &cmd_text, text );
|
||||
}
|
||||
|
||||
void Cbuf_AddTextf( const char *fmt, ... )
|
||||
{
|
||||
va_list va;
|
||||
char buf[MAX_VA_STRING];
|
||||
|
||||
va_start( va, fmt );
|
||||
Q_vsnprintf( buf, sizeof( buf ), fmt, va );
|
||||
va_end( va );
|
||||
|
||||
Cbuf_AddText( buf );
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
Cbuf_AddFilteredText
|
||||
|
@ -173,6 +185,14 @@ void Cbuf_ExecuteCommandsFromBuffer( cmdbuf_t *buf, qboolean isPrivileged, int c
|
|||
|
||||
while( buf->cursize )
|
||||
{
|
||||
if( cmd_wait > 0 )
|
||||
{
|
||||
// skip out while text still remains in buffer,
|
||||
// leaving it for next frame
|
||||
cmd_wait--;
|
||||
break;
|
||||
}
|
||||
|
||||
// limit amount of commands that can be issued
|
||||
if( cmdsToExecute >= 0 )
|
||||
{
|
||||
|
@ -237,14 +257,6 @@ void Cbuf_ExecuteCommandsFromBuffer( cmdbuf_t *buf, qboolean isPrivileged, int c
|
|||
|
||||
// execute the command line
|
||||
Cmd_ExecuteStringWithPrivilegeCheck( line, isPrivileged );
|
||||
|
||||
if( cmd_wait )
|
||||
{
|
||||
// skip out while text still remains in buffer,
|
||||
// leaving it for next frame
|
||||
cmd_wait = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -360,7 +372,13 @@ bind g "cmd use rocket ; +attack ; wait ; -attack ; cmd use blaster"
|
|||
*/
|
||||
void Cmd_Wait_f( void )
|
||||
{
|
||||
cmd_wait = true;
|
||||
if ( Cmd_Argc() > 1 )
|
||||
{
|
||||
const char *arg = Cmd_Argv( 1 );
|
||||
cmd_wait = atoi( arg );
|
||||
}
|
||||
|
||||
cmd_wait = Q_max( cmd_wait, 1 );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -535,7 +553,7 @@ int GAME_EXPORT Cmd_Argc( void )
|
|||
Cmd_Argv
|
||||
============
|
||||
*/
|
||||
const char *Cmd_Argv( int arg )
|
||||
const char *GAME_EXPORT Cmd_Argv( int arg )
|
||||
{
|
||||
if((uint)arg >= cmd_argc )
|
||||
return "";
|
||||
|
@ -547,7 +565,7 @@ const char *Cmd_Argv( int arg )
|
|||
Cmd_Args
|
||||
============
|
||||
*/
|
||||
const char *Cmd_Args( void )
|
||||
const char *GAME_EXPORT Cmd_Args( void )
|
||||
{
|
||||
return cmd_args;
|
||||
}
|
||||
|
@ -984,7 +1002,7 @@ static void Cmd_ExecuteStringWithPrivilegeCheck( const char *text, qboolean isPr
|
|||
cmd_condlevel = 0;
|
||||
|
||||
// cvar value substitution
|
||||
if( CVAR_TO_BOOL( cmd_scripting ))
|
||||
if( cmd_scripting.value && isPrivileged )
|
||||
{
|
||||
while( *text )
|
||||
{
|
||||
|
@ -1150,13 +1168,13 @@ void Cmd_ForwardToServer( void )
|
|||
str[0] = 0;
|
||||
if( Q_stricmp( Cmd_Argv( 0 ), "cmd" ))
|
||||
{
|
||||
Q_strcat( str, Cmd_Argv( 0 ));
|
||||
Q_strcat( str, " " );
|
||||
Q_strncat( str, Cmd_Argv( 0 ), sizeof( str ));
|
||||
Q_strncat( str, " ", sizeof( str ));
|
||||
}
|
||||
|
||||
if( Cmd_Argc() > 1 )
|
||||
Q_strcat( str, Cmd_Args( ));
|
||||
else Q_strcat( str, "\n" );
|
||||
Q_strncat( str, Cmd_Args( ), sizeof( str ));
|
||||
else Q_strncat( str, "\n", sizeof( str ));
|
||||
|
||||
MSG_WriteString( &cls.netchan.message, str );
|
||||
}
|
||||
|
@ -1171,17 +1189,21 @@ void Cmd_List_f( void )
|
|||
{
|
||||
cmd_t *cmd;
|
||||
int i = 0;
|
||||
const char *match;
|
||||
size_t matchlen = 0;
|
||||
const char *match = NULL;
|
||||
|
||||
if( Cmd_Argc() > 1 ) match = Cmd_Argv( 1 );
|
||||
else match = NULL;
|
||||
if( Cmd_Argc() > 1 )
|
||||
{
|
||||
match = Cmd_Argv( 1 );
|
||||
matchlen = Q_strlen( match );
|
||||
}
|
||||
|
||||
for( cmd = cmd_functions; cmd; cmd = cmd->next )
|
||||
{
|
||||
if( cmd->name[0] == '@' )
|
||||
continue; // never show system cmds
|
||||
|
||||
if( match && !Q_stricmpext( match, cmd->name ))
|
||||
if( match && !Q_strnicmpext( match, cmd->name, matchlen ))
|
||||
continue;
|
||||
|
||||
Con_Printf( " %-*s ^3%s^7\n", 32, cmd->name, cmd->desc );
|
||||
|
@ -1250,21 +1272,21 @@ static void Cmd_Apropos_f( void )
|
|||
cmdalias_t *alias;
|
||||
const char *partial;
|
||||
int count = 0;
|
||||
qboolean ispattern;
|
||||
char buf[MAX_VA_STRING];
|
||||
|
||||
if( Cmd_Argc() > 1 )
|
||||
{
|
||||
partial = Cmd_Args();
|
||||
}
|
||||
else
|
||||
if( Cmd_Argc() < 2 )
|
||||
{
|
||||
Msg( "apropos what?\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
ispattern = partial && Q_strpbrk( partial, "*?" );
|
||||
if( !ispattern )
|
||||
partial = va( "*%s*", partial );
|
||||
partial = Cmd_Args();
|
||||
|
||||
if( !Q_strpbrk( partial, "*?" ))
|
||||
{
|
||||
Q_snprintf( buf, sizeof( buf ), "*%s*", partial );
|
||||
partial = buf;
|
||||
}
|
||||
|
||||
for( var = (convar_t*)Cvar_GetList(); var; var = var->next )
|
||||
{
|
||||
|
@ -1341,7 +1363,7 @@ inserts escape sequences
|
|||
void Cmd_Escape( char *newCommand, const char *oldCommand, int len )
|
||||
{
|
||||
int c;
|
||||
int scripting = CVAR_TO_BOOL( cmd_scripting );
|
||||
int scripting = cmd_scripting.value;
|
||||
|
||||
while( (c = *oldCommand++) && len > 1 )
|
||||
{
|
||||
|
@ -1391,8 +1413,8 @@ void Cmd_Init( void )
|
|||
#endif // XASH_DEDICATED
|
||||
Cmd_AddRestrictedCommand( "alias", Cmd_Alias_f, "create a script function. Without arguments show the list of all alias" );
|
||||
Cmd_AddRestrictedCommand( "unalias", Cmd_UnAlias_f, "remove a script function" );
|
||||
Cmd_AddCommand( "if", Cmd_If_f, "compare and set condition bits" );
|
||||
Cmd_AddCommand( "else", Cmd_Else_f, "invert condition bit" );
|
||||
Cmd_AddRestrictedCommand( "if", Cmd_If_f, "compare and set condition bits" );
|
||||
Cmd_AddRestrictedCommand( "else", Cmd_Else_f, "invert condition bit" );
|
||||
|
||||
#if defined(XASH_HASHED_VARS)
|
||||
Cmd_AddCommand( "basecmd_stats", BaseCmd_Stats_f, "print info about basecmd usage" );
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue