Results 1 to 14 of 14

Thread: Campaign-Tree Generator

  1. #1

    Default Campaign-Tree Generator

    This tool generates random tree coordinates from a set area that one has colored. The idea with this tool is to reduce work time with making the trees. If done manually, one has to set the coordinates for every tree and change them if they are not on the right place. This process can be tedious if you want to add hundreds of trees to, for example a new landmass. By using this tool you will save alot of man-hours. In fact, the process is so quick that if you are not content with the trees, just do it again. The randomness of the generating will assure you that the next seed will not be the same at all.

    My thanks to taw for his help with Shogun 2 converter and converting campaign.tree_list file.

    Example pictures:
    Spoiler Alert, click show to read: 









    Installing
    Spoiler Alert, click show to read: 

    First you need to install python 3.3. That can be done on this website:http://www.python.org/download/ (If on windows, pick the download at the top. Make sure to install python at C:/Python33, i.e the default installing directory). Then you need to download and install the PIL module, you need only to run the installing program. Pillow-2.3.0.win32-py3.3.exe (md5).

    After you have done that, in order to make the trees after you have used this tool you need to use the Shogun 2 converter tool, made by taw and husslertw. Download:http://www.twcenter.net/forums/showt...-update-30-03)

    For Shogun2 converter you will need to download the latest version of jruby (http://jruby.org.s3.amazonaws.com/do..._x64_1_7_9.exe for 64bit and http://jruby.org.s3.amazonaws.com/do...dows_1_7_9.exe otherwise.

    Optional:
    The tree making progress will be much easier if you use some kind of IDE that can handle XML. I recommend notepad++. Download: http://notepad-plus-plus.org/download/v6.5.3.html



    Usage and workflow

    Spoiler Alert, click show to read: 


    1. From data.pack in Shogun 2/data folder, extract the campaign.tree_list file that is in campaign_maps/"campaign of choice"/display/Trees
    2. Put the campaign.tree_list file in a part of the Shogun 2 converter directory.(S2C/Shogun2 Converter/ESF) That means the first ESF folder you stumble upon, not the one inside it.
    3. Go back to (S2C/Shogun2 Converter) and hold shift, rightclick "ESF" folder, open command window.
    4. Write this: "jruby --1.8 esf2xml campaign.tree_list unpacked".
    5. When that is done, go to the unpacked folder inside ESF folder. Open tree_lod_list with any text program(notepad++ recommended). Let it be opened for the time being.
    6. Extract heightmap.tif from data.pack and (campaign_maps/"campaign of choice"/display/Heightmap) into the folder where the python script TreeGenerator.py is. Convert it to .png and save it as "PaintArea.png"(Capitals important).
    7. Paint on the area in the png where you want your trees(additional info regarding this can be found in readme, like RGB).
    8. Save the image and run the python script. Let it run for a while, will take some time. It will then ask you for the number of trees you want added into that area. It will also print some info you can ignore.
    9. Open the MyFile.xml with notepad++ or whatever and copy all the entries except the head one(displaying how many trees you added) and paste them into the tree_lod_list file among the other, similar entries. It is divided into parts which represent different treesorts. Paste into one of these. Under the line that tells you what sort it is(ex <s>campaign_maps\vegetation\climate\japan_campaign\trees\spruce_groupb.rigid_model_v2</s>) and the "u" value, paste the tree coordinates from MyFile. Add the number of trees to the value of u, for that part of the document. If u was 250 before you added your 100 trees it must be 350 after. Save the file.
    10. Go to the same command window as before(open it again if you closed if previously).
    11. Run this : "jruby --1.8 xml2esf unpacked campaign.tree_list" and then go into the ESF folder. The campaign.tree_list file in there is the new one you just created. Append it to your mod into the same directory as the default one you extracted.
    12. Run Shogun 2 and check the area on the map where you added the trees.

    Possible bugs that you should be aware of:
    1. If no or few of the tree sorts except the one you added your new trees to is visible on the campaign map it is very likely that you have not altered the "u" value accordingly to how many trees you added, or you might have altered the wrong "u" value for another tree sort.



    Using my script and altering its variables/parameters
    Spoiler Alert, click show to read: 

    Anyone is free to edit and redistribute this software without asking me of permission. I have added all the variables in the beginning of the script, with comments about what they do. This way, you can alter their values to suit your specific needs for something, like having a paintmap with another resolution, or changing the RGB color.

    Attached Files Attached Files
    Last edited by Ygge; January 08, 2014 at 07:57 AM.

  2. #2
    Primergy's Avatar Protector of the Union
    Join Date
    Mar 2009
    Location
    Augsburg
    Posts
    2,457

    Default Re: Campaign-Tree Generator

    Very good work!

  3. #3

    Default Re: Campaign-Tree Generator

    Thanks, not sure if anyone will use it though. Thought I'd upload it just in case.

  4. #4

    Default Re: Campaign-Tree Generator

    Quote Originally Posted by Ygge View Post
    Thanks, not sure if anyone will use it though. Thought I'd upload it just in case.
    But how did you get Korea??

  5. #5
    izzi's Avatar A true man hates no one
    Join Date
    Jan 2010
    Location
    Flanders
    Posts
    883

    Default Re: Campaign-Tree Generator

    Guys, i can't get it to work. This is the error message i receive:
    RuntimeError: Incorrect ESF magic: ABCA
    parse_magic at ./esf_parser.rb:143
    initialize at ./esf_parser.rb:370
    initialize at ./esf_converter.rb:184
    (root) at esf2xml:30
    Knowledge + Understanding = Wisdom.


  6. #6

    Default Re: Campaign-Tree Generator

    I keep getting this error.

    Code:
    File "TreeGenerator.py", line 79, in <module>
        pixeltrial = random.choice(pixels)     #the set RGB value.
      File "C:\Python36\lib\random.py", line 257, in choice
        raise IndexError('Cannot choose from an empty sequence') from None
    IndexError: Cannot choose from an empty sequence
    I'm using python 3.6 and a Win 10 PC.
    Morning Sun (adds Korea to the Shogun 2 map)
    http://www.twcenter.net/forums/forum...28-Morning-Sun

    Expanded Japan mod (97 new regions and 101 new factions)
    http://www.twcenter.net/forums/showt...ew-factions%29

    How to split a region in TWS2
    http://www.twcenter.net/forums/showt...split-a-region

    Eras Total Conquest 2.3 (12 campaigns from 970-1547)

  7. #7
    izzi's Avatar A true man hates no one
    Join Date
    Jan 2010
    Location
    Flanders
    Posts
    883

    Default Re: Campaign-Tree Generator

    Quote Originally Posted by uanime5 View Post
    I keep getting this error.

    Code:
    File "TreeGenerator.py", line 79, in <module>
        pixeltrial = random.choice(pixels)     #the set RGB value.
      File "C:\Python36\lib\random.py", line 257, in choice
        raise IndexError('Cannot choose from an empty sequence') from None
    IndexError: Cannot choose from an empty sequence
    I'm using python 3.6 and a Win 10 PC.
    Yeah, I know. The tree generator doesn't work or FOTS, only Shogun 2. Have you any ideas how to fix that for FOTS?
    Knowledge + Understanding = Wisdom.


  8. #8

    Default Re: Campaign-Tree Generator

    Quote Originally Posted by uanime5 View Post
    I keep getting this error.

    Code:
    File "TreeGenerator.py", line 79, in <module>
        pixeltrial = random.choice(pixels)     #the set RGB value.
      File "C:\Python36\lib\random.py", line 257, in choice
        raise IndexError('Cannot choose from an empty sequence') from None
    IndexError: Cannot choose from an empty sequence
    I'm using python 3.6 and a Win 10 PC.
    So ive asked 2 buddies in class, they say that the index error means that something isnt defined properly. Lets say theres a range of 0-10 maybe youve only depicted 0-9. Also I think since the first 79 line error is saying random.py maybe you havent defined the RGB color properly in the depicted area.

    Another thing is the guide asys 3.3 so maybe try that version?


    ALSO izzi, hes working on S2 not FOTS. So i dont think thats the problem

  9. #9

    Default Re: Campaign-Tree Generator

    For clarity I'm going to post the whole code.

    Spoiler Alert, click show to read: 
    Code:
    from PIL import Image
    import random
    import math
    
    print("Loading...")
    x = 0
    y = 0
    image = Image.open('PaintArea.png') #Name of the image this script reads from.
    pix = image.load()
    
    #Useful variables
    rgb = (186, 32, 37)  #RGB used to paint with. Goes (Red, Green, Blue).
    
    est_radious = 0.5355      #Original estimated radious(not in use, just for documentation)
    
    radious = 6.8544          #Radious converted for heithmap size
    
    middle = [8192, 4096]     #Middle pixel. Change if you change resolution of PaintArea.png.
    
    factor = 12.8             #The factor that determines the change between PaintArea coordinates
                              #and game coordinates. Needs to be changed if changed resolution.
    
    xy = 134217728            #The maximum x * maximum y. Change this if resolution is changed.
    
    
    i = 0
    pixels = []
    while i < xy -1: #Generates pixel coordinates which has the RGB value we want.
        x += 1
        i += 1
        if x == 16384:
            x = 0
            y += 1
        if pix[x,y] == rgb:
            pixels.append([x,y])
    
    XML = open('myfile.xml', 'w') #Name of XML files this script writes to.
        
    def distancecheck(pixeltrial, pixels, radious): #Checks the distance between two trees and
        for pixel in pixels:                        #returns False if too close to one another
            xChange = pixel[0] - pixeltrial[0]      #and True if not.
            xChange = abs(xChange)
            yChange = pixel[1] - pixeltrial[1]
            yChange = abs(yChange)
            distancesquared = (xChange**2) + (yChange**2)
            distance = math.sqrt(distancesquared)
            distancehalf = distance/2
            output = False
            if distancehalf >= radious:
                output = True
            return output
        
    def coordinateconvert(TreeList, middle, factor):       #Converts coordinates in a given list to
        FinalList = []                                     #gamereadable format and writes it to XML file.
        for point in TreeList:
            realdiffX = point[0] - middle[0]
            realdiffY = -point[1] + middle[1]
            realdiffX = realdiffX/factor
            realdiffY = realdiffY/factor
            z = random.random()
            z = "%.15f" % (z,)
            #String under has custom XML syntax. Change if you need to.
            CoordinateString = '<v2 x="' + str(realdiffX) + '" y="' + str(realdiffY) + '"/>\n' + '<flt>' + str(z) + '</flt>'
            FinalList.append(CoordinateString)
        NumberOfEntities = len(FinalList)
        XML.write("Number of trees: %s" % NumberOfEntities)
        for co in FinalList:
            XML.writelines("\n" + co)
        XML.close()
        return FinalList
    
    NumberOfTrees = input("How many tree-entities do you want:")
    
    GeneratedTrees = 0
    NumberOfTrees = int(NumberOfTrees)
    TreeList = []
    
    while GeneratedTrees <= NumberOfTrees - 1: #Generates random tree-coordinates from given pixelpool with
        pixeltrial = random.choice(pixels)     #the set RGB value.
        TryPixel = distancecheck(pixeltrial, pixels, radious)
        if TryPixel == True:
            GeneratedTrees += 1
            TreeList.append(pixeltrial)
        else:
            print("Choice was too close to other pixels.")
    Conversion = coordinateconvert(TreeList, middle, factor)
    print(Conversion)


    The code shows that the RGB colour has been defined and the problem seems to be with the placement of the trees. Basically if the code finds a pixel that's the right colour it will create a tree a random distance from this pixel. However for unknown reasons the code to calculate a random distance isn't working and I don't know how to modify the code so it will work. Havie it may be helpful if you can have one of your buddied look at the code and recommend a different way to calculate random numbers.
    Morning Sun (adds Korea to the Shogun 2 map)
    http://www.twcenter.net/forums/forum...28-Morning-Sun

    Expanded Japan mod (97 new regions and 101 new factions)
    http://www.twcenter.net/forums/showt...ew-factions%29

    How to split a region in TWS2
    http://www.twcenter.net/forums/showt...split-a-region

    Eras Total Conquest 2.3 (12 campaigns from 970-1547)

  10. #10
    izzi's Avatar A true man hates no one
    Join Date
    Jan 2010
    Location
    Flanders
    Posts
    883

    Default Re: Campaign-Tree Generator

    Quote Originally Posted by uanime5 View Post
    For clarity I'm going to post the whole code.

    Spoiler Alert, click show to read: 
    Code:
    from PIL import Image
    import random
    import math
    
    print("Loading...")
    x = 0
    y = 0
    image = Image.open('PaintArea.png') #Name of the image this script reads from.
    pix = image.load()
    
    #Useful variables
    rgb = (186, 32, 37)  #RGB used to paint with. Goes (Red, Green, Blue).
    
    est_radious = 0.5355      #Original estimated radious(not in use, just for documentation)
    
    radious = 6.8544          #Radious converted for heithmap size
    
    middle = [8192, 4096]     #Middle pixel. Change if you change resolution of PaintArea.png.
    
    factor = 12.8             #The factor that determines the change between PaintArea coordinates
                              #and game coordinates. Needs to be changed if changed resolution.
    
    xy = 134217728            #The maximum x * maximum y. Change this if resolution is changed.
    
    
    i = 0
    pixels = []
    while i < xy -1: #Generates pixel coordinates which has the RGB value we want.
        x += 1
        i += 1
        if x == 16384:
            x = 0
            y += 1
        if pix[x,y] == rgb:
            pixels.append([x,y])
    
    XML = open('myfile.xml', 'w') #Name of XML files this script writes to.
        
    def distancecheck(pixeltrial, pixels, radious): #Checks the distance between two trees and
        for pixel in pixels:                        #returns False if too close to one another
            xChange = pixel[0] - pixeltrial[0]      #and True if not.
            xChange = abs(xChange)
            yChange = pixel[1] - pixeltrial[1]
            yChange = abs(yChange)
            distancesquared = (xChange**2) + (yChange**2)
            distance = math.sqrt(distancesquared)
            distancehalf = distance/2
            output = False
            if distancehalf >= radious:
                output = True
            return output
        
    def coordinateconvert(TreeList, middle, factor):       #Converts coordinates in a given list to
        FinalList = []                                     #gamereadable format and writes it to XML file.
        for point in TreeList:
            realdiffX = point[0] - middle[0]
            realdiffY = -point[1] + middle[1]
            realdiffX = realdiffX/factor
            realdiffY = realdiffY/factor
            z = random.random()
            z = "%.15f" % (z,)
            #String under has custom XML syntax. Change if you need to.
            CoordinateString = '<v2 x="' + str(realdiffX) + '" y="' + str(realdiffY) + '"/>\n' + '<flt>' + str(z) + '</flt>'
            FinalList.append(CoordinateString)
        NumberOfEntities = len(FinalList)
        XML.write("Number of trees: %s" % NumberOfEntities)
        for co in FinalList:
            XML.writelines("\n" + co)
        XML.close()
        return FinalList
    
    NumberOfTrees = input("How many tree-entities do you want:")
    
    GeneratedTrees = 0
    NumberOfTrees = int(NumberOfTrees)
    TreeList = []
    
    while GeneratedTrees <= NumberOfTrees - 1: #Generates random tree-coordinates from given pixelpool with
        pixeltrial = random.choice(pixels)     #the set RGB value.
        TryPixel = distancecheck(pixeltrial, pixels, radious)
        if TryPixel == True:
            GeneratedTrees += 1
            TreeList.append(pixeltrial)
        else:
            print("Choice was too close to other pixels.")
    Conversion = coordinateconvert(TreeList, middle, factor)
    print(Conversion)


    The code shows that the RGB colour has been defined and the problem seems to be with the placement of the trees. Basically if the code finds a pixel that's the right colour it will create a tree a random distance from this pixel. However for unknown reasons the code to calculate a random distance isn't working and I don't know how to modify the code so it will work. Havie it may be helpful if you can have one of your buddied look at the code and recommend a different way to calculate random numbers.
    Normally, the code works with Shogun 2 TW. But not with FOTS. Also, the resolution in FOTS is (I guess) 4096 by 4096. So what is the factor value then? (the factor multiplies the values of trees?). The max. xy value (for FOTS) must be than 16777216. If use the python version that is mentioned (3.3) and jruby version, than for Shogun2 it works. But the strange thing, is that it doesn't work with FOTS. I mean the python script yes, but when starting with jruby not.
    Knowledge + Understanding = Wisdom.


  11. #11
    izzi's Avatar A true man hates no one
    Join Date
    Jan 2010
    Location
    Flanders
    Posts
    883

    Default Re: Campaign-Tree Generator

    I have tested again and yes, I have the same issue now as you have. The random tree value doesn't get properly values to put the trees around the pixel.
    Knowledge + Understanding = Wisdom.


  12. #12

    Default Re: Campaign-Tree Generator

    I wonder if the problem is with the PIL module or the code using it, as this part of the code looks at the image and determines which pixels are red. If this doesn't work correctly then the tool won't know where the trees should be located.
    Morning Sun (adds Korea to the Shogun 2 map)
    http://www.twcenter.net/forums/forum...28-Morning-Sun

    Expanded Japan mod (97 new regions and 101 new factions)
    http://www.twcenter.net/forums/showt...ew-factions%29

    How to split a region in TWS2
    http://www.twcenter.net/forums/showt...split-a-region

    Eras Total Conquest 2.3 (12 campaigns from 970-1547)

  13. #13
    izzi's Avatar A true man hates no one
    Join Date
    Jan 2010
    Location
    Flanders
    Posts
    883

    Default Re: Campaign-Tree Generator

    I think that's a possibility. Line 79 "pixeltrial = random.choice(pixels)" also makes it difficult to add the trees at the (specific) coordinates. If you just add the RGB coordinates (the variable pixels), than off course, the trees are to close towards each other. Something goes wrong when randomly putting the trees around the specific radius of the RGB sample.
    Knowledge + Understanding = Wisdom.


  14. #14

    Default Re: Campaign-Tree Generator

    Okay I figured out how to get this app to work. For some reason if you make the PNG file with Photoshop it won't work, but if you convert the PaintArea file to a PNG file using Infranview it does work.

    Is there anyone who can explain why some PNG files work while others do not?
    Morning Sun (adds Korea to the Shogun 2 map)
    http://www.twcenter.net/forums/forum...28-Morning-Sun

    Expanded Japan mod (97 new regions and 101 new factions)
    http://www.twcenter.net/forums/showt...ew-factions%29

    How to split a region in TWS2
    http://www.twcenter.net/forums/showt...split-a-region

    Eras Total Conquest 2.3 (12 campaigns from 970-1547)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •