mirror of
https://git.planet-casio.com/Slyvtt/Collab_RPG.git
synced 2024-12-28 04:23:42 +01:00
Started writing a new converter
This commit is contained in:
parent
a06977469c
commit
bc8382ac65
4 changed files with 385 additions and 519 deletions
|
@ -32,7 +32,8 @@ set(SOURCES
|
|||
)
|
||||
# Shared assets, fx-9860G-only assets and fx-CG-50-only assets
|
||||
set(ASSETS
|
||||
assets/WorldRPG.world
|
||||
#assets/WorldRPG.world
|
||||
assets/level0.tmx
|
||||
# ...
|
||||
)
|
||||
|
||||
|
|
|
@ -1,522 +1,375 @@
|
|||
from random import randint
|
||||
from PIL import Image
|
||||
import fxconv
|
||||
import xml.etree.ElementTree as ET
|
||||
import json
|
||||
import pathlib
|
||||
import csv
|
||||
import os
|
||||
import sys
|
||||
|
||||
DEBUG = 0
|
||||
VERBOSE = 1
|
||||
SIGN_TYPES = ["INFO", "SGN"]
|
||||
|
||||
# TODO: Add more doc.
|
||||
|
||||
class Tileset:
|
||||
"""
|
||||
Handle the tiled tileset.
|
||||
"""
|
||||
def __init__(self, element: ET.Element, parent_dir = ""):
|
||||
firstgid_str = element.get("firstgid")
|
||||
if firstgid_str == None: raise Exception("firstgid not found!")
|
||||
self.firstgid = int(firstgid_str)
|
||||
self.source = element.get("source")
|
||||
if self.source == None: raise Exception("source not found!")
|
||||
self.source = parent_dir + self.source
|
||||
tree = ET.parse(self.source)
|
||||
self.root = tree.getroot()
|
||||
tilecount_str = self.root.get("tilecount")
|
||||
if tilecount_str == None: raise Exception("tilecount not found!")
|
||||
self.tilecount = int(tilecount_str)
|
||||
|
||||
def is_raw_in_tileset(self, raw: int) -> bool:
|
||||
if raw >= self.firstgid and raw < self.firstgid+self.tilecount:
|
||||
return True
|
||||
return False
|
||||
def get_tile_from_raw(self, raw: int) -> int:
|
||||
if not self.is_raw_in_tileset(raw) and raw:
|
||||
raise Exception(f"Tile {raw} not in tileset!")
|
||||
return raw-self.firstgid
|
||||
|
||||
class Layer:
|
||||
"""
|
||||
A class to handle a tiled map layer
|
||||
"""
|
||||
def __init__(self, element: ET.Element):
|
||||
self.element = element
|
||||
|
||||
def get_width(self) -> int:
|
||||
"""
|
||||
Get the layer width
|
||||
"""
|
||||
value = self.element.get("width")
|
||||
if value == None: raise Exception("Layer width not found")
|
||||
return int(value)
|
||||
|
||||
def get_height(self) -> int:
|
||||
"""
|
||||
Get the layer height
|
||||
"""
|
||||
value = self.element.get("height")
|
||||
if value == None: raise Exception("Layer height not found")
|
||||
return int(value)
|
||||
|
||||
def get_raw_data(self) -> list:
|
||||
"""
|
||||
Get the data of the map
|
||||
"""
|
||||
data_tag = self.element.find("data")
|
||||
if data_tag == None: raise Exception("Data not found!")
|
||||
raw_data = data_tag.text.split(",")
|
||||
int_data = []
|
||||
for tile in raw_data:
|
||||
int_data.append(int(tile))
|
||||
return int_data
|
||||
def get_data_with_tileset(self, tileset: Tileset):
|
||||
raw_data = self.get_raw_data()
|
||||
out_data = []
|
||||
for i in raw_data:
|
||||
out_data.append(tileset.get_tile_from_raw(i))
|
||||
return out_data
|
||||
|
||||
class Object:
|
||||
"""
|
||||
An group object (see ObjectGroup) object.
|
||||
"""
|
||||
def __init__(self, element: ET.Element):
|
||||
self.element = element
|
||||
self.name = element.get("name")
|
||||
if self.name == None: raise Exception("Name attribute missing!")
|
||||
self.type = element.get("type")
|
||||
if self.type == None: raise Exception("Type attribute missing!")
|
||||
x_str = element.get("x")
|
||||
if x_str == None: raise Exception("X attribute missing!")
|
||||
self.x = int(float(x_str))
|
||||
y_str = element.get("y")
|
||||
if y_str == None: raise Exception("Y attribute missing!")
|
||||
self.y = int(float(y_str))
|
||||
self.id = element.get("id")
|
||||
if self.id == None: raise Exception("ID attribute missing!")
|
||||
|
||||
def __get_point(self) -> list:
|
||||
# Private method to get a point. Used in get_data.
|
||||
return [self.x, self.y]
|
||||
|
||||
def __get_polyline(self) -> list:
|
||||
# Private method to get a polyline. Used in get_data.
|
||||
data = self.element.find("polyline").get("points")
|
||||
if data == None: raise Exception("Data not found!")
|
||||
data = data.replace(' ', ',').split(',')
|
||||
out_data = []
|
||||
for i in data:
|
||||
out_data.append(int(float(i)))
|
||||
return out_data
|
||||
|
||||
def get_data(self) -> list:
|
||||
"""
|
||||
Get the geometric shape of this object.
|
||||
"""
|
||||
if self.element.find("point") != None:
|
||||
# It is a point.
|
||||
return self.__get_point()
|
||||
if self.element.find("polyline") != None:
|
||||
# It is a polyline.
|
||||
return self.__get_polyline()
|
||||
raise Exception("Unknown data!")
|
||||
|
||||
def get_data_type(self) -> str:
|
||||
"""
|
||||
Get the geometric shape of this object.
|
||||
"""
|
||||
if self.element.find("point") != None:
|
||||
# It is a point.
|
||||
return "point"
|
||||
if self.element.find("polyline") != None:
|
||||
# It is a polyline.
|
||||
return "polyline"
|
||||
raise Exception("Unknown data!")
|
||||
|
||||
def get_property(self, property: str) -> str:
|
||||
"""
|
||||
Get the value of a property.
|
||||
"""
|
||||
properties = self.element.find("properties")
|
||||
if properties == None: raise Exception("Properties not found!")
|
||||
for i in properties:
|
||||
if i.get("name") == property:
|
||||
value = i.get("value")
|
||||
if value == None: raise Exception("Property value not found!")
|
||||
return value
|
||||
raise Exception(f"Property {property} not found!")
|
||||
|
||||
class ObjectGroup:
|
||||
"""
|
||||
Handle tiled object groups. They can contain points, lines and other
|
||||
geometric shapes that can be very handy to add NPCs, the path they walk on,
|
||||
as we do it here, in Collab_RPG.
|
||||
"""
|
||||
def __init__(self, element: ET.Element):
|
||||
self.element = element
|
||||
self.objects = []
|
||||
for object in self.element.iterfind("object"):
|
||||
self.objects.append(Object(object))
|
||||
|
||||
|
||||
|
||||
class Map:
|
||||
"""
|
||||
A class to handle the tiled maps.
|
||||
"""
|
||||
def __init__(self, input: str):
|
||||
"""
|
||||
Loads a tmx map made with tiled.
|
||||
"""
|
||||
tree = ET.parse(input)
|
||||
self.root = tree.getroot()
|
||||
self.parent_dir = os.path.abspath(input).rpartition('/')[0]
|
||||
|
||||
def get_property(self, property: str) -> str:
|
||||
"""
|
||||
Get a map property.
|
||||
"""
|
||||
properties = self.root.find("properties")
|
||||
# If properties wasn't found.
|
||||
if properties == None:
|
||||
raise Exception("Properties not found!")
|
||||
for child in properties:
|
||||
# Look at the name attribute of each property
|
||||
if child.get("name") == property:
|
||||
value = child.get("value")
|
||||
if value == None: raise Exception("Value attribute not found!")
|
||||
return value
|
||||
# The dialog file property wasn't found.
|
||||
raise Exception(f"\"{property}\" property not found!")
|
||||
|
||||
def get_layer_by_id(self, layer_id: str) -> Layer:
|
||||
"""
|
||||
Get a layer by its id.
|
||||
"""
|
||||
for layer in self.root.iterfind("layer"):
|
||||
if layer.get("id") == layer_id:
|
||||
return Layer(layer)
|
||||
raise Exception("Layer not found!")
|
||||
|
||||
def get_layer_by_name(self, name: str) -> Layer:
|
||||
"""
|
||||
Get a layer by its name.
|
||||
"""
|
||||
for layer in self.root.iterfind("layer"):
|
||||
if layer.get("name") == name:
|
||||
return Layer(layer)
|
||||
raise Exception("Layer not found!")
|
||||
|
||||
def get_objectgroup_by_id(self, group_id: str) -> Layer:
|
||||
"""
|
||||
Get a layer by its id.
|
||||
"""
|
||||
for layer in self.root.iterfind("objectgroup"):
|
||||
if layer.get("id") == group_id:
|
||||
return ObjectGroup(layer)
|
||||
raise Exception("Object group not found!")
|
||||
|
||||
def get_objectgroup_by_name(self, name: str) -> Layer:
|
||||
"""
|
||||
Get a layer by its name.
|
||||
"""
|
||||
for layer in self.root.iterfind("objectgroup"):
|
||||
if layer.get("name") == name:
|
||||
return ObjectGroup(layer)
|
||||
raise Exception("Object group not found!")
|
||||
|
||||
def get_tileset_by_firstgid(self, firstgid: int) -> Tileset:
|
||||
for tileset in self.root.iterfind("tileset"):
|
||||
if tileset.get("firstgid") == str(firstgid):
|
||||
return Tileset(tileset, self.parent_dir + "/")
|
||||
raise Exception("Tileset not found!")
|
||||
|
||||
def convert(input, output, params, target):
|
||||
if params["custom-type"] == "map":
|
||||
print("ERROR : Asset ", params["name"], " has legacy type map")
|
||||
return 1
|
||||
elif params["custom-type"] == "world":
|
||||
convert_world(input, output, params, target)
|
||||
if params["custom-type"] == "tmx":
|
||||
convert_map(input, output, params, target)
|
||||
return 0
|
||||
elif params["custom-type"] == "custom-image":
|
||||
convert_custom_image(input, output, params, target)
|
||||
elif params["custom-type"] == "json":
|
||||
convert_dialog(input, output, params, target)
|
||||
return 0
|
||||
elif params["custom-type"] == "font":
|
||||
convert_font(input, output, params, target)
|
||||
return 0
|
||||
elif params["custom-type"] == "dialogs":
|
||||
print("ERROR : Asset ", params["name"], " has legacy type dialog")
|
||||
#convert_dialogs(input, output, params, target)
|
||||
return 0
|
||||
else:
|
||||
return 1
|
||||
|
||||
def convert_world(input, output, params, target):
|
||||
print( "WE ARE COMPUTING THE WORLD", input )
|
||||
|
||||
data = json.load(open(input, "r"))
|
||||
nbMaps = ["fileName" in i for i in data["maps"]].count(True)
|
||||
if DEBUG: print( "We have to treat ", nbMaps, " maps")
|
||||
if DEBUG: print( "So let's go ... ")
|
||||
|
||||
structWorld = fxconv.Structure()
|
||||
#structExtra = fxconv.Structure()
|
||||
|
||||
for i in range(nbMaps):
|
||||
nameMap = data["maps"][i]["fileName"].replace(".tmx","")
|
||||
nameMapFree = nameMap.split("/")[-1]
|
||||
#count the number of "back" (cd ..) to locate the map on the computer
|
||||
nbRetour = nameMap.count("..")+1
|
||||
#create the map absolute path
|
||||
|
||||
nameTMX = "/".join(input.split("/")[:-nbRetour]) + "/" + nameMap + ".tmx"
|
||||
nameJSON = "/".join(input.split("/")[:-nbRetour]) + "/" + nameMap + ".json"
|
||||
|
||||
commandline = 'tiled --export-map json ' + nameTMX + ' ' + nameJSON
|
||||
if DEBUG: print( "TILED COMMAND LINE FOR MAPS : ", commandline )
|
||||
os.system( commandline )
|
||||
|
||||
mapPath = "/".join(input.split("/")[:-nbRetour]) + "/" + nameMap + ".json"
|
||||
if DEBUG: print("Map ", i , " name : ", mapPath )
|
||||
|
||||
xmin = data["maps"][i]["x"]
|
||||
if DEBUG: print( "xmin = ", xmin )
|
||||
|
||||
ymin = data["maps"][i]["y"]
|
||||
if DEBUG: print( "ymin = ", ymin )
|
||||
|
||||
xmax = data["maps"][i]["x"] + data["maps"][i]["width"]
|
||||
if DEBUG: print( "xmax = ", xmax )
|
||||
|
||||
ymax = data["maps"][i]["y"] + data["maps"][i]["height"]
|
||||
if DEBUG: print( "ymax = ", ymax )
|
||||
|
||||
map = get_tile_map_data( mapPath, output, params, target, xmin, ymin, xmax, ymax)
|
||||
if DEBUG: print( "Map = ", map )
|
||||
structWorld += fxconv.ptr( map )
|
||||
|
||||
#structWorld += fxconv.u32(0)
|
||||
|
||||
#generate !
|
||||
fxconv.elf(structWorld, output, "_" + params["name"], **target)
|
||||
|
||||
|
||||
def get_tile_map_data(input, output, params, target, xmin, ymin, xmax, ymax):
|
||||
print( "WE ARE COMPUTING THE MAP : ", input )
|
||||
data = json.load(open(input, "r"))
|
||||
|
||||
#find the tileset in use. it's a relative path (like ../tileset.tsx)
|
||||
nameTileset = data["tilesets"][0]["source"].replace(".tsx","")
|
||||
if DEBUG: print(nameTileset)
|
||||
#the name of the tileset without the .something
|
||||
nameTilesetFree = nameTileset.split("/")[-1]
|
||||
#count the number of "back" (cd ..) to locate the tileset on the computer
|
||||
nbRetour = nameTileset.count("..")+1
|
||||
#create the tileset absolute path
|
||||
tilesetTSX = "/".join(input.split("/")[:-nbRetour]) + "/" + nameTileset + ".tsx"
|
||||
tilesetJSON = "/".join(input.split("/")[:-nbRetour]) + "/" + nameTileset + ".json"
|
||||
|
||||
commandline = 'tiled --export-tileset json ' + tilesetTSX + ' ' + tilesetJSON
|
||||
if DEBUG: print( "TILED COMMAND LINE FOR TILESET : ", commandline )
|
||||
os.system( commandline )
|
||||
|
||||
tileset = open(tilesetJSON, "r")
|
||||
data_tileset = json.load(tileset)
|
||||
tileset_size = data_tileset.get("columns")
|
||||
tileset.close()
|
||||
|
||||
#find the ID of the first tile in the walkable tileset ()
|
||||
indexWalkable = data["tilesets"][1]["firstgid"]
|
||||
if DEBUG: print(indexWalkable)
|
||||
|
||||
#Extract from the json the width, height
|
||||
w, h = data["width"], data["height"]
|
||||
|
||||
#nbTileLayer is the number of "true" layers (without ObjectsLayer)
|
||||
nbTilelayer = ["data" in i for i in data["layers"]].count(True) - 1
|
||||
if DEBUG: print( nbTilelayer)
|
||||
|
||||
#index of the various layers (may change from one map to another)
|
||||
layer_walkable = 0
|
||||
layer_foreground = 0
|
||||
layer_background = 0
|
||||
|
||||
#create the structure of the map
|
||||
structMap = fxconv.Structure()
|
||||
|
||||
structMap += fxconv.u32(w) + fxconv.u32(h) + fxconv.u32(nbTilelayer)
|
||||
structMap += fxconv.u32(tileset_size)
|
||||
|
||||
structMap += fxconv.u32(xmin) + fxconv.u32(ymin) + fxconv.u32(xmax) + fxconv.u32(ymax)
|
||||
|
||||
structMap += fxconv.ref(f"img_{nameTilesetFree}")
|
||||
|
||||
|
||||
#extraction of the data contained in the layer "Walkable" of the map
|
||||
for i in range(nbTilelayer+1):
|
||||
datavalid = data["layers"][i]
|
||||
if datavalid["name"]=="Walkable":
|
||||
layer_walkable = i
|
||||
if DEBUG: print( "Walkable Tile Data in layer : ", layer_walkable)
|
||||
break
|
||||
elif i==nbTilelayer:
|
||||
print( "ERROR : No Walkable layer data !!!" )
|
||||
|
||||
walk_data = bytes()
|
||||
layer = data["layers"][layer_walkable]
|
||||
for tile in layer["data"]:
|
||||
#print( tile )
|
||||
if tile == 0: walk_data += fxconv.u8(tile) #if walkable_data = 0 then it is a blanck cell so nothing to change
|
||||
else : walk_data += fxconv.u8(tile-indexWalkable) #if !=0 than we need to shift the tile number by considering the first tileID (given by indexwalkable)
|
||||
structMap += fxconv.ptr(walk_data)
|
||||
|
||||
|
||||
|
||||
|
||||
nbextra = 0
|
||||
extradata = fxconv.Structure()
|
||||
|
||||
nbextra, extradata = get_extra_map_data(input, output, params, target, xmin, ymin, xmax, ymax)
|
||||
|
||||
if (nbextra==0):
|
||||
structMap += fxconv.u32( 0 )
|
||||
structMap += fxconv.u32( 0 )
|
||||
else:
|
||||
structMap += fxconv.u32( int(nbextra) )
|
||||
structMap += fxconv.ptr( extradata )
|
||||
|
||||
|
||||
|
||||
|
||||
nameDialog = data["properties"][0]["value"]
|
||||
dialogfile = "/".join(input.split("/")[:-nbRetour]) + "/" + nameDialog
|
||||
if DEBUG: print( "THE DIALOGS ARE CONTAINED IN THE FILE : ", dialogfile )
|
||||
|
||||
nbdiag = 0
|
||||
diagdata = fxconv.Structure()
|
||||
|
||||
nbdiag, diagdata = convert_dialogs(dialogfile, output, params, target)
|
||||
|
||||
if (nbdiag==0):
|
||||
structMap += fxconv.u32( 0 )
|
||||
structMap += fxconv.u32( 0 )
|
||||
else:
|
||||
structMap += fxconv.u32( int(nbdiag) )
|
||||
structMap += fxconv.ptr( diagdata )
|
||||
|
||||
|
||||
|
||||
#extraction of the data contained in the layer "Background" and "Foreground" of the map
|
||||
|
||||
|
||||
#import the Background layer of the map
|
||||
for i in range(nbTilelayer+1):
|
||||
datavalid = data["layers"][i]
|
||||
if datavalid["name"]=="Background":
|
||||
layer_background = i
|
||||
if DEBUG: print( "Background Tile Data in layer : ", layer_background)
|
||||
break
|
||||
elif i==nbTilelayer:
|
||||
print( "ERROR : No Background layer data !!!" )
|
||||
|
||||
layer_data = bytes()
|
||||
layer = data["layers"][layer_background]
|
||||
for tile in layer["data"]:
|
||||
layer_data += fxconv.u16(tile-1)
|
||||
structMap += fxconv.ptr(layer_data)
|
||||
|
||||
|
||||
|
||||
#import the foreground layer of the map
|
||||
for i in range(nbTilelayer+1):
|
||||
datavalid = data["layers"][i]
|
||||
if datavalid["name"]=="Foreground":
|
||||
layer_foreground = i
|
||||
if DEBUG: print( "Foreground Tile Data in layer : ", layer_foreground)
|
||||
break
|
||||
elif i==nbTilelayer:
|
||||
print( "ERROR : No Foreground layer data !!!" )
|
||||
|
||||
layer_data = bytes()
|
||||
layer = data["layers"][layer_foreground]
|
||||
for tile in layer["data"]:
|
||||
layer_data += fxconv.u16(tile-1)
|
||||
structMap += fxconv.ptr(layer_data)
|
||||
|
||||
|
||||
return structMap
|
||||
|
||||
|
||||
|
||||
def get_extra_map_data(input, output, params, target, xmin, ymin, xmax, ymax):
|
||||
if DEBUG: print( "WE ARE COMPUTING THE EXTRA DATA OF THE MAP : ", input )
|
||||
data = json.load(open(input, "r"))
|
||||
|
||||
nblayer = ["id" in i for i in data["layers"]].count(True) - 1
|
||||
if DEBUG: print( "I found ", nblayer, " of extradata")
|
||||
|
||||
#index of the various layers (may change from one map to another)
|
||||
layer_extradata = 0
|
||||
|
||||
#import the foreground layer of the map
|
||||
for i in range(nblayer+1):
|
||||
datavalid = data["layers"][i]
|
||||
if datavalid["name"]=="ExtraData":
|
||||
layer_extradata = i
|
||||
if DEBUG: print( "Extra Data in layer : ", layer_extradata)
|
||||
break
|
||||
elif i==nblayer:
|
||||
print( "ERROR : No ExtraData layer data !!!" )
|
||||
return 0, fxconv.u32(0)
|
||||
|
||||
#create the structure of the map
|
||||
structData = fxconv.Structure()
|
||||
|
||||
nbSign = 0
|
||||
nbNPC = 0
|
||||
nbPortal = 0
|
||||
nbDiag = 0
|
||||
|
||||
npcs = fxconv.Structure()
|
||||
signs = fxconv.Structure()
|
||||
portals = fxconv.Structure()
|
||||
|
||||
layer = data["layers"][layer_extradata]
|
||||
for i in layer["objects"]:
|
||||
|
||||
#get the type of the item
|
||||
tpe = i["type"]
|
||||
|
||||
#we check if the type corresponds to a items of type Point in Tiled
|
||||
if tpe in ("NPC"):
|
||||
currData = fxconv.Structure()
|
||||
|
||||
x = i["x"] + xmin
|
||||
y = i["y"] + ymin
|
||||
nme = i["name"]
|
||||
|
||||
|
||||
dialogID = None
|
||||
needAction = None
|
||||
path = 0
|
||||
path_length = 0
|
||||
xdata = None
|
||||
ydata = None
|
||||
face_type = "MALE"
|
||||
|
||||
#we now fill all the properties of this item
|
||||
for j in i["properties"]:
|
||||
#property "dialog"
|
||||
if j["name"]=="dialogID":
|
||||
dialogID = j[ "value" ]
|
||||
nbDiag += 1
|
||||
#property "isQuestion"
|
||||
elif j["name"]=="needAction": needAction = j[ "value" ]
|
||||
|
||||
else:
|
||||
#Extra properties for NPCs (path and face)
|
||||
if tpe=="NPC":
|
||||
if j["name"]=="face":
|
||||
face_type = j["value"]
|
||||
elif j["name"]=="hasPath":
|
||||
pathID = None
|
||||
path = j[ "value" ]
|
||||
if path==1:
|
||||
if DEBUG: print( "PNJ has path - NOW LOOKING FOR RELEVANT DATA" )
|
||||
|
||||
# we start looking for path data with first the ID of the path Object
|
||||
for u in i["properties"]:
|
||||
if u["name"]=="path":
|
||||
pathID = u[ "value" ]
|
||||
if DEBUG: print( "path ID is identified : ID= ", pathID )
|
||||
|
||||
for v in layer["objects"]:
|
||||
if v[ "id" ] == pathID:
|
||||
if DEBUG: print( "path data found : " )
|
||||
|
||||
xdata = bytes()
|
||||
ydata = bytes()
|
||||
|
||||
for w in v[ "polyline" ]:
|
||||
path_length = path_length + 1
|
||||
if DEBUG: print( "X= ", w[ "x" ], " Y= ", w[ "y" ] )
|
||||
xdata += fxconv.u16( int( w[ "x" ] ) )
|
||||
ydata += fxconv.u16( int( w[ "y" ] ) )
|
||||
|
||||
else:
|
||||
if DEBUG: print( "PNJ has no Path" )
|
||||
def convert_map(input, output, params, target):
|
||||
if VERBOSE: print(f"INFO: Converting map {input} -> {output}")
|
||||
input_map = Map(input)
|
||||
dialog_file = ""
|
||||
background_layer = []
|
||||
foreground_layer = []
|
||||
walkable_layer = []
|
||||
width = 0
|
||||
height = 0
|
||||
outdoor_tileset = None
|
||||
walkable_tileset = None
|
||||
|
||||
npc_paths = {}
|
||||
npcs = {}
|
||||
signs = {}
|
||||
|
||||
# Get the dialog file
|
||||
try:
|
||||
if VERBOSE: print("INFO: Getting the dialog file")
|
||||
dialog_file = input_map.get_property("dialogFile")
|
||||
if VERBOSE: print(f"INFO: Dialog file: {dialog_file}.")
|
||||
except Exception as e:
|
||||
sys.stderr.write(f"ERROR: Failed to get the dialog file.\n"
|
||||
+ f" Error message: {e}\n")
|
||||
sys.exit(1)
|
||||
|
||||
# Get the outdoor tileset
|
||||
try:
|
||||
if VERBOSE: print("INFO: Getting the outdoor tileset")
|
||||
outdoor_tileset = input_map.get_tileset_by_firstgid(1)
|
||||
except Exception as e:
|
||||
sys.stderr.write(f"ERROR: Failed to get the outdoor tileset.\n"
|
||||
+ f" Error message: {e}\n")
|
||||
sys.exit(1)
|
||||
|
||||
# Get the walkable tileset
|
||||
try:
|
||||
if VERBOSE: print("INFO: Getting the walkable tileset")
|
||||
walkable_tileset = input_map.get_tileset_by_firstgid(409)
|
||||
except Exception as e:
|
||||
sys.stderr.write(f"ERROR: Failed to get the walkable tileset.\n"
|
||||
+ f" Error message: {e}\n")
|
||||
sys.exit(1)
|
||||
|
||||
# Get the background
|
||||
try:
|
||||
if VERBOSE: print("INFO: Getting the background layer")
|
||||
bg_layer = input_map.get_layer_by_name("Background")
|
||||
# The bg layer will be used to set the map width and height.
|
||||
width = bg_layer.get_width()
|
||||
height = bg_layer.get_height()
|
||||
if VERBOSE: print(f"INFO: Map size: ({width}, {height}).")
|
||||
# Get the layer data himself
|
||||
background_layer = bg_layer.get_data_with_tileset(outdoor_tileset)
|
||||
# Check if the size of the layer data is correct.
|
||||
if len(background_layer) != width*height:
|
||||
raise Exception("Bad layer size!")
|
||||
if VERBOSE: print("INFO: Layer data has the right size.")
|
||||
except Exception as e:
|
||||
sys.stderr.write(f"ERROR: Failed to get the background layer.\n"
|
||||
+ f" Error message: {e}\n")
|
||||
sys.exit(1)
|
||||
|
||||
# Get the foreground
|
||||
try:
|
||||
if VERBOSE: print("INFO: Getting the foreground layer")
|
||||
fg_layer = input_map.get_layer_by_name("Foreground")
|
||||
# Get the layer data himself
|
||||
foreground_layer = fg_layer.get_data_with_tileset(outdoor_tileset)
|
||||
# Check if the size of the layer data is correct.
|
||||
if len(foreground_layer) != width*height:
|
||||
raise Exception("Bad layer size!")
|
||||
if VERBOSE: print("INFO: Layer data has the right size.")
|
||||
except Exception as e:
|
||||
sys.stderr.write(f"ERROR: Failed to get the foreground layer.\n"
|
||||
+ f" Error message: {e}\n")
|
||||
sys.exit(1)
|
||||
|
||||
# Get the walkable layer
|
||||
try:
|
||||
if VERBOSE: print("INFO: Getting the walkable layer")
|
||||
wk_layer = input_map.get_layer_by_name("Walkable")
|
||||
# Get the layer data himself
|
||||
walkable_layer = wk_layer.get_data_with_tileset(walkable_tileset)
|
||||
# Check if the size of the layer data is correct.
|
||||
if len(walkable_layer) != width*height:
|
||||
raise Exception("Bad layer size!")
|
||||
if VERBOSE: print("INFO: Layer data has the right size.")
|
||||
except Exception as e:
|
||||
sys.stderr.write(f"ERROR: Failed to get the walkable layer.\n"
|
||||
+ f" Error message: {e}\n")
|
||||
sys.exit(1)
|
||||
|
||||
# Get the extra data
|
||||
try:
|
||||
if VERBOSE: print("INFO: Getting the extra data")
|
||||
ed_objgroup = input_map.get_objectgroup_by_name("ExtraData")
|
||||
# Get the paths the NPCs take.
|
||||
for object in ed_objgroup.objects:
|
||||
if object.get_data_type() == "polyline":
|
||||
npc_paths[object.id] = object.get_data()
|
||||
# Get the NPCs
|
||||
for object in ed_objgroup.objects:
|
||||
if object.get_data_type() == "point" and object.type == "NPC":
|
||||
path = None
|
||||
if int(object.get_property("hasPath")):
|
||||
if object.get_property("path") in npc_paths:
|
||||
path = npc_paths[object.get_property("path")]
|
||||
else:
|
||||
print( "UNIDENTIFIED PROPERTY : ", j["name"])
|
||||
raise Exception("Path required but not found!")
|
||||
data = {
|
||||
"position": object.get_data(),
|
||||
"needAction": object.get_property("needAction"),
|
||||
"dialogID": object.get_property("dialogID"),
|
||||
#"face": object.get_property("face"),
|
||||
"path": path
|
||||
}
|
||||
npcs[object.id] = data
|
||||
# Get the signs
|
||||
for object in ed_objgroup.objects:
|
||||
if object.get_data_type() == "point" and object.type in SIGN_TYPES:
|
||||
data = {
|
||||
"needAction": object.get_property("needAction"),
|
||||
"dialogID": object.get_property("dialogID")
|
||||
}
|
||||
signs[object.id] = data
|
||||
except Exception as e:
|
||||
sys.stderr.write(f"ERROR: Failed to get the extra data.\n"
|
||||
+ f" Error message: {e}\n")
|
||||
sys.exit(1)
|
||||
# Generate the structs
|
||||
#
|
||||
|
||||
if DEBUG:
|
||||
print( "OBJECT X= ", x, " Y= ", y, "STR= ", dialogID )
|
||||
print( " Type= ", tpe, " Name= ", nme, "Face =", face_type)
|
||||
print( " Action?= ", needAction )
|
||||
|
||||
|
||||
currData += fxconv.u32(0)
|
||||
currData += fxconv.u32(0)
|
||||
currData += fxconv.u32( int(x) )
|
||||
currData += fxconv.u32( int(y) )
|
||||
|
||||
currData += fxconv.u16(0) #TODO : faceid
|
||||
|
||||
currData += fxconv.u8(0)
|
||||
|
||||
currData += fxconv.u8(1)
|
||||
currData += fxconv.u32( int(dialogID) )
|
||||
currData += fxconv.u32( int(needAction) )
|
||||
|
||||
currData += fxconv.string( nme )
|
||||
|
||||
if path==0:
|
||||
currData += fxconv.u32(0)
|
||||
currData += fxconv.u32(0)
|
||||
currData += fxconv.u32(0)
|
||||
currData += fxconv.u32(0)
|
||||
currData += fxconv.u32(0)
|
||||
else:
|
||||
o_xdata = fxconv.Structure()
|
||||
o_xdata += xdata
|
||||
o_ydata = fxconv.Structure()
|
||||
o_ydata += ydata
|
||||
|
||||
currData += fxconv.u32(path)
|
||||
currData += fxconv.u32(path_length)
|
||||
currData += fxconv.u32(0)
|
||||
currData += fxconv.ptr(o_xdata)
|
||||
currData += fxconv.ptr(o_ydata)
|
||||
|
||||
#TODO
|
||||
currData += fxconv.i32(0)
|
||||
currData += fxconv.u8(0)
|
||||
currData += fxconv.u8(0)
|
||||
|
||||
currData += fxconv.u16(0)
|
||||
|
||||
nbNPC += 1
|
||||
signs += currData
|
||||
|
||||
elif tpe in ["SGN", "INFO"]:
|
||||
currData = fxconv.Structure()
|
||||
|
||||
x = i["x"] + xmin
|
||||
y = i["y"] + ymin
|
||||
nme = i["name"]
|
||||
if tpe == "SIGN":
|
||||
icon = 0
|
||||
else:
|
||||
icon = 1
|
||||
|
||||
dialogID = None
|
||||
needAction = None
|
||||
|
||||
#we now fill all the properties of this item
|
||||
for j in i["properties"]:
|
||||
#property "dialog"
|
||||
if j["name"]=="dialogID":
|
||||
dialogID = j[ "value" ]
|
||||
nbDiag += 1
|
||||
#property "isQuestion"
|
||||
elif j["name"]=="needAction": needAction = j[ "value" ]
|
||||
else:
|
||||
print( "UNIDENTIFIED PROPERTY : ", j["name"])
|
||||
|
||||
currData += fxconv.u32( int(x) )
|
||||
currData += fxconv.u32( int(y) )
|
||||
currData += fxconv.u32(icon)
|
||||
currData += fxconv.string( nme )
|
||||
currData += fxconv.u32( int(dialogID) )
|
||||
currData += fxconv.u32( int(needAction) )
|
||||
|
||||
nbSign += 1
|
||||
signs += currData
|
||||
|
||||
elif tpe == "PORTAL":
|
||||
nbPortal+=1
|
||||
currData = fxconv.Structure()
|
||||
|
||||
x = i["x"] + xmin
|
||||
y = i["y"] + ymin
|
||||
h = -1
|
||||
w = -1
|
||||
tp_interior = -1
|
||||
tp_to = -1
|
||||
|
||||
for j in i["properties"]:
|
||||
if j["name"] == "h":
|
||||
h = j["value"]
|
||||
if j["name"] == "w":
|
||||
w = j["value"]
|
||||
if j["name"] == "tp_interior":
|
||||
tp_interior = j["value"]
|
||||
if j["name"] == "tp_to":
|
||||
tp_to = j["value"]
|
||||
|
||||
if w==-1 or h==-1 or tp_interior==-1 or tp_to==-1:
|
||||
print("ERROR : Invalid portal " + i["ID"])
|
||||
continue
|
||||
|
||||
currData += fxconv.u32(int(x))
|
||||
currData += fxconv.u32(int(y))
|
||||
currData += fxconv.u32(int(w))
|
||||
currData += fxconv.u32(int(h))
|
||||
currData += fxconv.u16(int(tp_interior))
|
||||
currData += fxconv.u16(int(tp_to))
|
||||
|
||||
portals += currData
|
||||
|
||||
#else we do nothing
|
||||
else:
|
||||
print( 'Unknown object type "'+tpe+'" !' )
|
||||
|
||||
structData += fxconv.u32(nbNPC)
|
||||
if nbNPC:
|
||||
structData += fxconv.ptr(npcs)
|
||||
else:
|
||||
structData += fxconv.u32(0)
|
||||
|
||||
structData += fxconv.u32(nbSign)
|
||||
if nbSign:
|
||||
structData += fxconv.ptr(signs)
|
||||
else:
|
||||
structData += fxconv.u32(0)
|
||||
|
||||
structData += fxconv.u32(nbPortal)
|
||||
if nbPortal:
|
||||
structData += fxconv.ptr(portals)
|
||||
else:
|
||||
structData += fxconv.u32(0)
|
||||
|
||||
return nbDiag, structData
|
||||
|
||||
|
||||
def convert_custom_image(input, output, params, target):
|
||||
scale = int(params.get("scale", 1))
|
||||
|
||||
# Upscale image before converting
|
||||
im = Image.open(input)
|
||||
im = im.resize((im.width * scale, im.height * scale),
|
||||
resample=Image.NEAREST)
|
||||
|
||||
o = fxconv.convert_image_cg(im, params)
|
||||
fxconv.elf(o, output, "_" + params["name"], **target)
|
||||
|
||||
|
||||
|
||||
def convert_font(input, output, params, target):
|
||||
o = fxconv.convert_topti(input, params)
|
||||
fxconv.elf(o, output, "_" + params["name"], **target)
|
||||
|
||||
|
||||
|
||||
def convert_dialogs(input, output, params, target):
|
||||
|
||||
if DEBUG: print( "WE ARE COMPUTING THE DIALOGS FROM : ", input )
|
||||
data = json.load(open(input, "r"))
|
||||
|
||||
structDialogs = fxconv.Structure()
|
||||
nbdialogs = 0
|
||||
|
||||
for d in data["dialogs"]:
|
||||
if DEBUG: print( int(d[ "ID" ]))
|
||||
# print( d[ "dialog" ] )
|
||||
if DEBUG: print( int(d[ "isQuestion" ]) )
|
||||
# print( d[ "choice" ].replace('$', chr(0)) )
|
||||
# print( d[ "conclusion1" ] )
|
||||
# print( int(d[ "next1" ] ) )
|
||||
# print( d[ "conclusion2" ] )
|
||||
# print( int(d[ "next2" ] ) )
|
||||
# print( int(d[ "nextOther" ]) )
|
||||
nbdialogs = nbdialogs + 1
|
||||
|
||||
structDialogs += fxconv.u32( int(d[ "ID" ] ) )
|
||||
structDialogs += fxconv.string( d[ "dialog" ] )
|
||||
structDialogs += fxconv.u32( int(d[ "isQuestion" ] ) )
|
||||
structDialogs += fxconv.string( d[ "choice" ].replace('$', chr(0)) )
|
||||
structDialogs += fxconv.string( d[ "conclusion1" ] )
|
||||
structDialogs += fxconv.u32( int(d[ "next1" ] ) )
|
||||
structDialogs += fxconv.string( d[ "conclusion2" ] )
|
||||
structDialogs += fxconv.u32( int(d[ "next2" ] ) )
|
||||
structDialogs += fxconv.u32( int(d[ "nextOther" ] ) )
|
||||
|
||||
return nbdialogs, structDialogs
|
||||
|
||||
#fxconv.elf(structDialogs, output, "_" + params["name"], **target)
|
||||
def convert_dialog(input, output, params, target):
|
||||
if VERBOSE: print(f"INFO: Converting dialog file {input} -> {output}")
|
||||
|
|
|
@ -1,7 +1,19 @@
|
|||
WorldRPG.world:
|
||||
custom-type: world
|
||||
name: worldRPG
|
||||
level0.tmx:
|
||||
custom-type: tmx
|
||||
name: level0
|
||||
|
||||
#DialogsRPG.json:
|
||||
# custom-type: dialogs
|
||||
# name: dialogRPG
|
||||
level1.tmx:
|
||||
custom-type: tmx
|
||||
name: level1
|
||||
|
||||
level2.tmx:
|
||||
custom-type: tmx
|
||||
name: level2
|
||||
|
||||
level3.tmx:
|
||||
custom-type: tmx
|
||||
name: level3
|
||||
|
||||
level4.tmx:
|
||||
custom-type: tmx
|
||||
name: level4
|
||||
|
|
0
assets/tiled.py
Normal file
0
assets/tiled.py
Normal file
Loading…
Reference in a new issue