User Tools

Site Tools


client_side_scripting:cfequip.cpp
/* cfequip.cpp
 * $Id: cfequip.cpp,v 1.3 2005/12/01 23:11:02 tbrown Exp $
 * Author: Terry Brown
 * Created: Tue Nov 29 2005
 */

/*

Bugs, contact:

  terry_n_brown@yahoo.com

To compile:

   g++ cfequip.cpp -o cfequip

To run from within the client:

   script /path/to/cfequip

Commands to script from client:

(replace '1' with the number of the script if more than one running,
use client command 'scripts' to list)

scripttell 1 cfe file <filename>
  set the file for storing / reading equipment sets

scripttell 1 cfe store <name>
save current equipment set as <name> (use a single word)
  the file is written every time you use this command, so there's no need
  to save before you quit

scripttell 1 cfe use <name> 
  equip the equipment set <name>

scripttell 1 cfe list
  list known equipment sets

scripttell 1 cfe quit
  quit the script - not really necessary

Equipment needs unique names, e.g. "shoes +1" might be confused with
"red shoes +1" - just rename the items as needed.

Containers behave oddly, because "apply -u bag" opens rather than drops
an active but non-open bag.

*/

#include <vector>
#include <map>
#include <iostream>  
#include <fstream>

using namespace std;

#define inv_col_flag 6 // request items inv returns multiple columns, with
                       // flags in column inv_col_flag
#define inv_col_name 8 // and the name starting in column inv_col_name
#define flag_equip 8   // the flags value to test for being equipped
#define red "draw 3 "  // see crossfire-client-1.8.0/common/newclient.h NDI_RED
#define blue "draw 5 "

// make a string of words into a vector of words
vector<string> stringToVector(const string &s);

// class the handle equipment sets
class EquipmentSets 
{
public:
  void setfile(const string &fn);  // set the file sets are stored in
  void store(const string &name);  // store current equipment as set <name>
  void use(const string &name);    // equip equipment set <name>
  void list();                     // list stored equipment sets

private:

  typedef map<string, vector<string> > eSets;
  eSets m_dat;
  string m_fn;

  bool load(const string &fn);
  void save(const string &fn);
};

void EquipmentSets::setfile(const string &fn)
{
  m_fn = fn;
  m_dat.clear();
  if (!load(m_fn))
    {
      cout << red << "Couldn't open '" << m_fn 
	   << "', will create on first"
	   << " cfe_store command (if writeable)\n";
    }
  else
    {
      cout << blue << "Loaded " << m_fn << "\n";
      list();
    }
}

bool EquipmentSets::load(const string &fn)
{
  ifstream in(fn.c_str(), ios::in);
  if (!in)
    {
      return false;
    }

  m_dat.clear();
  string c;
  while (in.good())
    {
      string l;
      getline(in, l);
      if (l.length() < 1)
	{
	  break;
	}
      if (l[0] != '\t')
	{
	  c = l;
	  cout << blue << "Set '" << c << "'\n";
	}
      else
	{
	  m_dat[c].push_back(l.substr(1));
	  cout << blue << l << "'\n";
	}
    }

  return true;
}

void EquipmentSets::save(const string &fn)
{
  ofstream out(fn.c_str(), ios::out);
  if (!out)
    {
      cout << red << "ERROR - couldn't write to '"
	   << fn << "'\n"; 
      return;
    }

  for (eSets::const_iterator i = m_dat.begin();
       i != m_dat.end(); i++)
    {
      out << (*i).first << "\n";

      for (vector<string>::const_iterator j = (*i).second.begin();
	   j != (*i).second.end(); j++)
	{
	  out << "\t" << *j << "\n";
	}
    }
}

void EquipmentSets::list()
{
  cout << blue << m_dat.size() << " sets loaded\n";
  for (eSets::const_iterator i = m_dat.begin();
       i != m_dat.end(); i++)
    {
      cout << blue << (*i).first << "\n";
    }
}

void EquipmentSets::store(const string &s)
{
  m_dat[s].clear();

  cout << "request items inv\n";
  string l;

  while (getline(cin, l))
    {
      vector<string> r = stringToVector(l);

      if (r[3] == "end")
	{
	  break;
	}

      if  (r[0]+r[1]+r[2] == ("request" "items" "inv") )
	{
	  int flags = atol(r[inv_col_flag].c_str());
	  if (flags & flag_equip) 
	    {
	      string item = "";
	      string comma = "";
	      for (unsigned int i = inv_col_name; i < r.size(); i++)
		{
		  item = item + comma + r[i];
		  comma = " ";
		}
	      cout << blue << item << "\n";
	      m_dat[s].push_back(item);
	    }
	}
    }

  save(m_fn);

  cout << blue << "saved\n";

}

void EquipmentSets::use(const string &s)
{

  if (m_dat.find(s) == m_dat.end())
    {
      cout << red << "Can't find set '" << s << "'\n";
      list();
      return;
    }

  cout << blue << "use " << s << " (" << m_dat[s].size() << " items)\n";
  cout << "request items inv\n";
  string l;

  while (getline(cin, l))
    {
      vector<string> r = stringToVector(l);

      if (r[3] == "end")
	{
	  break;
	}

      if  (r[0]+r[1]+r[2] == ("request" "items" "inv") )
	{
	  int flags = atol(r[inv_col_flag].c_str());
	  if (flags & flag_equip) 
	    {
	      string item = "";
	      string comma = "";
	      for (unsigned int i = inv_col_name; i < r.size(); i++)
		{
		  item = item + comma + r[i];
		  comma = " ";
		}
	      // cout << blue << item << "\n";
	      cout << "issue 1 1 apply -u " << item << "\n";
	      
	    }
	}
    }
  
  for (vector<string>::const_iterator j = (m_dat[s]).begin();
       j != m_dat[s].end(); j++)
    {
      cout << "issue 1 1 apply -a " << *j << "\n";
    }
}

vector<string> stringToVector(const string &s)
{
  vector<string> ans;

  string part;

  for (unsigned int i=0; i < s.length(); i++)
    {
      if (s[i] > ' ')
	{
	  part += s[i];
	}
      else
	{
	  if (part.length() > 0)
	    {
	      ans.push_back(part);
	    }
	  part = "";
	}
    }

  if (part.length() > 0)
    {
      ans.push_back(part);
    }

  return ans;
}

int main()
{
  string s;

  cout << blue << "Starting cfequip\n";
  cout << blue << "================\n";
  cout << blue << "\n";
  cout << blue << "Supply equipment set file name with:\n";
  cout << blue << "  scripttell 1 cfe file <filename>\n";
  cout << blue << "Other commands:\n";
  cout << blue << "  scripttell 1 cfe list - list known equipment sets\n";
  cout << blue << "  scripttell 1 cfe quit - end script\n";
  cout << blue << "  scripttell 1 cfe store <name> - store current equipment as <name>\n";
  cout << blue << "  scripttell 1 cfe use <name> - equip equipment set <name>\n";

  EquipmentSets es;

  while (cin.good())
    {
      getline(cin, s);

      vector<string> r = stringToVector(s);

      if  (r[0] + r[2] == ("scripttell" "cfe") )
	{
	  if (r.size() == 5 && r[3] == "file")
	    {
	      es.setfile(r[4]);
	    }
	  else if (r.size() == 4 && r[3] == "quit")
	    {
	      cout << blue << "cfequip quitting\n";
	      cout.flush();
	      return 0;
	    }
	  else if (r.size() == 4 && r[3] == "list")
	    {
	      es.list();
	    }
	  else if (r.size() == 5 && r[3] == "store")
	    {
	      es.store(r[4]);
	    }
	  else if (r.size() == 5 && r[3] == "use")
	    {
	      es.use(r[4]);
	    }
	  else 
	    {
	      cout << red << "invalid cfe command\n";
	    }
	} 

      cout.flush();
    }
  
  return 0;

}
client_side_scripting/cfequip.cpp.txt · Last modified: 2009/04/29 14:18 (external edit)