diff options
-rw-r--r-- | docs/TODO.txt | 53 | ||||
-rw-r--r-- | src/being.cpp | 257 | ||||
-rw-r--r-- | src/being.h | 42 | ||||
-rw-r--r-- | src/game.cpp | 1122 |
4 files changed, 744 insertions, 730 deletions
diff --git a/docs/TODO.txt b/docs/TODO.txt index 946383a6..81d3d364 100644 --- a/docs/TODO.txt +++ b/docs/TODO.txt @@ -1,26 +1,27 @@ -1) Gui - - Fix drag & drop (ElvenProgrammer) - - Add iconify button (ElvenProgrammer) - - Trading system (SimEdw) - - Add config dialog (SimEdw) -2) Sound engine - - ogg/mp3 playback (kth5) -3) Npc - - Quest system (SimEdw) -4) Chat - - Linewrapping in chatbox (kth5) -5) Graphics & animation - - Animated and transparent tiles (ElvenProgrammer) - - Fix fringe layer (ElvenProgrammer) -6) Battle system - - General fixes (ElvenProgrammer) - - Long range weapons - - Magic attacks -7) Misc - - Keyboard shortcuts - - Clothing and hairstyling system - - Item drops (ElvenProgrammer) - - Minimap -8) Optimization - - Bubble sort->quick sort - - Fix A* +Gui + - Fix drag & drop (ElvenProgrammer) + - Add iconify button (ElvenProgrammer) + - Trading system (SimEdw) + - Add config dialog (SimEdw) + +Npc + - Quest system (SimEdw) + +Graphics & animation + - Animated and transparent tiles (ElvenProgrammer) + - Fix fringe layer (ElvenProgrammer) + +Battle system + - General fixes (ElvenProgrammer) + - Long range weapons + - Magic attacks + +Misc + - Keyboard shortcuts + - Clothing and hairstyling system + - Item drops (ElvenProgrammer) + - Minimap + +Optimization + - Bubble sort->quick sort + - Fix A* diff --git a/src/being.cpp b/src/being.cpp index 31b87d73..4404854a 100644 --- a/src/being.cpp +++ b/src/being.cpp @@ -30,6 +30,7 @@ NODE *player_node = NULL; NODE *head = NULL; // First node of the list unsigned int b_count = 0; // Number of beings in the list + PATH_NODE::PATH_NODE(unsigned short x, unsigned short y): next(NULL) { @@ -44,172 +45,174 @@ PATH_NODE *calculate_path( return find_path(1, src_x, src_y, dest_x, dest_y); } -/** Returns the first node of the list */ -NODE *get_head() { - return head; -} - -/** Creates a empty node */ NODE::NODE(): - id(0), job(0), - next(NULL), - action(0), frame(0), - path(NULL), - speech(NULL), speech_time(0), - tick_time(0), speed(150), - emotion(0), emotion_time(0), - text_x(0), text_y(0), - hair_style(1), hair_color(1), - weapon(0) + id(0), job(0), + next(NULL), + action(0), frame(0), + path(NULL), + speech(NULL), speech_time(0), + tick_time(0), speed(150), + emotion(0), emotion_time(0), + text_x(0), text_y(0), + hair_style(1), hair_color(1), + weapon(0) { memset(coordinates, 0, 3); speech_color = makecol(0, 0, 0); } -/** Returns number of beings in the list */ +NODE *get_head() { + return head; +} + unsigned int get_count() { - return b_count; + return b_count; } -/** Removes all beings from the list */ void empty() { - NODE *node = head; - NODE *next; - while(node) { - next = node->next; - delete node; - node = next; - } - b_count = 0; - head = NULL; + NODE *node = head; + NODE *next; + while(node) { + next = node->next; + delete node; + node = next; + } + b_count = 0; + head = NULL; } -/** Add a node to the list */ void add_node(NODE *node) { - NODE *temp = head; - if(temp) { - while(temp->next) - temp = temp->next; - temp->next = node; - } else head = node; - b_count++; + NODE *temp = head; + if(temp) { + while(temp->next) + temp = temp->next; + temp->next = node; + } else head = node; + b_count++; } -/** Remove a node */ void remove_node(unsigned int id) { - unsigned int temp; - NODE *node_old, *node_new; - node_old = head; - node_new = NULL; - while(node_old) { - temp = get_id(node_old); - if(temp==id) { - if(node_new==NULL) { - head = node_old->next; - delete node_old; - b_count--; - return; - } else { + unsigned int temp; + NODE *node_old, *node_new; + node_old = head; + node_new = NULL; + while (node_old) { + temp = get_id(node_old); + if (temp==id) { + if (node_new==NULL) { + head = node_old->next; + delete node_old; + b_count--; + return; + } else { node_new->next = node_old->next; - delete node_old; - b_count--; - return; - } + delete node_old; + b_count--; + return; + } } else { - node_new = node_old; - node_old = node_old->next; + node_new = node_old; + node_old = node_old->next; + } } - } } -/** Returns the id of a being in the list */ unsigned int get_id(NODE *node) { - return node->id; + return node->id; } -/** Find a NPC id based on its coordinates */ unsigned int find_npc(unsigned short x, unsigned short y) { - NODE *node = head; - while(node) { - if((node->job>=46)&&(node->job<=125)) { // Check if is a NPC (only low job ids) - if((get_x(node->coordinates)==x)&&(get_y(node->coordinates)==y)) - return node->id; - else node = node->next; - } else { - node = node->next; - //alert("id","","","","",0,0); - } - } - return 0; + NODE *node = head; + while (node) { + // Check if is a NPC (only low job ids) + if ((node->job >= 46) && (node->job <= 125)) { + if ((get_x(node->coordinates) == x) && + (get_y(node->coordinates) == y)) + { + return node->id; + } + else { + node = node->next; + } + } else { + node = node->next; + } + } + return 0; } -/** Find a MONSTER id based on its coordinates */ unsigned int find_monster(unsigned short x, unsigned short y) { - NODE *node = head; - while(node) { - if(node->job>200) { // Check if is a MONSTER - if(get_x(node->coordinates)==x && get_y(node->coordinates)==y) - return node->id; + NODE *node = head; + while (node) { + // Check if is a MONSTER + if (node->job > 200) { + if (get_x(node->coordinates) == x && + get_y(node->coordinates) == y) + { + return node->id; + } + } + node = node->next; } - node = node->next; - } - return 0; + return 0; } -/** Return a specific id node */ NODE *find_node(unsigned int id) { - NODE *node = head; - while(node) - if(node->id==id) - return node; - else node = node->next; - return NULL; + NODE *node = head; + while (node) { + if (node->id == id) { + return node; + } + else { + node = node->next; + } + return NULL; + } } -/** Sort beings in vertical order using bubble sort */ void sort() { - NODE *p, *q, *r, *s, *temp; - s = NULL; - - while(s!=head->next) { - r = p = head; - q = p->next; - - while(p!=s) { - if(get_y(p->coordinates)>get_y(q->coordinates)) { - if(p==head) { - temp = q->next; - q->next = p; - p->next = temp; - head = q; - r = q; - } else { - temp = q->next; - q->next = p; - p->next = temp; - r->next = q; - r = q; + NODE *p, *q, *r, *s, *temp; + s = NULL; + + // Bubble sort + while (s != head->next) { + r = p = head; + q = p->next; + + while (p != s) { + if (get_y(p->coordinates) > get_y(q->coordinates)) { + if (p == head) { + temp = q->next; + q->next = p; + p->next = temp; + head = q; + r = q; + } else { + temp = q->next; + q->next = p; + p->next = temp; + r->next = q; + r = q; + } + } else { + r = p; + p = p->next; + } + q = p->next; + if (q == s) s = p; } - } else { - r = p; - p = p->next; - } - q = p->next; - if(q==s)s = p; } - } } -/** Remove all path nodes from a being */ void empty_path(NODE *node) { - if(node) { - PATH_NODE *temp = node->path; - PATH_NODE *next; - while(temp) { - next = temp->next; - delete temp; - temp = next; + if (node) { + PATH_NODE *temp = node->path; + PATH_NODE *next; + while (temp) { + next = temp->next; + delete temp; + temp = next; + } + node->path = NULL; } - node->path = NULL; - } } diff --git a/src/being.h b/src/being.h index f45023a1..a64e41e2 100644 --- a/src/being.h +++ b/src/being.h @@ -67,35 +67,43 @@ struct NODE { short weapon; }; +/** Removes all beings from the list */ void empty(); + +/** Returns the first node of the list */ NODE *get_head(); + +/** Add a node to the list */ void add_node(NODE *node); + +/** Return a specific id node */ NODE *find_node(unsigned int id); + +/** Remove a node */ void remove_node(unsigned int id); + +/** Returns number of beings in the list */ unsigned int get_count(); -bool remove_being(char *data); -void remove_being(unsigned int id); -int get_beings_size(); -bool is_being(int id); -void popup_being(unsigned char type, char *data); -void move_being(char *data); -PATH_NODE *calculate_path(unsigned short src_x, unsigned short src_y, unsigned short dest_x, unsigned short dest_y); + +PATH_NODE *calculate_path( + unsigned short src_x, unsigned short src_y, + unsigned short dest_x, unsigned short dest_y); + +/** Returns the id of a being in the list */ unsigned int get_id(NODE *node); + +/** Find a NPC id based on its coordinates */ unsigned int find_npc(unsigned short x, unsigned short y); + +/** Find a MONSTER id based on its coordinates */ unsigned int find_monster(unsigned short x, unsigned short y); + +/** Sort beings in vertical order */ void sort(); + +/** Remove all path nodes from a being */ void empty_path(NODE *node); extern NODE *player_node; -class Being { - public: - unsigned int id; - unsigned short x, y, direction; - unsigned short image; - unsigned char action, frame; -}; - -//std::vector<Being *> beings; - #endif diff --git a/src/game.cpp b/src/game.cpp index c84d8b3c..82973850 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -372,569 +372,571 @@ void do_parse() { 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);*/ + + // 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); + 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) { + // 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(); + 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); + } + 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); + } } - } } |