diff options
author | Andrei Karas <akaras@inbox.ru> | 2015-09-19 16:50:54 +0300 |
---|---|---|
committer | Andrei Karas <akaras@inbox.ru> | 2015-09-19 21:58:34 +0300 |
commit | 4964b079cb3864f5e5a7c530b0eb0c5957363baa (patch) | |
tree | 1014f957aef0be5af0572167205b37989aede26f | |
parent | d27db8cca78e06582d8372a9d05f6483202c26ba (diff) | |
download | evol-tools-4964b079cb3864f5e5a7c530b0eb0c5957363baa.tar.gz evol-tools-4964b079cb3864f5e5a7c530b0eb0c5957363baa.tar.bz2 evol-tools-4964b079cb3864f5e5a7c530b0eb0c5957363baa.tar.xz evol-tools-4964b079cb3864f5e5a7c530b0eb0c5957363baa.zip |
hercules: allow convert non free monsters.
-rw-r--r-- | hercules/code/servertoclient/monsters.py | 11 | ||||
-rw-r--r-- | hercules/code/servertoclient/sprites.py | 315 | ||||
-rw-r--r-- | hercules/templates/sprite.xml | 21 |
3 files changed, 331 insertions, 16 deletions
diff --git a/hercules/code/servertoclient/monsters.py b/hercules/code/servertoclient/monsters.py index 32255a3..782b449 100644 --- a/hercules/code/servertoclient/monsters.py +++ b/hercules/code/servertoclient/monsters.py @@ -23,8 +23,6 @@ def convertMonsters(isNonFree = False, idtofile = None): data = "" ids = Set() - monsterSprite = """<sprite>monsters/blub.xml</sprite> - <sprite>accessories/blub-tentacle.xml|#3e4164,3a3968,544a82,64437a,7d6db4,a26392,8f99c4,d294ab,b3cdcd,e7b8b8,d9ecd1,f0e8c5</sprite>"""; with open(monstersDbFile, "r") as f: for line in f: if len(line) < 10 or line[0:2] == "//" or line[0:12] != "REPLACE INTO": @@ -36,9 +34,12 @@ def convertMonsters(isNonFree = False, idtofile = None): if len(rows) < 5: continue monsterId = rows[0] - if isNonFree == True: - if monsterId in idtofile: - convertSprite("rodata/data/sprite/ёуЅєЕН/" + idtofile[monsterId]) + if isNonFree == True and monsterId in idtofile: + convertSprite("rodata/data/sprite/ёуЅєЕН/", idtofile[monsterId]) + monsterSprite = "<sprite>monsters/{0}.xml</sprite>".format(idtofile[monsterId]) + else: + monsterSprite = """<sprite>monsters/blub.xml</sprite> + <sprite>accessories/blub-tentacle.xml|#3e4164,3a3968,544a82,64437a,7d6db4,a26392,8f99c4,d294ab,b3cdcd,e7b8b8,d9ecd1,f0e8c5</sprite>"""; name = strToXml(stripQuotes(rows[2])) data = data + tpl.format(monsterId, name, monsterSprite) diff --git a/hercules/code/servertoclient/sprites.py b/hercules/code/servertoclient/sprites.py index 1a04745..7e03b58 100644 --- a/hercules/code/servertoclient/sprites.py +++ b/hercules/code/servertoclient/sprites.py @@ -4,6 +4,9 @@ # Author: Andrei Karas (4144) import os +from PIL import Image +from PIL import ImageDraw +from sets import Set from code.fileutils import * from code.stringutils import * @@ -29,14 +32,293 @@ class ActEventClass: class SprClass: pass +class SprImageClass: + pass + def readIndexedRLEImage(f, spr): - + spr.nimages = spr.indexedSpritesCount + spr.images = dict() + for imageN in range(0, spr.indexedSpritesCount): + image = SprImageClass() + spr.images[imageN] = image + image.width = readInt16(f) + image.height = readInt16(f) + image.compressed = True + data = array.array('B', (0 for _ in xrange(image.width * image.height))) + image.data = data + + compressSize = readInt16(f) + uncompressedSize = image.width * image.height + #print "uncompressed size=" + str(uncompressedSize) + #print "compressed size=" + str(compressSize) + + idx = 0 + readCnt = 0 + while readCnt < compressSize: + c = readInt8(f) + readCnt = readCnt + 1 + data[idx] = c; + #print "{0:4}: {1}".format(idx, c) + idx = idx + 1 + if c == 0: + cnt = readInt8(f) + readCnt = readCnt + 1 + if cnt == 0: + data[idx] = cnt + #print "{0:4}: {1}".format(idx, cnt) + idx = idx + 1 + else: + for j in range(1, cnt): + data[idx] = c + #print "{0:4} ({1} to {2}): {3}".format(idx, j, cnt - 1, c) + idx = idx + 1 + #print "read bytes: " + str(readCnt) def readIndexedImage(f, spr): pass def readRgbaImage(f, spr): - pass + for imageN in range(0, spr.rgbaSpritesCount): + image = SprImageClass() + spr.images[imageN + spr.indexedSpritesCount] = image + image.width = readInt16(f) + image.height = readInt16(f) + data = array.array('I', (0 for _ in xrange(image.width * image.height))) + image.compressed = False + image.data = data + for idx in range(0, image.width * image.height): + data[idx] = readInt32(f) + + +def readPalette(f, spr): + palette = array.array('I', (0 for _ in xrange(256))) + spr.palette = palette + for col in range(0, 256): + palette[col] = readInt32(f) + +def getSignedNumber(number, bitLength): + mask = (2 ** bitLength) - 1 + if number & (1 << (bitLength - 1)): + return number | ~mask + else: + return number & mask + +def decodeSprite(spr): + palette = spr.palette + spr.maxwidth = 0 + spr.maxheight = 0 + alpha = False + for imageN in range(0, spr.indexedSpritesCount): + image = spr.images[imageN] + indexed = image.data + data = array.array('I', (0 for _ in xrange(image.width * image.height))) + for idx in range(0, image.width * image.height): + col = indexed[idx] + if col == 0: + data[idx] = 0 + else: + if palette[col] > 0x00ffffff: + data[idx] = palette[col] + alpha = True + else: + data[idx] = palette[col] + 0xff000000 + image.data = data + if image.width > spr.maxwidth: + spr.maxwidth = image.width + if image.height > spr.maxheight: + spr.maxheight = image.height + + # for debug +# png = Image.new('RGBA', (image.width, image.height)) +# png.putdata(image.data) +# png.save("test{0}.png".format(imageN)) + + if alpha: + print "detected alpha" + + for imageN in range(0, spr.rgbaSpritesCount): + image = spr.images[imageN + spr.indexedSpritesCount] + if image.width > spr.maxwidth: + spr.maxwidth = image.width + if image.height > spr.maxheight: + spr.maxheight = image.height + + + +def saveSpriteImage(act, spr, spriteName): + monstersDir = "clientdata/graphics/sprites/monsters/" +# for imageN in range(0, spr.rgbaSpritesCount): +# image = spr.images[imageN + spr.indexedSpritesCount] +# print "{0} x {1}".format(image.width, image.height) +# png = Image.new('RGBA', (image.width, image.height)) +# png.putdata(image.data) +# png.save("test{0}.png".format(imageN + spr.indexedSpritesCount)) + +# numTiles = spr.indexedSpritesCount + spr.rgbaSpritesCount + + counted = 0 + for animN in range(0, act.nanimations): + anim = act.animations[animN] + for spriteN in range(0, anim.nsprites): + sprite = anim.sprites[spriteN] + key = [] +# for frameN in range(0, sprite.nframes): +# frame = sprite.frames[frameN] +# idf = frame.frameIndex +# if frame.mirror > 0: +# idf = - idf +# key.append(idf) + counted = counted + 1 + + numTiles = counted + #print "max: {0}x{1}".format(spr.maxwidth, spr.maxheight) + + # in row + rowTiles = int(2048 / spr.maxwidth) + colTiles = int(numTiles / rowTiles) + if colTiles * rowTiles < numTiles: + colTiles = colTiles + 1 + tilesetWidth = 2048 + tilesetHeight = colTiles * spr.maxheight +# print "num {0} row {1}, col {2}".format(numTiles, rowTiles, colTiles) +# print "size {0}x{1}".format(2048, colTiles * spr.maxheight) + +# tileset = array.array('I', (0 for _ in xrange(tilesetWidth * tilesetHeight))) + tileset = Image.new('RGBA', (tilesetWidth, tilesetHeight)) +# png.putdata(tileset) + #draw = ImageDraw.Draw(png) + + x = 0 + y = 0 + + frameToIdx = dict() + + tile = 0 + for animN in range(0, act.nanimations): + anim = act.animations[animN] + for spriteN in range(0, anim.nsprites): + sprite = anim.sprites[spriteN] + frameToIdx[str(animN) + "_" + str(spriteN)] = tile + for frameN in range(0, sprite.nframes): + frame = sprite.frames[frameN] + frm = frame.frameIndex + if frame.mirror > 0: + frm = - frm + + if frm in frameToIdx: + continue + + if frame.frameIndex not in spr.images: + print "wrong frame index: {0}".format(frame.frameIndex) + continue + image = spr.images[frame.frameIndex] + png = Image.new('RGBA', (image.width, image.height)) + png.putdata(image.data) + if frame.mirror > 0: + png = png.transpose(Image.FLIP_LEFT_RIGHT) + offsetX = (spr.maxwidth - image.width) / 2 + offsetY = spr.maxheight - image.height +# offsetX = (spr.maxwidth - image.width) / 2 + getSignedNumber(frame.offsetX, 32) +# offsetY = spr.maxheight - image.height + getSignedNumber(frame.offsetY, 32) + tileset.paste(png, (x + offsetX, y + offsetY)) + tile = tile + 1 + x = x + spr.maxwidth + if x + spr.maxwidth > 2048: + x = 0 + y = y + spr.maxheight + +# for imageN in range(0, spr.rgbaSpritesCount + spr.indexedSpritesCount): +# image = spr.images[imageN] +# png = Image.new('RGBA', (image.width, image.height)) +# png.putdata(image.data) +# tileset.paste(png, (x, y)) +# x = x + spr.maxwidth +# if x + spr.maxwidth > 2048: +# x = 0 +# y = y + spr.maxheight + + spr.frameToIdx = frameToIdx + spr.tilesetWidth = tilesetWidth + spr.tilesetHeight = tilesetHeight + makeDir(monstersDir) + tileset.save(monstersDir + spriteName + ".png") + +def extractSpriteAnimData(act, spr, actIndex, direction): +# delay = anim.delay + delay = 100 + data = " <animation direction=\"" + direction + "\">\n" + if actIndex not in act.animations: + data = data + " <frame index=\"{0}\" delay=\"{1}\" offsetX=\"{2}\" offsetY=\"{3}\"/>\n".format( + 0, delay, 0, 0) + data = data + " </animation>\n" + return data + + anim = act.animations[actIndex] + for spriteN in range(0, anim.nsprites): + sprite = anim.sprites[spriteN] + #for frameN in range(0, sprite.nframes): + #frame = sprite.frames[frameN] + #frm = frame.frameIndex + #if frame.mirror > 0: + # frm = -frm + #if frm not in spr.frameToIdx: + # continue + + idx = spr.frameToIdx[str(actIndex) + "_" + str(spriteN)] + offsetX = 0 + offsetY = 0 +# offsetX = frame.offsetX +# offsetY = frame.offsetY +# if offsetX > 4294900000: +# offsetX = - (4294967296 - offsetX) +# if offsetY > 4294000000: +# offsetY = -(4294967296 - offsetY) + + data = data + " <frame index=\"{0}\" delay=\"{1}\" offsetX=\"{2}\" offsetY=\"{3}\"/>\n".format( + idx, delay, offsetX, offsetY) + + data = data + " </animation>\n" + return data + +def extractSpriteDataAll(act, spr, actIndex, name): + data = extractSpriteAnimData(act, spr, actIndex, "down") + data = data + extractSpriteAnimData(act, spr, actIndex + 1, "leftdown") + data = data + extractSpriteAnimData(act, spr, actIndex + 2, "left") + data = data + extractSpriteAnimData(act, spr, actIndex + 3, "leftup") + data = data + extractSpriteAnimData(act, spr, actIndex + 4, "up") + data = data + extractSpriteAnimData(act, spr, actIndex + 5, "rightup") + data = data + extractSpriteAnimData(act, spr, actIndex + 6, "right") + data = data + extractSpriteAnimData(act, spr, actIndex + 6, "rightdown") + return data + +def saveSpriteXml(act, spr, spriteName): + monstersDir = "clientdata/graphics/sprites/monsters/" + templatesDir = "templates/" + dstFile = monstersDir + spriteName + ".xml" + tpl = readFile(templatesDir + "sprite.xml") + # 0, 8, 16, 24, 32, 40, 48 + # 0 - walk or attack or ? + # 8 - walk + # 16 - attack + # 24 - dead + # 32 - dead2 ? + # no more + standData = extractSpriteDataAll(act, spr, 0, "stand") + walkData = extractSpriteDataAll(act, spr, 8, "walk") + attackData = extractSpriteDataAll(act, spr, 16, "attack") + deadData = extractSpriteDataAll(act, spr, 32, "dead") + + data = tpl.format( + src = "graphics/sprites/monsters/" + spriteName + ".png", + width = spr.maxwidth, + height = spr.maxheight, + stand = standData, + walk = walkData, + attack = attackData, + dead = deadData + ) + saveFile(dstFile, data) + def readAct(actFile): act = ActClass() @@ -47,13 +329,14 @@ def readAct(actFile): return None act.minorVersion = readInt8(f) act.majorVersion = readInt8(f) - #print "file: {0}, version: {1}.{2}".format(actFile, act.majorVersion, act.minorVersion) act.nanimations = readInt16(f) + print "{0}, {1}.{2}, {1}".format(actFile, act.majorVersion, act.minorVersion, act.nanimations) #print " animations: " + str(act.nanimations) act.animations = dict() skipData(f, 10) for animN in range(0, act.nanimations): anim = ActAnimationClass() + anim.delay = 30 act.animations[animN] = anim anim.nsprites = readInt32(f) #print " sprites: " + str(anim.nsprites) @@ -70,8 +353,8 @@ def readAct(actFile): sprite.right2 = readInt32(f) sprite.buttom2 = readInt32(f) sprite.nframes = readInt32(f) + #print "sprite {0}, frames: {1}".format(spriteN, sprite.nframes) sprite.frames = dict() - #print " frames: " + str(sprite.nframes) for frameN in range(0, sprite.nframes): frame = ActFrameClass() sprite.frames[frameN] = frame @@ -92,8 +375,7 @@ def readAct(actFile): if act.majorVersion > 2 or (act.majorVersion == 2 and act.minorVersion >= 5): frame.width = readInt32(f) frame.height = readInt32(f) - #print " width: " + str(frame.width) - #print " height: " + str(frame.height) + #print "{0} x {1}".format(frame.width, frame.height) if act.majorVersion >= 2: sprite.eventIndex = readInt32(f) if act.majorVersion > 2 or (act.majorVersion == 2 and act.minorVersion >= 3): @@ -119,6 +401,7 @@ def readAct(actFile): for animN in range(0, act.nanimations): anim = act.animations[animN] anim.delay = readInt32(f) + return act def readSpr(sprFile): spr = SprClass() @@ -143,11 +426,21 @@ def readSpr(sprFile): readIndexedImage(f, spr) readRgbaImage(f, spr) + if spr.majorVersion > 1 or (spr.majorVersion == 1 and spr.minorVersion >= 1): + readPalette(f, spr) + + return spr -def convertSprite(spriteName): - actFile = "{0}.act".format(spriteName) - sprFile = "{0}.spr".format(spriteName) +def convertSprite(spritePath, spriteName): + actFile = "{0}.act".format(spritePath + spriteName) + sprFile = "{0}.spr".format(spritePath + spriteName) if os.path.exists(actFile) == False or os.path.exists(sprFile) == False: return None - #readAct(actFile) - readSpr(sprFile) + act = readAct(actFile) + spr = readSpr(sprFile) + decodeSprite(spr) + saveSpriteImage(act, spr, spriteName) + saveSpriteXml(act, spr, spriteName) +# if actFile.find("wolf") > 0: +# exit(0) +# exit(0) diff --git a/hercules/templates/sprite.xml b/hercules/templates/sprite.xml new file mode 100644 index 0000000..7443ba7 --- /dev/null +++ b/hercules/templates/sprite.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Author: 4144 +Copyright (C) 2015 Evol Online --> +<sprite> + <imageset name="sprite" + src="{src}" + width="{width}" + height="{height}"/> + + <action name="stand" imageset="sprite"> +{stand}</action> + + <action name="walk" imageset="sprite"> +{walk}</action> + + <action name="attack" imageset="sprite"> +{attack}</action> + + <action name="dead" imageset="sprite"> +{dead}</action> +</sprite> |