mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-07 22:56:30 -10:00
Compare commits
631
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
322a152476 | ||
|
|
c72a062a84 | ||
|
|
422753976f | ||
|
|
374383bacb | ||
|
|
adfce4ec60 | ||
|
|
08faf52871 | ||
|
|
d99121cd52 | ||
|
|
6ff292a43c | ||
|
|
09f4f63be4 | ||
|
|
2d67fd3ef8 | ||
|
|
5666eb5014 | ||
|
|
8542e9e113 | ||
|
|
699c9e8d52 | ||
|
|
5b45a89287 | ||
|
|
741fc311cd | ||
|
|
aaa9c779c0 | ||
|
|
bfae614189 | ||
|
|
cb956961f6 | ||
|
|
6d2ebd1ed7 | ||
|
|
d7e6187ba8 | ||
|
|
62f6ee86ef | ||
|
|
56ae91c973 | ||
|
|
dfc8cbd1c9 | ||
|
|
77e61af23c | ||
|
|
7b80b0c564 | ||
|
|
a98d3bb064 | ||
|
|
741ee07249 | ||
|
|
04cefad927 | ||
|
|
3d68476505 | ||
|
|
81c63929b5 | ||
|
|
d6d03fbb14 | ||
|
|
9acd25bc28 | ||
|
|
7e00a8b10f | ||
|
|
bb0df2dc43 | ||
|
|
38f858198b | ||
|
|
a83307402a | ||
|
|
097148c2c2 | ||
|
|
fbf8a931c4 | ||
|
|
32d951b27a | ||
|
|
630e6c3e96 | ||
|
|
72ed33502b | ||
|
|
d3806b2107 | ||
|
|
c9a481f4f3 | ||
|
|
0a02f677fe | ||
|
|
d55e4343f9 | ||
|
|
e902934e89 | ||
|
|
26395f7c12 | ||
|
|
de92fe25e3 | ||
|
|
c72fa0917b | ||
|
|
bc0f47269d | ||
|
|
94469dc43f | ||
|
|
ce335dbcc2 | ||
|
|
6660d21f7e | ||
|
|
e622d81e89 | ||
|
|
10c8e16cda | ||
|
|
25029bfdf1 | ||
|
|
2255616ed5 | ||
|
|
62ab705d75 | ||
|
|
77fc335580 | ||
|
|
981b01eea2 | ||
|
|
366dc3749c | ||
|
|
e693367dd0 | ||
|
|
da53960003 | ||
|
|
687c1ba4f7 | ||
|
|
d901470880 | ||
|
|
7e74153a3d | ||
|
|
6cf75b77dc | ||
|
|
3ec0a9c35e | ||
|
|
519f60a63b | ||
|
|
252da89782 | ||
|
|
0f1b3fd6c2 | ||
|
|
58722425a3 | ||
|
|
211110d415 | ||
|
|
61a8aa5592 | ||
|
|
0692286bba | ||
|
|
72dae916a9 | ||
|
|
189ad9f694 | ||
|
|
b9f9fa0f73 | ||
|
|
dc7e88c888 | ||
|
|
b5dae2a56e | ||
|
|
969bfd0bdd | ||
|
|
63e8ae53c5 | ||
|
|
d57aaac8e4 | ||
|
|
ab981bd415 | ||
|
|
df7c91f3e7 | ||
|
|
ee73694cc8 | ||
|
|
65dcfe0a7c | ||
|
|
ae8f8baade | ||
|
|
86fcdb1502 | ||
|
|
b71fc4595c | ||
|
|
471402ec5d | ||
|
|
97fdca6b52 | ||
|
|
b50833e6fb | ||
|
|
4429cbb21c | ||
|
|
4a6d8573a0 | ||
|
|
2c6039759c | ||
|
|
f3a0d56a85 | ||
|
|
243aac1667 | ||
|
|
19fbe05cee | ||
|
|
e581a3b8a3 | ||
|
|
67a2d99a9b | ||
|
|
569f1ee237 | ||
|
|
e9a8b9d8a2 | ||
|
|
0efb98d4a9 | ||
|
|
ec99bf9c03 | ||
|
|
bd6ff021fd | ||
|
|
69213c3338 | ||
|
|
0bffac7615 | ||
|
|
ba089bd95e | ||
|
|
0a1519284f | ||
|
|
877a138192 | ||
|
|
8a34ceef91 | ||
|
|
d638cacc51 | ||
|
|
871317b5bd | ||
|
|
9b7a87d4c5 | ||
|
|
3b07636a16 | ||
|
|
8840d238d7 | ||
|
|
95128dd734 | ||
|
|
30866afbd6 | ||
|
|
2b43677c82 | ||
|
|
94a542a2a3 | ||
|
|
5c064afd95 | ||
|
|
6ee41c06d8 | ||
|
|
58fa411ad3 | ||
|
|
08c2449672 | ||
|
|
726af82c56 | ||
|
|
c11dce4a92 | ||
|
|
0121eb6123 | ||
|
|
8a325362f6 | ||
|
|
4eb0e41142 | ||
|
|
5528e4e42d | ||
|
|
968695f851 | ||
|
|
8f00c6e842 | ||
|
|
8a9edb1215 | ||
|
|
1c9e47ad3d | ||
|
|
74fd3c0637 | ||
|
|
fe0f0558c2 | ||
|
|
11ded47bd5 | ||
|
|
f8801446db | ||
|
|
7492615a31 | ||
|
|
53cfc1eae4 | ||
|
|
252facb6c4 | ||
|
|
65417be571 | ||
|
|
0da41b3943 | ||
|
|
97f9a6c91b | ||
|
|
10cd82456d | ||
|
|
7878ba0d19 | ||
|
|
a6879a1b40 | ||
|
|
cf7706eb1c | ||
|
|
09ed127d06 | ||
|
|
77c3c79143 | ||
|
|
62b74b8743 | ||
|
|
4d99a3b8b3 | ||
|
|
3a9a840633 | ||
|
|
86f67c3c84 | ||
|
|
28bb3bf914 | ||
|
|
bd4b116188 | ||
|
|
0a429e8a32 | ||
|
|
f70253e219 | ||
|
|
e901e44418 | ||
|
|
651268eeea | ||
|
|
9b7c32d0c1 | ||
|
|
d014e53505 | ||
|
|
00b0a80ad9 | ||
|
|
4a7109e1d5 | ||
|
|
1484ddbe77 | ||
|
|
48b03a1789 | ||
|
|
e790cf209a | ||
|
|
1eea298fe1 | ||
|
|
1de63cc881 | ||
|
|
c7be4734d3 | ||
|
|
fbc2a2dab2 | ||
|
|
e5be2372e1 | ||
|
|
9c69e11fe5 | ||
|
|
0173f44070 | ||
|
|
45559c13a9 | ||
|
|
34888cb1a6 | ||
|
|
b77b425f2f | ||
|
|
49b5c10295 | ||
|
|
0396d5670b | ||
|
|
bb6c00a516 | ||
|
|
4d0703ad98 | ||
|
|
27e91d8f6c | ||
|
|
3c4ab2eef1 | ||
|
|
4e7f29ea88 | ||
|
|
793a3d8dd3 | ||
|
|
49abb88385 | ||
|
|
4c2ed1501e | ||
|
|
6b425c1e6b | ||
|
|
978a58dba2 | ||
|
|
3de05aefef | ||
|
|
da951e8be4 | ||
|
|
483a6096bb | ||
|
|
0ac810e7f0 | ||
|
|
0de1e55fb7 | ||
|
|
3827bb9783 | ||
|
|
69013f1d41 | ||
|
|
3ac7864ac6 | ||
|
|
35a654660f | ||
|
|
f975edd343 | ||
|
|
9219712ff0 | ||
|
|
ead6cd9825 | ||
|
|
a32c5dad27 | ||
|
|
34d4ed5dba | ||
|
|
eb012584d6 | ||
|
|
7cadce113d | ||
|
|
17b01fa8eb | ||
|
|
45ea62a9a2 | ||
|
|
979a4b0924 | ||
|
|
e1db71fb69 | ||
|
|
c33d406942 | ||
|
|
30baac39a9 | ||
|
|
15dc45cc0a | ||
|
|
3c41b56449 | ||
|
|
50dbbc4687 | ||
|
|
e19a6f9e01 | ||
|
|
d9184545f7 | ||
|
|
5c07d181ad | ||
|
|
140fed2812 | ||
|
|
dd2fd3ee5c | ||
|
|
dd7c36e43d | ||
|
|
409c7da2d7 | ||
|
|
791e22bc1d | ||
|
|
6a93715c9b | ||
|
|
8fee9804df | ||
|
|
2dc6d64c37 | ||
|
|
a8142b8f80 | ||
|
|
53f98cda99 | ||
|
|
115d06a051 | ||
|
|
485af1bad3 | ||
|
|
0ca5ade5ef | ||
|
|
ff601db6fc | ||
|
|
686bc35cff | ||
|
|
ffe9a085b6 | ||
|
|
33df766edf | ||
|
|
9a6227e7b0 | ||
|
|
c664eac1ee | ||
|
|
a7a9514fd1 | ||
|
|
b402d9158c | ||
|
|
c1b055a685 | ||
|
|
412197d3e9 | ||
|
|
98f1d690f6 | ||
|
|
842dbb1b75 | ||
|
|
df8e85f22e | ||
|
|
73482a6d62 | ||
|
|
afa7976018 | ||
|
|
0d355982d4 | ||
|
|
7f9021cbdb | ||
|
|
1450c71e2e | ||
|
|
d80e6d0f71 | ||
|
|
f6dd3b09ab | ||
|
|
bc5ef0b28d | ||
|
|
8e618ffaec | ||
|
|
889474688c | ||
|
|
d56cb8fc62 | ||
|
|
98f196ee48 | ||
|
|
9f4ad9d1eb | ||
|
|
a69e1d7308 | ||
|
|
34d1bf03f9 | ||
|
|
9fcd96ff97 | ||
|
|
2b77721c79 | ||
|
|
95fafa50c4 | ||
|
|
cac07391ca | ||
|
|
9daeb7f417 | ||
|
|
f0ba0265fd | ||
|
|
5b77cad5ac | ||
|
|
3f024cb324 | ||
|
|
1d60d25cf5 | ||
|
|
be5c98c7e2 | ||
|
|
6212ad29f1 | ||
|
|
5ec30bdaee | ||
|
|
b9b74a3201 | ||
|
|
09c24313d7 | ||
|
|
afdaa3a3ee | ||
|
|
68dcef639d | ||
|
|
91f351b990 | ||
|
|
dd1def4f4c | ||
|
|
8b770792fb | ||
|
|
23f9cfc815 | ||
|
|
11f9175425 | ||
|
|
4fb9c27e71 | ||
|
|
4c7b7a0fef | ||
|
|
3dc1689936 | ||
|
|
94df2777e0 | ||
|
|
c9ebc33d98 | ||
|
|
9bd459d549 | ||
|
|
d9db8bdb71 | ||
|
|
f3cdfcc229 | ||
|
|
44e3f1f9b5 | ||
|
|
da5e7f1510 | ||
|
|
d830a01381 | ||
|
|
d24d536731 | ||
|
|
6d0e166dea | ||
|
|
e0301da596 | ||
|
|
a815c0247c | ||
|
|
f42eaf9637 | ||
|
|
c667668c17 | ||
|
|
8d4643bc7a | ||
|
|
01fb2c1243 | ||
|
|
408f259368 | ||
|
|
a9b8e5c043 | ||
|
|
cfb9540e2c | ||
|
|
88115c7703 | ||
|
|
8dba6770ae | ||
|
|
8f4d51b14a | ||
|
|
185aece470 | ||
|
|
0e962e269b | ||
|
|
095a2efc56 | ||
|
|
944a254551 | ||
|
|
f628999ef9 | ||
|
|
e2fb4d84d7 | ||
|
|
ff952298a2 | ||
|
|
66b3fdfed8 | ||
|
|
451c03f76a | ||
|
|
da30c5a38e | ||
|
|
5206aaabdf | ||
|
|
f6ed93f7a9 | ||
|
|
4f0e2ae9f1 | ||
|
|
c3f595ba0e | ||
|
|
d02d98681a | ||
|
|
98e37b2570 | ||
|
|
3c8b87c958 | ||
|
|
8d44946b2b | ||
|
|
98b9d5c899 | ||
|
|
2f5079fcd1 | ||
|
|
59a8a347a1 | ||
|
|
e04f1b4ca4 | ||
|
|
7da41c32e3 | ||
|
|
73770845b6 | ||
|
|
5828d7f634 | ||
|
|
45f6cdc687 | ||
|
|
13fe34a3c7 | ||
|
|
da64f285bc | ||
|
|
45f9ea2ea4 | ||
|
|
eb73328c14 | ||
|
|
380ca12b0d | ||
|
|
c7e66e26fb | ||
|
|
ff911e666d | ||
|
|
c8619ddd0d | ||
|
|
721b2da37b | ||
|
|
e9f4c1618e | ||
|
|
4eef54c10b | ||
|
|
f5ba1e470c | ||
|
|
94a00ca6ee | ||
|
|
3a8c10bec5 | ||
|
|
e92cc5161e | ||
|
|
ea73ea33ca | ||
|
|
8fe7dc4a1b | ||
|
|
f5bbb21199 | ||
|
|
c2761a6142 | ||
|
|
88b0dba208 | ||
|
|
7173299ca7 | ||
|
|
e35fc10530 | ||
|
|
46e8e735b6 | ||
|
|
e3e40ee576 | ||
|
|
f0b99e24ff | ||
|
|
e0f76e0cfa | ||
|
|
5303440dfb | ||
|
|
138a1d01d4 | ||
|
|
0814bf0ae1 | ||
|
|
39a0cfecbb | ||
|
|
b78d940136 | ||
|
|
bc03442a3c | ||
|
|
8ce1a6f490 | ||
|
|
18d2ef8580 | ||
|
|
4a86b70a69 | ||
|
|
f717c41083 | ||
|
|
92aacc8479 | ||
|
|
2ae7990c61 | ||
|
|
4e8ebedfa0 | ||
|
|
01f418f2fb | ||
|
|
0ed47de357 | ||
|
|
f5f1c97c0f | ||
|
|
b0d3957df7 | ||
|
|
332bd01f0f | ||
|
|
eb8717f051 | ||
|
|
af8ae03d9e | ||
|
|
0ca7299bbc | ||
|
|
98234c3bc2 | ||
|
|
50691c41da | ||
|
|
4a66cb190a | ||
|
|
9ba3a0ccf9 | ||
|
|
b625f51645 | ||
|
|
c2c8acbf13 | ||
|
|
ac58950ac5 | ||
|
|
8a84fffe12 | ||
|
|
0c216ede98 | ||
|
|
3e543729fc | ||
|
|
6385bf73be | ||
|
|
b7a32329db | ||
|
|
b363bda60d | ||
|
|
0b547d971e | ||
|
|
9ac04b9349 | ||
|
|
453b1ca619 | ||
|
|
e6f1332980 | ||
|
|
5840ca84d6 | ||
|
|
aa0e1c755f | ||
|
|
97469d65ef | ||
|
|
5834c01ca9 | ||
|
|
13076364d6 | ||
|
|
e2905e76ca | ||
|
|
accea7bb4d | ||
|
|
733b67ada3 | ||
|
|
de06d1e36f | ||
|
|
7e6eb25492 | ||
|
|
9de5d8d011 | ||
|
|
62d178d896 | ||
|
|
f8b210b659 | ||
|
|
d3e6ee81e1 | ||
|
|
5b01036723 | ||
|
|
66f95312ae | ||
|
|
a737c7a373 | ||
|
|
ead93f3175 | ||
|
|
48b1e3f289 | ||
|
|
8a2641181f | ||
|
|
36e8c3b623 | ||
|
|
1c2a136ef7 | ||
|
|
72272cb8cf | ||
|
|
4062f59128 | ||
|
|
24ab091671 | ||
|
|
7cd17205b5 | ||
|
|
d58bd7db69 | ||
|
|
ce11936e56 | ||
|
|
feda97c148 | ||
|
|
a0e85e7ef5 | ||
|
|
6939403262 | ||
|
|
33e8703555 | ||
|
|
8a87d20415 | ||
|
|
b324d2892c | ||
|
|
54bd7e3963 | ||
|
|
b2230f723b | ||
|
|
f75dafde4a | ||
|
|
d70f92e782 | ||
|
|
d7e042b38a | ||
|
|
941a0c3c8a | ||
|
|
edc6b94f7f | ||
|
|
1182a485ac | ||
|
|
3cd2c40331 | ||
|
|
c13cb44df4 | ||
|
|
aede65107b | ||
|
|
197767ce94 | ||
|
|
7924c66d37 | ||
|
|
3106191cea | ||
|
|
8c4ec9b91c | ||
|
|
5bfcd1d063 | ||
|
|
923265988c | ||
|
|
c485ed8199 | ||
|
|
4353d4d47f | ||
|
|
da65a66932 | ||
|
|
7df8313b8b | ||
|
|
187affe004 | ||
|
|
f29cc2ef86 | ||
|
|
97e15ca135 | ||
|
|
868418c100 | ||
|
|
e413b10ce1 | ||
|
|
bdd740eabd | ||
|
|
d24e3c9295 | ||
|
|
13be144495 | ||
|
|
8857c4561a | ||
|
|
af4a2555db | ||
|
|
ae2c4ef098 | ||
|
|
6e509868d2 | ||
|
|
d0bc3cf91d | ||
|
|
10079c88cd | ||
|
|
3aacb6cb42 | ||
|
|
b434776d53 | ||
|
|
20925f23cc | ||
|
|
64a9e3d03a | ||
|
|
fe01372f46 | ||
|
|
7134e22322 | ||
|
|
fac618c7f0 | ||
|
|
b333104f45 | ||
|
|
c0401c24e5 | ||
|
|
2ded9aa35d | ||
|
|
ad54f588bb | ||
|
|
a64ebca805 | ||
|
|
69781cec25 | ||
|
|
137457e570 | ||
|
|
b7f3ba3660 | ||
|
|
bf6cfe61d7 | ||
|
|
990838051a | ||
|
|
597104c479 | ||
|
|
2ee5d21a10 | ||
|
|
8c1d3492eb | ||
|
|
ba5fcb971a | ||
|
|
5359b12b4f | ||
|
|
0fb7345617 | ||
|
|
a34ca578ba | ||
|
|
7f03ac31ae | ||
|
|
25b396f6a0 | ||
|
|
c6e2f94d0b | ||
|
|
9de8d45f19 | ||
|
|
7f5168e9d6 | ||
|
|
490c5d8357 | ||
|
|
011ca4bb85 | ||
|
|
a4f499ce8c | ||
|
|
5578588894 | ||
|
|
dbee42bdec | ||
|
|
783e4b5ab2 | ||
|
|
cea27244dc | ||
|
|
09084395a5 | ||
|
|
886b14e595 | ||
|
|
2fca5fd965 | ||
|
|
69cb4f0136 | ||
|
|
76d36b1c5f | ||
|
|
bf37a36e89 | ||
|
|
6750f0a4cc | ||
|
|
06a21a0f9b | ||
|
|
3d653bd770 | ||
|
|
db3d92732f | ||
|
|
4fbc0d02fa | ||
|
|
c6f75e7d14 | ||
|
|
8f4d2a27db | ||
|
|
c4bb136d80 | ||
|
|
ea2656e75f | ||
|
|
d70672d7bc | ||
|
|
ccc727a148 | ||
|
|
87ac2ca6a3 | ||
|
|
e8bd6b3929 | ||
|
|
4e7756d29f | ||
|
|
fd96dd287d | ||
|
|
dea5fd9f30 | ||
|
|
5ebf48b9b0 | ||
|
|
2dc2c0643f | ||
|
|
e761d8a8e9 | ||
|
|
36b97487c6 | ||
|
|
367825b1e0 | ||
|
|
8f5a364345 | ||
|
|
07a15286b4 | ||
|
|
8e4deb0454 | ||
|
|
aed44067df | ||
|
|
83844222c4 | ||
|
|
ba5233e33b | ||
|
|
b0bb660eb2 | ||
|
|
74f258a9b3 | ||
|
|
d7d3b8c8e2 | ||
|
|
90aeb3651c | ||
|
|
6ee7679dd6 | ||
|
|
5baae08bdf | ||
|
|
646fb64c2f | ||
|
|
7544f321d6 | ||
|
|
b2ff79fb38 | ||
|
|
94c1cf65b3 | ||
|
|
0ce2908ce6 | ||
|
|
32fbe572e4 | ||
|
|
fb0ff8f1d0 | ||
|
|
2cef1d4aa1 | ||
|
|
9dfb8faea3 | ||
|
|
9651e7dca6 | ||
|
|
51557d3aa3 | ||
|
|
521a9b9461 | ||
|
|
130057c64a | ||
|
|
f63e18957b | ||
|
|
df0be20d22 | ||
|
|
cee37e7a2f | ||
|
|
90e16ffed2 | ||
|
|
c2a52174ba | ||
|
|
e389f7669d | ||
|
|
20681f1550 | ||
|
|
be8ea029da | ||
|
|
3dbcebb56e | ||
|
|
37453ae229 | ||
|
|
9d907c99fe | ||
|
|
490ef52b85 | ||
|
|
cf1cc5e862 | ||
|
|
fc0105141b | ||
|
|
9878b48dd3 | ||
|
|
af99fee8fc | ||
|
|
1cc09d5b8b | ||
|
|
d5c5cc6eb3 | ||
|
|
b5bb5097b9 | ||
|
|
f87e5bf318 | ||
|
|
48667f0cbd | ||
|
|
66637ef5cb | ||
|
|
3b2b58e2cc | ||
|
|
d5282ca697 | ||
|
|
6a099d2adc | ||
|
|
6aa1f4899f | ||
|
|
4ec7d21965 | ||
|
|
bd5a4c4348 | ||
|
|
9135a01b1d | ||
|
|
032579923e | ||
|
|
8c1e753991 | ||
|
|
6a4c74084e | ||
|
|
3799ce7d2f | ||
|
|
2e213d5c97 | ||
|
|
0c17177a1e | ||
|
|
93ced64c6f | ||
|
|
4020b7c594 | ||
|
|
13b26fd59f | ||
|
|
15bda8c4ac | ||
|
|
39ab45dc7c | ||
|
|
16a19783ae | ||
|
|
b1bc4ef44f | ||
|
|
08e664a93a | ||
|
|
aeee05c8dd | ||
|
|
1fb3a65a90 | ||
|
|
d53dc195ee | ||
|
|
5b8880daa7 | ||
|
|
b0fc9cb31a | ||
|
|
323354295f | ||
|
|
b1881a700d | ||
|
|
357cd76252 | ||
|
|
30e70db561 | ||
|
|
2c106f8c4b | ||
|
|
73bfb7a97e | ||
|
|
4bead819f9 | ||
|
|
268828f092 | ||
|
|
1614384a6a | ||
|
|
29b6af84cc | ||
|
|
cafee143c4 | ||
|
|
6e21c8a736 | ||
|
|
bb56958dfc | ||
|
|
120750ebd2 | ||
|
|
3430a1c438 | ||
|
|
1dc2e848cd | ||
|
|
305429bf8b | ||
|
|
ae149b6061 | ||
|
|
429858d02e | ||
|
|
1448277c29 | ||
|
|
61c533559b | ||
|
|
e92121bed4 | ||
|
|
7e399681cd | ||
|
|
f7b0f93c00 | ||
|
|
758ca86f6f | ||
|
|
6406e2fbd4 | ||
|
|
18c2dbbde9 | ||
|
|
ef6c5d4da7 | ||
|
|
cb960a3416 | ||
|
|
194d944108 | ||
|
|
9ac97f2422 |
No files matched your search
+100
@@ -0,0 +1,100 @@
|
||||
---
|
||||
Language: Cpp
|
||||
# BasedOnStyle: LLVM
|
||||
AccessModifierOffset: -2
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveAssignments: true
|
||||
AlignConsecutiveDeclarations: false
|
||||
AlignEscapedNewlinesLeft: false
|
||||
AlignOperands: true
|
||||
AlignTrailingComments: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortBlocksOnASingleLine: false
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: true
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BraceWrapping:
|
||||
AfterClass: false
|
||||
AfterControlStatement: false
|
||||
AfterEnum: false
|
||||
AfterFunction: true
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
IndentBraces: false
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeBraces: Custom
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 120
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
|
||||
IncludeBlocks: Regroup
|
||||
IncludeCategories:
|
||||
- Regex: '^(<.*\.(h|hh|hpp)>)$' # Includes of external libraries
|
||||
Priority: 4
|
||||
- Regex: '^(<.*>)$' # standard library includes (won't match deprecated C headers)
|
||||
Priority: 5
|
||||
- Regex: '^"[^/]*\.(h)"$' # Local includes
|
||||
Priority: 1
|
||||
- Regex: '^".*\.(h)"$' # standard engine includes
|
||||
Priority: 2
|
||||
- Regex: '.*' # Catch all in case something is unhandled above
|
||||
Priority: 3
|
||||
IncludeIsMainRegex: '$'
|
||||
IndentCaseLabels: false
|
||||
IndentWidth: 4
|
||||
IndentWrappedFunctionNames: false
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
ObjCBlockIndentWidth: 2
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PenaltyBreakBeforeFirstCallParameter: 19
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 60
|
||||
PointerAlignment: Left
|
||||
ReflowComments: true
|
||||
SortIncludes: true
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: false
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: Cpp11
|
||||
TabWidth: 4
|
||||
UseTab: ForIndentation
|
||||
...
|
||||
|
||||
@@ -3,12 +3,14 @@ Checks: "-*,\
|
||||
modernize-*,\
|
||||
-modernize-raw-string-literal,\
|
||||
-modernize-use-using,\
|
||||
-modernize-make-unique,\
|
||||
performance-*,\
|
||||
-performance-type-promotion-in-math-fn,\
|
||||
misc-*,\
|
||||
-misc-macro-parentheses,\
|
||||
-misc-misplaced-widening-cast,\
|
||||
-misc-static-assert,\
|
||||
-modernize-make-unique,\
|
||||
"
|
||||
WarningsAsErrors: ''
|
||||
HeaderFilterRegex: 'code/.*$|freespace2/.*$|qtfred/.*$|test/src/.*$|build/.*$'
|
||||
|
||||
@@ -26,9 +26,6 @@
|
||||
*.unsuccessfulbuild
|
||||
ipch/
|
||||
[Oo]bj/
|
||||
[Bb]in
|
||||
[Dd]ebug*/
|
||||
[Rr]elease*/
|
||||
Ankh.NoLoad
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
[submodule "cmake/external/rpavlik-cmake-modules"]
|
||||
path = cmake/external/rpavlik-cmake-modules
|
||||
url = https://github.com/asarium/cmake-modules.git
|
||||
[submodule "lib/libRocket"]
|
||||
path = lib/libRocket
|
||||
url = https://github.com/asarium/libRocket.git
|
||||
+164
-140
@@ -1,157 +1,181 @@
|
||||
language: generic
|
||||
language: bash
|
||||
sudo: required
|
||||
dist: trusty
|
||||
cache:
|
||||
directories:
|
||||
directories:
|
||||
- $HOME/cmake-3.8
|
||||
- $HOME/.ccache
|
||||
addons:
|
||||
apt:
|
||||
packages: &global_deps
|
||||
- ninja-build
|
||||
- libopenal-dev
|
||||
- libreadline6-dev
|
||||
- libpng12-dev
|
||||
- libjpeg62-dev
|
||||
- liblua5.1-0-dev
|
||||
- libjansson-dev
|
||||
- libsdl2-dev
|
||||
- valgrind
|
||||
- qt57base
|
||||
coverity_scan:
|
||||
project:
|
||||
name: "scp-fs2open/fs2open.github.com"
|
||||
notification_email: niffiwan.scp@gmail.com
|
||||
build_command: "ci/travis/script.sh"
|
||||
# must match TRAVIS_BRANCH check below
|
||||
branch_pattern: coverity_scan
|
||||
apt:
|
||||
packages: &global_deps
|
||||
- ninja-build
|
||||
- libopenal-dev
|
||||
- libreadline6-dev
|
||||
- libpng12-dev
|
||||
- libjpeg62-dev
|
||||
- liblua5.1-0-dev
|
||||
- libjansson-dev
|
||||
- libsdl2-dev
|
||||
- libfreetype6-dev
|
||||
- valgrind
|
||||
- qt57base
|
||||
coverity_scan:
|
||||
project:
|
||||
name: "scp-fs2open/fs2open.github.com"
|
||||
notification_email: [email protected]
|
||||
build_command: "ci/travis/script.sh"
|
||||
# must match TRAVIS_BRANCH check below
|
||||
branch_pattern: coverity_scan
|
||||
env:
|
||||
global:
|
||||
# The next declaration is the encrypted COVERITY_SCAN_TOKEN, created
|
||||
# via the "travis encrypt" command using the project repo's public key
|
||||
# also note that fork's don't get access to secure keys
|
||||
# you have to test using a branch in the main repo
|
||||
- secure: "C3wF967ZeliwwP1vC12EMIBOaC568n26Z/cPnwzn317ve59DWH3YSfPZVgvt08GzmaXITGGsJvPB+qxfGoKvQzYE4O1B73q81RpUe5pB3IhF+ThQ91VfQZIRJR5xEGJaLINUlHTTZGX5jxlkVO9wAcauVj/s3b8sQ3dvUZauPvk="
|
||||
# These declarations set INDIEGAMES_USER and INDIEGAMES_PASSWORD for uploading nightly builds to the indiegames server
|
||||
- secure: "lUuRu8XIi8MKNf1ebOfyC4iVEpPyASojJIDWXRo2bNqEF4ILAljXdkVeXeN6H5yKCHD52cxCNTtyePIG/o3p3QEuGSVud9bDS3D7LaQicLETGGrsw3l07U49gF2OKHXGopg0MzBbZUU9QmhoFTAe8t6PV9NDuEayYCheqvTqjZg="
|
||||
- secure: "E/DHLYcPK/hBUqxBYYlUqp5sjgvIqY5A0qRHyQ4bmjsB+WB/Xx71bGCSiF7hk6lTxar1ZI1i5RAXXh9AIvNVaYAIdEOlCP+q3gvwCYuc5naZEKmkxlUCf0oEL4O9Fye93A/3VkFHuBdC1TGPYYf69m4W5r4367wWO9dPRIdWpJA="
|
||||
# These declarations set FS2DOWNLOADS_USER and FS2DOWNLOADS_PASSWORD
|
||||
- secure: "h6GbMX2jLsW1bS9fCM9fthOSJ1nfQQIRWi6EUH2p8u4NFLD5Bfi/C8JhQPKHUzyo3wvKkSHl+PsW7bgr1oXLusRwAur/dtv2N3imqvtbfIz305b00hZlsvbcYmQmUzQFSAdOGShK57JJ5aKQKccaUBP25KqB7Q+JaqBRdaMBS54="
|
||||
- secure: "fUDAPAUUaaYZy8I4zU3SJ0JcK7aw4eb6eTdaEr7LyNyTMSfPgwY6P1MrbSQC0lJNQIUQ5ffjdxE5g7D7OYpoJF9L14ni4UY8t2QASt7kmpgcYihmjeuYy8FQXgmFG8CTxiWBPKTybZJ7voQcvIvRaNG7b2wM9PMfc5lRIondB6c="
|
||||
global:
|
||||
# The next declaration is the encrypted COVERITY_SCAN_TOKEN, created
|
||||
# via the "travis encrypt" command using the project repo's public key
|
||||
# also note that fork's don't get access to secure keys
|
||||
# you have to test using a branch in the main repo
|
||||
- secure: "C3wF967ZeliwwP1vC12EMIBOaC568n26Z/cPnwzn317ve59DWH3YSfPZVgvt08GzmaXITGGsJvPB+qxfGoKvQzYE4O1B73q81RpUe5pB3IhF+ThQ91VfQZIRJR5xEGJaLINUlHTTZGX5jxlkVO9wAcauVj/s3b8sQ3dvUZauPvk="
|
||||
# These declarations set INDIEGAMES_USER and INDIEGAMES_PASSWORD for uploading nightly builds to the indiegames server
|
||||
- secure: "lUuRu8XIi8MKNf1ebOfyC4iVEpPyASojJIDWXRo2bNqEF4ILAljXdkVeXeN6H5yKCHD52cxCNTtyePIG/o3p3QEuGSVud9bDS3D7LaQicLETGGrsw3l07U49gF2OKHXGopg0MzBbZUU9QmhoFTAe8t6PV9NDuEayYCheqvTqjZg="
|
||||
- secure: "E/DHLYcPK/hBUqxBYYlUqp5sjgvIqY5A0qRHyQ4bmjsB+WB/Xx71bGCSiF7hk6lTxar1ZI1i5RAXXh9AIvNVaYAIdEOlCP+q3gvwCYuc5naZEKmkxlUCf0oEL4O9Fye93A/3VkFHuBdC1TGPYYf69m4W5r4367wWO9dPRIdWpJA="
|
||||
# These declarations set FS2DOWNLOADS_USER and FS2DOWNLOADS_PASSWORD
|
||||
- secure: "h6GbMX2jLsW1bS9fCM9fthOSJ1nfQQIRWi6EUH2p8u4NFLD5Bfi/C8JhQPKHUzyo3wvKkSHl+PsW7bgr1oXLusRwAur/dtv2N3imqvtbfIz305b00hZlsvbcYmQmUzQFSAdOGShK57JJ5aKQKccaUBP25KqB7Q+JaqBRdaMBS54="
|
||||
- secure: "fUDAPAUUaaYZy8I4zU3SJ0JcK7aw4eb6eTdaEr7LyNyTMSfPgwY6P1MrbSQC0lJNQIUQ5ffjdxE5g7D7OYpoJF9L14ni4UY8t2QASt7kmpgcYihmjeuYy8FQXgmFG8CTxiWBPKTybZJ7voQcvIvRaNG7b2wM9PMfc5lRIondB6c="
|
||||
deploy:
|
||||
- provider: releases
|
||||
api_key:
|
||||
secure: "Wdt4Ccefo7a0ZDjEJQJgpghh7n72FtNJuKSAPUvoz4gtEX6Ct9J8yJI1t9V3jE3CTbbLJ21/Q6eZRDfT7UfNJe5DdepoJsP9DeFhKMWqQCq+AChqQWlm0KeZAffJoJreL8vXYhnRYcLT9ceZHEH6AqwN9TPV+xJziGPISAkYNZ8="
|
||||
skip_cleanup: true
|
||||
file_glob: true
|
||||
file: "/tmp/builds/*"
|
||||
on:
|
||||
condition: '"$RELEASE_BUILD" == true'
|
||||
tags: true
|
||||
- provider: releases
|
||||
api_key:
|
||||
secure: "Wdt4Ccefo7a0ZDjEJQJgpghh7n72FtNJuKSAPUvoz4gtEX6Ct9J8yJI1t9V3jE3CTbbLJ21/Q6eZRDfT7UfNJe5DdepoJsP9DeFhKMWqQCq+AChqQWlm0KeZAffJoJreL8vXYhnRYcLT9ceZHEH6AqwN9TPV+xJziGPISAkYNZ8="
|
||||
skip_cleanup: true
|
||||
file_glob: true
|
||||
file: "/tmp/builds/*"
|
||||
on:
|
||||
condition: '"$RELEASE_BUILD" == true'
|
||||
tags: true
|
||||
|
||||
- provider: script
|
||||
script: bash ci/travis/ftp_deploy.sh
|
||||
on:
|
||||
condition: '"$NIGHTLY_BUILD" == true'
|
||||
tags: true
|
||||
- provider: script
|
||||
script: bash ci/travis/ftp_deploy.sh
|
||||
on:
|
||||
condition: '"$NIGHTLY_BUILD" == true'
|
||||
tags: true
|
||||
|
||||
- provider: script
|
||||
skip_cleanup: true
|
||||
script: bash ci/travis/ftp_deploy.sh
|
||||
on:
|
||||
condition: $TEST_BUILD = true
|
||||
all_branches: true
|
||||
- provider: script
|
||||
skip_cleanup: true
|
||||
script: bash ci/travis/ftp_deploy.sh
|
||||
on:
|
||||
condition: $TEST_BUILD = true
|
||||
all_branches: true
|
||||
|
||||
matrix:
|
||||
include:
|
||||
# note that gcc Debug MUST be 1st for Coverity
|
||||
- os: linux
|
||||
env: CONFIGURATION="Debug" CC=gcc-5 CXX=g++-5
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- sourceline: 'ppa:beineri/opt-qt571-trusty'
|
||||
packages:
|
||||
- *global_deps
|
||||
- g++-5
|
||||
- os: linux
|
||||
env: CONFIGURATION="Debug" CC=gcc-7 CXX=g++-7
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- sourceline: 'ppa:beineri/opt-qt571-trusty'
|
||||
packages:
|
||||
- g++-7
|
||||
- *global_deps
|
||||
- os: linux
|
||||
env: CONFIGURATION="Debug" CC=clang-4.0 CXX=clang++-4.0 CMAKE_OPTIONS="-DCMAKE_EXPORT_COMPILE_COMMANDS=ON"
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-trusty-4.0
|
||||
- sourceline: 'ppa:beineri/opt-qt571-trusty'
|
||||
packages:
|
||||
- *global_deps
|
||||
- clang-4.0
|
||||
- clang-tidy-4.0
|
||||
- libc++-dev
|
||||
script:
|
||||
- ./ci/travis/script.sh
|
||||
- ./ci/travis/clang_tidy.sh
|
||||
- os: osx
|
||||
env: CONFIGURATION="Debug"
|
||||
include:
|
||||
# note that gcc Debug MUST be 1st for Coverity
|
||||
- os: linux
|
||||
env: CONFIGURATION="Debug" CC=gcc-5 CXX=g++-5
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- sourceline: 'ppa:beineri/opt-qt571-trusty'
|
||||
packages:
|
||||
- *global_deps
|
||||
- g++-5
|
||||
- os: linux
|
||||
env: CONFIGURATION="Debug" CC=gcc-8 CXX=g++-8
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- sourceline: 'ppa:beineri/opt-qt571-trusty'
|
||||
packages:
|
||||
- g++-8
|
||||
- *global_deps
|
||||
- os: linux
|
||||
env: CONFIGURATION="Debug" CC=clang-4.0 CXX=clang++-4.0 CMAKE_OPTIONS="-DCMAKE_EXPORT_COMPILE_COMMANDS=ON"
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-trusty-4.0
|
||||
- sourceline: 'ppa:beineri/opt-qt571-trusty'
|
||||
packages:
|
||||
- *global_deps
|
||||
- clang-4.0
|
||||
- clang-tidy-4.0
|
||||
- libc++-dev
|
||||
script:
|
||||
- ./ci/travis/script.sh
|
||||
- ./ci/travis/clang_tidy.sh
|
||||
- os: osx
|
||||
env: CONFIGURATION="Debug"
|
||||
|
||||
- os: windows
|
||||
env: CONFIGURATION="Debug" CMAKE_TOOLSET=v141_xp CMAKE_GENERATOR="Visual Studio 15 2017"
|
||||
- os: windows
|
||||
env: CONFIGURATION="Debug" CMAKE_TOOLSET="" CMAKE_GENERATOR="Ninja"
|
||||
|
||||
- os: linux
|
||||
env: CONFIGURATION="Release" CC=gcc-5 CXX=g++-5
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- sourceline: 'ppa:beineri/opt-qt571-trusty'
|
||||
packages:
|
||||
- *global_deps
|
||||
- g++-5
|
||||
- os: linux
|
||||
env: CONFIGURATION="Release" CC=gcc-8 CXX=g++-8
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- sourceline: 'ppa:beineri/opt-qt571-trusty'
|
||||
packages:
|
||||
- g++-8
|
||||
- *global_deps
|
||||
- os: linux
|
||||
env: CONFIGURATION="Release" CC=clang-4.0 CXX=clang++-4.0
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-trusty-4.0
|
||||
- sourceline: 'ppa:beineri/opt-qt571-trusty'
|
||||
packages:
|
||||
- *global_deps
|
||||
- clang-4.0
|
||||
- libc++-dev
|
||||
- os: osx
|
||||
env: CONFIGURATION="Release"
|
||||
|
||||
- os: windows
|
||||
env: CONFIGURATION="Release" CMAKE_TOOLSET=v141_xp CMAKE_GENERATOR="Visual Studio 15 2017"
|
||||
- os: windows
|
||||
env: CONFIGURATION="Release" CMAKE_TOOLSET="" CMAKE_GENERATOR="Ninja"
|
||||
# As long as Windows is still experimental on Travis CI, allow failures
|
||||
allow_failures:
|
||||
- os: windows
|
||||
env: CONFIGURATION="Debug" CMAKE_TOOLSET=v141_xp CMAKE_GENERATOR="Visual Studio 15 2017"
|
||||
- os: windows
|
||||
env: CONFIGURATION="Debug" CMAKE_TOOLSET="" CMAKE_GENERATOR="Ninja"
|
||||
- os: windows
|
||||
env: CONFIGURATION="Release" CMAKE_TOOLSET=v141_xp CMAKE_GENERATOR="Visual Studio 15 2017"
|
||||
- os: windows
|
||||
env: CONFIGURATION="Release" CMAKE_TOOLSET="" CMAKE_GENERATOR="Ninja"
|
||||
fast_finish: true
|
||||
|
||||
- os: linux
|
||||
env: CONFIGURATION="Release" CC=gcc-5 CXX=g++-5
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- sourceline: 'ppa:beineri/opt-qt571-trusty'
|
||||
packages:
|
||||
- *global_deps
|
||||
- g++-5
|
||||
- os: linux
|
||||
env: CONFIGURATION="Release" CC=gcc-7 CXX=g++-7
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- sourceline: 'ppa:beineri/opt-qt571-trusty'
|
||||
packages:
|
||||
- g++-7
|
||||
- *global_deps
|
||||
- os: linux
|
||||
env: CONFIGURATION="Release" CC=clang-4.0 CXX=clang++-4.0
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-trusty-4.0
|
||||
- sourceline: 'ppa:beineri/opt-qt571-trusty'
|
||||
packages:
|
||||
- *global_deps
|
||||
- clang-4.0
|
||||
- libc++-dev
|
||||
- os: osx
|
||||
env: CONFIGURATION="Release"
|
||||
before_install:
|
||||
# ugly hack; if running a coverity scan abort all except the 1st build
|
||||
# see note re gcc compiler above needing to be 1st
|
||||
# also note that branch_pattern & the TRAVIS_BRANCH check must match
|
||||
# unfortunately COVERITY_SCAN_BRANCH isn't defined until later in the
|
||||
# build process
|
||||
- if ([[ "${TRAVIS_JOB_NUMBER##*.}" != "1" ]] && [[ "${TRAVIS_BRANCH}" == "coverity_scan" ]]); then false ; fi
|
||||
- source "./ci/travis/check_release.sh"
|
||||
- "./ci/travis/before_install.sh"
|
||||
# ugly hack; if running a coverity scan abort all except the 1st build
|
||||
# see note re gcc compiler above needing to be 1st
|
||||
# also note that branch_pattern & the TRAVIS_BRANCH check must match
|
||||
# unfortunately COVERITY_SCAN_BRANCH isn't defined until later in the
|
||||
# build process
|
||||
- if ([[ "${TRAVIS_JOB_NUMBER##*.}" != "1" ]] && [[ "${TRAVIS_BRANCH}" == "coverity_scan" ]]); then false ; fi
|
||||
- source "./ci/travis/check_release.sh"
|
||||
- "./ci/travis/before_install.sh"
|
||||
install:
|
||||
- "./ci/travis/install.sh"
|
||||
- export PATH=$HOME/cmake-3.6/bin:$PATH
|
||||
- if [ "$TRAVIS_OS_NAME" = "windows" ]; then export PATH="/c/Program Files/CMake/bin":$PATH; fi
|
||||
- "./ci/travis/install.sh"
|
||||
- export PATH=$HOME/cmake-3.6/bin:$PATH
|
||||
before_script:
|
||||
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then QT_ENV_SCRIPT=$(find /opt -name 'qt*-env.sh'); source $QT_ENV_SCRIPT; fi
|
||||
- "./ci/travis/before_script.sh"
|
||||
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then QT_ENV_SCRIPT=$(find /opt -name 'qt*-env.sh'); source $QT_ENV_SCRIPT; fi
|
||||
- "./ci/travis/before_script.sh"
|
||||
script:
|
||||
- if [ "$BUILD_DEPLOYMENT" = true ] ; then ./ci/travis/release.sh ; else ./ci/travis/script.sh ; fi
|
||||
- if [ "$BUILD_DEPLOYMENT" = true ] ; then ./ci/travis/release.sh ; else ./ci/travis/script.sh ; fi
|
||||
@@ -84,7 +84,6 @@ IF (WIN32)
|
||||
OPTION(FSO_BUILD_FRED2 "Build FRED2 binary" ON)
|
||||
elseif(UNIX)
|
||||
option(FSO_BUILD_APPIMAGE "Build an AppImage package" OFF)
|
||||
set(APPIMAGE_ASSISTANT "" CACHE STRING "The root directory of an AppImage clone.")
|
||||
ENDIF(WIN32)
|
||||
|
||||
OPTION(FSO_BUILD_TOOLS "Build tools related to FSO" OFF)
|
||||
|
||||
+2
-2
@@ -9,11 +9,11 @@ environment:
|
||||
- BuildID: 0
|
||||
CMAKE_GENERATOR: Visual Studio 14 2015
|
||||
PlatformToolset: v140_xp
|
||||
QT_DIR: C:\Qt\5.9.5\msvc2015
|
||||
QT_DIR: C:\Qt\5.9\msvc2015
|
||||
- BuildID: 1
|
||||
CMAKE_GENERATOR: Visual Studio 14 2015 Win64
|
||||
PlatformToolset: v140_xp
|
||||
QT_DIR: C:\Qt\5.9.5\msvc2015_64
|
||||
QT_DIR: C:\Qt\5.9\msvc2015_64
|
||||
before_build:
|
||||
- git submodule update --init --recursive
|
||||
build_script:
|
||||
|
||||
@@ -14,7 +14,7 @@ $NightlyConfigurations = @(
|
||||
PackageType="Win64";
|
||||
Toolset="v140_xp";
|
||||
SimdType="SSE2";
|
||||
QtDir="C:\Qt\5.9.5\msvc2015_64";
|
||||
QtDir="C:\Qt\5.9\msvc2015_64";
|
||||
SourcePackage=$false;
|
||||
},
|
||||
[BuildConfig]@{
|
||||
@@ -22,7 +22,7 @@ $NightlyConfigurations = @(
|
||||
PackageType="Win32";
|
||||
Toolset="v140_xp";
|
||||
SimdType="SSE2";
|
||||
QtDir="C:\Qt\5.9.5\msvc2015";
|
||||
QtDir="C:\Qt\5.9\msvc2015";
|
||||
SourcePackage=$false;
|
||||
}
|
||||
)
|
||||
@@ -32,7 +32,7 @@ $ReleaseConfigurations = @(
|
||||
PackageType="Win32";
|
||||
Toolset="v140_xp";
|
||||
SimdType="SSE2";
|
||||
QtDir="C:\Qt\5.9.5\msvc2015";
|
||||
QtDir="C:\Qt\5.9\msvc2015";
|
||||
SourcePackage=$true;
|
||||
}
|
||||
[BuildConfig]@{
|
||||
@@ -40,7 +40,7 @@ $ReleaseConfigurations = @(
|
||||
PackageType="Win32-AVX";
|
||||
Toolset="v140_xp";
|
||||
SimdType="AVX";
|
||||
QtDir="C:\Qt\5.9.5\msvc2015";
|
||||
QtDir="C:\Qt\5.9\msvc2015";
|
||||
SourcePackage=$false;
|
||||
}
|
||||
[BuildConfig]@{
|
||||
@@ -48,7 +48,7 @@ $ReleaseConfigurations = @(
|
||||
PackageType="Win64";
|
||||
Toolset="v140_xp";
|
||||
SimdType="SSE2";
|
||||
QtDir="C:\Qt\5.9.5\msvc2015_64";
|
||||
QtDir="C:\Qt\5.9\msvc2015_64";
|
||||
SourcePackage=$false;
|
||||
}
|
||||
[BuildConfig]@{
|
||||
@@ -56,7 +56,7 @@ $ReleaseConfigurations = @(
|
||||
PackageType="Win64-AVX";
|
||||
Toolset="v140_xp";
|
||||
SimdType="AVX";
|
||||
QtDir="C:\Qt\5.9.5\msvc2015_64";
|
||||
QtDir="C:\Qt\5.9\msvc2015_64";
|
||||
SourcePackage=$false;
|
||||
}
|
||||
)
|
||||
@@ -133,6 +133,7 @@ if ($DeployBuild) {
|
||||
|
||||
cmake -DCMAKE_INSTALL_PREFIX="$env:APPVEYOR_BUILD_FOLDER/../install" -DFSO_USE_SPEECH="ON" `
|
||||
-DFSO_USE_VOICEREC="ON" -DMSVC_SIMD_INSTRUCTIONS="$($buildConfig.SimdType)" `
|
||||
-DQT5_INSTALL_ROOT="$($buildConfig.QtDir)" -DFSO_BUILD_QTFRED=ON `
|
||||
-G "$($buildConfig.Generator)" -T "$($buildConfig.Toolset)" ..
|
||||
|
||||
$Configs = @("Release", "FastDebug")
|
||||
|
||||
@@ -8,4 +8,7 @@ if [ "$TRAVIS_OS_NAME" = "linux" ]; then
|
||||
elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
|
||||
# Nothing to do here
|
||||
:
|
||||
elif [ "$TRAVIS_OS_NAME" = "windows" ]; then
|
||||
# Nothing to do here
|
||||
:
|
||||
fi
|
||||
@@ -2,15 +2,19 @@
|
||||
|
||||
set -ex
|
||||
|
||||
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
|
||||
mkdir -p /tmp/builds
|
||||
if [ "$RELEASE_BUILD" = true ]; then
|
||||
# Package the source code in release builds
|
||||
PARENT_DIR="$(basename "$PWD")"
|
||||
(cd .. && tar -czvf /tmp/builds/$PACKAGE_NAME-source-Unix.tar.gz --exclude-vcs "$PARENT_DIR")
|
||||
fi
|
||||
fi
|
||||
|
||||
mkdir -p build
|
||||
cd build
|
||||
|
||||
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
|
||||
if [ "$RELEASE_BUILD" = true ]; then
|
||||
PARENT_DIR="$(basename $PWD)"
|
||||
(cd .. && tar -czvf /tmp/builds/$PACKAGE_NAME-source-Unix.tar.gz --exclude-vcs "$PARENT_DIR")
|
||||
fi
|
||||
|
||||
CXXFLAGS="-m64 -mtune=generic -mfpmath=sse -msse -msse2 -pipe -Wno-unknown-pragmas"
|
||||
CFLAGS="-m64 -mtune=generic -mfpmath=sse -msse -msse2 -pipe -Wno-unknown-pragmas"
|
||||
|
||||
@@ -27,8 +31,7 @@ if [ "$TRAVIS_OS_NAME" = "linux" ]; then
|
||||
mkdir -p $config
|
||||
cd $config
|
||||
eval $CMAKE -DFSO_INSTALL_DEBUG_FILES=ON -DCMAKE_BUILD_TYPE=$config -DCMAKE_INSTALL_PREFIX="/tmp/release/$config" \
|
||||
-DFSO_BUILD_APPIMAGE=ON -DAPPIMAGE_ASSISTANT="$HOME/AppImageAssistant" \
|
||||
-DFSO_BUILD_INCLUDED_LIBS=ON -DFFMPEG_USE_PRECOMPILED=ON ../..
|
||||
-DFSO_BUILD_APPIMAGE=ON -DFSO_BUILD_INCLUDED_LIBS=ON -DFFMPEG_USE_PRECOMPILED=ON -DFSO_BUILD_QTFRED=OFF ../..
|
||||
cd ..
|
||||
done
|
||||
else
|
||||
@@ -40,4 +43,12 @@ elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
|
||||
else
|
||||
cmake -G "Xcode" $CMAKE_OPTIONS ..
|
||||
fi
|
||||
elif [ "$TRAVIS_OS_NAME" = "windows" ]; then
|
||||
if [ "$CMAKE_GENERATOR" = "Ninja" ]; then
|
||||
cmake -DFSO_USE_SPEECH="OFF" -DFSO_FATAL_WARNINGS="ON" -DFSO_USE_VOICEREC="OFF" -DFSO_BUILD_TESTS="ON" \
|
||||
-DFSO_BUILD_FRED2="OFF" -G "$CMAKE_GENERATOR" ..
|
||||
else
|
||||
cmake -DFSO_USE_SPEECH="ON" -DFSO_FATAL_WARNINGS="ON" -DFSO_USE_VOICEREC="OFF" -DFSO_BUILD_TESTS="ON" \
|
||||
-DMSVC_SIMD_INSTRUCTIONS=SSE2 -DFSO_BUILD_FRED2="ON" -G "$CMAKE_GENERATOR" -T "$CMAKE_TOOLSET" ..
|
||||
fi
|
||||
fi
|
||||
@@ -58,6 +58,11 @@ if [ "$BUILD_DEPLOYMENT" = true ]; then
|
||||
echo "Skipping non-release configuration";
|
||||
exit 0;
|
||||
fi
|
||||
|
||||
if [ "$TRAVIS_OS_NAME" = "windows" ]; then
|
||||
echo "Skipping non-release platform"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
export RELEASE_BUILD
|
||||
|
||||
@@ -16,14 +16,19 @@ if [ "$TRAVIS_OS_NAME" = "linux" ]; then
|
||||
cd $HOME
|
||||
|
||||
if [ "${BUILD_DEPLOYMENT}" = true ]; then
|
||||
wget -c "https://github.com/probonopd/AppImageKit/releases/download/5/AppImageAssistant" # (64-bit)
|
||||
chmod a+x ./AppImageAssistant
|
||||
wget -O appimagetool -c "https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage" # (64-bit)
|
||||
chmod a+x ./appimagetool
|
||||
|
||||
wget -O linuxdeployqt -c "https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage" # (64-bit)
|
||||
chmod a+x ./linuxdeployqt
|
||||
fi
|
||||
elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
|
||||
gem install xcpretty
|
||||
|
||||
brew update
|
||||
brew outdated cmake || brew upgrade cmake
|
||||
elif [ "$TRAVIS_OS_NAME" = "windows" ]; then
|
||||
choco install mingw ninja
|
||||
fi
|
||||
|
||||
cmake --version
|
||||
+34
-1
@@ -8,7 +8,40 @@ if [ "$TRAVIS_OS_NAME" = "linux" ]; then
|
||||
for config in $BUILD_CONFIGS
|
||||
do
|
||||
cd "$config"
|
||||
ninja appimage
|
||||
|
||||
# Compile all targets
|
||||
ninja all
|
||||
|
||||
# Install Freespace2 targets
|
||||
cmake -DCMAKE_INSTALL_PREFIX=/tmp/release/$config/fso -DCOMPONENT=Unspecified -P cmake_install.cmake
|
||||
cmake -DCMAKE_INSTALL_PREFIX=/tmp/release/$config/fso -DCOMPONENT=Freespace2 -P cmake_install.cmake
|
||||
|
||||
# We need to be a bit creative for determining the AppImage name since we don't want to hard-code the name
|
||||
FILENAME="$(find /tmp/release/$config/fso/bin -name 'fs2_open_*' -type f -printf "%f\n").AppImage"
|
||||
$HOME/appimagetool -n /tmp/release/$config/fso "/tmp/release/$config/fso/$FILENAME"
|
||||
|
||||
: <<'END'
|
||||
# Install qtFRED targets
|
||||
cmake -DCMAKE_INSTALL_PREFIX=/tmp/release/$config/qtfred/usr -DCOMPONENT=Unspecified -P cmake_install.cmake
|
||||
cmake -DCMAKE_INSTALL_PREFIX=/tmp/release/$config/qtfred/usr -DCOMPONENT=qtFRED -P cmake_install.cmake
|
||||
|
||||
PREV="$(pwd)"
|
||||
cd /tmp/release/$config/qtfred
|
||||
|
||||
unset QTDIR; unset QT_PLUGIN_PATH; unset LD_LIBRARY_PATH
|
||||
$HOME/linuxdeployqt usr/qtfred.desktop -bundle-non-qt-libs
|
||||
# Move our AppRun script to the right location
|
||||
mv usr/AppRun AppRun
|
||||
|
||||
echo "Embed newer libstdc++ for distros that don't come with it (ubuntu 14.04)";
|
||||
mkdir -p usr/optional/; mkdir -p usr/optional/libstdc++/;
|
||||
cp /usr/lib/x86_64-linux-gnu/libstdc++.so.6 ./usr/optional/libstdc++/;
|
||||
|
||||
$HOME/appimagetool -n . "$(find /tmp/release/$config/qtfred/usr/bin -name 'qtfred_*' -type f -printf "%f\n").AppImage"
|
||||
|
||||
cd "$PREV"
|
||||
END
|
||||
|
||||
cd ..
|
||||
done
|
||||
|
||||
|
||||
+13
-2
@@ -7,8 +7,13 @@ cd build
|
||||
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
|
||||
ninja -k 20 all
|
||||
|
||||
valgrind --leak-check=full --error-exitcode=1 --gen-suppressions=all \
|
||||
--suppressions="$TRAVIS_BUILD_DIR/ci/travis/valgrind.supp" ./bin/unittests --gtest_shuffle
|
||||
|
||||
if [ "$CONFIGURATION" = "Debug" ]; then
|
||||
valgrind --leak-check=full --error-exitcode=1 --gen-suppressions=all \
|
||||
--suppressions="$TRAVIS_BUILD_DIR/ci/travis/valgrind.supp" ./bin/unittests --gtest_shuffle
|
||||
else
|
||||
./bin/unittests --gtest_shuffle
|
||||
fi
|
||||
elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
|
||||
cmake --build . --config "$CONFIGURATION" | tee build.log | xcpretty
|
||||
XCODE_RET=${PIPESTATUS[0]}
|
||||
@@ -17,4 +22,10 @@ elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
|
||||
curl --upload-file build.log.tar.gz "https://transfer.sh/build.log.tar.gz"
|
||||
exit $XCODE_RET
|
||||
fi
|
||||
elif [ "$TRAVIS_OS_NAME" = "windows" ]; then
|
||||
if [ "$CMAKE_GENERATOR" = "Ninja" ]; then
|
||||
cmake --build . --config "$CONFIGURATION"
|
||||
else
|
||||
cmake --build . --config "$CONFIGURATION" -- /verbosity:minimal
|
||||
fi
|
||||
fi
|
||||
+16
-1
@@ -25,4 +25,19 @@
|
||||
fun:_dl_init
|
||||
fun:dl_open_worker
|
||||
fun:_dl_catch_error
|
||||
}
|
||||
}
|
||||
{
|
||||
CLang Lua unitialized value error
|
||||
Memcheck:Cond
|
||||
...
|
||||
fun:luaH_get
|
||||
fun:lua_rawget
|
||||
fun:_ZN12_GLOBAL__N_117ade_index_handlerEP9lua_State
|
||||
}
|
||||
{
|
||||
False-positive uninitialized variable warning
|
||||
Memcheck:Cond
|
||||
fun:_Z23cf_check_location_flagsjj
|
||||
fun:_Z29cf_create_default_path_stringPcjiPKcbj
|
||||
...
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=FreeSpace Open
|
||||
Exec=$<TARGET_FILE_NAME:Freespace2>
|
||||
Icon=app_icon.png
|
||||
Icon=app_icon
|
||||
Categories=Game;
|
||||
@@ -6,18 +6,16 @@ configure_file("${CMAKE_CURRENT_LIST_DIR}/AppRun.in" "${CMAKE_CURRENT_BINARY_DIR
|
||||
file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/AppRun-$<CONFIG>"
|
||||
INPUT "${CMAKE_CURRENT_BINARY_DIR}/AppRun.gen")
|
||||
|
||||
install(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/AppRun-$<CONFIG>" DESTINATION "." RENAME "AppRun")
|
||||
install(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/AppRun-$<CONFIG>" DESTINATION "." RENAME "AppRun"
|
||||
COMPONENT "Freespace2")
|
||||
|
||||
|
||||
configure_file("${CMAKE_CURRENT_LIST_DIR}/AppImage.desktop.in" "${CMAKE_CURRENT_BINARY_DIR}/AppImage.desktop.gen" @ONLY)
|
||||
file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/AppImage-$<CONFIG>.desktop"
|
||||
INPUT "${CMAKE_CURRENT_BINARY_DIR}/AppImage.desktop.gen")
|
||||
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/AppImage-$<CONFIG>.desktop" DESTINATION "." RENAME "fso.desktop")
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/AppImage-$<CONFIG>.desktop" DESTINATION "." RENAME "fso.desktop"
|
||||
COMPONENT "Freespace2")
|
||||
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/freespace2/resources/app_icon.png" DESTINATION ".")
|
||||
|
||||
add_custom_target(appimage
|
||||
COMMAND "${APPIMAGE_ASSISTANT}" "${CMAKE_INSTALL_PREFIX}" "${CMAKE_INSTALL_PREFIX}/fs2_open_${FSO_BINARY_SUFFIX}.AppImage")
|
||||
|
||||
add_dependencies(appimage install)
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/freespace2/resources/app_icon.png" DESTINATION "."
|
||||
COMPONENT "Freespace2")
|
||||
@@ -9,8 +9,6 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -funroll-loops -fsigned-char -Wno-
|
||||
# Omit "conversion from string literal to 'char *' is deprecated" warnings.
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-write-strings")
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-function")
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated -Wno-char-subscripts")
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fcolor-diagnostics")
|
||||
|
||||
@@ -66,8 +66,6 @@ set(COMPILER_FLAGS "${COMPILER_FLAGS} ${SANITIZE_FLAGS}")
|
||||
|
||||
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wformat-security")
|
||||
|
||||
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wno-unused-function")
|
||||
|
||||
# Dear Clang, please tell us if a function does not return a value since that part of the standard is stupid!
|
||||
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wreturn-type")
|
||||
|
||||
|
||||
@@ -78,13 +78,22 @@ set(COMPILER_FLAGS "${COMPILER_FLAGS} ${SANITIZE_FLAGS}")
|
||||
|
||||
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wformat-security")
|
||||
|
||||
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wno-unused-function")
|
||||
|
||||
# Dear GCC, please tell us if a function does not return a value since that part of the standard is stupid!
|
||||
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wreturn-type")
|
||||
|
||||
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wno-deprecated -Wno-char-subscripts")
|
||||
|
||||
# These two warnings cause a lot of false-positives in the FSO code base
|
||||
check_cxx_compiler_flag(-Wstringop-truncation SUPPORTS_STRINGOP_TRUNCATION)
|
||||
if(SUPPORTS_STRINGOP_TRUNCATION)
|
||||
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wno-stringop-truncation")
|
||||
endif()
|
||||
|
||||
check_cxx_compiler_flag(-Wstringop-overflow SUPPORTS_STRINGOP_OVERFLOW)
|
||||
if(SUPPORTS_STRINGOP_TRUNCATION)
|
||||
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wno-stringop-overflow")
|
||||
endif()
|
||||
|
||||
set(COMPILER_FLAGS_RELEASE "-O2 -Wno-unused-variable -Wno-unused-but-set-variable -Wno-array-bounds -Wno-empty-body -Wno-clobbered -Wno-unused-parameter")
|
||||
|
||||
set(COMPILER_FLAGS_DEBUG "-O0 -g -Wshadow")
|
||||
|
||||
@@ -36,6 +36,7 @@ set(WARNING_FLAGS
|
||||
/wd4592 # "symbol will be dynamically initialized" is being generated by a compiler bug, see https://stackoverflow.com/a/34027257 for an explanation - m!m
|
||||
$<$<CONFIG:Release>:/wd4101> # In release mode there are unreferenced variables because debug needs them
|
||||
/wd4995 # "'vsprintf': name was marked as #pragma deprecated" is being caused by our custom definition of vsprintf. I have no idea what causes this or how to fix it - m!m
|
||||
/wd4723 # "potential divide by 0" is caused by some code that definitely will not divide by zero - m!m
|
||||
)
|
||||
|
||||
target_compile_options(compiler INTERFACE ${WARNING_FLAGS})
|
||||
@@ -135,9 +136,9 @@ else()
|
||||
ENDIF()
|
||||
endif()
|
||||
|
||||
target_compile_definitions(compiler INTERFACE _CRT_SECURE_NO_DEPRECATE
|
||||
_CRT_SECURE_NO_WARNINGS _SECURE_SCL=0 NOMINMAX "$<$<CONFIG:FastDebug>:_ITERATOR_DEBUG_LEVEL=0>")
|
||||
|
||||
target_compile_definitions(compiler INTERFACE _CRT_SECURE_NO_DEPRECATE _CRT_SECURE_NO_WARNINGS _SECURE_SCL=0 NOMINMAX
|
||||
"$<$<CONFIG:FastDebug>:_ITERATOR_DEBUG_LEVEL=0>" _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING)
|
||||
|
||||
if (FSO_FATAL_WARNINGS)
|
||||
# Make warnings fatal if the right variable is set
|
||||
target_compile_options(compiler INTERFACE "/WX")
|
||||
|
||||
@@ -225,3 +225,13 @@ function(list_target_dependencies _target _out_var)
|
||||
list(REMOVE_DUPLICATES out_list)
|
||||
set(${_out_var} ${out_list} PARENT_SCOPE)
|
||||
endfunction(list_target_dependencies)
|
||||
|
||||
macro(add_file_folder FOLDER_NAME)
|
||||
string(MAKE_C_IDENTIFIER "${FOLDER_NAME}" VARIABLE_NAME)
|
||||
set(files_${VARIABLE_NAME} ${files_${VARIABLE_NAME}} ${ARGN})
|
||||
|
||||
string(REPLACE "/" "\\" FIXED_FOLDER_FILE "${FOLDER_NAME}")
|
||||
|
||||
source_group("${FIXED_FOLDER_FILE}" FILES ${ARGN})
|
||||
set(source_files ${source_files} ${ARGN})
|
||||
endmacro(add_file_folder)
|
||||
+5
-1
@@ -3,7 +3,7 @@ INCLUDE(source_groups.cmake)
|
||||
|
||||
INCLUDE(voice_rec.cmake)
|
||||
|
||||
ADD_LIBRARY(code STATIC ${file_root} ${VOICE_REC_FILES})
|
||||
ADD_LIBRARY(code STATIC ${source_files} ${VOICE_REC_FILES})
|
||||
|
||||
target_compile_features(code PUBLIC ${REQUIRED_CXX_FEATURES})
|
||||
|
||||
@@ -37,6 +37,10 @@ TARGET_LINK_LIBRARIES(code PUBLIC compiler)
|
||||
|
||||
target_link_libraries(code PUBLIC md5)
|
||||
|
||||
target_link_libraries(code PUBLIC discord-rpc)
|
||||
|
||||
target_link_libraries(code PUBLIC libRocket)
|
||||
|
||||
enable_clang_tidy(code)
|
||||
|
||||
IF (FSO_USE_SPEECH)
|
||||
|
||||
+4
-9
@@ -567,9 +567,9 @@ extern void ai_dock_with_object(object *docker, int docker_index, object *dockee
|
||||
extern void ai_stay_still(object *still_objp, vec3d *view_pos);
|
||||
extern void ai_do_default_behavior(object *obj);
|
||||
extern void ai_start_waypoints(object *objp, waypoint_list *wp_list, int wp_flags);
|
||||
extern void ai_ship_hit(object *objp_ship, object *hit_objp, vec3d *hitpos, int shield_quadrant, vec3d *hit_normal);
|
||||
extern void ai_ship_destroy(int shipnum, Ship::Exit_Flags method);
|
||||
extern void ai_turn_towards_vector(vec3d *dest, object *objp, float frametime, float turn_time, vec3d *slide_vec, vec3d *rel_pos, float bank_override, int flags, vec3d *rvec = NULL, int sexp_flags = 0);
|
||||
extern void ai_ship_hit(object *objp_ship, object *hit_objp, vec3d *hit_normal);
|
||||
extern void ai_ship_destroy(int shipnum);
|
||||
extern void ai_turn_towards_vector(vec3d *dest, object *objp, float turn_time, vec3d *slide_vec, vec3d *rel_pos, float bank_override, int flags, vec3d *rvec = nullptr, int sexp_flags = 0);
|
||||
extern void init_ai_object(int objnum);
|
||||
extern void ai_init(void); // Call this one to parse ai.tbl.
|
||||
extern void ai_level_init(void); // Call before each level to reset AI
|
||||
@@ -587,13 +587,10 @@ extern void get_absolute_wing_pos_autopilot( vec3d *result_pos, object *leader_o
|
||||
|
||||
// Interface from goals code to AI. Set ship to guard. *objp guards *other_objp
|
||||
extern void ai_set_guard_object(object *objp, object *other_objp);
|
||||
extern void ai_set_evade_object(object *objp, object *other_objp);
|
||||
extern void ai_set_guard_wing(object *objp, int wingnum);
|
||||
extern void ai_warp_out(object *objp, vec3d *vp);
|
||||
extern void ai_attack_wing(object *attacker, int wingnum);
|
||||
extern void ai_deathroll_start(object *ship_obj);
|
||||
extern void ai_fly_in_formation(int wing_num); // Force wing to fly in formation.
|
||||
extern void ai_disband_formation(int wing_num); // Force wing to disband formation flying.
|
||||
extern int set_target_objnum(ai_info *aip, int objnum);
|
||||
extern void ai_form_on_wing(object *objp, object *goal_objp);
|
||||
extern void ai_do_stay_near(object *objp, object *other_obj, float dist);
|
||||
@@ -622,7 +619,7 @@ extern float ai_path();
|
||||
extern void evade_weapon();
|
||||
extern int might_collide_with_ship(object *obj1, object *obj2, float dot_to_enemy, float dist_to_enemy, float duration);
|
||||
extern int ai_fire_primary_weapon(object *objp); //changed to return weather it fired-Bobboau
|
||||
extern int ai_fire_secondary_weapon(object *objp, int priority1 = -1, int priority2 = -1);
|
||||
extern int ai_fire_secondary_weapon(object *objp);
|
||||
extern float ai_get_weapon_dist(ship_weapon *swp);
|
||||
extern void turn_towards_point(object *objp, vec3d *point, vec3d *slide_vec, float bank_override);
|
||||
extern int ai_maybe_fire_afterburner(object *objp, ai_info *aip);
|
||||
@@ -646,8 +643,6 @@ extern void ai_do_objects_repairing_stuff( object *repaired_obj, object *repair_
|
||||
// Move to a position relative to a dock bay using thrusters.
|
||||
extern float dock_orient_and_approach(object *docker_objp, int docker_index, object *dockee_objp, int dockee_index, int dock_mode, rotating_dockpoint_info *rdinfo = NULL);
|
||||
|
||||
extern int find_danger_weapon(object *sobjp, float dtime, float *atime, float dot_threshhold);
|
||||
|
||||
void ai_set_mode_warp_out(object *objp, ai_info *aip);
|
||||
|
||||
// prototyped by Goober5000
|
||||
|
||||
@@ -87,6 +87,7 @@ namespace AI {
|
||||
Fix_heat_seeker_stealth_bug,
|
||||
Fix_linked_primary_bug,
|
||||
Force_beam_turret_fov,
|
||||
Free_afterburner_use,
|
||||
Glide_decay_requires_thrust,
|
||||
Hack_improve_non_homing_swarm_turret_fire_accuracy,
|
||||
Huge_turret_weapons_ignore_bombs,
|
||||
@@ -109,7 +110,9 @@ namespace AI {
|
||||
Smart_shield_management,
|
||||
Smart_subsystem_targeting_for_turrets,
|
||||
Strict_turred_tagged_only_targeting,
|
||||
Support_dont_add_primaries, //Prevents support ship from equipping new primary as requested in http://scp.indiegames.us/mantis/view.php?id=3198
|
||||
Turrets_ignore_target_radius,
|
||||
Use_actual_primary_range,
|
||||
Use_additive_weapon_velocity,
|
||||
Use_newtonian_dampening,
|
||||
Use_only_single_fov_for_turrets,
|
||||
|
||||
@@ -357,6 +357,8 @@ void parse_ai_profiles_tbl(const char *filename)
|
||||
|
||||
set_flag(profile, "$smart afterburner management:", AI::Profile_Flags::Smart_afterburner_management);
|
||||
|
||||
set_flag(profile, "$free afterburner use:", AI::Profile_Flags::Free_afterburner_use);
|
||||
|
||||
set_flag(profile, "$allow rapid secondary dumbfire:", AI::Profile_Flags::Allow_rapid_secondary_dumbfire);
|
||||
|
||||
set_flag(profile, "$huge turret weapons ignore bombs:", AI::Profile_Flags::Huge_turret_weapons_ignore_bombs);
|
||||
@@ -433,6 +435,8 @@ void parse_ai_profiles_tbl(const char *filename)
|
||||
|
||||
set_flag(profile, "$ai guards specific ship in wing:", AI::Profile_Flags::Ai_guards_specific_ship_in_wing);
|
||||
|
||||
set_flag(profile, "$support don't add primaries:", AI::Profile_Flags::Support_dont_add_primaries);
|
||||
|
||||
profile->ai_path_mode = AI_PATH_MODE_NORMAL;
|
||||
if (optional_string("$ai path mode:"))
|
||||
{
|
||||
@@ -458,6 +462,8 @@ void parse_ai_profiles_tbl(const char *filename)
|
||||
|
||||
set_flag(profile, "$ai can slow down when attacking big ships:", AI::Profile_Flags::Ai_can_slow_down_attacking_big_ships);
|
||||
|
||||
set_flag(profile, "$use actual primary range:", AI::Profile_Flags::Use_actual_primary_range);
|
||||
|
||||
profile->bay_arrive_speed_mult = 1.0f;
|
||||
profile->bay_depart_speed_mult = 1.0f;
|
||||
if (optional_string("$bay arrive speed multiplier:")) {
|
||||
|
||||
+20
-26
@@ -64,10 +64,11 @@ void ai_big_chase_attack(ai_info *aip, ship_info *sip, vec3d *enemy_pos, float d
|
||||
void ai_big_avoid_ship();
|
||||
int ai_big_maybe_follow_subsys_path(int do_dot_check=1);
|
||||
void ai_big_strafe_position();
|
||||
static int ai_big_strafe_maybe_retreat(const vec3d *target_pos);
|
||||
|
||||
extern int model_which_octant_distant_many( vec3d *pnt, int model_num,matrix *model_orient, vec3d * model_pos, polymodel **pm, int *octs);
|
||||
extern void compute_desired_rvec(vec3d *rvec, vec3d *goal_pos, vec3d *cur_pos);
|
||||
extern void big_ship_collide_recover_start(object *objp, object *big_objp, vec3d *collide_pos, vec3d *collision_normal);
|
||||
extern void big_ship_collide_recover_start(object *objp, object *big_objp, vec3d *collision_normal);
|
||||
|
||||
|
||||
// Called by ai_big_pick_attack_point.
|
||||
@@ -631,7 +632,7 @@ void ai_big_chase_attack(ai_info *aip, ship_info *sip, vec3d *enemy_pos, float d
|
||||
else
|
||||
rvec = NULL;
|
||||
|
||||
ai_turn_towards_vector(enemy_pos, Pl_objp, flFrametime, sip->srotation_time, NULL, rel_pos, 0.0f, 0, rvec);
|
||||
ai_turn_towards_vector(enemy_pos, Pl_objp, sip->srotation_time, nullptr, rel_pos, 0.0f, 0, rvec);
|
||||
|
||||
// calc range of primary weapon
|
||||
weapon_travel_dist = ai_get_weapon_dist(&Ships[Pl_objp->instance].weapons);
|
||||
@@ -641,7 +642,7 @@ void ai_big_chase_attack(ai_info *aip, ship_info *sip, vec3d *enemy_pos, float d
|
||||
accelerate_ship(aip, 1.0f);
|
||||
|
||||
ship *shipp = &Ships[Pl_objp->instance];
|
||||
if ((aip->ai_flags[AI::AI_Flags::Free_afterburner_use]) && !(shipp->flags[Ship::Ship_Flags::Afterburner_locked]) && (dot_to_enemy > 0.75f)) {
|
||||
if ((aip->ai_flags[AI::AI_Flags::Free_afterburner_use] || aip->ai_profile_flags[AI::Profile_Flags::Free_afterburner_use]) && !(shipp->flags[Ship::Ship_Flags::Afterburner_locked]) && (dot_to_enemy > 0.75f)) {
|
||||
if (ai_maybe_fire_afterburner(Pl_objp, aip)) {
|
||||
afterburners_start(Pl_objp);
|
||||
aip->afterburner_stop_time = Missiontime + 3*F1_0;
|
||||
@@ -683,7 +684,7 @@ void ai_big_chase_attack(ai_info *aip, ship_info *sip, vec3d *enemy_pos, float d
|
||||
accelerate_ship(aip, accel);
|
||||
|
||||
ship *shipp = &Ships[Pl_objp->instance];
|
||||
if ((aip->ai_flags[AI::AI_Flags::Free_afterburner_use]) && !(shipp->flags[Ship::Ship_Flags::Afterburner_locked]) && (accel > 0.95f)) {
|
||||
if ((aip->ai_flags[AI::AI_Flags::Free_afterburner_use] || aip->ai_profile_flags[AI::Profile_Flags::Free_afterburner_use]) && !(shipp->flags[Ship::Ship_Flags::Afterburner_locked]) && (accel > 0.95f)) {
|
||||
if (ai_maybe_fire_afterburner(Pl_objp, aip)) {
|
||||
afterburners_start(Pl_objp);
|
||||
aip->afterburner_stop_time = Missiontime + 3*F1_0;
|
||||
@@ -707,14 +708,14 @@ extern float set_secondary_fire_delay(ai_info *aip, ship *shipp, weapon_info *sw
|
||||
extern void ai_choose_secondary_weapon(object *objp, ai_info *aip, object *en_objp);
|
||||
extern int maybe_avoid_big_ship(object *objp, object *ignore_objp, ai_info *aip, vec3d *goal_point, float delta_time);
|
||||
|
||||
extern void maybe_cheat_fire_synaptic(object *objp, ai_info *aip);
|
||||
extern void maybe_cheat_fire_synaptic(object *objp);
|
||||
|
||||
// Determine if Pl_objp should fire weapons at current target, based on input parameters
|
||||
//
|
||||
// dist_to_enemy => distance (in m) to attack point on current target
|
||||
// dot_to_enemy => dot product between fvec of Pl_objp and vector from Pl_objp to attack point
|
||||
//
|
||||
void ai_big_maybe_fire_weapons(float dist_to_enemy, float dot_to_enemy, vec3d * /*firing_pos*/, vec3d * /*enemy_pos*/, vec3d * /*enemy_vel*/)
|
||||
static void ai_big_maybe_fire_weapons(float dist_to_enemy, float dot_to_enemy)
|
||||
{
|
||||
ai_info *aip;
|
||||
ship_weapon *swp;
|
||||
@@ -845,8 +846,6 @@ void ai_big_switch_to_chase_mode(ai_info *aip)
|
||||
aip->submode_start_time = Missiontime;
|
||||
}
|
||||
|
||||
extern int ai_big_strafe_maybe_retreat(float dist, vec3d *target_pos);
|
||||
|
||||
// Make object Pl_objp chase object En_objp, which is a big ship, not a small ship.
|
||||
void ai_big_chase()
|
||||
{
|
||||
@@ -859,7 +858,7 @@ void ai_big_chase()
|
||||
|
||||
Assert(aip->mode == AIM_CHASE);
|
||||
|
||||
maybe_cheat_fire_synaptic(Pl_objp, aip);
|
||||
maybe_cheat_fire_synaptic(Pl_objp);
|
||||
|
||||
ai_set_positions(Pl_objp, En_objp, aip, &player_pos, &enemy_pos);
|
||||
|
||||
@@ -882,7 +881,7 @@ void ai_big_chase()
|
||||
dot_to_enemy = vm_vec_dot(&vec_to_enemy, &Pl_objp->orient.vec.fvec);
|
||||
|
||||
if (aip->ai_flags[AI::AI_Flags::Target_collision]) {
|
||||
if ( ai_big_strafe_maybe_retreat(dist_to_enemy, &enemy_pos) ) {
|
||||
if ( ai_big_strafe_maybe_retreat(&enemy_pos) ) {
|
||||
aip->mode = AIM_STRAFE;
|
||||
aip->submode_parm0 = Missiontime; // use parm0 as time strafe mode entered (i.e. MODE start time)
|
||||
aip->submode = AIS_STRAFE_AVOID;
|
||||
@@ -1045,7 +1044,7 @@ void ai_big_chase()
|
||||
if ((dist_normal_to_enemy < ATTACK_COLLIDE_AVOID_DIST + speed_dist) || (time_to_enemy < ATTACK_COLLIDE_AVOID_TIME) ) {
|
||||
// get away, simulate crsh recovery (don't use avoid)
|
||||
// accelerate_ship(aip, -1.0f);
|
||||
big_ship_collide_recover_start(Pl_objp, En_objp, &Pl_objp->pos, NULL);
|
||||
big_ship_collide_recover_start(Pl_objp, En_objp, nullptr);
|
||||
// aip->submode = SM_AVOID;
|
||||
// aip->submode_start_time = Missiontime;
|
||||
} else if ((dist_normal_to_enemy < ATTACK_COLLIDE_SLOW_DIST) || (time_to_enemy < ATTACK_COLLIDE_SLOW_TIME) ) {
|
||||
@@ -1144,7 +1143,7 @@ void ai_big_chase()
|
||||
// TODO: investigate why ships fire (and aren't close to hitting ship) when following a path near
|
||||
// a big ship
|
||||
if (aip->mode != AIM_EVADE && aip->path_start == -1 ) {
|
||||
ai_big_maybe_fire_weapons(dist_to_enemy, dot_to_enemy, &player_pos, &predicted_enemy_pos, &En_objp->phys_info.vel);
|
||||
ai_big_maybe_fire_weapons(dist_to_enemy, dot_to_enemy);
|
||||
} else {
|
||||
if (flFrametime < 1.0f)
|
||||
aip->time_enemy_in_range *= (1.0f - flFrametime);
|
||||
@@ -1153,11 +1152,6 @@ void ai_big_chase()
|
||||
}
|
||||
}
|
||||
|
||||
void ai_big_ship(object * /*objp*/)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
// all three parms are output parameters
|
||||
// Enemy object is En_objp
|
||||
// pos => world pos of attack point
|
||||
@@ -1228,7 +1222,7 @@ void ai_big_attack_get_data(vec3d *enemy_pos, float *dist_to_enemy, float *dot_t
|
||||
|
||||
// check to see if Pl_objp has gotten too close to attacking point.. if so, break off by entering
|
||||
// AIS_STRAFE_RETREAT
|
||||
int ai_big_strafe_maybe_retreat(float /*dist*/, vec3d *target_pos)
|
||||
static int ai_big_strafe_maybe_retreat(const vec3d *target_pos)
|
||||
{
|
||||
ai_info *aip;
|
||||
aip = &Ai_info[Ships[Pl_objp->instance].ai_index];
|
||||
@@ -1258,7 +1252,7 @@ int ai_big_strafe_maybe_retreat(float /*dist*/, vec3d *target_pos)
|
||||
if (aip->ai_flags[AI::AI_Flags::Target_collision]) {
|
||||
// use standard collision resolution
|
||||
aip->ai_flags.remove(AI::AI_Flags::Target_collision);
|
||||
big_ship_collide_recover_start(Pl_objp, En_objp, &Pl_objp->pos, NULL);
|
||||
big_ship_collide_recover_start(Pl_objp, En_objp, nullptr);
|
||||
} else {
|
||||
// too close for comfort so fly to box point + 300
|
||||
aip->submode = AIS_STRAFE_RETREAT1;
|
||||
@@ -1298,12 +1292,12 @@ void ai_big_strafe_attack()
|
||||
}
|
||||
|
||||
ai_big_attack_get_data(&target_pos, &target_dist, &target_dot);
|
||||
if ( ai_big_strafe_maybe_retreat(target_dist, &target_pos) )
|
||||
if ( ai_big_strafe_maybe_retreat(&target_pos) )
|
||||
return;
|
||||
|
||||
if (aip->ai_flags[AI::AI_Flags::Kamikaze]) {
|
||||
if (target_dist < 1200.0f) {
|
||||
ai_turn_towards_vector(&target_pos, Pl_objp, flFrametime, Ship_info[Ships[Pl_objp->instance].ship_info_index].srotation_time, NULL, NULL, 0.0f, 0);
|
||||
ai_turn_towards_vector(&target_pos, Pl_objp, Ship_info[Ships[Pl_objp->instance].ship_info_index].srotation_time, nullptr, nullptr, 0.0f, 0);
|
||||
accelerate_ship(aip, 1.0f);
|
||||
if ((target_dist < 400.0f) && ai_maybe_fire_afterburner(Pl_objp, aip)) {
|
||||
afterburners_start(Pl_objp);
|
||||
@@ -1347,7 +1341,7 @@ void ai_big_strafe_attack()
|
||||
}
|
||||
|
||||
// maybe fire weapons at target
|
||||
ai_big_maybe_fire_weapons(target_dist, target_dot, &Pl_objp->pos, &En_objp->pos, &En_objp->phys_info.vel);
|
||||
ai_big_maybe_fire_weapons(target_dist, target_dot);
|
||||
turn_towards_point(Pl_objp, &target_pos, NULL, 0.0f);
|
||||
|
||||
fix last_hit = Missiontime - aip->last_hit_time;
|
||||
@@ -1493,7 +1487,7 @@ void ai_big_strafe_glide_attack()
|
||||
vm_vec_sub2(&target_pos, &En_objp->pos);
|
||||
|
||||
turn_towards_point(Pl_objp, &target_pos, NULL, 0.0f);
|
||||
ai_big_maybe_fire_weapons(target_dist, target_dot, &Pl_objp->pos, &En_objp->pos, &En_objp->phys_info.vel);
|
||||
ai_big_maybe_fire_weapons(target_dist, target_dot);
|
||||
}
|
||||
|
||||
// if haven't been hit in quite a while, leave strafe mode
|
||||
@@ -1517,7 +1511,7 @@ void ai_big_strafe_avoid()
|
||||
mode_time = Missiontime - aip->submode_start_time;
|
||||
|
||||
ai_big_attack_get_data(&target_pos, &target_dist, &target_dot);
|
||||
if ( ai_big_strafe_maybe_retreat(target_dist, &target_pos) )
|
||||
if ( ai_big_strafe_maybe_retreat(&target_pos) )
|
||||
return;
|
||||
|
||||
if ( mode_time > fl2f(0.5)) {
|
||||
@@ -1704,7 +1698,7 @@ void ai_big_strafe()
|
||||
//
|
||||
// Check if weapon_objnum was fired by Pl_objp's target, and whether Pl_objp's target is a big ship, if
|
||||
// so, enter AIM_STRAFE
|
||||
int ai_big_maybe_enter_strafe_mode(object *pl_objp, int weapon_objnum, int /*consider_target_only*/)
|
||||
int ai_big_maybe_enter_strafe_mode(const object *pl_objp, int weapon_objnum)
|
||||
{
|
||||
ai_info *aip;
|
||||
ship_info *sip;
|
||||
@@ -1778,7 +1772,7 @@ int ai_big_maybe_enter_strafe_mode(object *pl_objp, int weapon_objnum, int /*co
|
||||
// Consider attacking a turret, if a turret actually fired the weapon
|
||||
// input: ship_objp => ship that will attack the turret
|
||||
// weapon_objp =>
|
||||
void ai_big_strafe_maybe_attack_turret(object *ship_objp, object *weapon_objp)
|
||||
void ai_big_strafe_maybe_attack_turret(const object *ship_objp, const object *weapon_objp)
|
||||
{
|
||||
ai_info *aip;
|
||||
object *parent_objp;
|
||||
|
||||
+2
-3
@@ -17,14 +17,13 @@ struct ai_info;
|
||||
struct vec3d;
|
||||
class ship_subsys;
|
||||
|
||||
void ai_big_ship(object *objp);
|
||||
void ai_big_chase();
|
||||
void ai_big_subsys_path_cleanup(ai_info *aip);
|
||||
|
||||
// strafe functions
|
||||
void ai_big_strafe();
|
||||
int ai_big_maybe_enter_strafe_mode(object *objp, int weapon_objnum, int consider_target_only=0);
|
||||
void ai_big_strafe_maybe_attack_turret(object *ship_objp, object *weapon_objp);
|
||||
int ai_big_maybe_enter_strafe_mode(const object *objp, int weapon_objnum);
|
||||
void ai_big_strafe_maybe_attack_turret(const object *ship_objp, const object *weapon_objp);
|
||||
void ai_big_pick_attack_point(object *objp, object *attacker_objp, vec3d *attack_point, float fov=1.0f);
|
||||
void ai_big_pick_attack_point_turret(object *objp, ship_subsys *ssp, vec3d *gpos, vec3d *gvec, vec3d *attack_point, float weapon_travel_dist, float fov=1.0f);
|
||||
|
||||
|
||||
+79
-178
@@ -745,6 +745,8 @@ void parse_ai_class()
|
||||
|
||||
set_aic_flag(aicp, "$smart afterburner management:", AI::Profile_Flags::Smart_afterburner_management);
|
||||
|
||||
set_aic_flag(aicp, "$free afterburner use:", AI::Profile_Flags::Free_afterburner_use);
|
||||
|
||||
set_aic_flag(aicp, "$allow rapid secondary dumbfire:", AI::Profile_Flags::Allow_rapid_secondary_dumbfire);
|
||||
|
||||
set_aic_flag(aicp, "$huge turret weapons ignore bombs:", AI::Profile_Flags::Huge_turret_weapons_ignore_bombs);
|
||||
@@ -764,6 +766,8 @@ void parse_ai_class()
|
||||
set_aic_flag(aicp, "$all ships manage shields:", AI::Profile_Flags::All_ships_manage_shields);
|
||||
|
||||
set_aic_flag(aicp, "$ai can slow down when attacking big ships:", AI::Profile_Flags::Ai_can_slow_down_attacking_big_ships);
|
||||
|
||||
set_aic_flag(aicp, "$use actual primary range:", AI::Profile_Flags::Use_actual_primary_range);
|
||||
}
|
||||
|
||||
void reset_ai_class_names()
|
||||
@@ -1132,7 +1136,7 @@ void ai_update_danger_weapon(int attacked_objnum, int weapon_objnum)
|
||||
|
||||
// If rvec != NULL, use it to match bank by calling vm_matrix_interpolate.
|
||||
// (rvec defaults to NULL)
|
||||
void ai_turn_towards_vector(vec3d *dest, object *objp, float /*frametime*/, float turn_time, vec3d *slide_vec, vec3d *rel_pos, float bank_override, int flags, vec3d *rvec, int sexp_flags)
|
||||
void ai_turn_towards_vector(vec3d *dest, object *objp, float turn_time, vec3d *slide_vec, vec3d *rel_pos, float bank_override, int flags, vec3d *rvec, int sexp_flags)
|
||||
{
|
||||
matrix curr_orient;
|
||||
vec3d vel_in, vel_out, desired_fvec, src;
|
||||
@@ -1500,12 +1504,12 @@ void turn_towards_point(object *objp, vec3d *point, vec3d *slide_vec, float bank
|
||||
if (aip->ai_flags[AI::AI_Flags::Formation_object, AI::AI_Flags::Formation_wing]) {
|
||||
if (&Objects[aip->goal_objnum] != objp) {
|
||||
float rotvel_z = objp->phys_info.rotvel.xyz.z;
|
||||
ai_turn_towards_vector(point, objp, flFrametime, Ship_info[Ships[objp->instance].ship_info_index].srotation_time, slide_vec, NULL, bank_override, 0);
|
||||
ai_turn_towards_vector(point, objp, Ship_info[Ships[objp->instance].ship_info_index].srotation_time, slide_vec, nullptr, bank_override, 0);
|
||||
objp->phys_info.rotvel.xyz.z = rotvel_z;
|
||||
}
|
||||
} else {
|
||||
// normal turn
|
||||
ai_turn_towards_vector(point, objp, flFrametime, Ship_info[Ships[objp->instance].ship_info_index].srotation_time, slide_vec, NULL, bank_override, 0);
|
||||
ai_turn_towards_vector(point, objp, Ship_info[Ships[objp->instance].ship_info_index].srotation_time, slide_vec, nullptr, bank_override, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1520,7 +1524,7 @@ void turn_away_from_point(object *objp, vec3d *point, float bank_override)
|
||||
vm_vec_sub(&opposite_point, &objp->pos, point);
|
||||
vm_vec_add2(&opposite_point, &objp->pos);
|
||||
|
||||
ai_turn_towards_vector(&opposite_point, objp, flFrametime, Ship_info[Ships[objp->instance].ship_info_index].srotation_time, NULL, NULL, bank_override, AITTV_FAST);
|
||||
ai_turn_towards_vector(&opposite_point, objp, Ship_info[Ships[objp->instance].ship_info_index].srotation_time, nullptr, nullptr, bank_override, AITTV_FAST);
|
||||
}
|
||||
|
||||
|
||||
@@ -1789,7 +1793,7 @@ float get_wing_lowest_av_ab_speed(object *objp)
|
||||
|
||||
wingnum = aip->wing;
|
||||
|
||||
if (((shipp->flags[Ship::Ship_Flags::Afterburner_locked]) || !(sip->flags[Ship::Info_Flags::Afterburner])) || (shipp->current_max_speed < 5.0f) || (objp->phys_info.afterburner_max_vel.xyz.z <= shipp->current_max_speed) || !(aip->ai_flags[AI::AI_Flags::Free_afterburner_use])) {
|
||||
if (((shipp->flags[Ship::Ship_Flags::Afterburner_locked]) || !(sip->flags[Ship::Info_Flags::Afterburner])) || (shipp->current_max_speed < 5.0f) || (objp->phys_info.afterburner_max_vel.xyz.z <= shipp->current_max_speed) || !(aip->ai_flags[AI::AI_Flags::Free_afterburner_use] || aip->ai_profile_flags[AI::Profile_Flags::Free_afterburner_use])) {
|
||||
lowest_max_av_ab_speed = shipp->current_max_speed;
|
||||
}
|
||||
else
|
||||
@@ -1814,7 +1818,7 @@ float get_wing_lowest_av_ab_speed(object *objp)
|
||||
if ((oaip->mode == AIM_WAYPOINTS) && (oaip->wing == wingnum) && (oaip->ai_flags[AI::AI_Flags::Formation_object, AI::AI_Flags::Formation_wing])) {
|
||||
|
||||
float cur_max;
|
||||
if ((oshipp->flags[Ship::Ship_Flags::Afterburner_locked]) || !(osip->flags[Ship::Info_Flags::Afterburner]) || (o->phys_info.afterburner_max_vel.xyz.z <= oshipp->current_max_speed) || !(oaip->ai_flags[AI::AI_Flags::Free_afterburner_use])) {
|
||||
if ((oshipp->flags[Ship::Ship_Flags::Afterburner_locked]) || !(osip->flags[Ship::Info_Flags::Afterburner]) || (o->phys_info.afterburner_max_vel.xyz.z <= oshipp->current_max_speed) || !(oaip->ai_flags[AI::AI_Flags::Free_afterburner_use] || oaip->ai_profile_flags[AI::Profile_Flags::Free_afterburner_use])) {
|
||||
cur_max = oshipp->current_max_speed;
|
||||
}
|
||||
else
|
||||
@@ -3448,35 +3452,6 @@ float compute_time_to_enemy(float dist_to_enemy, object *pobjp)
|
||||
return time_to_enemy + flFrametime;
|
||||
}
|
||||
|
||||
// Stuff *dot and *tts.
|
||||
// *dot is always computed. If dot is less than zero, the magnitude is
|
||||
// incorrect, not having been divided by distance.
|
||||
// If *dot is > 0.0f, then tts is computed. This is the time it will take object
|
||||
// *objp to get to *pos, assuming it moves right at it.
|
||||
void fds_aux(float *dot, float *tts, vec3d *pos, float /*dtime*/, object *objp)
|
||||
{
|
||||
vec3d v2s;
|
||||
|
||||
vm_vec_sub(&v2s, pos, &objp->pos);
|
||||
*dot = vm_vec_dot(&v2s, &objp->orient.vec.fvec);
|
||||
|
||||
if (*dot > 0.0f) {
|
||||
float dist;
|
||||
|
||||
dist = vm_vec_dist(&objp->pos, pos);
|
||||
|
||||
if (dist > 0.1f)
|
||||
*dot /= dist;
|
||||
else
|
||||
*dot = 1.0f;
|
||||
|
||||
if (objp->phys_info.speed > 0.1f)
|
||||
*tts = dist / objp->phys_info.speed;
|
||||
else
|
||||
*tts = dist * 100.0f;
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
void ai_set_positions(object *pl_objp, object *en_objp, ai_info *aip, vec3d *player_pos, vec3d *enemy_pos)
|
||||
{
|
||||
@@ -3892,7 +3867,7 @@ float ai_path_0()
|
||||
}
|
||||
|
||||
if (dist_to_goal > 0.1f)
|
||||
ai_turn_towards_vector(&gcvp, Pl_objp, flFrametime, sip->srotation_time, slop_vec, NULL, 0.0f, 0);
|
||||
ai_turn_towards_vector(&gcvp, Pl_objp, sip->srotation_time, slop_vec, nullptr, 0.0f, 0);
|
||||
|
||||
// Code to control speed is MUCH less forgiving in path following than in waypoint
|
||||
// following. Must be very close to path or might hit objects.
|
||||
@@ -4034,10 +4009,10 @@ float ai_path_1()
|
||||
if (r <= 1.0f) {
|
||||
vec3d midpoint;
|
||||
vm_vec_avg3(&midpoint, &gcvp, &closest_point, &closest_point);
|
||||
ai_turn_towards_vector(&midpoint, Pl_objp, flFrametime, sip->srotation_time, NULL, NULL, 0.0f, 0, prvec);
|
||||
ai_turn_towards_vector(&midpoint, Pl_objp, sip->srotation_time, nullptr, nullptr, 0.0f, 0, prvec);
|
||||
}
|
||||
else {
|
||||
ai_turn_towards_vector(&gcvp, Pl_objp, flFrametime, sip->srotation_time, NULL, NULL, 0.0f, 0, prvec);
|
||||
ai_turn_towards_vector(&gcvp, Pl_objp, sip->srotation_time, nullptr, nullptr, 0.0f, 0, prvec);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4382,11 +4357,11 @@ void ai_fly_to_target_position(vec3d* target_pos, bool* pl_done_p=NULL, bool* pl
|
||||
vm_vector_2_matrix(&Pl_objp->orient, &perp, NULL, NULL);
|
||||
} else {
|
||||
vm_vec_scale_add(&perp, &Pl_objp->pos, &Autopilot_flight_leader->phys_info.vel, 1000.0f);
|
||||
ai_turn_towards_vector(&perp, Pl_objp, flFrametime, sip->srotation_time*3.0f*scale, slop_vec, NULL, 0.0f, 0);
|
||||
ai_turn_towards_vector(&perp, Pl_objp, sip->srotation_time*3.0f*scale, slop_vec, nullptr, 0.0f, 0);
|
||||
}
|
||||
} else {
|
||||
if (dist_to_goal > 0.1f) {
|
||||
ai_turn_towards_vector(target_pos, Pl_objp, flFrametime, sip->srotation_time*3.0f*scale, slop_vec, NULL, 0.0f, 0);
|
||||
ai_turn_towards_vector(target_pos, Pl_objp, sip->srotation_time*3.0f*scale, slop_vec, nullptr, 0.0f, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4440,7 +4415,7 @@ void ai_fly_to_target_position(vec3d* target_pos, bool* pl_done_p=NULL, bool* pl
|
||||
ab_allowed = false;
|
||||
}
|
||||
|
||||
if (!(sip->flags[Ship::Info_Flags::Afterburner]) || (shipp->flags[Ship::Ship_Flags::Afterburner_locked]) || !(aip->ai_flags[AI::AI_Flags::Free_afterburner_use])) {
|
||||
if (!(sip->flags[Ship::Info_Flags::Afterburner]) || (shipp->flags[Ship::Ship_Flags::Afterburner_locked]) || !(aip->ai_flags[AI::AI_Flags::Free_afterburner_use] || aip->ai_profile_flags[AI::Profile_Flags::Free_afterburner_use])) {
|
||||
ab_allowed = false;
|
||||
}
|
||||
|
||||
@@ -5051,7 +5026,7 @@ void slide_face_ship()
|
||||
|
||||
dist = vm_vec_normalized_dir(&vec_from_enemy, &Pl_objp->pos, &En_objp->pos);
|
||||
|
||||
ai_turn_towards_vector(&En_objp->pos, Pl_objp, flFrametime, sip->srotation_time, NULL, NULL, 0.0f, 0);
|
||||
ai_turn_towards_vector(&En_objp->pos, Pl_objp, sip->srotation_time, nullptr, nullptr, 0.0f, 0);
|
||||
|
||||
dot_from_enemy = vm_vec_dot(&vec_from_enemy, &En_objp->orient.vec.fvec);
|
||||
|
||||
@@ -5234,7 +5209,7 @@ vec3d G_predicted_pos, G_fire_pos;
|
||||
// Else
|
||||
// Select Any ol' weapon.
|
||||
// Returns primary_bank index.
|
||||
int ai_select_primary_weapon_OLD(object *objp, object * /*other_objp*/, Weapon::Info_Flags flags)
|
||||
static int ai_select_primary_weapon_OLD(const object *objp, Weapon::Info_Flags flags)
|
||||
{
|
||||
ship *shipp = &Ships[objp->instance];
|
||||
ship_weapon *swp = &shipp->weapons;
|
||||
@@ -5325,7 +5300,7 @@ int ai_select_primary_weapon(object *objp, object *other_objp, Weapon::Info_Flag
|
||||
//not using the new AI, use the old version of this function instead.
|
||||
if (!(Ai_info[shipp->ai_index].ai_profile_flags[AI::Profile_Flags::Smart_primary_weapon_selection]))
|
||||
{
|
||||
return ai_select_primary_weapon_OLD(objp, other_objp, flags);
|
||||
return ai_select_primary_weapon_OLD(objp, flags);
|
||||
}
|
||||
|
||||
Assert( shipp->ship_info_index >= 0 && shipp->ship_info_index < static_cast<int>(Ship_info.size()));
|
||||
@@ -6051,8 +6026,7 @@ int check_ok_to_fire(int objnum, int target_objnum, weapon_info *wip)
|
||||
// --------------------------------------------------------------------------
|
||||
// Fire a secondary weapon.
|
||||
// Maybe choose to fire a different one.
|
||||
// priority1 and priority2 are optional parameters with defaults = -1
|
||||
int ai_fire_secondary_weapon(object *objp, int /*priority1*/, int /*priority2*/)
|
||||
int ai_fire_secondary_weapon(object *objp)
|
||||
{
|
||||
ship_weapon *swp;
|
||||
ship *shipp;
|
||||
@@ -6072,7 +6046,7 @@ int ai_fire_secondary_weapon(object *objp, int /*priority1*/, int /*priority2*
|
||||
Assert( shipp->ship_info_index >= 0 && shipp->ship_info_index < static_cast<int>(Ship_info.size()));
|
||||
|
||||
// Select secondary weapon.
|
||||
current_bank = swp->current_secondary_bank; //ai_select_secondary_weapon(objp, swp, priority1, priority2);
|
||||
current_bank = swp->current_secondary_bank;
|
||||
|
||||
if (current_bank == -1) {
|
||||
return rval;
|
||||
@@ -6539,14 +6513,14 @@ void ai_chase_ct()
|
||||
vm_vec_add2(&tvec, &Pl_objp->orient.vec.rvec);
|
||||
}
|
||||
|
||||
ai_turn_towards_vector(&tvec, Pl_objp, flFrametime, sip->srotation_time, NULL, NULL, 0.0f, 0);
|
||||
ai_turn_towards_vector(&tvec, Pl_objp, sip->srotation_time, nullptr, nullptr, 0.0f, 0);
|
||||
accelerate_ship(aip, 1.0f);
|
||||
}
|
||||
|
||||
/**
|
||||
* ATTACK submode handler for chase mode.
|
||||
*/
|
||||
void ai_chase_eb(ai_info *aip, ship_info *sip, vec3d *predicted_enemy_pos, float /*dist_to_enemy*/)
|
||||
static void ai_chase_eb(ai_info *aip, ship_info *sip, vec3d *predicted_enemy_pos)
|
||||
{
|
||||
vec3d _pep;
|
||||
float dot_to_enemy, dot_from_enemy;
|
||||
@@ -6558,7 +6532,7 @@ void ai_chase_eb(ai_info *aip, ship_info *sip, vec3d *predicted_enemy_pos, float
|
||||
if ((dot_to_enemy > dot_from_enemy + 0.1f) || (dot_to_enemy > 0.9f))
|
||||
vm_vec_scale_add(&_pep, &Pl_objp->pos, &En_objp->orient.vec.fvec, 100.0f);
|
||||
|
||||
ai_turn_towards_vector(&_pep, Pl_objp, flFrametime, sip->srotation_time, NULL, NULL, 0.0f, 0);
|
||||
ai_turn_towards_vector(&_pep, Pl_objp, sip->srotation_time, nullptr, nullptr, 0.0f, 0);
|
||||
|
||||
accelerate_ship(aip, 0.0f);
|
||||
}
|
||||
@@ -6755,7 +6729,7 @@ void attack_set_accel(ai_info *aip, ship_info *sip, float dist_to_enemy, float d
|
||||
|
||||
// Pl_objp (aip) tries to get behind En_objp.
|
||||
// New on 2/21/98: If this ship can move backwards and slide, maybe do that to get behind.
|
||||
void get_behind_ship(ai_info *aip, ship_info *sip, float /*dist_to_enemy*/)
|
||||
static void get_behind_ship(ai_info *aip, ship_info *sip)
|
||||
{
|
||||
vec3d new_pos;
|
||||
float dot;
|
||||
@@ -6764,7 +6738,7 @@ void get_behind_ship(ai_info *aip, ship_info *sip, float /*dist_to_enemy*/)
|
||||
vm_vec_normalized_dir(&vec_from_enemy, &Pl_objp->pos, &En_objp->pos);
|
||||
|
||||
vm_vec_scale_add(&new_pos, &En_objp->pos, &En_objp->orient.vec.fvec, -100.0f); // Pick point 100 units behind.
|
||||
ai_turn_towards_vector(&new_pos, Pl_objp, flFrametime, sip->srotation_time, NULL, NULL, 0.0f, 0);
|
||||
ai_turn_towards_vector(&new_pos, Pl_objp, sip->srotation_time, nullptr, nullptr, 0.0f, 0);
|
||||
|
||||
dot = vm_vec_dot(&vec_from_enemy, &En_objp->orient.vec.fvec);
|
||||
|
||||
@@ -6783,7 +6757,7 @@ int avoid_player(object *objp, vec3d *goal_pos)
|
||||
if (aip->ai_flags[AI::AI_Flags::Avoiding_small_ship]) {
|
||||
ship_info *sip = &Ship_info[Ships[objp->instance].ship_info_index];
|
||||
|
||||
ai_turn_towards_vector(&aip->avoid_goal_point, objp, flFrametime, sip->srotation_time, NULL, NULL, 0.0f, 0);
|
||||
ai_turn_towards_vector(&aip->avoid_goal_point, objp, sip->srotation_time, nullptr, nullptr, 0.0f, 0);
|
||||
accelerate_ship(aip, 0.5f);
|
||||
return 1;
|
||||
}
|
||||
@@ -6981,7 +6955,7 @@ int maybe_avoid_big_ship(object *objp, object *ignore_objp, ai_info *aip, vec3d
|
||||
|
||||
vec3d v2g;
|
||||
|
||||
ai_turn_towards_vector(&aip->avoid_goal_point, Pl_objp, flFrametime, sip->srotation_time, NULL, NULL, 0.0f, 0);
|
||||
ai_turn_towards_vector(&aip->avoid_goal_point, Pl_objp, sip->srotation_time, nullptr, nullptr, 0.0f, 0);
|
||||
vm_vec_normalized_dir(&v2g, &aip->avoid_goal_point, &Pl_objp->pos);
|
||||
float dot = vm_vec_dot(&objp->orient.vec.fvec, &v2g);
|
||||
float d2 = (1.0f + dot) * (1.0f + dot);
|
||||
@@ -7073,7 +7047,7 @@ void ai_stealth_find()
|
||||
}
|
||||
}
|
||||
|
||||
ai_turn_towards_vector(&new_pos, Pl_objp, flFrametime, sip->srotation_time, NULL, NULL, 0.0f, 0);
|
||||
ai_turn_towards_vector(&new_pos, Pl_objp, sip->srotation_time, nullptr, nullptr, 0.0f, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -7083,9 +7057,9 @@ void ai_stealth_find()
|
||||
if (dist_to_enemy > 500.0f) {
|
||||
vec3d rvec;
|
||||
compute_desired_rvec(&rvec, &new_pos, &Pl_objp->pos);
|
||||
ai_turn_towards_vector(&new_pos, Pl_objp, flFrametime, sip->srotation_time, NULL, NULL, 0.0f, 0, &rvec);
|
||||
ai_turn_towards_vector(&new_pos, Pl_objp, sip->srotation_time, nullptr, nullptr, 0.0f, 0, &rvec);
|
||||
} else {
|
||||
ai_turn_towards_vector(&new_pos, Pl_objp, flFrametime, sip->srotation_time, NULL, NULL, 0.0f, 0);
|
||||
ai_turn_towards_vector(&new_pos, Pl_objp, sip->srotation_time, nullptr, nullptr, 0.0f, 0);
|
||||
}
|
||||
|
||||
dot_from_enemy = -vm_vec_dot(&vec_to_enemy, &En_objp->orient.vec.fvec);
|
||||
@@ -7213,7 +7187,7 @@ void ai_stealth_sweep()
|
||||
return;
|
||||
}
|
||||
|
||||
ai_turn_towards_vector(&goal_pt, Pl_objp, flFrametime, sip->srotation_time, NULL, NULL, 0.0f, 0);
|
||||
ai_turn_towards_vector(&goal_pt, Pl_objp, sip->srotation_time, nullptr, nullptr, 0.0f, 0);
|
||||
|
||||
float dot = 1.0f;
|
||||
if (dist_to_goal < 100) {
|
||||
@@ -7273,9 +7247,9 @@ void ai_chase_attack(ai_info *aip, ship_info *sip, vec3d *predicted_enemy_pos, f
|
||||
if (dist_to_enemy > 500.0f) {
|
||||
vec3d rvec;
|
||||
compute_desired_rvec(&rvec, predicted_enemy_pos, &Pl_objp->pos);
|
||||
ai_turn_towards_vector(&new_pos, Pl_objp, flFrametime, sip->srotation_time, NULL, rel_pos, bank_override, 0, &rvec);
|
||||
ai_turn_towards_vector(&new_pos, Pl_objp, sip->srotation_time, nullptr, rel_pos, bank_override, 0, &rvec);
|
||||
} else {
|
||||
ai_turn_towards_vector(&new_pos, Pl_objp, flFrametime, sip->srotation_time, NULL, rel_pos, bank_override, 0);
|
||||
ai_turn_towards_vector(&new_pos, Pl_objp, sip->srotation_time, nullptr, rel_pos, bank_override, 0);
|
||||
}
|
||||
|
||||
attack_set_accel(aip, sip, dist_to_enemy, dot_to_enemy, dot_from_enemy);
|
||||
@@ -7313,7 +7287,7 @@ void ai_chase_es(ai_info *aip, ship_info *sip)
|
||||
|
||||
float bank_override = Pl_objp->phys_info.speed;
|
||||
|
||||
ai_turn_towards_vector(&tvec, Pl_objp, flFrametime/2, sip->srotation_time, NULL, NULL, bank_override, 0);
|
||||
ai_turn_towards_vector(&tvec, Pl_objp, sip->srotation_time, nullptr, nullptr, bank_override, 0);
|
||||
accelerate_ship(aip, 1.0f);
|
||||
}
|
||||
|
||||
@@ -7339,7 +7313,7 @@ void ai_chase_ga(ai_info *aip, ship_info *sip)
|
||||
|
||||
bank_override = Pl_objp->phys_info.speed;
|
||||
|
||||
ai_turn_towards_vector(&tvec, Pl_objp, flFrametime/2, sip->srotation_time, NULL, NULL, bank_override, 0);
|
||||
ai_turn_towards_vector(&tvec, Pl_objp, sip->srotation_time, nullptr, nullptr, bank_override, 0);
|
||||
|
||||
accelerate_ship(aip, 2.0f);
|
||||
|
||||
@@ -7504,32 +7478,6 @@ void ai_set_guard_wing(object *objp, int wingnum)
|
||||
}
|
||||
}
|
||||
|
||||
// Make object *objp guard object *other_objp.
|
||||
// To be called from the goals code.
|
||||
void ai_set_evade_object(object *objp, object *other_objp)
|
||||
{
|
||||
ship *shipp;
|
||||
ai_info *aip;
|
||||
int other_objnum;
|
||||
|
||||
Assert(objp->type == OBJ_SHIP);
|
||||
Assert(objp->instance >= 0);
|
||||
|
||||
shipp = &Ships[objp->instance];
|
||||
|
||||
Assert(shipp->ai_index >= 0);
|
||||
|
||||
aip = &Ai_info[shipp->ai_index];
|
||||
|
||||
other_objnum = OBJ_INDEX(other_objp);
|
||||
Assert(other_objnum >= 0);
|
||||
|
||||
Assert(other_objnum != Ships[aip->shipnum].objnum); // make sure not targeting self
|
||||
aip->target_objnum = other_objnum;
|
||||
|
||||
aip->mode = AIM_EVADE;
|
||||
}
|
||||
|
||||
// Make objp guard other_objp
|
||||
// If other_objp is a member of a wing, objp will guard that whole wing
|
||||
// UNLESS objp is also a member of the wing!
|
||||
@@ -8001,7 +7949,7 @@ void ai_cruiser_chase()
|
||||
|
||||
// kamikaze - ram and explode
|
||||
if (aip->ai_flags[AI::AI_Flags::Kamikaze]) {
|
||||
ai_turn_towards_vector(&En_objp->pos, Pl_objp, flFrametime, turn_time, NULL, NULL, 0.0f, 0);
|
||||
ai_turn_towards_vector(&En_objp->pos, Pl_objp, turn_time, nullptr, nullptr, 0.0f, 0);
|
||||
accelerate_ship(aip, 1.0f);
|
||||
}
|
||||
|
||||
@@ -8041,7 +7989,7 @@ void ai_cruiser_chase()
|
||||
}
|
||||
|
||||
// now move as desired
|
||||
ai_turn_towards_vector(&goal_pos, Pl_objp, flFrametime, turn_time, NULL, NULL, 0.0f, 0, rvecp);
|
||||
ai_turn_towards_vector(&goal_pos, Pl_objp, turn_time, nullptr, nullptr, 0.0f, 0, rvecp);
|
||||
accelerate_ship(aip, accel);
|
||||
|
||||
// maybe switch to new mode
|
||||
@@ -8322,7 +8270,7 @@ void ai_chase()
|
||||
break;
|
||||
|
||||
case SM_EVADE_BRAKE:
|
||||
ai_chase_eb(aip, sip, &predicted_enemy_pos, dist_to_enemy);
|
||||
ai_chase_eb(aip, sip, &predicted_enemy_pos);
|
||||
break;
|
||||
|
||||
case SM_EVADE:
|
||||
@@ -8334,7 +8282,7 @@ void ai_chase()
|
||||
break;
|
||||
|
||||
case SM_GET_BEHIND:
|
||||
get_behind_ship(aip, sip, dist_to_enemy);
|
||||
get_behind_ship(aip, sip);
|
||||
break;
|
||||
|
||||
case SM_GET_AWAY: // Used to get away from opponent to prevent endless circling.
|
||||
@@ -8768,7 +8716,11 @@ void ai_chase()
|
||||
scale = (scale - 0.6f) * 1.5f;
|
||||
else
|
||||
scale = 0.0f;
|
||||
if (dist_to_enemy < pwip->max_speed * (1.0f + scale)) {
|
||||
float range = pwip->max_speed * (1.0f + scale);
|
||||
if (aip->ai_profile_flags[AI::Profile_Flags::Use_actual_primary_range]) {
|
||||
range = std::min( {range, pwip->max_speed * pwip->lifetime, pwip->weapon_range} );
|
||||
}
|
||||
if (dist_to_enemy < range) {
|
||||
if(ai_fire_primary_weapon(Pl_objp) == 1){
|
||||
has_fired = 1;
|
||||
}else{
|
||||
@@ -9329,7 +9281,7 @@ float dock_orient_and_approach(object *docker_objp, int docker_index, object *do
|
||||
{
|
||||
float dot, accel;
|
||||
float turn_time = Ship_info[Ships[docker_objp->instance].ship_info_index].srotation_time;
|
||||
ai_turn_towards_vector(&goal_point, docker_objp, flFrametime, turn_time, NULL, NULL, 0.0f, 0);
|
||||
ai_turn_towards_vector(&goal_point, docker_objp, turn_time, nullptr, nullptr, 0.0f, 0);
|
||||
|
||||
dot = vm_vec_dot(&docker_objp->orient.vec.fvec, &away_vec);
|
||||
accel = 0.1f;
|
||||
@@ -9964,10 +9916,10 @@ void ai_big_guard()
|
||||
}
|
||||
|
||||
// got the point, now let's go there
|
||||
ai_turn_towards_vector(&goal_pt, Pl_objp, flFrametime, Ship_info[Ships[Pl_objp->instance].ship_info_index].srotation_time, NULL, NULL, 0.0f, 0);
|
||||
ai_turn_towards_vector(&goal_pt, Pl_objp, Ship_info[Ships[Pl_objp->instance].ship_info_index].srotation_time, nullptr, nullptr, 0.0f, 0);
|
||||
accelerate_ship(aip, 1.0f);
|
||||
|
||||
if ((aip->ai_flags[AI::AI_Flags::Free_afterburner_use]) && !(shipp->flags[Ship::Ship_Flags::Afterburner_locked]) && (cur_guard_rad > 1.1f * max_guard_dist)) {
|
||||
if ((aip->ai_flags[AI::AI_Flags::Free_afterburner_use] || aip->ai_profile_flags[AI::Profile_Flags::Free_afterburner_use]) && !(shipp->flags[Ship::Ship_Flags::Afterburner_locked]) && (cur_guard_rad > 1.1f * max_guard_dist)) {
|
||||
vec3d v2g;
|
||||
float dot_to_goal_point;
|
||||
|
||||
@@ -10088,9 +10040,9 @@ void ai_guard()
|
||||
|
||||
// quite far away, so try to go straight to
|
||||
compute_desired_rvec(&rvec, &goal_point, &Pl_objp->pos);
|
||||
ai_turn_towards_vector(&goal_point, Pl_objp, flFrametime, Ship_info[shipp->ship_info_index].srotation_time, NULL, NULL, 0.0f, 0, &rvec);
|
||||
ai_turn_towards_vector(&goal_point, Pl_objp, Ship_info[shipp->ship_info_index].srotation_time, nullptr, nullptr, 0.0f, 0, &rvec);
|
||||
|
||||
if ((aip->ai_flags[AI::AI_Flags::Free_afterburner_use]) && !(shipp->flags[Ship::Ship_Flags::Afterburner_locked]) && (accel_scale * (0.25f + dist_to_goal_point/700.0f) > 0.8f)) {
|
||||
if ((aip->ai_flags[AI::AI_Flags::Free_afterburner_use] || aip->ai_profile_flags[AI::Profile_Flags::Free_afterburner_use]) && !(shipp->flags[Ship::Ship_Flags::Afterburner_locked]) && (accel_scale * (0.25f + dist_to_goal_point/700.0f) > 0.8f)) {
|
||||
if (ai_maybe_fire_afterburner(Pl_objp, aip)) {
|
||||
afterburners_start(Pl_objp);
|
||||
aip->afterburner_stop_time = Missiontime + 3*F1_0;
|
||||
@@ -10713,8 +10665,8 @@ void ai_dock()
|
||||
char *goal_ship_class_name = goal_sip->name;
|
||||
char *goal_dock_path_name = model_get(goal_sip->model_num)->paths[aip->mp_index].name;
|
||||
|
||||
Warning(LOCATION, "Ship class %s has only %i points on dock path \"%s\". Recommended minimum number of points is 4. "\
|
||||
"Docking along that path will look strange. You may wish to edit the model.", goal_ship_class_name, aip->path_length, goal_dock_path_name);
|
||||
mprintf(("Ship class %s has only %i points on dock path \"%s\". Recommended minimum number of points is 4. "\
|
||||
"Docking along that path will look strange. You may wish to edit the model.", goal_ship_class_name, aip->path_length, goal_dock_path_name));
|
||||
}
|
||||
|
||||
aip->submode = AIS_DOCK_1;
|
||||
@@ -11385,7 +11337,7 @@ float gwlr_1(object *objp, ai_info *aip)
|
||||
/**
|
||||
* Compute the largest radius of a ship forming on *objp's wing.
|
||||
*/
|
||||
float gwlr_object_1(object *objp, ai_info * /*aip*/)
|
||||
static float gwlr_object_1(object *objp)
|
||||
{
|
||||
float max_radius;
|
||||
object *o;
|
||||
@@ -11418,7 +11370,7 @@ float get_wing_largest_radius(object *objp, int formation_object_flag)
|
||||
aip = &Ai_info[shipp->ai_index];
|
||||
|
||||
if (formation_object_flag) {
|
||||
return gwlr_object_1(objp, aip);
|
||||
return gwlr_object_1(objp);
|
||||
} else {
|
||||
return gwlr_1(objp, aip);
|
||||
}
|
||||
@@ -11560,53 +11512,6 @@ void render_wing_phantoms_all()
|
||||
|
||||
#endif
|
||||
|
||||
// Hook from goals code to AI.
|
||||
// Force a wing to fly in formation.
|
||||
// Sets AIF_FORMATION bit in ai_flags.
|
||||
// wingnum Wing to force to fly in formation
|
||||
void ai_fly_in_formation(int wingnum)
|
||||
{
|
||||
object *objp;
|
||||
ship *shipp;
|
||||
ship_obj *so;
|
||||
|
||||
for ( so = GET_FIRST(&Ship_obj_list); so != END_OF_LIST(&Ship_obj_list); so = GET_NEXT(so) ) {
|
||||
objp = &Objects[so->objnum];
|
||||
Assert((objp->instance >= 0) && (objp->instance < MAX_SHIPS));
|
||||
|
||||
shipp = &Ships[objp->instance];
|
||||
Assert((shipp->ai_index >= 0) && (shipp->ai_index < MAX_AI_INFO));
|
||||
|
||||
if (Ai_info[shipp->ai_index].wing == wingnum) {
|
||||
Ai_info[shipp->ai_index].ai_flags.set(AI::AI_Flags::Formation_wing);
|
||||
Ai_info[shipp->ai_index].ai_flags.remove(AI::AI_Flags::Formation_object);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Hook from goals code to AI.
|
||||
// Force a wing to abandon formation flying.
|
||||
// Clears AIF_FORMATION bit in ai_flags.
|
||||
// wingnum Wing to force to fly in formation
|
||||
void ai_disband_formation(int wingnum)
|
||||
{
|
||||
object *objp;
|
||||
ship *shipp;
|
||||
ship_obj *so;
|
||||
|
||||
for ( so = GET_FIRST(&Ship_obj_list); so != END_OF_LIST(&Ship_obj_list); so = GET_NEXT(so) ) {
|
||||
objp = &Objects[so->objnum];
|
||||
Assert((objp->instance >= 0) && (objp->instance < MAX_SHIPS));
|
||||
|
||||
shipp = &Ships[objp->instance];
|
||||
Assert((shipp->ai_index >= 0) && (shipp->ai_index < MAX_AI_INFO));
|
||||
|
||||
if (Ai_info[shipp->ai_index].wing == wingnum) {
|
||||
Ai_info[shipp->ai_index].ai_flags.remove(AI::AI_Flags::Formation_wing);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float Leader_chaos = 0.0f;
|
||||
int Chaos_frame = -1;
|
||||
|
||||
@@ -11808,7 +11713,7 @@ int ai_formation()
|
||||
|
||||
ship_info *sip = &Ship_info[shipp->ship_info_index];
|
||||
bool ab_allowed = false;
|
||||
if ((sip->flags[Ship::Info_Flags::Afterburner]) && !(shipp->flags[Ship::Ship_Flags::Afterburner_locked]) && (aip->ai_flags[AI::AI_Flags::Free_afterburner_use])) {
|
||||
if ((sip->flags[Ship::Info_Flags::Afterburner]) && !(shipp->flags[Ship::Ship_Flags::Afterburner_locked]) && (aip->ai_flags[AI::AI_Flags::Free_afterburner_use] || aip->ai_profile_flags[AI::Profile_Flags::Free_afterburner_use])) {
|
||||
ab_allowed = true;
|
||||
} else {
|
||||
if (Pl_objp->phys_info.flags & PF_AFTERBURNER_ON)
|
||||
@@ -12191,7 +12096,7 @@ void ai_maybe_launch_cmeasure(object *objp, ai_info *aip)
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
void ai_preprocess_ignore_objnum(object * /*objp*/, ai_info *aip)
|
||||
static void ai_preprocess_ignore_objnum(ai_info *aip)
|
||||
{
|
||||
if (aip->ai_flags[AI::AI_Flags::Temporary_ignore])
|
||||
{
|
||||
@@ -13064,7 +12969,6 @@ void ai_execute_behavior(ai_info *aip)
|
||||
case AIM_NONE:
|
||||
break;
|
||||
case AIM_BIGSHIP:
|
||||
ai_big_ship(Pl_objp);
|
||||
break;
|
||||
case AIM_PATH: {
|
||||
int path_num;
|
||||
@@ -13382,7 +13286,7 @@ void ai_warp_out(object *objp)
|
||||
case AIS_WARP_2: // Make sure won't collide with any object.
|
||||
if (timestamp_elapsed(aip->force_warp_time)
|
||||
|| (!collide_predict_large_ship(objp, objp->radius*2.0f + 100.0f)
|
||||
|| (Ship_info[shipp->ship_info_index].warpout_type == WT_HYPERSPACE
|
||||
|| (Warp_params[shipp->warpout_params_index].warp_type == WT_HYPERSPACE
|
||||
&& !collide_predict_large_ship(objp, 100000.0f)))) {
|
||||
aip->submode = AIS_WARP_3;
|
||||
aip->submode_start_time = Missiontime;
|
||||
@@ -13425,7 +13329,7 @@ void ai_warp_out(object *objp)
|
||||
break;
|
||||
case AIS_WARP_4: {
|
||||
// Only lets the ship warp after waiting for the warpout engage time
|
||||
if ( (Missiontime / 100) >= (aip->submode_start_time / 100 + Ship_info[shipp->ship_info_index].warpout_engage_time) ) {
|
||||
if ( (Missiontime / 100) >= (aip->submode_start_time / 100 + Warp_params[shipp->warpout_params_index].warpout_engage_time) ) {
|
||||
shipfx_warpout_start(objp);
|
||||
aip->submode = AIS_WARP_5;
|
||||
aip->submode_start_time = Missiontime;
|
||||
@@ -13441,7 +13345,7 @@ void ai_warp_out(object *objp)
|
||||
|
||||
// Return object index of weapon that could produce a shockwave that should be known about to *objp.
|
||||
// Return nearest one.
|
||||
int ai_find_shockwave_weapon(object *objp, ai_info * /*aip*/)
|
||||
static int ai_find_shockwave_weapon(const object *objp)
|
||||
{
|
||||
missile_obj *mo;
|
||||
float nearest_dist = 999999.9f;
|
||||
@@ -13507,7 +13411,7 @@ void ai_announce_ship_dying(object *dying_objp)
|
||||
|
||||
// Return object index of weapon that could produce a shockwave that should be known about to *objp.
|
||||
// Return nearest one.
|
||||
int ai_find_shockwave_ship(object *objp, ai_info * /*aip*/)
|
||||
static int ai_find_shockwave_ship(object *objp)
|
||||
{
|
||||
ship_obj *so;
|
||||
float nearest_dist = 999999.9f;
|
||||
@@ -13550,7 +13454,7 @@ int aas_1(object *objp, ai_info *aip, vec3d *safe_pos)
|
||||
// If we don't currently know of a weapon to avoid, try to find one.
|
||||
// If we can't find one, then clear the bit so we don't keep coming here.
|
||||
if (aip->shockwave_object == -1) {
|
||||
int shockwave_weapon = ai_find_shockwave_weapon(objp, aip);
|
||||
int shockwave_weapon = ai_find_shockwave_weapon(objp);
|
||||
if (shockwave_weapon == -1) {
|
||||
aip->ai_flags.remove(AI::AI_Flags::Avoid_shockwave_weapon);
|
||||
return 0;
|
||||
@@ -13639,7 +13543,7 @@ int aas_1(object *objp, ai_info *aip, vec3d *safe_pos)
|
||||
}
|
||||
} else if (aip->ai_flags[AI::AI_Flags::Avoid_shockwave_ship]) {
|
||||
if (aip->shockwave_object == -1) {
|
||||
int shockwave_ship = ai_find_shockwave_ship(objp, aip);
|
||||
int shockwave_ship = ai_find_shockwave_ship(objp);
|
||||
if (shockwave_ship == -1) {
|
||||
aip->ai_flags.remove(AI::AI_Flags::Avoid_shockwave_ship);
|
||||
return 0;
|
||||
@@ -13869,7 +13773,7 @@ int maybe_big_ship_collide_recover_frame(object *objp, ai_info *aip)
|
||||
vec3d v2g;
|
||||
|
||||
if (aip->ai_flags[AI::AI_Flags::Big_ship_collide_recover_1]) {
|
||||
ai_turn_towards_vector(&aip->big_recover_pos_1, objp, flFrametime, Ship_info[Ships[objp->instance].ship_info_index].srotation_time, NULL, NULL, 0.0f, 0, NULL);
|
||||
ai_turn_towards_vector(&aip->big_recover_pos_1, objp, Ship_info[Ships[objp->instance].ship_info_index].srotation_time, nullptr, nullptr, 0.0f, 0, nullptr);
|
||||
dist = vm_vec_normalized_dir(&v2g, &aip->big_recover_pos_1, &objp->pos);
|
||||
dot = vm_vec_dot(&objp->orient.vec.fvec, &v2g);
|
||||
accelerate_ship(aip, dot);
|
||||
@@ -13883,7 +13787,7 @@ int maybe_big_ship_collide_recover_frame(object *objp, ai_info *aip)
|
||||
return 1;
|
||||
|
||||
} else if (aip->ai_flags[AI::AI_Flags::Big_ship_collide_recover_2]) {
|
||||
ai_turn_towards_vector(&aip->big_recover_pos_2, objp, flFrametime, Ship_info[Ships[objp->instance].ship_info_index].srotation_time, NULL, NULL, 0.0f, 0, NULL);
|
||||
ai_turn_towards_vector(&aip->big_recover_pos_2, objp, Ship_info[Ships[objp->instance].ship_info_index].srotation_time, nullptr, nullptr, 0.0f, 0, nullptr);
|
||||
dist = vm_vec_normalized_dir(&v2g, &aip->big_recover_pos_2, &objp->pos);
|
||||
dot = vm_vec_dot(&objp->orient.vec.fvec, &v2g);
|
||||
accelerate_ship(aip, dot);
|
||||
@@ -14003,7 +13907,7 @@ void ai_frame(int objnum)
|
||||
if (maybe_big_ship_collide_recover_frame(Pl_objp, aip))
|
||||
return;
|
||||
|
||||
ai_preprocess_ignore_objnum(Pl_objp, aip);
|
||||
ai_preprocess_ignore_objnum(aip);
|
||||
target_objnum = set_target_objnum(aip, aip->target_objnum);
|
||||
|
||||
Assert(objnum != target_objnum);
|
||||
@@ -14158,7 +14062,7 @@ void ai_frame(int objnum)
|
||||
}
|
||||
}
|
||||
|
||||
void ai_control_info_check( object * /*obj*/, ai_info *aip )
|
||||
static void ai_control_info_check(ai_info *aip)
|
||||
{
|
||||
if(aip->ai_override_flags.none_set())
|
||||
return;
|
||||
@@ -14259,7 +14163,7 @@ void ai_process( object * obj, int ai_index, float frametime )
|
||||
|
||||
if (rfc == 1) {
|
||||
// Wanderer - sexp based override goes here - only if rfc is valid though
|
||||
ai_control_info_check(obj, aip);
|
||||
ai_control_info_check(aip);
|
||||
vec3d copy_desired_rotvel = obj->phys_info.rotvel;
|
||||
physics_read_flying_controls( &obj->orient, &obj->phys_info, &AI_ci, frametime);
|
||||
// if obj is in formation and not flight leader, don't update rotvel
|
||||
@@ -14794,10 +14698,10 @@ int firing_aspect_seeking_bomb(object *objp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
// *objp collided with big ship *big_objp at global point *collide_pos
|
||||
// Make it fly away from the collision point.
|
||||
// *objp collided with big ship *big_objp at some global point.
|
||||
// Make it fly away from the collision point.
|
||||
// collision_normal is NULL, when a collision is imminent and we just want to bug out.
|
||||
void big_ship_collide_recover_start(object *objp, object *big_objp, vec3d * /*collide_pos*/, vec3d *collision_normal)
|
||||
void big_ship_collide_recover_start(object *objp, object *big_objp, vec3d *collision_normal)
|
||||
{
|
||||
ai_info *aip;
|
||||
|
||||
@@ -14886,9 +14790,9 @@ void ai_update_lethality(object *pship_obj, object *other_obj, float damage)
|
||||
|
||||
|
||||
/**
|
||||
* Object *objp_ship was hit by either weapon *objp_weapon or collided into by ship hit_objp at point *hitpos.
|
||||
* Object *objp_ship was hit by either weapon *objp_weapon or collided into by ship hit_objp
|
||||
*/
|
||||
void ai_ship_hit(object *objp_ship, object *hit_objp, vec3d *hitpos, int /*shield_quadrant*/, vec3d *hit_normal)
|
||||
void ai_ship_hit(object *objp_ship, object *hit_objp, vec3d *hit_normal)
|
||||
{
|
||||
int hitter_objnum = -2;
|
||||
object *objp_hitter = NULL;
|
||||
@@ -14930,7 +14834,7 @@ void ai_ship_hit(object *objp_ship, object *hit_objp, vec3d *hitpos, int /*shie
|
||||
// And the current object is _not_ a big ship
|
||||
if (!Ship_info[Ships[objp_ship->instance].ship_info_index].is_big_or_huge()) {
|
||||
// Recover from hitting a big ship. Note, if two big ships collide, they just pound away at each other. Oh well. Recovery looks dumb and it's very late.
|
||||
big_ship_collide_recover_start(objp_ship, hit_objp, hitpos, hit_normal);
|
||||
big_ship_collide_recover_start(objp_ship, hit_objp, hit_normal);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15067,7 +14971,7 @@ void ai_ship_hit(object *objp_ship, object *hit_objp, vec3d *hitpos, int /*shie
|
||||
return;
|
||||
|
||||
if ( (hit_objp->type == OBJ_WEAPON) && !(aip->ai_flags[AI::AI_Flags::No_dynamic]) ) {
|
||||
if ( ai_big_maybe_enter_strafe_mode(objp_ship, OBJ_INDEX(hit_objp), 1) )
|
||||
if ( ai_big_maybe_enter_strafe_mode(objp_ship, OBJ_INDEX(hit_objp)) )
|
||||
return;
|
||||
}
|
||||
break;
|
||||
@@ -15187,10 +15091,7 @@ void ai_ship_hit(object *objp_ship, object *hit_objp, vec3d *hitpos, int /*shie
|
||||
|
||||
// Ship shipnum has been destroyed.
|
||||
// Cleanup.
|
||||
// the parameter 'method' is used to tell is this ship was destroyed or it departed normally.
|
||||
// This function will get called in either case, and there are things that should be done if
|
||||
// the ship actually gets destroyed which shouldn't get done if it departed.
|
||||
void ai_ship_destroy(int shipnum, Ship::Exit_Flags /*method*/)
|
||||
void ai_ship_destroy(int shipnum)
|
||||
{
|
||||
int objnum;
|
||||
object *other_objp;
|
||||
@@ -15441,7 +15342,7 @@ int ai_issue_rearm_request(object *requester_objp)
|
||||
// we aren't able to do anything!
|
||||
else {
|
||||
Assert(result == 4);
|
||||
Assertion(false, "This case should have already been caught by the is_support_allowed precheck!");
|
||||
UNREACHABLE("This case should have already been caught by the is_support_allowed precheck!");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -15510,7 +15411,7 @@ int ai_return_path_num_from_dockbay(object *dockee_objp, int dockbay_index)
|
||||
/**
|
||||
* Actually go ahead and fire the synaptics.
|
||||
*/
|
||||
void cheat_fire_synaptic(object *objp, ship *shipp, ai_info * /*aip*/)
|
||||
static void cheat_fire_synaptic(object *objp, ship *shipp)
|
||||
{
|
||||
ship_weapon *swp;
|
||||
swp = &shipp->weapons;
|
||||
@@ -15532,7 +15433,7 @@ void cheat_fire_synaptic(object *objp, ship *shipp, ai_info * /*aip*/)
|
||||
// if they're near one or more enemies
|
||||
// every so often
|
||||
// fire a synaptic if they have one.
|
||||
void maybe_cheat_fire_synaptic(object *objp, ai_info *aip)
|
||||
void maybe_cheat_fire_synaptic(object *objp)
|
||||
{
|
||||
// Only do in subspace missions.
|
||||
if (!(The_mission.flags[Mission::Mission_Flags::Subspace]))
|
||||
@@ -15564,7 +15465,7 @@ void maybe_cheat_fire_synaptic(object *objp, ai_info *aip)
|
||||
int count = num_nearby_fighters(iff_get_attackee_mask(obj_team(objp)), &objp->pos, 1500.0f);
|
||||
|
||||
if (count > 0)
|
||||
cheat_fire_synaptic(objp, shipp, aip);
|
||||
cheat_fire_synaptic(objp, shipp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+49
-48
@@ -62,31 +62,32 @@ char Ai_dock_names[MAX_AI_DOCK_NAMES][NAME_LENGTH];
|
||||
// Used in objecttypes.tbl to define custom ship types
|
||||
ai_goal_list Ai_goal_names[] =
|
||||
{
|
||||
{ "Attack ship", AI_GOAL_CHASE, 0 },
|
||||
{ "Dock", AI_GOAL_DOCK, 0 },
|
||||
{ "Waypoints", AI_GOAL_WAYPOINTS, 0 },
|
||||
{ "Waypoints once", AI_GOAL_WAYPOINTS_ONCE, 0 },
|
||||
{ "Depart", AI_GOAL_WARP, 0 },
|
||||
{ "Attack subsys", AI_GOAL_DESTROY_SUBSYSTEM, 0 },
|
||||
{ "Form on wing", AI_GOAL_FORM_ON_WING, 0 },
|
||||
{ "Undock", AI_GOAL_UNDOCK, 0 },
|
||||
{ "Attack wing", AI_GOAL_CHASE_WING, 0 },
|
||||
{ "Guard ship", AI_GOAL_GUARD, 0 },
|
||||
{ "Disable ship", AI_GOAL_DISABLE_SHIP, 0 },
|
||||
{ "Disarm ship", AI_GOAL_DISARM_SHIP, 0 },
|
||||
{ "Attack any", AI_GOAL_CHASE_ANY, 0 },
|
||||
{ "Ignore ship", AI_GOAL_IGNORE, 0 },
|
||||
{ "Ignore ship (new)", AI_GOAL_IGNORE_NEW, 0 },
|
||||
{ "Guard wing", AI_GOAL_GUARD_WING, 0 },
|
||||
{ "Evade ship", AI_GOAL_EVADE_SHIP, 0 },
|
||||
{ "Stay near ship", AI_GOAL_STAY_NEAR_SHIP, 0 },
|
||||
{ "keep safe dist", AI_GOAL_KEEP_SAFE_DISTANCE, 0 },
|
||||
{ "Rearm ship", AI_GOAL_REARM_REPAIR, 0 },
|
||||
{ "Stay still", AI_GOAL_STAY_STILL, 0 },
|
||||
{ "Play dead", AI_GOAL_PLAY_DEAD, 0 },
|
||||
{ "Attack weapon", AI_GOAL_CHASE_WEAPON, 0 },
|
||||
{ "Fly to ship", AI_GOAL_FLY_TO_SHIP, 0 },
|
||||
{ "Attack ship class", AI_GOAL_CHASE_SHIP_CLASS, 0 },
|
||||
{ "Attack ship", AI_GOAL_CHASE, 0 },
|
||||
{ "Dock", AI_GOAL_DOCK, 0 },
|
||||
{ "Waypoints", AI_GOAL_WAYPOINTS, 0 },
|
||||
{ "Waypoints once", AI_GOAL_WAYPOINTS_ONCE, 0 },
|
||||
{ "Depart", AI_GOAL_WARP, 0 },
|
||||
{ "Attack subsys", AI_GOAL_DESTROY_SUBSYSTEM, 0 },
|
||||
{ "Form on wing", AI_GOAL_FORM_ON_WING, 0 },
|
||||
{ "Undock", AI_GOAL_UNDOCK, 0 },
|
||||
{ "Attack wing", AI_GOAL_CHASE_WING, 0 },
|
||||
{ "Guard ship", AI_GOAL_GUARD, 0 },
|
||||
{ "Disable ship", AI_GOAL_DISABLE_SHIP, 0 },
|
||||
{ "Disarm ship", AI_GOAL_DISARM_SHIP, 0 },
|
||||
{ "Attack any", AI_GOAL_CHASE_ANY, 0 },
|
||||
{ "Ignore ship", AI_GOAL_IGNORE, 0 },
|
||||
{ "Ignore ship (new)", AI_GOAL_IGNORE_NEW, 0 },
|
||||
{ "Guard wing", AI_GOAL_GUARD_WING, 0 },
|
||||
{ "Evade ship", AI_GOAL_EVADE_SHIP, 0 },
|
||||
{ "Stay near ship", AI_GOAL_STAY_NEAR_SHIP, 0 },
|
||||
{ "keep safe dist", AI_GOAL_KEEP_SAFE_DISTANCE, 0 },
|
||||
{ "Rearm ship", AI_GOAL_REARM_REPAIR, 0 },
|
||||
{ "Stay still", AI_GOAL_STAY_STILL, 0 },
|
||||
{ "Play dead", AI_GOAL_PLAY_DEAD, 0 },
|
||||
{ "Play dead (persistent)", AI_GOAL_PLAY_DEAD_PERSISTENT, 0 },
|
||||
{ "Attack weapon", AI_GOAL_CHASE_WEAPON, 0 },
|
||||
{ "Fly to ship", AI_GOAL_FLY_TO_SHIP, 0 },
|
||||
{ "Attack ship class", AI_GOAL_CHASE_SHIP_CLASS, 0 },
|
||||
};
|
||||
|
||||
int Num_ai_goals = sizeof(Ai_goal_names) / sizeof(ai_goal_list);
|
||||
@@ -125,7 +126,7 @@ const char *Ai_goal_text(int goal)
|
||||
case AI_GOAL_REARM_REPAIR:
|
||||
return XSTR( "rearm ", 484);
|
||||
case AI_GOAL_FLY_TO_SHIP:
|
||||
return XSTR( "rendezvous with ", -1);
|
||||
return XSTR( "rendezvous with ", 1597);
|
||||
}
|
||||
|
||||
// Avoid compiler warning
|
||||
@@ -937,6 +938,11 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_goal *aigp, char *actor_name )
|
||||
aigp->ai_mode = AI_GOAL_PLAY_DEAD;
|
||||
break;
|
||||
|
||||
case OP_AI_PLAY_DEAD_PERSISTENT:
|
||||
aigp->priority = atoi( CTEXT(CDR(node)) );
|
||||
aigp->ai_mode = AI_GOAL_PLAY_DEAD_PERSISTENT;
|
||||
break;
|
||||
|
||||
case OP_AI_KEEP_SAFE_DISTANCE:
|
||||
aigp->priority = atoi( CTEXT(CDR(node)) );
|
||||
aigp->ai_mode = AI_GOAL_KEEP_SAFE_DISTANCE;
|
||||
@@ -1126,6 +1132,10 @@ int ai_remove_goal_sexp_sub( int sexp, ai_goal* aigp )
|
||||
goalmode = AI_GOAL_PLAY_DEAD;
|
||||
priority = ( CDR(node) >= 0 ) ? atoi( CTEXT( CDR( node ) ) ) : -1;
|
||||
break;
|
||||
case OP_AI_PLAY_DEAD_PERSISTENT:
|
||||
goalmode = AI_GOAL_PLAY_DEAD_PERSISTENT;
|
||||
priority = ( CDR(node) >= 0 ) ? atoi( CTEXT( CDR( node ) ) ) : -1;
|
||||
break;
|
||||
case OP_AI_KEEP_SAFE_DISTANCE:
|
||||
priority = ( CDR(node) >= 0 ) ? atoi( CTEXT( CDR( node ) ) ) : -1;
|
||||
goalmode = AI_GOAL_KEEP_SAFE_DISTANCE;
|
||||
@@ -1340,25 +1350,6 @@ void ai_add_goal_ship_internal( ai_info *aip, int goal_type, char *name, int /*
|
||||
ai_process_mission_orders( Ships[aip->shipnum].objnum, aip );
|
||||
}
|
||||
|
||||
// function to add an internal goal to a wing. Mike K says that the goal doesn't need to persist
|
||||
// across waves of the wing so we merely need to add the goal to each ship in the wing. Certain
|
||||
// goal are simply not valid for wings (like dock, undock). Immediate parameter gets passed to add_ship_goal
|
||||
// to say whether or not we should process this goal right away
|
||||
void ai_add_goal_wing_internal( wing *wingp, int goal_type, char *name, int immediate )
|
||||
{
|
||||
int i;
|
||||
|
||||
// be sure we are not trying to issue dock or undock goals to wings
|
||||
Assert ( (goal_type != AI_GOAL_DOCK) && (goal_type != AI_GOAL_UNDOCK) );
|
||||
|
||||
for (i = 0; i < wingp->current_count; i++) {
|
||||
int num = wingp->ship_index[i];
|
||||
if ( num == -1 ) // ship must have been destroyed or departed
|
||||
continue;
|
||||
ai_add_goal_ship_internal( &Ai_info[Ships[num].ai_index], goal_type, name, -1, -1, immediate);
|
||||
}
|
||||
}
|
||||
|
||||
// this function copies goals from a wing to an ai_info * from a ship.
|
||||
void ai_copy_mission_wing_goal( ai_goal *aigp, ai_info *aip )
|
||||
{
|
||||
@@ -1401,7 +1392,7 @@ int ai_mission_goal_achievable( int objnum, ai_goal *aigp )
|
||||
// these orders are always achievable.
|
||||
if ( (aigp->ai_mode == AI_GOAL_KEEP_SAFE_DISTANCE)
|
||||
|| (aigp->ai_mode == AI_GOAL_CHASE_ANY) || (aigp->ai_mode == AI_GOAL_STAY_STILL)
|
||||
|| (aigp->ai_mode == AI_GOAL_PLAY_DEAD) )
|
||||
|| (aigp->ai_mode == AI_GOAL_PLAY_DEAD) || (aigp->ai_mode == AI_GOAL_PLAY_DEAD_PERSISTENT) )
|
||||
return AI_GOAL_ACHIEVABLE;
|
||||
|
||||
// warp (depart) only achievable if there's somewhere to depart to
|
||||
@@ -1895,9 +1886,12 @@ int ai_goal_priority_compare(const void *a, const void *b)
|
||||
// check whether or not the goal override flag is set. If it is set, then push this goal higher
|
||||
// in the list
|
||||
|
||||
else if ( (ga->flags[AI::Goal_Flags::Goal_override]) && !(gb->flags[AI::Goal_Flags::Goal_override]) )
|
||||
// Goober5000: the ONLY goals we do not override are play-dead and play-dead-persistent,
|
||||
// because the override flag needs to work in any other situation
|
||||
|
||||
else if ( (ga->flags[AI::Goal_Flags::Goal_override]) && !(gb->flags[AI::Goal_Flags::Goal_override]) && !(gb->ai_mode == AI_GOAL_PLAY_DEAD) && !(gb->ai_mode == AI_GOAL_PLAY_DEAD_PERSISTENT) )
|
||||
return -1;
|
||||
else if ( !(ga->flags[AI::Goal_Flags::Goal_override]) && (gb->flags[AI::Goal_Flags::Goal_override]) )
|
||||
else if ( !(ga->flags[AI::Goal_Flags::Goal_override]) && (gb->flags[AI::Goal_Flags::Goal_override]) && !(ga->ai_mode == AI_GOAL_PLAY_DEAD) && !(ga->ai_mode == AI_GOAL_PLAY_DEAD_PERSISTENT))
|
||||
return 1;
|
||||
|
||||
// now normal priority processing
|
||||
@@ -2290,6 +2284,13 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
|
||||
aip->submode_start_time = Missiontime;
|
||||
break;
|
||||
|
||||
case AI_GOAL_PLAY_DEAD_PERSISTENT:
|
||||
// same as above, but we don't clear out ship goals
|
||||
aip->mode = AIM_PLAY_DEAD;
|
||||
aip->submode = -1;
|
||||
aip->submode_start_time = Missiontime;
|
||||
break;
|
||||
|
||||
case AI_GOAL_FORM_ON_WING:
|
||||
// for form on wing, we need to clear out all goals for this ship, and then call the form
|
||||
// on wing AI code
|
||||
|
||||
+5
-5
@@ -58,16 +58,17 @@ struct ai_goal;
|
||||
#define AI_GOAL_FLY_TO_SHIP (1<<23) // 0x00800000
|
||||
#define AI_GOAL_IGNORE_NEW (1<<24) // 0x01000000
|
||||
#define AI_GOAL_CHASE_SHIP_CLASS (1<<25) // 0x02000000
|
||||
#define AI_GOAL_PLAY_DEAD_PERSISTENT (1<<26) // 0x03000000
|
||||
|
||||
// now the masks for ship types
|
||||
|
||||
// Goober5000: added AI_GOAL_STAY_NEAR_SHIP and AI_GOAL_KEEP_SAFE_DISTANCE as valid for fighters
|
||||
//WMC - Don't need these anymore. Whee!
|
||||
/*
|
||||
#define AI_GOAL_ACCEPT_FIGHTER ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_CHASE | AI_GOAL_WAYPOINTS | AI_GOAL_WAYPOINTS_ONCE | AI_GOAL_WARP | AI_GOAL_DESTROY_SUBSYSTEM | AI_GOAL_CHASE_WING | AI_GOAL_GUARD | AI_GOAL_DISABLE_SHIP | AI_GOAL_DISARM_SHIP | AI_GOAL_CHASE_ANY | AI_GOAL_IGNORE | AI_GOAL_IGNORE_NEW | AI_GOAL_GUARD_WING | AI_GOAL_EVADE_SHIP | AI_GOAL_STAY_STILL | AI_GOAL_PLAY_DEAD | AI_GOAL_STAY_NEAR_SHIP | AI_GOAL_KEEP_SAFE_DISTANCE )
|
||||
#define AI_GOAL_ACCEPT_FIGHTER ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_CHASE | AI_GOAL_WAYPOINTS | AI_GOAL_WAYPOINTS_ONCE | AI_GOAL_WARP | AI_GOAL_DESTROY_SUBSYSTEM | AI_GOAL_CHASE_WING | AI_GOAL_GUARD | AI_GOAL_DISABLE_SHIP | AI_GOAL_DISARM_SHIP | AI_GOAL_CHASE_ANY | AI_GOAL_IGNORE | AI_GOAL_IGNORE_NEW | AI_GOAL_GUARD_WING | AI_GOAL_EVADE_SHIP | AI_GOAL_STAY_STILL | AI_GOAL_PLAY_DEAD | AI_GOAL_PLAY_DEAD_PERSISTENT | AI_GOAL_STAY_NEAR_SHIP | AI_GOAL_KEEP_SAFE_DISTANCE )
|
||||
#define AI_GOAL_ACCEPT_BOMBER ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_FIGHTER | AI_GOAL_STAY_NEAR_SHIP )
|
||||
#define AI_GOAL_ACCEPT_STEALTH ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_FIGHTER | AI_GOAL_STAY_NEAR_SHIP )
|
||||
#define AI_GOAL_ACCEPT_TRANSPORT ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_CHASE | AI_GOAL_CHASE_WING | AI_GOAL_DOCK | AI_GOAL_WAYPOINTS | AI_GOAL_WAYPOINTS_ONCE | AI_GOAL_WARP | AI_GOAL_UNDOCK | AI_GOAL_STAY_STILL | AI_GOAL_PLAY_DEAD| AI_GOAL_STAY_NEAR_SHIP )
|
||||
#define AI_GOAL_ACCEPT_TRANSPORT ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_CHASE | AI_GOAL_CHASE_WING | AI_GOAL_DOCK | AI_GOAL_WAYPOINTS | AI_GOAL_WAYPOINTS_ONCE | AI_GOAL_WARP | AI_GOAL_UNDOCK | AI_GOAL_STAY_STILL | AI_GOAL_PLAY_DEAD | AI_GOAL_PLAY_DEAD_PERSISTENT | AI_GOAL_STAY_NEAR_SHIP )
|
||||
#define AI_GOAL_ACCEPT_FREIGHTER ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_TRANSPORT | AI_GOAL_STAY_NEAR_SHIP )
|
||||
#define AI_GOAL_ACCEPT_CRUISER ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_FREIGHTER | AI_GOAL_STAY_NEAR_SHIP )
|
||||
#define AI_GOAL_ACCEPT_CORVETTE ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_CRUISER | AI_GOAL_STAY_NEAR_SHIP )
|
||||
@@ -75,7 +76,7 @@ struct ai_goal;
|
||||
#define AI_GOAL_ACCEPT_AWACS ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_CRUISER | AI_GOAL_STAY_NEAR_SHIP )
|
||||
#define AI_GOAL_ACCEPT_CAPITAL ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_CRUISER & ~(AI_GOAL_DOCK | AI_GOAL_UNDOCK) | AI_GOAL_STAY_NEAR_SHIP )
|
||||
#define AI_GOAL_ACCEPT_SUPERCAP ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_CAPITAL | AI_GOAL_STAY_NEAR_SHIP )
|
||||
#define AI_GOAL_ACCEPT_SUPPORT ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_DOCK | AI_GOAL_UNDOCK | AI_GOAL_WAYPOINTS | AI_GOAL_WAYPOINTS_ONCE | AI_GOAL_STAY_NEAR_SHIP | AI_GOAL_KEEP_SAFE_DISTANCE | AI_GOAL_STAY_STILL | AI_GOAL_PLAY_DEAD)
|
||||
#define AI_GOAL_ACCEPT_SUPPORT ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_DOCK | AI_GOAL_UNDOCK | AI_GOAL_WAYPOINTS | AI_GOAL_WAYPOINTS_ONCE | AI_GOAL_STAY_NEAR_SHIP | AI_GOAL_KEEP_SAFE_DISTANCE | AI_GOAL_STAY_STILL | AI_GOAL_PLAY_DEAD | AI_GOAL_PLAY_DEAD_PERSISTENT )
|
||||
#define AI_GOAL_ACCEPT_ESCAPEPOD ( AI_GOAL_FLY_TO_SHIP | AI_GOAL_ACCEPT_TRANSPORT| AI_GOAL_STAY_NEAR_SHIP )
|
||||
*/
|
||||
|
||||
@@ -102,7 +103,7 @@ extern int ai_goal_num(ai_goal *goals);
|
||||
extern void ai_add_ship_goal_scripting(int mode, int submode, int priority, char *shipname, ai_info *aip);
|
||||
extern void ai_add_ship_goal_sexp( int sexp, int type, ai_info *aip );
|
||||
extern void ai_add_wing_goal_sexp( int sexp, int type, int wingnum );
|
||||
extern void ai_add_goal_sub_sexp( int sexp, int type, ai_goal *aigp );
|
||||
extern void ai_add_goal_sub_sexp( int sexp, int type, ai_goal *aigp, char *actor_name );
|
||||
|
||||
extern int ai_remove_goal_sexp_sub( int sexp, ai_goal* aigp );
|
||||
extern void ai_remove_wing_goal_sexp(int sexp, int wingnum);
|
||||
@@ -127,6 +128,5 @@ extern char *ai_add_dock_name(const char *str);
|
||||
extern int ai_query_goal_valid( int ship, int ai_goal_type );
|
||||
|
||||
extern void ai_add_goal_ship_internal( ai_info *aip, int goal_type, char *name, int docker_point, int dockee_point, int immediate = 1 );
|
||||
extern void ai_add_goal_wing_internal( wing *wingp, int goal_type, char *name, int immediate = 1 );
|
||||
|
||||
#endif
|
||||
@@ -1290,7 +1290,9 @@ void ship_get_global_turret_gun_info(object *objp, ship_subsys *ssp, vec3d *gpos
|
||||
model_instance_find_world_point(&tmp_pos, &avg, Ships[objp->instance].model_instance_num, tp->turret_gun_sobj, &objp->orient, &objp->pos);
|
||||
|
||||
if (targetp == nullptr) {
|
||||
Assertion(ssp->turret_enemy_objnum >= 0, "The turret enemy object number %d for %s on ship number %d is invalid.", ssp->turret_enemy_objnum, ssp->sub_name, ssp->parent_objnum);
|
||||
ship* shipp = &Ships[Objects[ssp->parent_objnum].instance];
|
||||
Assertion(ssp->turret_enemy_objnum >= 0, "The turret enemy object number %d for %s on ship name %s is invalid.", ssp->turret_enemy_objnum, ssp->sub_name,
|
||||
(shipp->has_display_name()) ? shipp->display_name.c_str() : shipp->ship_name);
|
||||
object *lep = &Objects[ssp->turret_enemy_objnum];
|
||||
|
||||
int best_weapon_tidx = turret_select_best_weapon(ssp, lep);
|
||||
@@ -1301,9 +1303,9 @@ void ship_get_global_turret_gun_info(object *objp, ship_subsys *ssp, vec3d *gpos
|
||||
|
||||
weapon_info *wip = get_turret_weapon_wip(&ssp->weapons, best_weapon_tidx);
|
||||
|
||||
float weapon_system_strength = ship_get_subsystem_strength(&Ships[ssp->parent_objnum], SUBSYSTEM_WEAPONS);
|
||||
float weapon_system_strength = ship_get_subsystem_strength(shipp, SUBSYSTEM_WEAPONS);
|
||||
|
||||
turret_ai_update_aim(&Ai_info[Ships[ssp->parent_objnum].ai_index], &Objects[ssp->turret_enemy_objnum], ssp);
|
||||
turret_ai_update_aim(&Ai_info[shipp->ai_index], &Objects[ssp->turret_enemy_objnum], ssp);
|
||||
|
||||
if ((ssp->targeted_subsys != nullptr) && !(ssp->flags[Ship::Subsystem_Flags::No_SS_targeting])) {
|
||||
vm_vec_unrotate(&enemy_point, &ssp->targeted_subsys->system_info->pnt, &Objects[ssp->turret_enemy_objnum].orient);
|
||||
@@ -1874,7 +1876,7 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
|
||||
turret->last_fired_weapon_info_index = turret_weapon_class;
|
||||
|
||||
Script_system.SetHookObjects(4, "Ship", &Objects[parent_objnum], "Weapon", nullptr, "Beam", objp, "Target", &Objects[turret->turret_enemy_objnum]);
|
||||
Script_system.RunCondition(CHA_ONTURRETFIRED, 0, NULL, &Objects[parent_objnum]);
|
||||
Script_system.RunCondition(CHA_ONTURRETFIRED, &Objects[parent_objnum]);
|
||||
Script_system.RemHookVars(4, "Ship", "Weapon", "Beam", "Target");
|
||||
}
|
||||
|
||||
@@ -2009,7 +2011,7 @@ bool turret_fire_weapon(int weapon_num, ship_subsys *turret, int parent_objnum,
|
||||
wp->turret_subsys = turret;
|
||||
|
||||
Script_system.SetHookObjects(4, "Ship", &Objects[parent_objnum], "Weapon", objp, "Beam", nullptr, "Target", &Objects[turret->turret_enemy_objnum]);
|
||||
Script_system.RunCondition(CHA_ONTURRETFIRED, 0, NULL, &Objects[parent_objnum]);
|
||||
Script_system.RunCondition(CHA_ONTURRETFIRED, &Objects[parent_objnum]);
|
||||
Script_system.RemHookVars(4, "Ship", "Weapon", "Beam", "Target");
|
||||
|
||||
// if the gun is a flak gun
|
||||
@@ -2126,7 +2128,7 @@ void turret_swarm_fire_from_turret(turret_swarm_info *tsi)
|
||||
tsi->turret->last_fired_weapon_info_index = tsi->weapon_class;
|
||||
|
||||
Script_system.SetHookObjects(4, "Ship", &Objects[tsi->parent_objnum], "Weapon", &Objects[weapon_objnum], "Beam", nullptr, "Target", &Objects[tsi->turret->turret_enemy_objnum]);
|
||||
Script_system.RunCondition(CHA_ONTURRETFIRED, 0, NULL, &Objects[tsi->parent_objnum]);
|
||||
Script_system.RunCondition(CHA_ONTURRETFIRED, &Objects[tsi->parent_objnum]);
|
||||
Script_system.RemHookVars(4, "Ship", "Weapon", "Beam", "Target");
|
||||
|
||||
// muzzle flash?
|
||||
|
||||
@@ -519,19 +519,6 @@ int anim_show_next_frame(anim_instance *instance, float frametime)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stop an anim instance that is on the anim_render_list from playing
|
||||
*/
|
||||
int anim_stop_playing(anim_instance* instance)
|
||||
{
|
||||
Assert(instance != NULL);
|
||||
|
||||
if ( anim_playing(instance) ) {
|
||||
anim_release_render_instance(instance);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Free a particular animation instance that is on the anim_render_list.
|
||||
* Do not call this function to free an animation instance in general (use
|
||||
@@ -866,20 +853,6 @@ int anim_free(anim *ptr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Return if an anim is playing or not.
|
||||
*/
|
||||
int anim_playing(anim_instance *ai)
|
||||
{
|
||||
Assert(ai != NULL);
|
||||
if ( ai->frame == NULL )
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Called at the beginning of a mission to initialize any mission dependent anim data.
|
||||
* @todo Redundant?
|
||||
@@ -896,138 +869,6 @@ void anim_level_close()
|
||||
anim_release_all_instances();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write the frames of a .ani file out to disk as .pcx files.
|
||||
* @details Use naming convention: filename0000.pcx, filename0001.pcx etc.
|
||||
*
|
||||
* @return If success 0, or if failed -1
|
||||
*/
|
||||
int anim_write_frames_out(char *filename)
|
||||
{
|
||||
anim *source_anim;
|
||||
anim_instance *ai;
|
||||
char root_name[256], pcxname[256];
|
||||
char buf[64];
|
||||
int i,j;
|
||||
ubyte **row_data;
|
||||
|
||||
strcpy_s(root_name, filename);
|
||||
root_name[strlen(filename)-4] = 0;
|
||||
|
||||
source_anim = anim_load(filename);
|
||||
if ( source_anim == NULL )
|
||||
return -1;
|
||||
|
||||
ai = init_anim_instance(source_anim, 16);
|
||||
|
||||
row_data = (ubyte**)vm_malloc((source_anim->height+1) * 4);
|
||||
|
||||
for ( i = 0; i < source_anim->total_frames; i++ ) {
|
||||
anim_get_next_raw_buffer(ai, 0, 0, 16);
|
||||
strcpy_s(pcxname, root_name);
|
||||
sprintf(buf,"%04d",i);
|
||||
strcat_s(pcxname, buf);
|
||||
|
||||
for ( j = 0; j < source_anim->height; j++ ) {
|
||||
row_data[j] = &ai->frame[j*source_anim->width];
|
||||
}
|
||||
|
||||
|
||||
pcx_write_bitmap( pcxname,
|
||||
source_anim->width,
|
||||
source_anim->height,
|
||||
row_data,
|
||||
source_anim->palette);
|
||||
|
||||
printf(".");
|
||||
|
||||
}
|
||||
printf("\n");
|
||||
vm_free(row_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Display information and statistics about a .ani file.
|
||||
* @details This is called when -i switch is on when running ac.exe
|
||||
*/
|
||||
void anim_display_info(char *real_filename)
|
||||
{
|
||||
CFILE *fp;
|
||||
anim A;
|
||||
float percent;
|
||||
int i, uncompressed, compressed, *key_frame_nums=NULL, tmp;
|
||||
char filename[MAX_FILENAME_LEN];
|
||||
|
||||
strcpy_s( filename, real_filename );
|
||||
char *p = strchr( filename, '.' );
|
||||
if ( p ) {
|
||||
*p = 0;
|
||||
}
|
||||
strcat_s( filename, ".ani" );
|
||||
|
||||
fp = cfopen(filename, "rb");
|
||||
if ( !fp ) {
|
||||
printf("Fatal error opening %s", filename);
|
||||
return;
|
||||
}
|
||||
|
||||
anim_read_header(&A, fp);
|
||||
|
||||
if (A.width < 0 || A.height < 0) {
|
||||
Error(LOCATION, "Ani file %s has a faulty header and cannot be loaded.", filename);
|
||||
}
|
||||
|
||||
// read the keyframe frame nums and offsets
|
||||
key_frame_nums = (int*)vm_malloc(sizeof(int)*A.num_keys);
|
||||
Assert(key_frame_nums != NULL);
|
||||
if (key_frame_nums == NULL)
|
||||
return;
|
||||
|
||||
for ( i = 0; i < A.num_keys; i++ ) {
|
||||
key_frame_nums[i] = 0;
|
||||
cfread(&key_frame_nums[i], 2, 1, fp);
|
||||
cfread(&tmp, 4, 1, fp);
|
||||
}
|
||||
|
||||
cfread(&compressed, 4, 1, fp);
|
||||
|
||||
uncompressed = A.width * A.height * A.total_frames; // 8 bits per pixel
|
||||
percent = i2fl(compressed) / uncompressed * 100.0f;
|
||||
|
||||
printf("%% of uncompressed size: %.0f%%\n", percent);
|
||||
printf("Width: %d\n", A.width);
|
||||
printf("Height: %d\n", A.height);
|
||||
printf("Total Frames: %d\n", A.total_frames);
|
||||
|
||||
#ifndef NDEBUG
|
||||
printf("Key Frames: %d\n", A.num_keys);
|
||||
if ( A.num_keys > 1 && (A.total_frames != A.num_keys) ) {
|
||||
printf("key list: (");
|
||||
for ( i = 0; i < A.num_keys; i++ ) {
|
||||
if ( i < A.num_keys-1 )
|
||||
printf("%d, ", key_frame_nums[i]);
|
||||
else
|
||||
printf("%d)\n", key_frame_nums[i]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
printf("FPS: %d\n", A.fps);
|
||||
|
||||
#ifndef NDEBUG
|
||||
printf("Transparent RGB: (%u,%u,%u)\n", A.xparent_r, A.xparent_g, A.xparent_b);
|
||||
#endif
|
||||
|
||||
printf("ac version: %d\n", A.version);
|
||||
|
||||
if ( key_frame_nums != NULL ) {
|
||||
vm_free(key_frame_nums);
|
||||
}
|
||||
|
||||
cfclose(fp);
|
||||
}
|
||||
|
||||
void anim_reverse_direction(anim_instance *ai)
|
||||
{
|
||||
int temp;
|
||||
@@ -1061,16 +902,6 @@ void anim_reverse_direction(anim_instance *ai)
|
||||
}
|
||||
}
|
||||
|
||||
void anim_pause(anim_instance *ai)
|
||||
{
|
||||
ai->paused = 1;
|
||||
}
|
||||
|
||||
void anim_unpause(anim_instance *ai)
|
||||
{
|
||||
ai->paused = 0;
|
||||
}
|
||||
|
||||
void anim_ignore_next_frametime()
|
||||
{
|
||||
Anim_ignore_frametime=1;
|
||||
|
||||
@@ -54,19 +54,13 @@ void anim_render_one(int screen_id, anim_instance *ani, float frametime);
|
||||
void anim_play_init(anim_play_struct *aps, anim *a_info, int x, int y, int max_x = -1, int max_y = -1);
|
||||
anim_instance *anim_play(anim_play_struct *aps);
|
||||
void anim_ignore_next_frametime();
|
||||
int anim_stop_playing(anim_instance* anim_instance);
|
||||
int anim_show_next_frame(anim_instance *instance, float frametime);
|
||||
void anim_release_all_instances(int screen_id = 0);
|
||||
void anim_release_render_instance(anim_instance* instance);
|
||||
anim *anim_load(const char *name, int cf_dir_type = CF_TYPE_ANY, int file_mapped = PAGE_FROM_DISK);
|
||||
int anim_free(anim *ptr);
|
||||
int anim_playing(anim_instance *ai);
|
||||
int anim_write_frames_out(char *filename);
|
||||
void anim_display_info(char *filename);
|
||||
void anim_read_header(anim *ptr, CFILE *fp);
|
||||
void anim_reverse_direction(anim_instance *ai); // called automatically for ping-ponging, and can also be called externally
|
||||
void anim_pause(anim_instance *ai);
|
||||
void anim_unpause(anim_instance *ai);
|
||||
|
||||
int anim_instance_is_streamed(anim_instance *ai);
|
||||
unsigned char anim_instance_get_byte(anim_instance *ai, int offset);
|
||||
|
||||
@@ -78,52 +78,6 @@ void free_anim_instance(anim_instance *inst)
|
||||
vm_free(inst);
|
||||
}
|
||||
|
||||
int anim_get_next_frame(anim_instance *inst)
|
||||
{
|
||||
int bm, bitmap_flags;
|
||||
int aabitmap = 0;
|
||||
int bpp = 16;
|
||||
|
||||
if ( anim_instance_is_streamed(inst) ) {
|
||||
if ( inst->file_offset <= 0 ) {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if (!inst->data)
|
||||
return -1;
|
||||
}
|
||||
|
||||
inst->frame_num++;
|
||||
if (inst->frame_num >= inst->parent->total_frames) {
|
||||
inst->data = NULL;
|
||||
inst->file_offset = inst->parent->file_offset;
|
||||
return -1;
|
||||
}
|
||||
|
||||
bitmap_flags = 0;
|
||||
|
||||
bpp = 16;
|
||||
if(inst->aa_color != NULL){
|
||||
bitmap_flags |= BMP_AABITMAP;
|
||||
aabitmap = 1;
|
||||
bpp = 8;
|
||||
}
|
||||
|
||||
anim_check_for_palette_change(inst);
|
||||
|
||||
BM_SELECT_TEX_FORMAT();
|
||||
|
||||
if ( anim_instance_is_streamed(inst) ) {
|
||||
inst->file_offset = unpack_frame_from_file(inst, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation, aabitmap, bpp);
|
||||
} else {
|
||||
inst->data = unpack_frame(inst, inst->data, inst->frame, inst->parent->width*inst->parent->height, inst->parent->palette_translation, aabitmap, bpp);
|
||||
}
|
||||
|
||||
bm = bm_create(bpp, inst->parent->width, inst->parent->height, inst->frame, bitmap_flags);
|
||||
bm_unload(bm);
|
||||
return bm;
|
||||
}
|
||||
|
||||
ubyte *anim_get_next_raw_buffer(anim_instance *inst, int xlate_pal, int aabitmap, int bpp)
|
||||
{
|
||||
if ( anim_instance_is_streamed(inst) ) {
|
||||
@@ -162,321 +116,6 @@ ubyte *anim_get_next_raw_buffer(anim_instance *inst, int xlate_pal, int aabitmap
|
||||
return inst->frame;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Pack key frame
|
||||
*
|
||||
* @param frame Frame pixel data to pack
|
||||
* @param save Memory to store packed data to
|
||||
* @param size Number of bytes to pack
|
||||
* @param max Maximum number of packed bytes (size of buffer)
|
||||
* @param compress_type Compress type
|
||||
* @return Actual number of bytes data packed to or -1 if error
|
||||
*/
|
||||
int pack_key_frame(ubyte *frame, ubyte *save, long size, long max, int compress_type)
|
||||
{
|
||||
int last = -32768, count = 0;
|
||||
long packed_size = 1;
|
||||
|
||||
switch ( compress_type ) {
|
||||
case PACKING_METHOD_RLE_KEY:
|
||||
*save++ = PACKING_METHOD_RLE_KEY;
|
||||
while (size--) {
|
||||
if (*frame != last || count > 255) {
|
||||
if (packed_size + 3 >= max)
|
||||
return -1;
|
||||
|
||||
if (count < 3) {
|
||||
if (last == packer_code) {
|
||||
*save++ = (ubyte)packer_code;
|
||||
*save++ = (ubyte)(count - 1);
|
||||
packed_size += 2;
|
||||
|
||||
} else
|
||||
while (count--) {
|
||||
*save++ = (ubyte)last;
|
||||
packed_size++;
|
||||
}
|
||||
|
||||
} else {
|
||||
*save++ = (ubyte)packer_code;
|
||||
*save++ = (ubyte)(count - 1);
|
||||
*save++ = (ubyte)last;
|
||||
packed_size += 3;
|
||||
}
|
||||
|
||||
count = 0;
|
||||
last = *frame;
|
||||
}
|
||||
|
||||
count++;
|
||||
frame++;
|
||||
}
|
||||
|
||||
if (packed_size + 3 >= max)
|
||||
return -1;
|
||||
|
||||
if (count < 3) {
|
||||
if (last == packer_code) {
|
||||
*save++ = (ubyte)packer_code;
|
||||
*save++ = (ubyte)(count - 1);
|
||||
packed_size += 2;
|
||||
|
||||
} else
|
||||
while (count--) {
|
||||
*save++ = (ubyte)last;
|
||||
packed_size++;
|
||||
}
|
||||
|
||||
} else {
|
||||
*save++ = (ubyte)packer_code;
|
||||
*save++ = (ubyte)(count - 1);
|
||||
*save++ = (ubyte)last;
|
||||
packed_size += 3;
|
||||
}
|
||||
break;
|
||||
|
||||
case PACKING_METHOD_STD_RLE_KEY: {
|
||||
ubyte *dest_start;
|
||||
int i;
|
||||
|
||||
dest_start = save;
|
||||
count = 1;
|
||||
|
||||
last = *frame++;
|
||||
*save++ = PACKING_METHOD_STD_RLE_KEY;
|
||||
for (i=1; i < size; i++ ) {
|
||||
|
||||
if ( *frame != last ) {
|
||||
if ( count ) {
|
||||
|
||||
if (packed_size + 2 >= max)
|
||||
return -1;
|
||||
|
||||
if ( (count == 1) && !(last & STD_RLE_CODE) ) {
|
||||
*save++ = (ubyte)last;
|
||||
packed_size++;
|
||||
Assert( last != STD_RLE_CODE );
|
||||
}
|
||||
else {
|
||||
count |= STD_RLE_CODE;
|
||||
*save++ = (ubyte)count;
|
||||
*save++ = (ubyte)last;
|
||||
packed_size += 2;
|
||||
}
|
||||
}
|
||||
|
||||
last = *frame;
|
||||
count = 0;
|
||||
}
|
||||
|
||||
count++;
|
||||
frame++;
|
||||
|
||||
if ( count == 127 ) {
|
||||
count |= STD_RLE_CODE;
|
||||
*save++ = (ubyte)count;
|
||||
*save++ = (ubyte)last;
|
||||
packed_size += 2;
|
||||
count = 0;
|
||||
}
|
||||
} // end for
|
||||
|
||||
if (count) {
|
||||
|
||||
if (packed_size + 2 >= max)
|
||||
return -1;
|
||||
|
||||
if ( (count == 1) && !(last & STD_RLE_CODE) ) {
|
||||
*save++ = (ubyte)last;
|
||||
packed_size++;
|
||||
Assert( last != STD_RLE_CODE );
|
||||
}
|
||||
else {
|
||||
count |= STD_RLE_CODE;
|
||||
*save++ = (ubyte)count;
|
||||
*save++ = (ubyte)last;
|
||||
packed_size += 2;
|
||||
}
|
||||
}
|
||||
|
||||
Assert(packed_size == (save-dest_start) );
|
||||
return packed_size;
|
||||
}
|
||||
|
||||
default:
|
||||
Assert(0);
|
||||
return -1;
|
||||
break;
|
||||
} // end switch
|
||||
|
||||
return packed_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Pack frame
|
||||
*
|
||||
* @param frame Frame pixel data to pack
|
||||
* @param frame2 Previous frame's pixel data
|
||||
* @param save Memory to store packed data to
|
||||
* @param size Number of bytes to pack
|
||||
* @param max Maximum number of packed bytes (size of buffer)
|
||||
* @param compress_type Compress type
|
||||
* @return Actual number of bytes data packed to or -1 if error
|
||||
*/
|
||||
int pack_frame(ubyte *frame, ubyte *frame2, ubyte *save, long size, long max, int compress_type)
|
||||
{
|
||||
int pixel, last = -32768, count = 0, i;
|
||||
long packed_size = 1;
|
||||
|
||||
switch ( compress_type ) {
|
||||
case PACKING_METHOD_RLE: // Hoffoss RLE regular frame
|
||||
*save++ = PACKING_METHOD_RLE;
|
||||
while (size--) {
|
||||
if (*frame != *frame2++)
|
||||
pixel = *frame;
|
||||
else
|
||||
pixel = transparent_code;
|
||||
|
||||
if (pixel != last || count > 255) {
|
||||
if (packed_size + 3 >= max)
|
||||
return -1;
|
||||
|
||||
if (count < 3) {
|
||||
if (last == packer_code) {
|
||||
*save++ = (ubyte)packer_code;
|
||||
*save++ = (ubyte)(count - 1);
|
||||
packed_size += 2;
|
||||
|
||||
} else
|
||||
while (count--) {
|
||||
*save++ = (ubyte)last;
|
||||
packed_size++;
|
||||
}
|
||||
|
||||
} else {
|
||||
*save++ = (ubyte)packer_code;
|
||||
*save++ = (ubyte)(count - 1);
|
||||
*save++ = (ubyte)last;
|
||||
packed_size += 3;
|
||||
}
|
||||
|
||||
count = 0;
|
||||
last = pixel;
|
||||
}
|
||||
|
||||
frame++;
|
||||
count++;
|
||||
}
|
||||
|
||||
if (packed_size + 3 >= max)
|
||||
return -1;
|
||||
|
||||
if (count < 3) {
|
||||
if (last == packer_code) {
|
||||
*save++ = (ubyte)packer_code;
|
||||
*save++ = (ubyte)(count - 1);
|
||||
packed_size += 2;
|
||||
|
||||
} else
|
||||
while (count--) {
|
||||
*save++ = (ubyte)last;
|
||||
packed_size++;
|
||||
}
|
||||
|
||||
} else {
|
||||
*save++ = (ubyte)(packer_code);
|
||||
*save++ = (ubyte)(count - 1);
|
||||
*save++ = (ubyte)(last);
|
||||
packed_size += 3;
|
||||
}
|
||||
break;
|
||||
|
||||
case PACKING_METHOD_STD_RLE: { // high bit count regular RLE frame
|
||||
|
||||
ubyte *dest_start;
|
||||
|
||||
dest_start = save;
|
||||
count = 1;
|
||||
|
||||
if (*frame++ != *frame2++)
|
||||
last = *frame;
|
||||
else
|
||||
last = transparent_code;
|
||||
|
||||
*save++ = PACKING_METHOD_STD_RLE;
|
||||
for (i=1; i < size; i++ ) {
|
||||
|
||||
if (*frame != *frame2++)
|
||||
pixel = *frame;
|
||||
else
|
||||
pixel = transparent_code;
|
||||
|
||||
if ( pixel != last ) {
|
||||
if ( count ) {
|
||||
|
||||
if (packed_size + 2 >= max)
|
||||
return -1;
|
||||
|
||||
if ( (count == 1) && !(last & STD_RLE_CODE) ) {
|
||||
*save++ = (ubyte)last;
|
||||
packed_size++;
|
||||
Assert( last != STD_RLE_CODE );
|
||||
}
|
||||
else {
|
||||
count |= STD_RLE_CODE;
|
||||
*save++ = (ubyte)count;
|
||||
*save++ = (ubyte)last;
|
||||
packed_size += 2;
|
||||
}
|
||||
}
|
||||
|
||||
last = pixel;
|
||||
count = 0;
|
||||
}
|
||||
|
||||
count++;
|
||||
frame++;
|
||||
|
||||
if ( count == 127 ) {
|
||||
count |= STD_RLE_CODE;
|
||||
*save++ = (ubyte)count;
|
||||
*save++ = (ubyte)last;
|
||||
packed_size += 2;
|
||||
count = 0;
|
||||
}
|
||||
} // end for
|
||||
|
||||
if (count) {
|
||||
|
||||
if (packed_size + 2 >= max)
|
||||
return -1;
|
||||
|
||||
if ( (count == 1) && !(last & STD_RLE_CODE) ) {
|
||||
*save++ = (ubyte)last;
|
||||
packed_size++;
|
||||
Assert( last != STD_RLE_CODE );
|
||||
}
|
||||
else {
|
||||
count |= STD_RLE_CODE;
|
||||
*save++ = (ubyte)count;
|
||||
*save++ = (ubyte)last;
|
||||
packed_size += 2;
|
||||
}
|
||||
}
|
||||
|
||||
Assert(packed_size == (save-dest_start) );
|
||||
return packed_size;
|
||||
}
|
||||
|
||||
default:
|
||||
Assert(0);
|
||||
return -1;
|
||||
break;
|
||||
} // end switch
|
||||
|
||||
return packed_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert a 24 bit value to a 16 bit value
|
||||
* @param bit_24 24 bit value
|
||||
|
||||
@@ -97,16 +97,12 @@ typedef struct anim_instance {
|
||||
int loop_count; // starts at 0, and is incremented each time it loops
|
||||
} anim_instance;
|
||||
|
||||
int pack_key_frame(ubyte *frame, ubyte *save, long size, long max, int compress_type);
|
||||
int pack_frame(ubyte *frame, ubyte *frame2, ubyte *save, long size, long max, int compress_type);
|
||||
|
||||
ubyte *unpack_frame(anim_instance *ai, ubyte *ptr, ubyte *frame, int size, ubyte *pal_translate, int aabitmap, int bpp);
|
||||
int unpack_frame_from_file(anim_instance *ai, ubyte *frame, int size, ubyte *pal_translate, int aabitmap, int bpp);
|
||||
|
||||
void anim_init();
|
||||
anim_instance *init_anim_instance(anim *ptr, int bpp);
|
||||
void free_anim_instance(anim_instance *inst);
|
||||
int anim_get_next_frame(anim_instance *inst);
|
||||
ubyte *anim_get_next_raw_buffer(anim_instance *inst, int xlate_pal, int aabitmap, int bpp);
|
||||
void anim_set_palette(anim *a);
|
||||
void anim_check_for_palette_change(anim_instance *inst);
|
||||
|
||||
@@ -1263,7 +1263,7 @@ static float asteroid_create_explosion(object *objp)
|
||||
|
||||
fireball_scale_multiplier = asteroid_get_fireball_scale_multiplier(objp->instance);
|
||||
|
||||
fireball_objnum = fireball_create( &objp->pos, fireball_type, FIREBALL_LARGE_EXPLOSION, OBJ_INDEX(objp), objp->radius*fireball_scale_multiplier, 0, &objp->phys_info.vel );
|
||||
fireball_objnum = fireball_create( &objp->pos, fireball_type, FIREBALL_LARGE_EXPLOSION, OBJ_INDEX(objp), objp->radius*fireball_scale_multiplier, false, &objp->phys_info.vel );
|
||||
if ( fireball_objnum > -1 ) {
|
||||
explosion_life = fireball_lifeleft(&Objects[fireball_objnum]);
|
||||
} else {
|
||||
@@ -1387,7 +1387,7 @@ void asteroid_hit( object * pasteroid_obj, object * other_obj, vec3d * hitpos, f
|
||||
weapon_info *wip;
|
||||
wip = &Weapon_info[Weapons[other_obj->instance].weapon_info_index];
|
||||
// If the weapon didn't play any impact animation, play custom asteroid impact animation
|
||||
if ( wip->impact_weapon_expl_effect < 0 ) {
|
||||
if (!wip->impact_weapon_expl_effect.isValid()) {
|
||||
particle::create( hitpos, &vmd_zero_vector, 0.0f, Asteroid_impact_explosion_radius, particle::PARTICLE_BITMAP, Asteroid_impact_explosion_ani );
|
||||
}
|
||||
}
|
||||
@@ -1547,7 +1547,7 @@ static void asteroid_maybe_break_up(object *pasteroid_obj)
|
||||
}
|
||||
asp->final_death_time = timestamp(-1);
|
||||
}
|
||||
Script_system.RunCondition(CHA_DEATH, '\0', NULL, pasteroid_obj);
|
||||
Script_system.RunCondition(CHA_DEATH, pasteroid_obj);
|
||||
Script_system.RemHookVar("Self");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,31 +122,6 @@ vec3d *NavPoint::GetPosition()
|
||||
}
|
||||
}
|
||||
|
||||
char* NavPoint::GetInternalName()
|
||||
{
|
||||
char *NavName;
|
||||
char strtmp[33];
|
||||
|
||||
if (flags & NP_WAYPOINT)
|
||||
{
|
||||
NavName = new char[strlen(((waypoint_list*)target_obj)->get_name())+5];
|
||||
memset(NavName, 0, strlen(((waypoint_list*)target_obj)->get_name())+5);
|
||||
strcpy(NavName, ((waypoint_list*)target_obj)->get_name());
|
||||
|
||||
strcat(NavName, ":");
|
||||
sprintf(strtmp, "%d", waypoint_num);
|
||||
strcat(NavName, strtmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
NavName = new char[strlen(((ship*)target_obj)->ship_name)+1];
|
||||
memset(NavName, 0, strlen(((ship*)target_obj)->ship_name)+1);
|
||||
strcpy(NavName, ((ship*)target_obj)->ship_name);
|
||||
}
|
||||
|
||||
return NavName;
|
||||
}
|
||||
|
||||
// ********************************************************************************************
|
||||
bool CanAutopilot(vec3d targetPos, bool send_msg)
|
||||
{
|
||||
@@ -998,7 +973,6 @@ camera* nav_get_set_camera()
|
||||
return nav_camera.getCamera();
|
||||
}
|
||||
|
||||
extern int Cmdline_old_collision_sys;
|
||||
void nav_warp(bool prewarp=false)
|
||||
{
|
||||
/* ok... find our end distance - norm1 is still a unit vector in the
|
||||
@@ -1053,11 +1027,7 @@ void nav_warp(bool prewarp=false)
|
||||
}
|
||||
|
||||
// retime all collision pairs
|
||||
if ( Cmdline_old_collision_sys ) {
|
||||
obj_all_collisions_retime();
|
||||
} else {
|
||||
obj_collide_retime_cached_pairs();
|
||||
}
|
||||
obj_collide_retime_cached_pairs();
|
||||
}
|
||||
|
||||
// ********************************************************************************************
|
||||
@@ -1464,22 +1434,6 @@ bool AddNav_Waypoint(char *Nav, char *WP_Path, int node, int flags)
|
||||
}
|
||||
|
||||
// ********************************************************************************************
|
||||
//Change Flags
|
||||
bool Nav_Alt_Flags(char *Nav, int flags)
|
||||
{
|
||||
flags &= ~NP_VALIDTYPE; //clear the NP_SHIP and NP_WAYPOINT bits, make sure they haven't been set
|
||||
|
||||
int nav = FindNav(Nav);
|
||||
|
||||
if (nav != -1)
|
||||
{
|
||||
Navs[nav].flags &= NP_VALIDTYPE; // Clear all bits BUT NP_SHIP or NO_WAYPOINT
|
||||
Navs[nav].flags |= flags; // merge
|
||||
}
|
||||
|
||||
return (nav != -1);
|
||||
}
|
||||
|
||||
//Get Flags
|
||||
int Nav_Get_Flags(char *Nav)
|
||||
{
|
||||
|
||||
@@ -36,7 +36,6 @@ public:
|
||||
int waypoint_num; //only used when flags & NP_WAYPOINT
|
||||
|
||||
vec3d *GetPosition();
|
||||
char* GetInternalName();
|
||||
|
||||
void clear()
|
||||
{
|
||||
@@ -129,9 +128,6 @@ void SelectNav(char *Nav);
|
||||
// Deselects any navpoint selected.
|
||||
void DeselectNav();
|
||||
|
||||
// Set A Nav point to "ZERO"
|
||||
void ZeroNav(int i);
|
||||
|
||||
// Removes a Nav
|
||||
bool DelNavPoint(char *Nav);
|
||||
bool DelNavPoint(int nav);
|
||||
@@ -140,9 +136,6 @@ bool DelNavPoint(int nav);
|
||||
bool AddNav_Ship(char *Nav, char *TargetName, int flags);
|
||||
bool AddNav_Waypoint(char *Nav, char *WP_Path, int node, int flags);
|
||||
|
||||
//Change Flags
|
||||
bool Nav_Alt_Flags(char *Nav, int flags);
|
||||
|
||||
// Sexp Accessors
|
||||
bool Nav_Set_Flag(char *Nav, int flag);
|
||||
bool Nav_UnSet_Flag(char *Nav, int flag);
|
||||
|
||||
@@ -67,9 +67,7 @@ struct bitmap_entry {
|
||||
char filename[MAX_FILENAME_LEN]; //!< filename for this bitmap
|
||||
|
||||
uint signature; //!< a unique signature identifying the data
|
||||
uint palette_checksum; //!< checksum used to be sure bitmap is in current palette
|
||||
int handle; //!< Handle = id*MAX_BITMAPS + bitmapnum
|
||||
int last_used; //!< When this bitmap was last used
|
||||
|
||||
BM_TYPE type; //!< PCX, USER, ANI, etc
|
||||
BM_TYPE comp_type; //!< What sort of compressed type, BM_TYPE_NONE if not compressed
|
||||
|
||||
+17
-146
@@ -55,14 +55,7 @@ MONITOR(SizeBitmapPage)
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// Definition of public variables (declared as extern in bmpman.h).
|
||||
int GLOWMAP = -1;
|
||||
int SPECMAP = -1;
|
||||
int SPECGLOSSMAP = -1;
|
||||
int ENVMAP = -1;
|
||||
int NORMMAP = -1;
|
||||
int HEIGHTMAP = -1;
|
||||
int MISCMAP = -1;
|
||||
int AMBIENTMAP = -1;
|
||||
|
||||
size_t bm_texture_ram = 0;
|
||||
int Bm_paging = 0;
|
||||
@@ -80,11 +73,6 @@ const char *bm_ani_ext_list[] = { ".eff", ".ani", ".png" };
|
||||
const int BM_ANI_NUM_TYPES = sizeof(bm_ani_type_list) / sizeof(bm_ani_type_list[0]);
|
||||
|
||||
void(*bm_set_components)(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a) = NULL;
|
||||
void(*bm_set_components_32)(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a) = NULL;
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// Declaration of protected variables (defined in cmdline.cpp).
|
||||
extern int Cmdline_cache_bitmaps;
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
// Definition of public variables (declared as extern in bm_internal.h).
|
||||
@@ -193,42 +181,6 @@ float bitmap_lookup::map_texture_address(float address)
|
||||
return address - floorf(address);
|
||||
}
|
||||
|
||||
float bitmap_lookup::get_channel_red(float u, float v)
|
||||
{
|
||||
Assert( Bitmap_data != NULL );
|
||||
|
||||
CLAMP(u, 0.0f, 1.0f);
|
||||
CLAMP(v, 0.0f, 1.0f);
|
||||
|
||||
int x = fl2i(map_texture_address(u) * (Width-1));
|
||||
int y = fl2i(map_texture_address(v) * (Height-1));
|
||||
|
||||
return i2fl(Bitmap_data[(y*Width + x)*Num_channels]) / 255.0f;
|
||||
}
|
||||
|
||||
float bitmap_lookup::get_channel_green(float u, float v)
|
||||
{
|
||||
Assert( Bitmap_data != NULL );
|
||||
|
||||
CLAMP(u, 0.0, 1.0f);
|
||||
CLAMP(v, 0.0, 1.0f);
|
||||
|
||||
int x = fl2i(map_texture_address(u) * (Width-1));
|
||||
int y = fl2i(map_texture_address(v) * (Height-1));
|
||||
|
||||
return i2fl(Bitmap_data[(y*Width + x)*Num_channels + 1]) / 255.0f;
|
||||
}
|
||||
|
||||
float bitmap_lookup::get_channel_blue(float u, float v)
|
||||
{
|
||||
Assert( Bitmap_data != NULL );
|
||||
|
||||
int x = fl2i(map_texture_address(u) * (Width-1));
|
||||
int y = fl2i(map_texture_address(v) * (Height-1));
|
||||
|
||||
return i2fl(Bitmap_data[(y*Width + x)*Num_channels + 2]) / 255.0f;
|
||||
}
|
||||
|
||||
float bitmap_lookup::get_channel_alpha(float u, float v)
|
||||
{
|
||||
Assert( Bitmap_data != NULL );
|
||||
@@ -591,10 +543,9 @@ int bm_create(int bpp, int w, int h, void *data, int flags) {
|
||||
|
||||
memset(entry, 0, sizeof(bitmap_entry));
|
||||
|
||||
sprintf(entry->filename, "TMP%dx%d+%d", w, h, bpp);
|
||||
sprintf_safe(entry->filename, "TMP%dx%d+%d", w, h, bpp);
|
||||
entry->type = BM_TYPE_USER;
|
||||
entry->comp_type = BM_TYPE_NONE;
|
||||
entry->palette_checksum = 0;
|
||||
|
||||
entry->bm.w = (short)w;
|
||||
entry->bm.h = (short)h;
|
||||
@@ -612,7 +563,6 @@ int bm_create(int bpp, int w, int h, void *data, int flags) {
|
||||
entry->signature = Bm_next_signature++;
|
||||
|
||||
entry->handle = n;
|
||||
entry->last_used = -1;
|
||||
entry->mem_taken = (w * h * (bpp >> 3));
|
||||
|
||||
entry->load_count++;
|
||||
@@ -958,16 +908,6 @@ void bm_get_palette(int handle, ubyte *pal, char *name) {
|
||||
}
|
||||
}
|
||||
|
||||
uint bm_get_signature(int handle) {
|
||||
Assertion(bm_inited, "bmpman must be initialized before this function can be called!");
|
||||
|
||||
return bm_get_entry(handle)->signature;
|
||||
}
|
||||
|
||||
size_t bm_get_size(int handle) {
|
||||
return bm_get_entry(handle)->mem_taken;
|
||||
}
|
||||
|
||||
int bm_get_tcache_type(int num) {
|
||||
if (bm_is_compressed(num))
|
||||
return TCACHE_TYPE_COMPRESSED;
|
||||
@@ -1155,7 +1095,7 @@ static int bm_load_info(BM_TYPE type, const char *filename, CFILE *img_cfp, int
|
||||
}
|
||||
}
|
||||
else {
|
||||
Assertion(false, "Unknown file type specified! This is probably a coding error.");
|
||||
UNREACHABLE("Unknown file type specified! This is probably a coding error.");
|
||||
|
||||
return -1;
|
||||
}
|
||||
@@ -1253,7 +1193,7 @@ int bm_load(const char *real_filename) {
|
||||
|
||||
// Mark the slot as filled, because cf_read might load a new bitmap
|
||||
// into this slot.
|
||||
strncpy(entry->filename, filename, MAX_FILENAME_LEN - 1);
|
||||
strcpy_s(entry->filename, filename);
|
||||
entry->type = type;
|
||||
entry->comp_type = c_type;
|
||||
entry->signature = Bm_next_signature++;
|
||||
@@ -1268,9 +1208,7 @@ int bm_load(const char *real_filename) {
|
||||
entry->num_mipmaps = mm_lvl;
|
||||
entry->mem_taken = (size_t)bm_size;
|
||||
entry->dir_type = CF_TYPE_ANY;
|
||||
entry->palette_checksum = 0;
|
||||
entry->handle = handle;
|
||||
entry->last_used = -1;
|
||||
|
||||
entry->load_count++;
|
||||
|
||||
@@ -1681,7 +1619,7 @@ int bm_load_animation(const char *real_filename, int *nframes, int *fps, int *ke
|
||||
|
||||
if (type == BM_TYPE_EFF) {
|
||||
entry->info.ani.eff.type = eff_type;
|
||||
sprintf(entry->info.ani.eff.filename, "%s_%.4d", clean_name, i);
|
||||
sprintf_safe(entry->info.ani.eff.filename, "%s_%.4d", clean_name, i);
|
||||
|
||||
// bm_load_info() returns non-0 on failure
|
||||
if (bm_load_info(eff_type, entry->info.ani.eff.filename,
|
||||
@@ -1733,10 +1671,8 @@ int bm_load_animation(const char *real_filename, int *nframes, int *fps, int *ke
|
||||
entry->bm.palette = nullptr;
|
||||
entry->type = type;
|
||||
entry->comp_type = c_type;
|
||||
entry->palette_checksum = 0;
|
||||
entry->signature = Bm_next_signature++;
|
||||
entry->handle = n + i;
|
||||
entry->last_used = -1;
|
||||
entry->num_mipmaps = mm_lvl;
|
||||
entry->mem_taken = (size_t)img_size;
|
||||
entry->dir_type = dir_type;
|
||||
@@ -1744,13 +1680,13 @@ int bm_load_animation(const char *real_filename, int *nframes, int *fps, int *ke
|
||||
entry->load_count++;
|
||||
|
||||
if (i == 0) {
|
||||
sprintf(entry->filename, "%s", filename);
|
||||
sprintf_safe(entry->filename, "%s", filename);
|
||||
} else {
|
||||
if (type == BM_TYPE_PNG) {
|
||||
sprintf(entry->filename, "%s_%04d", filename, i);
|
||||
sprintf_safe(entry->filename, "%s_%04d", filename, i);
|
||||
}
|
||||
else {
|
||||
sprintf(entry->filename, "%s[%d]", filename, i);
|
||||
sprintf_safe(entry->filename, "%s[%d]", filename, i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1876,27 +1812,23 @@ int bm_load_sub_fast(const char *real_filename, int *handle, int dir_type, bool
|
||||
}
|
||||
|
||||
int bm_load_sub_slow(const char *real_filename, const int num_ext, const char **ext_list, CFILE **img_cfp, int dir_type) {
|
||||
char full_path[MAX_PATH];
|
||||
size_t size = 0, offset = 0;
|
||||
int rval = -1;
|
||||
const void* file_data = nullptr;
|
||||
|
||||
rval = cf_find_file_location_ext(real_filename, num_ext, ext_list, dir_type, sizeof(full_path) - 1, full_path, &size, &offset, 0, &file_data);
|
||||
auto res = cf_find_file_location_ext(real_filename, num_ext, ext_list, dir_type, false);
|
||||
|
||||
// could not be found, or is invalid for some reason
|
||||
if ((rval < 0) || (rval >= num_ext))
|
||||
if (!res.found)
|
||||
return -1;
|
||||
|
||||
CFILE *test = cfopen_special(full_path, "rb", size, offset, file_data, dir_type);
|
||||
CFILE *test = cfopen_special(res.full_name.c_str(), "rb", res.size, res.offset, res.data_ptr, dir_type);
|
||||
|
||||
if (test != NULL) {
|
||||
if (img_cfp != NULL)
|
||||
*img_cfp = test;
|
||||
|
||||
return rval;
|
||||
return res.extension_index;
|
||||
}
|
||||
|
||||
// umm, that's not good...
|
||||
Warning(LOCATION, "Could not open file %s!", res.full_name.c_str());
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1983,8 +1915,6 @@ bitmap * bm_lock(int handle, int bpp, ubyte flags, bool nodebug) {
|
||||
// Mark all the bitmaps in this bitmap or animation as recently used
|
||||
auto frame_entry = bm_get_entry(first + i);
|
||||
|
||||
frame_entry->last_used = timer_get_milliseconds();
|
||||
|
||||
#ifdef BMPMAN_NDEBUG
|
||||
// Mark all the bitmaps in this bitmap or animation as used for the usage tracker.
|
||||
frame_entry->used_count++;
|
||||
@@ -1993,9 +1923,6 @@ bitmap * bm_lock(int handle, int bpp, ubyte flags, bool nodebug) {
|
||||
frame_entry->used_flags = flags;
|
||||
}
|
||||
} else {
|
||||
// Mark all the bitmaps in this bitmap or animation as recently used
|
||||
be->last_used = timer_get_milliseconds();
|
||||
|
||||
#ifdef BMPMAN_NDEBUG
|
||||
// Mark all the bitmaps in this bitmap or animation as used for the usage tracker.
|
||||
be->used_count++;
|
||||
@@ -2385,7 +2312,7 @@ void bm_lock_png(int handle, bitmap_slot *bs, bitmap *bmp, int /*bpp*/, ubyte /*
|
||||
|
||||
void bm_lock_tga(int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags) {
|
||||
ubyte *data = NULL;
|
||||
int d_size, byte_size;
|
||||
int byte_size;
|
||||
char filename[MAX_FILENAME_LEN];
|
||||
|
||||
auto be = &bs->entry;
|
||||
@@ -2393,6 +2320,8 @@ void bm_lock_tga(int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags)
|
||||
// Unload any existing data
|
||||
bm_free_data(bs);
|
||||
|
||||
bpp = be->bm.true_bpp;
|
||||
|
||||
if (Is_standalone) {
|
||||
Assert(bpp == 8);
|
||||
} else {
|
||||
@@ -2409,7 +2338,6 @@ void bm_lock_tga(int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags)
|
||||
|
||||
if (data) {
|
||||
memset(data, 0, be->mem_taken);
|
||||
d_size = byte_size;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
@@ -2429,7 +2357,7 @@ void bm_lock_tga(int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags)
|
||||
// this will populate filename[] whether it's EFF or not
|
||||
EFF_FILENAME_CHECK;
|
||||
|
||||
tga_error = targa_read_bitmap(filename, data, NULL, d_size, be->dir_type);
|
||||
tga_error = targa_read_bitmap(filename, data, nullptr, byte_size, be->dir_type);
|
||||
|
||||
if (tga_error != TARGA_ERROR_NONE) {
|
||||
bm_free_data(bs);
|
||||
@@ -2526,7 +2454,7 @@ int bm_make_render_target(int width, int height, int flags) {
|
||||
|
||||
entry->type = (flags & BMP_FLAG_RENDER_TARGET_STATIC) ? BM_TYPE_RENDER_TARGET_STATIC : BM_TYPE_RENDER_TARGET_DYNAMIC;
|
||||
entry->signature = Bm_next_signature++;
|
||||
sprintf(entry->filename, "RT_%dx%d+%d", w, h, bpp);
|
||||
sprintf_safe(entry->filename, "RT_%dx%d+%d", w, h, bpp);
|
||||
entry->bm.w = (short)w;
|
||||
entry->bm.h = (short)h;
|
||||
entry->bm.rowsize = (short)w;
|
||||
@@ -2539,9 +2467,7 @@ int bm_make_render_target(int width, int height, int flags) {
|
||||
entry->mem_taken = (size_t)size;
|
||||
entry->dir_type = CF_TYPE_ANY;
|
||||
|
||||
entry->palette_checksum = 0;
|
||||
entry->handle = n;
|
||||
entry->last_used = -1;
|
||||
|
||||
if (entry->mem_taken) {
|
||||
entry->bm.data = (ptr_u)bm_malloc(n, entry->mem_taken);
|
||||
@@ -2589,9 +2515,6 @@ void bm_page_in_start() {
|
||||
for (auto& slot : block) {
|
||||
auto& entry = slot.entry;
|
||||
|
||||
if (!Cmdline_cache_bitmaps && (entry.type != BM_TYPE_NONE)) {
|
||||
bm_unload_fast(entry.handle);
|
||||
}
|
||||
entry.preloaded = 0;
|
||||
entry.preload_count = 0;
|
||||
#ifdef BMPMAN_NDEBUG
|
||||
@@ -2781,30 +2704,6 @@ void bm_page_in_xparent_texture(int bitmapnum, int nframes) {
|
||||
}
|
||||
}
|
||||
|
||||
bool bm_page_out(int handle) {
|
||||
auto entry = bm_get_entry(handle);
|
||||
|
||||
// in case it's already been released
|
||||
if (entry->type == BM_TYPE_NONE)
|
||||
return 0;
|
||||
|
||||
// it's possible to hit < 0 here when model_page_out_textures() is
|
||||
// called from anywhere other than in a mission
|
||||
if (entry->preload_count > 0) {
|
||||
nprintf(("BmpMan",
|
||||
"PAGE-OUT: %s - preload_count remaining: %d\n",
|
||||
entry->filename,
|
||||
entry->preload_count));
|
||||
|
||||
// lets decrease it for next time around
|
||||
entry->preload_count--;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (bm_unload(handle) == 1);
|
||||
}
|
||||
|
||||
void bm_print_bitmaps() {
|
||||
#ifdef BMPMAN_NDEBUG
|
||||
for (auto& block : bm_blocks) {
|
||||
@@ -2890,7 +2789,6 @@ int bm_release(int handle, int clear_render_targets) {
|
||||
// For debugging:
|
||||
strcpy_s(entry->filename, "IVE_BEEN_RELEASED!");
|
||||
entry->signature = 0xDEADBEEF; // a unique signature identifying the data
|
||||
entry->palette_checksum = 0xDEADBEEF; // checksum used to be sure bitmap is in current palette
|
||||
|
||||
// bookeeping
|
||||
entry->ref_count = -1; // Number of locks on bitmap. Can't unload unless ref_count is 0.
|
||||
@@ -2917,7 +2815,6 @@ int bm_release(int handle, int clear_render_targets) {
|
||||
// For debugging:
|
||||
strcpy_s(entry->filename, "IVE_BEEN_RELEASED!");
|
||||
entry->signature = 0xDEADBEEF; // a unique signature identifying the data
|
||||
entry->palette_checksum = 0xDEADBEEF; // checksum used to be sure bitmap is in current palette
|
||||
|
||||
// bookeeping
|
||||
entry->ref_count = -1; // Number of locks on bitmap. Can't unload unless ref_count is 0.
|
||||
@@ -2959,7 +2856,6 @@ void BM_SELECT_ALPHA_TEX_FORMAT() {
|
||||
Gr_current_alpha = &Gr_ta_alpha;
|
||||
|
||||
// setup pointers
|
||||
bm_set_components_32 = bm_set_components_argb_32_tex;
|
||||
// should always assume that 16-bit is the default request
|
||||
bm_set_components = bm_set_components_argb_16_tex;
|
||||
}
|
||||
@@ -2971,7 +2867,6 @@ void BM_SELECT_SCREEN_FORMAT() {
|
||||
Gr_current_alpha = &Gr_alpha;
|
||||
|
||||
// setup pointers
|
||||
bm_set_components_32 = bm_set_components_argb_32_screen;
|
||||
// should always assume that 16-bit is the default request
|
||||
bm_set_components = bm_set_components_argb_16_screen;
|
||||
}
|
||||
@@ -2983,7 +2878,6 @@ void BM_SELECT_TEX_FORMAT() {
|
||||
Gr_current_alpha = &Gr_t_alpha;
|
||||
|
||||
// setup pointers
|
||||
bm_set_components_32 = bm_set_components_argb_32_tex;
|
||||
// should always assume that 16-bit is the default request
|
||||
bm_set_components = bm_set_components_argb_16_tex;
|
||||
}
|
||||
@@ -3011,29 +2905,6 @@ void bm_set_components_argb_16_tex(ubyte *pixel, ubyte *rv, ubyte *gv, ubyte *bv
|
||||
*((unsigned short*)pixel) |= (unsigned short)(Gr_current_alpha->mask);
|
||||
}
|
||||
|
||||
void bm_set_components_argb_32_screen(ubyte *pixel, ubyte *rv, ubyte *gv, ubyte *bv, ubyte *av) {
|
||||
if (*av == 0) {
|
||||
*((unsigned int*)pixel) = (unsigned int)Gr_current_green->mask;
|
||||
return;
|
||||
}
|
||||
|
||||
*((unsigned int*)pixel) = (unsigned int)(((int)*rv / Gr_current_red->scale) << Gr_current_red->shift);
|
||||
*((unsigned int*)pixel) |= (unsigned int)(((int)*gv / Gr_current_green->scale) << Gr_current_green->shift);
|
||||
*((unsigned int*)pixel) |= (unsigned int)(((int)*bv / Gr_current_blue->scale) << Gr_current_blue->shift);
|
||||
}
|
||||
|
||||
void bm_set_components_argb_32_tex(ubyte *pixel, ubyte *rv, ubyte *gv, ubyte *bv, ubyte *av) {
|
||||
if (*av == 0) {
|
||||
*((unsigned int*)pixel) = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
*((unsigned int*)pixel) = (unsigned int)(((int)*rv / Gr_current_red->scale) << Gr_current_red->shift);
|
||||
*((unsigned int*)pixel) |= (unsigned int)(((int)*gv / Gr_current_green->scale) << Gr_current_green->shift);
|
||||
*((unsigned int*)pixel) |= (unsigned int)(((int)*bv / Gr_current_blue->scale) << Gr_current_blue->shift);
|
||||
*((unsigned int*)pixel) |= (unsigned int)(Gr_current_alpha->mask);
|
||||
}
|
||||
|
||||
void bm_set_low_mem(int mode) {
|
||||
Assert((mode >= 0) && (mode <= 2));
|
||||
|
||||
|
||||
@@ -113,12 +113,7 @@ extern const BM_TYPE bm_ani_type_list[]; //!< List of valid bitmap animation t
|
||||
extern const char *bm_ani_ext_list[]; //!< List of extensions for those types
|
||||
extern const int BM_ANI_NUM_TYPES; //!< Calculated number of bitmap animation types
|
||||
|
||||
extern int GLOWMAP; //!< References a map that is a fully lit version of its index -Bobboau
|
||||
extern int SPECMAP; //!< References a map that is for specular mapping -Bobboau
|
||||
extern int ENVMAP; //!< References a map that is for environment mapping -Bobboau
|
||||
extern int NORMMAP; //!< Normal mapping
|
||||
extern int HEIGHTMAP; //!< Height map for normal mapping
|
||||
extern int MISCMAP; //!< Utility map, to be utilized for various things shader authors can come up with
|
||||
|
||||
/**
|
||||
* @brief Initilizes the bitmap manager
|
||||
@@ -167,9 +162,6 @@ public:
|
||||
|
||||
bool valid();
|
||||
|
||||
float get_channel_red(float u, float v);
|
||||
float get_channel_green(float u, float v);
|
||||
float get_channel_blue(float u, float v);
|
||||
float get_channel_alpha(float u, float v);
|
||||
};
|
||||
|
||||
@@ -311,13 +303,6 @@ int bm_load_either(const char *filename, int *nframes = NULL, int *fps = NULL, i
|
||||
*/
|
||||
bitmap* bm_lock(int handle, int bpp, ubyte flags, bool nodebug = false);
|
||||
|
||||
/**
|
||||
* @brief Returns a unique signiature for the bitmap indexed by handle
|
||||
*
|
||||
* @details A signature will change when the bitmap's data changes
|
||||
*/
|
||||
uint bm_get_signature(int handle);
|
||||
|
||||
/**
|
||||
* @brief Returns the image type of the given bitmap handle
|
||||
*/
|
||||
@@ -459,15 +444,6 @@ void bm_page_in_xparent_texture(int bitmapnum, int num_frames = 1);
|
||||
*/
|
||||
void bm_page_in_aabitmap(int bitmapnum, int num_frames = 1);
|
||||
|
||||
/**
|
||||
* @brief Unloads the bitmap indexed by handle that was previously paged-in
|
||||
*
|
||||
* @returns 0 If the bitmap had already been released, or
|
||||
* @returns 0 If the handle is invalid, or
|
||||
* @returns 1 If successful
|
||||
*/
|
||||
bool bm_page_out(int handle);
|
||||
|
||||
/**
|
||||
* @brief Sets BMPMAN's memory mode
|
||||
*
|
||||
@@ -516,16 +492,6 @@ void BM_SELECT_ALPHA_TEX_FORMAT();
|
||||
*/
|
||||
extern void(*bm_set_components)(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
|
||||
|
||||
/**
|
||||
* @brief Functional pointer that references any of the bm_set_components_32 functions.
|
||||
*
|
||||
* @details The bm_set_components functions packs the RGBA values into the ubyte array referenced by pixel, whose
|
||||
* format differs according to its bpp value and presence of an alpha channel. The RGBA values are scaled accordingly.
|
||||
*
|
||||
* @see bm_set_components
|
||||
*/
|
||||
extern void(*bm_set_components_32)(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
|
||||
|
||||
/**
|
||||
* @brief Sets the 16bpp screen pixel to the specified RGBA value
|
||||
*
|
||||
@@ -533,13 +499,6 @@ extern void(*bm_set_components_32)(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, u
|
||||
*/
|
||||
void bm_set_components_argb_16_screen(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
|
||||
|
||||
/**
|
||||
* @brief Sets the 32bpp screen pixel to the specified RGBA value
|
||||
*
|
||||
* @see bm_set_components
|
||||
*/
|
||||
void bm_set_components_argb_32_screen(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
|
||||
|
||||
/**
|
||||
* @brief Sets the 16bpp texture pixel to the specified RGBA value
|
||||
*
|
||||
@@ -561,15 +520,7 @@ void bm_set_components_argb_32_tex(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, u
|
||||
*/
|
||||
void bm_get_components(ubyte *pixel, ubyte *r, ubyte *g, ubyte *b, ubyte *a);
|
||||
|
||||
extern int UNLITMAP; //this holds a reference to a map that is optional used instead of the base map for unlit rendering
|
||||
extern int GLOWMAP; //this holds a reference to a map that is a fully lit version of its index -Bobboau
|
||||
extern int SPECMAP; //this holds a reference to a map that is for specular mapping -Bobboau
|
||||
extern int SPECGLOSSMAP; //this holds a reference to a map that is for specular mapping -Bobboau
|
||||
extern int ENVMAP; //this holds a reference to a map that is for environment mapping -Bobboau
|
||||
extern int NORMMAP; // normal mapping
|
||||
extern int HEIGHTMAP; // height map for normal mapping
|
||||
extern int AMBIENTMAP; // ambient occluion map. red channel affects ambient lighting, green channel affects diffuse and specular
|
||||
extern int MISCMAP; // Utility map, to be utilized for various things shader authors can come up with
|
||||
|
||||
/**
|
||||
* @brief Returns the compression type of the bitmap indexed by handle
|
||||
@@ -581,10 +532,6 @@ int bm_is_compressed(int handle);
|
||||
*/
|
||||
int bm_get_tcache_type(int handle);
|
||||
|
||||
/**
|
||||
* @brief Gets the size, in bytes, taken up by the bitmap indexed by handle
|
||||
*/
|
||||
size_t bm_get_size(int handle);
|
||||
|
||||
/**
|
||||
* @brief Gets the number of mipmaps of the indexed texture
|
||||
|
||||
+3
-15
@@ -145,7 +145,7 @@ void camera::set_object_target(object *objp, int n_object_target_submodel)
|
||||
* Custom function receives the already-modified current position value.
|
||||
* It should be replaced or added to as the custom function modifier sees fit.
|
||||
*/
|
||||
void camera::set_custom_position_function(void (*n_func_custom_position)(camera *cam, vec3d *camera_pos))
|
||||
void camera::set_custom_position_function(void (*n_func_custom_position)(camera* /*cam*/, vec3d* /*camera_pos*/))
|
||||
{
|
||||
func_custom_position = n_func_custom_position;
|
||||
}
|
||||
@@ -154,7 +154,7 @@ void camera::set_custom_position_function(void (*n_func_custom_position)(camera
|
||||
* Custom function receives the already-modified current orientation value.
|
||||
* It should be replaced or added to as the custom function modifier sees fit.
|
||||
*/
|
||||
void camera::set_custom_orientation_function(void (*n_func_custom_orientation)(camera *cam, matrix *camera_ori))
|
||||
void camera::set_custom_orientation_function(void (*n_func_custom_orientation)(camera* /*cam*/, matrix* /*camera_ori*/))
|
||||
{
|
||||
func_custom_orientation = n_func_custom_orientation;
|
||||
}
|
||||
@@ -185,13 +185,6 @@ void camera::set_position(vec3d *in_position, float in_translation_time, float i
|
||||
pos_z.setAVD(in_position->xyz.z, in_translation_time, in_translation_acceleration_time, in_translation_deceleration_time, in_end_velocity);
|
||||
}
|
||||
|
||||
void camera::set_translation_velocity(vec3d *in_velocity, float in_acceleration_time)
|
||||
{
|
||||
pos_x.setVD(in_acceleration_time, in_acceleration_time, in_velocity->xyz.x);
|
||||
pos_y.setVD(in_acceleration_time, in_acceleration_time, in_velocity->xyz.y);
|
||||
pos_z.setVD(in_acceleration_time, in_acceleration_time, in_velocity->xyz.z);
|
||||
}
|
||||
|
||||
void camera::set_rotation(matrix *in_orientation, float in_rotation_time, float in_rotation_acceleration_time, float in_rotation_deceleration_time)
|
||||
{
|
||||
if(in_orientation != NULL && in_rotation_time == 0.0f && in_rotation_acceleration_time == 0.0f && in_rotation_deceleration_time == 0.0f)
|
||||
@@ -245,11 +238,6 @@ void camera::set_rotation_facing(vec3d *in_target, float in_rotation_time, float
|
||||
set_rotation(&temp_matrix, in_rotation_time, in_rotation_acceleration_time, in_rotation_deceleration_time);
|
||||
}
|
||||
|
||||
void camera::set_rotation_velocity(angles * /*in_rotation_rate*/, float /*in_acceleration_time*/)
|
||||
{
|
||||
Error(LOCATION, "This function is disabled until further notice.");
|
||||
}
|
||||
|
||||
void camera::do_frame(float /*in_frametime*/)
|
||||
{
|
||||
|
||||
@@ -962,7 +950,7 @@ size_t cam_get_num()
|
||||
/**
|
||||
* Looks up camera by name, returns -1 on failure
|
||||
*/
|
||||
camid cam_lookup(char *name)
|
||||
camid cam_lookup(const char* name)
|
||||
{
|
||||
size_t i, size=Cameras.size();
|
||||
for(i = 0; i < size; i++)
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
class camera
|
||||
{
|
||||
friend class avd_camera;
|
||||
protected:
|
||||
char name[NAME_LENGTH];
|
||||
int sig;
|
||||
@@ -60,15 +59,13 @@ public:
|
||||
void set_fov(float in_fov, float in_fov_time = 0.0f, float in_fov_acceleration_time = 0.0f, float in_deceleration_time = 0.0f);
|
||||
|
||||
void set_position(vec3d *in_position = NULL, float in_translation_time = 0.0f, float in_translation_acceleration_time = 0.0f, float in_translation_deceleration_time = 0.0f, float in_end_velocity = 0.0f);
|
||||
void set_translation_velocity(vec3d *in_velocity, float in_acceleration_time = 0.0f);
|
||||
|
||||
void set_rotation(matrix *in_orientation = NULL, float in_rotation_time = 0.0f, float in_rotation_acceleration_time = 0.0f, float in_rotation_deceleration_time = 0.0f);
|
||||
void set_rotation(angles *in_angles, float in_rotation_time = 0.0f, float in_rotation_acceleration_time = 0.0f, float in_rotation_deceleration_time = 0.0f);
|
||||
void set_rotation_facing(vec3d *in_target, float in_rotation_time = 0.0f, float in_rotation_acceleration_time = 0.0f, float in_rotation_deceleration_time = 0.0f);
|
||||
void set_rotation_velocity(angles *in_rotation_rate, float in_acceleration_time = 0.0f);
|
||||
|
||||
//Get
|
||||
char *get_name() {return name;}
|
||||
const char* get_name() { return name; }
|
||||
int get_signature() {return sig;}
|
||||
object *get_object_host();
|
||||
int get_object_host_submodel();
|
||||
@@ -163,7 +160,7 @@ camid cam_create(const char *n_name, vec3d *n_pos, vec3d *n_norm, object *n_obje
|
||||
void cam_delete(camid cid);
|
||||
bool cam_set_camera(camid cid);
|
||||
void cam_reset_camera();
|
||||
camid cam_lookup(char *name);
|
||||
camid cam_lookup(const char* name);
|
||||
camid cam_get_camera(uint index);
|
||||
camid cam_get_current();
|
||||
size_t cam_get_num();
|
||||
|
||||
+120
-149
@@ -33,70 +33,66 @@
|
||||
#include "cfile/cfilesystem.h"
|
||||
#include "osapi/osapi.h"
|
||||
#include "parse/encrypt.h"
|
||||
#include "cfilesystem.h"
|
||||
|
||||
|
||||
#include <limits>
|
||||
|
||||
char Cfile_root_dir[CFILE_ROOT_DIRECTORY_LEN] = "";
|
||||
char Cfile_user_dir[CFILE_ROOT_DIRECTORY_LEN] = "";
|
||||
#ifdef SCP_UNIX
|
||||
char Cfile_user_dir_legacy[CFILE_ROOT_DIRECTORY_LEN] = "";
|
||||
#endif
|
||||
|
||||
// During cfile_init, verify that Pathtypes[n].index == n for each item
|
||||
// Each path must have a valid parent that can be tracable all the way back to the root
|
||||
// Each path must have a valid parent that can be tracable all the way back to the root
|
||||
// so that we can create directories when we need to.
|
||||
//
|
||||
// Please make sure extensions are all lower-case, or we'll break unix compatibility
|
||||
//
|
||||
cf_pathtype Pathtypes[CF_MAX_PATH_TYPES] = {
|
||||
// What type this is Path Extensions Parent
|
||||
// type
|
||||
{CF_TYPE_INVALID, NULL, NULL, CF_TYPE_INVALID},
|
||||
// Root must be index 1!!
|
||||
{CF_TYPE_ROOT, "", ".mve .ogg", CF_TYPE_ROOT},
|
||||
{CF_TYPE_DATA, "data", ".cfg .txt", CF_TYPE_ROOT},
|
||||
{CF_TYPE_MAPS, "data" DIR_SEPARATOR_STR "maps", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA},
|
||||
{CF_TYPE_TEXT, "data" DIR_SEPARATOR_STR "text", ".txt .net", CF_TYPE_DATA},
|
||||
{CF_TYPE_MODELS, "data" DIR_SEPARATOR_STR "models", ".pof", CF_TYPE_DATA},
|
||||
{CF_TYPE_TABLES, "data" DIR_SEPARATOR_STR "tables", ".tbl .tbm", CF_TYPE_DATA},
|
||||
{CF_TYPE_SOUNDS, "data" DIR_SEPARATOR_STR "sounds", ".wav .ogg", CF_TYPE_DATA},
|
||||
{CF_TYPE_SOUNDS_8B22K, "data" DIR_SEPARATOR_STR "sounds" DIR_SEPARATOR_STR "8b22k", ".wav .ogg", CF_TYPE_SOUNDS},
|
||||
{CF_TYPE_SOUNDS_16B11K, "data" DIR_SEPARATOR_STR "sounds" DIR_SEPARATOR_STR "16b11k", ".wav .ogg", CF_TYPE_SOUNDS},
|
||||
{CF_TYPE_VOICE, "data" DIR_SEPARATOR_STR "voice", "", CF_TYPE_DATA},
|
||||
{CF_TYPE_VOICE_BRIEFINGS, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "briefing", ".wav .ogg",
|
||||
CF_TYPE_VOICE},
|
||||
{CF_TYPE_VOICE_CMD_BRIEF, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "command_briefings", ".wav .ogg",
|
||||
CF_TYPE_VOICE},
|
||||
{CF_TYPE_VOICE_DEBRIEFINGS, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "debriefing", ".wav .ogg",
|
||||
CF_TYPE_VOICE},
|
||||
{CF_TYPE_VOICE_PERSONAS, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "personas", ".wav .ogg", CF_TYPE_VOICE},
|
||||
{CF_TYPE_VOICE_SPECIAL, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "special", ".wav .ogg", CF_TYPE_VOICE},
|
||||
{CF_TYPE_VOICE_TRAINING, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "training", ".wav .ogg", CF_TYPE_VOICE},
|
||||
{CF_TYPE_MUSIC, "data" DIR_SEPARATOR_STR "music", ".wav .ogg", CF_TYPE_DATA},
|
||||
{CF_TYPE_MOVIES, "data" DIR_SEPARATOR_STR "movies", ".mve .msb .ogg .mp4 .srt", CF_TYPE_DATA},
|
||||
{CF_TYPE_INTERFACE, "data" DIR_SEPARATOR_STR "interface", ".pcx .ani .dds .tga .eff .png .jpg", CF_TYPE_DATA},
|
||||
{CF_TYPE_FONT, "data" DIR_SEPARATOR_STR "fonts", ".vf .ttf", CF_TYPE_DATA},
|
||||
{CF_TYPE_EFFECTS, "data" DIR_SEPARATOR_STR "effects", ".ani .eff .pcx .neb .tga .jpg .png .dds .sdr", CF_TYPE_DATA},
|
||||
{CF_TYPE_HUD, "data" DIR_SEPARATOR_STR "hud", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA},
|
||||
{CF_TYPE_PLAYERS, "data" DIR_SEPARATOR_STR "players", ".hcf", CF_TYPE_DATA},
|
||||
{CF_TYPE_PLAYER_IMAGES, "data" DIR_SEPARATOR_STR "players" DIR_SEPARATOR_STR "images", ".pcx .png .dds",
|
||||
CF_TYPE_PLAYERS},
|
||||
{CF_TYPE_SQUAD_IMAGES, "data" DIR_SEPARATOR_STR "players" DIR_SEPARATOR_STR "squads", ".pcx .png .dds",
|
||||
CF_TYPE_PLAYERS},
|
||||
{CF_TYPE_SINGLE_PLAYERS, "data" DIR_SEPARATOR_STR "players" DIR_SEPARATOR_STR "single", ".pl2 .cs2 .plr .csg .css",
|
||||
CF_TYPE_PLAYERS},
|
||||
{CF_TYPE_MULTI_PLAYERS, "data" DIR_SEPARATOR_STR "players" DIR_SEPARATOR_STR "multi", ".plr", CF_TYPE_PLAYERS},
|
||||
{CF_TYPE_CACHE, "data" DIR_SEPARATOR_STR "cache", ".clr .tmp .bx", CF_TYPE_DATA}, // clr=cached color
|
||||
{CF_TYPE_MULTI_CACHE, "data" DIR_SEPARATOR_STR "multidata", ".pcx .png .dds .fs2 .txt", CF_TYPE_DATA},
|
||||
{CF_TYPE_MISSIONS, "data" DIR_SEPARATOR_STR "missions", ".fs2 .fc2 .ntl .ssv", CF_TYPE_DATA},
|
||||
{CF_TYPE_CONFIG, "data" DIR_SEPARATOR_STR "config", ".cfg .tbl .tbm .xml .csv", CF_TYPE_DATA},
|
||||
{CF_TYPE_DEMOS, "data" DIR_SEPARATOR_STR "demos", ".fsd", CF_TYPE_DATA},
|
||||
{CF_TYPE_CBANIMS, "data" DIR_SEPARATOR_STR "cbanims", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA},
|
||||
{CF_TYPE_INTEL_ANIMS, "data" DIR_SEPARATOR_STR "intelanims", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA},
|
||||
{CF_TYPE_SCRIPTS, "data" DIR_SEPARATOR_STR "scripts", ".lua .lc", CF_TYPE_DATA},
|
||||
{CF_TYPE_FICTION, "data" DIR_SEPARATOR_STR "fiction", ".txt", CF_TYPE_DATA},
|
||||
{CF_TYPE_FREDDOCS, "data" DIR_SEPARATOR_STR "freddocs", ".html", CF_TYPE_DATA},
|
||||
// clang-format off
|
||||
cf_pathtype Pathtypes[CF_MAX_PATH_TYPES] = {
|
||||
// What type this is Path Extensions Parent type
|
||||
{ CF_TYPE_INVALID, NULL, NULL, CF_TYPE_INVALID },
|
||||
// Root must be index 1!!
|
||||
{ CF_TYPE_ROOT, "", ".mve .ogg", CF_TYPE_ROOT },
|
||||
{ CF_TYPE_DATA, "data", ".cfg .txt", CF_TYPE_ROOT },
|
||||
{ CF_TYPE_MAPS, "data" DIR_SEPARATOR_STR "maps", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA },
|
||||
{ CF_TYPE_TEXT, "data" DIR_SEPARATOR_STR "text", ".txt .net", CF_TYPE_DATA },
|
||||
{ CF_TYPE_MODELS, "data" DIR_SEPARATOR_STR "models", ".pof", CF_TYPE_DATA },
|
||||
{ CF_TYPE_TABLES, "data" DIR_SEPARATOR_STR "tables", ".tbl .tbm", CF_TYPE_DATA },
|
||||
{ CF_TYPE_SOUNDS, "data" DIR_SEPARATOR_STR "sounds", ".wav .ogg", CF_TYPE_DATA },
|
||||
{ CF_TYPE_SOUNDS_8B22K, "data" DIR_SEPARATOR_STR "sounds" DIR_SEPARATOR_STR "8b22k", ".wav .ogg", CF_TYPE_SOUNDS },
|
||||
{ CF_TYPE_SOUNDS_16B11K, "data" DIR_SEPARATOR_STR "sounds" DIR_SEPARATOR_STR "16b11k", ".wav .ogg", CF_TYPE_SOUNDS },
|
||||
{ CF_TYPE_VOICE, "data" DIR_SEPARATOR_STR "voice", "", CF_TYPE_DATA },
|
||||
{ CF_TYPE_VOICE_BRIEFINGS, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "briefing", ".wav .ogg", CF_TYPE_VOICE },
|
||||
{ CF_TYPE_VOICE_CMD_BRIEF, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "command_briefings", ".wav .ogg", CF_TYPE_VOICE },
|
||||
{ CF_TYPE_VOICE_DEBRIEFINGS, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "debriefing", ".wav .ogg", CF_TYPE_VOICE },
|
||||
{ CF_TYPE_VOICE_PERSONAS, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "personas", ".wav .ogg", CF_TYPE_VOICE },
|
||||
{ CF_TYPE_VOICE_SPECIAL, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "special", ".wav .ogg", CF_TYPE_VOICE },
|
||||
{ CF_TYPE_VOICE_TRAINING, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "training", ".wav .ogg", CF_TYPE_VOICE },
|
||||
{ CF_TYPE_MUSIC, "data" DIR_SEPARATOR_STR "music", ".wav .ogg", CF_TYPE_DATA },
|
||||
{ CF_TYPE_MOVIES, "data" DIR_SEPARATOR_STR "movies", ".mve .msb .ogg .mp4 .srt .webm .png",CF_TYPE_DATA },
|
||||
{ CF_TYPE_INTERFACE, "data" DIR_SEPARATOR_STR "interface", ".pcx .ani .dds .tga .eff .png .jpg", CF_TYPE_DATA },
|
||||
{ CF_TYPE_FONT, "data" DIR_SEPARATOR_STR "fonts", ".vf .ttf", CF_TYPE_DATA },
|
||||
{ CF_TYPE_EFFECTS, "data" DIR_SEPARATOR_STR "effects", ".ani .eff .pcx .neb .tga .jpg .png .dds .sdr", CF_TYPE_DATA },
|
||||
{ CF_TYPE_HUD, "data" DIR_SEPARATOR_STR "hud", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA },
|
||||
{ CF_TYPE_PLAYERS, "data" DIR_SEPARATOR_STR "players", ".hcf", CF_TYPE_DATA },
|
||||
{ CF_TYPE_PLAYER_IMAGES, "data" DIR_SEPARATOR_STR "players" DIR_SEPARATOR_STR "images", ".pcx .png .dds", CF_TYPE_PLAYERS },
|
||||
{ CF_TYPE_SQUAD_IMAGES, "data" DIR_SEPARATOR_STR "players" DIR_SEPARATOR_STR "squads", ".pcx .png .dds", CF_TYPE_PLAYERS },
|
||||
{ CF_TYPE_SINGLE_PLAYERS, "data" DIR_SEPARATOR_STR "players" DIR_SEPARATOR_STR "single", ".pl2 .cs2 .plr .csg .css .json", CF_TYPE_PLAYERS },
|
||||
{ CF_TYPE_MULTI_PLAYERS, "data" DIR_SEPARATOR_STR "players" DIR_SEPARATOR_STR "multi", ".plr .json", CF_TYPE_PLAYERS },
|
||||
{ CF_TYPE_CACHE, "data" DIR_SEPARATOR_STR "cache", ".clr .tmp .bx", CF_TYPE_DATA }, //clr=cached color
|
||||
{ CF_TYPE_MULTI_CACHE, "data" DIR_SEPARATOR_STR "multidata", ".pcx .png .dds .fs2 .txt", CF_TYPE_DATA },
|
||||
{ CF_TYPE_MISSIONS, "data" DIR_SEPARATOR_STR "missions", ".fs2 .fc2 .ntl .ssv", CF_TYPE_DATA },
|
||||
{ CF_TYPE_CONFIG, "data" DIR_SEPARATOR_STR "config", ".cfg .tbl .tbm .xml .csv", CF_TYPE_DATA },
|
||||
{ CF_TYPE_DEMOS, "data" DIR_SEPARATOR_STR "demos", ".fsd", CF_TYPE_DATA },
|
||||
{ CF_TYPE_CBANIMS, "data" DIR_SEPARATOR_STR "cbanims", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA },
|
||||
{ CF_TYPE_INTEL_ANIMS, "data" DIR_SEPARATOR_STR "intelanims", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA },
|
||||
{ CF_TYPE_SCRIPTS, "data" DIR_SEPARATOR_STR "scripts", ".lua .lc", CF_TYPE_DATA },
|
||||
{ CF_TYPE_FICTION, "data" DIR_SEPARATOR_STR "fiction", ".txt", CF_TYPE_DATA },
|
||||
{ CF_TYPE_FREDDOCS, "data" DIR_SEPARATOR_STR "freddocs", ".html", CF_TYPE_DATA },
|
||||
{ CF_TYPE_INTERFACE_MARKUP, "data" DIR_SEPARATOR_STR "interface" DIR_SEPARATOR_STR "markup", ".rml", CF_TYPE_INTERFACE },
|
||||
{ CF_TYPE_INTERFACE_CSS, "data" DIR_SEPARATOR_STR "interface" DIR_SEPARATOR_STR "css", ".rcss", CF_TYPE_INTERFACE },
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
#define CFILE_STACK_MAX 8
|
||||
|
||||
@@ -230,14 +226,8 @@ int cfile_init(const char *exe_dir, const char *cdrom_dir)
|
||||
cfile_chdir(buf);
|
||||
|
||||
// set root directory
|
||||
strncpy(Cfile_root_dir, buf, CFILE_ROOT_DIRECTORY_LEN-1);
|
||||
strncpy(Cfile_user_dir, os_get_config_path().c_str(), CFILE_ROOT_DIRECTORY_LEN-1);
|
||||
|
||||
#ifdef SCP_UNIX
|
||||
// Initialize path of old pilot files
|
||||
extern const char* Osreg_user_dir_legacy;
|
||||
snprintf(Cfile_user_dir_legacy, CFILE_ROOT_DIRECTORY_LEN-1, "%s/%s/", getenv("HOME"), Osreg_user_dir_legacy);
|
||||
#endif
|
||||
strcpy_s(Cfile_root_dir, buf);
|
||||
strcpy_s(Cfile_user_dir, os_get_config_path().c_str());
|
||||
|
||||
for (i = 0; i < MAX_CFILE_BLOCKS; i++) {
|
||||
Cfile_block_list[i].type = CFILE_BLOCK_UNUSED;
|
||||
@@ -252,16 +242,6 @@ int cfile_init(const char *exe_dir, const char *cdrom_dir)
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Call this if pack files got added or removed or the
|
||||
// cdrom changed. This will refresh the list of filenames
|
||||
// stored in packfiles and on the cdrom.
|
||||
void cfile_refresh()
|
||||
{
|
||||
cf_build_secondary_filelist(Cfile_cdrom_dir);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
// Changes to a drive if valid.. 1=A, 2=B, etc
|
||||
// If flag, then changes to it.
|
||||
@@ -362,8 +342,7 @@ int cfile_push_chdir(int type)
|
||||
return -1;
|
||||
}
|
||||
|
||||
strncpy(Cfile_stack[Cfile_stack_pos++], OriginalDirectory,
|
||||
CFILE_ROOT_DIRECTORY_LEN - 1);
|
||||
strcpy_s(Cfile_stack[Cfile_stack_pos++], OriginalDirectory);
|
||||
|
||||
cf_create_default_path_string(dir, sizeof(dir) - 1, type, NULL);
|
||||
|
||||
@@ -486,17 +465,17 @@ char *cf_add_ext(const char *filename, const char *ext)
|
||||
*
|
||||
* @param filename Name of file to delete
|
||||
* @param path_type Path type (CF_TYPE_xxx)
|
||||
* @param location_flags Where to search for the location of the file to delete
|
||||
*
|
||||
* @return 0 on failure, 1 on success
|
||||
*/
|
||||
int cf_delete(const char *filename, int path_type)
|
||||
int cf_delete(const char *filename, int path_type, uint32_t location_flags)
|
||||
{
|
||||
char longname[MAX_PATH_LEN];
|
||||
|
||||
Assert(CF_TYPE_SPECIFIED(path_type));
|
||||
|
||||
cf_create_default_path_string(longname, sizeof(longname) - 1,
|
||||
path_type, filename);
|
||||
cf_create_default_path_string(longname, sizeof(longname) - 1, path_type, filename, false, location_flags);
|
||||
|
||||
return (_unlink(longname) != -1);
|
||||
}
|
||||
@@ -522,12 +501,12 @@ int cf_access(const char *filename, int dir_type, int mode)
|
||||
// If offset equates to boolean true, it was found in a VP and the logic will negate the function return
|
||||
int cf_exists(const char *filename, int dir_type)
|
||||
{
|
||||
size_t offset = 1;
|
||||
|
||||
if ( (filename == NULL) || !strlen(filename) )
|
||||
return 0;
|
||||
|
||||
return (cf_find_file_location(filename, dir_type, 0, NULL, NULL, &offset) && !offset);
|
||||
auto find_res = cf_find_file_location(filename, dir_type);
|
||||
|
||||
return find_res.found && !find_res.offset;
|
||||
}
|
||||
|
||||
// Goober5000
|
||||
@@ -538,7 +517,7 @@ int cf_exists_full(const char *filename, int dir_type)
|
||||
if ( (filename == NULL) || !strlen(filename) )
|
||||
return 0;
|
||||
|
||||
return cf_find_file_location(filename, dir_type, 0, NULL, NULL, NULL);
|
||||
return cf_find_file_location(filename, dir_type).found;
|
||||
}
|
||||
|
||||
// same as the above, but with extension check
|
||||
@@ -550,7 +529,7 @@ int cf_exists_full_ext(const char *filename, int dir_type, const int num_ext, co
|
||||
if ( (num_ext <= 0) || (ext_list == NULL) )
|
||||
return 0;
|
||||
|
||||
return (cf_find_file_location_ext(filename, num_ext, ext_list, dir_type, 0, NULL, NULL, NULL) != -1);
|
||||
return cf_find_file_location_ext(filename, num_ext, ext_list, dir_type).found;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
@@ -624,7 +603,7 @@ static void mkdir_recursive(const char *path) {
|
||||
|
||||
// Creates the directory path if it doesn't exist. Even creates all its
|
||||
// parent paths.
|
||||
void cf_create_directory( int dir_type )
|
||||
void cf_create_directory(int dir_type, uint32_t location_flags)
|
||||
{
|
||||
int num_dirs = 0;
|
||||
int dir_tree[CF_MAX_PATH_TYPES];
|
||||
@@ -646,7 +625,7 @@ void cf_create_directory( int dir_type )
|
||||
int i;
|
||||
|
||||
for (i=num_dirs-1; i>=0; i-- ) {
|
||||
cf_create_default_path_string( longname, sizeof(longname)-1, dir_tree[i], NULL );
|
||||
cf_create_default_path_string(longname, sizeof(longname) - 1, dir_tree[i], nullptr, false, location_flags);
|
||||
if (stat(longname, &statbuf) != 0) {
|
||||
mprintf(( "CFILE: Creating new directory '%s'\n", longname ));
|
||||
mkdir_recursive(longname);
|
||||
@@ -654,9 +633,6 @@ void cf_create_directory( int dir_type )
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extern int game_cd_changed();
|
||||
|
||||
// cfopen()
|
||||
//
|
||||
// parameters: *filepath ==> name of file to open (may be path+name)
|
||||
@@ -673,14 +649,13 @@ extern int game_cd_changed();
|
||||
// error ==> NULL
|
||||
//
|
||||
|
||||
CFILE *_cfopen(const char* source, int line, const char *file_path, const char *mode, int type, int dir_type, bool localize)
|
||||
CFILE* _cfopen(const char* source, int line, const char* file_path, const char* mode, int type, int dir_type,
|
||||
bool localize, uint32_t location_flags)
|
||||
{
|
||||
/* Bobboau, what is this doing here? 31 is way too short... - Goober5000
|
||||
if( strlen(file_path) > 31 )
|
||||
Error(LOCATION, "file name %s too long, \nmust be less than 31 charicters", file_path);*/
|
||||
|
||||
char longname[_MAX_PATH];
|
||||
|
||||
if ( !cfile_inited ) {
|
||||
Int3();
|
||||
return NULL;
|
||||
@@ -702,6 +677,8 @@ CFILE *_cfopen(const char* source, int line, const char *file_path, const char *
|
||||
// the harddisk. No fancy packfile stuff here!
|
||||
|
||||
if ( strchr(mode,'w') || strchr(mode,'+') || strchr(mode,'a') ) {
|
||||
char longname[_MAX_PATH];
|
||||
|
||||
// For write-only files, require a full path or a path type
|
||||
#ifdef SCP_UNIX
|
||||
if ( strpbrk(file_path, "/") ) {
|
||||
@@ -715,9 +692,9 @@ CFILE *_cfopen(const char* source, int line, const char *file_path, const char *
|
||||
Assert( dir_type != CF_TYPE_ANY );
|
||||
|
||||
// Create the directory if necessary
|
||||
cf_create_directory( dir_type );
|
||||
cf_create_directory(dir_type, location_flags);
|
||||
|
||||
cf_create_default_path_string( longname, sizeof(longname)-1, dir_type, file_path );
|
||||
cf_create_default_path_string(longname, sizeof(longname) - 1, dir_type, file_path, false, location_flags);
|
||||
}
|
||||
Assert( !(type & CFILE_MEMORY_MAPPED) );
|
||||
|
||||
@@ -767,30 +744,29 @@ CFILE *_cfopen(const char* source, int line, const char *file_path, const char *
|
||||
//================================================
|
||||
// Search for file on disk, on cdrom, or in a packfile
|
||||
|
||||
size_t offset, size;
|
||||
char copy_file_path[MAX_PATH_LEN]; // FIX change in memory from cf_find_file_location
|
||||
strcpy_s(copy_file_path, file_path);
|
||||
|
||||
const void* file_data = nullptr;
|
||||
if ( cf_find_file_location( copy_file_path, dir_type, sizeof(longname) - 1, longname, &size, &offset, localize, &file_data ) ) {
|
||||
auto find_res = cf_find_file_location( copy_file_path, dir_type, localize, location_flags );
|
||||
if ( find_res.found ) {
|
||||
|
||||
// Fount it, now create a cfile out of it
|
||||
nprintf(("CFileDebug", "Requested file %s found at: %s\n", file_path, longname));
|
||||
|
||||
nprintf(("CFileDebug", "Requested file %s found at: %s\n", file_path, find_res.full_name.c_str()));
|
||||
|
||||
if ( type & CFILE_MEMORY_MAPPED ) {
|
||||
|
||||
// Can't open memory mapped files out of pack or memory files
|
||||
if ( offset == 0 && file_data != nullptr ) {
|
||||
if ( find_res.offset == 0 && find_res.data_ptr != nullptr ) {
|
||||
#if defined _WIN32
|
||||
HANDLE hFile;
|
||||
|
||||
hFile = CreateFile(longname, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
hFile = CreateFile(find_res.full_name.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
if (hFile != INVALID_HANDLE_VALUE) {
|
||||
return cf_open_mapped_fill_cfblock(source, line, hFile, dir_type);
|
||||
}
|
||||
#elif defined SCP_UNIX
|
||||
FILE *fp = fopen( longname, "rb" );
|
||||
FILE* fp = fopen(find_res.full_name.c_str(), "rb");
|
||||
if (fp) {
|
||||
return cf_open_mapped_fill_cfblock(source, line, fp, dir_type);
|
||||
}
|
||||
@@ -799,7 +775,8 @@ CFILE *_cfopen(const char* source, int line, const char *file_path, const char *
|
||||
|
||||
} else {
|
||||
// since cfopen_special already has all the code to handle the opening we can just use that here
|
||||
return _cfopen_special(source, line, longname, mode, size, offset, file_data, dir_type);
|
||||
return _cfopen_special(source, line, find_res.full_name.c_str(), mode, find_res.size, find_res.offset,
|
||||
find_res.data_ptr, dir_type);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -907,7 +884,7 @@ static int cfget_cfile_block()
|
||||
mprintf(("Out of cfile blocks! Currently opened files:\n"));
|
||||
dump_opened_files();
|
||||
|
||||
Assertion(false, "There are no more free cfile blocks. This means that there are too many files opened by FSO.\n"
|
||||
UNREACHABLE("There are no more free cfile blocks. This means that there are too many files opened by FSO.\n"
|
||||
"This is probably caused by a programming or scripting error where a file does not get closed."); // out of free cfile blocks
|
||||
return -1;
|
||||
}
|
||||
@@ -1178,17 +1155,6 @@ const void *cf_returndata(CFILE *cfile)
|
||||
return cb->data;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// version number of opened file. Will be 0 unless you put something else here after you
|
||||
// open a file. Once set, you can use minimum version numbers with the read functions.
|
||||
void cf_set_version( CFILE * cfile, int version )
|
||||
{
|
||||
Assert(cfile != NULL);
|
||||
|
||||
cfile->version = version;
|
||||
}
|
||||
|
||||
// cutoff point where cfread() will throw an error when it hits this limit
|
||||
// if 'len' is 0 then this check will be disabled
|
||||
void cf_set_max_read_len( CFILE * cfile, size_t len )
|
||||
@@ -1306,22 +1272,6 @@ void cfread_vector(vec3d *vec, CFILE *file, int ver, vec3d *deflt)
|
||||
vec->xyz.y = cfread_float(file, ver, deflt ? deflt->xyz.y : 0.0f);
|
||||
vec->xyz.z = cfread_float(file, ver, deflt ? deflt->xyz.z : 0.0f);
|
||||
}
|
||||
|
||||
void cfread_angles(angles *ang, CFILE *file, int ver, angles *deflt)
|
||||
{
|
||||
if (file->version < ver) {
|
||||
if (deflt)
|
||||
*ang = *deflt;
|
||||
else
|
||||
ang->p = ang->b = ang->h = 0.0f;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ang->p = cfread_float(file, ver, deflt ? deflt->p : 0.0f);
|
||||
ang->b = cfread_float(file, ver, deflt ? deflt->b : 0.0f);
|
||||
ang->h = cfread_float(file, ver, deflt ? deflt->h : 0.0f);
|
||||
}
|
||||
|
||||
char cfread_char(CFILE *file, int ver, char deflt)
|
||||
{
|
||||
@@ -1360,6 +1310,19 @@ void cfread_string_len(char *buf,int n, CFILE *file)
|
||||
buf[len] = 0;
|
||||
}
|
||||
|
||||
SCP_string cfread_string_len(CFILE *file)
|
||||
{
|
||||
int len = cfread_int(file);
|
||||
|
||||
SCP_string str;
|
||||
str.resize(len);
|
||||
|
||||
if (len)
|
||||
cfread(&str[0], len, 1, file);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
// equivalent write functions of above read functions follow
|
||||
|
||||
int cfwrite_float(float f, CFILE *file)
|
||||
@@ -1397,28 +1360,6 @@ int cfwrite_ubyte(ubyte b, CFILE *file)
|
||||
return cfwrite(&b, sizeof(b), 1, file);
|
||||
}
|
||||
|
||||
int cfwrite_vector(vec3d *vec, CFILE *file)
|
||||
{
|
||||
if(!cfwrite_float(vec->xyz.x, file)){
|
||||
return 0;
|
||||
}
|
||||
if(!cfwrite_float(vec->xyz.y, file)){
|
||||
return 0;
|
||||
}
|
||||
return cfwrite_float(vec->xyz.z, file);
|
||||
}
|
||||
|
||||
int cfwrite_angles(angles *ang, CFILE *file)
|
||||
{
|
||||
if(!cfwrite_float(ang->p, file)){
|
||||
return 0;
|
||||
}
|
||||
if(!cfwrite_float(ang->b, file)){
|
||||
return 0;
|
||||
}
|
||||
return cfwrite_float(ang->h, file);
|
||||
}
|
||||
|
||||
int cfwrite_char(char b, CFILE *file)
|
||||
{
|
||||
return cfwrite( &b, sizeof(b), 1, file);
|
||||
@@ -1973,3 +1914,33 @@ int cflush(CFILE *cfile)
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int cfile_get_path_type(const SCP_string& dir)
|
||||
{
|
||||
SCP_string buf = dir;
|
||||
|
||||
// Remove trailing slashes; avoid buffer overflow on 1-char strings
|
||||
while (buf.size() > 0 && (buf[buf.size() - 1] == '\\' || buf[buf.size() - 1] == '/')) {
|
||||
buf.resize(buf.size() - 1);
|
||||
}
|
||||
|
||||
// Remove leading slashes
|
||||
while (buf.size() > 0 && (buf[0] == '\\' || buf[0] == '/')) {
|
||||
buf = buf.substr(1);
|
||||
}
|
||||
|
||||
// Use official DIR_SEPARATOR_CHAR
|
||||
for (char& c : buf) {
|
||||
if (c == '\\' || c == '/') {
|
||||
c = DIR_SEPARATOR_CHAR;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& Pathtype : Pathtypes) {
|
||||
if (Pathtype.path != nullptr && buf == Pathtype.path) {
|
||||
return Pathtype.index;
|
||||
}
|
||||
}
|
||||
|
||||
return CF_TYPE_INVALID;
|
||||
}
|
||||
+104
-35
@@ -79,9 +79,11 @@ typedef struct {
|
||||
#define CF_TYPE_SCRIPTS 35
|
||||
#define CF_TYPE_FICTION 36
|
||||
#define CF_TYPE_FREDDOCS 37
|
||||
#define CF_TYPE_INTERFACE_MARKUP 38
|
||||
#define CF_TYPE_INTERFACE_CSS 39
|
||||
|
||||
#define CF_MAX_PATH_TYPES 38 // Can be as high as you'd like //DTP; yeah but beware alot of things uses CF_MAX_PATH_TYPES
|
||||
|
||||
#define CF_MAX_PATH_TYPES \
|
||||
40 // Can be as high as you'd like //DTP; yeah but beware alot of things uses CF_MAX_PATH_TYPES
|
||||
|
||||
// TRUE if type is specified and valid
|
||||
#define CF_TYPE_SPECIFIED(path_type) (((path_type)>CF_TYPE_INVALID) && ((path_type)<CF_MAX_PATH_TYPES))
|
||||
@@ -95,8 +97,63 @@ typedef struct {
|
||||
#define CF_SORT_TIME 2
|
||||
#define CF_SORT_REVERSE 3
|
||||
|
||||
#define cfread_fix(file) (fix)cfread_int(file)
|
||||
#define cfwrite_fix(i,file) cfwrite_int(i,file)
|
||||
/**
|
||||
* @brief Contains a collection of flags for specifying from where a CFILE should be opened
|
||||
*
|
||||
* There are two types of flags. CF_LOCATION_GAME_ROOT and CF_LOCATION_USER_ROOT specify in which basic root directory
|
||||
* CFile should search for files.
|
||||
*
|
||||
* The remaining flags control what type of location may be used for the operation. It's possible to restrict the
|
||||
* location to the primary mod, the remaining mods or the top-level root directory.
|
||||
*/
|
||||
enum CFileLocationFlags {
|
||||
CF_LOCATION_ROOT_GAME = 1 << 0, //!< The game root location. This is the location of the game data (e.g. FS2 retail)
|
||||
/**
|
||||
* @brief The user directories.
|
||||
*
|
||||
* If the engine is in portable mode then using this flag exclusively will result in a failure to open files!
|
||||
*/
|
||||
CF_LOCATION_ROOT_USER = 1 << 1,
|
||||
|
||||
/**
|
||||
* @brief The memory root
|
||||
*
|
||||
* This contains all the built-in files available to the engine.
|
||||
*/
|
||||
CF_LOCATION_ROOT_MEMORY = 1 << 2,
|
||||
|
||||
/**
|
||||
* @brief Mask for extracting root type from a location bit field
|
||||
*/
|
||||
CF_LOCATION_ROOT_MASK = 0xFFFF,
|
||||
|
||||
CF_LOCATION_TYPE_ROOT = 1 << 16, //!< The basic, top-level root location
|
||||
/**
|
||||
* @brief The primary mod location.
|
||||
*
|
||||
* This is the mod that appears first on the command line. If there are no mods then the root location is considered
|
||||
* to be the primary mod
|
||||
*/
|
||||
CF_LOCATION_TYPE_PRIMARY_MOD = 1 << 17,
|
||||
/**
|
||||
* @brief The remaining mods.
|
||||
*
|
||||
* If there are no mods on the command line then this might not include any valid location.
|
||||
*/
|
||||
CF_LOCATION_TYPE_SECONDARY_MODS = 1 << 18,
|
||||
|
||||
/**
|
||||
* @brief Bitmask for extracting the type from a location bit field
|
||||
*/
|
||||
CF_LOCATION_TYPE_MASK = 0xFFFF0000,
|
||||
|
||||
/**
|
||||
* @brief A combination of all flags
|
||||
*
|
||||
* This should be used when the default behavior without any location filtering is desired.
|
||||
*/
|
||||
CF_LOCATION_ALL = CF_LOCATION_ROOT_MASK | CF_LOCATION_TYPE_MASK
|
||||
};
|
||||
|
||||
// callback function used for get_file_list() to filter files to be added to list. Return 1
|
||||
// to add file to list, or 0 to not add it.
|
||||
@@ -111,30 +168,21 @@ extern const char *Get_file_list_child;
|
||||
#define CFILE_ROOT_DIRECTORY_LEN 256
|
||||
extern char Cfile_root_dir[CFILE_ROOT_DIRECTORY_LEN];
|
||||
extern char Cfile_user_dir[CFILE_ROOT_DIRECTORY_LEN];
|
||||
#ifdef SCP_UNIX
|
||||
extern char Cfile_user_dir_legacy[CFILE_ROOT_DIRECTORY_LEN];
|
||||
#endif
|
||||
|
||||
//================= LOW-LEVEL FUNCTIONS ==================
|
||||
int cfile_init(const char *exe_dir, const char *cdrom_dir=NULL);
|
||||
void cfile_close();
|
||||
|
||||
// Call this if pack files got added or removed or the
|
||||
// cdrom changed. This will refresh the list of filenames
|
||||
// stored in packfiles and on the cdrom.
|
||||
void cfile_refresh();
|
||||
|
||||
// add an extension to a filename if it doesn't already have it
|
||||
char *cf_add_ext(const char *filename, const char *ext);
|
||||
|
||||
// return CF_TYPE (directory location type) of a CFILE you called cfopen() successfully on.
|
||||
int cf_get_dir_type(CFILE *cfile);
|
||||
|
||||
|
||||
// Opens the file. If no path is given, use the extension to look into the
|
||||
// default path. If mode is NULL, delete the file.
|
||||
CFILE *_cfopen(const char* source_file, int line, const char *filename, const char *mode,
|
||||
int type = CFILE_NORMAL, int dir_type = CF_TYPE_ANY, bool localize = false);
|
||||
// default path. If mode is NULL, delete the file.
|
||||
CFILE* _cfopen(const char* source_file, int line, const char* filename, const char* mode, int type = CFILE_NORMAL,
|
||||
int dir_type = CF_TYPE_ANY, bool localize = false, uint32_t location_flags = CF_LOCATION_ALL);
|
||||
#define cfopen(...) _cfopen(LOCATION, __VA_ARGS__) // Pass source location to the function
|
||||
|
||||
// like cfopen(), but it accepts a fully qualified path only (ie, the result of a cf_find_file_location() call)
|
||||
@@ -146,17 +194,13 @@ CFILE *_cfopen_special(const char* source_file, int line, const char *file_path,
|
||||
// Flush the open file buffer
|
||||
int cflush(CFILE *cfile);
|
||||
|
||||
// version number of opened file. Will be 0 unless you put something else here after you
|
||||
// open a file. Once set, you can use minimum version numbers with the read functions.
|
||||
void cf_set_version( CFILE * cfile, int version );
|
||||
|
||||
// will throw an error if cfread*() functions read past this mark
|
||||
// converted to raw offsets when used, but gets passed actual length from current position
|
||||
// setting 'len' to zero will disable the check
|
||||
void cf_set_max_read_len(CFILE *cfile, size_t len);
|
||||
|
||||
// Deletes a file. Returns 0 on error, 1 if successful
|
||||
int cf_delete(const char *filename, int dir_type);
|
||||
int cf_delete(const char *filename, int dir_type, uint32_t location_flags = CF_LOCATION_ALL);
|
||||
|
||||
// Same as _access function to read a file's access bits
|
||||
int cf_access(const char *filename, int dir_type, int mode);
|
||||
@@ -190,10 +234,6 @@ int cfread(void *buf, int elsize, int nelem, CFILE *fp);
|
||||
// cfwrite() writes to the file
|
||||
int cfwrite(const void *buf, int elsize, int nelem, CFILE *cfile);
|
||||
|
||||
// Reads/writes RLE compressed data.
|
||||
int cfread_compressed(void *buf, int elsize, int nelem, CFILE *cfile);
|
||||
int cfwrite_compressed(void *param_buf, int param_elsize, int param_nelem, CFILE *cfile);
|
||||
|
||||
// Moves the file pointer
|
||||
int cfseek(CFILE *fp, int offset, int where);
|
||||
|
||||
@@ -245,7 +285,6 @@ uint cf_add_chksum_long(uint seed, ubyte *buffer, size_t size);
|
||||
// convenient for misc checksumming purposes ------------------------------------------
|
||||
|
||||
//================= HIGH LEVEL FUNCTIONS ==================
|
||||
int cfexist(const char *filename); // Returns true if file exists on disk (1) or in hog (2).
|
||||
|
||||
// rename a file, utilizing the extension to determine where file is.
|
||||
#define CF_RENAME_SUCCESS 0 // successfully renamed the file
|
||||
@@ -263,7 +302,6 @@ int cfile_flush_dir(int type);
|
||||
// functions for reading from cfile
|
||||
// These are all high level, built up from
|
||||
// cfread.
|
||||
int cfgetc(CFILE *fp);
|
||||
char *cfgets(char *buf, size_t n, CFILE *fp);
|
||||
char cfread_char(CFILE *file, int ver = 0, char deflt = 0);
|
||||
ubyte cfread_ubyte(CFILE *file, int ver = 0, ubyte deflt = 0);
|
||||
@@ -273,7 +311,6 @@ int cfread_int(CFILE *file, int ver = 0, int deflt = 0);
|
||||
uint cfread_uint(CFILE *file, int ver = 0, uint deflt = 0);
|
||||
float cfread_float(CFILE *file, int ver = 0, float deflt = 0.0f);
|
||||
void cfread_vector(vec3d *vec, CFILE *file, int ver = 0, vec3d *deflt = NULL);
|
||||
void cfread_angles(angles *ang, CFILE *file, int ver = 0, angles *deflt = NULL);
|
||||
|
||||
// Reads variable length, null-termined string. Will only read up
|
||||
// to n characters.
|
||||
@@ -289,6 +326,13 @@ void cfread_string(char *buf,int n, CFILE *file);
|
||||
*/
|
||||
void cfread_string_len(char *buf,int n, CFILE *file);
|
||||
|
||||
/**
|
||||
* @brief Read a string from the file where the length is stored in the file
|
||||
* @param file The file to read the string from
|
||||
* @return The string that was read
|
||||
*/
|
||||
SCP_string cfread_string_len(CFILE *file);
|
||||
|
||||
// functions for writing cfiles
|
||||
int cfwrite_char(char c, CFILE *file);
|
||||
int cfwrite_float(float f, CFILE *file);
|
||||
@@ -297,8 +341,6 @@ int cfwrite_uint(uint i, CFILE *file);
|
||||
int cfwrite_short(short s, CFILE *file);
|
||||
int cfwrite_ushort(ushort s, CFILE *file);
|
||||
int cfwrite_ubyte(ubyte u, CFILE *file);
|
||||
int cfwrite_vector(vec3d *vec, CFILE *file);
|
||||
int cfwrite_angles(angles *ang, CFILE *file);
|
||||
|
||||
// writes variable length, null-termined string.
|
||||
int cfwrite_string(const char *buf, CFILE *file);
|
||||
@@ -311,12 +353,26 @@ int cfwrite_string(const char *buf, CFILE *file);
|
||||
*/
|
||||
int cfwrite_string_len(const char *buf, CFILE *file);
|
||||
|
||||
int cf_get_file_list( SCP_vector<SCP_string> &list, int pathtype, const char *filter, int sort = CF_SORT_NONE, SCP_vector<file_list_info> *info = NULL );
|
||||
int cf_get_file_list( int max, char **list, int type, const char *filter, int sort = CF_SORT_NONE, file_list_info *info = NULL );
|
||||
int cf_get_file_list_preallocated( int max, char arr[][MAX_FILENAME_LEN], char **list, int type, const char *filter, int sort = CF_SORT_NONE, file_list_info *info = NULL );
|
||||
int cf_get_file_list(SCP_vector<SCP_string>& list, int pathtype, const char* filter, int sort = CF_SORT_NONE,
|
||||
SCP_vector<file_list_info>* info = nullptr, uint32_t location_flags = CF_LOCATION_ALL);
|
||||
int cf_get_file_list(int max, char** list, int type, const char* filter, int sort = CF_SORT_NONE,
|
||||
file_list_info* info = nullptr, uint32_t location_flags = CF_LOCATION_ALL);
|
||||
int cf_get_file_list_preallocated(int max, char arr[][MAX_FILENAME_LEN], char** list, int type, const char* filter,
|
||||
int sort = CF_SORT_NONE, file_list_info* info = nullptr,
|
||||
uint32_t location_flags = CF_LOCATION_ALL);
|
||||
void cf_sort_filenames( int n, char **list, int sort, file_list_info *info = NULL );
|
||||
void cf_sort_filenames( SCP_vector<SCP_string> &list, int sort, SCP_vector<file_list_info> *info = NULL );
|
||||
|
||||
struct CFileLocation {
|
||||
bool found = false;
|
||||
SCP_string full_name;
|
||||
size_t size = 0;
|
||||
size_t offset = 0;
|
||||
const void* data_ptr = nullptr;
|
||||
|
||||
explicit CFileLocation(bool found_in = false) : found(found_in) {}
|
||||
};
|
||||
|
||||
// Searches for a file. Follows all rules and precedence and searches
|
||||
// CD's and pack files.
|
||||
// Input: filespace - Filename & extension
|
||||
@@ -326,7 +382,17 @@ void cf_sort_filenames( SCP_vector<SCP_string> &list, int sort, SCP_vector<file_
|
||||
// size - File size
|
||||
// offset - Offset into pack file. 0 if not a packfile.
|
||||
// Returns: If not found returns 0.
|
||||
int cf_find_file_location( const char *filespec, int pathtype, int max_out, char *pack_filename, size_t *size, size_t *offset, bool localize = false, const void** data_out = nullptr);
|
||||
CFileLocation cf_find_file_location(const char* filespec, int pathtype, bool localize = false,
|
||||
uint32_t location_flags = CF_LOCATION_ALL);
|
||||
|
||||
struct CFileLocationExt : public CFileLocation {
|
||||
int extension_index = -1;
|
||||
|
||||
explicit CFileLocationExt(int extension_index_in = -1)
|
||||
: CFileLocation(extension_index_in >= 0), extension_index(extension_index_in)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
// Searches for a file. Follows all rules and precedence and searches
|
||||
// CD's and pack files. Searches all locations in order for first filename using ext filter list.
|
||||
@@ -340,7 +406,8 @@ int cf_find_file_location( const char *filespec, int pathtype, int max_out, char
|
||||
// offset - Offset into pack file. 0 if not a packfile.
|
||||
// Returns: If not found returns -1, else returns offset into ext_list.
|
||||
// (NOTE: This function is exponentially slow, so don't use it unless truely needed!!)
|
||||
int cf_find_file_location_ext(const char *filename, const int ext_num, const char **ext_list, int pathtype, int max_out = 0, char *pack_filename = NULL, size_t *size = NULL, size_t *offset = NULL, bool localize = false, const void** data_out = nullptr);
|
||||
CFileLocationExt cf_find_file_location_ext(const char* filename, const int ext_num, const char** ext_list, int pathtype,
|
||||
bool localize = false);
|
||||
|
||||
// Functions to change directories
|
||||
int cfile_chdir(const char *dir);
|
||||
@@ -355,6 +422,8 @@ int cfile_push_chdir(int type);
|
||||
// restore directory on top of the stack
|
||||
int cfile_pop_dir();
|
||||
|
||||
int cfile_get_path_type(const SCP_string& dir);
|
||||
|
||||
namespace cfile
|
||||
{
|
||||
// exceptions and other errors
|
||||
|
||||
@@ -32,7 +32,6 @@ typedef struct Cfile_block {
|
||||
HANDLE hInFile; // Handle from CreateFile()
|
||||
HANDLE hMapFile; // Handle from CreateFileMapping()
|
||||
#else
|
||||
// int fd; // file descriptor
|
||||
size_t data_length; // length of data for mmap
|
||||
#endif
|
||||
size_t lib_offset;
|
||||
|
||||
+1
-350
@@ -200,353 +200,4 @@ void cf_sort_filenames( int n, char **list, int sort, file_list_info *info )
|
||||
}
|
||||
|
||||
nprintf(("Error", "Unknown sorting method %d passed to cf_sort_filenames()\n", sort));
|
||||
}
|
||||
|
||||
|
||||
#if (0) // these aren't used anywhere now
|
||||
|
||||
// cf_compress - Do Run Length Compression on a block of data. Targa format.
|
||||
//
|
||||
// Usage:
|
||||
// out Buffer to write it out to
|
||||
// in Buffer to compress
|
||||
// bytecount Number of bytes input
|
||||
int cf_compress(char *out, char *in, int bytecount )
|
||||
{
|
||||
int pixcount; // number of pixels in the current packet
|
||||
char *inputpixel=NULL; // current input pixel position
|
||||
char *matchpixel=NULL; // pixel value to match for a run
|
||||
char *flagbyte=NULL; // location of last flag byte to set
|
||||
int rlcount; // current count in r.l. string
|
||||
int rlthresh; // minimum valid run length
|
||||
char *copyloc; // location to begin copying at
|
||||
|
||||
// set the threshold -- the minimum valid run length
|
||||
rlthresh = 2; // Require a 2 pixel span before rle'ing
|
||||
|
||||
// set the first pixel up
|
||||
|
||||
flagbyte = out; // place to put next flag if run
|
||||
inputpixel = in;
|
||||
pixcount = 1;
|
||||
rlcount = 0;
|
||||
copyloc = (char *)0;
|
||||
|
||||
// loop till data processing complete
|
||||
do {
|
||||
|
||||
// if we have accumulated a 128-byte packet, process it
|
||||
if ( pixcount == 129 ) {
|
||||
*flagbyte = 127;
|
||||
|
||||
// set the run flag if this is a run
|
||||
|
||||
if ( rlcount >= rlthresh ) {
|
||||
*flagbyte |= 0x80;
|
||||
pixcount = 2;
|
||||
}
|
||||
|
||||
// copy the data into place
|
||||
++flagbyte;
|
||||
memmove( flagbyte, copyloc, pixcount-1 );
|
||||
flagbyte += pixcount-1;
|
||||
pixcount = 1;
|
||||
|
||||
// set up for next packet
|
||||
continue;
|
||||
}
|
||||
|
||||
// if zeroth byte, handle as special case
|
||||
if ( pixcount == 1 ) {
|
||||
rlcount = 0;
|
||||
copyloc = inputpixel; /* point to 1st guy in packet */
|
||||
matchpixel = inputpixel; /* set pointer to pix to match */
|
||||
pixcount = 2;
|
||||
inputpixel += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
// assembling a packet -- look at next pixel
|
||||
|
||||
// current pixel == match pixel?
|
||||
if ( *inputpixel == *matchpixel ) {
|
||||
|
||||
// establishing a run of enough length to
|
||||
// save space by doing it
|
||||
// -- write the non-run length packet
|
||||
// -- start run-length packet
|
||||
|
||||
if ( ++rlcount == rlthresh ) {
|
||||
|
||||
// close a non-run packet
|
||||
|
||||
if ( pixcount > (rlcount+1) ) {
|
||||
// write out length and do not set run flag
|
||||
|
||||
*flagbyte++ = (char)(pixcount - 2 - rlthresh);
|
||||
|
||||
memmove(flagbyte, copyloc, (pixcount-1-rlcount) );
|
||||
flagbyte += (pixcount-1-rlcount);
|
||||
|
||||
copyloc = inputpixel;
|
||||
pixcount = rlcount + 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
// no match -- either break a run or continue without one
|
||||
// if a run exists break it:
|
||||
// write the bytes in the string (1+1)
|
||||
// start the next string
|
||||
|
||||
if ( rlcount >= rlthresh ) {
|
||||
|
||||
*flagbyte++ = (char)(0x80 | rlcount);
|
||||
memmove(flagbyte, copyloc, 1 );
|
||||
flagbyte += 1;
|
||||
pixcount = 1;
|
||||
continue;
|
||||
} else {
|
||||
|
||||
// not a match and currently not a run
|
||||
// - save the current pixel
|
||||
// - reset the run-length flag
|
||||
rlcount = 0;
|
||||
matchpixel = inputpixel;
|
||||
}
|
||||
}
|
||||
pixcount++;
|
||||
inputpixel += 1;
|
||||
} while ( inputpixel < (in + bytecount));
|
||||
|
||||
// quit this buffer without loosing any data
|
||||
if ( --pixcount >= 1 ) {
|
||||
*flagbyte = (char)(pixcount - 1);
|
||||
if ( rlcount >= rlthresh ) {
|
||||
*flagbyte |= 0x80;
|
||||
pixcount = 1;
|
||||
}
|
||||
|
||||
// copy the data into place
|
||||
++flagbyte;
|
||||
memmove(flagbyte, copyloc, pixcount );
|
||||
flagbyte += pixcount;
|
||||
}
|
||||
return(flagbyte-out);
|
||||
}
|
||||
|
||||
|
||||
// cf_decompress - Do Decompression on a run-length encoded block of data. Targa format.
|
||||
//
|
||||
// Usage:
|
||||
// out Buffer to write it out to
|
||||
// in Buffer to compress
|
||||
// bytecount Number of bytes input
|
||||
int cf_decompress(char *out, char *in )
|
||||
{
|
||||
int count;
|
||||
|
||||
char *param_out = out;
|
||||
|
||||
while(1) {
|
||||
|
||||
count = int(*in++);
|
||||
int run_span = count & 0x80;
|
||||
|
||||
count &= (~0x80);
|
||||
|
||||
if ( count > 0 ) {
|
||||
if ( run_span ) {
|
||||
// RLE'd data
|
||||
ubyte c = *in++;
|
||||
|
||||
memset( out, c, count );
|
||||
out += count;
|
||||
} else {
|
||||
memmove( out, in, count );
|
||||
in += count;
|
||||
out += count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return out - param_out;
|
||||
|
||||
}
|
||||
|
||||
#endif // 0
|
||||
|
||||
|
||||
// cfread() reads from a file and decompresses it
|
||||
//
|
||||
// returns: returns the number of full elements read
|
||||
//
|
||||
//
|
||||
int cfread_compressed(void *buf, int elsize, int nelem, CFILE *cfile)
|
||||
{
|
||||
char *out = (char *)buf;
|
||||
|
||||
while(1) {
|
||||
|
||||
ubyte count;
|
||||
|
||||
if ( cfread( &count, 1, 1, cfile ) != 1 ) {
|
||||
break;
|
||||
}
|
||||
|
||||
int run_span = count & 0x80;
|
||||
count &= (~0x80);
|
||||
count++;
|
||||
|
||||
if ( count > 0 ) {
|
||||
if ( run_span ) {
|
||||
// RLE'd data
|
||||
ubyte c;
|
||||
if ( cfread( &c, 1, 1, cfile ) != 1 ) {
|
||||
break;
|
||||
}
|
||||
memset( out, c, count );
|
||||
} else {
|
||||
if ( cfread( out, 1, count, cfile ) != count ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
out += count;
|
||||
if ( out >= (char *)buf + (elsize*nelem)) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (int)((out - (char *)buf)/elsize);
|
||||
}
|
||||
|
||||
int cfwrite_compressed(void *param_buf, int param_elsize, int param_nelem, CFILE *cfile)
|
||||
{
|
||||
char *in = (char *)param_buf;
|
||||
int bytecount = (param_elsize * param_nelem );
|
||||
|
||||
int pixcount; // number of pixels in the current packet
|
||||
char *inputpixel=NULL; // current input pixel position
|
||||
char *matchpixel=NULL; // pixel value to match for a run
|
||||
int rlcount; // current count in r.l. string
|
||||
int rlthresh; // minimum valid run length
|
||||
char *copyloc; // location to begin copying at
|
||||
|
||||
// set the threshold -- the minimum valid run length
|
||||
rlthresh = 2; // Require a 2 pixel span before rle'ing
|
||||
|
||||
// set the first pixel up
|
||||
|
||||
inputpixel = in;
|
||||
pixcount = 1;
|
||||
rlcount = 0;
|
||||
copyloc = (char *)0;
|
||||
|
||||
// loop till data processing complete
|
||||
do {
|
||||
|
||||
// if we have accumulated a 128-byte packet, process it
|
||||
if ( pixcount == 129 ) {
|
||||
ubyte code = 127;
|
||||
|
||||
// set the run flag if this is a run
|
||||
|
||||
if ( rlcount >= rlthresh ) {
|
||||
code |= 0x80;
|
||||
pixcount = 2;
|
||||
}
|
||||
|
||||
cfwrite( &code, 1, 1, cfile );
|
||||
|
||||
// copy the data into place
|
||||
cfwrite( copyloc, 1, pixcount-1, cfile );
|
||||
pixcount = 1;
|
||||
|
||||
// set up for next packet
|
||||
continue;
|
||||
}
|
||||
|
||||
// if zeroth byte, handle as special case
|
||||
if ( pixcount == 1 ) {
|
||||
rlcount = 0;
|
||||
copyloc = inputpixel; /* point to 1st guy in packet */
|
||||
matchpixel = inputpixel; /* set pointer to pix to match */
|
||||
pixcount = 2;
|
||||
inputpixel += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
// assembling a packet -- look at next pixel
|
||||
|
||||
// current pixel == match pixel?
|
||||
if ( *inputpixel == *matchpixel ) {
|
||||
|
||||
// establishing a run of enough length to
|
||||
// save space by doing it
|
||||
// -- write the non-run length packet
|
||||
// -- start run-length packet
|
||||
|
||||
if ( ++rlcount == rlthresh ) {
|
||||
|
||||
// close a non-run packet
|
||||
|
||||
if ( pixcount > (rlcount+1) ) {
|
||||
// write out length and do not set run flag
|
||||
|
||||
ubyte code = (ubyte)(pixcount - 2 - rlthresh);
|
||||
cfwrite( &code, 1, 1, cfile );
|
||||
|
||||
cfwrite( copyloc, 1, (pixcount-1-rlcount), cfile );
|
||||
copyloc = inputpixel;
|
||||
pixcount = rlcount + 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
// no match -- either break a run or continue without one
|
||||
// if a run exists break it:
|
||||
// write the bytes in the string (1+1)
|
||||
// start the next string
|
||||
|
||||
if ( rlcount >= rlthresh ) {
|
||||
|
||||
ubyte code = (ubyte)(0x80 | rlcount);
|
||||
cfwrite( &code, 1, 1, cfile );
|
||||
cfwrite( copyloc, 1, 1, cfile );
|
||||
pixcount = 1;
|
||||
continue;
|
||||
} else {
|
||||
|
||||
// not a match and currently not a run
|
||||
// - save the current pixel
|
||||
// - reset the run-length flag
|
||||
rlcount = 0;
|
||||
matchpixel = inputpixel;
|
||||
}
|
||||
}
|
||||
pixcount++;
|
||||
inputpixel += 1;
|
||||
} while ( inputpixel < (in + bytecount));
|
||||
|
||||
// quit this buffer without loosing any data
|
||||
if ( --pixcount >= 1 ) {
|
||||
ubyte code = ubyte(pixcount - 1);
|
||||
|
||||
// set the run flag if this is a run
|
||||
|
||||
if ( rlcount >= rlthresh ) {
|
||||
code |= 0x80;
|
||||
pixcount = 1;
|
||||
}
|
||||
|
||||
cfwrite( &code, 1, 1, cfile );
|
||||
|
||||
// copy the data into place
|
||||
cfwrite( copyloc, 1, pixcount, cfile );
|
||||
}
|
||||
|
||||
return param_nelem;
|
||||
}
|
||||
}
|
||||
+263
-209
@@ -48,9 +48,6 @@ enum CfileRootType {
|
||||
CF_ROOTTYPE_MEMORY = 2,
|
||||
};
|
||||
|
||||
// for a defined and specifically set location to get/send pilot/campaign files
|
||||
SCP_string Pilot_file_path;
|
||||
|
||||
// Created by:
|
||||
// specifying hard drive tree
|
||||
// searching for pack files on hard drive // Found by searching all known paths
|
||||
@@ -59,6 +56,7 @@ SCP_string Pilot_file_path;
|
||||
typedef struct cf_root {
|
||||
char path[CF_MAX_PATHNAME_LENGTH]; // Contains something like c:\projects\freespace or c:\projects\freespace\freespace.vp
|
||||
int roottype; // CF_ROOTTYPE_PATH = Path, CF_ROOTTYPE_PACK =Pack file, CF_ROOTTYPE_MEMORY=In memory
|
||||
uint32_t location_flags;
|
||||
} cf_root;
|
||||
|
||||
// convenient type for sorting (see cf_build_pack_list())
|
||||
@@ -347,9 +345,9 @@ void cf_build_pack_list( cf_root *root )
|
||||
std::sort(temp_roots_sort, temp_roots_sort + temp_root_count, cf_packfile_sort_func);
|
||||
|
||||
// now insert them all into the real root list properly
|
||||
cf_root *new_root;
|
||||
for (i = 0; i < temp_root_count; i++) {
|
||||
new_root = cf_create_root();
|
||||
auto new_root = cf_create_root();
|
||||
new_root->location_flags = root->location_flags;
|
||||
strcpy_s( new_root->path, root->path );
|
||||
|
||||
#ifndef NDEBUG
|
||||
@@ -378,10 +376,11 @@ static char normalize_directory_separator(char in)
|
||||
return in;
|
||||
}
|
||||
|
||||
static void cf_add_mod_roots(const char* rootDirectory)
|
||||
static void cf_add_mod_roots(const char* rootDirectory, uint32_t basic_location)
|
||||
{
|
||||
if (Cmdline_mod)
|
||||
{
|
||||
bool primary = true;
|
||||
for (const char* cur_pos=Cmdline_mod; strlen(cur_pos) != 0; cur_pos+= (strlen(cur_pos)+1))
|
||||
{
|
||||
SCP_stringstream ss;
|
||||
@@ -405,9 +404,16 @@ static void cf_add_mod_roots(const char* rootDirectory)
|
||||
cf_root* root = cf_create_root();
|
||||
|
||||
strncpy(root->path, rootPath.c_str(), CF_MAX_PATHNAME_LENGTH-1);
|
||||
if (primary) {
|
||||
root->location_flags = basic_location | CF_LOCATION_TYPE_PRIMARY_MOD;
|
||||
} else {
|
||||
root->location_flags = basic_location | CF_LOCATION_TYPE_SECONDARY_MODS;
|
||||
}
|
||||
|
||||
root->roottype = CF_ROOTTYPE_PATH;
|
||||
cf_build_pack_list(root);
|
||||
|
||||
primary = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -425,10 +431,16 @@ void cf_build_root_list(const char *cdrom_dir)
|
||||
#ifdef WIN32
|
||||
// Nothing to do here, Windows uses the current directory as the base
|
||||
#else
|
||||
cf_add_mod_roots(Cfile_user_dir_legacy);
|
||||
cf_add_mod_roots(os_get_legacy_user_dir(), CF_LOCATION_ROOT_USER);
|
||||
|
||||
root = cf_create_root();
|
||||
strncpy(root->path, Cfile_user_dir_legacy, CF_MAX_PATHNAME_LENGTH - 1);
|
||||
strncpy(root->path, os_get_legacy_user_dir(), CF_MAX_PATHNAME_LENGTH - 1);
|
||||
|
||||
root->location_flags |= CF_LOCATION_ROOT_USER | CF_LOCATION_TYPE_ROOT;
|
||||
if (Cmdline_mod == nullptr || strlen(Cmdline_mod) <= 0) {
|
||||
// If there are no mods then the root is the primary mod
|
||||
root->location_flags |= CF_LOCATION_TYPE_PRIMARY_MOD;
|
||||
}
|
||||
|
||||
// do we already have a slash? as in the case of a root directory install
|
||||
if ((strlen(root->path) < (CF_MAX_PATHNAME_LENGTH - 1)) && (root->path[strlen(root->path) - 1] != DIR_SEPARATOR_CHAR)) {
|
||||
@@ -436,10 +448,6 @@ void cf_build_root_list(const char *cdrom_dir)
|
||||
}
|
||||
root->roottype = CF_ROOTTYPE_PATH;
|
||||
|
||||
// If it wasn't set before, set the pilot path
|
||||
if (Pilot_file_path.empty())
|
||||
Pilot_file_path = root->path;
|
||||
|
||||
// Next, check any VP files under the current directory.
|
||||
cf_build_pack_list(root);
|
||||
#endif
|
||||
@@ -449,13 +457,19 @@ void cf_build_root_list(const char *cdrom_dir)
|
||||
{
|
||||
// =========================================================================
|
||||
// now look for mods under the users HOME directory to use before system ones
|
||||
cf_add_mod_roots(Cfile_user_dir);
|
||||
cf_add_mod_roots(Cfile_user_dir, CF_LOCATION_ROOT_USER);
|
||||
// =========================================================================
|
||||
|
||||
// =========================================================================
|
||||
// set users HOME directory as default for loading and saving files
|
||||
root = cf_create_root();
|
||||
strncpy(root->path, Cfile_user_dir, CF_MAX_PATHNAME_LENGTH - 1);
|
||||
strcpy_s(root->path, Cfile_user_dir);
|
||||
|
||||
root->location_flags |= CF_LOCATION_ROOT_USER | CF_LOCATION_TYPE_ROOT;
|
||||
if (Cmdline_mod == nullptr || strlen(Cmdline_mod) <= 0) {
|
||||
// If there are no mods then the root is the primary mod
|
||||
root->location_flags |= CF_LOCATION_TYPE_PRIMARY_MOD;
|
||||
}
|
||||
|
||||
// do we already have a slash? as in the case of a root directory install
|
||||
if ((strlen(root->path) < (CF_MAX_PATHNAME_LENGTH - 1)) && (root->path[strlen(root->path) - 1] != DIR_SEPARATOR_CHAR)) {
|
||||
@@ -463,10 +477,6 @@ void cf_build_root_list(const char *cdrom_dir)
|
||||
}
|
||||
root->roottype = CF_ROOTTYPE_PATH;
|
||||
|
||||
// set the default player location to here
|
||||
if (Pilot_file_path.empty())
|
||||
Pilot_file_path = root->path;
|
||||
|
||||
// Next, check any VP files under the current directory.
|
||||
cf_build_pack_list(root);
|
||||
// =========================================================================
|
||||
@@ -477,11 +487,17 @@ void cf_build_root_list(const char *cdrom_dir)
|
||||
if ( !_getcwd(working_directory, CF_MAX_PATHNAME_LENGTH ) ) {
|
||||
Error(LOCATION, "Can't get current working directory -- %d", errno );
|
||||
}
|
||||
|
||||
cf_add_mod_roots(working_directory);
|
||||
|
||||
cf_add_mod_roots(working_directory, CF_LOCATION_ROOT_GAME);
|
||||
|
||||
root = cf_create_root();
|
||||
|
||||
|
||||
root->location_flags |= CF_LOCATION_ROOT_GAME | CF_LOCATION_TYPE_ROOT;
|
||||
if (Cmdline_mod == nullptr || strlen(Cmdline_mod) <= 0) {
|
||||
// If there are no mods then the root is the primary mod
|
||||
root->location_flags |= CF_LOCATION_TYPE_PRIMARY_MOD;
|
||||
}
|
||||
|
||||
strcpy_s(root->path, working_directory);
|
||||
|
||||
size_t path_len = strlen(root->path);
|
||||
@@ -493,10 +509,6 @@ void cf_build_root_list(const char *cdrom_dir)
|
||||
|
||||
root->roottype = CF_ROOTTYPE_PATH;
|
||||
|
||||
// If the path wasn't set before use the working directory
|
||||
if ( Pilot_file_path.empty() )
|
||||
Pilot_file_path = root->path;
|
||||
|
||||
//======================================================
|
||||
// Next, check any VP files under the current directory.
|
||||
cf_build_pack_list(root);
|
||||
@@ -517,6 +529,7 @@ void cf_build_root_list(const char *cdrom_dir)
|
||||
|
||||
// The final root is the in-memory root
|
||||
root = cf_create_root();
|
||||
root->location_flags = CF_LOCATION_ROOT_MEMORY | CF_LOCATION_TYPE_ROOT;
|
||||
memset(root->path, 0, sizeof(root->path));
|
||||
root->roottype = CF_ROOTTYPE_MEMORY;
|
||||
|
||||
@@ -977,15 +990,12 @@ void cf_free_secondary_filelist()
|
||||
*
|
||||
* @param filespec Filename & extension
|
||||
* @param pathtype See CF_TYPE_ defines in CFILE.H
|
||||
* @param max_out Maximum string length that should be stuffed into pack_filename
|
||||
* @param pack_filename OUTPUT: Absolute path and filename of this file. Could be a packfile or the actual file.
|
||||
* @param size OUTPUT: File size
|
||||
* @param offset OUTPUT: Offset into pack file. 0 if not a packfile.
|
||||
* @param localize Undertake localization
|
||||
* @param location_flags Specifies where to search for the specified flag
|
||||
*
|
||||
* @return If not found returns 0.
|
||||
* @return A structure which describes the found file
|
||||
*/
|
||||
int cf_find_file_location( const char *filespec, int pathtype, int max_out, char *pack_filename, size_t *size, size_t *offset, bool localize, const void** data_out )
|
||||
CFileLocation cf_find_file_location(const char* filespec, int pathtype, bool localize, uint32_t location_flags)
|
||||
{
|
||||
int i;
|
||||
uint ui;
|
||||
@@ -993,7 +1003,6 @@ int cf_find_file_location( const char *filespec, int pathtype, int max_out, char
|
||||
char longname[MAX_PATH_LEN];
|
||||
|
||||
Assert( (filespec != NULL) && (strlen(filespec) > 0) ); //-V805
|
||||
Assert( (pack_filename == NULL) || (max_out > 1) );
|
||||
|
||||
// see if we have something other than just a filename
|
||||
// our current rules say that any file that specifies a direct
|
||||
@@ -1009,16 +1018,15 @@ int cf_find_file_location( const char *filespec, int pathtype, int max_out, char
|
||||
#endif
|
||||
FILE *fp = fopen(filespec, "rb" );
|
||||
if (fp) {
|
||||
if ( size ) *size = filelength(fileno(fp));
|
||||
if ( offset ) *offset = 0;
|
||||
if ( pack_filename ) {
|
||||
strncpy( pack_filename, filespec, max_out );
|
||||
}
|
||||
CFileLocation res(true);
|
||||
res.size = static_cast<size_t>(filelength(fileno(fp)));
|
||||
res.offset = 0;
|
||||
res.full_name = filespec;
|
||||
fclose(fp);
|
||||
return 1;
|
||||
return res;
|
||||
}
|
||||
|
||||
return 0; // If they give a full path, fail if not found.
|
||||
return CFileLocation(); // If they give a full path, fail if not found.
|
||||
}
|
||||
|
||||
// Search the hard drive for files first.
|
||||
@@ -1057,43 +1065,39 @@ int cf_find_file_location( const char *filespec, int pathtype, int max_out, char
|
||||
}
|
||||
|
||||
if (cfs_slow_search) {
|
||||
cf_create_default_path_string( longname, sizeof(longname)-1, search_order[ui], filespec, localize );
|
||||
cf_create_default_path_string(longname, sizeof(longname) - 1, search_order[ui], filespec, localize,
|
||||
location_flags);
|
||||
|
||||
#if defined _WIN32
|
||||
_finddata_t findstruct;
|
||||
|
||||
intptr_t findhandle = _findfirst(longname, &findstruct);
|
||||
if (findhandle != -1) {
|
||||
if (size)
|
||||
*size = findstruct.size;
|
||||
CFileLocation res;
|
||||
res.found = true;
|
||||
res.size = static_cast<size_t>(findstruct.size);
|
||||
|
||||
_findclose(findhandle);
|
||||
|
||||
if (offset)
|
||||
*offset = 0;
|
||||
res.offset = 0;
|
||||
res.full_name = longname;
|
||||
|
||||
if (pack_filename)
|
||||
strncpy( pack_filename, longname, max_out );
|
||||
|
||||
return 1;
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
{
|
||||
FILE *fp = fopen(longname, "rb" );
|
||||
|
||||
if (fp) {
|
||||
if (size)
|
||||
*size = filelength( fileno(fp) );
|
||||
CFileLocation res(true);
|
||||
res.size = static_cast<size_t>(filelength( fileno(fp) ));
|
||||
|
||||
fclose(fp);
|
||||
|
||||
if (offset)
|
||||
*offset = 0;
|
||||
res.offset = 0;
|
||||
res.full_name = longname;
|
||||
|
||||
if (pack_filename)
|
||||
strncpy(pack_filename, longname, max_out);
|
||||
|
||||
return 1;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1107,6 +1111,15 @@ int cf_find_file_location( const char *filespec, int pathtype, int max_out, char
|
||||
if ( (pathtype != CF_TYPE_ANY) && (pathtype != f->pathtype_index) )
|
||||
continue;
|
||||
|
||||
if (location_flags != CF_LOCATION_ALL) {
|
||||
// If a location flag was specified we need to check if the root of this file satisfies the request
|
||||
auto root = cf_get_root(f->root_index);
|
||||
|
||||
if (!cf_check_location_flags(root->location_flags, location_flags)) {
|
||||
// Root does not satisfy location flags
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (localize) {
|
||||
// create localized filespec
|
||||
@@ -1114,70 +1127,58 @@ int cf_find_file_location( const char *filespec, int pathtype, int max_out, char
|
||||
|
||||
if ( lcl_add_dir_to_path_with_filename(longname, MAX_PATH_LEN - 1) ) {
|
||||
if ( !stricmp(longname, f->name_ext) ) {
|
||||
if (size)
|
||||
*size = f->size;
|
||||
CFileLocation res(true);
|
||||
res.size = static_cast<size_t>(f->size);
|
||||
res.offset = (size_t)f->pack_offset;
|
||||
res.data_ptr = f->data;
|
||||
|
||||
if (offset)
|
||||
*offset = (size_t)f->pack_offset;
|
||||
if (f->data != nullptr) {
|
||||
// This is an in-memory file so we just copy the pathtype name + file name
|
||||
res.full_name = Pathtypes[f->pathtype_index].path;
|
||||
res.full_name += DIR_SEPARATOR_STR;
|
||||
res.full_name += f->name_ext;
|
||||
} else if (f->pack_offset < 1) {
|
||||
// This is a real file, return the actual file path
|
||||
res.full_name = f->real_name;
|
||||
} else {
|
||||
// File is in a pack file
|
||||
cf_root *r = cf_get_root(f->root_index);
|
||||
|
||||
if (data_out)
|
||||
*data_out = f->data;
|
||||
|
||||
if (pack_filename) {
|
||||
if (f->data != nullptr) {
|
||||
// This is an in-memory file so we just copy the pathtype name + file name
|
||||
strncpy(pack_filename, Pathtypes[f->pathtype_index].path, max_out);
|
||||
strncat(pack_filename, DIR_SEPARATOR_STR, max_out);
|
||||
strncat(pack_filename, f->name_ext, max_out);
|
||||
} else if (f->pack_offset < 1) {
|
||||
// This is a real file, return the actual file path
|
||||
strncpy( pack_filename, f->real_name, max_out );
|
||||
} else {
|
||||
// File is in a pack file
|
||||
cf_root *r = cf_get_root(f->root_index);
|
||||
|
||||
strncpy( pack_filename, r->path, max_out );
|
||||
}
|
||||
res.full_name = r->path;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// file either not localized or localized version not found
|
||||
if ( !stricmp(filespec, f->name_ext) ) {
|
||||
if (size)
|
||||
*size = f->size;
|
||||
CFileLocation res(true);
|
||||
res.size = static_cast<size_t>(f->size);
|
||||
res.offset = (size_t)f->pack_offset;
|
||||
res.data_ptr = f->data;
|
||||
|
||||
if (offset)
|
||||
*offset = (size_t)f->pack_offset;
|
||||
if (f->data != nullptr) {
|
||||
// This is an in-memory file so we just copy the pathtype name + file name
|
||||
res.full_name = Pathtypes[f->pathtype_index].path;
|
||||
res.full_name += DIR_SEPARATOR_STR;
|
||||
res.full_name += f->name_ext;
|
||||
} else if (f->pack_offset < 1) {
|
||||
// This is a real file, return the actual file path
|
||||
res.full_name = f->real_name;
|
||||
} else {
|
||||
// File is in a pack file
|
||||
cf_root *r = cf_get_root(f->root_index);
|
||||
|
||||
if (data_out)
|
||||
*data_out = f->data;
|
||||
|
||||
if (pack_filename) {
|
||||
if (f->data != nullptr) {
|
||||
// This is an in-memory file so we just copy the pathtype name + file name
|
||||
strncpy(pack_filename, Pathtypes[f->pathtype_index].path, max_out);
|
||||
strncat(pack_filename, DIR_SEPARATOR_STR, max_out);
|
||||
strncat(pack_filename, f->name_ext, max_out);
|
||||
} else if (f->pack_offset < 1) {
|
||||
// This is a real file, return the actual file path
|
||||
strncpy( pack_filename, f->real_name, max_out );
|
||||
} else {
|
||||
// File is in a pack file
|
||||
cf_root *r = cf_get_root(f->root_index);
|
||||
|
||||
strncpy( pack_filename, r->path, max_out );
|
||||
}
|
||||
res.full_name = r->path;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return CFileLocation();
|
||||
}
|
||||
|
||||
// -- from parselo.cpp --
|
||||
@@ -1194,14 +1195,11 @@ extern char *stristr(char *str, const char *substr);
|
||||
* @param ext_list Extension filter list
|
||||
* @param pathtype See CF_TYPE_ defines in CFILE.H
|
||||
* @param max_out Maximum string length that should be stuffed into pack_filename
|
||||
* @param pack_filename OUTPUT: Absolute path and filename of this file. Could be a packfile or the actual file.
|
||||
* @param size OUTPUT: File size
|
||||
* @param offset OUTPUT: Offset into pack file. 0 if not a packfile.
|
||||
* @param localize Undertake localization
|
||||
*
|
||||
* @return If not found returns -1, else returns offset into ext_list.
|
||||
* @return A structure containing information about the found file
|
||||
*/
|
||||
int cf_find_file_location_ext( const char *filename, const int ext_num, const char **ext_list, int pathtype, int max_out, char *pack_filename, size_t *size, size_t *offset, bool localize, const void** data_out)
|
||||
CFileLocationExt cf_find_file_location_ext( const char *filename, const int ext_num, const char **ext_list, int pathtype, bool localize)
|
||||
{
|
||||
int cur_ext, i;
|
||||
uint ui;
|
||||
@@ -1213,7 +1211,6 @@ int cf_find_file_location_ext( const char *filename, const int ext_num, const ch
|
||||
Assert( (filename != NULL) && (strlen(filename) < MAX_FILENAME_LEN) );
|
||||
Assert( (ext_list != NULL) && (ext_num > 1) ); // if we are searching for just one ext
|
||||
// then this is the wrong function to use
|
||||
Assert( (pack_filename == NULL) || (max_out > 1) );
|
||||
|
||||
|
||||
// if we have a full path already then fail. this function if for searching via filter only!
|
||||
@@ -1223,7 +1220,7 @@ int cf_find_file_location_ext( const char *filename, const int ext_num, const ch
|
||||
if ( strpbrk(filename,"/\\:") ) { // do we have a full path already?
|
||||
#endif
|
||||
Int3();
|
||||
return 0;
|
||||
return CFileLocationExt();
|
||||
}
|
||||
|
||||
// Search the hard drive for files first.
|
||||
@@ -1281,44 +1278,35 @@ int cf_find_file_location_ext( const char *filename, const int ext_num, const ch
|
||||
|
||||
#if defined _WIN32
|
||||
_finddata_t findstruct;
|
||||
|
||||
intptr_t findhandle = _findfirst(longname, &findstruct);
|
||||
if (findhandle != -1) {
|
||||
if (size)
|
||||
*size = findstruct.size;
|
||||
|
||||
if (data_out)
|
||||
*data_out = nullptr;
|
||||
CFileLocationExt res(cur_ext);
|
||||
res.found = true;
|
||||
res.size = static_cast<size_t>(findstruct.size);
|
||||
|
||||
_findclose(findhandle);
|
||||
|
||||
if (offset)
|
||||
*offset = 0;
|
||||
res.offset = 0;
|
||||
res.full_name = longname;
|
||||
|
||||
if (pack_filename)
|
||||
strncpy( pack_filename, longname, max_out );
|
||||
|
||||
return cur_ext;
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
{
|
||||
FILE *fp = fopen(longname, "rb" );
|
||||
|
||||
if (fp) {
|
||||
if (size)
|
||||
*size = filelength( fileno(fp) );
|
||||
|
||||
if (data_out)
|
||||
*data_out = nullptr;
|
||||
CFileLocationExt res(cur_ext);
|
||||
res.found = true;
|
||||
res.size = static_cast<size_t>(filelength( fileno(fp) ));
|
||||
|
||||
fclose(fp);
|
||||
|
||||
if (offset)
|
||||
*offset = 0;
|
||||
res.offset = 0;
|
||||
res.full_name = longname;
|
||||
|
||||
if (pack_filename)
|
||||
strncpy(pack_filename, longname, max_out);
|
||||
|
||||
return cur_ext;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1403,76 +1391,62 @@ int cf_find_file_location_ext( const char *filename, const int ext_num, const ch
|
||||
|
||||
if ( lcl_add_dir_to_path_with_filename(longname, MAX_PATH_LEN - 1) ) {
|
||||
if ( !stricmp(longname, f->name_ext) ) {
|
||||
if (size)
|
||||
*size = f->size;
|
||||
CFileLocationExt res(cur_ext);
|
||||
res.found = true;
|
||||
res.size = static_cast<size_t>(f->size);
|
||||
res.offset = (size_t)f->pack_offset;
|
||||
res.data_ptr = f->data;
|
||||
|
||||
if (offset)
|
||||
*offset = f->pack_offset;
|
||||
if (f->data != nullptr) {
|
||||
// This is an in-memory file so we just copy the pathtype name + file name
|
||||
res.full_name = Pathtypes[f->pathtype_index].path;
|
||||
res.full_name += DIR_SEPARATOR_STR;
|
||||
res.full_name += f->name_ext;
|
||||
} else if (f->pack_offset < 1) {
|
||||
// This is a real file, return the actual file path
|
||||
res.full_name = f->real_name;
|
||||
} else {
|
||||
// File is in a pack file
|
||||
cf_root *r = cf_get_root(f->root_index);
|
||||
|
||||
if (data_out)
|
||||
*data_out = f->data;
|
||||
|
||||
if (pack_filename) {
|
||||
if (f->data != nullptr) {
|
||||
// This is an in-memory file so we just copy the pathtype name + file name
|
||||
strncpy(pack_filename, Pathtypes[f->pathtype_index].path, max_out);
|
||||
strncat(pack_filename, DIR_SEPARATOR_STR, max_out);
|
||||
strncat(pack_filename, f->name_ext, max_out);
|
||||
}
|
||||
else if (f->pack_offset < 1) {
|
||||
// This is a real file, return the actual file path
|
||||
strncpy(pack_filename, f->real_name, max_out);
|
||||
}
|
||||
else {
|
||||
// File is in a pack file
|
||||
cf_root *r = cf_get_root(f->root_index);
|
||||
|
||||
strncpy(pack_filename, r->path, max_out);
|
||||
}
|
||||
res.full_name = r->path;
|
||||
}
|
||||
|
||||
// found it, so cleanup and return
|
||||
file_list_index.clear();
|
||||
|
||||
return cur_ext;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// file either not localized or localized version not found
|
||||
if ( !stricmp(filespec, f->name_ext) ) {
|
||||
if (size)
|
||||
*size = f->size;
|
||||
CFileLocationExt res(cur_ext);
|
||||
res.found = true;
|
||||
res.size = static_cast<size_t>(f->size);
|
||||
res.offset = (size_t)f->pack_offset;
|
||||
res.data_ptr = f->data;
|
||||
|
||||
if (offset)
|
||||
*offset = f->pack_offset;
|
||||
if (f->data != nullptr) {
|
||||
// This is an in-memory file so we just copy the pathtype name + file name
|
||||
res.full_name = Pathtypes[f->pathtype_index].path;
|
||||
res.full_name += DIR_SEPARATOR_STR;
|
||||
res.full_name += f->name_ext;
|
||||
} else if (f->pack_offset < 1) {
|
||||
// This is a real file, return the actual file path
|
||||
res.full_name = f->real_name;
|
||||
} else {
|
||||
// File is in a pack file
|
||||
cf_root *r = cf_get_root(f->root_index);
|
||||
|
||||
if (data_out)
|
||||
*data_out = f->data;
|
||||
|
||||
if (pack_filename) {
|
||||
if (f->data != nullptr) {
|
||||
// This is an in-memory file so we just copy the pathtype name + file name
|
||||
strncpy(pack_filename, Pathtypes[f->pathtype_index].path, max_out);
|
||||
strncat(pack_filename, DIR_SEPARATOR_STR, max_out);
|
||||
strncat(pack_filename, f->name_ext, max_out);
|
||||
}
|
||||
else if (f->pack_offset < 1) {
|
||||
// This is a real file, return the actual file path
|
||||
strncpy(pack_filename, f->real_name, max_out);
|
||||
}
|
||||
else {
|
||||
// File is in a pack file
|
||||
cf_root *r = cf_get_root(f->root_index);
|
||||
|
||||
strncpy(pack_filename, r->path, max_out);
|
||||
}
|
||||
res.full_name = r->path;
|
||||
}
|
||||
|
||||
// found it, so cleanup and return
|
||||
file_list_index.clear();
|
||||
|
||||
return cur_ext;
|
||||
return res;
|
||||
}
|
||||
|
||||
// ok, we're still here, so strip off the extension again in order to
|
||||
@@ -1483,7 +1457,7 @@ int cf_find_file_location_ext( const char *filename, const int ext_num, const ch
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
return CFileLocationExt();
|
||||
}
|
||||
|
||||
|
||||
@@ -1582,7 +1556,8 @@ static int cf_file_already_in_list( SCP_vector<SCP_string> &list, const char *fi
|
||||
// This one has a 'type', which is a CF_TYPE_* value. Because this specifies the directory
|
||||
// location, 'filter' only needs to be the filter itself, with no path information.
|
||||
// See above descriptions of cf_get_file_list() for more information about how it all works.
|
||||
int cf_get_file_list( SCP_vector<SCP_string> &list, int pathtype, const char *filter, int sort, SCP_vector<file_list_info> *info )
|
||||
int cf_get_file_list(SCP_vector<SCP_string>& list, int pathtype, const char* filter, int sort,
|
||||
SCP_vector<file_list_info>* info, uint32_t location_flags)
|
||||
{
|
||||
char *ptr;
|
||||
uint i;
|
||||
@@ -1610,7 +1585,8 @@ int cf_get_file_list( SCP_vector<SCP_string> &list, int pathtype, const char *fi
|
||||
}
|
||||
|
||||
#if defined _WIN32
|
||||
cf_create_default_path_string( filespec, sizeof(filespec)-1, pathtype, (char*)Get_file_list_child );
|
||||
cf_create_default_path_string(filespec, sizeof(filespec) - 1, pathtype, (char*)Get_file_list_child, false,
|
||||
location_flags);
|
||||
strcat_s(filespec, DIR_SEPARATOR_STR);
|
||||
strcat_s(filespec, filter);
|
||||
|
||||
@@ -1650,7 +1626,8 @@ int cf_get_file_list( SCP_vector<SCP_string> &list, int pathtype, const char *fi
|
||||
}
|
||||
|
||||
#elif defined SCP_UNIX
|
||||
cf_create_default_path_string( filespec, sizeof(filespec)-1, pathtype, (char*)Get_file_list_child );
|
||||
cf_create_default_path_string(filespec, sizeof(filespec) - 1, pathtype, (char*)Get_file_list_child, false,
|
||||
location_flags);
|
||||
|
||||
DIR *dirp;
|
||||
struct dirent *dir;
|
||||
@@ -1718,6 +1695,16 @@ int cf_get_file_list( SCP_vector<SCP_string> &list, int pathtype, const char *fi
|
||||
continue;
|
||||
}
|
||||
|
||||
if (location_flags != CF_LOCATION_ALL) {
|
||||
// If a location flag was specified we need to check if the root of this file satisfies the request
|
||||
auto root = cf_get_root(f->root_index);
|
||||
|
||||
if (!cf_check_location_flags(root->location_flags, location_flags)) {
|
||||
// Root does not satisfy location flags
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !cf_matches_spec( filter,f->name_ext)) {
|
||||
continue;
|
||||
}
|
||||
@@ -1795,7 +1782,8 @@ int cf_file_already_in_list( int num_files, char **list, const char *filename )
|
||||
// This one has a 'type', which is a CF_TYPE_* value. Because this specifies the directory
|
||||
// location, 'filter' only needs to be the filter itself, with no path information.
|
||||
// See above descriptions of cf_get_file_list() for more information about how it all works.
|
||||
int cf_get_file_list( int max, char **list, int pathtype, const char *filter, int sort, file_list_info *info )
|
||||
int cf_get_file_list(int max, char** list, int pathtype, const char* filter, int sort, file_list_info* info,
|
||||
uint32_t location_flags)
|
||||
{
|
||||
char *ptr;
|
||||
uint i;
|
||||
@@ -1818,7 +1806,7 @@ int cf_get_file_list( int max, char **list, int pathtype, const char *filter, in
|
||||
char filespec[MAX_PATH_LEN];
|
||||
|
||||
#if defined _WIN32
|
||||
cf_create_default_path_string( filespec, sizeof(filespec)-1, pathtype, filter );
|
||||
cf_create_default_path_string(filespec, sizeof(filespec) - 1, pathtype, filter, false, location_flags);
|
||||
|
||||
_finddata_t find;
|
||||
intptr_t find_handle;
|
||||
@@ -1859,7 +1847,7 @@ int cf_get_file_list( int max, char **list, int pathtype, const char *filter, in
|
||||
}
|
||||
|
||||
#elif defined SCP_UNIX
|
||||
cf_create_default_path_string( filespec, sizeof(filespec)-1, pathtype, NULL );
|
||||
cf_create_default_path_string(filespec, sizeof(filespec) - 1, pathtype, nullptr, false, location_flags);
|
||||
|
||||
DIR *dirp;
|
||||
struct dirent *dir;
|
||||
@@ -1932,6 +1920,16 @@ int cf_get_file_list( int max, char **list, int pathtype, const char *filter, in
|
||||
continue;
|
||||
}
|
||||
|
||||
if (location_flags != CF_LOCATION_ALL) {
|
||||
// If a location flag was specified we need to check if the root of this file satisfies the request
|
||||
auto root = cf_get_root(f->root_index);
|
||||
|
||||
if (!cf_check_location_flags(root->location_flags, location_flags)) {
|
||||
// Root does not satisfy location flags
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (num_files >= max)
|
||||
break;
|
||||
|
||||
@@ -2015,7 +2013,8 @@ int cf_file_already_in_list_preallocated( int num_files, char arr[][MAX_FILENAME
|
||||
// This one has a 'type', which is a CF_TYPE_* value. Because this specifies the directory
|
||||
// location, 'filter' only needs to be the filter itself, with no path information.
|
||||
// See above descriptions of cf_get_file_list() for more information about how it all works.
|
||||
int cf_get_file_list_preallocated( int max, char arr[][MAX_FILENAME_LEN], char **list, int pathtype, const char *filter, int sort, file_list_info *info )
|
||||
int cf_get_file_list_preallocated(int max, char arr[][MAX_FILENAME_LEN], char** list, int pathtype, const char* filter,
|
||||
int sort, file_list_info* info, uint32_t location_flags)
|
||||
{
|
||||
int num_files = 0, own_flag = 0;
|
||||
|
||||
@@ -2044,7 +2043,7 @@ int cf_get_file_list_preallocated( int max, char arr[][MAX_FILENAME_LEN], char *
|
||||
|
||||
// Search the default directories
|
||||
#if defined _WIN32
|
||||
cf_create_default_path_string( filespec, sizeof(filespec)-1, pathtype, filter );
|
||||
cf_create_default_path_string(filespec, sizeof(filespec) - 1, pathtype, filter, false, location_flags);
|
||||
|
||||
intptr_t find_handle;
|
||||
_finddata_t find;
|
||||
@@ -2085,7 +2084,7 @@ int cf_get_file_list_preallocated( int max, char arr[][MAX_FILENAME_LEN], char *
|
||||
}
|
||||
|
||||
#elif defined SCP_UNIX
|
||||
cf_create_default_path_string( filespec, sizeof(filespec)-1, pathtype, NULL );
|
||||
cf_create_default_path_string(filespec, sizeof(filespec) - 1, pathtype, nullptr, false, location_flags);
|
||||
|
||||
DIR *dirp;
|
||||
struct dirent *dir;
|
||||
@@ -2121,7 +2120,7 @@ int cf_get_file_list_preallocated( int max, char arr[][MAX_FILENAME_LEN], char *
|
||||
|
||||
if ( !Get_file_list_filter || (*Get_file_list_filter)(dir->d_name) ) {
|
||||
|
||||
strncpy(arr[num_files], dir->d_name, MAX_FILENAME_LEN - 1 );
|
||||
strcpy_s(arr[num_files], dir->d_name );
|
||||
char *ptr = strrchr(arr[num_files], '.');
|
||||
if ( ptr ) {
|
||||
*ptr = 0;
|
||||
@@ -2156,6 +2155,16 @@ int cf_get_file_list_preallocated( int max, char arr[][MAX_FILENAME_LEN], char *
|
||||
continue;
|
||||
}
|
||||
|
||||
if (location_flags != CF_LOCATION_ALL) {
|
||||
// If a location flag was specified we need to check if the root of this file satisfies the request
|
||||
auto root = cf_get_root(f->root_index);
|
||||
|
||||
if (!cf_check_location_flags(root->location_flags, location_flags)) {
|
||||
// Root does not satisfy location flags
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (num_files >= max)
|
||||
|
||||
break;
|
||||
@@ -2222,7 +2231,8 @@ int cf_get_file_list_preallocated( int max, char arr[][MAX_FILENAME_LEN], char *
|
||||
// filename - optional, if set, tacks the filename onto end of path.
|
||||
// Output: path - Fully qualified pathname.
|
||||
//Returns 0 if the result would be too long (invalid result)
|
||||
int cf_create_default_path_string(char *path, uint path_max, int pathtype, const char *filename, bool localize )
|
||||
int cf_create_default_path_string(char* path, uint path_max, int pathtype, const char* filename, bool localize,
|
||||
uint32_t location_flags)
|
||||
{
|
||||
#ifdef SCP_UNIX
|
||||
if ( filename && strpbrk(filename,"/") ) {
|
||||
@@ -2233,7 +2243,22 @@ int cf_create_default_path_string(char *path, uint path_max, int pathtype, const
|
||||
strncpy( path, filename, path_max );
|
||||
|
||||
} else {
|
||||
cf_root *root = cf_get_root(0);
|
||||
cf_root* root = nullptr;
|
||||
|
||||
for (auto i = 0; i < Num_roots; ++i) {
|
||||
auto current_root = cf_get_root(i);
|
||||
|
||||
if (current_root->roottype != CF_ROOTTYPE_PATH) {
|
||||
// We want a "real" path here so only path roots are valid
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cf_check_location_flags(current_root->location_flags, location_flags)) {
|
||||
// We found a valid root
|
||||
root = current_root;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!root) {
|
||||
Assert( filename != NULL );
|
||||
@@ -2243,12 +2268,7 @@ int cf_create_default_path_string(char *path, uint path_max, int pathtype, const
|
||||
|
||||
Assert(CF_TYPE_SPECIFIED(pathtype));
|
||||
|
||||
// force a specific directory to search for player files
|
||||
if ( (pathtype == CF_TYPE_PLAYERS) || (pathtype == CF_TYPE_SINGLE_PLAYERS) || (pathtype == CF_TYPE_MULTI_PLAYERS) ) {
|
||||
strncpy(path, Pilot_file_path.c_str(), path_max);
|
||||
} else {
|
||||
strncpy(path, root->path, path_max);
|
||||
}
|
||||
strncpy(path, root->path, path_max);
|
||||
|
||||
strcat_s(path, path_max, Pathtypes[pathtype].path);
|
||||
|
||||
@@ -2294,7 +2314,8 @@ int cf_create_default_path_string(char *path, uint path_max, int pathtype, const
|
||||
// filename - optional, if set, tacks the filename onto end of path.
|
||||
// Output: path - Fully qualified pathname.
|
||||
//Returns 0 if the result would be too long (invalid result)
|
||||
int cf_create_default_path_string( SCP_string &path, int pathtype, const char *filename, bool /*localize*/ )
|
||||
int cf_create_default_path_string(SCP_string& path, int pathtype, const char* filename, bool /*localize*/,
|
||||
uint32_t location_flags)
|
||||
{
|
||||
#ifdef SCP_UNIX
|
||||
if ( filename && strpbrk(filename,"/") ) {
|
||||
@@ -2305,7 +2326,22 @@ int cf_create_default_path_string( SCP_string &path, int pathtype, const char *f
|
||||
path.assign(filename);
|
||||
|
||||
} else {
|
||||
cf_root *root = cf_get_root(0);
|
||||
cf_root* root = nullptr;
|
||||
|
||||
for (auto i = 0; i < Num_roots; ++i) {
|
||||
auto current_root = cf_get_root(i);
|
||||
|
||||
if (current_root->roottype != CF_ROOTTYPE_PATH) {
|
||||
// We want a "real" path here so only path roots are valid
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cf_check_location_flags(current_root->location_flags, location_flags)) {
|
||||
// We found a valid root
|
||||
root = current_root;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!root) {
|
||||
Assert( filename != NULL );
|
||||
@@ -2316,12 +2352,7 @@ int cf_create_default_path_string( SCP_string &path, int pathtype, const char *f
|
||||
Assert(CF_TYPE_SPECIFIED(pathtype));
|
||||
std::ostringstream s_path;
|
||||
|
||||
// force a specific directory to search for player files
|
||||
if ( (pathtype == CF_TYPE_PLAYERS) || (pathtype == CF_TYPE_SINGLE_PLAYERS) || (pathtype == CF_TYPE_MULTI_PLAYERS) ) {
|
||||
s_path << Pilot_file_path;
|
||||
} else {
|
||||
s_path << root->path;
|
||||
}
|
||||
s_path << root->path;
|
||||
|
||||
s_path << Pathtypes[pathtype].path;
|
||||
|
||||
@@ -2386,3 +2417,26 @@ void cfile_spew_pack_file_crcs()
|
||||
|
||||
fclose(out);
|
||||
}
|
||||
|
||||
bool cf_check_location_flags(uint32_t check_flags, uint32_t desired_flags)
|
||||
{
|
||||
Assertion((check_flags & CF_LOCATION_ROOT_MASK) != 0, "check_flags must have a valid root value");
|
||||
Assertion((check_flags & CF_LOCATION_TYPE_MASK) != 0, "check_flags must have a valid type value");
|
||||
|
||||
auto check_root = check_flags & CF_LOCATION_ROOT_MASK;
|
||||
auto desired_root_flags = desired_flags & CF_LOCATION_ROOT_MASK;
|
||||
|
||||
// If the root part is not set then assume that every root matches
|
||||
if (desired_root_flags != 0 && (check_root & desired_root_flags) == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto check_type = check_flags & CF_LOCATION_TYPE_MASK;
|
||||
auto desired_type_flags = desired_flags & CF_LOCATION_TYPE_MASK;
|
||||
|
||||
if (desired_type_flags != 0 && (check_type & desired_type_flags) == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -29,6 +29,8 @@ typedef struct cf_pathtype {
|
||||
// During cfile_init, verify that Pathtypes[n].index == n for each item
|
||||
extern cf_pathtype Pathtypes[CF_MAX_PATH_TYPES];
|
||||
|
||||
bool cf_check_location_flags(uint32_t check_flags, uint32_t desired_flags);
|
||||
|
||||
// Returns the default storage path for files given a
|
||||
// particular pathtype. In other words, the path to
|
||||
// the unpacked, non-cd'd, stored on hard drive path.
|
||||
@@ -39,7 +41,9 @@ extern cf_pathtype Pathtypes[CF_MAX_PATH_TYPES];
|
||||
// filename - optional, if set, tacks the filename onto end of path.
|
||||
// Output: path - Fully qualified pathname.
|
||||
//Returns 0 if result would be too long (invalid result)
|
||||
int cf_create_default_path_string( char *path, uint path_max, int pathtype, const char *filename=NULL, bool localize = false);
|
||||
int cf_create_default_path_string( SCP_string &path, int pathtype, const char *filename=NULL, bool localize = false );
|
||||
int cf_create_default_path_string(char* path, uint path_max, int pathtype, const char* filename = nullptr,
|
||||
bool localize = false, uint32_t location_flags = CF_LOCATION_ALL);
|
||||
int cf_create_default_path_string(SCP_string& path, int pathtype, const char* filename = nullptr, bool localize = false,
|
||||
uint32_t location_flags = CF_LOCATION_ALL);
|
||||
|
||||
#endif //_CFILESYSTEM_H
|
||||
+10
-28
@@ -173,7 +173,6 @@ Flag exe_params[] =
|
||||
{ "-no_deferred", "Disable Deferred Lighting", true, EASY_DEFAULT_MEM, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_deferred"},
|
||||
{ "-enable_shadows", "Enable Shadows", true, EASY_MEM_ALL_ON, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_shadows"},
|
||||
{ "-no_vsync", "Disable vertical sync", true, 0, EASY_DEFAULT, "Game Speed", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_vsync", },
|
||||
{ "-cache_bitmaps", "Cache bitmaps between missions", true, 0, EASY_DEFAULT_MEM, "Game Speed", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-cache_bitmaps", },
|
||||
|
||||
{ "-dualscanlines", "Add another pair of scanning lines", true, 0, EASY_DEFAULT, "HUD", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-dualscanlines", },
|
||||
{ "-targetinfo", "Enable info next to target", true, 0, EASY_DEFAULT, "HUD", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-targetinfo", },
|
||||
@@ -205,7 +204,6 @@ Flag exe_params[] =
|
||||
{ "-no_set_gamma", "Disable setting of gamma", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_set_gamma", },
|
||||
{ "-nomovies", "Disable video playback", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-nomovies", },
|
||||
{ "-noparseerrors", "Disable parsing errors", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-noparseerrors", },
|
||||
{ "-query_speech", "Check if this build has speech", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-query_speech", },
|
||||
{ "-loadallweps", "Load all weapons, even those not used", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-loadallweps", },
|
||||
{ "-disable_fbo", "Disable OpenGL RenderTargets", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-disable_fbo", },
|
||||
{ "-disable_pbo", "Disable OpenGL Pixel Buffer Objects", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-disable_pbo", },
|
||||
@@ -213,7 +211,6 @@ Flag exe_params[] =
|
||||
{ "-no_3d_sound", "Use only 2D/stereo for sound effects", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_3d_sound", },
|
||||
{ "-mipmap", "Enable mipmapping", true, 0, EASY_DEFAULT_MEM, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-mipmap", },
|
||||
{ "-use_gldrawelements","Don't use glDrawRangeElements", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-use_gldrawelements", },
|
||||
{ "-old_collision", "Use old collision detection system", true, EASY_DEFAULT, EASY_ALL_ON, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-old_collision", },
|
||||
{ "-gl_finish", "Fix input lag on some ATI+Linux systems", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-gl_finish", },
|
||||
{ "-no_geo_effects", "Disable geometry shader for effects", true, 0, EASY_DEFAULT, "Troubleshoot", "", },
|
||||
{ "-set_cpu_affinity", "Sets processor affinity to config value", true, 0, EASY_DEFAULT, "Troubleshoot", "", },
|
||||
@@ -233,7 +230,6 @@ Flag exe_params[] =
|
||||
{ "-fullscreen_window", "Run in fullscreen window", false, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-fullscreen_window", },
|
||||
{ "-stats", "Show statistics", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-stats", },
|
||||
{ "-coords", "Show coordinates", false, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-coords", },
|
||||
{ "-show_mem_usage", "Show memory usage", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-show_mem_usage", },
|
||||
{ "-pofspew", "Generate all ibx files immediately", false, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-pofspew", },
|
||||
{ "-tablecrcs", "Dump table CRCs for multi validation", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-tablecrcs", },
|
||||
{ "-missioncrcs", "Dump mission CRCs for multi validation", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-missioncrcs", },
|
||||
@@ -248,7 +244,6 @@ Flag exe_params[] =
|
||||
{ "-no_unfocused_pause","Don't pause if the window isn't focused", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_unfocused_pause", },
|
||||
{ "-benchmark_mode", "Puts the game into benchmark mode", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-benchmark_mode", },
|
||||
{ "-noninteractive", "Disables interactive dialogs", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-noninteractive", },
|
||||
{ "-json_pilot", "Dump pilot files in JSON format", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-json_pilot", },
|
||||
{ "-json_profiling", "Generate JSON profiling output", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-json_profiling", },
|
||||
{ "-profile_frame_time","Profile engine subsystems", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-profile_frame_timings", },
|
||||
{ "-debug_window", "Enable the debug window", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-debug_window", },
|
||||
@@ -363,11 +358,9 @@ int Cmdline_no_deferred_lighting = 0;
|
||||
int Cmdline_aniso_level = 0;
|
||||
|
||||
// Game Speed related
|
||||
cmdline_parm cache_bitmaps_arg("-cache_bitmaps", NULL, AT_NONE); // Cmdline_cache_bitmaps
|
||||
cmdline_parm no_fpscap("-no_fps_capping", "Don't limit frames-per-second", AT_NONE); // Cmdline_NoFPSCap
|
||||
cmdline_parm no_vsync_arg("-no_vsync", NULL, AT_NONE); // Cmdline_no_vsync
|
||||
|
||||
int Cmdline_cache_bitmaps = 0; // caching of bitmaps between missions (faster loads, can hit swap on reload with <512 Meg RAM though) - taylor
|
||||
int Cmdline_NoFPSCap = 0; // Disable FPS capping - kazan
|
||||
int Cmdline_no_vsync = 0;
|
||||
|
||||
@@ -400,10 +393,8 @@ int Cmdline_autopilot_interruptable = 1;
|
||||
int Cmdline_stretch_menu = 0;
|
||||
|
||||
// Audio related
|
||||
cmdline_parm query_speech_arg("-query_speech", NULL, AT_NONE); // Cmdline_query_speech
|
||||
cmdline_parm voice_recognition_arg("-voicer", NULL, AT_NONE); // Cmdline_voice_recognition
|
||||
|
||||
int Cmdline_query_speech = 0;
|
||||
int Cmdline_voice_recognition = 0;
|
||||
int Cmdline_no_enhanced_sound = 0;
|
||||
|
||||
@@ -443,7 +434,6 @@ cmdline_parm atiswap_arg("-ati_swap", NULL, AT_NONE); // Cmdline_atiswap
|
||||
cmdline_parm no3dsound_arg("-no_3d_sound", NULL, AT_NONE); // Cmdline_no_3d_sound - Disable use of full 3D sounds
|
||||
cmdline_parm no_drawrangeelements("-use_gldrawelements", NULL, AT_NONE); // Cmdline_drawelements -- Uses glDrawElements instead of glDrawRangeElements
|
||||
cmdline_parm keyboard_layout("-keyboard_layout", "Specify keyboard layout (qwertz or azerty)", AT_STRING);
|
||||
cmdline_parm old_collision_system("-old_collision", NULL, AT_NONE); // Cmdline_old_collision_sys
|
||||
cmdline_parm gl_finish ("-gl_finish", NULL, AT_NONE);
|
||||
cmdline_parm no_geo_sdr_effects("-no_geo_effects", NULL, AT_NONE);
|
||||
cmdline_parm set_cpu_affinity("-set_cpu_affinity", NULL, AT_NONE);
|
||||
@@ -493,7 +483,6 @@ cmdline_parm frame_profile_write_file("-profile_write_file", NULL, AT_NONE); //
|
||||
cmdline_parm no_unfocused_pause_arg("-no_unfocused_pause", NULL, AT_NONE); //Cmdline_no_unfocus_pause
|
||||
cmdline_parm benchmark_mode_arg("-benchmark_mode", NULL, AT_NONE); //Cmdline_benchmark_mode
|
||||
cmdline_parm noninteractive_arg("-noninteractive", NULL, AT_NONE); //Cmdline_noninteractive
|
||||
cmdline_parm json_pilot("-json_pilot", NULL, AT_NONE); //Cmdline_json_pilot
|
||||
cmdline_parm json_profiling("-json_profiling", NULL, AT_NONE); //Cmdline_json_profiling
|
||||
cmdline_parm show_video_info("-show_video_info", NULL, AT_NONE); //Cmdline_show_video_info
|
||||
cmdline_parm frame_profile_arg("-profile_frame_time", NULL, AT_NONE); //Cmdline_frame_profile
|
||||
@@ -501,7 +490,6 @@ cmdline_parm debug_window_arg("-debug_window", NULL, AT_NONE); // Cmdline_debug_
|
||||
|
||||
|
||||
char *Cmdline_start_mission = NULL;
|
||||
int Cmdline_old_collision_sys = 0;
|
||||
int Cmdline_dis_collisions = 0;
|
||||
int Cmdline_dis_weapons = 0;
|
||||
bool Cmdline_output_sexp_info = false;
|
||||
@@ -524,7 +512,6 @@ bool Cmdline_profile_write_file = false;
|
||||
bool Cmdline_no_unfocus_pause = false;
|
||||
bool Cmdline_benchmark_mode = false;
|
||||
bool Cmdline_noninteractive = false;
|
||||
bool Cmdline_json_pilot = false;
|
||||
bool Cmdline_json_profiling = false;
|
||||
bool Cmdline_frame_profile = false;
|
||||
bool Cmdline_show_video_info = false;
|
||||
@@ -546,6 +533,7 @@ cmdline_parm deprecated_htl_arg("-nohtl", "Deprecated", AT_NONE);
|
||||
cmdline_parm deprecated_brieflighting_arg("-brief_lighting", "Deprecated", AT_NONE);
|
||||
cmdline_parm deprecated_sndpreload_arg("-snd_preload", "Deprecated", AT_NONE);
|
||||
cmdline_parm deprecated_missile_lighting_arg("-missile_lighting", "Deprecated", AT_NONE);
|
||||
cmdline_parm deprecated_cache_bitmaps_arg("-cache_bitmaps", "Deprecated", AT_NONE);
|
||||
|
||||
int Cmdline_deprecated_spec = 0;
|
||||
int Cmdline_deprecated_glow = 0;
|
||||
@@ -556,6 +544,7 @@ int Cmdline_deprecated_jpgtga = 0;
|
||||
int Cmdline_deprecated_nohtl = 0;
|
||||
bool Cmdline_deprecated_brief_lighting = 0;
|
||||
bool Cmdline_deprecated_missile_lighting = false;
|
||||
bool Cmdline_deprecated_cache_bitmaps = false;
|
||||
|
||||
#ifndef NDEBUG
|
||||
// NOTE: this assumes that os_init() has already been called but isn't a fatal error if it hasn't
|
||||
@@ -626,6 +615,10 @@ void cmdline_debug_print_cmdline()
|
||||
{
|
||||
mprintf(("Deprecated flag '-missile_lighting' found. Please remove from your cmdline.\n"));
|
||||
}
|
||||
|
||||
if (Cmdline_deprecated_cache_bitmaps) {
|
||||
mprintf(("Deprecated flag '-cache_bitmaps' found. Please remove from your cmdline.\n"));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1880,9 +1873,6 @@ bool SetCmdlineParams()
|
||||
if ( glow_arg.found() )
|
||||
Cmdline_glow = 0;
|
||||
|
||||
if ( query_speech_arg.found() )
|
||||
Cmdline_query_speech = 1;
|
||||
|
||||
if ( ship_choice_3d_arg.found() )
|
||||
Cmdline_ship_choice_3d = 1;
|
||||
|
||||
@@ -1965,13 +1955,6 @@ bool SetCmdlineParams()
|
||||
Cmdline_ballistic_gauge = 1;
|
||||
}
|
||||
|
||||
if ( cache_bitmaps_arg.found() ) {
|
||||
Cmdline_cache_bitmaps = 1;
|
||||
}
|
||||
|
||||
if(old_collision_system.found())
|
||||
Cmdline_old_collision_sys = 1;
|
||||
|
||||
if(dis_collisions.found())
|
||||
Cmdline_dis_collisions = 1;
|
||||
|
||||
@@ -2089,11 +2072,6 @@ bool SetCmdlineParams()
|
||||
Cmdline_noninteractive = true;
|
||||
}
|
||||
|
||||
if (json_pilot.found())
|
||||
{
|
||||
Cmdline_json_pilot = true;
|
||||
}
|
||||
|
||||
if (json_profiling.found())
|
||||
{
|
||||
Cmdline_json_profiling = true;
|
||||
@@ -2159,6 +2137,10 @@ bool SetCmdlineParams()
|
||||
Cmdline_deprecated_missile_lighting = true;
|
||||
}
|
||||
|
||||
if (deprecated_cache_bitmaps_arg.found()) {
|
||||
Cmdline_deprecated_cache_bitmaps = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -82,7 +82,6 @@ extern int Cmdline_no_emissive;
|
||||
extern int Cmdline_aniso_level;
|
||||
|
||||
// Game Speed related
|
||||
extern int Cmdline_cache_bitmaps;
|
||||
extern int Cmdline_NoFPSCap;
|
||||
extern int Cmdline_no_vsync;
|
||||
|
||||
@@ -102,7 +101,6 @@ extern int Cmdline_autopilot_interruptable;
|
||||
extern int Cmdline_stretch_menu;
|
||||
|
||||
// Audio related
|
||||
extern int Cmdline_query_speech;
|
||||
extern int Cmdline_voice_recognition;
|
||||
extern int Cmdline_no_enhanced_sound;
|
||||
|
||||
@@ -141,7 +139,6 @@ extern bool Cmdline_alternate_registry_path;
|
||||
|
||||
// Developer/Testing related
|
||||
extern char *Cmdline_start_mission;
|
||||
extern int Cmdline_old_collision_sys;
|
||||
extern int Cmdline_dis_collisions;
|
||||
extern int Cmdline_dis_weapons;
|
||||
extern bool Cmdline_output_sexp_info;
|
||||
@@ -157,7 +154,6 @@ extern bool Cmdline_profile_write_file;
|
||||
extern bool Cmdline_no_unfocus_pause;
|
||||
extern bool Cmdline_benchmark_mode;
|
||||
extern bool Cmdline_noninteractive;
|
||||
extern bool Cmdline_json_pilot;
|
||||
extern bool Cmdline_json_profiling;
|
||||
extern bool Cmdline_frame_profile;
|
||||
extern bool Cmdline_show_video_info;
|
||||
|
||||
@@ -53,26 +53,6 @@ void cmeasure_set_ship_launch_vel(object *objp, object *parent_objp, int arand)
|
||||
vm_vec_copy_scale(&objp->phys_info.desired_vel, &objp->orient.vec.fvec, objp->phys_info.max_vel.xyz.z );
|
||||
}
|
||||
|
||||
void cmeasure_select_next(ship *shipp)
|
||||
{
|
||||
Assert(shipp != NULL);
|
||||
int i, new_index;
|
||||
|
||||
for (i = 1; i < Num_weapon_types; i++)
|
||||
{
|
||||
new_index = (shipp->current_cmeasure + i) % Num_weapon_types;
|
||||
|
||||
if(Weapon_info[new_index].wi_flags[Weapon::Info_Flags::Cmeasure])
|
||||
{
|
||||
shipp->current_cmeasure = new_index;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
mprintf(("Countermeasure type set to %i in frame %i\n", shipp->current_cmeasure, Framecount));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief If this is a player countermeasure, let the player know they evaded a missile.
|
||||
* @param objp [description]
|
||||
|
||||
@@ -28,7 +28,6 @@ extern int Cmeasures_homing_check;
|
||||
extern int Countermeasures_enabled;
|
||||
|
||||
extern void cmeasure_set_ship_launch_vel(object *objp, object *parent_objp, int arand);
|
||||
extern void cmeasure_select_next(object *objp);
|
||||
extern void cmeasure_maybe_alert_success(object *objp);
|
||||
|
||||
#endif // _CMEASURE_H
|
||||
@@ -38,7 +38,6 @@
|
||||
|
||||
|
||||
|
||||
#define NUM_SYSTEM_KEYS 14
|
||||
#define NUM_BUTTONS 19
|
||||
#define NUM_TABS 4
|
||||
|
||||
@@ -157,11 +156,6 @@ char *Mouse_button_text[NUM_MOUSE_TEXT];
|
||||
char *Mouse_axis_text[NUM_MOUSE_AXIS_TEXT];
|
||||
char *Invert_text[NUM_INVERT_TEXT];
|
||||
|
||||
ubyte System_keys[NUM_SYSTEM_KEYS] = {
|
||||
KEY_ESC, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10,
|
||||
KEY_F11, KEY_F12, KEY_PRINT_SCRN
|
||||
};
|
||||
|
||||
int Control_check_count = 0;
|
||||
|
||||
static int Tab; // which tab we are currently in
|
||||
@@ -2193,17 +2187,6 @@ void control_config_do_frame(float frametime)
|
||||
gr_flip();
|
||||
}
|
||||
|
||||
void clear_key_binding(short key)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<CCFG_MAX; i++) {
|
||||
if (Control_config[i].key_id == key) {
|
||||
Control_config[i].key_id = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float check_control_timef(int id)
|
||||
{
|
||||
float t1, t2;
|
||||
@@ -2345,7 +2328,7 @@ int check_control(int id, int key)
|
||||
// which has just been released
|
||||
|
||||
Script_system.SetHookVar("Action", 's', Control_config[id].text);
|
||||
Script_system.RunCondition(CHA_ONACTIONSTOPPED, '\0', NULL, NULL, id);
|
||||
Script_system.RunCondition(CHA_ONACTIONSTOPPED, nullptr, id);
|
||||
Script_system.RemHookVar("Action");
|
||||
|
||||
Control_config[id].continuous_ongoing = false;
|
||||
@@ -2419,7 +2402,7 @@ void control_used(int id)
|
||||
if (Control_config[id].used < Last_frame_timestamp) {
|
||||
if (!Control_config[id].continuous_ongoing) {
|
||||
Script_system.SetHookVar("Action", 's', Control_config[id].text);
|
||||
Script_system.RunCondition(CHA_ONACTION, '\0', NULL, NULL, id);
|
||||
Script_system.RunCondition(CHA_ONACTION, nullptr, id);
|
||||
Script_system.RemHookVar("Action");
|
||||
|
||||
if (Control_config[id].type == CC_TYPE_CONTINUOUS)
|
||||
@@ -2447,9 +2430,4 @@ void control_config_clear()
|
||||
for (i=0; i<CCFG_MAX; i++) {
|
||||
Control_config[i].key_id = Control_config[i].joy_id = -1;
|
||||
}
|
||||
}
|
||||
|
||||
int control_config_handle_conflict()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -277,12 +277,6 @@ enum IoActionId {
|
||||
};
|
||||
|
||||
extern int Failed_key_index;
|
||||
extern int Invert_heading;
|
||||
extern int Invert_pitch;
|
||||
extern int Invert_roll;
|
||||
extern int Invert_thrust;
|
||||
extern int Disable_axis2;
|
||||
extern int Disable_axis3;
|
||||
|
||||
extern int Axis_map_to[];
|
||||
extern int Invert_axis[];
|
||||
@@ -336,7 +330,6 @@ int check_control(int id, int key = -1);
|
||||
void control_get_axes_readings(int *h, int *p, int *b, int *ta, int *tr);
|
||||
void control_used(int id);
|
||||
void control_config_clear();
|
||||
void clear_key_binding(short key);
|
||||
void control_check_indicate();
|
||||
void control_config_clear_used_status();
|
||||
|
||||
|
||||
@@ -34,13 +34,6 @@ int Failed_key_index;
|
||||
int Joy_dead_zone_size = 10;
|
||||
int Joy_sensitivity = 9;
|
||||
|
||||
// assume control keys are used as modifiers until we find out
|
||||
int Shift_is_modifier;
|
||||
int Ctrl_is_modifier;
|
||||
int Alt_is_modifier;
|
||||
|
||||
int Axis_enabled[JOY_NUM_AXES] = { 1, 1, 1, 0, 0, 0 };
|
||||
int Axis_enabled_defaults[JOY_NUM_AXES] = { 1, 1, 1, 0, 0, 0 };
|
||||
int Invert_axis[JOY_NUM_AXES] = { 0, 0, 0, 0, 0, 0 };
|
||||
int Invert_axis_defaults[JOY_NUM_AXES] = { 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
@@ -410,31 +403,6 @@ const char **Joy_button_text = Joy_button_text_english;
|
||||
SCP_vector<config_item*> Control_config_presets;
|
||||
SCP_vector<SCP_string> Control_config_preset_names;
|
||||
|
||||
void set_modifier_status()
|
||||
{
|
||||
int i;
|
||||
|
||||
Alt_is_modifier = 0;
|
||||
Shift_is_modifier = 0;
|
||||
Ctrl_is_modifier = 0;
|
||||
|
||||
for (i=0; i<CCFG_MAX; i++) {
|
||||
if (Control_config[i].key_id < 0)
|
||||
continue;
|
||||
|
||||
if (Control_config[i].key_id & KEY_ALTED)
|
||||
Alt_is_modifier = 1;
|
||||
|
||||
if (Control_config[i].key_id & KEY_SHIFTED)
|
||||
Shift_is_modifier = 1;
|
||||
|
||||
if (Control_config[i].key_id & KEY_CTRLED) {
|
||||
Assert(0); // get Alan
|
||||
Ctrl_is_modifier = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If find_override is set to true, then this returns the index of the action
|
||||
// which has been bound to the given key. Otherwise, the index of the action
|
||||
// which has the given key as its default key will be returned.
|
||||
|
||||
@@ -3,6 +3,12 @@
|
||||
#include <memory>
|
||||
|
||||
namespace cutscene {
|
||||
FrameSize::FrameSize(size_t in_width, size_t in_height, size_t in_stride)
|
||||
: width(in_width), height(in_height), stride(in_stride)
|
||||
{
|
||||
}
|
||||
FrameSize::FrameSize() = default;
|
||||
|
||||
Decoder::Decoder() : m_decoding(true) {
|
||||
}
|
||||
|
||||
@@ -40,10 +46,6 @@ void Decoder::stopDecoder() {
|
||||
m_subtitleQueue->close();
|
||||
}
|
||||
|
||||
bool Decoder::canPushAudioData() {
|
||||
return !isAudioQueueFull();
|
||||
}
|
||||
|
||||
void Decoder::pushAudioData(AudioFramePtr&& data) {
|
||||
Assertion(data, "Invalid audio data passed!");
|
||||
|
||||
@@ -55,9 +57,6 @@ void Decoder::pushAudioData(AudioFramePtr&& data) {
|
||||
}
|
||||
}
|
||||
|
||||
bool Decoder::canPushSubtitleData() {
|
||||
return !isSubtitleQueueFull();
|
||||
}
|
||||
void Decoder::pushSubtitleData(SubtitleFramePtr&& data) {
|
||||
Assertion(data, "Invalid audio data passed!");
|
||||
|
||||
@@ -69,10 +68,6 @@ void Decoder::pushSubtitleData(SubtitleFramePtr&& data) {
|
||||
}
|
||||
}
|
||||
|
||||
bool Decoder::canPushVideoData() {
|
||||
return !isVideoQueueFull();
|
||||
}
|
||||
|
||||
void Decoder::pushFrameData(VideoFramePtr&& frame) {
|
||||
Assertion(frame, "Invalid video data passed!");
|
||||
|
||||
|
||||
+24
-22
@@ -10,28 +10,26 @@ struct FrameSize {
|
||||
size_t width = 0;
|
||||
size_t height = 0;
|
||||
size_t stride = 0;
|
||||
|
||||
FrameSize();
|
||||
FrameSize(size_t width, size_t in_height, size_t in_stride);
|
||||
};
|
||||
|
||||
class VideoFrame {
|
||||
protected:
|
||||
VideoFrame() {}
|
||||
VideoFrame() = default;
|
||||
|
||||
public:
|
||||
virtual ~VideoFrame() {}
|
||||
public:
|
||||
virtual ~VideoFrame() = default;
|
||||
|
||||
double frameTime = -1.0;
|
||||
int id = -1;
|
||||
|
||||
FrameSize ySize;
|
||||
FrameSize uvSize;
|
||||
virtual size_t getPlaneNumber() = 0;
|
||||
|
||||
struct DataPointers {
|
||||
ubyte* y;
|
||||
ubyte* u;
|
||||
ubyte* v;
|
||||
};
|
||||
virtual FrameSize getPlaneSize(size_t plane) = 0;
|
||||
|
||||
virtual DataPointers getDataPointers() = 0;
|
||||
virtual void* getPlaneData(size_t plane) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -43,10 +41,19 @@ using FramePtr = std::unique_ptr<T>;
|
||||
|
||||
typedef std::unique_ptr<VideoFrame> VideoFramePtr;
|
||||
|
||||
enum class FramePixelFormat {
|
||||
Invalid,
|
||||
YUV420,
|
||||
BGR,
|
||||
BGRA
|
||||
};
|
||||
|
||||
struct MovieProperties {
|
||||
FrameSize size;
|
||||
|
||||
float fps = -1.0f;
|
||||
|
||||
FramePixelFormat pixelFormat = FramePixelFormat::Invalid;
|
||||
};
|
||||
|
||||
struct AudioFrame {
|
||||
@@ -66,6 +73,11 @@ struct SubtitleFrame {
|
||||
};
|
||||
typedef std::unique_ptr<SubtitleFrame> SubtitleFramePtr;
|
||||
|
||||
struct PlaybackProperties {
|
||||
bool with_audio = true;
|
||||
bool looping = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Abstract class for decoding a video or audio stream
|
||||
*
|
||||
@@ -99,7 +111,7 @@ class Decoder {
|
||||
* @param fileName The name of the file that should be opened
|
||||
* @return @c true if the initialization was successfull, @c false otherwise
|
||||
*/
|
||||
virtual bool initialize(const SCP_string& fileName) = 0;
|
||||
virtual bool initialize(const SCP_string& fileName, const PlaybackProperties& properties) = 0;
|
||||
|
||||
/**
|
||||
* @brief Returns the properties of the video
|
||||
@@ -135,10 +147,6 @@ class Decoder {
|
||||
|
||||
bool isSubtitleQueueFull() { return m_subtitleQueue->size() == m_queueSize; }
|
||||
|
||||
bool isSubtitleFrameAvailable() { return !m_subtitleQueue->empty(); }
|
||||
|
||||
size_t getSubtitleQueueSize() { return m_subtitleQueue->size(); }
|
||||
|
||||
bool tryPopSubtitleData(SubtitleFramePtr&);
|
||||
|
||||
bool isVideoQueueFull() { return m_videoQueue->size() == m_queueSize; }
|
||||
@@ -156,16 +164,10 @@ class Decoder {
|
||||
protected:
|
||||
void initializeQueues(size_t queueSize);
|
||||
|
||||
bool canPushAudioData();
|
||||
|
||||
void pushAudioData(AudioFramePtr&& data);
|
||||
|
||||
bool canPushSubtitleData();
|
||||
|
||||
void pushSubtitleData(SubtitleFramePtr&& data);
|
||||
|
||||
bool canPushVideoData();
|
||||
|
||||
void pushFrameData(VideoFramePtr&& frame);
|
||||
};
|
||||
}
|
||||
@@ -14,46 +14,85 @@ struct movie_vertex {
|
||||
|
||||
namespace cutscene {
|
||||
namespace player {
|
||||
VideoPresenter::VideoPresenter(const MovieProperties& props) {
|
||||
VideoPresenter::VideoPresenter(const MovieProperties& props) : _properties(props)
|
||||
{
|
||||
GR_DEBUG_SCOPE("Init video");
|
||||
|
||||
_planeTextureHandles.fill(-1);
|
||||
|
||||
auto w = static_cast<int>(props.size.width);
|
||||
auto h = static_cast<int>(props.size.height);
|
||||
|
||||
// Create buffer textures
|
||||
_yTexBuffer.reset(new uint8_t[w * h]);
|
||||
_ytex = bm_create(8, w, h, _yTexBuffer.get(), BMP_AABITMAP);
|
||||
switch (props.pixelFormat) {
|
||||
case FramePixelFormat::YUV420:
|
||||
_planeTextureBuffers[0].reset(new uint8_t[w * h]);
|
||||
_planeTextureHandles[0] = bm_create(8, w, h, _planeTextureBuffers[0].get(), BMP_AABITMAP);
|
||||
|
||||
_uTexBuffer.reset(new uint8_t[w / 2 * h / 2]);
|
||||
_utex = bm_create(8, w / 2, h / 2, _uTexBuffer.get(), BMP_AABITMAP);
|
||||
_planeTextureBuffers[1].reset(new uint8_t[w / 2 * h / 2]);
|
||||
_planeTextureHandles[1] = bm_create(8, w / 2, h / 2, _planeTextureBuffers[1].get(), BMP_AABITMAP);
|
||||
|
||||
_vTexBuffer.reset(new uint8_t[w / 2 * h / 2]);
|
||||
_vtex = bm_create(8, w / 2, h / 2, _vTexBuffer.get(), BMP_AABITMAP);
|
||||
_planeTextureBuffers[2].reset(new uint8_t[w / 2 * h / 2]);
|
||||
_planeTextureHandles[2] = bm_create(8, w / 2, h / 2, _planeTextureBuffers[2].get(), BMP_AABITMAP);
|
||||
|
||||
material_set_movie(&_render_material, _ytex, _utex, _vtex);
|
||||
material_set_movie(&_movie_material, _planeTextureHandles[0], _planeTextureHandles[1], _planeTextureHandles[2]);
|
||||
break;
|
||||
case FramePixelFormat::BGR:
|
||||
_planeTextureBuffers[0].reset(new uint8_t[w * h * 3]);
|
||||
_planeTextureHandles[0] = bm_create(24, w, h, _planeTextureBuffers[0].get(), 0);
|
||||
|
||||
material_set_unlit(&_rgb_material, _planeTextureHandles[0], 1.0f, false, false);
|
||||
break;
|
||||
case FramePixelFormat::BGRA:
|
||||
_planeTextureBuffers[0].reset(new uint8_t[w * h * 4]);
|
||||
_planeTextureHandles[0] = bm_create(32, w, h, _planeTextureBuffers[0].get(), 0);
|
||||
|
||||
material_set_unlit(&_rgb_material, _planeTextureHandles[0], 1.0f, true, false);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE("Unhandled enum value!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
VideoPresenter::~VideoPresenter() {
|
||||
GR_DEBUG_SCOPE("Deinit video");
|
||||
|
||||
bm_release(_ytex);
|
||||
bm_release(_utex);
|
||||
bm_release(_vtex);
|
||||
|
||||
_ytex = _utex = _vtex = -1;
|
||||
for (auto& handle : _planeTextureHandles) {
|
||||
if (handle > 0) {
|
||||
bm_release(handle);
|
||||
handle = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VideoPresenter::uploadVideoFrame(const VideoFramePtr& frame) {
|
||||
GR_DEBUG_SCOPE("Update video frame");
|
||||
auto ptrs = frame->getDataPointers();
|
||||
|
||||
memcpy(_yTexBuffer.get(), ptrs.y, frame->ySize.stride * frame->ySize.height);
|
||||
memcpy(_uTexBuffer.get(), ptrs.u, frame->uvSize.stride * frame->uvSize.height);
|
||||
memcpy(_vTexBuffer.get(), ptrs.v, frame->uvSize.stride * frame->uvSize.height);
|
||||
for (size_t i = 0; i < frame->getPlaneNumber(); ++i) {
|
||||
auto size = frame->getPlaneSize(i);
|
||||
auto data = frame->getPlaneData(i);
|
||||
|
||||
gr_update_texture(_ytex, 8, _yTexBuffer.get(), (int) frame->ySize.width, (int) frame->ySize.height);
|
||||
gr_update_texture(_utex, 8, _uTexBuffer.get(), (int) frame->uvSize.width, (int) frame->uvSize.height);
|
||||
gr_update_texture(_vtex, 8, _vTexBuffer.get(), (int) frame->uvSize.width, (int) frame->uvSize.height);
|
||||
memcpy(_planeTextureBuffers[i].get(), data, size.stride * size.height);
|
||||
|
||||
int bpp = 0;
|
||||
switch (_properties.pixelFormat) {
|
||||
case FramePixelFormat::YUV420:
|
||||
bpp = 8;
|
||||
break;
|
||||
case FramePixelFormat::BGR:
|
||||
bpp = 24;
|
||||
break;
|
||||
case FramePixelFormat::BGRA:
|
||||
bpp = 32;
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE("Unhandled enum value!");
|
||||
break;
|
||||
}
|
||||
|
||||
gr_update_texture(_planeTextureHandles[i], bpp, _planeTextureBuffers[i].get(), static_cast<int>(size.width),
|
||||
static_cast<int>(size.height));
|
||||
}
|
||||
}
|
||||
|
||||
void VideoPresenter::displayFrame(float x1, float y1, float x2, float y2) {
|
||||
@@ -85,10 +124,14 @@ void VideoPresenter::displayFrame(float x1, float y1, float x2, float y2) {
|
||||
auto offset = gr_add_to_immediate_buffer(sizeof(vertex_data), vertex_data);
|
||||
|
||||
vertex_layout layout;
|
||||
layout.add_vertex_component(vertex_format_data::POSITION2, sizeof(vertex_data[0]), offset + offsetof(movie_vertex, pos));
|
||||
layout.add_vertex_component(vertex_format_data::TEX_COORD2, sizeof(vertex_data[0]), offset + offsetof(movie_vertex, uv));
|
||||
layout.add_vertex_component(vertex_format_data::POSITION2, sizeof(vertex_data[0]), offsetof(movie_vertex, pos));
|
||||
layout.add_vertex_component(vertex_format_data::TEX_COORD2, sizeof(vertex_data[0]), offsetof(movie_vertex, uv));
|
||||
|
||||
gr_render_movie(&_render_material, PRIM_TYPE_TRISTRIP, &layout, 4, gr_immediate_buffer_handle);
|
||||
if (_properties.pixelFormat == FramePixelFormat::YUV420) {
|
||||
gr_render_movie(&_movie_material, PRIM_TYPE_TRISTRIP, &layout, 4, gr_immediate_buffer_handle, offset);
|
||||
} else {
|
||||
gr_render_primitives(&_rgb_material, PRIM_TYPE_TRISTRIP, &layout, 0, 4, gr_immediate_buffer_handle, offset);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -12,16 +12,13 @@ namespace cutscene {
|
||||
namespace player {
|
||||
|
||||
class VideoPresenter {
|
||||
int _ytex = -1;
|
||||
std::unique_ptr<uint8_t[]> _yTexBuffer;
|
||||
MovieProperties _properties;
|
||||
|
||||
int _utex = -1;
|
||||
std::unique_ptr<uint8_t[]> _uTexBuffer;
|
||||
std::array<int, 3> _planeTextureHandles;
|
||||
std::array<std::unique_ptr<uint8_t[]>, 3> _planeTextureBuffers;
|
||||
|
||||
int _vtex = -1;
|
||||
std::unique_ptr<uint8_t[]> _vTexBuffer;
|
||||
|
||||
movie_material _render_material;
|
||||
movie_material _movie_material;
|
||||
material _rgb_material; // Material used when a RGB/RGBA movie is played
|
||||
public:
|
||||
explicit VideoPresenter(const MovieProperties& props);
|
||||
|
||||
|
||||
@@ -223,5 +223,8 @@ void AudioDecoder::finishDecoding() {
|
||||
// Push the last bits of audio data into the queue
|
||||
flushAudioBuffer();
|
||||
}
|
||||
void AudioDecoder::flushBuffers() {
|
||||
avcodec_flush_buffers(m_status->audioCodecCtx);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,8 @@ class AudioDecoder: public FFMPEGStreamDecoder<AudioFrame> {
|
||||
void decodePacket(AVPacket* packet) override;
|
||||
|
||||
void finishDecoding() override;
|
||||
|
||||
void flushBuffers() override;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -28,22 +28,26 @@ class AVPacketScope
|
||||
: _packet(av_packet) {
|
||||
}
|
||||
|
||||
AVPacketScope(const AVPacketScope&) = delete;
|
||||
AVPacketScope& operator=(const AVPacketScope&) = delete;
|
||||
|
||||
~AVPacketScope() {
|
||||
av_packet_unref(_packet);
|
||||
}
|
||||
};
|
||||
|
||||
const char* CHECKED_EXTENSIONS[] = {
|
||||
"webm",
|
||||
"mp4",
|
||||
"ogg",
|
||||
"mve"
|
||||
};
|
||||
const char* CHECKED_EXTENSIONS[] = {"webm", "mp4", "ogg",
|
||||
"png", // This is designed to be used with APNG animations
|
||||
"mve"};
|
||||
|
||||
const char *CHECKED_SUBT_EXTENSIONS[] = {"srt"};
|
||||
const char* CHECKED_SUBT_EXTENSIONS[] = {"srt"};
|
||||
|
||||
double getFrameRate(AVStream* stream, AVCodecContext* codecCtx) {
|
||||
#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(58, 3, 102)
|
||||
auto fps = av_q2d(stream->r_frame_rate);
|
||||
#else
|
||||
auto fps = av_q2d(av_stream_get_r_frame_rate(stream));
|
||||
#endif
|
||||
|
||||
if (fps < 0.000001)
|
||||
{
|
||||
@@ -58,7 +62,7 @@ double getFrameRate(AVStream* stream, AVCodecContext* codecCtx) {
|
||||
return fps;
|
||||
}
|
||||
|
||||
CodecContextParameters getCodecParameters(AVStream *stream) {
|
||||
CodecContextParameters getCodecParameters(AVStream* stream) {
|
||||
CodecContextParameters paras;
|
||||
#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(57, 24, 255)
|
||||
paras.width = stream->codecpar->width;
|
||||
@@ -84,7 +88,7 @@ CodecContextParameters getCodecParameters(AVStream *stream) {
|
||||
return paras;
|
||||
}
|
||||
|
||||
SCP_string normalizeLanguage(const char *langauge_name) {
|
||||
SCP_string normalizeLanguage(const char* langauge_name) {
|
||||
if (!stricmp(langauge_name, "eng")) {
|
||||
return "English";
|
||||
}
|
||||
@@ -101,6 +105,72 @@ SCP_string normalizeLanguage(const char *langauge_name) {
|
||||
// Default to english for everything else
|
||||
return "English";
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Given a FFmpeg pixel format returns the format it should be converted to
|
||||
* @param in_fmt The input format
|
||||
* @return The output format
|
||||
*/
|
||||
AVPixelFormat getConversionFormat(AVPixelFormat in_fmt)
|
||||
{
|
||||
switch (in_fmt) {
|
||||
case AV_PIX_FMT_RGB24:
|
||||
case AV_PIX_FMT_BGR24:
|
||||
case AV_PIX_FMT_BGR8:
|
||||
case AV_PIX_FMT_BGR4:
|
||||
case AV_PIX_FMT_BGR4_BYTE:
|
||||
case AV_PIX_FMT_RGB8:
|
||||
case AV_PIX_FMT_RGB4:
|
||||
case AV_PIX_FMT_RGB4_BYTE:
|
||||
case AV_PIX_FMT_RGB48BE:
|
||||
case AV_PIX_FMT_RGB48LE:
|
||||
case AV_PIX_FMT_RGB565BE:
|
||||
case AV_PIX_FMT_RGB565LE:
|
||||
case AV_PIX_FMT_RGB555BE:
|
||||
case AV_PIX_FMT_RGB555LE:
|
||||
case AV_PIX_FMT_BGR565BE:
|
||||
case AV_PIX_FMT_BGR565LE:
|
||||
case AV_PIX_FMT_BGR555BE:
|
||||
case AV_PIX_FMT_BGR555LE:
|
||||
case AV_PIX_FMT_RGB444LE:
|
||||
case AV_PIX_FMT_RGB444BE:
|
||||
case AV_PIX_FMT_BGR444LE:
|
||||
case AV_PIX_FMT_BGR444BE:
|
||||
case AV_PIX_FMT_BGR48BE:
|
||||
case AV_PIX_FMT_BGR48LE:
|
||||
case AV_PIX_FMT_0RGB:
|
||||
case AV_PIX_FMT_RGB0:
|
||||
case AV_PIX_FMT_0BGR:
|
||||
case AV_PIX_FMT_BGR0:
|
||||
return AV_PIX_FMT_BGR24;
|
||||
|
||||
case AV_PIX_FMT_RGBA64BE:
|
||||
case AV_PIX_FMT_RGBA64LE:
|
||||
case AV_PIX_FMT_BGRA64BE:
|
||||
case AV_PIX_FMT_BGRA64LE:
|
||||
case AV_PIX_FMT_ARGB:
|
||||
case AV_PIX_FMT_RGBA:
|
||||
case AV_PIX_FMT_ABGR:
|
||||
case AV_PIX_FMT_BGRA:
|
||||
return AV_PIX_FMT_BGRA;
|
||||
|
||||
default:
|
||||
// Assume that everything else is converted to YUV 420
|
||||
return AV_PIX_FMT_YUV420P;
|
||||
}
|
||||
}
|
||||
|
||||
FramePixelFormat getPixelFormat(AVPixelFormat fmt)
|
||||
{
|
||||
switch (fmt) {
|
||||
case AV_PIX_FMT_BGR24:
|
||||
return FramePixelFormat::BGR;
|
||||
case AV_PIX_FMT_BGRA:
|
||||
return FramePixelFormat::BGRA;
|
||||
default:
|
||||
return FramePixelFormat::YUV420;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace cutscene {
|
||||
@@ -146,8 +216,15 @@ std::unique_ptr<InputStream> openStream(const SCP_string& name) {
|
||||
return input;
|
||||
}
|
||||
|
||||
std::unique_ptr<DecoderStatus> initializeStatus(std::unique_ptr<InputStream> &stream,
|
||||
std::unique_ptr<InputStream> &subt) {
|
||||
std::unique_ptr<DecoderStatus> initializeStatus(std::unique_ptr<InputStream>& stream,
|
||||
std::unique_ptr<InputStream>& subt,
|
||||
const PlaybackProperties& properties)
|
||||
{
|
||||
if (subt && properties.looping) {
|
||||
mprintf(("FFmpeg: External subtitles and looping movies are not supported!\n"));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<DecoderStatus> status(new DecoderStatus());
|
||||
|
||||
auto ctx = stream->m_ctx->ctx();
|
||||
@@ -165,14 +242,18 @@ std::unique_ptr<DecoderStatus> initializeStatus(std::unique_ptr<InputStream> &st
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto audioStream = av_find_best_stream(ctx, AVMEDIA_TYPE_AUDIO, -1, videoStream, &status->audioCodec, 0);
|
||||
if (audioStream < 0) {
|
||||
if (audioStream == AVERROR_STREAM_NOT_FOUND) {
|
||||
mprintf(("FFmpeg: No audio stream found in file!\n"));
|
||||
} else if (audioStream == AVERROR_DECODER_NOT_FOUND) {
|
||||
mprintf(("FFmpeg: Codec for audio stream could not be found!\n"));
|
||||
} else {
|
||||
mprintf(("FFmpeg: Unknown error while finding audio stream!\n"));
|
||||
int audioStream = -1;
|
||||
|
||||
if (properties.with_audio) {
|
||||
audioStream = av_find_best_stream(ctx, AVMEDIA_TYPE_AUDIO, -1, videoStream, &status->audioCodec, 0);
|
||||
if (audioStream < 0) {
|
||||
if (audioStream == AVERROR_STREAM_NOT_FOUND) {
|
||||
mprintf(("FFmpeg: No audio stream found in file!\n"));
|
||||
} else if (audioStream == AVERROR_DECODER_NOT_FOUND) {
|
||||
mprintf(("FFmpeg: Codec for audio stream could not be found!\n"));
|
||||
} else {
|
||||
mprintf(("FFmpeg: Unknown error while finding audio stream!\n"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,18 +286,18 @@ std::unique_ptr<DecoderStatus> initializeStatus(std::unique_ptr<InputStream> &st
|
||||
|
||||
if (status->subtitleStream == nullptr) {
|
||||
// We don't have an external subtitle stream or loading from that file has failed
|
||||
auto ¤t_language = Lcl_languages[Lcl_current_lang];
|
||||
auto& current_language = Lcl_languages[Lcl_current_lang];
|
||||
for (uint32_t i = 0; i < ctx->nb_streams; ++i) {
|
||||
auto test_stream = ctx->streams[i];
|
||||
|
||||
#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(57, 24, 255)
|
||||
auto &pars = test_stream->codecpar;
|
||||
auto& pars = test_stream->codecpar;
|
||||
|
||||
if (!(pars->codec_type == AVMEDIA_TYPE_SUBTITLE)) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
AVDictionaryEntry *tag = nullptr;
|
||||
AVDictionaryEntry* tag = nullptr;
|
||||
if ((tag = av_dict_get(test_stream->metadata, "language", nullptr, 0)) == nullptr) {
|
||||
continue;
|
||||
}
|
||||
@@ -233,6 +314,11 @@ std::unique_ptr<DecoderStatus> initializeStatus(std::unique_ptr<InputStream> &st
|
||||
|
||||
status->videoCodecPars = getCodecParameters(status->videoStream);
|
||||
|
||||
if (properties.looping && status->videoCodecPars.codec_id == AV_CODEC_ID_INTERPLAY_VIDEO) {
|
||||
mprintf(("FFmpeg: Looping is not supported for inteplay (MVE) movies!\n"));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int err;
|
||||
#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(57, 24, 255)
|
||||
status->videoCodecCtx = avcodec_alloc_context3(status->videoCodec);
|
||||
@@ -340,8 +426,9 @@ std::unique_ptr<InputStream> openInputStream(const SCP_string& name) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<InputStream> openSubtitleStream(const SCP_string &name) {
|
||||
auto ¤t_language = Lcl_languages[Lcl_current_lang];
|
||||
std::unique_ptr<InputStream> openSubtitleStream(const SCP_string& name)
|
||||
{
|
||||
auto& current_language = Lcl_languages[Lcl_current_lang];
|
||||
|
||||
for (auto ext : CHECKED_SUBT_EXTENSIONS) {
|
||||
SCP_string fileName;
|
||||
@@ -362,10 +449,11 @@ std::unique_ptr<InputStream> openSubtitleStream(const SCP_string &name) {
|
||||
}
|
||||
}
|
||||
|
||||
bool FFMPEGDecoder::initialize(const SCP_string& fileName) {
|
||||
bool FFMPEGDecoder::initialize(const SCP_string& fileName, const PlaybackProperties& properties)
|
||||
{
|
||||
SCP_string movieName = fileName;
|
||||
// First make the file name lower case
|
||||
std::transform(movieName.begin(), movieName.end(), movieName.begin(), ::tolower);
|
||||
std::transform(movieName.begin(), movieName.end(), movieName.begin(), [](char c) { return (char)::tolower(c); });
|
||||
|
||||
// Then remove the extension
|
||||
size_t dotPos = movieName.find('.');
|
||||
@@ -382,7 +470,7 @@ bool FFMPEGDecoder::initialize(const SCP_string& fileName) {
|
||||
auto subt = openSubtitleStream(movieName);
|
||||
|
||||
// We now have a valid input stream, try to find the correct streams
|
||||
auto status = initializeStatus(input, subt);
|
||||
auto status = initializeStatus(input, subt, properties);
|
||||
if (!status) {
|
||||
return false;
|
||||
}
|
||||
@@ -394,21 +482,25 @@ bool FFMPEGDecoder::initialize(const SCP_string& fileName) {
|
||||
std::swap(m_input, input);
|
||||
std::swap(m_subtitleInput, subt);
|
||||
std::swap(m_status, status);
|
||||
m_properties = properties;
|
||||
return true;
|
||||
}
|
||||
|
||||
MovieProperties FFMPEGDecoder::getProperties() const {
|
||||
MovieProperties FFMPEGDecoder::getProperties() const
|
||||
{
|
||||
MovieProperties props;
|
||||
props.size.width = static_cast<size_t>(m_status->videoCodecPars.width);
|
||||
props.size.height = static_cast<size_t>(m_status->videoCodecPars.height);
|
||||
|
||||
props.fps = static_cast<float>(getFrameRate(m_status->videoStream, m_status->videoCodecCtx));
|
||||
|
||||
props.pixelFormat = getPixelFormat(getConversionFormat(m_status->videoCodecPars.pixel_format));
|
||||
|
||||
return props;
|
||||
}
|
||||
|
||||
void FFMPEGDecoder::startDecoding() {
|
||||
std::unique_ptr<VideoDecoder> videoDecoder(new VideoDecoder(m_status.get()));
|
||||
std::unique_ptr<VideoDecoder> videoDecoder(new VideoDecoder(m_status.get(), getConversionFormat(m_status->videoCodecPars.pixel_format)));
|
||||
|
||||
std::unique_ptr<AudioDecoder> audioDecoder;
|
||||
std::unique_ptr<SubtitleDecoder> subtitleDecoder;
|
||||
@@ -430,74 +522,98 @@ void FFMPEGDecoder::startDecoding() {
|
||||
|
||||
auto ctx = m_input->m_ctx->ctx();
|
||||
AVPacket packet;
|
||||
while (isDecoding()) {
|
||||
auto read_err = av_read_frame(ctx, &packet);
|
||||
AVPacketScope scope(&packet);
|
||||
|
||||
if (read_err < 0) {
|
||||
if (read_err == AVERROR_EOF) {
|
||||
// Finished reading -> break out of loop
|
||||
break;
|
||||
} else if (avio_feof(ctx->pb) != 0) {
|
||||
// Also EOF!
|
||||
break;
|
||||
} else {
|
||||
// Some kind of other error, try to continue reading
|
||||
do {
|
||||
if (m_properties.looping) {
|
||||
// Only seek if we are looping the movie. The MVE code doesn't support seeking to this function may not be
|
||||
// called there
|
||||
auto seek_err = av_seek_frame(ctx, -1, 0, AVSEEK_FLAG_BACKWARD);
|
||||
if (seek_err < 0) {
|
||||
char errorStr[512];
|
||||
av_strerror(read_err, errorStr, sizeof(errorStr));
|
||||
mprintf(("FFMPEG: Failed to read frame! Error: %s\n", errorStr));
|
||||
|
||||
// Skip packet
|
||||
continue;
|
||||
av_strerror(seek_err, errorStr, sizeof(errorStr));
|
||||
mprintf(("FFMPEG: Failed to seek to start of movie file! Error: %s\n", errorStr));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (packet.stream_index == m_status->videoStreamIndex) {
|
||||
videoDecoder->decodePacket(&packet);
|
||||
|
||||
VideoFramePtr ptr;
|
||||
while((ptr = videoDecoder->getFrame()) != nullptr) {
|
||||
pushFrameData(std::move(ptr));
|
||||
}
|
||||
} else if (audioDecoder && packet.stream_index == m_status->audioStreamIndex) {
|
||||
audioDecoder->decodePacket(&packet);
|
||||
|
||||
AudioFramePtr ptr;
|
||||
while ((ptr = audioDecoder->getFrame()) != nullptr) {
|
||||
pushAudioData(std::move(ptr));
|
||||
}
|
||||
} else if (subtitleDecoder && packet.stream_index == m_status->subtitleStreamIndex) {
|
||||
subtitleDecoder->decodePacket(&packet);
|
||||
|
||||
SubtitleFramePtr ptr;
|
||||
while ((ptr = subtitleDecoder->getFrame()) != nullptr) {
|
||||
pushSubtitleData(std::move(ptr));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isDecoding()) {
|
||||
// If we are still alive then read the last frames from the decoders
|
||||
videoDecoder->finishDecoding();
|
||||
VideoFramePtr video_ptr;
|
||||
while ((video_ptr = videoDecoder->getFrame()) != nullptr) {
|
||||
pushFrameData(std::move(video_ptr));
|
||||
}
|
||||
|
||||
videoDecoder->flushBuffers();
|
||||
if (audioDecoder) {
|
||||
audioDecoder->finishDecoding();
|
||||
AudioFramePtr audio_frame;
|
||||
while ((audio_frame = audioDecoder->getFrame()) != nullptr) {
|
||||
pushAudioData(std::move(audio_frame));
|
||||
audioDecoder->flushBuffers();
|
||||
}
|
||||
if (subtitleDecoder) {
|
||||
subtitleDecoder->flushBuffers();
|
||||
}
|
||||
|
||||
while (isDecoding()) {
|
||||
auto read_err = av_read_frame(ctx, &packet);
|
||||
AVPacketScope scope(&packet);
|
||||
|
||||
if (read_err < 0) {
|
||||
if (read_err == AVERROR_EOF) {
|
||||
// Finished reading -> break out of loop
|
||||
break;
|
||||
} else if (avio_feof(ctx->pb) != 0) {
|
||||
// Also EOF!
|
||||
break;
|
||||
} else {
|
||||
// Some kind of other error, try to continue reading
|
||||
char errorStr[512];
|
||||
av_strerror(read_err, errorStr, sizeof(errorStr));
|
||||
mprintf(("FFMPEG: Failed to read frame! Error: %s\n", errorStr));
|
||||
|
||||
// Skip packet
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (packet.stream_index == m_status->videoStreamIndex) {
|
||||
videoDecoder->decodePacket(&packet);
|
||||
|
||||
VideoFramePtr ptr;
|
||||
while ((ptr = videoDecoder->getFrame()) != nullptr) {
|
||||
pushFrameData(std::move(ptr));
|
||||
}
|
||||
} else if (audioDecoder && packet.stream_index == m_status->audioStreamIndex) {
|
||||
audioDecoder->decodePacket(&packet);
|
||||
|
||||
AudioFramePtr ptr;
|
||||
while ((ptr = audioDecoder->getFrame()) != nullptr) {
|
||||
pushAudioData(std::move(ptr));
|
||||
}
|
||||
} else if (subtitleDecoder && packet.stream_index == m_status->subtitleStreamIndex) {
|
||||
subtitleDecoder->decodePacket(&packet);
|
||||
|
||||
SubtitleFramePtr ptr;
|
||||
while ((ptr = subtitleDecoder->getFrame()) != nullptr) {
|
||||
pushSubtitleData(std::move(ptr));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isDecoding()) {
|
||||
// If we are still alive then read the last frames from the decoders
|
||||
videoDecoder->finishDecoding();
|
||||
VideoFramePtr video_ptr;
|
||||
while ((video_ptr = videoDecoder->getFrame()) != nullptr) {
|
||||
pushFrameData(std::move(video_ptr));
|
||||
}
|
||||
|
||||
if (audioDecoder) {
|
||||
audioDecoder->finishDecoding();
|
||||
AudioFramePtr audio_frame;
|
||||
while ((audio_frame = audioDecoder->getFrame()) != nullptr) {
|
||||
pushAudioData(std::move(audio_frame));
|
||||
}
|
||||
}
|
||||
}
|
||||
// If the video is being looped then we start again from the beginning
|
||||
} while (m_properties.looping && isDecoding());
|
||||
|
||||
// Stop the decoder first to let the subtitle thread know that it shouldn't continue
|
||||
stopDecoder();
|
||||
|
||||
if (subtitle_thread) {
|
||||
subtitle_thread->join();
|
||||
}
|
||||
|
||||
stopDecoder();
|
||||
}
|
||||
|
||||
bool FFMPEGDecoder::hasAudio() const { return m_status->audioStreamIndex >= 0; }
|
||||
@@ -520,7 +636,8 @@ void FFMPEGDecoder::close() {
|
||||
m_subtitleInput = nullptr;
|
||||
}
|
||||
}
|
||||
void FFMPEGDecoder::runSubtitleDecoder(SubtitleDecoder *decoder) {
|
||||
void FFMPEGDecoder::runSubtitleDecoder(SubtitleDecoder* decoder)
|
||||
{
|
||||
auto ctx = m_subtitleInput->m_ctx->ctx();
|
||||
AVPacket packet;
|
||||
|
||||
|
||||
@@ -18,16 +18,18 @@ class FFMPEGDecoder: public Decoder {
|
||||
|
||||
std::unique_ptr<DecoderStatus> m_status;
|
||||
|
||||
PlaybackProperties m_properties;
|
||||
|
||||
bool hasExternalSubtitle() const;
|
||||
|
||||
void runSubtitleDecoder(SubtitleDecoder *decoder);
|
||||
void runSubtitleDecoder(SubtitleDecoder* decoder);
|
||||
|
||||
public:
|
||||
FFMPEGDecoder();
|
||||
|
||||
~FFMPEGDecoder() override;
|
||||
|
||||
bool initialize(const SCP_string& fileName) override;
|
||||
bool initialize(const SCP_string& fileName, const PlaybackProperties& properties) override;
|
||||
|
||||
MovieProperties getProperties() const override;
|
||||
|
||||
|
||||
@@ -129,6 +129,9 @@ void SubtitleDecoder::pushSubtitleFrame(AVPacket* packet, AVSubtitle* subtitle)
|
||||
|
||||
pushFrame(std::move(frame));
|
||||
}
|
||||
void SubtitleDecoder::flushBuffers() {
|
||||
avcodec_flush_buffers(m_status->subtitleCodecCtx);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ class SubtitleDecoder: public FFMPEGStreamDecoder<SubtitleFrame> {
|
||||
|
||||
void finishDecoding() override;
|
||||
void pushSubtitleFrame(AVPacket* subtitle, AVSubtitle* pSubtitle);
|
||||
void flushBuffers() override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -3,11 +3,9 @@
|
||||
#include "tracing/tracing.h"
|
||||
|
||||
namespace {
|
||||
const AVPixelFormat DESTINATION_FORMAT = AV_PIX_FMT_YUV420P;
|
||||
|
||||
SwsContext* getSWSContext(int width, int height, AVPixelFormat fmt) {
|
||||
return sws_getContext(width, height, fmt, width, height, DESTINATION_FORMAT,
|
||||
SWS_BILINEAR, nullptr, nullptr, nullptr);
|
||||
SwsContext* getSWSContext(int width, int height, AVPixelFormat fmt, AVPixelFormat destination_fmt)
|
||||
{
|
||||
return sws_getContext(width, height, fmt, width, height, destination_fmt, SWS_BILINEAR, nullptr, nullptr, nullptr);
|
||||
}
|
||||
|
||||
double getFrameTime(int64_t pts, AVRational time_base) {
|
||||
@@ -18,34 +16,53 @@ double getFrameTime(int64_t pts, AVRational time_base) {
|
||||
namespace cutscene {
|
||||
namespace ffmpeg {
|
||||
class FFMPEGVideoFrame: public VideoFrame {
|
||||
public:
|
||||
FFMPEGVideoFrame() : frame(nullptr) {
|
||||
}
|
||||
size_t _width;
|
||||
size_t _height;
|
||||
AVFrame* _frame;
|
||||
|
||||
public:
|
||||
FFMPEGVideoFrame(size_t width, size_t height, AVFrame* frame) : _width(width), _height(height), _frame(frame) {}
|
||||
|
||||
~FFMPEGVideoFrame() override {
|
||||
if (frame != nullptr) {
|
||||
av_freep(&frame->data[0]);
|
||||
av_frame_free(&frame);
|
||||
if (_frame != nullptr) {
|
||||
av_freep(&_frame->data[0]);
|
||||
av_frame_free(&_frame);
|
||||
}
|
||||
}
|
||||
|
||||
DataPointers getDataPointers() override {
|
||||
DataPointers ptrs;
|
||||
ptrs.y = frame->data[0];
|
||||
ptrs.u = frame->data[1];
|
||||
ptrs.v = frame->data[2];
|
||||
|
||||
return ptrs;
|
||||
size_t getPlaneNumber() override
|
||||
{
|
||||
switch (_frame->format) {
|
||||
case AV_PIX_FMT_YUV420P:
|
||||
// YUV data is planar
|
||||
return 3;
|
||||
default:
|
||||
// Everything else is packed
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
FrameSize getPlaneSize(size_t plane) override
|
||||
{
|
||||
switch (_frame->format) {
|
||||
case AV_PIX_FMT_YUV420P: {
|
||||
// YUV data is planar
|
||||
auto width = plane > 0 ? _width / 2 : _width;
|
||||
auto height = plane > 0 ? _height / 2 : _height;
|
||||
|
||||
AVFrame* frame;
|
||||
return {width, height, (size_t)_frame->linesize[plane]};
|
||||
}
|
||||
default:
|
||||
// Everything else is packed
|
||||
return {_width, _height, (size_t)_frame->linesize[plane]};
|
||||
}
|
||||
}
|
||||
void* getPlaneData(size_t plane) override { return _frame->data[plane]; }
|
||||
};
|
||||
|
||||
VideoDecoder::VideoDecoder(DecoderStatus* status)
|
||||
: FFMPEGStreamDecoder(status),
|
||||
m_frameId(0) {
|
||||
VideoDecoder::VideoDecoder(DecoderStatus* status, AVPixelFormat destination_fmt)
|
||||
: FFMPEGStreamDecoder(status), m_frameId(0), m_destinationFormat(destination_fmt)
|
||||
{
|
||||
m_swsCtx = getSWSContext(m_status->videoCodecPars.width, m_status->videoCodecPars.height,
|
||||
m_status->videoCodecPars.pixel_format);
|
||||
m_status->videoCodecPars.pixel_format, destination_fmt);
|
||||
}
|
||||
|
||||
VideoDecoder::~VideoDecoder() {
|
||||
@@ -53,53 +70,32 @@ VideoDecoder::~VideoDecoder() {
|
||||
}
|
||||
|
||||
void VideoDecoder::convertAndPushPicture(const AVFrame* frame) {
|
||||
// Allocate a picture to hold the YUV data
|
||||
// Allocate a picture to hold the destination data
|
||||
AVFrame* yuvFrame = av_frame_alloc();
|
||||
av_frame_copy(yuvFrame, frame);
|
||||
yuvFrame->format = DESTINATION_FORMAT;
|
||||
yuvFrame->format = m_destinationFormat;
|
||||
|
||||
av_image_alloc(yuvFrame->data,
|
||||
yuvFrame->linesize,
|
||||
m_status->videoCodecPars.width,
|
||||
m_status->videoCodecPars.height,
|
||||
DESTINATION_FORMAT,
|
||||
1);
|
||||
av_image_alloc(yuvFrame->data, yuvFrame->linesize, m_status->videoCodecPars.width, m_status->videoCodecPars.height,
|
||||
m_destinationFormat, 1);
|
||||
|
||||
std::unique_ptr<FFMPEGVideoFrame> videoFramePtr(new FFMPEGVideoFrame());
|
||||
|
||||
if (m_status->videoCodecPars.pixel_format == DESTINATION_FORMAT) {
|
||||
av_image_copy(yuvFrame->data,
|
||||
yuvFrame->linesize,
|
||||
(const uint8_t**) (frame->data),
|
||||
frame->linesize,
|
||||
DESTINATION_FORMAT,
|
||||
m_status->videoCodecPars.width,
|
||||
m_status->videoCodecPars.height);
|
||||
if (m_status->videoCodecPars.pixel_format == m_destinationFormat) {
|
||||
av_image_copy(yuvFrame->data, yuvFrame->linesize, (const uint8_t**)(frame->data), frame->linesize,
|
||||
m_destinationFormat, m_status->videoCodecPars.width, m_status->videoCodecPars.height);
|
||||
} else {
|
||||
// Convert frame to YUV
|
||||
sws_scale(
|
||||
m_swsCtx,
|
||||
(uint8_t const* const*) frame->data,
|
||||
frame->linesize,
|
||||
0,
|
||||
m_status->videoCodecPars.height,
|
||||
yuvFrame->data,
|
||||
yuvFrame->linesize
|
||||
);
|
||||
// Convert frame to destination format
|
||||
sws_scale(m_swsCtx, (uint8_t const* const*)frame->data, frame->linesize, 0, m_status->videoCodecPars.height,
|
||||
yuvFrame->data, yuvFrame->linesize);
|
||||
}
|
||||
|
||||
std::unique_ptr<FFMPEGVideoFrame> videoFramePtr(
|
||||
new FFMPEGVideoFrame(static_cast<size_t>(m_status->videoCodecPars.width),
|
||||
static_cast<size_t>(m_status->videoCodecPars.height), yuvFrame));
|
||||
videoFramePtr->id = ++m_frameId;
|
||||
#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(58, 3, 102)
|
||||
videoFramePtr->frameTime = getFrameTime(frame->best_effort_timestamp, m_status->videoStream->time_base);
|
||||
#else
|
||||
videoFramePtr->frameTime = getFrameTime(av_frame_get_best_effort_timestamp(frame), m_status->videoStream->time_base);
|
||||
videoFramePtr->frame = yuvFrame;
|
||||
|
||||
videoFramePtr->ySize.height = static_cast<size_t>(m_status->videoCodecPars.height);
|
||||
videoFramePtr->ySize.width = static_cast<size_t>(m_status->videoCodecPars.width);
|
||||
videoFramePtr->ySize.stride = static_cast<size_t>(yuvFrame->linesize[0]);
|
||||
|
||||
// 420P means that the UV channels have half the width and height
|
||||
videoFramePtr->uvSize.height = static_cast<size_t>(m_status->videoCodecPars.height / 2);
|
||||
videoFramePtr->uvSize.width = static_cast<size_t>(m_status->videoCodecPars.width / 2);
|
||||
videoFramePtr->uvSize.stride = static_cast<size_t>(yuvFrame->linesize[1]);
|
||||
#endif
|
||||
|
||||
pushFrame(VideoFramePtr(videoFramePtr.release()));
|
||||
}
|
||||
@@ -162,5 +158,8 @@ void VideoDecoder::finishDecoding() {
|
||||
}
|
||||
#endif
|
||||
}
|
||||
void VideoDecoder::flushBuffers() {
|
||||
avcodec_flush_buffers(m_status->videoCodecCtx);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,17 +9,20 @@ class VideoDecoder: public FFMPEGStreamDecoder<VideoFrame> {
|
||||
private:
|
||||
int m_frameId;
|
||||
SwsContext* m_swsCtx;
|
||||
AVPixelFormat m_destinationFormat;
|
||||
|
||||
void convertAndPushPicture(const AVFrame* frame);
|
||||
|
||||
public:
|
||||
explicit VideoDecoder(DecoderStatus* status);
|
||||
explicit VideoDecoder(DecoderStatus* status, AVPixelFormat destination_fmt);
|
||||
|
||||
~VideoDecoder() override;
|
||||
|
||||
void decodePacket(AVPacket* packet) override;
|
||||
|
||||
void finishDecoding() override;
|
||||
|
||||
void flushBuffers() override;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -74,6 +74,8 @@ class FFMPEGStreamDecoder {
|
||||
|
||||
virtual void finishDecoding() = 0;
|
||||
|
||||
virtual void flushBuffers() = 0;
|
||||
|
||||
virtual FramePtr<frame_type> getFrame();
|
||||
};
|
||||
|
||||
|
||||
+25
-16
@@ -44,21 +44,11 @@ struct PlaybackState {
|
||||
int subtitle_font = -1;
|
||||
};
|
||||
|
||||
void processEvents(PlaybackState* state) {
|
||||
void processEvents()
|
||||
{
|
||||
io::mouse::CursorManager::get()->showCursor(false);
|
||||
|
||||
os_poll();
|
||||
|
||||
int k = key_inkey();
|
||||
switch (k) {
|
||||
case KEY_ESC:
|
||||
case KEY_ENTER:
|
||||
case KEY_SPACEBAR:
|
||||
state->playing = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
@@ -193,6 +183,21 @@ void movie_display_loop(Player* player, PlaybackState* state) {
|
||||
// We will sleep at most half the time a frame would be displayed
|
||||
auto sleepTime = static_cast<std::uint64_t>((1. / (4. * player->getMovieProperties().fps)) * 1000.);
|
||||
|
||||
auto listener = [state](const SDL_Event& event) {
|
||||
switch (event.key.keysym.sym) {
|
||||
case SDLK_ESCAPE:
|
||||
case SDLK_KP_ENTER:
|
||||
case SDLK_RETURN:
|
||||
case SDLK_SPACE:
|
||||
state->playing = false;
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
};
|
||||
// Use a dedicated listener here since we want to listen for the KEYUP event
|
||||
auto key_handle = os::events::addEventListener(SDL_KEYUP, os::events::DEFAULT_LISTENER_WEIGHT - 10, listener);
|
||||
|
||||
auto lastDisplayTimestamp = timer_get_microseconds();
|
||||
while (state->playing) {
|
||||
TRACE_SCOPE(tracing::CutsceneStep);
|
||||
@@ -202,12 +207,14 @@ void movie_display_loop(Player* player, PlaybackState* state) {
|
||||
auto passed = timestamp - lastDisplayTimestamp;
|
||||
lastDisplayTimestamp = timestamp;
|
||||
|
||||
// Play as long as the player reports that there is more to display
|
||||
state->playing = player->update(passed);
|
||||
if (player->isPlaybackReady()) {
|
||||
// Play as long as the player reports that there is more to display
|
||||
state->playing = player->update(passed);
|
||||
|
||||
displayVideo(player, state);
|
||||
displayVideo(player, state);
|
||||
}
|
||||
|
||||
processEvents(state);
|
||||
processEvents();
|
||||
|
||||
if (passed < sleepTime) {
|
||||
auto sleep = sleepTime - passed;
|
||||
@@ -215,6 +222,8 @@ void movie_display_loop(Player* player, PlaybackState* state) {
|
||||
os_sleep(static_cast<uint>(sleep));
|
||||
}
|
||||
}
|
||||
|
||||
os::events::removeEventListener(key_handle);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+36
-22
@@ -17,6 +17,7 @@
|
||||
#include "io/key.h"
|
||||
#include "io/timer.h"
|
||||
|
||||
#include "player.h"
|
||||
#include "parse/parselo.h"
|
||||
|
||||
using namespace cutscene::player;
|
||||
@@ -26,10 +27,10 @@ using namespace cutscene;
|
||||
|
||||
const int MAX_AUDIO_BUFFERS = 15;
|
||||
|
||||
std::unique_ptr<Decoder> findDecoder(const SCP_string& name) {
|
||||
std::unique_ptr<Decoder> findDecoder(const SCP_string& name, const PlaybackProperties& properties) {
|
||||
{
|
||||
std::unique_ptr<Decoder> ffmpeg(new ffmpeg::FFMPEGDecoder());
|
||||
if (ffmpeg->initialize(name)) {
|
||||
std::unique_ptr<Decoder> ffmpeg(new ::cutscene::ffmpeg::FFMPEGDecoder());
|
||||
if (ffmpeg->initialize(name, properties)) {
|
||||
return ffmpeg;
|
||||
}
|
||||
}
|
||||
@@ -49,7 +50,8 @@ void videoPlaybackInit(PlayerState* state) {
|
||||
|
||||
Assert(state != NULL);
|
||||
|
||||
if (gr_screen.mode == GR_OPENGL) {
|
||||
if (gr_screen.mode != GR_STUB) {
|
||||
// The video presenter is independent of the underlying graphics API
|
||||
state->videoPresenter.reset(new VideoPresenter(state->props));
|
||||
}
|
||||
|
||||
@@ -121,6 +123,15 @@ void processVideoData(PlayerState* state) {
|
||||
}
|
||||
|
||||
while (currentTime >= state->nextFrame->frameTime) {
|
||||
if (state->currentFrame) {
|
||||
if (state->nextFrame->frameTime < state->currentFrame->frameTime) {
|
||||
// We reached the end of the movie and just looped to the beginning. Now we need to reset the playback
|
||||
// time
|
||||
state->playback_time = 0;
|
||||
currentTime = playbackGetTime(state);
|
||||
}
|
||||
}
|
||||
|
||||
// Move the next frame to the current frame slot
|
||||
state->currentFrame = std::move(state->nextFrame);
|
||||
|
||||
@@ -272,8 +283,22 @@ bool shouldBeginPlayback(Decoder* decoder) {
|
||||
}
|
||||
|
||||
namespace cutscene {
|
||||
Player::Player(std::unique_ptr<Decoder>&& decoder) : m_decoder(std::move(decoder)) {
|
||||
initPlayback();
|
||||
Player::Player(std::unique_ptr<Decoder>&& decoder, const PlaybackProperties& properties)
|
||||
: m_decoder(std::move(decoder))
|
||||
{
|
||||
Assertion(!m_state.videoInited,
|
||||
"Internal State has been initialized before! Create a new player for replaying a movie.");
|
||||
|
||||
m_decoderThread.reset(new std::thread(std::bind(&Player::decoderThread, this)));
|
||||
|
||||
m_state.props = m_decoder->getProperties();
|
||||
m_state.decoder = m_decoder.get();
|
||||
|
||||
videoPlaybackInit(&m_state);
|
||||
|
||||
if (properties.with_audio) {
|
||||
audioPlaybackInit(&m_state);
|
||||
}
|
||||
}
|
||||
|
||||
Player::~Player() {
|
||||
@@ -315,19 +340,6 @@ bool Player::processDecoderData() {
|
||||
|
||||
return decoding || pendingAudio || pendingVideo;
|
||||
}
|
||||
|
||||
void Player::initPlayback() {
|
||||
Assertion(!m_state.videoInited, "Internal State has been initialized before! Create a new player for replaying a movie.");
|
||||
|
||||
m_decoderThread.reset(new std::thread(std::bind(&Player::decoderThread, this)));
|
||||
|
||||
m_state.props = m_decoder->getProperties();
|
||||
m_state.decoder = m_decoder.get();
|
||||
|
||||
videoPlaybackInit(&m_state);
|
||||
|
||||
audioPlaybackInit(&m_state);
|
||||
}
|
||||
bool Player::update(uint64_t diff_time_micro) {
|
||||
if (m_state.playbackHasBegun) {
|
||||
m_state.playback_time += diff_time_micro;
|
||||
@@ -354,15 +366,16 @@ void Player::decoderThread() {
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<Player> Player::newPlayer(const SCP_string& name) {
|
||||
std::unique_ptr<Player> Player::newPlayer(const SCP_string& name, const PlaybackProperties& properties)
|
||||
{
|
||||
mprintf(("Creating player for movie '%s'.\n", name.c_str()));
|
||||
|
||||
auto decoder = findDecoder(name);
|
||||
auto decoder = findDecoder(name, properties);
|
||||
|
||||
if (decoder == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
return std::unique_ptr<Player>(new Player(std::move(decoder)));
|
||||
return std::unique_ptr<Player>(new Player(std::move(decoder), properties));
|
||||
}
|
||||
const PlayerState& Player::getInternalState() const {
|
||||
return m_state;
|
||||
@@ -386,4 +399,5 @@ SCP_string Player::getCurrentSubtitle() {
|
||||
return m_state.currentSubtitle->text;
|
||||
}
|
||||
}
|
||||
bool Player::isPlaybackReady() const { return m_state.playbackHasBegun || shouldBeginPlayback(m_decoder.get()); }
|
||||
}
|
||||
+21
-13
@@ -52,7 +52,7 @@ struct PlayerState {
|
||||
* @brief A movie player
|
||||
*/
|
||||
class Player {
|
||||
private:
|
||||
private:
|
||||
std::unique_ptr<Decoder> m_decoder;
|
||||
|
||||
std::unique_ptr<std::thread> m_decoderThread;
|
||||
@@ -61,14 +61,11 @@ class Player {
|
||||
|
||||
bool processDecoderData();
|
||||
|
||||
private:
|
||||
private:
|
||||
void decoderThread();
|
||||
|
||||
void initPlayback();
|
||||
|
||||
public:
|
||||
explicit Player(std::unique_ptr<Decoder>&& decoder);
|
||||
|
||||
Player(std::unique_ptr<Decoder>&& decoder, const PlaybackProperties& properties);
|
||||
public:
|
||||
~Player();
|
||||
|
||||
Player(const Player&) = delete;
|
||||
@@ -97,6 +94,12 @@ class Player {
|
||||
*/
|
||||
const MovieProperties& getMovieProperties() const;
|
||||
|
||||
/**
|
||||
* @brief Determines if this player can start displaying video.
|
||||
* @return true if the cutscene is ready, false otherwise
|
||||
*/
|
||||
bool isPlaybackReady() const;
|
||||
|
||||
/**
|
||||
* @brief Draws the current movie frame at the specified coordinates.
|
||||
*
|
||||
@@ -109,6 +112,10 @@ class Player {
|
||||
*/
|
||||
void draw(float x1, float y1, float x2, float y2);
|
||||
|
||||
/**
|
||||
* @brief Gets the subtitle text that should be displayed now
|
||||
* @return The text, encoded in UTF-8
|
||||
*/
|
||||
SCP_string getCurrentSubtitle();
|
||||
|
||||
/**
|
||||
@@ -119,11 +126,12 @@ class Player {
|
||||
void stopPlayback();
|
||||
|
||||
/**
|
||||
* @brief Creates a player
|
||||
* The player is configured to play the movie with the specified name
|
||||
* @param name The movie to play
|
||||
* @return @c nullptr if the specified movie could not be opened, a valid Player pointer otherwise
|
||||
*/
|
||||
static std::unique_ptr<Player> newPlayer(const SCP_string& name);
|
||||
* @brief Creates a player
|
||||
* The player is configured to play the movie with the specified name
|
||||
* @param name The movie to play
|
||||
* @param properties A structure describing how the movie will be used
|
||||
* @return @c nullptr if the specified movie could not be opened, a valid Player pointer otherwise
|
||||
*/
|
||||
static std::unique_ptr<Player> newPlayer(const SCP_string& name, const PlaybackProperties& properties = PlaybackProperties());
|
||||
};
|
||||
}
|
||||
+4
-19
@@ -31,7 +31,6 @@
|
||||
#include "weapon/weapon.h"
|
||||
#include "tracing/Monitor.h"
|
||||
|
||||
#define MAX_LIFE 10.0f
|
||||
#define MIN_RADIUS_FOR_PERSISTANT_DEBRIS 50 // ship radius at which debris from it becomes persistant
|
||||
#define DEBRIS_SOUND_DELAY 2000 // time to start debris sound after created
|
||||
#define MAX_HULL_PIECES MAX_DEBRIS_PIECES // limit the number of hull debris chunks that can exist.
|
||||
@@ -52,10 +51,6 @@ int Debris_num_submodels = 0;
|
||||
#define DEBRIS_DISTANCE_CHECK_TIME (10*1000) // Check every 10 seconds.
|
||||
#define DEBRIS_INDEX(dp) (int)(dp-Debris)
|
||||
|
||||
#define MAX_SPEED_SMALL_DEBRIS 200 // maximum velocity of small debris piece
|
||||
#define MAX_SPEED_BIG_DEBRIS 150 // maximum velocity of big debris piece
|
||||
#define MAX_SPEED_CAPITAL_DEBRIS 100 // maximum velocity of capital debris piece
|
||||
|
||||
/**
|
||||
* Start the sequence of a piece of debris writhing in unholy agony!!!
|
||||
*/
|
||||
@@ -270,13 +265,8 @@ void debris_process_post(object * obj, float frame_time)
|
||||
|
||||
vec3d v1, v2, v3, v4;
|
||||
|
||||
if ( Cmdline_old_collision_sys ) {
|
||||
submodel_get_two_random_points( db->model_num, db->submodel_num, &v1, &v2 );
|
||||
submodel_get_two_random_points( db->model_num, db->submodel_num, &v3, &v4 );
|
||||
} else {
|
||||
submodel_get_two_random_points_better( db->model_num, db->submodel_num, &v1, &v2 );
|
||||
submodel_get_two_random_points_better( db->model_num, db->submodel_num, &v3, &v4 );
|
||||
}
|
||||
submodel_get_two_random_points_better(db->model_num, db->submodel_num, &v1, &v2);
|
||||
submodel_get_two_random_points_better(db->model_num, db->submodel_num, &v3, &v4);
|
||||
|
||||
n = 0;
|
||||
|
||||
@@ -352,12 +342,8 @@ void debris_process_post(object * obj, float frame_time)
|
||||
if ( mr < RAND_MAX/5 ) {
|
||||
vec3d v1, v2;
|
||||
|
||||
if ( Cmdline_old_collision_sys ) {
|
||||
submodel_get_two_random_points( db->model_num, db->submodel_num, &v1, &v2 );
|
||||
} else {
|
||||
submodel_get_two_random_points_better( db->model_num, db->submodel_num, &v1, &v2 );
|
||||
}
|
||||
|
||||
submodel_get_two_random_points_better(db->model_num, db->submodel_num, &v1, &v2);
|
||||
|
||||
db->arc_pts[i][mr % 2] = v1;
|
||||
}
|
||||
}
|
||||
@@ -505,7 +491,6 @@ object *debris_create(object *source_obj, int model_num, int submodel_num, vec3d
|
||||
db->flags |= DEBRIS_USED;
|
||||
db->is_hull = hull_flag;
|
||||
db->source_objnum = parent_objnum;
|
||||
db->source_sig = source_obj->signature;
|
||||
db->damage_type_idx = shipp->debris_damage_type_idx;
|
||||
db->ship_info_index = shipp->ship_info_index;
|
||||
db->team = shipp->team;
|
||||
|
||||
@@ -24,7 +24,6 @@ typedef struct debris {
|
||||
debris *next, *prev; // used for a linked list of the hull debris chunks
|
||||
int flags; // See DEBRIS_??? defines
|
||||
int source_objnum; // What object this came from
|
||||
int source_sig; // Signature of the source object
|
||||
int damage_type_idx; // Damage type of this debris
|
||||
int ship_info_index; // Ship info index of the ship type debris came from
|
||||
int team; // Team of the ship where the debris came from
|
||||
|
||||
@@ -70,7 +70,6 @@ int dc_font = font::FONT1;
|
||||
|
||||
SCP_string dc_title;
|
||||
|
||||
#define SCROLL_X_MAX (DBCOLS - DCOLS)
|
||||
#define SCROLL_Y_MAX (DBROWS - DROWS)
|
||||
|
||||
// Commands and History
|
||||
@@ -117,11 +116,6 @@ void dc_draw_window(bool show_prompt);
|
||||
*/
|
||||
void dc_putc(char c);
|
||||
|
||||
/**
|
||||
* @brief Predicate function used to sort debug_commands
|
||||
*/
|
||||
bool dcmd_less(debug_command *first, debug_command *second);
|
||||
|
||||
// ============================== IMPLEMENTATIONS =============================
|
||||
void dc_do_command(SCP_string *cmd_str)
|
||||
{
|
||||
@@ -494,11 +488,6 @@ void dc_putc(char c)
|
||||
line_str->push_back(c);
|
||||
}
|
||||
|
||||
bool dcmd_less(debug_command *first, debug_command *second)
|
||||
{
|
||||
return (strcmp(first->name, second->name) < 0);
|
||||
}
|
||||
|
||||
void debug_console(void (*_func)(void))
|
||||
{
|
||||
int done = 0;
|
||||
|
||||
@@ -28,10 +28,6 @@ debug_command *dc_commands[DC_MAX_COMMANDS];
|
||||
int dc_commands_size = 0;
|
||||
|
||||
// ========================= LOCALS ==========================
|
||||
// dcf_shell commands
|
||||
void dc_shell_font( void );
|
||||
void dc_shell_resize( void );
|
||||
void dc_shell_resize_buf( void );
|
||||
|
||||
// =================== class debug_command ===================
|
||||
debug_command::debug_command()
|
||||
@@ -155,6 +151,4 @@ DCF(help, "Displays the help list." )
|
||||
|
||||
dc_printf(" %s - %s\n", dc_commands[i]->name, dc_commands[i]->help);
|
||||
}
|
||||
}
|
||||
|
||||
debug_command dc_man("man", "Also displays the help list", dcf_help);
|
||||
}
|
||||
@@ -226,6 +226,7 @@ void parse_decals_table(const char* filename) {
|
||||
struct Decal {
|
||||
int definition_handle = -1;
|
||||
object_h object;
|
||||
int orig_obj_type = OBJ_NONE;
|
||||
int submodel = -1;
|
||||
|
||||
float creation_time = -1.0f; //!< The mission time at which this decal was created
|
||||
@@ -244,6 +245,12 @@ struct Decal {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (orig_obj_type != object.objp->type) {
|
||||
mprintf(("Decal object type for object %d has changed from %s to %s. Please let m!m know about this\n",
|
||||
OBJ_INDEX(object.objp), Object_type_names[orig_obj_type], Object_type_names[object.objp->type]));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (lifetime > 0.0f) {
|
||||
if (f2fl(Missiontime) >= creation_time + lifetime) {
|
||||
// Decal has expired
|
||||
@@ -525,6 +532,7 @@ addDecal(creation_info& info, object* host, int submodel, const vec3d& local_pos
|
||||
Decal newDecal;
|
||||
newDecal.definition_handle = info.definition_handle;
|
||||
newDecal.object = object_h(host);
|
||||
newDecal.orig_obj_type = host->type;
|
||||
newDecal.submodel = submodel;
|
||||
newDecal.creation_time = f2fl(Missiontime);
|
||||
newDecal.lifetime = info.lifetime.next();
|
||||
|
||||
@@ -24,11 +24,15 @@ void main()
|
||||
// Now we compute the depth value in projection space using the clipping plane information
|
||||
float view_depth = 2.0 * zNear * zFar / (zFar + zNear - depth_normalized * (zFar - zNear));
|
||||
|
||||
// This is the same formula that is also used by the main shader
|
||||
float fog_dist = isinf(view_depth) ? 1.0 : clamp((view_depth - fog_start) * 0.75 * fog_scale, 0.0, 1.0);
|
||||
if (isinf(view_depth)) {
|
||||
fragOut0.rgb = color_in.rgb;
|
||||
} else {
|
||||
// This is the same formula that is also used by the main shader
|
||||
float fog_dist = clamp((view_depth - fog_start) * 0.75 * fog_scale, 0.0, 1.0);
|
||||
|
||||
vec3 finalFogColor = srgb_to_linear(fog_color);
|
||||
vec3 finalFogColor = srgb_to_linear(fog_color);
|
||||
|
||||
fragOut0.rgb = mix(color_in.rgb, finalFogColor, fog_dist);
|
||||
fragOut0.rgb = mix(color_in.rgb, finalFogColor, fog_dist);
|
||||
}
|
||||
fragOut0.a = 1.0;
|
||||
}
|
||||
@@ -33,7 +33,7 @@ layout (std140) uniform modelData {
|
||||
|
||||
model_light lights[MAX_LIGHTS];
|
||||
|
||||
float extrudeWidth;
|
||||
float outlineWidth;
|
||||
float fogStart;
|
||||
float fogScale;
|
||||
int buffer_matrix_offset;
|
||||
@@ -105,11 +105,6 @@ in VertexOutput {
|
||||
#endif
|
||||
#ifdef FLAG_FOG
|
||||
float fogDist;
|
||||
#endif
|
||||
#ifdef WORKAROUND_CLIPPING_PLANES
|
||||
#ifdef FLAG_TRANSFORM
|
||||
float notVisible;
|
||||
#endif
|
||||
#endif
|
||||
vec4 position;
|
||||
vec3 normal;
|
||||
@@ -215,11 +210,6 @@ vec3 CalculateLighting(vec3 normal, vec3 diffuseMaterial, vec3 specularMaterial,
|
||||
|
||||
void main()
|
||||
{
|
||||
#ifdef WORKAROUND_CLIPPING_PLANES
|
||||
#ifdef FLAG_TRANSFORM
|
||||
if(vertIn.notVisible >= 0.9) { discard; }
|
||||
#endif
|
||||
#endif
|
||||
#ifdef FLAG_SHADOW_MAP
|
||||
// need depth and depth squared for variance shadow maps
|
||||
fragOut0 = vec4(vertIn.position.z, vertIn.position.z * vertIn.position.z * VARIANCE_SHADOW_SCALE_INV, 0.0, 1.0);
|
||||
@@ -290,11 +280,11 @@ void main()
|
||||
}
|
||||
if(gammaSpec) {
|
||||
specColor.rgb = max(specColor.rgb, vec3(0.03f)); // hardcoded minimum specular value. read John Hable's blog post titled 'Everything Is Shiny'.
|
||||
#ifdef FLAG_HDR
|
||||
specColor.rgb = srgb_to_linear(specColor.rgb);
|
||||
#endif
|
||||
fresnelFactor = 1.0;
|
||||
}
|
||||
#ifdef FLAG_HDR
|
||||
specColor.rgb = srgb_to_linear(specColor.rgb);
|
||||
#endif
|
||||
#endif
|
||||
baseColor.rgb *= aoFactors.y;
|
||||
specColor.rgb *= aoFactors.y;
|
||||
@@ -302,20 +292,29 @@ void main()
|
||||
#ifdef FLAG_TEAMCOLOR
|
||||
vec4 teamMask = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
teamMask = texture(sMiscmap, vec3(texCoord, float(sMiscmapIndex)));
|
||||
|
||||
//For team colors applied to a diffuse or spec map, we assume that the base color of the diffuse
|
||||
//at this point is vec3(0.5). To get accurate results, we subtract 0.5 from the team colors
|
||||
vec3 team_color = ((base_color - vec3(0.5)) * teamMask.x) + ((stripe_color - vec3(0.5)) * teamMask.y);
|
||||
vec3 color_offset = vec3(-0.5) * (teamMask.x + teamMask.y);
|
||||
|
||||
vec3 team_color = base_color * teamMask.x + stripe_color * teamMask.y + color_offset;
|
||||
vec3 team_color_glow = (base_color * teamMask.b) + (stripe_color * teamMask.a);
|
||||
|
||||
#ifdef FLAG_HDR
|
||||
team_color = srgb_to_linear(team_color);
|
||||
team_color_glow = srgb_to_linear(team_color_glow) * GLOW_MAP_SRGB_MULTIPLIER;
|
||||
baseColor.rgb = linear_to_srgb(baseColor.rgb);
|
||||
specColor.rgb = linear_to_srgb(specColor.rgb);
|
||||
#endif
|
||||
|
||||
baseColor.rgb += team_color;
|
||||
baseColor.rgb = max(baseColor.rgb, vec3(0.0)); // We need to make sure that nothing here ever goes negative
|
||||
specColor.rgb += team_color;
|
||||
specColor.rgb = max(specColor.rgb, vec3(0.03));
|
||||
|
||||
#ifdef FLAG_HDR
|
||||
baseColor.rgb = srgb_to_linear(baseColor.rgb);
|
||||
specColor.rgb = srgb_to_linear(specColor.rgb);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
||||
// Lights aren't applied when we are rendering to the G-buffers since that gets handled later
|
||||
@@ -426,6 +425,7 @@ void main()
|
||||
// emissive colors won't be added later when we are using forward rendering so we need to do that here
|
||||
baseColor.rgb += emissiveColor.rgb;
|
||||
#endif
|
||||
|
||||
fragOut0 = baseColor;
|
||||
#ifdef FLAG_DEFERRED
|
||||
fragOut1 = vec4(vertIn.position.xyz, 1.0);
|
||||
|
||||
@@ -1,9 +1,18 @@
|
||||
#extension GL_ARB_gpu_shader5: enable
|
||||
|
||||
#ifdef FLAG_THICK_OUTLINE
|
||||
layout (triangles) in;
|
||||
// For every triangle line we generate 2 triangles which can be done with 4 vertices so in total we will need 12 vertices
|
||||
layout (triangle_strip, max_vertices = 12) out;
|
||||
#else
|
||||
layout (triangles) in;
|
||||
layout (triangle_strip, max_vertices = 3) out;
|
||||
#ifdef GL_ARB_gpu_shader5
|
||||
#endif
|
||||
|
||||
#ifdef FLAG_SHADOW_MAP
|
||||
#ifdef GL_ARB_gpu_shader5
|
||||
layout(invocations = 4) in;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define MAX_LIGHTS 8
|
||||
@@ -33,7 +42,7 @@ layout (std140) uniform modelData {
|
||||
|
||||
model_light lights[MAX_LIGHTS];
|
||||
|
||||
float extrudeWidth;
|
||||
float outlineWidth;
|
||||
float fogStart;
|
||||
float fogScale;
|
||||
int buffer_matrix_offset;
|
||||
@@ -106,15 +115,13 @@ in VertexOutput {
|
||||
#ifdef FLAG_FOG
|
||||
float fogDist;
|
||||
#endif
|
||||
#ifdef WORKAROUND_CLIPPING_PLANES
|
||||
#ifdef FLAG_TRANSFORM
|
||||
float notVisible;
|
||||
#endif
|
||||
#endif
|
||||
#ifdef FLAG_SHADOW_MAP
|
||||
#if !defined(GL_ARB_gpu_shader5)
|
||||
float instance;
|
||||
#endif
|
||||
#ifdef FLAG_TRANSFORM
|
||||
float clipModel;
|
||||
#endif
|
||||
#else
|
||||
vec4 position;
|
||||
#endif
|
||||
@@ -135,11 +142,6 @@ out VertexOutput {
|
||||
#endif
|
||||
#ifdef FLAG_FOG
|
||||
float fogDist;
|
||||
#endif
|
||||
#ifdef WORKAROUND_CLIPPING_PLANES
|
||||
#ifdef FLAG_TRANSFORM
|
||||
float notVisible;
|
||||
#endif
|
||||
#endif
|
||||
vec4 position;
|
||||
vec3 normal;
|
||||
@@ -150,6 +152,7 @@ out VertexOutput {
|
||||
#endif
|
||||
} vertOut;
|
||||
|
||||
#ifdef FLAG_SHADOW_MAP
|
||||
void main(void)
|
||||
{
|
||||
#ifdef GL_ARB_gpu_shader5
|
||||
@@ -159,14 +162,25 @@ void main(void)
|
||||
#endif
|
||||
for(int vert = 0; vert < gl_in.length(); vert++)
|
||||
{
|
||||
#ifdef FLAG_TRANSFORM
|
||||
if (vertIn[vert].clipModel > 0.9) {
|
||||
// If the model was clipped in the vertex shader then we do not apply the shadow projection matrix here
|
||||
gl_Position = gl_in[vert].gl_Position;
|
||||
} else {
|
||||
gl_Position = shadow_proj_matrix[instanceID] * gl_in[vert].gl_Position;
|
||||
}
|
||||
#else
|
||||
gl_Position = shadow_proj_matrix[instanceID] * gl_in[vert].gl_Position;
|
||||
#endif
|
||||
if(gl_Position.z < -1.0)
|
||||
gl_Position.z = -1.0;
|
||||
|
||||
vertOut.position = gl_in[vert].gl_Position;
|
||||
vertOut.normal = vertIn[vert].normal;
|
||||
vertOut.texCoord = vertIn[vert].texCoord;
|
||||
|
||||
gl_Layer = instanceID;
|
||||
|
||||
#ifdef FLAG_ENV_MAP
|
||||
vertOut.envReflect = vertIn[vert].envReflect;
|
||||
#endif
|
||||
@@ -183,19 +197,66 @@ void main(void)
|
||||
vertOut.shadowUV[3] = vertIn[vert].shadowUV[3];
|
||||
vertOut.shadowPos = vertIn[vert].shadowPos;
|
||||
#endif
|
||||
#ifdef WORKAROUND_CLIPPING_PLANES
|
||||
#ifdef FLAG_TRANSFORM
|
||||
vertOut.notVisible = vertIn[vert].notVisible;
|
||||
#endif
|
||||
#ifdef FLAG_CLIP
|
||||
#if defined(FLAG_CLIP)
|
||||
gl_ClipDistance[0] = gl_in[vert].gl_ClipDistance[0];
|
||||
#endif
|
||||
#else
|
||||
#if defined(FLAG_CLIP) || defined(FLAG_TRANSFORM)
|
||||
gl_ClipDistance[0] = gl_in[vert].gl_ClipDistance[0];
|
||||
#endif
|
||||
#endif
|
||||
EmitVertex();
|
||||
}
|
||||
EndPrimitive();
|
||||
}
|
||||
#elif defined(FLAG_THICK_OUTLINE)
|
||||
const vec2 pixelOffsetDir[4] = vec2[](
|
||||
vec2(0.0, 1.0),
|
||||
vec2(1.0, 1.0),
|
||||
vec2(1.0, -1.0),
|
||||
vec2(0.0, -1.0)
|
||||
);
|
||||
void main(void)
|
||||
{
|
||||
for(int vert = 0; vert < gl_in.length(); vert++)
|
||||
{
|
||||
int nextVert = (vert + 1) % gl_in.length();
|
||||
vec4 clip = gl_in[vert].gl_Position;
|
||||
vec4 diff = gl_in[nextVert].gl_Position - clip; // vector from vert to the next vertex in the list
|
||||
vec2 normal = normalize(vec2(diff.y, -diff.x)); // Computing the normal of a 2D vector is actually rather simple...
|
||||
for (int lineVert = 0; lineVert < 4; ++lineVert)
|
||||
{
|
||||
// This is the pixel offset along the normal axis
|
||||
vec2 yOffPixel = pixelOffsetDir[lineVert].y * normal * (outlineWidth / 2.0);
|
||||
// This is the offset of the vertex along the vector between this vertex and the next one in the triangle
|
||||
vec2 xOff = pixelOffsetDir[lineVert].x * diff.xy;
|
||||
|
||||
// This is the final offset in clip space
|
||||
vec2 finalOffset = xOff + yOffPixel * vec2(vpwidth, vpheight) * clip.w;
|
||||
|
||||
gl_Position = vec4(clip.xyz + vec3(finalOffset, 0.0), clip.w);
|
||||
vertOut.position = vertIn[vert].position;
|
||||
vertOut.normal = vertIn[vert].normal;
|
||||
vertOut.texCoord = vertIn[vert].texCoord;
|
||||
|
||||
#ifdef FLAG_ENV_MAP
|
||||
vertOut.envReflect = vertIn[vert].envReflect;
|
||||
#endif
|
||||
#ifdef FLAG_NORMAL_MAP
|
||||
vertOut.tangentMatrix = vertIn[vert].tangentMatrix;
|
||||
#endif
|
||||
#ifdef FLAG_FOG
|
||||
vertOut.fogDist = vertIn[vert].fogDist;
|
||||
#endif
|
||||
#ifdef FLAG_SHADOWS
|
||||
vertOut.shadowUV[0] = vertIn[vert].shadowUV[0];
|
||||
vertOut.shadowUV[1] = vertIn[vert].shadowUV[1];
|
||||
vertOut.shadowUV[2] = vertIn[vert].shadowUV[2];
|
||||
vertOut.shadowUV[3] = vertIn[vert].shadowUV[3];
|
||||
vertOut.shadowPos = vertIn[vert].shadowPos;
|
||||
#endif
|
||||
#if defined(FLAG_CLIP)
|
||||
gl_ClipDistance[0] = gl_in[vert].gl_ClipDistance[0];
|
||||
#endif
|
||||
EmitVertex();
|
||||
}
|
||||
|
||||
EndPrimitive();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -36,7 +36,7 @@ layout (std140) uniform modelData {
|
||||
|
||||
model_light lights[MAX_LIGHTS];
|
||||
|
||||
float extrudeWidth;
|
||||
float outlineWidth;
|
||||
float fogStart;
|
||||
float fogScale;
|
||||
int buffer_matrix_offset;
|
||||
@@ -113,15 +113,15 @@ out VertexOutput {
|
||||
#ifdef FLAG_FOG
|
||||
float fogDist;
|
||||
#endif
|
||||
#ifdef WORKAROUND_CLIPPING_PLANES
|
||||
#ifdef FLAG_TRANSFORM
|
||||
float notVisible;
|
||||
#endif
|
||||
#endif
|
||||
#ifdef FLAG_SHADOW_MAP
|
||||
#if !defined(GL_ARB_gpu_shader5)
|
||||
float instance;
|
||||
#endif
|
||||
#ifdef FLAG_TRANSFORM
|
||||
// This flag is needed to let the geometry shader know that it doesn't need to apply the
|
||||
// shadow projection to gl_Position
|
||||
float clipModel;
|
||||
#endif
|
||||
#else
|
||||
vec4 position;
|
||||
#endif
|
||||
@@ -152,19 +152,9 @@ void main()
|
||||
vec4 texCoord;
|
||||
mat4 orient = mat4(1.0);
|
||||
mat4 scale = mat4(1.0);
|
||||
#ifdef WORKAROUND_CLIPPING_PLANES
|
||||
#ifdef FLAG_TRANSFORM
|
||||
#ifdef FLAG_TRANSFORM
|
||||
bool clipModel;
|
||||
getModelTransform(orient, clipModel, int(vertModelID), buffer_matrix_offset);
|
||||
vertOut.notVisible = clipModel ? 1.0 : 0.0;
|
||||
#endif
|
||||
#else
|
||||
#ifdef FLAG_TRANSFORM
|
||||
bool clipModel;
|
||||
getModelTransform(orient, clipModel, int(vertModelID), buffer_matrix_offset);
|
||||
#else
|
||||
bool clipModel = false;
|
||||
#endif
|
||||
#endif
|
||||
texCoord = textureMatrix * vertTexCoord;
|
||||
vec4 vertex = vertPosition;
|
||||
@@ -188,9 +178,6 @@ void main()
|
||||
#else
|
||||
gl_Position = projMatrix * position;
|
||||
#endif
|
||||
#ifdef FLAG_NORMAL_EXTRUDE
|
||||
gl_Position.xy += (mat3(projMatrix) * normal.xyz).xy * gl_Position.z * extrudeWidth;
|
||||
#endif
|
||||
#ifdef FLAG_SHADOWS
|
||||
vec4 shadowPos = shadow_mv_matrix * modelMatrix * orient * vertPosition;
|
||||
vertOut.shadowPos = shadow_mv_matrix * modelMatrix * orient * vertPosition;
|
||||
@@ -213,31 +200,28 @@ void main()
|
||||
#ifdef FLAG_FOG
|
||||
vertOut.fogDist = clamp((gl_Position.z - fogStart) * 0.75 * fogScale, 0.0, 1.0);
|
||||
#endif
|
||||
#ifdef WORKAROUND_CLIPPING_PLANES
|
||||
if(use_clip_plane) {
|
||||
gl_ClipDistance[0] = dot(clip_equation, modelMatrix * orient * vertex);
|
||||
} else {
|
||||
gl_ClipDistance[0] = 1.0;
|
||||
}
|
||||
#else
|
||||
#ifdef FLAG_CLIP
|
||||
#ifdef FLAG_TRANSFORM
|
||||
if (clipModel) {
|
||||
gl_ClipDistance[0] = -1.0;
|
||||
} else if(use_clip_plane) {
|
||||
// Clip this model by moving all vertices outside the clip volume
|
||||
gl_Position = vec4(vec3(-2.0), 1.0);
|
||||
}
|
||||
#ifdef FLAG_SHADOW_MAP
|
||||
vertOut.clipModel = clipModel ? 1.0 : 0.0;
|
||||
#endif
|
||||
#endif
|
||||
#ifdef FLAG_CLIP
|
||||
if(use_clip_plane) {
|
||||
gl_ClipDistance[0] = dot(clip_equation, modelMatrix * orient * vertex);
|
||||
} else {
|
||||
gl_ClipDistance[0] = 1.0;
|
||||
}
|
||||
#elif defined(FLAG_TRANSFORM)
|
||||
gl_ClipDistance[0] = clipModel ? -1.0 : 1.0;
|
||||
#endif
|
||||
#endif
|
||||
#ifndef FLAG_SHADOW_MAP
|
||||
#ifndef FLAG_SHADOW_MAP
|
||||
vertOut.position = position;
|
||||
vertOut.normal = normal;
|
||||
vertOut.texCoord = texCoord;
|
||||
#else
|
||||
#else
|
||||
vertOut.normal = normal;
|
||||
vertOut.texCoord = texCoord;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
|
||||
in vec2 fragTexCoord;
|
||||
in vec4 fragColor;
|
||||
|
||||
out vec4 fragOut0;
|
||||
|
||||
uniform bool textured;
|
||||
uniform sampler2DArray baseMap;
|
||||
uniform int baseMapIndex;
|
||||
|
||||
void main() {
|
||||
if (textured) {
|
||||
fragOut0 = texture(baseMap, vec3(fragTexCoord, float(baseMapIndex))) * fragColor;
|
||||
} else {
|
||||
fragOut0 = fragColor;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
|
||||
in vec2 vertPosition;
|
||||
in vec4 vertColor;
|
||||
in vec2 vertTexCoord;
|
||||
|
||||
out vec2 fragTexCoord;
|
||||
out vec4 fragColor;
|
||||
|
||||
uniform mat4 modelViewMatrix;
|
||||
uniform mat4 projMatrix;
|
||||
|
||||
void main()
|
||||
{
|
||||
fragTexCoord = vertTexCoord;
|
||||
fragColor = vertColor;
|
||||
|
||||
gl_Position = projMatrix * modelViewMatrix * vec4(vertPosition, 0.0, 1.0);
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
local exts = {
|
||||
"",
|
||||
".lua",
|
||||
".lc"
|
||||
}
|
||||
|
||||
local function cfileLoader(name)
|
||||
local file = nil
|
||||
|
||||
for i,v in ipairs(exts) do
|
||||
local real_name = name .. v
|
||||
file = cf.openFile(real_name, "r", "data/scripts")
|
||||
|
||||
if (file:isValid()) then
|
||||
name = real_name
|
||||
break;
|
||||
end
|
||||
end
|
||||
|
||||
if (file == nil or not file:isValid()) then
|
||||
return "Module '" .. name .. "' is not known by the CFile system"
|
||||
end
|
||||
|
||||
local content = file:read("*a")
|
||||
file:close()
|
||||
|
||||
local func, err = loadstring(content, name)
|
||||
|
||||
if err then
|
||||
return err
|
||||
end
|
||||
|
||||
return func
|
||||
end
|
||||
|
||||
table.insert(package.loaders, 2, cfileLoader)
|
||||
@@ -45,7 +45,7 @@ $Fog:
|
||||
+Start dist: 10.0
|
||||
+Compl dist: 600.0
|
||||
$AI:
|
||||
+Valid goals: ( "fly to ship" "attack ship" "attack wing" "dock" "waypoints" "waypoints once" "depart" "undock" "stay still" "play dead" "stay near ship" )
|
||||
+Valid goals: ( "fly to ship" "attack ship" "attack wing" "dock" "waypoints" "waypoints once" "depart" "undock" "stay still" "play dead" "play dead (persistent)" "stay near ship" )
|
||||
+Actively Pursues: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
|
||||
+Turrets attack this: YES
|
||||
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "stealth" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
|
||||
@@ -79,7 +79,7 @@ $Fog:
|
||||
+Start dist: 10.0
|
||||
+Compl dist: 500.0
|
||||
$AI:
|
||||
+Valid goals: ( "fly to ship" "dock" "undock" "waypoints" "waypoints once" "stay near ship" "keep safe dist" "stay still" "play dead" )
|
||||
+Valid goals: ( "fly to ship" "dock" "undock" "waypoints" "waypoints once" "stay near ship" "keep safe dist" "stay still" "play dead" "play dead (persistent)" )
|
||||
+Accept Player Orders: YES
|
||||
+Player orders: ( "rearm me" "abort rearm" "depart" )
|
||||
+Auto attacks: YES
|
||||
@@ -104,7 +104,7 @@ $Fog:
|
||||
+Start dist: 10.0
|
||||
+Compl dist: 500.0
|
||||
$AI:
|
||||
+Valid goals: ( "fly to ship" "attack ship" "waypoints" "waypoints once" "depart" "attack subsys" "attack wing" "guard ship" "disable ship" "disarm ship" "attack any" "attack ship class" "ignore ship" "ignore ship (new)" "guard wing" "evade ship" "stay still" "play dead" "stay near ship" "keep safe dist" )
|
||||
+Valid goals: ( "fly to ship" "attack ship" "waypoints" "waypoints once" "depart" "attack subsys" "attack wing" "guard ship" "disable ship" "disarm ship" "attack any" "attack ship class" "ignore ship" "ignore ship (new)" "guard wing" "evade ship" "stay still" "play dead" "play dead (persistent)" "stay near ship" "keep safe dist" )
|
||||
+Accept Player Orders: YES
|
||||
+Player Orders: ( "attack ship" "disable ship" "disarm ship" "guard ship" "ignore ship" "ignore ship (new)" "form on wing" "cover me" "attack any" "depart" "disable subsys" )
|
||||
+Auto attacks: YES
|
||||
@@ -130,7 +130,7 @@ $Fog:
|
||||
+Start dist: 10.0
|
||||
+Compl dist: 500.0
|
||||
$AI:
|
||||
+Valid goals: ( "fly to ship" "attack ship" "waypoints" "waypoints once" "depart" "attack subsys" "attack wing" "guard ship" "disable ship" "disarm ship" "attack any" "attack ship class" "ignore ship" "ignore ship (new)" "guard wing" "evade ship" "stay still" "play dead" "stay near ship" "keep safe dist" "form on wing")
|
||||
+Valid goals: ( "fly to ship" "attack ship" "waypoints" "waypoints once" "depart" "attack subsys" "attack wing" "guard ship" "disable ship" "disarm ship" "attack any" "attack ship class" "ignore ship" "ignore ship (new)" "guard wing" "evade ship" "stay still" "play dead" "play dead (persistent)" "stay near ship" "keep safe dist" "form on wing")
|
||||
+Accept Player Orders: YES
|
||||
+Player Orders: ( "attack ship" "disable ship" "disarm ship" "guard ship" "ignore ship" "ignore ship (new)" "form on wing" "cover me" "attack any" "depart" "disable subsys" )
|
||||
+Auto attacks: YES
|
||||
@@ -157,7 +157,7 @@ $Fog:
|
||||
+Start dist: 10.0
|
||||
+Compl dist: 500.0
|
||||
$AI:
|
||||
+Valid goals: ( "fly to ship" "attack ship" "waypoints" "waypoints once" "depart" "attack subsys" "attack wing" "guard ship" "disable ship" "disarm ship" "attack any" "attack ship class" "ignore ship" "ignore ship (new)" "guard wing" "evade ship" "stay still" "play dead" "stay near ship" "keep safe dist" "form on wing" )
|
||||
+Valid goals: ( "fly to ship" "attack ship" "waypoints" "waypoints once" "depart" "attack subsys" "attack wing" "guard ship" "disable ship" "disarm ship" "attack any" "attack ship class" "ignore ship" "ignore ship (new)" "guard wing" "evade ship" "stay still" "play dead" "play dead (persistent)" "stay near ship" "keep safe dist" "form on wing" )
|
||||
+Accept Player Orders: YES
|
||||
+Player Orders: ( "attack ship" "disable ship" "disarm ship" "guard ship" "ignore ship" "ignore ship (new)" "form on wing" "cover me" "attack any" "depart" "disable subsys" )
|
||||
+Auto attacks: YES
|
||||
@@ -184,7 +184,7 @@ $Fog:
|
||||
+Start dist: 10.0
|
||||
+Compl dist: 500.0
|
||||
$AI:
|
||||
+Valid goals: ( "fly to ship" "attack ship" "waypoints" "waypoints once" "depart" "attack subsys" "attack wing" "guard ship" "disable ship" "disarm ship" "attack any" "attack ship class" "ignore ship" "ignore ship (new)" "guard wing" "evade ship" "stay still" "play dead" "stay near ship" "keep safe dist" "form on wing" )
|
||||
+Valid goals: ( "fly to ship" "attack ship" "waypoints" "waypoints once" "depart" "attack subsys" "attack wing" "guard ship" "disable ship" "disarm ship" "attack any" "attack ship class" "ignore ship" "ignore ship (new)" "guard wing" "evade ship" "stay still" "play dead" "play dead (persistent)" "stay near ship" "keep safe dist" "form on wing" )
|
||||
+Accept Player Orders: YES
|
||||
+Player Orders: ( "attack ship" "disable ship" "disarm ship" "guard ship" "ignore ship" "ignore ship (new)" "form on wing" "cover me" "attack any" "depart" "disable subsys" )
|
||||
+Auto attacks: YES
|
||||
@@ -210,7 +210,7 @@ $Fog:
|
||||
+Start dist: 10.0
|
||||
+Compl dist: 500.0
|
||||
$AI:
|
||||
+Valid goals: ( "fly to ship" "attack ship" "attack wing" "dock" "waypoints" "waypoints once" "depart" "undock" "stay still" "play dead" "stay near ship" )
|
||||
+Valid goals: ( "fly to ship" "attack ship" "attack wing" "dock" "waypoints" "waypoints once" "depart" "undock" "stay still" "play dead" "play dead (persistent)" "stay near ship" )
|
||||
+Accept Player Orders: YES
|
||||
+Player Orders: ( "attack ship" "dock" "depart" )
|
||||
+Auto attacks: YES
|
||||
@@ -238,7 +238,7 @@ $Fog:
|
||||
+Start dist: 10.0
|
||||
+Compl dist: 600.0
|
||||
$AI:
|
||||
+Valid goals: ( "fly to ship" "attack ship" "attack wing" "dock" "waypoints" "waypoints once" "depart" "undock" "stay still" "play dead" "stay near ship" )
|
||||
+Valid goals: ( "fly to ship" "attack ship" "attack wing" "dock" "waypoints" "waypoints once" "depart" "undock" "stay still" "play dead" "play dead (persistent)" "stay near ship" )
|
||||
+Accept Player Orders: YES
|
||||
+Player Orders: ( "attack ship" "dock" "depart" )
|
||||
+Auto attacks: YES
|
||||
@@ -266,7 +266,7 @@ $Fog:
|
||||
+Start dist: 10.0
|
||||
+Compl dist: 600.0
|
||||
$AI:
|
||||
+Valid goals: ( "fly to ship" "attack ship" "attack wing" "dock" "waypoints" "waypoints once" "depart" "undock" "stay still" "play dead" "stay near ship" )
|
||||
+Valid goals: ( "fly to ship" "attack ship" "attack wing" "dock" "waypoints" "waypoints once" "depart" "undock" "stay still" "play dead" "play dead (persistent)" "stay near ship" )
|
||||
+Accept Player Orders: YES
|
||||
+Player Orders: ( "attack ship" "depart" )
|
||||
+Auto attacks: YES
|
||||
@@ -293,7 +293,7 @@ $Fog:
|
||||
+Start dist: 10.0
|
||||
+Compl dist: 600.0
|
||||
$AI:
|
||||
+Valid goals: ( "fly to ship" "attack ship" "attack wing" "dock" "waypoints" "waypoints once" "depart" "undock" "stay still" "play dead" "stay near ship" )
|
||||
+Valid goals: ( "fly to ship" "attack ship" "attack wing" "dock" "waypoints" "waypoints once" "depart" "undock" "stay still" "play dead" "play dead (persistent)" "stay near ship" )
|
||||
+Accept Player Orders: YES
|
||||
+Player Orders: ( "attack ship" "depart" )
|
||||
+Auto attacks: YES
|
||||
@@ -320,7 +320,7 @@ $Fog:
|
||||
+Start dist: 10.0
|
||||
+Compl dist: 600.0
|
||||
$AI:
|
||||
+Valid goals: ( "fly to ship" "attack ship" "attack wing" "dock" "waypoints" "waypoints once" "depart" "undock" "stay still" "play dead" "stay near ship" )
|
||||
+Valid goals: ( "fly to ship" "attack ship" "attack wing" "dock" "waypoints" "waypoints once" "depart" "undock" "stay still" "play dead" "play dead (persistent)" "stay near ship" )
|
||||
+Accept Player Orders: YES
|
||||
+Player Orders: ( "attack ship" "depart" )
|
||||
+Auto attacks: YES
|
||||
@@ -347,7 +347,7 @@ $Fog:
|
||||
+Start dist: 10.0
|
||||
+Compl dist: 600.0
|
||||
$AI:
|
||||
+Valid goals: ( "fly to ship" "attack ship" "attack wing" "dock" "waypoints" "waypoints once" "depart" "undock" "stay still" "play dead" "stay near ship" )
|
||||
+Valid goals: ( "fly to ship" "attack ship" "attack wing" "dock" "waypoints" "waypoints once" "depart" "undock" "stay still" "play dead" "play dead (persistent)" "stay near ship" )
|
||||
+Accept Player Orders: YES
|
||||
+Player Orders: ( "attack ship" "depart" )
|
||||
+Auto attacks: YES
|
||||
@@ -375,7 +375,7 @@ $Fog:
|
||||
+Start dist: 10.0
|
||||
+Compl dist: 750.0
|
||||
$AI:
|
||||
+Valid goals: ( "fly to ship" "attack ship" "attack wing" "waypoints" "waypoints once" "depart" "stay still" "play dead" "stay near ship" )
|
||||
+Valid goals: ( "fly to ship" "attack ship" "attack wing" "waypoints" "waypoints once" "depart" "stay still" "play dead" "play dead (persistent)" "stay near ship" )
|
||||
+Accept Player Orders: YES
|
||||
+Player Orders: ( "depart" )
|
||||
+Auto attacks: YES
|
||||
@@ -403,7 +403,7 @@ $Fog:
|
||||
+Start dist: 10.0
|
||||
+Compl dist: 1000.0
|
||||
$AI:
|
||||
+Valid goals: ( "fly to ship" "attack ship" "attack wing" "waypoints" "waypoints once" "depart" "stay still" "play dead" "stay near ship" )
|
||||
+Valid goals: ( "fly to ship" "attack ship" "attack wing" "waypoints" "waypoints once" "depart" "stay still" "play dead" "play dead (persistent)" "stay near ship" )
|
||||
+Auto attacks: YES
|
||||
+Attempt Broadside: YES
|
||||
+Actively Pursues: ( "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
|
||||
|
||||
@@ -5,7 +5,7 @@ IF(MSVC)
|
||||
set(RES_CONTENT)
|
||||
set(ARRAY_ELEMENTS)
|
||||
|
||||
FOREACH(file ${file_root_def_files_files})
|
||||
FOREACH(file ${default_files_files})
|
||||
set(INPUT_NAME "${CMAKE_CURRENT_SOURCE_DIR}/${file}")
|
||||
SET(OUTPUT "${GENERATED_SOURCE_DIR}/code/${file}")
|
||||
file(RELATIVE_PATH RELATIVE_FILE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/def_files" "${INPUT_NAME}")
|
||||
@@ -39,7 +39,7 @@ else()
|
||||
set(INCLUDE_LIST)
|
||||
set(ARRAY_ELEMENTS)
|
||||
|
||||
FOREACH(file ${file_root_def_files_files})
|
||||
FOREACH(file ${default_files_files})
|
||||
set(INPUT_NAME "${CMAKE_CURRENT_SOURCE_DIR}/${file}")
|
||||
SET(OUTPUT "${GENERATED_SOURCE_DIR}/code/${file}")
|
||||
file(RELATIVE_PATH RELATIVE_FILE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/def_files" "${INPUT_NAME}")
|
||||
@@ -53,8 +53,11 @@ else()
|
||||
file(TO_NATIVE_PATH "${PATH_TYPE}" PATH_TYPE)
|
||||
if (MINGW)
|
||||
# There is a bug in CMake where it thinks MinGW uses forward slashes for paths but we need backslashes for Windows builds
|
||||
string(REPLACE "/" "\\\\" PATH_TYPE "${PATH_TYPE}")
|
||||
string(REPLACE "/" "\\" PATH_TYPE "${PATH_TYPE}")
|
||||
endif()
|
||||
# Properly escape back slashes in strings
|
||||
string(REPLACE "\\" "\\\\" PATH_TYPE "${PATH_TYPE}")
|
||||
|
||||
GET_FILENAME_COMPONENT(FILE_NAME "${RELATIVE_FILE_PATH}" NAME)
|
||||
|
||||
string(MAKE_C_IDENTIFIER "${RELATIVE_FILE_PATH}" FIELD_NAME)
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
|
||||
#include "events.h"
|
||||
|
||||
namespace events {
|
||||
|
||||
util::event<void> EngineUpdate;
|
||||
|
||||
util::event<void> EngineShutdown;
|
||||
|
||||
util::event<void, int, int> GameLeaveState;
|
||||
|
||||
util::event<void, int, int> GameEnterState;
|
||||
|
||||
util::event<void, const char*> GameMissionLoad;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include "utils/event.h"
|
||||
|
||||
namespace events {
|
||||
|
||||
extern util::event<void> EngineUpdate;
|
||||
|
||||
extern util::event<void> EngineShutdown;
|
||||
|
||||
extern util::event<void, int, int> GameLeaveState;
|
||||
|
||||
extern util::event<void, int, int> GameEnterState;
|
||||
|
||||
extern util::event<void, const char*> GameMissionLoad;
|
||||
}
|
||||
+230
-168
@@ -26,18 +26,10 @@
|
||||
#include <cstdlib>
|
||||
|
||||
|
||||
// make use of the LOD checker for tbl/tbm parsing (from weapons.cpp)
|
||||
extern SCP_vector<lod_checker> LOD_checker;
|
||||
|
||||
static SCP_vector<color> LOD_color;
|
||||
|
||||
int Warp_model;
|
||||
int Knossos_warp_ani_used;
|
||||
|
||||
#define WARPHOLE_GROW_TIME (2.35f) // time for warphole to reach max size (also time to shrink to nothing once it begins to shrink)
|
||||
|
||||
#define MAX_FIREBALL_LOD 4
|
||||
|
||||
#define MAX_FIREBALLS 200
|
||||
|
||||
#define MAX_WARP_LOD 0
|
||||
@@ -51,12 +43,8 @@ int fireball_used[MAX_FIREBALL_TYPES];
|
||||
int Num_fireballs = 0;
|
||||
int Num_fireball_types = 0;
|
||||
|
||||
int fireballs_inited = 0;
|
||||
|
||||
int Warp_glow_bitmap = -1;
|
||||
int Warp_ball_bitmap = -1;
|
||||
|
||||
#define FB_INDEX(fb) (fb-Fireballs)
|
||||
bool fireballs_inited = false;
|
||||
bool fireballs_parsed = false;
|
||||
|
||||
/**
|
||||
* Play warp in sound for warp effect
|
||||
@@ -114,12 +102,53 @@ void fireball_play_warphole_close_sound(fireball *fb)
|
||||
snd_play_3d(gamesnd_get_game_sound(sound_index), &fireball_objp->pos, &Eye_position, fireball_objp->radius); // play warp sound effect
|
||||
}
|
||||
|
||||
static void fireball_generate_unique_id(char *unique_id, int buffer_len, int fireball_index)
|
||||
{
|
||||
Assert((fireball_index >= 0) && (fireball_index < MAX_FIREBALL_TYPES));
|
||||
|
||||
switch (fireball_index)
|
||||
{
|
||||
// use sensible names for the fireball.tbl default entries
|
||||
case FIREBALL_EXPLOSION_MEDIUM:
|
||||
strncpy(unique_id, "Medium Explosion", buffer_len);
|
||||
break;
|
||||
|
||||
case FIREBALL_WARP:
|
||||
strncpy(unique_id, "Warp Effect", buffer_len);
|
||||
break;
|
||||
|
||||
case FIREBALL_KNOSSOS:
|
||||
strncpy(unique_id, "Knossos Effect", buffer_len);
|
||||
break;
|
||||
|
||||
case FIREBALL_ASTEROID:
|
||||
strncpy(unique_id, "Asteroid Explosion", buffer_len);
|
||||
break;
|
||||
|
||||
case FIREBALL_EXPLOSION_LARGE1:
|
||||
strncpy(unique_id, "Large Explosion 1", buffer_len);
|
||||
break;
|
||||
|
||||
case FIREBALL_EXPLOSION_LARGE2:
|
||||
strncpy(unique_id, "Large Explosion 2", buffer_len);
|
||||
break;
|
||||
|
||||
// base the id on the index
|
||||
default:
|
||||
snprintf(unique_id, buffer_len, "Custom Fireball %d", fireball_index - NUM_DEFAULT_FIREBALLS + 1);
|
||||
break;
|
||||
}
|
||||
|
||||
// null-terminate
|
||||
unique_id[buffer_len - 1] = '\0';
|
||||
}
|
||||
|
||||
/**
|
||||
* Set default colors for each explosion type (original values from object.cpp)
|
||||
*/
|
||||
static void fireball_set_default_color(int idx)
|
||||
{
|
||||
Assert( (idx >= 0) && (idx < MAX_FIREBALL_TYPES) );
|
||||
Assert((idx >= 0) && (idx < MAX_FIREBALL_TYPES));
|
||||
|
||||
switch (idx)
|
||||
{
|
||||
@@ -153,71 +182,148 @@ static void fireball_set_default_color(int idx)
|
||||
}
|
||||
}
|
||||
|
||||
static void fireball_set_default_warp_attributes(int idx)
|
||||
{
|
||||
Assert((idx >= 0) && (idx < MAX_FIREBALL_TYPES));
|
||||
|
||||
switch (idx)
|
||||
{
|
||||
case FIREBALL_WARP:
|
||||
case FIREBALL_KNOSSOS:
|
||||
strcpy_s(Fireball_info[idx].warp_glow, "warpglow01");
|
||||
strcpy_s(Fireball_info[idx].warp_ball, "warpball01");
|
||||
strcpy_s(Fireball_info[idx].warp_model, "warp.pof");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void fireball_info_clear(fireball_info *fb)
|
||||
{
|
||||
Assert(fb != nullptr);
|
||||
memset(fb, 0, sizeof(fireball_info));
|
||||
|
||||
for (int i = 0; i < MAX_FIREBALL_LOD; ++i)
|
||||
fb->lod[i].bitmap_id = -1;
|
||||
|
||||
fb->warp_glow_bitmap = -1;
|
||||
fb->warp_ball_bitmap = -1;
|
||||
fb->warp_model_id = -1;
|
||||
}
|
||||
|
||||
int fireball_info_lookup(const char *unique_id)
|
||||
{
|
||||
for (int i = 0; i < Num_fireball_types; ++i)
|
||||
if (!stricmp(Fireball_info[i].unique_id, unique_id))
|
||||
return i;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse fireball tbl
|
||||
*
|
||||
* NOTE: we can't be too trusting here so a tbm will only modify the LOD count, not add an entry
|
||||
*/
|
||||
void parse_fireball_tbl(const char *filename)
|
||||
static void parse_fireball_tbl(const char *table_filename)
|
||||
{
|
||||
lod_checker lod_check;
|
||||
color fb_color;
|
||||
|
||||
try
|
||||
{
|
||||
read_file_text(filename, CF_TYPE_TABLES);
|
||||
read_file_text(table_filename, CF_TYPE_TABLES);
|
||||
reset_parse();
|
||||
|
||||
required_string("#Start");
|
||||
|
||||
while (required_string_either("#End", "$Name:")) {
|
||||
memset(&lod_check, 0, sizeof(lod_checker));
|
||||
while (required_string_one_of(3, "#End", "$Name:", "$Unique ID:"))
|
||||
{
|
||||
fireball_info *fi;
|
||||
int existing_idx = -1;
|
||||
char unique_id[NAME_LENGTH];
|
||||
char fireball_filename[MAX_FILENAME_LEN];
|
||||
|
||||
// unique ID, because indexes are unpredictable
|
||||
memset(unique_id, 0, NAME_LENGTH);
|
||||
if (optional_string("$Unique ID:"))
|
||||
stuff_string(unique_id, F_NAME, NAME_LENGTH);
|
||||
|
||||
// base filename
|
||||
required_string("$Name:");
|
||||
stuff_string(lod_check.filename, F_NAME, MAX_FILENAME_LEN);
|
||||
stuff_string(fireball_filename, F_NAME, MAX_FILENAME_LEN);
|
||||
|
||||
lod_check.override = -1;
|
||||
// find out if we are overriding a previous entry;
|
||||
// per precedent, these strings should only be in TBMs
|
||||
// UNLIKE precedent, we can now add fireballs in modular tables, not just replace them
|
||||
if (Parsing_modular_table)
|
||||
{
|
||||
if (optional_string("+Explosion_Medium"))
|
||||
existing_idx = FIREBALL_EXPLOSION_MEDIUM;
|
||||
else if (optional_string("+Warp_Effect"))
|
||||
existing_idx = FIREBALL_WARP;
|
||||
else if (optional_string("+Knossos_Effect"))
|
||||
existing_idx = FIREBALL_KNOSSOS;
|
||||
else if (optional_string("+Asteroid"))
|
||||
existing_idx = FIREBALL_ASTEROID;
|
||||
else if (optional_string("+Explosion_Large1"))
|
||||
existing_idx = FIREBALL_EXPLOSION_LARGE1;
|
||||
else if (optional_string("+Explosion_Large2"))
|
||||
existing_idx = FIREBALL_EXPLOSION_LARGE2;
|
||||
else if (optional_string("+Custom_Fireball"))
|
||||
stuff_int(&existing_idx);
|
||||
|
||||
// these entries should only be in TBMs, and it has to include at least one
|
||||
if (Parsing_modular_table) {
|
||||
if (optional_string("+Explosion_Medium")) {
|
||||
lod_check.override = FIREBALL_EXPLOSION_MEDIUM;
|
||||
}
|
||||
else if (optional_string("+Warp_Effect")) {
|
||||
lod_check.override = FIREBALL_WARP;
|
||||
}
|
||||
else if (optional_string("+Knossos_Effect")) {
|
||||
lod_check.override = FIREBALL_KNOSSOS;
|
||||
}
|
||||
else if (optional_string("+Asteroid")) {
|
||||
lod_check.override = FIREBALL_ASTEROID;
|
||||
}
|
||||
else if (optional_string("+Explosion_Large1")) {
|
||||
lod_check.override = FIREBALL_EXPLOSION_LARGE1;
|
||||
}
|
||||
else if (optional_string("+Explosion_Large2")){
|
||||
lod_check.override = FIREBALL_EXPLOSION_LARGE2;
|
||||
}
|
||||
else {
|
||||
required_string("+Custom_Fireball");
|
||||
stuff_int(&lod_check.override);
|
||||
// we can ALSO override a previous entry by specifying a previously used unique ID
|
||||
// either way will work, but if both are specified, unique ID takes precedence
|
||||
if (strlen(unique_id) > 0)
|
||||
{
|
||||
int temp_idx = fireball_info_lookup(unique_id);
|
||||
if (temp_idx >= 0)
|
||||
existing_idx = temp_idx;
|
||||
}
|
||||
}
|
||||
|
||||
lod_check.num_lods = 1;
|
||||
// now select our entry accordingly...
|
||||
// are we using a previous entry?
|
||||
if (existing_idx >= 0)
|
||||
{
|
||||
fi = &Fireball_info[existing_idx];
|
||||
}
|
||||
// we are creating a new entry, so set some defaults
|
||||
else
|
||||
{
|
||||
// make sure we don't exceed the max
|
||||
if (Num_fireball_types >= MAX_FIREBALL_TYPES)
|
||||
{
|
||||
error_display(0, "Too many fireball entries! Max is %d", MAX_FIREBALL_TYPES);
|
||||
return;
|
||||
}
|
||||
|
||||
// Do we have an LOD num
|
||||
if (optional_string("$LOD:")) {
|
||||
stuff_int(&lod_check.num_lods);
|
||||
fi = &Fireball_info[Num_fireball_types];
|
||||
fireball_info_clear(fi);
|
||||
|
||||
// If the table didn't specify a unique ID, generate one. This will be assigned a few lines later.
|
||||
if (strlen(unique_id) == 0)
|
||||
fireball_generate_unique_id(unique_id, NAME_LENGTH, Num_fireball_types);
|
||||
|
||||
// Set remaining fireball defaults
|
||||
fireball_set_default_color(Num_fireball_types);
|
||||
fireball_set_default_warp_attributes(Num_fireball_types);
|
||||
|
||||
Num_fireball_types++;
|
||||
}
|
||||
|
||||
if (lod_check.num_lods > MAX_FIREBALL_LOD) {
|
||||
lod_check.num_lods = MAX_FIREBALL_LOD;
|
||||
// copy over what we already parsed
|
||||
if (strlen(unique_id) > 0)
|
||||
strcpy_s(fi->unique_id, unique_id);
|
||||
strcpy_s(fi->lod[0].filename, fireball_filename);
|
||||
|
||||
// Do we have a LOD num?
|
||||
if (optional_string("$LOD:"))
|
||||
{
|
||||
stuff_int(&fi->lod_count);
|
||||
|
||||
if (fi->lod_count > MAX_FIREBALL_LOD)
|
||||
fi->lod_count = MAX_FIREBALL_LOD;
|
||||
}
|
||||
|
||||
// check for particular lighting color
|
||||
if (optional_string("$Light color:")) {
|
||||
if (optional_string("$Light color:"))
|
||||
{
|
||||
int r, g, b;
|
||||
|
||||
stuff_int(&r);
|
||||
@@ -228,90 +334,57 @@ void parse_fireball_tbl(const char *filename)
|
||||
CLAMP(g, 0, 255);
|
||||
CLAMP(b, 0, 255);
|
||||
|
||||
gr_init_color(&fb_color, r, g, b);
|
||||
}
|
||||
else {
|
||||
// to keep things simple, we just use 0 alpha to indicate that a default value should be used
|
||||
memset(&fb_color, 0, sizeof(color));
|
||||
fi->exp_color[0] = (r / 255.0f);
|
||||
fi->exp_color[1] = (g / 255.0f);
|
||||
fi->exp_color[2] = (b / 255.0f);
|
||||
}
|
||||
|
||||
// we may use one filename for multiple entries so we'll have to handle dupes post parse
|
||||
LOD_checker.push_back(lod_check);
|
||||
LOD_color.push_back(fb_color);
|
||||
// check for custom warp glow
|
||||
if (optional_string("$Warp glow:"))
|
||||
stuff_string(fi->warp_glow, F_NAME, NAME_LENGTH);
|
||||
|
||||
// check for custom warp ball
|
||||
if (optional_string("$Warp ball:"))
|
||||
stuff_string(fi->warp_ball, F_NAME, NAME_LENGTH);
|
||||
|
||||
// check for custom warp model
|
||||
if (optional_string("$Warp model:"))
|
||||
stuff_string(fi->warp_model, F_NAME, NAME_LENGTH);
|
||||
}
|
||||
|
||||
required_string("#End");
|
||||
}
|
||||
catch (const parse::ParseException& e)
|
||||
{
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", filename, e.what()));
|
||||
mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", table_filename, e.what()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void fireball_parse_tbl()
|
||||
{
|
||||
int i = 0, j;
|
||||
SCP_vector<lod_checker>::iterator lod;
|
||||
|
||||
memset( &Fireball_info, 0, sizeof(fireball_info) * MAX_FIREBALL_TYPES );
|
||||
if (fireballs_parsed)
|
||||
return;
|
||||
|
||||
// every newly parsed fireball_info will get cleared before being added
|
||||
// must do this outside of parse_fireball_tbl because it's called twice
|
||||
Num_fireball_types = 0;
|
||||
|
||||
parse_fireball_tbl("fireball.tbl");
|
||||
|
||||
// look for any modular tables
|
||||
parse_modular_table(NOX("*-fbl.tbm"), parse_fireball_tbl);
|
||||
|
||||
// we've got our list so pass it off for final checking and loading.
|
||||
// we assume that entries in fireball.tbl are in the correct order
|
||||
for (lod = LOD_checker.begin(); lod != LOD_checker.end(); ++lod) {
|
||||
if ( (i < MAX_FIREBALL_TYPES) && (lod->override < 0) ) {
|
||||
strcpy_s( Fireball_info[i].lod[0].filename, lod->filename );
|
||||
Fireball_info[i].lod_count = lod->num_lods;
|
||||
Num_fireball_types++;
|
||||
|
||||
if (LOD_color[i].alpha == 255) {
|
||||
Fireball_info[i].exp_color[0] = (LOD_color[i].red / 255.0f);
|
||||
Fireball_info[i].exp_color[1] = (LOD_color[i].green / 255.0f);
|
||||
Fireball_info[i].exp_color[2] = (LOD_color[i].blue / 255.0f);
|
||||
} else {
|
||||
fireball_set_default_color(i);
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
// having to do this twice is less than optimal, but less error prone too.
|
||||
// this handles (and should only have to handle) TBM related entries
|
||||
i = 0;
|
||||
for (lod = LOD_checker.begin(); lod != LOD_checker.end(); ++lod) {
|
||||
// try entry replacement
|
||||
if ( (lod->override >= 0) && (lod->override < Num_fireball_types) ) {
|
||||
strcpy_s( Fireball_info[lod->override].lod[0].filename, lod->filename );
|
||||
Fireball_info[lod->override].lod_count = lod->num_lods;
|
||||
|
||||
if (LOD_color[i].alpha == 255) {
|
||||
Fireball_info[lod->override].exp_color[0] = (LOD_color[i].red / 255.0f);
|
||||
Fireball_info[lod->override].exp_color[1] = (LOD_color[i].green / 255.0f);
|
||||
Fireball_info[lod->override].exp_color[2] = (LOD_color[i].blue / 255.0f);
|
||||
} else {
|
||||
fireball_set_default_color(lod->override);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// fill in extra LOD filenames
|
||||
for (i = 0; i < Num_fireball_types; i++) {
|
||||
for (j = 1; j < Fireball_info[i].lod_count; j++) {
|
||||
for (int i = 0; i < Num_fireball_types; i++)
|
||||
{
|
||||
for (int j = 1; j < Fireball_info[i].lod_count; j++)
|
||||
sprintf( Fireball_info[i].lod[j].filename, "%s_%d", Fireball_info[i].lod[0].filename, j);
|
||||
}
|
||||
}
|
||||
|
||||
// done
|
||||
LOD_checker.clear();
|
||||
fireballs_parsed = true;
|
||||
}
|
||||
|
||||
|
||||
void fireball_load_data()
|
||||
{
|
||||
int i, idx;
|
||||
@@ -330,13 +403,20 @@ void fireball_load_data()
|
||||
Error(LOCATION, "Could not load %s anim file\n", fd->lod[idx].filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( Warp_glow_bitmap == -1 ) {
|
||||
Warp_glow_bitmap = bm_load( NOX("warpglow01") );
|
||||
}
|
||||
if ( Warp_ball_bitmap == -1 ) {
|
||||
Warp_ball_bitmap = bm_load( NOX("warpball01") );
|
||||
if (strlen(fd->warp_glow) > 0) {
|
||||
mprintf(("Loading warp glow '%s'\n", fd->warp_glow));
|
||||
fd->warp_glow_bitmap = bm_load(fd->warp_glow);
|
||||
} else {
|
||||
fd->warp_glow_bitmap = -1;
|
||||
}
|
||||
|
||||
if (strlen(fd->warp_ball) > 0) {
|
||||
mprintf(("Loading warp ball '%s'\n", fd->warp_ball));
|
||||
fd->warp_ball_bitmap = bm_load(fd->warp_ball);
|
||||
} else {
|
||||
fd->warp_ball_bitmap = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -346,11 +426,11 @@ void fireball_init()
|
||||
int i;
|
||||
|
||||
if ( !fireballs_inited ) {
|
||||
fireballs_inited = 1;
|
||||
|
||||
// Do all the processing that happens only once
|
||||
fireball_parse_tbl();
|
||||
fireball_load_data();
|
||||
|
||||
fireballs_inited = true;
|
||||
}
|
||||
|
||||
// Reset everything between levels
|
||||
@@ -361,17 +441,6 @@ void fireball_init()
|
||||
|
||||
// Goober5000 - reset Knossos warp flag
|
||||
Knossos_warp_ani_used = 0;
|
||||
|
||||
mprintf(("Loading warp model\n"));
|
||||
Warp_model = -1;
|
||||
|
||||
// Goober5000 - check for existence of file before trying to load it
|
||||
if (cf_exists_full("warp.pof", CF_TYPE_MODELS))
|
||||
{
|
||||
Warp_model = model_load("warp.pof", 0, NULL, 0);
|
||||
}
|
||||
|
||||
mprintf((" %d\n", Warp_model));
|
||||
}
|
||||
|
||||
MONITOR( NumFireballsRend )
|
||||
@@ -543,7 +612,7 @@ void fireball_maybe_play_warp_close_sound(fireball *fb)
|
||||
|
||||
life_left = fb->total_time - fb->time_elapsed;
|
||||
|
||||
if ( life_left < WARPHOLE_GROW_TIME ) {
|
||||
if ( life_left < fb->warp_close_duration ) {
|
||||
fireball_play_warphole_close_sound(fb);
|
||||
fb->flags |= FBF_WARP_CLOSE_SOUND_PLAYED;
|
||||
}
|
||||
@@ -696,7 +765,7 @@ int fireball_get_lod(vec3d *pos, fireball_info *fd, float size)
|
||||
/**
|
||||
* Create a fireball, return object index.
|
||||
*/
|
||||
int fireball_create( vec3d * pos, int fireball_type, int render_type, int parent_obj, float size, int reverse, vec3d *velocity, float warp_lifetime, int ship_class, matrix *orient_override, int low_res, int extra_flags, gamesnd_id warp_open_sound, gamesnd_id warp_close_sound)
|
||||
int fireball_create(vec3d *pos, int fireball_type, int render_type, int parent_obj, float size, bool reverse, vec3d *velocity, float warp_lifetime, int ship_class, matrix *orient_override, int low_res, int extra_flags, gamesnd_id warp_open_sound, gamesnd_id warp_close_sound, float warp_open_duration, float warp_close_duration)
|
||||
{
|
||||
int n, objnum, fb_lod;
|
||||
object *obj;
|
||||
@@ -757,6 +826,8 @@ int fireball_create( vec3d * pos, int fireball_type, int render_type, int parent
|
||||
fb->flags = extra_flags;
|
||||
fb->warp_open_sound_index = warp_open_sound;
|
||||
fb->warp_close_sound_index = warp_close_sound;
|
||||
fb->warp_open_duration = (warp_open_duration < 0.0f) ? WARPHOLE_GROW_TIME : warp_open_duration;
|
||||
fb->warp_close_duration = (warp_close_duration < 0.0f) ? WARPHOLE_GROW_TIME : warp_close_duration;
|
||||
|
||||
matrix orient;
|
||||
if(orient_override != NULL){
|
||||
@@ -861,9 +932,9 @@ void fireballs_page_in()
|
||||
fireball_info *fd;
|
||||
|
||||
for ( i = 0; i < Num_fireball_types; i++ ) {
|
||||
if((i < NUM_DEFAULT_FIREBALLS) || fireball_used[i]){
|
||||
fd = &Fireball_info[i];
|
||||
fd = &Fireball_info[i];
|
||||
|
||||
if((i < NUM_DEFAULT_FIREBALLS) || fireball_used[i]) {
|
||||
// if this is a Knossos ani, only load if Knossos_warp_ani_used is true
|
||||
if ( (i == FIREBALL_KNOSSOS) && !Knossos_warp_ani_used)
|
||||
continue;
|
||||
@@ -876,10 +947,19 @@ void fireballs_page_in()
|
||||
bm_page_in_texture( fd->lod[idx].bitmap_id, fd->lod[idx].num_frames );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bm_page_in_texture( Warp_glow_bitmap );
|
||||
bm_page_in_texture( Warp_ball_bitmap );
|
||||
// page in glow and ball bitmaps, if we have any
|
||||
bm_page_in_texture(fd->warp_glow_bitmap);
|
||||
bm_page_in_texture(fd->warp_ball_bitmap);
|
||||
|
||||
// load the warp model, if we have one
|
||||
if (strlen(fd->warp_model) > 0 && cf_exists_full(fd->warp_model, CF_TYPE_MODELS)) {
|
||||
mprintf(("Loading warp model '%s'\n", fd->warp_model));
|
||||
fd->warp_model_id = model_load(fd->warp_model, 0, nullptr, 0);
|
||||
} else {
|
||||
fd->warp_model_id = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void fireball_get_color(int idx, float *red, float *green, float *blue)
|
||||
@@ -941,30 +1021,23 @@ int fireball_asteroid_explosion_type(asteroid_info *aip)
|
||||
return index;
|
||||
}
|
||||
|
||||
float fireball_wormhole_intensity( object *obj )
|
||||
float fireball_wormhole_intensity(fireball *fb)
|
||||
{
|
||||
int num, objnum;
|
||||
fireball *fb;
|
||||
|
||||
num = obj->instance;
|
||||
objnum = OBJ_INDEX(obj);
|
||||
Assertion( Fireballs[num].objnum == objnum, "Basic sanity check. Fireballs[num].objnum (%d) should == objnum (%d)", Fireballs[num].objnum, objnum );
|
||||
|
||||
fb = &Fireballs[num];
|
||||
|
||||
float t = fb->time_elapsed;
|
||||
float rad;
|
||||
|
||||
if ( t < WARPHOLE_GROW_TIME ) {
|
||||
rad = (float)pow(t/WARPHOLE_GROW_TIME,0.4f);
|
||||
} else if ( t < fb->total_time - WARPHOLE_GROW_TIME ) {
|
||||
rad = 1;
|
||||
if ( t < fb->warp_open_duration ) {
|
||||
rad = (float)pow(t / fb->warp_open_duration, 0.4f);
|
||||
} else if ( t < fb->total_time - fb->warp_close_duration ) {
|
||||
rad = 1.0f;
|
||||
} else {
|
||||
rad = (float)pow((fb->total_time - t)/WARPHOLE_GROW_TIME,0.4f);
|
||||
rad = (float)pow((fb->total_time - t) / fb->warp_close_duration, 0.4f);
|
||||
}
|
||||
return rad;
|
||||
}
|
||||
|
||||
extern void warpin_queue_render(model_draw_list *scene, object *obj, matrix *orient, vec3d *pos, int texture_bitmap_num, float radius, float life_percent, float max_radius, bool warp_3d, int warp_glow_bitmap, int warp_ball_bitmap, int warp_model_id);
|
||||
|
||||
void fireball_render(object* obj, model_draw_list *scene)
|
||||
{
|
||||
int num;
|
||||
@@ -996,21 +1069,10 @@ void fireball_render(object* obj, model_draw_list *scene)
|
||||
|
||||
case FIREBALL_WARP_EFFECT: {
|
||||
float percent_life = fb->time_elapsed / fb->total_time;
|
||||
float rad = obj->radius * fireball_wormhole_intensity(fb);
|
||||
|
||||
float rad;
|
||||
|
||||
// Code to make effect grow/shrink.
|
||||
float t = fb->time_elapsed;
|
||||
|
||||
if ( t < WARPHOLE_GROW_TIME ) {
|
||||
rad = (float)pow(t/WARPHOLE_GROW_TIME,0.4f)*obj->radius;
|
||||
} else if ( t < fb->total_time - WARPHOLE_GROW_TIME ) {
|
||||
rad = obj->radius;
|
||||
} else {
|
||||
rad = (float)pow((fb->total_time - t)/WARPHOLE_GROW_TIME,0.4f)*obj->radius;
|
||||
}
|
||||
|
||||
warpin_queue_render(scene, obj, &obj->orient, &obj->pos, Fireballs[num].current_bitmap, rad, percent_life, obj->radius, (Fireballs[num].flags & FBF_WARP_3D) );
|
||||
fireball_info *fi = &Fireball_info[fb->fireball_info_index];
|
||||
warpin_queue_render(scene, obj, &obj->orient, &obj->pos, fb->current_bitmap, rad, percent_life, obj->radius, (fb->flags & FBF_WARP_3D) != 0, fi->warp_glow_bitmap, fi->warp_ball_bitmap, fi->warp_model_id);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
+31
-17
@@ -36,10 +36,11 @@ class asteroid_info;
|
||||
#define MAX_FIREBALL_TYPES 32 // The maximum number of fireballs that can be defined
|
||||
#define NUM_DEFAULT_FIREBALLS 6
|
||||
|
||||
#define MAX_FIREBALL_LOD 4
|
||||
|
||||
#define FIREBALL_NUM_LARGE_EXPLOSIONS 2
|
||||
|
||||
extern int fireball_used[MAX_FIREBALL_TYPES];
|
||||
extern int Num_fireball_types;
|
||||
|
||||
// all this moved here by Goober5000 because it makes more sense in the H file
|
||||
typedef struct fireball_lod {
|
||||
@@ -50,11 +51,22 @@ typedef struct fireball_lod {
|
||||
} fireball_lod;
|
||||
|
||||
typedef struct fireball_info {
|
||||
char unique_id[NAME_LENGTH];
|
||||
int lod_count;
|
||||
float exp_color[3];
|
||||
fireball_lod lod[4];
|
||||
fireball_lod lod[MAX_FIREBALL_LOD];
|
||||
float exp_color[3]; // red, green, blue
|
||||
|
||||
char warp_glow[NAME_LENGTH];
|
||||
int warp_glow_bitmap;
|
||||
char warp_ball[NAME_LENGTH];
|
||||
int warp_ball_bitmap;
|
||||
char warp_model[NAME_LENGTH];
|
||||
int warp_model_id;
|
||||
} fireball_info;
|
||||
|
||||
extern fireball_info Fireball_info[MAX_FIREBALL_TYPES];
|
||||
extern int Num_fireball_types;
|
||||
|
||||
// flag values for fireball struct flags member
|
||||
#define FBF_WARP_CLOSE_SOUND_PLAYED (1<<0)
|
||||
#define FBF_WARP_CAPITAL_SIZE (1<<1)
|
||||
@@ -72,8 +84,12 @@ typedef struct fireball {
|
||||
char lod; // current LOD
|
||||
float time_elapsed; // in seconds
|
||||
float total_time; // total lifetime of animation in seconds
|
||||
gamesnd_id warp_open_sound_index; // for warp-effect - Goober5000
|
||||
gamesnd_id warp_close_sound_index; // for warp-effect - Goober5000
|
||||
|
||||
// for warp-effect - Goober5000
|
||||
gamesnd_id warp_open_sound_index;
|
||||
gamesnd_id warp_close_sound_index;
|
||||
float warp_open_duration;
|
||||
float warp_close_duration;
|
||||
} fireball;
|
||||
// end move
|
||||
|
||||
@@ -82,11 +98,16 @@ void fireball_render(object* obj, model_draw_list *scene);
|
||||
void fireball_delete( object * obj );
|
||||
void fireball_process_post(object * obj, float frame_time);
|
||||
|
||||
// reversed is for warp_in/out effects
|
||||
// Velocity: If not NULL, the fireball will move at a constant velocity.
|
||||
// This does not load all the data, just the filenames and such. Only used by FRED.
|
||||
void fireball_parse_tbl();
|
||||
|
||||
int fireball_info_lookup(const char *unique_id);
|
||||
|
||||
// reverse is for warp_in/out effects
|
||||
// velocity: If not NULL, the fireball will move at a constant velocity.
|
||||
// warp_lifetime: If warp_lifetime > 0.0f then makes the explosion loop so it lasts this long. Only works for warp effect
|
||||
int fireball_create(vec3d *pos, int fireball_type, int render_type, int parent_obj, float size, int reversed=0, vec3d *velocity=NULL, float warp_lifetime=0.0f, int ship_class=-1, matrix *orient=NULL, int low_res=0, int extra_flags=0, gamesnd_id warp_open_sound=gamesnd_id(), gamesnd_id warp_close_sound=gamesnd_id());
|
||||
void fireball_render_plane(int plane);
|
||||
int fireball_create(vec3d *pos, int fireball_type, int render_type, int parent_obj, float size, bool reverse=false, vec3d *velocity=nullptr, float warp_lifetime=0.0f, int ship_class=-1, matrix *orient=nullptr, int low_res=0, int extra_flags=0, gamesnd_id warp_open_sound=gamesnd_id(), gamesnd_id warp_close_sound=gamesnd_id(), float warp_open_duration=-1.0f, float warp_close_duration=-1.0f);
|
||||
|
||||
void fireball_close();
|
||||
|
||||
// Returns 1 if you can remove this fireball
|
||||
@@ -111,14 +132,7 @@ int fireball_ship_explosion_type(ship_info *sip);
|
||||
int fireball_asteroid_explosion_type(asteroid_info *aip);
|
||||
|
||||
// returns the intensity of a wormhole
|
||||
float fireball_wormhole_intensity( object *obj );
|
||||
|
||||
// internal function to draw warp grid.
|
||||
extern void warpin_render(object *obj, matrix *orient, vec3d *pos, int texture_bitmap_num, float radius, float life_percent, float max_radius, int warp_3d = 0 );
|
||||
|
||||
extern void warpin_queue_render(model_draw_list *scene, object *obj, matrix *orient, vec3d *pos, int texture_bitmap_num, float radius, float life_percent, float max_radius, int warp_3d);
|
||||
|
||||
extern int Warp_model;
|
||||
float fireball_wormhole_intensity( fireball *fb );
|
||||
|
||||
// Goober5000
|
||||
extern int Knossos_warp_ani_used;
|
||||
|
||||
@@ -21,10 +21,6 @@
|
||||
#include "render/batching.h"
|
||||
#include "ship/ship.h"
|
||||
|
||||
extern int Warp_model;
|
||||
extern int Warp_glow_bitmap;
|
||||
extern int Warp_ball_bitmap;
|
||||
|
||||
void warpin_batch_draw_face( int texture, vertex *v1, vertex *v2, vertex *v3 )
|
||||
{
|
||||
vec3d norm;
|
||||
@@ -45,7 +41,7 @@ void warpin_batch_draw_face( int texture, vertex *v1, vertex *v2, vertex *v3 )
|
||||
batching_add_tri(texture, vertlist); // TODO render as emissive
|
||||
}
|
||||
|
||||
void warpin_queue_render(model_draw_list *scene, object *obj, matrix *orient, vec3d *pos, int texture_bitmap_num, float radius, float life_percent, float max_radius, int warp_3d)
|
||||
void warpin_queue_render(model_draw_list *scene, object *obj, matrix *orient, vec3d *pos, int texture_bitmap_num, float radius, float life_percent, float max_radius, bool warp_3d, int warp_glow_bitmap, int warp_ball_bitmap, int warp_model_id)
|
||||
{
|
||||
vec3d center;
|
||||
vec3d vecs[5];
|
||||
@@ -60,7 +56,7 @@ void warpin_queue_render(model_draw_list *scene, object *obj, matrix *orient, ve
|
||||
|
||||
verts[1] = verts[2] = verts[3] = verts[4] = verts[0];
|
||||
|
||||
if (Warp_glow_bitmap >= 0) {
|
||||
if (warp_glow_bitmap >= 0) {
|
||||
float r = radius;
|
||||
bool render_it = true;
|
||||
|
||||
@@ -99,12 +95,12 @@ void warpin_queue_render(model_draw_list *scene, object *obj, matrix *orient, ve
|
||||
|
||||
float alpha = (The_mission.flags[Mission::Mission_Flags::Fullneb]) ? (1.0f - neb2_get_fog_intensity(obj)) : 1.0f;
|
||||
|
||||
//batch_add_bitmap(Warp_glow_bitmap, TMAP_FLAG_TEXTURED | TMAP_HTL_3D_UNLIT, &verts[4], 0, r, alpha);
|
||||
batching_add_bitmap(Warp_glow_bitmap, &verts[4], 0, r, alpha);
|
||||
//batch_add_bitmap(warp_glow_bitmap, TMAP_FLAG_TEXTURED | TMAP_HTL_3D_UNLIT, &verts[4], 0, r, alpha);
|
||||
batching_add_bitmap(warp_glow_bitmap, &verts[4], 0, r, alpha);
|
||||
}
|
||||
}
|
||||
|
||||
if ( (Warp_model >= 0) && (warp_3d || Cmdline_3dwarp) ) {
|
||||
if ( (warp_model_id >= 0) && (warp_3d || Cmdline_3dwarp) ) {
|
||||
model_render_params render_info;
|
||||
|
||||
float scale = radius / 25.0f;
|
||||
@@ -119,7 +115,7 @@ void warpin_queue_render(model_draw_list *scene, object *obj, matrix *orient, ve
|
||||
render_info.set_detail_level_lock((int)(dist / (radius * 10.0f)));
|
||||
render_info.set_flags(MR_NO_LIGHTING | MR_NORMAL | MR_NO_FOGGING | MR_NO_CULL | MR_NO_BATCH);
|
||||
|
||||
model_render_queue( &render_info, scene, Warp_model, orient, pos);
|
||||
model_render_queue( &render_info, scene, warp_model_id, orient, pos);
|
||||
} else {
|
||||
float Grid_depth = radius/2.5f;
|
||||
|
||||
@@ -171,14 +167,14 @@ void warpin_queue_render(model_draw_list *scene, object *obj, matrix *orient, ve
|
||||
warpin_batch_draw_face( texture_bitmap_num, &verts[0], &verts[3], &verts[4] );
|
||||
}
|
||||
|
||||
if (Warp_ball_bitmap > -1 && Cmdline_warp_flash == 1) {
|
||||
if (warp_ball_bitmap >= 0 && Cmdline_warp_flash) {
|
||||
flash_ball warp_ball(20, .1f,.25f, &orient->vec.fvec, pos, 4.0f, 0.5f);
|
||||
|
||||
float adg = (2.0f * life_percent) - 1.0f;
|
||||
float pct = (powf(adg, 4.0f) - powf(adg, 128.0f)) * 4.0f;
|
||||
|
||||
if (pct > 0.00001f) {
|
||||
warp_ball.render(Warp_ball_bitmap, max_radius * pct * 0.5f, adg * adg, adg * adg * 6.0f);
|
||||
warp_ball.render(warp_ball_bitmap, max_radius * pct * 0.5f, adg * adg, adg * adg * 6.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1101,7 +1101,7 @@ void fs2netd_store_stats()
|
||||
if (Duplicate_login_detected) {
|
||||
Duplicate_login_detected = false;
|
||||
multi_display_chat_msg( XSTR("<Duplicate login detected - stats have been tossed>", 1582), 0, 0 );
|
||||
ml_string( XSTR("<Duplicate login detected - stats have been tossed>", 1583) );
|
||||
ml_string( XSTR("<Duplicate login detected - stats have been tossed>", 1582) );
|
||||
fs2netd_store_stats_results();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -483,7 +483,7 @@ void parse_helptbl(const char *filename)
|
||||
break;
|
||||
case 4: // $end
|
||||
default:
|
||||
Assertion(false, "This should never happen.\n");
|
||||
UNREACHABLE("This should never happen.\n");
|
||||
break;
|
||||
}
|
||||
} // end while
|
||||
|
||||
@@ -109,38 +109,6 @@ static int Gameplay_help_inited = 0;
|
||||
|
||||
static int Current_help_page;
|
||||
|
||||
// generate a line for the on-line help for a control item with specified id
|
||||
// input: id => index for control item within Control_config[]
|
||||
// buf => buffer with enough space to hold ouput string
|
||||
const char *gameplay_help_control_text(int id, char *buf)
|
||||
{
|
||||
int has_key=0, has_joy=0;
|
||||
config_item *ci;
|
||||
|
||||
ci = &Control_config[id];
|
||||
|
||||
if ( ci->key_id >= 0 ) {
|
||||
strcpy(buf, textify_scancode(ci->key_id));
|
||||
has_key=1;
|
||||
}
|
||||
|
||||
if ( ci->joy_id >= 0 ) {
|
||||
if ( has_key ) {
|
||||
strcat(buf, XSTR( ", ", 129));
|
||||
}
|
||||
strcat(buf, Joy_button_text[ci->joy_id]);
|
||||
has_joy=1;
|
||||
}
|
||||
|
||||
if ( !has_key && !has_joy ) {
|
||||
strcpy(buf, XSTR( "no binding", 130));
|
||||
}
|
||||
|
||||
strcat(buf, XSTR( " - ", 131));
|
||||
strcat(buf, ci->text);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
void gameplay_help_blit_control_line(int x, int y, int id)
|
||||
{
|
||||
@@ -824,20 +792,3 @@ void gameplay_help_do_frame(float /*frametime*/)
|
||||
gameplay_help_draw_text();
|
||||
gr_flip();
|
||||
}
|
||||
|
||||
|
||||
// called once when leaving the gameplay help state
|
||||
void gameplay_help_close()
|
||||
{
|
||||
if ( Gameplay_help_inited ) {
|
||||
if (Background_bitmap >= 0) {
|
||||
bm_release(Background_bitmap);
|
||||
}
|
||||
|
||||
Ui_window.destroy();
|
||||
common_free_interface_palette(); // restore game palette
|
||||
game_flush();
|
||||
}
|
||||
|
||||
Gameplay_help_inited = 0;
|
||||
}
|
||||
@@ -13,7 +13,6 @@
|
||||
#define __GAMEPLAY_HELP_H__
|
||||
|
||||
void gameplay_help_init();
|
||||
void gameplay_help_close();
|
||||
void gameplay_help_do_frame(float frametime);
|
||||
|
||||
#endif
|
||||
@@ -350,29 +350,6 @@ void gameseq_pop_state()
|
||||
|
||||
}
|
||||
|
||||
// gameseq_pop_and_discard_state() is used to remove a state that was pushed onto the stack, but
|
||||
// will never need to be popped. An example of this is entering a state that may require returning
|
||||
// to the previous state (then you would call gameseq_pop_state). Or you may simply continue to
|
||||
// another part of the game, to avoid filling up the stack with states that may never be popped, you
|
||||
// call this function to discard the top of the gs.
|
||||
//
|
||||
|
||||
void gameseq_pop_and_discard_state()
|
||||
{
|
||||
if (gs_current_stack > 0 ) {
|
||||
gs_current_stack--;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the last state pushed on stack
|
||||
int gameseq_get_pushed_state()
|
||||
{
|
||||
if (gs_current_stack >= 1) {
|
||||
return gs[gs_current_stack-1].current_state;
|
||||
} else
|
||||
return -1;
|
||||
}
|
||||
|
||||
// gameseq_process_events gets called every time through high level loops
|
||||
// (i.e. game loops, main menu loop). Function is responsible for pulling
|
||||
// game sequence events off the queue and changing the state when necessary.
|
||||
@@ -404,9 +381,9 @@ int gameseq_process_events()
|
||||
state_reentry--;
|
||||
|
||||
return gs[gs_current_stack].current_state;
|
||||
}
|
||||
}
|
||||
|
||||
int gameseq_get_event_idx(char *s)
|
||||
int gameseq_get_event_idx(const char* s)
|
||||
{
|
||||
for(int i = 0; i < Num_gs_event_text; i++)
|
||||
{
|
||||
@@ -418,7 +395,7 @@ int gameseq_get_event_idx(char *s)
|
||||
return -1;
|
||||
}
|
||||
|
||||
int gameseq_get_state_idx(char *s)
|
||||
int gameseq_get_state_idx(const char* s)
|
||||
{
|
||||
for(int i = 0; i < Num_gs_state_text; i++)
|
||||
{
|
||||
|
||||
@@ -181,11 +181,8 @@ int gameseq_get_event( void );
|
||||
void gameseq_set_state(int new_state, int override = 0);
|
||||
void gameseq_push_state( int new_state );
|
||||
void gameseq_pop_state( void );
|
||||
int gameseq_get_pushed_state();
|
||||
int gameseq_get_depth();
|
||||
int gameseq_get_previous_state();
|
||||
void gameseq_pop_and_discard_state(void);
|
||||
|
||||
|
||||
// Called by the sequencing code when things happen.
|
||||
void game_process_event(int current_state, int event);
|
||||
@@ -197,8 +194,8 @@ void game_do_state(int current_state);
|
||||
bool GameState_Stack_Valid();
|
||||
|
||||
//WMC
|
||||
int gameseq_get_event_idx(char *s);
|
||||
int gameseq_get_state_idx(char *s);
|
||||
int gameseq_get_event_idx(const char* s);
|
||||
int gameseq_get_state_idx(const char* s);
|
||||
|
||||
//zookeeper
|
||||
int gameseq_get_state_idx(int state);
|
||||
|
||||
@@ -57,11 +57,8 @@ SOUNDTRACK_INFO Soundtracks[MAX_SOUNDTRACKS];
|
||||
int Num_soundtracks;
|
||||
int Current_soundtrack_num; // Active soundtrack for the current mission.. index into Soundtracks[]
|
||||
|
||||
#define PATTERN_DELAY 1000 // in ms
|
||||
int Current_pattern = -1; // currently playing part of track
|
||||
int Pending_pattern = -1;
|
||||
int Pattern_timer_id = 0;
|
||||
int Current_nrml = SONG_NRML_1;
|
||||
|
||||
// File Globals
|
||||
static int Num_enemy_arrivals;
|
||||
@@ -240,7 +237,6 @@ static int Event_music_begun = FALSE;
|
||||
|
||||
// forward function declarations
|
||||
int hostile_ships_present();
|
||||
int hostile_ships_to_arrive();
|
||||
extern int hud_target_invalid_awacs(object *objp);
|
||||
|
||||
// Holds file names of spooled music that is played at menus, briefings, credits etc.
|
||||
@@ -544,7 +540,6 @@ void event_music_level_init(int force_soundtrack)
|
||||
return;
|
||||
|
||||
Current_pattern = -1;
|
||||
Current_nrml = SONG_NRML_1;
|
||||
|
||||
if (Event_music_inited == FALSE)
|
||||
return;
|
||||
@@ -556,15 +551,6 @@ void event_music_level_init(int force_soundtrack)
|
||||
if (Current_soundtrack_num < 0)
|
||||
{
|
||||
return;
|
||||
/*
|
||||
// okay, assign a random soundtrack if one exists
|
||||
if ( Num_soundtracks > 0 ) {
|
||||
Current_soundtrack_num = rand()%Num_soundtracks;
|
||||
nprintf(("EVENTMUSIC", "EVENTMUSIC ==> Picking random event music soundtrack: %s\n", Soundtracks[Current_soundtrack_num].name));
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
Assert(Current_soundtrack_num >= 0 && Current_soundtrack_num < Num_soundtracks);
|
||||
@@ -631,9 +617,7 @@ void event_music_level_init(int force_soundtrack)
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
// event_music_first_pattern()
|
||||
//
|
||||
// Picks the first pattern to play, based on whether the battle has started. Delay start
|
||||
// by PATTERN_DELAY
|
||||
//
|
||||
// Picks the first pattern to play, based on whether the battle has started.
|
||||
void event_music_first_pattern()
|
||||
{
|
||||
if ( Event_music_inited == FALSE ) {
|
||||
@@ -1520,59 +1504,6 @@ void event_music_start_default()
|
||||
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
// event_music_pause()
|
||||
//
|
||||
// Stop any playing pattern, but don't rewind.
|
||||
//
|
||||
void event_music_pause()
|
||||
{
|
||||
if ( Event_music_enabled == FALSE ) {
|
||||
nprintf(("EVENTMUSIC", "EVENTMUSIC ==> Requested a song switch when event music is not enabled\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
if ( Event_music_level_inited == FALSE ) {
|
||||
nprintf(("EVENTMUSIC", "EVENTMUSIC ==> Event music is not enabled\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (Current_pattern == -1)
|
||||
return;
|
||||
|
||||
Assert( Current_pattern >= 0 && Current_pattern < MAX_PATTERNS );
|
||||
if ( audiostream_is_playing(Patterns[Current_pattern].handle) ) {
|
||||
audiostream_stop(Patterns[Current_pattern].handle, 0); // stop current and don't rewind
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
// event_music_unpause()
|
||||
//
|
||||
// Start the Current_pattern if it is paused.
|
||||
//
|
||||
void event_music_unpause()
|
||||
{
|
||||
if ( Event_music_enabled == FALSE ) {
|
||||
nprintf(("EVENTMUSIC", "EVENTMUSIC ==> Requested a song switch when event music is not enabled\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
if ( Event_music_level_inited == FALSE ) {
|
||||
nprintf(("EVENTMUSIC", "EVENTMUSIC ==> Event music is not enabled\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (Current_pattern == -1)
|
||||
return;
|
||||
|
||||
Assert( Current_pattern >= 0 && Current_pattern < MAX_PATTERNS );
|
||||
if ( audiostream_is_paused(Patterns[Current_pattern].handle) == TRUE ) {
|
||||
audiostream_play(Patterns[Current_pattern].handle, (Master_event_music_volume * aav_music_volume), 0); // no looping
|
||||
audiostream_set_sample_cutoff(Patterns[Current_pattern].handle, fl2i(Patterns[Current_pattern].num_measures * Patterns[Current_pattern].samples_per_measure) );
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
// event_music_set_volume_all()
|
||||
//
|
||||
@@ -1628,33 +1559,6 @@ int hostile_ships_present()
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// hostile_ships_to_arrive()
|
||||
//
|
||||
// Determine if there are any non-friendly ships yet to arrive
|
||||
//
|
||||
// NOTE: neutral ships are considered hostile for the purpose of event music
|
||||
//
|
||||
int hostile_ships_to_arrive()
|
||||
{
|
||||
p_object *p_objp;
|
||||
|
||||
for (p_objp = GET_FIRST(&Ship_arrival_list); p_objp != END_OF_LIST(&Ship_arrival_list); p_objp = GET_NEXT(p_objp))
|
||||
{
|
||||
// check if ship can arrive
|
||||
if (p_objp->flags[Mission::Parse_Object_Flags::SF_Cannot_arrive])
|
||||
continue;
|
||||
|
||||
// check if ship is enemy ship (we attack it)
|
||||
if (!(iff_x_attacks_y(Player_ship->team, p_objp->team)))
|
||||
continue;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// event_music_get_info()
|
||||
//
|
||||
|
||||
@@ -102,8 +102,6 @@ void event_music_level_close();
|
||||
void event_music_do_frame();
|
||||
void event_music_disable();
|
||||
void event_music_enable();
|
||||
void event_music_pause();
|
||||
void event_music_unpause();
|
||||
void event_music_set_volume_all(float volume);
|
||||
void event_music_parse_musictbl(const char *filename);
|
||||
void event_music_change_pattern(int new_pattern);
|
||||
|
||||
Loaded 100 of 657 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user