summaryrefslogblamecommitdiff
path: root/src/game.cpp
blob: c84d8b3cb28f81e71ac9b0b88eb205a064946e93 (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
 *
 *  $Id$
 */

#include "main.h"
#include "map.h"
#include "being.h"
#include "log.h"
#include "./gui/chat.h"
#include "./gui/gui.h"
#include "./gui/inventory.h"
#include "./gui/shop.h"
#include "./gui/npc.h"
#include "./gui/setup.h"
#include "./gui/stats.h"
#include "./gui/ok_dialog.h"
#include "./graphic/graphic.h"
#include "./sound/sound.h"

char map_path[480];

#ifndef WIN32
extern Sound sound;
#endif /* not WIN32 */

unsigned short dest_x, dest_y, src_x, src_y;
unsigned int player_x, player_y;
bool refresh_beings = false;
unsigned char keyb_state;
volatile int tick_time;
volatile bool action_time = false;
int current_npc, server_tick;
extern unsigned char screen_mode;
int fps = 0, frame = 0;

Setup *setup = NULL;
StatsWindow *stats = NULL;

#define MAX_TIME 10000

/**
 * Finite states machine to keep track of player walking status (2 steps
 * linear prediction)
 *
 *  0 = Standing
 *  1 = Walking without confirm packet
 *  2 = Walking with confirm
 */
char walk_status = 0;


// SDL callbacks
/*
Uint32 refresh_time(Uint32 interval, void *param)
{
    tick_time++;
    if (tick_time == MAX_TIME) tick_time = 0;
}

Uint32 second(Uint32 interval, void *param)
{
    action_time = true;
    fps = frame;
    frame = 0;
}
*/

void refresh_time(void) {
    tick_time++;
    if (tick_time == MAX_TIME) tick_time = 0;
}
END_OF_FUNCTION(refresh_frame);

/**
 * Lets u only trigger an action every other second
 * tmp. counts fps
 */
void second(void) {
    action_time = true;
    fps = frame;
    frame = 0;
}
END_OF_FUNCTION(second);

/**
 * Return elapsed time (Warning: very unsafe function. It supposes the delay
 * is always < MAX_TIME ms)
 */
short get_elapsed_time(short start_time) {
    if (start_time <= tick_time) {
        return tick_time - start_time;
    }
    else {
        return tick_time + (MAX_TIME - start_time);
    }
}

/**
 * Main game loop
 */
void game() {
    do_init();
    GraphicEngine *graphicEngine = new GraphicEngine();

    //SDL_Event event;
    //SDL_EnableUNICODE(1);

    while (state != EXIT) {

        // Handle SDL events
        //while (SDL_PollEvent(&event)) {
        //    switch (event.type) {
        //        case SDL_QUIT:
        //            state = EXIT;
        //            break;
        //    }
        //}

        do_input();
        graphicEngine->refresh();
        do_parse();
        flush();
    }


    delete graphicEngine;
    close_session();
}

/**
 * Initialize game engine
 */
void do_init() {
    if (!load_map(map_path)) {
        error("Could not find map file");
    }

#ifndef WIN32
    sound.startBgm("./data/sound/Mods/somemp.xm", -1);
#endif /* not WIN32 */

    // Initialize timers
    tick_time = 0;

    // The SDL way
    //SDL_AddTimer(10, refresh_time, NULL);
    //SDL_AddTimer(1000, second, NULL);

    // The Allegro way
    LOCK_VARIABLE(tick_time);
    install_int_ex(refresh_time, MSEC_TO_TIMER(1));
    install_int_ex(second, BPS_TO_TIMER(1));

    // Initialize beings
    empty();
    player_node = new NODE();
    player_node->id = account_ID;
    player_node->type = ACTION_NODE;
    set_coordinates(player_node->coordinates, x, y, 0);
    player_node->speed = 150;
    player_node->hair_color = char_info->hair_color;
    player_node->hair_style = char_info->hair_style;
    if (char_info->weapon == 11) {
        char_info->weapon = 1;
    }
    player_node->weapon = char_info->weapon;
    add_node(player_node);

    remove("./docs/packet.list");
}

/**
 * Clean the engine
 */
void do_exit() {
}

/**
 * Check user input
 */
void do_input() {
    if (walk_status == 0) {
        int x = get_x(player_node->coordinates);
        int y = get_y(player_node->coordinates);

        if (key[KEY_8_PAD] || key[KEY_UP]) {
            if (get_walk(x, y - 1) != 0) {
                walk(x, y-1, NORTH);
                walk_status = 1;
                src_x = x;
                src_y = y;
                player_node->action = WALK;
                player_node->tick_time = tick_time;
                set_coordinates(player_node->coordinates, x, y - 1, NORTH);
            } else set_coordinates(player_node->coordinates, x, y, NORTH);
        } else if (key[KEY_2_PAD] || key[KEY_DOWN]) {
            if(get_walk(x, y + 1) != 0) {
                walk(x, y + 1, SOUTH);
                walk_status = 1;
                src_x = x;
                src_y = y;
                player_node->action = WALK;
                player_node->tick_time = tick_time;
                set_coordinates(player_node->coordinates, x, y + 1, SOUTH);
            } else set_coordinates(player_node->coordinates, x, y, SOUTH);
        } else if (key[KEY_4_PAD] || key[KEY_LEFT]) {
            if (get_walk(x - 1, y) != 0) {
                walk(x - 1, y, WEST);
                walk_status = 1;
                src_x = x;
                src_y = y;
                player_node->action = WALK;
                player_node->tick_time = tick_time;
                set_coordinates(player_node->coordinates, x - 1, y, WEST);
            } else set_coordinates(player_node->coordinates, x, y, WEST);
        } else if (key[KEY_6_PAD] || key[KEY_RIGHT]) {
            if (get_walk(x + 1, y) != 0) {
                walk(x + 1, y, EAST);
                walk_status = 1;
                src_x = x;
                src_y = y;
                player_node->action = WALK;
                player_node->tick_time = tick_time;
                set_coordinates(player_node->coordinates, x + 1, y, EAST);
            } else set_coordinates(player_node->coordinates, x, y, EAST);
        }
    }

    if (player_node->action == STAND) {
        if (key[KEY_LCONTROL]) {
            player_node->action = ATTACK;
            attack(get_x(player_node->coordinates),
                    get_y(player_node->coordinates),
                    get_direction(player_node->coordinates));
            player_node->tick_time = tick_time;
        }
    }

    if (key[KEY_F5] && action_time) {
        if (player_node->action == STAND)
            action(2, 0);
        else if (player_node->action == SIT)
            action(3, 0);
        action_time = false;
        //alert("","","","","",0,0);
    }

    // Emotions, Skill dialog
    if (key_shifts & KB_ALT_FLAG && action_time == true) {
        if (player_node->emotion == 0) {
            unsigned char emotion = 0;
            if (key[KEY_1]) emotion = 1;
            else if (key[KEY_2]) emotion = 2;
            else if (key[KEY_3]) emotion = 3;
            else if (key[KEY_4]) emotion = 4;
            else if (key[KEY_5]) emotion = 5;
            else if (key[KEY_6]) emotion = 6;
            else if (key[KEY_7]) emotion = 7;
            else if (key[KEY_8]) emotion = 8;
            else if (key[KEY_9]) emotion = 9;
            else if (key[KEY_0]) emotion = 10;
            if (emotion != 0) {
                WFIFOW(0) = net_w_value(0x00bf);
                WFIFOB(2) = emotion;
                WFIFOSET(3);
                action_time = false;
            }
        }
    }

    if (mouse_b & 2) {
        // Make contact with NPC
        int npc_x = mouse_x / 32 + camera_x;
        int npc_y = mouse_y / 32 + camera_y;
        int id = find_npc(npc_x, npc_y);
        if (id != 0) {
            WFIFOW(0) = net_w_value(0x0090);
            WFIFOL(2) = net_l_value(id);
            WFIFOB(6) = 0;
            WFIFOSET(7);
        }
    }
}

bool handle_key(int unicode, int scancode)
{
    switch (scancode) {
        case KEY_ESC:
            state = EXIT;
            return true;
        case KEY_F1:
            save_bitmap("./data/graphic/screenshot.bmp", buffer, NULL);
            return true;
#ifndef WIN32
        case KEY_F12:
            sound.adjustVolume(1);
            return true;
        case KEY_F11:
            sound.adjustVolume(-1);
            return true;
#endif /* not WIN32 */
        case KEY_F9:
            setup = Setup::create_setup();
            return true;
        case KEY_F10:
            // was 3 goes to 0
            // was 0 goes to 3
            screen_mode = 3 - screen_mode;
            if (set_gfx_mode(screen_mode, 800, 600, 0, 0) != 0) {
                // less than: to add support for other hardware platforms
                error(allegro_error);
            }
            return true;
    }

    if (key_shifts & KB_ALT_FLAG) {
        switch (scancode) {
            case KEY_I:
                inventoryWindow->setVisible(!inventoryWindow->isVisible());
                return true;
            case KEY_S:
                if (stats == NULL)
                    stats = StatsWindow::create_statswindow();
                else {
                    stats->setVisible(!stats->isVisible());
                }
                return true;
            case KEY_K:
                show_skill_list_dialog = !show_skill_dialog;
                return true;
        }
    }

    return false;
}

/**
 * Calculate packet length
 */
int get_packet_length(short id) {
    int len = get_length(id);
    if (len == -1)len = RFIFOW(2);
    return len;
}

/**
 * Parse data received from map server into input buffer
 */
void do_parse() {
    unsigned short id;
    char *temp;
    char direction;
    NODE *node = NULL;
    PATH_NODE *pn;
    int len;
	
	// We need at least 2 bytes to identify a packet
	if(in_size>=2) {
		// Check if the received packet is complete
		while(in_size>=(len = get_packet_length(id = RFIFOW(0)))) {
			// Add infos to log file and dump the latest received packet
			char pkt_nfo[60];
			sprintf(pkt_nfo,"In-buffer size: %i Packet id: %x Packet length: %i",in_size,RFIFOW(0),len);
			/*log_hex("Packet", "Packet_ID", RFIFOW(0));
			log_int("Packet", "Packet_length", get_length(RFIFOW(0)));
			log_int("Packet", "Packet_in_size", RFIFOW(2));
			log_int("Packet", "In_size", in_size);
			FILE *file = fopen("packet.dump", "wb");
			for(int i=0;i<len;i++) {
				fprintf(file, "%x|%i|%c ", RFIFOB(i), RFIFOB(i), RFIFOB(i));
				if((i+1)%10==0)fprintf(file, "\n");
			}
			fclose(file);*/
#ifdef DEBUG
			FILE *file = fopen("./docs/packet.list", "ab");
			fprintf(file, "%x\n", RFIFOW(0));
			fclose(file);
#endif
			// Parse packet based on their id
			switch(id) {
				// Received speech
				case 0x008d:
					temp = (char *)malloc(RFIFOW(2)-7);
					memset(temp, '\0', RFIFOW(2)-7);
					memcpy(temp, RFIFOP(8), RFIFOW(2)-8);
					node = find_node(RFIFOL(4));
					if(node!=NULL) {
						if(node->speech!=NULL) {
							free(node->speech);
							node->speech = NULL;
							node->speech_time = 0;
						}
						node->speech = temp;
						node->speech_time = SPEECH_TIME;
						node->speech_color = makecol(255, 255, 255);
						chatlog.chat_log(node->speech, BY_OTHER, font);
					}
					break;
				case 0x008e:
				case 0x009a:
					if(RFIFOW(2)>4) {
						if(player_node->speech!=NULL) {
							free(player_node->speech);
							player_node->speech = NULL;
						}

						player_node->speech = (char *)malloc(RFIFOW(2)-3);
						memset(player_node->speech, '\0', RFIFOW(2)-3);
						memcpy(player_node->speech, RFIFOP(4), RFIFOW(2)-4);  // receive 1 byte less than expected, server might be sending garbage instead of '\0' /-kth5

						player_node->speech_time = SPEECH_TIME;
						player_node->speech_color = makecol(255, 255, 255);

						if(id==0x008e) {
							chatlog.chat_log(player_node->speech, BY_PLAYER, font);
						}
						else {
							chatlog.chat_log(player_node->speech, BY_GM, font);
						}
					}
					break;
				// Success to walk request
				case 0x0087:
					if(walk_status==1) {
						if(RFIFOL(2)>server_tick) {
							walk_status = 2;
							server_tick = RFIFOL(2);
						}
					}
					break;
				// Add new being / stop monster
				case 0x0078:
					if(find_node(RFIFOL(2))==NULL) {
						node = new NODE();
						node->id = RFIFOL(2);
						node->speed = RFIFOW(6);
						if(node->speed==0) {
							node->speed = 150; // Else division by 0 when calculating frame
						}
						node->job = RFIFOW(14);
						empty_path(node);
						memcpy(node->coordinates, RFIFOP(46), 3);
						node->hair_color = RFIFOW(28);
						node->hair_style = RFIFOW(16);
						add_node(node);
					}
					else {
						if(node) {
							empty_path(node);
							memcpy(node->coordinates, RFIFOP(46), 3);
							node->frame = 0;
							node->tick_time = tick_time;
							node->action = STAND;
						}
					}
					break;
				// Remove a being
				case 0x0080:
					node = find_node(RFIFOL(2));
					if(node!=NULL) {
						if(RFIFOB(6)==1) { // Death
							if(node->job>110) {
								node->action = MONSTER_DEAD;
								node->frame = 0;
								node->tick_time = tick_time;
							}
							else remove_node(RFIFOL(2));
						}
						else remove_node(RFIFOL(2));
					}
					break;
				// Player moving
				case 0x01d8:
				case 0x01d9:
					node = find_node(RFIFOL(2));
					if(node==NULL) {
						node = new NODE();
						node->id = RFIFOL(2);
						node->job = RFIFOW(14);
						memcpy(node->coordinates, RFIFOP(46), 3);
						add_node(node);
						node->tick_time = tick_time;
						node->frame = 0;
						node->speed = RFIFOW(6);
						node->hair_color = RFIFOW(28);
						node->hair_style = RFIFOW(16);
					}
					break;
				// Monster moving
				case 0x007b:
				//case 0x01da:
					node = find_node(RFIFOL(2));
					if(node==NULL) {
						node = new NODE();
						node->action = STAND;
						set_coordinates(node->coordinates,
							get_src_x(RFIFOP(50)),
							get_src_y(RFIFOP(50)), 0);
						node->id = RFIFOL(2);
						node->speed = RFIFOW(6);
						node->job = RFIFOW(14);
						add_node(node);
					}
					empty_path(node);
					node->path = calculate_path(get_src_x(RFIFOP(50)),
						get_src_y(RFIFOP(50)),get_dest_x(RFIFOP(50)),
						get_dest_y(RFIFOP(50)));
					if(node->path!=NULL) {
						direction = 0;
						if(node->path->next) {
							if(node->path->next->x>node->path->x && node->path->next->y>node->path->y)direction = SE;
							else if(node->path->next->x<node->path->x && node->path->next->y>node->path->y)direction = SW;
							else if(node->path->next->x>node->path->x && node->path->next->y<node->path->y)direction = NE;
							else if(node->path->next->x<node->path->x && node->path->next->y<node->path->y)direction = NW;
							else if(node->path->next->x>node->path->x)direction = EAST;
							else if(node->path->next->x<node->path->x)direction = WEST;
							else if(node->path->next->y>node->path->y)direction = SOUTH;
							else if(node->path->next->y<node->path->y)direction = NORTH;
						}
						pn = node->path;
						node->path = node->path->next;
						free(pn);
						set_coordinates(node->coordinates, node->path->x, node->path->y, direction);
						node->action = WALK;
						node->tick_time = tick_time;
						node->frame = 0;
					}
					break;
				// Being moving
				case 0x01da:
					node = find_node(RFIFOL(2));
					if(node==NULL) {
						node = new NODE();
						node->id = RFIFOL(2);
						node->job = RFIFOW(14);
						set_coordinates(node->coordinates, get_src_x(RFIFOP(50)), get_src_y(RFIFOP(50)), 0);
						add_node(node);
					}
					if(node->action!=WALK) {
						direction = get_direction(node->coordinates);
						node->action = WALK;
						if(get_dest_x(RFIFOP(50))>get_x(node->coordinates))direction = EAST;
						else if(get_dest_x(RFIFOP(50))<get_x(node->coordinates))direction = WEST;
						else if(get_dest_y(RFIFOP(50))>get_y(node->coordinates))direction = SOUTH;
						else if(get_dest_y(RFIFOP(50))<get_y(node->coordinates))direction = NORTH;
						else node->action = STAND;
						if(node->action==WALK)node->tick_time = tick_time;
						set_coordinates(node->coordinates, get_dest_x(RFIFOP(50)), get_dest_y(RFIFOP(50)), direction);
					}
					break;
				// NPC dialog
				case 0x00b4:
          npcTextDialog->addText(RFIFOP(8));
          npcListDialog->setVisible(false);
          npcTextDialog->setVisible(true);
          break;
        // Get the items
        case 0x01ee:
          for (int loop = 0; loop < (RFIFOW(2) - 4) / 18; loop++) {
              inventoryWindow->addItem(RFIFOW(4 + loop * 18),
                      RFIFOW(4 + loop * 18 + 2), RFIFOW(4 + loop * 18 + 6));
          }
          break;
				// Can I use the item?
				case 0x00a8:
					// index RFIFOW(2)
					// succes or not RFIFOB(6);
					//if (RFIFOB(6))
					//  inventoryWindow->addItem(RFIFOW(2), RFIFOW(4));
					break;
				// Warp
					case 0x0091:
						memset(map_path, '\0', 480);
						append_filename(map_path, "./data/map/", RFIFOP(2), 480);
						if (load_map(map_path)) {
							empty();
							player_node = new NODE();
							player_node->job = 0;
							player_node->action = STAND;
							player_node->frame = 0;
							player_node->type = ACTION_NODE;
							player_node->speed = 150;
							player_node->id = account_ID;
							set_coordinates(player_node->coordinates, RFIFOW(18), RFIFOW(20), 0);
							add_node(player_node);
							walk_status = 0;
							// Send "map loaded"
							WFIFOW(0) = net_w_value(0x007d);
							WFIFOSET(2);
							while(out_size>0)flush();
						}
						else {
							error("Could not find map file");
						}
						break;
					// Skill ...
					case 0x011a:
						break;
					case 0x01a4:
						break;
					// Action failed (ex. sit because you have not reached the right level)
					case 0x0110:
						CHATSKILL action;
						action.skill   = RFIFOW(2);
						action.bskill  = RFIFOW(4);
						action.unused  = RFIFOW(6);
						action.success = RFIFOB(8);
						action.reason  = RFIFOB(9);
						if(action.success != SKILL_FAILED &&
							action.bskill == BSKILL_EMOTE ) {
							printf("Action: %d/%d", action.bskill, action.success);
						}
						chatlog.chat_log(action, font);
						break;
					// Update stat values
					case 0x00b0:
						switch(RFIFOW(2)) {
							/*case 0x0000:
								player_node->speed;
								break;*/
							case 0x0005:
								char_info->hp = RFIFOW(4);
								break;
							case 0x0006:
								char_info->max_hp = RFIFOW(4);
								break;
							case 0x0007:
								char_info->sp = RFIFOW(4);
								break;
							case 0x0008:
								char_info->max_sp = RFIFOW(4);
								break;
							case 0x000b:
								char_info->lv = RFIFOW(4);
								break;
							case 0x000c:
								char_info->skill_point = RFIFOW(4);
								sprintf(skill_points, "Skill points: %i", char_info->skill_point);
								break;
							case 0x0037:
								char_info->job_lv = RFIFOW(4);
								break;
						}
						statusWindow->update();
						if(char_info->hp==0) {
							OkDialog *death = new OkDialog(guiTop,
								"You're now dead, press ok to restart");
							alert("","","","","",0,0);
							WFIFOW(0) = net_w_value(0x00b2);
							WFIFOB(2) = 0;
							WFIFOSET(3);
						}
						break;
				// Stop walking
				/*case 0x0088:  // Disabled because giving some problems
					if(node = find_node(RFIFOL(2))) {
						if(node->id!=player_node->id) {
						char ids[20];
						sprintf(ids,"%i",RFIFOL(2));
						alert(ids,"","","","",0,0);
              node->action = STAND;
              node->frame = 0;
              set_coordinates(node->coordinates, RFIFOW(6), RFIFOW(8), get_direction(node->coordinates));
						}
					}
          break;*/
				// Damage, sit, stand up
				case 0x008a:
					switch(RFIFOB(26)) {
            case 0: // Damage
							node = find_node(RFIFOL(6));
							if(node!=NULL) {
                if(node->speech!=NULL) {
                  free(node->speech);
                  node->speech = NULL;
                  //node->speech_time = SPEECH_TIME;
                }
                node->speech = (char *)malloc(5);
                memset(node->speech, '\0', 5);
								if(RFIFOW(22)==0) {
									sprintf(node->speech, "miss");
									node->speech_color = makecol(255, 255, 0);
								} else {
                  sprintf(node->speech, "%i", RFIFOW(22));
									if(node->id!=player_node->id)node->speech_color = makecol(0, 0, 255);
									else node->speech_color = makecol(255, 0, 0);
								}
                node->speech_time = SPEECH_TIME;
								if(RFIFOL(2)!=player_node->id) { // buggy
                  node = find_node(RFIFOL(2));
									if(node!=NULL) {
										if(node->job<10)
                      node->action = ATTACK;
										else node->action = MONSTER_ATTACK;
										node->frame = 0;
									}
								}
							}
              break;
            case 2: // Sit
            case 3: // Stand up
              node = find_node(RFIFOL(2));
							if(node!=NULL) {
								node->frame = 0;
								if(RFIFOB(26)==2) {
                  node->action = SIT;
									//alert("","","","","",0,0);
									walk_status = 0;
								}
                else if(RFIFOB(26)==3)
                  node->action = STAND;
							}
              break;
					}
					break;
				// Status change
				case 0x00b1:
					switch(RFIFOW(2)) {
            case 1:
							char_info->xp = RFIFOL(4);
							break;
						case 2:
							char_info->job_xp = RFIFOL(4);
							break;
						case 20:
							char_info->gp = RFIFOL(4);
							break;
						// case 16 and 17 missing
					}
					break;
				// Level up
				case 0x019b:
					if(RFIFOL(2)==player_node->id) {
#ifndef WIN32
					  SOUND_SID sound_id = sound.loadItem("./data/sound/wavs/level.wav");
					  sound.startItem(sound_id, 64);
					  sound.clearCache();
#endif /* not WIN32 */
					}
					break;
				// Emotion
				case 0x00c0:
					node = find_node(RFIFOL(2));
					if(node) {
						node->emotion = RFIFOB(6);
						node->emotion_time = EMOTION_TIME;
					}
					break;
				// Update skill values
				case 0x0141:
					switch(RFIFOL(2)) {
            case 0x000d:
							char_info->STR = RFIFOL(6) + RFIFOL(10); // Base + Bonus
							break;
            case 0x000e:
							char_info->AGI = RFIFOL(6) + RFIFOL(10);
							break;
            case 0x000f:
							char_info->VIT = RFIFOL(6) + RFIFOL(10);
							break;
            case 0x0010:
							char_info->INT = RFIFOL(6) + RFIFOL(10);
							break;
            case 0x0011:
							char_info->DEX = RFIFOL(6) + RFIFOL(10);
							break;
            case 0x0012:
							char_info->LUK = RFIFOL(6) + RFIFOL(10);
							break;
					}
					break;
				// Buy/Sell dialog
				case 0x00c4:
          buyDialog->setVisible(false);
          sellDialog->setVisible(false);
          buySellDialog->setVisible(true);
          current_npc = RFIFOL(2);
					break;
				// Buy dialog
				case 0x00c6:
					n_items = (len - 4) / 11;
          buyDialog->reset();
          buyDialog->setMoney(char_info->gp);
					buyDialog->setVisible(true);
					for (int k = 0; k < n_items; k++) {
						buyDialog->addItem(RFIFOW(4 + 11 * k + 9), RFIFOL(4 + 11 * k));
          }
					break;
				// Sell dialog
				case 0x00c7:
          n_items = (len - 4) / 10;
          if (n_items > 0) {
              sellDialog->reset();
              sellDialog->setVisible(true);
              for (int k = 0; k < n_items; k++) {
                  sellDialog->addItem(
                          RFIFOW(4 + 10 * k), RFIFOL(4 + 10 * k + 2));
              }
          }
          else {
              chatlog.chat_log("Nothing to sell", BY_SERVER, font);
          }
          break;
				// Answer to buy
				case 0x00ca:
					if(RFIFOB(2)==0)
            chatlog.chat_log("Thanks for buying", BY_SERVER, font);
					else
						chatlog.chat_log("Unable to buy", BY_SERVER, font);
					break;
				// Answer to sell
				case 0x00cb:
					if(RFIFOB(2)==0)
            chatlog.chat_log("Thanks for selling", BY_SERVER, font);
					else
						chatlog.chat_log("Unable to sell", BY_SERVER, font);
					break;
				// Add item to inventory after you bought it
				case 0x00a0:
				  if(RFIFOB(22)>0)
				    chatlog.chat_log("Unable to pick up item", BY_SERVER, font);
				  else
				    inventoryWindow->addItem(RFIFOW(2), RFIFOW(6), RFIFOW(4));
					break;
				// Remove item to inventory after you sold it
				case 0x00af:
          printf("sell %i\n", -RFIFOW(4));
					inventoryWindow->increaseQuantity(RFIFOW(2), -RFIFOW(4));
					break;
				// Use an item
				case 0x01c8:
					inventoryWindow->changeQuantity(RFIFOW(2), RFIFOW(10));
					break;
				// ??
				case 0x0119:
					sprintf(pkt_nfo, "%i %i %i %i", RFIFOL(2), RFIFOW(6), RFIFOW(8), RFIFOW(10));
					//alert(pkt_nfo,"","","","",0,0);
					break;
				// Skill list
				case 0x010f:
					//n_skills = 0;
					//SKILL *temp_skill = NULL;
					//n_skills = (len-4)/37;
					for(int k=0;k<(len-4)/37;k++) {
						if(RFIFOW(4+k*37+6)!=0 || RFIFOB(4+k*37+36)!=0) {
							SKILL *temp_skill = is_skill(RFIFOW(4+k*37));
							if(temp_skill) {
								temp_skill->lv = RFIFOW(4+k*37+6);
								temp_skill->sp = RFIFOW(4+k*37+36);
								if(temp_skill->sp<0)temp_skill->sp = 0;
							} else {
                n_skills++;
                add_skill(RFIFOW(4+k*37), RFIFOW(4+k*37+6), RFIFOW(4+k*37+8));
							}
						}
					}
					break;
				// MVP experience
				case 0x010b:
					break;
				// Display MVP payer
				case 0x010c:
					chatlog.chat_log("MVP player", BY_SERVER, font);
					break;
				// Item drop
				case 0x009e:
				  WFIFOW(0) = net_w_value(0x009f);
				  WFIFOL(2) = net_l_value(RFIFOL(2));
				  WFIFOSET(6);
				  break;
		    // Next button in NPC dialog
		    case 0x00b5:
		      strcpy(npc_button, "Next");
		      current_npc = RFIFOL(2);
		      break;
        // Close button in NPC dialog
        case 0x00b6:
		      strcpy(npc_button, "Close");
		      current_npc = RFIFOL(2);
		      break;
        // List in NPC dialog
        case 0x00b7:
          current_npc = RFIFOL(4);
          // Hammerbear: Second argument here shouldn't be neccesary, instead
          //   make sure the string is \0 terminated.
          //parse_items(RFIFOP(8), RFIFOW(2));
          npcListDialog->parseItems(RFIFOP(8));
          RFIFOW(2);
          npcListDialog->setVisible(true);
          break;
        // Look change
        case 0x00c3:
          // Change hair color
          if (RFIFOB(6) == 6) {
            node = find_node(RFIFOL(2));
            node->hair_color = RFIFOB(7);
            /*char prova[100];
            sprintf(prova, "%i %i %i", RFIFOL(2), RFIFOB(6), RFIFOB(7));
            alert(prova,"","","","",0,0);*/
          } else if (RFIFOB(6) == 1) {
            node = find_node(RFIFOL(2));
            node->hair_style = RFIFOB(7);
          }
          break;
          case 0x00a4:
				for (int i = 0; i < (RFIFOW(2) - 4) / 20; i++)
					inventoryWindow->addItem(RFIFOW(4 + 20 * i), RFIFOW(6 + 20 * i), 1);
			break;

        // Manage non implemented packets
        default:
          //printf("%x\n",id);
          //alert(pkt_nfo,"","","","",0,0);
          break;
      }
      //alert(pkt_nfo,"","","","",0,0);

      RFIFOSKIP(len);
    }
  }
}