├── .gitignore
├── ItemIDs.txt
├── LICENSE
├── Project
├── Icons
│ ├── IconAmulet.png
│ ├── IconBeak.png
│ ├── IconBlock.png
│ ├── IconBoots.png
│ ├── IconCandle.png
│ ├── IconChestArmor.png
│ ├── IconCoin.png
│ ├── IconConsumable.png
│ ├── IconGloves.png
│ ├── IconItems.png
│ ├── IconLamp.png
│ ├── IconLeftovers.png
│ ├── IconManaCube.png
│ ├── IconPainting.png
│ ├── IconPet.png
│ ├── IconPetFood.png
│ ├── IconPlatinumCoin.png
│ ├── IconQuestItem.png
│ ├── IconRecipe.png
│ ├── IconRing.png
│ ├── IconShoulderArmor.png
│ ├── IconTransportation.png
│ ├── IconVase.png
│ ├── IconWeapon.png
│ └── ItemIcon.png
├── icon.ico
├── icon.png
├── stats.ntl3fty.txt
└── x2048.png
├── README.md
├── References
├── SQLite.Interop.dll
├── System.Data.SQLite.dll
├── System.Data.SQLite.dll.NET40.2.old
├── System.Data.SQLite.dll.NET40.old
├── app.config
└── zlib.net.dll
├── Source
├── Character
│ ├── Character.cs
│ ├── ChineseRemainder.cs
│ ├── Constants.cs
│ ├── ICharacterData.cs
│ ├── Inventory.cs
│ ├── Item.cs
│ ├── ItemAttribute.cs
│ ├── NameGenerator.cs
│ ├── Slot.cs
│ └── World.cs
├── CharacterEditor.csproj
├── CharacterEditor.sln
├── Database.cs
├── DirtyWatcher.cs
├── Forms
│ ├── Editor.Character.cs
│ ├── Editor.Data.cs
│ ├── Editor.Designer.cs
│ ├── Editor.Equipment.cs
│ ├── Editor.Inventory.cs
│ ├── Editor.cs
│ ├── Editor.resx
│ ├── ExceptionDialog.Designer.cs
│ ├── ExceptionDialog.cs
│ ├── ExceptionDialog.resx
│ ├── FormItemStats.Designer.cs
│ ├── FormItemStats.cs
│ ├── FormItemStats.resx
│ ├── LoadCharacterDialog.Designer.cs
│ ├── LoadCharacterDialog.cs
│ ├── LoadCharacterDialog.resx
│ └── SafeNumericUpDown.cs
├── Program.cs
├── Properties
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ └── Resources.resx
├── Resources
│ └── x2048.png
├── Utility.cs
├── app.config
└── icon.ico
├── TODO.txt
└── characterformat.txt
/.gitignore:
--------------------------------------------------------------------------------
1 | # Build Folders (you can keep bin if you'd like, to store dlls and pdbs)
2 | [Bb]in/
3 | [Oo]bj/
4 |
5 | # mstest test results
6 | TestResults
7 |
8 | ## Ignore Visual Studio temporary files, build results, and
9 | ## files generated by popular Visual Studio add-ons.
10 |
11 | # User-specific files
12 | *.suo
13 | *.user
14 | *.sln.docstates
15 |
16 | # Build results
17 | [Dd]ebug/
18 | [Rr]elease/
19 | x64/
20 | *_i.c
21 | *_p.c
22 | *.ilk
23 | *.meta
24 | *.obj
25 | *.pch
26 | *.pdb
27 | *.pgc
28 | *.pgd
29 | *.rsp
30 | *.sbr
31 | *.tlb
32 | *.tli
33 | *.tlh
34 | *.tmp
35 | *.log
36 | *.vspscc
37 | *.vssscc
38 | .builds
39 |
40 | # Visual C++ cache files
41 | ipch/
42 | *.aps
43 | *.ncb
44 | *.opensdf
45 | *.sdf
46 |
47 | # Visual Studio profiler
48 | *.psess
49 | *.vsp
50 | *.vspx
51 |
52 | # Guidance Automation Toolkit
53 | *.gpState
54 |
55 | # ReSharper is a .NET coding add-in
56 | _ReSharper*
57 |
58 | # NCrunch
59 | *.ncrunch*
60 | .*crunch*.local.xml
61 |
62 | # Installshield output folder
63 | [Ee]xpress
64 |
65 | # DocProject is a documentation generator add-in
66 | DocProject/buildhelp/
67 | DocProject/Help/*.HxT
68 | DocProject/Help/*.HxC
69 | DocProject/Help/*.hhc
70 | DocProject/Help/*.hhk
71 | DocProject/Help/*.hhp
72 | DocProject/Help/Html2
73 | DocProject/Help/html
74 |
75 | # Click-Once directory
76 | publish
77 |
78 | # Publish Web Output
79 | *.Publish.xml
80 |
81 | # NuGet Packages Directory
82 | packages
83 |
84 | # Windows Azure Build Output
85 | csx
86 | *.build.csdef
87 |
88 | # Windows Store app package directory
89 | AppPackages/
90 |
91 | # Others
92 | [Bb]in
93 | [Oo]bj
94 | sql
95 | TestResults
96 | [Tt]est[Rr]esult*
97 | *.Cache
98 | ClientBin
99 | [Ss]tyle[Cc]op.*
100 | ~$*
101 | *.dbmdl
102 | Generated_Code #added for RIA/Silverlight projects
103 |
104 | # Backup & report files from converting an old project file to a newer
105 | # Visual Studio version. Backup files are not needed, because we have git ;-)
106 | _UpgradeReport_Files/
107 | Backup*/
108 | UpgradeLog*.XML
109 |
--------------------------------------------------------------------------------
/ItemIDs.txt:
--------------------------------------------------------------------------------
1 | - Material sometimes denotes a " of *" on items -
2 | Material
3 | 00 None
4 | 01 Iron
5 | 02 Wood
6 | 03 None
7 | 04 None
8 | 05 Obsidian
9 | 06 None
10 | 07 Bone
11 | 08 None
12 | 09 None
13 | 0A Copper
14 | 0B Gold
15 | 0C Silver
16 | 0D Emerald
17 | 0E Sapphire
18 | 0F Ruby
19 | 10 Diamond
20 | 11 Sandstone
21 | 12 Saurian
22 | 13 Parrot
23 | 14 Mammoth
24 | 15 Plant
25 | 16 Ice
26 | 17 Licht
27 | 18 Glass
28 | 19 Silk
29 | 1A Linen
30 | 1B Cotton
31 |
32 | Item Flags
33 | 01 Adapted
34 |
35 | Unknown [00]
36 | Unknown
37 |
38 | Consumables [01]
39 | Modifiers
40 | 00 None
41 | 00 Cookie
42 | 01 Life Potion
43 | 02 Cactus Potion
44 | 03 Mana Potion
45 | 04 Ginseng Soup
46 | 05 Snowberry Mash
47 | 06 Mushroom Spit
48 | 07 Bomb
49 | 08 Pineapple Slice
50 | 09 Pumpkin Muffin
51 |
52 | Recipes [02]
53 | Modifiers
54 | 00 None
55 | Unknown
56 |
57 | Weapons [03]
58 | Modifiers
59 | 00 None
60 | 01 Plain
61 | 02 Battered
62 | 03 Artless
63 | 04 Unwieldy
64 | 05 Used
65 | 06 Dusty
66 | 07 Scratched
67 | 08 Worn
68 | 09 Common
69 | 0A Shabby
70 | 00 Sword
71 | 01 Axe
72 | 02 Mace
73 | 03 Dagger
74 | 04 Fist
75 | 05 Longsword
76 | 06 Bow
77 | 07 Crossbow
78 | 08 Boomarang
79 | 09 Arrow
80 | 0A Staff
81 | 0B Wand
82 | 0C Bracelet
83 | 0D Shield
84 | 0E Arrows
85 | 0F Greatsword
86 | 10 Greataxe
87 | 11 Greatmace
88 | 12 (Rake)
89 | 13 (Pickaxe)
90 | 14 Torch
91 |
92 | Chest Armor [04]
93 | Modifiers
94 | 00 None
95 | 01 Polished
96 | 02 Extraordinary
97 | 03 Exquisite
98 | 04 Superb
99 | 05 Unique
100 | 06 Handsome
101 | 07 Grand
102 | 08 Magic
103 | 09 Decorated
104 | 0A Exceptional
105 | 00 Chest
106 |
107 | Gloves [05]
108 | Modifiers
109 | 00 None
110 | 01 Polished
111 | 02 Extraordinary
112 | 03 Exquisite
113 | 04 Superb
114 | 05 Unique
115 | 06 Handsome
116 | 07 Grand
117 | 08 Magic
118 | 09 Decorated
119 | 0A Exceptional
120 | 00 Gloves
121 |
122 | Boots [06]
123 | Modifiers
124 | 00 None
125 | 01 Polished
126 | 02 Extraordinary
127 | 03 Exquisite
128 | 04 Superb
129 | 05 Unique
130 | 06 Handsome
131 | 07 Grand
132 | 08 Magic
133 | 09 Decorated
134 | 0A Exceptional
135 | 00 Boots
136 |
137 | Shoulder Armors [07]
138 | Modifiers
139 | 00 None
140 | 01 Polished
141 | 02 Extraordinary
142 | 03 Exquisite
143 | 04 Superb
144 | 05 Unique
145 | 06 Handsome
146 | 07 Grand
147 | 08 Magic
148 | 09 Decorated
149 | 0A Exceptional
150 | Materials
151 | 19 Mage
152 | 1A Ranger
153 | 1B Rogue
154 | 00 Shoulder Armor
155 |
156 | Amulets [08]
157 | Modifiers
158 | 00 None
159 | 01 Polished
160 | 02 Extraordinary
161 | 03 Exquisite
162 | 04 Superb
163 | 05 Unique
164 | 06 Handsome
165 | 07 Grand
166 | 08 Magic
167 | 09 Decorated
168 | 0A Exceptional
169 | 00 Amulet
170 |
171 | Rings [09]
172 | Modifiers
173 | 00 None
174 | 01 Polished
175 | 02 Extraordinary
176 | 03 Exquisite
177 | 04 Superb
178 | 05 Unique
179 | 06 Handsome
180 | 07 Grand
181 | 08 Magic
182 | 09 Decorated
183 | 0A Exceptional
184 | 00 Ring
185 |
186 | Blocks [0A]
187 | Modifiers
188 | 00 None
189 | 01 Polished
190 | 02 Extraordinary
191 | 03 Exquisite
192 | 04 Superb
193 | 05 Unique
194 | 06 Handsome
195 | 07 Grand
196 | 08 Magic
197 | 09 Decorated
198 | 0A Exceptional
199 | 00 Block
200 |
201 | Items [0B]
202 | Modifiers
203 | 00 None
204 | 01 Polished
205 | 02 Extraordinary
206 | 03 Exquisite
207 | 04 Superb
208 | 05 Unique
209 | 06 Handsome
210 | 07 Grand
211 | 08 Magic
212 | 09 Decorated
213 | 0A Exceptional
214 | 00 Nugget
215 | 01 Log
216 | 02 Feather
217 | 03 Horn
218 | 04 Claw
219 | 05 Fiber
220 | 06 Cobweb
221 | 07 Hair
222 | 08 Crystal
223 | 09 Yarn
224 | 0A Cube
225 | 0B Capsule
226 | 0C Flask
227 | 0D Orb
228 | 0E Spirit
229 | 0F Mushroom
230 | 10 Pumpkin
231 | 11 Pineapple
232 | 12 Radish Slice
233 | 13 Shimmer Mushroom
234 | 14 Ginseg Root
235 | 15 Onion Slice
236 | 16 Heartflower
237 | 17 Prickly Pear
238 | 18 Iceflower
239 | 19 Soulflower
240 | 1A Water Flask
241 | 1B Snowberry
242 |
243 | Coins [0C]
244 | Modifiers
245 | 00 None
246 | 01 Polished
247 | 02 Extraordinary
248 | 03 Exquisite
249 | 04 Superb
250 | 05 Unique
251 | 06 Handsome
252 | 07 Grand
253 | 08 Magic
254 | 09 Decorated
255 | 0A Exceptional
256 | 00 Coin
257 |
258 | Platinum Coin [0D]
259 | Modifiers
260 | 00 None
261 | 01 Polished
262 | 02 Extraordinary
263 | 03 Exquisite
264 | 04 Superb
265 | 05 Unique
266 | 06 Handsome
267 | 07 Grand
268 | 08 Magic
269 | 09 Decorated
270 | 0A Exceptional
271 | 00 Platinum Coin
272 |
273 | Leftovers [0E]
274 | Modifiers
275 | 00 None
276 | 00 Leftovers
277 |
278 | Beak [0F]
279 | Modifiers
280 | 00 None
281 | 01 Polished
282 | 02 Extraordinary
283 | 03 Exquisite
284 | 04 Superb
285 | 05 Unique
286 | 06 Handsome
287 | 07 Grand
288 | 08 Magic
289 | 09 Decorated
290 | 0A Exceptional
291 | 00 Beak
292 |
293 | Painting [10]
294 | Modifiers
295 | 00 None
296 | 01 Polished
297 | 02 Extraordinary
298 | 03 Exquisite
299 | 04 Superb
300 | 05 Unique
301 | 06 Handsome
302 | 07 Grand
303 | 08 Magic
304 | 09 Decorated
305 | 0A Exceptional
306 | 00 Painting
307 |
308 | Vase [11]
309 | Modifiers
310 | 00 None
311 | 01 Polished
312 | 02 Extraordinary
313 | 03 Exquisite
314 | 04 Superb
315 | 05 Unique
316 | 06 Handsome
317 | 07 Grand
318 | 08 Magic
319 | 09 Decorated
320 | 0A Exceptional
321 | 00 Vase
322 |
323 | Candle [12]
324 | Modifiers
325 | 00 None
326 | 01 Fancy
327 | 02 3 fancy 5 me
328 | 00 Candle
329 | 01 Haunted Candle
330 |
331 | Pets [13]
332 | Look elsewhere
333 |
334 | Pet Food [14]
335 | Modifiers
336 | 00 None
337 | 01 Polished
338 | 02 Extraordinary
339 | 03 Exquisite
340 | 04 Superb
341 | 05 Unique
342 | 06 Handsome
343 | 07 Grand
344 | 08 Magic
345 | 09 Decorated
346 | 0A Exceptional
347 | [ Not gonna bother mentioning all the non-existant IDs ]
348 | 13 Bubble gum
349 | 17 Chocolate cupcake
350 | 19 Cinnamon role (sic)
351 | 1A Waffle
352 | 1B Croissant
353 | 1E Candy
354 | 21 Pumpkin mash
355 | 22 Cotton candy
356 | 23 Carrot
357 | 24 Blackberry marmalade
358 | 25 Green jelly
359 | 26 Pink Jelly
360 | 27 Yellow Jelly
361 | 28 Blue jelly
362 | 32 Banana split
363 | 35 Popcorn
364 | 37 Licorice candy
365 | 38 Cereal bar
366 | 39 Salted caramel
367 | 3A Ginger tartlet
368 | 3B Mango juice
369 | 3C Fruit basket
370 | 3D Melon ice cream
371 | 3E Bloodorange juice
372 | 3F Milk chocolate bar
373 | 40 Mint chocolate bar
374 | 41 White chocolate bar
375 | 42 Caramel chocolate bar
376 | 43 Chocolate cookie
377 | 4A Sugar candy
378 | 4B Apple ring
379 | 56 Water ice
380 | 57 Chocolate donut
381 | 58 Pancakes
382 | 5A Strawberry cake
383 | 5B Chocolate cake
384 | 5C Lollipop
385 | 5D Softice
386 | 62 Candied apple
387 | 63 Date cookie
388 | 66 Bread
389 | 67 Curry
390 | 68 Lolly
391 | 69 Lemon tart
392 | 6A strawberry cocktail
393 |
394 | [ I have no clue what's wrong here ]
395 |
396 | Quest Items [15]
397 | Modifiers
398 | 00 Eric's
399 | 01 Arweya's
400 | 02 Derek's
401 | 03 Sarah's
402 | 04 Grazic's
403 | 05 Kurra's
404 | 06 Krono's
405 | 07 Chorux's
406 | 08 Zirya's
407 | 09 Torlox's
408 | 0A Mumpie's
409 | 0B Uzku's
410 | 0C Uzka's
411 | 0D Qaurik's
412 | 0E Quaria's
413 | 0F Chulu's
414 | 10 Xula's
415 | 00 Amulet (Gold)
416 | 01 Amulet (Sapphire)
417 | 02 Jewel Case
418 | 03 Key
419 | 04 Medicine
420 | 05 Antivenom
421 | 06 Band Aid
422 | 07 Crutch
423 | 08 Bandage
424 | 09 Salve
425 |
426 | Unused [16]
427 | 00 Unused
428 |
429 | Transporation [17]
430 | Modifiers
431 | 00 None
432 | 01 Polished
433 | 02 Extraordinary
434 | 03 Exquisite
435 | 04 Superb
436 | 05 Unique
437 | 06 Handsome
438 | 07 Grand
439 | 08 Magic
440 | 09 Decorated
441 | 0A Exceptional
442 | 00 Hang Glider
443 | 01 Boat
444 |
445 | Lamps [18]
446 | Modifiers
447 | 00 None
448 | 01 Polished
449 | 02 Extraordinary
450 | 03 Exquisite
451 | 04 Superb
452 | 05 Unique
453 | 06 Handsome
454 | 07 Grand
455 | 08 Magic
456 | 09 Decorated
457 | 0A Exceptional
458 | 00 Lamp
459 |
460 | Mana Cube [19]
461 | Modifiers
462 | 00 None
463 | 01 Battle-tested
464 | 02 Extraordinary
465 | 03 Exquisite
466 | 04 Superb
467 | 05 Unique
468 | 06 Handsome
469 | 07 Grand
470 | 08 Magic
471 | 09 Decorated
472 | 0A Exceptional
473 | 00 Mana Cube
474 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2013 Zachary Reedy
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Project/Icons/IconAmulet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DatZach/CharacterEditor/974b2b9e9bd6756eb68b2a8ba349eac97ff67354/Project/Icons/IconAmulet.png
--------------------------------------------------------------------------------
/Project/Icons/IconBeak.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DatZach/CharacterEditor/974b2b9e9bd6756eb68b2a8ba349eac97ff67354/Project/Icons/IconBeak.png
--------------------------------------------------------------------------------
/Project/Icons/IconBlock.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DatZach/CharacterEditor/974b2b9e9bd6756eb68b2a8ba349eac97ff67354/Project/Icons/IconBlock.png
--------------------------------------------------------------------------------
/Project/Icons/IconBoots.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DatZach/CharacterEditor/974b2b9e9bd6756eb68b2a8ba349eac97ff67354/Project/Icons/IconBoots.png
--------------------------------------------------------------------------------
/Project/Icons/IconCandle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DatZach/CharacterEditor/974b2b9e9bd6756eb68b2a8ba349eac97ff67354/Project/Icons/IconCandle.png
--------------------------------------------------------------------------------
/Project/Icons/IconChestArmor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DatZach/CharacterEditor/974b2b9e9bd6756eb68b2a8ba349eac97ff67354/Project/Icons/IconChestArmor.png
--------------------------------------------------------------------------------
/Project/Icons/IconCoin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DatZach/CharacterEditor/974b2b9e9bd6756eb68b2a8ba349eac97ff67354/Project/Icons/IconCoin.png
--------------------------------------------------------------------------------
/Project/Icons/IconConsumable.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DatZach/CharacterEditor/974b2b9e9bd6756eb68b2a8ba349eac97ff67354/Project/Icons/IconConsumable.png
--------------------------------------------------------------------------------
/Project/Icons/IconGloves.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DatZach/CharacterEditor/974b2b9e9bd6756eb68b2a8ba349eac97ff67354/Project/Icons/IconGloves.png
--------------------------------------------------------------------------------
/Project/Icons/IconItems.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DatZach/CharacterEditor/974b2b9e9bd6756eb68b2a8ba349eac97ff67354/Project/Icons/IconItems.png
--------------------------------------------------------------------------------
/Project/Icons/IconLamp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DatZach/CharacterEditor/974b2b9e9bd6756eb68b2a8ba349eac97ff67354/Project/Icons/IconLamp.png
--------------------------------------------------------------------------------
/Project/Icons/IconLeftovers.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DatZach/CharacterEditor/974b2b9e9bd6756eb68b2a8ba349eac97ff67354/Project/Icons/IconLeftovers.png
--------------------------------------------------------------------------------
/Project/Icons/IconManaCube.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DatZach/CharacterEditor/974b2b9e9bd6756eb68b2a8ba349eac97ff67354/Project/Icons/IconManaCube.png
--------------------------------------------------------------------------------
/Project/Icons/IconPainting.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DatZach/CharacterEditor/974b2b9e9bd6756eb68b2a8ba349eac97ff67354/Project/Icons/IconPainting.png
--------------------------------------------------------------------------------
/Project/Icons/IconPet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DatZach/CharacterEditor/974b2b9e9bd6756eb68b2a8ba349eac97ff67354/Project/Icons/IconPet.png
--------------------------------------------------------------------------------
/Project/Icons/IconPetFood.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DatZach/CharacterEditor/974b2b9e9bd6756eb68b2a8ba349eac97ff67354/Project/Icons/IconPetFood.png
--------------------------------------------------------------------------------
/Project/Icons/IconPlatinumCoin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DatZach/CharacterEditor/974b2b9e9bd6756eb68b2a8ba349eac97ff67354/Project/Icons/IconPlatinumCoin.png
--------------------------------------------------------------------------------
/Project/Icons/IconQuestItem.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DatZach/CharacterEditor/974b2b9e9bd6756eb68b2a8ba349eac97ff67354/Project/Icons/IconQuestItem.png
--------------------------------------------------------------------------------
/Project/Icons/IconRecipe.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DatZach/CharacterEditor/974b2b9e9bd6756eb68b2a8ba349eac97ff67354/Project/Icons/IconRecipe.png
--------------------------------------------------------------------------------
/Project/Icons/IconRing.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DatZach/CharacterEditor/974b2b9e9bd6756eb68b2a8ba349eac97ff67354/Project/Icons/IconRing.png
--------------------------------------------------------------------------------
/Project/Icons/IconShoulderArmor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DatZach/CharacterEditor/974b2b9e9bd6756eb68b2a8ba349eac97ff67354/Project/Icons/IconShoulderArmor.png
--------------------------------------------------------------------------------
/Project/Icons/IconTransportation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DatZach/CharacterEditor/974b2b9e9bd6756eb68b2a8ba349eac97ff67354/Project/Icons/IconTransportation.png
--------------------------------------------------------------------------------
/Project/Icons/IconVase.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DatZach/CharacterEditor/974b2b9e9bd6756eb68b2a8ba349eac97ff67354/Project/Icons/IconVase.png
--------------------------------------------------------------------------------
/Project/Icons/IconWeapon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DatZach/CharacterEditor/974b2b9e9bd6756eb68b2a8ba349eac97ff67354/Project/Icons/IconWeapon.png
--------------------------------------------------------------------------------
/Project/Icons/ItemIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DatZach/CharacterEditor/974b2b9e9bd6756eb68b2a8ba349eac97ff67354/Project/Icons/ItemIcon.png
--------------------------------------------------------------------------------
/Project/icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DatZach/CharacterEditor/974b2b9e9bd6756eb68b2a8ba349eac97ff67354/Project/icon.ico
--------------------------------------------------------------------------------
/Project/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DatZach/CharacterEditor/974b2b9e9bd6756eb68b2a8ba349eac97ff67354/Project/icon.png
--------------------------------------------------------------------------------
/Project/stats.ntl3fty.txt:
--------------------------------------------------------------------------------
1 | public double Armor
2 | {
3 | get
4 | {
5 | if (!(Type == ItemType.Armor || Type == ItemType.Shoulder || Type == ItemType.Hand || Type == ItemType.Feet))
6 | return 0;
7 |
8 | double typeBonus = Type == ItemType.Armor ? 1.0 : 0.5;
9 |
10 | double materialBonus = 0;
11 | switch (Material)
12 | {
13 | case 23:
14 | case 25:
15 | materialBonus = 0.075;
16 | break;
17 | case 19:
18 | case 26:
19 | case 27:
20 | materialBonus = 0.85; // might need to expand the precision here
21 | break;
22 | case 18:
23 | materialBonus = 0.80; // might need to expand the precision here
24 | break;
25 | }
26 |
27 | double effect = CalculateLevelEffectValue(Level + UpgradeList.Used / 10.0, Rarity);
28 | return effect * typeBonus * materialBonus;
29 | }
30 | }
31 |
32 | public double Critical
33 | {
34 | get
35 | {
36 | if (!(Type == ItemType.Amulet || Type == ItemType.Ring || Type == ItemType.Weapon ||
37 | Type == ItemType.Armor || Type == ItemType.Shoulder || Type == ItemType.Hand ||
38 | Type == ItemType.Feet))
39 | {
40 | return 0;
41 | }
42 |
43 | double typeBonus = 0.05;
44 | if (Type == ItemType.Weapon && (Subtype == 15 || Subtype == 16 || Subtype == 17 ||
45 | Subtype == 5 || Subtype == 10 || Subtype == 11 ||
46 | Subtype == 18 || Subtype == 8 || Subtype == 6 || Subtype == 7)
47 | || Type == ItemType.Armor)
48 | {
49 | typeBonus = 0.1;
50 | }
51 |
52 | double modifierBonus = 1.0 - ((Modifier % 21) / 20.0);
53 | if (Material == 11)
54 | {
55 | modifierBonus += 1.0;
56 | }
57 |
58 | double effect = CalculateLevelEffectPercent(Level, Rarity);
59 | double result = effect * typeBonus * modifierBonus;
60 |
61 | return Math.Abs(result) < 0.001 ? 0 : result;
62 | }
63 | }
64 |
65 | public double Life
66 | {
67 | get
68 | {
69 | if (!(Type == ItemType.Weapon || Type == ItemType.Armor ||
70 | Type == ItemType.Shoulder || Type == ItemType.Hand || Type == ItemType.Feet))
71 | {
72 | return 0;
73 | }
74 |
75 | double typeBonus = Type == ItemType.Armor ? 1.0 : 0.5;
76 | double modifierBonus = (1.0 - ((Modifier % 21) / 20.0)) + 1.0;
77 |
78 | switch (Material)
79 | {
80 | case 1:
81 | modifierBonus += 1.0;
82 | break;
83 | case 26:
84 | modifierBonus += 0.5;
85 | break;
86 | case 27:
87 | modifierBonus += 0.75;
88 | break;
89 | }
90 |
91 | double effect = CalculateLevelEffectValue(Level + UpgradeList.Used / 10.0, Rarity);
92 | return effect * 5.0 * typeBonus * modifierBonus;
93 | }
94 | }
95 |
96 | public double Regeneration
97 | {
98 | get
99 | {
100 | if (!(Type == ItemType.Weapon || Type == ItemType.Armor ||
101 | Type == ItemType.Shoulder || Type == ItemType.Hand || Type == ItemType.Feet))
102 | {
103 | return 0;
104 | }
105 |
106 | double typeBonus = Type == ItemType.Armor ? 0.2 : 0.1;
107 | double modifierBonus = (Modifier % 21) / 20.0;
108 |
109 | switch (Material)
110 | {
111 | case 26:
112 | modifierBonus += 0.5;
113 | break;
114 | case 27:
115 | modifierBonus += 1.0;
116 | break;
117 | }
118 |
119 | double effect = CalculateLevelEffectValue(Level + UpgradeList.Used / 10.0, Rarity);
120 | return effect * typeBonus * modifierBonus;
121 | }
122 | }
123 |
124 | public double Resistance
125 | {
126 | get
127 | {
128 | if (!(Type == ItemType.Armor || Type == ItemType.Shoulder || Type == ItemType.Hand || Type == ItemType.Feet))
129 | return 0;
130 |
131 | double typeBonus = Type == ItemType.Armor ? 1.0 : 0.5;
132 |
133 | double materialBonus = 0;
134 | switch (Material)
135 | {
136 | case 1:
137 | case 19:
138 | materialBonus = 0.85;
139 | break;
140 | case 26:
141 | case 27:
142 | materialBonus = 0.75;
143 | break;
144 | }
145 |
146 | double effect = CalculateLevelEffectValue(Level + UpgradeList.Used / 10.0, Rarity);
147 | return effect * typeBonus * materialBonus;
148 | }
149 | }
150 |
151 | public double Tempo
152 | {
153 | get
154 | {
155 | if (!(Type == ItemType.Amulet || Type == ItemType.Ring || Type == ItemType.Weapon ||
156 | Type == ItemType.Armor || Type == ItemType.Shoulder || Type == ItemType.Hand ||
157 | Type == ItemType.Feet))
158 | {
159 | return 0;
160 | }
161 |
162 | double typeBonus = 0.1;
163 | if (Type == ItemType.Weapon && (Subtype == 15 || Subtype == 16 || Subtype == 17 ||
164 | Subtype == 5 || Subtype == 10 || Subtype == 11 ||
165 | Subtype == 18 || Subtype == 8 || Subtype == 6 || Subtype == 7)
166 | || Type == ItemType.Armor)
167 | {
168 | typeBonus = 0.2;
169 | }
170 |
171 | double modifierBonus = (Modifier % 21) / 20.0;
172 | if (Material == 12)
173 | {
174 | modifierBonus += 1.0;
175 | }
176 |
177 | double effect = CalculateLevelEffectPercent(Level, Rarity);
178 | double result = effect * typeBonus * modifierBonus;
179 |
180 | return Math.Abs(result) < 0.001 ? 0 : result;
181 |
182 | }
183 | }
184 |
185 | public double Damage
186 | {
187 | get
188 | {
189 | if (Type != ItemType.Weapon)
190 | return 0;
191 |
192 | double damageBonus = 4.0;
193 | switch (Subtype)
194 | {
195 | case 3:
196 | case 4:
197 | damageBonus = 2.0;
198 | break;
199 | case 5:
200 | damageBonus = 4.0;
201 | break;
202 | case 13:
203 | damageBonus = 2.0;
204 | break;
205 | case 15:
206 | case 16:
207 | case 17:
208 | case 10:
209 | case 11:
210 | case 18:
211 | case 8:
212 | case 6:
213 | case 7:
214 | damageBonus = 8.0;
215 | break;
216 | }
217 |
218 | double effect = CalculateLevelEffectValue(Level + UpgradeList.Used / 10.0, Rarity);
219 | return effect * damageBonus;
220 | }
221 | }
222 |
223 | private static double CalculateLevelEffectValue(double level, int rarity)
224 | {
225 | double a = 3.0 * (1.0 - (1.0 / (1.0 + ((level - 1.0) / 20.0))));
226 | double b = rarity / 4.0;
227 | double result = Math.Pow(2, a) * Math.Pow(2, b);
228 |
229 | return result;
230 | }
231 |
232 | private static double CalculateLevelEffectPercent(double level, int rarity)
233 | {
234 | double a = 3.0 * (1.0 - (1.0 / (1.0 + ((level - 1.0) / 20.0))));
235 | double b = rarity / 4.0;
236 | double c = 3.0;
237 | double result = Math.Pow(2, a) * Math.Pow(2, b) / Math.Pow(2, c);
238 |
239 | return result;
240 | }
--------------------------------------------------------------------------------
/Project/x2048.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DatZach/CharacterEditor/974b2b9e9bd6756eb68b2a8ba349eac97ff67354/Project/x2048.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | CharacterEditor
2 | ===============
3 |
4 | Cube World Character Editor
--------------------------------------------------------------------------------
/References/SQLite.Interop.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DatZach/CharacterEditor/974b2b9e9bd6756eb68b2a8ba349eac97ff67354/References/SQLite.Interop.dll
--------------------------------------------------------------------------------
/References/System.Data.SQLite.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DatZach/CharacterEditor/974b2b9e9bd6756eb68b2a8ba349eac97ff67354/References/System.Data.SQLite.dll
--------------------------------------------------------------------------------
/References/System.Data.SQLite.dll.NET40.2.old:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DatZach/CharacterEditor/974b2b9e9bd6756eb68b2a8ba349eac97ff67354/References/System.Data.SQLite.dll.NET40.2.old
--------------------------------------------------------------------------------
/References/System.Data.SQLite.dll.NET40.old:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DatZach/CharacterEditor/974b2b9e9bd6756eb68b2a8ba349eac97ff67354/References/System.Data.SQLite.dll.NET40.old
--------------------------------------------------------------------------------
/References/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/References/zlib.net.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DatZach/CharacterEditor/974b2b9e9bd6756eb68b2a8ba349eac97ff67354/References/zlib.net.dll
--------------------------------------------------------------------------------
/Source/Character/Character.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Drawing;
3 | using System.IO;
4 | using System.Linq;
5 |
6 | namespace CharacterEditor.Character
7 | {
8 | public class Character
9 | {
10 | public const int EquipmentCount = 13;
11 | public const int InventoryCount = 4;
12 | public const int SkillCount = 11;
13 |
14 | public enum ClassType : byte
15 | {
16 | None,
17 | Warrior,
18 | Ranger,
19 | Mage,
20 | Rogue
21 | }
22 |
23 | public int DatabaseIndex { get; private set; }
24 | public int EntityId { get; private set; }
25 | public long PositionX { get; private set; }
26 | public long PositionY { get; private set; }
27 | public long PositionZ { get; private set; }
28 | public float Pitch { get; private set; }
29 | public float Roll { get; private set; }
30 | public float Yaw { get; private set; }
31 |
32 | public float Health;
33 | public int Experience;
34 | public int Level;
35 | public ClassType Class;
36 | public byte Specialization;
37 |
38 | private uint unknown1;
39 | private uint unknown2;
40 |
41 | public List- Equipment;
42 |
43 | public string Name;
44 | public int Race;
45 | public byte Gender;
46 | public int Face;
47 | public int Hair;
48 | public Color HairColor;
49 |
50 | public List Inventories;
51 |
52 | public int Coins;
53 | public int PlatinumCoins;
54 |
55 | public List
- CraftingRecipes;
56 | public List Worlds;
57 | public World LastWorld;
58 |
59 | public int ManaCubes;
60 | public int PetMasterSkillLevel;
61 | public int PetRidingSkillLevel;
62 | public int ClimbingSkillLevel;
63 | public int HangGlidingSkillLevel;
64 | public int SwimmingSkillLevel;
65 | public int SailingSkillLevel;
66 | public int TierOneSkillLevel;
67 | public int TierTwoSkillLevel;
68 | public int TierThreeSkillLevel;
69 | private int unknown4;
70 | private int unknown5;
71 |
72 | public Character(int index)
73 | {
74 | DatabaseIndex = index;
75 |
76 | Equipment = new List
- ();
77 | Inventories = new List();
78 | CraftingRecipes = new List
- ();
79 | Worlds = new List();
80 | }
81 |
82 | public void Load(Database database)
83 | {
84 | byte[] characterData = database.ReadCharacterBlob(DatabaseIndex);
85 |
86 | using (BinaryReader reader = new BinaryReader(new MemoryStream(characterData)))
87 | Read(reader);
88 | }
89 |
90 | public bool Save(Database database)
91 | {
92 | MemoryStream saveDataStream = new MemoryStream();
93 |
94 | using (BinaryWriter writer = new BinaryWriter(saveDataStream))
95 | Write(writer);
96 |
97 | return database.WriteCharacterBlob(DatabaseIndex, saveDataStream.ToArray());
98 | }
99 |
100 | public void Read(BinaryReader reader)
101 | {
102 | EntityId = reader.ReadInt32();
103 | PositionX = reader.ReadInt64();
104 | PositionY = reader.ReadInt64();
105 | PositionZ = reader.ReadInt64();
106 | Pitch = reader.ReadSingle();
107 | Roll = reader.ReadSingle();
108 | Yaw = reader.ReadSingle();
109 |
110 | Health = reader.ReadSingle();
111 | Experience = reader.ReadInt32();
112 | Level = reader.ReadInt32();
113 | Class = (ClassType)reader.ReadByte();
114 | Specialization = reader.ReadByte();
115 | unknown1 = reader.ReadUInt32();
116 | unknown2 = reader.ReadUInt32();
117 |
118 | for (int i = 0; i < EquipmentCount; ++i)
119 | {
120 | Item item = new Item();
121 | item.Read(reader);
122 |
123 | Equipment.Add(item);
124 | }
125 |
126 | Name = reader.ReadLongString();
127 | Race = reader.ReadInt32();
128 | Gender = reader.ReadByte();
129 | reader.Skip(3);
130 | Face = reader.ReadInt32();
131 | Hair = reader.ReadInt32();
132 | HairColor = Utility.FromAbgr(reader.ReadInt32());
133 |
134 | int inventoryCount = reader.ReadInt32();
135 | for (int i = 0; i < inventoryCount; ++i)
136 | {
137 | Inventory inventory = new Inventory();
138 | inventory.Read(reader);
139 |
140 | Inventories.Add(inventory);
141 | }
142 |
143 | Coins = reader.ReadInt32();
144 | PlatinumCoins = reader.ReadInt32();
145 |
146 | int craftingRecipeCount = reader.ReadInt32();
147 | for (int i = 0; i < craftingRecipeCount; ++i)
148 | {
149 | Item item = new Item();
150 | item.Read(reader);
151 |
152 | CraftingRecipes.Add(item);
153 | }
154 |
155 | int worldCount = reader.ReadInt32();
156 | for (int i = 0; i < worldCount; ++i)
157 | {
158 | World world = new World();
159 | world.Read(reader);
160 |
161 | Worlds.Add(world);
162 | }
163 |
164 | int lastWorldSeed = reader.ReadInt32();
165 | string lastWorldName = reader.ReadLongString();
166 |
167 | LastWorld = Worlds.FirstOrDefault(w => w.Seed == lastWorldSeed && w.Name == lastWorldName) ?? new World { Name = lastWorldName, Seed = lastWorldSeed };
168 |
169 | ManaCubes = reader.ReadInt32();
170 | reader.Skip(4);
171 | PetMasterSkillLevel = reader.ReadInt32();
172 | PetRidingSkillLevel = reader.ReadInt32();
173 | ClimbingSkillLevel = reader.ReadInt32();
174 | HangGlidingSkillLevel = reader.ReadInt32();
175 | SwimmingSkillLevel = reader.ReadInt32();
176 | SailingSkillLevel = reader.ReadInt32();
177 | TierOneSkillLevel = reader.ReadInt32();
178 | TierTwoSkillLevel = reader.ReadInt32();
179 | TierThreeSkillLevel = reader.ReadInt32();
180 | unknown4 = reader.ReadInt32();
181 | unknown5 = reader.ReadInt32();
182 | }
183 |
184 | public void Write(BinaryWriter writer)
185 | {
186 | writer.Write(EntityId);
187 | writer.Write(PositionX);
188 | writer.Write(PositionY);
189 | writer.Write(PositionZ);
190 | writer.Write(Pitch);
191 | writer.Write(Roll);
192 | writer.Write(Yaw);
193 |
194 | writer.Write(Health);
195 | writer.Write(Experience);
196 | writer.Write(Level);
197 | writer.Write((byte)Class);
198 | writer.Write(Specialization);
199 | writer.Write(unknown1);
200 | writer.Write(unknown2);
201 |
202 | foreach (Item equipment in Equipment)
203 | equipment.Write(writer);
204 |
205 | writer.WriteLongString(Name);
206 | writer.Write(Race);
207 | writer.Write(Gender);
208 | writer.Skip(3);
209 | writer.Write(Face);
210 | writer.Write(Hair);
211 | writer.Write(Utility.ToAbgr(HairColor));
212 |
213 | writer.Write(InventoryCount);
214 | foreach (Inventory inventory in Inventories)
215 | inventory.Write(writer);
216 |
217 | writer.Write(Coins);
218 | writer.Write(PlatinumCoins);
219 |
220 | writer.Write(CraftingRecipes.Count);
221 | foreach (Item recipe in CraftingRecipes)
222 | recipe.Write(writer);
223 |
224 | writer.Write(Worlds.Count);
225 | foreach (World world in Worlds)
226 | world.Write(writer);
227 |
228 | writer.Write(LastWorld.Seed);
229 | writer.WriteLongString(LastWorld.Name);
230 |
231 | writer.Write(ManaCubes);
232 | writer.Write(SkillCount);
233 | writer.Write(PetMasterSkillLevel);
234 | writer.Write(PetRidingSkillLevel);
235 | writer.Write(ClimbingSkillLevel);
236 | writer.Write(HangGlidingSkillLevel);
237 | writer.Write(SwimmingSkillLevel);
238 | writer.Write(SailingSkillLevel);
239 | writer.Write(TierOneSkillLevel);
240 | writer.Write(TierTwoSkillLevel);
241 | writer.Write(TierThreeSkillLevel);
242 | writer.Write(unknown4);
243 | writer.Write(unknown5);
244 | }
245 | }
246 | }
247 |
--------------------------------------------------------------------------------
/Source/Character/ChineseRemainder.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Data;
3 |
4 | namespace CharacterEditor.Character
5 | {
6 | ///
7 | /// Solve Chinese Remainder Problem
8 | /// Original source: http://www.codeproject.com/Articles/29610/Chinese-Remainder-Problem
9 | ///
10 | class ChineseRemainder
11 | {
12 | ///
13 | /// Get Greatest Common Divisor
14 | ///
15 | public static int Gcd(int a, int b)
16 | {
17 | if (a > b)
18 | {
19 | int t = b;
20 | b = a;
21 | a = t;
22 | }
23 |
24 | int r = b % a;
25 | while (r != 0)
26 | {
27 | b = a;
28 | a = r;
29 | r = b % a;
30 | }
31 |
32 | return a;
33 | }
34 |
35 | ///
36 | /// Get Least Common Multiple
37 | ///
38 | public static int Lcm(int a, int b)
39 | {
40 | int gcd = Gcd(a, b);
41 | return a * b / gcd;
42 | }
43 |
44 | ///
45 | /// Solve ax=by+1
46 | ///
47 | public static void Solve(int a, int b, out int x, out int y)
48 | {
49 | if (b == 1)
50 | {
51 | x = 1;
52 | y = a - 1;
53 | }
54 | else if (a == 1)
55 | {
56 | y = 1;
57 | x = b + 1;
58 | }
59 | else if (b > a)
60 | {
61 | int subx;
62 | Solve(a, b - a, out subx, out y);
63 | x = y + subx;
64 | }
65 | else if (a > b)
66 | {
67 | int suby;
68 | Solve(a - b, b, out x, out suby);
69 | y = x + suby;
70 | }
71 | else
72 | throw new DataException(String.Format("The equation {0}x={1}y+1 has no integer solution.", a, b));
73 | }
74 |
75 | ///
76 | /// Solve ax = by + c
77 | ///
78 | public static void Solve(int a, int b, int c, out int x1, out int y1)
79 | {
80 | /* if
81 | a * x0 = b * y0 + 1
82 | then
83 | x = b * t + c * x0
84 | y = a * t + c * y0
85 | satisfies
86 | a * x = b * y + c
87 | so
88 | x1 = (c * x0) mod b
89 | y1 = (c * y0) mod a
90 | */
91 | int d = Gcd(a, b);
92 | if (d > 1)
93 | {
94 | if (c % d != 0)
95 | throw new DataException(String.Format("The equation {0}x={1}y+{2} has no integer solution.", a, b, c));
96 |
97 | a = a / d;
98 | b = b / d;
99 | c = c / d;
100 | }
101 |
102 | int x0, y0;
103 | Solve(a, b, out x0, out y0);
104 | x1 = (c * x0) % b;
105 | y1 = (c * y0) % a;
106 | }
107 |
108 | ///
109 | /// Solve a * x + r1 = b * y + r2
110 | ///
111 | public static void Solve(int a, int b, int r1, int r2, out int x1, out int y1)
112 | {
113 | if (r2 > r1)
114 | Solve(a, b, r2 - r1, out x1, out y1);
115 | else if (r1 > r2)
116 | Solve(b, a, r1 - r2, out y1, out x1);
117 | else
118 | {
119 | x1 = b;
120 | y1 = a;
121 | }
122 | }
123 |
124 | ///
125 | /// Solve a * x + r1 = b * y + r2 = c * z + r3 = n
126 | /// n0 = n mod t
127 | ///
128 | public static void Solve(int a, int b, int c, int r1,
129 | int r2, int r3, out int n0, out int t)
130 | {
131 | int x1, y1;
132 |
133 | Solve(a, b, r1, r2, out x1, out y1);
134 |
135 | // let r4 = a * x1 + r1 = b * y1 + r2
136 | // to satisfy n = a * x + r1 = b * y + r2
137 | // we can see n = a * b * u + r4
138 |
139 | int r4 = a * x1 + r1;
140 | int x2, y2;
141 |
142 | Solve(a * b, c, r4, r3, out x2, out y2);
143 | n0 = c * y2 + r3;
144 | t = Lcm(Lcm(a, b), c);
145 | //n0 = n % t;
146 | }
147 | }
148 | }
149 |
--------------------------------------------------------------------------------
/Source/Character/Constants.cs:
--------------------------------------------------------------------------------
1 | namespace CharacterEditor.Character
2 | {
3 | public static class Constants
4 | {
5 | public enum ItemType : byte
6 | {
7 | None,
8 | Consumables,
9 | Recipes,
10 | Weapons,
11 | ChestArmor,
12 | Gloves,
13 | Boots,
14 | ShoulderArmor,
15 | Amulets,
16 | Rings,
17 | Blocks,
18 | Items,
19 | Coins,
20 | PlatinumCoins,
21 | Leftovers,
22 | Beak,
23 | Painting,
24 | Vase,
25 | Candle,
26 | Pets,
27 | PetFood,
28 | QuestItems,
29 | Unused,
30 | Transportation,
31 | Lamps,
32 | ManaCubes
33 | }
34 |
35 | public static readonly string[] ItemTypeNames = new[]
36 | {
37 | "None", // None
38 | "Consumables",
39 | "Recipes",
40 | "Weapons",
41 | "Chest Armor",
42 | "Gloves",
43 | "Boots",
44 | "Shoulder Armor",
45 | "Amulets",
46 | "Rings",
47 | "Blocks",
48 | "Items",
49 | "Coins",
50 | "Platinum Coins",
51 | "Leftovers",
52 | "Beak",
53 | "Painting",
54 | "Vase",
55 | "Candle",
56 | "Pets",
57 | "Pet Food",
58 | "Quest Items",
59 | null,
60 | "Transportation",
61 | "Lamps",
62 | "Mana Cubes"
63 | };
64 |
65 | public static readonly string[][] ItemModifiers = new []
66 | {
67 | new [] // Rarity 0
68 | {
69 | "Plain {0}",
70 | "Battered {0}",
71 | "Artless {0}",
72 | "Unwieldy {0}",
73 | "Used {0}",
74 | "Dusty {0}",
75 | "Scratched {0}",
76 | "Worn {0}",
77 | "Common {0}",
78 | "Shabby {0}"
79 | },
80 |
81 | new [] // Rarity 1
82 | {
83 | "Balanced {0}",
84 | "Battle-tested {0}",
85 | "Good {0}",
86 | "Handmade {0}",
87 | "Fair {0}",
88 | "Neat {0}",
89 | "Clean {0}",
90 | "Undamaged {0}",
91 | "Flawless {0}",
92 | "Adjusted {0}"
93 | },
94 |
95 | new [] // Rarity 2
96 | {
97 | "Polished {0}",
98 | "Extraordinary {0}",
99 | "Exquisite {0}",
100 | "Superb {0}",
101 | "Unique {0}",
102 | "Handsome {0}",
103 | "Grand {0}",
104 | "Magic {0}",
105 | "Decorated {0}",
106 | "Exceptional {0}"
107 | },
108 |
109 | new[] // Rarity 3
110 | {
111 | "Polished {0} of {1}",
112 | "Extraordinary {0} of {1}",
113 | "Exquisite {0} of {1}",
114 | "{1}'s Superb {0}",
115 | "Unique {0} of {1}",
116 | "{1}'s Handsome {0}",
117 | "Grand {0} of {1}",
118 | "Magic {0} of {1}",
119 | "Decorated {0} of {1}",
120 | "{1}'s Exceptional {0}"
121 | },
122 |
123 | new [] // Rarity 4
124 | {
125 | "Shining {0} of {1}", // 1
126 | "Magnificent {0} von {1}",
127 | "Sublime {0} of {1}",
128 | "{1}'s Pompous {0}",
129 | "Glorious {0} of {1}",
130 | "{1}'s Splendid {0}",
131 | "Famous {0} of {1}",
132 | "Legendary {0} of {1}",
133 | "Fabulous {0} of {1}",
134 | "{1}'s Brilliant {0}"
135 | }
136 | };
137 |
138 | public static readonly string[] ItemMaterialNames = new[]
139 | {
140 | "None", // Might be a problem?
141 | "Iron",
142 | "Wood",
143 | null,
144 | null,
145 | "Obsidian",
146 | null,
147 | "Bone",
148 | null,
149 | null,
150 | "Copper",
151 | "Gold",
152 | "Silver",
153 | "Emerald",
154 | "Sapphire",
155 | "Ruby",
156 | "Diamond",
157 | "Sandstone",
158 | "Saurian",
159 | "Parrot",
160 | "Mammoth",
161 | "Plant",
162 | "Ice",
163 | "Licht (Light)",
164 | "Glass",
165 | "Silk",
166 | "Linen",
167 | "Cotton",
168 | null,
169 | null,
170 | null,
171 | null,
172 | null,
173 | null,
174 | null,
175 | null,
176 | null,
177 | null,
178 | null,
179 | null,
180 | null,
181 | null,
182 | null,
183 | null,
184 | null,
185 | null,
186 | null,
187 | null,
188 | null,
189 | null,
190 | null,
191 | null,
192 | null,
193 | null,
194 | null,
195 | null,
196 | null,
197 | null,
198 | null,
199 | null,
200 | null,
201 | null,
202 | null,
203 | null,
204 | null,
205 | null,
206 | null,
207 | null,
208 | null,
209 | null,
210 | null,
211 | null,
212 | null,
213 | null,
214 | null,
215 | null,
216 | null,
217 | null,
218 | null,
219 | null,
220 | null,
221 | null,
222 | null,
223 | null,
224 | null,
225 | null,
226 | null,
227 | null,
228 | null,
229 | null,
230 | null,
231 | null,
232 | null,
233 | null,
234 | null,
235 | null,
236 | null,
237 | null,
238 | null,
239 | null,
240 | null,
241 | null,
242 | null,
243 | null,
244 | null,
245 | null,
246 | null,
247 | null,
248 | null,
249 | null,
250 | null,
251 | null,
252 | null,
253 | null,
254 | null,
255 | null,
256 | null,
257 | null,
258 | null,
259 | null,
260 | null,
261 | null,
262 | null,
263 | null,
264 | null,
265 | null,
266 | null,
267 | null,
268 | "Fire",
269 | "Unholy",
270 | "Ice",
271 | "Wind"
272 | };
273 |
274 | // [type][subtype]
275 | public static readonly string[][] ItemSubtypes = new[]
276 | {
277 | new [] // None
278 | {
279 | ""
280 | },
281 |
282 | new [] // Consumable
283 | {
284 | "Cookie",
285 | "Life Potion",
286 | "Cactus Potion",
287 | "Mana Potion",
288 | "Ginseng Soup",
289 | "Snowberry Mash",
290 | "Mushroom Spit",
291 | "Bomb",
292 | "Pineapple Slice",
293 | "Pumpkin Muffin"
294 | },
295 |
296 | new [] // Recipes
297 | {
298 | "Recipe"
299 | },
300 |
301 | new [] // Weapons
302 | {
303 | "Sword",
304 | "Axe",
305 | "Mace",
306 | "Dagger",
307 | "Fist",
308 | "Longsword",
309 | "Bow",
310 | "Crossbow",
311 | "Boomarang",
312 | "Arrow",
313 | "Staff",
314 | "Wand",
315 | "Bracelet",
316 | "Shield",
317 | "Arrows",
318 | "Greatsword",
319 | "Greataxe",
320 | "Greatmace",
321 | "Rake",
322 | "Pickaxe",
323 | "Torch"
324 | },
325 |
326 | new [] // Chest Armor
327 | {
328 | "Chest Armor"
329 | },
330 |
331 | new [] // Gloves
332 | {
333 | "Gloves"
334 | },
335 |
336 | new [] // Boots
337 | {
338 | "Boots"
339 | },
340 |
341 | new [] // Shoulder Armor
342 | {
343 | "Shoulder Armor"
344 | },
345 |
346 | new [] // Amulets
347 | {
348 | "Amulet"
349 | },
350 |
351 | new [] // Rings
352 | {
353 | "Ring"
354 | },
355 |
356 | new [] // Blocks
357 | {
358 | "Block"
359 | },
360 |
361 | new [] // Items
362 | {
363 | "Nugget",
364 | "Log",
365 | "Feather",
366 | "Horn",
367 | "Claw",
368 | "Fiber",
369 | "Cobweb",
370 | "Hair",
371 | "Crystal",
372 | "Yarn",
373 | "Cube",
374 | "Capsule",
375 | "Flask",
376 | "Orb",
377 | "Spirit",
378 | "Mushroom",
379 | "Pumpkin",
380 | "Pineapple",
381 | "Radish Slice",
382 | "Shimmer Mushroom",
383 | "Ginseng Root",
384 | "Onion Slice",
385 | "Heartflower",
386 | "Prickly Pear",
387 | "Iceflower",
388 | "Soulflower",
389 | "Water Flask",
390 | "Snowberry"
391 | },
392 |
393 | new [] // Coins
394 | {
395 | "Coin"
396 | },
397 |
398 | new [] // Platinum Coins
399 | {
400 | "Platinum Coin"
401 | },
402 |
403 | new [] // Leftovers
404 | {
405 | "Leftovers"
406 | },
407 |
408 | new [] // Beak
409 | {
410 | "Beak"
411 | },
412 |
413 | new [] // Painting
414 | {
415 | "Painting"
416 | },
417 |
418 | new [] // Vase
419 | {
420 | "Vase"
421 | },
422 |
423 | new [] // Candle
424 | {
425 | "Candle",
426 | "Haunted Candle"
427 | },
428 |
429 | new [] // Pets
430 | {
431 | "", "", "", "", "", "", "", "",
432 | "", "", "", "", "", "", "", "",
433 | "", "", "",
434 | "Collie",
435 | "Shepherd Dog",
436 | "",
437 | "Alpaca",
438 | "Alpaca (Brown)",
439 | "",
440 | "Turtle",
441 | "Terrier",
442 | "Terrier (Scottish)",
443 | "Wolf",
444 | "",
445 | "Cat",
446 | "Cat (Brown)",
447 | "Cat (White)",
448 | "Pig",
449 | "Sheep",
450 | "Bunny",
451 | "Porcupine",
452 | "Slime (Green)",
453 | "Slime (Pink)",
454 | "Slime (Yellow)",
455 | "Slime (Blue)",
456 | "", "", "", "", "", "", "", "",
457 | "",
458 | "Monkey",
459 | "", "",
460 | "Hornet",
461 | "",
462 | "Crow",
463 | "Chicken",
464 | "Seagull",
465 | "Parrot",
466 | "Bat",
467 | "Fly",
468 | "Midge",
469 | "Mosquito",
470 | "Runner (Plain)",
471 | "Runner (Leaf)",
472 | "Runner (Snow)",
473 | "Runner (Desert)",
474 | "Peacock",
475 | "Frog",
476 | "", "", "", "",
477 | "Devourer",
478 | "Duckbill",
479 | "Crocodile",
480 | "", "", "", "", "", "", "", "", "",
481 | "Imp",
482 | "Spitter",
483 | "Mole",
484 | "Biter",
485 | "Koala",
486 | "Squirrel",
487 | "Raccoon",
488 | "Owl",
489 | "Penguin",
490 | "", "", "", "",
491 | "Horse",
492 | "Camel",
493 | "", "",
494 | "Beetle (Dark)",
495 | "Beetle (Fire)",
496 | "Beetle (Snout)",
497 | "Beetle (Lemon)",
498 | "Crab",
499 | "", "", "", "", "", "", "", "",
500 | "", "", "", "", "", "", "", "",
501 | "", "", "", "", "", "", "", "",
502 | "", "", "", "", "", "", "", "",
503 | "", "", "", "", "", "", "", "",
504 | "", "", "", "",
505 | "Bumblebee"
506 | },
507 |
508 | new [] // Pet Food
509 | {
510 | "", "", "", "", "", "", "", "",
511 | "", "", "", "", "", "", "", "",
512 | "", "", "",
513 | "Bubble Gum",
514 | "", "",
515 | "Vanilla Cupcake",
516 | "Chocolate Cupcake",
517 | "",
518 | "Cinnamon Roll",
519 | "Waffle",
520 | "Croissant",
521 | "",
522 | "",
523 | "Candy",
524 | "",
525 | "",
526 | "Pumpkin Mash",
527 | "Cotton Candy",
528 | "Carrot",
529 | "Blackberry Marmalade",
530 | "Green Jelly",
531 | "Pink Jelly",
532 | "Yellow Jelly",
533 | "Blue Jelly",
534 | "", "", "", "", "", "", "", "", "",
535 | "Banana Split",
536 | "", "",
537 | "Popcorn",
538 | "",
539 | "Licorice Candy",
540 | "Cereal Bar",
541 | "Salted Caramel",
542 | "Ginger Tartlet",
543 | "Mango Juice",
544 | "Fruit Basket",
545 | "Melon Icecream",
546 | "Bloodorange Juice",
547 | "Milk chocolate bar",
548 | "Mint chocolate bar",
549 | "White chocolate bar",
550 | "Caramel chocolate bar",
551 | "Chocolate Cookie",
552 | "", "", "", "", "", "",
553 | "Sugar Candy",
554 | "Apple Ring",
555 | "", "", "", "", "", "", "", "", "", "",
556 | "Water Ice",
557 | "Chocolate Doughnut",
558 | "Pancakes",
559 | "",
560 | "Strawberry Cake",
561 | "Chocolate Cake",
562 | "Lollipop",
563 | "Softice",
564 | "", "", "", "",
565 | "Candied Apple",
566 | "Date Cookie",
567 | "", "",
568 | "Bread",
569 | "Curry",
570 | "Lolly",
571 | "Lemon Tart",
572 | "Strawberry Cocktail",
573 | "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
574 | "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
575 | "", "", "", "",
576 | "Biscuit Role"
577 | },
578 |
579 | new [] // Quest Items
580 | {
581 | "Amulet (Gold)",
582 | "Amulet (Sapphire)",
583 | "Jewel Case",
584 | "Key",
585 | "Medicine",
586 | "Antivenom",
587 | "Band Aid",
588 | "Crutch",
589 | "Bandage",
590 | "Salve"
591 | },
592 |
593 | new [] // Unused
594 | {
595 | ""
596 | },
597 |
598 | new [] // Transportation
599 | {
600 | "Hang Glider",
601 | "Boat"
602 | },
603 |
604 | new [] // Lamps
605 | {
606 | "Lamp"
607 | },
608 |
609 | new [] // Mana Cubes
610 | {
611 | "Mana Cube"
612 | }
613 | };
614 | }
615 | }
616 |
--------------------------------------------------------------------------------
/Source/Character/ICharacterData.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 |
3 | namespace CharacterEditor.Character
4 | {
5 | public interface ICharacterData
6 | {
7 | void Read(BinaryReader reader);
8 | void Write(BinaryWriter writer);
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/Source/Character/Inventory.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.IO;
3 |
4 | namespace CharacterEditor.Character
5 | {
6 | public class Inventory : ICharacterData
7 | {
8 | public const int DefaultItemCount = 50;
9 |
10 | public List Items;
11 |
12 | public Inventory()
13 | {
14 | Items = new List();
15 | }
16 |
17 | public void Read(BinaryReader reader)
18 | {
19 | int inventoryCount = reader.ReadInt32();
20 | for (int i = 0; i < inventoryCount; ++i)
21 | {
22 | Slot slot = new Slot();
23 | slot.Read(reader);
24 |
25 | Items.Add(slot);
26 | }
27 | }
28 |
29 | public void Write(BinaryWriter writer)
30 | {
31 | writer.Write(Items.Count);
32 |
33 | foreach (Slot slot in Items)
34 | slot.Write(writer);
35 | }
36 | }
37 | }
--------------------------------------------------------------------------------
/Source/Character/Item.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 |
6 | namespace CharacterEditor.Character
7 | {
8 | public class Item : ICharacterData
9 | {
10 | public const int AttributeCount = 32;
11 | public const int PrefixDivisor = 10;
12 | public const int ModelDivisor = 11;
13 | public const int EffectDivisor = 21;
14 |
15 | public byte Type;
16 | public byte Subtype;
17 | //public short ActualModifier; // TODO Hack, should build modifier from its fragments
18 | public byte RecipeType;
19 | public byte Rarity;
20 | public byte Material;
21 | public ItemFlags Flags;
22 | public short Level;
23 |
24 | // Modifier subparts
25 | public int PrefixId;
26 | public int ModelId;
27 | public int EffectId;
28 |
29 | public List Attributes;
30 |
31 | public double Armor
32 | {
33 | get
34 | {
35 | HashSet supportedTypes = new HashSet
36 | {
37 | Constants.ItemType.ChestArmor,
38 | Constants.ItemType.ShoulderArmor,
39 | Constants.ItemType.Gloves,
40 | Constants.ItemType.Boots
41 | };
42 |
43 | Constants.ItemType itemType = (Constants.ItemType)Type;
44 |
45 | if (!supportedTypes.Contains(itemType))
46 | return 0.0;
47 |
48 | double typeBonus = itemType == Constants.ItemType.ChestArmor ? 1.0 : 0.5;
49 |
50 | double materialBonus = 0;
51 | switch (Material)
52 | {
53 | case 23:
54 | case 25:
55 | materialBonus = 0.075;
56 | break;
57 |
58 | case 19:
59 | case 26:
60 | case 27:
61 | materialBonus = 0.85; // might need to expand the precision here
62 | break;
63 |
64 | case 18:
65 | materialBonus = 0.80; // might need to expand the precision here
66 | break;
67 | }
68 |
69 | double effect = CalculateLevelEffectValue(Level + Attributes.Count / 10.0, Rarity);
70 | return effect * typeBonus * materialBonus;
71 | }
72 | }
73 |
74 | public double Critical
75 | {
76 | get
77 | {
78 | HashSet supportedTypes = new HashSet
79 | {
80 | Constants.ItemType.Amulets,
81 | Constants.ItemType.Rings,
82 | Constants.ItemType.Weapons,
83 | Constants.ItemType.ChestArmor,
84 | Constants.ItemType.ShoulderArmor,
85 | Constants.ItemType.Gloves,
86 | Constants.ItemType.Boots
87 | };
88 |
89 | Constants.ItemType itemType = (Constants.ItemType)Type;
90 |
91 | if (!supportedTypes.Contains(itemType))
92 | return 0.0;
93 |
94 | double typeBonus = 0.05;
95 | if (itemType == Constants.ItemType.Weapons && (Subtype == 15 || Subtype == 16 || Subtype == 17 ||
96 | Subtype == 5 || Subtype == 10 || Subtype == 11 ||
97 | Subtype == 18 || Subtype == 8 || Subtype == 6 || Subtype == 7) ||
98 | itemType == Constants.ItemType.ChestArmor)
99 | typeBonus = 0.1;
100 |
101 | double modifierBonus = 1.0 - ((Modifier % 21) / 20.0);
102 | if (Material == 11)
103 | modifierBonus += 1.0;
104 |
105 | double effect = CalculateLevelEffectPercent(Level, Rarity);
106 | double result = effect * typeBonus * modifierBonus;
107 |
108 | return Math.Abs(result) < 0.001 ? 0 : result;
109 | }
110 | }
111 |
112 | public double Life
113 | {
114 | get
115 | {
116 | HashSet supportedTypes = new HashSet
117 | {
118 | Constants.ItemType.Weapons,
119 | Constants.ItemType.ChestArmor,
120 | Constants.ItemType.ShoulderArmor,
121 | Constants.ItemType.Gloves,
122 | Constants.ItemType.Boots
123 | };
124 |
125 | Constants.ItemType itemType = (Constants.ItemType)Type;
126 |
127 | if (!supportedTypes.Contains(itemType))
128 | return 0.0;
129 |
130 | double typeBonus = itemType == Constants.ItemType.ChestArmor ? 1.0 : 0.5;
131 | double modifierBonus = (1.0 - ((Modifier % 21) / 20.0)) + 1.0;
132 |
133 | switch (Material)
134 | {
135 | case 1:
136 | modifierBonus += 1.0;
137 | break;
138 |
139 | case 26:
140 | modifierBonus += 0.5;
141 | break;
142 |
143 | case 27:
144 | modifierBonus += 0.75;
145 | break;
146 | }
147 |
148 | double effect = CalculateLevelEffectValue(Level + Attributes.Count / 10.0, Rarity);
149 | return effect * 5.0 * typeBonus * modifierBonus;
150 | }
151 | }
152 |
153 | public double Regeneration
154 | {
155 | get
156 | {
157 | HashSet supportedTypes = new HashSet
158 | {
159 | Constants.ItemType.Weapons,
160 | Constants.ItemType.ChestArmor,
161 | Constants.ItemType.ShoulderArmor,
162 | Constants.ItemType.Gloves,
163 | Constants.ItemType.Boots
164 | };
165 |
166 | Constants.ItemType itemType = (Constants.ItemType)Type;
167 |
168 | if (!supportedTypes.Contains(itemType))
169 | return 0.0;
170 |
171 | double typeBonus = itemType == Constants.ItemType.ChestArmor ? 0.2 : 0.1;
172 | double modifierBonus = (Modifier % 21) / 20.0;
173 |
174 | switch (Material)
175 | {
176 | case 26:
177 | modifierBonus += 0.5;
178 | break;
179 |
180 | case 27:
181 | modifierBonus += 1.0;
182 | break;
183 | }
184 |
185 | double effect = CalculateLevelEffectValue(Level + Attributes.Count / 10.0, Rarity);
186 | return effect * typeBonus * modifierBonus;
187 | }
188 | }
189 |
190 | public double Resistance
191 | {
192 | get
193 | {
194 | HashSet supportedTypes = new HashSet
195 | {
196 | Constants.ItemType.ChestArmor,
197 | Constants.ItemType.ShoulderArmor,
198 | Constants.ItemType.Gloves,
199 | Constants.ItemType.Boots
200 | };
201 |
202 | Constants.ItemType itemType = (Constants.ItemType)Type;
203 |
204 | if (!supportedTypes.Contains(itemType))
205 | return 0.0;
206 |
207 | double typeBonus = itemType == Constants.ItemType.ChestArmor ? 1.0 : 0.5;
208 |
209 | double materialBonus = 0.0;
210 | switch (Material)
211 | {
212 | case 1:
213 | case 19:
214 | materialBonus = 0.85;
215 | break;
216 |
217 | case 26:
218 | case 27:
219 | materialBonus = 0.75;
220 | break;
221 | }
222 |
223 | double effect = CalculateLevelEffectValue(Level + Attributes.Count / 10.0, Rarity);
224 | return effect * typeBonus * materialBonus;
225 | }
226 | }
227 |
228 | public double Tempo
229 | {
230 | get
231 | {
232 | HashSet supportedTypes = new HashSet
233 | {
234 | Constants.ItemType.Amulets,
235 | Constants.ItemType.Rings,
236 | Constants.ItemType.Weapons,
237 | Constants.ItemType.ChestArmor,
238 | Constants.ItemType.ShoulderArmor,
239 | Constants.ItemType.Gloves,
240 | Constants.ItemType.Boots
241 | };
242 |
243 | Constants.ItemType itemType = (Constants.ItemType)Type;
244 |
245 | if (!supportedTypes.Contains(itemType))
246 | return 0.0;
247 |
248 | double typeBonus = 0.1;
249 | if (itemType == Constants.ItemType.Weapons && (Subtype == 15 || Subtype == 16 || Subtype == 17 ||
250 | Subtype == 5 || Subtype == 10 || Subtype == 11 ||
251 | Subtype == 18 || Subtype == 8 || Subtype == 6 || Subtype == 7) ||
252 | itemType == Constants.ItemType.ChestArmor)
253 | typeBonus = 0.2;
254 |
255 | double modifierBonus = (Modifier % 21) / 20.0;
256 | if (Material == 12)
257 | modifierBonus += 1.0;
258 |
259 | double effect = CalculateLevelEffectPercent(Level, Rarity);
260 | double result = effect * typeBonus * modifierBonus;
261 |
262 | return Math.Abs(result) < 0.001 ? 0 : result;
263 |
264 | }
265 | }
266 |
267 | public double Damage
268 | {
269 | get
270 | {
271 | Constants.ItemType itemType = (Constants.ItemType)Type;
272 |
273 | if (itemType != Constants.ItemType.Weapons)
274 | return 0.0;
275 |
276 | double damageBonus = 4.0;
277 | switch (Subtype)
278 | {
279 | case 3:
280 | case 4:
281 | damageBonus = 2.0;
282 | break;
283 |
284 | case 5:
285 | damageBonus = 4.0;
286 | break;
287 |
288 | case 13:
289 | damageBonus = 2.0;
290 | break;
291 |
292 | case 15:
293 | case 16:
294 | case 17:
295 | case 10:
296 | case 11:
297 | case 18:
298 | case 8:
299 | case 6:
300 | case 7:
301 | damageBonus = 8.0;
302 | break;
303 | }
304 |
305 | double effect = CalculateLevelEffectValue(Level + Attributes.Count / 10.0, Rarity);
306 | return effect * damageBonus;
307 | }
308 | }
309 |
310 | public short Modifier
311 | {
312 | get
313 | {
314 | int modifier, t;
315 | ChineseRemainder.Solve(PrefixDivisor, ModelDivisor, EffectDivisor, PrefixId, ModelId, EffectId, out modifier, out t);
316 |
317 | return (short)modifier;
318 | }
319 |
320 | private set
321 | {
322 | PrefixId = value % PrefixDivisor;
323 | ModelId = value % ModelDivisor;
324 | EffectId = value % EffectDivisor;
325 | }
326 | }
327 |
328 | public string FriendlyName
329 | {
330 | get
331 | {
332 | try
333 | {
334 | // TODO Should probably clean this up
335 | string format = "{0}";
336 |
337 | string ownerName = NameGenerator.Generate(Modifier, (Modifier * 7) % 11);
338 | string itemName = string.Empty;
339 |
340 | if (Type == (int)Constants.ItemType.Recipes)
341 | {
342 | itemName += Constants.ItemSubtypes[RecipeType][Subtype] + " ";
343 | itemName += Constants.ItemSubtypes[(int)Constants.ItemType.Recipes][Subtype];
344 | }
345 | else
346 | itemName += Constants.ItemSubtypes[Type][Subtype];
347 |
348 | if (Material != 0)
349 | itemName = Constants.ItemMaterialNames[Material] + " " + itemName;
350 |
351 | if (Modifier != 0)
352 | format = Constants.ItemModifiers[Rarity][(Modifier - 1) % 10];
353 |
354 | return Rarity < 3 ? string.Format(format, itemName) : string.Format(format, itemName, ownerName);
355 | }
356 | catch (Exception)
357 | {
358 | return "ERROR";
359 | }
360 | }
361 | }
362 |
363 | [Flags]
364 | public enum ItemFlags : byte
365 | {
366 | Adapted = 0x01
367 | }
368 |
369 | public Item()
370 | {
371 | Attributes = new List();
372 | }
373 |
374 | public void Read(BinaryReader reader)
375 | {
376 | Type = reader.ReadByte();
377 | Subtype = reader.ReadByte();
378 | reader.Skip(2);
379 | Modifier = reader.ReadInt16();
380 | reader.Skip(2);
381 | RecipeType = reader.ReadByte();
382 | reader.Skip(3);
383 | Rarity = reader.ReadByte();
384 | Material = reader.ReadByte();
385 | Flags = (ItemFlags)reader.ReadByte();
386 | reader.Skip(1);
387 | Level = reader.ReadInt16();
388 | reader.Skip(2);
389 |
390 | for (int i = 0; i < AttributeCount; ++i)
391 | {
392 | ItemAttribute attribute = new ItemAttribute();
393 | attribute.Read(reader);
394 |
395 | Attributes.Add(attribute);
396 | }
397 |
398 | // AttributesUsed is calculated on write
399 | reader.Skip(4);
400 | }
401 |
402 | public void Write(BinaryWriter writer)
403 | {
404 | writer.Write(Type);
405 | writer.Write(Subtype);
406 | writer.Skip(2);
407 | writer.Write(Modifier);
408 | writer.Skip(2);
409 | writer.Write(RecipeType);
410 | writer.Skip(3);
411 | writer.Write(Rarity);
412 | writer.Write(Material);
413 | writer.Write((byte)Flags);
414 | writer.Skip(1);
415 | writer.Write(Level);
416 | writer.Skip(2);
417 |
418 | foreach (ItemAttribute attribute in Attributes)
419 | attribute.Write(writer);
420 |
421 | writer.Write(Attributes.Count(attr => attr.Used));
422 | }
423 |
424 | private static double CalculateLevelEffectValue(double level, int rarity)
425 | {
426 | double a = 3.0 * (1.0 - (1.0 / (1.0 + ((level - 1.0) / 20.0))));
427 | double b = rarity / 4.0;
428 | double result = Math.Pow(2, a) * Math.Pow(2, b);
429 |
430 | return result;
431 | }
432 |
433 | private static double CalculateLevelEffectPercent(double level, int rarity)
434 | {
435 | double a = 3.0 * (1.0 - (1.0 / (1.0 + ((level - 1.0) / 20.0))));
436 | double b = rarity / 4.0;
437 | double c = 3.0;
438 | double result = Math.Pow(2, a) * Math.Pow(2, b) / Math.Pow(2, c);
439 |
440 | return result;
441 | }
442 | }
443 | }
--------------------------------------------------------------------------------
/Source/Character/ItemAttribute.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 |
3 | namespace CharacterEditor.Character
4 | {
5 | public class ItemAttribute : ICharacterData
6 | {
7 | public byte OffsetX;
8 | public byte OffsetY;
9 | public byte OffsetZ;
10 | public byte Material;
11 | public short Level;
12 |
13 | public bool Used
14 | {
15 | get
16 | {
17 | return OffsetX + OffsetY + OffsetZ + Material + Level > 0;
18 | }
19 | }
20 |
21 | public void Read(BinaryReader reader)
22 | {
23 | OffsetX = reader.ReadByte();
24 | OffsetY = reader.ReadByte();
25 | OffsetZ = reader.ReadByte();
26 | Material = reader.ReadByte();
27 | Level = reader.ReadInt16();
28 | reader.Skip(2);
29 | }
30 |
31 | public void Write(BinaryWriter writer)
32 | {
33 | writer.Write(OffsetX);
34 | writer.Write(OffsetY);
35 | writer.Write(OffsetZ);
36 | writer.Write(Material);
37 | writer.Write(Level);
38 | writer.Skip(2);
39 | }
40 | }
41 | }
--------------------------------------------------------------------------------
/Source/Character/NameGenerator.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | namespace CharacterEditor.Character
4 | {
5 | // CREDIT Ntl3fty
6 | public class NameGenerator
7 | {
8 | private static readonly IDictionary PartialNames = new Dictionary
9 | {
10 | {
11 | -1,
12 | new[,]
13 | {
14 | { "Kro", "Aru", "As", "Ge", "Kur", "Lugo", "Iko", "Liku", "Tero", "Var", "An", "The", "Ga", "Lan", "Dura", "Dama", "Se", "Thal", "Nar", "San" },
15 | { "no", "mi", "la", "sel", "ron", "ion", "kor", "lon", "rok", "tar", "den", "gar", "dar", "dara", "lan", "ka", "gor", "rior", "ria", "mor" }
16 | }
17 | },
18 |
19 | {
20 | 0,
21 | new[,]
22 | {
23 | { "El", "Li", "Dri", "Elan", "Le", "Ly", "A", "Tho", "Da", "Les" },
24 | { "ric", "kun", "zic", "dor", "las", "sander", "reon", "reas", "lundra", "andor" }
25 | }
26 | },
27 |
28 | {
29 | 1,
30 | new[,]
31 | {
32 | { "Ar", "A", "Si", "Mer", "Lu", "Ari", "Su", "Sira", "Hia", "Li" },
33 | { "weya", "luna", "laya", "leya", "ma", "lia", "matra", "vy", "zyna", "ly" }
34 | }
35 | },
36 |
37 | {
38 | 2,
39 | new[,]
40 | {
41 | { "De", "Ro", "As", "Ge", "An", "Pat", "Wolf", "Ale", "Mi", "Ben" },
42 | { "rek", "man", "gram", "rald", "rick", "ram", "sander", "kal", "ton", "ny" }
43 | }
44 | },
45 |
46 | {
47 | 3, new[,]
48 | {
49 | { "Sa", "Jen", "Kla", "Mi", "La", "Auri", "Mela", "Alu", "Ve", "Est" },
50 | { "rah", "ny", "ria", "elle", "na", "ga", "ma", "riana", "rona", "una" }
51 | }
52 | },
53 |
54 | {
55 | 4,
56 | new[,]
57 | {
58 | { "Gra", "Xe", "Ur", "Bel", "Chu", "Ki", "Go", "Zim", "Kubo", "Raz" },
59 | { "zic", "nax", "tik", "tuk", "ruk", "bo", "rix", "mi", "tok", "nor" }
60 | }
61 | },
62 |
63 | {
64 | 5,
65 | new[,]
66 | {
67 | { "Kur", "Xe", "Ki", "Am", "Zifa", "Zu", "Ma", "Chi", "Zi", "Mia" },
68 | { "ra", "lia", "bi", "ba", "ly", "ki", "bara", "mi", "zy", "xa" }
69 | }
70 | },
71 |
72 | {
73 | 7,
74 | new[,]
75 | {
76 | { "Cho", "Zer", "Kaz", "Kraz", "Zel", "Drak", "Lo", "Raz", "Spi", "Zen" },
77 | { "rux", "rek", "zic", "tac", "mec", "kor", "rax", "zor", "ro", "go" }
78 | }
79 | },
80 |
81 | {
82 | 8,
83 | new[,]
84 | {
85 | { "Zi", "Zer", "Az", "Ki", "Iza", "Drak", "Li", "May", "Spi", "Zan" },
86 | { "rya", "ri", "zia", "ki", "mah", "ira", "maya", "ana", "ra", "ya" }
87 | }
88 | },
89 |
90 | {
91 | 9,
92 | new[,]
93 | {
94 | { "Tor", "Gem", "Bar", "Me", "As", "Tem", "Arak", "Ur", "Grim", "Xor" },
95 | { "lox", "bart", "kor", "thos", "kun", "bur", "thor", "lok", "li", "bor" }
96 | }
97 | },
98 |
99 | {
100 | 10,
101 | new[,]
102 | {
103 | { "Mum", "Grun", "Brun", "Hei", "Mo", "Hil", "Ur", "Lum", "Grim", "Xor" },
104 | { "pie", "hild", "di", "muna", "ki", "trud", "sa", "axa", "ira", "ika" }
105 | }
106 | },
107 |
108 | {
109 | 11,
110 | new[,]
111 | {
112 | { "Uz", "Ur", "Chu", "Ku", "Mor", "Ura", "Ak", "Ur", "Or", "Gor" },
113 | { "ku", "ruk", "muk", "thak", "dok", "tor", "rorok", "chak", "kaz", "rack" }
114 | }
115 | },
116 |
117 | {
118 | 12,
119 | new[,]
120 | {
121 | { "Uz", "Ur", "Chu", "Ku", "Mor", "Ura", "Ak", "Ur", "Or", "Gor" },
122 | { "ka", "rua", "mua", "thara", "daka", "tah", "rorah", "chaka", "kaya", "rana" }
123 | }
124 | },
125 |
126 | {
127 | 13,
128 | new[,]
129 | {
130 | { "Qua", "Rib", "Quib", "Zib", "Il", "Wok", "Wib", "Moko", "Sli", "Bul" },
131 | { "rik", "bit", "ble", "bik", "wak", "wok", "wib", "luk", "mey", "bak" }
132 | }
133 | },
134 |
135 | {
136 | 14,
137 | new[,]
138 | {
139 | { "Qua", "Rib", "Quib", "Zib", "Il", "Wok", "Wib", "Moko", "Sli", "Bul" },
140 | { "ria", "bia", "bla", "bia", "waka", "woka", "wibba", "lua", "maya", "ba" }
141 | }
142 | },
143 |
144 | {
145 | 15,
146 | new[,]
147 | {
148 | { "Chu", "Dro", "Al", "Dem", "Mor", "Mur", "Cro", "Zul", "Dra", "The" },
149 | { "lu", "kor", "card", "morius", "enius", "tus", "demar", "lus", "ruul", "zad" }
150 | }
151 | },
152 |
153 | {
154 | 16,
155 | new[,]
156 | {
157 | { "Xu", "Dra", "Al", "Dem", "Mor", "Myr", "Cra", "Zul", "Dri", "Thu" },
158 | { "la", "kira", "cara", "moria", "ena", "tana", "diria", "laza", "rah", "zazah" }
159 | }
160 | }
161 | };
162 |
163 | static NameGenerator()
164 | {
165 | PartialNames[18] = PartialNames[2];
166 | PartialNames[43] = PartialNames[2];
167 | PartialNames[83] = PartialNames[2];
168 |
169 | PartialNames[45] = PartialNames[3];
170 | PartialNames[84] = PartialNames[3];
171 | }
172 |
173 | public static string Generate(int id, int type = -1)
174 | {
175 | string[,] partials;
176 | if (!PartialNames.TryGetValue(type, out partials))
177 | partials = PartialNames[-1];
178 |
179 | int index1 = (13 * id + id / 7) % partials.GetLength(1);
180 | int index2 = (id / 10 + 7 * id) % partials.GetLength(1);
181 |
182 | return partials[0, index1] + partials[1, index2];
183 | }
184 | }
185 | }
186 |
--------------------------------------------------------------------------------
/Source/Character/Slot.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 |
3 | namespace CharacterEditor.Character
4 | {
5 | public class Slot : ICharacterData
6 | {
7 | public const int MaxItemCount = 50;
8 |
9 | public int Count;
10 | public Item Item;
11 |
12 | public void Read(BinaryReader reader)
13 | {
14 | Count = reader.ReadInt32();
15 | Item = new Item();
16 | Item.Read(reader);
17 | }
18 |
19 | public void Write(BinaryWriter writer)
20 | {
21 | writer.Write(Count);
22 | Item.Write(writer);
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Source/Character/World.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 |
3 | namespace CharacterEditor.Character
4 | {
5 | public class World : ICharacterData
6 | {
7 | public int Seed;
8 | public string Name;
9 | public long X;
10 | public long Y;
11 | public long Z;
12 |
13 | public void Read(BinaryReader reader)
14 | {
15 | Seed = reader.ReadInt32();
16 | Name = reader.ReadLongString();
17 | X = reader.ReadInt64();
18 | Y = reader.ReadInt64();
19 | Z = reader.ReadInt64();
20 | }
21 |
22 | public void Write(BinaryWriter writer)
23 | {
24 | writer.Write(Seed);
25 | writer.WriteLongString(Name);
26 | writer.Write(X);
27 | writer.Write(Y);
28 | writer.Write(Z);
29 | }
30 | }
31 | }
--------------------------------------------------------------------------------
/Source/CharacterEditor.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | x86
6 | 8.0.30703
7 | 2.0
8 | {42DB9E31-B097-4870-803A-54C924271BA6}
9 | Exe
10 | Properties
11 | CharacterEditor
12 | CharacterEditor
13 | v4.0
14 |
15 |
16 | 512
17 |
18 |
19 | x86
20 | true
21 | full
22 | false
23 | bin\Debug\
24 | DEBUG;TRACE
25 | prompt
26 | 4
27 |
28 |
29 | x86
30 | pdbonly
31 | true
32 | bin\Release\
33 | TRACE
34 | prompt
35 | 4
36 |
37 |
38 |
39 |
40 |
41 | icon.ico
42 |
43 |
44 |
45 |
46 |
47 |
48 | False
49 | ..\References\System.Data.SQLite.dll
50 |
51 |
52 |
53 |
54 |
55 | False
56 | ..\References\zlib.net.dll
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 | Editor.cs
74 | Form
75 |
76 |
77 | Form
78 |
79 |
80 | Editor.cs
81 | Form
82 |
83 |
84 | Editor.cs
85 |
86 |
87 | Editor.cs
88 | Form
89 |
90 |
91 | Editor.cs
92 | Form
93 |
94 |
95 | Form
96 |
97 |
98 | ExceptionDialog.cs
99 |
100 |
101 | Form
102 |
103 |
104 | FormItemStats.cs
105 |
106 |
107 | Form
108 |
109 |
110 | LoadCharacterDialog.cs
111 |
112 |
113 | Component
114 |
115 |
116 |
117 |
118 | True
119 | True
120 | Resources.resx
121 |
122 |
123 |
124 | Editor.cs
125 | Designer
126 |
127 |
128 | ExceptionDialog.cs
129 |
130 |
131 | FormItemStats.cs
132 |
133 |
134 | LoadCharacterDialog.cs
135 |
136 |
137 | ResXFileCodeGenerator
138 | Resources.Designer.cs
139 | Designer
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
157 |
--------------------------------------------------------------------------------
/Source/CharacterEditor.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2010
4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CharacterEditor", "CharacterEditor.csproj", "{42DB9E31-B097-4870-803A-54C924271BA6}"
5 | EndProject
6 | Global
7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
8 | Debug|Any CPU = Debug|Any CPU
9 | Debug|Mixed Platforms = Debug|Mixed Platforms
10 | Debug|x86 = Debug|x86
11 | Release|Any CPU = Release|Any CPU
12 | Release|Mixed Platforms = Release|Mixed Platforms
13 | Release|x86 = Release|x86
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {42DB9E31-B097-4870-803A-54C924271BA6}.Debug|Any CPU.ActiveCfg = Debug|x86
17 | {42DB9E31-B097-4870-803A-54C924271BA6}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
18 | {42DB9E31-B097-4870-803A-54C924271BA6}.Debug|Mixed Platforms.Build.0 = Debug|x86
19 | {42DB9E31-B097-4870-803A-54C924271BA6}.Debug|x86.ActiveCfg = Debug|x86
20 | {42DB9E31-B097-4870-803A-54C924271BA6}.Debug|x86.Build.0 = Debug|x86
21 | {42DB9E31-B097-4870-803A-54C924271BA6}.Release|Any CPU.ActiveCfg = Release|x86
22 | {42DB9E31-B097-4870-803A-54C924271BA6}.Release|Mixed Platforms.ActiveCfg = Release|x86
23 | {42DB9E31-B097-4870-803A-54C924271BA6}.Release|Mixed Platforms.Build.0 = Release|x86
24 | {42DB9E31-B097-4870-803A-54C924271BA6}.Release|x86.ActiveCfg = Release|x86
25 | {42DB9E31-B097-4870-803A-54C924271BA6}.Release|x86.Build.0 = Release|x86
26 | EndGlobalSection
27 | GlobalSection(SolutionProperties) = preSolution
28 | HideSolutionNode = FALSE
29 | EndGlobalSection
30 | EndGlobal
31 |
--------------------------------------------------------------------------------
/Source/Database.cs:
--------------------------------------------------------------------------------
1 | using System.Data;
2 | using System.Data.SQLite;
3 | using System.IO;
4 | using System.Linq;
5 | using zlib;
6 |
7 | namespace CharacterEditor
8 | {
9 | public class Database
10 | {
11 | private SQLiteConnection connection;
12 |
13 | public void Load(string filename)
14 | {
15 | string connectionString = string.Format("Data Source={0};Version=3", filename);
16 | connection = new SQLiteConnection(connectionString);
17 | connection.Open();
18 | }
19 |
20 | public byte[] ReadCharacterBlob(int index)
21 | {
22 | byte[] stream = ReadBlobByIndex(index);
23 | byte[] decompressedStream;
24 |
25 | DecompressData(stream, out decompressedStream);
26 |
27 | return decompressedStream;
28 | }
29 |
30 | public bool WriteCharacterBlob(int index, byte[] data)
31 | {
32 | byte[] compressedStream;
33 | CompressData(data, out compressedStream);
34 |
35 | return WriteBlobByIndex(index, compressedStream);
36 | }
37 |
38 | public bool WriteBlobByIndex(int index, byte[] data)
39 | {
40 | using (SQLiteCommand command = new SQLiteCommand(connection))
41 | {
42 | command.CommandText = string.Format("UPDATE `blobs` SET `value`=@blobData WHERE `key`='{0}'", index);
43 | command.Parameters.Add(new SQLiteParameter("@blobData", DbType.Binary)
44 | {
45 | Value = data
46 | });
47 |
48 | return command.ExecuteNonQuery() == 1;
49 | }
50 | }
51 |
52 | public byte[] ReadBlobByIndex(int index)
53 | {
54 | return ReadBlobByKey(index.ToString("G"));
55 | }
56 |
57 | public byte[] ReadBlobByKey(string index)
58 | {
59 | DataTable table = new DataTable();
60 |
61 | using (SQLiteCommand command = new SQLiteCommand(connection))
62 | {
63 | command.CommandText = string.Format("SELECT `value` FROM `blobs` WHERE `key`='{0}'", index);
64 | SQLiteDataReader reader = command.ExecuteReader();
65 | table.Load(reader);
66 | reader.Close();
67 | }
68 |
69 | if (table.Rows.Count == 0)
70 | return null;
71 |
72 | return (byte[])table.Rows[0].ItemArray.First();
73 | }
74 |
75 | private static void CompressData(byte[] inData, out byte[] outData)
76 | {
77 | using (MemoryStream outMemoryStream = new MemoryStream())
78 | {
79 | using (ZOutputStream outZStream = new ZOutputStream(outMemoryStream, zlibConst.Z_DEFAULT_COMPRESSION))
80 | {
81 | using (Stream inMemoryStream = new MemoryStream(inData))
82 | {
83 | CopyStream(inMemoryStream, outZStream);
84 | outZStream.finish();
85 |
86 | outData = outMemoryStream.ToArray();
87 | }
88 | }
89 | }
90 | }
91 |
92 | private static void DecompressData(byte[] inData, out byte[] outData)
93 | {
94 | using (MemoryStream outMemoryStream = new MemoryStream())
95 | {
96 | using (ZOutputStream outZStream = new ZOutputStream(outMemoryStream))
97 | {
98 | using (Stream inMemoryStream = new MemoryStream(inData))
99 | {
100 | CopyStream(inMemoryStream, outZStream);
101 | outZStream.finish();
102 |
103 | outData = outMemoryStream.ToArray();
104 | }
105 | }
106 | }
107 | }
108 |
109 | private static void CopyStream(Stream input, Stream output)
110 | {
111 | byte[] buffer = new byte[2048];
112 | int len;
113 |
114 | while ((len = input.Read(buffer, 0, buffer.Length)) > 0)
115 | output.Write(buffer, 0, len);
116 |
117 | output.Flush();
118 | }
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/Source/DirtyWatcher.cs:
--------------------------------------------------------------------------------
1 | using System.Windows.Forms;
2 |
3 | namespace CharacterEditor
4 | {
5 | public class DirtyWatcher
6 | {
7 | public bool Dirty;
8 | public bool IgnoreDirtiness;
9 |
10 | public DirtyWatcher(Control form)
11 | {
12 | RecurseControls(form);
13 | }
14 |
15 | private void RecurseControls(Control form)
16 | {
17 | foreach (Control control in form.Controls)
18 | RecurseControlsInner(control);
19 | }
20 |
21 | private void RecurseControlsInner(Control parent)
22 | {
23 | foreach (Control control in parent.Controls)
24 | {
25 | if (control is TextBox)
26 | {
27 | control.TextChanged += (o, e) => Dirty = !IgnoreDirtiness || Dirty;
28 | }
29 | else if (control is ComboBox)
30 | {
31 | ComboBox comboBox = (ComboBox)control;
32 | comboBox.SelectedIndexChanged += (o, e) => Dirty = !IgnoreDirtiness || Dirty;
33 | }
34 | else if (control is NumericUpDown)
35 | {
36 | NumericUpDown numericUpDown = (NumericUpDown)control;
37 | numericUpDown.ValueChanged += (o, e) => Dirty = !IgnoreDirtiness || Dirty;
38 | }
39 | else if (control is CheckBox)
40 | {
41 | CheckBox checkBox = (CheckBox)control;
42 | checkBox.CheckedChanged += (o, e) => Dirty = !IgnoreDirtiness || Dirty;
43 | }
44 | else if (control is Button)
45 | {
46 | Button button = (Button)control;
47 | button.BackColorChanged += (o, e) => Dirty = !IgnoreDirtiness || Dirty;
48 | }
49 |
50 | RecurseControlsInner(control);
51 | }
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/Source/Forms/Editor.Character.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Windows.Forms;
3 |
4 | namespace CharacterEditor.Forms
5 | {
6 | public partial class Editor
7 | {
8 | private void ButtonHairColorClick(object sender, EventArgs e)
9 | {
10 | ColorDialog colorDialog = new ColorDialog
11 | {
12 | Color = buttonHairColor.BackColor,
13 | FullOpen = true
14 | };
15 |
16 | colorDialog.ShowDialog(this);
17 |
18 | buttonHairColor.BackColor = colorDialog.Color;
19 | }
20 |
21 | private void ComboBoxRaceSelectedIndexChanged(object sender, EventArgs e)
22 | {
23 | int[,] faceMaximums = new[,]
24 | {
25 | { 6, 6 },
26 | { 4, 6 },
27 | { 5, 5 },
28 | { 5, 4 },
29 | { 5, 6 },
30 | { 2, 5 },
31 | { 6, 6 },
32 | { 5, 4 }
33 | };
34 |
35 | int[,] haircutMaximums = new[,]
36 | {
37 | { 15, 7 },
38 | { 10, 10 },
39 | { 3, 5 },
40 | { 10, 4 },
41 | { 6, 6 },
42 | { 6, 6 },
43 | { 6, 6 },
44 | { 5, 4 }
45 | };
46 |
47 | if (comboBoxRace.SelectedIndex == -1 || comboBoxGender.SelectedIndex == -1)
48 | return;
49 |
50 | nudFace.Maximum = faceMaximums[comboBoxRace.SelectedIndex, comboBoxGender.SelectedIndex];
51 | nudHair.Maximum = haircutMaximums[comboBoxRace.SelectedIndex, comboBoxGender.SelectedIndex];
52 | }
53 |
54 | private void ComboBoxClassSelectedIndexChanged(object sender, EventArgs e)
55 | {
56 | object[][] specializations = new object[][]
57 | {
58 | new[] { "Berserker", "Guardian" },
59 | new[] { "Sniper", "Scout" },
60 | new[] { "Fire Mage", "Water Mage" },
61 | new[] { "Assassin", "Ninja" }
62 | };
63 |
64 | if (comboBoxClass.SelectedIndex == -1)
65 | return;
66 |
67 | comboBoxSpecialization.Items.Clear();
68 | comboBoxSpecialization.Items.AddRange(specializations[comboBoxClass.SelectedIndex]);
69 |
70 | comboBoxSpecialization.SelectedIndex = character.Specialization;
71 | }
72 |
73 | private void NudLevelValueChanged(object sender, EventArgs e)
74 | {
75 | nudPetLevel.Maximum = nudLevel.Value;
76 | nudExperience.Maximum = (decimal)(50 + 1000 * (1 - 1 / (((int)nudLevel.Value - 1) * 0.05 + 1)));
77 | }
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/Source/Forms/Editor.Data.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using System.Windows.Forms;
3 | using CharacterEditor.Character;
4 |
5 | namespace CharacterEditor.Forms
6 | {
7 | public partial class Editor
8 | {
9 | private void SyncCharacterDataToGui()
10 | {
11 | textBoxName.Text = character.Name;
12 | nudLevel.Value = character.Level;
13 | nudExperience.Value = character.Experience;
14 | comboBoxGender.SelectedIndex = character.Gender;
15 | comboBoxRace.SelectedIndex = character.Race;
16 | comboBoxClass.SelectedIndex = (int)character.Class - 1;
17 | nudFace.Value = character.Face;
18 | nudHair.Value = character.Hair;
19 |
20 | buttonHairColor.BackColor = character.HairColor;
21 |
22 | nudPetMasterSkillLevel.Value = character.PetMasterSkillLevel;
23 | nudPetRidingSkillLevel.Value = character.PetRidingSkillLevel;
24 | nudClimbingSkillLevel.Value = character.ClimbingSkillLevel;
25 | nudHangGlidingSkillLevel.Value = character.HangGlidingSkillLevel;
26 | nudSwimmingSkillLevel.Value = character.SwimmingSkillLevel;
27 | nudSailingSkillLevel.Value = character.SailingSkillLevel;
28 | nudTierOneSkillLevel.Value = character.TierOneSkillLevel;
29 | nudTierTwoSkillLevel.Value = character.TierTwoSkillLevel;
30 | nudTierThreeSkillLevel.Value = character.TierThreeSkillLevel;
31 |
32 | for (int i = 0; i < Character.Character.EquipmentCount; ++i)
33 | {
34 | Item item = character.Equipment[i];
35 |
36 | // Do not add unused and pet equipment
37 | if (i == 0 || i == 12)
38 | continue;
39 |
40 | TabPage tabPage = CreateEquipmentTab(i);
41 | tabPage.Tag = item;
42 |
43 | tabControlEquipment.TabPages.Add(tabPage);
44 | }
45 |
46 | Item petEquipment = character.Equipment.Last();
47 | comboBoxPetKind.SelectedIndex = Utility.NormalizeIndex(petEquipment.Subtype, Constants.ItemSubtypes[(int)Constants.ItemType.Pets]) + 1;
48 | if (comboBoxPetKind.SelectedIndex == -1)
49 | comboBoxPetKind.SelectedIndex = 0;
50 |
51 | nudPetLevel.Value = petEquipment.Level;
52 | nudPetExperience.Value = petEquipment.Modifier;
53 | textBoxPetName.Text = petEquipment.Attributes.Aggregate("", (c, a) => c + (char)a.Material);
54 |
55 | nudCoinsGold.Value = (character.Coins / 10000) % 100;
56 | nudCoinsSilver.Value = (character.Coins / 100) % 100;
57 | nudCoinsCopper.Value = character.Coins % 100;
58 | nudCoinsPlatinum.Value = character.PlatinumCoins;
59 |
60 | // Sync inventory to GUI
61 | for (int i = 0; i < Character.Character.InventoryCount; ++i)
62 | {
63 | Inventory inventory = character.Inventories[i];
64 |
65 | TabPage tabPage = new TabPage(new[] { "Equipment", "Items", "Ingredients", "Pets" }[i]);
66 | ListView listView = new ListView
67 | {
68 | Activation = ItemActivation.OneClick,
69 | BorderStyle = BorderStyle.None,
70 | Dock = DockStyle.Fill,
71 | HideSelection = false,
72 | LargeImageList = imageListInventory,
73 | MultiSelect = false,
74 | UseCompatibleStateImageBehavior = false
75 | };
76 |
77 | // Ok .NET 2.0, have it your way
78 | listView.SelectedIndexChanged += ListViewInventorySelectedIndexChanged;
79 |
80 | foreach (Slot slot in inventory.Items)
81 | {
82 | ListViewItem listViewItem;
83 |
84 | if (slot.Count > 0 && slot.Item.Type != 0x00)
85 | {
86 | listViewItem = new ListViewItem
87 | {
88 | ImageIndex = slot.Item.Type,
89 | Text = slot.Item.FriendlyName,
90 | Tag = slot.Item
91 | };
92 | }
93 | else
94 | {
95 | listViewItem = new ListViewItem
96 | {
97 | ImageIndex = 0,
98 | Text = "",
99 | Tag = slot.Item
100 | };
101 | }
102 |
103 | listView.Items.Add(listViewItem);
104 | }
105 |
106 | tabPage.Controls.Add(listView);
107 | tabControlInventory.TabPages.Add(tabPage);
108 | }
109 |
110 | if (dirtyWatcher != null)
111 | dirtyWatcher.Dirty = false;
112 | }
113 |
114 | private void SyncGuiToCharacterData()
115 | {
116 | // TODO Shouldn't I be able to link all this with a DataModel?
117 |
118 | character.Name = textBoxName.Text;
119 | character.Level = (int)nudLevel.Value;
120 | character.Experience = (int)nudExperience.Value;
121 | character.Gender = (byte)comboBoxGender.SelectedIndex;
122 | character.Race = comboBoxRace.SelectedIndex;
123 | character.Class = (Character.Character.ClassType)(comboBoxClass.SelectedIndex + 1);
124 | character.Specialization = (byte)comboBoxSpecialization.SelectedIndex;
125 | character.Face = (int)nudFace.Value;
126 | character.Hair = (int)nudHair.Value;
127 | character.HairColor = buttonHairColor.BackColor;
128 |
129 | character.PetMasterSkillLevel = (int)nudPetMasterSkillLevel.Value;
130 | character.PetRidingSkillLevel = (int)nudPetRidingSkillLevel.Value;
131 | character.ClimbingSkillLevel = (int)nudClimbingSkillLevel.Value;
132 | character.HangGlidingSkillLevel = (int)nudHangGlidingSkillLevel.Value;
133 | character.SwimmingSkillLevel = (int)nudSwimmingSkillLevel.Value;
134 | character.SailingSkillLevel = (int)nudSailingSkillLevel.Value;
135 | character.TierOneSkillLevel = (int)nudTierOneSkillLevel.Value;
136 | character.TierTwoSkillLevel = (int)nudTierTwoSkillLevel.Value;
137 | character.TierThreeSkillLevel = (int)nudTierThreeSkillLevel.Value;
138 |
139 | character.Coins = (int)(nudCoinsGold.Value * 10000 + nudCoinsSilver.Value * 100 + nudCoinsCopper.Value);
140 | character.PlatinumCoins = (int)nudCoinsPlatinum.Value;
141 |
142 | Item petEquipment = character.Equipment.Last();
143 | petEquipment.Type = (byte)(comboBoxPetKind.SelectedIndex <= 0 ? (int)Constants.ItemType.None : (int)Constants.ItemType.Pets);
144 | petEquipment.Subtype = (byte)Utility.GoofyIndex(comboBoxPetKind.SelectedIndex - 1, Constants.ItemSubtypes[(int)Constants.ItemType.Pets]);
145 | petEquipment.Level = (short)nudPetLevel.Value;
146 | // TODO Fix pets..........
147 | //petEquipment.Modifier = (short)nudPetExperience.Value;
148 |
149 | for (int i = 0; i < textBoxPetName.Text.Length; ++i)
150 | petEquipment.Attributes[i].Material = (byte)textBoxPetName.Text[i];
151 |
152 | dirtyWatcher.Dirty = false;
153 | }
154 | }
155 | }
156 |
--------------------------------------------------------------------------------
/Source/Forms/Editor.Equipment.cs:
--------------------------------------------------------------------------------
1 | using System.Windows.Forms;
2 |
3 | namespace CharacterEditor.Forms
4 | {
5 | public partial class Editor
6 | {
7 | private TabPage CreateEquipmentTab(int i)
8 | {
9 | TabPage tabPage =
10 | new TabPage(
11 | new[]
12 | {
13 | "", "Neck", "Chest", "Feet", "Hands", "Shoulder Armor", "Left Weapon", "Right Weapon", "Left Ring", "Right Ring",
14 | "Light", "Special", "Pet"
15 | }[i]);
16 |
17 | ComboBox comboBoxEquipmentItemMaterial = new ComboBox
18 | {
19 | DropDownStyle = ComboBoxStyle.DropDownList,
20 | Location = new System.Drawing.Point(266, 32),
21 | Size = new System.Drawing.Size(124, 21)
22 | };
23 |
24 | Label labelEquipmentItemMaterial = new Label
25 | {
26 | AutoSize = true,
27 | Location = new System.Drawing.Point(267, 16),
28 | Size = new System.Drawing.Size(47, 13),
29 | Text = "Material:"
30 | };
31 |
32 | SafeNumericUpDown nudEquipmentItemLevel = new SafeNumericUpDown
33 | {
34 | Location = new System.Drawing.Point(136, 77),
35 | Maximum = 0x7FFF,
36 | Size = new System.Drawing.Size(124, 20)
37 | };
38 |
39 | Label labelEquipmentItemLevel = new Label
40 | {
41 | AutoSize = true,
42 | Location = new System.Drawing.Point(133, 60),
43 | Size = new System.Drawing.Size(36, 13),
44 | Text = "Level:"
45 | };
46 |
47 | ComboBox comboBoxEquipmentItemModifier = new ComboBox
48 | {
49 | DropDownStyle = ComboBoxStyle.DropDownList,
50 | Location = new System.Drawing.Point(136, 32),
51 | Size = new System.Drawing.Size(124, 21),
52 | };
53 |
54 | //comboBoxEquipmentItemModifier.Items.AddRange(Constants.ItemModifiers[comboBoxItemRarity.SelectedIndex].Where(x => !String.IsNullOrEmpty(x)).ToArray());
55 |
56 | Label labelEquipmentItemModifier = new Label
57 | {
58 | AutoSize = true,
59 | Location = new System.Drawing.Point(133, 16),
60 | Size = new System.Drawing.Size(47, 13),
61 | Text = "Modifier:"
62 | };
63 |
64 | Label labelEquipmentItemSubtype = new Label
65 | {
66 | AutoSize = true,
67 | Location = new System.Drawing.Point(7, 60),
68 | Size = new System.Drawing.Size(49, 13),
69 | Text = "Subtype:"
70 | };
71 |
72 | Label labelEquipmentItemType = new Label
73 | {
74 | AutoSize = true,
75 | Location = new System.Drawing.Point(6, 16),
76 | Size = new System.Drawing.Size(34, 13),
77 | Text = "Type:"
78 | };
79 |
80 | ComboBox comboBoxEquipmentItemSubtype = new ComboBox
81 | {
82 | DropDownStyle = ComboBoxStyle.DropDownList,
83 | Location = new System.Drawing.Point(6, 76),
84 | Size = new System.Drawing.Size(124, 21)
85 | };
86 |
87 | ComboBox comboBoxEquipmentItemType = new ComboBox
88 | {
89 | DropDownStyle = ComboBoxStyle.DropDownList,
90 | Location = new System.Drawing.Point(6, 32),
91 | Size = new System.Drawing.Size(124, 21)
92 | };
93 |
94 | GroupBox groupBoxEquipmentItem = new GroupBox
95 | {
96 | Enabled = false,
97 | Location = new System.Drawing.Point(6, 6),
98 | Size = new System.Drawing.Size(522, 189),
99 | TabStop = false,
100 | Text = "Item"
101 | };
102 |
103 | groupBoxEquipmentItem.Controls.AddRange(new Control[]
104 | {
105 | comboBoxEquipmentItemMaterial,
106 | labelEquipmentItemMaterial,
107 | nudEquipmentItemLevel,
108 | labelEquipmentItemLevel,
109 | comboBoxEquipmentItemModifier,
110 | labelEquipmentItemModifier,
111 | labelEquipmentItemSubtype,
112 | labelEquipmentItemType,
113 | comboBoxEquipmentItemSubtype,
114 | comboBoxEquipmentItemType
115 | });
116 |
117 | tabPage.Controls.Add(groupBoxEquipmentItem);
118 |
119 | return tabPage;
120 | }
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/Source/Forms/Editor.Inventory.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using System.Windows.Forms;
4 | using CharacterEditor.Character;
5 |
6 | namespace CharacterEditor.Forms
7 | {
8 | public partial class Editor
9 | {
10 | private Item SelectedItem
11 | {
12 | get
13 | {
14 | ListView listView = tabControlInventory.SelectedTab.Controls.OfType().FirstOrDefault();
15 | if (listView == null || listView.SelectedItems.Count == 0)
16 | return null;
17 |
18 | return (Item)listView.SelectedItems[0].Tag;
19 | }
20 | }
21 |
22 | private Slot SelectedSlot
23 | {
24 | get
25 | {
26 | Inventory inventory = character.Inventories[tabControlInventory.SelectedIndex];
27 | return inventory.Items.SingleOrDefault(t => t.Item == SelectedItem);
28 | }
29 | }
30 |
31 | // ListView Select
32 | private void ListViewInventorySelectedIndexChanged(object sender, EventArgs e)
33 | {
34 | if (SelectedItem == null)
35 | return;
36 |
37 | // Ignore dirtiness
38 | lock (dirtyWatcher)
39 | dirtyWatcher.IgnoreDirtiness = true;
40 |
41 | // Update controls if needed
42 | UpdateItemControls();
43 |
44 | if (SelectedSlot.Count != 0)
45 | {
46 | // There's an item here, update controls
47 | comboBoxItemType.SelectedIndex = Utility.NormalizeIndex(SelectedItem.Type, Constants.ItemTypeNames);
48 | comboBoxItemSubtype.SelectedIndex = Utility.NormalizeIndex(SelectedItem.Subtype, Constants.ItemSubtypes[SelectedItem.Type]);
49 | comboBoxItemMaterial.SelectedIndex = Utility.NormalizeIndex(SelectedItem.Material, Constants.ItemMaterialNames);
50 | //if (SelectedItem.Modifier != 0)
51 | // comboBoxItemPrefixId.SelectedIndex = (SelectedItem.Modifier - 1) % 10 + 1;
52 | //else
53 | // comboBoxItemPrefixId.SelectedIndex = 0;
54 |
55 | comboBoxItemPrefixId.SelectedIndex = SelectedItem.PrefixId;
56 | nudItemModelId.Value = SelectedItem.ModelId;
57 | nudItemEffectId.Value = SelectedItem.EffectId;
58 |
59 | nudItemHP.Value = (decimal)SelectedItem.Life;
60 | nudItemArmor.Value = (decimal)SelectedItem.Armor;
61 | nudItemResistance.Value = (decimal)SelectedItem.Resistance;
62 | nudItemTempo.Value = (decimal)SelectedItem.Tempo;
63 | nudItemCrit.Value = (decimal)SelectedItem.Critical;
64 | nudItemReg.Value = (decimal)SelectedItem.Regeneration;
65 |
66 | nudItemLevel.Value = SelectedItem.Level;
67 | comboBoxItemRarity.SelectedIndex = SelectedItem.Rarity;
68 | checkBoxItemAdapted.Checked = SelectedItem.Flags.HasFlag(Item.ItemFlags.Adapted);
69 | nudItemCount.Value = SelectedSlot.Count;
70 | }
71 | else
72 | {
73 | // No item here, update controls
74 | comboBoxItemType.SelectedIndex = -1;
75 | comboBoxItemSubtype.SelectedIndex = -1;
76 | comboBoxItemMaterial.SelectedIndex = -1;
77 | comboBoxItemPrefixId.SelectedIndex = -1;
78 | nudItemLevel.Value = 0;
79 | comboBoxItemRarity.SelectedIndex = -1;
80 | checkBoxItemAdapted.Checked = false;
81 | nudItemCount.Value = 0;
82 | }
83 |
84 | // Stop ignoring dirtiness
85 | lock (dirtyWatcher)
86 | dirtyWatcher.IgnoreDirtiness = false;
87 | }
88 |
89 | // Type
90 | private void ComboBoxItemTypeSelectedIndexChanged(object sender, EventArgs e)
91 | {
92 | if (SelectedItem == null)
93 | return;
94 |
95 | if (comboBoxItemType.SelectedIndex == -1)
96 | comboBoxItemType.SelectedIndex = 0;
97 |
98 | SelectedItem.Type = (byte)Utility.GoofyIndex(comboBoxItemType.SelectedIndex, Constants.ItemTypeNames);
99 |
100 | int subtypeIndex = Utility.GoofyIndex(comboBoxItemType.SelectedIndex, Constants.ItemTypeNames);
101 |
102 | comboBoxItemSubtype.Items.Clear();
103 |
104 | if (subtypeIndex <= 0)
105 | return;
106 |
107 | comboBoxItemSubtype.Items.AddRange(Constants.ItemSubtypes[subtypeIndex].Where(x => !String.IsNullOrEmpty(x)).ToArray());
108 | comboBoxItemSubtype.SelectedIndex = 0;
109 |
110 | UpdateItemAvatar();
111 | }
112 |
113 | // Subtype
114 | private void ComboBoxItemSubtypeSelectedIndexChanged(object sender, EventArgs e)
115 | {
116 | if (SelectedItem == null)
117 | return;
118 |
119 | SelectedItem.Subtype = (byte)Utility.GoofyIndex(comboBoxItemSubtype.SelectedIndex,
120 | Constants.ItemSubtypes[SelectedItem.Type]);
121 | UpdateItemAvatar();
122 | }
123 |
124 | // Material
125 | private void ComboBoxItemMaterialSelectedIndexChanged(object sender, EventArgs e)
126 | {
127 | if (SelectedItem == null)
128 | return;
129 |
130 | SelectedItem.Material = (byte)Utility.GoofyIndex(comboBoxItemMaterial.SelectedIndex, Constants.ItemMaterialNames);
131 | UpdateItemAvatar();
132 | }
133 |
134 | // Modifer
135 | private void ComboBoxItemModifierSelectedIndexChanged(object sender, EventArgs e)
136 | {
137 | if (SelectedItem == null)
138 | return;
139 |
140 | // TODO Magic code right here
141 | //int offset = 0;
142 | //int offsetInitial = ((SelectedItem.ActualModifier - 1) % 10 + 1);
143 | //if (comboBoxItemPrefixId.SelectedIndex != 0)
144 | // offset = comboBoxItemPrefixId.SelectedIndex - offsetInitial;
145 |
146 | //SelectedItem.Modifier = (short)(SelectedItem.ActualModifier + offset);
147 | UpdateItemAvatar();
148 | }
149 |
150 | // Level
151 | private void NudItemLevelValueChanged(object sender, EventArgs e)
152 | {
153 | if (SelectedItem == null)
154 | return;
155 |
156 | SelectedItem.Level = (short)nudItemLevel.Value;
157 | UpdateItemAvatar();
158 | }
159 |
160 | // Rarity
161 | private void ComboBoxItemRaritySelectedIndexChanged(object sender, EventArgs e)
162 | {
163 | if (SelectedItem == null || comboBoxItemRarity.SelectedIndex == -1)
164 | return;
165 |
166 | SelectedItem.Rarity = (byte)comboBoxItemRarity.SelectedIndex;
167 |
168 | string[] modifierList = (string[])Constants.ItemModifiers[SelectedItem.Rarity].Clone();
169 |
170 | for (int i = 0; i < modifierList.Length; i++)
171 | {
172 | modifierList[i] = modifierList[i].Replace("{0}", "*");
173 | modifierList[i] = modifierList[i].Replace("{1}", "*");
174 | }
175 |
176 | int restoreIndex = comboBoxItemPrefixId.SelectedIndex;
177 | comboBoxItemPrefixId.Items.Clear();
178 | comboBoxItemPrefixId.Items.Add("None");
179 | comboBoxItemPrefixId.Items.AddRange(modifierList);
180 | comboBoxItemPrefixId.SelectedIndex = restoreIndex;
181 | }
182 |
183 | // Adapted
184 | private void CheckBoxItemAdaptedCheckedChanged(object sender, EventArgs e)
185 | {
186 | if (SelectedItem == null)
187 | return;
188 |
189 | if (checkBoxItemAdapted.Checked)
190 | SelectedItem.Flags |= Item.ItemFlags.Adapted;
191 | else
192 | SelectedItem.Flags &= ~Item.ItemFlags.Adapted;
193 | }
194 |
195 | // Item Count
196 | private void NudItemCountValueChanged(object sender, EventArgs e)
197 | {
198 | if (SelectedSlot == null)
199 | return;
200 |
201 | SelectedSlot.Count = (int)nudItemCount.Value;
202 | }
203 |
204 | private void UpdateItemAvatar()
205 | {
206 | if (SelectedSlot.Count == 0)
207 | return;
208 |
209 | ListView listView = tabControlInventory.SelectedTab.Controls.OfType().FirstOrDefault();
210 | if (listView == null || listView.SelectedItems.Count == 0)
211 | return;
212 |
213 | ListViewItem selectedItem = listView.SelectedItems[0];
214 | Item item = (Item)selectedItem.Tag;
215 |
216 | selectedItem.Text = item.FriendlyName;
217 | selectedItem.ImageIndex = item.Type;
218 |
219 | // TODO Might be somewhat out of place
220 | nudItemHP.Value = (decimal)SelectedItem.Life;
221 | nudItemArmor.Value = (decimal)SelectedItem.Armor;
222 | nudItemResistance.Value = (decimal)SelectedItem.Resistance;
223 | nudItemTempo.Value = (decimal)SelectedItem.Tempo;
224 | nudItemCrit.Value = (decimal)SelectedItem.Critical;
225 | nudItemReg.Value = (decimal)SelectedItem.Regeneration;
226 | }
227 |
228 | private void UpdateItemControls()
229 | {
230 | if (comboBoxItemType.Items.Count == 0)
231 | comboBoxItemType.Items.AddRange(Constants.ItemTypeNames.Where(x => !String.IsNullOrEmpty(x)).ToArray());
232 |
233 | if (comboBoxItemMaterial.Items.Count == 0)
234 | comboBoxItemMaterial.Items.AddRange(Constants.ItemMaterialNames.Where(x => !String.IsNullOrEmpty(x)).ToArray());
235 |
236 | if (comboBoxItemPrefixId.Items.Count == 0)
237 | {
238 | string[] modifierList = (string[])Constants.ItemModifiers[0].Clone();
239 | //modifierList[0] = "None";
240 |
241 | for (int i = 0; i < modifierList.Length; i++)
242 | {
243 | modifierList[i] = modifierList[i].Replace("{0}", null);
244 | modifierList[i] = modifierList[i].Replace("{1}", null);
245 | }
246 |
247 | comboBoxItemPrefixId.Items.Clear();
248 | comboBoxItemPrefixId.Items.Add("None");
249 | comboBoxItemPrefixId.Items.AddRange(modifierList);
250 | }
251 |
252 | if (comboBoxItemRarity.Items.Count == 0)
253 | comboBoxItemRarity.Items.AddRange(new object[] { "Normal", "Uncommon", "Rare", "Epic", "Legendary" });
254 | }
255 | }
256 | }
257 |
--------------------------------------------------------------------------------
/Source/Forms/Editor.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using System.Linq;
4 | using System.Threading;
5 | using System.Windows.Forms;
6 | using CharacterEditor.Character;
7 |
8 | namespace CharacterEditor.Forms
9 | {
10 | public partial class Editor : Form
11 | {
12 | private readonly Database database;
13 | private Character.Character character;
14 | private DirtyWatcher dirtyWatcher;
15 | private Thread dirtyThread;
16 | private readonly FormItemStats itemStats;
17 |
18 | public Editor()
19 | {
20 | database = new Database();
21 | itemStats = new FormItemStats();
22 |
23 | InitializeComponent();
24 |
25 | labelAboutEditorName.Text += " v" + Program.Version;
26 |
27 | comboBoxPetKind.Items.Add("None");
28 | string[] pets = Constants.ItemSubtypes[(int)Constants.ItemType.Pets];
29 | comboBoxPetKind.Items.AddRange(pets.Where(x => !String.IsNullOrEmpty(x)).ToArray());
30 | }
31 |
32 | private void FormEditorShown(object sender, EventArgs e)
33 | {
34 | Text = "Character Editor v" + Program.Version;
35 | LoadCharacterDatabase();
36 |
37 | if (character == null)
38 | {
39 | Close();
40 | return;
41 | }
42 |
43 | dirtyWatcher = new DirtyWatcher(this);
44 | dirtyThread = new Thread(obj =>
45 | {
46 | bool previousDirty = !dirtyWatcher.Dirty;
47 |
48 | while (!IsDisposed)
49 | {
50 | lock (dirtyWatcher)
51 | {
52 | if (dirtyWatcher.Dirty != previousDirty && !dirtyWatcher.IgnoreDirtiness)
53 | {
54 | string title = "Character Editor v" + Program.Version + " [" + character.Name + "]";
55 |
56 | if (dirtyWatcher.Dirty)
57 | title += " *";
58 |
59 | if (InvokeRequired)
60 | Invoke(new MethodInvoker(() => Text = title));
61 | else
62 | Text = title;
63 |
64 | previousDirty = dirtyWatcher.Dirty;
65 | }
66 | else if (dirtyWatcher.IgnoreDirtiness)
67 | dirtyWatcher.Dirty = false;
68 | }
69 |
70 | Thread.Sleep(1);
71 | }
72 | });
73 |
74 | dirtyThread.Start();
75 | }
76 |
77 | private void FormEditorClosing(object sender, FormClosingEventArgs e)
78 | {
79 | if (dirtyWatcher == null || !dirtyWatcher.Dirty)
80 | return;
81 |
82 | DialogResult result = MessageBox.Show(this, "Would you like to save changes before closing?", "Character Editor",
83 | MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
84 | switch (result)
85 | {
86 | case DialogResult.Yes:
87 | SyncGuiToCharacterData();
88 | character.Save(database);
89 | break;
90 |
91 | case DialogResult.No:
92 | break;
93 |
94 | case DialogResult.Cancel:
95 | e.Cancel = true;
96 | return;
97 | }
98 |
99 | dirtyThread.Abort();
100 | }
101 |
102 | private void ButtonSaveCharacterClick(object sender, EventArgs e)
103 | {
104 | SyncGuiToCharacterData();
105 |
106 | try
107 | {
108 | if (!character.Save(database))
109 | MessageBox.Show(this, "Something went wrong trying to save your character to the database.", "Character Editor",
110 | MessageBoxButtons.OK);
111 | }
112 | catch (System.Data.SQLite.SQLiteException)
113 | {
114 | MessageBox.Show(this,
115 | "Cannot save because the database is currently read only.\r\nTry running the editor as Administrator.",
116 | "Character Editor",
117 | MessageBoxButtons.OK, MessageBoxIcon.Error);
118 | }
119 | }
120 |
121 | private void ButtonLoadNewCharacterClick(object sender, EventArgs e)
122 | {
123 | if (dirtyWatcher.Dirty)
124 | {
125 | DialogResult result = MessageBox.Show(this, "Would you like to save changes before loading a new character?", "Character Editor",
126 | MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
127 | switch (result)
128 | {
129 | case DialogResult.Yes:
130 | SyncGuiToCharacterData();
131 | character.Save(database);
132 | break;
133 |
134 | case DialogResult.No:
135 | break;
136 |
137 | case DialogResult.Cancel:
138 | return;
139 | }
140 | }
141 |
142 | LoadCharacterDatabase();
143 | }
144 |
145 | private void LoadCharacterDatabase()
146 | {
147 | Enabled = false;
148 |
149 | LoadCharacterDialog loadCharacter = new LoadCharacterDialog(database)
150 | {
151 | StartPosition = FormStartPosition.CenterParent
152 | };
153 |
154 | DialogResult result = loadCharacter.ShowDialog(this);
155 |
156 | if (result == DialogResult.OK)
157 | {
158 | tabControlInventory.TabPages.Clear();
159 | tabControlEquipment.TabPages.Clear();
160 |
161 | character = loadCharacter.SelectedCharacter;
162 |
163 | SyncCharacterDataToGui();
164 | }
165 |
166 | Enabled = character != null;
167 | }
168 |
169 | private void LinkLabelX2048LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
170 | {
171 | Process.Start("http://www.x2048.com/");
172 | }
173 |
174 | private void ButtonViewStatsClick(object sender, EventArgs e)
175 | {
176 | itemStats.Show();
177 | }
178 | }
179 | }
180 |
--------------------------------------------------------------------------------
/Source/Forms/ExceptionDialog.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace CharacterEditor.Forms
2 | {
3 | partial class ExceptionDialog
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Windows Form Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ExceptionDialog));
32 | this.labelExceptionMessage = new System.Windows.Forms.Label();
33 | this.buttonClose = new System.Windows.Forms.Button();
34 | this.textBoxExceptionInformation = new System.Windows.Forms.TextBox();
35 | this.labelStackTrace = new System.Windows.Forms.Label();
36 | this.buttonCopyToClipboard = new System.Windows.Forms.Button();
37 | this.labelHelpMessage = new System.Windows.Forms.Label();
38 | this.buttonContinue = new System.Windows.Forms.Button();
39 | this.SuspendLayout();
40 | //
41 | // labelExceptionMessage
42 | //
43 | this.labelExceptionMessage.AutoSize = true;
44 | this.labelExceptionMessage.Location = new System.Drawing.Point(12, 58);
45 | this.labelExceptionMessage.Name = "labelExceptionMessage";
46 | this.labelExceptionMessage.Size = new System.Drawing.Size(94, 13);
47 | this.labelExceptionMessage.TabIndex = 0;
48 | this.labelExceptionMessage.Text = "General Exception";
49 | //
50 | // buttonClose
51 | //
52 | this.buttonClose.Location = new System.Drawing.Point(537, 407);
53 | this.buttonClose.Name = "buttonClose";
54 | this.buttonClose.Size = new System.Drawing.Size(75, 23);
55 | this.buttonClose.TabIndex = 1;
56 | this.buttonClose.Text = "Close";
57 | this.buttonClose.UseVisualStyleBackColor = true;
58 | this.buttonClose.Click += new System.EventHandler(this.ButtonCloseClick);
59 | //
60 | // textBoxExceptionInformation
61 | //
62 | this.textBoxExceptionInformation.Location = new System.Drawing.Point(12, 87);
63 | this.textBoxExceptionInformation.Multiline = true;
64 | this.textBoxExceptionInformation.Name = "textBoxExceptionInformation";
65 | this.textBoxExceptionInformation.ReadOnly = true;
66 | this.textBoxExceptionInformation.ScrollBars = System.Windows.Forms.ScrollBars.Both;
67 | this.textBoxExceptionInformation.Size = new System.Drawing.Size(600, 314);
68 | this.textBoxExceptionInformation.TabIndex = 2;
69 | //
70 | // labelStackTrace
71 | //
72 | this.labelStackTrace.AutoSize = true;
73 | this.labelStackTrace.Location = new System.Drawing.Point(12, 71);
74 | this.labelStackTrace.Name = "labelStackTrace";
75 | this.labelStackTrace.Size = new System.Drawing.Size(69, 13);
76 | this.labelStackTrace.TabIndex = 3;
77 | this.labelStackTrace.Text = "Stack Trace:";
78 | //
79 | // buttonCopyToClipboard
80 | //
81 | this.buttonCopyToClipboard.Location = new System.Drawing.Point(337, 407);
82 | this.buttonCopyToClipboard.Name = "buttonCopyToClipboard";
83 | this.buttonCopyToClipboard.Size = new System.Drawing.Size(113, 23);
84 | this.buttonCopyToClipboard.TabIndex = 4;
85 | this.buttonCopyToClipboard.Text = "Copy to Clipboard";
86 | this.buttonCopyToClipboard.UseVisualStyleBackColor = true;
87 | this.buttonCopyToClipboard.Click += new System.EventHandler(this.ButtonCopyToClipboardClick);
88 | //
89 | // labelHelpMessage
90 | //
91 | this.labelHelpMessage.AutoSize = true;
92 | this.labelHelpMessage.Location = new System.Drawing.Point(12, 9);
93 | this.labelHelpMessage.Name = "labelHelpMessage";
94 | this.labelHelpMessage.Size = new System.Drawing.Size(393, 39);
95 | this.labelHelpMessage.TabIndex = 5;
96 | this.labelHelpMessage.Text = resources.GetString("labelHelpMessage.Text");
97 | //
98 | // buttonContinue
99 | //
100 | this.buttonContinue.Location = new System.Drawing.Point(456, 407);
101 | this.buttonContinue.Name = "buttonContinue";
102 | this.buttonContinue.Size = new System.Drawing.Size(75, 23);
103 | this.buttonContinue.TabIndex = 6;
104 | this.buttonContinue.Text = "Continue";
105 | this.buttonContinue.UseVisualStyleBackColor = true;
106 | this.buttonContinue.Click += new System.EventHandler(this.ButtonContinueClick);
107 | //
108 | // ExceptionDialog
109 | //
110 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
111 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
112 | this.ClientSize = new System.Drawing.Size(624, 442);
113 | this.Controls.Add(this.buttonContinue);
114 | this.Controls.Add(this.labelHelpMessage);
115 | this.Controls.Add(this.buttonCopyToClipboard);
116 | this.Controls.Add(this.labelStackTrace);
117 | this.Controls.Add(this.textBoxExceptionInformation);
118 | this.Controls.Add(this.buttonClose);
119 | this.Controls.Add(this.labelExceptionMessage);
120 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
121 | this.MaximizeBox = false;
122 | this.MinimizeBox = false;
123 | this.Name = "ExceptionDialog";
124 | this.Text = "Character Editor Exception Occurred";
125 | this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.FormExceptionClosed);
126 | this.ResumeLayout(false);
127 | this.PerformLayout();
128 |
129 | }
130 |
131 | #endregion
132 |
133 | private System.Windows.Forms.Label labelExceptionMessage;
134 | private System.Windows.Forms.Button buttonClose;
135 | private System.Windows.Forms.TextBox textBoxExceptionInformation;
136 | private System.Windows.Forms.Label labelStackTrace;
137 | private System.Windows.Forms.Button buttonCopyToClipboard;
138 | private System.Windows.Forms.Label labelHelpMessage;
139 | private System.Windows.Forms.Button buttonContinue;
140 | }
141 | }
--------------------------------------------------------------------------------
/Source/Forms/ExceptionDialog.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text;
3 | using System.Windows.Forms;
4 |
5 | namespace CharacterEditor.Forms
6 | {
7 | public partial class ExceptionDialog : Form
8 | {
9 | public ExceptionDialog(string humanMessage, Exception exception)
10 | {
11 | InitializeComponent();
12 |
13 | labelExceptionMessage.Text = humanMessage;
14 |
15 | StringBuilder message = new StringBuilder();
16 |
17 | message.AppendLine(exception.Message);
18 | message.AppendLine();
19 | message.AppendLine(exception.Source);
20 | message.AppendLine(exception.StackTrace);
21 |
22 | textBoxExceptionInformation.Text = message.ToString();
23 | }
24 |
25 | private void ButtonCloseClick(object sender, EventArgs e)
26 | {
27 | Application.Exit();
28 | }
29 |
30 | private void ButtonCopyToClipboardClick(object sender, EventArgs e)
31 | {
32 | Clipboard.SetText(textBoxExceptionInformation.Text);
33 | }
34 |
35 | private void ButtonContinueClick(object sender, EventArgs e)
36 | {
37 | DialogResult = DialogResult.OK;
38 | Close();
39 | }
40 |
41 | private void FormExceptionClosed(object sender, FormClosedEventArgs e)
42 | {
43 | if (DialogResult != DialogResult.OK)
44 | Application.Exit();
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/Source/Forms/ExceptionDialog.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | Character Editor has encountered a problem and may not be able to continue.
122 | You can either choose to end the program now, or attempt to continue.
123 | Be warned that attempting to continue running the program may result in data loss.
124 |
125 |
--------------------------------------------------------------------------------
/Source/Forms/FormItemStats.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace CharacterEditor.Forms
2 | {
3 | partial class FormItemStats
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Windows Form Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FormItemStats));
32 | this.labelDamage = new System.Windows.Forms.Label();
33 | this.labelAmor = new System.Windows.Forms.Label();
34 | this.labelResistance = new System.Windows.Forms.Label();
35 | this.labelTempo = new System.Windows.Forms.Label();
36 | this.labelCritical = new System.Windows.Forms.Label();
37 | this.labelRegeneration = new System.Windows.Forms.Label();
38 | this.labelHP = new System.Windows.Forms.Label();
39 | this.SuspendLayout();
40 | //
41 | // labelDamage
42 | //
43 | this.labelDamage.AutoSize = true;
44 | this.labelDamage.Location = new System.Drawing.Point(12, 22);
45 | this.labelDamage.Name = "labelDamage";
46 | this.labelDamage.Size = new System.Drawing.Size(47, 13);
47 | this.labelDamage.TabIndex = 0;
48 | this.labelDamage.Text = "Damage";
49 | //
50 | // labelAmor
51 | //
52 | this.labelAmor.AutoSize = true;
53 | this.labelAmor.Location = new System.Drawing.Point(12, 37);
54 | this.labelAmor.Name = "labelAmor";
55 | this.labelAmor.Size = new System.Drawing.Size(34, 13);
56 | this.labelAmor.TabIndex = 1;
57 | this.labelAmor.Text = "Armor";
58 | //
59 | // labelResistance
60 | //
61 | this.labelResistance.AutoSize = true;
62 | this.labelResistance.Location = new System.Drawing.Point(12, 50);
63 | this.labelResistance.Name = "labelResistance";
64 | this.labelResistance.Size = new System.Drawing.Size(60, 13);
65 | this.labelResistance.TabIndex = 2;
66 | this.labelResistance.Text = "Resistance";
67 | //
68 | // labelTempo
69 | //
70 | this.labelTempo.AutoSize = true;
71 | this.labelTempo.Location = new System.Drawing.Point(12, 63);
72 | this.labelTempo.Name = "labelTempo";
73 | this.labelTempo.Size = new System.Drawing.Size(40, 13);
74 | this.labelTempo.TabIndex = 3;
75 | this.labelTempo.Text = "Tempo";
76 | //
77 | // labelCritical
78 | //
79 | this.labelCritical.AutoSize = true;
80 | this.labelCritical.Location = new System.Drawing.Point(12, 76);
81 | this.labelCritical.Name = "labelCritical";
82 | this.labelCritical.Size = new System.Drawing.Size(38, 13);
83 | this.labelCritical.TabIndex = 4;
84 | this.labelCritical.Text = "Critical";
85 | //
86 | // labelRegeneration
87 | //
88 | this.labelRegeneration.AutoSize = true;
89 | this.labelRegeneration.Location = new System.Drawing.Point(12, 89);
90 | this.labelRegeneration.Name = "labelRegeneration";
91 | this.labelRegeneration.Size = new System.Drawing.Size(71, 13);
92 | this.labelRegeneration.TabIndex = 5;
93 | this.labelRegeneration.Text = "Regeneration";
94 | //
95 | // labelHP
96 | //
97 | this.labelHP.AutoSize = true;
98 | this.labelHP.Location = new System.Drawing.Point(15, 6);
99 | this.labelHP.Name = "labelHP";
100 | this.labelHP.Size = new System.Drawing.Size(22, 13);
101 | this.labelHP.TabIndex = 6;
102 | this.labelHP.Text = "HP";
103 | //
104 | // FormItemStats
105 | //
106 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
107 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
108 | this.ClientSize = new System.Drawing.Size(356, 215);
109 | this.Controls.Add(this.labelHP);
110 | this.Controls.Add(this.labelRegeneration);
111 | this.Controls.Add(this.labelCritical);
112 | this.Controls.Add(this.labelTempo);
113 | this.Controls.Add(this.labelResistance);
114 | this.Controls.Add(this.labelAmor);
115 | this.Controls.Add(this.labelDamage);
116 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
117 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
118 | this.MaximizeBox = false;
119 | this.MinimizeBox = false;
120 | this.Name = "FormItemStats";
121 | this.ShowInTaskbar = false;
122 | this.Text = "Item Stats";
123 | this.ResumeLayout(false);
124 | this.PerformLayout();
125 |
126 | }
127 |
128 | #endregion
129 |
130 | private System.Windows.Forms.Label labelDamage;
131 | private System.Windows.Forms.Label labelAmor;
132 | private System.Windows.Forms.Label labelResistance;
133 | private System.Windows.Forms.Label labelTempo;
134 | private System.Windows.Forms.Label labelCritical;
135 | private System.Windows.Forms.Label labelRegeneration;
136 | private System.Windows.Forms.Label labelHP;
137 | }
138 | }
--------------------------------------------------------------------------------
/Source/Forms/FormItemStats.cs:
--------------------------------------------------------------------------------
1 | using System.Windows.Forms;
2 |
3 | namespace CharacterEditor.Forms
4 | {
5 | public partial class FormItemStats : Form
6 | {
7 | public FormItemStats()
8 | {
9 | InitializeComponent();
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/Source/Forms/LoadCharacterDialog.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace CharacterEditor.Forms
2 | {
3 | partial class LoadCharacterDialog
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Windows Form Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(LoadCharacterDialog));
32 | this.buttonLoadDatabase = new System.Windows.Forms.Button();
33 | this.listBoxCharacters = new System.Windows.Forms.ListBox();
34 | this.SuspendLayout();
35 | //
36 | // buttonLoadDatabase
37 | //
38 | this.buttonLoadDatabase.Location = new System.Drawing.Point(361, 247);
39 | this.buttonLoadDatabase.Name = "buttonLoadDatabase";
40 | this.buttonLoadDatabase.Size = new System.Drawing.Size(101, 23);
41 | this.buttonLoadDatabase.TabIndex = 1;
42 | this.buttonLoadDatabase.Text = "Load Database";
43 | this.buttonLoadDatabase.UseVisualStyleBackColor = true;
44 | this.buttonLoadDatabase.Click += new System.EventHandler(this.ButtonLoadDatabaseClick);
45 | //
46 | // listBoxCharacters
47 | //
48 | this.listBoxCharacters.FormattingEnabled = true;
49 | this.listBoxCharacters.Location = new System.Drawing.Point(12, 12);
50 | this.listBoxCharacters.Name = "listBoxCharacters";
51 | this.listBoxCharacters.ScrollAlwaysVisible = true;
52 | this.listBoxCharacters.Size = new System.Drawing.Size(450, 225);
53 | this.listBoxCharacters.TabIndex = 0;
54 | this.listBoxCharacters.SelectedIndexChanged += new System.EventHandler(this.ListBoxCharactersSelectedIndexChanged);
55 | //
56 | // LoadCharacterDialog
57 | //
58 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
59 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
60 | this.ClientSize = new System.Drawing.Size(474, 282);
61 | this.Controls.Add(this.listBoxCharacters);
62 | this.Controls.Add(this.buttonLoadDatabase);
63 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
64 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
65 | this.MaximizeBox = false;
66 | this.MinimizeBox = false;
67 | this.Name = "LoadCharacterDialog";
68 | this.ShowInTaskbar = false;
69 | this.Text = "Load a Character";
70 | this.Load += new System.EventHandler(this.FormLoadCharacterLoad);
71 | this.ResumeLayout(false);
72 |
73 | }
74 |
75 | #endregion
76 |
77 | private System.Windows.Forms.Button buttonLoadDatabase;
78 | private System.Windows.Forms.ListBox listBoxCharacters;
79 | }
80 | }
81 |
82 |
--------------------------------------------------------------------------------
/Source/Forms/LoadCharacterDialog.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Windows.Forms;
5 | using Microsoft.Win32;
6 |
7 | namespace CharacterEditor.Forms
8 | {
9 | public partial class LoadCharacterDialog : Form
10 | {
11 | // TODO Backup database just in case
12 | // TODO Add character delete and add?
13 | // TODO Add character.db merging?
14 |
15 | public List Characters { get; private set; }
16 | public Character.Character SelectedCharacter { get; private set; }
17 | private readonly Database database;
18 |
19 | public LoadCharacterDialog(Database database)
20 | {
21 | Characters = new List();
22 | this.database = database;
23 | SelectedCharacter = null;
24 |
25 | InitializeComponent();
26 | }
27 |
28 | private void FormLoadCharacterLoad(object sender, EventArgs e)
29 | {
30 | string databasePath = FindCubeWorldDirectory();
31 | if (!String.IsNullOrEmpty(databasePath) && File.Exists(databasePath + @"\characters.db"))
32 | DatabaseLoad(databasePath + @"\characters.db");
33 | }
34 |
35 | private void ButtonLoadDatabaseClick(object sender, EventArgs e)
36 | {
37 | OpenFileDialog dialog = new OpenFileDialog
38 | {
39 | InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86),
40 | Filter = "Database|characters.db",
41 | CheckFileExists = true,
42 | CheckPathExists = true
43 | };
44 |
45 | DialogResult result = dialog.ShowDialog(this);
46 | if (result == DialogResult.Cancel)
47 | return;
48 |
49 | DatabaseLoad(dialog.FileName);
50 | }
51 |
52 | private void ListBoxCharactersSelectedIndexChanged(object sender, EventArgs e)
53 | {
54 | if (listBoxCharacters.SelectedIndex < 0 || listBoxCharacters.SelectedIndex >= Characters.Count)
55 | return;
56 |
57 | SelectedCharacter = Characters[listBoxCharacters.SelectedIndex];
58 | DialogResult = DialogResult.OK;
59 | Close();
60 | }
61 |
62 | private void DatabaseLoad(string filename)
63 | {
64 | try
65 | {
66 | database.Load(filename);
67 | }
68 | catch (Exception e)
69 | {
70 | ExceptionDialog exceptionDialog = new ExceptionDialog("Database appears to be corrupted!", e);
71 | exceptionDialog.ShowDialog(this);
72 |
73 | return;
74 | }
75 |
76 | Characters.Clear();
77 | listBoxCharacters.Items.Clear();
78 |
79 | try
80 | {
81 | int characterCount = database.ReadBlobByKey("num")[0];
82 | for (int i = 0; i < characterCount; ++i)
83 | {
84 | Character.Character character = new Character.Character(i);
85 | character.Load(database);
86 |
87 | Characters.Add(character);
88 | listBoxCharacters.Items.Add(character.Name);
89 | }
90 | }
91 | catch (Exception e)
92 | {
93 | ExceptionDialog exceptionDialog = new ExceptionDialog("Database appears to be corrupted!", e);
94 | exceptionDialog.ShowDialog(this);
95 |
96 | Characters.Clear();
97 | listBoxCharacters.Items.Clear();
98 | }
99 | }
100 |
101 | private string FindCubeWorldDirectory()
102 | {
103 | const string CubeWorldSaveDirectory = @"\Cube World\Save";
104 |
105 | // Check if it exists in Registry
106 | string registryPath = FindCubeWorldDirectoryFromRegistry();
107 | if (!String.IsNullOrEmpty(registryPath))
108 | return registryPath;
109 |
110 | // Check if it exists in Program Files (32bit)
111 | string programFiles = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86);
112 | if (Directory.Exists(programFiles + CubeWorldSaveDirectory))
113 | return programFiles + CubeWorldSaveDirectory;
114 |
115 | // Check if it exists on the Desktop
116 | string desktop = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
117 | if (Directory.Exists(desktop + CubeWorldSaveDirectory))
118 | return desktop + CubeWorldSaveDirectory;
119 |
120 | // Can't find it
121 | return String.Empty;
122 | }
123 |
124 | // Credit to Ricowan
125 | private string FindCubeWorldDirectoryFromRegistry()
126 | {
127 | // Look in 64bit local machine
128 | RegistryKey key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall");
129 | if (key != null)
130 | {
131 | foreach (String keyName in key.GetSubKeyNames())
132 | {
133 | RegistryKey subKey = key.OpenSubKey(keyName);
134 | if (subKey == null)
135 | continue;
136 |
137 | string displayName = (string)subKey.GetValue("DisplayName");
138 |
139 | if (!String.IsNullOrEmpty(displayName) && displayName.StartsWith("Cube World"))
140 | return subKey.GetValue("InstallLocation") + @"\Save";
141 | }
142 | }
143 |
144 | // Look in 32bit local machine
145 | key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall");
146 | if (key != null)
147 | {
148 | foreach (String keyName in key.GetSubKeyNames())
149 | {
150 | RegistryKey subKey = key.OpenSubKey(keyName);
151 | if (subKey == null)
152 | continue;
153 |
154 | string displayName = (string)subKey.GetValue("DisplayName");
155 |
156 | if (!String.IsNullOrEmpty(displayName) && displayName.StartsWith("Cube World"))
157 | return subKey.GetValue("InstallLocation") + @"\Save";
158 | }
159 | }
160 |
161 | // Look in CurrentUser
162 | key = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall");
163 | if (key != null)
164 | {
165 | foreach (string keyName in key.GetSubKeyNames())
166 | {
167 | RegistryKey subKey = key.OpenSubKey(keyName);
168 | if (subKey == null)
169 | continue;
170 |
171 | string displayName = (string)subKey.GetValue("DisplayName");
172 |
173 | if (!String.IsNullOrEmpty(displayName) && displayName.StartsWith("Cube World"))
174 | return subKey.GetValue("InstallLocation") + @"\Save";
175 | }
176 | }
177 |
178 | // Cannot find it
179 | return String.Empty;
180 | }
181 | }
182 | }
183 |
--------------------------------------------------------------------------------
/Source/Forms/SafeNumericUpDown.cs:
--------------------------------------------------------------------------------
1 | using System.Windows.Forms;
2 |
3 | namespace CharacterEditor.Forms
4 | {
5 | public class SafeNumericUpDown : NumericUpDown
6 | {
7 | public new decimal Value
8 | {
9 | get
10 | {
11 | return base.Value;
12 | }
13 |
14 | set
15 | {
16 | if (value < Minimum)
17 | base.Value = Minimum;
18 | else if (value > Maximum)
19 | base.Value = Maximum;
20 | else
21 | base.Value = value;
22 | }
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Source/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using System.Windows.Forms;
4 | using CharacterEditor.Forms;
5 |
6 | namespace CharacterEditor
7 | {
8 | public static class Program
9 | {
10 | public const string Version = "0.4c";
11 |
12 | [STAThread]
13 | public static void Main()
14 | {
15 | Application.EnableVisualStyles();
16 | Application.SetCompatibleTextRenderingDefault(false);
17 |
18 | #if !DEBUG
19 | AppDomain.CurrentDomain.UnhandledException += (sender, args) =>
20 | {
21 | Exception exception = (Exception)args.ExceptionObject;
22 |
23 | ExceptionDialog formException = new ExceptionDialog("An unrecoverable problem has occurred!", exception);
24 | formException.ShowDialog();
25 |
26 | if (args.IsTerminating)
27 | Application.Exit();
28 | };
29 |
30 | if (Process.GetProcessesByName("Cube").Length > 0)
31 | {
32 | MessageBox.Show("Please close Cube World before running the Character Editor.", "Character Editor", MessageBoxButtons.OK, MessageBoxIcon.Error);
33 | return;
34 | }
35 | #endif
36 |
37 | Application.Run(new Editor());
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Source/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 |
4 | // General Information about an assembly is controlled through the following
5 | // set of attributes. Change these attribute values to modify the information
6 | // associated with an assembly.
7 | [assembly: AssemblyTitle("CharacterEditor")]
8 | [assembly: AssemblyDescription("Character Editor for Cube World")]
9 | [assembly: AssemblyConfiguration("")]
10 | [assembly: AssemblyCompany("x2048")]
11 | [assembly: AssemblyProduct("CharacterEditor")]
12 | [assembly: AssemblyCopyright("Copyright © x2048 2013")]
13 | [assembly: AssemblyTrademark("")]
14 | [assembly: AssemblyCulture("")]
15 |
16 | // Setting ComVisible to false makes the types in this assembly not visible
17 | // to COM components. If you need to access a type in this assembly from
18 | // COM, set the ComVisible attribute to true on that type.
19 | [assembly: ComVisible(false)]
20 |
21 | // The following GUID is for the ID of the typelib if this project is exposed to COM
22 | [assembly: Guid("f35557de-dcc5-49e9-af49-ddde49bb1302")]
23 |
24 | // Version information for an assembly consists of the following four values:
25 | //
26 | // Major Version
27 | // Minor Version
28 | // Build Number
29 | // Revision
30 | //
31 | // You can specify all the values or you can default the Build and Revision Numbers
32 | // by using the '*' as shown below:
33 | // [assembly: AssemblyVersion("1.0.*")]
34 | [assembly: AssemblyVersion("1.0.0.0")]
35 | [assembly: AssemblyFileVersion("1.0.0.0")]
36 |
--------------------------------------------------------------------------------
/Source/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.18052
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace CharacterEditor.Properties {
12 | using System;
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resources() {
33 | }
34 |
35 | ///
36 | /// Returns the cached ResourceManager instance used by this class.
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | internal static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("CharacterEditor.Properties.Resources", typeof(Resources).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// Overrides the current thread's CurrentUICulture property for all
51 | /// resource lookups using this strongly typed resource class.
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | internal static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 |
63 | ///
64 | /// Looks up a localized resource of type System.Drawing.Bitmap.
65 | ///
66 | internal static System.Drawing.Bitmap x2048 {
67 | get {
68 | object obj = ResourceManager.GetObject("x2048", resourceCulture);
69 | return ((System.Drawing.Bitmap)(obj));
70 | }
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/Source/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 |
122 | ..\Resources\x2048.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
123 |
124 |
--------------------------------------------------------------------------------
/Source/Resources/x2048.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DatZach/CharacterEditor/974b2b9e9bd6756eb68b2a8ba349eac97ff67354/Source/Resources/x2048.png
--------------------------------------------------------------------------------
/Source/Utility.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Drawing;
3 | using System.IO;
4 | using System.Text;
5 |
6 | namespace CharacterEditor
7 | {
8 | public static class Utility
9 | {
10 | public static int GoofyIndex(int index, string[] list)
11 | {
12 | int result = index;
13 |
14 | for (int i = 0, j = 0; i <= index; ++i, ++j)
15 | {
16 | if (j >= list.Length)
17 | break;
18 |
19 | while (String.IsNullOrEmpty(list[j]))
20 | {
21 | ++result;
22 | ++j;
23 | }
24 | }
25 |
26 | return result;
27 | }
28 |
29 | public static int NormalizeIndex(int index, string[] list)
30 | {
31 | int result = 0;
32 |
33 | for (int i = 0; i < index; ++i)
34 | {
35 | if (i >= list.Length)
36 | return 0;
37 |
38 | if (String.IsNullOrEmpty(list[i]))
39 | continue;
40 |
41 | ++result;
42 | }
43 |
44 | return result;
45 | }
46 |
47 | public static Color FromAbgr(int abgr)
48 | {
49 | long value = abgr & 0xFF00FF00;
50 | value |= (abgr & 0x000000FFL) << 16;
51 | value |= (abgr & 0x00FF0000L) >> 16;
52 |
53 | return Color.FromArgb((int)(value | 0xFF000000));
54 | }
55 |
56 | public static int ToAbgr(Color color)
57 | {
58 | int argb = color.ToArgb();
59 | long value = argb & 0xFF00FF00;
60 | value |= (argb & 0x000000FFL) << 16;
61 | value |= (argb & 0x00FF0000L) >> 16;
62 |
63 | return (int)(value | 0xFF000000);
64 | }
65 |
66 | public static void Skip(this BinaryReader reader, int count)
67 | {
68 | reader.BaseStream.Seek(count, SeekOrigin.Current);
69 | }
70 |
71 | public static void Skip(this BinaryWriter writer, int count)
72 | {
73 | writer.Write(new byte[count]);
74 | }
75 |
76 | public static string ReadLongString(this BinaryReader reader)
77 | {
78 | int length = reader.ReadInt32();
79 | byte[] value = new byte[length];
80 |
81 | reader.Read(value, 0, length);
82 |
83 | return Encoding.ASCII.GetString(value);
84 | }
85 |
86 | public static int ReadIntAtOffset(this BinaryReader reader, long position)
87 | {
88 | long previousPosition = reader.BaseStream.Position;
89 | reader.BaseStream.Position = position;
90 |
91 | int value = reader.ReadInt32();
92 |
93 | reader.BaseStream.Position = previousPosition;
94 |
95 | return value;
96 | }
97 |
98 | public static float ReadSingleAtOffset(this BinaryReader reader, long position)
99 | {
100 | long previousPosition = reader.BaseStream.Position;
101 | reader.BaseStream.Position = position;
102 |
103 | float value = reader.ReadSingle();
104 |
105 | reader.BaseStream.Position = previousPosition;
106 |
107 | return value;
108 | }
109 |
110 | public static void WriteLongString(this BinaryWriter writer, string value)
111 | {
112 | writer.Write(value.Length);
113 | writer.Write(Encoding.ASCII.GetBytes(value));
114 | }
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/Source/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Source/icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DatZach/CharacterEditor/974b2b9e9bd6756eb68b2a8ba349eac97ff67354/Source/icon.ico
--------------------------------------------------------------------------------
/TODO.txt:
--------------------------------------------------------------------------------
1 | [ ] Fix items
2 | [ ] Modifiers
3 | [ ] Item stats
4 | [ ] Recipes
5 | [ ] "Advanced" mode
6 | [ ] Any entity as a pet
7 | [ ] Auto recipe/level scaling
8 | [ ] Database backups
9 | [ ] Model rendering
--------------------------------------------------------------------------------
/characterformat.txt:
--------------------------------------------------------------------------------
1 | Charater Format
2 |
3 | Compressed Stream
4 | {
5 | [ Padding is aligned to 8 bytes ]
6 |
7 | 00 4 Entity ID (Always 1)
8 | 04 8 X Position
9 | 0C 8 Y Position
10 | 14 8 Z Position
11 | 1C 4 Pitch
12 | 20 4 Roll
13 | 24 4 Yaw
14 | 28 4 Health (Float)
15 | 2C 4 Experience
16 | 30 4 Level
17 | 34 1 Class
18 | 35 1 Specialization
19 | 36 4 Unknown (Stored at [PlayerBase + 1198h])
20 | 3A 4 Unknown (Stored at [PlayerBase + 119Ch])
21 |
22 | [ Equipment ]
23 | { Unused, Neck, Chest, Feet, Hands, Shoulder, Left Weapon, Right Weapon,
24 | Left Ring, Right Ring, Light, Special, Pet }
25 | For 13
26 | {
27 |
-
28 | }
29 |
30 | 00 4 Length { Name }
31 | 04 4 Race
32 | 08 1 Gender (0 = Male, 1 = Female)
33 | 09 3 Padding
34 | 0C 4 Face Index
35 | 10 4 Hair Index
36 | 14 1 Hair R [ Stored as bytes in the structure ]
37 | 15 1 Hair G
38 | 16 1 Hair B
39 | 17 1 Padding
40 | 18 4 InventoryCount
41 | For InventoryCount
42 | {
43 | 00 4 SlotCount
44 | For SlotCount
45 | {
46 |
-
47 | }
48 | }
49 |
50 | 00 4 Coins (Split into bronze, silver, gold ingame)
51 | 04 4 Platinum Coins
52 |
53 | [ Crafting recipes ]
54 | 08 4 Count
55 | For Count
56 | {
57 |
-
58 | }
59 |
60 | [ Worlds ]
61 | 00 4 Count
62 | For Count
63 | {
64 | 00 4 Seed
65 | 04 4 Length { Name }
66 | 08 8 X
67 | 10 8 Z
68 | 18 8 Y
69 | }
70 |
71 | 00 4 LastWorldSeed
72 | 04 4 Length { String }
73 |
74 | [ Skills ]
75 |
76 | 00 4 Mana Cubes
77 | 04 4 Skill Count
78 | 08 4 Pet Master Skill Level
79 | 0C 4 Pet Riding Level
80 | 10 4 Climbing Skill Level
81 | 14 4 Hang Gliding Skill Level
82 | 18 4 Swimming Skill Level
83 | 1C 4 Sailing Skill Level
84 | 20 4 Tier 1 Skill Level
85 | 24 4 Tier 2 Skill Level
86 | 28 4 Tier 3 Skill Level
87 |
88 | [ I think that these are two extra skills to be added in a future update ]
89 | 2C 4 Unknown Skill? (Always 0)
90 | 30 4 Unknown Skill? (Always 0)
91 | }
92 |
93 |
-
94 | {
95 | 00 1 Type
96 | 01 1 Subtype
97 | 02 2 Padding
98 | 04 2 Modifier
99 | 06 2 Padding
100 | 08 1 Recipe Type
101 | 09 3 Padding
102 | 0C 1 Rarity
103 | 0D 1 Material
104 | 0E 1 Item Flags
105 | 0F 1 Padding
106 | 10 2 Level
107 | 12 2 Padding
108 |
109 | [ Item Attributes ]
110 | For 32
111 | {
112 | 00 1 X Offset
113 | 01 1 Y Offset
114 | 02 1 Z Offset
115 | 03 1 Material
116 | 04 2 Level
117 | 06 2 Padding
118 | }
119 |
120 | 00 4 Attributes Used
121 | }
122 |
123 | === Notes on Player Name ===
124 | Technicaly the name can be signed int max characters long, however,
125 | the game has some routine that verifies the names are less than
126 | or equal to 15 character and some other small attributes and
127 | panics if it isn't.
128 |
129 | === Notes on Pet Names ===
130 | Pet names can be 15 characters long and are stored as item attributes,
131 | the material byte being used as the ASCII character.
132 |
--------------------------------------------------------------------------------