@ -21,6 +21,7 @@ command_result follow (Core * c, std::vector <std::string> & parameters);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					df : : unit  * followedUnit ; 
 
					 
					 
					 
					df : : unit  * followedUnit ; 
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					int32_t  prevX ,  prevY ,  prevZ ; 
 
					 
					 
					 
					int32_t  prevX ,  prevY ,  prevZ ; 
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					uint8_t  prevMenuWidth ; 
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					DFhackCExport  const  char  *  plugin_name  (  void  ) 
 
					 
					 
					 
					DFhackCExport  const  char  *  plugin_name  (  void  ) 
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					{ 
 
					 
					 
					 
					{ 
 
				
			 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
							 
						
					 
					 
					@ -38,6 +39,7 @@ DFhackCExport command_result plugin_init ( Core * c, std::vector <PluginCommand>
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    ) ) ; 
 
					 
					 
					 
					    ) ) ; 
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    followedUnit  =  0 ; 
 
					 
					 
					 
					    followedUnit  =  0 ; 
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    prevX = prevY = prevZ  =  - 1 ; 
 
					 
					 
					 
					    prevX = prevY = prevZ  =  - 1 ; 
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    prevMenuWidth  =  0 ; 
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    return  CR_OK ; 
 
					 
					 
					 
					    return  CR_OK ; 
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					} 
 
					 
					 
					 
					} 
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
							 
						
					 
					 
					@ -47,17 +49,14 @@ DFhackCExport command_result plugin_shutdown ( Core * c )
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    return  CR_OK ; 
 
					 
					 
					 
					    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 ) 
 
					 
					 
					 
					DFhackCExport  command_result  plugin_onstatechange ( Core *  c ,  state_change_event  event ) 
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					{ 
 
					 
					 
					 
					{ 
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    switch  ( event )  { 
 
					 
					 
					 
					    switch  ( event )  { 
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    case  SC_GAME_LOADED : 
 
					 
					 
					 
					    case  SC_GAME_LOADED : 
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    case  SC_GAME_UNLOADED : 
 
					 
					 
					 
					    case  SC_GAME_UNLOADED :  //Make sure our plugin's variables are clean
  
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					        followedUnit  =  0 ; 
 
					 
					 
					 
					        followedUnit  =  0 ; 
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        prevX = prevY = prevZ  =  - 1 ; 
 
					 
					 
					 
					        prevX = prevY = prevZ  =  - 1 ; 
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        prevMenuWidth  =  0 ; 
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        break ; 
 
					 
					 
					 
					        break ; 
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    default : 
 
					 
					 
					 
					    default : 
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        break ; 
 
					 
					 
					 
					        break ; 
 
				
			 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
							 
						
					 
					 
					@ -68,50 +67,80 @@ DFhackCExport command_result plugin_onstatechange(Core* c, state_change_event ev
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					DFhackCExport  command_result  plugin_onupdate  (  Core  *  c  ) 
 
					 
					 
					 
					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 ( ) ; 
 
					 
					 
					 
					    DFHack : : World  * world  = c - > getWorld ( ) ; 
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    if  ( world - > ReadPauseState ( )  & &  prevX = = - 1 )  return  CR_OK ; 
 
					 
					 
					 
					    if  ( world - > ReadPauseState ( )  & &  prevX = = - 1 )  return  CR_OK ;  //Wait until the game is unpaused after first running "follow" to begin following
  
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
					    Gui  * gui  =  c - > getGui ( ) ;  
 
					 
					 
					 
					
 
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					    df : : coord  & unitPos  =  followedUnit - > pos ; 
 
					 
					 
					 
					    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 - > getViewCoords ( x , y , z ) ; 
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    gui - > getWindowSize ( w , h ) ; 
 
					 
					 
					 
					    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 ; 
 
					 
					 
					 
					        prevX  =  x ; 
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        prevY  =  y ; 
 
					 
					 
					 
					        prevY  =  y ; 
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        prevZ  =  z ; 
 
					 
					 
					 
					        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 ; 
 
					 
					 
					 
					        followedUnit  =  0 ; 
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        prevX = prevY = prevZ  =  - 1 ; 
 
					 
					 
					 
					        prevX = prevY = prevZ  =  - 1 ; 
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        prevMenuWidth  =  0 ; 
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        c - > con . print ( " No longer following anything. \n " ) ; 
 
					 
					 
					 
					        c - > con . print ( " No longer following anything. \n " ) ; 
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        return  CR_OK ; 
 
					 
					 
					 
					        return  CR_OK ; 
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    } 
 
					 
					 
					 
					    } 
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    
 
					 
					 
					 
					    
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    uint32_t  x_max ,  y_max ,  z_max ; 
 
					 
					 
					 
					    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 ; 
 
					 
					 
					 
					    x_max  * =  16 ; 
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    y_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 ) ; 
 
					 
					 
					 
					    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
 
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
					    prevY  =  unitPos . y  +  h / 2  > =  y_max  ?  y_max - h + 2  :  ( unitPos . y  > =  h / 2  ?  unitPos . y  -  h / 2  :  0 ) ; 
 
					 
					 
					 
					    y  =  unitPos . y  +  h / 2  > =  y_max  ?  y_max - h  :  ( unitPos . y  > =  h / 2  ?  unitPos . y  -  h / 2  :  0 ) ; 
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
					    prevZ  =  unitPos . z ; 
 
					 
					 
					 
					    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 ; 
 
					 
					 
					 
					    return  CR_OK ; 
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					} 
 
					 
					 
					 
					} 
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					command_result  follow  ( Core  *  c ,  std : : vector  < std : : string >  &  parameters ) 
 
					 
					 
					 
					command_result  follow  ( Core  *  c ,  std : : vector  < std : : string >  &  parameters ) 
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					{ 
 
					 
					 
					 
					{   
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					    if  ( ! parameters . empty ( ) ) 
 
					 
					 
					 
					    if  ( ! parameters . empty ( ) ) 
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        return  CR_WRONG_USAGE ; 
 
					 
					 
					 
					        return  CR_WRONG_USAGE ; 
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    CoreSuspender  suspend ( c ) ; 
 
					 
					 
					 
					    CoreSuspender  suspend ( c ) ; 
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    if  ( followedUnit ) 
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    { 
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        c - > con . print ( " No longer following previously selected unit. \n " ) ; 
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        followedUnit  =  0 ; 
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    } 
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    followedUnit  =  getSelectedUnit ( c ) ; 
 
					 
					 
					 
					    followedUnit  =  getSelectedUnit ( c ) ; 
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    if  ( followedUnit ) 
 
					 
					 
					 
					    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 ( "  %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 ; 
 
					 
					 
					 
					    else  followedUnit  =  0 ; 
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    return  CR_OK ; 
 
					 
					 
					 
					    return  CR_OK ;