I also made a model XML file that my program should be able to load. Every entry consists of basic stats about when to spawn it (name, tags, best dungeon level, frequency, etc.) then a "Classdata" tag that contains attributes specific to what type of thing it is (Basic Item? Basic Monster? Container? Weapon?) For a monster, this would include the combat map that my other tool generated, for a weapon, it's the strength, throwing range, what tool will make it go farther etc. It's also possible to "inherit" a stat from another item, so all humanoids can inherit the combat map from the player object. You can inherit everything from another entry, or just one stat.
I programmed it to load the file, and check the inheritance, output looks like this:
('CPP agent', (1, ('ITM_MONSTER', 'ITM_HUMANOID'), 'Human', {'speed': '120', 'attack_zones': {'rectangle': [{'slot': 'Head', 'damage': {'bio': '1', 'rad': '1', 'gas': '1', 'ele': '1', 'phis': '2', 'hea': '1', 'las': '2'}, 'dimentions': {'width': '18', 'top': '10', 'height': '16', 'left': '32'}}, {'slot': 'Body', 'damage': {'bio': '0', 'rad': '0', 'gas': '0', 'ele': '0', 'phis': '1', 'hea': '0', 'las': '0'}, 'dimentions': {'width': '18', 'top': '26', 'height': '17', 'left': '31'}}, {'slot': 'Body', 'damage': {'bio': '0', 'rad': '0', 'gas': '0', 'ele': '0', 'phis': '1', 'hea': '0', 'las': '0'}, 'dimentions': {'width': '6', 'top': '44', 'height': '7', 'left': '42'}}, {'slot': 'Body', 'damage': {'bio': '0', 'rad': '0', 'gas': '0', 'ele': '0', 'phis': '1', 'hea': '0', 'las': '0'}, 'dimentions': {'width': '18', 'top': '53', 'height': '7', 'left': '30'}}, {'slot': 'Legs', 'damage': {'bio': '0', 'rad': '0', 'gas': '0', 'ele': '0', 'phis': '1', 'hea': '0', 'las': '0'}, 'dimentions': {'width': '6', 'top': '62', 'height': '20', 'left': '42'}}, {'slot': 'Feet', 'damage': {'bio': '0', 'rad': '0', 'gas': '0', 'ele': '0', 'phis': '1', 'hea': '0', 'las': '0'}, 'dimentions': {'width': '10', 'top': '84', 'height': '4', 'left': '41'}}, {'slot': 'Feet', 'damage': {'bio': '0', 'rad': '0', 'gas': '0', 'ele': '0', 'phis': '1', 'hea': '0', 'las': '0'}, 'dimentions': {'width': '-10', 'top': '84', 'height': '5', 'left': '38'}}, {'slot': 'Legs', 'damage': {'bio': '0', 'rad': '0', 'gas': '0', 'ele': '0', 'phis': '1', 'hea': '0', 'las': '0'}, 'dimentions': {'width': '5', 'top': '62', 'height': '20', 'left': '32'}}, {'slot': 'Body', 'damage': {'bio': '0', 'rad': '0', 'gas': '0', 'ele': '0', 'phis': '1', 'hea': '0', 'las': '0'}, 'dimentions': {'width': '4', 'top': '28', 'height': '26', 'left': '52'}}, {'slot': 'Body', 'damage': {'bio': '0', 'rad': '0', 'gas': '0', 'ele': '0', 'phis': '1', 'hea': '0', 'las': '0'}, 'dimentions': {'width': '4', 'top': '32', 'height': '21', 'left': '24'}}, {'slot': 'Head', 'damage': {'bio': '0', 'rad': '0.25', 'gas': '0', 'ele': '2', 'phis': '0', 'hea': '0', 'las': '0'}, 'dimentions': {'width': '16', 'top': '4', 'height': '5', 'left': '34'}}, {'slot': 'Hands', 'damage': {'bio': '0', 'rad': '0', 'gas': '0', 'ele': '0', 'phis': '1', 'hea': '0', 'las': '0'}, 'dimentions': {'width': '4', 'top': '54', 'height': '3', 'left': '52'}}, {'slot': 'Hands', 'damage': {'bio': '0', 'rad': '0', 'gas': '0', 'ele': '0', 'phis': '1', 'hea': '0', 'las': '0'}, 'dimentions': {'width': '4', 'top': '54', 'height': '3', 'left': '24'}}]}, 'image_name': 'hero.png', 'advanced visibility check': 'True'}))('Goku', (4, (), 'Teleporters', {'speed': '120', 'attack_zones': {'rectangle': [{'slot': 'Head', 'damage': {'bio': '1', 'rad': '1', 'gas': '1', 'ele': '1', 'phis': '2', 'hea': '1', 'las': '2'}, 'dimentions': {'width': '18', 'top': '10', 'height': '16', 'left': '32'}}, {'slot': 'Body', 'damage': {'bio': '0', 'rad': '0', 'gas': '0', 'ele': '0', 'phis': '1', 'hea': '0', 'las': '0'}, 'dimentions': {'width': '18', 'top': '26', 'height': '17', 'left': '31'}}, {'slot': 'Body', 'damage': {'bio': '0', 'rad': '0', 'gas': '0', 'ele': '0', 'phis': '1', 'hea': '0', 'las': '0'}, 'dimentions': {'width': '6', 'top': '44', 'height': '7', 'left': '42'}}, {'slot': 'Body', 'damage': {'bio': '0', 'rad': '0', 'gas': '0', 'ele': '0', 'phis': '1', 'hea': '0', 'las': '0'}, 'dimentions': {'width': '18', 'top': '53', 'height': '7', 'left': '30'}}, {'slot': 'Legs', 'damage': {'bio': '0', 'rad': '0', 'gas': '0', 'ele': '0', 'phis': '1', 'hea': '0', 'las': '0'}, 'dimentions': {'width': '6', 'top': '62', 'height': '20', 'left': '42'}}, {'slot': 'Feet', 'damage': {'bio': '0', 'rad': '0', 'gas': '0', 'ele': '0', 'phis': '1', 'hea': '0', 'las': '0'}, 'dimentions': {'width': '10', 'top': '84', 'height': '4', 'left': '41'}}, {'slot': 'Feet', 'damage': {'bio': '0', 'rad': '0', 'gas': '0', 'ele': '0', 'phis': '1', 'hea': '0', 'las': '0'}, 'dimentions': {'width': '-10', 'top': '84', 'height': '5', 'left': '38'}}, {'slot': 'Legs', 'damage': {'bio': '0', 'rad': '0', 'gas': '0', 'ele': '0', 'phis': '1', 'hea': '0', 'las': '0'}, 'dimentions': {'width': '5', 'top': '62', 'height': '20', 'left': '32'}}, {'slot': 'Body', 'damage': {'bio': '0', 'rad': '0', 'gas': '0', 'ele': '0', 'phis': '1', 'hea': '0', 'las': '0'}, 'dimentions': {'width': '4', 'top': '28', 'height': '26', 'left': '52'}}, {'slot': 'Body', 'damage': {'bio': '0', 'rad': '0', 'gas': '0', 'ele': '0', 'phis': '1', 'hea': '0', 'las': '0'}, 'dimentions': {'width': '4', 'top': '32', 'height': '21', 'left': '24'}}, {'slot': 'Head', 'damage': {'bio': '0', 'rad': '0.25', 'gas': '0', 'ele': '2', 'phis': '0', 'hea': '0', 'las': '0'}, 'dimentions': {'width': '16', 'top': '4', 'height': '5', 'left': '34'}}, {'slot': 'Hands', 'damage': {'bio': '0', 'rad': '0', 'gas': '0', 'ele': '0', 'phis': '1', 'hea': '0', 'las': '0'}, 'dimentions': {'width': '4', 'top': '54', 'height': '3', 'left': '52'}}, {'slot': 'Hands', 'damage': {'bio': '0', 'rad': '0', 'gas': '0', 'ele': '0', 'phis': '1', 'hea': '0', 'las': '0'}, 'dimentions': {'width': '4', 'top': '54', 'height': '3', 'left': '24'}}]}, 'image_name': 'Goku.png', 'advanced visibility check': 'True'}))('human', (0, ('ITM_MONSTER', 'ITM_HUMANOID'), 'Human', {'attack_zones': {'rectangle': [{'slot': 'Head', 'damage': {'bio': '1', 'rad': '1', 'gas': '1', 'ele': '1', 'phis': '2', 'hea': '1', 'las': '2'}, 'dimentions': {'width': '18', 'top': '10', 'height': '16', 'left': '32'}}, {'slot': 'Body', 'damage': {'bio': '0', 'rad': '0', 'gas': '0', 'ele': '0', 'phis': '1', 'hea': '0', 'las': '0'}, 'dimentions': {'width': '18', 'top': '26', 'height': '17', 'left': '31'}}, {'slot': 'Body', 'damage': {'bio': '0', 'rad': '0', 'gas': '0', 'ele': '0', 'phis': '1', 'hea': '0', 'las': '0'}, 'dimentions': {'width': '6', 'top': '44', 'height': '7', 'left': '42'}}, {'slot': 'Body', 'damage': {'bio': '0', 'rad': '0', 'gas': '0', 'ele': '0', 'phis': '1', 'hea': '0', 'las': '0'}, 'dimentions': {'width': '18', 'top': '53', 'height': '7', 'left': '30'}}, {'slot': 'Legs', 'damage': {'bio': '0', 'rad': '0', 'gas': '0', 'ele': '0', 'phis': '1', 'hea': '0', 'las': '0'}, 'dimentions': {'width': '6', 'top': '62', 'height': '20', 'left': '42'}}, {'slot': 'Feet', 'damage': {'bio': '0', 'rad': '0', 'gas': '0', 'ele': '0', 'phis': '1', 'hea': '0', 'las': '0'}, 'dimentions': {'width': '10', 'top': '84', 'height': '4', 'left': '41'}}, {'slot': 'Feet', 'damage': {'bio': '0', 'rad': '0', 'gas': '0', 'ele': '0', 'phis': '1', 'hea': '0', 'las': '0'}, 'dimentions': {'width': '-10', 'top': '84', 'height': '5', 'left': '38'}}, {'slot': 'Legs', 'damage': {'bio': '0', 'rad': '0', 'gas': '0', 'ele': '0', 'phis': '1', 'hea': '0', 'las': '0'}, 'dimentions': {'width': '5', 'top': '62', 'height': '20', 'left': '32'}}, {'slot': 'Body', 'damage': {'bio': '0', 'rad': '0', 'gas': '0', 'ele': '0', 'phis': '1', 'hea': '0', 'las': '0'}, 'dimentions': {'width': '4', 'top': '28', 'height': '26', 'left': '52'}}, {'slot': 'Body', 'damage': {'bio': '0', 'rad': '0', 'gas': '0', 'ele': '0', 'phis': '1', 'hea': '0', 'las': '0'}, 'dimentions': {'width': '4', 'top': '32', 'height': '21', 'left': '24'}}, {'slot': 'Head', 'damage': {'bio': '0', 'rad': '0.25', 'gas': '0', 'ele': '2', 'phis': '0', 'hea': '0', 'las': '0'}, 'dimentions': {'width': '16', 'top': '4', 'height': '5', 'left': '34'}}, {'slot': 'Hands', 'damage': {'bio': '0', 'rad': '0', 'gas': '0', 'ele': '0', 'phis': '1', 'hea': '0', 'las': '0'}, 'dimentions': {'width': '4', 'top': '54', 'height': '3', 'left': '52'}}, {'slot': 'Hands', 'damage': {'bio': '0', 'rad': '0', 'gas': '0', 'ele': '0', 'phis': '1', 'hea': '0', 'las': '0'}, 'dimentions': {'width': '4', 'top': '54', 'height': '3', 'left': '24'}}]}, 'speed': '100', 'image_name': 'hero.png', 'advanced visibility check': 'True'}))
from this XML file: (I don't expect anybody to read this)
[spoiler]
0 human ITM_MONSTER ITM_HUMANOID Human 100 hero.png 32 10 18 16 2 1 2 1 1 1 1Head 31 26 18 17 1 0 0 0 0 0 0Body 42 44 6 7 1 0 0 0 0 0 0Body 30 53 18 7 1 0 0 0 0 0 0Body 42 62 6 20 1 0 0 0 0 0 0Legs 41 84 10 4 1 0 0 0 0 0 0Feet 38 84 -10 5 1 0 0 0 0 0 0Feet 32 62 5 20 1 0 0 0 0 0 0Legs 52 28 4 26 1 0 0 0 0 0 0Body 24 32 4 21 1 0 0 0 0 0 0Body 34 4 16 5 0 2 0 0 0.25 0 0Head 52 54 4 3 1 0 0 0 0 0 0Hands 24 54 4 3 1 0 0 0 0 0 0Hands True CPP agent 1 ITM_MONSTER ITM_HUMANOID Human 120 Goku 4 Teleporters Goku.png
[/spoiler]
notice how Goku inherits from human, but overrides speed with CPP agent's speed, and image_name with it's own value. (Not that I have actually designed a type of monster named Goku, it's just a test). I will still need to do some complicated maneuvering to link each monster type with it's class, probably it will involve lots of if-else statements, with small functions in the XML loader class for every class.
Before I implement that, I am going to rearrange some of the modules to remove circular dependencies. Right now, I am using some weird hacks to get the program to run, like loading a module at the end of a code file instead of the beginning. However, I calculated that if I rearranged it enough, I could get nice, linear, dependencies, looking like this:
Right now, the item loader contains a couple classes that depend on items, and cheats depends on the item picker, but I think if I let cheats use utility functions in the world class and move the classes in the item loader to a different module, everything can be fixed and I am free to replace the item picker class to my new XML one.
Comments, suggestions, or any response is welcome!