/*
* 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];
extern Sound sound;
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 refresh = false, action_time = false;
int current_npc, server_tick;
extern unsigned char screen_mode;
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;
void refresh_time(void) {
tick_time++;
if(tick_time==MAX_TIME)tick_time = 0;
}
END_OF_FUNCTION(refresh_frame);
void refresh_screen(void) {
refresh = true;
}
END_OF_FUNCTION(refresh_screen);
int fps = 0, frame = 0;
/** lets u only trigger an action every other second
tmp. counts fps*/
void second(void) {
action_time = true;
fps = (fps + frame)/2;
frame = 0;
}
END_OF_FUNCTION(second);
/** Return elapsed time (Warning: very unsafe
function. It supposes the delay is always < 10s) */
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() {
status("INIT");
do_init();
GraphicEngine *graphicEngine = new GraphicEngine();
while (state != EXIT) {
status("INPUT");
do_input();
status("GRAPHIC");
graphicEngine->refresh();
status("PARSE");
do_parse();
status("FLUSH");
flush();
}
delete graphicEngine;
close_session();
}
/** Initialize game engine */
void do_init() {
if (!load_map(map_path)) {
error("Could not find map file");
}
sound.startBgm("./data/sound/Mods/somemp.xm", -1);
// Initialize timers
tick_time = 0;
refresh = false;
LOCK_VARIABLE(tick_time);
LOCK_VARIABLE(refresh);
install_int_ex(refresh_time, MSEC_TO_TIMER(1));
install_int_ex(refresh_screen, /*MSEC_TO_TIMER(2000)*/BPS_TO_TIMER(200)); // Set max refresh rate to 75 fps
install_int_ex(second, BPS_TO_TIMER(1));
// Interrupt drawing while in background
#ifdef WIN32
set_display_switch_mode(SWITCH_AMNESIA);
#else
set_display_switch_mode(SWITCH_PAUSE);
#endif
// 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);
show_npc_dialog = 0;
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) {
//if(show_npc_dialog==0) {
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;
case KEY_F12:
sound.adjustVolume(1);
return true;
case KEY_F11:
sound.adjustVolume(-1);
return true;
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:
if(!strstr(npc_text, RFIFOP(8))) {
strcat(npc_text, RFIFOP(8));
strcat(npc_text, "\n");
show_npc_dialog = 1;
}
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) {
SOUND_SID sound_id = sound.loadItem("./data/sound/wavs/level.wav");
sound.startItem(sound_id, 64);
sound.clearCache();
}
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);
//alert(RFIFOP(8),"","","","",0,0);
//parse_items(RFIFOP(8), RFIFOW(2));
parse_items(RFIFOP(8));
RFIFOW(2);
show_npc_dialog = 5;
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);
}
}
}