mirror of
https://gitlab.com/Syroot/Worms.git
synced 2025-03-13 13:50:14 +03:00
Compare commits
181 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
914acc2e1b | ||
|
b4e6433545 | ||
|
63691f897b | ||
|
b509d7bdaf | ||
|
046033bba7 | ||
|
6dc2de2445 | ||
|
48f1f91be3 | ||
|
cbe1388fb0 | ||
|
b68503e609 | ||
|
5fdd97c5ad | ||
|
6a418e84ae | ||
|
8eb0a971e8 | ||
|
6cba058138 | ||
|
03095916f1 | ||
|
9a218549e7 | ||
|
a99a883f6f | ||
|
518207b7e6 | ||
|
2b94e09e39 | ||
|
a314377c13 | ||
|
4e251959b3 | ||
|
2ea6af0324 | ||
|
730b14cdfa | ||
|
bb2b7e72b5 | ||
|
65522b6af5 | ||
|
4c27eb415c | ||
|
e9ba6895b8 | ||
|
48e6988083 | ||
|
f242a6b745 | ||
|
d0a01c6a13 | ||
|
180a61a147 | ||
|
71c8f33ea7 | ||
|
db3a49539f | ||
|
4e1f9b17a8 | ||
|
c97ef5deb2 | ||
|
0cfbc5b675 | ||
|
20d7c3c743 | ||
|
02a644abe9 | ||
|
0fee2e1e13 | ||
|
9aad0faf6b | ||
|
ac2d12c1b6 | ||
|
17b0edf67f | ||
|
ebdf7f5168 | ||
|
a308ae49b1 | ||
|
420810fad2 | ||
|
b44ae666b6 | ||
|
6d2864e6f7 | ||
|
dd2e67eab9 | ||
|
4454cb1496 | ||
|
5b69f82a35 | ||
|
08703b6c12 | ||
|
9548855a8e | ||
|
7e13af88d1 | ||
|
ed4b69d4ad | ||
|
cc0ccaae7d | ||
|
bf0c60659a | ||
|
ebba11bd59 | ||
|
f8b1b84f21 | ||
|
b89ea5d7e9 | ||
|
c62d4a7551 | ||
|
5321dfb49a | ||
|
8b92e6a8be | ||
|
861d5ea585 | ||
|
1d06fbd578 | ||
|
13583a6971 | ||
|
10008eaf6e | ||
|
66d4d15305 | ||
|
7e3fcb766c | ||
|
fabc3e98b2 | ||
|
ad2a7c79e1 | ||
|
88d07a1ff1 | ||
|
378d2474b1 | ||
|
b46cdadb89 | ||
|
e2b41157db | ||
|
e72f6041e3 | ||
|
26a9125f0a | ||
|
57815e9072 | ||
|
b4cf309156 | ||
|
ed2785e339 | ||
|
84ba8c56a0 | ||
|
c51f67dc46 | ||
|
0ce2ce387e | ||
|
717da50d80 | ||
|
e57c593efa | ||
|
c5391c3d66 | ||
|
bd3d40245b | ||
|
93f9481dc9 | ||
|
0145636dc0 | ||
|
c7d7f5cb3e | ||
|
95b68d63c6 | ||
|
5c84357edb | ||
|
e9c88caadc | ||
|
1b527a3f20 | ||
|
38035742d6 | ||
|
a8073367f4 | ||
|
cc84ed3d5f | ||
|
e4104b8309 | ||
|
629103fce5 | ||
|
441648da6a | ||
|
b527021df4 | ||
|
587ac06330 | ||
|
899c031840 | ||
|
519a01b6f6 | ||
|
7852ef9d5a | ||
|
fcc2c74399 | ||
|
f066c27857 | ||
|
2d5fa21c00 | ||
|
197a958a98 | ||
|
efc1a9fcff | ||
|
c0cab3ecf5 | ||
|
13dee4ecbf | ||
|
a16d0a5146 | ||
|
077669b81c | ||
|
fd53660c5e | ||
|
9feea4313f | ||
|
4741e0f425 | ||
|
cf7e69e026 | ||
|
4aa9aef362 | ||
|
dac33e441a | ||
|
ff76e5b9c0 | ||
|
8a616939de | ||
|
83024baaf3 | ||
|
9b663bb72b | ||
|
645db214ca | ||
|
c33e1f7987 | ||
|
41991d6d78 | ||
|
1a5bbe714f | ||
|
1d02d3834b | ||
|
220597e65e | ||
|
9720cf1a02 | ||
|
b61f190df6 | ||
|
7e801057ac | ||
|
1d8c090957 | ||
|
ee17e5886e | ||
|
90110979c0 | ||
|
f6b37eb96c | ||
|
13f97d706a | ||
|
61377411a1 | ||
|
1c401235d5 | ||
|
e5352cadf2 | ||
|
35946c8e84 | ||
|
24b545f8e2 | ||
|
dd8b1a4be7 | ||
|
e9da2e440f | ||
|
c5db3266d3 | ||
|
dfae4ef3de | ||
|
8103229703 | ||
|
30c1454522 | ||
|
bb7d633f21 | ||
|
677b9eb9c7 | ||
|
26363c9165 | ||
|
06a2cad03b | ||
|
f850a01d19 | ||
|
a1de6d8c89 | ||
|
5541f66a78 | ||
|
e31c4b4f90 | ||
|
55fdd54027 | ||
|
3877a8dc27 | ||
|
f60a17bfca | ||
|
d57de03cf7 | ||
|
b24082bc24 | ||
|
ff042f1fc2 | ||
|
5e23aef58c | ||
|
e4f3c0ced1 | ||
|
95687b273b | ||
|
ece703f755 | ||
|
380b896e5e | ||
|
619822902a | ||
|
fb16f94cf6 | ||
|
accf37856c | ||
|
feb2ed72f7 | ||
|
ade95d4cd0 | ||
|
e5b1b9441f | ||
|
a965808afe | ||
|
3bf7531167 | ||
|
025637b7aa | ||
|
ff03f73af6 | ||
|
14e78bb43c | ||
|
364d6c53c6 | ||
|
ec3e79f8e1 | ||
|
21b48ad76b | ||
|
cf37f99ece |
8
.gitattributes
vendored
Normal file
8
.gitattributes
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
*.dat filter=lfs diff=lfs merge=lfs -text
|
||||
*.img filter=lfs diff=lfs merge=lfs -text
|
||||
*.pxl filter=lfs diff=lfs merge=lfs -text
|
||||
*.pxs filter=lfs diff=lfs merge=lfs -text
|
||||
*.wgt filter=lfs diff=lfs merge=lfs -text
|
||||
*.wsc filter=lfs diff=lfs merge=lfs -text
|
||||
*.wwp filter=lfs diff=lfs merge=lfs -text
|
||||
src/test/Syroot.Worms.Armageddon.Test/Files/Schemes/WA/Wsdb/dump.csv filter=lfs diff=lfs merge=lfs -text
|
2
LICENSE
2
LICENSE
@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017 Syroot
|
||||
Copyright (c) 2017-2024 Syroot
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
71
README.md
71
README.md
@ -1,41 +1,44 @@
|
||||
# Worms
|
||||
The goal of this .NET library is to provide managed language access to game specific file formats of the Worms game series by Team17.
|
||||
|
||||
Right now, the following file formats are supported:
|
||||
This repository hosts .NET libraries which can import, modify, and export the following file formats of second generation Worms games developed by Team17 or Mgame:
|
||||
|
||||
## First Generation (2D)
|
||||
Support for first generation 2D games is planned at a later stage.
|
||||
| Extension | Description | Games | Library | Load | Save |
|
||||
|-----------|-------------------|-------------|------------------------------------|:----:|:----:|
|
||||
| BIT | Monochrome Map | WA, WWP | `Syroot.Worms.Armageddon` | ❌ | ❌ |
|
||||
| DAT | Mission | W2 | `Syroot.Worms.Worms2` | ❌ | ❌ |
|
||||
| LAND.DAT | Land Data | W2, WA, WWP | `Syroot.Worms` | ✔ | ✔ |
|
||||
| DIR | Archive | W2, WA, WWP | `Syroot.Worms` | ✔ | ✔ |
|
||||
| IGD | Image Container | WWPA | `Syroot.Worms.Mgame` | ✔ | ❌ |
|
||||
| IMG | Image | W2, WA, WWP | `Syroot.Worms` | ✔ | ✔ |
|
||||
| KSF | Image Container | OW | `Syroot.Worms.Mgame` | ✔ | ❌ |
|
||||
| LEV | Generated Map | WA, WWP | `Syroot.Worms.Armageddon` | ✔ | ✔ |
|
||||
| LEV | Monochrome Map | W2 | `Syroot.Worms.Worms2` | ❌ | ❌ |
|
||||
| LPD | Interface Layout | WWPA | `Syroot.Worms.Mgame` | ✔ | ❌ |
|
||||
| OPT | Scheme Options | W2 | `Syroot.Worms.Worms2` | ✔ | ✔ |
|
||||
| PAL | Palette | W2, WA, WWP | `Syroot.Worms` | ✔ | ✔ |
|
||||
| PXL | Project X Library | WA+PX | `Syroot.Worms.Armageddon.ProjectX` | ✔ | ✔ |
|
||||
| PXS | Project X Scheme | WA+PX | `Syroot.Worms.Armageddon.ProjectX` | ✔ | ✔ |
|
||||
| ST1 | Team Container | W2 | `Syroot.Worms.Worms2` | ✔ | ✔ |
|
||||
| WAGAME | Replay | WA | `Syroot.Worms.Armageddon` | ❌ | ❌ |
|
||||
| WAM | Mission | WA, WWP | `Syroot.Worms.Worms2` | ❌ | ❌ |
|
||||
| WEP | Scheme Weapons | W2 | `Syroot.Worms.Worms2` | ✔ | ✔ |
|
||||
| WGT | Team Container | WA | `Syroot.Worms.Armageddon` | ✔ | ✔ |
|
||||
| WSC | Scheme | WA, WWP | `Syroot.Worms.Armageddon` | ✔ | ✔ |
|
||||
| WWP | Team Container | WWP | `Syroot.Worms.WorldParty` | ✔ | ✔ |
|
||||
|
||||
| Description | Extension | Games | Load | Save |
|
||||
|----------------|:---------:|:-------:|:----:|:----:|
|
||||
| Color Map | WRM | W1 | No | No |
|
||||
| DIY Terrain | DIY | DC | No | No |
|
||||
| Monochrome Map | GFT | DC | No | No |
|
||||
| Mountain Set | MNT | DC | No | No |
|
||||
| Option Scheme | OPT | DC | No | No |
|
||||
| Team Container | - | DC | No | No |
|
||||
Implementation of formats listed above as unsupported is planned for a later date.
|
||||
|
||||
## Second Generation (2D)
|
||||
Formats of the second generation 2D games are mostly focused right now.
|
||||
The libraries are available on [NuGet](https://www.nuget.org/packages?q=Syroot.Worms).
|
||||
|
||||
| Description | Extension | Games | Load | Save |
|
||||
|-------------------|:---------:|:-----------:|:----:|:----:|
|
||||
| Archive | DIR | W2, WA, WWP | Yes | Yes |
|
||||
| Image | IMG | W2, WA, WWP | Yes | No |
|
||||
| Land Data | LAND.DAT | W2, WA, WWP | Yes | No |
|
||||
| Mission | DAT | W2 | No | No |
|
||||
| Mission | WAM | WA, WWP | No | No |
|
||||
| Monochrome Map | LEV | W2 | No | No |
|
||||
| Monochrome Map | LEV, BIT | WA, WWP | No | No |
|
||||
| Palette | PAL | W2, WA, WWP | Yes | Yes |
|
||||
| Project X Library | PXL | WA+PX | No | No |
|
||||
| Project X Scheme | PXS | WA+PX | No | No |
|
||||
| Replay | WAGAME | WA | No | No |
|
||||
| Scheme | WSC | WA, WWP | Yes | Yes |
|
||||
| Scheme Options | OPT | W2 | Yes | Yes |
|
||||
| Scheme Weapons | WEP | W2 | Yes | Yes |
|
||||
| Team Container | ST1 | W2 | No | No |
|
||||
| Team Container | WGT | WA, WWP | No | No |
|
||||
## Modules
|
||||
|
||||
## Third Generation (3D)
|
||||
Third generation file formats used by the 3D games have not yet been looked into.
|
||||
* `fkNetcode`: Patches Worms 2's outdated external IP detection and resolves it properly via a web service.
|
||||
* `fkDesPatch`: Unfinished module meant to replace functionality found in Sn*tch patcher.
|
||||
* `FrontendKitWS`: WormKit-like module loader for patching the Worms 2 Frontend.
|
||||
* `WormKitLib`: Utilities like signature scanning or import replacement to help in patching Worms executables.
|
||||
|
||||
## Tools
|
||||
|
||||
* `Syroot.Worms.Mgame.Launcher`: Creates a fake launch configuration to start OW or WWPA clients with.
|
||||
* `Syroot.Worms.Mgame.GameServer`: Simulates OW or WWPA networking to allow playing games.
|
||||
* `Syroot.Worms.Worms2.GameServer`: Simulates a Worms 2 server.
|
||||
|
BIN
res/icon.ico
Normal file
BIN
res/icon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 34 KiB |
BIN
res/icon.png
Normal file
BIN
res/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.6 KiB |
113
res/icon.svg
Normal file
113
res/icon.svg
Normal file
@ -0,0 +1,113 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
id="svg3039"
|
||||
version="1.1"
|
||||
inkscape:version="0.92.3 (2405546, 2018-03-11)"
|
||||
width="64"
|
||||
height="64"
|
||||
sodipodi:docname="icon.svg"
|
||||
inkscape:export-filename="icon.png"
|
||||
inkscape:export-xdpi="192"
|
||||
inkscape:export-ydpi="192">
|
||||
<metadata
|
||||
id="metadata3045">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs3043" />
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1377"
|
||||
id="namedview3041"
|
||||
showgrid="false"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true"
|
||||
inkscape:zoom="19.203125"
|
||||
inkscape:cx="32"
|
||||
inkscape:cy="32"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g3889"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0" />
|
||||
<g
|
||||
id="g3889"
|
||||
transform="translate(-7.8100759,-66.876826)">
|
||||
<path
|
||||
style="fill:#f0eff1;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
d="m 27.04262,126.71289 c -1.181776,-1.55006 -1.966744,-3.43909 -2.368435,-5.34643 -0.731962,-3.47556 0.09235,-5.94777 0.01998,-10.65539 -1.181472,-0.48787 -1.759686,-1.09396 -2.451634,-1.84793 -0.54815,-0.59728 -1.00234,-1.30327 -1.292215,-2.06037 -0.32661,-0.85304 -0.539845,-1.78974 -0.466734,-2.70023 0.06964,-0.86724 0.419788,-1.86425 0.849262,-2.46806 -2.222622,-2.315179 -5.867212,-9.13785 -7.388442,-14.27538 -0.627091,-2.117826 -1.043782,-4.421047 -0.649327,-6.594253 0.555377,-3.059784 1.963392,-6.129269 4.118816,-8.370897 2.426515,-2.523562 5.794227,-4.355239 9.234755,-5.002661 5.494996,-1.034023 11.734091,-0.591808 16.644562,2.082413 3.532402,1.923732 6.734565,5.354675 7.754134,9.245561 1.992433,7.603525 -2.025069,17.565155 -4.34531,23.176897 0.372134,1.17735 0.38457,2.09971 0.0082,3.21285 0.749005,-1.22124 4.617222,-1.26695 6.698763,-0.44528 2.151128,0.84914 3.662957,3.01905 4.741805,5.06463 1.345959,2.55205 1.452591,4.39726 1.87347,8.45051 3.361416,-0.18651 4.546466,0.75415 5.629108,2.49832 1.281217,2.06409 0.988026,5.22596 -0.30647,7.28174 -0.983854,1.56245 -3.082892,2.22379 -4.890208,2.6017 -2.756327,0.57634 -7.55332,-0.082 -8.422992,-0.64716 -1.45258,-0.87758 -2.109794,-2.9623 -2.521142,-4.48379 -1.402821,1.51154 -3.163799,3.01285 -5.10957,3.91927 -2.09583,0.97633 -4.460352,1.39763 -6.772715,1.49729 -2.215996,0.0955 -4.559406,0.009 -6.594511,-0.87097 -1.577588,-0.68223 -2.951008,-1.89553 -3.993098,-3.26238 z"
|
||||
id="path3866"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="aacaaacaaaaaaccaacaaaccaaaa" />
|
||||
<path
|
||||
sodipodi:nodetypes="acacaaaaacaaaaacccacaaacaaaacaccaaaaa"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3863"
|
||||
d="m 27.793976,121.07863 c -0.938536,-3.15558 -0.431941,-7.06522 -0.225814,-9.874 1.138774,0.22476 2.717839,0.0994 3.985541,-0.31129 1.841729,-0.5966 4.299757,-1.43626 4.955594,-3.02871 0.236765,-0.63702 0.345752,-1.15549 0.06504,-1.61557 -0.193357,-0.31691 -0.638827,-0.46544 -1.010038,-0.46919 -1.673779,-0.0169 -2.943507,1.75701 -4.596122,2.02285 -1.760095,0.28312 -3.745971,0.31928 -5.323725,-0.51064 -1.09879,-0.57799 -2.201799,-1.62705 -2.39356,-2.85368 -0.154663,-0.98932 0.23963,-2.16839 1.135926,-2.78097 -2.929955,-3.399706 -8.1456,-12.579671 -8.160525,-19.681834 -0.0044,-2.109158 1.048726,-4.234736 2.398876,-5.855128 1.71254,-2.055312 4.188437,-3.580424 6.755692,-4.332973 4.127116,-1.209799 8.848113,-1.435252 12.902341,0 3.39863,1.203161 7.071834,3.456088 8.406815,6.805122 2.936371,7.366413 -1.457276,15.631594 -3.123633,23.584293 0.515326,1.26768 0.641215,2.38898 0.539889,2.96776 -0.154313,3.04461 -3.141404,4.07388 -3.239326,5.47599 -0.02063,0.58726 0.341836,1.39745 0.91974,1.50395 1.775112,0.32715 3.061188,-2.30516 4.286317,-3.30904 1.117915,-0.89135 1.996385,-0.9664 3.077678,-1.08716 0.874694,-0.0977 1.799048,-0.002 2.622308,0.3085 0.865772,0.32731 1.72577,0.84177 2.282632,1.5811 2.403642,3.1912 3.475179,7.7645 3.839445,11.35383 0.4388,-0.041 1.184307,-0.25821 1.779541,-0.20907 0.737401,0.0608 1.50374,0.22656 2.132242,0.61701 0.629338,0.39097 1.226145,0.95186 1.499881,1.64033 0.325059,0.81755 0.486956,1.87965 0.04271,2.63906 -0.723244,1.23633 -1.896504,1.92514 -3.779208,2.04498 -2.093197,0.12713 -3.819496,0.14085 -5.585908,-0.46833 -0.51923,-0.17906 -1.046235,-0.49834 -1.377768,-0.90375 -0.690384,-0.61349 -1.704647,-5.64303 -2.331707,-7.49746 -0.844935,1.6212 -1.981417,3.77823 -3.430533,5.30695 -0.873833,0.92182 -1.927815,1.71307 -3.085071,2.23666 -1.825122,0.82576 -3.858872,1.28185 -5.861626,1.3259 -2.28516,0.0503 -4.857846,0.0676 -6.748215,-1.21733 -1.75457,-1.19259 -2.750631,-3.37468 -3.355429,-5.40816 z"
|
||||
style="fill:#424242;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="aaaaaasa"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3852"
|
||||
d="m 24.845061,101.57125 c -0.757785,-0.16767 -1.362649,-0.8291 -1.812441,-1.46158 -2.864311,-4.027717 -5.244139,-9.020989 -5.003042,-13.957446 0.05609,-1.148428 0.472152,-2.555423 1.474802,-3.118219 0.785949,-0.441159 1.946104,-0.224569 2.688711,0.28619 1.490827,1.025381 1.978028,3.093067 2.467387,4.835045 1.194569,4.252334 1.587326,10.668599 1.004252,13.2127 -0.07475,0.32614 -0.544814,0.26412 -0.819669,0.20331 z"
|
||||
style="fill:#f0eff1;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="aaaaaaaaa"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3854"
|
||||
d="m 30.698047,101.30525 c -0.696747,-0.19779 -1.080939,-0.99485 -1.450625,-1.617677 -1.7475,-2.944117 -2.997748,-6.285458 -3.428451,-9.681934 -0.219233,-1.728845 -0.303507,-3.641173 0.459783,-5.207813 0.653868,-1.342053 1.810141,-2.749695 3.270463,-3.059737 1.927361,-0.409199 4.220692,0.514482 5.58488,1.936158 1.292526,1.346999 1.657827,3.496363 1.614575,5.362684 -0.09581,4.134002 -1.123529,8.853546 -4.122816,11.700209 -0.48591,0.46118 -1.283351,0.75106 -1.927809,0.56811 z"
|
||||
style="fill:#f0eff1;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="aaaaa"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3053"
|
||||
d="m 23.111155,79.209874 c -0.01138,-1.138917 -1.930391,-1.44014 -3.067506,-1.505266 -1.227005,-0.07027 -3.445842,0.007 -3.473799,1.235725 -0.03231,1.419638 2.525944,1.671948 3.944553,1.608843 0.972968,-0.04328 2.606486,-0.365424 2.596752,-1.339302 z"
|
||||
style="fill:#f0eff1;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="caaaac"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3049"
|
||||
d="m 29.471776,95.528773 c -1.113382,-2.31393 -2.039835,-6.332128 -0.123439,-8.229053 0.525742,-0.5204 1.661753,-0.39519 2.179449,0.133771 1.713921,1.751223 1.246507,5.081874 0.515104,7.455946 -0.180015,0.584323 -0.54871,1.299349 -1.129933,1.42105 -0.531671,0.111328 -1.046805,-0.154223 -1.441181,-0.781714 z"
|
||||
style="fill:#424242;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="saaas"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3055"
|
||||
d="m 25.360823,78.864231 c -0.04026,-1.419992 4.606645,-2.402702 7.123563,-2.53499 1.588866,-0.08351 4.506608,-0.465415 4.639913,1.120045 0.145405,1.729321 -3.071775,1.778317 -4.78587,2.049595 -2.306761,0.365074 -6.940969,0.657497 -6.977606,-0.63465 z"
|
||||
style="fill:#f0eff1;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="aaaasa"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3051"
|
||||
d="m 19.499778,91.756829 c -0.336512,-1.403856 -0.725814,-3.395762 0.388636,-4.3134 0.595308,-0.490178 1.713417,-0.260854 2.301122,0.238413 1.282561,1.08956 1.273616,3.189522 1.325224,4.871612 0.04396,1.432965 -0.03199,4.135797 -0.872415,4.211507 -1.153711,0.103931 -2.683166,-3.091608 -3.142567,-5.008132 z"
|
||||
style="fill:#424242;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 9.7 KiB |
8
src/010editor/Common.bt
Normal file
8
src/010editor/Common.bt
Normal file
@ -0,0 +1,8 @@
|
||||
void FAlign(byte alignment)
|
||||
{
|
||||
local int bytesToSkip <hidden=true> = (-FTell() % alignment + alignment) % alignment;
|
||||
while (bytesToSkip--)
|
||||
{
|
||||
byte padding <fgcolor=0x808080, hidden=true>;
|
||||
}
|
||||
}
|
18
src/010editor/IMG.bt
Normal file
18
src/010editor/IMG.bt
Normal file
@ -0,0 +1,18 @@
|
||||
//------------------------------------------------
|
||||
//--- 010 Editor v10.0.2 Binary Template
|
||||
//
|
||||
// File: IMG.bt
|
||||
// Authors: Syroot
|
||||
// Version: 0.1.0
|
||||
// Purpose: Parse Worms Armageddon and Worms World Party image files.
|
||||
// Category: Worms
|
||||
// File Mask: *.img
|
||||
// ID Bytes:
|
||||
// History:
|
||||
// 0.1.0 2020-06-29 Initial version.
|
||||
//------------------------------------------------
|
||||
|
||||
#include "Image.bt"
|
||||
|
||||
LittleEndian();
|
||||
Image image <open=true>;
|
74
src/010editor/Image.bt
Normal file
74
src/010editor/Image.bt
Normal file
@ -0,0 +1,74 @@
|
||||
#include "Common.bt"
|
||||
|
||||
typedef struct(char description, char align)
|
||||
{
|
||||
uint signature <format=hex>;
|
||||
if (signature != 0x1A474D49) // "IMG\x1A"
|
||||
{
|
||||
Warning("Invalid IMG signature.");
|
||||
Exit(-1);
|
||||
}
|
||||
|
||||
uint fileSize;
|
||||
|
||||
if (description)
|
||||
string description;
|
||||
|
||||
ubyte bpp;
|
||||
enum <ubyte> Flags
|
||||
{
|
||||
IMG_COMPRESSED = 1 << 6,
|
||||
IMG_PALETTIZED = 1 << 7
|
||||
} flags;
|
||||
|
||||
if (flags & IMG_PALETTIZED)
|
||||
{
|
||||
ushort colorCount;
|
||||
struct Color
|
||||
{
|
||||
ubyte r;
|
||||
ubyte g;
|
||||
ubyte b;
|
||||
} colors[colorCount];
|
||||
}
|
||||
|
||||
ushort width;
|
||||
ushort height;
|
||||
|
||||
if (align)
|
||||
FAlign(4);
|
||||
|
||||
if (flags & IMG_COMPRESSED)
|
||||
char data[GetCompressedImgSize()];
|
||||
else
|
||||
char data[bpp / 8.0 * width * height];
|
||||
} Image;
|
||||
|
||||
int GetCompressedImgSize()
|
||||
{
|
||||
local int pos = FTell();
|
||||
local int start = pos;
|
||||
local int cmd;
|
||||
while ((cmd = ReadByte(pos++)) != -1)
|
||||
{
|
||||
// Read a byte.
|
||||
if ((cmd & 0x80) != 0)
|
||||
{
|
||||
local int arg1 = cmd >> 3 & 0b1111; // bits 2-5
|
||||
local int arg2 = ReadByte(pos++);
|
||||
if (arg2 == -1)
|
||||
break;
|
||||
// Arg2 = bits 6-16
|
||||
arg2 = ((cmd << 8) | arg2) & 0x7FF;
|
||||
if (arg1 == 0)
|
||||
{
|
||||
// Command: 0x80 0x00
|
||||
if (arg2 == 0)
|
||||
break;
|
||||
if (ReadByte(pos++) == -1)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return pos - start;
|
||||
}
|
32
src/010editor/LEV.bt
Normal file
32
src/010editor/LEV.bt
Normal file
@ -0,0 +1,32 @@
|
||||
//------------------------------------------------
|
||||
//--- 010 Editor v9.0.1 Binary Template
|
||||
//
|
||||
// File: LEV.bt
|
||||
// Authors: Syroot
|
||||
// Version: 0.1.0
|
||||
// Purpose: Parse Worms LEV map terrain files.
|
||||
// Category: Worms
|
||||
// File Mask: *.bit;*.lev
|
||||
// ID Bytes:
|
||||
// History:
|
||||
// 0.1.0 2019-01-28 Initial version.
|
||||
//------------------------------------------------
|
||||
|
||||
LittleEndian();
|
||||
|
||||
uint landSeed;
|
||||
uint objectSeed;
|
||||
int cavern;
|
||||
enum LANDSTYLE
|
||||
{
|
||||
SingleIsland_Cavern,
|
||||
DoubleIsland_DoubleTunnel,
|
||||
SingleIslandSmall_CavernWater,
|
||||
DoubleIslandSmall_SingleTunnel,
|
||||
} style;
|
||||
int noBorder;
|
||||
int objectPercent;
|
||||
int bridgePercent;
|
||||
int waterLevel;
|
||||
int soilIndex;
|
||||
int waterColor;
|
29
src/010editor/OW_KSF.bt
Normal file
29
src/010editor/OW_KSF.bt
Normal file
@ -0,0 +1,29 @@
|
||||
//------------------------------------------------
|
||||
//--- 010 Editor v9.0.1 Binary Template
|
||||
//
|
||||
// File: KSF.bt
|
||||
// Authors: Syroot
|
||||
// Version: 0.1.0
|
||||
// Purpose: Parse Online Worms KSF bitmap files.
|
||||
// Category: Online Worms
|
||||
// File Mask: *.ksf
|
||||
// ID Bytes:
|
||||
// History:
|
||||
// 0.1.0 2018-12-21 Initial version.
|
||||
//------------------------------------------------
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint offset;
|
||||
uint halfWidth;
|
||||
uint halfHeight;
|
||||
ushort width;
|
||||
ushort height;
|
||||
} Image;
|
||||
|
||||
LittleEndian();
|
||||
|
||||
int numImages;
|
||||
int lenData;
|
||||
Image images[numImages];
|
||||
ubyte data[lenData];
|
20
src/010editor/OW_PAL.bt
Normal file
20
src/010editor/OW_PAL.bt
Normal file
@ -0,0 +1,20 @@
|
||||
//------------------------------------------------
|
||||
//--- 010 Editor v10.0.2 Binary Template
|
||||
//
|
||||
// File: OW_PAL.bt
|
||||
// Authors: Syroot
|
||||
// Version: 0.1.0
|
||||
// Purpose: Parse Online Worms PAL color palettes.
|
||||
// Category: Worms
|
||||
// File Mask: *.pal
|
||||
// ID Bytes:
|
||||
// History:
|
||||
// 0.1.0 2020-06-30 Initial version.
|
||||
//------------------------------------------------
|
||||
|
||||
LittleEndian();
|
||||
|
||||
struct Color
|
||||
{
|
||||
ubyte r, g, b;
|
||||
} colors[256];
|
44
src/010editor/W2_LandDAT.bt
Normal file
44
src/010editor/W2_LandDAT.bt
Normal file
@ -0,0 +1,44 @@
|
||||
//------------------------------------------------
|
||||
//--- 010 Editor v10.0.2 Binary Template
|
||||
//
|
||||
// File: W2_LandDAT.bt
|
||||
// Authors: Syroot
|
||||
// Version: 0.1.0
|
||||
// Purpose: Parse Worms 2 land generator data files.
|
||||
// Category: Worms
|
||||
// File Mask: land.dat
|
||||
// ID Bytes:
|
||||
// History:
|
||||
// 0.1.0 2020-06-30 Initial version.
|
||||
//------------------------------------------------
|
||||
|
||||
#include "Image.bt"
|
||||
|
||||
LittleEndian();
|
||||
|
||||
uint signature <format=hex>;
|
||||
if (signature != 0x1A444E4C) // "LND\x1A"
|
||||
{
|
||||
Warning("Invalid LND signature.");
|
||||
Exit(-1);
|
||||
}
|
||||
|
||||
int fileSize;
|
||||
int mapWidth;
|
||||
int mapHeight;
|
||||
int hasCavernBorder;
|
||||
int numObjectLocations;
|
||||
struct ObjectLocation
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
} objectLocations[numObjectLocations];
|
||||
int unknown;
|
||||
Image foregroundImage(true, false);
|
||||
Image collisionImage(true, false);
|
||||
Image backgroundImage(true, false);
|
||||
Image unknownImage(true, false);
|
||||
ubyte landTexPathLength;
|
||||
char landTexPath[landTexPathLength];
|
||||
ubyte waterDirPathLength;
|
||||
char waterDirPath[waterDirPathLength];
|
43
src/010editor/WA3.0_LandDAT.bt
Normal file
43
src/010editor/WA3.0_LandDAT.bt
Normal file
@ -0,0 +1,43 @@
|
||||
//------------------------------------------------
|
||||
//--- 010 Editor v10.0.2 Binary Template
|
||||
//
|
||||
// File: WA3.0_LandDAT.bt
|
||||
// Authors: Syroot
|
||||
// Version: 0.1.0
|
||||
// Purpose: Parse Worms Armageddon (older than 3.6.28.0) land generator data files.
|
||||
// Category: Worms
|
||||
// File Mask: land.dat
|
||||
// ID Bytes:
|
||||
// History:
|
||||
// 0.1.0 2020-06-30 Initial version.
|
||||
//------------------------------------------------
|
||||
|
||||
#include "Image.bt"
|
||||
|
||||
LittleEndian();
|
||||
|
||||
uint signature <format=hex>;
|
||||
if (signature != 0x1A444E4C) // "LND\x1A"
|
||||
{
|
||||
Warning("Invalid LND signature.");
|
||||
Exit(-1);
|
||||
}
|
||||
|
||||
int fileSize;
|
||||
int mapWidth;
|
||||
int mapHeight;
|
||||
int hasCavernBorder;
|
||||
int waterHeight;
|
||||
int numObjectLocations;
|
||||
struct ObjectLocation
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
} objectLocations[numObjectLocations];
|
||||
Image foregroundImage(false, false);
|
||||
Image collisionImage(false, false);
|
||||
Image backgroundImage(false, false);
|
||||
ubyte landTexPathLength;
|
||||
char landTexPath[landTexPathLength];
|
||||
ubyte waterDirPathLength;
|
||||
char waterDirPath[waterDirPathLength];
|
44
src/010editor/WA3.6_LandDAT.bt
Normal file
44
src/010editor/WA3.6_LandDAT.bt
Normal file
@ -0,0 +1,44 @@
|
||||
//------------------------------------------------
|
||||
//--- 010 Editor v10.0.2 Binary Template
|
||||
//
|
||||
// File: WA3.6_LandDAT.bt
|
||||
// Authors: Syroot
|
||||
// Version: 0.1.0
|
||||
// Purpose: Parse Worms Armageddon (3.6.28.0 and newer) land generator data files.
|
||||
// Category: Worms
|
||||
// File Mask: land.dat
|
||||
// ID Bytes:
|
||||
// History:
|
||||
// 0.1.0 2020-06-30 Initial version.
|
||||
//------------------------------------------------
|
||||
|
||||
#include "Image.bt"
|
||||
|
||||
LittleEndian();
|
||||
|
||||
uint signature <format=hex>;
|
||||
if (signature != 0x1A444E4C) // "LND\x1A"
|
||||
{
|
||||
Warning("Invalid LND signature.");
|
||||
Exit(-1);
|
||||
}
|
||||
|
||||
int fileSize;
|
||||
int mapWidth;
|
||||
int mapHeight;
|
||||
int hasCavernBorder;
|
||||
int waterHeight;
|
||||
int holeCount;
|
||||
int numObjectLocations;
|
||||
struct ObjectLocation
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
} objectLocations[numObjectLocations];
|
||||
Image foregroundImage(false, false);
|
||||
Image collisionImage(false, false);
|
||||
Image backgroundImage(false, false);
|
||||
ubyte landTexPathLength;
|
||||
char landTexPath[landTexPathLength];
|
||||
ubyte waterDirPathLength;
|
||||
char waterDirPath[waterDirPathLength];
|
51
src/010editor/WWPA_IGD.bt
Normal file
51
src/010editor/WWPA_IGD.bt
Normal file
@ -0,0 +1,51 @@
|
||||
//------------------------------------------------
|
||||
//--- 010 Editor v9.0.1 Binary Template
|
||||
//
|
||||
// File: IGD.bt
|
||||
// Authors: Syroot
|
||||
// Version: 0.1.0
|
||||
// Purpose: Parse Worms World Party Aqua IGD graphics containers.
|
||||
// Category: Worms World Party Aqua
|
||||
// File Mask: *.igd
|
||||
// ID Bytes:
|
||||
// History:
|
||||
// 0.1.0 2019-01-05 Initial version.
|
||||
//------------------------------------------------
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
} Vec2 <read=Vec2Read>;
|
||||
string Vec2Read(Vec2& v)
|
||||
{
|
||||
string s;
|
||||
SPrintf(s, "(%d, %d)", v.x, v.y);
|
||||
return s;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint unkA;
|
||||
uint index;
|
||||
uint unkB;
|
||||
uint unkC;
|
||||
Vec2 size;
|
||||
Vec2 center;
|
||||
uint lenData;
|
||||
uint lenDataComp;
|
||||
ubyte dataComp[lenDataComp];
|
||||
} Image;
|
||||
|
||||
LittleEndian();
|
||||
|
||||
uint unkA;
|
||||
uint unkB;
|
||||
Vec2 negativeCenter;
|
||||
Vec2 center;
|
||||
Vec2 size;
|
||||
uint numColors;
|
||||
uint palette[numColors] <format=hex>;
|
||||
uint numImages;
|
||||
if (numImages <= 512)
|
||||
Image images[numImages] <optimize=false>;
|
35
src/010editor/WWPA_LPD.bt
Normal file
35
src/010editor/WWPA_LPD.bt
Normal file
@ -0,0 +1,35 @@
|
||||
//------------------------------------------------
|
||||
//--- 010 Editor v9.0.1 Binary Template
|
||||
//
|
||||
// File: LPD.bt
|
||||
// Authors: Syroot
|
||||
// Version: 0.1.0
|
||||
// Purpose: Parse Worms World Party Aqua LPD layout files.
|
||||
// Category: Worms World Party Aqua
|
||||
// File Mask: *.lpd
|
||||
// ID Bytes:
|
||||
// History:
|
||||
// 0.1.0 2019-01-05 Initial version.
|
||||
//------------------------------------------------
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint lenFileName;
|
||||
char fileName[lenFileName];
|
||||
uint left;
|
||||
uint top;
|
||||
uint right;
|
||||
uint bottom;
|
||||
uint param5;
|
||||
uint version;
|
||||
} Element <read=ElementRead>;
|
||||
wstring ElementRead(Element &var)
|
||||
{
|
||||
return StringToWString(var.fileName, CHARSET_KOREAN_J);
|
||||
}
|
||||
|
||||
LittleEndian();
|
||||
|
||||
uint numElements;
|
||||
if (numElements <= 512)
|
||||
Element elements[numElements] <optimize=false>;
|
44
src/010editor/WWPA_LandDAT.bt
Normal file
44
src/010editor/WWPA_LandDAT.bt
Normal file
@ -0,0 +1,44 @@
|
||||
//------------------------------------------------
|
||||
//--- 010 Editor v10.0.2 Binary Template
|
||||
//
|
||||
// File: WWPA_LandDAT.bt
|
||||
// Authors: Syroot
|
||||
// Version: 0.1.0
|
||||
// Purpose: Parse Worms World Party Aqua land generator data files.
|
||||
// Category: Worms
|
||||
// File Mask: land.dat
|
||||
// ID Bytes:
|
||||
// History:
|
||||
// 0.1.0 2020-06-30 Initial version.
|
||||
//------------------------------------------------
|
||||
|
||||
#include "Image.bt"
|
||||
|
||||
LittleEndian();
|
||||
|
||||
uint signature <format=hex>;
|
||||
if (signature != 0x1B444E4C) // "LND\x1B"
|
||||
{
|
||||
Warning("Invalid LND signature.");
|
||||
Exit(-1);
|
||||
}
|
||||
|
||||
int fileSize;
|
||||
int mapWidth;
|
||||
int mapHeight;
|
||||
int hasCavernBorder;
|
||||
int waterHeight;
|
||||
int holeCount;
|
||||
int numObjectLocations;
|
||||
struct ObjectLocation
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
} objectLocations[numObjectLocations];
|
||||
Image foregroundImage(false, true);
|
||||
Image collisionImage(false, true);
|
||||
Image backgroundImage(false, true);
|
||||
ubyte landTexPathLength;
|
||||
char landTexPath[landTexPathLength];
|
||||
ubyte waterDirPathLength;
|
||||
char waterDirPath[waterDirPathLength];
|
43
src/010editor/WWP_LandDAT.bt
Normal file
43
src/010editor/WWP_LandDAT.bt
Normal file
@ -0,0 +1,43 @@
|
||||
//------------------------------------------------
|
||||
//--- 010 Editor v10.0.2 Binary Template
|
||||
//
|
||||
// File: WWP_LandDAT.bt
|
||||
// Authors: Syroot
|
||||
// Version: 0.1.0
|
||||
// Purpose: Parse Worms World Party land generator data files.
|
||||
// Category: Worms
|
||||
// File Mask: land.dat
|
||||
// ID Bytes:
|
||||
// History:
|
||||
// 0.1.0 2020-06-30 Initial version.
|
||||
//------------------------------------------------
|
||||
|
||||
#include "Image.bt"
|
||||
|
||||
LittleEndian();
|
||||
|
||||
uint signature <format=hex>;
|
||||
if (signature != 0x1A444E4C) // "LND\x1A"
|
||||
{
|
||||
Warning("Invalid LND signature.");
|
||||
Exit(-1);
|
||||
}
|
||||
|
||||
int fileSize;
|
||||
int mapWidth;
|
||||
int mapHeight;
|
||||
int hasCavernBorder;
|
||||
int waterHeight;
|
||||
int numObjectLocations;
|
||||
struct ObjectLocation
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
} objectLocations[numObjectLocations];
|
||||
Image foregroundImage(false, true);
|
||||
Image collisionImage(false, true);
|
||||
Image backgroundImage(false, true);
|
||||
ubyte landTexPathLength;
|
||||
char landTexPath[landTexPathLength];
|
||||
ubyte waterDirPathLength;
|
||||
char waterDirPath[waterDirPathLength];
|
@ -1,35 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using Syroot.Worms.Gen2;
|
||||
|
||||
namespace Syroot.Worms.Test
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the main class of the application containing the program entry point.
|
||||
/// </summary>
|
||||
internal class Program
|
||||
{
|
||||
// ---- CONSTANTS ----------------------------------------------------------------------------------------------
|
||||
|
||||
private static readonly string[] _testPaths = { @"C:\Games\Worms Armageddon 3.7.2.1" };
|
||||
|
||||
// ---- METHODS (PRIVATE) --------------------------------------------------------------------------------------
|
||||
|
||||
private static void Main(string[] args)
|
||||
{
|
||||
Console.WriteLine("Done.");
|
||||
Console.ReadLine();
|
||||
}
|
||||
|
||||
private static List<string> GetFiles(string wildcard)
|
||||
{
|
||||
List<string> files = new List<string>();
|
||||
foreach (string testPath in _testPaths)
|
||||
{
|
||||
files.AddRange(Directory.GetFiles(testPath, wildcard, SearchOption.AllDirectories));
|
||||
}
|
||||
return files;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp1.1</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Syroot.Worms\Syroot.Worms.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
@ -1,91 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Syroot.Worms.Core;
|
||||
|
||||
namespace Syroot.Worms.UnitTest.Common
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a collection of methods helping in executing tests.
|
||||
/// </summary>
|
||||
internal static class TestHelpers
|
||||
{
|
||||
// ---- MEMBERS ------------------------------------------------------------------------------------------------
|
||||
|
||||
private static readonly string[] _gamePathsWorms2 = { @"C:\Games\Worms2" };
|
||||
private static readonly string[] _gamePathsWormsArmageddon = { @"C:\Games\Worms Armageddon 3.7.2.1" };
|
||||
private static readonly string[] _gamePathsWormsWorldParty = { @"C:\Games\Worms World Party" };
|
||||
|
||||
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Loads the files found with the given <paramref name="wildcard"/>. Excludes file names specified in the
|
||||
/// optional array <paramref name="excludedFiles"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the files to load.</typeparam>
|
||||
/// <param name="games">The games to test.</param>
|
||||
/// <param name="wildcard">The wildcard to match.</param>
|
||||
/// <param name="excludedFiles">Optionally, the files to exclude.</param>
|
||||
internal static void LoadFiles<T>(Game games, string wildcard, string[] excludedFiles = null)
|
||||
where T : ILoadableFile, new()
|
||||
{
|
||||
foreach (string fileName in FindFiles(games, wildcard))
|
||||
{
|
||||
if (excludedFiles?.Contains(Path.GetFileName(fileName), StringComparer.OrdinalIgnoreCase) == true)
|
||||
{
|
||||
Debug.WriteLine($"Skipping {fileName}");
|
||||
continue;
|
||||
}
|
||||
Debug.Write($"Loading {fileName}...");
|
||||
T instance = new T();
|
||||
instance.Load(fileName);
|
||||
Debug.WriteLine($" ok");
|
||||
}
|
||||
}
|
||||
|
||||
// ---- METHODS (PRIVATE) --------------------------------------------------------------------------------------
|
||||
|
||||
private static List<string> FindFiles(Game games, string wildcard)
|
||||
{
|
||||
List<string> gamePaths = GetGamePaths(games);
|
||||
List<string> files = new List<string>();
|
||||
foreach (string testPath in gamePaths)
|
||||
{
|
||||
files.AddRange(Directory.GetFiles(testPath, wildcard, SearchOption.AllDirectories));
|
||||
}
|
||||
return files;
|
||||
}
|
||||
|
||||
private static List<string> GetGamePaths(Game game)
|
||||
{
|
||||
List<string> gamePaths = new List<string>();
|
||||
if (game.HasFlag(Game.Worms2))
|
||||
{
|
||||
gamePaths.AddRange(_gamePathsWorms2);
|
||||
}
|
||||
if (game.HasFlag(Game.WormsArmageddon))
|
||||
{
|
||||
gamePaths.AddRange(_gamePathsWormsArmageddon);
|
||||
}
|
||||
if (game.HasFlag(Game.WormsWorldParty))
|
||||
{
|
||||
gamePaths.AddRange(_gamePathsWormsWorldParty);
|
||||
}
|
||||
return gamePaths;
|
||||
}
|
||||
}
|
||||
|
||||
[Flags]
|
||||
internal enum Game
|
||||
{
|
||||
Worms2 = 1 << 0,
|
||||
WormsArmageddon = 1 << 1,
|
||||
WormsWorldParty = 1 << 2,
|
||||
|
||||
Gen2 = Worms2 | WormsArmageddon | WormsWorldParty,
|
||||
Armageddon = WormsArmageddon | WormsWorldParty,
|
||||
All = -1
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Syroot.Worms.Gen2;
|
||||
using Syroot.Worms.UnitTest.Common;
|
||||
|
||||
namespace Syroot.Worms.UnitTest.Gen2
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a collection of tests for the <see cref="Image"/> class.
|
||||
/// </summary>
|
||||
[TestCategory("Image")]
|
||||
[TestClass]
|
||||
public class ImageTests
|
||||
{
|
||||
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Loads all files found in any game directories.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void LoadImages()
|
||||
{
|
||||
TestHelpers.LoadFiles<Image>(Game.All, "*.img");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Syroot.Worms.Gen2;
|
||||
using Syroot.Worms.UnitTest.Common;
|
||||
|
||||
namespace Syroot.Worms.UnitTest.Gen2
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a collection of tests for the <see cref="Palette"/> class.
|
||||
/// </summary>
|
||||
[TestCategory("Palette")]
|
||||
[TestClass]
|
||||
public class PaletteTests
|
||||
{
|
||||
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Loads all files found in any game directories.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void LoadPalettes()
|
||||
{
|
||||
TestHelpers.LoadFiles<Palette>(Game.Gen2, "*.pal", new string[]
|
||||
{
|
||||
"wwp.pal", // Contains 4 bytes of trash after the data chunk.
|
||||
"wwpmaped.pal" // Contains 4 bytes of trash after the data chunk.
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp1.1</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="1.1.11" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="1.1.11" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Syroot.Worms\Syroot.Worms.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
@ -1,34 +1,189 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.26403.7
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Syroot.Worms", "Syroot.Worms\Syroot.Worms.csproj", "{DD76B6AA-5A5A-4FCD-95AA-9552977525A1}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Syroot.Worms.UnitTest", "Syroot.Worms.UnitTest\Syroot.Worms.UnitTest.csproj", "{493816DB-A1A1-4981-9F5F-8044499937B6}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Syroot.Worms.Test", "Syroot.Worms.Test\Syroot.Worms.Test.csproj", "{2D796945-A523-4A22-BDEE-702D6BA36F69}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{DD76B6AA-5A5A-4FCD-95AA-9552977525A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{DD76B6AA-5A5A-4FCD-95AA-9552977525A1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{DD76B6AA-5A5A-4FCD-95AA-9552977525A1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{DD76B6AA-5A5A-4FCD-95AA-9552977525A1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{493816DB-A1A1-4981-9F5F-8044499937B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{493816DB-A1A1-4981-9F5F-8044499937B6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{493816DB-A1A1-4981-9F5F-8044499937B6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{493816DB-A1A1-4981-9F5F-8044499937B6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2D796945-A523-4A22-BDEE-702D6BA36F69}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2D796945-A523-4A22-BDEE-702D6BA36F69}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2D796945-A523-4A22-BDEE-702D6BA36F69}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2D796945-A523-4A22-BDEE-702D6BA36F69}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.30204.135
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Syroot.Worms", "library\Syroot.Worms\Syroot.Worms.csproj", "{DD76B6AA-5A5A-4FCD-95AA-9552977525A1}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Syroot.Worms.Scratchpad", "tool\Syroot.Worms.Scratchpad\Syroot.Worms.Scratchpad.csproj", "{0D7F9DC3-7268-494E-BA1E-6C01525EB9AB}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Syroot.Worms.Mgame.Launcher", "tool\Syroot.Worms.Mgame.Launcher\Syroot.Worms.Mgame.Launcher.csproj", "{510EE83E-9C52-40FD-AC7E-C4981EBF4182}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Syroot.Worms.Armageddon", "library\Syroot.Worms.Armageddon\Syroot.Worms.Armageddon.csproj", "{D9694108-539C-4DEE-B5DD-284208D48B46}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Syroot.Worms.Armageddon.ProjectX", "library\Syroot.Worms.Armageddon.ProjectX\Syroot.Worms.Armageddon.ProjectX.csproj", "{AC9F52FA-F552-49E0-83AE-79759BF44FED}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Syroot.Worms.WorldParty", "library\Syroot.Worms.WorldParty\Syroot.Worms.WorldParty.csproj", "{4E124BBA-15B5-422E-93D5-96EA7D4180F3}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Syroot.Worms.Worms2", "library\Syroot.Worms.Worms2\Syroot.Worms.Worms2.csproj", "{BBCECFCC-F2FD-4C4D-A6E9-CC7AA5F10FDD}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Syroot.Worms.Mgame", "library\Syroot.Worms.Mgame\Syroot.Worms.Mgame.csproj", "{BD8079D9-FDB5-4C7D-8AD4-C80ADC4A4B26}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Test Projects", "Test Projects", "{99E56312-A064-4AD3-8443-0B56A5F76E6B}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Library Projects", "Library Projects", "{9E964426-D744-405A-9EAA-D8D7A310B614}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tool Projects", "Tool Projects", "{0B9B0B74-3EB1-46A4-BCCC-F2D6AE59A9EE}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Syroot.Worms.WorldParty.Test", "test\Syroot.Worms.WorldParty.Test\Syroot.Worms.WorldParty.Test.csproj", "{239763CD-B7C9-4E8B-A84B-8F24DECF6D7B}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Syroot.Worms.Armageddon.Test", "test\Syroot.Worms.Armageddon.Test\Syroot.Worms.Armageddon.Test.csproj", "{748D16FF-35C6-4249-A1E8-04B2D239C954}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Syroot.Worms.Worms2.Test", "test\Syroot.Worms.Worms2.Test\Syroot.Worms.Worms2.Test.csproj", "{3AAC4992-DDB9-4175-82B9-C57F22E12FF6}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Syroot.Worms.Armageddon.ProjectX.Test", "test\Syroot.Worms.Armageddon.ProjectX.Test\Syroot.Worms.Armageddon.ProjectX.Test.csproj", "{EF308D4E-26A0-471C-B764-9C4EB713BEAE}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Syroot.Worms.Test", "test\Syroot.Worms.Test\Syroot.Worms.Test.csproj", "{351B93B0-301F-42E1-82A0-7FA217154F5D}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Syroot.Worms.Mgame.GameServer", "tool\Syroot.Worms.Mgame.GameServer\Syroot.Worms.Mgame.GameServer.csproj", "{392E4CA2-61D9-4BE1-B065-8801A9F102B8}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Syroot.Worms.Mgame.Test", "test\Syroot.Worms.Mgame.Test\Syroot.Worms.Mgame.Test.csproj", "{212F8090-9775-4098-BD44-9ABC01FBE553}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Syroot.Worms.Shell", "tool\Syroot.Worms.Shell\Syroot.Worms.Shell.csproj", "{1FAB6B9F-2585-46DC-81C0-579DC808C389}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = " Solution Items", " Solution Items", "{8A49F314-1011-4819-A8F6-0EDDA94A9C3D}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
build.xml = build.xml
|
||||
test.xml = test.xml
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Syroot.Worms.Worms2.GameServer", "tool\Syroot.Worms.Worms2.GameServer\Syroot.Worms.Worms2.GameServer.csproj", "{13ABF717-5809-441D-A5D8-66E1EE75A390}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Module Projects", "Module Projects", "{2A8C6AAA-BA1F-4FB6-A598-114930217B6C}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WormKitTools", "module\WormKitTools\WormKitTools.vcxproj", "{068A8647-0A66-4E39-983B-43ACEAC5C937}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FrontendKitWS", "module\FrontendKitWS\FrontendKitWS.vcxproj", "{E391EA12-B929-466C-932F-DEF72B8CEB5D}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fkDesPatch", "module\fkDesPatch\fkDesPatch.vcxproj", "{6B4D57EA-4642-440A-AB62-2E011D7B64E1}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fkNetcode", "module\fkNetcode\fkNetcode.vcxproj", "{C4138811-7CFA-4826-A3DD-AF2B618EAFC1}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wkUnlimiter", "module\wkUnlimiter\wkUnlimiter.vcxproj", "{CDED4B7C-91DF-45D3-9704-DB8750BDAF5B}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{DD76B6AA-5A5A-4FCD-95AA-9552977525A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{DD76B6AA-5A5A-4FCD-95AA-9552977525A1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{DD76B6AA-5A5A-4FCD-95AA-9552977525A1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{DD76B6AA-5A5A-4FCD-95AA-9552977525A1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{0D7F9DC3-7268-494E-BA1E-6C01525EB9AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0D7F9DC3-7268-494E-BA1E-6C01525EB9AB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0D7F9DC3-7268-494E-BA1E-6C01525EB9AB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0D7F9DC3-7268-494E-BA1E-6C01525EB9AB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{510EE83E-9C52-40FD-AC7E-C4981EBF4182}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{510EE83E-9C52-40FD-AC7E-C4981EBF4182}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{510EE83E-9C52-40FD-AC7E-C4981EBF4182}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{510EE83E-9C52-40FD-AC7E-C4981EBF4182}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D9694108-539C-4DEE-B5DD-284208D48B46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D9694108-539C-4DEE-B5DD-284208D48B46}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D9694108-539C-4DEE-B5DD-284208D48B46}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D9694108-539C-4DEE-B5DD-284208D48B46}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{AC9F52FA-F552-49E0-83AE-79759BF44FED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AC9F52FA-F552-49E0-83AE-79759BF44FED}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AC9F52FA-F552-49E0-83AE-79759BF44FED}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{AC9F52FA-F552-49E0-83AE-79759BF44FED}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4E124BBA-15B5-422E-93D5-96EA7D4180F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4E124BBA-15B5-422E-93D5-96EA7D4180F3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4E124BBA-15B5-422E-93D5-96EA7D4180F3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4E124BBA-15B5-422E-93D5-96EA7D4180F3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BBCECFCC-F2FD-4C4D-A6E9-CC7AA5F10FDD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BBCECFCC-F2FD-4C4D-A6E9-CC7AA5F10FDD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BBCECFCC-F2FD-4C4D-A6E9-CC7AA5F10FDD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BBCECFCC-F2FD-4C4D-A6E9-CC7AA5F10FDD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BD8079D9-FDB5-4C7D-8AD4-C80ADC4A4B26}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BD8079D9-FDB5-4C7D-8AD4-C80ADC4A4B26}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BD8079D9-FDB5-4C7D-8AD4-C80ADC4A4B26}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BD8079D9-FDB5-4C7D-8AD4-C80ADC4A4B26}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{239763CD-B7C9-4E8B-A84B-8F24DECF6D7B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{239763CD-B7C9-4E8B-A84B-8F24DECF6D7B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{239763CD-B7C9-4E8B-A84B-8F24DECF6D7B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{239763CD-B7C9-4E8B-A84B-8F24DECF6D7B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{748D16FF-35C6-4249-A1E8-04B2D239C954}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{748D16FF-35C6-4249-A1E8-04B2D239C954}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{748D16FF-35C6-4249-A1E8-04B2D239C954}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{748D16FF-35C6-4249-A1E8-04B2D239C954}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{3AAC4992-DDB9-4175-82B9-C57F22E12FF6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3AAC4992-DDB9-4175-82B9-C57F22E12FF6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3AAC4992-DDB9-4175-82B9-C57F22E12FF6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3AAC4992-DDB9-4175-82B9-C57F22E12FF6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{EF308D4E-26A0-471C-B764-9C4EB713BEAE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EF308D4E-26A0-471C-B764-9C4EB713BEAE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EF308D4E-26A0-471C-B764-9C4EB713BEAE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{EF308D4E-26A0-471C-B764-9C4EB713BEAE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{351B93B0-301F-42E1-82A0-7FA217154F5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{351B93B0-301F-42E1-82A0-7FA217154F5D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{351B93B0-301F-42E1-82A0-7FA217154F5D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{351B93B0-301F-42E1-82A0-7FA217154F5D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{392E4CA2-61D9-4BE1-B065-8801A9F102B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{392E4CA2-61D9-4BE1-B065-8801A9F102B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{392E4CA2-61D9-4BE1-B065-8801A9F102B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{392E4CA2-61D9-4BE1-B065-8801A9F102B8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{212F8090-9775-4098-BD44-9ABC01FBE553}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{212F8090-9775-4098-BD44-9ABC01FBE553}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{212F8090-9775-4098-BD44-9ABC01FBE553}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{212F8090-9775-4098-BD44-9ABC01FBE553}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{1FAB6B9F-2585-46DC-81C0-579DC808C389}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1FAB6B9F-2585-46DC-81C0-579DC808C389}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1FAB6B9F-2585-46DC-81C0-579DC808C389}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1FAB6B9F-2585-46DC-81C0-579DC808C389}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{13ABF717-5809-441D-A5D8-66E1EE75A390}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{13ABF717-5809-441D-A5D8-66E1EE75A390}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{13ABF717-5809-441D-A5D8-66E1EE75A390}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{13ABF717-5809-441D-A5D8-66E1EE75A390}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{068A8647-0A66-4E39-983B-43ACEAC5C937}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{068A8647-0A66-4E39-983B-43ACEAC5C937}.Debug|Any CPU.Build.0 = Debug|Win32
|
||||
{068A8647-0A66-4E39-983B-43ACEAC5C937}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{068A8647-0A66-4E39-983B-43ACEAC5C937}.Release|Any CPU.Build.0 = Release|Win32
|
||||
{E391EA12-B929-466C-932F-DEF72B8CEB5D}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{E391EA12-B929-466C-932F-DEF72B8CEB5D}.Debug|Any CPU.Build.0 = Debug|Win32
|
||||
{E391EA12-B929-466C-932F-DEF72B8CEB5D}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{E391EA12-B929-466C-932F-DEF72B8CEB5D}.Release|Any CPU.Build.0 = Release|Win32
|
||||
{6B4D57EA-4642-440A-AB62-2E011D7B64E1}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{6B4D57EA-4642-440A-AB62-2E011D7B64E1}.Debug|Any CPU.Build.0 = Debug|Win32
|
||||
{6B4D57EA-4642-440A-AB62-2E011D7B64E1}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{6B4D57EA-4642-440A-AB62-2E011D7B64E1}.Release|Any CPU.Build.0 = Release|Win32
|
||||
{C4138811-7CFA-4826-A3DD-AF2B618EAFC1}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{C4138811-7CFA-4826-A3DD-AF2B618EAFC1}.Debug|Any CPU.Build.0 = Debug|Win32
|
||||
{C4138811-7CFA-4826-A3DD-AF2B618EAFC1}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{C4138811-7CFA-4826-A3DD-AF2B618EAFC1}.Release|Any CPU.Build.0 = Release|Win32
|
||||
{CDED4B7C-91DF-45D3-9704-DB8750BDAF5B}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{CDED4B7C-91DF-45D3-9704-DB8750BDAF5B}.Debug|Any CPU.Build.0 = Debug|Win32
|
||||
{CDED4B7C-91DF-45D3-9704-DB8750BDAF5B}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{CDED4B7C-91DF-45D3-9704-DB8750BDAF5B}.Release|Any CPU.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{DD76B6AA-5A5A-4FCD-95AA-9552977525A1} = {9E964426-D744-405A-9EAA-D8D7A310B614}
|
||||
{0D7F9DC3-7268-494E-BA1E-6C01525EB9AB} = {0B9B0B74-3EB1-46A4-BCCC-F2D6AE59A9EE}
|
||||
{510EE83E-9C52-40FD-AC7E-C4981EBF4182} = {0B9B0B74-3EB1-46A4-BCCC-F2D6AE59A9EE}
|
||||
{D9694108-539C-4DEE-B5DD-284208D48B46} = {9E964426-D744-405A-9EAA-D8D7A310B614}
|
||||
{AC9F52FA-F552-49E0-83AE-79759BF44FED} = {9E964426-D744-405A-9EAA-D8D7A310B614}
|
||||
{4E124BBA-15B5-422E-93D5-96EA7D4180F3} = {9E964426-D744-405A-9EAA-D8D7A310B614}
|
||||
{BBCECFCC-F2FD-4C4D-A6E9-CC7AA5F10FDD} = {9E964426-D744-405A-9EAA-D8D7A310B614}
|
||||
{BD8079D9-FDB5-4C7D-8AD4-C80ADC4A4B26} = {9E964426-D744-405A-9EAA-D8D7A310B614}
|
||||
{239763CD-B7C9-4E8B-A84B-8F24DECF6D7B} = {99E56312-A064-4AD3-8443-0B56A5F76E6B}
|
||||
{748D16FF-35C6-4249-A1E8-04B2D239C954} = {99E56312-A064-4AD3-8443-0B56A5F76E6B}
|
||||
{3AAC4992-DDB9-4175-82B9-C57F22E12FF6} = {99E56312-A064-4AD3-8443-0B56A5F76E6B}
|
||||
{EF308D4E-26A0-471C-B764-9C4EB713BEAE} = {99E56312-A064-4AD3-8443-0B56A5F76E6B}
|
||||
{351B93B0-301F-42E1-82A0-7FA217154F5D} = {99E56312-A064-4AD3-8443-0B56A5F76E6B}
|
||||
{392E4CA2-61D9-4BE1-B065-8801A9F102B8} = {0B9B0B74-3EB1-46A4-BCCC-F2D6AE59A9EE}
|
||||
{212F8090-9775-4098-BD44-9ABC01FBE553} = {99E56312-A064-4AD3-8443-0B56A5F76E6B}
|
||||
{1FAB6B9F-2585-46DC-81C0-579DC808C389} = {0B9B0B74-3EB1-46A4-BCCC-F2D6AE59A9EE}
|
||||
{13ABF717-5809-441D-A5D8-66E1EE75A390} = {0B9B0B74-3EB1-46A4-BCCC-F2D6AE59A9EE}
|
||||
{068A8647-0A66-4E39-983B-43ACEAC5C937} = {2A8C6AAA-BA1F-4FB6-A598-114930217B6C}
|
||||
{E391EA12-B929-466C-932F-DEF72B8CEB5D} = {2A8C6AAA-BA1F-4FB6-A598-114930217B6C}
|
||||
{6B4D57EA-4642-440A-AB62-2E011D7B64E1} = {2A8C6AAA-BA1F-4FB6-A598-114930217B6C}
|
||||
{C4138811-7CFA-4826-A3DD-AF2B618EAFC1} = {2A8C6AAA-BA1F-4FB6-A598-114930217B6C}
|
||||
{CDED4B7C-91DF-45D3-9704-DB8750BDAF5B} = {2A8C6AAA-BA1F-4FB6-A598-114930217B6C}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {1CD4EDE2-A5FB-4A58-A850-3506AB7E7B69}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
@ -1,33 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Syroot.Worms.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents extension methods for <see cref="BinaryReader"/> instances.
|
||||
/// </summary>
|
||||
internal static class BinaryReaderExtensions
|
||||
{
|
||||
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Reads a raw byte structure from the current stream and returns it.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the structure to read.</typeparam>
|
||||
/// <param name="self">The extended <see cref="BinaryReader"/> instance.</param>
|
||||
/// <returns>The structure of type <typeparamref name="T"/>.</returns>
|
||||
internal static T ReadStruct<T>(this BinaryReader self) where T : struct
|
||||
{
|
||||
// Read the raw bytes of the structure.
|
||||
byte[] bytes = self.ReadBytes(Marshal.SizeOf<T>());
|
||||
|
||||
// Convert them to a structure instance and return it.
|
||||
GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
|
||||
T instance = Marshal.PtrToStructure<T>(handle.AddrOfPinnedObject());
|
||||
handle.Free();
|
||||
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Syroot.Worms.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents extension methods for <see cref="BinaryWriter"/> instances.
|
||||
/// </summary>
|
||||
internal static class BinaryWriterExtensions
|
||||
{
|
||||
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Writes the bytes of a structure into the current stream.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the structure to read.</typeparam>
|
||||
/// <param name="self">The extended <see cref="BinaryWriter"/> instance.</param>
|
||||
/// <param name="instance">The structure to write.</param>
|
||||
internal static void Write<T>(this BinaryWriter self, T instance) where T : struct
|
||||
{
|
||||
// Get the raw bytes of the structure instance.
|
||||
byte[] bytes = new byte[Marshal.SizeOf<T>()];
|
||||
|
||||
GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
|
||||
Marshal.StructureToPtr(instance, handle.AddrOfPinnedObject(), false);
|
||||
handle.Free();
|
||||
|
||||
// Write the bytes to the stream.
|
||||
self.Write(bytes);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
namespace Syroot.Worms.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents extension methods for <see cref="Byte"/> array instances.
|
||||
/// </summary>
|
||||
internal static class ByteArrayExtensions
|
||||
{
|
||||
// ---- METHODS (INTERNAL) -------------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Returns <c>true</c> if the current byte array instance holds the same values as the given one.
|
||||
/// </summary>
|
||||
/// <param name="self">The extended byte array instance.</param>
|
||||
/// <param name="other">The byte array instance to compare with.</param>
|
||||
/// <returns><c>true</c> if both instances hold the same values, otherwise <c>false</c>.</returns>
|
||||
internal static bool Compare(this byte[] self, byte[] other)
|
||||
{
|
||||
if (self.Length != other.Length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < self.Length; i++)
|
||||
{
|
||||
if (self[i] != other[i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,230 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Syroot.IO;
|
||||
using Syroot.Worms.Core;
|
||||
|
||||
namespace Syroot.Worms.Gen2
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a directory of files stored in a DIR file, mostly used to store graphics files. Due to the nowadays
|
||||
/// small size of typical directories, the entries and data are loaded directly into a dictionary to profit from
|
||||
/// optimal performance when accessing and manipulating the directory.
|
||||
/// Used by W2, WA and WWP. S. https://worms2d.info/Graphics_directory.
|
||||
/// </summary>
|
||||
public class Archive : Dictionary<string, byte[]>, ILoadableFile, ISaveableFile
|
||||
{
|
||||
// ---- CONSTANTS ----------------------------------------------------------------------------------------------
|
||||
|
||||
private const int _signature = 0x1A524944; // "DIR", 0x1A
|
||||
private const int _tocSignature = 0x0000000A;
|
||||
|
||||
private const int _hashBits = 10;
|
||||
private const int _hashSize = 1 << _hashBits;
|
||||
|
||||
// ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Archive"/> class.
|
||||
/// </summary>
|
||||
public Archive()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Archive"/> class, loading the data from the given
|
||||
/// <see cref="Stream"/>.
|
||||
/// </summary>
|
||||
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
|
||||
public Archive(Stream stream)
|
||||
{
|
||||
Load(stream);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Archive"/> class, loading the data from the given file.
|
||||
/// </summary>
|
||||
/// <param name="fileName">The name of the file to load the data from.</param>
|
||||
public Archive(string fileName)
|
||||
{
|
||||
Load(fileName);
|
||||
}
|
||||
|
||||
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Loads the data from the given <see cref="Stream"/>.
|
||||
/// </summary>
|
||||
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
|
||||
public void Load(Stream stream)
|
||||
{
|
||||
if (!stream.CanSeek)
|
||||
{
|
||||
throw new ArgumentException("Stream requires to be seekable.", nameof(stream));
|
||||
}
|
||||
|
||||
Clear();
|
||||
using (BinaryDataReader reader = new BinaryDataReader(stream, Encoding.ASCII, true))
|
||||
{
|
||||
// Read the header.
|
||||
if (reader.ReadInt32() != _signature)
|
||||
{
|
||||
throw new InvalidDataException("Invalid DIR file signature.");
|
||||
}
|
||||
int fileSize = reader.ReadInt32();
|
||||
int tocOffset = reader.ReadInt32();
|
||||
|
||||
// Read the table of contents.
|
||||
reader.Position = tocOffset;
|
||||
int tocSignature = reader.ReadInt32();
|
||||
if (tocSignature != _tocSignature)
|
||||
{
|
||||
throw new InvalidDataException("Invalid DIR table of contents signature.");
|
||||
}
|
||||
// Generate a data dictionary out of the hash table and file entries.
|
||||
int[] hashTable = reader.ReadInt32s(_hashSize);
|
||||
foreach (int entryOffset in hashTable)
|
||||
{
|
||||
// If the hash is not 0, it points to a list of files which have a hash being the hash table index.
|
||||
if (entryOffset > 0)
|
||||
{
|
||||
int nextEntryOffset = entryOffset;
|
||||
do
|
||||
{
|
||||
reader.Position = tocOffset + nextEntryOffset;
|
||||
nextEntryOffset = reader.ReadInt32();
|
||||
int offset = reader.ReadInt32();
|
||||
int length = reader.ReadInt32();
|
||||
string name = reader.ReadString(BinaryStringFormat.ZeroTerminated);
|
||||
using (reader.TemporarySeek(offset, SeekOrigin.Begin))
|
||||
{
|
||||
Add(name, reader.ReadBytes(length));
|
||||
}
|
||||
} while (nextEntryOffset != 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads the data from the given file.
|
||||
/// </summary>
|
||||
/// <param name="fileName">The name of the file to load the data from.</param>
|
||||
public void Load(string fileName)
|
||||
{
|
||||
using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
Load(stream);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves the data into the given <paramref name="stream"/>.
|
||||
/// </summary>
|
||||
/// <param name="stream">The <see cref="Stream"/> to save the data in.</param>
|
||||
public void Save(Stream stream)
|
||||
{
|
||||
using (BinaryDataWriter writer = new BinaryDataWriter(stream))
|
||||
{
|
||||
// Write the header.
|
||||
writer.Write(_signature);
|
||||
Offset fileSizeOffset = writer.ReserveOffset();
|
||||
Offset tocOffset = writer.ReserveOffset();
|
||||
|
||||
// Write the data and build the hash table and file entries.
|
||||
List<HashTableEntry>[] hashTable = new List<HashTableEntry>[_hashSize];
|
||||
foreach (KeyValuePair<string, byte[]> item in this)
|
||||
{
|
||||
HashTableEntry entry = new HashTableEntry()
|
||||
{
|
||||
Name = item.Key,
|
||||
Offset = (int)writer.Position,
|
||||
Length = item.Value.Length
|
||||
};
|
||||
writer.Write(item.Value);
|
||||
|
||||
int hash = CalculateHash(item.Key);
|
||||
if (hashTable[hash] == null)
|
||||
{
|
||||
hashTable[hash] = new List<HashTableEntry>();
|
||||
}
|
||||
hashTable[hash].Add(entry);
|
||||
}
|
||||
|
||||
// Write the hash table and file entries.
|
||||
int tocStart = (int)writer.Position;
|
||||
int fileEntryOffset = sizeof(int) + _hashSize * sizeof(int);
|
||||
tocOffset.Satisfy(tocStart);
|
||||
writer.Write(_tocSignature);
|
||||
for (int i = 0; i < _hashSize; i++)
|
||||
{
|
||||
List<HashTableEntry> entries = hashTable[i];
|
||||
if (entries == null)
|
||||
{
|
||||
writer.Write(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Write the entries resolving to the current hash.
|
||||
writer.Write(fileEntryOffset);
|
||||
using (writer.TemporarySeek(tocStart + fileEntryOffset, SeekOrigin.Begin))
|
||||
{
|
||||
for (int j = 0; j < entries.Count; j++)
|
||||
{
|
||||
HashTableEntry entry = entries[j];
|
||||
Offset nextEntryOffset = writer.ReserveOffset();
|
||||
writer.Write(entry.Offset);
|
||||
writer.Write(entry.Length);
|
||||
writer.Write(entry.Name, BinaryStringFormat.ZeroTerminated);
|
||||
writer.Align(4);
|
||||
if (j < entries.Count - 1)
|
||||
{
|
||||
nextEntryOffset.Satisfy((int)writer.Position - tocStart);
|
||||
}
|
||||
}
|
||||
fileEntryOffset = (int)writer.Position - tocStart;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fileSizeOffset.Satisfy(tocStart + fileEntryOffset - 1);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves the data in the file with the given <paramref name="fileName"/>.
|
||||
/// </summary>
|
||||
/// <param name="fileName">The name of the file to save the data in.</param>
|
||||
public void Save(string fileName)
|
||||
{
|
||||
using (FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None))
|
||||
{
|
||||
Save(stream);
|
||||
}
|
||||
}
|
||||
|
||||
// ---- METHODS (PRIVATE) --------------------------------------------------------------------------------------
|
||||
|
||||
private int CalculateHash(string name)
|
||||
{
|
||||
int hash = 0;
|
||||
for (int i = 0; i < name.Length; i++)
|
||||
{
|
||||
hash = ((hash << 1) % _hashSize) | (hash >> (_hashBits - 1) & 1);
|
||||
hash += name[i];
|
||||
hash %= _hashSize;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
// ---- STRUCTURES ---------------------------------------------------------------------------------------------
|
||||
|
||||
private struct HashTableEntry
|
||||
{
|
||||
internal string Name;
|
||||
internal int Offset;
|
||||
internal int Length;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,147 +0,0 @@
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Syroot.IO;
|
||||
using Syroot.Maths;
|
||||
using Syroot.Worms.Core;
|
||||
|
||||
namespace Syroot.Worms.Gen2.Armageddon
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents map configuration stored by the land generator in LAND.DAT files.
|
||||
/// Used by WA and WWP. S. https://worms2d.info/Land_Data_file.
|
||||
/// </summary>
|
||||
public class LandData : ILoadableFile
|
||||
{
|
||||
// ---- CONSTANTS ----------------------------------------------------------------------------------------------
|
||||
|
||||
private const int _signature = 0x1A444E4C; // "LND", 0x1A
|
||||
|
||||
// ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LandData"/> class.
|
||||
/// </summary>
|
||||
public LandData()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LandData"/> class, loading the data from the given
|
||||
/// <see cref="Stream"/>.
|
||||
/// </summary>
|
||||
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
|
||||
public LandData(Stream stream)
|
||||
{
|
||||
Load(stream);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LandData"/> class, loading the data from the given file.
|
||||
/// </summary>
|
||||
/// <param name="fileName">The name of the file to load the data from.</param>
|
||||
public LandData(string fileName)
|
||||
{
|
||||
Load(fileName);
|
||||
}
|
||||
|
||||
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the size of the landscape in pixels.
|
||||
/// </summary>
|
||||
public Vector2 Size { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether an indestructible top border will be enabled.
|
||||
/// </summary>
|
||||
public bool TopBorder { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the height of the water in pixels.
|
||||
/// </summary>
|
||||
public int WaterHeight { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets an array of coordinates at which objects can be placed.
|
||||
/// </summary>
|
||||
public Vector2[] ObjectLocations { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the visual foreground image.
|
||||
/// </summary>
|
||||
public Image Foreground { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the collision mask of the landscape.
|
||||
/// </summary>
|
||||
public Image CollisionMask { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the visual background image.
|
||||
/// </summary>
|
||||
public Image Background { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the path to the land image file.
|
||||
/// </summary>
|
||||
public string LandTexturePath { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the path to the Water.dir file.
|
||||
/// </summary>
|
||||
public string WaterDirPath { get; set; }
|
||||
|
||||
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Loads the data from the given <see cref="Stream"/>.
|
||||
/// </summary>
|
||||
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
|
||||
public void Load(Stream stream)
|
||||
{
|
||||
using (BinaryDataReader reader = new BinaryDataReader(stream, Encoding.ASCII, true))
|
||||
{
|
||||
// Read the header.
|
||||
if (reader.ReadInt32() != _signature)
|
||||
{
|
||||
throw new InvalidDataException("Invalid LND file signature.");
|
||||
}
|
||||
int fileLength = reader.ReadInt32();
|
||||
|
||||
// Read the data.
|
||||
Size = reader.ReadStruct<Vector2>();
|
||||
TopBorder = reader.ReadBoolean(BinaryBooleanFormat.NonZeroDword);
|
||||
WaterHeight = reader.ReadInt32();
|
||||
|
||||
// Read the possible object coordinate array.
|
||||
int badObjectLocations = reader.ReadInt32(); // TODO: Check what this is used for.
|
||||
ObjectLocations = new Vector2[reader.ReadInt32()];
|
||||
for (int i = 0; i < ObjectLocations.Length; i++)
|
||||
{
|
||||
ObjectLocations[i] = reader.ReadStruct<Vector2>();
|
||||
}
|
||||
|
||||
// Read the image data.
|
||||
Foreground = new Image(stream);
|
||||
CollisionMask = new Image(stream);
|
||||
Background = new Image(stream);
|
||||
|
||||
// Read the file paths.
|
||||
LandTexturePath = reader.ReadString(BinaryStringFormat.ByteLengthPrefix);
|
||||
WaterDirPath = reader.ReadString(BinaryStringFormat.ByteLengthPrefix);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads the data from the given file.
|
||||
/// </summary>
|
||||
/// <param name="fileName">The name of the file to load the data from.</param>
|
||||
public void Load(string fileName)
|
||||
{
|
||||
using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
Load(stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Syroot.Worms.Gen2.Armageddon
|
||||
{
|
||||
class Mission
|
||||
{
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Syroot.Worms.Gen2.Armageddon
|
||||
{
|
||||
class MonoMap
|
||||
{
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Syroot.Worms.Gen2.Armageddon
|
||||
{
|
||||
class Replay
|
||||
{
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,35 +0,0 @@
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Syroot.Worms.Gen2.Armageddon
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the configuration of a weapon.
|
||||
/// </summary>
|
||||
[DebuggerDisplay("Ammo={Ammunition} Power={Power} Delay={Delay} Prob={Probability}")]
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct SchemeWeaponSetting
|
||||
{
|
||||
/// <summary>
|
||||
/// The amount of this weapon with which a team is equipped at game start. 10 and negative values represent
|
||||
/// infinity.
|
||||
/// </summary>
|
||||
public sbyte Ammunition;
|
||||
|
||||
/// <summary>
|
||||
/// The power of this weapon.
|
||||
/// </summary>
|
||||
public byte Power;
|
||||
|
||||
/// <summary>
|
||||
/// The number of turns required to be taken by each team before this weapon becomes available. Negative values
|
||||
/// represent infinity.
|
||||
/// </summary>
|
||||
public sbyte Delay;
|
||||
|
||||
/// <summary>
|
||||
/// The percentual chance of this weapon to appear in crates. Has no effect for super weapons.
|
||||
/// </summary>
|
||||
public sbyte Probability;
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Syroot.Worms.Gen2.Armageddon
|
||||
{
|
||||
class TeamContainer
|
||||
{
|
||||
}
|
||||
}
|
@ -1,158 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Syroot.IO;
|
||||
using Syroot.Maths;
|
||||
using Syroot.Worms.Core;
|
||||
|
||||
namespace Syroot.Worms.Gen2
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a (palettized) graphical image stored in an IMG file, possibly compressed.
|
||||
/// Used by W2, WA and WWP. S. https://worms2d.info/Image_file.
|
||||
/// </summary>
|
||||
public class Image : ILoadableFile
|
||||
{
|
||||
// ---- CONSTANTS ----------------------------------------------------------------------------------------------
|
||||
|
||||
private const int _signature = 0x1A474D49; // "IMG", 0x1A
|
||||
|
||||
// ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Image"/> class.
|
||||
/// </summary>
|
||||
public Image()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Image"/> class, loading the data from the given
|
||||
/// <see cref="Stream"/>.
|
||||
/// </summary>
|
||||
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
|
||||
public Image(Stream stream)
|
||||
{
|
||||
Load(stream);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Image"/> class, loading the data from the given file.
|
||||
/// </summary>
|
||||
/// <param name="fileName">The name of the file to load the data from.</param>
|
||||
public Image(string fileName)
|
||||
{
|
||||
Load(fileName);
|
||||
}
|
||||
|
||||
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Gets an optional description of the image contents.
|
||||
/// </summary>
|
||||
public string Description { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of bits required to describe a color per pixel.
|
||||
/// </summary>
|
||||
public int BitsPerPixel { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the color palette of the image. The first color must always be black.
|
||||
/// </summary>
|
||||
public Color[] Palette { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size of the image in pixels.
|
||||
/// </summary>
|
||||
public Vector2 Size { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the data of the image pixels.
|
||||
/// </summary>
|
||||
public byte[] Data { get; private set; }
|
||||
|
||||
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Loads the data from the given <see cref="Stream"/>.
|
||||
/// </summary>
|
||||
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
|
||||
public void Load(Stream stream)
|
||||
{
|
||||
using (BinaryDataReader reader = new BinaryDataReader(stream, Encoding.ASCII, true))
|
||||
{
|
||||
// Read the header.
|
||||
if (reader.ReadInt32() != _signature)
|
||||
{
|
||||
throw new InvalidDataException("Invalid IMG file signature.");
|
||||
}
|
||||
int fileSize = reader.ReadInt32();
|
||||
|
||||
// Read an optional string describing the image contents or the bits per pixel.
|
||||
BitsPerPixel = reader.ReadByte();
|
||||
if (BitsPerPixel == 0)
|
||||
{
|
||||
Description = String.Empty;
|
||||
BitsPerPixel = reader.ReadByte();
|
||||
}
|
||||
else if (BitsPerPixel > 32)
|
||||
{
|
||||
Description = (char)BitsPerPixel + reader.ReadString(BinaryStringFormat.ZeroTerminated);
|
||||
BitsPerPixel = reader.ReadByte();
|
||||
}
|
||||
|
||||
// Read image flags describing the format and availability of the following contents.
|
||||
Flags flags = (Flags)reader.ReadByte();
|
||||
|
||||
// Read the image palette if available. The first color of the palette is implicitly black.
|
||||
if (flags.HasFlag(Flags.Palettized))
|
||||
{
|
||||
int colorCount = reader.ReadInt16();
|
||||
Palette = new Color[colorCount + 1];
|
||||
Palette[0] = Color.Black;
|
||||
for (int i = 1; i <= colorCount; i++)
|
||||
{
|
||||
Palette[i] = new Color(reader.ReadByte(), reader.ReadByte(), reader.ReadByte());
|
||||
}
|
||||
}
|
||||
|
||||
Size = new Vector2(reader.ReadInt16(), reader.ReadInt16());
|
||||
|
||||
// Read the bytes, which might be compressed.
|
||||
byte[] data = new byte[Size.X * Size.Y * BitsPerPixel / 8];
|
||||
if (flags.HasFlag(Flags.Compressed))
|
||||
{
|
||||
Team17Compression.Decompress(reader.BaseStream, ref data);
|
||||
}
|
||||
else
|
||||
{
|
||||
data = reader.ReadBytes(data.Length);
|
||||
}
|
||||
|
||||
Data = data;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads the data from the given file.
|
||||
/// </summary>
|
||||
/// <param name="fileName">The name of the file to load the data from.</param>
|
||||
public void Load(string fileName)
|
||||
{
|
||||
using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
Load(stream);
|
||||
}
|
||||
}
|
||||
|
||||
// ---- ENUMERATIONS -------------------------------------------------------------------------------------------
|
||||
|
||||
[Flags]
|
||||
private enum Flags
|
||||
{
|
||||
Compressed = 1 << 6,
|
||||
Palettized = 1 << 7
|
||||
}
|
||||
}
|
||||
}
|
@ -1,147 +0,0 @@
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Syroot.IO;
|
||||
using Syroot.Maths;
|
||||
using Syroot.Worms.Core;
|
||||
|
||||
namespace Syroot.Worms.Gen2.Worms2
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents map configuration stored by the land generator in LAND.DAT files.
|
||||
/// Used by W2. S. https://worms2d.info/Land_Data_file.
|
||||
/// </summary>
|
||||
public class LandData : ILoadableFile
|
||||
{
|
||||
// ---- CONSTANTS ----------------------------------------------------------------------------------------------
|
||||
|
||||
private const int _signature = 0x1A444E4C; // "LND", 0x1A
|
||||
|
||||
// ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LandData"/> class.
|
||||
/// </summary>
|
||||
public LandData()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LandData"/> class, loading the data from the given
|
||||
/// <see cref="Stream"/>.
|
||||
/// </summary>
|
||||
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
|
||||
public LandData(Stream stream)
|
||||
{
|
||||
Load(stream);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LandData"/> class, loading the data from the given file.
|
||||
/// </summary>
|
||||
/// <param name="fileName">The name of the file to load the data from.</param>
|
||||
public LandData(string fileName)
|
||||
{
|
||||
Load(fileName);
|
||||
}
|
||||
|
||||
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the size of the landscape in pixels.
|
||||
/// </summary>
|
||||
public Vector2 Size { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether an indestructible top border will be enabled.
|
||||
/// </summary>
|
||||
public bool TopBorder { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets an array of coordinates at which objects can be placed.
|
||||
/// </summary>
|
||||
public Vector2[] ObjectLocations { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the visual foreground image.
|
||||
/// </summary>
|
||||
public Image Foreground { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the collision mask of the landscape.
|
||||
/// </summary>
|
||||
public Image CollisionMask { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the visual background image.
|
||||
/// </summary>
|
||||
public Image Background { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets an image of unknown use.
|
||||
/// </summary>
|
||||
public Image UnknownImage { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the path to the land image file.
|
||||
/// </summary>
|
||||
public string LandTexturePath { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the path to the Water.dir file.
|
||||
/// </summary>
|
||||
public string WaterDirPath { get; set; }
|
||||
|
||||
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Loads the data from the given <see cref="Stream"/>.
|
||||
/// </summary>
|
||||
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
|
||||
public void Load(Stream stream)
|
||||
{
|
||||
using (BinaryDataReader reader = new BinaryDataReader(stream, Encoding.ASCII, true))
|
||||
{
|
||||
// Read the header.
|
||||
if (reader.ReadInt32() != _signature)
|
||||
{
|
||||
throw new InvalidDataException("Invalid LND file signature.");
|
||||
}
|
||||
int fileLength = reader.ReadInt32();
|
||||
|
||||
// Read the data.
|
||||
Size = reader.ReadStruct<Vector2>();
|
||||
TopBorder = reader.ReadBoolean(BinaryBooleanFormat.NonZeroDword);
|
||||
|
||||
// Read the possible object coordinate array.
|
||||
ObjectLocations = new Vector2[reader.ReadInt32()];
|
||||
for (int i = 0; i < ObjectLocations.Length; i++)
|
||||
{
|
||||
ObjectLocations[i] = reader.ReadStruct<Vector2>();
|
||||
}
|
||||
int unknown = reader.ReadInt32(); // Seems 0.
|
||||
|
||||
// Read the image data.
|
||||
Foreground = new Image(stream);
|
||||
CollisionMask = new Image(stream);
|
||||
Background = new Image(stream);
|
||||
UnknownImage = new Image(stream);
|
||||
|
||||
// Read the file paths.
|
||||
LandTexturePath = reader.ReadString(BinaryStringFormat.ByteLengthPrefix);
|
||||
WaterDirPath = reader.ReadString(BinaryStringFormat.ByteLengthPrefix);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads the data from the given file.
|
||||
/// </summary>
|
||||
/// <param name="fileName">The name of the file to load the data from.</param>
|
||||
public void Load(string fileName)
|
||||
{
|
||||
using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
Load(stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Syroot.Worms.Gen2.Worms2
|
||||
{
|
||||
class Mission
|
||||
{
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Syroot.Worms.Gen2.Worms2
|
||||
{
|
||||
class MonoMap
|
||||
{
|
||||
}
|
||||
}
|
@ -1,225 +0,0 @@
|
||||
namespace Syroot.Worms.Gen2.Worms2
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the method to determine the next turn's worm.
|
||||
/// </summary>
|
||||
public enum SchemeWormSelect : int
|
||||
{
|
||||
/// <summary>
|
||||
/// Worms are selected in the order in which they appear in the team.
|
||||
/// </summary>
|
||||
Sequential = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Worms are selected randomly.
|
||||
/// </summary>
|
||||
Random = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Worms are selected by a computed rating system.
|
||||
/// </summary>
|
||||
Intelligent = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Worms are selected by the player.
|
||||
/// </summary>
|
||||
Manual = 3
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Represents the weapons in the game.
|
||||
/// </summary>
|
||||
public enum SchemeWeapon
|
||||
{
|
||||
/// <summary>
|
||||
/// The Bazooka weapon.
|
||||
/// </summary>
|
||||
Bazooka,
|
||||
|
||||
/// <summary>
|
||||
/// The Homing Missile weapon.
|
||||
/// </summary>
|
||||
HomingMissile,
|
||||
|
||||
/// <summary>
|
||||
/// The Grenade weapon.
|
||||
/// </summary>
|
||||
Grenade,
|
||||
|
||||
/// <summary>
|
||||
/// The Cluster Bomb weapon.
|
||||
/// </summary>
|
||||
ClusterBomb,
|
||||
|
||||
/// <summary>
|
||||
/// The Banana Bomb weapon.
|
||||
/// </summary>
|
||||
BananaBomb,
|
||||
|
||||
/// <summary>
|
||||
/// The Holy Hand Grenade weapon.
|
||||
/// </summary>
|
||||
HolyHandGrenade,
|
||||
|
||||
/// <summary>
|
||||
/// The Homing Cluster Bomb weapon.
|
||||
/// </summary>
|
||||
HomingClusterBomb,
|
||||
|
||||
/// <summary>
|
||||
/// The Petrol Bomb weapon.
|
||||
/// </summary>
|
||||
PetrolBomb,
|
||||
|
||||
/// <summary>
|
||||
/// The Shotgun weapon.
|
||||
/// </summary>
|
||||
Shotgun,
|
||||
|
||||
/// <summary>
|
||||
/// The Handgun weapon.
|
||||
/// </summary>
|
||||
Handgun,
|
||||
|
||||
/// <summary>
|
||||
/// The Uzi weapon.
|
||||
/// </summary>
|
||||
Uzi,
|
||||
|
||||
/// <summary>
|
||||
/// The Minigun weapon.
|
||||
/// </summary>
|
||||
Minigun,
|
||||
|
||||
/// <summary>
|
||||
/// The Fire Punch weapon.
|
||||
/// </summary>
|
||||
FirePunch,
|
||||
|
||||
/// <summary>
|
||||
/// The Dragon Ball weapon.
|
||||
/// </summary>
|
||||
DragonBall,
|
||||
|
||||
/// <summary>
|
||||
/// The Kamikaze weapon.
|
||||
/// </summary>
|
||||
Kamikaze,
|
||||
|
||||
/// <summary>
|
||||
/// The Dynamite weapon.
|
||||
/// </summary>
|
||||
Dynamite,
|
||||
|
||||
/// <summary>
|
||||
/// The Mine weapon.
|
||||
/// </summary>
|
||||
Mine,
|
||||
|
||||
/// <summary>
|
||||
/// The Ming Vase weapon.
|
||||
/// </summary>
|
||||
MingVase,
|
||||
|
||||
/// <summary>
|
||||
/// The Air Strike weapon.
|
||||
/// </summary>
|
||||
AirStrike,
|
||||
|
||||
/// <summary>
|
||||
/// The Homing Air Strike weapon.
|
||||
/// </summary>
|
||||
HomingAirStrike,
|
||||
|
||||
/// <summary>
|
||||
/// The Napalm Strike weapon.
|
||||
/// </summary>
|
||||
NapalmStrike,
|
||||
|
||||
/// <summary>
|
||||
/// The Mail Strike weapon.
|
||||
/// </summary>
|
||||
MailStrike,
|
||||
|
||||
/// <summary>
|
||||
/// The Girder weapon.
|
||||
/// </summary>
|
||||
Girder,
|
||||
|
||||
/// <summary>
|
||||
/// The Pneumatic Drill weapon.
|
||||
/// </summary>
|
||||
PneumaticDrill,
|
||||
|
||||
/// <summary>
|
||||
/// The Baseball Bat weapon.
|
||||
/// </summary>
|
||||
BaseballBat,
|
||||
|
||||
/// <summary>
|
||||
/// The Prod weapon.
|
||||
/// </summary>
|
||||
Prod,
|
||||
|
||||
/// <summary>
|
||||
/// The Teleport weapon.
|
||||
/// </summary>
|
||||
Teleport,
|
||||
|
||||
/// <summary>
|
||||
/// The Ninja Rope weapon.
|
||||
/// </summary>
|
||||
NinjaRope,
|
||||
|
||||
/// <summary>
|
||||
/// The Bungee weapon.
|
||||
/// </summary>
|
||||
Bungee,
|
||||
|
||||
/// <summary>
|
||||
/// The Parachute weapon.
|
||||
/// </summary>
|
||||
Parachute,
|
||||
|
||||
/// <summary>
|
||||
/// The Sheep weapon.
|
||||
/// </summary>
|
||||
Sheep,
|
||||
|
||||
/// <summary>
|
||||
/// The Mad Cow weapon.
|
||||
/// </summary>
|
||||
MadCow,
|
||||
|
||||
/// <summary>
|
||||
/// The Old Woman weapon.
|
||||
/// </summary>
|
||||
OldWoman,
|
||||
|
||||
/// <summary>
|
||||
/// The Mortar weapon.
|
||||
/// </summary>
|
||||
Mortar,
|
||||
|
||||
/// <summary>
|
||||
/// The Blow Torch weapon.
|
||||
/// </summary>
|
||||
BlowTorch,
|
||||
|
||||
/// <summary>
|
||||
/// The Homing Pigeon weapon.
|
||||
/// </summary>
|
||||
HomingPigeon,
|
||||
|
||||
/// <summary>
|
||||
/// The Super Sheep weapon.
|
||||
/// </summary>
|
||||
SuperSheep,
|
||||
|
||||
/// <summary>
|
||||
/// The Super Banana Bomb weapon.
|
||||
/// </summary>
|
||||
SuperBananaBomb
|
||||
}
|
||||
}
|
@ -1,182 +0,0 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Syroot.Worms.Gen2.Worms2
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the configuration of a weapon.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct SchemeWeaponSetting
|
||||
{
|
||||
/// <summary>
|
||||
/// The amount of this weapon with which a team is equipped at game start. 10 and negative values represent
|
||||
/// infinity.
|
||||
/// </summary>
|
||||
public int Ammunition;
|
||||
|
||||
/// <summary>
|
||||
/// The number of turns required to be taken by each team before this weapon becomes available.
|
||||
/// </summary>
|
||||
public int Delay;
|
||||
|
||||
/// <summary>
|
||||
/// Retreat time after using this weapon. 0 uses the setting from the game options.
|
||||
/// </summary>
|
||||
public int RetreatTime;
|
||||
|
||||
/// <summary>
|
||||
/// <c>true</c> to preselect this weapon in the next turn; otherwise <c>false</c>.
|
||||
/// </summary>
|
||||
public bool Remember;
|
||||
|
||||
/// <summary>
|
||||
/// An unused field with unknown value.
|
||||
/// </summary>
|
||||
public int Unused1;
|
||||
|
||||
/// <summary>
|
||||
/// The amount of this weapon added to the team armory when collected from a crate.
|
||||
/// </summary>
|
||||
public int CrateAmmunition;
|
||||
|
||||
/// <summary>
|
||||
/// The amount of bullets shot at once.
|
||||
/// </summary>
|
||||
public int BulletCount;
|
||||
|
||||
/// <summary>
|
||||
/// The percentual chance of this weapon to appear in crates.
|
||||
/// </summary>
|
||||
public int Probability;
|
||||
|
||||
/// <summary>
|
||||
/// The damage measured in health points which also determines the blast radius.
|
||||
/// </summary>
|
||||
public int Damage;
|
||||
|
||||
/// <summary>
|
||||
/// The pushing power measured in percent.
|
||||
/// </summary>
|
||||
public int BlastPower;
|
||||
|
||||
/// <summary>
|
||||
/// The offset to the bottom of an explosion, measured in percent.
|
||||
/// </summary>
|
||||
public int BlastBias;
|
||||
|
||||
/// <summary>
|
||||
/// The milliseconds required before this weapon starts flying towards its target.
|
||||
/// </summary>
|
||||
public int HomingDelay;
|
||||
|
||||
/// <summary>
|
||||
/// The length in milliseconds this weapon flies towards its target before giving up.
|
||||
/// </summary>
|
||||
public int HomingTime;
|
||||
|
||||
/// <summary>
|
||||
/// The percentual amount this weaopn is affected by wind.
|
||||
/// </summary>
|
||||
public int WindResponse;
|
||||
|
||||
/// <summary>
|
||||
/// An unused field with unknown value.
|
||||
/// </summary>
|
||||
public int Unused2;
|
||||
|
||||
/// <summary>
|
||||
/// The number of clusters into which this weapon explodes.
|
||||
/// </summary>
|
||||
public int ClusterCount;
|
||||
|
||||
/// <summary>
|
||||
/// The speed in which clusters are dispersed in percent.
|
||||
/// </summary>
|
||||
public int ClusterLaunchPower;
|
||||
|
||||
/// <summary>
|
||||
/// The angle in which clusters are dispersed in degrees.
|
||||
/// </summary>
|
||||
public int ClusterLaunchAngle;
|
||||
|
||||
/// <summary>
|
||||
/// The damage of clusters measured in health points which also determines the blast radius.
|
||||
/// </summary>
|
||||
public int ClusterDamage;
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the fuse of this weapon, 0 for default.
|
||||
/// </summary>
|
||||
public int Fuse;
|
||||
|
||||
/// <summary>
|
||||
/// The amount of fire created.
|
||||
/// </summary>
|
||||
public int FireAmount;
|
||||
|
||||
/// <summary>
|
||||
/// The speed in which fire spreads, measured in percent.
|
||||
/// </summary>
|
||||
public int FireSpreadSpeed;
|
||||
|
||||
/// <summary>
|
||||
/// The period in which fire burns, measured in percent.
|
||||
/// </summary>
|
||||
public int FireTime;
|
||||
|
||||
/// <summary>
|
||||
/// The melee impact force in percent.
|
||||
/// </summary>
|
||||
public int MeleeForce;
|
||||
|
||||
/// <summary>
|
||||
/// The melee impact angle in degrees.
|
||||
/// </summary>
|
||||
public int MeleeAngle;
|
||||
|
||||
/// <summary>
|
||||
/// The melee damage in health points.
|
||||
/// </summary>
|
||||
public int MeleeDamage;
|
||||
|
||||
/// <summary>
|
||||
/// The height of the fire punch jump, measured in percent.
|
||||
/// </summary>
|
||||
public int FirePunchHeight;
|
||||
|
||||
/// <summary>
|
||||
/// The damage a dragon ball causes, measured in health points.
|
||||
/// </summary>
|
||||
public int DragonBallDamage;
|
||||
|
||||
/// <summary>
|
||||
/// The power in which a dragon ball launches hit worms, measured in percent.
|
||||
/// </summary>
|
||||
public int DragonBallPower;
|
||||
|
||||
/// <summary>
|
||||
/// The angle in which a dragon ball launches hit worms, measured in degrees.
|
||||
/// </summary>
|
||||
public int DragonBallAngle;
|
||||
|
||||
/// <summary>
|
||||
/// The life time of a launched dragon ball measured in milliseconds.
|
||||
/// </summary>
|
||||
public int DragonBallTime;
|
||||
|
||||
/// <summary>
|
||||
/// The length of digging measured in milliseconds. Applies to Kamikaze and digging tools.
|
||||
/// </summary>
|
||||
public int DiggingTime;
|
||||
|
||||
/// <summary>
|
||||
/// The amount of airstrike clusters thrown.
|
||||
/// </summary>
|
||||
public int StrikeClusterCount;
|
||||
|
||||
/// <summary>
|
||||
/// The angle in which bullets are dispersed, measured in degrees.
|
||||
/// </summary>
|
||||
public int BulletSpreadAngle;
|
||||
}
|
||||
}
|
@ -1,127 +0,0 @@
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Syroot.IO;
|
||||
using Syroot.Worms.Core;
|
||||
|
||||
namespace Syroot.Worms.Gen2.Worms2
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents scheme weapons stored in an WEP file which contains armory configuration.
|
||||
/// Used by W2. S. https://worms2d.info/Weapons_file.
|
||||
/// </summary>
|
||||
public class SchemeWeapons : ILoadableFile, ISaveableFile
|
||||
{
|
||||
// ---- CONSTANTS ----------------------------------------------------------------------------------------------
|
||||
|
||||
private const int _trashLength = 16;
|
||||
private const string _signature = "WEPFILE"; // Zero-terminated.
|
||||
private const int _weaponCount = 38;
|
||||
|
||||
// ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SchemeWeapons"/> class.
|
||||
/// </summary>
|
||||
public SchemeWeapons()
|
||||
{
|
||||
Weapons = new SchemeWeaponSetting[_weaponCount];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SchemeWeapons"/> class, loading the data from the given
|
||||
/// <see cref="Stream"/>.
|
||||
/// </summary>
|
||||
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
|
||||
public SchemeWeapons(Stream stream)
|
||||
{
|
||||
Load(stream);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SchemeWeapons"/> class, loading the data from the given file.
|
||||
/// </summary>
|
||||
/// <param name="fileName">The name of the file to load the data from.</param>
|
||||
public SchemeWeapons(string fileName)
|
||||
{
|
||||
Load(fileName);
|
||||
}
|
||||
|
||||
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Gets the array of <see cref="SchemeWeaponSetting"/> instances, each mapping to one weapon at the index of
|
||||
/// the <see cref="SchemeWeapon"/> enumeration.
|
||||
/// </summary>
|
||||
public SchemeWeaponSetting[] Weapons { get; set; }
|
||||
|
||||
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Loads the data from the given <see cref="Stream"/>.
|
||||
/// </summary>
|
||||
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
|
||||
public void Load(Stream stream)
|
||||
{
|
||||
using (BinaryDataReader reader = new BinaryDataReader(stream, Encoding.ASCII, true))
|
||||
{
|
||||
// Read the header.
|
||||
reader.Seek(_trashLength);
|
||||
if (reader.ReadString(BinaryStringFormat.ZeroTerminated) != _signature)
|
||||
{
|
||||
throw new InvalidDataException("Invalid WEP file signature.");
|
||||
}
|
||||
|
||||
// Read the weapon settings.
|
||||
Weapons = new SchemeWeaponSetting[_weaponCount];
|
||||
for (int i = 0; i < _weaponCount; i++)
|
||||
{
|
||||
Weapons[i] = reader.ReadStruct<SchemeWeaponSetting>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads the data from the given file.
|
||||
/// </summary>
|
||||
/// <param name="fileName">The name of the file to load the data from.</param>
|
||||
public void Load(string fileName)
|
||||
{
|
||||
using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
Load(stream);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves the data into the given <paramref name="stream"/> with the specified <paramref name="format"/>.
|
||||
/// </summary>
|
||||
/// <param name="stream">The <see cref="Stream"/> to save the data to.</param>
|
||||
public void Save(Stream stream)
|
||||
{
|
||||
using (BinaryDataWriter writer = new BinaryDataWriter(stream, Encoding.ASCII))
|
||||
{
|
||||
// Write the header.
|
||||
writer.Write(new byte[_trashLength]);
|
||||
writer.Write(_signature, BinaryStringFormat.ZeroTerminated);
|
||||
|
||||
// Write the weapon settings.
|
||||
foreach (SchemeWeaponSetting weapon in Weapons)
|
||||
{
|
||||
writer.Write(weapon);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves the data in the given file.
|
||||
/// </summary>
|
||||
/// <param name="fileName">The name of the file to save the data in.</param>
|
||||
public void Save(string fileName)
|
||||
{
|
||||
using (FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None))
|
||||
{
|
||||
Save(stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Syroot.Worms.Gen2.Worms2
|
||||
{
|
||||
class TeamContainer
|
||||
{
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<Description>.NET library to load and modify file formats of Team17 Worms games.</Description>
|
||||
<Copyright>(c) Syroot, licensed under MIT</Copyright>
|
||||
<AssemblyName>Syroot.Worms</AssemblyName>
|
||||
<AssemblyTitle>Worms</AssemblyTitle>
|
||||
<Authors>Syroot</Authors>
|
||||
<VersionPrefix>0.1.0</VersionPrefix>
|
||||
|
||||
<PackageId>Syroot.Worms</PackageId>
|
||||
<PackageTags>worms;team17</PackageTags>
|
||||
<PackageReleaseNotes>Initial alpha release.</PackageReleaseNotes>
|
||||
<PackageIconUrl>https://raw.githubusercontent.com/Syroot/Worms/master/res/Logo.png</PackageIconUrl>
|
||||
<PackageProjectUrl>https://github.com/Syroot/Worms</PackageProjectUrl>
|
||||
<PackageLicenseUrl>https://raw.githubusercontent.com/Syroot/Worms/master/LICENSE</PackageLicenseUrl>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
<RepositoryUrl>https://github.com/Syroot/Worms</RepositoryUrl>
|
||||
|
||||
<TargetFrameworks>net46;netstandard1.6</TargetFrameworks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Syroot.IO.BinaryData" Version="1.2.2" />
|
||||
<PackageReference Include="Syroot.Maths" Version="1.3.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net45'">
|
||||
<Reference Include="System" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
|
||||
<DebugType>portable</DebugType>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
|
||||
<DebugType>none</DebugType>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
39
src/build.xml
Normal file
39
src/build.xml
Normal file
@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
|
||||
<!-- Metadata -->
|
||||
<PropertyGroup>
|
||||
<Authors>Syroot</Authors>
|
||||
<Copyright>(c) Syroot, licensed under MIT</Copyright>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
<RepositoryUrl>https://gitlab.com/Syroot/Worms</RepositoryUrl>
|
||||
<PackageIcon>icon.png</PackageIcon>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
<PackageProjectUrl>https://gitlab.com/Syroot/Worms</PackageProjectUrl>
|
||||
<PackageTags>team17;worms</PackageTags>
|
||||
<RepositoryUrl>https://gitlab.com/Syroot/Worms</RepositoryUrl>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<None Include="$(MSBuildThisFileDirectory)..\res\icon.png" Pack="true" PackagePath="" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Compilation -->
|
||||
<PropertyGroup>
|
||||
<IncludeSymbols>true</IncludeSymbols>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<TargetFrameworks>netstandard2.0;netstandard2.1</TargetFrameworks>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Output -->
|
||||
<PropertyGroup>
|
||||
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
|
||||
<OutputPath>$(MSBuildThisFileDirectory)..\bin\$(MSBuildProjectName)</OutputPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Release'">
|
||||
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using Syroot.BinaryData;
|
||||
|
||||
namespace Syroot.Worms.Armageddon.ProjectX
|
||||
{
|
||||
internal class ActionConverter : IBinaryConverter
|
||||
{
|
||||
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
|
||||
|
||||
/// <inheritdoc/>
|
||||
public object? Read(Stream stream, object instance, BinaryMemberAttribute memberAttribute,
|
||||
ByteConverter byteConverter)
|
||||
{
|
||||
ExplosionAction explosionAction = instance switch
|
||||
{
|
||||
LauncherStyle launcherStyle => launcherStyle.ExplosionAction,
|
||||
ClusterTarget clusterTarget => clusterTarget.ExplosionAction,
|
||||
_ => throw new NotImplementedException()
|
||||
};
|
||||
return explosionAction switch
|
||||
{
|
||||
ExplosionAction.Home => stream.ReadObject<HomeAction>(),
|
||||
ExplosionAction.Bounce => stream.ReadObject<BounceAction>(),
|
||||
ExplosionAction.Roam => stream.ReadObject<RoamAction>(),
|
||||
ExplosionAction.Dig => stream.ReadObject<DigAction>(),
|
||||
_ => null
|
||||
};
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Write(Stream stream, object instance, BinaryMemberAttribute memberAttribute, object value,
|
||||
ByteConverter byteConverter)
|
||||
{
|
||||
stream.WriteObject(value);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
namespace Syroot.Worms.Armageddon.ProjectX
|
||||
{
|
||||
public class BounceAction : IAction
|
||||
{
|
||||
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
|
||||
|
||||
public CollisionFlags Collisions { get; set; }
|
||||
|
||||
public int Bounciness { get; set; }
|
||||
|
||||
public int Acceleration { get; set; }
|
||||
|
||||
public int Sound { get; set; }
|
||||
|
||||
public int Unknown1 { get; set; }
|
||||
|
||||
public int Unknown2 { get; set; }
|
||||
|
||||
public int ExplosionBias { get; set; }
|
||||
|
||||
public int ExplosionPower { get; set; }
|
||||
|
||||
public int ExplosionDamage { get; set; }
|
||||
|
||||
public int DamageRandomness { get; set; }
|
||||
|
||||
public int BounceCount { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
namespace Syroot.Worms.Armageddon.ProjectX
|
||||
{
|
||||
public class DigAction : IAction
|
||||
{
|
||||
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
|
||||
|
||||
public int Unknown1 { get; set; }
|
||||
|
||||
public int Unknown2 { get; set; }
|
||||
|
||||
public int DiggingSound { get; set; }
|
||||
|
||||
public int SpriteJumping { get; set; }
|
||||
|
||||
public int Sprite1 { get; set; }
|
||||
|
||||
public int Sprite2 { get; set; }
|
||||
|
||||
public int Sprite3 { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
using Syroot.BinaryData;
|
||||
|
||||
namespace Syroot.Worms.Armageddon.ProjectX
|
||||
{
|
||||
public class HomeAction : IAction
|
||||
{
|
||||
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
|
||||
|
||||
[BinaryMember(Offset = 4)]
|
||||
public Sprite Sprite { get; set; }
|
||||
|
||||
public HomeStyle HomeStyle { get; set; }
|
||||
|
||||
public int Delay { get; set; }
|
||||
|
||||
public int Duration { get; set; }
|
||||
}
|
||||
|
||||
public enum HomeStyle
|
||||
{
|
||||
None,
|
||||
Straight,
|
||||
Intelligent
|
||||
}
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
namespace Syroot.Worms.Armageddon.ProjectX
|
||||
{
|
||||
public interface IAction { }
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
using Syroot.BinaryData;
|
||||
|
||||
namespace Syroot.Worms.Armageddon.ProjectX
|
||||
{
|
||||
public class RoamAction : IAction
|
||||
{
|
||||
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
|
||||
|
||||
public CollisionFlags RoamCollisions { get; set; }
|
||||
|
||||
public CollisionFlags ExplosionCollisions { get; set; }
|
||||
|
||||
public int WalkSpeed { get; set; }
|
||||
|
||||
public int Unknown { get; set; }
|
||||
|
||||
public int JumpAngleEdge { get; set; }
|
||||
|
||||
public int JumpVelocityEdge { get; set; }
|
||||
|
||||
public int JumpSoundEdge { get; set; }
|
||||
|
||||
public int JumpAngle { get; set; }
|
||||
|
||||
public int JumpVelocity { get; set; }
|
||||
|
||||
public int JumpSound { get; set; }
|
||||
|
||||
public int TerrainOffset { get; set; }
|
||||
|
||||
[BinaryMember(BooleanCoding = BooleanCoding.Dword)]
|
||||
public bool Fart { get; set; }
|
||||
|
||||
public int DiseasePower { get; set; }
|
||||
|
||||
public int SpriteFarting { get; set; }
|
||||
|
||||
public int SpriteFlying { get; set; }
|
||||
|
||||
public int SpriteFlying2 { get; set; }
|
||||
|
||||
public int SpriteTakeOff { get; set; }
|
||||
|
||||
public int SpriteDuringFlight { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
using System;
|
||||
|
||||
namespace Syroot.Worms.Armageddon.ProjectX
|
||||
{
|
||||
[Flags]
|
||||
public enum CollisionFlags : int
|
||||
{
|
||||
None,
|
||||
Unused0 = 1 << 0,
|
||||
Terrain = 1 << 1,
|
||||
WormsOnTerrain = 1 << 2,
|
||||
WormsUsingWeapon = 1 << 3,
|
||||
WormsInAir = 1 << 4,
|
||||
WormsOnRope = 1 << 5,
|
||||
FrozenWorms = 1 << 6,
|
||||
Unused7 = 1 << 7,
|
||||
KamikazeBomber = 1 << 8,
|
||||
GasCanisters = 1 << 9,
|
||||
Mines = 1 << 10,
|
||||
Crates = 1 << 11,
|
||||
DonorCards = 1 << 12,
|
||||
Gravestones = 1 << 13,
|
||||
Unused14 = 1 << 14,
|
||||
OtherWeapons = 1 << 15,
|
||||
LongbowArrows = 1 << 16,
|
||||
OilDrums = 1 << 17,
|
||||
Unused18 = 1 << 18,
|
||||
Unused19 = 1 << 19,
|
||||
Unused20 = 1 << 20,
|
||||
Unused21 = 1 << 21,
|
||||
Skimming = 1 << 22,
|
||||
Unused23 = 1 << 23,
|
||||
Unused24 = 1 << 24,
|
||||
Unused25 = 1 << 25,
|
||||
Unused26 = 1 << 26,
|
||||
Unused27 = 1 << 27,
|
||||
Unused28 = 1 << 28,
|
||||
Unused29 = 1 << 29,
|
||||
Unknown = 1 << 30,
|
||||
Unused31 = 1 << 31
|
||||
}
|
||||
}
|
298
src/library/Syroot.Worms.Armageddon.ProjectX/Library.cs
Normal file
298
src/library/Syroot.Worms.Armageddon.ProjectX/Library.cs
Normal file
@ -0,0 +1,298 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Syroot.BinaryData;
|
||||
using Syroot.Worms.IO;
|
||||
|
||||
namespace Syroot.Worms.Armageddon.ProjectX
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a library stored in a PXL file which contains reusable weapons, files and scripts.
|
||||
/// Used by WA PX. S. https://worms2d.info/Project_X/Library_file.
|
||||
/// </summary>
|
||||
public class Library : IList<LibraryItem>, ILoadableFile, ISaveableFile
|
||||
{
|
||||
// ---- CONSTANTS ----------------------------------------------------------------------------------------------
|
||||
|
||||
private const int _signature = 0x1BCD0102;
|
||||
private const byte _version = 0x00;
|
||||
|
||||
// ---- FIELDS -------------------------------------------------------------------------------------------------
|
||||
|
||||
private readonly List<LibraryItem> _list = new List<LibraryItem>();
|
||||
|
||||
// ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Scheme"/> class.
|
||||
/// </summary>
|
||||
public Library() { }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Scheme"/> class, loading the data from the given
|
||||
/// <see cref="Stream"/>.
|
||||
/// </summary>
|
||||
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
|
||||
public Library(Stream stream) => Load(stream);
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Scheme"/> class, loading the data from the given file.
|
||||
/// </summary>
|
||||
/// <param name="fileName">The name of the file to load the data from.</param>
|
||||
public Library(string fileName) => Load(fileName);
|
||||
|
||||
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
|
||||
|
||||
/// <inheritdoc/>
|
||||
public int Count => _list.Count;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the ProjectX library version.
|
||||
/// </summary>
|
||||
public byte Version { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
bool ICollection<LibraryItem>.IsReadOnly => false;
|
||||
|
||||
// ---- OPERATORS ----------------------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Gets the library entries matching the given key.
|
||||
/// </summary>
|
||||
/// <param name="key">The key of the entries to match.</param>
|
||||
/// <returns>All matching entries.</returns>
|
||||
public IEnumerable<LibraryItem> this[string key] => this.Where(x => x.Key == key);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public LibraryItem this[int index]
|
||||
{
|
||||
get => _list[index];
|
||||
set => _list[index] = value;
|
||||
}
|
||||
|
||||
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Add(LibraryItem item) => _list.Add(item);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Clear() => _list.Clear();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool Contains(LibraryItem item) => _list.Contains(item);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void CopyTo(LibraryItem[] array, int arrayIndex) => _list.CopyTo(array, arrayIndex);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IEnumerator<LibraryItem> GetEnumerator() => _list.GetEnumerator();
|
||||
|
||||
/// <summary>
|
||||
/// Gets all attached files.
|
||||
/// </summary>
|
||||
/// <returns>The enumeration of attached files.</returns>
|
||||
public IEnumerable<byte[]> GetFiles()
|
||||
=> this.Where(x => x.Type == LibraryItemType.File).Select(x => (byte[])x.Value);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all attached scripts.
|
||||
/// </summary>
|
||||
/// <returns>The enumeration of attached scripts.</returns>
|
||||
public IEnumerable<string> GetScripts()
|
||||
=> this.Where(x => x.Type == LibraryItemType.Script).Select(x => (string)x.Value);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all attached weapons.
|
||||
/// </summary>
|
||||
/// <returns>The enumeration of attached weapons.</returns>
|
||||
public IEnumerable<Weapon> GetWeapons()
|
||||
=> this.Where(x => x.Type == LibraryItemType.Weapon).Select(x => (Weapon)x.Value);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public int IndexOf(LibraryItem item) => _list.IndexOf(item);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Insert(int index, LibraryItem item) => _list.Insert(index, item);
|
||||
|
||||
/// <summary>
|
||||
/// Loads the data from the given <see cref="Stream"/>.
|
||||
/// </summary>
|
||||
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
|
||||
public void Load(Stream stream)
|
||||
{
|
||||
using BinaryStream reader = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true);
|
||||
|
||||
// Read the header.
|
||||
if (reader.ReadInt32() != _signature)
|
||||
throw new InvalidDataException("Invalid PXL file signature.");
|
||||
Version = reader.Read1Byte();
|
||||
if (Version != _version)
|
||||
throw new InvalidDataException("Invalid PXL file version.");
|
||||
|
||||
// Read the items.
|
||||
_list.Clear();
|
||||
int itemCount = reader.ReadInt32();
|
||||
for (int i = 0; i < itemCount; i++)
|
||||
{
|
||||
LibraryItemType type = reader.ReadEnum<LibraryItemType>(true);
|
||||
string name = reader.ReadString(StringCoding.Int32CharCount);
|
||||
switch (type)
|
||||
{
|
||||
case LibraryItemType.File:
|
||||
_list.Add(new LibraryItem(name, reader.ReadBytes(reader.ReadInt32())));
|
||||
break;
|
||||
case LibraryItemType.Script:
|
||||
_list.Add(new LibraryItem(name, reader.ReadString(StringCoding.Int32CharCount)));
|
||||
break;
|
||||
case LibraryItemType.Weapon:
|
||||
_list.Add(new LibraryItem(name, reader.Load<Weapon>()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads the data from the given file.
|
||||
/// </summary>
|
||||
/// <param name="fileName">The name of the file to load the data from.</param>
|
||||
public void Load(string fileName)
|
||||
{
|
||||
using FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
Load(stream);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool Remove(LibraryItem item) => _list.Remove(item);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void RemoveAt(int index) => _list.RemoveAt(index);
|
||||
|
||||
/// <summary>
|
||||
/// Saves the data into the given <paramref name="stream"/>.
|
||||
/// </summary>
|
||||
/// <param name="stream">The <see cref="Stream"/> to save the data to.</param>
|
||||
public void Save(Stream stream)
|
||||
{
|
||||
using BinaryStream writer = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true);
|
||||
|
||||
// Write the header.
|
||||
writer.Write(_signature);
|
||||
writer.Write(Version);
|
||||
|
||||
// Write the items.
|
||||
writer.Write(Count);
|
||||
foreach (LibraryItem item in _list)
|
||||
{
|
||||
writer.WriteEnum(item.Type, true);
|
||||
writer.Write(item.Key, StringCoding.Int32CharCount);
|
||||
switch (item.Type)
|
||||
{
|
||||
case LibraryItemType.File:
|
||||
byte[] value = (byte[])item.Value;
|
||||
writer.Write(value.Length);
|
||||
writer.Write(value);
|
||||
break;
|
||||
case LibraryItemType.Script:
|
||||
writer.Write((string)item.Value, StringCoding.Int32CharCount);
|
||||
break;
|
||||
case LibraryItemType.Weapon:
|
||||
writer.Save((Weapon)item.Value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves the data in the given file.
|
||||
/// </summary>
|
||||
/// <param name="fileName">The name of the file to save the data in.</param>
|
||||
public void Save(string fileName)
|
||||
{
|
||||
using FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None);
|
||||
Save(stream);
|
||||
}
|
||||
|
||||
// ---- METHODS ------------------------------------------------------------------------------------------------
|
||||
|
||||
/// <inheritdoc/>
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return ((IEnumerable)_list).GetEnumerator();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents an entry in a Project X library.
|
||||
/// </summary>
|
||||
[DebuggerDisplay("LibraryItem Key={Key} Type={Type}")]
|
||||
public class LibraryItem
|
||||
{
|
||||
// ---- FIELDS -------------------------------------------------------------------------------------------------
|
||||
|
||||
private object _value = null!;
|
||||
|
||||
// ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LibraryItem"/> class with the given <paramref name="key"/> and
|
||||
/// <paramref name="value"/>.
|
||||
/// </summary>
|
||||
/// <param name="key">The key under which the item will be stored.</param>
|
||||
/// <param name="value">The value which will be stored under the key. The type is inferred from this.</param>
|
||||
public LibraryItem(string key, object value)
|
||||
{
|
||||
Key = key;
|
||||
Value = value;
|
||||
}
|
||||
|
||||
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name under which this item is stored.
|
||||
/// </summary>
|
||||
public string Key { get; set; } = String.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the item.
|
||||
/// </summary>
|
||||
public LibraryItemType Type { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the data of the item.
|
||||
/// </summary>
|
||||
public object Value
|
||||
{
|
||||
get => _value;
|
||||
set
|
||||
{
|
||||
// Validate the type.
|
||||
if (value.GetType() == typeof(byte[]))
|
||||
Type = LibraryItemType.File;
|
||||
else if (value.GetType() == typeof(string))
|
||||
Type = LibraryItemType.Script;
|
||||
else if (value.GetType() == typeof(Weapon))
|
||||
Type = LibraryItemType.Weapon;
|
||||
else
|
||||
throw new ArgumentException("Invalid LibraryItemType.", nameof(value));
|
||||
_value = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the possible type of a library entry.
|
||||
/// </summary>
|
||||
public enum LibraryItemType : byte
|
||||
{
|
||||
/// <summary>The entry is a raw file in form of a byte array.</summary>
|
||||
File = 2,
|
||||
/// <summary>The entry is a script in form of a string.</summary>
|
||||
Script = 4,
|
||||
/// <summary>The entry is a weapon in form of a <see cref="Weapon"/> instance.</summary>
|
||||
Weapon = 8
|
||||
}
|
||||
}
|
17
src/library/Syroot.Worms.Armageddon.ProjectX/Mine.cs
Normal file
17
src/library/Syroot.Worms.Armageddon.ProjectX/Mine.cs
Normal file
@ -0,0 +1,17 @@
|
||||
using Syroot.BinaryData;
|
||||
|
||||
namespace Syroot.Worms.Armageddon.ProjectX
|
||||
{
|
||||
public struct Mine
|
||||
{
|
||||
// ---- FIELDS -------------------------------------------------------------------------------------------------
|
||||
|
||||
[BinaryMember(Order = 1)] public int Sensitivity;
|
||||
[BinaryMember(Order = 2)] public int TimeBeforeOn;
|
||||
[BinaryMember(Order = 3)] public CollisionFlags SensitiveTo;
|
||||
[BinaryMember(Order = 4)] public int FuseTime;
|
||||
[BinaryMember(Order = 5)] public int ExplosionBias;
|
||||
[BinaryMember(Order = 6)] public int ExplosionPower;
|
||||
[BinaryMember(Order = 7)] public int MaxDamage;
|
||||
}
|
||||
}
|
199
src/library/Syroot.Worms.Armageddon.ProjectX/Scheme.cs
Normal file
199
src/library/Syroot.Worms.Armageddon.ProjectX/Scheme.cs
Normal file
@ -0,0 +1,199 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Syroot.BinaryData;
|
||||
using Syroot.Worms.IO;
|
||||
|
||||
namespace Syroot.Worms.Armageddon.ProjectX
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a scheme stored in a PXS file which contains game settings, weapon tables, required libraries and
|
||||
/// attached files and scripts.
|
||||
/// Used by WA PX. S. https://worms2d.info/Project_X/Scheme_file.
|
||||
/// </summary>
|
||||
public class Scheme : ILoadableFile, ISaveableFile
|
||||
{
|
||||
// ---- CONSTANTS ----------------------------------------------------------------------------------------------
|
||||
|
||||
private const string _signature = "SCHM OF WAPX";
|
||||
private const int _weaponsPerTable = 71;
|
||||
|
||||
// ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Scheme"/> class.
|
||||
/// </summary>
|
||||
public Scheme() { }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Scheme"/> class, loading the data from the given
|
||||
/// <see cref="Stream"/>.
|
||||
/// </summary>
|
||||
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
|
||||
public Scheme(Stream stream) => Load(stream);
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Scheme"/> class, loading the data from the given file.
|
||||
/// </summary>
|
||||
/// <param name="fileName">The name of the file to load the data from.</param>
|
||||
public Scheme(string fileName) => Load(fileName);
|
||||
|
||||
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
|
||||
|
||||
public int Version { get; set; }
|
||||
|
||||
public SchemeFlags Flags { get; set; }
|
||||
|
||||
public IList<Weapon[]> WeaponTables { get; set; } = new List<Weapon[]>();
|
||||
|
||||
public IDictionary<string, byte[]> Files { get; set; } = new Dictionary<string, byte[]>();
|
||||
|
||||
public IDictionary<string, string> Scripts { get; set; } = new Dictionary<string, string>();
|
||||
|
||||
public IList<string> Libraries { get; set; } = new List<string>();
|
||||
|
||||
public string GameSchemeName { get; set; } = String.Empty;
|
||||
|
||||
public Armageddon.Scheme? GameScheme { get; set; }
|
||||
|
||||
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Load(Stream stream)
|
||||
{
|
||||
using BinaryStream reader = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true);
|
||||
|
||||
// Read the header.
|
||||
if (reader.ReadString(_signature.Length) != _signature)
|
||||
throw new InvalidDataException("Invalid PXS file signature.");
|
||||
Version = reader.ReadInt32();
|
||||
|
||||
// Read the scheme flags.
|
||||
Flags = reader.ReadStruct<SchemeFlags>();
|
||||
|
||||
// Read the weapon tables.
|
||||
int weaponTableCount = reader.ReadInt32();
|
||||
WeaponTables = new List<Weapon[]>(weaponTableCount);
|
||||
for (int i = 0; i < weaponTableCount; i++)
|
||||
{
|
||||
Weapon[] weaponTable = new Weapon[_weaponsPerTable];
|
||||
for (int j = 0; j < _weaponsPerTable; j++)
|
||||
weaponTable[j] = reader.Load<Weapon>();
|
||||
WeaponTables.Add(weaponTable);
|
||||
}
|
||||
|
||||
// Read a placeholder array.
|
||||
reader.Seek(sizeof(int));
|
||||
|
||||
// Read attached files.
|
||||
int filesCount = reader.ReadInt32();
|
||||
Files = new Dictionary<string, byte[]>(filesCount);
|
||||
for (int i = 0; i < filesCount; i++)
|
||||
{
|
||||
string name = reader.ReadString(StringCoding.Int32CharCount);
|
||||
int length = reader.ReadInt32();
|
||||
Files.Add(name, reader.ReadBytes(length));
|
||||
}
|
||||
|
||||
// Read attached scripts.
|
||||
int scriptsCount = reader.ReadInt32();
|
||||
Scripts = new Dictionary<string, string>(scriptsCount);
|
||||
for (int i = 0; i < scriptsCount; i++)
|
||||
Scripts.Add(reader.ReadString(StringCoding.Int32CharCount),
|
||||
reader.ReadString(StringCoding.Int32CharCount));
|
||||
|
||||
// Read required libraries.
|
||||
int librariesCount = reader.ReadInt32();
|
||||
Libraries = new List<string>(reader.ReadStrings(librariesCount, StringCoding.Int32CharCount));
|
||||
|
||||
// Read a possibly attached scheme file.
|
||||
if (reader.ReadBoolean())
|
||||
{
|
||||
byte[] schemeData = reader.ReadBytes(reader.ReadInt32());
|
||||
using MemoryStream schemeStream = new MemoryStream(schemeData);
|
||||
GameScheme = schemeStream.Load<Armageddon.Scheme>();
|
||||
GameSchemeName = reader.ReadString(StringCoding.Int32CharCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
GameScheme = null;
|
||||
GameSchemeName = String.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Load(string fileName)
|
||||
{
|
||||
using FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
Load(stream);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Save(Stream stream)
|
||||
{
|
||||
using BinaryStream writer = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true);
|
||||
|
||||
// Write the header.
|
||||
writer.Write(_signature, StringCoding.Raw);
|
||||
writer.Write(Version);
|
||||
|
||||
// Write the scheme flags.
|
||||
writer.WriteStruct(Flags);
|
||||
|
||||
// Write the weapon tables.
|
||||
writer.Write(WeaponTables.Count);
|
||||
foreach (Weapon[] weaponTable in WeaponTables)
|
||||
for (int i = 0; i < _weaponsPerTable; i++)
|
||||
writer.Save(weaponTable[i]);
|
||||
|
||||
// Write a placeholder array.
|
||||
writer.Write(0);
|
||||
|
||||
// Write attached files.
|
||||
writer.Write(Files.Count);
|
||||
foreach (KeyValuePair<string, byte[]> file in Files)
|
||||
{
|
||||
writer.Write(file.Key, StringCoding.Int32CharCount);
|
||||
writer.Write(file.Value.Length);
|
||||
writer.Write(file.Value);
|
||||
}
|
||||
|
||||
// Write attached scripts.
|
||||
writer.Write(Scripts.Count);
|
||||
foreach (KeyValuePair<string, string> script in Scripts)
|
||||
{
|
||||
writer.Write(script.Key, StringCoding.Int32CharCount);
|
||||
writer.Write(script.Value, StringCoding.Int32CharCount);
|
||||
}
|
||||
|
||||
// Write required libraries.
|
||||
writer.Write(Libraries.Count);
|
||||
writer.Write(Libraries, StringCoding.Int32CharCount);
|
||||
|
||||
// Write a possibly attached scheme file.
|
||||
if (GameScheme != null)
|
||||
{
|
||||
writer.Write(true);
|
||||
using MemoryStream schemeStream = new MemoryStream();
|
||||
GameScheme.Save(schemeStream);
|
||||
|
||||
writer.Write((int)schemeStream.Position);
|
||||
schemeStream.Position = 0;
|
||||
schemeStream.CopyTo(writer);
|
||||
writer.Write(GameSchemeName, StringCoding.Int32CharCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.Write(false);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Save(string fileName)
|
||||
{
|
||||
using FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None);
|
||||
Save(stream);
|
||||
}
|
||||
}
|
||||
}
|
29
src/library/Syroot.Worms.Armageddon.ProjectX/SchemeFlags.cs
Normal file
29
src/library/Syroot.Worms.Armageddon.ProjectX/SchemeFlags.cs
Normal file
@ -0,0 +1,29 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Syroot.Worms.Armageddon.ProjectX
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents global Project X scheme flags affecting general game behavior.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct SchemeFlags
|
||||
{
|
||||
// ---- FIELDS -------------------------------------------------------------------------------------------------
|
||||
|
||||
public bool CyclicMaps;
|
||||
public bool UnderwaterJetpack;
|
||||
public bool UnderwaterRope;
|
||||
public bool Unused1;
|
||||
public bool Unused2;
|
||||
public bool Unused3;
|
||||
public bool Unused4;
|
||||
public bool Unused5;
|
||||
public bool Unused6;
|
||||
public bool Unused7;
|
||||
public bool Unused8;
|
||||
public bool ShotDoesntEndTurn;
|
||||
public bool LoseControlDoesntEndTurn;
|
||||
public bool FiringPausesTimer;
|
||||
public bool EnableSchemePowers;
|
||||
}
|
||||
}
|
15
src/library/Syroot.Worms.Armageddon.ProjectX/Sound.cs
Normal file
15
src/library/Syroot.Worms.Armageddon.ProjectX/Sound.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using Syroot.BinaryData;
|
||||
|
||||
namespace Syroot.Worms.Armageddon.ProjectX
|
||||
{
|
||||
public struct Sound
|
||||
{
|
||||
// ---- FIELDS -------------------------------------------------------------------------------------------------
|
||||
|
||||
[BinaryMember(Order = 1)] public ushort SoundIndex;
|
||||
[BinaryMember(Order = 2, BooleanCoding = BooleanCoding.Word)] public bool RepeatSound;
|
||||
[BinaryMember(Order = 3, BooleanCoding = BooleanCoding.Dword)] public bool UseExplosionSound;
|
||||
[BinaryMember(Order = 4)] public int SoundBeforeExplosion;
|
||||
[BinaryMember(Order = 5)] public int DelayBeforeExplosion;
|
||||
}
|
||||
}
|
27
src/library/Syroot.Worms.Armageddon.ProjectX/Sprite.cs
Normal file
27
src/library/Syroot.Worms.Armageddon.ProjectX/Sprite.cs
Normal file
@ -0,0 +1,27 @@
|
||||
using Syroot.BinaryData;
|
||||
|
||||
namespace Syroot.Worms.Armageddon.ProjectX
|
||||
{
|
||||
public struct Sprite
|
||||
{
|
||||
// ---- FIELDS -------------------------------------------------------------------------------------------------
|
||||
|
||||
[BinaryMember(Order = 1)] public int SpriteNumber;
|
||||
[BinaryMember(Order = 2)] public SpriteAnimationType AnimationType;
|
||||
[BinaryMember(Order = 3)] public int TrailSprite;
|
||||
[BinaryMember(Order = 4)] public int TrailAmount;
|
||||
[BinaryMember(Order = 5)] public int TrailVanishSpeed;
|
||||
[BinaryMember(Order = 6)] public int Unknown;
|
||||
}
|
||||
|
||||
public enum SpriteAnimationType : int
|
||||
{
|
||||
HorizontalVelocity,
|
||||
Cycle,
|
||||
TrackMovement,
|
||||
TrackSpeed,
|
||||
SlowCycle,
|
||||
FasterCycle,
|
||||
FastCycle
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
using Syroot.BinaryData;
|
||||
|
||||
namespace Syroot.Worms.Armageddon.ProjectX
|
||||
{
|
||||
public class AirstrikeStyle : IStyle
|
||||
{
|
||||
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
|
||||
|
||||
[BinaryMember(Order = 1)] public int PlaneSprite;
|
||||
|
||||
[BinaryMember(Order = 2)] public int BombsCount;
|
||||
|
||||
[BinaryMember(Order = 3)] public int DropDistance;
|
||||
|
||||
[BinaryMember(Order = 4)] public int HorizontalSpeed;
|
||||
|
||||
[BinaryMember(Order = 5)] public int Sound;
|
||||
|
||||
[BinaryMember(Order = 6)] public WeaponAirstrikeSubstyle AirstrikeSubstyle;
|
||||
|
||||
[BinaryMember(Order = 7, Converter = typeof(AirstrikeSubstyleConverter))] public IStyle? Style;
|
||||
}
|
||||
|
||||
public enum WeaponAirstrikeSubstyle : int
|
||||
{
|
||||
Mines,
|
||||
Worms,
|
||||
Launcher
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using Syroot.BinaryData;
|
||||
|
||||
namespace Syroot.Worms.Armageddon.ProjectX
|
||||
{
|
||||
public class AirstrikeSubstyleConverter : IBinaryConverter
|
||||
{
|
||||
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
|
||||
|
||||
/// <inheritdoc/>
|
||||
public object? Read(Stream stream, object instance, BinaryMemberAttribute memberAttribute,
|
||||
ByteConverter byteConverter)
|
||||
{
|
||||
WeaponAirstrikeSubstyle airstrikeSubstyle = instance switch
|
||||
{
|
||||
AirstrikeStyle airstrikeStyle => airstrikeStyle.AirstrikeSubstyle,
|
||||
_ => throw new NotImplementedException(),
|
||||
};
|
||||
return airstrikeSubstyle switch
|
||||
{
|
||||
WeaponAirstrikeSubstyle.Mines => stream.ReadObject<MineStyle>(),
|
||||
WeaponAirstrikeSubstyle.Launcher => stream.ReadObject<LauncherStyle>(),
|
||||
_ => null
|
||||
};
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Write(Stream stream, object instance, BinaryMemberAttribute memberAttribute, object value,
|
||||
ByteConverter byteConverter)
|
||||
{
|
||||
stream.WriteObject(value);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
using Syroot.BinaryData;
|
||||
|
||||
namespace Syroot.Worms.Armageddon.ProjectX
|
||||
{
|
||||
public class BaseballBatStyle : IStyle
|
||||
{
|
||||
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
|
||||
|
||||
[BinaryMember(Order = 1)] public int Damage { get; set; }
|
||||
|
||||
[BinaryMember(Order = 2)] public int PushPower { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
using Syroot.BinaryData;
|
||||
|
||||
namespace Syroot.Worms.Armageddon.ProjectX
|
||||
{
|
||||
public class BattleAxeStyle : IStyle
|
||||
{
|
||||
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
|
||||
|
||||
[BinaryMember(Order = 1)] public int PercentualDamage { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
using Syroot.BinaryData;
|
||||
|
||||
namespace Syroot.Worms.Armageddon.ProjectX
|
||||
{
|
||||
public class BlowtorchStyle : IStyle
|
||||
{
|
||||
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
|
||||
|
||||
[BinaryMember(Order = 1)] public int Damage { get; set; }
|
||||
|
||||
[BinaryMember(Order = 2)] public int PushPower { get; set; }
|
||||
|
||||
[BinaryMember(Order = 3)] public int ImpactAngle { get; set; }
|
||||
|
||||
[BinaryMember(Order = 4)] public int TunellingTime { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
using Syroot.BinaryData;
|
||||
|
||||
namespace Syroot.Worms.Armageddon.ProjectX
|
||||
{
|
||||
public class BowStyle : IStyle
|
||||
{
|
||||
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
|
||||
|
||||
[BinaryMember(Order = 1)] public int Damage { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
using Syroot.BinaryData;
|
||||
|
||||
namespace Syroot.Worms.Armageddon.ProjectX
|
||||
{
|
||||
public class CanisterStyle : IStyle
|
||||
{
|
||||
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
|
||||
|
||||
[BinaryMember(Order = 1)] public int SpriteInactive { get; set; }
|
||||
|
||||
[BinaryMember(Order = 2)] public int SpriteActive { get; set; }
|
||||
|
||||
[BinaryMember(Order = 3)] public int DiseasePoints { get; set; }
|
||||
|
||||
[BinaryMember(Order = 4)] public int MaxDamage { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
using Syroot.BinaryData;
|
||||
|
||||
namespace Syroot.Worms.Armageddon.ProjectX
|
||||
{
|
||||
public class DragonballStyle : IStyle
|
||||
{
|
||||
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
|
||||
|
||||
[BinaryMember(Order = 1)] public int FiringSound { get; set; }
|
||||
|
||||
[BinaryMember(Order = 2)] public int ImpactSound { get; set; }
|
||||
|
||||
[BinaryMember(Order = 3)] public int BallSprite { get; set; }
|
||||
|
||||
[BinaryMember(Order = 4)] public int Damage { get; set; }
|
||||
|
||||
[BinaryMember(Order = 5)] public int Angle { get; set; }
|
||||
|
||||
[BinaryMember(Order = 6)] public int Force { get; set; }
|
||||
|
||||
[BinaryMember(Order = 7)] public int BallTime { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
using Syroot.BinaryData;
|
||||
|
||||
namespace Syroot.Worms.Armageddon.ProjectX
|
||||
{
|
||||
public class FirepunchStyle : IStyle
|
||||
{
|
||||
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
|
||||
|
||||
[BinaryMember(Order = 1)] public int Damage { get; set; }
|
||||
|
||||
[BinaryMember(Order = 2)] public int Angle { get; set; }
|
||||
|
||||
[BinaryMember(Order = 3)] public int PushPower { get; set; }
|
||||
|
||||
[BinaryMember(Order = 4)] public int JumpHeight { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
using Syroot.BinaryData;
|
||||
|
||||
namespace Syroot.Worms.Armageddon.ProjectX
|
||||
{
|
||||
public class FlamethrowerStyle : IStyle
|
||||
{
|
||||
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
|
||||
|
||||
[BinaryMember(Order = 1)] public int FuelAmount { get; set; }
|
||||
|
||||
[BinaryMember(Order = 2)] public int FireIntensity { get; set; }
|
||||
|
||||
[BinaryMember(Order = 3)] public int FireAmount { get; set; }
|
||||
|
||||
[BinaryMember(Order = 4)] public int FireBurnTime { get; set; }
|
||||
|
||||
[BinaryMember(Order = 5, BooleanCoding = BooleanCoding.Dword)] public bool RemainOnTerrain { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
using Syroot.BinaryData;
|
||||
|
||||
namespace Syroot.Worms.Armageddon.ProjectX
|
||||
{
|
||||
public class GunStyle : IStyle
|
||||
{
|
||||
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
|
||||
|
||||
[BinaryMember(Order = 1)] public int BulletCount { get; set; }
|
||||
|
||||
[BinaryMember(Order = 2)] public int ReloadTime { get; set; }
|
||||
|
||||
[BinaryMember(Order = 3)] public int BulletSpread { get; set; }
|
||||
|
||||
[BinaryMember(Order = 4)] public int Burst { get; set; }
|
||||
|
||||
[BinaryMember(Order = 5)] public int BurstSpread { get; set; }
|
||||
|
||||
[BinaryMember(Order = 6)] public CollisionFlags Collisions { get; set; }
|
||||
|
||||
[BinaryMember(Order = 7)] public int ExplosionBias { get; set; }
|
||||
|
||||
[BinaryMember(Order = 8)] public int ExplosionPower { get; set; }
|
||||
|
||||
[BinaryMember(Order = 9)] public int MaxDamage { get; set; }
|
||||
|
||||
[BinaryMember(Order = 10)] public int DamageSpread { get; set; }
|
||||
|
||||
[BinaryMember(Order = 11)] public int ExpEffect { get; set; }
|
||||
|
||||
[BinaryMember(Order = 12)] public int Range1 { get; set; }
|
||||
|
||||
[BinaryMember(Order = 13)] public int Range2 { get; set; }
|
||||
|
||||
[BinaryMember(Order = 14)] public int Range3 { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
namespace Syroot.Worms.Armageddon.ProjectX
|
||||
{
|
||||
public interface IStyle { }
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
using Syroot.BinaryData;
|
||||
|
||||
namespace Syroot.Worms.Armageddon.ProjectX
|
||||
{
|
||||
public class JetpackStyle : IStyle
|
||||
{
|
||||
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
|
||||
|
||||
[BinaryMember(Order = 1)] public int Fuel { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
using Syroot.BinaryData;
|
||||
|
||||
namespace Syroot.Worms.Armageddon.ProjectX
|
||||
{
|
||||
public class KamikazeStyle : IStyle
|
||||
{
|
||||
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
|
||||
|
||||
[BinaryMember(Order = 1)] public int FlyingTime { get; set; }
|
||||
|
||||
[BinaryMember(Order = 2)] public int ExplosionDamage { get; set; }
|
||||
|
||||
[BinaryMember(Order = 3)] public int FireSound { get; set; }
|
||||
|
||||
[BinaryMember(Order = 4)] public int Damage { get; set; }
|
||||
|
||||
[BinaryMember(Order = 5)] public int ImpactForce { get; set; }
|
||||
|
||||
[BinaryMember(Order = 6)] public int ImpactAngle { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
using Syroot.BinaryData;
|
||||
|
||||
namespace Syroot.Worms.Armageddon.ProjectX
|
||||
{
|
||||
public class LauncherStyle : IStyle
|
||||
{
|
||||
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
|
||||
|
||||
[BinaryMember(Order = 1)] public int SpriteSize { get; set; }
|
||||
|
||||
[BinaryMember(Order = 2)] public int FixedSpeed { get; set; }
|
||||
|
||||
[BinaryMember(Order = 3, BooleanCoding = BooleanCoding.Dword)] public bool RunAway { get; set; }
|
||||
|
||||
[BinaryMember(Order = 4)] public CollisionFlags Collisions { get; set; }
|
||||
|
||||
[BinaryMember(Order = 5)] public int ExplosionBias { get; set; }
|
||||
|
||||
[BinaryMember(Order = 6)] public int ExplosionPushPower { get; set; }
|
||||
|
||||
[BinaryMember(Order = 7)] public int ExplosionDamage { get; set; }
|
||||
|
||||
[BinaryMember(Order = 8)] public int ExplosionDamageVariation { get; set; }
|
||||
|
||||
[BinaryMember(Order = 9)] public int ExplosionUnknown { get; set; }
|
||||
|
||||
[BinaryMember(Order = 10)] public Sprite Sprite { get; set; }
|
||||
|
||||
[BinaryMember(Order = 11)] public int VariableSpeed { get; set; }
|
||||
|
||||
[BinaryMember(Order = 12)] public int WindFactor { get; set; }
|
||||
|
||||
[BinaryMember(Order = 13)] public int MotionRandomness { get; set; }
|
||||
|
||||
[BinaryMember(Order = 14)] public int GravityFactor { get; set; }
|
||||
|
||||
[BinaryMember(Order = 15)] public int ExplosionCountdown { get; set; }
|
||||
|
||||
[BinaryMember(Order = 16)] public int ExplosionTimer { get; set; }
|
||||
|
||||
[BinaryMember(Order = 17)] public Sound Sound { get; set; }
|
||||
|
||||
[BinaryMember(Order = 18, BooleanCoding = BooleanCoding.Dword)] public bool ExplodeOnSpace { get; set; }
|
||||
|
||||
[BinaryMember(Order = 19)] public ExplosionAction ExplosionAction { get; set; }
|
||||
|
||||
[BinaryMember(Order = 20, Converter = typeof(ActionConverter))] public IAction? Action { get; set; }
|
||||
|
||||
[BinaryMember(Order = 21, OffsetOrigin = OffsetOrigin.Begin, Offset = 180)]
|
||||
public ExplosionTarget ExplosionTarget { get; set; }
|
||||
|
||||
[BinaryMember(Order = 22, Offset = sizeof(int), Converter = typeof(TargetConverter))]
|
||||
public ITarget? Target { get; set; }
|
||||
}
|
||||
|
||||
public enum ExplosionAction : int
|
||||
{
|
||||
None,
|
||||
Home,
|
||||
Bounce,
|
||||
Roam,
|
||||
Dig
|
||||
}
|
||||
|
||||
public enum ExplosionTarget : int
|
||||
{
|
||||
None,
|
||||
Clusters,
|
||||
Fire
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
using Syroot.BinaryData;
|
||||
|
||||
namespace Syroot.Worms.Armageddon.ProjectX
|
||||
{
|
||||
public class MineStyle : IStyle
|
||||
{
|
||||
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
|
||||
|
||||
[BinaryMember(Order = 1)] public Mine Mine;
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
using Syroot.BinaryData;
|
||||
|
||||
namespace Syroot.Worms.Armageddon.ProjectX
|
||||
{
|
||||
public class NinjaRopeStyle : IStyle
|
||||
{
|
||||
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
|
||||
|
||||
[BinaryMember(Order = 1)] public int ShotCount { get; set; }
|
||||
|
||||
[BinaryMember(Order = 2)] public int Length { get; set; }
|
||||
|
||||
[BinaryMember(Order = 3)] public int AngleRestriction { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
using Syroot.BinaryData;
|
||||
|
||||
namespace Syroot.Worms.Armageddon.ProjectX
|
||||
{
|
||||
public class NuclearTestStyle : IStyle
|
||||
{
|
||||
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
|
||||
|
||||
[BinaryMember(Order = 1)] public int WaterRise { get; set; }
|
||||
|
||||
[BinaryMember(Order = 2)] public int DiseasePoints { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
using Syroot.BinaryData;
|
||||
|
||||
namespace Syroot.Worms.Armageddon.ProjectX
|
||||
{
|
||||
public class ParachuteStyle : IStyle
|
||||
{
|
||||
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
|
||||
|
||||
[BinaryMember(Order = 1)] public int WindResponse { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
using Syroot.BinaryData;
|
||||
|
||||
namespace Syroot.Worms.Armageddon.ProjectX
|
||||
{
|
||||
public class PneumaticDrillStyle : IStyle
|
||||
{
|
||||
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
|
||||
|
||||
[BinaryMember(Order = 1)] public int Damage { get; set; }
|
||||
|
||||
[BinaryMember(Order = 2)] public int PushPower { get; set; }
|
||||
|
||||
[BinaryMember(Order = 3)] public int ImpactAngle { get; set; }
|
||||
|
||||
[BinaryMember(Order = 4)] public int TunellingTime { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
using Syroot.BinaryData;
|
||||
|
||||
namespace Syroot.Worms.Armageddon.ProjectX
|
||||
{
|
||||
public class ProdStyle : IStyle
|
||||
{
|
||||
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
|
||||
|
||||
[BinaryMember(Order = 1)] public int Damage { get; set; }
|
||||
|
||||
[BinaryMember(Order = 2)] public int Force { get; set; }
|
||||
|
||||
[BinaryMember(Order = 3)] public int Angle { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
using Syroot.BinaryData;
|
||||
|
||||
namespace Syroot.Worms.Armageddon.ProjectX
|
||||
{
|
||||
public class SuicideBomberStyle : IStyle
|
||||
{
|
||||
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
|
||||
|
||||
[BinaryMember(Order = 1)] public int DiseasePoints { get; set; }
|
||||
|
||||
[BinaryMember(Order = 2)] public int Damage { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="$(MSBuildThisFileDirectory)..\..\build.xml" />
|
||||
|
||||
<!-- Metadata -->
|
||||
<PropertyGroup>
|
||||
<AssemblyName>Syroot.Worms.Armageddon.ProjectX</AssemblyName>
|
||||
<Description>.NET library for loading and modifying files of Worms Armageddon ProjectX.</Description>
|
||||
<PackageReleaseNotes>Fix StackOverflowException when using legacy .NET versions.</PackageReleaseNotes>
|
||||
<PackageTags>$(PackageTags);project x;worms armageddon</PackageTags>
|
||||
<Version>4.0.3</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- References -->
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Syroot.BinaryData.Serialization" Version="5.2.1" />
|
||||
<ProjectReference Include="..\Syroot.Worms\Syroot.Worms.csproj" />
|
||||
<ProjectReference Include="..\Syroot.Worms.Armageddon\Syroot.Worms.Armageddon.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
@ -0,0 +1,53 @@
|
||||
using Syroot.BinaryData;
|
||||
|
||||
namespace Syroot.Worms.Armageddon.ProjectX
|
||||
{
|
||||
public class ClusterTarget : ITarget
|
||||
{
|
||||
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
|
||||
|
||||
[BinaryMember(Order = 1)] public int ClusterCount { get; set; }
|
||||
|
||||
[BinaryMember(Order = 2)] public int DispersionPower { get; set; }
|
||||
|
||||
[BinaryMember(Order = 3)] public int Speed { get; set; }
|
||||
|
||||
[BinaryMember(Order = 4)] public int EjectionAngle { get; set; }
|
||||
|
||||
[BinaryMember(Order = 5)] public int DispersionAngle { get; set; }
|
||||
|
||||
[BinaryMember(Order = 6)] public CollisionFlags Collisions { get; set; }
|
||||
|
||||
[BinaryMember(Order = 7)] public int ExplosionBias { get; set; }
|
||||
|
||||
[BinaryMember(Order = 8)] public int ExplosionPushPower { get; set; }
|
||||
|
||||
[BinaryMember(Order = 9)] public int ExplosionDamage { get; set; }
|
||||
|
||||
[BinaryMember(Order = 10)] public int ExplosionDamageVariation { get; set; }
|
||||
|
||||
[BinaryMember(Order = 11)] public int SpriteCount { get; set; }
|
||||
|
||||
[BinaryMember(Order = 12)] public Sprite Sprite { get; set; }
|
||||
|
||||
[BinaryMember(Order = 13)] public int Acceleration { get; set; }
|
||||
|
||||
[BinaryMember(Order = 14)] public int WindResponse { get; set; }
|
||||
|
||||
[BinaryMember(Order = 15)] public int MotionRandomness { get; set; }
|
||||
|
||||
[BinaryMember(Order = 16)] public int GravityFactor { get; set; }
|
||||
|
||||
[BinaryMember(Order = 17)] public int Unused1 { get; set; }
|
||||
|
||||
[BinaryMember(Order = 18)] public int Unused2 { get; set; }
|
||||
|
||||
[BinaryMember(Order = 19)] public Sound Sound { get; set; }
|
||||
|
||||
[BinaryMember(Order = 20, BooleanCoding = BooleanCoding.Dword)] public bool ExplodeOnSpace { get; set; }
|
||||
|
||||
[BinaryMember(Order = 21)] public ExplosionAction ExplosionAction { get; set; }
|
||||
|
||||
[BinaryMember(Order = 22, Converter = typeof(ActionConverter))] public IAction? Action { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
using Syroot.BinaryData;
|
||||
|
||||
namespace Syroot.Worms.Armageddon.ProjectX
|
||||
{
|
||||
public class FireTarget : ITarget
|
||||
{
|
||||
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
|
||||
|
||||
[BinaryMember(Order = 1)] public int Power { get; set; }
|
||||
|
||||
[BinaryMember(Order = 2)] public int Spread { get; set; }
|
||||
|
||||
[BinaryMember(Order = 3)] public int Time { get; set; }
|
||||
|
||||
[BinaryMember(Order = 4, BooleanCoding = BooleanCoding.Dword)] public bool StayBetweenTurns { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
namespace Syroot.Worms.Armageddon.ProjectX
|
||||
{
|
||||
public interface ITarget { }
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using Syroot.BinaryData;
|
||||
|
||||
namespace Syroot.Worms.Armageddon.ProjectX
|
||||
{
|
||||
internal class TargetConverter : IBinaryConverter
|
||||
{
|
||||
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
|
||||
|
||||
/// <inheritdoc/>
|
||||
public object? Read(Stream stream, object instance, BinaryMemberAttribute memberAttribute,
|
||||
ByteConverter byteConverter)
|
||||
{
|
||||
ExplosionTarget explosionTarget = instance switch
|
||||
{
|
||||
LauncherStyle launcherStyle => launcherStyle.ExplosionTarget,
|
||||
_ => throw new NotImplementedException(),
|
||||
};
|
||||
return explosionTarget switch
|
||||
{
|
||||
ExplosionTarget.Clusters => stream.ReadObject<ClusterTarget>(),
|
||||
ExplosionTarget.Fire => stream.ReadObject<FireTarget>(),
|
||||
_ => null,
|
||||
};
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Write(Stream stream, object instance, BinaryMemberAttribute memberAttribute, object value,
|
||||
ByteConverter byteConverter)
|
||||
{
|
||||
stream.WriteObject(value);
|
||||
}
|
||||
}
|
||||
}
|
398
src/library/Syroot.Worms.Armageddon.ProjectX/Weapon.cs
Normal file
398
src/library/Syroot.Worms.Armageddon.ProjectX/Weapon.cs
Normal file
@ -0,0 +1,398 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Syroot.BinaryData;
|
||||
using Syroot.Worms.IO;
|
||||
|
||||
namespace Syroot.Worms.Armageddon.ProjectX
|
||||
{
|
||||
[DebuggerDisplay("Weapon Name={Name}")]
|
||||
public class Weapon : ILoadable, ISaveable
|
||||
{
|
||||
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
|
||||
|
||||
[BinaryMember(Order = 1)] public WeaponVersion Version { get; set; }
|
||||
|
||||
[BinaryMember(Order = 2)] public long Checksum { get; set; }
|
||||
|
||||
[BinaryMember(Order = 3)] public int TableRow { get; set; }
|
||||
|
||||
[BinaryMember(Order = 4)] public bool Remembered { get; set; }
|
||||
|
||||
[BinaryMember(Order = 5)] public bool UsableInCavern { get; set; }
|
||||
|
||||
[BinaryMember(Order = 6)] public int Shots { get; set; }
|
||||
|
||||
[BinaryMember(Order = 7)] public bool ShotEndsTurn { get; set; }
|
||||
|
||||
[BinaryMember(Order = 8)] public int RetreatTime { get; set; }
|
||||
|
||||
[BinaryMember(Order = 9)] public int Unknown1 { get; set; }
|
||||
|
||||
[BinaryMember(Order = 10)] public int CrateChance { get; set; }
|
||||
|
||||
[BinaryMember(Order = 11)] public int CrateCount { get; set; }
|
||||
|
||||
[BinaryMember(Order = 12)] public int Unknown2 { get; set; }
|
||||
|
||||
[BinaryMember(Order = 13)] public WeaponActivation Activation { get; set; }
|
||||
|
||||
[BinaryMember(Order = 14)] public int NotUsed { get; set; }
|
||||
|
||||
[BinaryMember(Order = 15)] public int ThrowHerdCount { get; set; }
|
||||
|
||||
[BinaryMember(Order = 16)] public int AirstrikeSubtype { get; set; }
|
||||
|
||||
[BinaryMember(Order = 17)] public WeaponSpacebarAction SpacebarAction { get; set; }
|
||||
|
||||
[BinaryMember(Order = 18)] public WeaponCrosshairAction CrosshairAction { get; set; }
|
||||
|
||||
[BinaryMember(Order = 19)] public WeaponThrowAction ThrowAction { get; set; }
|
||||
|
||||
[BinaryMember(Order = 20)] public IStyle? Style { get; set; }
|
||||
|
||||
[BinaryMember(Order = 21)] public bool AmmunitionOverride { get; set; }
|
||||
|
||||
[BinaryMember(Order = 22)] public int Ammunition { get; set; }
|
||||
|
||||
[BinaryMember(Order = 23)] public int Unknown3 { get; set; }
|
||||
|
||||
[BinaryMember(Order = 24)] public int WeaponSprite { get; set; }
|
||||
|
||||
[BinaryMember(Order = 25)] public string NameLong { get; set; } = String.Empty;
|
||||
|
||||
[BinaryMember(Order = 26)] public string Name { get; set; } = String.Empty;
|
||||
|
||||
[BinaryMember(Order = 27)] public string GridImageFile { get; set; } = String.Empty;
|
||||
|
||||
[BinaryMember(Order = 28)] public string GfxDirectoryFile { get; set; } = String.Empty;
|
||||
|
||||
[BinaryMember(Order = 29)] public string[] SpriteNames { get; } = new string[5];
|
||||
|
||||
[BinaryMember(Order = 30)] public bool DelayOverride { get; set; }
|
||||
|
||||
[BinaryMember(Order = 31)] public int Delay { get; set; }
|
||||
|
||||
[BinaryMember(Order = 32)] public bool UseLibrary { get; set; }
|
||||
|
||||
[BinaryMember(Order = 33)] public string LibraryName { get; set; } = String.Empty;
|
||||
|
||||
[BinaryMember(Order = 34)] public string LibraryWeaponName { get; set; } = String.Empty;
|
||||
|
||||
[BinaryMember(Order = 35)] public string AimSpriteEven { get; set; } = String.Empty;
|
||||
|
||||
[BinaryMember(Order = 36)] public string AimSpriteUphill { get; set; } = String.Empty;
|
||||
|
||||
[BinaryMember(Order = 37)] public string AimSpriteDownhill { get; set; } = String.Empty;
|
||||
|
||||
[BinaryMember(Order = 38)] public string PickSpriteEven { get; set; } = String.Empty;
|
||||
|
||||
[BinaryMember(Order = 39)] public string PickSpriteUphill { get; set; } = String.Empty;
|
||||
|
||||
[BinaryMember(Order = 40)] public string PickSpriteDownhill { get; set; } = String.Empty;
|
||||
|
||||
[BinaryMember(Order = 41)] public string FireSpriteEven { get; set; } = String.Empty;
|
||||
|
||||
[BinaryMember(Order = 42)] public string FireSpriteUphill { get; set; } = String.Empty;
|
||||
|
||||
[BinaryMember(Order = 43)] public string FireSpriteDownhill { get; set; } = String.Empty;
|
||||
|
||||
[BinaryMember(Order = 44)] public bool AimSpriteOverride { get; set; }
|
||||
|
||||
[BinaryMember(Order = 45)] public bool PickSpriteOverride { get; set; }
|
||||
|
||||
[BinaryMember(Order = 46)] public bool FireSpriteOverride { get; set; }
|
||||
|
||||
[BinaryMember(Order = 47)] public bool Utility { get; set; }
|
||||
|
||||
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Load(Stream stream)
|
||||
{
|
||||
using BinaryStream reader = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true);
|
||||
|
||||
// Read the header.
|
||||
long offset = reader.Position;
|
||||
Version = reader.ReadEnum<WeaponVersion>(true);
|
||||
Checksum = reader.ReadInt64();
|
||||
|
||||
// Read general settings.
|
||||
TableRow = reader.ReadInt32();
|
||||
Remembered = reader.ReadBoolean(BooleanCoding.Dword);
|
||||
UsableInCavern = reader.ReadBoolean(BooleanCoding.Dword);
|
||||
Shots = reader.ReadInt32();
|
||||
ShotEndsTurn = reader.ReadBoolean(BooleanCoding.Dword);
|
||||
RetreatTime = reader.ReadInt32();
|
||||
Unknown1 = reader.ReadInt32();
|
||||
CrateChance = reader.ReadInt32();
|
||||
CrateCount = reader.ReadInt32();
|
||||
Unknown2 = reader.ReadInt32();
|
||||
|
||||
// Read the activation and the corresponding weapon settings.
|
||||
Activation = reader.ReadEnum<WeaponActivation>(false);
|
||||
switch (Activation)
|
||||
{
|
||||
case WeaponActivation.Airstrike:
|
||||
AirstrikeSubtype = reader.ReadInt32();
|
||||
Style = reader.ReadObject<AirstrikeStyle>();
|
||||
break;
|
||||
case WeaponActivation.Crosshair:
|
||||
NotUsed = reader.ReadInt32();
|
||||
CrosshairAction = reader.ReadEnum<WeaponCrosshairAction>(false);
|
||||
Style = CrosshairAction switch
|
||||
{
|
||||
WeaponCrosshairAction.Bow => reader.ReadObject<BowStyle>(),
|
||||
WeaponCrosshairAction.Flamethrower => reader.ReadObject<FlamethrowerStyle>(),
|
||||
WeaponCrosshairAction.Gun => reader.ReadObject<GunStyle>(),
|
||||
WeaponCrosshairAction.Launcher => reader.ReadObject<LauncherStyle>(),
|
||||
_ => null
|
||||
};
|
||||
break;
|
||||
case WeaponActivation.Spacebar:
|
||||
SpacebarAction = reader.ReadEnum<WeaponSpacebarAction>(false);
|
||||
Style = SpacebarAction switch
|
||||
{
|
||||
WeaponSpacebarAction.Armageddon => reader.ReadObject<LauncherStyle>(),
|
||||
WeaponSpacebarAction.BaseballBat => reader.ReadObject<BaseballBatStyle>(),
|
||||
WeaponSpacebarAction.BattleAxe => reader.ReadObject<BattleAxeStyle>(),
|
||||
WeaponSpacebarAction.Blowtorch => reader.ReadObject<BlowtorchStyle>(),
|
||||
WeaponSpacebarAction.Dragonball => reader.ReadObject<DragonballStyle>(),
|
||||
WeaponSpacebarAction.Firepunch => reader.ReadObject<FirepunchStyle>(),
|
||||
WeaponSpacebarAction.Jetpack => reader.ReadObject<JetpackStyle>(),
|
||||
WeaponSpacebarAction.Kamikaze => reader.ReadObject<KamikazeStyle>(),
|
||||
WeaponSpacebarAction.NinjaRope => reader.ReadObject<NinjaRopeStyle>(),
|
||||
WeaponSpacebarAction.NuclearTest => reader.ReadObject<NuclearTestStyle>(),
|
||||
WeaponSpacebarAction.Parachute => reader.ReadObject<ParachuteStyle>(),
|
||||
WeaponSpacebarAction.PneumaticDrill => reader.ReadObject<PneumaticDrillStyle>(),
|
||||
WeaponSpacebarAction.Prod => reader.ReadObject<ProdStyle>(),
|
||||
WeaponSpacebarAction.SuicideBomber => reader.ReadObject<SuicideBomberStyle>(),
|
||||
_ => null
|
||||
};
|
||||
break;
|
||||
case WeaponActivation.Throw:
|
||||
ThrowHerdCount = reader.ReadInt32();
|
||||
ThrowAction = reader.ReadEnum<WeaponThrowAction>(false);
|
||||
Style = ThrowAction switch
|
||||
{
|
||||
WeaponThrowAction.Canister => reader.ReadObject<CanisterStyle>(),
|
||||
WeaponThrowAction.Launcher => reader.ReadObject<LauncherStyle>(),
|
||||
WeaponThrowAction.Mine => reader.ReadObject<MineStyle>(),
|
||||
_ => null
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
||||
// Read additional settings.
|
||||
reader.Position = offset + 468;
|
||||
AmmunitionOverride = reader.ReadBoolean(BooleanCoding.Dword);
|
||||
Ammunition = reader.ReadInt32();
|
||||
Unknown3 = reader.ReadInt32();
|
||||
WeaponSprite = reader.ReadInt32();
|
||||
NameLong = reader.ReadString(StringCoding.Int32CharCount);
|
||||
Name = reader.ReadString(StringCoding.Int32CharCount);
|
||||
GridImageFile = reader.ReadString(StringCoding.Int32CharCount);
|
||||
GfxDirectoryFile = reader.ReadString(StringCoding.Int32CharCount);
|
||||
for (int i = 0; i < SpriteNames.Length; i++)
|
||||
SpriteNames[i] = reader.ReadString(StringCoding.Int32CharCount);
|
||||
DelayOverride = reader.ReadBoolean(BooleanCoding.Dword);
|
||||
Delay = reader.ReadInt32();
|
||||
|
||||
UseLibrary = reader.ReadBoolean();
|
||||
if (UseLibrary)
|
||||
{
|
||||
LibraryName = reader.ReadString(StringCoding.Int32CharCount);
|
||||
LibraryWeaponName = reader.ReadString(StringCoding.Int32CharCount);
|
||||
}
|
||||
|
||||
AimSpriteEven = reader.ReadString(StringCoding.Int32CharCount);
|
||||
AimSpriteUphill = reader.ReadString(StringCoding.Int32CharCount);
|
||||
AimSpriteDownhill = reader.ReadString(StringCoding.Int32CharCount);
|
||||
PickSpriteEven = reader.ReadString(StringCoding.Int32CharCount);
|
||||
PickSpriteUphill = reader.ReadString(StringCoding.Int32CharCount);
|
||||
PickSpriteDownhill = reader.ReadString(StringCoding.Int32CharCount);
|
||||
FireSpriteEven = reader.ReadString(StringCoding.Int32CharCount);
|
||||
FireSpriteUphill = reader.ReadString(StringCoding.Int32CharCount);
|
||||
FireSpriteDownhill = reader.ReadString(StringCoding.Int32CharCount);
|
||||
AimSpriteOverride = reader.ReadBoolean();
|
||||
PickSpriteOverride = reader.ReadBoolean();
|
||||
FireSpriteOverride = reader.ReadBoolean();
|
||||
if (Version == WeaponVersion.Version_0_8_0)
|
||||
Utility = reader.ReadBoolean();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Save(Stream stream)
|
||||
{
|
||||
using BinaryStream writer = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true);
|
||||
|
||||
// Write the header.
|
||||
long offset = writer.Position;
|
||||
writer.WriteEnum(Version, true);
|
||||
writer.Write(Checksum);
|
||||
|
||||
// Write the general settings.
|
||||
writer.Write(TableRow);
|
||||
writer.Write(Remembered, BooleanCoding.Dword);
|
||||
writer.Write(UsableInCavern, BooleanCoding.Dword);
|
||||
writer.Write(Shots);
|
||||
writer.Write(ShotEndsTurn, BooleanCoding.Dword);
|
||||
writer.Write(RetreatTime);
|
||||
writer.Write(Unknown1);
|
||||
writer.Write(CrateChance);
|
||||
writer.Write(CrateCount);
|
||||
writer.Write(Unknown2);
|
||||
|
||||
// Write the activation and the corresponding weapon settings.
|
||||
writer.WriteEnum(Activation, true);
|
||||
switch (Activation)
|
||||
{
|
||||
case WeaponActivation.Airstrike:
|
||||
writer.Write(AirstrikeSubtype);
|
||||
writer.WriteObject(Style);
|
||||
break;
|
||||
case WeaponActivation.Crosshair:
|
||||
writer.Write(NotUsed);
|
||||
writer.WriteEnum(CrosshairAction, true);
|
||||
if (CrosshairAction != WeaponCrosshairAction.None)
|
||||
writer.WriteObject(Style);
|
||||
break;
|
||||
case WeaponActivation.Spacebar:
|
||||
writer.WriteEnum(SpacebarAction, true);
|
||||
switch (SpacebarAction)
|
||||
{
|
||||
case WeaponSpacebarAction.Armageddon:
|
||||
case WeaponSpacebarAction.BaseballBat:
|
||||
case WeaponSpacebarAction.BattleAxe:
|
||||
case WeaponSpacebarAction.Blowtorch:
|
||||
case WeaponSpacebarAction.Dragonball:
|
||||
case WeaponSpacebarAction.Firepunch:
|
||||
case WeaponSpacebarAction.Jetpack:
|
||||
case WeaponSpacebarAction.Kamikaze:
|
||||
case WeaponSpacebarAction.NinjaRope:
|
||||
case WeaponSpacebarAction.NuclearTest:
|
||||
case WeaponSpacebarAction.Parachute:
|
||||
case WeaponSpacebarAction.PneumaticDrill:
|
||||
case WeaponSpacebarAction.Prod:
|
||||
case WeaponSpacebarAction.SuicideBomber:
|
||||
writer.WriteObject(Style);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case WeaponActivation.Throw:
|
||||
writer.Write(ThrowHerdCount);
|
||||
writer.WriteEnum(ThrowAction, true);
|
||||
if (ThrowAction != WeaponThrowAction.None)
|
||||
writer.WriteObject(Style);
|
||||
break;
|
||||
}
|
||||
|
||||
// Write additional settings.
|
||||
writer.Position = offset + 468;
|
||||
writer.Write(AmmunitionOverride, BooleanCoding.Dword);
|
||||
writer.Write(Ammunition);
|
||||
writer.Write(Unknown3);
|
||||
writer.Write(WeaponSprite);
|
||||
writer.Write(NameLong, StringCoding.Int32CharCount);
|
||||
writer.Write(Name, StringCoding.Int32CharCount);
|
||||
writer.Write(GridImageFile, StringCoding.Int32CharCount);
|
||||
writer.Write(GfxDirectoryFile, StringCoding.Int32CharCount);
|
||||
writer.Write(SpriteNames, StringCoding.Int32CharCount);
|
||||
writer.Write(DelayOverride, BooleanCoding.Dword);
|
||||
writer.Write(Delay);
|
||||
|
||||
writer.Write(UseLibrary);
|
||||
if (UseLibrary)
|
||||
{
|
||||
writer.Write(LibraryName, StringCoding.Int32CharCount);
|
||||
writer.Write(LibraryWeaponName, StringCoding.Int32CharCount);
|
||||
}
|
||||
|
||||
writer.Write(AimSpriteEven, StringCoding.Int32CharCount);
|
||||
writer.Write(AimSpriteUphill, StringCoding.Int32CharCount);
|
||||
writer.Write(AimSpriteDownhill, StringCoding.Int32CharCount);
|
||||
writer.Write(PickSpriteEven, StringCoding.Int32CharCount);
|
||||
writer.Write(PickSpriteUphill, StringCoding.Int32CharCount);
|
||||
writer.Write(PickSpriteDownhill, StringCoding.Int32CharCount);
|
||||
writer.Write(FireSpriteEven, StringCoding.Int32CharCount);
|
||||
writer.Write(FireSpriteUphill, StringCoding.Int32CharCount);
|
||||
writer.Write(FireSpriteDownhill, StringCoding.Int32CharCount);
|
||||
writer.Write(AimSpriteOverride);
|
||||
writer.Write(PickSpriteOverride);
|
||||
writer.Write(FireSpriteOverride);
|
||||
if (Version == WeaponVersion.Version_0_8_0)
|
||||
writer.Write(Utility);
|
||||
}
|
||||
}
|
||||
|
||||
public enum WeaponVersion : int
|
||||
{
|
||||
Version_0_8_0_pre = 0x5ABBDD05,
|
||||
Version_0_8_0 = 0x5ABBDD06
|
||||
}
|
||||
|
||||
public enum WeaponActivation : int
|
||||
{
|
||||
None,
|
||||
Crosshair,
|
||||
Throw,
|
||||
Airstrike,
|
||||
Spacebar
|
||||
}
|
||||
|
||||
public enum WeaponSpacebarAction : int
|
||||
{
|
||||
None,
|
||||
Firepunch,
|
||||
BaseballBat,
|
||||
Dragonball,
|
||||
Kamikaze,
|
||||
SuicideBomber,
|
||||
NinjaRope,
|
||||
Bungee,
|
||||
PneumaticDrill,
|
||||
Prod,
|
||||
Teleport,
|
||||
Blowtorch,
|
||||
Parachute,
|
||||
Surrender,
|
||||
SkipGo,
|
||||
SelectWorm,
|
||||
NuclearTest,
|
||||
Girder,
|
||||
BattleAxe,
|
||||
Utility,
|
||||
Freeze,
|
||||
Earthquake,
|
||||
ScalesOfJustice,
|
||||
Jetpack,
|
||||
Armageddon
|
||||
}
|
||||
|
||||
public enum WeaponCrosshairAction : int
|
||||
{
|
||||
None,
|
||||
Flamethrower,
|
||||
Gun,
|
||||
Launcher,
|
||||
Bow
|
||||
}
|
||||
|
||||
public enum WeaponThrowAction : int
|
||||
{
|
||||
None,
|
||||
Mine,
|
||||
Launcher,
|
||||
Canister
|
||||
}
|
||||
|
||||
public enum WeaponSpriteNameIndex
|
||||
{
|
||||
Unknown0,
|
||||
Launcher,
|
||||
Cluster,
|
||||
Home,
|
||||
Unknown4
|
||||
}
|
||||
}
|
175
src/library/Syroot.Worms.Armageddon/GeneratedMap.cs
Normal file
175
src/library/Syroot.Worms.Armageddon/GeneratedMap.cs
Normal file
@ -0,0 +1,175 @@
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using Syroot.BinaryData;
|
||||
using Syroot.Worms.IO;
|
||||
|
||||
namespace Syroot.Worms.Armageddon
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents <see cref="MapGenSettings"/> stored in a LEV file.
|
||||
/// Used by WA and WWP. S. https://worms2d.info/Monochrome_map_(.bit,_.lev).
|
||||
/// </summary>
|
||||
public class GeneratedMap : ILoadableFile, ISaveableFile
|
||||
{
|
||||
// ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GeneratedMap"/> class.
|
||||
/// </summary>
|
||||
public GeneratedMap() { }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GeneratedMap"/> class, loading the data from the given
|
||||
/// <see cref="Stream"/>.
|
||||
/// </summary>
|
||||
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
|
||||
public GeneratedMap(Stream stream) => Load(stream);
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GeneratedMap"/> class, loading the data from the given file.
|
||||
/// </summary>
|
||||
/// <param name="fileName">The name of the file to load the data from.</param>
|
||||
public GeneratedMap(string fileName) => Load(fileName);
|
||||
|
||||
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="MapGenSettings"/>.
|
||||
/// </summary>
|
||||
public MapGenSettings Settings { get; set; }
|
||||
|
||||
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Load(Stream stream)
|
||||
{
|
||||
using BinaryStream reader = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true);
|
||||
Settings = reader.ReadStruct<MapGenSettings>();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>>
|
||||
public void Load(string fileName)
|
||||
{
|
||||
using FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
Load(stream);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Save(Stream stream)
|
||||
{
|
||||
using BinaryStream writer = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true);
|
||||
writer.WriteStruct(Settings);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Save(string fileName)
|
||||
{
|
||||
using FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None);
|
||||
Save(stream);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the required configuration for the land generator to create a map. This structure appears in LEV
|
||||
/// files (being their only content), in BIT files (being the header) and in PNG maps stored by WA (being the data
|
||||
/// of the w2lv or waLV chunks).
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct MapGenSettings
|
||||
{
|
||||
// ---- FIELDS -------------------------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>Random seed to generate the land shape (no effect in BIT files).</summary>
|
||||
public int LandSeed;
|
||||
/// <summary>Random seed to generate object placements.</summary>
|
||||
public int ObjectSeed;
|
||||
/// <summary><see langword="true"/> treats the generated map as a cavern, otherwise as an island, depending on
|
||||
/// <see cref="Style"/>.</summary>
|
||||
public bool Cavern;
|
||||
/// <summary>Style of the land generated, dependending on <see cref="Cavern"/>.</summary>
|
||||
public MapGenStyle Style;
|
||||
/// <summary><see langword="true"/> to disable an indestructible border being placed around the map.</summary>
|
||||
public bool NoIndiBorders;
|
||||
/// <summary>Probability percentage of map objects to appear on the land, from 0-100.</summary>
|
||||
public int ObjectPercentage;
|
||||
/// <summary>Probability percentage of bridges to appear on the land, from 0-100.</summary>
|
||||
public int BridgePercentage;
|
||||
/// <summary>Height of the water in percent, from 0-99.</summary>
|
||||
public int WaterLevel;
|
||||
/// <summary>Version of the structure, determining the available <see cref="SoilTextureIndex"/> values in Worms
|
||||
/// Armageddon.</summary>
|
||||
public MapGenVersion Version;
|
||||
/// <summary>Texture index determining the style of the generated map.</summary>
|
||||
public MapGenSoil SoilTextureIndex;
|
||||
/// <summary>Water color used for the map (deprecated, used only in Worms Armageddon 1.0).</summary>
|
||||
public int WaterColor;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the possible land styles.
|
||||
/// </summary>
|
||||
public enum MapGenStyle : int
|
||||
{
|
||||
/// <summary>A single island or a cavern.</summary>
|
||||
OneIslandOrCavern,
|
||||
/// <summary>Two islands or a double-layer cavern.</summary>
|
||||
TwoIslandsOrCaverns,
|
||||
/// <summary>One flat island or a cavern open at the bottom.</summary>
|
||||
OneFlatIslandOrCavernOpenBottom,
|
||||
/// <summary>Two flat islands or a cavern open at the left or right.</summary>
|
||||
TwoFlatIslandsOrCavernOpenLeftRight
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the possible versions which can be stored in the <see cref="MapGenSettings.Version"/> field.
|
||||
/// </summary>
|
||||
public enum MapGenVersion : short
|
||||
{
|
||||
/// <summary>Game version 3.0. Last soil texture indices are 26 = Tribal, 27 = Tribal, 28 = Urban. Additionally,
|
||||
/// floor and ceiling trimming is more severe.</summary>
|
||||
Version_3_0_0_0 = -1,
|
||||
/// <summary>Game version 3.5. Last soil texture indices are 26 = Tribal, 27 = Urban, 28 = undefined.</summary>
|
||||
Version_3_5_0_0 = 0,
|
||||
/// <summary>Game version 3.6.26.4. Last soil texture indices are 26 = Tools, 27 = Tribal, Urban = 28 (same as
|
||||
/// in WWP).</summary>
|
||||
Version_3_6_26_4 = 1
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the possible soil styles. In case of Worms Armageddon, this list matches
|
||||
/// <see cref="MapGenVersion.Version_3_6_26_4"/>.
|
||||
/// </summary>
|
||||
public enum MapGenSoil : short
|
||||
{
|
||||
ClassicBeach,
|
||||
ClassicDesert,
|
||||
ClassicFarm,
|
||||
ClassicForest,
|
||||
ClassicHell,
|
||||
Art,
|
||||
Cheese,
|
||||
Construction,
|
||||
Desert,
|
||||
Dungeon,
|
||||
Easter,
|
||||
Forest,
|
||||
Fruit,
|
||||
Gulf,
|
||||
Hell,
|
||||
Hospital,
|
||||
Jungle,
|
||||
Manhattan,
|
||||
Medieval,
|
||||
Music,
|
||||
Pirate,
|
||||
Snow,
|
||||
Space,
|
||||
Sports,
|
||||
Tentacle,
|
||||
Time,
|
||||
Tools,
|
||||
Tribal,
|
||||
Urban
|
||||
}
|
||||
}
|
246
src/library/Syroot.Worms.Armageddon/LandData.cs
Normal file
246
src/library/Syroot.Worms.Armageddon/LandData.cs
Normal file
@ -0,0 +1,246 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using Syroot.BinaryData;
|
||||
using Syroot.Worms.IO;
|
||||
|
||||
namespace Syroot.Worms.Armageddon
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents map configuration stored by the land generator in LAND.DAT files.
|
||||
/// Used by WA and WWP. S. https://worms2d.info/Land_Data_file.
|
||||
/// </summary>
|
||||
public class LandData : ILoadableFile, ISaveableFile
|
||||
{
|
||||
// ---- FIELDS -------------------------------------------------------------------------------------------------
|
||||
|
||||
private bool _alignImgData;
|
||||
|
||||
// ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LandData"/> class.
|
||||
/// </summary>
|
||||
public LandData() { }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LandData"/> class, loading the data from the given
|
||||
/// <see cref="Stream"/>.
|
||||
/// </summary>
|
||||
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
|
||||
public LandData(Stream stream) => Load(stream);
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LandData"/> class, loading the data from the given file.
|
||||
/// </summary>
|
||||
/// <param name="fileName">The name of the file to load the data from.</param>
|
||||
public LandData(string fileName) => Load(fileName);
|
||||
|
||||
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the format version of the file.
|
||||
/// </summary>
|
||||
public LandDataVersion Version { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether image data is aligned by 4-bytes. This is the case only for WWP.
|
||||
/// </summary>
|
||||
public bool AlignImgData
|
||||
{
|
||||
get => _alignImgData;
|
||||
set => _alignImgData = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the size of the landscape in pixels.
|
||||
/// </summary>
|
||||
public Size Size { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether an indestructible top border will be enabled.
|
||||
/// </summary>
|
||||
public bool TopBorder { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the height of the water in pixels.
|
||||
/// </summary>
|
||||
public int WaterHeight { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets an unknown value only available in newer W:A versions (apparently since 3.6.28.0).
|
||||
/// </summary>
|
||||
public int? Unknown { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets an array of coordinates at which objects can be placed.
|
||||
/// </summary>
|
||||
public IList<Point> ObjectLocations { get; set; } = new List<Point>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the visual foreground image.
|
||||
/// </summary>
|
||||
public Img Foreground { get; set; } = new Img();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the collision mask of the landscape.
|
||||
/// </summary>
|
||||
public Img CollisionMask { get; set; } = new Img();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the visual background image.
|
||||
/// </summary>
|
||||
public Img Background { get; set; } = new Img();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the path to the land image file.
|
||||
/// </summary>
|
||||
public string LandTexturePath { get; set; } = String.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the path to the Water.dir file.
|
||||
/// </summary>
|
||||
public string WaterDirPath { get; set; } = String.Empty;
|
||||
|
||||
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Load(Stream stream)
|
||||
{
|
||||
using BinaryStream reader = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true);
|
||||
|
||||
int readLocationCount()
|
||||
{
|
||||
int oldLocationCount = reader.ReadInt32();
|
||||
int oldImgStart = oldLocationCount * Unsafe.SizeOf<Point>();
|
||||
|
||||
// Check whether the old IMG start would be invalid.
|
||||
bool isNew = false;
|
||||
using (reader.TemporarySeek(oldImgStart))
|
||||
isNew = reader.EndOfStream || reader.ReadUInt32() != Img.Signature;
|
||||
if (isNew)
|
||||
{
|
||||
Unknown = oldLocationCount;
|
||||
return reader.ReadInt32();
|
||||
}
|
||||
else
|
||||
{
|
||||
Unknown = null;
|
||||
return oldLocationCount;
|
||||
}
|
||||
}
|
||||
|
||||
Img readImage(ref bool aligned)
|
||||
{
|
||||
long imgStart = reader.Position;
|
||||
Img img = new Img(reader.BaseStream, aligned);
|
||||
|
||||
// If reading the next image fails, the previous data was aligned and must be reread.
|
||||
if (!aligned)
|
||||
{
|
||||
if (reader.ReadUInt32() == Img.Signature)
|
||||
{
|
||||
reader.Position -= sizeof(uint);
|
||||
}
|
||||
else
|
||||
{
|
||||
reader.Position = imgStart;
|
||||
img = new Img(reader.BaseStream, true);
|
||||
aligned = true;
|
||||
}
|
||||
}
|
||||
|
||||
return img;
|
||||
}
|
||||
|
||||
// Read the header.
|
||||
Version = reader.ReadEnum<LandDataVersion>(true);
|
||||
int fileSize = reader.ReadInt32();
|
||||
|
||||
// Read the data.
|
||||
Size = reader.ReadStruct<Size>();
|
||||
TopBorder = reader.ReadBoolean(BooleanCoding.Dword);
|
||||
WaterHeight = reader.ReadInt32();
|
||||
|
||||
// Read the object locations.
|
||||
int locationCount = readLocationCount();
|
||||
ObjectLocations = new List<Point>(locationCount);
|
||||
for (int i = 0; i < locationCount; i++)
|
||||
ObjectLocations.Add(reader.ReadStruct<Point>());
|
||||
|
||||
// Read the image data, which alignment must be detected by trial-and-error.
|
||||
_alignImgData = Version == LandDataVersion.WormsWorldPartyAqua;
|
||||
long foreImgLocation = reader.Position;
|
||||
Foreground = readImage(ref _alignImgData);
|
||||
CollisionMask = readImage(ref _alignImgData);
|
||||
Background = new Img(reader.BaseStream, _alignImgData);
|
||||
|
||||
// Read the file paths.
|
||||
LandTexturePath = reader.ReadString(StringCoding.ByteCharCount);
|
||||
WaterDirPath = reader.ReadString(StringCoding.ByteCharCount);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Load(string fileName)
|
||||
{
|
||||
using FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
Load(stream);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Save(Stream stream)
|
||||
{
|
||||
using BinaryStream writer = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true);
|
||||
|
||||
// Write the header.
|
||||
writer.WriteEnum(Version, true);
|
||||
uint fileSizeOffset = writer.ReserveOffset();
|
||||
|
||||
// Write the data.
|
||||
writer.WriteStruct(Size);
|
||||
writer.Write(TopBorder, BooleanCoding.Dword);
|
||||
writer.Write(WaterHeight);
|
||||
if (Unknown.HasValue)
|
||||
writer.Write(Unknown.Value);
|
||||
|
||||
// Write the possible object coordinate array.
|
||||
writer.Write(ObjectLocations.Count);
|
||||
for (int i = 0; i < ObjectLocations.Count; i++)
|
||||
writer.WriteStruct(ObjectLocations[i]);
|
||||
|
||||
// Write the image data.
|
||||
Foreground.Save(writer.BaseStream, _alignImgData);
|
||||
CollisionMask.Save(writer.BaseStream, _alignImgData);
|
||||
Background.Save(writer.BaseStream, _alignImgData);
|
||||
|
||||
// Write the file paths.
|
||||
writer.Write(LandTexturePath, StringCoding.ByteCharCount);
|
||||
writer.Write(WaterDirPath, StringCoding.ByteCharCount);
|
||||
|
||||
writer.SatisfyOffset(fileSizeOffset, (uint)writer.Position);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Save(string fileName)
|
||||
{
|
||||
using FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None);
|
||||
Save(stream);
|
||||
}
|
||||
}
|
||||
|
||||
// ---- CONSTANTS ----------------------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Represents the version of <see cref="LandData"/> files, encoded as the signature.
|
||||
/// </summary>
|
||||
public enum LandDataVersion : uint
|
||||
{
|
||||
/// <summary>Found in W2, WA, WWP, and OW.</summary>
|
||||
Team17 = 0x1A444E4C, // "LND\x1A"
|
||||
/// <summary>Found only in WWPA.</summary>
|
||||
WormsWorldPartyAqua = 0x1B444E4C // "LND\x1B"
|
||||
}
|
||||
}
|
226
src/library/Syroot.Worms.Armageddon/Scheme.Enums.cs
Normal file
226
src/library/Syroot.Worms.Armageddon/Scheme.Enums.cs
Normal file
@ -0,0 +1,226 @@
|
||||
using System;
|
||||
|
||||
namespace Syroot.Worms.Armageddon
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents which worms are cured from being poisoned if a worm collects a health crate.
|
||||
/// </summary>
|
||||
public enum HealthCure : byte
|
||||
{
|
||||
/// <summary>Cures only the worm collecting the health crate.</summary>
|
||||
Single,
|
||||
/// <summary>Cures the team of the worm collecting the health crate.</summary>
|
||||
Team,
|
||||
/// <summary>Cures all allied teams of the worm collecting the health crate.</summary>
|
||||
Allies,
|
||||
/// <summary>Cures nobody.</summary>
|
||||
Nobody = Byte.MaxValue
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the types of objects which can appear on the map.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum MapObjectType
|
||||
{
|
||||
/// <summary>Neither mines or oil drums are placed on the map.</summary>
|
||||
None,
|
||||
/// <summary>Only mines are placed on the map.</summary>
|
||||
Mines = 1 << 0,
|
||||
/// <summary>Only oil drums are placed on the map.</summary>
|
||||
OilDrums = 1 << 1,
|
||||
/// <summary>Both mines and oil drums are placed on the map.</summary>
|
||||
Both = Mines | OilDrums
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the possible cavern roof extension directions.
|
||||
/// </summary>
|
||||
public enum Roofing : byte
|
||||
{
|
||||
/// <summary>Does not extend the roof.</summary>
|
||||
Default,
|
||||
/// <summary>Extends the roof infinitely upwards.</summary>
|
||||
Up,
|
||||
/// <summary>Extends the roof infinitely up- and sidewards.</summary>
|
||||
UpSide
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value determining which kinds of weapons can be dropped while rolling during roping.
|
||||
/// </summary>
|
||||
public enum RopeRollDrops : byte
|
||||
{
|
||||
/// <summary>No weapons can be dropped while rolling.</summary>
|
||||
None,
|
||||
/// <summary>Weapons which are droppable from a rope can be dropped while rolling.</summary>
|
||||
Rope,
|
||||
/// <summary>Weapons which are droppable from a rope or while jumping can be dropped while rolling.</summary>
|
||||
RopeJump
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the known versions of scheme file formats.
|
||||
/// </summary>
|
||||
public enum SchemeVersion : byte
|
||||
{
|
||||
/// <summary>WA 3.0 and WWP, original format.</summary>
|
||||
Version1 = 1,
|
||||
/// <summary>WA 3.5 and newer, storing super weapons.</summary>
|
||||
Version2 = 2,
|
||||
/// <summary>WA 3.7.3 and newer, storing new options.</summary>
|
||||
Version3 = 3
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents extension methods for <see cref="SchemeVersion"/> instances.
|
||||
/// </summary>
|
||||
public static class SchemeVersionExtensions
|
||||
{
|
||||
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Returns how many <see cref="SchemeWeapon"/> instances are stored in the <paramref name="version"/>.
|
||||
/// </summary>
|
||||
/// <param name="version">The <see cref="SchemeVersion"/>.</param>
|
||||
/// <returns>The number of weapons stored for this version.</returns>
|
||||
public static int GetWeaponCount(this SchemeVersion version) => version == SchemeVersion.Version1 ? 45 : 64;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the gravity simulation used in a game (as originating from RubberWorm).
|
||||
/// </summary>
|
||||
public enum RwGravityType : byte
|
||||
{
|
||||
/// <summary>No RubberWorm gravity logic is used.</summary>
|
||||
None,
|
||||
/// <summary>Default gravity, but affecting more objects.</summary>
|
||||
Default,
|
||||
/// <summary>Gravity is calculated as a constant force black hole.</summary>
|
||||
BlackHoleConstant,
|
||||
/// <summary>Gravity is calculated as a linear force / proportional black hole.</summary>
|
||||
BlackHoleLinear
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the known identifiers of scheme editors stored in schemes modified by them.
|
||||
/// </summary>
|
||||
public enum SchemeEditor : byte
|
||||
{
|
||||
/// <summary>Default (game editor or those that do not set a recognition byte).</summary>
|
||||
None,
|
||||
/// <summary>LeTotalKiller's PHP online editor.</summary>
|
||||
LeTotalKiller = 0x5F,
|
||||
/// <summary>SchemeEddy's Win32 editor.</summary>
|
||||
SchemeEddy = 0x89
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the effects an enabled <see cref="Scheme.SheepHeaven"/> has on the game.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum SheepHeavenFlags : byte
|
||||
{
|
||||
/// <summary>Crates always eject a sheep when exploding.</summary>
|
||||
Explode = 1 << 0,
|
||||
/// <summary>Extended fuse timer on sheep weapons.</summary>
|
||||
Fuse = 1 << 1,
|
||||
/// <summary>Crates have higher probability to contain sheep weapons.</summary>
|
||||
Odds = 1 << 2,
|
||||
/// <summary>Enabled all of the sheep heaven effects.</summary>
|
||||
All = Explode | Fuse | Odds
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the possible loss of control when skimming on water.
|
||||
/// </summary>
|
||||
public enum SkimControlLoss : byte
|
||||
{
|
||||
/// <summary>Control is lost when skimming.</summary>
|
||||
Lost,
|
||||
/// <summary>Control is retained but the rope cannot be shot again until landing.</summary>
|
||||
Kept,
|
||||
/// <summary>Control is retained and the rope can be shot even before landing.</summary>
|
||||
KeptWithRope
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the possible methods of triggering skip walking to speed up the walking speed.
|
||||
/// </summary>
|
||||
public enum SkipWalk : byte
|
||||
{
|
||||
/// <summary>Skip walking is possible by right clicking during the turn.</summary>
|
||||
Default,
|
||||
/// <summary>Skip walking is possible by using the up and down arrow keys.</summary>
|
||||
Facilitated,
|
||||
/// <summary>Skip walking is prevented.</summary>
|
||||
Disabled = Byte.MaxValue
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the stockpiling mode of weapon armory between rounds.
|
||||
/// </summary>
|
||||
public enum Stockpiling : byte
|
||||
{
|
||||
/// <summary>Each round starts with the exact amount of weapons set in the scheme.</summary>
|
||||
Off,
|
||||
/// <summary>Weapons collected additionally to the ones set in the scheme are transfered to the next round.</summary>
|
||||
On,
|
||||
/// <summary>Weapons are only given out at start of first round, and not renewed in following rounds.</summary>
|
||||
Anti
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the method to determine the next turn's worm.
|
||||
/// </summary>
|
||||
public enum WormSelect : byte
|
||||
{
|
||||
/// <summary>Worms are selected in the order in which they appear in the team.</summary>
|
||||
Sequential,
|
||||
/// <summary>Worms are selected by the player.</summary>
|
||||
Manual,
|
||||
/// <summary>Worms are selected randomly.</summary>
|
||||
Random
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the event triggered when the round timer runs out.
|
||||
/// </summary>
|
||||
public enum SuddenDeathEvent : byte
|
||||
{
|
||||
/// <summary>The round ends and is drawn.</summary>
|
||||
RoundEnd,
|
||||
/// <summary>A nuklear test is triggered.</summary>
|
||||
NuclearStrike,
|
||||
/// <summary>The worms health is reduced to 1.</summary>
|
||||
HealthDrop,
|
||||
/// <summary>No special event is triggered and the water only rises in the rate specified in the scheme.</summary>
|
||||
WaterRise
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the objects or effects worms phase through.
|
||||
/// </summary>
|
||||
public enum WormPhasing : byte
|
||||
{
|
||||
/// <summary>Worms are affected as usual.</summary>
|
||||
None,
|
||||
/// <summary>Worms are not affected by other worms.</summary>
|
||||
Worms,
|
||||
/// <summary>Worms are not affected by other worms and weapons.</summary>
|
||||
WormsWeapons,
|
||||
/// <summary>Worms are not affected by other worms, weapons, and damage.</summary>
|
||||
WormsWeaponsDamage
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the possible loss of control on high speed horizontal collisions.
|
||||
/// </summary>
|
||||
public enum XImpactControlLoss : byte
|
||||
{
|
||||
/// <summary>Control is lost.</summary>
|
||||
Loss,
|
||||
/// <summary>Control is retained.</summary>
|
||||
Kept = Byte.MaxValue
|
||||
}
|
||||
}
|
1072
src/library/Syroot.Worms.Armageddon/Scheme.ExtendedOptions.cs
Normal file
1072
src/library/Syroot.Worms.Armageddon/Scheme.ExtendedOptions.cs
Normal file
File diff suppressed because it is too large
Load Diff
46
src/library/Syroot.Worms.Armageddon/Scheme.WeaponList.cs
Normal file
46
src/library/Syroot.Worms.Armageddon/Scheme.WeaponList.cs
Normal file
@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Syroot.Worms.Armageddon
|
||||
{
|
||||
partial class Scheme
|
||||
{
|
||||
// ---- CLASSES, STRUCTS & ENUMS -------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Represents a list of <see cref="SchemeWeapon"/> instances which can be accessed by <see cref="Weapon"/>.
|
||||
/// </summary>
|
||||
public class WeaponList : IReadOnlyCollection<SchemeWeapon>
|
||||
{
|
||||
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
|
||||
private readonly SchemeWeapon[] _array = new SchemeWeapon[64];
|
||||
|
||||
/// <summary>
|
||||
/// Gets a reference to the weapon with the given <paramref name="index"/>.
|
||||
/// </summary>
|
||||
/// <param name="index">The index of the weapon to access.</param>
|
||||
/// <returns>A reference to the <see cref="SchemeWeapon"/>.</returns>
|
||||
public ref SchemeWeapon this[int index] => ref _array[index];
|
||||
|
||||
/// <summary>
|
||||
/// Gets a reference to the weapon with the given <paramref name="name"/>.
|
||||
/// </summary>
|
||||
/// <param name="name">The <see cref="Weapon"/> of the weapon to access.</param>
|
||||
/// <returns>A reference to the <see cref="SchemeWeapon"/>.</returns>
|
||||
public ref SchemeWeapon this[Weapon name] => ref _array[(int)name];
|
||||
|
||||
/// <inheritdoc/>
|
||||
public int Count => _array.Length;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IEnumerator<SchemeWeapon> GetEnumerator() => ((IEnumerable<SchemeWeapon>)_array).GetEnumerator();
|
||||
|
||||
internal Span<SchemeWeapon> AsSpan(int length) => _array.AsSpan(0, length);
|
||||
|
||||
/// <inheritdoc/>
|
||||
IEnumerator IEnumerable.GetEnumerator() => _array.GetEnumerator();
|
||||
}
|
||||
}
|
||||
}
|
1484
src/library/Syroot.Worms.Armageddon/Scheme.cs
Normal file
1484
src/library/Syroot.Worms.Armageddon/Scheme.cs
Normal file
File diff suppressed because it is too large
Load Diff
59
src/library/Syroot.Worms.Armageddon/SchemeWeapon.cs
Normal file
59
src/library/Syroot.Worms.Armageddon/SchemeWeapon.cs
Normal file
@ -0,0 +1,59 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Syroot.Worms.Armageddon
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the configuration of a weapon in a <see cref="Scheme"/>.
|
||||
/// </summary>
|
||||
[DebuggerDisplay("Ammo={Ammo} Power={Power} Delay={Delay} Crates={Crates}")]
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct SchemeWeapon : IEquatable<SchemeWeapon>
|
||||
{
|
||||
// ---- FIELDS -------------------------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>Amount with which a team is equipped at game start. 10 and negative values represent infinity.</summary>
|
||||
public sbyte Ammo;
|
||||
/// <summary>Intensity of this weapon.</summary>
|
||||
public byte Power;
|
||||
/// <summary>Number of turns required to be taken by each team before this weapon becomes available. Negative
|
||||
/// values represent infinity.</summary>
|
||||
public sbyte Delay;
|
||||
/// <summary>Probability of this weapon to appear in crates. Has no effect on super weapons.</summary>
|
||||
public sbyte Prob;
|
||||
|
||||
// ---- OPERATORS ----------------------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether two <see cref="SchemeWeapon"/> instances are equal by value.
|
||||
/// </summary>
|
||||
/// <param name="left">The first instance to compare.</param>
|
||||
/// <param name="right">The second instance to compare.</param>
|
||||
/// <returns>Whether the instances are equal.</returns>
|
||||
public static bool operator ==(SchemeWeapon left, SchemeWeapon right) => left.Equals(right);
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether two <see cref="SchemeWeapon"/> instances are inequal by value.
|
||||
/// </summary>
|
||||
/// <param name="left">The first instance to compare.</param>
|
||||
/// <param name="right">The second instance to compare.</param>
|
||||
/// <returns>Whether the instances are inequal.</returns>
|
||||
public static bool operator !=(SchemeWeapon left, SchemeWeapon right) => !(left == right);
|
||||
|
||||
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Equals(object obj) => obj is SchemeWeapon weapon && Equals(weapon);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool Equals(SchemeWeapon other)
|
||||
=> Ammo == other.Ammo
|
||||
&& Power == other.Power
|
||||
&& Delay == other.Delay
|
||||
&& Prob == other.Prob;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override int GetHashCode() => HashCode.Combine(Ammo, Power, Delay, Prob);
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="$(MSBuildThisFileDirectory)..\..\build.xml" />
|
||||
|
||||
<!-- Metadata -->
|
||||
<PropertyGroup>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<Description>.NET library for loading and modifying files of Team17's Worms Armageddon.</Description>
|
||||
<PackageReleaseNotes>Fix StackOverflowException when using legacy .NET versions.</PackageReleaseNotes>
|
||||
<PackageTags>$(PackageTags);worms armageddon</PackageTags>
|
||||
<Version>4.0.3</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- References -->
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Syroot.Worms\Syroot.Worms.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
311
src/library/Syroot.Worms.Armageddon/Team.cs
Normal file
311
src/library/Syroot.Worms.Armageddon/Team.cs
Normal file
@ -0,0 +1,311 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Syroot.BinaryData;
|
||||
using Syroot.Worms.IO;
|
||||
|
||||
namespace Syroot.Worms.Armageddon
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a team stored in a <see cref="TeamContainer"/> file.
|
||||
/// </summary>
|
||||
public class Team : ILoadable, ISaveable
|
||||
{
|
||||
// ---- CONSTANTS ----------------------------------------------------------------------------------------------
|
||||
|
||||
private const int _missionCount = 33;
|
||||
private const int _trainingMissionCount = 6;
|
||||
|
||||
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the team.
|
||||
/// </summary>
|
||||
public string Name { get; set; } = String.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the 8 worm names.
|
||||
/// </summary>
|
||||
public string[] WormNames { get; } = new string[8];
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the AI intelligence difficulty level, from 0-5, where 0 is human-controlled.
|
||||
/// </summary>
|
||||
public byte CpuLevel { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of soundbank for the voice of team worms.
|
||||
/// </summary>
|
||||
public string SoundBankName { get; set; } = String.Empty;
|
||||
|
||||
public byte SoundBankLocation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the team fanfare.
|
||||
/// </summary>
|
||||
public string FanfareName { get; set; } = String.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the fanfare with the name stored in <see cref="FanfareName"/>
|
||||
/// (<see langword="true"/>) or the player's countries' fanfare should be played (<see langword="false"/>).
|
||||
/// </summary>
|
||||
public byte UseCustomFanfare { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the sprite index of the team grave, -1 being a custom bitmap grave.
|
||||
/// </summary>
|
||||
public sbyte GraveSprite { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the file name of the team grave bitmap if it uses a custom one.
|
||||
/// </summary>
|
||||
public string GraveFileName { get; set; } = String.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the team grave bitmap if it uses a custom one.
|
||||
/// </summary>
|
||||
public RawBitmap Grave { get; set; } = new RawBitmap();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the team's special weapon.
|
||||
/// </summary>
|
||||
public TeamWeapon TeamWeapon { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number of games lost.
|
||||
/// </summary>
|
||||
public int GamesLost { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number of deathmatch games lost.
|
||||
/// </summary>
|
||||
public int DeathmatchesLost { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number of games won.
|
||||
/// </summary>
|
||||
public int GamesWon { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number of deathmatch games won.
|
||||
/// </summary>
|
||||
public int DeathmatchesWon { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number of games drawn.
|
||||
/// </summary>
|
||||
public int GamesDrawn { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number of deathmatch games drawn.
|
||||
/// </summary>
|
||||
public int DeathmatchesDrawn { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number of opponent worms killed by this team.
|
||||
/// </summary>
|
||||
public int Kills { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number of opponent worms killed by this team in deathmatches.
|
||||
/// </summary>
|
||||
public int DeathmatchKills { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number of worms which got killed in this team.
|
||||
/// </summary>
|
||||
public int Deaths { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number of worms which got killed in this team in deathmatches.
|
||||
/// </summary>
|
||||
public int DeathmatchDeaths { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the array of 33 mission statuses.
|
||||
/// </summary>
|
||||
public TeamMissionStatus[] MissionStatuses { get; } = new TeamMissionStatus[_missionCount];
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the file name of the team flag.
|
||||
/// </summary>
|
||||
public string FlagFileName { get; set; } = String.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the bitmap of the team flag.
|
||||
/// </summary>
|
||||
public RawBitmap Flag { get; set; } = new RawBitmap();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the deathmatch rank this team reached.
|
||||
/// </summary>
|
||||
public byte DeathmatchRank { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the seconds the team required to finish all 6 training missions.
|
||||
/// </summary>
|
||||
public int[] TrainingMissionTimes { get; set; } = new int[_trainingMissionCount];
|
||||
|
||||
public int[] Unknown1 { get; set; } = new int[10];
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the medals the team achieved in all 6 training missions.
|
||||
/// </summary>
|
||||
public byte[] TrainingMissionMedals { get; set; } = new byte[_trainingMissionCount];
|
||||
|
||||
public byte[] Unknown2 { get; set; } = new byte[10];
|
||||
|
||||
public int[] Unknown3 { get; set; } = new int[7];
|
||||
|
||||
public byte Unknown4 { get; set; }
|
||||
|
||||
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Load(Stream stream)
|
||||
{
|
||||
using BinaryStream reader = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true);
|
||||
|
||||
Name = reader.ReadString(17);
|
||||
for (int i = 0; i < WormNames.Length; i++)
|
||||
WormNames[i] = reader.ReadString(17);
|
||||
CpuLevel = reader.Read1Byte();
|
||||
SoundBankName = reader.ReadString(0x20);
|
||||
SoundBankLocation = reader.Read1Byte();
|
||||
FanfareName = reader.ReadString(0x20);
|
||||
UseCustomFanfare = reader.Read1Byte();
|
||||
|
||||
GraveSprite = reader.ReadSByte();
|
||||
if (GraveSprite < 0)
|
||||
{
|
||||
GraveFileName = reader.ReadString(0x20);
|
||||
Grave = new RawBitmap()
|
||||
{
|
||||
BitsPerPixel = 8,
|
||||
Size = new Size(24, 32),
|
||||
Palette = reader.ReadColors(256),
|
||||
Data = reader.ReadBytes(24 * 32)
|
||||
};
|
||||
}
|
||||
|
||||
TeamWeapon = reader.ReadEnum<TeamWeapon>(true);
|
||||
GamesLost = reader.ReadInt32();
|
||||
DeathmatchesLost = reader.ReadInt32();
|
||||
GamesWon = reader.ReadInt32();
|
||||
DeathmatchesWon = reader.ReadInt32();
|
||||
GamesDrawn = reader.ReadInt32();
|
||||
DeathmatchesDrawn = reader.ReadInt32();
|
||||
Kills = reader.ReadInt32();
|
||||
DeathmatchKills = reader.ReadInt32();
|
||||
Deaths = reader.ReadInt32();
|
||||
DeathmatchDeaths = reader.ReadInt32();
|
||||
for (int i = 0; i < _missionCount; i++)
|
||||
MissionStatuses[i] = reader.ReadStruct<TeamMissionStatus>();
|
||||
|
||||
FlagFileName = reader.ReadString(0x20);
|
||||
Flag = new RawBitmap()
|
||||
{
|
||||
BitsPerPixel = 8,
|
||||
Size = new Size(20, 17),
|
||||
Palette = reader.ReadColors(256),
|
||||
Data = reader.ReadBytes(20 * 17)
|
||||
};
|
||||
|
||||
DeathmatchRank = reader.Read1Byte();
|
||||
TrainingMissionTimes = reader.ReadInt32s(_trainingMissionCount);
|
||||
Unknown1 = reader.ReadInt32s(10);
|
||||
TrainingMissionMedals = reader.ReadBytes(_trainingMissionCount);
|
||||
Unknown2 = reader.ReadBytes(10);
|
||||
Unknown3 = reader.ReadInt32s(7);
|
||||
Unknown4 = reader.Read1Byte();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Save(Stream stream)
|
||||
{
|
||||
using BinaryStream writer = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true);
|
||||
|
||||
writer.WriteFixedString(Name, 17);
|
||||
for (int i = 0; i < WormNames.Length; i++)
|
||||
writer.WriteFixedString(WormNames[i], 17);
|
||||
writer.Write(CpuLevel);
|
||||
writer.WriteFixedString(SoundBankName, 0x20);
|
||||
writer.Write(SoundBankLocation);
|
||||
writer.WriteFixedString(FanfareName, 0x20);
|
||||
writer.Write(UseCustomFanfare);
|
||||
|
||||
writer.Write(GraveSprite);
|
||||
if (GraveSprite < 0)
|
||||
{
|
||||
writer.WriteFixedString(GraveFileName, 0x20);
|
||||
writer.WriteColors(Grave.Palette!);
|
||||
writer.Write(Grave.Data);
|
||||
}
|
||||
|
||||
writer.WriteEnum(TeamWeapon, true);
|
||||
writer.Write(GamesLost);
|
||||
writer.Write(DeathmatchesLost);
|
||||
writer.Write(GamesWon);
|
||||
writer.Write(DeathmatchesWon);
|
||||
writer.Write(GamesDrawn);
|
||||
writer.Write(DeathmatchesDrawn);
|
||||
writer.Write(Kills);
|
||||
writer.Write(DeathmatchKills);
|
||||
writer.Write(Deaths);
|
||||
writer.Write(DeathmatchDeaths);
|
||||
for (int i = 0; i < MissionStatuses.Length; i++)
|
||||
writer.WriteStruct(ref MissionStatuses[i]);
|
||||
|
||||
writer.WriteFixedString(FlagFileName, 0x20);
|
||||
writer.WriteColors(Flag.Palette!);
|
||||
writer.Write(Flag.Data);
|
||||
|
||||
writer.Write(DeathmatchRank);
|
||||
writer.Write(TrainingMissionTimes);
|
||||
writer.Write(Unknown1);
|
||||
writer.Write(TrainingMissionMedals);
|
||||
writer.Write(Unknown2);
|
||||
writer.Write(Unknown3);
|
||||
writer.Write(Unknown4);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a team's progress in a mission.
|
||||
/// </summary>
|
||||
[DebuggerDisplay("TeamMissionStatus Attemps={Attempts} Medal={Medal}")]
|
||||
public struct TeamMissionStatus
|
||||
{
|
||||
// ---- FIELDS -------------------------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>The number of attempts the team required to solve the mission.</summary>
|
||||
public int Attempts;
|
||||
/// <summary>The medal the team got to solve the mission.</summary>
|
||||
public int Medal;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the special weapon of a team.
|
||||
/// </summary>
|
||||
public enum TeamWeapon : byte
|
||||
{
|
||||
/// <summary>The Flame Thrower weapon.</summary>
|
||||
Flamethrower,
|
||||
/// <summary>The Mole Bomb weapon.</summary>
|
||||
MoleBomb,
|
||||
/// <summary>The Old Woman weapon.</summary>
|
||||
OldWoman,
|
||||
/// <summary>The Homing Pigeon weapon.</summary>
|
||||
HomingPigeon,
|
||||
/// <summary>The Sheep Launcher weapon.</summary>
|
||||
SheepLauncher,
|
||||
/// <summary>The Mad Cow weapon.</summary>
|
||||
MadCow,
|
||||
/// <summary>The Holy Hand Grenade weapon.</summary>
|
||||
HolyHandGrenade,
|
||||
/// <summary>The Super Sheep or Aqua Sheep weapon.</summary>
|
||||
SuperSheep
|
||||
}
|
||||
}
|
156
src/library/Syroot.Worms.Armageddon/TeamContainer.cs
Normal file
156
src/library/Syroot.Worms.Armageddon/TeamContainer.cs
Normal file
@ -0,0 +1,156 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Syroot.BinaryData;
|
||||
using Syroot.Worms.IO;
|
||||
|
||||
namespace Syroot.Worms.Armageddon
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the list of teams and unlocked game features stored in WGT files.
|
||||
/// Used by WA. S. https://worms2d.info/Team_file.
|
||||
/// </summary>
|
||||
public class TeamContainer : ILoadableFile, ISaveableFile
|
||||
{
|
||||
// ---- CONSTANTS ----------------------------------------------------------------------------------------------
|
||||
|
||||
private const string _signature = "WGT"; // 0-terminated.
|
||||
|
||||
// ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TeamContainer"/> class.
|
||||
/// </summary>
|
||||
public TeamContainer() { }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TeamContainer"/> class, loading the data from the given
|
||||
/// <see cref="Stream"/>.
|
||||
/// </summary>
|
||||
/// <param name="stream">The <see cref="Stream"/> to load the data from.</param>
|
||||
public TeamContainer(Stream stream) => Load(stream);
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TeamContainer"/> class, loading the data from the given file.
|
||||
/// </summary>
|
||||
/// <param name="fileName">The name of the file to load the data from.</param>
|
||||
public TeamContainer(string fileName) => Load(fileName);
|
||||
|
||||
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value possibly indicating a version of the file format.
|
||||
/// </summary>
|
||||
public byte Version { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the unlocked utilities, weapon upgrades, and game cheats.
|
||||
/// </summary>
|
||||
public UnlockedFeatures UnlockedFeatures { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets an unknown value.
|
||||
/// </summary>
|
||||
public byte Unknown { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the list of <see cref="Team"/> instances stored.
|
||||
/// </summary>
|
||||
public IList<Team> Teams { get; set; } = new List<Team>();
|
||||
|
||||
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Load(Stream stream)
|
||||
{
|
||||
using BinaryStream reader = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true);
|
||||
|
||||
// Read the header.
|
||||
if (reader.ReadString(StringCoding.ZeroTerminated) != _signature)
|
||||
throw new InvalidDataException("Invalid WGT file signature.");
|
||||
Version = reader.Read1Byte(); // Really version?
|
||||
|
||||
// Read global settings.
|
||||
byte teamCount = reader.Read1Byte();
|
||||
UnlockedFeatures = reader.ReadEnum<UnlockedFeatures>(false);
|
||||
Unknown = reader.Read1Byte();
|
||||
|
||||
// Read the teams.
|
||||
Teams = new List<Team>();
|
||||
while (teamCount-- > 0)
|
||||
Teams.Add(reader.Load<Team>());
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Load(string fileName)
|
||||
{
|
||||
using FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
Load(stream);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Save(Stream stream)
|
||||
{
|
||||
using BinaryStream writer = new BinaryStream(stream, encoding: Encoding.ASCII, leaveOpen: true);
|
||||
|
||||
// Write the header.
|
||||
writer.Write(_signature, StringCoding.ZeroTerminated);
|
||||
writer.Write(Version);
|
||||
|
||||
// Write global settings.
|
||||
writer.Write((byte)Teams.Count);
|
||||
writer.WriteEnum(UnlockedFeatures, false);
|
||||
writer.Write(Unknown);
|
||||
|
||||
// Write the teams.
|
||||
foreach (Team team in Teams)
|
||||
team.Save(writer.BaseStream);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Save(string fileName)
|
||||
{
|
||||
using FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None);
|
||||
Save(stream);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents unlockable features of the game.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum UnlockedFeatures : int
|
||||
{
|
||||
/// <summary>No features have been unlocked yet.</summary>
|
||||
None,
|
||||
/// <summary>The utility weapon Laser Sight can be configured.</summary>
|
||||
UtilityLaserSight = 1 << 0,
|
||||
/// <summary>The utility weapon Fast Walk can be configured.</summary>
|
||||
UtilityFastWalk = 1 << 1,
|
||||
/// <summary>The utility weapon Invisibility can be configured.</summary>
|
||||
UtilityInvisibility = 1 << 2,
|
||||
/// <summary>The utility weapon Low Gravity can be configured.</summary>
|
||||
UtilityLowGravity = 1 << 3,
|
||||
/// <summary>The utility weapon Jetpack can be configured.</summary>
|
||||
UtilityJetpack = 1 << 4,
|
||||
/// <summary>The Grenade upgrade can be enabled.</summary>
|
||||
UpgradedGrenade = 1 << 8,
|
||||
/// <summary>The Shotgun upgrade can be enabled.</summary>
|
||||
UpgradedShotgun = 1 << 9,
|
||||
/// <summary>The cluster upgrade can be enabled.</summary>
|
||||
UpgradedClusters = 1 << 10,
|
||||
/// <summary>The Longbow upgrade can be enabled.</summary>
|
||||
UpgradedLongbow = 1 << 11,
|
||||
/// <summary>The upgrade of Super Sheeps to become Aqua Sheeps can be enabled.</summary>
|
||||
AquaSheep = 1 << 12,
|
||||
/// <summary>Worms can have infinite health and are killable only by drowning them.</summary>
|
||||
GodWorms = 1 << 16,
|
||||
/// <summary>Blood effects when hitting worms can be enabled.</summary>
|
||||
BloodFx = 1 << 17,
|
||||
/// <summary>Every crate explodes with a sheep.</summary>
|
||||
SheepHeaven = 1 << 18,
|
||||
/// <summary>Map terrain can be indestructible and Full Wormage scheme is accessible.</summary>
|
||||
IndestructibleAndFullWormage = 1 << 24
|
||||
}
|
||||
}
|
152
src/library/Syroot.Worms.Armageddon/Weapon.cs
Normal file
152
src/library/Syroot.Worms.Armageddon/Weapon.cs
Normal file
@ -0,0 +1,152 @@
|
||||
namespace Syroot.Worms.Armageddon
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the weapons in the game.
|
||||
/// </summary>
|
||||
public enum Weapon
|
||||
{
|
||||
/// <summary>The Bazooka weapon.</summary>
|
||||
Bazooka,
|
||||
/// <summary>The Homing Missile weapon.</summary>
|
||||
HomingMissile,
|
||||
/// <summary>The Mortar weapon.</summary>
|
||||
Mortar,
|
||||
/// <summary>The Grenade weapon.</summary>
|
||||
Grenade,
|
||||
/// <summary>The Cluster Bomb weapon.</summary>
|
||||
ClusterBomb,
|
||||
/// <summary>The Skunk weapon.</summary>
|
||||
Skunk,
|
||||
/// <summary>The Petrol Bomb weapon.</summary>
|
||||
PetrolBomb,
|
||||
/// <summary>The Banana Bomb weapon.</summary>
|
||||
BananaBomb,
|
||||
/// <summary>The Handgun weapon.</summary>
|
||||
Handgun,
|
||||
/// <summary>The Shotgun weapon.</summary>
|
||||
Shotgun,
|
||||
/// <summary>The Uzi weapon.</summary>
|
||||
Uzi,
|
||||
/// <summary>The Minigun weapon.</summary>
|
||||
Minigun,
|
||||
/// <summary>The Longbow weapon.</summary>
|
||||
Longbow,
|
||||
/// <summary>The Airstrike weapon.</summary>
|
||||
Airstrike,
|
||||
/// <summary>The Napalm Strike weapon.</summary>
|
||||
NapalmStrike,
|
||||
/// <summary>The Mine weapon.</summary>
|
||||
Mine,
|
||||
/// <summary>The Firepunch weapon.</summary>
|
||||
Firepunch,
|
||||
/// <summary>The Dragonball weapon.</summary>
|
||||
Dragonball,
|
||||
/// <summary>The Kamikaze weapon.</summary>
|
||||
Kamikaze,
|
||||
/// <summary>The Prod weapon.</summary>
|
||||
Prod,
|
||||
/// <summary>The Battle Axe weapon.</summary>
|
||||
BattleAxe,
|
||||
/// <summary>The Blowtorch weapon.</summary>
|
||||
Blowtorch,
|
||||
/// <summary>The Pneumatic Drill weapon.</summary>
|
||||
PneumaticDrill,
|
||||
/// <summary>The Girder weapon.</summary>
|
||||
Girder,
|
||||
/// <summary>The Ninja Rope weapon.</summary>
|
||||
NinjaRope,
|
||||
/// <summary>The Parachute weapon.</summary>
|
||||
Parachute,
|
||||
/// <summary>The Bungee weapon.</summary>
|
||||
Bungee,
|
||||
/// <summary>The Teleport weapon.</summary>
|
||||
Teleport,
|
||||
/// <summary>The Dynamite weapon.</summary>
|
||||
Dynamite,
|
||||
/// <summary>The Sheep weapon.</summary>
|
||||
Sheep,
|
||||
/// <summary>The Baseball Bat weapon.</summary>
|
||||
BaseballBat,
|
||||
/// <summary>The Flame Thrower weapon.</summary>
|
||||
Flamethrower,
|
||||
/// <summary>The Homing Pigeon weapon.</summary>
|
||||
HomingPigeon,
|
||||
/// <summary>The Mad Cow weapon.</summary>
|
||||
MadCow,
|
||||
/// <summary>The Holy Hand Grenade weapon.</summary>
|
||||
HolyHandGrenade,
|
||||
/// <summary>The Old Woman weapon.</summary>
|
||||
OldWoman,
|
||||
/// <summary>The Sheep Launcher weapon.</summary>
|
||||
SheepLauncher,
|
||||
/// <summary>The Super Sheep or Aqua Sheep weapon.</summary>
|
||||
SuperSheep,
|
||||
/// <summary>The Mole Bomb weapon.</summary>
|
||||
MoleBomb,
|
||||
/// <summary>The Jetpack utility.</summary>
|
||||
Jetpack,
|
||||
/// <summary>The Low Gravity utility.</summary>
|
||||
LowGravity,
|
||||
/// <summary>The Laser Sight utility.</summary>
|
||||
LaserSight,
|
||||
/// <summary>The Fast Walk utility.</summary>
|
||||
FastWalk,
|
||||
/// <summary>The Invisibility utility.</summary>
|
||||
Invisibility,
|
||||
/// <summary>The Damage x2 utility.</summary>
|
||||
DamageX2,
|
||||
/// <summary>The Freeze super weapon.</summary>
|
||||
Freeze,
|
||||
/// <summary>The Super Banana Bomb super weapon.</summary>
|
||||
SuperBananaBomb,
|
||||
/// <summary>The Mine Strike super weapon.</summary>
|
||||
MineStrike,
|
||||
/// <summary>The Girder Starter Pack super weapon.</summary>
|
||||
GirderStarterPack,
|
||||
/// <summary>The Earthquake super weapon.</summary>
|
||||
Earthquake,
|
||||
/// <summary>The Scales Of Justice super weapon.</summary>
|
||||
ScalesOfJustice,
|
||||
/// <summary>The Ming Vase super weapon.</summary>
|
||||
MingVase,
|
||||
/// <summary>The Mike's Carpet Bomb super weapon.</summary>
|
||||
MikesCarpetBomb,
|
||||
/// <summary>The Patsy's Magic Bullet super weapon.</summary>
|
||||
MagicBullet,
|
||||
/// <summary>The Indian Nuclear Test super weapon.</summary>
|
||||
NuclearTest,
|
||||
/// <summary>The Select Worm super weapon.</summary>
|
||||
SelectWorm,
|
||||
/// <summary>The Salvation Army super weapon.</summary>
|
||||
SalvationArmy,
|
||||
/// <summary>The Mole Squadron super weapon.</summary>
|
||||
MoleSquadron,
|
||||
/// <summary>The MB Bomb super weapon.</summary>
|
||||
MBBomb,
|
||||
/// <summary>The Concrete Donkey super weapon.</summary>
|
||||
ConcreteDonkey,
|
||||
/// <summary>The Suicide Bomber super weapon.</summary>
|
||||
SuicideBomber,
|
||||
/// <summary>The Sheep Strike super weapon.</summary>
|
||||
SheepStrike,
|
||||
/// <summary>The Mail Strike super weapon.</summary>
|
||||
MailStrike,
|
||||
/// <summary>The Armageddon super weapon.</summary>
|
||||
Armageddon
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents utility methods for <see cref="Weapon"/> instances.
|
||||
/// </summary>
|
||||
public static class WeaponTools
|
||||
{
|
||||
// ---- METHODS (PUBLIC) ---------------------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Returns a value indicating whether the <paramref name="weapon"/> is handled as a super weapon.
|
||||
/// </summary>
|
||||
/// <param name="weapon">The <see cref="Weapon"/> to check for being a super weapon.</param>
|
||||
/// <returns>Whether the weapon is a super weapon.</returns>
|
||||
public static bool IsSuperWeapon(this Weapon weapon) => weapon >= Weapon.Freeze;
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user