summaryrefslogtreecommitdiff
path: root/plugins/follow.cpp
diff options
context:
space:
mode:
authorMike Stewart2012-02-21 23:30:44 -0800
committerMike Stewart2012-02-21 23:30:44 -0800
commit14b471a45933c5eb8b94c834a387ea91b0644a00 (patch)
treed2d6d9ba2372719a534a53bd82c0ed5ca2e64d1f /plugins/follow.cpp
parentf8d0b83b0a1d7033351bad67c6abecfbf573dcc6 (diff)
downloaddfhack-14b471a45933c5eb8b94c834a387ea91b0644a00.tar.gz
dfhack-14b471a45933c5eb8b94c834a387ea91b0644a00.tar.bz2
dfhack-14b471a45933c5eb8b94c834a387ea91b0644a00.tar.xz
Add ability menu/area map width reading and writing to the Gui module, and use the new information in follow to properly center the screen regardless of menu configuration. Also general fixing and cleanup in follow.
Diffstat (limited to 'plugins/follow.cpp')
-rw-r--r--plugins/follow.cpp69
1 files changed, 50 insertions, 19 deletions
diff --git a/plugins/follow.cpp b/plugins/follow.cpp
index 2c4237b3..19536f25 100644
--- a/plugins/follow.cpp
+++ b/plugins/follow.cpp
@@ -21,6 +21,7 @@ command_result follow (Core * c, std::vector <std::string> & parameters);
df::unit *followedUnit;
int32_t prevX, prevY, prevZ;
+uint8_t prevMenuWidth;
DFhackCExport const char * plugin_name ( void )
{
@@ -38,6 +39,7 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand>
));
followedUnit = 0;
prevX=prevY=prevZ = -1;
+ prevMenuWidth = 0;
return CR_OK;
}
@@ -47,17 +49,14 @@ DFhackCExport command_result plugin_shutdown ( Core * c )
return CR_OK;
}
-// Called to notify the plugin about important state changes.
-// Invoked with DF suspended, and always before the matching plugin_onupdate.
-// More event codes may be added in the future.
-
DFhackCExport command_result plugin_onstatechange(Core* c, state_change_event event)
{
switch (event) {
case SC_GAME_LOADED:
- case SC_GAME_UNLOADED:
+ case SC_GAME_UNLOADED: //Make sure our plugin's variables are clean
followedUnit = 0;
prevX=prevY=prevZ = -1;
+ prevMenuWidth = 0;
break;
default:
break;
@@ -68,50 +67,80 @@ DFhackCExport command_result plugin_onstatechange(Core* c, state_change_event ev
DFhackCExport command_result plugin_onupdate ( Core * c )
{
- if (!followedUnit) return CR_OK;
+ if (!followedUnit) return CR_OK; //Don't do anything if we're not following a unit
+
DFHack::World *world =c->getWorld();
- if (world->ReadPauseState() && prevX==-1) return CR_OK;
- Gui *gui = c->getGui();
+ if (world->ReadPauseState() && prevX==-1) return CR_OK; //Wait until the game is unpaused after first running "follow" to begin following
+
df::coord &unitPos = followedUnit->pos;
- int32_t x,y,z,w,h;
+
+ Gui *gui = c->getGui(); //Get all of the relevant data for determining the size of the map on the window
+ int32_t x,y,z,w,h,c_x,c_y,c_z;
+ uint8_t menu_width, area_map_width;
gui->getViewCoords(x,y,z);
gui->getWindowSize(w,h);
- if (prevX==-1)
+ gui->getMenuWidth(menu_width, area_map_width);
+ gui->getCursorCoords(c_x,c_y,c_z);
+
+ if (c_z == -3000 && menu_width == 3) menu_width = 2; //Presence of the cursor means that there's actually a width-2 menu open
+
+ h -= 2; //account for vertical borders
+
+ if (menu_width == 1) w -= 57; //Menu is open doubly wide
+ else if (menu_width == 2 && area_map_width == 3) w -= 33; //Just the menu is open
+ else if (menu_width == 2 && area_map_width == 2) w -= 26; //Just the area map is open
+ else w -= 2; //No menu or area map, just account for borders
+
+ if (prevMenuWidth == 0) prevMenuWidth = menu_width; //have we already had a menu width?
+
+ if (prevX==-1) //have we already had previous values for the window location?
{
prevX = x;
prevY = y;
prevZ = z;
}
- else if(prevX != x || prevY != y || prevZ != z)
+ else if((prevX != x || prevY != y || prevZ != z) && prevMenuWidth == menu_width) //User has manually moved the window, stop following the unit
{
followedUnit = 0;
prevX=prevY=prevZ = -1;
+ prevMenuWidth = 0;
c->con.print("No longer following anything.\n");
return CR_OK;
}
uint32_t x_max, y_max, z_max;
- Simple::Maps::getSize(x_max, y_max, z_max);
-
+ Simple::Maps::getSize(x_max, y_max, z_max); //Get map size in tiles so we can prevent the camera from going off the edge
x_max *= 16;
y_max *= 16;
- prevX = unitPos.x + w/2 >= x_max ? x_max-w+2 : (unitPos.x >= w/2 ? unitPos.x - w/2 : 0);
- prevY = unitPos.y + h/2 >= y_max ? y_max-h+2 : (unitPos.y >= h/2 ? unitPos.y - h/2 : 0);
- prevZ = unitPos.z;
+ x = unitPos.x + w/2 >= x_max ? x_max-w : (unitPos.x >= w/2 ? unitPos.x - w/2 : 0); //Calculate a new screen position centered on the selected unit
+ y = unitPos.y + h/2 >= y_max ? y_max-h : (unitPos.y >= h/2 ? unitPos.y - h/2 : 0);
+ z = unitPos.z;
+
+ gui->setViewCoords(x, y, z); //Set the new screen position!
- gui->setViewCoords(prevX, prevY, prevZ);
+ if (c_x != 3000 && !world->ReadPauseState()) gui->setCursorCoords(c_x - (prevX-x), c_y - (prevY-y), z); //If, for some reason, the cursor is active and the screen is still moving, move the cursor along with the screen
+ prevX = x; //Save this round's stuff for next time so we can monitor for changes made by the user
+ prevY = y;
+ prevZ = z;
+ prevMenuWidth = menu_width;
+
return CR_OK;
}
command_result follow (Core * c, std::vector <std::string> & parameters)
-{
+{
if (!parameters.empty())
return CR_WRONG_USAGE;
CoreSuspender suspend(c);
+ if (followedUnit)
+ {
+ c->con.print("No longer following previously selected unit.\n");
+ followedUnit = 0;
+ }
followedUnit = getSelectedUnit(c);
if (followedUnit)
{
@@ -121,7 +150,9 @@ command_result follow (Core * c, std::vector <std::string> & parameters)
{
c->con.print(" %s", followedUnit->name.first_name.c_str());
}
- c->con.print(".\n");
+ c->con.print(". Simply manually move the view to break the following.\n");
+ prevX=prevY=prevZ = -1;
+ prevMenuWidth = 0;
}
else followedUnit = 0;
return CR_OK;