MagicBot
2 years ago
110 changed files with 3542 additions and 1088 deletions
@ -1,12 +1,65 @@
@@ -1,12 +1,65 @@
|
||||
``` |
||||
• ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄ |
||||
·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪ |
||||
▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄ |
||||
██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌ |
||||
▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪ |
||||
|
||||
``` |
||||
• ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄ |
||||
·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪ |
||||
▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄ |
||||
██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌ |
||||
▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪ |
||||
Magicbane Emulator Project © 2013 - 2022 |
||||
www.magicbane.com |
||||
``` |
||||
|
||||
This repository holds the source code for mbEditorPro along with other tooling and data required to give every MagicBox administrator the ability to fully modify the game as they see fit. |
||||
# mbEditorPro v 2.0 |
||||
|
||||
![Example Output](https://cdn.discordapp.com/attachments/399623779531096074/1029063849640468550/unknown.png) |
||||
|
||||
Team Magicbane presents to the community technology allowing MagicBox administrators<br> |
||||
to fully modify their game using nothing more than notepad.exe. <br> |
||||
|
||||
- Tool directly converts Shadowbane .cache files to and from a high fidelity pure JSON representation. |
||||
- Enumerations are used throughout hiding from the user ugly signed ulong values. |
||||
- Written in Python and open-source allowing modification and extension with ease. |
||||
- Want to raise all weapon damage by x%; Just modify item values as they are being parsed! |
||||
|
||||
The tool built with Edltirch Technologies parses all Shadowbane .cache files giving the user complete control over the game<br> |
||||
|
||||
Team Magicbane aims to deliver you the best crackhead free MMO technology around; all for free! |
||||
|
||||
### Usage: |
||||
``` |
||||
mbEditorPro.py unpack cobjects |
||||
mbEditorPro.py unpack all |
||||
``` |
||||
JSON output will be in a folder **ARCANE DUMP** <br> |
||||
|
||||
``` |
||||
mbEditorPro.py pack textures |
||||
mbEditorPro.py pack all |
||||
``` |
||||
|
||||
New binary cache file will be built from the JSON and output in the current directory. <br>> |
||||
|
||||
> note: Unpacked data from a 2008 cache file is available in the Data repo. Build a new cache file right out of the box. |
||||
|
||||
### Limitations |
||||
|
||||
Hirelings, ZoneEvents and Mobile Inventory are not parsed or written as there were no <br> |
||||
examples in the .cache files to begin with. The game does seem to support them, however. |
||||
|
||||
### JSON |
||||
|
||||
The tool generating pure JSON has the following benefits: |
||||
|
||||
- It's ubiquitous and the tooling is mature. The standard interop exchange format. |
||||
- Human and machine-readable. |
||||
- Ease of importing into MySQL or other databases. |
||||
- Use as an intermediate representation to build a GUI World Editor or FBX importer. |
||||
|
||||
### Future |
||||
|
||||
mbEditorPro will be the cornerstone of Magicbane's data project. The Team's goal is threefold: |
||||
|
||||
- Ship MagicBox 1.5 with both Aerynth and Vorringia mapsets available. |
||||
- Integrate Magicbane's wpak extractor technology into the tool<br> |
||||
|
||||
|
||||
|
||||
|
@ -1,7 +0,0 @@
@@ -1,7 +0,0 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄ |
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪ |
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄ |
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌ |
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪ |
||||
# Magicbane Emulator Project © 2013 - 2022 |
||||
# www.magicbane.com |
@ -1,7 +0,0 @@
@@ -1,7 +0,0 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄ |
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪ |
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄ |
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌ |
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪ |
||||
# Magicbane Emulator Project © 2013 - 2022 |
||||
# www.magicbane.com |
@ -1,7 +0,0 @@
@@ -1,7 +0,0 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄ |
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪ |
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄ |
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌ |
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪ |
||||
# Magicbane Emulator Project © 2013 - 2022 |
||||
# www.magicbane.com |
@ -1,23 +0,0 @@
@@ -1,23 +0,0 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄ |
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪ |
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄ |
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌ |
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪ |
||||
# Magicbane Emulator Project © 2013 - 2022 |
||||
# www.magicbane.com |
||||
|
||||
INVENTORY_TYPE_GOLD = 1 |
||||
INVENTORY_TYPE_ITEM = 2 |
||||
INVENTORY_TYPE_BOOTYTABLE = 3 |
||||
|
||||
INVENTORY_TYPE_TO_STRING = { |
||||
INVENTORY_TYPE_GOLD: 'GOLD', |
||||
INVENTORY_TYPE_ITEM: 'ITEM', |
||||
INVENTORY_TYPE_BOOTYTABLE: 'BOOTYTABLE', |
||||
} |
||||
|
||||
STRING_TO_INVENTORY_TYPE = { |
||||
'GOLD': INVENTORY_TYPE_GOLD, |
||||
'ITEM': INVENTORY_TYPE_ITEM, |
||||
'BOOTYTABLE': INVENTORY_TYPE_BOOTYTABLE, |
||||
} |
@ -1,41 +0,0 @@
@@ -1,41 +0,0 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄ |
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪ |
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄ |
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌ |
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪ |
||||
# Magicbane Emulator Project © 2013 - 2022 |
||||
# www.magicbane.com |
||||
|
||||
import glob |
||||
import os |
||||
|
||||
from arcane.util.hasher import hash_string |
||||
|
||||
_STRING_TO_HASH = {} |
||||
_HASH_TO_STRING = {} |
||||
|
||||
|
||||
def load_files(): |
||||
directory = os.path.dirname(__file__) |
||||
|
||||
for filepath in glob.glob(os.path.join(directory, '*.txt')): |
||||
lines = list(map(lambda s: s.strip(), open(filepath).readlines())) |
||||
|
||||
_STRING_TO_HASH.update({ |
||||
s: hash_string(s) for s in lines |
||||
}) |
||||
|
||||
_HASH_TO_STRING.update({ |
||||
hash_string(s): s for s in lines |
||||
}) |
||||
|
||||
|
||||
def string_to_hash(s): |
||||
return _STRING_TO_HASH.get(s, s) |
||||
|
||||
|
||||
def hash_to_string(h): |
||||
return _HASH_TO_STRING.get(h, h) |
||||
|
||||
|
||||
load_files() |
@ -1,38 +0,0 @@
@@ -1,38 +0,0 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄ |
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪ |
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄ |
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌ |
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪ |
||||
# Magicbane Emulator Project © 2013 - 2022 |
||||
# www.magicbane.com |
||||
|
||||
MOBILE = 1 |
||||
BANKER = 2 |
||||
SHOPKEEPER = 3 |
||||
TRAINER = 4 |
||||
MERCHANT = 8 |
||||
HIRELING = 9 |
||||
PET = 10 |
||||
MINION = 11 |
||||
|
||||
MOBILE_TO_STRING = { |
||||
MOBILE: 'MOBILE', |
||||
BANKER: 'BANKER', |
||||
SHOPKEEPER: 'SHOPKEEPER', |
||||
TRAINER: 'TRAINER', |
||||
MERCHANT: 'MERCHANT', |
||||
HIRELING: 'HIRELING', |
||||
PET: 'PET', |
||||
MINION: 'MINION', |
||||
} |
||||
|
||||
STRING_TO_MOBILE = { |
||||
'MOBILE': MOBILE, |
||||
'BANKER': BANKER, |
||||
'SHOPKEEPER': SHOPKEEPER, |
||||
'TRAINER': TRAINER, |
||||
'MERCHANT': MERCHANT, |
||||
'HIRELING': HIRELING, |
||||
'PET': PET, |
||||
'MINION': MINION, |
||||
} |
@ -1,23 +0,0 @@
@@ -1,23 +0,0 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄ |
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪ |
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄ |
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌ |
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪ |
||||
# Magicbane Emulator Project © 2013 - 2022 |
||||
# www.magicbane.com |
||||
|
||||
PROP = 5 |
||||
CITY = 6 |
||||
CONTAINER = 7 |
||||
|
||||
PROP_TO_STRING = { |
||||
PROP: 'PROP', |
||||
CITY: 'CITY', |
||||
CONTAINER: 'CONTAINER', |
||||
} |
||||
|
||||
STRING_TO_PROP = { |
||||
'PROP': PROP, |
||||
'CITY': CITY, |
||||
'CONTAINER': CONTAINER, |
||||
} |
@ -1,35 +0,0 @@
@@ -1,35 +0,0 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄ |
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪ |
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄ |
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌ |
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪ |
||||
# Magicbane Emulator Project © 2013 - 2022 |
||||
# www.magicbane.com |
||||
|
||||
PEAKED = 1 |
||||
RIDGED = 2 |
||||
ROLLING = 3 |
||||
MESA = 5 |
||||
PLANAR = 4 |
||||
MESH = 6 |
||||
TARGA = 7 |
||||
|
||||
TERRAIN_TYPE_TO_STRING = { |
||||
PEAKED: 'PEAKED', |
||||
RIDGED: 'RIDGED', |
||||
ROLLING: 'ROLLING', |
||||
MESA: 'MESA', |
||||
PLANAR: 'PLANAR', |
||||
MESH: 'MESH', |
||||
TARGA: 'TARGA', |
||||
} |
||||
|
||||
STRING_TO_TERRAIN_TYPE = { |
||||
'PEAKED': PEAKED, |
||||
'RIDGED': RIDGED, |
||||
'ROLLING': ROLLING, |
||||
'MESA': MESA, |
||||
'PLANAR': PLANAR, |
||||
'MESH': MESH, |
||||
'TARGA': TARGA, |
||||
} |
@ -1,62 +0,0 @@
@@ -1,62 +0,0 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄ |
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪ |
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄ |
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌ |
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪ |
||||
# Magicbane Emulator Project © 2013 - 2022 |
||||
# www.magicbane.com |
||||
|
||||
ELLIPTICAL = 0 |
||||
RECTANGULAR = 1 |
||||
|
||||
ZONE_TO_STRING = { |
||||
ELLIPTICAL: 'ELLIPTICAL', |
||||
RECTANGULAR: 'RECTANGULAR', |
||||
} |
||||
|
||||
STRING_TO_ZONE = { |
||||
'ELLIPTICAL': ELLIPTICAL, |
||||
'RECTANGULAR': RECTANGULAR, |
||||
} |
||||
|
||||
GLOBAL = 0 |
||||
LOCAL = 1 |
||||
|
||||
TILECOORD_TO_STRING = { |
||||
GLOBAL: 'GLOBAL', |
||||
LOCAL: 'LOCAL', |
||||
} |
||||
|
||||
STRING_TO_TILECOORD = { |
||||
'GLOBAL': GLOBAL, |
||||
'LOCAL': LOCAL, |
||||
} |
||||
|
||||
ADJACENT = 0 |
||||
RANDOM = 1 |
||||
|
||||
PATTERN_TO_STRING = { |
||||
ADJACENT: 'ADJACENT', |
||||
RANDOM: 'RANDOM', |
||||
} |
||||
|
||||
STRING_TO_PATTERN = { |
||||
'ADJACENT': ADJACENT, |
||||
'RANDOM': RANDOM, |
||||
} |
||||
|
||||
PARENT = 0 |
||||
WORLD = 1 |
||||
SELF = 2 |
||||
|
||||
SEALEVEL_TO_STRING = { |
||||
PARENT: 'PARENT', |
||||
WORLD: 'WORLD', |
||||
SELF: 'SELF', |
||||
} |
||||
|
||||
STRING_TO_SEALEVEL = { |
||||
'PARENT': PARENT, |
||||
'WORLD': WORLD, |
||||
'SELF': SELF, |
||||
} |
@ -1,29 +0,0 @@
@@ -1,29 +0,0 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄ |
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪ |
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄ |
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌ |
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪ |
||||
# Magicbane Emulator Project © 2013 - 2022 |
||||
# www.magicbane.com |
||||
|
||||
from arcane.util import ResStream |
||||
from .ArcStructureObject import ArcStructureObject |
||||
|
||||
|
||||
class ArcAssetStructureObject(ArcStructureObject): |
||||
def load_binary(self, stream: ResStream): |
||||
super().load_binary(stream) |
||||
self.asset_structure_template_id = stream.read_qword() |
||||
|
||||
def save_binary(self, stream: ResStream): |
||||
super().save_binary(stream) |
||||
stream.write_qword(self.asset_structure_template_id) |
||||
|
||||
def load_json(self, data): |
||||
super().load_json(data) |
||||
self.asset_structure_template_id = data['asset_structure_template_id'] |
||||
|
||||
def save_json(self): |
||||
data = super().save_json() |
||||
data['asset_structure_template_id'] = self.asset_structure_template_id |
||||
return data |
@ -1,21 +0,0 @@
@@ -1,21 +0,0 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄ |
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪ |
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄ |
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌ |
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪ |
||||
# Magicbane Emulator Project © 2013 - 2022 |
||||
# www.magicbane.com |
||||
|
||||
from .ArcAssetStructureObject import ArcAssetStructureObject |
||||
from .ArcCityAssetTemplate import ArcCityAssetTemplate |
||||
from .ArcCombatObj import ArcCombatObj, ArcCharacter |
||||
from .ArcContainerObject import ArcContainerObject |
||||
from .ArcDeed import ArcDeed |
||||
from .ArcDoorObject import ArcDoorObject |
||||
from .ArcDungeonUnitObject import ArcDungeonUnitObject, ArcDungeonExitObject, ArcDungeonStairObject |
||||
from .ArcItem import ArcItem |
||||
from .ArcKey import ArcKey |
||||
from .ArcObj import ArcObj |
||||
from .ArcRune import ArcRune |
||||
from .ArcStaticObject import ArcStaticObject |
||||
from .ArcStructureObject import ArcStructureObject |
@ -1,40 +0,0 @@
@@ -1,40 +0,0 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄ |
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪ |
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄ |
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌ |
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪ |
||||
# Magicbane Emulator Project © 2013 - 2022 |
||||
# www.magicbane.com |
||||
from collections import OrderedDict |
||||
|
||||
from arcane.enums.hashes import hash_to_string, string_to_hash |
||||
from arcane.util import ResStream |
||||
|
||||
|
||||
class DiscRequired: |
||||
def load_binary(self, stream: ResStream): |
||||
discs = stream.read_dword() |
||||
self.disc_restrict = stream.read_bool() |
||||
self.disc_values = [ |
||||
stream.read_dword() for _ in range(discs) |
||||
] |
||||
|
||||
def save_binary(self, stream: ResStream): |
||||
stream.write_dword(len(self.disc_values)) |
||||
stream.write_bool(self.disc_restrict) |
||||
for disc in self.disc_values: |
||||
stream.write_dword(disc) |
||||
|
||||
def load_json(self, data): |
||||
self.disc_restrict = data['restrict'] |
||||
self.disc_values = [] |
||||
for disc in data['disces']: |
||||
self.disc_values.append(string_to_hash(disc)) |
||||
|
||||
def save_json(self): |
||||
data = OrderedDict() |
||||
data['restrict'] = self.disc_restrict |
||||
data['disces'] = [] |
||||
for disc in self.disc_values: |
||||
data['disces'].append(hash_to_string(disc)) |
||||
return data |
@ -1,40 +0,0 @@
@@ -1,40 +0,0 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄ |
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪ |
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄ |
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌ |
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪ |
||||
# Magicbane Emulator Project © 2013 - 2022 |
||||
# www.magicbane.com |
||||
from collections import OrderedDict |
||||
|
||||
from arcane.enums.hashes import hash_to_string, string_to_hash |
||||
from arcane.util import ResStream |
||||
|
||||
|
||||
class RaceRequired: |
||||
def load_binary(self, stream: ResStream): |
||||
races = stream.read_dword() |
||||
self.race_restrict = stream.read_bool() |
||||
self.race_values = [ |
||||
stream.read_dword() for _ in range(races) |
||||
] |
||||
|
||||
def save_binary(self, stream: ResStream): |
||||
stream.write_dword(len(self.race_values)) |
||||
stream.write_bool(self.race_restrict) |
||||
for race in self.race_values: |
||||
stream.write_dword(race) |
||||
|
||||
def load_json(self, data): |
||||
self.race_restrict = data['restrict'] |
||||
self.race_values = [] |
||||
for race in data['racees']: |
||||
self.race_values.append(string_to_hash(race)) |
||||
|
||||
def save_json(self): |
||||
data = OrderedDict() |
||||
data['restrict'] = self.race_restrict |
||||
data['racees'] = [] |
||||
for race in self.race_values: |
||||
data['racees'].append(hash_to_string(race)) |
||||
return data |
@ -1,7 +0,0 @@
@@ -1,7 +0,0 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄ |
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪ |
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄ |
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌ |
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪ |
||||
# Magicbane Emulator Project © 2013 - 2022 |
||||
# www.magicbane.com |
@ -1,10 +0,0 @@
@@ -1,10 +0,0 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄ |
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪ |
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄ |
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌ |
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪ |
||||
# Magicbane Emulator Project © 2013 - 2022 |
||||
# www.magicbane.com |
||||
|
||||
from .ArcFileCache import load_cache_file, save_cache_file |
||||
from .ResStream import ResStream |
@ -1,39 +0,0 @@
@@ -1,39 +0,0 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄ |
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪ |
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄ |
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌ |
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪ |
||||
# Magicbane Emulator Project © 2013 - 2022 |
||||
# www.magicbane.com |
||||
|
||||
from collections import OrderedDict |
||||
|
||||
from arcane.util import ResStream |
||||
|
||||
|
||||
class ArcDungeonInfo: |
||||
def load_binary(self, stream: ResStream): |
||||
self.dungeon_template_id = stream.read_qword() |
||||
self.dungeon_unkown = stream.read_qword() |
||||
self.dungeon_spawn_location = stream.read_tuple() |
||||
self.dungeon_y_offset = stream.read_float() |
||||
|
||||
def save_binary(self, stream: ResStream): |
||||
stream.write_qword(self.dungeon_template_id) |
||||
stream.write_qword(self.dungeon_unkown) |
||||
stream.write_tuple(self.dungeon_spawn_location) |
||||
stream.write_float(self.dungeon_y_offset) |
||||
|
||||
def save_json(self): |
||||
data = OrderedDict() |
||||
data['dungeon_template_id'] = self.dungeon_template_id |
||||
data['dungeon_unkown'] = self.dungeon_unkown |
||||
data['dungeon_spawn_location'] = self.dungeon_spawn_location |
||||
data['dungeon_y_offset'] = self.dungeon_y_offset |
||||
return data |
||||
|
||||
def load_json(self, data): |
||||
self.dungeon_template_id = data['dungeon_template_id'] |
||||
self.dungeon_unkown = data['dungeon_unkown'] |
||||
self.dungeon_spawn_location = data['dungeon_spawn_location'] |
||||
self.dungeon_y_offset = data['dungeon_y_offset'] |
@ -1,9 +0,0 @@
@@ -1,9 +0,0 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄ |
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪ |
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄ |
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌ |
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪ |
||||
# Magicbane Emulator Project © 2013 - 2022 |
||||
# www.magicbane.com |
||||
|
||||
from .ArcZone import ArcZone |
@ -1,20 +0,0 @@
@@ -1,20 +0,0 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄ |
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪ |
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄ |
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌ |
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪ |
||||
# Magicbane Emulator Project © 2013 - 2022 |
||||
# www.magicbane.com |
||||
|
||||
from arcane.util import ResStream |
||||
from .HirelingInfo import HirelingInfo |
||||
|
||||
|
||||
class MinionInfo(HirelingInfo): |
||||
def __init__(self): |
||||
super().__init__() |
||||
self.minion_info_u = None |
||||
|
||||
def load_binary(self, stream: ResStream): |
||||
super().load_binary(stream) |
||||
self.minion_info_u = stream.read_string() |
@ -1,7 +0,0 @@
@@ -1,7 +0,0 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄ |
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪ |
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄ |
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌ |
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪ |
||||
# Magicbane Emulator Project © 2013 - 2022 |
||||
# www.magicbane.com |
@ -1,223 +0,0 @@
@@ -1,223 +0,0 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄ |
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪ |
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄ |
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌ |
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪ |
||||
# Magicbane Emulator Project © 2013 - 2022 |
||||
# www.magicbane.com |
||||
|
||||
import glob |
||||
import json |
||||
import os |
||||
import sys |
||||
|
||||
from arcane.enums.arc_object import * |
||||
from arcane.objects import * |
||||
from arcane.util import * |
||||
from arcane.zones import * |
||||
|
||||
DUMP_DIRECTORY = 'ARCANE_DUMP' |
||||
WORKING_DIRECTORY = os.path.dirname(__file__) |
||||
TARGET_DIRECTORY = os.path.join(WORKING_DIRECTORY, DUMP_DIRECTORY) |
||||
COBJECTS_DIRECTORY = os.path.join(TARGET_DIRECTORY, 'COBJECTS') |
||||
CZONE_DIRECTORY = os.path.join(TARGET_DIRECTORY, 'CZONE') |
||||
COBJECTS_MAGIC = 0x434c4e54 |
||||
|
||||
COBJECTS_MAP = { |
||||
OBJECT_TYPE_LIGHT: ArcObj, |
||||
OBJECT_TYPE_DOOR: ArcDoorObject, |
||||
OBJECT_TYPE_STATIC: ArcStaticObject, |
||||
OBJECT_TYPE_STRUCTURE: ArcStructureObject, |
||||
OBJECT_TYPE_ASSETSTRUCTURE: ArcAssetStructureObject, |
||||
OBJECT_TYPE_DUNGEONUNIT: ArcDungeonUnitObject, |
||||
OBJECT_TYPE_DUNGEONEXIT: ArcDungeonExitObject, |
||||
OBJECT_TYPE_DUNGEONSTAIR: ArcDungeonStairObject, |
||||
OBJECT_TYPE_ITEM: ArcItem, |
||||
OBJECT_TYPE_PLAYER: ArcCharacter, |
||||
OBJECT_TYPE_MOBILE: ArcCharacter, |
||||
OBJECT_TYPE_RUNE: ArcRune, |
||||
OBJECT_TYPE_CONTAINER: ArcContainerObject, |
||||
OBJECT_TYPE_DEED: ArcDeed, |
||||
OBJECT_TYPE_KEY: ArcKey, |
||||
OBJECT_TYPE_ASSET: ArcCityAssetTemplate, |
||||
OBJECT_TYPE_OBJECT: ArcObj, |
||||
} |
||||
|
||||
|
||||
def init_cobjects(): |
||||
for type in COBJECTS_MAP: |
||||
directory_path = os.path.join(COBJECTS_DIRECTORY, OBJECT_TYPE_TO_STRING[type]) |
||||
os.makedirs(directory_path, exist_ok=True) |
||||
|
||||
|
||||
def init_czones(): |
||||
directory_path = CZONE_DIRECTORY |
||||
os.makedirs(directory_path, exist_ok=True) |
||||
|
||||
|
||||
def unpack_cobjects(): |
||||
init_cobjects() |
||||
|
||||
resources = load_cache_file('CObjects.cache') |
||||
|
||||
for res_id, data in resources: |
||||
in_stream = ResStream(data) |
||||
magic = in_stream.read_dword() |
||||
obj_type = in_stream.read_dword() |
||||
|
||||
arc_object = COBJECTS_MAP[obj_type]() |
||||
filepath = os.path.join( |
||||
COBJECTS_DIRECTORY, |
||||
OBJECT_TYPE_TO_STRING[obj_type], |
||||
f'{res_id:020d}.json' |
||||
) |
||||
arc_object.load_binary(in_stream) |
||||
parsed = arc_object.save_json() |
||||
with open(filepath, 'w') as fp: |
||||
json.dump(parsed, fp, indent=2) |
||||
|
||||
|
||||
def pack_cobjects(): |
||||
init_cobjects() |
||||
|
||||
resources = [] |
||||
for obj_type in COBJECTS_MAP: |
||||
directory = os.path.join( |
||||
COBJECTS_DIRECTORY, |
||||
OBJECT_TYPE_TO_STRING[obj_type] |
||||
) |
||||
for filepath in glob.glob(os.path.join(directory, '*.json')): |
||||
filename = os.path.basename(filepath) |
||||
res_id = int(filename.split('.json')[0]) |
||||
json_data = json.load(open(filepath)) |
||||
|
||||
out_stream = ResStream() |
||||
out_stream.write_dword(COBJECTS_MAGIC) |
||||
out_stream.write_dword(obj_type) |
||||
|
||||
arc_object = COBJECTS_MAP[obj_type]() |
||||
try: |
||||
arc_object.load_json(json_data) |
||||
arc_object.save_binary(out_stream) |
||||
except: |
||||
print(res_id) |
||||
raise |
||||
|
||||
resources.append([res_id, out_stream.get_bytes()]) |
||||
|
||||
save_cache_file('CObjects.cache.new', resources) |
||||
|
||||
|
||||
def test_cobjects(): |
||||
resources = load_cache_file('CObjects.cache') |
||||
|
||||
for res_id, data in resources: |
||||
in_stream = ResStream(data) |
||||
out_stream = ResStream() |
||||
|
||||
magic = in_stream.read_dword() |
||||
o_type = in_stream.read_dword() |
||||
out_stream.write_dword(magic) |
||||
out_stream.write_dword(o_type) |
||||
|
||||
arc_in = COBJECTS_MAP[o_type]() |
||||
arc_out = COBJECTS_MAP[o_type]() |
||||
|
||||
arc_in.load_binary(in_stream) |
||||
parsed = arc_in.save_json() |
||||
arc_out.load_json(parsed) |
||||
arc_out.save_binary(out_stream) |
||||
try: |
||||
assert in_stream.get_bytes() == out_stream.get_bytes() |
||||
except: |
||||
print(res_id, in_stream.buffer.tell(), out_stream.buffer.tell()) |
||||
print() |
||||
|
||||
|
||||
def unpack_czones(): |
||||
init_czones() |
||||
|
||||
resources = load_cache_file('CZone.cache') |
||||
|
||||
for res_id, data in resources: |
||||
arc_zone = ArcZone() |
||||
in_stream = ResStream(data) |
||||
filepath = os.path.join( |
||||
CZONE_DIRECTORY, |
||||
f'{res_id:020d}.json' |
||||
) |
||||
arc_zone.load_binary(in_stream) |
||||
parsed = arc_zone.save_json() |
||||
with open(filepath, 'w') as fp: |
||||
json.dump(parsed, fp, indent=2) |
||||
|
||||
|
||||
def pack_czones(): |
||||
init_czones() |
||||
|
||||
resources = [] |
||||
directory = CZONE_DIRECTORY |
||||
for filepath in glob.glob(os.path.join(directory, '*.json')): |
||||
filename = os.path.basename(filepath) |
||||
res_id = int(filename.split('.json')[0]) |
||||
json_data = json.load(open(filepath)) |
||||
|
||||
out_stream = ResStream() |
||||
arc_object = ArcZone() |
||||
try: |
||||
arc_object.load_json(json_data) |
||||
arc_object.save_binary(out_stream) |
||||
except: |
||||
print(res_id) |
||||
raise |
||||
|
||||
resources.append([res_id, out_stream.get_bytes()]) |
||||
|
||||
save_cache_file('CZone.cache.new', resources) |
||||
|
||||
|
||||
def test_czones(): |
||||
resources = load_cache_file('CZone.cache') |
||||
for res_id, data in resources: |
||||
in_stream = ResStream(data) |
||||
out_stream = ResStream() |
||||
|
||||
arc_in = ArcZone() |
||||
arc_out = ArcZone() |
||||
|
||||
arc_in.load_binary(in_stream) |
||||
parsed = arc_in.save_json() |
||||
arc_out.load_json(parsed) |
||||
arc_out.save_binary(out_stream) |
||||
try: |
||||
assert in_stream.get_bytes() == out_stream.get_bytes() |
||||
except: |
||||
print(res_id, in_stream.buffer.tell(), out_stream.buffer.tell()) |
||||
print() |
||||
|
||||
|
||||
def usage(): |
||||
print('mbEditorPro commands:') |
||||
print('usage: {} unpack cobjects'.format(sys.argv[0])) |
||||
print('usage: {} pack cobjects'.format(sys.argv[0])) |
||||
print('usage: {} unpack czones'.format(sys.argv[0])) |
||||
print('usage: {} pack czones'.format(sys.argv[0])) |
||||
exit(1) |
||||
|
||||
|
||||
def main(): |
||||
if not sys.argv[2:]: |
||||
usage() |
||||
|
||||
if sys.argv[1] not in ['pack', 'unpack']: |
||||
usage() |
||||
|
||||
if sys.argv[2] not in ['cobjects', 'czones']: |
||||
usage() |
||||
|
||||
method = '_'.join(sys.argv[1:3]) + '()' |
||||
print(method) |
||||
exec(method) |
||||
|
||||
|
||||
main() |
@ -0,0 +1,70 @@
@@ -0,0 +1,70 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄ |
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪ |
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄ |
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌ |
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪ |
||||
# Magicbane Emulator Project © 2013 - 2022 |
||||
# www.magicbane.com |
||||
|
||||
from PIL import Image, ImageOps |
||||
|
||||
from arcane.util import ResStream |
||||
|
||||
|
||||
class ArcTexture: |
||||
VALUE_TO_MODE = { |
||||
(4, 8, 2): 'RGBA', |
||||
(3, 0, 0): 'RGB', |
||||
(1, 0, 0): 'L', |
||||
(1, 8, 2): 'P', |
||||
} |
||||
|
||||
MODE_TO_VALUE = {value: key for key, value in VALUE_TO_MODE.items()} |
||||
|
||||
def load_binary(self, stream: ResStream): |
||||
self.image_width = stream.read_dword() |
||||
self.image_height = stream.read_dword() |
||||
self.image_color_depth = stream.read_dword() |
||||
self.image_alpha = stream.read_dword() |
||||
self.image_type = stream.read_dword() |
||||
self.image_compressed = stream.read_bool() |
||||
self.image_linear = stream.read_bool() |
||||
data_size = stream.read_dword() |
||||
self.image_data = stream.read_bytes(data_size) |
||||
|
||||
def save_binary(self, stream: ResStream): |
||||
stream.write_dword(self.image_width) |
||||
stream.write_dword(self.image_height) |
||||
stream.write_dword(self.image_color_depth) |
||||
stream.write_dword(self.image_alpha) |
||||
stream.write_dword(self.image_type) |
||||
stream.write_bool(self.image_compressed) |
||||
stream.write_bool(self.image_linear) |
||||
stream.write_dword(len(self.image_data)) |
||||
stream.write_bytes(self.image_data) |
||||
|
||||
def load_img(self, filepath): |
||||
img = Image.open(filepath) |
||||
img = ImageOps.mirror(img).rotate(180) |
||||
self.image_width = img.width |
||||
self.image_height = img.height |
||||
self.image_color_depth, self.image_alpha, self.image_type = self.MODE_TO_VALUE[img.mode] |
||||
self.image_compressed = True |
||||
self.image_linear = True |
||||
self.image_data = img.tobytes() |
||||
|
||||
def save_img(self, filepath): |
||||
mode = self.VALUE_TO_MODE[ |
||||
(self.image_color_depth, self.image_alpha, self.image_type) |
||||
] |
||||
img = Image.frombytes(mode, (self.image_width, self.image_height), self.image_data) |
||||
img = ImageOps.mirror(img.rotate(180)) |
||||
img.save(filepath) |
||||
|
||||
|
||||
class ArcTerrain(ArcTexture): |
||||
VALUE_TO_MODE = { |
||||
(1, 1, 0): 'P', |
||||
} |
||||
|
||||
MODE_TO_VALUE = {value: key for key, value in VALUE_TO_MODE.items()} |
@ -0,0 +1,113 @@
@@ -0,0 +1,113 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄ |
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪ |
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄ |
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌ |
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪ |
||||
# Magicbane Emulator Project © 2013 - 2022 |
||||
# www.magicbane.com |
||||
|
||||
from collections import OrderedDict |
||||
|
||||
from arcane.util import ResStream |
||||
|
||||
|
||||
class ArcMesh: |
||||
def load_binary(self, stream: ResStream): |
||||
self.mesh_name = stream.read_string() |
||||
self.mesh_distance = stream.read_float() |
||||
self.mesh_start_point = stream.read_tuple() |
||||
self.mesh_end_point = stream.read_tuple() |
||||
self.mesh_ref_point = stream.read_tuple() |
||||
self.mesh_use_face_normals = stream.read_bool() |
||||
self.mesh_use_tangent_basis = stream.read_bool() |
||||
num_vertices = stream.read_dword() |
||||
self.mesh_vertices = [stream.read_tuple() for _ in range(num_vertices)] |
||||
num_other_vertices = stream.read_dword() |
||||
self.mesh_normals = [stream.read_tuple() for _ in range(num_other_vertices)] |
||||
num = stream.read_dword() |
||||
self.mesh_uv = [ |
||||
[ |
||||
stream.read_float(), |
||||
stream.read_float(), |
||||
] for _ in range(num) |
||||
] |
||||
if self.mesh_use_tangent_basis: |
||||
num_tangent_vertices = stream.read_dword() |
||||
self.mesh_tanget_vertices = [stream.read_tuple() for _ in range(num_tangent_vertices)] |
||||
num_indicies = stream.read_dword() |
||||
self.mesh_indices = [stream.read_word() for _ in range(num_indicies)] |
||||
num = stream.read_dword() |
||||
self.mesh_extra_indices = [ |
||||
[ |
||||
stream.read_dword(), |
||||
stream.read_dword(), |
||||
[stream.read_word() for _ in range(stream.read_dword())], |
||||
] for _ in range(num) |
||||
] |
||||
|
||||
def save_binary(self, stream: ResStream): |
||||
stream.write_string(self.mesh_name) |
||||
stream.write_float(self.mesh_distance) |
||||
stream.write_tuple(self.mesh_start_point) |
||||
stream.write_tuple(self.mesh_end_point) |
||||
stream.write_tuple(self.mesh_ref_point) |
||||
stream.write_bool(self.mesh_use_face_normals) |
||||
stream.write_bool(self.mesh_use_tangent_basis) |
||||
stream.write_dword(len(self.mesh_vertices)) |
||||
for i in range(len(self.mesh_vertices)): |
||||
stream.write_tuple(self.mesh_vertices[i]) |
||||
stream.write_dword(len(self.mesh_normals)) |
||||
for i in range(len(self.mesh_normals)): |
||||
stream.write_tuple(self.mesh_normals[i]) |
||||
stream.write_dword(len(self.mesh_uv)) |
||||
for i in range(len(self.mesh_uv)): |
||||
stream.write_float(self.mesh_uv[i][0]) |
||||
stream.write_float(self.mesh_uv[i][1]) |
||||
if self.mesh_use_tangent_basis: |
||||
stream.write_dword(len(self.mesh_tanget_vertices)) |
||||
for i in range(len(self.mesh_tanget_vertices)): |
||||
stream.write_tuple(self.mesh_tanget_vertices[i]) |
||||
stream.write_dword(len(self.mesh_indices)) |
||||
for i in range(len(self.mesh_indices)): |
||||
stream.write_word(self.mesh_indices[i]) |
||||
stream.write_dword(len(self.mesh_extra_indices)) |
||||
for i in range(len(self.mesh_extra_indices)): |
||||
stream.write_dword(self.mesh_extra_indices[i][0]) |
||||
stream.write_dword(self.mesh_extra_indices[i][1]) |
||||
stream.write_dword(len(self.mesh_extra_indices[i][2])) |
||||
for j in range(len(self.mesh_extra_indices[i][2])): |
||||
stream.write_word(self.mesh_extra_indices[i][2][j]) |
||||
|
||||
def load_json(self, data): |
||||
self.mesh_name = data['mesh_name'] |
||||
self.mesh_distance = data['mesh_distance'] |
||||
self.mesh_start_point = data['mesh_start_point'] |
||||
self.mesh_end_point = data['mesh_end_point'] |
||||
self.mesh_ref_point = data['mesh_ref_point'] |
||||
self.mesh_use_face_normals = data['mesh_use_face_normals'] |
||||
self.mesh_use_tangent_basis = data['mesh_use_tangent_basis'] |
||||
self.mesh_vertices = data['mesh_vertices'] |
||||
self.mesh_normals = data['mesh_normals'] |
||||
self.mesh_uv = data['mesh_uv'] |
||||
if self.mesh_use_tangent_basis: |
||||
self.mesh_tanget_vertices = data['mesh_tanget_vertices'] |
||||
self.mesh_indices = data['mesh_indices'] |
||||
self.mesh_extra_indices = data['mesh_extra_indices'] |
||||
|
||||
def save_json(self): |
||||
data = OrderedDict() |
||||
data['mesh_name'] = self.mesh_name |
||||
data['mesh_distance'] = self.mesh_distance |
||||
data['mesh_start_point'] = self.mesh_start_point |
||||
data['mesh_end_point'] = self.mesh_end_point |
||||
data['mesh_ref_point'] = self.mesh_ref_point |
||||
data['mesh_use_face_normals'] = self.mesh_use_face_normals |
||||
data['mesh_use_tangent_basis'] = self.mesh_use_tangent_basis |
||||
data['mesh_vertices'] = self.mesh_vertices |
||||
data['mesh_normals'] = self.mesh_normals |
||||
data['mesh_uv'] = self.mesh_uv |
||||
if self.mesh_use_tangent_basis: |
||||
data['mesh_tanget_vertices'] = self.mesh_tanget_vertices |
||||
data['mesh_indices'] = self.mesh_indices |
||||
data['mesh_extra_indices'] = self.mesh_extra_indices |
||||
return data |
@ -0,0 +1,89 @@
@@ -0,0 +1,89 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄ |
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪ |
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄ |
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌ |
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪ |
||||
# Magicbane Emulator Project © 2013 - 2022 |
||||
# www.magicbane.com |
||||
|
||||
from collections import OrderedDict |
||||
|
||||
from arcane.util import ResStream |
||||
|
||||
|
||||
class ArcMotion: |
||||
def load_binary(self, stream: ResStream): |
||||
self.motion_file = stream.read_string() |
||||
self.motion_smoothed_count = stream.read_dword() |
||||
self.motion_smoothed_value = stream.read_dword() |
||||
self.motion_smoothed_factor = stream.read_float() |
||||
self.motion_sound = stream.read_qword() |
||||
self.motion_sheath = stream.read_dword() |
||||
self.motion_reset_loc = stream.read_bool() |
||||
self.motion_leave_ground = stream.read_bool() |
||||
self.motion_force = stream.read_float() |
||||
self.motion_disable_blend = stream.read_bool() |
||||
num_parts = stream.read_dword() |
||||
self.motion_parts = [stream.read_string() for _ in range(num_parts)] |
||||
num_smoothing = stream.read_dword() |
||||
self.motion_smoothing = [ |
||||
[ |
||||
stream.read_float() for _ in range(10) |
||||
] for _ in range(num_smoothing) |
||||
] |
||||
num_target_frames = stream.read_dword() |
||||
self.motion_target_frames = [stream.read_dword() for _ in range(num_target_frames)] |
||||
|
||||
def save_binary(self, stream: ResStream): |
||||
stream.write_string(self.motion_file) |
||||
stream.write_dword(self.motion_smoothed_count) |
||||
stream.write_dword(self.motion_smoothed_value) |
||||
stream.write_float(self.motion_smoothed_factor) |
||||
stream.write_qword(self.motion_sound) |
||||
stream.write_dword(self.motion_sheath) |
||||
stream.write_bool(self.motion_reset_loc) |
||||
stream.write_bool(self.motion_leave_ground) |
||||
stream.write_float(self.motion_force) |
||||
stream.write_bool(self.motion_disable_blend) |
||||
stream.write_dword(len(self.motion_parts)) |
||||
for i in range(len(self.motion_parts)): |
||||
stream.write_string(self.motion_parts[i]) |
||||
stream.write_dword(len(self.motion_smoothing)) |
||||
for i in range(len(self.motion_smoothing)): |
||||
for j in range(10): |
||||
stream.write_float(self.motion_smoothing[i][j]) |
||||
stream.write_dword(len(self.motion_target_frames)) |
||||
for i in range(len(self.motion_target_frames)): |
||||
stream.write_dword(self.motion_target_frames[i]) |
||||
|
||||
def load_json(self, data): |
||||
self.motion_file = data['motion_file'] |
||||
self.motion_smoothed_count = data['motion_smoothed_count'] |
||||
self.motion_smoothed_value = data['motion_smoothed_value'] |
||||
self.motion_smoothed_factor = data['motion_smoothed_factor'] |
||||
self.motion_sound = data['motion_sound'] |
||||
self.motion_sheath = data['motion_sheath'] |
||||
self.motion_reset_loc = data['motion_reset_loc'] |
||||
self.motion_leave_ground = data['motion_leave_ground'] |
||||
self.motion_force = data['motion_force'] |
||||
self.motion_disable_blend = data['motion_disable_blend'] |
||||
self.motion_parts = data['motion_parts'] |
||||
self.motion_smoothing = data['motion_smoothing'] |
||||
self.motion_target_frames = data['motion_target_frames'] |
||||
|
||||
def save_json(self): |
||||
data = OrderedDict() |
||||
data['motion_file'] = self.motion_file |
||||
data['motion_smoothed_count'] = self.motion_smoothed_count |
||||
data['motion_smoothed_value'] = self.motion_smoothed_value |
||||
data['motion_smoothed_factor'] = self.motion_smoothed_factor |
||||
data['motion_sound'] = self.motion_sound |
||||
data['motion_sheath'] = self.motion_sheath |
||||
data['motion_reset_loc'] = self.motion_reset_loc |
||||
data['motion_leave_ground'] = self.motion_leave_ground |
||||
data['motion_force'] = self.motion_force |
||||
data['motion_disable_blend'] = self.motion_disable_blend |
||||
data['motion_parts'] = self.motion_parts |
||||
data['motion_smoothing'] = self.motion_smoothing |
||||
data['motion_target_frames'] = self.motion_target_frames |
||||
return data |
@ -0,0 +1,644 @@
@@ -0,0 +1,644 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄ |
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪ |
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄ |
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌ |
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪ |
||||
# Magicbane Emulator Project © 2013 - 2022 |
||||
# www.magicbane.com |
||||
|
||||
from collections import OrderedDict |
||||
|
||||
from arcane.util import ResStream |
||||
|
||||
TRACKER_TO_STRING = { |
||||
0: 'NONE', |
||||
1: 'XY', |
||||
2: 'Y', |
||||
} |
||||
STRING_TO_TRACKER = {value: key for key, value in TRACKER_TO_STRING.items()} |
||||
|
||||
TRANSPARENT_TO_STRING = { |
||||
0: 'NONE', |
||||
1: 'PINK', |
||||
2: 'BLACK', |
||||
3: 'WHITE', |
||||
4: 'SEMI', |
||||
6: 'ALPHA', |
||||
} |
||||
STRING_TO_TRANSPARENT = {value: key for key, value in TRANSPARENT_TO_STRING.items()} |
||||
|
||||
TEXTURE_TO_STRING = { |
||||
0: 'SINGLE_TEXTURE', |
||||
1: 'COLOR_TEXTURE', |
||||
3: 'ANIMATED_TEXTURE', |
||||
} |
||||
STRING_TO_TEXTURE = {value: key for key, value in TEXTURE_TO_STRING.items()} |
||||
|
||||
LIGHT_TYPE_TO_STRING = { |
||||
0xb6787258: 'ArcLightPoint', |
||||
0x54e8ff1d: 'ArcLightAffectorAttach', |
||||
0xa73bd9d4: 'ArcLightAffectorFlicker', |
||||
} |
||||
STRING_TO_LIGHT_TYPE = {value: key for key, value in LIGHT_TYPE_TO_STRING.items()} |
||||
|
||||
|
||||
class ArcSinglePolyMesh: |
||||
def load_binary(self, stream: ResStream): |
||||
self.polymesh_id = stream.read_qword() |
||||
self.polymesh_decal = stream.read_bool() |
||||
self.polymesh_double_sided = stream.read_bool() |
||||
|
||||
def save_binary(self, stream: ResStream): |
||||
stream.write_qword(self.polymesh_id) |
||||
stream.write_bool(self.polymesh_decal) |
||||
stream.write_bool(self.polymesh_double_sided) |
||||
|
||||
def load_json(self, data): |
||||
self.polymesh_id = data['polymesh_id'] |
||||
self.polymesh_decal = data['polymesh_decal'] |
||||
self.polymesh_double_sided = data['polymesh_double_sided'] |
||||
|
||||
def save_json(self): |
||||
data = OrderedDict() |
||||
data['polymesh_id'] = self.polymesh_id |
||||
data['polymesh_decal'] = self.polymesh_decal |
||||
data['polymesh_double_sided'] = self.polymesh_double_sided |
||||
return data |
||||
|
||||
|
||||
class ArcMeshSet: |
||||
def load_binary(self, stream: ResStream): |
||||
num = stream.read_dword() |
||||
self.mesh_set = [ArcSinglePolyMesh() for _ in range(num)] |
||||
for mesh in self.mesh_set: |
||||
mesh.load_binary(stream) |
||||
|
||||
def save_binary(self, stream: ResStream): |
||||
stream.write_dword(len(self.mesh_set)) |
||||
for mesh in self.mesh_set: |
||||
mesh.save_binary(stream) |
||||
|
||||
def load_json(self, data): |
||||
self.mesh_set = [] |
||||
for mesh_data in data['mesh_set']: |
||||
mesh = ArcSinglePolyMesh() |
||||
mesh.load_json(mesh_data) |
||||
self.mesh_set.append(mesh) |
||||
|
||||
def save_json(self): |
||||
data = OrderedDict() |
||||
data['mesh_set'] = [] |
||||
for mesh in self.mesh_set: |
||||
data['mesh_set'].append(mesh.save_json()) |
||||
return data |
||||
|
||||
|
||||
class ArcRenderTemplate: |
||||
def load_binary(self, stream: ResStream): |
||||
self.template_object_can_fade = stream.read_bool() |
||||
self.template_tracker = stream.read_dword() |
||||
self.template_illuminated = stream.read_bool() |
||||
self.template_bone_length = stream.read_float() |
||||
self.template_clip_map = stream.read_dword() |
||||
self.template_light_two_side = stream.read_dword() |
||||
self.template_cull_face = stream.read_dword() |
||||
self.template_specular_map = stream.read_qword() |
||||
self.template_shininess = stream.read_float() |
||||
self.template_has_mesh = stream.read_bool() |
||||
if self.template_has_mesh: |
||||
self.template_mesh = ArcMeshSet() |
||||
self.template_mesh.load_binary(stream) |
||||
|
||||
def save_binary(self, stream: ResStream): |
||||
stream.write_bool(self.template_object_can_fade) |
||||
stream.write_dword(self.template_tracker) |
||||
stream.write_bool(self.template_illuminated) |
||||
stream.write_float(self.template_bone_length) |
||||
stream.write_dword(self.template_clip_map) |
||||
stream.write_dword(self.template_light_two_side) |
||||
stream.write_dword(self.template_cull_face) |
||||
stream.write_qword(self.template_specular_map) |
||||
stream.write_float(self.template_shininess) |
||||
stream.write_bool(self.template_has_mesh) |
||||
if self.template_has_mesh: |
||||
self.template_mesh.save_binary(stream) |
||||
|
||||
def load_json(self, data): |
||||
self.template_object_can_fade = data['template_object_can_fade'] |
||||
self.template_tracker = STRING_TO_TRACKER[data['template_tracker']] |
||||
self.template_illuminated = data['template_illuminated'] |
||||
self.template_bone_length = data['template_bone_length'] |
||||
self.template_clip_map = data['template_clip_map'] |
||||
self.template_light_two_side = data['template_light_two_side'] |
||||
self.template_cull_face = data['template_cull_face'] |
||||
self.template_specular_map = data['template_specular_map'] |
||||
self.template_shininess = data['template_shininess'] |
||||
self.template_has_mesh = data['template_has_mesh'] |
||||
if self.template_has_mesh: |
||||
self.template_mesh = ArcMeshSet() |
||||
self.template_mesh.load_json(data['template_mesh']) |
||||
|
||||
def save_json(self): |
||||
data = OrderedDict() |
||||
data['template_object_can_fade'] = self.template_object_can_fade |
||||
data['template_tracker'] = TRACKER_TO_STRING[self.template_tracker] |
||||
data['template_illuminated'] = self.template_illuminated |
||||
data['template_bone_length'] = self.template_bone_length |
||||
data['template_clip_map'] = self.template_clip_map |
||||
data['template_light_two_side'] = self.template_light_two_side |
||||
data['template_cull_face'] = self.template_cull_face |
||||
data['template_specular_map'] = self.template_specular_map |
||||
data['template_shininess'] = self.template_shininess |
||||
data['template_has_mesh'] = self.template_has_mesh |
||||
if self.template_has_mesh: |
||||
data['template_mesh'] = self.template_mesh.save_json() |
||||
return data |
||||
|
||||
|
||||
class ArcSingleTexture: |
||||
def load_binary(self, stream: ResStream): |
||||
self.texture_id = stream.read_qword() |
||||
self.texture_transparent = stream.read_dword() |
||||
self.texture_compress = stream.read_bool() |
||||
self.texture_normal_map = stream.read_bool() |
||||
self.texture_detail_normal_map = stream.read_bool() |
||||
self.texture_create_mip_maps = stream.read_bool() |
||||
self.texture_x0 = stream.read_string() |
||||
self.texture_x1 = stream.read_string() |
||||
self.texture_x2 = stream.read_dword() |
||||
self.texture_x3 = stream.read_dword() |
||||
self.texture_x4 = stream.read_bool() |
||||
self.texture_wrap = stream.read_bool() |
||||
|
||||
def save_binary(self, stream: ResStream): |
||||
stream.write_qword(self.texture_id) |
||||
stream.write_dword(self.texture_transparent) |
||||
stream.write_bool(self.texture_compress) |
||||
stream.write_bool(self.texture_normal_map) |
||||
stream.write_bool(self.texture_detail_normal_map) |
||||
stream.write_bool(self.texture_create_mip_maps) |
||||
stream.write_string(self.texture_x0) |
||||
stream.write_string(self.texture_x1) |
||||
stream.write_dword(self.texture_x2) |
||||
stream.write_dword(self.texture_x3) |
||||
stream.write_bool(self.texture_x4) |
||||
stream.write_bool(self.texture_wrap) |
||||
|
||||
def load_json(self, data): |
||||
self.texture_id = data['texture_id'] |
||||
self.texture_transparent = STRING_TO_TRANSPARENT[data['texture_transparent']] |
||||
self.texture_compress = data['texture_compress'] |
||||
self.texture_normal_map = data['texture_normal_map'] |
||||
self.texture_detail_normal_map = data['texture_detail_normal_map'] |
||||
self.texture_create_mip_maps = data['texture_create_mip_maps'] |
||||
self.texture_x0 = '' |
||||
self.texture_x1 = '' |
||||
self.texture_x2 = 255 |
||||
self.texture_x3 = 0 |
||||
self.texture_x4 = False |
||||
self.texture_wrap = data['texture_wrap'] |
||||
|
||||
def save_json(self): |
||||
data = OrderedDict() |
||||
data['texture_id'] = self.texture_id |
||||
data['texture_transparent'] = TRANSPARENT_TO_STRING[self.texture_transparent] |
||||
data['texture_compress'] = self.texture_compress |
||||
data['texture_normal_map'] = self.texture_normal_map |
||||
data['texture_detail_normal_map'] = self.texture_detail_normal_map |
||||
data['texture_create_mip_maps'] = self.texture_create_mip_maps |
||||
data['texture_wrap'] = self.texture_wrap |
||||
return data |
||||
|
||||
|
||||
class ArcColorTexture(ArcSingleTexture): |
||||
pass |
||||
|
||||
|
||||
class ArcAnimatedTexture: |
||||
def load_binary(self, stream: ResStream): |
||||
self.animated_texture_id = stream.read_qword() |
||||
self.animated_texture_transparent = stream.read_dword() |
||||
self.animated_texture_compress = stream.read_bool() |
||||
self.animated_texture_normal_map = stream.read_bool() |
||||
self.animated_texture_detail_normal_map = stream.read_bool() |
||||
self.animated_texture_create_mip_maps = stream.read_bool() |
||||
self.animated_texture_frame_timer = stream.read_float() |
||||
self.animated_texture_x0 = stream.read_float() |
||||
self.animated_texture_frame_rand = stream.read_dword() |
||||
|
||||
num = stream.read_dword() |
||||
self.animated_texture_sets = [ArcTextureSet() for _ in range(num)] |
||||
for texture in self.animated_texture_sets: |
||||
texture.load_binary(stream) |
||||
|
||||
def save_binary(self, stream: ResStream): |
||||
stream.write_qword(self.animated_texture_id) |
||||
stream.write_dword(self.animated_texture_transparent) |
||||
stream.write_bool(self.animated_texture_compress) |
||||
stream.write_bool(self.animated_texture_normal_map) |
||||
stream.write_bool(self.animated_texture_detail_normal_map) |
||||
stream.write_bool(self.animated_texture_create_mip_maps) |
||||
stream.write_float(self.animated_texture_frame_timer) |
||||
stream.write_float(self.animated_texture_x0) |
||||
stream.write_dword(self.animated_texture_frame_rand) |
||||
|
||||
stream.write_dword(len(self.animated_texture_sets)) |
||||
for texture in self.animated_texture_sets: |
||||
texture.save_binary(stream) |
||||
|
||||
def load_json(self, data): |
||||
self.animated_texture_id = data['animated_texture_id'] |
||||
self.animated_texture_transparent = STRING_TO_TRANSPARENT[data['animated_texture_transparent']] |
||||
self.animated_texture_compress = data['animated_texture_compress'] |
||||
self.animated_texture_normal_map = data['animated_texture_normal_map'] |
||||
self.animated_texture_detail_normal_map = data['animated_texture_detail_normal_map'] |
||||
self.animated_texture_create_mip_maps = data['animated_texture_create_mip_maps'] |
||||
self.animated_texture_frame_timer = data['animated_texture_frame_timer'] |
||||
self.animated_texture_x0 = 0.0 |
||||
self.animated_texture_frame_rand = data['animated_texture_frame_rand'] |
||||
self.animated_texture_sets = [] |
||||
for texture_data in data['animated_texture_sets']: |
||||
texture = ArcTextureSet() |
||||
texture.load_json(texture_data) |
||||
self.animated_texture_sets.append(texture) |
||||
|
||||
def save_json(self): |
||||
data = OrderedDict() |
||||
data['animated_texture_id'] = self.animated_texture_id |
||||
data['animated_texture_transparent'] = TRANSPARENT_TO_STRING[self.animated_texture_transparent] |
||||
data['animated_texture_compress'] = self.animated_texture_compress |
||||
data['animated_texture_normal_map'] = self.animated_texture_normal_map |
||||
data['animated_texture_detail_normal_map'] = self.animated_texture_detail_normal_map |
||||
data['animated_texture_create_mip_maps'] = self.animated_texture_create_mip_maps |
||||
data['animated_texture_frame_timer'] = self.animated_texture_frame_timer |
||||
data['animated_texture_frame_rand'] = self.animated_texture_frame_rand |
||||
data['animated_texture_sets'] = [] |
||||
for texture in self.animated_texture_sets: |
||||
data['animated_texture_sets'].append(texture.save_json()) |
||||
return data |
||||
|
||||
|
||||
class ArcTextureSet: |
||||
def load_binary(self, stream: ResStream): |
||||
self.texture_type = stream.read_dword() |
||||
if self.texture_type == 0: |
||||
self.texture_data = ArcSingleTexture() |
||||
elif self.texture_type == 1: |
||||
self.texture_data = ArcColorTexture() |
||||
elif self.texture_type == 3: |
||||
self.texture_data = ArcAnimatedTexture() |
||||
self.texture_data.load_binary(stream) |
||||
|
||||
def save_binary(self, stream: ResStream): |
||||
stream.write_dword(self.texture_type) |
||||
self.texture_data.save_binary(stream) |
||||
|
||||
def load_json(self, data): |
||||
self.texture_type = STRING_TO_TEXTURE[data['texture_type']] |
||||
if self.texture_type == 0: |
||||
self.texture_data = ArcSingleTexture() |
||||
elif self.texture_type == 1: |
||||
self.texture_data = ArcColorTexture() |
||||
elif self.texture_type == 3: |
||||
self.texture_data = ArcAnimatedTexture() |
||||
self.texture_data.load_json(data['texture_data']) |
||||
|
||||
def save_json(self): |
||||
data = OrderedDict() |
||||
data['texture_type'] = TEXTURE_TO_STRING[self.texture_type] |
||||
data['texture_data'] = self.texture_data.save_json() |
||||
return data |
||||
|
||||
|
||||
class ArcLightPoint: |
||||
def load_binary(self, stream: ResStream): |
||||
self.lightpoint_x0 = stream.read_dword() |
||||
self.lightpoint_x1 = stream.read_bool() |
||||
self.lightpoint_shader = stream.read_bool() |
||||
self.lightpoint_update_offscreen = stream.read_bool() |
||||
self.lightpoint_radius = stream.read_float() |
||||
self.lightpoint_position = stream.read_tuple() |
||||
self.lightpoint_diffuse_color = [stream.read_float() for _ in range(4)] |
||||
self.lightpoint_x2 = stream.read_dword() |
||||
self.lightpoint_orientation = [stream.read_float() for _ in range(4)] |
||||
self.lightpoint_cubemap = stream.read_dword() |
||||
self.lightpoint_x3 = stream.read_bool() |
||||
|
||||
def save_binary(self, stream: ResStream): |
||||
stream.write_dword(self.lightpoint_x0) |
||||
stream.write_bool(self.lightpoint_x1) |
||||
stream.write_bool(self.lightpoint_shader) |
||||
stream.write_bool(self.lightpoint_update_offscreen) |
||||
stream.write_float(self.lightpoint_radius) |
||||
stream.write_tuple(self.lightpoint_position) |
||||
for i in range(4): |
||||
stream.write_float(self.lightpoint_diffuse_color[i]) |
||||
stream.write_dword(self.lightpoint_x2) |
||||
for i in range(4): |
||||
stream.write_float(self.lightpoint_orientation[i]) |
||||
stream.write_dword(self.lightpoint_cubemap) |
||||
stream.write_bool(self.lightpoint_x3) |
||||
|
||||
def load_json(self, data): |
||||
self.lightpoint_x0 = 1 |
||||
self.lightpoint_x1 = True |
||||
self.lightpoint_shader = data['lightpoint_shader'] |
||||
self.lightpoint_update_offscreen = data['lightpoint_update_offscreen'] |
||||
self.lightpoint_radius = data['lightpoint_radius'] |
||||
self.lightpoint_position = data['lightpoint_position'] |
||||
self.lightpoint_diffuse_color = data['lightpoint_diffuse_color'] |
||||
self.lightpoint_x2 = 1 |
||||
self.lightpoint_orientation = data['lightpoint_orientation'] |
||||
self.lightpoint_cubemap = data['lightpoint_cubemap'] |
||||
self.lightpoint_x3 = False |
||||
|
||||
def save_json(self): |
||||
data = OrderedDict() |
||||
data['lightpoint_shader'] = self.lightpoint_shader |
||||
data['lightpoint_update_offscreen'] = self.lightpoint_update_offscreen |
||||
data['lightpoint_radius'] = self.lightpoint_radius |
||||
data['lightpoint_position'] = self.lightpoint_position |
||||
data['lightpoint_diffuse_color'] = self.lightpoint_diffuse_color |
||||
data['lightpoint_orientation'] = self.lightpoint_orientation |
||||
data['lightpoint_cubemap'] = self.lightpoint_cubemap |
||||
return data |
||||
|
||||
|
||||
class ArcLightAffectorAttach: |
||||
def load_binary(self, stream: ResStream): |
||||
self.attach_x0 = stream.read_dword() |
||||
self.attach_offset = stream.read_tuple() |
||||
|
||||
def save_binary(self, stream: ResStream): |
||||
stream.write_dword(self.attach_x0) |
||||
stream.write_tuple(self.attach_offset) |
||||
|
||||
def load_json(self, data): |
||||
self.attach_x0 = 1 |
||||
self.attach_offset = data['attach_offset'] |
||||
|
||||
def save_json(self): |
||||
data = OrderedDict() |
||||
data['attach_offset'] = self.attach_offset |
||||
return data |
||||
|
||||
|
||||
class ArcLightAffectorFlicker: |
||||
def load_binary(self, stream: ResStream): |
||||
self.flicker_x0 = stream.read_dword() |
||||
self.flicker_avg_period = stream.read_float() |
||||
self.flicker_std_dev_radius = stream.read_float() |
||||
self.flicker_std_dev_period = stream.read_float() |
||||
self.flicker_falloff = stream.read_float() |
||||
|
||||
def save_binary(self, stream: ResStream): |
||||
stream.write_dword(self.flicker_x0) |
||||
stream.write_float(self.flicker_avg_period) |
||||
stream.write_float(self.flicker_std_dev_radius) |
||||
stream.write_float(self.flicker_std_dev_period) |
||||
stream.write_float(self.flicker_falloff) |
||||
|
||||
def load_json(self, data): |
||||
self.flicker_x0 = 1 |
||||
self.flicker_avg_period = data['flicker_avg_period'] |
||||
self.flicker_std_dev_radius = data['flicker_std_dev_radius'] |
||||
self.flicker_std_dev_period = data['flicker_std_dev_period'] |
||||
self.flicker_falloff = data['flicker_falloff'] |
||||
|
||||
def save_json(self): |
||||
data = OrderedDict() |
||||
data['flicker_avg_period'] = self.flicker_avg_period |
||||
data['flicker_std_dev_radius'] = self.flicker_std_dev_radius |
||||
data['flicker_std_dev_period'] = self.flicker_std_dev_period |
||||
data['flicker_falloff'] = self.flicker_falloff |
||||
return data |
||||
|
||||
|
||||
class ArcLightAffectors: |
||||
def load_binary(self, stream: ResStream): |
||||
self.light_affector_type = stream.read_dword() |
||||
|
||||
if self.light_affector_type == 0x54e8ff1d: |
||||
self.light_affector_data = ArcLightAffectorAttach() |
||||
elif self.light_affector_type == 0xa73bd9d4: |
||||
self.light_affector_data = ArcLightAffectorFlicker() |
||||
self.light_affector_data.load_binary(stream) |
||||
|
||||
self.light_affector_0xdaed = stream.read_dword() |
||||
|
||||
def save_binary(self, stream: ResStream): |
||||
stream.write_dword(self.light_affector_type) |
||||
self.light_affector_data.save_binary(stream) |
||||
stream.write_dword(self.light_affector_0xdaed) |
||||
|
||||
def load_json(self, data): |
||||
self.light_affector_type = STRING_TO_LIGHT_TYPE[data['light_affector_type']] |
||||
if self.light_affector_type == 0x54e8ff1d: |
||||
self.light_affector_data = ArcLightAffectorAttach() |
||||
elif self.light_affector_type == 0xa73bd9d4: |
||||
self.light_affector_data = ArcLightAffectorFlicker() |
||||
self.light_affector_data.load_json(data['light_affector_data']) |
||||
self.light_affector_0xdaed = 0xddaaeedd |
||||
|
||||
def save_json(self): |
||||
data = OrderedDict() |
||||
data['light_affector_type'] = LIGHT_TYPE_TO_STRING[self.light_affector_type] |
||||
data['light_affector_data'] = self.light_affector_data.save_json() |
||||
return data |
||||
|
||||
|
||||
class ArcLight: |
||||
def load_binary(self, stream: ResStream): |
||||
self.light_x0 = stream.read_dword() |
||||
self.light_x1 = stream.read_bool() |
||||
self.light_type = stream.read_dword() |
||||
|
||||
if self.light_type == 0xb6787258: |
||||
self.light_data = ArcLightPoint() |
||||
self.light_data.load_binary(stream) |
||||
|
||||
self.light_0xdaed = stream.read_dword() |
||||
|
||||
num = stream.read_dword() |
||||
self.light_affectors = [ArcLightAffectors() for _ in range(num)] |
||||
for extra in self.light_affectors: |
||||
extra.load_binary(stream) |
||||
|
||||
def save_binary(self, stream: ResStream): |
||||
stream.write_dword(self.light_x0) |
||||
stream.write_bool(self.light_x1) |
||||
stream.write_dword(self.light_type) |
||||
self.light_data.save_binary(stream) |
||||
stream.write_dword(self.light_0xdaed) |
||||
|
||||
stream.write_dword(len(self.light_affectors)) |
||||
for extra in self.light_affectors: |
||||
extra.save_binary(stream) |
||||
|
||||
def load_json(self, data): |
||||
self.light_x0 = 1 |
||||
self.light_x1 = True |
||||
self.light_type = STRING_TO_LIGHT_TYPE[data['light_type']] |
||||
if self.light_type == 0xb6787258: |
||||
self.light_data = ArcLightPoint() |
||||
self.light_data.load_json(data['light_data']) |
||||
self.light_0xdaed = 0xddaaeedd |
||||
|
||||
self.light_affectors = [] |
||||
for extra_data in data['light_affectors']: |
||||
extra = ArcLightAffectors() |
||||
extra.load_json(extra_data) |
||||
self.light_affectors.append(extra) |
||||
|
||||
def save_json(self): |
||||
data = OrderedDict() |
||||
data['light_type'] = LIGHT_TYPE_TO_STRING[self.light_type] |
||||
data['light_data'] = self.light_data.save_json() |
||||
|
||||
data['light_affectors'] = [] |
||||
for extra in self.light_affectors: |
||||
data['light_affectors'].append(extra.save_json()) |
||||
return data |
||||
|
||||
|
||||
class ArcRender: |
||||
def load_binary(self, stream: ResStream): |
||||
self.render_template = ArcRenderTemplate() |
||||
self.render_template.load_binary(stream) |
||||
self.render_target_bone = stream.read_string() |
||||
self.render_scale = stream.read_tuple() |
||||
self.render_has_loc = stream.read_dword() |
||||
if self.render_has_loc: |
||||
self.render_loc = stream.read_tuple() |
||||
num_children = stream.read_dword() |
||||
self.render_children = [stream.read_qword() for _ in range(num_children)] |
||||
self.render_has_texture_set = stream.read_bool() |
||||
if self.render_has_texture_set: |
||||
num = stream.read_dword() |
||||
self.render_texture_set = [ArcTextureSet() for _ in range(num)] |
||||
for texture in self.render_texture_set: |
||||
texture.load_binary(stream) |
||||
self.render_collides = stream.read_bool() |
||||
self.render_calculate_bounding_box = stream.read_bool() |
||||
self.render_nation_crest = stream.read_bool() |
||||
self.render_guild_crest = stream.read_bool() |
||||
self.render_bumped = stream.read_bool() |
||||
self.render_vp_active = stream.read_bool() |
||||
if self.render_vp_active: |
||||
self.render_vp_name = stream.read_string() |
||||
num_params = stream.read_dword() |
||||
self.render_vp_params = [ |
||||
[ |
||||
stream.read_dword(), |
||||
stream.read_float(), |
||||
stream.read_float(), |
||||
stream.read_float(), |
||||
stream.read_float(), |
||||
] for _ in range(num_params) |
||||
] |
||||
self.render_has_light_effects = stream.read_bool() |
||||
if self.render_has_light_effects: |
||||
num_effects = stream.read_dword() |
||||
self.render_light_effects = [ArcLight() for _ in range(num_effects)] |
||||
for effect in self.render_light_effects: |
||||
effect.load_binary(stream) |
||||
|
||||
def save_binary(self, stream: ResStream): |
||||
self.render_template.save_binary(stream) |
||||
stream.write_string(self.render_target_bone) |
||||
stream.write_tuple(self.render_scale) |
||||
stream.write_dword(self.render_has_loc) |
||||
if self.render_has_loc: |
||||
stream.write_tuple(self.render_loc) |
||||
stream.write_dword(len(self.render_children)) |
||||
for child in self.render_children: |
||||
stream.write_qword(child) |
||||
stream.write_bool(self.render_has_texture_set) |
||||
if self.render_has_texture_set: |
||||
stream.write_dword(len(self.render_texture_set)) |
||||
for texture in self.render_texture_set: |
||||
texture.save_binary(stream) |
||||
stream.write_bool(self.render_collides) |
||||
stream.write_bool(self.render_calculate_bounding_box) |
||||
stream.write_bool(self.render_nation_crest) |
||||
stream.write_bool(self.render_guild_crest) |
||||
stream.write_bool(self.render_bumped) |
||||
stream.write_bool(self.render_vp_active) |
||||
if self.render_vp_active: |
||||
stream.write_string(self.render_vp_name) |
||||
|
||||
stream.write_dword(len(self.render_vp_params)) |
||||
for param in self.render_vp_params: |
||||
stream.write_dword(param[0]) |
||||
stream.write_float(param[1]) |
||||
stream.write_float(param[2]) |
||||
stream.write_float(param[3]) |
||||
stream.write_float(param[4]) |
||||
stream.write_bool(self.render_has_light_effects) |
||||
if self.render_has_light_effects: |
||||
stream.write_dword(len(self.render_light_effects)) |
||||
for effect in self.render_light_effects: |
||||
effect.save_binary(stream) |
||||
|
||||
def load_json(self, data): |
||||
self.render_template = ArcRenderTemplate() |
||||
self.render_template.load_json(data['render_template']) |
||||
self.render_target_bone = data['render_target_bone'] |
||||
self.render_scale = data['render_scale'] |
||||
self.render_has_loc = data['render_has_loc'] |
||||
if self.render_has_loc: |
||||
self.render_loc = data['render_loc'] |
||||
self.render_children = data['render_children'] |
||||
self.render_has_texture_set = data['render_has_texture_set'] |
||||
if self.render_has_texture_set: |
||||
self.render_texture_set = [] |
||||
for texture_data in data['render_texture_set']: |
||||
texture = ArcTextureSet() |
||||
texture.load_json(texture_data) |
||||
self.render_texture_set.append(texture) |
||||
self.render_collides = data['render_collides'] |
||||
self.render_calculate_bounding_box = data['render_calculate_bounding_box'] |
||||
self.render_nation_crest = data['render_nation_crest'] |
||||
self.render_guild_crest = data['render_guild_crest'] |
||||
self.render_bumped = data['render_bumped'] |
||||
self.render_vp_active = data['render_vp_active'] |
||||
if self.render_vp_active: |
||||
self.render_vp_name = data['render_vp_name'] |
||||
self.render_vp_params = data['render_vp_params'] |
||||
self.render_has_light_effects = data['render_has_light_effects'] |
||||
if self.render_has_light_effects: |
||||
self.render_light_effects = [] |
||||
for effect_data in data['render_light_effects']: |
||||
effect = ArcLight() |
||||
effect.load_json(effect_data) |
||||
self.render_light_effects.append(effect) |
||||
|
||||
def save_json(self): |
||||
data = OrderedDict() |
||||
data['render_template'] = self.render_template.save_json() |
||||
data['render_target_bone'] = self.render_target_bone |
||||
data['render_scale'] = self.render_scale |
||||
data['render_has_loc'] = self.render_has_loc |
||||
if self.render_has_loc: |
||||
data['render_loc'] = self.render_loc |
||||
data['render_children'] = self.render_children |
||||
data['render_has_texture_set'] = self.render_has_texture_set |
||||
if self.render_has_texture_set: |
||||
data['render_texture_set'] = [] |
||||
for texture in self.render_texture_set: |
||||
data['render_texture_set'].append(texture.save_json()) |
||||
data['render_collides'] = self.render_collides |
||||
data['render_calculate_bounding_box'] = self.render_calculate_bounding_box |
||||
data['render_nation_crest'] = self.render_nation_crest |
||||
data['render_guild_crest'] = self.render_guild_crest |
||||
data['render_bumped'] = self.render_bumped |
||||
data['render_vp_active'] = self.render_vp_active |
||||
if self.render_vp_active: |
||||
data['render_vp_name'] = self.render_vp_name |
||||
data['render_vp_params'] = self.render_vp_params |
||||
data['render_has_light_effects'] = self.render_has_light_effects |
||||
if self.render_has_light_effects: |
||||
data['render_light_effects'] = [] |
||||
for effect in self.render_light_effects: |
||||
data['render_light_effects'].append(effect.save_json()) |
||||
return data |
@ -0,0 +1,125 @@
@@ -0,0 +1,125 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄ |
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪ |
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄ |
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌ |
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪ |
||||
# Magicbane Emulator Project © 2013 - 2022 |
||||
# www.magicbane.com |
||||
|
||||
from collections import OrderedDict |
||||
|
||||
from arcane.util import ResStream |
||||
|
||||
|
||||
class ArcBone: |
||||
def load_binary(self, stream: ResStream): |
||||
self.bone_id = stream.read_dword() |
||||
self.bone_name = stream.read_string() |
||||
self.bone_direction = stream.read_tuple() |
||||
self.bone_length = stream.read_float() |
||||
self.bone_axis = stream.read_tuple() |
||||
self.bone_dof = stream.read_string() |
||||
self.bone_order = stream.read_tuple() |
||||
self.bone_position = stream.read_tuple() |
||||
self.bone_orientation = stream.read_tuple() |
||||
self.bone_u0 = stream.read_bool() |
||||
self.bone_u1 = stream.read_bool() |
||||
|
||||
num = stream.read_dword() |
||||
self.bone_hierarchy = [ArcBone() for _ in range(num)] |
||||
for bone in self.bone_hierarchy: |
||||
bone.load_binary(stream) |
||||
|
||||
def save_binary(self, stream: ResStream): |
||||
stream.write_dword(self.bone_id) |
||||
stream.write_string(self.bone_name) |
||||
stream.write_tuple(self.bone_direction) |
||||
stream.write_float(self.bone_length) |
||||
stream.write_tuple(self.bone_axis) |
||||
stream.write_string(self.bone_dof) |
||||
stream.write_tuple(self.bone_order) |
||||
stream.write_tuple(self.bone_position) |
||||
stream.write_tuple(self.bone_orientation) |
||||
stream.write_bool(self.bone_u0) |
||||
stream.write_bool(self.bone_u1) |
||||
|
||||
stream.write_dword(len(self.bone_hierarchy)) |
||||
for bone in self.bone_hierarchy: |
||||
bone.save_binary(stream) |
||||
|
||||
def load_json(self, data): |
||||
self.bone_id = data['bone_id'] |
||||
self.bone_name = data['bone_name'] |
||||
self.bone_direction = data['bone_direction'] |
||||
self.bone_length = data['bone_length'] |
||||
self.bone_axis = data['bone_axis'] |
||||
self.bone_dof = data['bone_dof'] |
||||
self.bone_order = data['bone_order'] |
||||
self.bone_position = data['bone_position'] |
||||
self.bone_orientation = data['bone_orientation'] |
||||
self.bone_u0 = data['bone_u0'] |
||||
self.bone_u1 = data['bone_u1'] |
||||
|
||||
self.bone_hierarchy = [] |
||||
for bone_data in data['bone_hierarchy']: |
||||
bone = ArcBone() |
||||
bone.load_json(bone_data) |
||||
self.bone_hierarchy.append(bone) |
||||
|
||||
def save_json(self): |
||||
data = OrderedDict() |
||||
data['bone_id'] = self.bone_id |
||||
data['bone_name'] = self.bone_name |
||||
data['bone_direction'] = self.bone_direction |
||||
data['bone_length'] = self.bone_length |
||||
data['bone_axis'] = self.bone_axis |
||||
data['bone_dof'] = self.bone_dof |
||||
data['bone_order'] = self.bone_order |
||||
data['bone_position'] = self.bone_position |
||||
data['bone_orientation'] = self.bone_orientation |
||||
data['bone_u0'] = self.bone_u0 |
||||
data['bone_u1'] = self.bone_u1 |
||||
|
||||
data['bone_hierarchy'] = [] |
||||
for bone in self.bone_hierarchy: |
||||
data['bone_hierarchy'].append(bone.save_json()) |
||||
return data |
||||
|
||||
|
||||
class ArcSkeleton: |
||||
def load_binary(self, stream: ResStream): |
||||
self.skeleton_name = stream.read_string() |
||||
|
||||
num = stream.read_dword() |
||||
self.skeleton_motion = [ |
||||
[ |
||||
stream.read_qword(), |
||||
stream.read_qword(), |
||||
] for _ in range(num) |
||||
] |
||||
|
||||
self.skeleton_root = ArcBone() |
||||
self.skeleton_root.load_binary(stream) |
||||
|
||||
def save_binary(self, stream: ResStream): |
||||
stream.write_string(self.skeleton_name) |
||||
|
||||
stream.write_dword(len(self.skeleton_motion)) |
||||
for i in range(len(self.skeleton_motion)): |
||||
stream.write_qword(self.skeleton_motion[i][0]) |
||||
stream.write_qword(self.skeleton_motion[i][1]) |
||||
|
||||
self.skeleton_root.save_binary(stream) |
||||
|
||||
def load_json(self, data): |
||||
self.skeleton_name = data['skeleton_name'] |
||||
self.skeleton_motion = data['skeleton_motion'] |
||||
self.skeleton_root = ArcBone() |
||||
self.skeleton_root.load_json(data['skeleton_root']) |
||||
|
||||
def save_json(self): |
||||
data = OrderedDict() |
||||
data['skeleton_name'] = self.skeleton_name |
||||
data['skeleton_motion'] = self.skeleton_motion |
||||
data['skeleton_root'] = self.skeleton_root.save_json() |
||||
return data |
@ -0,0 +1,40 @@
@@ -0,0 +1,40 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄ |
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪ |
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄ |
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌ |
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪ |
||||
# Magicbane Emulator Project © 2013 - 2022 |
||||
# www.magicbane.com |
||||
|
||||
from wave import Wave_read, Wave_write |
||||
|
||||
from arcane.util import ResStream |
||||
|
||||
|
||||
class ArcSound: |
||||
def load_binary(self, stream: ResStream): |
||||
data_size = stream.read_dword() |
||||
self.sound_frame_rate = stream.read_dword() |
||||
self.sound_n_channels = stream.read_dword() |
||||
self.sound_sample_width = stream.read_dword() |
||||
self.sound_data = stream.read_bytes(data_size) |
||||
|
||||
def save_binary(self, stream: ResStream): |
||||
data_size = len(self.sound_data) |
||||
stream.write_dword(data_size) |
||||
stream.write_dword(self.sound_frame_rate) |
||||
stream.write_dword(self.sound_n_channels) |
||||
stream.write_dword(self.sound_sample_width) |
||||
stream.write_bytes(self.sound_data) |
||||
|
||||
def load_wav(self, stream: Wave_read): |
||||
self.sound_frame_rate = stream.getframerate() |
||||
self.sound_n_channels = stream.getnchannels() |
||||
self.sound_sample_width = stream.getsampwidth() * 8 |
||||
self.sound_data = stream.readframes(stream.getnframes()) |
||||
|
||||
def save_wav(self, stream: Wave_write): |
||||
stream.setframerate(self.sound_frame_rate) |
||||
stream.setnchannels(self.sound_n_channels) |
||||
stream.setsampwidth(self.sound_sample_width // 8) |
||||
stream.writeframes(self.sound_data) |
@ -0,0 +1,242 @@
@@ -0,0 +1,242 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄ |
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪ |
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄ |
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌ |
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪ |
||||
# Magicbane Emulator Project © 2013 - 2022 |
||||
# www.magicbane.com |
||||
|
||||
from collections import OrderedDict |
||||
|
||||
from arcane.util import ResStream |
||||
|
||||
TILE_TO_STRING = { |
||||
0: "UNKNOWN", |
||||
1: "Regular", |
||||
2: "Slope", |
||||
3: "Road", |
||||
} |
||||
STRING_TO_TILE = {value: key for key, value in TILE_TO_STRING.items()} |
||||
|
||||
MASK_TO_STRING = { |
||||
0: "UNKNOWN", |
||||
1: "Transition", |
||||
2: "Road", |
||||
} |
||||
STRING_TO_MASK = {value: key for key, value in MASK_TO_STRING.items()} |
||||
|
||||
|
||||
class ArcTile: |
||||
def load_binary(self, stream: ResStream): |
||||
self.tile_row_0 = stream.read_dword() |
||||
self.tile_row_1 = stream.read_dword() |
||||
self.tile_row_2 = stream.read_dword() |
||||
self.tile_row_3 = stream.read_dword() |
||||
self.tile_prob = stream.read_float() |
||||
self.tile_type = stream.read_dword() |
||||
|
||||
num_alts = stream.read_dword() |
||||
self.tile_alts = [stream.read_dword() for _ in range(num_alts)] |
||||
|
||||
def save_binary(self, stream: ResStream): |
||||
stream.write_dword(self.tile_row_0) |
||||
stream.write_dword(self.tile_row_1) |
||||
stream.write_dword(self.tile_row_2) |
||||
stream.write_dword(self.tile_row_3) |
||||
stream.write_float(self.tile_prob) |
||||
stream.write_dword(self.tile_type) |
||||
stream.write_dword(len(self.tile_alts)) |
||||
for i in range(len(self.tile_alts)): |
||||
stream.write_dword(self.tile_alts[i]) |
||||
|
||||
def load_json(self, data): |
||||
self.tile_row_0 = data['tile_row_0'] |
||||
self.tile_row_1 = data['tile_row_1'] |
||||
self.tile_row_2 = data['tile_row_2'] |
||||
self.tile_row_3 = data['tile_row_3'] |
||||
self.tile_prob = data['tile_prob'] |
||||
self.tile_type = STRING_TO_TILE[data['tile_type']] |
||||
self.tile_alts = data['tile_alts'] |
||||
|
||||
def save_json(self): |
||||
data = OrderedDict() |
||||
data['tile_row_0'] = self.tile_row_0 |
||||
data['tile_row_1'] = self.tile_row_1 |
||||
data['tile_row_2'] = self.tile_row_2 |
||||
data['tile_row_3'] = self.tile_row_3 |
||||
data['tile_prob'] = self.tile_prob |
||||
data['tile_type'] = TILE_TO_STRING[self.tile_type] |
||||
data['tile_alts'] = self.tile_alts |
||||
return data |
||||
|
||||
|
||||
class ArcTileMask: |
||||
def load_binary(self, stream: ResStream): |
||||
self.mask_row_0 = stream.read_dword() |
||||
self.mask_row_1 = stream.read_dword() |
||||
self.mask_row_2 = stream.read_dword() |
||||
self.mask_row_3 = stream.read_dword() |
||||
self.mask_prob = stream.read_float() |
||||
self.mask_start = stream.read_dword() |
||||
self.mask_end = stream.read_dword() |
||||
self.mask_end1 = stream.read_dword() |
||||
self.mask_end2 = stream.read_dword() |
||||
self.mask_type = stream.read_dword() |
||||
self.mask_width = stream.read_dword() |
||||
|
||||
def save_binary(self, stream: ResStream): |
||||
stream.write_dword(self.mask_row_0) |
||||
stream.write_dword(self.mask_row_1) |
||||
stream.write_dword(self.mask_row_2) |
||||
stream.write_dword(self.mask_row_3) |
||||
stream.write_float(self.mask_prob) |
||||
stream.write_dword(self.mask_start) |
||||
stream.write_dword(self.mask_end) |
||||
stream.write_dword(self.mask_end1) |
||||
stream.write_dword(self.mask_end2) |
||||
stream.write_dword(self.mask_type) |
||||
stream.write_dword(self.mask_width) |
||||
|
||||
def load_json(self, data): |
||||
self.mask_row_0 = data['mask_row_0'] |
||||
self.mask_row_1 = data['mask_row_1'] |
||||
self.mask_row_2 = data['mask_row_2'] |
||||
self.mask_row_3 = data['mask_row_3'] |
||||
self.mask_prob = data['mask_prob'] |
||||
self.mask_start = data['mask_start'] |
||||
self.mask_end = data['mask_end'] |
||||
self.mask_end1 = data['mask_end1'] |
||||
self.mask_end2 = data['mask_end2'] |
||||
self.mask_type = STRING_TO_MASK[data['mask_type']] |
||||
self.mask_width = data['mask_width'] |
||||
|
||||
def save_json(self): |
||||
data = OrderedDict() |
||||
data['mask_row_0'] = self.mask_row_0 |
||||
data['mask_row_1'] = self.mask_row_1 |
||||
data['mask_row_2'] = self.mask_row_2 |
||||
data['mask_row_3'] = self.mask_row_3 |
||||
data['mask_prob'] = self.mask_prob |
||||
data['mask_start'] = self.mask_start |
||||
data['mask_end'] = self.mask_end |
||||
data['mask_end1'] = self.mask_end1 |
||||
data['mask_end2'] = self.mask_end2 |
||||
data['mask_type'] = MASK_TO_STRING[self.mask_type] |
||||
data['mask_width'] = self.mask_width |
||||
return data |
||||
|
||||
|
||||
class ArcTilePattern: |
||||
def load_binary(self, stream: ResStream): |
||||
self.pattern_row_0 = stream.read_dword() |
||||
self.pattern_row_1 = stream.read_dword() |
||||
self.pattern_row_2 = stream.read_dword() |
||||
self.pattern_row_3 = stream.read_dword() |
||||
self.pattern_prob = stream.read_float() |
||||
self.pattern_patx = stream.read_dword() |
||||
self.pattern_patz = stream.read_dword() |
||||
num_tiles = stream.read_dword() |
||||
self.pattern_tiles = [stream.read_dword() for _ in range(num_tiles)] |
||||
|
||||
def save_binary(self, stream: ResStream): |
||||
stream.write_dword(self.pattern_row_0) |
||||
stream.write_dword(self.pattern_row_1) |
||||
stream.write_dword(self.pattern_row_2) |
||||
stream.write_dword(self.pattern_row_3) |
||||
stream.write_float(self.pattern_prob) |
||||
stream.write_dword(self.pattern_patx) |
||||
stream.write_dword(self.pattern_patz) |
||||
stream.write_dword(len(self.pattern_tiles)) |
||||
for i in range(len(self.pattern_tiles)): |
||||
stream.write_dword(self.pattern_tiles[i]) |
||||
|
||||
def load_json(self, data): |
||||
self.pattern_row_0 = data['pattern_row_0'] |
||||
self.pattern_row_1 = data['pattern_row_1'] |
||||
self.pattern_row_2 = data['pattern_row_2'] |
||||
self.pattern_row_3 = data['pattern_row_3'] |
||||
self.pattern_prob = data['pattern_prob'] |
||||
self.pattern_patx = data['pattern_patx'] |
||||
self.pattern_patz = data['pattern_patz'] |
||||
self.pattern_tiles = data['pattern_tiles'] |
||||
|
||||
def save_json(self): |
||||
data = OrderedDict() |
||||
data['pattern_row_0'] = self.pattern_row_0 |
||||
data['pattern_row_1'] = self.pattern_row_1 |
||||
data['pattern_row_2'] = self.pattern_row_2 |
||||
data['pattern_row_3'] = self.pattern_row_3 |
||||
data['pattern_prob'] = self.pattern_prob |
||||
data['pattern_patx'] = self.pattern_patx |
||||
data['pattern_patz'] = self.pattern_patz |
||||
data['pattern_tiles'] = self.pattern_tiles |
||||
return data |
||||
|
||||
|
||||
class ArcTileManager: |
||||
def load_binary(self, stream: ResStream): |
||||
self.manager_texture_width = stream.read_dword() |
||||
self.manager_tile_width = stream.read_dword() |
||||
self.manager_tile_texture = stream.read_qword() |
||||
num_tiles = stream.read_dword() |
||||
self.manager_tiles = [ArcTile() for _ in range(num_tiles)] |
||||
for tile in self.manager_tiles: |
||||
tile.load_binary(stream) |
||||
num_masks = stream.read_dword() |
||||
self.manager_masks = [ArcTileMask() for _ in range(num_masks)] |
||||
for mask in self.manager_masks: |
||||
mask.load_binary(stream) |
||||
num_patterns = stream.read_dword() |
||||
self.manager_patterns = [ArcTilePattern() for _ in range(num_patterns)] |
||||
for pattern in self.manager_patterns: |
||||
pattern.load_binary(stream) |
||||
|
||||
def save_binary(self, stream: ResStream): |
||||
stream.write_dword(self.manager_texture_width) |
||||
stream.write_dword(self.manager_tile_width) |
||||
stream.write_qword(self.manager_tile_texture) |
||||
stream.write_dword(len(self.manager_tiles)) |
||||
for tile in self.manager_tiles: |
||||
tile.save_binary(stream) |
||||
stream.write_dword(len(self.manager_masks)) |
||||
for mask in self.manager_masks: |
||||
mask.save_binary(stream) |
||||
stream.write_dword(len(self.manager_patterns)) |
||||
for pattern in self.manager_patterns: |
||||
pattern.save_binary(stream) |
||||
|
||||
def load_json(self, data): |
||||
self.manager_texture_width = data['manager_texture_width'] |
||||
self.manager_tile_width = data['manager_tile_width'] |
||||
self.manager_tile_texture = data['manager_tile_texture'] |
||||
self.manager_tiles = [] |
||||
for tile_data in data['manager_tiles']: |
||||
tile = ArcTile() |
||||
tile.load_json(tile_data) |
||||
self.manager_tiles.append(tile) |
||||
self.manager_masks = [] |
||||
for mask_data in data['manager_masks']: |
||||
mask = ArcTileMask() |
||||
mask.load_json(mask_data) |
||||
self.manager_masks.append(mask) |
||||
self.manager_patterns = [] |
||||
for pattern_data in data['manager_patterns']: |
||||
pattern = ArcTilePattern() |
||||
pattern.load_json(pattern_data) |
||||
self.manager_patterns.append(pattern) |
||||
|
||||
def save_json(self): |
||||
data = OrderedDict() |
||||
data['manager_texture_width'] = self.manager_texture_width |
||||
data['manager_tile_width'] = self.manager_tile_width |
||||
data['manager_tile_texture'] = self.manager_tile_texture |
||||
data['manager_tiles'] = [] |
||||
for tile in self.manager_tiles: |
||||
data['manager_tiles'].append(tile.save_json()) |
||||
data['manager_masks'] = [] |
||||
for mask in self.manager_masks: |
||||
data['manager_masks'].append(mask.save_json()) |
||||
data['manager_patterns'] = [] |
||||
for pattern in self.manager_patterns: |
||||
data['manager_patterns'].append(pattern.save_json()) |
||||
return data |
@ -0,0 +1,396 @@
@@ -0,0 +1,396 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄ |
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪ |
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄ |
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌ |
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪ |
||||
# Magicbane Emulator Project © 2013 - 2022 |
||||
# www.magicbane.com |
||||
# |
||||
|
||||
|
||||
from base64 import b64decode, b64encode |
||||
from collections import OrderedDict |
||||
|
||||
from arcane.util import ResStream |
||||
|
||||
EFFETCT_TO_STRING = { |
||||
0: 'PARTICLE', |
||||
1: 'LIGHTNING', |
||||
2: 'GEOMETRY', |
||||
} |
||||
|
||||
STRING_TO_EFFECT = {value: key for key, value in EFFETCT_TO_STRING.items()} |
||||
|
||||
|
||||
class ArcParticle: |
||||
def load_binary(self, stream: ResStream): |
||||
self.particle_attached_bone = stream.read_dword() |
||||
self.particle_count = stream.read_dword() |
||||
self.particle_size = stream.read_float() |
||||
self.particle_life = stream.read_float() |
||||
self.particle_life_rand = stream.read_float() |
||||
self.particle_shape_and_pos = stream.read_dword() |
||||
self.particle_emitter_scale = stream.read_float() |
||||
self.particle_pos_offset = stream.read_tuple() |
||||
self.particle_ppos_reference = stream.read_tuple() |
||||
self.particle_initial_velocities = stream.read_dword() |
||||
self.particle_velocity_scale = stream.read_float() |
||||
self.particle_vel_reference = stream.read_tuple() |
||||
self.particle_dir_random = stream.read_float() |
||||
self.particle_spd_random = stream.read_float() |
||||
self.particle_initial_rot = stream.read_float() |
||||
self.particle_initial_rot_random = stream.read_float() |
||||
self.particle_incremental_rot = stream.read_float() |
||||
self.particle_incremental_rot_random = stream.read_float() |
||||
self.particle_color_keys = [ |
||||
[ |
||||
stream.read_float(), |
||||
stream.read_float(), |
||||
stream.read_float(), |
||||
stream.read_float(), |
||||
] for _ in range(5) |
||||
] |
||||
self.particle_color_keytimes = [stream.read_float() for _ in range(5)] |
||||
self.particle_size_keys = [stream.read_float() for _ in range(5)] |
||||
self.particle_targettype = stream.read_dword() |
||||
self.particle_lifetime = stream.read_float() |
||||
self.particle_texture = stream.read_dword() |
||||
self.particle_blend_type = stream.read_dword() |
||||
self.particle_attractor_bone = stream.read_dword() |
||||
self.particle_directional_grav = stream.read_tuple() |
||||
self.particle_field_function = stream.read_dword() |
||||
self.particle_gravity_strength = stream.read_float() |
||||
|
||||
def save_binary(self, stream: ResStream): |
||||
stream.write_dword(self.particle_attached_bone) |
||||
stream.write_dword(self.particle_count) |
||||
stream.write_float(self.particle_size) |
||||
stream.write_float(self.particle_life) |
||||
stream.write_float(self.particle_life_rand) |
||||
stream.write_dword(self.particle_shape_and_pos) |
||||
stream.write_float(self.particle_emitter_scale) |
||||
stream.write_tuple(self.particle_pos_offset) |
||||
stream.write_tuple(self.particle_ppos_reference) |
||||
stream.write_dword(self.particle_initial_velocities) |
||||
stream.write_float(self.particle_velocity_scale) |
||||
stream.write_tuple(self.particle_vel_reference) |
||||
stream.write_float(self.particle_dir_random) |
||||
stream.write_float(self.particle_spd_random) |
||||
stream.write_float(self.particle_initial_rot) |
||||
stream.write_float(self.particle_initial_rot_random) |
||||
stream.write_float(self.particle_incremental_rot) |
||||
stream.write_float(self.particle_incremental_rot_random) |
||||
for i in range(5): |
||||
stream.write_float(self.particle_color_keys[i][0]) |
||||
stream.write_float(self.particle_color_keys[i][1]) |
||||
stream.write_float(self.particle_color_keys[i][2]) |
||||
stream.write_float(self.particle_color_keys[i][3]) |
||||
for i in range(5): |
||||
stream.write_float(self.particle_color_keytimes[i]) |
||||
for i in range(5): |
||||
stream.write_float(self.particle_size_keys[i]) |
||||
stream.write_dword(self.particle_targettype) |
||||
stream.write_float(self.particle_lifetime) |
||||
stream.write_dword(self.particle_texture) |
||||
stream.write_dword(self.particle_blend_type) |
||||
stream.write_dword(self.particle_attractor_bone) |
||||
stream.write_tuple(self.particle_directional_grav) |
||||
stream.write_dword(self.particle_field_function) |
||||
stream.write_float(self.particle_gravity_strength) |
||||
|
||||
def load_json(self, data): |
||||
self.particle_attached_bone = data['particle_attached_bone'] |
||||
self.particle_count = data['particle_count'] |
||||
self.particle_size = data['particle_size'] |
||||
self.particle_life = data['particle_life'] |
||||
self.particle_life_rand = data['particle_life_rand'] |
||||
self.particle_shape_and_pos = data['particle_shape_and_pos'] |
||||
self.particle_emitter_scale = data['particle_emitter_scale'] |
||||
self.particle_pos_offset = data['particle_pos_offset'] |
||||
self.particle_ppos_reference = data['particle_ppos_reference'] |
||||
self.particle_initial_velocities = data['particle_initial_velocities'] |
||||
self.particle_velocity_scale = data['particle_velocity_scale'] |
||||
self.particle_vel_reference = data['particle_vel_reference'] |
||||
self.particle_dir_random = data['particle_dir_random'] |
||||
self.particle_spd_random = data['particle_spd_random'] |
||||
self.particle_initial_rot = data['particle_initial_rot'] |
||||
self.particle_initial_rot_random = data['particle_initial_rot_random'] |
||||
self.particle_incremental_rot = data['particle_incremental_rot'] |
||||
self.particle_incremental_rot_random = data['particle_incremental_rot_random'] |
||||
self.particle_color_keys = data['particle_color_keys'] |
||||
self.particle_color_keytimes = data['particle_color_keytimes'] |
||||
self.particle_size_keys = data['particle_size_keys'] |
||||
self.particle_targettype = data['particle_targettype'] |
||||
self.particle_lifetime = data['particle_lifetime'] |
||||
self.particle_texture = data['particle_texture'] |
||||
self.particle_blend_type = data['particle_blend_type'] |
||||
self.particle_attractor_bone = data['particle_attractor_bone'] |
||||
self.particle_directional_grav = data['particle_directional_grav'] |
||||
self.particle_field_function = data['particle_field_function'] |
||||
self.particle_gravity_strength = data['particle_gravity_strength'] |
||||
|
||||
def save_json(self): |
||||
data = OrderedDict() |
||||
data['particle_attached_bone'] = self.particle_attached_bone |
||||
data['particle_count'] = self.particle_count |
||||
data['particle_size'] = self.particle_size |
||||
data['particle_life'] = self.particle_life |
||||
data['particle_life_rand'] = self.particle_life_rand |
||||
data['particle_shape_and_pos'] = self.particle_shape_and_pos |
||||
data['particle_emitter_scale'] = self.particle_emitter_scale |
||||
data['particle_pos_offset'] = self.particle_pos_offset |
||||
data['particle_ppos_reference'] = self.particle_ppos_reference |
||||
data['particle_initial_velocities'] = self.particle_initial_velocities |
||||
data['particle_velocity_scale'] = self.particle_velocity_scale |
||||
data['particle_vel_reference'] = self.particle_vel_reference |
||||
data['particle_dir_random'] = self.particle_dir_random |
||||
data['particle_spd_random'] = self.particle_spd_random |
||||
data['particle_initial_rot'] = self.particle_initial_rot |
||||
data['particle_initial_rot_random'] = self.particle_initial_rot_random |
||||
data['particle_incremental_rot'] = self.particle_incremental_rot |
||||
data['particle_incremental_rot_random'] = self.particle_incremental_rot_random |
||||
data['particle_color_keys'] = self.particle_color_keys |
||||
data['particle_color_keytimes'] = self.particle_color_keytimes |
||||
data['particle_size_keys'] = self.particle_size_keys |
||||
data['particle_targettype'] = self.particle_targettype |
||||
data['particle_lifetime'] = self.particle_lifetime |
||||
data['particle_texture'] = self.particle_texture |
||||
data['particle_blend_type'] = self.particle_blend_type |
||||
data['particle_attractor_bone'] = self.particle_attractor_bone |
||||
data['particle_directional_grav'] = self.particle_directional_grav |
||||
data['particle_field_function'] = self.particle_field_function |
||||
data['particle_gravity_strength'] = self.particle_gravity_strength |
||||
return data |
||||
|
||||
|
||||
class ArcLightning: |
||||
def load_binary(self, stream: ResStream): |
||||
self.lightning_texture = stream.read_dword() |
||||
self.lightning_src_bone = stream.read_dword() |
||||
self.lightning_dst_bone = stream.read_dword() |
||||
self.lightning_width = stream.read_float() |
||||
self.lightning_random_factor = stream.read_float() |
||||
self.lightning_sine_factor = stream.read_float() |
||||
self.lightning_sine_phase = stream.read_float() |
||||
self.lightning_sine_phase_rep = stream.read_float() |
||||
self.lightning_length = stream.read_float() |
||||
self.lightning_random_move_speed = stream.read_float() |
||||
self.lightning_color = stream.read_tuple() |
||||
self.lightning_lifetime = stream.read_float() |
||||
|
||||
def save_binary(self, stream: ResStream): |
||||
stream.write_dword(self.lightning_texture) |
||||
stream.write_dword(self.lightning_src_bone) |
||||
stream.write_dword(self.lightning_dst_bone) |
||||
stream.write_float(self.lightning_width) |
||||
stream.write_float(self.lightning_random_factor) |
||||
stream.write_float(self.lightning_sine_factor) |
||||
stream.write_float(self.lightning_sine_phase) |
||||
stream.write_float(self.lightning_sine_phase_rep) |
||||
stream.write_float(self.lightning_length) |
||||
stream.write_float(self.lightning_random_move_speed) |
||||
stream.write_tuple(self.lightning_color) |
||||
stream.write_float(self.lightning_lifetime) |
||||
|
||||
def load_json(self, data): |
||||
self.lightning_texture = data['lightning_texture'] |
||||
self.lightning_src_bone = data['lightning_src_bone'] |
||||
self.lightning_dst_bone = data['lightning_dst_bone'] |
||||
self.lightning_width = data['lightning_width'] |
||||
self.lightning_random_factor = data['lightning_random_factor'] |
||||
self.lightning_sine_factor = data['lightning_sine_factor'] |
||||
self.lightning_sine_phase = data['lightning_sine_phase'] |
||||
self.lightning_sine_phase_rep = data['lightning_sine_phase_rep'] |
||||
self.lightning_length = data['lightning_length'] |
||||
self.lightning_random_move_speed = data['lightning_random_move_speed'] |
||||
self.lightning_color = data['lightning_color'] |
||||
self.lightning_lifetime = data['lightning_lifetime'] |
||||
|
||||
def save_json(self): |
||||
data = OrderedDict() |
||||
data['lightning_texture'] = self.lightning_texture |
||||
data['lightning_src_bone'] = self.lightning_src_bone |
||||
data['lightning_dst_bone'] = self.lightning_dst_bone |
||||
data['lightning_width'] = self.lightning_width |
||||
data['lightning_random_factor'] = self.lightning_random_factor |
||||
data['lightning_sine_factor'] = self.lightning_sine_factor |
||||
data['lightning_sine_phase'] = self.lightning_sine_phase |
||||
data['lightning_sine_phase_rep'] = self.lightning_sine_phase_rep |
||||
data['lightning_length'] = self.lightning_length |
||||
data['lightning_random_move_speed'] = self.lightning_random_move_speed |
||||
data['lightning_color'] = self.lightning_color |
||||
data['lightning_lifetime'] = self.lightning_lifetime |
||||
return data |
||||
|
||||
|
||||
class ArcGeometry: |
||||
def load_binary(self, stream: ResStream): |
||||
self.geometry_texture = stream.read_dword() |
||||
self.geometry_src_bone = stream.read_dword() |
||||
self.geometry_lifetime = stream.read_float() |
||||
self.geometry_tex_trans_x = stream.read_float() |
||||
self.geometry_tex_trans_y = stream.read_float() |
||||
self.geometry_tex_rot = stream.read_float() |
||||
self.geometry_grow = stream.read_tuple() |
||||
self.geometry_tesselation = stream.read_float() |
||||
self.geometry_size = stream.read_tuple() |
||||
self.geometry_geo_rot_x = stream.read_float() |
||||
self.geometry_fade_falloff = stream.read_float() |
||||
self.geometry_fadein = stream.read_float() |
||||
self.geometry_fadeout = stream.read_float() |
||||
self.geometry_color = [stream.read_float() for _ in range(4)] |
||||
self.geometry_type = stream.read_dword() |
||||
self.geometry_texture_proj = stream.read_dword() |
||||
self.geometry_fade_dir = stream.read_dword() |
||||
self.geometry_offset = stream.read_tuple() |
||||
|
||||
def save_binary(self, stream: ResStream): |
||||
stream.write_dword(self.geometry_texture) |
||||
stream.write_dword(self.geometry_src_bone) |
||||
stream.write_float(self.geometry_lifetime) |
||||
stream.write_float(self.geometry_tex_trans_x) |
||||
stream.write_float(self.geometry_tex_trans_y) |
||||
stream.write_float(self.geometry_tex_rot) |
||||
stream.write_tuple(self.geometry_grow) |
||||
stream.write_float(self.geometry_tesselation) |
||||
stream.write_tuple(self.geometry_size) |
||||
stream.write_float(self.geometry_geo_rot_x) |
||||
stream.write_float(self.geometry_fade_falloff) |
||||
stream.write_float(self.geometry_fadein) |
||||
stream.write_float(self.geometry_fadeout) |
||||
for i in range(4): |
||||
stream.write_float(self.geometry_color[i]) |
||||
stream.write_dword(self.geometry_type) |
||||
stream.write_dword(self.geometry_texture_proj) |
||||
stream.write_dword(self.geometry_fade_dir) |
||||
stream.write_tuple(self.geometry_offset) |
||||
|
||||
def load_json(self, data): |
||||
self.geometry_texture = data['geometry_texture'] |
||||
self.geometry_src_bone = data['geometry_src_bone'] |
||||
self.geometry_lifetime = data['geometry_lifetime'] |
||||
self.geometry_tex_trans_x = data['geometry_tex_trans_x'] |
||||
self.geometry_tex_trans_y = data['geometry_tex_trans_y'] |
||||
self.geometry_tex_rot = data['geometry_tex_rot'] |
||||
self.geometry_grow = data['geometry_grow'] |
||||
self.geometry_tesselation = data['geometry_tesselation'] |
||||
self.geometry_size = data['geometry_size'] |
||||
self.geometry_geo_rot_x = data['geometry_geo_rot_x'] |
||||
self.geometry_fade_falloff = data['geometry_fade_falloff'] |
||||
self.geometry_fadein = data['geometry_fadein'] |
||||
self.geometry_fadeout = data['geometry_fadeout'] |
||||
self.geometry_color = data['geometry_color'] |
||||
self.geometry_type = data['geometry_type'] |
||||
self.geometry_texture_proj = data['geometry_texture_proj'] |
||||
self.geometry_fade_dir = data['geometry_fade_dir'] |
||||
self.geometry_offset = data['geometry_offset'] |
||||
|
||||
def save_json(self): |
||||
data = OrderedDict() |
||||
data['geometry_texture'] = self.geometry_texture |
||||
data['geometry_src_bone'] = self.geometry_src_bone |
||||
data['geometry_lifetime'] = self.geometry_lifetime |
||||
data['geometry_tex_trans_x'] = self.geometry_tex_trans_x |
||||
data['geometry_tex_trans_y'] = self.geometry_tex_trans_y |
||||
data['geometry_tex_rot'] = self.geometry_tex_rot |
||||
data['geometry_grow'] = self.geometry_grow |
||||
data['geometry_tesselation'] = self.geometry_tesselation |
||||
data['geometry_size'] = self.geometry_size |
||||
data['geometry_geo_rot_x'] = self.geometry_geo_rot_x |
||||
data['geometry_fade_falloff'] = self.geometry_fade_falloff |
||||
data['geometry_fadein'] = self.geometry_fadein |
||||
data['geometry_fadeout'] = self.geometry_fadeout |
||||
data['geometry_color'] = self.geometry_color |
||||
data['geometry_type'] = self.geometry_type |
||||
data['geometry_texture_proj'] = self.geometry_texture_proj |
||||
data['geometry_fade_dir'] = self.geometry_fade_dir |
||||
data['geometry_offset'] = self.geometry_offset |
||||
return data |
||||
|
||||
|
||||
class ArcVisualEffect: |
||||
def load_binary(self, stream: ResStream): |
||||
self.effect_type = stream.read_dword() |
||||
self.effect_time = stream.read_float() |
||||
|
||||
if self.effect_type == 0: |
||||
self.effect = ArcParticle() |
||||
elif self.effect_type == 1: |
||||
self.effect = ArcLightning() |
||||
elif self.effect_type == 2: |
||||
self.effect = ArcGeometry() |
||||
self.effect.load_binary(stream) |
||||
|
||||
def save_binary(self, stream: ResStream): |
||||
stream.write_dword(self.effect_type) |
||||
stream.write_float(self.effect_time) |
||||
self.effect.save_binary(stream) |
||||
|
||||
def load_json(self, data): |
||||
self.effect_type = STRING_TO_EFFECT[data['effect_type']] |
||||
self.effect_time = data['effect_time'] |
||||
if self.effect_type == 0: |
||||
self.effect = ArcParticle() |
||||
elif self.effect_type == 1: |
||||
self.effect = ArcLightning() |
||||
elif self.effect_type == 2: |
||||
self.effect = ArcGeometry() |
||||
self.effect.load_json(data['effect']) |
||||
|
||||
def save_json(self): |
||||
data = OrderedDict() |
||||
data['effect_type'] = EFFETCT_TO_STRING[self.effect_type] |
||||
data['effect_time'] = self.effect_time |
||||
data['effect'] = self.effect.save_json() |
||||
return data |
||||
|
||||
|
||||
class ArcVisual: |
||||
def load_binary(self, stream: ResStream): |
||||
num_effects = stream.read_dword() |
||||
|
||||
self.vfx_fail = None |
||||
if num_effects == 1617156728: |
||||
stream.buffer.seek(0, 0) |
||||
self.vfx_fail = stream.buffer.read() |
||||
return |
||||
|
||||
self.vfx_duration = stream.read_float() |
||||
self.vfx_effects = [ArcVisualEffect() for _ in range(num_effects)] |
||||
for effect in self.vfx_effects: |
||||
effect.load_binary(stream) |
||||
|
||||
def save_binary(self, stream: ResStream): |
||||
if self.vfx_fail: |
||||
stream.buffer.write(self.vfx_fail) |
||||
return |
||||
|
||||
stream.write_dword(len(self.vfx_effects)) |
||||
stream.write_float(self.vfx_duration) |
||||
for effect in self.vfx_effects: |
||||
effect.save_binary(stream) |
||||
|
||||
def load_json(self, data): |
||||
self.vfx_fail = data.get('vfx_fail') |
||||
if self.vfx_fail: |
||||
self.vfx_fail = b64decode(self.vfx_fail) |
||||
return |
||||
|
||||
self.vfx_duration = data['vfx_duration'] |
||||
self.vfx_effects = [] |
||||
for effect_data in data['vfx_effects']: |
||||
effect = ArcVisualEffect() |
||||
effect.load_json(effect_data) |
||||
self.vfx_effects.append(effect) |
||||
|
||||
def save_json(self): |
||||
data = OrderedDict() |
||||
if self.vfx_fail: |
||||
data['vfx_fail'] = b64encode(self.vfx_fail).decode() |
||||
return data |
||||
|
||||
data['vfx_duration'] = self.vfx_duration |
||||
data['vfx_effects'] = [] |
||||
for effect in self.vfx_effects: |
||||
data['vfx_effects'].append(effect.save_json()) |
||||
return data |
@ -0,0 +1,7 @@
@@ -0,0 +1,7 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄ |
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪ |
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄ |
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌ |
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪ |
||||
# Magicbane Emulator Project © 2013 - 2022 |
||||
# www.magicbane.com |
@ -0,0 +1,7 @@
@@ -0,0 +1,7 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄ |
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪ |
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄ |
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌ |
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪ |
||||
# Magicbane Emulator Project © 2013 - 2022 |
||||
# www.magicbane.com |
@ -0,0 +1,7 @@
@@ -0,0 +1,7 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄ |
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪ |
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄ |
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌ |
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪ |
||||
# Magicbane Emulator Project © 2013 - 2022 |
||||
# www.magicbane.com |
@ -0,0 +1,23 @@
@@ -0,0 +1,23 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄ |
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪ |
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄ |
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌ |
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪ |
||||
# Magicbane Emulator Project © 2013 - 2022 |
||||
# www.magicbane.com |
||||
|
||||
INVENTORY_TYPE_GOLD = 1 |
||||
INVENTORY_TYPE_ITEM = 2 |
||||
INVENTORY_TYPE_BOOTYTABLE = 3 |
||||
|
||||
INVENTORY_TYPE_TO_STRING = { |
||||
INVENTORY_TYPE_GOLD: 'GOLD', |
||||
INVENTORY_TYPE_ITEM: 'ITEM', |
||||
INVENTORY_TYPE_BOOTYTABLE: 'BOOTYTABLE', |
||||
} |
||||
|
||||
STRING_TO_INVENTORY_TYPE = { |
||||
'GOLD': INVENTORY_TYPE_GOLD, |
||||
'ITEM': INVENTORY_TYPE_ITEM, |
||||
'BOOTYTABLE': INVENTORY_TYPE_BOOTYTABLE, |
||||
} |
@ -0,0 +1,41 @@
@@ -0,0 +1,41 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄ |
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪ |
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄ |
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌ |
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪ |
||||
# Magicbane Emulator Project © 2013 - 2022 |
||||
# www.magicbane.com |
||||
|
||||
import glob |
||||
import os |
||||
|
||||
from arcane.util.hasher import hash_string |
||||
|
||||
_STRING_TO_HASH = {} |
||||
_HASH_TO_STRING = {} |
||||
|
||||
|
||||
def load_files(): |
||||
directory = os.path.dirname(__file__) |
||||
|
||||
for filepath in glob.glob(os.path.join(directory, '*.txt')): |
||||
lines = list(map(lambda s: s.strip(), open(filepath).readlines())) |
||||
|
||||
_STRING_TO_HASH.update({ |
||||
s: hash_string(s) for s in lines |
||||
}) |
||||
|
||||
_HASH_TO_STRING.update({ |
||||
hash_string(s): s for s in lines |
||||
}) |
||||
|
||||
|
||||
def string_to_hash(s): |
||||
return _STRING_TO_HASH.get(s, s) |
||||
|
||||
|
||||
def hash_to_string(h): |
||||
return _HASH_TO_STRING.get(h, h) |
||||
|
||||
|
||||
load_files() |
@ -0,0 +1,38 @@
@@ -0,0 +1,38 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄ |
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪ |
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄ |
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌ |
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪ |
||||
# Magicbane Emulator Project © 2013 - 2022 |
||||
# www.magicbane.com |
||||
|
||||
MOBILE = 1 |
||||
BANKER = 2 |
||||
SHOPKEEPER = 3 |
||||
TRAINER = 4 |
||||
MERCHANT = 8 |
||||
HIRELING = 9 |
||||
PET = 10 |
||||
MINION = 11 |
||||
|
||||
MOBILE_TO_STRING = { |
||||
MOBILE: 'MOBILE', |
||||
BANKER: 'BANKER', |
||||
SHOPKEEPER: 'SHOPKEEPER', |
||||
TRAINER: 'TRAINER', |
||||
MERCHANT: 'MERCHANT', |
||||
HIRELING: 'HIRELING', |
||||
PET: 'PET', |
||||
MINION: 'MINION', |
||||
} |
||||
|
||||
STRING_TO_MOBILE = { |
||||
'MOBILE': MOBILE, |
||||
'BANKER': BANKER, |
||||
'SHOPKEEPER': SHOPKEEPER, |
||||
'TRAINER': TRAINER, |
||||
'MERCHANT': MERCHANT, |
||||
'HIRELING': HIRELING, |
||||
'PET': PET, |
||||
'MINION': MINION, |
||||
} |
@ -0,0 +1,23 @@
@@ -0,0 +1,23 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄ |
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪ |
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄ |
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌ |
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪ |
||||
# Magicbane Emulator Project © 2013 - 2022 |
||||
# www.magicbane.com |
||||
|
||||
PROP = 5 |
||||
CITY = 6 |
||||
CONTAINER = 7 |
||||
|
||||
PROP_TO_STRING = { |
||||
PROP: 'PROP', |
||||
CITY: 'CITY', |
||||
CONTAINER: 'CONTAINER', |
||||
} |
||||
|
||||
STRING_TO_PROP = { |
||||
'PROP': PROP, |
||||
'CITY': CITY, |
||||
'CONTAINER': CONTAINER, |
||||
} |
@ -0,0 +1,35 @@
@@ -0,0 +1,35 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄ |
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪ |
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄ |
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌ |
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪ |
||||
# Magicbane Emulator Project © 2013 - 2022 |
||||
# www.magicbane.com |
||||
|
||||
PEAKED = 1 |
||||
RIDGED = 2 |
||||
ROLLING = 3 |
||||
MESA = 5 |
||||
PLANAR = 4 |
||||
MESH = 6 |
||||
TARGA = 7 |
||||
|
||||
TERRAIN_TYPE_TO_STRING = { |
||||
PEAKED: 'PEAKED', |
||||
RIDGED: 'RIDGED', |
||||
ROLLING: 'ROLLING', |
||||
MESA: 'MESA', |
||||
PLANAR: 'PLANAR', |
||||
MESH: 'MESH', |
||||
TARGA: 'TARGA', |
||||
} |
||||
|
||||
STRING_TO_TERRAIN_TYPE = { |
||||
'PEAKED': PEAKED, |
||||
'RIDGED': RIDGED, |
||||
'ROLLING': ROLLING, |
||||
'MESA': MESA, |
||||
'PLANAR': PLANAR, |
||||
'MESH': MESH, |
||||
'TARGA': TARGA, |
||||
} |
@ -0,0 +1,62 @@
@@ -0,0 +1,62 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄ |
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪ |
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄ |
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌ |
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪ |
||||
# Magicbane Emulator Project © 2013 - 2022 |
||||
# www.magicbane.com |
||||
|
||||
ELLIPTICAL = 0 |
||||
RECTANGULAR = 1 |
||||
|
||||
ZONE_TO_STRING = { |
||||
ELLIPTICAL: 'ELLIPTICAL', |
||||
RECTANGULAR: 'RECTANGULAR', |
||||
} |
||||
|
||||
STRING_TO_ZONE = { |
||||
'ELLIPTICAL': ELLIPTICAL, |
||||
'RECTANGULAR': RECTANGULAR, |
||||
} |
||||
|
||||
GLOBAL = 0 |
||||
LOCAL = 1 |
||||
|
||||
TILECOORD_TO_STRING = { |
||||
GLOBAL: 'GLOBAL', |
||||
LOCAL: 'LOCAL', |
||||
} |
||||
|
||||
STRING_TO_TILECOORD = { |
||||
'GLOBAL': GLOBAL, |
||||
'LOCAL': LOCAL, |
||||
} |
||||
|
||||
ADJACENT = 0 |
||||
RANDOM = 1 |
||||
|
||||
PATTERN_TO_STRING = { |
||||
ADJACENT: 'ADJACENT', |
||||
RANDOM: 'RANDOM', |
||||
} |
||||
|
||||
STRING_TO_PATTERN = { |
||||
'ADJACENT': ADJACENT, |
||||
'RANDOM': RANDOM, |
||||
} |
||||
|
||||
PARENT = 0 |
||||
WORLD = 1 |
||||
SELF = 2 |
||||
|
||||
SEALEVEL_TO_STRING = { |
||||
PARENT: 'PARENT', |
||||
WORLD: 'WORLD', |
||||
SELF: 'SELF', |
||||
} |
||||
|
||||
STRING_TO_SEALEVEL = { |
||||
'PARENT': PARENT, |
||||
'WORLD': WORLD, |
||||
'SELF': SELF, |
||||
} |
@ -0,0 +1,29 @@
@@ -0,0 +1,29 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄ |
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪ |
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄ |
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌ |
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪ |
||||
# Magicbane Emulator Project © 2013 - 2022 |
||||
# www.magicbane.com |
||||
|
||||
from arcane.util import ResStream |
||||
from .ArcStructureObject import ArcStructureObject |
||||
|
||||
|
||||
class ArcAssetStructureObject(ArcStructureObject): |
||||
def load_binary(self, stream: ResStream): |
||||
super().load_binary(stream) |
||||
self.asset_structure_template_id = stream.read_qword() |
||||
|
||||
def save_binary(self, stream: ResStream): |
||||
super().save_binary(stream) |
||||
stream.write_qword(self.asset_structure_template_id) |
||||
|
||||
def load_json(self, data): |
||||
super().load_json(data) |
||||
self.asset_structure_template_id = data['asset_structure_template_id'] |
||||
|
||||
def save_json(self): |
||||
data = super().save_json() |
||||
data['asset_structure_template_id'] = self.asset_structure_template_id |
||||
return data |
@ -0,0 +1,21 @@
@@ -0,0 +1,21 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄ |
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪ |
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄ |
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌ |
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪ |
||||
# Magicbane Emulator Project © 2013 - 2022 |
||||
# www.magicbane.com |
||||
|
||||
from .ArcAssetStructureObject import ArcAssetStructureObject |
||||
from .ArcCityAssetTemplate import ArcCityAssetTemplate |
||||
from .ArcCombatObj import ArcCombatObj, ArcCharacter |
||||
from .ArcContainerObject import ArcContainerObject |
||||
from .ArcDeed import ArcDeed |
||||
from .ArcDoorObject import ArcDoorObject |
||||
from .ArcDungeonUnitObject import ArcDungeonUnitObject, ArcDungeonExitObject, ArcDungeonStairObject |
||||
from .ArcItem import ArcItem |
||||
from .ArcKey import ArcKey |
||||
from .ArcObj import ArcObj |
||||
from .ArcRune import ArcRune |
||||
from .ArcStaticObject import ArcStaticObject |
||||
from .ArcStructureObject import ArcStructureObject |
@ -0,0 +1,41 @@
@@ -0,0 +1,41 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄ |
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪ |
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄ |
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌ |
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪ |
||||
# Magicbane Emulator Project © 2013 - 2022 |
||||
# www.magicbane.com |
||||
|
||||
from collections import OrderedDict |
||||
|
||||
from arcane.enums.hashes import hash_to_string, string_to_hash |
||||
from arcane.util import ResStream |
||||
|
||||
|
||||
class DiscRequired: |
||||
def load_binary(self, stream: ResStream): |
||||
discs = stream.read_dword() |
||||
self.disc_restrict = stream.read_bool() |
||||
self.disc_values = [ |
||||
stream.read_dword() for _ in range(discs) |
||||
] |
||||
|
||||
def save_binary(self, stream: ResStream): |
||||
stream.write_dword(len(self.disc_values)) |
||||
stream.write_bool(self.disc_restrict) |
||||
for disc in self.disc_values: |
||||
stream.write_dword(disc) |
||||
|
||||
def load_json(self, data): |
||||
self.disc_restrict = data['restrict'] |
||||
self.disc_values = [] |
||||
for disc in data['discs']: |
||||
self.disc_values.append(string_to_hash(disc)) |
||||
|
||||
def save_json(self): |
||||
data = OrderedDict() |
||||
data['restrict'] = self.disc_restrict |
||||
data['discs'] = [] |
||||
for disc in self.disc_values: |
||||
data['discs'].append(hash_to_string(disc)) |
||||
return data |
@ -0,0 +1,41 @@
@@ -0,0 +1,41 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄ |
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪ |
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄ |
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌ |
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪ |
||||
# Magicbane Emulator Project © 2013 - 2022 |
||||
# www.magicbane.com |
||||
|
||||
from collections import OrderedDict |
||||
|
||||
from arcane.enums.hashes import hash_to_string, string_to_hash |
||||
from arcane.util import ResStream |
||||
|
||||
|
||||
class RaceRequired: |
||||
def load_binary(self, stream: ResStream): |
||||
races = stream.read_dword() |
||||
self.race_restrict = stream.read_bool() |
||||
self.race_values = [ |
||||
stream.read_dword() for _ in range(races) |
||||
] |
||||
|
||||
def save_binary(self, stream: ResStream): |
||||
stream.write_dword(len(self.race_values)) |
||||
stream.write_bool(self.race_restrict) |
||||
for race in self.race_values: |
||||
stream.write_dword(race) |
||||
|
||||
def load_json(self, data): |
||||
self.race_restrict = data['restrict'] |
||||
self.race_values = [] |
||||
for race in data['races']: |
||||
self.race_values.append(string_to_hash(race)) |
||||
|
||||
def save_json(self): |
||||
data = OrderedDict() |
||||
data['restrict'] = self.race_restrict |
||||
data['races'] = [] |
||||
for race in self.race_values: |
||||
data['races'].append(hash_to_string(race)) |
||||
return data |
@ -0,0 +1,7 @@
@@ -0,0 +1,7 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄ |
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪ |
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄ |
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌ |
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪ |
||||
# Magicbane Emulator Project © 2013 - 2022 |
||||
# www.magicbane.com |
@ -0,0 +1,10 @@
@@ -0,0 +1,10 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄ |
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪ |
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄ |
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌ |
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪ |
||||
# Magicbane Emulator Project © 2013 - 2022 |
||||
# www.magicbane.com |
||||
|
||||
from .ArcFileCache import load_cache_file, save_cache_file |
||||
from .ResStream import ResStream |
@ -0,0 +1,19 @@
@@ -0,0 +1,19 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄ |
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪ |
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄ |
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌ |
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪ |
||||
# Magicbane Emulator Project © 2013 - 2022 |
||||
# www.magicbane.com |
||||
# |
||||
|
||||
def int32(x): |
||||
if x > 0xFFFFFFFF: |
||||
raise OverflowError |
||||
if x > 0x7FFFFFFF: |
||||
x = int(0x100000000 - x) |
||||
if x < 2147483648: |
||||
return -x |
||||
else: |
||||
return -2147483648 |
||||
return x |
@ -0,0 +1,39 @@
@@ -0,0 +1,39 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄ |
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪ |
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄ |
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌ |
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪ |
||||
# Magicbane Emulator Project © 2013 - 2022 |
||||
# www.magicbane.com |
||||
|
||||
from collections import OrderedDict |
||||
|
||||
from arcane.util import ResStream |
||||
|
||||
|
||||
class ArcDungeonInfo: |
||||
def load_binary(self, stream: ResStream): |
||||
self.dungeon_template_id = stream.read_qword() |
||||
self.dungeon_unknown = stream.read_qword() |
||||
self.dungeon_spawn_location = stream.read_tuple() |
||||
self.dungeon_y_offset = stream.read_float() |
||||
|
||||
def save_binary(self, stream: ResStream): |
||||
stream.write_qword(self.dungeon_template_id) |
||||
stream.write_qword(self.dungeon_unknown) |
||||
stream.write_tuple(self.dungeon_spawn_location) |
||||
stream.write_float(self.dungeon_y_offset) |
||||
|
||||
def save_json(self): |
||||
data = OrderedDict() |
||||
data['dungeon_template_id'] = self.dungeon_template_id |
||||
data['dungeon_unknown'] = self.dungeon_unknown |
||||
data['dungeon_spawn_location'] = self.dungeon_spawn_location |
||||
data['dungeon_y_offset'] = self.dungeon_y_offset |
||||
return data |
||||
|
||||
def load_json(self, data): |
||||
self.dungeon_template_id = data['dungeon_template_id'] |
||||
self.dungeon_unknown = data['dungeon_unknown'] |
||||
self.dungeon_spawn_location = data['dungeon_spawn_location'] |
||||
self.dungeon_y_offset = data['dungeon_y_offset'] |
@ -0,0 +1,9 @@
@@ -0,0 +1,9 @@
|
||||
# • ▌ ▄ ·. ▄▄▄▄· ▄▄▄ .·▄▄▄▄ ▪ ▄▄▄▄▄ ▄▄▄ ▄▄▄·▄▄▄ |
||||
# ·██ ▐███▪▐█ ▀█▪ ▀▄.▀·██▪ ██ ██ •██ ▪ ▀▄ █· ▐█ ▄█▀▄ █·▪ |
||||
# ▐█ ▌▐▌▐█·▐█▀▀█▄ ▐▀▀▪▄▐█· ▐█▌▐█· ▐█.▪ ▄█▀▄ ▐▀▀▄ ██▀·▐▀▀▄ ▄█▀▄ |
||||
# ██ ██▌▐█▌██▄▪▐█ ▐█▄▄▌██. ██ ▐█▌ ▐█▌·▐█▌.▐▌▐█•█▌ ▐█▪·•▐█•█▌▐█▌.▐▌ |
||||
# ▀▀ █▪▀▀▀·▀▀▀▀ ▀▀▀ ▀▀▀▀▀• ▀▀▀ ▀▀▀ ▀█▄▀▪.▀ ▀ .▀ .▀ ▀ ▀█▄▀▪ |
||||
# Magicbane Emulator Project © 2013 - 2022 |
||||
# www.magicbane.com |
||||
|
||||
from .ArcZone import ArcZone |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue