Example #1
0
 df::tiletype findRandomVariant (const df::tiletype tile)
 {
     if (tileVariant(tile) == tiletype_variant::NONE)
         return tile;
     std::vector<df::tiletype> matches;
     FOR_ENUM_ITEMS(tiletype, tt)
     {
         if (tileShape(tt) == tileShape(tile) &&
             tileMaterial(tt) == tileMaterial(tile) &&
             tileSpecial(tt) == tileSpecial(tile))
             matches.push_back(tt);
     }
     return matches[rand() % matches.size()];
 }
Example #2
0
void Tile::AssembleTile( void )
{

    if(!visible) {
        return;
    }

    if((material.type == INORGANIC) && (material.index == -1)) {
        material.index = 0;
    }

    bool defaultSnow = 1;
    t_SpriteWithOffset sprite;
    c_sprite* spriteobject = 0;

	int32_t drawx = 0;
	int32_t drawy = 0;
	GetDrawLocation(drawx, drawy);

    //TODO the following check should get incorporated into segment beautification
    if(((drawx + TILEWIDTH*ssConfig.scale) < 0) || (drawx > ssState.ScreenW) || ((drawy + (TILETOPHEIGHT + FLOORHEIGHT)*ssConfig.scale) < 0) || (drawy - WALLHEIGHT*ssConfig.scale > ssState.ScreenH)) {
		visible = false;
		return;
    }

    bool chopThisTile = 0;

    if(ssConfig.truncate_walls == 1) {
        chopThisTile = 1;
    } else if(ssConfig.truncate_walls == 2 && obscuringCreature == 1) {
        chopThisTile = 1;
    } else if(ssConfig.truncate_walls == 3 && (obscuringCreature == 1 || obscuringBuilding == 1)) {
        chopThisTile = 1;
    } else if(ssConfig.truncate_walls == 4 && obscuringBuilding == 1) {
        chopThisTile = 1;
    }

    if(building.type == BUILDINGTYPE_BLACKBOX) {
        AssembleSpriteFromSheet( SPRITEOBJECT_BLACK, IMGObjectSheet, al_map_rgb(255,255,255), drawx, drawy+FLOORHEIGHT*ssConfig.scale);
        AssembleSpriteFromSheet( SPRITEOBJECT_BLACK, IMGObjectSheet, al_map_rgb(255,255,255), drawx, drawy);
        return;
    }

	ALLEGRO_COLOR plateBorderColor = al_map_rgb(85,85,85);
	int rando = randomCube[x%RANDOM_CUBE][y%RANDOM_CUBE][z%RANDOM_CUBE];

    DrawGrowth(spriteobject, false);


	//Draw Ramp Tops
	if(tileType == tiletype::RampTop){
		Tile * b = this->ownerSegment->getTile(this->x, this->y, this->z - 1);
		if ( b && b->building.type != BUILDINGTYPE_BLACKBOX && b->tileShapeBasic() == tiletype_shape_basic::Ramp ) {
			spriteobject = GetTileSpriteMap(b->tileType, b->material, b->consForm);
			if (spriteobject->get_sheetindex() == UNCONFIGURED_INDEX) {
				spriteobject->set_sheetindex(0);
				spriteobject->set_fileindex(INVALID_INDEX);
				spriteobject->set_defaultsheet(IMGRampSheet);
			}
			if (spriteobject->get_sheetindex() != INVALID_INDEX) {
				spriteobject->set_size(SPRITEWIDTH, TILETOPHEIGHT);
				spriteobject->set_plate_layout(RAMPTOPPLATE);
				spriteobject->set_offset(0, WALLHEIGHT);
				spriteobject->assemble_world_offset(x, y, z, 0, b);
				spriteobject->set_offset(0, 0);
			}
			spriteobject->set_plate_layout(TILEPLATE);
		} else {
			return;
		}
	}

    //Draw Floor
    if( tileShapeBasic()==tiletype_shape_basic::Floor ||
            tileShapeBasic()==tiletype_shape_basic::Wall ||
            tileShapeBasic()==tiletype_shape_basic::Ramp ||
            tileShapeBasic()==tiletype_shape_basic::Stair ||
            tileShape()==RemoteFortressReader::TWIG) {

        //If plate has no floor, look for a Filler Floor from it's wall
        if (tileShapeBasic() == tiletype_shape_basic::Floor || tileShape() == RemoteFortressReader::TWIG) {
            spriteobject = GetFloorSpriteMap(tileType, this->material, consForm);
        } else if (tileShapeBasic()==tiletype_shape_basic::Wall) {
            spriteobject = GetFloorSpriteMap(tileType, this->material, consForm);
        } else if (tileShapeBasic()==tiletype_shape_basic::Ramp) {
            spriteobject = GetFloorSpriteMap(tileType, this->material, consForm);
        } else if (tileShapeBasic()==tiletype_shape_basic::Stair) {
            spriteobject = GetFloorSpriteMap(tileType, this->material, consForm);
        }
        if(spriteobject->get_sheetindex() != INVALID_INDEX) {
            if (spriteobject->get_sheetindex() == UNCONFIGURED_INDEX) {
                spriteobject->set_sheetindex(SPRITEOBJECT_FLOOR_NA);
                spriteobject->set_fileindex(INVALID_INDEX);
                spriteobject->set_offset(0, WALLHEIGHT);
                spriteobject->assemble_world(x, y, z, this);
            } else {
                spriteobject->assemble_world(x, y, z, this);
            }
        }
    }

    //Floor Engravings
    if((tileShapeBasic()==tiletype_shape_basic::Floor) && engraving_character && engraving_flags.bits.floor) {
        AssembleSpriteFromSheet( engraving_character, IMGEngFloorSheet, al_map_rgba_f(1.0,1.0,1.0,((engraving_quality + 5.0f) / 10.0f)), drawx, drawy, this );
    }

    //Draw Ramp
    if(tileShapeBasic()==tiletype_shape_basic::Ramp) {
        spriteobject = GetTileSpriteMap(tileType, material, consForm);
        if (spriteobject->get_sheetindex() == UNCONFIGURED_INDEX) {
            spriteobject->set_sheetindex(0);
            spriteobject->set_fileindex(INVALID_INDEX);
            spriteobject->set_defaultsheet(IMGRampSheet);
        }
        if (spriteobject->get_sheetindex() != INVALID_INDEX) {
            spriteobject->set_size(SPRITEWIDTH, SPRITEHEIGHT);
            spriteobject->set_plate_layout(RAMPBOTTOMPLATE);
            spriteobject->assemble_world_offset(x, y, z, 0, this, (chopThisTile && this->z == ownerSegment->segState.Position.z + ownerSegment->segState.Size.z -2));
        }
        spriteobject->set_plate_layout(TILEPLATE);
    }

    if(snowlevel <= bloodlevel) {
        AssembleFloorBlood ( drawx, drawy );
    }

    //first part of snow
    if(tileShapeBasic()!=tiletype_shape_basic::Ramp 
        && tileShapeBasic()!=tiletype_shape_basic::Wall 
        && tileShapeBasic()!=tiletype_shape_basic::Stair 
        && defaultSnow
        && snowlevel>bloodlevel) {
        if(snowlevel > 75) {
            AssembleSpriteFromSheet( 20, IMGObjectSheet, bloodcolor, drawx, drawy, this);
        } else if(snowlevel > 50) {
            AssembleSpriteFromSheet( 21, IMGObjectSheet, bloodcolor, drawx, drawy, this );
        } else if(snowlevel > 25) {
            AssembleSpriteFromSheet( 22, IMGObjectSheet, bloodcolor, drawx, drawy, this );
        } else if(snowlevel > 0) {
            AssembleSpriteFromSheet( 23, IMGObjectSheet, bloodcolor, drawx, drawy, this );
        }
    }

    ////vegetation
    //if(tree.index > 0 || tree.type > 0){
    //	c_sprite * vegetationsprite = 0;
    //	vegetationsprite = GetSpriteVegetation( (TileClass) getVegetationType( this->floorType ), tree.index );
    //	if(vegetationsprite)
    //		vegetationsprite->assemble_world(x, y, z);
    //}

    //items
    if(Item.item.type >= 0) {
        if(
            contentLoader->itemConfigs[Item.item.type] &&
            (Item.item.index < contentLoader->itemConfigs[Item.item.type]->subItems.size()) &&
            contentLoader->itemConfigs[Item.item.type]->subItems[Item.item.index]) {
            contentLoader->itemConfigs[Item.item.type]->subItems[Item.item.index]->sprite.assemble_world(x, y, z, this);
        } else if (
            contentLoader->itemConfigs[Item.item.type] &&
            contentLoader->itemConfigs[Item.item.type]->configured) {
            contentLoader->itemConfigs[Item.item.type]->default_sprite.assemble_world(x, y, z, this);
        } else {
            AssembleSpriteFromSheet( 350, IMGObjectSheet, lookupMaterialColor(Item.matt, Item.dyematt), drawx, (tileShapeBasic()==tiletype_shape_basic::Ramp)?(drawy - ((WALLHEIGHT/2)*ssConfig.scale)):drawy , this);
        }
    }

    //shadow
    if (shadow > 0) {
        AssembleSpriteFromSheet( BASE_SHADOW_PLATE + shadow - 1, IMGObjectSheet, al_map_rgb(255,255,255), drawx, (tileShapeBasic()==tiletype_shape_basic::Ramp)?(drawy - ((WALLHEIGHT/2)*ssConfig.scale)):drawy , this);
    }

    //Building
    bool skipBuilding =
        (building.type == building_type::Civzone && !ssConfig.show_zones) ||
        (building.type == building_type::Stockpile && !ssConfig.show_stockpiles);

    if(building.type != BUILDINGTYPE_NA && !skipBuilding) {
        for(uint32_t i=0; i < building.sprites.size(); i++) {
            spriteobject = &building.sprites[i];
            if(building.parent) {
                spriteobject->assemble_world(x, y, z, building.parent);
            } else {
                spriteobject->assemble_world(x, y, z, this);
            }
        }
    }

    //Draw Stairs
    if(tileShapeBasic()==tiletype_shape_basic::Stair) {
        bool mirrored = false;
        if(findWallCloseTo(ownerSegment, this) == eSimpleW) {
            mirrored = true;
        }

        //down part
        spriteobject = GetFloorSpriteMap(tileType, material, consForm);
        if(spriteobject->get_sheetindex() != INVALID_INDEX && spriteobject->get_sheetindex() != UNCONFIGURED_INDEX) {
            if (mirrored) {
                spriteobject->assemble_world_offset(x, y, z, 1, this);
            } else {
                spriteobject->assemble_world(x, y, z, this);
            }
        }

        //up part
        spriteobject = GetTileSpriteMap(tileType, material, consForm);
        if(spriteobject->get_sheetindex() != INVALID_INDEX && spriteobject->get_sheetindex() != UNCONFIGURED_INDEX) {
            if (mirrored) {
                spriteobject->assemble_world_offset(x, y, z, 1, this);
            } else {
                spriteobject->assemble_world(x, y, z, this);
            }
        }
    }

    if(tileShapeBasic()==tiletype_shape_basic::Floor ||
            tileShapeBasic()==tiletype_shape_basic::Wall) {
        //draw wall
        spriteobject =  GetTileSpriteMap(tileType, material, consForm);
        int spriteOffset = 0;
        if (spriteobject->get_sheetindex() == UNCONFIGURED_INDEX) {
            if(tileShapeBasic()==tiletype_shape_basic::Wall){
                spriteobject->set_sheetindex(SPRITEOBJECT_WALL_NA);
                spriteobject->set_fileindex(INVALID_INDEX);
                spriteobject->set_plate_layout(TILEPLATE);
                spriteobject->set_defaultsheet(IMGObjectSheet);
            } else {
                //unconfigured non-walls are not valid
                spriteobject->set_sheetindex(INVALID_INDEX);
            }
        }
        if (spriteobject->get_sheetindex() == INVALID_INDEX ) {
            //skip
        } else {
            spriteobject->assemble_world(x, y, z, this, (chopThisTile && this->z == ownerSegment->segState.Position.z + ownerSegment->segState.Size.z -2));
        }
    }

    //Wall Engravings
    if((tileShapeBasic()==tiletype_shape_basic::Wall) && engraving_character) {
        if(ownerSegment->segState.Rotation == 0) {
            if(engraving_flags.bits.east) {
                AssembleSpriteFromSheet( engraving_character, IMGEngRightSheet, al_map_rgba_f(1.0,1.0,1.0,((engraving_quality + 5.0f) / 10.0f)), drawx, drawy, this );
            }
            if(engraving_flags.bits.south) {
                AssembleSpriteFromSheet( engraving_character, IMGEngLeftSheet, al_map_rgba_f(1.0,1.0,1.0,((engraving_quality + 5.0f) / 10.0f)), drawx, drawy, this );
            }
        }
        if(ownerSegment->segState.Rotation == 1) {
            if(engraving_flags.bits.north) {
                AssembleSpriteFromSheet( engraving_character, IMGEngRightSheet, al_map_rgba_f(1.0,1.0,1.0,((engraving_quality + 5.0f) / 10.0f)), drawx, drawy, this );
            }
            if(engraving_flags.bits.east) {
                AssembleSpriteFromSheet( engraving_character, IMGEngLeftSheet, al_map_rgba_f(1.0,1.0,1.0,((engraving_quality + 5.0f) / 10.0f)), drawx, drawy, this );
            }
        }
        if(ownerSegment->segState.Rotation == 2) {
            if(engraving_flags.bits.west) {
                AssembleSpriteFromSheet( engraving_character, IMGEngRightSheet, al_map_rgba_f(1.0,1.0,1.0,((engraving_quality + 5.0f) / 10.0f)), drawx, drawy, this );
            }
            if(engraving_flags.bits.north) {
                AssembleSpriteFromSheet( engraving_character, IMGEngLeftSheet, al_map_rgba_f(1.0,1.0,1.0,((engraving_quality + 5.0f) / 10.0f)), drawx, drawy, this );
            }
        }
        if(ownerSegment->segState.Rotation == 3) {
            if(engraving_flags.bits.south) {
                AssembleSpriteFromSheet( engraving_character, IMGEngRightSheet, al_map_rgba_f(1.0,1.0,1.0,((engraving_quality + 5.0f) / 10.0f)), drawx, drawy, this );
            }
            if(engraving_flags.bits.west) {
                AssembleSpriteFromSheet( engraving_character, IMGEngLeftSheet, al_map_rgba_f(1.0,1.0,1.0,((engraving_quality + 5.0f) / 10.0f)), drawx, drawy, this );
            }
        }
    }

    DrawGrowth(spriteobject, true);
    if(designation.bits.flow_size > 0) {
        //if(waterlevel == 7) waterlevel--;
        uint32_t waterlevel = designation.bits.flow_size + (deepwater ? 1 : 0);
        if(designation.bits.liquid_type == 0) {
            contentLoader->water[waterlevel-1].sprite.assemble_world(x, y, z, this, (chopThisTile && this->z == ownerSegment->segState.Position.z + ownerSegment->segState.Size.z -2));
        } else {
            contentLoader->lava[waterlevel-1].sprite.assemble_world(x, y, z, this, (chopThisTile && this->z == ownerSegment->segState.Position.z + ownerSegment->segState.Size.z -2));
        }
    }

    // creature
    if(occ.bits.unit && creature && (ssConfig.show_hidden_tiles || !designation.bits.hidden)) {
        AssembleCreature(drawx, drawy, creature, this);
    }

    //second part of snow
    if(tileShapeBasic()!=tiletype_shape_basic::Wall 
        && tileShapeBasic()!=tiletype_shape_basic::Stair 
        && defaultSnow
        && snowlevel>bloodlevel) {
        if(snowlevel > 75) {
            AssembleSpriteFromSheet( 24, IMGObjectSheet, bloodcolor, drawx, drawy, this );
        } else if(snowlevel > 50) {
            AssembleSpriteFromSheet( 25, IMGObjectSheet, bloodcolor, drawx, drawy, this );
        } else if(snowlevel > 25) {
            AssembleSpriteFromSheet( 26, IMGObjectSheet, bloodcolor, drawx, drawy, this );
        }
    }

    if(tileeffect.density>0) {
        ALLEGRO_COLOR tint = lookupMaterialColor(tileeffect.matt);
        int size = 0;
        switch(tileeffect.type){
        case df::flow_type::Miasma:
            AssembleParticleCloud(tileeffect.density, drawx, drawy - (SPRITEHEIGHT/2), SPRITEWIDTH, SPRITEHEIGHT, sprite_miasma, tint);
            break;
        case df::flow_type::Steam:
            AssembleParticleCloud(tileeffect.density, drawx, drawy - (SPRITEHEIGHT/2), SPRITEWIDTH, SPRITEHEIGHT, sprite_water, tint);
            break;
        case df::flow_type::Mist:
            AssembleParticleCloud(tileeffect.density, drawx, drawy - (SPRITEHEIGHT/2), SPRITEWIDTH, SPRITEHEIGHT, sprite_water2, tint);
            break;
        case df::flow_type::MaterialDust:
            AssembleParticleCloud(tileeffect.density, drawx, drawy - (SPRITEHEIGHT/2), SPRITEWIDTH, SPRITEHEIGHT, sprite_dust, tint);
            break;
        case df::flow_type::MagmaMist:
            AssembleParticleCloud(tileeffect.density, drawx, drawy - (SPRITEHEIGHT/2), SPRITEWIDTH, SPRITEHEIGHT, sprite_magma, tint);
            break;
        case df::flow_type::Smoke:
            AssembleParticleCloud(tileeffect.density, drawx, drawy - (SPRITEHEIGHT/2), SPRITEWIDTH, SPRITEHEIGHT, sprite_smoke, tint);
            break;
        case df::flow_type::Dragonfire:
            tint.a*=tileeffect.density/100.0f;
            tint.g*=tileeffect.density/100.0f;
            tint.b*=tileeffect.density/100.0f;
            size = 3 - ((tileeffect.density-1)/25);
            AssembleSpriteFromSheet((((currentFrameLong+rando)%8)*20+size), sprite_dragonfire, tint, drawx, drawy, this, 2.0f);
            //ALLEGRO_COLOR tint = lookupMaterialColor(Eff_Dragonfire.matt.type, Eff_Dragonfire.matt.index);
            //draw_particle_cloud(Eff_Dragonfire.density, drawx, drawy - (SPRITEHEIGHT/2), SPRITEWIDTH, SPRITEHEIGHT, sprite_dragonfire, tint);
            break;
        case df::flow_type::Fire:
            tint.a*=tileeffect.density/100.0f;
            tint.g*=tileeffect.density/100.0f;
            tint.b*=tileeffect.density/100.0f;
            size = 3 - ((tileeffect.density-1)/25);
            AssembleSpriteFromSheet((((currentFrameLong+rando)%8)*20+size), sprite_dragonfire, tint, drawx, drawy, this, 2.0f);
            //ALLEGRO_COLOR tint = lookupMaterialColor(Eff_Fire.matt.type, Eff_Fire.matt.index);
            //draw_particle_cloud(Eff_Fire.density, drawx, drawy - (SPRITEHEIGHT/2), SPRITEWIDTH, SPRITEHEIGHT, sprite_fire, tint);
            break;
        case df::flow_type::Web:
            tint.a*=tileeffect.density/100.0f;
            AssembleSpriteFromSheet(rando%5, sprite_webing, tint, drawx, drawy, this, 4.0f);
            //al_draw_tinted_bitmap(sprite_webing,tint, drawx, drawy - (WALLHEIGHT), 0);
            break;
        case df::flow_type::MaterialGas:
            AssembleParticleCloud(tileeffect.density, drawx, drawy - (SPRITEHEIGHT/2), SPRITEWIDTH, SPRITEHEIGHT, sprite_boiling, tint);
            break;
        case df::flow_type::MaterialVapor:
            AssembleParticleCloud(tileeffect.density, drawx, drawy - (SPRITEHEIGHT/2), SPRITEWIDTH, SPRITEHEIGHT, sprite_boiling, tint);
            break;
        case df::flow_type::SeaFoam:
            tint.a*=tileeffect.density/100.0f;
            AssembleSprite(sprite_oceanwave, tint, 0, 0, al_get_bitmap_width(sprite_oceanwave), al_get_bitmap_height(sprite_oceanwave), 
                drawx, drawy - (WALLHEIGHT)*ssConfig.scale, SPRITEWIDTH*ssConfig.scale, SPRITEHEIGHT*ssConfig.scale, 0);
            break;
        case df::flow_type::OceanWave:
            AssembleParticleCloud(tileeffect.density, drawx, drawy - (SPRITEHEIGHT/2), SPRITEWIDTH, SPRITEHEIGHT, sprite_water, tint);
            break;

        }
    }
	
	// Creature Names / Info
    if(occ.bits.unit && creature && (ssConfig.show_hidden_tiles || !designation.bits.hidden)) {
        AssembleCreatureText(drawx, drawy, creature, ownerSegment);
    }
}
Example #3
0
void Tile::DrawGrowth(c_sprite * spriteobject, bool top=true)
{
    //Draw Growths that appear over branches
    if (tileMaterial() == RemoteFortressReader::ROOT
        || tileMaterial() == RemoteFortressReader::TREE_MATERIAL
        || tileMaterial() == RemoteFortressReader::MUSHROOM)
    {
        df::plant_raw* plantRaw = df::global::world->raws.plants.all[tree.index];
        for (int i = 0; i < plantRaw->growths.size(); i++)
        {
            df::plant_growth * growth = plantRaw->growths[i];
            if (!growth->locations.whole)
                continue; //we need at least one location.
            int32_t time = *df::global::cur_year_tick;
            if (growth->timing_1 >= 0 && growth->timing_1 > time)
                continue;
            if (growth->timing_2 >= 0 && growth->timing_2 < time)
                continue;
            growth_locations loca = LOCATION_NONE;
            if (growth->locations.bits.cap && tileMaterial() == RemoteFortressReader::MUSHROOM)
                loca = LOCATION_CAP;
            if (growth->locations.bits.heavy_branches && (tileSpecial() == RemoteFortressReader::BRANCH && tileType != df::tiletype::TreeBranches))
                loca = LOCATION_HEAVY_BRANCHES;
            if (growth->locations.bits.roots && tileMaterial() == RemoteFortressReader::ROOT)
                loca = LOCATION_ROOTS;
            if (growth->locations.bits.light_branches && tileType == df::tiletype::TreeBranches)
                loca = LOCATION_LIGHT_BRANCHES;
            if (growth->locations.bits.sapling && tileMaterial() == RemoteFortressReader::SAPLING)
                loca = LOCATION_SAPLING;
            if (growth->locations.bits.trunk && tileShape() == RemoteFortressReader::WALL)
                loca = LOCATION_TRUNK;
            if (growth->locations.bits.twigs && tileShape() == RemoteFortressReader::TWIG)
                loca = LOCATION_TWIGS;

            if (loca == LOCATION_NONE)
                continue;

            DFHack::t_matglossPair fakeMat;
            fakeMat.index = tree.index;
            fakeMat.type = i * 10 + loca;
            if (top)
                spriteobject = contentLoader->growthTopConfigs.get(fakeMat);
            else
                spriteobject = contentLoader->growthBottomConfigs.get(fakeMat);

            if (spriteobject)
            {
                DFHack::t_matglossPair growthMat;
                growthMat.index = growth->mat_index;
                growthMat.type = growth->mat_type;
                ALLEGRO_COLOR growCol = lookupMaterialColor(growthMat);
                if (growth->prints.size() > 1)
                {
                    df::plant_growth_print * basePrint = growth->prints[0];
                    df::plant_growth_print * currentPrint = basePrint;
                    for (int k = 0; k < growth->prints.size(); k++)
                    {
                        if (growth->prints[k]->timing_start >= 0 && growth->prints[k]->timing_start > time)
                            continue;
                        if (growth->prints[k]->timing_end >= 0 && growth->prints[k]->timing_end < time)
                            continue;
                        currentPrint = growth->prints[k];
                    }
                    growCol = morph_color(growCol,
                        ssConfig.colors.getDfColor(basePrint->color[0], basePrint->color[2], ssConfig.useDfColors),
                        ssConfig.colors.getDfColor(currentPrint->color[0], currentPrint->color[2], ssConfig.useDfColors));
                }
                spriteobject->set_growthColor(growCol);
                spriteobject->assemble_world(x, y, z, this);
            }
        }
    }
}
Example #4
0
/**
* reads one 16x16 map block into stonesense tiles
* attempts to only read as much information as is necessary to do the tile optimization
*/
void readBlockToSegment(DFHack::Core& DF, WorldSegment& segment, 
    int BlockX, int BlockY, int BlockZ,
    uint32_t BoundrySX, uint32_t BoundrySY,
    uint32_t BoundryEX, uint32_t BoundryEY,
    vector< vector <int16_t> >* allLayers)
{
    if(ssConfig.skipMaps) {
        return;
    }
    //boundry check
    int blockDimX, blockDimY, blockDimZ;
    Maps::getSize((unsigned int &)blockDimX, (unsigned int &)blockDimY, (unsigned int &)blockDimZ);
    if( BlockX < 0 || BlockX >= blockDimX ||
        BlockY < 0 || BlockY >= blockDimY ||
        BlockZ < 0 || BlockZ >= blockDimZ ) {
            return;
    }

    //make boundries local
    BoundrySX -= BlockX * BLOCKEDGESIZE;
    BoundryEX -= BlockX * BLOCKEDGESIZE;
    BoundrySY -= BlockY * BLOCKEDGESIZE;
    BoundryEY -= BlockY * BLOCKEDGESIZE;

    //read block data
    df::map_block *trueBlock;
    trueBlock = Maps::getBlock(BlockX, BlockY, BlockZ);
    if(!trueBlock) {
        return;
    }        
    //read the map features
    t_feature local, global;
    Maps::ReadFeatures(BlockX,BlockY,BlockZ,&local,&global);
    //read local vein data
    vector <df::block_square_event_mineralst * > veins;
    vector <df::block_square_event_frozen_liquidst * > ices;
    vector <df::block_square_event_material_spatterst * > splatter;
    vector <df::block_square_event_grassst * > grass;
    vector <df::block_square_event_world_constructionst * > worldconstructions;
    Maps::SortBlockEvents(
        trueBlock,
        &veins,
        &ices,
        &splatter,
        &grass,
        &worldconstructions);    
    //parse block
    for(uint32_t ly = BoundrySY; ly <= BoundryEY; ly++) {
        for(uint32_t lx = BoundrySX; lx <= BoundryEX; lx++) {
            uint32_t gx = lx + (BlockX * BLOCKEDGESIZE);
            uint32_t gy = ly + (BlockY * BLOCKEDGESIZE);
            if( !segment.CoordinateInsideSegment( gx, gy, BlockZ) ) {
                continue;
            }

            bool shouldBeIncluded = true;

            //open terrain needs to be included to make blackboxes if 
            // we are shading but not showing hidden tiles
            if(isOpenTerrain(trueBlock->tiletype[lx][ly]) 
                && trueBlock->tiletype[lx][ly] != tiletype::RampTop
                && tileShape(trueBlock->tiletype[lx][ly]) != tiletype_shape::TWIG) {
                    if(!ssConfig.show_hidden_tiles 
                        && ssConfig.shade_hidden_tiles 
                        && trueBlock->designation[lx][ly].bits.hidden) {
                            shouldBeIncluded = true;
                    } else {
                        shouldBeIncluded = false;
                    }
                    //all other terrain needs including, except for hidden tiles
                    // when we are neither showing nor shading hidden tiles
            } else if(!ssConfig.show_hidden_tiles
                && !ssConfig.shade_hidden_tiles
                && trueBlock->designation[lx][ly].bits.hidden) {
                    shouldBeIncluded = false;
            }

            //add back in any liquid tiles, in case they can be seen from above
            // as well as any hanging buildings
            if(trueBlock->designation[lx][ly].bits.flow_size
                || trueBlock->occupancy[lx][ly].bits.building) {
                    shouldBeIncluded = true;
            }

			//add back in any tiles that are constructions or designations
			if( ssConfig.show_designations
				&& containsDesignations(
					trueBlock->designation[lx][ly], 
					trueBlock->occupancy[lx][ly] ) ) {
				shouldBeIncluded = true;
			}

            if(!shouldBeIncluded){
                continue;
            }

            Tile * b = segment.ResetTile(gx, gy, BlockZ, trueBlock->tiletype[lx][ly]);
			
			b->occ.bits.unit = false;//this will be set manually when we read the creatures vector
            b->occ = trueBlock->occupancy[lx][ly];
			b->designation = trueBlock->designation[lx][ly];

			//if the tile has designations, read them and nothing else
			if( ssConfig.show_designations 
				&& readDesignationsToTile( 
					b, trueBlock->designation[lx][ly], 
					trueBlock->occupancy[lx][ly] ) ) {
						continue;
			}
			
			//set whether the tile is hidden
			b->fog_of_war = !b->designation.bits.pile;

            //don't read detailed information for blackbox tiles
            if(!ssConfig.show_hidden_tiles
                && ssConfig.shade_hidden_tiles
                && b->designation.bits.hidden
                && !b->designation.bits.flow_size) {
                    continue;
            }

            //read the grasses
            b->grasslevel = 0;
            b->grassmat = -1;
            //b->grasslevels.clear();
            //b->grassmats.clear();
            for(int i = 0; i < grass.size(); i++) {
                if(grass[i]->amount[lx][ly] > 0 && b->grasslevel == 0) { //b->grasslevel)
                    b->grasslevel = grass[i]->amount[lx][ly];
                    b->grassmat = grass[i]->plant_index;
                    //b->grasslevels.push_back(grass[i].intensity[lx][ly]);
                    //b->grassmats.push_back(grass[i].material);
                }
            }

			//read the water flows and direction.
			b->flow_direction = trueBlock->liquid_flow[lx][ly].bits.perm_flow_dir;

            //read the tile spatter
            readSpatterToTile(b, lx, ly, splatter); 

            //read the tile material
            readMaterialToTile(b, lx, ly, trueBlock, local, global, veins, allLayers);
        }
    }

    ////add trees and other vegetation
    //for(auto iter = trueBlock->plants.begin(); iter != trueBlock->plants.end(); iter++) {
    //    df::plant * wheat = *iter;
    //    assert(wheat != NULL);
    //    Tile* b = segment.getTile( wheat->pos.x, wheat->pos.y, wheat->pos.z);
    //    if(!b) {
    //        b = segment.ResetTile(wheat->pos.x, wheat->pos.y, wheat->pos.z, tiletype::OpenSpace);
    //        if(!b) {
    //            continue;
    //        }
    //    }
    //    if( b->tileShape() == tiletype_shape::TREE ||
    //        b->tileShape() == tiletype_shape::SAPLING ||
    //        b->tileShape() == tiletype_shape::SHRUB) {
    //            b->tree.type = wheat->flags.whole;
    //            b->tree.index = wheat->material;
    //    }
    //}

    //add items
    for(auto iter = trueBlock->items.begin(); iter != trueBlock->items.end(); iter++) {
		int32_t item_index = *iter;
		df::item * found_item = df::item::find(item_index);
		if(!found_item) {
			continue;
		}
		Tile* b = segment.getTile( found_item->pos.x, found_item->pos.y, found_item->pos.z);
		if(!b) {
			b = segment.ResetTile(found_item->pos.x, found_item->pos.y, found_item->pos.z, tiletype::OpenSpace);
			if(!b) {
				continue;
			}
		}
		b->Item = ConvertItem(found_item, segment);
	}


    //add effects
    for(auto iter = trueBlock->flows.begin(); iter != trueBlock->flows.end(); iter++) {
        df::flow_info * eff = *iter;
        if(eff == NULL || eff->density <= 0) {
            continue;
        }
        Tile* b = segment.getTile( eff->pos.x, eff->pos.y, eff->pos.z);
        if(segment.CoordinateInsideSegment(eff->pos.x, eff->pos.y, eff->pos.z)) {
            if(!b) {
                b = segment.ResetTile(eff->pos.x, eff->pos.y, eff->pos.z, tiletype::OpenSpace);
                if(!b) {
                    continue;
                }
            }
            if(eff->density > b->tileeffect.density 
                || b->tileeffect.type == (df::flow_type) INVALID_INDEX) {
                    b->tileeffect.type = eff->type;
                    b->tileeffect.density = eff->density;
                    b->tileeffect.matt.index = eff->mat_index;
                    b->tileeffect.matt.type = eff->mat_type;
            }
        } 
    }
}