Compare commits
1402 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
33abd1b4e7 | ||
|
|
a16fcd8d6a | ||
|
|
6a12033942 | ||
|
|
a04a84e00b | ||
|
|
abe6c22f56 | ||
|
|
232a45c9ac | ||
|
|
29383a6a11 | ||
|
|
669c8c8988 | ||
|
|
9bd80324d1 | ||
|
|
4b747e567a | ||
|
|
27ddca26c2 | ||
|
|
b67a087448 | ||
|
|
6df0cb1ddb | ||
|
|
320624edc8 | ||
|
|
8cbdf27228 | ||
|
|
145af411ab | ||
|
|
07a1339704 | ||
|
|
0df6fbb30a | ||
|
|
a1c241af37 | ||
|
|
c5c887cc11 | ||
|
|
453f8c05a4 | ||
|
|
47c23ba917 | ||
|
|
a404689e50 | ||
|
|
c6f9bbce8e | ||
|
|
07778c81bc | ||
|
|
5b0c8fb3e2 | ||
|
|
355c260bf2 | ||
|
|
764762f236 | ||
|
|
eeacbfeb6a | ||
|
|
9a7b469f4e | ||
|
|
2be8fcfa64 | ||
|
|
e865e65955 | ||
|
|
8ef1e29a5c | ||
|
|
2a69f34f93 | ||
|
|
6d1d60f699 | ||
|
|
7a80acf6a1 | ||
|
|
b2daa0e502 | ||
|
|
915888d275 | ||
|
|
a94812b28d | ||
|
|
8de1ffb84d | ||
|
|
b7db2a12d4 | ||
|
|
cc9398df14 | ||
|
|
9187873396 | ||
|
|
d750a1101b | ||
|
|
f87f14b432 | ||
|
|
e1286fcb04 | ||
|
|
800ab92960 | ||
|
|
c8492ab5e0 | ||
|
|
5f7de20cde | ||
|
|
d4a2113a8a | ||
|
|
a5ec7a45db | ||
|
|
abbfb09a64 | ||
|
|
38f4ea7aa3 | ||
|
|
e9a61ca38c | ||
|
|
b89dd7f0e3 | ||
|
|
ef0ba763b9 | ||
|
|
ceb65eafa5 | ||
|
|
381d0b4e3e | ||
|
|
3cbf84f98b | ||
|
|
5cb1c8580d | ||
|
|
6110f74ad6 | ||
|
|
09f693b9b9 | ||
|
|
285fee01f2 | ||
|
|
d81890f6a8 | ||
|
|
c52aebe8e7 | ||
|
|
e500b77cd3 | ||
|
|
f86bdb2cdb | ||
|
|
d4ce6bcde0 | ||
|
|
e33b56b49a | ||
|
|
3779a39f1f | ||
|
|
e0be6beb18 | ||
|
|
7c80093efa | ||
|
|
b683c047dc | ||
|
|
fe51abd534 | ||
|
|
80b7d52eeb | ||
|
|
0256790e1c | ||
|
|
6b958b957e | ||
|
|
fe1e1ec8c7 | ||
|
|
8b7f469ae1 | ||
|
|
7d5b1e6c2e | ||
|
|
811729ab41 | ||
|
|
11f2d941f1 | ||
|
|
aa104bb0aa | ||
|
|
071dbc3086 | ||
|
|
6ad85725d9 | ||
|
|
239367663b | ||
|
|
9c40489589 | ||
|
|
a401f926d3 | ||
|
|
ef0b5f857d | ||
|
|
c168786b42 | ||
|
|
aed313d81c | ||
|
|
c8623cfe09 | ||
|
|
0e5ffb8c34 | ||
|
|
2d41405e29 | ||
|
|
32fe837dca | ||
|
|
5ceb3aedeb | ||
|
|
843b43001a | ||
|
|
d3e7ab933d | ||
|
|
a9798d0645 | ||
|
|
136b25133d | ||
|
|
71e0895dc6 | ||
|
|
51ba90dd52 | ||
|
|
eda2c05448 | ||
|
|
2120d4d3ce | ||
|
|
01c70dfb76 | ||
|
|
296e7ed9ad | ||
|
|
a13089cd2e | ||
|
|
597802ff2e | ||
|
|
5c562c3adc | ||
|
|
dff327df40 | ||
|
|
ba07534d99 | ||
|
|
c707f92d0a | ||
|
|
a9604a88c2 | ||
|
|
d4175c5315 | ||
|
|
6b4b11d80e | ||
|
|
dc4ee41b70 | ||
|
|
16ff379ebe | ||
|
|
e2014cfd92 | ||
|
|
2c4a3b5f5e | ||
|
|
2526503743 | ||
|
|
7374fbf54c | ||
|
|
e0ecbeee39 | ||
|
|
79856dac25 | ||
|
|
8641e9d0bb | ||
|
|
e73e965d5b | ||
|
|
4e40c6f2ed | ||
|
|
0c55f331cf | ||
|
|
176cadff05 | ||
|
|
076b324539 | ||
|
|
cd0a765f66 | ||
|
|
2633295ada | ||
|
|
dc28d52d08 | ||
|
|
76f2191476 | ||
|
|
bcb5b4f94d | ||
|
|
d7e764d519 | ||
|
|
d6fbf9fbe7 | ||
|
|
c7e05c74b9 | ||
|
|
ab03fbb6c8 | ||
|
|
9ed94f310a | ||
|
|
77f692c669 | ||
|
|
97aeb85d84 | ||
|
|
f4894952fc | ||
|
|
2f92ccecb1 | ||
|
|
8e2ed40f66 | ||
|
|
9ba2f7d43c | ||
|
|
7d1cfe50af | ||
|
|
dec09bde1c | ||
|
|
9deabc7b60 | ||
|
|
495a447c8a | ||
|
|
25075decb2 | ||
|
|
1b178a55d7 | ||
|
|
e30e1ccccd | ||
|
|
6bdfb0d386 | ||
|
|
26e5a7eed1 | ||
|
|
4b4aefe339 | ||
|
|
042284de8b | ||
|
|
c48f6e9bda | ||
|
|
435b8fe52e | ||
|
|
3441714a13 | ||
|
|
5fe04940be | ||
|
|
854ee12d9d | ||
|
|
5ddd0649e3 | ||
|
|
886650a887 | ||
|
|
747ae04279 | ||
|
|
f4e723e690 | ||
|
|
0db14d718c | ||
|
|
fd52285074 | ||
|
|
eadf0496bf | ||
|
|
4a5f7464c1 | ||
|
|
39d2c427e5 | ||
|
|
958e2f36bb | ||
|
|
ba859dc3b5 | ||
|
|
3a95c77c9e | ||
|
|
df89e5091e | ||
|
|
81c6c5e47a | ||
|
|
b7c7c883d7 | ||
|
|
4141caa4d6 | ||
|
|
0a2df3ca4c | ||
|
|
8759c2edf0 | ||
|
|
92c5cf1877 | ||
|
|
43fbf297c8 | ||
|
|
033d89a9ab | ||
|
|
f1545daeae | ||
|
|
ec22576e49 | ||
|
|
9a1b826021 | ||
|
|
4f8993e19b | ||
|
|
2ef43e8d1a | ||
|
|
ce78081a7f | ||
|
|
6c2d179aad | ||
|
|
b99edf9a6b | ||
|
|
cb35f78511 | ||
|
|
2eb0390dc9 | ||
|
|
f131f70761 | ||
|
|
68c37d2d88 | ||
|
|
80dc23621e | ||
|
|
b289bb4edb | ||
|
|
2c79080e1b | ||
|
|
75f812cfcd | ||
|
|
463fdab6a4 | ||
|
|
d7a28c4d2b | ||
|
|
0544beb00d | ||
|
|
1f98f01dcb | ||
|
|
8ea411e4c5 | ||
|
|
ab5965cc8d | ||
|
|
858f913fac | ||
|
|
e042ba6f24 | ||
|
|
4b7dc08bf5 | ||
|
|
c851d9a6ba | ||
|
|
3869369703 | ||
|
|
2ee32abf84 | ||
|
|
c5af250959 | ||
|
|
42ad9c4378 | ||
|
|
26a9ac91ee | ||
|
|
76a22c0d13 | ||
|
|
f887d515fa | ||
|
|
729ef37040 | ||
|
|
e17504a36a | ||
|
|
4673f509f6 | ||
|
|
35dd465c19 | ||
|
|
7b9d8c5a1f | ||
|
|
8d9508bda4 | ||
|
|
bd96584433 | ||
|
|
68db861c45 | ||
|
|
873840a6a5 | ||
|
|
947f67dfb7 | ||
|
|
478bdcc1ca | ||
|
|
63046894b0 | ||
|
|
74f00c3c63 | ||
|
|
668311a444 | ||
|
|
15f770531c | ||
|
|
88b4c7b50b | ||
|
|
9cc1201892 | ||
|
|
e6b1a0691b | ||
|
|
0c4ab5b609 | ||
|
|
2672504e8a | ||
|
|
a7e86e0510 | ||
|
|
827f0ffbb6 | ||
|
|
883e8390c9 | ||
|
|
c69edce800 | ||
|
|
747705d430 | ||
|
|
e947081622 | ||
|
|
621f941ff7 | ||
|
|
1cfd4f741e | ||
|
|
bec1cbc1cb | ||
|
|
4f461bd7be | ||
|
|
80d00fe31a | ||
|
|
6fbb7da82d | ||
|
|
5a22896197 | ||
|
|
8bcbee4ea7 | ||
|
|
5999ddc76d | ||
|
|
0338d4c393 | ||
|
|
4a047f56bc | ||
|
|
09748d094a | ||
|
|
ae1deb2209 | ||
|
|
cb5586e658 | ||
|
|
865ce46fdb | ||
|
|
2b99f2634b | ||
|
|
6d7dec96af | ||
|
|
418bf3ab69 | ||
|
|
192190769d | ||
|
|
1479093d33 | ||
|
|
70080f1fdb | ||
|
|
0542b1bd4d | ||
|
|
e80cbf8bb2 | ||
|
|
a481b900b9 | ||
|
|
d923cd2f24 | ||
|
|
835fa4e74b | ||
|
|
bf035b8167 | ||
|
|
232b5a04ba | ||
|
|
9d25e7f315 | ||
|
|
e8dcc8432d | ||
|
|
3f3e258d77 | ||
|
|
3c5bae164f | ||
|
|
30061396e8 | ||
|
|
b77d93ba4a | ||
|
|
7bacf3b6f4 | ||
|
|
cce97588fe | ||
|
|
6cea1de9e6 | ||
|
|
81673ab304 | ||
|
|
04126cd18a | ||
|
|
2aa37813d2 | ||
|
|
92679555b9 | ||
|
|
8960ffaf0b | ||
|
|
7adc85995f | ||
|
|
61176acbad | ||
|
|
98003d0d41 | ||
|
|
49ee711c75 | ||
|
|
029e315f0a | ||
|
|
16f892b667 | ||
|
|
f82c3c8ea7 | ||
|
|
9dbaa7a77f | ||
|
|
d0666a8702 | ||
|
|
16e2e3d091 | ||
|
|
fbb42085bd | ||
|
|
7aa8d7c073 | ||
|
|
c4f5cbce5e | ||
|
|
c26a57fb9f | ||
|
|
ad2ccdb44a | ||
|
|
782d38c6b7 | ||
|
|
5240dce018 | ||
|
|
1eedf7f0ae | ||
|
|
ec7d702185 | ||
|
|
6dc8c5bd92 | ||
|
|
55e83982c3 | ||
|
|
388dd5cb00 | ||
|
|
0461a36a4e | ||
|
|
9e374491c5 | ||
|
|
d77ed4608f | ||
|
|
c0488b3190 | ||
|
|
1180f32d9c | ||
|
|
371f1be9b3 | ||
|
|
250727c9ca | ||
|
|
f7a2c265b3 | ||
|
|
f19a1aebd4 | ||
|
|
bc3734cae3 | ||
|
|
cafc0f3c10 | ||
|
|
123f2fda9b | ||
|
|
1aac4d802f | ||
|
|
f73dfa12e6 | ||
|
|
6a94299eac | ||
|
|
ed9c911a0e | ||
|
|
a064b3a687 | ||
|
|
a510a03b8a | ||
|
|
c234cb4663 | ||
|
|
c7d3b88cb7 | ||
|
|
bf4b39781b | ||
|
|
d83b8cf940 | ||
|
|
5032d24ad8 | ||
|
|
601f63f4fb | ||
|
|
1619d2395e | ||
|
|
b69222e017 | ||
|
|
d86637daea | ||
|
|
dc729009ac | ||
|
|
bf757fc960 | ||
|
|
a7e673c2ec | ||
|
|
3adf37a3a9 | ||
|
|
aec797671e | ||
|
|
bd3c3849fe | ||
|
|
cc13e31264 | ||
|
|
1d1f10d68c | ||
|
|
5e34b1efcf | ||
|
|
953e4fc4ff | ||
|
|
bbbe9b2632 | ||
|
|
a1444b992f | ||
|
|
76558e9313 | ||
|
|
a437d2bc26 | ||
|
|
7a034142c9 | ||
|
|
d0404cbdb7 | ||
|
|
c937bdbfea | ||
|
|
cb7f18f268 | ||
|
|
0a23afebb7 | ||
|
|
8018e40ebf | ||
|
|
ec5a07b049 | ||
|
|
c8cb1ed013 | ||
|
|
026a2b3f1f | ||
|
|
780cd225e9 | ||
|
|
2ce36a48b9 | ||
|
|
3377709c4b | ||
|
|
17fca82401 | ||
|
|
02c4ada807 | ||
|
|
4f78733836 | ||
|
|
81aece7117 | ||
|
|
fb5a207abc | ||
|
|
d2e594db2b | ||
|
|
894495689f | ||
|
|
7f544f9049 | ||
|
|
6665b16ba2 | ||
|
|
207378c947 | ||
|
|
a7b38e1b34 | ||
|
|
5cab196718 | ||
|
|
3bde84f6c8 | ||
|
|
a99a04ed49 | ||
|
|
b09b489ae7 | ||
|
|
a247d53367 | ||
|
|
ca5d3c8811 | ||
|
|
02ec56e8f7 | ||
|
|
6da20aa723 | ||
|
|
28f266302f | ||
|
|
523b23339c | ||
|
|
c982700a69 | ||
|
|
6f0f9d7d69 | ||
|
|
b69cee3801 | ||
|
|
a4b92fe9be | ||
|
|
6c097398d1 | ||
|
|
91d958bf27 | ||
|
|
bef07b6353 | ||
|
|
2f7ae611ed | ||
|
|
f50026828a | ||
|
|
55d30a11ec | ||
|
|
ac3905123e | ||
|
|
3f5fdc39a5 | ||
|
|
b4364c3672 | ||
|
|
3515363df5 | ||
|
|
6f52ad190e | ||
|
|
c0cbf8045f | ||
|
|
02e84b4b97 | ||
|
|
a8fd3f828a | ||
|
|
291213ed40 | ||
|
|
2a6f9c2757 | ||
|
|
dc29e7c044 | ||
|
|
11434f96cc | ||
|
|
776d46aacb | ||
|
|
f686065769 | ||
|
|
3194fdb2c1 | ||
|
|
58de524d70 | ||
|
|
d7ceb4870c | ||
|
|
8a114514d9 | ||
|
|
9f0a96ac89 | ||
|
|
e9baf31ad8 | ||
|
|
d82dbf91ef | ||
|
|
db4ae18e5d | ||
|
|
5458632c40 | ||
|
|
ab73c2f539 | ||
|
|
12efd1209b | ||
|
|
33c45e4ae0 | ||
|
|
011aafa043 | ||
|
|
6f103a3b82 | ||
|
|
61c2398b67 | ||
|
|
71f28c8cf5 | ||
|
|
6a2ce20313 | ||
|
|
41f3d4d9d7 | ||
|
|
71d1b46417 | ||
|
|
df8ef2d58d | ||
|
|
4981fe3091 | ||
|
|
4eb9a149e4 | ||
|
|
f09da45823 | ||
|
|
ddf2b09e55 | ||
|
|
d824a321b9 | ||
|
|
026cd10f3f | ||
|
|
9a68f94c54 | ||
|
|
a7ab4cc23a | ||
|
|
5b390ade40 | ||
|
|
f184c43b9b | ||
|
|
ffe199290b | ||
|
|
37b6d491e7 | ||
|
|
0b269571d7 | ||
|
|
e2ae17d994 | ||
|
|
d781db6c0f | ||
|
|
7a1ff3b2ad | ||
|
|
72f6780905 | ||
|
|
47f153fe76 | ||
|
|
79c010f082 | ||
|
|
f9a2f1daf7 | ||
|
|
e6544a6983 | ||
|
|
dadc56ccf9 | ||
|
|
37a43ebf45 | ||
|
|
c5e896c420 | ||
|
|
164623d58e | ||
|
|
386b113603 | ||
|
|
0b27a3dc23 | ||
|
|
8916fe1820 | ||
|
|
74fd58513b | ||
|
|
ab7513cc85 | ||
|
|
2029ac3d62 | ||
|
|
6edb8d9610 | ||
|
|
62425b5866 | ||
|
|
10d7b303a5 | ||
|
|
52e4cd19ce | ||
|
|
70876d3cde | ||
|
|
3750124dcc | ||
|
|
1d51734d0b | ||
|
|
5d5e0f62e8 | ||
|
|
ec45ba68cd | ||
|
|
77f31105de | ||
|
|
3ed4cdf109 | ||
|
|
3136ce6451 | ||
|
|
a92dcaa0b1 | ||
|
|
060c1181bc | ||
|
|
be6e273930 | ||
|
|
1c0878f65b | ||
|
|
43631ba203 | ||
|
|
f9f854c4a8 | ||
|
|
63d9d9c148 | ||
|
|
51042e15aa | ||
|
|
a8549e86a7 | ||
|
|
424a6d90bd | ||
|
|
70fa7fc239 | ||
|
|
4eea98c66b | ||
|
|
10cc444482 | ||
|
|
987e09515b | ||
|
|
9ea3549743 | ||
|
|
ae4bfef590 | ||
|
|
7df71c9673 | ||
|
|
8e6e46a919 | ||
|
|
65219365db | ||
|
|
f7816c577f | ||
|
|
3988fec6e7 | ||
|
|
de64bbe875 | ||
|
|
b8e80a67ea | ||
|
|
2d38eb923d | ||
|
|
2071abd295 | ||
|
|
dd790b00e5 | ||
|
|
cb72fee941 | ||
|
|
a3964dfd4a | ||
|
|
138abb91f6 | ||
|
|
a73a2c9179 | ||
|
|
b1c9340fd3 | ||
|
|
abe57fefa0 | ||
|
|
3383d8c6e7 | ||
|
|
d31a7e24a8 | ||
|
|
cac1c5bd42 | ||
|
|
9f0daee186 | ||
|
|
de4699a97e | ||
|
|
fdbd414299 | ||
|
|
22e8e0eff8 | ||
|
|
d17d437de3 | ||
|
|
cb3b3855b8 | ||
|
|
1c5a864598 | ||
|
|
eaebaa6db3 | ||
|
|
f8297df9c5 | ||
|
|
3e9c983f5c | ||
|
|
cc235be3aa | ||
|
|
53a4b6936b | ||
|
|
091a65996e | ||
|
|
73e112a217 | ||
|
|
879761af2c | ||
|
|
c7243aa2e9 | ||
|
|
3587cb029e | ||
|
|
883d8172b0 | ||
|
|
a923728877 | ||
|
|
05a29c7e6c | ||
|
|
ab38b0089e | ||
|
|
4819d195d8 | ||
|
|
f3a931e1c9 | ||
|
|
090fa619b4 | ||
|
|
2c92accb8e | ||
|
|
9c8ef3cca0 | ||
|
|
107c4df69c | ||
|
|
636f67ca3f | ||
|
|
d4ba7c387b | ||
|
|
831737ecc8 | ||
|
|
9ab4f1a2d9 | ||
|
|
171d9fd036 | ||
|
|
d8f5e86ede | ||
|
|
036eff2c48 | ||
|
|
85d60b36da | ||
|
|
fff899ec16 | ||
|
|
225530ef04 | ||
|
|
6cb8c11285 | ||
|
|
3092b9a46e | ||
|
|
9b5caa190e | ||
|
|
af7573ddbe | ||
|
|
ebd980bf14 | ||
|
|
c869602b6d | ||
|
|
4bab6d5356 | ||
|
|
2b67aba94c | ||
|
|
9382e86d38 | ||
|
|
0b057f34c9 | ||
|
|
6152f02333 | ||
|
|
8a5afd0db2 | ||
|
|
4e3fc35401 | ||
|
|
84fb48825d | ||
|
|
940d6bf6d3 | ||
|
|
5341840943 | ||
|
|
a83ecc123d | ||
|
|
a3ae267e83 | ||
|
|
f46461331c | ||
|
|
1f082a85cb | ||
|
|
4660491243 | ||
|
|
7e7a2b74cd | ||
|
|
e671fe682d | ||
|
|
e5aa150557 | ||
|
|
14c71f39ff | ||
|
|
1254c1202a | ||
|
|
74867af2e7 | ||
|
|
3ebc475494 | ||
|
|
27df328ec2 | ||
|
|
4351198bf5 | ||
|
|
7c3457257b | ||
|
|
ba23408007 | ||
|
|
eaaba8646b | ||
|
|
0910188058 | ||
|
|
3cc9eb1c1c | ||
|
|
db1c7de125 | ||
|
|
7a351f18ba | ||
|
|
776e8ff2ee | ||
|
|
3aac4ea62a | ||
|
|
1558788df1 | ||
|
|
29d47da61e | ||
|
|
e014bb5359 | ||
|
|
fb03ee45b5 | ||
|
|
60bb16d26c | ||
|
|
b5bc3a9000 | ||
|
|
f34365dfc0 | ||
|
|
1fa0116f5f | ||
|
|
c7821635fd | ||
|
|
0c3ee871f4 | ||
|
|
714cd47db9 | ||
|
|
008f8a1e19 | ||
|
|
499b16678f | ||
|
|
0682cdedbd | ||
|
|
1471c82a20 | ||
|
|
b8cf8c53e7 | ||
|
|
5156626582 | ||
|
|
fe65f20a30 | ||
|
|
4b8b0a6d74 | ||
|
|
0f0cb40151 | ||
|
|
2b8ae07ec6 | ||
|
|
1b5dbc4b41 | ||
|
|
6426963807 | ||
|
|
23755fdfb4 | ||
|
|
793e1223de | ||
|
|
fad64667a7 | ||
|
|
6e4a2947ea | ||
|
|
f2c8522daa | ||
|
|
93e9929925 | ||
|
|
be019c6126 | ||
|
|
02655313e9 | ||
|
|
59ed4d0029 | ||
|
|
42e655b4cc | ||
|
|
5bcdb933a7 | ||
|
|
bd94c16e78 | ||
|
|
618d689dff | ||
|
|
5c1af537af | ||
|
|
a446dbefaa | ||
|
|
2592da2273 | ||
|
|
b90784da90 | ||
|
|
f741101e44 | ||
|
|
cacec36dd1 | ||
|
|
f2390deaa9 | ||
|
|
8fc99387f5 | ||
|
|
939d0c59a3 | ||
|
|
edc25a689f | ||
|
|
68b5270fe4 | ||
|
|
a11bf19b93 | ||
|
|
2ad3a75be5 | ||
|
|
50058371ef | ||
|
|
ce0a097392 | ||
|
|
1e084dfab7 | ||
|
|
5a55d3a949 | ||
|
|
7a2dbd9112 | ||
|
|
c9804510d1 | ||
|
|
c37f4c3c1a | ||
|
|
319bf9d8d2 | ||
|
|
786e101acf | ||
|
|
596e12b897 | ||
|
|
4a9d890ae9 | ||
|
|
873c4fc81e | ||
|
|
f518676b76 | ||
|
|
0f6583560d | ||
|
|
6537dfe7f1 | ||
|
|
f2b59f5097 | ||
|
|
8ae4859398 | ||
|
|
c4f231deb4 | ||
|
|
c58d98a39e | ||
|
|
77ca9c593f | ||
|
|
8488dc791a | ||
|
|
19dd95a1cb | ||
|
|
3596897961 | ||
|
|
288c3dfc8f | ||
|
|
0c41734c20 | ||
|
|
bd70540b53 | ||
|
|
3a7cb9c5ce | ||
|
|
247974afd3 | ||
|
|
8a728faeb6 | ||
|
|
fdb6428c6b | ||
|
|
2fc431d1bb | ||
|
|
4e79d53661 | ||
|
|
fc1bfcbc21 | ||
|
|
8f54093de1 | ||
|
|
4da733145e | ||
|
|
3dda658e42 | ||
|
|
1817727a66 | ||
|
|
519218572a | ||
|
|
f6f8a24335 | ||
|
|
62b8f0f553 | ||
|
|
ceb22d71dd | ||
|
|
97008905b6 | ||
|
|
6122f6980b | ||
|
|
7c42ed6edb | ||
|
|
ce604c77ba | ||
|
|
df1ad8e122 | ||
|
|
82245789ed | ||
|
|
931bc690cd | ||
|
|
d2b5a422e4 | ||
|
|
087174c6a6 | ||
|
|
a311f643f9 | ||
|
|
9fce8636b0 | ||
|
|
c5303c2ea4 | ||
|
|
49b3bf5f2e | ||
|
|
478f6e07d4 | ||
|
|
f6910d35f7 | ||
|
|
5bdbb5f802 | ||
|
|
b01d6be3f4 | ||
|
|
59c9ae29cf | ||
|
|
82ebd8aae1 | ||
|
|
d506f8588c | ||
|
|
a3f1601fd1 | ||
|
|
1d336d851d | ||
|
|
620155ac8d | ||
|
|
71cf666bbd | ||
|
|
040c6f9027 | ||
|
|
14dcd8f04c | ||
|
|
b88cf7b939 | ||
|
|
9a7fa47857 | ||
|
|
111ccf5d34 | ||
|
|
0b1d3669bc | ||
|
|
8128e8e817 | ||
|
|
60bc816af5 | ||
|
|
73fce903b8 | ||
|
|
3d5f0ef318 | ||
|
|
b52356f6b5 | ||
|
|
139c6bfcf3 | ||
|
|
c274c05ce3 | ||
|
|
53631f97db | ||
|
|
006254fc9c | ||
|
|
bf7280b55b | ||
|
|
dfa0c8bf19 | ||
|
|
82322293fe | ||
|
|
4eea06e620 | ||
|
|
781617d484 | ||
|
|
48cec4a786 | ||
|
|
946be081b0 | ||
|
|
11bc8ea602 | ||
|
|
6245a17e16 | ||
|
|
1402b9ed72 | ||
|
|
3457ff48ce | ||
|
|
253021866c | ||
|
|
146ad3b4a1 | ||
|
|
e8b435a624 | ||
|
|
996772faf2 | ||
|
|
9db87fc636 | ||
|
|
8dabde94bf | ||
|
|
bb8b823c30 | ||
|
|
9bdc4aace2 | ||
|
|
1a429bb3c4 | ||
|
|
cba1f85026 | ||
|
|
a2afe54f5a | ||
|
|
037c332158 | ||
|
|
73612215d8 | ||
|
|
59bf3a1cc4 | ||
|
|
a4412e8d63 | ||
|
|
c3af33f97d | ||
|
|
68cc5fe965 | ||
|
|
5ce7a0bde4 | ||
|
|
33a648e5f5 | ||
|
|
f670658407 | ||
|
|
3feca1c530 | ||
|
|
8dca3182a6 | ||
|
|
6227aee863 | ||
|
|
ac88a00f06 | ||
|
|
ee6b7152c7 | ||
|
|
a73a3380d7 | ||
|
|
691c8e7702 | ||
|
|
0b6fad7619 | ||
|
|
75d8dd2bf2 | ||
|
|
53e3bc6092 | ||
|
|
f603f4397d | ||
|
|
7db2df33e8 | ||
|
|
0810abd294 | ||
|
|
b4c96bca93 | ||
|
|
ed38118008 | ||
|
|
c488ce166e | ||
|
|
2b6628aa65 | ||
|
|
4d8f340827 | ||
|
|
d37dc246eb | ||
|
|
396326014d | ||
|
|
184f12a214 | ||
|
|
0f46c8904d | ||
|
|
88c11e92d3 | ||
|
|
eccf87acc7 | ||
|
|
19b39f49fa | ||
|
|
e482ab6292 | ||
|
|
21278356ec | ||
|
|
e38467ef3a | ||
|
|
20d9498fdb | ||
|
|
1bfd7c0345 | ||
|
|
ee287f6120 | ||
|
|
48227bd350 | ||
|
|
1a64053da5 | ||
|
|
5ee4931fb6 | ||
|
|
4368841f02 | ||
|
|
49fd99119d | ||
|
|
b451be6c7f | ||
|
|
7c382c85b8 | ||
|
|
179b11151e | ||
|
|
3baccc9d3e | ||
|
|
78f4e8fdca | ||
|
|
63e5afda0b | ||
|
|
08f0f275af | ||
|
|
edc77d7f00 | ||
|
|
adf688635a | ||
|
|
a58d76d27d | ||
|
|
fec39e87c0 | ||
|
|
a76c962aa3 | ||
|
|
a826091dc9 | ||
|
|
5ce5000b14 | ||
|
|
a3eae736e7 | ||
|
|
6fcea142a2 | ||
|
|
a666de46aa | ||
|
|
e35c56ceb3 | ||
|
|
be55085303 | ||
|
|
0b6e46b1e4 | ||
|
|
826be7472f | ||
|
|
b2b243e803 | ||
|
|
475a4d71d8 | ||
|
|
0dd5be788f | ||
|
|
4e8f42f6f6 | ||
|
|
9f575a70c1 | ||
|
|
f372420dc0 | ||
|
|
2183e25081 | ||
|
|
8d27dba4cd | ||
|
|
02ac7c309e | ||
|
|
4907c56231 | ||
|
|
42952743ba | ||
|
|
04345643a0 | ||
|
|
80aabfe0aa | ||
|
|
9c7d83ebc1 | ||
|
|
465f156e03 | ||
|
|
d0fbba19d1 | ||
|
|
f407c5a25f | ||
|
|
c1a274d91c | ||
|
|
0f8614221b | ||
|
|
291cdd4bfb | ||
|
|
2ce946584e | ||
|
|
78cc2aa9cc | ||
|
|
9553478d9c | ||
|
|
6689b0be02 | ||
|
|
a44d7d86cb | ||
|
|
8659b9d77c | ||
|
|
1b8d03f3aa | ||
|
|
bf1db80e4f | ||
|
|
e7a4a3516f | ||
|
|
2c194df591 | ||
|
|
6580ddd6cb | ||
|
|
a3a5e5b824 | ||
|
|
788ab8d3a8 | ||
|
|
9e1c048e20 | ||
|
|
a1903e025c | ||
|
|
f3bfdd7857 | ||
|
|
c7dae2aca6 | ||
|
|
69138fc08b | ||
|
|
a6b56e6b7a | ||
|
|
c9f804486d | ||
|
|
3b0c958600 | ||
|
|
1d8d2bd7b7 | ||
|
|
a2c2a364a4 | ||
|
|
8fb3a3ff23 | ||
|
|
a6d402e8fd | ||
|
|
c06b971b65 | ||
|
|
25703b04a2 | ||
|
|
031df36935 | ||
|
|
62f28cc4ac | ||
|
|
d460c3863e | ||
|
|
0eb1913713 | ||
|
|
6db96753d2 | ||
|
|
9b9ffc4b13 | ||
|
|
d224f8b7ee | ||
|
|
6662e60b63 | ||
|
|
410eb19ce6 | ||
|
|
c7ba01b034 | ||
|
|
2bd8be5872 | ||
|
|
5385d004ec | ||
|
|
bf299e5c17 | ||
|
|
7aaaaa953b | ||
|
|
ad87a6d185 | ||
|
|
e653f4f7dd | ||
|
|
95208bc3dd | ||
|
|
263a766d8e | ||
|
|
61618389e1 | ||
|
|
e6d86bfab5 | ||
|
|
f7959d5646 | ||
|
|
e077a6bf28 | ||
|
|
c002dd6cba | ||
|
|
f2cd511d9c | ||
|
|
3f8bf89e72 | ||
|
|
3584dac5c0 | ||
|
|
f6c8225dac | ||
|
|
4f7793a423 | ||
|
|
91c3bdfa15 | ||
|
|
bd368b29b1 | ||
|
|
2e8429858e | ||
|
|
862f83cc40 | ||
|
|
ac339f4724 | ||
|
|
aeccd8c166 | ||
|
|
f6326606b7 | ||
|
|
f541520040 | ||
|
|
7ff899bd22 | ||
|
|
f42f785c78 | ||
|
|
1667ffdd8f | ||
|
|
a7e11d134f | ||
|
|
adf07aab47 | ||
|
|
91612eb45a | ||
|
|
b47a23ab79 | ||
|
|
e28188edd9 | ||
|
|
ef28d12d85 | ||
|
|
b65f8a3fe2 | ||
|
|
8d4c134f80 | ||
|
|
3f60034c39 | ||
|
|
4afa7b86ae | ||
|
|
2343e69ce5 | ||
|
|
251b2aaeb8 | ||
|
|
48926fcade | ||
|
|
3d4791f291 | ||
|
|
7a3b80a9b7 | ||
|
|
bb47f3a8e4 | ||
|
|
5de4e88d7a | ||
|
|
b60baf46f6 | ||
|
|
d76b58cc72 | ||
|
|
da378077f7 | ||
|
|
3677749935 | ||
|
|
75a20216d9 | ||
|
|
07a5cc6544 | ||
|
|
01d4312251 | ||
|
|
2c29ab5542 | ||
|
|
c3c2a4269d | ||
|
|
a0c5d75f83 | ||
|
|
d69b73eaa8 | ||
|
|
f61a91c97d | ||
|
|
d52b917c54 | ||
|
|
f7fc919d98 | ||
|
|
2e7405b76c | ||
|
|
3dfffdf351 | ||
|
|
1a7810efe1 | ||
|
|
6700c5fd46 | ||
|
|
f05cfe2627 | ||
|
|
69cb133c57 | ||
|
|
4270180b8b | ||
|
|
2d5f087041 | ||
|
|
7c38e2db24 | ||
|
|
64a4ed6db6 | ||
|
|
ebb615d080 | ||
|
|
2d0562412e | ||
|
|
a74f597d45 | ||
|
|
9fc0ec0bf4 | ||
|
|
2b269ff1c0 | ||
|
|
3f8e258055 | ||
|
|
e9054f2980 | ||
|
|
fa2eb24ba2 | ||
|
|
433baf5f3c | ||
|
|
d2cf090ace | ||
|
|
93ffe6123d | ||
|
|
8846f50cb7 | ||
|
|
843dd9b5e1 | ||
|
|
70c1f0640d | ||
|
|
9b1db9709b | ||
|
|
edb50b66a0 | ||
|
|
0862c79b21 | ||
|
|
0f623c2354 | ||
|
|
f27e1ec818 | ||
|
|
2fea28f194 | ||
|
|
42d9d6abc8 | ||
|
|
46e63da4d8 | ||
|
|
d7bd0be53e | ||
|
|
3f80e92f2c | ||
|
|
0ae6d1fecf | ||
|
|
d898abf63d | ||
|
|
ba4028b9dd | ||
|
|
d3cd707db7 | ||
|
|
7afb8ff679 | ||
|
|
fb64bb314c | ||
|
|
bc5f3abd3c | ||
|
|
1934bedde2 | ||
|
|
cea8ad4b85 | ||
|
|
129d7333be | ||
|
|
9647901ba0 | ||
|
|
c21e5f5e79 | ||
|
|
b4e0c97469 | ||
|
|
cb34060f00 | ||
|
|
785bd8ebcc | ||
|
|
a4c5b87b90 | ||
|
|
fef87b9219 | ||
|
|
4f591aa87a | ||
|
|
d6544933aa | ||
|
|
a01a9e5943 | ||
|
|
ed4edb93e7 | ||
|
|
8869f4ca4d | ||
|
|
b137dba5db | ||
|
|
ed2b985245 | ||
|
|
d7e38b378e | ||
|
|
4564f7aeea | ||
|
|
ce7f166ba3 | ||
|
|
1ab96abb91 | ||
|
|
1d3b4d1e9a | ||
|
|
0ad1426950 | ||
|
|
c1f0fe1da6 | ||
|
|
5336620f5c | ||
|
|
a0bf47cfd2 | ||
|
|
a202e67349 | ||
|
|
d7c00841d6 | ||
|
|
e79e8b30e0 | ||
|
|
1bee2caf5c | ||
|
|
9361aeb8eb | ||
|
|
8cbae5d62a | ||
|
|
d68ec362dd | ||
|
|
3e6bb267f3 | ||
|
|
e9d58b5a90 | ||
|
|
ee89c485fc | ||
|
|
c1a7ded1e4 | ||
|
|
5183d7cf0f | ||
|
|
db6b7b473d | ||
|
|
8cdc6b5d7c | ||
|
|
c4f0b4fb6d | ||
|
|
6bdc0365ee | ||
|
|
921ca7712e | ||
|
|
2d00d9cbe6 | ||
|
|
d28e9a7b62 | ||
|
|
37d1aa4129 | ||
|
|
a1d6833bac | ||
|
|
13507d422b | ||
|
|
de44a17e64 | ||
|
|
e9689a0a07 | ||
|
|
defbb01aaa | ||
|
|
904090cbb6 | ||
|
|
4bde3366c1 | ||
|
|
cfac29b0ef | ||
|
|
3326603265 | ||
|
|
35258b9b9c | ||
|
|
a22b6168c6 | ||
|
|
20bcd4bd69 | ||
|
|
552497d71b | ||
|
|
8d0100f100 | ||
|
|
a105003a7a | ||
|
|
e03aaec030 | ||
|
|
0aad73f4a1 | ||
|
|
2650fa9a92 | ||
|
|
3565f179af | ||
|
|
b35b0c598d | ||
|
|
6b54d04bfc | ||
|
|
965a3d6eec | ||
|
|
917cf44def | ||
|
|
c884edd923 | ||
|
|
6f4e2ab491 | ||
|
|
5988c0e95a | ||
|
|
fd461ca702 | ||
|
|
0ea72af60c | ||
|
|
6118ed89bb | ||
|
|
226e3b83da | ||
|
|
f6c846d27a | ||
|
|
3b4e79f073 | ||
|
|
2e5898490c | ||
|
|
d58f090198 | ||
|
|
e9adf8162b | ||
|
|
a034661bc9 | ||
|
|
609cad506f | ||
|
|
950a3e82c1 | ||
|
|
bdb216bf7c | ||
|
|
e019bd91fd | ||
|
|
ea916b6ae5 | ||
|
|
ba0b06f268 | ||
|
|
cea6b20c09 | ||
|
|
d77846bb16 | ||
|
|
8dab92d158 | ||
|
|
b5deee823c | ||
|
|
7091ab5e75 | ||
|
|
0495d0f232 | ||
|
|
e6d9a0d1ad | ||
|
|
c8236d0dd2 | ||
|
|
6bdf005171 | ||
|
|
ce77e80414 | ||
|
|
de10f0dda6 | ||
|
|
37b9ba5bd7 | ||
|
|
035d655e47 | ||
|
|
06d8860d42 | ||
|
|
9d2509ab5b | ||
|
|
f7ab5cb7c4 | ||
|
|
8520bbd2c7 | ||
|
|
497e0b801f | ||
|
|
a511d79bf0 | ||
|
|
69500eed56 | ||
|
|
c67273e92a | ||
|
|
e8db0e3abb | ||
|
|
ef24783bff | ||
|
|
46ae5700ee | ||
|
|
c8e715c33b | ||
|
|
034df61f3c | ||
|
|
ed74182cc2 | ||
|
|
3c221d9466 | ||
|
|
6df52f06b6 | ||
|
|
f2596b3759 | ||
|
|
ac0f759b27 | ||
|
|
4ba19c9556 | ||
|
|
8e825fa629 | ||
|
|
a5be17d941 | ||
|
|
23831e38e6 | ||
|
|
ad745aae63 | ||
|
|
cc94419a72 | ||
|
|
c54f5c4b4f | ||
|
|
9b193a47a2 | ||
|
|
95448eea3d | ||
|
|
ba34d72183 | ||
|
|
b4b4c996ba | ||
|
|
b1454276ed | ||
|
|
aa0f77043c | ||
|
|
dac4dd560a | ||
|
|
505438cd90 | ||
|
|
bb66028e74 | ||
|
|
7e136a792f | ||
|
|
a9b8d30ce0 | ||
|
|
e6ef164441 | ||
|
|
25d3066eae | ||
|
|
8baae4c77f | ||
|
|
c295981c5a | ||
|
|
3ebd08e38c | ||
|
|
f38ff074c4 | ||
|
|
c124bbe4bf | ||
|
|
061fd25c61 | ||
|
|
923abb94d8 | ||
|
|
ef59c623fd | ||
|
|
8c1f4ba65d | ||
|
|
47c697feca | ||
|
|
177680216c | ||
|
|
032a937b06 | ||
|
|
4f36a1fb77 | ||
|
|
14a1d3d251 | ||
|
|
239dd55146 | ||
|
|
c09297997e | ||
|
|
776693235c | ||
|
|
b5c09965a9 | ||
|
|
91093305d6 | ||
|
|
7687ce84ed | ||
|
|
7a730384ef | ||
|
|
8d2aa61f9b | ||
|
|
8395704dc6 | ||
|
|
a672860c40 | ||
|
|
b73aaa4899 | ||
|
|
78cf2ead38 | ||
|
|
da29203219 | ||
|
|
a6faa0384b | ||
|
|
deaaf3d22f | ||
|
|
448e41ecaa | ||
|
|
5a47379bf5 | ||
|
|
5e1113d884 | ||
|
|
45f1c96ff2 | ||
|
|
4703ec5164 | ||
|
|
9001a64ef9 | ||
|
|
186441e7f5 | ||
|
|
e5af1edcb9 | ||
|
|
357b67e3f5 | ||
|
|
777ef6b663 | ||
|
|
f5164f3804 | ||
|
|
6075bf3fc2 | ||
|
|
e99cd8052c | ||
|
|
d25420a33b | ||
|
|
9a7442c2fd | ||
|
|
ef97134f50 | ||
|
|
c28ed42617 | ||
|
|
eb5fdac918 | ||
|
|
518bc555a6 | ||
|
|
caa7d3177c | ||
|
|
19505b664c | ||
|
|
b4f6a9336b | ||
|
|
708d5831e4 | ||
|
|
405a75f26b | ||
|
|
34942b5af3 | ||
|
|
d2fac78413 | ||
|
|
481cebee7e | ||
|
|
96fdbac69a | ||
|
|
068093aae0 | ||
|
|
d8f352ae7c | ||
|
|
21bb2ea063 | ||
|
|
efae5d6a69 | ||
|
|
8989b5ea39 | ||
|
|
4bd7bafd7c | ||
|
|
8b6bcef4b7 | ||
|
|
c00ebef329 | ||
|
|
a06bd7f735 | ||
|
|
260591cc54 | ||
|
|
ad908f5dde | ||
|
|
8baa104453 | ||
|
|
a844cbbc3d | ||
|
|
97c9a4a02c | ||
|
|
a9ab3ea5b4 | ||
|
|
d63e3f1559 | ||
|
|
7388cc8a78 | ||
|
|
d1b2dd2831 | ||
|
|
011a9cc775 | ||
|
|
7f15e11b1b | ||
|
|
e8727cf4a1 | ||
|
|
3e198086e3 | ||
|
|
49c8292e48 | ||
|
|
ff057838ec | ||
|
|
6aab948be2 | ||
|
|
083aa700e9 | ||
|
|
7c3e43aa2e | ||
|
|
d88a3cf558 | ||
|
|
b9dc81d600 | ||
|
|
57201187de | ||
|
|
4097c20bdd | ||
|
|
fb1bd1a5bd | ||
|
|
4837969e09 | ||
|
|
ef0b2291a0 | ||
|
|
29172e9ee2 | ||
|
|
66b8c870f4 | ||
|
|
94f25a429f | ||
|
|
ec17355056 | ||
|
|
6103677914 | ||
|
|
005ddf26c1 | ||
|
|
c210e1bae6 | ||
|
|
4fe64d1b0d | ||
|
|
461e9fe5c2 | ||
|
|
a7ad2a7e1a | ||
|
|
510ad223f0 | ||
|
|
b2ee24b549 | ||
|
|
ad1d0ffc5a | ||
|
|
d68d1d9999 | ||
|
|
4a96c7c9f2 | ||
|
|
39dd219fbc | ||
|
|
660d040531 | ||
|
|
2088dfb3b3 | ||
|
|
3e6016dc6e | ||
|
|
096db533a6 | ||
|
|
3648ef4687 | ||
|
|
3ae4c00562 | ||
|
|
13d5c5e7e6 | ||
|
|
8929e55bff | ||
|
|
11ecab3ca1 | ||
|
|
f73e870bde | ||
|
|
e6aa9f9d4e | ||
|
|
48ce6151f9 | ||
|
|
1c3f3c1842 | ||
|
|
55320a03f1 | ||
|
|
9b2037419f | ||
|
|
8888ee3974 | ||
|
|
cb4b4d584c | ||
|
|
fe1d82c9c3 | ||
|
|
167a841010 | ||
|
|
2736c3a9d1 | ||
|
|
dcb4eedeb0 | ||
|
|
be1e09aad4 | ||
|
|
3e6eea25b3 | ||
|
|
2ce6e59d9b | ||
|
|
132a710a0a | ||
|
|
6ef3b8c458 | ||
|
|
7496a463d4 | ||
|
|
091b40cb39 | ||
|
|
0f0812618a | ||
|
|
383142bcbe | ||
|
|
06fbbaa43f | ||
|
|
a223157000 | ||
|
|
31dd135075 | ||
|
|
0345861b5f | ||
|
|
4422a3df23 | ||
|
|
a214d0ed4c | ||
|
|
08e5c8e010 | ||
|
|
625376f0d3 | ||
|
|
3519cbd3e5 | ||
|
|
6b8374f391 | ||
|
|
96e2ba19f8 | ||
|
|
a78e4a3366 | ||
|
|
b375e20c75 | ||
|
|
d9f6a05b7e | ||
|
|
64b585efa1 | ||
|
|
54b88cdfbe | ||
|
|
e9adfd8663 | ||
|
|
8d0b4ede68 | ||
|
|
9707eeb8cb | ||
|
|
2f48d0c828 | ||
|
|
2ff9270279 | ||
|
|
8f925a2e84 | ||
|
|
8a157eee0a | ||
|
|
cf11b32849 | ||
|
|
53a99cb9ee | ||
|
|
8aaa3c4884 | ||
|
|
7d877ab488 | ||
|
|
642970df95 | ||
|
|
75d1715442 | ||
|
|
59825a5268 | ||
|
|
ca64363899 | ||
|
|
0508a62c91 | ||
|
|
93ea98520b | ||
|
|
cc2cebffb6 | ||
|
|
c3b6e9da43 | ||
|
|
5256f1c967 | ||
|
|
c631e6c61c | ||
|
|
5fe6c2dcb4 | ||
|
|
453405f131 | ||
|
|
0ee87d7b46 | ||
|
|
b0e395e853 | ||
|
|
ad7855f995 | ||
|
|
9f288fc16f | ||
|
|
1b3047c812 | ||
|
|
f5b97f1e8a | ||
|
|
d3aa8a118c | ||
|
|
820bf37445 | ||
|
|
2639fba582 | ||
|
|
03c5fdef43 | ||
|
|
203dff9165 | ||
|
|
4bb6740bf4 | ||
|
|
5a5f06ef2a | ||
|
|
9693184cea | ||
|
|
92913c4c27 | ||
|
|
1f79fb608a | ||
|
|
3a2a4dee5c | ||
|
|
c1e68b2c61 | ||
|
|
a38d0a0fbd | ||
|
|
b32301592f | ||
|
|
97c95b7639 | ||
|
|
852c3badbb | ||
|
|
e5b7628802 | ||
|
|
da10ce7b05 | ||
|
|
b484638bb9 | ||
|
|
9a145ab15f | ||
|
|
822f0bd40b | ||
|
|
7f5deb0f97 | ||
|
|
225b8953fd | ||
|
|
2ce925caba | ||
|
|
4a7b3d6d7b | ||
|
|
219af60102 | ||
|
|
14a5144de7 | ||
|
|
49d5c02d69 | ||
|
|
a871da4fbe | ||
|
|
3ac74c86a1 | ||
|
|
2bf88fcef5 | ||
|
|
b6875b41f4 | ||
|
|
a9559f03b0 | ||
|
|
02f6ed7da3 | ||
|
|
de13141b68 | ||
|
|
39a121351d | ||
|
|
00d23c61d9 | ||
|
|
af09cb06f5 | ||
|
|
8eed6ae179 | ||
|
|
079b8e0e16 | ||
|
|
4debd89d8e | ||
|
|
6e42c791cf | ||
|
|
bf3135eb41 | ||
|
|
368d2f3279 | ||
|
|
e9001207ea | ||
|
|
95260371cb | ||
|
|
613d08d3e2 | ||
|
|
c594d89dc5 | ||
|
|
5fb3edf258 | ||
|
|
ecdd751ec3 | ||
|
|
ead2a1a606 | ||
|
|
8485dcdb03 | ||
|
|
d68ffc2da6 | ||
|
|
223b49e3be | ||
|
|
a99457ee29 | ||
|
|
0e2af13656 | ||
|
|
37a58a04f2 | ||
|
|
236b3b1c2b | ||
|
|
ec61964bce | ||
|
|
ebdf08a514 | ||
|
|
d8a04c9e43 | ||
|
|
ef13866af6 | ||
|
|
168d3d7ddb | ||
|
|
5e10f1fe6a | ||
|
|
2173ceae95 | ||
|
|
416a898943 | ||
|
|
69d30f2204 | ||
|
|
02a28996f4 | ||
|
|
36996af82b | ||
|
|
145bd243e8 | ||
|
|
4cb00d3801 | ||
|
|
148383ff53 | ||
|
|
493f6cb578 | ||
|
|
a6409fb445 | ||
|
|
d94e8e8faf | ||
|
|
fd4c2172f5 | ||
|
|
2e734a4750 | ||
|
|
e6ef2f12de | ||
|
|
11de714d9d | ||
|
|
042e21115e | ||
|
|
63e9f6d826 | ||
|
|
150f5302b7 | ||
|
|
047f9c49ec | ||
|
|
0f43523a16 | ||
|
|
8d782a1027 | ||
|
|
c2ff171364 | ||
|
|
3b1400eaed | ||
|
|
2860f6e4a9 | ||
|
|
bbbfe65870 | ||
|
|
ab788a5316 | ||
|
|
f1660d8e05 | ||
|
|
eac0d0c99a | ||
|
|
52df1e65de | ||
|
|
bb5d2c501c | ||
|
|
bec8f6b86c | ||
|
|
213a8eb905 | ||
|
|
ee05c7fe42 | ||
|
|
28ec412369 | ||
|
|
941e70a701 | ||
|
|
0d05be4e31 | ||
|
|
78fed0dfe7 | ||
|
|
cdb65e9ced | ||
|
|
482ff4562f | ||
|
|
38bca2332d | ||
|
|
c587203ebe | ||
|
|
716e322246 | ||
|
|
3a0d99d24c | ||
|
|
29b76fc4f5 | ||
|
|
d3b11c2b8c | ||
|
|
e6914355dd | ||
|
|
b3581bc0b4 | ||
|
|
b4b9f9601b | ||
|
|
c9a7fd9435 | ||
|
|
575845772f | ||
|
|
bc7161754f | ||
|
|
7a360b1181 | ||
|
|
8fadca196b | ||
|
|
30236a804d | ||
|
|
24eb7c98f2 | ||
|
|
89e2709304 | ||
|
|
7b9e58f7c6 | ||
|
|
737d41e184 | ||
|
|
97f83c9fb2 | ||
|
|
224e805fe4 | ||
|
|
9e8faebcd6 | ||
|
|
bc4d3a32eb | ||
|
|
b9b9dabd75 | ||
|
|
ed5a9d5dc1 | ||
|
|
7339ebce60 |
13
.github/pull_request_template.md
vendored
Normal file
13
.github/pull_request_template.md
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
As long as it's not linux/cross-platform skeleton/compatibility layer, all of the code on the repo that's not behind a preprocessor condition(like FIX_BUGS) are **completely** reversed code from original binaries.
|
||||
|
||||
We **don't** accept custom codes, as long as it's not wrapped via preprocessor conditions, or it's linux/cross-platform skeleton/compatibility layer.
|
||||
|
||||
We accept only these kinds of PRs;
|
||||
|
||||
- A new feature that exists in at least one of the GTAs (if it wasn't in III/VC then it doesn't have to be decompilation)
|
||||
- Game, UI or UX bug fixes (if it's a fix to R* code, it should be behind FIX_BUGS)
|
||||
- Platform-specific and/or unused code that's not been reversed yet
|
||||
- Makes reversed code more understandable/accurate, as in "which code would produce this assembly".
|
||||
- A new cross-platform skeleton/compatibility layer, or improvements to them
|
||||
- Translation fixes, for languages R* supported/outsourced
|
||||
- Code that increase maintainability
|
||||
19
.github/workflows/build-cmake-conan.yml
vendored
19
.github/workflows/build-cmake-conan.yml
vendored
@@ -1,4 +1,4 @@
|
||||
name: reVC conan+cmake
|
||||
name: reLCS conan+cmake
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
@@ -23,11 +23,11 @@ jobs:
|
||||
# - os: 'windows-latest'
|
||||
# platform: 'd3d9'
|
||||
# audio: 'miles'
|
||||
- os: 'ubuntu-latest'
|
||||
- os: 'ubuntu-18.04'
|
||||
platform: 'gl3'
|
||||
gl3_gfxlib: 'glfw'
|
||||
audio: 'openal'
|
||||
# - os: 'ubuntu-latest'
|
||||
# - os: 'ubuntu-18.04'
|
||||
# platform: 'gl3'
|
||||
# gl3_gfxlib: 'sdl2'
|
||||
# audio: 'openal'
|
||||
@@ -63,8 +63,9 @@ jobs:
|
||||
python -m pip install conan
|
||||
conan config init
|
||||
conan config set log.print_run_commands=True
|
||||
conan remote add bincrafters https://api.bintray.com/conan/bincrafters/public-conan
|
||||
conan remote add madebr_ps2dev https://api.bintray.com/conan/madebr/ps2dev
|
||||
conan config set general.revisions_enabled=1
|
||||
conan remote add bincrafters https://bincrafters.jfrog.io/artifactory/api/conan/public-conan
|
||||
# conan remote add madebr_ps2dev https://api.bintray.com/conan/madebr/ps2dev
|
||||
- name: "Add os=playstation2 + gcc.version=3.2 to .conan/settings.yml"
|
||||
shell: python
|
||||
run: |
|
||||
@@ -85,7 +86,7 @@ jobs:
|
||||
fi
|
||||
- name: "Export Playstation 2 CMake toolchain conan recipe"
|
||||
run: |
|
||||
conan export vendor/librw/cmake/ps2toolchain ps2dev-cmaketoolchain/master@
|
||||
conan export vendor/librw/cmake/ps2/cmaketoolchain ps2dev-cmaketoolchain/master@
|
||||
- name: "Export librw conan recipe"
|
||||
run: |
|
||||
conan export vendor/librw librw/master@
|
||||
@@ -95,13 +96,13 @@ jobs:
|
||||
conan export re3mss miles-sdk/master@
|
||||
- name: "Download/build dependencies (conan install)"
|
||||
run: |
|
||||
conan install ${{ github.workspace }} reVC/master@ -if build -o reVC:audio=${{ matrix.audio }} -o librw:platform=${{ matrix.platform }} -o librw:gl3_gfxlib=${{ matrix.gl3_gfxlib || 'glfw' }} --build missing -pr:h ./host_profile -pr:b default -s reVC:build_type=RelWithDebInfo -s librw:build_type=RelWithDebInfo
|
||||
conan install ${{ github.workspace }} reLCS/master@ -if build -o reLCS:audio=${{ matrix.audio }} -o librw:platform=${{ matrix.platform }} -o librw:gl3_gfxlib=${{ matrix.gl3_gfxlib || 'glfw' }} --build missing -pr:h ./host_profile -pr:b default -s reLCS:build_type=RelWithDebInfo -s librw:build_type=RelWithDebInfo
|
||||
env:
|
||||
CONAN_SYSREQUIRES_MODE: enabled
|
||||
- name: "Build reVC (conan build)"
|
||||
- name: "Build reLCS (conan build)"
|
||||
run: |
|
||||
conan build ${{ github.workspace }} -if build -bf build -pf package
|
||||
- name: "Package reVC (conan package)"
|
||||
- name: "Package reLCS (conan package)"
|
||||
run: |
|
||||
conan package ${{ github.workspace }} -if build -bf build -pf package
|
||||
- name: "Create binary package (cpack)"
|
||||
|
||||
29
.github/workflows/build-switch.yml.bak
vendored
Normal file
29
.github/workflows/build-switch.yml.bak
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
|
||||
name: reLCS cmake devkitA64 (Nintendo Switch)
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
release:
|
||||
types: published
|
||||
jobs:
|
||||
build-nintendo-switch:
|
||||
runs-on: ubuntu-latest
|
||||
container: devkitpro/devkita64:latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: 'true'
|
||||
- name: "Build files"
|
||||
run: |
|
||||
/opt/devkitpro/portlibs/switch/bin/aarch64-none-elf-cmake -S. -Bbuild -DREVC_AUDIO=OAL -DLIBRW_PLATFORM=GL3 -DLIBRW_GL3_GFXLIB=GLFW -DREVC_WITH_OPUS=False -DREVC_VENDORED_LIBRW=True -DREVC_INSTALL=True
|
||||
cmake --build build --parallel
|
||||
- name: "Create binary package (cpack)"
|
||||
working-directory: ./build
|
||||
run: |
|
||||
cpack
|
||||
- name: "Archive binary package (github artifacts)"
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: "switch-gl3"
|
||||
path: build/*.tar.xz
|
||||
if-no-files-found: error
|
||||
@@ -1,4 +1,4 @@
|
||||
name: reVC premake amd64
|
||||
name: reLCS premake amd64
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
@@ -6,13 +6,9 @@ on:
|
||||
release:
|
||||
types: published
|
||||
env:
|
||||
GLEW_VER: "2.1.0"
|
||||
GLFW_VER: "3.3.2"
|
||||
GLEW_BASE: "glew-2.1.0"
|
||||
GLFW_BASE: "glfw-3.3.2.bin.WIN64"
|
||||
GLEW_FILE: "glew-2.1.0-win32.zip"
|
||||
GLFW_FILE: "glfw-3.3.2.bin.WIN64.zip"
|
||||
GLEW_URL: "https://github.com/nigels-com/glew/releases/download/glew-2.1.0/glew-2.1.0-win32.zip"
|
||||
GLFW_URL: "https://github.com/glfw/glfw/releases/download/3.3.2/glfw-3.3.2.bin.WIN64.zip"
|
||||
jobs:
|
||||
build:
|
||||
@@ -20,18 +16,13 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
platform: [win-amd64-librw_d3d9-oal, win-amd64-librw_gl3_glfw-oal]
|
||||
buildtype: [Debug, Release, Vanilla]
|
||||
buildtype: [Debug, Release]
|
||||
steps:
|
||||
- name: Add msbuild to PATH
|
||||
uses: microsoft/setup-msbuild@v1.0.2
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: 'true'
|
||||
- if: ${{ matrix.platform }} == "win-amd64-librw_gl3_glfw-mss"
|
||||
name: Download glew
|
||||
uses: carlosperate/download-file-action@v1.0.3
|
||||
with:
|
||||
file-url: ${{env.GLEW_URL}}
|
||||
- if: ${{ matrix.platform }} == "win-amd64-librw_gl3_glfw-mss"
|
||||
name: Download glfw
|
||||
uses: carlosperate/download-file-action@v1.0.3
|
||||
@@ -40,21 +31,20 @@ jobs:
|
||||
- if: ${{ matrix.platform }} == "win-amd64-librw_gl3_glfw-mss"
|
||||
name: Unpack archives
|
||||
run: |
|
||||
7z x ${{env.GLEW_FILE}}
|
||||
7z x ${{env.GLFW_FILE}}
|
||||
- name: Configure build
|
||||
run: |
|
||||
./premake5 vs2019 --with-librw --glewdir=${{env.GLEW_BASE}} --glfwdir64=${{env.GLFW_BASE}}
|
||||
./premake5 vs2019 --with-librw --no-full-paths --glfwdir64=${{env.GLFW_BASE}}
|
||||
- name: Build
|
||||
run: |
|
||||
msbuild -m build/reVC.sln /property:Configuration=${{matrix.buildtype}} /property:Platform=${{matrix.platform}}
|
||||
msbuild -m build/reLCS.sln /property:Configuration=${{matrix.buildtype}} /property:Platform=${{matrix.platform}}
|
||||
# - name: Pack artifacts
|
||||
# run: |
|
||||
# 7z a reVC_${{matrix.buildtype}}_${{matrix.platform}}.zip ./bin/${{matrix.platform}}/${{matrix.buildtype}}/*
|
||||
# 7z a reLCS_${{matrix.buildtype}}_${{matrix.platform}}.zip ./bin/${{matrix.platform}}/${{matrix.buildtype}}/*
|
||||
- name: Move binaries to gamefiles
|
||||
run: |
|
||||
mv ./bin/${{matrix.platform}}/${{matrix.buildtype}}/reVC.exe ./gamefiles/
|
||||
mv ./bin/${{matrix.platform}}/${{matrix.buildtype}}/reVC.pdb ./gamefiles/
|
||||
mv ./bin/${{matrix.platform}}/${{matrix.buildtype}}/reLCS.exe ./gamefiles/
|
||||
mv ./bin/${{matrix.platform}}/${{matrix.buildtype}}/reLCS.pdb ./gamefiles/
|
||||
- name: Move dynamic dependencies to gamefiles
|
||||
run: |
|
||||
mv ./vendor/mpg123/dist/Win64/libmpg123-0.dll ./gamefiles/
|
||||
@@ -62,12 +52,12 @@ jobs:
|
||||
- name: Upload artifact to actions
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: reVC_${{matrix.buildtype}}_${{matrix.platform}}
|
||||
name: reLCS_${{matrix.buildtype}}_${{matrix.platform}}
|
||||
path: ./gamefiles/*
|
||||
# - name: Upload artifact to Bintray
|
||||
# uses: hpcsc/upload-bintray-docker-action@v1
|
||||
# with:
|
||||
# repository: reVC
|
||||
# repository: reLCS
|
||||
# package: ${{matrix.buildtype}}_${{matrix.platform}}
|
||||
# version: 1.0-$(echo ${GITHUB_SHA}
|
||||
# sourcePath: ./bin/${{matrix.platform}}/${{matrix.buildtype}}
|
||||
@@ -1,4 +1,4 @@
|
||||
name: reVC premake x86
|
||||
name: reLCS premake x86
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
@@ -6,13 +6,9 @@ on:
|
||||
release:
|
||||
types: published
|
||||
env:
|
||||
GLEW_VER: "2.1.0"
|
||||
GLFW_VER: "3.3.2"
|
||||
GLEW_BASE: "glew-2.1.0"
|
||||
GLFW_BASE: "glfw-3.3.2.bin.WIN32"
|
||||
GLEW_FILE: "glew-2.1.0-win32.zip"
|
||||
GLFW_FILE: "glfw-3.3.2.bin.WIN32.zip"
|
||||
GLEW_URL: "https://github.com/nigels-com/glew/releases/download/glew-2.1.0/glew-2.1.0-win32.zip"
|
||||
GLFW_URL: "https://github.com/glfw/glfw/releases/download/3.3.2/glfw-3.3.2.bin.WIN32.zip"
|
||||
jobs:
|
||||
build:
|
||||
@@ -20,18 +16,13 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
platform: [win-x86-librw_d3d9-mss, win-x86-librw_gl3_glfw-mss, win-x86-librw_d3d9-oal, win-x86-librw_gl3_glfw-oal]
|
||||
buildtype: [Debug, Release, Vanilla]
|
||||
buildtype: [Debug, Release]
|
||||
steps:
|
||||
- name: Add msbuild to PATH
|
||||
uses: microsoft/setup-msbuild@v1.0.2
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: 'true'
|
||||
- if: ${{ matrix.platform }} == "win-x86-librw_gl3_glfw-mss"
|
||||
name: Download glew
|
||||
uses: carlosperate/download-file-action@v1.0.3
|
||||
with:
|
||||
file-url: ${{env.GLEW_URL}}
|
||||
- if: ${{ matrix.platform }} == "win-x86-librw_gl3_glfw-mss"
|
||||
name: Download glfw
|
||||
uses: carlosperate/download-file-action@v1.0.3
|
||||
@@ -40,21 +31,20 @@ jobs:
|
||||
- if: ${{ matrix.platform }} == "win-x86-librw_gl3_glfw-mss"
|
||||
name: Unpack archives
|
||||
run: |
|
||||
7z x ${{env.GLEW_FILE}}
|
||||
7z x ${{env.GLFW_FILE}}
|
||||
- name: Configure build
|
||||
run: |
|
||||
./premake5 vs2019 --with-librw --glewdir=${{env.GLEW_BASE}} --glfwdir32=${{env.GLFW_BASE}}
|
||||
./premake5 vs2019 --with-librw --no-full-paths --glfwdir32=${{env.GLFW_BASE}}
|
||||
- name: Build
|
||||
run: |
|
||||
msbuild -m build/reVC.sln /property:Configuration=${{matrix.buildtype}} /property:Platform=${{matrix.platform}}
|
||||
msbuild -m build/reLCS.sln /property:Configuration=${{matrix.buildtype}} /property:Platform=${{matrix.platform}}
|
||||
# - name: Pack artifacts
|
||||
# run: |
|
||||
# 7z a reVC_${{matrix.buildtype}}_${{matrix.platform}}.zip ./bin/${{matrix.platform}}/${{matrix.buildtype}}/*
|
||||
# 7z a reLCS_${{matrix.buildtype}}_${{matrix.platform}}.zip ./bin/${{matrix.platform}}/${{matrix.buildtype}}/*
|
||||
- name: Move binaries to gamefiles
|
||||
run: |
|
||||
mv ./bin/${{matrix.platform}}/${{matrix.buildtype}}/reVC.exe ./gamefiles/
|
||||
mv ./bin/${{matrix.platform}}/${{matrix.buildtype}}/reVC.pdb ./gamefiles/
|
||||
mv ./bin/${{matrix.platform}}/${{matrix.buildtype}}/reLCS.exe ./gamefiles/
|
||||
mv ./bin/${{matrix.platform}}/${{matrix.buildtype}}/reLCS.pdb ./gamefiles/
|
||||
- if: contains(matrix.platform, 'oal')
|
||||
name: Move dynamic dependencies to gamefiles
|
||||
run: |
|
||||
@@ -63,12 +53,12 @@ jobs:
|
||||
- name: Upload artifact to actions
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: reVC_${{matrix.buildtype}}_${{matrix.platform}}
|
||||
name: reLCS_${{matrix.buildtype}}_${{matrix.platform}}
|
||||
path: ./gamefiles/*
|
||||
# - name: Upload artifact to Bintray
|
||||
# uses: hpcsc/upload-bintray-docker-action@v1
|
||||
# with:
|
||||
# repository: reVC
|
||||
# repository: reLCS
|
||||
# package: ${{matrix.buildtype}}_${{matrix.platform}}
|
||||
# version: 1.0-$(echo ${GITHUB_SHA}
|
||||
# sourcePath: ./bin/${{matrix.platform}}/${{matrix.buildtype}}
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -355,6 +355,7 @@ vendor/glfw-3.3.2.bin.WIN64/
|
||||
|
||||
sdk/
|
||||
|
||||
codewarrior/reVC.mcp
|
||||
codewarrior/reVC_Data/
|
||||
codewarrior/Release/
|
||||
codewarrior/Debug/
|
||||
|
||||
18
.vscode/c_cpp_properties.json
vendored
18
.vscode/c_cpp_properties.json
vendored
@@ -26,6 +26,24 @@
|
||||
"compilerArgs": ["-ggdb"],
|
||||
"cStandard": "gnu11",
|
||||
"cppStandard": "gnu++14"
|
||||
},
|
||||
{
|
||||
"name": "devkitPro aarch64 (Nintendo Switch)",
|
||||
"compilerPath": "${env:DEVKITPRO}/devkitA64/bin/aarch64-none-elf-g++",
|
||||
"includePath": [
|
||||
"${default}",
|
||||
"${env:DEVKITPRO}/portlibs/switch/include",
|
||||
"${env:DEVKITPRO}/libnx/include"
|
||||
],
|
||||
"intelliSenseMode": "gcc-arm64",
|
||||
"cStandard": "gnu11",
|
||||
"cppStandard": "gnu++11",
|
||||
"defines": [
|
||||
"__SWITCH__",
|
||||
"LIBRW",
|
||||
"RW_GL3",
|
||||
"AUDIO_OAL"
|
||||
]
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
|
||||
8
.vscode/settings.json
vendored
8
.vscode/settings.json
vendored
@@ -2,8 +2,13 @@
|
||||
"C_Cpp.default.cStandard": "gnu11",
|
||||
"C_Cpp.default.cppStandard": "gnu++14",
|
||||
"C_Cpp.default.includePath": [
|
||||
"src",
|
||||
"src/animation",
|
||||
"src/audio",
|
||||
"src/audio/eax",
|
||||
"src/audio/oal",
|
||||
"src/buildings",
|
||||
"src/collision",
|
||||
"src/control",
|
||||
"src/core",
|
||||
"src/entities",
|
||||
@@ -13,9 +18,10 @@
|
||||
"src/modelinfo",
|
||||
"src/objects",
|
||||
"src/peds",
|
||||
"src/render",
|
||||
"src/renderer",
|
||||
"src/rw",
|
||||
"src/save",
|
||||
"src/save/glfw",
|
||||
"src/skel",
|
||||
"src/text",
|
||||
"src/vehicles",
|
||||
|
||||
@@ -1,15 +1,27 @@
|
||||
cmake_minimum_required(VERSION 3.8)
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
|
||||
set(EXECUTABLE reVC)
|
||||
set(PROJECT REVC)
|
||||
set(EXECUTABLE reLCS)
|
||||
set(PROJECT RELCS)
|
||||
|
||||
project(${EXECUTABLE} C CXX)
|
||||
set(${PROJECT}_AUTHOR "${PROJECT} Team")
|
||||
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
|
||||
|
||||
include(GetGitRevisionDescription)
|
||||
get_git_head_revision(GIT_REFSPEC GIT_SHA1 "ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR")
|
||||
message(STATUS "Building ${CMAKE_PROJECT_NAME} GIT SHA1: ${GIT_SHA1}")
|
||||
|
||||
|
||||
if(NINTENDO_SWITCH)
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake/nx")
|
||||
include(NXFunctions)
|
||||
endif()
|
||||
|
||||
if(NOT COMMAND reVC_platform_target)
|
||||
function(reVC_platform_target)
|
||||
endfunction()
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
set(${PROJECT}_AUDIOS "OAL" "MSS")
|
||||
else()
|
||||
@@ -66,6 +78,8 @@ if(${PROJECT}_INSTALL)
|
||||
set(os "-apple")
|
||||
elseif(UNIX)
|
||||
set(os "-linux")
|
||||
elseif(NINTENDO_SWITCH)
|
||||
set(os "-switch")
|
||||
else()
|
||||
set(compiler "-UNK")
|
||||
message(WARNING "Unknown os. Created cpack package will be wrong. (override using cpack -P)")
|
||||
|
||||
180
README.md
180
README.md
@@ -1,175 +1,37 @@
|
||||
<img src="https://github.com/GTAmodding/re3/blob/miami/logo.png?raw=true" alt="reVC logo" width="200">
|
||||
|
||||
[](https://actions-badge.atrox.dev/GTAmodding/re3/goto?ref=miami)
|
||||
<a href="https://discord.gg/ERYg58ttcE"><img src="https://img.shields.io/badge/discord-join-7289DA.svg?logo=discord&longCache=true&style=flat" /></a>
|
||||
# reLCS
|
||||
[](https://actions-badge.atrox.dev/GTAmodding/re3/goto?ref=lcs)
|
||||
<a href="https://discord.gg/RFNbjsUMGg"><img src="https://img.shields.io/badge/discord-join-7289DA.svg?logo=discord&longCache=true&style=flat" /></a>
|
||||
|
||||
## Intro
|
||||
|
||||
In this repository you'll find the fully reversed source code for GTA III ([master](https://github.com/GTAmodding/re3/tree/master/) branch) and GTA VC ([miami](https://github.com/GTAmodding/re3/tree/miami/) branch).
|
||||
|
||||
It has been tested and works on Windows, Linux and FreeBSD, on x86, amd64, arm and arm64.\
|
||||
Rendering is handled either by original RenderWare (D3D8)
|
||||
or the reimplementation [librw](https://github.com/aap/librw) (D3D9, OpenGL 2.1 or above, OpenGL ES 2.0 or above).\
|
||||
Audio is done with MSS (using dlls from original GTA) or OpenAL.
|
||||
|
||||
We cannot build for PS2 or Xbox yet. If you're interested in doing so, get in touch with us.
|
||||
The aim of this project is to reverse GTA Liberty City Stories.
|
||||
|
||||
## How can I try it?
|
||||
|
||||
- reVC requires game assets to work, so you **must** own [a copy of GTA Vice City](https://store.steampowered.com/app/12110/Grand_Theft_Auto_Vice_City/).
|
||||
- Build reVC or download the latest nightly build:
|
||||
- [Windows D3D9 MSS 32bit](https://nightly.link/GTAmodding/re3/workflows/reVC_msvc_x86/miami/reVC_Release_win-x86-librw_d3d9-mss.zip)
|
||||
- [Windows D3D9 64bit](https://nightly.link/GTAmodding/re3/workflows/reVC_msvc_amd64/miami/reVC_Release_win-amd64-librw_d3d9-oal.zip)
|
||||
- [Windows OpenGL 64bit](https://nightly.link/GTAmodding/re3/workflows/reVC_msvc_amd64/miami/reVC_Release_win-amd64-librw_gl3_glfw-oal.zip)
|
||||
- [Linux 64bit](https://nightly.link/GTAmodding/re3/workflows/build-cmake-conan/miami/ubuntu-latest-gl3.zip)
|
||||
- [MacOS 64bit](https://nightly.link/GTAmodding/re3/workflows/build-cmake-conan/miami/macos-latest-gl3.zip)
|
||||
- Extract the downloaded zip over your GTA VC directory and run reVC. The zip includes the gamefiles and in case of OpenAL the required dlls.
|
||||
- reLCS requires game assets to work.
|
||||
- Build reLCS or download it from one of the above links (Debug or Release).
|
||||
- (Optional) If you want to use optional features, copy the files in /gamefiles folder to your game root folder.
|
||||
- Move reLCS.exe to GTA LCS directory and run it.
|
||||
|
||||
## Screenshots
|
||||
## Preparing the environment for building
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
You may want to point GTA_LCS_RE_DIR environment variable to GTA LCS root folder if you want executable to be moved there via post-build script.
|
||||
|
||||
## Improvements
|
||||
|
||||
We have implemented a number of changes and improvements to the original game.
|
||||
They can be configured in `core/config.h`.
|
||||
Some of them can be toggled at runtime, some cannot.
|
||||
|
||||
* Fixed a lot of smaller and bigger bugs
|
||||
* User files (saves and settings) stored in GTA root directory
|
||||
* Settings stored in reVC.ini file instead of gta_vc.set
|
||||
* Debug menu to do and change various things (Ctrl-M to open)
|
||||
* Debug camera (Ctrl-B to toggle)
|
||||
* Rotatable camera
|
||||
* Xinput controller support (Windows)
|
||||
* No loading screens between islands ("map memory usage" in menu)
|
||||
* Rendering
|
||||
* Widescreen support (properly scaled HUD, Menu and FOV)
|
||||
* PS2 MatFX (vehicle reflections)
|
||||
* PS2 alpha test (better rendering of transparency)
|
||||
* Xbox vehicle rendering
|
||||
* Xbox world lightmap rendering (needs Xbox map)
|
||||
* Xbox ped rim light
|
||||
* Xbox screen rain droplets
|
||||
* More customizable colourfilter
|
||||
* Menu
|
||||
* More options
|
||||
* Controller configuration menu
|
||||
* ...
|
||||
* Can load DFFs and TXDs from other platforms, possibly with a performance penalty
|
||||
* ...
|
||||
|
||||
## To-Do
|
||||
|
||||
The following things would be nice to have/do:
|
||||
|
||||
* Fix physics for high FPS
|
||||
* Improve performance on lower end devices, especially the OpenGL layer on the Raspberry Pi (if you have experience with this, please get in touch)
|
||||
* [PS2 port](https://github.com/GTAmodding/re3/wiki/PS2-port)
|
||||
* Xbox port (not quite as important)
|
||||
* reverse remaining unused/debug functions
|
||||
* compare Codewarrior build with original binary for more accurate code (very tedious)
|
||||
|
||||
## Modding
|
||||
|
||||
Asset modifications (models, texture, handling, script, ...) should work the same way as with original GTA for the most part.
|
||||
|
||||
Mods that make changes to the code (dll/asi, CLEO, limit adjusters) will *not* work.
|
||||
Some things these mods do are already implemented in re3 (much of SkyGFX, GInput, SilentPatch, Widescreen fix),
|
||||
others can easily be achieved (increasing limis, see `config.h`),
|
||||
others will simply have to be rewritten and integrated into the code directly.
|
||||
Sorry for the inconvenience.
|
||||
|
||||
## Building from Source
|
||||
|
||||
When using premake, you may want to point GTA_VC_RE_DIR environment variable to GTA Vice City root folder if you want the executable to be moved there via post-build script.
|
||||
|
||||
Clone the repository with `git clone --recursive -b miami https://github.com/GTAmodding/re3.git reVC`. Then `cd reVC` into the cloned repository.
|
||||
|
||||
<details><summary>Linux Premake</summary>
|
||||
|
||||
For Linux using premake, proceed: [Building on Linux](https://github.com/GTAmodding/re3/wiki/Building-on-Linux)
|
||||
|
||||
</details>
|
||||
|
||||
<details><summary>Linux Conan</summary>
|
||||
|
||||
Install python and conan, and then run build.
|
||||
```
|
||||
conan export vendor/librw librw/master@
|
||||
mkdir build
|
||||
cd build
|
||||
conan install .. reVC/master@ -if build -o reVC:audio=openal -o librw:platform=gl3 -o librw:gl3_gfxlib=glfw --build missing -s reVC:build_type=RelWithDebInfo -s librw:build_type=RelWithDebInfo
|
||||
conan build .. -if build -bf build -pf package
|
||||
```
|
||||
</details>
|
||||
|
||||
<details><summary>FreeBSD</summary>
|
||||
|
||||
For FreeBSD using premake, proceed: [Building on FreeBSD](https://github.com/GTAmodding/re3/wiki/Building-on-FreeBSD)
|
||||
|
||||
</details>
|
||||
|
||||
<details><summary>Windows</summary>
|
||||
|
||||
Assuming you have Visual Studio 2015/2017/2019:
|
||||
- Run one of the `premake-vsXXXX.cmd` variants on root folder.
|
||||
- Open build/reVC.sln with Visual Studio and compile the solution.
|
||||
- For Linux, proceed: [Building on Linux](https://github.com/GTAmodding/re3/wiki/Building-on-Linux)
|
||||
- For FreeBSD, proceed: [Building on FreeBSD](https://github.com/GTAmodding/re3/wiki/Building-on-FreeBSD)
|
||||
- For Windows, assuming you have Visual Studio:
|
||||
- Clone the repo using the argument `--recursive`.
|
||||
- Run one of the `premake-vsXXXX.cmd` variants on root folder.
|
||||
- Open the project via Visual Studio
|
||||
|
||||
Microsoft recently discontinued its downloads of the DX9 SDK. You can download an archived version here: https://archive.org/details/dxsdk_jun10
|
||||
**If you use 64-bit D3D9**: We don't ship 64-bit Dx9 SDK. You need to download it from Microsoft if you don't have it(although it should come pre-installed after some Windows version)
|
||||
|
||||
**If you choose OpenAL on Windows** You must read [Running OpenAL build on Windows](https://github.com/GTAmodding/re3/wiki/Running-OpenAL-build-on-Windows).
|
||||
</details>
|
||||
There are various settings at the very bottom of [config.h](https://github.com/GTAmodding/re3/tree/lcs/src/core/config.h), you may want to take a look there. i.e. FIX_BUGS define fixes the bugs we've come across.
|
||||
|
||||
> :information_source: premake has an `--lto` option if you want the project to be compiled with Link Time Optimization.
|
||||
> :information_source: **If you choose OpenAL on Windows** You must read [Running OpenAL build on Windows](https://github.com/GTAmodding/re3/wiki/Running-OpenAL-build-on-Windows).
|
||||
|
||||
> :information_source: There are various settings in [config.h](https://github.com/GTAmodding/re3/tree/miami/src/core/config.h), you may want to take a look there.
|
||||
|
||||
> :information_source: reVC uses completely homebrew RenderWare-replacement rendering engine; [librw](https://github.com/aap/librw/). librw comes as submodule of re3, but you also can use LIBRW enviorenment variable to specify path to your own librw.
|
||||
|
||||
If you feel the need, you can also use Codewarrior 7 to compile reVC using the supplied codewarrior/reVC.mcp project - this requires the original RW34 libraries, and the DX8 SDK. The build is unstable compared to the MSVC builds though, and is mostly meant to serve as a reference.
|
||||
> :information_source: **Did you notice librw?** reLCS uses completely homebrew RenderWare-replacement rendering engine; [librw](https://github.com/aap/librw/). librw comes as submodule of reLCS, but you also can use LIBRW enviorenment variable to specify path to your own librw.
|
||||
|
||||
## Contributing
|
||||
We have a [Coding Style](https://github.com/GTAmodding/re3/blob/master/CODING_STYLE.md) document that isn't followed or enforced very well.
|
||||
Please read the [Coding Style](https://github.com/GTAmodding/re3/blob/master/CODING_STYLE.md) Document
|
||||
|
||||
Do not use features from C++11 or later.
|
||||
|
||||
|
||||
## History
|
||||
|
||||
re3 was started sometime in the spring of 2018,
|
||||
initially as a way to test reversed collision and physics code
|
||||
inside the game.
|
||||
This was done by replacing single functions of the game
|
||||
with their reversed counterparts using a dll.
|
||||
|
||||
After a bit of work the project lay dormant for about a year
|
||||
and was picked up again and pushed to github in May 2019.
|
||||
At the time I (aap) had reversed around 10k lines of code and estimated
|
||||
the final game to have around 200-250k.
|
||||
Others quickly joined the effort and we made very quick progress
|
||||
throughout the summer of 2019
|
||||
after which the pace slowed down a bit.
|
||||
|
||||
Due to everyone staying home during the start of the Corona pandemic
|
||||
everybody had a lot of time to work on re3 again and
|
||||
we finally got a standalone exe in April 2020 (around 180k lines by then).
|
||||
|
||||
After the initial excitement and fixing and polishing the code further,
|
||||
reVC was started in early May 2020 by starting from re3 code,
|
||||
not by starting from scratch replacing functions with a dll.
|
||||
After a few months of mostly steady progress we considered reVC
|
||||
finished in December.
|
||||
|
||||
Since then we have started reLCS, which is currently work in progress.
|
||||
|
||||
|
||||
## License
|
||||
|
||||
We don't feel like we're in a position to give this code a license.\
|
||||
The code should only be used for educational, documentation and modding purposes.\
|
||||
We do not encourage piracy or commercial use.\
|
||||
Please keep derivate work open source and give proper credit.
|
||||
|
||||
27
autoconf/LICENSE.txt
Normal file
27
autoconf/LICENSE.txt
Normal file
@@ -0,0 +1,27 @@
|
||||
Copyright (c) 2016 Blizzard Entertainment and individual contributors.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of Premake nor the names of its contributors may be
|
||||
used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
305
autoconf/api.lua
Normal file
305
autoconf/api.lua
Normal file
@@ -0,0 +1,305 @@
|
||||
---
|
||||
-- Autoconfiguration.
|
||||
-- Copyright (c) 2016 Blizzard Entertainment
|
||||
-- Enhanced by re3
|
||||
---
|
||||
local p = premake
|
||||
local autoconf = p.modules.autoconf
|
||||
autoconf.cache = {}
|
||||
autoconf.parameters = ""
|
||||
|
||||
|
||||
---
|
||||
-- register autoconfigure api.
|
||||
---
|
||||
p.api.register {
|
||||
name = "autoconfigure",
|
||||
scope = "config",
|
||||
kind = "table"
|
||||
}
|
||||
|
||||
---
|
||||
-- Check for a particular include file.
|
||||
--
|
||||
-- @cfg : Current config.
|
||||
-- @variable : The variable to store the result, such as 'HAVE_STDINT_H'.
|
||||
-- @filename : The header file to check for.
|
||||
---
|
||||
function check_include(cfg, variable, filename)
|
||||
local res = autoconf.cache_compile(cfg, variable, function ()
|
||||
p.outln('#include <' .. filename .. '>')
|
||||
p.outln('int main(void) { return 0; }')
|
||||
end)
|
||||
|
||||
if res.value then
|
||||
autoconf.set_value(cfg, variable, 1)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
---
|
||||
-- Check for size of a particular type.
|
||||
--
|
||||
-- @cfg : Current config.
|
||||
-- @variable : The variable to use, such as 'SIZEOF_SIZE_T', this method will also add "'HAVE_' .. variable".
|
||||
-- @type : The type to check.
|
||||
-- @headers : An optional array of header files to include.
|
||||
-- @defines : An optional array of defines to define.
|
||||
---
|
||||
function check_type_size(cfg, variable, type, headers, defines)
|
||||
check_include(cfg, 'HAVE_SYS_TYPES_H', 'sys/types.h')
|
||||
check_include(cfg, 'HAVE_STDINT_H', 'stdint.h')
|
||||
check_include(cfg, 'HAVE_STDDEF_H', 'stddef.h')
|
||||
|
||||
local res = autoconf.cache_compile(cfg, variable .. cfg.platform,
|
||||
function ()
|
||||
if cfg.autoconf['HAVE_SYS_TYPES_H'] then
|
||||
p.outln('#include <sys/types.h>')
|
||||
end
|
||||
|
||||
if cfg.autoconf['HAVE_STDINT_H'] then
|
||||
p.outln('#include <stdint.h>')
|
||||
end
|
||||
|
||||
if cfg.autoconf['HAVE_STDDEF_H'] then
|
||||
p.outln('#include <stddef.h>')
|
||||
end
|
||||
|
||||
autoconf.include_defines(defines)
|
||||
autoconf.include_headers(headers)
|
||||
p.outln("")
|
||||
p.outln("#define SIZE (sizeof(" .. type .. "))")
|
||||
p.outln("char info_size[] = {'I', 'N', 'F', 'O', ':', 's','i','z','e','[',")
|
||||
p.outln(" ('0' + ((SIZE / 10000)%10)),")
|
||||
p.outln(" ('0' + ((SIZE / 1000)%10)),")
|
||||
p.outln(" ('0' + ((SIZE / 100)%10)),")
|
||||
p.outln(" ('0' + ((SIZE / 10)%10)),")
|
||||
p.outln(" ('0' + (SIZE %10)),")
|
||||
p.outln(" ']', '\\0'};")
|
||||
p.outln("")
|
||||
p.outln("int main(int argc, char *argv[]) {")
|
||||
p.outln(" int require = 0;")
|
||||
p.outln(" require += info_size[argc];")
|
||||
p.outln(" (void)argv;")
|
||||
p.outln(" return require;")
|
||||
p.outln("}")
|
||||
end,
|
||||
function (e)
|
||||
-- if the compile step succeeded, we should have a binary with 'INFO:size[*****]'
|
||||
-- somewhere in there.
|
||||
local content = io.readfile(e.binary)
|
||||
if content then
|
||||
local size = string.find(content, 'INFO:size')
|
||||
if size then
|
||||
e.size = tonumber(string.sub(content, size+10, size+14))
|
||||
end
|
||||
end
|
||||
end
|
||||
)
|
||||
|
||||
if res.size then
|
||||
autoconf.set_value(cfg, 'HAVE_' .. variable, 1)
|
||||
autoconf.set_value(cfg, variable, res.size)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
---
|
||||
-- Check if the given struct or class has the specified member variable
|
||||
--
|
||||
-- @cfg : current config.
|
||||
-- @variable : variable to store the result.
|
||||
-- @type : the name of the struct or class you are interested in
|
||||
-- @member : the member which existence you want to check
|
||||
-- @headers : an optional array of header files to include.
|
||||
-- @defines : An optional array of defines to define.
|
||||
---
|
||||
function check_struct_has_member(cfg, variable, type, member, headers, defines)
|
||||
local res = autoconf.cache_compile(cfg, variable, function ()
|
||||
autoconf.include_defines(defines)
|
||||
autoconf.include_headers(headers)
|
||||
p.outln('int main(void) {')
|
||||
p.outln(' (void)sizeof(((' .. type .. '*)0)->' .. member ..');')
|
||||
p.outln(' return 0;')
|
||||
p.outln('}')
|
||||
end)
|
||||
|
||||
if res.value then
|
||||
autoconf.set_value(cfg, variable, 1)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
---
|
||||
-- Check if a symbol exists as a function, variable, or macro
|
||||
--
|
||||
-- @cfg : current config.
|
||||
-- @variable : variable to store the result.
|
||||
-- @symbol : The symbol to check for.
|
||||
-- @headers : an optional array of header files to include.
|
||||
-- @defines : An optional array of defines to define.
|
||||
---
|
||||
function check_symbol_exists(cfg, variable, symbol, headers, defines)
|
||||
local h = headers
|
||||
local res = autoconf.cache_compile(cfg, variable, function ()
|
||||
autoconf.include_defines(defines)
|
||||
autoconf.include_headers(headers)
|
||||
p.outln('int main(int argc, char** argv) {')
|
||||
p.outln(' (void)argv;')
|
||||
p.outln('#ifndef ' .. symbol)
|
||||
p.outln(' return ((int*)(&' .. symbol .. '))[argc];')
|
||||
p.outln('#else')
|
||||
p.outln(' (void)argc;')
|
||||
p.outln(' return 0;')
|
||||
p.outln('#endif')
|
||||
p.outln('}')
|
||||
end)
|
||||
|
||||
if res.value then
|
||||
autoconf.set_value(cfg, variable, 1)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
---
|
||||
-- try compiling a piece of c/c++
|
||||
---
|
||||
function autoconf.try_compile(cfg, cpp)
|
||||
local ts = autoconf.toolset(cfg)
|
||||
if ts then
|
||||
return ts.try_compile(cfg, cpp, autoconf.parameters)
|
||||
else
|
||||
p.warnOnce('autoconf', 'no toolset found, autoconf always failing.')
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function autoconf.cache_compile(cfg, entry, func, post)
|
||||
if not autoconf.cache[entry] then
|
||||
local cpp = p.capture(func)
|
||||
local res = autoconf.try_compile(cfg, cpp)
|
||||
if res then
|
||||
local e = { binary = res, value = true }
|
||||
if post then
|
||||
post(e)
|
||||
end
|
||||
autoconf.cache[entry] = e
|
||||
else
|
||||
autoconf.cache[entry] = { }
|
||||
end
|
||||
end
|
||||
return autoconf.cache[entry]
|
||||
end
|
||||
|
||||
|
||||
---
|
||||
-- get the current configured toolset, or the default.
|
||||
---
|
||||
function autoconf.toolset(cfg)
|
||||
local ts = p.config.toolset(cfg)
|
||||
if not ts then
|
||||
local tools = {
|
||||
-- Actually we always return nil on msc. see msc.lua
|
||||
['vs2010'] = p.tools.msc,
|
||||
['vs2012'] = p.tools.msc,
|
||||
['vs2013'] = p.tools.msc,
|
||||
['vs2015'] = p.tools.msc,
|
||||
['vs2017'] = p.tools.msc,
|
||||
['vs2019'] = p.tools.msc,
|
||||
['gmake'] = premake.tools.gcc,
|
||||
['gmake2'] = premake.tools.gcc,
|
||||
['codelite'] = premake.tools.gcc,
|
||||
['xcode4'] = premake.tools.clang,
|
||||
}
|
||||
ts = tools[_ACTION]
|
||||
end
|
||||
return ts
|
||||
end
|
||||
|
||||
|
||||
---
|
||||
-- store the value of the variable in the configuration
|
||||
---
|
||||
function autoconf.set_value(cfg, variable, value)
|
||||
cfg.autoconf[variable] = value
|
||||
end
|
||||
|
||||
|
||||
---
|
||||
-- write the cfg.autoconf table to the file
|
||||
---
|
||||
function autoconf.writefile(cfg, filename)
|
||||
if cfg.autoconf then
|
||||
local file = io.open(filename, "w+")
|
||||
for variable, value in pairs(cfg.autoconf) do
|
||||
file:write('#define ' .. variable .. ' ' .. tostring(value) .. (_eol or '\n'))
|
||||
end
|
||||
file:close()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
---
|
||||
-- Utility method to add a table of headers.
|
||||
---
|
||||
function autoconf.include_headers(headers)
|
||||
if headers ~= nil then
|
||||
if type(headers) == "table" then
|
||||
for _, v in ipairs(headers) do
|
||||
p.outln('#include <' .. v .. '>')
|
||||
end
|
||||
else
|
||||
p.outln('#include <' .. headers .. '>')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function autoconf.include_defines(defines)
|
||||
if defines ~= nil then
|
||||
if type(defines) == "table" then
|
||||
for _, v in ipairs(defines) do
|
||||
p.outln('#define ' .. v)
|
||||
end
|
||||
else
|
||||
p.outln('#define ' .. defines)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---
|
||||
-- attach ourselfs to the running action.
|
||||
---
|
||||
p.override(p.action, 'call', function (base, name)
|
||||
local a = p.action.get(name)
|
||||
|
||||
-- store the old callback.
|
||||
local onBaseProject = a.onProject or a.onproject
|
||||
|
||||
-- override it with our own.
|
||||
a.onProject = function(prj)
|
||||
-- go through each configuration, and call the setup configuration methods.
|
||||
for cfg in p.project.eachconfig(prj) do
|
||||
cfg.autoconf = {}
|
||||
if cfg.autoconfigure then
|
||||
verbosef('Running auto config steps for "%s/%s".', prj.name, cfg.name)
|
||||
for file, func in pairs(cfg.autoconfigure) do
|
||||
func(cfg)
|
||||
|
||||
if not (file ~= "dontWrite") then
|
||||
os.mkdir(cfg.objdir)
|
||||
local filename = path.join(cfg.objdir, file)
|
||||
autoconf.writefile(cfg, filename)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- then call the old onProject.
|
||||
if onBaseProject then
|
||||
onBaseProject(prj)
|
||||
end
|
||||
end
|
||||
|
||||
-- now call the original action.call methods
|
||||
base(name)
|
||||
end)
|
||||
18
autoconf/autoconf.lua
Normal file
18
autoconf/autoconf.lua
Normal file
@@ -0,0 +1,18 @@
|
||||
---
|
||||
-- Autoconfiguration.
|
||||
-- Copyright (c) 2016 Blizzard Entertainment
|
||||
---
|
||||
local p = premake
|
||||
|
||||
if not premake.modules.autoconf then
|
||||
p.modules.autoconf = {}
|
||||
p.modules.autoconf._VERSION = p._VERSION
|
||||
|
||||
verbosef('Loading autoconf module...')
|
||||
include('api.lua')
|
||||
include('msc.lua')
|
||||
include('clang.lua')
|
||||
include('gcc.lua')
|
||||
end
|
||||
|
||||
return p.modules.autoconf
|
||||
27
autoconf/clang.lua
Normal file
27
autoconf/clang.lua
Normal file
@@ -0,0 +1,27 @@
|
||||
---
|
||||
-- Autoconfiguration.
|
||||
-- Copyright (c) 2016 Blizzard Entertainment
|
||||
---
|
||||
local p = premake
|
||||
local clang = p.tools.clang
|
||||
|
||||
function clang.try_compile(cfg, text, parameters)
|
||||
-- write the text to a temporary file.
|
||||
local cppFile = path.join(cfg.objdir, "temp.cpp")
|
||||
if not io.writefile(cppFile, text) then
|
||||
return nil
|
||||
end
|
||||
|
||||
if parameters == nil then
|
||||
parameters = ""
|
||||
end
|
||||
|
||||
local outFile = path.join(cfg.objdir, "temp.out")
|
||||
|
||||
-- compile that text file.
|
||||
if os.execute('clang "' .. cppFile .. '" ' .. parameters .. ' -o "' .. outFile ..'" &> /dev/null') then
|
||||
return outFile
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
27
autoconf/gcc.lua
Normal file
27
autoconf/gcc.lua
Normal file
@@ -0,0 +1,27 @@
|
||||
---
|
||||
-- Autoconfiguration.
|
||||
-- Copyright (c) 2016 Blizzard Entertainment
|
||||
---
|
||||
local p = premake
|
||||
local gcc = p.tools.gcc
|
||||
|
||||
function gcc.try_compile(cfg, text, parameters)
|
||||
-- write the text to a temporary file.
|
||||
local cppFile = path.join(cfg.objdir, "temp.cpp")
|
||||
if not io.writefile(cppFile, text) then
|
||||
return nil
|
||||
end
|
||||
|
||||
if parameters == nil then
|
||||
parameters = ""
|
||||
end
|
||||
|
||||
local outFile = path.join(cfg.objdir, "temp.out")
|
||||
|
||||
-- compile that text file.
|
||||
if os.execute('gcc "' .. cppFile .. '" ' .. parameters .. ' -o "' .. outFile ..'" &> /dev/null') then
|
||||
return outFile
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
62
autoconf/msc.lua
Normal file
62
autoconf/msc.lua
Normal file
@@ -0,0 +1,62 @@
|
||||
---
|
||||
-- Autoconfiguration.
|
||||
-- Copyright (c) 2016 Blizzard Entertainment
|
||||
---
|
||||
local p = premake
|
||||
local msc = p.tools.msc
|
||||
|
||||
-- "parameters" is unused, matter of fact this file is unused - re3
|
||||
function msc.try_compile(cfg, text, parameters)
|
||||
|
||||
return nil
|
||||
--[[
|
||||
-- write the text to a temporary file.
|
||||
local cppFile = path.join(cfg.objdir, "temp.cpp")
|
||||
if not io.writefile(cppFile, text) then
|
||||
return nil
|
||||
end
|
||||
|
||||
-- write out a batch file.
|
||||
local batch = p.capture(function ()
|
||||
p.outln('@echo off')
|
||||
p.outln('SET mypath=%~dp0')
|
||||
p.outln('pushd %mypath%')
|
||||
|
||||
local map = {
|
||||
vs2010 = 'VS100COMNTOOLS',
|
||||
vs2012 = 'VS110COMNTOOLS',
|
||||
vs2013 = 'VS120COMNTOOLS',
|
||||
vs2015 = 'VS140COMNTOOLS',
|
||||
vs2017 = 'VS141COMNTOOLS',
|
||||
vs2019 = 'VS142COMNTOOLS',
|
||||
}
|
||||
|
||||
local a = map[_ACTION]
|
||||
if a then
|
||||
a = path.translate(os.getenv(a), '/')
|
||||
a = path.join(a, '../../VC/vcvarsall.bat')
|
||||
|
||||
if cfg.platform == 'x86' then
|
||||
p.outln('call "' .. a .. '" > NUL')
|
||||
else
|
||||
p.outln('call "' .. a .. '" amd64 > NUL')
|
||||
end
|
||||
|
||||
p.outln('cl.exe /nologo temp.cpp > NUL')
|
||||
else
|
||||
error('Unsupported Visual Studio version: ' .. _ACTION)
|
||||
end
|
||||
end)
|
||||
|
||||
local batchFile = path.join(cfg.objdir, "compile.bat")
|
||||
if not io.writefile(batchFile, batch) then
|
||||
return nil
|
||||
end
|
||||
|
||||
if os.execute(batchFile) then
|
||||
return path.join(cfg.objdir, "temp.exe")
|
||||
else
|
||||
return nil
|
||||
end
|
||||
--]]
|
||||
end
|
||||
@@ -28,7 +28,7 @@ find_package_handle_standard_args(MilesSDK DEFAULT_MSG MilesSDK_LIBRARIES MilesS
|
||||
if(NOT TARGET MilesSDK::MilesSDK)
|
||||
add_library(MilesSDK::MilesSDK UNKNOWN IMPORTED)
|
||||
set_target_properties(MilesSDK::MilesSDK PROPERTIES
|
||||
IMPORTED_LOCATION "${MilesSDK_LIBRARIES}
|
||||
IMPORTED_LOCATION "${MilesSDK_LIBRARIES}"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${MilesSDK_INCLUDE_DIR}"
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -18,7 +18,7 @@ find_path(mpg123_INCLUDE_DIR mpg123.h
|
||||
PATH_SUFFIXES include
|
||||
)
|
||||
|
||||
find_library(mpg123_LIBRARIES NAMES mpg123 mpg123-0
|
||||
find_library(mpg123_LIBRARIES NAMES mpg123 mpg123-0 libmpg123-0
|
||||
HINTS ${PKG_MPG123_LIBRARIES}
|
||||
PATHS "${mpg123_DIR}"
|
||||
PATH_SUFFIXES lib
|
||||
|
||||
38
cmake/nx/NXFunctions.cmake
Normal file
38
cmake/nx/NXFunctions.cmake
Normal file
@@ -0,0 +1,38 @@
|
||||
if(NOT COMMAND nx_generate_nacp)
|
||||
message(FATAL_ERROR "The `nx_generate_nacp` cmake command is not available. Please use an appropriate Nintendo Switch toolchain.")
|
||||
endif()
|
||||
|
||||
if(NOT COMMAND nx_create_nro)
|
||||
message(FATAL_ERROR "The `nx_create_nro` cmake command is not available. Please use an appropriate Nintendo Switch toolchain.")
|
||||
endif()
|
||||
|
||||
set(CMAKE_EXECUTABLE_SUFFIX ".elf")
|
||||
|
||||
function(reVC_platform_target TARGET)
|
||||
cmake_parse_arguments(RPT "INSTALL" "" "" ${ARGN})
|
||||
|
||||
get_target_property(TARGET_TYPE "${TARGET}" TYPE)
|
||||
if(TARGET_TYPE STREQUAL "EXECUTABLE")
|
||||
nx_generate_nacp(${TARGET}.nacp
|
||||
NAME "${TARGET}"
|
||||
AUTHOR "${${PROJECT}_AUTHOR}"
|
||||
VERSION "1.0.0-${GIT_SHA1}"
|
||||
)
|
||||
|
||||
nx_create_nro(${TARGET}
|
||||
NACP ${TARGET}.nacp
|
||||
ICON "${PROJECT_SOURCE_DIR}/res/images/logo_256.jpg"
|
||||
)
|
||||
|
||||
if(${PROJECT}_INSTALL AND RPT_INSTALL)
|
||||
get_target_property(TARGET_OUTPUT_NAME ${TARGET} OUTPUT_NAME)
|
||||
if(NOT TARGET_OUTPUT_NAME)
|
||||
set(TARGET_OUTPUT_NAME "${TARGET}")
|
||||
endif()
|
||||
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${TARGET_OUTPUT_NAME}.nro"
|
||||
DESTINATION "."
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
endfunction()
|
||||
Binary file not shown.
16096
codewarrior/reVC.mcp.xml
Normal file
16096
codewarrior/reVC.mcp.xml
Normal file
File diff suppressed because it is too large
Load Diff
18
conanfile.py
18
conanfile.py
@@ -5,8 +5,8 @@ import shutil
|
||||
import textwrap
|
||||
|
||||
|
||||
class ReVCConan(ConanFile):
|
||||
name = "reVC"
|
||||
class ReLCSConan(ConanFile):
|
||||
name = "reLCS"
|
||||
version = "master"
|
||||
license = "???" # FIXME: https://github.com/GTAmodding/re3/issues/794
|
||||
settings = "os", "arch", "compiler", "build_type"
|
||||
@@ -69,10 +69,10 @@ class ReVCConan(ConanFile):
|
||||
raise ConanInvalidConfiguration("Only `glfw` is supported as gl3_gfxlib.")
|
||||
#if not self.options.with_opus:
|
||||
# if not self.options["libsndfile"].with_external_libs:
|
||||
# raise ConanInvalidConfiguration("reVC with opus support requires a libsndfile built with external libs (=ogg/flac/opus/vorbis)")
|
||||
# raise ConanInvalidConfiguration("reLCS with opus support requires a libsndfile built with external libs (=ogg/flac/opus/vorbis)")
|
||||
|
||||
@property
|
||||
def _reVC_audio(self):
|
||||
def _reLCS_audio(self):
|
||||
return {
|
||||
"miles": "MSS",
|
||||
"openal": "OAL",
|
||||
@@ -111,16 +111,16 @@ class ReVCConan(ConanFile):
|
||||
include("{}/conanbuildinfo.cmake")
|
||||
conan_basic_setup(TARGETS NO_OUTPUT_DIRS)
|
||||
|
||||
add_subdirectory("{}" reVC)
|
||||
add_subdirectory("{}" reLCS)
|
||||
""").format(self.install_folder.replace("\\", "/"),
|
||||
self.source_folder.replace("\\", "/")))
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
cmake = CMake(self)
|
||||
cmake.definitions["REVC_AUDIO"] = self._reVC_audio
|
||||
cmake.definitions["REVC_WITH_OPUS"] = self.options.with_opus
|
||||
cmake.definitions["REVC_INSTALL"] = True
|
||||
cmake.definitions["REVC_VENDORED_LIBRW"] = False
|
||||
cmake.definitions["RELCS_AUDIO"] = self._reLCS_audio
|
||||
cmake.definitions["RELCS_WITH_OPUS"] = self.options.with_opus
|
||||
cmake.definitions["RELCS_INSTALL"] = True
|
||||
cmake.definitions["RELCS_VENDORED_LIBRW"] = False
|
||||
env = {}
|
||||
if self._os_is_playstation2:
|
||||
cmake.definitions["CMAKE_TOOLCHAIN_FILE"] = self.deps_user_info["ps2dev-cmaketoolchain"].cmake_toolchain_file
|
||||
|
||||
BIN
gamefiles/TEXT/ENGLISH.gxt
Normal file
BIN
gamefiles/TEXT/ENGLISH.gxt
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
gamefiles/models/frontend_nsw.txd
Normal file
BIN
gamefiles/models/frontend_nsw.txd
Normal file
Binary file not shown.
Binary file not shown.
BIN
gamefiles/models/nswbtns.txd
Normal file
BIN
gamefiles/models/nswbtns.txd
Normal file
Binary file not shown.
909
premake5.lua
909
premake5.lua
@@ -1,421 +1,488 @@
|
||||
newoption {
|
||||
trigger = "glewdir",
|
||||
value = "PATH",
|
||||
description = "Directory of GLEW",
|
||||
default = "vendor/glew-2.1.0"
|
||||
}
|
||||
|
||||
newoption {
|
||||
trigger = "glfwdir64",
|
||||
value = "PATH",
|
||||
description = "Directory of glfw",
|
||||
default = "vendor/glfw-3.3.2.bin.WIN64",
|
||||
}
|
||||
|
||||
newoption {
|
||||
trigger = "glfwdir32",
|
||||
value = "PATH",
|
||||
description = "Directory of glfw",
|
||||
default = "vendor/glfw-3.3.2.bin.WIN32",
|
||||
}
|
||||
|
||||
newoption {
|
||||
trigger = "with-asan",
|
||||
description = "Build with address sanitizer"
|
||||
}
|
||||
|
||||
newoption {
|
||||
trigger = "with-librw",
|
||||
description = "Build and use librw from this solution"
|
||||
}
|
||||
|
||||
newoption {
|
||||
trigger = "with-opus",
|
||||
description = "Build with opus"
|
||||
}
|
||||
|
||||
newoption {
|
||||
trigger = "lto",
|
||||
description = "Use link time optimization"
|
||||
}
|
||||
|
||||
if(_OPTIONS["with-librw"]) then
|
||||
Librw = "vendor/librw"
|
||||
else
|
||||
Librw = os.getenv("LIBRW") or "vendor/librw"
|
||||
end
|
||||
|
||||
function getsys(a)
|
||||
if a == 'windows' then
|
||||
return 'win'
|
||||
end
|
||||
return a
|
||||
end
|
||||
|
||||
function getarch(a)
|
||||
if a == 'x86_64' then
|
||||
return 'amd64'
|
||||
elseif a == 'ARM' then
|
||||
return 'arm'
|
||||
elseif a == 'ARM64' then
|
||||
return 'arm64'
|
||||
end
|
||||
return a
|
||||
end
|
||||
|
||||
workspace "reVC"
|
||||
language "C++"
|
||||
configurations { "Debug", "Release", "Vanilla" }
|
||||
startproject "reVC"
|
||||
location "build"
|
||||
symbols "Full"
|
||||
staticruntime "off"
|
||||
|
||||
if _OPTIONS["with-asan"] then
|
||||
buildoptions { "-fsanitize=address -g3 -fno-omit-frame-pointer" }
|
||||
linkoptions { "-fsanitize=address" }
|
||||
end
|
||||
|
||||
filter { "system:windows" }
|
||||
platforms {
|
||||
"win-x86-RW34_d3d8-mss",
|
||||
"win-x86-librw_d3d9-mss",
|
||||
"win-x86-librw_gl3_glfw-mss",
|
||||
"win-x86-RW34_d3d8-oal",
|
||||
"win-x86-librw_d3d9-oal",
|
||||
"win-x86-librw_gl3_glfw-oal",
|
||||
"win-amd64-librw_d3d9-oal",
|
||||
"win-amd64-librw_gl3_glfw-oal",
|
||||
}
|
||||
|
||||
filter { "system:linux" }
|
||||
platforms {
|
||||
"linux-x86-librw_gl3_glfw-oal",
|
||||
"linux-amd64-librw_gl3_glfw-oal",
|
||||
"linux-arm-librw_gl3_glfw-oal",
|
||||
"linux-arm64-librw_gl3_glfw-oal",
|
||||
}
|
||||
|
||||
filter { "system:bsd" }
|
||||
platforms {
|
||||
"bsd-x86-librw_gl3_glfw-oal",
|
||||
"bsd-amd64-librw_gl3_glfw-oal",
|
||||
"bsd-arm-librw_gl3_glfw-oal",
|
||||
"bsd-arm64-librw_gl3_glfw-oal"
|
||||
}
|
||||
|
||||
filter { "system:macosx" }
|
||||
platforms {
|
||||
"macosx-arm64-librw_gl3_glfw-oal",
|
||||
"macosx-amd64-librw_gl3_glfw-oal",
|
||||
}
|
||||
|
||||
filter "configurations:Debug"
|
||||
defines { "DEBUG" }
|
||||
|
||||
filter "configurations:not Debug"
|
||||
defines { "NDEBUG" }
|
||||
optimize "Speed"
|
||||
if(_OPTIONS["lto"]) then
|
||||
flags { "LinkTimeOptimization" }
|
||||
end
|
||||
|
||||
filter "configurations:Vanilla"
|
||||
defines { "VANILLA_DEFINES" }
|
||||
|
||||
filter { "platforms:win*" }
|
||||
system "windows"
|
||||
|
||||
filter { "platforms:linux*" }
|
||||
system "linux"
|
||||
|
||||
filter { "platforms:bsd*" }
|
||||
system "bsd"
|
||||
|
||||
filter { "platforms:macosx*" }
|
||||
system "macosx"
|
||||
|
||||
filter { "platforms:*x86*" }
|
||||
architecture "x86"
|
||||
|
||||
filter { "platforms:*amd64*" }
|
||||
architecture "amd64"
|
||||
|
||||
filter { "platforms:*arm*" }
|
||||
architecture "ARM"
|
||||
|
||||
filter { "platforms:macosx-arm64-*" }
|
||||
buildoptions { "-target", "arm64-apple-macos11", "-std=gnu++14" }
|
||||
|
||||
filter { "platforms:macosx-amd64-*" }
|
||||
buildoptions { "-target", "x86_64-apple-macos10.12", "-std=gnu++14" }
|
||||
|
||||
filter { "platforms:*librw_d3d9*" }
|
||||
defines { "RW_D3D9" }
|
||||
if(not _OPTIONS["with-librw"]) then
|
||||
libdirs { path.join(Librw, "lib/win-%{getarch(cfg.architecture)}-d3d9/%{cfg.buildcfg}") }
|
||||
end
|
||||
|
||||
filter "platforms:*librw_gl3_glfw*"
|
||||
defines { "RW_GL3" }
|
||||
includedirs { path.join(_OPTIONS["glewdir"], "include") }
|
||||
if(not _OPTIONS["with-librw"]) then
|
||||
libdirs { path.join(Librw, "lib/%{getsys(cfg.system)}-%{getarch(cfg.architecture)}-gl3/%{cfg.buildcfg}") }
|
||||
end
|
||||
|
||||
filter "platforms:*x86-librw_gl3_glfw*"
|
||||
includedirs { path.join(_OPTIONS["glfwdir32"], "include") }
|
||||
|
||||
filter "platforms:*amd64-librw_gl3_glfw*"
|
||||
includedirs { path.join(_OPTIONS["glfwdir64"], "include") }
|
||||
|
||||
filter "platforms:win*librw_gl3_glfw*"
|
||||
defines { "GLEW_STATIC" }
|
||||
|
||||
filter {}
|
||||
|
||||
function setpaths (gamepath, exepath)
|
||||
if (gamepath) then
|
||||
postbuildcommands {
|
||||
'{COPYFILE} "%{cfg.buildtarget.abspath}" "' .. gamepath .. '%{cfg.buildtarget.name}"'
|
||||
}
|
||||
debugdir (gamepath)
|
||||
if (exepath) then
|
||||
-- Used VS variable $(TargetFileName) because it doesn't accept premake tokens. Does debugcommand even work outside VS??
|
||||
debugcommand (gamepath .. "$(TargetFileName)")
|
||||
dir, file = exepath:match'(.*/)(.*)'
|
||||
debugdir (gamepath .. (dir or ""))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if(_OPTIONS["with-librw"]) then
|
||||
project "librw"
|
||||
kind "StaticLib"
|
||||
targetname "rw"
|
||||
targetdir(path.join(Librw, "lib/%{cfg.platform}/%{cfg.buildcfg}"))
|
||||
files { path.join(Librw, "src/*.*") }
|
||||
files { path.join(Librw, "src/*/*.*") }
|
||||
|
||||
filter { "platforms:*x86*" }
|
||||
architecture "x86"
|
||||
|
||||
filter { "platforms:*amd64*" }
|
||||
architecture "amd64"
|
||||
|
||||
filter "platforms:win*"
|
||||
defines { "_CRT_SECURE_NO_WARNINGS", "_CRT_NONSTDC_NO_DEPRECATE" }
|
||||
staticruntime "on"
|
||||
buildoptions { "/Zc:sizedDealloc-" }
|
||||
|
||||
filter "platforms:bsd*"
|
||||
includedirs { "/usr/local/include" }
|
||||
libdirs { "/usr/local/lib" }
|
||||
|
||||
filter "platforms:macosx*"
|
||||
-- Support MacPorts and Homebrew
|
||||
includedirs { "/opt/local/include" }
|
||||
includedirs {"/usr/local/include" }
|
||||
libdirs { "/opt/local/lib" }
|
||||
libdirs { "/usr/local/lib" }
|
||||
|
||||
filter "platforms:*gl3_glfw*"
|
||||
staticruntime "off"
|
||||
|
||||
filter "platforms:*RW34*"
|
||||
flags { "ExcludeFromBuild" }
|
||||
filter {}
|
||||
end
|
||||
|
||||
local function addSrcFiles( prefix )
|
||||
return prefix .. "/*cpp", prefix .. "/*.h", prefix .. "/*.c", prefix .. "/*.ico", prefix .. "/*.rc"
|
||||
end
|
||||
|
||||
project "reVC"
|
||||
kind "WindowedApp"
|
||||
targetname "reVC"
|
||||
targetdir "bin/%{cfg.platform}/%{cfg.buildcfg}"
|
||||
|
||||
if(_OPTIONS["with-librw"]) then
|
||||
dependson "librw"
|
||||
end
|
||||
|
||||
files { addSrcFiles("src") }
|
||||
files { addSrcFiles("src/animation") }
|
||||
files { addSrcFiles("src/audio") }
|
||||
files { addSrcFiles("src/audio/eax") }
|
||||
files { addSrcFiles("src/audio/oal") }
|
||||
files { addSrcFiles("src/buildings") }
|
||||
files { addSrcFiles("src/collision") }
|
||||
files { addSrcFiles("src/control") }
|
||||
files { addSrcFiles("src/core") }
|
||||
files { addSrcFiles("src/entities") }
|
||||
files { addSrcFiles("src/math") }
|
||||
files { addSrcFiles("src/modelinfo") }
|
||||
files { addSrcFiles("src/objects") }
|
||||
files { addSrcFiles("src/peds") }
|
||||
files { addSrcFiles("src/render") }
|
||||
files { addSrcFiles("src/rw") }
|
||||
files { addSrcFiles("src/save") }
|
||||
files { addSrcFiles("src/skel") }
|
||||
files { addSrcFiles("src/skel/glfw") }
|
||||
files { addSrcFiles("src/text") }
|
||||
files { addSrcFiles("src/vehicles") }
|
||||
files { addSrcFiles("src/weapons") }
|
||||
files { addSrcFiles("src/extras") }
|
||||
files { "src/extras/GitSHA1.cpp" } -- this won't be in repo in first build
|
||||
|
||||
includedirs { "src" }
|
||||
includedirs { "src/animation" }
|
||||
includedirs { "src/audio" }
|
||||
includedirs { "src/audio/eax" }
|
||||
includedirs { "src/audio/oal" }
|
||||
includedirs { "src/buildings" }
|
||||
includedirs { "src/collision" }
|
||||
includedirs { "src/control" }
|
||||
includedirs { "src/core" }
|
||||
includedirs { "src/entities" }
|
||||
includedirs { "src/math" }
|
||||
includedirs { "src/modelinfo" }
|
||||
includedirs { "src/objects" }
|
||||
includedirs { "src/peds" }
|
||||
includedirs { "src/render" }
|
||||
includedirs { "src/rw" }
|
||||
includedirs { "src/save/" }
|
||||
includedirs { "src/skel/" }
|
||||
includedirs { "src/skel/glfw" }
|
||||
includedirs { "src/text" }
|
||||
includedirs { "src/vehicles" }
|
||||
includedirs { "src/weapons" }
|
||||
includedirs { "src/extras" }
|
||||
|
||||
if _OPTIONS["with-opus"] then
|
||||
includedirs { "vendor/ogg/include" }
|
||||
includedirs { "vendor/opus/include" }
|
||||
includedirs { "vendor/opusfile/include" }
|
||||
end
|
||||
|
||||
filter "platforms:*mss"
|
||||
defines { "AUDIO_MSS" }
|
||||
includedirs { "vendor/milessdk/include" }
|
||||
libdirs { "vendor/milessdk/lib" }
|
||||
|
||||
if _OPTIONS["with-opus"] then
|
||||
filter "platforms:win*"
|
||||
libdirs { "vendor/ogg/win32/VS2015/Win32/%{cfg.buildcfg}" }
|
||||
libdirs { "vendor/opus/win32/VS2015/Win32/%{cfg.buildcfg}" }
|
||||
libdirs { "vendor/opusfile/win32/VS2015/Win32/Release-NoHTTP" }
|
||||
filter {}
|
||||
defines { "AUDIO_OPUS" }
|
||||
end
|
||||
|
||||
filter "platforms:*oal"
|
||||
defines { "AUDIO_OAL" }
|
||||
|
||||
filter {}
|
||||
if(os.getenv("GTA_VC_RE_DIR")) then
|
||||
setpaths(os.getenv("GTA_VC_RE_DIR") .. "/", "%(cfg.buildtarget.name)")
|
||||
end
|
||||
|
||||
filter "platforms:win*"
|
||||
files { addSrcFiles("src/skel/win") }
|
||||
includedirs { "src/skel/win" }
|
||||
buildoptions { "/Zc:sizedDealloc-" }
|
||||
linkoptions "/SAFESEH:NO"
|
||||
characterset ("MBCS")
|
||||
targetextension ".exe"
|
||||
if(_OPTIONS["with-librw"]) then
|
||||
-- external librw is dynamic
|
||||
staticruntime "on"
|
||||
end
|
||||
prebuildcommands { '"%{prj.location}..\\printHash.bat" "%{prj.location}..\\src\\extras\\GitSHA1.cpp"' }
|
||||
|
||||
filter "platforms:not win*"
|
||||
prebuildcommands { '"%{prj.location}/../printHash.sh" "%{prj.location}/../src/extras/GitSHA1.cpp"' }
|
||||
|
||||
filter "platforms:win*glfw*"
|
||||
staticruntime "off"
|
||||
|
||||
filter "platforms:win*oal"
|
||||
includedirs { "vendor/openal-soft/include" }
|
||||
includedirs { "vendor/libsndfile/include" }
|
||||
includedirs { "vendor/mpg123/include" }
|
||||
|
||||
filter "platforms:win-x86*oal"
|
||||
libdirs { "vendor/mpg123/lib/Win32" }
|
||||
libdirs { "vendor/libsndfile/lib/Win32" }
|
||||
libdirs { "vendor/openal-soft/libs/Win32" }
|
||||
|
||||
filter "platforms:win-amd64*oal"
|
||||
libdirs { "vendor/mpg123/lib/Win64" }
|
||||
libdirs { "vendor/libsndfile/lib/Win64" }
|
||||
libdirs { "vendor/openal-soft/libs/Win64" }
|
||||
|
||||
filter "platforms:linux*oal"
|
||||
links { "openal", "mpg123", "sndfile", "pthread" }
|
||||
|
||||
filter "platforms:bsd*oal"
|
||||
links { "openal", "mpg123", "sndfile", "pthread" }
|
||||
|
||||
filter "platforms:macosx*oal"
|
||||
links { "openal", "mpg123", "sndfile", "pthread" }
|
||||
includedirs { "/usr/local/opt/openal-soft/include" }
|
||||
libdirs { "/usr/local/opt/openal-soft/lib" }
|
||||
|
||||
if _OPTIONS["with-opus"] then
|
||||
filter {}
|
||||
links { "libogg" }
|
||||
links { "opus" }
|
||||
links { "opusfile" }
|
||||
end
|
||||
|
||||
filter "platforms:*RW34*"
|
||||
includedirs { "sdk/rwsdk/include/d3d8" }
|
||||
libdirs { "sdk/rwsdk/lib/d3d8/release" }
|
||||
links { "rwcore", "rpworld", "rpmatfx", "rpskin", "rphanim", "rtbmp", "rtquat", "rtanim", "rtcharse", "rpanisot" }
|
||||
defines { "RWLIBS" }
|
||||
linkoptions "/SECTION:_rwcseg,ER!W /MERGE:_rwcseg=.text"
|
||||
|
||||
filter "platforms:*librw*"
|
||||
defines { "LIBRW" }
|
||||
files { addSrcFiles("src/fakerw") }
|
||||
includedirs { "src/fakerw" }
|
||||
includedirs { Librw }
|
||||
if(_OPTIONS["with-librw"]) then
|
||||
libdirs { "vendor/librw/lib/%{cfg.platform}/%{cfg.buildcfg}" }
|
||||
end
|
||||
links { "rw" }
|
||||
|
||||
filter "platforms:*d3d9*"
|
||||
defines { "USE_D3D9" }
|
||||
links { "d3d9" }
|
||||
|
||||
filter "platforms:*x86*d3d*"
|
||||
includedirs { "sdk/dx8sdk/include" }
|
||||
libdirs { "sdk/dx8sdk/lib" }
|
||||
|
||||
filter "platforms:win-x86*gl3_glfw*"
|
||||
libdirs { path.join(_OPTIONS["glewdir"], "lib/Release/Win32") }
|
||||
libdirs { path.join(_OPTIONS["glfwdir32"], "lib-" .. string.gsub(_ACTION or '', "vs", "vc")) }
|
||||
links { "opengl32", "glew32s", "glfw3" }
|
||||
|
||||
filter "platforms:win-amd64*gl3_glfw*"
|
||||
libdirs { path.join(_OPTIONS["glewdir"], "lib/Release/x64") }
|
||||
libdirs { path.join(_OPTIONS["glfwdir64"], "lib-" .. string.gsub(_ACTION or '', "vs", "vc")) }
|
||||
links { "opengl32", "glew32s", "glfw3" }
|
||||
|
||||
filter "platforms:linux*gl3_glfw*"
|
||||
links { "GL", "GLEW", "glfw" }
|
||||
|
||||
filter "platforms:bsd*gl3_glfw*"
|
||||
links { "GL", "GLEW", "glfw", "sysinfo" }
|
||||
includedirs { "/usr/local/include" }
|
||||
libdirs { "/usr/local/lib" }
|
||||
|
||||
filter "platforms:macosx*gl3_glfw*"
|
||||
links { "GLEW", "glfw" }
|
||||
linkoptions { "-framework OpenGL" }
|
||||
includedirs { "/opt/local/include" }
|
||||
includedirs { "/usr/local/include" }
|
||||
libdirs { "/opt/local/lib" }
|
||||
libdirs { "/usr/local/lib" }
|
||||
newoption {
|
||||
trigger = "glfwdir64",
|
||||
value = "PATH",
|
||||
description = "Directory of glfw",
|
||||
default = "vendor/glfw-3.3.2.bin.WIN64",
|
||||
}
|
||||
|
||||
newoption {
|
||||
trigger = "glfwdir32",
|
||||
value = "PATH",
|
||||
description = "Directory of glfw",
|
||||
default = "vendor/glfw-3.3.2.bin.WIN32",
|
||||
}
|
||||
|
||||
newoption {
|
||||
trigger = "with-asan",
|
||||
description = "Build with address sanitizer"
|
||||
}
|
||||
|
||||
newoption {
|
||||
trigger = "with-librw",
|
||||
description = "Build and use librw from this solution"
|
||||
}
|
||||
|
||||
newoption {
|
||||
trigger = "with-opus",
|
||||
description = "Build with opus"
|
||||
}
|
||||
|
||||
newoption {
|
||||
trigger = "with-lto",
|
||||
description = "Build with link time optimization"
|
||||
}
|
||||
|
||||
newoption {
|
||||
trigger = "no-git-hash",
|
||||
description = "Don't print git commit hash into binary"
|
||||
}
|
||||
|
||||
newoption {
|
||||
trigger = "no-full-paths",
|
||||
description = "Don't print full paths into binary"
|
||||
}
|
||||
|
||||
require("autoconf")
|
||||
|
||||
if(_OPTIONS["with-librw"]) then
|
||||
Librw = "vendor/librw"
|
||||
else
|
||||
Librw = os.getenv("LIBRW") or "vendor/librw"
|
||||
end
|
||||
|
||||
function getsys(a)
|
||||
if a == 'windows' then
|
||||
return 'win'
|
||||
end
|
||||
return a
|
||||
end
|
||||
|
||||
function getarch(a)
|
||||
if a == 'x86_64' then
|
||||
return 'amd64'
|
||||
elseif a == 'ARM' then
|
||||
return 'arm'
|
||||
elseif a == 'ARM64' then
|
||||
return 'arm64'
|
||||
end
|
||||
return a
|
||||
end
|
||||
|
||||
workspace "reLCS"
|
||||
language "C++"
|
||||
configurations { "Debug", "Release" }
|
||||
startproject "reLCS"
|
||||
location "build"
|
||||
symbols "Full"
|
||||
staticruntime "off"
|
||||
|
||||
-- for CVECTORHACK
|
||||
configuration { "gmake*" }
|
||||
buildoptions { "-fpermissive" }
|
||||
|
||||
filter { "platforms:macosx*" }
|
||||
buildoptions { "-Wno-address-of-temporary" }
|
||||
|
||||
if _OPTIONS["with-asan"] then
|
||||
buildoptions { "-fsanitize=address -g3 -fno-omit-frame-pointer" }
|
||||
linkoptions { "-fsanitize=address" }
|
||||
end
|
||||
|
||||
filter { "system:windows" }
|
||||
configurations { "Vanilla" }
|
||||
platforms {
|
||||
"win-x86-RW34_d3d8-mss",
|
||||
"win-x86-librw_d3d9-mss",
|
||||
"win-x86-librw_gl3_glfw-mss",
|
||||
"win-x86-RW34_d3d8-oal",
|
||||
"win-x86-librw_d3d9-oal",
|
||||
"win-x86-librw_gl3_glfw-oal",
|
||||
"win-amd64-librw_d3d9-oal",
|
||||
"win-amd64-librw_gl3_glfw-oal",
|
||||
}
|
||||
|
||||
filter { "system:linux" }
|
||||
platforms {
|
||||
"linux-x86-librw_gl3_glfw-oal",
|
||||
"linux-amd64-librw_gl3_glfw-oal",
|
||||
"linux-arm-librw_gl3_glfw-oal",
|
||||
"linux-arm64-librw_gl3_glfw-oal",
|
||||
}
|
||||
|
||||
filter { "system:bsd" }
|
||||
platforms {
|
||||
"bsd-x86-librw_gl3_glfw-oal",
|
||||
"bsd-amd64-librw_gl3_glfw-oal",
|
||||
"bsd-arm-librw_gl3_glfw-oal",
|
||||
"bsd-arm64-librw_gl3_glfw-oal"
|
||||
}
|
||||
|
||||
filter { "system:macosx" }
|
||||
platforms {
|
||||
"macosx-arm64-librw_gl3_glfw-oal",
|
||||
"macosx-amd64-librw_gl3_glfw-oal",
|
||||
}
|
||||
|
||||
filter "configurations:Debug"
|
||||
defines { "DEBUG" }
|
||||
|
||||
filter "configurations:not Debug"
|
||||
defines { "NDEBUG" }
|
||||
optimize "Speed"
|
||||
if(_OPTIONS["with-lto"]) then
|
||||
flags { "LinkTimeOptimization" }
|
||||
end
|
||||
|
||||
filter { "platforms:win*" }
|
||||
system "windows"
|
||||
|
||||
filter { "platforms:linux*" }
|
||||
system "linux"
|
||||
|
||||
filter { "platforms:bsd*" }
|
||||
system "bsd"
|
||||
|
||||
filter { "platforms:macosx*" }
|
||||
system "macosx"
|
||||
|
||||
filter { "platforms:*x86*" }
|
||||
architecture "x86"
|
||||
|
||||
filter { "platforms:*amd64*" }
|
||||
architecture "amd64"
|
||||
|
||||
filter { "platforms:*arm*" }
|
||||
architecture "ARM"
|
||||
|
||||
filter { "platforms:macosx-arm64-*", "files:**.cpp"}
|
||||
buildoptions { "-target", "arm64-apple-macos11", "-std=gnu++14" }
|
||||
|
||||
filter { "platforms:macosx-arm64-*", "files:**.c"}
|
||||
buildoptions { "-target", "arm64-apple-macos11" }
|
||||
|
||||
filter { "platforms:macosx-amd64-*", "files:**.cpp"}
|
||||
buildoptions { "-target", "x86_64-apple-macos10.12", "-std=gnu++14" }
|
||||
|
||||
filter { "platforms:macosx-amd64-*", "files:**.c"}
|
||||
buildoptions { "-target", "x86_64-apple-macos10.12" }
|
||||
|
||||
filter { "platforms:*librw_d3d9*" }
|
||||
defines { "RW_D3D9" }
|
||||
if(not _OPTIONS["with-librw"]) then
|
||||
libdirs { path.join(Librw, "lib/win-%{getarch(cfg.architecture)}-d3d9/%{cfg.buildcfg}") }
|
||||
end
|
||||
|
||||
filter "platforms:*librw_gl3_glfw*"
|
||||
defines { "RW_GL3" }
|
||||
if(not _OPTIONS["with-librw"]) then
|
||||
libdirs { path.join(Librw, "lib/%{getsys(cfg.system)}-%{getarch(cfg.architecture)}-gl3/%{cfg.buildcfg}") }
|
||||
end
|
||||
|
||||
filter "platforms:*x86-librw_gl3_glfw*"
|
||||
includedirs { path.join(_OPTIONS["glfwdir32"], "include") }
|
||||
|
||||
filter "platforms:*amd64-librw_gl3_glfw*"
|
||||
includedirs { path.join(_OPTIONS["glfwdir64"], "include") }
|
||||
|
||||
filter {}
|
||||
|
||||
function setpaths (gamepath, exepath)
|
||||
if (gamepath) then
|
||||
postbuildcommands {
|
||||
'{COPYFILE} "%{cfg.buildtarget.abspath}" "' .. gamepath .. '%{cfg.buildtarget.name}"'
|
||||
}
|
||||
debugdir (gamepath)
|
||||
if (exepath) then
|
||||
-- Used VS variable $(TargetFileName) because it doesn't accept premake tokens. Does debugcommand even work outside VS??
|
||||
debugcommand (gamepath .. "$(TargetFileName)")
|
||||
dir, file = exepath:match'(.*/)(.*)'
|
||||
debugdir (gamepath .. (dir or ""))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if(_OPTIONS["with-librw"]) then
|
||||
project "librw"
|
||||
kind "StaticLib"
|
||||
targetname "rw"
|
||||
targetdir(path.join(Librw, "lib/%{cfg.platform}/%{cfg.buildcfg}"))
|
||||
files { path.join(Librw, "src/*.*") }
|
||||
files { path.join(Librw, "src/*/*.*") }
|
||||
files { path.join(Librw, "src/gl/*/*.*") }
|
||||
|
||||
filter { "platforms:*x86*" }
|
||||
architecture "x86"
|
||||
|
||||
filter { "platforms:*amd64*" }
|
||||
architecture "amd64"
|
||||
|
||||
filter "platforms:win*"
|
||||
defines { "_CRT_SECURE_NO_WARNINGS", "_CRT_NONSTDC_NO_DEPRECATE" }
|
||||
staticruntime "on"
|
||||
buildoptions { "/Zc:sizedDealloc-" }
|
||||
|
||||
filter "platforms:bsd*"
|
||||
includedirs { "/usr/local/include" }
|
||||
libdirs { "/usr/local/lib" }
|
||||
|
||||
-- Support MacPorts and Homebrew
|
||||
filter "platforms:macosx-arm64-*"
|
||||
includedirs { "/opt/local/include" }
|
||||
includedirs {"/opt/homebrew/include" }
|
||||
libdirs { "/opt/local/lib" }
|
||||
libdirs { "/opt/homebrew/lib" }
|
||||
|
||||
filter "platforms:macosx-amd64-*"
|
||||
includedirs { "/opt/local/include" }
|
||||
includedirs {"/usr/local/include" }
|
||||
libdirs { "/opt/local/lib" }
|
||||
libdirs { "/usr/local/lib" }
|
||||
|
||||
filter "platforms:*gl3_glfw*"
|
||||
staticruntime "off"
|
||||
|
||||
filter "platforms:*RW34*"
|
||||
flags { "ExcludeFromBuild" }
|
||||
filter {}
|
||||
end
|
||||
|
||||
local function addSrcFiles( prefix )
|
||||
return prefix .. "/*cpp", prefix .. "/*.h", prefix .. "/*.c", prefix .. "/*.ico", prefix .. "/*.rc"
|
||||
end
|
||||
|
||||
project "reLCS"
|
||||
kind "WindowedApp"
|
||||
targetname "reLCS"
|
||||
targetdir "bin/%{cfg.platform}/%{cfg.buildcfg}"
|
||||
|
||||
if(_OPTIONS["with-librw"]) then
|
||||
dependson "librw"
|
||||
end
|
||||
|
||||
files { addSrcFiles("src") }
|
||||
files { addSrcFiles("src/animation") }
|
||||
files { addSrcFiles("src/audio") }
|
||||
files { addSrcFiles("src/audio/eax") }
|
||||
files { addSrcFiles("src/audio/oal") }
|
||||
files { addSrcFiles("src/buildings") }
|
||||
files { addSrcFiles("src/collision") }
|
||||
files { addSrcFiles("src/control") }
|
||||
files { addSrcFiles("src/core") }
|
||||
files { addSrcFiles("src/entities") }
|
||||
files { addSrcFiles("src/leeds") }
|
||||
files { addSrcFiles("src/leeds/base") }
|
||||
files { addSrcFiles("src/math") }
|
||||
files { addSrcFiles("src/modelinfo") }
|
||||
files { addSrcFiles("src/objects") }
|
||||
files { addSrcFiles("src/peds") }
|
||||
files { addSrcFiles("src/renderer") }
|
||||
files { addSrcFiles("src/rw") }
|
||||
files { addSrcFiles("src/save") }
|
||||
files { addSrcFiles("src/skel") }
|
||||
files { addSrcFiles("src/skel/glfw") }
|
||||
files { addSrcFiles("src/text") }
|
||||
files { addSrcFiles("src/vehicles") }
|
||||
files { addSrcFiles("src/weapons") }
|
||||
files { addSrcFiles("src/extras") }
|
||||
if(not _OPTIONS["no-git-hash"]) then
|
||||
files { "src/extras/GitSHA1.cpp" } -- this won't be in repo in first build
|
||||
else
|
||||
removefiles { "src/extras/GitSHA1.cpp" } -- but it will be everytime after
|
||||
end
|
||||
|
||||
includedirs { "src" }
|
||||
includedirs { "src/animation" }
|
||||
includedirs { "src/audio" }
|
||||
includedirs { "src/audio/eax" }
|
||||
includedirs { "src/audio/oal" }
|
||||
includedirs { "src/buildings" }
|
||||
includedirs { "src/collision" }
|
||||
includedirs { "src/control" }
|
||||
includedirs { "src/core" }
|
||||
includedirs { "src/entities" }
|
||||
includedirs { "src/leeds" }
|
||||
includedirs { "src/leeds/base" }
|
||||
includedirs { "src/math" }
|
||||
includedirs { "src/modelinfo" }
|
||||
includedirs { "src/objects" }
|
||||
includedirs { "src/peds" }
|
||||
includedirs { "src/renderer" }
|
||||
includedirs { "src/rw" }
|
||||
includedirs { "src/save/" }
|
||||
includedirs { "src/skel/" }
|
||||
includedirs { "src/skel/glfw" }
|
||||
includedirs { "src/text" }
|
||||
includedirs { "src/vehicles" }
|
||||
includedirs { "src/weapons" }
|
||||
includedirs { "src/extras" }
|
||||
|
||||
if(not _OPTIONS["no-git-hash"]) then
|
||||
defines { "USE_OUR_VERSIONING" }
|
||||
end
|
||||
|
||||
if _OPTIONS["with-opus"] then
|
||||
includedirs { "vendor/ogg/include" }
|
||||
includedirs { "vendor/opus/include" }
|
||||
includedirs { "vendor/opusfile/include" }
|
||||
end
|
||||
|
||||
filter "configurations:Vanilla"
|
||||
defines { "VANILLA_DEFINES" }
|
||||
|
||||
filter "platforms:*mss"
|
||||
defines { "AUDIO_MSS" }
|
||||
includedirs { "vendor/milessdk/include" }
|
||||
libdirs { "vendor/milessdk/lib" }
|
||||
|
||||
if _OPTIONS["with-opus"] then
|
||||
filter "platforms:win*"
|
||||
libdirs { "vendor/ogg/win32/VS2015/Win32/%{cfg.buildcfg}" }
|
||||
libdirs { "vendor/opus/win32/VS2015/Win32/%{cfg.buildcfg}" }
|
||||
libdirs { "vendor/opusfile/win32/VS2015/Win32/Release-NoHTTP" }
|
||||
filter {}
|
||||
defines { "AUDIO_OPUS" }
|
||||
end
|
||||
|
||||
filter "platforms:*oal"
|
||||
defines { "AUDIO_OAL" }
|
||||
|
||||
filter {}
|
||||
if(os.getenv("GTA_LCS_RE_DIR")) then
|
||||
setpaths(os.getenv("GTA_LCS_RE_DIR") .. "/", "%(cfg.buildtarget.name)")
|
||||
end
|
||||
|
||||
filter "platforms:win*"
|
||||
files { addSrcFiles("src/skel/win") }
|
||||
includedirs { "src/skel/win" }
|
||||
buildoptions { "/Zc:sizedDealloc-" }
|
||||
linkoptions "/SAFESEH:NO"
|
||||
characterset ("MBCS")
|
||||
targetextension ".exe"
|
||||
if(_OPTIONS["no-full-paths"]) then
|
||||
usefullpaths "off"
|
||||
linkoptions "/PDBALTPATH:%_PDB%"
|
||||
end
|
||||
if(_OPTIONS["with-librw"]) then
|
||||
-- external librw is dynamic
|
||||
staticruntime "on"
|
||||
end
|
||||
if(not _OPTIONS["no-git-hash"]) then
|
||||
prebuildcommands { '"%{prj.location}..\\printHash.bat" "%{prj.location}..\\src\\extras\\GitSHA1.cpp"' }
|
||||
end
|
||||
|
||||
filter "platforms:not win*"
|
||||
if(not _OPTIONS["no-git-hash"]) then
|
||||
prebuildcommands { '"%{prj.location}/../printHash.sh" "%{prj.location}/../src/extras/GitSHA1.cpp"' }
|
||||
end
|
||||
|
||||
filter "platforms:win*glfw*"
|
||||
staticruntime "off"
|
||||
|
||||
filter "platforms:*glfw*"
|
||||
premake.modules.autoconf.parameters = "-lglfw -lX11"
|
||||
autoconfigure {
|
||||
-- iterates all configs and runs on them
|
||||
["dontWrite"] = function (cfg)
|
||||
check_symbol_exists(cfg, "haveX11", "glfwGetX11Display", { "X11/Xlib.h", "X11/XKBlib.h", "GLFW/glfw3.h", "GLFW/glfw3native.h" }, "GLFW_EXPOSE_NATIVE_X11")
|
||||
if cfg.autoconf["haveX11"] ~= nil and cfg.autoconf["haveX11"] == 1 then
|
||||
table.insert(cfg.links, "X11")
|
||||
table.insert(cfg.defines, "GET_KEYBOARD_INPUT_FROM_X11")
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
filter "platforms:win*oal"
|
||||
includedirs { "vendor/openal-soft/include" }
|
||||
includedirs { "vendor/libsndfile/include" }
|
||||
includedirs { "vendor/mpg123/include" }
|
||||
|
||||
filter "platforms:win-x86*oal"
|
||||
libdirs { "vendor/mpg123/lib/Win32" }
|
||||
libdirs { "vendor/libsndfile/lib/Win32" }
|
||||
libdirs { "vendor/openal-soft/libs/Win32" }
|
||||
|
||||
filter "platforms:win-amd64*oal"
|
||||
libdirs { "vendor/mpg123/lib/Win64" }
|
||||
libdirs { "vendor/libsndfile/lib/Win64" }
|
||||
libdirs { "vendor/openal-soft/libs/Win64" }
|
||||
|
||||
filter "platforms:linux*oal"
|
||||
links { "openal", "mpg123", "sndfile", "pthread" }
|
||||
|
||||
filter "platforms:bsd*oal"
|
||||
links { "openal", "mpg123", "sndfile", "pthread" }
|
||||
|
||||
filter "platforms:macosx*oal"
|
||||
links { "openal", "mpg123", "sndfile", "pthread" }
|
||||
|
||||
filter "platforms:macosx-arm64-*oal"
|
||||
includedirs { "/opt/homebrew/opt/openal-soft/include" }
|
||||
libdirs { "/opt/homebrew/opt/openal-soft/lib" }
|
||||
|
||||
filter "platforms:macosx-amd64-*oal"
|
||||
includedirs { "/usr/local/opt/openal-soft/include" }
|
||||
libdirs { "/usr/local/opt/openal-soft/lib" }
|
||||
|
||||
if _OPTIONS["with-opus"] then
|
||||
filter {}
|
||||
links { "libogg" }
|
||||
links { "opus" }
|
||||
links { "opusfile" }
|
||||
end
|
||||
|
||||
filter "platforms:*RW34*"
|
||||
includedirs { "sdk/rwsdk/include/d3d8" }
|
||||
libdirs { "sdk/rwsdk/lib/d3d8/release" }
|
||||
links { "rwcore", "rpworld", "rpmatfx", "rpskin", "rphanim", "rtbmp", "rtquat", "rtanim", "rtcharse", "rpanisot" }
|
||||
defines { "RWLIBS" }
|
||||
linkoptions "/SECTION:_rwcseg,ER!W /MERGE:_rwcseg=.text"
|
||||
|
||||
filter "platforms:*librw*"
|
||||
defines { "LIBRW" }
|
||||
files { addSrcFiles("src/fakerw") }
|
||||
includedirs { "src/fakerw" }
|
||||
includedirs { Librw }
|
||||
if(_OPTIONS["with-librw"]) then
|
||||
libdirs { "vendor/librw/lib/%{cfg.platform}/%{cfg.buildcfg}" }
|
||||
end
|
||||
links { "rw" }
|
||||
|
||||
filter "platforms:*d3d9*"
|
||||
defines { "USE_D3D9" }
|
||||
links { "d3d9" }
|
||||
|
||||
filter "platforms:*x86*d3d*"
|
||||
includedirs { "sdk/dx8sdk/include" }
|
||||
libdirs { "sdk/dx8sdk/lib" }
|
||||
|
||||
filter "platforms:win-x86*gl3_glfw*"
|
||||
libdirs { path.join(_OPTIONS["glfwdir32"], "lib-" .. string.gsub(_ACTION or '', "vs", "vc")) }
|
||||
links { "opengl32", "glfw3" }
|
||||
|
||||
filter "platforms:win-amd64*gl3_glfw*"
|
||||
libdirs { path.join(_OPTIONS["glfwdir64"], "lib-" .. string.gsub(_ACTION or '', "vs", "vc")) }
|
||||
links { "opengl32", "glfw3" }
|
||||
|
||||
filter "platforms:linux*gl3_glfw*"
|
||||
links { "GL", "glfw" }
|
||||
|
||||
filter "platforms:bsd*gl3_glfw*"
|
||||
links { "GL", "glfw", "sysinfo" }
|
||||
includedirs { "/usr/local/include" }
|
||||
libdirs { "/usr/local/lib" }
|
||||
|
||||
filter "platforms:macosx-arm64-*gl3_glfw*"
|
||||
links { "glfw" }
|
||||
linkoptions { "-framework OpenGL" }
|
||||
includedirs { "/opt/local/include" }
|
||||
includedirs {"/opt/homebrew/include" }
|
||||
libdirs { "/opt/local/lib" }
|
||||
libdirs { "/opt/homebrew/lib" }
|
||||
|
||||
filter "platforms:macosx-amd64-*gl3_glfw*"
|
||||
links { "glfw" }
|
||||
linkoptions { "-framework OpenGL" }
|
||||
includedirs { "/opt/local/include" }
|
||||
includedirs {"/usr/local/include" }
|
||||
libdirs { "/opt/local/lib" }
|
||||
libdirs { "/usr/local/lib" }
|
||||
|
||||
20
printHash.sh
20
printHash.sh
@@ -1,12 +1,14 @@
|
||||
#!/usr/bin/env bash
|
||||
#!/usr/bin/env sh
|
||||
if [ -z "${1}" ]
|
||||
then
|
||||
printf "%s\n" "Input the path to the file for writing the commit hash to."
|
||||
else
|
||||
printf "%s" "#define GIT_SHA1 \"" > $1
|
||||
|
||||
> $1
|
||||
if (command -v "git" >/dev/null) then
|
||||
git rev-parse --short HEAD | tr -d '\n' >> $1
|
||||
fi
|
||||
|
||||
echo -n "#define GIT_SHA1 \"" > $1
|
||||
|
||||
if (command -v "git" >/dev/null) then
|
||||
git rev-parse --short HEAD | tr -d '\n' >> $1
|
||||
printf "%s\n" "\"" >> $1
|
||||
printf "%s\n" "const char* g_GIT_SHA1 = GIT_SHA1;" >> $1
|
||||
fi
|
||||
|
||||
echo "\"" >> $1
|
||||
echo "const char* g_GIT_SHA1 = GIT_SHA1;" >> $1
|
||||
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 57 KiB |
BIN
res/images/logo_256.jpg
Normal file
BIN
res/images/logo_256.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 30 KiB |
@@ -50,12 +50,17 @@ if(LIBRW_PLATFORM_D3D9)
|
||||
endif()
|
||||
|
||||
target_compile_definitions(${EXECUTABLE} PRIVATE CMAKE_BUILD)
|
||||
target_compile_definitions(${EXECUTABLE} PRIVATE USE_OUR_VERSIONING)
|
||||
|
||||
if(${PROJECT}_AUDIO STREQUAL "OAL")
|
||||
find_package(OpenAL REQUIRED)
|
||||
target_include_directories(${EXECUTABLE} PRIVATE ${OPENAL_INCLUDE_DIR})
|
||||
target_link_libraries(${EXECUTABLE} PRIVATE ${OPENAL_LIBRARY})
|
||||
target_compile_definitions(${EXECUTABLE} PRIVATE ${OPENAL_DEFINITIONS})
|
||||
if(TARGET OpenAL::OpenAL)
|
||||
target_link_libraries(${EXECUTABLE} PRIVATE OpenAL::OpenAL)
|
||||
else()
|
||||
target_include_directories(${EXECUTABLE} PRIVATE ${OPENAL_INCLUDE_DIR})
|
||||
target_link_libraries(${EXECUTABLE} PRIVATE ${OPENAL_LIBRARY})
|
||||
target_compile_definitions(${EXECUTABLE} PRIVATE ${OPENAL_DEFINITIONS})
|
||||
endif()
|
||||
target_compile_definitions(${EXECUTABLE} PRIVATE AUDIO_OAL)
|
||||
elseif(${PROJECT}_AUDIO STREQUAL "MSS")
|
||||
find_package(MilesSDK REQUIRED)
|
||||
@@ -107,6 +112,8 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang
|
||||
if (NOT LIBRW_PLATFORM_PS2)
|
||||
target_compile_options(${EXECUTABLE}
|
||||
PRIVATE
|
||||
-fpermissive # for CVECTORHACK
|
||||
-Wno-address-of-temporary # for CVECTORHACK
|
||||
-Wextra
|
||||
-Wdouble-promotion
|
||||
-Wpedantic
|
||||
@@ -119,13 +126,35 @@ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||
)
|
||||
endif()
|
||||
|
||||
if(NINTENDO_SWITCH)
|
||||
set(${PROJECT}_C_CXX_EXTENSIONS ON)
|
||||
else()
|
||||
set(${PROJECT}_C_CXX_EXTENSIONS OFF)
|
||||
endif()
|
||||
|
||||
if(LIBRW_PLATFORM_GL3 AND LIBRW_GL3_GFXLIB STREQUAL "GLFW")
|
||||
include(CheckSymbolExists)
|
||||
|
||||
set(CMAKE_REQUIRED_LIBRARIES glfw)
|
||||
set(CMAKE_REQUIRED_DEFINITIONS -DGLFW_EXPOSE_NATIVE_X11)
|
||||
check_symbol_exists(glfwGetX11Display "GLFW/glfw3.h;GLFW/glfw3native.h" GLFW_HAS_X11)
|
||||
unset(CMAKE_REQUIRED_DEFINITIONS)
|
||||
unset(CMAKE_REQUIRED_LIBRARIES)
|
||||
|
||||
if (GLFW_HAS_X11)
|
||||
find_package(X11 REQUIRED)
|
||||
target_link_libraries(${EXECUTABLE} PRIVATE X11::X11)
|
||||
target_compile_definitions(${EXECUTABLE} PRIVATE GET_KEYBOARD_INPUT_FROM_X11)
|
||||
endif (GLFW_HAS_X11)
|
||||
endif()
|
||||
|
||||
set_target_properties(${EXECUTABLE}
|
||||
PROPERTIES
|
||||
C_STANDARD 11
|
||||
C_EXTENSIONS OFF
|
||||
C_EXTENSIONS ${${PROJECT}_C_CXX_EXTENSIONS}
|
||||
C_STANDARD_REQUIRED ON
|
||||
CXX_STANDARD 11
|
||||
CXX_EXTENSIONS OFF
|
||||
CXX_EXTENSIONS ${${PROJECT}_C_CXX_EXTENSIONS}
|
||||
CXX_STANDARD_REQUIRED ON
|
||||
)
|
||||
|
||||
@@ -139,3 +168,5 @@ if(${PROJECT}_INSTALL)
|
||||
install(FILES $<TARGET_PDB_FILE:${EXECUTABLE}> DESTINATION "." OPTIONAL)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
reVC_platform_target(${EXECUTABLE} INSTALL)
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "RpAnimBlend.h"
|
||||
#include "AnimBlendAssociation.h"
|
||||
#include "AnimBlendAssocGroup.h"
|
||||
#include "KeyGen.h"
|
||||
|
||||
CAnimBlendAssocGroup::CAnimBlendAssocGroup(void)
|
||||
{
|
||||
@@ -111,27 +112,34 @@ strcmpIgnoringDigits(const char *s1, const char *s2)
|
||||
}
|
||||
}
|
||||
|
||||
extern const char* csPlayerNames[];
|
||||
extern const char* playerNames[];
|
||||
|
||||
CBaseModelInfo*
|
||||
GetModelFromName(const char *name)
|
||||
{
|
||||
int i;
|
||||
CBaseModelInfo *mi;
|
||||
char playername[32];
|
||||
|
||||
if(strncasecmp(name, "CSplay", 6) == 0 &&
|
||||
strncasecmp(CModelInfo::GetModelInfo(MI_PLAYER)->GetModelName(), "ig", 2) == 0){
|
||||
strcpy(playername, CModelInfo::GetModelInfo(MI_PLAYER)->GetModelName());
|
||||
playername[0] = 'C';
|
||||
playername[1] = 'S';
|
||||
name = playername;
|
||||
CBaseModelInfo* mi;
|
||||
if (CKeyGen::GetUppercaseKey(name) == CKeyGen::GetUppercaseKey("cstoni_a")) {
|
||||
i = 0;
|
||||
while (csPlayerNames[i][0] != '\0') {
|
||||
if (CModelInfo::GetModelInfo(0)->GetNameHashKey() == CKeyGen::GetUppercaseKey(playerNames[i])) {
|
||||
name = csPlayerNames[i];
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
for(i = 0; i < MODELINFOSIZE; i++){
|
||||
uint32 hashKey = CKeyGen::GetUppercaseKey(name);
|
||||
for (i = 0; i < CModelInfo::GetNumModelInfos(); i++) {
|
||||
mi = CModelInfo::GetModelInfo(i);
|
||||
if(mi && mi->GetRwObject() && RwObjectGetType(mi->GetRwObject()) == rpCLUMP &&
|
||||
strcmpIgnoringDigits(mi->GetModelName(), name))
|
||||
if (mi && mi->GetRwObject()
|
||||
&& RwObjectGetType(mi->GetRwObject()) == rpCLUMP &&
|
||||
hashKey == mi->GetNameHashKey())
|
||||
return mi;
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
@@ -185,3 +193,45 @@ CAnimBlendAssocGroup::CreateAssociations(const char *blockName, RpClump *clump,
|
||||
}
|
||||
numAssociations = numAssocs;
|
||||
}
|
||||
|
||||
void
|
||||
CAnimBlendAssocGroup::CreateAssociations(const char *blockName, const char *animNames, const char *objectNames, int numChars)
|
||||
{
|
||||
if (!objectNames) {
|
||||
CreateAssociations(blockName);
|
||||
return;
|
||||
}
|
||||
|
||||
if (assocList)
|
||||
DestroyAssociations();
|
||||
|
||||
animBlock = CAnimManager::GetAnimationBlock(blockName);
|
||||
assocList = new CAnimBlendAssociation[animBlock->numAnims];
|
||||
|
||||
numAssociations = 0;
|
||||
if (animBlock->numAnims > 0)
|
||||
{
|
||||
int i, j;
|
||||
for (i = 0; i < animBlock->numAnims; i++) {
|
||||
int animId = -1;
|
||||
for (j = 0; j != animBlock->numAnims; j++)
|
||||
if (strcmp(CAnimManager::GetAnimation(i + animBlock->firstIndex)->name, animNames + numChars * j) == 0)
|
||||
animId = j;
|
||||
|
||||
if (animId != -1) {
|
||||
CBaseModelInfo* minfo = GetModelFromName(objectNames + numChars * animId);
|
||||
if (minfo)
|
||||
{
|
||||
RpClump* clump = (RpClump*)minfo->CreateInstance();
|
||||
RpAnimBlendClumpInit(clump);
|
||||
assocList[numAssociations].Init(clump, CAnimManager::GetAnimation(i + animBlock->firstIndex));
|
||||
if (IsClumpSkinned(clump))
|
||||
RpClumpForAllAtomics(clump, AtomicRemoveAnimFromSkinCB, nil);
|
||||
RpClumpDestroy(clump);
|
||||
assocList[numAssociations].animId = i + numAssociations;
|
||||
assocList[numAssociations++].groupId = groupId;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,4 +21,5 @@ public:
|
||||
CAnimBlendAssociation *CopyAnimation(const char *name);
|
||||
void CreateAssociations(const char *name);
|
||||
void CreateAssociations(const char *blockName, RpClump *clump, const char **animNames, int numAssocs);
|
||||
void CreateAssociations(const char *blockName, const char *animNames, const char *objectNames, int numChars);
|
||||
};
|
||||
|
||||
@@ -230,3 +230,9 @@ CAnimBlendAssociation::UpdateBlend(float timeDelta)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
CAnimBlendAssociation::Remove()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
@@ -81,6 +81,7 @@ public:
|
||||
void UpdateTimeStep(float timeDelta, float relSpeed);
|
||||
bool UpdateTime(float timeDelta, float relSpeed);
|
||||
bool UpdateBlend(float timeDelta);
|
||||
void Remove();
|
||||
|
||||
void SetRun(void) { flags |= ASSOC_RUNNING; }
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -29,6 +29,7 @@ enum AssocGroupId
|
||||
ASSOCGRP_SNIPER,
|
||||
ASSOCGRP_THROW,
|
||||
ASSOCGRP_FLAMETHROWER,
|
||||
ASSOCGRP_ROCKETLAUNCHER,
|
||||
ASSOCGRP_MEDIC,
|
||||
ASSOCGRP_SUNBATHE,
|
||||
ASSOCGRP_PLAYER_IDLE,
|
||||
@@ -40,6 +41,7 @@ enum AssocGroupId
|
||||
ASSOCGRP_PLAYER1ARMED,
|
||||
ASSOCGRP_PLAYER2ARMED,
|
||||
ASSOCGRP_PLAYERBBBAT,
|
||||
ASSOCGRP_AICHAINSAW,
|
||||
ASSOCGRP_PLAYERCHAINSAW,
|
||||
ASSOCGRP_SHUFFLE,
|
||||
ASSOCGRP_OLD,
|
||||
@@ -64,11 +66,33 @@ enum AssocGroupId
|
||||
ASSOCGRP_ROCKETBACK,
|
||||
ASSOCGRP_ROCKETLEFT,
|
||||
ASSOCGRP_ROCKETRIGHT,
|
||||
ASSOCGRP_CHAINSAWBACK,
|
||||
ASSOCGRP_CHAINSAWLEFT,
|
||||
ASSOCGRP_CHAINSAWRIGHT,
|
||||
#endif
|
||||
|
||||
ASSOCGRP_MPNOTE,
|
||||
ASSOCGRP_CSMISC,
|
||||
ASSOCGRP_DONH2,
|
||||
ASSOCGRP_DONH3,
|
||||
ASSOCGRP_JDT2,
|
||||
ASSOCGRP_JDT4,
|
||||
ASSOCGRP_JDT5,
|
||||
ASSOCGRP_JDT6,
|
||||
ASSOCGRP_MAR1,
|
||||
ASSOCGRP_MAR2,
|
||||
ASSOCGRP_MAR3,
|
||||
ASSOCGRP_SAL1,
|
||||
ASSOCGRP_SAL2,
|
||||
ASSOCGRP_SAL3,
|
||||
ASSOCGRP_SAL4,
|
||||
ASSOCGRP_SAL6,
|
||||
ASSOCGRP_SAL7,
|
||||
ASSOCGRP_VIC2,
|
||||
ASSOCGRP_VIC3,
|
||||
ASSOCGRP_VIC4,
|
||||
ASSOCGRP_VIC6,
|
||||
ASSOCGRP_TOURIST,
|
||||
ASSOCGRP_MAC2,
|
||||
ASSOCGRP_VIC7,
|
||||
|
||||
NUM_ANIM_ASSOC_GROUPS
|
||||
};
|
||||
|
||||
|
||||
@@ -40,42 +40,25 @@ enum AnimationId
|
||||
ANIM_STD_HIT_BACK,
|
||||
ANIM_STD_HIT_RIGHT,
|
||||
ANIM_STD_HIT_FLOOR,
|
||||
|
||||
/* names made up */
|
||||
ANIM_STD_HIT_BODYBLOW,
|
||||
ANIM_STD_HIT_CHEST,
|
||||
ANIM_STD_HIT_HEAD,
|
||||
ANIM_STD_HIT_WALK,
|
||||
/**/
|
||||
|
||||
ANIM_STD_HIT_WALL,
|
||||
ANIM_STD_HIT_FLOOR_FRONT,
|
||||
ANIM_STD_HIT_BEHIND,
|
||||
ANIM_STD_FIGHT_IDLE,
|
||||
ANIM_STD_FIGHT_2IDLE,
|
||||
ANIM_STD_FIGHT_SHUFFLE_F,
|
||||
|
||||
/* names made up */
|
||||
ANIM_STD_FIGHT_BODYBLOW,
|
||||
ANIM_STD_FIGHT_HEAD,
|
||||
ANIM_STD_FIGHT_KICK,
|
||||
ANIM_STD_FIGHT_KNEE,
|
||||
ANIM_STD_FIGHT_LHOOK,
|
||||
ANIM_STD_FIGHT_PUNCH,
|
||||
ANIM_STD_FIGHT_ROUNDHOUSE,
|
||||
ANIM_STD_FIGHT_LONGKICK,
|
||||
/**/
|
||||
|
||||
ANIM_STD_PARTIAL_PUNCH,
|
||||
|
||||
/* names made up */
|
||||
ANIM_STD_FIGHT_JAB,
|
||||
ANIM_STD_FIGHT_ELBOW_L,
|
||||
ANIM_STD_FIGHT_ELBOW_R,
|
||||
ANIM_STD_FIGHT_BKICK_L,
|
||||
ANIM_STD_FIGHT_BKICK_R,
|
||||
/**/
|
||||
|
||||
ANIM_FIGHT_ATTACK_A1,
|
||||
ANIM_FIGHT_ATTACK_A2,
|
||||
ANIM_FIGHT_ATTACK_A3,
|
||||
ANIM_FIGHT_ATTACK_B1,
|
||||
ANIM_FIGHT_ATTACK_B2,
|
||||
ANIM_FIGHT_ATTACK_B3,
|
||||
ANIM_FIGHT_HIT_A1,
|
||||
ANIM_FIGHT_HIT_A2,
|
||||
ANIM_FIGHT_HIT_A3,
|
||||
ANIM_FIGHT_HIT_B1,
|
||||
ANIM_FIGHT_HIT_B2,
|
||||
ANIM_FIGHT_HIT_B3,
|
||||
ANIM_STD_DETONATE,
|
||||
ANIM_STD_PUNCH,
|
||||
ANIM_STD_PARTIALPUNCH,
|
||||
@@ -174,6 +157,7 @@ enum AnimationId
|
||||
|
||||
ANIM_STD_EVADE_STEP,
|
||||
ANIM_STD_EVADE_DIVE,
|
||||
ANIM_STD_COMMANDO_ROLL,
|
||||
ANIM_STD_XPRESS_SCRATCH,
|
||||
ANIM_STD_ROADCROSS,
|
||||
ANIM_STD_TURN180,
|
||||
@@ -284,4 +268,65 @@ enum AnimationId
|
||||
ANIM_STRIP_E,
|
||||
ANIM_STRIP_F,
|
||||
ANIM_STRIP_G,
|
||||
|
||||
|
||||
ANIM_MULTIPLAYER_CUTSCENE_MPNOTE,
|
||||
ANIM_MULTIPLAYER_CUTSCENE_MPNOTE_LOOP,
|
||||
|
||||
ANIM_CS_MISC_IDLE_LOOK,
|
||||
ANIM_CS_MISC_IDLE_NO,
|
||||
ANIM_CS_MISC_IDLE_YES,
|
||||
ANIM_CS_MISC_IDLE_CHAT2,
|
||||
ANIM_CS_MISC_IDLE_COUGH,
|
||||
ANIM_CS_MISC_IDLE_GIGGLE_FEMALE,
|
||||
ANIM_CS_MISC_IDLE_TOUGH_CHAT,
|
||||
ANIM_CS_MISC_IDLE_CELL_TALK,
|
||||
|
||||
ANIM_DONH2_CAMERA,
|
||||
ANIM_DONH3_HAPPY,
|
||||
|
||||
ANIM_JDT2_ANXIOUS_TALK,
|
||||
ANIM_JDT2_SHRUG,
|
||||
ANIM_JDT4_DILDO_TALK,
|
||||
ANIM_JDT5_CALM_DOWN,
|
||||
ANIM_JDT5_POINT,
|
||||
ANIM_JDT6_PICKUP,
|
||||
ANIM_JDT6_KNOCK,
|
||||
|
||||
ANIM_MAR1_SKIRT,
|
||||
ANIM_MAR2_CELL_ANSWER,
|
||||
ANIM_MAR2_CELL_END,
|
||||
ANIM_MAR2_CELL_TALK,
|
||||
ANIM_MAR2_FOOT_TAP,
|
||||
ANIM_MAR3_HOOCHY,
|
||||
ANIM_MAR3_NOTE_IDLE,
|
||||
ANIM_MAR3_NOTE_PICKUP,
|
||||
|
||||
ANIM_SAL1_BIREFCASE_DOWN,
|
||||
ANIM_SAL2_IDLE_SEATED,
|
||||
ANIM_SAL2_SEAT_TO_STAND,
|
||||
ANIM_SAL3_SEATED_TALK,
|
||||
ANIM_SAL3_SEATED_IDLE,
|
||||
ANIM_SAL3_SIT_DOWN,
|
||||
ANIM_SAL4_DUST_DOWN,
|
||||
ANIM_SAL4_GIRL_RUN,
|
||||
ANIM_SAL6_ANGRY_SEATED,
|
||||
ANIM_SAL6_IDLE_SEATED,
|
||||
ANIM_SAL7_LOOKOUT,
|
||||
|
||||
ANIM_VIC2_POINT_ANGRY,
|
||||
ANIM_VIC3_WAFT,
|
||||
ANIM_VIC3_PICKUP_ROLL,
|
||||
ANIM_VIC4_CARRY_BOX,
|
||||
ANIM_VIC4_CELL_LOOK,
|
||||
ANIM_VIC4_CRATE_IDLE,
|
||||
ANIM_VIC6_CELL_ANGRY,
|
||||
|
||||
ANIM_TOURIST3,
|
||||
ANIM_TOURIST2,
|
||||
ANIM_TOURIST1,
|
||||
|
||||
ANIM_MAC2_PLEAD,
|
||||
|
||||
ANIM_VIC7_PROD_WITH_FOOT
|
||||
};
|
||||
@@ -22,154 +22,54 @@
|
||||
#include "ColStore.h"
|
||||
#include "Radar.h"
|
||||
#include "Pools.h"
|
||||
#include "crossplatform.h"
|
||||
|
||||
const struct {
|
||||
const char *szTrackName;
|
||||
int iTrackId;
|
||||
} musicNameIdAssoc[] = {
|
||||
{ "ASS_1", STREAMED_SOUND_CUTSCENE_ASS_1 },
|
||||
{ "ASS_2", STREAMED_SOUND_CUTSCENE_ASS_2 },
|
||||
{ "BANK_1", STREAMED_SOUND_CUTSCENE_BANK_1 },
|
||||
{ "BANK_2A", STREAMED_SOUND_CUTSCENE_BANK_2A },
|
||||
{ "BANK_2B", STREAMED_SOUND_CUTSCENE_BANK_2B },
|
||||
{ "BANK_3A", STREAMED_SOUND_CUTSCENE_BANK_3A },
|
||||
{ "BANK_3B", STREAMED_SOUND_CUTSCENE_BANK_3B },
|
||||
{ "BANK_4", STREAMED_SOUND_CUTSCENE_BANK_4 },
|
||||
{ "BIKE_1", STREAMED_SOUND_CUTSCENE_BIKE_1 },
|
||||
{ "BIKE_2", STREAMED_SOUND_CUTSCENE_BIKE_2 },
|
||||
{ "BIKE_3", STREAMED_SOUND_CUTSCENE_BIKE_3 },
|
||||
{ "BUD_1", STREAMED_SOUND_CUTSCENE_BUD_1 },
|
||||
{ "BUD_2", STREAMED_SOUND_CUTSCENE_BUD_2 },
|
||||
{ "BUD_3", STREAMED_SOUND_CUTSCENE_BUD_3 },
|
||||
{ "CAP_1", STREAMED_SOUND_CUTSCENE_CAP_1 },
|
||||
{ "CAR_1", STREAMED_SOUND_CUTSCENE_CAR_1 },
|
||||
{ "CNT_1A", STREAMED_SOUND_CUTSCENE_CNT_1A },
|
||||
{ "CNT_1B", STREAMED_SOUND_CUTSCENE_CNT_1B },
|
||||
{ "CNT_2", STREAMED_SOUND_CUTSCENE_CNT_2 },
|
||||
{ "COK_1", STREAMED_SOUND_CUTSCENE_COK_1 },
|
||||
{ "COK_2A", STREAMED_SOUND_CUTSCENE_COK_2A },
|
||||
{ "COK_2B", STREAMED_SOUND_CUTSCENE_COK_2B },
|
||||
{ "COK_3", STREAMED_SOUND_CUTSCENE_COK_3 },
|
||||
{ "COK_4A", STREAMED_SOUND_CUTSCENE_COK_4A },
|
||||
{ "COK_4A2", STREAMED_SOUND_CUTSCENE_COK_4A2 },
|
||||
{ "COK_4B", STREAMED_SOUND_CUTSCENE_COK_4B },
|
||||
{ "COL_1", STREAMED_SOUND_CUTSCENE_COL_1 },
|
||||
{ "COL_2", STREAMED_SOUND_CUTSCENE_COL_2 },
|
||||
{ "COL_3A", STREAMED_SOUND_CUTSCENE_COL_3A },
|
||||
{ "COL_4A", STREAMED_SOUND_CUTSCENE_COL_4A },
|
||||
{ "COL_5A", STREAMED_SOUND_CUTSCENE_COL_5A },
|
||||
{ "COL_5B", STREAMED_SOUND_CUTSCENE_COL_5B },
|
||||
{ "CUB_1", STREAMED_SOUND_CUTSCENE_CUB_1 },
|
||||
{ "CUB_2", STREAMED_SOUND_CUTSCENE_CUB_2 },
|
||||
{ "CUB_3", STREAMED_SOUND_CUTSCENE_CUB_3 },
|
||||
{ "CUB_4", STREAMED_SOUND_CUTSCENE_CUB_4 },
|
||||
{ "DRUG_1", STREAMED_SOUND_CUTSCENE_DRUG_1 },
|
||||
{ "FIN", STREAMED_SOUND_CUTSCENE_FIN },
|
||||
{ "FIN_2", STREAMED_SOUND_CUTSCENE_FIN2 },
|
||||
{ "FINALE", STREAMED_SOUND_CUTSCENE_FINALE },
|
||||
{ "HAT_1", STREAMED_SOUND_CUTSCENE_HAT_1 },
|
||||
{ "HAT_2", STREAMED_SOUND_CUTSCENE_HAT_2 },
|
||||
{ "HAT_3", STREAMED_SOUND_CUTSCENE_HAT_3 },
|
||||
{ "ICE_1", STREAMED_SOUND_CUTSCENE_ICE_1 },
|
||||
{ "INT_A", STREAMED_SOUND_CUTSCENE_INT_A },
|
||||
{ "INT_B", STREAMED_SOUND_CUTSCENE_INT_B },
|
||||
{ "INT_D", STREAMED_SOUND_CUTSCENE_INT_D },
|
||||
{ "INT_M", STREAMED_SOUND_CUTSCENE_INT_M },
|
||||
{ "LAW_1A", STREAMED_SOUND_CUTSCENE_LAW_1A },
|
||||
{ "LAW_1B", STREAMED_SOUND_CUTSCENE_LAW_1B },
|
||||
{ "LAW_2A", STREAMED_SOUND_CUTSCENE_LAW_2A },
|
||||
{ "LAW_2B", STREAMED_SOUND_CUTSCENE_LAW_2B },
|
||||
{ "LAW_2C", STREAMED_SOUND_CUTSCENE_LAW_2C },
|
||||
{ "LAW_3", STREAMED_SOUND_CUTSCENE_LAW_3 },
|
||||
{ "LAW_4", STREAMED_SOUND_CUTSCENE_LAW_4 },
|
||||
{ "PHIL_1", STREAMED_SOUND_CUTSCENE_PHIL_1 },
|
||||
{ "PHIL_2", STREAMED_SOUND_CUTSCENE_PHIL_2 },
|
||||
{ "PORN_1", STREAMED_SOUND_CUTSCENE_PORN_1 },
|
||||
{ "PORN_2", STREAMED_SOUND_CUTSCENE_PORN_2 },
|
||||
{ "PORN_3", STREAMED_SOUND_CUTSCENE_PORN_3 },
|
||||
{ "PORN_4", STREAMED_SOUND_CUTSCENE_PORN_4 },
|
||||
{ "RESC_1A", STREAMED_SOUND_CUTSCENE_RESC_1A },
|
||||
{ "ROK_1", STREAMED_SOUND_CUTSCENE_ROK_1 },
|
||||
{ "ROK_2", STREAMED_SOUND_CUTSCENE_ROK_2 },
|
||||
{ "ROK_3A", STREAMED_SOUND_CUTSCENE_ROK_3A },
|
||||
{ "STRIPA", STREAMED_SOUND_CUTSCENE_STRIPA },
|
||||
{ "TAX_1", STREAMED_SOUND_CUTSCENE_TAX_1 },
|
||||
{ "TEX_1", STREAMED_SOUND_CUTSCENE_TEX_1 },
|
||||
{ "TEX_2", STREAMED_SOUND_CUTSCENE_TEX_2 },
|
||||
{ "TEX_3", STREAMED_SOUND_CUTSCENE_TEX_3 },
|
||||
{ "GSPOT", STREAMED_SOUND_CUTSCENE_GLIGHT },
|
||||
{ "FIST", STREAMED_SOUND_CUTSCENE_FIST },
|
||||
{ "EL_PH1", STREAMED_SOUND_CUTSCENE_ELBURRO1_PH1 },
|
||||
{ "EL_PH2", STREAMED_SOUND_CUTSCENE_ELBURRO2_PH2 },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
static bool bModelsRemovedForCutscene;
|
||||
static int32 NumberOfSavedWeapons;
|
||||
static eWeaponType SavedWeaponIDs[TOTAL_WEAPON_SLOTS];
|
||||
static int32 SavedWeaponAmmo[TOTAL_WEAPON_SLOTS];
|
||||
|
||||
int
|
||||
FindCutsceneAudioTrackId(const char *szCutsceneName)
|
||||
{
|
||||
for (int i = 0; musicNameIdAssoc[i].szTrackName; i++) {
|
||||
if (!CGeneral::faststricmp(musicNameIdAssoc[i].szTrackName, szCutsceneName))
|
||||
return musicNameIdAssoc[i].iTrackId;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool CCutsceneMgr::ms_running;
|
||||
bool CCutsceneMgr::ms_cutsceneProcessing;
|
||||
char CCutsceneMgr::ms_cAppendAnimName[NUMCUTSCENEOBJECTS][NAMELENGTH];
|
||||
char CCutsceneMgr::ms_cAppendObjectName[NUMCUTSCENEOBJECTS][NAMELENGTH];
|
||||
int CCutsceneMgr::ms_numAppendObjectNames;
|
||||
CDirectory *CCutsceneMgr::ms_pCutsceneDir;
|
||||
CCutsceneObject *CCutsceneMgr::ms_pCutsceneObjects[NUMCUTSCENEOBJECTS];
|
||||
int32 CCutsceneMgr::ms_numCutsceneObjs;
|
||||
bool CCutsceneMgr::ms_loaded;
|
||||
bool CCutsceneMgr::ms_animLoaded;
|
||||
bool CCutsceneMgr::ms_useLodMultiplier;
|
||||
char CCutsceneMgr::ms_cutsceneName[CUTSCENENAMESIZE];
|
||||
CAnimBlendAssocGroup CCutsceneMgr::ms_cutsceneAssociations;
|
||||
CVector CCutsceneMgr::ms_cutsceneOffset;
|
||||
float CCutsceneMgr::ms_cutsceneTimer;
|
||||
bool CCutsceneMgr::ms_hasFileInfo;
|
||||
bool CCutsceneMgr::ms_wasCutsceneSkipped;
|
||||
bool CCutsceneMgr::ms_useLodMultiplier;
|
||||
bool CCutsceneMgr::ms_cutsceneProcessing;
|
||||
bool CCutsceneMgr::ms_running;
|
||||
bool CCutsceneMgr::ms_animLoaded;
|
||||
uint32 CCutsceneMgr::ms_cutsceneLoadStatus;
|
||||
bool CCutsceneMgr::ms_useCutsceneShadows = true;
|
||||
|
||||
bool bCamLoaded;
|
||||
bool bIsEverythingRemovedFromTheWorldForTheBiggestFuckoffCutsceneEver; // pls don't shrink the name :P
|
||||
int32 NumberOfSavedWeapons;
|
||||
eWeaponType SavedWeaponIDs[TOTAL_WEAPON_SLOTS];
|
||||
int32 SavedWeaponAmmo[TOTAL_WEAPON_SLOTS];
|
||||
char uncompressedAnims[8][32];
|
||||
uint32 numUncompressedAnims;
|
||||
|
||||
|
||||
RpAtomic *
|
||||
CalculateBoundingSphereRadiusCB(RpAtomic *atomic, void *data)
|
||||
{
|
||||
float radius = RpAtomicGetBoundingSphere(atomic)->radius;
|
||||
RwV3d center = RpAtomicGetBoundingSphere(atomic)->center;
|
||||
|
||||
for (RwFrame *frame = RpAtomicGetFrame(atomic); RwFrameGetParent(frame); frame = RwFrameGetParent(frame))
|
||||
RwV3dTransformPoints(¢er, ¢er, 1, RwFrameGetMatrix(frame));
|
||||
|
||||
float size = RwV3dLength(¢er) + radius;
|
||||
if (size > *(float *)data)
|
||||
*(float *)data = size;
|
||||
return atomic;
|
||||
}
|
||||
|
||||
void
|
||||
CCutsceneMgr::Initialise(void)
|
||||
CCutsceneMgr::Initialise(void *dir)
|
||||
{
|
||||
ms_numCutsceneObjs = 0;
|
||||
ms_loaded = false;
|
||||
ms_wasCutsceneSkipped = false;
|
||||
ms_cutsceneLoadStatus = CUTSCENE_NOT_LOADED;
|
||||
ms_running = false;
|
||||
ms_useLodMultiplier = false;
|
||||
ms_animLoaded = false;
|
||||
ms_cutsceneProcessing = false;
|
||||
ms_useLodMultiplier = false;
|
||||
ms_wasCutsceneSkipped = false;
|
||||
ms_hasFileInfo = false;
|
||||
//ms_numCutsceneObjs = 0;
|
||||
//ms_loaded = false;
|
||||
if (gMakeResources) {
|
||||
ms_pCutsceneDir = new CDirectory(CUTSCENEDIRSIZE);
|
||||
ms_pCutsceneDir->ReadDirFile("ANIM\\CUTS.DIR");
|
||||
}
|
||||
else
|
||||
ms_pCutsceneDir = (CDirectory*)dir;
|
||||
|
||||
ms_pCutsceneDir = new CDirectory(CUTSCENEDIRSIZE);
|
||||
ms_pCutsceneDir->ReadDirFile("ANIM\\CUTS.DIR");
|
||||
//numUncompressedAnims = 0;
|
||||
//uncompressedAnims[0][0] = '\0';
|
||||
}
|
||||
|
||||
numUncompressedAnims = 0;
|
||||
uncompressedAnims[0][0] = '\0';
|
||||
void CCutsceneMgr::Write(base::cRelocatableChunkWriter& writer)
|
||||
{
|
||||
writer.AllocateRaw(ms_pCutsceneDir, sizeof(*ms_pCutsceneDir), 4, false, true);
|
||||
writer.AllocateRaw(ms_pCutsceneDir->entries, sizeof(CDirectory::DirectoryInfo) * ms_pCutsceneDir->numEntries, 4, false, true);
|
||||
writer.AddPatch(ms_pCutsceneDir);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -181,431 +81,25 @@ CCutsceneMgr::Shutdown(void)
|
||||
void
|
||||
CCutsceneMgr::LoadCutsceneData(const char *szCutsceneName)
|
||||
{
|
||||
int file;
|
||||
uint32 size;
|
||||
uint32 offset;
|
||||
CPlayerPed *pPlayerPed;
|
||||
|
||||
ms_cutsceneProcessing = true;
|
||||
ms_wasCutsceneSkipped = false;
|
||||
CTimer::Suspend();
|
||||
if (!bIsEverythingRemovedFromTheWorldForTheBiggestFuckoffCutsceneEver)
|
||||
CStreaming::RemoveCurrentZonesModels();
|
||||
|
||||
ms_pCutsceneDir->numEntries = 0;
|
||||
ms_pCutsceneDir->ReadDirFile("ANIM\\CUTS.DIR");
|
||||
|
||||
CStreaming::RemoveUnusedModelsInLoadedList();
|
||||
CGame::DrasticTidyUpMemory(true);
|
||||
|
||||
strcpy(ms_cutsceneName, szCutsceneName);
|
||||
|
||||
RwStream *stream;
|
||||
stream = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMREAD, "ANIM\\CUTS.IMG");
|
||||
assert(stream);
|
||||
|
||||
// Load animations
|
||||
sprintf(gString, "%s.IFP", szCutsceneName);
|
||||
if (ms_pCutsceneDir->FindItem(gString, offset, size)) {
|
||||
CStreaming::MakeSpaceFor(size << 11);
|
||||
CStreaming::ImGonnaUseStreamingMemory();
|
||||
RwStreamSkip(stream, offset << 11);
|
||||
CAnimManager::LoadAnimFile(stream, true, uncompressedAnims);
|
||||
ms_cutsceneAssociations.CreateAssociations(szCutsceneName);
|
||||
CStreaming::IHaveUsedStreamingMemory();
|
||||
ms_animLoaded = true;
|
||||
} else {
|
||||
ms_animLoaded = false;
|
||||
}
|
||||
RwStreamClose(stream, nil);
|
||||
|
||||
// Load camera data
|
||||
file = CFileMgr::OpenFile("ANIM\\CUTS.IMG", "rb");
|
||||
sprintf(gString, "%s.DAT", szCutsceneName);
|
||||
if (ms_pCutsceneDir->FindItem(gString, offset, size)) {
|
||||
CStreaming::ImGonnaUseStreamingMemory();
|
||||
CFileMgr::Seek(file, offset << 11, SEEK_SET);
|
||||
TheCamera.LoadPathSplines(file);
|
||||
CStreaming::IHaveUsedStreamingMemory();
|
||||
bCamLoaded = true;
|
||||
} else {
|
||||
bCamLoaded = false;
|
||||
}
|
||||
|
||||
CFileMgr::CloseFile(file);
|
||||
|
||||
if (CGeneral::faststricmp(ms_cutsceneName, "finale")) {
|
||||
DMAudio.ChangeMusicMode(MUSICMODE_CUTSCENE);
|
||||
int trackId = FindCutsceneAudioTrackId(szCutsceneName);
|
||||
if (trackId != -1) {
|
||||
printf("Start preload audio %s\n", szCutsceneName);
|
||||
DMAudio.PreloadCutSceneMusic(trackId);
|
||||
printf("End preload audio %s\n", szCutsceneName);
|
||||
}
|
||||
}
|
||||
|
||||
ms_cutsceneTimer = 0.0f;
|
||||
ms_loaded = true;
|
||||
ms_cutsceneOffset = CVector(0.0f, 0.0f, 0.0f);
|
||||
|
||||
pPlayerPed = FindPlayerPed();
|
||||
pPlayerPed->m_pWanted->ClearQdCrimes();
|
||||
pPlayerPed->bIsVisible = false;
|
||||
pPlayerPed->m_fCurrentStamina = pPlayerPed->m_fMaxStamina;
|
||||
CPad::GetPad(0)->SetDisablePlayerControls(PLAYERCONTROL_CUTSCENE);
|
||||
CWorld::Players[CWorld::PlayerInFocus].MakePlayerSafe(true);
|
||||
|
||||
CTimer::Resume();
|
||||
}
|
||||
|
||||
void
|
||||
CCutsceneMgr::FinishCutscene()
|
||||
{
|
||||
ms_wasCutsceneSkipped = true;
|
||||
if (bCamLoaded) {
|
||||
CCutsceneMgr::ms_cutsceneTimer = TheCamera.GetCutSceneFinishTime() * 0.001f;
|
||||
TheCamera.FinishCutscene();
|
||||
}
|
||||
|
||||
FindPlayerPed()->bIsVisible = true;
|
||||
CWorld::Players[CWorld::PlayerInFocus].MakePlayerSafe(false);
|
||||
}
|
||||
|
||||
void
|
||||
CCutsceneMgr::SetupCutsceneToStart(void)
|
||||
{
|
||||
if (bCamLoaded) {
|
||||
TheCamera.SetCamCutSceneOffSet(ms_cutsceneOffset);
|
||||
TheCamera.TakeControlWithSpline(JUMP_CUT);
|
||||
TheCamera.SetWideScreenOn();
|
||||
}
|
||||
|
||||
ms_cutsceneOffset.z++;
|
||||
|
||||
for (int i = ms_numCutsceneObjs - 1; i >= 0; i--) {
|
||||
assert(RwObjectGetType(ms_pCutsceneObjects[i]->m_rwObject) == rpCLUMP);
|
||||
if (CAnimBlendAssociation *pAnimBlendAssoc = RpAnimBlendClumpGetFirstAssociation((RpClump*)ms_pCutsceneObjects[i]->m_rwObject)) {
|
||||
assert(pAnimBlendAssoc->hierarchy->sequences[0].HasTranslation());
|
||||
if (ms_pCutsceneObjects[i]->m_pAttachTo != nil) {
|
||||
pAnimBlendAssoc->flags &= (~ASSOC_HAS_TRANSLATION);
|
||||
} else {
|
||||
if (pAnimBlendAssoc->hierarchy->IsCompressed()){
|
||||
KeyFrameTransCompressed *keyFrames = ((KeyFrameTransCompressed*)pAnimBlendAssoc->hierarchy->sequences[0].GetKeyFrameCompressed(0));
|
||||
CVector trans;
|
||||
keyFrames->GetTranslation(&trans);
|
||||
ms_pCutsceneObjects[i]->SetPosition(ms_cutsceneOffset + trans);
|
||||
}else{
|
||||
KeyFrameTrans *keyFrames = ((KeyFrameTrans*)pAnimBlendAssoc->hierarchy->sequences[0].GetKeyFrame(0));
|
||||
ms_pCutsceneObjects[i]->SetPosition(ms_cutsceneOffset + keyFrames->translation);
|
||||
}
|
||||
}
|
||||
pAnimBlendAssoc->SetRun();
|
||||
} else {
|
||||
ms_pCutsceneObjects[i]->SetPosition(ms_cutsceneOffset);
|
||||
}
|
||||
CWorld::Add(ms_pCutsceneObjects[i]);
|
||||
if (RwObjectGetType(ms_pCutsceneObjects[i]->m_rwObject) == rpCLUMP) {
|
||||
ms_pCutsceneObjects[i]->UpdateRpHAnim();
|
||||
}
|
||||
}
|
||||
|
||||
CTimer::Update();
|
||||
CTimer::Update();
|
||||
ms_running = true;
|
||||
ms_cutsceneTimer = 0.0f;
|
||||
}
|
||||
|
||||
void
|
||||
CCutsceneMgr::SetCutsceneAnim(const char *animName, CObject *pObject)
|
||||
{
|
||||
CAnimBlendAssociation *pNewAnim;
|
||||
CAnimBlendClumpData *pAnimBlendClumpData;
|
||||
|
||||
assert(RwObjectGetType(pObject->m_rwObject) == rpCLUMP);
|
||||
debug("Give cutscene anim %s\n", animName);
|
||||
RpAnimBlendClumpRemoveAllAssociations((RpClump*)pObject->m_rwObject);
|
||||
|
||||
pNewAnim = ms_cutsceneAssociations.GetAnimation(animName);
|
||||
if (!pNewAnim) {
|
||||
debug("\n\nHaven't I told you I can't find the fucking animation %s\n\n\n", animName);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pNewAnim->hierarchy->IsCompressed())
|
||||
pNewAnim->hierarchy->keepCompressed = true;
|
||||
|
||||
CStreaming::ImGonnaUseStreamingMemory();
|
||||
pNewAnim = ms_cutsceneAssociations.CopyAnimation(animName);
|
||||
CStreaming::IHaveUsedStreamingMemory();
|
||||
|
||||
pNewAnim->SetCurrentTime(0.0f);
|
||||
pNewAnim->flags |= ASSOC_HAS_TRANSLATION;
|
||||
pNewAnim->flags &= ~ASSOC_RUNNING;
|
||||
|
||||
pAnimBlendClumpData = *RPANIMBLENDCLUMPDATA(pObject->m_rwObject);
|
||||
pAnimBlendClumpData->link.Prepend(&pNewAnim->link);
|
||||
|
||||
if (pNewAnim->hierarchy->keepCompressed)
|
||||
pAnimBlendClumpData->frames->flag |= AnimBlendFrameData::COMPRESSED;
|
||||
}
|
||||
|
||||
void
|
||||
CCutsceneMgr::SetCutsceneAnimToLoop(const char* animName)
|
||||
{
|
||||
ms_cutsceneAssociations.GetAnimation(animName)->flags |= ASSOC_REPEAT;
|
||||
}
|
||||
|
||||
CCutsceneHead *
|
||||
CCutsceneMgr::AddCutsceneHead(CObject *pObject, int modelId)
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
void UpdateCutsceneObjectBoundingBox(RpClump* clump, int modelId)
|
||||
{
|
||||
if (modelId >= MI_CUTOBJ01 && modelId <= MI_CUTOBJ05) {
|
||||
CColModel* pColModel = &CTempColModels::ms_colModelCutObj[modelId - MI_CUTOBJ01];
|
||||
float radius = 0.0f;
|
||||
RpClumpForAllAtomics(clump, CalculateBoundingSphereRadiusCB, &radius);
|
||||
pColModel->boundingSphere.radius = radius;
|
||||
pColModel->boundingBox.min = CVector(-radius, -radius, -radius);
|
||||
pColModel->boundingBox.max = CVector(radius, radius, radius);
|
||||
}
|
||||
}
|
||||
|
||||
CCutsceneObject *
|
||||
CCutsceneMgr::CreateCutsceneObject(int modelId)
|
||||
{
|
||||
CBaseModelInfo *pModelInfo;
|
||||
CColModel *pColModel;
|
||||
CCutsceneObject *pCutsceneObject;
|
||||
|
||||
CStreaming::ImGonnaUseStreamingMemory();
|
||||
debug("Created cutscene object %s\n", CModelInfo::GetModelInfo(modelId)->GetModelName());
|
||||
if (modelId >= MI_CUTOBJ01 && modelId <= MI_CUTOBJ05) {
|
||||
pModelInfo = CModelInfo::GetModelInfo(modelId);
|
||||
pColModel = &CTempColModels::ms_colModelCutObj[modelId - MI_CUTOBJ01];
|
||||
pModelInfo->SetColModel(pColModel);
|
||||
UpdateCutsceneObjectBoundingBox((RpClump*)pModelInfo->GetRwObject(), modelId);
|
||||
} else if (modelId >= MI_SPECIAL01 && modelId <= MI_SPECIAL21) {
|
||||
pModelInfo = CModelInfo::GetModelInfo(modelId);
|
||||
if (pModelInfo->GetColModel() == &CTempColModels::ms_colModelPed1) {
|
||||
CColModel *colModel = new CColModel();
|
||||
colModel->boundingSphere.radius = 2.0f;
|
||||
colModel->boundingSphere.center = CVector(0.0f, 0.0f, 0.0f);
|
||||
pModelInfo->SetColModel(colModel, true);
|
||||
}
|
||||
pColModel = pModelInfo->GetColModel();
|
||||
float radius = 2.0f;
|
||||
pColModel->boundingSphere.radius = radius;
|
||||
pColModel->boundingBox.min = CVector(-radius, -radius, -radius);
|
||||
pColModel->boundingBox.max = CVector(radius, radius, radius);
|
||||
}
|
||||
|
||||
pCutsceneObject = new CCutsceneObject();
|
||||
pCutsceneObject->SetModelIndex(modelId);
|
||||
if (ms_useCutsceneShadows)
|
||||
pCutsceneObject->CreateShadow();
|
||||
ms_pCutsceneObjects[ms_numCutsceneObjs++] = pCutsceneObject;
|
||||
CStreaming::IHaveUsedStreamingMemory();
|
||||
return pCutsceneObject;
|
||||
LoadCutsceneData_overlay(szCutsceneName);
|
||||
}
|
||||
|
||||
void
|
||||
CCutsceneMgr::DeleteCutsceneData(void)
|
||||
{
|
||||
if (!ms_loaded) return;
|
||||
CTimer::Suspend();
|
||||
|
||||
ms_cutsceneProcessing = false;
|
||||
ms_useLodMultiplier = false;
|
||||
ms_useCutsceneShadows = true;
|
||||
|
||||
for (--ms_numCutsceneObjs; ms_numCutsceneObjs >= 0; ms_numCutsceneObjs--) {
|
||||
CWorld::Remove(ms_pCutsceneObjects[ms_numCutsceneObjs]);
|
||||
ms_pCutsceneObjects[ms_numCutsceneObjs]->DeleteRwObject();
|
||||
delete ms_pCutsceneObjects[ms_numCutsceneObjs];
|
||||
ms_pCutsceneObjects[ms_numCutsceneObjs] = nil;
|
||||
}
|
||||
ms_numCutsceneObjs = 0;
|
||||
|
||||
for (int i = MI_SPECIAL01; i < MI_SPECIAL21; i++) {
|
||||
CBaseModelInfo *minfo = CModelInfo::GetModelInfo(i);
|
||||
CColModel *colModel = minfo->GetColModel();
|
||||
if (colModel != &CTempColModels::ms_colModelPed1) {
|
||||
delete colModel;
|
||||
minfo->SetColModel(&CTempColModels::ms_colModelPed1);
|
||||
}
|
||||
}
|
||||
|
||||
if (ms_animLoaded)
|
||||
CAnimManager::RemoveLastAnimFile();
|
||||
|
||||
ms_animLoaded = false;
|
||||
numUncompressedAnims = 0;
|
||||
uncompressedAnims[0][0] = '\0';
|
||||
|
||||
if (bCamLoaded) {
|
||||
TheCamera.RestoreWithJumpCut();
|
||||
TheCamera.SetWideScreenOff();
|
||||
TheCamera.DeleteCutSceneCamDataMemory();
|
||||
}
|
||||
ms_running = false;
|
||||
ms_loaded = false;
|
||||
|
||||
FindPlayerPed()->bIsVisible = true;
|
||||
CPad::GetPad(0)->SetEnablePlayerControls(PLAYERCONTROL_CUTSCENE);
|
||||
CWorld::Players[CWorld::PlayerInFocus].MakePlayerSafe(false);
|
||||
|
||||
if (CGeneral::faststricmp(ms_cutsceneName, "finale")) {
|
||||
DMAudio.StopCutSceneMusic();
|
||||
DMAudio.ChangeMusicMode(MUSICMODE_GAME);
|
||||
}
|
||||
|
||||
CStreaming::ms_disableStreaming = false;
|
||||
CWorld::bProcessCutsceneOnly = false;
|
||||
|
||||
if(bCamLoaded)
|
||||
CGame::DrasticTidyUpMemory(TheCamera.GetScreenFadeStatus() == FADE_2);
|
||||
|
||||
CPad::GetPad(0)->Clear(false);
|
||||
if (bIsEverythingRemovedFromTheWorldForTheBiggestFuckoffCutsceneEver) {
|
||||
CStreaming::LoadInitialPeds();
|
||||
CStreaming::LoadInitialWeapons();
|
||||
CStreaming::LoadInitialVehicles();
|
||||
bIsEverythingRemovedFromTheWorldForTheBiggestFuckoffCutsceneEver = false;
|
||||
|
||||
CPlayerPed *pPlayerPed = FindPlayerPed();
|
||||
for (int i = 0; i < NumberOfSavedWeapons; i++) {
|
||||
int32 weaponModelId = CWeaponInfo::GetWeaponInfo(SavedWeaponIDs[i])->m_nModelId;
|
||||
uint8 flags = CStreaming::ms_aInfoForModel[weaponModelId].m_flags;
|
||||
CStreaming::RequestModel(weaponModelId, STREAMFLAGS_DONT_REMOVE);
|
||||
CStreaming::LoadAllRequestedModels(false);
|
||||
if (CWeaponInfo::GetWeaponInfo(SavedWeaponIDs[i])->m_nModel2Id != -1) {
|
||||
CStreaming::RequestModel(CWeaponInfo::GetWeaponInfo(SavedWeaponIDs[i])->m_nModel2Id, 0);
|
||||
CStreaming::LoadAllRequestedModels(false);
|
||||
}
|
||||
if (!(flags & STREAMFLAGS_DONT_REMOVE))
|
||||
CStreaming::SetModelIsDeletable(weaponModelId);
|
||||
pPlayerPed->GiveWeapon(SavedWeaponIDs[i], SavedWeaponAmmo[i], true);
|
||||
}
|
||||
NumberOfSavedWeapons = 0;
|
||||
}
|
||||
|
||||
CTimer::Resume();
|
||||
DeleteCutsceneData_overlay();
|
||||
if (bModelsRemovedForCutscene)
|
||||
LoadEverythingBecauseCutsceneDeletedAllOfIt();
|
||||
}
|
||||
|
||||
void
|
||||
CCutsceneMgr::Update(void)
|
||||
CCutsceneMgr::RemoveEverythingBecauseCutsceneDoesntFitInMemory()
|
||||
{
|
||||
enum {
|
||||
CUTSCENE_LOADING_0 = 0,
|
||||
CUTSCENE_LOADING_AUDIO,
|
||||
CUTSCENE_LOADING_2,
|
||||
CUTSCENE_LOADING_3,
|
||||
CUTSCENE_LOADING_4
|
||||
};
|
||||
|
||||
switch (ms_cutsceneLoadStatus) {
|
||||
case CUTSCENE_LOADING_AUDIO:
|
||||
SetupCutsceneToStart();
|
||||
if (CGeneral::faststricmp(ms_cutsceneName, "finale"))
|
||||
DMAudio.PlayPreloadedCutSceneMusic();
|
||||
ms_cutsceneLoadStatus++;
|
||||
break;
|
||||
case CUTSCENE_LOADING_2:
|
||||
case CUTSCENE_LOADING_3:
|
||||
ms_cutsceneLoadStatus++;
|
||||
break;
|
||||
case CUTSCENE_LOADING_4:
|
||||
ms_cutsceneLoadStatus = CUTSCENE_LOADING_0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!ms_running) return;
|
||||
|
||||
ms_cutsceneTimer += CTimer::GetTimeStepNonClippedInSeconds();
|
||||
|
||||
for (int i = 0; i < ms_numCutsceneObjs; i++) {
|
||||
int modelId = ms_pCutsceneObjects[i]->GetModelIndex();
|
||||
if (modelId >= MI_CUTOBJ01 && modelId <= MI_CUTOBJ05)
|
||||
UpdateCutsceneObjectBoundingBox(ms_pCutsceneObjects[i]->GetClump(), modelId);
|
||||
|
||||
if (ms_pCutsceneObjects[i]->m_pAttachTo != nil && modelId >= MI_SPECIAL01 && modelId <= MI_SPECIAL21)
|
||||
UpdateCutsceneObjectBoundingBox(ms_pCutsceneObjects[i]->GetClump(), modelId);
|
||||
}
|
||||
|
||||
if (bCamLoaded)
|
||||
if (CGeneral::faststricmp(ms_cutsceneName, "finale") && TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_FLYBY && ms_cutsceneLoadStatus == CUTSCENE_LOADING_0) {
|
||||
if (CPad::GetPad(0)->GetCrossJustDown()
|
||||
|| (CGame::playingIntro && CPad::GetPad(0)->GetStartJustDown())
|
||||
|| CPad::GetPad(0)->GetLeftMouseJustDown()
|
||||
|| CPad::GetPad(0)->GetEnterJustDown()
|
||||
|| CPad::GetPad(0)->GetCharJustDown(' '))
|
||||
FinishCutscene();
|
||||
}
|
||||
}
|
||||
|
||||
bool CCutsceneMgr::HasCutsceneFinished(void) { return !bCamLoaded || TheCamera.GetPositionAlongSpline() == 1.0f; }
|
||||
|
||||
void
|
||||
CCutsceneMgr::LoadAnimationUncompressed(char const* name)
|
||||
{
|
||||
strcpy(uncompressedAnims[numUncompressedAnims], name);
|
||||
|
||||
// Because that's how CAnimManager knows the end of array
|
||||
++numUncompressedAnims;
|
||||
assert(numUncompressedAnims < ARRAY_SIZE(uncompressedAnims));
|
||||
uncompressedAnims[numUncompressedAnims][0] = '\0';
|
||||
}
|
||||
|
||||
void
|
||||
CCutsceneMgr::AttachObjectToParent(CObject *pObject, CEntity *pAttachTo)
|
||||
{
|
||||
((CCutsceneObject*)pObject)->m_pAttachmentObject = nil;
|
||||
((CCutsceneObject*)pObject)->m_pAttachTo = RpClumpGetFrame(pAttachTo->GetClump());
|
||||
|
||||
debug("Attach %s to %s\n", CModelInfo::GetModelInfo(pObject->GetModelIndex())->GetModelName(), CModelInfo::GetModelInfo(pAttachTo->GetModelIndex())->GetModelName());
|
||||
}
|
||||
|
||||
void
|
||||
CCutsceneMgr::AttachObjectToFrame(CObject *pObject, CEntity *pAttachTo, const char *frame)
|
||||
{
|
||||
((CCutsceneObject*)pObject)->m_pAttachmentObject = nil;
|
||||
((CCutsceneObject*)pObject)->m_pAttachTo = RpAnimBlendClumpFindFrame(pAttachTo->GetClump(), frame)->frame;
|
||||
debug("Attach %s to component %s of %s\n",
|
||||
CModelInfo::GetModelInfo(pObject->GetModelIndex())->GetModelName(),
|
||||
frame,
|
||||
CModelInfo::GetModelInfo(pAttachTo->GetModelIndex())->GetModelName());
|
||||
if (RwObjectGetType(pObject->m_rwObject) == rpCLUMP) {
|
||||
RpClump *clump = (RpClump*)pObject->m_rwObject;
|
||||
if (IsClumpSkinned(clump))
|
||||
RpAtomicGetBoundingSphere(GetFirstAtomic(clump))->radius *= 1.1f;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CCutsceneMgr::AttachObjectToBone(CObject *pObject, CObject *pAttachTo, int bone)
|
||||
{
|
||||
RpHAnimHierarchy *hanim = GetAnimHierarchyFromSkinClump(pAttachTo->GetClump());
|
||||
RwInt32 id = RpHAnimIDGetIndex(hanim, bone);
|
||||
RwMatrix *matrixArray = RpHAnimHierarchyGetMatrixArray(hanim);
|
||||
((CCutsceneObject*)pObject)->m_pAttachmentObject = pAttachTo;
|
||||
((CCutsceneObject*)pObject)->m_pAttachTo = &matrixArray[id];
|
||||
debug("Attach %s to %s\n",
|
||||
CModelInfo::GetModelInfo(pObject->GetModelIndex())->GetModelName(),
|
||||
CModelInfo::GetModelInfo(pAttachTo->GetModelIndex())->GetModelName());
|
||||
}
|
||||
|
||||
void
|
||||
CCutsceneMgr::RemoveEverythingFromTheWorldForTheBiggestFuckoffCutsceneEver()
|
||||
{
|
||||
CStreaming::ms_disableStreaming = true;
|
||||
//CStreaming::ms_disableStreaming = true;
|
||||
CWorld::ClearExcitingStuffFromArea(FindPlayerCoors(), 120.0f, true);
|
||||
CColStore::RemoveAllCollision();
|
||||
CWorld::bProcessCutsceneOnly = true;
|
||||
ms_cutsceneProcessing = true;
|
||||
/*ms_cutsceneProcessing = true;
|
||||
|
||||
for (int i = CPools::GetPedPool()->GetSize() - 1; i >= 0; i--) {
|
||||
CPed *pPed = CPools::GetPedPool()->GetSlot(i);
|
||||
@@ -626,25 +120,21 @@ CCutsceneMgr::RemoveEverythingFromTheWorldForTheBiggestFuckoffCutsceneEver()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bIsEverythingRemovedFromTheWorldForTheBiggestFuckoffCutsceneEver = true;
|
||||
CWorld::bProcessCutsceneOnly = true;
|
||||
//bIsEverythingRemovedFromTheWorldForTheBiggestFuckoffCutsceneEver = true;*/
|
||||
CStreaming::RemoveCurrentZonesModels();
|
||||
while (CStreaming::RemoveLoadedVehicle());
|
||||
CRadar::RemoveRadarSections();
|
||||
CStreaming::SetModelIsDeletable(MI_MALE01);
|
||||
CStreaming::SetModelTxdIsDeletable(MI_MALE01);
|
||||
CStreaming::SetModelIsDeletable(MI_TAXI_D);
|
||||
CStreaming::SetModelTxdIsDeletable(MI_TAXI_D);
|
||||
CStreaming::SetModelIsDeletable(MI_COLT45);
|
||||
CStreaming::SetModelTxdIsDeletable(MI_COLT45);
|
||||
CStreaming::SetModelIsDeletable(MI_NIGHTSTICK);
|
||||
CStreaming::SetModelTxdIsDeletable(MI_NIGHTSTICK);
|
||||
CStreaming::SetModelIsDeletable(MI_MISSILE);
|
||||
CStreaming::SetModelTxdIsDeletable(MI_MISSILE);
|
||||
CStreaming::SetModelIsDeletable(MI_POLICE);
|
||||
CStreaming::SetModelTxdIsDeletable(MI_POLICE);
|
||||
|
||||
while (CStreaming::RemoveLoadedVehicle()) ;
|
||||
|
||||
CRadar::RemoveRadarSections();
|
||||
|
||||
for (int i = CPools::GetDummyPool()->GetSize() - 1; i >= 0; i--) {
|
||||
/*for (int i = CPools::GetDummyPool()->GetSize() - 1; i >= 0; i--) {
|
||||
CDummy* pDummy = CPools::GetDummyPool()->GetSlot(i);
|
||||
if (pDummy)
|
||||
pDummy->DeleteRwObject();
|
||||
@@ -664,7 +154,7 @@ CCutsceneMgr::RemoveEverythingFromTheWorldForTheBiggestFuckoffCutsceneEver()
|
||||
if (!pBuilding->bImBeingRendered)
|
||||
pBuilding->DeleteRwObject();
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
CPlayerPed *pPlayerPed = FindPlayerPed();
|
||||
pPlayerPed->RemoveWeaponAnims(0, -1000.0f);
|
||||
@@ -679,5 +169,69 @@ CCutsceneMgr::RemoveEverythingFromTheWorldForTheBiggestFuckoffCutsceneEver()
|
||||
}
|
||||
|
||||
pPlayerPed->ClearWeapons();
|
||||
CGame::DrasticTidyUpMemory(true);
|
||||
bModelsRemovedForCutscene = true;
|
||||
//CGame::DrasticTidyUpMemory(true);
|
||||
}
|
||||
|
||||
void
|
||||
CCutsceneMgr::LoadEverythingBecauseCutsceneDeletedAllOfIt()
|
||||
{
|
||||
bModelsRemovedForCutscene = false;
|
||||
CStreaming::LoadInitialPeds();
|
||||
CStreaming::LoadInitialWeapons();
|
||||
//CStreaming::LoadInitialVehicles();
|
||||
|
||||
CPlayerPed *pPlayerPed = FindPlayerPed();
|
||||
for (int i = 0; i < NumberOfSavedWeapons; i++) {
|
||||
int32 weaponModelId = CWeaponInfo::GetWeaponInfo(SavedWeaponIDs[i])->m_nModelId;
|
||||
uint8 flags = CStreaming::ms_aInfoForModel[weaponModelId].m_flags;
|
||||
CStreaming::RequestModel(weaponModelId, STREAMFLAGS_DONT_REMOVE);
|
||||
CStreaming::LoadAllRequestedModels(false);
|
||||
if (CWeaponInfo::GetWeaponInfo(SavedWeaponIDs[i])->m_nModel2Id != -1) {
|
||||
CStreaming::RequestModel(CWeaponInfo::GetWeaponInfo(SavedWeaponIDs[i])->m_nModel2Id, 0);
|
||||
CStreaming::LoadAllRequestedModels(false);
|
||||
}
|
||||
if (!(flags & STREAMFLAGS_DONT_REMOVE))
|
||||
CStreaming::SetModelIsDeletable(weaponModelId);
|
||||
pPlayerPed->GiveWeapon(SavedWeaponIDs[i], SavedWeaponAmmo[i], true);
|
||||
}
|
||||
NumberOfSavedWeapons = 0;
|
||||
}
|
||||
|
||||
void
|
||||
CCutsceneMgr::Update(void)
|
||||
{
|
||||
if (ms_cutsceneLoadStatus != CUTSCENE_NOT_LOADED)
|
||||
Update_overlay();
|
||||
}
|
||||
|
||||
void
|
||||
CCutsceneMgr::LoadAnimationUncompressed(char const* name)
|
||||
{
|
||||
strcpy(ms_aUncompressedCutsceneAnims[ms_numUncompressedCutsceneAnims], name);
|
||||
|
||||
// Because that's how CAnimManager knows the end of array
|
||||
++ms_numUncompressedCutsceneAnims;
|
||||
assert(ms_numUncompressedCutsceneAnims < ARRAY_SIZE(ms_aUncompressedCutsceneAnims));
|
||||
ms_aUncompressedCutsceneAnims[ms_numUncompressedCutsceneAnims][0] = '\0';
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
CCutsceneMgr::IsCutsceneSkipButtonBeingPressed()
|
||||
{
|
||||
return (CPad::GetPad(0)->GetCrossJustDown()
|
||||
|| CPad::GetPad(0)->GetLeftMouseJustDown()
|
||||
|| CPad::GetPad(0)->GetEnterJustDown()
|
||||
|| CPad::GetPad(0)->GetCharJustDown(' '));
|
||||
}
|
||||
|
||||
void
|
||||
CCutsceneMgr::AppendToNextCutscene(const char *object, const char *anim)
|
||||
{
|
||||
strcpy(ms_cAppendObjectName[ms_numAppendObjectNames], object);
|
||||
strlwr(ms_cAppendObjectName[ms_numAppendObjectNames]);
|
||||
strcpy(ms_cAppendAnimName[ms_numAppendObjectNames], anim);
|
||||
strlwr(ms_cAppendAnimName[ms_numAppendObjectNames]);
|
||||
ms_numAppendObjectNames++;
|
||||
}
|
||||
@@ -1,14 +1,69 @@
|
||||
#pragma once
|
||||
#include "CutsceneObject.h"
|
||||
|
||||
#define CUTSCENENAMESIZE 8
|
||||
|
||||
class CDirectory;
|
||||
class CAnimBlendAssocGroup;
|
||||
class CCutsceneHead;
|
||||
|
||||
enum {
|
||||
CUTSCENE_NOT_LOADED = 0,
|
||||
CUTSCENE_LOADING,
|
||||
CUTSCENE_LOADED,
|
||||
};
|
||||
|
||||
enum {
|
||||
CUTSCENE_PLAYING_0 = 0,
|
||||
CUTSCENE_STARTED,
|
||||
CUTSCENE_PLAYING_2,
|
||||
CUTSCENE_PLAYING_3,
|
||||
CUTSCENE_PLAYING_4,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
NAMELENGTH = 32,
|
||||
NUM_CUTS_PARTICLE_EFFECTS = 8,
|
||||
NUM_CUTS_MAX_TEXTS = 64,
|
||||
NUM_CUTS_UNCOMPRESSED_ANIMS = 8,
|
||||
TEXT_KEY_SIZE = 8,
|
||||
CUTSCENENAMESIZE = 8
|
||||
};
|
||||
|
||||
struct sToHideItem
|
||||
{
|
||||
float x, y, z;
|
||||
char name[NAMELENGTH];
|
||||
};
|
||||
|
||||
// TODO: figure out from SA
|
||||
// this is unused in LCS anyway
|
||||
struct sParticleEffect
|
||||
{
|
||||
char name[NAMELENGTH];
|
||||
bool bPlayed; // ??
|
||||
int iTime;
|
||||
int unk1;
|
||||
int unk2;
|
||||
char name2[NAMELENGTH];
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float unkX;
|
||||
float unkY;
|
||||
float unkZ;
|
||||
bool unk10;
|
||||
bool unk11;
|
||||
};
|
||||
|
||||
struct sAttachInfo
|
||||
{
|
||||
int attachToId, objectId, boneId;
|
||||
};
|
||||
|
||||
class CCutsceneMgr
|
||||
{
|
||||
|
||||
static bool ms_running;
|
||||
static CCutsceneObject *ms_pCutsceneObjects[NUMCUTSCENEOBJECTS];
|
||||
|
||||
@@ -24,10 +79,55 @@ class CCutsceneMgr
|
||||
static bool ms_wasCutsceneSkipped;
|
||||
static bool ms_cutsceneProcessing;
|
||||
static bool ms_useCutsceneShadows;
|
||||
static bool ms_hasFileInfo;
|
||||
static int ms_numLoadObjectNames;
|
||||
|
||||
static char ms_cAppendAnimName[NUMCUTSCENEOBJECTS][NAMELENGTH];
|
||||
static char ms_cAppendObjectName[NUMCUTSCENEOBJECTS][NAMELENGTH];
|
||||
static int ms_numAppendObjectNames;
|
||||
public:
|
||||
static CDirectory *ms_pCutsceneDir;
|
||||
static uint32 ms_cutsceneLoadStatus;
|
||||
|
||||
static bool mCutsceneSkipFading;
|
||||
static int mCutsceneSkipFadeTime;
|
||||
|
||||
static float m_fPrevCarDensity;
|
||||
static float m_fPrevPedDensity;
|
||||
|
||||
static bool m_PrevExtraColourOn;
|
||||
static uint32 m_PrevExtraColour;
|
||||
|
||||
static uint32 ms_iNumParticleEffects;
|
||||
static sParticleEffect ms_pParticleEffects[NUM_CUTS_PARTICLE_EFFECTS];
|
||||
|
||||
static sToHideItem ms_crToHideItems[NUMCUTSCENEOBJECTS];
|
||||
static uint32 ms_iNumHiddenEntities;
|
||||
static CEntity *ms_pHiddenEntities[NUMCUTSCENEOBJECTS];
|
||||
|
||||
static int ms_numAttachObjectToBones;
|
||||
static bool ms_bRepeatObject[NUMCUTSCENEOBJECTS];
|
||||
|
||||
static sAttachInfo ms_iAttachObjectToBone[NUMCUTSCENEOBJECTS];
|
||||
|
||||
static uint32 ms_numUncompressedCutsceneAnims;
|
||||
|
||||
static char ms_aUncompressedCutsceneAnims[NUM_CUTS_UNCOMPRESSED_ANIMS][NAMELENGTH];
|
||||
|
||||
static uint32 ms_iTextDuration[NUM_CUTS_MAX_TEXTS];
|
||||
static uint32 ms_iTextStartTime[NUM_CUTS_MAX_TEXTS];
|
||||
static char ms_cTextOutput[NUM_CUTS_MAX_TEXTS][TEXT_KEY_SIZE];
|
||||
|
||||
static uint32 ms_currTextOutput;
|
||||
static uint32 ms_numTextOutput;
|
||||
static uint32 ms_iModelIndex[NUMCUTSCENEOBJECTS];
|
||||
|
||||
static char ms_cLoadAnimName[NUMCUTSCENEOBJECTS][NAMELENGTH];
|
||||
static char ms_cLoadObjectName[NUMCUTSCENEOBJECTS][NAMELENGTH];
|
||||
|
||||
static uint32 ms_cutscenePlayStatus;
|
||||
|
||||
static void StartCutscene();
|
||||
static void StartCutsceneProcessing() { ms_cutsceneProcessing = true; }
|
||||
static bool IsRunning(void) { return ms_running; }
|
||||
static bool HasLoaded(void) { return ms_loaded; }
|
||||
@@ -35,19 +135,19 @@ public:
|
||||
static bool WasCutsceneSkipped(void) { return ms_wasCutsceneSkipped; }
|
||||
static bool UseLodMultiplier(void) { return ms_useLodMultiplier; }
|
||||
static CCutsceneObject* GetCutsceneObject(int id) { return ms_pCutsceneObjects[id]; }
|
||||
static int GetCutsceneTimeInMilleseconds(void) { return 1000.0f * ms_cutsceneTimer; }
|
||||
static uint32 GetCutsceneTimeInMilleseconds(void);
|
||||
static char *GetCutsceneName(void) { return ms_cutsceneName; }
|
||||
static void SetCutsceneOffset(const CVector& vec) { ms_cutsceneOffset = vec; }
|
||||
static bool HasCutsceneFinished(void);
|
||||
|
||||
static void Initialise(void);
|
||||
static void Initialise(void *dir = nil);
|
||||
static void Shutdown(void);
|
||||
static void LoadCutsceneData(const char *szCutsceneName);
|
||||
static void FinishCutscene(void);
|
||||
static void SetupCutsceneToStart(void);
|
||||
static void SetCutsceneAnim(const char *animName, CObject *pObject);
|
||||
static void SetCutsceneAnimToLoop(const char *animName);
|
||||
static CCutsceneHead *AddCutsceneHead(CObject *pObject, int modelId);
|
||||
static CCutsceneHead *SetHeadAnim(const char*, CObject *pObject);
|
||||
static CCutsceneObject *CreateCutsceneObject(int modelId);
|
||||
static void DeleteCutsceneData(void);
|
||||
static void LoadAnimationUncompressed(char const*);
|
||||
@@ -56,6 +156,24 @@ public:
|
||||
static void AttachObjectToParent(CObject *pObject, CEntity *pAttachTo);
|
||||
static void AttachObjectToFrame(CObject *pObject, CEntity *pAttachTo, const char *frame);
|
||||
static void AttachObjectToBone(CObject *pObject, CObject *pAttachTo, int frame);
|
||||
static void RemoveEverythingFromTheWorldForTheBiggestFuckoffCutsceneEver();
|
||||
static void RemoveEverythingBecauseCutsceneDoesntFitInMemory();
|
||||
static void LoadEverythingBecauseCutsceneDeletedAllOfIt();
|
||||
static void DisableCutsceneShadows() { ms_useCutsceneShadows = false; }
|
||||
|
||||
|
||||
static void LoadCutsceneData_overlay(const char* szCutsceneName);
|
||||
static bool LoadCutsceneData_postload(bool b = false);
|
||||
static void Update_overlay(void);
|
||||
static void DeleteCutsceneData_overlay(void);
|
||||
|
||||
static bool IsCutsceneSkipButtonBeingPressed();
|
||||
static void AppendToNextCutscene(const char *object, const char *anim);
|
||||
|
||||
static void LoadCutsceneData_preload();
|
||||
static void LoadCutsceneData_loading();
|
||||
static void HideRequestedObjects();
|
||||
|
||||
static bool PresubBodge();
|
||||
|
||||
static void Write(base::cRelocatableChunkWriter& writer);
|
||||
};
|
||||
|
||||
1030
src/animation/CutsceneMgr_overlay.cpp
Normal file
1030
src/animation/CutsceneMgr_overlay.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -8,29 +8,46 @@
|
||||
#include "SurfaceTable.h"
|
||||
#include "sampman.h"
|
||||
|
||||
const int CollisionSoundIntensity = 60;
|
||||
|
||||
cAudioCollisionManager::cAudioCollisionManager()
|
||||
void
|
||||
cAudioManager::ReportCollision(CEntity *entity1, CEntity *entity2, uint8 surface1, uint8 surface2, float collisionPower,
|
||||
float velocity)
|
||||
{
|
||||
m_sQueue.m_pEntity1 = nil;
|
||||
m_sQueue.m_pEntity2 = nil;
|
||||
m_sQueue.m_bSurface1 = SURFACE_DEFAULT;
|
||||
m_sQueue.m_bSurface2 = SURFACE_DEFAULT;
|
||||
m_sQueue.m_fIntensity2 = 0.0f;
|
||||
m_sQueue.m_fIntensity1 = 0.0f;
|
||||
m_sQueue.m_vecPosition = CVector(0.0f, 0.0f, 0.0f);
|
||||
float distSquared;
|
||||
CVector v1;
|
||||
CVector v2;
|
||||
|
||||
for (int i = 0; i < NUMAUDIOCOLLISIONS; i++)
|
||||
m_bIndicesTable[i] = NUMAUDIOCOLLISIONS;
|
||||
if(!m_bIsInitialised || m_nCollisionEntity < 0 || m_bIsPaused ||
|
||||
(velocity < 0.0016f && collisionPower < 0.01f))
|
||||
return;
|
||||
|
||||
m_bCollisionsInQueue = 0;
|
||||
if(entity1->IsBuilding()) {
|
||||
v1 = v2 = entity2->GetPosition();
|
||||
} else if(entity2->IsBuilding()) {
|
||||
v1 = v2 = entity1->GetPosition();
|
||||
} else {
|
||||
v1 = entity1->GetPosition();
|
||||
v2 = entity2->GetPosition();
|
||||
}
|
||||
CVector pos = (v1 + v2) * 0.5f;
|
||||
distSquared = GetDistanceSquared(pos);
|
||||
if(distSquared < SQR(COLLISION_MAX_DIST)) {
|
||||
m_sCollisionManager.m_sQueue.m_pEntity1 = entity1;
|
||||
m_sCollisionManager.m_sQueue.m_pEntity2 = entity2;
|
||||
m_sCollisionManager.m_sQueue.m_bSurface1 = surface1;
|
||||
m_sCollisionManager.m_sQueue.m_bSurface2 = surface2;
|
||||
m_sCollisionManager.m_sQueue.m_fIntensity1 = collisionPower;
|
||||
m_sCollisionManager.m_sQueue.m_fIntensity2 = velocity;
|
||||
m_sCollisionManager.m_sQueue.m_vecPosition = pos;
|
||||
m_sCollisionManager.m_sQueue.m_fDistance = distSquared;
|
||||
m_sCollisionManager.AddCollisionToRequestedQueue();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
cAudioCollisionManager::AddCollisionToRequestedQueue()
|
||||
{
|
||||
int32 collisionsIndex;
|
||||
int32 i;
|
||||
uint32 collisionsIndex;
|
||||
uint32 i;
|
||||
|
||||
|
||||
if (m_bCollisionsInQueue < NUMAUDIOCOLLISIONS)
|
||||
@@ -55,139 +72,72 @@ cAudioCollisionManager::AddCollisionToRequestedQueue()
|
||||
m_bIndicesTable[i] = collisionsIndex;
|
||||
}
|
||||
|
||||
float
|
||||
cAudioManager::GetCollisionLoopingRatio(uint32 a, uint32 b, float c) const
|
||||
{
|
||||
return GetCollisionRatio(c, 0.0f, 0.02f, 0.02f);
|
||||
}
|
||||
|
||||
float
|
||||
cAudioManager::GetCollisionOneShotRatio(int32 a, float b) const
|
||||
{
|
||||
float result;
|
||||
|
||||
switch(a) {
|
||||
case SURFACE_DEFAULT:
|
||||
case SURFACE_TARMAC:
|
||||
case SURFACE_PAVEMENT:
|
||||
case SURFACE_STEEP_CLIFF:
|
||||
case SURFACE_TRANSPARENT_STONE:
|
||||
case SURFACE_CONCRETE_BEACH: result = GetCollisionRatio(b, 10.f, 60.f, 50.f); break;
|
||||
case SURFACE_GRASS:
|
||||
case SURFACE_GRAVEL:
|
||||
case SURFACE_MUD_DRY:
|
||||
case SURFACE_CARDBOARDBOX: result = GetCollisionRatio(b, 0.f, 2.f, 2.f); break;
|
||||
case SURFACE_CAR: result = GetCollisionRatio(b, 6.f, 50.f, 44.f); break;
|
||||
case SURFACE_GLASS:
|
||||
case SURFACE_METAL_CHAIN_FENCE: result = GetCollisionRatio(b, 0.1f, 10.f, 9.9f); break;
|
||||
case SURFACE_TRANSPARENT_CLOTH:
|
||||
case SURFACE_THICK_METAL_PLATE: result = GetCollisionRatio(b, 30.f, 130.f, 100.f); break;
|
||||
case SURFACE_GARAGE_DOOR: result = GetCollisionRatio(b, 20.f, 100.f, 80.f); break;
|
||||
case SURFACE_CAR_PANEL: result = GetCollisionRatio(b, 0.f, 4.f, 4.f); break;
|
||||
case SURFACE_SCAFFOLD_POLE:
|
||||
case SURFACE_METAL_GATE:
|
||||
case SURFACE_LAMP_POST: result = GetCollisionRatio(b, 1.f, 10.f, 9.f); break;
|
||||
case SURFACE_FIRE_HYDRANT: result = GetCollisionRatio(b, 1.f, 15.f, 14.f); break;
|
||||
case SURFACE_GIRDER: result = GetCollisionRatio(b, 8.f, 50.f, 42.f); break;
|
||||
case SURFACE_PED: result = GetCollisionRatio(b, 0.f, 20.f, 20.f); break;
|
||||
case SURFACE_SAND:
|
||||
case SURFACE_WATER:
|
||||
case SURFACE_RUBBER:
|
||||
case SURFACE_WHEELBASE:
|
||||
case SURFACE_SAND_BEACH: result = GetCollisionRatio(b, 0.f, 10.f, 10.f); break;
|
||||
case SURFACE_WOOD_CRATES: result = GetCollisionRatio(b, 1.f, 4.f, 3.f); break;
|
||||
case SURFACE_WOOD_BENCH: result = GetCollisionRatio(b, 0.1f, 5.f, 4.9f); break;
|
||||
case SURFACE_WOOD_SOLID: result = GetCollisionRatio(b, 0.1f, 40.f, 39.9f); break;
|
||||
case SURFACE_PLASTIC: result = GetCollisionRatio(b, 0.1f, 4.f, 3.9f); break;
|
||||
case SURFACE_HEDGE: result = GetCollisionRatio(b, 0.f, 0.5f, 0.5f); break;
|
||||
case SURFACE_CONTAINER: result = GetCollisionRatio(b, 4.f, 40.f, 36.f); break;
|
||||
case SURFACE_NEWS_VENDOR: result = GetCollisionRatio(b, 0.f, 5.f, 5.f); break;
|
||||
default: result = 0.f; break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
float
|
||||
cAudioManager::GetCollisionRatio(float a, float b, float c, float d) const
|
||||
{
|
||||
float e;
|
||||
e = a;
|
||||
if(a <= b) return 0.0f;
|
||||
if(c <= a) e = c;
|
||||
return (e - b) / d;
|
||||
}
|
||||
|
||||
uint32
|
||||
cAudioManager::SetLoopingCollisionRequestedSfxFreqAndGetVol(const cAudioCollision &audioCollision)
|
||||
{
|
||||
uint8 surface1 = audioCollision.m_bSurface1;
|
||||
uint8 surface2 = audioCollision.m_bSurface2;
|
||||
int32 vol;
|
||||
float ratio;
|
||||
|
||||
if(surface1 == SURFACE_GRASS || surface2 == SURFACE_GRASS || surface1 == SURFACE_HEDGE ||
|
||||
surface2 == SURFACE_HEDGE) {
|
||||
ratio = GetCollisionRatio(audioCollision.m_fIntensity2, 0.0001f, 0.09f, 0.0899f);
|
||||
m_sQueueSample.m_nSampleIndex = SFX_RAIN;
|
||||
m_sQueueSample.m_nFrequency = 13000.f * ratio + 35000;
|
||||
vol = 50.f * ratio;
|
||||
} else if(surface1 == SURFACE_WATER || surface2 == SURFACE_WATER) {
|
||||
ratio = GetCollisionRatio(audioCollision.m_fIntensity2, 0.0001f, 0.09f, 0.0899f);
|
||||
m_sQueueSample.m_nSampleIndex = SFX_BOAT_WATER_LOOP;
|
||||
m_sQueueSample.m_nFrequency = 6050.f * ratio + 16000;
|
||||
vol = 30.f * ratio;
|
||||
} else if(surface1 == SURFACE_GRAVEL || surface2 == SURFACE_GRAVEL || surface1 == SURFACE_MUD_DRY || surface2 == SURFACE_MUD_DRY ||
|
||||
surface1 == SURFACE_SAND || surface2 == SURFACE_SAND || surface1 == SURFACE_SAND_BEACH || surface2 == SURFACE_SAND_BEACH) {
|
||||
ratio = GetCollisionRatio(audioCollision.m_fIntensity2, 0.0001f, 0.09f, 0.0899f);
|
||||
m_sQueueSample.m_nSampleIndex = SFX_GRAVEL_SKID;
|
||||
m_sQueueSample.m_nFrequency = 6000.f * ratio + 10000;
|
||||
vol = 50.f * ratio;
|
||||
} else if(surface1 == SURFACE_PED || surface2 == SURFACE_PED) {
|
||||
return 0;
|
||||
} else {
|
||||
ratio = GetCollisionRatio(audioCollision.m_fIntensity2, 0.0001f, 0.09f, 0.0899f);
|
||||
m_sQueueSample.m_nSampleIndex = SFX_SCRAPE_CAR_1;
|
||||
m_sQueueSample.m_nFrequency = 10000.f * ratio + 10000;
|
||||
vol = 40.f * ratio;
|
||||
}
|
||||
if(audioCollision.m_nBaseVolume < 2) vol = audioCollision.m_nBaseVolume * vol / 2;
|
||||
return vol;
|
||||
}
|
||||
|
||||
void
|
||||
cAudioManager::SetUpLoopingCollisionSound(const cAudioCollision &col, uint8 counter)
|
||||
cAudioManager::ServiceCollisions()
|
||||
{
|
||||
bool distCalculated = false;
|
||||
if(col.m_fIntensity2 > 0.0016f) {
|
||||
uint8 emittingVol = SetLoopingCollisionRequestedSfxFreqAndGetVol(col);
|
||||
if(emittingVol) {
|
||||
CalculateDistance(distCalculated, m_sQueueSample.m_fDistance);
|
||||
m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, CollisionSoundIntensity, m_sQueueSample.m_fDistance);
|
||||
if(m_sQueueSample.m_nVolume) {
|
||||
m_sQueueSample.m_nCounter = counter;
|
||||
m_sQueueSample.m_vecPos = col.m_vecPosition;
|
||||
m_sQueueSample.m_nBankIndex = SFX_BANK_0;
|
||||
m_sQueueSample.m_bIs2D = false;
|
||||
m_sQueueSample.m_nReleasingVolumeModificator = 7;
|
||||
m_sQueueSample.m_nLoopCount = 0;
|
||||
m_sQueueSample.m_nEmittingVolume = emittingVol;
|
||||
m_sQueueSample.m_nLoopStart =
|
||||
SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);
|
||||
m_sQueueSample.m_nLoopEnd =
|
||||
SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);
|
||||
m_sQueueSample.m_fSpeedMultiplier = 4.0f;
|
||||
m_sQueueSample.m_fSoundIntensity = CollisionSoundIntensity;
|
||||
m_sQueueSample.m_bReleasingSoundFlag = false;
|
||||
m_sQueueSample.m_nReleasingVolumeDivider = 5;
|
||||
m_sQueueSample.m_bReverbFlag = true;
|
||||
m_sQueueSample.m_bRequireReflection = false;
|
||||
AddSampleToRequestedQueue();
|
||||
int i, j;
|
||||
bool8 abRepeatedCollision1[NUMAUDIOCOLLISIONS];
|
||||
bool8 abRepeatedCollision2[NUMAUDIOCOLLISIONS];
|
||||
|
||||
m_sQueueSample.m_nEntityIndex = m_nCollisionEntity;
|
||||
|
||||
for (int i = 0; i < NUMAUDIOCOLLISIONS; i++)
|
||||
abRepeatedCollision1[i] = abRepeatedCollision2[i] = FALSE;
|
||||
|
||||
for (i = 0; i < m_sCollisionManager.m_bCollisionsInQueue; i++) {
|
||||
for (j = 0; j < NUMAUDIOCOLLISIONS; j++) {
|
||||
int index = m_sCollisionManager.m_bIndicesTable[i];
|
||||
if ((m_sCollisionManager.m_asCollisions1[index].m_pEntity1 == m_sCollisionManager.m_asCollisions2[j].m_pEntity1)
|
||||
&& (m_sCollisionManager.m_asCollisions1[index].m_pEntity2 == m_sCollisionManager.m_asCollisions2[j].m_pEntity2)
|
||||
&& (m_sCollisionManager.m_asCollisions1[index].m_bSurface1 == m_sCollisionManager.m_asCollisions2[j].m_bSurface1)
|
||||
&& (m_sCollisionManager.m_asCollisions1[index].m_bSurface2 == m_sCollisionManager.m_asCollisions2[j].m_bSurface2)
|
||||
) {
|
||||
abRepeatedCollision1[index] = TRUE;
|
||||
abRepeatedCollision2[j] = TRUE;
|
||||
m_sCollisionManager.m_asCollisions1[index].m_nBaseVolume = ++m_sCollisionManager.m_asCollisions2[j].m_nBaseVolume;
|
||||
SetUpLoopingCollisionSound(m_sCollisionManager.m_asCollisions1[index], j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < NUMAUDIOCOLLISIONS; i++) {
|
||||
if (!abRepeatedCollision2[i]) {
|
||||
m_sCollisionManager.m_asCollisions2[i].m_pEntity1 = nil;
|
||||
m_sCollisionManager.m_asCollisions2[i].m_pEntity2 = nil;
|
||||
m_sCollisionManager.m_asCollisions2[i].m_bSurface1 = SURFACE_DEFAULT;
|
||||
m_sCollisionManager.m_asCollisions2[i].m_bSurface2 = SURFACE_DEFAULT;
|
||||
m_sCollisionManager.m_asCollisions2[i].m_fIntensity2 = 0.0f;
|
||||
m_sCollisionManager.m_asCollisions2[i].m_fIntensity1 = 0.0f;
|
||||
m_sCollisionManager.m_asCollisions2[i].m_vecPosition = CVector(0.0f, 0.0f, 0.0f);
|
||||
m_sCollisionManager.m_asCollisions2[i].m_fDistance = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < m_sCollisionManager.m_bCollisionsInQueue; i++) {
|
||||
int index = m_sCollisionManager.m_bIndicesTable[i];
|
||||
if (!abRepeatedCollision1[index]) {
|
||||
for (j = 0; j < NUMAUDIOCOLLISIONS; j++) {
|
||||
if (!abRepeatedCollision2[j]) {
|
||||
m_sCollisionManager.m_asCollisions2[j].m_nBaseVolume = 1;
|
||||
m_sCollisionManager.m_asCollisions2[j].m_pEntity1 = m_sCollisionManager.m_asCollisions1[index].m_pEntity1;
|
||||
m_sCollisionManager.m_asCollisions2[j].m_pEntity2 = m_sCollisionManager.m_asCollisions1[index].m_pEntity2;
|
||||
m_sCollisionManager.m_asCollisions2[j].m_bSurface1 = m_sCollisionManager.m_asCollisions1[index].m_bSurface1;
|
||||
m_sCollisionManager.m_asCollisions2[j].m_bSurface2 = m_sCollisionManager.m_asCollisions1[index].m_bSurface2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
SetUpOneShotCollisionSound(m_sCollisionManager.m_asCollisions1[index]);
|
||||
SetUpLoopingCollisionSound(m_sCollisionManager.m_asCollisions1[index], j);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUMAUDIOCOLLISIONS; i++)
|
||||
m_sCollisionManager.m_bIndicesTable[i] = NUMAUDIOCOLLISIONS;
|
||||
m_sCollisionManager.m_bCollisionsInQueue = 0;
|
||||
}
|
||||
static const int32 gOneShotCol[] = {SFX_COL_TARMAC_1,
|
||||
|
||||
static const uint32 gOneShotCol[] = {SFX_COL_TARMAC_1,
|
||||
SFX_COL_TARMAC_1,
|
||||
SFX_COL_GRASS_1,
|
||||
SFX_COL_GRAVEL_1,
|
||||
@@ -226,11 +176,10 @@ static const int32 gOneShotCol[] = {SFX_COL_TARMAC_1,
|
||||
void
|
||||
cAudioManager::SetUpOneShotCollisionSound(const cAudioCollision &col)
|
||||
{
|
||||
uint16 s1;
|
||||
uint16 s2;
|
||||
|
||||
int16 s1;
|
||||
int16 s2;
|
||||
|
||||
int32 emittingVol;
|
||||
uint32 emittingVol;
|
||||
float ratio;
|
||||
|
||||
static uint16 counter = 28;
|
||||
@@ -249,12 +198,12 @@ cAudioManager::SetUpOneShotCollisionSound(const cAudioCollision &col)
|
||||
s1 = SURFACE_CAR_PANEL;
|
||||
ratio = Min(1.f, 2.f * ratio);
|
||||
}
|
||||
emittingVol = 40.f * ratio;
|
||||
emittingVol = 40 * ratio;
|
||||
if(emittingVol) {
|
||||
m_sQueueSample.m_fDistance = Sqrt(col.m_fDistance);
|
||||
m_sQueueSample.m_nVolume =
|
||||
ComputeVolume(emittingVol, CollisionSoundIntensity, m_sQueueSample.m_fDistance);
|
||||
if(m_sQueueSample.m_nVolume) {
|
||||
ComputeVolume(emittingVol, COLLISION_MAX_DIST, m_sQueueSample.m_fDistance);
|
||||
if(m_sQueueSample.m_nVolume > 0) {
|
||||
m_sQueueSample.m_nSampleIndex = gOneShotCol[s1];
|
||||
switch(m_sQueueSample.m_nSampleIndex) {
|
||||
case SFX_COL_TARMAC_1:
|
||||
@@ -311,17 +260,16 @@ cAudioManager::SetUpOneShotCollisionSound(const cAudioCollision &col)
|
||||
if(counter >= 255) counter = 28;
|
||||
m_sQueueSample.m_vecPos = col.m_vecPosition;
|
||||
m_sQueueSample.m_nBankIndex = SFX_BANK_0;
|
||||
m_sQueueSample.m_bIs2D = false;
|
||||
m_sQueueSample.m_nReleasingVolumeModificator = 11;
|
||||
m_sQueueSample.m_bIs2D = FALSE;
|
||||
m_sQueueSample.m_nPriority = 11;
|
||||
m_sQueueSample.m_nLoopCount = 1;
|
||||
m_sQueueSample.m_nEmittingVolume = emittingVol;
|
||||
m_sQueueSample.m_nLoopStart = 0;
|
||||
m_sQueueSample.m_nLoopEnd = -1;
|
||||
SET_EMITTING_VOLUME(emittingVol);
|
||||
RESET_LOOP_OFFSETS
|
||||
m_sQueueSample.m_fSpeedMultiplier = 4.0f;
|
||||
m_sQueueSample.m_fSoundIntensity = CollisionSoundIntensity;
|
||||
m_sQueueSample.m_bReleasingSoundFlag = true;
|
||||
m_sQueueSample.m_bReverbFlag = true;
|
||||
m_sQueueSample.m_bRequireReflection = false;
|
||||
m_sQueueSample.m_MaxDistance = COLLISION_MAX_DIST;
|
||||
m_sQueueSample.m_bStatic = TRUE;
|
||||
SET_SOUND_REVERB(TRUE);
|
||||
SET_SOUND_REFLECTION(FALSE);
|
||||
AddSampleToRequestedQueue();
|
||||
}
|
||||
}
|
||||
@@ -329,101 +277,129 @@ cAudioManager::SetUpOneShotCollisionSound(const cAudioCollision &col)
|
||||
}
|
||||
|
||||
void
|
||||
cAudioManager::ServiceCollisions()
|
||||
cAudioManager::SetUpLoopingCollisionSound(const cAudioCollision &col, uint8 counter)
|
||||
{
|
||||
int i, j;
|
||||
bool abRepeatedCollision1[NUMAUDIOCOLLISIONS];
|
||||
bool abRepeatedCollision2[NUMAUDIOCOLLISIONS];
|
||||
|
||||
m_sQueueSample.m_nEntityIndex = m_nCollisionEntity;
|
||||
|
||||
for (int i = 0; i < NUMAUDIOCOLLISIONS; i++)
|
||||
abRepeatedCollision1[i] = abRepeatedCollision2[i] = false;
|
||||
|
||||
for (i = 0; i < m_sCollisionManager.m_bCollisionsInQueue; i++) {
|
||||
for (j = 0; j < NUMAUDIOCOLLISIONS; j++) {
|
||||
int index = m_sCollisionManager.m_bIndicesTable[i];
|
||||
if ((m_sCollisionManager.m_asCollisions1[index].m_pEntity1 == m_sCollisionManager.m_asCollisions2[j].m_pEntity1)
|
||||
&& (m_sCollisionManager.m_asCollisions1[index].m_pEntity2 == m_sCollisionManager.m_asCollisions2[j].m_pEntity2)
|
||||
&& (m_sCollisionManager.m_asCollisions1[index].m_bSurface1 == m_sCollisionManager.m_asCollisions2[j].m_bSurface1)
|
||||
&& (m_sCollisionManager.m_asCollisions1[index].m_bSurface2 == m_sCollisionManager.m_asCollisions2[j].m_bSurface2)
|
||||
) {
|
||||
abRepeatedCollision1[index] = true;
|
||||
abRepeatedCollision2[j] = true;
|
||||
m_sCollisionManager.m_asCollisions1[index].m_nBaseVolume = ++m_sCollisionManager.m_asCollisions2[j].m_nBaseVolume;
|
||||
SetUpLoopingCollisionSound(m_sCollisionManager.m_asCollisions1[index], j);
|
||||
break;
|
||||
bool8 distCalculated = FALSE;
|
||||
if(col.m_fIntensity2 > 0.0016f) {
|
||||
uint8 emittingVol = SetLoopingCollisionRequestedSfxFreqAndGetVol(col);
|
||||
if(emittingVol) {
|
||||
CalculateDistance(distCalculated, m_sQueueSample.m_fDistance);
|
||||
m_sQueueSample.m_nVolume = ComputeVolume(emittingVol, COLLISION_MAX_DIST, m_sQueueSample.m_fDistance);
|
||||
if(m_sQueueSample.m_nVolume > 0) {
|
||||
m_sQueueSample.m_nCounter = counter;
|
||||
m_sQueueSample.m_vecPos = col.m_vecPosition;
|
||||
m_sQueueSample.m_nBankIndex = SFX_BANK_0;
|
||||
m_sQueueSample.m_bIs2D = FALSE;
|
||||
m_sQueueSample.m_nPriority = 7;
|
||||
m_sQueueSample.m_nLoopCount = 0;
|
||||
SET_EMITTING_VOLUME(emittingVol);
|
||||
SET_LOOP_OFFSETS(m_sQueueSample.m_nSampleIndex)
|
||||
m_sQueueSample.m_fSpeedMultiplier = 4.0f;
|
||||
m_sQueueSample.m_MaxDistance = COLLISION_MAX_DIST;
|
||||
m_sQueueSample.m_bStatic = FALSE;
|
||||
m_sQueueSample.m_nFramesToPlay = 5;
|
||||
SET_SOUND_REVERB(TRUE);
|
||||
SET_SOUND_REFLECTION(FALSE);
|
||||
AddSampleToRequestedQueue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < NUMAUDIOCOLLISIONS; i++) {
|
||||
if (!abRepeatedCollision2[i]) {
|
||||
m_sCollisionManager.m_asCollisions2[i].m_pEntity1 = nil;
|
||||
m_sCollisionManager.m_asCollisions2[i].m_pEntity2 = nil;
|
||||
m_sCollisionManager.m_asCollisions2[i].m_bSurface1 = SURFACE_DEFAULT;
|
||||
m_sCollisionManager.m_asCollisions2[i].m_bSurface2 = SURFACE_DEFAULT;
|
||||
m_sCollisionManager.m_asCollisions2[i].m_fIntensity2 = 0.0f;
|
||||
m_sCollisionManager.m_asCollisions2[i].m_fIntensity1 = 0.0f;
|
||||
m_sCollisionManager.m_asCollisions2[i].m_vecPosition = CVector(0.0f, 0.0f, 0.0f);
|
||||
m_sCollisionManager.m_asCollisions2[i].m_fDistance = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < m_sCollisionManager.m_bCollisionsInQueue; i++) {
|
||||
int index = m_sCollisionManager.m_bIndicesTable[i];
|
||||
if (!abRepeatedCollision1[index]) {
|
||||
for (j = 0; j < NUMAUDIOCOLLISIONS; j++) {
|
||||
if (!abRepeatedCollision2[j]) {
|
||||
m_sCollisionManager.m_asCollisions2[j].m_nBaseVolume = 1;
|
||||
m_sCollisionManager.m_asCollisions2[j].m_pEntity1 = m_sCollisionManager.m_asCollisions1[index].m_pEntity1;
|
||||
m_sCollisionManager.m_asCollisions2[j].m_pEntity2 = m_sCollisionManager.m_asCollisions1[index].m_pEntity2;
|
||||
m_sCollisionManager.m_asCollisions2[j].m_bSurface1 = m_sCollisionManager.m_asCollisions1[index].m_bSurface1;
|
||||
m_sCollisionManager.m_asCollisions2[j].m_bSurface2 = m_sCollisionManager.m_asCollisions1[index].m_bSurface2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
SetUpOneShotCollisionSound(m_sCollisionManager.m_asCollisions1[index]);
|
||||
SetUpLoopingCollisionSound(m_sCollisionManager.m_asCollisions1[index], j);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUMAUDIOCOLLISIONS; i++)
|
||||
m_sCollisionManager.m_bIndicesTable[i] = NUMAUDIOCOLLISIONS;
|
||||
m_sCollisionManager.m_bCollisionsInQueue = 0;
|
||||
}
|
||||
|
||||
void
|
||||
cAudioManager::ReportCollision(CEntity *entity1, CEntity *entity2, uint8 surface1, uint8 surface2, float collisionPower,
|
||||
float velocity)
|
||||
uint32
|
||||
cAudioManager::SetLoopingCollisionRequestedSfxFreqAndGetVol(const cAudioCollision &audioCollision)
|
||||
{
|
||||
float distSquared;
|
||||
CVector v1;
|
||||
CVector v2;
|
||||
uint8 surface1 = audioCollision.m_bSurface1;
|
||||
uint8 surface2 = audioCollision.m_bSurface2;
|
||||
int32 vol;
|
||||
float ratio;
|
||||
|
||||
if(!m_bIsInitialised || m_nCollisionEntity < 0 || m_nUserPause ||
|
||||
(velocity < 0.0016f && collisionPower < 0.01f))
|
||||
return;
|
||||
|
||||
if(entity1->IsBuilding()) {
|
||||
v1 = v2 = entity2->GetPosition();
|
||||
} else if(entity2->IsBuilding()) {
|
||||
v1 = v2 = entity1->GetPosition();
|
||||
if(surface1 == SURFACE_GRASS || surface2 == SURFACE_GRASS || surface1 == SURFACE_HEDGE ||
|
||||
surface2 == SURFACE_HEDGE) {
|
||||
ratio = GetCollisionRatio(audioCollision.m_fIntensity2, 0.0001f, 0.09f, 0.0899f);
|
||||
m_sQueueSample.m_nSampleIndex = SFX_RAIN;
|
||||
m_sQueueSample.m_nFrequency = 13000.f * ratio + 35000;
|
||||
vol = 50.f * ratio;
|
||||
} else if(surface1 == SURFACE_WATER || surface2 == SURFACE_WATER) {
|
||||
ratio = GetCollisionRatio(audioCollision.m_fIntensity2, 0.0001f, 0.09f, 0.0899f);
|
||||
m_sQueueSample.m_nSampleIndex = SFX_BOAT_WATER_LOOP;
|
||||
m_sQueueSample.m_nFrequency = 6050.f * ratio + 16000;
|
||||
vol = 30.f * ratio;
|
||||
} else if(surface1 == SURFACE_GRAVEL || surface2 == SURFACE_GRAVEL || surface1 == SURFACE_MUD_DRY || surface2 == SURFACE_MUD_DRY ||
|
||||
surface1 == SURFACE_SAND || surface2 == SURFACE_SAND || surface1 == SURFACE_SAND_BEACH || surface2 == SURFACE_SAND_BEACH) {
|
||||
ratio = GetCollisionRatio(audioCollision.m_fIntensity2, 0.0001f, 0.09f, 0.0899f);
|
||||
m_sQueueSample.m_nSampleIndex = SFX_GRAVEL_SKID;
|
||||
m_sQueueSample.m_nFrequency = 6000.f * ratio + 10000;
|
||||
vol = 50.f * ratio;
|
||||
} else if(surface1 == SURFACE_PED || surface2 == SURFACE_PED) {
|
||||
return 0;
|
||||
} else {
|
||||
v1 = entity1->GetPosition();
|
||||
v2 = entity2->GetPosition();
|
||||
}
|
||||
CVector pos = (v1 + v2) * 0.5f;
|
||||
distSquared = GetDistanceSquared(pos);
|
||||
if(distSquared < SQR(CollisionSoundIntensity)) {
|
||||
m_sCollisionManager.m_sQueue.m_pEntity1 = entity1;
|
||||
m_sCollisionManager.m_sQueue.m_pEntity2 = entity2;
|
||||
m_sCollisionManager.m_sQueue.m_bSurface1 = surface1;
|
||||
m_sCollisionManager.m_sQueue.m_bSurface2 = surface2;
|
||||
m_sCollisionManager.m_sQueue.m_fIntensity1 = collisionPower;
|
||||
m_sCollisionManager.m_sQueue.m_fIntensity2 = velocity;
|
||||
m_sCollisionManager.m_sQueue.m_vecPosition = pos;
|
||||
m_sCollisionManager.m_sQueue.m_fDistance = distSquared;
|
||||
m_sCollisionManager.AddCollisionToRequestedQueue();
|
||||
ratio = GetCollisionRatio(audioCollision.m_fIntensity2, 0.0001f, 0.09f, 0.0899f);
|
||||
m_sQueueSample.m_nSampleIndex = SFX_SCRAPE_CAR_1;
|
||||
m_sQueueSample.m_nFrequency = 10000.f * ratio + 10000;
|
||||
vol = 40.f * ratio;
|
||||
}
|
||||
if(audioCollision.m_nBaseVolume < 2) vol = audioCollision.m_nBaseVolume * vol / 2;
|
||||
return vol;
|
||||
}
|
||||
|
||||
float
|
||||
cAudioManager::GetCollisionOneShotRatio(uint32 a, float b)
|
||||
{
|
||||
switch(a) {
|
||||
case SURFACE_DEFAULT:
|
||||
case SURFACE_TARMAC:
|
||||
case SURFACE_PAVEMENT:
|
||||
case SURFACE_STEEP_CLIFF:
|
||||
case SURFACE_TRANSPARENT_STONE:
|
||||
case SURFACE_CONCRETE_BEACH: return GetCollisionRatio(b, 10.f, 60.f, 50.f);
|
||||
case SURFACE_GRASS:
|
||||
case SURFACE_GRAVEL:
|
||||
case SURFACE_MUD_DRY:
|
||||
case SURFACE_CARDBOARDBOX: return GetCollisionRatio(b, 0.f, 2.f, 2.f);
|
||||
case SURFACE_CAR: return GetCollisionRatio(b, 6.f, 50.f, 44.f);
|
||||
case SURFACE_GLASS:
|
||||
case SURFACE_METAL_CHAIN_FENCE: return GetCollisionRatio(b, 0.1f, 10.f, 9.9f);
|
||||
case SURFACE_TRANSPARENT_CLOTH:
|
||||
case SURFACE_THICK_METAL_PLATE: return GetCollisionRatio(b, 30.f, 130.f, 100.f);
|
||||
case SURFACE_GARAGE_DOOR: return GetCollisionRatio(b, 20.f, 100.f, 80.f);
|
||||
case SURFACE_CAR_PANEL: return GetCollisionRatio(b, 0.f, 4.f, 4.f);
|
||||
case SURFACE_SCAFFOLD_POLE:
|
||||
case SURFACE_METAL_GATE:
|
||||
case SURFACE_LAMP_POST: return GetCollisionRatio(b, 1.f, 10.f, 9.f);
|
||||
case SURFACE_FIRE_HYDRANT: return GetCollisionRatio(b, 1.f, 15.f, 14.f);
|
||||
case SURFACE_GIRDER: return GetCollisionRatio(b, 8.f, 50.f, 42.f);
|
||||
case SURFACE_PED: return GetCollisionRatio(b, 0.f, 20.f, 20.f);
|
||||
case SURFACE_SAND:
|
||||
case SURFACE_WATER:
|
||||
case SURFACE_RUBBER:
|
||||
case SURFACE_WHEELBASE:
|
||||
case SURFACE_SAND_BEACH: return GetCollisionRatio(b, 0.f, 10.f, 10.f);
|
||||
case SURFACE_WOOD_CRATES: return GetCollisionRatio(b, 1.f, 4.f, 3.f);
|
||||
case SURFACE_WOOD_BENCH: return GetCollisionRatio(b, 0.1f, 5.f, 4.9f);
|
||||
case SURFACE_WOOD_SOLID: return GetCollisionRatio(b, 0.1f, 40.f, 39.9f);
|
||||
case SURFACE_PLASTIC: return GetCollisionRatio(b, 0.1f, 4.f, 3.9f);
|
||||
case SURFACE_HEDGE: return GetCollisionRatio(b, 0.f, 0.5f, 0.5f);
|
||||
case SURFACE_CONTAINER: return GetCollisionRatio(b, 4.f, 40.f, 36.f);
|
||||
case SURFACE_NEWS_VENDOR: return GetCollisionRatio(b, 0.f, 5.f, 5.f);
|
||||
default: break;
|
||||
}
|
||||
|
||||
return 0.f;
|
||||
}
|
||||
|
||||
float
|
||||
cAudioManager::GetCollisionLoopingRatio(uint32 a, uint32 b, float c)
|
||||
{
|
||||
return GetCollisionRatio(c, 0.0f, 0.02f, 0.02f);
|
||||
}
|
||||
|
||||
float
|
||||
cAudioManager::GetCollisionRatio(float a, float b, float c, float d)
|
||||
{
|
||||
float e;
|
||||
e = a;
|
||||
if(a <= b) return 0.0f;
|
||||
if(c <= a) e = c;
|
||||
return (e - b) / d;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#define NUMAUDIOCOLLISIONS 10
|
||||
#define NUMAUDIOCOLLISIONS 14
|
||||
|
||||
class CEntity;
|
||||
|
||||
@@ -17,7 +17,18 @@ public:
|
||||
float m_fDistance;
|
||||
int32 m_nBaseVolume;
|
||||
|
||||
// no methods
|
||||
cAudioCollision() { Reset(); }
|
||||
|
||||
void Reset()
|
||||
{
|
||||
m_pEntity1 = nil;
|
||||
m_pEntity2 = nil;
|
||||
m_bSurface1 = 0;
|
||||
m_bSurface2 = 0;
|
||||
m_fIntensity1 = m_fIntensity2 = 0.0f;
|
||||
m_vecPosition = CVector(0.0f, 0.0f, 0.0f);
|
||||
m_fDistance = 0.0f;
|
||||
}
|
||||
};
|
||||
|
||||
VALIDATE_SIZE(cAudioCollision, 40);
|
||||
@@ -31,7 +42,15 @@ public:
|
||||
uint8 m_bCollisionsInQueue;
|
||||
cAudioCollision m_sQueue;
|
||||
|
||||
cAudioCollisionManager();
|
||||
cAudioCollisionManager()
|
||||
{
|
||||
m_sQueue.Reset();
|
||||
|
||||
for(int i = 0; i < NUMAUDIOCOLLISIONS; i++)
|
||||
m_bIndicesTable[i] = NUMAUDIOCOLLISIONS;
|
||||
|
||||
m_bCollisionsInQueue = 0;
|
||||
}
|
||||
void AddCollisionToRequestedQueue();
|
||||
};
|
||||
|
||||
|
||||
15871
src/audio/AudioLogic.cpp
15871
src/audio/AudioLogic.cpp
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -3,6 +3,7 @@
|
||||
#include "AudioScriptObject.h"
|
||||
#include "Pools.h"
|
||||
#include "DMAudio.h"
|
||||
#include "SaveBuf.h"
|
||||
|
||||
cAudioScriptObject::cAudioScriptObject()
|
||||
{
|
||||
@@ -23,25 +24,25 @@ cAudioScriptObject::Reset()
|
||||
}
|
||||
|
||||
void *
|
||||
cAudioScriptObject::operator new(size_t sz)
|
||||
cAudioScriptObject::operator new(size_t sz) throw()
|
||||
{
|
||||
return CPools::GetAudioScriptObjectPool()->New();
|
||||
}
|
||||
|
||||
void *
|
||||
cAudioScriptObject::operator new(size_t sz, int handle)
|
||||
cAudioScriptObject::operator new(size_t sz, int handle) throw()
|
||||
{
|
||||
return CPools::GetAudioScriptObjectPool()->New(handle);
|
||||
}
|
||||
|
||||
void
|
||||
cAudioScriptObject::operator delete(void *p, size_t sz)
|
||||
cAudioScriptObject::operator delete(void *p, size_t sz) throw()
|
||||
{
|
||||
CPools::GetAudioScriptObjectPool()->Delete((cAudioScriptObject *)p);
|
||||
}
|
||||
|
||||
void
|
||||
cAudioScriptObject::operator delete(void *p, int handle)
|
||||
cAudioScriptObject::operator delete(void *p, int handle) throw()
|
||||
{
|
||||
CPools::GetAudioScriptObjectPool()->Delete((cAudioScriptObject *)p);
|
||||
}
|
||||
@@ -53,12 +54,14 @@ cAudioScriptObject::LoadAllAudioScriptObjects(uint8 *buf, uint32 size)
|
||||
|
||||
CheckSaveHeader(buf, 'A', 'U', 'D', '\0', size - SAVE_HEADER_SIZE);
|
||||
|
||||
int32 pool_size = ReadSaveBuf<int32>(buf);
|
||||
int32 pool_size;
|
||||
ReadSaveBuf(&pool_size, buf);
|
||||
for (int32 i = 0; i < pool_size; i++) {
|
||||
int handle = ReadSaveBuf<int32>(buf);
|
||||
int32 handle;
|
||||
ReadSaveBuf(&handle, buf);
|
||||
cAudioScriptObject *p = new(handle) cAudioScriptObject;
|
||||
assert(p != nil);
|
||||
*p = ReadSaveBuf<cAudioScriptObject>(buf);
|
||||
ReadSaveBuf(p, buf);
|
||||
p->AudioEntity = DMAudio.CreateLoopingScriptObject(p);
|
||||
}
|
||||
|
||||
@@ -90,6 +93,8 @@ cAudioScriptObject::SaveAllAudioScriptObjects(uint8 *buf, uint32 *size)
|
||||
void
|
||||
PlayOneShotScriptObject(uint8 id, CVector const &pos)
|
||||
{
|
||||
if (!DMAudio.IsAudioInitialised()) return;
|
||||
|
||||
cAudioScriptObject *audioScriptObject = new cAudioScriptObject();
|
||||
audioScriptObject->Posn = pos;
|
||||
audioScriptObject->AudioId = id;
|
||||
|
||||
@@ -12,10 +12,10 @@ public:
|
||||
|
||||
void Reset(); /// ok
|
||||
|
||||
static void* operator new(size_t);
|
||||
static void* operator new(size_t, int);
|
||||
static void operator delete(void*, size_t);
|
||||
static void operator delete(void*, int);
|
||||
static void* operator new(size_t) throw();
|
||||
static void* operator new(size_t, int) throw();
|
||||
static void operator delete(void*, size_t) throw();
|
||||
static void operator delete(void*, int) throw();
|
||||
|
||||
static void LoadAllAudioScriptObjects(uint8 *buf, uint32 size);
|
||||
static void SaveAllAudioScriptObjects(uint8 *buf, uint32 *size);
|
||||
|
||||
@@ -38,8 +38,14 @@ cDMAudio::DestroyEntity(int32 audioEntity)
|
||||
AudioManager.DestroyEntity(audioEntity);
|
||||
}
|
||||
|
||||
bool8
|
||||
cDMAudio::GetEntityStatus(int32 audioEntity)
|
||||
{
|
||||
return AudioManager.GetEntityStatus(audioEntity);
|
||||
}
|
||||
|
||||
void
|
||||
cDMAudio::SetEntityStatus(int32 audioEntity, uint8 status)
|
||||
cDMAudio::SetEntityStatus(int32 audioEntity, bool8 status)
|
||||
{
|
||||
AudioManager.SetEntityStatus(audioEntity, status);
|
||||
}
|
||||
@@ -57,9 +63,9 @@ cDMAudio::DestroyAllGameCreatedEntities(void)
|
||||
}
|
||||
|
||||
void
|
||||
cDMAudio::SetMonoMode(uint8 mono)
|
||||
cDMAudio::SetOutputMode(bool8 surround)
|
||||
{
|
||||
AudioManager.SetMonoMode(mono);
|
||||
AudioManager.SetOutputMode(surround);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -142,7 +148,7 @@ cDMAudio::SetSpeakerConfig(int32 config)
|
||||
AudioManager.SetSpeakerConfig(config);
|
||||
}
|
||||
|
||||
bool
|
||||
bool8
|
||||
cDMAudio::IsMP3RadioChannelAvailable(void)
|
||||
{
|
||||
return AudioManager.IsMP3RadioChannelAvailable();
|
||||
@@ -161,12 +167,14 @@ cDMAudio::ReacquireDigitalHandle(void)
|
||||
}
|
||||
|
||||
void
|
||||
cDMAudio::SetDynamicAcousticModelingStatus(uint8 status)
|
||||
cDMAudio::SetDynamicAcousticModelingStatus(bool8 status)
|
||||
{
|
||||
#ifdef AUDIO_REFLECTIONS
|
||||
AudioManager.SetDynamicAcousticModelingStatus(status);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
bool8
|
||||
cDMAudio::CheckForAnAudioFileOnCD(void)
|
||||
{
|
||||
return AudioManager.CheckForAnAudioFileOnCD();
|
||||
@@ -178,12 +186,18 @@ cDMAudio::GetCDAudioDriveLetter(void)
|
||||
return AudioManager.GetCDAudioDriveLetter();
|
||||
}
|
||||
|
||||
bool
|
||||
bool8
|
||||
cDMAudio::IsAudioInitialised(void)
|
||||
{
|
||||
return AudioManager.IsAudioInitialised();
|
||||
}
|
||||
|
||||
void
|
||||
cDMAudio::ResetPoliceRadio()
|
||||
{
|
||||
AudioManager.ResetPoliceRadio();
|
||||
}
|
||||
|
||||
void
|
||||
cDMAudio::ReportCrime(eCrimeType crime, const CVector &pos)
|
||||
{
|
||||
@@ -196,7 +210,7 @@ cDMAudio::CreateLoopingScriptObject(cAudioScriptObject *scriptObject)
|
||||
int32 audioEntity = AudioManager.CreateEntity(AUDIOTYPE_SCRIPTOBJECT, scriptObject);
|
||||
|
||||
if ( AEHANDLE_IS_OK(audioEntity) )
|
||||
AudioManager.SetEntityStatus(audioEntity, true);
|
||||
AudioManager.SetEntityStatus(audioEntity, TRUE);
|
||||
|
||||
return audioEntity;
|
||||
}
|
||||
@@ -214,7 +228,7 @@ cDMAudio::CreateOneShotScriptObject(cAudioScriptObject *scriptObject)
|
||||
|
||||
if ( AEHANDLE_IS_OK(audioEntity) )
|
||||
{
|
||||
AudioManager.SetEntityStatus(audioEntity, true);
|
||||
AudioManager.SetEntityStatus(audioEntity, TRUE);
|
||||
AudioManager.PlayOneShot(audioEntity, scriptObject->AudioId, 0.0f);
|
||||
}
|
||||
}
|
||||
@@ -244,7 +258,7 @@ cDMAudio::PlayRadioAnnouncement(uint32 announcement)
|
||||
}
|
||||
|
||||
void
|
||||
cDMAudio::PlayFrontEndTrack(uint32 track, uint8 frontendFlag)
|
||||
cDMAudio::PlayFrontEndTrack(uint32 track, bool8 frontendFlag)
|
||||
{
|
||||
MusicManager.PlayFrontEndTrack(track, frontendFlag);
|
||||
}
|
||||
@@ -309,7 +323,13 @@ cDMAudio::PlayLoadedMissionAudio(uint8 slot)
|
||||
AudioManager.PlayLoadedMissionAudio(slot);
|
||||
}
|
||||
|
||||
bool
|
||||
bool8
|
||||
cDMAudio::IsMissionAudioSamplePlaying(uint8 slot)
|
||||
{
|
||||
return AudioManager.IsMissionAudioSamplePlaying(slot);
|
||||
}
|
||||
|
||||
bool8
|
||||
cDMAudio::IsMissionAudioSampleFinished(uint8 slot)
|
||||
{
|
||||
return AudioManager.IsMissionAudioSampleFinished(slot);
|
||||
@@ -321,6 +341,12 @@ cDMAudio::ClearMissionAudio(uint8 slot)
|
||||
AudioManager.ClearMissionAudio(slot);
|
||||
}
|
||||
|
||||
const char *
|
||||
cDMAudio::GetMissionAudioLoadedLabel(uint8 slot)
|
||||
{
|
||||
return AudioManager.GetMissionAudioLoadedLabel(slot);
|
||||
}
|
||||
|
||||
uint8
|
||||
cDMAudio::GetRadioInCar(void)
|
||||
{
|
||||
@@ -340,7 +366,7 @@ cDMAudio::SetRadioChannel(uint32 radio, int32 pos)
|
||||
}
|
||||
|
||||
void
|
||||
cDMAudio::SetStartingTrackPositions(uint8 isStartGame)
|
||||
cDMAudio::SetStartingTrackPositions(bool8 isStartGame)
|
||||
{
|
||||
MusicManager.SetStartingTrackPositions(isStartGame);
|
||||
}
|
||||
@@ -364,7 +390,7 @@ cDMAudio::GetRadioPosition(uint32 station)
|
||||
}
|
||||
|
||||
void
|
||||
cDMAudio::SetPedTalkingStatus(CPed *ped, uint8 status)
|
||||
cDMAudio::SetPedTalkingStatus(CPed *ped, bool8 status)
|
||||
{
|
||||
return AudioManager.SetPedTalkingStatus(ped, status);
|
||||
}
|
||||
@@ -376,7 +402,7 @@ cDMAudio::SetPlayersMood(uint8 mood, uint32 time)
|
||||
}
|
||||
|
||||
void
|
||||
cDMAudio::ShutUpPlayerTalking(uint8 state)
|
||||
cDMAudio::ShutUpPlayerTalking(bool8 state)
|
||||
{
|
||||
AudioManager.m_bIsPlayerShutUp = state;
|
||||
}
|
||||
@@ -25,11 +25,12 @@ public:
|
||||
|
||||
int32 CreateEntity(eAudioType type, void *UID);
|
||||
void DestroyEntity(int32 audioEntity);
|
||||
void SetEntityStatus(int32 audioEntity, uint8 status);
|
||||
bool8 GetEntityStatus(int32 audioEntity);
|
||||
void SetEntityStatus(int32 audioEntity, bool8 status);
|
||||
void PlayOneShot(int32 audioEntity, uint16 oneShot, float volume);
|
||||
void DestroyAllGameCreatedEntities(void);
|
||||
|
||||
void SetMonoMode(uint8 mono);
|
||||
void SetOutputMode(bool8 surround);
|
||||
void SetMP3BoostVolume(uint8 volume);
|
||||
void SetEffectsMasterVolume(uint8 volume);
|
||||
void SetMusicMasterVolume(uint8 volume);
|
||||
@@ -46,18 +47,19 @@ public:
|
||||
|
||||
void SetSpeakerConfig(int32 config);
|
||||
|
||||
bool IsMP3RadioChannelAvailable(void);
|
||||
bool8 IsMP3RadioChannelAvailable(void);
|
||||
|
||||
void ReleaseDigitalHandle(void);
|
||||
void ReacquireDigitalHandle(void);
|
||||
|
||||
void SetDynamicAcousticModelingStatus(uint8 status);
|
||||
void SetDynamicAcousticModelingStatus(bool8 status);
|
||||
|
||||
bool CheckForAnAudioFileOnCD(void);
|
||||
bool8 CheckForAnAudioFileOnCD(void);
|
||||
|
||||
char GetCDAudioDriveLetter(void);
|
||||
bool IsAudioInitialised(void);
|
||||
|
||||
bool8 IsAudioInitialised(void);
|
||||
|
||||
void ResetPoliceRadio();
|
||||
void ReportCrime(eCrimeType crime, CVector const &pos);
|
||||
|
||||
int32 CreateLoopingScriptObject(cAudioScriptObject *scriptObject);
|
||||
@@ -70,7 +72,7 @@ public:
|
||||
|
||||
void PlayFrontEndSound(uint16 frontend, uint32 volume);
|
||||
void PlayRadioAnnouncement(uint32 announcement);
|
||||
void PlayFrontEndTrack(uint32 track, uint8 frontendFlag);
|
||||
void PlayFrontEndTrack(uint32 track, bool8 frontendFlag);
|
||||
void StopFrontEndTrack(void);
|
||||
|
||||
void ResetTimers(uint32 time);
|
||||
@@ -85,19 +87,21 @@ public:
|
||||
uint8 GetMissionAudioLoadingStatus(uint8 slot);
|
||||
void SetMissionAudioLocation(uint8 slot, float x, float y, float z);
|
||||
void PlayLoadedMissionAudio(uint8 slot);
|
||||
bool IsMissionAudioSampleFinished(uint8 slot);
|
||||
bool8 IsMissionAudioSamplePlaying(uint8 slot);
|
||||
bool8 IsMissionAudioSampleFinished(uint8 slot);
|
||||
void ClearMissionAudio(uint8 slot);
|
||||
const char *GetMissionAudioLoadedLabel(uint8 slot);
|
||||
|
||||
uint8 GetRadioInCar(void);
|
||||
void SetRadioInCar(uint32 radio);
|
||||
void SetRadioChannel(uint32 radio, int32 pos);
|
||||
|
||||
void SetStartingTrackPositions(uint8 isStartGame);
|
||||
void SetStartingTrackPositions(bool8 isStartGame);
|
||||
float *GetListenTimeArray();
|
||||
uint32 GetFavouriteRadioStation();
|
||||
int32 GetRadioPosition(uint32 station);
|
||||
void SetPedTalkingStatus(class CPed *ped, uint8 status);
|
||||
void SetPedTalkingStatus(class CPed *ped, bool8 status);
|
||||
void SetPlayersMood(uint8 mood, uint32 time);
|
||||
void ShutUpPlayerTalking(uint8 state);
|
||||
void ShutUpPlayerTalking(bool8 state);
|
||||
};
|
||||
extern cDMAudio DMAudio;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -16,18 +16,18 @@ class CPed;
|
||||
class cMusicManager
|
||||
{
|
||||
public:
|
||||
bool m_bIsInitialised;
|
||||
bool m_bDisabled;
|
||||
bool m_bSetNextStation;
|
||||
bool8 m_bIsInitialised;
|
||||
bool8 m_bDisabled;
|
||||
bool8 m_bSetNextStation;
|
||||
uint8 m_nVolumeLatency;
|
||||
uint8 m_nCurrentVolume;
|
||||
uint8 m_nMaxVolume;
|
||||
uint32 m_nAnnouncement;
|
||||
bool m_bAnnouncementInProgress;
|
||||
bool8 m_bAnnouncementInProgress;
|
||||
tStreamedSample m_aTracks[TOTAL_STREAMED_SOUNDS];
|
||||
bool m_bResetTimers;
|
||||
bool8 m_bResetTimers;
|
||||
uint32 m_nResetTime;
|
||||
bool m_bRadioSetByScript;
|
||||
bool8 m_bRadioSetByScript;
|
||||
uint8 m_nRadioStationScript;
|
||||
int32 m_nRadioPosition;
|
||||
uint32 m_nRadioInCar;
|
||||
@@ -35,40 +35,40 @@ public:
|
||||
uint32 m_nPlayingTrack;
|
||||
uint8 m_nUpcomingMusicMode;
|
||||
uint8 m_nMusicMode;
|
||||
bool m_FrontendLoopFlag;
|
||||
bool m_bTrackChangeStarted;
|
||||
bool8 m_FrontendLoopFlag;
|
||||
bool8 m_bTrackChangeStarted;
|
||||
uint32 m_nNextTrack;
|
||||
bool m_nNextLoopFlag;
|
||||
bool m_bVerifyNextTrackStartedToPlay;
|
||||
bool m_bGameplayAllowsRadio;
|
||||
bool m_bRadioStreamReady;
|
||||
bool8 m_nNextLoopFlag;
|
||||
bool8 m_bVerifyNextTrackStartedToPlay;
|
||||
bool8 m_bGameplayAllowsRadio;
|
||||
bool8 m_bRadioStreamReady;
|
||||
int8 nFramesSinceCutsceneEnded;
|
||||
bool m_bUserResumedGame;
|
||||
bool m_bMusicModeChangeStarted;
|
||||
bool8 m_bUserResumedGame;
|
||||
bool8 m_bMusicModeChangeStarted;
|
||||
uint8 m_nMusicModeToBeSet;
|
||||
bool m_bEarlyFrontendTrack;
|
||||
bool8 m_bEarlyFrontendTrack;
|
||||
float aListenTimeArray[NUM_RADIOS];
|
||||
float m_nLastTrackServiceTime;
|
||||
|
||||
public:
|
||||
cMusicManager();
|
||||
bool IsInitialised() { return m_bIsInitialised; }
|
||||
bool8 IsInitialised() { return m_bIsInitialised; }
|
||||
uint8 GetMusicMode() { return m_nMusicMode; }
|
||||
uint32 GetCurrentTrack() { return m_nPlayingTrack; }
|
||||
|
||||
void ResetMusicAfterReload();
|
||||
void SetStartingTrackPositions(uint8 isNewGameTimer);
|
||||
bool Initialise();
|
||||
void SetStartingTrackPositions(bool8 isNewGameTimer);
|
||||
bool8 Initialise();
|
||||
void Terminate();
|
||||
|
||||
void ChangeMusicMode(uint8 mode);
|
||||
void StopFrontEndTrack();
|
||||
|
||||
bool PlayerInCar();
|
||||
bool8 PlayerInCar();
|
||||
void DisplayRadioStationName();
|
||||
|
||||
void PlayAnnouncement(uint32);
|
||||
void PlayFrontEndTrack(uint32, uint8);
|
||||
void PlayFrontEndTrack(uint32, bool8);
|
||||
void PreloadCutSceneMusic(uint32);
|
||||
void PlayPreloadedCutSceneMusic(void);
|
||||
void StopCutSceneMusic(void);
|
||||
@@ -76,23 +76,23 @@ public:
|
||||
void SetRadioInCar(uint32);
|
||||
void SetRadioChannelByScript(uint32, int32);
|
||||
|
||||
void ResetTimers(int32);
|
||||
void ResetTimers(uint32);
|
||||
void Service();
|
||||
void ServiceFrontEndMode();
|
||||
void ServiceGameMode();
|
||||
void ServiceAmbience();
|
||||
void ServiceTrack(CVehicle *veh, CPed *ped);
|
||||
|
||||
bool UsesPoliceRadio(CVehicle *veh);
|
||||
bool UsesTaxiRadio(CVehicle *veh);
|
||||
bool8 UsesPoliceRadio(CVehicle *veh);
|
||||
bool8 UsesTaxiRadio(CVehicle *veh);
|
||||
uint32 GetTrackStartPos(uint32 track);
|
||||
|
||||
void ComputeAmbienceVol(uint8 reset, uint8& outVolume);
|
||||
bool ServiceAnnouncement();
|
||||
void ComputeAmbienceVol(bool8 reset, uint8& outVolume);
|
||||
bool8 ServiceAnnouncement();
|
||||
|
||||
uint32 GetCarTuning();
|
||||
uint32 GetNextCarTuning();
|
||||
bool ChangeRadioChannel();
|
||||
bool8 ChangeRadioChannel();
|
||||
void RecordRadioStats();
|
||||
void SetUpCorrectAmbienceTrack();
|
||||
float *GetListenTimeArray();
|
||||
@@ -100,7 +100,7 @@ public:
|
||||
uint32 GetFavouriteRadioStation();
|
||||
void SetMalibuClubTrackPos(uint8 pos);
|
||||
void SetStripClubTrackPos(uint8 pos);
|
||||
bool CheckForMusicInterruptions();
|
||||
bool8 CheckForMusicInterruptions();
|
||||
|
||||
void Enable();
|
||||
void Disable();
|
||||
@@ -109,5 +109,5 @@ public:
|
||||
VALIDATE_SIZE(cMusicManager, 0x95C);
|
||||
|
||||
extern cMusicManager MusicManager;
|
||||
extern bool g_bAnnouncementReadPosAlready; // we have a symbol of this so it was declared in .h
|
||||
extern bool8 g_bAnnouncementReadPosAlready; // we have a symbol of this so it was declared in .h
|
||||
float GetHeightScale();
|
||||
|
||||
751
src/audio/PolRadio.cpp
Normal file
751
src/audio/PolRadio.cpp
Normal file
@@ -0,0 +1,751 @@
|
||||
#include "common.h"
|
||||
|
||||
#include "DMAudio.h"
|
||||
|
||||
#include "AudioManager.h"
|
||||
|
||||
#include "AudioSamples.h"
|
||||
#include "MusicManager.h"
|
||||
#include "PlayerPed.h"
|
||||
#include "PolRadio.h"
|
||||
#include "Replay.h"
|
||||
#include "Vehicle.h"
|
||||
#include "World.h"
|
||||
#include "Zones.h"
|
||||
#include "sampman.h"
|
||||
#include "Wanted.h"
|
||||
|
||||
struct tPoliceRadioZone {
|
||||
char m_aName[8];
|
||||
uint32 m_nSampleIndex;
|
||||
int32 field_12;
|
||||
};
|
||||
|
||||
tPoliceRadioZone ZoneSfx[NUMAUDIOZONES];
|
||||
|
||||
uint32 g_nMissionAudioSfx = TOTAL_AUDIO_SAMPLES;
|
||||
int8 g_nMissionAudioPlayingStatus = PLAY_STATUS_FINISHED;
|
||||
bool8 gSpecialSuspectLastSeenReport;
|
||||
uint32 gMinTimeToNextReport[NUM_CRIME_TYPES];
|
||||
|
||||
void
|
||||
cAudioManager::InitialisePoliceRadioZones()
|
||||
{
|
||||
for (int32 i = 0; i < NUMAUDIOZONES; i++)
|
||||
memset(ZoneSfx[i].m_aName, 0, 8);
|
||||
|
||||
#define SETZONESFX(i, name, sample) \
|
||||
strcpy(ZoneSfx[i].m_aName, name); \
|
||||
ZoneSfx[i].m_nSampleIndex = sample;
|
||||
|
||||
SETZONESFX(0, "VICE_C", SFX_SFX_POLICE_RADIO_VICE_CITY);
|
||||
SETZONESFX(1, "IND_ZON", SFX_SFX_POLICE_RADIO_VICE_CITY_BEACH);
|
||||
SETZONESFX(2, "COM_ZON", SFX_SFX_POLICE_RADIO_VICE_CITY_MAINLAND);
|
||||
SETZONESFX(3, "BEACH1", SFX_SFX_POLICE_RADIO_OCEAN_BEACH);
|
||||
SETZONESFX(4, "BEACH2", SFX_SFX_POLICE_RADIO_WASHINGTON_BEACH);
|
||||
SETZONESFX(5, "BEACH3", SFX_SFX_POLICE_RADIO_VICE_POINT);
|
||||
SETZONESFX(6, "GOLFC", SFX_SFX_POLICE_RADIO_LEAF_LINKS);
|
||||
SETZONESFX(7, "STARI", SFX_SFX_POLICE_RADIO_STARFISH_ISLAND);
|
||||
SETZONESFX(8, "DOCKS", SFX_SFX_POLICE_RADIO_VICEPORT);
|
||||
SETZONESFX(9, "HAVANA", SFX_SFX_POLICE_RADIO_LITTLE_HAVANA);
|
||||
SETZONESFX(10, "HAITI", SFX_SFX_POLICE_RADIO_LITTLE_HAITI);
|
||||
SETZONESFX(11, "PORNI", SFX_SFX_POLICE_RADIO_PRAWN_ISLAND);
|
||||
SETZONESFX(12, "DTOWN", SFX_SFX_POLICE_RADIO_DOWNTOWN);
|
||||
SETZONESFX(13, "A_PORT", SFX_SFX_POLICE_RADIO_ESCOBAR_INTERNATIONAL);
|
||||
|
||||
#undef SETZONESFX
|
||||
}
|
||||
|
||||
void
|
||||
cAudioManager::InitialisePoliceRadio()
|
||||
{
|
||||
m_sPoliceRadioQueue.Reset();
|
||||
for (int32 i = 0; i < ARRAY_SIZE(m_aCrimes); i++)
|
||||
m_aCrimes[i].type = CRIME_NONE;
|
||||
#if !defined(GTA_PS2) || defined(AUDIO_REVERB)
|
||||
SampleManager.SetChannelReverbFlag(CHANNEL_POLICE_RADIO, FALSE);
|
||||
#endif
|
||||
gSpecialSuspectLastSeenReport = FALSE;
|
||||
for (int32 i = 0; i < ARRAY_SIZE(gMinTimeToNextReport); i++)
|
||||
gMinTimeToNextReport[i] = m_FrameCounter;
|
||||
}
|
||||
|
||||
void
|
||||
cAudioManager::ResetPoliceRadio()
|
||||
{
|
||||
if (!m_bIsInitialised) return;
|
||||
if (SampleManager.GetChannelUsedFlag(CHANNEL_POLICE_RADIO)) SampleManager.StopChannel(CHANNEL_POLICE_RADIO);
|
||||
InitialisePoliceRadio();
|
||||
}
|
||||
|
||||
void
|
||||
cAudioManager::SetMissionScriptPoliceAudio(uint32 sfx)
|
||||
{
|
||||
if (!m_bIsInitialised) return;
|
||||
if (g_nMissionAudioPlayingStatus != PLAY_STATUS_PLAYING) {
|
||||
g_nMissionAudioPlayingStatus = PLAY_STATUS_STOPPED;
|
||||
g_nMissionAudioSfx = sfx;
|
||||
}
|
||||
}
|
||||
|
||||
int8
|
||||
cAudioManager::GetMissionScriptPoliceAudioPlayingStatus()
|
||||
{
|
||||
return g_nMissionAudioPlayingStatus;
|
||||
}
|
||||
|
||||
void
|
||||
cAudioManager::DoPoliceRadioCrackle()
|
||||
{
|
||||
m_sQueueSample.m_nEntityIndex = m_nPoliceChannelEntity;
|
||||
m_sQueueSample.m_nCounter = 0;
|
||||
m_sQueueSample.m_nSampleIndex = SFX_POLICE_RADIO_CRACKLE;
|
||||
m_sQueueSample.m_nBankIndex = SFX_BANK_0;
|
||||
m_sQueueSample.m_bIs2D = TRUE;
|
||||
m_sQueueSample.m_nPriority = 10;
|
||||
m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_POLICE_RADIO_CRACKLE);
|
||||
m_sQueueSample.m_nVolume = m_anRandomTable[2] % 20 + 15;
|
||||
m_sQueueSample.m_nLoopCount = 0;
|
||||
SET_EMITTING_VOLUME(m_sQueueSample.m_nVolume);
|
||||
SET_LOOP_OFFSETS(SFX_POLICE_RADIO_CRACKLE)
|
||||
m_sQueueSample.m_bStatic = FALSE;
|
||||
SET_SOUND_REVERB(FALSE);
|
||||
m_sQueueSample.m_nPan = 63;
|
||||
m_sQueueSample.m_nFramesToPlay = 3;
|
||||
SET_SOUND_REFLECTION(FALSE);
|
||||
AddSampleToRequestedQueue();
|
||||
}
|
||||
|
||||
void
|
||||
cAudioManager::ServicePoliceRadio()
|
||||
{
|
||||
/*
|
||||
int32 wantedLevel = 0; // uninitialized variable
|
||||
static uint32 nLastSeen = 300;
|
||||
|
||||
if(!m_bIsInitialised) return;
|
||||
|
||||
if(!m_bIsPaused) {
|
||||
bool8 crimeReport = SetupCrimeReport();
|
||||
#ifdef FIX_BUGS // Crash at 0x5fe6ef
|
||||
if(CReplay::IsPlayingBack() || !FindPlayerPed() || !FindPlayerPed()->m_pWanted)
|
||||
return;
|
||||
#endif
|
||||
CPlayerPed *playerPed = FindPlayerPed();
|
||||
if (playerPed) {
|
||||
wantedLevel = playerPed->m_pWanted->GetWantedLevel();
|
||||
if (!crimeReport) {
|
||||
if (wantedLevel != 0) {
|
||||
if (nLastSeen != 0)
|
||||
#ifdef FIX_BUGS
|
||||
nLastSeen -= CTimer::GetLogicalFramesPassed();
|
||||
#else
|
||||
nLastSeen--;
|
||||
#endif
|
||||
else {
|
||||
nLastSeen = m_anRandomTable[1] % 1000 + 2000;
|
||||
SetupSuspectLastSeenReport();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ServicePoliceRadioChannel(wantedLevel);
|
||||
*/
|
||||
}
|
||||
|
||||
void
|
||||
cAudioManager::ServicePoliceRadioChannel(uint8 wantedLevel)
|
||||
{
|
||||
bool8 processed = FALSE;
|
||||
uint32 sample;
|
||||
uint32 freq;
|
||||
|
||||
static int cWait = 0;
|
||||
static bool8 bChannelOpen = FALSE;
|
||||
static uint8 bMissionAudioPhysicalPlayingStatus = PLAY_STATUS_STOPPED;
|
||||
static uint32 PoliceChannelFreq = 22050;
|
||||
|
||||
if (!m_bIsInitialised) return;
|
||||
|
||||
if (m_bIsPaused) {
|
||||
if (SampleManager.GetChannelUsedFlag(CHANNEL_POLICE_RADIO)) SampleManager.StopChannel(CHANNEL_POLICE_RADIO);
|
||||
if (g_nMissionAudioSfx != NO_SAMPLE && bMissionAudioPhysicalPlayingStatus == PLAY_STATUS_PLAYING &&
|
||||
SampleManager.IsStreamPlaying(1)) {
|
||||
SampleManager.PauseStream(TRUE, 1);
|
||||
}
|
||||
} else {
|
||||
if (m_bWasPaused && g_nMissionAudioSfx != NO_SAMPLE &&
|
||||
bMissionAudioPhysicalPlayingStatus == PLAY_STATUS_PLAYING) {
|
||||
SampleManager.PauseStream(FALSE, 1);
|
||||
}
|
||||
if (m_sPoliceRadioQueue.m_nSamplesInQueue == 0) bChannelOpen = FALSE;
|
||||
if (cWait) {
|
||||
#ifdef FIX_BUGS
|
||||
cWait -= CTimer::GetLogicalFramesPassed();
|
||||
#else
|
||||
--cWait;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
if (g_nMissionAudioSfx != NO_SAMPLE && !bChannelOpen) {
|
||||
if (g_nMissionAudioPlayingStatus != PLAY_STATUS_STOPPED) {
|
||||
if (g_nMissionAudioPlayingStatus == PLAY_STATUS_PLAYING && bMissionAudioPhysicalPlayingStatus == PLAY_STATUS_STOPPED &&
|
||||
SampleManager.IsStreamPlaying(1)) {
|
||||
bMissionAudioPhysicalPlayingStatus = PLAY_STATUS_PLAYING;
|
||||
}
|
||||
if (bMissionAudioPhysicalPlayingStatus == PLAY_STATUS_PLAYING) {
|
||||
if (SampleManager.IsStreamPlaying(1)) {
|
||||
DoPoliceRadioCrackle();
|
||||
} else {
|
||||
bMissionAudioPhysicalPlayingStatus = PLAY_STATUS_FINISHED;
|
||||
g_nMissionAudioPlayingStatus = PLAY_STATUS_FINISHED;
|
||||
g_nMissionAudioSfx = NO_SAMPLE;
|
||||
cWait = 30;
|
||||
}
|
||||
return;
|
||||
}
|
||||
} else if (!SampleManager.GetChannelUsedFlag(CHANNEL_POLICE_RADIO)) {
|
||||
SampleManager.PreloadStreamedFile(g_nMissionAudioSfx, 1);
|
||||
SampleManager.SetStreamedVolumeAndPan(MAX_VOLUME, 63, TRUE, 1);
|
||||
SampleManager.StartPreloadedStreamedFile(1);
|
||||
g_nMissionAudioPlayingStatus = PLAY_STATUS_PLAYING;
|
||||
bMissionAudioPhysicalPlayingStatus = PLAY_STATUS_STOPPED;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (bChannelOpen) DoPoliceRadioCrackle();
|
||||
if ((g_nMissionAudioSfx == NO_SAMPLE || g_nMissionAudioPlayingStatus != PLAY_STATUS_PLAYING) &&
|
||||
!SampleManager.GetChannelUsedFlag(CHANNEL_POLICE_RADIO) && m_sPoliceRadioQueue.m_nSamplesInQueue != 0) {
|
||||
sample = m_sPoliceRadioQueue.Remove();
|
||||
if (wantedLevel == 0) {
|
||||
if (gSpecialSuspectLastSeenReport) {
|
||||
gSpecialSuspectLastSeenReport = FALSE;
|
||||
} else if (sample == SFX_POLICE_RADIO_MESSAGE_NOISE_1) {
|
||||
bChannelOpen = FALSE;
|
||||
processed = TRUE;
|
||||
}
|
||||
}
|
||||
if (sample == NO_SAMPLE) {
|
||||
if (!processed) cWait = 30;
|
||||
} else {
|
||||
SampleManager.InitialiseChannel(CHANNEL_POLICE_RADIO, sample, SFX_BANK_0);
|
||||
switch (sample) {
|
||||
case SFX_POLICE_RADIO_MESSAGE_NOISE_1:
|
||||
freq = m_anRandomTable[4] % 2000 + 10025;
|
||||
bChannelOpen = bChannelOpen == FALSE;
|
||||
break;
|
||||
default: freq = SampleManager.GetSampleBaseFrequency(sample); break;
|
||||
}
|
||||
PoliceChannelFreq = freq;
|
||||
#ifdef USE_TIME_SCALE_FOR_AUDIO
|
||||
SampleManager.SetChannelFrequency(CHANNEL_POLICE_RADIO, freq * CTimer::GetTimeScale());
|
||||
#else
|
||||
SampleManager.SetChannelFrequency(CHANNEL_POLICE_RADIO, freq);
|
||||
#endif
|
||||
SampleManager.SetChannelVolume(CHANNEL_POLICE_RADIO, 100);
|
||||
SampleManager.SetChannelPan(CHANNEL_POLICE_RADIO, 63);
|
||||
SampleManager.SetChannelLoopCount(CHANNEL_POLICE_RADIO, 1);
|
||||
#ifndef GTA_PS2
|
||||
SampleManager.SetChannelLoopPoints(CHANNEL_POLICE_RADIO, 0, -1);
|
||||
#endif
|
||||
SampleManager.StartChannel(CHANNEL_POLICE_RADIO);
|
||||
}
|
||||
if (processed) ResetPoliceRadio();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool8
|
||||
cAudioManager::SetupCrimeReport()
|
||||
{
|
||||
int16 audioZoneId;
|
||||
CZone *zone;
|
||||
float rangeX;
|
||||
float rangeY;
|
||||
float halfX;
|
||||
float halfY;
|
||||
float quarterX;
|
||||
float quarterY;
|
||||
int i;
|
||||
uint32 sampleIndex;
|
||||
bool8 processed = FALSE;
|
||||
|
||||
if (MusicManager.m_nMusicMode == MUSICMODE_CUTSCENE) return FALSE;
|
||||
|
||||
if (POLICE_RADIO_QUEUE_MAX_SAMPLES - m_sPoliceRadioQueue.m_nSamplesInQueue <= 9) {
|
||||
AgeCrimes();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(m_aCrimes); i++) {
|
||||
if (m_aCrimes[i].type != CRIME_NONE)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == ARRAY_SIZE(m_aCrimes)) return FALSE;
|
||||
audioZoneId = CTheZones::FindAudioZone(&m_aCrimes[i].position);
|
||||
if (audioZoneId >= 0 && audioZoneId < NUMAUDIOZONES) {
|
||||
zone = CTheZones::GetAudioZone(audioZoneId);
|
||||
for (int j = 0; j < NUMAUDIOZONES; j++) {
|
||||
if (strcmp(zone->name, ZoneSfx[j].m_aName) == 0) {
|
||||
sampleIndex = ZoneSfx[j].m_nSampleIndex;
|
||||
m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_MESSAGE_NOISE_1);
|
||||
m_sPoliceRadioQueue.Add(m_anRandomTable[0] % 3 + SFX_WEVE_GOT);
|
||||
m_sPoliceRadioQueue.Add(SFX_A_10);
|
||||
switch (m_aCrimes[i].type) {
|
||||
case CRIME_PED_BURNED:
|
||||
case CRIME_HIT_PED_NASTYWEAPON:
|
||||
m_aCrimes[i].type = CRIME_HIT_PED;
|
||||
break;
|
||||
case CRIME_COP_BURNED:
|
||||
case CRIME_HIT_COP_NASTYWEAPON:
|
||||
m_aCrimes[i].type = CRIME_HIT_COP;
|
||||
break;
|
||||
case CRIME_VEHICLE_BURNED: m_aCrimes[i].type = CRIME_STEAL_CAR; break;
|
||||
case CRIME_DESTROYED_CESSNA: m_aCrimes[i].type = CRIME_SHOOT_HELI; break;
|
||||
case CRIME_EXPLOSION: m_aCrimes[i].type = CRIME_STEAL_CAR; break; // huh?
|
||||
default: break;
|
||||
}
|
||||
#ifdef FIX_BUGS
|
||||
m_sPoliceRadioQueue.Add(m_aCrimes[i].type + SFX_SFX_CRIME_1 - 1);
|
||||
#else
|
||||
m_sPoliceRadioQueue.Add(m_aCrimes[i].type + SFX_SFX_CRIME_1);
|
||||
#endif
|
||||
m_sPoliceRadioQueue.Add(SFX_IN);
|
||||
rangeX = zone->maxx - zone->minx;
|
||||
rangeY = zone->maxy - zone->miny;
|
||||
halfX = 0.5f * rangeX + zone->minx;
|
||||
halfY = 0.5f * rangeY + zone->miny;
|
||||
quarterX = 0.25f * rangeX;
|
||||
quarterY = 0.25f * rangeY;
|
||||
|
||||
if (m_aCrimes[i].position.y > halfY + quarterY) {
|
||||
m_sPoliceRadioQueue.Add(SFX_NORTH);
|
||||
processed = TRUE;
|
||||
} else if (m_aCrimes[i].position.y < halfY - quarterY) {
|
||||
m_sPoliceRadioQueue.Add(SFX_SOUTH);
|
||||
processed = TRUE;
|
||||
}
|
||||
|
||||
if (m_aCrimes[i].position.x > halfX + quarterX)
|
||||
m_sPoliceRadioQueue.Add(SFX_EAST);
|
||||
else if (m_aCrimes[i].position.x < halfX - quarterX)
|
||||
m_sPoliceRadioQueue.Add(SFX_WEST);
|
||||
else if (!processed)
|
||||
m_sPoliceRadioQueue.Add(SFX_CENTRAL);
|
||||
|
||||
m_sPoliceRadioQueue.Add(sampleIndex);
|
||||
m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_MESSAGE_NOISE_1);
|
||||
m_sPoliceRadioQueue.Add(NO_SAMPLE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
m_aCrimes[i].type = CRIME_NONE;
|
||||
AgeCrimes();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
Const uint32 gCarColourTable[][3] = {
|
||||
{NO_SAMPLE, SFX_SFX_POLICE_RADIO_BLACK, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_SFX_POLICE_RADIO_WHITE, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_SFX_POLICE_RADIO_BLUE, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_SFX_POLICE_RADIO_RED, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, SFX_SFX_POLICE_RADIO_BLUE, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_SFX_POLICE_RADIO_PURPLE, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_SFX_POLICE_RADIO_YELLOW, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_BRIGHT, SFX_SFX_POLICE_RADIO_BLUE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_LIGHT, SFX_SFX_POLICE_RADIO_BLUE, SFX_SFX_POLICE_RADIO_GREY},
|
||||
{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, SFX_SFX_POLICE_RADIO_RED, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_SFX_POLICE_RADIO_RED, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_SFX_POLICE_RADIO_RED, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_SFX_POLICE_RADIO_RED, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_SFX_POLICE_RADIO_RED, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_SFX_POLICE_RADIO_RED, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_SFX_POLICE_RADIO_RED, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_SFX_POLICE_RADIO_ORANGE, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_SFX_POLICE_RADIO_ORANGE, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_SFX_POLICE_RADIO_ORANGE, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_SFX_POLICE_RADIO_ORANGE, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_SFX_POLICE_RADIO_ORANGE, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_SFX_POLICE_RADIO_ORANGE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_SFX_POLICE_RADIO_YELLOW, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_SFX_POLICE_RADIO_YELLOW, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_SFX_POLICE_RADIO_YELLOW, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_SFX_POLICE_RADIO_YELLOW, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_SFX_POLICE_RADIO_YELLOW, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_SFX_POLICE_RADIO_YELLOW, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_SFX_POLICE_RADIO_GREEN, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_SFX_POLICE_RADIO_GREEN, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_SFX_POLICE_RADIO_GREEN, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_SFX_POLICE_RADIO_GREEN, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_SFX_POLICE_RADIO_GREEN, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_SFX_POLICE_RADIO_GREEN, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_SFX_POLICE_RADIO_BLUE, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_SFX_POLICE_RADIO_BLUE, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_SFX_POLICE_RADIO_BLUE, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_SFX_POLICE_RADIO_BLUE, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_SFX_POLICE_RADIO_BLUE, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_SFX_POLICE_RADIO_BLUE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_SFX_POLICE_RADIO_PURPLE, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_SFX_POLICE_RADIO_PURPLE, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_SFX_POLICE_RADIO_PURPLE, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_SFX_POLICE_RADIO_PURPLE, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_SFX_POLICE_RADIO_PURPLE, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_SFX_POLICE_RADIO_PURPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_SFX_POLICE_RADIO_SILVER, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_SFX_POLICE_RADIO_SILVER, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_SFX_POLICE_RADIO_SILVER, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_SFX_POLICE_RADIO_SILVER, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_SFX_POLICE_RADIO_SILVER, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_SFX_POLICE_RADIO_SILVER, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE}
|
||||
};
|
||||
|
||||
void
|
||||
cAudioManager::SetupSuspectLastSeenReport()
|
||||
{
|
||||
CVehicle *veh;
|
||||
uint8 color1;
|
||||
uint32 main_color;
|
||||
uint32 sample;
|
||||
|
||||
uint32 color_pre_modifier;
|
||||
uint32 color_post_modifier;
|
||||
|
||||
if (MusicManager.m_nMusicMode != MUSICMODE_CUTSCENE) {
|
||||
veh = FindVehicleOfPlayer();
|
||||
if (veh != nil) {
|
||||
if (POLICE_RADIO_QUEUE_MAX_SAMPLES - m_sPoliceRadioQueue.m_nSamplesInQueue > 9) {
|
||||
color1 = veh->m_currentColour1;
|
||||
if (color1 >= ARRAY_SIZE(gCarColourTable)) {
|
||||
debug("\n *** UNKNOWN CAR COLOUR %d *** ", color1);
|
||||
} else {
|
||||
main_color = gCarColourTable[color1][1];
|
||||
color_pre_modifier = gCarColourTable[color1][0];
|
||||
color_post_modifier = gCarColourTable[color1][2];
|
||||
switch (veh->GetModelIndex()) {
|
||||
case MI_LANDSTAL:
|
||||
case MI_PATRIOT:
|
||||
case MI_RANCHER:
|
||||
case MI_FBIRANCH:
|
||||
case MI_SANDKING:
|
||||
sample = SFX_SFX_POLICE_RADIO_OFFROAD;
|
||||
break;
|
||||
case MI_IDAHO:
|
||||
case MI_MANANA:
|
||||
case MI_ESPERANT:
|
||||
case MI_CUBAN:
|
||||
case MI_STALLION:
|
||||
case MI_SABRE:
|
||||
case MI_SABRETUR:
|
||||
case MI_VIRGO:
|
||||
case MI_BLISTAC:
|
||||
sample = SFX_SFX_POLICE_RADIO_TUDOOR;
|
||||
break;
|
||||
case MI_STINGER:
|
||||
case MI_INFERNUS:
|
||||
case MI_CHEETAH:
|
||||
case MI_BANSHEE:
|
||||
case MI_PHEONIX:
|
||||
case MI_COMET:
|
||||
case MI_DELUXO:
|
||||
case MI_HOTRING:
|
||||
sample = SFX_SFX_POLICE_RADIO_SPORTS_CAR;
|
||||
break;
|
||||
case MI_LINERUN:
|
||||
sample = SFX_SFX_POLICE_RADIO_RIG;
|
||||
break;
|
||||
case MI_PEREN:
|
||||
case MI_REGINA:
|
||||
sample = SFX_SFX_POLICE_RADIO_STATION_WAGON;
|
||||
break;
|
||||
case MI_SENTINEL:
|
||||
case MI_FBICAR:
|
||||
case MI_WASHING:
|
||||
case MI_SENTXS:
|
||||
case MI_ADMIRAL:
|
||||
case MI_GLENDALE:
|
||||
case MI_OCEANIC:
|
||||
case MI_HERMES:
|
||||
case MI_GREENWOO:
|
||||
sample = SFX_SFX_POLICE_RADIO_SEDAN;
|
||||
break;
|
||||
case MI_RIO:
|
||||
sample = SFX_SFX_POLICE_RADIO_CRUISER;
|
||||
break;
|
||||
case MI_FIRETRUCK:
|
||||
sample = SFX_SFX_POLICE_RADIO_FIRE_TRUCK;
|
||||
break;
|
||||
case MI_TRASH:
|
||||
sample = SFX_SFX_POLICE_RADIO_GARBAGE_TRUCK;
|
||||
break;
|
||||
case MI_STRETCH:
|
||||
case MI_LOVEFIST:
|
||||
sample = SFX_SFX_POLICE_RADIO_STRETCH;
|
||||
break;
|
||||
case MI_VOODOO:
|
||||
sample = SFX_SFX_POLICE_RADIO_LOWRIDER;
|
||||
break;
|
||||
case MI_PONY:
|
||||
case MI_MOONBEAM:
|
||||
case MI_SECURICA:
|
||||
case MI_RUMPO:
|
||||
case MI_GANGBUR:
|
||||
case MI_YANKEE:
|
||||
case MI_TOPFUN:
|
||||
case MI_BURRITO:
|
||||
case MI_SPAND:
|
||||
sample = SFX_SFX_POLICE_RADIO_VAN;
|
||||
break;
|
||||
case MI_MULE:
|
||||
case MI_BARRACKS:
|
||||
case MI_PACKER:
|
||||
case MI_FLATBED:
|
||||
sample = SFX_SFX_POLICE_RADIO_TRUCK;
|
||||
break;
|
||||
case MI_AMBULAN:
|
||||
sample = SFX_SFX_POLICE_RADIO_AMBULANCE;
|
||||
break;
|
||||
case MI_TAXI:
|
||||
case MI_CABBIE:
|
||||
case MI_BORGNINE:
|
||||
sample = SFX_SFX_POLICE_RADIO_TAXI;
|
||||
break;
|
||||
case MI_BOBCAT:
|
||||
case MI_WALTON:
|
||||
sample = SFX_SFX_POLICE_RADIO_PICKUP;
|
||||
break;
|
||||
case MI_MRWHOOP:
|
||||
sample = SFX_SFX_POLICE_RADIO_ICE_CREAM_VAN;
|
||||
break;
|
||||
case MI_BFINJECT:
|
||||
sample = SFX_SFX_POLICE_RADIO_BUGGY;
|
||||
break;
|
||||
case MI_HUNTER:
|
||||
case MI_CHOPPER:
|
||||
case MI_SEASPAR:
|
||||
case MI_SPARROW:
|
||||
case MI_MAVERICK:
|
||||
case MI_VCNMAV:
|
||||
case MI_POLMAV:
|
||||
sample = SFX_SFX_POLICE_RADIO_HELICOPTER;
|
||||
break;
|
||||
case MI_POLICE:
|
||||
sample = SFX_SFX_POLICE_RADIO_POLICE_CAR;
|
||||
break;
|
||||
case MI_ENFORCER:
|
||||
sample = SFX_SFX_POLICE_RADIO_SWAT_VAN;
|
||||
break;
|
||||
case MI_PREDATOR:
|
||||
case MI_SQUALO:
|
||||
case MI_SPEEDER:
|
||||
sample = SFX_SFX_POLICE_RADIO_SPEEDBOAT;
|
||||
break;
|
||||
case MI_BUS:
|
||||
sample = SFX_SFX_POLICE_RADIO_BUS;
|
||||
break;
|
||||
case MI_RHINO:
|
||||
sample = SFX_SFX_POLICE_RADIO_TANK;
|
||||
break;
|
||||
case MI_ANGEL:
|
||||
case MI_PCJ600:
|
||||
case MI_FREEWAY:
|
||||
case MI_SANCHEZ:
|
||||
sample = SFX_SFX_POLICE_RADIO_MOTOBIKE;
|
||||
break;
|
||||
case MI_COACH:
|
||||
sample = SFX_SFX_POLICE_RADIO_COACH;
|
||||
break;
|
||||
case MI_HEARSE:
|
||||
sample = SFX_SFX_POLICE_RADIO_HEARSE;
|
||||
break;
|
||||
case MI_PIZZABOY:
|
||||
case MI_FAGGIO:
|
||||
sample = SFX_SFX_POLICE_RADIO_MOPED;
|
||||
break;
|
||||
case MI_DEADDODO:
|
||||
case MI_SKIMMER:
|
||||
sample = SFX_SFX_POLICE_RADIO_PLANE;
|
||||
break;
|
||||
case MI_REEFER:
|
||||
case MI_TROPIC:
|
||||
case MI_COASTG:
|
||||
case MI_MARQUIS:
|
||||
case MI_JETMAX:
|
||||
sample = SFX_SFX_POLICE_RADIO_BOAT;
|
||||
break;
|
||||
case MI_CADDY:
|
||||
sample = SFX_SFX_POLICE_RADIO_GOLF_CART;
|
||||
break;
|
||||
case MI_DINGHY:
|
||||
sample = SFX_SFX_POLICE_RADIO_DINGHY;
|
||||
break;
|
||||
default:
|
||||
//debug("\n *** UNKNOWN CAR MODEL INDEX %d *** ", veh->GetModelIndex());
|
||||
return;
|
||||
}
|
||||
m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_MESSAGE_NOISE_1);
|
||||
m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_SUSPECT);
|
||||
if (m_anRandomTable[3] % 2)
|
||||
m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_LAST_SEEN);
|
||||
m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_IN_A);
|
||||
if (color_pre_modifier != NO_SAMPLE)
|
||||
m_sPoliceRadioQueue.Add(color_pre_modifier);
|
||||
if (main_color != NO_SAMPLE)
|
||||
m_sPoliceRadioQueue.Add(main_color);
|
||||
if (color_post_modifier != NO_SAMPLE)
|
||||
m_sPoliceRadioQueue.Add(color_post_modifier);
|
||||
m_sPoliceRadioQueue.Add(sample);
|
||||
m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_MESSAGE_NOISE_1);
|
||||
m_sPoliceRadioQueue.Add(NO_SAMPLE);
|
||||
}
|
||||
}
|
||||
} else if (POLICE_RADIO_QUEUE_MAX_SAMPLES - m_sPoliceRadioQueue.m_nSamplesInQueue > 4) {
|
||||
m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_MESSAGE_NOISE_1);
|
||||
m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_SUSPECT);
|
||||
m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_ON_FOOT);
|
||||
m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_MESSAGE_NOISE_1);
|
||||
m_sPoliceRadioQueue.Add(NO_SAMPLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
cAudioManager::ReportCrime(eCrimeType type, const CVector &pos)
|
||||
{
|
||||
int32 lastCrime = ARRAY_SIZE(m_aCrimes);
|
||||
if (m_bIsInitialised && MusicManager.m_nMusicMode != MUSICMODE_CUTSCENE && FindPlayerPed()->m_pWanted->GetWantedLevel() > 0 &&
|
||||
(type > CRIME_NONE || type < NUM_CRIME_TYPES) && m_FrameCounter >= gMinTimeToNextReport[type]) {
|
||||
for (int32 i = 0; i < ARRAY_SIZE(m_aCrimes); i++) {
|
||||
if (m_aCrimes[i].type != CRIME_NONE) {
|
||||
if (m_aCrimes[i].type == type) {
|
||||
m_aCrimes[i].position = pos;
|
||||
m_aCrimes[i].timer = 0;
|
||||
return;
|
||||
}
|
||||
} else
|
||||
lastCrime = i;
|
||||
}
|
||||
|
||||
if (lastCrime < ARRAY_SIZE(m_aCrimes)) {
|
||||
m_aCrimes[lastCrime].type = type;
|
||||
m_aCrimes[lastCrime].position = pos;
|
||||
m_aCrimes[lastCrime].timer = 0;
|
||||
gMinTimeToNextReport[type] = m_FrameCounter + 500;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
cAudioManager::PlaySuspectLastSeen(float x, float y, float z)
|
||||
{
|
||||
int16 audioZone;
|
||||
CZone *zone;
|
||||
float rangeX;
|
||||
float rangeY;
|
||||
float halfX;
|
||||
float halfY;
|
||||
float quarterX;
|
||||
float quarterY;
|
||||
uint32 sample;
|
||||
bool8 processed = FALSE;
|
||||
CVector vec = CVector(x, y, z);
|
||||
|
||||
if (!m_bIsInitialised) return;
|
||||
|
||||
if (MusicManager.m_nMusicMode != MUSICMODE_CUTSCENE && POLICE_RADIO_QUEUE_MAX_SAMPLES - m_sPoliceRadioQueue.m_nSamplesInQueue > 9) {
|
||||
audioZone = CTheZones::FindAudioZone(&vec);
|
||||
if (audioZone >= 0 && audioZone < NUMAUDIOZONES) {
|
||||
zone = CTheZones::GetAudioZone(audioZone);
|
||||
for (int i = 0; i < NUMAUDIOZONES; i++) {
|
||||
if (strcmp(zone->name, ZoneSfx[i].m_aName) == 0) {
|
||||
sample = ZoneSfx[i].m_nSampleIndex;
|
||||
m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_MESSAGE_NOISE_1);
|
||||
m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_SUSPECT);
|
||||
m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_LAST_SEEN);
|
||||
m_sPoliceRadioQueue.Add(SFX_IN);
|
||||
rangeX = zone->maxx - zone->minx;
|
||||
rangeY = zone->maxy - zone->miny;
|
||||
halfX = 0.5f * rangeX + zone->minx;
|
||||
halfY = 0.5f * rangeY + zone->miny;
|
||||
quarterX = 0.25f * rangeX;
|
||||
quarterY = 0.25f * rangeY;
|
||||
|
||||
if (vec.y > halfY + quarterY) {
|
||||
m_sPoliceRadioQueue.Add(SFX_NORTH);
|
||||
processed = TRUE;
|
||||
} else if (vec.y < halfY - quarterY) {
|
||||
m_sPoliceRadioQueue.Add(SFX_SOUTH);
|
||||
processed = TRUE;
|
||||
}
|
||||
|
||||
if (vec.x > halfX + quarterX)
|
||||
m_sPoliceRadioQueue.Add(SFX_EAST);
|
||||
else if (vec.x < halfX - quarterX)
|
||||
m_sPoliceRadioQueue.Add(SFX_WEST);
|
||||
else if (!processed)
|
||||
m_sPoliceRadioQueue.Add(SFX_CENTRAL);
|
||||
m_sPoliceRadioQueue.Add(sample);
|
||||
m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_MESSAGE_NOISE_1);
|
||||
m_sPoliceRadioQueue.Add(NO_SAMPLE);
|
||||
gSpecialSuspectLastSeenReport = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
cAudioManager::AgeCrimes()
|
||||
{
|
||||
for (uint8 i = 0; i < ARRAY_SIZE(m_aCrimes); i++) {
|
||||
if (m_aCrimes[i].type != CRIME_NONE) {
|
||||
if (++m_aCrimes[i].timer > 1200) m_aCrimes[i].type = CRIME_NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
67
src/audio/PolRadio.h
Normal file
67
src/audio/PolRadio.h
Normal file
@@ -0,0 +1,67 @@
|
||||
#pragma once
|
||||
|
||||
#include "Crime.h"
|
||||
#include "AudioSamples.h"
|
||||
|
||||
struct cAMCrime {
|
||||
int32 type;
|
||||
CVector position;
|
||||
uint16 timer;
|
||||
|
||||
cAMCrime()
|
||||
{
|
||||
type = CRIME_NONE;
|
||||
position = CVector(0.0f, 0.0f, 0.0f);
|
||||
timer = 0;
|
||||
}
|
||||
};
|
||||
|
||||
VALIDATE_SIZE(cAMCrime, 20);
|
||||
|
||||
#define POLICE_RADIO_QUEUE_MAX_SAMPLES 60
|
||||
|
||||
class cPoliceRadioQueue
|
||||
{
|
||||
public:
|
||||
uint32 m_aSamples[POLICE_RADIO_QUEUE_MAX_SAMPLES];
|
||||
uint8 m_nSamplesInQueue;
|
||||
uint8 m_nAddOffset;
|
||||
uint8 m_nRemoveOffset;
|
||||
|
||||
cPoliceRadioQueue()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
m_nAddOffset = 0;
|
||||
m_nRemoveOffset = 0;
|
||||
m_nSamplesInQueue = 0;
|
||||
}
|
||||
|
||||
bool8 Add(uint32 sample)
|
||||
{
|
||||
if (m_nSamplesInQueue != POLICE_RADIO_QUEUE_MAX_SAMPLES) {
|
||||
m_aSamples[m_nAddOffset] = sample;
|
||||
m_nSamplesInQueue++;
|
||||
m_nAddOffset = (m_nAddOffset + 1) % POLICE_RADIO_QUEUE_MAX_SAMPLES;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
uint32 Remove()
|
||||
{
|
||||
if (m_nSamplesInQueue != 0) {
|
||||
uint32 sample = m_aSamples[m_nRemoveOffset];
|
||||
m_nSamplesInQueue--;
|
||||
m_nRemoveOffset = (m_nRemoveOffset + 1) % POLICE_RADIO_QUEUE_MAX_SAMPLES;
|
||||
return sample;
|
||||
}
|
||||
return NO_SAMPLE;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
VALIDATE_SIZE(cPoliceRadioQueue, 244);
|
||||
@@ -1,747 +0,0 @@
|
||||
#include "common.h"
|
||||
|
||||
#include "DMAudio.h"
|
||||
|
||||
#include "AudioManager.h"
|
||||
|
||||
#include "AudioSamples.h"
|
||||
#include "MusicManager.h"
|
||||
#include "PlayerPed.h"
|
||||
#include "PoliceRadio.h"
|
||||
#include "Replay.h"
|
||||
#include "Vehicle.h"
|
||||
#include "World.h"
|
||||
#include "Zones.h"
|
||||
#include "sampman.h"
|
||||
#include "Wanted.h"
|
||||
|
||||
const int channels = ARRAY_SIZE(AudioManager.m_asActiveSamples);
|
||||
const int policeChannel = channels + 1;
|
||||
|
||||
struct tPoliceRadioZone {
|
||||
char m_aName[8];
|
||||
uint32 m_nSampleIndex;
|
||||
int32 field_12;
|
||||
};
|
||||
|
||||
tPoliceRadioZone ZoneSfx[NUMAUDIOZONES];
|
||||
|
||||
int32 g_nMissionAudioSfx = TOTAL_AUDIO_SAMPLES;
|
||||
int8 g_nMissionAudioPlayingStatus = 2;
|
||||
uint8 gSpecialSuspectLastSeenReport;
|
||||
uint32 gMinTimeToNextReport[NUM_CRIME_TYPES];
|
||||
|
||||
void
|
||||
cAudioManager::InitialisePoliceRadioZones()
|
||||
{
|
||||
for (int32 i = 0; i < NUMAUDIOZONES; i++)
|
||||
memset(ZoneSfx[i].m_aName, 0, 8);
|
||||
|
||||
#define SETZONESFX(i, name, sample) \
|
||||
strcpy(ZoneSfx[i].m_aName, name); \
|
||||
ZoneSfx[i].m_nSampleIndex = sample;
|
||||
|
||||
SETZONESFX(0, "VICE_C", SFX_POLICE_RADIO_VICE_CITY);
|
||||
SETZONESFX(1, "IND_ZON", SFX_POLICE_RADIO_VICE_CITY_BEACH);
|
||||
SETZONESFX(2, "COM_ZON", SFX_POLICE_RADIO_VICE_CITY_MAINLAND);
|
||||
SETZONESFX(3, "BEACH1", SFX_POLICE_RADIO_OCEAN_BEACH);
|
||||
SETZONESFX(4, "BEACH2", SFX_POLICE_RADIO_WASHINGTON_BEACH);
|
||||
SETZONESFX(5, "BEACH3", SFX_POLICE_RADIO_VICE_POINT);
|
||||
SETZONESFX(6, "GOLFC", SFX_POLICE_RADIO_LEAF_LINKS);
|
||||
SETZONESFX(7, "STARI", SFX_POLICE_RADIO_STRAFISH_ISLAND);
|
||||
SETZONESFX(8, "DOCKS", SFX_POLICE_RADIO_VICE_PORT);
|
||||
SETZONESFX(9, "HAVANA", SFX_POLICE_RADIO_LITTLE_HAVANA);
|
||||
SETZONESFX(10, "HAITI", SFX_POLICE_RADIO_LITTLE_HAITI);
|
||||
SETZONESFX(11, "PORNI", SFX_POLICE_RADIO_PRAWN_ISLAND);
|
||||
SETZONESFX(12, "DTOWN", SFX_POLICE_RADIO_DOWNTOWN);
|
||||
SETZONESFX(13, "A_PORT", SFX_POLICE_RADIO_ESCOBAR_INTERNATIONAL);
|
||||
|
||||
#undef SETZONESFX
|
||||
}
|
||||
|
||||
void
|
||||
cAudioManager::InitialisePoliceRadio()
|
||||
{
|
||||
m_sPoliceRadioQueue.policeChannelTimer = 0;
|
||||
m_sPoliceRadioQueue.policeChannelTimerSeconds = 0;
|
||||
m_sPoliceRadioQueue.policeChannelCounterSeconds = 0;
|
||||
for (int32 i = 0; i < ARRAY_SIZE(m_sPoliceRadioQueue.crimes); i++)
|
||||
m_sPoliceRadioQueue.crimes[i].type = CRIME_NONE;
|
||||
|
||||
SampleManager.SetChannelReverbFlag(policeChannel, false);
|
||||
gSpecialSuspectLastSeenReport = false;
|
||||
for (int32 i = 0; i < ARRAY_SIZE(gMinTimeToNextReport); i++)
|
||||
gMinTimeToNextReport[i] = m_FrameCounter;
|
||||
}
|
||||
|
||||
void
|
||||
cAudioManager::ResetPoliceRadio()
|
||||
{
|
||||
if (!m_bIsInitialised) return;
|
||||
if (SampleManager.GetChannelUsedFlag(policeChannel)) SampleManager.StopChannel(policeChannel);
|
||||
InitialisePoliceRadio();
|
||||
}
|
||||
|
||||
void
|
||||
cAudioManager::SetMissionScriptPoliceAudio(int32 sfx) const
|
||||
{
|
||||
if (!m_bIsInitialised) return;
|
||||
if (g_nMissionAudioPlayingStatus != 1) {
|
||||
g_nMissionAudioPlayingStatus = 0;
|
||||
g_nMissionAudioSfx = sfx;
|
||||
}
|
||||
}
|
||||
|
||||
int8
|
||||
cAudioManager::GetMissionScriptPoliceAudioPlayingStatus() const
|
||||
{
|
||||
return g_nMissionAudioPlayingStatus;
|
||||
}
|
||||
|
||||
void
|
||||
cAudioManager::DoPoliceRadioCrackle()
|
||||
{
|
||||
m_sQueueSample.m_nEntityIndex = m_nPoliceChannelEntity;
|
||||
m_sQueueSample.m_nCounter = 0;
|
||||
m_sQueueSample.m_nSampleIndex = SFX_POLICE_RADIO_CRACKLE;
|
||||
m_sQueueSample.m_nBankIndex = SFX_BANK_0;
|
||||
m_sQueueSample.m_bIs2D = true;
|
||||
m_sQueueSample.m_nReleasingVolumeModificator = 10;
|
||||
m_sQueueSample.m_nFrequency = SampleManager.GetSampleBaseFrequency(SFX_POLICE_RADIO_CRACKLE);
|
||||
m_sQueueSample.m_nVolume = m_anRandomTable[2] % 20 + 15;
|
||||
m_sQueueSample.m_nLoopCount = 0;
|
||||
m_sQueueSample.m_nEmittingVolume = m_sQueueSample.m_nVolume;
|
||||
m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(SFX_POLICE_RADIO_CRACKLE);
|
||||
m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(SFX_POLICE_RADIO_CRACKLE);
|
||||
m_sQueueSample.m_bReleasingSoundFlag = false;
|
||||
m_sQueueSample.m_bReverbFlag = false;
|
||||
m_sQueueSample.m_nOffset = 63;
|
||||
m_sQueueSample.m_nReleasingVolumeDivider = 3;
|
||||
m_sQueueSample.m_bRequireReflection = false;
|
||||
AddSampleToRequestedQueue();
|
||||
}
|
||||
|
||||
void
|
||||
cAudioManager::ServicePoliceRadio()
|
||||
{
|
||||
int32 wantedLevel = 0; // uninitialized variable
|
||||
static uint32 nLastSeen = 300;
|
||||
|
||||
if(!m_bIsInitialised) return;
|
||||
|
||||
if(m_nUserPause == 0) {
|
||||
bool crimeReport = SetupCrimeReport();
|
||||
#ifdef FIX_BUGS // Crash at 0x5fe6ef
|
||||
if(CReplay::IsPlayingBack() || !FindPlayerPed() || !FindPlayerPed()->m_pWanted)
|
||||
return;
|
||||
#endif
|
||||
CPlayerPed *playerPed = FindPlayerPed();
|
||||
if (playerPed) {
|
||||
wantedLevel = playerPed->m_pWanted->GetWantedLevel();
|
||||
if (!crimeReport) {
|
||||
if (wantedLevel != 0) {
|
||||
if (nLastSeen != 0)
|
||||
--nLastSeen;
|
||||
else {
|
||||
nLastSeen = m_anRandomTable[1] % 1000 + 2000;
|
||||
SetupSuspectLastSeenReport();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ServicePoliceRadioChannel(wantedLevel);
|
||||
}
|
||||
|
||||
void
|
||||
cAudioManager::ServicePoliceRadioChannel(uint8 wantedLevel)
|
||||
{
|
||||
bool processed = false;
|
||||
uint32 sample;
|
||||
int32 freq;
|
||||
|
||||
static int cWait = 0;
|
||||
static bool bChannelOpen = false;
|
||||
static uint8 bMissionAudioPhysicalPlayingStatus = 0;
|
||||
static int32 PoliceChannelFreq = 22050;
|
||||
|
||||
if (!m_bIsInitialised) return;
|
||||
|
||||
if (m_nUserPause != 0) {
|
||||
if (SampleManager.GetChannelUsedFlag(policeChannel)) SampleManager.StopChannel(policeChannel);
|
||||
if (g_nMissionAudioSfx != NO_SAMPLE && bMissionAudioPhysicalPlayingStatus == 1 &&
|
||||
SampleManager.IsStreamPlaying(1)) {
|
||||
SampleManager.PauseStream(1, 1);
|
||||
}
|
||||
} else {
|
||||
if (m_nPreviousUserPause && g_nMissionAudioSfx != NO_SAMPLE &&
|
||||
bMissionAudioPhysicalPlayingStatus == 1) {
|
||||
SampleManager.PauseStream(0, 1);
|
||||
}
|
||||
if (m_sPoliceRadioQueue.policeChannelTimer == 0) bChannelOpen = false;
|
||||
if (cWait) {
|
||||
--cWait;
|
||||
return;
|
||||
}
|
||||
if (g_nMissionAudioSfx != NO_SAMPLE && !bChannelOpen) {
|
||||
if (g_nMissionAudioPlayingStatus) {
|
||||
if (g_nMissionAudioPlayingStatus == 1 && !bMissionAudioPhysicalPlayingStatus &&
|
||||
SampleManager.IsStreamPlaying(1)) {
|
||||
bMissionAudioPhysicalPlayingStatus = 1;
|
||||
}
|
||||
if (bMissionAudioPhysicalPlayingStatus == 1) {
|
||||
if (SampleManager.IsStreamPlaying(1)) {
|
||||
DoPoliceRadioCrackle();
|
||||
} else {
|
||||
bMissionAudioPhysicalPlayingStatus = 2;
|
||||
g_nMissionAudioPlayingStatus = 2;
|
||||
g_nMissionAudioSfx = NO_SAMPLE;
|
||||
cWait = 30;
|
||||
}
|
||||
return;
|
||||
}
|
||||
} else if (!SampleManager.GetChannelUsedFlag(policeChannel)) {
|
||||
SampleManager.PreloadStreamedFile(g_nMissionAudioSfx, 1);
|
||||
SampleManager.SetStreamedVolumeAndPan(MAX_VOLUME, 63, 1, 1);
|
||||
SampleManager.StartPreloadedStreamedFile(1);
|
||||
g_nMissionAudioPlayingStatus = 1;
|
||||
bMissionAudioPhysicalPlayingStatus = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (bChannelOpen) DoPoliceRadioCrackle();
|
||||
if ((g_nMissionAudioSfx == NO_SAMPLE || g_nMissionAudioPlayingStatus != 1) &&
|
||||
!SampleManager.GetChannelUsedFlag(policeChannel) && m_sPoliceRadioQueue.policeChannelTimer) {
|
||||
if (m_sPoliceRadioQueue.policeChannelTimer) {
|
||||
sample = m_sPoliceRadioQueue.crimesSamples[m_sPoliceRadioQueue.policeChannelCounterSeconds];
|
||||
m_sPoliceRadioQueue.policeChannelTimer--;
|
||||
m_sPoliceRadioQueue.policeChannelCounterSeconds = (m_sPoliceRadioQueue.policeChannelCounterSeconds + 1) % 60;
|
||||
} else {
|
||||
sample = NO_SAMPLE;
|
||||
}
|
||||
if (wantedLevel == 0) {
|
||||
if (gSpecialSuspectLastSeenReport) {
|
||||
gSpecialSuspectLastSeenReport = 0;
|
||||
} else if (sample == SFX_POLICE_RADIO_MESSAGE_NOISE_1) {
|
||||
bChannelOpen = false;
|
||||
processed = true;
|
||||
}
|
||||
}
|
||||
if (sample == NO_SAMPLE) {
|
||||
if (!processed) cWait = 30;
|
||||
} else {
|
||||
SampleManager.InitialiseChannel(policeChannel, sample, 0);
|
||||
switch (sample) {
|
||||
case SFX_POLICE_RADIO_MESSAGE_NOISE_1:
|
||||
freq = m_anRandomTable[4] % 2000 + 10025;
|
||||
bChannelOpen = bChannelOpen == false;
|
||||
break;
|
||||
default: freq = SampleManager.GetSampleBaseFrequency(sample); break;
|
||||
}
|
||||
PoliceChannelFreq = freq;
|
||||
SampleManager.SetChannelFrequency(policeChannel, freq);
|
||||
SampleManager.SetChannelVolume(policeChannel, 100);
|
||||
SampleManager.SetChannelPan(policeChannel, 63);
|
||||
SampleManager.SetChannelLoopCount(policeChannel, 1);
|
||||
SampleManager.SetChannelLoopPoints(policeChannel, 0, -1);
|
||||
SampleManager.StartChannel(policeChannel);
|
||||
}
|
||||
if (processed) ResetPoliceRadio();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
cAudioManager::SetupCrimeReport()
|
||||
{
|
||||
int16 audioZoneId;
|
||||
CZone *zone;
|
||||
float rangeX;
|
||||
float rangeY;
|
||||
float halfX;
|
||||
float halfY;
|
||||
float quarterX;
|
||||
float quarterY;
|
||||
int i;
|
||||
int32 sampleIndex;
|
||||
bool processed = false;
|
||||
|
||||
if (MusicManager.m_nMusicMode == MUSICMODE_CUTSCENE) return false;
|
||||
|
||||
if (60 - m_sPoliceRadioQueue.policeChannelTimer <= 9) {
|
||||
AgeCrimes();
|
||||
return true;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(m_sPoliceRadioQueue.crimes); i++) {
|
||||
if (m_sPoliceRadioQueue.crimes[i].type != CRIME_NONE)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == ARRAY_SIZE(m_sPoliceRadioQueue.crimes)) return false;
|
||||
audioZoneId = CTheZones::FindAudioZone(&m_sPoliceRadioQueue.crimes[i].position);
|
||||
if (audioZoneId >= 0 && audioZoneId < NUMAUDIOZONES) {
|
||||
zone = CTheZones::GetAudioZone(audioZoneId);
|
||||
for (int j = 0; j < NUMAUDIOZONES; j++) {
|
||||
if (strcmp(zone->name, ZoneSfx[j].m_aName) == 0) {
|
||||
sampleIndex = ZoneSfx[j].m_nSampleIndex;
|
||||
m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_MESSAGE_NOISE_1);
|
||||
m_sPoliceRadioQueue.Add(m_anRandomTable[0] % 3 + SFX_WEVE_GOT);
|
||||
m_sPoliceRadioQueue.Add(SFX_A_10);
|
||||
switch (m_sPoliceRadioQueue.crimes[i].type) {
|
||||
case CRIME_PED_BURNED:
|
||||
case CRIME_HIT_PED_NASTYWEAPON:
|
||||
m_sPoliceRadioQueue.crimes[i].type = CRIME_HIT_PED;
|
||||
break;
|
||||
case CRIME_COP_BURNED:
|
||||
case CRIME_HIT_COP_NASTYWEAPON:
|
||||
m_sPoliceRadioQueue.crimes[i].type = CRIME_HIT_COP;
|
||||
break;
|
||||
case CRIME_VEHICLE_BURNED: m_sPoliceRadioQueue.crimes[i].type = CRIME_STEAL_CAR; break;
|
||||
case CRIME_DESTROYED_CESSNA: m_sPoliceRadioQueue.crimes[i].type = CRIME_SHOOT_HELI; break;
|
||||
case CRIME_EXPLOSION: m_sPoliceRadioQueue.crimes[i].type = CRIME_STEAL_CAR; break; // huh?
|
||||
default: break;
|
||||
}
|
||||
#ifdef FIX_BUGS
|
||||
m_sPoliceRadioQueue.Add(m_sPoliceRadioQueue.crimes[i].type + SFX_CRIME_1 - 1);
|
||||
#else
|
||||
m_sPoliceRadioQueue.Add(m_sPoliceRadioQueue.crimes[i].type + SFX_CRIME_1);
|
||||
#endif
|
||||
m_sPoliceRadioQueue.Add(SFX_IN);
|
||||
rangeX = zone->maxx - zone->minx;
|
||||
rangeY = zone->maxy - zone->miny;
|
||||
halfX = 0.5f * rangeX + zone->minx;
|
||||
halfY = 0.5f * rangeY + zone->miny;
|
||||
quarterX = 0.25f * rangeX;
|
||||
quarterY = 0.25f * rangeY;
|
||||
|
||||
if (m_sPoliceRadioQueue.crimes[i].position.y > halfY + quarterY) {
|
||||
m_sPoliceRadioQueue.Add(SFX_NORTH);
|
||||
processed = true;
|
||||
} else if (m_sPoliceRadioQueue.crimes[i].position.y < halfY - quarterY) {
|
||||
m_sPoliceRadioQueue.Add(SFX_SOUTH);
|
||||
processed = true;
|
||||
}
|
||||
|
||||
if (m_sPoliceRadioQueue.crimes[i].position.x > halfX + quarterX)
|
||||
m_sPoliceRadioQueue.Add(SFX_EAST);
|
||||
else if (m_sPoliceRadioQueue.crimes[i].position.x < halfX - quarterX)
|
||||
m_sPoliceRadioQueue.Add(SFX_WEST);
|
||||
else if (!processed)
|
||||
m_sPoliceRadioQueue.Add(SFX_CENTRAL);
|
||||
|
||||
m_sPoliceRadioQueue.Add(sampleIndex);
|
||||
m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_MESSAGE_NOISE_1);
|
||||
m_sPoliceRadioQueue.Add(NO_SAMPLE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
m_sPoliceRadioQueue.crimes[i].type = CRIME_NONE;
|
||||
AgeCrimes();
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
cAudioManager::SetupSuspectLastSeenReport()
|
||||
{
|
||||
CVehicle *veh;
|
||||
uint8 color1;
|
||||
int32 main_color;
|
||||
int32 sample;
|
||||
|
||||
int32 color_pre_modifier;
|
||||
int32 color_post_modifier;
|
||||
|
||||
const int32 gCarColourTable[][3] = {
|
||||
{NO_SAMPLE, SFX_POLICE_RADIO_BLACK, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_POLICE_RADIO_WHITE, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_POLICE_RADIO_BLUE, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_POLICE_RADIO_RED, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_BLUE, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_POLICE_RADIO_PURPLE, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_POLICE_RADIO_YELLOW, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_BRIGHT, SFX_POLICE_RADIO_BLUE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_LIGHT, SFX_POLICE_RADIO_BLUE, SFX_POLICE_RADIO_GREY},
|
||||
{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, SFX_POLICE_RADIO_RED, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_POLICE_RADIO_RED, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_POLICE_RADIO_RED, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_POLICE_RADIO_RED, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_POLICE_RADIO_RED, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_POLICE_RADIO_RED, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_POLICE_RADIO_RED, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_POLICE_RADIO_ORANGE, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_POLICE_RADIO_ORANGE, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_POLICE_RADIO_ORANGE, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_POLICE_RADIO_ORANGE, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_POLICE_RADIO_ORANGE, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_POLICE_RADIO_ORANGE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_POLICE_RADIO_YELLOW, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_POLICE_RADIO_YELLOW, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_POLICE_RADIO_YELLOW, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_POLICE_RADIO_YELLOW, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_POLICE_RADIO_YELLOW, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_POLICE_RADIO_YELLOW, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_POLICE_RADIO_GREEN, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_POLICE_RADIO_GREEN, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_POLICE_RADIO_GREEN, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_POLICE_RADIO_GREEN, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_POLICE_RADIO_GREEN, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_POLICE_RADIO_GREEN, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_POLICE_RADIO_BLUE, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_POLICE_RADIO_BLUE, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_POLICE_RADIO_BLUE, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_POLICE_RADIO_BLUE, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_POLICE_RADIO_BLUE, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_POLICE_RADIO_BLUE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_POLICE_RADIO_PURPLE, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_POLICE_RADIO_PURPLE, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_POLICE_RADIO_PURPLE, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_POLICE_RADIO_PURPLE, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_POLICE_RADIO_PURPLE, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_POLICE_RADIO_PURPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_POLICE_RADIO_SILVER, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_POLICE_RADIO_SILVER, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_POLICE_RADIO_SILVER, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_POLICE_RADIO_SILVER, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_POLICE_RADIO_SILVER, NO_SAMPLE},
|
||||
{NO_SAMPLE, SFX_POLICE_RADIO_SILVER, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_LIGHT, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE},
|
||||
{SFX_POLICE_RADIO_DARK, NO_SAMPLE, NO_SAMPLE}
|
||||
};
|
||||
|
||||
if (MusicManager.m_nMusicMode != MUSICMODE_CUTSCENE) {
|
||||
veh = FindVehicleOfPlayer();
|
||||
if (veh != nil) {
|
||||
if (60 - m_sPoliceRadioQueue.policeChannelTimer > 9) {
|
||||
color1 = veh->m_currentColour1;
|
||||
if (color1 >= ARRAY_SIZE(gCarColourTable)) {
|
||||
debug("\n *** UNKNOWN CAR COLOUR %d *** ", color1);
|
||||
} else {
|
||||
main_color = gCarColourTable[color1][1];
|
||||
color_pre_modifier = gCarColourTable[color1][0];
|
||||
color_post_modifier = gCarColourTable[color1][2];
|
||||
switch (veh->GetModelIndex()) {
|
||||
case MI_LANDSTAL:
|
||||
case MI_PATRIOT:
|
||||
case MI_RANCHER:
|
||||
case MI_FBIRANCH:
|
||||
case MI_SANDKING:
|
||||
sample = SFX_POLICE_RADIO_OFFROAD;
|
||||
break;
|
||||
case MI_IDAHO:
|
||||
case MI_MANANA:
|
||||
case MI_ESPERANT:
|
||||
case MI_CUBAN:
|
||||
case MI_STALLION:
|
||||
case MI_SABRE:
|
||||
case MI_SABRETUR:
|
||||
case MI_VIRGO:
|
||||
case MI_BLISTAC:
|
||||
sample = SFX_POLICE_RADIO_2_DOOR;
|
||||
break;
|
||||
case MI_STINGER:
|
||||
case MI_INFERNUS:
|
||||
case MI_CHEETAH:
|
||||
case MI_BANSHEE:
|
||||
case MI_PHEONIX:
|
||||
case MI_COMET:
|
||||
case MI_DELUXO:
|
||||
case MI_HOTRING:
|
||||
sample = SFX_POLICE_RADIO_SPORTS_CAR;
|
||||
break;
|
||||
case MI_LINERUN:
|
||||
sample = SFX_POLICE_RADIO_RIG;
|
||||
break;
|
||||
case MI_PEREN:
|
||||
case MI_REGINA:
|
||||
sample = SFX_POLICE_RADIO_STATION_WAGON;
|
||||
break;
|
||||
case MI_SENTINEL:
|
||||
case MI_FBICAR:
|
||||
case MI_WASHING:
|
||||
case MI_SENTXS:
|
||||
case MI_ADMIRAL:
|
||||
case MI_GLENDALE:
|
||||
case MI_OCEANIC:
|
||||
case MI_HERMES:
|
||||
case MI_GREENWOO:
|
||||
sample = SFX_POLICE_RADIO_SEDAN;
|
||||
break;
|
||||
case MI_RIO:
|
||||
sample = SFX_POLICE_RADIO_CRUISER;
|
||||
break;
|
||||
case MI_FIRETRUCK:
|
||||
sample = SFX_POLICE_RADIO_FIRE_TRUCK;
|
||||
break;
|
||||
case MI_TRASH:
|
||||
sample = SFX_POLICE_RADIO_GARBAGE_TRUCK;
|
||||
break;
|
||||
case MI_STRETCH:
|
||||
case MI_LOVEFIST:
|
||||
sample = SFX_POLICE_RADIO_STRETCH;
|
||||
break;
|
||||
case MI_VOODOO:
|
||||
sample = SFX_POLICE_RADIO_LOWRIDER;
|
||||
break;
|
||||
case MI_PONY:
|
||||
case MI_MOONBEAM:
|
||||
case MI_SECURICA:
|
||||
case MI_RUMPO:
|
||||
case MI_GANGBUR:
|
||||
case MI_YANKEE:
|
||||
case MI_TOPFUN:
|
||||
case MI_BURRITO:
|
||||
case MI_SPAND:
|
||||
sample = SFX_POLICE_RADIO_VAN;
|
||||
break;
|
||||
case MI_MULE:
|
||||
case MI_BARRACKS:
|
||||
case MI_PACKER:
|
||||
case MI_FLATBED:
|
||||
sample = SFX_POLICE_RADIO_TRUCK;
|
||||
break;
|
||||
case MI_AMBULAN:
|
||||
sample = SFX_POLICE_RADIO_AMBULANCE;
|
||||
break;
|
||||
case MI_TAXI:
|
||||
case MI_CABBIE:
|
||||
case MI_ZEBRA:
|
||||
case MI_KAUFMAN:
|
||||
sample = SFX_POLICE_RADIO_TAXI;
|
||||
break;
|
||||
case MI_BOBCAT:
|
||||
case MI_WALTON:
|
||||
sample = SFX_POLICE_RADIO_PICKUP;
|
||||
break;
|
||||
case MI_MRWHOOP:
|
||||
sample = SFX_POLICE_RADIO_ICE_CREAM_VAN;
|
||||
break;
|
||||
case MI_BFINJECT:
|
||||
sample = SFX_POLICE_RADIO_BUGGY;
|
||||
break;
|
||||
case MI_HUNTER:
|
||||
case MI_CHOPPER:
|
||||
case MI_SEASPAR:
|
||||
case MI_SPARROW:
|
||||
case MI_MAVERICK:
|
||||
case MI_VCNMAV:
|
||||
case MI_POLMAV:
|
||||
sample = SFX_POLICE_RADIO_HELICOPTER;
|
||||
break;
|
||||
case MI_POLICE:
|
||||
sample = SFX_POLICE_RADIO_POLICE_CAR;
|
||||
break;
|
||||
case MI_ENFORCER:
|
||||
sample = SFX_POLICE_RADIO_SWAT_VAN;
|
||||
break;
|
||||
case MI_PREDATOR:
|
||||
case MI_SQUALO:
|
||||
case MI_SPEEDER:
|
||||
sample = SFX_POLICE_RADIO_SPEEDBOAT;
|
||||
break;
|
||||
case MI_BUS:
|
||||
sample = SFX_POLICE_RADIO_BUS;
|
||||
break;
|
||||
case MI_RHINO:
|
||||
sample = SFX_POLICE_RADIO_TANK;
|
||||
break;
|
||||
case MI_ANGEL:
|
||||
case MI_PCJ600:
|
||||
case MI_FREEWAY:
|
||||
case MI_SANCHEZ:
|
||||
sample = SFX_POLICE_RADIO_MOTOBIKE;
|
||||
break;
|
||||
case MI_COACH:
|
||||
sample = SFX_POLICE_RADIO_COACH;
|
||||
break;
|
||||
case MI_ROMERO:
|
||||
sample = SFX_POLICE_RADIO_HEARSE;
|
||||
break;
|
||||
case MI_PIZZABOY:
|
||||
case MI_FAGGIO:
|
||||
sample = SFX_POLICE_RADIO_MOPED;
|
||||
break;
|
||||
case MI_DEADDODO:
|
||||
case MI_SKIMMER:
|
||||
sample = SFX_POLICE_RADIO_PLANE;
|
||||
break;
|
||||
case MI_REEFER:
|
||||
case MI_TROPIC:
|
||||
case MI_COASTG:
|
||||
case MI_MARQUIS:
|
||||
case MI_JETMAX:
|
||||
sample = SFX_POLICE_RADIO_BOAT;
|
||||
break;
|
||||
case MI_CADDY:
|
||||
sample = SFX_POLICE_RADIO_GOLF_CART;
|
||||
break;
|
||||
case MI_DINGHY:
|
||||
sample = SFX_POLICE_RADIO_DINGHY;
|
||||
break;
|
||||
default:
|
||||
//debug("\n *** UNKNOWN CAR MODEL INDEX %d *** ", veh->GetModelIndex());
|
||||
return;
|
||||
}
|
||||
m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_MESSAGE_NOISE_1);
|
||||
m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_SUSPECT);
|
||||
if (m_anRandomTable[3] % 2)
|
||||
m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_LAST_SEEN);
|
||||
m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_IN_A);
|
||||
if (color_pre_modifier != NO_SAMPLE)
|
||||
m_sPoliceRadioQueue.Add(color_pre_modifier);
|
||||
if (main_color != NO_SAMPLE)
|
||||
m_sPoliceRadioQueue.Add(main_color);
|
||||
if (color_post_modifier != NO_SAMPLE)
|
||||
m_sPoliceRadioQueue.Add(color_post_modifier);
|
||||
m_sPoliceRadioQueue.Add(sample);
|
||||
m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_MESSAGE_NOISE_1);
|
||||
m_sPoliceRadioQueue.Add(NO_SAMPLE);
|
||||
}
|
||||
}
|
||||
} else if (60 - m_sPoliceRadioQueue.policeChannelTimer > 4) {
|
||||
m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_MESSAGE_NOISE_1);
|
||||
m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_SUSPECT);
|
||||
m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_ON_FOOT);
|
||||
m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_MESSAGE_NOISE_1);
|
||||
m_sPoliceRadioQueue.Add(NO_SAMPLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
cAudioManager::ReportCrime(eCrimeType type, const CVector &pos)
|
||||
{
|
||||
int32 lastCrime = ARRAY_SIZE(m_sPoliceRadioQueue.crimes);
|
||||
if (m_bIsInitialised && MusicManager.m_nMusicMode != MUSICMODE_CUTSCENE && FindPlayerPed()->m_pWanted->GetWantedLevel() > 0 &&
|
||||
(type > CRIME_NONE || type < NUM_CRIME_TYPES) && m_FrameCounter >= gMinTimeToNextReport[type]) {
|
||||
for (int32 i = 0; i < ARRAY_SIZE(m_sPoliceRadioQueue.crimes); i++) {
|
||||
if (m_sPoliceRadioQueue.crimes[i].type != CRIME_NONE) {
|
||||
if (m_sPoliceRadioQueue.crimes[i].type == type) {
|
||||
m_sPoliceRadioQueue.crimes[i].position = pos;
|
||||
m_sPoliceRadioQueue.crimes[i].timer = 0;
|
||||
return;
|
||||
}
|
||||
} else
|
||||
lastCrime = i;
|
||||
}
|
||||
|
||||
if (lastCrime < ARRAY_SIZE(m_sPoliceRadioQueue.crimes)) {
|
||||
m_sPoliceRadioQueue.crimes[lastCrime].type = type;
|
||||
m_sPoliceRadioQueue.crimes[lastCrime].position = pos;
|
||||
m_sPoliceRadioQueue.crimes[lastCrime].timer = 0;
|
||||
gMinTimeToNextReport[type] = m_FrameCounter + 500;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
cAudioManager::PlaySuspectLastSeen(float x, float y, float z)
|
||||
{
|
||||
int16 audioZone;
|
||||
CZone *zone;
|
||||
float rangeX;
|
||||
float rangeY;
|
||||
float halfX;
|
||||
float halfY;
|
||||
float quarterX;
|
||||
float quarterY;
|
||||
int32 sample;
|
||||
bool processed = false;
|
||||
CVector vec = CVector(x, y, z);
|
||||
|
||||
if (!m_bIsInitialised) return;
|
||||
|
||||
if (MusicManager.m_nMusicMode != MUSICMODE_CUTSCENE && 60 - m_sPoliceRadioQueue.policeChannelTimer > 9) {
|
||||
audioZone = CTheZones::FindAudioZone(&vec);
|
||||
if (audioZone >= 0 && audioZone < NUMAUDIOZONES) {
|
||||
zone = CTheZones::GetAudioZone(audioZone);
|
||||
for (int i = 0; i < NUMAUDIOZONES; i++) {
|
||||
if (strcmp(zone->name, ZoneSfx[i].m_aName) == 0) {
|
||||
sample = ZoneSfx[i].m_nSampleIndex;
|
||||
m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_MESSAGE_NOISE_1);
|
||||
m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_SUSPECT);
|
||||
m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_LAST_SEEN);
|
||||
m_sPoliceRadioQueue.Add(SFX_IN);
|
||||
rangeX = zone->maxx - zone->minx;
|
||||
rangeY = zone->maxy - zone->miny;
|
||||
halfX = 0.5f * rangeX + zone->minx;
|
||||
halfY = 0.5f * rangeY + zone->miny;
|
||||
quarterX = 0.25f * rangeX;
|
||||
quarterY = 0.25f * rangeY;
|
||||
|
||||
if (vec.y > halfY + quarterY) {
|
||||
m_sPoliceRadioQueue.Add(SFX_NORTH);
|
||||
processed = true;
|
||||
} else if (vec.y < halfY - quarterY) {
|
||||
m_sPoliceRadioQueue.Add(SFX_SOUTH);
|
||||
processed = true;
|
||||
}
|
||||
|
||||
if (vec.x > halfX + quarterX)
|
||||
m_sPoliceRadioQueue.Add(SFX_EAST);
|
||||
else if (vec.x < halfX - quarterX)
|
||||
m_sPoliceRadioQueue.Add(SFX_WEST);
|
||||
else if (!processed)
|
||||
m_sPoliceRadioQueue.Add(SFX_CENTRAL);
|
||||
m_sPoliceRadioQueue.Add(sample);
|
||||
m_sPoliceRadioQueue.Add(SFX_POLICE_RADIO_MESSAGE_NOISE_1);
|
||||
m_sPoliceRadioQueue.Add(NO_SAMPLE);
|
||||
gSpecialSuspectLastSeenReport = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
cAudioManager::AgeCrimes()
|
||||
{
|
||||
for (uint8 i = 0; i < ARRAY_SIZE(m_sPoliceRadioQueue.crimes); i++) {
|
||||
if (m_sPoliceRadioQueue.crimes[i].type != CRIME_NONE) {
|
||||
if (++m_sPoliceRadioQueue.crimes[i].timer > 1200) m_sPoliceRadioQueue.crimes[i].type = CRIME_NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "Crime.h"
|
||||
|
||||
struct cAMCrime {
|
||||
int32 type;
|
||||
CVector position;
|
||||
uint16 timer;
|
||||
|
||||
cAMCrime()
|
||||
{
|
||||
type = CRIME_NONE;
|
||||
position = CVector(0.0f, 0.0f, 0.0f);
|
||||
timer = 0;
|
||||
}
|
||||
};
|
||||
|
||||
VALIDATE_SIZE(cAMCrime, 20);
|
||||
|
||||
class cPoliceRadioQueue
|
||||
{
|
||||
public:
|
||||
int32 crimesSamples[60];
|
||||
uint8 policeChannelTimer;
|
||||
uint8 policeChannelTimerSeconds;
|
||||
uint8 policeChannelCounterSeconds;
|
||||
cAMCrime crimes[10];
|
||||
|
||||
cPoliceRadioQueue()
|
||||
{
|
||||
policeChannelTimerSeconds = 0;
|
||||
policeChannelCounterSeconds = 0;
|
||||
policeChannelTimer = 0;
|
||||
}
|
||||
|
||||
void Add(uint32 sample)
|
||||
{
|
||||
if (policeChannelTimer != 60) {
|
||||
crimesSamples[policeChannelTimerSeconds] = sample;
|
||||
policeChannelTimer++;
|
||||
policeChannelTimerSeconds = (policeChannelTimerSeconds + 1) % 60;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
VALIDATE_SIZE(cPoliceRadioQueue, 0x1BC);
|
||||
File diff suppressed because it is too large
Load Diff
@@ -24,12 +24,6 @@
|
||||
|
||||
#include "aldlist.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#define _stricmp strcasecmp
|
||||
#define _strnicmp strncasecmp
|
||||
#define _strdup strdup
|
||||
#endif
|
||||
|
||||
#ifdef AUDIO_OAL
|
||||
/*
|
||||
* Init call
|
||||
@@ -47,8 +41,8 @@ ALDeviceList::ALDeviceList()
|
||||
defaultDeviceIndex = 0;
|
||||
|
||||
if (alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT")) {
|
||||
devices = (char *)alcGetString(NULL, ALC_DEVICE_SPECIFIER);
|
||||
defaultDeviceName = (char *)alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER);
|
||||
devices = (char *)alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER);
|
||||
defaultDeviceName = (char *)alcGetString(NULL, ALC_DEFAULT_ALL_DEVICES_SPECIFIER);
|
||||
|
||||
index = 0;
|
||||
// go through device list (each device terminated with a single NULL, list terminated with double NULL)
|
||||
@@ -62,17 +56,11 @@ ALDeviceList::ALDeviceList()
|
||||
if (context) {
|
||||
alcMakeContextCurrent(context);
|
||||
// if new actual device name isn't already in the list, then add it...
|
||||
actualDeviceName = alcGetString(device, ALC_DEVICE_SPECIFIER);
|
||||
bool bNewName = true;
|
||||
for (unsigned int i = 0; i < GetNumDevices(); i++) {
|
||||
if (strcmp(GetDeviceName(i), actualDeviceName) == 0) {
|
||||
bNewName = false;
|
||||
}
|
||||
}
|
||||
if ((bNewName) && (actualDeviceName != NULL) && (strlen(actualDeviceName) > 0)) {
|
||||
ALDEVICEINFO ALDeviceInfo;
|
||||
actualDeviceName = alcGetString(device, ALC_ALL_DEVICES_SPECIFIER);
|
||||
if ((actualDeviceName != NULL) && (strlen(actualDeviceName) > 0)) {
|
||||
ALDEVICEINFO &ALDeviceInfo = aDeviceInfo[nNumOfDevices++];
|
||||
ALDeviceInfo.bSelected = true;
|
||||
ALDeviceInfo.strDeviceName = _strdup(actualDeviceName);
|
||||
ALDeviceInfo.SetName(actualDeviceName);
|
||||
alcGetIntegerv(device, ALC_MAJOR_VERSION, sizeof(int), &ALDeviceInfo.iMajorVersion);
|
||||
alcGetIntegerv(device, ALC_MINOR_VERSION, sizeof(int), &ALDeviceInfo.iMinorVersion);
|
||||
|
||||
@@ -105,8 +93,6 @@ ALDeviceList::ALDeviceList()
|
||||
|
||||
// Get Source Count
|
||||
ALDeviceInfo.uiSourceCount = GetMaxNumSources();
|
||||
|
||||
aDeviceInfo[nNumOfDevices++] = ALDeviceInfo;
|
||||
}
|
||||
alcMakeContextCurrent(NULL);
|
||||
alcDestroyContext(context);
|
||||
|
||||
@@ -21,7 +21,7 @@ enum
|
||||
};
|
||||
|
||||
struct ALDEVICEINFO {
|
||||
const char *strDeviceName;
|
||||
char *strDeviceName;
|
||||
int iMajorVersion;
|
||||
int iMinorVersion;
|
||||
unsigned int uiSourceCount;
|
||||
@@ -33,6 +33,19 @@ struct ALDEVICEINFO {
|
||||
strDeviceName = NULL;
|
||||
Extensions = 0;
|
||||
}
|
||||
|
||||
~ALDEVICEINFO()
|
||||
{
|
||||
delete[] strDeviceName;
|
||||
strDeviceName = NULL;
|
||||
}
|
||||
|
||||
void SetName(const char *name)
|
||||
{
|
||||
if(strDeviceName) delete[] strDeviceName;
|
||||
strDeviceName = new char[strlen(name) + 1];
|
||||
strcpy(strDeviceName, name);
|
||||
}
|
||||
};
|
||||
|
||||
typedef ALDEVICEINFO *LPALDEVICEINFO;
|
||||
|
||||
@@ -10,20 +10,22 @@
|
||||
|
||||
extern bool IsFXSupported();
|
||||
|
||||
ALuint alSources[MAXCHANNELS+MAX2DCHANNELS];
|
||||
ALuint alFilters[MAXCHANNELS+MAX2DCHANNELS];
|
||||
ALuint alBuffers[MAXCHANNELS+MAX2DCHANNELS];
|
||||
ALuint alSources[NUM_CHANNELS];
|
||||
ALuint alFilters[NUM_CHANNELS];
|
||||
ALuint alBuffers[NUM_CHANNELS];
|
||||
bool bChannelsCreated = false;
|
||||
|
||||
int32 CChannel::channelsThatNeedService = 0;
|
||||
|
||||
uint8 tempStereoBuffer[PED_BLOCKSIZE * 2];
|
||||
|
||||
void
|
||||
CChannel::InitChannels()
|
||||
{
|
||||
alGenSources(MAXCHANNELS+MAX2DCHANNELS, alSources);
|
||||
alGenBuffers(MAXCHANNELS+MAX2DCHANNELS, alBuffers);
|
||||
alGenSources(NUM_CHANNELS, alSources);
|
||||
alGenBuffers(NUM_CHANNELS, alBuffers);
|
||||
if (IsFXSupported())
|
||||
alGenFilters(MAXCHANNELS + MAX2DCHANNELS, alFilters);
|
||||
alGenFilters(NUM_CHANNELS, alFilters);
|
||||
bChannelsCreated = true;
|
||||
}
|
||||
|
||||
@@ -32,13 +34,13 @@ CChannel::DestroyChannels()
|
||||
{
|
||||
if (bChannelsCreated)
|
||||
{
|
||||
alDeleteSources(MAXCHANNELS + MAX2DCHANNELS, alSources);
|
||||
alDeleteSources(NUM_CHANNELS, alSources);
|
||||
memset(alSources, 0, sizeof(alSources));
|
||||
alDeleteBuffers(MAXCHANNELS + MAX2DCHANNELS, alBuffers);
|
||||
alDeleteBuffers(NUM_CHANNELS, alBuffers);
|
||||
memset(alBuffers, 0, sizeof(alBuffers));
|
||||
if (IsFXSupported())
|
||||
{
|
||||
alDeleteFilters(MAXCHANNELS + MAX2DCHANNELS, alFilters);
|
||||
alDeleteFilters(NUM_CHANNELS, alFilters);
|
||||
memset(alFilters, 0, sizeof(alFilters));
|
||||
}
|
||||
bChannelsCreated = false;
|
||||
@@ -50,6 +52,7 @@ CChannel::CChannel()
|
||||
{
|
||||
Data = nil;
|
||||
DataSize = 0;
|
||||
bIs2D = false;
|
||||
SetDefault();
|
||||
}
|
||||
|
||||
@@ -90,6 +93,7 @@ void CChannel::Init(uint32 _id, bool Is2D)
|
||||
|
||||
if ( Is2D )
|
||||
{
|
||||
bIs2D = true;
|
||||
alSource3f(alSources[id], AL_POSITION, 0.0f, 0.0f, 0.0f);
|
||||
alSourcef(alSources[id], AL_GAIN, 1.0f);
|
||||
}
|
||||
@@ -113,7 +117,20 @@ void CChannel::Start()
|
||||
if ( !HasSource() ) return;
|
||||
if ( !Data ) return;
|
||||
|
||||
alBufferData(alBuffers[id], AL_FORMAT_MONO16, Data, DataSize, Frequency);
|
||||
if ( bIs2D )
|
||||
{
|
||||
// convert mono data to stereo
|
||||
int16 *monoData = (int16*)Data;
|
||||
int16 *stereoData = (int16*)tempStereoBuffer;
|
||||
for (size_t i = 0; i < DataSize / 2; i++)
|
||||
{
|
||||
*(stereoData++) = *monoData;
|
||||
*(stereoData++) = *(monoData++);
|
||||
}
|
||||
alBufferData(alBuffers[id], AL_FORMAT_STEREO16, tempStereoBuffer, DataSize * 2, Frequency);
|
||||
}
|
||||
else
|
||||
alBufferData(alBuffers[id], AL_FORMAT_MONO16, Data, DataSize, Frequency);
|
||||
if ( LoopPoints[0] != 0 && LoopPoints[0] != -1 )
|
||||
alBufferiv(alBuffers[id], AL_LOOP_POINTS_SOFT, LoopPoints);
|
||||
alSourcei(alSources[id], AL_BUFFER, alBuffers[id]);
|
||||
|
||||
@@ -20,6 +20,7 @@ class CChannel
|
||||
int32 LoopCount;
|
||||
ALint LoopPoints[2];
|
||||
ALint LastProcessedOffset;
|
||||
bool bIs2D;
|
||||
public:
|
||||
static int32 channelsThatNeedService;
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
#include "common.h"
|
||||
|
||||
#ifdef AUDIO_OAL
|
||||
#include "stream.h"
|
||||
#include "sampman.h"
|
||||
|
||||
#if defined _MSC_VER && !defined CMAKE_NO_AUTOLINK
|
||||
#ifdef AUDIO_OAL_USE_SNDFILE
|
||||
@@ -22,6 +20,29 @@
|
||||
#include <opusfile.h>
|
||||
#endif
|
||||
|
||||
#include <queue>
|
||||
#include <utility>
|
||||
|
||||
#ifdef MULTITHREADED_AUDIO
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include "MusicManager.h"
|
||||
#include "stream.h"
|
||||
|
||||
std::thread gAudioThread;
|
||||
std::mutex gAudioThreadQueueMutex;
|
||||
std::condition_variable gAudioThreadCv;
|
||||
bool gAudioThreadTerm = false;
|
||||
std::queue<CStream*> gStreamsToProcess; // values are not unique, we will handle that ourself
|
||||
std::queue<std::pair<IDecoder*, void*>> gStreamsToClose;
|
||||
#else
|
||||
#include "stream.h"
|
||||
#endif
|
||||
|
||||
#include "sampman.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#include "crossplatform.h"
|
||||
#endif
|
||||
@@ -39,6 +60,10 @@ class CSortStereoBuffer
|
||||
{
|
||||
uint16* PcmBuf;
|
||||
size_t BufSize;
|
||||
//#ifdef MULTITHREADED_AUDIO
|
||||
// std::mutex Mutex;
|
||||
//#endif
|
||||
|
||||
public:
|
||||
CSortStereoBuffer() : PcmBuf(nil), BufSize(0) {}
|
||||
~CSortStereoBuffer()
|
||||
@@ -65,6 +90,9 @@ public:
|
||||
|
||||
void SortStereo(void* buf, size_t size)
|
||||
{
|
||||
//#ifdef MULTITHREADED_AUDIO
|
||||
// std::lock_guard<std::mutex> lock(Mutex);
|
||||
//#endif
|
||||
uint16* InBuf = (uint16*)buf;
|
||||
uint16* OutBuf = GetBuffer(size);
|
||||
|
||||
@@ -134,7 +162,7 @@ public:
|
||||
else
|
||||
StepIndex--;
|
||||
|
||||
StepIndex = clamp(StepIndex, 0, 88);
|
||||
StepIndex = Clamp(StepIndex, 0, 88);
|
||||
|
||||
int delta = step >> 3;
|
||||
if (adpcm & 1) delta += step >> 2;
|
||||
@@ -143,7 +171,7 @@ public:
|
||||
if (adpcm & 8) delta = -delta;
|
||||
|
||||
int newSample = Sample + delta;
|
||||
Sample = clamp(newSample, -32768, 32767);
|
||||
Sample = Clamp(newSample, -32768, 32767);
|
||||
return Sample;
|
||||
}
|
||||
};
|
||||
@@ -279,6 +307,10 @@ public:
|
||||
#undef CLOSE_ON_ERROR
|
||||
}
|
||||
|
||||
void FileOpen()
|
||||
{
|
||||
}
|
||||
|
||||
~CWavFile()
|
||||
{
|
||||
Close();
|
||||
@@ -289,6 +321,7 @@ public:
|
||||
return m_bIsOpen;
|
||||
}
|
||||
|
||||
|
||||
uint32 GetSampleSize()
|
||||
{
|
||||
return sizeof(uint16);
|
||||
@@ -405,6 +438,10 @@ public:
|
||||
m_pfSound = sf_open(path, SFM_READ, &m_soundInfo);
|
||||
}
|
||||
|
||||
void FileOpen()
|
||||
{
|
||||
}
|
||||
|
||||
~CSndFile()
|
||||
{
|
||||
if ( m_pfSound )
|
||||
@@ -464,8 +501,6 @@ public:
|
||||
#endif
|
||||
|
||||
#ifdef AUDIO_OAL_USE_MPG123
|
||||
// fuzzy seek eliminates stutter when playing ADF but spams errors a lot (nothing breaks though)
|
||||
#define MP3_USE_FUZZY_SEEK
|
||||
|
||||
class CMP3File : public IDecoder
|
||||
{
|
||||
@@ -474,43 +509,58 @@ protected:
|
||||
bool m_bOpened;
|
||||
uint32 m_nRate;
|
||||
uint32 m_nChannels;
|
||||
|
||||
const char* m_pPath;
|
||||
bool m_bFileNotOpenedYet;
|
||||
|
||||
CMP3File() :
|
||||
m_pMH(nil),
|
||||
m_bOpened(false),
|
||||
m_nRate(0),
|
||||
m_bFileNotOpenedYet(false),
|
||||
m_nChannels(0) {}
|
||||
public:
|
||||
CMP3File(const char *path) :
|
||||
m_pMH(nil),
|
||||
m_bOpened(false),
|
||||
m_nRate(0),
|
||||
m_nChannels(0)
|
||||
m_nChannels(0),
|
||||
m_pPath(path),
|
||||
m_bFileNotOpenedYet(false)
|
||||
{
|
||||
m_pMH = mpg123_new(nil, nil);
|
||||
if ( m_pMH )
|
||||
{
|
||||
#ifdef MP3_USE_FUZZY_SEEK
|
||||
mpg123_param(m_pMH, MPG123_FLAGS, MPG123_FUZZY | MPG123_SEEKBUFFER | MPG123_GAPLESS | MPG123_QUIET, 0.0);
|
||||
#endif
|
||||
long rate = 0;
|
||||
int channels = 0;
|
||||
int encoding = 0;
|
||||
|
||||
m_bOpened = mpg123_open(m_pMH, path) == MPG123_OK
|
||||
&& mpg123_getformat(m_pMH, &rate, &channels, &encoding) == MPG123_OK;
|
||||
mpg123_param(m_pMH, MPG123_FLAGS, MPG123_SEEKBUFFER | MPG123_GAPLESS, 0.0);
|
||||
|
||||
m_nRate = rate;
|
||||
m_nChannels = channels;
|
||||
|
||||
if ( IsOpened() )
|
||||
{
|
||||
mpg123_format_none(m_pMH);
|
||||
mpg123_format(m_pMH, rate, channels, encoding);
|
||||
}
|
||||
m_bOpened = true;
|
||||
m_bFileNotOpenedYet = true;
|
||||
// It's possible to move this to audioFileOpsThread(), but effect isn't noticable + probably not compatible with our current cutscene audio handling
|
||||
#if 1
|
||||
FileOpen();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void FileOpen()
|
||||
{
|
||||
if(!m_bFileNotOpenedYet) return;
|
||||
|
||||
long rate = 0;
|
||||
int channels = 0;
|
||||
int encoding = 0;
|
||||
m_bOpened = mpg123_open(m_pMH, m_pPath) == MPG123_OK
|
||||
&& mpg123_getformat(m_pMH, &rate, &channels, &encoding) == MPG123_OK;
|
||||
|
||||
m_nRate = rate;
|
||||
m_nChannels = channels;
|
||||
|
||||
if(IsOpened()) {
|
||||
mpg123_format_none(m_pMH);
|
||||
mpg123_format(m_pMH, rate, channels, encoding);
|
||||
}
|
||||
m_bFileNotOpenedYet = false;
|
||||
}
|
||||
|
||||
~CMP3File()
|
||||
{
|
||||
if ( m_pMH )
|
||||
@@ -533,7 +583,7 @@ public:
|
||||
|
||||
uint32 GetSampleCount()
|
||||
{
|
||||
if ( !IsOpened() ) return 0;
|
||||
if ( !IsOpened() || m_bFileNotOpenedYet ) return 0;
|
||||
return mpg123_length(m_pMH);
|
||||
}
|
||||
|
||||
@@ -549,19 +599,19 @@ public:
|
||||
|
||||
void Seek(uint32 milliseconds)
|
||||
{
|
||||
if ( !IsOpened() ) return;
|
||||
if ( !IsOpened() || m_bFileNotOpenedYet ) return;
|
||||
mpg123_seek(m_pMH, ms2samples(milliseconds), SEEK_SET);
|
||||
}
|
||||
|
||||
uint32 Tell()
|
||||
{
|
||||
if ( !IsOpened() ) return 0;
|
||||
if ( !IsOpened() || m_bFileNotOpenedYet ) return 0;
|
||||
return samples2ms(mpg123_tell(m_pMH));
|
||||
}
|
||||
|
||||
uint32 Decode(void *buffer)
|
||||
{
|
||||
if ( !IsOpened() ) return 0;
|
||||
if ( !IsOpened() || m_bFileNotOpenedYet ) return 0;
|
||||
|
||||
size_t size;
|
||||
int err = mpg123_read(m_pMH, (unsigned char *)buffer, GetBufferSize(), &size);
|
||||
@@ -600,27 +650,42 @@ public:
|
||||
m_pMH = mpg123_new(nil, nil);
|
||||
if (m_pMH)
|
||||
{
|
||||
#ifdef MP3_USE_FUZZY_SEEK
|
||||
mpg123_param(m_pMH, MPG123_FLAGS, MPG123_FUZZY | MPG123_SEEKBUFFER | MPG123_GAPLESS | MPG123_QUIET, 0.0);
|
||||
mpg123_param(m_pMH, MPG123_FLAGS, MPG123_SEEKBUFFER | MPG123_GAPLESS, 0.0);
|
||||
|
||||
m_bOpened = true;
|
||||
m_bFileNotOpenedYet = true;
|
||||
m_pPath = path;
|
||||
// It's possible to move this to audioFileOpsThread(), but effect isn't noticable + probably not compatible with our current cutscene audio handling
|
||||
#if 1
|
||||
FileOpen();
|
||||
#endif
|
||||
long rate = 0;
|
||||
int channels = 0;
|
||||
int encoding = 0;
|
||||
|
||||
FILE* f = fopen(path, "rb");
|
||||
|
||||
m_bOpened = mpg123_replace_reader_handle(m_pMH, r_read, r_seek, r_close) == MPG123_OK
|
||||
&& mpg123_open_handle(m_pMH, f) == MPG123_OK && mpg123_getformat(m_pMH, &rate, &channels, &encoding) == MPG123_OK;
|
||||
m_nRate = rate;
|
||||
m_nChannels = channels;
|
||||
|
||||
if (IsOpened())
|
||||
{
|
||||
mpg123_format_none(m_pMH);
|
||||
mpg123_format(m_pMH, rate, channels, encoding);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FileOpen()
|
||||
{
|
||||
if(!m_bFileNotOpenedYet) return;
|
||||
|
||||
long rate = 0;
|
||||
int channels = 0;
|
||||
int encoding = 0;
|
||||
|
||||
FILE *f = fopen(m_pPath, "rb");
|
||||
|
||||
m_bOpened = f && mpg123_replace_reader_handle(m_pMH, r_read, r_seek, r_close) == MPG123_OK
|
||||
&& mpg123_open_handle(m_pMH, f) == MPG123_OK && mpg123_getformat(m_pMH, &rate, &channels, &encoding) == MPG123_OK;
|
||||
|
||||
m_nRate = rate;
|
||||
m_nChannels = channels;
|
||||
|
||||
if(IsOpened()) {
|
||||
mpg123_format_none(m_pMH);
|
||||
mpg123_format(m_pMH, rate, channels, encoding);
|
||||
}
|
||||
|
||||
m_bFileNotOpenedYet = false;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -651,7 +716,7 @@ public:
|
||||
static short quantize(double sample)
|
||||
{
|
||||
int a = int(sample + 0.5);
|
||||
return short(clamp(a, -32768, 32767));
|
||||
return short(Clamp(a, -32768, 32767));
|
||||
}
|
||||
|
||||
void Decode(void* _inbuf, int16* _outbuf, size_t size)
|
||||
@@ -740,6 +805,10 @@ public:
|
||||
m_ppVagBuffers[i] = new uint8[VB_BLOCK_SIZE];
|
||||
}
|
||||
|
||||
void FileOpen()
|
||||
{
|
||||
}
|
||||
|
||||
~CVbFile()
|
||||
{
|
||||
if (m_pFile)
|
||||
@@ -892,6 +961,10 @@ public:
|
||||
m_bOpened = true;
|
||||
}
|
||||
}
|
||||
|
||||
void FileOpen()
|
||||
{
|
||||
}
|
||||
|
||||
~COpusFile()
|
||||
{
|
||||
@@ -957,11 +1030,173 @@ public:
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
// For multi-thread: Someone always acquire stream's mutex before entering here
|
||||
void
|
||||
CStream::BuffersShouldBeFilled()
|
||||
{
|
||||
#ifdef MULTITHREADED_AUDIO
|
||||
if (MusicManager.m_nMusicMode != MUSICMODE_CUTSCENE) {
|
||||
std::queue<std::pair<ALuint, ALuint>> tempQueue;
|
||||
for(int i = 0; i < NUM_STREAMBUFFERS / 2; i++) {
|
||||
tempQueue.push(std::pair<ALuint, ALuint>(m_alBuffers[i * 2], m_alBuffers[i * 2 + 1]));
|
||||
}
|
||||
m_fillBuffers.swap(tempQueue);
|
||||
|
||||
FlagAsToBeProcessed();
|
||||
|
||||
m_bActive = true; // to allow Update() to queue the filled buffers & play
|
||||
return;
|
||||
}
|
||||
std::queue<std::pair<ALuint, ALuint>>().swap(m_fillBuffers);
|
||||
#endif
|
||||
if ( FillBuffers() != 0 )
|
||||
{
|
||||
SetPlay(true);
|
||||
}
|
||||
}
|
||||
|
||||
// returns whether it's queued (not on multi-thread)
|
||||
bool
|
||||
CStream::BufferShouldBeFilledAndQueued(std::pair<ALuint, ALuint>* bufs)
|
||||
{
|
||||
#ifdef MULTITHREADED_AUDIO
|
||||
if (MusicManager.m_nMusicMode != MUSICMODE_CUTSCENE)
|
||||
m_fillBuffers.push(*bufs);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
ALuint alBuffers[2] = {(*bufs).first, (*bufs).second}; // left - right
|
||||
if (FillBuffer(alBuffers)) {
|
||||
alSourceQueueBuffers(m_pAlSources[0], 1, &alBuffers[0]);
|
||||
alSourceQueueBuffers(m_pAlSources[1], 1, &alBuffers[1]);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef MULTITHREADED_AUDIO
|
||||
void
|
||||
CStream::FlagAsToBeProcessed(bool close)
|
||||
{
|
||||
if (!close && MusicManager.m_nMusicMode == MUSICMODE_CUTSCENE)
|
||||
return;
|
||||
|
||||
gAudioThreadQueueMutex.lock();
|
||||
if (close)
|
||||
gStreamsToClose.push(std::pair<IDecoder*, void*>(m_pSoundFile ? m_pSoundFile : nil, m_pBuffer ? m_pBuffer : nil));
|
||||
else
|
||||
gStreamsToProcess.push(this);
|
||||
|
||||
gAudioThreadQueueMutex.unlock();
|
||||
|
||||
gAudioThreadCv.notify_one();
|
||||
}
|
||||
|
||||
void audioFileOpsThread()
|
||||
{
|
||||
do
|
||||
{
|
||||
CStream *stream;
|
||||
{
|
||||
// Just a semaphore
|
||||
std::unique_lock<std::mutex> queueMutex(gAudioThreadQueueMutex);
|
||||
gAudioThreadCv.wait(queueMutex, [] { return gStreamsToProcess.size() > 0 || gStreamsToClose.size() > 0 || gAudioThreadTerm; });
|
||||
if (gAudioThreadTerm)
|
||||
return;
|
||||
|
||||
if (!gStreamsToClose.empty()) {
|
||||
auto streamToClose = gStreamsToClose.front();
|
||||
gStreamsToClose.pop();
|
||||
if (streamToClose.first) { // pSoundFile
|
||||
delete streamToClose.first;
|
||||
}
|
||||
|
||||
if (streamToClose.second) { // pBuffer
|
||||
free(streamToClose.second);
|
||||
}
|
||||
}
|
||||
|
||||
if (!gStreamsToProcess.empty()) {
|
||||
stream = gStreamsToProcess.front();
|
||||
gStreamsToProcess.pop();
|
||||
} else
|
||||
continue;
|
||||
}
|
||||
|
||||
std::unique_lock<std::mutex> lock(stream->m_mutex);
|
||||
|
||||
std::pair<ALuint, ALuint> buffers, *lastBufAddr;
|
||||
bool insertBufsAfterCheck = false;
|
||||
|
||||
do {
|
||||
if (!stream->IsOpened()) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (stream->m_bReset)
|
||||
break;
|
||||
|
||||
// We gave up this idea for now
|
||||
/*
|
||||
stream->m_pSoundFile->FileOpen();
|
||||
|
||||
// Deffered allocation, do it now
|
||||
if (stream->m_pBuffer == nil) {
|
||||
stream->m_pBuffer = malloc(stream->m_pSoundFile->GetBufferSize());
|
||||
ASSERT(stream->m_pBuffer != nil);
|
||||
}
|
||||
*/
|
||||
|
||||
if (stream->m_bDoSeek) {
|
||||
stream->m_bDoSeek = false;
|
||||
int pos = stream->m_SeekPos;
|
||||
lock.unlock();
|
||||
stream->m_pSoundFile->Seek(pos);
|
||||
lock.lock();
|
||||
|
||||
continue; // let's do the checks again, make sure we didn't miss anything while Seeking
|
||||
}
|
||||
|
||||
if (insertBufsAfterCheck) {
|
||||
stream->m_queueBuffers.push(buffers);
|
||||
insertBufsAfterCheck = false;
|
||||
}
|
||||
|
||||
if (!stream->m_fillBuffers.empty()) {
|
||||
lastBufAddr = &stream->m_fillBuffers.front();
|
||||
buffers = *lastBufAddr;
|
||||
lock.unlock();
|
||||
|
||||
ALuint alBuffers[2] = {buffers.first, buffers.second}; // left - right
|
||||
bool filled = stream->FillBuffer(alBuffers);
|
||||
|
||||
lock.lock();
|
||||
|
||||
// Make sure queue isn't touched after we released mutex
|
||||
if (!stream->m_fillBuffers.empty() && lastBufAddr == &stream->m_fillBuffers.front()) {
|
||||
stream->m_fillBuffers.pop();
|
||||
if (filled)
|
||||
insertBufsAfterCheck = true; // Also make sure stream's properties aren't changed. So make one more pass, and push it to m_queueBuffers only if it pass checks again.
|
||||
}
|
||||
} else
|
||||
break;
|
||||
|
||||
} while (true);
|
||||
|
||||
} while(true);
|
||||
}
|
||||
#endif
|
||||
|
||||
void CStream::Initialise()
|
||||
{
|
||||
#ifdef AUDIO_OAL_USE_MPG123
|
||||
mpg123_init();
|
||||
#endif
|
||||
#ifdef MULTITHREADED_AUDIO
|
||||
gAudioThread = std::thread(audioFileOpsThread);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CStream::Terminate()
|
||||
@@ -969,14 +1204,27 @@ void CStream::Terminate()
|
||||
#ifdef AUDIO_OAL_USE_MPG123
|
||||
mpg123_exit();
|
||||
#endif
|
||||
#ifdef MULTITHREADED_AUDIO
|
||||
gAudioThreadQueueMutex.lock();
|
||||
gAudioThreadTerm = true;
|
||||
gAudioThreadQueueMutex.unlock();
|
||||
|
||||
gAudioThreadCv.notify_one();
|
||||
gAudioThread.join();
|
||||
#endif
|
||||
}
|
||||
|
||||
CStream::CStream(char *filename, ALuint *sources, ALuint (&buffers)[NUM_STREAMBUFFERS], uint32 overrideSampleRate) :
|
||||
CStream::CStream(ALuint *sources, ALuint (&buffers)[NUM_STREAMBUFFERS]) :
|
||||
m_pAlSources(sources),
|
||||
m_alBuffers(buffers),
|
||||
m_pBuffer(nil),
|
||||
m_bPaused(false),
|
||||
m_bActive(false),
|
||||
#ifdef MULTITHREADED_AUDIO
|
||||
m_bIExist(false),
|
||||
m_bDoSeek(false),
|
||||
m_SeekPos(0),
|
||||
#endif
|
||||
m_pSoundFile(nil),
|
||||
m_bReset(false),
|
||||
m_nVolume(0),
|
||||
@@ -985,6 +1233,27 @@ CStream::CStream(char *filename, ALuint *sources, ALuint (&buffers)[NUM_STREAMBU
|
||||
m_nLoopCount(1)
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
bool CStream::Open(const char* filename, uint32 overrideSampleRate)
|
||||
{
|
||||
if (IsOpened()) return false;
|
||||
|
||||
#ifdef MULTITHREADED_AUDIO
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
|
||||
m_bDoSeek = false;
|
||||
m_SeekPos = 0;
|
||||
#endif
|
||||
|
||||
m_bPaused = false;
|
||||
m_bActive = false;
|
||||
m_bReset = false;
|
||||
m_nVolume = 0;
|
||||
m_nPan = 0;
|
||||
m_nPosBeforeReset = 0;
|
||||
m_nLoopCount = 1;
|
||||
|
||||
// Be case-insensitive on linux (from https://github.com/OneSadCookie/fcaseopen/)
|
||||
#if !defined(_WIN32)
|
||||
char *real = casepath(filename);
|
||||
@@ -1021,44 +1290,67 @@ CStream::CStream(char *filename, ALuint *sources, ALuint (&buffers)[NUM_STREAMBU
|
||||
else
|
||||
m_pSoundFile = nil;
|
||||
|
||||
if ( IsOpened() )
|
||||
if ( m_pSoundFile && m_pSoundFile->IsOpened() )
|
||||
{
|
||||
m_pBuffer = malloc(m_pSoundFile->GetBufferSize());
|
||||
ASSERT(m_pBuffer!=nil);
|
||||
|
||||
DEV("AvgSamplesPerSec: %d\n", m_pSoundFile->GetAvgSamplesPerSec());
|
||||
DEV("SampleCount: %d\n", m_pSoundFile->GetSampleCount());
|
||||
DEV("SampleRate: %d\n", m_pSoundFile->GetSampleRate());
|
||||
DEV("Channels: %d\n", m_pSoundFile->GetChannels());
|
||||
DEV("Buffer Samples: %d\n", m_pSoundFile->GetBufferSamples());
|
||||
DEV("Buffer sec: %f\n", (float(m_pSoundFile->GetBufferSamples()) / float(m_pSoundFile->GetChannels())/ float(m_pSoundFile->GetSampleRate())));
|
||||
DEV("Length MS: %02d:%02d\n", (m_pSoundFile->GetLength() / 1000) / 60, (m_pSoundFile->GetLength() / 1000) % 60);
|
||||
|
||||
return;
|
||||
uint32 bufSize = m_pSoundFile->GetBufferSize();
|
||||
if(bufSize != 0) { // Otherwise it's deferred
|
||||
m_pBuffer = malloc(bufSize);
|
||||
ASSERT(m_pBuffer != nil);
|
||||
|
||||
DEV("AvgSamplesPerSec: %d\n", m_pSoundFile->GetAvgSamplesPerSec());
|
||||
DEV("SampleCount: %d\n", m_pSoundFile->GetSampleCount());
|
||||
DEV("SampleRate: %d\n", m_pSoundFile->GetSampleRate());
|
||||
DEV("Channels: %d\n", m_pSoundFile->GetChannels());
|
||||
DEV("Buffer Samples: %d\n", m_pSoundFile->GetBufferSamples());
|
||||
DEV("Buffer sec: %f\n", (float(m_pSoundFile->GetBufferSamples()) / float(m_pSoundFile->GetChannels())/ float(m_pSoundFile->GetSampleRate())));
|
||||
DEV("Length MS: %02d:%02d\n", (m_pSoundFile->GetLength() / 1000) / 60, (m_pSoundFile->GetLength() / 1000) % 60);
|
||||
}
|
||||
#ifdef MULTITHREADED_AUDIO
|
||||
m_bIExist = true;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
CStream::~CStream()
|
||||
{
|
||||
Delete();
|
||||
assert(!IsOpened());
|
||||
}
|
||||
|
||||
void CStream::Delete()
|
||||
void CStream::Close()
|
||||
{
|
||||
if(!IsOpened()) return;
|
||||
|
||||
#ifdef MULTITHREADED_AUDIO
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
Stop();
|
||||
ClearBuffers();
|
||||
m_bIExist = false;
|
||||
std::queue<std::pair<ALuint, ALuint>>().swap(m_fillBuffers);
|
||||
tsQueue<std::pair<ALuint, ALuint>>().swapNts(m_queueBuffers); // TSness not required, mutex is acquired
|
||||
}
|
||||
|
||||
FlagAsToBeProcessed(true);
|
||||
#else
|
||||
|
||||
Stop();
|
||||
ClearBuffers();
|
||||
|
||||
|
||||
if ( m_pSoundFile )
|
||||
{
|
||||
delete m_pSoundFile;
|
||||
m_pSoundFile = nil;
|
||||
}
|
||||
|
||||
|
||||
if ( m_pBuffer )
|
||||
{
|
||||
free(m_pBuffer);
|
||||
m_pBuffer = nil;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool CStream::HasSource()
|
||||
@@ -1066,9 +1358,14 @@ bool CStream::HasSource()
|
||||
return (m_pAlSources[0] != AL_NONE) && (m_pAlSources[1] != AL_NONE);
|
||||
}
|
||||
|
||||
// m_bIExist only written in main thread, thus mutex is not needed on main thread
|
||||
bool CStream::IsOpened()
|
||||
{
|
||||
#ifdef MULTITHREADED_AUDIO
|
||||
return m_bIExist;
|
||||
#else
|
||||
return m_pSoundFile && m_pSoundFile->IsOpened();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool CStream::IsPlaying()
|
||||
@@ -1082,6 +1379,14 @@ bool CStream::IsPlaying()
|
||||
alGetSourcei(m_pAlSources[1], AL_SOURCE_STATE, &sourceState[1]);
|
||||
if (sourceState[0] == AL_PLAYING || sourceState[1] == AL_PLAYING)
|
||||
return true;
|
||||
|
||||
#ifdef MULTITHREADED_AUDIO
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
// Streams are designed in such a way that m_fillBuffers and m_queueBuffers will be *always* filled if audio is playing, and mutex is acquired
|
||||
if (!m_fillBuffers.empty() || !m_queueBuffers.emptyNts())
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -1143,10 +1448,10 @@ void CStream::SetVolume(uint32 nVol)
|
||||
|
||||
void CStream::SetPan(uint8 nPan)
|
||||
{
|
||||
m_nPan = clamp((int8)nPan - 63, 0, 63);
|
||||
m_nPan = Clamp((int8)nPan - 63, 0, 63);
|
||||
SetPosition(0, (m_nPan - 63) / 64.0f, 0.0f, Sqrt(1.0f - SQR((m_nPan - 63) / 64.0f)));
|
||||
|
||||
m_nPan = clamp((int8)nPan + 64, 64, 127);
|
||||
m_nPan = Clamp((int8)nPan + 64, 64, 127);
|
||||
SetPosition(1, (m_nPan - 63) / 64.0f, 0.0f, Sqrt(1.0f - SQR((m_nPan - 63) / 64.0f)));
|
||||
|
||||
m_nPan = nPan;
|
||||
@@ -1156,8 +1461,24 @@ void CStream::SetPan(uint8 nPan)
|
||||
void CStream::SetPosMS(uint32 nPos)
|
||||
{
|
||||
if ( !IsOpened() ) return;
|
||||
m_pSoundFile->Seek(nPos);
|
||||
|
||||
#ifdef MULTITHREADED_AUDIO
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
std::queue<std::pair<ALuint, ALuint>>().swap(m_fillBuffers);
|
||||
tsQueue<std::pair<ALuint, ALuint>>().swapNts(m_queueBuffers); // TSness not required, second thread always access it when stream mutex acquired
|
||||
|
||||
if (MusicManager.m_nMusicMode != MUSICMODE_CUTSCENE) {
|
||||
m_bDoSeek = true;
|
||||
m_SeekPos = nPos;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
m_pSoundFile->Seek(nPos);
|
||||
}
|
||||
ClearBuffers();
|
||||
|
||||
// adding to gStreamsToProcess not needed, someone always calls Start() / BuffersShouldBeFilled() after SetPosMS
|
||||
}
|
||||
|
||||
uint32 CStream::GetPosMS()
|
||||
@@ -1165,10 +1486,16 @@ uint32 CStream::GetPosMS()
|
||||
if ( !HasSource() ) return 0;
|
||||
if ( !IsOpened() ) return 0;
|
||||
|
||||
// Deferred init causes division by zero
|
||||
if (m_pSoundFile->GetChannels() == 0)
|
||||
return 0;
|
||||
|
||||
ALint offset;
|
||||
//alGetSourcei(m_alSource, AL_SAMPLE_OFFSET, &offset);
|
||||
alGetSourcei(m_pAlSources[0], AL_BYTE_OFFSET, &offset);
|
||||
|
||||
//std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
return m_pSoundFile->Tell()
|
||||
- m_pSoundFile->samples2ms(m_pSoundFile->GetBufferSamples() * (NUM_STREAMBUFFERS/2-1)) / m_pSoundFile->GetChannels()
|
||||
+ m_pSoundFile->samples2ms(offset/m_pSoundFile->GetSampleSize()) / m_pSoundFile->GetChannels();
|
||||
@@ -1182,6 +1509,7 @@ uint32 CStream::GetLengthMS()
|
||||
|
||||
bool CStream::FillBuffer(ALuint *alBuffer)
|
||||
{
|
||||
#ifndef MULTITHREADED_AUDIO
|
||||
if ( !HasSource() )
|
||||
return false;
|
||||
if ( !IsOpened() )
|
||||
@@ -1190,13 +1518,14 @@ bool CStream::FillBuffer(ALuint *alBuffer)
|
||||
return false;
|
||||
if ( !(alBuffer[1] != AL_NONE && alIsBuffer(alBuffer[1])) )
|
||||
return false;
|
||||
|
||||
#endif
|
||||
|
||||
uint32 size = m_pSoundFile->Decode(m_pBuffer);
|
||||
if( size == 0 )
|
||||
return false;
|
||||
|
||||
uint32 channelSize = size / m_pSoundFile->GetChannels();
|
||||
|
||||
uint32 channelSize = size / m_pSoundFile->GetChannels();
|
||||
|
||||
alBufferData(alBuffer[0], AL_FORMAT_MONO16, m_pBuffer, channelSize, m_pSoundFile->GetSampleRate());
|
||||
// TODO: use just one buffer if we play mono
|
||||
if (m_pSoundFile->GetChannels() == 1)
|
||||
@@ -1206,6 +1535,26 @@ bool CStream::FillBuffer(ALuint *alBuffer)
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef MULTITHREADED_AUDIO
|
||||
bool CStream::QueueBuffers()
|
||||
{
|
||||
bool buffersQueued = false;
|
||||
std::pair<ALuint, ALuint> buffers;
|
||||
while (m_queueBuffers.peekPop(&buffers)) // beware: m_queueBuffers is tsQueue
|
||||
{
|
||||
ALuint leftBuf = buffers.first;
|
||||
ALuint rightBuf = buffers.second;
|
||||
|
||||
alSourceQueueBuffers(m_pAlSources[0], 1, &leftBuf);
|
||||
alSourceQueueBuffers(m_pAlSources[1], 1, &rightBuf);
|
||||
|
||||
buffersQueued = true;
|
||||
}
|
||||
return buffersQueued;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Only used in single-threaded audio or cutscene audio
|
||||
int32 CStream::FillBuffers()
|
||||
{
|
||||
int32 i = 0;
|
||||
@@ -1235,17 +1584,33 @@ void CStream::ClearBuffers()
|
||||
alSourceUnqueueBuffers(m_pAlSources[1], 1, &value);
|
||||
}
|
||||
|
||||
bool CStream::Setup(bool imSureQueueIsEmpty)
|
||||
bool CStream::Setup(bool imSureQueueIsEmpty, bool lock)
|
||||
{
|
||||
if ( IsOpened() )
|
||||
{
|
||||
alSourcei(m_pAlSources[0], AL_LOOPING, AL_FALSE);
|
||||
alSourcei(m_pAlSources[1], AL_LOOPING, AL_FALSE);
|
||||
#ifdef MULTITHREADED_AUDIO
|
||||
if (lock)
|
||||
m_mutex.lock();
|
||||
#endif
|
||||
|
||||
if (!imSureQueueIsEmpty) {
|
||||
SetPlay(false);
|
||||
Stop();
|
||||
ClearBuffers();
|
||||
}
|
||||
#ifdef MULTITHREADED_AUDIO
|
||||
if (MusicManager.m_nMusicMode == MUSICMODE_CUTSCENE) {
|
||||
m_pSoundFile->Seek(0);
|
||||
} else {
|
||||
m_bDoSeek = true;
|
||||
m_SeekPos = 0;
|
||||
}
|
||||
|
||||
if (lock)
|
||||
m_mutex.unlock();
|
||||
#else
|
||||
m_pSoundFile->Seek(0);
|
||||
#endif
|
||||
|
||||
//SetPosition(0.0f, 0.0f, 0.0f);
|
||||
SetPitch(1.0f);
|
||||
//SetPan(m_nPan);
|
||||
@@ -1283,7 +1648,7 @@ void CStream::SetPlay(bool state)
|
||||
{
|
||||
ALint sourceState = AL_STOPPED;
|
||||
alGetSourcei(m_pAlSources[0], AL_SOURCE_STATE, &sourceState);
|
||||
if (sourceState != AL_STOPPED )
|
||||
if (sourceState != AL_STOPPED)
|
||||
alSourceStop(m_pAlSources[0]);
|
||||
|
||||
sourceState = AL_STOPPED;
|
||||
@@ -1298,8 +1663,12 @@ void CStream::SetPlay(bool state)
|
||||
void CStream::Start()
|
||||
{
|
||||
if ( !HasSource() ) return;
|
||||
if ( FillBuffers() != 0 )
|
||||
SetPlay(true);
|
||||
|
||||
#ifdef MULTITHREADED_AUDIO
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
tsQueue<std::pair<ALuint, ALuint>>().swapNts(m_queueBuffers); // TSness not required, second thread always access it when stream mutex acquired
|
||||
#endif
|
||||
BuffersShouldBeFilled();
|
||||
}
|
||||
|
||||
void CStream::Stop()
|
||||
@@ -1321,9 +1690,23 @@ void CStream::Update()
|
||||
|
||||
if ( !m_bPaused )
|
||||
{
|
||||
ALint totalBuffers[2] = { 0, 0 };
|
||||
ALint buffersProcessed[2] = { 0, 0 };
|
||||
|
||||
bool buffersQueuedAndStarted = false;
|
||||
bool buffersQueuedButNotStarted = false;
|
||||
#ifdef MULTITHREADED_AUDIO
|
||||
// Put it in here because we need totalBuffers after queueing to decide when to loop audio
|
||||
if (m_bActive)
|
||||
{
|
||||
buffersQueuedAndStarted = QueueBuffers();
|
||||
if(buffersQueuedAndStarted) {
|
||||
SetPlay(true);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
ALint totalBuffers[2] = {0, 0};
|
||||
ALint buffersProcessed[2] = {0, 0};
|
||||
|
||||
// Relying a lot on left buffer states in here
|
||||
|
||||
do
|
||||
@@ -1335,44 +1718,66 @@ void CStream::Update()
|
||||
alGetSourcei(m_pAlSources[1], AL_BUFFERS_QUEUED, &totalBuffers[1]);
|
||||
alGetSourcei(m_pAlSources[1], AL_BUFFERS_PROCESSED, &buffersProcessed[1]);
|
||||
} while (buffersProcessed[0] != buffersProcessed[1]);
|
||||
|
||||
|
||||
assert(buffersProcessed[0] == buffersProcessed[1]);
|
||||
|
||||
// Correcting OpenAL concepts here:
|
||||
// AL_BUFFERS_QUEUED = Number of *all* buffers in queue, including processed, processing and pending
|
||||
// AL_BUFFERS_PROCESSED = Index of the buffer being processing right now. Buffers coming after that(have greater index) are pending buffers.
|
||||
// which means: totalBuffers[0] - buffersProcessed[0] = pending buffers
|
||||
|
||||
bool buffersRefilled = false;
|
||||
|
||||
|
||||
// We should wait queue to be cleared to loop track, because position calculation relies on queue.
|
||||
if (m_nLoopCount != 1 && m_bActive && totalBuffers[0] == 0)
|
||||
{
|
||||
Setup(true);
|
||||
buffersRefilled = FillBuffers() != 0;
|
||||
if (m_nLoopCount != 0)
|
||||
m_nLoopCount--;
|
||||
#ifdef MULTITHREADED_AUDIO
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
if (m_fillBuffers.empty() && m_queueBuffers.emptyNts()) // we already acquired stream mutex, which is enough for second thread. thus Nts variant
|
||||
#endif
|
||||
{
|
||||
Setup(true, false);
|
||||
BuffersShouldBeFilled(); // will also call SetPlay(true)
|
||||
if (m_nLoopCount != 0)
|
||||
m_nLoopCount--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while( buffersProcessed[0]-- )
|
||||
static std::queue<std::pair<ALuint, ALuint>> tempFillBuffer;
|
||||
|
||||
while ( buffersProcessed[0]-- )
|
||||
{
|
||||
ALuint buffer[2];
|
||||
|
||||
alSourceUnqueueBuffers(m_pAlSources[0], 1, &buffer[0]);
|
||||
alSourceUnqueueBuffers(m_pAlSources[1], 1, &buffer[1]);
|
||||
|
||||
if (m_bActive && FillBuffer(buffer))
|
||||
|
||||
if (m_bActive)
|
||||
{
|
||||
buffersRefilled = true;
|
||||
alSourceQueueBuffers(m_pAlSources[0], 1, &buffer[0]);
|
||||
alSourceQueueBuffers(m_pAlSources[1], 1, &buffer[1]);
|
||||
tempFillBuffer.push(std::pair<ALuint, ALuint>(buffer[0], buffer[1]));
|
||||
}
|
||||
}
|
||||
|
||||
if (m_bActive && buffersProcessed[1])
|
||||
{
|
||||
#ifdef MULTITHREADED_AUDIO
|
||||
m_mutex.lock();
|
||||
#endif
|
||||
while (!tempFillBuffer.empty()) {
|
||||
auto elem = tempFillBuffer.front();
|
||||
tempFillBuffer.pop();
|
||||
buffersQueuedButNotStarted = BufferShouldBeFilledAndQueued(&elem);
|
||||
}
|
||||
#ifdef MULTITHREADED_AUDIO
|
||||
m_mutex.unlock();
|
||||
FlagAsToBeProcessed();
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Two reasons: 1-Source may be starved to audio and stopped itself, 2- We're already waiting it to starve and die for looping track!
|
||||
if (m_bActive && (buffersRefilled || (totalBuffers[1] - buffersProcessed[1] != 0)))
|
||||
// Source may be starved to audio and stopped itself
|
||||
if (m_bActive && !buffersQueuedAndStarted && (buffersQueuedButNotStarted || (totalBuffers[1] - buffersProcessed[1] != 0)))
|
||||
SetPlay(true);
|
||||
}
|
||||
}
|
||||
@@ -1381,28 +1786,45 @@ void CStream::ProviderInit()
|
||||
{
|
||||
if ( m_bReset )
|
||||
{
|
||||
if ( Setup(true) )
|
||||
if ( Setup(true, false) ) // lock not needed, thread can't process streams with m_bReset set
|
||||
{
|
||||
SetPan(m_nPan);
|
||||
SetVolume(m_nVolume);
|
||||
SetLoopCount(m_nLoopCount);
|
||||
SetPosMS(m_nPosBeforeReset);
|
||||
if (m_bActive)
|
||||
FillBuffers();
|
||||
SetPlay(m_bActive);
|
||||
if ( m_bPaused )
|
||||
#ifdef MULTITHREADED_AUDIO
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
#endif
|
||||
if(m_bActive)
|
||||
BuffersShouldBeFilled();
|
||||
|
||||
if (m_bPaused)
|
||||
Pause();
|
||||
|
||||
m_bReset = false;
|
||||
|
||||
} else {
|
||||
#ifdef MULTITHREADED_AUDIO
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
#endif
|
||||
m_bReset = false;
|
||||
}
|
||||
|
||||
m_bReset = false;
|
||||
}
|
||||
}
|
||||
|
||||
void CStream::ProviderTerm()
|
||||
{
|
||||
#ifdef MULTITHREADED_AUDIO
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
// unlike Close() we will reuse this stream, so clearing queues are important.
|
||||
std::queue<std::pair<ALuint, ALuint>>().swap(m_fillBuffers);
|
||||
tsQueue<std::pair<ALuint, ALuint>>().swapNts(m_queueBuffers); // stream mutex is already acquired, thus Nts variant
|
||||
#endif
|
||||
m_bReset = true;
|
||||
m_nPosBeforeReset = GetPosMS();
|
||||
|
||||
|
||||
Stop();
|
||||
ClearBuffers();
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ public:
|
||||
virtual ~IDecoder() { }
|
||||
|
||||
virtual bool IsOpened() = 0;
|
||||
virtual void FileOpen() = 0;
|
||||
|
||||
virtual uint32 GetSampleSize() = 0;
|
||||
virtual uint32 GetSampleCount() = 0;
|
||||
@@ -48,12 +49,70 @@ public:
|
||||
|
||||
uint32 GetLength()
|
||||
{
|
||||
FileOpen(); // abort deferred init, we need length now - game has to cache audio file sizes
|
||||
return float(GetSampleCount()) * 1000.0f / float(GetSampleRate());
|
||||
}
|
||||
|
||||
virtual uint32 Decode(void *buffer) = 0;
|
||||
};
|
||||
#ifdef MULTITHREADED_AUDIO
|
||||
template <typename T> class tsQueue
|
||||
{
|
||||
public:
|
||||
tsQueue() : count(0) { }
|
||||
|
||||
void push(const T &value)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
m_queue.push(value);
|
||||
count++;
|
||||
}
|
||||
|
||||
bool peekPop(T *retVal)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
if (count == 0)
|
||||
return false;
|
||||
|
||||
*retVal = m_queue.front();
|
||||
m_queue.pop();
|
||||
count--;
|
||||
return true;
|
||||
}
|
||||
|
||||
void swapNts(tsQueue<T> &replaceWith)
|
||||
{
|
||||
m_queue.swap(replaceWith.m_queue);
|
||||
replaceWith.count = count;
|
||||
}
|
||||
|
||||
/*
|
||||
void swapTs(tsQueue<T> &replaceWith)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
std::lock_guard<std::mutex> lock2(replaceWith.m_mutex);
|
||||
swapNts(replaceWith);
|
||||
}
|
||||
*/
|
||||
|
||||
bool emptyNts()
|
||||
{
|
||||
return count == 0;
|
||||
}
|
||||
|
||||
/*
|
||||
bool emptyTs()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
return emptyNts();
|
||||
}
|
||||
*/
|
||||
|
||||
std::queue<T> m_queue;
|
||||
int count;
|
||||
mutable std::mutex m_mutex;
|
||||
};
|
||||
#endif
|
||||
class CStream
|
||||
{
|
||||
char m_aFilename[128];
|
||||
@@ -63,6 +122,17 @@ class CStream
|
||||
bool m_bPaused;
|
||||
bool m_bActive;
|
||||
|
||||
public:
|
||||
#ifdef MULTITHREADED_AUDIO
|
||||
std::mutex m_mutex;
|
||||
std::queue<std::pair<ALuint, ALuint>> m_fillBuffers; // left and right buffer
|
||||
tsQueue<std::pair<ALuint, ALuint>> m_queueBuffers;
|
||||
// std::condition_variable m_closeCv;
|
||||
bool m_bDoSeek;
|
||||
uint32 m_SeekPos;
|
||||
bool m_bIExist;
|
||||
#endif
|
||||
|
||||
void *m_pBuffer;
|
||||
|
||||
bool m_bReset;
|
||||
@@ -72,7 +142,14 @@ class CStream
|
||||
int32 m_nLoopCount;
|
||||
|
||||
IDecoder *m_pSoundFile;
|
||||
|
||||
|
||||
void BuffersShouldBeFilled(); // all
|
||||
bool BufferShouldBeFilledAndQueued(std::pair<ALuint, ALuint>*); // two (left-right)
|
||||
#ifdef MULTITHREADED_AUDIO
|
||||
void FlagAsToBeProcessed(bool close = false);
|
||||
bool QueueBuffers();
|
||||
#endif
|
||||
|
||||
bool HasSource();
|
||||
void SetPosition(int i, float x, float y, float z);
|
||||
void SetPitch(float pitch);
|
||||
@@ -81,15 +158,17 @@ class CStream
|
||||
void SetPlay(bool state);
|
||||
|
||||
bool FillBuffer(ALuint *alBuffer);
|
||||
int32 FillBuffers();
|
||||
int32 FillBuffers();
|
||||
void ClearBuffers();
|
||||
public:
|
||||
//public:
|
||||
static void Initialise();
|
||||
static void Terminate();
|
||||
|
||||
CStream(char *filename, ALuint *sources, ALuint (&buffers)[NUM_STREAMBUFFERS], uint32 overrideSampleRate = 32000);
|
||||
CStream(ALuint *sources, ALuint (&buffers)[NUM_STREAMBUFFERS]);
|
||||
~CStream();
|
||||
void Delete();
|
||||
bool Open(const char *filename, uint32 overrideSampleRate = 32000);
|
||||
void Close();
|
||||
|
||||
bool IsOpened();
|
||||
bool IsPlaying();
|
||||
@@ -100,12 +179,11 @@ public:
|
||||
uint32 GetPosMS();
|
||||
uint32 GetLengthMS();
|
||||
|
||||
bool Setup(bool imSureQueueIsEmpty = false);
|
||||
bool Setup(bool imSureQueueIsEmpty = false, bool lock = true);
|
||||
void Start();
|
||||
void Stop();
|
||||
void Update(void);
|
||||
void SetLoopCount(int32);
|
||||
|
||||
|
||||
void ProviderInit();
|
||||
void ProviderTerm();
|
||||
|
||||
1541
src/audio/sampman.h
1541
src/audio/sampman.h
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -4,7 +4,7 @@
|
||||
#include "AudioManager.h"
|
||||
|
||||
cSampleManager SampleManager;
|
||||
bool _bSampmanInitialised = false;
|
||||
bool8 _bSampmanInitialised = FALSE;
|
||||
|
||||
uint32 BankStartOffset[MAX_SFX_BANKS];
|
||||
uint32 nNumMP3s;
|
||||
@@ -19,6 +19,7 @@ cSampleManager::~cSampleManager(void)
|
||||
|
||||
}
|
||||
|
||||
#ifdef EXTERNAL_3D_SOUND
|
||||
void cSampleManager::SetSpeakerConfig(int32 nConfig)
|
||||
{
|
||||
|
||||
@@ -59,8 +60,9 @@ int8 cSampleManager::SetCurrent3DProvider(uint8 nProvider)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool
|
||||
bool8
|
||||
cSampleManager::IsMP3RadioChannelAvailable(void)
|
||||
{
|
||||
return nNumMP3s != 0;
|
||||
@@ -75,10 +77,10 @@ void cSampleManager::ReacquireDigitalHandle(void)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
bool8
|
||||
cSampleManager::Initialise(void)
|
||||
{
|
||||
return true;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -87,9 +89,9 @@ cSampleManager::Terminate(void)
|
||||
|
||||
}
|
||||
|
||||
bool cSampleManager::CheckForAnAudioFileOnCD(void)
|
||||
bool8 cSampleManager::CheckForAnAudioFileOnCD(void)
|
||||
{
|
||||
return true;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
char cSampleManager::GetCDAudioDriveLetter(void)
|
||||
@@ -114,7 +116,7 @@ cSampleManager::SetMusicMasterVolume(uint8 nVolume)
|
||||
}
|
||||
|
||||
void
|
||||
cSampleManager::SetMusicMasterVolume(uint8 nVolume)
|
||||
cSampleManager::SetMP3BoostVolume(uint8 nVolume)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -129,15 +131,15 @@ cSampleManager::SetMusicFadeVolume(uint8 nVolume)
|
||||
}
|
||||
|
||||
void
|
||||
cSampleManager::SetMonoMode(uint8 nMode)
|
||||
cSampleManager::SetMonoMode(bool8 nMode)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
bool8
|
||||
cSampleManager::LoadSampleBank(uint8 nBank)
|
||||
{
|
||||
ASSERT( nBank < MAX_SFX_BANKS );
|
||||
return false;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -146,20 +148,36 @@ cSampleManager::UnloadSampleBank(uint8 nBank)
|
||||
ASSERT( nBank < MAX_SFX_BANKS );
|
||||
}
|
||||
|
||||
bool
|
||||
int8
|
||||
cSampleManager::IsSampleBankLoaded(uint8 nBank)
|
||||
{
|
||||
ASSERT( nBank < MAX_SFX_BANKS );
|
||||
|
||||
return false;
|
||||
return LOADING_STATUS_NOT_LOADED;
|
||||
}
|
||||
|
||||
bool
|
||||
uint8
|
||||
cSampleManager::IsMissionAudioLoaded(uint8 nSlot, uint32 nSample)
|
||||
{
|
||||
ASSERT(nSlot < MISSION_AUDIO_COUNT);
|
||||
|
||||
return LOADING_STATUS_NOT_LOADED;
|
||||
}
|
||||
|
||||
bool8
|
||||
cSampleManager::LoadMissionAudio(uint8 nSlot, uint32 nSample)
|
||||
{
|
||||
ASSERT(nSlot < MISSION_AUDIO_COUNT);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
uint8
|
||||
cSampleManager::IsPedCommentLoaded(uint32 nComment)
|
||||
{
|
||||
ASSERT( nComment < TOTAL_AUDIO_SAMPLES );
|
||||
|
||||
return false;
|
||||
return LOADING_STATUS_NOT_LOADED;
|
||||
}
|
||||
|
||||
|
||||
@@ -169,11 +187,11 @@ cSampleManager::_GetPedCommentSlot(uint32 nComment)
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool
|
||||
bool8
|
||||
cSampleManager::LoadPedComment(uint32 nComment)
|
||||
{
|
||||
ASSERT( nComment < TOTAL_AUDIO_SAMPLES );
|
||||
return false;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int32
|
||||
@@ -182,14 +200,14 @@ cSampleManager::GetBankContainingSound(uint32 offset)
|
||||
return INVALID_SFX_BANK;
|
||||
}
|
||||
|
||||
int32
|
||||
uint32
|
||||
cSampleManager::GetSampleBaseFrequency(uint32 nSample)
|
||||
{
|
||||
ASSERT( nSample < TOTAL_AUDIO_SAMPLES );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32
|
||||
uint32
|
||||
cSampleManager::GetSampleLoopStartOffset(uint32 nSample)
|
||||
{
|
||||
ASSERT( nSample < TOTAL_AUDIO_SAMPLES );
|
||||
@@ -210,56 +228,58 @@ cSampleManager::GetSampleLength(uint32 nSample)
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool cSampleManager::UpdateReverb(void)
|
||||
bool8 cSampleManager::UpdateReverb(void)
|
||||
{
|
||||
return false;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
cSampleManager::SetChannelReverbFlag(uint32 nChannel, uint8 nReverbFlag)
|
||||
cSampleManager::SetChannelReverbFlag(uint32 nChannel, bool8 nReverbFlag)
|
||||
{
|
||||
ASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS );
|
||||
}
|
||||
|
||||
bool
|
||||
bool8
|
||||
cSampleManager::InitialiseChannel(uint32 nChannel, uint32 nSfx, uint8 nBank)
|
||||
{
|
||||
ASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS );
|
||||
return false;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#ifdef EXTERNAL_3D_SOUND
|
||||
void
|
||||
cSampleManager::SetChannelEmittingVolume(uint32 nChannel, uint32 nVolume)
|
||||
{
|
||||
ASSERT( nChannel != CHANNEL2D );
|
||||
ASSERT( nChannel < MAXCHANNELS );
|
||||
ASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS );
|
||||
}
|
||||
|
||||
void
|
||||
cSampleManager::SetChannel3DPosition(uint32 nChannel, float fX, float fY, float fZ)
|
||||
{
|
||||
ASSERT( nChannel != CHANNEL2D );
|
||||
ASSERT( nChannel < MAXCHANNELS );
|
||||
ASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS );
|
||||
}
|
||||
|
||||
void
|
||||
cSampleManager::SetChannel3DDistances(uint32 nChannel, float fMax, float fMin)
|
||||
{
|
||||
ASSERT( nChannel != CHANNEL2D );
|
||||
ASSERT( nChannel < MAXCHANNELS );
|
||||
ASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS );
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
cSampleManager::SetChannelVolume(uint32 nChannel, uint32 nVolume)
|
||||
{
|
||||
ASSERT( nChannel == CHANNEL2D );
|
||||
ASSERT( nChannel >= MAXCHANNELS );
|
||||
ASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS );
|
||||
}
|
||||
|
||||
void
|
||||
cSampleManager::SetChannelPan(uint32 nChannel, uint32 nPan)
|
||||
{
|
||||
ASSERT(nChannel == CHANNEL2D);
|
||||
ASSERT( nChannel >= MAXCHANNELS );
|
||||
ASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS );
|
||||
}
|
||||
|
||||
@@ -281,12 +301,12 @@ cSampleManager::SetChannelLoopCount(uint32 nChannel, uint32 nLoopCount)
|
||||
ASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS );
|
||||
}
|
||||
|
||||
bool
|
||||
bool8
|
||||
cSampleManager::GetChannelUsedFlag(uint32 nChannel)
|
||||
{
|
||||
ASSERT( nChannel < MAXCHANNELS+MAX2DCHANNELS );
|
||||
|
||||
return false;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -308,7 +328,7 @@ cSampleManager::PreloadStreamedFile(uint32 nFile, uint8 nStream)
|
||||
}
|
||||
|
||||
void
|
||||
cSampleManager::PauseStream(uint8 nPauseFlag, uint8 nStream)
|
||||
cSampleManager::PauseStream(bool8 nPauseFlag, uint8 nStream)
|
||||
{
|
||||
ASSERT( nStream < MAX_STREAMS );
|
||||
}
|
||||
@@ -319,12 +339,12 @@ cSampleManager::StartPreloadedStreamedFile(uint8 nStream)
|
||||
ASSERT( nStream < MAX_STREAMS );
|
||||
}
|
||||
|
||||
bool
|
||||
bool8
|
||||
cSampleManager::StartStreamedFile(uint32 nFile, uint32 nPos, uint8 nStream)
|
||||
{
|
||||
ASSERT( nStream < MAX_STREAMS );
|
||||
|
||||
return false;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -342,7 +362,7 @@ cSampleManager::GetStreamedFilePosition(uint8 nStream)
|
||||
}
|
||||
|
||||
void
|
||||
cSampleManager::SetStreamedVolumeAndPan(uint8 nVolume, uint8 nPan, uint8 nEffectFlag, uint8 nStream)
|
||||
cSampleManager::SetStreamedVolumeAndPan(uint8 nVolume, uint8 nPan, bool8 nEffectFlag, uint8 nStream)
|
||||
{
|
||||
ASSERT( nStream < MAX_STREAMS );
|
||||
}
|
||||
@@ -355,23 +375,23 @@ cSampleManager::GetStreamedFileLength(uint8 nStream)
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool
|
||||
bool8
|
||||
cSampleManager::IsStreamPlaying(uint8 nStream)
|
||||
{
|
||||
ASSERT( nStream < MAX_STREAMS );
|
||||
|
||||
return false;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool
|
||||
bool8
|
||||
cSampleManager::InitialiseSampleBanks(void)
|
||||
{
|
||||
|
||||
return true;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
cSampleManager::SetStreamedFileLoopFlag(uint8 nLoopFlag, uint8 nChannel)
|
||||
cSampleManager::SetStreamedFileLoopFlag(bool8 nLoopFlag, uint8 nChannel)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -54,8 +54,8 @@ enum eSound
|
||||
SOUND_49,
|
||||
SOUND_WEAPON_BAT_ATTACK,
|
||||
SOUND_WEAPON_KNIFE_ATTACK,
|
||||
SOUND_WEAPON_CHAINSAW_ATTACK,
|
||||
SOUND_WEAPON_CHAINSAW_IDLE,
|
||||
SOUND_WEAPON_CHAINSAW_ATTACK,
|
||||
SOUND_WEAPON_CHAINSAW_MADECONTACT,
|
||||
SOUND_WEAPON_SHOT_FIRED,
|
||||
SOUND_WEAPON_RELOAD,
|
||||
@@ -116,8 +116,8 @@ enum eSound
|
||||
SOUND_PED_MIAMIVICE_EXITING_CAR,
|
||||
SOUND_PED_COP_HELIPILOTPHRASE,
|
||||
SOUND_PED_PULLOUTWEAPON,
|
||||
SOUND_PED_HELI_PLAYER_FOUND = 114,
|
||||
SOUND_PED_VCPA_PLAYER_FOUND = 115,
|
||||
SOUND_PED_HELI_PLAYER_FOUND,
|
||||
SOUND_PED_VCPA_PLAYER_FOUND,
|
||||
SOUND_PED_ON_FIRE,
|
||||
SOUND_PED_AIMING,
|
||||
SOUND_PED_HANDS_UP,
|
||||
@@ -128,15 +128,15 @@ enum eSound
|
||||
SOUND_PED_CAR_JACKED,
|
||||
SOUND_PED_ROBBED,
|
||||
SOUND_PED_ACCIDENTREACTION1,
|
||||
SOUND_PED_UNK_126,
|
||||
SOUND_PED_INNOCENT,
|
||||
SOUND_PED_PLAYER_AFTERSEX,
|
||||
SOUND_PED_PLAYER_BEFORESEX,
|
||||
SOUND_PED_COP_UNK_129, // also used for medics
|
||||
SOUND_PED_COP_TARGETING, // also used for medics
|
||||
SOUND_PED_COP_MANYCOPSAROUND, // also used for medics
|
||||
SOUND_PED_GUNAIMEDAT2,
|
||||
SOUND_PED_COP_ALONE, // also used for medics
|
||||
SOUND_PED_GUNAIMEDAT3,
|
||||
SOUND_PED_COP_REACTION,
|
||||
SOUND_PED_COP_ASK_FOR_ID,
|
||||
SOUND_PED_COP_LITTLECOPSAROUND, // also used for medics
|
||||
SOUND_PED_PLAYER_FARFROMCOPS, // also used for medics
|
||||
SOUND_PED_TAXI_WAIT,
|
||||
@@ -151,12 +151,12 @@ enum eSound
|
||||
SOUND_PED_ANNOYED_DRIVER,
|
||||
SOUND_PED_147,
|
||||
SOUND_PED_SOLICIT,
|
||||
SOUND_PED_149,
|
||||
SOUND_PED_JEER,
|
||||
SOUND_PED_150,
|
||||
SOUND_PED_EXTINGUISHING_FIRE,
|
||||
SOUND_PED_WAIT_DOUBLEBACK,
|
||||
SOUND_153,
|
||||
SOUND_PED_CHAT_SEXY,
|
||||
SOUND_PED_CHAT_SEXY_FEMALE,
|
||||
SOUND_PED_CHAT_SEXY_MALE,
|
||||
SOUND_PED_CHAT_EVENT,
|
||||
SOUND_PED_PED_COLLISION,
|
||||
SOUND_PED_CHAT,
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
#include "Streaming.h"
|
||||
#include "Pools.h"
|
||||
|
||||
void *CBuilding::operator new(size_t sz) { return CPools::GetBuildingPool()->New(); }
|
||||
void CBuilding::operator delete(void *p, size_t sz) { CPools::GetBuildingPool()->Delete((CBuilding*)p); }
|
||||
void *CBuilding::operator new(size_t sz) throw() { return CPools::GetBuildingPool()->New(); }
|
||||
void CBuilding::operator delete(void *p, size_t sz) throw() { CPools::GetBuildingPool()->Delete((CBuilding*)p); }
|
||||
|
||||
void
|
||||
CBuilding::ReplaceWithNewModel(int32 id)
|
||||
|
||||
@@ -9,8 +9,8 @@ public:
|
||||
m_type = ENTITY_TYPE_BUILDING;
|
||||
bUsesCollision = true;
|
||||
}
|
||||
static void *operator new(size_t);
|
||||
static void operator delete(void*, size_t);
|
||||
static void *operator new(size_t) throw();
|
||||
static void operator delete(void*, size_t) throw();
|
||||
|
||||
void ReplaceWithNewModel(int32 id);
|
||||
|
||||
|
||||
@@ -4,5 +4,5 @@
|
||||
#include "Treadable.h"
|
||||
#include "Pools.h"
|
||||
|
||||
void *CTreadable::operator new(size_t sz) { return CPools::GetTreadablePool()->New(); }
|
||||
void CTreadable::operator delete(void *p, size_t sz) { CPools::GetTreadablePool()->Delete((CTreadable*)p); }
|
||||
void *CTreadable::operator new(size_t sz) throw() { return CPools::GetTreadablePool()->New(); }
|
||||
void CTreadable::operator delete(void *p, size_t sz) throw() { CPools::GetTreadablePool()->Delete((CTreadable*)p); }
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
class CTreadable : public CBuilding
|
||||
{
|
||||
public:
|
||||
static void *operator new(size_t);
|
||||
static void operator delete(void*, size_t);
|
||||
static void *operator new(size_t) throw();
|
||||
static void operator delete(void*, size_t) throw();
|
||||
|
||||
bool GetIsATreadable(void) { return true; }
|
||||
};
|
||||
|
||||
@@ -19,4 +19,12 @@ struct CColBox : public CBox
|
||||
using CBox::Set;
|
||||
|
||||
CColBox& operator=(const CColBox &other);
|
||||
};
|
||||
};
|
||||
|
||||
// no name for this
|
||||
// bounds for a number of triangles
|
||||
struct CColTriBBox : public CBox
|
||||
{
|
||||
int32 first;
|
||||
int32 last;
|
||||
};
|
||||
|
||||
@@ -4,9 +4,9 @@ struct CColLine
|
||||
{
|
||||
// NB: this has to be compatible with two CVuVectors
|
||||
CVector p0;
|
||||
int pad0;
|
||||
// int pad0;
|
||||
CVector p1;
|
||||
int pad1;
|
||||
// int pad1;
|
||||
|
||||
CColLine(void) { };
|
||||
CColLine(const CVector &p0, const CVector &p1) { this->p0 = p0; this->p1 = p1; };
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "common.h"
|
||||
#include "main.h"
|
||||
#include "ColModel.h"
|
||||
#include "Collision.h"
|
||||
#include "Game.h"
|
||||
@@ -7,6 +8,10 @@
|
||||
|
||||
CColModel::CColModel(void)
|
||||
{
|
||||
boundingSphere.Set(0.0001f, CVector(0.0f, 0.0f, 0.0f));
|
||||
boundingBox.Set(CVector(0.0f, 0.0f, 0.0f), CVector(0.0f, 0.0f, 0.0f));
|
||||
numTriBBoxes = 0;
|
||||
triBBoxes = nil;
|
||||
numSpheres = 0;
|
||||
spheres = nil;
|
||||
numLines = 0;
|
||||
@@ -18,16 +23,20 @@ CColModel::CColModel(void)
|
||||
triangles = nil;
|
||||
trianglePlanes = nil;
|
||||
level = LEVEL_GENERIC; // generic col slot
|
||||
ownsCollisionVolumes = true;
|
||||
// ownsCollisionVolumes = true;
|
||||
}
|
||||
|
||||
CColModel::~CColModel(void)
|
||||
{
|
||||
RemoveCollisionVolumes();
|
||||
if(!gNASTY_NASTY_MEM_SHUTDOWN_HACK){
|
||||
RemoveTrianglePlanes();
|
||||
RemoveCollisionVolumes();
|
||||
}
|
||||
}
|
||||
|
||||
//--LCS: no pool used, but maybe we better keep it?
|
||||
void*
|
||||
CColModel::operator new(size_t)
|
||||
CColModel::operator new(size_t) throw()
|
||||
{
|
||||
CColModel* node = CPools::GetColModelPool()->New();
|
||||
assert(node);
|
||||
@@ -35,7 +44,7 @@ CColModel::operator new(size_t)
|
||||
}
|
||||
|
||||
void
|
||||
CColModel::operator delete(void *p, size_t)
|
||||
CColModel::operator delete(void *p, size_t) throw()
|
||||
{
|
||||
CPools::GetColModelPool()->Delete((CColModel*)p);
|
||||
}
|
||||
@@ -43,19 +52,28 @@ CColModel::operator delete(void *p, size_t)
|
||||
void
|
||||
CColModel::RemoveCollisionVolumes(void)
|
||||
{
|
||||
if(ownsCollisionVolumes){
|
||||
RwFree(spheres);
|
||||
RwFree(lines);
|
||||
RwFree(boxes);
|
||||
RwFree(vertices);
|
||||
RwFree(triangles);
|
||||
CCollision::RemoveTrianglePlanes(this);
|
||||
#ifdef FIX_BUGS
|
||||
// why is this missing?
|
||||
if(ownsCollisionVolumes)
|
||||
#endif
|
||||
if(!gUseChunkFiles){
|
||||
delete[] triBBoxes;
|
||||
delete[] spheres;
|
||||
delete[] lines;
|
||||
delete[] boxes;
|
||||
delete[] vertices;
|
||||
delete[] triangles;
|
||||
}
|
||||
CCollision::RemoveTrianglePlanes(this);
|
||||
numSpheres = 0;
|
||||
numTriBBoxes = 0;
|
||||
numLines = 0;
|
||||
numBoxes = 0;
|
||||
numTriangles = 0;
|
||||
spheres = nil;
|
||||
#ifdef FIX_BUGS
|
||||
triBBoxes = nil;
|
||||
#endif
|
||||
lines = nil;
|
||||
boxes = nil;
|
||||
vertices = nil;
|
||||
@@ -68,7 +86,7 @@ CColModel::CalculateTrianglePlanes(void)
|
||||
PUSH_MEMID(MEMID_COLLISION);
|
||||
|
||||
// HACK: allocate space for one more element to stuff the link pointer into
|
||||
trianglePlanes = (CColTrianglePlane*)RwMalloc(sizeof(CColTrianglePlane) * (numTriangles+1));
|
||||
trianglePlanes = new CColTrianglePlane[numTriangles+1];
|
||||
REGISTER_MEMPTR(&trianglePlanes);
|
||||
for(int i = 0; i < numTriangles; i++)
|
||||
trianglePlanes[i].Set(vertices, triangles[i]);
|
||||
@@ -79,8 +97,10 @@ CColModel::CalculateTrianglePlanes(void)
|
||||
void
|
||||
CColModel::RemoveTrianglePlanes(void)
|
||||
{
|
||||
RwFree(trianglePlanes);
|
||||
trianglePlanes = nil;
|
||||
if(trianglePlanes){
|
||||
delete[] trianglePlanes;
|
||||
trianglePlanes = nil;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -112,20 +132,33 @@ CColModel::operator=(const CColModel &other)
|
||||
boundingSphere = other.boundingSphere;
|
||||
boundingBox = other.boundingBox;
|
||||
|
||||
// copy tri bboxes
|
||||
if(other.numTriBBoxes){
|
||||
if(numTriBBoxes != other.numTriBBoxes){
|
||||
numTriBBoxes = other.numTriBBoxes;
|
||||
delete[] triBBoxes;
|
||||
triBBoxes = new CColTriBBox[numTriBBoxes];
|
||||
}
|
||||
for(i = 0; i < numTriBBoxes; i++)
|
||||
triBBoxes[i] = other.triBBoxes[i];
|
||||
}else{
|
||||
numTriBBoxes = 0;
|
||||
delete[] triBBoxes;
|
||||
triBBoxes = nil;
|
||||
}
|
||||
|
||||
// copy spheres
|
||||
if(other.numSpheres){
|
||||
if(numSpheres != other.numSpheres){
|
||||
numSpheres = other.numSpheres;
|
||||
if(spheres)
|
||||
RwFree(spheres);
|
||||
spheres = (CColSphere*)RwMalloc(numSpheres*sizeof(CColSphere));
|
||||
delete[] spheres;
|
||||
spheres = new CColSphere[numSpheres];
|
||||
}
|
||||
for(i = 0; i < numSpheres; i++)
|
||||
spheres[i] = other.spheres[i];
|
||||
}else{
|
||||
numSpheres = 0;
|
||||
if(spheres)
|
||||
RwFree(spheres);
|
||||
delete[] spheres;
|
||||
spheres = nil;
|
||||
}
|
||||
|
||||
@@ -133,16 +166,14 @@ CColModel::operator=(const CColModel &other)
|
||||
if(other.numLines){
|
||||
if(numLines != other.numLines){
|
||||
numLines = other.numLines;
|
||||
if(lines)
|
||||
RwFree(lines);
|
||||
lines = (CColLine*)RwMalloc(numLines*sizeof(CColLine));
|
||||
delete[] lines;
|
||||
lines = new CColLine[numLines];
|
||||
}
|
||||
for(i = 0; i < numLines; i++)
|
||||
lines[i] = other.lines[i];
|
||||
}else{
|
||||
numLines = 0;
|
||||
if(lines)
|
||||
RwFree(lines);
|
||||
delete[] lines;
|
||||
lines = nil;
|
||||
}
|
||||
|
||||
@@ -150,23 +181,21 @@ CColModel::operator=(const CColModel &other)
|
||||
if(other.numBoxes){
|
||||
if(numBoxes != other.numBoxes){
|
||||
numBoxes = other.numBoxes;
|
||||
if(boxes)
|
||||
RwFree(boxes);
|
||||
boxes = (CColBox*)RwMalloc(numBoxes*sizeof(CColBox));
|
||||
delete[] boxes;
|
||||
boxes = new CColBox[numBoxes];
|
||||
}
|
||||
for(i = 0; i < numBoxes; i++)
|
||||
boxes[i] = other.boxes[i];
|
||||
}else{
|
||||
numBoxes = 0;
|
||||
if(boxes)
|
||||
RwFree(boxes);
|
||||
delete[] boxes;
|
||||
boxes = nil;
|
||||
}
|
||||
|
||||
// copy mesh
|
||||
if(other.numTriangles){
|
||||
// copy vertices
|
||||
numVerts = 0;
|
||||
numVerts = -1;
|
||||
for(i = 0; i < other.numTriangles; i++){
|
||||
if(other.triangles[i].a > numVerts)
|
||||
numVerts = other.triangles[i].a;
|
||||
@@ -176,10 +205,9 @@ CColModel::operator=(const CColModel &other)
|
||||
numVerts = other.triangles[i].c;
|
||||
}
|
||||
numVerts++;
|
||||
if(vertices)
|
||||
RwFree(vertices);
|
||||
delete[] vertices;
|
||||
if(numVerts){
|
||||
vertices = (CompressedVector*)RwMalloc(numVerts*sizeof(CompressedVector));
|
||||
vertices = new CompressedVector[numVerts];
|
||||
for(i = 0; i < numVerts; i++)
|
||||
vertices[i] = other.vertices[i];
|
||||
}
|
||||
@@ -187,20 +215,54 @@ CColModel::operator=(const CColModel &other)
|
||||
// copy triangles
|
||||
if(numTriangles != other.numTriangles){
|
||||
numTriangles = other.numTriangles;
|
||||
if(triangles)
|
||||
RwFree(triangles);
|
||||
triangles = (CColTriangle*)RwMalloc(numTriangles*sizeof(CColTriangle));
|
||||
delete[] triangles;
|
||||
triangles = new CColTriangle[numTriangles];
|
||||
}
|
||||
for(i = 0; i < numTriangles; i++)
|
||||
triangles[i] = other.triangles[i];
|
||||
}else{
|
||||
numTriangles = 0;
|
||||
if(triangles)
|
||||
RwFree(triangles);
|
||||
delete[] triangles;
|
||||
triangles = nil;
|
||||
if(vertices)
|
||||
RwFree(vertices);
|
||||
delete[] vertices;
|
||||
vertices = nil;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool
|
||||
CColModel::Write(base::cRelocatableChunkWriter &writer, bool allocSpace)
|
||||
{
|
||||
int numVerts = -1;
|
||||
for(int i = 0; i < numTriangles; i++){
|
||||
if(triangles[i].a > numVerts)
|
||||
numVerts = triangles[i].a;
|
||||
if(triangles[i].b > numVerts)
|
||||
numVerts = triangles[i].b;
|
||||
if(triangles[i].c > numVerts)
|
||||
numVerts = triangles[i].c;
|
||||
}
|
||||
numVerts++;
|
||||
|
||||
if(allocSpace)
|
||||
writer.AllocateRaw(this, sizeof(*this), 16, false, true);
|
||||
writer.AllocateRaw(spheres, sizeof(*spheres)*numSpheres, 16, false, true);
|
||||
writer.AddPatch(&spheres);
|
||||
writer.AllocateRaw(lines, sizeof(*lines)*numLines, 16, false, true);
|
||||
writer.AddPatch(&lines);
|
||||
writer.AllocateRaw(boxes, sizeof(*boxes)*numBoxes, 16, false, true);
|
||||
writer.AddPatch(&boxes);
|
||||
if(triBBoxes && numTriBBoxes != 0){
|
||||
writer.AllocateRaw(triBBoxes, sizeof(*triBBoxes)*numTriBBoxes, 16, false, true);
|
||||
writer.AddPatch(&triBBoxes);
|
||||
}else
|
||||
triBBoxes = nil;
|
||||
if(numTriangles != 0){
|
||||
writer.AllocateRaw(vertices, sizeof(*vertices)*numVerts, 2, false, true);
|
||||
writer.AddPatch(&vertices);
|
||||
writer.AllocateRaw(triangles, sizeof(*triangles)*numTriangles, 2, false, true);
|
||||
writer.AddPatch(&triangles);
|
||||
RemoveTrianglePlanes();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -15,11 +15,13 @@ struct CColModel
|
||||
int16 numBoxes;
|
||||
int16 numTriangles;
|
||||
int8 numLines;
|
||||
int8 numTriBBoxes;
|
||||
uint8 level; // colstore slot but probably still named level
|
||||
bool ownsCollisionVolumes;
|
||||
CColSphere *spheres;
|
||||
CColLine *lines;
|
||||
CColBox *boxes;
|
||||
CColTriBBox *triBBoxes;
|
||||
CompressedVector *vertices;
|
||||
CColTriangle *triangles;
|
||||
CColTrianglePlane *trianglePlanes;
|
||||
@@ -33,7 +35,9 @@ struct CColModel
|
||||
void SetLinkPtr(CLink<CColModel*>*);
|
||||
void GetTrianglePoint(CVector &v, int i) const;
|
||||
|
||||
void *operator new(size_t);
|
||||
void operator delete(void *p, size_t);
|
||||
void *operator new(size_t) throw();
|
||||
void operator delete(void *p, size_t) throw();
|
||||
CColModel& operator=(const CColModel& other);
|
||||
|
||||
bool Write(base::cRelocatableChunkWriter &writer, bool allocSpace);
|
||||
};
|
||||
@@ -3,15 +3,13 @@
|
||||
struct CColPoint
|
||||
{
|
||||
CVector point;
|
||||
int pad1;
|
||||
float depth;
|
||||
// the surface normal on the surface of point
|
||||
CVector normal;
|
||||
int pad2;
|
||||
uint8 surfaceA;
|
||||
uint8 pieceA;
|
||||
uint8 surfaceB;
|
||||
uint8 pieceB;
|
||||
float depth;
|
||||
|
||||
const CVector &GetNormal() { return normal; }
|
||||
float GetDepth() { return depth; }
|
||||
|
||||
@@ -2,10 +2,11 @@
|
||||
|
||||
#include "SurfaceTable.h"
|
||||
|
||||
struct CSphere
|
||||
// TODO(LCS): maybe this was in a union with CVuVector? or is the alignment manual?
|
||||
struct TYPEALIGN(16) CSphere
|
||||
{
|
||||
// NB: this has to be compatible with a CVuVector
|
||||
CVector center;
|
||||
RwV3d center;
|
||||
float radius;
|
||||
void Set(float radius, const CVector ¢er) { this->center = center; this->radius = radius; }
|
||||
};
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "common.h"
|
||||
|
||||
#include "main.h"
|
||||
#include "smallHeap.h"
|
||||
#include "templates.h"
|
||||
#include "General.h"
|
||||
#include "ModelInfo.h"
|
||||
@@ -8,6 +10,9 @@
|
||||
#include "Script.h"
|
||||
#include "Timer.h"
|
||||
#include "Camera.h"
|
||||
#include "World.h"
|
||||
#include "Zones.h"
|
||||
#include "Garages.h"
|
||||
#include "Frontend.h"
|
||||
#include "Physical.h"
|
||||
#include "ColStore.h"
|
||||
@@ -15,16 +20,55 @@
|
||||
#include "Pools.h"
|
||||
|
||||
CPool<ColDef,ColDef> *CColStore::ms_pColPool;
|
||||
bool CColStore::m_onlyBB;
|
||||
#ifndef MASTER
|
||||
bool bDispColInMem;
|
||||
#endif
|
||||
|
||||
// LCS: file done except unused:
|
||||
// CColStore::LoadCol(int,char const*)
|
||||
// CColStore::LoadAllBoundingBoxes(void)
|
||||
// CColStore::Write(base::cRelocatableChunkWriter &)
|
||||
|
||||
const CVector&
|
||||
LevelPos(eLevelName level)
|
||||
{
|
||||
static CVector pos[4] = {
|
||||
CVector(1060.0f, -800.0f, 0.0f),
|
||||
CVector(1060.0f, -800.0f, 0.0f),
|
||||
CVector(350.0f, -624.0f, 0.0f),
|
||||
CVector(-670.0f, -511.0f, 0.0f)
|
||||
};
|
||||
return pos[level];
|
||||
};
|
||||
|
||||
static eLevelName
|
||||
PosLevel(const CVector &pos)
|
||||
{
|
||||
static eLevelName lastPlayerLevel = LEVEL_INDUSTRIAL;
|
||||
static eLevelName lastOtherLevel = LEVEL_INDUSTRIAL;
|
||||
|
||||
if(Abs(FindPlayerCoors().x - pos.x) < 5.0f &&
|
||||
Abs(FindPlayerCoors().y - pos.y) < 5.0f &&
|
||||
Abs(FindPlayerCoors().z - pos.z) < 5.0f){
|
||||
if(CGame::currLevel != LEVEL_GENERIC)
|
||||
lastPlayerLevel = CGame::currLevel;
|
||||
return lastPlayerLevel;
|
||||
}else{
|
||||
eLevelName lvl = CTheZones::GetLevelFromPosition(&pos);
|
||||
if(lvl != LEVEL_GENERIC)
|
||||
lastOtherLevel = lvl;
|
||||
return lastOtherLevel;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CColStore::Initialise(void)
|
||||
{
|
||||
if(ms_pColPool == nil)
|
||||
if(ms_pColPool == nil){
|
||||
ms_pColPool = new CPool<ColDef,ColDef>(COLSTORESIZE, "CollisionFiles");
|
||||
AddColSlot("generic"); // slot 0. not streamed
|
||||
AddColSlot("generic"); // slot 0. not streamed
|
||||
}
|
||||
#ifndef MASTER
|
||||
VarConsole.Add("Display collision in memory", &bDispColInMem, true);
|
||||
#endif
|
||||
@@ -38,7 +82,9 @@ CColStore::Shutdown(void)
|
||||
RemoveColSlot(i);
|
||||
if(ms_pColPool)
|
||||
delete ms_pColPool;
|
||||
#ifdef FIX_BUGS
|
||||
ms_pColPool = nil;
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
@@ -119,11 +165,34 @@ CColStore::LoadCol(int32 slot, uint8 *buffer, int32 bufsize)
|
||||
return success;
|
||||
}
|
||||
|
||||
struct ColChunkEntry
|
||||
{
|
||||
int32 modelId; // -1 marks end
|
||||
CColModel *colModel;
|
||||
};
|
||||
|
||||
void
|
||||
CColStore::LoadColCHK(int32 slot, void *data, void *chunk)
|
||||
{
|
||||
ColDef *def = GetSlot(slot);
|
||||
def->chunk = chunk;
|
||||
CStreaming::RegisterPointer(&def->chunk, 1, true);
|
||||
for(ColChunkEntry *entry = (ColChunkEntry*)data; entry->modelId != -1; entry++){
|
||||
CBaseModelInfo *mi = CModelInfo::GetModelInfo(entry->modelId);
|
||||
mi->SetColModel(entry->colModel, true); // we own this? can that work?
|
||||
CStreaming::RegisterPointer(&mi->m_colModel, 1, true);
|
||||
}
|
||||
def->isLoaded = true;
|
||||
}
|
||||
|
||||
CColModel nullCollision;
|
||||
|
||||
void
|
||||
CColStore::RemoveCol(int32 slot)
|
||||
{
|
||||
int id;
|
||||
GetSlot(slot)->isLoaded = false;
|
||||
ColDef *def = GetSlot(slot);
|
||||
def->isLoaded = false;
|
||||
for(id = 0; id < MODELINFOSIZE; id++){
|
||||
CBaseModelInfo *mi = CModelInfo::GetModelInfo(id);
|
||||
if(mi){
|
||||
@@ -132,6 +201,23 @@ CColStore::RemoveCol(int32 slot)
|
||||
col->RemoveCollisionVolumes();
|
||||
}
|
||||
}
|
||||
if(gUseChunkFiles){
|
||||
for(id = 0; id < MODELINFOSIZE; id++){
|
||||
CBaseModelInfo *mi = CModelInfo::GetModelInfo(id);
|
||||
if(mi){
|
||||
CColModel *col = mi->GetColModel();
|
||||
if(col && col->level == slot){
|
||||
mi->SetColModel(&nullCollision);
|
||||
CStreaming::UnregisterPointer(&mi->m_colModel, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(def->chunk){
|
||||
CStreaming::UnregisterPointer(&def->chunk, 1);
|
||||
cSmallHeap::msInstance.Free(def->chunk);
|
||||
def->chunk = nil;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -156,29 +242,49 @@ CColStore::RemoveAllCollision(void)
|
||||
}
|
||||
|
||||
static bool bLoadAtSecondPosition;
|
||||
static CVector2D secondPosition;
|
||||
static CVector secondPosition;
|
||||
|
||||
void
|
||||
CColStore::AddCollisionNeededAtPosn(const CVector2D &pos)
|
||||
CColStore::AddCollisionNeededAtPosn(const CVector &pos)
|
||||
{
|
||||
bLoadAtSecondPosition = true;
|
||||
secondPosition = pos;
|
||||
}
|
||||
|
||||
void
|
||||
CColStore::LoadCollision(const CVector2D &pos)
|
||||
CColStore::LoadCollision(const CVector &pos, eLevelName level)
|
||||
{
|
||||
int i;
|
||||
|
||||
if(CStreaming::ms_disableStreaming)
|
||||
return;
|
||||
|
||||
if(level == LEVEL_GENERIC)
|
||||
level = PosLevel(pos);
|
||||
|
||||
eLevelName allowedLevel = (eLevelName)CTheScripts::AllowedCollision[0];
|
||||
if(allowedLevel == LEVEL_GENERIC)
|
||||
allowedLevel = (eLevelName)CTheScripts::AllowedCollision[1];
|
||||
|
||||
bool requestedSomething = false;
|
||||
|
||||
for(i = 1; i < COLSTORESIZE; i++){
|
||||
if(GetSlot(i) == nil)
|
||||
if(GetSlot(i) == nil || !DoScriptsWantThisIn(i))
|
||||
continue;
|
||||
|
||||
bool wantThisOne = false;
|
||||
|
||||
if(strcmp(GetColName(i), "indust") == 0){
|
||||
if(allowedLevel != LEVEL_GENERIC && level != LEVEL_INDUSTRIAL)
|
||||
wantThisOne = allowedLevel == LEVEL_INDUSTRIAL;
|
||||
else
|
||||
wantThisOne = level == LEVEL_INDUSTRIAL;
|
||||
}else if(GetBoundingBox(i).IsPointInside(LevelPos(level)))
|
||||
wantThisOne = true;
|
||||
else if(allowedLevel != LEVEL_GENERIC && GetBoundingBox(i).IsPointInside(LevelPos(allowedLevel)))
|
||||
wantThisOne = true;
|
||||
|
||||
/* // LCS: removed
|
||||
if(GetBoundingBox(i).IsPointInside(pos) ||
|
||||
bLoadAtSecondPosition && GetBoundingBox(i).IsPointInside(secondPosition, -119.0f) ||
|
||||
strcmp(GetColName(i), "yacht") == 0){
|
||||
@@ -186,7 +292,7 @@ CColStore::LoadCollision(const CVector2D &pos)
|
||||
}else{
|
||||
for (int j = 0; j < MAX_CLEANUP; j++) {
|
||||
CPhysical* pEntity = nil;
|
||||
cleanup_entity_struct* pCleanup = &CTheScripts::MissionCleanUp.m_sEntities[i];
|
||||
cleanup_entity_struct* pCleanup = &CTheScripts::MissionCleanUp.m_sEntities[j];
|
||||
if (pCleanup->type == CLEANUP_CAR) {
|
||||
pEntity = CPools::GetVehiclePool()->GetAt(pCleanup->id);
|
||||
if (!pEntity || pEntity->GetStatus() == STATUS_WRECKED)
|
||||
@@ -203,28 +309,38 @@ CColStore::LoadCollision(const CVector2D &pos)
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
if(wantThisOne)
|
||||
if(wantThisOne){
|
||||
CStreaming::RequestCol(i, STREAMFLAGS_PRIORITY);
|
||||
else
|
||||
requestedSomething = true;
|
||||
}else
|
||||
CStreaming::RemoveCol(i);
|
||||
}
|
||||
if(requestedSomething){
|
||||
CTimer::Suspend();
|
||||
// BUG? request was done with priority but now loading non-priority?
|
||||
CStreaming::LoadAllRequestedModels(false);
|
||||
CGarages::SetupAnyGaragesForThisIsland();
|
||||
CTimer::Resume();
|
||||
}
|
||||
bLoadAtSecondPosition = false;
|
||||
}
|
||||
|
||||
void
|
||||
CColStore::RequestCollision(const CVector2D &pos)
|
||||
CColStore::RequestCollision(const CVector &pos)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 1; i < COLSTORESIZE; i++)
|
||||
if(GetSlot(i) && GetBoundingBox(i).IsPointInside(pos, -115.0f))
|
||||
if(GetSlot(i) && DoScriptsWantThisIn(i) && GetBoundingBox(i).IsPointInside(LevelPos(PosLevel(pos)), -115.0f))
|
||||
CStreaming::RequestCol(i, STREAMFLAGS_PRIORITY);
|
||||
}
|
||||
|
||||
void
|
||||
CColStore::EnsureCollisionIsInMemory(const CVector2D &pos)
|
||||
CColStore::EnsureCollisionIsInMemory(const CVector &pos)
|
||||
{
|
||||
/* // LCS: removed
|
||||
int i;
|
||||
|
||||
if(CStreaming::ms_disableStreaming)
|
||||
@@ -240,16 +356,48 @@ CColStore::EnsureCollisionIsInMemory(const CVector2D &pos)
|
||||
CStreaming::LoadAllRequestedModels(false);
|
||||
CTimer::Resume();
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
bool
|
||||
CColStore::HasCollisionLoaded(const CVector2D &pos)
|
||||
CColStore::DoScriptsWantThisIn(int32 slot)
|
||||
{
|
||||
if(slot == 0)
|
||||
return false;
|
||||
ColDef *coldef = GetSlot(slot);
|
||||
if(coldef == nil)
|
||||
return false;
|
||||
if(strcmp(coldef->name, "fortstaunton") == 0)
|
||||
return !CTheScripts::IsFortStauntonDestroyed();
|
||||
if(strcmp(coldef->name, "fortdestroyed") == 0)
|
||||
return CTheScripts::IsFortStauntonDestroyed();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CColStore::HasCollisionLoaded(eLevelName level)
|
||||
{
|
||||
int i;
|
||||
|
||||
const CVector &pos = LevelPos(level);
|
||||
for(i = 1; i < COLSTORESIZE; i++)
|
||||
if(GetSlot(i) && GetBoundingBox(i).IsPointInside(pos, -115.0f) &&
|
||||
if(GetSlot(i) && DoScriptsWantThisIn(i) &&
|
||||
(!CGeneral::faststricmp(GetColName(i), "indust") && level == LEVEL_INDUSTRIAL ||
|
||||
GetBoundingBox(i).IsPointInside(pos)) &&
|
||||
!GetSlot(i)->isLoaded)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CColStore::HasCollisionLoaded(const CVector &pos)
|
||||
{
|
||||
return HasCollisionLoaded(PosLevel(pos));
|
||||
}
|
||||
|
||||
void
|
||||
CColStore::Load(bool onlyBB, CPool<ColDef> *pool)
|
||||
{
|
||||
ms_pColPool = pool;
|
||||
m_onlyBB = onlyBB;
|
||||
}
|
||||
|
||||
@@ -9,11 +9,13 @@ struct ColDef { // made up name
|
||||
char name[20];
|
||||
int16 minIndex;
|
||||
int16 maxIndex;
|
||||
void *chunk;
|
||||
};
|
||||
|
||||
class CColStore
|
||||
{
|
||||
static CPool<ColDef,ColDef> *ms_pColPool;
|
||||
static bool m_onlyBB;
|
||||
|
||||
public:
|
||||
static void Initialise(void);
|
||||
@@ -25,14 +27,18 @@ public:
|
||||
static CRect &GetBoundingBox(int32 slot);
|
||||
static void IncludeModelIndex(int32 slot, int32 modelIndex);
|
||||
static bool LoadCol(int32 storeID, uint8 *buffer, int32 bufsize);
|
||||
static void LoadColCHK(int32 slot, void *data, void *chunk);
|
||||
static void RemoveCol(int32 slot);
|
||||
static void AddCollisionNeededAtPosn(const CVector2D &pos);
|
||||
static void AddCollisionNeededAtPosn(const CVector &pos);
|
||||
static void LoadAllCollision(void);
|
||||
static void RemoveAllCollision(void);
|
||||
static void LoadCollision(const CVector2D &pos);
|
||||
static void RequestCollision(const CVector2D &pos);
|
||||
static void EnsureCollisionIsInMemory(const CVector2D &pos);
|
||||
static bool HasCollisionLoaded(const CVector2D &pos);
|
||||
static void LoadCollision(const CVector &pos, eLevelName level = LEVEL_GENERIC);
|
||||
static void RequestCollision(const CVector &pos);
|
||||
static void EnsureCollisionIsInMemory(const CVector &pos);
|
||||
static bool DoScriptsWantThisIn(int32 slot);
|
||||
static bool HasCollisionLoaded(eLevelName level);
|
||||
static bool HasCollisionLoaded(const CVector &pos);
|
||||
static void Load(bool, CPool<ColDef> *pool);
|
||||
|
||||
static ColDef *GetSlot(int slot) {
|
||||
assert(slot >= 0);
|
||||
@@ -41,3 +47,5 @@ public:
|
||||
return ms_pColPool->GetSlot(slot);
|
||||
}
|
||||
};
|
||||
|
||||
const CVector& LevelPos(eLevelName level);
|
||||
|
||||
@@ -62,6 +62,7 @@ struct CColTrianglePlane
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
// TODO(LCS): LCS actually uses CompressedVector too
|
||||
CVector normal;
|
||||
float dist;
|
||||
uint8 dir;
|
||||
|
||||
@@ -24,6 +24,10 @@
|
||||
#include "Camera.h"
|
||||
#include "ColStore.h"
|
||||
|
||||
// gotta figure out how they handled CSphere exactly
|
||||
// so using this to remind me to look into it again.
|
||||
#define CVECTORHACK(rwv3d) CVector(rwv3d)
|
||||
|
||||
#ifdef VU_COLLISION
|
||||
#include "VuCollision.h"
|
||||
|
||||
@@ -101,7 +105,7 @@ GetCollisionInSectorList(CPtrList &list)
|
||||
|
||||
for(node = list.first; node; node = node->next){
|
||||
e = (CEntity*)node->item;
|
||||
level = CModelInfo::GetModelInfo(e->GetModelIndex())->GetColModel()->level;
|
||||
level = CModelInfo::GetColModel(e->GetModelIndex())->level;
|
||||
if(level != LEVEL_GENERIC)
|
||||
return (eLevelName)level;
|
||||
}
|
||||
@@ -144,11 +148,10 @@ CCollision::SortOutCollisionAfterLoad(void)
|
||||
void
|
||||
CCollision::LoadCollisionScreen(eLevelName level)
|
||||
{
|
||||
static Const char *levelNames[4] = {
|
||||
static Const char *levelNames[] = {
|
||||
"",
|
||||
"IND_ZON",
|
||||
"COM_ZON",
|
||||
"SUB_ZON"
|
||||
};
|
||||
|
||||
// Why twice?
|
||||
@@ -399,7 +402,7 @@ CCollision::TestLineSphere(const CColLine &line, const CColSphere &sph)
|
||||
// The length of the tangent would be this: Sqrt((c-p0)^2 - r^2).
|
||||
// Negative if p0 is inside the sphere! This breaks the test!
|
||||
float tansq = 4.0f * linesq *
|
||||
(sph.center.MagnitudeSqr() - 2.0f*DotProduct(sph.center, line.p0) + line.p0.MagnitudeSqr() - sph.radius*sph.radius);
|
||||
(CVECTORHACK(sph.center).MagnitudeSqr() - 2.0f*DotProduct(sph.center, line.p0) + line.p0.MagnitudeSqr() - sph.radius*sph.radius);
|
||||
float diffsq = projline*projline - tansq;
|
||||
// if diffsq < 0 that means the line is a passant, so no intersection
|
||||
if(diffsq < 0.0f)
|
||||
@@ -478,9 +481,9 @@ CCollision::TestSphereTriangle(const CColSphere &sphere,
|
||||
case 2:
|
||||
// closest to an edge
|
||||
// looks like original game as DistToLine manually inlined
|
||||
if(!insideAB) dist = DistToLine(&va, &vb, &sphere.center);
|
||||
else if(!insideAC) dist = DistToLine(&va, &vc, &sphere.center);
|
||||
else if(!insideBC) dist = DistToLine(&vb, &vc, &sphere.center);
|
||||
if(!insideAB) dist = DistToLine(&va, &vb, &CVECTORHACK(sphere.center));
|
||||
else if(!insideAC) dist = DistToLine(&va, &vc, &CVECTORHACK(sphere.center));
|
||||
else if(!insideBC) dist = DistToLine(&vb, &vc, &CVECTORHACK(sphere.center));
|
||||
else assert(0);
|
||||
break;
|
||||
case 3:
|
||||
@@ -1296,9 +1299,9 @@ CCollision::ProcessSphereTriangle(const CColSphere &sphere,
|
||||
case 2:
|
||||
// closest to an edge
|
||||
// looks like original game as DistToLine manually inlined
|
||||
if(!insideAB) dist = DistToLine(&va, &vb, &sphere.center, p);
|
||||
else if(!insideAC) dist = DistToLine(&va, &vc, &sphere.center, p);
|
||||
else if(!insideBC) dist = DistToLine(&vb, &vc, &sphere.center, p);
|
||||
if(!insideAB) dist = DistToLine(&va, &vb, &CVECTORHACK(sphere.center), p);
|
||||
else if(!insideAC) dist = DistToLine(&va, &vc, &CVECTORHACK(sphere.center), p);
|
||||
else if(!insideBC) dist = DistToLine(&vb, &vc, &CVECTORHACK(sphere.center), p);
|
||||
else assert(0);
|
||||
break;
|
||||
case 3:
|
||||
|
||||
@@ -1,22 +1,25 @@
|
||||
#include "common.h"
|
||||
|
||||
#include "main.h"
|
||||
#include "TempColModels.h"
|
||||
#include "Game.h"
|
||||
|
||||
CColModel CTempColModels::ms_colModelPed1;
|
||||
// LCS: haven't yet checked the numbers but they probably haven't changed
|
||||
|
||||
CColModel CTempColModels::ms_colModelPed2;
|
||||
CColModel CTempColModels::ms_colModelBBox;
|
||||
CColModel CTempColModels::ms_colModelBumper1;
|
||||
CColModel CTempColModels::ms_colModelWheel1;
|
||||
CColModel CTempColModels::ms_colModelPanel1;
|
||||
CColModel CTempColModels::ms_colModelBodyPart2;
|
||||
CColModel CTempColModels::ms_colModelBodyPart1;
|
||||
CColModel CTempColModels::ms_colModelCutObj[5];
|
||||
CColModel CTempColModels::ms_colModelCutObj[10];
|
||||
CColModel CTempColModels::ms_colModelPedGroundHit;
|
||||
CColModel CTempColModels::ms_colModelBoot1;
|
||||
CColModel CTempColModels::ms_colModelDoor1;
|
||||
CColModel CTempColModels::ms_colModelBonnet1;
|
||||
CColModel CTempColModels::ms_colModelWeapon;
|
||||
CColModel CTempColModels::ms_colModelFerryDocked;
|
||||
|
||||
CTempColModels *gpTempColModels;
|
||||
|
||||
|
||||
CColSphere s_aPedSpheres[3];
|
||||
@@ -34,6 +37,7 @@ CColSphere s_aBootSpheres[4];
|
||||
CColSphere s_aWheelSpheres[2];
|
||||
CColSphere s_aBodyPartSpheres1[2];
|
||||
CColSphere s_aBodyPartSpheres2[2];
|
||||
CColBox S_aFerryDockedBoxes[1];
|
||||
|
||||
void
|
||||
CTempColModels::Initialise(void)
|
||||
@@ -44,11 +48,26 @@ CTempColModels::Initialise(void)
|
||||
colmodel.level = LEVEL_GENERIC;\
|
||||
colmodel.ownsCollisionVolumes = false;
|
||||
|
||||
int i;
|
||||
if(gMakeResources){
|
||||
if(gpTempColModels == nil){
|
||||
gpTempColModels = new CTempColModels;
|
||||
gpTempColModels->Initialise();
|
||||
return;
|
||||
}
|
||||
|
||||
ms_colModelBBox.boundingSphere.Set(2.0f, CVector(0.0f, 0.0f, 0.0f));
|
||||
ms_colModelBBox.boundingBox.Set(CVector(-2.0f, -2.0f, -2.0f), CVector(2.0f, 2.0f, 2.0f));
|
||||
ms_colModelBBox.level = LEVEL_GENERIC;
|
||||
ms_colModelBBox.boundingSphere.Set(2.0f, CVector(0.0f, 0.0f, 0.0f));
|
||||
ms_colModelBBox.boundingBox.Set(CVector(-2.0f, -2.0f, -2.0f), CVector(2.0f, 2.0f, 2.0f));
|
||||
ms_colModelBBox.level = LEVEL_GENERIC;
|
||||
|
||||
ms_colModelPed1.boundingSphere.Set(1.25f, CVector(0.0f, 0.0f, 0.0f));
|
||||
ms_colModelPed1.boundingBox.Set(CVector(-0.35f, -0.35f, -1.0f), CVector(0.35f, 0.35f, 0.9f));
|
||||
SET_COLMODEL_SPHERES(ms_colModelPed1, s_aPedSpheres);
|
||||
|
||||
ms_colModelWeapon.boundingSphere.Set(0.25f, CVector(0.0f, 0.0f, 0.0f));
|
||||
ms_colModelWeapon.boundingBox.Set(CVector(-0.25f, -0.25f, -0.25f), CVector(0.25f, 0.25f, 0.25f));
|
||||
}
|
||||
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ms_colModelCutObj); i++) {
|
||||
ms_colModelCutObj[i].boundingSphere.Set(2.0f, CVector(0.0f, 0.0f, 0.0f));
|
||||
@@ -74,10 +93,6 @@ CTempColModels::Initialise(void)
|
||||
s_aPedSpheres[i].piece = 0;
|
||||
}
|
||||
|
||||
ms_colModelPed1.boundingSphere.Set(1.25f, CVector(0.0f, 0.0f, 0.0f));
|
||||
ms_colModelPed1.boundingBox.Set(CVector(-0.35f, -0.35f, -1.0f), CVector(0.35f, 0.35f, 0.9f));
|
||||
SET_COLMODEL_SPHERES(ms_colModelPed1, s_aPedSpheres);
|
||||
|
||||
// Ped 2 Spheres
|
||||
|
||||
s_aPed2Spheres[0].radius = 0.3f;
|
||||
@@ -294,13 +309,47 @@ CTempColModels::Initialise(void)
|
||||
|
||||
SET_COLMODEL_SPHERES(ms_colModelBodyPart2, s_aBodyPartSpheres2);
|
||||
|
||||
ms_colModelWeapon.boundingSphere.radius = 0.25f;
|
||||
ms_colModelWeapon.boundingBox.min.x = -0.25f;
|
||||
ms_colModelWeapon.boundingBox.min.y = -0.25f;
|
||||
ms_colModelWeapon.boundingBox.min.z = -0.25f;
|
||||
ms_colModelWeapon.boundingBox.max.x = 0.25f;
|
||||
ms_colModelWeapon.boundingBox.max.y = 0.25f;
|
||||
ms_colModelWeapon.boundingBox.max.z = 0.25f;
|
||||
// Ferry Docked
|
||||
|
||||
S_aFerryDockedBoxes[0].Set(CVector(-6.3f, -22.78f, -2.0f), CVector(6.3f, 22.78f, 2.8f), SURFACE_THICK_METAL_PLATE, SURFACE_DEFAULT);
|
||||
|
||||
ms_colModelFerryDocked.boundingSphere.Set(35.0f, CVector(0.0f, -0.0f, 0.0f));
|
||||
ms_colModelFerryDocked.boundingBox.Set(S_aFerryDockedBoxes[0].min, S_aFerryDockedBoxes[0].max);
|
||||
ms_colModelFerryDocked.spheres = nil;
|
||||
ms_colModelFerryDocked.numSpheres = 0;
|
||||
ms_colModelFerryDocked.boxes = S_aFerryDockedBoxes;
|
||||
ms_colModelFerryDocked.numBoxes = ARRAY_SIZE(S_aFerryDockedBoxes);
|
||||
ms_colModelFerryDocked.level = LEVEL_GENERIC;
|
||||
|
||||
|
||||
#undef SET_COLMODEL_SPHERES
|
||||
}
|
||||
|
||||
void
|
||||
CTempColModels::Write(base::cRelocatableChunkWriter &writer)
|
||||
{
|
||||
writer.AllocateRaw(this, sizeof(*this), 0x10, false, true);
|
||||
|
||||
ms_colModelBBox.Write(writer, false);
|
||||
writer.AddPatch(&ms_colModelBBox);
|
||||
|
||||
ms_colModelPed1.Write(writer, false);
|
||||
writer.AddPatch(&ms_colModelPed1);
|
||||
|
||||
ms_colModelWeapon.Write(writer, false);
|
||||
writer.AddPatch(&ms_colModelWeapon);
|
||||
|
||||
for(int i = 0; i < ARRAY_SIZE(ms_colModelCutObj); i++)
|
||||
ms_colModelCutObj[i].Write(writer, true);
|
||||
ms_colModelPed2.Write(writer, true);
|
||||
ms_colModelPedGroundHit.Write(writer, true);
|
||||
ms_colModelDoor1.Write(writer, true);
|
||||
ms_colModelBumper1.Write(writer, true);
|
||||
ms_colModelPanel1.Write(writer, true);
|
||||
ms_colModelBonnet1.Write(writer, true);
|
||||
ms_colModelBoot1.Write(writer, true);
|
||||
ms_colModelWheel1.Write(writer, true);
|
||||
ms_colModelBodyPart1.Write(writer, true);
|
||||
ms_colModelBodyPart2.Write(writer, true);
|
||||
ms_colModelFerryDocked.Write(writer, true);
|
||||
}
|
||||
|
||||
@@ -5,20 +5,25 @@
|
||||
class CTempColModels
|
||||
{
|
||||
public:
|
||||
static CColModel ms_colModelPed1;
|
||||
CColModel ms_colModelPed1;
|
||||
CColModel ms_colModelBBox;
|
||||
CColModel ms_colModelWeapon;
|
||||
|
||||
static CColModel ms_colModelPed2;
|
||||
static CColModel ms_colModelBBox;
|
||||
static CColModel ms_colModelBumper1;
|
||||
static CColModel ms_colModelWheel1;
|
||||
static CColModel ms_colModelPanel1;
|
||||
static CColModel ms_colModelBodyPart2;
|
||||
static CColModel ms_colModelBodyPart1;
|
||||
static CColModel ms_colModelCutObj[5];
|
||||
static CColModel ms_colModelCutObj[10];
|
||||
static CColModel ms_colModelPedGroundHit;
|
||||
static CColModel ms_colModelBoot1;
|
||||
static CColModel ms_colModelDoor1;
|
||||
static CColModel ms_colModelBonnet1;
|
||||
static CColModel ms_colModelWeapon;
|
||||
static CColModel ms_colModelFerryDocked;
|
||||
|
||||
static void Initialise(void);
|
||||
void Initialise(void);
|
||||
void Write(base::cRelocatableChunkWriter &writer);
|
||||
};
|
||||
|
||||
extern CTempColModels *gpTempColModels;
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
#include "CarCtrl.h"
|
||||
#include "Curves.h"
|
||||
#include "PathFind.h"
|
||||
#include "SaveBuf.h"
|
||||
|
||||
//--LCS: file done
|
||||
|
||||
void CAutoPilot::ModifySpeed(float speed)
|
||||
{
|
||||
@@ -49,86 +52,87 @@ void CAutoPilot::RemoveOnePathNode()
|
||||
#ifdef COMPATIBLE_SAVES
|
||||
void CAutoPilot::Save(uint8*& buf)
|
||||
{
|
||||
WriteSaveBuf<int32>(buf, m_nCurrentRouteNode);
|
||||
WriteSaveBuf<int32>(buf, m_nNextRouteNode);
|
||||
WriteSaveBuf<int32>(buf, m_nPrevRouteNode);
|
||||
WriteSaveBuf<int32>(buf, m_nTimeEnteredCurve);
|
||||
WriteSaveBuf<int32>(buf, m_nTimeToSpendOnCurrentCurve);
|
||||
WriteSaveBuf<uint32>(buf, m_nCurrentPathNodeInfo);
|
||||
WriteSaveBuf<uint32>(buf, m_nNextPathNodeInfo);
|
||||
WriteSaveBuf<uint32>(buf, m_nPreviousPathNodeInfo);
|
||||
WriteSaveBuf<uint32>(buf, m_nAntiReverseTimer);
|
||||
WriteSaveBuf<uint32>(buf, m_nTimeToStartMission);
|
||||
WriteSaveBuf<int8>(buf, m_nPreviousDirection);
|
||||
WriteSaveBuf<int8>(buf, m_nCurrentDirection);
|
||||
WriteSaveBuf<int8>(buf, m_nNextDirection);
|
||||
WriteSaveBuf<int8>(buf, m_nCurrentLane);
|
||||
WriteSaveBuf<int8>(buf, m_nNextLane);
|
||||
WriteSaveBuf<uint8>(buf, m_nDrivingStyle);
|
||||
WriteSaveBuf<uint8>(buf, m_nCarMission);
|
||||
WriteSaveBuf<uint8>(buf, m_nTempAction);
|
||||
WriteSaveBuf<uint32>(buf, m_nTimeTempAction);
|
||||
WriteSaveBuf<float>(buf, m_fMaxTrafficSpeed);
|
||||
WriteSaveBuf<uint8>(buf, m_nCruiseSpeed);
|
||||
WriteSaveBuf<uint8>(buf, m_nCruiseSpeedMultiplierType);
|
||||
SkipSaveBuf(buf, 2);
|
||||
WriteSaveBuf<float>(buf, m_fCruiseSpeedMultiplier);
|
||||
WriteSaveBuf(buf, m_nCurrentRouteNode);
|
||||
WriteSaveBuf(buf, m_nNextRouteNode);
|
||||
WriteSaveBuf(buf, m_nPrevRouteNode);
|
||||
WriteSaveBuf(buf, m_nTimeEnteredCurve);
|
||||
WriteSaveBuf(buf, m_nTimeToSpendOnCurrentCurve);
|
||||
WriteSaveBuf(buf, m_nCurrentPathNodeInfo);
|
||||
WriteSaveBuf(buf, m_nNextPathNodeInfo);
|
||||
WriteSaveBuf(buf, m_nPreviousPathNodeInfo);
|
||||
WriteSaveBuf(buf, m_nAntiReverseTimer);
|
||||
WriteSaveBuf(buf, m_nTimeToStartMission);
|
||||
WriteSaveBuf(buf, m_nPreviousDirection);
|
||||
WriteSaveBuf(buf, m_nCurrentDirection);
|
||||
WriteSaveBuf(buf, m_nNextDirection);
|
||||
WriteSaveBuf(buf, m_nCurrentLane);
|
||||
WriteSaveBuf(buf, m_nNextLane);
|
||||
WriteSaveBuf(buf, m_nDrivingStyle);
|
||||
WriteSaveBuf(buf, m_nCarMission);
|
||||
WriteSaveBuf(buf, m_nTempAction);
|
||||
WriteSaveBuf(buf, m_nTimeTempAction);
|
||||
WriteSaveBuf(buf, m_fMaxTrafficSpeed);
|
||||
WriteSaveBuf(buf, m_nCruiseSpeed);
|
||||
WriteSaveBuf(buf, m_nCruiseSpeedMultiplierType);
|
||||
ZeroSaveBuf(buf, 2);
|
||||
WriteSaveBuf(buf, m_fCruiseSpeedMultiplier);
|
||||
uint8 flags = 0;
|
||||
if (m_bSlowedDownBecauseOfCars) flags |= BIT(0);
|
||||
if (m_bSlowedDownBecauseOfPeds) flags |= BIT(1);
|
||||
if (m_bStayInCurrentLevel) flags |= BIT(2);
|
||||
if (m_bStayInFastLane) flags |= BIT(3);
|
||||
if (m_bIgnorePathfinding) flags |= BIT(4);
|
||||
WriteSaveBuf<uint8>(buf, flags);
|
||||
WriteSaveBuf<uint8>(buf, m_nSwitchDistance);
|
||||
SkipSaveBuf(buf, 2);
|
||||
WriteSaveBuf<float>(buf, m_vecDestinationCoors.x);
|
||||
WriteSaveBuf<float>(buf, m_vecDestinationCoors.y);
|
||||
WriteSaveBuf<float>(buf, m_vecDestinationCoors.z);
|
||||
SkipSaveBuf(buf, 32);
|
||||
WriteSaveBuf<int16>(buf, m_nPathFindNodesCount);
|
||||
SkipSaveBuf(buf, 6);
|
||||
WriteSaveBuf(buf, flags);
|
||||
WriteSaveBuf(buf, m_nSwitchDistance);
|
||||
ZeroSaveBuf(buf, 2);
|
||||
WriteSaveBuf(buf, m_vecDestinationCoors.x);
|
||||
WriteSaveBuf(buf, m_vecDestinationCoors.y);
|
||||
WriteSaveBuf(buf, m_vecDestinationCoors.z);
|
||||
ZeroSaveBuf(buf, 32);
|
||||
WriteSaveBuf(buf, m_nPathFindNodesCount);
|
||||
ZeroSaveBuf(buf, 6);
|
||||
}
|
||||
|
||||
void CAutoPilot::Load(uint8*& buf)
|
||||
{
|
||||
m_nCurrentRouteNode = ReadSaveBuf<int32>(buf);
|
||||
m_nNextRouteNode = ReadSaveBuf<int32>(buf);
|
||||
m_nPrevRouteNode = ReadSaveBuf<int32>(buf);
|
||||
m_nTimeEnteredCurve = ReadSaveBuf<int32>(buf);
|
||||
m_nTimeToSpendOnCurrentCurve = ReadSaveBuf<int32>(buf);
|
||||
m_nCurrentPathNodeInfo = ReadSaveBuf<uint32>(buf);
|
||||
m_nNextPathNodeInfo = ReadSaveBuf<uint32>(buf);
|
||||
m_nPreviousPathNodeInfo = ReadSaveBuf<uint32>(buf);
|
||||
m_nAntiReverseTimer = ReadSaveBuf<uint32>(buf);
|
||||
m_nTimeToStartMission = ReadSaveBuf<uint32>(buf);
|
||||
m_nPreviousDirection = ReadSaveBuf<int8>(buf);
|
||||
m_nCurrentDirection = ReadSaveBuf<int8>(buf);
|
||||
m_nNextDirection = ReadSaveBuf<int8>(buf);
|
||||
m_nCurrentLane = ReadSaveBuf<int8>(buf);
|
||||
m_nNextLane = ReadSaveBuf<int8>(buf);
|
||||
m_nDrivingStyle = ReadSaveBuf<uint8>(buf);
|
||||
m_nCarMission = ReadSaveBuf<uint8>(buf);
|
||||
m_nTempAction = ReadSaveBuf<uint8>(buf);
|
||||
m_nTimeTempAction = ReadSaveBuf<uint32>(buf);
|
||||
m_fMaxTrafficSpeed = ReadSaveBuf<float>(buf);
|
||||
m_nCruiseSpeed = ReadSaveBuf<uint8>(buf);
|
||||
m_nCruiseSpeedMultiplierType = ReadSaveBuf<uint8>(buf);
|
||||
ReadSaveBuf(&m_nCurrentRouteNode, buf);
|
||||
ReadSaveBuf(&m_nNextRouteNode, buf);
|
||||
ReadSaveBuf(&m_nPrevRouteNode, buf);
|
||||
ReadSaveBuf(&m_nTimeEnteredCurve, buf);
|
||||
ReadSaveBuf(&m_nTimeToSpendOnCurrentCurve, buf);
|
||||
ReadSaveBuf(&m_nCurrentPathNodeInfo, buf);
|
||||
ReadSaveBuf(&m_nNextPathNodeInfo, buf);
|
||||
ReadSaveBuf(&m_nPreviousPathNodeInfo, buf);
|
||||
ReadSaveBuf(&m_nAntiReverseTimer, buf);
|
||||
ReadSaveBuf(&m_nTimeToStartMission, buf);
|
||||
ReadSaveBuf(&m_nPreviousDirection, buf);
|
||||
ReadSaveBuf(&m_nCurrentDirection, buf);
|
||||
ReadSaveBuf(&m_nNextDirection, buf);
|
||||
ReadSaveBuf(&m_nCurrentLane, buf);
|
||||
ReadSaveBuf(&m_nNextLane, buf);
|
||||
ReadSaveBuf(&m_nDrivingStyle, buf);
|
||||
ReadSaveBuf(&m_nCarMission, buf);
|
||||
ReadSaveBuf(&m_nTempAction, buf);
|
||||
ReadSaveBuf(&m_nTimeTempAction, buf);
|
||||
ReadSaveBuf(&m_fMaxTrafficSpeed, buf);
|
||||
ReadSaveBuf(&m_nCruiseSpeed, buf);
|
||||
ReadSaveBuf(&m_nCruiseSpeedMultiplierType, buf);
|
||||
SkipSaveBuf(buf, 2);
|
||||
m_fCruiseSpeedMultiplier = ReadSaveBuf<float>(buf);
|
||||
uint8 flags = ReadSaveBuf<uint8>(buf);
|
||||
ReadSaveBuf(&m_fCruiseSpeedMultiplier, buf);
|
||||
uint8 flags;
|
||||
ReadSaveBuf(&flags, buf);
|
||||
m_bSlowedDownBecauseOfCars = !!(flags & BIT(0));
|
||||
m_bSlowedDownBecauseOfPeds = !!(flags & BIT(1));
|
||||
m_bStayInCurrentLevel = !!(flags & BIT(2));
|
||||
m_bStayInFastLane = !!(flags & BIT(3));
|
||||
m_bIgnorePathfinding = !!(flags & BIT(4));
|
||||
m_nSwitchDistance = ReadSaveBuf<uint8>(buf);
|
||||
ReadSaveBuf(&m_nSwitchDistance, buf);
|
||||
SkipSaveBuf(buf, 2);
|
||||
m_vecDestinationCoors.x = ReadSaveBuf<float>(buf);
|
||||
m_vecDestinationCoors.y = ReadSaveBuf<float>(buf);
|
||||
m_vecDestinationCoors.z = ReadSaveBuf<float>(buf);
|
||||
ReadSaveBuf(&m_vecDestinationCoors.x, buf);
|
||||
ReadSaveBuf(&m_vecDestinationCoors.y, buf);
|
||||
ReadSaveBuf(&m_vecDestinationCoors.z, buf);
|
||||
SkipSaveBuf(buf, 32);
|
||||
m_nPathFindNodesCount = ReadSaveBuf<int16>(buf);
|
||||
ReadSaveBuf(&m_nPathFindNodesCount, buf);
|
||||
SkipSaveBuf(buf, 6);
|
||||
}
|
||||
#endif
|
||||
@@ -6,6 +6,8 @@
|
||||
#include "PathFind.h"
|
||||
#include "Stats.h"
|
||||
|
||||
//--LCS: file done except TODO
|
||||
|
||||
CEntity *CBridge::pLiftRoad;
|
||||
CEntity *CBridge::pLiftPart;
|
||||
CEntity *CBridge::pWeight;
|
||||
@@ -25,14 +27,14 @@ void CBridge::Init()
|
||||
{
|
||||
#ifdef GTA_BRIDGE
|
||||
FindBridgeEntities();
|
||||
State = STATE_BRIDGE_LOCKED;
|
||||
OldLift = -1.0f;
|
||||
if (pLiftPart && pWeight)
|
||||
{
|
||||
DefaultZLiftPart = pLiftPart->GetPosition().z;
|
||||
DefaultZLiftWeight = pWeight->GetPosition().z;
|
||||
|
||||
if (pLiftRoad)
|
||||
DefaultZLiftRoad = pLiftRoad->GetPosition().z;
|
||||
DefaultZLiftWeight = pWeight->GetPosition().z;
|
||||
|
||||
ThePaths.SetLinksBridgeLights(-330.0, -230.0, -700.0, -588.0, true);
|
||||
}
|
||||
@@ -49,36 +51,42 @@ void CBridge::Update()
|
||||
|
||||
float liftHeight;
|
||||
|
||||
// Set bridge height and state
|
||||
if (CStats::CommercialPassed)
|
||||
{
|
||||
if (State == STATE_BRIDGE_LOCKED) {
|
||||
liftHeight = 25.0f;
|
||||
TimeOfBridgeBecomingOperational = 0;
|
||||
}
|
||||
else if (State == STATE_BRIDGE_ALWAYS_UNLOCKED) {
|
||||
liftHeight = 0.0f;
|
||||
TimeOfBridgeBecomingOperational = CTimer::GetTimeInMilliseconds() - 20001;
|
||||
}
|
||||
else {
|
||||
if (TimeOfBridgeBecomingOperational == 0)
|
||||
TimeOfBridgeBecomingOperational = CTimer::GetTimeInMilliseconds();
|
||||
|
||||
// Time remaining for bridge to become operational
|
||||
// uint16, so after about a minute it overflows to 0 and the cycle repeats
|
||||
uint16 timeElapsed = CTimer::GetTimeInMilliseconds() - TimeOfBridgeBecomingOperational;
|
||||
// this time cycle duration is 0x20000, so ~2:11
|
||||
uint32 timeElapsed = (CTimer::GetTimeInMilliseconds() - TimeOfBridgeBecomingOperational) % 0x20000;
|
||||
|
||||
// Calculate lift part height and bridge state
|
||||
if (timeElapsed < 10000)
|
||||
if (timeElapsed < 20000)
|
||||
{
|
||||
State = STATE_LIFT_PART_MOVING_DOWN;
|
||||
liftHeight = 25.0f - timeElapsed / 10000.0f * 25.0f;
|
||||
liftHeight = 25.0f - timeElapsed / 20000.0f * 25.0f;
|
||||
}
|
||||
else if (timeElapsed < 40000)
|
||||
else if (timeElapsed < 80000)
|
||||
{
|
||||
liftHeight = 0.0f;
|
||||
State = STATE_LIFT_PART_IS_DOWN;
|
||||
}
|
||||
else if (timeElapsed < 50000)
|
||||
else if (timeElapsed < 90000)
|
||||
{
|
||||
liftHeight = 0.0f;
|
||||
State = STATE_LIFT_PART_ABOUT_TO_MOVE_UP;
|
||||
}
|
||||
else if (timeElapsed < 60000)
|
||||
else if (timeElapsed < 110000)
|
||||
{
|
||||
State = STATE_LIFT_PART_MOVING_UP;
|
||||
liftHeight = (timeElapsed - 50000) / 10000.0f * 25.0f;
|
||||
liftHeight = (timeElapsed - 90000) / 20000.0f * 25.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -86,12 +94,7 @@ void CBridge::Update()
|
||||
State = STATE_LIFT_PART_IS_UP;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
liftHeight = 25.0f;
|
||||
TimeOfBridgeBecomingOperational = 0;
|
||||
State = STATE_BRIDGE_LOCKED;
|
||||
}
|
||||
|
||||
|
||||
// Move bridge part
|
||||
if (liftHeight != OldLift)
|
||||
@@ -112,6 +115,8 @@ void CBridge::Update()
|
||||
OldLift = liftHeight;
|
||||
}
|
||||
|
||||
// TODO(LCS): cWorldStream
|
||||
|
||||
if (State == STATE_LIFT_PART_ABOUT_TO_MOVE_UP && OldState == STATE_LIFT_PART_IS_DOWN)
|
||||
ThePaths.SetLinksBridgeLights(-330.0, -230.0, -700.0, -588.0, true);
|
||||
else if (State == STATE_LIFT_PART_IS_DOWN && OldState == STATE_LIFT_PART_MOVING_DOWN)
|
||||
@@ -161,3 +166,23 @@ bool CBridge::ThisIsABridgeObjectMovingUp(int index)
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void CBridge::ForceBridgeState(uint8 state)
|
||||
{
|
||||
#ifdef GTA_BRIDGE
|
||||
State = state;
|
||||
switch (state)
|
||||
{
|
||||
case STATE_BRIDGE_LOCKED:
|
||||
case STATE_LIFT_PART_MOVING_DOWN:
|
||||
case STATE_LIFT_PART_ABOUT_TO_MOVE_UP:
|
||||
ThePaths.SetLinksBridgeLights(-330.0f, -230.0f, -700.0f, -588.0f, true);
|
||||
break;
|
||||
case STATE_BRIDGE_ALWAYS_UNLOCKED:
|
||||
ThePaths.SetLinksBridgeLights(-330.0f, -230.0f, -700.0f, -588.0f, false);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -8,7 +8,8 @@ enum bridgeStates {
|
||||
STATE_LIFT_PART_MOVING_DOWN,
|
||||
STATE_LIFT_PART_IS_DOWN,
|
||||
STATE_LIFT_PART_ABOUT_TO_MOVE_UP,
|
||||
STATE_LIFT_PART_MOVING_UP
|
||||
STATE_LIFT_PART_MOVING_UP,
|
||||
STATE_BRIDGE_ALWAYS_UNLOCKED
|
||||
};
|
||||
|
||||
class CBridge
|
||||
@@ -25,4 +26,5 @@ public:
|
||||
static bool ShouldLightsBeFlashing();
|
||||
static void FindBridgeEntities();
|
||||
static bool ThisIsABridgeObjectMovingUp(int);
|
||||
static void ForceBridgeState(uint8 state);
|
||||
};
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "Accident.h"
|
||||
#include "AutoPilot.h"
|
||||
#include "Bridge.h"
|
||||
#include "CarCtrl.h"
|
||||
#include "General.h"
|
||||
#include "HandlingMgr.h"
|
||||
@@ -20,6 +21,8 @@
|
||||
#include "World.h"
|
||||
#include "ZoneCull.h"
|
||||
|
||||
//--LCS: file done
|
||||
|
||||
#define DISTANCE_TO_SWITCH_DISTANCE_GOTO 20.0f
|
||||
|
||||
float CCarAI::FindSwitchDistanceClose(CVehicle* pVehicle)
|
||||
@@ -72,6 +75,18 @@ void CCarAI::UpdateCarAI(CVehicle* pVehicle)
|
||||
case STATUS_PLAYER_DISABLED:
|
||||
break;
|
||||
case STATUS_SIMPLE:
|
||||
{
|
||||
if (pVehicle->m_pCurGroundEntity && CBridge::ThisIsABridgeObjectMovingUp(pVehicle->m_pCurGroundEntity->GetModelIndex()))
|
||||
pVehicle->SetStatus(STATUS_PHYSICS);
|
||||
CColPoint colPoint;
|
||||
CEntity* pEntity;
|
||||
if ((pVehicle->m_randomSeed & 0x3F) == (CTimer::GetFrameCounter() & 0x3F) &&
|
||||
!CWorld::ProcessVerticalLine(pVehicle->GetPosition(), -2.0f, colPoint, pEntity, true, false, false, false, true, false, nil)) {
|
||||
debug("FLOATING CAR TURNED INTO PHYSICS CAR!\n");
|
||||
pVehicle->SetStatus(STATUS_PHYSICS);
|
||||
}
|
||||
}
|
||||
// fallthough
|
||||
case STATUS_PHYSICS:
|
||||
switch (pVehicle->AutoPilot.m_nCarMission) {
|
||||
case MISSION_RAMPLAYER_FARAWAY:
|
||||
@@ -584,8 +599,18 @@ void CCarAI::TellOccupantsToLeaveCar(CVehicle* pVehicle)
|
||||
{
|
||||
if (pVehicle->pDriver){
|
||||
pVehicle->pDriver->SetObjective(OBJECTIVE_LEAVE_CAR, pVehicle);
|
||||
if (pVehicle->GetModelIndex() == MI_AMBULAN)
|
||||
switch (pVehicle->GetModelIndex()) {
|
||||
case MI_FIRETRUCK:
|
||||
case MI_FBICAR:
|
||||
case MI_ENFORCER:
|
||||
case MI_BARRACKS:
|
||||
case MI_RHINO:
|
||||
case MI_POLICE:
|
||||
break;
|
||||
case MI_AMBULAN:
|
||||
pVehicle->pDriver->Say(SOUND_PED_LEAVE_VEHICLE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
int timer = 100;
|
||||
for (int i = 0; i < pVehicle->m_nNumMaxPassengers; i++){
|
||||
@@ -601,8 +626,18 @@ void CCarAI::TellOccupantsToFleeCar(CVehicle* pVehicle)
|
||||
{
|
||||
if (pVehicle->pDriver && !pVehicle->pDriver->IsPlayer()) {
|
||||
pVehicle->pDriver->SetObjective(OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE);
|
||||
if (pVehicle->GetModelIndex() != MI_FIRETRUCK && pVehicle->GetModelIndex() == MI_AMBULAN)
|
||||
switch (pVehicle->GetModelIndex()) {
|
||||
case MI_FIRETRUCK:
|
||||
case MI_FBIRANCH:
|
||||
case MI_ENFORCER:
|
||||
case MI_BARRACKS:
|
||||
case MI_RHINO:
|
||||
case MI_POLICE:
|
||||
break;
|
||||
case MI_AMBULAN:
|
||||
pVehicle->pDriver->Say(SOUND_PED_LEAVE_VEHICLE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
int timer = 100;
|
||||
for (int i = 0; i < pVehicle->m_nNumMaxPassengers; i++) {
|
||||
|
||||
@@ -11,11 +11,13 @@
|
||||
#include "Cranes.h"
|
||||
#include "Curves.h"
|
||||
#include "CutsceneMgr.h"
|
||||
#include "Frontend.h"
|
||||
#include "Gangs.h"
|
||||
#include "Game.h"
|
||||
#include "Garages.h"
|
||||
#include "General.h"
|
||||
#include "IniFile.h"
|
||||
#include "Lines.h"
|
||||
#include "ModelIndices.h"
|
||||
#include "PathFind.h"
|
||||
#include "Ped.h"
|
||||
@@ -37,7 +39,9 @@
|
||||
#include "Zones.h"
|
||||
#include "Pickups.h"
|
||||
|
||||
#define DISTANCE_TO_SPAWN_ROADBLOCK_PEDS (51.0f)
|
||||
//--LCS: file done except TODO
|
||||
|
||||
#define DISTANCE_TO_SPAWN_ROADBLOCK_PEDS (51.0f) // apparently POPULATION_CULL_RANGE? TODO: unite with CPopulation
|
||||
#define DISTANCE_TO_SCAN_FOR_DANGER (14.0f)
|
||||
#define DISTANCE_TO_SCAN_FOR_PED_DANGER (11.0f)
|
||||
#define SAFE_DISTANCE_TO_PED (3.0f)
|
||||
@@ -77,12 +81,30 @@
|
||||
#define DISTANCE_BETWEEN_CAR_AND_DEAD_PED (6.0f)
|
||||
#define PROBABILITY_OF_PASSENGER_IN_VEHICLE (0.125f)
|
||||
|
||||
#define ONSCREEN_DESPAWN_RANGE (120.0f)
|
||||
#ifdef GTA_PSP
|
||||
#define ONSCREEN_DESPAWN_RANGE (160.0f)
|
||||
#define MINIMAL_DISTANCE_TO_SPAWN_ONSCREEN (100.0f)
|
||||
#define REQUEST_ONSCREEN_DISTANCE ((ONSCREEN_DESPAWN_RANGE + MINIMAL_DISTANCE_TO_SPAWN_ONSCREEN) / 2)
|
||||
#define OFFSCREEN_DESPAWN_RANGE (40.0f)
|
||||
#define MAX_DISTANCE_FROM_CAMERA_TO_SPAWN_ONSCREEN (82.5f)
|
||||
#else
|
||||
#define ONSCREEN_DESPAWN_RANGE (190.0f)
|
||||
#define MINIMAL_DISTANCE_TO_SPAWN_ONSCREEN (130.0f)
|
||||
#define MAX_DISTANCE_FROM_CAMERA_TO_SPAWN_ONSCREEN (105.0f)
|
||||
#endif
|
||||
|
||||
#define REQUEST_ONSCREEN_DISTANCE (140.0f)
|
||||
#define OFFSCREEN_DESPAWN_RANGE (60.0f)
|
||||
#define MINIMAL_DISTANCE_TO_SPAWN_OFFSCREEN (40.0f)
|
||||
#define EXTENDED_RANGE_DESPAWN_MULTIPLIER (1.5f)
|
||||
|
||||
#ifdef GTA_NETWORK
|
||||
const int32 CCarCtrl::MultiplayerCarBanks[TOTAL_MULTIPLAYER_CAR_BANKS][CARS_IN_MULTIPLAYER_BANK] =
|
||||
{
|
||||
MI_SANCHEZ, MI_KURUMA, MI_ESPRIT, MI_MULE, MI_DIABLOS, MI_KURUMA, MI_PEREN, MI_STINGER,
|
||||
MI_PCJ600, MI_BOBCAT, MI_BLISTA, MI_LANDSTAL,MI_SENTINEL,MI_MOONBEAM,MI_MANANA, MI_PEREN,
|
||||
MI_SANCHEZ2,MI_PCJ600, MI_STALLION,MI_MANANA, MI_LINERUN, MI_RCBANDIT,MI_MRWONGS, MI_STINGER
|
||||
};
|
||||
#endif
|
||||
|
||||
bool CCarCtrl::bMadDriversCheat;
|
||||
int CCarCtrl::NumLawEnforcerCars;
|
||||
int CCarCtrl::NumAmbulancesOnDuty;
|
||||
@@ -94,7 +116,7 @@ int32 CCarCtrl::NumRandomCars;
|
||||
int32 CCarCtrl::NumParkedCars;
|
||||
int32 CCarCtrl::NumPermanentCars;
|
||||
int8 CCarCtrl::CountDownToCarsAtStart;
|
||||
int32 CCarCtrl::MaxNumberOfCarsInUse = 12;
|
||||
int32 CCarCtrl::MaxNumberOfCarsInUse = DEFAULT_MAX_NUMBER_OF_CARS;
|
||||
uint32 CCarCtrl::LastTimeLawEnforcerCreated;
|
||||
uint32 CCarCtrl::LastTimeFireTruckCreated;
|
||||
uint32 CCarCtrl::LastTimeAmbulanceCreated;
|
||||
@@ -108,6 +130,15 @@ int32 CCarCtrl::CarFreqArrays[TOTAL_CUSTOM_CLASSES][MAX_CAR_MODELS_IN_ARRAY];
|
||||
int32 CCarCtrl::LoadedCarsArray[TOTAL_CUSTOM_CLASSES][MAX_CAR_MODELS_IN_ARRAY];
|
||||
CVehicle* apCarsToKeep[MAX_CARS_TO_KEEP];
|
||||
uint32 aCarsToKeepTime[MAX_CARS_TO_KEEP];
|
||||
uint32 CCarCtrl::maxRandomMpCars = 20;
|
||||
bool CCarCtrl::scriptControlsMpCarLimit = false;
|
||||
|
||||
bool gbEmergencyVehiclesEnabled = true;
|
||||
|
||||
#ifdef GTA_NETWORK // TMP
|
||||
extern bool gIsMultiplayerGame;
|
||||
extern int8 nAmbientCarBank; // actually gMultiGame.nAmbientCarBank (TODO)
|
||||
#endif
|
||||
|
||||
void
|
||||
CCarCtrl::GenerateRandomCars()
|
||||
@@ -141,31 +172,60 @@ CCarCtrl::GenerateOneRandomCar()
|
||||
CZoneInfo zone;
|
||||
CTheZones::GetZoneInfoForTimeOfDay(&vecTargetPos, &zone);
|
||||
pPlayer->m_nTrafficMultiplier = pPlayer->m_fRoadDensity * zone.carDensity;
|
||||
if (NumRandomCars >= pPlayer->m_nTrafficMultiplier * CarDensityMultiplier * CIniFile::CarNumberMultiplier)
|
||||
return;
|
||||
if (NumFiretrucksOnDuty + NumAmbulancesOnDuty + NumParkedCars + NumMissionCars + NumLawEnforcerCars + NumRandomCars >= MaxNumberOfCarsInUse)
|
||||
return;
|
||||
#ifdef GTA_NETWORK
|
||||
if (gIsMultiplayerGame) {
|
||||
// TODO (count number of players within 250 meters from spawn position
|
||||
int numPlayersClose = 1;
|
||||
if (NumRandomCars >= pPlayer->m_nTrafficMultiplier * CarDensityMultiplier * CIniFile::CarNumberMultiplier * numPlayersClose)
|
||||
return;
|
||||
if (NumFiretrucksOnDuty + NumAmbulancesOnDuty + NumParkedCars + NumMissionCars + NumLawEnforcerCars + NumRandomCars >= MaxNumberOfCarsInUse)
|
||||
return;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (NumRandomCars >= pPlayer->m_nTrafficMultiplier * CarDensityMultiplier * CIniFile::CarNumberMultiplier)
|
||||
return;
|
||||
if (NumFiretrucksOnDuty + NumAmbulancesOnDuty + NumParkedCars + NumMissionCars + NumLawEnforcerCars + NumRandomCars >= MaxNumberOfCarsInUse)
|
||||
return;
|
||||
}
|
||||
CWanted* pWanted = pPlayer->m_pPed->m_pWanted;
|
||||
int carClass;
|
||||
int carModel;
|
||||
if (pWanted->GetWantedLevel() > 1 && NumLawEnforcerCars < pWanted->m_MaximumLawEnforcerVehicles &&
|
||||
pWanted->m_CurrentCops < pWanted->m_MaxCops && !CGame::IsInInterior() && (
|
||||
pWanted->GetWantedLevel() > 3 ||
|
||||
pWanted->GetWantedLevel() > 2 && CTimer::GetTimeInMilliseconds() > LastTimeLawEnforcerCreated + 5000 ||
|
||||
pWanted->GetWantedLevel() > 1 && CTimer::GetTimeInMilliseconds() > LastTimeLawEnforcerCreated + 8000)) {
|
||||
/* Last pWanted->GetWantedLevel() > 1 is unnecessary but I added it for better readability. */
|
||||
/* Wouldn't be surprised it was there originally but was optimized out. */
|
||||
carClass = COPS;
|
||||
carModel = ChoosePoliceCarModel();
|
||||
}else{
|
||||
#ifdef GTA_NETWORK
|
||||
if (gIsMultiplayerGame) {
|
||||
carModel = ChooseModel(&zone, &carClass);
|
||||
if (carModel == -1 || (carClass == COPS && pWanted->GetWantedLevel() >= 1))
|
||||
/* All cop spawns with wanted level are handled by condition above. */
|
||||
/* In particular it means that cop cars never spawn if player has wanted level of 1. */
|
||||
if (carModel == -1)
|
||||
return;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (pWanted->GetWantedLevel() > 1 && NumLawEnforcerCars < pWanted->m_MaximumLawEnforcerVehicles &&
|
||||
pWanted->m_CurrentCops < pWanted->m_MaxCops && !CGame::IsInInterior() && (
|
||||
pWanted->GetWantedLevel() > 3 ||
|
||||
pWanted->GetWantedLevel() > 2 && CTimer::GetTimeInMilliseconds() > LastTimeLawEnforcerCreated + 5000 ||
|
||||
pWanted->GetWantedLevel() > 1 && CTimer::GetTimeInMilliseconds() > LastTimeLawEnforcerCreated + 8000)) {
|
||||
/* Last pWanted->GetWantedLevel() > 1 is unnecessary but I added it for better readability. */
|
||||
/* Wouldn't be surprised it was there originally but was optimized out. */
|
||||
carClass = COPS;
|
||||
carModel = ChoosePoliceCarModel();
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < 5; i++) {
|
||||
carModel = ChooseModel(&zone, &carClass);
|
||||
if (carModel == -1)
|
||||
return;
|
||||
if (!(carClass == COPS && pWanted->GetWantedLevel() >= 1))
|
||||
/* All cop spawns with wanted level are handled by condition above. */
|
||||
/* In particular it means that cop cars never spawn if player has wanted level of 1. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
float frontX, frontY;
|
||||
float preferredDistance, angleLimit;
|
||||
float requestMultiplier = 1.0f;
|
||||
bool invertAngleLimitTest;
|
||||
CVector spawnPosition;
|
||||
int32 curNodeId, nextNodeId;
|
||||
@@ -185,11 +245,14 @@ CCarCtrl::GenerateOneRandomCar()
|
||||
angleLimit = -1.0f;
|
||||
bTopDownCamera = true;
|
||||
invertAngleLimitTest = true;
|
||||
preferredDistance = OFFSCREEN_DESPAWN_RANGE + 15.0f;
|
||||
preferredDistance = MINIMAL_DISTANCE_TO_SPAWN_OFFSCREEN + 15.0f;
|
||||
/* BUG: testForCollision not initialized in original game. */
|
||||
testForCollision = false;
|
||||
}else if (!pPlayerVehicle){
|
||||
/* Player is not in vehicle. */
|
||||
requestMultiplier = 13.0f / 20.0f;
|
||||
if (FrontEndMenuManager.m_PrefsUseWideScreen) // TODO(LCS): static
|
||||
requestMultiplier *= 4.0f / 3.0f;
|
||||
testForCollision = true;
|
||||
frontX = TheCamera.CamFrontXNorm;
|
||||
frontY = TheCamera.CamFrontYNorm;
|
||||
@@ -199,95 +262,105 @@ CCarCtrl::GenerateOneRandomCar()
|
||||
/* Forward to his current direction (camera direction). */
|
||||
angleLimit = 0.707f; /* 45 degrees */
|
||||
invertAngleLimitTest = true;
|
||||
preferredDistance = REQUEST_ONSCREEN_DISTANCE * TheCamera.GenerationDistMultiplier;
|
||||
preferredDistance = REQUEST_ONSCREEN_DISTANCE * requestMultiplier * TheCamera.GenerationDistMultiplier;
|
||||
break;
|
||||
case 1:
|
||||
/* Spawn a vehicle close to player to his side. */
|
||||
/* Kinda not within camera angle. */
|
||||
angleLimit = 0.707f; /* 45 degrees */
|
||||
invertAngleLimitTest = false;
|
||||
preferredDistance = OFFSCREEN_DESPAWN_RANGE;
|
||||
preferredDistance = MINIMAL_DISTANCE_TO_SPAWN_OFFSCREEN;
|
||||
break;
|
||||
}
|
||||
}else if (fPlayerVehicleSpeed > 0.4f){ /* 72 km/h */
|
||||
}
|
||||
else {
|
||||
requestMultiplier = 13.0f / 20.0f;
|
||||
if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_1STPERSON && !FrontEndMenuManager.m_PrefsUseWideScreen)
|
||||
requestMultiplier *= 0.9f;
|
||||
if (FrontEndMenuManager.m_PrefsUseWideScreen) // TODO(LCS): static
|
||||
requestMultiplier *= 4.0f / 3.0f;
|
||||
if (fPlayerVehicleSpeed > 0.4f) { /* 72 km/h */
|
||||
/* Player is moving fast in vehicle */
|
||||
/* Prefer spawning vehicles very far away from him. */
|
||||
frontX = vecPlayerVehicleSpeed.x / fPlayerVehicleSpeed;
|
||||
frontY = vecPlayerVehicleSpeed.y / fPlayerVehicleSpeed;
|
||||
testForCollision = false;
|
||||
switch (CTimer::GetFrameCounter() & 3) {
|
||||
case 0:
|
||||
case 1:
|
||||
/* Spawn a vehicle in a very narrow gap in front of a player */
|
||||
angleLimit = 0.85f; /* approx 30 degrees */
|
||||
invertAngleLimitTest = true;
|
||||
preferredDistance = REQUEST_ONSCREEN_DISTANCE * TheCamera.GenerationDistMultiplier;
|
||||
break;
|
||||
case 2:
|
||||
/* Spawn a vehicle relatively far away from player. */
|
||||
/* Forward to his current direction (camera direction). */
|
||||
angleLimit = 0.707f; /* 45 degrees */
|
||||
invertAngleLimitTest = true;
|
||||
preferredDistance = REQUEST_ONSCREEN_DISTANCE * TheCamera.GenerationDistMultiplier;
|
||||
break;
|
||||
case 3:
|
||||
/* Spawn a vehicle close to player to his side. */
|
||||
/* Kinda not within camera angle. */
|
||||
angleLimit = 0.707f; /* 45 degrees */
|
||||
invertAngleLimitTest = false;
|
||||
preferredDistance = OFFSCREEN_DESPAWN_RANGE;
|
||||
break;
|
||||
frontX = vecPlayerVehicleSpeed.x / fPlayerVehicleSpeed;
|
||||
frontY = vecPlayerVehicleSpeed.y / fPlayerVehicleSpeed;
|
||||
testForCollision = false;
|
||||
switch (CTimer::GetFrameCounter() & 3) {
|
||||
case 0:
|
||||
case 1:
|
||||
/* Spawn a vehicle in a very narrow gap in front of a player */
|
||||
angleLimit = 0.85f; /* approx 30 degrees */
|
||||
invertAngleLimitTest = true;
|
||||
preferredDistance = REQUEST_ONSCREEN_DISTANCE * requestMultiplier * TheCamera.GenerationDistMultiplier;
|
||||
break;
|
||||
case 2:
|
||||
/* Spawn a vehicle relatively far away from player. */
|
||||
/* Forward to his current direction (camera direction). */
|
||||
angleLimit = 0.707f; /* 45 degrees */
|
||||
invertAngleLimitTest = true;
|
||||
preferredDistance = REQUEST_ONSCREEN_DISTANCE * requestMultiplier * TheCamera.GenerationDistMultiplier;
|
||||
break;
|
||||
case 3:
|
||||
/* Spawn a vehicle close to player to his side. */
|
||||
/* Kinda not within camera angle. */
|
||||
angleLimit = 0.707f; /* 45 degrees */
|
||||
invertAngleLimitTest = false;
|
||||
preferredDistance = MINIMAL_DISTANCE_TO_SPAWN_OFFSCREEN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}else if (fPlayerVehicleSpeed > 0.1f){ /* 18 km/h */
|
||||
/* Player is moving moderately fast in vehicle */
|
||||
/* Spawn more vehicles to player's side. */
|
||||
frontX = vecPlayerVehicleSpeed.x / fPlayerVehicleSpeed;
|
||||
frontY = vecPlayerVehicleSpeed.y / fPlayerVehicleSpeed;
|
||||
testForCollision = false;
|
||||
switch (CTimer::GetFrameCounter() & 3) {
|
||||
case 0:
|
||||
/* Spawn a vehicle in a very narrow gap in front of a player */
|
||||
angleLimit = 0.85f; /* approx 30 degrees */
|
||||
invertAngleLimitTest = true;
|
||||
preferredDistance = REQUEST_ONSCREEN_DISTANCE * TheCamera.GenerationDistMultiplier;
|
||||
break;
|
||||
case 1:
|
||||
/* Spawn a vehicle relatively far away from player. */
|
||||
/* Forward to his current direction (camera direction). */
|
||||
angleLimit = 0.707f; /* 45 degrees */
|
||||
invertAngleLimitTest = true;
|
||||
preferredDistance = REQUEST_ONSCREEN_DISTANCE * TheCamera.GenerationDistMultiplier;
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
/* Spawn a vehicle close to player to his side. */
|
||||
/* Kinda not within camera angle. */
|
||||
angleLimit = 0.707f; /* 45 degrees */
|
||||
invertAngleLimitTest = false;
|
||||
preferredDistance = OFFSCREEN_DESPAWN_RANGE;
|
||||
break;
|
||||
else if (fPlayerVehicleSpeed > 0.1f) { /* 18 km/h */
|
||||
/* Player is moving moderately fast in vehicle */
|
||||
/* Spawn more vehicles to player's side. */
|
||||
frontX = vecPlayerVehicleSpeed.x / fPlayerVehicleSpeed;
|
||||
frontY = vecPlayerVehicleSpeed.y / fPlayerVehicleSpeed;
|
||||
testForCollision = false;
|
||||
switch (CTimer::GetFrameCounter() & 3) {
|
||||
case 0:
|
||||
/* Spawn a vehicle in a very narrow gap in front of a player */
|
||||
angleLimit = 0.85f; /* approx 30 degrees */
|
||||
invertAngleLimitTest = true;
|
||||
preferredDistance = REQUEST_ONSCREEN_DISTANCE * requestMultiplier * TheCamera.GenerationDistMultiplier;
|
||||
break;
|
||||
case 1:
|
||||
/* Spawn a vehicle relatively far away from player. */
|
||||
/* Forward to his current direction (camera direction). */
|
||||
angleLimit = 0.707f; /* 45 degrees */
|
||||
invertAngleLimitTest = true;
|
||||
preferredDistance = REQUEST_ONSCREEN_DISTANCE * requestMultiplier * TheCamera.GenerationDistMultiplier;
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
/* Spawn a vehicle close to player to his side. */
|
||||
/* Kinda not within camera angle. */
|
||||
angleLimit = 0.707f; /* 45 degrees */
|
||||
invertAngleLimitTest = false;
|
||||
preferredDistance = MINIMAL_DISTANCE_TO_SPAWN_OFFSCREEN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
/* Player is in vehicle but moving very slow. */
|
||||
/* Then use camera direction instead of vehicle direction. */
|
||||
testForCollision = true;
|
||||
frontX = TheCamera.CamFrontXNorm;
|
||||
frontY = TheCamera.CamFrontYNorm;
|
||||
switch (CTimer::GetFrameCounter() & 1) {
|
||||
case 0:
|
||||
/* Spawn a vehicle relatively far away from player. */
|
||||
/* Forward to his current direction (camera direction). */
|
||||
angleLimit = 0.707f; /* 45 degrees */
|
||||
invertAngleLimitTest = true;
|
||||
preferredDistance = REQUEST_ONSCREEN_DISTANCE * TheCamera.GenerationDistMultiplier;
|
||||
break;
|
||||
case 1:
|
||||
/* Spawn a vehicle close to player to his side. */
|
||||
/* Kinda not within camera angle. */
|
||||
angleLimit = 0.707f; /* 45 degrees */
|
||||
invertAngleLimitTest = false;
|
||||
preferredDistance = OFFSCREEN_DESPAWN_RANGE;
|
||||
break;
|
||||
else {
|
||||
/* Player is in vehicle but moving very slow. */
|
||||
/* Then use camera direction instead of vehicle direction. */
|
||||
testForCollision = true;
|
||||
frontX = TheCamera.CamFrontXNorm;
|
||||
frontY = TheCamera.CamFrontYNorm;
|
||||
switch (CTimer::GetFrameCounter() & 1) {
|
||||
case 0:
|
||||
/* Spawn a vehicle relatively far away from player. */
|
||||
/* Forward to his current direction (camera direction). */
|
||||
angleLimit = 0.707f; /* 45 degrees */
|
||||
invertAngleLimitTest = true;
|
||||
preferredDistance = REQUEST_ONSCREEN_DISTANCE * requestMultiplier * TheCamera.GenerationDistMultiplier;
|
||||
break;
|
||||
case 1:
|
||||
/* Spawn a vehicle close to player to his side. */
|
||||
/* Kinda not within camera angle. */
|
||||
angleLimit = 0.707f; /* 45 degrees */
|
||||
invertAngleLimitTest = false;
|
||||
preferredDistance = MINIMAL_DISTANCE_TO_SPAWN_OFFSCREEN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!ThePaths.GenerateCarCreationCoors(vecTargetPos.x, vecTargetPos.y, frontX, frontY,
|
||||
@@ -297,6 +370,8 @@ CCarCtrl::GenerateOneRandomCar()
|
||||
CPathNode* pCurNode = &ThePaths.m_pathNodes[curNodeId];
|
||||
CPathNode* pNextNode = &ThePaths.m_pathNodes[nextNodeId];
|
||||
bool bBoatGenerated = false;
|
||||
if (!OkToCreateVehicleAtThisPosition(spawnPosition))
|
||||
return;
|
||||
if ((CGeneral::GetRandomNumber() & 0xF) > Min(pCurNode->spawnRate, pNextNode->spawnRate))
|
||||
return;
|
||||
if (pCurNode->bWaterPath) {
|
||||
@@ -346,10 +421,16 @@ CCarCtrl::GenerateOneRandomCar()
|
||||
CVehicle* pVehicle;
|
||||
if (CModelInfo::IsBoatModel(carModel))
|
||||
pVehicle = new CBoat(carModel, RANDOM_VEHICLE);
|
||||
else if (CModelInfo::IsBikeModel(carModel))
|
||||
pVehicle = new CBike(carModel, RANDOM_VEHICLE);
|
||||
else
|
||||
pVehicle = new CAutomobile(carModel, RANDOM_VEHICLE);
|
||||
{
|
||||
if (CModelInfo::IsBikeModel(carModel))
|
||||
pVehicle = new CBike(carModel, RANDOM_VEHICLE);
|
||||
else
|
||||
pVehicle = new CAutomobile(carModel, RANDOM_VEHICLE);
|
||||
#ifdef GTA_NETWORK
|
||||
// TODO
|
||||
#endif
|
||||
}
|
||||
pVehicle->AutoPilot.m_nPrevRouteNode = 0;
|
||||
pVehicle->AutoPilot.m_nCurrentRouteNode = curNodeId;
|
||||
pVehicle->AutoPilot.m_nNextRouteNode = nextNodeId;
|
||||
@@ -367,7 +448,7 @@ CCarCtrl::GenerateOneRandomCar()
|
||||
pVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_STOP_FOR_CARS;
|
||||
pVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE;
|
||||
}
|
||||
if (carModel == MI_FBIRANCH){
|
||||
if (carModel == MI_FBICAR){
|
||||
pVehicle->m_currentColour1 = 0;
|
||||
pVehicle->m_currentColour2 = 0;
|
||||
}
|
||||
@@ -400,7 +481,7 @@ CCarCtrl::GenerateOneRandomCar()
|
||||
pVehicle->m_bSirenOrAlarm = true;
|
||||
pVehicle->AutoPilot.m_nNextPathNodeInfo = connectionId;
|
||||
pVehicle->AutoPilot.m_nNextLane = pVehicle->AutoPilot.m_nCurrentLane = CGeneral::GetRandomNumber() % lanesOnCurrentRoad;
|
||||
CBox* boundingBox = &CModelInfo::GetModelInfo(pVehicle->GetModelIndex())->GetColModel()->boundingBox;
|
||||
CBox* boundingBox = &CModelInfo::GetColModel(pVehicle->GetModelIndex())->boundingBox;
|
||||
float carLength = 1.0f + (boundingBox->max.y - boundingBox->min.y) / 2;
|
||||
float distanceBetweenNodes = (pCurNode->GetPosition() - pNextNode->GetPosition()).Magnitude2D();
|
||||
/* If car is so long that it doesn't fit between two car nodes, place it directly in the middle. */
|
||||
@@ -589,6 +670,9 @@ CCarCtrl::GenerateOneRandomCar()
|
||||
break;
|
||||
}
|
||||
CVisibilityPlugins::SetClumpAlpha(pVehicle->GetClump(), 0);
|
||||
#ifdef GTA_MOBILE
|
||||
//CVisibilityPlugins::SetObjectDistanceAlpha(pVehicle->GetClump(), 0) // TODO(LCS)
|
||||
#endif
|
||||
if (!pVehicle->GetIsOnScreen()){
|
||||
if ((vecTargetPos - pVehicle->GetPosition()).Magnitude2D() > OFFSCREEN_DESPAWN_RANGE * (pVehicle->bExtendedRange ? EXTENDED_RANGE_DESPAWN_MULTIPLIER : 1.0f)) {
|
||||
/* Too far away cars that are not visible aren't needed. */
|
||||
@@ -596,12 +680,12 @@ CCarCtrl::GenerateOneRandomCar()
|
||||
return;
|
||||
}
|
||||
}else{
|
||||
if ((vecTargetPos - pVehicle->GetPosition()).Magnitude2D() > TheCamera.GenerationDistMultiplier * (pVehicle->bExtendedRange ? EXTENDED_RANGE_DESPAWN_MULTIPLIER : 1.0f) * ONSCREEN_DESPAWN_RANGE ||
|
||||
(vecTargetPos - pVehicle->GetPosition()).Magnitude2D() < TheCamera.GenerationDistMultiplier * MINIMAL_DISTANCE_TO_SPAWN_ONSCREEN) {
|
||||
if ((vecTargetPos - pVehicle->GetPosition()).Magnitude2D() > TheCamera.GenerationDistMultiplier * requestMultiplier * (pVehicle->bExtendedRange ? EXTENDED_RANGE_DESPAWN_MULTIPLIER : 1.0f) * ONSCREEN_DESPAWN_RANGE ||
|
||||
(vecTargetPos - pVehicle->GetPosition()).Magnitude2D() < TheCamera.GenerationDistMultiplier * requestMultiplier * MINIMAL_DISTANCE_TO_SPAWN_ONSCREEN) {
|
||||
delete pVehicle;
|
||||
return;
|
||||
}
|
||||
if ((TheCamera.GetPosition() - pVehicle->GetPosition()).Magnitude2D() < 82.5f * TheCamera.GenerationDistMultiplier || bTopDownCamera) {
|
||||
if ((TheCamera.GetPosition() - pVehicle->GetPosition()).Magnitude2D() < MAX_DISTANCE_FROM_CAMERA_TO_SPAWN_ONSCREEN * requestMultiplier * TheCamera.GenerationDistMultiplier || bTopDownCamera) {
|
||||
delete pVehicle;
|
||||
return;
|
||||
}
|
||||
@@ -635,29 +719,34 @@ CCarCtrl::GenerateOneRandomCar()
|
||||
CCarAI::AddPoliceCarOccupants(pVehicle);
|
||||
else {
|
||||
pVehicle->SetUpDriver();
|
||||
int32 passengers = 0;
|
||||
for (int i = 0; i < pVehicle->m_nNumMaxPassengers; i++)
|
||||
passengers += (CGeneral::GetRandomNumberInRange(0.0f, 1.0f) < PROBABILITY_OF_PASSENGER_IN_VEHICLE) ? 1 : 0;
|
||||
if (CModelInfo::IsCarModel(carModel) && (CModelInfo::GetModelInfo(carModel)->GetAnimFileIndex() == CAnimManager::GetAnimationBlockIndex("van") && passengers >= 1))
|
||||
passengers = 1;
|
||||
for (int i = 0; i < passengers; i++) {
|
||||
CPed* pPassenger = pVehicle->SetupPassenger(i);
|
||||
if (pPassenger) {
|
||||
++CPopulation::ms_nTotalCarPassengerPeds;
|
||||
pPassenger->bCarPassenger = true;
|
||||
#ifdef GTA_NETWORK
|
||||
if (!gIsMultiplayerGame)
|
||||
#endif
|
||||
{
|
||||
int32 passengers = 0;
|
||||
for (int i = 0; i < pVehicle->m_nNumMaxPassengers; i++)
|
||||
passengers += (CGeneral::GetRandomNumberInRange(0.0f, 1.0f) < PROBABILITY_OF_PASSENGER_IN_VEHICLE) ? 1 : 0;
|
||||
if (CModelInfo::IsCarModel(carModel) && (CModelInfo::GetModelInfo(carModel)->GetAnimFileIndex() == CAnimManager::GetAnimationBlockIndex("van") && passengers >= 1))
|
||||
passengers = 1;
|
||||
for (int i = 0; i < passengers; i++) {
|
||||
CPed* pPassenger = pVehicle->SetupPassenger(i);
|
||||
if (pPassenger) {
|
||||
++CPopulation::ms_nTotalCarPassengerPeds;
|
||||
pPassenger->bCarPassenger = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
int nMadDrivers;
|
||||
switch (pVehicle->GetVehicleAppearance()) {
|
||||
case VEHICLE_APPEARANCE_BIKE:
|
||||
nMadDrivers = 30;
|
||||
nMadDrivers = 20;
|
||||
break;
|
||||
case VEHICLE_APPEARANCE_BOAT:
|
||||
nMadDrivers = 40;
|
||||
break;
|
||||
default:
|
||||
nMadDrivers = 6;
|
||||
nMadDrivers = 3;
|
||||
break;
|
||||
}
|
||||
if ((CGeneral::GetRandomNumber() & 0x7F) < nMadDrivers || bMadDriversCheat) {
|
||||
@@ -714,12 +803,9 @@ CCarCtrl::GenerateOneRandomCar()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
CCarCtrl::BoatWithTallMast(int32 mi)
|
||||
{
|
||||
return mi == MI_RIO || mi == MI_TROPIC || mi == MI_MARQUIS;
|
||||
#ifdef GTA_NETWORK
|
||||
// TODO
|
||||
#endif
|
||||
}
|
||||
|
||||
int32
|
||||
@@ -755,6 +841,22 @@ int32
|
||||
CCarCtrl::ChooseModel(CZoneInfo* pZone, int* pClass) {
|
||||
int32 model = -1;
|
||||
int32 i;
|
||||
#ifdef GTA_NETWORK
|
||||
if (gIsMultiplayerGame) {
|
||||
for (i = 10; i > 0 && (model == -1 || !CStreaming::HasModelLoaded(model)); i--) {
|
||||
*pClass = ChooseCarRating(pZone);
|
||||
model = ChooseCarModel(*pClass);
|
||||
bool found = false;
|
||||
for (int j = 0; j < 8; j++) {
|
||||
if (model == MultiplayerCarBanks[nAmbientCarBank][j])
|
||||
found = true;
|
||||
}
|
||||
if (!found)
|
||||
model = -1;
|
||||
}
|
||||
return model;
|
||||
}
|
||||
#endif
|
||||
for (i = 10; i > 0 && (model == -1 || !CStreaming::HasModelLoaded(model)); i--) {
|
||||
int rnd = CGeneral::GetRandomNumberInRange(0, 1000);
|
||||
|
||||
@@ -781,6 +883,9 @@ CCarCtrl::ChooseModel(CZoneInfo* pZone, int* pClass) {
|
||||
}
|
||||
if (i == 0)
|
||||
return -1;
|
||||
CColModel* pColModel = CModelInfo::GetColModel(model);
|
||||
if (!pColModel || pColModel->boundingSphere.radius > 20.0f)
|
||||
return -1;
|
||||
return model;
|
||||
}
|
||||
|
||||
@@ -941,6 +1046,7 @@ CCarCtrl::RemoveCarsIfThePoolGetsFull(void)
|
||||
}
|
||||
}
|
||||
if (pClosestVehicle) {
|
||||
debug(":::::::::::\'Nearest removed\' cause pools was full -> NumRandomCars %d\n", NumRandomCars);
|
||||
CWorld::Remove(pClosestVehicle);
|
||||
delete pClosestVehicle;
|
||||
}
|
||||
@@ -963,7 +1069,13 @@ CCarCtrl::PossiblyRemoveVehicle(CVehicle* pVehicle)
|
||||
return;
|
||||
}
|
||||
float distanceToPlayer = (pVehicle->GetPosition() - vecPlayerPos).Magnitude2D();
|
||||
float threshold = OFFSCREEN_DESPAWN_RANGE;
|
||||
float despawnMultiplier = 1.0f;
|
||||
#if !defined EXTENDED_OFFSCREEN_DESPAWN_RANGE || defined GTA_PSP
|
||||
if (FindPlayerVehicle() && TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_1STPERSON && !FrontEndMenuManager.m_PrefsUseWideScreen)
|
||||
despawnMultiplier = 0.75f;
|
||||
#endif
|
||||
float threshold = OFFSCREEN_DESPAWN_RANGE * despawnMultiplier;
|
||||
#ifndef EXTENDED_OFFSCREEN_DESPAWN_RANGE
|
||||
if (pVehicle->GetIsOnScreen() ||
|
||||
TheCamera.Cams[TheCamera.ActiveCam].LookingLeft ||
|
||||
TheCamera.Cams[TheCamera.ActiveCam].LookingRight ||
|
||||
@@ -975,17 +1087,29 @@ CCarCtrl::PossiblyRemoveVehicle(CVehicle* pVehicle)
|
||||
pVehicle->bIsLawEnforcer ||
|
||||
pVehicle->bIsCarParkVehicle ||
|
||||
CTimer::GetTimeInMilliseconds() < pVehicle->m_nSetPieceExtendedRangeTime
|
||||
){
|
||||
threshold = ONSCREEN_DESPAWN_RANGE * TheCamera.GenerationDistMultiplier;
|
||||
)
|
||||
#endif
|
||||
{
|
||||
threshold = ONSCREEN_DESPAWN_RANGE * despawnMultiplier * TheCamera.GenerationDistMultiplier;
|
||||
}
|
||||
#ifndef EXTENDED_OFFSCREEN_DESPAWN_RANGE
|
||||
if (TheCamera.GetForward().z < -0.9f)
|
||||
threshold = 70.0f;
|
||||
#endif
|
||||
if (pVehicle->bExtendedRange)
|
||||
threshold *= EXTENDED_RANGE_DESPAWN_MULTIPLIER;
|
||||
if (distanceToPlayer > threshold && !CGarages::IsPointWithinHideOutGarage(pVehicle->GetPosition())){
|
||||
if (pVehicle->GetIsOnScreen()){
|
||||
pVehicle->bFadeOut = true;
|
||||
}else{
|
||||
#ifdef GTA_NETWORK
|
||||
if (gIsMultiplayerGame) {
|
||||
// TODO
|
||||
if (false)
|
||||
MultiPlayerRemoveVehicleAndDriver(pVehicle);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
CWorld::Remove(pVehicle);
|
||||
delete pVehicle;
|
||||
}
|
||||
@@ -1003,18 +1127,44 @@ CCarCtrl::PossiblyRemoveVehicle(CVehicle* pVehicle)
|
||||
!CTrafficLights::ShouldCarStopForLight(pVehicle, true) &&
|
||||
!CTrafficLights::ShouldCarStopForBridge(pVehicle) &&
|
||||
!CGarages::IsPointWithinHideOutGarage(pVehicle->GetPosition())){
|
||||
CWorld::Remove(pVehicle);
|
||||
delete pVehicle;
|
||||
#ifdef GTA_NETWORK
|
||||
if (!gIsMultiplayerGame)
|
||||
#endif
|
||||
{
|
||||
CWorld::Remove(pVehicle);
|
||||
delete pVehicle;
|
||||
return;
|
||||
}
|
||||
#ifdef GTA_NETWORK
|
||||
if (false) // TODO(LCS): figure out condition for mp
|
||||
MultiPlayerRemoveVehicleAndDriver(pVehicle);
|
||||
#endif
|
||||
}
|
||||
#ifdef GTA_NETWORK
|
||||
if (gIsMultiplayerGame) {
|
||||
if (pVehicle->GetStatus() == STATUS_WRECKED && CTimer::GetLogicalFrameCounter() == pVehicle->m_randomSeed) {
|
||||
if ((pVehicle->GetPosition() - vecPlayerPos).MagnitudeSqr() > SQR(6.5f)) {
|
||||
if (pVehicle->GetMoveSpeed().MagnitudeSqr() <= SQR(0.01f)) {
|
||||
printf("viciously removing dead vehicle");
|
||||
CWorld::Remove(pVehicle);
|
||||
delete pVehicle;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (pVehicle->GetStatus() != STATUS_WRECKED || pVehicle->m_nTimeOfDeath == 0)
|
||||
return;
|
||||
if (CTimer::GetTimeInMilliseconds() > pVehicle->m_nTimeOfDeath + 60000 &&
|
||||
!pVehicle->GetIsOnScreen()){
|
||||
if ((pVehicle->GetPosition() - vecPlayerPos).MagnitudeSqr() > SQR(7.5f)){
|
||||
if (!CGarages::IsPointWithinHideOutGarage(pVehicle->GetPosition())){
|
||||
CWorld::Remove(pVehicle);
|
||||
delete pVehicle;
|
||||
#endif
|
||||
if (pVehicle->GetStatus() == STATUS_WRECKED) {
|
||||
if (pVehicle->m_nTimeOfDeath != 0) {
|
||||
if (CTimer::GetTimeInMilliseconds() > pVehicle->m_nTimeOfDeath + 60000 &&
|
||||
CTimer::GetTimeInMilliseconds() > pVehicle->m_nSetPieceExtendedRangeTime &&
|
||||
!(pVehicle->GetIsOnScreen())) {
|
||||
if ((pVehicle->GetPosition() - vecPlayerPos).MagnitudeSqr() > SQR(6.5f)) {
|
||||
if (!CGarages::IsPointWithinHideOutGarage(pVehicle->GetPosition())) {
|
||||
CWorld::Remove(pVehicle);
|
||||
delete pVehicle;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1052,8 +1202,8 @@ CCarCtrl::UpdateCarOnRails(CVehicle* pVehicle)
|
||||
pVehicle->AutoPilot.ModifySpeed(0.0f);
|
||||
if (CTimer::GetTimeInMilliseconds() > pVehicle->AutoPilot.m_nTempAction){
|
||||
pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
|
||||
pVehicle->AutoPilot.m_nAntiReverseTimer = 0;
|
||||
pVehicle->AutoPilot.m_nTimeToStartMission = 0;
|
||||
pVehicle->AutoPilot.m_nAntiReverseTimer = CTimer::GetTimeInMilliseconds();
|
||||
pVehicle->AutoPilot.m_nTimeToStartMission = CTimer::GetTimeInMilliseconds();
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -1339,6 +1489,10 @@ void CCarCtrl::SlowCarDownForOtherCar(CEntity* pOtherEntity, CVehicle* pVehicle,
|
||||
pVehicle->AutoPilot.m_bSlowedDownBecauseOfCars = true;
|
||||
*pSpeed = Min(*pSpeed, minProximity * curSpeed);
|
||||
}
|
||||
#ifdef GTA_NETWORK
|
||||
if (gIsMultiplayerGame)
|
||||
return;
|
||||
#endif
|
||||
if (minProximity >= 0.0f && minProximity < 0.5f && pOtherEntity->IsVehicle() &&
|
||||
CTimer::GetTimeInMilliseconds() - pVehicle->AutoPilot.m_nTimeToStartMission > 15000 &&
|
||||
CTimer::GetTimeInMilliseconds() - pOtherVehicle->AutoPilot.m_nTimeToStartMission > 15000){
|
||||
@@ -1554,7 +1708,7 @@ void CCarCtrl::WeaveThroughCarsSectorList(CPtrList& lst, CVehicle* pVehicle, CPh
|
||||
continue;
|
||||
if (Abs(pTestVehicle->GetPosition().z - pVehicle->GetPosition().z) >= VEHICLE_HEIGHT_DIFF_TO_CONSIDER_WEAVING)
|
||||
continue;
|
||||
if (pTestVehicle != pVehicle)
|
||||
if (pTestVehicle != pVehicle && (!pVehicle->bPartOfConvoy || !pTestVehicle->bPartOfConvoy))
|
||||
WeaveForOtherCar(pTestVehicle, pVehicle, pAngleToWeaveLeft, pAngleToWeaveRight);
|
||||
}
|
||||
}
|
||||
@@ -1562,8 +1716,6 @@ void CCarCtrl::WeaveThroughCarsSectorList(CPtrList& lst, CVehicle* pVehicle, CPh
|
||||
void CCarCtrl::WeaveForOtherCar(CEntity* pOtherEntity, CVehicle* pVehicle, float* pAngleToWeaveLeft, float* pAngleToWeaveRight)
|
||||
{
|
||||
CVehicle* pOtherCar = (CVehicle*)pOtherEntity;
|
||||
if (pVehicle->bPartOfConvoy && pOtherCar->bPartOfConvoy)
|
||||
return;
|
||||
if (pVehicle->AutoPilot.m_nCarMission == MISSION_RAMPLAYER_CLOSE && pOtherEntity == FindPlayerVehicle())
|
||||
return;
|
||||
if (pVehicle->AutoPilot.m_nCarMission == MISSION_RAMCAR_CLOSE && pOtherEntity == pVehicle->AutoPilot.m_pTargetCar)
|
||||
@@ -1581,23 +1733,19 @@ void CCarCtrl::WeaveForOtherCar(CEntity* pOtherEntity, CVehicle* pVehicle, float
|
||||
forward.Normalise();
|
||||
float forwardAngle = CGeneral::GetATanOfXY(forward.x, forward.y);
|
||||
float angleDiff = angleBetweenVehicles - forwardAngle;
|
||||
float lenProjection = ABS(pOtherCar->GetColModel()->boundingBox.max.y * sin(angleDiff));
|
||||
float widthProjection = ABS(pOtherCar->GetColModel()->boundingBox.max.x * cos(angleDiff));
|
||||
float lenProjection = ABS(pOtherCar->GetColModel()->boundingBox.max.y * Sin(angleDiff));
|
||||
float widthProjection = ABS(pOtherCar->GetColModel()->boundingBox.max.x * Cos(angleDiff));
|
||||
float lengthToEvade = (2 * (lenProjection + widthProjection) + WIDTH_COEF_TO_WEAVE_SAFELY * 2 * pVehicle->GetColModel()->boundingBox.max.x) / distance;
|
||||
float diffToLeftAngle = LimitRadianAngle(angleBetweenVehicles - *pAngleToWeaveLeft);
|
||||
diffToLeftAngle = ABS(diffToLeftAngle);
|
||||
float angleToWeave = lengthToEvade / 2;
|
||||
if (diffToLeftAngle < angleToWeave){
|
||||
*pAngleToWeaveLeft = angleBetweenVehicles - angleToWeave;
|
||||
while (*pAngleToWeaveLeft < -PI)
|
||||
*pAngleToWeaveLeft += TWOPI;
|
||||
*pAngleToWeaveLeft = LimitRadianAngle(angleBetweenVehicles - angleToWeave);
|
||||
}
|
||||
float diffToRightAngle = LimitRadianAngle(angleBetweenVehicles - *pAngleToWeaveRight);
|
||||
diffToRightAngle = ABS(diffToRightAngle);
|
||||
if (diffToRightAngle < angleToWeave){
|
||||
*pAngleToWeaveRight = angleBetweenVehicles + angleToWeave;
|
||||
while (*pAngleToWeaveRight > PI)
|
||||
*pAngleToWeaveRight -= TWOPI;
|
||||
*pAngleToWeaveRight = LimitRadianAngle(angleBetweenVehicles + angleToWeave);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1636,16 +1784,12 @@ void CCarCtrl::WeaveForPed(CEntity* pOtherEntity, CVehicle* pVehicle, float* pAn
|
||||
diffToLeftAngle = ABS(diffToLeftAngle);
|
||||
float angleToWeave = lengthToEvade / 2;
|
||||
if (diffToLeftAngle < angleToWeave) {
|
||||
*pAngleToWeaveLeft = angleBetweenVehicleAndPed - angleToWeave;
|
||||
while (*pAngleToWeaveLeft < -PI)
|
||||
*pAngleToWeaveLeft += TWOPI;
|
||||
*pAngleToWeaveLeft = LimitRadianAngle(angleBetweenVehicleAndPed - angleToWeave);
|
||||
}
|
||||
float diffToRightAngle = LimitRadianAngle(angleBetweenVehicleAndPed - *pAngleToWeaveRight);
|
||||
diffToRightAngle = ABS(diffToRightAngle);
|
||||
if (diffToRightAngle < angleToWeave) {
|
||||
*pAngleToWeaveRight = angleBetweenVehicleAndPed + angleToWeave;
|
||||
while (*pAngleToWeaveRight > PI)
|
||||
*pAngleToWeaveRight -= TWOPI;
|
||||
*pAngleToWeaveRight = LimitRadianAngle(angleBetweenVehicleAndPed + angleToWeave);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1708,16 +1852,12 @@ void CCarCtrl::WeaveForObject(CEntity* pOtherEntity, CVehicle* pVehicle, float*
|
||||
diffToLeftAngle = ABS(diffToLeftAngle);
|
||||
float angleToWeave = lengthToEvade / 2;
|
||||
if (diffToLeftAngle < angleToWeave) {
|
||||
*pAngleToWeaveLeft = angleBetweenVehicleAndObject - angleToWeave;
|
||||
while (*pAngleToWeaveLeft < -PI)
|
||||
*pAngleToWeaveLeft += TWOPI;
|
||||
*pAngleToWeaveLeft = LimitRadianAngle(angleBetweenVehicleAndObject - angleToWeave);
|
||||
}
|
||||
float diffToRightAngle = LimitRadianAngle(angleBetweenVehicleAndObject - *pAngleToWeaveRight);
|
||||
diffToRightAngle = ABS(diffToRightAngle);
|
||||
if (diffToRightAngle < angleToWeave) {
|
||||
*pAngleToWeaveRight = angleBetweenVehicleAndObject + angleToWeave;
|
||||
while (*pAngleToWeaveRight > PI)
|
||||
*pAngleToWeaveRight -= TWOPI;
|
||||
*pAngleToWeaveRight = LimitRadianAngle(angleBetweenVehicleAndObject + angleToWeave);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1759,7 +1899,7 @@ bool CCarCtrl::PickNextNodeAccordingStrategy(CVehicle* pVehicle)
|
||||
void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle)
|
||||
{
|
||||
if (pVehicle->m_nRouteSeed)
|
||||
CGeneral::SetRandomSeed(pVehicle->m_nRouteSeed);
|
||||
CGeneral::SetRandomSeed(pVehicle->m_nRouteSeed++);
|
||||
int32 prevNode = pVehicle->AutoPilot.m_nCurrentRouteNode;
|
||||
int32 curNode = pVehicle->AutoPilot.m_nNextRouteNode;
|
||||
uint8 totalLinks = ThePaths.m_pathNodes[curNode].numLinks;
|
||||
@@ -1845,13 +1985,15 @@ void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle)
|
||||
pNextPathNode = &ThePaths.m_pathNodes[pVehicle->AutoPilot.m_nNextRouteNode];
|
||||
if ((!pNextPathNode->bDisabled || pPrevPathNode->bDisabled) &&
|
||||
(!pNextPathNode->bBetweenLevels || pPrevPathNode->bBetweenLevels || !pVehicle->AutoPilot.m_bStayInCurrentLevel))
|
||||
/* Nice way to exit loop but this will fail because this is used for indexing! */
|
||||
nextLink = 1000;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (nextLink < 999)
|
||||
if (nextLink >= totalLinks) {
|
||||
/* If everything else failed, turn vehicle around */
|
||||
nextLink = 0;
|
||||
debug("Couldn\'t find ANYTHING. Just go back from where we came.\n");
|
||||
pVehicle->AutoPilot.m_nNextRouteNode = prevNode;
|
||||
}
|
||||
}
|
||||
pNextPathNode = &ThePaths.m_pathNodes[pVehicle->AutoPilot.m_nNextRouteNode];
|
||||
pNextLink = &ThePaths.m_carPathLinks[ThePaths.m_carPathConnections[nextLink + pCurPathNode->firstLink]];
|
||||
@@ -1964,7 +2106,7 @@ void CCarCtrl::PickNextNodeToChaseCar(CVehicle* pVehicle, float targetX, float t
|
||||
#endif
|
||||
{
|
||||
if (pVehicle->m_nRouteSeed)
|
||||
CGeneral::SetRandomSeed(pVehicle->m_nRouteSeed);
|
||||
CGeneral::SetRandomSeed(pVehicle->m_nRouteSeed++);
|
||||
int prevNode = pVehicle->AutoPilot.m_nCurrentRouteNode;
|
||||
int curNode = pVehicle->AutoPilot.m_nNextRouteNode;
|
||||
CPathNode* pPrevNode = &ThePaths.m_pathNodes[prevNode];
|
||||
@@ -1978,7 +2120,7 @@ void CCarCtrl::PickNextNodeToChaseCar(CVehicle* pVehicle, float targetX, float t
|
||||
#else
|
||||
CVector(targetX, targetY, 0.0f),
|
||||
#endif
|
||||
pTargetNode, &numNodes, 2, pVehicle, &distanceToTargetNode, 999999.9f, -1);
|
||||
pTargetNode, &numNodes, 2, pVehicle, &distanceToTargetNode, 100.0f, -1);
|
||||
|
||||
int newNextNode;
|
||||
int nextLink;
|
||||
@@ -2093,14 +2235,14 @@ void CCarCtrl::PickNextNodeToChaseCar(CVehicle* pVehicle, float targetX, float t
|
||||
bool CCarCtrl::PickNextNodeToFollowPath(CVehicle* pVehicle)
|
||||
{
|
||||
if (pVehicle->m_nRouteSeed)
|
||||
CGeneral::SetRandomSeed(pVehicle->m_nRouteSeed);
|
||||
CGeneral::SetRandomSeed(pVehicle->m_nRouteSeed++);
|
||||
int curNode = pVehicle->AutoPilot.m_nNextRouteNode;
|
||||
CPathNode* pCurNode = &ThePaths.m_pathNodes[curNode];
|
||||
if (pVehicle->AutoPilot.m_nPathFindNodesCount == 0){
|
||||
ThePaths.DoPathSearch(0, pVehicle->GetPosition(), curNode,
|
||||
pVehicle->AutoPilot.m_vecDestinationCoors, pVehicle->AutoPilot.m_aPathFindNodesInfo,
|
||||
&pVehicle->AutoPilot.m_nPathFindNodesCount, NUM_PATH_NODES_IN_AUTOPILOT,
|
||||
pVehicle, nil, 999999.9f, -1);
|
||||
pVehicle, nil, 100.0f, -1);
|
||||
if (pVehicle->AutoPilot.m_nPathFindNodesCount < 2)
|
||||
return true;
|
||||
pVehicle->AutoPilot.RemoveOnePathNode();
|
||||
@@ -2412,6 +2554,16 @@ void CCarCtrl::SteerAICarWithPhysics_OnlyMission(CVehicle* pVehicle, float* pSwe
|
||||
*pHandbrake = true;
|
||||
return;
|
||||
case MISSION_CRUISE:
|
||||
if (CTrafficLights::ShouldCarStopForBridge(pVehicle)) {
|
||||
*pAccel = 0.0f;
|
||||
*pBrake = 1.0f;
|
||||
*pHandbrake = true;
|
||||
#ifdef FIX_BUGS
|
||||
*pSwerve = 0.0f;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
// fallthough
|
||||
case MISSION_RAMPLAYER_FARAWAY:
|
||||
case MISSION_BLOCKPLAYER_FARAWAY:
|
||||
case MISSION_GOTOCOORDS:
|
||||
@@ -2482,11 +2634,19 @@ void CCarCtrl::SteerAICarWithPhysics_OnlyMission(CVehicle* pVehicle, float* pSwe
|
||||
*pHandbrake = false;
|
||||
return;
|
||||
case MISSION_RAMCAR_CLOSE:
|
||||
if (!pVehicle->AutoPilot.m_pTargetCar) {
|
||||
debug("NO TARGET VEHICLE FOR MISSION_RAMCAR_CLOSE\n");
|
||||
return;
|
||||
}
|
||||
SteerAICarWithPhysicsHeadingForTarget(pVehicle, pVehicle->AutoPilot.m_pTargetCar,
|
||||
pVehicle->AutoPilot.m_pTargetCar->GetPosition().x, pVehicle->AutoPilot.m_pTargetCar->GetPosition().y,
|
||||
pSwerve, pAccel, pBrake, pHandbrake);
|
||||
return;
|
||||
case MISSION_BLOCKCAR_CLOSE:
|
||||
if (!pVehicle->AutoPilot.m_pTargetCar) {
|
||||
debug("NO TARGET VEHICLE FOR MISSION_BLOCKCAR_CLOSE\n");
|
||||
return;
|
||||
}
|
||||
SteerAICarWithPhysicsTryingToBlockTarget(pVehicle,
|
||||
pVehicle->AutoPilot.m_pTargetCar->GetPosition().x,
|
||||
pVehicle->AutoPilot.m_pTargetCar->GetPosition().y,
|
||||
@@ -2495,6 +2655,9 @@ void CCarCtrl::SteerAICarWithPhysics_OnlyMission(CVehicle* pVehicle, float* pSwe
|
||||
pSwerve, pAccel, pBrake, pHandbrake);
|
||||
return;
|
||||
case MISSION_BLOCKCAR_HANDBRAKESTOP:
|
||||
if (!pVehicle->AutoPilot.m_pTargetCar) {
|
||||
return;
|
||||
}
|
||||
SteerAICarWithPhysicsTryingToBlockTarget_Stop(pVehicle,
|
||||
pVehicle->AutoPilot.m_pTargetCar->GetPosition().x,
|
||||
pVehicle->AutoPilot.m_pTargetCar->GetPosition().y,
|
||||
@@ -2575,7 +2738,7 @@ void CCarCtrl::SteerAIBoatWithPhysicsHeadingForTarget(CVehicle* pVehicle, float
|
||||
float angleToTarget = CGeneral::GetATanOfXY(targetX - pVehicle->GetPosition().x, targetY - pVehicle->GetPosition().y);
|
||||
float angleForward = CGeneral::GetATanOfXY(forward.x, forward.y);
|
||||
float steerAngle = LimitRadianAngle(angleToTarget - angleForward);
|
||||
steerAngle = clamp(steerAngle, -DEFAULT_MAX_STEER_ANGLE, DEFAULT_MAX_STEER_ANGLE);
|
||||
steerAngle = Clamp(steerAngle, -DEFAULT_MAX_STEER_ANGLE, DEFAULT_MAX_STEER_ANGLE);
|
||||
#ifdef FIX_BUGS
|
||||
float speedTarget = pVehicle->AutoPilot.GetCruiseSpeed();
|
||||
#else
|
||||
@@ -2735,7 +2898,7 @@ void CCarCtrl::SteerAIPlaneTowardsTargetCoors(CAutomobile* pPlane)
|
||||
{
|
||||
CVector2D vecToTarget = pPlane->AutoPilot.m_vecDestinationCoors - pPlane->GetPosition();
|
||||
float fForwardZ = (pPlane->AutoPilot.m_vecDestinationCoors.z - pPlane->GetPosition().z) / vecToTarget.Magnitude();
|
||||
fForwardZ = clamp(fForwardZ, -0.3f, 0.3f);
|
||||
fForwardZ = Clamp(fForwardZ, -0.3f, 0.3f);
|
||||
float angle = CGeneral::GetATanOfXY(vecToTarget.x, vecToTarget.y);
|
||||
while (angle > TWOPI)
|
||||
angle -= TWOPI;
|
||||
@@ -3103,7 +3266,7 @@ bool CCarCtrl::JoinCarWithRoadSystemGotoCoors(CVehicle* pVehicle, CVector vecTar
|
||||
{
|
||||
pVehicle->AutoPilot.m_vecDestinationCoors = vecTarget;
|
||||
ThePaths.DoPathSearch(0, pVehicle->GetPosition(), -1, vecTarget, pVehicle->AutoPilot.m_aPathFindNodesInfo,
|
||||
&pVehicle->AutoPilot.m_nPathFindNodesCount, NUM_PATH_NODES_IN_AUTOPILOT, pVehicle, nil, 999999.9f, -1);
|
||||
&pVehicle->AutoPilot.m_nPathFindNodesCount, NUM_PATH_NODES_IN_AUTOPILOT, pVehicle, nil, 100.0f, -1);
|
||||
ThePaths.RemoveBadStartNode(pVehicle->GetPosition(),
|
||||
pVehicle->AutoPilot.m_aPathFindNodesInfo, &pVehicle->AutoPilot.m_nPathFindNodesCount);
|
||||
if (pVehicle->AutoPilot.m_nPathFindNodesCount < 2){
|
||||
@@ -3124,7 +3287,7 @@ bool CCarCtrl::JoinCarWithRoadSystemGotoCoors(CVehicle* pVehicle, CVector vecTar
|
||||
void CCarCtrl::FindLinksToGoWithTheseNodes(CVehicle* pVehicle)
|
||||
{
|
||||
if (pVehicle->m_nRouteSeed)
|
||||
CGeneral::SetRandomSeed(pVehicle->m_nRouteSeed);
|
||||
CGeneral::SetRandomSeed(pVehicle->m_nRouteSeed++);
|
||||
int nextLink;
|
||||
CPathNode* pCurNode = &ThePaths.m_pathNodes[pVehicle->AutoPilot.m_nCurrentRouteNode];
|
||||
for (nextLink = 0; nextLink < 12; nextLink++)
|
||||
@@ -3162,14 +3325,22 @@ void CCarCtrl::FindLinksToGoWithTheseNodes(CVehicle* pVehicle)
|
||||
|
||||
void CCarCtrl::GenerateEmergencyServicesCar(void)
|
||||
{
|
||||
#ifdef GTA_NETWORK
|
||||
if (gIsMultiplayerGame)
|
||||
return;
|
||||
#endif
|
||||
if (FindPlayerPed()->m_pWanted->GetWantedLevel() > 3)
|
||||
return;
|
||||
if (CGame::IsInInterior())
|
||||
return;
|
||||
#ifndef GTA_PSP
|
||||
if (TheCamera.m_WideScreenOn)
|
||||
return;
|
||||
#endif
|
||||
if (NumFiretrucksOnDuty + NumAmbulancesOnDuty + NumParkedCars + NumMissionCars +
|
||||
NumLawEnforcerCars + NumRandomCars > MaxNumberOfCarsInUse)
|
||||
return;
|
||||
if (NumAmbulancesOnDuty == 0){
|
||||
if (NumAmbulancesOnDuty == 0 && gbEmergencyVehiclesEnabled){
|
||||
if (gAccidentManager.CountActiveAccidents() < 2){
|
||||
if (CStreaming::HasModelLoaded(MI_AMBULAN))
|
||||
CStreaming::SetModelIsDeletable(MI_MEDIC);
|
||||
@@ -3189,7 +3360,7 @@ void CCarCtrl::GenerateEmergencyServicesCar(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (NumFiretrucksOnDuty == 0){
|
||||
if (NumFiretrucksOnDuty == 0 && gbEmergencyVehiclesEnabled){
|
||||
if (gFireManager.GetTotalActiveFires() < 3){
|
||||
if (CStreaming::HasModelLoaded(MI_FIRETRUCK))
|
||||
CStreaming::SetModelIsDeletable(MI_FIREMAN);
|
||||
@@ -3219,6 +3390,10 @@ void CCarCtrl::GenerateEmergencyServicesCar(void)
|
||||
|
||||
bool CCarCtrl::GenerateOneEmergencyServicesCar(uint32 mi, CVector vecPos)
|
||||
{
|
||||
#ifdef GTA_NETWORK
|
||||
if (gIsMultiplayerGame)
|
||||
return;
|
||||
#endif
|
||||
CVector pPlayerPos = FindPlayerCentreOfWorld(CWorld::PlayerInFocus);
|
||||
bool created = false;
|
||||
int attempts = 0;
|
||||
@@ -3238,7 +3413,7 @@ bool CCarCtrl::GenerateOneEmergencyServicesCar(uint32 mi, CVector vecPos)
|
||||
attempts += 1;
|
||||
}
|
||||
if (attempts >= 5)
|
||||
return nil;
|
||||
return false;
|
||||
CAutomobile* pVehicle = new CAutomobile(mi, RANDOM_VEHICLE);
|
||||
pVehicle->AutoPilot.m_vecDestinationCoors = vecPos;
|
||||
pVehicle->SetPosition(spawnPos);
|
||||
@@ -3284,6 +3459,11 @@ bool CCarCtrl::GenerateOneEmergencyServicesCar(uint32 mi, CVector vecPos)
|
||||
pVehicle->m_bSirenOrAlarm = true;
|
||||
CWorld::Add(pVehicle);
|
||||
printf("CREATED EMERGENCY VEHICLE\n");
|
||||
#ifdef GTA_NETWORK
|
||||
if (gIsMultiplayerGame) {
|
||||
// TODO (register car for network)
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -3353,6 +3533,22 @@ bool CCarCtrl::MapCouldMoveInThisArea(float x, float y)
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
CCarCtrl::BoatWithTallMast(int32 mi)
|
||||
{
|
||||
return mi == MI_RIO || mi == MI_TROPIC || mi == MI_MARQUIS;
|
||||
}
|
||||
|
||||
bool CCarCtrl::OkToCreateVehicleAtThisPosition(const CVector& pos)
|
||||
{
|
||||
#ifdef GTA_NETWORK
|
||||
if (gIsMultiplayerGame) {
|
||||
// TODO
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
float CCarCtrl::FindSpeedMultiplierWithSpeedFromNodes(int8 type)
|
||||
{
|
||||
switch (type)
|
||||
@@ -3362,3 +3558,64 @@ float CCarCtrl::FindSpeedMultiplierWithSpeedFromNodes(int8 type)
|
||||
}
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
void CCarCtrl::RenderDebugInfo(CVehicle* pVehicle)
|
||||
{
|
||||
if (!pVehicle->AutoPilot.m_nNextRouteNode || !pVehicle->AutoPilot.m_nCurrentRouteNode)
|
||||
return;
|
||||
|
||||
CPathNode* pCurNode = &ThePaths.m_pathNodes[pVehicle->AutoPilot.m_nCurrentRouteNode];
|
||||
CPathNode* pNextNode = &ThePaths.m_pathNodes[pVehicle->AutoPilot.m_nNextRouteNode];
|
||||
CCarPathLink* pCurLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo];
|
||||
CCarPathLink* pNextLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo];
|
||||
|
||||
CVector vCurNodePos(pCurNode->GetPosition());
|
||||
vCurNodePos.z += 1.0f;
|
||||
CVector vNextNodePos(pNextNode->GetPosition());
|
||||
vNextNodePos.z += 1.0f;
|
||||
CVector vCurLinkDir(pCurLink->GetDirX() * pVehicle->AutoPilot.m_nCurrentDirection, pCurLink->GetDirY() * pVehicle->AutoPilot.m_nCurrentDirection, 0.0f);
|
||||
CVector vNextLinkDir(pNextLink->GetDirX() * pVehicle->AutoPilot.m_nNextDirection, pNextLink->GetDirY() * pVehicle->AutoPilot.m_nNextDirection, 0.0f);
|
||||
vCurLinkDir.Normalise();
|
||||
vNextLinkDir.Normalise();
|
||||
|
||||
if (vCurLinkDir.x * vNextLinkDir.x + vCurLinkDir.y * vNextLinkDir.y < 0.5f) {
|
||||
CVector vCurPos(vCurNodePos);
|
||||
CVector vCurDir(0.0f, 0.0f, 1.0f);
|
||||
for (int i = 0; i < 10; i++) {
|
||||
CVector vPrevPos = vCurPos;
|
||||
CCurves::CalcCurvePoint(&vCurNodePos, &vNextNodePos, &vCurLinkDir, &vNextLinkDir, i * 0.1f, pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve, &vCurPos, &vCurDir);
|
||||
// Render3DLine(&vCurPos, &vNextPos, CVector(255.0f, 255.0f, 0.0f, 255.0f)); // <- originally this is called, let's reuse stuff we have
|
||||
// TODO: not drawing :(
|
||||
CLines::RenderLineWithClipping(vPrevPos.x, vPrevPos.y, vCurNodePos.z, vCurPos.x, vCurPos.y, vNextNodePos.z, 0xFFFF00FF, 0xFFFF00FF); // using NodePos for Z coord cause Curves set it to 0
|
||||
}
|
||||
DefinedState();
|
||||
}
|
||||
}
|
||||
|
||||
void CCarCtrl::SetMultiplayerAmbientCarLimit(uint32 limit)
|
||||
{
|
||||
maxRandomMpCars = limit;
|
||||
}
|
||||
|
||||
void CCarCtrl::ToggleScriptControlsMpCarLimit(bool toggle)
|
||||
{
|
||||
scriptControlsMpCarLimit = toggle;
|
||||
}
|
||||
|
||||
void CCarCtrl::MultiPlayerRemoveVehicleAndDriver(CVehicle* pVehicle)
|
||||
{
|
||||
CPed* pDriver = pVehicle->pDriver;
|
||||
CWorld::Remove(pVehicle);
|
||||
delete pVehicle;
|
||||
if (pDriver) {
|
||||
CWorld::Remove(pDriver);
|
||||
delete pDriver;
|
||||
}
|
||||
}
|
||||
|
||||
void CCarCtrl::Write(base::cRelocatableChunkWriter& writer)
|
||||
{
|
||||
writer.AllocateRaw(CarArrays, sizeof(CarArrays), 4);
|
||||
writer.AllocateRaw(TotalNumOfCarsOfRating, sizeof(TotalNumOfCarsOfRating), 4, false, true);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#include "PathFind.h"
|
||||
#include "Boat.h"
|
||||
#include "General.h"
|
||||
#include "Vehicle.h"
|
||||
|
||||
#define GAME_SPEED_TO_METERS_PER_SECOND 50.0f
|
||||
@@ -16,6 +17,13 @@ enum{
|
||||
MAX_CAR_MODELS_IN_ARRAY = 25,
|
||||
};
|
||||
|
||||
#ifdef GTA_NETWORK
|
||||
enum {
|
||||
TOTAL_MULTIPLAYER_CAR_BANKS = 3,
|
||||
CARS_IN_MULTIPLAYER_BANK = 8
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef FIX_BUGS
|
||||
#define FIX_PATHFIND_BUG
|
||||
#endif
|
||||
@@ -130,6 +138,13 @@ public:
|
||||
static void SteerAIBoatWithPhysicsAttackingPlayer(CVehicle*, float*, float*, float*, bool*);
|
||||
static void SteerAICarBlockingPlayerForwardAndBack(CVehicle*, float*, float*, float*, bool*);
|
||||
|
||||
static bool OkToCreateVehicleAtThisPosition(const CVector&);
|
||||
static void RenderDebugInfo(CVehicle*);
|
||||
static void SetMultiplayerAmbientCarLimit(uint32);
|
||||
static void ToggleScriptControlsMpCarLimit(bool);
|
||||
static void MultiPlayerRemoveVehicleAndDriver(CVehicle*);
|
||||
static void Write(base::cRelocatableChunkWriter&);
|
||||
|
||||
static float GetPositionAlongCurrentCurve(CVehicle* pVehicle)
|
||||
{
|
||||
uint32 timeInCurve = CTimer::GetTimeInMilliseconds() - pVehicle->AutoPilot.m_nTimeEnteredCurve;
|
||||
@@ -138,11 +153,7 @@ public:
|
||||
|
||||
static float LimitRadianAngle(float angle)
|
||||
{
|
||||
while (angle < -PI)
|
||||
angle += TWOPI;
|
||||
while (angle > PI)
|
||||
angle -= TWOPI;
|
||||
return angle;
|
||||
return CGeneral::LimitRadianAngle(angle);
|
||||
}
|
||||
|
||||
static bool bMadDriversCheat;
|
||||
@@ -169,6 +180,15 @@ public:
|
||||
static int32 NumOfLoadedCarsOfRating[TOTAL_CUSTOM_CLASSES];
|
||||
static int32 CarFreqArrays[TOTAL_CUSTOM_CLASSES][MAX_CAR_MODELS_IN_ARRAY];
|
||||
static int32 LoadedCarsArray[TOTAL_CUSTOM_CLASSES][MAX_CAR_MODELS_IN_ARRAY];
|
||||
|
||||
#ifdef GTA_NETWORK
|
||||
static const int32 MultiplayerCarBanks[TOTAL_MULTIPLAYER_CAR_BANKS][CARS_IN_MULTIPLAYER_BANK];
|
||||
#endif
|
||||
|
||||
static uint32 maxRandomMpCars;
|
||||
static bool scriptControlsMpCarLimit;
|
||||
|
||||
};
|
||||
|
||||
extern CVehicle* apCarsToKeep[MAX_CARS_TO_KEEP];
|
||||
extern CVehicle* apCarsToKeep[MAX_CARS_TO_KEEP];
|
||||
extern bool gbEmergencyVehiclesEnabled;
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include "Curves.h"
|
||||
|
||||
//--LCS: file done except TODO
|
||||
|
||||
float CCurves::CalcSpeedScaleFactor(CVector* pPoint1, CVector* pPoint2, float dir1X, float dir1Y, float dir2X, float dir2Y)
|
||||
{
|
||||
CVector2D dir1(dir1X, dir1Y);
|
||||
@@ -19,17 +21,27 @@ void CCurves::CalcCurvePoint(CVector* pPos1, CVector* pPos2, CVector* pDir1, CVe
|
||||
float actualFactor = CalcSpeedScaleFactor(pPos1, pPos2, pDir1->x, pDir1->y, pDir2->x, pDir2->y);
|
||||
CVector2D dir1 = *pDir1 * actualFactor;
|
||||
CVector2D dir2 = *pDir2 * actualFactor;
|
||||
float t1 = Abs(DotProduct2D(*pPos1 - *pPos2, *pDir1));
|
||||
float t2 = Abs(DotProduct2D(*pPos2 - *pPos1, *pDir2));
|
||||
float t1 = Abs(DotProduct2D(*pPos2 - *pPos1, *pDir1));
|
||||
float t2 = Abs(DotProduct2D(*pPos1 - *pPos2, *pDir2));
|
||||
float curveCoef;
|
||||
if (t1 > t2) {
|
||||
if (between < (t1 - t2) / (t1 + t2))
|
||||
float coef = (t1 - t2) / (t1 + t2);
|
||||
#ifdef FIX_BUGS
|
||||
if (between <= coef)
|
||||
#else
|
||||
if (between < coef)
|
||||
#endif
|
||||
curveCoef = 0.0f;
|
||||
else
|
||||
curveCoef = 0.5f - 0.5f * Cos(3.1415f * (t1 + t2) / (2 * t2) * (between - (t1 - t2) / (t1 + t2)));
|
||||
curveCoef = 0.5f - 0.5f * Cos(3.1415f * (between - coef) * (t1 + t2) / (2 * t2));
|
||||
}
|
||||
else {
|
||||
if (2 * t1 / (t1 + t2) < between)
|
||||
float coef = 2 * t1 / (t1 + t2);
|
||||
#ifdef FIX_BUGS
|
||||
if (coef <= between)
|
||||
#else
|
||||
if (coef < between)
|
||||
#endif
|
||||
curveCoef = 1.0f;
|
||||
else
|
||||
curveCoef = 0.5f - 0.5f * Cos(3.1415f * between * (t1 + t2) / (2 * t1));
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "Automobile.h"
|
||||
#include "MBlur.h"
|
||||
#include "screendroplets.h"
|
||||
#include "SaveBuf.h"
|
||||
|
||||
uint8 CGameLogic::ActivePlayers;
|
||||
uint8 CGameLogic::ShortCutState;
|
||||
@@ -45,6 +46,7 @@ float CGameLogic::AfterDeathStartPointOrientation[NUM_SHORTCUT_START_POINTS];
|
||||
CVector CGameLogic::ShortCutDropOffForMission;
|
||||
float CGameLogic::ShortCutDropOffOrientationForMission;
|
||||
bool CGameLogic::MissionDropOffReadyToBeUsed;
|
||||
char CGameLogic::mStoredPlayerOutfit[8] = "plr3";
|
||||
|
||||
#define SHORTCUT_TAXI_COST (9)
|
||||
#define TOTAL_BUSTED_AUDIO (28)
|
||||
@@ -88,7 +90,7 @@ CGameLogic::SortOutStreamingAndMemory(const CVector &pos)
|
||||
CStreaming::DeleteRwObjectsAfterDeath(pos);
|
||||
CStreaming::RemoveUnusedModelsInLoadedList();
|
||||
CGame::DrasticTidyUpMemory(true);
|
||||
CWorld::Players[CWorld::PlayerInFocus].m_pPed->Undress("player");
|
||||
CWorld::Players[CWorld::PlayerInFocus].m_pPed->Undress(mStoredPlayerOutfit);
|
||||
CStreaming::LoadSceneCollision(pos);
|
||||
CStreaming::LoadScene(pos);
|
||||
CWorld::Players[CWorld::PlayerInFocus].m_pPed->Dress();
|
||||
@@ -157,7 +159,7 @@ CGameLogic::Update()
|
||||
#endif
|
||||
CMessages::ClearMessages();
|
||||
CCarCtrl::ClearInterestingVehicleList();
|
||||
CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1);
|
||||
CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, true);
|
||||
CRestart::FindClosestHospitalRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat);
|
||||
CRestart::OverrideHospitalLevel = LEVEL_GENERIC;
|
||||
CRestart::OverridePoliceStationLevel = LEVEL_GENERIC;
|
||||
@@ -190,7 +192,7 @@ CGameLogic::Update()
|
||||
}
|
||||
|
||||
|
||||
if (!CTheScripts::IsPlayerOnAMission() && pPlayerInfo.m_nBustedAudioStatus == 0) {
|
||||
if (!CTheScripts::IsPlayerOnAMission() && pPlayerInfo.m_nBustedAudioStatus == BUSTEDAUDIO_NONE) {
|
||||
if (CGeneral::GetRandomNumberInRange(0, 4) == 0)
|
||||
pPlayerInfo.m_nBustedAudioStatus = BUSTEDAUDIO_DONE;
|
||||
else {
|
||||
@@ -266,7 +268,7 @@ CGameLogic::Update()
|
||||
#endif
|
||||
CMessages::ClearMessages();
|
||||
CCarCtrl::ClearInterestingVehicleList();
|
||||
CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1);
|
||||
CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, true);
|
||||
CRestart::FindClosestPoliceRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat);
|
||||
CRestart::OverrideHospitalLevel = LEVEL_GENERIC;
|
||||
CRestart::OverridePoliceStationLevel = LEVEL_GENERIC;
|
||||
@@ -321,7 +323,7 @@ CGameLogic::Update()
|
||||
#endif
|
||||
CMessages::ClearMessages();
|
||||
CCarCtrl::ClearInterestingVehicleList();
|
||||
CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1);
|
||||
CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, true);
|
||||
CRestart::FindClosestPoliceRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat);
|
||||
CRestart::OverridePoliceStationLevel = LEVEL_GENERIC;
|
||||
CRestart::OverrideHospitalLevel = LEVEL_GENERIC;
|
||||
@@ -378,10 +380,10 @@ CGameLogic::RestorePlayerStuffDuringResurrection(CPlayerPed *pPlayerPed, CVector
|
||||
pPlayerPed->m_fRotationDest = pPlayerPed->m_fRotationCur;
|
||||
pPlayerPed->SetHeading(pPlayerPed->m_fRotationCur);
|
||||
CTheScripts::ClearSpaceForMissionEntity(pos, pPlayerPed);
|
||||
CWorld::ClearExcitingStuffFromArea(pos, 4000.0, 1);
|
||||
CWorld::ClearExcitingStuffFromArea(pos, 4000.0f, true);
|
||||
pPlayerPed->RestoreHeadingRate();
|
||||
CGame::currArea = AREA_MAIN_MAP;
|
||||
CStreaming::RemoveBuildingsNotInArea(0);
|
||||
CStreaming::RemoveBuildingsNotInArea(AREA_MAIN_MAP);
|
||||
TheCamera.SetCameraDirectlyInFrontForFollowPed_CamOnAString();
|
||||
TheCamera.Restore();
|
||||
CReferences::RemoveReferencesToPlayer();
|
||||
@@ -391,7 +393,7 @@ CGameLogic::RestorePlayerStuffDuringResurrection(CPlayerPed *pPlayerPed, CVector
|
||||
CWorld::Add(pPlayerPed);
|
||||
CHud::ResetWastedText();
|
||||
CStreaming::StreamZoneModels(pos);
|
||||
clearWaterDrop = true;
|
||||
//clearWaterDrop = true;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -418,7 +420,7 @@ CGameLogic::SetUpShortCut(CVector vStartPos, float fStartAngle, CVector vEndPos,
|
||||
ShortCutStartOrientation = fStartAngle;
|
||||
ShortCutDestination = vEndPos;
|
||||
ShortCutDestinationOrientation = fEndAngle;
|
||||
CStreaming::RequestModel(MI_KAUFMAN, 0);
|
||||
CStreaming::RequestModel(MI_CABBIE, 0);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -450,11 +452,11 @@ CGameLogic::UpdateShortCut()
|
||||
{
|
||||
switch (ShortCutState) {
|
||||
case SHORTCUT_INIT:
|
||||
if (!CStreaming::HasModelLoaded(MI_KAUFMAN)) {
|
||||
CStreaming::RequestModel(MI_KAUFMAN, 0);
|
||||
if (!CStreaming::HasModelLoaded(MI_CABBIE)) {
|
||||
CStreaming::RequestModel(MI_CABBIE, 0);
|
||||
return;
|
||||
}
|
||||
pShortCutTaxi = new CAutomobile(MI_KAUFMAN, RANDOM_VEHICLE);
|
||||
pShortCutTaxi = new CAutomobile(MI_CABBIE, RANDOM_VEHICLE);
|
||||
if (!pShortCutTaxi)
|
||||
return;
|
||||
pShortCutTaxi->SetPosition(ShortCutStart);
|
||||
@@ -488,7 +490,7 @@ CGameLogic::UpdateShortCut()
|
||||
pShortCutTaxi->AutoPilot.m_nTempAction = TEMPACT_GOFORWARD;
|
||||
pShortCutTaxi->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 2500;
|
||||
TheCamera.SetFadeColour(0, 0, 0);
|
||||
TheCamera.Fade(2.5f, 0);
|
||||
TheCamera.Fade(2.5f, FADE_OUT);
|
||||
ShortCutState = SHORTCUT_TRANSITION;
|
||||
ShortCutTimer = CTimer::GetTimeInMilliseconds() + 3000;
|
||||
CMessages::AddBigMessage(TheText.Get("TAXI"), 4500, 1);
|
||||
@@ -508,7 +510,7 @@ CGameLogic::UpdateShortCut()
|
||||
pShortCutTaxi->SetMoveSpeed(pShortCutTaxi->GetForward() * 0.4f);
|
||||
ShortCutTimer = CTimer::GetTimeInMilliseconds() + 1500;
|
||||
TheCamera.SetFadeColour(0, 0, 0);
|
||||
TheCamera.Fade(1.0f, 1);
|
||||
TheCamera.Fade(1.0f, FADE_IN);
|
||||
ShortCutState = SHORTCUT_ARRIVING;
|
||||
CTimer::Resume();
|
||||
}
|
||||
@@ -611,12 +613,12 @@ void
|
||||
CGameLogic::Load(uint8* buf, uint32 size)
|
||||
{
|
||||
INITSAVEBUF
|
||||
NumAfterDeathStartPoints = ReadSaveBuf<uint32>(buf);
|
||||
ReadSaveBuf(&NumAfterDeathStartPoints, buf);
|
||||
for (int i = 0; i < NUM_SHORTCUT_START_POINTS; i++) {
|
||||
AfterDeathStartPoints[i].x = ReadSaveBuf<float>(buf);
|
||||
AfterDeathStartPoints[i].y = ReadSaveBuf<float>(buf);
|
||||
AfterDeathStartPoints[i].z = ReadSaveBuf<float>(buf);
|
||||
AfterDeathStartPointOrientation[i] = ReadSaveBuf<float>(buf);
|
||||
ReadSaveBuf(&AfterDeathStartPoints[i].x, buf);
|
||||
ReadSaveBuf(&AfterDeathStartPoints[i].y, buf);
|
||||
ReadSaveBuf(&AfterDeathStartPoints[i].z, buf);
|
||||
ReadSaveBuf(&AfterDeathStartPointOrientation[i], buf);
|
||||
}
|
||||
VALIDATESAVEBUF(size)
|
||||
}
|
||||
|
||||
@@ -48,4 +48,5 @@ public:
|
||||
static CVector ShortCutDropOffForMission;
|
||||
static float ShortCutDropOffOrientationForMission;
|
||||
static bool MissionDropOffReadyToBeUsed;
|
||||
static char mStoredPlayerOutfit[8];
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user