Merge branch 'bugfixes'

Conflicts:
	src/qtscriptfuncs.cpp
master
Per Inge Mathisen 2012-06-25 21:37:47 +02:00
commit 7bc528ebd7
99 changed files with 13904 additions and 13237 deletions

View File

@ -1,17 +1,25 @@
2012-06-xx: Version 3.1 beta11 2012-06-20: Version 3.1 beta11
* General: * General:
* Change: CB sensor also defends allies (commit:313738ed235c69c64c83eb9b987d63efc95d8782) * Change: CB sensor also defends allies (commit:313738ed235c69c64c83eb9b987d63efc95d8782)
* Change: Structures with no cost to build (oil derricks) deconstruct when abandoned, taking one minute for 100% build progress (commit:5ba90fec427096f6016867852ce696126514d378) * Change: Structures with no cost to build (oil derricks) deconstruct when abandoned, taking one minute for 100% build progress (commit:5ba90fec427096f6016867852ce696126514d378)
* Change: Queue building on burning oil wells, trucks wait until the fire stops (commit:353357b1b6f3b8a12131abd7c2c2cef571402e5b) * Change: Queue building on burning oil wells, trucks wait until the fire stops (commit:353357b1b6f3b8a12131abd7c2c2cef571402e5b)
* Fix: Pathfinding improvements (commit:d11516795a7d98a6bcf0cdeafe159435108344a4, commit:57a56f21c372e268a645e6312b3f1c5a95a98000, commit:f7c6e38aa8e06051c6ac6e42ab9bbaf1b760c9e8)
* Fix: Loading of rearm pads in savegames (ticket:3518, commit:eb3001bd2fb6c0494abb3677cd05f62c1b0d8a4a)
* Fix: CB fire against mobile targets (ticket:3529, commit:193eba2a9f8d4a5fc2dd6ed58dabe4c42e1eaa1a) * Fix: CB fire against mobile targets (ticket:3529, commit:193eba2a9f8d4a5fc2dd6ed58dabe4c42e1eaa1a)
* Fix: Weapon reloading (commit:74d8086132a3f847ea13b88254096fe68a30474b) * Fix: Weapon reloading (commit:74d8086132a3f847ea13b88254096fe68a30474b)
* Fix: Correct unit count of commanders after loading a savegame (ticket:3062, ticket:3513, commit:b3f3b089f1438bf66fad0e3d4db4447bd2dd6d23) * Fix: Correct unit count of commanders after loading a savegame (ticket:3062, ticket:3513, commit:b3f3b089f1438bf66fad0e3d4db4447bd2dd6d23)
* Fix: Correct factory numbers after loading a savegame (ticket:3384, commit:737b3d9d24ab1634dafd09558fc8b8a5354ffa9c) * Fix: Correct factory numbers after loading a savegame (ticket:3384, commit:737b3d9d24ab1634dafd09558fc8b8a5354ffa9c)
* Fix: Show correct number of selected units (ticket:3479, commit:22799c2b2607949b1920e8d1f143311c167f7a39) * Fix: Show correct number of selected units (ticket:3479, commit:22799c2b2607949b1920e8d1f143311c167f7a39)
* Fix: Player switching in debug mode (ticket:3264, commit:4a2f7d4399649662f33d146cbe97a12110b8995b)
* Graphics: * Graphics:
* Change: Support texture animations on structures (commit:190c7a99cccc9e831a49712ec431b194f0b65cb8, commit:2d0a089bad6b6b2fdca75556444a66e07ad3dbaa, commit:b59fe8bdb587671c8a382887c10ce804a1d1cd9a, commit:07a2a9671b32d4817942739de723f380c7b88cc7, commit:e636d41472762f0573979c1f05ada2e1484e4eca, commit:da433789c3e272c9c22307b6e74eeb81b2925e07)
* Change: New skybox for urban maps (ticket:3534, commit:aca180e0e860f42206bc9be21d9e7a65638afbec)
* Change: New cliff decals to make cliffs more visible (commit:4a53a0e010452a1ef2a64d92fd3f12c27b451a50) * Change: New cliff decals to make cliffs more visible (commit:4a53a0e010452a1ef2a64d92fd3f12c27b451a50)
* Fix: Work better with archaic OpenGL drivers, and add a workaround option to the menu (commit:f54eb00d7044827e011bd3261108bfd446f6a68e, commit:8b8282cc1f9bbddd6c48cef4dbf1681b84160129, commit:0c03151e250a89f23ea5960cd488367112bd3fdc, commit:96272ebf5008ad7ac47865e3493d43a597371944, commit:f5a7fd52c01dbe848ecaab27da4a08fc7eef536a, commit:7867b7abe209613da26ae36897ac864eaee73a14, commit:691df6a1837cec65fe7ac4e924c96868df2b749d)
* Fix: Placement of droid selection boxes and group/commander numbers (ticket:3547, commit:dd8025d10853fe775ef37c0c632647086752b4d9)
* Multiplayer: * Multiplayer:
* Change: Add oil barrels to map preview (commit:5b07a7b755a529d37c5f308b5ecd6df52da05fec) * Change: Add oil barrels to map preview (commit:5b07a7b755a529d37c5f308b5ecd6df52da05fec)
* Fix: Sensibly handle multiple maps with the same name (ticket:3531, ticket:3180, commit:15c04ab10f87de89ca7dcae2813834bd1a03247b, commit:205609302755ec151d4768da6cdcefe768059fb1, commit:1461b3a5a81b72381bc3cc3dbc57bbd2f5ce22a7)
* Fix: Don't crash when a player fails to join a game (commit:bf2483cbd7430bd81457a6931c1e526828c7d18a, commit:7a0cd2eccfe733215ee43cab28243d7f29918b75) * Fix: Don't crash when a player fails to join a game (commit:bf2483cbd7430bd81457a6931c1e526828c7d18a, commit:7a0cd2eccfe733215ee43cab28243d7f29918b75)
* Fix: Don't freeze when a player leaves (ticket:3410, commit:53ce0a7c38822feda52bc9ba24fd45d02a0fa7cc, commit:e0939a02175e56f8a0f1468286f0cbd039053174) * Fix: Don't freeze when a player leaves (ticket:3410, commit:53ce0a7c38822feda52bc9ba24fd45d02a0fa7cc, commit:e0939a02175e56f8a0f1468286f0cbd039053174)
* Fix: Don't desync when a player leaves (commit:35f301b1ba7f76be1bbfc80d8cdb924f12d6ae7e) * Fix: Don't desync when a player leaves (commit:35f301b1ba7f76be1bbfc80d8cdb924f12d6ae7e)
@ -54,6 +62,7 @@
* Update: Turkish (ticket:3486, commit:a400fe055fd5d176cd809bcfdc0973cf839a4a2c) * Update: Turkish (ticket:3486, commit:a400fe055fd5d176cd809bcfdc0973cf839a4a2c)
* Update: Dutch (ticket:3484, commit:c46d2d56ea3cbfe9d7ba7516f5b1962a2fef2d37) * Update: Dutch (ticket:3484, commit:c46d2d56ea3cbfe9d7ba7516f5b1962a2fef2d37)
2012-05-13: Version 3.1 beta10 2012-05-13: Version 3.1 beta10
* General: * General:
* Fix: Loading of skirmish games (ticket:3451, commit:18216c60e76d05ad0fe2bf7d860347f76f70c8f8) * Fix: Loading of skirmish games (ticket:3451, commit:18216c60e76d05ad0fe2bf7d860347f76f70c8f8)

View File

@ -44,6 +44,9 @@ EXTRA_DIST= \
pkg/dpkg \ pkg/dpkg \
macosx \ macosx \
3rdparty/SDL/mac \ 3rdparty/SDL/mac \
tools/image/image.cpp \
tools/image/configs \
tools/image/Image.xcodeproj \
po/custom/mac-infoplist.txt \ po/custom/mac-infoplist.txt \
po/custom/warzone2100.desktop.txt po/custom/warzone2100.desktop.txt

View File

@ -3,105 +3,111 @@ TYPE 10200
TEXTURE 0 page-13-player-buildings.png 256 256 TEXTURE 0 page-13-player-buildings.png 256 256
LEVELS 1 LEVELS 1
LEVEL 1 LEVEL 1
POINTS 46 POINTS 50
-39 90 65 40 90 65
-9 90 65 40 90 97
-9 90 97 40 0 97
-39 90 97 40 0 65
-53 0 26 10 90 97
-53 0 -123 10 90 65
-30 113 -110 10 0 65
-30 104 -3 10 0 97
55 0 -123 -39 90 97
55 0 26 -39 90 65
32 104 -3 -39 0 65
32 113 -110 -39 0 97
-30 71 6 -9 90 65
-17 71 6 -9 90 97
-17 71 64 -9 0 97
-30 71 64 -9 0 65
19 71 6 -30 71 6
32 71 6 -30 0 26
32 71 64 -17 0 26
19 71 64 -17 71 6
32 58 10 -17 71 64
32 58 64 -17 58 64
19 58 64 -17 58 10
19 58 10 32 0 26
-17 58 10 32 71 6
-17 58 64 19 71 6
-30 58 64
-30 58 10
-39 0 65
-9 0 65
-9 0 97
-39 0 97
10 0 65
40 0 65
40 90 65
10 90 65
40 0 97
40 90 97
10 0 97
10 90 97
-50 0 26
-30 0 26
39 71 6
-17 0 26
32 0 26
19 0 26 19 0 26
POLYGONS 52 19 71 64
200 3 34 37 36 140 84 91 84 91 134 19 58 10
200 3 34 36 33 140 84 91 134 140 134 19 58 64
200 3 39 35 32 91 84 140 84 140 134 32 71 64
200 3 39 32 38 91 84 140 134 91 134 32 58 64
200 3 3 0 28 91 84 140 84 140 134 32 58 10
200 3 3 28 31 91 84 140 134 91 134 55 0 26
200 3 1 2 30 140 84 91 84 91 134 39 71 6
200 3 1 30 29 140 84 91 134 140 134 -30 71 64
200 3 39 37 34 253 63 210 63 210 108 32 104 -3
200 3 39 34 35 253 63 210 108 253 108 -30 104 -3
200 3 3 2 1 253 63 210 63 210 108 -30 58 10
200 3 3 1 0 253 63 210 108 253 108 -30 58 64
200 3 0 1 29 91 84 140 84 140 134 -50 0 26
200 3 0 29 28 91 84 140 134 91 134 -30 113 -110
200 3 35 34 33 91 84 140 84 140 134 -53 0 -123
200 3 35 33 32 91 84 140 134 91 134 -53 0 26
200 3 12 41 43 9 41 9 73 14 73 32 113 -110
200 3 12 43 13 9 41 14 73 14 41 55 0 -123
200 3 13 14 25 3 61 36 61 36 68 -23 113 -89
200 3 13 25 24 3 61 36 68 5 68 -23 109 -41
200 3 44 17 16 35 73 35 41 29 41 25 113 -89
200 3 44 16 45 35 73 29 41 29 73 25 109 -41
200 3 19 16 23 36 61 3 61 4 68 POLYGONS 54
200 3 19 23 22 36 61 4 68 36 68 200 3 0 1 2 140 84 91 84 91 134
200 3 13 43 45 14 41 14 73 29 73 200 3 0 2 3 140 84 91 134 140 134
200 3 13 45 16 14 41 29 73 29 41 200 3 4 5 6 91 84 140 84 140 134
200 3 17 18 21 3 61 36 61 36 68 200 3 4 6 7 91 84 140 134 91 134
200 3 17 21 20 3 61 36 68 5 68 200 3 8 9 10 91 84 140 84 140 134
200 3 9 42 17 46 73 39 41 35 41 200 3 8 10 11 91 84 140 134 91 134
200 3 9 17 44 46 73 35 41 35 73 200 3 12 13 14 140 84 91 84 91 134
200 3 19 18 17 36 61 37 68 3 68 200 3 12 14 15 140 84 91 134 140 134
200 3 19 17 16 36 61 3 68 3 61 200 3 4 1 0 253 63 210 63 210 108
200 3 15 14 13 36 61 37 68 3 68 200 3 4 0 5 253 63 210 108 253 108
200 3 15 13 12 36 61 3 68 3 61 200 3 8 13 12 253 63 210 63 210 108
200 3 10 7 12 37 27 10 27 9 41 200 3 8 12 9 253 63 210 108 253 108
200 3 10 12 42 37 27 9 41 39 41 200 3 9 12 15 91 84 140 84 140 134
200 3 15 12 27 36 61 3 61 4 68 200 3 9 15 10 91 84 140 134 91 134
200 3 15 27 26 36 61 4 68 36 68 200 3 5 0 3 91 84 140 84 140 134
200 3 40 41 7 1 73 9 73 10 27 200 3 5 3 6 91 84 140 134 91 134
200 3 7 6 5 22 18 56 13 60 76 200 3 16 17 18 9 41 9 73 14 73
200 3 7 5 4 22 18 60 76 14 76 200 3 16 18 19 9 41 14 73 14 41
200 3 4 40 7 0 73 1 73 10 27 200 3 19 20 21 3 61 36 61 36 68
200 3 6 11 8 224 186 250 186 254 233 200 3 19 21 22 3 61 36 68 5 68
200 3 6 8 5 224 186 254 233 221 233 200 3 23 24 25 35 73 35 41 29 41
200 3 11 10 9 57 13 23 17 14 76 200 3 23 25 26 35 73 29 41 29 73
200 3 11 9 8 57 13 14 76 60 76 200 3 27 25 28 36 61 3 61 4 68
200 3 7 10 11 184 191 218 191 218 243 200 3 27 28 29 36 61 4 68 36 68
200 3 7 11 6 184 191 218 243 184 243 200 3 19 18 26 14 41 14 73 29 73
200 3 2 3 31 140 84 91 84 91 134 200 3 19 26 25 14 41 29 73 29 41
200 3 2 31 30 140 84 91 134 140 134 200 3 24 30 31 3 61 36 61 36 68
200 3 37 39 38 140 84 91 84 91 134 200 3 24 31 32 3 61 36 68 5 68
200 3 37 38 36 140 84 91 134 140 134 200 3 33 34 24 46 73 39 41 35 41
200 3 33 24 23 46 73 35 41 35 73
200 3 27 30 24 36 61 37 68 3 68
200 3 27 24 25 36 61 3 68 3 61
200 3 35 20 19 36 61 37 68 3 68
200 3 35 19 16 36 61 3 68 3 61
200 3 36 37 16 37 27 10 27 9 41
200 3 36 16 34 37 27 9 41 39 41
200 3 35 16 38 36 61 3 61 4 68
200 3 35 38 39 36 61 4 68 36 68
200 3 40 17 37 1 73 9 73 10 27
200 3 37 41 42 22 18 56 13 60 76
200 3 37 42 43 22 18 60 76 14 76
200 3 43 40 37 0 73 1 73 10 27
200 3 41 44 45 224 186 250 186 254 233
200 3 41 45 42 224 186 254 233 221 233
200 3 44 36 33 57 13 23 17 14 76
200 3 44 33 45 57 13 14 76 60 76
200 3 37 36 44 184 191 218 191 218 243
200 3 37 44 41 184 191 218 243 184 243
200 3 13 8 11 140 84 91 84 91 134
200 3 13 11 14 140 84 91 134 140 134
200 3 1 4 7 140 84 91 84 91 134
200 3 1 7 2 140 84 91 134 140 134
4200 3 46 47 49 3 100 17 18 131 238 131 256 148 256
4200 3 49 48 46 3 100 17 18 148 256 148 238 131 238
CONNECTORS 1 CONNECTORS 1
3 -63 114 3 -63 114

View File

@ -3,7 +3,7 @@ TYPE 10200
TEXTURE 0 page-13-player-buildings.png 256 256 TEXTURE 0 page-13-player-buildings.png 256 256
LEVELS 1 LEVELS 1
LEVEL 1 LEVEL 1
POINTS 29 POINTS 37
-183 78 -5 -183 78 -5
-170 78 24 -170 78 24
-140 93 -3 -140 93 -3
@ -33,7 +33,15 @@ POINTS 29
-183 0 -5 -183 0 -5
-4 1 -185 -4 1 -185
-170 0 24 -170 0 24
POLYGONS 42 -62 142 -88
-62 126 -41
-15 142 -88
-15 126 -41
-4 100 -185
-73 100 -185
-73 1 -185
-4 1 -185
POLYGONS 44
200 3 0 1 2 234 110 250 103 234 87 200 3 0 1 2 234 110 250 103 234 87
200 3 3 0 2 216 104 234 110 234 87 200 3 3 0 2 216 104 234 110 234 87
200 3 1 4 2 250 103 255 87 234 87 200 3 1 4 2 250 103 255 87 234 87
@ -74,7 +82,9 @@ POLYGONS 42
200 3 20 15 17 189 248 218 165 214 248 200 3 20 15 17 189 248 218 165 214 248
200 3 4 1 28 0 187 25 187 25 238 200 3 4 1 28 0 187 25 187 25 238
200 3 4 28 7 0 187 25 238 0 238 200 3 4 28 7 0 187 25 238 0 238
200 3 21 27 23 255 190 255 233 219 233 4200 3 29 30 32 3 100 17 18 131 238 131 256 148 256
200 3 21 23 22 255 190 219 233 219 190 4200 3 32 31 29 3 100 17 18 148 256 148 238 131 238
200 3 33 36 35 255 190 255 233 219 233
200 3 33 35 34 255 190 219 233 219 190
CONNECTORS 1 CONNECTORS 1
-37 -65 135 -50 -70 136

View File

@ -3,7 +3,7 @@ TYPE 10200
TEXTURE 0 page-13-player-buildings.png 256 256 TEXTURE 0 page-13-player-buildings.png 256 256
LEVELS 1 LEVELS 1
LEVEL 1 LEVEL 1
POINTS 55 POINTS 63
-183 78 -5 -183 78 -5
-170 78 24 -170 78 24
-140 93 -3 -140 93 -3
@ -59,7 +59,15 @@ POINTS 55
-161 0 135 -161 0 135
-148 0 165 -148 0 165
-117 0 178 -117 0 178
POLYGONS 76 6 142 -88
6 126 -41
54 142 -88
54 126 -41
-62 142 -88
-62 126 -41
-15 142 -88
-15 126 -41
POLYGONS 80
200 3 0 1 2 234 110 250 103 234 87 200 3 0 1 2 234 110 250 103 234 87
200 3 3 0 2 216 104 234 110 234 87 200 3 3 0 2 216 104 234 110 234 87
200 3 1 4 2 250 103 255 87 234 87 200 3 1 4 2 250 103 255 87 234 87
@ -136,5 +144,9 @@ POLYGONS 76
200 3 39 54 40 0 135 25 187 0 187 200 3 39 54 40 0 135 25 187 0 187
200 3 39 38 45 250 71 234 63 234 87 200 3 39 38 45 250 71 234 63 234 87
200 3 49 44 45 250 103 255 87 234 87 200 3 49 44 45 250 103 255 87 234 87
4200 3 55 56 58 3 100 17 18 131 238 131 256 148 256
4200 3 58 57 55 3 100 17 18 148 256 148 238 131 238
4200 3 59 60 62 3 100 17 18 131 238 131 256 148 256
4200 3 62 61 59 3 100 17 18 148 256 148 238 131 238
CONNECTORS 1 CONNECTORS 1
32 -65 136 32 -65 136

View File

@ -3,7 +3,7 @@ TYPE 10200
TEXTURE 0 page-13-player-buildings.png 256 256 TEXTURE 0 page-13-player-buildings.png 256 256
LEVELS 1 LEVELS 1
LEVEL 1 LEVEL 1
POINTS 75 POINTS 87
145 78 85 145 78 85
113 78 93 113 78 93
138 93 126 138 93 126
@ -79,7 +79,19 @@ POINTS 75
-148 0 165 -148 0 165
-117 0 178 -117 0 178
-87 0 165 -87 0 165
POLYGONS 110 -62 142 -88
-62 126 -41
-15 142 -88
-15 126 -41
5 142 -89
5 126 -42
53 142 -89
53 126 -42
75 142 -88
75 126 -41
122 142 -88
122 126 -41
POLYGONS 116
200 3 0 1 2 209 87 216 104 234 87 200 3 0 1 2 209 87 216 104 234 87
200 3 0 3 4 0 83 25 83 25 135 200 3 0 3 4 0 83 25 83 25 135
200 3 0 4 5 0 83 25 135 0 135 200 3 0 4 5 0 83 25 135 0 135
@ -190,5 +202,11 @@ POLYGONS 110
200 3 59 62 74 0 135 25 135 25 187 200 3 59 62 74 0 135 25 135 25 187
200 3 59 74 60 0 135 25 187 0 187 200 3 59 74 60 0 135 25 187 0 187
200 3 59 58 63 234 63 218 71 234 87 200 3 59 58 63 234 63 218 71 234 87
4200 3 75 76 78 3 100 17 18 131 238 131 256 148 256
4200 3 78 77 75 3 100 17 18 148 256 148 238 131 238
4200 3 79 80 82 3 100 17 18 131 238 131 256 148 256
4200 3 82 81 79 3 100 17 18 148 256 148 238 131 238
4200 3 83 84 86 3 100 17 18 131 238 131 256 148 256
4200 3 86 85 83 3 100 17 18 148 256 148 238 131 238
CONNECTORS 1 CONNECTORS 1
101 -63 136 101 -63 136

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 MiB

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 258 KiB

After

Width:  |  Height:  |  Size: 296 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 MiB

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 MiB

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 MiB

After

Width:  |  Height:  |  Size: 302 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 MiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 MiB

After

Width:  |  Height:  |  Size: 336 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 MiB

After

Width:  |  Height:  |  Size: 26 KiB

View File

@ -272,18 +272,18 @@ data "wrf/multires3.wrf"
// Tech 2 // Tech 2
level Sk-Rush2-T2
players 4
type 18
dataset MULTI_T2_C1
game "multiplay/maps/4c-rush2.gam"
level Sk-Rush-T2 level Sk-Rush-T2
players 4 players 4
type 18 type 18
dataset MULTI_T2_C1 dataset MULTI_T2_C1
game "multiplay/maps/4c-rush.gam" game "multiplay/maps/4c-rush.gam"
level Sk-Rush2-T2
players 4
type 18
dataset MULTI_T2_C1
game "multiplay/maps/4c-rush2.gam"
level Sk-StartUp-T2 level Sk-StartUp-T2
players 2 players 2
type 18 type 18
@ -382,18 +382,18 @@ game "multiplay/maps/8c-thepit.gam"
// Tech 3 // Tech 3
level Sk-Rush2-T3
players 4
type 19
dataset MULTI_T3_C1
game "multiplay/maps/4c-rush2.gam"
level Sk-Rush-T3 level Sk-Rush-T3
players 4 players 4
type 19 type 19
dataset MULTI_T3_C1 dataset MULTI_T3_C1
game "multiplay/maps/4c-rush.gam" game "multiplay/maps/4c-rush.gam"
level Sk-Rush2-T3
players 4
type 19
dataset MULTI_T3_C1
game "multiplay/maps/4c-rush2.gam"
level Sk-StartUp-T3 level Sk-StartUp-T3
players 2 players 2
type 19 type 19

Binary file not shown.

View File

@ -494,9 +494,9 @@ static bool gdbExtendedBacktrace(int const dumpFile)
* additions to the frame-pointer register's content. * additions to the frame-pointer register's content.
*/ */
void const * const frame = void const * const frame =
#if defined(SA_SIGINFO) && __WORDSIZE == 64 #if defined(SA_SIGINFO) && defined(REG_RBP)
sigcontext ? (void*)(sigcontext->uc_mcontext.gregs[REG_RBP] + sizeof(greg_t) + sizeof(void (*)(void))) : NULL; sigcontext ? (void*)(sigcontext->uc_mcontext.gregs[REG_RBP] + sizeof(greg_t) + sizeof(void (*)(void))) : NULL;
#elif defined(SA_SIGINFO) && __WORDSIZE == 32 #elif defined(SA_SIGINFO) && defined(REG_EBP)
sigcontext ? (void*)(sigcontext->uc_mcontext.gregs[REG_EBP] + sizeof(greg_t) + sizeof(void (*)(void))) : NULL; sigcontext ? (void*)(sigcontext->uc_mcontext.gregs[REG_EBP] + sizeof(greg_t) + sizeof(void (*)(void))) : NULL;
#else #else
NULL; NULL;
@ -506,9 +506,9 @@ static bool gdbExtendedBacktrace(int const dumpFile)
* Faulting instruction. * Faulting instruction.
*/ */
void (*instruction)(void) = void (*instruction)(void) =
#if defined(SA_SIGINFO) && __WORDSIZE == 64 #if defined(SA_SIGINFO) && defined(REG_RIP)
sigcontext ? (void (*)(void))sigcontext->uc_mcontext.gregs[REG_RIP] : NULL; sigcontext ? (void (*)(void))sigcontext->uc_mcontext.gregs[REG_RIP] : NULL;
#elif defined(SA_SIGINFO) && __WORDSIZE == 32 #elif defined(SA_SIGINFO) && defined(REG_EIP)
sigcontext ? (void (*)(void))sigcontext->uc_mcontext.gregs[REG_EIP] : NULL; sigcontext ? (void (*)(void))sigcontext->uc_mcontext.gregs[REG_EIP] : NULL;
#else #else
NULL; NULL;

View File

@ -17,7 +17,9 @@
along with Warzone 2100; if not, write to the Free Software along with Warzone 2100; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#include "crc.h" #include "crc.h"
#include "lib/netplay/netsocket.h" // For htonl
// Invariant: // Invariant:
// crcTable[0] = 0; // crcTable[0] = 0;
@ -64,3 +66,155 @@ uint32_t crcSumVector2i(uint32_t crc, const Vector2i *data, size_t dataLen)
return crc; return crc;
} }
// Let primes[n] = {2, 3, 5, 7, 11, ...}.
// Invariant: sha256TableH[n] = sqrt(primes[n]) << 32
static const uint32_t sha256TableH[8] = {0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19};
// Invariant: sha256TableK[n] = pow(primes[n], 1/3.) << 32
static const uint32_t sha256TableK[64] = {0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967, 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2};
// Rotate right.
static inline uint32_t ror(uint32_t a, int shift)
{
return (a >> shift) | (a << (32 - shift)); // This is correctly optimised to a rotate-right instruction, in GCC, at least.
}
static void sha256SumBlock(uint32_t *w, uint32_t *h)
{
for (unsigned i = 0; i < 16; ++i)
{
w[i] = ntohl(w[i]); // Interpret data as big-endian 32-bit numbers.
}
// Extend w block from length 16 to 64.
for (unsigned i = 16; i < 64; ++i)
{
uint32_t s0 = ror(w[i - 15], 7) ^ ror(w[i - 15], 18) ^ (w[i - 15] >> 3);
uint32_t s1 = ror(w[i - 2], 17) ^ ror(w[i - 2], 19) ^ (w[i - 2] >> 10);
w[i] = w[i - 16] + s0 + w[i - 7] + s1;
}
uint32_t a = h[0], b = h[1], c = h[2], d = h[3], e = h[4], f = h[5], g = h[6], j = h[7];
for (unsigned i = 0; i < 64; ++i)
{
uint32_t s0 = ror(a, 2) ^ ror(a, 13) ^ ror(a, 22);
uint32_t maj = (a & b) ^ (a & c) ^ (b & c); // Can be simplified to ((a ^ b) & c) ^ (a & b), but GCC does this at compile time.
uint32_t t2 = s0 + maj;
uint32_t s1 = ror(e, 6) ^ ror(e, 11) ^ ror(e, 25);
uint32_t ch = (e & (f ^ g)) ^ g; // Equivalent to (e & f) ^ (~e & g), but saves a 'notl' instruction.
uint32_t t1 = j + s1 + ch + sha256TableK[i] + w[i];
j = g;
g = f;
f = e;
e = d + t1;
d = c;
c = b;
b = a;
a = t1 + t2;
}
h[0] += a;
h[1] += b;
h[2] += c;
h[3] += d;
h[4] += e;
h[5] += f;
h[6] += g;
h[7] += j;
}
Sha256 sha256Sum(void const *data, size_t dataLen)
{
uint32_t h[8];
std::copy(sha256TableH, sha256TableH + 8, h);
// Add the suffix to the data.
char suffix[64 + 8];
size_t suffixLen = ((-9 - dataLen) & 63) + 9;
suffix[0] = 0x80;
memset(suffix + 1, 0x00, suffixLen - 1 - 8);
uint32_t size[2] = {htonl(dataLen >> 29), htonl(dataLen << 3)}; // Convert dataLen to number of bits, in big-endian format.
memcpy(suffix + suffixLen - 8, (char *)size, 8);
// Hash the data.
uint32_t w[64]; // 16 elements are passed to sha256SumBlock(), rest is used as scratch space by sha256SumBlock().
for (size_t z = 0; z + 63 < dataLen; z += 64)
{
memcpy((char *)w, (char const *)data + z, 64);
sha256SumBlock(w, h);
}
memcpy((char *)w, (char const *)data + (dataLen & ~63), dataLen & 63);
memcpy((char *)w + (dataLen & 63), suffix, ((suffixLen - 1) & 63) + 1);
sha256SumBlock(w, h);
if (suffixLen > 64)
{
memcpy((char *)w, suffix + (suffixLen & 63), 64);
sha256SumBlock(w, h);
}
// Convert result to big-endian, and return it.
for (unsigned i = 0; i < 8; ++i)
{
h[i] = htonl(h[i]);
}
Sha256 ret;
memcpy(ret.bytes, h, 32);
return ret;
}
bool Sha256::operator ==(Sha256 const &b) const
{
return memcmp(bytes, b.bytes, Bytes) == 0;
}
bool Sha256::isZero() const
{
return bytes[0] == 0x00 && memcmp(bytes, bytes + 1, Bytes - 1) == 0;
}
void Sha256::setZero()
{
memset(bytes, 0x00, Bytes);
}
std::string Sha256::toString() const
{
std::string str;
str.resize(Bytes*2);
char const *hexDigits = "0123456789abcdef";
for (unsigned n = 0; n < Bytes; ++n)
{
str[n*2 ] = hexDigits[bytes[n] >> 4];
str[n*2 + 1] = hexDigits[bytes[n] & 15];
}
return str;
}
void Sha256::fromString(std::string const &s)
{
setZero();
unsigned nChars = std::min<unsigned>(Bytes*2, s.size());
for (unsigned n = 0; n < nChars; ++n)
{
unsigned h;
unsigned c = s[n];
if (c >= '0' && c <= '9')
{
h = c - '0';
}
else if (c >= 'a' && c <= 'f')
{
h = c - 'a' + 10;
}
else if (c >= 'A' && c <= 'F')
{
h = c - 'A' + 10;
}
else
{
break;
}
bytes[n/2] |= h << (n%2? 0 : 4);
}
}

View File

@ -22,9 +22,26 @@
#include "types.h" #include "types.h"
#include "vector.h" #include "vector.h"
#include <vector>
#include <string>
uint32_t crcSum(uint32_t crc, const void *data, size_t dataLen); uint32_t crcSum(uint32_t crc, const void *data, size_t dataLen);
uint32_t crcSumU16(uint32_t crc, const uint16_t *data, size_t dataLen); uint32_t crcSumU16(uint32_t crc, const uint16_t *data, size_t dataLen);
uint32_t crcSumVector2i(uint32_t crc, const Vector2i *data, size_t dataLen); uint32_t crcSumVector2i(uint32_t crc, const Vector2i *data, size_t dataLen);
struct Sha256
{
static const int Bytes = 32;
bool operator ==(Sha256 const &b) const;
bool isZero() const;
void setZero();
std::string toString() const;
void fromString(std::string const &s);
uint8_t bytes[Bytes];
};
Sha256 sha256Sum(void const *data, size_t dataLen);
#endif //_CRC_H_ #endif //_CRC_H_

View File

@ -21,6 +21,9 @@
#include <physfs.h> #include <physfs.h>
#include "crc.h"
/*! Open a file for reading */ /*! Open a file for reading */
extern PHYSFS_file* openLoadFile(const char* fileName, bool hard_fail); extern PHYSFS_file* openLoadFile(const char* fileName, bool hard_fail);
@ -42,4 +45,6 @@ extern bool loadFileToBuffer(const char *pFileName, char *pFileBuffer, UDWORD bu
extern bool loadFileToBufferNoError(const char *pFileName, char *pFileBuffer, UDWORD bufferSize, extern bool loadFileToBufferNoError(const char *pFileName, char *pFileBuffer, UDWORD bufferSize,
UDWORD *pSize); UDWORD *pSize);
Sha256 findHashOfFile(char const *realFileName);
#endif // _file_h #endif // _file_h

View File

@ -183,17 +183,22 @@ PHYSFS_file* openLoadFile(const char* fileName, bool hard_fail)
static bool loadFile2(const char *pFileName, char **ppFileData, UDWORD *pFileSize, static bool loadFile2(const char *pFileName, char **ppFileData, UDWORD *pFileSize,
bool AllocateMem, bool hard_fail) bool AllocateMem, bool hard_fail)
{ {
PHYSFS_file *pfile; if (PHYSFS_isDirectory(pFileName))
PHYSFS_sint64 filesize; {
PHYSFS_sint64 length_read; return false;
}
pfile = openLoadFile(pFileName, hard_fail); PHYSFS_file *pfile = openLoadFile(pFileName, hard_fail);
if (!pfile) if (!pfile)
{ {
return false; return false;
} }
filesize = PHYSFS_fileLength(pfile); PHYSFS_sint64 filesize = PHYSFS_fileLength(pfile);
if (filesize < 0)
{
return false; // File size could not be determined. Is a directory?
}
//debug(LOG_WZ, "loadFile2: %s opened, size %i", pFileName, filesize); //debug(LOG_WZ, "loadFile2: %s opened, size %i", pFileName, filesize);
@ -220,7 +225,7 @@ static bool loadFile2(const char *pFileName, char **ppFileData, UDWORD *pFileSiz
} }
/* Load the file data */ /* Load the file data */
length_read = PHYSFS_read(pfile, *ppFileData, 1, filesize); PHYSFS_sint64 length_read = PHYSFS_read(pfile, *ppFileData, 1, filesize);
if (length_read != filesize) if (length_read != filesize)
{ {
if (AllocateMem) if (AllocateMem)
@ -336,6 +341,16 @@ bool loadFileToBufferNoError(const char *pFileName, char *pFileBuffer, UDWORD bu
return loadFile2(pFileName, &pFileBuffer, pSize, false, false); return loadFile2(pFileName, &pFileBuffer, pSize, false, false);
} }
Sha256 findHashOfFile(char const *realFileName)
{
char *realFileData = NULL;
uint32_t realFileSize = 0;
loadFile(realFileName, &realFileData, &realFileSize);
Sha256 realFileHash = sha256Sum(realFileData, realFileSize);
free(realFileData);
return realFileHash;
}
/* next four used in HashPJW */ /* next four used in HashPJW */
#define BITS_IN_int 32 #define BITS_IN_int 32

View File

@ -53,6 +53,15 @@
extern bool drawing_interface; extern bool drawing_interface;
// Shadow stencil stuff
static void ss_GL2_1pass();
static void ss_EXT_1pass();
static void ss_ATI_1pass();
static void ss_2pass();
static void (*ShadowStencilFunc)() = 0;
static GLenum ss_op_depth_pass_front = GL_INCR;
static GLenum ss_op_depth_pass_back = GL_DECR;
/* /*
* Local Variables * Local Variables
*/ */
@ -136,7 +145,7 @@ static void pie_Draw3DShape2(iIMDShape *shape, int frame, PIELIGHT colour, PIELI
{ {
iIMDPoly *pPolys; iIMDPoly *pPolys;
bool light = true; bool light = true;
bool shaders = pie_GetShaderAvailability(); bool shaders = pie_GetShaderUsage();
pie_SetAlphaTest((pieFlag & pie_PREMULTIPLIED) == 0); pie_SetAlphaTest((pieFlag & pie_PREMULTIPLIED) == 0);
@ -438,7 +447,30 @@ static void inverse_matrix(const float * src, float * dst)
void pie_SetUp(void) void pie_SetUp(void)
{ {
// initialise pie engine (just a placeholder for now) // initialise pie engine
if (GLEW_EXT_stencil_wrap)
{
ss_op_depth_pass_front = GL_INCR_WRAP;
ss_op_depth_pass_back = GL_DECR_WRAP;
}
if (GLEW_VERSION_2_0)
{
ShadowStencilFunc = ss_GL2_1pass;
}
else if (GLEW_EXT_stencil_two_side)
{
ShadowStencilFunc = ss_EXT_1pass;
}
else if (GLEW_ATI_separate_stencil)
{
ShadowStencilFunc = ss_ATI_1pass;
}
else
{
ShadowStencilFunc = ss_2pass;
}
} }
void pie_CleanUp( void ) void pie_CleanUp( void )
@ -529,7 +561,6 @@ static void pie_DrawShadows(void)
{ {
const float width = pie_GetVideoBufferWidth(); const float width = pie_GetVideoBufferWidth();
const float height = pie_GetVideoBufferHeight(); const float height = pie_GetVideoBufferHeight();
GLenum op_depth_pass_front = GL_INCR, op_depth_pass_back = GL_DECR;
pie_SetTexturePage(TEXPAGE_NONE); pie_SetTexturePage(TEXPAGE_NONE);
@ -541,60 +572,7 @@ static void pie_DrawShadows(void)
glDepthMask(GL_FALSE); glDepthMask(GL_FALSE);
glEnable(GL_STENCIL_TEST); glEnable(GL_STENCIL_TEST);
// Check if we have the required extensions ShadowStencilFunc();
if (GLEW_EXT_stencil_wrap)
{
op_depth_pass_front = GL_INCR_WRAP_EXT;
op_depth_pass_back = GL_DECR_WRAP_EXT;
}
// generic 1-pass version
if (GLEW_EXT_stencil_two_side)
{
glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
glDisable(GL_CULL_FACE);
glStencilMask(~0);
glActiveStencilFaceEXT(GL_BACK);
glStencilOp(GL_KEEP, GL_KEEP, op_depth_pass_back);
glStencilFunc(GL_ALWAYS, 0, ~0);
glActiveStencilFaceEXT(GL_FRONT);
glStencilOp(GL_KEEP, GL_KEEP, op_depth_pass_front);
glStencilFunc(GL_ALWAYS, 0, ~0);
pie_ShadowDrawLoop();
glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);
}
// check for ATI-specific 1-pass version
else if (GLEW_ATI_separate_stencil)
{
glDisable(GL_CULL_FACE);
glStencilMask(~0);
glStencilOpSeparateATI(GL_BACK, GL_KEEP, GL_KEEP, op_depth_pass_back);
glStencilOpSeparateATI(GL_FRONT, GL_KEEP, GL_KEEP, op_depth_pass_front);
glStencilFunc(GL_ALWAYS, 0, ~0);
pie_ShadowDrawLoop();
}
// fall back to default 2-pass version
else
{
glStencilMask(~0);
glStencilFunc(GL_ALWAYS, 0, ~0);
glEnable(GL_CULL_FACE);
// Setup stencil for front-facing polygons
glCullFace(GL_BACK);
glStencilOp(GL_KEEP, GL_KEEP, op_depth_pass_front);
pie_ShadowDrawLoop();
// Setup stencil for back-facing polygons
glCullFace(GL_FRONT);
glStencilOp(GL_KEEP, GL_KEEP, op_depth_pass_back);
pie_ShadowDrawLoop();
}
pie_SetRendMode(REND_ALPHA); pie_SetRendMode(REND_ALPHA);
glEnable(GL_CULL_FACE); glEnable(GL_CULL_FACE);
@ -698,3 +676,65 @@ void pie_GetResetCounts(unsigned int* pPieCount, unsigned int* pPolyCount, unsig
pieStateCount = 0; pieStateCount = 0;
return; return;
} }
// GL 2.0 1-pass version
static void ss_GL2_1pass()
{
glDisable(GL_CULL_FACE);
glStencilMask(~0);
glStencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, GL_INCR_WRAP);
glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_DECR_WRAP);
glStencilFunc(GL_ALWAYS, 0, ~0);
pie_ShadowDrawLoop();
}
// generic 1-pass version
static void ss_EXT_1pass()
{
glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
glDisable(GL_CULL_FACE);
glStencilMask(~0);
glActiveStencilFaceEXT(GL_BACK);
glStencilOp(GL_KEEP, GL_KEEP, ss_op_depth_pass_back);
glStencilFunc(GL_ALWAYS, 0, ~0);
glActiveStencilFaceEXT(GL_FRONT);
glStencilOp(GL_KEEP, GL_KEEP, ss_op_depth_pass_front);
glStencilFunc(GL_ALWAYS, 0, ~0);
pie_ShadowDrawLoop();
glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);
}
// ATI-specific 1-pass version
static void ss_ATI_1pass()
{
glDisable(GL_CULL_FACE);
glStencilMask(~0);
glStencilOpSeparateATI(GL_BACK, GL_KEEP, GL_KEEP, ss_op_depth_pass_back);
glStencilOpSeparateATI(GL_FRONT, GL_KEEP, GL_KEEP, ss_op_depth_pass_front);
glStencilFunc(GL_ALWAYS, 0, ~0);
pie_ShadowDrawLoop();
}
// generic 2-pass version
static void ss_2pass()
{
glStencilMask(~0);
glStencilFunc(GL_ALWAYS, 0, ~0);
glEnable(GL_CULL_FACE);
// Setup stencil for front-facing polygons
glCullFace(GL_BACK);
glStencilOp(GL_KEEP, GL_KEEP, ss_op_depth_pass_front);
pie_ShadowDrawLoop();
// Setup stencil for back-facing polygons
glCullFace(GL_FRONT);
glStencilOp(GL_KEEP, GL_KEEP, ss_op_depth_pass_back);
pie_ShadowDrawLoop();
}

View File

@ -50,6 +50,7 @@ iSurface rendSurface;
bool pie_Initialise(void) bool pie_Initialise(void)
{ {
pie_SetUp();
pie_TexInit(); pie_TexInit();
/* Find texture compression extension */ /* Find texture compression extension */

View File

@ -37,6 +37,7 @@
*/ */
static bool shadersAvailable = false; static bool shadersAvailable = false;
static bool shaderUsage = false;
static GLuint shaderProgram[SHADER_MAX]; static GLuint shaderProgram[SHADER_MAX];
static GLfloat shaderStretch = 0; static GLfloat shaderStretch = 0;
static GLint locTeam, locStretch, locTCMask, locFog, locNormalMap, locEcm, locTime; static GLint locTeam, locStretch, locTCMask, locFog, locNormalMap, locEcm, locTime;
@ -139,6 +140,16 @@ void pie_SetShaderAvailability(bool availability)
shadersAvailable = availability; shadersAvailable = availability;
} }
bool pie_GetShaderUsage(void)
{
return shaderUsage;
}
void pie_SetShaderUsage(bool usage)
{
shaderUsage = pie_GetShaderAvailability() && usage;
}
// Read shader into text buffer // Read shader into text buffer
static char *readShaderBuf(const char *name) static char *readShaderBuf(const char *name)
{ {
@ -389,7 +400,7 @@ void pie_ActivateFallback(SHADER_MODE, iIMDShape* shape, PIELIGHT teamcolour, PI
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
if (GLEW_ARB_imaging) if (GLEW_ARB_imaging || GLEW_EXT_blend_color)
{ {
glEnable(GL_BLEND); glEnable(GL_BLEND);
glBlendFunc(GL_CONSTANT_COLOR, GL_ZERO); glBlendFunc(GL_CONSTANT_COLOR, GL_ZERO);

View File

@ -85,6 +85,9 @@ extern void pie_SetRendMode(REND_MODE rendMode);
// Shaders control center // Shaders control center
extern bool pie_GetShaderAvailability(void); extern bool pie_GetShaderAvailability(void);
extern void pie_SetShaderAvailability(bool); extern void pie_SetShaderAvailability(bool);
extern bool pie_GetShaderUsage(void);
extern void pie_SetShaderUsage(bool);
bool pie_LoadShaders(void); bool pie_LoadShaders(void);
// Actual shaders (we do not want to export these calls) // Actual shaders (we do not want to export these calls)
void pie_DeactivateShader(void); void pie_DeactivateShader(void);

View File

@ -47,7 +47,6 @@
/* global used to indicate preferred internal OpenGL format */ /* global used to indicate preferred internal OpenGL format */
int wz_texture_compression = 0; int wz_texture_compression = 0;
bool opengl_fallback_mode = false;
static bool bBackDrop = false; static bool bBackDrop = false;
static char screendump_filename[PATH_MAX]; static char screendump_filename[PATH_MAX];
@ -167,11 +166,14 @@ bool screenInitialise()
debug(LOG_3D, " * (current) Max Sample level is %d.", (int) glmaxSamples); debug(LOG_3D, " * (current) Max Sample level is %d.", (int) glmaxSamples);
} }
bool canRunAtAll = GLEW_VERSION_1_2 && GLEW_ARB_vertex_buffer_object && GLEW_ARB_texture_env_crossbar; bool haveARB_vertex_buffer_object = GLEW_ARB_vertex_buffer_object || GLEW_VERSION_1_5;
bool haveARB_texture_env_crossbar = GLEW_ARB_texture_env_crossbar || GLEW_NV_texture_env_combine4 || GLEW_VERSION_1_4;
bool canRunAtAll = GLEW_VERSION_1_2 && haveARB_vertex_buffer_object && haveARB_texture_env_crossbar;
bool canRunShaders = canRunAtAll && glslVersion >= std::make_pair(1, 20); // glGetString(GL_SHADING_LANGUAGE_VERSION) >= "1.20" bool canRunShaders = canRunAtAll && glslVersion >= std::make_pair(1, 20); // glGetString(GL_SHADING_LANGUAGE_VERSION) >= "1.20"
if (canRunShaders && !opengl_fallback_mode) if (canRunShaders)
{ {
screen_EnableMissingFunctions(); // We need to do this before pie_LoadShaders(), but the effect of this call will be undone later by iV_TextInit(), so we will need to call it again.
if (pie_LoadShaders()) if (pie_LoadShaders())
{ {
pie_SetShaderAvailability(true); pie_SetShaderAvailability(true);
@ -251,6 +253,16 @@ void screen_EnableMissingFunctions()
__glewUniform1i = __glewUniform1iARB; __glewUniform1i = __glewUniform1iARB;
__glewUniform4fv = __glewUniform4fvARB; __glewUniform4fv = __glewUniform4fvARB;
} }
if ((GLEW_ARB_imaging || GLEW_EXT_blend_color) && __glewBlendColor == NULL)
{
__glewBlendColor = __glewBlendColorEXT; // Shouldn't be needed if GLEW_ARB_imaging is true, but apparently is needed even in that case, with some drivers..?
if (__glewBlendColor == NULL)
{
debug(LOG_ERROR, "Your graphics driver is broken, and claims to support ARB_imaging or EXT_blend_color without exporting glBlendColor[EXT].");
__GLEW_ARB_imaging = __GLEW_EXT_blend_color = 0;
}
}
} }
void screen_SetBackDropFromFile(const char* filename) void screen_SetBackDropFromFile(const char* filename)

View File

@ -56,7 +56,6 @@ extern void screenDumpToDisk(const char* path);
extern int wz_texture_compression; extern int wz_texture_compression;
extern bool opengl_fallback_mode;
extern void screenDoDumpToDiskIfRequired(void); extern void screenDoDumpToDiskIfRequired(void);

View File

@ -52,6 +52,7 @@
#include "src/multiplay.h" #include "src/multiplay.h"
#include "src/warzoneconfig.h" #include "src/warzoneconfig.h"
#include "src/version.h" #include "src/version.h"
#include "src/loadsave.h"
#ifdef WZ_OS_LINUX #ifdef WZ_OS_LINUX
#include <execinfo.h> // Nonfatal runtime backtraces. #include <execinfo.h> // Nonfatal runtime backtraces.
@ -1838,7 +1839,7 @@ bool NETrecvGame(NETQUEUE *queue, uint8_t *type)
* NET_BUFFER_SIZE is at 16k. (also remember text chat, plus all the other cruff) * NET_BUFFER_SIZE is at 16k. (also remember text chat, plus all the other cruff)
*/ */
#define MAX_FILE_TRANSFER_PACKET 2048 #define MAX_FILE_TRANSFER_PACKET 2048
UBYTE NETsendFile(char *fileName, UDWORD player) int NETsendFile(char *fileName, Sha256 const &fileHash, UDWORD player)
{ {
uint32_t bytesToRead = 0; uint32_t bytesToRead = 0;
uint8_t sendto = 0; uint8_t sendto = 0;
@ -1862,7 +1863,11 @@ UBYTE NETsendFile(char *fileName, UDWORD player)
NETint32_t(&NetPlay.players[player].wzFile.fileSize_32); // total bytes in this file. (we don't support 64bit yet) NETint32_t(&NetPlay.players[player].wzFile.fileSize_32); // total bytes in this file. (we don't support 64bit yet)
NETuint32_t(&bytesToRead); // bytes in this packet NETuint32_t(&bytesToRead); // bytes in this packet
NETint32_t(&NetPlay.players[player].wzFile.currPos); // start byte NETint32_t(&NetPlay.players[player].wzFile.currPos); // start byte
NETstring(fileName, 256); //256 = max filename size if (NetPlay.players[player].wzFile.currPos == 0)
{
NETstring(fileName, 256); //256 = max filename size
NETbin(const_cast<uint8_t *>(fileHash.bytes), fileHash.Bytes); // const_cast ok since we're encoding, not decoding.
}
NETbin(inBuff, bytesToRead); NETbin(inBuff, bytesToRead);
NETend(); NETend();
@ -1883,11 +1888,9 @@ UBYTE NETrecvFile(NETQUEUE queue)
{ {
uint32_t bytesToRead = 0; uint32_t bytesToRead = 0;
int32_t fileSize = 0, currPos = 0; int32_t fileSize = 0, currPos = 0;
char fileName[256];
uint8_t outBuff[MAX_FILE_TRANSFER_PACKET]; uint8_t outBuff[MAX_FILE_TRANSFER_PACKET];
static bool isLoop = false; static bool isLoop = false;
memset(fileName, 0x0, sizeof(fileName));
memset(outBuff, 0x0, sizeof(outBuff)); memset(outBuff, 0x0, sizeof(outBuff));
//read incoming bytes. //read incoming bytes.
@ -1895,18 +1898,35 @@ UBYTE NETrecvFile(NETQUEUE queue)
NETint32_t(&fileSize); // total bytes in this file. NETint32_t(&fileSize); // total bytes in this file.
NETuint32_t(&bytesToRead); // bytes in this packet NETuint32_t(&bytesToRead); // bytes in this packet
NETint32_t(&currPos); // start byte NETint32_t(&currPos); // start byte
NETstring(fileName, 256); // read filename (only valid on 1st packet)
debug(LOG_NET, "Creating new file %s, position is %d", fileName, currPos);
if (currPos == 0) // first packet! if (currPos == 0) // first packet!
{ {
char mapName[256];
Sha256 fileHash;
memset(mapName, 0x0, sizeof(mapName));
fileHash.setZero();
// Read filename and hash (only valid on 1st packet)
NETstring(mapName, 256);
NETbin(fileHash.bytes, fileHash.Bytes);
removeWildcards(mapName);
char fileName[256];
if (strlen(mapName) >= 3 && mapName[strlen(mapName) - 3] == '-' && mapName[strlen(mapName) - 2] == 'T' && unsigned(mapName[strlen(mapName) - 1] - '1') < 3)
{
mapName[strlen(mapName) - 3] = '\0'; // Cut off "-T1", "-T2" or "-T3".
}
snprintf(fileName, sizeof(fileName), "maps/%dc-%s-%s.wz", game.maxPlayers, mapName, fileHash.toString().c_str()); // Wonder whether game.maxPlayers is initialised already?
debug(LOG_NET, "Creating new file %s hash %s", fileName, fileHash.toString().c_str());
if (PHYSFS_exists(fileName)) if (PHYSFS_exists(fileName))
{ {
PHYSFS_file *fin; PHYSFS_file *fin;
PHYSFS_sint64 fsize;
fin = PHYSFS_openRead(fileName); fin = PHYSFS_openRead(fileName);
if (!fin) if (!fin)
{ {
NETend();
// the file exists, but we can't open it, and I have no clue how to fix this... // the file exists, but we can't open it, and I have no clue how to fix this...
debug(LOG_FATAL, "PHYSFS_openRead(\"%s\") failed with error: %s\n", fileName, PHYSFS_getLastError()); debug(LOG_FATAL, "PHYSFS_openRead(\"%s\") failed with error: %s\n", fileName, PHYSFS_getLastError());
@ -1921,11 +1941,8 @@ UBYTE NETrecvFile(NETQUEUE queue)
abort(); abort();
} }
else Sha256 ourHash = findHashOfFile(fileName);
{ if (ourHash == fileHash)
fsize = PHYSFS_fileLength(fin);
}
if ((int32_t) fsize == fileSize)
{ {
uint32_t reason = ALREADY_HAVE_FILE; uint32_t reason = ALREADY_HAVE_FILE;
debug(LOG_NET, "We already have the file %s! ", fileName); debug(LOG_NET, "We already have the file %s! ", fileName);
@ -1954,21 +1971,23 @@ UBYTE NETrecvFile(NETQUEUE queue)
PHYSFS_close(NetPlay.pMapFileHandle); PHYSFS_close(NetPlay.pMapFileHandle);
NetPlay.pMapFileHandle = NULL; NetPlay.pMapFileHandle = NULL;
debug(LOG_FATAL, "Something is really wrong with the file's (%s) data, game can't detect it?", fileName); debug(LOG_FATAL, "Something is really wrong with the file's (%s) data, game can't detect it?", fileName);
return 100;
} }
return 100;
} }
PHYSFS_close(fin); PHYSFS_close(fin);
debug(LOG_NET, "We already have the file %s, but different size %d vs %d. Redownloading", fileName, (int32_t) fsize, fileSize); debug(LOG_NET, "We already have the file %s, but wrong hash, ours %s vs theirs %s. Redownloading", fileName, ourHash.toString().c_str(), fileHash.toString().c_str());
} }
NetPlay.pMapFileHandle = PHYSFS_openWrite(fileName); // create a new file. NetPlay.pMapFileHandle = PHYSFS_openWrite(fileName); // create a new file.
} }
debug(LOG_NET, "New file position is %d", currPos);
if (!NetPlay.pMapFileHandle) // file can't be opened if (!NetPlay.pMapFileHandle) // file can't be opened
{ {
debug(LOG_FATAL, "Fatal error while creating file: %s", PHYSFS_getLastError()); debug(LOG_FATAL, "Fatal error while creating file: %s", PHYSFS_getLastError());
debug(LOG_FATAL, "Either we do not have write permission, or the host sent us a invalid file (%s)!", fileName); debug(LOG_FATAL, "Either we do not have write permission, or the host sent us a invalid file!");
abort(); abort();
} }

View File

@ -26,6 +26,7 @@
#ifndef _netplay_h #ifndef _netplay_h
#define _netplay_h #define _netplay_h
#include "lib/framework/crc.h"
#include "nettypes.h" #include "nettypes.h"
#include <physfs.h> #include <physfs.h>
@ -291,7 +292,7 @@ extern bool NETrecvNet(NETQUEUE *queue, uint8_t *type); ///< re
extern bool NETrecvGame(NETQUEUE *queue, uint8_t *type); ///< recv a message from the game queues which is sceduled to execute by time, if possible. extern bool NETrecvGame(NETQUEUE *queue, uint8_t *type); ///< recv a message from the game queues which is sceduled to execute by time, if possible.
void NETflush(void); ///< Flushes any data stuck in compression buffers. void NETflush(void); ///< Flushes any data stuck in compression buffers.
extern UBYTE NETsendFile(char *fileName, UDWORD player); // send file chunk. int NETsendFile(char *mapName, Sha256 const &fileHash, UDWORD player); // send file chunk.
extern UBYTE NETrecvFile(NETQUEUE queue); // recv file chunk extern UBYTE NETrecvFile(NETQUEUE queue); // recv file chunk
extern int NETclose(void); // close current game extern int NETclose(void); // close current game

View File

@ -1,10 +1,10 @@
#!/bin/sh #!/bin/sh
OutDir="WarzoneHelp" OutDir="WarzoneHelp"
DirectorY="${OutDir}-1974546" DirectorY="${OutDir}-b66426c"
FileName="${DirectorY}.tgz" FileName="${DirectorY}.tgz"
BuiltDLP="http://downloads.sourceforge.net/project/warzone2100/build-tools/mac/${FileName}" BuiltDLP="http://downloads.sourceforge.net/project/warzone2100/build-tools/mac/${FileName}"
MD5Sum="ec7fafe1ffc4f2c94f2e916e85489982" MD5Sum="e0f3b5d15efa4a063461c1ffb21769b8"
configs/FetchPrebuilt.sh "${DirectorY}" "${OutDir}" "${FileName}" "${BuiltDLP}" "${MD5Sum}" configs/FetchPrebuilt.sh "${DirectorY}" "${OutDir}" "${FileName}" "${BuiltDLP}" "${MD5Sum}"
exit ${?} exit ${?}

File diff suppressed because it is too large Load Diff

825
po/cs.po

File diff suppressed because it is too large Load Diff

825
po/da.po

File diff suppressed because it is too large Load Diff

830
po/de.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

830
po/es.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

825
po/fi.po

File diff suppressed because it is too large Load Diff

830
po/fr.po

File diff suppressed because it is too large Load Diff

824
po/fy.po

File diff suppressed because it is too large Load Diff

824
po/ga.po

File diff suppressed because it is too large Load Diff

825
po/hr.po

File diff suppressed because it is too large Load Diff

830
po/hu.po

File diff suppressed because it is too large Load Diff

825
po/it.po

File diff suppressed because it is too large Load Diff

825
po/ko.po

File diff suppressed because it is too large Load Diff

830
po/la.po

File diff suppressed because it is too large Load Diff

824
po/lt.po

File diff suppressed because it is too large Load Diff

824
po/nb.po

File diff suppressed because it is too large Load Diff

830
po/nl.po

File diff suppressed because it is too large Load Diff

830
po/pl.po

File diff suppressed because it is too large Load Diff

825
po/pt.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

825
po/ro.po

File diff suppressed because it is too large Load Diff

830
po/ru.po

File diff suppressed because it is too large Load Diff

825
po/sk.po

File diff suppressed because it is too large Load Diff

825
po/sl.po

File diff suppressed because it is too large Load Diff

830
po/tr.po

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

View File

@ -599,7 +599,7 @@ bool ParseCommandLine(int argc, const char** argv)
break; break;
case CLI_FALLBACKMODE: case CLI_FALLBACKMODE:
opengl_fallback_mode = true; war_SetShaders(SHADERS_OFF);
break; break;
}; };
} }

View File

@ -55,7 +55,7 @@ bool combFire(WEAPON *psWeap, BASE_OBJECT *psAttacker, BASE_OBJECT *psTarget, in
/* Watermelon:dont shoot if the weapon_slot of a vtol is empty */ /* Watermelon:dont shoot if the weapon_slot of a vtol is empty */
if (psAttacker->type == OBJ_DROID && isVtolDroid(((DROID *)psAttacker))) if (psAttacker->type == OBJ_DROID && isVtolDroid(((DROID *)psAttacker)))
{ {
if (((DROID *)psAttacker)->sMove.iAttackRuns[weapon_slot] >= getNumAttackRuns(((DROID *)psAttacker), weapon_slot)) if (psWeap->usedAmmo >= getNumAttackRuns(((DROID *)psAttacker), weapon_slot))
{ {
objTrace(psAttacker->id, "VTOL slot %d is empty", weapon_slot); objTrace(psAttacker->id, "VTOL slot %d is empty", weapon_slot);
return false; return false;

View File

@ -98,12 +98,14 @@ bool loadConfig()
if (ini.contains("mapName") && ini.contains("maxPlayers")) if (ini.contains("mapName") && ini.contains("maxPlayers"))
{ {
sstrcpy(game.map, ini.value("mapName").toString().toUtf8().constData()); sstrcpy(game.map, ini.value("mapName").toString().toUtf8().constData());
game.hash.fromString(ini.value("mapHash").toString().toUtf8().constData());
game.maxPlayers = ini.value("maxPlayers").toInt(); // FIXME: horrible kluge, MUST match map above game.maxPlayers = ini.value("maxPlayers").toInt(); // FIXME: horrible kluge, MUST match map above
} }
else else
{ {
// Set a default map to prevent hosting games without a map. // Set a default map to prevent hosting games without a map.
sstrcpy(game.map, "Sk-Rush"); sstrcpy(game.map, "Sk-Rush");
game.hash.setZero();
game.maxPlayers = 4; game.maxPlayers = 4;
} }
game.power = ini.value("power", LEV_MED).toInt(); game.power = ini.value("power", LEV_MED).toInt();
@ -121,6 +123,7 @@ bool loadConfig()
if (ini.contains("textureSize")) setTextureSize(ini.value("textureSize").toInt()); if (ini.contains("textureSize")) setTextureSize(ini.value("textureSize").toInt());
NetPlay.isUPNP = ini.value("UPnP", true).toBool(); NetPlay.isUPNP = ini.value("UPnP", true).toBool();
if (ini.contains("FSAA")) war_setFSAA(ini.value("FSAA").toInt()); if (ini.contains("FSAA")) war_setFSAA(ini.value("FSAA").toInt());
if (ini.contains("shaders")) war_SetShaders(ini.value("shaders").toInt());
// Leave this to false, some system will fail and they can't see the system popup dialog! // Leave this to false, some system will fail and they can't see the system popup dialog!
war_setFullscreen(ini.value("fullscreen", false).toBool()); war_setFullscreen(ini.value("fullscreen", false).toBool());
war_SetTrapCursor(ini.value("trapCursor", false).toBool()); war_SetTrapCursor(ini.value("trapCursor", false).toBool());
@ -187,6 +190,7 @@ bool saveConfig()
ini.setValue("radarTerrainMode",(SDWORD)radarDrawMode); ini.setValue("radarTerrainMode",(SDWORD)radarDrawMode);
ini.setValue("trapCursor", war_GetTrapCursor()); ini.setValue("trapCursor", war_GetTrapCursor());
ini.setValue("vsync", war_GetVsync()); ini.setValue("vsync", war_GetVsync());
ini.setValue("shaders", war_GetShaders());
ini.setValue("textureSize", getTextureSize()); ini.setValue("textureSize", getTextureSize());
ini.setValue("FSAA", war_getFSAA()); ini.setValue("FSAA", war_getFSAA());
ini.setValue("UPnP", (SDWORD)NetPlay.isUPNP); ini.setValue("UPnP", (SDWORD)NetPlay.isUPNP);
@ -208,6 +212,7 @@ bool saveConfig()
ini.setValue("gameName", game.name); // last hosted game ini.setValue("gameName", game.name); // last hosted game
} }
ini.setValue("mapName", game.map); // map name ini.setValue("mapName", game.map); // map name
ini.setValue("mapHash", game.hash.toString().c_str()); // map hash
ini.setValue("maxPlayers", game.maxPlayers); // maxPlayers ini.setValue("maxPlayers", game.maxPlayers); // maxPlayers
ini.setValue("power", game.power); // power ini.setValue("power", game.power); // power
ini.setValue("base", game.base); // size of base ini.setValue("base", game.base); // size of base
@ -264,6 +269,7 @@ bool reloadMPConfig(void)
} }
} }
ini.setValue("mapName", game.map); // map name ini.setValue("mapName", game.map); // map name
ini.setValue("mapHash", game.hash.toString().c_str()); // map hash
ini.setValue("maxPlayers", game.maxPlayers); // maxPlayers ini.setValue("maxPlayers", game.maxPlayers); // maxPlayers
ini.setValue("power", game.power); // power ini.setValue("power", game.power); // power
ini.setValue("base", game.base); // size of base ini.setValue("base", game.base); // size of base
@ -281,6 +287,7 @@ bool reloadMPConfig(void)
if (ini.contains("mapName") && ini.contains("maxPlayers")) if (ini.contains("mapName") && ini.contains("maxPlayers"))
{ {
sstrcpy(game.map, ini.value("mapName").toString().toUtf8().constData()); sstrcpy(game.map, ini.value("mapName").toString().toUtf8().constData());
game.hash.fromString(ini.value("mapHash").toString().toUtf8().constData());
game.maxPlayers = ini.value("maxPlayers").toInt(); // FIXME: horrible kluge, MUST match map above game.maxPlayers = ini.value("maxPlayers").toInt(); // FIXME: horrible kluge, MUST match map above
} }
game.power = ini.value("power", LEV_MED).toInt(); game.power = ini.value("power", LEV_MED).toInt();

View File

@ -109,6 +109,8 @@ static void dealWithRMB( void );
static bool mouseInBox(SDWORD x0, SDWORD y0, SDWORD x1, SDWORD y1); static bool mouseInBox(SDWORD x0, SDWORD y0, SDWORD x1, SDWORD y1);
static OBJECT_POSITION *checkMouseLoc(void); static OBJECT_POSITION *checkMouseLoc(void);
void finishDeliveryPosition(void);
static bool bInstantRadarJump = false; static bool bInstantRadarJump = false;
static SDWORD desiredPitch = 340; static SDWORD desiredPitch = 340;
static UDWORD currentFrame; static UDWORD currentFrame;
@ -290,14 +292,6 @@ static void shakeUpdate(void)
} }
} }
/* Initialise the display system */
bool dispInitialise(void)
{
return true;
}
void ProcessRadarInput() void ProcessRadarInput()
{ {
int PosX, PosY; int PosX, PosY;
@ -586,7 +580,13 @@ static bool CheckFinishedFindPosition(void)
/* Do not let the player position buildings 'under' the radar */ /* Do not let the player position buildings 'under' the radar */
if(mouseReleased(MOUSE_LMB) && !OverRadar) if(mouseReleased(MOUSE_LMB) && !OverRadar)
{ {
if (buildState == BUILD3D_VALID)
if (deliveryReposValid())
{
finishDeliveryPosition();
return true;
}
else if (buildState == BUILD3D_VALID)
{ {
if ((((STRUCTURE_STATS *)sBuildDetails.psStats)->type == REF_WALL if ((((STRUCTURE_STATS *)sBuildDetails.psStats)->type == REF_WALL
|| ((STRUCTURE_STATS *)sBuildDetails.psStats)->type == REF_GATE || ((STRUCTURE_STATS *)sBuildDetails.psStats)->type == REF_GATE
@ -761,6 +761,10 @@ void processMouseClickInput(void)
kill3DBuilding(); kill3DBuilding();
bRadarDragging = false; bRadarDragging = false;
} }
if (mouseReleased(MOUSE_RMB))
{
cancelDeliveryRepos();
}
if (mouseDrag(MOUSE_ROTATE,(UDWORD *)&rotX,(UDWORD *)&rotY) && !rotActive && !bRadarDragging) if (mouseDrag(MOUSE_ROTATE,(UDWORD *)&rotX,(UDWORD *)&rotY) && !rotActive && !bRadarDragging)
{ {
rotInitial = player.r.y; rotInitial = player.r.y;
@ -1378,12 +1382,6 @@ UDWORD dispX,dispY,dispR;
return(psReturn); return(psReturn);
} }
// Dummy structure stats used for positioning delivery points.
static STRUCTURE_STATS ReposStats;
static bool ReposValid = false;
static bool BVReposValid = false;
static FLAG_POSITION *ReposFlag;
FLAG_POSITION *deliveryPointToMove = NULL;
void StartTacticalScrollObj(WZ_DECL_UNUSED bool driveActive, WZ_DECL_UNUSED BASE_OBJECT* psObj) void StartTacticalScrollObj(WZ_DECL_UNUSED bool driveActive, WZ_DECL_UNUSED BASE_OBJECT* psObj)
{ {
@ -1393,24 +1391,23 @@ void CancelTacticalScroll(void)
{ {
} }
void displayInitVars(void)
{
ReposValid = false;
BVReposValid = false;
}
// Start repositioning a delivery point. // Start repositioning a delivery point.
// //
void StartDeliveryPosition( OBJECT_POSITION *psLocation ) static FLAG_POSITION flagPos;
static int flagStructId;
static bool flagReposVarsValid;
static bool flagReposFinished;
void startDeliveryPosition(FLAG_POSITION *psFlag)
{ {
FLAG_POSITION *psFlagPos; FLAG_POSITION *psFlagPos;
STRUCTURE_STATS *tmpStructStats;
BASE_STATS *tmpBaseStats;
//clear the Deliv Point if one if (tryingToGetLocation()) // if we're placing a building don't place
{
return;
}
//clear the selected delivery point
for (psFlagPos = apsFlagPosLists[selectedPlayer]; psFlagPos; for (psFlagPos = apsFlagPosLists[selectedPlayer]; psFlagPos;
psFlagPos = psFlagPos->psNext) psFlagPos = psFlagPos->psNext)
{ {
@ -1418,84 +1415,119 @@ void StartDeliveryPosition( OBJECT_POSITION *psLocation )
} }
//set this object position to be highlighted //set this object position to be highlighted
psLocation->selected = true; psFlag->selected = true;
deliveryPointToMove = (FLAG_POSITION*)psLocation; flagPos = *psFlag;
if(bInTutorial) STRUCTURE* psStruct = findDeliveryFactory(psFlag);
if (!psStruct)
{
flagStructId = 0; // not a struct, just a flag.
}
else
{
flagStructId = psStruct->id;
}
flagReposVarsValid = true;
flagReposFinished = false;
if (bInTutorial)
{ {
eventFireCallbackTrigger((TRIGGER_TYPE)CALL_DELIVPOINTMOVED); eventFireCallbackTrigger((TRIGGER_TYPE)CALL_DELIVPOINTMOVED);
} }
// Setup dummy structure stats for positioning a delivery point.
ReposValid = false;
ReposFlag = NULL;
ReposStats.baseWidth = 1;
ReposStats.baseBreadth = 1;
ReposStats.ref = 0;//REF_STRUCTURE_START;
//set up the buildSite variable for drawing
buildSite.xTL = (UWORD)psLocation->screenX;
buildSite.yTL = (UWORD)psLocation->screenY;
buildSite.xBR = (UWORD)(buildSite.xTL-1);
buildSite.yBR = (UWORD)(buildSite.yTL-1);
tmpStructStats = &ReposStats;
tmpBaseStats = (BASE_STATS *)tmpStructStats;
init3DBuilding(tmpBaseStats, FinishDeliveryPosition, psLocation);
} }
// Finished repositioning a delivery point. // Finished repositioning a delivery point.
// //
void FinishDeliveryPosition(UDWORD xPos,UDWORD yPos,void *UserData) void finishDeliveryPosition()
{ {
//This deals with adding waypoints and moving the primary FLAG_POSITION* psFlagPos;
processDeliveryPoint(((FLAG_POSITION*)UserData)->player, if (flagStructId)
world_coord(xPos), world_coord(yPos)); {
flagReposVarsValid = false;
//deselect it STRUCTURE* psStruct = IdToStruct(flagStructId, selectedPlayer);
((FLAG_POSITION*)UserData)->selected = false; if (StructIsFactory(psStruct) && psStruct->pFunctionality
deliveryPointToMove = NULL; && psStruct->pFunctionality->factory.psAssemblyPoint)
{
CancelDeliveryRepos(); setAssemblyPoint(psStruct->pFunctionality->factory.psAssemblyPoint,
flagPos.coords.x, flagPos.coords.y, selectedPlayer, true);
}
//deselect once moved
for (psFlagPos = apsFlagPosLists[selectedPlayer]; psFlagPos;
psFlagPos = psFlagPos->psNext)
{
psFlagPos->selected = false;
}
}
flagReposFinished = true;
} }
// Is there a valid delivery point repositioning going on. // Is there a valid delivery point repositioning going on.
//
bool DeliveryReposValid(void) bool deliveryReposValid(void)
{ {
if(driveModeActive()) { if (!flagReposVarsValid)
return ReposValid && (ReposFlag !=NULL); return false;
} else {
return BVReposValid; Vector2i map = map_coord(removeZ(flagPos.coords));
//make sure we are not too near map edge
if (map.x < scrollMinX + TOO_NEAR_EDGE || map.x + 1 > scrollMaxX - TOO_NEAR_EDGE ||
map.y < scrollMinY + TOO_NEAR_EDGE || map.y + 1 > scrollMaxY - TOO_NEAR_EDGE)
{
return false;
} }
// cant place on top of a delivery point...
for (FLAG_POSITION const *psCurrFlag = apsFlagPosLists[selectedPlayer]; psCurrFlag; psCurrFlag = psCurrFlag->psNext)
{
Vector2i flagTile = map_coord(removeZ(psCurrFlag->coords));
if (flagTile == map)
return false;
}
if (fpathBlockingTile(map.x, map.y, PROPULSION_TYPE_WHEELED))
{
return false;
}
return true;
} }
bool deliveryReposFinished(FLAG_POSITION *psFlag)
{
if (!flagReposVarsValid)
return false;
if (psFlag)
*psFlag = flagPos;
return flagReposFinished;
}
void processDeliveryRepos(void)
{
if (!flagReposVarsValid)
return;
int bX = clip(mouseTileX, 2, mapWidth - 3);
int bY = clip(mouseTileY, 2, mapHeight - 3);
flagPos.coords = Vector3i(world_coord(Vector2i(bX, bY))+Vector2i(TILE_UNITS/2,TILE_UNITS/2), map_TileHeight(bX, bY) + 2*ASSEMBLY_POINT_Z_PADDING);
}
// Cancel repositioning of the delivery point without moving it. // Cancel repositioning of the delivery point without moving it.
// //
void CancelDeliveryRepos(void) void cancelDeliveryRepos(void)
{ {
if((ReposValid) && (ReposFlag!=NULL)) flagReposVarsValid = false;
{
if(driveModeActive())
{
DROID *Driven = driveGetDriven();
if(Driven != NULL) {
// Driven->selected = true;
SelectDroid(Driven);
camAllignWithTarget((BASE_OBJECT *)Driven);
}
driveEnableControl();
}
ReposValid = false;
ReposFlag = NULL;
}
BVReposValid = false;
} }
void renderDeliveryRepos(void)
{
if (flagReposVarsValid)
renderDeliveryPoint(&flagPos, true);
}
// check whether a clicked on droid is in a command group or assigned to a sensor // check whether a clicked on droid is in a command group or assigned to a sensor
static bool droidHasLeader(DROID *psDroid) static bool droidHasLeader(DROID *psDroid)
@ -2111,7 +2143,7 @@ void dealWithLMB( void )
} }
else else
{ {
StartDeliveryPosition(psLocation); startDeliveryPosition((FLAG_POSITION *)psLocation);
} }
#if 0 #if 0
/* We've clicked on one of our own DP */ /* We've clicked on one of our own DP */
@ -2472,7 +2504,7 @@ static void dealWithRMB( void )
{ {
if (bRightClickOrders) if (bRightClickOrders)
{ {
StartDeliveryPosition(psLocation); startDeliveryPosition((FLAG_POSITION *)psLocation);
} }
else else
{ {
@ -3001,8 +3033,6 @@ bool cyborgDroidSelected(UDWORD player)
} }
/* Clear the selection flag for a player */ /* Clear the selection flag for a player */
void clearSel(void) void clearSel(void)
{ {
@ -3034,7 +3064,6 @@ void clearSel(void)
{ {
psFlagPos->selected = false; psFlagPos->selected = false;
} }
deliveryPointToMove = NULL;
setSelectedGroup(UBYTE_MAX); setSelectedGroup(UBYTE_MAX);
setSelectedCommander(UBYTE_MAX); setSelectedCommander(UBYTE_MAX);
@ -3055,3 +3084,11 @@ void setSensorAssigned(void)
{ {
bSensorAssigned = true; bSensorAssigned = true;
} }
/* Initialise the display system */
bool dispInitialise(void)
{
flagReposVarsValid = false;
return true;
}

View File

@ -183,11 +183,12 @@ BASE_OBJECT *mouseTarget( void );
bool StartObjectOrbit(BASE_OBJECT *psObj); bool StartObjectOrbit(BASE_OBJECT *psObj);
void CancelObjectOrbit(void); void CancelObjectOrbit(void);
extern void FinishDeliveryPosition(UDWORD xPos,UDWORD yPos,void *UserData); extern void cancelDeliveryRepos(void);
extern void CancelDeliveryRepos(void); extern void startDeliveryPosition(FLAG_POSITION *psFlag);
extern void StartDeliveryPosition( OBJECT_POSITION *psLocation ); extern bool deliveryReposValid(void);
extern bool DeliveryReposValid(void); extern void processDeliveryRepos(void);
extern FLAG_POSITION *deliveryPointToMove; extern void renderDeliveryRepos(void);
extern bool deliveryReposFinished(FLAG_POSITION *psFlag = NULL);
extern void StartTacticalScrollObj(bool driveActive,BASE_OBJECT *psObj); extern void StartTacticalScrollObj(bool driveActive,BASE_OBJECT *psObj);
extern void CancelTacticalScroll(void); extern void CancelTacticalScroll(void);
@ -218,8 +219,6 @@ extern void setSensorAssigned(void);
extern void setShakeStatus( bool val ); extern void setShakeStatus( bool val );
extern bool getShakeStatus( void ); extern bool getShakeStatus( void );
extern void displayInitVars(void);
void AddDerrickBurningMessage(void); void AddDerrickBurningMessage(void);
// check whether the queue order keys are pressed // check whether the queue order keys are pressed

View File

@ -1706,19 +1706,6 @@ void displayBlueprints(void)
blueprints.push_back(blueprint); blueprints.push_back(blueprint);
} }
} }
else
{
ASSERT(deliveryPointToMove != NULL, "Expected a delivery point.");
if (deliveryPointToMove)
{
// it's a droid (from the debug menu) or a delivery point
FLAG_POSITION pos = *deliveryPointToMove;
pos.coords.x = world_coord(sBuildDetails.x)+world_coord(1)/2;
pos.coords.y = world_coord(sBuildDetails.y)+world_coord(1)/2;
pos.coords.z = map_Height(pos.coords.x, pos.coords.y) + world_coord(1)/8;
renderDeliveryPoint(&pos, true);
}
}
} }
// now we draw the blueprints for all ordered buildings // now we draw the blueprints for all ordered buildings
@ -1752,6 +1739,8 @@ void displayBlueprints(void)
{ {
blueprint->renderBlueprint(); blueprint->renderBlueprint();
} }
renderDeliveryRepos();
} }
/// Draw Factory Delivery Points /// Draw Factory Delivery Points
@ -2596,7 +2585,7 @@ void renderDeliveryPoint(FLAG_POSITION *psPosition, bool blueprint)
if (blueprint) if (blueprint)
{ {
colour = (buildState == BUILD3D_VALID) ? WZCOL_BLUEPRINT_VALID : WZCOL_BLUEPRINT_INVALID; colour = deliveryReposValid() ? WZCOL_BLUEPRINT_VALID : WZCOL_BLUEPRINT_INVALID;
} }
else else
{ {
@ -2842,7 +2831,7 @@ static void drawWeaponReloadBar(BASE_OBJECT *psObj, WEAPON *psWeap, int weapon_s
if (psObj->type == OBJ_DROID && isVtolDroid((DROID *)psObj)) if (psObj->type == OBJ_DROID && isVtolDroid((DROID *)psObj))
{ {
//deal with VTOLs //deal with VTOLs
firingStage = getNumAttackRuns((DROID *)psObj, weapon_slot) - ((DROID *)psObj)->sMove.iAttackRuns[weapon_slot]; firingStage = getNumAttackRuns((DROID *)psObj, weapon_slot) - ((DROID *)psObj)->asWeaps[weapon_slot].usedAmmo;
//compare with max value //compare with max value
interval = getNumAttackRuns((DROID *)psObj, weapon_slot); interval = getNumAttackRuns((DROID *)psObj, weapon_slot);

View File

@ -1895,6 +1895,7 @@ DROID *reallyBuildDroid(DROID_TEMPLATE *pTemplate, Position pos, UDWORD player,
// Initialise the movement stuff // Initialise the movement stuff
psDroid->baseSpeed = calcDroidBaseSpeed(pTemplate, psDroid->weight, (UBYTE)player); psDroid->baseSpeed = calcDroidBaseSpeed(pTemplate, psDroid->weight, (UBYTE)player);
psDroid->sMove.asPath = NULL;
initDroidMovement(psDroid); initDroidMovement(psDroid);
// it was never drawn before // it was never drawn before
@ -1985,6 +1986,7 @@ DROID *buildDroid(DROID_TEMPLATE *pTemplate, UDWORD x, UDWORD y, UDWORD player,
//initialises the droid movement model //initialises the droid movement model
void initDroidMovement(DROID *psDroid) void initDroidMovement(DROID *psDroid)
{ {
free(psDroid->sMove.asPath);
memset(&psDroid->sMove, 0, sizeof(MOVE_CONTROL)); memset(&psDroid->sMove, 0, sizeof(MOVE_CONTROL));
} }
@ -2018,6 +2020,7 @@ void droidSetBits(DROID_TEMPLATE *pTemplate,DROID *psDroid)
psDroid->asWeaps[inc].nStat = pTemplate->asWeaps[inc]; psDroid->asWeaps[inc].nStat = pTemplate->asWeaps[inc];
psDroid->asWeaps[inc].ammo = (asWeaponStats + psDroid->asWeaps[inc].nStat)->numRounds; psDroid->asWeaps[inc].ammo = (asWeaponStats + psDroid->asWeaps[inc].nStat)->numRounds;
} }
psDroid->asWeaps[inc].usedAmmo = 0;
} }
//allocate the components hit points //allocate the components hit points
psDroid->asBits[COMP_BODY].nStat = (UBYTE)pTemplate->asParts[COMP_BODY]; psDroid->asBits[COMP_BODY].nStat = (UBYTE)pTemplate->asParts[COMP_BODY];
@ -2960,7 +2963,7 @@ bool vtolEmpty(DROID *psDroid)
for (i = 0; i < psDroid->numWeaps; i++) for (i = 0; i < psDroid->numWeaps; i++)
{ {
if (asWeaponStats[psDroid->asWeaps[i].nStat].vtolAttackRuns > 0 && if (asWeaponStats[psDroid->asWeaps[i].nStat].vtolAttackRuns > 0 &&
psDroid->sMove.iAttackRuns[i] < getNumAttackRuns(psDroid, i)) psDroid->asWeaps[i].usedAmmo < getNumAttackRuns(psDroid, i))
{ {
return false; return false;
} }
@ -2988,7 +2991,7 @@ bool vtolFull(DROID *psDroid)
for (i = 0; i < psDroid->numWeaps; i++) for (i = 0; i < psDroid->numWeaps; i++)
{ {
if (asWeaponStats[psDroid->asWeaps[i].nStat].vtolAttackRuns > 0 && if (asWeaponStats[psDroid->asWeaps[i].nStat].vtolAttackRuns > 0 &&
psDroid->sMove.iAttackRuns[i] > 0) psDroid->asWeaps[i].usedAmmo > 0)
{ {
return false; return false;
} }
@ -3174,7 +3177,7 @@ bool vtolHappy(const DROID* psDroid)
for (i = 0; i < psDroid->numWeaps; ++i) for (i = 0; i < psDroid->numWeaps; ++i)
{ {
if (asWeaponStats[psDroid->asWeaps[i].nStat].vtolAttackRuns > 0 if (asWeaponStats[psDroid->asWeaps[i].nStat].vtolAttackRuns > 0
&& psDroid->sMove.iAttackRuns[i] != 0) && psDroid->asWeaps[i].usedAmmo != 0)
{ {
return false; return false;
} }
@ -3192,42 +3195,18 @@ void updateVtolAttackRun(DROID *psDroid , int weapon_slot)
{ {
if (asWeaponStats[psDroid->asWeaps[weapon_slot].nStat].vtolAttackRuns > 0) if (asWeaponStats[psDroid->asWeaps[weapon_slot].nStat].vtolAttackRuns > 0)
{ {
psDroid->sMove.iAttackRuns[weapon_slot]++; ++psDroid->asWeaps[weapon_slot].usedAmmo;
if (psDroid->sMove.iAttackRuns[weapon_slot] == getNumAttackRuns(psDroid, weapon_slot)) if (psDroid->asWeaps[weapon_slot].usedAmmo == getNumAttackRuns(psDroid, weapon_slot))
{ {
psDroid->asWeaps[weapon_slot].ammo = 0; psDroid->asWeaps[weapon_slot].ammo = 0;
} }
//quick check doesn't go over limit //quick check doesn't go over limit
ASSERT( psDroid->sMove.iAttackRuns[weapon_slot] < UWORD_MAX, "too many attack runs"); ASSERT(psDroid->asWeaps[weapon_slot].usedAmmo < UWORD_MAX, "too many attack runs");
} }
} }
} }
} }
/*this mends the VTOL when it has been returned to home base whilst on an
offworld mission*/
void mendVtol(DROID *psDroid)
{
UBYTE i;
ASSERT_OR_RETURN( , vtolEmpty(psDroid), "droid is not an empty weapon VTOL!");
CHECK_DROID(psDroid);
/* set rearm value to no runs made */
for (i = 0;i < psDroid->numWeaps;i++)
{
psDroid->sMove.iAttackRuns[i] = 0;
//reset ammo and lastTimeFired
psDroid->asWeaps[i].ammo = asWeaponStats[psDroid->
asWeaps[i].nStat].numRounds;
psDroid->asWeaps[i].lastFired = 0;
}
/* set droid points to max */
psDroid->body = psDroid->originalBody;
CHECK_DROID(psDroid);
}
//assign rearmPad to the VTOL //assign rearmPad to the VTOL
void assignVTOLPad(DROID *psNewDroid, STRUCTURE *psReArmPad) void assignVTOLPad(DROID *psNewDroid, STRUCTURE *psReArmPad)
{ {

View File

@ -286,9 +286,6 @@ extern bool vtolFull(DROID *psDroid);
/*Checks a vtol for being fully armed and fully repaired to see if ready to /*Checks a vtol for being fully armed and fully repaired to see if ready to
leave reArm pad */ leave reArm pad */
extern bool vtolHappy(const DROID* psDroid); extern bool vtolHappy(const DROID* psDroid);
/*this mends the VTOL when it has been returned to home base whilst on an
offworld mission*/
extern void mendVtol(DROID *psDroid);
/*checks if the droid is a VTOL droid and updates the attack runs as required*/ /*checks if the droid is a VTOL droid and updates the attack runs as required*/
extern void updateVtolAttackRun(DROID *psDroid, int weapon_slot); extern void updateVtolAttackRun(DROID *psDroid, int weapon_slot);
/*returns a count of the base number of attack runs for the weapon attached to the droid*/ /*returns a count of the base number of attack runs for the weapon attached to the droid*/

View File

@ -153,7 +153,6 @@ void init3DBuilding(BASE_STATS *psStats,BUILDCALLBACK CallBack,void *UserData)
void kill3DBuilding ( void ) void kill3DBuilding ( void )
{ {
CancelDeliveryRepos();
//cancel the drag boxes //cancel the drag boxes
dragBox3D.status = DRAG_INACTIVE; dragBox3D.status = DRAG_INACTIVE;
wallDrag.status = DRAG_INACTIVE; wallDrag.status = DRAG_INACTIVE;
@ -239,7 +238,7 @@ bool found3DBuilding(UDWORD *x, UDWORD *y)
if (ctrlShiftDown()) if (ctrlShiftDown())
{ {
quickQueueMode = true; quickQueueMode = true;
init3DBuilding(sBuildDetails.psStats, NULL, NULL); init3DBuilding(sBuildDetails.psStats, sBuildDetails.CallBack, sBuildDetails.UserData);
} }
else else
{ {
@ -276,7 +275,7 @@ bool found3DBuildLocTwo(UDWORD *px1, UDWORD *py1, UDWORD *px2, UDWORD *py2)
if (ctrlShiftDown()) if (ctrlShiftDown())
{ {
quickQueueMode = true; quickQueueMode = true;
init3DBuilding(sBuildDetails.psStats, NULL, NULL); init3DBuilding(sBuildDetails.psStats, sBuildDetails.CallBack, sBuildDetails.UserData);
} }
return true; return true;

View File

@ -33,6 +33,7 @@
#include "lib/framework/input.h" #include "lib/framework/input.h"
#include "lib/ivis_opengl/bitimage.h" #include "lib/ivis_opengl/bitimage.h"
#include "lib/ivis_opengl/pieblitfunc.h" #include "lib/ivis_opengl/pieblitfunc.h"
#include "lib/ivis_opengl/piestate.h"
#include "lib/sound/mixer.h" #include "lib/sound/mixer.h"
#include "lib/widget/button.h" #include "lib/widget/button.h"
#include "lib/widget/label.h" #include "lib/widget/label.h"
@ -883,6 +884,18 @@ static bool startVideoOptionsMenu(void)
break; break;
} }
// Shaders
addTextButton(FRONTEND_SHADERS, FRONTEND_POS6X-35, FRONTEND_POS7Y, _("Shaders"), 0);
if (war_GetShaders() == SHADERS_ON)
{
addTextButton(FRONTEND_SHADERS_R, FRONTEND_POS6M-55, FRONTEND_POS7Y, _("On"), 0);
}
else
{
addTextButton(FRONTEND_SHADERS_R, FRONTEND_POS6M-55, FRONTEND_POS7Y, _("Off"), 0);
}
// Add some text down the side of the form // Add some text down the side of the form
addSideText(FRONTEND_SIDETEXT, FRONTEND_SIDEX, FRONTEND_SIDEY, _("VIDEO OPTIONS")); addSideText(FRONTEND_SIDETEXT, FRONTEND_SIDEX, FRONTEND_SIDEY, _("VIDEO OPTIONS"));
@ -1043,6 +1056,26 @@ bool runVideoOptionsMenu(void)
break; break;
} }
case FRONTEND_SHADERS:
case FRONTEND_SHADERS_R:
{
switch (war_GetShaders())
{
case SHADERS_ON:
war_SetShaders(SHADERS_OFF);
widgSetString(psWScreen, FRONTEND_SHADERS_R, _("Off"));
break;
case SHADERS_OFF:
war_SetShaders(SHADERS_ON);
widgSetString(psWScreen, FRONTEND_SHADERS_R, _("On"));
break;
case FALLBACK:
break;
}
pie_SetShaderUsage(war_GetShaders()==SHADERS_ON);
break;
}
case FRONTEND_QUIT: case FRONTEND_QUIT:
changeTitleMode(OPTIONS); changeTitleMode(OPTIONS);
break; break;

View File

@ -234,6 +234,8 @@ enum
FRONTEND_VSYNC_R, FRONTEND_VSYNC_R,
FRONTEND_FSAA, FRONTEND_FSAA,
FRONTEND_FSAA_R, FRONTEND_FSAA_R,
FRONTEND_SHADERS,
FRONTEND_SHADERS_R,
FRONTEND_MOUSEOPTIONS = 25000, // Mouse Options Menu FRONTEND_MOUSEOPTIONS = 25000, // Mouse Options Menu
FRONTEND_TRAP, FRONTEND_TRAP,

View File

@ -46,7 +46,7 @@ typedef bool (*LoadFunction)(const char *pData);
/*Returns the Function type based on the string - used for reading in data */ /*Returns the Function type based on the string - used for reading in data */
static UDWORD functionType(const char* pType) static UDWORD functionType(const char *pType)
{ {
if (!strcmp(pType, "Production")) if (!strcmp(pType, "Production"))
{ {
@ -129,42 +129,29 @@ static UDWORD functionType(const char* pType)
return REARM_UPGRADE_TYPE; return REARM_UPGRADE_TYPE;
} }
ASSERT( false, "Unknown Function Type: %s", pType ); ASSERT(false, "Unknown Function Type: %s", pType);
return 0; return 0;
} }
// Allocate storage for the name // Allocate storage for the name
static bool storeName(FUNCTION* pFunction, const char* pNameToStore) static bool storeName(FUNCTION *pFunction, const char *pNameToStore)
{ {
pFunction->pName = strdup(pNameToStore); pFunction->pName = strdup(pNameToStore);
if (pFunction->pName == NULL)
{
debug( LOG_FATAL, "Function Name - Out of memory" );
abort();
return false;
}
return true; return true;
} }
static bool loadProduction(const char *pData) static bool loadProduction(const char *pData)
{ {
PRODUCTION_FUNCTION* psFunction; PRODUCTION_FUNCTION *psFunction;
char functionName[MAX_STR_LENGTH], bodySize[MAX_STR_LENGTH]; char functionName[MAX_STR_LENGTH], bodySize[MAX_STR_LENGTH];
UDWORD productionOutput; UDWORD productionOutput;
psFunction = (PRODUCTION_FUNCTION *)malloc(sizeof(PRODUCTION_FUNCTION)); psFunction = (PRODUCTION_FUNCTION *)malloc(sizeof(PRODUCTION_FUNCTION));
if (psFunction == NULL)
{
debug( LOG_FATAL, "Production Function - Out of memory" );
abort();
return false;
}
memset(psFunction, 0, sizeof(PRODUCTION_FUNCTION)); memset(psFunction, 0, sizeof(PRODUCTION_FUNCTION));
//store the pointer in the Function Array //store the pointer in the Function Array
*asFunctions = (FUNCTION*)psFunction; *asFunctions = (FUNCTION *)psFunction;
psFunction->ref = REF_FUNCTION_START + numFunctions; psFunction->ref = REF_FUNCTION_START + numFunctions;
numFunctions++; numFunctions++;
asFunctions++; asFunctions++;
@ -176,14 +163,14 @@ static bool loadProduction(const char *pData)
functionName[0] = '\0'; functionName[0] = '\0';
bodySize[0] = '\0'; bodySize[0] = '\0';
sscanf(pData, "%255[^,'\r\n],%255[^,'\r\n],%d", functionName, bodySize, sscanf(pData, "%255[^,'\r\n],%255[^,'\r\n],%d", functionName, bodySize,
&productionOutput); &productionOutput);
//allocate storage for the name //allocate storage for the name
storeName((FUNCTION *)psFunction, functionName); storeName((FUNCTION *)psFunction, functionName);
if (!getBodySize(bodySize, &psFunction->capacity)) if (!getBodySize(bodySize, &psFunction->capacity))
{ {
ASSERT( false, "loadProduction: unknown body size for %s",psFunction->pName ); ASSERT(false, "loadProduction: unknown body size for %s", psFunction->pName);
return false; return false;
} }
@ -194,7 +181,7 @@ static bool loadProduction(const char *pData)
} }
else else
{ {
ASSERT( false, "loadProduction: production Output too big for %s",psFunction->pName ); ASSERT(false, "loadProduction: production Output too big for %s", psFunction->pName);
psFunction->productionOutput = 0; psFunction->productionOutput = 0;
} }
@ -204,20 +191,14 @@ static bool loadProduction(const char *pData)
static bool loadProductionUpgradeFunction(const char *pData) static bool loadProductionUpgradeFunction(const char *pData)
{ {
PRODUCTION_UPGRADE_FUNCTION* psFunction; PRODUCTION_UPGRADE_FUNCTION *psFunction;
char functionName[MAX_STR_LENGTH]; char functionName[MAX_STR_LENGTH];
UDWORD factory, cyborg, vtol; UDWORD factory, cyborg, vtol;
UDWORD outputModifier; UDWORD outputModifier;
//allocate storage //allocate storage
psFunction = (PRODUCTION_UPGRADE_FUNCTION *)malloc(sizeof psFunction = (PRODUCTION_UPGRADE_FUNCTION *)malloc(sizeof
(PRODUCTION_UPGRADE_FUNCTION)); (PRODUCTION_UPGRADE_FUNCTION));
if (psFunction == NULL)
{
debug( LOG_FATAL, "Production Upgrade Function - Out of memory" );
abort();
return false;
}
memset(psFunction, 0, sizeof(PRODUCTION_UPGRADE_FUNCTION)); memset(psFunction, 0, sizeof(PRODUCTION_UPGRADE_FUNCTION));
//store the pointer in the Function Array //store the pointer in the Function Array
@ -232,10 +213,9 @@ static bool loadProductionUpgradeFunction(const char *pData)
//read the data in //read the data in
functionName[0] = '\0'; functionName[0] = '\0';
sscanf(pData, "%255[^,'\r\n],%d,%d,%d,%d", functionName, &factory, sscanf(pData, "%255[^,'\r\n],%d,%d,%d,%d", functionName, &factory,
&cyborg, &vtol,&outputModifier); &cyborg, &vtol, &outputModifier);
psFunction->outputModifier = (UBYTE)outputModifier;
psFunction->outputModifier=(UBYTE)outputModifier;
//allocate storage for the name //allocate storage for the name
storeName((FUNCTION *)psFunction, functionName); storeName((FUNCTION *)psFunction, functionName);
@ -264,25 +244,16 @@ static bool loadProductionUpgradeFunction(const char *pData)
{ {
psFunction->vtolFactory = false; psFunction->vtolFactory = false;
} }
//increment the number of upgrades
//numProductionUpgrades++;
return true; return true;
} }
static bool loadResearchFunction(const char *pData) static bool loadResearchFunction(const char *pData)
{ {
RESEARCH_FUNCTION* psFunction; RESEARCH_FUNCTION *psFunction;
char functionName[MAX_STR_LENGTH]; char functionName[MAX_STR_LENGTH];
//allocate storage //allocate storage
psFunction = (RESEARCH_FUNCTION *)malloc(sizeof(RESEARCH_FUNCTION)); psFunction = (RESEARCH_FUNCTION *)malloc(sizeof(RESEARCH_FUNCTION));
if (psFunction == NULL)
{
debug( LOG_FATAL, "Research Function - Out of memory" );
abort();
return false;
}
memset(psFunction, 0, sizeof(RESEARCH_FUNCTION)); memset(psFunction, 0, sizeof(RESEARCH_FUNCTION));
//store the pointer in the Function Array //store the pointer in the Function Array
@ -306,17 +277,11 @@ static bool loadResearchFunction(const char *pData)
static bool loadReArmFunction(const char *pData) static bool loadReArmFunction(const char *pData)
{ {
REARM_FUNCTION* psFunction; REARM_FUNCTION *psFunction;
char functionName[MAX_STR_LENGTH]; char functionName[MAX_STR_LENGTH];
//allocate storage //allocate storage
psFunction = (REARM_FUNCTION *)malloc(sizeof(REARM_FUNCTION)); psFunction = (REARM_FUNCTION *)malloc(sizeof(REARM_FUNCTION));
if (psFunction == NULL)
{
debug( LOG_FATAL, "ReArm Function - Out of memory" );
abort();
return false;
}
memset(psFunction, 0, sizeof(REARM_FUNCTION)); memset(psFunction, 0, sizeof(REARM_FUNCTION));
//store the pointer in the Function Array //store the pointer in the Function Array
@ -348,12 +313,6 @@ static bool loadUpgradeFunction(const char *pData, UBYTE type)
//allocate storage //allocate storage
psFunction = (UPGRADE_FUNCTION *)malloc(sizeof(UPGRADE_FUNCTION)); psFunction = (UPGRADE_FUNCTION *)malloc(sizeof(UPGRADE_FUNCTION));
if (psFunction == NULL)
{
debug( LOG_FATAL, "Upgrade Function - Out of memory" );
abort();
return false;
}
memset(psFunction, 0, sizeof(UPGRADE_FUNCTION)); memset(psFunction, 0, sizeof(UPGRADE_FUNCTION));
//store the pointer in the Function Array //store the pointer in the Function Array
@ -374,7 +333,7 @@ static bool loadUpgradeFunction(const char *pData, UBYTE type)
if (modifier > UWORD_MAX) if (modifier > UWORD_MAX)
{ {
ASSERT( false, "loadUpgradeFunction: modifier too great for %s", functionName ); ASSERT(false, "loadUpgradeFunction: modifier too great for %s", functionName);
return false; return false;
} }
@ -385,7 +344,6 @@ static bool loadUpgradeFunction(const char *pData, UBYTE type)
} }
static bool loadResearchUpgradeFunction(const char *pData) static bool loadResearchUpgradeFunction(const char *pData)
{ {
return loadUpgradeFunction(pData, RESEARCH_UPGRADE_TYPE); return loadUpgradeFunction(pData, RESEARCH_UPGRADE_TYPE);
@ -426,18 +384,10 @@ static bool loadDroidBodyUpgradeFunction(const char *pData)
{ {
DROIDBODY_UPGRADE_FUNCTION *psFunction; DROIDBODY_UPGRADE_FUNCTION *psFunction;
char functionName[MAX_STR_LENGTH]; char functionName[MAX_STR_LENGTH];
UDWORD modifier, armourKinetic, armourHeat, UDWORD modifier, armourKinetic, armourHeat, body, droid, cyborg;
body, droid, cyborg;
//allocate storage //allocate storage
psFunction = (DROIDBODY_UPGRADE_FUNCTION *)malloc( psFunction = (DROIDBODY_UPGRADE_FUNCTION *)malloc(sizeof(DROIDBODY_UPGRADE_FUNCTION));
sizeof(DROIDBODY_UPGRADE_FUNCTION));
if (psFunction == NULL)
{
debug( LOG_FATAL, "UnitBody Upgrade Function - Out of memory" );
abort();
return false;
}
memset(psFunction, 0, sizeof(DROIDBODY_UPGRADE_FUNCTION)); memset(psFunction, 0, sizeof(DROIDBODY_UPGRADE_FUNCTION));
//store the pointer in the Function Array //store the pointer in the Function Array
@ -452,16 +402,16 @@ static bool loadDroidBodyUpgradeFunction(const char *pData)
//read the data in //read the data in
functionName[0] = '\0'; functionName[0] = '\0';
sscanf(pData, "%255[^,'\r\n],%d,%d,%d,%d,%d,%d", functionName, &modifier, sscanf(pData, "%255[^,'\r\n],%d,%d,%d,%d,%d,%d", functionName, &modifier,
&body, &armourKinetic, &armourHeat, &droid, &cyborg); &body, &armourKinetic, &armourHeat, &droid, &cyborg);
//allocate storage for the name //allocate storage for the name
storeName((FUNCTION *)psFunction, functionName); storeName((FUNCTION *)psFunction, functionName);
if (modifier > UWORD_MAX || armourKinetic > UWORD_MAX || if (modifier > UWORD_MAX || armourKinetic > UWORD_MAX ||
armourHeat > UWORD_MAX || body > UWORD_MAX) armourHeat > UWORD_MAX || body > UWORD_MAX)
{ {
ASSERT( false, ASSERT(false,
"loadUnitBodyUpgradeFunction: one or more modifiers too great" ); "loadUnitBodyUpgradeFunction: one or more modifiers too great");
return false; return false;
} }
@ -497,14 +447,7 @@ static bool loadDroidSensorUpgradeFunction(const char *pData)
UDWORD modifier, range; UDWORD modifier, range;
//allocate storage //allocate storage
psFunction = (DROIDSENSOR_UPGRADE_FUNCTION *)malloc( psFunction = (DROIDSENSOR_UPGRADE_FUNCTION *)malloc(sizeof(DROIDSENSOR_UPGRADE_FUNCTION));
sizeof(DROIDSENSOR_UPGRADE_FUNCTION));
if (psFunction == NULL)
{
debug( LOG_FATAL, "UnitSensor Upgrade Function - Out of memory" );
abort();
return false;
}
memset(psFunction, 0, sizeof(DROIDSENSOR_UPGRADE_FUNCTION)); memset(psFunction, 0, sizeof(DROIDSENSOR_UPGRADE_FUNCTION));
//store the pointer in the Function Array //store the pointer in the Function Array
@ -525,8 +468,8 @@ static bool loadDroidSensorUpgradeFunction(const char *pData)
if (modifier > UWORD_MAX || range > UWORD_MAX) if (modifier > UWORD_MAX || range > UWORD_MAX)
{ {
ASSERT( false, ASSERT(false,
"loadUnitSensorUpgradeFunction: one or more modifiers too great" ); "loadUnitSensorUpgradeFunction: one or more modifiers too great");
return false; return false;
} }
@ -534,26 +477,19 @@ static bool loadDroidSensorUpgradeFunction(const char *pData)
psFunction->upgradePoints = (UWORD)modifier; psFunction->upgradePoints = (UWORD)modifier;
psFunction->range = (UWORD)range; psFunction->range = (UWORD)range;
return true; return true;
} }
static bool loadWeaponUpgradeFunction(const char *pData) static bool loadWeaponUpgradeFunction(const char *pData)
{ {
WEAPON_UPGRADE_FUNCTION* psFunction; WEAPON_UPGRADE_FUNCTION *psFunction;
char functionName[MAX_STR_LENGTH], char functionName[MAX_STR_LENGTH],
weaponSubClass[MAX_STR_LENGTH]; weaponSubClass[MAX_STR_LENGTH];
UDWORD firePause, shortHit, longHit, damage, UDWORD firePause, shortHit, longHit, damage,
radiusDamage, incenDamage, radiusHit; radiusDamage, incenDamage, radiusHit;
//allocate storage //allocate storage
psFunction = (WEAPON_UPGRADE_FUNCTION *)malloc(sizeof psFunction = (WEAPON_UPGRADE_FUNCTION *)malloc(sizeof(WEAPON_UPGRADE_FUNCTION));
(WEAPON_UPGRADE_FUNCTION));
if (psFunction == NULL)
{
debug( LOG_FATAL, "Weapon Upgrade Function - Out of memory" );
abort();
return false;
}
memset(psFunction, 0, sizeof(WEAPON_UPGRADE_FUNCTION)); memset(psFunction, 0, sizeof(WEAPON_UPGRADE_FUNCTION));
//store the pointer in the Function Array //store the pointer in the Function Array
@ -569,8 +505,8 @@ static bool loadWeaponUpgradeFunction(const char *pData)
functionName[0] = '\0'; functionName[0] = '\0';
weaponSubClass[0] = '\0'; weaponSubClass[0] = '\0';
sscanf(pData, "%255[^,'\r\n],%255[^,'\r\n],%d,%d,%d,%d,%d,%d,%d", functionName, sscanf(pData, "%255[^,'\r\n],%255[^,'\r\n],%d,%d,%d,%d,%d,%d,%d", functionName,
weaponSubClass, &firePause, &shortHit, &longHit, &damage, &radiusDamage, weaponSubClass, &firePause, &shortHit, &longHit, &damage, &radiusDamage,
&incenDamage, &radiusHit); &incenDamage, &radiusHit);
//allocate storage for the name //allocate storage for the name
storeName((FUNCTION *)psFunction, functionName); storeName((FUNCTION *)psFunction, functionName);
@ -582,14 +518,14 @@ static bool loadWeaponUpgradeFunction(const char *pData)
//check none of the %increases are over UBYTE max //check none of the %increases are over UBYTE max
if (firePause > UBYTE_MAX || if (firePause > UBYTE_MAX ||
shortHit > UWORD_MAX || shortHit > UWORD_MAX ||
longHit > UWORD_MAX || longHit > UWORD_MAX ||
damage > UWORD_MAX || damage > UWORD_MAX ||
radiusDamage > UWORD_MAX || radiusDamage > UWORD_MAX ||
incenDamage > UWORD_MAX || incenDamage > UWORD_MAX ||
radiusHit > UWORD_MAX) radiusHit > UWORD_MAX)
{ {
debug( LOG_ERROR, "A percentage increase for Weapon Upgrade function is too large" ); debug(LOG_ERROR, "A percentage increase for Weapon Upgrade function is too large");
return false; return false;
} }
@ -606,7 +542,7 @@ static bool loadWeaponUpgradeFunction(const char *pData)
//increment the number of upgrades //increment the number of upgrades
//numWeaponUpgrades++; //numWeaponUpgrades++;
return true; return true;
} }
static bool loadStructureUpgradeFunction(const char *pData) static bool loadStructureUpgradeFunction(const char *pData)
@ -617,13 +553,7 @@ static bool loadStructureUpgradeFunction(const char *pData)
//allocate storage //allocate storage
psFunction = (STRUCTURE_UPGRADE_FUNCTION *)malloc(sizeof psFunction = (STRUCTURE_UPGRADE_FUNCTION *)malloc(sizeof
(STRUCTURE_UPGRADE_FUNCTION)); (STRUCTURE_UPGRADE_FUNCTION));
if (psFunction == NULL)
{
debug( LOG_FATAL, "Structure Upgrade Function - Out of memory" );
abort();
return false;
}
memset(psFunction, 0, sizeof(STRUCTURE_UPGRADE_FUNCTION)); memset(psFunction, 0, sizeof(STRUCTURE_UPGRADE_FUNCTION));
//store the pointer in the Function Array //store the pointer in the Function Array
@ -644,10 +574,10 @@ static bool loadStructureUpgradeFunction(const char *pData)
//check none of the %increases are over UWORD max //check none of the %increases are over UWORD max
if (armour > UWORD_MAX || if (armour > UWORD_MAX ||
body > UWORD_MAX || body > UWORD_MAX ||
resistance > UWORD_MAX) resistance > UWORD_MAX)
{ {
debug( LOG_ERROR, "A percentage increase for Structure Upgrade function is too large" ); debug(LOG_ERROR, "A percentage increase for Structure Upgrade function is too large");
return false; return false;
} }
@ -668,13 +598,7 @@ static bool loadWallDefenceUpgradeFunction(const char *pData)
//allocate storage //allocate storage
psFunction = (WALLDEFENCE_UPGRADE_FUNCTION *)malloc(sizeof psFunction = (WALLDEFENCE_UPGRADE_FUNCTION *)malloc(sizeof
(WALLDEFENCE_UPGRADE_FUNCTION)); (WALLDEFENCE_UPGRADE_FUNCTION));
if (psFunction == NULL)
{
debug( LOG_FATAL, "WallDefence Upgrade Function - Out of memory" );
abort();
return false;
}
memset(psFunction, 0, sizeof(WALLDEFENCE_UPGRADE_FUNCTION)); memset(psFunction, 0, sizeof(WALLDEFENCE_UPGRADE_FUNCTION));
//store the pointer in the Function Array //store the pointer in the Function Array
@ -695,9 +619,9 @@ static bool loadWallDefenceUpgradeFunction(const char *pData)
//check none of the %increases are over UWORD max //check none of the %increases are over UWORD max
if (armour > UWORD_MAX || if (armour > UWORD_MAX ||
body > UWORD_MAX) body > UWORD_MAX)
{ {
debug( LOG_ERROR, "A percentage increase for WallDefence Upgrade function is too large" ); debug(LOG_ERROR, "A percentage increase for WallDefence Upgrade function is too large");
return false; return false;
} }
@ -712,18 +636,11 @@ static bool loadWallDefenceUpgradeFunction(const char *pData)
static bool loadPowerGenFunction(const char *pData) static bool loadPowerGenFunction(const char *pData)
{ {
POWER_GEN_FUNCTION* psFunction; POWER_GEN_FUNCTION *psFunction;
char functionName[MAX_STR_LENGTH]; char functionName[MAX_STR_LENGTH];
//allocate storage //allocate storage
psFunction = (POWER_GEN_FUNCTION *)malloc(sizeof psFunction = (POWER_GEN_FUNCTION *)malloc(sizeof(POWER_GEN_FUNCTION));
(POWER_GEN_FUNCTION));
if (psFunction == NULL)
{
debug( LOG_FATAL, "Power Gen Function - Out of memory" );
abort();
return false;
}
memset(psFunction, 0, sizeof(POWER_GEN_FUNCTION)); memset(psFunction, 0, sizeof(POWER_GEN_FUNCTION));
//store the pointer in the Function Array //store the pointer in the Function Array
@ -738,30 +655,30 @@ static bool loadPowerGenFunction(const char *pData)
//read the data in //read the data in
functionName[0] = '\0'; functionName[0] = '\0';
sscanf(pData, "%255[^,'\r\n],%d,%d,%d,%d,%d,%d", functionName, sscanf(pData, "%255[^,'\r\n],%d,%d,%d,%d,%d,%d", functionName,
&psFunction->powerOutput, &psFunction->powerMultiplier, &psFunction->powerOutput, &psFunction->powerMultiplier,
&psFunction->criticalMassChance, &psFunction->criticalMassRadius, &psFunction->criticalMassChance, &psFunction->criticalMassRadius,
&psFunction->criticalMassDamage, &psFunction->radiationDecayTime); &psFunction->criticalMassDamage, &psFunction->radiationDecayTime);
if(bMultiPlayer) if (bMultiPlayer)
{ {
switch(game.power) switch (game.power)
{ {
// Multiply by 3/4 // Multiply by 3/4
case LEV_LOW: case LEV_LOW:
psFunction->powerMultiplier *= 3; psFunction->powerMultiplier *= 3;
psFunction->powerMultiplier /= 4; psFunction->powerMultiplier /= 4;
break; break;
// No change // No change
case LEV_MED: case LEV_MED:
break; break;
// Multiply by 5/4 // Multiply by 5/4
case LEV_HI: case LEV_HI:
psFunction->powerMultiplier *= 5; psFunction->powerMultiplier *= 5;
psFunction->powerMultiplier /= 4; psFunction->powerMultiplier /= 4;
break; break;
default: default:
break; break;
} }
} }
@ -778,14 +695,7 @@ static bool loadResourceFunction(const char *pData)
char functionName[MAX_STR_LENGTH]; char functionName[MAX_STR_LENGTH];
//allocate storage //allocate storage
psFunction = (RESOURCE_FUNCTION *)malloc(sizeof psFunction = (RESOURCE_FUNCTION *)malloc(sizeof(RESOURCE_FUNCTION));
(RESOURCE_FUNCTION));
if (psFunction == NULL)
{
debug( LOG_FATAL, "Resource Function - Out of memory" );
abort();
return false;
}
memset(psFunction, 0, sizeof(RESOURCE_FUNCTION)); memset(psFunction, 0, sizeof(RESOURCE_FUNCTION));
//store the pointer in the Function Array //store the pointer in the Function Array
@ -795,7 +705,7 @@ static bool loadResourceFunction(const char *pData)
asFunctions++; asFunctions++;
//set the type of function //set the type of function
psFunction->type = RESOURCE_TYPE; psFunction->type = RESOURCE_TYPE;
//read the data in //read the data in
functionName[0] = '\0'; functionName[0] = '\0';
@ -810,18 +720,11 @@ static bool loadResourceFunction(const char *pData)
static bool loadRepairDroidFunction(const char *pData) static bool loadRepairDroidFunction(const char *pData)
{ {
REPAIR_DROID_FUNCTION* psFunction; REPAIR_DROID_FUNCTION *psFunction;
char functionName[MAX_STR_LENGTH]; char functionName[MAX_STR_LENGTH];
//allocate storage //allocate storage
psFunction = (REPAIR_DROID_FUNCTION *)malloc(sizeof psFunction = (REPAIR_DROID_FUNCTION *)malloc(sizeof(REPAIR_DROID_FUNCTION));
(REPAIR_DROID_FUNCTION));
if (psFunction == NULL)
{
debug( LOG_FATAL, "Repair Droid Function - Out of memory" );
abort();
return false;
}
memset(psFunction, 0, sizeof(REPAIR_DROID_FUNCTION)); memset(psFunction, 0, sizeof(REPAIR_DROID_FUNCTION));
//store the pointer in the Function Array //store the pointer in the Function Array
@ -836,7 +739,7 @@ static bool loadRepairDroidFunction(const char *pData)
//read the data in //read the data in
functionName[0] = '\0'; functionName[0] = '\0';
sscanf(pData, "%255[^,'\r\n],%d", functionName, sscanf(pData, "%255[^,'\r\n],%d", functionName,
&psFunction->repairPoints); &psFunction->repairPoints);
//allocate storage for the name //allocate storage for the name
storeName((FUNCTION *)psFunction, functionName); storeName((FUNCTION *)psFunction, functionName);
@ -849,23 +752,15 @@ static bool loadRepairDroidFunction(const char *pData)
static bool loadWallFunction(const char *pData) static bool loadWallFunction(const char *pData)
{ {
WALL_FUNCTION *psFunction; WALL_FUNCTION *psFunction;
// UDWORD i;
char functionName[MAX_STR_LENGTH]; char functionName[MAX_STR_LENGTH];
char structureName[MAX_STR_LENGTH]; char structureName[MAX_STR_LENGTH];
// STRUCTURE_STATS *pStructStat;
//allocate storage //allocate storage
psFunction = (WALL_FUNCTION *)malloc(sizeof(WALL_FUNCTION)); psFunction = (WALL_FUNCTION *)malloc(sizeof(WALL_FUNCTION));
if (psFunction == NULL)
{
debug( LOG_FATAL, "Wall Function - Out of memory" );
abort();
return false;
}
memset(psFunction, 0, sizeof(WALL_FUNCTION)); memset(psFunction, 0, sizeof(WALL_FUNCTION));
//store the pointer in the Function Array //store the pointer in the Function Array
*asFunctions = (FUNCTION*)psFunction; *asFunctions = (FUNCTION *)psFunction;
psFunction->ref = REF_FUNCTION_START + numFunctions; psFunction->ref = REF_FUNCTION_START + numFunctions;
numFunctions++; numFunctions++;
asFunctions++; asFunctions++;
@ -886,7 +781,7 @@ static bool loadWallFunction(const char *pData)
psFunction->pStructName = allocateName(structureName); psFunction->pStructName = allocateName(structureName);
if (!psFunction->pStructName) if (!psFunction->pStructName)
{ {
debug( LOG_ERROR, "Structure Stats Invalid for function - %s", functionName ); debug(LOG_ERROR, "Structure Stats Invalid for function - %s", functionName);
return false; return false;
} }
@ -899,34 +794,34 @@ void productionUpgrade(FUNCTION *pFunction, UBYTE player)
{ {
PRODUCTION_UPGRADE_FUNCTION *pUpgrade; PRODUCTION_UPGRADE_FUNCTION *pUpgrade;
pUpgrade = (PRODUCTION_UPGRADE_FUNCTION *)pFunction; pUpgrade = (PRODUCTION_UPGRADE_FUNCTION *)pFunction;
//check upgrades increase all values //check upgrades increase all values
if (pUpgrade->factory) if (pUpgrade->factory)
{ {
if (asProductionUpgrade[player][FACTORY_FLAG].modifier < if (asProductionUpgrade[player][FACTORY_FLAG].modifier <
pUpgrade->outputModifier) pUpgrade->outputModifier)
{ {
asProductionUpgrade[player][FACTORY_FLAG].modifier = asProductionUpgrade[player][FACTORY_FLAG].modifier =
pUpgrade->outputModifier; pUpgrade->outputModifier;
} }
} }
if (pUpgrade->cyborgFactory) if (pUpgrade->cyborgFactory)
{ {
if (asProductionUpgrade[player][CYBORG_FLAG].modifier < if (asProductionUpgrade[player][CYBORG_FLAG].modifier <
pUpgrade->outputModifier) pUpgrade->outputModifier)
{ {
asProductionUpgrade[player][CYBORG_FLAG].modifier = asProductionUpgrade[player][CYBORG_FLAG].modifier =
pUpgrade->outputModifier; pUpgrade->outputModifier;
} }
} }
if (pUpgrade->vtolFactory) if (pUpgrade->vtolFactory)
{ {
if (asProductionUpgrade[player][VTOL_FLAG].modifier < if (asProductionUpgrade[player][VTOL_FLAG].modifier <
pUpgrade->outputModifier) pUpgrade->outputModifier)
{ {
asProductionUpgrade[player][VTOL_FLAG].modifier = asProductionUpgrade[player][VTOL_FLAG].modifier =
pUpgrade->outputModifier; pUpgrade->outputModifier;
} }
} }
} }
@ -935,7 +830,7 @@ void researchUpgrade(FUNCTION *pFunction, UBYTE player)
{ {
RESEARCH_UPGRADE_FUNCTION *pUpgrade; RESEARCH_UPGRADE_FUNCTION *pUpgrade;
pUpgrade = (RESEARCH_UPGRADE_FUNCTION *)pFunction; pUpgrade = (RESEARCH_UPGRADE_FUNCTION *)pFunction;
//check upgrades increase all values //check upgrades increase all values
if (asResearchUpgrade[player].modifier < pUpgrade->upgradePoints) if (asResearchUpgrade[player].modifier < pUpgrade->upgradePoints)
@ -948,7 +843,7 @@ void repairFacUpgrade(FUNCTION *pFunction, UBYTE player)
{ {
REPAIR_UPGRADE_FUNCTION *pUpgrade; REPAIR_UPGRADE_FUNCTION *pUpgrade;
pUpgrade = (REPAIR_UPGRADE_FUNCTION *)pFunction; pUpgrade = (REPAIR_UPGRADE_FUNCTION *)pFunction;
//check upgrades increase all values //check upgrades increase all values
if (asRepairFacUpgrade[player].modifier < pUpgrade->upgradePoints) if (asRepairFacUpgrade[player].modifier < pUpgrade->upgradePoints)
@ -961,7 +856,7 @@ void powerUpgrade(FUNCTION *pFunction, UBYTE player)
{ {
POWER_UPGRADE_FUNCTION *pUpgrade; POWER_UPGRADE_FUNCTION *pUpgrade;
pUpgrade = (POWER_UPGRADE_FUNCTION *)pFunction; pUpgrade = (POWER_UPGRADE_FUNCTION *)pFunction;
//check upgrades increase all values //check upgrades increase all values
if (asPowerUpgrade[player].modifier < pUpgrade->upgradePoints) if (asPowerUpgrade[player].modifier < pUpgrade->upgradePoints)
@ -987,7 +882,7 @@ void structureBodyUpgrade(FUNCTION *pFunction, STRUCTURE *psBuilding)
{ {
UWORD increase, prevBaseBody, newBaseBody; UWORD increase, prevBaseBody, newBaseBody;
switch(psBuilding->pStructureType->type) switch (psBuilding->pStructureType->type)
{ {
case REF_WALL: case REF_WALL:
case REF_WALLCORNER: case REF_WALLCORNER:
@ -1002,10 +897,8 @@ void structureBodyUpgrade(FUNCTION *pFunction, STRUCTURE *psBuilding)
} }
prevBaseBody = (UWORD)structureBody(psBuilding); prevBaseBody = (UWORD)structureBody(psBuilding);
//newBaseBody = (UWORD)(psBuilding->pStructureType->bodyPoints + (psBuilding->
// pStructureType->bodyPoints * increase) / 100);
newBaseBody = (UWORD)(structureBaseBody(psBuilding) + newBaseBody = (UWORD)(structureBaseBody(psBuilding) +
(structureBaseBody(psBuilding) * increase) / 100); (structureBaseBody(psBuilding) * increase) / 100);
if (newBaseBody > prevBaseBody) if (newBaseBody > prevBaseBody)
{ {
@ -1018,7 +911,7 @@ void structureArmourUpgrade(FUNCTION *pFunction, STRUCTURE *psBuilding)
{ {
UWORD increase, prevBaseArmour, newBaseArmour; UWORD increase, prevBaseArmour, newBaseArmour;
switch(psBuilding->pStructureType->type) switch (psBuilding->pStructureType->type)
{ {
case REF_WALL: case REF_WALL:
case REF_WALLCORNER: case REF_WALLCORNER:
@ -1034,7 +927,7 @@ void structureArmourUpgrade(FUNCTION *pFunction, STRUCTURE *psBuilding)
prevBaseArmour = (UWORD)structureArmour(psBuilding->pStructureType, psBuilding->player); prevBaseArmour = (UWORD)structureArmour(psBuilding->pStructureType, psBuilding->player);
newBaseArmour = (UWORD)(psBuilding->pStructureType->armourValue + (psBuilding-> newBaseArmour = (UWORD)(psBuilding->pStructureType->armourValue + (psBuilding->
pStructureType->armourValue * increase) / 100); pStructureType->armourValue * increase) / 100);
if (newBaseArmour > prevBaseArmour) if (newBaseArmour > prevBaseArmour)
{ {
@ -1052,14 +945,14 @@ void structureResistanceUpgrade(FUNCTION *pFunction, STRUCTURE *psBuilding)
increase = ((STRUCTURE_UPGRADE_FUNCTION *)pFunction)->resistance; increase = ((STRUCTURE_UPGRADE_FUNCTION *)pFunction)->resistance;
prevBaseResistance = (UWORD)structureResistance(psBuilding->pStructureType, prevBaseResistance = (UWORD)structureResistance(psBuilding->pStructureType,
psBuilding->player); psBuilding->player);
newBaseResistance = (UWORD)(psBuilding->pStructureType->resistance + (psBuilding newBaseResistance = (UWORD)(psBuilding->pStructureType->resistance + (psBuilding
->pStructureType->resistance * increase) / 100); ->pStructureType->resistance * increase) / 100);
if (newBaseResistance > prevBaseResistance) if (newBaseResistance > prevBaseResistance)
{ {
psBuilding->resistance = (UWORD)((psBuilding->resistance * newBaseResistance) / psBuilding->resistance = (UWORD)((psBuilding->resistance * newBaseResistance) /
prevBaseResistance); prevBaseResistance);
} }
} }
@ -1068,9 +961,9 @@ void structureProductionUpgrade(STRUCTURE *psBuilding)
FACTORY *pFact; FACTORY *pFact;
PRODUCTION_FUNCTION *pFactFunc; PRODUCTION_FUNCTION *pFactFunc;
UDWORD type, baseOutput, i; UDWORD type, baseOutput, i;
STRUCTURE_STATS *psStat; STRUCTURE_STATS *psStat;
switch(psBuilding->pStructureType->type) switch (psBuilding->pStructureType->type)
{ {
case REF_FACTORY: case REF_FACTORY:
type = FACTORY_FLAG; type = FACTORY_FLAG;
@ -1088,54 +981,54 @@ void structureProductionUpgrade(STRUCTURE *psBuilding)
//upgrade the Output //upgrade the Output
pFact = &psBuilding->pFunctionality->factory; pFact = &psBuilding->pFunctionality->factory;
ASSERT( pFact != NULL, ASSERT(pFact != NULL,
"structureProductionUpgrade: invalid Factory pointer" ); "structureProductionUpgrade: invalid Factory pointer");
pFactFunc = (PRODUCTION_FUNCTION *)psBuilding->pStructureType->asFuncList[0]; pFactFunc = (PRODUCTION_FUNCTION *)psBuilding->pStructureType->asFuncList[0];
ASSERT( pFactFunc != NULL, ASSERT(pFactFunc != NULL,
"structureProductionUpgrade: invalid Function pointer" ); "structureProductionUpgrade: invalid Function pointer");
//current base value depends on whether there are modules attached to the structure //current base value depends on whether there are modules attached to the structure
baseOutput = pFactFunc->productionOutput; baseOutput = pFactFunc->productionOutput;
psStat = getModuleStat(psBuilding); psStat = getModuleStat(psBuilding);
if (psStat) if (psStat)
{ {
for (i = 0; i < pFact->capacity; i++) for (i = 0; i < pFact->capacity; i++)
{ {
baseOutput += ((PRODUCTION_FUNCTION*)psStat->asFuncList[0])->productionOutput; baseOutput += ((PRODUCTION_FUNCTION *)psStat->asFuncList[0])->productionOutput;
} }
} }
pFact->productionOutput = (UBYTE)(baseOutput + (pFactFunc->productionOutput * pFact->productionOutput = (UBYTE)(baseOutput + (pFactFunc->productionOutput *
asProductionUpgrade[psBuilding->player][type].modifier) / 100); asProductionUpgrade[psBuilding->player][type].modifier) / 100);
} }
void structureResearchUpgrade(STRUCTURE *psBuilding) void structureResearchUpgrade(STRUCTURE *psBuilding)
{ {
RESEARCH_FACILITY *pRes = &psBuilding->pFunctionality->researchFacility; RESEARCH_FACILITY *pRes = &psBuilding->pFunctionality->researchFacility;
RESEARCH_FUNCTION *pResFunc; RESEARCH_FUNCTION *pResFunc;
UDWORD baseOutput; UDWORD baseOutput;
STRUCTURE_STATS *psStat; STRUCTURE_STATS *psStat;
//upgrade the research points //upgrade the research points
ASSERT(pRes != NULL, "structureResearchUpgrade: invalid Research pointer"); ASSERT(pRes != NULL, "structureResearchUpgrade: invalid Research pointer");
pResFunc = (RESEARCH_FUNCTION *)psBuilding->pStructureType->asFuncList[0]; pResFunc = (RESEARCH_FUNCTION *)psBuilding->pStructureType->asFuncList[0];
ASSERT( pResFunc != NULL, ASSERT(pResFunc != NULL,
"structureResearchUpgrade: invalid Function pointer" ); "structureResearchUpgrade: invalid Function pointer");
//current base value depends on whether there are modules attached to the structure //current base value depends on whether there are modules attached to the structure
baseOutput = pResFunc->researchPoints; baseOutput = pResFunc->researchPoints;
psStat = getModuleStat(psBuilding); psStat = getModuleStat(psBuilding);
if (psStat) if (psStat)
{ {
if (pRes->capacity) if (pRes->capacity)
{ {
baseOutput += ((RESEARCH_FUNCTION*)psStat->asFuncList[0])->researchPoints; baseOutput += ((RESEARCH_FUNCTION *)psStat->asFuncList[0])->researchPoints;
} }
} }
pRes->researchPoints = baseOutput + (pResFunc->researchPoints * pRes->researchPoints = baseOutput + (pResFunc->researchPoints *
asResearchUpgrade[psBuilding->player].modifier) / 100; asResearchUpgrade[psBuilding->player].modifier) / 100;
} }
void structureReArmUpgrade(STRUCTURE *psBuilding) void structureReArmUpgrade(STRUCTURE *psBuilding)
@ -1147,11 +1040,11 @@ void structureReArmUpgrade(STRUCTURE *psBuilding)
ASSERT(pPad != NULL, "structureReArmUpgrade: invalid ReArm pointer"); ASSERT(pPad != NULL, "structureReArmUpgrade: invalid ReArm pointer");
pPadFunc = (REARM_FUNCTION *)psBuilding->pStructureType->asFuncList[0]; pPadFunc = (REARM_FUNCTION *)psBuilding->pStructureType->asFuncList[0];
ASSERT( pPadFunc != NULL, ASSERT(pPadFunc != NULL,
"structureReArmUpgrade: invalid Function pointer" ); "structureReArmUpgrade: invalid Function pointer");
pPad->reArmPoints = pPadFunc->reArmPoints + (pPadFunc->reArmPoints * pPad->reArmPoints = pPadFunc->reArmPoints + (pPadFunc->reArmPoints *
asReArmUpgrade[psBuilding->player].modifier) / 100; asReArmUpgrade[psBuilding->player].modifier) / 100;
} }
void structurePowerUpgrade(STRUCTURE *psBuilding) void structurePowerUpgrade(STRUCTURE *psBuilding)
@ -1171,7 +1064,7 @@ void structurePowerUpgrade(STRUCTURE *psBuilding)
{ {
if (pPowerGen->capacity) if (pPowerGen->capacity)
{ {
multiplier += ((POWER_GEN_FUNCTION*)psStat->asFuncList[0])->powerMultiplier; multiplier += ((POWER_GEN_FUNCTION *)psStat->asFuncList[0])->powerMultiplier;
} }
} }
pPowerGen->multiplier = multiplier + (pPGFunc->powerMultiplier * asPowerUpgrade[psBuilding->player].modifier) / 100; pPowerGen->multiplier = multiplier + (pPGFunc->powerMultiplier * asPowerUpgrade[psBuilding->player].modifier) / 100;
@ -1186,11 +1079,11 @@ void structureRepairUpgrade(STRUCTURE *psBuilding)
ASSERT(pRepair != NULL, "structureRepairUpgrade: invalid Repair pointer"); ASSERT(pRepair != NULL, "structureRepairUpgrade: invalid Repair pointer");
pRepairFunc = (REPAIR_DROID_FUNCTION *)psBuilding->pStructureType->asFuncList[0]; pRepairFunc = (REPAIR_DROID_FUNCTION *)psBuilding->pStructureType->asFuncList[0];
ASSERT( pRepairFunc != NULL, ASSERT(pRepairFunc != NULL,
"structureRepairUpgrade: invalid Function pointer" ); "structureRepairUpgrade: invalid Function pointer");
pRepair->power = pRepairFunc->repairPoints + (pRepairFunc->repairPoints * pRepair->power = pRepairFunc->repairPoints + (pRepairFunc->repairPoints *
asRepairFacUpgrade[psBuilding->player].modifier) / 100; asRepairFacUpgrade[psBuilding->player].modifier) / 100;
} }
void structureSensorUpgrade(STRUCTURE *psBuilding) void structureSensorUpgrade(STRUCTURE *psBuilding)
@ -1216,9 +1109,9 @@ void droidECMUpgrade(DROID *psDroid)
void droidBodyUpgrade(FUNCTION *pFunction, DROID *psDroid) void droidBodyUpgrade(FUNCTION *pFunction, DROID *psDroid)
{ {
UDWORD increase, prevBaseBody, newBaseBody, base; UDWORD increase, prevBaseBody, newBaseBody, base;
DROID *psCurr; DROID *psCurr;
increase = ((DROIDBODY_UPGRADE_FUNCTION*)pFunction)->body; increase = ((DROIDBODY_UPGRADE_FUNCTION *)pFunction)->body;
prevBaseBody = psDroid->originalBody; prevBaseBody = psDroid->originalBody;
base = calcDroidBaseBody(psDroid); base = calcDroidBaseBody(psDroid);
@ -1229,18 +1122,18 @@ void droidBodyUpgrade(FUNCTION *pFunction, DROID *psDroid)
psDroid->body = (psDroid->body * newBaseBody) / prevBaseBody; psDroid->body = (psDroid->body * newBaseBody) / prevBaseBody;
psDroid->originalBody = newBaseBody; psDroid->originalBody = newBaseBody;
} }
//if a transporter droid then need to upgrade the contents //if a transporter droid then need to upgrade the contents
if (psDroid->droidType == DROID_TRANSPORTER || psDroid->droidType == DROID_SUPERTRANSPORTER) if (psDroid->droidType == DROID_TRANSPORTER || psDroid->droidType == DROID_SUPERTRANSPORTER)
{ {
for (psCurr = psDroid->psGroup->psList; psCurr != NULL; psCurr = for (psCurr = psDroid->psGroup->psList; psCurr != NULL; psCurr =
psCurr->psGrpNext) psCurr->psGrpNext)
{ {
if (psCurr != psDroid) if (psCurr != psDroid)
{ {
droidBodyUpgrade(pFunction, psCurr); droidBodyUpgrade(pFunction, psCurr);
} }
} }
} }
} }
//upgrade the weapon stats for the correct subclass //upgrade the weapon stats for the correct subclass
@ -1253,11 +1146,11 @@ void weaponUpgrade(FUNCTION *pFunction, UBYTE player)
//check upgrades increase all values! //check upgrades increase all values!
if (asWeaponUpgrade[player][pUpgrade->subClass].firePause < pUpgrade->firePause) if (asWeaponUpgrade[player][pUpgrade->subClass].firePause < pUpgrade->firePause)
{ {
//make sure don't go less than 100% //make sure don't go less than 100%
if (pUpgrade->firePause > 100) if (pUpgrade->firePause > 100)
{ {
pUpgrade->firePause = 100; pUpgrade->firePause = 100;
} }
asWeaponUpgrade[player][pUpgrade->subClass].firePause = pUpgrade->firePause; asWeaponUpgrade[player][pUpgrade->subClass].firePause = pUpgrade->firePause;
} }
if (asWeaponUpgrade[player][pUpgrade->subClass].shortHit < pUpgrade->shortHit) if (asWeaponUpgrade[player][pUpgrade->subClass].shortHit < pUpgrade->shortHit)
@ -1358,48 +1251,48 @@ void bodyUpgrade(FUNCTION *pFunction, UBYTE player)
if (pUpgrade->droid) if (pUpgrade->droid)
{ {
if (asBodyUpgrade[player][DROID_BODY_UPGRADE].powerOutput < if (asBodyUpgrade[player][DROID_BODY_UPGRADE].powerOutput <
pUpgrade->upgradePoints) pUpgrade->upgradePoints)
{ {
asBodyUpgrade[player][DROID_BODY_UPGRADE].powerOutput = asBodyUpgrade[player][DROID_BODY_UPGRADE].powerOutput =
pUpgrade->upgradePoints; pUpgrade->upgradePoints;
} }
if (asBodyUpgrade[player][DROID_BODY_UPGRADE].body < if (asBodyUpgrade[player][DROID_BODY_UPGRADE].body <
pUpgrade->body) pUpgrade->body)
{ {
asBodyUpgrade[player][DROID_BODY_UPGRADE].body = asBodyUpgrade[player][DROID_BODY_UPGRADE].body =
pUpgrade->body; pUpgrade->body;
} }
for (inc=0; inc < WC_NUM_WEAPON_CLASSES; inc++) for (inc = 0; inc < WC_NUM_WEAPON_CLASSES; inc++)
{ {
if (asBodyUpgrade[player][DROID_BODY_UPGRADE].armourValue[inc] < if (asBodyUpgrade[player][DROID_BODY_UPGRADE].armourValue[inc] <
pUpgrade->armourValue[inc]) pUpgrade->armourValue[inc])
{ {
asBodyUpgrade[player][DROID_BODY_UPGRADE].armourValue[inc] = asBodyUpgrade[player][DROID_BODY_UPGRADE].armourValue[inc] =
pUpgrade->armourValue[inc]; pUpgrade->armourValue[inc];
} }
} }
} }
if (pUpgrade->cyborg) if (pUpgrade->cyborg)
{ {
if (asBodyUpgrade[player][CYBORG_BODY_UPGRADE].powerOutput < if (asBodyUpgrade[player][CYBORG_BODY_UPGRADE].powerOutput <
pUpgrade->upgradePoints) pUpgrade->upgradePoints)
{ {
asBodyUpgrade[player][CYBORG_BODY_UPGRADE].powerOutput = asBodyUpgrade[player][CYBORG_BODY_UPGRADE].powerOutput =
pUpgrade->upgradePoints; pUpgrade->upgradePoints;
} }
if (asBodyUpgrade[player][CYBORG_BODY_UPGRADE].body < if (asBodyUpgrade[player][CYBORG_BODY_UPGRADE].body <
pUpgrade->body) pUpgrade->body)
{ {
asBodyUpgrade[player][CYBORG_BODY_UPGRADE].body = asBodyUpgrade[player][CYBORG_BODY_UPGRADE].body =
pUpgrade->body; pUpgrade->body;
} }
for (inc=0; inc < WC_NUM_WEAPON_CLASSES; inc++) for (inc = 0; inc < WC_NUM_WEAPON_CLASSES; inc++)
{ {
if (asBodyUpgrade[player][CYBORG_BODY_UPGRADE].armourValue[inc] < if (asBodyUpgrade[player][CYBORG_BODY_UPGRADE].armourValue[inc] <
pUpgrade->armourValue[inc]) pUpgrade->armourValue[inc])
{ {
asBodyUpgrade[player][CYBORG_BODY_UPGRADE].armourValue[inc] = asBodyUpgrade[player][CYBORG_BODY_UPGRADE].armourValue[inc] =
pUpgrade->armourValue[inc]; pUpgrade->armourValue[inc];
} }
} }
} }
@ -1448,25 +1341,25 @@ void wallDefenceUpgrade(FUNCTION *pFunction, UBYTE player)
/*upgrades the droids inside a Transporter uwith the appropriate upgrade function*/ /*upgrades the droids inside a Transporter uwith the appropriate upgrade function*/
void upgradeTransporterDroids(DROID *psTransporter, void(*pUpgradeFunction)(DROID *psDroid)) void upgradeTransporterDroids(DROID *psTransporter, void(*pUpgradeFunction)(DROID *psDroid))
{ {
ASSERT (psTransporter->droidType == DROID_TRANSPORTER || psTransporter->droidType == DROID_SUPERTRANSPORTER, "upgradeTransporterUnits: invalid unit type"); ASSERT(psTransporter->droidType == DROID_TRANSPORTER || psTransporter->droidType == DROID_SUPERTRANSPORTER, "upgradeTransporterUnits: invalid unit type");
//loop thru' each unit in the Transporter //loop thru' each unit in the Transporter
for (DROID *psCurr = psTransporter->psGroup->psList; psCurr != NULL; psCurr = psCurr->psGrpNext) for (DROID *psCurr = psTransporter->psGroup->psList; psCurr != NULL; psCurr = psCurr->psGrpNext)
{ {
if (psCurr != psTransporter) if (psCurr != psTransporter)
{ {
//apply upgrade if not the transporter itself //apply upgrade if not the transporter itself
pUpgradeFunction(psCurr); pUpgradeFunction(psCurr);
} }
} }
} }
bool FunctionShutDown(void) bool FunctionShutDown(void)
{ {
UDWORD inc;//, player; UDWORD inc;
FUNCTION *pFunction, **pStartList = asFunctions; FUNCTION *pFunction, **pStartList = asFunctions;
for (inc=0; inc < numFunctions; inc++) for (inc = 0; inc < numFunctions; inc++)
{ {
pFunction = *asFunctions; pFunction = *asFunctions;
free(pFunction->pName); free(pFunction->pName);
@ -1511,35 +1404,26 @@ bool loadFunctionStats(const char *pFunctionData, UDWORD bufferSize)
FUNCTION **pStartList; FUNCTION **pStartList;
//allocate storage for the Function pointer array //allocate storage for the Function pointer array
asFunctions = (FUNCTION**) malloc(totalFunctions*sizeof(FUNCTION*)); asFunctions = (FUNCTION **) malloc(totalFunctions * sizeof(FUNCTION *));
if (!asFunctions)
{
debug( LOG_FATAL, "Out of memory" );
abort();
return false;
}
pStartList = asFunctions; pStartList = asFunctions;
//initialise the storage //initialise the storage
memset(asFunctions, 0, totalFunctions*sizeof(FUNCTION*)); memset(asFunctions, 0, totalFunctions * sizeof(FUNCTION *));
numFunctions = 0; numFunctions = 0;
//numProductionUpgrades = numResearchUpgrades = 0;//numArmourUpgrades =
//numRepairUpgrades = numResistanceUpgrades = numBodyUpgrades =
//numWeaponUpgrades = 0;
for (i=0; i < totalFunctions; i++) for (i = 0; i < totalFunctions; i++)
{ {
//read the data into the storage - the data is delimeted using comma's //read the data into the storage - the data is delimeted using comma's
FunctionType[0] = '\0'; FunctionType[0] = '\0';
sscanf(pFunctionData, "%255[^,'\r\n]", FunctionType); sscanf(pFunctionData, "%255[^,'\r\n]", FunctionType);
type = functionType(FunctionType); type = functionType(FunctionType);
pFunctionData += (strlen(FunctionType)+1); pFunctionData += (strlen(FunctionType) + 1);
if (!(pLoadFunction[type](pFunctionData))) if (!(pLoadFunction[type](pFunctionData)))
{ {
return false; return false;
} }
//increment the pointer to the start of the next record //increment the pointer to the start of the next record
pFunctionData = strchr(pFunctionData,'\n') + 1; pFunctionData = strchr(pFunctionData, '\n') + 1;
} }
//set the function list pointer to the start //set the function list pointer to the start
asFunctions = pStartList; asFunctions = pStartList;

View File

@ -333,7 +333,8 @@ static bool serializeMultiplayerGame(PHYSFS_file* fileHandle, const MULTIPLAYERG
|| !PHYSFS_writeUBE32(fileHandle, serializeMulti->power) || !PHYSFS_writeUBE32(fileHandle, serializeMulti->power)
|| !PHYSFS_writeUBE8(fileHandle, serializeMulti->base) || !PHYSFS_writeUBE8(fileHandle, serializeMulti->base)
|| !PHYSFS_writeUBE8(fileHandle, serializeMulti->alliance) || !PHYSFS_writeUBE8(fileHandle, serializeMulti->alliance)
|| !PHYSFS_writeUBE8(fileHandle, 0) || !PHYSFS_writeUBE8(fileHandle, serializeMulti->hash.Bytes)
|| !PHYSFS_write(fileHandle, serializeMulti->hash.bytes, serializeMulti->hash.Bytes, 1)
|| !PHYSFS_writeUBE16(fileHandle, 0) // dummy, was bytesPerSec || !PHYSFS_writeUBE16(fileHandle, 0) // dummy, was bytesPerSec
|| !PHYSFS_writeUBE8(fileHandle, 0) // dummy, was packetsPerSec || !PHYSFS_writeUBE8(fileHandle, 0) // dummy, was packetsPerSec
|| !PHYSFS_writeUBE8(fileHandle, challengeActive)) // reuse available field, was encryptKey || !PHYSFS_writeUBE8(fileHandle, challengeActive)) // reuse available field, was encryptKey
@ -357,6 +358,9 @@ static bool deserializeMultiplayerGame(PHYSFS_file* fileHandle, MULTIPLAYERGAME*
uint8_t dummy8; uint8_t dummy8;
uint16_t dummy16; uint16_t dummy16;
char dummy8c[8]; char dummy8c[8];
uint8_t hashSize;
serializeMulti->hash.setZero();
if (!PHYSFS_readUBE8(fileHandle, &serializeMulti->type) if (!PHYSFS_readUBE8(fileHandle, &serializeMulti->type)
|| PHYSFS_read(fileHandle, serializeMulti->map, 1, 128) != 128 || PHYSFS_read(fileHandle, serializeMulti->map, 1, 128) != 128
@ -367,7 +371,8 @@ static bool deserializeMultiplayerGame(PHYSFS_file* fileHandle, MULTIPLAYERGAME*
|| !PHYSFS_readUBE32(fileHandle, &serializeMulti->power) || !PHYSFS_readUBE32(fileHandle, &serializeMulti->power)
|| !PHYSFS_readUBE8(fileHandle, &serializeMulti->base) || !PHYSFS_readUBE8(fileHandle, &serializeMulti->base)
|| !PHYSFS_readUBE8(fileHandle, &serializeMulti->alliance) || !PHYSFS_readUBE8(fileHandle, &serializeMulti->alliance)
|| !PHYSFS_readUBE8(fileHandle, &dummy8) || !PHYSFS_readUBE8(fileHandle, &hashSize)
|| (hashSize == serializeMulti->hash.Bytes && !PHYSFS_read(fileHandle, serializeMulti->hash.bytes, serializeMulti->hash.Bytes, 1))
|| !PHYSFS_readUBE16(fileHandle, &dummy16) // dummy, was bytesPerSec || !PHYSFS_readUBE16(fileHandle, &dummy16) // dummy, was bytesPerSec
|| !PHYSFS_readUBE8(fileHandle, &dummy8) // dummy, was packetsPerSec || !PHYSFS_readUBE8(fileHandle, &dummy8) // dummy, was packetsPerSec
|| !PHYSFS_readUBE8(fileHandle, &dummy8)) // reused for challenge, was encryptKey || !PHYSFS_readUBE8(fileHandle, &dummy8)) // reused for challenge, was encryptKey
@ -3219,7 +3224,7 @@ bool gameLoadV7(PHYSFS_file* fileHandle)
//copy the level name across //copy the level name across
sstrcpy(aLevelName, saveGame.levelName); sstrcpy(aLevelName, saveGame.levelName);
//load up the level dataset //load up the level dataset
if (!levLoadData(aLevelName, saveGameName, (GAME_TYPE)gameType)) if (!levLoadData(aLevelName, NULL, saveGameName, (GAME_TYPE)gameType))
{ {
return false; return false;
} }
@ -3657,7 +3662,9 @@ bool gameLoadV(PHYSFS_file* fileHandle, unsigned int version)
//copy the level name across //copy the level name across
sstrcpy(aLevelName, saveGameData.levelName); sstrcpy(aLevelName, saveGameData.levelName);
//load up the level dataset //load up the level dataset
if (!levLoadData(aLevelName, saveGameName, (GAME_TYPE)gameType)) //if (!levLoadData(saveGameData.sGame.map /*aLevelName*/, &saveGameData.sGame.hash, saveGameName, (GAME_TYPE)gameType))
// Not sure what aLevelName is, in relation to game.map. But need to use aLevelName here, to be able to start the right map for campaign, and need game.hash, to start the right non-campaign map, if there are multiple identically named maps.
if (!levLoadData(aLevelName, &saveGameData.sGame.hash, saveGameName, (GAME_TYPE)gameType))
{ {
return false; return false;
} }
@ -4331,9 +4338,9 @@ static bool loadSaveDroid(const char *pFileName, DROID **ppsCurrentDroidLists)
psDroid->sMove.iVertSpeed = ini.value("vertSpeed").toInt(); psDroid->sMove.iVertSpeed = ini.value("vertSpeed").toInt();
psDroid->sMove.bumpTime = ini.value("bumpTime").toInt(); psDroid->sMove.bumpTime = ini.value("bumpTime").toInt();
psDroid->sMove.shuffleStart = ini.value("shuffleStart").toInt(); psDroid->sMove.shuffleStart = ini.value("shuffleStart").toInt();
for (int j = 0; j < sizeof(psDroid->sMove.iAttackRuns) / sizeof(psDroid->sMove.iAttackRuns[0]); ++j) for (int j = 0; j < DROID_MAXWEAPS; ++j)
{ {
psDroid->sMove.iAttackRuns[j] = ini.value("attackRun/" + QString::number(j)).toInt(); psDroid->asWeaps[j].usedAmmo = ini.value("attackRun/" + QString::number(j)).toInt();
} }
psDroid->sMove.lastBump = ini.value("lastBump").toInt(); psDroid->sMove.lastBump = ini.value("lastBump").toInt();
psDroid->sMove.pauseTime = ini.value("pauseTime").toInt(); psDroid->sMove.pauseTime = ini.value("pauseTime").toInt();
@ -4481,9 +4488,9 @@ static bool writeDroid(WzConfig &ini, DROID *psCurr, bool onMission, int &counte
ini.setValue("vertSpeed", psCurr->sMove.iVertSpeed); ini.setValue("vertSpeed", psCurr->sMove.iVertSpeed);
ini.setValue("bumpTime", psCurr->sMove.bumpTime); ini.setValue("bumpTime", psCurr->sMove.bumpTime);
ini.setValue("shuffleStart", psCurr->sMove.shuffleStart); ini.setValue("shuffleStart", psCurr->sMove.shuffleStart);
for (int i = 0; i < sizeof(psCurr->sMove.iAttackRuns) / sizeof(psCurr->sMove.iAttackRuns[0]); ++i) for (int i = 0; i < DROID_MAXWEAPS; ++i)
{ {
ini.setValue("attackRun/" + QString::number(i), psCurr->sMove.iAttackRuns[i]); ini.setValue("attackRun/" + QString::number(i), psCurr->asWeaps[i].usedAmmo);
} }
ini.setValue("lastBump", psCurr->sMove.lastBump); ini.setValue("lastBump", psCurr->sMove.lastBump);
ini.setValue("pauseTime", psCurr->sMove.pauseTime); ini.setValue("pauseTime", psCurr->sMove.pauseTime);
@ -4913,9 +4920,9 @@ static bool loadSaveStructure2(const char *pFileName, STRUCTURE **ppList)
break; break;
case REF_REARM_PAD: case REF_REARM_PAD:
psReArmPad = ((REARM_PAD *)psStructure->pFunctionality); psReArmPad = ((REARM_PAD *)psStructure->pFunctionality);
psReArmPad->reArmPoints = ini.value("Rearm/reArmPoints").toInt(); psReArmPad->reArmPoints = ini.value("Rearm/reArmPoints", psReArmPad->reArmPoints).toInt();
psReArmPad->timeStarted = ini.value("Rearm/timeStarted").toInt(); psReArmPad->timeStarted = ini.value("Rearm/timeStarted", psReArmPad->timeStarted).toInt();
psReArmPad->timeLastUpdated = ini.value("Rearm/timeLastUpdated").toInt(); psReArmPad->timeLastUpdated = ini.value("Rearm/timeLastUpdated", psReArmPad->timeLastUpdated).toInt();
break; break;
case REF_WALL: case REF_WALL:
case REF_GATE: case REF_GATE:
@ -6412,7 +6419,7 @@ bool plotStructurePreview16(char *backDropSprite, Vector2i playeridpos[])
PIELIGHT color = WZCOL_BLACK ; PIELIGHT color = WZCOL_BLACK ;
bool HQ = false; bool HQ = false;
psLevel = levFindDataSet(game.map); psLevel = levFindDataSet(game.map, &game.hash);
strcpy(aFileName, psLevel->apDataFiles[0]); strcpy(aFileName, psLevel->apDataFiles[0]);
aFileName[strlen(aFileName) - 4] = '\0'; aFileName[strlen(aFileName) - 4] = '\0';
strcat(aFileName, "/struct.bjo"); strcat(aFileName, "/struct.bjo");
@ -6614,7 +6621,7 @@ static void plotFeature(char *backDropSprite)
const PIELIGHT colourOil = WZCOL_MAP_PREVIEW_OIL; const PIELIGHT colourOil = WZCOL_MAP_PREVIEW_OIL;
const PIELIGHT colourBarrel = WZCOL_MAP_PREVIEW_BARREL; const PIELIGHT colourBarrel = WZCOL_MAP_PREVIEW_BARREL;
psLevel = levFindDataSet(game.map); psLevel = levFindDataSet(game.map, &game.hash);
strcpy(aFileName, psLevel->apDataFiles[0]); strcpy(aFileName, psLevel->apDataFiles[0]);
aFileName[strlen(aFileName) - 4] = '\0'; aFileName[strlen(aFileName) - 4] = '\0';
strcat(aFileName, "/feat.bjo"); strcat(aFileName, "/feat.bjo");

View File

@ -88,8 +88,6 @@ bool SecondaryWindowUp = false;
static UDWORD newMapWidth, newMapHeight; static UDWORD newMapWidth, newMapHeight;
static FLAG_POSITION debugMenuDroidDeliveryPoint;
#define RETXOFFSET (0)// Reticule button offset #define RETXOFFSET (0)// Reticule button offset
#define RETYOFFSET (0) #define RETYOFFSET (0)
#define NUMRETBUTS 7 // Number of reticule buttons. #define NUMRETBUTS 7 // Number of reticule buttons.
@ -822,7 +820,7 @@ static void intDoScreenRefresh(void)
if (psFlag != NULL) if (psFlag != NULL)
{ {
// need to restart the delivery point position // need to restart the delivery point position
StartDeliveryPosition(psFlag); startDeliveryPosition(psFlag);
} }
// make sure the commander order screen is in the right state // make sure the commander order screen is in the right state
@ -1355,12 +1353,17 @@ static void intProcessEditStats(UDWORD id)
if (psPositionStats->ref >= REF_TEMPLATE_START && if (psPositionStats->ref >= REF_TEMPLATE_START &&
psPositionStats->ref < REF_TEMPLATE_START + REF_RANGE) psPositionStats->ref < REF_TEMPLATE_START + REF_RANGE)
{ {
FLAG_POSITION debugMenuDroidDeliveryPoint;
// Placing a droid from the debug menu, set up the flag. (This would probably be safe to do, even if we're placing something else.) // Placing a droid from the debug menu, set up the flag. (This would probably be safe to do, even if we're placing something else.)
debugMenuDroidDeliveryPoint.factoryType = REPAIR_FLAG; debugMenuDroidDeliveryPoint.factoryType = REPAIR_FLAG;
debugMenuDroidDeliveryPoint.factoryInc = 0; debugMenuDroidDeliveryPoint.factoryInc = 0;
deliveryPointToMove = &debugMenuDroidDeliveryPoint; debugMenuDroidDeliveryPoint.player = selectedPlayer;
startDeliveryPosition(&debugMenuDroidDeliveryPoint);
}
else
{
intStartStructPosition(psPositionStats);
} }
intStartStructPosition(psPositionStats);
editPosMode = IED_POS; editPosMode = IED_POS;
} }
else if (id == IDSTAT_CLOSE) else if (id == IDSTAT_CLOSE)
@ -1905,9 +1908,10 @@ INT_RETVAL intRunWidgets(void)
/* Directly positioning some type of object */ /* Directly positioning some type of object */
unsigned structX1 = INT32_MAX; unsigned structX1 = INT32_MAX;
unsigned structY1 = INT32_MAX; unsigned structY1 = INT32_MAX;
FLAG_POSITION flag;
structX2 = INT32_MAX - 1; structX2 = INT32_MAX - 1;
structY2 = INT32_MAX - 1; structY2 = INT32_MAX - 1;
if (found3DBuildLocTwo(&structX1, &structY1, &structX2, &structY2) || found3DBuilding(&structX1, &structY1)) if (sBuildDetails.psStats && (found3DBuilding(&structX1, &structY1) || found3DBuildLocTwo(&structX1, &structY1, &structX2, &structY2)))
{ {
if (structX2 == INT32_MAX - 1) if (structX2 == INT32_MAX - 1)
{ {
@ -1923,6 +1927,12 @@ INT_RETVAL intRunWidgets(void)
std::swap(structY1, structY2); std::swap(structY1, structY2);
} }
} }
else if (deliveryReposFinished(&flag))
{
structX2 = structX1 = map_coord(flag.coords.x);
structY2 = structY1 = map_coord(flag.coords.y);
}
for (unsigned j = structY1; j <= structY2; ++j) for (unsigned j = structY1; j <= structY2; ++j)
for (unsigned i = structX1; i <= structX2; ++i) for (unsigned i = structX1; i <= structX2; ++i)
{ {
@ -2001,6 +2011,7 @@ INT_RETVAL intRunWidgets(void)
psDroid = buildDroid((DROID_TEMPLATE *)psPositionStats, psDroid = buildDroid((DROID_TEMPLATE *)psPositionStats,
world_coord(structX) + TILE_UNITS / 2, world_coord(structY) + TILE_UNITS / 2, world_coord(structX) + TILE_UNITS / 2, world_coord(structY) + TILE_UNITS / 2,
selectedPlayer, false, NULL); selectedPlayer, false, NULL);
cancelDeliveryRepos();
if (psDroid) if (psDroid)
{ {
addDroid(psDroid, apsDroidLists); addDroid(psDroid, apsDroidLists);
@ -2751,7 +2762,7 @@ static void intProcessStats(UDWORD id)
psFlag = FindFactoryDelivery(psStruct); psFlag = FindFactoryDelivery(psStruct);
if (psFlag) if (psFlag)
{ {
StartDeliveryPosition(psFlag); startDeliveryPosition(psFlag);
} }
} }
} }
@ -2897,8 +2908,6 @@ void intCommanderSelected(DROID *psDroid)
widgHide(psWScreen, IDOBJ_FORM); widgHide(psWScreen, IDOBJ_FORM);
} }
extern void FinishStructurePosition(UDWORD xPos,UDWORD yPos,void *UserData);
/* Start looking for a structure location */ /* Start looking for a structure location */
static void intStartStructPosition(BASE_STATS *psStats) static void intStartStructPosition(BASE_STATS *psStats)
{ {

View File

@ -139,19 +139,26 @@ static bool InitialiseGlobals(void)
} }
static bool loadLevFile(const char* filename, searchPathMode datadir, bool ignoreWrf) static bool loadLevFile(const char* filename, searchPathMode datadir, bool ignoreWrf, char const *realFileName)
{ {
char *pBuffer; char *pBuffer;
UDWORD size; UDWORD size;
debug( LOG_WZ, "Loading lev file: %s\n", filename ); if (realFileName == NULL)
{
debug(LOG_WZ, "Loading lev file: \"%s\", builtin\n", filename);
}
else
{
debug(LOG_WZ, "Loading lev file: \"%s\" from \"%s\"\n", filename, realFileName);
}
if (!PHYSFS_exists(filename) || !loadFile(filename, &pBuffer, &size)) if (!PHYSFS_exists(filename) || !loadFile(filename, &pBuffer, &size))
{ {
debug(LOG_ERROR, "loadLevFile: File not found: %s\n", filename); debug(LOG_ERROR, "loadLevFile: File not found: %s\n", filename);
return false; // only in NDEBUG case return false; // only in NDEBUG case
} }
if (!levParse(pBuffer, size, datadir, ignoreWrf)) if (!levParse(pBuffer, size, datadir, ignoreWrf, realFileName))
{ {
debug(LOG_ERROR, "loadLevFile: Parse error in %s\n", filename); debug(LOG_ERROR, "loadLevFile: Parse error in %s\n", filename);
return false; return false;
@ -235,10 +242,11 @@ void registerSearchPath( const char path[], unsigned int priority )
bool rebuildSearchPath( searchPathMode mode, bool force ) bool rebuildSearchPath( searchPathMode mode, bool force )
{ {
static searchPathMode current_mode = mod_clean; static searchPathMode current_mode = mod_clean;
static std::string current_current_map;
wzSearchPath * curSearchPath = searchPathRegistry; wzSearchPath * curSearchPath = searchPathRegistry;
char tmpstr[PATH_MAX] = "\0"; char tmpstr[PATH_MAX] = "\0";
if (mode != current_mode || force || if (mode != current_mode || (current_map != NULL? current_map : "") != current_current_map || force ||
(use_override_mods && strcmp(override_mod_list, getModList()))) (use_override_mods && strcmp(override_mod_list, getModList())))
{ {
if (mode != mod_clean) if (mode != mod_clean)
@ -247,6 +255,7 @@ bool rebuildSearchPath( searchPathMode mode, bool force )
} }
current_mode = mode; current_mode = mode;
current_current_map = current_map != NULL? current_map : "";
// Start at the lowest priority // Start at the lowest priority
while( curSearchPath->lowerPriority ) while( curSearchPath->lowerPriority )
@ -356,14 +365,11 @@ bool rebuildSearchPath( searchPathMode mode, bool force )
PHYSFS_addToSearchPath(tmpstr, PHYSFS_APPEND); PHYSFS_addToSearchPath(tmpstr, PHYSFS_APPEND);
curSearchPath = curSearchPath->higherPriority; curSearchPath = curSearchPath->higherPriority;
} }
curSearchPath = searchPathRegistry;
while (curSearchPath->lowerPriority)
curSearchPath = curSearchPath->lowerPriority;
// Add the selected map first, for mapmod support // Add the selected map first, for mapmod support
while (curSearchPath) if (current_map != NULL)
{ {
addSubdirs(curSearchPath->path, "maps", PHYSFS_APPEND, current_map, false); std::string realPathAndDir = std::string(PHYSFS_getRealDir(current_map)) + current_map;
curSearchPath = curSearchPath->higherPriority; PHYSFS_addToSearchPath(realPathAndDir.c_str(), PHYSFS_APPEND);
} }
curSearchPath = searchPathRegistry; curSearchPath = searchPathRegistry;
while (curSearchPath->lowerPriority) while (curSearchPath->lowerPriority)
@ -403,15 +409,6 @@ bool rebuildSearchPath( searchPathMode mode, bool force )
curSearchPath = curSearchPath->higherPriority; curSearchPath = curSearchPath->higherPriority;
} }
curSearchPath = searchPathRegistry;
while (curSearchPath->lowerPriority)
curSearchPath = curSearchPath->lowerPriority;
// Add maps last, so files in them don't override game data
while (curSearchPath)
{
addSubdirs(curSearchPath->path, "maps", PHYSFS_APPEND, NULL, false);
curSearchPath = curSearchPath->higherPriority;
}
break; break;
default: default:
debug(LOG_ERROR, "Can't switch to unknown mods %i", mode); debug(LOG_ERROR, "Can't switch to unknown mods %i", mode);
@ -443,35 +440,61 @@ bool rebuildSearchPath( searchPathMode mode, bool force )
return true; return true;
} }
typedef std::vector<std::string> MapFileList;
bool buildMapList(void) static MapFileList listMapFiles()
{ {
char ** filelist, ** file; MapFileList ret;
size_t len;
if (!loadLevFile("gamedesc.lev", mod_campaign, false)) char **subdirlist = PHYSFS_enumerateFiles("maps");
for (char **i = subdirlist; *i != NULL; ++i)
{
if (*i[0] == '.')
{
continue;
}
std::string realFileName = std::string("maps/") + *i;
ret.push_back(realFileName);
}
PHYSFS_freeList(subdirlist);
return ret;
}
bool buildMapList()
{
if (!loadLevFile("gamedesc.lev", mod_campaign, false, NULL))
{ {
return false; return false;
} }
loadLevFile("addon.lev", mod_multiplay, false); loadLevFile("addon.lev", mod_multiplay, false, NULL);
filelist = PHYSFS_enumerateFiles(""); MapFileList realFileNames = listMapFiles();
for ( file = filelist; *file != NULL; ++file ) for (MapFileList::iterator realFileName = realFileNames.begin(); realFileName != realFileNames.end(); ++realFileName)
{ {
len = strlen( *file ); std::string realFilePathAndName = PHYSFS_getRealDir(realFileName->c_str()) + *realFileName;
if ( len > 10 // Do not add addon.lev again PHYSFS_addToSearchPath(realFilePathAndName.c_str(), PHYSFS_APPEND);
&& !strcasecmp( *file+(len-10), ".addon.lev") )
{
loadLevFile(*file, mod_multiplay, true);
}
// add support for X player maps using a new name to prevent conflicts.
if ( len > 13 && !strcasecmp( *file+(len-13), ".xplayers.lev") )
{
loadLevFile(*file, mod_multiplay, true);
}
char **filelist = PHYSFS_enumerateFiles("");
for (char **file = filelist; *file != NULL; ++file)
{
size_t len = strlen(*file);
if (len > 10 && !strcasecmp(*file + (len - 10), ".addon.lev")) // Do not add addon.lev again
{
loadLevFile(*file, mod_multiplay, true, realFileName->c_str());
}
// add support for X player maps using a new name to prevent conflicts.
if (len > 13 && !strcasecmp(*file + (len - 13), ".xplayers.lev"))
{
loadLevFile(*file, mod_multiplay, true, realFileName->c_str());
}
}
PHYSFS_freeList(filelist);
PHYSFS_removeFromSearchPath(realFilePathAndName.c_str());
} }
PHYSFS_freeList( filelist );
return true; return true;
} }
@ -917,7 +940,7 @@ bool stageOneShutDown(void)
debug(LOG_TEXTURE, "=== stageOneShutDown ==="); debug(LOG_TEXTURE, "=== stageOneShutDown ===");
pie_TexShutDown(); pie_TexShutDown();
// no map for the main menu // no map for the main menu
setCurrentMap((char*)"", 1); setCurrentMap(NULL, 1);
// Use mod_multiplay as the default (campaign might have set it to mod_singleplayer) // Use mod_multiplay as the default (campaign might have set it to mod_singleplayer)
rebuildSearchPath( mod_multiplay, true ); rebuildSearchPath( mod_multiplay, true );
pie_TexInit(); // restart it pie_TexInit(); // restart it
@ -1120,7 +1143,6 @@ bool stageThreeInitialise(void)
// Re-inititialise some static variables. // Re-inititialise some static variables.
driveInitVars(false); driveInitVars(false);
displayInitVars();
resizeRadar(); resizeRadar();
setAllPauseStates(false); setAllPauseStates(false);

View File

@ -30,6 +30,9 @@
#include "lib/framework/frame.h" #include "lib/framework/frame.h"
#include "lib/framework/frameresource.h" #include "lib/framework/frameresource.h"
#include "lib/framework/listmacs.h" #include "lib/framework/listmacs.h"
#include "lib/framework/file.h"
#include "lib/framework/crc.h"
#include "lib/framework/physfs_ext.h"
#include "lib/exceptionhandler/dumpinfo.h" #include "lib/exceptionhandler/dumpinfo.h"
#include "init.h" #include "init.h"
#include "objects.h" #include "objects.h"
@ -68,7 +71,7 @@ static LEVEL_DATASET *psBaseData = NULL;
static LEVEL_DATASET *psCurrLevel = NULL; static LEVEL_DATASET *psCurrLevel = NULL;
// dummy level data for single WRF loads // dummy level data for single WRF loads
static LEVEL_DATASET sSingleWRF = { 0, 0, 0, 0, mod_clean, { 0 }, 0, 0, 0 }; static LEVEL_DATASET sSingleWRF = {0, 0, 0, 0, mod_clean, {0}, 0, 0, 0, NULL, {{0}}};
// return values from the lexer // return values from the lexer
char *pLevToken; char *pLevToken;
@ -124,6 +127,7 @@ void levShutDown(void)
} }
free(toDelete->pName); free(toDelete->pName);
free(toDelete->realFileName);
free(toDelete); free(toDelete);
} }
psLevels = NULL; psLevels = NULL;
@ -141,26 +145,54 @@ void lev_error(const char* msg)
* @return a dataset with associated with the given @c name, or NULL if none * @return a dataset with associated with the given @c name, or NULL if none
* could be found. * could be found.
*/ */
LEVEL_DATASET* levFindDataSet(const char* name) LEVEL_DATASET *levFindDataSet(char const *name, Sha256 const *hash)
{ {
LEVEL_DATASET* psNewLevel; if (hash != NULL && hash->isZero())
for (psNewLevel = psLevels; psNewLevel; psNewLevel = psNewLevel->psNext)
{ {
if (psNewLevel->pName != NULL hash = NULL; // Don't check hash if it's just 0000000000000000000000000000000000000000000000000000000000000000. Assuming real map files probably won't have that particular SHA-256 hash.
&& strcmp(psNewLevel->pName, name) == 0) }
for (LEVEL_DATASET *psNewLevel = psLevels; psNewLevel != NULL; psNewLevel = psNewLevel->psNext)
{
if (psNewLevel->pName != NULL && strcmp(psNewLevel->pName, name) == 0)
{ {
return psNewLevel; if (hash == NULL || levGetFileHash(psNewLevel) == *hash)
{
return psNewLevel;
}
} }
} }
return NULL; return NULL;
} }
Sha256 levGetFileHash(LEVEL_DATASET *level)
{
if (level->realFileName != NULL && level->realFileHash.isZero())
{
level->realFileHash = findHashOfFile(level->realFileName);
debug(LOG_WZ, "Hash of file \"%s\" is %s.", level->realFileName, level->realFileHash.toString().c_str());
}
return level->realFileHash;
}
Sha256 levGetMapNameHash(char const *mapName)
{
LEVEL_DATASET *level = levFindDataSet(mapName, NULL);
if (level == NULL)
{
debug(LOG_WARNING, "Couldn't find map \"%s\" to hash.", mapName);
Sha256 zero;
zero.setZero();
return zero;
}
return levGetFileHash(level);
}
// parse a level description data file // parse a level description data file
// the ignoreWrf hack is for compatibility with old maps that try to link in various // the ignoreWrf hack is for compatibility with old maps that try to link in various
// data files that we have removed // data files that we have removed
bool levParse(const char* buffer, size_t size, searchPathMode datadir, bool ignoreWrf) bool levParse(const char* buffer, size_t size, searchPathMode datadir, bool ignoreWrf, char const *realFileName)
{ {
lexerinput_t input; lexerinput_t input;
LEVELPARSER_STATE state; LEVELPARSER_STATE state;
@ -202,6 +234,8 @@ bool levParse(const char* buffer, size_t size, searchPathMode datadir, bool igno
psDataSet->players = 1; psDataSet->players = 1;
psDataSet->game = -1; psDataSet->game = -1;
psDataSet->dataDir = datadir; psDataSet->dataDir = datadir;
psDataSet->realFileName = realFileName != NULL? strdup(realFileName) : NULL;
psDataSet->realFileHash.setZero(); // The hash is only calculated on demand; for example, if the map name matches.
LIST_APPEND(psLevels, psDataSet, LEVEL_DATASET); LIST_APPEND(psLevels, psDataSet, LEVEL_DATASET);
currData = 0; currData = 0;
@ -592,13 +626,13 @@ char *getLevelName( void )
// load up the data for a level // load up the data for a level
bool levLoadData(const char* name, char *pSaveName, GAME_TYPE saveType) bool levLoadData(char const *name, Sha256 const *hash, char *pSaveName, GAME_TYPE saveType)
{ {
LEVEL_DATASET *psNewLevel, *psBaseData, *psChangeLevel; LEVEL_DATASET *psNewLevel, *psBaseData, *psChangeLevel;
SDWORD i; SDWORD i;
bool bCamChangeSaveGame; bool bCamChangeSaveGame;
debug(LOG_WZ, "Loading level %s (%s, type %d)", name, pSaveName, (int)saveType); debug(LOG_WZ, "Loading level %s hash %s (%s, type %d)", name, hash == NULL? "builtin" : hash->toString().c_str(), pSaveName, (int)saveType);
if (saveType == GTYPE_SAVE_START || saveType == GTYPE_SAVE_MIDMISSION) if (saveType == GTYPE_SAVE_START || saveType == GTYPE_SAVE_MIDMISSION)
{ {
if (!levReleaseAll()) if (!levReleaseAll())
@ -611,7 +645,7 @@ bool levLoadData(const char* name, char *pSaveName, GAME_TYPE saveType)
levelLoadType = saveType; levelLoadType = saveType;
// find the level dataset // find the level dataset
psNewLevel = levFindDataSet(name); psNewLevel = levFindDataSet(name, hash);
if (psNewLevel == NULL) if (psNewLevel == NULL)
{ {
debug(LOG_WZ, "Dataset %s not found - trying to load as WRF", name); debug(LOG_WZ, "Dataset %s not found - trying to load as WRF", name);
@ -686,7 +720,7 @@ bool levLoadData(const char* name, char *pSaveName, GAME_TYPE saveType)
} }
} }
setCurrentMap(psNewLevel->pName, psNewLevel->players); setCurrentMap(psNewLevel->realFileName, psNewLevel->players);
if (!rebuildSearchPath(psNewLevel->dataDir, true)) if (!rebuildSearchPath(psNewLevel->dataDir, true))
{ {
return false; return false;

View File

@ -24,6 +24,7 @@
#ifndef __INCLUDED_SRC_LEVELS_H__ #ifndef __INCLUDED_SRC_LEVELS_H__
#define __INCLUDED_SRC_LEVELS_H__ #define __INCLUDED_SRC_LEVELS_H__
#include "lib/framework/crc.h"
#include "init.h" #include "init.h"
#include "game.h" #include "game.h"
@ -68,6 +69,9 @@ struct LEVEL_DATASET
LEVEL_DATASET *psChange; // LEVEL_DATASET used when changing to this level from another LEVEL_DATASET *psChange; // LEVEL_DATASET used when changing to this level from another
LEVEL_DATASET *psNext; LEVEL_DATASET *psNext;
char * realFileName; ///< Filename of the file containing the level, or NULL if the level is built in.
Sha256 realFileHash; ///< Use levGetFileHash() to read this value. SHA-256 hash of the file containing the level, or 0x00×32 if the level is built in or not yet calculated.
}; };
@ -75,7 +79,7 @@ struct LEVEL_DATASET
extern LEVEL_DATASET *psLevels; extern LEVEL_DATASET *psLevels;
// parse a level description data file // parse a level description data file
extern bool levParse(const char* buffer, size_t size, searchPathMode datadir, bool ignoreWrf); bool levParse(const char* buffer, size_t size, searchPathMode datadir, bool ignoreWrf, char const *realFileName);
// shutdown the level system // shutdown the level system
extern void levShutDown(void); extern void levShutDown(void);
@ -83,10 +87,13 @@ extern void levShutDown(void);
extern bool levInitialise(void); extern bool levInitialise(void);
// load up the data for a level // load up the data for a level
extern bool levLoadData(const char* name, char *pSaveName, GAME_TYPE saveType); bool levLoadData(char const *name, Sha256 const *hash, char *pSaveName, GAME_TYPE saveType);
// find the level dataset // find the level dataset
extern LEVEL_DATASET* levFindDataSet(const char* name); LEVEL_DATASET *levFindDataSet(char const *name, Sha256 const *hash = NULL);
Sha256 levGetFileHash(LEVEL_DATASET *level);
Sha256 levGetMapNameHash(char const *name);
// free the currently loaded dataset // free the currently loaded dataset
extern bool levReleaseAll(void); extern bool levReleaseAll(void);

View File

@ -182,6 +182,7 @@ static GAMECODE renderLoop()
//handles callbacks for positioning of DP's //handles callbacks for positioning of DP's
process3DBuilding(); process3DBuilding();
processDeliveryRepos();
//ajl. get the incoming netgame messages and process them. //ajl. get the incoming netgame messages and process them.
// FIXME Previous comment is deprecated. multiPlayerLoop does some other weird stuff, but not that anymore. // FIXME Previous comment is deprecated. multiPlayerLoop does some other weird stuff, but not that anymore.

View File

@ -115,7 +115,7 @@ char * override_mods[MAX_MODS] = { NULL };
char * override_mod_list = NULL; char * override_mod_list = NULL;
bool use_override_mods = false; bool use_override_mods = false;
char *current_map[3] = { NULL }; char *current_map = NULL;
char * loaded_mods[MAX_MODS] = { NULL }; char * loaded_mods[MAX_MODS] = { NULL };
char * mod_list = NULL; char * mod_list = NULL;
@ -274,28 +274,8 @@ void setOverrideMods(char * modlist)
void setCurrentMap(char* map, int maxPlayers) void setCurrentMap(char* map, int maxPlayers)
{ {
free(current_map[0]); free(current_map);
free(current_map[1]); current_map = map != NULL? strdup(map) : NULL;
// Transform "Sk-Rush-T2" into "4c-Rush.wz" so it can be matched by the map loader
current_map[0] = (char*)malloc(strlen(map) + 1 + 7);
snprintf(current_map[0], 3, "%d", maxPlayers);
strcat(current_map[0], "c-");
if (strncmp(map, "Sk-", 3) == 0)
{
strcat(current_map[0], map + 3);
}
else
{
strcat(current_map[0], map);
}
if (strncmp(current_map[0] + strlen(current_map[0]) - 3, "-T", 2) == 0)
{
current_map[0][strlen(current_map[0]) - 3] = '\0';
}
current_map[1] = (char*)malloc(strlen(map) + 1 + 7);
strcpy(current_map[1], current_map[0]);
strcat(current_map[1],".wz");
current_map[2] = NULL;
} }
void clearOverrideMods(void) void clearOverrideMods(void)
@ -779,7 +759,9 @@ static void startGameLoop(void)
{ {
SetGameMode(GS_NORMAL); SetGameMode(GS_NORMAL);
if (!levLoadData(aLevelName, NULL, GTYPE_SCENARIO_START)) //if (!levLoadData(game.map /*aLevelName*/, &game.hash, NULL, GTYPE_SCENARIO_START))
// Not sure what aLevelName is, in relation to game.map. But need to use aLevelName here, to be able to start the right map for campaign, and need game.hash, to start the right non-campaign map, if there are multiple identically named maps.
if (!levLoadData(aLevelName, &game.hash, NULL, GTYPE_SCENARIO_START))
{ {
debug( LOG_FATAL, "Shutting down after failure" ); debug( LOG_FATAL, "Shutting down after failure" );
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
@ -1268,6 +1250,15 @@ int realmain(int argc, char *argv[])
war_SetWidth(pie_GetVideoBufferWidth()); war_SetWidth(pie_GetVideoBufferWidth());
war_SetHeight(pie_GetVideoBufferHeight()); war_SetHeight(pie_GetVideoBufferHeight());
if (!pie_GetShaderAvailability())
{
war_SetShaders(FALLBACK);
}
else
{
pie_SetShaderUsage(war_GetShaders()==SHADERS_ON);
}
pie_SetFogStatus(false); pie_SetFogStatus(false);
pie_ScreenFlip(CLEAR_BLACK); pie_ScreenFlip(CLEAR_BLACK);

View File

@ -54,6 +54,6 @@ extern char * override_mod_list;
extern bool use_override_mods; extern bool use_override_mods;
void setCurrentMap(char* map, int maxPlayers); void setCurrentMap(char* map, int maxPlayers);
extern char *current_map[3]; extern char *current_map;
#endif // __INCLUDED_SRC_MAIN_H__ #endif // __INCLUDED_SRC_MAIN_H__

View File

@ -26,9 +26,6 @@
#include "lib/framework/vector.h" #include "lib/framework/vector.h"
//Watermelon:num of VTOL weapons should be same as DROID_MAXWEAPS
#define VTOL_MAXWEAPS 3
enum MOVE_STATUS enum MOVE_STATUS
{ {
MOVEINACTIVE, MOVEINACTIVE,
@ -65,9 +62,6 @@ struct MOVE_CONTROL
/* vtol movement - GJ */ /* vtol movement - GJ */
SWORD iVertSpeed; SWORD iVertSpeed;
// iAttackRuns tracks the amount of ammunition a VTOL has remaining for each weapon
UDWORD iAttackRuns[VTOL_MAXWEAPS];
}; };
#endif // __INCLUDED_MOVEDEF_H__ #endif // __INCLUDED_MOVEDEF_H__

View File

@ -392,6 +392,32 @@ static int guessMapTilesetType(LEVEL_DATASET *psLevel)
return TILESET_ARIZONA; return TILESET_ARIZONA;
} }
static void loadEmptyMapPreview()
{
// No map is available to preview, so improvise.
char *imageData = (char *)malloc(BACKDROP_HACK_WIDTH * BACKDROP_HACK_HEIGHT * 3);
memset(imageData, 0, BACKDROP_HACK_WIDTH * BACKDROP_HACK_HEIGHT * 3); //dunno about background color
int const ex = 100, ey = 100, bx = 5, by = 8;
for (unsigned n = 0; n < 125; ++n)
{
int sx = rand()%(ex - bx), sy = rand()%(ey - by);
char col[3] = {char(rand()%256), char(rand()%256), char(rand()%256)};
for (unsigned y = 0; y < by; ++y)
for (unsigned x = 0; x < bx; ++x)
if (("\2\1\261\11\6"[x]>>y & 1) == 1) // ?
memcpy(imageData + 3*(sx + x + BACKDROP_HACK_WIDTH*(sy + y)), col, 3);
}
// Slight hack to init array with a special value used to determine how many players on map
Vector2i playerpos[MAX_PLAYERS];
memset(playerpos, 0x77, sizeof(playerpos));
screen_enableMapPreview((char *)"This string is written somewhere and then ignored.", ex, ey, playerpos);
screen_Upload(imageData, true);
free(imageData);
}
/// Loads the entire map just to show a picture of it /// Loads the entire map just to show a picture of it
void loadMapPreview(bool hideInterface) void loadMapPreview(bool hideInterface)
{ {
@ -417,8 +443,22 @@ void loadMapPreview(bool hideInterface)
} }
// load the terrain types // load the terrain types
psLevel = levFindDataSet(game.map); psLevel = levFindDataSet(game.map, &game.hash);
ASSERT_OR_RETURN(, psLevel != NULL, "Could not find level dataset!"); if (psLevel == NULL)
{
debug(LOG_INFO, "Could not find level dataset \"%s\" %s. Probably waiting for download.", game.map, game.hash.toString().c_str());
loadEmptyMapPreview();
return;
}
setCurrentMap(psLevel->realFileName, psLevel->players);
if (psLevel->realFileName == NULL)
{
debug(LOG_WZ, "Loading map preview: \"%s\" builtin t%d", psLevel->pName, psLevel->dataDir);
}
else
{
debug(LOG_WZ, "Loading map preview: \"%s\" in \"%s\" %s t%d", psLevel->pName, psLevel->realFileName, psLevel->realFileHash.toString().c_str(), psLevel->dataDir);
}
rebuildSearchPath(psLevel->dataDir, false); rebuildSearchPath(psLevel->dataDir, false);
sstrcpy(aFileName,psLevel->apDataFiles[0]); sstrcpy(aFileName,psLevel->apDataFiles[0]);
aFileName[strlen(aFileName)-4] = '\0'; aFileName[strlen(aFileName)-4] = '\0';
@ -2942,7 +2982,8 @@ static void processMultiopWidgets(UDWORD id)
debug(LOG_NET, "MULTIOP_HOST enabled"); debug(LOG_NET, "MULTIOP_HOST enabled");
sstrcpy(game.name, widgGetString(psWScreen, MULTIOP_GNAME)); // game name sstrcpy(game.name, widgGetString(psWScreen, MULTIOP_GNAME)); // game name
sstrcpy(sPlayer, widgGetString(psWScreen, MULTIOP_PNAME)); // pname sstrcpy(sPlayer, widgGetString(psWScreen, MULTIOP_PNAME)); // pname
sstrcpy(game.map, widgGetString(psWScreen, MULTIOP_MAP)); // add the name // Should not set game.map or game.hash here, since MULTIOP_MAP's string came from game.map in the first place, anyway. Wouldn't know what to set the hash to, and clearing it means selecting the first map with the right name.
//sstrcpy(game.map, widgGetString(psWScreen, MULTIOP_MAP)); // add the name
resetReadyStatus(false); resetReadyStatus(false);
resetDataHash(); resetDataHash();
@ -3498,7 +3539,7 @@ void frontendMultiMessages(void)
void runMultiOptions(void) void runMultiOptions(void)
{ {
static UDWORD lastrefresh = 0; static UDWORD lastrefresh = 0;
UDWORD id, value, i; UDWORD id, i;
char sTemp[128], oldGameMap[128]; char sTemp[128], oldGameMap[128];
int oldMaxPlayers; int oldMaxPlayers;
PLAYERSTATS playerStats; PLAYERSTATS playerStats;
@ -3574,9 +3615,12 @@ void runMultiOptions(void)
if(multiRequestUp) if(multiRequestUp)
{ {
id = widgRunScreen(psRScreen); // a requester box is up. id = widgRunScreen(psRScreen); // a requester box is up.
LEVEL_DATASET *mapData;
bool isHoverPreview; bool isHoverPreview;
if (runMultiRequester(id, &id, (char *)&sTemp, &value, &isHoverPreview)) if (runMultiRequester(id, &id, (char *)&sTemp, &mapData, &isHoverPreview))
{ {
Sha256 oldGameHash;
switch(id) switch(id)
{ {
case MULTIOP_PNAME: case MULTIOP_PNAME:
@ -3594,22 +3638,27 @@ void runMultiOptions(void)
netPlayersUpdated = true; netPlayersUpdated = true;
break; break;
case MULTIOP_MAP: case MULTIOP_MAP:
{
sstrcpy(oldGameMap, game.map); sstrcpy(oldGameMap, game.map);
oldGameHash = game.hash;
oldMaxPlayers = game.maxPlayers; oldMaxPlayers = game.maxPlayers;
sstrcpy(game.map, sTemp); sstrcpy(game.map, mapData->pName);
game.maxPlayers = value; game.hash = levGetFileHash(mapData);
game.maxPlayers = mapData->players;
loadMapPreview(!isHoverPreview); loadMapPreview(!isHoverPreview);
if (isHoverPreview) if (isHoverPreview)
{ {
sstrcpy(game.map, oldGameMap); sstrcpy(game.map, oldGameMap);
game.hash = oldGameHash;
game.maxPlayers = oldMaxPlayers; game.maxPlayers = oldMaxPlayers;
} }
widgSetString(psWScreen,MULTIOP_MAP,sTemp); widgSetString(psWScreen, MULTIOP_MAP, mapData->pName);
addGameOptions(); addGameOptions();
break; break;
}
default: default:
loadMapPreview(false); // Restore the preview of the old map. loadMapPreview(false); // Restore the preview of the old map.
break; break;
@ -3709,6 +3758,7 @@ bool startMultiOptions(bool bReenter)
game.type = SKIRMISH; game.type = SKIRMISH;
game.scavengers = false; game.scavengers = false;
sstrcpy(game.map, DEFAULTSKIRMISHMAP); sstrcpy(game.map, DEFAULTSKIRMISHMAP);
game.hash = levGetMapNameHash(game.map);
game.maxPlayers = 4; game.maxPlayers = 4;
} }
@ -3733,6 +3783,7 @@ bool startMultiOptions(bool bReenter)
challenge.beginGroup("challenge"); challenge.beginGroup("challenge");
sstrcpy(game.map, challenge.value("Map", game.map).toString().toAscii().constData()); sstrcpy(game.map, challenge.value("Map", game.map).toString().toAscii().constData());
game.hash = levGetMapNameHash(game.map);
game.maxPlayers = challenge.value("MaxPlayers", game.maxPlayers).toInt(); // TODO, read from map itself, not here!! game.maxPlayers = challenge.value("MaxPlayers", game.maxPlayers).toInt(); // TODO, read from map itself, not here!!
game.scavengers = challenge.value("Scavengers", game.scavengers).toInt(); game.scavengers = challenge.value("Scavengers", game.scavengers).toInt();
game.alliance = ALLIANCES_TEAMS; game.alliance = ALLIANCES_TEAMS;

View File

@ -196,7 +196,7 @@ static void SetPlayerTextColor( int mode, UDWORD player )
// //////////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////////////
// enumerates maps in the gamedesc file. // enumerates maps in the gamedesc file.
// returns only maps that are valid the right 'type' // returns only maps that are valid the right 'type'
static char* enumerateMultiMaps(UDWORD* players, bool first, unsigned int camToUse, unsigned int numPlayers) static LEVEL_DATASET *enumerateMultiMaps(bool first, unsigned camToUse, unsigned numPlayers)
{ {
static LEVEL_DATASET *lev; static LEVEL_DATASET *lev;
unsigned int cam; unsigned int cam;
@ -226,16 +226,8 @@ static char* enumerateMultiMaps(UDWORD* players, bool first, unsigned int camToU
&& (numPlayers == 0 || numPlayers == lev->players) && (numPlayers == 0 || numPlayers == lev->players)
&& cam == camToUse ) && cam == camToUse )
{ {
char* const found = strdup(lev->pName); LEVEL_DATASET *found = lev;
if (found == NULL)
{
debug(LOG_FATAL, "Out of memory");
// No way to indicate out-of-memory failure by return value
abort();
return NULL;
}
*players = lev->players;
lev = lev->psNext; lev = lev->psNext;
return found; return found;
} }
@ -261,16 +253,8 @@ static char* enumerateMultiMaps(UDWORD* players, bool first, unsigned int camToU
&& (numPlayers == 0 || numPlayers == lev->players) && (numPlayers == 0 || numPlayers == lev->players)
&& cam == camToUse ) && cam == camToUse )
{ {
char* const found = strdup(lev->pName); LEVEL_DATASET *found = lev;
if (found == NULL)
{
debug(LOG_FATAL, "Out of memory");
// No way to indicate out-of-memory failure by return value
abort();
return NULL;
}
*players = lev->players;
lev = lev->psNext; lev = lev->psNext;
return found; return found;
} }
@ -285,13 +269,13 @@ static char* enumerateMultiMaps(UDWORD* players, bool first, unsigned int camToU
// //////////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////////////
void displayRequestOption(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset, PIELIGHT *pColours) void displayRequestOption(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset, PIELIGHT *pColours)
{ {
LEVEL_DATASET *mapData = (LEVEL_DATASET *)psWidget->pUserData;
UDWORD x = xOffset+psWidget->x; UDWORD x = xOffset+psWidget->x;
UDWORD y = yOffset+psWidget->y; UDWORD y = yOffset+psWidget->y;
UDWORD count;
char butString[255]; char butString[255];
strcpy(butString,((W_BUTTON *)psWidget)->pTip); sstrcpy(butString, ((W_BUTTON *)psWidget)->pTip);
drawBlueBox(x,y,psWidget->width,psWidget->height); //draw box drawBlueBox(x,y,psWidget->width,psWidget->height); //draw box
@ -305,10 +289,36 @@ void displayRequestOption(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset, PIEL
iV_DrawText(butString, x + 6, y + 12); //draw text iV_DrawText(butString, x + 6, y + 12); //draw text
// if map, then draw no. of players. if (mapData != NULL)
for(count=0;count<psWidget->UserData;count++)
{ {
iV_DrawImage(FrontImages,IMAGE_WEE_GUY,(x+(6*count)+6),y+16); // Display map hash, so we can see the difference between identically named maps.
Sha256 hash = mapData->realFileHash; // levGetFileHash can be slightly expensive.
static uint32_t lastHashTime = 0;
if (lastHashTime != realTime && hash.isZero())
{
hash = levGetFileHash(mapData);
if (!hash.isZero())
{
lastHashTime = realTime; // We just calculated a hash. Don't calculate any more hashes this frame.
}
}
if (!hash.isZero())
{
iV_SetFont(font_small);
iV_SetTextColour(WZCOL_TEXT_DARK);
sstrcpy(butString, hash.toString().c_str());
while (iV_GetTextWidth(butString) > psWidget->width - 10 - (8 + mapData->players*6))
{
butString[strlen(butString) - 1] = '\0';
}
iV_DrawText(butString, x + 6 + 8 + mapData->players*6, y + 26);
}
// if map, then draw no. of players.
for (int count = 0; count < mapData->players; ++count)
{
iV_DrawImage(FrontImages, IMAGE_WEE_GUY, x + 6*count + 6, y + 16);
}
} }
} }
@ -376,7 +386,6 @@ static unsigned int check_tip_index(unsigned int i) {
*/ */
void addMultiRequest(const char* searchDir, const char* fileExtension, UDWORD mode, UBYTE mapCam, UBYTE numPlayers) void addMultiRequest(const char* searchDir, const char* fileExtension, UDWORD mode, UBYTE mapCam, UBYTE numPlayers)
{ {
UDWORD players;
char** fileList; char** fileList;
char** currFile; char** currFile;
const unsigned int extensionLength = strlen(fileExtension); const unsigned int extensionLength = strlen(fileExtension);
@ -415,16 +424,11 @@ void addMultiRequest(const char* searchDir, const char* fileExtension, UDWORD mo
if(mode == MULTIOP_MAP) // if its a map, also look in the predone stuff. if(mode == MULTIOP_MAP) // if its a map, also look in the predone stuff.
{ {
char* map; bool first = true;
if ((map = enumerateMultiMaps(&players, true, mapCam, numPlayers))) while (enumerateMultiMaps(first, mapCam, numPlayers) != NULL)
{ {
free(map); first = false;
numButtons++; numButtons++;
while ((map = enumerateMultiMaps(&players, false, mapCam, numPlayers)))
{
free(map);
numButtons++;
}
} }
} }
@ -532,6 +536,8 @@ void addMultiRequest(const char* searchDir, const char* fileExtension, UDWORD mo
if(mode == MULTIOP_MAP) // if its a map, set player flag. if(mode == MULTIOP_MAP) // if its a map, set player flag.
{ {
ASSERT(false, "Confusing code, can we even get here?");
const char* mapText; const char* mapText;
unsigned int mapTextLength; unsigned int mapTextLength;
@ -574,36 +580,35 @@ void addMultiRequest(const char* searchDir, const char* fileExtension, UDWORD mo
if(mode == MULTIOP_MAP) if(mode == MULTIOP_MAP)
{ {
char* mapName; LEVEL_DATASET *mapData;
if ((mapName = enumerateMultiMaps(&players, true, mapCam, numPlayers))) bool first = true;
while ((mapData = enumerateMultiMaps(first, mapCam, numPlayers)) != NULL)
{ {
do first = false;
unsigned int tip_index = check_tip_index(sButInit.id-M_REQUEST_BUT);
// add number of players to string.
sstrcpy(tips[tip_index], mapData->pName);
sButInit.pTip = tips[tip_index];
sButInit.pText = tips[tip_index];
sButInit.pUserData = mapData;
widgAddButton(psRScreen, &sButInit);
sButInit.id += 1;
sButInit.x = (SWORD)(sButInit.x + (R_BUT_W+ 4));
if (sButInit.x + R_BUT_W+ 2 > M_REQUEST_W)
{ {
unsigned int tip_index = check_tip_index(sButInit.id-M_REQUEST_BUT); sButInit.x = buttonsX;
sButInit.y = (SWORD)(sButInit.y +R_BUT_H + 4);
// add number of players to string. }
sstrcpy(tips[tip_index], mapName); if (sButInit.y +R_BUT_H + 4 > M_REQUEST_H)
free(mapName); {
sButInit.y = 4;
sButInit.pTip = tips[tip_index]; sButInit.majorID += 1;
sButInit.pText = tips[tip_index]; }
sButInit.UserData = players;
widgAddButton(psRScreen, &sButInit);
sButInit.id += 1;
sButInit.x = (SWORD)(sButInit.x + (R_BUT_W+ 4));
if (sButInit.x + R_BUT_W+ 2 > M_REQUEST_W)
{
sButInit.x = buttonsX;
sButInit.y = (SWORD)(sButInit.y +R_BUT_H + 4);
}
if (sButInit.y +R_BUT_H + 4 > M_REQUEST_H)
{
sButInit.y = 4;
sButInit.majorID += 1;
}
} while ((mapName = enumerateMultiMaps(&players, false, mapCam, numPlayers)));
} }
} }
multiRequestUp = true; multiRequestUp = true;
@ -669,7 +674,7 @@ static void closeMultiRequester(void)
return; return;
} }
bool runMultiRequester(UDWORD id, UDWORD *mode, char *chosen, UDWORD *chosenValue, bool *isHoverPreview) bool runMultiRequester(UDWORD id, UDWORD *mode, char *chosen, LEVEL_DATASET **chosenValue, bool *isHoverPreview)
{ {
static unsigned hoverId = 0; static unsigned hoverId = 0;
static unsigned hoverStartTime = 0; static unsigned hoverStartTime = 0;
@ -700,7 +705,7 @@ bool runMultiRequester(UDWORD id, UDWORD *mode, char *chosen, UDWORD *chosenValu
{ {
strcpy(chosen,((W_BUTTON *)widgGetFromID(psRScreen,id))->pText ); strcpy(chosen,((W_BUTTON *)widgGetFromID(psRScreen,id))->pText );
*chosenValue = ((W_BUTTON *)widgGetFromID(psRScreen,id))->UserData ; *chosenValue = (LEVEL_DATASET *)((W_BUTTON *)widgGetFromID(psRScreen,id))->pUserData;
*mode = context; *mode = context;
*isHoverPreview = hoverPreview; *isHoverPreview = hoverPreview;
hoverPreviewId = id; hoverPreviewId = id;

View File

@ -31,7 +31,7 @@
extern void addMultiRequest(const char* searchDir, const char* fileExtension, UDWORD id,UBYTE mapCam, UBYTE numPlayers); extern void addMultiRequest(const char* searchDir, const char* fileExtension, UDWORD id,UBYTE mapCam, UBYTE numPlayers);
extern bool multiRequestUp; extern bool multiRequestUp;
extern W_SCREEN *psRScreen; // requester stuff. extern W_SCREEN *psRScreen; // requester stuff.
bool runMultiRequester(UDWORD id, UDWORD *mode, char *chosen, UDWORD *chosenValue, bool *isHoverPreview); bool runMultiRequester(UDWORD id, UDWORD *mode, char *chosen, LEVEL_DATASET **chosenValue, bool *isHoverPreview);
extern void displayRequestOption(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset, PIELIGHT *pColours); extern void displayRequestOption(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset, PIELIGHT *pColours);
// multimenu // multimenu

View File

@ -59,7 +59,6 @@
// send complete game info set! // send complete game info set!
void sendOptions() void sendOptions()
{ {
bool dummy = true;
unsigned int i; unsigned int i;
if (!NetPlay.isHost || !bHosted) // Only host should act, and only if the game hasn't started yet. if (!NetPlay.isHost || !bHosted) // Only host should act, and only if the game hasn't started yet.
@ -73,9 +72,9 @@ void sendOptions()
// First send information about the game // First send information about the game
NETuint8_t(&game.type); NETuint8_t(&game.type);
NETstring(game.map, 128); NETstring(game.map, 128);
NETbin(game.hash.bytes, game.hash.Bytes);
NETuint8_t(&game.maxPlayers); NETuint8_t(&game.maxPlayers);
NETstring(game.name, 128); NETstring(game.name, 128);
NETbool(&dummy);
NETuint32_t(&game.power); NETuint32_t(&game.power);
NETuint8_t(&game.base); NETuint8_t(&game.base);
NETuint8_t(&game.alliance); NETuint8_t(&game.alliance);
@ -118,31 +117,11 @@ void sendOptions()
NETend(); NETend();
} }
// ////////////////////////////////////////////////////////////////////////////
/*!
* check the wdg files that are being used.
*/
static bool checkGameWdg(const char *nm)
{
LEVEL_DATASET *lev;
for (lev = psLevels; lev; lev = lev->psNext)
{
if (strcmp(lev->pName, nm) == 0)
{
return true;
}
}
return false;
}
// //////////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////////////
// options for a game. (usually recvd in frontend) // options for a game. (usually recvd in frontend)
void recvOptions(NETQUEUE queue) void recvOptions(NETQUEUE queue)
{ {
unsigned int i; unsigned int i;
bool dummy = true;
debug(LOG_NET, "Receiving options from host"); debug(LOG_NET, "Receiving options from host");
NETbeginDecode(queue, NET_OPTIONS); NETbeginDecode(queue, NET_OPTIONS);
@ -150,9 +129,9 @@ void recvOptions(NETQUEUE queue)
// Get general information about the game // Get general information about the game
NETuint8_t(&game.type); NETuint8_t(&game.type);
NETstring(game.map, 128); NETstring(game.map, 128);
NETbin(game.hash.bytes, game.hash.Bytes);
NETuint8_t(&game.maxPlayers); NETuint8_t(&game.maxPlayers);
NETstring(game.name, 128); NETstring(game.name, 128);
NETbool(&dummy);
NETuint32_t(&game.power); NETuint32_t(&game.power);
NETuint8_t(&game.base); NETuint8_t(&game.base);
NETuint8_t(&game.alliance); NETuint8_t(&game.alliance);
@ -219,10 +198,11 @@ void recvOptions(NETQUEUE queue)
// clear out the old level list. // clear out the old level list.
levShutDown(); levShutDown();
levInitialise(); levInitialise();
setCurrentMap(NULL, 42);
rebuildSearchPath(mod_multiplay, true); // MUST rebuild search path for the new maps we just got! rebuildSearchPath(mod_multiplay, true); // MUST rebuild search path for the new maps we just got!
buildMapList(); buildMapList();
// See if we have the map or not // See if we have the map or not
if (!checkGameWdg(game.map)) if (levFindDataSet(game.map, &game.hash) == NULL)
{ {
uint32_t player = selectedPlayer; uint32_t player = selectedPlayer;

View File

@ -1589,7 +1589,7 @@ bool recvDestroyFeature(NETQUEUE queue)
// Network File packet processor. // Network File packet processor.
bool recvMapFileRequested(NETQUEUE queue) bool recvMapFileRequested(NETQUEUE queue)
{ {
char mapStr[256],mapName[256],fixedname[256]; //char mapStr[256],mapName[256],fixedname[256];
uint32_t player; uint32_t player;
PHYSFS_sint64 fileSize_64; PHYSFS_sint64 fileSize_64;
@ -1612,30 +1612,11 @@ bool recvMapFileRequested(NETQUEUE queue)
NetPlay.players[player].wzFile.isCancelled = false; NetPlay.players[player].wzFile.isCancelled = false;
NetPlay.players[player].wzFile.isSending = true; NetPlay.players[player].wzFile.isSending = true;
memset(mapStr,0,256); LEVEL_DATASET *mapData = levFindDataSet(game.map, &game.hash);
memset(mapName,0,256);
memset(fixedname,0,256);
addConsoleMessage("Map was requested: SENDING MAP!",DEFAULT_JUSTIFY, SYSTEM_MESSAGE); addConsoleMessage("Map was requested: SENDING MAP!",DEFAULT_JUSTIFY, SYSTEM_MESSAGE);
sstrcpy(mapName, game.map); char *mapStr = mapData->realFileName;
if ( strstr(mapName,"-T1") != 0
|| strstr(mapName,"-T2") != 0
|| strstr(mapName,"-T3") != 0)
{
// chop off the -T1 *only when needed!*
mapName[strlen(game.map)-3] = 0; // chop off the -T1 etc..
}
// chop off the sk- if required.
if(strncmp(mapName,"Sk-",3) == 0)
{
sstrcpy(mapStr, &(mapName[3]));
sstrcpy(mapName, mapStr);
}
snprintf(mapStr, sizeof(mapStr), "%dc-%s.wz", game.maxPlayers, mapName);
snprintf(fixedname, sizeof(fixedname), "maps/%s", mapStr); //We know maps are in /maps dir...now. fix for linux -Q
sstrcpy(mapStr, fixedname);
debug(LOG_NET, "Map was requested. Looking for %s", mapStr); debug(LOG_NET, "Map was requested. Looking for %s", mapStr);
// Checking to see if file is available... // Checking to see if file is available...
@ -1650,7 +1631,7 @@ bool recvMapFileRequested(NETQUEUE queue)
NETbeginEncode(NETbroadcastQueue(), NET_HOST_DROPPED); NETbeginEncode(NETbroadcastQueue(), NET_HOST_DROPPED);
NETend(); NETend();
abort(); abort();
} }
// get the file's size. // get the file's size.
fileSize_64 = PHYSFS_fileLength(pFileHandle); fileSize_64 = PHYSFS_fileLength(pFileHandle);
@ -1660,7 +1641,7 @@ bool recvMapFileRequested(NETQUEUE queue)
NetPlay.players[player].wzFile.fileSize_32 = (int32_t) fileSize_64; //we don't support 64bit int nettypes. NetPlay.players[player].wzFile.fileSize_32 = (int32_t) fileSize_64; //we don't support 64bit int nettypes.
NetPlay.players[player].wzFile.currPos = 0; NetPlay.players[player].wzFile.currPos = 0;
NETsendFile(mapStr, player); NETsendFile(game.map, game.hash, player);
} }
return true; return true;
} }
@ -1669,20 +1650,19 @@ bool recvMapFileRequested(NETQUEUE queue)
void sendMap(void) void sendMap(void)
{ {
int i = 0; int i = 0;
UBYTE done;
for (i = 0; i < MAX_PLAYERS; i++) for (i = 0; i < MAX_PLAYERS; i++)
{ {
if (NetPlay.players[i].wzFile.isSending) if (NetPlay.players[i].wzFile.isSending)
{ {
done = NETsendFile(game.map, i); int done = NETsendFile(game.map, game.hash, i);
if (done == 100) if (done == 100)
{ {
addConsoleMessage("MAP SENT!",DEFAULT_JUSTIFY, SYSTEM_MESSAGE); addConsoleMessage("MAP SENT!",DEFAULT_JUSTIFY, SYSTEM_MESSAGE);
debug(LOG_NET, "=== File has been sent to player %d ===", i); debug(LOG_NET, "=== File has been sent to player %d ===", i);
NetPlay.players[i].wzFile.isSending = false; NetPlay.players[i].wzFile.isSending = false;
NetPlay.players[i].needFile = false; NetPlay.players[i].needFile = false;
} }
} }
} }
} }
@ -1705,6 +1685,7 @@ bool recvMapFileData(NETQUEUE queue)
{ {
return false; return false;
} }
loadMapPreview(false);
return true; return true;
} }

View File

@ -28,6 +28,7 @@
#include "group.h" #include "group.h"
#include "featuredef.h" #include "featuredef.h"
#include "droid.h" // For INITIAL_DROID_ORDERS. #include "droid.h" // For INITIAL_DROID_ORDERS.
#include "levels.h" // For LevelHashSize.
// ///////////////////////////////////////////////////////////////////////////////////////////////// // /////////////////////////////////////////////////////////////////////////////////////////////////
// Game Options Structure. Enough info to completely describe the static stuff in a multiplayer game. // Game Options Structure. Enough info to completely describe the static stuff in a multiplayer game.
@ -39,6 +40,7 @@ struct MULTIPLAYERGAME
char map[128]; // name of multiplayer map being used. char map[128]; // name of multiplayer map being used.
uint8_t maxPlayers; // max players to allow uint8_t maxPlayers; // max players to allow
char name[128]; // game name (to be used) char name[128]; // game name (to be used)
Sha256 hash; ///< Hash of map file. Zero if built in.
uint32_t power; // power level for arena game uint32_t power; // power level for arena game
uint8_t base; // clean/base/base&defence uint8_t base; // clean/base/base&defence
uint8_t alliance; // no/yes/AIs vs Humans uint8_t alliance; // no/yes/AIs vs Humans

View File

@ -158,14 +158,14 @@ QScriptValue convStructure(STRUCTURE *psStruct, QScriptEngine *engine)
value.setProperty("stattype", (int)REF_WALL, QScriptValue::ReadOnly); value.setProperty("stattype", (int)REF_WALL, QScriptValue::ReadOnly);
break; break;
case REF_BLASTDOOR: case REF_BLASTDOOR:
value.setProperty("stattype", (int)REF_DEFENSE, QScriptValue::ReadOnly);
break;
case REF_DEFENSE: case REF_DEFENSE:
if (isLasSat(psStruct->pStructureType)) if (isLasSat(psStruct->pStructureType))
{ {
value.setProperty("stattype", (int)FAKE_REF_LASSAT, QScriptValue::ReadOnly); value.setProperty("stattype", (int)FAKE_REF_LASSAT, QScriptValue::ReadOnly);
break; break;
} }
value.setProperty("stattype", (int)REF_DEFENSE, QScriptValue::ReadOnly);
break;
default: default:
value.setProperty("stattype", (int)psStruct->pStructureType->type, QScriptValue::ReadOnly); value.setProperty("stattype", (int)psStruct->pStructureType->type, QScriptValue::ReadOnly);
break; break;
@ -426,7 +426,7 @@ bool loadLabels(const char *filename)
{ {
p.p1 = ini.vector2i("pos"); p.p1 = ini.vector2i("pos");
p.p2 = p.p1; p.p2 = p.p1;
p.type = POSITION; p.type = SCRIPT_POSITION;
p.player = -1; p.player = -1;
p.id = -1; p.id = -1;
labels.insert(label, p); labels.insert(label, p);
@ -435,7 +435,7 @@ bool loadLabels(const char *filename)
{ {
p.p1 = ini.vector2i("pos1"); p.p1 = ini.vector2i("pos1");
p.p2 = ini.vector2i("pos2"); p.p2 = ini.vector2i("pos2");
p.type = AREA; p.type = SCRIPT_AREA;
p.player = -1; p.player = -1;
p.id = -1; p.id = -1;
labels.insert(label, p); labels.insert(label, p);
@ -470,14 +470,14 @@ bool writeLabels(const char *filename)
{ {
QString key = i.key(); QString key = i.key();
labeltype l = i.value(); labeltype l = i.value();
if (l.type == POSITION) if (l.type == SCRIPT_POSITION)
{ {
ini.beginGroup("position_" + QString::number(c[0]++)); ini.beginGroup("position_" + QString::number(c[0]++));
ini.setVector2i("pos", l.p1); ini.setVector2i("pos", l.p1);
ini.setValue("label", key); ini.setValue("label", key);
ini.endGroup(); ini.endGroup();
} }
else if (l.type == AREA) else if (l.type == SCRIPT_AREA)
{ {
ini.beginGroup("area_" + QString::number(c[1]++)); ini.beginGroup("area_" + QString::number(c[1]++));
ini.setVector2i("pos1", l.p1); ini.setVector2i("pos1", l.p1);
@ -530,12 +530,13 @@ static QScriptValue js_label(QScriptContext *context, QScriptEngine *engine)
if (labels.contains(label)) if (labels.contains(label))
{ {
labeltype p = labels.value(label); labeltype p = labels.value(label);
if (p.type == AREA || p.type == POSITION) if (p.type == SCRIPT_AREA || p.type == SCRIPT_POSITION)
{ {
ret.setProperty("x", map_coord(p.p1.x), QScriptValue::ReadOnly); ret.setProperty("x", map_coord(p.p1.x), QScriptValue::ReadOnly);
ret.setProperty("y", map_coord(p.p1.y), QScriptValue::ReadOnly); ret.setProperty("y", map_coord(p.p1.y), QScriptValue::ReadOnly);
ret.setProperty("type", p.type, QScriptValue::ReadOnly);
} }
if (p.type == AREA) if (p.type == SCRIPT_AREA)
{ {
ret.setProperty("x2", map_coord(p.p2.x), QScriptValue::ReadOnly); ret.setProperty("x2", map_coord(p.p2.x), QScriptValue::ReadOnly);
ret.setProperty("xy", map_coord(p.p2.y), QScriptValue::ReadOnly); ret.setProperty("xy", map_coord(p.p2.y), QScriptValue::ReadOnly);
@ -2517,6 +2518,34 @@ static QScriptValue js_hackNetOn(QScriptContext *, QScriptEngine *)
return QScriptValue(); return QScriptValue();
} }
//-- \subsection{getDroidLimit([player[, unit type]])}
//-- Return maximum number of droids that this player can produce. This limit is usually
//-- fixed throughout a game and the same for all players. If no arguments are passed,
//-- returns general unit limit for the current player. If a second, unit type argument
//-- is passed, the limit for this unit type is returned, which may be different from
//-- the general unit limit (eg for commanders and construction droids).
static QScriptValue js_getDroidLimit(QScriptContext *context, QScriptEngine *engine)
{
if (context->argumentCount() > 1)
{
DROID_TYPE type = (DROID_TYPE)context->argument(1).toInt32();
if (type == DROID_COMMAND)
{
return QScriptValue(MAX_COMMAND_DROIDS);
}
else if (type == DROID_CONSTRUCT)
{
return QScriptValue(MAX_CONSTRUCTOR_DROIDS);
}
// else return general unit limit
}
if (context->argumentCount() > 0)
{
return QScriptValue(getMaxDroids(context->argument(0).toInt32()));
}
return QScriptValue(getMaxDroids(engine->globalObject().property("me").toInt32()));
}
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
// Register functions with scripting system // Register functions with scripting system
@ -2572,6 +2601,7 @@ bool registerFunctions(QScriptEngine *engine)
engine->globalObject().setProperty("safeDest", engine->newFunction(js_safeDest)); engine->globalObject().setProperty("safeDest", engine->newFunction(js_safeDest));
engine->globalObject().setProperty("activateStructure", engine->newFunction(js_activateStructure)); engine->globalObject().setProperty("activateStructure", engine->newFunction(js_activateStructure));
engine->globalObject().setProperty("chat", engine->newFunction(js_chat)); engine->globalObject().setProperty("chat", engine->newFunction(js_chat));
engine->globalObject().setProperty("getDroidLimit", engine->newFunction(js_getDroidLimit));
// Functions that operate on the current player only // Functions that operate on the current player only
engine->globalObject().setProperty("centreView", engine->newFunction(js_centreView)); engine->globalObject().setProperty("centreView", engine->newFunction(js_centreView));
@ -2672,11 +2702,13 @@ bool registerFunctions(QScriptEngine *engine)
engine->globalObject().setProperty("STRUCTURE", OBJ_STRUCTURE, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("STRUCTURE", OBJ_STRUCTURE, QScriptValue::ReadOnly | QScriptValue::Undeletable);
engine->globalObject().setProperty("DROID", OBJ_DROID, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("DROID", OBJ_DROID, QScriptValue::ReadOnly | QScriptValue::Undeletable);
engine->globalObject().setProperty("FEATURE", OBJ_FEATURE, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("FEATURE", OBJ_FEATURE, QScriptValue::ReadOnly | QScriptValue::Undeletable);
engine->globalObject().setProperty("POSITION", POSITION, QScriptValue::ReadOnly | QScriptValue::Undeletable);
engine->globalObject().setProperty("AREA", AREA, QScriptValue::ReadOnly | QScriptValue::Undeletable);
engine->globalObject().setProperty("ALL_PLAYERS", ALL_PLAYERS, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("ALL_PLAYERS", ALL_PLAYERS, QScriptValue::ReadOnly | QScriptValue::Undeletable);
engine->globalObject().setProperty("ALLIES", ALLIES, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("ALLIES", ALLIES, QScriptValue::ReadOnly | QScriptValue::Undeletable);
engine->globalObject().setProperty("ENEMIES", ENEMIES, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("ENEMIES", ENEMIES, QScriptValue::ReadOnly | QScriptValue::Undeletable);
engine->globalObject().setProperty("POSITION", SCRIPT_POSITION, QScriptValue::ReadOnly | QScriptValue::Undeletable);
engine->globalObject().setProperty("AREA", SCRIPT_AREA, QScriptValue::ReadOnly | QScriptValue::Undeletable);
engine->globalObject().setProperty("PLAYER_DATA", SCRIPT_PLAYER, QScriptValue::ReadOnly | QScriptValue::Undeletable);
engine->globalObject().setProperty("RESEARCH_DATA", SCRIPT_RESEARCH, QScriptValue::ReadOnly | QScriptValue::Undeletable);
// Static knowledge about players // Static knowledge about players
//== \item[playerData] An array of information about the players in a game. Each item in the array is an object //== \item[playerData] An array of information about the players in a game. Each item in the array is an object
@ -2693,6 +2725,7 @@ bool registerFunctions(QScriptEngine *engine)
vector.setProperty("team", NetPlay.players[i].team, QScriptValue::ReadOnly | QScriptValue::Undeletable); vector.setProperty("team", NetPlay.players[i].team, QScriptValue::ReadOnly | QScriptValue::Undeletable);
vector.setProperty("isAI", !NetPlay.players[i].allocated && NetPlay.players[i].ai >= 0, QScriptValue::ReadOnly | QScriptValue::Undeletable); vector.setProperty("isAI", !NetPlay.players[i].allocated && NetPlay.players[i].ai >= 0, QScriptValue::ReadOnly | QScriptValue::Undeletable);
vector.setProperty("isHuman", NetPlay.players[i].allocated, QScriptValue::ReadOnly | QScriptValue::Undeletable); vector.setProperty("isHuman", NetPlay.players[i].allocated, QScriptValue::ReadOnly | QScriptValue::Undeletable);
vector.setProperty("type", SCRIPT_PLAYER, QScriptValue::ReadOnly | QScriptValue::Undeletable);
playerData.setProperty(i, vector, QScriptValue::ReadOnly | QScriptValue::Undeletable); playerData.setProperty(i, vector, QScriptValue::ReadOnly | QScriptValue::Undeletable);
} }
engine->globalObject().setProperty("playerData", playerData, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("playerData", playerData, QScriptValue::ReadOnly | QScriptValue::Undeletable);
@ -2708,6 +2741,7 @@ bool registerFunctions(QScriptEngine *engine)
QScriptValue vector = engine->newObject(); QScriptValue vector = engine->newObject();
vector.setProperty("x", map_coord(positions[i].x), QScriptValue::ReadOnly | QScriptValue::Undeletable); vector.setProperty("x", map_coord(positions[i].x), QScriptValue::ReadOnly | QScriptValue::Undeletable);
vector.setProperty("y", map_coord(positions[i].y), QScriptValue::ReadOnly | QScriptValue::Undeletable); vector.setProperty("y", map_coord(positions[i].y), QScriptValue::ReadOnly | QScriptValue::Undeletable);
vector.setProperty("type", SCRIPT_POSITION, QScriptValue::ReadOnly | QScriptValue::Undeletable);
startPositions.setProperty(i, vector, QScriptValue::ReadOnly | QScriptValue::Undeletable); startPositions.setProperty(i, vector, QScriptValue::ReadOnly | QScriptValue::Undeletable);
} }
QScriptValue derrickPositions = engine->newArray(derricks.size()); QScriptValue derrickPositions = engine->newArray(derricks.size());
@ -2716,6 +2750,7 @@ bool registerFunctions(QScriptEngine *engine)
QScriptValue vector = engine->newObject(); QScriptValue vector = engine->newObject();
vector.setProperty("x", map_coord(derricks[i].x), QScriptValue::ReadOnly | QScriptValue::Undeletable); vector.setProperty("x", map_coord(derricks[i].x), QScriptValue::ReadOnly | QScriptValue::Undeletable);
vector.setProperty("y", map_coord(derricks[i].y), QScriptValue::ReadOnly | QScriptValue::Undeletable); vector.setProperty("y", map_coord(derricks[i].y), QScriptValue::ReadOnly | QScriptValue::Undeletable);
vector.setProperty("type", SCRIPT_POSITION, QScriptValue::ReadOnly | QScriptValue::Undeletable);
derrickPositions.setProperty(i, vector, QScriptValue::ReadOnly | QScriptValue::Undeletable); derrickPositions.setProperty(i, vector, QScriptValue::ReadOnly | QScriptValue::Undeletable);
} }
engine->globalObject().setProperty("derrickPositions", derrickPositions, QScriptValue::ReadOnly | QScriptValue::Undeletable); engine->globalObject().setProperty("derrickPositions", derrickPositions, QScriptValue::ReadOnly | QScriptValue::Undeletable);

View File

@ -27,8 +27,10 @@
enum SCRIPT_TYPES enum SCRIPT_TYPES
{ {
POSITION = OBJ_NUM_TYPES, SCRIPT_POSITION = OBJ_NUM_TYPES,
AREA, SCRIPT_AREA,
SCRIPT_PLAYER,
SCRIPT_RESEARCH,
}; };
#include <QtScript/QScriptEngine> #include <QtScript/QScriptEngine>

View File

@ -5640,7 +5640,8 @@ bool scrGetGameStatus(void)
break; break;
case STATUS_DeliveryReposInProgress: case STATUS_DeliveryReposInProgress:
if (DeliveryReposValid()==true) bResult=true; if (deliveryReposValid())
bResult=true;
break; break;
default: default:

View File

@ -474,6 +474,8 @@ STRUCTURE_STATS::STRUCTURE_STATS(LineView line)
} }
std::fill_n(psWeapStat, STRUCT_MAXWEAPS, (WEAPON_STATS *)NULL); std::fill_n(psWeapStat, STRUCT_MAXWEAPS, (WEAPON_STATS *)NULL);
numWeaps = std::min<unsigned>(numWeaps, STRUCT_MAXWEAPS);
} }
/* load the Structure stats from the Access database */ /* load the Structure stats from the Access database */
@ -613,7 +615,7 @@ bool loadStructureWeapons(const char *pWeaponData, UDWORD bufferSize)
LineView line(table, i); LineView line(table, i);
STRUCTURE_STATS *structureStats = line.stats(0, asStructureStats, numStructureStats); STRUCTURE_STATS *structureStats = line.stats(0, asStructureStats, numStructureStats);
for (unsigned j = 0; j < structureStats->numWeaps && !table.isError(); ++j) for (unsigned j = 0; !table.isError() && j < structureStats->numWeaps; ++j)
{ {
structureStats->psWeapStat[j] = line.stats(1 + j, asWeaponStats, numWeaponStats); structureStats->psWeapStat[j] = line.stats(1 + j, asWeaponStats, numWeaponStats);
} }
@ -3406,61 +3408,45 @@ static void aiUpdateStructure(STRUCTURE *psStructure, bool isMission)
psReArmPad->timeLastUpdated = gameTime; psReArmPad->timeLastUpdated = gameTime;
} }
// dont rearm on remote pcs. /* do rearming */
// Huh?! Why not?! if(!bMultiPlayer || myResponsibility(psDroid->player)) UDWORD pointsRequired;
{
/* do rearming */
if (psDroid->sMove.iAttackRuns != 0)
{
UDWORD pointsRequired;
//amount required is a factor of the droids' weight //amount required is a factor of the droids' weight
pointsRequired = psDroid->weight / REARM_FACTOR; pointsRequired = psDroid->weight / REARM_FACTOR;
//take numWeaps into consideration //take numWeaps into consideration
pointsToAdd = psReArmPad->reArmPoints * (gameTime - psReArmPad->timeStarted) / pointsToAdd = psReArmPad->reArmPoints * (gameTime - psReArmPad->timeStarted) / GAME_TICKS_PER_SEC;
GAME_TICKS_PER_SEC; pointsAlreadyAdded = psReArmPad->reArmPoints * (psReArmPad->timeLastUpdated - psReArmPad->timeStarted) / GAME_TICKS_PER_SEC;
pointsAlreadyAdded = psReArmPad->reArmPoints * (psReArmPad->timeLastUpdated - psReArmPad->timeStarted) / if (pointsToAdd >= pointsRequired)
GAME_TICKS_PER_SEC; {
if (pointsToAdd >= pointsRequired) // We should be fully loaded by now.
for (i = 0; i < psDroid->numWeaps; i++)
{
// set rearm value to no runs made
psDroid->asWeaps[i].usedAmmo = 0;
// reset ammo and lastFired
psDroid->asWeaps[i].ammo = asWeaponStats[psDroid->asWeaps[i].nStat].numRounds;
psDroid->asWeaps[i].lastFired = 0;
}
}
else
{
for (i = 0; i < psDroid->numWeaps; i++)
{
// Make sure it's a rearmable weapon (and so we don't divide by zero)
if (psDroid->asWeaps[i].usedAmmo > 0 && asWeaponStats[psDroid->asWeaps[i].nStat].numRounds > 0)
{ {
// We should be fully loaded by now. // Do not "simplify" this formula.
for (i = 0; i < psDroid->numWeaps; i++) // It is written this way to prevent rounding errors.
int ammoToAddThisTime =
pointsToAdd*getNumAttackRuns(psDroid,i)/pointsRequired -
pointsAlreadyAdded*getNumAttackRuns(psDroid,i)/pointsRequired;
psDroid->asWeaps[i].usedAmmo -= std::min<unsigned>(ammoToAddThisTime, psDroid->asWeaps[i].usedAmmo);
if (ammoToAddThisTime)
{ {
// set rearm value to no runs made
psDroid->sMove.iAttackRuns[i] = 0;
// reset ammo and lastFired // reset ammo and lastFired
psDroid->asWeaps[i].ammo = asWeaponStats[psDroid->asWeaps[i].nStat].numRounds; psDroid->asWeaps[i].ammo = asWeaponStats[psDroid->asWeaps[i].nStat].numRounds;
psDroid->asWeaps[i].lastFired = 0; psDroid->asWeaps[i].lastFired = 0;
} break;
}
else
{
for (i = 0; i < psDroid->numWeaps; i++)
{
// Make sure it's a rearmable weapon (and so we don't divide by zero)
if (psDroid->sMove.iAttackRuns[i] > 0 && asWeaponStats[psDroid->asWeaps[i].nStat].numRounds > 0)
{
// Do not "simplify" this formula.
// It is written this way to prevent rounding errors.
int ammoToAddThisTime =
pointsToAdd*getNumAttackRuns(psDroid,i)/pointsRequired -
pointsAlreadyAdded*getNumAttackRuns(psDroid,i)/pointsRequired;
if (ammoToAddThisTime > psDroid->sMove.iAttackRuns[i])
{
psDroid->sMove.iAttackRuns[i] = 0;
}
else if (ammoToAddThisTime > 0)
{
psDroid->sMove.iAttackRuns[i] -= ammoToAddThisTime;
}
if (ammoToAddThisTime)
{
// reset ammo and lastFired
psDroid->asWeaps[i].ammo = asWeaponStats[psDroid->asWeaps[i].nStat].numRounds;
psDroid->asWeaps[i].lastFired = 0;
break;
}
}
} }
} }
} }
@ -4534,7 +4520,6 @@ static void removeStructFromMap(STRUCTURE *psStruct)
bool removeStruct(STRUCTURE *psDel, bool bDestroy) bool removeStruct(STRUCTURE *psDel, bool bDestroy)
{ {
bool resourceFound = false; bool resourceFound = false;
FACTORY *psFactory;
SDWORD cluster; SDWORD cluster;
FLAG_POSITION *psAssemblyPoint=NULL; FLAG_POSITION *psAssemblyPoint=NULL;
@ -4591,7 +4576,7 @@ bool removeStruct(STRUCTURE *psDel, bool bDestroy)
//if it is a factory - need to reset the factoryNumFlag //if it is a factory - need to reset the factoryNumFlag
if (StructIsFactory(psDel)) if (StructIsFactory(psDel))
{ {
psFactory = &psDel->pFunctionality->factory; FACTORY *psFactory = &psDel->pFunctionality->factory;
//need to initialise the production run as well //need to initialise the production run as well
cancelProduction(psDel, ModeImmediate); cancelProduction(psDel, ModeImmediate);
@ -4611,17 +4596,9 @@ bool removeStruct(STRUCTURE *psDel, bool bDestroy)
} }
//need to cancel the repositioning of the DP if selectedPlayer and currently moving //need to cancel the repositioning of the DP if selectedPlayer and currently moving
if (psDel->player == selectedPlayer) if (psDel->player == selectedPlayer && psAssemblyPoint->selected)
{ {
//if currently trying to place a DP cancelDeliveryRepos();
if (tryingToGetLocation())
{
//need to check if this factory's DP is trying to be re-positioned
if (psAssemblyPoint == sBuildDetails.UserData)
{
kill3DBuilding();
}
}
} }
} }
@ -5048,28 +5025,6 @@ void setFlagPositionInc(FUNCTIONALITY* pFunctionality, UDWORD player, UBYTE fact
ASSERT( false, "Can't set flag!"); ASSERT( false, "Can't set flag!");
} }
/* called from order.c.. delivery/assembly point handler*/
/*now called from display.c */
void processDeliveryPoint(UDWORD player, UDWORD x, UDWORD y)
{
FLAG_POSITION *psCurrFlag;//,*psFlag;//,*psNewFlag
for (psCurrFlag = apsFlagPosLists[player]; psCurrFlag; psCurrFlag = psCurrFlag->psNext)
{
// must be selected and have a valid pos.
if (psCurrFlag->selected)
{
setAssemblyPoint(psCurrFlag, x, y, player, true);
//deselect once moved
psCurrFlag->selected = false;
return; //will want to break if more than one can be selected?
}
}
}
/*called when a structure has been built - checks through the list of callbacks /*called when a structure has been built - checks through the list of callbacks
for the scripts*/ for the scripts*/
void structureCompletedCallback(STRUCTURE_STATS *psStructType) void structureCompletedCallback(STRUCTURE_STATS *psStructType)

View File

@ -183,9 +183,6 @@ extern bool checkStructureStatus( STRUCTURE_STATS *psStats, UDWORD player, UDWOR
extern void setAssemblyPoint(FLAG_POSITION *psAssemblyPoint, UDWORD x, UDWORD y, extern void setAssemblyPoint(FLAG_POSITION *psAssemblyPoint, UDWORD x, UDWORD y,
UDWORD player, bool bCheck); UDWORD player, bool bCheck);
/* consider delivery points when selected by player*/
extern void processDeliveryPoint(UDWORD player, UDWORD x, UDWORD y);
/*called when a structure has been built - checks through the list of callbacks /*called when a structure has been built - checks through the list of callbacks
for the scripts*/ for the scripts*/
extern void structureCompletedCallback(STRUCTURE_STATS *psStructType); extern void structureCompletedCallback(STRUCTURE_STATS *psStructType);

View File

@ -1437,6 +1437,7 @@ void transporterAddDroid(DROID *psTransporter, DROID *psDroidToAdd)
{ {
visRemoveVisibility((BASE_OBJECT *)psDroidToAdd); visRemoveVisibility((BASE_OBJECT *)psDroidToAdd);
} }
fpathRemoveDroidData(psDroidToAdd->id);
// This is called by droidRemove. But we still need to refresh after adding to the transporter group. // This is called by droidRemove. But we still need to refresh after adding to the transporter group.
intRefreshScreen(); intRefreshScreen();

View File

@ -47,18 +47,19 @@ struct WARZONE_GLOBALS
{ {
FMV_MODE FMVmode; FMV_MODE FMVmode;
SWORD effectsLevel; SWORD effectsLevel;
UDWORD width;
UDWORD height;
int8_t SPcolor;
int MPcolour;
FSAA_LEVEL fsaa;
RENDER_MODE shaders;
bool Fullscreen; bool Fullscreen;
bool soundEnabled; bool soundEnabled;
bool trapCursor; bool trapCursor;
UDWORD width;
UDWORD height;
FSAA_LEVEL fsaa;
bool vsync; bool vsync;
bool pauseOnFocusLoss; bool pauseOnFocusLoss;
bool ColouredCursor; bool ColouredCursor;
bool MusicEnabled; bool MusicEnabled;
int8_t SPcolor;
int MPcolour;
}; };
/***************************************************************************/ /***************************************************************************/
@ -84,11 +85,13 @@ void war_SetDefaultStates(void)//Sets all states
{ {
//set those here and reset in clParse or loadConfig //set those here and reset in clParse or loadConfig
war_setFSAA(0); war_setFSAA(0);
war_SetVsync(true);
war_setSoundEnabled( true ); war_setSoundEnabled( true );
war_SetPauseOnFocusLoss(false); war_SetPauseOnFocusLoss(false);
war_SetMusicEnabled(true); war_SetMusicEnabled(true);
war_SetSPcolor(0); //default color is green war_SetSPcolor(0); //default color is green
war_setMPcolour(-1); // Default color is random. war_setMPcolour(-1); // Default color is random.
war_SetShaders(SHADERS_ON);
} }
void war_SetSPcolor(int color) void war_SetSPcolor(int color)
@ -136,6 +139,16 @@ unsigned int war_getFSAA()
return warGlobs.fsaa; return warGlobs.fsaa;
} }
void war_SetShaders(unsigned shaders)
{
warGlobs.shaders = (RENDER_MODE)shaders;
}
unsigned war_GetShaders()
{
return warGlobs.shaders;
}
void war_SetTrapCursor(bool b) void war_SetTrapCursor(bool b)
{ {
warGlobs.trapCursor = b; warGlobs.trapCursor = b;

View File

@ -48,6 +48,13 @@ enum FSAA_LEVEL
FSAA_8X, FSAA_8X,
FSAA_MAX FSAA_MAX
}; };
enum RENDER_MODE
{
FALLBACK, /// Shaders not supported
SHADERS_OFF,/// Shaders supported but off
SHADERS_ON, /// Shaders supported and on
};
/***************************************************************************/ /***************************************************************************/
/* /*
* Global ProtoTypes * Global ProtoTypes
@ -66,6 +73,8 @@ extern void war_SetTrapCursor(bool b);
extern bool war_GetTrapCursor(void); extern bool war_GetTrapCursor(void);
extern void war_SetVsync(bool b); extern void war_SetVsync(bool b);
extern bool war_GetVsync(void); extern bool war_GetVsync(void);
extern void war_SetShaders(unsigned);
extern unsigned war_GetShaders(void);
extern void war_SetWidth(UDWORD width); extern void war_SetWidth(UDWORD width);
extern UDWORD war_GetWidth(void); extern UDWORD war_GetWidth(void);
extern void war_SetHeight(UDWORD height); extern void war_SetHeight(UDWORD height);

View File

@ -32,6 +32,7 @@ struct WEAPON
uint32_t shotsFired; uint32_t shotsFired;
Rotation rot; Rotation rot;
Rotation prevRot; Rotation prevRot;
unsigned usedAmmo; ///< Amount of ammunition used up by a VTOL
}; };
// Defined in droid.cpp. // Defined in droid.cpp.

View File

@ -5,7 +5,7 @@ AM_CXXFLAGS = $(WZ_CXXFLAGS) $(QT4_CFLAGS) -I../..
BUILT_SOURCES = BUILT_SOURCES =
CLEANFILES = $(BUILT_SOURCES) CLEANFILES = $(BUILT_SOURCES)
EXTRA_DIST = EXTRA_DIST =
bin_PROGRAMS = mapconv mapinfo map2lnd map2preview map2png noinst_PROGRAMS = mapconv mapinfo map2lnd map2preview map2png
noinst_HEADERS = maplib.h mapload.h pngsave.h vector.h noinst_HEADERS = maplib.h mapload.h pngsave.h vector.h
LIBLIST = $(LTLIBINTL) $(PHYSFS_LIBS) $(PNG_LIBS) $(QT4_LIBS) LIBLIST = $(LTLIBINTL) $(PHYSFS_LIBS) $(PNG_LIBS) $(QT4_LIBS)