Changes you need to follow as Modder

Follow this forum if u are a modder (having the modded version)
Contains announcements and how-to guides
Useful for forumers who want to learn how to help out in the game
Stratego (dev)
Site Admin
Posts: 15752
Joined: Fri Apr 25, 2014 9:28 pm

Re: Changes you need to follow as Modder

Post by Stratego (dev) »

new specunitactions:
please set them on the tech jsons as from code they gone to be configuration options:

Code: Select all

    
    TECH_STEALING,         //Mark the Stealing tech with this (increases stealing possibility)
    TECH_STEALING_DEFENSE, //Mark the Stealing Defense tech with this (decreases enemy stealing possibility)
    TECH_LOYALTY,          //Mark the Loyalty tech with this (on convert unit will got 1 hp instead)
    TECH_SEE_ALLY_LOS,     //Mark the Writing tech with this (lets u see your allies line of sight)
    TECH_BONE_SIGHT,       //Mark the Bone Sight tech with this (lets u see all corpses on map (for AOF))
    TECH_NATURE_CALL,      //Mark the Nature Call tech with this (lets u see all animals on map (for AOF))
Stratego (dev)
Site Admin
Posts: 15752
Joined: Fri Apr 25, 2014 9:28 pm

Re: Changes you need to follow as Modder

Post by Stratego (dev) »

python changed to check skinpacks if all files are used in jsons - so probably will not run into errors

Code: Select all


from os import listdir
from os.path import isfile, join
import json
import os


my_os_sep="/"
path_work="effects/"
fname_output = "id/gen_effect_id.txt"
path_units="units/"
path_skin_packs="gfx/cosm_units/"
fname_unit_id_filename_rel = "id/gen_unit_id.txt"
fname_unit_categories = "id/gen_unit_categories.txt"
fname_unit_builders = "id/gen_unit_builders.json"
fname_unit_directories = "id/gen_dirs.txt"







print("Effects start")


collected_errors = ""
used_effect_names=","
used_effect_ids=","
used_effect_id_max=0

onlyfiles = [f for f in listdir(path_work) if isfile(join(path_work, f)) and f.endswith(".json")]
f_workfile = open(fname_output, 'w')
cnt=0
sum=len(onlyfiles)
for filename in onlyfiles :    
    with open(path_work+filename) as f:
      cnt=cnt+1
      print(str(cnt)+"/"+str(sum)+ " effect processing:" + filename)
      data = json.load(f)
      effect_id=str(data['effectDefID'])
      effect_name_string=data['effectNameString']
      if 'effectDefIDRelated' in data and data['effectDefIDRelated'] is not None and data['effectDefIDRelated'] != 0:
        collected_errors = collected_errors + "ERROR effectDefIDRelated must not be used!:" + effect_name_string + "\n"
      if ","+effect_name_string+"," in used_effect_names:
        collected_errors = collected_errors + "duplicate effect name:" + effect_name_string + "\n"
      else:
        used_effect_names=used_effect_names+effect_name_string+","      
      if ","+effect_id+"," in used_effect_ids:
        collected_errors = collected_errors + "duplicate effect id:" + effect_id + "\n"
      else:
        used_effect_ids=used_effect_ids+effect_id+","        
      if used_effect_id_max < int(effect_id):
        used_effect_id_max = int(effect_id)
      f_workfile.write(effect_id + "," + effect_name_string + "," + filename + ";" + "\n")
   
print("\n\n")   
print(fname_output + " written\n")



print("Cosmetic pack checks, caching all filenames\n\n")


skin_filenames=","
for root, dirs, files in os.walk(path_skin_packs):
    #print("DIR:" + root)
    if path_skin_packs != root:
        for f in files:
            #print(f)
            if ".meta" not in f:
                skin_filenames=skin_filenames + f + ","





print("Units start")



onlyfiles = [f for f in listdir(path_units) if isfile(join(path_units, f)) and f.endswith(".json")]


f_unit_id_filename_rel = open(fname_unit_id_filename_rel, 'w')
f_unit_categories = open(fname_unit_categories, 'w')
f_unit_builders = open(fname_unit_builders, 'w')
f_unit_builders.write("{\"list\":[" + "\n")


used_ids=","
used_id_max=0
used_unit_type_names=","
collected_non_jsoned=","
cnt=0
sum=len(onlyfiles)
known_non_jsoneds=",EFFECT_INSTANT_SWING_AROUND_EFFECT,EFFECT_ENCHANT_VANISHING,EFFECT_FIRE_ARROWS,EFFECT_FIRE_ARROWS_INSTANT,EFFECT_FIRE_ARROWS_ON_EVERYONE,EFFECT_ENCHANT_VANISHING_SILENT,EFFECT_ENCHANT_POISONED_WEAPON,EFFECT_TRAMPLE,EFFECT_ENCHANT_FIRE_WEAPON,EFFECT_ENCHANT_LIGHTNING_WEAPON,EFFECT_INSTANT_THUNDER_STRIKE,EFFECT_INSTANT_FIREBALL_UNDEAD,EFFECT_INSTANT_FIREBALL_EFFECT,EFFECT_INSTANT_THUNDER_STORM,EFFECT_ENCHANTMENT_CURSED,EFFECT_INSTANT_DRAGON_FIRE,EFFECT_INSTANT_DRAGON_BREATH,EFFECT_INSTANT_BANSHEE_SCREAM,EFFECT_ENCHANT_FEAR,EFFECT_IMMEDIATE_CONVERSION,EFFECT_INSTANT_SACRI_HP_DAMAGE,EFFECT_SLOWING,EFFECT_SLOWING_1,EFFECT_INSTANT_TROLL_ROT,EFFECT_DISARMOR,EFFECT_INSTANT_PAIN_DAMAGER,EFFECT_INSTANT_CASTER_AND_TARGET_DIES,EFFECT_INSTANT_SUMMON_SKELETON,EFFECT_ANIMATE_DEAD,EFFECT_ANIMATE_DEAD_CLOSE,EFFECT_INSTANT_INCREMENT_VANISHING,EFFECT_INSTANT_MAGIC_ARROW,EFFECT_AURA_LIFELINK,EFFECT_ENCHANT_VISION,EFFECT_AURA_VISION_ULIMITED,EFFECT_VISION,EFFECT_ENCHANT_STRENGTHEN,EFFECT_ENCHANT_STRENGTHEN_MYSELF,EFFECT_INSTANT_TRAMPLE,EFFECT_INSTANT_HEAL_3,EFFECT_INSTANT_EAT_CORPSE_TO_HEAL,EFFECT_STRENGTH_1ATTACK,EFFECT_STRENGTH_2ATTACK,EFFECT_STRENGTH_3ATTACK,EFFECT_AURA_STRENGTH_1ATTACK_ULIMITED,EFFECT_AURA_STRENGTH_2ATTACK_ULIMITED,EFFECT_AURA_STRENGTH_3ATTACK_ULIMITED,EFFECT_CAST_AURA_STRENGTH_1ATTACK,EFFECT_AURA_STRENGTH_1ATTACK,EFFECT_CAST_FIRE_WEAPON,EFFECT_CAST_LIGHTNING_WEAPON,EFFECT_ENCHANT_FORESTWALK,"
for filename in onlyfiles :
    with open(path_units+filename) as f:
      cnt=cnt+1
      print(str(cnt)+"/"+str(sum)+ " unit processing:" + filename)
      data = json.load(f)
      specs=""
      races=""
      is_fact="N"
      is_tech="N"
      default_image=""
      default_image_imgcolumns="1"
      unit_cost="0"
      unit_typeid=str(data['unitType'])
      unit_typename=data['unitTypeName']
      if 'unitStatSheet' in data: 
        if 'unit' in data['unitStatSheet']:
          if 'trnRaces' in data['unitStatSheet']['unit']:
            if data['unitStatSheet']['unit']['trnRaces'] is not None:
              races=str(data['unitStatSheet']['unit']['trnRaces']).replace("'", "").replace(" ", "").replace("[", "").replace("]", "")
          if 'trnSpecUnitActions' in data['unitStatSheet']['unit']:
            if data['unitStatSheet']['unit']['trnSpecUnitActions'] is not None:
              specs=str(data['unitStatSheet']['unit']['trnSpecUnitActions']).replace("'", "").replace(" ", "").replace("[", "").replace("]", "")
          if 'trnWeaponEffects' in data['unitStatSheet']['unit']:
            we=data['unitStatSheet']['unit']['trnWeaponEffects']
            if we is not None:
              for weaponeffect in we:                
                  if 'effOptions' in weaponeffect:                 
                    if weaponeffect['effOptions'] is not None:
                      effects=str(weaponeffect['effOptions']).replace("'", "").replace(" ", "").replace("[", "").replace("]", "")
                      effectssplit=effects.split(sep=",")                  
                      if ('effDefault' not in weaponeffect):
                        collected_errors = collected_errors + ".........................MISSING trnWeaponEffects/effDefault in:" + unit_typename + "\n"
                      else:
                        if (weaponeffect['effDefault'] is None): 
                          collected_errors = collected_errors + ".........................EMPTY trnWeaponEffects/effDefault in:" + unit_typename + "\n"
                      if ('effDefault' in weaponeffect) and (weaponeffect['effDefault'] is not None):
                        effect_default_option=str(weaponeffect['effDefault']).replace("'", "").replace(" ", "").replace("[", "").replace("]", "")
                        effectssplit.append(effect_default_option)
                      for effectitem in effectssplit:
                        if ","+effectitem+"," not in used_effect_names:
                          if ","+effectitem+"," in known_non_jsoneds:
                            if ","+effectitem+"," not in collected_non_jsoned:
                              collected_non_jsoned = collected_non_jsoned  + effectitem + ","
                          else:
                            collected_errors = collected_errors + "MISSING effect definition:" + effectitem + " in:" + unit_typename + "\n"
          if 'isTechnology' in data['unitStatSheet']['unit']:  
            if data['unitStatSheet']['unit']['isTechnology']==True:
              is_tech="Y"
          if 'isFactory' in data['unitStatSheet']['unit']:  
            if data['unitStatSheet']['unit']['isFactory']==True:
              is_fact="Y"
          if 'costTurn' in data['unitStatSheet']['unit']:      
            unit_cost=str(data['unitStatSheet']['unit']['costTurn'])
      if 'uiDefinition' in data:
        if 'visuals' in data['uiDefinition']:
          if len(data['uiDefinition']['visuals'])>0:
            if 'imgName' in data['uiDefinition']['visuals'][0]:
              default_image = data['uiDefinition']['visuals'][0]['imgName']
              if data['uiDefinition']['visuals'][0]['type'] != "DEFAULT":
                collected_errors = collected_errors + "ERROR: 0th visual is not default:" + filename + "\n"
              image_only_file_name=my_os_sep+default_image             
              image_only_file_name=image_only_file_name[image_only_file_name.rfind(my_os_sep)+1:]              
              if ","+image_only_file_name+"," in skin_filenames:   
                skin_filenames = skin_filenames.replace(image_only_file_name+",", '')              
              default_image_imgcolumns = str(data['uiDefinition']['visuals'][0]['imgColumns'])            
          if len(data['uiDefinition']['visuals'])>1:
            if 'imgName' in data['uiDefinition']['visuals'][1]:
              default_image = data['uiDefinition']['visuals'][1]['imgName']
              image_only_file_name=my_os_sep+default_image             
              image_only_file_name=image_only_file_name[image_only_file_name.rfind(my_os_sep)+1:]              
              if ","+image_only_file_name+"," in skin_filenames:   
                skin_filenames = skin_filenames.replace(image_only_file_name+",", '')              
      if ","+unit_typeid+"," in used_ids:
        collected_errors = collected_errors + "duplicate id:" + unit_typeid + "\n"
      else:
        used_ids=used_ids+unit_typeid+","
      if used_id_max < int(unit_typeid):
        used_id_max = int(unit_typeid)
      if ","+unit_typename+"," in used_unit_type_names:        
        collected_errors = collected_errors + "duplicate type name:" + unit_typename + "\n"
      else:
        used_unit_type_names=used_unit_type_names+unit_typename+","        
      f_unit_id_filename_rel.write( unit_typeid + "|" +  unit_typename  + "|" + filename  + "|" + unit_cost + "|"  + default_image + "|" + default_image_imgcolumns + "|"  + specs + "|" + races +  "|" + is_tech + "|" + is_fact + ";" + "\n")
      if 'unitStatSheet' in data: 
        if 'unit' in data['unitStatSheet']: 
          if 'trnCategories' in data['unitStatSheet']['unit']: 
            if data['unitStatSheet']['unit']['trnCategories'] is not None: 
              if str(data['unitStatSheet']['unit']['trnCategories']) != '[]': 
                f_unit_categories.write(data['unitTypeName'] + ":" + str(data['unitStatSheet']['unit']['trnCategories']) + ";" + "\n")
          if 'trnBuilders' in data['unitStatSheet']['unit']: 
            if data['unitStatSheet']['unit']['trnBuilders'] is not None: 
              if str(data['unitStatSheet']['unit']['trnBuilders']) != '[]': 
                if str(data['unitStatSheet']['unit']['trnBuilders']) != '{}': 
                  f_unit_builders.write("{\"unitIdString\":" + "\""  + data['unitTypeName'] + "\"," + "\"trnBuilders\":" + str(data['unitStatSheet']['unit']['trnBuilders']).replace("'", "\"") + "}")
                  if filename == onlyfiles[-1]:
                    f_unit_builders.write("\n")
                  else:
                    f_unit_builders.write("," + "\n")
                  

f_unit_builders.write("]}" + "\n")

if (len(skin_filenames) > 3):
    collected_errors = collected_errors + "MISSING SKINPACK files!:" + skin_filenames + "\n"


print("Directory tree start")

f_unit_directories = open(fname_unit_directories, 'w')


startpath = "."
for root, dirs, files in os.walk(startpath):
    #level = root.replace(startpath, '').count(os.sep)
    #indent = ' ' * 4 * (level)
    #print('{}{}/'.format(indent, os.path.basename(root)))
    #subindent = ' ' * 4 * (level + 1)
    #print("DIR:" + root)
    if "cosm_units" in root or "wallpaper" in root or "cosmetics" in root:
        f_unit_directories.write("DIRBREAK:" + "\n")
        f_unit_directories.write("DIR:" + root+ "\n")
        for d in dirs:
            f_unit_directories.write(d + "\n")
        for f in files:
            #print('{}{}'.format(subindent, f))
            #print(f)
            if ".meta" not in f:
                f_unit_directories.write(f + "\n")

print("\n\n")      
print(fname_unit_directories + " written\n")



print(fname_unit_id_filename_rel + " written\n")
print(fname_unit_categories + " written\n")
print(fname_unit_builders + " written\n")

print("Last effect id:" + str(used_effect_id_max))
print("Last unit id:" + str(used_id_max) + "\n(warning! in many alternatives the biggest ID-s  are spec ids - so not the real last one among units...)\n")


if collected_non_jsoned!=",":
  print("Error " + str(collected_non_jsoned.count(",") - 1) + " NON JSONED EFFECTS:\n"   + collected_non_jsoned + "\n")  

print("Errors:\n" + collected_errors)
input("Press Enter to continue...")





Stratego (dev)
Site Admin
Posts: 15752
Joined: Fri Apr 25, 2014 9:28 pm

Re: Changes you need to follow as Modder

Post by Stratego (dev) »

previous python code updated with fixes
Stratego (dev)
Site Admin
Posts: 15752
Joined: Fri Apr 25, 2014 9:28 pm

Re: Changes you need to follow as Modder

Post by Stratego (dev) »

the python was wrong, here is the fixed

Code: Select all

from os import listdir
from os.path import isfile, join
import json
import os


my_os_sep="/"
path_work="effects/"
fname_output = "id/gen_effect_id.txt"
path_units="units/"
path_skin_packs="gfx/cosm_units/"
fname_unit_id_filename_rel = "id/gen_unit_id.txt"
fname_unit_categories = "id/gen_unit_categories.txt"
fname_unit_builders = "id/gen_unit_builders.json"
fname_unit_directories = "id/gen_dirs.txt"







print("Effects start")


collected_errors = ""
used_effect_names=","
used_effect_ids=","
used_effect_id_max=0

onlyfiles = [f for f in listdir(path_work) if isfile(join(path_work, f)) and f.endswith(".json")]
f_workfile = open(fname_output, 'w')
cnt=0
sum=len(onlyfiles)
for filename in onlyfiles :    
    with open(path_work+filename) as f:
      cnt=cnt+1
      print(str(cnt)+"/"+str(sum)+ " effect processing:" + filename)
      data = json.load(f)
      effect_id=str(data['effectDefID'])
      effect_name_string=data['effectNameString']
      if 'effectDefIDRelated' in data and data['effectDefIDRelated'] is not None and data['effectDefIDRelated'] != 0:
        collected_errors = collected_errors + "ERROR effectDefIDRelated must not be used!:" + effect_name_string + "\n"
      if ","+effect_name_string+"," in used_effect_names:
        collected_errors = collected_errors + "duplicate effect name:" + effect_name_string + "\n"
      else:
        used_effect_names=used_effect_names+effect_name_string+","      
      if ","+effect_id+"," in used_effect_ids:
        collected_errors = collected_errors + "duplicate effect id:" + effect_id + "\n"
      else:
        used_effect_ids=used_effect_ids+effect_id+","        
      if used_effect_id_max < int(effect_id):
        used_effect_id_max = int(effect_id)
      f_workfile.write(effect_id + "," + effect_name_string + "," + filename + ";" + "\n")
   
print("\n\n")   
print(fname_output + " written\n")



print("Cosmetic pack checks, caching all filenames\n\n")


skin_filenames=","
for root, dirs, files in os.walk(path_skin_packs):
    #print("DIR:" + root)
    if path_skin_packs != root:
        for f in files:
            #print(f)
            if ".meta" not in f:
                skin_filenames=skin_filenames + f + ","





print("Units start")



onlyfiles = [f for f in listdir(path_units) if isfile(join(path_units, f)) and f.endswith(".json")]


f_unit_id_filename_rel = open(fname_unit_id_filename_rel, 'w')
f_unit_categories = open(fname_unit_categories, 'w')
f_unit_builders = open(fname_unit_builders, 'w')
f_unit_builders.write("{\"list\":[" + "\n")


used_ids=","
used_id_max=0
used_unit_type_names=","
collected_non_jsoned=","
cnt=0
sum=len(onlyfiles)
known_non_jsoneds=",EFFECT_INSTANT_SWING_AROUND_EFFECT,EFFECT_ENCHANT_VANISHING,EFFECT_FIRE_ARROWS,EFFECT_FIRE_ARROWS_INSTANT,EFFECT_FIRE_ARROWS_ON_EVERYONE,EFFECT_ENCHANT_VANISHING_SILENT,EFFECT_ENCHANT_POISONED_WEAPON,EFFECT_TRAMPLE,EFFECT_ENCHANT_FIRE_WEAPON,EFFECT_ENCHANT_LIGHTNING_WEAPON,EFFECT_INSTANT_THUNDER_STRIKE,EFFECT_INSTANT_FIREBALL_UNDEAD,EFFECT_INSTANT_FIREBALL_EFFECT,EFFECT_INSTANT_THUNDER_STORM,EFFECT_ENCHANTMENT_CURSED,EFFECT_INSTANT_DRAGON_FIRE,EFFECT_INSTANT_DRAGON_BREATH,EFFECT_INSTANT_BANSHEE_SCREAM,EFFECT_ENCHANT_FEAR,EFFECT_IMMEDIATE_CONVERSION,EFFECT_INSTANT_SACRI_HP_DAMAGE,EFFECT_SLOWING,EFFECT_SLOWING_1,EFFECT_INSTANT_TROLL_ROT,EFFECT_DISARMOR,EFFECT_INSTANT_PAIN_DAMAGER,EFFECT_INSTANT_CASTER_AND_TARGET_DIES,EFFECT_INSTANT_SUMMON_SKELETON,EFFECT_ANIMATE_DEAD,EFFECT_ANIMATE_DEAD_CLOSE,EFFECT_INSTANT_INCREMENT_VANISHING,EFFECT_INSTANT_MAGIC_ARROW,EFFECT_AURA_LIFELINK,EFFECT_ENCHANT_VISION,EFFECT_AURA_VISION_ULIMITED,EFFECT_VISION,EFFECT_ENCHANT_STRENGTHEN,EFFECT_ENCHANT_STRENGTHEN_MYSELF,EFFECT_INSTANT_TRAMPLE,EFFECT_INSTANT_HEAL_3,EFFECT_INSTANT_EAT_CORPSE_TO_HEAL,EFFECT_STRENGTH_1ATTACK,EFFECT_STRENGTH_2ATTACK,EFFECT_STRENGTH_3ATTACK,EFFECT_AURA_STRENGTH_1ATTACK_ULIMITED,EFFECT_AURA_STRENGTH_2ATTACK_ULIMITED,EFFECT_AURA_STRENGTH_3ATTACK_ULIMITED,EFFECT_CAST_AURA_STRENGTH_1ATTACK,EFFECT_AURA_STRENGTH_1ATTACK,EFFECT_CAST_FIRE_WEAPON,EFFECT_CAST_LIGHTNING_WEAPON,EFFECT_ENCHANT_FORESTWALK,"
for filename in onlyfiles :
    with open(path_units+filename) as f:
      cnt=cnt+1
      print(str(cnt)+"/"+str(sum)+ " unit processing:" + filename)
      data = json.load(f)
      specs=""
      races=""
      is_fact="N"
      is_tech="N"
      default_image=""
      default_image_imgcolumns="1"
      unit_cost="0"
      unit_typeid=str(data['unitType'])
      unit_typename=data['unitTypeName']
      if 'unitStatSheet' in data: 
        if 'unit' in data['unitStatSheet']:
          if 'trnRaces' in data['unitStatSheet']['unit']:
            if data['unitStatSheet']['unit']['trnRaces'] is not None:
              races=str(data['unitStatSheet']['unit']['trnRaces']).replace("'", "").replace(" ", "").replace("[", "").replace("]", "")
          if 'trnSpecUnitActions' in data['unitStatSheet']['unit']:
            if data['unitStatSheet']['unit']['trnSpecUnitActions'] is not None:
              specs=str(data['unitStatSheet']['unit']['trnSpecUnitActions']).replace("'", "").replace(" ", "").replace("[", "").replace("]", "")
          if 'trnWeaponEffects' in data['unitStatSheet']['unit']:
            we=data['unitStatSheet']['unit']['trnWeaponEffects']
            if we is not None:
              for weaponeffect in we:                
                  if 'effOptions' in weaponeffect:                 
                    if weaponeffect['effOptions'] is not None:
                      effects=str(weaponeffect['effOptions']).replace("'", "").replace(" ", "").replace("[", "").replace("]", "")
                      effectssplit=effects.split(sep=",")                  
                      if ('effDefault' not in weaponeffect):
                        collected_errors = collected_errors + ".........................MISSING trnWeaponEffects/effDefault in:" + unit_typename + "\n"
                      else:
                        if (weaponeffect['effDefault'] is None): 
                          collected_errors = collected_errors + ".........................EMPTY trnWeaponEffects/effDefault in:" + unit_typename + "\n"
                      if ('effDefault' in weaponeffect) and (weaponeffect['effDefault'] is not None):
                        effect_default_option=str(weaponeffect['effDefault']).replace("'", "").replace(" ", "").replace("[", "").replace("]", "")
                        effectssplit.append(effect_default_option)
                      for effectitem in effectssplit:
                        if ","+effectitem+"," not in used_effect_names:
                          if ","+effectitem+"," in known_non_jsoneds:
                            if ","+effectitem+"," not in collected_non_jsoned:
                              collected_non_jsoned = collected_non_jsoned  + effectitem + ","
                          else:
                            collected_errors = collected_errors + "MISSING effect definition:" + effectitem + " in:" + unit_typename + "\n"
          if 'isTechnology' in data['unitStatSheet']['unit']:  
            if data['unitStatSheet']['unit']['isTechnology']==True:
              is_tech="Y"
          if 'isFactory' in data['unitStatSheet']['unit']:  
            if data['unitStatSheet']['unit']['isFactory']==True:
              is_fact="Y"
          if 'costTurn' in data['unitStatSheet']['unit']:      
            unit_cost=str(data['unitStatSheet']['unit']['costTurn'])
      if 'uiDefinition' in data:
        if 'visuals' in data['uiDefinition']:
          if len(data['uiDefinition']['visuals'])>0:
            if 'imgName' in data['uiDefinition']['visuals'][0]:
              default_image = data['uiDefinition']['visuals'][0]['imgName']
              if data['uiDefinition']['visuals'][0]['type'] != "DEFAULT":
                collected_errors = collected_errors + "ERROR: 0th visual is not default:" + filename + "\n"
              image_only_file_name=my_os_sep+default_image             
              image_only_file_name=image_only_file_name[image_only_file_name.rfind(my_os_sep)+1:]              
              if ","+image_only_file_name+"," in skin_filenames:   
                skin_filenames = skin_filenames.replace(image_only_file_name+",", '')              
              default_image_imgcolumns = str(data['uiDefinition']['visuals'][0]['imgColumns'])            
          if len(data['uiDefinition']['visuals'])>1:
            if 'imgName' in data['uiDefinition']['visuals'][1]:
              default_image1 = data['uiDefinition']['visuals'][1]['imgName']
              image_only_file_name=my_os_sep+default_image1             
              image_only_file_name=image_only_file_name[image_only_file_name.rfind(my_os_sep)+1:]              
              if ","+image_only_file_name+"," in skin_filenames:   
                skin_filenames = skin_filenames.replace(image_only_file_name+",", '')              
      if ","+unit_typeid+"," in used_ids:
        collected_errors = collected_errors + "duplicate id:" + unit_typeid + "\n"
      else:
        used_ids=used_ids+unit_typeid+","
      if used_id_max < int(unit_typeid):
        used_id_max = int(unit_typeid)
      if ","+unit_typename+"," in used_unit_type_names:        
        collected_errors = collected_errors + "duplicate type name:" + unit_typename + "\n"
      else:
        used_unit_type_names=used_unit_type_names+unit_typename+","        
      f_unit_id_filename_rel.write( unit_typeid + "|" +  unit_typename  + "|" + filename  + "|" + unit_cost + "|"  + default_image + "|" + default_image_imgcolumns + "|"  + specs + "|" + races +  "|" + is_tech + "|" + is_fact + ";" + "\n")
      if 'unitStatSheet' in data: 
        if 'unit' in data['unitStatSheet']: 
          if 'trnCategories' in data['unitStatSheet']['unit']: 
            if data['unitStatSheet']['unit']['trnCategories'] is not None: 
              if str(data['unitStatSheet']['unit']['trnCategories']) != '[]': 
                f_unit_categories.write(data['unitTypeName'] + ":" + str(data['unitStatSheet']['unit']['trnCategories']) + ";" + "\n")
          if 'trnBuilders' in data['unitStatSheet']['unit']: 
            if data['unitStatSheet']['unit']['trnBuilders'] is not None: 
              if str(data['unitStatSheet']['unit']['trnBuilders']) != '[]': 
                if str(data['unitStatSheet']['unit']['trnBuilders']) != '{}': 
                  f_unit_builders.write("{\"unitIdString\":" + "\""  + data['unitTypeName'] + "\"," + "\"trnBuilders\":" + str(data['unitStatSheet']['unit']['trnBuilders']).replace("'", "\"") + "}")
                  if filename == onlyfiles[-1]:
                    f_unit_builders.write("\n")
                  else:
                    f_unit_builders.write("," + "\n")
                  

f_unit_builders.write("]}" + "\n")

if (len(skin_filenames) > 3):
    collected_errors = collected_errors + "MISSING SKINPACK files!:" + skin_filenames + "\n"


print("Directory tree start")

f_unit_directories = open(fname_unit_directories, 'w')


startpath = "."
for root, dirs, files in os.walk(startpath):
    #level = root.replace(startpath, '').count(os.sep)
    #indent = ' ' * 4 * (level)
    #print('{}{}/'.format(indent, os.path.basename(root)))
    #subindent = ' ' * 4 * (level + 1)
    #print("DIR:" + root)
    if "cosm_units" in root or "wallpaper" in root or "cosmetics" in root:
        f_unit_directories.write("DIRBREAK:" + "\n")
        f_unit_directories.write("DIR:" + root+ "\n")
        for d in dirs:
            f_unit_directories.write(d + "\n")
        for f in files:
            #print('{}{}'.format(subindent, f))
            #print(f)
            if ".meta" not in f:
                f_unit_directories.write(f + "\n")

print("\n\n")      
print(fname_unit_directories + " written\n")



print(fname_unit_id_filename_rel + " written\n")
print(fname_unit_categories + " written\n")
print(fname_unit_builders + " written\n")

print("Last effect id:" + str(used_effect_id_max))
print("Last unit id:" + str(used_id_max) + "\n(warning! in many alternatives the biggest ID-s  are spec ids - so not the real last one among units...)\n")


if collected_non_jsoned!=",":
  print("Error " + str(collected_non_jsoned.count(",") - 1) + " NON JSONED EFFECTS:\n"   + collected_non_jsoned + "\n")  

print("Errors:\n" + collected_errors)
input("Press Enter to continue...")



Stratego (dev)
Site Admin
Posts: 15752
Joined: Fri Apr 25, 2014 9:28 pm

Re: Changes you need to follow as Modder

Post by Stratego (dev) »

and again a changed Python,
new extra check if the shopitem ID-s are duplicated accidentally.
(all shopconfig files were invalid due to having extra comma on the end of the list of items - please remove those - i have removed them in all alternatives - but if anyone have pack for modification he will run into that error using this python)

Code: Select all

from os import listdir
from os.path import isfile, join
import json
import os


my_os_sep="/"
path_work="effects/"
fname_output = "id/gen_effect_id.txt"
path_units="units/"
path_skin_packs="gfx/cosm_units/"
fname_unit_id_filename_rel = "id/gen_unit_id.txt"
fname_unit_categories = "id/gen_unit_categories.txt"
fname_unit_builders = "id/gen_unit_builders.json"
fname_unit_directories = "id/gen_dirs.txt"
fname_shopitems = "others/shopconfig.json"




print("Effects start")


collected_errors = ""
used_effect_names=","
used_effect_ids=","
used_effect_id_max=0

onlyfiles = [f for f in listdir(path_work) if isfile(join(path_work, f)) and f.endswith(".json")]
f_workfile = open(fname_output, 'w')
cnt=0
sum=len(onlyfiles)
for filename in onlyfiles :    
    with open(path_work+filename) as f:
      cnt=cnt+1
      print(str(cnt)+"/"+str(sum)+ " effect processing:" + filename)
      data = json.load(f)
      effect_id=str(data['effectDefID'])
      effect_name_string=data['effectNameString']
      if 'effectDefIDRelated' in data and data['effectDefIDRelated'] is not None and data['effectDefIDRelated'] != 0:
        collected_errors = collected_errors + "ERROR effectDefIDRelated must not be used!:" + effect_name_string + "\n"
      if ","+effect_name_string+"," in used_effect_names:
        collected_errors = collected_errors + "duplicate effect name:" + effect_name_string + "\n"
      else:
        used_effect_names=used_effect_names+effect_name_string+","      
      if ","+effect_id+"," in used_effect_ids:
        collected_errors = collected_errors + "duplicate effect id:" + effect_id + "\n"
      else:
        used_effect_ids=used_effect_ids+effect_id+","        
      if used_effect_id_max < int(effect_id):
        used_effect_id_max = int(effect_id)
      f_workfile.write(effect_id + "," + effect_name_string + "," + filename + ";" + "\n")
   
print("\n\n")   
print(fname_output + " written\n")



print("Cosmetic pack checks, caching all filenames\n\n")


skin_filenames=","
for root, dirs, files in os.walk(path_skin_packs):
    #print("DIR:" + root)
    if path_skin_packs != root:
        for f in files:
            #print(f)
            if ".meta" not in f:
                skin_filenames=skin_filenames + f + ","





print("Units start")



onlyfiles = [f for f in listdir(path_units) if isfile(join(path_units, f)) and f.endswith(".json")]


f_unit_id_filename_rel = open(fname_unit_id_filename_rel, 'w')
f_unit_categories = open(fname_unit_categories, 'w')
f_unit_builders = open(fname_unit_builders, 'w')
f_unit_builders.write("{\"list\":[" + "\n")


used_ids=","
used_id_max=0
used_unit_type_names=","
collected_non_jsoned=","
cnt=0
sum=len(onlyfiles)
known_non_jsoneds=",EFFECT_INSTANT_SWING_AROUND_EFFECT,EFFECT_ENCHANT_VANISHING,EFFECT_FIRE_ARROWS,EFFECT_FIRE_ARROWS_INSTANT,EFFECT_FIRE_ARROWS_ON_EVERYONE,EFFECT_ENCHANT_VANISHING_SILENT,EFFECT_ENCHANT_POISONED_WEAPON,EFFECT_TRAMPLE,EFFECT_ENCHANT_FIRE_WEAPON,EFFECT_ENCHANT_LIGHTNING_WEAPON,EFFECT_INSTANT_THUNDER_STRIKE,EFFECT_INSTANT_FIREBALL_UNDEAD,EFFECT_INSTANT_FIREBALL_EFFECT,EFFECT_INSTANT_THUNDER_STORM,EFFECT_ENCHANTMENT_CURSED,EFFECT_INSTANT_DRAGON_FIRE,EFFECT_INSTANT_DRAGON_BREATH,EFFECT_INSTANT_BANSHEE_SCREAM,EFFECT_ENCHANT_FEAR,EFFECT_IMMEDIATE_CONVERSION,EFFECT_INSTANT_SACRI_HP_DAMAGE,EFFECT_SLOWING,EFFECT_SLOWING_1,EFFECT_INSTANT_TROLL_ROT,EFFECT_DISARMOR,EFFECT_INSTANT_PAIN_DAMAGER,EFFECT_INSTANT_CASTER_AND_TARGET_DIES,EFFECT_INSTANT_SUMMON_SKELETON,EFFECT_ANIMATE_DEAD,EFFECT_ANIMATE_DEAD_CLOSE,EFFECT_INSTANT_INCREMENT_VANISHING,EFFECT_INSTANT_MAGIC_ARROW,EFFECT_AURA_LIFELINK,EFFECT_ENCHANT_VISION,EFFECT_AURA_VISION_ULIMITED,EFFECT_VISION,EFFECT_ENCHANT_STRENGTHEN,EFFECT_ENCHANT_STRENGTHEN_MYSELF,EFFECT_INSTANT_TRAMPLE,EFFECT_INSTANT_HEAL_3,EFFECT_INSTANT_EAT_CORPSE_TO_HEAL,EFFECT_STRENGTH_1ATTACK,EFFECT_STRENGTH_2ATTACK,EFFECT_STRENGTH_3ATTACK,EFFECT_AURA_STRENGTH_1ATTACK_ULIMITED,EFFECT_AURA_STRENGTH_2ATTACK_ULIMITED,EFFECT_AURA_STRENGTH_3ATTACK_ULIMITED,EFFECT_CAST_AURA_STRENGTH_1ATTACK,EFFECT_AURA_STRENGTH_1ATTACK,EFFECT_CAST_FIRE_WEAPON,EFFECT_CAST_LIGHTNING_WEAPON,EFFECT_ENCHANT_FORESTWALK,"
for filename in onlyfiles :
    with open(path_units+filename) as f:
      cnt=cnt+1
      print(str(cnt)+"/"+str(sum)+ " unit processing:" + filename)
      data = json.load(f)
      specs=""
      races=""
      is_fact="N"
      is_tech="N"
      default_image=""
      default_image_imgcolumns="1"
      unit_cost="0"
      unit_typeid=str(data['unitType'])
      unit_typename=data['unitTypeName']
      if 'unitStatSheet' in data: 
        if 'unit' in data['unitStatSheet']:
          if 'trnRaces' in data['unitStatSheet']['unit']:
            if data['unitStatSheet']['unit']['trnRaces'] is not None:
              races=str(data['unitStatSheet']['unit']['trnRaces']).replace("'", "").replace(" ", "").replace("[", "").replace("]", "")
          if 'trnSpecUnitActions' in data['unitStatSheet']['unit']:
            if data['unitStatSheet']['unit']['trnSpecUnitActions'] is not None:
              specs=str(data['unitStatSheet']['unit']['trnSpecUnitActions']).replace("'", "").replace(" ", "").replace("[", "").replace("]", "")
          if 'trnWeaponEffects' in data['unitStatSheet']['unit']:
            we=data['unitStatSheet']['unit']['trnWeaponEffects']
            if we is not None:
              for weaponeffect in we:                
                  if 'effOptions' in weaponeffect:                 
                    if weaponeffect['effOptions'] is not None:
                      effects=str(weaponeffect['effOptions']).replace("'", "").replace(" ", "").replace("[", "").replace("]", "")
                      effectssplit=effects.split(sep=",")                  
                      if ('effDefault' not in weaponeffect):
                        collected_errors = collected_errors + ".........................MISSING trnWeaponEffects/effDefault in:" + unit_typename + "\n"
                      else:
                        if (weaponeffect['effDefault'] is None): 
                          collected_errors = collected_errors + ".........................EMPTY trnWeaponEffects/effDefault in:" + unit_typename + "\n"
                      if ('effDefault' in weaponeffect) and (weaponeffect['effDefault'] is not None):
                        effect_default_option=str(weaponeffect['effDefault']).replace("'", "").replace(" ", "").replace("[", "").replace("]", "")
                        effectssplit.append(effect_default_option)
                      for effectitem in effectssplit:
                        if ","+effectitem+"," not in used_effect_names:
                          if ","+effectitem+"," in known_non_jsoneds:
                            if ","+effectitem+"," not in collected_non_jsoned:
                              collected_non_jsoned = collected_non_jsoned  + effectitem + ","
                          else:
                            collected_errors = collected_errors + "MISSING effect definition:" + effectitem + " in:" + unit_typename + "\n"
          if 'isTechnology' in data['unitStatSheet']['unit']:  
            if data['unitStatSheet']['unit']['isTechnology']==True:
              is_tech="Y"
          if 'isFactory' in data['unitStatSheet']['unit']:  
            if data['unitStatSheet']['unit']['isFactory']==True:
              is_fact="Y"
          if 'costTurn' in data['unitStatSheet']['unit']:      
            unit_cost=str(data['unitStatSheet']['unit']['costTurn'])
      if 'uiDefinition' in data:
        if 'visuals' in data['uiDefinition']:
          if len(data['uiDefinition']['visuals'])>0:
            if 'imgName' in data['uiDefinition']['visuals'][0]:
              default_image = data['uiDefinition']['visuals'][0]['imgName']
              if data['uiDefinition']['visuals'][0]['type'] != "DEFAULT":
                collected_errors = collected_errors + "ERROR: 0th visual is not default:" + filename + "\n"
              image_only_file_name=my_os_sep+default_image             
              image_only_file_name=image_only_file_name[image_only_file_name.rfind(my_os_sep)+1:]              
              if ","+image_only_file_name+"," in skin_filenames:   
                skin_filenames = skin_filenames.replace(image_only_file_name+",", '')              
              default_image_imgcolumns = str(data['uiDefinition']['visuals'][0]['imgColumns'])            
          if len(data['uiDefinition']['visuals'])>1:
            if 'imgName' in data['uiDefinition']['visuals'][1]:
              default_image1 = data['uiDefinition']['visuals'][1]['imgName']
              image_only_file_name=my_os_sep+default_image1             
              image_only_file_name=image_only_file_name[image_only_file_name.rfind(my_os_sep)+1:]              
              if ","+image_only_file_name+"," in skin_filenames:   
                skin_filenames = skin_filenames.replace(image_only_file_name+",", '')              
      if ","+unit_typeid+"," in used_ids:
        collected_errors = collected_errors + "duplicate id:" + unit_typeid + "\n"
      else:
        used_ids=used_ids+unit_typeid+","
      if used_id_max < int(unit_typeid):
        used_id_max = int(unit_typeid)
      if ","+unit_typename+"," in used_unit_type_names:        
        collected_errors = collected_errors + "duplicate type name:" + unit_typename + "\n"
      else:
        used_unit_type_names=used_unit_type_names+unit_typename+","        
      f_unit_id_filename_rel.write( unit_typeid + "|" +  unit_typename  + "|" + filename  + "|" + unit_cost + "|"  + default_image + "|" + default_image_imgcolumns + "|"  + specs + "|" + races +  "|" + is_tech + "|" + is_fact + ";" + "\n")
      if 'unitStatSheet' in data: 
        if 'unit' in data['unitStatSheet']: 
          if 'trnCategories' in data['unitStatSheet']['unit']: 
            if data['unitStatSheet']['unit']['trnCategories'] is not None: 
              if str(data['unitStatSheet']['unit']['trnCategories']) != '[]': 
                f_unit_categories.write(data['unitTypeName'] + ":" + str(data['unitStatSheet']['unit']['trnCategories']) + ";" + "\n")
          if 'trnBuilders' in data['unitStatSheet']['unit']: 
            if data['unitStatSheet']['unit']['trnBuilders'] is not None: 
              if str(data['unitStatSheet']['unit']['trnBuilders']) != '[]': 
                if str(data['unitStatSheet']['unit']['trnBuilders']) != '{}': 
                  f_unit_builders.write("{\"unitIdString\":" + "\""  + data['unitTypeName'] + "\"," + "\"trnBuilders\":" + str(data['unitStatSheet']['unit']['trnBuilders']).replace("'", "\"") + "}")
                  if filename == onlyfiles[-1]:
                    f_unit_builders.write("\n")
                  else:
                    f_unit_builders.write("," + "\n")
                  

f_unit_builders.write("]}" + "\n")

if (len(skin_filenames) > 3):
    collected_errors = collected_errors + "MISSING SKINPACK files!:" + skin_filenames + "\n"


print("Directory tree start")

f_unit_directories = open(fname_unit_directories, 'w')


startpath = "."
for root, dirs, files in os.walk(startpath):
    #level = root.replace(startpath, '').count(os.sep)
    #indent = ' ' * 4 * (level)
    #print('{}{}/'.format(indent, os.path.basename(root)))
    #subindent = ' ' * 4 * (level + 1)
    #print("DIR:" + root)
    if "cosm_units" in root or "wallpaper" in root or "cosmetics" in root:
        f_unit_directories.write("DIRBREAK:" + "\n")
        f_unit_directories.write("DIR:" + root+ "\n")
        for d in dirs:
            f_unit_directories.write(d + "\n")
        for f in files:
            #print('{}{}'.format(subindent, f))
            #print(f)
            if ".meta" not in f:
                f_unit_directories.write(f + "\n")


print("Shopitems start")

used_shopids=","
used_shopid_max=0
with open(fname_shopitems) as f:
    data = json.load(f)
    we=data['shopConfigItems']
    for shopitem in we:
        currid=str(shopitem['shopItemId'])
        if used_shopid_max < int(currid):
            used_shopid_max = int(currid)
        if ","+currid+"," not in used_shopids:
            used_shopids=used_shopids+currid+",";
        else:
            collected_errors = collected_errors + "DUPLICATED SHOP_ID:" + currid + "\n"


print("\n\n")      
print(fname_unit_directories + " written\n")


print(fname_unit_id_filename_rel + " written\n")
print(fname_unit_categories + " written\n")
print(fname_unit_builders + " written\n")




print("Last Shop id:" + str(used_shopid_max))
print("Last effect id:" + str(used_effect_id_max))
print("Last unit id:" + str(used_id_max) + "\n(warning! in many alternatives the biggest ID-s  are spec ids - so not the real last one among units...)\n")


if collected_non_jsoned!=",":
  print("Error " + str(collected_non_jsoned.count(",") - 1) + " NON JSONED EFFECTS:\n"   + collected_non_jsoned + "\n")  

print("Errors:\n" + collected_errors)
input("Press Enter to continue...")



Stratego (dev)
Site Admin
Posts: 15752
Joined: Fri Apr 25, 2014 9:28 pm

Re: Changes you need to follow as Modder

Post by Stratego (dev) »

again python change: now it checks if u accidentally made duplicate TAGs in unit jsons or in effect jsons:

Code: Select all

from os import listdir
from os.path import isfile, join
import json
import os


my_os_sep="/"
path_work="effects/"
fname_output = "id/gen_effect_id.txt"
path_units="units/"
path_skin_packs="gfx/cosm_units/"
fname_unit_id_filename_rel = "id/gen_unit_id.txt"
fname_unit_categories = "id/gen_unit_categories.txt"
fname_unit_builders = "id/gen_unit_builders.json"
fname_unit_directories = "id/gen_dirs.txt"
fname_shopitems = "others/shopconfig.json"

never_duplicate_in_unit_json = [
"unitTypeName","uiDefinition",
"isTechnology","costTurn","hpMax","power","rangeAttack","rangeAttackMin","armorPierce","armorNormal",
"sight","unitSizeCol","unitSizeRow","isUnderConstruction","isFactory","isWalkableThrough",
"powerAccuracyPenalty","powerRange","powerRangePenaltyPercent","attackTypeBurningRock","attackTypeArrow",
"rangeWalk","trnWalkTerrain","convertRange","convertResistance","convertPossibility",
"rangeHeal","healRate","rangeMend","mendRate","canBuild","bonusMendingWhenConstructing","bonusMending",
"bonusHealing","carryCapacity","canBeCarried","isCarriedUnitSurvivesIfIDie",
"isCarrierCanCarryUnderConstruction","isCarrierHidesCarriedUnits","isCarrierLetCarriedUnitsToShoot",
"isCarrierRemovesTerrainDrawbacks","maxActionCount","canOccupyBuilding",
"trnEffectAffectTurnsLeft","trnWeaponEffects","trnTransformTo2","trnTransformOnDie","trnRaces",
"trnCategories","trnSpecUnitActions","trnBuilders","trnBonusList","trnBestAgainstMeWater","trnBestAgainstMeGround"
]
never_duplicate_in_effect_json = [
"effectNameString","effectDefID","effectDefIDRelated",
"trnActionUnitID","trnActionUnitIDForCaster",
"trnIndicatorTextureID","trnButtonTextureID","trnProjectileSpriteID","trnActionTextureID","trnSpotAnimationSpriteID",
"indicatorTextureID","buttonTextureID","projectileSpriteID","actionTextureID","spotAnimationSpriteID",         
"chancePercent","lastsTurnNr","effectBehaviour","effectTargets","trnSystemSpecialEffectID","auraRadius",         
"isOneTimeSpell","castRangeModifier","cooldownTurnNr",                
"specCostNr","specCost","priority"
]

print("Effects start")


collected_errors = ""
collected_errors_of_duplicated_effect_TAGs=""
used_effect_names=","
used_effect_ids=","
used_effect_id_max=0

onlyfiles = [f for f in listdir(path_work) if isfile(join(path_work, f)) and f.endswith(".json")]
f_workfile = open(fname_output, 'w')
cnt=0
sum=len(onlyfiles)
for filename in onlyfiles :    
    with open(path_work+filename) as f_dupl:
      file_as_text = f_dupl.read()
      for never_duplicate_this in never_duplicate_in_effect_json:
        if file_as_text.count('"' + never_duplicate_this + '"') > 1:
          collected_errors_of_duplicated_effect_TAGs = collected_errors_of_duplicated_effect_TAGs + "!! Duplicate EFFECT TAG:" + never_duplicate_this + " in:" + filename + "\n"        
    with open(path_work+filename) as f:
      cnt=cnt+1
      print(str(cnt)+"/"+str(sum)+ " effect processing:" + filename)
      data = json.load(f)
      effect_id=str(data['effectDefID'])
      effect_name_string=data['effectNameString']
      if 'effectDefIDRelated' in data and data['effectDefIDRelated'] is not None and data['effectDefIDRelated'] != 0:
        collected_errors = collected_errors + "ERROR effectDefIDRelated must not be used!:" + effect_name_string + "\n"
      if ","+effect_name_string+"," in used_effect_names:
        collected_errors = collected_errors + "duplicate effect name:" + effect_name_string + "\n"
      else:
        used_effect_names=used_effect_names+effect_name_string+","      
      if ","+effect_id+"," in used_effect_ids:
        collected_errors = collected_errors + "duplicate effect id:" + effect_id + "\n"
      else:
        used_effect_ids=used_effect_ids+effect_id+","        
      if used_effect_id_max < int(effect_id):
        used_effect_id_max = int(effect_id)
      f_workfile.write(effect_id + "," + effect_name_string + "," + filename + ";" + "\n")
   
print("\n\n")   
print(fname_output + " written\n")



print("Cosmetic pack checks, caching all filenames\n\n")


skin_filenames=","
for root, dirs, files in os.walk(path_skin_packs):
    #print("DIR:" + root)
    if path_skin_packs != root:
        for f in files:
            #print(f)
            if ".meta" not in f:
                skin_filenames=skin_filenames + f + ","





print("Units start")



onlyfiles = [f for f in listdir(path_units) if isfile(join(path_units, f)) and f.endswith(".json")]


f_unit_id_filename_rel = open(fname_unit_id_filename_rel, 'w')
f_unit_categories = open(fname_unit_categories, 'w')
f_unit_builders = open(fname_unit_builders, 'w')
f_unit_builders.write("{\"list\":[" + "\n")


used_ids=","
used_id_max=0
used_unit_type_names=","
collected_non_jsoned=","
collected_errors_of_duplicatedTAGs=""
cnt=0
sum=len(onlyfiles)
known_non_jsoneds=",EFFECT_INSTANT_SWING_AROUND_EFFECT,EFFECT_ENCHANT_VANISHING,EFFECT_FIRE_ARROWS,EFFECT_FIRE_ARROWS_INSTANT,EFFECT_FIRE_ARROWS_ON_EVERYONE,EFFECT_ENCHANT_VANISHING_SILENT,EFFECT_ENCHANT_POISONED_WEAPON,EFFECT_TRAMPLE,EFFECT_ENCHANT_FIRE_WEAPON,EFFECT_ENCHANT_LIGHTNING_WEAPON,EFFECT_INSTANT_THUNDER_STRIKE,EFFECT_INSTANT_FIREBALL_UNDEAD,EFFECT_INSTANT_FIREBALL_EFFECT,EFFECT_INSTANT_THUNDER_STORM,EFFECT_ENCHANTMENT_CURSED,EFFECT_INSTANT_DRAGON_FIRE,EFFECT_INSTANT_DRAGON_BREATH,EFFECT_INSTANT_BANSHEE_SCREAM,EFFECT_ENCHANT_FEAR,EFFECT_IMMEDIATE_CONVERSION,EFFECT_INSTANT_SACRI_HP_DAMAGE,EFFECT_SLOWING,EFFECT_SLOWING_1,EFFECT_INSTANT_TROLL_ROT,EFFECT_DISARMOR,EFFECT_INSTANT_PAIN_DAMAGER,EFFECT_INSTANT_CASTER_AND_TARGET_DIES,EFFECT_INSTANT_SUMMON_SKELETON,EFFECT_ANIMATE_DEAD,EFFECT_ANIMATE_DEAD_CLOSE,EFFECT_INSTANT_INCREMENT_VANISHING,EFFECT_INSTANT_MAGIC_ARROW,EFFECT_AURA_LIFELINK,EFFECT_ENCHANT_VISION,EFFECT_AURA_VISION_ULIMITED,EFFECT_VISION,EFFECT_ENCHANT_STRENGTHEN,EFFECT_ENCHANT_STRENGTHEN_MYSELF,EFFECT_INSTANT_TRAMPLE,EFFECT_INSTANT_HEAL_3,EFFECT_INSTANT_EAT_CORPSE_TO_HEAL,EFFECT_STRENGTH_1ATTACK,EFFECT_STRENGTH_2ATTACK,EFFECT_STRENGTH_3ATTACK,EFFECT_AURA_STRENGTH_1ATTACK_ULIMITED,EFFECT_AURA_STRENGTH_2ATTACK_ULIMITED,EFFECT_AURA_STRENGTH_3ATTACK_ULIMITED,EFFECT_CAST_AURA_STRENGTH_1ATTACK,EFFECT_AURA_STRENGTH_1ATTACK,EFFECT_CAST_FIRE_WEAPON,EFFECT_CAST_LIGHTNING_WEAPON,EFFECT_ENCHANT_FORESTWALK,"
for filename in onlyfiles :
    never_duplicate_in_unit_json
    with open(path_units+filename) as f_dupl:
      file_as_text = f_dupl.read()
      for never_duplicate_this in never_duplicate_in_unit_json:
        if file_as_text.count('"' + never_duplicate_this + '"') > 1:
          collected_errors_of_duplicatedTAGs = collected_errors_of_duplicatedTAGs + "!! Duplicate UNIT TAG:" + never_duplicate_this + " in:" + filename + "\n"        
    with open(path_units+filename) as f:
      cnt=cnt+1
      print(str(cnt)+"/"+str(sum)+ " unit processing:" + filename)
      data = json.load(f)
      specs=""
      races=""
      is_fact="N"
      is_tech="N"
      default_image=""
      default_image_imgcolumns="1"
      unit_cost="0"
      unit_typeid=str(data['unitType'])
      unit_typename=data['unitTypeName']
      if 'unitStatSheet' in data: 
        if 'unit' in data['unitStatSheet']:
          if 'trnRaces' in data['unitStatSheet']['unit']:
            if data['unitStatSheet']['unit']['trnRaces'] is not None:
              races=str(data['unitStatSheet']['unit']['trnRaces']).replace("'", "").replace(" ", "").replace("[", "").replace("]", "")
          if 'trnSpecUnitActions' in data['unitStatSheet']['unit']:
            if data['unitStatSheet']['unit']['trnSpecUnitActions'] is not None:
              specs=str(data['unitStatSheet']['unit']['trnSpecUnitActions']).replace("'", "").replace(" ", "").replace("[", "").replace("]", "")
          if 'trnWeaponEffects' in data['unitStatSheet']['unit']:
            we=data['unitStatSheet']['unit']['trnWeaponEffects']
            if we is not None:
              for weaponeffect in we:                
                  if 'effOptions' in weaponeffect:                 
                    if weaponeffect['effOptions'] is not None:
                      effects=str(weaponeffect['effOptions']).replace("'", "").replace(" ", "").replace("[", "").replace("]", "")
                      effectssplit=effects.split(sep=",")                  
                      if ('effDefault' not in weaponeffect):
                        collected_errors = collected_errors + ".........................MISSING trnWeaponEffects/effDefault in:" + unit_typename + "\n"
                      else:
                        if (weaponeffect['effDefault'] is None): 
                          collected_errors = collected_errors + ".........................EMPTY trnWeaponEffects/effDefault in:" + unit_typename + "\n"
                      if ('effDefault' in weaponeffect) and (weaponeffect['effDefault'] is not None):
                        effect_default_option=str(weaponeffect['effDefault']).replace("'", "").replace(" ", "").replace("[", "").replace("]", "")
                        effectssplit.append(effect_default_option)
                      for effectitem in effectssplit:
                        if ","+effectitem+"," not in used_effect_names:
                          if ","+effectitem+"," in known_non_jsoneds:
                            if ","+effectitem+"," not in collected_non_jsoned:
                              collected_non_jsoned = collected_non_jsoned  + effectitem + ","
                          else:
                            collected_errors = collected_errors + "MISSING effect definition:" + effectitem + " in:" + unit_typename + "\n"
          if 'isTechnology' in data['unitStatSheet']['unit']:  
            if data['unitStatSheet']['unit']['isTechnology']==True:
              is_tech="Y"
          if 'isFactory' in data['unitStatSheet']['unit']:  
            if data['unitStatSheet']['unit']['isFactory']==True:
              is_fact="Y"
          if 'costTurn' in data['unitStatSheet']['unit']:      
            unit_cost=str(data['unitStatSheet']['unit']['costTurn'])
      if 'uiDefinition' in data:
        if 'visuals' in data['uiDefinition']:
          if len(data['uiDefinition']['visuals'])>0:
            if 'imgName' in data['uiDefinition']['visuals'][0]:
              default_image = data['uiDefinition']['visuals'][0]['imgName']
              if data['uiDefinition']['visuals'][0]['type'] != "DEFAULT":
                collected_errors = collected_errors + "ERROR: 0th visual is not default:" + filename + "\n"
              image_only_file_name=my_os_sep+default_image             
              image_only_file_name=image_only_file_name[image_only_file_name.rfind(my_os_sep)+1:]              
              if ","+image_only_file_name+"," in skin_filenames:   
                skin_filenames = skin_filenames.replace(image_only_file_name+",", '')              
              default_image_imgcolumns = str(data['uiDefinition']['visuals'][0]['imgColumns'])            
          if len(data['uiDefinition']['visuals'])>1:
            if 'imgName' in data['uiDefinition']['visuals'][1]:
              default_image1 = data['uiDefinition']['visuals'][1]['imgName']
              image_only_file_name=my_os_sep+default_image1             
              image_only_file_name=image_only_file_name[image_only_file_name.rfind(my_os_sep)+1:]              
              if ","+image_only_file_name+"," in skin_filenames:   
                skin_filenames = skin_filenames.replace(image_only_file_name+",", '')              
      if ","+unit_typeid+"," in used_ids:
        collected_errors = collected_errors + "duplicate id:" + unit_typeid + "\n"
      else:
        used_ids=used_ids+unit_typeid+","
      if used_id_max < int(unit_typeid):
        used_id_max = int(unit_typeid)
      if ","+unit_typename+"," in used_unit_type_names:        
        collected_errors = collected_errors + "duplicate type name:" + unit_typename + "\n"
      else:
        used_unit_type_names=used_unit_type_names+unit_typename+","        
      f_unit_id_filename_rel.write( unit_typeid + "|" +  unit_typename  + "|" + filename  + "|" + unit_cost + "|"  + default_image + "|" + default_image_imgcolumns + "|"  + specs + "|" + races +  "|" + is_tech + "|" + is_fact + ";" + "\n")
      if 'unitStatSheet' in data: 
        if 'unit' in data['unitStatSheet']: 
          if 'trnCategories' in data['unitStatSheet']['unit']: 
            if data['unitStatSheet']['unit']['trnCategories'] is not None: 
              if str(data['unitStatSheet']['unit']['trnCategories']) != '[]': 
                f_unit_categories.write(data['unitTypeName'] + ":" + str(data['unitStatSheet']['unit']['trnCategories']) + ";" + "\n")
          if 'trnBuilders' in data['unitStatSheet']['unit']: 
            if data['unitStatSheet']['unit']['trnBuilders'] is not None: 
              if str(data['unitStatSheet']['unit']['trnBuilders']) != '[]': 
                if str(data['unitStatSheet']['unit']['trnBuilders']) != '{}': 
                  f_unit_builders.write("{\"unitIdString\":" + "\""  + data['unitTypeName'] + "\"," + "\"trnBuilders\":" + str(data['unitStatSheet']['unit']['trnBuilders']).replace("'", "\"") + "}")
                  if filename == onlyfiles[-1]:
                    f_unit_builders.write("\n")
                  else:
                    f_unit_builders.write("," + "\n")
                 
f_unit_builders.write("]}" + "\n")

if (len(skin_filenames) > 3):
    collected_errors = collected_errors + "MISSING SKINPACK files!:" + skin_filenames + "\n"


collected_errors = collected_errors + collected_errors_of_duplicated_effect_TAGs + collected_errors_of_duplicatedTAGs;


print("Directory tree start")

f_unit_directories = open(fname_unit_directories, 'w')


startpath = "."
for root, dirs, files in os.walk(startpath):
    #level = root.replace(startpath, '').count(os.sep)
    #indent = ' ' * 4 * (level)
    #print('{}{}/'.format(indent, os.path.basename(root)))
    #subindent = ' ' * 4 * (level + 1)
    #print("DIR:" + root)
    if "cosm_units" in root or "wallpaper" in root or "cosmetics" in root:
        f_unit_directories.write("DIRBREAK:" + "\n")
        f_unit_directories.write("DIR:" + root+ "\n")
        for d in dirs:
            f_unit_directories.write(d + "\n")
        for f in files:
            #print('{}{}'.format(subindent, f))
            #print(f)
            if ".meta" not in f:
                f_unit_directories.write(f + "\n")


print("Shopitems start")

used_shopids=","
used_shopid_max=0
with open(fname_shopitems) as f:
    data = json.load(f)
    we=data['shopConfigItems']
    for shopitem in we:
        currid=str(shopitem['shopItemId'])
        if used_shopid_max < int(currid):
            used_shopid_max = int(currid)
        if ","+currid+"," not in used_shopids:
            used_shopids=used_shopids+currid+",";
        else:
            collected_errors = collected_errors + "DUPLICATED SHOP_ID:" + currid + "\n"


print("\n\n")      
print(fname_unit_directories + " written\n")


print(fname_unit_id_filename_rel + " written\n")
print(fname_unit_categories + " written\n")
print(fname_unit_builders + " written\n")




print("Last Shop id:" + str(used_shopid_max))
print("Last effect id:" + str(used_effect_id_max))
print("Last unit id:" + str(used_id_max) + "\n(warning! in many alternatives the biggest ID-s  are spec ids - so not the real last one among units...)\n")


if collected_non_jsoned!=",":
  print("Error " + str(collected_non_jsoned.count(",") - 1) + " NON JSONED EFFECTS:\n"   + collected_non_jsoned + "\n")  

print("Errors:\n" + collected_errors)
input("Press Enter to continue...")



Stratego (dev)
Site Admin
Posts: 15752
Joined: Fri Apr 25, 2014 9:28 pm

Re: Changes you need to follow as Modder

Post by Stratego (dev) »

(on PC latest python requires this as it has image pixel size checking from now:

Code: Select all

pip install Pillow
)

i will post latest python soon - i am testing it.
Stratego (dev)
Site Admin
Posts: 15752
Joined: Fri Apr 25, 2014 9:28 pm

Re: Changes you need to follow as Modder

Post by Stratego (dev) »

ok, here is new python,
it is now checking the skins if they have same pixel sizes as the unit images themselves.
(also handles the "OVERLAPPERS" folder - by the means: it ignores it - does not check them)




Code: Select all

from PIL import Image
from os import listdir
from os.path import isfile, join
import json
import os

app_prefix = "AOS"
app_ver = "101"

def get_num_pixels_string(filepath):
    width, height = Image.open(filepath).size
    #this is commented now as it was a wrong plan to do, all overlappers are now exluded
    #if "OVERLAPPERS" in filepath:
    #    if app_prefix == "AOS" or app_prefix == "AOF":
    #        height = 64
    #    else:
    #        height = 128
    return "[" + str(width) + "x" + str(height) + "]"


my_os_sep="/"
path_work="effects/"
fname_output = "id/gen_effect_id.txt"
path_units="units/"
path_skin_packs="gfx/cosm_units/"
path_gfx="gfx/"
fname_unit_id_filename_rel = "id/gen_unit_id.txt"
fname_unit_categories = "id/gen_unit_categories.txt"
fname_unit_builders = "id/gen_unit_builders.json"
fname_unit_directories = "id/gen_dirs.txt"
fname_shopitems = "others/shopconfig.json"
fname_manif = "id/gen_manif.txt"
fname_app = "id/gen_app.txt"

never_duplicate_in_unit_json = [
"unitTypeName","uiDefinition",
"isTechnology","costTurn","hpMax","power","rangeAttack","rangeAttackMin","armorPierce","armorNormal",
"sight","unitSizeCol","unitSizeRow","isUnderConstruction","isFactory","isWalkableThrough",
"powerAccuracyPenalty","powerRange","powerRangePenaltyPercent","attackTypeBurningRock","attackTypeArrow",
"rangeWalk","trnWalkTerrain","convertRange","convertResistance","convertPossibility",
"rangeHeal","healRate","rangeMend","mendRate","canBuild","bonusMendingWhenConstructing","bonusMending",
"bonusHealing","carryCapacity","canBeCarried","isCarriedUnitSurvivesIfIDie",
"isCarrierCanCarryUnderConstruction","isCarrierHidesCarriedUnits","isCarrierLetCarriedUnitsToShoot",
"isCarrierRemovesTerrainDrawbacks","maxActionCount","canOccupyBuilding",
"trnEffectAffectTurnsLeft","trnWeaponEffects","trnTransformTo2","trnTransformOnDie","trnRaces",
"trnCategories","trnSpecUnitActions","trnBuilders","trnBonusList","trnBestAgainstMeWater","trnBestAgainstMeGround"
]
never_duplicate_in_effect_json = [
"effectNameString","effectDefID","effectDefIDRelated",
"trnActionUnitID","trnActionUnitIDForCaster",
"trnIndicatorTextureID","trnButtonTextureID","trnProjectileSpriteID","trnActionTextureID","trnSpotAnimationSpriteID",
"indicatorTextureID","buttonTextureID","projectileSpriteID","actionTextureID","spotAnimationSpriteID",         
"chancePercent","lastsTurnNr","effectBehaviour","effectTargets","trnSystemSpecialEffectID","auraRadius",         
"isOneTimeSpell","castRangeModifier","cooldownTurnNr",                
"specCostNr","specCost","priority"
]

print("Reading App info")


if os.path.exists(fname_manif):
    f_app = open(fname_app, 'w')
    file1 = open(fname_manif, 'r')
    app_lines = file1.readlines()
    for app_line in app_lines : 
        if "android:versionCode=" in app_line:
            app_ver=app_line.replace("android:versionCode=", '')
            app_ver=app_ver.replace("\"", '')
            app_ver=app_ver.replace(" ", '')
        if "package=" in app_line:
            if "com.zts.ageofmodernwars" in app_line:
                app_prefix = "AOMW"
            elif "com.zts.ageofstrategy" in app_line:
                app_prefix = "AOS"  
            elif "com.zts.ageoffantasy" in app_line:
                app_prefix = "AOF"     
            elif "com.zts.ageofgalaxy" in app_line:
                app_prefix = "AOG"         
            elif "com.zts.ageofworldwars" in app_line:
                app_prefix = "AOW"   
            elif "com.zts.ageofalder" in app_line:
                app_prefix = "AOA"    
            else:    
                app_prefix = "UNKNOWN_PREFIX" 
    f_app.write(app_prefix + ":" + app_ver)   
    print("Reading App info:" + app_prefix + ":" + app_ver)
else:
    print("ERROR " + fname_manif + " not exists")
    exit()

print("Effects start")


collected_errors = ""
collected_errors_of_duplicated_effect_TAGs=""
used_effect_names=","
used_effect_ids=","
used_effect_id_max=0

onlyfiles = [f for f in listdir(path_work) if isfile(join(path_work, f)) and f.endswith(".json")]
f_workfile = open(fname_output, 'w')
cnt=0
sum=len(onlyfiles)
for filename in onlyfiles :    
    with open(path_work+filename) as f_dupl:
      file_as_text = f_dupl.read()
      for never_duplicate_this in never_duplicate_in_effect_json:
        if file_as_text.count('"' + never_duplicate_this + '"') > 1:
          collected_errors_of_duplicated_effect_TAGs = collected_errors_of_duplicated_effect_TAGs + "!! Duplicate EFFECT TAG:" + never_duplicate_this + " in:" + filename + "\n"        
    with open(path_work+filename) as f:
      cnt=cnt+1
      print(str(cnt)+"/"+str(sum)+ " effect processing:" + filename)
      data = json.load(f)
      effect_id=str(data['effectDefID'])
      effect_name_string=data['effectNameString']
      if 'effectDefIDRelated' in data and data['effectDefIDRelated'] is not None and data['effectDefIDRelated'] != 0:
        collected_errors = collected_errors + "ERROR effectDefIDRelated must not be used!:" + effect_name_string + "\n"
      if ","+effect_name_string+"," in used_effect_names:
        collected_errors = collected_errors + "duplicate effect name:" + effect_name_string + "\n"
      else:
        used_effect_names=used_effect_names+effect_name_string+","      
      if ","+effect_id+"," in used_effect_ids:
        collected_errors = collected_errors + "duplicate effect id:" + effect_id + "\n"
      else:
        used_effect_ids=used_effect_ids+effect_id+","        
      if used_effect_id_max < int(effect_id):
        used_effect_id_max = int(effect_id)
      f_workfile.write(effect_id + "," + effect_name_string + "," + filename + ";" + "\n")
   
print("\n\n")   
print(fname_output + " written\n")



print("Cosmetic pack checks, caching all filenames\n\n")


skin_filenames=","
skin_filenames_n_sizes=","
for root, dirs, files in os.walk(path_skin_packs):
    #print("DIR:" + root)
    if path_skin_packs != root:
        for f in files:
            #print(f)
            if ".meta" not in f:
                skin_filenames=skin_filenames + f + ","     
                filepath = os.path.join(root, f)
                if "OVERLAPPERS" not in filepath:
                    skin_filenames_n_sizes=skin_filenames_n_sizes + f + get_num_pixels_string(filepath) + ","


#print(skin_filenames_n_sizes)


print("Units start")



onlyfiles = [f for f in listdir(path_units) if isfile(join(path_units, f)) and f.endswith(".json")]


f_unit_id_filename_rel = open(fname_unit_id_filename_rel, 'w')
f_unit_categories = open(fname_unit_categories, 'w')
f_unit_builders = open(fname_unit_builders, 'w')
f_unit_builders.write("{\"list\":[" + "\n")


used_ids=","
used_id_max=0
used_unit_type_names=","
collected_non_jsoned=","
collected_errors_of_duplicatedTAGs=""
cnt=0
sum=len(onlyfiles)
known_non_jsoneds=",EFFECT_INSTANT_SWING_AROUND_EFFECT,EFFECT_ENCHANT_VANISHING,EFFECT_FIRE_ARROWS,EFFECT_FIRE_ARROWS_INSTANT,EFFECT_FIRE_ARROWS_ON_EVERYONE,EFFECT_ENCHANT_VANISHING_SILENT,EFFECT_ENCHANT_POISONED_WEAPON,EFFECT_TRAMPLE,EFFECT_ENCHANT_FIRE_WEAPON,EFFECT_ENCHANT_LIGHTNING_WEAPON,EFFECT_INSTANT_THUNDER_STRIKE,EFFECT_INSTANT_FIREBALL_UNDEAD,EFFECT_INSTANT_FIREBALL_EFFECT,EFFECT_INSTANT_THUNDER_STORM,EFFECT_ENCHANTMENT_CURSED,EFFECT_INSTANT_DRAGON_FIRE,EFFECT_INSTANT_DRAGON_BREATH,EFFECT_INSTANT_BANSHEE_SCREAM,EFFECT_ENCHANT_FEAR,EFFECT_IMMEDIATE_CONVERSION,EFFECT_INSTANT_SACRI_HP_DAMAGE,EFFECT_SLOWING,EFFECT_SLOWING_1,EFFECT_INSTANT_TROLL_ROT,EFFECT_DISARMOR,EFFECT_INSTANT_PAIN_DAMAGER,EFFECT_INSTANT_CASTER_AND_TARGET_DIES,EFFECT_INSTANT_SUMMON_SKELETON,EFFECT_ANIMATE_DEAD,EFFECT_ANIMATE_DEAD_CLOSE,EFFECT_INSTANT_INCREMENT_VANISHING,EFFECT_INSTANT_MAGIC_ARROW,EFFECT_AURA_LIFELINK,EFFECT_ENCHANT_VISION,EFFECT_AURA_VISION_ULIMITED,EFFECT_VISION,EFFECT_ENCHANT_STRENGTHEN,EFFECT_ENCHANT_STRENGTHEN_MYSELF,EFFECT_INSTANT_TRAMPLE,EFFECT_INSTANT_HEAL_3,EFFECT_INSTANT_EAT_CORPSE_TO_HEAL,EFFECT_STRENGTH_1ATTACK,EFFECT_STRENGTH_2ATTACK,EFFECT_STRENGTH_3ATTACK,EFFECT_AURA_STRENGTH_1ATTACK_ULIMITED,EFFECT_AURA_STRENGTH_2ATTACK_ULIMITED,EFFECT_AURA_STRENGTH_3ATTACK_ULIMITED,EFFECT_CAST_AURA_STRENGTH_1ATTACK,EFFECT_AURA_STRENGTH_1ATTACK,EFFECT_CAST_FIRE_WEAPON,EFFECT_CAST_LIGHTNING_WEAPON,EFFECT_ENCHANT_FORESTWALK,"
for filename in onlyfiles :
    never_duplicate_in_unit_json
    with open(path_units+filename) as f_dupl:
      file_as_text = f_dupl.read()
      for never_duplicate_this in never_duplicate_in_unit_json:
        if file_as_text.count('"' + never_duplicate_this + '"') > 1:
          collected_errors_of_duplicatedTAGs = collected_errors_of_duplicatedTAGs + "!! Duplicate UNIT TAG:" + never_duplicate_this + " in:" + filename + "\n"        
    with open(path_units+filename) as f:
      cnt=cnt+1
      print(str(cnt)+"/"+str(sum)+ " unit processing:" + filename)
      data = json.load(f)
      specs=""
      races=""
      is_fact="N"
      is_tech="N"
      default_image=""
      default_image_imgcolumns="1"
      unit_cost="0"
      unit_typeid=str(data['unitType'])
      unit_typename=data['unitTypeName']
      if 'unitStatSheet' in data: 
        if 'unit' in data['unitStatSheet']:
          if 'trnRaces' in data['unitStatSheet']['unit']:
            if data['unitStatSheet']['unit']['trnRaces'] is not None:
              races=str(data['unitStatSheet']['unit']['trnRaces']).replace("'", "").replace(" ", "").replace("[", "").replace("]", "")
          if 'trnSpecUnitActions' in data['unitStatSheet']['unit']:
            if data['unitStatSheet']['unit']['trnSpecUnitActions'] is not None:
              specs=str(data['unitStatSheet']['unit']['trnSpecUnitActions']).replace("'", "").replace(" ", "").replace("[", "").replace("]", "")
          if 'trnWeaponEffects' in data['unitStatSheet']['unit']:
            we=data['unitStatSheet']['unit']['trnWeaponEffects']
            if we is not None:
              for weaponeffect in we:                
                  if 'effOptions' in weaponeffect:                 
                    if weaponeffect['effOptions'] is not None:
                      effects=str(weaponeffect['effOptions']).replace("'", "").replace(" ", "").replace("[", "").replace("]", "")
                      effectssplit=effects.split(sep=",")                  
                      if ('effDefault' not in weaponeffect):
                        collected_errors = collected_errors + ".........................MISSING trnWeaponEffects/effDefault in:" + unit_typename + "\n"
                      else:
                        if (weaponeffect['effDefault'] is None): 
                          collected_errors = collected_errors + ".........................EMPTY trnWeaponEffects/effDefault in:" + unit_typename + "\n"
                      if ('effDefault' in weaponeffect) and (weaponeffect['effDefault'] is not None):
                        effect_default_option=str(weaponeffect['effDefault']).replace("'", "").replace(" ", "").replace("[", "").replace("]", "")
                        effectssplit.append(effect_default_option)
                      for effectitem in effectssplit:
                        if ","+effectitem+"," not in used_effect_names:
                          if ","+effectitem+"," in known_non_jsoneds:
                            if ","+effectitem+"," not in collected_non_jsoned:
                              collected_non_jsoned = collected_non_jsoned  + effectitem + ","
                          else:
                            collected_errors = collected_errors + "MISSING effect definition:" + effectitem + " in:" + unit_typename + "\n"
          if 'isTechnology' in data['unitStatSheet']['unit']:  
            if data['unitStatSheet']['unit']['isTechnology']==True:
              is_tech="Y"
          if 'isFactory' in data['unitStatSheet']['unit']:  
            if data['unitStatSheet']['unit']['isFactory']==True:
              is_fact="Y"
          if 'costTurn' in data['unitStatSheet']['unit']:      
            unit_cost=str(data['unitStatSheet']['unit']['costTurn'])
      if 'uiDefinition' in data:
        if 'visuals' in data['uiDefinition']:
          if len(data['uiDefinition']['visuals'])>0:
            if 'imgName' in data['uiDefinition']['visuals'][0]:
              default_image = data['uiDefinition']['visuals'][0]['imgName']
              if data['uiDefinition']['visuals'][0]['type'] != "DEFAULT":
                collected_errors = collected_errors + "ERROR: 0th visual is not default:" + filename + "\n"
              image_only_file_name=my_os_sep+default_image             
              image_only_file_name=image_only_file_name[image_only_file_name.rfind(my_os_sep)+1:]              
              if ","+image_only_file_name+"," in skin_filenames:   
                skin_filenames = skin_filenames.replace(image_only_file_name+",", '')   
                filewithsize = image_only_file_name + get_num_pixels_string(path_gfx + default_image)
                if (","+filewithsize+",") in skin_filenames_n_sizes:
                    skin_filenames_n_sizes = skin_filenames_n_sizes.replace(filewithsize+",", '')
              default_image_imgcolumns = str(data['uiDefinition']['visuals'][0]['imgColumns'])            
          if len(data['uiDefinition']['visuals'])>1:
            if 'imgName' in data['uiDefinition']['visuals'][1]:
              default_image1 = data['uiDefinition']['visuals'][1]['imgName']
              image_only_file_name=my_os_sep+default_image1             
              image_only_file_name=image_only_file_name[image_only_file_name.rfind(my_os_sep)+1:]              
              if ","+image_only_file_name+"," in skin_filenames:   
                skin_filenames = skin_filenames.replace(image_only_file_name+",", '')       
                filewithsize = image_only_file_name + get_num_pixels_string(path_gfx + default_image1)
                if (","+filewithsize+",") in skin_filenames_n_sizes:
                    skin_filenames_n_sizes = skin_filenames_n_sizes.replace(filewithsize+",", '')                
      if ","+unit_typeid+"," in used_ids:
        collected_errors = collected_errors + "duplicate id:" + unit_typeid + "\n"
      else:
        used_ids=used_ids+unit_typeid+","
      if used_id_max < int(unit_typeid):
        used_id_max = int(unit_typeid)
      if ","+unit_typename+"," in used_unit_type_names:        
        collected_errors = collected_errors + "duplicate type name:" + unit_typename + "\n"
      else:
        used_unit_type_names=used_unit_type_names+unit_typename+","        
      f_unit_id_filename_rel.write( unit_typeid + "|" +  unit_typename  + "|" + filename  + "|" + unit_cost + "|"  + default_image + "|" + default_image_imgcolumns + "|"  + specs + "|" + races +  "|" + is_tech + "|" + is_fact + ";" + "\n")
      if 'unitStatSheet' in data: 
        if 'unit' in data['unitStatSheet']: 
          if 'trnCategories' in data['unitStatSheet']['unit']: 
            if data['unitStatSheet']['unit']['trnCategories'] is not None: 
              if str(data['unitStatSheet']['unit']['trnCategories']) != '[]': 
                f_unit_categories.write(data['unitTypeName'] + ":" + str(data['unitStatSheet']['unit']['trnCategories']) + ";" + "\n")
          if 'trnBuilders' in data['unitStatSheet']['unit']: 
            if data['unitStatSheet']['unit']['trnBuilders'] is not None: 
              if str(data['unitStatSheet']['unit']['trnBuilders']) != '[]': 
                if str(data['unitStatSheet']['unit']['trnBuilders']) != '{}': 
                  f_unit_builders.write("{\"unitIdString\":" + "\""  + data['unitTypeName'] + "\"," + "\"trnBuilders\":" + str(data['unitStatSheet']['unit']['trnBuilders']).replace("'", "\"") + "}")
                  if filename == onlyfiles[-1]:
                    f_unit_builders.write("\n")
                  else:
                    f_unit_builders.write("," + "\n")
                 
f_unit_builders.write("]}" + "\n")

if (len(skin_filenames) > 3):
    collected_errors = collected_errors + "MISSING SKINPACK files!:" + skin_filenames + "\n"

if (len(skin_filenames_n_sizes) > 3):
    collected_errors = collected_errors + "WRONG SKINPACK file sizes!:" + skin_filenames_n_sizes + "\n"

collected_errors = collected_errors + collected_errors_of_duplicated_effect_TAGs + collected_errors_of_duplicatedTAGs;


print("Directory tree start")

f_unit_directories = open(fname_unit_directories, 'w')


startpath = "."
for root, dirs, files in os.walk(startpath):
    #level = root.replace(startpath, '').count(os.sep)
    #indent = ' ' * 4 * (level)
    #print('{}{}/'.format(indent, os.path.basename(root)))
    #subindent = ' ' * 4 * (level + 1)
    #print("DIR:" + root)
    if "cosm_units" in root or "wallpaper" in root or "cosmetics" in root:
        f_unit_directories.write("DIRBREAK:" + "\n")
        f_unit_directories.write("DIR:" + root+ "\n")
        for d in dirs:
            f_unit_directories.write(d + "\n")
        for f in files:
            #print('{}{}'.format(subindent, f))
            #print(f)
            if ".meta" not in f:
                f_unit_directories.write(f + "\n")


print("Shopitems start")

used_shopids=","
used_shopid_max=0
with open(fname_shopitems) as f:
    data = json.load(f)
    we=data['shopConfigItems']
    for shopitem in we:
        currid=str(shopitem['shopItemId'])
        if used_shopid_max < int(currid):
            used_shopid_max = int(currid)
        if ","+currid+"," not in used_shopids:
            used_shopids=used_shopids+currid+",";
        else:
            collected_errors = collected_errors + "DUPLICATED SHOP_ID:" + currid + "\n"


print("\n\n")      
print(fname_unit_directories + " written\n")


print(fname_unit_id_filename_rel + " written\n")
print(fname_unit_categories + " written\n")
print(fname_unit_builders + " written\n")




print("Last Shop id:" + str(used_shopid_max))
print("Last effect id:" + str(used_effect_id_max))
print("Last unit id:" + str(used_id_max) + "\n(warning! in many alternatives the biggest ID-s  are spec ids - so not the real last one among units...)\n")


if collected_non_jsoned!=",":
  print("Error " + str(collected_non_jsoned.count(",") - 1) + " NON JSONED EFFECTS:\n"   + collected_non_jsoned + "\n")  

print("Errors:\n" + collected_errors)
input("Press Enter to continue...")








(on PC latest python requires this as it has image pixel size checking from now:

Code: Select all

pip install Pillow
)
Stratego (dev)
Site Admin
Posts: 15752
Joined: Fri Apr 25, 2014 9:28 pm

Re: Changes you need to follow as Modder

Post by Stratego (dev) »

updated the latest code, with excluding hte OVERLAPPERS
Stratego (dev)
Site Admin
Posts: 15752
Joined: Fri Apr 25, 2014 9:28 pm

Re: Changes you need to follow as Modder

Post by Stratego (dev) »

in the assets directory there is a new python "gen_change_log.py"
you can run that by to get a help on making changelog.

it will generate lines about new units to be in versin log (last 50 units)

it is based on the texting of the units so the texts should be ready.

You as a modder should run th script like this:

Code: Select all

gen_change_log.py MODDER
this way the "others/strings.xml" will be used to get the textings (anyway you need to fill that file with the new texts so no problem)

(remark: without parameter it uses the in-code strings file so that is not useful for you as a modder as that will show the older units)
Stratego (dev)
Site Admin
Posts: 15752
Joined: Fri Apr 25, 2014 9:28 pm

Re: Changes you need to follow as Modder

Post by Stratego (dev) »

new unit help template file tmpl_propsheet.html pleae use this in all alternative
(removing + sign from tech display -> code will place "+" signs)

Code: Select all


<!DOCTYPE html>

<head>
<title>Stats</title>

<style>
.icon{width:32px}
.icon_small{height:14px}
.img_frame { margin:1px;float:left; width: 32px; height: 64px; display:table; overflow: hidden; }
.img_holder { vertical-align: bottom;display:table-cell }
.img_div_small {margin:auto; max-width: 32px;max-height:100%; width: auto !important; height: auto\9; overflow: hidden; -ms-interpolation-mode:bicubic}
.img_proper_small{}
.img_div_list {position:relative; width: 32px;height:64px; overflow: hidden;}
.img_proper_list{ position:absolute; bottom:0; left:0; max-height:100%;}
.img_div_large{margin:auto; position:relative; width: 64px;height:64px; overflow: hidden;}
.img_proper_large {  position:absolute; bottom:0; left:0; max-height:100%;}
.img_builder_frame { margin:5px; float:left; width:32px; height:32px; overflow: hidden; }
.img_div_builder {position:relative;height:32px;width:32px}
.img_proper_builder{ max-height:32px;width:auto;position:absolute;bottom:0;left:0}
.texts {
    font-family: Helvetica, sans-serif;
}
.titles {
    font-weight: bold;
    text-align:center;
}
.titles_left {
    font-weight: bold;
    text-align:left;
}
.descriptions{
	text-align:justify;
	vertical-align:top;
}
.table_texts{
	text-align:center;
	word-wrap:normal;
}
.table_texts_left{
	text-align:left;
	word-wrap:normal;
}
.table_texts_topleft{
	text-align:left;
  vertical-align: top;
	word-wrap:normal;
}
.list_titles {
    font-weight: bold;
    text-align:left;
}
.list_elements{
    text-align:left;
	word-wrap:normal;
}
.name{
	word-wrap:normal;
}
.num_values_div{
	text-align:right;
	padding-right:5px;
	display:inline-block
}

.sheet_title_font{
	font-size: x-large;
	color: #000000;
}
.desc_font {
	font-size: small;
	color: #000000;
}
.param_titles_font {
	font-size: small;
	color: #990000;
}
.param_values_font {
	font-size: small;
	color: #0000CC;
}
.table_title_font{font-size: small;}
.table_headers_font{font-size: xx-small;}
.table_txt_font{font-size: xx-small;}
.table_values_font{font-size: x-small;}
.categories_color{color:#734d26;}
.effects_color{color:#005500;}
.dropdown_color{color:#858585;}
.dmg_bonus_color{color:#993d00;}
.spells_color{color:#665200;}
.production_color{color:#0e3c7b;}
.unlocks_units_color{color:#660066;}
.unlocks_effects_color{color:#5900b3;}
.possible_effect_color{color:#26734d;}
.effect_separator {border-top: 1px solid #739900}
.effect_small_separator {border-bottom: 1px dashed #739900}
.spell_separator {border-top: 1px solid #cc9900}
.fit {width:0%}
.full {width:100%}
.thinner_td {width:25%}
.wider_td {width:75%}
.borderless {border:0}
#main_table{border-spacing: 1px;}
#main_table>td{padding: 5px;}
.mild_spaced{border-spacing: 1px;}
.mild_spaced>td{padding: 3px;}
.tight_spaced{border-spacing: 0px;}
.tight_spaced>td{padding: 0px;}
.centered{margin: 0 auto;}
.halfsize{width:50%}
.quartersize{width:25%}
.threeforthssize{width:75%}
.categories_table {background-color: rgba(153, 102, 0, 0.2);border:solid #663300}
.active_effects_table {background-color: rgba(153, 204, 0, 0.2);border:solid #739900}
.stats_table {background-color: rgba(235, 204, 154, 0.3);border:solid #AA0000}
.spell_details_table {background-color: rgba(255, 204, 102, 0.4);border:solid #cc9900}
.spell_damage_bonuses_table{background-color: rgba(255, 204, 102, 0.4);border:none #cc9900}
.production_table {background-color: rgba(116, 155, 207, 0.4);border:solid #225dac}
.damage_bonuses_table{background-color: rgba(255, 170, 119, 0.2);border:solid #ff6600;;}
.effect_details_table{background-color: rgba(204, 255, 153, 0.1);border:solid #009900}
.possible_effects_table{background-color: rgba(102, 255, 153, 0.2);border:solid #00cc66}
.unlocks_units_table{background-color: rgba(153, 0, 204, 0.2);border:solid #9900cc}
.unlocks_effects_table{background-color: rgba(102, 0, 204, 0.2);border:solid #5900b3}

.top_spacings {margin-bottom:0cm; margin-bottom:.0001pt;line-height:16.5pt;vertical-align:baseline;}
.frame_left {float:left; margin:5px; }
.collapsible_row{ display: none; }
.selectable{ }
.right_aligned_title{ text-align:right; font-weight: bold; font-size: small; color:black; }
.center_aligned_title{text-align:center; font-weight: bold; font-size: small; color:black;}
.hint_row{pointer-events:none; z-index:1000; border-radius:5px; background-color:rgba(255, 255, 255, 0.8);}
.floating_row{width:80%; height:32px; position:absolute; line-height:32px;}
.unit_image{}
.crop_img{}
.crop_32{}
.crop_64{}
.crop_96{}
</style>
<script type="text/javascript">
function toggleMe(a){
  var e = document.getElementById(a);
  if(e){
    if(e.style.display == "none"){
      e.style.display="table-row";
    }else{
      e.style.display="none";
    }
  }
  var targetElements = document.getElementsByClassName(a);
  for(var i = 0; i < targetElements.length; i++)
  {
    var e2 = targetElements.item(i);
    if(e2.style.display == "none"){
      e2.style.display="table-row";
    }else{
      e2.style.display="none";
    }
  }
}

function initiate(){
	initCollapsible();
	if (areImagesToCropReady()){
		var scale = document.getElementById("imgScale").value;
		animationCrop(scale);
		scaleAllImagesInLists(scale);
    }
    else {
		setTimeout(
            function() {
                initiate2();
            }
        , 100);
    }
}

function areImagesToCropReady(){
	var images_to_crop = document.getElementsByClassName("crop_img");
	var ready = true;
	for(var i = 0;
        i < images_to_crop.length;
        i++)	{
		var img = images_to_crop.item(i);
		if(img.complete == false || img.naturalHeight == 0){
			ready = false;
        }
    }
	return ready;
}

function initiate2(){
	if (areImagesToCropReady()){
		var scale = document.getElementById("imgScale").value;
		animationCrop(scale);
		scaleAllImagesInLists(scale);
    }
    else {
		setTimeout(
            function() {
                initiate2();
            }
        , 100);
    }
}
function animationCrop(scale){
    var images_to_crop = document.getElementsByClassName("crop_img");
	for(var i = 0;
        i < images_to_crop.length;
        i++)	{
		var img = images_to_crop.item(i);
        var height = img.height;
        img.style.background= "url('"+img.src+"') 0 0";
		if (scale != 0 && scale != 1 && !img.classList.contains("dont_scale")){
			img.style.backgroundSize=img.width*scale + "px " + height*scale+ "px";
		}
        img.src="gfx/templates/damage_vs_armor_none.png";
        img.width=img.title;
        img.height=height;
    }
}
function scaleAllImagesInLists(scale){
	if (scale != 0 && scale != 1){
		var images = document.getElementsByClassName("unit_image");
		for(var i = 0;
			i < images.length;
			i++)	{
			var img = images.item(i);
			if ( !img.classList.contains("dont_scale")){
				var height = img.height*scale;
				var width = img.width*scale;
				img.width=width;
				img.height=height;
			}
		}
	}
}
function initCollapsible(){
  var collapsibles = document.getElementsByClassName("collapsible_row");
  for(var i = 0; i < collapsibles.length; i++)
  {
    collapsibles.item(i).style.display="none";
  }
}
function unselect(){
  var ongoing = document.getElementById("unselectOngoing");
  ongoing.value = parseInt(ongoing.value)+1;
  var collapsibles = document.getElementsByClassName("hint_row");
  for(var i = 0; i < collapsibles.length; i++)
  {
    collapsibles.item(i).style.display="none";
  }
  var selectables = document.getElementsByClassName("selectable");
  for(var i = 0; i < selectables.length; i++)
  {
    selectables.item(i).style.filter="brightness(100%)";
  }
  var to_remove = document.getElementById("to_remove");
  if (to_remove){
    to_remove.remove();
  }
}
function setUnselect(){
    var ongoing = document.getElementById("unselectOngoing");
    var ongoingValue = parseInt(ongoing.value)+1;
    ongoing.value = ongoingValue;
    setTimeout(function() { launchUnselect(ongoingValue); }, 5000);
}
function launchUnselect(conditionValue){
    var ongoing = document.getElementById("unselectOngoing");
    if (parseInt(ongoing.value) == conditionValue){
      unselect();
    }
}
function showMyName(myclass, imgclass, mynamedisplayrowid){
  unselect();
  if (imgclass=="ID"){
    var me = document.getElementById(myclass);
  } else {
    var idclasses = document.getElementsByClassName(myclass + " " + imgclass);
    if(idclasses.length > 0){
      var me = idclasses.item(0);
    }
  }
  if (me) {
    me.style.filter="brightness(200%)";
  }
  var mynamedisplayrow = document.getElementById(mynamedisplayrowid);
  if(mynamedisplayrow){
    mynamedisplayrow.firstElementChild.innerHTML = me.alt;
    mynamedisplayrow.style.display="table-row";
    setUnselect();
  }
}
function showMyNameOnTable(myclass, imgclass, tableid){
  unselect();
  var idclasses = document.getElementsByClassName(myclass + " " + imgclass);
  if(idclasses.length > 0){
    var me = idclasses.item(0);
    me.style.filter="brightness(200%)";
    var node = document.createElement("DIV");
    node.id = "to_remove";
    node.className = "hint_row center_aligned_title floating_row";
    var text = document.createTextNode(me.alt);
    node.appendChild(text);
    document.getElementById(tableid).parentElement.appendChild(node);
    node.style.left = document.getElementById(tableid).getBoundingClientRect().left+document.getElementById(tableid).getBoundingClientRect().width*0.1+"px";
    node.style.top = window.scrollY + me.getBoundingClientRect().top-32 +"px" ;
    setUnselect();
  }
}
</script>
</head>

<body onload="initiate()">
<input type="hidden" id="unselectOngoing" value="0">
<input type="hidden" id="imgScale" value="<tmpl_var up_scale>">



<p class="top_spacings" >&nbsp;</p>
<table class="full borderless" id="main_table">

  <tr>
    <td colspan="2" class="texts descriptions desc_font">
      <span class="texts descriptions sheet_title_font">
        <tmpl_var name="up_name">
      </span>
    </td>
  </tr>


  <tmpl_if up_effects>
  	<tr>
  	<td colspan="2" >
      <table  class="borderless active_effects_table">
        <tr onClick="toggleMe('id_effects_table')">
          <td  class="thinner_td texts titles table_title_font dropdown_color"><img src="gfx/templates/expand_triangle.png" alt="&darr;"/></td>
          <td  class="wider_td texts titles table_title_font effects_color">Active Effects</td>
        </tr>
        <tr class='id_effects_table' onClick="toggleMe('id_effects_table')" >
          <td colspan="2" class="texts table_texts table_title_font effects_color"><tmpl_var up_effects></td>
        </tr>
        <tr class='collapsible_row id_effects_table' onClick="toggleMe('id_effects_table')">
          <td class="thinner_td texts titles_left table_headers_font effects_color">Name</td>
          <td class="wider_td texts titles_left table_headers_font effects_color">Description</td>
        </tr>
        <tmpl_loop up_effect_details>
         <tr class='collapsible_row id_effects_table' onClick="toggleMe('id_effects_table')">
		      <td class="thinner_td texts table_texts_topleft table_txt_font effects_color effect_separator"><tmpl_var up_effect_name></td>
          <td class="wider_td texts table_texts_left table_txt_font effects_color effect_separator">
          <p style="background-color:powderblue;"><tmpl_var up_effect_desc></p>


            <tmpl_loop up_spells_details>
              <div class="effect_small_separator" >
              <u><strong><tmpl_var name="up_spell_name">:</strong></u>

              <tmpl_var name="up_spell_desc">
              <tmpl_if up_spell_adddesc>
                 <br>
                 <tmpl_var name="up_spell_adddesc">
              <tmpl_else>
                <br>
              </tmpl_if>
              <tmpl_if up_spell_chance>
                <strong>Chance:</strong><tmpl_var name="up_spell_chance"><br>
              </tmpl_if>
              <i><tmpl_var name="up_spell_behaviour"> </i>       <i> <tmpl_var name="up_spell_targets"> </i> <i><tmpl_var name="up_spell_specs">   </i>


              <br>
              <tmpl_if up_spell_indicator>
                <img class="icon_small"  alt=" " src="<tmpl_var up_spell_indicator>"  />
              </tmpl_if>

              <tmpl_loop  up_spells_loop>
                <tmpl_if up_spell_action_id>
                  <tmpl_if up_spell_action_name>
                    <strong><tmpl_var name="up_spell_action_title"></strong> <tmpl_var name="up_spell_action_name"> <tmpl_var name="up_spell_action_desc">

                    <tmpl_if up_bonus>

                            <table class="mild_spaced full spell_damage_bonuses_table">

                              <tr>
                                 <td class="texts titles table_txt_font spells_color">Bonus</td>
                                 <td class="texts titles table_txt_font spells_color"> Damage</td>
                                 <td class="texts list_titles table_txt_font spells_color">Against</td>
                              </tr>
                              <tmpl_loop  up_bonus>
                                 <tr>
                                   <td class="texts table_texts table_txt_font spells_color">
                                      <div class="num_values_div"><tmpl_var name="up_bonus_percentage"></div>
                                   </td>
                                   <td class="texts table_texts table_txt_font spells_color" >
                                      <div class="num_values_div"><tmpl_var name="up_bonus_value"></div>
                                   </td>
                                   <td class="texts list_elements table_txt_font spells_color"><tmpl_var name="up_bonus_against"></td>
                                 </tr>
                              </tmpl_loop>
                            </table>
                    </tmpl_if>
                  </tmpl_if>
                </tmpl_if>
              </tmpl_loop>
			  </div>
            </tmpl_loop>

          </td>
        </tr>
        </tmpl_loop>

      </table>


    </td>
    </tr>
  </tmpl_if>


  <tr>
    <td	class="halfsize texts descriptions desc_font">
	  <p>
	    <tmpl_if up_descr>
	      <tmpl_var up_descr>
      </tmpl_if>
      <tmpl_if up_spec_actions>
        <tmpl_if if_tech>
          <br>Adds:
        </tmpl_if>
        <i><tmpl_var up_spec_actions></i>
      </tmpl_if>
	  </p>


  <tmpl_if up_categories>

      <table  class="borderless categories_table">
        <tr>
          <td class="full texts titles table_title_font categories_color">Categories</td>
        </tr>
        <tr>
          <td class="texts table_texts table_title_font categories_color"><tmpl_var up_categories></td>
        </tr>
      </table>

  </tmpl_if>




	</td>
    <td class="halfsize">
      <table  class="full tight_spaced stats_table">
        <tr>
          <td colspan="2" class="texts titles param_titles_font"><tmpl_var name="up_name">	<tmpl_if up_player_name><br>(<tmpl_var name="up_player_name">)</tmpl_if>	  </td>
          </tr>
        <tr>
          <td colspan="2" class="texts titles param_titles_font">&nbsp;

            <tmpl_if up_img>
				<img class="<tmpl_if up_img_crop_width>crop_img</tmpl_if> unit_image dont_scale" alt=" " title="<tmpl_var  up_img_crop_width>"
 src="<tmpl_var up_img>"/>
			<tmpl_else>
				<img class="<tmpl_if up_img_crop_width>crop_img</tmpl_if> unit_image dont_scale" alt=" " title="<tmpl_var  up_img_crop_width>"
 src="<tmpl_var up_img_double>"/>
			</tmpl_if>


		  </td>
        </tr>

     <!--
     -------------------------------------------- START OF ATTRIBUTES --------------------------------------------------
    -->

			  <tr>
				<td class="threeforthssize texts titles param_titles_font">Cost</td>
				<td class="quartersize texts titles param_values_font"><tmpl_var name="up_cost"></td>
			  </tr>

      <tmpl_if if_randomprod>
     		  <tr>
				 <td class="texts titles param_titles_font"> </td>
				 <td class="texts titles param_values_font"> </td>
			  </tr>
			  <tr>
				 <td colspan="2" class="texts titles param_values_font">(Can spawn alternative unit)</td>

			  </tr>
			  <tr>
				 <td class="texts titles param_titles_font"> </td>
				 <td class="texts titles param_values_font"> </td>
			  </tr>
       </tmpl_if>


    <tmpl_if if_show_stats>
      <tmpl_if if_tech>

				<tmpl_if up_hp_max>
				  <tr>
					<td class="texts titles param_titles_font">Max Hp</td>
					<td class="texts titles param_values_font"><tmpl_var name="up_hp_max"></td>
				  </tr>
				</tmpl_if>
				<tmpl_if up_hp_max_percent>
				  <tr>
					<td class="texts titles param_titles_font">Max Hp</td>
					<td class="texts titles param_values_font"><tmpl_var name="up_hp_max_percent">%</td>
				  </tr>
				</tmpl_if>
				<tmpl_if up_power>
				  <tr>
					<td class="texts titles param_titles_font">Attack power</td>
					<td class="texts titles param_values_font"><tmpl_var name="up_power"></td>
				  </tr>
				</tmpl_if>
				<tmpl_if up_rangeAttack>
				  <tr>
					<td class="texts titles param_titles_font">Range</td>
					<td class="texts titles param_values_font"><tmpl_var name="up_rangeAttack"></td>
				  </tr>
				</tmpl_if>
				<tmpl_if up_rangeAttackMin>
				  <tr>
					<td class="texts titles param_titles_font">Minimum range</td>
					<td class="texts titles param_values_font"><tmpl_var name="up_rangeAttackMin"></td>
				  </tr>
				</tmpl_if>

				<tmpl_if up_armorNormal>
				  <tr>
					<td class="texts titles param_titles_font"><tmpl_var name="lb_armorNormal"></td>
					<td class="texts titles param_values_font"><tmpl_var name="up_armorNormal"></td>
				  </tr>
				</tmpl_if>
				<tmpl_if up_armorPierce>
				  <tr>
					<td class="texts titles param_titles_font"><tmpl_var name="lb_armorPierce"></td>
					<td class="texts titles param_values_font"><tmpl_var name="up_armorPierce"></td>
				  </tr>
				</tmpl_if>
				<tmpl_if up_moveRange>
				  <tr>
					<td class="texts titles param_titles_font">Speed</td>
					<td class="texts titles param_values_font"><tmpl_var name="up_moveRange"></td>
				  </tr>
				</tmpl_if>
				<tmpl_if up_sight>
				  <tr>
					<td class="texts titles param_titles_font">Sight</td>
					<td class="texts titles param_values_font"><tmpl_var name="up_sight"></td>
				  </tr>
				</tmpl_if>
				<tmpl_if up_attack_per_turn_max>
				  <tr>
					<td class="texts titles param_titles_font">Action</td>
					<td class="texts titles param_values_font"><tmpl_var name="up_attack_per_turn_max"></td>
				  </tr>
				</tmpl_if>
				<tmpl_if up_carryCapacity>
				  <tr>
					<td class="texts titles param_titles_font">Carry capacity </td>
					<td class="texts titles param_values_font"><tmpl_var name="up_carryCapacity"></td>
				  </tr>
				</tmpl_if>
				<tmpl_if up_powerRange>
				  <tr>
					<td class="texts titles param_titles_font">Power range </td>
					<td class="texts titles param_values_font"><tmpl_var name="up_powerRange"></td>
				  </tr>
				</tmpl_if>
				<tmpl_if up_mendRate>
				  <tr>
					<td class="texts titles param_titles_font">Mend rate </td>
					<td class="texts titles param_values_font"><tmpl_var name="up_mendRate"></td>
				  </tr>
				</tmpl_if>
				<tmpl_if up_healRate>
				  <tr>
					<td class="texts titles param_titles_font">Heal rate </td>
					<td class="texts titles param_values_font"><tmpl_var name="up_healRate"></td>
				  </tr>
					</tmpl_if>
				<tmpl_if up_convertRange>
				  <tr>
					<td class="texts titles param_titles_font">Ability range </td>
					<td class="texts titles param_values_font"><tmpl_var name="up_convertRange"></td>
				  </tr>
				</tmpl_if>
				<tmpl_if up_convertPossibility_int>
				  <tr>
					<td class="texts titles param_titles_font">Ability possibility </td>
					<td class="texts titles param_values_font"><tmpl_var name="up_convertPossibility_int">%</td>
				  </tr>
				</tmpl_if>
				<tmpl_if up_abilityPower>
					<tr>
					  <td class="texts titles param_titles_font">Ability power </td>
					  <td class="texts titles param_values_font"><tmpl_var name="up_abilityPower"></td>
					</tr>
					  </tmpl_if>
				<tmpl_if up_dodge_ranged>
				  <tr>
					<td class="texts titles param_titles_font">Dodge arrows</td>
					<td class="texts titles param_values_font"><tmpl_var name="up_dodge_ranged"></td>
				  </tr>
					</tmpl_if>
				<tmpl_if up_dodge_close>
				  <tr>
					<td class="texts titles param_titles_font">Dodge melee</td>
					<td class="texts titles param_values_font"><tmpl_var name="up_dodge_close"></td>
				  </tr>
					</tmpl_if>
				<tmpl_if up_dodge_counter>
				  <tr>
					<td class="texts titles param_titles_font">Dodge counters</td>
					<td class="texts titles param_values_font"><tmpl_var name="up_dodge_counter"></td>
				  </tr>
				</tmpl_if>
				<tmpl_if up_constr_bonus>
				  <tr>
					<td class="texts titles param_titles_font">Construct aff.</td>
					<td class="texts titles param_values_font"><tmpl_var name="up_constr_bonus"></td>
				  </tr>
				</tmpl_if>
				<tmpl_if up_mend_bonus>
				  <tr>
					<td class="texts titles param_titles_font">Mend aff.</td>
					<td class="texts titles param_values_font"><tmpl_var name="up_mend_bonus"></td>
				  </tr>
				</tmpl_if>
				<tmpl_if up_heal_bonus>
				  <tr>
					<td class="texts titles param_titles_font">Heal aff.</td>
					<td class="texts titles param_values_font"><tmpl_var name="up_heal_bonus">%</td>
				  </tr>
				</tmpl_if>
				<tmpl_if up_convertResistance_int>
				  <tr>
					<td class="texts titles param_titles_font">Mental Resistance </td>
					<td class="texts titles param_values_font"><tmpl_var name="up_convertResistance_int">%</td>
				  </tr>
				</tmpl_if>


      <tmpl_else>
     <!--
     so from here normal units
    -->
				<tr>
				  <td class="texts titles param_titles_font">Hp</td>
				  <td class="texts titles param_values_font"><tmpl_var name="up_hp"></td>
				</tr>
				<tr>
				  <td class="texts titles param_titles_font">Attack power</td>
				  <td class="texts titles param_values_font"><tmpl_var name="up_power"><tmpl_if up_base_attack_type>
					<img src="gfx/templates/damage_vs_armor_<tmpl_var up_base_attack_type>.png" alt="&spades;"/></tmpl_if>
				  </td>


				</tr>
				<tr>
				  <td class="texts titles param_titles_font">Range</td>
				  <td class="texts titles param_values_font"><tmpl_var name="up_rangeAttack"></td>
				</tr>
				<tmpl_if up_rangeAttackMin>
				  <tr>
					<td class="texts titles param_titles_font">Minimum range</td>
					<td class="texts titles param_values_font"><tmpl_var name="up_rangeAttackMin"></td>
				  </tr>
				</tmpl_if>
				<tmpl_if up_misschance>
				  <tr>
					<td class="texts titles param_titles_font"><tmpl_var name="lb_misschance"></td>
					<td class="texts titles param_values_font"><tmpl_var name="up_misschance"></td>
				  </tr>
				</tmpl_if>
				<tr>
				  <td class="texts titles param_titles_font"><tmpl_var name="lb_armorNormal"> ( vs <img src="gfx/templates/damage_vs_armor_default.png" alt="&spades;">)</td>
				  <td class="texts titles param_values_font"><tmpl_var name="up_armorNormal"></td>
				</tr>
				<tr>
				  <td class="texts titles param_titles_font"><tmpl_var name="lb_armorPierce"> ( vs <img src="gfx/templates/damage_vs_armor_second.png" alt="&spades;"/>)</td>
				  <td class="texts titles param_values_font"><tmpl_var name="up_armorPierce"></td>
				</tr>
				<tr onClick="toggleMe('terrain_id')">
				  <td class="texts titles param_titles_font"><img src="gfx/templates/expand_triangle.png" alt="&darr;"/> Speed</td>
				  <td class="texts titles param_values_font"><tmpl_var name="up_moveRange"></td>
				</tr>

				<tr class='collapsible_row terrain_id' onClick="toggleMe('terrain_id')" >
				  <td colspan="2" class="table_texts table_values_font dmg_bonus_color">
					<table class="mild_spaced full damage_bonuses_table">
					  <tmpl_loop up_terrain_loop>
					  <tr>
						<td class="texts table_texts table_values_font dmg_bonus_color">
						  <tmpl_var name="up_terr_name">
						</td>
						<td class="texts table_texts table_values_font dmg_bonus_color" >
						  <tmpl_var name="up_terr_value">
						</td>
						<td class="texts table_texts table_values_font dmg_bonus_color" >
						  (<tmpl_var name="up_terr_percent">)
						</td>
					  </tr>
					  </tmpl_loop>
					  </table>
				  </td>
				</tr>


				<tr>
				  <td class="texts titles param_titles_font">Sight</td>
				  <td class="texts titles param_values_font"><tmpl_var name="up_sight"></td>
				</tr>
				<tr>
				  <td class="texts titles param_titles_font">Action /turn </td>
				  <td class="texts titles param_values_font"><tmpl_var name="up_attack_per_turn"></td>
				</tr>

				<tmpl_if if_carrier>
				  <tr onClick="toggleMe('carry_id')">
					<td class="texts titles param_titles_font"><tmpl_if up_can_carry_text><img src="gfx/templates/expand_triangle.png" alt="&darr;"/> </tmpl_if>Carry capacity </td>
					<td class="texts titles param_values_font"><tmpl_var name="up_carryCapacity"></td>
				  </tr>
				  <tmpl_if up_can_carry_text>
					<tr class='collapsible_row' id="carry_id" onClick="toggleMe('carry_id')" >
					  <td colspan="2" class="table_texts table_values_font spells_color">
						<table class="mild_spaced full spell_details_table">
						  <tr>
							<td class="full texts titles table_title_font possible_effect_color">Can carry: </td>
						  </tr>
						  <tr>
							<td class="full texts table_texts table_title_font spells_color"><tmpl_var name="up_can_carry_text"></td>
						  </tr>
						</table>
					  </td>
					</tr>
				  </tmpl_if>
				</tmpl_if>
				<tmpl_if if_areadamage>
				<tr>
				  <td class="texts titles param_titles_font">Power range </td>
				  <td class="texts titles param_values_font"><tmpl_var name="up_powerRange"></td>
				</tr>
				</tmpl_if>
				<tmpl_if if_mender>
				<tr>
				  <td class="texts titles param_titles_font">Mend rate </td>
				  <td class="texts titles param_values_font"><tmpl_var name="up_mendRate"></td>
				</tr>
				</tmpl_if>
				<tmpl_if if_healer>
				<tr>
				  <td class="texts titles param_titles_font">Heal rate </td>
				  <td class="texts titles param_values_font"><tmpl_var name="up_healRate"></td>
				</tr>
				</tmpl_if>

				<tmpl_if if_caster>

				<tr>
				  <td class="texts titles param_titles_font">Ability range </td>
				  <td class="texts titles param_values_font"><tmpl_var name="up_convertRange"></td>
				</tr>
				<!--
				<tr>
				  <td class="texts titles param_titles_font">Ability possibility</td>
				  <td class="texts titles param_values_font"><tmpl_var name="up_convertPossibility"></td>
				</tr>
				-->
				</tmpl_if>
				<tmpl_if has_abilityPowerInUse>
					<tr>
					  <td class="texts titles param_titles_font">Ability power </td>
					  <td class="texts titles param_values_font"><tmpl_var name="up_abilityPower"></td>
					</tr>
				</tmpl_if>

				<tmpl_if if_dodge>
				<tr>
				  <td class="texts titles param_titles_font">Dodge arrows</td>
				  <td class="texts titles param_values_font"><tmpl_var name="up_dodge_ranged"></td>
				</tr>
				<tr>
				  <td class="texts titles param_titles_font">Dodge melee</td>
				  <td class="texts titles param_values_font"><tmpl_var name="up_dodge_close"></td>
				</tr>
				<tr>
				  <td class="texts titles param_titles_font">Dodge counters</td>
				  <td class="texts titles param_values_font"><tmpl_var name="up_dodge_counter"></td>
				</tr>
				</tmpl_if>

				<tmpl_if if_mendable>
				  <tmpl_if up_constr_bonus>
					<tr>
					  <td class="texts titles param_titles_font">Construct aff.</td>
					  <td class="texts titles param_values_font"><tmpl_var name="up_constr_bonus"></td>
					</tr>
				  </tmpl_if>
				  <tr>
					<td class="texts titles param_titles_font">Mend aff.</td>
					<td class="texts titles param_values_font"><tmpl_var name="up_mend_bonus"></td>
				  </tr>

				<tmpl_else>
				  <tmpl_if up_heal_bonus>
					<tr>
					  <td class="texts titles param_titles_font">Heal aff.</td>
					  <td class="texts titles param_values_font"><tmpl_var name="up_heal_bonus">%</td>
					</tr>
				  </tmpl_if>
			  </tmpl_if>



			<tmpl_if up_convertResistance_int>
			  <tr>
				<td class="texts titles param_titles_font">Mental resistance </td>
				<td class="texts titles param_values_font"><tmpl_var name="up_convertResistance"></td>
			  </tr>
			</tmpl_if>
			  <tr>
				<td class="texts titles param_titles_font">Size</td>
				<td class="texts titles param_values_font"><tmpl_var name="up_size"></td>
			  </tr>


			  <tmpl_if up_upgrade_to>
			  <tr class="collapsible_row hint_row center_aligned_title" id='upgrade_to_unitname_id' >
				<td colspan="2" class="texts titles " id='upgrade_to_unitname_id_child'></td>
			  </tr>
			  <tr>
				<td class="texts titles param_titles_font">Upgrade to</td>
			  <td><img class="<tmpl_if up_upgrade_to_img_crop_width>crop_img</tmpl_if> unit_image selectable" src="<tmpl_var up_upgrade_to>" id="upgrade_to_img_id" title="<tmpl_var  up_upgrade_to_img_crop_width>" alt="<tmpl_var up_upgrade_to_unitname>" onClick="showMyName('upgrade_to_img_id', 'ID', 'upgrade_to_unitname_id')"/></td>
			  </tr>
			  </tmpl_if>
			  <tmpl_if up_upgrade_from>
			  <tr class="collapsible_row hint_row center_aligned_title" id='upgrade_from_unitname_id' >
				<td colspan="2" class="texts titles " id='upgrade_from_unitname_id_child'></td>
			  </tr>
			  <tr>
				<td class="texts titles param_titles_font">Upgrade from</td>
			  <td><img class="<tmpl_if up_upgrade_from_img_crop_width>crop_img</tmpl_if> unit_image selectable" src="<tmpl_var up_upgrade_from>" id="upgrade_from_img_id" title="<tmpl_var  up_upgrade_from_img_crop_width>" alt="<tmpl_var up_upgrade_from_unitname>" onClick="showMyName('upgrade_from_img_id', 'ID', 'upgrade_from_unitname_id')"/></td>
			  </tr>
			  </tmpl_if>


	  <!--
		 is tech end
	-->
    </tmpl_if>



	  <!--
		 is show stats end
		-->
     </tmpl_if>

     <!--
     -------------------------------------------- END OF ATTRIBUTES --------------------------------------------------
    -->


	  <tmpl_if up_builders>
      <tr>
        <td class="texts titles param_titles_font">Builders:</td><td></td>
      </tr>
      <tr class="collapsible_row hint_row center_aligned_title" id='builders_unitname_id' >
        <td colspan="2" class="texts titles"  id='builders_unitname_id_child'></td>
      </tr>
      <tr>
        <td colspan="2" class="right_aligned_title">
          <tmpl_loop up_builders>
            <tmpl_if up_builder_img>
              <img class="<tmpl_if up_builder_img_crop_width>crop_img</tmpl_if> unit_image selectable buildersimg <tmpl_var up_builder_img_id>" src="<tmpl_var up_builder_img>" title="<tmpl_var  up_builder_img_crop_width>" alt="<tmpl_var up_builder_unitname>"  onClick="showMyName('<tmpl_var up_builder_img_id>', 'buildersimg', 'builders_unitname_id')"  />
            <tmpl_else>
              <img class="<tmpl_if up_builder_img_crop_width>crop_img</tmpl_if> unit_image selectable buildersimg <tmpl_var up_builder_img_id>" src="<tmpl_var up_builder_img_double>" title="<tmpl_var  up_builder_img_crop_width>" alt="<tmpl_var up_builder_unitname>"  onClick="showMyName('<tmpl_var up_builder_img_id>', 'buildersimg', 'builders_unitname_id')" />
            </tmpl_if>
          </tmpl_loop>
        </td>
      </tr>
	  </tmpl_if>


   <tmpl_if up_requires>
      <tr class="collapsible_row hint_row center_aligned_title" id='requires_unitname_id' >
        <td colspan="2" class="texts titles" id='requires_unitname_id_child'> </td>
      </tr>
      <tr>
         <td class="texts titles param_titles_font">Requires: </td><td></td>
      </tr>
      <tr>
        <td colspan="2" class="right_aligned_title">
           <tmpl_loop up_requires>
              <tmpl_if up_req_img>
                 <img class="<tmpl_if up_requires_img_crop_width>crop_img</tmpl_if> unit_image image selectable requiresimg <tmpl_var up_requires_img_id>" src="<tmpl_var up_req_img>" title="<tmpl_var up_requires_img_crop_width>"  alt="<tmpl_var up_requires_unitname>"  onClick="showMyName('<tmpl_var up_requires_img_id>', 'requiresimg', 'requires_unitname_id')" />
              </tmpl_if>
           </tmpl_loop>
         </td>
      </tr>
   </tmpl_if>

      <tmpl_if up_related>
         <tr class="collapsible_row hint_row center_aligned_title" id='related_unitname_id' >
           <td colspan="2" class="texts titles" id='related_unitname_id_child'> </td>
         </tr>
         <tr>
            <td class="texts titles param_titles_font">Related: </td><td></td>
         </tr>
         <tr>
           <td colspan="2" class="right_aligned_title">
              <tmpl_loop up_related>
                 <tmpl_if up_rel_img>
                    <img class="<tmpl_if up_related_img_crop_width>crop_img</tmpl_if> unit_image image selectable relatedimg <tmpl_var up_related_img_id>" src="<tmpl_var up_rel_img>" title="<tmpl_var up_related_img_crop_width>"  alt="<tmpl_var up_related_unitname>"  onClick="showMyName('<tmpl_var up_related_img_id>', 'relatedimg', 'related_unitname_id')" />
                 </tmpl_if>
              </tmpl_loop>
            </td>
         </tr>
   </tmpl_if>

   </table>
   </td>
   </tr>





  <tmpl_if up_bonus>
  <tr>
    <td colspan="2" class="texts descriptions desc_font">
      <div>
        <table  class="borderless full damage_bonuses_table">
          <tr>
            <td colspan="3" class="full texts titles table_title_font dmg_bonus_color">Damage bonuses</td>
          </tr>
          <tr>
             <td class="texts titles table_values_font dmg_bonus_color">Bonus</td>
             <td class="texts titles table_values_font dmg_bonus_color"> Damage</td>
             <td class="texts list_titles table_values_font dmg_bonus_color">Against</td>
          </tr>
          <tmpl_loop  up_bonus>
             <tr>
               <td class="texts table_texts table_values_font dmg_bonus_color">
                  <div class="num_values_div"><tmpl_var name="up_bonus_percentage"></div>
               </td>
               <td class="texts table_texts table_values_font dmg_bonus_color" >
                  <div class="num_values_div"><tmpl_var name="up_bonus_value"></div>
               </td>
               <td class="texts list_elements table_values_font dmg_bonus_color"><tmpl_var name="up_bonus_against"></td>
             </tr>
          </tmpl_loop>
        </table>
       </div>
    </td>
  </tr>
</tmpl_if>



  <tmpl_if up_spells_details>
    <tr>
    <td colspan="2" class="full texts descriptions">
     <div>
      <table class="centered mild_spaced full spell_details_table">

        <tr>
          <td colspan="7" class="full texts titles table_title_font spells_color" >Special abilities </td>
        </tr>
        <tr>
          <td class="texts titles table_headers_font spells_color">Image</td>
          <td class="texts titles name table_headers_font spells_color">Name</td>
          <td class="texts titles table_headers_font spells_color">Chance</td>
          <td class="texts titles table_headers_font spells_color">Range</td>
          <td class="texts titles table_headers_font spells_color">Timeout<br>[turns]</td>
          <td class="texts titles table_headers_font spells_color">Cooldown<br>[turns]</td>
          <td class="texts titles table_headers_font spells_color"> </td>
        </tr>

		<tmpl_loop up_spells_details>
        <tr <tmpl_if up_spell_sub>class='collapsible_row <tmpl_var name="up_spell_id">'</tmpl_if> onClick="toggleMe('<tmpl_var name="up_spell_id">')">
          <td class="texts table_texts table_txt_font spells_color spell_separator">
            <tmpl_if up_spell_sub>
              <span style='font-size:40px;'>&#8627;</span>
            <tmpl_else>
              <img  class="icon"  alt=" " src="<tmpl_var up_spell_img>"  />
            </tmpl_if>
          </td>
		      <td class="texts table_texts table_txt_font spells_color spell_separator"><tmpl_var up_spell_name></td>
          <td class="texts table_texts table_txt_font spells_color spell_separator"><tmpl_var up_spell_chance></td>
          <td class="texts table_texts table_txt_font spells_color spell_separator"><tmpl_var up_spell_range></td>
          <td class="texts table_texts table_txt_font spells_color spell_separator"><tmpl_var up_spell_timeout></td>
          <td class="texts table_texts table_txt_font spells_color spell_separator"><tmpl_var up_spell_cooldown></td>
          <td class="texts table_texts table_txt_font spells_color spell_separator"><img src="gfx/templates/expand_triangle.png" alt="&darr;"/></td>
        </tr>
        <tr class='collapsible_row <tmpl_var name="up_spell_id">' >
          <td colspan="7" class="full texts table_texts_left table_txt_font spells_color" >
            <p>
              <tmpl_var name="up_spell_desc">
              <tmpl_if up_spell_adddesc>
                 <br>
                 <tmpl_var name="up_spell_adddesc">
              </tmpl_if>
              <br>
              <i><tmpl_var name="up_spell_behaviour"> <tmpl_var name="up_spell_targets"> <tmpl_var name="up_spell_specs"></i>


              <br>
              <tmpl_if up_spell_indicator>
                <img class="icon_small"  alt=" " src="<tmpl_var up_spell_indicator>"  />
              </tmpl_if>

              <tmpl_loop  up_spells_loop>
                <tmpl_if up_spell_action_id>
                  <tmpl_if up_spell_action_name>
                    <strong><tmpl_var name="up_spell_action_title"></strong> <tmpl_var name="up_spell_action_name"> <tmpl_var name="up_spell_action_desc">

                    <tmpl_if up_bonus>

                            <table class="mild_spaced full table spell_damage_bonuses_table">

                              <tr>
                                 <td class="texts titles table_txt_font spells_color">Bonus</td>
                                 <td class="texts titles table_txt_font spells_color"> Damage</td>
                                 <td class="texts list_titles table_txt_font spells_color">Against</td>
                              </tr>
                              <tmpl_loop  up_bonus>
                                 <tr>
                                   <td class="texts table_texts table_txt_font spells_color">
                                      <div class="num_values_div"><tmpl_var name="up_bonus_percentage"></div>
                                   </td>
                                   <td class="texts table_texts table_txt_font spells_color" >
                                      <div class="num_values_div"><tmpl_var name="up_bonus_value"></div>
                                   </td>
                                   <td class="texts list_elements table_txt_font spells_color"><tmpl_var name="up_bonus_against"></td>
                                 </tr>
                              </tmpl_loop>
                            </table>
                    </tmpl_if>
                  </tmpl_if>
                </tmpl_if>
              </tmpl_loop>





              <tmpl_if up_spell_reqs>
                 <br>
                 <strong>Requires:</strong> <tmpl_var name="up_spell_reqs">
              </tmpl_if>
            </p>
            <p>


            </p>
          </td>
		</tr>
		</tmpl_loop>

      </table>
     </div>
	</td>
  </tr>
 </tmpl_if>


<tmpl_if up_produces>
  <tr>
    <td colspan="2" class="texts descriptions desc_font">
     <div>
      <table class="tight_spaced full table production_table" id="produces_table">
        <tr>
          <td class="full texts titles table_title_font production_color">Produces </td>
        </tr>
        <tr>
          <td >
              <tmpl_loop up_produces>
                <img class="unit_image <tmpl_if up_produces_img_crop_width>crop_img</tmpl_if> selectable producesimg <tmpl_var up_produces_img_id>"  src="<tmpl_var up_produces_img>"  alt="<tmpl_var up_produces_unitname>" title="<tmpl_var  up_produces_img_crop_width>" onClick="showMyNameOnTable('<tmpl_var up_produces_img_id>', 'producesimg', 'produces_table')"  />
              </tmpl_loop>
          </td>
        </tr>
          <tmpl_if up_produces_shortened>
            <tr>
              <td class="texts table_texts table_title_font production_color">
                ... too many to show all
              </td>
            </tr>
          </tmpl_if>
      </table>
     </div>
    </td>
  </tr>
</tmpl_if>


<tmpl_if up_valid_targets_text>
  <tr>
    <td colspan="2" class="texts descriptions desc_font">
      <div>
        <table class="mild_spaced full possible_effects_table" id="valid_targets_table">
          <tr>
            <tmpl_if if_tech>
              <td class="texts titles table_title_font possible_effect_color">Affects: </td>
            <tmpl_else>
              <td class="texts titles table_title_font possible_effect_color">Can only attack: </td>
            </tmpl_if>
          </tr>
          <tr>
            <td class="texts table_texts table_title_font possible_effect_color"><tmpl_var name="up_valid_targets_text"></td>
          </tr>
          <tr>
            <td >
              <tmpl_loop up_valid_targets>
                <img class="<tmpl_if up_valid_targets_img_crop_width>crop_img</tmpl_if> unit_image selectable affectsunitsimg <tmpl_var up_valid_targets_img_id>"  src="<tmpl_var up_valid_targets_img>"  title="<tmpl_var up_valid_targets_img_crop_width>" alt="<tmpl_var up_valid_targets_unitname>"  onClick="showMyNameOnTable('<tmpl_var up_valid_targets_img_id>', 'affectsunitsimg', 'valid_targets_table')"  />
              </tmpl_loop>
            </td>
          </tr>
          <tmpl_if up_valid_targets_shortened>
            <tr>
              <td class="texts table_texts table_title_font possible_effect_color">
                ... too many to show all
              </td>
            </tr>
          </tmpl_if>
        </table>
      </div>
    </td>
  </tr>
</tmpl_if>



<tmpl_if up_tech_unlocks_units>
  <tr>
    <td colspan="2" class="texts descriptions desc_font">
     <div>
      <table class="tight_spaced full unlocks_units_table" id="unlock_units_table">
        <tr>
          <td class="full texts titles table_title_font unlocks_units_color">Needed for producing </td>
        </tr>
        <tr>
          <td >
              <tmpl_loop up_tech_unlocks_units>
                <img class="<tmpl_if up_tech_unlocks_units_img_crop_width>crop_img</tmpl_if> unit_image selectable techunlocksunitsimg <tmpl_var up_tech_unlocks_units_img_id>"  src="<tmpl_var up_tech_unlocks_units_img>" title="<tmpl_var  up_tech_unlocks_units_img_crop_width>"  alt="<tmpl_var up_tech_unlocks_units_unitname>"  onClick="showMyNameOnTable('<tmpl_var up_tech_unlocks_units_img_id>', 'techunlocksunitsimg', 'unlock_units_table')"  />
              </tmpl_loop>
          </td>
        </tr>
          <tmpl_if up_tech_unlocks_units_shortened>
            <tr>
              <td class="texts table_texts table_title_font unlocks_units_color">
                ... too many to show all
              </td>
            </tr>
          </tmpl_if>
      </table>
     </div>
    </td>
  </tr>
</tmpl_if>

<tmpl_if up_tech_unlocks_effects>
  <tr>
    <td colspan="2" class="texts descriptions desc_font">
     <div>
      <table class="tight_spaced full unlocks_effects_table" id="unlock_effects_table">
        <tr>
          <td class="full texts titles table_title_font unlocks_effects_color">Needed for using abilities </td>
        </tr>

        <tr>
          <td >
              <tmpl_loop up_tech_unlocks_effects>
                <img class="<tmpl_if up_tech_unlocks_effects_img_crop_width>crop_img</tmpl_if> unit_image selectable techunlockseffectsimg <tmpl_var up_tech_unlocks_effects_img_id>"  src="<tmpl_var up_tech_unlocks_effects_img>" title="<tmpl_var  up_tech_unlocks_effects_img_crop_width>"  alt="<tmpl_var up_tech_unlocks_effects_unitname>"  onClick="showMyNameOnTable('<tmpl_var up_tech_unlocks_effects_img_id>', 'techunlockseffectsimg', 'unlock_effects_table')"  />
              </tmpl_loop>
          </td>
        </tr>
          <tmpl_if up_tech_unlocks_effects_shortened>
            <tr>
              <td class="texts table_texts table_title_font unlocks_effects_color">
                ... too many to show all
              </td>
            </tr>
          </tmpl_if>
       </div>

      </table>
    </td>
  </tr>
</tmpl_if>

 <!--
  <tmpl_if up_effects_details>
    <tr>
    <td colspan="2" class="full texts descriptions desc_font">
      <table class="centered full borderless effect_details_table">

        <tr>
          <td colspan="3" class="full texts titles table_title_font effects_color">Active Effects</td>
        </tr>
        <tr>
          <td class="texts titles table_headers_font effects_color">Name</td>
          <td class="texts titles table_headers_font effects_color">Chance</td>
          <td class="texts titles table_headers_font effects_color">Radius</td>
          <td class="texts titles table_headers_font effects_color">Timeout<br>[turns]</td>
        </tr>

		<tmpl_loop up_effects_details>
        <tr onClick="toggleMe('<tmpl_var name="up_effects_details_id">')">
		  <td class="texts table_texts table_txt_font effects_color"><tmpl_var up_effects_name></td>
          <td class="texts table_texts table_txt_font effects_color"><tmpl_var up_effects_chance></td>
          <td class="texts table_texts table_txt_font effects_color"><tmpl_var up_effects_radius></td>
          <td class="texts table_texts table_txt_font effects_color"><tmpl_var up_effects_timeout></td>
        </tr>
        <tr class='collapsible_row'  id="<tmpl_var name="up_effects_details_id">">
			<td colspan="3" class="full texts table_texts table_txt_font effects_color" >
				<p>
					<tmpl_var name="up_effects_desc">
				</p>
				<p>
					<tmpl_var name="up_effects_action">
				</p>
			</td>
		</tr>
		</tmpl_loop>

      </table>
	</td>
  </tr>
 </tmpl_if>
 -->


<tmpl_if up_aff_effects>
  <tr>
    <td colspan="2" class="texts descriptions desc_font">
        <table  class="borderless full possible_effects_table">
          <tr>
            <td class="full texts titles table_title_font possible_effect_color">Possible affecting effects: </td>
          </tr>
          <tr>
            <td class="texts table_texts table_title_font possible_effect_color"><tmpl_var name="up_aff_effects"></td>
          </tr>
        </table>
    </td>
  </tr>
</tmpl_if>






</table>


</body>

</html>
Post Reply

Return to “Modders lounge”