mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-09 04:49:39 -10:00
Compare commits
1218
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4a654272ea | ||
|
|
91a2291c03 | ||
|
|
83d12684e4 | ||
|
|
565d91b6dc | ||
|
|
a1a5780104 | ||
|
|
49ee006dd5 | ||
|
|
b734d6017f | ||
|
|
349a9927cc | ||
|
|
da9ae0dd69 | ||
|
|
04f5c2ff84 | ||
|
|
d723300c86 | ||
|
|
c9e9b9849a | ||
|
|
44b4c04058 | ||
|
|
fbee2b8f49 | ||
|
|
6c1bb9a617 | ||
|
|
09d89066ec | ||
|
|
03b99a3fd0 | ||
|
|
6f089d74cb | ||
|
|
62180212f5 | ||
|
|
c6cd2de577 | ||
|
|
466995a909 | ||
|
|
56fc5b457f | ||
|
|
461c62823c | ||
|
|
24555ac739 | ||
|
|
d67fe30982 | ||
|
|
e35b03dc61 | ||
|
|
b596fa305d | ||
|
|
f08d82be23 | ||
|
|
dfe34ec58d | ||
|
|
2f3423d70e | ||
|
|
98de7323aa | ||
|
|
b6879da96d | ||
|
|
45d99265b8 | ||
|
|
ee9770d418 | ||
|
|
9d6c8509ab | ||
|
|
854b0139d2 | ||
|
|
c59a967f46 | ||
|
|
e6f46cf031 | ||
|
|
10f6f47819 | ||
|
|
328e7d37e0 | ||
|
|
b4ace94637 | ||
|
|
68943d2c06 | ||
|
|
a3e62433f2 | ||
|
|
5475c63309 | ||
|
|
3a7c532d1a | ||
|
|
39565d36e2 | ||
|
|
c8aa28b1cc | ||
|
|
b98b8f2d07 | ||
|
|
28659bb1f9 | ||
|
|
d68b18dfc8 | ||
|
|
40bbced2f9 | ||
|
|
a84941e6d1 | ||
|
|
faaa235c84 | ||
|
|
33f136dd26 | ||
|
|
bec860e9d8 | ||
|
|
6280ffe0e1 | ||
|
|
91a673ac58 | ||
|
|
a74bfab94b | ||
|
|
12784be019 | ||
|
|
23f7fa7f02 | ||
|
|
8da346dee3 | ||
|
|
ac16a54bec | ||
|
|
ddfd0c6fca | ||
|
|
dccb7dc8cf | ||
|
|
20338ff28b | ||
|
|
c8010e5447 | ||
|
|
92b628353f | ||
|
|
ff69743836 | ||
|
|
38f8943ccf | ||
|
|
df0f3da79c | ||
|
|
f5ccf98b17 | ||
|
|
e87d311d92 | ||
|
|
b5acdd607f | ||
|
|
332ccbc2df | ||
|
|
32b69eda2a | ||
|
|
a569bd9ab7 | ||
|
|
ca70a5a242 | ||
|
|
397a1c84ba | ||
|
|
ce6a6b447e | ||
|
|
5531dfc58d | ||
|
|
db13168729 | ||
|
|
cc5bb307c0 | ||
|
|
6b0fe5a763 | ||
|
|
704bf95a75 | ||
|
|
9887a7b638 | ||
|
|
908c1c7b32 | ||
|
|
619591f680 | ||
|
|
16447b7c7b | ||
|
|
05a0220f4a | ||
|
|
20bd8b4bf4 | ||
|
|
57c160623a | ||
|
|
590cfa5f81 | ||
|
|
8390304a6e | ||
|
|
f7e934440c | ||
|
|
6da7830b7b | ||
|
|
67a9f6f5b7 | ||
|
|
e1be949d0e | ||
|
|
c64a3e5e6a | ||
|
|
65d281e3cb | ||
|
|
4cbd84d59e | ||
|
|
d4cd767679 | ||
|
|
e9592bc4d7 | ||
|
|
5bc929d06e | ||
|
|
8dc1ffea94 | ||
|
|
a9fdbac199 | ||
|
|
01d3e14dc1 | ||
|
|
61e94636ac | ||
|
|
d16eb20aea | ||
|
|
f2bffd3234 | ||
|
|
35db8e31c9 | ||
|
|
cb75da4de6 | ||
|
|
d057c0b830 | ||
|
|
693a4a346d | ||
|
|
734efbdb54 | ||
|
|
c6844755d3 | ||
|
|
1ca56897bb | ||
|
|
1fae61b873 | ||
|
|
500bf1c2ca | ||
|
|
19b415e524 | ||
|
|
558f922209 | ||
|
|
7caef527d4 | ||
|
|
72b5135df4 | ||
|
|
f041b8dace | ||
|
|
372d2dd18e | ||
|
|
81da8a8499 | ||
|
|
6a5cd9fcc5 | ||
|
|
4ea0757950 | ||
|
|
79d0c93ba5 | ||
|
|
eeba1085c9 | ||
|
|
70629876b9 | ||
|
|
e1458ae8ab | ||
|
|
bac4eb84c0 | ||
|
|
20602b19c2 | ||
|
|
3c3289a3cc | ||
|
|
2166c756ab | ||
|
|
5faed98e3a | ||
|
|
fe3b72b01e | ||
|
|
8914ac6e2d | ||
|
|
87ea04fa53 | ||
|
|
f5a268bcef | ||
|
|
1db093e1d6 | ||
|
|
3d556af391 | ||
|
|
e1fd863dd0 | ||
|
|
1744718a03 | ||
|
|
d9cfd1f626 | ||
|
|
d9f9996c2d | ||
|
|
6f05c26542 | ||
|
|
944549ae5f | ||
|
|
fbab427943 | ||
|
|
705238a184 | ||
|
|
7557c54aa9 | ||
|
|
f341987471 | ||
|
|
cdbf525877 | ||
|
|
cc790a00bd | ||
|
|
b565376a02 | ||
|
|
52f417500c | ||
|
|
79d6e91403 | ||
|
|
5235aac95b | ||
|
|
bebed48bf8 | ||
|
|
38e27f8a25 | ||
|
|
98d5de9d13 | ||
|
|
6fdaf87717 | ||
|
|
acccc90ded | ||
|
|
de570875d0 | ||
|
|
e17f0260f6 | ||
|
|
6b6a622c4d | ||
|
|
e90416e199 | ||
|
|
a319adad76 | ||
|
|
97e36d8af6 | ||
|
|
f20c1bddfd | ||
|
|
c50b425fee | ||
|
|
7a99e9a7c9 | ||
|
|
84ccd1375e | ||
|
|
a7fc64389f | ||
|
|
ac44f1478e | ||
|
|
ffd78555a0 | ||
|
|
1f834aa406 | ||
|
|
4f2f8c9f25 | ||
|
|
200ef1093c | ||
|
|
691fe96151 | ||
|
|
840759d59a | ||
|
|
83d07277f2 | ||
|
|
cccf76863f | ||
|
|
c03207f141 | ||
|
|
5df0acf3ef | ||
|
|
75221b0ff5 | ||
|
|
6a4774dcc4 | ||
|
|
eed055d41a | ||
|
|
e374db538c | ||
|
|
6468901c0d | ||
|
|
d14b66456f | ||
|
|
723209ce29 | ||
|
|
98da98c53b | ||
|
|
558a8333e4 | ||
|
|
ffcbfeb70b | ||
|
|
c5de5149a9 | ||
|
|
e868d94927 | ||
|
|
253d97a3df | ||
|
|
da93cc6047 | ||
|
|
b57278ab18 | ||
|
|
630f479fd9 | ||
|
|
e7a7c830f0 | ||
|
|
d6e7d56081 | ||
|
|
5c5bcf72e9 | ||
|
|
06f909d7e3 | ||
|
|
46d4a1f219 | ||
|
|
7e71d4c194 | ||
|
|
2314294a8c | ||
|
|
3bce3fd631 | ||
|
|
31452e397b | ||
|
|
80e3030a0c | ||
|
|
4a739c988f | ||
|
|
7b4deb6c6b | ||
|
|
3d285f2f42 | ||
|
|
7403f4a1c9 | ||
|
|
9f99a9eae4 | ||
|
|
d11003a869 | ||
|
|
1b855044c7 | ||
|
|
a390b5a01a | ||
|
|
8c913c8cc5 | ||
|
|
ebeec69a6d | ||
|
|
1821df58cf | ||
|
|
3f9ec121ae | ||
|
|
408f116d95 | ||
|
|
ce34f77780 | ||
|
|
1bb34cc0ae | ||
|
|
f733414403 | ||
|
|
9a26d1fba5 | ||
|
|
c7334de3bd | ||
|
|
e1f0042e99 | ||
|
|
559a2616f3 | ||
|
|
7f20b9cf64 | ||
|
|
e1b44892e5 | ||
|
|
866f907e27 | ||
|
|
a1aac15e5a | ||
|
|
49e2d60551 | ||
|
|
67ebeb438e | ||
|
|
0f4c3ce8c7 | ||
|
|
786a4eff42 | ||
|
|
d87e997d79 | ||
|
|
aee0123587 | ||
|
|
be454f74b0 | ||
|
|
c1985656d1 | ||
|
|
d5e387479e | ||
|
|
574c39210f | ||
|
|
4432341694 | ||
|
|
8b43b5d325 | ||
|
|
836840154c | ||
|
|
41bdcfe720 | ||
|
|
4cdc0b9c0b | ||
|
|
c4a7a9dd15 | ||
|
|
f4921b6d01 | ||
|
|
900199d97f | ||
|
|
230fdf4d03 | ||
|
|
0da93ec5fd | ||
|
|
4ed38896d2 | ||
|
|
3529e49466 | ||
|
|
64c17f4830 | ||
|
|
b831c773dd | ||
|
|
350130ce9d | ||
|
|
1fa0f43c6f | ||
|
|
b5351c7ca8 | ||
|
|
e4b5d5fb7e | ||
|
|
b1d4e0a5e2 | ||
|
|
6a83875d93 | ||
|
|
01bb406b3d | ||
|
|
14aa38eea9 | ||
|
|
e991872c22 | ||
|
|
e9a91f9c1f | ||
|
|
e710b651de | ||
|
|
f0f7eb513f | ||
|
|
3164261152 | ||
|
|
120b76b21e | ||
|
|
c6efd0a0a3 | ||
|
|
914f895cac | ||
|
|
b3a51d776f | ||
|
|
dbac7d1259 | ||
|
|
42355b2384 | ||
|
|
16a0268bd7 | ||
|
|
73bbc94e5e | ||
|
|
a0d1ad163d | ||
|
|
3b0d4558ca | ||
|
|
ad8d9484c8 | ||
|
|
e93a60c68a | ||
|
|
d2af199f14 | ||
|
|
b122c7a10c | ||
|
|
8b3e36b3c9 | ||
|
|
87704fc817 | ||
|
|
0f67b85ac0 | ||
|
|
8e082e7293 | ||
|
|
aa3192aa94 | ||
|
|
6419adfbe4 | ||
|
|
27caca5d2f | ||
|
|
e3bdc106f3 | ||
|
|
c1af4317d4 | ||
|
|
3f5a154e7a | ||
|
|
8bd8e785b1 | ||
|
|
24e9a3a0c1 | ||
|
|
122e29fcaa | ||
|
|
03311c1527 | ||
|
|
379077242a | ||
|
|
cb4258e31f | ||
|
|
8ce463daf5 | ||
|
|
fd32abad25 | ||
|
|
f1c521413c | ||
|
|
3b31034688 | ||
|
|
30d1653cae | ||
|
|
724e2e7f68 | ||
|
|
5ccc3d5a78 | ||
|
|
49777052ac | ||
|
|
b9466193f5 | ||
|
|
6fdb9459b5 | ||
|
|
0d1c86e0cd | ||
|
|
cb93748898 | ||
|
|
9192bb00b1 | ||
|
|
ebd39bb5df | ||
|
|
30b0026ca5 | ||
|
|
c14a62e9d3 | ||
|
|
046f302458 | ||
|
|
4b6cbb9c01 | ||
|
|
ed78fd84ea | ||
|
|
393a9d4eba | ||
|
|
9b94655250 | ||
|
|
5a501a8447 | ||
|
|
3747a45dbe | ||
|
|
5d30c07e31 | ||
|
|
e2bf3bbd46 | ||
|
|
5d6e68b8fd | ||
|
|
d51f53fb30 | ||
|
|
23dda4ba43 | ||
|
|
499a5f4a02 | ||
|
|
67e689106c | ||
|
|
67999a3fe8 | ||
|
|
5cb0633314 | ||
|
|
2bbc052e7f | ||
|
|
a222b29586 | ||
|
|
49a1e8458f | ||
|
|
b5efed380f | ||
|
|
9d9714f0bb | ||
|
|
edeabbbd58 | ||
|
|
62f25d7400 | ||
|
|
d43818f7dc | ||
|
|
6c9bf8def4 | ||
|
|
c73c0ef889 | ||
|
|
a9141e9733 | ||
|
|
fc4024ab66 | ||
|
|
c2335640ad | ||
|
|
8b984781fd | ||
|
|
c3b01da2d1 | ||
|
|
68a936504f | ||
|
|
6edaea6056 | ||
|
|
bf7c923020 | ||
|
|
bfe40e12c6 | ||
|
|
8d9736d3e3 | ||
|
|
322f807ac0 | ||
|
|
209f5636b0 | ||
|
|
dea9437c04 | ||
|
|
b624019f32 | ||
|
|
d1d173b99f | ||
|
|
b7f4ad9780 | ||
|
|
69c8957500 | ||
|
|
76359c649f | ||
|
|
855331bcd6 | ||
|
|
fa6d64ae7e | ||
|
|
bc4cc598c9 | ||
|
|
3d92d469ac | ||
|
|
9edcf5f450 | ||
|
|
2f5e7a4de2 | ||
|
|
8d6a8721f9 | ||
|
|
7ebfa52bf5 | ||
|
|
89e8961984 | ||
|
|
0f4dc47db9 | ||
|
|
eacba95b7b | ||
|
|
f40941304c | ||
|
|
eb9c58dc2d | ||
|
|
742fd321d5 | ||
|
|
3851832db5 | ||
|
|
539d89ca8c | ||
|
|
289d0b66d1 | ||
|
|
f3c6b0f8f3 | ||
|
|
1bd65192ba | ||
|
|
2642fa22de | ||
|
|
ac8d774bc7 | ||
|
|
a57ae15c72 | ||
|
|
26c4ea1057 | ||
|
|
148efb4713 | ||
|
|
88bf67a64f | ||
|
|
a18b122b19 | ||
|
|
0a59c533c2 | ||
|
|
3ad0d3713d | ||
|
|
7acf56f4f5 | ||
|
|
55c41c96a7 | ||
|
|
e63383d324 | ||
|
|
7ae8c79dea | ||
|
|
002783ce7c | ||
|
|
72b6ded0ac | ||
|
|
4c7f16fb1b | ||
|
|
ecb9fae3c4 | ||
|
|
55c20636d9 | ||
|
|
e8d164c926 | ||
|
|
89f4fe54c3 | ||
|
|
7fba753f9d | ||
|
|
bd05f13f07 | ||
|
|
d5a3813e8b | ||
|
|
735d4ab678 | ||
|
|
71543c9c10 | ||
|
|
b2e1ae43a9 | ||
|
|
c7cffcb311 | ||
|
|
c96f1af375 | ||
|
|
c2d1b69ea2 | ||
|
|
861e5f9813 | ||
|
|
f288ef7101 | ||
|
|
067f862c4d | ||
|
|
3478640b4d | ||
|
|
66204287e6 | ||
|
|
6b1d9304ed | ||
|
|
66ec2c8154 | ||
|
|
e3918a14f2 | ||
|
|
4b1476c101 | ||
|
|
86db536bf5 | ||
|
|
b3b811841b | ||
|
|
cc62643001 | ||
|
|
3b7157e2de | ||
|
|
a5630d63a5 | ||
|
|
052b4b29e9 | ||
|
|
ea8e356b63 | ||
|
|
9bba53c3e8 | ||
|
|
3df616e69d | ||
|
|
0fb18a15c4 | ||
|
|
e1503a8ac8 | ||
|
|
b11cf2c2db | ||
|
|
9c8d02b69b | ||
|
|
055cc6e4c8 | ||
|
|
e3447223eb | ||
|
|
8b575e7a72 | ||
|
|
30547ff026 | ||
|
|
d564329ffb | ||
|
|
18c5662584 | ||
|
|
534c69ee60 | ||
|
|
b3bafb83b4 | ||
|
|
9783e96207 | ||
|
|
103275e488 | ||
|
|
16ff22cce1 | ||
|
|
ef31905f3e | ||
|
|
18f76652cf | ||
|
|
d3c43732fa | ||
|
|
e6b2cbf900 | ||
|
|
0267fb539c | ||
|
|
218a98dde3 | ||
|
|
f52ebc8ccb | ||
|
|
88897b907c | ||
|
|
9ab82ae607 | ||
|
|
c01c7da121 | ||
|
|
817fa2cd98 | ||
|
|
41be934485 | ||
|
|
b870675cc9 | ||
|
|
5b3dddff4a | ||
|
|
8c904c36f9 | ||
|
|
c7f80725fe | ||
|
|
5af559d1cf | ||
|
|
d4246432d7 | ||
|
|
95bc875ac2 | ||
|
|
6b72772ac9 | ||
|
|
6de2897347 | ||
|
|
7a83c71b87 | ||
|
|
74805c83ba | ||
|
|
c9f3244268 | ||
|
|
308e2edb3e | ||
|
|
2baec05a55 | ||
|
|
bf2dbb4a02 | ||
|
|
228a8994ee | ||
|
|
fe2561c893 | ||
|
|
ee73fadad1 | ||
|
|
d75e4e46ab | ||
|
|
2d90756fed | ||
|
|
807e416ebb | ||
|
|
b8bb4d445b | ||
|
|
f0f57bf576 | ||
|
|
8b081bf2ed | ||
|
|
1f034209d0 | ||
|
|
cef7abb1db | ||
|
|
d9909e2a21 | ||
|
|
90097293cb | ||
|
|
c2aa94bdde | ||
|
|
404a8c9bb7 | ||
|
|
209583b449 | ||
|
|
5c746f13a6 | ||
|
|
dae99e5b80 | ||
|
|
e5f0b674b5 | ||
|
|
eebc2bfd59 | ||
|
|
7eb64e59bb | ||
|
|
7db278410c | ||
|
|
ed4d187365 | ||
|
|
1bbcdc3dc5 | ||
|
|
c36551fbd6 | ||
|
|
6f94d67cfa | ||
|
|
0ffd9bc421 | ||
|
|
4899e6454e | ||
|
|
8f6f6ab970 | ||
|
|
3388341343 | ||
|
|
e65803b747 | ||
|
|
197356077d | ||
|
|
168d3c9ddf | ||
|
|
55ead5c2c6 | ||
|
|
db8a3651cd | ||
|
|
620afa0c1e | ||
|
|
7fdcd4abc7 | ||
|
|
18394f7074 | ||
|
|
897e388d1c | ||
|
|
8bde63a9ae | ||
|
|
f021e9df8a | ||
|
|
4a1d794a64 | ||
|
|
fecb9b16af | ||
|
|
aa12ec7790 | ||
|
|
7e637d5d5a | ||
|
|
ff5bc2f6a0 | ||
|
|
c08a669c2e | ||
|
|
03f6f09c93 | ||
|
|
74c2a204c7 | ||
|
|
a9ad87ea08 | ||
|
|
0a86623e9e | ||
|
|
2f957668e3 | ||
|
|
38d9a975ce | ||
|
|
f26643c43d | ||
|
|
c2cb07ded3 | ||
|
|
7a04f76a46 | ||
|
|
006d2a49b1 | ||
|
|
a281f35f1a | ||
|
|
88f7e41d8c | ||
|
|
f2998a2c69 | ||
|
|
1b0a3ea6f9 | ||
|
|
5e274a008c | ||
|
|
38be5c248c | ||
|
|
0450ef0d1a | ||
|
|
e6a2a2a7f9 | ||
|
|
bbb6a6f199 | ||
|
|
1c0b58e11b | ||
|
|
0bf0735cd9 | ||
|
|
cc3791b594 | ||
|
|
799906a921 | ||
|
|
043e3fab79 | ||
|
|
2e34c29215 | ||
|
|
8ac68c5b8b | ||
|
|
b92f50e94f | ||
|
|
96228d6e98 | ||
|
|
dc4daafd61 | ||
|
|
4b37796628 | ||
|
|
45a434a60a | ||
|
|
488ec8d5a8 | ||
|
|
b1460eb3fa | ||
|
|
671fe21a75 | ||
|
|
d6606ad642 | ||
|
|
d9b2b428a0 | ||
|
|
e87fcfaf28 | ||
|
|
65d1b7f99a | ||
|
|
712337a2da | ||
|
|
b9169cc425 | ||
|
|
b7a0124a9b | ||
|
|
27925607b8 | ||
|
|
38d8f17990 | ||
|
|
5143855863 | ||
|
|
648a1d009d | ||
|
|
df531fc595 | ||
|
|
5802f718f6 | ||
|
|
7d62d741b9 | ||
|
|
45258aabb4 | ||
|
|
db34b4d53c | ||
|
|
7c2077baf2 | ||
|
|
eef7623e9f | ||
|
|
529ac05034 | ||
|
|
6ac8559630 | ||
|
|
2626e7862b | ||
|
|
b3cd35258c | ||
|
|
0fb12b89eb | ||
|
|
c082babd9c | ||
|
|
d5f3be091c | ||
|
|
790227a2bf | ||
|
|
803f08f969 | ||
|
|
f2c40a2669 | ||
|
|
63756c00af | ||
|
|
2147571dff | ||
|
|
bb9c76103b | ||
|
|
857e61f638 | ||
|
|
58053a02b2 | ||
|
|
e8ea8733d0 | ||
|
|
184bbb52bb | ||
|
|
b00410ab01 | ||
|
|
525d8e34d0 | ||
|
|
4cdf10b399 | ||
|
|
c652d5a84c | ||
|
|
1a356834b4 | ||
|
|
3f48f7c4ad | ||
|
|
3e8a9d9738 | ||
|
|
592eefb60f | ||
|
|
373218d7d9 | ||
|
|
1bdd6c3c4c | ||
|
|
1313434e11 | ||
|
|
bf996313dc | ||
|
|
2eb5a3ecde | ||
|
|
1aee2401e5 | ||
|
|
f8203e9da3 | ||
|
|
b24bcbcc62 | ||
|
|
0b8c1b6853 | ||
|
|
6ae6c550a7 | ||
|
|
9c521d04d8 | ||
|
|
c6c9945e50 | ||
|
|
8dfeca4ac3 | ||
|
|
bb4898cb04 | ||
|
|
6e38656658 | ||
|
|
e72dd4c2ca | ||
|
|
be8725c6c6 | ||
|
|
15c921223b | ||
|
|
ec241fcab3 | ||
|
|
0e00ab670c | ||
|
|
1f9a2ca4ce | ||
|
|
0d697672dc | ||
|
|
1fe62ea8d1 | ||
|
|
687694c732 | ||
|
|
9093af9b95 | ||
|
|
3b0dca6cd9 | ||
|
|
817b7dc975 | ||
|
|
d4d7c8dbd2 | ||
|
|
bb89553b0a | ||
|
|
e4acd15a1e | ||
|
|
d16f46fb1c | ||
|
|
77ad3ba0aa | ||
|
|
da31995331 | ||
|
|
25d326567e | ||
|
|
03696d07ca | ||
|
|
0528538a6f | ||
|
|
3a48613a2d | ||
|
|
a7b795e965 | ||
|
|
99875810c6 | ||
|
|
13420121dd | ||
|
|
26c5152d4a | ||
|
|
5066e498a3 | ||
|
|
4bf806c485 | ||
|
|
2403f13483 | ||
|
|
8e98cddd6e | ||
|
|
30cabc4174 | ||
|
|
8a3b36d921 | ||
|
|
b74824f793 | ||
|
|
6a26ca5061 | ||
|
|
9b78fad1c5 | ||
|
|
d34570ae90 | ||
|
|
a0f4c4d2b3 | ||
|
|
63990c54a9 | ||
|
|
6593565165 | ||
|
|
af93922ba5 | ||
|
|
6ca68151a1 | ||
|
|
f61407d899 | ||
|
|
86ef5c356e | ||
|
|
a127a35eee | ||
|
|
2a6c14d3b5 | ||
|
|
4f28615c6c | ||
|
|
46408cce3a | ||
|
|
3f1e67330c | ||
|
|
e16ae385fa | ||
|
|
2e90c8eed6 | ||
|
|
da352c3eea | ||
|
|
daeb1a7940 | ||
|
|
f56cbc59f1 | ||
|
|
79418a073d | ||
|
|
ce2e165510 | ||
|
|
e9ee311709 | ||
|
|
7576d4f2fe | ||
|
|
866b06ca35 | ||
|
|
f4d7b45e4d | ||
|
|
d23e4b8e87 | ||
|
|
f3d15f8ddc | ||
|
|
c9fe191d31 | ||
|
|
bad255fffb | ||
|
|
be260ef74c | ||
|
|
0ac3d52261 | ||
|
|
f7df03c654 | ||
|
|
a7e1a27e36 | ||
|
|
d83de47ef2 | ||
|
|
59435abfb2 | ||
|
|
ab319a631c | ||
|
|
7c2950480e | ||
|
|
a80bc26bfc | ||
|
|
ead3c62d23 | ||
|
|
5cd502fb79 | ||
|
|
905d777e18 | ||
|
|
66deb83980 | ||
|
|
de3e382180 | ||
|
|
0190fda7ee | ||
|
|
9651dc1598 | ||
|
|
743cf779bf | ||
|
|
da1e2c1049 | ||
|
|
bf13ce54a8 | ||
|
|
fcd3264fad | ||
|
|
e33419c48d | ||
|
|
a73df5bcb4 | ||
|
|
4e707fc8e9 | ||
|
|
2e7057ed8d | ||
|
|
ba9285e09a | ||
|
|
138eddfbd2 | ||
|
|
66be185d0c | ||
|
|
0c355efaa2 | ||
|
|
89a6e2aa7d | ||
|
|
84033d901c | ||
|
|
46226a6cbe | ||
|
|
4b49123070 | ||
|
|
213bcbc80b | ||
|
|
0da34f0bc8 | ||
|
|
8fcf385e7e | ||
|
|
4f4722ccad | ||
|
|
7d94561ea5 | ||
|
|
248cec7cf9 | ||
|
|
e987d1cd7b | ||
|
|
f1aa29551b | ||
|
|
76734fb5ed | ||
|
|
fb0a62c400 | ||
|
|
1403301b65 | ||
|
|
1d1eb5ec4d | ||
|
|
7283412880 | ||
|
|
1d2ca8eb5a | ||
|
|
130ddb41f1 | ||
|
|
9462241c0b | ||
|
|
14bba9aea1 | ||
|
|
c7b43b0e0e | ||
|
|
1355c484fe | ||
|
|
1866c6adb5 | ||
|
|
a11517984e | ||
|
|
f207d2d12c | ||
|
|
4970252e9f | ||
|
|
d789e9b33a | ||
|
|
292f7d3b03 | ||
|
|
3bfc37172a | ||
|
|
2bb1c10557 | ||
|
|
84f97936aa | ||
|
|
40fac5dd5f | ||
|
|
2a33e374c2 | ||
|
|
d48d00d946 | ||
|
|
562875130c | ||
|
|
4401101fea | ||
|
|
509f887f6c | ||
|
|
266079997a | ||
|
|
f4a3903478 | ||
|
|
f4202df450 | ||
|
|
e619c0c3d3 | ||
|
|
ff0b79b6be | ||
|
|
701d20c112 | ||
|
|
9a45c9fd05 | ||
|
|
146102e82c | ||
|
|
be2c18d608 | ||
|
|
c9644cdcae | ||
|
|
d088e895f8 | ||
|
|
f1a9b2639b | ||
|
|
a1690dcb90 | ||
|
|
2c4088efdd | ||
|
|
da3725a3ac | ||
|
|
81b7460e57 | ||
|
|
c9a1127764 | ||
|
|
6eb9ae2aec | ||
|
|
d3d9ee3092 | ||
|
|
f66fc92859 | ||
|
|
94cbc350a4 | ||
|
|
550e9ec5b2 | ||
|
|
de3463958d | ||
|
|
03d7845124 | ||
|
|
661dceb0d8 | ||
|
|
202686dab6 | ||
|
|
b8da1106eb | ||
|
|
43f7921121 | ||
|
|
f4669db41c | ||
|
|
b3df3364e4 | ||
|
|
b6a76b788d | ||
|
|
e21b07662e | ||
|
|
9b4b0b552b | ||
|
|
bdab7a0c55 | ||
|
|
e269cdab6e | ||
|
|
edc76bcb40 | ||
|
|
cbde5a8e85 | ||
|
|
7fcfc35820 | ||
|
|
f852421d76 | ||
|
|
2321311725 | ||
|
|
38cd1bff86 | ||
|
|
71ee9501f9 | ||
|
|
221670589e | ||
|
|
9a47a664f7 | ||
|
|
7b7b19b71b | ||
|
|
666b9a5751 | ||
|
|
733e1adcba | ||
|
|
8421d8d8e6 | ||
|
|
63ed4c8254 | ||
|
|
3124c55642 | ||
|
|
485eb16fe3 | ||
|
|
a493f07333 | ||
|
|
366c1a9d0b | ||
|
|
0594a487c8 | ||
|
|
f8733eab72 | ||
|
|
8dcc4a24e9 | ||
|
|
bf4d7a3114 | ||
|
|
5e8a4f754d | ||
|
|
d0a537ff82 | ||
|
|
e7c98d6d23 | ||
|
|
36e7598ceb | ||
|
|
0672bd94e9 | ||
|
|
c7792cd781 | ||
|
|
252392b26a | ||
|
|
65677542cb | ||
|
|
691bbca2b2 | ||
|
|
cd95b143a0 | ||
|
|
a360a1f5f1 | ||
|
|
d1119b2353 | ||
|
|
c37e1b1c96 | ||
|
|
fd6ca9dde9 | ||
|
|
fbb3a8f6a5 | ||
|
|
0e63d64647 | ||
|
|
de50f693ae | ||
|
|
6e9b31cb5a | ||
|
|
e316c28258 | ||
|
|
1ef528af5f | ||
|
|
e536413259 | ||
|
|
ccbe7efcbe | ||
|
|
1fcf51bd92 | ||
|
|
b9938b854f | ||
|
|
ad06cb1c5b | ||
|
|
b62a7fbe3d | ||
|
|
4011a0800d | ||
|
|
8f7c6a0ed8 | ||
|
|
9e719440c9 | ||
|
|
6692540cbf | ||
|
|
668fc18d5c | ||
|
|
a101e3cf77 | ||
|
|
dcce4a6538 | ||
|
|
7ce3217f17 | ||
|
|
33a1b1f8ca | ||
|
|
a29a97f39a | ||
|
|
8d40d7467e | ||
|
|
eb57482c1a | ||
|
|
50f083043b | ||
|
|
d02bd6ca04 | ||
|
|
e543c1aea2 | ||
|
|
22962afcde | ||
|
|
1f9c9a3673 | ||
|
|
f3922f35e8 | ||
|
|
bb5bfad828 | ||
|
|
18ac8425ee | ||
|
|
f6167bb89a | ||
|
|
c8ceb289ba | ||
|
|
9ea64627ab | ||
|
|
6e9ca36481 | ||
|
|
90dbdc4236 | ||
|
|
3a35f7ebe7 | ||
|
|
05f190b36c | ||
|
|
0924a392aa | ||
|
|
21db833dee | ||
|
|
86011f2669 | ||
|
|
2bd143e093 | ||
|
|
79d3077071 | ||
|
|
aacd14e1df | ||
|
|
43afcd5ea6 | ||
|
|
b98544d862 | ||
|
|
7867dc77bd | ||
|
|
426c227b68 | ||
|
|
612bdcf4df | ||
|
|
0d712d6fc0 | ||
|
|
62fa0c081b | ||
|
|
8035a2b32a | ||
|
|
f7f2c58746 | ||
|
|
7bf0fd137d | ||
|
|
6d818f1e3b | ||
|
|
e23b5533aa | ||
|
|
6b79571edc | ||
|
|
27f022b2f2 | ||
|
|
4578fbc900 | ||
|
|
bfde2144a2 | ||
|
|
1787f4457b | ||
|
|
be14c34f7d | ||
|
|
da66bd65da | ||
|
|
dc7aa86147 | ||
|
|
4bf743765c | ||
|
|
b4e3ebe085 | ||
|
|
ada432a1f3 | ||
|
|
25d796afe4 | ||
|
|
1a034031d1 | ||
|
|
23098666e2 | ||
|
|
5490751167 | ||
|
|
4bc9cf0846 | ||
|
|
dd9248fc22 | ||
|
|
c2ed03ca59 | ||
|
|
7491a82d74 | ||
|
|
2f0c0f1d6f | ||
|
|
3b231b375f | ||
|
|
07fb5bec0e | ||
|
|
e51815a933 | ||
|
|
ea6e503ea1 | ||
|
|
a381ecc607 | ||
|
|
125e47d749 | ||
|
|
d280800bce | ||
|
|
a1c9b108ed | ||
|
|
d7a06c893f | ||
|
|
3aa672c855 | ||
|
|
8acbe82aa0 | ||
|
|
5227e2e0c4 | ||
|
|
95baa85750 | ||
|
|
fb1ffd8413 | ||
|
|
f43732c5da | ||
|
|
8dbe0e7b8a | ||
|
|
3ad66b988d | ||
|
|
969759426a | ||
|
|
224503391f | ||
|
|
0edc6267aa | ||
|
|
def75287eb | ||
|
|
c427014fc2 | ||
|
|
99d140fb83 | ||
|
|
808e5bedd9 | ||
|
|
6dfd1ed0b8 | ||
|
|
0d1d6fdf44 | ||
|
|
369b90a156 | ||
|
|
7bb6a8ae86 | ||
|
|
7afb00e976 | ||
|
|
c4fe9e664f | ||
|
|
eda9f16294 | ||
|
|
f7dddc35d1 | ||
|
|
b8806e958d | ||
|
|
40cf32133f | ||
|
|
691ec74406 | ||
|
|
359886fee1 | ||
|
|
9b86d2f16d | ||
|
|
260f15624b | ||
|
|
6de870766a | ||
|
|
072e802863 | ||
|
|
2ca9d6672c | ||
|
|
7281e8d127 | ||
|
|
a730f30435 | ||
|
|
cd5f044217 | ||
|
|
8b90cda3f4 | ||
|
|
6b2ced4643 | ||
|
|
5ee051c55f | ||
|
|
ecc452088c | ||
|
|
841ae430c0 | ||
|
|
3f7ffdb6a0 | ||
|
|
737717fe3f | ||
|
|
a463ac19cf | ||
|
|
9d0ee6ab0d | ||
|
|
703269aa71 | ||
|
|
b7a0170cd1 | ||
|
|
6f263365af | ||
|
|
6435843c24 | ||
|
|
22ee5d5c15 | ||
|
|
5fadb12b0f | ||
|
|
e94c515ab8 | ||
|
|
d83ddeed0f | ||
|
|
3556d41b44 | ||
|
|
f2df96b4bb | ||
|
|
9eeb3307d0 | ||
|
|
a406b43876 | ||
|
|
c86802e9c1 | ||
|
|
5b4065bd53 | ||
|
|
5fd439fb60 | ||
|
|
2043f836ed | ||
|
|
4a3c7fc9a9 | ||
|
|
e0e3f7e7ac | ||
|
|
542d9741c4 | ||
|
|
68eef5949b | ||
|
|
7958670868 | ||
|
|
226ed40cec | ||
|
|
d454a74716 | ||
|
|
4ff96abd9e | ||
|
|
5bc1200731 | ||
|
|
b23dff91e7 | ||
|
|
3af831e0b7 | ||
|
|
bcae459b56 | ||
|
|
ff7d85a60f | ||
|
|
267fcfc6f8 | ||
|
|
8587bf768b | ||
|
|
535ff9f99a | ||
|
|
422ccaa514 | ||
|
|
a3e27f566f | ||
|
|
9ecb451efe | ||
|
|
e3d2c02f99 | ||
|
|
13170a235e | ||
|
|
5406445ed4 | ||
|
|
301b9453b6 | ||
|
|
cd32c2ce42 | ||
|
|
7b1b1113da | ||
|
|
1f32834d9d | ||
|
|
bee0742aa2 | ||
|
|
d336d395db | ||
|
|
1953bd9c49 | ||
|
|
e27cbe9517 | ||
|
|
4b5d4320f8 | ||
|
|
ed7f3e6880 | ||
|
|
980d2c2bcc | ||
|
|
17dfa0ddb9 | ||
|
|
5f511e34e3 | ||
|
|
31c8739ecd | ||
|
|
8e23c32b8c | ||
|
|
b628b665cf | ||
|
|
7a367b10ad | ||
|
|
09c885c4af | ||
|
|
9ac6060abd | ||
|
|
a34f37fa8d | ||
|
|
7645704ac2 | ||
|
|
b25e76cb65 | ||
|
|
a9cfd27455 | ||
|
|
110f609dea | ||
|
|
ba3ac66958 | ||
|
|
274366c8ad | ||
|
|
df285b7ae1 | ||
|
|
7eec846b3d | ||
|
|
25a9f6abe2 | ||
|
|
f0737f1b87 | ||
|
|
dbefa6d333 | ||
|
|
54c0680b2a | ||
|
|
058cec3d2c | ||
|
|
a73cc9bfce | ||
|
|
245ac3f6b3 | ||
|
|
ee6159c685 | ||
|
|
68f9d90629 | ||
|
|
2523218fdc | ||
|
|
b323760659 | ||
|
|
5a93f78933 | ||
|
|
e99341d79f | ||
|
|
54a188d46a | ||
|
|
f686046a1d | ||
|
|
61f8e0370b | ||
|
|
397125fc6e | ||
|
|
6f458d5398 | ||
|
|
1223808a14 | ||
|
|
19c4c6edba | ||
|
|
bfeb86f017 | ||
|
|
e7ded2b4cd | ||
|
|
b2d1da6701 | ||
|
|
d0086c31b8 | ||
|
|
d9786f8aae | ||
|
|
fe916eb7ce | ||
|
|
a476897963 | ||
|
|
e404f32c7b | ||
|
|
77a2f5345f | ||
|
|
41efb57879 | ||
|
|
729aa2f6f7 | ||
|
|
346ce5c975 | ||
|
|
d1d64a0afb | ||
|
|
94cd6cf8bb | ||
|
|
9b09818b49 | ||
|
|
1ab0d74939 | ||
|
|
474db9e184 | ||
|
|
36cb7a62d6 | ||
|
|
cb1f1e9c0b | ||
|
|
9dc291569f | ||
|
|
5da1a075ad | ||
|
|
ad05ce147e | ||
|
|
9a227de872 | ||
|
|
d4ca441449 | ||
|
|
4ea99eb461 | ||
|
|
e01dabeb59 | ||
|
|
27e80a3fff | ||
|
|
3ab8cb097c | ||
|
|
3721f8165d | ||
|
|
f94119d722 | ||
|
|
5e78054a66 | ||
|
|
cfe64748a4 | ||
|
|
7a281781e3 | ||
|
|
a859192587 | ||
|
|
fa49d05e0c | ||
|
|
d8ff77f57f | ||
|
|
fdc8c246f5 | ||
|
|
395aadba6b | ||
|
|
1625d86ad7 | ||
|
|
187d24c2f4 | ||
|
|
47ac8a56a0 | ||
|
|
72ccbff147 | ||
|
|
9960d4bc9f | ||
|
|
2334138b99 | ||
|
|
a0b7134b9b | ||
|
|
b20efdec80 | ||
|
|
b546dcf949 | ||
|
|
15329b9564 | ||
|
|
94bd1af5cd | ||
|
|
367f48cf2f | ||
|
|
eff00035fa | ||
|
|
ba2c2f03fb | ||
|
|
309bf0b3ea | ||
|
|
b62c49ec81 | ||
|
|
e34c82d7d1 | ||
|
|
67e00da79b | ||
|
|
8528bfe750 | ||
|
|
37c344a127 | ||
|
|
b5b922cbf0 | ||
|
|
1cbeae2cd9 | ||
|
|
4292303018 | ||
|
|
3ebdc51c48 | ||
|
|
6e8ab64523 | ||
|
|
1b04d9f22c | ||
|
|
4013cf6046 | ||
|
|
26df8e9a45 | ||
|
|
bb3e3eadfc | ||
|
|
b5e215a85c | ||
|
|
da4eeb3582 | ||
|
|
dc578c2479 | ||
|
|
3522f3be91 | ||
|
|
bd52d75ab9 | ||
|
|
a54dc0ded7 | ||
|
|
c076cd11f1 | ||
|
|
b42c7af847 | ||
|
|
5893ef836c | ||
|
|
9eeb7e7983 | ||
|
|
71fa18927c | ||
|
|
ae89ed2b9d | ||
|
|
24a4c0df6a | ||
|
|
a5f90ddcc1 | ||
|
|
3fe94fc3f4 | ||
|
|
f89d437506 | ||
|
|
86a8c1c6f5 | ||
|
|
f72fb68615 | ||
|
|
3447b76736 | ||
|
|
7dd52a4214 | ||
|
|
8671b9e2f7 | ||
|
|
b861989fb6 | ||
|
|
1c8a272eca | ||
|
|
221b0dc7ee | ||
|
|
0a5cf6ad9d | ||
|
|
2cb12b8ff7 | ||
|
|
9f173e8cd9 | ||
|
|
6588daaca5 | ||
|
|
9cd648a206 | ||
|
|
44c797f65b | ||
|
|
46b9c27dfe | ||
|
|
33e3b13d43 | ||
|
|
8351d4f623 | ||
|
|
e0443739bd | ||
|
|
80a206151c | ||
|
|
64a592d0d5 | ||
|
|
c30559a63a | ||
|
|
245cec5a34 | ||
|
|
ddedc1bd8e | ||
|
|
6b71812e7b | ||
|
|
844e9affea | ||
|
|
b69cdc08ee | ||
|
|
69d56172b0 | ||
|
|
9d2a89f778 | ||
|
|
adcc19085d | ||
|
|
faddde8307 | ||
|
|
0355d2b8d1 | ||
|
|
21f42ce47b | ||
|
|
574b1e6197 | ||
|
|
34e57d301a | ||
|
|
dc83e4f14a | ||
|
|
3c837b7e9a | ||
|
|
c7b77a5b24 | ||
|
|
5a58ff46f2 | ||
|
|
4145717363 | ||
|
|
eca583074a | ||
|
|
723bdcb9f1 | ||
|
|
cb4fe955ea | ||
|
|
ed83ed79ec | ||
|
|
02669338e8 | ||
|
|
6e86a3a035 | ||
|
|
4f8344c91e | ||
|
|
643d18c6f8 | ||
|
|
8dc481d034 | ||
|
|
3ba2193d3f | ||
|
|
8693fa37eb | ||
|
|
3764146957 | ||
|
|
50c923d397 | ||
|
|
617c903cbd | ||
|
|
b6903fbdf4 | ||
|
|
dc751a9c5d | ||
|
|
dff0b2acb4 | ||
|
|
ea10ac157f | ||
|
|
173a3d23e8 | ||
|
|
98e20c0979 | ||
|
|
db02a829aa | ||
|
|
cfe92a4d32 | ||
|
|
7f9a10a9a0 | ||
|
|
925e2e53f4 | ||
|
|
0e7f24bcac | ||
|
|
b2d85b8e2f | ||
|
|
e23409f5f8 | ||
|
|
381e45f483 | ||
|
|
2d2db58905 | ||
|
|
2b3da41a6d | ||
|
|
9da948be56 | ||
|
|
79454fb6c4 | ||
|
|
10ed12182c | ||
|
|
729e448fe5 | ||
|
|
96ae3d0608 | ||
|
|
55ed0a08f6 | ||
|
|
c017ef9b8a | ||
|
|
e071603ac0 | ||
|
|
e6792ab441 | ||
|
|
5d6c34c2ab | ||
|
|
17ad0e09dd | ||
|
|
a0c787aa83 | ||
|
|
ee27abf693 | ||
|
|
6bcd2f730c | ||
|
|
c8d78816b0 | ||
|
|
b53f3fc803 | ||
|
|
d1f0b9343f | ||
|
|
0b2d4768f3 | ||
|
|
42fc9891e3 | ||
|
|
bfd261a1d3 | ||
|
|
0c8564f085 | ||
|
|
6d08a90106 | ||
|
|
92ed875e69 | ||
|
|
1dc701270f | ||
|
|
41b10e4d40 | ||
|
|
8460218707 | ||
|
|
f2d0bfdb31 | ||
|
|
6350a67e73 | ||
|
|
bfad425738 | ||
|
|
e387038cc3 | ||
|
|
52b7a3d198 | ||
|
|
b7045f1756 | ||
|
|
accb842ffa | ||
|
|
97adef1d87 | ||
|
|
bb6917ab3b | ||
|
|
861a9c9c4a | ||
|
|
d2d1d8f996 | ||
|
|
46530b78b7 | ||
|
|
cf3b5e8085 | ||
|
|
71ac62e395 | ||
|
|
676fb4b17d |
No files matched your search
+11
-1
@@ -4,20 +4,27 @@ modernize-*,\
|
||||
-modernize-avoid-c-arrays,\
|
||||
-modernize-make-unique,\
|
||||
-modernize-raw-string-literal,\
|
||||
-modernize-use-default-member-init,\
|
||||
-modernize-use-trailing-return-type,\
|
||||
-modernize-use-using,\
|
||||
performance-*,\
|
||||
-performance-no-int-to-ptr,\
|
||||
-performance-type-promotion-in-math-fn,\
|
||||
misc-*,\
|
||||
-misc-include-cleaner,\
|
||||
-misc-macro-parentheses,\
|
||||
-misc-misplaced-widening-cast,\
|
||||
-misc-no-recursion,\
|
||||
-misc-non-private-member-variables-in-classes,\
|
||||
-misc-static-assert,\
|
||||
-misc-unused-parameters,\
|
||||
-misc-use-anonymous-namespace,\
|
||||
readability-*,\
|
||||
-readability-avoid-const-params-in-decls,\
|
||||
-readability-else-after-return,\
|
||||
-readability-function-cognitive-complexity,\
|
||||
-readability-function-size,\
|
||||
-readability-identifier-length,\
|
||||
-readability-identifier-naming,\
|
||||
-readability-implicit-bool-conversion,\
|
||||
-readability-inconsistent-declaration-parameter-name,\
|
||||
@@ -29,10 +36,13 @@ readability-*,\
|
||||
"
|
||||
WarningsAsErrors: ''
|
||||
HeaderFilterRegex: 'code/.*$|freespace2/.*$|qtfred/.*$|test/src/.*$|build/.*$'
|
||||
AnalyzeTemporaryDtors: false
|
||||
CheckOptions:
|
||||
- key: 'misc-assert-side-effect.AssertMacros'
|
||||
value: 'assert,Assert,Assertion'
|
||||
- key: 'misc-const-correctness.AnalyzeValues'
|
||||
value: 'false'
|
||||
- key: 'misc-const-correctness.TransformValues'
|
||||
value: 'false'
|
||||
- key: 'modernize-use-emplace.ContainersWithPushBack'
|
||||
value: 'std::vector;std::deque;std::list;SCP_vector;SCP_deque;SCP_list'
|
||||
- key: 'readability-braces-around-statements.ShortStatementLines'
|
||||
|
||||
@@ -6,7 +6,7 @@ on:
|
||||
- 'nightly_*'
|
||||
|
||||
env:
|
||||
QT_VERSION: 5.12.9
|
||||
QT_VERSION: 5.12.12
|
||||
|
||||
jobs:
|
||||
build_linux:
|
||||
@@ -15,36 +15,17 @@ jobs:
|
||||
configuration: [FastDebug, Release]
|
||||
name: Linux
|
||||
runs-on: ubuntu-latest
|
||||
container: ghcr.io/scp-fs2open/linux_build:sha-3d30dc5
|
||||
container: ghcr.io/scp-fs2open/linux_build:sha-1ff82e8
|
||||
steps:
|
||||
# - name: Cache Qt
|
||||
# id: cache-qt-lin
|
||||
# uses: actions/cache@v1
|
||||
# with:
|
||||
# path: ${{ github.workspace }}/../Qt
|
||||
# key: ${{ runner.os }}-QtCache-${{ env.QT_VERSION }}
|
||||
# - name: Install Qt
|
||||
# uses: jurplel/install-qt-action@v2
|
||||
# with:
|
||||
# version: ${{ env.QT_VERSION }}
|
||||
# dir: ${{ github.workspace }}/..
|
||||
# cached: ${{ steps.cache-qt-lin.outputs.cache-hit }}
|
||||
# setup-python: 'false'
|
||||
# aqtversion: ==1.1.3
|
||||
- uses: actions/checkout@v1
|
||||
name: Checkout
|
||||
with:
|
||||
submodules: true
|
||||
- name: Prepare Vulkan SDK
|
||||
uses: humbletim/[email protected]
|
||||
with:
|
||||
vulkan-query-version: 1.3.204.0
|
||||
vulkan-components: Vulkan-Headers, Vulkan-Loader
|
||||
vulkan-use-cache: true
|
||||
- name: Configure CMake
|
||||
env:
|
||||
CONFIGURATION: ${{ matrix.configuration }}
|
||||
COMPILER: gcc-5
|
||||
COMPILER: gcc-9
|
||||
ENABLE_QTFRED: OFF
|
||||
run: $GITHUB_WORKSPACE/ci/linux/configure_cmake.sh
|
||||
- name: Compile
|
||||
working-directory: ./build
|
||||
@@ -64,7 +45,7 @@ jobs:
|
||||
CONFIGURATION: ${{ matrix.configuration }}
|
||||
run: $GITHUB_WORKSPACE/ci/linux/generate_appimage.sh $GITHUB_WORKSPACE/build/install
|
||||
- name: Upload build result
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: linux-${{ matrix.configuration }}
|
||||
path: ${{ github.workspace }}/build/install/*.AppImage
|
||||
@@ -80,12 +61,12 @@ jobs:
|
||||
submodules: true
|
||||
fetch-depth: '0'
|
||||
- name: Download Release builds
|
||||
uses: actions/download-artifact@v1
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: linux-Release
|
||||
path: builds
|
||||
- name: Download FastDebug builds
|
||||
uses: actions/download-artifact@v2
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: linux-FastDebug
|
||||
path: builds
|
||||
@@ -183,7 +164,7 @@ jobs:
|
||||
shell: bash
|
||||
run: ./bin/$CONFIGURATION/unittests --gtest_shuffle
|
||||
- name: Upload build result
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: windows-${{ matrix.configuration }}-${{ matrix.arch }}-${{ matrix.simd }}
|
||||
path: ${{ github.workspace }}/build/install/*
|
||||
@@ -203,12 +184,12 @@ jobs:
|
||||
submodules: true
|
||||
fetch-depth: '0'
|
||||
- name: Download Release builds
|
||||
uses: actions/download-artifact@v1
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: windows-Release-${{ matrix.arch }}-${{ matrix.simd }}
|
||||
path: builds
|
||||
- name: Download FastDebug builds
|
||||
uses: actions/download-artifact@v2
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: windows-FastDebug-${{ matrix.arch }}-${{ matrix.simd }}
|
||||
path: builds
|
||||
@@ -234,7 +215,7 @@ jobs:
|
||||
matrix:
|
||||
configuration: [FastDebug, Release]
|
||||
compiler: [clang]
|
||||
arch: [x86_64]
|
||||
arch: [x86_64, arm64]
|
||||
name: Mac
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
@@ -276,6 +257,7 @@ jobs:
|
||||
COMPILER: ${{ matrix.compiler }}
|
||||
ARCHITECTURE: ${{ matrix.arch }}
|
||||
JOB_CMAKE_OPTIONS: ${{ matrix.cmake_options }}
|
||||
ENABLE_QTFRED: OFF
|
||||
run: $GITHUB_WORKSPACE/ci/linux/configure_cmake.sh
|
||||
- name: Compile
|
||||
working-directory: ./build
|
||||
@@ -284,23 +266,39 @@ jobs:
|
||||
working-directory: ./build
|
||||
env:
|
||||
CONFIGURATION: ${{ matrix.configuration }}
|
||||
ARCH: ${{ matrix.arch }}
|
||||
XDG_RUNTIME_DIR: /root
|
||||
run: $GITHUB_WORKSPACE/ci/linux/run_tests.sh
|
||||
- name: Sign builds
|
||||
working-directory: ./build/bin
|
||||
run: |
|
||||
# make sure OpenAL framework is signed
|
||||
find . -name OpenAL -type f | while read xx; do codesign --force -s - $xx; done
|
||||
find . -name OpenAL.framework -type d | while read xx; do codesign --force -s - $xx; done
|
||||
# make sure dylibs are signed
|
||||
find . -name \*.dylib -type f | while read xx; do codesign --force -s - $xx; done
|
||||
# sign binaries
|
||||
find . -perm +111 -type f | grep MacOS | while read xx; do codesign --force -s - $xx; done
|
||||
# sign apps
|
||||
find . -name \*.app -maxdepth 1 | while read xx; do codesign --force -s - $xx; done
|
||||
- name: Package build result
|
||||
working-directory: ./build/bin
|
||||
# Use GNU tar here (part of runner image) to avoid weird corruption bug with bsdtar
|
||||
# Ref: https://github.com/actions/runner-images/issues/2619
|
||||
run: gtar -cvzf macos-build-${{ matrix.configuration }}.tgz *.app
|
||||
run: gtar -cvzf macos-build-${{ matrix.configuration }}-${{ matrix.arch }}.tgz *.app
|
||||
- name: Upload build result
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: mac-${{ matrix.configuration }}
|
||||
path: ${{ github.workspace }}/build/bin/macos-build-${{ matrix.configuration }}.tgz
|
||||
name: mac-${{ matrix.configuration }}-${{ matrix.arch }}
|
||||
path: ${{ github.workspace }}/build/bin/macos-build-${{ matrix.configuration }}-${{ matrix.arch }}.tgz
|
||||
mac_zip:
|
||||
name: Build Mac distribution zip
|
||||
needs: build_mac
|
||||
runs-on: ubuntu-latest
|
||||
container: ghcr.io/scp-fs2open/sftp_upload:sha-748b19d
|
||||
strategy:
|
||||
matrix:
|
||||
arch: [x86_64, arm64]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
name: Checkout
|
||||
@@ -309,22 +307,24 @@ jobs:
|
||||
fetch-depth: '0'
|
||||
ref: '${{ github.ref }}'
|
||||
- name: Download Release builds
|
||||
uses: actions/download-artifact@v2
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: mac-Release
|
||||
name: mac-Release-${{ matrix.arch }}
|
||||
path: builds
|
||||
- name: Download FastDebug builds
|
||||
uses: actions/download-artifact@v2
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: mac-FastDebug
|
||||
name: mac-FastDebug-${{ matrix.arch }}
|
||||
path: builds
|
||||
- name: Unpack builds
|
||||
working-directory: ./builds
|
||||
run: |
|
||||
tar -xvzf macos-build-Release.tgz
|
||||
tar -xvzf macos-build-FastDebug.tgz
|
||||
tar -xvzf macos-build-Release-${{ matrix.arch }}.tgz
|
||||
tar -xvzf macos-build-FastDebug-${{ matrix.arch }}.tgz
|
||||
- name: Create Distribution package
|
||||
working-directory: ./builds
|
||||
env:
|
||||
ARCH: ${{ matrix.arch }}
|
||||
run: $GITHUB_WORKSPACE/ci/linux/create_dist_pack.sh Mac
|
||||
- name: Upload result package
|
||||
working-directory: ./builds
|
||||
|
||||
@@ -6,7 +6,7 @@ on:
|
||||
- 'release_*'
|
||||
|
||||
env:
|
||||
QT_VERSION: 5.12.9
|
||||
QT_VERSION: 5.12.12
|
||||
|
||||
jobs:
|
||||
create_release:
|
||||
@@ -44,65 +44,19 @@ jobs:
|
||||
name: Linux
|
||||
needs: create_release # Don't run this job until create_release is done and successful
|
||||
runs-on: ubuntu-latest
|
||||
container: ghcr.io/scp-fs2open/linux_build:sha-3d30dc5
|
||||
container: ghcr.io/scp-fs2open/linux_build:sha-1ff82e8
|
||||
steps:
|
||||
# - name: Cache Qt
|
||||
# id: cache-qt-lin
|
||||
# uses: actions/cache@v1
|
||||
# cache the Qt directory so we don't have to reinstall it every time
|
||||
# cache.inputs:
|
||||
# path - A list of files, directories, and wildcard patterns to cache and restore. See @actions/glob for supported patterns.
|
||||
# key - An explicit key for restoring and saving the cache
|
||||
# restore-keys - An ordered list of keys to use for restoring the cache if no cache hit occurred for key
|
||||
# cache.outputs:
|
||||
# cache-hit true when an exact match was found for the key, false otherwise.
|
||||
# with:
|
||||
# path: ${{ github.workspace }}/../Qt
|
||||
# key: ${{ runner.os }}-QtCache-${{ env.QT_VERSION }}
|
||||
# - name: Install Qt
|
||||
# uses: jurplel/install-qt-action@v2
|
||||
# installs Qt in the action workflow
|
||||
# install-qt-action.inputs:
|
||||
# version desired qt version to install
|
||||
# host Host platform of Qt, default to platform used by runs-on
|
||||
# target target platform of Qt, default to desktop
|
||||
# arch target architecture of Qt, only used for windows or android builds
|
||||
# dir root dir Qt will be installed to
|
||||
# install-deps if true, auto-install dependencies on linux. Default true
|
||||
# modules whitespace delimited list string of additional addon modules to install
|
||||
# archives whitespace delimited list string of Qt archives to install
|
||||
# cached if true, Don't download Qt but set ENVARs; use with cache.outputs.cache-hit
|
||||
# setup-python Set to false to skip using setup-python to find/download a valid python version
|
||||
# set-env if true, set ENVARs; default = false
|
||||
# aqtversion version of aqtinstall to use; default = 2.0.0
|
||||
# py7zrversion version of py7zr to use; default = 0.16.1
|
||||
# extra additional arguments to pass to aqinstall
|
||||
# ENVARS set:
|
||||
# Qt5_DIR / Qt6_DIR
|
||||
# Qt bin dir appended to PATH
|
||||
# QT_PLUGIN_PATH, QML2_IMPORT_PATH, PKG_CONFIG_PATH, LD_LIBRARY_PATH
|
||||
# with:
|
||||
# version: ${{ env.QT_VERSION }}
|
||||
# dir: ${{ github.workspace }}/..
|
||||
# cached: ${{ steps.cache-qt-lin.outputs.cache-hit }}
|
||||
# setup-python: 'false'
|
||||
# aqtversion: ==1.1.3
|
||||
- uses: actions/checkout@v1
|
||||
# checks-out your repository under $GITHUB_WORKSPACE, so your workflow can access it.
|
||||
name: Checkout
|
||||
with:
|
||||
submodules: true # `true` to checkout submodules, `recursive` to recursively checkout submodules
|
||||
ref: '${{ github.ref }}'
|
||||
- name: Prepare Vulkan SDK
|
||||
uses: humbletim/[email protected]
|
||||
with:
|
||||
vulkan-query-version: 1.3.204.0
|
||||
vulkan-components: Vulkan-Headers, Vulkan-Loader
|
||||
vulkan-use-cache: true
|
||||
- name: Configure CMake
|
||||
env:
|
||||
CONFIGURATION: ${{ matrix.configuration }}
|
||||
COMPILER: gcc-5
|
||||
COMPILER: gcc-9
|
||||
ENABLE_QTFRED: OFF
|
||||
run: $GITHUB_WORKSPACE/ci/linux/configure_cmake.sh
|
||||
- name: Compile
|
||||
working-directory: ./build
|
||||
@@ -122,7 +76,7 @@ jobs:
|
||||
CONFIGURATION: ${{ matrix.configuration }}
|
||||
run: $GITHUB_WORKSPACE/ci/linux/generate_appimage.sh $GITHUB_WORKSPACE/build/install
|
||||
- name: Upload build result
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
# Upload the url file for use with other runners
|
||||
# upload-artifact.inputs:
|
||||
# if-no-files-found=warn What to do if path fails to find any files.
|
||||
@@ -149,13 +103,13 @@ jobs:
|
||||
ref: '${{ github.ref }}'
|
||||
- name: Download Release builds
|
||||
# Grab the release builds
|
||||
uses: actions/download-artifact@v2
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: linux-Release
|
||||
path: builds
|
||||
- name: Download FastDebug builds
|
||||
# Grab the debug builds
|
||||
uses: actions/download-artifact@v2
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: linux-FastDebug
|
||||
path: builds
|
||||
@@ -166,7 +120,7 @@ jobs:
|
||||
run: $GITHUB_WORKSPACE/ci/linux/create_dist_pack.sh Linux
|
||||
- name: Upload result package
|
||||
# Stash the result to artifact filespace
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ steps.generate_package.outputs.package_name }}
|
||||
path: ${{ steps.generate_package.outputs.package_path }}
|
||||
@@ -266,7 +220,7 @@ jobs:
|
||||
shell: bash
|
||||
run: ./bin/$CONFIGURATION/unittests --gtest_shuffle
|
||||
- name: Upload build result
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: windows-${{ matrix.configuration }}-${{ matrix.arch }}-${{ matrix.simd }}
|
||||
path: ${{ github.workspace }}/build/install/*
|
||||
@@ -290,13 +244,13 @@ jobs:
|
||||
fetch-depth: '0'
|
||||
ref: '${{ github.ref }}'
|
||||
- name: Download Release builds
|
||||
uses: actions/download-artifact@v2
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: windows-Release-${{ matrix.arch }}-${{ matrix.simd }}
|
||||
path: builds
|
||||
|
||||
- name: Download FastDebug builds
|
||||
uses: actions/download-artifact@v2
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: windows-FastDebug-${{ matrix.arch }}-${{ matrix.simd }}
|
||||
path: builds
|
||||
@@ -311,13 +265,13 @@ jobs:
|
||||
run: $GITHUB_WORKSPACE/ci/linux/create_dist_pack.sh Windows
|
||||
|
||||
- name: Upload result package
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ steps.generate_package.outputs.package_name }}
|
||||
path: ${{ steps.generate_package.outputs.package_path }}
|
||||
|
||||
- name: Upload debug package
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ steps.generate_package.outputs.debug_name }}
|
||||
path: ${{ steps.generate_package.outputs.debug_path }}
|
||||
@@ -336,7 +290,7 @@ jobs:
|
||||
matrix:
|
||||
configuration: [FastDebug, Release]
|
||||
compiler: [clang]
|
||||
arch: [x86_64]
|
||||
arch: [x86_64, arm64]
|
||||
name: Mac
|
||||
needs: create_release
|
||||
runs-on: macos-latest
|
||||
@@ -373,6 +327,7 @@ jobs:
|
||||
COMPILER: ${{ matrix.compiler }}
|
||||
ARCHITECTURE: ${{ matrix.arch }}
|
||||
JOB_CMAKE_OPTIONS: ${{ matrix.cmake_options }}
|
||||
ENABLE_QTFRED: OFF
|
||||
run: $GITHUB_WORKSPACE/ci/linux/configure_cmake.sh
|
||||
- name: Compile
|
||||
working-directory: ./build
|
||||
@@ -381,23 +336,39 @@ jobs:
|
||||
working-directory: ./build
|
||||
env:
|
||||
CONFIGURATION: ${{ matrix.configuration }}
|
||||
ARCH: ${{ matrix.arch }}
|
||||
XDG_RUNTIME_DIR: /root
|
||||
run: $GITHUB_WORKSPACE/ci/linux/run_tests.sh
|
||||
- name: Sign builds
|
||||
working-directory: ./build/bin
|
||||
run: |
|
||||
# make sure OpenAL framework is signed
|
||||
find . -name OpenAL -type f | while read xx; do codesign --force -s - $xx; done
|
||||
find . -name OpenAL.framework -type d | while read xx; do codesign --force -s - $xx; done
|
||||
# make sure dylibs are signed
|
||||
find . -name \*.dylib -type f | while read xx; do codesign --force -s - $xx; done
|
||||
# sign binaries
|
||||
find . -perm +111 -type f | grep MacOS | while read xx; do codesign --force -s - $xx; done
|
||||
# sign apps
|
||||
find . -name \*.app -maxdepth 1 | while read xx; do codesign --force -s - $xx; done
|
||||
- name: Package build result
|
||||
working-directory: ./build/bin
|
||||
# Use GNU tar here (part of runner image) to avoid weird corruption bug with bsdtar
|
||||
# Ref: https://github.com/actions/runner-images/issues/2619
|
||||
run: gtar -cvzf macos-build-${{ matrix.configuration }}.tgz *.app
|
||||
run: gtar -cvzf macos-build-${{ matrix.configuration }}-${{ matrix.arch }}.tgz *.app
|
||||
- name: Upload build result
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: mac-${{ matrix.configuration }}
|
||||
path: ${{ github.workspace }}/build/bin/macos-build-${{ matrix.configuration }}.tgz
|
||||
name: mac-${{ matrix.configuration }}-${{ matrix.arch }}
|
||||
path: ${{ github.workspace }}/build/bin/macos-build-${{ matrix.configuration }}-${{ matrix.arch }}.tgz
|
||||
mac_zip:
|
||||
name: Build Mac distribution zip
|
||||
needs: build_mac
|
||||
runs-on: ubuntu-latest
|
||||
container: ghcr.io/scp-fs2open/sftp_upload:sha-748b19d
|
||||
strategy:
|
||||
matrix:
|
||||
arch: [x86_64, arm64]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
name: Checkout
|
||||
@@ -406,26 +377,28 @@ jobs:
|
||||
fetch-depth: '0'
|
||||
ref: '${{ github.ref }}'
|
||||
- name: Download Release builds
|
||||
uses: actions/download-artifact@v2
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: mac-Release
|
||||
name: mac-Release-${{ matrix.arch }}
|
||||
path: builds
|
||||
- name: Download FastDebug builds
|
||||
uses: actions/download-artifact@v2
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: mac-FastDebug
|
||||
name: mac-FastDebug-${{ matrix.arch }}
|
||||
path: builds
|
||||
- name: Unpack builds
|
||||
working-directory: ./builds
|
||||
run: |
|
||||
tar -xvzf macos-build-Release.tgz
|
||||
tar -xvzf macos-build-FastDebug.tgz
|
||||
tar -xvzf macos-build-Release-${{ matrix.arch }}.tgz
|
||||
tar -xvzf macos-build-FastDebug-${{ matrix.arch }}.tgz
|
||||
- name: Create Distribution package
|
||||
id: generate_package
|
||||
working-directory: ./builds
|
||||
env:
|
||||
ARCH: ${{ matrix.arch }}
|
||||
run: $GITHUB_WORKSPACE/ci/linux/create_dist_pack.sh Mac
|
||||
- name: Upload result package
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ steps.generate_package.outputs.package_name }}
|
||||
path: ${{ steps.generate_package.outputs.package_path }}
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
name: Publish Standalone docker image
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'nightly_*'
|
||||
- 'release_*'
|
||||
|
||||
jobs:
|
||||
build_images:
|
||||
if: github.repository == 'scp-fs2open/fs2open.github.com'
|
||||
strategy:
|
||||
matrix:
|
||||
configuration: [FastDebug, Release]
|
||||
include:
|
||||
- configuration: FastDebug
|
||||
tag_suffix: -debug
|
||||
- configuration: Release
|
||||
tag_suffix: ""
|
||||
fail-fast: false
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
name: Checkout
|
||||
with:
|
||||
submodules: true
|
||||
- name: Prepare Vulkan SDK
|
||||
uses: humbletim/[email protected]
|
||||
with:
|
||||
vulkan-query-version: 1.3.204.0
|
||||
vulkan-components: Vulkan-Headers, Vulkan-Loader
|
||||
vulkan-use-cache: true
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
|
||||
- name: Docker meta
|
||||
id: docker_meta
|
||||
uses: crazy-max/ghaction-docker-meta@v1
|
||||
with:
|
||||
images: ghcr.io/scp-fs2open/standalone_server
|
||||
tag-latest: false
|
||||
|
||||
- name: Login to GitHub Docker Registry
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.CR_PAT }}
|
||||
- name: Build and push
|
||||
id: docker_build
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
context: .
|
||||
file: ./docker/standalone/Dockerfile
|
||||
push: true
|
||||
tags: ${{ steps.docker_meta.outputs.tags }}${{ matrix.tag_suffix }}
|
||||
labels: ${{ steps.docker_meta.outputs.labels }}
|
||||
build-args: |
|
||||
build_type=${{ matrix.configuration }}
|
||||
@@ -6,7 +6,7 @@ on:
|
||||
- 'test/*'
|
||||
|
||||
env:
|
||||
QT_VERSION: 5.12.9
|
||||
QT_VERSION: 5.12.12
|
||||
|
||||
jobs:
|
||||
build_linux:
|
||||
@@ -15,22 +15,8 @@ jobs:
|
||||
configuration: [FastDebug, Release]
|
||||
name: Linux
|
||||
runs-on: ubuntu-latest
|
||||
container: ghcr.io/scp-fs2open/linux_build:sha-3d30dc5
|
||||
container: ghcr.io/scp-fs2open/linux_build:sha-1ff82e8
|
||||
steps:
|
||||
# - name: Cache Qt
|
||||
# id: cache-qt-lin
|
||||
# uses: actions/cache@v1
|
||||
# with:
|
||||
# path: ${{ github.workspace }}/../Qt
|
||||
# key: ${{ runner.os }}-QtCache-${{ env.QT_VERSION }}
|
||||
# - name: Install Qt
|
||||
# uses: jurplel/install-qt-action@v2
|
||||
# with:
|
||||
# version: ${{ env.QT_VERSION }}
|
||||
# dir: ${{ github.workspace }}/..
|
||||
# cached: ${{ steps.cache-qt-lin.outputs.cache-hit }}
|
||||
# setup-python: 'false'
|
||||
# aqtversion: ==1.1.3
|
||||
- uses: actions/checkout@v1
|
||||
name: Checkout
|
||||
with:
|
||||
@@ -41,16 +27,11 @@ jobs:
|
||||
[[ "${{ github.ref }}" =~ ^refs\/heads\/test\/(.*)$ ]]
|
||||
# Override the revision string so that the builds are named correctly
|
||||
echo "set(FSO_VERSION_REVISION_STR ${BASH_REMATCH[1]})" > "version_override.cmake"
|
||||
- name: Prepare Vulkan SDK
|
||||
uses: humbletim/[email protected]
|
||||
with:
|
||||
vulkan-query-version: 1.3.204.0
|
||||
vulkan-components: Vulkan-Headers, Vulkan-Loader
|
||||
vulkan-use-cache: true
|
||||
- name: Configure CMake
|
||||
env:
|
||||
CONFIGURATION: ${{ matrix.configuration }}
|
||||
COMPILER: gcc-5
|
||||
COMPILER: gcc-9
|
||||
ENABLE_QTFRED: OFF
|
||||
run: $GITHUB_WORKSPACE/ci/linux/configure_cmake.sh
|
||||
- name: Compile
|
||||
working-directory: ./build
|
||||
@@ -70,7 +51,7 @@ jobs:
|
||||
CONFIGURATION: ${{ matrix.configuration }}
|
||||
run: $GITHUB_WORKSPACE/ci/linux/generate_appimage.sh $GITHUB_WORKSPACE/build/install
|
||||
- name: Upload build result
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: linux-${{ matrix.configuration }}
|
||||
path: ${{ github.workspace }}/build/install/*.AppImage
|
||||
@@ -87,12 +68,12 @@ jobs:
|
||||
fetch-depth: '0'
|
||||
ref: '${{ github.ref }}'
|
||||
- name: Download Release builds
|
||||
uses: actions/download-artifact@v1
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: linux-Release
|
||||
path: builds
|
||||
- name: Download FastDebug builds
|
||||
uses: actions/download-artifact@v2
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: linux-FastDebug
|
||||
path: builds
|
||||
@@ -196,7 +177,7 @@ jobs:
|
||||
shell: bash
|
||||
run: ./bin/$CONFIGURATION/unittests --gtest_shuffle
|
||||
- name: Upload build result
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: windows-${{ matrix.configuration }}-${{ matrix.arch }}-${{ matrix.simd }}
|
||||
path: ${{ github.workspace }}/build/install/*
|
||||
@@ -217,12 +198,12 @@ jobs:
|
||||
fetch-depth: '0'
|
||||
ref: '${{ github.ref }}'
|
||||
- name: Download Release builds
|
||||
uses: actions/download-artifact@v1
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: windows-Release-${{ matrix.arch }}-${{ matrix.simd }}
|
||||
path: builds
|
||||
- name: Download FastDebug builds
|
||||
uses: actions/download-artifact@v2
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: windows-FastDebug-${{ matrix.arch }}-${{ matrix.simd }}
|
||||
path: builds
|
||||
@@ -248,7 +229,7 @@ jobs:
|
||||
matrix:
|
||||
configuration: [FastDebug, Release]
|
||||
compiler: [clang]
|
||||
arch: [x86_64]
|
||||
arch: [x86_64, arm64]
|
||||
name: Mac
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
@@ -289,6 +270,7 @@ jobs:
|
||||
CONFIGURATION: ${{ matrix.configuration }}
|
||||
COMPILER: ${{ matrix.compiler }}
|
||||
ARCHITECTURE: ${{ matrix.arch }}
|
||||
ENABLE_QTFRED: OFF
|
||||
run: $GITHUB_WORKSPACE/ci/linux/configure_cmake.sh
|
||||
- name: Compile
|
||||
working-directory: ./build
|
||||
@@ -297,23 +279,39 @@ jobs:
|
||||
working-directory: ./build
|
||||
env:
|
||||
CONFIGURATION: ${{ matrix.configuration }}
|
||||
ARCH: ${{ matrix.arch }}
|
||||
XDG_RUNTIME_DIR: /root
|
||||
run: $GITHUB_WORKSPACE/ci/linux/run_tests.sh
|
||||
- name: Sign builds
|
||||
working-directory: ./build/bin
|
||||
run: |
|
||||
# make sure OpenAL framework is signed
|
||||
find . -name OpenAL -type f | while read xx; do codesign --force -s - $xx; done
|
||||
find . -name OpenAL.framework -type d | while read xx; do codesign --force -s - $xx; done
|
||||
# make sure dylibs are signed
|
||||
find . -name \*.dylib -type f | while read xx; do codesign --force -s - $xx; done
|
||||
# sign binaries
|
||||
find . -perm +111 -type f | grep MacOS | while read xx; do codesign --force -s - $xx; done
|
||||
# sign apps
|
||||
find . -name \*.app -maxdepth 1 | while read xx; do codesign --force -s - $xx; done
|
||||
- name: Package build result
|
||||
working-directory: ./build/bin
|
||||
# Use GNU tar here (part of runner image) to avoid weird corruption bug with bsdtar
|
||||
# Ref: https://github.com/actions/runner-images/issues/2619
|
||||
run: gtar -cvzf macos-build-${{ matrix.configuration }}.tgz *.app
|
||||
run: gtar -cvzf macos-build-${{ matrix.configuration }}-${{ matrix.arch }}.tgz *.app
|
||||
- name: Upload build result
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: mac-${{ matrix.configuration }}
|
||||
path: ${{ github.workspace }}/build/bin/macos-build-${{ matrix.configuration }}.tgz
|
||||
name: mac-${{ matrix.configuration }}-${{ matrix.arch }}
|
||||
path: ${{ github.workspace }}/build/bin/macos-build-${{ matrix.configuration }}-${{ matrix.arch }}.tgz
|
||||
mac_zip:
|
||||
name: Build Mac distribution zip
|
||||
needs: build_mac
|
||||
runs-on: ubuntu-latest
|
||||
container: ghcr.io/scp-fs2open/sftp_upload:sha-748b19d
|
||||
strategy:
|
||||
matrix:
|
||||
arch: [x86_64, arm64]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
name: Checkout
|
||||
@@ -322,22 +320,24 @@ jobs:
|
||||
fetch-depth: '0'
|
||||
ref: '${{ github.ref }}'
|
||||
- name: Download Release builds
|
||||
uses: actions/download-artifact@v2
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: mac-Release
|
||||
name: mac-Release-${{ matrix.arch }}
|
||||
path: builds
|
||||
- name: Download FastDebug builds
|
||||
uses: actions/download-artifact@v2
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: mac-FastDebug
|
||||
name: mac-FastDebug-${{ matrix.arch }}
|
||||
path: builds
|
||||
- name: Unpack builds
|
||||
working-directory: ./builds
|
||||
run: |
|
||||
tar -xvzf macos-build-Release.tgz
|
||||
tar -xvzf macos-build-FastDebug.tgz
|
||||
tar -xvzf macos-build-Release-${{ matrix.arch }}.tgz
|
||||
tar -xvzf macos-build-FastDebug-${{ matrix.arch }}.tgz
|
||||
- name: Create Distribution package
|
||||
working-directory: ./builds
|
||||
env:
|
||||
ARCH: ${{ matrix.arch }}
|
||||
run: $GITHUB_WORKSPACE/ci/linux/create_dist_pack.sh Mac
|
||||
- name: Upload result package
|
||||
working-directory: ./builds
|
||||
|
||||
@@ -6,42 +6,27 @@ on:
|
||||
- master
|
||||
|
||||
env:
|
||||
QT_VERSION: 5.12.9
|
||||
QT_VERSION: 5.12.12
|
||||
|
||||
jobs:
|
||||
build_linux:
|
||||
strategy:
|
||||
matrix:
|
||||
configuration: [Debug, Release]
|
||||
compiler: [gcc-5, gcc-10]
|
||||
compiler: [gcc-9, gcc-13, clang-16]
|
||||
cmake_options: [""]
|
||||
include:
|
||||
# Also include configurations that check if the code compiles without the graphics backends
|
||||
- configuration: Debug
|
||||
compiler: gcc-10
|
||||
compiler: gcc-13
|
||||
cmake_options: -DFSO_BUILD_WITH_OPENGL=OFF -DFSO_BUILD_WITH_VULKAN=OFF
|
||||
- configuration: Release
|
||||
compiler: gcc-10
|
||||
compiler: gcc-13
|
||||
cmake_options: -DFSO_BUILD_WITH_OPENGL=OFF -DFSO_BUILD_WITH_VULKAN=OFF
|
||||
name: Linux
|
||||
runs-on: ubuntu-latest
|
||||
container: ghcr.io/scp-fs2open/linux_build:sha-3d30dc5
|
||||
container: ghcr.io/scp-fs2open/linux_build:sha-1ff82e8
|
||||
steps:
|
||||
# - name: Cache Qt
|
||||
# id: cache-qt-lin
|
||||
# uses: actions/cache@v1
|
||||
# with:
|
||||
# path: ${{ github.workspace }}/../Qt
|
||||
# key: ${{ runner.os }}-QtCache-${{ env.QT_VERSION }}
|
||||
# - name: Install Qt
|
||||
# uses: jurplel/install-qt-action@v2
|
||||
# with:
|
||||
# version: ${{ env.QT_VERSION }}
|
||||
# dir: ${{ github.workspace }}/..
|
||||
# cached: ${{ steps.cache-qt-lin.outputs.cache-hit }}
|
||||
# setup-python: 'false'
|
||||
# aqtversion: ==1.1.3
|
||||
|
||||
- uses: actions/checkout@v1
|
||||
name: Checkout
|
||||
with:
|
||||
@@ -50,13 +35,22 @@ jobs:
|
||||
uses: hendrikmuhs/ccache-action@v1
|
||||
with:
|
||||
key: ${{ runner.os }}-${{ matrix.configuration }}-${{ matrix.compiler }}
|
||||
- name: Configure ccache
|
||||
run: |
|
||||
ccache --set-config=sloppiness=pch_defines,time_macros
|
||||
ccache -p
|
||||
|
||||
- name: Configure CMake
|
||||
env:
|
||||
CONFIGURATION: ${{ matrix.configuration }}
|
||||
COMPILER: ${{ matrix.compiler }}
|
||||
JOB_CMAKE_OPTIONS: ${{ matrix.cmake_options }}
|
||||
CCACHE_PATH: /usr/local/bin/ccache
|
||||
ENABLE_QTFRED: ON
|
||||
Qt5_DIR: /qt/${{ env.QT_VERSION }}/gcc_64/lib/cmake/Qt5
|
||||
run: $GITHUB_WORKSPACE/ci/linux/configure_cmake.sh
|
||||
- name: Compile
|
||||
working-directory: ./build
|
||||
run: LD_LIBRARY_PATH=$Qt5_DIR/lib:$LD_LIBRARY_PATH ninja -k 20 all
|
||||
- name: Show CCache statistics
|
||||
run: ccache --show-stats
|
||||
@@ -3,41 +3,27 @@ name: Check a pull request
|
||||
on: [pull_request]
|
||||
|
||||
env:
|
||||
QT_VERSION: 5.12.9
|
||||
QT_VERSION: 5.12.12
|
||||
|
||||
jobs:
|
||||
build_linux:
|
||||
strategy:
|
||||
matrix:
|
||||
configuration: [Debug, Release]
|
||||
compiler: [gcc-5, gcc-10, clang-9]
|
||||
compiler: [gcc-9, gcc-13, clang-16]
|
||||
cmake_options: [""]
|
||||
include:
|
||||
# Also include configurations that check if the code compiles without the graphics backends
|
||||
- configuration: Debug
|
||||
compiler: gcc-10
|
||||
compiler: gcc-13
|
||||
cmake_options: -DFSO_BUILD_WITH_OPENGL=OFF -DFSO_BUILD_WITH_VULKAN=OFF
|
||||
- configuration: Release
|
||||
compiler: gcc-10
|
||||
compiler: gcc-13
|
||||
cmake_options: -DFSO_BUILD_WITH_OPENGL=OFF -DFSO_BUILD_WITH_VULKAN=OFF
|
||||
name: Linux
|
||||
runs-on: ubuntu-latest
|
||||
container: ghcr.io/scp-fs2open/linux_build:sha-3d30dc5
|
||||
container: ghcr.io/scp-fs2open/linux_build:sha-1ff82e8
|
||||
steps:
|
||||
# - name: Cache Qt
|
||||
# id: cache-qt-lin
|
||||
# uses: actions/cache@v1
|
||||
# with:
|
||||
# path: ${{ github.workspace }}/../Qt
|
||||
# key: ${{ runner.os }}-QtCache-${{ env.QT_VERSION }}
|
||||
# - name: Install Qt
|
||||
# uses: jurplel/install-qt-action@v2
|
||||
# with:
|
||||
# version: ${{ env.QT_VERSION }}
|
||||
# dir: ${{ github.workspace }}/..
|
||||
# cached: ${{ steps.cache-qt-lin.outputs.cache-hit }}
|
||||
# setup-python: 'false'
|
||||
# aqtversion: ==1.1.3
|
||||
- uses: actions/checkout@v1
|
||||
name: Checkout
|
||||
with:
|
||||
@@ -47,17 +33,18 @@ jobs:
|
||||
uses: hendrikmuhs/ccache-action@v1
|
||||
with:
|
||||
key: ${{ runner.os }}-${{ matrix.configuration }}-${{ matrix.compiler }}
|
||||
- name: Prepare Vulkan SDK
|
||||
uses: humbletim/[email protected]
|
||||
with:
|
||||
vulkan-query-version: 1.3.204.0
|
||||
vulkan-components: Vulkan-Headers, Vulkan-Loader
|
||||
vulkan-use-cache: true
|
||||
save: false # Caches are created by a separate job and only restored for PRs
|
||||
verbose: 1
|
||||
- name: Configure ccache
|
||||
run: ccache --set-config=sloppiness=pch_defines,time_macros
|
||||
- name: Configure CMake
|
||||
env:
|
||||
CONFIGURATION: ${{ matrix.configuration }}
|
||||
COMPILER: ${{ matrix.compiler }}
|
||||
JOB_CMAKE_OPTIONS: ${{ matrix.cmake_options }}
|
||||
CCACHE_PATH: /usr/local/bin/ccache
|
||||
ENABLE_QTFRED: ON
|
||||
Qt5_DIR: /qt/${{ env.QT_VERSION }}/gcc_64/lib/cmake/Qt5
|
||||
run: $GITHUB_WORKSPACE/ci/linux/configure_cmake.sh
|
||||
- name: Compile
|
||||
working-directory: ./build
|
||||
@@ -68,6 +55,8 @@ jobs:
|
||||
CONFIGURATION: ${{ matrix.configuration }}
|
||||
XDG_RUNTIME_DIR: /root
|
||||
run: $GITHUB_WORKSPACE/ci/linux/run_tests.sh
|
||||
- name: Show CCache statistics
|
||||
run: ccache --show-stats
|
||||
- name: Run Clang Tidy
|
||||
# Clang-tidy reuses the precompiled headers so this only makes sense for the clang compilers
|
||||
if: startsWith(matrix.compiler, 'clang-')
|
||||
@@ -182,7 +171,7 @@ jobs:
|
||||
matrix:
|
||||
configuration: [Debug, Release]
|
||||
compiler: [clang]
|
||||
arch: [x86_64]
|
||||
arch: [x86_64, arm64]
|
||||
cmake_options: [""]
|
||||
name: Mac
|
||||
runs-on: macos-latest
|
||||
@@ -210,7 +199,8 @@ jobs:
|
||||
- name: ccache
|
||||
uses: hendrikmuhs/ccache-action@v1
|
||||
with:
|
||||
key: ${{ runner.os }}-${{ matrix.configuration }}-${{ matrix.compiler }}
|
||||
key: ${{ runner.os }}-${{ matrix.configuration }}-${{ matrix.compiler }}-${{ matrix.arch }}
|
||||
save: false # Caches are created by a separate job and only restored for PRs
|
||||
- name: Prepare Vulkan SDK
|
||||
uses: humbletim/[email protected]
|
||||
with:
|
||||
@@ -223,6 +213,7 @@ jobs:
|
||||
COMPILER: ${{ matrix.compiler }}
|
||||
ARCHITECTURE: ${{ matrix.arch }}
|
||||
JOB_CMAKE_OPTIONS: ${{ matrix.cmake_options }}
|
||||
ENABLE_QTFRED: OFF
|
||||
run: $GITHUB_WORKSPACE/ci/linux/configure_cmake.sh
|
||||
- name: Compile
|
||||
working-directory: ./build
|
||||
@@ -231,6 +222,7 @@ jobs:
|
||||
working-directory: ./build
|
||||
env:
|
||||
CONFIGURATION: ${{ matrix.configuration }}
|
||||
ARCH: ${{ matrix.arch }}
|
||||
XDG_RUNTIME_DIR: /root
|
||||
run: $GITHUB_WORKSPACE/ci/linux/run_tests.sh
|
||||
- name: Run Clang Tidy
|
||||
|
||||
+12
-24
@@ -2,40 +2,34 @@ name: Weekly Coverity Scan for Freespace Open
|
||||
# adapted from code by "albert-github" on the doxygen repository
|
||||
# many thanks for figuring this out first so it could be less painful for us!
|
||||
|
||||
# This mode is for testing
|
||||
on: [push, pull_request]
|
||||
#This mode is for testing
|
||||
#on: [push, pull_request]
|
||||
|
||||
# In production, push on a specific schedule
|
||||
#on:
|
||||
# schedule:
|
||||
# - cron: "1 0 * * 5" # Run once per a week on Friday morning (midnight UTC, 4 AM EST), to avoid Coverity's submission limits
|
||||
on:
|
||||
schedule:
|
||||
- cron: "5 0 * * 5" # Run once per a week on Friday morning (midnight UTC, 4 AM EST), to avoid Coverity's submission limits
|
||||
|
||||
env:
|
||||
QT_VERSION: 5.12.9
|
||||
QT_VERSION: 5.12.12
|
||||
coverity_email: [email protected]
|
||||
coverity_token: ${{ secrets.COVERITY_TOKEN }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build FSO With Coverity Wrapper
|
||||
if: github.repository == 'scp-fs2open/fs2open.github.com'
|
||||
runs-on: ${{ matrix.config.os }}
|
||||
container: ghcr.io/scp-fs2open/linux_build:sha-1ff82e8
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
config:
|
||||
- { name: "GCC on ubuntu", os: ubuntu-latest, build_type: "Release" }
|
||||
steps:
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
sudo apt-get install ninja-build
|
||||
sudo apt install cmake libsdl2-dev g++
|
||||
sudo apt-get install libopenal-dev
|
||||
sudo apt-get install -y libudev-dev
|
||||
sudo apt-get install doxygen
|
||||
sudo apt install graphviz
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v1
|
||||
with:
|
||||
submodules: recursive # `true` to checkout submodules, `recursive` to recursively checkout submodules
|
||||
|
||||
@@ -51,17 +45,11 @@ jobs:
|
||||
echo "$(pwd)/cov-scan/bin" >> $GITHUB_PATH
|
||||
echo "NPROC=$(getconf _NPROCESSORS_ONLN)" >> $GITHUB_ENV
|
||||
|
||||
- name: Prepare Vulkan SDK
|
||||
uses: humbletim/[email protected]
|
||||
with:
|
||||
vulkan-query-version: 1.3.204.0
|
||||
vulkan-components: Vulkan-Headers, Vulkan-Loader
|
||||
vulkan-use-cache: true
|
||||
|
||||
- name: Configure CMake for FSO
|
||||
env:
|
||||
CONFIGURATION: Release
|
||||
compiler: gcc-5
|
||||
COMPILER: gcc-9
|
||||
ENABLE_QTFRED: OFF
|
||||
run: $GITHUB_WORKSPACE/ci/linux/configure_cmake.sh
|
||||
|
||||
- name: Build FSO with Coverity Wrapper
|
||||
+3
-14
@@ -47,20 +47,6 @@ endif()
|
||||
|
||||
PROJECT(FS2_Open LANGUAGES ${FSO_LANGUAGES})
|
||||
|
||||
find_program(CCACHE_PROGRAM ccache)
|
||||
# Currently only GCC support ccache properly without generating additional warnings
|
||||
# Enable ccache on Mac even for clang
|
||||
if(CCACHE_PROGRAM AND ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR APPLE))
|
||||
if(NOT CMAKE_C_COMPILER_LAUNCHER)
|
||||
message(STATUS "Using ccache for C compilation: ${CCACHE_PROGRAM}")
|
||||
SET(CMAKE_C_COMPILER_LAUNCHER ${CCACHE_PROGRAM})
|
||||
endif()
|
||||
if(NOT CMAKE_CXX_COMPILER_LAUNCHER)
|
||||
message(STATUS "Using ccache for C++ compilation: ${CCACHE_PROGRAM}")
|
||||
SET(CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE_PROGRAM})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
IF(CMAKE_CROSSCOMPILING)
|
||||
SET(IMPORT_EXE_DIR "IMPORT_EXE_DIR-NOTFOUND" CACHE FILEPATH "Required for a cross compiling build, point to binary directory of a cmake build for the real OS")
|
||||
INCLUDE(${IMPORT_EXE_DIR}/ImportExecutables.cmake)
|
||||
@@ -141,6 +127,8 @@ OPTION(FSO_BUILD_WITH_OPENGL_DEBUG "Enables debug option for OpenGL" OFF)
|
||||
|
||||
OPTION(FSO_BUILD_WITH_VULKAN "Enable compilation of the Vulkan renderer" OFF)
|
||||
|
||||
OPTION(FSO_BUILD_WITH_OPENXR_DEBUG "Enables debug option for OpenXR" OFF)
|
||||
|
||||
MARK_AS_ADVANCED(FORCE FSO_CMAKE_DEBUG)
|
||||
MARK_AS_ADVANCED(FORCE FSO_BUILD_INCLUDED_LIBS)
|
||||
MARK_AS_ADVANCED(FORCE FSO_USE_OPENALSOFT)
|
||||
@@ -154,6 +142,7 @@ mark_as_advanced(FORCE FSO_BUILD_WITH_FFMPEG)
|
||||
mark_as_advanced(FORCE FSO_BUILD_WITH_OPENGL)
|
||||
mark_as_advanced(FORCE FSO_BUILD_WITH_OPENGL_DEBUG)
|
||||
mark_as_advanced(FORCE FSO_BUILD_WITH_VULKAN)
|
||||
mark_as_advanced(FORCE FSO_BUILD_WITH_OPENXR_DEBUG)
|
||||
|
||||
# Include cotire file from https://github.com/sakra/cotire/
|
||||
include(cotire)
|
||||
|
||||
@@ -5,6 +5,8 @@ set -e
|
||||
SCRIPT=$(readlink -f "$0")
|
||||
HERE=$(dirname "$SCRIPT")
|
||||
|
||||
git config --global --add safe.directory "$GITHUB_WORKSPACE"
|
||||
|
||||
COMMIT_RANGE=$1..$2
|
||||
|
||||
if ! git rev-list $COMMIT_RANGE 2>&1 >/dev/null; then
|
||||
@@ -20,4 +22,4 @@ echo "Running clang-tidy on changed files"
|
||||
git diff -U0 --no-color "$BASE_COMMIT..$2" | \
|
||||
$HERE/clang-tidy-diff.py -path "$(pwd)/build" -p1 \
|
||||
-regex '(code(?!((\/graphics\/shaders\/compiled)|(\/globalincs\/windebug)))|freespace2|qtfred|test|build|tools)\/.*\.(cpp|h)' \
|
||||
-clang-tidy-binary /usr/bin/clang-tidy-9 -j$(nproc) -export-fixes "$(pwd)/clang-fixes.yaml"
|
||||
-clang-tidy-binary /usr/bin/clang-tidy-16 -j$(nproc) -export-fixes "$(pwd)/clang-fixes.yaml"
|
||||
+20
-12
@@ -1,17 +1,16 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
if [ "$COMPILER" = "gcc-5" ]; then
|
||||
export CC=gcc-5
|
||||
export CXX=g++-5
|
||||
if [ "$COMPILER" = "gcc-9" ]; then
|
||||
export CC=gcc-9
|
||||
export CXX=g++-9
|
||||
fi
|
||||
if [ "$COMPILER" = "gcc-10" ]; then
|
||||
export CC=gcc-10
|
||||
export CXX=g++-10
|
||||
if [ "$COMPILER" = "gcc-13" ]; then
|
||||
export CC=gcc-13
|
||||
export CXX=g++-13
|
||||
fi
|
||||
if [ "$COMPILER" = "clang-9" ]; then
|
||||
# Work around bug in clang that uses the wrong installation directory: https://bugs.llvm.org/show_bug.cgi?id=47460
|
||||
export CC=$(readlink -f $(which clang-9))
|
||||
export CXX=$(readlink -f $(which clang++-9))
|
||||
if [ "$COMPILER" = "clang-16" ]; then
|
||||
export CC=clang-16
|
||||
export CXX=clang++-16
|
||||
fi
|
||||
|
||||
LD_LIBRARY_PATH=$Qt5_DIR/lib:$LD_LIBRARY_PATH
|
||||
@@ -34,6 +33,11 @@ if [[ "$COMPILER" =~ ^clang.*$ ]]; then
|
||||
CXXFLAGS="$CXXFLAGS -Qunused-arguments"
|
||||
fi
|
||||
|
||||
if [ ! "$CCACHE_PATH" = "" ]; then
|
||||
echo "Using ccache at $CCACHE_PATH"
|
||||
CMAKE_OPTIONS="$CMAKE_OPTIONS -DCMAKE_C_COMPILER_LAUNCHER=$CCACHE_PATH -DCMAKE_CXX_COMPILER_LAUNCHER=$CCACHE_PATH"
|
||||
fi
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
|
||||
@@ -44,7 +48,11 @@ export LD_LIBRARY_PATH
|
||||
if [ "$RUNNER_OS" = "macOS" ]; then
|
||||
brew install ninja
|
||||
fi
|
||||
|
||||
# CMAKE_JOB_POOLS and CMAKE_JOB_POOL_LINK ensure that when using ninja, link operations are done sequentially
|
||||
# we have some build rules that do not play nice with parallel invocation and that fixes these issues
|
||||
|
||||
cmake -G Ninja -DFSO_FATAL_WARNINGS=ON -DCMAKE_EXPORT_COMPILE_COMMANDS=ON $CMAKE_OPTIONS $PLATFORM_CMAKE_OPTIONS \
|
||||
-DCMAKE_INSTALL_PREFIX="$(pwd)/install" -DCMAKE_BUILD_TYPE=$CONFIGURATION \
|
||||
-DFFMPEG_USE_PRECOMPILED=ON -DFSO_BUILD_TESTS=ON -DFSO_BUILD_INCLUDED_LIBS=ON -DFSO_BUILD_QTFRED=OFF \
|
||||
-DSHADERS_ENABLE_COMPILATION=ON ..
|
||||
-DFFMPEG_USE_PRECOMPILED=ON -DFSO_BUILD_TESTS=ON -DFSO_BUILD_INCLUDED_LIBS=ON -DFSO_BUILD_QTFRED=${ENABLE_QTFRED:-OFF} \
|
||||
-DSHADERS_ENABLE_COMPILATION=ON -DCMAKE_JOB_POOLS=link=1 -DCMAKE_JOB_POOL_LINK=link ..
|
||||
@@ -26,11 +26,11 @@ elif [ "$OS" = "Windows" ]; then
|
||||
echo "debug_name=$(get_package_name)-debug-$ARCH-$SIMD.7z" >> $GITHUB_OUTPUT
|
||||
echo "debug_mime=$(file -b --mime-type "$(pwd)/$(get_package_name)-debug-$ARCH-$SIMD.7z")" >> $GITHUB_OUTPUT
|
||||
elif [ "$OS" = "Mac" ]; then
|
||||
tar -cvzf "$(get_package_name)-builds-Mac.tar.gz" *.app
|
||||
tar -cvzf "$(get_package_name)-builds-Mac-$ARCH.tar.gz" *.app
|
||||
|
||||
echo "package_path=$(pwd)/$(get_package_name)-builds-Mac.tar.gz" >> $GITHUB_OUTPUT
|
||||
echo "package_name=$(get_package_name)-builds-Mac.tar.gz" >> $GITHUB_OUTPUT
|
||||
echo "package_mime=$(file -b --mime-type "$(pwd)/$(get_package_name)-builds-Mac.tar.gz")" >> $GITHUB_OUTPUT
|
||||
echo "package_path=$(pwd)/$(get_package_name)-builds-Mac-$ARCH.tar.gz" >> $GITHUB_OUTPUT
|
||||
echo "package_name=$(get_package_name)-builds-Mac-$ARCH.tar.gz" >> $GITHUB_OUTPUT
|
||||
echo "package_mime=$(file -b --mime-type "$(pwd)/$(get_package_name)-builds-Mac-$ARCH.tar.gz")" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "Invalid OS: $OS"
|
||||
fi
|
||||
@@ -5,6 +5,13 @@ HERE=$(dirname "$SCRIPT")
|
||||
|
||||
export LD_LIBRARY_PATH=$(pwd)/bin/lib:$LD_LIBRARY_PATH
|
||||
|
||||
# if on mac and building for architecture that doesn't match host
|
||||
# then unittests will fail so we just need to skip it (for now)
|
||||
if [ "$RUNNER_OS" = "macOS" ] && [ "$ARCH" != "$(uname -m)" ]; then
|
||||
echo "Skipping tests due to architecture mismatch!"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$CONFIGURATION" = "Debug"] && [[ "$RUNNER_OS" != "macOS" ]] ; then
|
||||
valgrind --leak-check=full --error-exitcode=1 --gen-suppressions=all \
|
||||
--suppressions="$HERE/valgrind.supp" ./bin/unittests --gtest_shuffle
|
||||
|
||||
+9
-5
@@ -8,7 +8,8 @@ from file_list import ReleaseFile
|
||||
from util import retry_multi, GLOBAL_TIMEOUT
|
||||
|
||||
LINUX_KEY = "Linux"
|
||||
MACOSX_KEY = "Mac"
|
||||
MACOSX_X64_KEY = "Mac-x86_64"
|
||||
MACOSX_ARM64_KEY = "Mac-arm64"
|
||||
WIN32_SSE2_KEY = "Win32-SSE2"
|
||||
WIN64_SSE2_KEY = "Win64-SSE2"
|
||||
WIN32_AVX_KEY = "Win32-AVX"
|
||||
@@ -34,7 +35,8 @@ metadata = {
|
||||
|
||||
platforms = {
|
||||
LINUX_KEY: 'linux',
|
||||
MACOSX_KEY: 'macosx',
|
||||
MACOSX_X64_KEY: 'macosx',
|
||||
MACOSX_ARM64_KEY: 'macosx',
|
||||
WIN32_SSE2_KEY: 'windows',
|
||||
WIN64_SSE2_KEY: 'windows',
|
||||
WIN32_AVX_KEY: 'windows',
|
||||
@@ -43,7 +45,8 @@ platforms = {
|
||||
|
||||
envs = {
|
||||
LINUX_KEY: 'linux && x86_64', # Linux only has 64bit builds
|
||||
MACOSX_KEY: 'macosx',
|
||||
MACOSX_X64_KEY: 'macosx && x86_64',
|
||||
MACOSX_ARM64_KEY: 'macosx && arm64',
|
||||
WIN32_SSE2_KEY: 'windows',
|
||||
WIN64_SSE2_KEY: 'windows && x86_64',
|
||||
WIN32_AVX_KEY: 'windows && avx',
|
||||
@@ -135,7 +138,7 @@ def render_nebula_release(version, stability, files, config):
|
||||
'label': label,
|
||||
'properties': props,
|
||||
})
|
||||
elif group == MACOSX_KEY and fn.startswith(os.path.basename(fn) + '.app/'):
|
||||
elif group.startswith('Mac') and fn.startswith(os.path.basename(fn) + '.app/'):
|
||||
if 'qtfred' in fn:
|
||||
if '-FASTDBG' in fn:
|
||||
label = 'QtFRED Debug'
|
||||
@@ -148,7 +151,8 @@ def render_nebula_release(version, stability, files, config):
|
||||
label = None
|
||||
|
||||
props = {
|
||||
"x64": True, # All Mac builds are 64-bit
|
||||
"arm64": "arm64" in fn,
|
||||
"x64": "x64" in fn,
|
||||
"sse2": True, # There are no forced options on mac but 64-bit always implies SSE2 so we set that here
|
||||
"avx": False,
|
||||
"avx2": False,
|
||||
|
||||
@@ -7,15 +7,15 @@ PLACEHOLDER
|
||||
[b]Deprecations:[/b]
|
||||
PLACEHOLDER
|
||||
|
||||
Deprecations are a mechanism in FSO where a certain feature or aspect of the engine has changed or is no longer supported. Since this would normally break existing mods we have the mod table feature "[tt]$Target Version:[/tt]" with which a mod can specify what version of FSO it was developed with. The features listed above will be removed or changed when the target version of a mod is at least the version released in this post.
|
||||
Deprecations are a mechanism in FSO where a certain feature or aspect of the engine has changed or is no longer supported. Since this would normally break existing mods, we have the mod table feature "[tt]$Target Version:[/tt]" with which a mod can specify what version of FSO it was developed with. Any features listed under Deprecations will be removed or changed when the target version of a mod is at least the version released in this post.
|
||||
|
||||
[size=5pt]Previous [url=https://www.hard-light.net/forums/index.php?topic=98682.0]23.0.0 Release Thread[/url][/size]
|
||||
[size=5pt]Previous [url=https://www.hard-light.net/forums/index.php?topic=99015.0]23.2.1 Release Thread[/url][/size]
|
||||
|
||||
Launchers, if you don't have one already:
|
||||
[b]All platforms: [/b] For every day use, we recommend [url=https://www.hard-light.net/forums/index.php?topic=94068.0]Knossos[/url], an integrated solution for downloading and launching mods.
|
||||
[b]All platforms: [/b] For every day use, we recommend [url=https://knossosnet.github.io/Knossos-Release-Page/]Knossos.NET[/url], an integrated solution for downloading and launching mods.
|
||||
|
||||
[hidden=Alternative Launchers]
|
||||
Cross-platform: [url=https://www.hard-light.net/forums/index.php?topic=89162]wxLauncher 0.12.x Test Build[/url] (ongoing project for a unified launcher, you should upgrade to the latest RC/test build if you have not yet)
|
||||
Cross-platform: [url=https://www.hard-light.net/forums/index.php?topic=89162]wxLauncher 0.12.x Test Build[/url] (legacy project for a unified launcher)
|
||||
[b]Important:[/b] For best compatibility with FSO 3.8 and later you should use at least wxLauncher 0.12.
|
||||
|
||||
Windows: [url=http://scp.fsmods.net/builds/Launcher55g.zip]Launcher 5.5g[/url] ([url=https://scp.indiegames.us/builds/Launcher55g.zip]Mirror[/url]) ([url=https://www.mediafire.com/?wdvzn7hhhzh418m]Mirror[/url]) Not compatible with Windows 8+, use wxLauncher above
|
||||
@@ -41,7 +41,7 @@ Linux: [url=https://www.hard-light.net/forums/index.php/topic,53206.0.html]YAL[
|
||||
|
||||
[b]What are those SSE, SSE2 and AVX builds I keep seeing everywhere?[/b]
|
||||
[url=https://www.hard-light.net/forums/index.php?topic=65628.0]Your answer is in this topic.[/url]
|
||||
Don't want to deal with that? Use [url=https://www.hard-light.net/forums/index.php?topic=94068.0]Knossos[/url] and it will download the best build specifically for your PC!
|
||||
Don't want to deal with that? Use [url=https://knossosnet.github.io/Knossos-Release-Page/]Knossos.NET[/url] and it will download the best build specifically for your PC!
|
||||
[/hidden]
|
||||
|
||||
[img]https://scp.indiegames.us/img/linux-icon.png[/img] [color=green][size=12pt]Linux 64-bit[/size][/color]
|
||||
@@ -53,8 +53,9 @@ Alternatively, if there is a package in your software repository then you should
|
||||
|
||||
|
||||
[img]https://scp.indiegames.us/img/mac-icon.png[/img] [color=green][size=12pt]macOS[/size][/color]
|
||||
[size=8pt]macOS 10.9+, 64-bit (Intel)[/size]
|
||||
${build(groups["Mac"].mainFile)}
|
||||
[size=8pt]macOS 10.9+[/size]
|
||||
[b]Intel (64-bit):[/b] ${build(groups["Mac"].subFiles["x86_64"])}
|
||||
[b]Apple Silicon:[/b] ${build(groups["Mac"].subFiles["arm64"])}
|
||||
|
||||
These builds are not signed and so by default will fail to launch. To run them simply right-click on the app, click open, then click open again on the security confirmation dialog. You should only have to do this once for each app.
|
||||
If running the game through Knossos or Knossos.NET this step should not be necessary.
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
Mako==1.2.2
|
||||
requests==2.31.0
|
||||
requests==2.32.0
|
||||
semantic-version==2.8.5
|
||||
@@ -7,3 +7,15 @@ if (CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
else()
|
||||
set(IS_64BIT FALSE)
|
||||
endif()
|
||||
|
||||
set(IS_ARM64 FALSE)
|
||||
|
||||
if (NOT "${CMAKE_GENERATOR_PLATFORM}" STREQUAL "") # needed to cover Visual Studio generator
|
||||
if(CMAKE_GENERATOR_PLATFORM MATCHES "^(aarch64|arm64|ARM64)")
|
||||
set(IS_ARM64 TRUE)
|
||||
endif()
|
||||
else()
|
||||
if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64|arm64|ARM64)")
|
||||
set(IS_ARM64 TRUE)
|
||||
endif()
|
||||
endif()
|
||||
@@ -22,6 +22,14 @@ SET(LIBRAY_DESTINATION "../Frameworks")
|
||||
|
||||
set(PLATFORM_MAC TRUE CACHE INTERNAL "" FORCE)
|
||||
|
||||
# Maybe override arm64 setting if we are compiling for different architecture
|
||||
# If not specified, or if it's a universal build, then this should do nothing
|
||||
if(CMAKE_OSX_ARCHITECTURES MATCHES "arm64")
|
||||
set(IS_ARM64 TRUE)
|
||||
elseif(CMAKE_OSX_ARCHITECTURES MATCHES "x86_64")
|
||||
set(IS_ARM64 FALSE)
|
||||
endif()
|
||||
|
||||
# Generate and don't strip debug symbols
|
||||
# These settings don't seem to generate debug symbols for code and Freespace2
|
||||
# so those settings are set manually in code and Freespace2's CMakeLists.txt files
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#cmakedefine SCP_HAVE_STD_MAX_ALIGN_T
|
||||
|
||||
#cmakedefine01 IS_64BIT
|
||||
#cmakedefine01 IS_ARM64
|
||||
|
||||
#cmakedefine01 SCP_HAVE_STRCASECMP
|
||||
#cmakedefine01 SCP_HAVE_STRNCASECMP
|
||||
|
||||
@@ -83,20 +83,41 @@ if(SUPPORTS_SHIFT_NEGATIVE_VALUE)
|
||||
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wno-shift-negative-value")
|
||||
endif()
|
||||
|
||||
set(COMPILER_FLAGS_RELEASE "-O2 -Wno-unused-variable -Wno-unused-parameter")
|
||||
# Check if there is a user-set optimisation flag
|
||||
string(REGEX MATCH "-O[a-zA-Z|0-9]+" CXX_OPT_FLAG ${CXX_BASE_FLAGS})
|
||||
string(REGEX MATCH "-O[a-zA-Z|0-9]+" C_OPT_FLAG ${C_BASE_FLAGS})
|
||||
|
||||
set(COMPILER_FLAGS_DEBUG "-Og -g -Wshadow")
|
||||
# If no user-set opt flag, set -O2 and -Og
|
||||
if ("${CXX_OPT_FLAG}" STREQUAL "")
|
||||
set(CXX_OPT_FLAG_RELEASE "-O2")
|
||||
set(CXX_OPT_FLAG_DEBUG "-Og")
|
||||
else()
|
||||
set(CXX_OPT_FLAG_RELEASE "${CXX_OPT_FLAG}")
|
||||
set(CXX_OPT_FLAG_DEBUG "${CXX_OPT_FLAG}")
|
||||
endif()
|
||||
if ("${C_OPT_FLAG}" STREQUAL "")
|
||||
set(C_OPT_FLAG_RELEASE "-O2")
|
||||
set(C_OPT_FLAG_DEBUG "-Og")
|
||||
else()
|
||||
set(C_OPT_FLAG_RELEASE "${C_OPT_FLAG}")
|
||||
set(C_OPT_FLAG_DEBUG "${C_OPT_FLAG}")
|
||||
endif()
|
||||
|
||||
# Always use the base flags and add our compiler flags at the bacl
|
||||
set(CXX_FLAGS_RELEASE "${CXX_OPT_FLAG_RELEASE} -Wno-unused-variable -Wno-unused-parameter")
|
||||
set(C_FLAGS_RELEASE "${C_OPT_FLAG_RELEASE} -Wno-unused-variable -Wno-unused-parameter")
|
||||
|
||||
set(CXX_FLAGS_DEBUG "${CXX_OPT_FLAG_DEBUG} -g -Wshadow")
|
||||
set(C_FLAGS_DEBUG "${C_OPT_FLAG_DEBUG} -g -Wshadow")
|
||||
|
||||
# Always use the base flags and add our compiler flags at the back
|
||||
set(CMAKE_CXX_FLAGS "${CXX_BASE_FLAGS} ${COMPILER_FLAGS}")
|
||||
set(CMAKE_C_FLAGS "${C_BASE_FLAGS} ${COMPILER_FLAGS}")
|
||||
|
||||
set(CMAKE_CXX_FLAGS_RELEASE ${COMPILER_FLAGS_RELEASE})
|
||||
set(CMAKE_C_FLAGS_RELEASE ${COMPILER_FLAGS_RELEASE})
|
||||
|
||||
set(CMAKE_CXX_FLAGS_DEBUG ${COMPILER_FLAGS_DEBUG})
|
||||
set(CMAKE_C_FLAGS_DEBUG ${COMPILER_FLAGS_DEBUG})
|
||||
set(CMAKE_CXX_FLAGS_RELEASE ${CXX_FLAGS_RELEASE})
|
||||
set(CMAKE_C_FLAGS_RELEASE ${C_FLAGS_RELEASE})
|
||||
|
||||
set(CMAKE_CXX_FLAGS_DEBUG ${CXX_FLAGS_DEBUG})
|
||||
set(CMAKE_C_FLAGS_DEBUG ${C_FLAGS_DEBUG})
|
||||
|
||||
set(CMAKE_EXE_LINKER_FLAGS "")
|
||||
|
||||
|
||||
@@ -113,19 +113,41 @@ 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")
|
||||
# Check if there is a user-set optimisation flag
|
||||
string(REGEX MATCH "-O[a-zA-Z|0-9]+" CXX_OPT_FLAG ${CXX_BASE_FLAGS})
|
||||
string(REGEX MATCH "-O[a-zA-Z|0-9]+" C_OPT_FLAG ${C_BASE_FLAGS})
|
||||
|
||||
set(COMPILER_FLAGS_DEBUG "-Og -g -Wshadow")
|
||||
# If no user-set opt flag, set -O2 and -Og
|
||||
if ("${CXX_OPT_FLAG}" STREQUAL "")
|
||||
set(CXX_OPT_FLAG_RELEASE "-O2")
|
||||
set(CXX_OPT_FLAG_DEBUG "-Og")
|
||||
else()
|
||||
set(CXX_OPT_FLAG_RELEASE "${CXX_OPT_FLAG}")
|
||||
set(CXX_OPT_FLAG_DEBUG "${CXX_OPT_FLAG}")
|
||||
endif()
|
||||
if ("${C_OPT_FLAG}" STREQUAL "")
|
||||
set(C_OPT_FLAG_RELEASE "-O2")
|
||||
set(C_OPT_FLAG_DEBUG "-Og")
|
||||
else()
|
||||
set(C_OPT_FLAG_RELEASE "${C_OPT_FLAG}")
|
||||
set(C_OPT_FLAG_DEBUG "${C_OPT_FLAG}")
|
||||
endif()
|
||||
|
||||
set(CXX_FLAGS_RELEASE "${CXX_OPT_FLAG_RELEASE} -Wno-unused-variable -Wno-unused-but-set-variable -Wno-array-bounds -Wno-empty-body -Wno-clobbered -Wno-unused-parameter")
|
||||
set(C_FLAGS_RELEASE "${C_OPT_FLAG_RELEASE} -Wno-unused-variable -Wno-unused-but-set-variable -Wno-array-bounds -Wno-empty-body -Wno-clobbered -Wno-unused-parameter")
|
||||
|
||||
set(CXX_FLAGS_DEBUG "${CXX_OPT_FLAG_DEBUG} -g -Wshadow")
|
||||
set(C_FLAGS_DEBUG "${C_OPT_FLAG_DEBUG} -g -Wshadow")
|
||||
|
||||
# Always use the base flags and add our compiler flags at the back
|
||||
set(CMAKE_CXX_FLAGS "${CXX_BASE_FLAGS} ${COMPILER_FLAGS}")
|
||||
set(CMAKE_C_FLAGS "${C_BASE_FLAGS} ${COMPILER_FLAGS}")
|
||||
|
||||
set(CMAKE_CXX_FLAGS_RELEASE ${COMPILER_FLAGS_RELEASE})
|
||||
set(CMAKE_C_FLAGS_RELEASE ${COMPILER_FLAGS_RELEASE})
|
||||
set(CMAKE_CXX_FLAGS_RELEASE ${CXX_FLAGS_RELEASE})
|
||||
set(CMAKE_C_FLAGS_RELEASE ${C_FLAGS_RELEASE})
|
||||
|
||||
set(CMAKE_CXX_FLAGS_DEBUG ${COMPILER_FLAGS_DEBUG})
|
||||
set(CMAKE_C_FLAGS_DEBUG ${COMPILER_FLAGS_DEBUG})
|
||||
set(CMAKE_CXX_FLAGS_DEBUG ${CXX_FLAGS_DEBUG})
|
||||
set(CMAKE_C_FLAGS_DEBUG ${C_FLAGS_DEBUG})
|
||||
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${LINKER_FLAGS}")
|
||||
|
||||
|
||||
@@ -46,9 +46,13 @@ target_compile_options(compiler INTERFACE ${WARNING_FLAGS})
|
||||
set(CMAKE_C_FLAGS "/MP /GS- /analyze- /Zc:wchar_t /errorReport:prompt /Zc:forScope /Gd /EHsc /nologo /Zm200")
|
||||
set(CMAKE_CXX_FLAGS "/MP /GS- /analyze- /Zc:wchar_t /errorReport:prompt /Zc:forScope /Gd /EHsc /nologo /Zm200")
|
||||
|
||||
set(CMAKE_EXE_LINKER_FLAGS "/MANIFEST /DYNAMICBASE:NO /SAFESEH:NO /ERRORREPORT:PROMPT /NOLOGO")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "/MANIFEST /SAFESEH:NO /ERRORREPORT:PROMPT /NOLOGO")
|
||||
set(CMAKE_STATIC_LINKER_FLAGS "")
|
||||
|
||||
if(NOT IS_ARM64)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /DYNAMICBASE:NO")
|
||||
endif()
|
||||
|
||||
# Release
|
||||
set(CMAKE_C_FLAGS_RELEASE "/GL /Gy- /Ox /Ot /Ob2 /fp:precise /GF /Oy /Oi /Zi /W3")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "/GL /Gy- /Ox /Ot /Ob2 /fp:precise /GF /Oy /Oi /Zi /W3")
|
||||
|
||||
+5
-3
@@ -6,8 +6,8 @@ if (EXISTS "${PROJECT_SOURCE_DIR}/version_override.cmake")
|
||||
include("${PROJECT_SOURCE_DIR}/version_override.cmake")
|
||||
endif()
|
||||
|
||||
set_if_not_defined(FSO_VERSION_MAJOR 23)
|
||||
set_if_not_defined(FSO_VERSION_MINOR 3)
|
||||
set_if_not_defined(FSO_VERSION_MAJOR 24)
|
||||
set_if_not_defined(FSO_VERSION_MINOR 1)
|
||||
set_if_not_defined(FSO_VERSION_BUILD 0)
|
||||
|
||||
# A numeric revision e.g. the CI build number
|
||||
@@ -35,7 +35,9 @@ ELSE()
|
||||
SET(FSO_BINARY_SUFFIX "${FSO_VERSION_MAJOR}_${FSO_VERSION_MINOR}_${FSO_VERSION_BUILD}_${FSO_VERSION_REVISION_STR}")
|
||||
ENDIF()
|
||||
|
||||
IF(IS_64BIT)
|
||||
IF(IS_ARM64)
|
||||
SET(FSO_BINARY_SUFFIX "${FSO_BINARY_SUFFIX}_arm64")
|
||||
ELSEIF(IS_64BIT)
|
||||
# This is a 64-bit builds
|
||||
SET(FSO_BINARY_SUFFIX "${FSO_BINARY_SUFFIX}_x64")
|
||||
ENDIF()
|
||||
|
||||
@@ -25,6 +25,10 @@ if (FSO_BUILD_WITH_OPENGL)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(FSO_BUILD_WITH_OPENXR_DEBUG)
|
||||
add_definitions(-DFS_OPENXR_DEBUG)
|
||||
endif()
|
||||
|
||||
TARGET_LINK_LIBRARIES(code PUBLIC openal)
|
||||
TARGET_LINK_LIBRARIES(code PUBLIC ${LUA_LIBS})
|
||||
TARGET_LINK_LIBRARIES(code PUBLIC ${PNG_LIBS})
|
||||
@@ -75,6 +79,17 @@ target_link_libraries(code PUBLIC hidapi::hidapi)
|
||||
|
||||
target_link_libraries(code PUBLIC imgui)
|
||||
|
||||
IF(NOT APPLE)
|
||||
target_link_libraries(code PUBLIC OpenXR::openxr_loader)
|
||||
target_include_directories(code PUBLIC OpenXR::Headers)
|
||||
ENDIF()
|
||||
IF(CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
# On Linux, we need to access X11 window data.
|
||||
# On Windows, SDL already provides everything, so no need to do anything
|
||||
find_package(X11)
|
||||
target_link_libraries(code PUBLIC ${X11_LIBRARIES})
|
||||
ENDIF()
|
||||
|
||||
# Headers for standalone "gui" on UNIX
|
||||
IF(UNIX)
|
||||
TARGET_LINK_LIBRARIES(code PUBLIC ${MONGOOSE_LIBS})
|
||||
|
||||
@@ -47,7 +47,7 @@ ProgramInstance::ProgramInstance(const actions::Program* program) : _program(pro
|
||||
|
||||
ProgramState ProgramInstance::step()
|
||||
{
|
||||
if (!_locals.host.IsValid()) {
|
||||
if (!_locals.host.isValid()) {
|
||||
return ProgramState::Done;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ ActionResult MoveToSubmodel::execute(ProgramLocals& locals) const
|
||||
// The calling code should ensure that this never happens
|
||||
Assertion(locals.hostSubobject >= 0, "Did not have a valid host subobject.");
|
||||
|
||||
auto instance = object_get_model_instance(locals.host.objp);
|
||||
auto instance = object_get_model_instance(locals.host.objp());
|
||||
Assertion(instance != -1, "Model instances are required if a host subobject is specified.");
|
||||
|
||||
auto pmi = model_get_instance(instance);
|
||||
|
||||
@@ -37,7 +37,7 @@ ActionResult ParticleEffectAction::execute(ProgramLocals& locals) const
|
||||
vec3d local_pos;
|
||||
matrix local_orient;
|
||||
if (locals.hostSubobject != -1) {
|
||||
auto instance = object_get_model_instance(locals.host.objp);
|
||||
auto instance = object_get_model_instance(locals.host.objp());
|
||||
Assertion(instance != -1, "Model instances are required if a host subobject is specified.");
|
||||
|
||||
auto pmi = model_get_instance(instance);
|
||||
@@ -59,7 +59,7 @@ ActionResult ParticleEffectAction::execute(ProgramLocals& locals) const
|
||||
|
||||
auto direction = locals.variables.getValue({"locals", "direction"}).getVector();
|
||||
|
||||
source.moveToObject(locals.host.objp, &local_pos);
|
||||
source.moveToObject(locals.host.objp(), &local_pos);
|
||||
source.setOrientationFromNormalizedVec(&direction, true);
|
||||
|
||||
source.finish();
|
||||
|
||||
@@ -26,7 +26,7 @@ ActionResult PlaySoundAction::execute(ProgramLocals& locals) const
|
||||
vec3d local_pos;
|
||||
matrix local_orient;
|
||||
if (locals.hostSubobject != -1) {
|
||||
auto instance = object_get_model_instance(locals.host.objp);
|
||||
auto instance = object_get_model_instance(locals.host.objp());
|
||||
Assertion(instance != -1, "Model instances are required if a host subobject is specified.");
|
||||
|
||||
auto pmi = model_get_instance(instance);
|
||||
@@ -47,8 +47,8 @@ ActionResult PlaySoundAction::execute(ProgramLocals& locals) const
|
||||
local_pos += locals.variables.getValue({"locals", "position"}).getVector();
|
||||
|
||||
vec3d global_pos;
|
||||
vm_vec_unrotate(&global_pos, &local_pos, &locals.host.objp->orient);
|
||||
global_pos += locals.host.objp->pos;
|
||||
vm_vec_unrotate(&global_pos, &local_pos, &locals.host.objp()->orient);
|
||||
global_pos += locals.host.objp()->pos;
|
||||
|
||||
const auto soundId = gamesnd_get_by_name(m_soundIdExpression.execute(locals.variables).c_str());
|
||||
|
||||
|
||||
+8
-7
@@ -277,7 +277,7 @@ typedef struct ai_info {
|
||||
|
||||
// Probably become obsolete, to be replaced by path_start, path_cur, etc.
|
||||
waypoint_list *wp_list; // waypoint list being followed
|
||||
size_t wp_index; // waypoint index in list
|
||||
int wp_index; // waypoint index in list
|
||||
int wp_flags; // waypoint flags, see WPF_xxxx
|
||||
int waypoint_speed_cap; // -1 no cap, otherwise cap - changed to int by Goober5000
|
||||
|
||||
@@ -533,11 +533,11 @@ extern void ai_ignore_wing(object *ignorer, int wingnum);
|
||||
extern void ai_dock_with_object(object *docker, int docker_index, object *dockee, int dockee_index, int dock_type);
|
||||
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_start_waypoints(object *objp, waypoint_list *wp_list, int wp_flags, int start_index);
|
||||
extern void ai_ship_hit(object *objp_ship, object *hit_objp, vec3d *hit_normal);
|
||||
extern void ai_ship_destroy(int shipnum);
|
||||
extern vec3d ai_get_acc_limit(vec3d* vel_limit, const object* objp);
|
||||
extern void ai_turn_towards_vector(vec3d *dest, object *objp, vec3d *slide_vec, vec3d *rel_pos, float bank_override, int flags, vec3d *rvec = nullptr, vec3d* turnrate_mod = nullptr);
|
||||
extern void ai_turn_towards_vector(const vec3d *dest, object *objp, const vec3d *slide_vec, const vec3d *rel_pos, float bank_override, int flags, const vec3d *rvec = nullptr, const vec3d* turnrate_mod = nullptr);
|
||||
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
|
||||
@@ -597,11 +597,12 @@ extern void set_predicted_enemy_pos(vec3d *predicted_enemy_pos, object *pobjp, v
|
||||
extern int is_instructor(object *objp);
|
||||
extern int find_enemy(int objnum, float range, int max_attackers, int ship_info_index = -1);
|
||||
|
||||
float ai_get_weapon_speed(ship_weapon *swp);
|
||||
void set_predicted_enemy_pos_turret(vec3d *predicted_enemy_pos, vec3d *gun_pos, object *pobjp, vec3d *enemy_pos, vec3d *enemy_vel, float weapon_speed, float time_enemy_in_range);
|
||||
float ai_get_weapon_speed(const ship_weapon *swp);
|
||||
void set_predicted_enemy_pos_turret(vec3d *predicted_enemy_pos, const vec3d *gun_pos, const object *pobjp, const vec3d *enemy_pos, const vec3d *enemy_vel, float weapon_speed, float time_enemy_in_range);
|
||||
|
||||
// function to change rearm status for ai ships (called from sexpression code)
|
||||
extern void ai_set_rearm_status( int team, int new_status );
|
||||
extern void ai_set_good_rearm_time( int team, int time );
|
||||
extern void ai_set_bad_rearm_time(int team, int time);
|
||||
extern void ai_good_secondary_time( int team, int weapon_index, int num_weapons, const char *shipname );
|
||||
|
||||
extern void ai_do_objects_docked_stuff(object *docker, int docker_point, object *dockee, int dockee_point, bool update_clients = true);
|
||||
@@ -634,6 +635,6 @@ void do_random_sidethrust(ai_info *aip, ship_info *sip);
|
||||
void ai_formation_object_recalculate_slotnums(int form_objnum, int exiting_objnum = -1);
|
||||
|
||||
|
||||
bool test_line_of_sight(vec3d* from, vec3d* to, std::unordered_set<const object*>&& excluded_objects = {}, float threshold = 10.0f, bool test_for_shields = false, bool test_for_hull = true, float* first_intersect_dist = nullptr, object** first_intersect_obj = nullptr);
|
||||
bool test_line_of_sight(vec3d* from, vec3d* to, std::unordered_set<int>&& excluded_object_ids = {}, float threshold = 10.0f, bool test_for_shields = false, bool test_for_hull = true, float* first_intersect_dist = nullptr, object** first_intersect_obj = nullptr);
|
||||
|
||||
#endif
|
||||
@@ -32,6 +32,8 @@ namespace AI {
|
||||
Unload_primaries, // Fire primaries as fast as possible!
|
||||
Trying_unsuccessfully_to_warp, // Trying to warp, but can't warp at the moment
|
||||
Free_afterburner_use, // Use afterburners while following waypoints or flying towards objects
|
||||
Waypoints_no_formation, // wont get into formation when running waypoints as part of a wing
|
||||
|
||||
|
||||
NUM_VALUES
|
||||
};
|
||||
@@ -47,6 +49,7 @@ namespace AI {
|
||||
Depart_sound_played,// Goober5000 - replacement for AL's hack ;)
|
||||
Target_own_team, // this attack goal is allowed to target friendlies
|
||||
Afterburn_hard, // afterburn as hard as possible to the goal
|
||||
Waypoints_in_reverse, // decrement instead of increment
|
||||
|
||||
NUM_VALUES
|
||||
};
|
||||
@@ -156,7 +159,12 @@ namespace AI {
|
||||
Whackable_debris,
|
||||
Whackable_asteroids,
|
||||
Dynamic_goals_afterburn_hard,
|
||||
Player_orders_afterburn_hard,
|
||||
Hudsquadmsg_tactical_disarm_disable,
|
||||
Align_to_target_when_guarding_still,
|
||||
Debris_respects_big_damage,
|
||||
Dont_limit_change_in_speed_due_to_physics_whack,
|
||||
Guards_ignore_protected_attackers,
|
||||
|
||||
NUM_VALUES
|
||||
};
|
||||
|
||||
+44
-7
@@ -184,6 +184,14 @@ void parse_ai_profiles_tbl(const char *filename)
|
||||
if (optional_string("$Max Beam Friendly Fire Damage:"))
|
||||
parse_float_list(profile->beam_friendly_damage_cap, NUM_SKILL_LEVELS);
|
||||
|
||||
if (optional_string("$Max Weapon Friendly Fire Damage:")) {
|
||||
parse_float_list(profile->weapon_friendly_damage_cap, NUM_SKILL_LEVELS);
|
||||
}
|
||||
|
||||
if (optional_string("$Max Weapon Self Damage:")) {
|
||||
parse_float_list(profile->weapon_self_damage_cap, NUM_SKILL_LEVELS);
|
||||
}
|
||||
|
||||
if (optional_string("$Player Countermeasure Life Scale:"))
|
||||
parse_float_list(profile->cmeasure_life_scale, NUM_SKILL_LEVELS);
|
||||
|
||||
@@ -258,7 +266,7 @@ void parse_ai_profiles_tbl(const char *filename)
|
||||
|
||||
if (optional_string("$Glide Attack Percent:")) {
|
||||
parse_float_list(profile->glide_attack_percent, NUM_SKILL_LEVELS);
|
||||
//Percent is nice for modders, but here in the code we want it betwwen 0 and 1.0
|
||||
//Percent is nice for modders, but here in the code we want it between 0 and 1.0
|
||||
//While we're at it, verify the range
|
||||
for (i = 0; i < NUM_SKILL_LEVELS; i++) {
|
||||
if (profile->glide_attack_percent[i] < 0.0f || profile->glide_attack_percent[i] > 100.0f) {
|
||||
@@ -271,7 +279,7 @@ void parse_ai_profiles_tbl(const char *filename)
|
||||
|
||||
if (optional_string("$Circle Strafe Percent:")) {
|
||||
parse_float_list(profile->circle_strafe_percent, NUM_SKILL_LEVELS);
|
||||
//Percent is nice for modders, but here in the code we want it betwwen 0 and 1.0
|
||||
//Percent is nice for modders, but here in the code we want it between 0 and 1.0
|
||||
//While we're at it, verify the range
|
||||
for (i = 0; i < NUM_SKILL_LEVELS; i++) {
|
||||
if (profile->circle_strafe_percent[i] < 0.0f || profile->circle_strafe_percent[i] > 100.0f) {
|
||||
@@ -284,7 +292,7 @@ void parse_ai_profiles_tbl(const char *filename)
|
||||
|
||||
if (optional_string("$Glide Strafe Percent:")) {
|
||||
parse_float_list(profile->glide_strafe_percent, NUM_SKILL_LEVELS);
|
||||
//Percent is nice for modders, but here in the code we want it betwwen 0 and 1.0
|
||||
//Percent is nice for modders, but here in the code we want it between 0 and 1.0
|
||||
//While we're at it, verify the range
|
||||
for (i = 0; i < NUM_SKILL_LEVELS; i++) {
|
||||
if (profile->glide_strafe_percent[i] < 0.0f || profile->glide_strafe_percent[i] > 100.0f) {
|
||||
@@ -297,7 +305,7 @@ void parse_ai_profiles_tbl(const char *filename)
|
||||
|
||||
if (optional_string("$Random Sidethrust Percent:")) {
|
||||
parse_float_list(profile->random_sidethrust_percent, NUM_SKILL_LEVELS);
|
||||
//Percent is nice for modders, but here in the code we want it betwwen 0 and 1.0
|
||||
//Percent is nice for modders, but here in the code we want it between 0 and 1.0
|
||||
//While we're at it, verify the range
|
||||
for (i = 0; i < NUM_SKILL_LEVELS; i++) {
|
||||
if (profile->random_sidethrust_percent[i] < 0.0f || profile->random_sidethrust_percent[i] > 100.0f) {
|
||||
@@ -471,10 +479,20 @@ void parse_ai_profiles_tbl(const char *filename)
|
||||
|
||||
set_flag(profile, "$firing requires exact los:", AI::Profile_Flags::Require_exact_los);
|
||||
|
||||
if (optional_string("$exact los minimum detection radius:")) {
|
||||
stuff_float(&profile->los_min_detection_radius);
|
||||
}
|
||||
|
||||
set_flag(profile, "$fighterbay arrivals use carrier orientation:", AI::Profile_Flags::Fighterbay_arrivals_use_carrier_orient);
|
||||
|
||||
set_flag(profile, "$fighterbay departures use carrier orientation:", AI::Profile_Flags::Fighterbay_departures_use_carrier_orient);
|
||||
|
||||
set_flag(profile, "$debris damage respects 'big damage' flag:", AI::Profile_Flags::Debris_respects_big_damage);
|
||||
|
||||
set_flag(profile, "$don't limit change in speed due to physics whack:", AI::Profile_Flags::Dont_limit_change_in_speed_due_to_physics_whack);
|
||||
|
||||
set_flag(profile, "$guards ignore protected attackers:", AI::Profile_Flags::Guards_ignore_protected_attackers);
|
||||
|
||||
if (optional_string("$ai path mode:"))
|
||||
{
|
||||
stuff_string(buf, F_NAME, NAME_LENGTH);
|
||||
@@ -625,15 +643,25 @@ void parse_ai_profiles_tbl(const char *filename)
|
||||
|
||||
set_flag(profile, "$dynamic goals afterburn hard:", AI::Profile_Flags::Dynamic_goals_afterburn_hard);
|
||||
|
||||
set_flag(profile, "$player orders afterburn hard:", AI::Profile_Flags::Player_orders_afterburn_hard);
|
||||
|
||||
set_flag(profile, "$hud squad messages use tactical disarm/disable:", AI::Profile_Flags::Hudsquadmsg_tactical_disarm_disable);
|
||||
|
||||
set_flag(profile, "$align to target when guarding stationary ship:", AI::Profile_Flags::Align_to_target_when_guarding_still);
|
||||
|
||||
if (optional_string("$rotation factor multiplier for player collisions:")) {
|
||||
stuff_float(&profile->rot_fac_multiplier_ply_collisions);
|
||||
}
|
||||
|
||||
// end of options ----------------------------------------
|
||||
|
||||
// if we've been through once already and are at the same place, force a move
|
||||
if (saved_Mp && (saved_Mp == Mp))
|
||||
{
|
||||
char tmp[60];
|
||||
memset(tmp, 0, 60);
|
||||
strncpy(tmp, Mp, 59);
|
||||
mprintf(("WARNING: Unrecognized parameter in ai_profiles: %s\n", tmp));
|
||||
mprintf(("WARNING: Unrecognized parameter in %s: %s\n", filename, tmp));
|
||||
|
||||
Mp++;
|
||||
}
|
||||
@@ -707,6 +735,7 @@ void ai_profile_t::reset()
|
||||
|
||||
flags.reset();
|
||||
|
||||
los_min_detection_radius = 10.0f;
|
||||
ai_path_mode = AI_PATH_MODE_NORMAL;
|
||||
subsystem_path_radii = 0;
|
||||
bay_arrive_speed_mult = 1.0f;
|
||||
@@ -714,6 +743,7 @@ void ai_profile_t::reset()
|
||||
second_order_lead_predict_factor = 0;
|
||||
ai_range_aware_secondary_select_mode = AI_RANGE_AWARE_SEC_SEL_MODE_RETAIL;
|
||||
turret_target_recheck_time = 2000.0f;
|
||||
rot_fac_multiplier_ply_collisions = 0.0f;
|
||||
|
||||
for (int i = 0; i < NUM_SKILL_LEVELS; ++i) {
|
||||
max_incoming_asteroids[i] = 0;
|
||||
@@ -736,10 +766,12 @@ void ai_profile_t::reset()
|
||||
shield_energy_scale[i] = 0;
|
||||
afterburner_recharge_scale[i] = 0;
|
||||
player_damage_scale[i] = 0;
|
||||
player_damage_inflicted_scale[i] = 0;
|
||||
player_damage_inflicted_scale[i] = 0;
|
||||
|
||||
subsys_damage_scale[i] = 0;
|
||||
beam_friendly_damage_cap[i] = 0;
|
||||
beam_friendly_damage_cap[i] = -1.f;
|
||||
weapon_friendly_damage_cap[i] = -1.f;
|
||||
weapon_self_damage_cap[i] = -1.f;
|
||||
turn_time_scale[i] = 0;
|
||||
glide_attack_percent[i] = 0;
|
||||
circle_strafe_percent[i] = 0;
|
||||
@@ -819,4 +851,9 @@ void ai_profile_t::reset()
|
||||
if (mod_supports_version(23, 4, 0)) {
|
||||
flags.set(AI::Profile_Flags::Hudsquadmsg_tactical_disarm_disable);
|
||||
}
|
||||
if (mod_supports_version(24, 2, 0)) {
|
||||
flags.set(AI::Profile_Flags::Debris_respects_big_damage);
|
||||
flags.set(AI::Profile_Flags::Force_beam_turret_fov);
|
||||
flags.set(AI::Profile_Flags::Guards_ignore_protected_attackers);
|
||||
}
|
||||
}
|
||||
@@ -57,6 +57,8 @@ public:
|
||||
|
||||
float subsys_damage_scale[NUM_SKILL_LEVELS]; // damage applied to a player subsystem
|
||||
float beam_friendly_damage_cap[NUM_SKILL_LEVELS]; // damage cap values for friendly beam fire
|
||||
float weapon_friendly_damage_cap[NUM_SKILL_LEVELS];
|
||||
float weapon_self_damage_cap[NUM_SKILL_LEVELS];
|
||||
float turn_time_scale[NUM_SKILL_LEVELS]; // speed at which enemy ships turn
|
||||
float glide_attack_percent[NUM_SKILL_LEVELS]; // SUSHI: The likelihood (0.0-1.0) of the AI to use the "glide attack" move
|
||||
float circle_strafe_percent[NUM_SKILL_LEVELS]; // SUSHI: The likelihood (0.0-1.0) of the AI to use the "circle strafe" move
|
||||
@@ -99,6 +101,9 @@ public:
|
||||
|
||||
float detail_distance_mult[MAX_DETAIL_LEVEL + 1]; //MAX_DETAIL_LEVEL really needs to be 4
|
||||
|
||||
// minimum radius for the line-of-sight (los) detection --wookieejedi
|
||||
float los_min_detection_radius;
|
||||
|
||||
int ai_path_mode;
|
||||
|
||||
// radii to use for the radius for subsystem path points and default value --wookieejedi
|
||||
@@ -118,6 +123,9 @@ public:
|
||||
// how often turrets shoulds check for new targets, milliseconds
|
||||
float turret_target_recheck_time;
|
||||
|
||||
// Multiplier value so the player can also experience rotational effects from collisions --wookieejedi
|
||||
float rot_fac_multiplier_ply_collisions;
|
||||
|
||||
void reset();
|
||||
};
|
||||
|
||||
|
||||
+13
-11
@@ -76,7 +76,7 @@ extern void big_ship_collide_recover_start(object *objp, object *big_objp, vec3d
|
||||
// If truly_random flag set (haha), then generate a pretty random number. Otherwise, generate a static rand which
|
||||
// tends to not change from frame to frame.
|
||||
// Try four times and choose nearest point to increase chance of getting a good point.
|
||||
void ai_bpap(object *objp, vec3d *attacker_objp_pos, vec3d *attacker_objp_fvec, vec3d *attack_point, vec3d *local_attack_point, float fov, float weapon_travel_dist, vec3d *surface_normal, ship_subsys *ss)
|
||||
void ai_bpap(const object *objp, const vec3d *attacker_objp_pos, const vec3d *attacker_objp_fvec, vec3d *attack_point, vec3d *local_attack_point, float fov, float weapon_travel_dist, vec3d *surface_normal, const ship_subsys *ss)
|
||||
{
|
||||
float nearest_dist;
|
||||
vec3d result_point, best_point;
|
||||
@@ -193,7 +193,7 @@ done_1:
|
||||
//
|
||||
// Note: Default value for fov is 1.0f 1.0f means don't use fov parameter.
|
||||
// If fov != 1.0f, try up to four times to find a point that's in the field of view.
|
||||
void ai_big_pick_attack_point_turret(object *objp, ship_subsys *ssp, vec3d *gpos, vec3d *gvec, vec3d *attack_point, float fov, float weapon_travel_dist)
|
||||
void ai_big_pick_attack_point_turret(const object *objp, ship_subsys *ssp, const vec3d *gpos, const vec3d *gvec, vec3d *attack_point, float fov, float weapon_travel_dist)
|
||||
{
|
||||
if (!timestamp_elapsed(ssp->turret_pick_big_attack_point_timestamp)) {
|
||||
vec3d result_point;
|
||||
@@ -213,7 +213,7 @@ void ai_big_pick_attack_point_turret(object *objp, ship_subsys *ssp, vec3d *gpos
|
||||
// Note: Default value for fov is 1.0f 1.0f means don't use fov parameter.
|
||||
// If fov != 1.0f, try up to four times to find a point that's in the field of view.
|
||||
// Note, attacker_objp can be a ship or a weapon.
|
||||
void ai_big_pick_attack_point(object *objp, object *attacker_objp, vec3d *attack_point, float fov)
|
||||
void ai_big_pick_attack_point(const object *objp, const object *attacker_objp, vec3d *attack_point, float fov)
|
||||
{
|
||||
Assert(objp->instance > -1);
|
||||
Assert(objp->type == OBJ_SHIP);
|
||||
@@ -411,7 +411,7 @@ int ai_big_maybe_follow_subsys_path(int do_dot_check)
|
||||
}
|
||||
}
|
||||
|
||||
if ( ship_subsystem_in_sight(En_objp, aip->targeted_subsys, &geye, &gsubpos, 1) ) {
|
||||
if ( ship_subsystem_in_sight(En_objp, aip->targeted_subsys, &geye, &gsubpos, true) ) {
|
||||
subsys_in_sight = 1;
|
||||
}
|
||||
}
|
||||
@@ -538,15 +538,15 @@ bool ai_new_maybe_reposition_attack_subsys() {
|
||||
model_local_to_global_point(&geye, &ep->pnt, pm, 0, &Pl_objp->orient, &Pl_objp->pos);
|
||||
|
||||
// get world pos of subsystem
|
||||
polymodel* tgt_pm = model_get(Ship_info[Ships[target_objp->instance].ship_info_index].model_num);
|
||||
model_local_to_global_point(&gsubpos, &vmd_zero_vector, tgt_pm, aip->targeted_subsys->system_info->subobj_num, &En_objp->orient, &En_objp->pos);
|
||||
get_subsystem_pos(&gsubpos, target_objp, aip->targeted_subsys);
|
||||
|
||||
// you're in sight! shoot it!
|
||||
if (ship_subsystem_in_sight(En_objp, aip->targeted_subsys, &geye, &gsubpos, 0))
|
||||
if (ship_subsystem_in_sight(En_objp, aip->targeted_subsys, &geye, &gsubpos, false))
|
||||
return false;
|
||||
|
||||
// not in sight, gotta get there
|
||||
vec3d* good_pos = nullptr;
|
||||
vec3d world_goal_pos;
|
||||
// For performance reasons we only recheck once a second, otherwise we reuse the last found target.
|
||||
if (timestamp_elapsed(aip->next_dynamic_path_check_time)) {
|
||||
vec3d tgt2pl = Pl_objp->pos - target_objp->pos;
|
||||
@@ -568,7 +568,6 @@ bool ai_new_maybe_reposition_attack_subsys() {
|
||||
vm_rot_point_around_line(&goal_pos, &tgt2pl, angle2goal, &vmd_zero_vector, &cross);
|
||||
|
||||
// then scale in (or out) towards our subsys
|
||||
vec3d world_goal_pos;
|
||||
float new_radius = ((subsys_dist - pl_dist) * (angle2goal / angle2subsys)) + pl_dist;
|
||||
vm_vec_copy_scale(&world_goal_pos, &goal_pos, new_radius / pl_dist);
|
||||
world_goal_pos += target_objp->pos;
|
||||
@@ -1035,7 +1034,7 @@ void ai_big_chase()
|
||||
ai_big_pick_attack_point(En_objp, Pl_objp, &enemy_pos, 0.8f);
|
||||
|
||||
weapon_info* wip = ai_get_weapon(&shipp->weapons);
|
||||
bool ballistic_aiming = !IS_VEC_NULL(&The_mission.gravity) && wip->gravity_const != 0.0f;
|
||||
bool ballistic_aiming = !IS_VEC_NULL(&The_mission.gravity) && wip && wip->gravity_const != 0.0f;
|
||||
bool valid_ballistic_trajectory = true;
|
||||
|
||||
if (!ballistic_aiming) {
|
||||
@@ -1842,7 +1841,7 @@ void ai_big_strafe()
|
||||
|
||||
/*
|
||||
if ( aip->goal_objnum != aip->target_objnum ) {
|
||||
Int3(); // what is going on here? - Get Alan
|
||||
UNREACHABLE("The goal objnum does not match the target objnum in ai_big_strafe(), please report to the SCP!"); // what is going on here? - Get Alan
|
||||
aip->mode = AIM_NONE;
|
||||
return;
|
||||
}
|
||||
@@ -1934,7 +1933,10 @@ int ai_big_maybe_enter_strafe_mode(const object *pl_objp, int weapon_objnum)
|
||||
weapon_objp = &Objects[weapon_objnum];
|
||||
Assert(weapon_objp->type == OBJ_WEAPON);
|
||||
|
||||
Assert(weapon_objp->parent >= 0 && weapon_objp->parent < MAX_OBJECTS);
|
||||
if (weapon_objp->parent < 0) {
|
||||
return 0;
|
||||
}
|
||||
Assert(weapon_objp->parent < MAX_OBJECTS);
|
||||
parent_objp = &Objects[weapon_objp->parent];
|
||||
if ( (parent_objp->signature != weapon_objp->parent_sig) || (parent_objp->type != OBJ_SHIP) ) {
|
||||
return 0;
|
||||
|
||||
+2
-2
@@ -24,8 +24,8 @@ void ai_big_subsys_path_cleanup(ai_info *aip);
|
||||
void ai_big_strafe();
|
||||
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);
|
||||
void ai_big_pick_attack_point(const object *objp, const object *attacker_objp, vec3d *attack_point, float fov=1.0f);
|
||||
void ai_big_pick_attack_point_turret(const object *objp, ship_subsys *ssp, const vec3d *gpos, const vec3d *gvec, vec3d *attack_point, float weapon_travel_dist, float fov=1.0f);
|
||||
|
||||
// default distance for following subsystem path points --wookieejedi
|
||||
// the value is 5 because that was the original value specified in ai_big_maybe_follow_subsys_path()
|
||||
|
||||
+358
-152
File diff suppressed because it is too large.
Load diff
+66
-59
@@ -214,7 +214,7 @@ void ai_maybe_add_form_goal(wing* wingp)
|
||||
int wingnum;
|
||||
if (Netgame.type_flags & NG_TYPE_TEAM) {
|
||||
const ship_registry_entry* ship_regp = ship_registry_get(Ships[wingp->ship_index[j]].ship_name);
|
||||
wingnum = TVT_wings[ship_regp->p_objp->team];
|
||||
wingnum = TVT_wings[ship_regp->p_objp()->team];
|
||||
ai_add_ship_goal_player(AIG_TYPE_PLAYER_SHIP, AI_GOAL_FORM_ON_WING, -1, Ships[Wings[wingnum].ship_index[Wings[wingnum].special_ship]].ship_name, aip);
|
||||
} else {
|
||||
wingnum = Starting_wings[0];
|
||||
@@ -487,10 +487,12 @@ void ai_goal_purge_invalid_goals( ai_goal *aigp, ai_goal *goal_list, ai_info *ai
|
||||
// these goals cannot be associated to wings, but can to a ship in a wing. So, we should find out
|
||||
// if the ship is in a wing so we can purge goals which might operate on that wing
|
||||
ship_index = ship_name_lookup(name);
|
||||
if ( ship_index == -1 ) {
|
||||
Int3(); // get allender -- this is sort of odd
|
||||
return;
|
||||
|
||||
Assertion(ship_index > -1, "Found a bad ship_index of %d in ai_goal_purge_invalid_goals, please report to the SCP!", ship_index); // get allender -- this is sort of odd
|
||||
if ( ship_index < 0 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
wingnum = Ships[ship_index].wingnum;
|
||||
|
||||
purge_goal = goal_list;
|
||||
@@ -726,7 +728,7 @@ void ai_goal_fixup_dockpoints(ai_info *aip, ai_goal *aigp)
|
||||
// from the mission goals (i.e. those goals which come from events) in that we don't
|
||||
// use sexpressions for goals from the player...so we enumerate all the parameters
|
||||
|
||||
void ai_add_goal_sub_player(int type, int mode, int submode, char *target_name, ai_goal *aigp, const ai_lua_parameters& lua_target )
|
||||
void ai_add_goal_sub_player(int type, int mode, int submode, const char *target_name, ai_goal *aigp, const ai_lua_parameters& lua_target )
|
||||
{
|
||||
Assert ( (type == AIG_TYPE_PLAYER_WING) || (type == AIG_TYPE_PLAYER_SHIP) );
|
||||
|
||||
@@ -749,6 +751,9 @@ void ai_add_goal_sub_player(int type, int mode, int submode, char *target_name,
|
||||
if ( target_name != NULL )
|
||||
aigp->target_name = ai_get_goal_target_name( target_name, &aigp->target_name_index );
|
||||
|
||||
if (The_mission.ai_profile->flags[AI::Profile_Flags::Player_orders_afterburn_hard])
|
||||
aigp->flags.set(AI::Goal_Flags::Afterburn_hard);
|
||||
|
||||
|
||||
// special case certain orders from player so that ships continue to do the right thing
|
||||
|
||||
@@ -813,7 +818,7 @@ int ai_goal_num(ai_goal *goals)
|
||||
}
|
||||
|
||||
|
||||
void ai_add_goal_sub_scripting(int type, int mode, int submode, int priority, char *target_name, ai_goal *aigp )
|
||||
void ai_add_goal_sub_scripting(int type, int mode, int submode, int priority, const char *target_name, ai_goal *aigp )
|
||||
{
|
||||
Assert ( (type == AIG_TYPE_PLAYER_WING) || (type == AIG_TYPE_PLAYER_SHIP) );
|
||||
|
||||
@@ -830,7 +835,7 @@ void ai_add_goal_sub_scripting(int type, int mode, int submode, int priority, ch
|
||||
aigp->priority = priority;
|
||||
}
|
||||
|
||||
void ai_add_ship_goal_scripting(int mode, int submode, int priority, char *shipname, ai_info *aip)
|
||||
void ai_add_ship_goal_scripting(int mode, int submode, int priority, const char *shipname, ai_info *aip)
|
||||
{
|
||||
int empty_index;
|
||||
ai_goal *aigp;
|
||||
@@ -854,7 +859,7 @@ void ai_add_ship_goal_scripting(int mode, int submode, int priority, char *shipn
|
||||
// is issued to ship or wing (from player), mode is AI_GOAL_*. submode is the submode the
|
||||
// ship should go into. shipname is the object of the action. aip is the ai_info pointer
|
||||
// of the ship receiving the order
|
||||
void ai_add_ship_goal_player( int type, int mode, int submode, char *shipname, ai_info *aip, const ai_lua_parameters& lua_target)
|
||||
void ai_add_ship_goal_player( int type, int mode, int submode, const char *shipname, ai_info *aip, const ai_lua_parameters& lua_target)
|
||||
{
|
||||
int empty_index;
|
||||
ai_goal *aigp;
|
||||
@@ -875,7 +880,7 @@ void ai_add_ship_goal_player( int type, int mode, int submode, char *shipname, a
|
||||
|
||||
// adds a goal from the player to the given wing (which in turn will add it to the proper
|
||||
// ships in the wing
|
||||
void ai_add_wing_goal_player( int type, int mode, int submode, char *shipname, int wingnum, const ai_lua_parameters& lua_target)
|
||||
void ai_add_wing_goal_player( int type, int mode, int submode, const char *shipname, int wingnum, const ai_lua_parameters& lua_target)
|
||||
{
|
||||
int i, empty_index;
|
||||
wing *wingp = &Wings[wingnum];
|
||||
@@ -899,7 +904,7 @@ void ai_add_wing_goal_player( int type, int mode, int submode, char *shipname, i
|
||||
|
||||
|
||||
// common routine to add a sexpression mission goal to the appropriate goal structure.
|
||||
void ai_add_goal_sub_sexp( int sexp, int type, ai_info *aip, ai_goal *aigp, char *actor_name )
|
||||
void ai_add_goal_sub_sexp( int sexp, int type, ai_info *aip, ai_goal *aigp, const char *actor_name )
|
||||
{
|
||||
int node, dummy, op;
|
||||
|
||||
@@ -913,22 +918,30 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_info *aip, ai_goal *aigp, char
|
||||
switch (op) {
|
||||
|
||||
case OP_AI_WAYPOINTS_ONCE:
|
||||
case OP_AI_WAYPOINTS: {
|
||||
case OP_AI_WAYPOINTS:
|
||||
{
|
||||
int ref_type;
|
||||
bool is_nan, is_nan_forever;
|
||||
|
||||
ref_type = Sexp_nodes[CDR(node)].subtype;
|
||||
if (ref_type == SEXP_ATOM_STRING || ref_type == SEXP_ATOM_CONTAINER_DATA) { // referenced by name
|
||||
// save the waypoint path name -- the list will get resolved when the goal is checked
|
||||
// for achievability.
|
||||
aigp->target_name = ai_get_goal_target_name(CTEXT(CDR(node)), &aigp->target_name_index); // waypoint path name;
|
||||
Assertion(ref_type == SEXP_ATOM_STRING || ref_type == SEXP_ATOM_CONTAINER_DATA, "Found a bad ref_type in ai_add_goal_sub_sexp of %d. Please report to the SCP!", ref_type);
|
||||
|
||||
// referenced by name
|
||||
// save the waypoint path name -- the list will get resolved when the goal is checked
|
||||
// for achievability.
|
||||
aigp->target_name = ai_get_goal_target_name(CTEXT(CDR(node)), &aigp->target_name_index); // waypoint path name;
|
||||
|
||||
} else
|
||||
Int3();
|
||||
|
||||
aigp->priority = atoi( CTEXT(CDR(CDR(node))) );
|
||||
aigp->ai_mode = AI_GOAL_WAYPOINTS;
|
||||
if ( op == OP_AI_WAYPOINTS_ONCE )
|
||||
aigp->ai_mode = AI_GOAL_WAYPOINTS_ONCE;
|
||||
if (CDDDDR(node) < 0)
|
||||
aigp->int_data = 0; // handle optional node separately because we don't subtract 1 here
|
||||
else
|
||||
aigp->int_data = eval_num(CDDDDR(node), is_nan, is_nan_forever) - 1;
|
||||
if (is_sexp_true(CDDDDDR(node)))
|
||||
aigp->flags.set(AI::Goal_Flags::Waypoints_in_reverse);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -990,9 +1003,9 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_info *aip, ai_goal *aigp, char
|
||||
// this goal needs some extra setup
|
||||
// if this doesn't work, the goal will be immediately removed
|
||||
auto ship_entry = ship_registry_get(aigp->target_name);
|
||||
if (ship_entry && ship_entry->shipp)
|
||||
if (ship_entry && ship_entry->has_shipp())
|
||||
{
|
||||
auto target_aip = &Ai_info[ship_entry->shipp->ai_index];
|
||||
auto target_aip = &Ai_info[ship_entry->shipp()->ai_index];
|
||||
target_aip->ai_flags.set(AI::AI_Flags::Awaiting_repair);
|
||||
Assertion(aip != nullptr, "Must provide aip if assigning a rearm goal!");
|
||||
ai_goal_fixup_dockpoints( aip, aigp );
|
||||
@@ -1452,15 +1465,8 @@ void ai_add_goal_ship_internal( ai_info *aip, int goal_type, char *name, int /*
|
||||
int gindex;
|
||||
ai_goal *aigp;
|
||||
|
||||
#ifndef NDEBUG
|
||||
// Goober5000 - none of the goals act on the actor, as in ai_add_goal_sub_sexp
|
||||
if (!strcmp(name, Ships[aip->shipnum].ship_name))
|
||||
{
|
||||
// not good
|
||||
Int3();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
Assertion(strcmp(name, Ships[aip->shipnum].ship_name) != 0, "The goals apply to the actor in ai_add_goal_ship_internal for ship %s, please report to the SCP!", name);
|
||||
|
||||
// find an empty slot to put this goal in.
|
||||
gindex = ai_goal_find_empty_slot( aip->goals, aip->active_goal );
|
||||
@@ -1511,7 +1517,7 @@ void ai_add_goal_ship_internal( ai_info *aip, int goal_type, char *name, int /*
|
||||
break;
|
||||
|
||||
default:
|
||||
Int3(); // unsupported internal goal -- see Mike K or Mark A.
|
||||
UNREACHABLE("unsupported internal goal of %d found in ai_add_goal_ship_internal. Please report to the SCP", goal_type); // see Mike K or Mark A.
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1589,7 +1595,7 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
|
||||
// if the wing target is valid then be sure to set the override bit so that it always
|
||||
// gets executed next
|
||||
if ( aigp->ai_mode == AI_GOAL_FORM_ON_WING ) {
|
||||
if (!target_ship_entry || !target_ship_entry->shipp)
|
||||
if (!target_ship_entry || !target_ship_entry->has_shipp())
|
||||
return ai_achievability::NOT_ACHIEVABLE;
|
||||
|
||||
aigp->flags.set(AI::Goal_Flags::Goal_override);
|
||||
@@ -1649,7 +1655,7 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
|
||||
|
||||
// can't determine the status of this goal if ship not valid
|
||||
// or we haven't found a valid subsystem index yet
|
||||
if ( !target_ship_entry || !target_ship_entry->shipp || (aigp->flags[AI::Goal_Flags::Subsys_needs_fixup]) ) {
|
||||
if ( !target_ship_entry || !target_ship_entry->has_shipp() || (aigp->flags[AI::Goal_Flags::Subsys_needs_fixup]) ) {
|
||||
status = 0;
|
||||
break;
|
||||
}
|
||||
@@ -1658,13 +1664,13 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
|
||||
// as 0 so we can continue. (The subsystem name must be turned into an index into the ship's subsystems
|
||||
// for this goal to be valid).
|
||||
Assert ( aigp->ai_submode >= 0 );
|
||||
ssp = ship_get_indexed_subsys( target_ship_entry->shipp, aigp->ai_submode );
|
||||
ssp = ship_get_indexed_subsys( target_ship_entry->shipp(), aigp->ai_submode );
|
||||
if (ssp != NULL) {
|
||||
// see MWA 3/20/97 comment above - instead of checking the mission log, check the current hits
|
||||
status = (ssp->current_hits <= 0.0f) ? 1 : 0;
|
||||
} else {
|
||||
// not supposed to ever happen, but could if there is a mismatch between the table and model subsystems
|
||||
nprintf(("AI", "Couldn't find subsystem %d for ship %s\n", aigp->ai_submode, target_ship_entry->shipp->ship_name));
|
||||
nprintf(("AI", "Couldn't find subsystem %d for ship %s\n", aigp->ai_submode, target_ship_entry->shipp()->ship_name));
|
||||
status = 0;
|
||||
}
|
||||
break;
|
||||
@@ -1677,11 +1683,11 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
|
||||
// destroyed when shipnum is valid
|
||||
|
||||
// can't determine the status of this goal if ship not valid
|
||||
if (!target_ship_entry || !target_ship_entry->shipp) {
|
||||
if (!target_ship_entry || !target_ship_entry->has_shipp()) {
|
||||
status = 0;
|
||||
} else {
|
||||
// see MWA 3/20/97 comment above - instead of checking the mission log, check the current hits
|
||||
status = (target_ship_entry->shipp->subsys_info[SUBSYSTEM_ENGINE].aggregate_current_hits <= 0.0f) ? 1 : 0;
|
||||
status = (target_ship_entry->shipp()->subsys_info[SUBSYSTEM_ENGINE].aggregate_current_hits <= 0.0f) ? 1 : 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1693,11 +1699,11 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
|
||||
// destroyed when shipnum is valid
|
||||
|
||||
// can't determine the status of this goal if ship not valid
|
||||
if (!target_ship_entry || !target_ship_entry->shipp) {
|
||||
if (!target_ship_entry || !target_ship_entry->has_shipp()) {
|
||||
status = 0;
|
||||
} else {
|
||||
// see MWA 3/20/97 comment above - instead of checking the mission log, check the current hits
|
||||
status = (target_ship_entry->shipp->subsys_info[SUBSYSTEM_TURRET].aggregate_current_hits <= 0.0f) ? 1 : 0;
|
||||
status = (target_ship_entry->shipp()->subsys_info[SUBSYSTEM_TURRET].aggregate_current_hits <= 0.0f) ? 1 : 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1725,8 +1731,8 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
|
||||
}
|
||||
|
||||
// fly-to-ship can potentially be determined
|
||||
if (aigp->ai_mode == AI_GOAL_FLY_TO_SHIP && target_ship_entry && target_ship_entry->objp) {
|
||||
auto dist = vm_vec_dist(&target_ship_entry->objp->pos, &objp->pos);
|
||||
if (aigp->ai_mode == AI_GOAL_FLY_TO_SHIP && target_ship_entry && target_ship_entry->has_objp()) {
|
||||
auto dist = vm_vec_dist(&target_ship_entry->objp()->pos, &objp->pos);
|
||||
if (dist < aigp->float_data) {
|
||||
return_val = ai_achievability::SATISFIED;
|
||||
status = 1;
|
||||
@@ -1840,9 +1846,9 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
|
||||
// Goober5000 - before doing anything else, check if this is a disarm goal for an arrived ship...
|
||||
if ((status == SHIP_STATUS_ARRIVED) && (aigp->ai_mode == AI_GOAL_DISARM_SHIP || aigp->ai_mode == AI_GOAL_DISARM_SHIP_TACTICAL))
|
||||
{
|
||||
if (target_ship_entry && target_ship_entry->shipp) {
|
||||
if (target_ship_entry && target_ship_entry->has_shipp()) {
|
||||
// if the ship has no turrets, we can't disarm it!
|
||||
if (target_ship_entry->shipp->subsys_info[SUBSYSTEM_TURRET].type_count == 0)
|
||||
if (target_ship_entry->shipp()->subsys_info[SUBSYSTEM_TURRET].type_count == 0)
|
||||
return ai_achievability::NOT_ACHIEVABLE;
|
||||
} else {
|
||||
UNREACHABLE("Target name %s is not an arrived ship!", aigp->target_name);
|
||||
@@ -1876,8 +1882,8 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
|
||||
}
|
||||
|
||||
if (!(aigp->flags[AI::Goal_Flags::Dockee_index_valid])) {
|
||||
if (target_ship_entry && target_ship_entry->shipp) {
|
||||
int modelnum = Ship_info[target_ship_entry->shipp->ship_info_index].model_num;
|
||||
if (target_ship_entry && target_ship_entry->has_shipp()) {
|
||||
int modelnum = Ship_info[target_ship_entry->shipp()->ship_info_index].model_num;
|
||||
aigp->dockee.index = model_find_dock_name_index(modelnum, aigp->dockee.name);
|
||||
aigp->flags.set(AI::Goal_Flags::Dockee_index_valid);
|
||||
} else
|
||||
@@ -1894,11 +1900,11 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
|
||||
return ai_achievability::NOT_KNOWN;
|
||||
|
||||
// we must also determine if we're prevented from docking for any reason
|
||||
if (!target_ship_entry || !target_ship_entry->shipp) {
|
||||
if (!target_ship_entry || !target_ship_entry->has_shipp()) {
|
||||
UNREACHABLE("Target name %s is not an arrived ship!", aigp->target_name);
|
||||
return ai_achievability::NOT_ACHIEVABLE; // force this goal to be invalid
|
||||
}
|
||||
auto goal_objp = target_ship_entry->objp;
|
||||
auto goal_objp = target_ship_entry->objp();
|
||||
|
||||
// if the ship that I am supposed to dock with is docked with something else, then I need to put my goal on hold
|
||||
// [MK, 4/23/98: With Mark, we believe this fixes the problem of Comet refusing to warp out after docking with Omega.
|
||||
@@ -1947,9 +1953,9 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
|
||||
// might happen too, so err on the safe side. (Yay for emergent paragraph justification!)
|
||||
if ((aip->mode == AIM_DOCK) && (aip->submode >= AIS_UNDOCK_0))
|
||||
{
|
||||
if ( target_ship_entry && target_ship_entry->shipp ) {
|
||||
if ( target_ship_entry && target_ship_entry->has_objp() ) {
|
||||
// only put it on hold if it's someone other than the guy we're undocking from right now!!
|
||||
if (aip->goal_objnum != target_ship_entry->shipp->objnum)
|
||||
if (aip->goal_objnum != target_ship_entry->objnum)
|
||||
return ai_achievability::NOT_KNOWN;
|
||||
} else {
|
||||
UNREACHABLE("Target name %s is not an arrived ship!", aigp->target_name);
|
||||
@@ -1962,8 +1968,8 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
|
||||
// have fixed up the subsystem name (of the subsystem to destroy) into an index into
|
||||
// the ship's subsystem list
|
||||
if ( aigp->flags[AI::Goal_Flags::Subsys_needs_fixup] ) {
|
||||
if ( target_ship_entry && target_ship_entry->shipp ) {
|
||||
aigp->ai_submode = ship_find_subsys( target_ship_entry->shipp, aigp->docker.name );
|
||||
if ( target_ship_entry && target_ship_entry->has_shipp() ) {
|
||||
aigp->ai_submode = ship_find_subsys( target_ship_entry->shipp(), aigp->docker.name );
|
||||
aigp->flags.remove(AI::Goal_Flags::Subsys_needs_fixup);
|
||||
} else {
|
||||
UNREACHABLE("Target name %s is not an arrived ship!", aigp->target_name);
|
||||
@@ -1972,11 +1978,11 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
|
||||
}
|
||||
} else if ( ((aigp->ai_mode == AI_GOAL_IGNORE) || (aigp->ai_mode == AI_GOAL_IGNORE_NEW)) && (status == SHIP_STATUS_ARRIVED) ) {
|
||||
// for ignoring a ship, call the ai_ignore object function, then declare the goal satisfied
|
||||
if (!target_ship_entry || !target_ship_entry->shipp) {
|
||||
if (!target_ship_entry || !target_ship_entry->has_objp()) {
|
||||
UNREACHABLE("Target name %s is not an arrived ship!", aigp->target_name);
|
||||
return ai_achievability::NOT_ACHIEVABLE; // force this goal to be invalid
|
||||
}
|
||||
auto ignored = target_ship_entry->objp;
|
||||
auto ignored = target_ship_entry->objp();
|
||||
|
||||
ai_ignore_object(objp, ignored, (aigp->ai_mode == AI_GOAL_IGNORE_NEW));
|
||||
|
||||
@@ -2030,22 +2036,22 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
|
||||
if ( status == SHIP_STATUS_GONE )
|
||||
return ai_achievability::NOT_ACHIEVABLE;
|
||||
|
||||
if ( !target_ship_entry || !target_ship_entry->shipp ) {
|
||||
if ( !target_ship_entry || !target_ship_entry->has_shipp() ) {
|
||||
UNREACHABLE("Target name %s is not an arrived ship!", aigp->target_name);
|
||||
return ai_achievability::NOT_ACHIEVABLE;
|
||||
}
|
||||
|
||||
// if destination currently being repaired, then goal is still active
|
||||
if ( Ai_info[target_ship_entry->shipp->ai_index].ai_flags[AI::AI_Flags::Being_repaired] )
|
||||
if ( Ai_info[target_ship_entry->shipp()->ai_index].ai_flags[AI::AI_Flags::Being_repaired] )
|
||||
return ai_achievability::ACHIEVABLE;
|
||||
|
||||
// if the destination ship is dying or departing (but not completed yet), the mark goal as
|
||||
// not achievable.
|
||||
if ( target_ship_entry->shipp->is_dying_or_departing())
|
||||
if ( target_ship_entry->shipp()->is_dying_or_departing())
|
||||
return ai_achievability::NOT_ACHIEVABLE;
|
||||
|
||||
// if the destination object is no longer awaiting repair, then remove the item
|
||||
if ( !(Ai_info[target_ship_entry->shipp->ai_index].ai_flags[AI::AI_Flags::Awaiting_repair]) )
|
||||
if ( !(Ai_info[target_ship_entry->shipp()->ai_index].ai_flags[AI::AI_Flags::Awaiting_repair]) )
|
||||
return ai_achievability::NOT_ACHIEVABLE;
|
||||
|
||||
// not repairing anything means that he can do this goal!!!
|
||||
@@ -2060,7 +2066,7 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
|
||||
// if he is repairing something, he can satisfy his repair goal (his goal_objnum)
|
||||
// return GOAL_NOT_KNOWN which is kind of a hack which puts the goal on hold until it can be
|
||||
// satisfied.
|
||||
if ( aip->goal_objnum != target_ship_entry->shipp->objnum )
|
||||
if ( aip->goal_objnum != target_ship_entry->objnum )
|
||||
return ai_achievability::NOT_KNOWN;
|
||||
|
||||
return ai_achievability::ACHIEVABLE;
|
||||
@@ -2334,10 +2340,11 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
|
||||
case AI_GOAL_WAYPOINTS: // do nothing for waypoints
|
||||
case AI_GOAL_WAYPOINTS_ONCE: {
|
||||
int flags = 0;
|
||||
|
||||
if ( current_goal->ai_mode == AI_GOAL_WAYPOINTS)
|
||||
if (current_goal->ai_mode == AI_GOAL_WAYPOINTS)
|
||||
flags |= WPF_REPEAT;
|
||||
ai_start_waypoints(objp, current_goal->wp_list, flags);
|
||||
if (current_goal->flags[AI::Goal_Flags::Waypoints_in_reverse])
|
||||
flags |= WPF_BACKTRACK;
|
||||
ai_start_waypoints(objp, current_goal->wp_list, flags, current_goal->int_data);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2544,7 +2551,7 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
|
||||
break;
|
||||
|
||||
default:
|
||||
Int3();
|
||||
UNREACHABLE("unsupported goal of %d found in ai_process_mission_orders. Please report to the SCP", current_goal->ai_mode);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -168,17 +168,17 @@ extern void ai_process_mission_orders( int objnum, ai_info *aip );
|
||||
extern int ai_goal_num(ai_goal *goals);
|
||||
|
||||
// adds goals to ships/wing through sexpressions
|
||||
extern void ai_add_ship_goal_scripting(int mode, int submode, int priority, char *shipname, ai_info *aip);
|
||||
extern void ai_add_ship_goal_scripting(int mode, int submode, int priority, const 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, wing *wingp );
|
||||
extern void ai_add_goal_sub_sexp( int sexp, int type, ai_info *aip, ai_goal *aigp, char *actor_name);
|
||||
extern void ai_add_goal_sub_sexp( int sexp, int type, ai_info *aip, ai_goal *aigp, const char *actor_name);
|
||||
|
||||
extern int ai_remove_goal_sexp_sub( int sexp, ai_goal* aigp );
|
||||
extern void ai_remove_wing_goal_sexp( int sexp, wing *wingp );
|
||||
|
||||
// adds goals to ships/sings through player orders
|
||||
extern void ai_add_ship_goal_player(int type, int mode, int submode, char* shipname, ai_info* aip, const ai_lua_parameters& lua_target = { object_ship_wing_point_team(), luacpp::LuaValueList{} });
|
||||
extern void ai_add_wing_goal_player(int type, int mode, int submode, char* shipname, int wingnum, const ai_lua_parameters& lua_target = { object_ship_wing_point_team(), luacpp::LuaValueList{} });
|
||||
extern void ai_add_ship_goal_player(int type, int mode, int submode, const char* shipname, ai_info* aip, const ai_lua_parameters& lua_target = { object_ship_wing_point_team(), luacpp::LuaValueList{} });
|
||||
extern void ai_add_wing_goal_player(int type, int mode, int submode, const char* shipname, int wingnum, const ai_lua_parameters& lua_target = { object_ship_wing_point_team(), luacpp::LuaValueList{} });
|
||||
|
||||
extern void ai_remove_ship_goal( ai_info *aip, int index );
|
||||
extern void ai_clear_ship_goals( ai_info *aip );
|
||||
|
||||
@@ -14,24 +14,24 @@
|
||||
#include "weapon/weapon.h"
|
||||
|
||||
//Returns true if the specified object is a stealth ship, false if not
|
||||
bool is_object_stealth_ship(object* objp);
|
||||
bool is_object_stealth_ship(const object* objp);
|
||||
|
||||
//Number of live turrets on the object attacking
|
||||
int num_turrets_attacking(object *turret_parent, int target_objnum);
|
||||
int num_turrets_attacking(const object *turret_parent, int target_objnum);
|
||||
|
||||
//Determine whether an object is targetable within a nebula (checks for stealth)
|
||||
int object_is_targetable(object *target, ship *viewer);
|
||||
bool object_is_targetable(const object *target, const ship *viewer);
|
||||
|
||||
//Returns the number of enemy fighters within threshold of pos.
|
||||
int num_nearby_fighters(int enemy_team_mask, vec3d *pos, float threshold);
|
||||
int num_nearby_fighters(int enemy_team_mask, const vec3d *pos, float threshold);
|
||||
|
||||
//Returns true if OK for *aip to fire its current weapon at its current target.
|
||||
int check_ok_to_fire(int objnum, int target_objnum, weapon_info *wip, int secondary_bank, ship_subsys* turret);
|
||||
bool check_ok_to_fire(int objnum, int target_objnum, const weapon_info *wip, int secondary_bank, const vec3d *firing_pos_global);
|
||||
|
||||
//Returns true if *aip has a line of sight to its current target.
|
||||
bool check_los(int objnum, int target_objnum, float threshold, int primary_bank, int secondary_bank, ship_subsys* turret);
|
||||
bool check_los(int objnum, int target_objnum, float threshold, int primary_bank, int secondary_bank, const vec3d *firing_pos_global);
|
||||
|
||||
//Does all the stuff needed to aim and fire a turret.
|
||||
void ai_turret_execute_behavior(ship *shipp, ship_subsys *ss);
|
||||
void ai_turret_execute_behavior(const ship *shipp, ship_subsys *ss);
|
||||
|
||||
#endif
|
||||
+23
-17
@@ -97,29 +97,35 @@ SCP_vector<SCP_string> ai_lua_get_general_order_categories(bool enabled_only)
|
||||
return list;
|
||||
}
|
||||
|
||||
// Provides a list of general orders for mission saving. You can only get one kind
|
||||
// of list at a time. If onlyEnabled and onlyValid are both true, for example, you will get
|
||||
// a list of onlyEnabled orders. If you need a list of enabled orders that are also valid, you'll
|
||||
// need to get both lists separately and compare.
|
||||
SCP_vector<SCP_string> ai_lua_get_general_orders(bool onlyEnabled, bool onlyValid, const SCP_string& category)
|
||||
{
|
||||
SCP_vector<SCP_string> list;
|
||||
|
||||
for (auto order : Lua_player_orders) {
|
||||
for (const auto& order : Lua_player_orders) {
|
||||
if (order.second.generalOrder) {
|
||||
bool add = false;
|
||||
|
||||
// Only enabled orders
|
||||
if (onlyEnabled && order.second.cur_enabled) {
|
||||
add = true;
|
||||
|
||||
// Only valid orders
|
||||
} else if (onlyValid && order.second.cur_valid) {
|
||||
add = true;
|
||||
|
||||
// Only orders that match the category requested
|
||||
} else if ((!category.empty()) && (order.second.category == category)) {
|
||||
add = true;
|
||||
|
||||
// All general orders
|
||||
} else {
|
||||
if (!onlyEnabled && !onlyValid && category.empty()) {
|
||||
add = true;
|
||||
} else {
|
||||
|
||||
// Only enabled orders
|
||||
if (onlyEnabled && order.second.cur_enabled) {
|
||||
add = true;
|
||||
|
||||
// Only valid orders
|
||||
} else if (onlyValid && order.second.cur_valid) {
|
||||
add = true;
|
||||
|
||||
// Only orders that match the category requested
|
||||
} else if ((!category.empty()) && (order.second.category == category)) {
|
||||
add = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (add) {
|
||||
@@ -161,7 +167,7 @@ void ai_lua_validate_general_order(int sexp_op, bool validity)
|
||||
}
|
||||
|
||||
void ai_lua_reset_general_orders() {
|
||||
for (auto order : Lua_player_orders) {
|
||||
for (const auto& order : Lua_player_orders) {
|
||||
ai_lua_enable_general_order(order.first, false);
|
||||
ai_lua_validate_general_order(order.first, false);
|
||||
}
|
||||
@@ -248,7 +254,7 @@ void ai_lua_start_general(int lua_sexp_id, int target_objnum)
|
||||
ai_info aip;
|
||||
aip.shipnum = -1;
|
||||
|
||||
if (target_objnum >= 0) {
|
||||
if (target_objnum >= 0 && Objects[target_objnum].type == OBJ_SHIP) {
|
||||
aip.lua_ai_target = {object_ship_wing_point_team(&Ships[Objects[target_objnum].instance]), {}};
|
||||
}
|
||||
|
||||
@@ -383,7 +389,7 @@ ai_achievability ai_lua_is_achievable(const ai_goal* aigp, int objnum){
|
||||
if (!retVals.empty() && retVals[0].getValueType() == luacpp::ValueType::USERDATA) {
|
||||
scripting::api::enum_h enumData;
|
||||
retVals[0].getValue(scripting::api::l_Enum.Get(&enumData));
|
||||
if (!enumData.IsValid()) {
|
||||
if (!enumData.isValid()) {
|
||||
Error(LOCATION, "LuaAI SEXP achievability hook returned an invalid avilability enum.");
|
||||
return ai_achievability::ACHIEVABLE;
|
||||
}
|
||||
|
||||
+230
-278
File diff suppressed because it is too large.
Load diff
@@ -22,19 +22,19 @@ anim_instance *init_anim_instance(anim *ptr, int bpp)
|
||||
{
|
||||
anim_instance *inst;
|
||||
|
||||
Assertion(ptr, "Bad pointer in init_anim_instance(), please report to the SCP!");
|
||||
if (!ptr) {
|
||||
Int3();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( ptr->flags & ANF_STREAMED ) {
|
||||
Assertion(ptr->file_offset > -1, "Bad file offset of %d in init_anim_instance(), please report to the SCP!", ptr->file_offset);
|
||||
if ( ptr->file_offset < 0 ) {
|
||||
Int3();
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
Assertion(ptr->data, "Bad data in init_anim_instance(), please report to the SCP!");
|
||||
if ( !ptr->data ) {
|
||||
Int3();
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
+239
-182
@@ -262,6 +262,25 @@ static void inner_bound_pos_fixup(asteroid_field *asfieldp, vec3d *pos)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Randomly select an asteroid subtype
|
||||
*/
|
||||
const SCP_string& pick_random_asteroid_type()
|
||||
{
|
||||
return Asteroid_field.field_asteroid_type[Random::next(static_cast<int>(Asteroid_field.field_asteroid_type.size()))];
|
||||
}
|
||||
|
||||
int get_asteroid_subtype_index_by_name(const SCP_string &name, int asteroid_idx) {
|
||||
asteroid_info* this_asteroid = &Asteroid_info[asteroid_idx];
|
||||
for (int i = 0; i < static_cast<int>(this_asteroid->subtypes.size()); i++) {
|
||||
if (this_asteroid->subtypes[i].type_name == name) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a single asteroid
|
||||
*/
|
||||
@@ -279,8 +298,8 @@ object *asteroid_create(asteroid_field *asfieldp, int asteroid_type, int asteroi
|
||||
int rand_base;
|
||||
|
||||
// bogus
|
||||
if(asfieldp == NULL) {
|
||||
return NULL;
|
||||
if(asfieldp == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for (n=0; n<MAX_ASTEROIDS; n++) {
|
||||
@@ -291,15 +310,11 @@ object *asteroid_create(asteroid_field *asfieldp, int asteroid_type, int asteroi
|
||||
|
||||
if (n >= MAX_ASTEROIDS) {
|
||||
nprintf(("Warning","Could not create asteroid, no more slots left\n"));
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if((asteroid_type < 0) || (asteroid_type >= (int)Asteroid_info.size())) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if((asteroid_subtype < 0) || (asteroid_subtype >= NUM_ASTEROID_POFS)) {
|
||||
return NULL;
|
||||
if (!SCP_vector_inbounds(Asteroid_info, asteroid_type)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// HACK: multiplayer asteroid subtype always 0 to keep subtype in sync
|
||||
@@ -309,9 +324,13 @@ object *asteroid_create(asteroid_field *asfieldp, int asteroid_type, int asteroi
|
||||
|
||||
asip = &Asteroid_info[asteroid_type];
|
||||
|
||||
// bogus
|
||||
if(asip->modelp[asteroid_subtype] == NULL) {
|
||||
return NULL;
|
||||
if (!SCP_vector_inbounds(asip->subtypes, asteroid_subtype)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// if the model is not loaded then abort
|
||||
if(asip->subtypes[asteroid_subtype].model_pointer == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
asp = &Asteroids[n];
|
||||
@@ -326,7 +345,7 @@ object *asteroid_create(asteroid_field *asfieldp, int asteroid_type, int asteroi
|
||||
asp->collide_objsig = -1;
|
||||
asp->target_objnum = -1;
|
||||
|
||||
radius = model_get_radius(asip->model_num[asteroid_subtype]);
|
||||
radius = model_get_radius(asip->subtypes[asteroid_subtype].model_number);
|
||||
|
||||
vm_vec_sub(&delta_bound, &asfieldp->max_bound, &asfieldp->min_bound);
|
||||
|
||||
@@ -379,8 +398,8 @@ object *asteroid_create(asteroid_field *asfieldp, int asteroid_type, int asteroi
|
||||
asp->objnum = objnum;
|
||||
asp->model_instance_num = -1;
|
||||
|
||||
if (model_get(asip->model_num[asteroid_subtype])->flags & PM_FLAG_HAS_INTRINSIC_MOTION) {
|
||||
asp->model_instance_num = model_create_instance(objnum, asip->model_num[asteroid_subtype]);
|
||||
if (model_get(asip->subtypes[asteroid_subtype].model_number)->flags & PM_FLAG_HAS_INTRINSIC_MOTION) {
|
||||
asp->model_instance_num = model_create_instance(objnum, asip->subtypes[asteroid_subtype].model_number);
|
||||
}
|
||||
|
||||
// Add to Asteroid_used_list
|
||||
@@ -401,12 +420,12 @@ object *asteroid_create(asteroid_field *asfieldp, int asteroid_type, int asteroi
|
||||
vec3d rotvel;
|
||||
if ( Game_mode & GM_NORMAL ) {
|
||||
vm_vec_rand_vec_quick(&rotvel);
|
||||
vm_vec_scale(&rotvel, frand()/4.0f + 0.1f);
|
||||
vm_vec_scale(&rotvel, asip->rotational_vel_multiplier * (frand()/4.0f + 0.1f));
|
||||
objp->phys_info.rotvel = rotvel;
|
||||
vm_vec_rand_vec_quick(&objp->phys_info.vel);
|
||||
} else {
|
||||
static_randvec( rand_base++, &rotvel );
|
||||
vm_vec_scale(&rotvel, static_randf(rand_base++)/4.0f + 0.1f);
|
||||
vm_vec_scale(&rotvel, asip->rotational_vel_multiplier * (static_randf(rand_base++)/4.0f + 0.1f));
|
||||
objp->phys_info.rotvel = rotvel;
|
||||
static_randvec( rand_base++, &objp->phys_info.vel );
|
||||
}
|
||||
@@ -435,8 +454,8 @@ object *asteroid_create(asteroid_field *asfieldp, int asteroid_type, int asteroi
|
||||
objp->phys_info.max_vel.xyz.y = 0.0f;
|
||||
objp->phys_info.max_vel.xyz.z = vm_vec_mag(&objp->phys_info.desired_vel);
|
||||
|
||||
objp->phys_info.mass = asip->modelp[asteroid_subtype]->rad * 700.0f;
|
||||
objp->phys_info.I_body_inv.vec.rvec.xyz.x = 1.0f / (objp->phys_info.mass*asip->modelp[asteroid_subtype]->rad);
|
||||
objp->phys_info.mass = asip->subtypes[asteroid_subtype].model_pointer->rad * 700.0f;
|
||||
objp->phys_info.I_body_inv.vec.rvec.xyz.x = 1.0f / (objp->phys_info.mass*asip->subtypes[asteroid_subtype].model_pointer->rad);
|
||||
objp->phys_info.I_body_inv.vec.uvec.xyz.y = objp->phys_info.I_body_inv.vec.rvec.xyz.x;
|
||||
objp->phys_info.I_body_inv.vec.fvec.xyz.z = objp->phys_info.I_body_inv.vec.rvec.xyz.x;
|
||||
objp->hull_strength = asip->initial_asteroid_strength * (0.8f + (float)Game_skill_level/NUM_SKILL_LEVELS)/2.0f;
|
||||
@@ -465,7 +484,8 @@ void asteroid_sub_create(object *parent_objp, int asteroid_type, vec3d *relvec)
|
||||
int subtype = Asteroids[parent_objp->instance].asteroid_subtype;
|
||||
new_objp = asteroid_create(&Asteroid_field, asteroid_type, subtype);
|
||||
|
||||
if (new_objp == NULL)
|
||||
// New asteroid size doesn't have this subtype, so abort
|
||||
if (new_objp == nullptr)
|
||||
return;
|
||||
|
||||
if ( MULTIPLAYER_MASTER ){
|
||||
@@ -502,27 +522,35 @@ static void asteroid_load(int asteroid_info_index, int asteroid_subtype)
|
||||
int i;
|
||||
asteroid_info *asip;
|
||||
|
||||
Assertion(asteroid_info_index < (int)Asteroid_info.size(), "Command to load asteroid at index %i, but only %i asteroids exist", asteroid_info_index, (int)Asteroid_info.size());
|
||||
Assertion(asteroid_subtype < NUM_ASTEROID_POFS, "Command to load asteroid pof %i, but only %i pofs are allowed", asteroid_subtype, NUM_ASTEROID_POFS);
|
||||
Assertion(asteroid_info_index < static_cast<int>(Asteroid_info.size()),
|
||||
"Command to load asteroid at index %i, but only %i asteroids exist",
|
||||
asteroid_info_index,
|
||||
static_cast<int>(Asteroid_info.size()));
|
||||
|
||||
if ( (asteroid_info_index >= (int)Asteroid_info.size()) || (asteroid_subtype >= NUM_ASTEROID_POFS) ) {
|
||||
// invalid asteroid index
|
||||
if (!SCP_vector_inbounds(Asteroid_info, asteroid_info_index)) {
|
||||
return;
|
||||
}
|
||||
|
||||
asip = &Asteroid_info[asteroid_info_index];
|
||||
|
||||
if ( !VALID_FNAME(asip->pof_files[asteroid_subtype]) )
|
||||
// This asteroid does not have this subtype so just return
|
||||
if (!SCP_vector_inbounds(asip->subtypes, asteroid_subtype)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !VALID_FNAME(asip->subtypes[asteroid_subtype].pof_filename) )
|
||||
return;
|
||||
|
||||
//Check if the model is already loaded
|
||||
if (asip->model_num[asteroid_subtype] >= 0)
|
||||
if (asip->subtypes[asteroid_subtype].model_number >= 0)
|
||||
return;
|
||||
|
||||
asip->model_num[asteroid_subtype] = model_load( asip->pof_files[asteroid_subtype], 0, NULL );
|
||||
asip->subtypes[asteroid_subtype].model_number = model_load( asip->subtypes[asteroid_subtype].pof_filename, 0, nullptr );
|
||||
|
||||
if (asip->model_num[asteroid_subtype] >= 0)
|
||||
if (asip->subtypes[asteroid_subtype].model_number >= 0)
|
||||
{
|
||||
polymodel *pm = asip->modelp[asteroid_subtype] = model_get(asip->model_num[asteroid_subtype]);
|
||||
polymodel *pm = asip->subtypes[asteroid_subtype].model_pointer = model_get(asip->subtypes[asteroid_subtype].model_number);
|
||||
|
||||
if ( asip->num_detail_levels != pm->n_detail_levels )
|
||||
{
|
||||
@@ -553,10 +581,11 @@ void asteroid_create_all()
|
||||
// each different type (size) of debris piece has a diffenent weight, smaller weighted more heavily than larger.
|
||||
// choose next type from table ship_debris_odds_table by Random::next()%max_weighted_range,
|
||||
// the threshold *below* which the debris type is selected.
|
||||
struct {
|
||||
struct ShipDebrisOdds {
|
||||
float random_threshold;
|
||||
int debris_type;
|
||||
} ship_debris_odds_table[MAX_ACTIVE_DEBRIS_TYPES];
|
||||
};
|
||||
std::vector<ShipDebrisOdds> shipDebrisOddsTable(Asteroid_field.field_debris_type.size());
|
||||
|
||||
float max_weighted_range = 0.0f;
|
||||
|
||||
@@ -567,7 +596,8 @@ void asteroid_create_all()
|
||||
return;
|
||||
}
|
||||
|
||||
if (Asteroid_field.num_used_field_debris_types <= 0) {
|
||||
if ((Asteroid_field.debris_genre == DG_DEBRIS && Asteroid_field.field_debris_type.empty()) ||
|
||||
(Asteroid_field.debris_genre == DG_ASTEROID && Asteroid_field.field_asteroid_type.empty())) {
|
||||
Warning(LOCATION, "An asteroid field is enabled, but no asteroid types were enabled.");
|
||||
return;
|
||||
}
|
||||
@@ -602,45 +632,29 @@ void asteroid_create_all()
|
||||
|
||||
int num_debris_types = 0;
|
||||
|
||||
// get number of ship debris types
|
||||
// get number of debris types
|
||||
if (Asteroid_field.debris_genre == DG_DEBRIS) {
|
||||
for (idx=0; idx<MAX_ACTIVE_DEBRIS_TYPES; idx++) {
|
||||
if (Asteroid_field.field_debris_type[idx] != -1) {
|
||||
num_debris_types++;
|
||||
}
|
||||
}
|
||||
num_debris_types = static_cast<int>(Asteroid_field.field_debris_type.size());
|
||||
|
||||
// Calculate the odds table
|
||||
for (idx=0; idx<num_debris_types; idx++) {
|
||||
float debris_weight = Asteroid_info[Asteroid_field.field_debris_type[idx]].spawn_weight;
|
||||
ship_debris_odds_table[idx].random_threshold = max_weighted_range + debris_weight;
|
||||
ship_debris_odds_table[idx].debris_type = Asteroid_field.field_debris_type[idx];
|
||||
shipDebrisOddsTable[idx].random_threshold = max_weighted_range + debris_weight;
|
||||
shipDebrisOddsTable[idx].debris_type = Asteroid_field.field_debris_type[idx];
|
||||
max_weighted_range += debris_weight;
|
||||
}
|
||||
}
|
||||
|
||||
// Load Asteroid/ship models
|
||||
// Load Asteroid/debris models
|
||||
if (Asteroid_field.debris_genre == DG_DEBRIS) {
|
||||
for (idx=0; idx<num_debris_types; idx++) {
|
||||
asteroid_load(Asteroid_field.field_debris_type[idx], 0);
|
||||
}
|
||||
} else {
|
||||
if (Asteroid_field.field_debris_type[0] != -1) {
|
||||
asteroid_load(ASTEROID_TYPE_SMALL, 0);
|
||||
asteroid_load(ASTEROID_TYPE_MEDIUM, 0);
|
||||
asteroid_load(ASTEROID_TYPE_LARGE, 0);
|
||||
}
|
||||
|
||||
if (Asteroid_field.field_debris_type[1] != -1) {
|
||||
asteroid_load(ASTEROID_TYPE_SMALL, 1);
|
||||
asteroid_load(ASTEROID_TYPE_MEDIUM, 1);
|
||||
asteroid_load(ASTEROID_TYPE_LARGE, 1);
|
||||
}
|
||||
|
||||
if (Asteroid_field.field_debris_type[2] != -1) {
|
||||
asteroid_load(ASTEROID_TYPE_SMALL, 2);
|
||||
asteroid_load(ASTEROID_TYPE_MEDIUM, 2);
|
||||
asteroid_load(ASTEROID_TYPE_LARGE, 2);
|
||||
for (const auto& subtype : Asteroid_field.field_asteroid_type) {
|
||||
asteroid_load(ASTEROID_TYPE_SMALL, get_asteroid_subtype_index_by_name(subtype, ASTEROID_TYPE_SMALL));
|
||||
asteroid_load(ASTEROID_TYPE_MEDIUM, get_asteroid_subtype_index_by_name(subtype, ASTEROID_TYPE_MEDIUM));
|
||||
asteroid_load(ASTEROID_TYPE_LARGE, get_asteroid_subtype_index_by_name(subtype, ASTEROID_TYPE_LARGE));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -650,17 +664,7 @@ void asteroid_create_all()
|
||||
// For asteroid, load only large asteroids
|
||||
|
||||
// get a valid subtype
|
||||
int counter = Random::next(Asteroid_field.num_used_field_debris_types);
|
||||
int subtype = -1;
|
||||
for (int j = 0; j < NUM_ASTEROID_POFS; j++) {
|
||||
if (Asteroid_field.field_debris_type[j] >= 0) {
|
||||
if (counter == 0) {
|
||||
subtype = j;
|
||||
break;
|
||||
} else
|
||||
counter--;
|
||||
}
|
||||
}
|
||||
int subtype = get_asteroid_subtype_index_by_name(pick_random_asteroid_type(), ASTEROID_TYPE_LARGE);
|
||||
|
||||
if (subtype >= 0)
|
||||
asteroid_create(&Asteroid_field, ASTEROID_TYPE_LARGE, subtype);
|
||||
@@ -669,10 +673,10 @@ void asteroid_create_all()
|
||||
|
||||
float rand_choice = frand() * max_weighted_range;
|
||||
|
||||
for (idx=0; idx<MAX_ACTIVE_DEBRIS_TYPES; idx++) {
|
||||
for (idx = 0; idx < static_cast<int>(Asteroid_field.field_debris_type.size()); idx++) {
|
||||
// for ship debris, choose type according to odds table
|
||||
if (rand_choice < ship_debris_odds_table[idx].random_threshold) {
|
||||
asteroid_create(&Asteroid_field, ship_debris_odds_table[idx].debris_type, 0);
|
||||
if (rand_choice < shipDebrisOddsTable[idx].random_threshold) {
|
||||
asteroid_create(&Asteroid_field, shipDebrisOddsTable[idx].debris_type, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -698,7 +702,7 @@ void remove_all_asteroids()
|
||||
}
|
||||
|
||||
// will replace any existing asteroid or debris field with an asteroid field
|
||||
void asteroid_create_asteroid_field(int num_asteroids, int field_type, int asteroid_speed, bool brown, bool blue, bool orange, vec3d o_min, vec3d o_max, bool inner_box, vec3d i_min, vec3d i_max, SCP_vector<SCP_string> targets)
|
||||
void asteroid_create_asteroid_field(int num_asteroids, int field_type, int asteroid_speed, vec3d o_min, vec3d o_max, bool inner_box, vec3d i_min, vec3d i_max, SCP_vector<SCP_string> asteroid_types)
|
||||
{
|
||||
remove_all_asteroids();
|
||||
|
||||
@@ -732,25 +736,11 @@ void asteroid_create_asteroid_field(int num_asteroids, int field_type, int aster
|
||||
Asteroid_field.speed = (float)asteroid_speed;
|
||||
Asteroid_field.debris_genre = DG_ASTEROID;
|
||||
|
||||
Asteroid_field.field_debris_type[0] = -1;
|
||||
Asteroid_field.field_debris_type[1] = -1;
|
||||
Asteroid_field.field_debris_type[2] = -1;
|
||||
Asteroid_field.field_debris_type.clear();
|
||||
|
||||
int count = 0;
|
||||
if (brown) {
|
||||
Asteroid_field.field_debris_type[0] = 1;
|
||||
count++;
|
||||
}
|
||||
if (blue) {
|
||||
Asteroid_field.field_debris_type[1] = 1;
|
||||
count++;
|
||||
}
|
||||
if (orange) {
|
||||
Asteroid_field.field_debris_type[2] = 1;
|
||||
count++;
|
||||
}
|
||||
Asteroid_field.field_asteroid_type.clear();
|
||||
|
||||
Asteroid_field.num_used_field_debris_types = count;
|
||||
Asteroid_field.field_asteroid_type = std::move(asteroid_types);
|
||||
|
||||
Asteroid_field.min_bound = o_min;
|
||||
Asteroid_field.max_bound = o_max;
|
||||
@@ -768,16 +758,14 @@ void asteroid_create_asteroid_field(int num_asteroids, int field_type, int aster
|
||||
Asteroid_field.inner_max_bound = i_max;
|
||||
}
|
||||
|
||||
Asteroid_field.target_names = targets;
|
||||
|
||||
// Only create asteroids if we have some to create
|
||||
if ((count > 0) && (num_asteroids > 0)) {
|
||||
if ((!Asteroid_field.field_asteroid_type.empty()) && (num_asteroids > 0)) {
|
||||
asteroid_create_all();
|
||||
}
|
||||
}
|
||||
|
||||
// will replace any existing asteroid or debris field with a debris field
|
||||
void asteroid_create_debris_field(int num_asteroids, int asteroid_speed, int debris1, int debris2, int debris3, vec3d o_min, vec3d o_max, bool enhanced)
|
||||
void asteroid_create_debris_field(int num_asteroids, int asteroid_speed, SCP_vector<int> debris_types, vec3d o_min, vec3d o_max, bool enhanced)
|
||||
{
|
||||
remove_all_asteroids();
|
||||
|
||||
@@ -792,33 +780,11 @@ void asteroid_create_debris_field(int num_asteroids, int asteroid_speed, int deb
|
||||
Asteroid_field.speed = (float)asteroid_speed;
|
||||
Asteroid_field.debris_genre = DG_DEBRIS;
|
||||
|
||||
Asteroid_field.field_debris_type[0] = -1;
|
||||
Asteroid_field.field_debris_type[1] = -1;
|
||||
Asteroid_field.field_debris_type[2] = -1;
|
||||
Asteroid_field.field_debris_type.clear();
|
||||
|
||||
int count = 0;
|
||||
for (int i = 0; i < MAX_ACTIVE_DEBRIS_TYPES; i++) {
|
||||
if (debris1 >= 0) {
|
||||
Asteroid_field.field_debris_type[i] = debris1;
|
||||
debris1 = -1;
|
||||
count++;
|
||||
continue;
|
||||
}
|
||||
if (debris2 >= 0) {
|
||||
Asteroid_field.field_debris_type[i] = debris2;
|
||||
debris2 = -1;
|
||||
count++;
|
||||
continue;
|
||||
}
|
||||
if (debris3 >= 0) {
|
||||
Asteroid_field.field_debris_type[i] = debris3;
|
||||
debris3 = -1;
|
||||
count++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
Asteroid_field.field_asteroid_type.clear();
|
||||
|
||||
Asteroid_field.num_used_field_debris_types = count;
|
||||
Asteroid_field.field_debris_type = std::move(debris_types);
|
||||
|
||||
Asteroid_field.min_bound = o_min;
|
||||
Asteroid_field.max_bound = o_max;
|
||||
@@ -831,7 +797,7 @@ void asteroid_create_debris_field(int num_asteroids, int asteroid_speed, int deb
|
||||
Asteroid_field.bound_rad = MAX(3000.0f, b_rad);
|
||||
|
||||
// Only create debris if we have some to create
|
||||
if ((count > 0) && (num_asteroids > 0)) {
|
||||
if ((!Asteroid_field.field_debris_type.empty()) && (num_asteroids > 0)) {
|
||||
asteroid_create_all();
|
||||
}
|
||||
}
|
||||
@@ -850,10 +816,8 @@ void asteroid_level_init()
|
||||
Asteroid_field.has_inner_bound = false;
|
||||
Asteroid_field.field_type = FT_ACTIVE;
|
||||
Asteroid_field.debris_genre = DG_ASTEROID;
|
||||
Asteroid_field.field_debris_type[0] = -1;
|
||||
Asteroid_field.field_debris_type[1] = -1;
|
||||
Asteroid_field.field_debris_type[2] = -1;
|
||||
Asteroid_field.num_used_field_debris_types = 0;
|
||||
Asteroid_field.field_debris_type.clear();
|
||||
Asteroid_field.field_asteroid_type.clear();
|
||||
Asteroid_field.target_names.clear();
|
||||
|
||||
if (!Fred_running)
|
||||
@@ -1049,6 +1013,7 @@ bool asteroid_is_within_view(vec3d *pos, float range, bool range_override)
|
||||
*/
|
||||
static void maybe_throw_asteroid()
|
||||
{
|
||||
Assertion(!Asteroid_field.field_asteroid_type.empty(), "maybe_throw_asteroid() called while field_asteroid_type.size was 0; this should never happen, get a coder!");
|
||||
|
||||
for (asteroid_target& target : Asteroid_targets) {
|
||||
if (!timestamp_elapsed(target.throw_stamp))
|
||||
@@ -1066,18 +1031,8 @@ static void maybe_throw_asteroid()
|
||||
|
||||
target.throw_stamp = _timestamp(1000 + 1200 * target.incoming_asteroids / (Game_skill_level+1));
|
||||
|
||||
int counter = Random::next(Asteroid_field.num_used_field_debris_types);
|
||||
int subtype = -1;
|
||||
for (int i = 0; i < NUM_ASTEROID_POFS; i++) {
|
||||
if (Asteroid_field.field_debris_type[i] >= 0) {
|
||||
if (counter == 0) {
|
||||
subtype = i;
|
||||
break;
|
||||
}
|
||||
else
|
||||
counter--;
|
||||
}
|
||||
}
|
||||
// get a valid subtype
|
||||
int subtype = get_asteroid_subtype_index_by_name(pick_random_asteroid_type(), ASTEROID_TYPE_LARGE);
|
||||
|
||||
// this really shouldn't happen but just in case...
|
||||
if (subtype < 0)
|
||||
@@ -1254,7 +1209,7 @@ int asteroid_check_collision(object *pasteroid, object *other_obj, vec3d *hitpos
|
||||
// asteroid weapon collision
|
||||
Assert( other_obj->type == OBJ_WEAPON );
|
||||
mc.model_instance_num = Asteroids[num].model_instance_num;
|
||||
mc.model_num = Asteroid_info[Asteroids[num].asteroid_type].model_num[asteroid_subtype]; // Fill in the model to check
|
||||
mc.model_num = Asteroid_info[Asteroids[num].asteroid_type].subtypes[asteroid_subtype].model_number; // Fill in the model to check
|
||||
mc.orient = &pasteroid->orient; // The object's orient
|
||||
mc.pos = &pasteroid->pos; // The object's position
|
||||
mc.p0 = &other_obj->last_pos; // Point 1 of ray to check
|
||||
@@ -1332,10 +1287,9 @@ int asteroid_check_collision(object *pasteroid, object *other_obj, vec3d *hitpos
|
||||
mc.flags = (MC_CHECK_MODEL | MC_CHECK_SPHERELINE);
|
||||
|
||||
// copy important data
|
||||
int copy_flags = mc.flags; // make a copy of start end positions of sphere in big ship RF
|
||||
vec3d copy_p0, copy_p1;
|
||||
copy_p0 = *mc.p0;
|
||||
copy_p1 = *mc.p1;
|
||||
int orig_flags = mc.flags; // make a copy of start end positions of sphere in big ship RF
|
||||
vec3d orig_p0 = *mc.p0;
|
||||
vec3d orig_p1 = *mc.p1;
|
||||
|
||||
// first test against the sphere - if this fails then don't do any submodel tests
|
||||
mc.flags = MC_ONLY_SPHERE | MC_CHECK_SPHERELINE;
|
||||
@@ -1361,7 +1315,7 @@ int asteroid_check_collision(object *pasteroid, object *other_obj, vec3d *hitpos
|
||||
}
|
||||
|
||||
// Only check single submodel now, since children of moving submodels are handled as moving as well
|
||||
mc.flags = copy_flags | MC_SUBMODEL;
|
||||
mc.flags = orig_flags | MC_SUBMODEL;
|
||||
|
||||
// check each submodel in turn
|
||||
for (auto submodel: submodel_vector) {
|
||||
@@ -1406,9 +1360,9 @@ int asteroid_check_collision(object *pasteroid, object *other_obj, vec3d *hitpos
|
||||
}
|
||||
|
||||
// Now complete base model collision checks that do not take into account rotating submodels.
|
||||
mc.flags = copy_flags;
|
||||
*mc.p0 = copy_p0;
|
||||
*mc.p1 = copy_p1;
|
||||
mc.flags = orig_flags;
|
||||
mc.p0 = &orig_p0;
|
||||
mc.p1 = &orig_p1;
|
||||
mc.orient = &heavy_obj->orient;
|
||||
|
||||
// usual ship_ship collision test
|
||||
@@ -1436,7 +1390,7 @@ int asteroid_check_collision(object *pasteroid, object *other_obj, vec3d *hitpos
|
||||
} else {
|
||||
// Asteroid is heavier obj
|
||||
mc.model_instance_num = Asteroids[num].model_instance_num;
|
||||
mc.model_num = Asteroid_info[Asteroids[num].asteroid_type].model_num[asteroid_subtype]; // Fill in the model to check
|
||||
mc.model_num = Asteroid_info[Asteroids[num].asteroid_type].subtypes[asteroid_subtype].model_number; // Fill in the model to check
|
||||
mc.orient = &pasteroid->orient; // The object's orient
|
||||
mc.radius = model_get_core_radius(Ship_info[Ships[pship_obj->instance].ship_info_index].model_num);
|
||||
|
||||
@@ -1517,14 +1471,16 @@ void asteroid_render(object * obj, model_draw_list *scene)
|
||||
|
||||
Assert( asp->flags & AF_USED );
|
||||
|
||||
model_clear_instance( Asteroid_info[asp->asteroid_type].model_num[asp->asteroid_subtype]);
|
||||
model_clear_instance( Asteroid_info[asp->asteroid_type].subtypes[asp->asteroid_subtype].model_number);
|
||||
|
||||
model_render_params render_info;
|
||||
|
||||
render_info.set_object_number( OBJ_INDEX(obj) );
|
||||
render_info.set_flags(MR_IS_ASTEROID);
|
||||
if (asp->model_instance_num >= 0)
|
||||
render_info.set_replacement_textures(model_get_instance(asp->model_instance_num)->texture_replace);
|
||||
|
||||
model_render_queue(&render_info, scene, Asteroid_info[asp->asteroid_type].model_num[asp->asteroid_subtype], &obj->orient, &obj->pos); // Replace MR_NORMAL with 0x07 for big yellow blobs
|
||||
model_render_queue(&render_info, scene, Asteroid_info[asp->asteroid_type].subtypes[asp->asteroid_subtype].model_number, &obj->orient, &obj->pos); // Replace MR_NORMAL with 0x07 for big yellow blobs
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1593,9 +1549,8 @@ static float asteroid_create_explosion(object *objp)
|
||||
fireball_type = FIREBALL_ASTEROID;
|
||||
}
|
||||
|
||||
if (fireball_type >= Num_fireball_types) {
|
||||
Warning(LOCATION, "Invalid fireball type %i specified for an asteroid, only %i fireball types are defined.", fireball_type, Num_fireball_types);
|
||||
|
||||
if (fireball_type >= static_cast<int>(Fireball_info.size())) {
|
||||
Warning(LOCATION, "Invalid fireball type %i specified for an asteroid; only " SIZE_T_ARG " fireball types are defined.", fireball_type, Fireball_info.size());
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1759,9 +1714,10 @@ void asteroid_level_close()
|
||||
|
||||
//when a level is closed, all models are cleared, so let's make sure that
|
||||
//is tracked for asteroids as well -Mjn
|
||||
for (int i = 0; i < (int)Asteroid_info.size(); i++) {
|
||||
for (int j = 0; j < NUM_ASTEROID_POFS; j++) {
|
||||
Asteroid_info[i].model_num[j] = -1;
|
||||
for (size_t i = 0; i < Asteroid_info.size(); i++) {
|
||||
for (size_t j = 0; j < Asteroid_info[i].subtypes.size(); j++) {
|
||||
Asteroid_info[i].subtypes[j].model_number = -1;
|
||||
Asteroid_info[i].subtypes[j].model_pointer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2220,15 +2176,71 @@ static void asteroid_parse_section()
|
||||
}
|
||||
|
||||
if (optional_string("$POF file1:")) {
|
||||
stuff_string(asteroid_p->pof_files[0], F_NAME, MAX_FILENAME_LEN);
|
||||
asteroid_subtype_info thisType;
|
||||
|
||||
thisType.type_name = "Brown";
|
||||
|
||||
stuff_string(thisType.pof_filename, F_NAME, MAX_FILENAME_LEN);
|
||||
|
||||
thisType.model_number = -1;
|
||||
thisType.model_pointer = nullptr;
|
||||
|
||||
asteroid_p->subtypes.push_back(thisType);
|
||||
}
|
||||
|
||||
if (optional_string("$POF file2:")) {
|
||||
stuff_string(asteroid_p->pof_files[1], F_NAME, MAX_FILENAME_LEN);
|
||||
asteroid_subtype_info thisType;
|
||||
|
||||
thisType.type_name = "Blue";
|
||||
stuff_string(thisType.pof_filename, F_NAME, MAX_FILENAME_LEN);
|
||||
|
||||
thisType.model_number = -1;
|
||||
thisType.model_pointer = nullptr;
|
||||
|
||||
asteroid_p->subtypes.push_back(thisType);
|
||||
}
|
||||
|
||||
if (optional_string("$POF file3:")) {
|
||||
stuff_string(asteroid_p->pof_files[2], F_NAME, MAX_FILENAME_LEN);
|
||||
asteroid_subtype_info thisType;
|
||||
|
||||
thisType.type_name = "Orange";
|
||||
stuff_string(thisType.pof_filename, F_NAME, MAX_FILENAME_LEN);
|
||||
|
||||
thisType.model_number = -1;
|
||||
thisType.model_pointer = nullptr;
|
||||
|
||||
asteroid_p->subtypes.push_back(thisType);
|
||||
}
|
||||
|
||||
// For asteroid types we can have unlimited subtypes
|
||||
if (asteroid_p->type != ASTEROID_TYPE_DEBRIS) {
|
||||
while (optional_string("$Subtype:")) {
|
||||
asteroid_subtype_info thisType;
|
||||
|
||||
stuff_string(thisType.type_name, F_NAME);
|
||||
|
||||
required_string("+POF file:");
|
||||
stuff_string(thisType.pof_filename, F_NAME, MAX_FILENAME_LEN);
|
||||
|
||||
thisType.model_number = -1;
|
||||
thisType.model_pointer = nullptr;
|
||||
|
||||
bool exists = false;
|
||||
for (const auto& type : asteroid_p->subtypes) {
|
||||
if (type.type_name == thisType.type_name) {
|
||||
exists = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (exists) {
|
||||
error_display(0,
|
||||
"Asteroid subtype %s already exists for asteroid %s",
|
||||
thisType.type_name.c_str(),
|
||||
asteroid_p->name);
|
||||
} else {
|
||||
asteroid_p->subtypes.push_back(thisType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (optional_string("$Detail distance:")) {
|
||||
@@ -2239,6 +2251,10 @@ static void asteroid_parse_section()
|
||||
stuff_float(&asteroid_p->max_speed);
|
||||
}
|
||||
|
||||
if (optional_string("$Rotational Velocity Multiplier:")) {
|
||||
stuff_float(&asteroid_p->rotational_vel_multiplier);
|
||||
}
|
||||
|
||||
if(optional_string("$Damage Type:")) {
|
||||
char buf[NAME_LENGTH];
|
||||
stuff_string(buf, F_NAME, NAME_LENGTH);
|
||||
@@ -2247,10 +2263,7 @@ static void asteroid_parse_section()
|
||||
}
|
||||
|
||||
if(optional_string("$Explosion Animations:")){
|
||||
int temp[MAX_FIREBALL_TYPES];
|
||||
auto parsed_ints = stuff_int_list(temp, MAX_FIREBALL_TYPES, RAW_INTEGER_TYPE);
|
||||
asteroid_p->explosion_bitmap_anims.clear();
|
||||
asteroid_p->explosion_bitmap_anims.insert(asteroid_p->explosion_bitmap_anims.begin(), temp, temp + parsed_ints);
|
||||
stuff_fireball_index_list(asteroid_p->explosion_bitmap_anims, asteroid_p->name);
|
||||
}
|
||||
|
||||
if (optional_string("$Explosion Radius Mult:")) {
|
||||
@@ -2416,7 +2429,7 @@ static void asteroid_parse_tbl(const char* filename)
|
||||
// Gets the index of an asteroid by name from Asteroid_info
|
||||
int get_asteroid_index(const char* asteroid_name)
|
||||
{
|
||||
for (int i = 0; i < (int)Asteroid_info.size(); i++) {
|
||||
for (int i = 0; i < static_cast<int>(Asteroid_info.size()); i++) {
|
||||
if (!stricmp(asteroid_name, Asteroid_info[i].name)) {
|
||||
return i;
|
||||
}
|
||||
@@ -2425,6 +2438,31 @@ int get_asteroid_index(const char* asteroid_name)
|
||||
return -1;
|
||||
}
|
||||
|
||||
// For FRED. Gets a list of unique asteroid subtype names
|
||||
SCP_vector<SCP_string> get_list_valid_asteroid_subtypes()
|
||||
{
|
||||
SCP_vector<SCP_string> list;
|
||||
|
||||
for (const auto& this_asteroid : Asteroid_info) {
|
||||
if (this_asteroid.type != ASTEROID_TYPE_DEBRIS) {
|
||||
for (const auto& subtype : this_asteroid.subtypes) {
|
||||
bool exists = false;
|
||||
for (const auto& entry : list) {
|
||||
if (subtype.type_name == entry) {
|
||||
exists = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!exists) {
|
||||
list.push_back(subtype.type_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
static void verify_asteroid_splits()
|
||||
{
|
||||
|
||||
@@ -2483,7 +2521,14 @@ static void verify_asteroid_list()
|
||||
|
||||
}
|
||||
|
||||
// Rest should be debris type
|
||||
for (int i = 0; i < (int)asteroid_list.size(); i++) {
|
||||
|
||||
// Remove all subtypes except the first one
|
||||
asteroid_list[i].subtypes.resize(1);
|
||||
// Make sure the first subtype is set as debris
|
||||
asteroid_list[i].subtypes[0].type_name = "Debris";
|
||||
|
||||
if (asteroid_list[i].type < 0) {
|
||||
Asteroid_info.push_back(asteroid_list[i]);
|
||||
} else {
|
||||
@@ -2497,14 +2542,8 @@ static void verify_asteroid_list()
|
||||
|
||||
//Check that we have the appropriate POF files-Mjn
|
||||
for (int i = 0; i < (int)Asteroid_info.size(); i++) {
|
||||
if (Asteroid_info[i].pof_files[0][0] == '\0')
|
||||
Error(LOCATION, "Missing [POF File 1] for %s", Asteroid_info[i].name);
|
||||
|
||||
if (Asteroid_info[i].type != ASTEROID_TYPE_DEBRIS) {
|
||||
if (Asteroid_info[i].pof_files[1][0] == '\0')
|
||||
Error(LOCATION, "Missing [POF File 2] for %s", Asteroid_info[i].name);
|
||||
if (Asteroid_info[i].pof_files[2][0] == '\0')
|
||||
Error(LOCATION, "Missing [POF File 3] for %s", Asteroid_info[i].name);
|
||||
if (Asteroid_info[i].subtypes.size() == 0) {
|
||||
Error(LOCATION, "Asteroid %s needs at least one subtype!", Asteroid_info[i].name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2541,7 +2580,7 @@ void asteroid_init()
|
||||
}
|
||||
|
||||
if (Asteroid_icon_closeup_model[0] == '\0')
|
||||
strcpy_s(Asteroid_icon_closeup_model, Asteroid_info[ASTEROID_TYPE_LARGE].pof_files[0]); // magic file from retail
|
||||
strcpy_s(Asteroid_icon_closeup_model, Asteroid_info[ASTEROID_TYPE_LARGE].subtypes[0].pof_filename); // magic file from retail
|
||||
|
||||
}
|
||||
|
||||
@@ -2581,6 +2620,11 @@ void asteroid_frame()
|
||||
return;
|
||||
}
|
||||
|
||||
// If no asteroid types are defined for the field, abort.
|
||||
if (Asteroid_field.field_asteroid_type.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If there are no explicit targets, fall back to default retail targeting behavior
|
||||
if (Asteroid_field.target_names.empty()) {
|
||||
int objnum = set_asteroid_throw_objnum();
|
||||
@@ -2689,21 +2733,26 @@ void asteroid_page_in()
|
||||
return;
|
||||
|
||||
if (Asteroid_field.num_initial_asteroids > 0 ) {
|
||||
int i, j, k;
|
||||
|
||||
nprintf(( "Paging", "Paging in asteroids\n" ));
|
||||
|
||||
size_t num_debris_types = NUM_ASTEROID_SIZES;
|
||||
if (Asteroid_field.debris_genre == DG_DEBRIS) {
|
||||
num_debris_types = Asteroid_field.field_debris_type.size();
|
||||
}
|
||||
|
||||
// max of MAX_ACTIVE_DEBRIS_TYPES possible debris field models
|
||||
for (i=0; i<MAX_ACTIVE_DEBRIS_TYPES; i++) {
|
||||
|
||||
// for asteroids this will loop over all three possible sizes
|
||||
// for debris this will loop over all selected types
|
||||
for (size_t i = 0; i < num_debris_types; i++) {
|
||||
asteroid_info *asip;
|
||||
|
||||
if (Asteroid_field.debris_genre == DG_ASTEROID) {
|
||||
// asteroid
|
||||
Assertion(i < NUM_ASTEROID_SIZES, "Got invalid call to load a debris type instead of asteroid type!");
|
||||
Assertion(i < NUM_ASTEROID_SIZES, "Got invalid call to load non-existent asteroid size!");
|
||||
asip = &Asteroid_info[i];
|
||||
} else {
|
||||
// ship debris - always full until empty
|
||||
// debris - always full until empty
|
||||
if (Asteroid_field.field_debris_type[i] != -1) {
|
||||
asip = &Asteroid_info[Asteroid_field.field_debris_type[i]];
|
||||
} else {
|
||||
@@ -2712,28 +2761,36 @@ void asteroid_page_in()
|
||||
}
|
||||
|
||||
|
||||
for (k=0; k<NUM_ASTEROID_POFS; k++) {
|
||||
for (size_t k = 0; k < asip->subtypes.size(); k++) {
|
||||
|
||||
// SHIP DEBRIS - use subtype 0
|
||||
// DEBRIS FIELDS - always use subtype 0
|
||||
if (Asteroid_field.debris_genre == DG_DEBRIS) {
|
||||
if (k > 0) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// ASTEROID DEBRIS - use subtype (Asteroid_field.field_debris_type[] != -1)
|
||||
if (Asteroid_field.field_debris_type[k] == -1) {
|
||||
// ASTEROID FIELDS - use subtype k, if active
|
||||
bool active = false;
|
||||
for (const auto& active_type : Asteroid_field.field_asteroid_type) {
|
||||
if (active_type == asip->subtypes[k].type_name) {
|
||||
active = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!active) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (asip->model_num[k] < 0)
|
||||
// model is already paged in
|
||||
if (asip->subtypes[k].model_number < 0)
|
||||
continue;
|
||||
|
||||
asip->modelp[k] = model_get(asip->model_num[k]);
|
||||
asip->subtypes[k].model_pointer = model_get(asip->subtypes[k].model_number);
|
||||
|
||||
// Page in textures
|
||||
for (j=0; j<asip->modelp[k]->n_textures; j++ ) {
|
||||
asip->modelp[k]->maps[j].PageIn();
|
||||
for (int j = 0; j < asip->subtypes[k].model_pointer->n_textures; j++ ) {
|
||||
asip->subtypes[k].model_pointer->maps[j].PageIn();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+22
-21
@@ -24,15 +24,14 @@ class model_draw_list;
|
||||
#define MAX_ASTEROIDS 2000 //Increased from 512 to 2000 in 2022
|
||||
|
||||
#define NUM_ASTEROID_SIZES 3
|
||||
#define NUM_ASTEROID_POFS 3 // Number of POFs per debris size
|
||||
|
||||
#define ASTEROID_TYPE_DEBRIS -1
|
||||
#define ASTEROID_TYPE_SMALL 0
|
||||
#define ASTEROID_TYPE_MEDIUM 1
|
||||
#define ASTEROID_TYPE_LARGE 2
|
||||
|
||||
// these should always be equal for the benefit of generic asteroids (c.f. asteroid_page_in)
|
||||
#define MAX_ACTIVE_DEBRIS_TYPES NUM_ASTEROID_SIZES
|
||||
// Only used for parsing & saving retail compatible mission files
|
||||
#define MAX_RETAIL_DEBRIS_TYPES 3
|
||||
|
||||
// Goober5000 - currently same as MAX_SHIP_DETAIL_LEVELS (put here to avoid an #include)
|
||||
#define MAX_ASTEROID_DETAIL_LEVELS 5
|
||||
@@ -54,15 +53,23 @@ typedef struct asteroid_split_info {
|
||||
int max; //maximum asteroids to spawn
|
||||
} asteroid_split_info;
|
||||
|
||||
// Data structure for storing asteroid subtype info. POFs, model pointer, model num, etc.
|
||||
typedef struct asteroid_subtype_info {
|
||||
char pof_filename[MAX_FILENAME_LEN];
|
||||
polymodel* model_pointer;
|
||||
int model_number;
|
||||
SCP_string type_name;
|
||||
} asteroid_subtype_info;
|
||||
|
||||
class asteroid_info
|
||||
{
|
||||
public:
|
||||
char name[NAME_LENGTH]; // name for the asteroid
|
||||
int type; // type of asteroid, 0 = small, 1 = medium, 2 = large, -1 = debris
|
||||
char pof_files[NUM_ASTEROID_POFS][MAX_FILENAME_LEN]; // POF files to load/associate with ship
|
||||
int num_detail_levels; // number of detail levels for this ship
|
||||
int num_detail_levels; // number of detail levels for this asteroid
|
||||
int detail_distance[MAX_ASTEROID_DETAIL_LEVELS]; // distance to change detail levels at
|
||||
float max_speed; // cap on speed for asteroid
|
||||
float rotational_vel_multiplier; // rotational velocity multiplier for asteroid --wookieejedi
|
||||
int damage_type_idx; //Damage type of the asteroid
|
||||
int damage_type_idx_sav; // stored value from table used to reset damage_type_idx
|
||||
float inner_rad; // radius within which maximum area effect damage is applied
|
||||
@@ -71,16 +78,16 @@ public:
|
||||
float blast; // maximum blast impulse from area effect explosion
|
||||
float initial_asteroid_strength; // starting strength of asteroid
|
||||
SCP_vector< asteroid_split_info > split_info;
|
||||
polymodel *modelp[NUM_ASTEROID_POFS];
|
||||
int model_num[NUM_ASTEROID_POFS];
|
||||
SCP_vector<int> explosion_bitmap_anims;
|
||||
float fireball_radius_multiplier; // the model radius is multiplied by this to determine the fireball size
|
||||
SCP_string display_name; // only used for hud targeting display and for 'ship' asteroids
|
||||
float spawn_weight; // ship asteroids only, relative proportion to spawn compared to other types in its asteroid field
|
||||
SCP_string display_name; // only used for hud targeting display and for debris
|
||||
float spawn_weight; // debris only, relative proportion to spawn compared to other types in its asteroid field
|
||||
float gravity_const; // multiplier for mission gravity
|
||||
SCP_vector<asteroid_subtype_info> subtypes;
|
||||
|
||||
asteroid_info( )
|
||||
: type(ASTEROID_TYPE_DEBRIS), num_detail_levels(0), max_speed(0), damage_type_idx(0),
|
||||
: type(ASTEROID_TYPE_DEBRIS), num_detail_levels(0), max_speed(0),
|
||||
rotational_vel_multiplier(1), damage_type_idx(0),
|
||||
damage_type_idx_sav( -1 ), inner_rad( 0 ), outer_rad( 0 ),
|
||||
damage( 0 ), blast( 0 ), initial_asteroid_strength( 0 ),
|
||||
fireball_radius_multiplier( -1 ), spawn_weight( 1 ), gravity_const( 0 )
|
||||
@@ -88,13 +95,6 @@ public:
|
||||
name[ 0 ] = 0;
|
||||
display_name = "";
|
||||
memset( detail_distance, 0, sizeof( detail_distance ) );
|
||||
|
||||
for (int i = 0; i < NUM_ASTEROID_POFS; i++)
|
||||
{
|
||||
modelp[i] = NULL;
|
||||
model_num[i] = -1;
|
||||
pof_files[i][0] = '\0';
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -141,8 +141,8 @@ typedef struct asteroid_field {
|
||||
int num_initial_asteroids; // Number of asteroids at creation.
|
||||
field_type_t field_type; // active throws and wraps, passive does not
|
||||
debris_genre_t debris_genre; // type of debris (ship or asteroid) [generic type]
|
||||
int field_debris_type[MAX_ACTIVE_DEBRIS_TYPES]; // one of the debris type defines above
|
||||
int num_used_field_debris_types; // how many of the above are used
|
||||
SCP_vector<int> field_debris_type; // one of the debris type defines above
|
||||
SCP_vector<SCP_string> field_asteroid_type; // one of the asteroid subtypes
|
||||
bool enhanced_visibility_checks; // if true then range checks are overridden for spawning and wrapping asteroids in the field
|
||||
|
||||
SCP_vector<SCP_string> target_names; // default retail behavior is to just throw at the first big ship in the field
|
||||
@@ -163,8 +163,8 @@ bool asteroid_is_within_view(vec3d *pos, float range, bool range_override = f
|
||||
void asteroid_level_init();
|
||||
void asteroid_level_close();
|
||||
void asteroid_create_all();
|
||||
void asteroid_create_asteroid_field(int num_asteroids, int field_type, int asteroid_speed, bool brown, bool blue, bool orange, vec3d o_min, vec3d o_max, bool inner_box, vec3d i_min, vec3d i_max, SCP_vector<SCP_string> targets);
|
||||
void asteroid_create_debris_field(int num_asteroids, int asteroid_speed, int debris1, int debris2, int debris3, vec3d o_min, vec3d o_max, bool enhanced);
|
||||
void asteroid_create_asteroid_field(int num_asteroids, int field_type, int asteroid_speed, vec3d o_min, vec3d o_max, bool inner_box, vec3d i_min, vec3d i_max, SCP_vector<SCP_string> asteroid_types);
|
||||
void asteroid_create_debris_field(int num_asteroids, int asteroid_speed, SCP_vector<int> debris_types, vec3d o_min, vec3d o_max, bool enhanced);
|
||||
void asteroid_render(object* obj, model_draw_list* scene);
|
||||
void asteroid_delete( object *asteroid_objp );
|
||||
void asteroid_process_pre( object *asteroid_objp );
|
||||
@@ -178,6 +178,7 @@ void asteroid_show_brackets();
|
||||
void asteroid_target_closest_danger();
|
||||
void asteroid_add_target(object* objp);
|
||||
int get_asteroid_index(const char* asteroid_name);
|
||||
SCP_vector<SCP_string> get_list_valid_asteroid_subtypes();
|
||||
|
||||
// need to extern for keycontrol debug commands
|
||||
object *asteroid_create(asteroid_field *asfieldp, int asteroid_type, int asteroid_subtype, bool check_visibility = false);
|
||||
|
||||
@@ -869,7 +869,7 @@ void EndAutoPilot()
|
||||
Assert( CurrentNav >= 0 );
|
||||
|
||||
int goal = 0;
|
||||
char *goal_name = NULL;
|
||||
const char *goal_name = NULL;
|
||||
|
||||
if (Navs[CurrentNav].flags & NP_WAYPOINT)
|
||||
{
|
||||
|
||||
@@ -425,6 +425,7 @@ DCF(bm_used, "Shows BmpMan Slot Usage") {
|
||||
|
||||
SCP_stringstream text;
|
||||
text << "BmpMan Used Slots\n";
|
||||
text << " " << std::dec << std::setw(4) << std::setfill('0') << none << ", NONE\n";
|
||||
text << " " << std::dec << std::setw(4) << std::setfill('0') << pcx << ", PCX\n";
|
||||
text << " " << std::dec << std::setw(4) << std::setfill('0') << user << ", User\n";
|
||||
text << " " << std::dec << std::setw(4) << std::setfill('0') << tga << ", TGA\n";
|
||||
@@ -1026,10 +1027,6 @@ int bm_is_compressed(int num) {
|
||||
auto entry = bm_get_entry(num);
|
||||
BM_TYPE type = BM_TYPE_NONE;
|
||||
|
||||
//duh
|
||||
if (!Use_compressed_textures)
|
||||
return 0;
|
||||
|
||||
type = entry->comp_type;
|
||||
|
||||
switch (type) {
|
||||
|
||||
+63
-29
@@ -14,8 +14,8 @@
|
||||
#include "ship/ship.h" //compute_slew_matrix
|
||||
|
||||
//*************************IMPORTANT GLOBALS*************************
|
||||
fov_t VIEWER_ZOOM_DEFAULT = 0.75f; // Default viewer zoom, 0.625 as per multi-lateral agreement on 3/24/97
|
||||
fov_t COCKPIT_ZOOM_DEFAULT = 0.75f;
|
||||
fov_t VIEWER_ZOOM_DEFAULT = DEFAULT_FOV;
|
||||
fov_t COCKPIT_ZOOM_DEFAULT = DEFAULT_FOV;
|
||||
float Sexp_fov = 0.0f;
|
||||
warp_camera Warp_camera;
|
||||
|
||||
@@ -54,6 +54,9 @@ APPLY_TO_FOV_T(*, mul)
|
||||
APPLY_TO_FOV_T(+, add)
|
||||
APPLY_TO_FOV_T(-, sub)
|
||||
|
||||
// Used to set the default value for in-game options
|
||||
static constexpr float fov_default = DEFAULT_FOV;
|
||||
|
||||
static SCP_string fov_display(float val)
|
||||
{
|
||||
auto degrees = fl_degrees(val);
|
||||
@@ -64,18 +67,55 @@ static SCP_string fov_display(float val)
|
||||
auto FovOption = options::OptionBuilder<float>("Graphics.FOV",
|
||||
std::pair<const char*, int>{"Field Of View", 1703},
|
||||
std::pair<const char*, int>{"The vertical field of view", 1704})
|
||||
.category("Graphics")
|
||||
.category(std::make_pair("Graphics", 1825))
|
||||
.range(0.436332f, 1.5708f)
|
||||
.change_listener([](const float& val, bool) {
|
||||
VIEWER_ZOOM_DEFAULT = val;
|
||||
return true;
|
||||
})
|
||||
.display(fov_display)
|
||||
.default_val(0.75f)
|
||||
.default_val(fov_default)
|
||||
.level(options::ExpertLevel::Advanced)
|
||||
.importance(60)
|
||||
.finish();
|
||||
|
||||
bool Use_cockpit_fov = false;
|
||||
|
||||
auto CockpitFOVToggleOption = options::OptionBuilder<bool>("Graphics.CockpitFOVToggle",
|
||||
std::pair<const char*, int>{"Cockpit FOV Toggle", 1838},
|
||||
std::pair<const char*, int>{"Whether or not to use a different FOV for cockpit rendering from normal rendering", 1839})
|
||||
.category(std::make_pair("Graphics", 1825))
|
||||
.default_val(false)
|
||||
.change_listener([](bool val, bool) {
|
||||
if (!val) {
|
||||
COCKPIT_ZOOM_DEFAULT = VIEWER_ZOOM_DEFAULT;
|
||||
}
|
||||
return true; // This option will always persist so we never return false
|
||||
})
|
||||
.level(options::ExpertLevel::Advanced)
|
||||
.bind_to(&Use_cockpit_fov)
|
||||
.importance(61)
|
||||
.finish();
|
||||
|
||||
auto CockpitFovOption = options::OptionBuilder<float>("Graphics.CockpitFOV",
|
||||
std::pair<const char*, int>{"Cockpit Field Of View", 1840},
|
||||
std::pair<const char*, int>{"The vertical field of view for cockpit rendering. Only works if cockpits are active and cockpit FOV toggle is turned on.", 1841})
|
||||
.category(std::make_pair("Graphics", 1825))
|
||||
.range(0.436332f, 1.5708f)
|
||||
.change_listener([](const float& val, bool) {
|
||||
if (Use_cockpit_fov){
|
||||
COCKPIT_ZOOM_DEFAULT = val;
|
||||
} else {
|
||||
COCKPIT_ZOOM_DEFAULT = VIEWER_ZOOM_DEFAULT;
|
||||
}
|
||||
return true;
|
||||
})
|
||||
.display(fov_display)
|
||||
.default_val(fov_default)
|
||||
.level(options::ExpertLevel::Advanced)
|
||||
.importance(62)
|
||||
.finish();
|
||||
|
||||
//*************************CLASS: camera*************************
|
||||
//This is where the camera class begins! :D
|
||||
camera::camera(const char *in_name, int in_signature)
|
||||
@@ -301,7 +341,7 @@ void camera::set_rotation_facing(vec3d *in_target, float in_rotation_time, float
|
||||
|
||||
// if we have a host, we need the difference between the camera's current orient and the orient we want
|
||||
// if not, we will later set the absolute orientation, rather than the orientation relative to the host
|
||||
if (object_host.IsValid())
|
||||
if (object_host.isValid())
|
||||
{
|
||||
vm_transpose(orient);
|
||||
temp_matrix = temp_matrix * *orient;
|
||||
@@ -324,10 +364,7 @@ void camera::do_frame(float /*in_frametime*/)
|
||||
|
||||
object *camera::get_object_host()
|
||||
{
|
||||
if(object_host.IsValid())
|
||||
return object_host.objp;
|
||||
else
|
||||
return NULL;
|
||||
return object_host.objp_or_null();
|
||||
}
|
||||
|
||||
int camera::get_object_host_submodel()
|
||||
@@ -337,10 +374,7 @@ int camera::get_object_host_submodel()
|
||||
|
||||
object *camera::get_object_target()
|
||||
{
|
||||
if(object_target.IsValid())
|
||||
return object_target.objp;
|
||||
else
|
||||
return NULL;
|
||||
return object_target.objp_or_null();
|
||||
}
|
||||
|
||||
int camera::get_object_target_submodel()
|
||||
@@ -373,7 +407,7 @@ void camera::get_info(vec3d *position, matrix *orientation, bool apply_camera_or
|
||||
bool use_host_orient = false;
|
||||
|
||||
//POSITION
|
||||
if(!(flags & CAM_STATIONARY_POS) || object_host.IsValid())
|
||||
if(!(flags & CAM_STATIONARY_POS) || object_host.isValid())
|
||||
{
|
||||
c_pos = vmd_zero_vector;
|
||||
|
||||
@@ -382,9 +416,9 @@ void camera::get_info(vec3d *position, matrix *orientation, bool apply_camera_or
|
||||
pos_y.get(&pt.xyz.y, NULL);
|
||||
pos_z.get(&pt.xyz.z, NULL);
|
||||
|
||||
if(object_host.IsValid())
|
||||
if(object_host.isValid())
|
||||
{
|
||||
object *objp = object_host.objp;
|
||||
object *objp = object_host.objp();
|
||||
int model_num = object_get_model(objp);
|
||||
polymodel *pm = nullptr;
|
||||
polymodel_instance *pmi = nullptr;
|
||||
@@ -398,8 +432,8 @@ void camera::get_info(vec3d *position, matrix *orientation, bool apply_camera_or
|
||||
|
||||
if(object_host_submodel < 0 || pm == NULL)
|
||||
{
|
||||
vm_vec_unrotate(&c_pos, &pt, &object_host.objp->orient);
|
||||
vm_vec_add2(&c_pos, &object_host.objp->pos);
|
||||
vm_vec_unrotate(&c_pos, &pt, &object_host.objp()->orient);
|
||||
vm_vec_add2(&c_pos, &object_host.objp()->pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -444,11 +478,11 @@ void camera::get_info(vec3d *position, matrix *orientation, bool apply_camera_or
|
||||
if(orientation != NULL)
|
||||
{
|
||||
bool target_set = false;
|
||||
if(!(flags & CAM_STATIONARY_ORI) || object_target.IsValid() || object_host.IsValid())
|
||||
if(!(flags & CAM_STATIONARY_ORI) || object_target.isValid() || object_host.isValid())
|
||||
{
|
||||
if(object_target.IsValid())
|
||||
if(object_target.isValid())
|
||||
{
|
||||
object *target_objp = object_target.objp;
|
||||
object *target_objp = object_target.objp();
|
||||
int model_num = object_get_model(target_objp);
|
||||
polymodel *target_pm = nullptr;
|
||||
polymodel_instance *target_pmi = nullptr;
|
||||
@@ -481,11 +515,11 @@ void camera::get_info(vec3d *position, matrix *orientation, bool apply_camera_or
|
||||
vm_vector_2_matrix(&c_ori, &targetvec, NULL, NULL);
|
||||
target_set = true;
|
||||
}
|
||||
else if(object_host.IsValid())
|
||||
else if(object_host.isValid())
|
||||
{
|
||||
if(eyep)
|
||||
{
|
||||
vm_vector_2_matrix(&c_ori, &host_normal, vm_vec_same(&host_normal, &object_host.objp->orient.vec.uvec)?NULL:&object_host.objp->orient.vec.uvec, NULL);
|
||||
vm_vector_2_matrix(&c_ori, &host_normal, vm_vec_same(&host_normal, &object_host.objp()->orient.vec.uvec)?NULL:&object_host.objp()->orient.vec.uvec, NULL);
|
||||
target_set = true;
|
||||
}
|
||||
else if (use_host_orient)
|
||||
@@ -494,7 +528,7 @@ void camera::get_info(vec3d *position, matrix *orientation, bool apply_camera_or
|
||||
}
|
||||
else
|
||||
{
|
||||
c_ori = object_host.objp->orient;
|
||||
c_ori = object_host.objp()->orient;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -754,7 +788,7 @@ subtitle::subtitle(int in_x_pos, int in_y_pos, const char* in_text, const char*
|
||||
//Get text size
|
||||
for(int i = 0; i < num_text_lines; i++)
|
||||
{
|
||||
gr_get_string_size(&w, &h, text_line_ptrs[i], text_line_lens[i]);
|
||||
gr_get_string_size(&w, &h, text_line_ptrs[i], static_cast<size_t>(text_line_lens[i]));
|
||||
|
||||
if(w > tw)
|
||||
tw = w;
|
||||
@@ -1011,7 +1045,7 @@ int camid::getSignature()
|
||||
return sig;
|
||||
}
|
||||
|
||||
bool camid::isValid()
|
||||
bool camid::isValid() const
|
||||
{
|
||||
if(idx >= Cameras.size())
|
||||
return false;
|
||||
@@ -1203,7 +1237,7 @@ vec3d normal_cache;
|
||||
void get_turret_cam_pos(camera *cam, vec3d *pos)
|
||||
{
|
||||
object_h obj(cam->get_object_host());
|
||||
if(!obj.IsValid())
|
||||
if(!obj.isValid())
|
||||
return;
|
||||
ship* shipp = &Ships[cam->get_object_host()->instance];
|
||||
ship_subsys* ssp = GET_FIRST(&shipp->subsys_list);
|
||||
@@ -1211,7 +1245,7 @@ void get_turret_cam_pos(camera *cam, vec3d *pos)
|
||||
{
|
||||
if(ssp->system_info->subobj_num == cam->get_object_host_submodel())
|
||||
{
|
||||
ship_get_global_turret_gun_info(cam->get_object_host(), ssp, pos, &normal_cache, 1, NULL);
|
||||
ship_get_global_turret_gun_info(cam->get_object_host(), ssp, pos, true, &normal_cache, true, nullptr);
|
||||
vec3d offset = vmd_zero_vector;
|
||||
offset.xyz.x = 0.0001f;
|
||||
vm_vec_add2(pos, &offset); // prevent beam turrets from crashing with a nullvec
|
||||
@@ -1224,7 +1258,7 @@ void get_turret_cam_pos(camera *cam, vec3d *pos)
|
||||
void get_turret_cam_orient(camera *cam, matrix *ori)
|
||||
{
|
||||
object_h obj(cam->get_object_host());
|
||||
if(!obj.IsValid())
|
||||
if(!obj.isValid())
|
||||
return;
|
||||
vm_vector_2_matrix(ori, &normal_cache, vm_vec_same(&normal_cache, &cam->get_object_host()->orient.vec.uvec)?NULL:&cam->get_object_host()->orient.vec.uvec, NULL);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
#define EXTERN_CAM_BBOX_CONSTANT_PADDING 5.0f
|
||||
#define EXTERN_CAM_BBOX_MULTIPLIER_PADDING 1.5f
|
||||
|
||||
#define DEFAULT_FOV 0.75f;
|
||||
|
||||
struct asymmetric_fov {
|
||||
float left, right, up, down;
|
||||
friend asymmetric_fov operator* (const asymmetric_fov&, const float&);
|
||||
|
||||
+19
-17
@@ -91,12 +91,10 @@ cf_pathtype Pathtypes[CF_MAX_PATH_TYPES] = {
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
#define CFILE_STACK_MAX 8
|
||||
|
||||
int cfile_inited = 0;
|
||||
static int Cfile_stack_pos = 0;
|
||||
|
||||
static char Cfile_stack[CFILE_STACK_MAX][CFILE_ROOT_DIRECTORY_LEN];
|
||||
static SCP_vector<SCP_string> Cfile_stack;
|
||||
|
||||
std::array<CFILE, MAX_CFILE_BLOCKS> Cfile_block_list;
|
||||
|
||||
@@ -330,17 +328,16 @@ int cfile_push_chdir(int type)
|
||||
|
||||
_getcwd(OriginalDirectory, CFILE_ROOT_DIRECTORY_LEN - 1);
|
||||
|
||||
Assert(Cfile_stack_pos < CFILE_STACK_MAX);
|
||||
|
||||
if (Cfile_stack_pos >= CFILE_STACK_MAX) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
strcpy_s(Cfile_stack[Cfile_stack_pos++], OriginalDirectory);
|
||||
|
||||
cf_create_default_path_string(dir, type, NULL);
|
||||
|
||||
return _cfile_chdir(dir.c_str(), OriginalDirectory);
|
||||
int rc = _cfile_chdir(dir.c_str(), OriginalDirectory);
|
||||
|
||||
// if success then push the original directory on to the stack
|
||||
if (rc == 0) {
|
||||
Cfile_stack.push_back(OriginalDirectory);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -363,13 +360,16 @@ int cfile_chdir(const char *dir)
|
||||
|
||||
int cfile_pop_dir()
|
||||
{
|
||||
Assert(Cfile_stack_pos);
|
||||
|
||||
if ( !Cfile_stack_pos )
|
||||
if (Cfile_stack.empty())
|
||||
return -1;
|
||||
|
||||
Cfile_stack_pos--;
|
||||
return cfile_chdir(Cfile_stack[Cfile_stack_pos]);
|
||||
int rc = cfile_chdir(Cfile_stack.back().c_str());
|
||||
|
||||
Assertion(rc == 0, "Failed to chdir() to previous directory (%s)!", Cfile_stack.back().c_str());
|
||||
|
||||
Cfile_stack.pop_back();
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
// flush (delete all files in) the passed directory (by type), return the # of files deleted
|
||||
@@ -681,6 +681,8 @@ CFILE* _cfopen(const char* source, int line, const char* file_path, const char*
|
||||
} else {
|
||||
// Path type given?
|
||||
Assert( dir_type != CF_TYPE_ANY );
|
||||
if (dir_type == CF_TYPE_ANY)
|
||||
return NULL;
|
||||
|
||||
// Create the directory if necessary
|
||||
cf_create_directory(dir_type, location_flags);
|
||||
|
||||
@@ -377,6 +377,7 @@ struct CFileLocation {
|
||||
SCP_string full_name;
|
||||
size_t size = 0;
|
||||
size_t offset = 0;
|
||||
time_t m_time = 0;
|
||||
const void* data_ptr = nullptr;
|
||||
|
||||
explicit CFileLocation(bool found_in = false) : found(found_in) {}
|
||||
|
||||
@@ -595,7 +595,7 @@ static void cf_add_mod_roots(const char* rootDirectory, uint32_t basic_location)
|
||||
|
||||
cf_root* root = cf_create_root();
|
||||
|
||||
root->path = rootPath;
|
||||
root->path = std::move(rootPath);
|
||||
if (primary) {
|
||||
root->location_flags = basic_location | CF_LOCATION_TYPE_PRIMARY_MOD;
|
||||
} else {
|
||||
@@ -826,7 +826,8 @@ static void check_file_shadows(const int root_index __UNUSED, const int pathtype
|
||||
}
|
||||
|
||||
// this log message occurs in the middle of an existing line, hence the extra new lines
|
||||
mprintf(("\nWARNING! A %sfile being indexed may be shadowed by an existing file!\n New:\n %s\n Existing:\n %s\n",
|
||||
// critical files and files in same root are always logged, files in different root are behind a filter
|
||||
nprintf(((critical || !root->path.compare(r->path)) ? "General" : "CFileSystem", "\nWARNING! A %sfile being indexed may be shadowed by an existing file!\n New:\n %s\n Existing:\n %s\n",
|
||||
critical ? "critical " : "",
|
||||
newfile.c_str(), curfile.c_str()));
|
||||
|
||||
@@ -1172,7 +1173,7 @@ void cf_build_file_list()
|
||||
}
|
||||
|
||||
Warning(LOCATION, "Some critical files might be shadowed! Please check the debug log for details.\n\n"
|
||||
"%lu file(s) detected, including:\n%s", count, shadowed.c_str());
|
||||
SIZE_T_ARG " file(s) detected, including:\n%s", count, shadowed.c_str());
|
||||
}
|
||||
|
||||
critical_shadowed.clear();
|
||||
@@ -1236,6 +1237,22 @@ static bool sub_path_match(const SCP_string &search, const SCP_string &index)
|
||||
return !stricmp(search.c_str(), index.c_str());
|
||||
}
|
||||
|
||||
static time_t get_mtime(int fd)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
struct _stat buf;
|
||||
#define fstat _fstat
|
||||
#else
|
||||
struct stat buf;
|
||||
#endif
|
||||
|
||||
if (fstat(fd, &buf) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return buf.st_mtime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches for a file.
|
||||
*
|
||||
@@ -1270,6 +1287,7 @@ CFileLocation cf_find_file_location(const char* filespec, int pathtype, uint32_t
|
||||
if (fp) {
|
||||
CFileLocation res(true);
|
||||
res.size = static_cast<size_t>(filelength(fileno(fp)));
|
||||
res.m_time = get_mtime(fileno(fp));
|
||||
|
||||
fclose(fp);
|
||||
|
||||
@@ -1332,6 +1350,7 @@ CFileLocation cf_find_file_location(const char* filespec, int pathtype, uint32_t
|
||||
if (fp) {
|
||||
CFileLocation res(true);
|
||||
res.size = static_cast<size_t>(filelength( fileno(fp) ));
|
||||
res.m_time = get_mtime(fileno(fp));
|
||||
|
||||
fclose(fp);
|
||||
|
||||
@@ -1388,6 +1407,7 @@ CFileLocation cf_find_file_location(const char* filespec, int pathtype, uint32_t
|
||||
res.offset = (size_t)f->pack_offset;
|
||||
res.data_ptr = f->data;
|
||||
res.name_ext = f->name_ext;
|
||||
res.m_time = f->write_time;
|
||||
|
||||
if (f->data != nullptr) {
|
||||
// This is an in-memory file so we just copy the pathtype name + file name
|
||||
@@ -1523,6 +1543,7 @@ CFileLocationExt cf_find_file_location_ext(const char *filename, const int ext_n
|
||||
CFileLocationExt res(cur_ext);
|
||||
res.found = true;
|
||||
res.size = static_cast<size_t>(filelength( fileno(fp) ));
|
||||
res.m_time = get_mtime(fileno(fp));
|
||||
|
||||
fclose(fp);
|
||||
|
||||
@@ -1611,6 +1632,7 @@ CFileLocationExt cf_find_file_location_ext(const char *filename, const int ext_n
|
||||
res.offset = (size_t)f->pack_offset;
|
||||
res.data_ptr = f->data;
|
||||
res.name_ext = f->name_ext;
|
||||
res.m_time = f->write_time;
|
||||
|
||||
if (f->data != nullptr) {
|
||||
// This is an in-memory file so we just copy the pathtype name + file name
|
||||
|
||||
@@ -82,7 +82,7 @@ void SpawnShipCheat::runCheat() {
|
||||
if (ptr->system_info->type == SUBSYSTEM_TURRET)
|
||||
{
|
||||
ptr->weapons.flags.set(Ship::Weapon_Flags::Beam_Free);
|
||||
ptr->turret_next_fire_stamp = timestamp((int)frand_range(50.0f, 4000.0f));
|
||||
ptr->turret_next_fire_stamp = timestamp(Random::next(50, 4000));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+174
-121
@@ -15,6 +15,7 @@
|
||||
#include "globalincs/pstypes.h"
|
||||
#include "globalincs/systemvars.h"
|
||||
#include "globalincs/version.h"
|
||||
#include "graphics/openxr.h"
|
||||
#include "graphics/shadows.h"
|
||||
#include "hud/hudconfig.h"
|
||||
#include "io/joy.h"
|
||||
@@ -39,6 +40,7 @@
|
||||
#ifdef SCP_UNIX
|
||||
#include "osapi/osapi.h"
|
||||
#include <dirent.h>
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#include <cstring>
|
||||
@@ -163,11 +165,9 @@ Flag exe_params[] =
|
||||
{ "-nonormal", "Disable normal maps", true, EASY_DEFAULT | EASY_HI_MEM_OFF, EASY_ALL_ON | EASY_HI_MEM_ON, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-nonormal" },
|
||||
{ "-emissive_light", "Enable emissive light from ships", true, 0, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-emissive_light" },
|
||||
{ "-noheight", "Disable height/parallax maps", true, EASY_DEFAULT | EASY_HI_MEM_OFF, EASY_ALL_ON | EASY_HI_MEM_ON, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-noheight" },
|
||||
{ "-3dshockwave", "Enable 3D shockwaves", true, EASY_ALL_ON | EASY_HI_MEM_ON, EASY_DEFAULT | EASY_HI_MEM_OFF, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-3dshockwave" },
|
||||
{ "-no_post_process", "Disable post-processing", true, EASY_DEFAULT | EASY_HI_MEM_OFF, EASY_ALL_ON | EASY_HI_MEM_ON, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_post_process" },
|
||||
{ "-soft_particles", "Enable soft particles", true, EASY_ALL_ON, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-soft_particles" },
|
||||
{ "-aa", "Enable Post-process anti-aliasing", true, EASY_ALL_ON | EASY_HI_MEM_ON, EASY_DEFAULT | EASY_HI_MEM_OFF, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-aa" },
|
||||
{ "-nolightshafts", "Disable lightshafts", true, EASY_DEFAULT | EASY_HI_MEM_OFF, EASY_ALL_ON | EASY_HI_MEM_ON, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-nolightshafts"},
|
||||
{ "-fb_explosions", "Enable Framebuffer Shockwaves", true, EASY_ALL_ON, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-fb_explosions", },
|
||||
{ "-fb_thrusters", "Enable Framebuffer Thrusters", true, EASY_ALL_ON, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-fb_thrusters", },
|
||||
{ "-no_deferred", "Disable Deferred Lighting", true, EASY_DEFAULT | EASY_HI_MEM_OFF, EASY_ALL_ON | EASY_HI_MEM_ON, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_deferred"},
|
||||
@@ -191,11 +191,10 @@ Flag exe_params[] =
|
||||
{ "-capture_mouse", "Capture the mouse within the window", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-capture_mouse", },
|
||||
{ "-stretch_menu", "Stretch interface to fill screen", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-stretch_menu", },
|
||||
{ "-noscalevid", "Disable scale-to-window for movies", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-noscalevid", },
|
||||
{ "-nomotiondebris", "Disable motion debris", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-nomotiondebris",},
|
||||
{ "-3dwarp", "Enable 3D warp", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-3dwarp", },
|
||||
{ "-warp_flash", "Enable flash upon warp", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-warp_flash", },
|
||||
{ "-no_ap_interrupt", "Disable interrupting autopilot", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_ap_interrupt", },
|
||||
{ "-no_screenshake", "Disable screen shaking", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_screenshake", },
|
||||
{ "-vr", "Enable Virtual Reality Mode", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-vr", },
|
||||
{ "-no_unfocused_pause","Don't pause if the window isn't focused", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_unfocused_pause", },
|
||||
{ "-orig_speedx_range", "Restrict speedup/slowdown (1x to 4x)", true, 0, EASY_DEFAULT, "Gameplay", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-orig_speedx_range", },
|
||||
|
||||
//flag launcher text FSO on_flags off_flags category reference URL
|
||||
{ "-nosound", "Disable all sound", false, 0, EASY_DEFAULT, "Audio", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-nosound", },
|
||||
@@ -219,6 +218,7 @@ Flag exe_params[] =
|
||||
|
||||
//flag launcher text FSO on_flags off_flags category reference URL
|
||||
{ "-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", },
|
||||
{ "-no_ingame_options", "Disable using ingame options", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_ingame_options", },
|
||||
{ "-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", },
|
||||
{ "-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", },
|
||||
@@ -237,6 +237,8 @@ Flag exe_params[] =
|
||||
{ "-prefer_ipv6", "Prefer IPv6 DNS lookups", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-prefer_ipv6", },
|
||||
{ "-log_multi_packet", "Log multi packet types ", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-log_multi_packet",},
|
||||
{ "-no_bsp_align", "Disable pof BSP data alignment", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_bsp_align", },
|
||||
{ "-no_large_shaders", "Split large shader into smaller shaders", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_large_shaders", },
|
||||
|
||||
#ifdef WIN32
|
||||
{ "-fix_registry", "Use a different registry path", true, 0, EASY_DEFAULT, "Troubleshoot", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-fix_registry", },
|
||||
#endif
|
||||
@@ -264,7 +266,6 @@ Flag exe_params[] =
|
||||
{ "-verify_vps", "Spew VP CRCs to vp_crcs.txt", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-verify_vps", },
|
||||
{ "-reparse_mainhall", "Reparse mainhall.tbl when loading halls", false, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-reparse_mainhall", },
|
||||
{ "-noninteractive", "Disables interactive dialogs", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-noninteractive", },
|
||||
{ "-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", },
|
||||
{ "-profile_frame_time","Profile frame time", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-profile_frame_time", },
|
||||
{ "-profile_write_file", "Write profiling information to file", true, 0, EASY_DEFAULT, "Dev Tool", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-profile_write_file", },
|
||||
@@ -338,15 +339,12 @@ cmdline_parm emissive_power_arg("-emissive", "Multiplies the brightness of all a
|
||||
cmdline_parm emissive_arg("-emissive_light", "Enable emissive light from ships", AT_NONE); // semi-deprecated but still functional
|
||||
cmdline_parm env("-noenv", NULL, AT_NONE); // Cmdline_env
|
||||
cmdline_parm glow_arg("-noglow", NULL, AT_NONE); // Cmdline_glow -- use Bobs glow code
|
||||
cmdline_parm nomotiondebris_arg("-nomotiondebris", NULL, AT_NONE); // Cmdline_nomotiondebris -- Removes those ugly floating rocks -C
|
||||
cmdline_parm noscalevid_arg("-noscalevid", NULL, AT_NONE); // Cmdline_noscalevid -- disable video scaling that fits to window
|
||||
cmdline_parm spec_arg("-nospec", NULL, AT_NONE); // Cmdline_spec --
|
||||
cmdline_parm normal_arg("-nonormal", NULL, AT_NONE); // Cmdline_normal -- disable normal mapping
|
||||
cmdline_parm height_arg("-noheight", NULL, AT_NONE); // Cmdline_height -- enable support for parallax mapping
|
||||
cmdline_parm enable_3d_shockwave_arg("-3dshockwave", NULL, AT_NONE);
|
||||
cmdline_parm softparticles_arg("-soft_particles", NULL, AT_NONE);
|
||||
cmdline_parm no_postprocess_arg("-no_post_process", "Disables post-processing", AT_NONE);
|
||||
cmdline_parm bloom_intensity_arg("-bloom_intensity", "Set bloom intensity, requires post-processing", AT_INT);
|
||||
cmdline_parm post_process_aa_arg("-aa", "Enables post-process antialiasing", AT_NONE);
|
||||
cmdline_parm post_process_aa_preset_arg("-aa_preset", "Sets the AA effect to use. See the wiki for details", AT_INT);
|
||||
cmdline_parm deprecated_fxaa_arg("-fxaa", nullptr, AT_NONE);
|
||||
@@ -356,7 +354,6 @@ cmdline_parm deprecated_smaa_preset_arg("-smaa_preset", "SMAA quality (0-3), req
|
||||
cmdline_parm msaa_enabled_arg("-msaa", nullptr, AT_INT);
|
||||
cmdline_parm fb_explosions_arg("-fb_explosions", NULL, AT_NONE);
|
||||
cmdline_parm fb_thrusters_arg("-fb_thrusters", NULL, AT_NONE);
|
||||
cmdline_parm flightshaftsoff_arg("-nolightshafts", NULL, AT_NONE);
|
||||
cmdline_parm shadow_quality_arg("-shadow_quality", NULL, AT_INT);
|
||||
cmdline_parm enable_shadows_arg("-enable_shadows", NULL, AT_NONE);
|
||||
cmdline_parm no_deferred_lighting_arg("-no_deferred", NULL, AT_NONE); // Cmdline_no_deferred
|
||||
@@ -374,10 +371,7 @@ int Cmdline_spec = 1;
|
||||
int Cmdline_emissive = 0;
|
||||
int Cmdline_normal = 1;
|
||||
int Cmdline_height = 1;
|
||||
int Cmdline_enable_3d_shockwave = 0;
|
||||
int Cmdline_softparticles = 0;
|
||||
int Cmdline_bloom_intensity = 25;
|
||||
bool Cmdline_force_lightshaft_off = false;
|
||||
int Cmdline_no_deferred_lighting = 0;
|
||||
bool Cmdline_deferred_lighting_cockpit = false;
|
||||
int Cmdline_aniso_level = 0;
|
||||
@@ -403,22 +397,18 @@ int Cmdline_orb_radar = 0;
|
||||
int Cmdline_rearm_timer = 0;
|
||||
|
||||
// Gameplay related
|
||||
cmdline_parm use_3dwarp("-3dwarp", nullptr, AT_NONE); // Is now Fireball_use_3d_warp
|
||||
cmdline_parm use_warp_flash("-warp_flash", nullptr, AT_NONE); // Cmdline_warp_flash
|
||||
cmdline_parm allow_autpilot_interrupt("-no_ap_interrupt", nullptr, AT_NONE);
|
||||
cmdline_parm stretch_menu("-stretch_menu", nullptr, AT_NONE); // Cmdline_stretch_menu
|
||||
cmdline_parm capture_mouse("-capture_mouse", nullptr, AT_NONE); // Cmdline_capture_mouse
|
||||
cmdline_parm no_screenshake("-no_screenshake", nullptr, AT_NONE); // Cmdline_no_screenshake
|
||||
cmdline_parm vr("-vr", nullptr, AT_NONE);
|
||||
cmdline_parm deadzone("-deadzone",
|
||||
"Sets the joystick deadzone. Integer value from 0 to 100 as a percentage of the joystick's range (100% would make the stick do nothing). Disables deadzone slider in the in-game Options menu.", AT_INT); //Cmdline_deadzone
|
||||
|
||||
int Cmdline_ship_choice_3d = 0;
|
||||
int Cmdline_weapon_choice_3d = 0;
|
||||
int Cmdline_autopilot_interruptable = 1;
|
||||
int Cmdline_stretch_menu = 0;
|
||||
bool Cmdline_capture_mouse = false;
|
||||
int Cmdline_no_screenshake = 0;
|
||||
int Cmdline_deadzone = -1;
|
||||
bool Cmdline_enable_vr = false;
|
||||
|
||||
// Audio related
|
||||
cmdline_parm voice_recognition_arg("-voicer", NULL, AT_NONE); // Cmdline_voice_recognition
|
||||
@@ -456,6 +446,7 @@ SCP_string Cmdline_lang;
|
||||
cmdline_parm loadallweapons_arg("-loadallweps", NULL, AT_NONE); // Cmdline_load_all_weapons
|
||||
cmdline_parm nomovies_arg("-nomovies", NULL, AT_NONE); // Cmdline_nomovies -- Allows video streaming
|
||||
cmdline_parm no_set_gamma_arg("-no_set_gamma", NULL, AT_NONE); // Cmdline_no_set_gamma
|
||||
cmdline_parm no_ingame_options_arg("-no_ingame_options", NULL, AT_NONE); // Cmdline_no_ingame_options
|
||||
cmdline_parm no_fbo_arg("-disable_fbo", NULL, AT_NONE); // Cmdline_no_fbo
|
||||
cmdline_parm no_pbo_arg("-disable_pbo", NULL, AT_NONE); // Cmdline_no_pbo
|
||||
cmdline_parm mipmap_arg("-mipmap", NULL, AT_NONE); // Cmdline_mipmap
|
||||
@@ -472,6 +463,7 @@ cmdline_parm prefer_ipv4_arg("-prefer_ipv4", nullptr, AT_NONE);
|
||||
cmdline_parm prefer_ipv6_arg("-prefer_ipv6", nullptr, AT_NONE);
|
||||
cmdline_parm log_multi_packet_arg("-log_multi_packet", nullptr, AT_NONE);
|
||||
cmdline_parm no_bsp_align_arg("-no_bsp_align", nullptr, AT_NONE);
|
||||
cmdline_parm no_large_shaders("-no_large_shaders", NULL, AT_NONE);
|
||||
#ifdef WIN32
|
||||
cmdline_parm fix_registry("-fix_registry", NULL, AT_NONE);
|
||||
#endif
|
||||
@@ -479,6 +471,7 @@ cmdline_parm fix_registry("-fix_registry", NULL, AT_NONE);
|
||||
int Cmdline_load_all_weapons = 0;
|
||||
int Cmdline_nomovies = 0;
|
||||
int Cmdline_no_set_gamma = 0;
|
||||
bool Cmdline_no_ingame_options = false;
|
||||
int Cmdline_no_fbo = 0;
|
||||
int Cmdline_no_pbo = 0;
|
||||
int Cmdline_ati_color_swap = 0;
|
||||
@@ -494,6 +487,7 @@ bool Cmdline_prefer_ipv4 = false;
|
||||
bool Cmdline_prefer_ipv6 = false;
|
||||
bool Cmdline_dump_packet_type = false;
|
||||
bool Cmdline_no_bsp_align = false;
|
||||
bool Cmdline_no_large_shaders = false;
|
||||
#ifdef WIN32
|
||||
bool Cmdline_alternate_registry_path = false;
|
||||
#endif
|
||||
@@ -513,13 +507,16 @@ cmdline_parm stats_arg("-stats", NULL, AT_NONE); // Cmdline_show_stats
|
||||
cmdline_parm save_render_targets_arg("-save_render_target", NULL, AT_NONE); // Cmdline_save_render_targets
|
||||
cmdline_parm window_arg("-window", NULL, AT_NONE); // Cmdline_window
|
||||
cmdline_parm fullscreen_window_arg("-fullscreen_window", "Fullscreen/borderless window (Windows only)", AT_NONE);
|
||||
cmdline_parm res_arg("-res", "Resolution, formatted like 1600x900", AT_STRING);
|
||||
cmdline_parm deprecated_res_arg("-res", "Deprecated, resolution, formatted like 1600x900", AT_STRING);
|
||||
cmdline_parm render_res_arg("-render_res", "Resolution, formatted like 1600x900", AT_STRING);
|
||||
cmdline_parm window_res_arg("-window_res", "Window resolution, formatted like 1600x900.", AT_STRING);
|
||||
cmdline_parm center_res_arg("-center_res", "Resolution of center monitor, formatted like 1600x900", AT_STRING);
|
||||
cmdline_parm verify_vps_arg("-verify_vps", NULL, AT_NONE); // Cmdline_verify_vps -- spew VP crcs to vp_crcs.txt
|
||||
cmdline_parm parse_cmdline_only(PARSE_COMMAND_LINE_STRING, "Ignore any cmdline_fso.cfg files", AT_NONE);
|
||||
cmdline_parm reparse_mainhall_arg("-reparse_mainhall", NULL, AT_NONE); //Cmdline_reparse_mainhall
|
||||
cmdline_parm frame_profile_write_file("-profile_write_file", NULL, AT_NONE); // Cmdline_profile_write_file
|
||||
cmdline_parm no_unfocused_pause_arg("-no_unfocused_pause", NULL, AT_NONE); //Cmdline_no_unfocus_pause
|
||||
cmdline_parm retail_time_compression_range_arg("-orig_speedx_range", NULL, AT_NONE); //Cmdline_retail_time_compression_range
|
||||
cmdline_parm benchmark_mode_arg("-benchmark_mode", NULL, AT_NONE); //Cmdline_benchmark_mode
|
||||
cmdline_parm pilot_arg("-pilot", nullptr, AT_STRING); //Cmdline_pilot
|
||||
cmdline_parm noninteractive_arg("-noninteractive", NULL, AT_NONE); //Cmdline_noninteractive
|
||||
@@ -551,12 +548,14 @@ int Cmdline_show_stats = 0;
|
||||
int Cmdline_save_render_targets = 0;
|
||||
int Cmdline_window = 0;
|
||||
int Cmdline_fullscreen_window = 0;
|
||||
tl::optional<std::pair<uint16_t, uint16_t>>Cmdline_window_res = tl::nullopt;
|
||||
char *Cmdline_res = 0;
|
||||
char *Cmdline_center_res = 0;
|
||||
int Cmdline_verify_vps = 0;
|
||||
int Cmdline_reparse_mainhall = 0;
|
||||
bool Cmdline_profile_write_file = false;
|
||||
bool Cmdline_no_unfocus_pause = false;
|
||||
bool Cmdline_retail_time_compression_range = false;
|
||||
bool Cmdline_benchmark_mode = false;
|
||||
const char *Cmdline_pilot = nullptr;
|
||||
bool Cmdline_noninteractive = false;
|
||||
@@ -599,6 +598,13 @@ cmdline_parm deprecated_spec_tube_arg("-spec_tube", "Deprecated", AT_NONE);
|
||||
cmdline_parm deprecated_ambient_factor_arg("-ambient_factor", "Deprecated", AT_NONE); //
|
||||
cmdline_parm deprecated_ship_choice_3d_arg("-ship_choice_3d", "Deprecated", AT_NONE);
|
||||
cmdline_parm deprecated_weapon_choice_3d_arg("-weapon_choice_3d", "Deprecated", AT_NONE);
|
||||
cmdline_parm deprecated_no_screenshake("-no_screenshake", "Deprecated", AT_NONE);
|
||||
cmdline_parm deprecated_bloom_intensity_arg("-bloom_intensity", "Deprecated", AT_INT);
|
||||
cmdline_parm deprecated_nomotiondebris_arg("-nomotiondebris", "Deprecated", AT_NONE);
|
||||
cmdline_parm deprecated_flightshaftsoff_arg("-nolightshafts", "Deprecated", AT_NONE);
|
||||
cmdline_parm deprecated_use_warp_flash("-warp_flash", "Deprecated", AT_NONE);
|
||||
cmdline_parm deprecated_use_3dwarp("-3dwarp", "Deprecated", AT_NONE);
|
||||
cmdline_parm deprecated_enable_3d_shockwave_arg("-3dshockwave", "Deprecated", AT_NONE);
|
||||
|
||||
#ifndef NDEBUG
|
||||
// NOTE: this assumes that os_init() has already been called but isn't a fatal error if it hasn't
|
||||
@@ -1198,93 +1204,133 @@ bool cmdline_parm::has_param() {
|
||||
}
|
||||
|
||||
#ifdef SCP_UNIX
|
||||
// Return a vector with all filesystem names of "parent/dir" relative to parent.
|
||||
// dir must not contain a slash.
|
||||
static SCP_vector<SCP_string> unix_get_single_dir_names(const SCP_string& parent, const SCP_string& dir)
|
||||
extern void normalize_directory_separators(SCP_string &str);
|
||||
|
||||
static SCP_string get_real_mod_path(const char *mod)
|
||||
{
|
||||
SCP_vector<SCP_string> ret;
|
||||
DIR *dirp;
|
||||
SCP_string fullpath;
|
||||
SCP_string mod_path = mod;
|
||||
|
||||
DIR *dp;
|
||||
if ((dp = opendir(parent.c_str())) == NULL) {
|
||||
Warning(LOCATION, "Can't open directory '%s' when searching mod paths. Ignoring. errno=%d", parent.c_str(), errno);
|
||||
return ret;
|
||||
normalize_directory_separators(mod_path);
|
||||
|
||||
fullpath = SCP_string(".") + DIR_SEPARATOR_STR;
|
||||
fullpath += mod_path;
|
||||
|
||||
// check if path already exists
|
||||
dirp = opendir(fullpath.c_str());
|
||||
|
||||
if (dirp) {
|
||||
// found it, return unchanged
|
||||
closedir(dirp);
|
||||
|
||||
return mod_path;
|
||||
}
|
||||
|
||||
dirent *dirp;
|
||||
while ((dirp = readdir(dp)) != NULL) {
|
||||
if (!stricmp(dirp->d_name, dir.c_str())) {
|
||||
ret.push_back(dirp->d_name);
|
||||
// not found, check for a difference in case
|
||||
SCP_string new_mod_path;
|
||||
SCP_string part;
|
||||
struct dirent *dir;
|
||||
SCP_string::size_type separator;
|
||||
SCP_string::size_type offset = 0;
|
||||
|
||||
fullpath = SCP_string(".") + DIR_SEPARATOR_STR;
|
||||
|
||||
do {
|
||||
separator = mod_path.find(DIR_SEPARATOR_CHAR, offset);
|
||||
|
||||
if (separator != SCP_string::npos) {
|
||||
part = mod_path.substr(offset, separator-offset);
|
||||
offset += separator-offset + 1;
|
||||
} else {
|
||||
part = mod_path.substr(offset);
|
||||
offset += part.length();
|
||||
}
|
||||
}
|
||||
(void)closedir(dp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
dirp = opendir(fullpath.c_str());
|
||||
|
||||
// Return a vector with all filesystem names of "parent/dir" relative to parent.
|
||||
// Recurses to deal with slashes in dir.
|
||||
static SCP_vector<SCP_string> unix_get_dir_names(const SCP_string& parent, const SCP_string& dir)
|
||||
{
|
||||
size_t slash = dir.find_first_of("/\\");
|
||||
|
||||
// no subdirectories, no need to recurse
|
||||
if (slash == std::string::npos) {
|
||||
return unix_get_single_dir_names(parent, dir);
|
||||
}
|
||||
|
||||
// get the names of the first component of dir
|
||||
SCP_vector<SCP_string> this_dir_names = unix_get_single_dir_names(parent, dir.substr(0, slash));
|
||||
|
||||
SCP_string rest = dir.substr(slash + 1);
|
||||
|
||||
SCP_vector<SCP_string> ret;
|
||||
|
||||
// search for the rest of dir in each of these
|
||||
SCP_vector<SCP_string>::iterator ii, end = this_dir_names.end();
|
||||
for (ii = this_dir_names.begin(); ii != end; ++ii) {
|
||||
SCP_string this_dir_path = parent + "/" + *ii;
|
||||
SCP_vector<SCP_string> mod_path = unix_get_dir_names(this_dir_path, rest);
|
||||
|
||||
// add all found paths relative to parent
|
||||
SCP_vector<SCP_string>::iterator ii2, end2 = mod_path.end();
|
||||
for (ii2 = mod_path.begin(); ii2 != end2; ++ii2) {
|
||||
ret.push_back(*ii + "/" + *ii2);
|
||||
if ( !dirp ) {
|
||||
break;
|
||||
}
|
||||
|
||||
while ((dir = readdir(dirp)) != nullptr) {
|
||||
if (stricmp(dir->d_name, part.c_str())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
SCP_string fn = fullpath + dir->d_name;
|
||||
|
||||
// make sure it accessible and a directory
|
||||
struct stat buf;
|
||||
|
||||
if (stat(fn.c_str(), &buf) == -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( !S_ISDIR(buf.st_mode) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( !new_mod_path.empty() ) {
|
||||
new_mod_path += DIR_SEPARATOR_STR;
|
||||
}
|
||||
|
||||
new_mod_path += dir->d_name;
|
||||
|
||||
fullpath += dir->d_name;
|
||||
fullpath += DIR_SEPARATOR_STR;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (dirp) {
|
||||
closedir(dirp);
|
||||
}
|
||||
} while (offset < mod_path.length());
|
||||
|
||||
// Append anything left from mod_path onto the new path. This will catch trailing separators
|
||||
// as well as mod folders which don't exist so that the mod string remains unchanged except
|
||||
// for the directory name case.
|
||||
if (new_mod_path.length() != mod_path.length()) {
|
||||
new_mod_path += mod_path.substr(new_mod_path.length());
|
||||
}
|
||||
|
||||
return ret;
|
||||
return new_mod_path;
|
||||
}
|
||||
|
||||
// For case sensitive filesystems (e.g. Linux/BSD) perform case-insensitive dir matches.
|
||||
//
|
||||
// NOTE: Aside from change in case no alterations should be made to the modlist. Missing
|
||||
// mod folders should be left in place and no errors or warnings should be generated.
|
||||
// There should be no difference between Windows and non-Windows modlist handling.
|
||||
static void handle_unix_modlist(char **modlist, size_t *len)
|
||||
{
|
||||
// search filesystem for given paths
|
||||
SCP_vector<SCP_string> mod_paths;
|
||||
for (char *cur_mod = strtok(*modlist, ","); cur_mod != NULL; cur_mod = strtok(NULL, ","))
|
||||
{
|
||||
SCP_vector<SCP_string> this_mod_paths = unix_get_dir_names(".", cur_mod);
|
||||
// Ignore non-existing mods for unit tests
|
||||
if (!running_unittests && this_mod_paths.empty()) {
|
||||
ReleaseWarning(LOCATION, "Can't find mod '%s'. Ignoring.", cur_mod);
|
||||
}
|
||||
mod_paths.insert(mod_paths.end(), this_mod_paths.begin(), this_mod_paths.end());
|
||||
|
||||
for (char *cur_mod = strtok(*modlist, ","); cur_mod != NULL; cur_mod = strtok(NULL, ",")) {
|
||||
SCP_string path = get_real_mod_path(cur_mod);
|
||||
mod_paths.push_back(path);
|
||||
}
|
||||
|
||||
// create new char[] to replace modlist
|
||||
size_t total_len = 0;
|
||||
SCP_vector<SCP_string>::iterator ii, end = mod_paths.end();
|
||||
for (ii = mod_paths.begin(); ii != end; ++ii) {
|
||||
total_len += ii->length() + 1;
|
||||
|
||||
for (auto &path : mod_paths) {
|
||||
total_len += path.length() + 1;
|
||||
}
|
||||
|
||||
char *new_modlist = new char[total_len + 1];
|
||||
memset(new_modlist, 0, total_len + 1);
|
||||
end = mod_paths.end();
|
||||
for (ii = mod_paths.begin(); ii != end; ++ii) {
|
||||
strcat_s(new_modlist, total_len + 1, ii->c_str());
|
||||
strcat_s(new_modlist, total_len + 1, ","); // replace later with NUL
|
||||
|
||||
for (auto &path : mod_paths) {
|
||||
strcat_s(new_modlist, total_len + 1, path.c_str());
|
||||
strcat_s(new_modlist, total_len + 1, ",");
|
||||
}
|
||||
|
||||
// remove trailing comma
|
||||
new_modlist[total_len-1] = '\0';
|
||||
|
||||
// make the rest of the modlist manipulation unaware that anything happened here
|
||||
delete [] *modlist;
|
||||
*modlist = new_modlist;
|
||||
@@ -1713,31 +1759,48 @@ bool SetCmdlineParams()
|
||||
// d3d windowed
|
||||
if(window_arg.found()) {
|
||||
// We need to set both values since we don't know if we are going to use the new config system
|
||||
options::OptionsManager::instance()->setOverride("Graphics.WindowMode", "0");
|
||||
//options::OptionsManager::instance()->setOverride("Graphics.WindowMode", "0");
|
||||
Cmdline_window = 1;
|
||||
}
|
||||
|
||||
if ( fullscreen_window_arg.found( ) )
|
||||
{
|
||||
options::OptionsManager::instance()->setOverride("Graphics.WindowMode", "1");
|
||||
//options::OptionsManager::instance()->setOverride("Graphics.WindowMode", "1");
|
||||
Cmdline_fullscreen_window = 1;
|
||||
Cmdline_window = 0; /* Make sure no-one sets both */
|
||||
}
|
||||
|
||||
if(res_arg.found()){
|
||||
Cmdline_res = res_arg.str();
|
||||
if(render_res_arg.found() || deprecated_res_arg.found()){
|
||||
if (render_res_arg.found()) {
|
||||
Cmdline_res = render_res_arg.str();
|
||||
}
|
||||
else {
|
||||
Cmdline_res = deprecated_res_arg.str();
|
||||
mprintf(("Deprecated -res argument. Use -render_res instead...\n"));
|
||||
}
|
||||
|
||||
int width = 0;
|
||||
/*int width = 0;
|
||||
int height = 0;
|
||||
|
||||
if ( sscanf(Cmdline_res, "%dx%d", &width, &height) == 2 ) {
|
||||
if (sscanf(Cmdline_res, "%dx%d", &width, &height) == 2) {
|
||||
SCP_string override;
|
||||
sprintf(override, "{\"width\":%d,\"height\":%d}", width, height);
|
||||
options::OptionsManager::instance()->setOverride("Graphics.Resolution", override);
|
||||
} else {
|
||||
mprintf(("Failed to parse -res parameter \"%s\". Must be in format \"<width>x<height>\".\n", Cmdline_res));
|
||||
Warning(LOCATION, "Failed to parse -res parameter \"%s\". Must be in format \"<width>x<height>\".\n", Cmdline_res);
|
||||
}*/
|
||||
}
|
||||
if(window_res_arg.found()){
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
|
||||
if ( sscanf(window_res_arg.str(), "%dx%d", &width, &height) == 2 ) {
|
||||
Cmdline_window_res.emplace(static_cast<uint16_t>(width), static_cast<uint16_t>(height));
|
||||
} else {
|
||||
Warning(LOCATION, "Failed to parse -window_res parameter \"%s\". Must be in format \"<width>x<height>\".\n", window_res_arg.str());
|
||||
}
|
||||
}
|
||||
|
||||
if(center_res_arg.found()){
|
||||
Cmdline_center_res = center_res_arg.str();
|
||||
}
|
||||
@@ -1772,7 +1835,7 @@ bool SetCmdlineParams()
|
||||
if(mod_arg.found() ) {
|
||||
Cmdline_mod = mod_arg.str();
|
||||
|
||||
// strip off blank space it it's there
|
||||
// strip off blank space if it's there
|
||||
if ( Cmdline_mod[strlen(Cmdline_mod)-1] == ' ' ) {
|
||||
Cmdline_mod[strlen(Cmdline_mod)-1] = '\0';
|
||||
}
|
||||
@@ -1815,10 +1878,6 @@ bool SetCmdlineParams()
|
||||
Cmdline_show_pos = 1;
|
||||
}
|
||||
|
||||
if ( nomotiondebris_arg.found() ) {
|
||||
Motion_debris_enabled = false;
|
||||
}
|
||||
|
||||
if( mipmap_arg.found() ) {
|
||||
Cmdline_mipmap = 1;
|
||||
}
|
||||
@@ -1832,7 +1891,7 @@ bool SetCmdlineParams()
|
||||
if (val > 0.1) {
|
||||
VIEWER_ZOOM_DEFAULT = val;
|
||||
} else {
|
||||
VIEWER_ZOOM_DEFAULT = 0.75f;
|
||||
VIEWER_ZOOM_DEFAULT = DEFAULT_FOV;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1846,26 +1905,22 @@ bool SetCmdlineParams()
|
||||
}
|
||||
}
|
||||
|
||||
if (vr.found()) {
|
||||
Cmdline_enable_vr = true;
|
||||
if (fov_arg.found() || fov_cockpit_arg.found()) {
|
||||
Warning(LOCATION, "FoV Command line settings found. VR-Mode will override these with the HMD's native FoV...");
|
||||
}
|
||||
openxr_prepare();
|
||||
}
|
||||
|
||||
if (orb_radar.found())
|
||||
{
|
||||
Cmdline_orb_radar = 1;
|
||||
}
|
||||
|
||||
if ( use_3dwarp.found() ) {
|
||||
Fireball_use_3d_warp = true;
|
||||
}
|
||||
|
||||
if ( use_warp_flash.found() ) {
|
||||
Fireball_warp_flash = true;
|
||||
}
|
||||
|
||||
if ( allow_autpilot_interrupt.found() ) {
|
||||
Cmdline_autopilot_interruptable = 0;
|
||||
}
|
||||
|
||||
if ( no_screenshake.found() ) {
|
||||
Cmdline_no_screenshake = 1;
|
||||
}
|
||||
|
||||
if ( deadzone.found() ) {
|
||||
Cmdline_deadzone = deadzone.get_int();
|
||||
@@ -1901,6 +1956,10 @@ bool SetCmdlineParams()
|
||||
Cmdline_no_set_gamma = 1;
|
||||
}
|
||||
|
||||
if (no_ingame_options_arg.found()) {
|
||||
Cmdline_no_ingame_options = true;
|
||||
}
|
||||
|
||||
if(no_vsync_arg.found() )
|
||||
{
|
||||
Gr_enable_vsync = false;
|
||||
@@ -2035,6 +2094,10 @@ bool SetCmdlineParams()
|
||||
if (no_bsp_align_arg.found()) {
|
||||
Cmdline_no_bsp_align = true;
|
||||
}
|
||||
|
||||
if (no_large_shaders.found()) {
|
||||
Cmdline_no_large_shaders = true;
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
if (fix_registry.found()) {
|
||||
@@ -2077,11 +2140,6 @@ bool SetCmdlineParams()
|
||||
Cmdline_ati_color_swap = 1;
|
||||
}
|
||||
|
||||
if ( enable_3d_shockwave_arg.found() )
|
||||
{
|
||||
Cmdline_enable_3d_shockwave = 1;
|
||||
}
|
||||
|
||||
if ( softparticles_arg.found() )
|
||||
{
|
||||
Cmdline_softparticles = 1;
|
||||
@@ -2102,16 +2160,6 @@ bool SetCmdlineParams()
|
||||
Gr_post_processing_enabled = false;
|
||||
}
|
||||
|
||||
if ( bloom_intensity_arg.found() )
|
||||
{
|
||||
Cmdline_bloom_intensity = bloom_intensity_arg.get_int();
|
||||
}
|
||||
|
||||
if ( flightshaftsoff_arg.found() )
|
||||
{
|
||||
Cmdline_force_lightshaft_off = true;
|
||||
}
|
||||
|
||||
if( reparse_mainhall_arg.found() )
|
||||
{
|
||||
Cmdline_reparse_mainhall = 1;
|
||||
@@ -2177,6 +2225,11 @@ bool SetCmdlineParams()
|
||||
{
|
||||
Cmdline_no_unfocus_pause = true;
|
||||
}
|
||||
|
||||
if (retail_time_compression_range_arg.found())
|
||||
{
|
||||
Cmdline_retail_time_compression_range = true;
|
||||
}
|
||||
|
||||
if (benchmark_mode_arg.found())
|
||||
{
|
||||
|
||||
@@ -6,12 +6,13 @@
|
||||
* source.
|
||||
*
|
||||
|
||||
*/
|
||||
*/
|
||||
|
||||
|
||||
#ifndef FS_CMDLINE_HEADER_FILE
|
||||
#define FS_CMDLINE_HEADER_FILE
|
||||
|
||||
#include <tl/optional.hpp>
|
||||
|
||||
int parse_cmdline(int argc, char *argv[]);
|
||||
|
||||
@@ -46,6 +47,7 @@ extern int Cmdline_use_last_pilot;
|
||||
extern int Cmdline_window;
|
||||
extern int Cmdline_fullscreen_window;
|
||||
extern char *Cmdline_res;
|
||||
extern tl::optional<std::pair<uint16_t, uint16_t>>Cmdline_window_res;
|
||||
extern char *Cmdline_center_res;
|
||||
|
||||
|
||||
@@ -61,10 +63,7 @@ extern int Cmdline_noscalevid; // disables fit-to-window for movies - taylor
|
||||
extern int Cmdline_spec;
|
||||
extern int Cmdline_normal;
|
||||
extern int Cmdline_height;
|
||||
extern int Cmdline_enable_3d_shockwave;
|
||||
extern int Cmdline_softparticles;
|
||||
extern int Cmdline_bloom_intensity;
|
||||
extern bool Cmdline_force_lightshaft_off;
|
||||
extern int Cmdline_no_deferred_lighting;
|
||||
extern bool Cmdline_deferred_lighting_cockpit;
|
||||
extern int Cmdline_emissive;
|
||||
@@ -82,13 +81,11 @@ extern int Cmdline_orb_radar;
|
||||
extern int Cmdline_rearm_timer;
|
||||
|
||||
// Gameplay related
|
||||
extern int Cmdline_ship_choice_3d;
|
||||
extern int Cmdline_weapon_choice_3d;
|
||||
extern int Cmdline_autopilot_interruptable;
|
||||
extern int Cmdline_stretch_menu;
|
||||
extern bool Cmdline_capture_mouse;
|
||||
extern int Cmdline_no_screenshake;
|
||||
extern int Cmdline_deadzone;
|
||||
extern bool Cmdline_enable_vr;
|
||||
|
||||
// Audio related
|
||||
extern int Cmdline_voice_recognition;
|
||||
@@ -111,6 +108,7 @@ extern SCP_string Cmdline_lang;
|
||||
extern int Cmdline_load_all_weapons;
|
||||
extern int Cmdline_nomovies; // WMC Toggles movie playing support
|
||||
extern int Cmdline_no_set_gamma;
|
||||
extern bool Cmdline_no_ingame_options;
|
||||
extern int Cmdline_no_fbo;
|
||||
extern int Cmdline_no_pbo;
|
||||
extern int Cmdline_mipmap;
|
||||
@@ -126,6 +124,7 @@ extern bool Cmdline_noshadercache;
|
||||
extern bool Cmdline_prefer_ipv4;
|
||||
extern bool Cmdline_prefer_ipv6;
|
||||
extern bool Cmdline_dump_packet_type;
|
||||
extern bool Cmdline_no_large_shaders;
|
||||
#ifdef WIN32
|
||||
extern bool Cmdline_alternate_registry_path;
|
||||
#endif
|
||||
@@ -145,6 +144,7 @@ extern int Cmdline_verify_vps;
|
||||
extern int Cmdline_reparse_mainhall;
|
||||
extern bool Cmdline_profile_write_file;
|
||||
extern bool Cmdline_no_unfocus_pause;
|
||||
extern bool Cmdline_retail_time_compression_range;
|
||||
extern bool Cmdline_benchmark_mode;
|
||||
extern const char *Cmdline_pilot;
|
||||
extern bool Cmdline_noninteractive;
|
||||
|
||||
@@ -141,6 +141,9 @@ SCP_vector<cc_line> Cc_lines;
|
||||
// Backups for use when user closes the config menu without saving
|
||||
SCP_vector<CCI> Control_config_backup;
|
||||
|
||||
// The current preset that the user is working on and will likely want to save to
|
||||
static SCP_string Current_preset_name;
|
||||
|
||||
// Undo system
|
||||
Undo_system Undo_controls;
|
||||
|
||||
@@ -923,8 +926,8 @@ bool control_config_do_reset(bool cycle, bool API_Access)
|
||||
|
||||
// first, determine how many bindings need to be changed
|
||||
for (size_t e = 0; e < Control_config.size(); ++e) {
|
||||
auto item = Control_config[e];
|
||||
auto default_item = default_bindings[e];
|
||||
const auto& item = Control_config[e];
|
||||
const auto& default_item = default_bindings[e];
|
||||
|
||||
if (item.disabled) {
|
||||
// skip
|
||||
@@ -1291,11 +1294,12 @@ bool control_config_accept(bool API_Access)
|
||||
char* cstr; // Must be a char *, because popup_input may return nullptr and std::string don't like it
|
||||
|
||||
retry:;
|
||||
SCP_string default_string = (Current_preset_name.empty()) ? Player->callsign : Current_preset_name;
|
||||
cstr = popup_input(flags,
|
||||
"Confirm new custom preset name.\n\nThe name must not be empty.\n\n Press [Enter] to accept, [Esc] to "
|
||||
"abort to config menu.",
|
||||
32 - 6,
|
||||
Player->callsign);
|
||||
default_string.c_str());
|
||||
if (cstr == nullptr) {
|
||||
// Abort
|
||||
gamesnd_play_iface(InterfaceSounds::USER_SELECT);
|
||||
@@ -1354,6 +1358,9 @@ bool control_config_accept(bool API_Access)
|
||||
// consistant ordering
|
||||
Control_config_presets.resize(1);
|
||||
load_preset_files();
|
||||
|
||||
// finally, save the new preset so that changes will get saved to this preset
|
||||
Current_preset_name = preset.name;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
@@ -1537,9 +1544,11 @@ void control_config_init(bool API_Access)
|
||||
// Init preset cycling system
|
||||
auto preset_it = control_config_get_current_preset();
|
||||
if (preset_it == Control_config_presets.end()) {
|
||||
Current_preset_name.clear();
|
||||
Defaults_cycle_pos = 0;
|
||||
|
||||
} else {
|
||||
Current_preset_name = preset_it->name;
|
||||
Defaults_cycle_pos = static_cast<unsigned int>(std::distance(Control_config_presets.begin(), preset_it));
|
||||
}
|
||||
|
||||
@@ -1651,6 +1660,9 @@ void control_config_close(bool API_Access)
|
||||
Cc_lines.clear();
|
||||
Conflicts.clear();
|
||||
Undo_controls.clear();
|
||||
|
||||
// Clear this, just to be tidy
|
||||
Current_preset_name.clear();
|
||||
}
|
||||
|
||||
SCP_vector<CC_preset>::iterator control_config_get_current_preset(bool invert_agnostic) {
|
||||
@@ -1896,7 +1908,7 @@ int control_config_draw_list(int select_tease_line) {
|
||||
char buf[256]; // c_str buffer
|
||||
int font_height = gr_get_font_height();
|
||||
|
||||
for (line = Scroll_offset; cc_line_query_visible(line); ++line) {
|
||||
for (line = Scroll_offset; cc_line_query_visible(line) && (line - Scroll_offset < LIST_BUTTONS_MAX); ++line) {
|
||||
z = Cc_lines[line].cc_index;
|
||||
|
||||
// screen coordinate y = list box origin y + (this item's relative y - topmost item's relative y)
|
||||
@@ -2091,7 +2103,7 @@ int control_config_bind_key_on_frame(int ctrl, selItem item, bool API_Access)
|
||||
}
|
||||
|
||||
if ((ctrl == BANK_WHEN_PRESSED || ctrl == GLIDE_WHEN_PRESSED) && (Last_key >= 0) && (k <= 0) &&
|
||||
!keyd_pressed[Last_key]) {
|
||||
!key_is_pressed(Last_key)) {
|
||||
// If the selected cc_item is BANK_WHEN_PRESSED or GLIDE_WHEN_PRESSED, and
|
||||
// If the polled key is a modifier, and
|
||||
// k was consumed, and
|
||||
@@ -2820,12 +2832,12 @@ int check_control_used(int id, int key)
|
||||
|
||||
// check what current modifiers are pressed
|
||||
mask = 0;
|
||||
if (keyd_pressed[KEY_LSHIFT] || key_down_count(KEY_LSHIFT) || keyd_pressed[KEY_RSHIFT] || key_down_count(KEY_RSHIFT)) {
|
||||
if (key_is_pressed(KEY_LSHIFT, true) || key_is_pressed(KEY_RSHIFT, true)) {
|
||||
// Any shift key is pressed, add KEY_SHIFTED mask
|
||||
mask |= KEY_SHIFTED;
|
||||
}
|
||||
|
||||
if (keyd_pressed[KEY_LALT] || key_down_count(KEY_LALT) || keyd_pressed[KEY_RALT] || key_down_count(KEY_RALT)) {
|
||||
if (key_is_pressed(KEY_LALT, true) || key_is_pressed(KEY_RALT, true)) {
|
||||
// Any alt key is pressed, add KEY_ALTED to the mask
|
||||
mask |= KEY_ALTED;
|
||||
}
|
||||
@@ -2841,7 +2853,7 @@ int check_control_used(int id, int key)
|
||||
|
||||
z &= KEY_MASK;
|
||||
|
||||
if (keyd_pressed[z] || key_down_count(z)) {
|
||||
if (key_is_pressed(z, true)) {
|
||||
// Key combo is pressed, control activated
|
||||
control_used(id);
|
||||
return 1;
|
||||
|
||||
@@ -947,7 +947,7 @@ int check_control(int id, int key = -1);
|
||||
void control_get_axes_readings(int *axis_v, float frame_time);
|
||||
|
||||
/**
|
||||
* @brief Markes the given control (by IoActionId) as used
|
||||
* @brief Marks the given control (by IoActionId) as used
|
||||
*
|
||||
* @details Updates the ::used timestamp, triggers a script hook, and marks ::continous_ongoing as true
|
||||
*/
|
||||
|
||||
@@ -48,12 +48,13 @@ int Joy_dead_zone_size = 10;
|
||||
auto DeadZoneOption = options::OptionBuilder<int>("Input.JoystickDeadZone",
|
||||
std::pair<const char*, int>{"Deadzone", 1377},
|
||||
std::pair<const char*, int>{"The deadzone used for all joysticks", 1744})
|
||||
.category("Input")
|
||||
.category(std::make_pair("Input", 1827))
|
||||
.range(0, 45)
|
||||
.level(options::ExpertLevel::Beginner)
|
||||
.default_val(10)
|
||||
.bind_to(&Joy_dead_zone_size)
|
||||
.importance(1)
|
||||
.flags({options::OptionFlags::RetailBuiltinOption})
|
||||
.finish();
|
||||
|
||||
int Joy_sensitivity = 9;
|
||||
@@ -61,12 +62,13 @@ int Joy_sensitivity = 9;
|
||||
auto SensitivityOption = options::OptionBuilder<int>("Input.JoystickSensitivity",
|
||||
std::pair<const char*, int>{"Sensitivity", 1745},
|
||||
std::pair<const char*, int>{"The sensitivity used for all joysticks", 1746})
|
||||
.category("Input")
|
||||
.category(std::make_pair("Input", 1827))
|
||||
.range(0, 9)
|
||||
.level(options::ExpertLevel::Beginner)
|
||||
.default_val(9)
|
||||
.bind_to(&Joy_sensitivity)
|
||||
.importance(2)
|
||||
.flags({options::OptionFlags::RetailBuiltinOption})
|
||||
.finish();
|
||||
|
||||
//! arrays which hold the key mappings. The array index represents a key-independent action.
|
||||
@@ -264,11 +266,11 @@ void control_config_common_init_bindings() {
|
||||
(HUD_TARGETBOX_TOGGLE_WIREFRAME, KEY_ALTED | KEY_SHIFTED | KEY_Q, -1, COMPUTER_TAB, 1, "Toggle HUD Wireframe Target View", CC_TYPE_TRIGGER)
|
||||
|
||||
// Custom Controls
|
||||
(CUSTOM_CONTROL_1, KEY_ALTED | KEY_SHIFTED | KEY_1, -1, COMPUTER_TAB, 0, "Custom Control 1", CC_TYPE_TRIGGER, true)
|
||||
(CUSTOM_CONTROL_2, KEY_ALTED | KEY_SHIFTED | KEY_2, -1, COMPUTER_TAB, 0, "Custom Control 2", CC_TYPE_TRIGGER, true)
|
||||
(CUSTOM_CONTROL_3, KEY_ALTED | KEY_SHIFTED | KEY_3, -1, COMPUTER_TAB, 0, "Custom Control 3", CC_TYPE_TRIGGER, true)
|
||||
(CUSTOM_CONTROL_4, KEY_ALTED | KEY_SHIFTED | KEY_4, -1, COMPUTER_TAB, 0, "Custom Control 4", CC_TYPE_TRIGGER, true)
|
||||
(CUSTOM_CONTROL_5, KEY_ALTED | KEY_SHIFTED | KEY_5, -1, COMPUTER_TAB, 0, "Custom Control 5", CC_TYPE_TRIGGER, true)
|
||||
(CUSTOM_CONTROL_1, KEY_ALTED | KEY_SHIFTED | KEY_1, -1, COMPUTER_TAB, 1784, "Custom Control 1", CC_TYPE_TRIGGER, true)
|
||||
(CUSTOM_CONTROL_2, KEY_ALTED | KEY_SHIFTED | KEY_2, -1, COMPUTER_TAB, 1785, "Custom Control 2", CC_TYPE_TRIGGER, true)
|
||||
(CUSTOM_CONTROL_3, KEY_ALTED | KEY_SHIFTED | KEY_3, -1, COMPUTER_TAB, 1786, "Custom Control 3", CC_TYPE_TRIGGER, true)
|
||||
(CUSTOM_CONTROL_4, KEY_ALTED | KEY_SHIFTED | KEY_4, -1, COMPUTER_TAB, 1787, "Custom Control 4", CC_TYPE_TRIGGER, true)
|
||||
(CUSTOM_CONTROL_5, KEY_ALTED | KEY_SHIFTED | KEY_5, -1, COMPUTER_TAB, 1788, "Custom Control 5", CC_TYPE_TRIGGER, true)
|
||||
.end(); // Builder
|
||||
|
||||
// init default preset
|
||||
@@ -451,7 +453,7 @@ const char* Joy_button_text_french_u[] = {
|
||||
"Bouton 13", "Bouton 14", "Bouton 15", "Bouton 16", "Bouton 17", "Bouton 18",
|
||||
"Bouton 19", "Bouton 20", "Bouton 21", "Bouton 22", "Bouton 23", "Bouton 24",
|
||||
"Bouton 25", "Bouton 26", "Bouton 27", "Bouton 28", "Bouton 29", "Bouton 30",
|
||||
"Bouton 31", "Bouton 32", "Chapeau Arri\xc3\xa8""re", "Chapeau Avant", "Chapeau Gauche", "Chapeau Droite"
|
||||
"Bouton 31", "Bouton 32", ("Chapeau Arri\xc3\xa8""re"), "Chapeau Avant", "Chapeau Gauche", "Chapeau Droite"
|
||||
};
|
||||
|
||||
const char* Joy_button_text_polish_u[] = {
|
||||
@@ -460,7 +462,7 @@ const char* Joy_button_text_polish_u[] = {
|
||||
"Przyc.13", "Przyc.14", "Przyc.15", "Przyc.16", "Przyc.17", "Przyc.18",
|
||||
"Przyc.19", "Przyc.20", "Przyc.21", "Przyc.22", "Przyc.23", "Przyc.24",
|
||||
"Przyc.25", "Przyc.26", "Przyc.27", "Przyc.28", "Przyc.29", "Przyc.30",
|
||||
"Przyc.31", "Przyc.32", "Hat Ty\xc5\x82", "Hat Prz\xc3\xb3""d", "Hat Lewo", "Hat Prawo"
|
||||
"Przyc.31", "Przyc.32", "Hat Ty\xc5\x82", ("Hat Prz\xc3\xb3""d"), "Hat Lewo", "Hat Prawo"
|
||||
};
|
||||
|
||||
const char* Joy_button_text_english_u[] = {
|
||||
@@ -2782,10 +2784,12 @@ bool CCB::operator!=(const CCB& A) const {
|
||||
}
|
||||
|
||||
bool CCB::has_first_conflict(const CCB& A) const {
|
||||
// coverity[copy_paste_error:FALSE]
|
||||
return !first.empty() && (first.conflicts_with(A.first) || first.conflicts_with(A.second));
|
||||
}
|
||||
|
||||
bool CCB::has_second_conflict(const CCB& A) const {
|
||||
// coverity[copy_paste_error:FALSE]
|
||||
return !second.empty() && (second.conflicts_with(A.first) || second.conflicts_with(A.second));
|
||||
}
|
||||
|
||||
|
||||
@@ -52,6 +52,7 @@ struct MovieProperties {
|
||||
FrameSize size;
|
||||
|
||||
float fps = -1.0f;
|
||||
float duration = 0.0f;
|
||||
|
||||
FramePixelFormat pixelFormat = FramePixelFormat::Invalid;
|
||||
};
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
|
||||
extern int Cmdline_nomovies;
|
||||
|
||||
bool Movie_active = false;
|
||||
|
||||
|
||||
const char* Cutscene_bitmap_name[GR_NUM_RESOLUTIONS] = {
|
||||
"ViewFootage",
|
||||
@@ -60,6 +62,18 @@ static cutscene_info *get_cutscene_pointer(char *cutscene_filename)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int get_cutscene_index_by_name(const char* name)
|
||||
{
|
||||
for (int i = 0; i < static_cast<int>(Cutscenes.size()); i++) {
|
||||
if (!stricmp(name, Cutscenes[i].name)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
// Didn't find anything.
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void cutscene_info_init(cutscene_info *csni)
|
||||
{
|
||||
csni->filename[0] = '\0';
|
||||
@@ -222,7 +236,6 @@ void cutscene_mark_viewable(const char* filename)
|
||||
|
||||
// change to lower case
|
||||
strlwr(file);
|
||||
int i = 0;
|
||||
for (SCP_vector<cutscene_info>::iterator cut = Cutscenes.begin(); cut != Cutscenes.end(); ++cut)
|
||||
{
|
||||
// change the cutscene file name to lower case
|
||||
@@ -235,7 +248,6 @@ void cutscene_mark_viewable(const char* filename)
|
||||
cut->flags.set(Cutscene::Cutscene_Flags::Viewable);
|
||||
return;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
Warning(LOCATION, "Could not find cutscene '%s' in listing; cannot mark it viewable...", filename);
|
||||
|
||||
@@ -37,6 +37,8 @@ typedef struct cutscene_info
|
||||
|
||||
extern SCP_vector<cutscene_info> Cutscenes;
|
||||
|
||||
extern bool Movie_active;
|
||||
|
||||
// initializa table data
|
||||
void cutscene_init();
|
||||
|
||||
@@ -48,4 +50,6 @@ void cutscenes_screen_do_frame();
|
||||
|
||||
void cutscene_mark_viewable(const char* filename);
|
||||
|
||||
int get_cutscene_index_by_name(const char* name);
|
||||
|
||||
#endif
|
||||
@@ -6,7 +6,7 @@ namespace {
|
||||
const int OUT_CH_LAYOUT = AV_CH_LAYOUT_STEREO;
|
||||
const int OUT_SAMPLE_RATE = 48000;
|
||||
const AVSampleFormat OUT_SAMPLE_FORMAT = AV_SAMPLE_FMT_S16;
|
||||
const int OUT_NUM_CHANNELS = av_get_channel_layout_nb_channels(OUT_CH_LAYOUT);
|
||||
const int OUT_NUM_CHANNELS = av_popcount64(OUT_CH_LAYOUT);
|
||||
|
||||
const int DEFAULT_SRC_NUM_SAMPLES = 1024;
|
||||
|
||||
|
||||
@@ -69,7 +69,11 @@ CodecContextParameters getCodecParameters(AVStream* stream) {
|
||||
paras.height = stream->codecpar->height;
|
||||
paras.pixel_format = (AVPixelFormat)stream->codecpar->format;
|
||||
|
||||
paras.channel_layout = stream->codecpar->channel_layout;
|
||||
#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(59, 36, 255)
|
||||
paras.channel_layout = stream->codecpar->ch_layout.u.mask;
|
||||
#else
|
||||
paras.channel_layout = stream->codecpar->channel_layout;
|
||||
#endif
|
||||
paras.sample_rate = stream->codecpar->sample_rate;
|
||||
paras.audio_format = (AVSampleFormat)stream->codecpar->format;
|
||||
|
||||
@@ -503,6 +507,7 @@ MovieProperties FFMPEGDecoder::getProperties() const
|
||||
props.size.height = static_cast<size_t>(m_status->videoCodecPars.height);
|
||||
|
||||
props.fps = static_cast<float>(getFrameRate(m_status->videoStream, m_status->videoCodecCtx));
|
||||
props.duration = static_cast<float>(m_status->videoStream->duration * av_q2d(m_status->videoStream->time_base));
|
||||
|
||||
props.pixelFormat = getPixelFormat(getConversionFormat(m_status->videoCodecPars.pixel_format));
|
||||
|
||||
|
||||
@@ -122,7 +122,7 @@ void SubtitleDecoder::pushSubtitleFrame(AVPacket* packet, AVSubtitle* subtitle)
|
||||
}
|
||||
|
||||
SubtitleFramePtr frame(new SubtitleFrame());
|
||||
frame->text = processed_text;
|
||||
frame->text = std::move(processed_text);
|
||||
|
||||
frame->displayStartTime = start_time;
|
||||
frame->displayEndTime = end_time;
|
||||
|
||||
+18
-1
@@ -45,6 +45,7 @@ struct PlaybackState {
|
||||
vec2d posBottomRight;
|
||||
|
||||
int subtitle_font = -1;
|
||||
color subtitle_color = Color_bright_white;
|
||||
};
|
||||
|
||||
void processEvents()
|
||||
@@ -102,7 +103,7 @@ void displayVideo(Player* player, PlaybackState* state) {
|
||||
|
||||
auto subtitle = player->getCurrentSubtitle();
|
||||
if (!subtitle.empty() && state->subtitle_font >= 0) {
|
||||
gr_set_color_fast(&Color_bright_white);
|
||||
gr_set_color_fast(&state->subtitle_color);
|
||||
font::set_font(state->subtitle_font);
|
||||
|
||||
int width;
|
||||
@@ -179,7 +180,20 @@ void initialize_player_state(Player* player, PlaybackState* state) {
|
||||
|
||||
if (state->subtitle_font < 0) {
|
||||
Warning(LOCATION, "Failed to load subtitle font '%s'! Subtitles will be disabled.", Movie_subtitle_font.c_str());
|
||||
}
|
||||
|
||||
if ((Movie_subtitle_rgba[0] >= 0 && Movie_subtitle_rgba[0] <= 255) &&
|
||||
(Movie_subtitle_rgba[1] >= 0 && Movie_subtitle_rgba[1] <= 255) &&
|
||||
(Movie_subtitle_rgba[2] >= 0 && Movie_subtitle_rgba[2] <= 255) &&
|
||||
(Movie_subtitle_rgba[3] >= 0 && Movie_subtitle_rgba[3] <= 255))
|
||||
{
|
||||
gr_init_alphacolor(&state->subtitle_color,
|
||||
Movie_subtitle_rgba[0],
|
||||
Movie_subtitle_rgba[1],
|
||||
Movie_subtitle_rgba[2],
|
||||
Movie_subtitle_rgba[3]);
|
||||
}
|
||||
|
||||
}
|
||||
else if (font::FontManager::numberOfFonts() > 0) {
|
||||
state->subtitle_font = 0; // if not explicitly specified, default to the first available font
|
||||
@@ -278,6 +292,7 @@ bool play(const char* name) {
|
||||
// clear the screen and hide the mouse cursor
|
||||
io::mouse::CursorManager::get()->pushStatus();
|
||||
io::mouse::CursorManager::get()->showCursor(false);
|
||||
Movie_active = true;
|
||||
gr_reset_clip();
|
||||
gr_set_color(255, 255, 255);
|
||||
gr_set_clear_color(0, 0, 0);
|
||||
@@ -304,6 +319,8 @@ bool play(const char* name) {
|
||||
mprintf(("MOVIE ERROR: Found invalid movie! (%s)\n", name));
|
||||
}
|
||||
|
||||
Movie_active = false;
|
||||
|
||||
// show the mouse cursor again
|
||||
io::mouse::CursorManager::get()->popStatus();
|
||||
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
+332
-177
@@ -3,6 +3,17 @@
|
||||
#include "cfile/cfile.h"
|
||||
#include "osapi/osregistry.h"
|
||||
|
||||
#ifdef WITH_OPENGL
|
||||
#include <glad/glad.h>
|
||||
#else
|
||||
static constexpr int GLAD_GL_EXT_texture_compression_s3tc = 0;
|
||||
static constexpr int GLAD_GL_ARB_texture_compression_bptc = 0;
|
||||
#endif
|
||||
|
||||
#define BCDEC_IMPLEMENTATION 1
|
||||
PUSH_SUPPRESS_WARNINGS
|
||||
#include "ddsutils/bcdec.h"
|
||||
POP_SUPPRESS_WARNINGS
|
||||
|
||||
/* Currently supported formats:
|
||||
* DXT1a (compressed)
|
||||
@@ -12,12 +23,9 @@
|
||||
* uncompressed 1555 (16-bit, 1-bit being alpha)
|
||||
* uncompressed 8888 (32-bit)
|
||||
* uncompressed 888 (24-bit, no alpha)
|
||||
* paletted 8-bit (256 colors)
|
||||
* uncompressed R8 (8-bit, Red channel as luminance)
|
||||
*/
|
||||
|
||||
|
||||
int Texture_compression_available = 0;
|
||||
int Use_compressed_textures = 0;
|
||||
|
||||
// power of two check, to verify that a given DDS will always be usable since
|
||||
// some may not be power-of-2
|
||||
@@ -26,39 +34,219 @@ static inline int is_power_of_two(int w, int h)
|
||||
return ( (w && !(w & (w-1))) && (h && !(h & (h-1))) );
|
||||
}
|
||||
|
||||
// This function is used to verify that the file format specified in the DX10 Header
|
||||
// is supported by the OpenGL extensions
|
||||
bool dds_read_dx10_header(CFILE* dds_file, DDS_HEADER_DXT10* header)
|
||||
static bool valid_dx10_format(const DDS_HEADER_DXT10 &header)
|
||||
{
|
||||
header->dxgiFormat = static_cast<DXGI_FORMAT>(cfread_uint(dds_file));
|
||||
header->resourceDimension = static_cast<D3D10_RESOURCE_DIMENSION>(cfread_uint(dds_file));
|
||||
header->miscFlag = cfread_uint(dds_file);
|
||||
header->arraySize = cfread_uint(dds_file);
|
||||
header->miscFlags2 = cfread_uint(dds_file);
|
||||
switch (header.dxgiFormat) {
|
||||
case DXGI_FORMAT::DXGI_FORMAT_BC7_TYPELESS:
|
||||
case DXGI_FORMAT::DXGI_FORMAT_BC7_UNORM:
|
||||
case DXGI_FORMAT::DXGI_FORMAT_BC7_UNORM_SRGB:
|
||||
return true;
|
||||
|
||||
switch (header->dxgiFormat) {
|
||||
case DXGI_FORMAT::DXGI_FORMAT_BC7_TYPELESS:
|
||||
case DXGI_FORMAT::DXGI_FORMAT_BC7_UNORM:
|
||||
case DXGI_FORMAT::DXGI_FORMAT_BC7_UNORM_SRGB:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int dds_read_header(const char *filename, CFILE *img_cfp, int *width, int *height, int *bpp, int *compression_type, int *levels, size_t *size, ubyte *palette)
|
||||
static bool conversion_needed(const DDS_HEADER &dds_header)
|
||||
{
|
||||
if ((dds_header.ddspf.dwFlags & DDPF_FOURCC) != DDPF_FOURCC) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (dds_header.ddspf.dwFourCC) {
|
||||
case FOURCC_DXT1:
|
||||
case FOURCC_DXT3:
|
||||
case FOURCC_DXT5:
|
||||
return !GLAD_GL_EXT_texture_compression_s3tc;
|
||||
|
||||
case FOURCC_DX10:
|
||||
// anything other than BC7 will end up invalid
|
||||
return !GLAD_GL_ARB_texture_compression_bptc;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// anything not specifically listed should end up invalid
|
||||
return false;
|
||||
}
|
||||
|
||||
// Memory usage for uncompressed textures is quite high. Some MVP assets can
|
||||
// require well over a GB of VRAM for a single ship after conversion. To help
|
||||
// alleviate this we need to resize those textures where possible. At 1024x1024
|
||||
// the memory requirement is reduced to about 36 MB per ship with a full set
|
||||
// of textures.
|
||||
//
|
||||
// NOTE: modifies header!!
|
||||
//
|
||||
// returns: number of mipmap levels to skip
|
||||
static uint conversion_resize(DDS_HEADER &dds_header)
|
||||
{
|
||||
const size_t MAX_SIZE = 1024;
|
||||
uint width, height, depth, offset = 0;
|
||||
|
||||
if (dds_header.dwMipMapCount <= 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
width = dds_header.dwWidth;
|
||||
height = dds_header.dwHeight;
|
||||
depth = dds_header.dwDepth;
|
||||
|
||||
// drop levels until we get to an appropriate size, but make sure we have
|
||||
// at least 1 mipmap level remaining at the end (in case there's not a full chain)
|
||||
while (((width > MAX_SIZE) || (height > MAX_SIZE)) && (offset < dds_header.dwMipMapCount-1)) {
|
||||
width >>= 1;
|
||||
height >>= 1;
|
||||
depth >>= 1;
|
||||
|
||||
++offset;
|
||||
}
|
||||
|
||||
// no change needed
|
||||
if ( !offset ) {
|
||||
return offset;
|
||||
}
|
||||
|
||||
// update header with new values
|
||||
dds_header.dwWidth = std::max(1U, width);
|
||||
dds_header.dwHeight = std::max(1U, height);
|
||||
dds_header.dwDepth = std::max(1U, depth);
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
static int _dds_read_header(CFILE *ddsfile, DDS_HEADER &dds_header, DDS_HEADER_DXT10 *dds_header_dx10 = nullptr)
|
||||
{
|
||||
DDS_HEADER_DXT10 dx10_header;
|
||||
|
||||
// read the code
|
||||
int code = cfread_int(ddsfile);
|
||||
|
||||
// check it
|
||||
if (code != DDS_FILECODE) {
|
||||
return DDS_ERROR_BAD_HEADER;
|
||||
}
|
||||
|
||||
// read header variables
|
||||
dds_header.dwSize = cfread_uint(ddsfile);
|
||||
dds_header.dwFlags = cfread_uint(ddsfile);
|
||||
dds_header.dwHeight = cfread_uint(ddsfile);
|
||||
dds_header.dwWidth = cfread_uint(ddsfile);
|
||||
dds_header.dwPitchOrLinearSize = cfread_uint(ddsfile);
|
||||
dds_header.dwDepth = cfread_uint(ddsfile);
|
||||
dds_header.dwMipMapCount = cfread_uint(ddsfile);
|
||||
|
||||
// skip over the crap we don't care about
|
||||
cfseek(ddsfile, 11*4, CF_SEEK_CUR);
|
||||
|
||||
dds_header.ddspf.dwSize = cfread_uint(ddsfile);
|
||||
dds_header.ddspf.dwFlags = cfread_uint(ddsfile);
|
||||
dds_header.ddspf.dwFourCC = cfread_uint(ddsfile);
|
||||
dds_header.ddspf.dwRGBBitCount = cfread_uint(ddsfile);
|
||||
dds_header.ddspf.dwRBitMask = cfread_uint(ddsfile);
|
||||
dds_header.ddspf.dwGBitMask = cfread_uint(ddsfile);
|
||||
dds_header.ddspf.dwBBitMask = cfread_uint(ddsfile);
|
||||
dds_header.ddspf.dwABitMask = cfread_uint(ddsfile);
|
||||
|
||||
dds_header.dwCaps = cfread_uint(ddsfile);
|
||||
dds_header.dwCaps2 = cfread_uint(ddsfile);
|
||||
|
||||
// Unused but need them checked for later
|
||||
dds_header.dwCaps3 = cfread_uint(ddsfile);
|
||||
dds_header.dwCaps4 = cfread_uint(ddsfile);
|
||||
dds_header.dwReserved2 = cfread_uint(ddsfile);
|
||||
|
||||
if (dds_header.ddspf.dwFourCC == FOURCC_DX10) {
|
||||
dx10_header.dxgiFormat = static_cast<DXGI_FORMAT>(cfread_uint(ddsfile));
|
||||
dx10_header.resourceDimension = static_cast<D3D10_RESOURCE_DIMENSION>(cfread_uint(ddsfile));
|
||||
dx10_header.miscFlag = cfread_uint(ddsfile);
|
||||
dx10_header.arraySize = cfread_uint(ddsfile);
|
||||
dx10_header.miscFlags2 = cfread_uint(ddsfile);
|
||||
|
||||
if (dds_header_dx10) {
|
||||
memcpy(dds_header_dx10, &dx10_header, sizeof(DDS_HEADER_DXT10));
|
||||
}
|
||||
}
|
||||
|
||||
// sanitize values
|
||||
dds_header.dwDepth = std::max(1U, dds_header.dwDepth);
|
||||
dds_header.dwMipMapCount = std::max(1U, dds_header.dwMipMapCount);
|
||||
|
||||
#ifndef NDEBUG
|
||||
if (dds_header.dwDepth > 1) {
|
||||
Assertion(dds_header.dwFlags & DDSD_DEPTH, "ERROR: Volume texture missing proper flags!!");
|
||||
}
|
||||
#endif
|
||||
|
||||
// set pitch manually (per MS docs)
|
||||
dds_header.dwFlags &= ~DDSD_LINEARSIZE;
|
||||
dds_header.dwFlags |= DDSD_PITCH;
|
||||
|
||||
if (dds_header.ddspf.dwFlags & DDPF_FOURCC) {
|
||||
int block_size = (dds_header.ddspf.dwFourCC == FOURCC_DXT1) ? 8 : 16;
|
||||
dds_header.dwPitchOrLinearSize = std::max(1U, (dds_header.dwWidth+3)/4) * block_size;
|
||||
} else {
|
||||
// this isn't technically correct, but it's only wrong for formats we don't support
|
||||
dds_header.dwPitchOrLinearSize = (dds_header.dwWidth * dds_header.ddspf.dwRGBBitCount + 7) / 8;
|
||||
}
|
||||
|
||||
return DDS_ERROR_NONE;
|
||||
}
|
||||
|
||||
static size_t compute_dds_size(const DDS_HEADER &dds_header)
|
||||
{
|
||||
uint d_width, d_height, d_depth;
|
||||
size_t d_size = 0;
|
||||
|
||||
for (uint i = 0; i < dds_header.dwMipMapCount; i++) {
|
||||
d_width = std::max(1U, dds_header.dwWidth >> i);
|
||||
d_height = std::max(1U, dds_header.dwHeight >> i);
|
||||
d_depth = std::max(1U, dds_header.dwDepth >> i);
|
||||
|
||||
if (dds_header.ddspf.dwFlags & DDPF_FOURCC) {
|
||||
// size of data block (4x4)
|
||||
d_size += ((d_width + 3) / 4) * ((d_height + 3) / 4) * d_depth * ((dds_header.ddspf.dwFourCC == FOURCC_DXT1) ? 8 : 16);
|
||||
} else {
|
||||
d_size += d_width * d_height * d_depth * (dds_header.ddspf.dwRGBBitCount / 8);
|
||||
}
|
||||
}
|
||||
|
||||
// assumes valid cubemap (should be checked elsewhere)
|
||||
if (dds_header.dwCaps2 & DDSCAPS2_CUBEMAP) {
|
||||
// the previously computed size is just per face, mult by 6 for full size
|
||||
d_size *= 6;
|
||||
}
|
||||
|
||||
Assertion(d_size > 0, "ERROR: DDS size computed to 0!!");
|
||||
|
||||
return d_size;
|
||||
}
|
||||
|
||||
static int get_bit_count(const DDS_HEADER &dds_header)
|
||||
{
|
||||
if (dds_header.ddspf.dwFlags & DDPF_RGB) {
|
||||
return dds_header.ddspf.dwRGBBitCount;
|
||||
} else if (dds_header.ddspf.dwFlags & DDPF_FOURCC) {
|
||||
if (dds_header.ddspf.dwFourCC == FOURCC_DXT1) {
|
||||
return 24;
|
||||
} else {
|
||||
return 32;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dds_read_header(const char *filename, CFILE *img_cfp, int *width, int *height, int *bpp, int *compression_type, int *levels, size_t *size)
|
||||
{
|
||||
DDS_HEADER dds_header;
|
||||
DDS_HEADER_DXT10 dds_header_dx10;
|
||||
int code = 0;
|
||||
CFILE *ddsfile;
|
||||
char real_name[MAX_FILENAME_LEN];
|
||||
int retval = DDS_ERROR_NONE;
|
||||
int ct = DDS_UNCOMPRESSED;
|
||||
int bits = 0;
|
||||
int i, is_cubemap = 0;
|
||||
uint32_t d_width = 0, d_height = 0, d_depth = 0;
|
||||
size_t d_size = 0;
|
||||
int is_cubemap = 0;
|
||||
|
||||
|
||||
if (img_cfp == NULL) {
|
||||
@@ -81,113 +269,36 @@ int dds_read_header(const char *filename, CFILE *img_cfp, int *width, int *heigh
|
||||
ddsfile = img_cfp;
|
||||
}
|
||||
|
||||
// read the code
|
||||
code = cfread_int(ddsfile);
|
||||
retval = _dds_read_header(ddsfile, dds_header, &dds_header_dx10);
|
||||
|
||||
// check it
|
||||
if (code != DDS_FILECODE) {
|
||||
retval = DDS_ERROR_BAD_HEADER;
|
||||
if (retval != DDS_ERROR_NONE) {
|
||||
goto Done;
|
||||
}
|
||||
|
||||
// read header variables
|
||||
dds_header.dwSize = cfread_uint(ddsfile);
|
||||
dds_header.dwFlags = cfread_uint(ddsfile);
|
||||
dds_header.dwHeight = cfread_uint(ddsfile);
|
||||
dds_header.dwWidth = cfread_uint(ddsfile);
|
||||
dds_header.dwPitchOrLinearSize = cfread_uint(ddsfile);
|
||||
dds_header.dwDepth = cfread_uint(ddsfile);
|
||||
dds_header.dwMipMapCount = cfread_uint(ddsfile);
|
||||
// check for valid cubemap (we require all 6 faces)
|
||||
if (dds_header.dwCaps2 & DDSCAPS2_CUBEMAP) {
|
||||
if ( !(dds_header.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES) ) {
|
||||
retval = DDS_ERROR_CUBEMAP_FACES;
|
||||
ct = DDS_DXT_INVALID;
|
||||
goto Done;
|
||||
}
|
||||
|
||||
// skip over the crap we don't care about
|
||||
for (i = 0; i < 11; i++)
|
||||
cfread_uint(ddsfile);
|
||||
// it's a valid cubemap, probably
|
||||
is_cubemap = 1;
|
||||
}
|
||||
|
||||
dds_header.ddspf.dwSize = cfread_uint(ddsfile);
|
||||
dds_header.ddspf.dwFlags = cfread_uint(ddsfile);
|
||||
dds_header.ddspf.dwFourCC = cfread_uint(ddsfile);
|
||||
dds_header.ddspf.dwRGBBitCount = cfread_uint(ddsfile);
|
||||
dds_header.ddspf.dwRBitMask = cfread_uint(ddsfile);
|
||||
dds_header.ddspf.dwGBitMask = cfread_uint(ddsfile);
|
||||
dds_header.ddspf.dwBBitMask = cfread_uint(ddsfile);
|
||||
dds_header.ddspf.dwABitMask = cfread_uint(ddsfile);
|
||||
|
||||
dds_header.dwCaps = cfread_uint(ddsfile);
|
||||
dds_header.dwCaps2 = cfread_uint(ddsfile);
|
||||
|
||||
// Unused but need them checked for later
|
||||
dds_header.dwCaps3 = cfread_uint(ddsfile);
|
||||
dds_header.dwCaps4 = cfread_uint(ddsfile);
|
||||
dds_header.dwReserved2 = cfread_uint(ddsfile);
|
||||
|
||||
// sanity
|
||||
if (dds_header.dwDepth == 0)
|
||||
dds_header.dwDepth = 1;
|
||||
|
||||
if (dds_header.dwMipMapCount < 1)
|
||||
dds_header.dwMipMapCount = 1;
|
||||
|
||||
d_width = dds_header.dwWidth;
|
||||
d_height = dds_header.dwHeight;
|
||||
d_depth = dds_header.dwDepth;
|
||||
|
||||
// calculate the type and size of the data
|
||||
// determine and verify the type of data for internal use
|
||||
if (dds_header.ddspf.dwFlags & DDPF_FOURCC) {
|
||||
// did I mention lately that I hate Microsoft?
|
||||
// this is here to fix the situation where Microsoft doesn't follow their own docs
|
||||
if ( !(dds_header.dwFlags & (DDSD_LINEARSIZE | DDSD_PITCH) ) || dds_header.dwPitchOrLinearSize <= 0 ) {
|
||||
// calculate the block size, mult by 8 for DXT1, 16 for DXT3 & 5
|
||||
d_size = ((dds_header.dwWidth + 3)/4) * ((dds_header.dwHeight + 3)/4) * ((dds_header.dwDepth + 3)/4) * ((dds_header.ddspf.dwFourCC == FOURCC_DXT1) ? 8 : 16);
|
||||
} else {
|
||||
d_size = dds_header.dwPitchOrLinearSize;
|
||||
}
|
||||
|
||||
// if we have mipmaps then compute them into the final size too
|
||||
for (i = 1; i < (int)dds_header.dwMipMapCount; i++) {
|
||||
// reduce size by half for the next pass
|
||||
d_width /= 2;
|
||||
d_height /= 2;
|
||||
|
||||
if (d_width <= 0)
|
||||
d_width = 1;
|
||||
|
||||
if (d_height <= 0)
|
||||
d_height = 1;
|
||||
|
||||
// size of data block (4x4)
|
||||
d_size += ((d_width + 3) / 4) * ((d_height + 3) / 4) * ((dds_header.ddspf.dwFourCC == FOURCC_DXT1) ? 8 : 16);
|
||||
}
|
||||
|
||||
if ( dds_header.dwCaps2 & DDSCAPS2_CUBEMAP ) {
|
||||
if ( !(dds_header.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES) ) {
|
||||
retval = DDS_ERROR_CUBEMAP_FACES;
|
||||
ct = DDS_DXT_INVALID;
|
||||
goto Done;
|
||||
}
|
||||
|
||||
// it's a valid cubemap, probably
|
||||
is_cubemap = 1;
|
||||
|
||||
// the previously computed size is just per face, mult by 6 for full size
|
||||
d_size *= 6;
|
||||
}
|
||||
|
||||
Assert( d_size > 0 );
|
||||
*size = d_size;
|
||||
|
||||
switch (dds_header.ddspf.dwFourCC) {
|
||||
case FOURCC_DXT1:
|
||||
bits = 24;
|
||||
ct = (is_cubemap) ? DDS_CUBEMAP_DXT1 : DDS_DXT1;
|
||||
break;
|
||||
|
||||
case FOURCC_DXT3:
|
||||
bits = 32;
|
||||
ct = (is_cubemap) ? DDS_CUBEMAP_DXT3 : DDS_DXT3;
|
||||
break;
|
||||
|
||||
case FOURCC_DXT5:
|
||||
bits = 32;
|
||||
ct = (is_cubemap) ? DDS_CUBEMAP_DXT5 : DDS_DXT5;
|
||||
break;
|
||||
|
||||
@@ -200,9 +311,8 @@ int dds_read_header(const char *filename, CFILE *img_cfp, int *width, int *heigh
|
||||
break;
|
||||
|
||||
case FOURCC_DX10:
|
||||
if (dds_read_dx10_header(ddsfile, &dds_header_dx10)) {
|
||||
if (valid_dx10_format(dds_header_dx10)) {
|
||||
// Currently only BC7 is supported
|
||||
bits = 32;
|
||||
ct = DDS_BC7;
|
||||
} else {
|
||||
retval = DDS_ERROR_UNSUPPORTED;
|
||||
@@ -218,46 +328,7 @@ int dds_read_header(const char *filename, CFILE *img_cfp, int *width, int *heigh
|
||||
goto Done;
|
||||
break;
|
||||
}
|
||||
} else if ( dds_header.ddspf.dwFlags & (DDPF_RGB | DDPF_PALETTEINDEXED8) ) {
|
||||
d_size += d_width * d_height * d_depth * (dds_header.ddspf.dwRGBBitCount / 8);
|
||||
|
||||
// calculate full data size for all mipmap levels
|
||||
for (i = 1; i < (int)dds_header.dwMipMapCount; i++) {
|
||||
d_width /= 2;
|
||||
d_height /= 2;
|
||||
d_depth /= 2;
|
||||
|
||||
if (d_width < 1)
|
||||
d_width = 1;
|
||||
|
||||
if (d_height < 1)
|
||||
d_height = 1;
|
||||
|
||||
if (d_depth < 1)
|
||||
d_depth = 1;
|
||||
|
||||
d_size += d_width * d_height * d_depth * (dds_header.ddspf.dwRGBBitCount / 8);
|
||||
}
|
||||
|
||||
Assert( d_size > 0 );
|
||||
|
||||
if ( dds_header.dwCaps2 & DDSCAPS2_CUBEMAP ) {
|
||||
if ( !(dds_header.dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES) ) {
|
||||
retval = DDS_ERROR_CUBEMAP_FACES;
|
||||
ct = DDS_DXT_INVALID;
|
||||
goto Done;
|
||||
}
|
||||
|
||||
// it's a valid cubemap, probably
|
||||
is_cubemap = 1;
|
||||
|
||||
// the previously computed size is just per face, mult by 6 for full size
|
||||
d_size *= 6;
|
||||
}
|
||||
|
||||
*size = d_size;
|
||||
|
||||
bits = dds_header.ddspf.dwRGBBitCount;
|
||||
} else if (dds_header.ddspf.dwFlags & DDPF_RGB) {
|
||||
ct = (is_cubemap) ? DDS_CUBEMAP_UNCOMPRESSED : DDS_UNCOMPRESSED;
|
||||
} else {
|
||||
// it's not a readable format
|
||||
@@ -265,21 +336,33 @@ int dds_read_header(const char *filename, CFILE *img_cfp, int *width, int *heigh
|
||||
goto Done;
|
||||
}
|
||||
|
||||
// maybe do conversion if format not supported
|
||||
if (conversion_needed(dds_header)) {
|
||||
// switch to uncompressed format and reset vars
|
||||
dds_header.ddspf.dwFlags &= ~DDPF_FOURCC;
|
||||
dds_header.ddspf.dwFlags |= DDPF_RGB;
|
||||
|
||||
dds_header.ddspf.dwRGBBitCount = 32;
|
||||
|
||||
// NOTE: modifies header and returns offset for mipmap count
|
||||
dds_header.dwMipMapCount -= conversion_resize(dds_header);
|
||||
dds_header.dwMipMapCount = std::max(1U, dds_header.dwMipMapCount);
|
||||
|
||||
ct = (is_cubemap) ? DDS_CUBEMAP_UNCOMPRESSED : DDS_UNCOMPRESSED;
|
||||
}
|
||||
|
||||
// we don't support compressed, non-power-of-2 images
|
||||
if ( (ct != DDS_UNCOMPRESSED) && (!is_power_of_two(dds_header.dwWidth, dds_header.dwHeight)) ) {
|
||||
retval = DDS_ERROR_NON_POWER_OF_2;
|
||||
goto Done;
|
||||
}
|
||||
|
||||
// make sure that the video card can handle compressed textures before using them
|
||||
if ( !Use_compressed_textures && (ct != DDS_UNCOMPRESSED) && (ct != DDS_DXT_INVALID) ) {
|
||||
retval = DDS_ERROR_NO_COMPRESSION;
|
||||
goto Done;
|
||||
}
|
||||
|
||||
// stuff important info
|
||||
if (size)
|
||||
*size = compute_dds_size(dds_header);
|
||||
|
||||
if (bpp)
|
||||
*bpp = bits;
|
||||
*bpp = get_bit_count(dds_header);
|
||||
|
||||
if (compression_type)
|
||||
*compression_type = ct;
|
||||
@@ -293,12 +376,6 @@ int dds_read_header(const char *filename, CFILE *img_cfp, int *width, int *heigh
|
||||
if (levels)
|
||||
*levels = dds_header.dwMipMapCount;
|
||||
|
||||
if (palette && (bits == 8)) {
|
||||
cfseek(ddsfile, (ct == DDS_BC7) ? DX10_OFFSET : DDS_OFFSET, CF_SEEK_SET);
|
||||
cfread(palette, 1, 1024, ddsfile);
|
||||
}
|
||||
|
||||
|
||||
Done:
|
||||
if (img_cfp == NULL) {
|
||||
// close file and return
|
||||
@@ -313,11 +390,10 @@ Done:
|
||||
int dds_read_bitmap(const char *filename, ubyte *data, ubyte *bpp, int cf_type)
|
||||
{
|
||||
int retval;
|
||||
int w,h,ct,lvl;
|
||||
size_t size = 0;
|
||||
int bits = 0;
|
||||
CFILE *cfp;
|
||||
char real_name[MAX_FILENAME_LEN];
|
||||
DDS_HEADER dds_header;
|
||||
|
||||
// this better not happen.. ever
|
||||
Assert(filename != NULL);
|
||||
@@ -332,25 +408,104 @@ int dds_read_bitmap(const char *filename, ubyte *data, ubyte *bpp, int cf_type)
|
||||
cfp = cfopen(real_name, "rb", CFILE_NORMAL, cf_type);
|
||||
|
||||
// just in case
|
||||
if (cfp == NULL)
|
||||
if (cfp == nullptr)
|
||||
return DDS_ERROR_INVALID_FILENAME;
|
||||
|
||||
// read the header -- if its at this stage, it should be legal.
|
||||
retval = dds_read_header(real_name, cfp, &w, &h, &bits, &ct, &lvl, &size);
|
||||
retval = _dds_read_header(cfp, dds_header);
|
||||
Assert(retval == DDS_ERROR_NONE);
|
||||
|
||||
// this really shouldn't be needed but better safe than sorry
|
||||
if (retval != DDS_ERROR_NONE) {
|
||||
cfclose(cfp);
|
||||
return retval;
|
||||
}
|
||||
|
||||
cfseek(cfp, (ct == DDS_BC7) ? DX10_OFFSET : DDS_OFFSET, CF_SEEK_SET);
|
||||
cfseek(cfp, (dds_header.ddspf.dwFourCC == FOURCC_DX10) ? DX10_OFFSET : DDS_OFFSET, CF_SEEK_SET);
|
||||
|
||||
size = compute_dds_size(dds_header);
|
||||
|
||||
// read in the data
|
||||
cfread(data, 1, (int)size, cfp);
|
||||
if ( !conversion_needed(dds_header) ) {
|
||||
cfread(data, 1, (int)size, cfp);
|
||||
} else {
|
||||
// Compression format not supported, convert to BGRA
|
||||
ubyte *comp_data = (ubyte*)vm_malloc(size);
|
||||
|
||||
cfread(comp_data, 1, (int)size, cfp);
|
||||
|
||||
ubyte *src = comp_data;
|
||||
ubyte *dst = data;
|
||||
|
||||
uint d_width, d_height, d_depth;
|
||||
size_t data_offset = 0;
|
||||
|
||||
// NOTE: this alters the width, height, and depth values in the header,
|
||||
// so we have to jump through some hoops to get the proper values
|
||||
const uint mipmap_offset = conversion_resize(dds_header);
|
||||
|
||||
const int num_faces = (dds_header.dwCaps2 & DDSCAPS2_CUBEMAP) ? 6 : 1;
|
||||
const bool has_depth = (dds_header.dwFlags & DDSD_DEPTH) == DDSD_DEPTH;
|
||||
|
||||
for (int f = 0; f < num_faces; ++f) {
|
||||
// if we resized then skip over all of that data (altering values to match pre-resize)
|
||||
for (uint x = 0; x < mipmap_offset; ++x) {
|
||||
d_width = std::max(1U, dds_header.dwWidth << (mipmap_offset - x));
|
||||
d_height = std::max(1U, dds_header.dwHeight << (mipmap_offset - x));
|
||||
d_depth = has_depth ? std::max(1U, dds_header.dwDepth << (mipmap_offset - x)) : 1U;
|
||||
|
||||
src += (d_width * d_height * d_depth);
|
||||
}
|
||||
|
||||
for (uint m = mipmap_offset; m < dds_header.dwMipMapCount; ++m) {
|
||||
// width/height/depth at post-resize mipmap sizes, so compensate here
|
||||
d_width = std::max(1U, dds_header.dwWidth >> (m - mipmap_offset));
|
||||
d_height = std::max(1U, dds_header.dwHeight >> (m - mipmap_offset));
|
||||
d_depth = std::max(1U, dds_header.dwDepth >> (m - mipmap_offset));
|
||||
|
||||
for (uint d = 0; d < d_depth; ++d) {
|
||||
for (uint i = 0; i < d_height; i += 4) {
|
||||
for (uint j = 0; j < d_width; j += 4) {
|
||||
dst = data + data_offset + ((i * d_width + j) * 4);
|
||||
|
||||
if (dds_header.ddspf.dwFourCC == FOURCC_DX10) {
|
||||
bcdec_bc7(src, dst, d_width * 4);
|
||||
src += BCDEC_BC7_BLOCK_SIZE;
|
||||
} else if (dds_header.ddspf.dwFourCC == FOURCC_DXT5) {
|
||||
bcdec_bc3(src, dst, d_width * 4);
|
||||
src += BCDEC_BC3_BLOCK_SIZE;
|
||||
} else if (dds_header.ddspf.dwFourCC == FOURCC_DXT1) {
|
||||
bcdec_bc1(src, dst, d_width * 4);
|
||||
src += BCDEC_BC1_BLOCK_SIZE;
|
||||
} else if (dds_header.ddspf.dwFourCC == FOURCC_DXT3) {
|
||||
bcdec_bc2(src, dst, d_width * 4);
|
||||
src += BCDEC_BC2_BLOCK_SIZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// we need it in bgra, XOR to the rescue
|
||||
for (size_t x = data_offset; x < (data_offset + (d_width * d_height * d_depth * 4)); x += 4) {
|
||||
data[x] ^= data[x+2], data[x+2] ^= data[x], data[x] ^= data[x+2];
|
||||
}
|
||||
|
||||
// bump data offset to next layer
|
||||
data_offset += (d_width * d_height * d_depth * 4);
|
||||
}
|
||||
}
|
||||
|
||||
vm_free(comp_data);
|
||||
comp_data = nullptr;
|
||||
|
||||
// switch to uncompressed format and reset vars (needed below to get correct bit count)
|
||||
dds_header.ddspf.dwFlags &= ~DDPF_FOURCC;
|
||||
dds_header.ddspf.dwFlags |= DDPF_RGB;
|
||||
dds_header.ddspf.dwRGBBitCount = 32;
|
||||
}
|
||||
|
||||
if (bpp)
|
||||
*bpp = (ubyte)bits;
|
||||
*bpp = (ubyte)get_bit_count(dds_header);
|
||||
|
||||
// we look done here
|
||||
cfclose(cfp);
|
||||
|
||||
@@ -59,6 +59,7 @@
|
||||
#define DDSD_HEIGHT 0x00000002
|
||||
#define DDSD_CAPS 0x00000001
|
||||
#define DDSD_MIPMAPCOUNT 0x00020000
|
||||
#define DDSD_DEPTH 0x00800000
|
||||
|
||||
#define DDSCAPS_COMPLEX 0x00000008
|
||||
#define DDSCAPS_PRIMARYSURFACE 0x00000200
|
||||
@@ -278,7 +279,7 @@ typedef struct {
|
||||
//reads a dds header
|
||||
//returns one of the error values
|
||||
//'compression_type' comes back as one of the DDS_DXTC* defines
|
||||
int dds_read_header(const char *filename, CFILE *img_cfp = NULL, int *width = 0, int *height = 0, int *bpp = 0, int *compression_type = 0, int *levels = 0, size_t *size = 0, ubyte *palette = NULL);
|
||||
int dds_read_header(const char *filename, CFILE *img_cfp = NULL, int *width = 0, int *height = 0, int *bpp = 0, int *compression_type = 0, int *levels = 0, size_t *size = 0);
|
||||
|
||||
//reads bitmap
|
||||
//size of the data it stored in size
|
||||
@@ -290,7 +291,4 @@ void dds_save_image(int width, int height, int bpp, int num_mipmaps, ubyte *data
|
||||
//returns a string from a DDS error code
|
||||
const char *dds_error_string(int code);
|
||||
|
||||
extern int Texture_compression_available;
|
||||
extern int Use_compressed_textures;
|
||||
|
||||
#endif //__DDS_H
|
||||
+13
-11
@@ -501,11 +501,11 @@ object *debris_create_only(int parent_objnum, int parent_ship_class, int alt_typ
|
||||
}
|
||||
else if (vaporize) {
|
||||
db->model_num = Debris_vaporize_model;
|
||||
db->submodel_num = Random::next(Debris_num_submodels);
|
||||
db->submodel_num = (Debris_num_submodels <= 0 ? 0 : Random::next(Debris_num_submodels));
|
||||
}
|
||||
else {
|
||||
db->model_num = Debris_model;
|
||||
db->submodel_num = Random::next(Debris_num_submodels);
|
||||
db->submodel_num = (Debris_num_submodels <= 0 ? 0 : Random::next(Debris_num_submodels));
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -644,7 +644,7 @@ object *debris_create_only(int parent_objnum, int parent_ship_class, int alt_typ
|
||||
if (spark_timeout >= 0) {
|
||||
db->fire_timeout = _timestamp(spark_timeout);
|
||||
} else if (parent_objnum >= 0) {
|
||||
float t = 1000*Objects[parent_objnum].radius/3 + Random::next(fl2i(1000*3*Objects[parent_objnum].radius));
|
||||
float t = 1000*Objects[parent_objnum].radius/3 + (fl2i(1000*3*Objects[parent_objnum].radius) == 0 ? 0 : Random::next(fl2i(1000*3*Objects[parent_objnum].radius)));
|
||||
db->fire_timeout = _timestamp(fl2i(t)); // fireballs last from 5 - 30 seconds
|
||||
} else {
|
||||
db->fire_timeout = TIMESTAMP::immediate();
|
||||
@@ -926,10 +926,9 @@ int debris_check_collision(object *pdebris, object *other_obj, vec3d *hitpos, co
|
||||
mc.flags = (MC_CHECK_MODEL | MC_CHECK_SPHERELINE);
|
||||
|
||||
// copy important data
|
||||
int copy_flags = mc.flags; // make a copy of start end positions of sphere in big ship RF
|
||||
vec3d copy_p0, copy_p1;
|
||||
copy_p0 = *mc.p0;
|
||||
copy_p1 = *mc.p1;
|
||||
int orig_flags = mc.flags; // make a copy of start end positions of sphere in big ship RF
|
||||
vec3d orig_p0 = *mc.p0;
|
||||
vec3d orig_p1 = *mc.p1;
|
||||
|
||||
// first test against the sphere - if this fails then don't do any submodel tests
|
||||
mc.flags = MC_ONLY_SPHERE | MC_CHECK_SPHERELINE;
|
||||
@@ -955,7 +954,7 @@ int debris_check_collision(object *pdebris, object *other_obj, vec3d *hitpos, co
|
||||
}
|
||||
|
||||
// Only check single submodel now, since children of moving submodels are handled as moving as well
|
||||
mc.flags = copy_flags | MC_SUBMODEL;
|
||||
mc.flags = orig_flags | MC_SUBMODEL;
|
||||
|
||||
if (Ship_info[Ships[pship_obj->instance].ship_info_index].collision_lod > -1) {
|
||||
mc.lod = Ship_info[Ships[pship_obj->instance].ship_info_index].collision_lod;
|
||||
@@ -1005,9 +1004,9 @@ int debris_check_collision(object *pdebris, object *other_obj, vec3d *hitpos, co
|
||||
}
|
||||
|
||||
// Now complete base model collision checks that do not take into account rotating submodels.
|
||||
mc.flags = copy_flags;
|
||||
*mc.p0 = copy_p0;
|
||||
*mc.p1 = copy_p1;
|
||||
mc.flags = orig_flags;
|
||||
mc.p0 = &orig_p0;
|
||||
mc.p1 = &orig_p1;
|
||||
mc.orient = &heavy_obj->orient;
|
||||
|
||||
// usual ship_ship collision test
|
||||
@@ -1198,6 +1197,9 @@ void debris_render(object * obj, model_draw_list *scene)
|
||||
// render_info.set_flags(MR_NO_LIGHTING);
|
||||
}
|
||||
|
||||
if (db->model_instance_num >= 0)
|
||||
render_info.set_replacement_textures(model_get_instance(db->model_instance_num)->texture_replace);
|
||||
|
||||
submodel_render_queue( &render_info, scene, pm, pmi, db->submodel_num, &obj->orient, &obj->pos );
|
||||
|
||||
if (tbase != NULL && (swapped!=-1) && pm) {
|
||||
|
||||
+14
-14
@@ -174,7 +174,7 @@ void parse_decals_table(const char* filename) {
|
||||
SCP_string name;
|
||||
stuff_string(name, F_NAME);
|
||||
|
||||
DecalDefinition def(name);
|
||||
DecalDefinition def(std::move(name));
|
||||
def.parse();
|
||||
|
||||
DecalDefinitions.push_back(std::move(def));
|
||||
@@ -186,17 +186,17 @@ void parse_decals_table(const char* filename) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!gr_is_capable(CAPABILITY_DEFERRED_LIGHTING)) {
|
||||
if (!gr_is_capable(gr_capability::CAPABILITY_DEFERRED_LIGHTING)) {
|
||||
// We need deferred lighting
|
||||
Decal_system_active = false;
|
||||
mprintf(("Note: Decal system has been disabled due to lack of deferred lighting.\n"));
|
||||
}
|
||||
if (!gr_is_capable(CAPABILITY_NORMAL_MAP)) {
|
||||
if (!gr_is_capable(gr_capability::CAPABILITY_NORMAL_MAP)) {
|
||||
// We need normal mapping for the full feature range
|
||||
Decal_system_active = false;
|
||||
mprintf(("Note: Decal system has been disabled due to lack of normal mapping.\n"));
|
||||
}
|
||||
if (!gr_is_capable(CAPABILITY_SEPARATE_BLEND_FUNCTIONS)) {
|
||||
if (!gr_is_capable(gr_capability::CAPABILITY_SEPARATE_BLEND_FUNCTIONS)) {
|
||||
// We need separate blending functions for different color buffers
|
||||
Decal_system_active = false;
|
||||
mprintf(("Note: Decal system has been disabled due to lack of separate color buffer blend functions.\n"));
|
||||
@@ -220,17 +220,17 @@ struct Decal {
|
||||
vm_vec_make(&scale, 1.f, 1.f, 1.f);
|
||||
}
|
||||
|
||||
bool isValid() {
|
||||
if (!object.IsValid()) {
|
||||
bool isValid() const {
|
||||
if (!object.isValid()) {
|
||||
return false;
|
||||
}
|
||||
if (object.objp->flags[Object::Object_Flags::Should_be_dead]) {
|
||||
if (object.objp()->flags[Object::Object_Flags::Should_be_dead]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (orig_obj_type != object.objp->type) {
|
||||
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]));
|
||||
object.objnum, Object_type_names[orig_obj_type], Object_type_names[object.objp()->type]));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -241,7 +241,7 @@ struct Decal {
|
||||
}
|
||||
}
|
||||
|
||||
auto objp = object.objp;
|
||||
auto objp = object.objp();
|
||||
if (objp->type == OBJ_SHIP) {
|
||||
auto shipp = &Ships[objp->instance];
|
||||
auto model_instance = model_get_instance(shipp->model_instance_num);
|
||||
@@ -339,7 +339,7 @@ void parseDecalReference(creation_info& dest_info, bool is_new_entry) {
|
||||
}
|
||||
|
||||
if (required_string_if_new("+Radius:", is_new_entry)) {
|
||||
dest_info.radius = util::parseUniformRange(0.0001f);
|
||||
dest_info.radius = util::ParsedRandomFloatRange::parseRandomRange(0.0001f);
|
||||
}
|
||||
|
||||
if (required_string_if_new("+Lifetime:", is_new_entry)) {
|
||||
@@ -347,7 +347,7 @@ void parseDecalReference(creation_info& dest_info, bool is_new_entry) {
|
||||
dest_info.lifetime = util::UniformFloatRange(-1.0f);
|
||||
} else {
|
||||
// Require at least a small lifetime so that the calculations don't have to deal with div-by-zero
|
||||
dest_info.lifetime = util::parseUniformRange(0.0001f);
|
||||
dest_info.lifetime = util::ParsedRandomFloatRange::parseRandomRange(0.0001f);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -393,9 +393,9 @@ void initializeMission() {
|
||||
}
|
||||
|
||||
matrix4 getDecalTransform(Decal& decal) {
|
||||
Assertion(decal.object.objp->type == OBJ_SHIP, "Only ships are currently supported for decals!");
|
||||
Assertion(decal.object.objp()->type == OBJ_SHIP, "Only ships are currently supported for decals!");
|
||||
|
||||
auto objp = decal.object.objp;
|
||||
auto objp = decal.object.objp();
|
||||
auto ship = &Ships[objp->instance];
|
||||
auto pmi = model_get_instance(ship->model_instance_num);
|
||||
auto pm = model_get(pmi->model_num);
|
||||
|
||||
@@ -65,10 +65,10 @@ typedef int DecalReference;
|
||||
*/
|
||||
struct creation_info {
|
||||
DecalReference definition_handle = -1;
|
||||
util::UniformFloatRange radius = ::util::UniformFloatRange(-1.0f);
|
||||
util::ParsedRandomFloatRange radius = ::util::UniformFloatRange(-1.0f);
|
||||
float width = -1.0f;
|
||||
float height = -1.0f;
|
||||
util::UniformFloatRange lifetime = ::util::UniformFloatRange(-1.0f);
|
||||
util::ParsedRandomFloatRange lifetime = ::util::UniformFloatRange(-1.0f);
|
||||
bool random_rotation = false;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,9 +1,17 @@
|
||||
in vec4 fragTexCoord;
|
||||
out vec4 fragOut0;
|
||||
|
||||
#ifdef COPY_ARRAY
|
||||
uniform sampler2DArray tex;
|
||||
#else
|
||||
uniform sampler2D tex;
|
||||
#endif
|
||||
|
||||
void main()
|
||||
{
|
||||
#ifdef COPY_ARRAY
|
||||
fragOut0 = texture(tex, vec3(fragTexCoord.xy, 0));
|
||||
#else
|
||||
fragOut0 = texture(tex, fragTexCoord.xy);
|
||||
#endif
|
||||
}
|
||||
@@ -2,8 +2,9 @@
|
||||
#include "shadows.sdr" //! #include "shadows.sdr"
|
||||
#include "lighting.sdr" //! #include "lighting.sdr"
|
||||
#include "gamma.sdr" //! #include "gamma.sdr"
|
||||
#include "model_shader_flags.h"
|
||||
|
||||
#conditional_include +"LARGE_SHADER" "main_large.sdr"
|
||||
#conditional_include -"LARGE_SHADER" "main_small.sdr"
|
||||
|
||||
#define MAX_LIGHTS 8
|
||||
#define LT_DIRECTIONAL 0
|
||||
@@ -96,32 +97,61 @@ layout (std140) uniform modelData {
|
||||
};
|
||||
|
||||
in VertexOutput {
|
||||
#prereplace IF_FLAG_COMPILED MODEL_SDR_FLAG_ENV
|
||||
vec3 envReflect;
|
||||
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_ENV
|
||||
|
||||
mat3 tangentMatrix;
|
||||
|
||||
#prereplace IF_FLAG_COMPILED MODEL_SDR_FLAG_FOG
|
||||
float fogDist;
|
||||
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_FOG
|
||||
|
||||
vec4 position;
|
||||
vec3 normal;
|
||||
vec4 texCoord;
|
||||
|
||||
#prereplace IF_FLAG_COMPILED MODEL_SDR_FLAG_SHADOWS
|
||||
vec4 shadowUV[4];
|
||||
vec4 shadowPos;
|
||||
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_SHADOWS
|
||||
} vertIn;
|
||||
|
||||
#prereplace IF_FLAG_COMPILED MODEL_SDR_FLAG_DIFFUSE
|
||||
uniform sampler2DArray sBasemap;
|
||||
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_DIFFUSE
|
||||
#prereplace IF_FLAG_COMPILED MODEL_SDR_FLAG_GLOW
|
||||
uniform sampler2DArray sGlowmap;
|
||||
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_GLOW
|
||||
#prereplace IF_FLAG_COMPILED MODEL_SDR_FLAG_SPEC
|
||||
uniform sampler2DArray sSpecmap;
|
||||
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_SPEC
|
||||
#prereplace IF_FLAG_COMPILED MODEL_SDR_FLAG_ENV
|
||||
uniform samplerCube sEnvmap;
|
||||
uniform samplerCube sIrrmap;
|
||||
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_ENV
|
||||
#prereplace IF_FLAG_COMPILED MODEL_SDR_FLAG_NORMAL
|
||||
uniform sampler2DArray sNormalmap;
|
||||
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_NORMAL
|
||||
#prereplace IF_FLAG_COMPILED MODEL_SDR_FLAG_AMBIENT
|
||||
uniform sampler2DArray sAmbientmap;
|
||||
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_AMBIENT
|
||||
uniform sampler2D sFramebuffer;
|
||||
#prereplace IF_FLAG_COMPILED MODEL_SDR_FLAG_MISC
|
||||
uniform sampler2DArray sMiscmap;
|
||||
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_MISC
|
||||
#prereplace IF_FLAG_COMPILED MODEL_SDR_FLAG_SHADOWS
|
||||
uniform sampler2DArray shadow_map;
|
||||
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_SHADOWS
|
||||
|
||||
out vec4 fragOut0;
|
||||
|
||||
#ifndef MODEL_SDR_FLAG_SHADOW_MAP
|
||||
out vec4 fragOut1;
|
||||
out vec4 fragOut2;
|
||||
out vec4 fragOut3;
|
||||
out vec4 fragOut4;
|
||||
#endif
|
||||
|
||||
vec3 FresnelLazarovEnv(vec3 specColor, vec3 view, vec3 normal, float gloss)
|
||||
{
|
||||
@@ -182,13 +212,12 @@ vec3 CalculateLighting(vec3 normal, vec3 diffuseMaterial, vec3 specularMaterial,
|
||||
|
||||
void main()
|
||||
{
|
||||
#ifdef FLAG_SHADOW_MAP
|
||||
#ifdef MODEL_SDR_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);
|
||||
if (true) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
return;
|
||||
#else
|
||||
vec3 eyeDir = vec3(normalize(-vertIn.position).xyz);
|
||||
vec2 texCoord = vertIn.texCoord.xy;
|
||||
|
||||
@@ -203,13 +232,13 @@ void main()
|
||||
vec3 unitNormal = normalize(vertIn.normal);
|
||||
vec3 normal = unitNormal;
|
||||
|
||||
if (FLAG_ACTIVE(MODEL_SDR_FLAG_AMBIENT)) {
|
||||
#prereplace IF_FLAG MODEL_SDR_FLAG_AMBIENT
|
||||
// red channel is ambient occlusion factor which only affects ambient lighting.
|
||||
// green is cavity occlusion factor which only affects diffuse and specular lighting.
|
||||
aoFactors = texture(sAmbientmap, vec3(texCoord, float(sAmbientmapIndex))).xy;
|
||||
}
|
||||
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_AMBIENT
|
||||
|
||||
if (FLAG_ACTIVE(MODEL_SDR_FLAG_NORMAL)) {
|
||||
#prereplace IF_FLAG MODEL_SDR_FLAG_NORMAL
|
||||
// Normal map - convert from DXT5nm
|
||||
vec2 normalSample;
|
||||
normal.rg = normalSample = (texture(sNormalmap, vec3(texCoord, float(sNormalmapIndex))).ag * 2.0) - 1.0;
|
||||
@@ -221,7 +250,7 @@ void main()
|
||||
normal /= norm;
|
||||
else
|
||||
normal = unitNormal;
|
||||
}
|
||||
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_NORMAL
|
||||
|
||||
vec2 distort = vec2(0.0, 0.0);
|
||||
|
||||
@@ -229,26 +258,26 @@ void main()
|
||||
distort = vec2(cos(vertIn.position.x*vertIn.position.w*0.005+anim_timer*20.0)*sin(vertIn.position.y*vertIn.position.w*0.005),sin(vertIn.position.x*vertIn.position.w*0.005+anim_timer*20.0)*cos(vertIn.position.y*vertIn.position.w*0.005))*0.03;
|
||||
}
|
||||
|
||||
if (FLAG_ACTIVE(MODEL_SDR_FLAG_DIFFUSE)) {
|
||||
#prereplace IF_FLAG MODEL_SDR_FLAG_DIFFUSE
|
||||
vec2 diffuseTexCoord = texCoord;
|
||||
if (effect_num == 2) {
|
||||
diffuseTexCoord = texCoord + distort*(1.0-anim_timer);
|
||||
}
|
||||
baseColor = texture(sBasemap, vec3(diffuseTexCoord, float(sBasemapIndex)));
|
||||
|
||||
if (FLAG_ACTIVE(MODEL_SDR_FLAG_HDR)) {
|
||||
#prereplace IF_FLAG MODEL_SDR_FLAG_HDR
|
||||
baseColor.rgb = srgb_to_linear(baseColor.rgb);
|
||||
}
|
||||
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_HDR
|
||||
|
||||
if (FLAG_ACTIVE(MODEL_SDR_FLAG_ALPHA_MULT)) {
|
||||
#prereplace IF_FLAG MODEL_SDR_FLAG_ALPHA_MULT
|
||||
baseColor.a *= alphaMult;
|
||||
}
|
||||
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_ALPHA_MULT
|
||||
|
||||
if ( blend_alpha == 0 && baseColor.a < 0.95 ) discard; // if alpha blending is not on, discard transparent pixels
|
||||
// premultiply alpha if blend_alpha is 1. assume that our blend function is srcColor + (1-Alpha)*destColor.
|
||||
// if blend_alpha is 2, assume blend func is additive and don't modify color
|
||||
if(blend_alpha == 1) baseColor.rgb = baseColor.rgb * baseColor.a;
|
||||
}
|
||||
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_DIFFUSE
|
||||
|
||||
// Anti-glint "trick" based on Valve's "Advanced VR Rendering" talk at GDC2015:
|
||||
// http://media.steampowered.com/apps/valve/2015/Alex_Vlachos_Advanced_VR_Rendering_GDC2015.pdf Page 43
|
||||
@@ -261,18 +290,22 @@ void main()
|
||||
// Now that we have a base color and min gloss value, compute the spec color
|
||||
vec4 specColor = vec4(baseColor.rgb * SPEC_FACTOR_NO_SPEC_MAP, glossData);
|
||||
|
||||
if (FLAG_ACTIVE(MODEL_SDR_FLAG_SPEC)) {
|
||||
#prereplace IF_FLAG MODEL_SDR_FLAG_SPEC
|
||||
specColor = texture(sSpecmap, vec3(texCoord, float(sSpecmapIndex)));
|
||||
#prereplace IF_FLAG MODEL_SDR_FLAG_ALPHA_MULT
|
||||
specColor *= alphaMult;
|
||||
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_ALPHA_MULT
|
||||
|
||||
if(alphaGloss) glossData = specColor.a;
|
||||
if(gammaSpec) {
|
||||
specColor.rgb = max(specColor.rgb, vec3(0.03f)); // hardcoded minimum specular value. read John Hable's blog post titled 'Everything Is Shiny'.
|
||||
fresnelFactor = 1.0;
|
||||
}
|
||||
|
||||
if (FLAG_ACTIVE(MODEL_SDR_FLAG_HDR)) {
|
||||
#prereplace IF_FLAG MODEL_SDR_FLAG_HDR
|
||||
specColor.rgb = srgb_to_linear(specColor.rgb);
|
||||
}
|
||||
}
|
||||
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_HDR
|
||||
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_SPEC
|
||||
|
||||
baseColor.rgb *= aoFactors.y;
|
||||
specColor.rgb *= aoFactors.y;
|
||||
@@ -280,8 +313,8 @@ void main()
|
||||
vec4 teamMask = vec4(0.0);
|
||||
vec3 team_color_glow = vec3(0.0);
|
||||
|
||||
if (FLAG_ACTIVE(MODEL_SDR_FLAG_MISC)) {
|
||||
if (FLAG_ACTIVE(MODEL_SDR_FLAG_TEAMCOLOR)) {
|
||||
#prereplace IF_FLAG MODEL_SDR_FLAG_MISC
|
||||
#prereplace IF_FLAG MODEL_SDR_FLAG_TEAMCOLOR
|
||||
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
|
||||
@@ -291,52 +324,52 @@ void main()
|
||||
vec3 team_color = base_color * teamMask.x + stripe_color * teamMask.y + color_offset;
|
||||
team_color_glow = (base_color * teamMask.b) + (stripe_color * teamMask.a);
|
||||
|
||||
if (FLAG_ACTIVE(MODEL_SDR_FLAG_HDR)) {
|
||||
#prereplace IF_FLAG MODEL_SDR_FLAG_HDR
|
||||
baseColor.rgb = linear_to_srgb(baseColor.rgb);
|
||||
specColor.rgb = linear_to_srgb(specColor.rgb);
|
||||
}
|
||||
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_HDR
|
||||
|
||||
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));
|
||||
|
||||
if (FLAG_ACTIVE(MODEL_SDR_FLAG_HDR)) {
|
||||
#prereplace IF_FLAG MODEL_SDR_FLAG_HDR
|
||||
baseColor.rgb = srgb_to_linear(baseColor.rgb);
|
||||
specColor.rgb = srgb_to_linear(specColor.rgb);
|
||||
}
|
||||
}
|
||||
}
|
||||
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_HDR
|
||||
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_TEAMCOLOR
|
||||
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_MISC
|
||||
|
||||
// Lights aren't applied when we are rendering to the G-buffers since that gets handled later
|
||||
if (FLAG_ACTIVE(MODEL_SDR_FLAG_DEFERRED)) {
|
||||
if (FLAG_ACTIVE(MODEL_SDR_FLAG_LIGHT)) {
|
||||
#prereplace IF_FLAG MODEL_SDR_FLAG_DEFERRED
|
||||
#prereplace IF_FLAG MODEL_SDR_FLAG_LIGHT
|
||||
// Ambient lighting still needs to be done since that counts as an "emissive" color
|
||||
vec3 lightAmbient = (emissionFactor + ambientFactor * ambientFactor) * aoFactors.x; // ambientFactor^2 due to legacy OpenGL compatibility behavior
|
||||
emissiveColor.rgb += baseColor.rgb * lightAmbient;
|
||||
} else {
|
||||
if (FLAG_ACTIVE(MODEL_SDR_FLAG_SPEC)) {
|
||||
#prereplace ELSE_FLAG //MODEL_SDR_FLAG_LIGHT
|
||||
#prereplace IF_FLAG MODEL_SDR_FLAG_SPEC
|
||||
baseColor.rgb += pow(1.0 - clamp(dot(eyeDir, normal), 0.0, 1.0), 5.0 * clamp(glossData, 0.01, 1.0)) * specColor.rgb;
|
||||
}
|
||||
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_SPEC
|
||||
// If there is no lighting then we copy the color data so far into the
|
||||
emissiveColor.rgb += baseColor.rgb;
|
||||
}
|
||||
} else {
|
||||
if (FLAG_ACTIVE(MODEL_SDR_FLAG_LIGHT)) {
|
||||
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_LIGHT
|
||||
#prereplace ELSE_FLAG //MODEL_SDR_FLAG_DEFERRED
|
||||
#prereplace IF_FLAG MODEL_SDR_FLAG_LIGHT
|
||||
float shadow = 1.0;
|
||||
if (FLAG_ACTIVE(MODEL_SDR_FLAG_SHADOWS)) {
|
||||
#prereplace IF_FLAG MODEL_SDR_FLAG_SHADOWS
|
||||
shadow = getShadowValue(shadow_map, -vertIn.position.z, vertIn.shadowPos.z, vertIn.shadowUV, fardist, middist, neardist, veryneardist);
|
||||
}
|
||||
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_SHADOWS
|
||||
baseColor.rgb = CalculateLighting(normal, baseColor.rgb, specColor.rgb, glossData, fresnelFactor, shadow, aoFactors.x);
|
||||
} else {
|
||||
if (FLAG_ACTIVE(MODEL_SDR_FLAG_SPEC)) {
|
||||
#prereplace ELSE_FLAG //MODEL_SDR_FLAG_LIGHT
|
||||
#prereplace IF_FLAG MODEL_SDR_FLAG_SPEC
|
||||
baseColor.rgb += pow(1.0 - clamp(dot(eyeDir, normal), 0.0, 1.0), 5.0 * clamp(glossData, 0.01, 1.0)) * specColor.rgb;
|
||||
}
|
||||
}
|
||||
}
|
||||
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_SPEC
|
||||
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_LIGHT
|
||||
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_DEFERRED
|
||||
|
||||
if (FLAG_ACTIVE(MODEL_SDR_FLAG_ENV)) {
|
||||
if (FLAG_ACTIVE(MODEL_SDR_FLAG_LIGHT)) {
|
||||
#prereplace IF_FLAG MODEL_SDR_FLAG_ENV
|
||||
#prereplace IF_FLAG MODEL_SDR_FLAG_LIGHT
|
||||
// Bit of a hack here, pretend we're doing blinn-phong shading and use a (modified version of) the derivation from
|
||||
// Plausible Blinn-Phong Reflection of Standard Cube MIP-Maps - McGuire et al.
|
||||
// to determine the mip bias.
|
||||
@@ -380,43 +413,48 @@ void main()
|
||||
vec3 diffEnvColor = srgb_to_linear(texture(sIrrmap, vec3(envMatrix * vec4(normal, 0.0))).rgb);
|
||||
vec3 diffEnvLighting = kD * baseColor.rgb * diffEnvColor * aoFactors.x;
|
||||
emissiveColor.rgb += (specEnvLighting + diffEnvLighting) * baseColor.a;
|
||||
}
|
||||
}
|
||||
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_LIGHT
|
||||
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_ENV
|
||||
|
||||
if (FLAG_ACTIVE(MODEL_SDR_FLAG_GLOW)) {
|
||||
#prereplace IF_FLAG MODEL_SDR_FLAG_GLOW
|
||||
vec3 glowColor = texture(sGlowmap, vec3(texCoord, float(sGlowmapIndex))).rgb;
|
||||
if (FLAG_ACTIVE(MODEL_SDR_FLAG_MISC)) {
|
||||
if (FLAG_ACTIVE(MODEL_SDR_FLAG_TEAMCOLOR)) {
|
||||
#prereplace IF_FLAG MODEL_SDR_FLAG_MISC
|
||||
#prereplace IF_FLAG MODEL_SDR_FLAG_TEAMCOLOR
|
||||
float glowColorLuminance = dot(glowColor, vec3(0.299, 0.587, 0.114));
|
||||
glowColor = team_glow_enabled ? mix(max(team_color_glow, vec3(0.0)), glowColor, clamp(glowColorLuminance - teamMask.b - teamMask.a, 0.0, 1.0)) : glowColor;
|
||||
}
|
||||
}
|
||||
if (FLAG_ACTIVE(MODEL_SDR_FLAG_HDR)) {
|
||||
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_TEAMCOLOR
|
||||
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_MISC
|
||||
#prereplace IF_FLAG MODEL_SDR_FLAG_HDR
|
||||
glowColor = srgb_to_linear(glowColor) * GLOW_MAP_SRGB_MULTIPLIER;
|
||||
}
|
||||
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_HDR
|
||||
emissiveColor.rgb += glowColor * GLOW_MAP_INTENSITY;
|
||||
}
|
||||
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_GLOW
|
||||
|
||||
if (FLAG_ACTIVE(MODEL_SDR_FLAG_FOG)) {
|
||||
#prereplace IF_FLAG MODEL_SDR_FLAG_ALPHA_MULT
|
||||
//Since this is emissive, we need to premultiply it for intensity, and apply alpha to not replace existing emissive
|
||||
emissiveColor *= alphaMult;
|
||||
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_ALPHA_MULT
|
||||
|
||||
#prereplace IF_FLAG MODEL_SDR_FLAG_FOG
|
||||
vec3 finalFogColor = fogColor.rgb;
|
||||
if (FLAG_ACTIVE(MODEL_SDR_FLAG_HDR)) {
|
||||
#prereplace IF_FLAG MODEL_SDR_FLAG_HDR
|
||||
finalFogColor = srgb_to_linear(finalFogColor);
|
||||
}
|
||||
if (FLAG_ACTIVE(MODEL_SDR_FLAG_DIFFUSE)) {
|
||||
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_HDR
|
||||
#prereplace IF_FLAG MODEL_SDR_FLAG_DIFFUSE
|
||||
if(blend_alpha == 1) finalFogColor *= baseColor.a;
|
||||
}
|
||||
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_DIFFUSE
|
||||
// This code will only be used by the forward renderer so we apply the fog effect to both the emissive and the base
|
||||
// color.
|
||||
baseColor.rgb = mix(emissiveColor.rgb + baseColor.rgb, finalFogColor, vertIn.fogDist);
|
||||
emissiveColor.rgb = vec3(0.0); // Zero the emissive color since it has already been added by the previous line
|
||||
specColor.rgb *= vertIn.fogDist;
|
||||
}
|
||||
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_FOG
|
||||
|
||||
if (FLAG_ACTIVE(MODEL_SDR_FLAG_DIFFUSE)) {
|
||||
#prereplace IF_FLAG MODEL_SDR_FLAG_DIFFUSE
|
||||
if(desaturate == 1) {
|
||||
baseColor.rgb = color.rgb * dot(vec3(1.0), baseColor.rgb) * 0.3333333;
|
||||
}
|
||||
}
|
||||
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_DIFFUSE
|
||||
|
||||
if (effect_num == 0) {
|
||||
float shinefactor = 1.0/(1.0 + pow(abs((fract(abs(texCoord.x))-anim_timer) * 1000.0), 2.0)) * 1000.0;
|
||||
@@ -425,32 +463,34 @@ void main()
|
||||
} else if (effect_num == 1) {
|
||||
float shinefactor = 1.0/(1.0 + pow(abs(vertIn.position.y-anim_timer), 2.0));
|
||||
emissiveColor.rgb += vec3(shinefactor);
|
||||
if (!(FLAG_ACTIVE(MODEL_SDR_FLAG_LIGHT))) {
|
||||
#prereplace IF_NOT_FLAG MODEL_SDR_FLAG_LIGHT
|
||||
// ATI Wireframe fix *grumble*
|
||||
baseColor.a = clamp((vertIn.position.y-anim_timer) * 10000.0,0.0,1.0);
|
||||
}
|
||||
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_LIGHT
|
||||
} else if (effect_num == 2) {
|
||||
vec2 screenPos = gl_FragCoord.xy * vec2(vpwidth,vpheight);
|
||||
baseColor.a = baseColor.a;
|
||||
float cloak_interp = (sin(vertIn.position.x*vertIn.position.w*0.005+anim_timer*20.0)*sin(vertIn.position.y*vertIn.position.w*0.005)*0.5)-0.5;
|
||||
if (FLAG_ACTIVE(MODEL_SDR_FLAG_LIGHT)) {
|
||||
#prereplace IF_FLAG MODEL_SDR_FLAG_LIGHT
|
||||
baseColor.rgb = mix(texture(sFramebuffer, screenPos + distort*anim_timer + anim_timer*0.1*normal.xy).rgb,baseColor.rgb,clamp(cloak_interp+anim_timer*2.0,0.0,1.0));
|
||||
} else {
|
||||
#prereplace ELSE_FLAG //MODEL_SDR_FLAG_LIGHT
|
||||
baseColor.rgb = mix(texture(sFramebuffer, screenPos + distort*anim_timer + anim_timer*0.1*vertIn.normal.xy).rgb,baseColor.rgb,clamp(cloak_interp+anim_timer*2.0,0.0,1.0));
|
||||
}
|
||||
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_LIGHT
|
||||
}
|
||||
|
||||
if (!(FLAG_ACTIVE(MODEL_SDR_FLAG_DEFERRED))) {
|
||||
#prereplace IF_NOT_FLAG MODEL_SDR_FLAG_DEFERRED
|
||||
// emissive colors won't be added later when we are using forward rendering so we need to do that here
|
||||
baseColor.rgb += emissiveColor.rgb;
|
||||
}
|
||||
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_DEFERRED
|
||||
|
||||
fragOut0 = baseColor;
|
||||
|
||||
if (FLAG_ACTIVE(MODEL_SDR_FLAG_DEFERRED)) {
|
||||
#prereplace IF_FLAG MODEL_SDR_FLAG_DEFERRED
|
||||
fragOut1 = vec4(vertIn.position.xyz, 1.0);
|
||||
fragOut2 = vec4(normal, glossData);
|
||||
fragOut3 = vec4(specColor.rgb, fresnelFactor);
|
||||
fragOut4 = emissiveColor;
|
||||
}
|
||||
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_DEFERRED
|
||||
|
||||
#endif
|
||||
}
|
||||
@@ -1,17 +1,18 @@
|
||||
#extension GL_ARB_gpu_shader5: enable
|
||||
|
||||
#include "model_shader_flags.h"
|
||||
#conditional_include +"LARGE_SHADER" "main_large.sdr"
|
||||
#conditional_include -"LARGE_SHADER" "main_small.sdr"
|
||||
|
||||
#ifdef FLAG_THICK_OUTLINE
|
||||
#ifdef MODEL_SDR_FLAG_THICK_OUTLINES
|
||||
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;
|
||||
#elif defined(FLAG_SHADOW_MAP)
|
||||
#elif defined(MODEL_SDR_FLAG_SHADOW_MAP)
|
||||
layout (triangles) in;
|
||||
layout (triangle_strip, max_vertices = 3) out;
|
||||
#endif
|
||||
|
||||
#ifdef FLAG_SHADOW_MAP
|
||||
#ifdef MODEL_SDR_FLAG_SHADOW_MAP
|
||||
#ifdef GL_ARB_gpu_shader5
|
||||
layout(invocations = 4) in;
|
||||
#endif
|
||||
@@ -102,11 +103,17 @@ layout (std140) uniform modelData {
|
||||
};
|
||||
|
||||
in VertexOutput {
|
||||
#prereplace IF_FLAG_COMPILED MODEL_SDR_FLAG_ENV
|
||||
vec3 envReflect;
|
||||
mat3 tangentMatrix;
|
||||
float fogDist;
|
||||
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_ENV
|
||||
|
||||
#ifdef FLAG_SHADOW_MAP
|
||||
mat3 tangentMatrix;
|
||||
|
||||
#prereplace IF_FLAG_COMPILED MODEL_SDR_FLAG_FOG
|
||||
float fogDist;
|
||||
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_FOG
|
||||
|
||||
#ifdef MODEL_SDR_FLAG_SHADOW_MAP
|
||||
#if !defined(GL_ARB_gpu_shader5)
|
||||
float instance;
|
||||
#endif
|
||||
@@ -116,22 +123,35 @@ in VertexOutput {
|
||||
#endif
|
||||
vec3 normal;
|
||||
vec4 texCoord;
|
||||
|
||||
#prereplace IF_FLAG_COMPILED MODEL_SDR_FLAG_SHADOWS
|
||||
vec4 shadowUV[4];
|
||||
vec4 shadowPos;
|
||||
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_SHADOWS
|
||||
} vertIn[];
|
||||
|
||||
out VertexOutput {
|
||||
#prereplace IF_FLAG_COMPILED MODEL_SDR_FLAG_ENV
|
||||
vec3 envReflect;
|
||||
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_ENV
|
||||
|
||||
mat3 tangentMatrix;
|
||||
|
||||
#prereplace IF_FLAG_COMPILED MODEL_SDR_FLAG_FOG
|
||||
float fogDist;
|
||||
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_FOG
|
||||
|
||||
vec4 position;
|
||||
vec3 normal;
|
||||
vec4 texCoord;
|
||||
|
||||
#prereplace IF_FLAG_COMPILED MODEL_SDR_FLAG_SHADOWS
|
||||
vec4 shadowUV[4];
|
||||
vec4 shadowPos;
|
||||
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_SHADOWS
|
||||
} vertOut;
|
||||
|
||||
#ifdef FLAG_SHADOW_MAP
|
||||
#ifdef MODEL_SDR_FLAG_SHADOW_MAP
|
||||
void main(void)
|
||||
{
|
||||
#ifdef GL_ARB_gpu_shader5
|
||||
@@ -141,16 +161,17 @@ out VertexOutput {
|
||||
#endif
|
||||
for(int vert = 0; vert < gl_in.length(); vert++)
|
||||
{
|
||||
if (FLAG_ACTIVE(MODEL_SDR_FLAG_TRANSFORM)) {
|
||||
#prereplace IF_FLAG MODEL_SDR_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 {
|
||||
#prereplace ELSE_FLAG //MODEL_SDR_FLAG_TRANSFORM
|
||||
gl_Position = shadow_proj_matrix[instanceID] * gl_in[vert].gl_Position;
|
||||
}
|
||||
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_TRANSFORM
|
||||
|
||||
if(gl_Position.z < -1.0)
|
||||
gl_Position.z = -1.0;
|
||||
|
||||
@@ -160,22 +181,26 @@ out VertexOutput {
|
||||
|
||||
gl_Layer = instanceID;
|
||||
|
||||
if (FLAG_ACTIVE(MODEL_SDR_FLAG_ENV)) {
|
||||
#prereplace IF_FLAG MODEL_SDR_FLAG_ENV
|
||||
vertOut.envReflect = vertIn[vert].envReflect;
|
||||
}
|
||||
if (FLAG_ACTIVE(MODEL_SDR_FLAG_NORMAL)) {
|
||||
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_ENV
|
||||
|
||||
#prereplace IF_FLAG MODEL_SDR_FLAG_NORMAL
|
||||
vertOut.tangentMatrix = vertIn[vert].tangentMatrix;
|
||||
}
|
||||
if (FLAG_ACTIVE(MODEL_SDR_FLAG_FOG)) {
|
||||
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_NORMAL
|
||||
|
||||
#prereplace IF_FLAG MODEL_SDR_FLAG_FOG
|
||||
vertOut.fogDist = vertIn[vert].fogDist;
|
||||
}
|
||||
if (FLAG_ACTIVE(MODEL_SDR_FLAG_SHADOWS)) {
|
||||
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_FOG
|
||||
|
||||
#prereplace IF_FLAG MODEL_SDR_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;
|
||||
}
|
||||
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_SHADOWS
|
||||
|
||||
if (use_clip_plane) {
|
||||
gl_ClipDistance[0] = gl_in[vert].gl_ClipDistance[0];
|
||||
}
|
||||
@@ -183,7 +208,7 @@ out VertexOutput {
|
||||
}
|
||||
EndPrimitive();
|
||||
}
|
||||
#elif defined(FLAG_THICK_OUTLINE)
|
||||
#elif defined(MODEL_SDR_FLAG_THICK_OUTLINES)
|
||||
const vec2 pixelOffsetDir[4] = vec2[](
|
||||
vec2(0.0, 1.0),
|
||||
vec2(1.0, 1.0),
|
||||
@@ -214,22 +239,26 @@ out VertexOutput {
|
||||
vertOut.normal = vertIn[vert].normal;
|
||||
vertOut.texCoord = vertIn[vert].texCoord;
|
||||
|
||||
if (FLAG_ACTIVE(MODEL_SDR_FLAG_ENV)) {
|
||||
vertOut.envReflect = vertIn[vert].envReflect;
|
||||
}
|
||||
if (FLAG_ACTIVE(MODEL_SDR_FLAG_NORMAL)) {
|
||||
vertOut.tangentMatrix = vertIn[vert].tangentMatrix;
|
||||
}
|
||||
if (FLAG_ACTIVE(MODEL_SDR_FLAG_FOG)) {
|
||||
vertOut.fogDist = vertIn[vert].fogDist;
|
||||
}
|
||||
if (FLAG_ACTIVE(MODEL_SDR_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;
|
||||
}
|
||||
#prereplace IF_FLAG MODEL_SDR_FLAG_ENV
|
||||
vertOut.envReflect = vertIn[vert].envReflect;
|
||||
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_ENV
|
||||
|
||||
#prereplace IF_FLAG MODEL_SDR_FLAG_NORMAL
|
||||
vertOut.tangentMatrix = vertIn[vert].tangentMatrix;
|
||||
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_NORMAL
|
||||
|
||||
#prereplace IF_FLAG MODEL_SDR_FLAG_FOG
|
||||
vertOut.fogDist = vertIn[vert].fogDist;
|
||||
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_FOG
|
||||
|
||||
#prereplace IF_FLAG MODEL_SDR_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;
|
||||
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_SHADOWS
|
||||
|
||||
if (use_clip_plane) {
|
||||
gl_ClipDistance[0] = gl_in[vert].gl_ClipDistance[0];
|
||||
}
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
#extension GL_ARB_gpu_shader5: enable
|
||||
|
||||
#include "shadows.sdr"
|
||||
#include "model_shader_flags.h"
|
||||
|
||||
#conditional_include +"LARGE_SHADER" "main_large.sdr"
|
||||
#conditional_include -"LARGE_SHADER" "main_small.sdr"
|
||||
|
||||
in vec4 vertPosition;
|
||||
in vec4 vertTexCoord;
|
||||
@@ -95,13 +97,22 @@ layout (std140) uniform modelData {
|
||||
int flags;
|
||||
};
|
||||
|
||||
#prereplace IF_FLAG_COMPILED MODEL_SDR_FLAG_TRANSFORM
|
||||
uniform samplerBuffer transform_tex;
|
||||
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_TRANSFORM
|
||||
|
||||
out VertexOutput {
|
||||
#prereplace IF_FLAG_COMPILED MODEL_SDR_FLAG_ENV
|
||||
vec3 envReflect;
|
||||
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_ENV
|
||||
|
||||
mat3 tangentMatrix;
|
||||
|
||||
#prereplace IF_FLAG_COMPILED MODEL_SDR_FLAG_FOG
|
||||
float fogDist;
|
||||
#ifdef FLAG_SHADOW_MAP
|
||||
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_FOG
|
||||
|
||||
#ifdef MODEL_SDR_FLAG_SHADOW_MAP
|
||||
#if !defined(GL_ARB_gpu_shader5)
|
||||
float instance;
|
||||
#endif
|
||||
@@ -113,11 +124,15 @@ out VertexOutput {
|
||||
#endif
|
||||
vec3 normal;
|
||||
vec4 texCoord;
|
||||
|
||||
#prereplace IF_FLAG_COMPILED MODEL_SDR_FLAG_SHADOWS
|
||||
vec4 shadowUV[4];
|
||||
vec4 shadowPos;
|
||||
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_SHADOWS
|
||||
} vertOut;
|
||||
|
||||
#define TEXELS_PER_MATRIX 4
|
||||
#prereplace IF_FLAG_COMPILED MODEL_SDR_FLAG_TRANSFORM
|
||||
void getModelTransform(inout mat4 transform, out bool invisible, int id, int matrix_offset)
|
||||
{
|
||||
transform[0] = texelFetch(transform_tex, (matrix_offset + id) * TEXELS_PER_MATRIX);
|
||||
@@ -127,6 +142,7 @@ void getModelTransform(inout mat4 transform, out bool invisible, int id, int mat
|
||||
invisible = transform[3].w >= 0.9;
|
||||
transform[3].w = 1.0;
|
||||
}
|
||||
#prereplace ENDIF_FLAG_COMPILED MODEL_SDR_FLAG_TRANSFORM
|
||||
|
||||
void main()
|
||||
{
|
||||
@@ -137,20 +153,21 @@ void main()
|
||||
mat4 scale = mat4(1.0);
|
||||
bool clipModel = false;
|
||||
|
||||
if (FLAG_ACTIVE(MODEL_SDR_FLAG_TRANSFORM)) {
|
||||
#prereplace IF_FLAG MODEL_SDR_FLAG_TRANSFORM
|
||||
getModelTransform(orient, clipModel, int(vertModelID), buffer_matrix_offset);
|
||||
}
|
||||
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_TRANSFORM
|
||||
|
||||
texCoord = textureMatrix * vertTexCoord;
|
||||
vec4 vertex = vertPosition;
|
||||
if (FLAG_ACTIVE(MODEL_SDR_FLAG_THRUSTER)) {
|
||||
#prereplace IF_FLAG MODEL_SDR_FLAG_THRUSTER
|
||||
if(vertex.z < -1.5) {
|
||||
vertex.z *= thruster_scale;
|
||||
}
|
||||
}
|
||||
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_THRUSTER
|
||||
// Transform the normal into eye space and normalize the result.
|
||||
normal = normalize(mat3(modelViewMatrix) * mat3(orient) * vertNormal);
|
||||
position = modelViewMatrix * orient * vertex;
|
||||
#ifdef FLAG_SHADOW_MAP
|
||||
#ifdef MODEL_SDR_FLAG_SHADOW_MAP
|
||||
gl_Position = position;
|
||||
#if !defined(GL_ARB_gpu_shader5)
|
||||
#ifdef APPLE
|
||||
@@ -162,37 +179,39 @@ void main()
|
||||
#else
|
||||
gl_Position = projMatrix * position;
|
||||
#endif
|
||||
if (FLAG_ACTIVE(MODEL_SDR_FLAG_SHADOWS)) {
|
||||
#prereplace IF_FLAG MODEL_SDR_FLAG_SHADOWS
|
||||
vec4 shadowPos = shadow_mv_matrix * modelMatrix * orient * vertPosition;
|
||||
vertOut.shadowPos = shadow_mv_matrix * modelMatrix * orient * vertPosition;
|
||||
vertOut.shadowUV[0] = transformToShadowMap(shadow_proj_matrix[0], 0, shadowPos);
|
||||
vertOut.shadowUV[1] = transformToShadowMap(shadow_proj_matrix[1], 1, shadowPos);
|
||||
vertOut.shadowUV[2] = transformToShadowMap(shadow_proj_matrix[2], 2, shadowPos);
|
||||
vertOut.shadowUV[3] = transformToShadowMap(shadow_proj_matrix[3], 3, shadowPos);
|
||||
}
|
||||
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_SHADOWS
|
||||
|
||||
// Setup stuff for normal maps and envmaps
|
||||
vec3 t = normalize(mat3(modelViewMatrix) * mat3(orient) * vertTangent.xyz);
|
||||
vec3 b = cross(normal, t) * vertTangent.w;
|
||||
vertOut.tangentMatrix = mat3(t, b, normal);
|
||||
|
||||
if (FLAG_ACTIVE(MODEL_SDR_FLAG_ENV)) {
|
||||
#prereplace IF_FLAG MODEL_SDR_FLAG_ENV
|
||||
// Environment mapping reflection vector.
|
||||
vec3 envReflect = reflect(normalize(position.xyz), normal);
|
||||
vertOut.envReflect = vec3(envMatrix * vec4(envReflect, 0.0));
|
||||
}
|
||||
if (FLAG_ACTIVE(MODEL_SDR_FLAG_FOG)) {
|
||||
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_ENV
|
||||
|
||||
#prereplace IF_FLAG MODEL_SDR_FLAG_FOG
|
||||
vertOut.fogDist = clamp((gl_Position.z - fogStart) * 0.75 * fogScale, 0.0, 1.0);
|
||||
}
|
||||
if (FLAG_ACTIVE(MODEL_SDR_FLAG_TRANSFORM)) {
|
||||
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_FOG
|
||||
|
||||
#prereplace IF_FLAG MODEL_SDR_FLAG_TRANSFORM
|
||||
if (clipModel) {
|
||||
// Clip this model by moving all vertices outside the clip volume
|
||||
gl_Position = vec4(vec3(-2.0), 1.0);
|
||||
}
|
||||
#ifdef FLAG_SHADOW_MAP
|
||||
#ifdef MODEL_SDR_FLAG_SHADOW_MAP
|
||||
vertOut.clipModel = clipModel ? 1.0 : 0.0;
|
||||
#endif
|
||||
}
|
||||
#prereplace ENDIF_FLAG //MODEL_SDR_FLAG_TRANSFORM
|
||||
|
||||
if(use_clip_plane) {
|
||||
gl_ClipDistance[0] = dot(clip_equation, modelMatrix * orient * vertex);
|
||||
@@ -200,7 +219,7 @@ void main()
|
||||
gl_ClipDistance[0] = 1.0;
|
||||
}
|
||||
|
||||
#ifndef FLAG_SHADOW_MAP
|
||||
#ifndef MODEL_SDR_FLAG_SHADOW_MAP
|
||||
vertOut.position = position;
|
||||
vertOut.normal = normal;
|
||||
vertOut.texCoord = texCoord;
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
#predefine IF_FLAG if ((flags & %s) != 0) {
|
||||
#predefine IF_NOT_FLAG if ((flags & %s) == 0) {
|
||||
#predefine ELSE_FLAG } else { %s
|
||||
#predefine ENDIF_FLAG } %s
|
||||
#predefine IF_FLAG_COMPILED //if true %s
|
||||
#predefine ENDIF_FLAG_COMPILED //endif true %s
|
||||
|
||||
#define MODEL_SDR_FLAG_MODE_GLSL 1
|
||||
#include "model_shader_flags.h"
|
||||
@@ -0,0 +1,6 @@
|
||||
#predefine IF_FLAG #ifdef %s
|
||||
#predefine IF_NOT_FLAG #ifndef %s
|
||||
#predefine ELSE_FLAG #else //%s
|
||||
#predefine ENDIF_FLAG #endif //%s
|
||||
#predefine IF_FLAG_COMPILED #ifdef %s
|
||||
#predefine ENDIF_FLAG_COMPILED #endif //%s
|
||||
@@ -1,19 +1,35 @@
|
||||
#define MODEL_SDR_FLAG_LIGHT (1 << 0)
|
||||
#define MODEL_SDR_FLAG_DEFERRED (1 << 1)
|
||||
#define MODEL_SDR_FLAG_HDR (1 << 2)
|
||||
#define MODEL_SDR_FLAG_DIFFUSE (1 << 3)
|
||||
#define MODEL_SDR_FLAG_GLOW (1 << 4)
|
||||
#define MODEL_SDR_FLAG_SPEC (1 << 5)
|
||||
#define MODEL_SDR_FLAG_ENV (1 << 6)
|
||||
#define MODEL_SDR_FLAG_NORMAL (1 << 7)
|
||||
#define MODEL_SDR_FLAG_AMBIENT (1 << 8)
|
||||
#define MODEL_SDR_FLAG_MISC (1 << 9)
|
||||
#define MODEL_SDR_FLAG_TEAMCOLOR (1 << 10)
|
||||
#define MODEL_SDR_FLAG_FOG (1 << 11)
|
||||
#define MODEL_SDR_FLAG_TRANSFORM (1 << 12)
|
||||
#define MODEL_SDR_FLAG_SHADOWS (1 << 13)
|
||||
#define MODEL_SDR_FLAG_THRUSTER (1 << 14)
|
||||
#define MODEL_SDR_FLAG_ALPHA_MULT (1 << 15)
|
||||
#ifdef MODEL_SDR_FLAG_MODE_CPP
|
||||
#define SDR_FLAG(name, value, geoshader) constexpr int name = value;
|
||||
#elif defined MODEL_SDR_FLAG_MODE_CPP_ARRAY
|
||||
#define SDR_FLAG(name, value, geoshader) {SDR_TYPE_MODEL, geoshader, value, #name, {}, #name},
|
||||
#elif defined MODEL_SDR_FLAG_MODE_GLSL
|
||||
#define SDR_FLAG(name, value, geoshader) const int name = value;
|
||||
#else
|
||||
#error Make sure to properly define the usage mode for this file!
|
||||
#endif
|
||||
|
||||
SDR_FLAG(MODEL_SDR_FLAG_LIGHT , (1 << 0) , false)
|
||||
SDR_FLAG(MODEL_SDR_FLAG_DEFERRED , (1 << 1) , false)
|
||||
SDR_FLAG(MODEL_SDR_FLAG_HDR , (1 << 2) , false)
|
||||
SDR_FLAG(MODEL_SDR_FLAG_DIFFUSE , (1 << 3) , false)
|
||||
SDR_FLAG(MODEL_SDR_FLAG_GLOW , (1 << 4) , false)
|
||||
SDR_FLAG(MODEL_SDR_FLAG_SPEC , (1 << 5) , false)
|
||||
SDR_FLAG(MODEL_SDR_FLAG_ENV , (1 << 6) , false)
|
||||
SDR_FLAG(MODEL_SDR_FLAG_NORMAL , (1 << 7) , false)
|
||||
SDR_FLAG(MODEL_SDR_FLAG_AMBIENT , (1 << 8) , false)
|
||||
SDR_FLAG(MODEL_SDR_FLAG_MISC , (1 << 9) , false)
|
||||
SDR_FLAG(MODEL_SDR_FLAG_TEAMCOLOR , (1 << 10), false)
|
||||
SDR_FLAG(MODEL_SDR_FLAG_FOG , (1 << 11), false)
|
||||
SDR_FLAG(MODEL_SDR_FLAG_TRANSFORM , (1 << 12), false)
|
||||
SDR_FLAG(MODEL_SDR_FLAG_SHADOWS , (1 << 13), false)
|
||||
SDR_FLAG(MODEL_SDR_FLAG_THRUSTER , (1 << 14), false)
|
||||
SDR_FLAG(MODEL_SDR_FLAG_ALPHA_MULT , (1 << 15), false)
|
||||
|
||||
#define FLAG_ACTIVE(flag) (flags & flag) != 0
|
||||
#ifndef MODEL_SDR_FLAG_MODE_GLSL
|
||||
//The following ones are used ONLY as compile-time flags, but they still need to be defined here to ensure no conflict occurs
|
||||
//But since these are checked with ifdefs even for the large shader, they must never be available in GLSL mode
|
||||
|
||||
SDR_FLAG(MODEL_SDR_FLAG_SHADOW_MAP , (1 << 16), true)
|
||||
SDR_FLAG(MODEL_SDR_FLAG_THICK_OUTLINES, (1 << 17), true)
|
||||
|
||||
#endif
|
||||
@@ -5,7 +5,6 @@ out vec4 fragOut2;
|
||||
out vec4 fragOut3;
|
||||
out vec4 fragOut4;
|
||||
out vec4 fragOut5;
|
||||
out float gl_FragDepth;
|
||||
|
||||
uniform sampler2DMS texColor;
|
||||
uniform sampler2DMS texPos;
|
||||
@@ -175,7 +174,8 @@ void main()
|
||||
for(int i = 0; i < samples; i++) {
|
||||
vec4 localPos = texelFetch(texPos, texel, i);
|
||||
//Calculate local weight from distance Voxel, but if the distance is 0 (i.e. no model at all), set weight to 1 to allow stuff like background emissive
|
||||
float localWeight = max(step(-0.001, dist),
|
||||
//However, if the median distance is 0, only deal with current texel if it's local distance is 0 as well
|
||||
float localWeight = max(step(-0.001, dist) * step(-0.001, localPos.z),
|
||||
smoothstep(dist + dist * texelWidthFactor * (voxelDepth + voxelDepthFalloff), dist + dist * texelWidthFactor * voxelDepth, localPos.z) *
|
||||
smoothstep(dist - dist * texelWidthFactor * voxelDepth, dist + dist * texelWidthFactor * (voxelDepth + voxelDepthFalloff), localPos.z)
|
||||
);
|
||||
@@ -191,7 +191,7 @@ void main()
|
||||
|
||||
fragOut0 = color / weight;
|
||||
fragOut1 = pos / weight;
|
||||
fragOut2 = normalize(normal);
|
||||
fragOut2 = vec4(normalize(normal.xyz), normal.a / weight);
|
||||
fragOut3 = specular / weight;
|
||||
fragOut4 = emissive / weight;
|
||||
gl_FragDepth = depth / weight;
|
||||
|
||||
@@ -37,7 +37,6 @@ vec3 Uncharted2ToneMapping(vec3 hdr_color) // John Hable's filmic
|
||||
hdr_color = ((hdr_color * (A * hdr_color + C * B) + D * E) / (hdr_color * (A * hdr_color + B) + D * F)) - E / F;
|
||||
float white = ((W * (A * W + C * B) + D * E) / (W * (A * W + B) + D * F)) - E / F;
|
||||
hdr_color /= white;
|
||||
hdr_color = linear_to_srgb(hdr_color); // return from linear color space to SRGB color space
|
||||
|
||||
return hdr_color;
|
||||
}
|
||||
@@ -65,7 +64,6 @@ vec3 aces(vec3 hdr_color)
|
||||
hdr_color = aces_input * hdr_color;
|
||||
hdr_color = rtt_and_odt_fit(hdr_color);
|
||||
hdr_color = aces_output * hdr_color;
|
||||
hdr_color = linear_to_srgb(hdr_color);
|
||||
return hdr_color;
|
||||
}
|
||||
|
||||
@@ -79,7 +77,6 @@ vec3 aces_approx(vec3 hdr_color) // also filmic, higher contrast then Uncharted2
|
||||
hdr_color *= 0.6f;
|
||||
|
||||
hdr_color = clamp((hdr_color*(a*hdr_color+b))/(hdr_color*(c*hdr_color+d)+e), 0.0f, 1.0f);
|
||||
hdr_color = linear_to_srgb(hdr_color); // return from linear color space to SRGB color space
|
||||
return hdr_color;
|
||||
}
|
||||
|
||||
@@ -96,7 +93,6 @@ vec3 rhj_lumaToneMapping(vec3 hdr_color) // reinhard_jodie
|
||||
float luma = dot(hdr_color, vec3(0.2126, 0.7152, 0.0722)); //dot products are a bit more expensive
|
||||
float toneMappedLuma = luma / (1.0 + luma);
|
||||
hdr_color *= toneMappedLuma / luma;
|
||||
hdr_color = linear_to_srgb(hdr_color); // return from linear color space to SRGB color space
|
||||
return hdr_color;
|
||||
}
|
||||
|
||||
@@ -105,14 +101,12 @@ vec3 reinhard_extended(vec3 hdr_color)
|
||||
float max_white = 1.0;
|
||||
vec3 numerator = hdr_color * (1.0f + (hdr_color / vec3(max_white * max_white)));
|
||||
hdr_color = numerator / (1.0f + hdr_color);
|
||||
hdr_color = linear_to_srgb(hdr_color); // return from linear color space to SRGB color space
|
||||
return hdr_color;
|
||||
}
|
||||
|
||||
vec3 linearToneMapping(vec3 hdr_color)
|
||||
{
|
||||
hdr_color = clamp(hdr_color, 0., 1.);
|
||||
hdr_color = linear_to_srgb(hdr_color); // return from linear color space to SRGB color space
|
||||
return hdr_color;
|
||||
}
|
||||
|
||||
@@ -155,7 +149,7 @@ vec3 PPC_RGB( vec3 color ) {
|
||||
funswitch(color.g),
|
||||
funswitch(color.b));
|
||||
|
||||
return linear_to_srgb(color);
|
||||
return color;
|
||||
}
|
||||
|
||||
|
||||
@@ -174,7 +168,7 @@ vec3 PPC( vec3 color ) {
|
||||
else {
|
||||
luma_tone = sh_offsetY;
|
||||
}
|
||||
return linear_to_srgb(color * luma_tone / luma);
|
||||
return color * luma_tone / luma;
|
||||
}
|
||||
|
||||
|
||||
@@ -213,5 +207,9 @@ void main()
|
||||
break;
|
||||
|
||||
}
|
||||
#ifdef LINEAR_OUT
|
||||
fragOut0 = vec4(color.rgb, 1.0);
|
||||
#else
|
||||
fragOut0 = vec4(linear_to_srgb(color.rgb), 1.0);
|
||||
#endif
|
||||
}
|
||||
@@ -21,9 +21,11 @@ layout (std140) uniform genericData {
|
||||
vec3 globalLightDiffuse;
|
||||
float stepsize;
|
||||
vec3 nebPos;
|
||||
float globalstepalpha;
|
||||
float opacitydistance;
|
||||
vec3 nebSize;
|
||||
float alphalim;
|
||||
vec3 nebulaColor;
|
||||
float udfScale;
|
||||
float emissiveSpreadFactor;
|
||||
float emissiveIntensity;
|
||||
float emissiveFalloff;
|
||||
@@ -92,12 +94,14 @@ void main()
|
||||
|
||||
vec3 sidestep = 1.0 / vec3(textureSize(volume_tex, 0));
|
||||
|
||||
for(float stept = maxtMin; stept < mintMax; stept += stepsize) {
|
||||
for(float stept = maxtMin; stept < mintMax;) {
|
||||
//Step setup
|
||||
vec3 position = camera + rayDirection * stept - nebPos;
|
||||
vec3 sampleposition = position / nebSize + 0.5;
|
||||
vec4 volume_sample = textureGrad(volume_tex, sampleposition, gradX, gradY);
|
||||
|
||||
float stepsize_current = min(max(stepsize, volume_sample.x * udfScale), mintMax - stept);
|
||||
|
||||
#ifdef DO_EDGE_SMOOTHING
|
||||
//Average 3D texel with texels on corner, in an attempt to reduce jagged edges.
|
||||
float stepcolor_alpha = volume_sample.a;
|
||||
@@ -117,7 +121,7 @@ void main()
|
||||
float stepcolor_alpha = volume_sample.a;
|
||||
#endif
|
||||
|
||||
float stepalpha = globalstepalpha * stepcolor_alpha;
|
||||
float stepalpha = -(pow(alphalim, 1.0 / (opacitydistance / stepsize_current)) - 1.0f) * stepcolor_alpha;
|
||||
//All the following computations are just required if we have a stepcoloralpha that is non-zero.
|
||||
if(stepcolor_alpha > 0.01)
|
||||
{
|
||||
@@ -127,10 +131,10 @@ void main()
|
||||
//Diffuse
|
||||
#ifdef NOISE
|
||||
//Mix the actual nebula color with the noise color depending on the product of the noise channels multiplied with intensity, smooth-clamped from 0 to 1
|
||||
vec3 stepcolor_neb = mix(volume_sample.rgb, noiseColor,
|
||||
vec3 stepcolor_neb = mix(nebulaColor, noiseColor,
|
||||
smoothstep(0, 1, (textureGrad(noise_volume_tex, position / noiseColorScale1, gradX, gradY).r + textureGrad(noise_volume_tex, position / noiseColorScale2, gradX, gradY).g) / 2.0 * noiseIntensity));
|
||||
#else
|
||||
vec3 stepcolor_neb = volume_sample.rgb;
|
||||
vec3 stepcolor_neb = nebulaColor;
|
||||
#endif
|
||||
vec3 stepcolor_diffuse = stepcolor_neb * henyey_greenstein(dot(rayDirection, globalLightDirection));
|
||||
float directionalLightStep = 4.0 / float(directionalLightSampleSteps);
|
||||
@@ -145,17 +149,17 @@ void main()
|
||||
stepcolor_diffuse *= beer_powder_norm * (1 - exp(-directionalLightDepth * 2.0)) * exp(-directionalLightDepth);
|
||||
|
||||
//Emissive
|
||||
cumnebdist += stepcolor_alpha * stepsize;
|
||||
cumnebdist += stepcolor_alpha * stepsize_current;
|
||||
vec3 emissive_lod = textureLod(emissive, fragTexCoord.xy, clamp(cumnebdist * emissiveSpreadFactor, 0, float(textureQueryLevels(emissive) - 1))).rgb;
|
||||
vec3 stepcolor_emissive = emissive_lod.rgb * pow(1 - globalstepalpha, (depth - stept) * emissiveFalloff) * emissiveIntensity;
|
||||
vec3 stepcolor_emissive = emissive_lod.rgb * pow(alphalim, 1.0 / (opacitydistance / ((depth - stept) * emissiveFalloff + 0.01))) * emissiveIntensity;
|
||||
|
||||
//Step finish
|
||||
vec3 stepcolor = clamp(stepcolor_diffuse + stepcolor_emissive, 0, 1);
|
||||
float stepalpha = globalstepalpha * stepcolor_alpha;
|
||||
cumcolor += stepalpha * cumOMAlpha * stepcolor;
|
||||
}
|
||||
|
||||
cumOMAlpha *= 1.0 - stepalpha;
|
||||
stept += stepsize_current;
|
||||
|
||||
if(cumOMAlpha < alphalim)
|
||||
break;
|
||||
|
||||
@@ -8,10 +8,10 @@ $Fog:
|
||||
+Start dist: 10.0
|
||||
+Compl dist: 500.0
|
||||
$AI:
|
||||
+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" )
|
||||
+Actively Pursues: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "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" )
|
||||
$Vaporize Percent Chance: 0.0
|
||||
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
|
||||
$Skip Death Roll Percent Chance: 0.0
|
||||
|
||||
$Name: Sentry Gun
|
||||
$Counts for Alone: YES
|
||||
@@ -28,11 +28,11 @@ $Fog:
|
||||
$AI:
|
||||
+Accept Player Orders: NO
|
||||
+Auto attacks: YES
|
||||
+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" )
|
||||
+Actively Pursues: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
|
||||
+Guards attack this: YES
|
||||
+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" )
|
||||
$Vaporize Percent Chance: 0.0
|
||||
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
|
||||
$Skip Death Roll Percent Chance: 0.0
|
||||
|
||||
$Name: Escape Pod
|
||||
$Praise Destruction: YES
|
||||
@@ -48,10 +48,10 @@ $Fog:
|
||||
+Compl dist: 600.0
|
||||
$AI:
|
||||
+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" )
|
||||
+Actively Pursues: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "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" )
|
||||
$Vaporize Percent Chance: 0.0
|
||||
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
|
||||
$Skip Death Roll Percent Chance: 0.0
|
||||
|
||||
$Name: Cargo
|
||||
$Scannable: YES
|
||||
@@ -65,7 +65,7 @@ $Fog:
|
||||
+Compl dist: 500.0
|
||||
$AI:
|
||||
+Passive docks: ( "cargo" )
|
||||
$Vaporize Percent Chance: 0.0
|
||||
$Skip Death Roll Percent Chance: 0.0
|
||||
|
||||
$Name: Support
|
||||
$Counts for Alone: YES
|
||||
@@ -87,38 +87,12 @@ $AI:
|
||||
+Accept Player Orders: YES
|
||||
+Player orders: ( "rearm me" "abort rearm" "depart" )
|
||||
+Auto attacks: YES
|
||||
+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" )
|
||||
+Actively Pursues: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
|
||||
+Guards attack this: YES
|
||||
+Turrets attack this: YES
|
||||
+Active docks: ( "support" )
|
||||
+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" )
|
||||
$Vaporize Percent Chance: 0.0
|
||||
|
||||
;;WMC - Stealth ships always have another type, so this isn't used
|
||||
$Name: Stealth
|
||||
$Counts for Alone: YES
|
||||
$Praise Destruction: YES
|
||||
$On Hotkey List: YES
|
||||
$Target as Threat: YES
|
||||
$Show Attack Direction: YES
|
||||
$Max Debris Speed: 200
|
||||
$FF Multiplier: 1.0
|
||||
$EMP Multiplier: 4.0
|
||||
$Protected on cripple: YES
|
||||
$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" "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
|
||||
+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" )
|
||||
+Guards attack this: YES
|
||||
+Turrets attack this: YES
|
||||
+Passive docks: ( "support" )
|
||||
+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" )
|
||||
$Vaporize Percent Chance: 0.0
|
||||
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
|
||||
$Skip Death Roll Percent Chance: 0.0
|
||||
|
||||
$Name: Fighter
|
||||
$Counts for Alone: YES
|
||||
@@ -136,17 +110,17 @@ $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" "play dead (persistent)" "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" "disable ship (tactical)" "disarm ship" "disarm ship (tactical)" "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" )
|
||||
+Player Orders: ( "attack ship" "disable ship" "disable ship (tactical)" "disarm ship" "disarm ship (tactical)" "guard ship" "ignore ship" "ignore ship (new)" "form on wing" "cover me" "attack any" "attack ship class" "depart" "disable subsys" )
|
||||
+Auto attacks: YES
|
||||
+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" )
|
||||
+Actively Pursues: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
|
||||
+Guards attack this: YES
|
||||
+Turrets attack this: YES
|
||||
+Can Form Wing: YES
|
||||
+Passive docks: ( "support" )
|
||||
+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" )
|
||||
$Vaporize Percent Chance: 0.0
|
||||
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
|
||||
$Skip Death Roll Percent Chance: 0.0
|
||||
|
||||
$Name: Bomber
|
||||
$Counts for Alone: YES
|
||||
@@ -164,17 +138,17 @@ $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" "play dead (persistent)" "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" "disable ship (tactical)" "disarm ship" "disarm ship (tactical)" "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" )
|
||||
+Player Orders: ( "attack ship" "disable ship" "disable ship (tactical)" "disarm ship" "disarm ship (tactical)" "guard ship" "ignore ship" "ignore ship (new)" "form on wing" "cover me" "attack any" "attack ship class" "depart" "disable subsys" )
|
||||
+Auto attacks: YES
|
||||
+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" )
|
||||
+Actively Pursues: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
|
||||
+Guards attack this: YES
|
||||
+Turrets attack this: YES
|
||||
+Can Form Wing: YES
|
||||
+Passive docks: ( "support" )
|
||||
+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" )
|
||||
$Vaporize Percent Chance: 0.0
|
||||
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
|
||||
$Skip Death Roll Percent Chance: 0.0
|
||||
|
||||
;;WMC - This fighter/bomber type doesn't seem to be used anywhere, because no ship is set as both fighter and bomber
|
||||
$Name: Fighter/bomber
|
||||
@@ -192,17 +166,17 @@ $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" "play dead (persistent)" "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" "disable ship (tactical)" "disarm ship" "disarm ship (tactical)" "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" )
|
||||
+Player Orders: ( "attack ship" "disable ship" "disable ship (tactical)" "disarm ship" "disarm ship (tactical)" "guard ship" "ignore ship" "ignore ship (new)" "form on wing" "cover me" "attack any" "attack ship class" "depart" "disable subsys" )
|
||||
+Auto attacks: YES
|
||||
+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" )
|
||||
+Actively Pursues: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
|
||||
+Guards attack this: YES
|
||||
+Turrets attack this: YES
|
||||
+Can Form Wing: YES
|
||||
+Passive docks: ( "support" )
|
||||
+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" )
|
||||
$Vaporize Percent Chance: 0.0
|
||||
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
|
||||
$Skip Death Roll Percent Chance: 0.0
|
||||
|
||||
$Name: Transport
|
||||
$Counts for Alone: YES
|
||||
@@ -230,9 +204,9 @@ $AI:
|
||||
+Turrets attack this: YES
|
||||
+Can Form Wing: YES
|
||||
+Passive docks: ( "support" )
|
||||
+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" )
|
||||
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
|
||||
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
|
||||
$Vaporize Percent Chance: 0.0
|
||||
$Skip Death Roll Percent Chance: 0.0
|
||||
|
||||
$Name: Freighter
|
||||
$Counts for Alone: YES
|
||||
@@ -262,9 +236,9 @@ $AI:
|
||||
+Can Form Wing: YES
|
||||
+Active docks: ( "cargo" )
|
||||
+Passive docks: ( "support" )
|
||||
+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" )
|
||||
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
|
||||
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
|
||||
$Vaporize Percent Chance: 0.0
|
||||
$Skip Death Roll Percent Chance: 0.0
|
||||
|
||||
$Name: AWACS
|
||||
$Counts for Alone: YES
|
||||
@@ -292,9 +266,9 @@ $AI:
|
||||
+Turrets attack this: YES
|
||||
+Can Form Wing: YES
|
||||
+Passive docks: ( "support" )
|
||||
+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" )
|
||||
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
|
||||
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
|
||||
$Vaporize Percent Chance: 0.0
|
||||
$Skip Death Roll Percent Chance: 0.0
|
||||
|
||||
$Name: Gas Miner
|
||||
$Counts for Alone: YES
|
||||
@@ -322,9 +296,9 @@ $AI:
|
||||
+Turrets attack this: YES
|
||||
+Can Form Wing: YES
|
||||
+Passive docks: ( "support" )
|
||||
+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" )
|
||||
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
|
||||
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
|
||||
$Vaporize Percent Chance: 0.0
|
||||
$Skip Death Roll Percent Chance: 0.0
|
||||
|
||||
$Name: Cruiser
|
||||
$Counts for Alone: YES
|
||||
@@ -352,9 +326,9 @@ $AI:
|
||||
+Turrets attack this: YES
|
||||
+Can Form Wing: YES
|
||||
+Passive docks: ( "support" )
|
||||
+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" )
|
||||
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
|
||||
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
|
||||
$Vaporize Percent Chance: 0.0
|
||||
$Skip Death Roll Percent Chance: 0.0
|
||||
|
||||
$Name: Corvette
|
||||
$Counts for Alone: YES
|
||||
@@ -382,9 +356,9 @@ $AI:
|
||||
+Turrets attack this: YES
|
||||
+Can Form Wing: YES
|
||||
+Passive docks: ( "support" )
|
||||
+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" )
|
||||
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
|
||||
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
|
||||
$Vaporize Percent Chance: 0.0
|
||||
$Skip Death Roll Percent Chance: 0.0
|
||||
|
||||
$Name: Capital
|
||||
$Counts for Alone: YES
|
||||
@@ -412,9 +386,9 @@ $AI:
|
||||
+Turrets attack this: YES
|
||||
+Can Form Wing: YES
|
||||
+Passive docks: ( "support" )
|
||||
+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" )
|
||||
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
|
||||
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
|
||||
$Vaporize Percent Chance: 0.0
|
||||
$Skip Death Roll Percent Chance: 0.0
|
||||
|
||||
$Name: Super Cap
|
||||
$Counts for Alone: YES
|
||||
@@ -440,9 +414,9 @@ $AI:
|
||||
+Turrets attack this: YES
|
||||
+Can Form Wing: YES
|
||||
+Passive docks: ( "support" )
|
||||
+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" )
|
||||
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
|
||||
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
|
||||
$Vaporize Percent Chance: 0.0
|
||||
$Skip Death Roll Percent Chance: 0.0
|
||||
|
||||
$Name: Drydock
|
||||
$Counts for Alone: YES
|
||||
@@ -466,9 +440,9 @@ $AI:
|
||||
+Guards attack this: YES
|
||||
+Turrets attack this: YES
|
||||
+Passive docks: ( "support" )
|
||||
+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" )
|
||||
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
|
||||
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
|
||||
$Vaporize Percent Chance: 0.0
|
||||
$Skip Death Roll Percent Chance: 0.0
|
||||
|
||||
$Name: Knossos Device
|
||||
$Counts for Alone: YES
|
||||
@@ -490,8 +464,8 @@ $AI:
|
||||
+Guards attack this: YES
|
||||
+Turrets attack this: YES
|
||||
+Passive docks: ( "support" )
|
||||
+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" )
|
||||
+Ignored on cripple by: ( "navbuoy" "sentry gun" "escape pod" "cargo" "support" "fighter" "bomber" "fighter/bomber" "transport" "freighter" "awacs" "gas miner" "cruiser" "corvette" "capital" "super cap" "drydock" "knossos device" )
|
||||
+Targeted by 'Huge' weapons and Ignored by 'small only' weapons: YES
|
||||
$Vaporize Percent Chance: 0.0
|
||||
$Skip Death Roll Percent Chance: 0.0
|
||||
|
||||
#End
|
||||
+40
-36
@@ -37,11 +37,7 @@ constexpr int INTITIAL_FIREBALL_CONTAINTER_SIZE = 256;
|
||||
SCP_vector<fireball> Fireballs;
|
||||
SCP_vector<int> Unused_fireball_indices;
|
||||
|
||||
fireball_info Fireball_info[MAX_FIREBALL_TYPES];
|
||||
|
||||
int fireball_used[MAX_FIREBALL_TYPES];
|
||||
|
||||
int Num_fireball_types = 0;
|
||||
SCP_vector<fireball_info> Fireball_info;
|
||||
|
||||
bool fireballs_inited = false;
|
||||
bool fireballs_parsed = false;
|
||||
@@ -51,7 +47,7 @@ bool Fireball_use_3d_warp = false;
|
||||
static auto WarpOption __UNUSED = options::OptionBuilder<bool>("Graphics.3dWarp",
|
||||
std::pair<const char*, int>{"3D Warp", 1770},
|
||||
std::pair<const char*, int>{"Use a 3D model for warp effects", 1771})
|
||||
.category("Graphics")
|
||||
.category(std::make_pair("Graphics", 1825))
|
||||
.default_val(true)
|
||||
.level(options::ExpertLevel::Advanced)
|
||||
.bind_to(&Fireball_use_3d_warp)
|
||||
@@ -120,7 +116,7 @@ void fireball_play_warphole_close_sound(fireball *fb)
|
||||
|
||||
static void fireball_generate_unique_id(char *unique_id, int buffer_len, int fireball_index)
|
||||
{
|
||||
Assert((fireball_index >= 0) && (fireball_index < MAX_FIREBALL_TYPES));
|
||||
Assertion(SCP_vector_inbounds(Fireball_info, fireball_index), "fireball_index is out of bounds!");
|
||||
|
||||
switch (fireball_index)
|
||||
{
|
||||
@@ -164,7 +160,7 @@ static void fireball_generate_unique_id(char *unique_id, int buffer_len, int fir
|
||||
*/
|
||||
static void fireball_set_default_color(int idx)
|
||||
{
|
||||
Assert((idx >= 0) && (idx < MAX_FIREBALL_TYPES));
|
||||
Assertion(SCP_vector_inbounds(Fireball_info, idx), "idx is out of bounds!");
|
||||
|
||||
switch (idx)
|
||||
{
|
||||
@@ -200,7 +196,7 @@ static void fireball_set_default_color(int idx)
|
||||
|
||||
static void fireball_set_default_warp_attributes(int idx)
|
||||
{
|
||||
Assert((idx >= 0) && (idx < MAX_FIREBALL_TYPES));
|
||||
Assertion(SCP_vector_inbounds(Fireball_info, idx), "idx is out of bounds!");
|
||||
|
||||
switch (idx)
|
||||
{
|
||||
@@ -232,9 +228,9 @@ void fireball_info_clear(fireball_info *fb)
|
||||
|
||||
int fireball_info_lookup(const char *unique_id)
|
||||
{
|
||||
for (int i = 0; i < Num_fireball_types; ++i)
|
||||
for (size_t i = 0; i < Fireball_info.size(); ++i)
|
||||
if (!stricmp(Fireball_info[i].unique_id, unique_id))
|
||||
return i;
|
||||
return static_cast<int>(i);
|
||||
|
||||
return -1;
|
||||
}
|
||||
@@ -308,25 +304,19 @@ static void parse_fireball_tbl(const char *table_filename)
|
||||
// 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;
|
||||
}
|
||||
|
||||
fi = &Fireball_info[Num_fireball_types];
|
||||
int new_fireball_index = static_cast<int>(Fireball_info.size());
|
||||
Fireball_info.emplace_back();
|
||||
fi = &Fireball_info.back();
|
||||
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);
|
||||
fireball_generate_unique_id(unique_id, NAME_LENGTH, new_fireball_index);
|
||||
|
||||
// Set remaining fireball defaults
|
||||
fireball_set_default_color(Num_fireball_types);
|
||||
fireball_set_default_warp_attributes(Num_fireball_types);
|
||||
fireball_set_default_color(new_fireball_index);
|
||||
fireball_set_default_warp_attributes(new_fireball_index);
|
||||
|
||||
Num_fireball_types++;
|
||||
first_time = true;
|
||||
}
|
||||
|
||||
@@ -399,9 +389,9 @@ void fireball_parse_tbl()
|
||||
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;
|
||||
// every newly parsed fireball_info will get cleared before being added;
|
||||
// must clear the vector outside of parse_fireball_tbl because it's called more than once
|
||||
Fireball_info.clear();
|
||||
|
||||
parse_fireball_tbl("fireball.tbl");
|
||||
|
||||
@@ -436,10 +426,11 @@ void fireball_parse_tbl()
|
||||
|
||||
void fireball_load_data()
|
||||
{
|
||||
int i, idx;
|
||||
int i, n, idx;
|
||||
fireball_info *fd;
|
||||
|
||||
for ( i = 0; i < Num_fireball_types; i++ ) {
|
||||
n = static_cast<int>(Fireball_info.size());
|
||||
for ( i = 0; i < n; i++ ) {
|
||||
fd = &Fireball_info[i];
|
||||
|
||||
for(idx=0; idx<fd->lod_count; idx++){
|
||||
@@ -798,8 +789,7 @@ int fireball_create(vec3d *pos, int fireball_type, int render_type, int parent_o
|
||||
object *obj;
|
||||
fireball_info *fd;
|
||||
fireball_lod *fl;
|
||||
Assert( fireball_type > -1 );
|
||||
Assert( fireball_type < Num_fireball_types );
|
||||
Assertion(SCP_vector_inbounds(Fireball_info, fireball_type), "fireball_type is out of bounds!");
|
||||
|
||||
fd = &Fireball_info[fireball_type];
|
||||
|
||||
@@ -946,13 +936,14 @@ void fireball_close()
|
||||
|
||||
void fireballs_page_in()
|
||||
{
|
||||
int i, idx;
|
||||
int i, n, idx;
|
||||
fireball_info *fd;
|
||||
|
||||
for ( i = 0; i < Num_fireball_types; i++ ) {
|
||||
n = static_cast<int>(Fireball_info.size());
|
||||
for ( i = 0; i < n; i++ ) {
|
||||
fd = &Fireball_info[i];
|
||||
|
||||
if((i < NUM_DEFAULT_FIREBALLS) || fireball_used[i]) {
|
||||
if ((i < NUM_DEFAULT_FIREBALLS) || fd->fireball_used) {
|
||||
// if this is a Knossos ani, only load if Knossos_warp_ani_used is true
|
||||
if ( (i == FIREBALL_KNOSSOS) && !Knossos_warp_ani_used)
|
||||
continue;
|
||||
@@ -984,8 +975,8 @@ void fireball_get_color(int idx, float *red, float *green, float *blue)
|
||||
{
|
||||
Assert( red && blue && green );
|
||||
|
||||
if ( (idx < 0) || (idx >= Num_fireball_types) ) {
|
||||
Int3();
|
||||
if (!SCP_vector_inbounds(Fireball_info, idx)) {
|
||||
UNREACHABLE("idx is out of bounds!");
|
||||
|
||||
*red = 1.0f;
|
||||
*green = 1.0f;
|
||||
@@ -1052,7 +1043,7 @@ float fireball_wormhole_intensity(fireball *fb)
|
||||
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);
|
||||
|
||||
@@ -1120,3 +1111,16 @@ int fireball_get_count()
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void stuff_fireball_index_list(SCP_vector<int> &list, const char *name)
|
||||
{
|
||||
stuff_int_list(list, RAW_INTEGER_TYPE);
|
||||
|
||||
list.erase(std::remove_if(list.begin(), list.end(), [&](int index) {
|
||||
if (!SCP_vector_inbounds(Fireball_info, index)) {
|
||||
Warning(LOCATION, "Fireball index %d for %s was out of bounds. Removing this index.", index, name);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}), list.end());
|
||||
}
|
||||
@@ -33,15 +33,12 @@ class asteroid_info;
|
||||
#define FIREBALL_EXPLOSION_LARGE1 4 // Used for the big explosion when a ship breaks into pieces
|
||||
#define FIREBALL_EXPLOSION_LARGE2 5 // Used for the big explosion when a ship breaks into pieces
|
||||
|
||||
#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];
|
||||
|
||||
// all this moved here by Goober5000 because it makes more sense in the H file
|
||||
typedef struct fireball_lod {
|
||||
char filename[MAX_FILENAME_LEN];
|
||||
@@ -57,6 +54,7 @@ typedef struct fireball_info {
|
||||
float exp_color[3]; // red, green, blue
|
||||
|
||||
bool use_3d_warp;
|
||||
bool fireball_used;
|
||||
|
||||
char warp_glow[NAME_LENGTH];
|
||||
int warp_glow_bitmap;
|
||||
@@ -66,8 +64,7 @@ typedef struct fireball_info {
|
||||
int warp_model_id;
|
||||
} fireball_info;
|
||||
|
||||
extern fireball_info Fireball_info[MAX_FIREBALL_TYPES];
|
||||
extern int Num_fireball_types;
|
||||
extern SCP_vector<fireball_info> Fireball_info;
|
||||
|
||||
// flag values for fireball struct flags member
|
||||
#define FBF_WARP_CLOSE_SOUND_PLAYED (1<<0)
|
||||
@@ -153,4 +150,7 @@ extern bool Fireball_warp_flash;
|
||||
// Cyborg - get a count of how many valid fireballs are in the mission.
|
||||
int fireball_get_count();
|
||||
|
||||
// Goober5000 - stuffs fireballs and checks that indexes are in bounds
|
||||
void stuff_fireball_index_list(SCP_vector<int> &list, const char *name);
|
||||
|
||||
#endif /* _FIREBALLS_H */
|
||||
@@ -27,10 +27,10 @@ bool Fireball_warp_flash = false;
|
||||
static auto WarpFlashOption __UNUSED = options::OptionBuilder<bool>("Graphics.WarpFlash",
|
||||
std::pair<const char*, int>{"Warp Flash", 1768},
|
||||
std::pair<const char*, int>{"Show flash upon warp open or close", 1769})
|
||||
.category("Graphics")
|
||||
.category(std::make_pair("Graphics", 1825))
|
||||
.default_val(true)
|
||||
.level(options::ExpertLevel::Advanced)
|
||||
.bind_to_once(&Fireball_warp_flash)
|
||||
.bind_to(&Fireball_warp_flash)
|
||||
.importance(65)
|
||||
.finish();
|
||||
|
||||
|
||||
@@ -499,7 +499,7 @@ void help_overlay_blit(int overlay_id, int resolution_index)
|
||||
font::set_font(help_overlaylist[overlay_id].fontlist.at(resolution_index));
|
||||
for (idx = 0; idx < textcount; idx++) {
|
||||
gr_set_color_fast(&Color_black);
|
||||
gr_get_string_size(&width, &height, help_overlaylist[overlay_id].textlist.at(0).at(idx).string, (int)strlen(help_overlaylist[overlay_id].textlist.at(0).at(idx).string));
|
||||
gr_get_string_size(&width, &height, help_overlaylist[overlay_id].textlist.at(0).at(idx).string, strlen(help_overlaylist[overlay_id].textlist.at(0).at(idx).string));
|
||||
gr_rect(help_overlaylist[overlay_id].textlist.at(resolution_index).at(idx).x_coord-2*HELP_PADDING, help_overlaylist[overlay_id].textlist.at(resolution_index).at(idx).y_coord-3*HELP_PADDING, width+4*HELP_PADDING, height+4*HELP_PADDING, GR_RESIZE_MENU);
|
||||
gr_set_color_fast(&Color_bright_white);
|
||||
gr_printf_menu(help_overlaylist[overlay_id].textlist.at(resolution_index).at(idx).x_coord, help_overlaylist[overlay_id].textlist.at(resolution_index).at(idx).y_coord,
|
||||
|
||||
@@ -113,7 +113,9 @@ const char *GS_event_text[] =
|
||||
"GS_EVENT_LAB",
|
||||
"GS_EVENT_PXO_HELP",
|
||||
"GS_EVENT_FICTION_VIEWER", // 65
|
||||
"GS_EVENT_SCRIPTING"
|
||||
"GS_EVENT_SCRIPTING",
|
||||
"GS_EVENT_SCRIPTING_MISSION",
|
||||
"GS_EVENT_INGAME_OPTIONS"
|
||||
};
|
||||
//XSTR:ON
|
||||
|
||||
@@ -176,7 +178,9 @@ const char *GS_state_text[] =
|
||||
"GS_STATE_PXO_HELP", // 50
|
||||
"GS_STATE_START_GAME",
|
||||
"GS_STATE_FICTION_VIEWER",
|
||||
"GS_STATE_SCRIPTING"
|
||||
"GS_STATE_SCRIPTING",
|
||||
"GS_STATE_SCRIPTING_MISSION",
|
||||
"GS_STATE_INGAME_OPTIONS"
|
||||
};
|
||||
//XSTR:ON
|
||||
|
||||
|
||||
@@ -89,6 +89,8 @@ enum GS_EVENT {
|
||||
GS_EVENT_PXO_HELP,
|
||||
GS_EVENT_FICTION_VIEWER,
|
||||
GS_EVENT_SCRIPTING,
|
||||
GS_EVENT_SCRIPTING_MISSION,
|
||||
GS_EVENT_INGAME_OPTIONS,
|
||||
|
||||
GS_NUM_EVENTS // Last one++
|
||||
};
|
||||
@@ -159,6 +161,8 @@ enum GS_STATE {
|
||||
GS_STATE_START_GAME,
|
||||
GS_STATE_FICTION_VIEWER,
|
||||
GS_STATE_SCRIPTING,
|
||||
GS_STATE_SCRIPTING_MISSION,
|
||||
GS_STATE_INGAME_OPTIONS,
|
||||
|
||||
GS_NUM_STATES // Last one++
|
||||
};
|
||||
|
||||
@@ -48,11 +48,12 @@ static bool music_volume_change_listener(float new_val, bool /*initial*/)
|
||||
static auto MusicVolumeOption __UNUSED = options::OptionBuilder<float>("Audio.Music",
|
||||
std::pair<const char*, int>{"Music", 1371},
|
||||
std::pair<const char*, int>{"Volume used for playing music", 1760})
|
||||
.category("Audio")
|
||||
.category(std::make_pair("Audio", 1826))
|
||||
.default_val(Default_music_volume)
|
||||
.range(0.0f, 1.0f)
|
||||
.change_listener(music_volume_change_listener)
|
||||
.importance(1)
|
||||
.flags({options::OptionFlags::RetailBuiltinOption})
|
||||
.finish();
|
||||
|
||||
typedef struct tagSNDPATTERN {
|
||||
@@ -340,7 +341,7 @@ void event_music_init()
|
||||
Warning(LOCATION, "Soundtrack file %s was not found with its specified extension, but another file %s exists in the modpack. Please update the extension and adjust audio specifications if necessary.", filename, res.name_ext.c_str());
|
||||
#endif
|
||||
|
||||
Warning(LOCATION, "One or more files in '%s' could not be loaded. The soundtrack will not be used.", soundtrack.name);
|
||||
Warning(LOCATION, "Soundtrack file %s was not found. The soundtrack '%s' will not be used.", filename, soundtrack.name);
|
||||
all_patterns_valid = false;
|
||||
break;
|
||||
}
|
||||
@@ -970,11 +971,13 @@ int event_music_friendly_arrival()
|
||||
// overlay
|
||||
if (Soundtracks[Current_soundtrack_num].flags & EMF_ALLIED_ARRIVAL_OVERLAY)
|
||||
{
|
||||
// Goober5000 - I didn't touch this part... for some reason, FS2 only has one
|
||||
// Goober5000 - This is how retail did it. For some reason, FS2 only has one
|
||||
// arrival music pattern, and this is it
|
||||
Assert(Patterns[SONG_AARV_1].handle >= 0 );
|
||||
audiostream_play(Patterns[SONG_AARV_1].handle, (Master_event_music_volume * aav_music_volume), 0); // no looping
|
||||
audiostream_set_sample_cutoff(Patterns[SONG_AARV_1].handle, fl2i(Patterns[SONG_AARV_1].num_measures * Patterns[SONG_AARV_1].samples_per_measure) );
|
||||
if (Patterns[SONG_AARV_1].handle >= 0)
|
||||
{
|
||||
audiostream_play(Patterns[SONG_AARV_1].handle, (Master_event_music_volume * aav_music_volume), 0); // no looping
|
||||
audiostream_set_sample_cutoff(Patterns[SONG_AARV_1].handle, fl2i(Patterns[SONG_AARV_1].num_measures * Patterns[SONG_AARV_1].samples_per_measure));
|
||||
}
|
||||
}
|
||||
// don't overlay
|
||||
else
|
||||
|
||||
+231
-37
@@ -222,6 +222,7 @@ static EnhancedSoundData Default_sound_priorities[NUM_RETAIL_GAMEPLAY_SOUNDS] =
|
||||
|
||||
static const EnhancedSoundData default_enhanced_sound_data(SND_ENHANCED_PRIORITY_MEDIUM_HIGH, 1);
|
||||
|
||||
int gamesnd_find_nonreserved_last_index(SCP_vector<game_snd>& lookupVector, bool (*is_reserved_index)(int));
|
||||
|
||||
/*
|
||||
* Update any uninitialized EnhancedSoundData in Snds
|
||||
@@ -545,7 +546,7 @@ void gamesnd_preload_common_sounds()
|
||||
|
||||
Assert( Snds.size() <= INT_MAX );
|
||||
for (auto& gs: Snds) {
|
||||
if ( gs.preload ) {
|
||||
if ( gs.flags & GAME_SND_PRELOAD ) {
|
||||
for (auto& entry : gs.sound_entries) {
|
||||
if ( entry.filename[0] != 0 && strnicmp(entry.filename, NOX("none.wav"), 4) != 0 ) {
|
||||
game_busy( NOX("** preloading common game sounds **") ); // Animate loading cursor... does nothing if loading screen not active.
|
||||
@@ -566,7 +567,7 @@ void gamesnd_load_gameplay_sounds()
|
||||
|
||||
Assert( Snds.size() <= INT_MAX );
|
||||
for (auto& gs: Snds) {
|
||||
if ( !gs.preload ) { // don't try to load anything that's already preloaded
|
||||
if ( !(gs.flags & GAME_SND_PRELOAD) ) { // don't try to load anything that's already preloaded
|
||||
for (auto& entry : gs.sound_entries) {
|
||||
if (entry.filename[0] != 0 && strnicmp(entry.filename, NOX("none.wav"), 4) != 0) {
|
||||
game_busy(NOX("** preloading gameplay sounds **")); // Animate loading cursor... does nothing if loading screen not active.
|
||||
@@ -633,6 +634,10 @@ void parse_gamesnd_old(game_snd* gs)
|
||||
int is_3d;
|
||||
int temp;
|
||||
|
||||
// retail-style sounds with numeric indexes, as seen in the original sounds.tbl format
|
||||
if (can_construe_as_integer(gs->name.c_str()))
|
||||
gs->flags |= GAME_SND_RETAIL_STYLE;
|
||||
|
||||
// An old sound is just a single entry sound set
|
||||
gs->sound_entries.resize(1);
|
||||
auto& entry = gs->sound_entries.back();
|
||||
@@ -649,7 +654,7 @@ void parse_gamesnd_old(game_snd* gs)
|
||||
{
|
||||
entry.filename[0] = 0;
|
||||
advance_to_eoln(nullptr);
|
||||
gs->flags |= GAME_SND_NOT_VALID;
|
||||
gs->flags |= (GAME_SND_NOT_VALID | GAME_SND_EXPLICITLY_EMPTY);
|
||||
return;
|
||||
}
|
||||
Mp++;
|
||||
@@ -658,7 +663,7 @@ void parse_gamesnd_old(game_snd* gs)
|
||||
|
||||
if (temp > 0)
|
||||
{
|
||||
gs->preload = true;
|
||||
gs->flags |= GAME_SND_PRELOAD;
|
||||
}
|
||||
|
||||
float default_volume;
|
||||
@@ -701,7 +706,7 @@ void parse_gamesnd_old(game_snd* gs)
|
||||
// check for extra values per Mantis #2408
|
||||
if (stuff_int_optional(&temp) == 2)
|
||||
{
|
||||
Warning(LOCATION, "Unexpected extra value %d found for sound '%s' (filename '%s')! Check the format of the sounds.tbl (or .tbm) entry.", temp, gs->name.c_str(), entry.filename);
|
||||
error_display(0, "Unexpected extra value %d found for sound '%s' (filename '%s')! Check the format of the sounds.tbl (or .tbm) entry.", temp, gs->name.c_str(), entry.filename);
|
||||
}
|
||||
|
||||
advance_to_eoln(NULL);
|
||||
@@ -770,8 +775,8 @@ void parse_gamesnd_soundset(game_snd* gs, bool no_create) {
|
||||
// If this gets called then we just saw "+Entry:" so we can begin processing the first entry immediately
|
||||
|
||||
do {
|
||||
// For now there is no way to change an existing entry so ever +Entry statement creates a new sound entry
|
||||
gs->sound_entries.resize(gs->sound_entries.size() + 1);
|
||||
// For now there is no way to change an existing entry so every +Entry statement creates a new sound entry
|
||||
gs->sound_entries.emplace_back();
|
||||
auto& entry = gs->sound_entries.back();
|
||||
|
||||
stuff_string(entry.filename, F_NAME, MAX_FILENAME_LEN);
|
||||
@@ -783,12 +788,18 @@ void parse_gamesnd_soundset(game_snd* gs, bool no_create) {
|
||||
|
||||
if (required_string_no_create("+Preload:", no_create))
|
||||
{
|
||||
stuff_boolean(&gs->preload);
|
||||
bool temp;
|
||||
stuff_boolean(&temp);
|
||||
|
||||
if (temp)
|
||||
gs->flags |= GAME_SND_PRELOAD;
|
||||
else
|
||||
gs->flags &= ~GAME_SND_PRELOAD;
|
||||
}
|
||||
|
||||
if (required_string_no_create("+Volume:", no_create))
|
||||
{
|
||||
gs->volume_range = util::parseUniformRange(0.0f, 1.0f);
|
||||
gs->volume_range = util::ParsedRandomFloatRange::parseRandomRange(0.0f, 1.0f);
|
||||
}
|
||||
|
||||
if (optional_string("+3D Sound:"))
|
||||
@@ -837,7 +848,7 @@ void parse_gamesnd_soundset(game_snd* gs, bool no_create) {
|
||||
}
|
||||
|
||||
if (optional_string("+Pitch:")) {
|
||||
gs->pitch_range = util::parseUniformRange(0.0001f);
|
||||
gs->pitch_range = util::ParsedRandomFloatRange::parseRandomRange(0.0001f);
|
||||
} else if (!no_create) {
|
||||
// Default pitch is 1.0
|
||||
gs->pitch_range = util::UniformFloatRange(1.0f);
|
||||
@@ -851,7 +862,9 @@ void parse_gamesnd_new(game_snd* gs, bool no_create)
|
||||
gs->sound_entries.resize(1);
|
||||
entry = &gs->sound_entries.back();
|
||||
} else {
|
||||
if (gs->sound_entries.size() != 1) {
|
||||
if (gs->sound_entries.empty()) {
|
||||
gs->sound_entries.resize(1);
|
||||
} else if (gs->sound_entries.size() > 1) {
|
||||
error_display(1, "The SCP syntax cannot be used to modify an existing sound that has more than one entry! Use the soundset syntax for adding new entries.");
|
||||
}
|
||||
entry = &gs->sound_entries.back();
|
||||
@@ -870,7 +883,7 @@ void parse_gamesnd_new(game_snd* gs, bool no_create)
|
||||
if (!stricmp(name, NOX("empty")) || !stricmp(name, NOX("none")))
|
||||
{
|
||||
entry->filename[0] = 0;
|
||||
gs->flags |= GAME_SND_NOT_VALID;
|
||||
gs->flags |= (GAME_SND_NOT_VALID | GAME_SND_EXPLICITLY_EMPTY);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -888,7 +901,13 @@ void parse_gamesnd_new(game_snd* gs, bool no_create)
|
||||
|
||||
if (required_string_no_create("+Preload:", no_create))
|
||||
{
|
||||
stuff_boolean(&gs->preload);
|
||||
bool temp;
|
||||
stuff_boolean(&temp);
|
||||
|
||||
if (temp)
|
||||
gs->flags |= GAME_SND_PRELOAD;
|
||||
else
|
||||
gs->flags &= ~GAME_SND_PRELOAD;
|
||||
}
|
||||
|
||||
if (required_string_no_create("+Volume:", no_create))
|
||||
@@ -944,33 +963,107 @@ void parse_gamesnd_new(game_snd* gs, bool no_create)
|
||||
}
|
||||
}
|
||||
|
||||
void gamesnd_parse_entry(game_snd *gs, bool no_create, SCP_vector<game_snd> *lookupVector)
|
||||
bool gamesnd_is_placeholder(const game_snd& gs)
|
||||
{
|
||||
return (gs.sound_entries.empty() || gs.sound_entries[0].filename[0] == '\0') && !(gs.flags & GAME_SND_EXPLICITLY_EMPTY);
|
||||
}
|
||||
|
||||
void gamesnd_parse_entry(game_snd *gs, bool &orig_no_create, SCP_vector<game_snd> *lookupVector, size_t lookupVectorMaxIndexableSize, bool (*is_reserved_index)(int))
|
||||
{
|
||||
SCP_string name;
|
||||
|
||||
stuff_string(name, F_NAME, "\t \n");
|
||||
|
||||
if (lookupVector && can_construe_as_integer(name.c_str()))
|
||||
{
|
||||
Assertion(is_reserved_index != nullptr, "If lookupVector is supplied, the is_reserved_index() function must also be supplied");
|
||||
|
||||
int candidate_index = atoi(name.c_str());
|
||||
|
||||
// if this is a number within the range of possible indexes
|
||||
if (candidate_index >= 0 && static_cast<size_t>(candidate_index) < lookupVectorMaxIndexableSize)
|
||||
{
|
||||
// make sure the vector contains an entry for that index
|
||||
while (lookupVector->size() <= static_cast<size_t>(candidate_index))
|
||||
{
|
||||
size_t back_index = lookupVector->size();
|
||||
lookupVector->emplace_back();
|
||||
sprintf(lookupVector->back().name, SIZE_T_ARG, back_index);
|
||||
}
|
||||
|
||||
// if there is a named sound already at that index, move it to the end of the vector
|
||||
// (because named sounds can go anywhere, while indexed sounds need to be at their indexes)
|
||||
auto candidate_gs = &lookupVector->at(candidate_index);
|
||||
if (!candidate_gs->name.empty() && !can_construe_as_integer(candidate_gs->name.c_str()))
|
||||
{
|
||||
// prevent new named sounds from colliding with reserved indexes
|
||||
int endIndex = gamesnd_find_nonreserved_last_index(*lookupVector, is_reserved_index);
|
||||
|
||||
// add a new sound at the end of the vector
|
||||
lookupVector->emplace_back();
|
||||
|
||||
// swap them
|
||||
std::swap(lookupVector->at(candidate_index), lookupVector->at(endIndex));
|
||||
sprintf(lookupVector->at(candidate_index).name, "%d", candidate_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int vectorIndex;
|
||||
if (lookupVector)
|
||||
vectorIndex = gamesnd_lookup_name(name.c_str(), *lookupVector);
|
||||
else
|
||||
vectorIndex = -1;
|
||||
|
||||
bool no_create = orig_no_create;
|
||||
|
||||
if (!no_create)
|
||||
{
|
||||
if (lookupVector != NULL)
|
||||
if (vectorIndex >= 0)
|
||||
{
|
||||
if (gamesnd_lookup_name(name.c_str(), *lookupVector) >= 0)
|
||||
auto existing_gs = &lookupVector->at(vectorIndex);
|
||||
|
||||
// if the existing sound was an empty or placeholder sound, replace it, don't warn
|
||||
if (gamesnd_is_placeholder(*existing_gs))
|
||||
{
|
||||
Warning(LOCATION, "Duplicate sound name \"%s\" found!", name.c_str());
|
||||
gs = existing_gs;
|
||||
orig_no_create = true; // prevent sound from being appended in parse_sound_table
|
||||
// (leave no_create as false because we are creating a new sound and we need all the fields to be filled out)
|
||||
}
|
||||
else
|
||||
{
|
||||
error_display(0, "Duplicate sound name \"%s\" found!", name.c_str());
|
||||
}
|
||||
}
|
||||
else if (lookupVector)
|
||||
{
|
||||
// see if there is an empty or placeholder sound that we can replace
|
||||
int i = 0;
|
||||
for (const auto& ii : *lookupVector)
|
||||
{
|
||||
if (gamesnd_is_placeholder(ii) && !is_reserved_index(i))
|
||||
{
|
||||
vectorIndex = i;
|
||||
gs = &lookupVector->at(vectorIndex);
|
||||
orig_no_create = true; // prevent sound from being appended in parse_sound_table
|
||||
// (leave no_create as false because we are creating a new sound and we need all the fields to be filled out)
|
||||
|
||||
// a placeholder can have a single entry with an empty filename, so remove that if it exists
|
||||
gs->sound_entries.clear();
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
gs->name = name;
|
||||
gs->name = std::move(name);
|
||||
}
|
||||
else
|
||||
{
|
||||
int vectorIndex = gamesnd_lookup_name(name.c_str(), *lookupVector);
|
||||
|
||||
if (vectorIndex < 0)
|
||||
{
|
||||
Warning(LOCATION, "No existing sound entry with name \"%s\" found!", name.c_str());
|
||||
no_create = false;
|
||||
gs->name = name;
|
||||
error_display(0, "No existing sound entry with name \"%s\" found!", name.c_str());
|
||||
no_create = false; // this is a new sound, so we need all the fields to be filled out
|
||||
gs->name = std::move(name);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -981,7 +1074,9 @@ void gamesnd_parse_entry(game_snd *gs, bool no_create, SCP_vector<game_snd> *loo
|
||||
if (optional_string("+Filename:"))
|
||||
{
|
||||
parse_gamesnd_new(gs, no_create);
|
||||
} else if (optional_string("+Entry:")) {
|
||||
}
|
||||
else if (optional_string("+Entry:"))
|
||||
{
|
||||
parse_gamesnd_soundset(gs, no_create);
|
||||
}
|
||||
else
|
||||
@@ -996,11 +1091,16 @@ void gamesnd_parse_entry(game_snd *gs, bool no_create, SCP_vector<game_snd> *loo
|
||||
* @param gs The game_snd instance to fill in
|
||||
* @param tag The tag that's required before an entry
|
||||
* @param lookupVector If non-NULL used to look up @c +nocreate entries
|
||||
* @param lookupVectorMaxIndexableSize Numbers less than this size will be treated as indexes;
|
||||
* numbers at or above this size will be treated as numeric IDs that aren't indexes.
|
||||
* Note that this distinct from the vector's current or default size.
|
||||
* @param is_reserved_index A function to indicate whether a particular index should not be used
|
||||
* by a named sound
|
||||
*
|
||||
* @return @c true when a new entry has been parsed and should be added to the list of known
|
||||
* entries. @c false otherwise, for example in case of @c +nocreate
|
||||
*/
|
||||
bool gamesnd_parse_line(game_snd *gs, const char *tag, SCP_vector<game_snd> *lookupVector = NULL)
|
||||
bool gamesnd_parse_line(game_snd *gs, const char *tag, SCP_vector<game_snd> *lookupVector = nullptr, size_t lookupVectorMaxIndexableSize = 0, bool (*is_reserved_index)(int) = nullptr)
|
||||
{
|
||||
Assertion(gs != NULL, "Invalid game_snd pointer passed to gamesnd_parse_line!");
|
||||
|
||||
@@ -1016,7 +1116,7 @@ bool gamesnd_parse_line(game_snd *gs, const char *tag, SCP_vector<game_snd> *loo
|
||||
}
|
||||
}
|
||||
|
||||
gamesnd_parse_entry(gs, no_create, lookupVector);
|
||||
gamesnd_parse_entry(gs, no_create, lookupVector, lookupVectorMaxIndexableSize, is_reserved_index);
|
||||
|
||||
return !no_create;
|
||||
}
|
||||
@@ -1189,6 +1289,47 @@ void parse_sound_environments()
|
||||
required_string("#Sound Environments End");
|
||||
}
|
||||
|
||||
// indicate whether an index into Game Sounds is reserved for a built-in sound
|
||||
bool gamesnd_is_reserved_game_index(int index)
|
||||
{
|
||||
if (index >= 0 && index <= 161)
|
||||
return true;
|
||||
if (index >= 173 && index <= 191)
|
||||
return true;
|
||||
if (index == 200 || index == 201)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// indicate whether an index into Interface Sounds is reserved for a built-in sound
|
||||
bool gamesnd_is_reserved_interface_index(int index)
|
||||
{
|
||||
if (index >= 0 && index <= 64)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Finds an index that
|
||||
// 1) is just after the last index in lookupVector (i.e. equal to the size);
|
||||
// 2) does not correspond to a reserved index, as determined by the function.
|
||||
// If needed, empty game_snds are emplaced onto the vector until these conditions are true.
|
||||
int gamesnd_find_nonreserved_last_index(SCP_vector<game_snd>& lookupVector, bool (*is_reserved_index)(int))
|
||||
{
|
||||
int candidate_last_index = static_cast<int>(lookupVector.size());
|
||||
|
||||
// prevent new named sounds from colliding with reserved indexes
|
||||
while (is_reserved_index(candidate_last_index))
|
||||
{
|
||||
lookupVector.emplace_back();
|
||||
sprintf(lookupVector.back().name, "%d", candidate_last_index);
|
||||
candidate_last_index = static_cast<int>(lookupVector.size());
|
||||
}
|
||||
|
||||
return candidate_last_index;
|
||||
}
|
||||
|
||||
// Due to the cyclic depdendency between sounds and species, the parsing is now broken up into two stages.
|
||||
// First, just the sounds are parsed; and second, just the flyby sounds are parsed (or assigned).
|
||||
static bool Sound_table_first_stage = false;
|
||||
@@ -1210,9 +1351,19 @@ void parse_sound_table(const char* filename)
|
||||
while (!check_for_string("#Game Sounds End"))
|
||||
{
|
||||
game_snd tempSound;
|
||||
if (gamesnd_parse_line(&tempSound, "$Name:", &Snds))
|
||||
if (gamesnd_parse_line(&tempSound, "$Name:", &Snds, static_cast<size_t>(GameSounds::MIN_GAME_SOUNDS) * 2, gamesnd_is_reserved_game_index))
|
||||
{
|
||||
Snds.push_back(game_snd(tempSound));
|
||||
// if we are in this block, this is a new named sound that will be appended
|
||||
int tempIndex = static_cast<int>(Snds.size());
|
||||
|
||||
// retail sounds with numeric names must match their indexes
|
||||
if ((tempSound.flags & GAME_SND_RETAIL_STYLE) && (atoi(tempSound.name.c_str()) != tempIndex) && !gamesnd_is_placeholder(tempSound))
|
||||
error_display(0, "Retail-style sound %s has a name that does not match its index %d!", tempSound.name.c_str(), tempIndex);
|
||||
|
||||
// prevent new named sounds from colliding with reserved indexes
|
||||
tempIndex = gamesnd_find_nonreserved_last_index(Snds, gamesnd_is_reserved_game_index);
|
||||
|
||||
Snds.emplace_back(std::move(tempSound));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1230,10 +1381,19 @@ void parse_sound_table(const char* filename)
|
||||
while (!check_for_string("#Interface Sounds End"))
|
||||
{
|
||||
game_snd tempSound;
|
||||
if (gamesnd_parse_line(&tempSound, "$Name:", &Snds_iface))
|
||||
if (gamesnd_parse_line(&tempSound, "$Name:", &Snds_iface, static_cast<size_t>(InterfaceSounds::MIN_INTERFACE_SOUNDS) * 2, gamesnd_is_reserved_interface_index))
|
||||
{
|
||||
Snds_iface.push_back(game_snd(tempSound));
|
||||
Snds_iface_handle.push_back(sound_handle::invalid());
|
||||
// if we are in this block, this is a new named sound that will be appended
|
||||
int tempIndex = static_cast<int>(Snds_iface.size());
|
||||
|
||||
// retail sounds with numeric names must match their indexes
|
||||
if ((tempSound.flags & GAME_SND_RETAIL_STYLE) && (atoi(tempSound.name.c_str()) != tempIndex) && !gamesnd_is_placeholder(tempSound))
|
||||
error_display(0, "Retail-style sound %s has a name that does not match its index %d!", tempSound.name.c_str(), tempIndex);
|
||||
|
||||
// prevent new named sounds from colliding with reserved indexes
|
||||
tempIndex = gamesnd_find_nonreserved_last_index(Snds_iface, gamesnd_is_reserved_interface_index);
|
||||
|
||||
Snds_iface.emplace_back(std::move(tempSound));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1314,10 +1474,30 @@ void gamesnd_parse_soundstbl(bool first_stage)
|
||||
|
||||
parse_modular_table("*-snd.tbm", parse_sound_table);
|
||||
|
||||
if (!first_stage) {
|
||||
if (first_stage)
|
||||
{
|
||||
// these vectors should be the same size
|
||||
while (Snds_iface_handle.size() < Snds_iface.size())
|
||||
Snds_iface_handle.push_back(sound_handle::invalid());
|
||||
|
||||
// mark any placeholder sounds as invalid
|
||||
// (most places in the code already check for this, but it is possible for sexps and scripts to attempt to play an empty sound)
|
||||
for (auto& snd : Snds)
|
||||
if (gamesnd_is_placeholder(snd))
|
||||
snd.flags |= GAME_SND_NOT_VALID;
|
||||
|
||||
// ditto for interface sounds
|
||||
for (auto& snd : Snds_iface)
|
||||
if (gamesnd_is_placeholder(snd))
|
||||
snd.flags |= GAME_SND_NOT_VALID;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Set any flyby sounds for species that use the borrowed feature
|
||||
for (size_t i = 0; i < Species_info.size(); i++) {
|
||||
if (Species_info[i].borrows_flyby_sounds_species >= 0) {
|
||||
for (size_t i = 0; i < Species_info.size(); i++)
|
||||
{
|
||||
if (Species_info[i].borrows_flyby_sounds_species >= 0)
|
||||
{
|
||||
int idx = Species_info[i].borrows_flyby_sounds_species;
|
||||
Species_info[i].snd_flyby_fighter = Species_info[idx].snd_flyby_fighter;
|
||||
Species_info[i].snd_flyby_bomber = Species_info[idx].snd_flyby_bomber;
|
||||
@@ -1377,6 +1557,16 @@ bool gamesnd_game_sound_try_load(gamesnd_id sound)
|
||||
}
|
||||
auto gs = gamesnd_get_game_sound(sound);
|
||||
|
||||
// check flag the first time
|
||||
if (gs->flags & GAME_SND_NOT_VALID) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (gs->sound_entries.empty()) {
|
||||
gs->flags |= GAME_SND_NOT_VALID;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto& entry : gs->sound_entries) {
|
||||
if (!entry.id.isValid()) {
|
||||
// Lazily load unloaded sound entries when required
|
||||
@@ -1384,7 +1574,7 @@ bool gamesnd_game_sound_try_load(gamesnd_id sound)
|
||||
}
|
||||
}
|
||||
|
||||
// check flag
|
||||
// check flag again
|
||||
return (gs->flags & GAME_SND_NOT_VALID) == 0;
|
||||
}
|
||||
|
||||
@@ -1403,7 +1593,11 @@ float gamesnd_get_max_duration(game_snd* gs) {
|
||||
return max_length / gs->pitch_range.max();
|
||||
}
|
||||
game_snd_entry* gamesnd_choose_entry(game_snd* gs) {
|
||||
Assertion(!gs->sound_entries.empty(), "No sound entries found in game sound! This may not happen!");
|
||||
if (gs->sound_entries.empty()) {
|
||||
// This entire game_snd should have been skipped due to having the GAME_SND_NOT_VALID flag before we get to this function
|
||||
UNREACHABLE("No sound entries found in game sound %s! This may not happen!", gs->name.c_str());
|
||||
gs->sound_entries.emplace_back(); // add an empty entry so that we can return something; it will be invalid and will not be played
|
||||
}
|
||||
|
||||
size_t index = 0;
|
||||
switch(gs->cycle_type) {
|
||||
|
||||
+10
-3
@@ -237,6 +237,8 @@ enum class GameSounds {
|
||||
BALLISTIC_START_LOAD = 200,//!< (SCP)
|
||||
BALLISTIC_LOAD = 201,//!< (SCP)
|
||||
|
||||
// NOTE: If any other indexes become reserved, be sure to update gamesnd_is_reserved_game_index()
|
||||
|
||||
/**
|
||||
* Keep this below all defined enum values
|
||||
*/
|
||||
@@ -310,8 +312,10 @@ enum class InterfaceSounds {
|
||||
INTERFACE_UNDEFINED_60 =60,//!< vasudan hall - vasudan pa 3
|
||||
VASUDAN_BUP =61,//!< bup bup bup-bup bup bup
|
||||
INTERFACE_UNDEFINED_62 =62,//!< thankyou
|
||||
INTERFACE_UNDEFINED_63 =62,//!< vasudan hall - exit open
|
||||
INTERFACE_UNDEFINED_64 =62,//!< vasudan hall - exit close
|
||||
INTERFACE_UNDEFINED_63 =63,//!< vasudan hall - exit open
|
||||
INTERFACE_UNDEFINED_64 =64,//!< vasudan hall - exit close
|
||||
|
||||
// NOTE: If any other indexes become reserved, be sure to update gamesnd_is_reserved_interface_index()
|
||||
|
||||
/**
|
||||
* Keep this below all defined enum values
|
||||
@@ -319,7 +323,7 @@ enum class InterfaceSounds {
|
||||
MIN_INTERFACE_SOUNDS =70 //!< MIN_INTERFACE_SOUNDS
|
||||
};
|
||||
|
||||
// These two id types are defined as sublcasses so that type safe implicit conversions are possible from the predefined
|
||||
// These two id types are defined as subclasses so that type safe implicit conversions are possible from the predefined
|
||||
// sound enum values
|
||||
|
||||
struct gamesnd_id_tag{};
|
||||
@@ -352,6 +356,9 @@ class interface_snd_id : public util::ID<interface_snd_tag, int, -1> {
|
||||
}
|
||||
};
|
||||
|
||||
bool gamesnd_is_reserved_game_index(int index);
|
||||
bool gamesnd_is_reserved_interface_index(int index);
|
||||
|
||||
void gamesnd_parse_soundstbl(bool first_stage); // Loads in general game sounds from sounds.tbl
|
||||
void gamesnd_close(); // close out gamesnd... only call from game_shutdown()!
|
||||
void gamesnd_load_gameplay_sounds();
|
||||
|
||||
@@ -191,8 +191,8 @@ class flagset {
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool any_set() { return values.any(); }
|
||||
bool none_set() { return values.none(); }
|
||||
bool any_set() const { return values.any(); }
|
||||
bool none_set() const { return values.none(); }
|
||||
|
||||
void from_u64(std::uint64_t num) { values = (unsigned long) num; }
|
||||
|
||||
|
||||
@@ -72,6 +72,7 @@
|
||||
#define MAX_POLYGON_MODELS 300
|
||||
|
||||
// object.h
|
||||
//If this value exceeds 2^16-1, this will break collision pair caching as is. Proceed with caution.
|
||||
#define MAX_OBJECTS 5000 //Increased from 3500 to 5000 in 2022
|
||||
|
||||
// from weapon.h (and beam.h)
|
||||
|
||||
@@ -216,6 +216,11 @@ DWORD WINAPI SCP_mspdbcs_DumpStackThread( LPVOID pv )
|
||||
stackFrame.AddrPC.Offset = context.Rip;
|
||||
stackFrame.AddrStack.Offset = context.Rsp;
|
||||
stackFrame.AddrFrame.Offset = context.Rbp;
|
||||
#elif defined(_M_ARM64)
|
||||
dwMachType = IMAGE_FILE_MACHINE_ARM64;
|
||||
stackFrame.AddrPC.Offset = context.Pc;
|
||||
stackFrame.AddrStack.Offset = context.Sp;
|
||||
stackFrame.AddrFrame.Offset = context.Fp;
|
||||
#else
|
||||
# error UNKNOWN ARCHITECTURE
|
||||
#endif
|
||||
|
||||
@@ -99,6 +99,14 @@ struct ivec2 {
|
||||
int x, y;
|
||||
};
|
||||
|
||||
inline bool operator<(const ivec3& l, const ivec3& r){
|
||||
return l.x < r.x || (l.x == r.x && (l.y < r.y || (l.y == r.y && l.z < r.z)));
|
||||
}
|
||||
|
||||
inline bool operator<(const ivec2& l, const ivec2& r){
|
||||
return l.x < r.x || (l.x == r.x && l.y < r.y);
|
||||
}
|
||||
|
||||
namespace scripting {
|
||||
class ade_table_entry;
|
||||
}
|
||||
@@ -117,9 +125,6 @@ typedef struct vec3d {
|
||||
} xyz;
|
||||
float a1d[3];
|
||||
};
|
||||
|
||||
void serialize(lua_State* /*L*/, const scripting::ade_table_entry& /*tableEntry*/, const luacpp::LuaValue& value, ubyte* data, int& packet_size);
|
||||
void deserialize(lua_State* /*L*/, const scripting::ade_table_entry& /*tableEntry*/, char* data_ptr, ubyte* data, int& offset);
|
||||
} vec3d;
|
||||
|
||||
typedef struct vec2d {
|
||||
@@ -288,7 +293,7 @@ constexpr bool LoggingEnabled = false;
|
||||
// Disabling this functionality is dangerous, crazy values can run rampant unchecked, and the longer it's disabled
|
||||
// the more likely you are to have problems getting it working again.
|
||||
#if defined(NDEBUG)
|
||||
# define Assert(expr) do { ASSUME(expr); } while (false)
|
||||
# define Assert(expr) do { ASSUME(expr); (void)sizeof(expr); } while (false)
|
||||
#else
|
||||
# define Assert(expr) do {\
|
||||
if (!(expr)) {\
|
||||
@@ -442,7 +447,7 @@ public:
|
||||
class camera *getCamera();
|
||||
size_t getIndex();
|
||||
int getSignature();
|
||||
bool isValid();
|
||||
bool isValid() const;
|
||||
};
|
||||
|
||||
#include "globalincs/vmallocator.h"
|
||||
@@ -453,7 +458,7 @@ public:
|
||||
// - is not "none"
|
||||
// - is not "<none>"
|
||||
inline bool VALID_FNAME(const char* x) {
|
||||
return strlen((x)) && stricmp((x), "none") != 0 && stricmp((x), "<none>") != 0;
|
||||
return (x[0] != '\0') && stricmp(x, "none") != 0 && stricmp(x, "<none>") != 0;
|
||||
}
|
||||
/**
|
||||
* @brief Checks if the specified string may be a valid file name
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
#include "debugconsole/console.h"
|
||||
#include "globalincs/pstypes.h"
|
||||
#include "graphics/2d.h"
|
||||
#include "io/timer.h"
|
||||
#include "nebula/neb.h"
|
||||
#include "options/Option.h"
|
||||
|
||||
@@ -34,12 +33,6 @@ float Cutscene_delta_time = 1.0f;
|
||||
//How far along a change is (0 to 1)
|
||||
float Cutscene_bars_progress = 1.0f;
|
||||
|
||||
//FADEIN STUFF
|
||||
shader Viewer_shader;
|
||||
FadeType Fade_type = FI_NONE;
|
||||
int Fade_start_timestamp = 0;
|
||||
int Fade_end_timestamp = 0;
|
||||
|
||||
// The detail level. Anything below zero draws simple models earlier than it
|
||||
// should. Anything above zero draws higher detail models longer than it should.
|
||||
// -2=lowest
|
||||
@@ -246,54 +239,57 @@ detail_levels Detail_defaults[NUM_DEFAULT_DETAIL_LEVELS] = {
|
||||
detail_levels Detail = Detail_defaults[NUM_DEFAULT_DETAIL_LEVELS - 1];
|
||||
|
||||
const SCP_vector<std::pair<int, std::pair<const char*, int>>> DetailLevelValues = {{ 0, {"Minimum", 1680}},
|
||||
{ 1, {"Low", 1161}},
|
||||
{ 2, {"Medium", 1162}},
|
||||
{ 3, {"High", 1163}},
|
||||
{ 1, {"Low", 1160}},
|
||||
{ 2, {"Medium", 1161}},
|
||||
{ 3, {"High", 1162}},
|
||||
{ 4, {"Ultra", 1721}}};
|
||||
|
||||
const auto ModelDetailOption __UNUSED = options::OptionBuilder<int>("Graphics.Detail",
|
||||
std::pair<const char*, int>{"Model Detail", 1739},
|
||||
std::pair<const char*, int>{"Detail level of models", 1740})
|
||||
.importance(8)
|
||||
.category("Graphics")
|
||||
.category(std::make_pair("Graphics", 1825))
|
||||
.values(DetailLevelValues)
|
||||
.default_val(MAX_DETAIL_LEVEL)
|
||||
.change_listener([](int val, bool) {
|
||||
Detail.detail_distance = val;
|
||||
return true;
|
||||
})
|
||||
.flags({options::OptionFlags::RetailBuiltinOption})
|
||||
.finish();
|
||||
|
||||
const auto TexturesOption __UNUSED = options::OptionBuilder<int>("Graphics.Texture",
|
||||
std::pair<const char*, int>{"3D Hardware Textures", 1362},
|
||||
std::pair<const char*, int>{"Level of detail of textures", 1720})
|
||||
.importance(6)
|
||||
.category("Graphics")
|
||||
.category(std::make_pair("Graphics", 1825))
|
||||
.values(DetailLevelValues)
|
||||
.default_val(MAX_DETAIL_LEVEL)
|
||||
.change_listener([](int val, bool) {
|
||||
Detail.hardware_textures = val;
|
||||
return true;
|
||||
})
|
||||
.flags({options::OptionFlags::RetailBuiltinOption})
|
||||
.finish();
|
||||
|
||||
const auto ParticlesOption __UNUSED = options::OptionBuilder<int>("Graphics.Particles",
|
||||
std::pair<const char*, int>{"Particles", 1363},
|
||||
std::pair<const char*, int>{"Level of detail for particles", 1717})
|
||||
.importance(5)
|
||||
.category("Graphics")
|
||||
.category(std::make_pair("Graphics", 1825))
|
||||
.values(DetailLevelValues)
|
||||
.default_val(MAX_DETAIL_LEVEL)
|
||||
.change_listener([](int val, bool) {
|
||||
Detail.num_particles = val;
|
||||
return true;
|
||||
})
|
||||
.flags({options::OptionFlags::RetailBuiltinOption})
|
||||
.finish();
|
||||
|
||||
const auto SmallDebrisOption __UNUSED = options::OptionBuilder<int>("Graphics.SmallDebris",
|
||||
std::pair<const char*, int>{"Impact Effects", 1364},
|
||||
std::pair<const char*, int>{"Level of detail of impact effects", 1743})
|
||||
.category("Graphics")
|
||||
.category(std::make_pair("Graphics", 1825))
|
||||
.values(DetailLevelValues)
|
||||
.default_val(MAX_DETAIL_LEVEL)
|
||||
.importance(4)
|
||||
@@ -301,32 +297,35 @@ const auto SmallDebrisOption __UNUSED = options::OptionBuilder<int>("Graphics.Sm
|
||||
Detail.num_small_debris = val;
|
||||
return true;
|
||||
})
|
||||
.flags({options::OptionFlags::RetailBuiltinOption})
|
||||
.finish();
|
||||
|
||||
const auto ShieldEffectsOption __UNUSED = options::OptionBuilder<int>("Graphics.ShieldEffects",
|
||||
std::pair<const char*, int>{"Shield Hit Effects", 1718},
|
||||
std::pair<const char*, int>{"Level of detail of shield impacts", 1719})
|
||||
.importance(3)
|
||||
.category("Graphics")
|
||||
.category(std::make_pair("Graphics", 1825))
|
||||
.values(DetailLevelValues)
|
||||
.default_val(MAX_DETAIL_LEVEL)
|
||||
.change_listener([](int val, bool) {
|
||||
Detail.shield_effects = val;
|
||||
return true;
|
||||
})
|
||||
.flags({options::OptionFlags::RetailBuiltinOption})
|
||||
.finish();
|
||||
|
||||
const auto StarsOption __UNUSED = options::OptionBuilder<int>("Graphics.Stars",
|
||||
std::pair<const char*, int>{"Stars", 1366},
|
||||
std::pair<const char*, int>{"Number of stars in the mission", 1698})
|
||||
.importance(2)
|
||||
.category("Graphics")
|
||||
.category(std::make_pair("Graphics", 1825))
|
||||
.values(DetailLevelValues)
|
||||
.default_val(MAX_DETAIL_LEVEL)
|
||||
.change_listener([](int val, bool) {
|
||||
Detail.num_stars = val;
|
||||
return true;
|
||||
})
|
||||
.flags({options::OptionFlags::RetailBuiltinOption})
|
||||
.finish();
|
||||
|
||||
// Call this with:
|
||||
|
||||
@@ -59,19 +59,6 @@
|
||||
extern float Cutscene_bars_progress, Cutscene_delta_time;
|
||||
extern int Cutscene_bar_flags;
|
||||
|
||||
//-----Fadein stuff
|
||||
struct shader;
|
||||
extern shader Viewer_shader;
|
||||
|
||||
enum FadeType {
|
||||
FI_NONE,
|
||||
FI_FADEIN,
|
||||
FI_FADEOUT
|
||||
};
|
||||
extern FadeType Fade_type;
|
||||
extern int Fade_start_timestamp;
|
||||
extern int Fade_end_timestamp;
|
||||
|
||||
|
||||
typedef struct vei {
|
||||
angles_t angles; // Angles defining viewer location.
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
#define ASSUME(x)
|
||||
|
||||
#if defined(NDEBUG)
|
||||
# define Assertion(expr, msg, ...) do { } while (false)
|
||||
# define Assertion(expr, msg, ...) do { (void)sizeof(expr); } while (false)
|
||||
#else
|
||||
/*
|
||||
* NOTE: Assertion() can only use its proper functionality in compilers
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
#define ASSUME(x)
|
||||
|
||||
#if defined(NDEBUG)
|
||||
# define Assertion(expr, msg, ...) do {} while (false)
|
||||
# define Assertion(expr, msg, ...) do { (void)sizeof(expr); } while (false)
|
||||
#else
|
||||
/*
|
||||
* NOTE: Assertion() can only use its proper functionality in compilers
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
#define ASSUME(x)
|
||||
|
||||
#if defined(NDEBUG)
|
||||
# define Assertion(expr, msg, ...) do {} while (false)
|
||||
# define Assertion(expr, msg, ...) do { (void)sizeof(expr); } while (false)
|
||||
#else
|
||||
/*
|
||||
* NOTE: Assertion() can only use its proper functionality in compilers
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
#define ASSUME(x)
|
||||
|
||||
#if defined(NDEBUG)
|
||||
# define Assertion(expr, msg, ...) do { ASSUME(expr); } while (false)
|
||||
# define Assertion(expr, msg, ...) do { ASSUME(expr); (void)sizeof(expr); } while (false)
|
||||
#else
|
||||
# define Assertion(expr, msg, ...) \
|
||||
do { \
|
||||
|
||||
@@ -27,7 +27,7 @@ void Undo_system::clamp_stacks() {
|
||||
// This while() shouldn't ever be triggered, but this is a safety to prevent any weird edge-cases.
|
||||
while (redo_stack.size() > max_undos) {
|
||||
delete redo_stack.front();
|
||||
undo_stack.pop_front();
|
||||
redo_stack.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loaded 100 of 1154 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user