summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrei Karas <akaras@inbox.ru>2015-09-19 16:50:54 +0300
committerAndrei Karas <akaras@inbox.ru>2015-09-19 21:58:34 +0300
commit4964b079cb3864f5e5a7c530b0eb0c5957363baa (patch)
tree1014f957aef0be5af0572167205b37989aede26f
parentd27db8cca78e06582d8372a9d05f6483202c26ba (diff)
downloadevol-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.py11
-rw-r--r--hercules/code/servertoclient/sprites.py315
-rw-r--r--hercules/templates/sprite.xml21
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>