summaryrefslogblamecommitdiff
path: root/src/gui/chat.cpp
blob: fb424b4e7300277412ee5197978deb586949f6d7 (plain) (tree)













































































                                                                                                                   












                                                              


                                      
             
















































































                                                                                                                                           
                     








                                                                     
                 









                                                                                         

             

                    
                                 
                                        
                                                                  
                                                     
                                      


























































































                                                                                              
/**

  The Mana World
  Copyright 2004 The Mana World Development Team

    This file is part of The Mana World.

    The Mana World is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    any later version.

    The Mana World is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with The Mana World; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

*/

/**
	Simple ChatLog Object v0.5 (i'd say...)

	Bestviewd w/ Bitstream Vera Sans Mono @ 9pt and a tab-width of 2 spaces

	Author: kth5 aka Alexander Baldeck
		pipe your questions, suggestions and flames to: kth5@gawab.com
*/

#include "../main.h"
#include "chat.h"
#include <list>
#include <string>
#include <fstream>

using namespace std;


Chat::Chat(const char * logfile, int item_num) {
	chatlog_file.open(logfile, ios::out | ios::app);
	items = 0;
	items_keep = item_num;
}

Chat::~Chat() {
	chatlog_file.flush();
	chatlog_file.close();
}

void Chat::chat_dlgrsize(int) {
}

/** adds a line of text to our message list

		string line					-> message text
		int own							-> type of message (usually the owner-type)
		ALFONT_FONT * font	-> font that'll be used to draw the text later
   
		NOTE:
			to all of you who wonder why the font needs to be passed, simple.
			i already store the width in pixel in the list rather than
			calculating it again and again on every draw event. ;-)
*/
void Chat::chat_log(string line, int own, ALFONT_FONT * font) {
	int pos;
	CHATLOG tmp;

	if(items<=items_keep)
		items++;     // delete overhead from the end of the list
	else
		chatlog.pop_back();

	pos = 0;
	pos = (int)line.find(" : ", 0);
	if(pos > 0) {
		tmp.nick = line.substr(0,pos);
		switch(own) {
			case ACT_IS :
				tmp.nick += CAT_IS;
				break;
			case ACT_WHISPER :
				tmp.nick += CAT_WHISPER;
				break;
			default :
				tmp.nick += CAT_NORMAL;
		}
		tmp.width = TEXT_GETWIDTH(tmp.nick.c_str())+2;
		line.erase(0,pos+3);
	}else {
			tmp.nick = "";
			tmp.width = 1;
	}    
	tmp.own  = own;	
	tmp.text = line;	

	chatlog_file << tmp.nick << tmp.text << "\n";
	chatlog_file.flush();
	
	chatlog.push_front(tmp);
}

void Chat::chat_log(CHATSKILL action, ALFONT_FONT * font) {
	chat_log(const_msg(action), BY_SERVER, font);
}


/** draw first n lines of the list onto a Allegro type bitmap buffer
		using Alfont

		BITMAP * bmp				-> Allegro type bitmap buffer to draw onto
		int n								-> number of lines to be drawn
		ALFONT_FONT * font	-> font to use
   
		NOTE:
			take great care using this, make sure the buffer passed is
			empty! ;-) anyway, line wrapping is not supported yet.
*/
void Chat::chat_draw(BITMAP * bmp, int n, ALFONT_FONT * font) {
	int y = 600-35, i = 0;
	CHATLOG line;
	n -= 1;
	
    for(iter = chatlog.begin(); iter != chatlog.end(); iter++) {
		line = *iter;
		y -=11;
 
		switch(line.own) {
			case BY_GM :
				alfont_textprintf_aa(bmp, font, 1, y, COLOR_BLUE, "Global announcement: ");
				alfont_textprintf_aa(bmp, font, TEXT_GETWIDTH("Global announcement: "), y, COLOR_GREEN, line.text.c_str());
				break;
			case BY_PLAYER :
				alfont_textprintf_aa(bmp, font, 1, y, COLOR_YELLOW, line.nick.c_str());
				alfont_textprintf_aa(bmp, font, line.width, y, COLOR_WHITE, line.text.c_str());
				break;
			case BY_OTHER :
				alfont_textprintf_aa(bmp, font, 1, y, COLOR_GREEN, line.nick.c_str());
				alfont_textprintf_aa(bmp, font, line.width, y, COLOR_WHITE, line.text.c_str());
				break;
			default :
				alfont_textprintf_aa(bmp, font, 1, y, COLOR_LIGHTBLUE, line.text.c_str());
		}
    
		if(i>=n)
			return;
		i++;
	}
}

/** determines wether to send a command or an ordinary message, then
		contructs packets & sends them

		string nick -> the character's name to display infront
		string msg  -> the message's text which is to be send.
   
		NOTE:
			the nickname is required by the server, if not specified
			the message may not be sent unless a command was intended
			which requires another packet to be constructed! you can
			achieve this by putting a slash ("/") infront of the
			message followed by the command name and the message.
			of course all slash-commands need implemented handler-
			routines. ;-)
			remember, a line starting w/ "@" is not a command that needs
			to be parsed rather is sent using the normal chat-packet.

		EXAMPLE:
			// for an global announcement   /- command
			chatlog.chat_send("", "/announce Hello to all logged in users!");
			// for simple message by a user /- message
			chatlog.chat_send("Zaeiru", "Hello to all users on the screen!");
*/
char * Chat::chat_send(string nick, string msg) {
	short packid;

	// prepare command
	if(msg.substr(0,1)=="/") {
		// global announcement
		if(msg.substr(0,IS_ANNOUNCE_LENGTH) == IS_ANNOUNCE) {
			msg.erase(0,IS_ANNOUNCE_LENGTH);
			packid = 0x0099;
		} else {
			packid = 0x008c;
		}
	// prepare ordinary message
	} else {
		// temporary hack to make messed-up-keyboard-ppl able to send GM commands
		if(msg.substr(0,1)=="#")
			msg.replace(0,1,"@");
		// end temp. hack XD
		nick += " : ";
		nick += msg;
		msg = nick;
		packid = 0x008c;
	}    

	msg += "\0";

	// send processed message
	WFIFOW(0) = net_w_value(packid);
	WFIFOW(2) = net_w_value((unsigned short)(msg.length()+4));
	memcpy(WFIFOP(4), msg.c_str(), msg.length());
	WFIFOSET((int)msg.length()+4);
	nick = msg = "";
	return "";
}    

/** PRIVATE : 
	NOTE:
		these usually will be left undocumented coz u can't call them
		directly anyway. ;-)
*/ 

/** constructs failed messages for actions */
string Chat::const_msg(CHATSKILL action) {
	string msg;
	if(action.success == SKILL_FAILED && action.skill == SKILL_BASIC) {
		switch(action.bskill) {
			case BSKILL_TRADE :
				msg = "Trade failed!";
				break;
			case BSKILL_EMOTE :
				msg = "Emote failed!";
				break;
			case BSKILL_SIT :
				msg = "Sit failed!";
				break;
			case BSKILL_CREATECHAT :
				msg = "Chat creating failed!";
				break;
			case BSKILL_JOINPARTY :
				msg = "Could not join party!";
				break;
			case BSKILL_SHOUT :
				msg = "Cannot shout!";
				break;
		}
		
		switch(action.reason) {
			case RFAIL_SKILLDEP :
				msg += " You have not yet reached a high enough lvl!";
				break;
			case RFAIL_INSUFHP :
				msg += " Insufficient HP!";
				break;
			case RFAIL_INSUFSP :
				msg += " Insufficient SP!";
				break;
			case RFAIL_NOMEMO :
				msg += " You have no memos!";
				break;
			case RFAIL_SKILLDELAY :
				msg += " You cannot do that right now!";
				break;
			case RFAIL_ZENY :
				msg += " Seems you need more Zeny... ;-)";
				break;
			case RFAIL_WEAPON :
				msg += " You cannot use this skill with that kind of weapon!";
				break;
			case RFAIL_REDGEM :
				msg += " You need another red gem!";
				break;
			case RFAIL_BLUEGEM :
				msg += " You need another blue gem!";
				break;
			case RFAIL_OVERWEIGHT :
				msg += " You're carrying to much to do this!";
				break;
			default :
				msg += " Huh? What's that?";
				break;
		}
	}else{
		switch(action.skill) {
			case SKILL_WARP :
				msg = "Warp failed...";
				break;
			case SKILL_STEAL :
				msg = "Could not steal anything...";
				break;
			case SKILL_ENVENOM :
				msg = "Poison had no effect...";
				break;
		}
	}
	
	return msg;
}

string const_msg(int own) {
  string msg;
	return msg;
}