Ir para conteúdo

Teleport Manager @ Thechaos Style - V0.1a


Posts Recomendados

Vamos lá, eu fiz isso pq era um saco esses comandos que você tinha que editar no config.lua, num sei onde, num sei nas sources e sempre muito limitado. Com esse não, você tem um grande leque de opções, com nome e podendo editar tudo dentro do próprio jogo, sem mecher na xml, mas você também pode editar por ela caso preciso ;)

 

Vamos lá, abra suas sources e vamos começar!

 

Commands.cpp

Depois de:

{"/raid",&Commands::forceRaid},

 

Adicione:

{"/teleport",&Commands::teleportManager},

Essa linha vai ser nosso comando ingame. (faz sentido...)

 

Na função dos reloads nos commands, depois de:

else if(param == "raids"){

Raids::getInstance()->reload();

Raids::getInstance()->startup();

}

 

Adicione:

else if(param == "teleports"){
  this->reloadTeleports(true);
}

Pra quando a gente der um "/reload teleports" dentro do jogo, ele vai limpa os teleports atuais e carregar os do xml de novo. Bom pra edições manuais no xml.

 

Tá agora vá la no fim do arquivo, e adicione:

bool Commands::teleportManager(Creature* creature, const std::string& cmd, const std::string& param){
  Player* player = creature->getPlayer();
  if(!player)
  return false;

  std::stringstream teste;
  std::string func, cname;

  bool jump = false;   

  std::string::size_type pos = param.find(",", 0);
  if(pos == std::string::npos){
  jump = true;
  pos = param.size();
  }
  func = param.substr(0, pos).c_str();

  TeleportMap::iterator it;
  if(func == "edit"){
  Item* book = Item::CreateItem(2597);
  std::stringstream tds;  
  tds << "Teleport\n";
  for(it = teleportMap.begin(); it != teleportMap.end(); ++it){
	 tds << it->second->name << ": x:\""<<it->second->dest.x<<"\" y:\""<<it->second->dest.y<<"\" z:\""<<it->second->dest.z<<"\"."<<std::endl;
  }
  book->setText(tds.str().c_str());
  player->sendTextWindow(book,65535, true);
  return false;   
  }
  if(func.substr(0,3) == "add"){
  it = teleportMap.find(func.substr(4,func.size()));
  if(it != teleportMap.end())
	 player->sendTextMessage(MSG_INFO_DESCR, "This name is already being used as teleport position.");   
  else{
	 Teleports* tp = new Teleports;
	 tp->name = func.substr(4,func.size());
	 tp->dest.x = player->getPosition().x;
	 tp->dest.y = player->getPosition().y;
	 tp->dest.z = player->getPosition().z;
	 player->sendTextMessage(MSG_INFO_DESCR, "New Teleport Added.");  
	 teleportMap[tp->name] = tp;
	 saveTeleportXml("NULL");
  }
  }
  if(func.substr(0,6) == "remove"){
  it = teleportMap.find(func.substr(7, func.size()));
  if(it != teleportMap.end()){
	 teleportMap.erase(it);
	 saveTeleportXml("NULL");
	 player->sendTextMessage(MSG_INFO_DESCR, "Teleport deleted.");
  }
  }

  Creature* toMove = creature;
  if(!jump){
  cname = param.substr(pos+2, param.size()).c_str();
  toMove = game->getCreatureByName(cname);
  if(!toMove){
	 player->sendTextMessage(MSG_INFO_DESCR, "This name doesnt belong to any creature online.");
	 return false;	 
  }
  }  

  it = teleportMap.find(func);
  if(it != teleportMap.end()){
  if(game->internalTeleport(toMove, it->second->dest) == RET_NOERROR){
  game->addMagicEffect(it->second->dest, NM_ME_ENERGY_AREA);
  return true;
  }
  }
}
bool Commands::saveTeleportXml(const std::string& text)
{
  std::string tmp = text;
  std::string::size_type pos;
  std::stringstream sb;
  std::string datadir = g_config.getString(ConfigManager::DATA_DIRECTORY);
  std::string filename = datadir + "teleports.xml";
  xmlNodePtr pn, root;

  if(tmp != "NULL"){
  reloadTeleports(false);
  tmp.erase(0,9);//Erase Teleports\n
  while(tmp.size()  > 1){
	 Teleports* temp = new Teleports;				   
	 pos = tmp.find(':', 0);
	 sb.str("");
	 sb << tmp.substr(0, pos).c_str();// Nome da cidade
	 temp->name = sb.str().c_str();

	 tmp.erase(0, pos+5);
	 pos = tmp.find('y', 0);
	 sb.str("");
	 sb <<tmp.substr(0,pos-2);//Tirar X
	 temp->dest.x = atoi(sb.str().c_str());

	 tmp.erase(0, pos+3);
	 pos = tmp.find('z',0);
	 sb.str("");
	 sb <<tmp.substr(0,pos-2);//Tirar Y
	 temp->dest.y = atoi(sb.str().c_str());

	 tmp.erase(0, pos+3);
	 pos = tmp.find('.',0);
	 sb.str("");
	 sb <<tmp.substr(0,pos-1);//Tirar Z
	 temp->dest.z = atoi(sb.str().c_str());
	 tmp.erase(0, pos+2);

	 teleportMap[temp->name] = temp;
  }
  }

  xmlDocPtr doc = xmlNewDoc((const xmlChar*)"1.0");
  doc->children = xmlNewDocNode(doc, NULL, (const xmlChar*)"teleports", NULL);
  root = doc->children;
  TeleportMap::iterator it = teleportMap.begin();
  while(it != teleportMap.end()){
  pn = xmlNewNode(NULL,(const xmlChar*)"teleport");

  sb.str("");
  sb << it->second->name;
  xmlSetProp(pn, (const xmlChar*)"name", (const xmlChar*)sb.str().c_str());

  sb.str("");
  sb << it->second->dest.x;
  xmlSetProp(pn, (const xmlChar*)"posX", (const xmlChar*)sb.str().c_str());

  sb.str("");
  sb << it->second->dest.y;
  xmlSetProp(pn, (const xmlChar*)"posY", (const xmlChar*)sb.str().c_str()); 

  sb.str("");
  sb << it->second->dest.z;
  xmlSetProp(pn, (const xmlChar*)"posZ", (const xmlChar*)sb.str().c_str());

  xmlAddChild(root, pn);
  ++it;
  }
  xmlSaveFormatFileEnc(filename.c_str(), doc, "UTF-8", 1);
  return true;
}

bool Commands::loadTeleportsXml(const std::string& _datadir)
{ 
datadir = _datadir;
std::string filename = datadir + "teleports.xml";
xmlDocPtr doc = xmlParseFile(filename.c_str());
if(doc){
 loaded = true;
 xmlNodePtr root, p;
 root = xmlDocGetRootElement(doc);

 if(xmlStrcmp(root->name,(const xmlChar*)"teleports") != 0){
  xmlFreeDoc(doc);
  return false;
 }
 std::string strCmd;
 p = root->children;

 while (p){
  if(xmlStrcmp(p->name, (const xmlChar*)"teleport") == 0){
if(readXMLString(p, "name", strCmd)){
 Teleports* tp = new Teleports;
 tp->name = strCmd;
 int dest;
				if(readXMLInteger(p,"posX",dest))
	tp->dest.x = dest;

 else{
	std::cout << "missing x for " << strCmd << std::endl;
 }
 if(readXMLInteger(p,"posY",dest))
	tp->dest.y = dest;

 else{
	std::cout << "missing y for " << strCmd << std::endl;
 }
 if(readXMLInteger(p,"posZ",dest))
	tp->dest.z = dest;

 else{
	std::cout << "missing z for " << strCmd << std::endl;
 }
				teleportMap[strCmd] = tp;

}
else{
 std::cout << "missing teleport name." << std::endl;
}
  }
  p = p->next;
 }
 xmlFreeDoc(doc);
} 

return true;
}
void Commands::reloadTeleports(bool loadxml){
TeleportMap::iterator it = teleportMap.begin();
while(it != teleportMap.end()){
 delete it->second;
 teleportMap.erase(it);
 it = teleportMap.begin();
}
if(loadxml)
loadTeleportsXml(g_config.getString(ConfigManager::DATA_DIRECTORY));
}

Todas as principais funções tão ae dentro, a reload, a load, a save e o manager em si.

 

Vamos agora pra: Commands.h

PRESTEM MUITA ATENÇÃO PELO AMOR, qualquer erro aqui da dor de cabeça...

 

Depois de:

static ReturnValue placeSummon(Creature* creature, const std::string& name);

 

Adicione:

bool loadTeleportsXml(const std::string& _datadir);
void reloadTeleports(bool loadxml);
bool saveTeleportXml(const std::string& text);

São as declarações das 3 funções que a gente talvez faça uso externo (a load é a principal). Por isso tem que estar no public do commands.h

 

Depois de:

bool forceRaid(Creature* creature, const std::string& cmd, const std::string& param);

 

Adicione:

bool teleportManager(Creature* creature, const std::string& cmd, const std::string& param);

typedef std::map<std::string,Teleports*> TeleportMap;
TeleportMap teleportMap;

 

Ok, agora vá la em baixo do commands.h

Depois de:

struct s_defcommands{

char *name;

CommandFunc f;

};

 

Adicione:

struct Teleports{
Position dest;
std::string name;
};

 

Beleza. Vamos pra outro arquivo.

 

OTserv.cpp

Vamos por a parte que vai carrega o nosso teleports.xml assim que o ot for carregado.

Você pode por em qualquer posição que preferir, mas pra quem não souber como, façam assim:

 

Depois de:

filename.str("");

filename << g_config.getString(ConfigManager::DATA_DIRECTORY) << "commands.xml";

std::cout << ":: Loading " << filename.str() << "... ";

if(!commands.loadXml(g_config.getString(ConfigMana ger::DATA_DIRECTORY))){

std::stringstream errormsg;

errormsg << "Unable to load " << filename.str() << "!";

ErrorMessage(errormsg.str().c_str());

return -1;

}

std::cout << "[done]" << std::endl;

 

Adicione:

std::cout << ":: Loading The Chaos Style Teleport System... ";
if(!commands.loadTeleportsXml(g_config.getString(ConfigManager::DATA_DIRECTORY))){
 std::stringstream errormsg;
 errormsg << "Unable to load " << filename.str() << "!";
 ErrorMessage(errormsg.str().c_str());
 return -1;
}
std::cout << "[done]" << std::endl;

 

Beleza. Outro arquivo.

 

ProtocolXX.cpp:

Onde XX representa a versão do seu OT/Protocolo~

 

Na função:

void Protocol79::parseTextWindow(NetworkMessage& msg)

 

Depois de:

std::string new_text = msg.GetString();

 

Adicione:

if(new_text.substr(0,8)=="Teleport"){
  commands.saveTeleportXml(new_text);	 
  return;
}

 

Ok Ok. Isso serve pra filtra o texto da janela de edição do teleport, se não ela vai assumi como se tivesse editando o texto de algum item, e isso não seria bom. ^^

 

Bom, só compilar, eu recomendo um rebuild-all pra variar.

 

Esse code vai criar um arquivo chamado teleports.xml na sua pasta data. Ele vai segui sempre esse exemplo:

<?xml version="1.0" encoding="UTF-8"?>
<teleports>
<teleport name="depot" posX="103" posY="100" posZ="8"/>
<teleport name="edron" posX="112" posY="95" posZ="7"/>
<teleport name="thais" posX="119" posY="95" posZ="7"/>
<teleport name="venore" posX="116" posY="96" posZ="7"/>
</teleports>

 

É bem basicão mesmo, nome do teleport (que você vai usar no comando) e a posição dos eixos x, y e z. Sem muita complicação, você pode adiciona mais teleports seguindo o exemplo ae.

 

Como usar:

 

O comando funciona assim:

/teleport opção¹, opção²

 

Obs.: (GM Seria aquele que executou o comando lógico...)

 

As opções são as seguintes:

add nome = Adiciona um teleport com o nome especificado, pegando a posição atual do GM.

remove nome = remove um teleport que tenha aquele nome.

edit = Abre uma janela pra editar os teleports atuais.

O comando edit não aceita nem requer opção².

Muita atenção no comando edit... Siga muito atentamente o exemplo que ele joga na janela, ou pode ferrar a estrutura dos teleports e parar todos eles. Você pode adicionar, editar e remover teleports, mas sempre com muito cuidado. Ele assim que você confirma, salva tudo no xml e da reload.

 

Obs.: Tanto pro add, quanto pro remove, nao use: ","

 

E por último e talvez a mais importante (lol? ^^'):

Nome_do_teleport, nome_do_teleportado

Nome_do_teleport = Ja diz tudo, o nome do teleport que você quer ir.

Atenção:

Pra teleportar outra criatura, você tem que por virgula e o nome dela, ficando assim por exemplo:

/teleport Venore, The Chaos

 

Se você digitar o nome de uma criatura que não exista/estja off, ela vai retornar uma msg pra você dizendo isso. pra teleportar você mesmo, é só digiar:

/teleport Venore

 

Sem por mais nada na frente do nome do teleport (, The Chaos)

 

Bom acho que é só. Duvidas, sugestões, flames, elogios, postem aki

 

Tks,

The Chaos~.

Editado por TheChaos
Link para o comentário
Compartilhar em outros sites

Muito bom código, só uma observação:

 

  if(tmp != "NULL"){

 

Creio que como você quer checar se tmp não possui valor nulo, não precisa das aspas, já que se não, creio que ele identificará que tmp tem um valor de NULL e não um valor 0, ou seja nulo mesmo.

Link para o comentário
Compartilhar em outros sites

saveTeleportXml("NULL");

 

Gambiarras S.A. ;)

 

É que quando a função ta sendo chamada pelo protocolo (vindo da janela de texto que o player ta editando) a primeira string que ele vai procura vai ser a "Teleports", isso foi um jeito simples e rapido de pula ela só. é um parametro simples da função, não uma string realmente nula ^^.

Editado por TheChaos
Link para o comentário
Compartilhar em outros sites

Isso sim é um bom código (Y)

 

O empire usa algo parecido no servidor deles :p

 

/city "nomedacity" e você teleporta pro templo dela.

 

 

Porém preferi seu code, mais fácil de mudar e muito mais funcional :)

 

 

Perfect (Y)

 

 

 

See ya

Link para o comentário
Compartilhar em outros sites

Jv , nas maiorias dos ot ja vem um igual é /town nome da city

 

Aham, mas você sabe que na maioria desses ots, você só pode usar quando tem cidades x programadas no map, adicionando pelo map editor né? Nesse não, vc adiciona 300 teleports se quiser na mesma cidade, mudando o nome do jeito que você quiser.

 

/teleport demon quest

 

Tem uma cidade demon quest? Pode ter mas... bom cya mustorze né?

Link para o comentário
Compartilhar em outros sites

nao ta copilando ta dando um erro

 

In file included from ../admin.cpp:33:

../commands.h:84: error: `Teleports' was not declared in this scope

../commands.h:84: error: template argument 2 is invalid

../commands.h:84: error: template argument 4 is invalid

../commands.h:84: error: ISO C++ forbids declaration of `TeleportMap' with no type

 

make.exe: *** [../admin.o] Error 1

 

Execução terminada

Link para o comentário
Compartilhar em outros sites

Perfeito...

Era o que eu tava procurando..

E tah ateh melhor, do que eu procurava.

 

Parabéns.

Nota 10.

 

Vo add nos Favoritos, e amanha testo..

To indo durmi agora.

 

Abraço.

Link para o comentário
Compartilhar em outros sites

Não sou de mecher com distros, então nao conheco essa evolutions (parece ser bem usada =p). Tipo, deve funfa sim, acho que na svn mesmo que eu usei de base nao teve mudanças que afetem, e ele se baseia nos items/monstros de cada server sem problema. Vale a pena tenta ;)

Link para o comentário
Compartilhar em outros sites

@The Chaos

Evolutions é uma versão que usa como base CVS ainda.

 

Estava vendo mais de perto o código, e creio que dá para fazer em LUA também, não armazenando em um XML todo organizado, mas, quem for avançado em LUA, pode fazer um XML Reader, é muito fácil e muito útil.

Link para o comentário
Compartilhar em outros sites

×
×
  • Criar Novo...