示例#1
0
文件: probe.cpp 项目: lxnt/dfhack
command_result df_cprobe (Core * c, vector <string> & parameters)
{
    Console & con = c->con;
    CoreSuspender suspend(c);
    DFHack::Gui *Gui = c->getGui();
    int32_t cursorX, cursorY, cursorZ;
    Gui->getCursorCoords(cursorX,cursorY,cursorZ);
    if(cursorX == -30000)
    {
        con.printerr("No cursor; place cursor over creature to probe.\n");
    }
    else
    {
        for(size_t i = 0; i < world->units.all.size(); i++)
        {
            df::unit * unit = world->units.all[i];
            if(unit->pos.x == cursorX && unit->pos.y == cursorY && unit->pos.z == cursorZ)
            {
                con.print("Creature %d, race %d (%x), civ %d (%x)\n", unit->id, unit->race, unit->race, unit->civ_id, unit->civ_id);
                break;
            }
        }
    }
    return CR_OK;
}
示例#2
0
DFhackCExport command_result plugin_onupdate ( Core * c )
{
    if(timering == true)
    {
        uint64_t time2 = GetTimeMs64();
        // harmless potential data race here...
        uint64_t delta = time2-timeLast;
        // harmless potential data race here...
        timeLast = time2;
        c->con.print("Time delta = %d ms\n", delta);
    }
    if(trackmenu_flg)
    {
        DFHack::Gui * g =c->getGui();
        if (last_menu != *g->df_menu_state)
        {
            last_menu = *g->df_menu_state;
            c->con.print("Menu: %d\n",last_menu);
        }
    }
    if(trackpos_flg)
    {
        DFHack::Gui * g =c->getGui();
        g->Start();
        int32_t desig_x, desig_y, desig_z;
        g->getDesignationCoords(desig_x,desig_y,desig_z);
        if(desig_x != last_designation[0] || desig_y != last_designation[1] || desig_z != last_designation[2])
        {
            last_designation[0] = desig_x;
            last_designation[1] = desig_y;
            last_designation[2] = desig_z;
            c->con.print("Designation: %d %d %d\n",desig_x, desig_y, desig_z);
        }
        int mouse_x, mouse_y;
        g->getMousePos(mouse_x,mouse_y);
        if(mouse_x != last_mouse[0] || mouse_y != last_mouse[1])
        {
            last_mouse[0] = mouse_x;
            last_mouse[1] = mouse_y;
            c->con.print("Mouse: %d %d\n",mouse_x, mouse_y);
        }
    }
    return CR_OK;
}
示例#3
0
文件: vdig.cpp 项目: raoulxq/dfhack
int main (int argc, char* argv[])
{
    // Command line options
    bool updown = false;
    if(argc > 1 && strcmp(argv[1],"-x") == 0)
        updown = true;

    DFHack::ContextManager DFMgr("Memory.xml");
    DFHack::Context * DF;
    try
    {
        DF = DFMgr.getSingleContext();
        DF->Attach();
    }
    catch (exception& e)
    {
        cerr << e.what() << endl;
        #ifndef LINUX_BUILD
            cin.ignore();
        #endif
        return 1;
    }

    uint32_t x_max,y_max,z_max;
    DFHack::Maps * Maps = DF->getMaps();
    DFHack::Gui * Gui = DF->getGui();

    // init the map
    if(!Maps->Start())
    {
        cerr << "Can't init map. Make sure you have a map loaded in DF." << endl;
        DF->Detach();
        #ifndef LINUX_BUILD
            cin.ignore();
        #endif
        return 1;
    }

    int32_t cx, cy, cz;
    Maps->getSize(x_max,y_max,z_max);
    uint32_t tx_max = x_max * 16;
    uint32_t ty_max = y_max * 16;

    Gui->getCursorCoords(cx,cy,cz);
    while(cx == -30000)
    {
        cerr << "Cursor is not active. Point the cursor at a vein." << endl;
        DF->Resume();
        cin.ignore();
        DF->Suspend();
        Gui->getCursorCoords(cx,cy,cz);
    }
    DFHack::DFCoord xy ((uint32_t)cx,(uint32_t)cy,cz);
    if(xy.x == 0 || xy.x == tx_max - 1 || xy.y == 0 || xy.y == ty_max - 1)
    {
        cerr << "I won't dig the borders. That would be cheating!" << endl;
        DF->Detach();
        #ifndef LINUX_BUILD
            cin.ignore();
        #endif
        return 1;
    }
    MapCache * MCache = new MapCache(Maps);

    DFHack::t_designation des = MCache->designationAt(xy);
    int16_t tt = MCache->tiletypeAt(xy);
    int16_t veinmat = MCache->veinMaterialAt(xy);

    if( veinmat == -1 )
    {
        cerr << "This tile is non-vein. Bye :)" << endl;
        delete MCache;
        DF->Detach();
        #ifndef LINUX_BUILD
            cin.ignore();
        #endif
        return 1;
    }
    printf("%d/%d/%d tiletype: %d, veinmat: %d, designation: 0x%x ... DIGGING!\n", cx,cy,cz, tt, veinmat, des.whole);
    stack <DFHack::DFCoord> flood;
    flood.push(xy);


    while( !flood.empty() )
    {
        DFHack::DFCoord current = flood.top();
        flood.pop();
        int16_t vmat2 = MCache->veinMaterialAt(current);
        tt = MCache->tiletypeAt(current);
        if(!DFHack::isWallTerrain(tt))
            continue;
        if(vmat2!=veinmat)
            continue;

        // found a good tile, dig+unset material
        DFHack::t_designation des = MCache->designationAt(current);
        DFHack::t_designation des_minus;
        DFHack::t_designation des_plus;
        des_plus.whole = des_minus.whole = 0;
        int16_t vmat_minus = -1;
        int16_t vmat_plus = -1;
        bool below = 0;
        bool above = 0;
        if(updown)
        {
            if(MCache->testCoord(current-1))
            {
                below = 1;
                des_minus = MCache->designationAt(current-1);
                vmat_minus = MCache->veinMaterialAt(current-1);
            }

            if(MCache->testCoord(current+1))
            {
                above = 1;
                des_plus = MCache->designationAt(current+1);
                vmat_plus = MCache->veinMaterialAt(current+1);
            }
        }
        if(MCache->testCoord(current))
        {
            MCache->clearMaterialAt(current);
            if(current.x < tx_max - 2)
            {
                flood.push(DFHack::DFCoord(current.x + 1, current.y, current.z));
                if(current.y < ty_max - 2)
                {
                    flood.push(DFHack::DFCoord(current.x + 1, current.y + 1,current.z));
                    flood.push(DFHack::DFCoord(current.x, current.y + 1,current.z));
                }
                if(current.y > 1)
                {
                    flood.push(DFHack::DFCoord(current.x + 1, current.y - 1,current.z));
                    flood.push(DFHack::DFCoord(current.x, current.y - 1,current.z));
                }
            }
            if(current.x > 1)
            {
                flood.push(DFHack::DFCoord(current.x - 1, current.y,current.z));
                if(current.y < ty_max - 2)
                {
                    flood.push(DFHack::DFCoord(current.x - 1, current.y + 1,current.z));
                    flood.push(DFHack::DFCoord(current.x, current.y + 1,current.z));
                }
                if(current.y > 1)
                {
                    flood.push(DFHack::DFCoord(current.x - 1, current.y - 1,current.z));
                    flood.push(DFHack::DFCoord(current.x, current.y - 1,current.z));
                }
            }
            if(updown)
            {
                if(current.z > 0 && below && vmat_minus == vmat2)
                {
                    flood.push(current-1);

                    if(des_minus.bits.dig == DFHack::designation_d_stair)
                        des_minus.bits.dig = DFHack::designation_ud_stair;
                    else
                        des_minus.bits.dig = DFHack::designation_u_stair;
                    MCache->setDesignationAt(current-1,des_minus);

                    des.bits.dig = DFHack::designation_d_stair;
                }
                if(current.z < z_max - 1 && above && vmat_plus == vmat2)
                {
                    flood.push(current+ 1);

                    if(des_plus.bits.dig == DFHack::designation_u_stair)
                        des_plus.bits.dig = DFHack::designation_ud_stair;
                    else
                        des_plus.bits.dig = DFHack::designation_d_stair;
                    MCache->setDesignationAt(current+1,des_plus);

                    if(des.bits.dig == DFHack::designation_d_stair)
                        des.bits.dig = DFHack::designation_ud_stair;
                    else
                        des.bits.dig = DFHack::designation_u_stair;
                }
            }
            if(des.bits.dig == DFHack::designation_no)
                des.bits.dig = DFHack::designation_default;
            MCache->setDesignationAt(current,des);
        }
    }
    MCache->WriteAll();
    delete MCache;
    DF->Detach();
    #ifndef LINUX_BUILD
        cout << "Done. Press any key to continue" << endl;
        cin.ignore();
    #endif
    return 0;
}
示例#4
0
文件: vdig.cpp 项目: gsvslto/dfhack
DFhackCExport command_result vdig (Core * c, vector <string> & parameters)
{
    uint32_t x_max,y_max,z_max;
    bool updown = false;
    for(int i = 0; i < parameters.size();i++)
    {
        if(parameters.size() && parameters[0]=="x")
            updown = true;
        else if(parameters[i] == "help" || parameters[i] == "?")
        {
            c->con.print("Designates a whole vein under the cursor for digging.\n"
                         "Options:\n"
                         "x        - follow veins through z-levels with stairs.\n"
            );
            return CR_OK;
        }
    }

    Console & con = c->con;

    c->Suspend();
    DFHack::Maps * Maps = c->getMaps();
    DFHack::Gui * Gui = c->getGui();
    // init the map
    if(!Maps->Start())
    {
        con.printerr("Can't init map. Make sure you have a map loaded in DF.\n");
        c->Resume();
        return CR_FAILURE;
    }

    int32_t cx, cy, cz;
    Maps->getSize(x_max,y_max,z_max);
    uint32_t tx_max = x_max * 16;
    uint32_t ty_max = y_max * 16;
    Gui->getCursorCoords(cx,cy,cz);
    while(cx == -30000)
    {
        con.printerr("Cursor is not active. Point the cursor at a vein.\n");
        c->Resume();
        return CR_FAILURE;
    }
    DFHack::DFCoord xy ((uint32_t)cx,(uint32_t)cy,cz);
    if(xy.x == 0 || xy.x == tx_max - 1 || xy.y == 0 || xy.y == ty_max - 1)
    {
        con.printerr("I won't dig the borders. That would be cheating!\n");
        c->Resume();
        return CR_FAILURE;
    }
    MapExtras::MapCache * MCache = new MapExtras::MapCache(Maps);
    DFHack::t_designation des = MCache->designationAt(xy);
    int16_t tt = MCache->tiletypeAt(xy);
    int16_t veinmat = MCache->veinMaterialAt(xy);
    if( veinmat == -1 )
    {
        con.printerr("This tile is not a vein.\n");
        delete MCache;
        c->Resume();
        return CR_FAILURE;
    }
    con.print("%d/%d/%d tiletype: %d, veinmat: %d, designation: 0x%x ... DIGGING!\n", cx,cy,cz, tt, veinmat, des.whole);
    stack <DFHack::DFCoord> flood;
    flood.push(xy);

    while( !flood.empty() )
    {
        DFHack::DFCoord current = flood.top();
        flood.pop();
        int16_t vmat2 = MCache->veinMaterialAt(current);
        tt = MCache->tiletypeAt(current);
        if(!DFHack::isWallTerrain(tt))
            continue;
        if(vmat2!=veinmat)
            continue;

        // found a good tile, dig+unset material
        DFHack::t_designation des = MCache->designationAt(current);
        DFHack::t_designation des_minus;
        DFHack::t_designation des_plus;
        des_plus.whole = des_minus.whole = 0;
        int16_t vmat_minus = -1;
        int16_t vmat_plus = -1;
        bool below = 0;
        bool above = 0;
        if(updown)
        {
            if(MCache->testCoord(current-1))
            {
                below = 1;
                des_minus = MCache->designationAt(current-1);
                vmat_minus = MCache->veinMaterialAt(current-1);
            }

            if(MCache->testCoord(current+1))
            {
                above = 1;
                des_plus = MCache->designationAt(current+1);
                vmat_plus = MCache->veinMaterialAt(current+1);
            }
        }
        if(MCache->testCoord(current))
        {
            MCache->clearMaterialAt(current);
            if(current.x < tx_max - 2)
            {
                flood.push(DFHack::DFCoord(current.x + 1, current.y, current.z));
                if(current.y < ty_max - 2)
                {
                    flood.push(DFHack::DFCoord(current.x + 1, current.y + 1,current.z));
                    flood.push(DFHack::DFCoord(current.x, current.y + 1,current.z));
                }
                if(current.y > 1)
                {
                    flood.push(DFHack::DFCoord(current.x + 1, current.y - 1,current.z));
                    flood.push(DFHack::DFCoord(current.x, current.y - 1,current.z));
                }
            }
            if(current.x > 1)
            {
                flood.push(DFHack::DFCoord(current.x - 1, current.y,current.z));
                if(current.y < ty_max - 2)
                {
                    flood.push(DFHack::DFCoord(current.x - 1, current.y + 1,current.z));
                    flood.push(DFHack::DFCoord(current.x, current.y + 1,current.z));
                }
                if(current.y > 1)
                {
                    flood.push(DFHack::DFCoord(current.x - 1, current.y - 1,current.z));
                    flood.push(DFHack::DFCoord(current.x, current.y - 1,current.z));
                }
            }
            if(updown)
            {
                if(current.z > 0 && below && vmat_minus == vmat2)
                {
                    flood.push(current-1);

                    if(des_minus.bits.dig == DFHack::designation_d_stair)
                        des_minus.bits.dig = DFHack::designation_ud_stair;
                    else
                        des_minus.bits.dig = DFHack::designation_u_stair;
                    MCache->setDesignationAt(current-1,des_minus);

                    des.bits.dig = DFHack::designation_d_stair;
                }
                if(current.z < z_max - 1 && above && vmat_plus == vmat2)
                {
                    flood.push(current+ 1);

                    if(des_plus.bits.dig == DFHack::designation_u_stair)
                        des_plus.bits.dig = DFHack::designation_ud_stair;
                    else
                        des_plus.bits.dig = DFHack::designation_d_stair;
                    MCache->setDesignationAt(current+1,des_plus);

                    if(des.bits.dig == DFHack::designation_d_stair)
                        des.bits.dig = DFHack::designation_ud_stair;
                    else
                        des.bits.dig = DFHack::designation_u_stair;
                }
            }
            if(des.bits.dig == DFHack::designation_no)
                des.bits.dig = DFHack::designation_default;
            MCache->setDesignationAt(current,des);
        }
    }
    MCache->WriteAll();
    c->Resume();
    return CR_OK;
}
示例#5
0
int main (void)
{
    uint32_t x_max,y_max,z_max;
    DFHack::designations40d designations;
    
    DFHack::ContextManager DFMgr("Memory.xml");
    DFHack::Context *DF;
    try
    {
        DF = DFMgr.getSingleContext();
        DF->Attach();
    }
    catch (exception& e)
    {
        cerr << e.what() << endl;
        #ifndef LINUX_BUILD
            cin.ignore();
        #endif
        return 1;
    }
    
    DFHack::Maps *Maps =DF->getMaps();
    DFHack::Gui *Gui =DF->getGui();
    // walk the map, save the hide bits, reveal.
    cout << "Pausing..." << endl;

    // horrible hack to make sure the pause is really set
    // preblem here is that we could be 'arriving' at the wrong time and DF could be in the middle of a frame.
    // that could mean that revealing, even with suspending DF's thread, would mean unleashing hell *in the same frame* 
    // this here hack sets the pause state, resumes DF, waits a second for it to enter the pause (I know, BS value.) and suspends.
    Gui->SetPauseState(true);
    DF->Resume();
    waitmsec(1000);
    DF->Suspend();

    // init the map
    if(!Maps->Start())
    {
        cerr << "Can't init map." << endl;
        #ifndef LINUX_BUILD
            cin.ignore();
        #endif
        return 1;
    }

    cout << "Revealing, please wait..." << endl;

    Maps->getSize(x_max,y_max,z_max);
    vector <hideblock> hidesaved;

    for(uint32_t x = 0; x< x_max;x++)
    {
        for(uint32_t y = 0; y< y_max;y++)
        {
            for(uint32_t z = 0; z< z_max;z++)
            {
                if(Maps->isValidBlock(x,y,z))
                {
                    hideblock hb;
                    hb.x = x;
                    hb.y = y;
                    hb.z = z;
                    // read block designations
                    Maps->ReadDesignations(x,y,z, &designations);
                    // change the hidden flag to 0
                    for (uint32_t i = 0; i < 16;i++) for (uint32_t j = 0; j < 16;j++)
                    {
                        hb.hiddens[i][j] = designations[i][j].bits.hidden;
                        designations[i][j].bits.hidden = 0;
                    }
                    hidesaved.push_back(hb);
                    // write the designations back
                    Maps->WriteDesignations(x,y,z, &designations);
                }
            }
        }
    }
    // FIXME: force game pause here!
    DF->Detach();
    cout << "Map revealed. The game has been paused for you." << endl;
    cout << "Unpausing can unleash the forces of hell!" << endl << endl;
    cout << "Press any key to unreveal." << endl;
    cout << "Close to keep the map revealed." << endl;
    cin.ignore();
    cout << "Unrevealing... please wait." << endl;
    // FIXME: do some consistency checks here!
    DF->Attach();
    Maps = DF->getMaps();
    Maps->Start();
    for(int i = 0; i < hidesaved.size();i++)
    {
        hideblock & hb = hidesaved[i];
        Maps->ReadDesignations(hb.x,hb.y,hb.z, &designations);
        for (uint32_t i = 0; i < 16;i++) for (uint32_t j = 0; j < 16;j++)
        {
            designations[i][j].bits.hidden = hb.hiddens[i][j];
        }
        Maps->WriteDesignations(hb.x,hb.y,hb.z, &designations);
    }
    #ifndef LINUX_BUILD
    cout << "Done. Press any key to continue" << endl;
    cin.ignore();
    #endif
    return 0;
}
示例#6
0
DFhackCExport command_result filltraffic(DFHack::Core * c, std::vector<std::string> & params)
{
	//Maximum map size.
	uint32_t x_max,y_max,z_max;
	//Source and target traffic types.
	e_traffic source = traffic_normal;
	e_traffic target = traffic_normal;
	//Option flags
	bool updown        = false;
	bool checkpit      = true;
	bool checkbuilding = true;

	//Loop through parameters
    for(int i = 0; i < params.size();i++)
    {
        if(params[i] == "help" || params[i] == "?")
        {
            c->con.print("Flood-fill selected traffic type from the cursor.\n"
                         "Traffic Type Codes:\n"
                         "\tH: High Traffic\n"
                         "\tN: Normal Traffic\n"
                         "\tL: Low Traffic\n"
                         "\tR: Restricted Traffic\n"
                         "Other Options:\n"
                         "\tX: Fill accross z-levels.\n"
                         "\tB: Include buildings and stockpiles.\n"
                         "\tP: Include empty space.\n"
                         "Example:\n"
                         "'filltraffic H' - When used in a room with doors,\n"
                         "                  it will set traffic to HIGH in just that room."
            );
            return CR_OK;
        }

        switch (toupper(params[i][0]))
        {
            case 'H':
                target = traffic_high; break;
            case 'N':
                target = traffic_normal; break;
            case 'L':
                target = traffic_low; break;
            case 'R':
                target = traffic_restricted; break;
            case 'X':
                updown = true; break;
            case 'B':
                checkbuilding = false; break;
            case 'P':
                checkpit = false; break;
        }
    }

    //Initialization.
    c->Suspend();

    DFHack::Maps * Maps = c->getMaps();
    DFHack::Gui * Gui = c->getGui();
    // init the map
    if(!Maps->Start())
    {
        c->con.printerr("Can't init map. Make sure you have a map loaded in DF.\n");
        c->Resume();
        return CR_FAILURE;
    }

	int32_t cx, cy, cz;
    Maps->getSize(x_max,y_max,z_max);
    uint32_t tx_max = x_max * 16;
    uint32_t ty_max = y_max * 16;
    Gui->getCursorCoords(cx,cy,cz);
    while(cx == -30000)
    {
        c->con.printerr("Cursor is not active.\n");
        c->Resume();
        return CR_FAILURE;
    }

    DFHack::DFCoord xy ((uint32_t)cx,(uint32_t)cy,cz);
    MapExtras::MapCache * MCache = new MapExtras::MapCache(Maps);

    DFHack::t_designation des = MCache->designationAt(xy);
    int16_t tt = MCache->tiletypeAt(xy);
    DFHack::t_occupancy oc;

    if (checkbuilding)
        oc = MCache->occupancyAt(xy);

    source = des.bits.traffic;
    if(source == target)
    {
        c->con.printerr("This tile is already set to the target traffic type.\n");
        delete MCache;
        c->Resume();
        return CR_FAILURE;
    }

    if(DFHack::isWallTerrain(tt))
    {
        c->con.printerr("This tile is a wall. Please select a passable tile.\n");
        delete MCache;
        c->Resume();
        return CR_FAILURE;
    }

	if(checkpit && DFHack::isOpenTerrain(tt))
	{
		c->con.printerr("This tile is a hole. Please select a passable tile.\n");
        delete MCache;
        c->Resume();
        return CR_FAILURE;
	}

	if(checkbuilding && oc.bits.building)
	{
		c->con.printerr("This tile contains a building. Please select an empty tile.\n");
        delete MCache;
        c->Resume();
        return CR_FAILURE;
	}

	c->con.print("%d/%d/%d  ... FILLING!\n", cx,cy,cz);

	//Naive four-way or six-way flood fill with possible tiles on a stack.
	stack <DFHack::DFCoord> flood;
	flood.push(xy);

	while(!flood.empty())
	{
		xy = flood.top();
		flood.pop();

		des = MCache->designationAt(xy);
		if (des.bits.traffic != source) continue;

		tt = MCache->tiletypeAt(xy);

		if(DFHack::isWallTerrain(tt)) continue;
		if(checkpit && DFHack::isOpenTerrain(tt)) continue;

		if (checkbuilding)
		{
			oc = MCache->occupancyAt(xy);
			if(oc.bits.building) continue;
		}

		//This tile is ready.  Set its traffic level and add surrounding tiles.
		if (MCache->testCoord(xy))
		{
			des.bits.traffic = target;
			MCache->setDesignationAt(xy,des);

			if (xy.x > 0)
			{
				flood.push(DFHack::DFCoord(xy.x - 1, xy.y, xy.z));
			}
			if (xy.x < tx_max - 1)
			{
				flood.push(DFHack::DFCoord(xy.x + 1, xy.y, xy.z));
			}
			if (xy.y > 0)
			{
				flood.push(DFHack::DFCoord(xy.x, xy.y - 1, xy.z));
			}
			if (xy.y < ty_max - 1)
			{
				flood.push(DFHack::DFCoord(xy.x, xy.y + 1, xy.z));
			}

			if (updown)
			{
				if (xy.z > 0 && DFHack::LowPassable(tt))
				{
					flood.push(DFHack::DFCoord(xy.x, xy.y, xy.z - 1));
				}
				if (xy.z < z_max && DFHack::HighPassable(tt))
				{
					flood.push(DFHack::DFCoord(xy.x, xy.y, xy.z + 1));
				}
			}

		}
	}

	MCache->WriteAll();
    c->Resume();
    return CR_OK;
}
示例#7
0
command_result df_tiles (Core * c, vector <string> & parameters)
{
    int32_t x,y,z;
    uint32_t x_max,y_max,z_max;
    DFHack::Maps * Maps;
    DFHack::Gui * Position;
    Brush * brush = new RectangleBrush(1,1);

    Maps = c->getMaps();
    Maps->Start();
    Maps->getSize(x_max,y_max,z_max);
    Position = c->getGui();

    string command = "";
    if(command=="help" || command == "?")
    {
        c->con.print
        (
            "Usage: This command sets the properties of the tile painter brush\n"
            "       It is best used from the console, or as an alias bound to a hotkey\n"
            "       After setting the brush\n"
            "\n"
            "Modes:\n"
            "none          - nothing, the default"
            "magma [0-7]   - magma, accepts depth\n"
            "water [0-7]   - water\n"
            "obsidian      - obsidian wall\n"
            "obsfloor      - obsidian floors\n"
            "obsramp       - obsidian ramp (forces 1 z-level brush)\n"
            "riversource   - an endless source of water (floor tile)\n"
            "type ###      - plain tiletype painter. For a list of tile types see:\n"
            "                http://df.magmawiki.com/index.php/DF2010:Tile_types_in_DF_memory\n"
            "\n"
            "Set-Modes (only for magma/water):\n"
            "add           - set liquid level everywhere\n"
            "keep          - set liquid level only where liquids are already present\n"
            "\n"
            "Brush:\n"
            "point         - single tile [p]\n"
            "#x#[x#]       - block with cursor at bottom north-west [r]\n"
            "                (any place, any size)\n"
            "                Example:"
            "                3x3x2 = rectangle 3x3 x2 z-levels\n"
            "                The z-level part is optional - ommiting it is\n"
            "                the same as setting it to 1.\n"
            "h#x#[x#]      - Same as previous, only the rectangle is 'hollow'.\n"
            "block         - DF map block with cursor in it\n"
            "                (regular spaced 16x16x1 blocks)\n"
            "column        - Column from cursor, up through free space\n"
            "line          - A line between two points.\n"
            "circle [#]    - A filled circle, optional # specifies radius in tiles.\n"
            "hcircle [#,#] - A hollow circle (ring). First # specifies radius\n"
            "                second # ring thickness in tiles.\n"
            "\n"
            "Other:\n"
            "help or ?     - print this list of commands\n"
            "paint         - same effect as if you also the 'paint' command at the same time.\n"
            "\n"
        );
    }
    else if(command == "m")
    {
        mode = "magma";
    }
    else if(command == "o")
    {
        mode = "obsidian";
    }
    else if(command == "of")
    {
        mode = "obsidian_floor";
    }
    else if(command == "w")
    {
        mode = "water";
    }
    else if(command == "f")
    {
        mode = "flowbits";
    }
    else if(command == "rs")
    {
        mode = "riversource";
    }
    else if(command == "point" || command == "p")
    {
        delete brush;
        brushname = "point";
        brush = new RectangleBrush(1,1);
    }
    else if(command == "range" || command == "r")
    {
        cout << " :set range width<" << width << "># ";
        getline(cin, command);
        width = command == "" ? width : atoi (command.c_str());
        if(width < 1) width = 1;

        cout << " :set range height<" << height << "># ";
        getline(cin, command);
        height = command == "" ? height : atoi (command.c_str());
        if(height < 1) height = 1;

        cout << " :set range z-levels<" << z_levels << "># ";
        getline(cin, command);
        z_levels = command == "" ? z_levels : atoi (command.c_str());
        if(z_levels < 1) z_levels = 1;
        delete brush;
        if(width == 1 && height == 1 && z_levels == 1)
        {
            brushname="point";
        }
        else
        {
            brushname = "range";
        }
        brush = new RectangleBrush(width,height,z_levels,0,0,0);
    }
    else if(command == "block")
    {
        delete brush;
        brushname = "block";
        brush = new BlockBrush();
    }
    else if(command == "column")
    {
        delete brush;
        brushname = "column";
        brush = new ColumnBrush();
    }
    else if(command == "q")
    {
        end = true;
    }
    else if(command == "f+")
    {
        flowmode = "f+";
    }
    else if(command == "f-")
    {
        flowmode = "f-";
    }
    else if(command == "f.")
    {
        flowmode = "f.";
    }
    else if(command == "s+")
    {
        setmode = "s+";
    }
    else if(command == "s-")
    {
        setmode = "s-";
    }
    else if(command == "s.")
    {
        setmode = "s.";
    }
    // blah blah, bad code, bite me.
    else if(command == "0")
        amount = 0;
    else if(command == "1")
        amount = 1;
    else if(command == "2")
        amount = 2;
    else if(command == "3")
        amount = 3;
    else if(command == "4")
        amount = 4;
    else if(command == "5")
        amount = 5;
    else if(command == "6")
        amount = 6;
    else if(command == "7")
        amount = 7;
    else if(command.empty())
    {
        DF->Suspend();
        do
        {
            if(!Maps->Start())
            {
                cout << "Can't see any DF map loaded." << endl;
                break;
            }
            if(!Position->getCursorCoords(x,y,z))
            {
                cout << "Can't get cursor coords! Make sure you have a cursor active in DF." << endl;
                break;
            }
            cout << "cursor coords: " << x << "/" << y << "/" << z << endl;
            MapCache mcache(Maps);
            DFHack::DFCoord cursor(x,y,z);
            coord_vec all_tiles = brush->points(mcache,cursor);
            cout << "working..." << endl;
            if(mode == "obsidian")
            {
                coord_vec::iterator iter = all_tiles.begin();
                while (iter != all_tiles.end())
                {
                    mcache.setTiletypeAt(*iter, 331);
                    mcache.setTemp1At(*iter,10015);
                    mcache.setTemp2At(*iter,10015);
                    DFHack::t_designation des = mcache.designationAt(*iter);
                    des.bits.flow_size = 0;
                    mcache.setDesignationAt(*iter, des);
                    iter ++;
                }
            }
            if(mode == "obsidian_floor")
            {
                coord_vec::iterator iter = all_tiles.begin();
                while (iter != all_tiles.end())
                {
                    mcache.setTiletypeAt(*iter, 340);
                    iter ++;
                }
            }
            else if(mode == "riversource")
            {
                set <Block *> seen_blocks;
                coord_vec::iterator iter = all_tiles.begin();
                while (iter != all_tiles.end())
                {
                    mcache.setTiletypeAt(*iter, 90);

                    DFHack::t_designation a = mcache.designationAt(*iter);
                    a.bits.liquid_type = DFHack::liquid_water;
                    a.bits.liquid_static = false;
                    a.bits.flow_size = 7;
                    mcache.setTemp1At(*iter,10015);
                    mcache.setTemp2At(*iter,10015);
                    mcache.setDesignationAt(*iter,a);

                    Block * b = mcache.BlockAt((*iter)/16);
                    DFHack::t_blockflags bf = b->BlockFlags();
                    bf.bits.liquid_1 = true;
                    bf.bits.liquid_2 = true;
                    b->setBlockFlags(bf);

                    iter++;
                }
            }
            else if(mode== "magma" || mode== "water" || mode == "flowbits")
            {
                set <Block *> seen_blocks;
                coord_vec::iterator iter = all_tiles.begin();
                while (iter != all_tiles.end())
                {
                    DFHack::DFCoord current = *iter;
                    DFHack::t_designation des = mcache.designationAt(current);
                    uint16_t tt = mcache.tiletypeAt(current);
                    DFHack::naked_designation & flow = des.bits;
                    // don't put liquids into places where they don't belong...
                    if(!DFHack::FlowPassable(tt))
                    {
                        iter++;
                        continue;
                    }
                    if(mode != "flowbits")
                    {
                        if(setmode == "s.")
                        {
                            flow.flow_size = amount;
                        }
                        else if(setmode == "s+")
                        {
                            if(flow.flow_size < amount)
                                flow.flow_size = amount;
                        }
                        else if(setmode == "s-")
                        {
                            if (flow.flow_size > amount)
                                flow.flow_size = amount;
                        }
                        if(amount != 0 && mode == "magma")
                        {
                            flow.liquid_type =  DFHack::liquid_magma;
                            mcache.setTemp1At(current,12000);
                            mcache.setTemp2At(current,12000);
                        }
                        else if(amount != 0 && mode == "water")
                        {
                            flow.liquid_type =  DFHack::liquid_water;
                            mcache.setTemp1At(current,10015);
                            mcache.setTemp2At(current,10015);
                        }
                        else if(amount == 0 && (mode == "water" || mode == "magma"))
                        {
                            // reset temperature to sane default
                            mcache.setTemp1At(current,10015);
                            mcache.setTemp2At(current,10015);
                        }
                        mcache.setDesignationAt(current,des);
                    }
                    seen_blocks.insert(mcache.BlockAt((*iter) / 16));
                    iter++;
                }
                set <Block *>::iterator biter = seen_blocks.begin();
                while (biter != seen_blocks.end())
                {
                    DFHack::t_blockflags bflags = (*biter)->BlockFlags();
                    if(flowmode == "f+")
                    {
                        bflags.bits.liquid_1 = true;
                        bflags.bits.liquid_2 = true;
                        (*biter)->setBlockFlags(bflags);
                    }
                    else if(flowmode == "f-")
                    {
                        bflags.bits.liquid_1 = false;
                        bflags.bits.liquid_2 = false;
                        (*biter)->setBlockFlags(bflags);
                    }
                    else
                    {
                        cout << "flow bit 1 = " << bflags.bits.liquid_1 << endl;
                        cout << "flow bit 2 = " << bflags.bits.liquid_2 << endl;
                    }
                    biter ++;
                }
            }
            if(mcache.WriteAll())
                cout << "OK" << endl;
            else
                cout << "Something failed horribly! RUN!" << endl;
            Maps->Finish();
        } while (0);
    }
    else
    {
        cout << command << " : unknown command." << endl;
    }
    return CR_OK;
}
示例#8
0
int main (int argc, char *argv[])
{
    bool print_refs = false;
    bool print_hex = false;
    bool print_acc = false;

    for(int i = 1; i < argc; i++)
    {
        char *arg = argv[i];
        if (arg[0] != '-')
            continue;

        for (; *arg; arg++) {
            switch (arg[0]) {
            case 'r':
                print_refs = true;
                break;
            case 'x':
                print_hex = true;
                break;
            case 'a':
                print_acc = true;
                break;
            }
        }
    }


    DFHack::Process * p;
    DFHack::ContextManager DFMgr("Memory.xml");
    DFHack::Context * DF;
    try
    {
        DF = DFMgr.getSingleContext();
        DF->Attach();
    }
    catch (exception& e)
    {
        cerr << e.what() << endl;
#ifndef LINUX_BUILD
        cin.ignore();
#endif
        return 1;
    }
    DFHack::Materials * Materials = DF->getMaterials();
    Materials->ReadAllMaterials();

    DFHack::Gui * Gui = DF->getGui();

    DFHack::Items * Items = DF->getItems();
    Items->Start();

    DFHack::VersionInfo * mem = DF->getMemoryInfo();
    p = DF->getProcess();
    int32_t x,y,z;
    Gui->getCursorCoords(x,y,z);

    std::vector<uint32_t> p_items;
    Items->readItemVector(p_items);
    uint32_t size = p_items.size();

    // FIXME: tools should never be exposed to DFHack internals!
    DFHack::OffsetGroup* itemGroup = mem->getGroup("Items");
    uint32_t ref_vector = itemGroup->getOffset("item_ref_vector");

    for(size_t i = 0; i < size; i++)
    {
        DFHack::dfh_item itm;
        memset(&itm, 0, sizeof(DFHack::dfh_item));
        Items->readItem(p_items[i],itm);

        if (x != -30000
                && !(itm.base.x == x && itm.base.y == y && itm.base.z == z
                     && itm.base.flags.on_ground
                     && !itm.base.flags.in_chest
                     && !itm.base.flags.in_inventory
                     && !itm.base.flags.in_building))
            continue;

        printf(
            "%5d: %08x %6d %08x (%d,%d,%d) #%08x [%d] *%d %s - %s\n",
            i, itm.origin, itm.id, itm.base.flags.whole,
            itm.base.x, itm.base.y, itm.base.z,
            itm.base.vtable,
            itm.wear_level,
            itm.quantity,
            Items->getItemClass(itm).c_str(),
            Items->getItemDescription(itm, Materials).c_str()
        );

        if (print_hex)
            hexdump(DF,p_items[i],0x300);

        if (print_acc)
            cout << Items->dumpAccessors(itm) << endl;

        if (print_refs) {
            DFHack::DfVector<uint32_t> p_refs(p, itm.origin + ref_vector);
            for (size_t j = 0; j < p_refs.size(); j++) {
                uint32_t vptr = p->readDWord(p_refs[j]);
                uint32_t val = p->readDWord(p_refs[j]+4);
                printf("\t-> %d \t%s\n", int(val), p->readClassName(vptr).c_str());
            }
        }
    }
#ifndef LINUX_BUILD
    cout << "Done. Press any key to continue" << endl;
    cin.ignore();
#endif
    return 0;
}
示例#9
0
int main (void)
{
    int32_t x,y,z,tx,ty;
    //DFHack::designations40d designations;
    DFHack::tiletypes40d tiles;
    //DFHack::t_temperatures temp1,temp2;
    uint32_t x_max,y_max,z_max;
    int32_t oldT, newT;
	int count, dirty;

	//Brush defaults
	DFHack::TileShape BrushClass = DFHack::WALL;
	DFHack::TileMaterial BrushMat = DFHack::tilematerial_invalid;
	int BrushType = -1;

    DFHack::ContextManager DFMgr("Memory.xml");
    DFHack::Context *DF;
    DFHack::Maps * Maps;
    DFHack::Gui * Gui;
    try
    {
        DF=DFMgr.getSingleContext();
        DF->Attach();
        Maps = DF->getMaps();
        Maps->Start();
        Maps->getSize(x_max,y_max,z_max);
        Gui = DF->getGui();
    }
    catch (exception& e)
    {
        cerr << e.what() << endl;
        #ifndef LINUX_BUILD
            cin.ignore();
        #endif
        return 1;
    }
    bool end = false;
    cout << "Welcome to the Tile Drawing tool.\nType 'help' or ? for a list of available commands, 'q' to quit" << endl;
    string mode = "wall";
    string command = "";

	while(!end)
	{
        DF->Resume();

		cout << endl << ":";
		getline(cin, command);
		int ch = command[0];
		if(command.length()<=0) ch=0;
		if( ((int)command.find("help")) >=0 ) ch='?';  //under windows, find was casting unsigned!
		switch(ch)
        {
		case '?':
            cout << "Modes:" << endl
				 << "O             - draw Open Space" << endl
                 << "M             - draw material only (shape unchanged)" << endl
                 << "m number      - use Material value entered" << endl
                 << "r             - use Rock/stone material" << endl
                 << "l             - use Soil material" << endl
                 << "v             - use Vein material" << endl
                 << "H             - draw tile shape only (material unchanged)" << endl
				 << "h number      - draw Tile Shape value entered" << endl
                 << "w             - draw Wall tiles" << endl
                 << "f             - draw Floor tiles" << endl
				 << "t number      - draw exact tile type entered" << endl
                 << "Commands:" << endl
                 << "p             - print tile shapes and materials, and current brush" << endl
                 << "P             - print all tile types" << endl
                 << "q             - quit" << endl
                 << "help OR ?     - print this list of commands" << endl
                 << "d             - being drawing" << endl
                 << endl
                 << "Usage:\nChoose a mode (default is walls), then enter 'd' to being drawing.\nMove the cursor in DF wherever you want to draw.\nPress any key to pause drawing." << endl;
			break;
		case 'p':
			//Classes
			printf("\nTile Type Classes:\n");
			for(int i=0;i<DFHack::tileshape_count;++i)
			{
				printf("%4i ; %s\n", i, DFHack::TileShapeString[i] ,0 );
			}
			//Materials
			printf("\nTile Type Materials:\n");
			for(int i=0;i<DFHack::tilematerial_count;++i)
			{
				printf("%4i ; %s\n", i, DFHack::TileMaterialString[i] ,0 );
			}
			//fall through...
		case 10:
		case 13:
		case 0:
			//Print current cursor & brush settings.
			cout << "\nCurrent Brush:\n";
			cout << "tile = ";
			if(BrushClass<0) cout<<"(not drawing)"; else cout<<DFHack::TileShapeString[BrushClass]; cout << endl;
			cout << "mat  = ";
			if(BrushMat<0) cout<<"(not drawing)"; else cout<<DFHack::TileMaterialString[BrushMat]; cout << endl;
			cout << "type = ";
			if(BrushType<0){
				cout<<"(not drawing)";
			}else{
				printtiletype(BrushType);
			}
			break;
		case 'P':
			cout << "\nAll Valid Tile Types:\n";
			for(int i=0;i<TILE_TYPE_ARRAY_LENGTH;++i)
			{
				if( DFHack::tileTypeTable[i].name )
					printtiletype(i);
			}
		case 'w':
			BrushType=-1;
            BrushClass = DFHack::WALL;
            cout << "Tile brush shape set to Wall." << endl;
			break;
		case 'f':
			BrushType=-1;
            BrushClass = DFHack::FLOOR;
            cout << "Tile brush shape set to Floor." << endl;
			break;
		case 'h':
			BrushType=-1;
			BrushClass = (DFHack::TileShape)atol( command.c_str()+1 );
            cout << "Tile brush shape set to " << BrushClass << endl;
			break;
		case 'M':
            BrushClass = DFHack::tileshape_invalid;
            cout << "Tile brush will not draw tile shape." << endl;
			break;
		case 'r':
			BrushType=-1;
            BrushMat = DFHack::STONE;
            cout << "Tile brush material set to Rock." << endl;
			break;
		case 'l':
			BrushType=-1;
            BrushMat = DFHack::SOIL;
            cout << "Tile brush material set to Soil." << endl;
			break;
		case 'v':
			BrushType=-1;
            BrushMat = DFHack::VEIN;
            cout << "Tile brush material set to Vein." << endl;
			break;
		case 'm':
			BrushType=-1;
			BrushMat = (DFHack::TileMaterial)atol( command.c_str()+1 );
            cout << "Tile brush material set to " << BrushMat << endl;
			break;
		case 'H':
            BrushMat = DFHack::tilematerial_invalid;
            cout << "Tile brush will not draw material." << endl;
			break;
		case 'O':
			BrushType=-1;
			BrushClass = DFHack::EMPTY;
			BrushMat = DFHack::AIR;
            cout << "Tile brush will draw Open Space." << endl;
			break;
		case 't':
			BrushClass = DFHack::tileshape_invalid ;
			BrushMat = DFHack::tilematerial_invalid;
			BrushType = atol( command.c_str()+1 );
			cout << "Tile brush type set to:" << endl;
			printtiletype(BrushType);
			break;
		case 'q':
            end = true;
            cout << "Bye!" << endl;
			break;
		case 'd':
        {
			count=0;
			cout << "Beginning to draw at cursor." << endl << "Press any key to stop drawing." << endl;
            //DF->Suspend();
			kbhit(); //throw away, just to be sure.
            for(;;)
            {
				if(!Maps->Start())
                {
                    cout << "Can't see any DF map loaded." << endl;
                    break;
                }
                if(!Gui->getCursorCoords(x,y,z))
                {
                    cout << "Can't get cursor coords! Make sure you have a cursor active in DF." << endl;
                    break;
                }
                //cout << "cursor coords: " << x << "/" << y << "/" << z << endl;
				tx=x%16; ty=y%16;

                if(!Maps->isValidBlock(x/16,y/16,z))
                {
                    cout << "Invalid block." << endl;
                    break;
                }

				//Read the tiles.
				dirty=0;
				Maps->ReadTileTypes((x/16),(y/16),z, &tiles);
                oldT = tiles[tx][ty];

				newT = -1;
				if( 0<BrushType ){
					//Explicit tile type set.  Trust the user.
					newT = BrushType;
				}else if( 0==BrushMat && 0==BrushClass ){
					//Special case, Empty Air.
					newT = 32;
				}else if( BrushMat>=0 && BrushClass>=0 && ( BrushClass != DFHack::tileTypeTable[oldT].shape || BrushMat != DFHack::tileTypeTable[oldT].material) ){
					//Set tile material and class
					newT = DFHack::findTileType(BrushClass,BrushMat, DFHack::tileTypeTable[oldT].variant , DFHack::tileTypeTable[oldT].special , DFHack::tileTypeTable[oldT].direction );
					if(newT<0) newT = DFHack::findTileType(BrushClass,BrushMat, DFHack::tilevariant_invalid, DFHack::tileTypeTable[oldT].special , DFHack::tileTypeTable[oldT].direction );
					if(newT<0) newT = DFHack::findTileType(BrushClass,BrushMat, DFHack::tilevariant_invalid , DFHack::tileTypeTable[oldT].special , (uint32_t)0 );
				}else if( BrushMat<0 && BrushClass>=0 && BrushClass != DFHack::tileTypeTable[oldT].shape ){
					//Set current tile class only, as accurately as can be expected
                    newT = DFHack::findSimilarTileType(oldT,BrushClass);
				}else if( BrushClass<0 && BrushMat>=0 && BrushMat != DFHack::tileTypeTable[oldT].material ){
					//Set current tile material only
					newT = DFHack::findTileType(DFHack::tileTypeTable[oldT].shape,BrushMat, DFHack::tileTypeTable[oldT].variant , DFHack::tileTypeTable[oldT].special , DFHack::tileTypeTable[oldT].direction );
					if(newT<0) newT = DFHack::findTileType(DFHack::tileTypeTable[oldT].shape,BrushMat, DFHack::tilevariant_invalid , DFHack::tileTypeTable[oldT].special , DFHack::tileTypeTable[oldT].direction );
					if(newT<0) newT = DFHack::findTileType(DFHack::tileTypeTable[oldT].shape,BrushMat, DFHack::tilevariant_invalid , DFHack::tileTypeTable[oldT].special , (uint32_t)0 );
				}
                //If no change, skip it (couldn't find a good tile type, or already what we want)
				if ( newT > 0 && oldT != newT ){
                    //Set new tile type
                    tiles[tx][ty] = newT;
                    dirty=-1;
				}
                //If anything was changed, write it all.
                if (dirty)
                {
                    //Maps->WriteDesignations(x/16,y/16,z/16, &designations);
                    Maps->WriteTileTypes(x/16,y/16,z, &tiles);
					printf("(%4d,%4d,%4d)",x,y,z);
                    ++count;
                }

                Maps->Finish();

				Sleep(10);
				if( kbhit() ) break;				
            }
			cin.clear();
			cout << endl << count << " tiles were drawn." << endl << "Drawing halted.  Entering command mode." << endl;
		}
			continue;
			break;
		default:
			cout << "Unknown command: " << command << endl;
		}

    }
    DF->Detach();
    #ifndef LINUX_BUILD
    cout << "Done. Press any key to continue" << endl;
    cin.ignore();
    #endif
    return 0;
}
示例#10
0
文件: plants.cpp 项目: kaypy/dfhack
/**
 * Book of Immolations, chapter 1, verse 35:
 * Armok emerged from the hellish depths and beheld the sunny realms for the first time.
 * And he cursed the plants and trees for their bloodless wood, turning them into ash and smoldering ruin.
 * Armok was pleased and great temples were built by the dwarves, for they shared his hatred for trees and plants.
 */
static command_result immolations (Core * c, do_what what, bool shrubs, bool trees, bool help)
{
    static const char * what1 = "destroys";
    static const char * what2 = "burns";
    if(help)
    {
        c->con.print("Without any options, this command %s a plant under the cursor.\n"
        "Options:\n"
        "shrubs   - affect all shrubs\n"
        "trees    - affect all trees\n"
        "all      - affect all plants\n",
        what == do_immolate? what2 : what1
        );
        return CR_OK;
    }
    c->Suspend();
    DFHack::Maps *maps = c->getMaps();
    if (!maps->Start())
    {
        c->con.printerr( "Cannot get map info!\n");
        c->Resume();
        return CR_FAILURE;
    }
    DFHack::Gui * Gui = c->getGui();
    uint32_t x_max, y_max, z_max;
    maps->getSize(x_max, y_max, z_max);
    MapExtras::MapCache map(maps);
    DFHack::Vegetation *veg = c->getVegetation();
    if (!veg->all_plants)
    {
        std::cerr << "Unable to read vegetation!" << std::endl;
        return CR_FAILURE;
    }
    if(shrubs || trees)
    {
        int destroyed = 0;
        for(size_t i = 0 ; i < veg->all_plants->size(); i++)
        {
            DFHack::df_plant *p = veg->all_plants->at(i);
            if(shrubs && p->is_shrub || trees && !p->is_shrub)
            {
                if (what == do_immolate)
                    p->is_burning = true;
                p->hitpoints = 0;
                destroyed ++;
            }
        }
        c->con.print("Praise Armok!\n");
    }
    else
    {
        int32_t x,y,z;
        if(Gui->getCursorCoords(x,y,z))
        {
            vector<DFHack::df_plant *> * alltrees;
            if(maps->ReadVegetation(x/16,y/16,z,alltrees))
            {
                bool didit = false;
                for(size_t i = 0 ; i < alltrees->size(); i++)
                {
                    DFHack::df_plant * tree = alltrees->at(i);
                    if(tree->x == x && tree->y == y && tree->z == z)
                    {
                        if(what == do_immolate)
                            tree->is_burning = true;
                        tree->hitpoints = 0;
                        didit = true;
                        break;
                    }
                }
                /*
                if(!didit)
                {
                    cout << "----==== There's NOTHING there! ====----" << endl;
                }
                */
            }
        }
        else
        {
            c->con.printerr("No mass destruction and no cursor...\n" );
        }
    }
    // Cleanup
    veg->Finish();
    maps->Finish();
    c->Resume();
    return CR_OK;
}
示例#11
0
文件: plants.cpp 项目: kaypy/dfhack
DFhackCExport command_result df_grow (Core * c, vector <string> & parameters)
{
    for(int i = 0; i < parameters.size();i++)
    {
        if(parameters[i] == "help" || parameters[i] == "?")
        {
            c->con.print("This command turns all living saplings into full-grown trees.\n");
            return CR_OK;
        }
    }
    c->Suspend();
    DFHack::Maps *maps = c->getMaps();
    Console & con = c->con;
    if (!maps->Start())
    {
        con.printerr("Cannot get map info!\n");
        c->Resume();
        return CR_FAILURE;
    }
    //maps->getSize(x_max, y_max, z_max);
    MapExtras::MapCache map(maps);
    DFHack::Vegetation *veg = c->getVegetation();
    if (!veg->all_plants)
    {
        con.printerr("Unable to read vegetation!\n");
        c->Resume();
        return CR_FAILURE;
    }
    DFHack::Gui *Gui = c->getGui();
    int32_t x,y,z;
    if(Gui->getCursorCoords(x,y,z))
    {
        vector<DFHack::df_plant *> * alltrees;
        if(maps->ReadVegetation(x/16,y/16,z,alltrees))
        {
            for(size_t i = 0 ; i < alltrees->size(); i++)
            {
                DFHack::df_plant * tree = alltrees->at(i);
                if(tree->x == x && tree->y == y && tree->z == z)
                {
                    if(DFHack::tileShape(map.tiletypeAt(DFHack::DFCoord(x,y,z))) == DFHack::SAPLING_OK)
                    {
                        tree->grow_counter = DFHack::sapling_to_tree_threshold;
                    }
                    break;
                }
            }
        }
    }
    else
    {
        int grown = 0;
        for(size_t i = 0 ; i < veg->all_plants->size(); i++)
        {
            DFHack::df_plant *p = veg->all_plants->at(i);
            uint16_t ttype = map.tiletypeAt(DFHack::DFCoord(p->x,p->y,p->z));
            if(!p->is_shrub && DFHack::tileShape(ttype) == DFHack::SAPLING_OK)
            {
                p->grow_counter = DFHack::sapling_to_tree_threshold;
            }
        }
    }

    // Cleanup
    veg->Finish();
    maps->Finish();
    c->Resume();
    return CR_OK;
}
示例#12
0
文件: probe.cpp 项目: lxnt/dfhack
command_result df_probe (Core * c, vector <string> & parameters)
{
    //bool showBlock, showDesig, showOccup, showTile, showMisc;
    Console & con = c->con;
    /*
    if (!parseOptions(parameters, showBlock, showDesig, showOccup,
                      showTile, showMisc))
    {
        con.printerr("Unknown parameters!\n");
        return CR_FAILURE;
    }
    */

    CoreSuspender suspend(c);

    DFHack::Gui *Gui = c->getGui();
    DFHack::Materials *Materials = c->getMaterials();
    DFHack::VersionInfo* mem = c->vinfo;
    std::vector<t_matglossInorganic> inorganic;
    bool hasmats = Materials->CopyInorganicMaterials(inorganic);

    if (!Maps::IsValid())
    {
        c->con.printerr("Map is not available!\n");
        return CR_FAILURE;
    }
    MapExtras::MapCache mc;

    int32_t regionX, regionY, regionZ;
    Maps::getPosition(regionX,regionY,regionZ);

    int32_t cursorX, cursorY, cursorZ;
    Gui->getCursorCoords(cursorX,cursorY,cursorZ);
    if(cursorX == -30000)
    {
        con.printerr("No cursor; place cursor over tile to probe.\n");
        return CR_FAILURE;
    }
    DFCoord cursor (cursorX,cursorY,cursorZ);

    uint32_t blockX = cursorX / 16;
    uint32_t tileX = cursorX % 16;
    uint32_t blockY = cursorY / 16;
    uint32_t tileY = cursorY % 16;

    MapExtras::Block * b = mc.BlockAt(cursor/16);
    if(!b && !b->valid)
    {
        con.printerr("No data.\n");
        return CR_OK;
    }
    mapblock40d & block = b->raw;
    con.print("block addr: 0x%x\n\n", block.origin);
/*
    if (showBlock)
    {
        con.print("block flags:\n");
        print_bits<uint32_t>(block.blockflags.whole,con);
        con.print("\n\n");
    }
*/
    df::tiletype tiletype = mc.tiletypeAt(cursor);
    df::tile_designation &des = block.designation[tileX][tileY];
/*
    if(showDesig)
    {
        con.print("designation\n");
        print_bits<uint32_t>(block.designation[tileX][tileY].whole,
                                con);
        con.print("\n\n");
    }

    if(showOccup)
    {
        con.print("occupancy\n");
        print_bits<uint32_t>(block.occupancy[tileX][tileY].whole,
                                con);
        con.print("\n\n");
    }
*/

    // tiletype
    con.print("tiletype: %d", tiletype);
    if(tileName(tiletype))
        con.print(" = %s",tileName(tiletype));
    con.print("\n");

    df::tiletype_shape shape = tileShape(tiletype);
    df::tiletype_material material = tileMaterial(tiletype);
    df::tiletype_special special = tileSpecial(tiletype);
    df::tiletype_variant variant = tileVariant(tiletype);
    con.print("%-10s: %4d %s\n","Class"    ,shape,
            ENUM_KEY_STR(tiletype_shape, shape));
    con.print("%-10s: %4d %s\n","Material" ,
            material, ENUM_KEY_STR(tiletype_material, material));
    con.print("%-10s: %4d %s\n","Special"  ,
            special, ENUM_KEY_STR(tiletype_special, special));
    con.print("%-10s: %4d %s\n"   ,"Variant"  ,
            variant, ENUM_KEY_STR(tiletype_variant, variant));
    con.print("%-10s: %s\n"    ,"Direction",
            tileDirection(tiletype).getStr());
    con.print("\n");

    con.print("temperature1: %d U\n",mc.temperature1At(cursor));
    con.print("temperature2: %d U\n",mc.temperature2At(cursor));

    // biome, geolayer
    con << "biome: " << des.bits.biome << std::endl;
    con << "geolayer: " << des.bits.geolayer_index
        << std::endl;
    int16_t base_rock = mc.baseMaterialAt(cursor);
    if(base_rock != -1)
    {
        con << "Layer material: " << dec << base_rock;
        if(hasmats)
            con << " / " << inorganic[base_rock].id
                << " / "
                << inorganic[base_rock].name
                << endl;
        else
            con << endl;
    }
    int16_t vein_rock = mc.veinMaterialAt(cursor);
    if(vein_rock != -1)
    {
        con << "Vein material (final): " << dec << vein_rock;
        if(hasmats)
            con << " / " << inorganic[vein_rock].id
                << " / "
                << inorganic[vein_rock].name
                << endl;
        else
            con << endl;
    }
    // liquids
    if(des.bits.flow_size)
    {
        if(des.bits.liquid_type == tile_liquid::Magma)
            con <<"magma: ";
        else con <<"water: ";
        con << des.bits.flow_size << std::endl;
    }
    if(des.bits.flow_forbid)
        con << "flow forbid" << std::endl;
    if(des.bits.pile)
        con << "stockpile?" << std::endl;
    if(des.bits.rained)
        con << "rained?" << std::endl;
    if(des.bits.smooth)
        con << "smooth?" << std::endl;
    if(des.bits.water_salt)
        con << "salty" << endl;
    if(des.bits.water_stagnant)
        con << "stagnant" << endl;

    #define PRINT_FLAG( X )  con.print("%-16s= %c\n", #X , ( des.X ? 'Y' : ' ' ) )
    PRINT_FLAG( bits.hidden );
    PRINT_FLAG( bits.light );
    PRINT_FLAG( bits.outside );
    PRINT_FLAG( bits.subterranean );
    PRINT_FLAG( bits.water_table );
    PRINT_FLAG( bits.rained );

    df::coord2d pc(blockX, blockY);

    t_feature local;
    t_feature global;
    Maps::ReadFeatures(&(b->raw),&local,&global);
    PRINT_FLAG( bits.feature_local );
    if(local.type != -1)
    {
        con.print("%-16s", "");
        con.print("  %4d", block.local_feature);
        con.print(" (%2d)", local.type);
        con.print(" addr 0x%X ", local.origin);
        con.print(" %s\n", sa_feature(local.type));
    }
    PRINT_FLAG( bits.feature_global );
    if(global.type != -1)
    {
        con.print("%-16s", "");
        con.print("  %4d", block.global_feature);
        con.print(" (%2d)", global.type);
        con.print(" %s\n", sa_feature(global.type));
    }
    #undef PRINT_FLAG
    con << "local feature idx: " << block.local_feature
        << endl;
    con << "global feature idx: " << block.global_feature
        << endl;
    con << "mystery: " << block.mystery << endl;
    con << std::endl;
    return CR_OK;
}
示例#13
0
int main (int argc, const char* argv[])
{
    // Command line options
    bool updown = false;
    bool quiet = true;
    // let's be more useful when double-clicked on windows
    #ifndef LINUX_BUILD
    quiet = false;
    #endif
    int dig_up_n = 5;
    int dig_down_n = 5;

    for(int i = 1; i < argc; i++)
    {
        string arg_cur = argv[i];
        string arg_next = "";
	int arg_next_int = -99999;
	/* Check if argv[i+1] is a number >= 0 */
	if (i < argc-1) {
	    arg_next = argv[i+1];
	    arg_next_int = strtoint(arg_next);
	    if (arg_next != "0" && arg_next_int == 0) {
		arg_next_int = -99999;
	    }
	}
	if (arg_cur == "-x")
	{
	    updown = true;
	}
	else if (arg_cur == "-q")
	{
	    quiet = true;
	}
	else if(arg_cur == "-u" && i < argc-1)
	{
	    if (arg_next_int < 0 || arg_next_int >= 99999) {
		usage(argc, argv);
		return 1;
	    }
	    dig_up_n = arg_next_int;
	    i++;
	}
	else if(arg_cur == "-d" && i < argc-1)
	{
	    if (arg_next_int < 0 || arg_next_int >= 99999) {
		usage(argc, argv);
		return 1;
	    }
	    dig_down_n = arg_next_int;
	    i++;
	}
	else
	{
	    usage(argc, argv);
	    return 1;
	}
    }

    DFHack::ContextManager DFMgr("Memory.xml");
    DFHack::Context * DF;
    try
    {
        DF = DFMgr.getSingleContext();
        DF->Attach();
    }
    catch (exception& e)
    {
        cerr << "Error getting context: " << e.what() << endl;
        if (!quiet)
            cin.ignore();

        return 1;
    }

    uint32_t x_max,y_max,z_max;
    DFHack::Maps * Maps = DF->getMaps();
    DFHack::Gui * Gui = DF->getGui();

    // init the map
    if(!Maps->Start())
    {
        cerr << "Can't init map. Make sure you have a map loaded in DF." << endl;
        DF->Detach();
        if (!quiet)
            cin.ignore();

        return 1;
    }

    int32_t cx, cy, cz;
    Maps->getSize(x_max,y_max,z_max);
    uint32_t tx_max = x_max * 16;
    uint32_t ty_max = y_max * 16;

    Gui->getCursorCoords(cx,cy,cz);
    if (cx == -30000)
    {
        cerr << "Cursor is not active. Point the cursor at the position to dig at." << endl;
        DF->Detach();
        if (!quiet)
	{
            cin.ignore();
	}
	return 1;
    }

    DFHack::DFCoord xy ((uint32_t)cx,(uint32_t)cy,cz);
    if(xy.x == 0 || xy.x == tx_max - 1 || xy.y == 0 || xy.y == ty_max - 1)
    {
        cerr << "I won't dig the borders. That would be cheating!" << endl;
        DF->Detach();
        if (!quiet)
	{
            cin.ignore();
	}
        return 1;
    }
    MapCache * MCache = new MapCache(Maps);

    DFHack::t_designation des = MCache->designationAt(xy);
    int16_t tt = MCache->tiletypeAt(xy);
    int16_t veinmat = MCache->veinMaterialAt(xy);

    /*
    if( veinmat == -1 )
    {
        cerr << "This tile is non-vein. Bye :)" << endl;
        delete MCache;
        DF->Detach();
        if (!quiet) {
            cin.ignore();
	}
        return 1;
    }
    */
    printf("Digging at (%d/%d/%d), tiletype: %d, veinmat: %d, designation: 0x%x ... DIGGING!\n", cx,cy,cz, tt, veinmat, des.whole);

    // 1 < xy.x < tx_max - 1
    // 1 < xy.y < ty_max - 1
    // xy.z

    // X____
    // X_XXX
    // XXXXX
    // __XXX
    // __XXX
    // _____
    pos map[] = 
    {
	  { 0,0 }
	, { 0,1 }
	, { 0,2 }         , { 2,2 }, { 3,2 }, { 4,2 }
	, { 0,3 }, { 1,3 }, { 2,3 }, { 3,3 }, { 4,3 }
	                  , { 2,4 }, { 3,4 }, { 4,4 }
    // this is mirrored, goes left instead of right
	                  , {-2,2 }, {-3,2 }, {-4,2 }
	         , {-1,3 }, {-2,3 }, {-3,3 }, {-4,3 }
	                  , {-2,4 }, {-3,4 }, {-4,4 }
    };

    DFHack::DFCoord npos = xy;

    if (dig_up_n > 0)
    {
	for (int j = 0; j < dig_up_n; j++)
	{
	    for (int i = 0; i < sizeof(map)/sizeof(map[0]); i++) 
	    {
		npos=xy;
		npos.x += map[i].x;
		npos.y -= 4*j + map[i].y;
		printf("Digging at (%d/%d/%d)\n", npos.x, npos.y, npos.z);
		digat(MCache, npos);
	    }
	}
    }
    if (dig_down_n > 0)
    {
	for (int j = 0; j < dig_down_n; j++)
	{
	    for (int i = 0; i < sizeof(map)/sizeof(map[0]); i++) 
	    {
		npos=xy;
		npos.x += map[i].x;
		npos.y += 4*j + map[i].y;
		printf("Digging at (%d/%d/%d)\n", npos.x, npos.y, npos.z);
		digat(MCache, npos);
	    }
	}
    }

    MCache->WriteAll();
    delete MCache;
    DF->Detach();
    if (!quiet) {
        cout << "Done. Press any key to continue" << endl;
        cin.ignore();
    }
    return 0;
}
示例#14
0
int main (int numargs, const char ** args)
{
    map<string, string> buildCommands;
    buildCommands["building_stockpilest"]="";
    buildCommands["building_zonest"]="";
    buildCommands["building_construction_blueprintst"]="";
    buildCommands["building_wagonst"]="";
    buildCommands["building_armor_standst"]="a";
    buildCommands["building_bedst"]="b";
    buildCommands["building_seatst"]="c";
    buildCommands["building_burial_receptaclest"]="n";
    buildCommands["building_doorst"]="d";
    buildCommands["building_floodgatest"]="x";
    buildCommands["building_floor_hatchst"]="H";
    buildCommands["building_wall_gratest"]="W";
    buildCommands["building_floor_gratest"]="G";
    buildCommands["building_vertical_barsst"]="B";
    buildCommands["building_floor_barsst"]="alt-b";
    buildCommands["building_cabinetst"]="f";
    buildCommands["building_containerst"]="h";
    buildCommands["building_shopst"]="";
    buildCommands["building_workshopst"]="";
    buildCommands["building_alchemists_laboratoryst"]="wa";
    buildCommands["building_carpenters_workshopst"]="wc";
    buildCommands["building_farmers_workshopst"]="ww";
    buildCommands["building_masons_workshopst"]="wm";
    buildCommands["building_craftdwarfs_workshopst"]="wr";
    buildCommands["building_jewelers_workshopst"]="wj";
    buildCommands["building_metalsmiths_workshopst"]="wf";
    buildCommands["building_magma_forgest"]="";
    buildCommands["building_bowyers_workshopst"]="wb";
    buildCommands["building_mechanics_workshopst"]="wt";
    buildCommands["building_siege_workshopst"]="ws";
    buildCommands["building_butchers_shopst"]="wU";
    buildCommands["building_leather_worksst"]="we";
    buildCommands["building_tanners_shopst"]="wn";
    buildCommands["building_clothiers_shopst"]="wk";
    buildCommands["building_fisheryst"]="wh";
    buildCommands["building_stillst"]="wl";
    buildCommands["building_loomst"]="wo";
    buildCommands["building_quernst"]="wq";
    buildCommands["building_kennelsst"]="k";
    buildCommands["building_kitchenst"]="wz";
    buildCommands["building_asheryst"]="wy";
    buildCommands["building_dyers_shopst"]="wd";
    buildCommands["building_millstonest"]="wM";
    buildCommands["building_farm_plotst"]="p";
    buildCommands["building_weapon_rackst"]="r";
    buildCommands["building_statuest"]="s";
    buildCommands["building_tablest"]="t";
    buildCommands["building_paved_roadst"]="o";
    buildCommands["building_bridgest"]="g";
    buildCommands["building_wellst"]="l";
    buildCommands["building_siege enginest"]="i";
    buildCommands["building_catapultst"]="ic";
    buildCommands["building_ballistast"]="ib";
    buildCommands["building_furnacest"]="";
    buildCommands["building_wood_furnacest"]="ew";
    buildCommands["building_smelterst"]="es";
    buildCommands["building_glass_furnacest"]="ek";
    buildCommands["building_kilnst"]="ek";
    buildCommands["building_magma_smelterst"]="es";
    buildCommands["building_magma_glass_furnacest"]="ek";
    buildCommands["building_magma_kilnst"]="ek";
    buildCommands["building_glass_windowst"]="y";
    buildCommands["building_gem_windowst"]="Y";
    buildCommands["building_tradedepotst"]="D";
    buildCommands["building_mechanismst"]="";
    buildCommands["building_leverst"]="Tl";
    buildCommands["building_pressure_platest"]="Tp";
    buildCommands["building_cage_trapst"]="Tc";
    buildCommands["building_stonefall_trapst"]="Ts";
    buildCommands["building_weapon_trapst"]="Tw";
    buildCommands["building_spikest"]="";
    buildCommands["building_animal_trapst"]="m";
    buildCommands["building_screw_pumpst"]="Ms";
    buildCommands["building_water_wheelst"]="Mw";
    buildCommands["building_windmillst"]="Mm";
    buildCommands["building_gear_assemblyst"]="Mg";
    buildCommands["building_horizontal_axlest"]="Mh";
    buildCommands["building_vertical_axlest"]="Mv";
    buildCommands["building_supportst"]="S";
    buildCommands["building_cagest"]="j";
    buildCommands["building_archery_targetst"]="A";
    buildCommands["building_restraintst"]="v";

    DFHack::ContextManager DFMgr("Memory.xml");
    DFHack::Context *DF = DFMgr.getSingleContext();
    
    try
    {
        DF->Attach();
    }
    catch (std::exception& e)
    {
        std::cerr << e.what() << std::endl;
        #ifndef LINUX_BUILD
            cin.ignore();
        #endif
        return 1;
    }
    
    DFHack::Gui *Gui = DF->getGui();
    DFHack::VersionInfo* mem = DF->getMemoryInfo();
    DFHack::Process * p = DF->getProcess();
    OffsetGroup * OG_Maps = mem->getGroup("Maps");
    OffsetGroup * OG_MapBlock = OG_Maps->getGroup("block");
    OffsetGroup * OG_LocalFt = OG_Maps->getGroup("features")->getGroup("local");
    uint32_t designations = OG_MapBlock->getOffset("designation");
    uint32_t block_feature1 = OG_MapBlock->getOffset("feature_local");
    uint32_t block_feature2 = OG_MapBlock->getOffset("feature_global");
    uint32_t region_x_offset = OG_Maps->getAddress("region_x");
    uint32_t region_y_offset = OG_Maps->getAddress("region_y");
    uint32_t region_z_offset = OG_Maps->getAddress("region_z");
    uint32_t feature1_start_ptr = OG_LocalFt->getAddress("start_ptr");
    int32_t regionX, regionY, regionZ;
    
    // read position of the region inside DF world
    p->readDWord (region_x_offset, (uint32_t &)regionX);
    p->readDWord (region_y_offset, (uint32_t &)regionY);
    p->readDWord (region_z_offset, (uint32_t &)regionZ);
    while(1){
    int32_t cx1,cy1,cz1;
    cx1 = -30000;
    while(cx1 == -30000)
    {
        DF->ForceResume();
        cout << "Set cursor at first position, then press any key";
        cin.ignore();
        DF->Suspend();
        Gui->getCursorCoords(cx1,cy1,cz1);
    }

    uint32_t tx1,ty1,tz1;
    tx1 = cx1/16;
    ty1 = cy1/16;
    tz1 = cz1;

    int32_t cx2,cy2,cz2;
    cx2 = -30000;
    while(cx2 == -30000)
    {
        DF->Resume();
        cout << "Set cursor at second position, then press any key";
        cin.ignore();
        DF->Suspend();
        Gui->getCursorCoords(cx2,cy2,cz2);
    }
    uint32_t tx2,ty2,tz2;
    tx2 = cx2/16;
    ty2 = cy2/16;
    tz2 = cz2;
    sort(tx1,tx2);
    sort(ty1,ty2);
    sort(tz1,tz2);
    sort(cx1,cx2);
    sort(cy1,cy2);
    sort(cz1,cz2);

    vector <vector<vector<string> > >dig(cz2-cz1+1,vector<vector<string> >(cy2-cy1+1,vector<string>(cx2-cx1+1)));
    vector <vector<vector<string> > >build(cz2-cz1+1,vector<vector<string> >(cy2-cy1+1,vector<string>(cx2-cx1+1)));
    mapblock40d block;
    DFHack::Maps *Maps = DF->getMaps();
    Maps->Start();
    for(uint32_t y = ty1;y<=ty2;y++)
    {
        for(uint32_t x = tx1;x<=tx2;x++)
        {
            for(uint32_t z = tz1;z<=tz2;z++)
            {
                if(Maps->isValidBlock(x,y,z))
                {
                    if(Maps->ReadBlock40d(x,y,z,&block))
                    {
                        int ystart,yend,xstart,xend;
                        ystart=xstart=0;
                        yend=xend=15;
                        if(y == ty2)
                        {
                            yend = cy2 % 16;
                        }
                        if(y == ty1)
                        {
                            ystart = cy1 % 16;
                        }
                        if(x == tx2)
                        {
                            xend = cx2 % 16;
                        }
                        if(x == tx1)
                        {
                            xstart = cx1 % 16;
                        }
                        int zidx = z-tz1;
                        for(int yy = ystart; yy <= yend;yy++)
                        {
                            int yidx = yy+(16*(y-ty1)-(cy1%16));
                            for(int xx = xstart; xx <= xend;xx++)
                            {
                                int xidx = xx+(16*(x-tx1)-(cx1%16));
                                int16_t tt = block.tiletypes[xx][yy];
                                DFHack::TileShape ts = DFHack::tileShape(tt);
                                if(DFHack::isOpenTerrain(tt) || DFHack::isFloorTerrain(tt))
                                {
                                    dig[zidx][yidx][xidx] = "d";
                                }
                                else if(DFHack::STAIR_DOWN == ts)
                                {
                                    dig [zidx][yidx][xidx] = "j";
                                    build [zidx][yidx][xidx] = "Cd";
                                }
                                else if(DFHack::STAIR_UP == ts)
                                {
                                    dig [zidx][yidx][xidx] = "u";
                                    build [zidx][yidx][xidx] = "Cu";
                                }
                                else if(DFHack::STAIR_UPDOWN == ts)
                                {
                                    dig [zidx][yidx][xidx] = "i";
                                    build [zidx][yidx][xidx] = "Cx";
                                }
                                else if(DFHack::isRampTerrain(tt))
                                {
                                    dig [zidx][yidx][xidx] = "r";
                                    build [zidx][yidx][xidx] = "Cr";
                                }
                                else if(DFHack::isWallTerrain(tt))
                                {
                                    build [zidx][yidx][xidx] = "Cw";
                                }
                            }
                            yidx++;
                        }
                    }
                }
            }
        }
    }
    DFHack::Buildings * Bld = DF->getBuildings();
    std::map <uint32_t, std::string> custom_workshop_types;
    uint32_t numBuildings;
    if(Bld->Start(numBuildings))
    {
        Bld->ReadCustomWorkshopTypes(custom_workshop_types);
        for(uint32_t i = 0; i < numBuildings; i++)
        {
            DFHack::t_building temp;
            Bld->Read(i, temp);
            if(temp.type != 0xFFFFFFFF) // check if type isn't invalid
            {
                std::string typestr;
                mem->resolveClassIDToClassname(temp.type, typestr);
                if(temp.z == cz1 && cx1 <= temp.x1 && cx2 >= temp.x2 && cy1 <= temp.y1 && cy2 >= temp.y2)
                {
                    string currStr = build[temp.z-cz1][temp.y1-cy1][temp.x1-cx1];
                    stringstream stream;
                    string newStr = buildCommands[typestr];
                    if(temp.x1 != temp.x2)
                    {
                        stream << "(" << temp.x2-temp.x1+1 << "x" << temp.y2-temp.y1+1 << ")";
                        newStr += stream.str();
                    }
                    build[temp.z-cz1][temp.y1-cy1][temp.x1-cx1] = newStr + currStr;
                }
            }
        }
    }
// for testing purposes
    //ofstream outfile("test.txt");
//    printVecOfVec(outfile, dig,'\t');
//    outfile << endl;
//   printVecOfVec(outfile, build,'\t');
//    outfile << endl;
//    outfile.close();

    int32_t cx3,cy3,cz3,cx4,cy4,cz4;
    uint32_t tx3,ty3,tz3,tx4,ty4,tz4;
    char result;
    while(1){
        cx3 = -30000;
        while(cx3 == -30000){
            DF->Resume();
            cout << "Set cursor at new position, then press any key:";
            result = cin.get();
            DF->Suspend();
            Gui->getCursorCoords(cx3,cy3,cz3);
        }
        if(result == 'q'){
            break;
        }
        cx4 = cx3+cx2-cx1;
        cy4 = cy3+cy2-cy1;
        cz4 = cz3+cz2-cz1;
        tx3=cx3/16;
        ty3=cy3/16;
        tz3=cz3;
        tx4=cx4/16;
        ty4=cy4/16;
        tz4=cz4;
        DFHack::WindowIO * Win = DF->getWindowIO();
        designations40d designationBlock;
        for(uint32_t y = ty3;y<=ty4;y++)
        {
            for(uint32_t x = tx3;x<=tx4;x++)
            {
                for(uint32_t z = tz3;z<=tz4;z++)
                {
                    Maps->Start();
                    Maps->ReadBlock40d(x,y,z,&block);
                    Maps->ReadDesignations(x,y,z,&designationBlock);
                    int ystart,yend,xstart,xend;
                    ystart=xstart=0;
                    yend=xend=15;
                    if(y == ty4){
                        yend = cy4 % 16;
                    }
                    if(y == ty3){
                        ystart = cy3 % 16;
                    }
                    if(x == tx4){
                        xend = cx4 % 16;
                    }
                    if(x == tx3){
                        xstart = cx3 % 16;
                    }
                    int zidx = z-tz3;
                    for(int yy = ystart; yy <= yend;yy++){
                        int yidx = yy+(16*(y-ty3)-(cy3%16));
                        for(int xx = xstart; xx <= xend;xx++){
                            int xidx = xx+(16*(x-tx3)-(cx3%16));
                                if(dig[zidx][yidx][xidx] != ""){
                                    char test = dig[zidx][yidx][xidx].c_str()[0];
                                    switch (test){
                                        case 'd':
                                            designationBlock[xx][yy].bits.dig = DFHack::designation_default;
                                            break;
                                        case 'i':
                                            designationBlock[xx][yy].bits.dig = DFHack::designation_ud_stair;
                                            break;
                                        case 'u':
                                            designationBlock[xx][yy].bits.dig = DFHack::designation_u_stair;
                                            break;
                                        case 'j':
                                            designationBlock[xx][yy].bits.dig = DFHack::designation_d_stair;
                                            break;
                                        case 'r':
                                            designationBlock[xx][yy].bits.dig = DFHack::designation_ramp;
                                            break;
                                    }
                                
                                }
                        }
                        yidx++;
                    }
                    Maps->Start();
                    Maps->WriteDesignations(x,y,z,&designationBlock);
                }
            }
        }
    }
    }
    DF->Detach();
    #ifndef LINUX_BUILD
    std::cout << "Done. Press any key to continue" << std::endl;
    cin.ignore();
    #endif
    return 0;
}
示例#15
0
DFhackCExport command_result df_liquids (Core * c, vector <string> & parameters)
{
    int32_t x,y,z;
    uint32_t x_max,y_max,z_max;

    DFHack::Maps * Maps;
    DFHack::Gui * Position;
    for(int i = 0; i < parameters.size();i++)
    {
        if(parameters[i] == "help" || parameters[i] == "?")
        {
            c->con.print("This tool allows placing magma, water and other similar things.\n"
            "It is interactive and further help is available when you run it.\n"
            );
            return CR_OK;
        }
    }
    Brush * brush = new RectangleBrush(1,1);
    string brushname = "point";
    bool end = false;
    c->con << "Welcome to the liquid spawner.\nType 'help' or '?' for a list of available commands, 'q' to quit.\nPress return after a command to confirm." << std::endl;
    string mode="magma";

    string flowmode="f+";
    string setmode ="s.";
    unsigned int amount = 7;
    int width = 1, height = 1, z_levels = 1;
    while(!end)
    {
        string command = "";
        std::stringstream str;
        str <<"[" << mode << ":" << brushname << ":" << amount << ":" << flowmode << ":" << setmode << "]#";
        if(c->con.lineedit(str.str(),command,liquids_hist) == -1)
            return CR_FAILURE;
        if(command=="help" || command == "?")
        {
            c->con << "Modes:" << endl
                 << "m             - switch to magma" << endl
                 << "w             - switch to water" << endl
                 << "o             - make obsidian wall instead" << endl
                 << "of            - make obsidian floors" << endl
                 << "rs            - make a river source" << endl
                 << "f             - flow bits only" << endl
                 << "Set-Modes (only for magma/water):" << endl
                 << "s+            - only add" << endl
                 << "s.            - set" << endl
                 << "s-            - only remove" << endl
                 << "Properties (only for magma/water):" << endl
                 << "f+            - make the spawned liquid flow" << endl
                 << "f.            - don't change flow state (read state in flow mode)" << endl
                 << "f-            - make the spawned liquid static" << endl
                 << "0-7           - set liquid amount" << endl
                 << "Brush:" << endl
                 << "point         - single tile [p]" << endl
                 << "range         - block with cursor at bottom north-west [r]" << endl
                 << "                (any place, any size)" << endl
                 << "block         - DF map block with cursor in it" << endl
                 << "                (regular spaced 16x16x1 blocks)" << endl
                 << "column        - Column from cursor, up through free space" << endl
                 << "Other:" << endl
                 << "q             - quit" << endl
                 << "help or ?     - print this list of commands" << endl
                 << "empty line    - put liquid" << endl
                 << endl
                 << "Usage: point the DF cursor at a tile you want to modify" << endl
                 << "and use the commands available :)" << endl;
        }
        else if(command == "m")
        {
            mode = "magma";
        }
        else if(command == "o")
        {
            mode = "obsidian";
        }
        else if(command == "of")
        {
            mode = "obsidian_floor";
        }
        else if(command == "w")
        {
            mode = "water";
        }
        else if(command == "f")
        {
            mode = "flowbits";
        }
        else if(command == "rs")
        {
            mode = "riversource";
        }
        else if(command == "point" || command == "p")
        {
            delete brush;
            brushname = "point";
            brush = new RectangleBrush(1,1);
        }
        else if(command == "range" || command == "r")
        {
            std::stringstream str;
            CommandHistory range_hist;
            str << " :set range width<" << width << "># ";
            c->con.lineedit(str.str(),command,range_hist);
            range_hist.add(command);
            width = command == "" ? width : atoi (command.c_str());
            if(width < 1) width = 1;

            str.str("");
            str << " :set range height<" << height << "># ";
            c->con.lineedit(str.str(),command,range_hist);
            range_hist.add(command);
            height = command == "" ? height : atoi (command.c_str());
            if(height < 1) height = 1;

            str.str("");
            str << " :set range z-levels<" << z_levels << "># ";
            c->con.lineedit(str.str(),command,range_hist);
            range_hist.add(command);
            z_levels = command == "" ? z_levels : atoi (command.c_str());
            if(z_levels < 1) z_levels = 1;
            delete brush;
            if(width == 1 && height == 1 && z_levels == 1)
            {
                brushname="point";
            }
            else
            {
                brushname = "range";
            }
            brush = new RectangleBrush(width,height,z_levels,0,0,0);
        }
        else if(command == "block")
        {
            delete brush;
            brushname = "block";
            brush = new BlockBrush();
        }
        else if(command == "column")
        {
            delete brush;
            brushname = "column";
            brush = new ColumnBrush();
        }
        else if(command == "q")
        {
            end = true;
        }
        else if(command == "f+")
        {
            flowmode = "f+";
        }
        else if(command == "f-")
        {
            flowmode = "f-";
        }
        else if(command == "f.")
        {
            flowmode = "f.";
        }
        else if(command == "s+")
        {
            setmode = "s+";
        }
        else if(command == "s-")
        {
            setmode = "s-";
        }
        else if(command == "s.")
        {
            setmode = "s.";
        }
        // blah blah, bad code, bite me.
        else if(command == "0")
            amount = 0;
        else if(command == "1")
            amount = 1;
        else if(command == "2")
            amount = 2;
        else if(command == "3")
            amount = 3;
        else if(command == "4")
            amount = 4;
        else if(command == "5")
            amount = 5;
        else if(command == "6")
            amount = 6;
        else if(command == "7")
            amount = 7;
        else if(command.empty())
        {
            c->Suspend();
            Maps = c->getMaps();
            Maps->Start();
            Maps->getSize(x_max,y_max,z_max);
            Position = c->getGui();
            do
            {
                if(!Maps->Start())
                {
                    c->con << "Can't see any DF map loaded." << endl;
                    break;
                }
                if(!Position->getCursorCoords(x,y,z))
                {
                    c->con << "Can't get cursor coords! Make sure you have a cursor active in DF." << endl;
                    break;
                }
                c->con << "cursor coords: " << x << "/" << y << "/" << z << endl;
                MapCache mcache(Maps);
                DFHack::DFCoord cursor(x,y,z);
                coord_vec all_tiles = brush->points(mcache,cursor);
                c->con << "working..." << endl;
                if(mode == "obsidian")
                {
                    coord_vec::iterator iter = all_tiles.begin();
                    while (iter != all_tiles.end())
                    {
                        mcache.setTiletypeAt(*iter, 331);
                        mcache.setTemp1At(*iter,10015);
                        mcache.setTemp2At(*iter,10015);
                        DFHack::t_designation des = mcache.designationAt(*iter);
                        des.bits.flow_size = 0;
                        mcache.setDesignationAt(*iter, des);
                        iter ++;
                    }
                }
                if(mode == "obsidian_floor")
                {
                    coord_vec::iterator iter = all_tiles.begin();
                    while (iter != all_tiles.end())
                    {
                        mcache.setTiletypeAt(*iter, 340);
                        iter ++;
                    }
                }
                else if(mode == "riversource")
                {
                    set <Block *> seen_blocks;
                    coord_vec::iterator iter = all_tiles.begin();
                    while (iter != all_tiles.end())
                    {
                        mcache.setTiletypeAt(*iter, 90);

                        DFHack::t_designation a = mcache.designationAt(*iter);
                        a.bits.liquid_type = DFHack::liquid_water;
                        a.bits.liquid_static = false;
                        a.bits.flow_size = 7;
                        mcache.setTemp1At(*iter,10015);
                        mcache.setTemp2At(*iter,10015);
                        mcache.setDesignationAt(*iter,a);

                        Block * b = mcache.BlockAt((*iter)/16);
                        DFHack::t_blockflags bf = b->BlockFlags();
                        bf.bits.liquid_1 = true;
                        bf.bits.liquid_2 = true;
                        b->setBlockFlags(bf);

                        iter++;
                    }
                }
                else if(mode== "magma" || mode== "water" || mode == "flowbits")
                {
                    set <Block *> seen_blocks;
                    coord_vec::iterator iter = all_tiles.begin();
                    while (iter != all_tiles.end())
                    {
                        DFHack::DFCoord current = *iter;
                        DFHack::t_designation des = mcache.designationAt(current);
                        uint16_t tt = mcache.tiletypeAt(current);
                        DFHack::naked_designation & flow = des.bits;
                        // don't put liquids into places where they don't belong...
                        if(!DFHack::FlowPassable(tt))
                        {
                            iter++;
                            continue;
                        }
                        if(mode != "flowbits")
                        {
                            if(setmode == "s.")
                            {
                                flow.flow_size = amount;
                            }
                            else if(setmode == "s+")
                            {
                                if(flow.flow_size < amount)
                                    flow.flow_size = amount;
                            }
                            else if(setmode == "s-")
                            {
                                if (flow.flow_size > amount)
                                    flow.flow_size = amount;
                            }
                            if(amount != 0 && mode == "magma")
                            {
                                flow.liquid_type =  DFHack::liquid_magma;
                                mcache.setTemp1At(current,12000);
                                mcache.setTemp2At(current,12000);
                            }
                            else if(amount != 0 && mode == "water")
                            {
                                flow.liquid_type =  DFHack::liquid_water;
                                mcache.setTemp1At(current,10015);
                                mcache.setTemp2At(current,10015);
                            }
                            else if(amount == 0 && (mode == "water" || mode == "magma"))
                            {
                                // reset temperature to sane default
                                mcache.setTemp1At(current,10015);
                                mcache.setTemp2At(current,10015);
                            }
                            mcache.setDesignationAt(current,des);
                        }
                        seen_blocks.insert(mcache.BlockAt((*iter) / 16));
                        iter++;
                    }
                    set <Block *>::iterator biter = seen_blocks.begin();
                    while (biter != seen_blocks.end())
                    {
                        DFHack::t_blockflags bflags = (*biter)->BlockFlags();
                        if(flowmode == "f+")
                        {
                            bflags.bits.liquid_1 = true;
                            bflags.bits.liquid_2 = true;
                            (*biter)->setBlockFlags(bflags);
                        }
                        else if(flowmode == "f-")
                        {
                            bflags.bits.liquid_1 = false;
                            bflags.bits.liquid_2 = false;
                            (*biter)->setBlockFlags(bflags);
                        }
                        else
                        {
                            c->con << "flow bit 1 = " << bflags.bits.liquid_1 << endl; 
                            c->con << "flow bit 2 = " << bflags.bits.liquid_2 << endl;
                        }
                        biter ++;
                    }
                }
                if(mcache.WriteAll())
                    c->con << "OK" << endl;
                else
                    c->con << "Something failed horribly! RUN!" << endl;
                Maps->Finish();
            } while (0);
            c->Resume();
        }
        else
        {
            c->con << command << " : unknown command." << endl;
        }
    }
    return CR_OK;
}
示例#16
0
// FIXME: use block cache, break into manageable bits
int main (void)
{
    srand ( (unsigned int)time(NULL) );

    //Message of intent
    cout <<
         "DF Hole" << endl <<
         "This tool will instantly dig a chasm, pit, pipe, etc through hell, wherever your cursor is." << endl <<
         "This can not be undone!  End program now if you don't want hellish fun." << endl
         ;

    //User selection of settings should have it own routine, a structure for settings, I know
    //sloppy mess, but this is just a demo utility.

    //Pit Types.
    e_pitType pittype = selectPitType();

    //Here are all the settings.
    //Default values are set here.
    int pitdepth=0;
    int roof=-1;
    int holeradius=6;
    int wallthickness=1;
    int wallpillar=1;
    int holepillar=1;
    int exposehell = 0;
    int fillmagma=0;
    int fillwater=0;
    int stopatmagma=0;
    int exposemagma=0;
    int aquify=0;

    //The Tile Type to use for the walls lining the hole
    //263 is semi-molten rock, 331 is obsidian
    uint32_t whell=263, wmolten=263, wmagma=331, wcave=331;
    //The Tile Type to use for the hole's floor at bottom of the map
    //35 is chasm, 42 is eerie pit , 340 is obsidian floor, 344 is featstone floor, 264 is 'magma flow' floor
    uint32_t floor=35, cap=340;
    int floorvar=0;


    //Modify default settings based on pit type.
    switch ( pittype )
    {
        case pitTypeChasm:
            floor=35;
            break;
        case pitTypeEerie:
            floor=42;
            break;
        case pitTypeFloor:
            floor=344;
            floorvar=3;
            break;
        case pitTypeSolid:
            holeradius=0;
            wallthickness=7;
            wallpillar=4;
            break;
        case pitTypeOasis:
            stopatmagma=-1;
            fillwater=-1;
            holeradius=5;
            wallthickness=2;
            //aquify=-1;
            floor=340;
            floorvar=3;
            break;
        case pitTypeOPool:
            pitdepth=5;
            fillwater=-1;
            holeradius=5;
            wallthickness=2;
            //aquify=-1;
            floor=340;
            floorvar=3;
            break;
        case pitTypeMagma:
            stopatmagma=-1;
            exposemagma=-1;
            wallthickness=2;
            fillmagma=-1;
            floor=264;
            break;
        case pitTypeMPool:
            pitdepth=5;
            wallthickness=2;
            fillmagma=-1;
            floor=340;
            floorvar=3;
            break;
    }


    //Should tiles be revealed?
    int reveal=0;


    int accept = getyesno("Use default settings?",1);

    while ( !accept )
    {
        //Pit Depth
        pitdepth = getint( "Enter max depth (0 for bottom of map)", 0, INT_MAX, pitdepth );

        //Hole Size
        holeradius = getint( "Enter hole radius, 0 to 16", 0, 16, holeradius );

        //Wall thickness
        wallthickness = getint( "Enter wall thickness, 0 to 16", 0, 16, wallthickness );

        //Obsidian Pillars
        holepillar = getint( "Number of Obsidian Pillars in hole, 0 to 255", 0, 255, holepillar );
        wallpillar = getint( "Number of Obsidian Pillars in wall, 0 to 255", 0, 255, wallpillar );

        //Open Hell?
        exposehell=getyesno("Expose the pit to hell (no walls in hell)?",exposehell);

        //Stop when magma sea is hit?
        stopatmagma=getyesno("Stop at magma sea?",stopatmagma);
        exposemagma=getyesno("Expose magma sea (no walls in magma)?",exposemagma);

        //Fill?
        fillmagma=getyesno("Fill with magma?",fillmagma);
        if (fillmagma) aquify=fillwater=0;
        fillwater=getyesno("Fill with water?",fillwater);
        //aquify=getyesno("Aquifer?",aquify);


        ///////////////////////////////////////////////////////////////////////////////////////////////
        //Print settings.
        //If a settings struct existed, this could be in a routine
        printf("Using Settings:\n");
        printf("Pit Type......: %d = %s\n", pittype, pitTypeDesc[pittype]);
        printf("Depth.........: %d\n",  pitdepth);
        printf("Hole Radius...: %d\n",  holeradius);
        printf("Wall Thickness: %d\n",  wallthickness);
        printf("Pillars, Hole.: %d\n",  holepillar);
        printf("Pillars, Wall.: %d\n",  wallpillar);
        printf("Expose Hell...: %c\n", (exposehell?'Y':'N') );
        printf("Stop at Magma.: %c\n", (stopatmagma?'Y':'N') );
        printf("Expose Magma..: %c\n", (exposemagma?'Y':'N') );
        printf("Magma Fill....: %c\n", (fillmagma?'Y':'N') );
        printf("Water Fill....: %c\n", (fillwater?'Y':'N') );
        printf("Aquifer.......: %c\n", (aquify?'Y':'N') );

        accept = getyesno("Accept these settings?",1);
    }


    int64_t n;
    uint32_t x_max,y_max,z_max;


    //Pattern to dig
    unsigned char pattern[16][16];


    for (int regen=1;regen; )
    {
        regen=0;

        memset(pattern,0,sizeof(pattern));

        //Calculate a randomized circle.
        //These values found through experimentation.
        int x=0, y=0, n=0;

        //Two concentric irregular circles
        //Outer circle, solid.
        if ( wallthickness )
        {
            drawcircle(holeradius+wallthickness, pattern, 2);
        }
        //Inner circle, hole.
        if ( holeradius )
        {
            drawcircle(holeradius, pattern, 1);
        }


        //Post-process to be certain the wall totally encloses hole.
        if (wallthickness)
        {
            for (y=0;y<16;++y)
            {
                for (x=0;x<16;++x)
                {
                    if ( 1==pattern[x][y] )
                    {
                        //No hole at edges.
                        if ( x<1 || x>14 || y<1 || y>14 )
                        {
                            pattern[x][y]=2;
                        }
                    }
                    else if ( 0==pattern[x][y] )
                    {
                        //check neighbors
                        checkneighbors( pattern , x,y, 1, 2);
                    }
                }
            }
        }

        //Makes sure that somewhere random gets a vertical pillar of rock which is safe
        //to dig stairs down, to permit access to anywhere within the pit from the top.
        for (n=holepillar; n ; --n)
        {
            settileat( pattern , 1 , 3 , rand()&255 );
        }
        for (n=wallpillar; n ; --n)
        {
            settileat( pattern , 2 , 3 , rand()&255 );
        }

        //Note:
        //At this point, the pattern holds:
        //0 for all tiles which will be ignored.
        //1 for all tiles set to empty pit space.
        //2 for all normal walls.
        //3 for the straight obsidian top-to-bottom wall.
        //4 is randomized between wall or floor (!not implemented!)

        printf("\nPattern:\n");
        const char patternkey[] = ".cW!?567890123";

        //Print the pattern
        for (y=0;y<16;++y)
        {
            for (x=0;x<16;++x)
            {
                cout << patternkey[ pattern[x][y] ];
            }
            cout << endl;
        }
        cout << endl;

        regen = !getyesno("Acceptable Pattern?",1);
    }

    //Post-process settings to fix problems here
    if (pitdepth<1)
    {
        pitdepth=INT_MAX;
    }


    ///////////////////////////////////////////////////////////////////////////////////////////////


    cerr << "Loading memory map..." << endl;

    //Connect to DF!
    DFHack::ContextManager DFMgr("Memory.xml");
    DFHack::Context *DF = DFMgr.getSingleContext();



    //Init
    cerr << "Attaching to DF..." << endl;
    try
    {
        DF->Attach();
    }
    catch (exception& e)
    {
        cerr << e.what() << endl;
        #ifndef LINUX_BUILD
            cin.ignore();
        #endif
        return 1;
    }

    // init the map
    DFHack::Maps *Mapz = DF->getMaps();
    if (!Mapz->Start())
    {
        cerr << "Can't init map.  Exiting." << endl;
        #ifndef LINUX_BUILD
            cin.ignore();
        #endif
        return 1;
    }

    Mapz->getSize(x_max,y_max,z_max);


    //Get cursor
    int32_t cursorX, cursorY, cursorZ;
    DFHack::Gui *Gui = DF->getGui();
    Gui->getCursorCoords(cursorX,cursorY,cursorZ);
    if (-30000==cursorX)
    {
        cout << "No cursor position found.  Exiting." << endl;
        #ifndef LINUX_BUILD
            cin.ignore();
        #endif
        return 1;
    }

    //Block coordinates
    int32_t bx=cursorX/16, by=cursorY/16, bz=cursorZ;
    //Tile coordinates within block
    int32_t tx=cursorX%16, ty=cursorY%16, tz=cursorZ;

    /*
    //Access the DF interface to pause the game.
    //Copied from the reveal tool.
    DFHack::Gui *Gui =DF->getGui();
    cout << "Pausing..." << endl;
    Gui->SetPauseState(true);
    DF->Resume();
    waitmsec(1000);
    DF->Suspend();
    */

    //Verify that every z-level at this location exists.
    for (int32_t Z = 0; Z<= bz ;Z++)
    {
        if ( ! Mapz->isValidBlock(bx,by,Z) )
        {
            cout << "This block does't exist!  Exiting." << endl;
            #ifndef LINUX_BUILD
                cin.ignore();
            #endif
            return 1;
        }
    }

    //Get all the map features.
    vector<DFHack::t_feature> global_features;
    if (!Mapz->ReadGlobalFeatures(global_features))
    {
        cout << "Couldn't load global features! Probably a version problem." << endl;
        #ifndef LINUX_BUILD
            cin.ignore();
        #endif
        return 1;
    }

    std::map <DFHack::DFCoord, std::vector<DFHack::t_feature *> > local_features;
    if (!Mapz->ReadLocalFeatures(local_features))
    {
        cout << "Couldn't load local features! Probably a version problem." << endl;
        #ifndef LINUX_BUILD
            cin.ignore();
        #endif
        return 1;
    }

    //Get info on current tile, to determine how to generate the pit
    mapblock40d topblock;
    Mapz->ReadBlock40d( bx, by, bz , &topblock );
    //Related block info
    DFCoord pc(bx,by);
    mapblock40d block;
    const TileRow * tp;
    t_designation * d;

    //////////////////////////////////////
    //From top to bottom, dig this thing.
    //////////////////////////////////////

    //Top level, cap.
    //Might make this an option in the future
    //For now, no wall means no cap.
    if (wallthickness)
    {
        Mapz->ReadBlock40d( bx, by, bz , &block );
        for (uint32_t x=0;x<16;++x)
        {
            for (uint32_t y=0;y<16;++y)
            {
                if ( (pattern[x][y]>1) || (roof && pattern[x][y]) )
                {
                    tp = getTileRow(block.tiletypes[x][y]);
                    d = &block.designation[x][y];
                    //Only modify this level if it's 'empty'
                    if ( EMPTY != tp->shape && RAMP_TOP != tp->shape && STAIR_DOWN != tp->shape && DFHack::TILE_STREAM_TOP != tp->special)
                    {
                        continue;
                    }

                    //Need a floor for empty space.
                    if (reveal)
                    {
                        d->bits.hidden = 0; //topblock.designation[x][y].bits.hidden;
                    }
                    //Always clear the dig designation.
                    d->bits.dig = designation_no;
                    //unlock fluids, so they fall down the pit.
                    d->bits.flow_forbid = d->bits.liquid_static=0;
                    block.blockflags.bits.liquid_1 = block.blockflags.bits.liquid_2 = 1;
                    //Remove aquifer, to prevent bugginess
                    d->bits.water_table=0;
                    //Set the tile.
                    block.tiletypes[x][y] = cap + rand()%4;
                }
            }
        }
        //Write the block.
        Mapz->WriteBlockFlags(bx,by,bz, block.blockflags );
        Mapz->WriteDesignations(bx,by,bz, &block.designation );
        Mapz->WriteTileTypes(bx,by,bz, &block.tiletypes );
        Mapz->WriteDirtyBit(bx,by,bz,1);
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////
    //All levels in between.
    int done=0;
    uint32_t t,v;
    int32_t z = bz-1;
    int32_t bottom = max(0,bz-pitdepth-1);
    assert( bottom>=0 && bottom<=bz );
    for ( ; !done && z>=bottom ; --z)
    {
        int watercount=0;
        int magmacount=0;
        int moltencount=0;
        int rockcount=0;
        int veincount=0;
        int emptycount=0;
        int hellcount=0;
        int templecount=0;
        int adamcount=0;
        int featcount=0;
        int tpat;

        cout << z << endl;
        assert( Mapz->isValidBlock(bx,by,z) );
        if (!Mapz->ReadBlock40d( bx, by, z , &block ))
        {
            cout << "Bad block! " << bx << "," << by << "," << z << endl;
        }

        //Pre-process this z-level, to get some tile statistics.
        for (int32_t x=0;x<16;++x)
        {
            for (int32_t y=0;y<16;++y)
            {
                t=0;
                tp = getTileRow(block.tiletypes[x][y]);
                d = &block.designation[x][y];
                tpat=pattern[x][y];

                //Tile type material categories
                switch ( tp->material )
                {
                    case AIR:
                        ++emptycount;
                        break;
                    case MAGMA:
                        ++moltencount;
                        break;
                    case VEIN:
                        ++veincount;
                        break;
                    case FEATSTONE:
                    case HFS:
                    case OBSIDIAN:
                        //basicly, ignored.
                        break;
                    default:
                        if ( EMPTY == tp->shape || RAMP_TOP == tp->shape || STAIR_DOWN == tp->shape )
                        {
                            ++emptycount;
                        }
                        else
                        {
                            ++rockcount;
                        }
                        break;
                }

                //Magma and water
                if ( d->bits.flow_size )
                {
                    if (d->bits.liquid_type)
                    {
                        ++magmacount;
                    }
                    else
                    {
                        ++watercount;
                    }
                }


                //Check for Features
                if ( block.local_feature > -1 || block.global_feature > -1 )
                {
                    //Count tiles which actually are in the feature.
                    //It is possible for a block to have a feature, but no tiles to be feature.
                    if ( d->bits.feature_global || d->bits.feature_local )
                    {
                        //All features
                        ++featcount;

                        if ( d->bits.feature_global && d->bits.feature_local )
                        {
                            cout << "warn:tile is global and local at same time!" << endl;
                        }

                        n=0;
                        if ( block.global_feature > -1 && d->bits.feature_global )
                        {
                            n=global_features[block.global_feature].type;
                            switch ( n )
                            {
                                case feature_Other:
                                    //no count
                                    break;
                                case feature_Adamantine_Tube:
                                    ++adamcount;
                                    break;
                                case feature_Underworld:
                                    ++hellcount;
                                    break;
                                case feature_Hell_Temple:
                                    ++templecount;
                                    break;
                                default:
                                    //something here. for debugging, it may be interesting to know.
                                    if (n) cout << '(' << n << ')';
                            }
                        }

                        n=0;
                        if ( block.local_feature > -1 && d->bits.feature_local )
                        {
                            n=local_features[pc][block.local_feature]->type;
                            switch ( n )
                            {
                                case feature_Other:
                                    //no count
                                    break;
                                case feature_Adamantine_Tube:
                                    ++adamcount;
                                    break;
                                case feature_Underworld:
                                    ++hellcount;
                                    break;
                                case feature_Hell_Temple:
                                    ++templecount;
                                    break;
                                default:
                                    //something here. for debugging, it may be interesting to know.
                                    if (n) cout << '[' << n << ']';
                            }
                        }
                    }
                }
            }
        }


        //If stopping at magma, and no no non-feature stone in this layer, and magma found, then we're either at
        //or below the magma sea / molten rock.
        if ( stopatmagma && (moltencount || magmacount) && (!exposemagma || !rockcount) )
        {
            //If not exposing magma, quit at the first sign of magma.
            //If exposing magma, quite once magma is exposed.
            done=-1;
        }


        /////////////////////////////////////////////////////////////////////////////////////////////////
        //Some checks, based on settings and stats collected
        //First check, are we at illegal depth?
        if ( !done && hellcount && stopatmagma )
        {
            //Panic!
            done=-1;
            tpat=0;
            cout << "error: illegal breach of hell!" << endl;
        }

        /////////////////////////////////////////////////////////////////////////////////////////////////
        //Actually process the current z-level.
        //These loops do the work.
        for (int32_t x=0;!done && x<16;++x)
        {
            for (int32_t y=0;!done && y<16;++y)
            {
                t=0;
                tp = getTileRow(block.tiletypes[x][y]);
                d = &block.designation[x][y];
                tpat=pattern[x][y];

                //Up front, remove aquifer, to prevent bugginess
                //It may be added back if aquify is set.
                d->bits.water_table=0;

                //Change behaviour based on settings and stats from this z-level

                //In hell?
                if ( tpat && tpat!=3 && isfeature(global_features, local_features,block,pc,x,y,feature_Underworld ) )
                {
                    if ( exposehell )
                    {
                        tpat=0;
                    }
                }

                //Expose magma?
                if ( tpat && tpat!=3 && exposemagma )
                {
                    //Leave certain tiles unchanged.
                    switch ( tp->material )
                    {
                        case HFS:
                        case FEATSTONE:
                        case MAGMA:
                            tpat=0;
                        default:
                            break;
                    }
                    //Adamantine may be left unchanged...
                    if ( isfeature(global_features, local_features,block,pc,x,y,feature_Adamantine_Tube ) )
                    {
                        tpat=0;
                    }
                    //Leave magma sea unchanged.
                    if ( d->bits.flow_size && d->bits.liquid_type)
                    {
                        tpat=0;
                    }
                }


                //For all situations...
                //Special modification for walls, always for adamantine.
                if ( isfeature(global_features, local_features,block,pc,x,y,feature_Adamantine_Tube ) )
                {
                    if ( 2==pattern[x][y] || 3==pattern[x][y] )
                    {
                        tpat=2;
                    }
                }


                //Border or space?
                switch (tpat)
                {
                    case 0:
                        continue;
                        break;
                    case 1:
                        //Empty Space
                        t=32;
                        //d->bits.light = topblock.designation[x][y].bits.light;
                        //d->bits.skyview = topblock.designation[x][y].bits.skyview;
                        //d->bits.subterranean = topblock.designation[x][y].bits.subterranean;

                        //Erase special markers?
                        //d->bits.feature_global = d->bits.feature_local = 0;

                        //Water? Magma?
                        if (fillmagma || fillwater)
                        {
                            d->bits.flow_size=7;
                            d->bits.water_stagnant = false;
                            d->bits.water_salt = false;
                            if (fillmagma)
                            {
                                d->bits.liquid_type=liquid_magma;
                            }
                            else
                            {
                                d->bits.liquid_type=liquid_water;
                            }
                        }
                        else
                        {
                            //Otherwise, remove all liquids.
                            d->bits.flow_size=0;
                            d->bits.water_stagnant = false;
                            d->bits.water_salt = false;
                            d->bits.liquid_type = liquid_water;
                        }

                        break;
                    case 2:
                        //Wall.
                        //First guess based on current material
                        switch ( tp->material )
                        {
                            case OBSIDIAN:
                                t=wmagma;
                                break;
                            case MAGMA:
                                t=wmolten;
                                break;
                            case HFS:
                                //t=whell;
                                break;
                            case VEIN:
                                t=440; //Solid vein block
                                break;
                            case FEATSTONE:
                                t=335; //Solid feature stone block
                                break;
                            default:
                                t=wcave;
                        }
                        //Adamantine (a local feature) trumps veins.
                        {
                            //Local Feature?
                            if ( block.local_feature > -1  )
                            {
                                switch ( n=local_features[pc][block.local_feature]->type )
                                {
                                    case feature_Underworld:
                                    case feature_Hell_Temple:
                                        //Only adopt these if there is no global feature present
                                        if ( block.global_feature >-1 )
                                        {
                                            break;
                                        }
                                    case feature_Adamantine_Tube:
                                        //Always for adamantine, sometimes for others
                                        //Whatever the feature is made of. "featstone wall"
                                        d->bits.feature_global = 0;
                                        d->bits.feature_local = 1;
                                        t=335;
                                        break;
                                }
                            }
                            //Global Feature?
                            else if (block.global_feature > -1 && !d->bits.feature_local )
                            {
                                switch ( n=global_features[block.global_feature].type )
                                {
                                    case feature_Adamantine_Tube:
                                    case feature_Underworld:
                                    case feature_Hell_Temple:
                                        //Whatever the feature is made of. "featstone wall"
                                        d->bits.feature_global = 1;
                                        t=335;
                                        break;
                                }
                            }
                        }

                        //Erase any liquids, as they cause problems.
                        d->bits.flow_size=0;
                        d->bits.water_stagnant = false;
                        d->bits.water_salt = false;
                        d->bits.liquid_type=liquid_water;

                        //Placing an aquifer?
                        //(bugged, these aquifers don't generate water!)
                        if ( aquify )
                        {
                            //Only normal stone types can be aquified
                            if ( tp->material!=MAGMA && tp->material!=FEATSTONE && tp->material!=HFS  )
                            {
                                //Only place next to the hole.
                                //If no hole, place in middle.
                                if ( checkneighbors(pattern,x,y,1) || (7==x && 7==y) )
                                {
                                    d->bits.water_table = 1;
                                    //t=265; //soil wall
                                }
                            }
                        }
                        break;
                    case 3:
                        ////No obsidian walls on bottom of map!
                        //if(z<1 && (d->bits.feature_global || d->bits.feature_local) ) {
                        //  t=335;
                        //}

                        //Special wall, always sets to obsidian, to give a stairway
                        t=331;

                        //Erase special markers
                        d->bits.feature_global = d->bits.feature_local = 0;

                        //Erase any liquids, as they cause problems.
                        d->bits.flow_size=0;
                        d->bits.water_stagnant = false;
                        d->bits.water_salt = false;
                        d->bits.liquid_type=liquid_water;
                        break;
                    default:
                        cout << ".error,bad pattern.";
                }

                //For all tiles.
                if (reveal)
                {
                    d->bits.hidden = 0; //topblock.designation[x][y].bits.hidden;
                }
                //Always clear the dig designation.
                d->bits.dig=designation_no;
                //Make it underground, because it is capped
                d->bits.subterranean=1;
                d->bits.light=0;
                d->bits.skyview=0;
                //unlock fluids, so they fall down the pit.
                d->bits.flow_forbid = d->bits.liquid_static=0;
                block.blockflags.bits.liquid_1 = block.blockflags.bits.liquid_2 = 1;
                //Set the tile.
                block.tiletypes[x][y] = t;

            }
        }

        //Write the block.
        Mapz->WriteBlockFlags(bx,by,z, block.blockflags );
        Mapz->WriteDesignations(bx,by,z, &block.designation );
        Mapz->WriteTileTypes(bx,by,z, &block.tiletypes );
        Mapz->WriteDirtyBit(bx,by,z,1);

    }

    //Re-process the last z-level handled above.
    z++;
    assert( z>=0 );


    ///////////////////////////////////////////////////////////////////////////////////////////////
    //The bottom level is special.
    if (-1)
    {
        if (!Mapz->ReadBlock40d( bx, by, z , &block ))
        {
            cout << "Bad block! " << bx << "," << by << "," << z << endl;
        }
        for (uint32_t x=0;x<16;++x)
        {
            for (uint32_t y=0;y<16;++y)
            {
                t=floor;
                v=floorvar;
                tp = getTileRow(block.tiletypes[x][y]);
                d = &block.designation[x][y];

                if ( exposehell )
                {
                    //Leave hell tiles unchanged when exposing hell.
                    if ( isfeature(global_features,local_features,block,pc,x,y,feature_Underworld) )
                    {
                        continue;
                    }
                }

                //Does expose magma need anything at this level?
                if ( exposemagma && stopatmagma )
                {
                    continue;
                }

                switch (pattern[x][y])
                {
                    case 0:
                        continue;
                        break;
                    case 1:
                        //Empty becomes floor.

                        //Base floor type on the z-level first, features, then tile type.
                        if (!z) {
                            //Bottom of map, use the floor specified, always.
                            break;
                        }

                        ////Only place floor where ground is already solid when exposing
                        //if( EMPTY == tp->c || RAMP_TOP == tp->c || STAIR_DOWN == tp->c ){
                        //  continue;
                        //}

                        if ( d->bits.feature_global || d->bits.feature_global ) {
                            //Feature Floor!
                            t=344;
                            break;
                        }

                        //Tile material check.
                        switch ( tp->material )
                        {
                            case OBSIDIAN:
                                t=340;
                                v=3;
                                break;
                            case MAGMA:
                                v=0;
                                t=264; //magma flow
                                break;
                            case HFS:
                                //should only happen at bottom of map
                                break;
                            case VEIN:
                                t=441;  //vein floor
                                v=3;
                                break;
                            case FEATSTONE:
                                t=344;
                                v=3;
                                break;
                        }

                        break;
                    case 2:
                    case 3:
                        //Walls already drawn.
                        //Ignore.
                        continue;
                        break;
                }

                //For all tiles.
                if (reveal) d->bits.hidden = 0; //topblock.designation[x][y].bits.hidden;
                //Always clear the dig designation.
                d->bits.dig=designation_no;
                //unlock fluids
                d->bits.flow_forbid = d->bits.liquid_static=0;
                block.blockflags.bits.liquid_1 = block.blockflags.bits.liquid_2 = 1;

                //Set the tile.
                block.tiletypes[x][y] = t + ( v ? rand()&v : 0 );
            }
        }
        //Write the block.
        Mapz->WriteBlockFlags(bx,by,z, block.blockflags );
        Mapz->WriteDesignations(bx,by,z, &block.designation );
        Mapz->WriteTileTypes(bx,by,z, &block.tiletypes );
        Mapz->WriteDirtyBit(bx,by,z,1);
    }

    DF->Detach();
#ifndef LINUX_BUILD
    cout << "Done. Press any key to continue" << endl;
    cin.ignore();
#endif
    return 0;
}
示例#17
0
文件: autodump.cpp 项目: kaypy/dfhack
static command_result autodump_main(Core * c, vector <string> & parameters)
{
    // Command line options
    bool destroy = false;
    bool here = false;
    if(parameters.size() > 0)
    {
        string & p = parameters[0];
        if(p == "destroy")
            destroy = true;
        else if (p == "destroy-here")
            destroy = here = true;
        else if(p == "?" || p == "help")
        {
            c->con.print(
                "This utility lets you quickly move all items designated to be dumped.\n"
                "Items are instantly moved to the cursor position, the dump flag is unset,\n"
                "and the forbid flag is set, as if it had been dumped normally.\n"
                "Be aware that any active dump item tasks still point at the item.\n\n"
                "Options:\n"
                "destroy       - instead of dumping, destroy the items instantly.\n"
                "destroy-here  - only affect the tile under cursor.\n"
                        );
            return CR_OK;
        }
    }
    c->Suspend();
    DFHack::VersionInfo *mem = c->vinfo;
    DFHack::Gui * Gui = c->getGui();
    DFHack::Items * Items = c->getItems();
    DFHack::Maps *Maps = c->getMaps();

    vector <df_item*> p_items;
    if(!Items->readItemVector(p_items))
    {
        c->con.printerr("Can't access the item vector.\n");
        return CR_FAILURE;
    }
    std::size_t numItems = p_items.size();

    // init the map
    if(!Maps->Start())
    {
        c->con.printerr("Can't initialize map.\n");
        return CR_FAILURE;
    }
    MapCache MC (Maps);
    int i = 0;
    int dumped_total = 0;

    int cx, cy, cz;
    DFCoord pos_cursor;
    if(!destroy || here)
    {
        if (!Gui->getCursorCoords(cx,cy,cz))
        {
            c->con.printerr("Cursor position not found. Please enabled the cursor.\n");
            return CR_FAILURE;
        }
        pos_cursor = DFCoord(cx,cy,cz);
    }
    if (!destroy)
    {
        {
            Block * b = MC.BlockAt(pos_cursor / 16);
            if(!b)
            {
                c->con.printerr("Cursor is in an invalid/uninitialized area. Place it over a floor.\n");
                return CR_FAILURE;
            }
            uint16_t ttype = MC.tiletypeAt(pos_cursor);
            if(!DFHack::isFloorTerrain(ttype))
            {
                c->con.printerr("Cursor should be placed over a floor.\n");
                return CR_FAILURE;
            }
        }
    }
    coordmap counts;
    // proceed with the dumpification operation
    for(std::size_t i=0; i< numItems; i++)
    {
        df_item * itm = p_items[i];
        DFCoord pos_item(itm->x, itm->y, itm->z);

        // keep track how many items are at places. all items.
        coordmap::iterator it = counts.find(pos_item);
        if(it == counts.end())
        {
            std::pair< coordmap::iterator, bool > inserted = counts.insert(std::make_pair(pos_item,1));
            it = inserted.first;
        }
        else
        {
            it->second ++;
        }
        // iterator is valid here, we use it later to decrement the pile counter if the item is moved

        // only dump the stuff marked for dumping and laying on the ground
        if (   !itm->flags.dump
            || !itm->flags.on_ground
            ||  itm->flags.construction
            ||  itm->flags.hidden
            ||  itm->flags.in_building
            ||  itm->flags.in_chest
            ||  itm->flags.in_inventory
            ||  itm->flags.artifact1
        )
            continue;

        if(!destroy) // move to cursor
        {
            // Change flags to indicate the dump was completed, as if by super-dwarfs
            itm->flags.dump = false;
            itm->flags.forbid = true;

            // Don't move items if they're already at the cursor
            if (pos_cursor == pos_item)
                continue;

            // Do we need to fix block-local item ID vector?
            if(pos_item/16 != pos_cursor/16)
            {
                // yes...
                cerr << "Moving from block to block!" << endl;
                df_block * bl_src = Maps->getBlock(itm->x /16, itm->y/16, itm->z);
                df_block * bl_tgt = Maps->getBlock(cx /16, cy/16, cz);
                if(bl_src)
                {
                    std::remove(bl_src->items.begin(), bl_src->items.end(),itm->id);
                }
                else
                {
                    cerr << "No source block" << endl;
                }
                if(bl_tgt)
                {
                    bl_tgt->items.push_back(itm->id);
                }
                else
                {
                    cerr << "No target block" << endl;
                }
            }

            // Move the item
            itm->x = pos_cursor.x;
            itm->y = pos_cursor.y;
            itm->z = pos_cursor.z;
        }
        else // destroy
        {
            if (here && pos_item != pos_cursor)
                continue;

            itm->flags.garbage_colect = true;

            // Cosmetic changes: make them disappear from view instantly
            itm->flags.forbid = true;
            itm->flags.hidden = true;
        }
        // keeping track of item pile sizes ;)
        it->second --;
        dumped_total++;
    }
    if(!destroy) // TODO: do we have to do any of this when destroying items?
    {
        // for each item pile, see if it reached zero. if so, unset item flag on the tile it's on
        coordmap::iterator it = counts.begin();
        coordmap::iterator end = counts.end();
        while(it != end)
        {
            if(it->second == 0)
            {
                t_occupancy occ = MC.occupancyAt(it->first);
                occ.bits.item = false;
                MC.setOccupancyAt(it->first, occ);
            }
            it++;
        }
        // Set "item here" flag on target tile, if we moved any items to the target tile.
        if (dumped_total > 0)
        {
            // assume there is a possibility the cursor points at some weird location with missing block data
            Block * b = MC.BlockAt(pos_cursor / 16);
            if(b)
            {
                t_occupancy occ = MC.occupancyAt(pos_cursor);
                occ.bits.item = 1;
                MC.setOccupancyAt(pos_cursor,occ);
            }
        }
        // write map changes back to DF.
        MC.WriteAll();
        // Is this necessary?  Is "forbid" a dirtyable attribute like "dig" is?
        Maps->WriteDirtyBit(cx/16, cy/16, cz, true);
    }
    c->con.print("Done. %d items %s.\n", dumped_total, destroy ? "marked for desctruction" : "quickdumped");
    return CR_OK;
}