From 9ac2cf7bc508248450ddd9f3eaca32cb6fe715a4 Mon Sep 17 00:00:00 2001 From: Susu Date: Mon, 29 Jul 2013 15:09:42 +0200 Subject: Added chat interface --- src/map/chat.c | 871 ++++++++++++++++++++++++++++--------------------------- src/map/chat.h | 99 ++++--- src/map/clif.c | 14 +- src/map/npc.c | 2 +- src/map/script.c | 10 +- src/map/unit.c | 2 +- 6 files changed, 517 insertions(+), 481 deletions(-) diff --git a/src/map/chat.c b/src/map/chat.c index c0452f2c5..a6a5d2c8b 100644 --- a/src/map/chat.c +++ b/src/map/chat.c @@ -1,424 +1,447 @@ -// Copyright (c) Athena Dev Teams - Licensed under GNU GPL -// For more information, see LICENCE in the main folder - -#include "../common/cbasetypes.h" -#include "../common/malloc.h" -#include "../common/nullpo.h" -#include "../common/showmsg.h" -#include "../common/strlib.h" -#include "../common/mmo.h" -#include "atcommand.h" // msg_txt() -#include "battle.h" // struct battle_config -#include "clif.h" -#include "map.h" -#include "npc.h" // npc_event_do() -#include "pc.h" -#include "skill.h" // ext_skill_unit_onplace() -#include "chat.h" - -#include -#include - - -int chat_triggerevent(struct chat_data *cd); // forward declaration - -/// Initializes a chatroom object (common functionality for both pc and npc chatrooms). -/// Returns a chatroom object on success, or NULL on failure. -static struct chat_data* chat_createchat(struct block_list* bl, const char* title, const char* pass, int limit, bool pub, int trigger, const char* ev, int zeny, int minLvl, int maxLvl) -{ - struct chat_data* cd; - nullpo_retr(NULL, bl); - - cd = (struct chat_data *) aMalloc(sizeof(struct chat_data)); - - safestrncpy(cd->title, title, sizeof(cd->title)); - safestrncpy(cd->pass, pass, sizeof(cd->pass)); - cd->pub = pub; - cd->users = 0; - cd->limit = min(limit, ARRAYLENGTH(cd->usersd)); - cd->trigger = trigger; - cd->zeny = zeny; - cd->minLvl = minLvl; - cd->maxLvl = maxLvl; - memset(cd->usersd, 0, sizeof(cd->usersd)); - cd->owner = bl; - safestrncpy(cd->npc_event, ev, sizeof(cd->npc_event)); - - cd->bl.id = iMap->get_new_object_id(); - cd->bl.m = bl->m; - cd->bl.x = bl->x; - cd->bl.y = bl->y; - cd->bl.type = BL_CHAT; - cd->bl.next = cd->bl.prev = NULL; - - if( cd->bl.id == 0 ) - { - aFree(cd); - cd = NULL; - } - - iMap->addiddb(&cd->bl); - - if( bl->type != BL_NPC ) - cd->kick_list = idb_alloc(DB_OPT_BASE); - - return cd; -} - -/*========================================== - * player chatroom creation - *------------------------------------------*/ -int chat_createpcchat(struct map_session_data* sd, const char* title, const char* pass, int limit, bool pub) -{ - struct chat_data* cd; - nullpo_ret(sd); - - if( sd->chatID ) - return 0; //Prevent people abusing the chat system by creating multiple chats, as pointed out by End of Exam. [Skotlex] - - if( sd->state.vending || sd->state.buyingstore ) - {// not chat, when you already have a store open - return 0; - } - - if( map[sd->bl.m].flag.nochat ) - { - clif->message(sd->fd, msg_txt(281)); - return 0; //Can't create chatrooms on this map. - } - - if( iMap->getcell(sd->bl.m,sd->bl.x,sd->bl.y,CELL_CHKNOCHAT) ) - { - clif->message (sd->fd, msg_txt(665)); - return 0; - } - - pc_stop_walking(sd,1); - - cd = chat_createchat(&sd->bl, title, pass, limit, pub, 0, "", 0, 1, MAX_LEVEL); - if( cd ) { - cd->users = 1; - cd->usersd[0] = sd; - pc_setchatid(sd,cd->bl.id); - pc_stop_attack(sd); - clif->createchat(sd,0); - clif->dispchat(cd,0); - } else - clif->createchat(sd,1); - - return 0; -} - -/*========================================== - * join an existing chatroom - *------------------------------------------*/ -int chat_joinchat(struct map_session_data* sd, int chatid, const char* pass) -{ - struct chat_data* cd; - - nullpo_ret(sd); - cd = (struct chat_data*)iMap->id2bl(chatid); - - if( cd == NULL || cd->bl.type != BL_CHAT || cd->bl.m != sd->bl.m || sd->state.vending || sd->state.buyingstore || sd->chatID || ((cd->owner->type == BL_NPC) ? cd->users+1 : cd->users) >= cd->limit ) - { - clif->joinchatfail(sd,0); - return 0; - } - - if( !cd->pub && strncmp(pass, cd->pass, sizeof(cd->pass)) != 0 && !pc_has_permission(sd, PC_PERM_JOIN_ALL_CHAT) ) - { - clif->joinchatfail(sd,1); - return 0; - } - - if( sd->status.base_level < cd->minLvl || sd->status.base_level > cd->maxLvl ) { - if(sd->status.base_level < cd->minLvl) - clif->joinchatfail(sd,5); - else - clif->joinchatfail(sd,6); - - return 0; - } - - if( sd->status.zeny < cd->zeny ) { - clif->joinchatfail(sd,4); - return 0; - } - - if( cd->owner->type != BL_NPC && idb_exists(cd->kick_list,sd->status.char_id) ) { - clif->joinchatfail(sd,2);//You have been kicked out of the room. - return 0; - } - - pc_stop_walking(sd,1); - cd->usersd[cd->users] = sd; - cd->users++; - - pc_setchatid(sd,cd->bl.id); - - clif->joinchatok(sd, cd); //To the person who newly joined the list of all - clif->addchat(cd, sd); //Reports To the person who already in the chat - clif->dispchat(cd, 0); //Reported number of changes to the people around - - chat_triggerevent(cd); //Event - - return 0; -} - - -/*========================================== - * leave a chatroom - *------------------------------------------*/ -int chat_leavechat(struct map_session_data* sd, bool kicked) -{ - struct chat_data* cd; - int i; - int leavechar; - - nullpo_retr(1, sd); - - cd = (struct chat_data*)iMap->id2bl(sd->chatID); - if( cd == NULL ) - { - pc_setchatid(sd, 0); - return 1; - } - - ARR_FIND( 0, cd->users, i, cd->usersd[i] == sd ); - if ( i == cd->users ) - { // Not found in the chatroom? - pc_setchatid(sd, 0); - return -1; - } - - clif->leavechat(cd, sd, kicked); - pc_setchatid(sd, 0); - cd->users--; - - leavechar = i; - - for( i = leavechar; i < cd->users; i++ ) - cd->usersd[i] = cd->usersd[i+1]; - - - if( cd->users == 0 && cd->owner->type == BL_PC ) { // Delete empty chatroom - struct skill_unit* unit; - struct skill_unit_group* group; - - clif->clearchat(cd, 0); - db_destroy(cd->kick_list); - iMap->deliddb(&cd->bl); - iMap->delblock(&cd->bl); - iMap->freeblock(&cd->bl); - - unit = iMap->find_skill_unit_oncell(&sd->bl, sd->bl.x, sd->bl.y, AL_WARP, NULL, 0); - group = (unit != NULL) ? unit->group : NULL; - if (group != NULL) - skill->unit_onplace(unit, &sd->bl, group->tick); - - return 1; - } - - if( leavechar == 0 && cd->owner->type == BL_PC ) - { // Set and announce new owner - cd->owner = (struct block_list*) cd->usersd[0]; - clif->changechatowner(cd, cd->usersd[0]); - clif->clearchat(cd, 0); - - //Adjust Chat location after owner has been changed. - iMap->delblock( &cd->bl ); - cd->bl.x=cd->usersd[0]->bl.x; - cd->bl.y=cd->usersd[0]->bl.y; - iMap->addblock( &cd->bl ); - - clif->dispchat(cd,0); - } - else - clif->dispchat(cd,0); // refresh chatroom - - return 0; -} - -/*========================================== - * change a chatroom's owner - *------------------------------------------*/ -int chat_changechatowner(struct map_session_data* sd, const char* nextownername) -{ - struct chat_data* cd; - struct map_session_data* tmpsd; - int i; - - nullpo_retr(1, sd); - - cd = (struct chat_data*)iMap->id2bl(sd->chatID); - if( cd == NULL || (struct block_list*) sd != cd->owner ) - return 1; - - ARR_FIND( 1, cd->users, i, strncmp(cd->usersd[i]->status.name, nextownername, NAME_LENGTH) == 0 ); - if( i == cd->users ) - return -1; // name not found - - // erase temporarily - clif->clearchat(cd,0); - - // set new owner - cd->owner = (struct block_list*) cd->usersd[i]; - clif->changechatowner(cd,cd->usersd[i]); - - // swap the old and new owners' positions - tmpsd = cd->usersd[i]; - cd->usersd[i] = cd->usersd[0]; - cd->usersd[0] = tmpsd; - - // set the new chatroom position - iMap->delblock( &cd->bl ); - cd->bl.x = cd->owner->x; - cd->bl.y = cd->owner->y; - iMap->addblock( &cd->bl ); - - // and display again - clif->dispchat(cd,0); - - return 0; -} - -/*========================================== - * change a chatroom's status (title, etc) - *------------------------------------------*/ -int chat_changechatstatus(struct map_session_data* sd, const char* title, const char* pass, int limit, bool pub) -{ - struct chat_data* cd; - - nullpo_retr(1, sd); - - cd = (struct chat_data*)iMap->id2bl(sd->chatID); - if( cd==NULL || (struct block_list *)sd != cd->owner ) - return 1; - - safestrncpy(cd->title, title, CHATROOM_TITLE_SIZE); - safestrncpy(cd->pass, pass, CHATROOM_PASS_SIZE); - cd->limit = min(limit, ARRAYLENGTH(cd->usersd)); - cd->pub = pub; - - clif->changechatstatus(cd); - clif->dispchat(cd,0); - - return 0; -} - -/*========================================== - * kick an user from a chatroom - *------------------------------------------*/ -int chat_kickchat(struct map_session_data* sd, const char* kickusername) -{ - struct chat_data* cd; - int i; - - nullpo_retr(1, sd); - - cd = (struct chat_data *)iMap->id2bl(sd->chatID); - - if( cd==NULL || (struct block_list *)sd != cd->owner ) - return -1; - - ARR_FIND( 0, cd->users, i, strncmp(cd->usersd[i]->status.name, kickusername, NAME_LENGTH) == 0 ); - if( i == cd->users ) - return -1; - - if (pc_has_permission(cd->usersd[i], PC_PERM_NO_CHAT_KICK)) - return 0; //gm kick protection [Valaris] - - idb_put(cd->kick_list,cd->usersd[i]->status.char_id,(void*)1); - - chat_leavechat(cd->usersd[i],1); - return 0; -} - -/// Creates a chat room for the npc. -int chat_createnpcchat(struct npc_data* nd, const char* title, int limit, bool pub, int trigger, const char* ev, int zeny, int minLvl, int maxLvl) -{ - struct chat_data* cd; - nullpo_ret(nd); - - if( nd->chat_id ) { - ShowError("chat_createnpcchat: npc '%s' already has a chatroom, cannot create new one!\n", nd->exname); - return 0; - } - - if( zeny > MAX_ZENY || maxLvl > MAX_LEVEL ) { - ShowError("chat_createnpcchat: npc '%s' has a required lvl or amount of zeny over the max limit!\n", nd->exname); - return 0; - } - - cd = chat_createchat(&nd->bl, title, "", limit, pub, trigger, ev, zeny, minLvl, maxLvl); - - if( cd ) { - nd->chat_id = cd->bl.id; - clif->dispchat(cd,0); - } - - return 0; -} - -/// Removes the chatroom from the npc. -int chat_deletenpcchat(struct npc_data* nd) -{ - struct chat_data *cd; - nullpo_ret(nd); - - cd = (struct chat_data*)iMap->id2bl(nd->chat_id); - if( cd == NULL ) - return 0; - - chat_npckickall(cd); - clif->clearchat(cd, 0); - iMap->deliddb(&cd->bl); - iMap->delblock(&cd->bl); - iMap->freeblock(&cd->bl); - nd->chat_id = 0; - - return 0; -} - -/*========================================== - * Trigger npc event when we enter the chatroom - *------------------------------------------*/ -int chat_triggerevent(struct chat_data *cd) -{ - nullpo_ret(cd); - - if( cd->users >= cd->trigger && cd->npc_event[0] ) - npc_event_do(cd->npc_event); - return 0; -} - -/// Enables the event of the chat room. -/// At most, 127 users are needed to trigger the event. -int chat_enableevent(struct chat_data* cd) -{ - nullpo_ret(cd); - - cd->trigger &= 0x7f; - chat_triggerevent(cd); - return 0; -} - -/// Disables the event of the chat room -int chat_disableevent(struct chat_data* cd) -{ - nullpo_ret(cd); - - cd->trigger |= 0x80; - return 0; -} - -/// Kicks all the users from the chat room. -int chat_npckickall(struct chat_data* cd) -{ - nullpo_ret(cd); - - while( cd->users > 0 ) - chat_leavechat(cd->usersd[cd->users-1],0); - - return 0; -} +// Copyright (c) Athena Dev Teams - Licensed under GNU GPL +// For more information, see LICENCE in the main folder + +#include "../common/cbasetypes.h" +#include "../common/malloc.h" +#include "../common/nullpo.h" +#include "../common/showmsg.h" +#include "../common/strlib.h" +#include "../common/mmo.h" +#include "atcommand.h" // msg_txt() +#include "battle.h" // struct battle_config +#include "clif.h" +#include "map.h" +#include "npc.h" // npc_event_do() +#include "pc.h" +#include "skill.h" // ext_skill_unit_onplace() +#include "chat.h" + +#include +#include + + +int chat_triggerevent(struct chat_data *cd); // forward declaration + +/// Initializes a chatroom object (common functionality for both pc and npc chatrooms). +/// Returns a chatroom object on success, or NULL on failure. +static struct chat_data* chat_createchat(struct block_list* bl, const char* title, const char* pass, int limit, bool pub, int trigger, const char* ev, int zeny, int minLvl, int maxLvl) +{ + struct chat_data* cd; + nullpo_retr(NULL, bl); + + cd = (struct chat_data *) aMalloc(sizeof(struct chat_data)); + + safestrncpy(cd->title, title, sizeof(cd->title)); + safestrncpy(cd->pass, pass, sizeof(cd->pass)); + cd->pub = pub; + cd->users = 0; + cd->limit = min(limit, ARRAYLENGTH(cd->usersd)); + cd->trigger = trigger; + cd->zeny = zeny; + cd->minLvl = minLvl; + cd->maxLvl = maxLvl; + memset(cd->usersd, 0, sizeof(cd->usersd)); + cd->owner = bl; + safestrncpy(cd->npc_event, ev, sizeof(cd->npc_event)); + + cd->bl.id = iMap->get_new_object_id(); + cd->bl.m = bl->m; + cd->bl.x = bl->x; + cd->bl.y = bl->y; + cd->bl.type = BL_CHAT; + cd->bl.next = cd->bl.prev = NULL; + + if( cd->bl.id == 0 ) + { + aFree(cd); + cd = NULL; + } + + iMap->addiddb(&cd->bl); + + if( bl->type != BL_NPC ) + cd->kick_list = idb_alloc(DB_OPT_BASE); + + return cd; +} + +/*========================================== + * player chatroom creation + *------------------------------------------*/ +int chat_createpcchat(struct map_session_data* sd, const char* title, const char* pass, int limit, bool pub) +{ + struct chat_data* cd; + nullpo_ret(sd); + + if( sd->chatID ) + return 0; //Prevent people abusing the chat system by creating multiple chats, as pointed out by End of Exam. [Skotlex] + + if( sd->state.vending || sd->state.buyingstore ) + {// not chat, when you already have a store open + return 0; + } + + if( map[sd->bl.m].flag.nochat ) + { + clif->message(sd->fd, msg_txt(281)); + return 0; //Can't create chatrooms on this map. + } + + if( iMap->getcell(sd->bl.m,sd->bl.x,sd->bl.y,CELL_CHKNOCHAT) ) + { + clif->message (sd->fd, msg_txt(665)); + return 0; + } + + pc_stop_walking(sd,1); + + cd = chat_createchat(&sd->bl, title, pass, limit, pub, 0, "", 0, 1, MAX_LEVEL); + if( cd ) { + cd->users = 1; + cd->usersd[0] = sd; + pc_setchatid(sd,cd->bl.id); + pc_stop_attack(sd); + clif->createchat(sd,0); + clif->dispchat(cd,0); + } else + clif->createchat(sd,1); + + return 0; +} + +/*========================================== + * join an existing chatroom + *------------------------------------------*/ +int chat_joinchat(struct map_session_data* sd, int chatid, const char* pass) +{ + struct chat_data* cd; + + nullpo_ret(sd); + cd = (struct chat_data*)iMap->id2bl(chatid); + + if( cd == NULL || cd->bl.type != BL_CHAT || cd->bl.m != sd->bl.m || sd->state.vending || sd->state.buyingstore || sd->chatID || ((cd->owner->type == BL_NPC) ? cd->users+1 : cd->users) >= cd->limit ) + { + clif->joinchatfail(sd,0); + return 0; + } + + if( !cd->pub && strncmp(pass, cd->pass, sizeof(cd->pass)) != 0 && !pc_has_permission(sd, PC_PERM_JOIN_ALL_CHAT) ) + { + clif->joinchatfail(sd,1); + return 0; + } + + if( sd->status.base_level < cd->minLvl || sd->status.base_level > cd->maxLvl ) { + if(sd->status.base_level < cd->minLvl) + clif->joinchatfail(sd,5); + else + clif->joinchatfail(sd,6); + + return 0; + } + + if( sd->status.zeny < cd->zeny ) { + clif->joinchatfail(sd,4); + return 0; + } + + if( cd->owner->type != BL_NPC && idb_exists(cd->kick_list,sd->status.char_id) ) { + clif->joinchatfail(sd,2);//You have been kicked out of the room. + return 0; + } + + pc_stop_walking(sd,1); + cd->usersd[cd->users] = sd; + cd->users++; + + pc_setchatid(sd,cd->bl.id); + + clif->joinchatok(sd, cd); //To the person who newly joined the list of all + clif->addchat(cd, sd); //Reports To the person who already in the chat + clif->dispchat(cd, 0); //Reported number of changes to the people around + + chat_triggerevent(cd); //Event + + return 0; +} + + +/*========================================== + * leave a chatroom + *------------------------------------------*/ +int chat_leavechat(struct map_session_data* sd, bool kicked) +{ + struct chat_data* cd; + int i; + int leavechar; + + nullpo_retr(1, sd); + + cd = (struct chat_data*)iMap->id2bl(sd->chatID); + if( cd == NULL ) + { + pc_setchatid(sd, 0); + return 1; + } + + ARR_FIND( 0, cd->users, i, cd->usersd[i] == sd ); + if ( i == cd->users ) + { // Not found in the chatroom? + pc_setchatid(sd, 0); + return -1; + } + + clif->leavechat(cd, sd, kicked); + pc_setchatid(sd, 0); + cd->users--; + + leavechar = i; + + for( i = leavechar; i < cd->users; i++ ) + cd->usersd[i] = cd->usersd[i+1]; + + + if( cd->users == 0 && cd->owner->type == BL_PC ) { // Delete empty chatroom + struct skill_unit* unit; + struct skill_unit_group* group; + + clif->clearchat(cd, 0); + db_destroy(cd->kick_list); + iMap->deliddb(&cd->bl); + iMap->delblock(&cd->bl); + iMap->freeblock(&cd->bl); + + unit = iMap->find_skill_unit_oncell(&sd->bl, sd->bl.x, sd->bl.y, AL_WARP, NULL, 0); + group = (unit != NULL) ? unit->group : NULL; + if (group != NULL) + skill->unit_onplace(unit, &sd->bl, group->tick); + + return 1; + } + + if( leavechar == 0 && cd->owner->type == BL_PC ) + { // Set and announce new owner + cd->owner = (struct block_list*) cd->usersd[0]; + clif->changechatowner(cd, cd->usersd[0]); + clif->clearchat(cd, 0); + + //Adjust Chat location after owner has been changed. + iMap->delblock( &cd->bl ); + cd->bl.x=cd->usersd[0]->bl.x; + cd->bl.y=cd->usersd[0]->bl.y; + iMap->addblock( &cd->bl ); + + clif->dispchat(cd,0); + } + else + clif->dispchat(cd,0); // refresh chatroom + + return 0; +} + +/*========================================== + * change a chatroom's owner + *------------------------------------------*/ +int chat_changechatowner(struct map_session_data* sd, const char* nextownername) +{ + struct chat_data* cd; + struct map_session_data* tmpsd; + int i; + + nullpo_retr(1, sd); + + cd = (struct chat_data*)iMap->id2bl(sd->chatID); + if( cd == NULL || (struct block_list*) sd != cd->owner ) + return 1; + + ARR_FIND( 1, cd->users, i, strncmp(cd->usersd[i]->status.name, nextownername, NAME_LENGTH) == 0 ); + if( i == cd->users ) + return -1; // name not found + + // erase temporarily + clif->clearchat(cd,0); + + // set new owner + cd->owner = (struct block_list*) cd->usersd[i]; + clif->changechatowner(cd,cd->usersd[i]); + + // swap the old and new owners' positions + tmpsd = cd->usersd[i]; + cd->usersd[i] = cd->usersd[0]; + cd->usersd[0] = tmpsd; + + // set the new chatroom position + iMap->delblock( &cd->bl ); + cd->bl.x = cd->owner->x; + cd->bl.y = cd->owner->y; + iMap->addblock( &cd->bl ); + + // and display again + clif->dispchat(cd,0); + + return 0; +} + +/*========================================== + * change a chatroom's status (title, etc) + *------------------------------------------*/ +int chat_changechatstatus(struct map_session_data* sd, const char* title, const char* pass, int limit, bool pub) +{ + struct chat_data* cd; + + nullpo_retr(1, sd); + + cd = (struct chat_data*)iMap->id2bl(sd->chatID); + if( cd==NULL || (struct block_list *)sd != cd->owner ) + return 1; + + safestrncpy(cd->title, title, CHATROOM_TITLE_SIZE); + safestrncpy(cd->pass, pass, CHATROOM_PASS_SIZE); + cd->limit = min(limit, ARRAYLENGTH(cd->usersd)); + cd->pub = pub; + + clif->changechatstatus(cd); + clif->dispchat(cd,0); + + return 0; +} + +/*========================================== + * kick an user from a chatroom + *------------------------------------------*/ +int chat_kickchat(struct map_session_data* sd, const char* kickusername) +{ + struct chat_data* cd; + int i; + + nullpo_retr(1, sd); + + cd = (struct chat_data *)iMap->id2bl(sd->chatID); + + if( cd==NULL || (struct block_list *)sd != cd->owner ) + return -1; + + ARR_FIND( 0, cd->users, i, strncmp(cd->usersd[i]->status.name, kickusername, NAME_LENGTH) == 0 ); + if( i == cd->users ) + return -1; + + if (pc_has_permission(cd->usersd[i], PC_PERM_NO_CHAT_KICK)) + return 0; //gm kick protection [Valaris] + + idb_put(cd->kick_list,cd->usersd[i]->status.char_id,(void*)1); + + chat->leavechat(cd->usersd[i],1); + return 0; +} + +/// Creates a chat room for the npc. +int chat_createnpcchat(struct npc_data* nd, const char* title, int limit, bool pub, int trigger, const char* ev, int zeny, int minLvl, int maxLvl) +{ + struct chat_data* cd; + nullpo_ret(nd); + + if( nd->chat_id ) { + ShowError("chat_createnpcchat: npc '%s' already has a chatroom, cannot create new one!\n", nd->exname); + return 0; + } + + if( zeny > MAX_ZENY || maxLvl > MAX_LEVEL ) { + ShowError("chat_createnpcchat: npc '%s' has a required lvl or amount of zeny over the max limit!\n", nd->exname); + return 0; + } + + cd = chat_createchat(&nd->bl, title, "", limit, pub, trigger, ev, zeny, minLvl, maxLvl); + + if( cd ) { + nd->chat_id = cd->bl.id; + clif->dispchat(cd,0); + } + + return 0; +} + +/// Removes the chatroom from the npc. +int chat_deletenpcchat(struct npc_data* nd) +{ + struct chat_data *cd; + nullpo_ret(nd); + + cd = (struct chat_data*)iMap->id2bl(nd->chat_id); + if( cd == NULL ) + return 0; + + chat->npckickall(cd); + clif->clearchat(cd, 0); + iMap->deliddb(&cd->bl); + iMap->delblock(&cd->bl); + iMap->freeblock(&cd->bl); + nd->chat_id = 0; + + return 0; +} + +/*========================================== + * Trigger npc event when we enter the chatroom + *------------------------------------------*/ +int chat_triggerevent(struct chat_data *cd) +{ + nullpo_ret(cd); + + if( cd->users >= cd->trigger && cd->npc_event[0] ) + npc_event_do(cd->npc_event); + return 0; +} + +/// Enables the event of the chat room. +/// At most, 127 users are needed to trigger the event. +int chat_enableevent(struct chat_data* cd) +{ + nullpo_ret(cd); + + cd->trigger &= 0x7f; + chat_triggerevent(cd); + return 0; +} + +/// Disables the event of the chat room +int chat_disableevent(struct chat_data* cd) +{ + nullpo_ret(cd); + + cd->trigger |= 0x80; + return 0; +} + +/// Kicks all the users from the chat room. +int chat_npckickall(struct chat_data* cd) +{ + nullpo_ret(cd); + + while( cd->users > 0 ) + chat->leavechat(cd->usersd[cd->users-1],0); + + return 0; +} + +/*===================================== +* Default Functions : chat.h +* Generated by HerculesInterfaceMaker +* created by Susu +*-------------------------------------*/ +void chat_defaults(void) { + chat = &chat_s; + /* funcs */ + + chat->createpcchat = chat_createpcchat; + chat->joinchat = chat_joinchat; + chat->leavechat = chat_leavechat; + chat->changechatowner = chat_changechatowner; + chat->changechatstatus = chat_changechatstatus; + chat->kickchat = chat_kickchat; + + chat->createnpcchat = chat_createnpcchat; + chat->deletenpcchat = chat_deletenpcchat; + chat->enableevent = chat_enableevent; + chat->disableevent = chat_disableevent; + chat->npckickall = chat_npckickall; +} diff --git a/src/map/chat.h b/src/map/chat.h index cb2e6ecd9..ff78d8617 100644 --- a/src/map/chat.h +++ b/src/map/chat.h @@ -1,43 +1,56 @@ -// Copyright (c) Athena Dev Teams - Licensed under GNU GPL -// For more information, see LICENCE in the main folder - -#ifndef _CHAT_H_ -#define _CHAT_H_ - -#include "map.h" // struct block_list, CHATROOM_TITLE_SIZE -struct map_session_data; -struct chat_data; - - -struct chat_data { - struct block_list bl; // data for this map object - char title[CHATROOM_TITLE_SIZE]; // room title - char pass[CHATROOM_PASS_SIZE]; // password - bool pub; // private/public flag - uint8 users; // current user count - uint8 limit; // join limit - uint8 trigger; // number of users needed to trigger event - uint32 zeny; // required zeny to join - uint32 minLvl; // minimum base level to join - uint32 maxLvl; // maximum base level allowed to join - struct map_session_data* usersd[20]; - struct block_list* owner; - char npc_event[EVENT_NAME_LENGTH]; - DBMap* kick_list; //DBMap of users who were kicked from this chat -}; - - -int chat_createpcchat(struct map_session_data* sd, const char* title, const char* pass, int limit, bool pub); -int chat_joinchat(struct map_session_data* sd, int chatid, const char* pass); -int chat_leavechat(struct map_session_data* sd, bool kicked); -int chat_changechatowner(struct map_session_data* sd, const char* nextownername); -int chat_changechatstatus(struct map_session_data* sd, const char* title, const char* pass, int limit, bool pub); -int chat_kickchat(struct map_session_data* sd, const char* kickusername); - -int chat_createnpcchat(struct npc_data* nd, const char* title, int limit, bool pub, int trigger, const char* ev, int zeny, int minLvl, int maxLvl); -int chat_deletenpcchat(struct npc_data* nd); -int chat_enableevent(struct chat_data* cd); -int chat_disableevent(struct chat_data* cd); -int chat_npckickall(struct chat_data* cd); - -#endif /* _CHAT_H_ */ +// Copyright (c) Athena Dev Teams - Licensed under GNU GPL +// For more information, see LICENCE in the main folder +#ifndef _CHAT_H_ +#define _CHAT_H_ +#include "map.h" // struct block_list, CHATROOM_TITLE_SIZE +struct map_session_data; +struct chat_data; + + +struct chat_data { + struct block_list bl; // data for this map object + char title[CHATROOM_TITLE_SIZE]; // room title + char pass[CHATROOM_PASS_SIZE]; // password + bool pub; // private/public flag + uint8 users; // current user count + uint8 limit; // join limit + uint8 trigger; // number of users needed to trigger event + uint32 zeny; // required zeny to join + uint32 minLvl; // minimum base level to join + uint32 maxLvl; // maximum base level allowed to join + struct map_session_data* usersd[20]; + struct block_list* owner; + char npc_event[EVENT_NAME_LENGTH]; + DBMap* kick_list; //DBMap of users who were kicked from this chat +}; + + + + +/*===================================== +* Interface : chat.h +* Generated by HerculesInterfaceMaker +* created by Susu +*-------------------------------------*/ +struct chat_interface { + /* funcs */ + + int (*createpcchat) (struct map_session_data* sd, const char* title, const char* pass, int limit, bool pub); + int (*joinchat) (struct map_session_data* sd, int chatid, const char* pass); + int (*leavechat) (struct map_session_data* sd, bool kicked); + int (*changechatowner) (struct map_session_data* sd, const char* nextownername); + int (*changechatstatus) (struct map_session_data* sd, const char* title, const char* pass, int limit, bool pub); + int (*kickchat) (struct map_session_data* sd, const char* kickusername); + + int (*createnpcchat) (struct npc_data* nd, const char* title, int limit, bool pub, int trigger, const char* ev, int zeny, int minLvl, int maxLvl); + int (*deletenpcchat) (struct npc_data* nd); + int (*enableevent) (struct chat_data* cd); + int (*disableevent) (struct chat_data* cd); + int (*npckickall) (struct chat_data* cd); +} chat_s; + +struct chat_interface *chat; + +void chat_defaults(void); + +#endif /* _CHAT_H_ */ diff --git a/src/map/clif.c b/src/map/clif.c index 718b98bc5..8377eed5c 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -8573,7 +8573,7 @@ void clif_refresh(struct map_session_data *sd) iMap->foreachinrange(clif->getareachar,&sd->bl,AREA_SIZE,BL_ALL,sd); clif->weather_check(sd); if( sd->chatID ) - chat_leavechat(sd,0); + chat->leavechat(sd,0); if( sd->state.vending ) clif->openvending(sd, sd->bl.id, sd->vending); if( pc_issit(sd) ) @@ -10966,7 +10966,7 @@ void clif_parse_CreateChatRoom(int fd, struct map_session_data* sd) safestrncpy(s_password, password, CHATROOM_PASS_SIZE); safestrncpy(s_title, title, min(len+1,CHATROOM_TITLE_SIZE)); //NOTE: assumes that safestrncpy will not access the len+1'th byte - chat_createpcchat(sd, s_title, s_password, limit, pub); + chat->createpcchat(sd, s_title, s_password, limit, pub); } @@ -10977,7 +10977,7 @@ void clif_parse_ChatAddMember(int fd, struct map_session_data* sd) int chatid = RFIFOL(fd,2); const char* password = (char*)RFIFOP(fd,6); // not zero-terminated - chat_joinchat(sd,chatid,password); + chat->joinchat(sd,chatid,password); } @@ -11002,7 +11002,7 @@ void clif_parse_ChatRoomStatusChange(int fd, struct map_session_data* sd) safestrncpy(s_password, password, CHATROOM_PASS_SIZE); safestrncpy(s_title, title, min(len+1,CHATROOM_TITLE_SIZE)); //NOTE: assumes that safestrncpy will not access the len+1'th byte - chat_changechatstatus(sd, s_title, s_password, limit, pub); + chat->changechatstatus(sd, s_title, s_password, limit, pub); } @@ -11013,7 +11013,7 @@ void clif_parse_ChatRoomStatusChange(int fd, struct map_session_data* sd) /// 1 = normal void clif_parse_ChangeChatOwner(int fd, struct map_session_data* sd) { - chat_changechatowner(sd,(char*)RFIFOP(fd,6)); + chat->changechatowner(sd,(char*)RFIFOP(fd,6)); } @@ -11021,7 +11021,7 @@ void clif_parse_ChangeChatOwner(int fd, struct map_session_data* sd) /// 00e2 .24B void clif_parse_KickFromChat(int fd,struct map_session_data *sd) { - chat_kickchat(sd,(char*)RFIFOP(fd,2)); + chat->kickchat(sd,(char*)RFIFOP(fd,2)); } @@ -11029,7 +11029,7 @@ void clif_parse_KickFromChat(int fd,struct map_session_data *sd) /// 00e3 void clif_parse_ChatLeave(int fd, struct map_session_data* sd) { - chat_leavechat(sd,0); + chat->leavechat(sd,0); } diff --git a/src/map/npc.c b/src/map/npc.c index 911fbe1d4..6bb058229 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -1817,7 +1817,7 @@ int npc_unload(struct npc_data* nd, bool single) { strdb_remove(npcname_db, nd->exname); if (nd->chat_id) // remove npc chatroom object and kick users - chat_deletenpcchat(nd); + chat->deletenpcchat(nd); #ifdef PCRE_SUPPORT npc_chat_finalize(nd); // deallocate npc PCRE data structures diff --git a/src/map/script.c b/src/map/script.c index 865673630..0827eb497 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -10017,7 +10017,7 @@ BUILDIN(waitingroom) nd = (struct npc_data *)iMap->id2bl(st->oid); if( nd != NULL ) - chat_createnpcchat(nd, title, limit, pub, trigger, ev, zeny, minLvl, maxLvl); + chat->createnpcchat(nd, title, limit, pub, trigger, ev, zeny, minLvl, maxLvl); return true; } @@ -10034,7 +10034,7 @@ BUILDIN(delwaitingroom) else nd = (struct npc_data *)iMap->id2bl(st->oid); if( nd != NULL ) - chat_deletenpcchat(nd); + chat->deletenpcchat(nd); return true; } @@ -10053,7 +10053,7 @@ BUILDIN(waitingroomkickall) nd = (struct npc_data *)iMap->id2bl(st->oid); if( nd != NULL && (cd=(struct chat_data *)iMap->id2bl(nd->chat_id)) != NULL ) - chat_npckickall(cd); + chat->npckickall(cd); return true; } @@ -10072,7 +10072,7 @@ BUILDIN(enablewaitingroomevent) nd = (struct npc_data *)iMap->id2bl(st->oid); if( nd != NULL && (cd=(struct chat_data *)iMap->id2bl(nd->chat_id)) != NULL ) - chat_enableevent(cd); + chat->enableevent(cd); return true; } @@ -10091,7 +10091,7 @@ BUILDIN(disablewaitingroomevent) nd = (struct npc_data *)iMap->id2bl(st->oid); if( nd != NULL && (cd=(struct chat_data *)iMap->id2bl(nd->chat_id)) != NULL ) - chat_disableevent(cd); + chat->disableevent(cd); return true; } diff --git a/src/map/unit.c b/src/map/unit.c index b1ed24666..38606230f 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -2131,7 +2131,7 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file, } //Leave/reject all invitations. if(sd->chatID) - chat_leavechat(sd,0); + chat->leavechat(sd,0); if(sd->trade_partner) trade->cancel(sd); buyingstore->close(sd); -- cgit v1.2.3-60-g2f50 From 5a22b0445416dbf7d0a0ddd95d31c1f068e704b3 Mon Sep 17 00:00:00 2001 From: Susu Date: Mon, 29 Jul 2013 15:16:48 +0200 Subject: Added iDuel interface (duel.c) --- src/map/atcommand.c | 28 ++-- src/map/duel.c | 388 +++++++++++++++++++++++++++------------------------- src/map/duel.h | 46 +++++-- src/map/map.c | 4 +- src/map/pc.c | 4 +- src/map/unit.c | 4 +- 6 files changed, 255 insertions(+), 219 deletions(-) diff --git a/src/map/atcommand.c b/src/map/atcommand.c index 069856754..d11fd9a9b 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -7694,8 +7694,8 @@ ACMD(invite) return true; } - if(duel_list[did].max_players_limit > 0 && - duel_list[did].members_count >= duel_list[did].max_players_limit) { + if(iDuel->duel_list[did].max_players_limit > 0 && + iDuel->duel_list[did].members_count >= iDuel->duel_list[did].max_players_limit) { // "Duel: Limit of players is reached." clif->message(fd, msg_txt(351)); @@ -7721,7 +7721,7 @@ ACMD(invite) return true; } - duel_invite(did, sd, target_sd); + iDuel->invite(did, sd, target_sd); // "Duel: Invitation has been sent." clif->message(fd, msg_txt(354)); return true; @@ -7732,7 +7732,7 @@ ACMD(duel) unsigned int maxpl = 0; if(sd->duel_group > 0) { - duel_showinfo(sd->duel_group, sd); + iDuel->showinfo(sd->duel_group, sd); return true; } @@ -7742,7 +7742,7 @@ ACMD(duel) return true; } - if(!duel_checktime(sd)) { + if(!iDuel->checktime(sd)) { char output[CHAT_SIZE_MAX]; // "Duel: You can take part in duel only one time per %d minutes." sprintf(output, msg_txt(356), battle_config.duel_time_interval); @@ -7756,18 +7756,18 @@ ACMD(duel) clif->message(fd, msg_txt(357)); // "Duel: Invalid value." return true; } - duel_create(sd, maxpl); + iDuel->create(sd, maxpl); } else { struct map_session_data *target_sd; target_sd = iMap->nick2sd((char *)message); if(target_sd != NULL) { unsigned int newduel; - if((newduel = duel_create(sd, 2)) != -1) { + if((newduel = iDuel->create(sd, 2)) != -1) { if(target_sd->duel_group > 0 || target_sd->duel_invite > 0) { clif->message(fd, msg_txt(353)); // "Duel: Player already in duel." return true; } - duel_invite(newduel, sd, target_sd); + iDuel->invite(newduel, sd, target_sd); clif->message(fd, msg_txt(354)); // "Duel: Invitation has been sent." } } else { @@ -7777,7 +7777,7 @@ ACMD(duel) } } } else - duel_create(sd, 0); + iDuel->create(sd, 0); return true; } @@ -7791,14 +7791,14 @@ ACMD(leave) return true; } - duel_leave(sd->duel_group, sd); + iDuel->leave(sd->duel_group, sd); clif->message(fd, msg_txt(359)); // "Duel: You left the duel." return true; } ACMD(accept) { - if(!duel_checktime(sd)) { + if(!iDuel->checktime(sd)) { char output[CHAT_SIZE_MAX]; // "Duel: You can take part in duel only one time per %d minutes." sprintf(output, msg_txt(356), battle_config.duel_time_interval); @@ -7812,14 +7812,14 @@ ACMD(accept) return true; } - if( duel_list[sd->duel_invite].max_players_limit > 0 && duel_list[sd->duel_invite].members_count >= duel_list[sd->duel_invite].max_players_limit ) + if( iDuel->duel_list[sd->duel_invite].max_players_limit > 0 && iDuel->duel_list[sd->duel_invite].members_count >= iDuel->duel_list[sd->duel_invite].max_players_limit ) { // "Duel: Limit of players is reached." clif->message(fd, msg_txt(351)); return true; } - duel_accept(sd->duel_invite, sd); + iDuel->accept(sd->duel_invite, sd); // "Duel: Invitation has been accepted." clif->message(fd, msg_txt(361)); return true; @@ -7833,7 +7833,7 @@ ACMD(reject) return true; } - duel_reject(sd->duel_invite, sd); + iDuel->reject(sd->duel_invite, sd); // "Duel: Invitation has been rejected." clif->message(fd, msg_txt(363)); return true; diff --git a/src/map/duel.c b/src/map/duel.c index 9a8b6d12b..80ef1b530 100644 --- a/src/map/duel.c +++ b/src/map/duel.c @@ -1,184 +1,204 @@ -// Copyright (c) Hercules Dev Team, licensed under GNU GPL. -// See the LICENSE file -// Portions Copyright (c) Athena Dev Teams - -#include "../common/cbasetypes.h" - -#include "atcommand.h" // msg_txt -#include "clif.h" -#include "duel.h" -#include "pc.h" - -#include -#include -#include -#include - -struct duel duel_list[MAX_DUEL]; -int duel_count = 0; - -/*========================================== - * Duel organizing functions [LuzZza] - *------------------------------------------*/ -void duel_savetime(struct map_session_data* sd) -{ - time_t timer; - struct tm *t; - - time(&timer); - t = localtime(&timer); - - pc_setglobalreg(sd, "PC_LAST_DUEL_TIME", t->tm_mday*24*60 + t->tm_hour*60 + t->tm_min); -} - -int duel_checktime(struct map_session_data* sd) -{ - int diff; - time_t timer; - struct tm *t; - - time(&timer); - t = localtime(&timer); - - diff = t->tm_mday*24*60 + t->tm_hour*60 + t->tm_min - pc_readglobalreg(sd, "PC_LAST_DUEL_TIME"); - - return !(diff >= 0 && diff < battle_config.duel_time_interval); -} -static int duel_showinfo_sub(struct map_session_data* sd, va_list va) -{ - struct map_session_data *ssd = va_arg(va, struct map_session_data*); - int *p = va_arg(va, int*); - char output[256]; - - if (sd->duel_group != ssd->duel_group) return 0; - - sprintf(output, " %d. %s", ++(*p), sd->status.name); - clif->disp_onlyself(ssd, output, strlen(output)); - return 1; -} - -void duel_showinfo(const unsigned int did, struct map_session_data* sd) -{ - int p=0; - char output[256]; - - if(duel_list[did].max_players_limit > 0) - sprintf(output, msg_txt(370), //" -- Duels: %d/%d, Members: %d/%d, Max players: %d --" - did, duel_count, - duel_list[did].members_count, - duel_list[did].members_count + duel_list[did].invites_count, - duel_list[did].max_players_limit); - else - sprintf(output, msg_txt(371), //" -- Duels: %d/%d, Members: %d/%d --" - did, duel_count, - duel_list[did].members_count, - duel_list[did].members_count + duel_list[did].invites_count); - - clif->disp_onlyself(sd, output, strlen(output)); - iMap->map_foreachpc(duel_showinfo_sub, sd, &p); -} - -int duel_create(struct map_session_data* sd, const unsigned int maxpl) -{ - int i=1; - char output[256]; - - while(duel_list[i].members_count > 0 && i < MAX_DUEL) i++; - if(i == MAX_DUEL) return 0; - - duel_count++; - sd->duel_group = i; - duel_list[i].members_count++; - duel_list[i].invites_count = 0; - duel_list[i].max_players_limit = maxpl; - - strcpy(output, msg_txt(372)); // " -- Duel has been created (@invite/@leave) --" - clif->disp_onlyself(sd, output, strlen(output)); - - clif->map_property(sd, MAPPROPERTY_FREEPVPZONE); - clif->maptypeproperty2(&sd->bl,SELF); - return i; -} - -void duel_invite(const unsigned int did, struct map_session_data* sd, struct map_session_data* target_sd) -{ - char output[256]; - - // " -- Player %s invites %s to duel --" - sprintf(output, msg_txt(373), sd->status.name, target_sd->status.name); - clif->disp_message(&sd->bl, output, strlen(output), DUEL_WOS); - - target_sd->duel_invite = did; - duel_list[did].invites_count++; - - // "Blue -- Player %s invites you to PVP duel (@accept/@reject) --" - sprintf(output, msg_txt(374), sd->status.name); - clif->broadcast((struct block_list *)target_sd, output, strlen(output)+1, 0x10, SELF); -} - -static int duel_leave_sub(struct map_session_data* sd, va_list va) -{ - int did = va_arg(va, int); - if (sd->duel_invite == did) - sd->duel_invite = 0; - return 0; -} - -void duel_leave(const unsigned int did, struct map_session_data* sd) -{ - char output[256]; - - // " <- Player %s has left duel --" - sprintf(output, msg_txt(375), sd->status.name); - clif->disp_message(&sd->bl, output, strlen(output), DUEL_WOS); - - duel_list[did].members_count--; - - if(duel_list[did].members_count == 0) { - iMap->map_foreachpc(duel_leave_sub, did); - duel_count--; - } - - sd->duel_group = 0; - duel_savetime(sd); - clif->map_property(sd, MAPPROPERTY_NOTHING); - clif->maptypeproperty2(&sd->bl,SELF); -} - -void duel_accept(const unsigned int did, struct map_session_data* sd) -{ - char output[256]; - - duel_list[did].members_count++; - sd->duel_group = sd->duel_invite; - duel_list[did].invites_count--; - sd->duel_invite = 0; - - // " -> Player %s has accepted duel --" - sprintf(output, msg_txt(376), sd->status.name); - clif->disp_message(&sd->bl, output, strlen(output), DUEL_WOS); - - clif->map_property(sd, MAPPROPERTY_FREEPVPZONE); - clif->maptypeproperty2(&sd->bl,SELF); -} - -void duel_reject(const unsigned int did, struct map_session_data* sd) -{ - char output[256]; - - // " -- Player %s has rejected duel --" - sprintf(output, msg_txt(377), sd->status.name); - clif->disp_message(&sd->bl, output, strlen(output), DUEL_WOS); - - duel_list[did].invites_count--; - sd->duel_invite = 0; -} - -void do_final_duel(void) -{ -} - -void do_init_duel(void) -{ - memset(&duel_list[0], 0, sizeof(duel_list)); -} +// Copyright (c) Hercules Dev Team, licensed under GNU GPL. +// See the LICENSE file +// Portions Copyright (c) Athena Dev Teams + +#include "../common/cbasetypes.h" + +#include "atcommand.h" // msg_txt +#include "clif.h" +#include "duel.h" +#include "pc.h" + +#include +#include +#include +#include + +/*========================================== + * Duel organizing functions [LuzZza] + *------------------------------------------*/ +void duel_savetime(struct map_session_data* sd) +{ + time_t timer; + struct tm *t; + + time(&timer); + t = localtime(&timer); + + pc_setglobalreg(sd, "PC_LAST_DUEL_TIME", t->tm_mday*24*60 + t->tm_hour*60 + t->tm_min); +} + +int duel_checktime(struct map_session_data* sd) +{ + int diff; + time_t timer; + struct tm *t; + + time(&timer); + t = localtime(&timer); + + diff = t->tm_mday*24*60 + t->tm_hour*60 + t->tm_min - pc_readglobalreg(sd, "PC_LAST_DUEL_TIME"); + + return !(diff >= 0 && diff < battle_config.duel_time_interval); +} +static int duel_showinfo_sub(struct map_session_data* sd, va_list va) +{ + struct map_session_data *ssd = va_arg(va, struct map_session_data*); + int *p = va_arg(va, int*); + char output[256]; + + if (sd->duel_group != ssd->duel_group) return 0; + + sprintf(output, " %d. %s", ++(*p), sd->status.name); + clif->disp_onlyself(ssd, output, strlen(output)); + return 1; +} + +void duel_showinfo(const unsigned int did, struct map_session_data* sd) +{ + int p=0; + char output[256]; + + if(iDuel->duel_list[did].max_players_limit > 0) + sprintf(output, msg_txt(370), //" -- Duels: %d/%d, Members: %d/%d, Max players: %d --" + did, iDuel->duel_count, + iDuel->duel_list[did].members_count, + iDuel->duel_list[did].members_count + iDuel->duel_list[did].invites_count, + iDuel->duel_list[did].max_players_limit); + else + sprintf(output, msg_txt(371), //" -- Duels: %d/%d, Members: %d/%d --" + did, iDuel->duel_count, + iDuel->duel_list[did].members_count, + iDuel->duel_list[did].members_count + iDuel->duel_list[did].invites_count); + + clif->disp_onlyself(sd, output, strlen(output)); + iMap->map_foreachpc(duel_showinfo_sub, sd, &p); +} + +int duel_create(struct map_session_data* sd, const unsigned int maxpl) +{ + int i=1; + char output[256]; + + while(iDuel->duel_list[i].members_count > 0 && i < MAX_DUEL) i++; + if(i == MAX_DUEL) return 0; + + iDuel->duel_count++; + sd->duel_group = i; + iDuel->duel_list[i].members_count++; + iDuel->duel_list[i].invites_count = 0; + iDuel->duel_list[i].max_players_limit = maxpl; + + strcpy(output, msg_txt(372)); // " -- Duel has been created (@invite/@leave) --" + clif->disp_onlyself(sd, output, strlen(output)); + + clif->map_property(sd, MAPPROPERTY_FREEPVPZONE); + clif->maptypeproperty2(&sd->bl,SELF); + return i; +} + +void duel_invite(const unsigned int did, struct map_session_data* sd, struct map_session_data* target_sd) +{ + char output[256]; + + // " -- Player %s invites %s to duel --" + sprintf(output, msg_txt(373), sd->status.name, target_sd->status.name); + clif->disp_message(&sd->bl, output, strlen(output), DUEL_WOS); + + target_sd->duel_invite = did; + iDuel->duel_list[did].invites_count++; + + // "Blue -- Player %s invites you to PVP duel (@accept/@reject) --" + sprintf(output, msg_txt(374), sd->status.name); + clif->broadcast((struct block_list *)target_sd, output, strlen(output)+1, 0x10, SELF); +} + +static int duel_leave_sub(struct map_session_data* sd, va_list va) +{ + int did = va_arg(va, int); + if (sd->duel_invite == did) + sd->duel_invite = 0; + return 0; +} + +void duel_leave(const unsigned int did, struct map_session_data* sd) +{ + char output[256]; + + // " <- Player %s has left duel --" + sprintf(output, msg_txt(375), sd->status.name); + clif->disp_message(&sd->bl, output, strlen(output), DUEL_WOS); + + iDuel->duel_list[did].members_count--; + + if(iDuel->duel_list[did].members_count == 0) { + iMap->map_foreachpc(duel_leave_sub, did); + iDuel->duel_count--; + } + + sd->duel_group = 0; + duel_savetime(sd); + clif->map_property(sd, MAPPROPERTY_NOTHING); + clif->maptypeproperty2(&sd->bl,SELF); +} + +void duel_accept(const unsigned int did, struct map_session_data* sd) +{ + char output[256]; + + iDuel->duel_list[did].members_count++; + sd->duel_group = sd->duel_invite; + iDuel->duel_list[did].invites_count--; + sd->duel_invite = 0; + + // " -> Player %s has accepted duel --" + sprintf(output, msg_txt(376), sd->status.name); + clif->disp_message(&sd->bl, output, strlen(output), DUEL_WOS); + + clif->map_property(sd, MAPPROPERTY_FREEPVPZONE); + clif->maptypeproperty2(&sd->bl,SELF); +} + +void duel_reject(const unsigned int did, struct map_session_data* sd) +{ + char output[256]; + + // " -- Player %s has rejected duel --" + sprintf(output, msg_txt(377), sd->status.name); + clif->disp_message(&sd->bl, output, strlen(output), DUEL_WOS); + + iDuel->duel_list[did].invites_count--; + sd->duel_invite = 0; +} + +void do_final_duel(void) +{ +} + +void do_init_duel(void) +{ + memset(&iDuel->duel_list[0], 0, sizeof(iDuel->duel_list)); +} + +/*===================================== +* Default Functions : duel.h +* Generated by HerculesInterfaceMaker +* created by Susu +*-------------------------------------*/ +void duel_defaults(void) { + iDuel = &iDuel_s; + /* vars */ + iDuel->duel_count = 0; + /* funcs */ + //Duel functions // [LuzZza] + iDuel->create = duel_create; + iDuel->invite = duel_invite; + iDuel->accept = duel_accept; + iDuel->reject = duel_reject; + iDuel->leave = duel_leave; + iDuel->showinfo = duel_showinfo; + iDuel->checktime = duel_checktime; + + iDuel->do_init_duel = do_init_duel; + iDuel->do_final_duel = do_final_duel; +} diff --git a/src/map/duel.h b/src/map/duel.h index 04d8e4e84..ec9c4bf83 100644 --- a/src/map/duel.h +++ b/src/map/duel.h @@ -1,6 +1,5 @@ // Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder - #ifndef _DUEL_H_ #define _DUEL_H_ @@ -11,19 +10,36 @@ struct duel { }; #define MAX_DUEL 1024 -extern struct duel duel_list[MAX_DUEL]; -extern int duel_count; - -//Duel functions // [LuzZza] -int duel_create(struct map_session_data* sd, const unsigned int maxpl); -void duel_invite(const unsigned int did, struct map_session_data* sd, struct map_session_data* target_sd); -void duel_accept(const unsigned int did, struct map_session_data* sd); -void duel_reject(const unsigned int did, struct map_session_data* sd); -void duel_leave(const unsigned int did, struct map_session_data* sd); -void duel_showinfo(const unsigned int did, struct map_session_data* sd); -int duel_checktime(struct map_session_data* sd); - -void do_init_duel(void); -void do_final_duel(void); + + + +/*===================================== +* Interface : duel.h +* Generated by HerculesInterfaceMaker +* created by Susu +*-------------------------------------*/ +struct duel_interface { + + /* vars */ + struct duel duel_list[MAX_DUEL]; + int duel_count; + + /* funcs */ + //Duel functions // [LuzZza] + int (*create) (struct map_session_data* sd, const unsigned int maxpl); + void (*invite) (const unsigned int did, struct map_session_data* sd, struct map_session_data* target_sd); + void (*accept) (const unsigned int did, struct map_session_data* sd); + void (*reject) (const unsigned int did, struct map_session_data* sd); + void (*leave) (const unsigned int did, struct map_session_data* sd); + void (*showinfo) (const unsigned int did, struct map_session_data* sd); + int (*checktime) (struct map_session_data* sd); + + void (*do_init_duel) (void); + void (*do_final_duel) (void); +} iDuel_s; + +struct duel_interface *iDuel; + +void duel_defaults(void); #endif /* _DUEL_H_ */ diff --git a/src/map/map.c b/src/map/map.c index 589f6f76d..0fb988351 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -4944,7 +4944,7 @@ void do_final(void) iStatus->do_final_status(); do_final_unit(); do_final_battleground(); - do_final_duel(); + iDuel->do_final_duel(); do_final_elemental(); do_final_maps(); vending->final(); @@ -5392,7 +5392,7 @@ int do_init(int argc, char *argv[]) do_init_npc(); do_init_unit(); do_init_battleground(); - do_init_duel(); + iDuel->do_init_duel(); vending->init(); npc_event_do_oninit(); // Init npcs (OnInit) diff --git a/src/map/pc.c b/src/map/pc.c index 11e775dea..ee2e62e92 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -6733,9 +6733,9 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) { // Leave duel if you die [LuzZza] if(battle_config.duel_autoleave_when_die) { if(sd->duel_group > 0) - duel_leave(sd->duel_group, sd); + iDuel->leave(sd->duel_group, sd); if(sd->duel_invite > 0) - duel_reject(sd->duel_invite, sd); + iDuel->reject(sd->duel_invite, sd); } if (sd->npc_id && sd->st && sd->st->state != RUN) diff --git a/src/map/unit.c b/src/map/unit.c index 38606230f..7a1c15838 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -2167,7 +2167,7 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file, sd->pvp_rank = 0; } if(sd->duel_group > 0) - duel_leave(sd->duel_group, sd); + iDuel->leave(sd->duel_group, sd); if(pc_issit(sd)) { pc->setstand(sd); @@ -2343,7 +2343,7 @@ int unit_free(struct block_list *bl, clr_type clrtype) pc->stop_following(sd); if( sd->duel_invite > 0 ) - duel_reject(sd->duel_invite, sd); + iDuel->reject(sd->duel_invite, sd); // Notify friends that this char logged out. [Skotlex] iMap->map_foreachpc(clif->friendslist_toggle_sub, sd->status.account_id, sd->status.char_id, 0); -- cgit v1.2.3-60-g2f50 From 9d5309327da9543f86385549001df7e9a7c98833 Mon Sep 17 00:00:00 2001 From: Susu Date: Mon, 29 Jul 2013 15:28:48 +0200 Subject: Added elemental interface --- src/map/atcommand.c | 4 +- src/map/chrif.c | 4 +- src/map/duel.c | 2 +- src/map/duel.h | 2 +- src/map/elemental.c | 1928 ++++++++++++++++++++++++++------------------------- src/map/elemental.h | 200 +++--- src/map/intif.c | 2 +- src/map/map.c | 14 +- src/map/pc.c | 6 +- src/map/skill.c | 18 +- src/map/status.c | 10 +- src/map/unit.c | 8 +- 12 files changed, 1129 insertions(+), 1069 deletions(-) diff --git a/src/map/atcommand.c b/src/map/atcommand.c index d11fd9a9b..c14b8a26e 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -3600,7 +3600,7 @@ ACMD(reloadmobdb) { homun->reload(); read_mercenarydb(); read_mercenary_skilldb(); - reload_elementaldb(); + elemental->reload_elementaldb(); clif->message(fd, msg_txt(98)); // Monster database has been reloaded. return true; @@ -3614,7 +3614,7 @@ ACMD(reloadskilldb) nullpo_retr(-1, sd); skill->reload(); homun->reload_skill(); - reload_elemental_skilldb(); + elemental->reload_skilldb(); read_mercenary_skilldb(); clif->message(fd, msg_txt(99)); // Skill database has been reloaded. diff --git a/src/map/chrif.c b/src/map/chrif.c index 0fd14cd28..02e9e977c 100644 --- a/src/map/chrif.c +++ b/src/map/chrif.c @@ -314,8 +314,8 @@ int chrif_save(struct map_session_data *sd, int flag) { homun->save(sd->hd); if( sd->md && mercenary_get_lifetime(sd->md) > 0 ) mercenary_save(sd->md); - if( sd->ed && elemental_get_lifetime(sd->ed) > 0 ) - elemental_save(sd->ed); + if( sd->ed && elemental->get_lifetime(sd->ed) > 0 ) + elemental->save(sd->ed); if( sd->save_quest ) intif_quest_save(sd); diff --git a/src/map/duel.c b/src/map/duel.c index 80ef1b530..7a4e61fa0 100644 --- a/src/map/duel.c +++ b/src/map/duel.c @@ -185,7 +185,7 @@ void do_init_duel(void) * Generated by HerculesInterfaceMaker * created by Susu *-------------------------------------*/ -void duel_defaults(void) { +void iDuel_defaults(void) { iDuel = &iDuel_s; /* vars */ iDuel->duel_count = 0; diff --git a/src/map/duel.h b/src/map/duel.h index ec9c4bf83..9fa33833a 100644 --- a/src/map/duel.h +++ b/src/map/duel.h @@ -40,6 +40,6 @@ struct duel_interface { struct duel_interface *iDuel; -void duel_defaults(void); +void iDuel_defaults(void); #endif /* _DUEL_H_ */ diff --git a/src/map/elemental.c b/src/map/elemental.c index 839fa3640..3c212ccaa 100644 --- a/src/map/elemental.c +++ b/src/map/elemental.c @@ -1,944 +1,984 @@ -// Copyright (c) Hercules Dev Team, licensed under GNU GPL. -// See the LICENSE file -// Portions Copyright (c) Athena Dev Teams - -#include "../common/cbasetypes.h" -#include "../common/malloc.h" -#include "../common/socket.h" -#include "../common/timer.h" -#include "../common/nullpo.h" -#include "../common/mmo.h" -#include "../common/showmsg.h" -#include "../common/utils.h" -#include "../common/random.h" -#include "../common/strlib.h" - -#include "log.h" -#include "clif.h" -#include "chrif.h" -#include "intif.h" -#include "itemdb.h" -#include "map.h" -#include "pc.h" -#include "status.h" -#include "skill.h" -#include "mob.h" -#include "pet.h" -#include "battle.h" -#include "party.h" -#include "guild.h" -#include "atcommand.h" -#include "script.h" -#include "npc.h" -#include "trade.h" -#include "unit.h" -#include "elemental.h" - -#include -#include -#include -#include - -struct s_elemental_db elemental_db[MAX_ELEMENTAL_CLASS]; // Elemental Database - -int elemental_search_index(int class_) { - int i; - ARR_FIND(0, MAX_ELEMENTAL_CLASS, i, elemental_db[i].class_ == class_); - return (i == MAX_ELEMENTAL_CLASS)?-1:i; -} - -bool elemental_class(int class_) { - return (bool)(elemental_search_index(class_) > -1); -} - -struct view_data * elemental_get_viewdata(int class_) { - int i = elemental_search_index(class_); - if( i < 0 ) - return 0; - - return &elemental_db[i].vd; -} - -int elemental_create(struct map_session_data *sd, int class_, unsigned int lifetime) { - struct s_elemental ele; - struct s_elemental_db *db; - int i; - - nullpo_retr(1,sd); - - if( (i = elemental_search_index(class_)) < 0 ) - return 0; - - db = &elemental_db[i]; - memset(&ele,0,sizeof(struct s_elemental)); - - ele.char_id = sd->status.char_id; - ele.class_ = class_; - ele.mode = EL_MODE_PASSIVE; // Initial mode - i = db->status.size+1; // summon level - - //[(Caster�s Max HP/ 3 ) + (Caster�s INT x 10 )+ (Caster�s Job Level x 20 )] x [(Elemental Summon Level + 2) / 3] - ele.hp = ele.max_hp = (sd->battle_status.max_hp/3 + sd->battle_status.int_*10 + sd->status.job_level) * ((i + 2) / 3); - //Caster�s Max SP /4 - ele.sp = ele.max_sp = sd->battle_status.max_sp/4; - //Caster�s [ Max SP / (18 / Elemental Summon Skill Level) 1- 100 ] - ele.atk = (sd->battle_status.max_sp / (18 / i) * 1 - 100); - //Caster�s [ Max SP / (18 / Elemental Summon Skill Level) ] - ele.atk2 = sd->battle_status.max_sp / 18; - //Caster�s HIT + (Caster�s Base Level ) - ele.hit = sd->battle_status.hit + sd->status.base_level; - //[Elemental Summon Skill Level x (Caster�s INT / 2 + Caster�s DEX / 4)] - ele.matk = i * (sd->battle_status.int_ / 2 + sd->battle_status.dex / 4); - //150 + [Caster�s DEX / 10] + [Elemental Summon Skill Level x 3 ] - ele.amotion = 150 + sd->battle_status.dex / 10 + i * 3; - //Caster�s DEF + (Caster�s Base Level / (5 � Elemental Summon Skill Level) - ele.def = sd->battle_status.def + sd->status.base_level / (5-i); - //Caster�s MDEF + (Caster�s INT / (5 - Elemental Summon Skill Level) - ele.mdef = sd->battle_status.mdef + sd->battle_status.int_ / (5-i); - //Caster�s FLEE + (Caster�s Base Level / (5 � Elemental Summon Skill Level) - ele.flee = sd->status.base_level / (5-i); - //Caster�s HIT + (Caster�s Base Level ) - ele.hit = sd->battle_status.hit + sd->status.base_level; - - //per individual bonuses - switch(db->class_){ - case 2114: case 2115: - case 2116: //ATK + (Summon Agni Skill Level x 20) / HIT + (Summon Agni Skill Level x 10) - ele.atk += i * 20; - ele.atk2 += i * 20; - ele.hit += i * 10; - break; - case 2117: case 2118: - case 2119: //MDEF + (Summon Aqua Skill Level x 10) / MATK + (Summon Aqua Skill Level x 20) - ele.mdef += i * 10; - ele.matk += i * 20; - break; - case 2120: case 2121: - case 2122: //FLEE + (Summon Ventus Skill Level x 20) / MATK + (Summon Ventus Skill Level x 10) - ele.flee += i * 20; - ele.matk += i * 10; - break; - case 2123: case 2124: - case 2125: //DEF + (Summon Tera Skill Level x 25) / ATK + (Summon Tera Skill Level x 5) - ele.def += i * 25; - ele.atk += i * 5; - ele.atk2 += i * 5; - break; - } - - if( (i=pc->checkskill(sd,SO_EL_SYMPATHY)) > 0 ){ - ele.hp = ele.max_hp = ele.max_hp * 5 * i / 100; - ele.sp = ele.max_sp = ele.max_sp * 5 * i / 100; - ele.atk += 25 * i; - ele.atk2 += 25 * i; - ele.matk += 25 * i; - } - - ele.life_time = lifetime; - - // Request Char Server to create this elemental - intif_elemental_create(&ele); - - return 1; -} - -int elemental_get_lifetime(struct elemental_data *ed) { - const struct TimerData * td; - if( ed == NULL || ed->summon_timer == INVALID_TIMER ) - return 0; - - td = iTimer->get_timer(ed->summon_timer); - return (td != NULL) ? DIFF_TICK(td->tick, iTimer->gettick()) : 0; -} - -int elemental_save(struct elemental_data *ed) { - ed->elemental.mode = ed->battle_status.mode; - ed->elemental.hp = ed->battle_status.hp; - ed->elemental.sp = ed->battle_status.sp; - ed->elemental.max_hp = ed->battle_status.max_hp; - ed->elemental.max_sp = ed->battle_status.max_sp; - ed->elemental.atk = ed->battle_status.rhw.atk; - ed->elemental.atk2 = ed->battle_status.rhw.atk2; - ed->elemental.matk = ed->battle_status.matk_min; - ed->elemental.def = ed->battle_status.def; - ed->elemental.mdef = ed->battle_status.mdef; - ed->elemental.flee = ed->battle_status.flee; - ed->elemental.hit = ed->battle_status.hit; - ed->elemental.life_time = elemental_get_lifetime(ed); - intif_elemental_save(&ed->elemental); - return 1; -} - -static int elemental_summon_end(int tid, unsigned int tick, int id, intptr_t data) { - struct map_session_data *sd; - struct elemental_data *ed; - - if( (sd = iMap->id2sd(id)) == NULL ) - return 1; - if( (ed = sd->ed) == NULL ) - return 1; - - if( ed->summon_timer != tid ) { - ShowError("elemental_summon_end %d != %d.\n", ed->summon_timer, tid); - return 0; - } - - ed->summon_timer = INVALID_TIMER; - elemental_delete(ed, 0); // Elemental's summon time is over. - - return 0; -} - -void elemental_summon_stop(struct elemental_data *ed) { - nullpo_retv(ed); - if( ed->summon_timer != INVALID_TIMER ) - iTimer->delete_timer(ed->summon_timer, elemental_summon_end); - ed->summon_timer = INVALID_TIMER; -} - -int elemental_delete(struct elemental_data *ed, int reply) { - struct map_session_data *sd; - nullpo_ret(ed); - - sd = ed->master; - ed->elemental.life_time = 0; - - elemental_clean_effect(ed); - elemental_summon_stop(ed); - - if( !sd ) - return unit_free(&ed->bl, 0); - - sd->ed = NULL; - sd->status.ele_id = 0; - - return unit_remove_map(&ed->bl, 0); -} - -void elemental_summon_init(struct elemental_data *ed) { - if( ed->summon_timer == INVALID_TIMER ) - ed->summon_timer = iTimer->add_timer(iTimer->gettick() + ed->elemental.life_time, elemental_summon_end, ed->master->bl.id, 0); - - ed->regen.state.block = 0; -} - -int elemental_data_received(struct s_elemental *ele, bool flag) { - struct map_session_data *sd; - struct elemental_data *ed; - struct s_elemental_db *db; - int i = elemental_search_index(ele->class_); - - if( (sd = iMap->charid2sd(ele->char_id)) == NULL ) - return 0; - - if( !flag || i < 0 ) { // Not created - loaded - DB info - sd->status.ele_id = 0; - return 0; - } - - db = &elemental_db[i]; - if( !sd->ed ) { // Initialize it after first summon. - sd->ed = ed = (struct elemental_data*)aCalloc(1,sizeof(struct elemental_data)); - ed->bl.type = BL_ELEM; - ed->bl.id = npc_get_new_npc_id(); - ed->master = sd; - ed->db = db; - memcpy(&ed->elemental, ele, sizeof(struct s_elemental)); - iStatus->set_viewdata(&ed->bl, ed->elemental.class_); - ed->vd->head_mid = 10; // Why? - iStatus->change_init(&ed->bl); - unit_dataset(&ed->bl); - ed->ud.dir = sd->ud.dir; - - ed->bl.m = sd->bl.m; - ed->bl.x = sd->bl.x; - ed->bl.y = sd->bl.y; - unit_calc_pos(&ed->bl, sd->bl.x, sd->bl.y, sd->ud.dir); - ed->bl.x = ed->ud.to_x; - ed->bl.y = ed->ud.to_y; - - iMap->addiddb(&ed->bl); - status_calc_elemental(ed,1); - ed->last_spdrain_time = ed->last_thinktime = iTimer->gettick(); - ed->summon_timer = INVALID_TIMER; - elemental_summon_init(ed); - } else { - memcpy(&sd->ed->elemental, ele, sizeof(struct s_elemental)); - ed = sd->ed; - } - - sd->status.ele_id = ele->elemental_id; - - if( ed->bl.prev == NULL && sd->bl.prev != NULL ) { - iMap->addblock(&ed->bl); - clif->spawn(&ed->bl); - clif->elemental_info(sd); - clif->elemental_updatestatus(sd,SP_HP); - clif->hpmeter_single(sd->fd,ed->bl.id,ed->battle_status.hp,ed->battle_status.max_hp); - clif->elemental_updatestatus(sd,SP_SP); - } - - return 1; -} - -int elemental_clean_single_effect(struct elemental_data *ed, uint16 skill_id) { - struct block_list *bl; - sc_type type = iStatus->skill2sc(skill_id); - - nullpo_ret(ed); - - bl = battle->get_master(&ed->bl); - - if( type ) { - switch( type ) { - // Just remove status change. - case SC_PYROTECHNIC_OPTION: - case SC_HEATER_OPTION: - case SC_TROPIC_OPTION: - case SC_FIRE_CLOAK_OPTION: - case SC_AQUAPLAY_OPTION: - case SC_WATER_SCREEN_OPTION: - case SC_COOLER_OPTION: - case SC_CHILLY_AIR_OPTION: - case SC_GUST_OPTION: - case SC_WIND_STEP_OPTION: - case SC_BLAST_OPTION: - case SC_WATER_DROP_OPTION: - case SC_WIND_CURTAIN_OPTION: - case SC_WILD_STORM_OPTION: - case SC_PETROLOGY_OPTION: - case SC_SOLID_SKIN_OPTION: - case SC_CURSED_SOIL_OPTION: - case SC_STONE_SHIELD_OPTION: - case SC_UPHEAVAL_OPTION: - case SC_CIRCLE_OF_FIRE_OPTION: - case SC_TIDAL_WEAPON_OPTION: - if( bl ) status_change_end(bl,type,INVALID_TIMER); // Master - status_change_end(&ed->bl,type-1,INVALID_TIMER); // Elemental Spirit - break; - case SC_ZEPHYR: - if( bl ) status_change_end(bl,type,INVALID_TIMER); - break; - default: - ShowWarning("Invalid SC=%d in elemental_clean_single_effect\n",type); - break; - } - } - - return 1; -} - -int elemental_clean_effect(struct elemental_data *ed) { - struct map_session_data *sd; - - nullpo_ret(ed); - - // Elemental side - status_change_end(&ed->bl, SC_TROPIC, INVALID_TIMER); - status_change_end(&ed->bl, SC_HEATER, INVALID_TIMER); - status_change_end(&ed->bl, SC_AQUAPLAY, INVALID_TIMER); - status_change_end(&ed->bl, SC_COOLER, INVALID_TIMER); - status_change_end(&ed->bl, SC_CHILLY_AIR, INVALID_TIMER); - status_change_end(&ed->bl, SC_PYROTECHNIC, INVALID_TIMER); - status_change_end(&ed->bl, SC_FIRE_CLOAK, INVALID_TIMER); - status_change_end(&ed->bl, SC_WATER_DROP, INVALID_TIMER); - status_change_end(&ed->bl, SC_WATER_SCREEN, INVALID_TIMER); - status_change_end(&ed->bl, SC_GUST, INVALID_TIMER); - status_change_end(&ed->bl, SC_WIND_STEP, INVALID_TIMER); - status_change_end(&ed->bl, SC_BLAST, INVALID_TIMER); - status_change_end(&ed->bl, SC_WIND_CURTAIN, INVALID_TIMER); - status_change_end(&ed->bl, SC_WILD_STORM, INVALID_TIMER); - status_change_end(&ed->bl, SC_PETROLOGY, INVALID_TIMER); - status_change_end(&ed->bl, SC_SOLID_SKIN, INVALID_TIMER); - status_change_end(&ed->bl, SC_CURSED_SOIL, INVALID_TIMER); - status_change_end(&ed->bl, SC_STONE_SHIELD, INVALID_TIMER); - status_change_end(&ed->bl, SC_UPHEAVAL, INVALID_TIMER); - status_change_end(&ed->bl, SC_CIRCLE_OF_FIRE, INVALID_TIMER); - status_change_end(&ed->bl, SC_TIDAL_WEAPON, INVALID_TIMER); - - if( (sd = ed->master) == NULL ) - return 0; - - // Master side - status_change_end(&sd->bl, SC_TROPIC_OPTION, INVALID_TIMER); - status_change_end(&sd->bl, SC_HEATER_OPTION, INVALID_TIMER); - status_change_end(&sd->bl, SC_AQUAPLAY_OPTION, INVALID_TIMER); - status_change_end(&sd->bl, SC_COOLER_OPTION, INVALID_TIMER); - status_change_end(&sd->bl, SC_CHILLY_AIR_OPTION, INVALID_TIMER); - status_change_end(&sd->bl, SC_PYROTECHNIC_OPTION, INVALID_TIMER); - status_change_end(&sd->bl, SC_FIRE_CLOAK_OPTION, INVALID_TIMER); - status_change_end(&sd->bl, SC_WATER_DROP_OPTION, INVALID_TIMER); - status_change_end(&sd->bl, SC_WATER_SCREEN_OPTION, INVALID_TIMER); - status_change_end(&sd->bl, SC_GUST_OPTION, INVALID_TIMER); - status_change_end(&sd->bl, SC_WIND_STEP_OPTION, INVALID_TIMER); - status_change_end(&sd->bl, SC_BLAST_OPTION, INVALID_TIMER); - status_change_end(&sd->bl, SC_WATER_DROP_OPTION, INVALID_TIMER); - status_change_end(&sd->bl, SC_WIND_CURTAIN_OPTION, INVALID_TIMER); - status_change_end(&sd->bl, SC_WILD_STORM_OPTION, INVALID_TIMER); - status_change_end(&sd->bl, SC_ZEPHYR, INVALID_TIMER); - status_change_end(&sd->bl, SC_WIND_STEP_OPTION, INVALID_TIMER); - status_change_end(&sd->bl, SC_PETROLOGY_OPTION, INVALID_TIMER); - status_change_end(&sd->bl, SC_SOLID_SKIN_OPTION, INVALID_TIMER); - status_change_end(&sd->bl, SC_CURSED_SOIL_OPTION, INVALID_TIMER); - status_change_end(&sd->bl, SC_STONE_SHIELD_OPTION, INVALID_TIMER); - status_change_end(&sd->bl, SC_UPHEAVAL_OPTION, INVALID_TIMER); - status_change_end(&sd->bl, SC_CIRCLE_OF_FIRE_OPTION, INVALID_TIMER); - status_change_end(&sd->bl, SC_TIDAL_WEAPON_OPTION, INVALID_TIMER); - - return 1; -} - -int elemental_action(struct elemental_data *ed, struct block_list *bl, unsigned int tick) { - struct skill_condition req; - uint16 skill_id, skill_lv; - int i; - - nullpo_ret(ed); - nullpo_ret(bl); - - if( !ed->master ) - return 0; - - if( ed->target_id ) - elemental_unlocktarget(ed); // Remove previous target. - - ARR_FIND(0, MAX_ELESKILLTREE, i, ed->db->skill[i].id && (ed->db->skill[i].mode&EL_SKILLMODE_AGGRESSIVE)); - if( i == MAX_ELESKILLTREE ) - return 0; - - skill_id = ed->db->skill[i].id; - skill_lv = ed->db->skill[i].lv; - - if( elemental_skillnotok(skill_id, ed) ) - return 0; - - if( ed->ud.skilltimer != INVALID_TIMER ) - return 0; - else if( DIFF_TICK(tick, ed->ud.canact_tick) < 0 ) - return 0; - - ed->target_id = ed->ud.skilltarget = bl->id; // Set new target - ed->last_thinktime = tick; - - // Not in skill range. - if( !battle->check_range(&ed->bl,bl,skill->get_range(skill_id,skill_lv)) ) { - // Try to walk to the target. - if( !unit_walktobl(&ed->bl, bl, skill->get_range(skill_id,skill_lv), 2) ) - elemental_unlocktarget(ed); - else { - // Walking, waiting to be in range. Client don't handle it, then we must handle it here. - int walk_dist = distance_bl(&ed->bl,bl) - skill->get_range(skill_id,skill_lv); - ed->ud.skill_id = skill_id; - ed->ud.skill_lv = skill_lv; - - if( skill->get_inf(skill_id) & INF_GROUND_SKILL ) - ed->ud.skilltimer = iTimer->add_timer( tick+iStatus->get_speed(&ed->bl)*walk_dist, skill->castend_pos, ed->bl.id, 0 ); - else - ed->ud.skilltimer = iTimer->add_timer( tick+iStatus->get_speed(&ed->bl)*walk_dist, skill->castend_id, ed->bl.id, 0 ); - } - return 1; - - } - - req = elemental_skill_get_requirements(skill_id, skill_lv); - - if(req.hp || req.sp){ - struct map_session_data *sd = BL_CAST(BL_PC, battle->get_master(&ed->bl)); - if( sd ){ - if( sd->skill_id_old != SO_EL_ACTION && //regardless of remaining HP/SP it can be cast - (status_get_hp(&ed->bl) < req.hp || status_get_sp(&ed->bl) < req.sp) ) - return 1; - else - status_zap(&ed->bl, req.hp, req.sp); - } - } - - //Otherwise, just cast the skill. - if( skill->get_inf(skill_id) & INF_GROUND_SKILL ) - unit_skilluse_pos(&ed->bl, bl->x, bl->y, skill_id, skill_lv); - else - unit_skilluse_id(&ed->bl, bl->id, skill_id, skill_lv); - - // Reset target. - ed->target_id = 0; - - return 1; -} - -/*=============================================================== - * Action that elemental perform after changing mode. - * Activates one of the skills of the new mode. - *-------------------------------------------------------------*/ -int elemental_change_mode_ack(struct elemental_data *ed, int mode) { - struct block_list *bl = &ed->master->bl; - uint16 skill_id, skill_lv; - int i; - - nullpo_ret(ed); - - if( !bl ) - return 0; - - // Select a skill. - ARR_FIND(0, MAX_ELESKILLTREE, i, ed->db->skill[i].id && (ed->db->skill[i].mode&mode)); - if( i == MAX_ELESKILLTREE ) - return 0; - - skill_id = ed->db->skill[i].id; - skill_lv = ed->db->skill[i].lv; - - if( elemental_skillnotok(skill_id, ed) ) - return 0; - - if( ed->ud.skilltimer != INVALID_TIMER ) - return 0; - else if( DIFF_TICK(iTimer->gettick(), ed->ud.canact_tick) < 0 ) - return 0; - - ed->target_id = bl->id; // Set new target - ed->last_thinktime = iTimer->gettick(); - - if( skill->get_inf(skill_id) & INF_GROUND_SKILL ) - unit_skilluse_pos(&ed->bl, bl->x, bl->y, skill_id, skill_lv); - else - unit_skilluse_id(&ed->bl,bl->id,skill_id,skill_lv); - - ed->target_id = 0; // Reset target after casting the skill to avoid continious attack. - - return 1; -} - -/*=============================================================== - * Change elemental mode. - *-------------------------------------------------------------*/ -int elemental_change_mode(struct elemental_data *ed, int mode) { - nullpo_ret(ed); - - // Remove target - elemental_unlocktarget(ed); - - // Removes the effects of the previous mode. - if(ed->elemental.mode != mode ) elemental_clean_effect(ed); - - ed->battle_status.mode = ed->elemental.mode = mode; - - // Normalize elemental mode to elemental skill mode. - if( mode == EL_MODE_AGGRESSIVE ) mode = EL_SKILLMODE_AGGRESSIVE; // Aggressive spirit mode -> Aggressive spirit skill. - else if( mode == EL_MODE_ASSIST ) mode = EL_SKILLMODE_ASSIST; // Assist spirit mode -> Assist spirit skill. - else mode = EL_SKILLMODE_PASIVE; // Passive spirit mode -> Passive spirit skill. - - // Use a skill inmediately after every change mode. - if( mode != EL_SKILLMODE_AGGRESSIVE ) - elemental_change_mode_ack(ed,mode); - return 1; -} - -void elemental_heal(struct elemental_data *ed, int hp, int sp) { - if( hp ) - clif->elemental_updatestatus(ed->master, SP_HP); - if( sp ) - clif->elemental_updatestatus(ed->master, SP_SP); -} - -int elemental_dead(struct elemental_data *ed) { - elemental_delete(ed, 1); - return 0; -} - -int elemental_unlocktarget(struct elemental_data *ed) { - nullpo_ret(ed); - - ed->target_id = 0; - elemental_stop_attack(ed); - elemental_stop_walking(ed,1); - return 0; -} - -int elemental_skillnotok(uint16 skill_id, struct elemental_data *ed) { - int idx = skill->get_index(skill_id); - nullpo_retr(1,ed); - - if (idx == 0) - return 1; // invalid skill id - - return skill->not_ok(skill_id, ed->master); -} - -struct skill_condition elemental_skill_get_requirements(uint16 skill_id, uint16 skill_lv){ - struct skill_condition req; - int idx = skill->get_index(skill_id); - - memset(&req,0,sizeof(req)); - - if( idx == 0 ) // invalid skill id - return req; - - if( skill_lv < 1 || skill_lv > MAX_SKILL_LEVEL ) - return req; - - req.hp = skill_db[idx].hp[skill_lv-1]; - req.sp = skill_db[idx].sp[skill_lv-1]; - - return req; -} - -int elemental_set_target( struct map_session_data *sd, struct block_list *bl ) { - struct elemental_data *ed = sd->ed; - - nullpo_ret(ed); - nullpo_ret(bl); - - if( ed->bl.m != bl->m || !check_distance_bl(&ed->bl, bl, ed->db->range2) ) - return 0; - - if( !iStatus->check_skilluse(&ed->bl, bl, 0, 0) ) - return 0; - - if( ed->target_id == 0 ) - ed->target_id = bl->id; - - return 1; -} - -static int elemental_ai_sub_timer_activesearch(struct block_list *bl, va_list ap) { - struct elemental_data *ed; - struct block_list **target; - int dist; - - nullpo_ret(bl); - - ed = va_arg(ap,struct elemental_data *); - target = va_arg(ap,struct block_list**); - - //If can't seek yet, not an enemy, or you can't attack it, skip. - if( (*target) == bl || !iStatus->check_skilluse(&ed->bl, bl, 0, 0) ) - return 0; - - if( battle->check_target(&ed->bl,bl,BCT_ENEMY) <= 0 ) - return 0; - - switch( bl->type ) { - case BL_PC: - if( !map_flag_vs(ed->bl.m) ) - return 0; - default: - dist = distance_bl(&ed->bl, bl); - if( ((*target) == NULL || !check_distance_bl(&ed->bl, *target, dist)) && battle->check_range(&ed->bl,bl,ed->db->range2) ) { //Pick closest target? - (*target) = bl; - ed->target_id = bl->id; - ed->min_chase = dist + ed->db->range3; - if( ed->min_chase > AREA_SIZE ) - ed->min_chase = AREA_SIZE; - return 1; - } - break; - } - return 0; -} - -static int elemental_ai_sub_timer(struct elemental_data *ed, struct map_session_data *sd, unsigned int tick) { - struct block_list *target = NULL; - int master_dist, view_range, mode; - - nullpo_ret(ed); - nullpo_ret(sd); - - if( ed->bl.prev == NULL || sd == NULL || sd->bl.prev == NULL ) - return 0; - - // Check if caster can sustain the summoned elemental - if( DIFF_TICK(tick,ed->last_spdrain_time) >= 10000 ){// Drain SP every 10 seconds - int sp = 5; - - switch(ed->vd->class_){ - case 2115: case 2118: - case 2121: case 2124: - sp = 8; - break; - case 2116: case 2119: - case 2122: case 2125: - sp = 11; - break; - } - - if( status_get_sp(&sd->bl) < sp ){ // Can't sustain delete it. - elemental_delete(sd->ed,0); - return 0; - } - - status_zap(&sd->bl,0,sp); - ed->last_spdrain_time = tick; - } - - if( DIFF_TICK(tick,ed->last_thinktime) < MIN_ELETHINKTIME ) - return 0; - - ed->last_thinktime = tick; - - if( ed->ud.skilltimer != INVALID_TIMER ) - return 0; - - if( ed->ud.walktimer != INVALID_TIMER && ed->ud.walkpath.path_pos <= 2 ) - return 0; //No thinking when you just started to walk. - - if(ed->ud.walkpath.path_pos < ed->ud.walkpath.path_len && ed->ud.target == sd->bl.id) - return 0; //No thinking until be near the master. - - if( ed->sc.count && ed->sc.data[SC_BLIND] ) - view_range = 3; - else - view_range = ed->db->range2; - - mode = status_get_mode(&ed->bl); - - master_dist = distance_bl(&sd->bl, &ed->bl); - if( master_dist > AREA_SIZE ) { // Master out of vision range. - elemental_unlocktarget(ed); - unit_warp(&ed->bl,sd->bl.m,sd->bl.x,sd->bl.y,CLR_TELEPORT); - clif->elemental_updatestatus(sd,SP_HP); - clif->elemental_updatestatus(sd,SP_SP); - return 0; - } else if( master_dist > MAX_ELEDISTANCE ) { // Master too far, chase. - short x = sd->bl.x, y = sd->bl.y; - if( ed->target_id ) - elemental_unlocktarget(ed); - if( ed->ud.walktimer != INVALID_TIMER && ed->ud.target == sd->bl.id ) - return 0; //Already walking to him - if( DIFF_TICK(tick, ed->ud.canmove_tick) < 0 ) - return 0; //Can't move yet. - if( iMap->search_freecell(&ed->bl, sd->bl.m, &x, &y, MIN_ELEDISTANCE, MIN_ELEDISTANCE, 1) - && unit_walktoxy(&ed->bl, x, y, 0) ) - return 0; - } - - if( mode == EL_MODE_AGGRESSIVE ) { - target = iMap->id2bl(ed->ud.target); - - if( !target ) - iMap->foreachinrange(elemental_ai_sub_timer_activesearch, &ed->bl, view_range, BL_CHAR, ed, &target, status_get_mode(&ed->bl)); - - if( !target ) { //No targets available. - elemental_unlocktarget(ed); - return 1; - } - - if( battle->check_range(&ed->bl,target,view_range) && rnd()%100 < 2 ) { // 2% chance to cast attack skill. - if( elemental_action(ed,target,tick) ) - return 1; - } - - //Attempt to attack. - //At this point we know the target is attackable, we just gotta check if the range matches. - if( ed->ud.target == target->id && ed->ud.attacktimer != INVALID_TIMER ) //Already locked. - return 1; - - if( battle->check_range(&ed->bl, target, ed->base_status.rhw.range) ) {//Target within range, engage - unit_attack(&ed->bl,target->id,1); - return 1; - } - - //Follow up if possible. - if( !unit_walktobl(&ed->bl, target, ed->base_status.rhw.range, 2) ) - elemental_unlocktarget(ed); - } - - return 0; -} - -static int elemental_ai_sub_foreachclient(struct map_session_data *sd, va_list ap) { - unsigned int tick = va_arg(ap,unsigned int); - if(sd->status.ele_id && sd->ed) - elemental_ai_sub_timer(sd->ed,sd,tick); - - return 0; -} - -static int elemental_ai_timer(int tid, unsigned int tick, int id, intptr_t data) { - iMap->map_foreachpc(elemental_ai_sub_foreachclient,tick); - return 0; -} - -int read_elementaldb(void) { - FILE *fp; - char line[1024], *p; - char *str[26]; - int i, j = 0, k = 0, ele; - struct s_elemental_db *db; - struct status_data *status; - - sprintf(line, "%s/%s", iMap->db_path, "elemental_db.txt"); - memset(elemental_db,0,sizeof(elemental_db)); - - fp = fopen(line, "r"); - if( !fp ) { - ShowError("read_elementaldb : can't read elemental_db.txt\n"); - return -1; - } - - while( fgets(line, sizeof(line), fp) && j < MAX_ELEMENTAL_CLASS ) { - k++; - if( line[0] == '/' && line[1] == '/' ) - continue; - - if( line[0] == '\0' || line[0] == '\n' || line[0] == '\r') - continue; - - i = 0; - p = strtok(line, ","); - while( p != NULL && i < 26 ) { - str[i++] = p; - p = strtok(NULL, ","); - } - if( i < 26 ) { - ShowError("read_elementaldb : Incorrect number of columns at elemental_db.txt line %d.\n", k); - continue; - } - - db = &elemental_db[j]; - db->class_ = atoi(str[0]); - safestrncpy(db->sprite, str[1], NAME_LENGTH); - safestrncpy(db->name, str[2], NAME_LENGTH); - db->lv = atoi(str[3]); - - status = &db->status; - db->vd.class_ = db->class_; - - status->max_hp = atoi(str[4]); - status->max_sp = atoi(str[5]); - status->rhw.range = atoi(str[6]); - status->rhw.atk = atoi(str[7]); - status->rhw.atk2 = atoi(str[8]); - status->def = atoi(str[9]); - status->mdef = atoi(str[10]); - status->str = atoi(str[11]); - status->agi = atoi(str[12]); - status->vit = atoi(str[13]); - status->int_ = atoi(str[14]); - status->dex = atoi(str[15]); - status->luk = atoi(str[16]); - db->range2 = atoi(str[17]); - db->range3 = atoi(str[18]); - status->size = atoi(str[19]); - status->race = atoi(str[20]); - - ele = atoi(str[21]); - status->def_ele = ele%10; - status->ele_lv = ele/20; - if( status->def_ele >= ELE_MAX ) { - ShowWarning("Elemental %d has invalid element type %d (max element is %d)\n", db->class_, status->def_ele, ELE_MAX - 1); - status->def_ele = ELE_NEUTRAL; - } - if( status->ele_lv < 1 || status->ele_lv > 4 ) { - ShowWarning("Elemental %d has invalid element level %d (max is 4)\n", db->class_, status->ele_lv); - status->ele_lv = 1; - } - - status->aspd_rate = 1000; - status->speed = atoi(str[22]); - status->adelay = atoi(str[23]); - status->amotion = atoi(str[24]); - status->dmotion = atoi(str[25]); - - j++; - } - - fclose(fp); - ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' elementals in '"CL_WHITE"db/elemental_db.txt"CL_RESET"'.\n",j); - - return 0; -} - -int read_elemental_skilldb(void) { - FILE *fp; - char line[1024], *p; - char *str[4]; - struct s_elemental_db *db; - int i, j = 0, k = 0, class_; - uint16 skill_id, skill_lv; - int skillmode; - - sprintf(line, "%s/%s", iMap->db_path, "elemental_skill_db.txt"); - fp = fopen(line, "r"); - if( !fp ) { - ShowError("read_elemental_skilldb : can't read elemental_skill_db.txt\n"); - return -1; - } - - while( fgets(line, sizeof(line), fp) ) { - k++; - if( line[0] == '/' && line[1] == '/' ) - continue; - - if( line[0] == '\0' || line[0] == '\n' || line[0] == '\r') - continue; - - i = 0; - p = strtok(line, ","); - while( p != NULL && i < 4 ) { - str[i++] = p; - p = strtok(NULL, ","); - } - if( i < 4 ) { - ShowError("read_elemental_skilldb : Incorrect number of columns at elemental_skill_db.txt line %d.\n", k); - continue; - } - - class_ = atoi(str[0]); - ARR_FIND(0, MAX_ELEMENTAL_CLASS, i, class_ == elemental_db[i].class_); - if( i == MAX_ELEMENTAL_CLASS ) { - ShowError("read_elemental_skilldb : Class not found in elemental_db for skill entry, line %d.\n", k); - continue; - } - - skill_id = atoi(str[1]); - if( skill_id < EL_SKILLBASE || skill_id >= EL_SKILLBASE + MAX_ELEMENTALSKILL ) { - ShowError("read_elemental_skilldb : Skill out of range, line %d.\n", k); - continue; - } - - db = &elemental_db[i]; - skill_lv = atoi(str[2]); - - skillmode = atoi(str[3]); - if( skillmode < EL_SKILLMODE_PASIVE || skillmode > EL_SKILLMODE_AGGRESSIVE ) { - ShowError("read_elemental_skilldb : Skillmode out of range, line %d.\n",k); - continue; - } - ARR_FIND( 0, MAX_ELESKILLTREE, i, db->skill[i].id == 0 || db->skill[i].id == skill_id ); - if( i == MAX_ELESKILLTREE ) { - ShowWarning("Unable to load skill %d into Elemental %d's tree. Maximum number of skills per elemental has been reached.\n", skill_id, class_); - continue; - } - db->skill[i].id = skill_id; - db->skill[i].lv = skill_lv; - db->skill[i].mode = skillmode; - j++; - } - - fclose(fp); - ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"db/elemental_skill_db.txt"CL_RESET"'.\n",j); - return 0; -} - -void reload_elementaldb(void) { - read_elementaldb(); - reload_elemental_skilldb(); -} - -void reload_elemental_skilldb(void) { - read_elemental_skilldb(); -} - -int do_init_elemental(void) { - read_elementaldb(); - read_elemental_skilldb(); - - iTimer->add_timer_func_list(elemental_ai_timer,"elemental_ai_timer"); - iTimer->add_timer_interval(iTimer->gettick()+MIN_ELETHINKTIME,elemental_ai_timer,0,0,MIN_ELETHINKTIME); - - return 0; -} - -void do_final_elemental(void) { - return; -} +// Copyright (c) Hercules Dev Team, licensed under GNU GPL. +// See the LICENSE file +// Portions Copyright (c) Athena Dev Teams + +#include "../common/cbasetypes.h" +#include "../common/malloc.h" +#include "../common/socket.h" +#include "../common/timer.h" +#include "../common/nullpo.h" +#include "../common/mmo.h" +#include "../common/showmsg.h" +#include "../common/utils.h" +#include "../common/random.h" +#include "../common/strlib.h" + +#include "log.h" +#include "clif.h" +#include "chrif.h" +#include "intif.h" +#include "itemdb.h" +#include "map.h" +#include "pc.h" +#include "status.h" +#include "skill.h" +#include "mob.h" +#include "pet.h" +#include "battle.h" +#include "party.h" +#include "guild.h" +#include "atcommand.h" +#include "script.h" +#include "npc.h" +#include "trade.h" +#include "unit.h" +#include "elemental.h" + +#include +#include +#include +#include + +int elemental_search_index(int class_) { + int i; + ARR_FIND(0, MAX_ELEMENTAL_CLASS, i, elemental->elemental_db[i].class_ == class_); + return (i == MAX_ELEMENTAL_CLASS)?-1:i; +} + +bool elemental_class(int class_) { + return (bool)(elemental_search_index(class_) > -1); +} + +struct view_data * elemental_get_viewdata(int class_) { + int i = elemental_search_index(class_); + if( i < 0 ) + return 0; + + return &elemental->elemental_db[i].vd; +} + +int elemental_create(struct map_session_data *sd, int class_, unsigned int lifetime) { + struct s_elemental ele; + struct s_elemental_db *db; + int i; + + nullpo_retr(1,sd); + + if( (i = elemental_search_index(class_)) < 0 ) + return 0; + + db = &elemental->elemental_db[i]; + memset(&ele,0,sizeof(struct s_elemental)); + + ele.char_id = sd->status.char_id; + ele.class_ = class_; + ele.mode = EL_MODE_PASSIVE; // Initial mode + i = db->status.size+1; // summon level + + //[(Caster�s Max HP/ 3 ) + (Caster�s INT x 10 )+ (Caster�s Job Level x 20 )] x [(Elemental Summon Level + 2) / 3] + ele.hp = ele.max_hp = (sd->battle_status.max_hp/3 + sd->battle_status.int_*10 + sd->status.job_level) * ((i + 2) / 3); + //Caster�s Max SP /4 + ele.sp = ele.max_sp = sd->battle_status.max_sp/4; + //Caster�s [ Max SP / (18 / Elemental Summon Skill Level) 1- 100 ] + ele.atk = (sd->battle_status.max_sp / (18 / i) * 1 - 100); + //Caster�s [ Max SP / (18 / Elemental Summon Skill Level) ] + ele.atk2 = sd->battle_status.max_sp / 18; + //Caster�s HIT + (Caster�s Base Level ) + ele.hit = sd->battle_status.hit + sd->status.base_level; + //[Elemental Summon Skill Level x (Caster�s INT / 2 + Caster�s DEX / 4)] + ele.matk = i * (sd->battle_status.int_ / 2 + sd->battle_status.dex / 4); + //150 + [Caster�s DEX / 10] + [Elemental Summon Skill Level x 3 ] + ele.amotion = 150 + sd->battle_status.dex / 10 + i * 3; + //Caster�s DEF + (Caster�s Base Level / (5 � Elemental Summon Skill Level) + ele.def = sd->battle_status.def + sd->status.base_level / (5-i); + //Caster�s MDEF + (Caster�s INT / (5 - Elemental Summon Skill Level) + ele.mdef = sd->battle_status.mdef + sd->battle_status.int_ / (5-i); + //Caster�s FLEE + (Caster�s Base Level / (5 � Elemental Summon Skill Level) + ele.flee = sd->status.base_level / (5-i); + //Caster�s HIT + (Caster�s Base Level ) + ele.hit = sd->battle_status.hit + sd->status.base_level; + + //per individual bonuses + switch(db->class_){ + case 2114: case 2115: + case 2116: //ATK + (Summon Agni Skill Level x 20) / HIT + (Summon Agni Skill Level x 10) + ele.atk += i * 20; + ele.atk2 += i * 20; + ele.hit += i * 10; + break; + case 2117: case 2118: + case 2119: //MDEF + (Summon Aqua Skill Level x 10) / MATK + (Summon Aqua Skill Level x 20) + ele.mdef += i * 10; + ele.matk += i * 20; + break; + case 2120: case 2121: + case 2122: //FLEE + (Summon Ventus Skill Level x 20) / MATK + (Summon Ventus Skill Level x 10) + ele.flee += i * 20; + ele.matk += i * 10; + break; + case 2123: case 2124: + case 2125: //DEF + (Summon Tera Skill Level x 25) / ATK + (Summon Tera Skill Level x 5) + ele.def += i * 25; + ele.atk += i * 5; + ele.atk2 += i * 5; + break; + } + + if( (i=pc->checkskill(sd,SO_EL_SYMPATHY)) > 0 ){ + ele.hp = ele.max_hp = ele.max_hp * 5 * i / 100; + ele.sp = ele.max_sp = ele.max_sp * 5 * i / 100; + ele.atk += 25 * i; + ele.atk2 += 25 * i; + ele.matk += 25 * i; + } + + ele.life_time = lifetime; + + // Request Char Server to create this elemental + intif_elemental_create(&ele); + + return 1; +} + +int elemental_get_lifetime(struct elemental_data *ed) { + const struct TimerData * td; + if( ed == NULL || ed->summon_timer == INVALID_TIMER ) + return 0; + + td = iTimer->get_timer(ed->summon_timer); + return (td != NULL) ? DIFF_TICK(td->tick, iTimer->gettick()) : 0; +} + +int elemental_save(struct elemental_data *ed) { + ed->elemental.mode = ed->battle_status.mode; + ed->elemental.hp = ed->battle_status.hp; + ed->elemental.sp = ed->battle_status.sp; + ed->elemental.max_hp = ed->battle_status.max_hp; + ed->elemental.max_sp = ed->battle_status.max_sp; + ed->elemental.atk = ed->battle_status.rhw.atk; + ed->elemental.atk2 = ed->battle_status.rhw.atk2; + ed->elemental.matk = ed->battle_status.matk_min; + ed->elemental.def = ed->battle_status.def; + ed->elemental.mdef = ed->battle_status.mdef; + ed->elemental.flee = ed->battle_status.flee; + ed->elemental.hit = ed->battle_status.hit; + ed->elemental.life_time = elemental->get_lifetime(ed); + intif_elemental_save(&ed->elemental); + return 1; +} + +static int elemental_summon_end(int tid, unsigned int tick, int id, intptr_t data) { + struct map_session_data *sd; + struct elemental_data *ed; + + if( (sd = iMap->id2sd(id)) == NULL ) + return 1; + if( (ed = sd->ed) == NULL ) + return 1; + + if( ed->summon_timer != tid ) { + ShowError("elemental_summon_end %d != %d.\n", ed->summon_timer, tid); + return 0; + } + + ed->summon_timer = INVALID_TIMER; + elemental->delete(ed, 0); // Elemental's summon time is over. + + return 0; +} + +void elemental_summon_stop(struct elemental_data *ed) { + nullpo_retv(ed); + if( ed->summon_timer != INVALID_TIMER ) + iTimer->delete_timer(ed->summon_timer, elemental_summon_end); + ed->summon_timer = INVALID_TIMER; +} + +int elemental_delete(struct elemental_data *ed, int reply) { + struct map_session_data *sd; + nullpo_ret(ed); + + sd = ed->master; + ed->elemental.life_time = 0; + + elemental->clean_effect(ed); + elemental->summon_stop(ed); + + if( !sd ) + return unit_free(&ed->bl, 0); + + sd->ed = NULL; + sd->status.ele_id = 0; + + return unit_remove_map(&ed->bl, 0); +} + +void elemental_summon_init(struct elemental_data *ed) { + if( ed->summon_timer == INVALID_TIMER ) + ed->summon_timer = iTimer->add_timer(iTimer->gettick() + ed->elemental.life_time, elemental_summon_end, ed->master->bl.id, 0); + + ed->regen.state.block = 0; +} + +int elemental_data_received(struct s_elemental *ele, bool flag) { + struct map_session_data *sd; + struct elemental_data *ed; + struct s_elemental_db *db; + int i = elemental_search_index(ele->class_); + + if( (sd = iMap->charid2sd(ele->char_id)) == NULL ) + return 0; + + if( !flag || i < 0 ) { // Not created - loaded - DB info + sd->status.ele_id = 0; + return 0; + } + + db = &elemental->elemental_db[i]; + if( !sd->ed ) { // Initialize it after first summon. + sd->ed = ed = (struct elemental_data*)aCalloc(1,sizeof(struct elemental_data)); + ed->bl.type = BL_ELEM; + ed->bl.id = npc_get_new_npc_id(); + ed->master = sd; + ed->db = db; + memcpy(&ed->elemental, ele, sizeof(struct s_elemental)); + iStatus->set_viewdata(&ed->bl, ed->elemental.class_); + ed->vd->head_mid = 10; // Why? + iStatus->change_init(&ed->bl); + unit_dataset(&ed->bl); + ed->ud.dir = sd->ud.dir; + + ed->bl.m = sd->bl.m; + ed->bl.x = sd->bl.x; + ed->bl.y = sd->bl.y; + unit_calc_pos(&ed->bl, sd->bl.x, sd->bl.y, sd->ud.dir); + ed->bl.x = ed->ud.to_x; + ed->bl.y = ed->ud.to_y; + + iMap->addiddb(&ed->bl); + status_calc_elemental(ed,1); + ed->last_spdrain_time = ed->last_thinktime = iTimer->gettick(); + ed->summon_timer = INVALID_TIMER; + elemental_summon_init(ed); + } else { + memcpy(&sd->ed->elemental, ele, sizeof(struct s_elemental)); + ed = sd->ed; + } + + sd->status.ele_id = ele->elemental_id; + + if( ed->bl.prev == NULL && sd->bl.prev != NULL ) { + iMap->addblock(&ed->bl); + clif->spawn(&ed->bl); + clif->elemental_info(sd); + clif->elemental_updatestatus(sd,SP_HP); + clif->hpmeter_single(sd->fd,ed->bl.id,ed->battle_status.hp,ed->battle_status.max_hp); + clif->elemental_updatestatus(sd,SP_SP); + } + + return 1; +} + +int elemental_clean_single_effect(struct elemental_data *ed, uint16 skill_id) { + struct block_list *bl; + sc_type type = iStatus->skill2sc(skill_id); + + nullpo_ret(ed); + + bl = battle->get_master(&ed->bl); + + if( type ) { + switch( type ) { + // Just remove status change. + case SC_PYROTECHNIC_OPTION: + case SC_HEATER_OPTION: + case SC_TROPIC_OPTION: + case SC_FIRE_CLOAK_OPTION: + case SC_AQUAPLAY_OPTION: + case SC_WATER_SCREEN_OPTION: + case SC_COOLER_OPTION: + case SC_CHILLY_AIR_OPTION: + case SC_GUST_OPTION: + case SC_WIND_STEP_OPTION: + case SC_BLAST_OPTION: + case SC_WATER_DROP_OPTION: + case SC_WIND_CURTAIN_OPTION: + case SC_WILD_STORM_OPTION: + case SC_PETROLOGY_OPTION: + case SC_SOLID_SKIN_OPTION: + case SC_CURSED_SOIL_OPTION: + case SC_STONE_SHIELD_OPTION: + case SC_UPHEAVAL_OPTION: + case SC_CIRCLE_OF_FIRE_OPTION: + case SC_TIDAL_WEAPON_OPTION: + if( bl ) status_change_end(bl,type,INVALID_TIMER); // Master + status_change_end(&ed->bl,type-1,INVALID_TIMER); // Elemental Spirit + break; + case SC_ZEPHYR: + if( bl ) status_change_end(bl,type,INVALID_TIMER); + break; + default: + ShowWarning("Invalid SC=%d in elemental_clean_single_effect\n",type); + break; + } + } + + return 1; +} + +int elemental_clean_effect(struct elemental_data *ed) { + struct map_session_data *sd; + + nullpo_ret(ed); + + // Elemental side + status_change_end(&ed->bl, SC_TROPIC, INVALID_TIMER); + status_change_end(&ed->bl, SC_HEATER, INVALID_TIMER); + status_change_end(&ed->bl, SC_AQUAPLAY, INVALID_TIMER); + status_change_end(&ed->bl, SC_COOLER, INVALID_TIMER); + status_change_end(&ed->bl, SC_CHILLY_AIR, INVALID_TIMER); + status_change_end(&ed->bl, SC_PYROTECHNIC, INVALID_TIMER); + status_change_end(&ed->bl, SC_FIRE_CLOAK, INVALID_TIMER); + status_change_end(&ed->bl, SC_WATER_DROP, INVALID_TIMER); + status_change_end(&ed->bl, SC_WATER_SCREEN, INVALID_TIMER); + status_change_end(&ed->bl, SC_GUST, INVALID_TIMER); + status_change_end(&ed->bl, SC_WIND_STEP, INVALID_TIMER); + status_change_end(&ed->bl, SC_BLAST, INVALID_TIMER); + status_change_end(&ed->bl, SC_WIND_CURTAIN, INVALID_TIMER); + status_change_end(&ed->bl, SC_WILD_STORM, INVALID_TIMER); + status_change_end(&ed->bl, SC_PETROLOGY, INVALID_TIMER); + status_change_end(&ed->bl, SC_SOLID_SKIN, INVALID_TIMER); + status_change_end(&ed->bl, SC_CURSED_SOIL, INVALID_TIMER); + status_change_end(&ed->bl, SC_STONE_SHIELD, INVALID_TIMER); + status_change_end(&ed->bl, SC_UPHEAVAL, INVALID_TIMER); + status_change_end(&ed->bl, SC_CIRCLE_OF_FIRE, INVALID_TIMER); + status_change_end(&ed->bl, SC_TIDAL_WEAPON, INVALID_TIMER); + + if( (sd = ed->master) == NULL ) + return 0; + + // Master side + status_change_end(&sd->bl, SC_TROPIC_OPTION, INVALID_TIMER); + status_change_end(&sd->bl, SC_HEATER_OPTION, INVALID_TIMER); + status_change_end(&sd->bl, SC_AQUAPLAY_OPTION, INVALID_TIMER); + status_change_end(&sd->bl, SC_COOLER_OPTION, INVALID_TIMER); + status_change_end(&sd->bl, SC_CHILLY_AIR_OPTION, INVALID_TIMER); + status_change_end(&sd->bl, SC_PYROTECHNIC_OPTION, INVALID_TIMER); + status_change_end(&sd->bl, SC_FIRE_CLOAK_OPTION, INVALID_TIMER); + status_change_end(&sd->bl, SC_WATER_DROP_OPTION, INVALID_TIMER); + status_change_end(&sd->bl, SC_WATER_SCREEN_OPTION, INVALID_TIMER); + status_change_end(&sd->bl, SC_GUST_OPTION, INVALID_TIMER); + status_change_end(&sd->bl, SC_WIND_STEP_OPTION, INVALID_TIMER); + status_change_end(&sd->bl, SC_BLAST_OPTION, INVALID_TIMER); + status_change_end(&sd->bl, SC_WATER_DROP_OPTION, INVALID_TIMER); + status_change_end(&sd->bl, SC_WIND_CURTAIN_OPTION, INVALID_TIMER); + status_change_end(&sd->bl, SC_WILD_STORM_OPTION, INVALID_TIMER); + status_change_end(&sd->bl, SC_ZEPHYR, INVALID_TIMER); + status_change_end(&sd->bl, SC_WIND_STEP_OPTION, INVALID_TIMER); + status_change_end(&sd->bl, SC_PETROLOGY_OPTION, INVALID_TIMER); + status_change_end(&sd->bl, SC_SOLID_SKIN_OPTION, INVALID_TIMER); + status_change_end(&sd->bl, SC_CURSED_SOIL_OPTION, INVALID_TIMER); + status_change_end(&sd->bl, SC_STONE_SHIELD_OPTION, INVALID_TIMER); + status_change_end(&sd->bl, SC_UPHEAVAL_OPTION, INVALID_TIMER); + status_change_end(&sd->bl, SC_CIRCLE_OF_FIRE_OPTION, INVALID_TIMER); + status_change_end(&sd->bl, SC_TIDAL_WEAPON_OPTION, INVALID_TIMER); + + return 1; +} + +int elemental_action(struct elemental_data *ed, struct block_list *bl, unsigned int tick) { + struct skill_condition req; + uint16 skill_id, skill_lv; + int i; + + nullpo_ret(ed); + nullpo_ret(bl); + + if( !ed->master ) + return 0; + + if( ed->target_id ) + elemental->unlocktarget(ed); // Remove previous target. + + ARR_FIND(0, MAX_ELESKILLTREE, i, ed->db->skill[i].id && (ed->db->skill[i].mode&EL_SKILLMODE_AGGRESSIVE)); + if( i == MAX_ELESKILLTREE ) + return 0; + + skill_id = ed->db->skill[i].id; + skill_lv = ed->db->skill[i].lv; + + if( elemental->skillnotok(skill_id, ed) ) + return 0; + + if( ed->ud.skilltimer != INVALID_TIMER ) + return 0; + else if( DIFF_TICK(tick, ed->ud.canact_tick) < 0 ) + return 0; + + ed->target_id = ed->ud.skilltarget = bl->id; // Set new target + ed->last_thinktime = tick; + + // Not in skill range. + if( !battle->check_range(&ed->bl,bl,skill->get_range(skill_id,skill_lv)) ) { + // Try to walk to the target. + if( !unit_walktobl(&ed->bl, bl, skill->get_range(skill_id,skill_lv), 2) ) + elemental->unlocktarget(ed); + else { + // Walking, waiting to be in range. Client don't handle it, then we must handle it here. + int walk_dist = distance_bl(&ed->bl,bl) - skill->get_range(skill_id,skill_lv); + ed->ud.skill_id = skill_id; + ed->ud.skill_lv = skill_lv; + + if( skill->get_inf(skill_id) & INF_GROUND_SKILL ) + ed->ud.skilltimer = iTimer->add_timer( tick+iStatus->get_speed(&ed->bl)*walk_dist, skill->castend_pos, ed->bl.id, 0 ); + else + ed->ud.skilltimer = iTimer->add_timer( tick+iStatus->get_speed(&ed->bl)*walk_dist, skill->castend_id, ed->bl.id, 0 ); + } + return 1; + + } + + req = elemental->skill_get_requirements(skill_id, skill_lv); + + if(req.hp || req.sp){ + struct map_session_data *sd = BL_CAST(BL_PC, battle->get_master(&ed->bl)); + if( sd ){ + if( sd->skill_id_old != SO_EL_ACTION && //regardless of remaining HP/SP it can be cast + (status_get_hp(&ed->bl) < req.hp || status_get_sp(&ed->bl) < req.sp) ) + return 1; + else + status_zap(&ed->bl, req.hp, req.sp); + } + } + + //Otherwise, just cast the skill. + if( skill->get_inf(skill_id) & INF_GROUND_SKILL ) + unit_skilluse_pos(&ed->bl, bl->x, bl->y, skill_id, skill_lv); + else + unit_skilluse_id(&ed->bl, bl->id, skill_id, skill_lv); + + // Reset target. + ed->target_id = 0; + + return 1; +} + +/*=============================================================== + * Action that elemental perform after changing mode. + * Activates one of the skills of the new mode. + *-------------------------------------------------------------*/ +int elemental_change_mode_ack(struct elemental_data *ed, int mode) { + struct block_list *bl = &ed->master->bl; + uint16 skill_id, skill_lv; + int i; + + nullpo_ret(ed); + + if( !bl ) + return 0; + + // Select a skill. + ARR_FIND(0, MAX_ELESKILLTREE, i, ed->db->skill[i].id && (ed->db->skill[i].mode&mode)); + if( i == MAX_ELESKILLTREE ) + return 0; + + skill_id = ed->db->skill[i].id; + skill_lv = ed->db->skill[i].lv; + + if( elemental->skillnotok(skill_id, ed) ) + return 0; + + if( ed->ud.skilltimer != INVALID_TIMER ) + return 0; + else if( DIFF_TICK(iTimer->gettick(), ed->ud.canact_tick) < 0 ) + return 0; + + ed->target_id = bl->id; // Set new target + ed->last_thinktime = iTimer->gettick(); + + if( skill->get_inf(skill_id) & INF_GROUND_SKILL ) + unit_skilluse_pos(&ed->bl, bl->x, bl->y, skill_id, skill_lv); + else + unit_skilluse_id(&ed->bl,bl->id,skill_id,skill_lv); + + ed->target_id = 0; // Reset target after casting the skill to avoid continious attack. + + return 1; +} + +/*=============================================================== + * Change elemental mode. + *-------------------------------------------------------------*/ +int elemental_change_mode(struct elemental_data *ed, int mode) { + nullpo_ret(ed); + + // Remove target + elemental->unlocktarget(ed); + + // Removes the effects of the previous mode. + if(ed->elemental.mode != mode ) elemental->clean_effect(ed); + + ed->battle_status.mode = ed->elemental.mode = mode; + + // Normalize elemental mode to elemental skill mode. + if( mode == EL_MODE_AGGRESSIVE ) mode = EL_SKILLMODE_AGGRESSIVE; // Aggressive spirit mode -> Aggressive spirit skill. + else if( mode == EL_MODE_ASSIST ) mode = EL_SKILLMODE_ASSIST; // Assist spirit mode -> Assist spirit skill. + else mode = EL_SKILLMODE_PASIVE; // Passive spirit mode -> Passive spirit skill. + + // Use a skill inmediately after every change mode. + if( mode != EL_SKILLMODE_AGGRESSIVE ) + elemental->change_mode_ack(ed,mode); + return 1; +} + +void elemental_heal(struct elemental_data *ed, int hp, int sp) { + if( hp ) + clif->elemental_updatestatus(ed->master, SP_HP); + if( sp ) + clif->elemental_updatestatus(ed->master, SP_SP); +} + +int elemental_dead(struct elemental_data *ed) { + elemental->delete(ed, 1); + return 0; +} + +int elemental_unlocktarget(struct elemental_data *ed) { + nullpo_ret(ed); + + ed->target_id = 0; + elemental_stop_attack(ed); + elemental_stop_walking(ed,1); + return 0; +} + +int elemental_skillnotok(uint16 skill_id, struct elemental_data *ed) { + int idx = skill->get_index(skill_id); + nullpo_retr(1,ed); + + if (idx == 0) + return 1; // invalid skill id + + return skill->not_ok(skill_id, ed->master); +} + +struct skill_condition elemental_skill_get_requirements(uint16 skill_id, uint16 skill_lv){ + struct skill_condition req; + int idx = skill->get_index(skill_id); + + memset(&req,0,sizeof(req)); + + if( idx == 0 ) // invalid skill id + return req; + + if( skill_lv < 1 || skill_lv > MAX_SKILL_LEVEL ) + return req; + + req.hp = skill_db[idx].hp[skill_lv-1]; + req.sp = skill_db[idx].sp[skill_lv-1]; + + return req; +} + +int elemental_set_target( struct map_session_data *sd, struct block_list *bl ) { + struct elemental_data *ed = sd->ed; + + nullpo_ret(ed); + nullpo_ret(bl); + + if( ed->bl.m != bl->m || !check_distance_bl(&ed->bl, bl, ed->db->range2) ) + return 0; + + if( !iStatus->check_skilluse(&ed->bl, bl, 0, 0) ) + return 0; + + if( ed->target_id == 0 ) + ed->target_id = bl->id; + + return 1; +} + +static int elemental_ai_sub_timer_activesearch(struct block_list *bl, va_list ap) { + struct elemental_data *ed; + struct block_list **target; + int dist; + + nullpo_ret(bl); + + ed = va_arg(ap,struct elemental_data *); + target = va_arg(ap,struct block_list**); + + //If can't seek yet, not an enemy, or you can't attack it, skip. + if( (*target) == bl || !iStatus->check_skilluse(&ed->bl, bl, 0, 0) ) + return 0; + + if( battle->check_target(&ed->bl,bl,BCT_ENEMY) <= 0 ) + return 0; + + switch( bl->type ) { + case BL_PC: + if( !map_flag_vs(ed->bl.m) ) + return 0; + default: + dist = distance_bl(&ed->bl, bl); + if( ((*target) == NULL || !check_distance_bl(&ed->bl, *target, dist)) && battle->check_range(&ed->bl,bl,ed->db->range2) ) { //Pick closest target? + (*target) = bl; + ed->target_id = bl->id; + ed->min_chase = dist + ed->db->range3; + if( ed->min_chase > AREA_SIZE ) + ed->min_chase = AREA_SIZE; + return 1; + } + break; + } + return 0; +} + +static int elemental_ai_sub_timer(struct elemental_data *ed, struct map_session_data *sd, unsigned int tick) { + struct block_list *target = NULL; + int master_dist, view_range, mode; + + nullpo_ret(ed); + nullpo_ret(sd); + + if( ed->bl.prev == NULL || sd == NULL || sd->bl.prev == NULL ) + return 0; + + // Check if caster can sustain the summoned elemental + if( DIFF_TICK(tick,ed->last_spdrain_time) >= 10000 ){// Drain SP every 10 seconds + int sp = 5; + + switch(ed->vd->class_){ + case 2115: case 2118: + case 2121: case 2124: + sp = 8; + break; + case 2116: case 2119: + case 2122: case 2125: + sp = 11; + break; + } + + if( status_get_sp(&sd->bl) < sp ){ // Can't sustain delete it. + elemental->delete(sd->ed,0); + return 0; + } + + status_zap(&sd->bl,0,sp); + ed->last_spdrain_time = tick; + } + + if( DIFF_TICK(tick,ed->last_thinktime) < MIN_ELETHINKTIME ) + return 0; + + ed->last_thinktime = tick; + + if( ed->ud.skilltimer != INVALID_TIMER ) + return 0; + + if( ed->ud.walktimer != INVALID_TIMER && ed->ud.walkpath.path_pos <= 2 ) + return 0; //No thinking when you just started to walk. + + if(ed->ud.walkpath.path_pos < ed->ud.walkpath.path_len && ed->ud.target == sd->bl.id) + return 0; //No thinking until be near the master. + + if( ed->sc.count && ed->sc.data[SC_BLIND] ) + view_range = 3; + else + view_range = ed->db->range2; + + mode = status_get_mode(&ed->bl); + + master_dist = distance_bl(&sd->bl, &ed->bl); + if( master_dist > AREA_SIZE ) { // Master out of vision range. + elemental->unlocktarget(ed); + unit_warp(&ed->bl,sd->bl.m,sd->bl.x,sd->bl.y,CLR_TELEPORT); + clif->elemental_updatestatus(sd,SP_HP); + clif->elemental_updatestatus(sd,SP_SP); + return 0; + } else if( master_dist > MAX_ELEDISTANCE ) { // Master too far, chase. + short x = sd->bl.x, y = sd->bl.y; + if( ed->target_id ) + elemental->unlocktarget(ed); + if( ed->ud.walktimer != INVALID_TIMER && ed->ud.target == sd->bl.id ) + return 0; //Already walking to him + if( DIFF_TICK(tick, ed->ud.canmove_tick) < 0 ) + return 0; //Can't move yet. + if( iMap->search_freecell(&ed->bl, sd->bl.m, &x, &y, MIN_ELEDISTANCE, MIN_ELEDISTANCE, 1) + && unit_walktoxy(&ed->bl, x, y, 0) ) + return 0; + } + + if( mode == EL_MODE_AGGRESSIVE ) { + target = iMap->id2bl(ed->ud.target); + + if( !target ) + iMap->foreachinrange(elemental_ai_sub_timer_activesearch, &ed->bl, view_range, BL_CHAR, ed, &target, status_get_mode(&ed->bl)); + + if( !target ) { //No targets available. + elemental->unlocktarget(ed); + return 1; + } + + if( battle->check_range(&ed->bl,target,view_range) && rnd()%100 < 2 ) { // 2% chance to cast attack skill. + if( elemental->action(ed,target,tick) ) + return 1; + } + + //Attempt to attack. + //At this point we know the target is attackable, we just gotta check if the range matches. + if( ed->ud.target == target->id && ed->ud.attacktimer != INVALID_TIMER ) //Already locked. + return 1; + + if( battle->check_range(&ed->bl, target, ed->base_status.rhw.range) ) {//Target within range, engage + unit_attack(&ed->bl,target->id,1); + return 1; + } + + //Follow up if possible. + if( !unit_walktobl(&ed->bl, target, ed->base_status.rhw.range, 2) ) + elemental->unlocktarget(ed); + } + + return 0; +} + +static int elemental_ai_sub_foreachclient(struct map_session_data *sd, va_list ap) { + unsigned int tick = va_arg(ap,unsigned int); + if(sd->status.ele_id && sd->ed) + elemental_ai_sub_timer(sd->ed,sd,tick); + + return 0; +} + +static int elemental_ai_timer(int tid, unsigned int tick, int id, intptr_t data) { + iMap->map_foreachpc(elemental_ai_sub_foreachclient,tick); + return 0; +} + +int read_elementaldb(void) { + FILE *fp; + char line[1024], *p; + char *str[26]; + int i, j = 0, k = 0, ele; + struct s_elemental_db *db; + struct status_data *status; + + sprintf(line, "%s/%s", iMap->db_path, "elemental_db.txt"); + memset(elemental->elemental_db,0,sizeof(elemental->elemental_db)); + + fp = fopen(line, "r"); + if( !fp ) { + ShowError("read_elementaldb : can't read elemental_db.txt\n"); + return -1; + } + + while( fgets(line, sizeof(line), fp) && j < MAX_ELEMENTAL_CLASS ) { + k++; + if( line[0] == '/' && line[1] == '/' ) + continue; + + if( line[0] == '\0' || line[0] == '\n' || line[0] == '\r') + continue; + + i = 0; + p = strtok(line, ","); + while( p != NULL && i < 26 ) { + str[i++] = p; + p = strtok(NULL, ","); + } + if( i < 26 ) { + ShowError("read_elementaldb : Incorrect number of columns at elemental_db.txt line %d.\n", k); + continue; + } + + db = &elemental->elemental_db[j]; + db->class_ = atoi(str[0]); + safestrncpy(db->sprite, str[1], NAME_LENGTH); + safestrncpy(db->name, str[2], NAME_LENGTH); + db->lv = atoi(str[3]); + + status = &db->status; + db->vd.class_ = db->class_; + + status->max_hp = atoi(str[4]); + status->max_sp = atoi(str[5]); + status->rhw.range = atoi(str[6]); + status->rhw.atk = atoi(str[7]); + status->rhw.atk2 = atoi(str[8]); + status->def = atoi(str[9]); + status->mdef = atoi(str[10]); + status->str = atoi(str[11]); + status->agi = atoi(str[12]); + status->vit = atoi(str[13]); + status->int_ = atoi(str[14]); + status->dex = atoi(str[15]); + status->luk = atoi(str[16]); + db->range2 = atoi(str[17]); + db->range3 = atoi(str[18]); + status->size = atoi(str[19]); + status->race = atoi(str[20]); + + ele = atoi(str[21]); + status->def_ele = ele%10; + status->ele_lv = ele/20; + if( status->def_ele >= ELE_MAX ) { + ShowWarning("Elemental %d has invalid element type %d (max element is %d)\n", db->class_, status->def_ele, ELE_MAX - 1); + status->def_ele = ELE_NEUTRAL; + } + if( status->ele_lv < 1 || status->ele_lv > 4 ) { + ShowWarning("Elemental %d has invalid element level %d (max is 4)\n", db->class_, status->ele_lv); + status->ele_lv = 1; + } + + status->aspd_rate = 1000; + status->speed = atoi(str[22]); + status->adelay = atoi(str[23]); + status->amotion = atoi(str[24]); + status->dmotion = atoi(str[25]); + + j++; + } + + fclose(fp); + ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' elementals in '"CL_WHITE"db/elemental_db.txt"CL_RESET"'.\n",j); + + return 0; +} + +int read_elemental_skilldb(void) { + FILE *fp; + char line[1024], *p; + char *str[4]; + struct s_elemental_db *db; + int i, j = 0, k = 0, class_; + uint16 skill_id, skill_lv; + int skillmode; + + sprintf(line, "%s/%s", iMap->db_path, "elemental_skill_db.txt"); + fp = fopen(line, "r"); + if( !fp ) { + ShowError("read_elemental_skilldb : can't read elemental_skill_db.txt\n"); + return -1; + } + + while( fgets(line, sizeof(line), fp) ) { + k++; + if( line[0] == '/' && line[1] == '/' ) + continue; + + if( line[0] == '\0' || line[0] == '\n' || line[0] == '\r') + continue; + + i = 0; + p = strtok(line, ","); + while( p != NULL && i < 4 ) { + str[i++] = p; + p = strtok(NULL, ","); + } + if( i < 4 ) { + ShowError("read_elemental_skilldb : Incorrect number of columns at elemental_skill_db.txt line %d.\n", k); + continue; + } + + class_ = atoi(str[0]); + ARR_FIND(0, MAX_ELEMENTAL_CLASS, i, class_ == elemental->elemental_db[i].class_); + if( i == MAX_ELEMENTAL_CLASS ) { + ShowError("read_elemental_skilldb : Class not found in elemental_db for skill entry, line %d.\n", k); + continue; + } + + skill_id = atoi(str[1]); + if( skill_id < EL_SKILLBASE || skill_id >= EL_SKILLBASE + MAX_ELEMENTALSKILL ) { + ShowError("read_elemental_skilldb : Skill out of range, line %d.\n", k); + continue; + } + + db = &elemental->elemental_db[i]; + skill_lv = atoi(str[2]); + + skillmode = atoi(str[3]); + if( skillmode < EL_SKILLMODE_PASIVE || skillmode > EL_SKILLMODE_AGGRESSIVE ) { + ShowError("read_elemental_skilldb : Skillmode out of range, line %d.\n",k); + continue; + } + ARR_FIND( 0, MAX_ELESKILLTREE, i, db->skill[i].id == 0 || db->skill[i].id == skill_id ); + if( i == MAX_ELESKILLTREE ) { + ShowWarning("Unable to load skill %d into Elemental %d's tree. Maximum number of skills per elemental has been reached.\n", skill_id, class_); + continue; + } + db->skill[i].id = skill_id; + db->skill[i].lv = skill_lv; + db->skill[i].mode = skillmode; + j++; + } + + fclose(fp); + ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"db/elemental_skill_db.txt"CL_RESET"'.\n",j); + return 0; +} + +void reload_elementaldb(void) { + read_elementaldb(); + elemental->reload_skilldb(); +} + +void reload_elemental_skilldb(void) { + elemental->read_skilldb(); +} + +int do_init_elemental(void) { + read_elementaldb(); + elemental->read_skilldb(); + + iTimer->add_timer_func_list(elemental_ai_timer,"elemental_ai_timer"); + iTimer->add_timer_interval(iTimer->gettick()+MIN_ELETHINKTIME,elemental_ai_timer,0,0,MIN_ELETHINKTIME); + + return 0; +} + +void do_final_elemental(void) { + return; +} + +/*===================================== +* Default Functions : elemental.h +* Generated by HerculesInterfaceMaker +* created by Susu +*-------------------------------------*/ +void elemental_defaults(void) { + elemental = &elemental_s; + /* funcs */ + + elemental->class = elemental_class; + elemental->get_viewdata = elemental_get_viewdata; + + elemental->create = elemental_create; + elemental->data_received = elemental_data_received; + elemental->save = elemental_save; + + elemental->change_mode_ack = elemental_change_mode_ack; + elemental->change_mode = elemental_change_mode; + + elemental->heal = elemental_heal; + elemental->dead = elemental_dead; + + elemental->delete = elemental_delete; + elemental->summon_stop = elemental_summon_stop; + + elemental->get_lifetime = elemental_get_lifetime; + + elemental->unlocktarget = elemental_unlocktarget; + elemental->skillnotok = elemental_skillnotok; + elemental->set_target = elemental_set_target; + elemental->clean_single_effect = elemental_clean_single_effect; + elemental->clean_effect = elemental_clean_effect; + elemental->action = elemental_action; + elemental->skill_get_requirements = elemental_skill_get_requirements; + + elemental->read_skilldb = read_elemental_skilldb; + elemental->reload_elementaldb = reload_elementaldb; + elemental->reload_skilldb = reload_elemental_skilldb; + elemental->do_init_elemental = do_init_elemental; + elemental->do_final_elemental = do_final_elemental; +} diff --git a/src/map/elemental.h b/src/map/elemental.h index f941f3dfd..96d2ed89f 100644 --- a/src/map/elemental.h +++ b/src/map/elemental.h @@ -1,94 +1,106 @@ -// Copyright (c) Athena Dev Teams - Licensed under GNU GPL -// For more information, see LICENCE in the main folder - -#ifndef _ELEMENTAL_H_ -#define _ELEMENTAL_H_ - -#include "status.h" // struct status_data, struct status_change -#include "unit.h" // struct unit_data - -#define MIN_ELETHINKTIME 100 -#define MIN_ELEDISTANCE 2 -#define MAX_ELEDISTANCE 5 - -#define EL_MODE_AGGRESSIVE (MD_CANMOVE|MD_AGGRESSIVE|MD_CANATTACK) -#define EL_MODE_ASSIST (MD_CANMOVE|MD_ASSIST) -#define EL_MODE_PASSIVE MD_CANMOVE - -#define EL_SKILLMODE_PASIVE 0x1 -#define EL_SKILLMODE_ASSIST 0x2 -#define EL_SKILLMODE_AGGRESSIVE 0x4 - -struct elemental_skill { - unsigned short id, lv; - short mode; -}; - -struct s_elemental_db { - int class_; - char sprite[NAME_LENGTH], name[NAME_LENGTH]; - unsigned short lv; - short range2, range3; - struct status_data status; - struct view_data vd; - struct elemental_skill skill[MAX_ELESKILLTREE]; -}; - -extern struct s_elemental_db elemental_db[MAX_ELEMENTAL_CLASS]; - -struct elemental_data { - struct block_list bl; - struct unit_data ud; - struct view_data *vd; - struct status_data base_status, battle_status; - struct status_change sc; - struct regen_data regen; - - struct s_elemental_db *db; - struct s_elemental elemental; - - struct map_session_data *master; - int summon_timer; - int skill_timer; - - unsigned last_thinktime, last_linktime, last_spdrain_time; - short min_chase; - int target_id, attacked_id; -}; - -bool elemental_class(int class_); -struct view_data * elemental_get_viewdata(int class_); - -int elemental_create(struct map_session_data *sd, int class_, unsigned int lifetime); -int elemental_data_received(struct s_elemental *ele, bool flag); -int elemental_save(struct elemental_data *ed); - -int elemental_change_mode_ack(struct elemental_data *ed, int mode); -int elemental_change_mode(struct elemental_data *ed, int mode); - -void elemental_heal(struct elemental_data *ed, int hp, int sp); -int elemental_dead(struct elemental_data *ed); - -int elemental_delete(struct elemental_data *ed, int reply); -void elemental_summon_stop(struct elemental_data *ed); - -int elemental_get_lifetime(struct elemental_data *ed); - -int elemental_unlocktarget(struct elemental_data *ed); -int elemental_skillnotok(uint16 skill_id, struct elemental_data *ed); -int elemental_set_target( struct map_session_data *sd, struct block_list *bl ); -int elemental_clean_single_effect(struct elemental_data *ed, uint16 skill_id); -int elemental_clean_effect(struct elemental_data *ed); -int elemental_action(struct elemental_data *ed, struct block_list *bl, unsigned int tick); -struct skill_condition elemental_skill_get_requirements(uint16 skill_id, uint16 skill_lv); - -#define elemental_stop_walking(ed, type) unit_stop_walking(&(ed)->bl, type) -#define elemental_stop_attack(ed) unit_stop_attack(&(ed)->bl) - -int read_elemental_skilldb(void); -void reload_elementaldb(void); -void reload_elemental_skilldb(void); -int do_init_elemental(void); -void do_final_elemental(void); - -#endif /* _ELEMENTAL_H_ */ +// Copyright (c) Athena Dev Teams - Licensed under GNU GPL +// For more information, see LICENCE in the main folder +#ifndef _ELEMENTAL_H_ +#define _ELEMENTAL_H_ +#include "status.h" // struct status_data, struct status_change +#include "unit.h" // struct unit_data +#define MIN_ELETHINKTIME 100 +#define MIN_ELEDISTANCE 2 +#define MAX_ELEDISTANCE 5 +#define EL_MODE_AGGRESSIVE (MD_CANMOVE|MD_AGGRESSIVE|MD_CANATTACK) +#define EL_MODE_ASSIST (MD_CANMOVE|MD_ASSIST) +#define EL_MODE_PASSIVE MD_CANMOVE +#define EL_SKILLMODE_PASIVE 0x1 +#define EL_SKILLMODE_ASSIST 0x2 +#define EL_SKILLMODE_AGGRESSIVE 0x4 +struct elemental_skill { + unsigned short id, lv; + short mode; +}; +struct s_elemental_db { + int class_; + char sprite[NAME_LENGTH], name[NAME_LENGTH]; + unsigned short lv; + short range2, range3; + struct status_data status; + struct view_data vd; + struct elemental_skill skill[MAX_ELESKILLTREE]; +}; +struct elemental_data { + struct block_list bl; + struct unit_data ud; + struct view_data *vd; + struct status_data base_status, battle_status; + struct status_change sc; + struct regen_data regen; + + struct s_elemental_db *db; + struct s_elemental elemental; + + struct map_session_data *master; + int summon_timer; + int skill_timer; + + unsigned last_thinktime, last_linktime, last_spdrain_time; + short min_chase; + int target_id, attacked_id; +}; + + + + + + + + +#define elemental_stop_walking(ed, type) unit_stop_walking(&(ed)->bl, type) +#define elemental_stop_attack(ed) unit_stop_attack(&(ed)->bl) + + +/*===================================== +* Interface : elemental.h +* Generated by HerculesInterfaceMaker +* created by Susu +*-------------------------------------*/ +struct elemental_interface { + /* vars */ + struct s_elemental_db elemental_db[MAX_ELEMENTAL_CLASS]; // Elemental Database + /* funcs */ + bool (*class) (int class_); + struct view_data * (*get_viewdata) (int class_); + + int (*create) (struct map_session_data *sd, int class_, unsigned int lifetime); + int (*data_received) (struct s_elemental *ele, bool flag); + int (*save) (struct elemental_data *ed); + + int (*change_mode_ack) (struct elemental_data *ed, int mode); + int (*change_mode) (struct elemental_data *ed, int mode); + + void (*heal) (struct elemental_data *ed, int hp, int sp); + int (*dead) (struct elemental_data *ed); + + int (*delete) (struct elemental_data *ed, int reply); + void (*summon_stop) (struct elemental_data *ed); + + int (*get_lifetime) (struct elemental_data *ed); + + int (*unlocktarget) (struct elemental_data *ed); + int (*skillnotok) (uint16 skill_id, struct elemental_data *ed); + int (*set_target) (struct map_session_data *sd, struct block_list *bl); + int (*clean_single_effect) (struct elemental_data *ed, uint16 skill_id); + int (*clean_effect) (struct elemental_data *ed); + int (*action) (struct elemental_data *ed, struct block_list *bl, unsigned int tick); + struct skill_condition (*skill_get_requirements) (uint16 skill_id, uint16 skill_lv); + + int (*read_skilldb) (void); + void (*reload_elementaldb) (void); + void (*reload_skilldb) (void); + int (*do_init_elemental) (void); + void (*do_final_elemental) (void); +} elemental_s; + +struct elemental_interface *elemental; + +void elemental_defaults(void); + +#endif /* _ELEMENTAL_H_ */ diff --git a/src/map/intif.c b/src/map/intif.c index 294d79656..f2c5e7e78 100644 --- a/src/map/intif.c +++ b/src/map/intif.c @@ -2055,7 +2055,7 @@ int intif_parse_elemental_received(int fd) return 0; } - elemental_data_received((struct s_elemental*)RFIFOP(fd,5), RFIFOB(fd,4)); + elemental->data_received((struct s_elemental*)RFIFOP(fd,5), RFIFOB(fd,4)); return 0; } diff --git a/src/map/map.c b/src/map/map.c index 0fb988351..5e8102ea0 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -1591,7 +1591,7 @@ int map_quit(struct map_session_data *sd) { if (sd->state.permanent_speed == 1) sd->state.permanent_speed = 0; // Remove lock so speed is set back to normal at login. if( sd->ed ) { - elemental_clean_effect(sd->ed); + elemental->clean_effect(sd->ed); unit_remove_map(&sd->ed->bl,CLR_TELEPORT); } @@ -4945,7 +4945,7 @@ void do_final(void) do_final_unit(); do_final_battleground(); iDuel->do_final_duel(); - do_final_elemental(); + elemental->do_final_elemental(); do_final_maps(); vending->final(); @@ -5155,6 +5155,11 @@ void map_hp_symbols(void) { HPM->share(storage,"storage"); HPM->share(trade,"trade"); HPM->share(iStatus,"iStatus"); + HPM->share(chat, "chat"); + HPM->share(iDuel,"iDuel"); + HPM->share(elemental,"elemental"); + + /* partial */ HPM->share(mapit,"mapit"); /* sql link */ @@ -5191,6 +5196,9 @@ void map_load_defaults(void) { storage_defaults(); trade_defaults(); status_defaults(); + chat_defaults(); + iDuel_defaults(); + elemental_defaults(); } int do_init(int argc, char *argv[]) { @@ -5387,7 +5395,7 @@ int do_init(int argc, char *argv[]) do_init_pet(); homun->init(); do_init_mercenary(); - do_init_elemental(); + elemental->do_init_elemental(); do_init_quest(); do_init_npc(); do_init_unit(); diff --git a/src/map/pc.c b/src/map/pc.c index ee2e62e92..30ef9848c 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -6687,7 +6687,7 @@ void pc_damage(struct map_session_data *sd,struct block_list *src,unsigned int h pet_target_check(sd,src,1); if( sd->status.ele_id > 0 ) - elemental_set_target(sd,src); + elemental->set_target(sd,src); sd->canlog_tick = iTimer->gettick(); } @@ -6728,7 +6728,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) { merc_delete(sd->md, 3); // Your mercenary soldier has ran away. if( sd->ed ) - elemental_delete(sd->ed, 0); + elemental->delete(sd->ed, 0); // Leave duel if you die [LuzZza] if(battle_config.duel_autoleave_when_die) { @@ -7621,7 +7621,7 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper) clif->skillinfoblock(sd); if (sd->ed) - elemental_delete(sd->ed, 0); + elemental->delete(sd->ed, 0); if (sd->state.vending) vending->close(sd); diff --git a/src/map/skill.c b/src/map/skill.c index d2a9b7fbe..0fbd340fa 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -4481,7 +4481,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint clif->skill_nodamage(src,battle->get_master(src),skill_id,skill_lv,1); clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); if( (sc && sc->data[type2]) || (tsc && tsc->data[type]) ) { - elemental_clean_single_effect(ele, skill_id); + elemental->clean_single_effect(ele, skill_id); } if( rnd()%100 < 50 ) skill->attack(skill->get_type(skill_id),src,src,bl,skill_id,skill_lv,tick,flag); @@ -8885,10 +8885,10 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui // Remove previous elemental fisrt. if( sd->ed ) - elemental_delete(sd->ed,0); + elemental->delete(sd->ed,0); // Summoning the new one. - if( !elemental_create(sd,elemental_class,skill->get_time(skill_id,skill_lv)) ) { + if( !elemental->create(sd,elemental_class,skill->get_time(skill_id,skill_lv)) ) { clif->skill_fail(sd,skill_id,0,0); break; } @@ -8903,14 +8903,14 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui if( !sd->ed ) break; if( skill_lv == 4 ) {// At level 4 delete elementals. - elemental_delete(sd->ed, 0); + elemental->delete(sd->ed, 0); break; } switch( skill_lv ) {// Select mode bassed on skill level used. case 2: mode = EL_MODE_ASSIST; break; case 3: mode = EL_MODE_AGGRESSIVE; break; } - if( !elemental_change_mode(sd->ed,mode) ) { + if( !elemental->change_mode(sd->ed,mode) ) { clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); break; } @@ -8923,7 +8923,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui int duration = 3000; if( !sd->ed ) break; sd->skill_id_old = skill_id; - elemental_action(sd->ed, bl, tick); + elemental->action(sd->ed, bl, tick); clif->skill_nodamage(src,bl,skill_id,skill_lv,1); switch(sd->ed->db->class_){ case 2115:case 2124: @@ -8959,7 +8959,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui case SO_ELEMENTAL_SHIELD: if( !sd->ed ) break; - elemental_delete(sd->ed, 0); + elemental->delete(sd->ed, 0); if( sd == NULL || sd->status.party_id == 0 || flag&1 ) skill->unitsetting(src,MG_SAFETYWALL,skill_lv,bl->x,bl->y,0); else if( sd ) @@ -9073,7 +9073,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui struct status_change *sc = iStatus->get_sc(&ele->bl); if( (sc && sc->data[type2]) || (tsc && tsc->data[type]) ) { - elemental_clean_single_effect(ele, skill_id); + elemental->clean_single_effect(ele, skill_id); } else { clif->skill_nodamage(src,src,skill_id,skill_lv,1); clif->skill_damage(src, ( skill_id == EL_GUST || skill_id == EL_BLAST || skill_id == EL_WILD_STORM )?src:bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); @@ -9103,7 +9103,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui clif->skill_nodamage(src,src,skill_id,skill_lv,1); if( (sc && sc->data[type2]) || (tsc && tsc->data[type]) ) { - elemental_clean_single_effect(ele, skill_id); + elemental->clean_single_effect(ele, skill_id); } else { // This not heals at the end. clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); diff --git a/src/map/status.c b/src/map/status.c index a8b61f2d6..48a61cfcb 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -1243,7 +1243,7 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s case BL_MOB: mob_damage((TBL_MOB*)target, src, hp); break; case BL_HOM: homun->damaged((TBL_HOM*)target); break; case BL_MER: mercenary_heal((TBL_MER*)target,hp,sp); break; - case BL_ELEM: elemental_heal((TBL_ELEM*)target,hp,sp); break; + case BL_ELEM: elemental->heal((TBL_ELEM*)target,hp,sp); break; } if( src && target->type == BL_PC && (((TBL_PC*)target)->disguise) > 0 ) {// stop walking when attacked in disguise to prevent walk-delay bug @@ -1268,7 +1268,7 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s case BL_MOB: flag = mob_dead((TBL_MOB*)target, src, flag&4?3:0); break; case BL_HOM: flag = homun->dead((TBL_HOM*)target); break; case BL_MER: flag = mercenary_dead((TBL_MER*)target); break; - case BL_ELEM: flag = elemental_dead((TBL_ELEM*)target); break; + case BL_ELEM: flag = elemental->dead((TBL_ELEM*)target); break; default: //Unhandled case, do nothing to object. flag = 0; break; @@ -1414,7 +1414,7 @@ int status_heal(struct block_list *bl,int hp,int sp, int flag) case BL_MOB: mob_heal((TBL_MOB*)bl,hp); break; case BL_HOM: homun->healed((TBL_HOM*)bl); break; case BL_MER: mercenary_heal((TBL_MER*)bl,hp,sp); break; - case BL_ELEM: elemental_heal((TBL_ELEM*)bl,hp,sp); break; + case BL_ELEM: elemental->heal((TBL_ELEM*)bl,hp,sp); break; } return hp+sp; @@ -6057,8 +6057,8 @@ void status_set_viewdata(struct block_list *bl, int class_) vd = homun->get_viewdata(class_); else if (merc_class(class_)) vd = merc_get_viewdata(class_); - else if (elemental_class(class_)) - vd = elemental_get_viewdata(class_); + else if (elemental->class(class_)) + vd = elemental->get_viewdata(class_); else vd = NULL; diff --git a/src/map/unit.c b/src/map/unit.c index 7a1c15838..8a11363cb 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -2265,7 +2265,7 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file, case BL_ELEM: { struct elemental_data *ed = (struct elemental_data *)bl; ud->canact_tick = ud->canmove_tick; - if( elemental_get_lifetime(ed) <= 0 && !(ed->master && !ed->master->state.active) ) + if( elemental->get_lifetime(ed) <= 0 && !(ed->master && !ed->master->state.active) ) { clif->clearunit_area(bl,clrtype); iMap->delblock(bl); @@ -2548,8 +2548,8 @@ int unit_free(struct block_list *bl, clr_type clrtype) case BL_ELEM: { struct elemental_data *ed = (TBL_ELEM*)bl; struct map_session_data *sd = ed->master; - if( elemental_get_lifetime(ed) > 0 ) - elemental_save(ed); + if( elemental->get_lifetime(ed) > 0 ) + elemental->save(ed); else { intif_elemental_delete(ed->elemental.elemental_id); if( sd ) @@ -2558,7 +2558,7 @@ int unit_free(struct block_list *bl, clr_type clrtype) if( sd ) sd->ed = NULL; - elemental_summon_stop(ed); + elemental->summon_stop(ed); break; } } -- cgit v1.2.3-60-g2f50 From 853489bcb5f2acfce14731b117ddc2b246042883 Mon Sep 17 00:00:00 2001 From: Susu Date: Mon, 29 Jul 2013 15:49:14 +0200 Subject: Added intif interface --- src/map/atcommand.c | 20 +- src/map/chrif.c | 14 +- src/map/clif.c | 30 +- src/map/elemental.c | 4 +- src/map/guild.c | 56 +- src/map/homunculus.c | 10 +- src/map/intif.c | 4610 +++++++++++++++++++++++++------------------------- src/map/intif.h | 240 +-- src/map/map.c | 4 +- src/map/mercenary.c | 4 +- src/map/mob.c | 6 +- src/map/npc.c | 4 +- src/map/party.c | 30 +- src/map/pc.c | 34 +- src/map/pet.c | 12 +- src/map/quest.c | 1 - src/map/script.c | 16 +- src/map/storage.c | 4 +- src/map/trade.c | 6 +- src/map/unit.c | 10 +- 20 files changed, 2612 insertions(+), 2503 deletions(-) diff --git a/src/map/atcommand.c b/src/map/atcommand.c index c14b8a26e..018098928 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -745,7 +745,7 @@ ACMD(save) pc->setsavepoint(sd, sd->mapindex, sd->bl.x, sd->bl.y); if (sd->status.pet_id > 0 && sd->pd) - intif_save_petdata(sd->status.account_id, &sd->pd->pet); + intif->save_petdata(sd->status.account_id, &sd->pd->pet); chrif->save(sd,0); @@ -1048,7 +1048,7 @@ ACMD(kami) if (strstr(command, "l") != NULL) clif->broadcast(&sd->bl, atcmd_output, strlen(atcmd_output) + 1, 0, ALL_SAMEMAP); else - intif_broadcast(atcmd_output, strlen(atcmd_output) + 1, (*(command + 5) == 'b' || *(command + 5) == 'B') ? 0x10 : 0); + intif->broadcast(atcmd_output, strlen(atcmd_output) + 1, (*(command + 5) == 'b' || *(command + 5) == 'B') ? 0x10 : 0); } else { if(!message || !*message || (sscanf(message, "%lx %199[^\n]", &color, atcmd_output) < 2)) { clif->message(fd, msg_txt(981)); // Please enter color and message (usage: @kamic ). @@ -1059,7 +1059,7 @@ ACMD(kami) clif->message(fd, msg_txt(982)); // Invalid color. return false; } - intif_broadcast2(atcmd_output, strlen(atcmd_output) + 1, color, 0x190, 12, 0, 0); + intif->broadcast2(atcmd_output, strlen(atcmd_output) + 1, color, 0x190, 12, 0, 0); } return true; } @@ -2526,7 +2526,7 @@ ACMD(guildlevelup) added_level = 1 - guild_info->guild_lv; if (added_level != 0) { - intif_guild_change_basicinfo(guild_info->guild_id, GBI_GUILDLV, &added_level, sizeof(added_level)); + intif->guild_change_basicinfo(guild_info->guild_id, GBI_GUILDLV, &added_level, sizeof(added_level)); clif->message(fd, msg_txt(179)); // Guild level changed. } else { clif->message(fd, msg_txt(45)); // Guild level change failed. @@ -2563,7 +2563,7 @@ ACMD(makeegg) pet_id = search_petDB_index(id, PET_EGG); if (pet_id >= 0) { sd->catch_target_class = pet_db[pet_id].class_; - intif_create_pet( + intif->create_pet( sd->status.account_id, sd->status.char_id, (short)pet_db[pet_id].class_, (short)mob_db(pet_db[pet_id].class_)->lv, (short)pet_db[pet_id].EggID, 0, (short)pet_db[pet_id].intimate, @@ -2682,7 +2682,7 @@ ACMD(petrename) } pd->pet.rename_flag = 0; - intif_save_petdata(sd->status.account_id, &pd->pet); + intif->save_petdata(sd->status.account_id, &pd->pet); clif->send_petstatus(sd); clif->message(fd, msg_txt(187)); // You can now rename your pet. @@ -4960,7 +4960,7 @@ ACMD(broadcast) } sprintf(atcmd_output, "%s: %s", sd->status.name, message); - intif_broadcast(atcmd_output, strlen(atcmd_output) + 1, 0); + intif->broadcast(atcmd_output, strlen(atcmd_output) + 1, 0); return true; } @@ -7974,7 +7974,7 @@ ACMD(request) } sprintf(atcmd_output, msg_txt(278), message); // (@request): %s - intif_wis_message_to_gm(sd->status.name, PC_PERM_RECEIVE_REQUESTS, atcmd_output); + intif->wis_message_to_gm(sd->status.name, PC_PERM_RECEIVE_REQUESTS, atcmd_output); clif->disp_onlyself(sd, atcmd_output, strlen(atcmd_output)); clif->message(sd->fd,msg_txt(279)); // @request sent. return true; @@ -8335,7 +8335,7 @@ ACMD(delitem) if( sd->inventory_data[idx]->type == IT_PETEGG && sd->status.inventory[idx].card[0] == CARD0_PET ) {// delete pet - intif_delete_petdata(MakeDWord(sd->status.inventory[idx].card[1], sd->status.inventory[idx].card[2])); + intif->delete_petdata(MakeDWord(sd->status.inventory[idx].card[1], sd->status.inventory[idx].card[2])); } pc->delitem(sd, idx, delamount, 0, 0, LOG_TYPE_COMMAND); @@ -8508,7 +8508,7 @@ ACMD(accinfo) { //remove const type safestrncpy(query, message, NAME_LENGTH); - intif_request_accinfo( sd->fd, sd->bl.id, pc->get_group_level(sd), query ); + intif->request_accinfo( sd->fd, sd->bl.id, pc->get_group_level(sd), query ); return true; } diff --git a/src/map/chrif.c b/src/map/chrif.c index 02e9e977c..d1ee8b5b1 100644 --- a/src/map/chrif.c +++ b/src/map/chrif.c @@ -293,11 +293,11 @@ int chrif_save(struct map_session_data *sd, int flag) { //Saving of registry values. if (sd->state.reg_dirty&4) - intif_saveregistry(sd, 3); //Save char regs + intif->saveregistry(sd, 3); //Save char regs if (sd->state.reg_dirty&2) - intif_saveregistry(sd, 2); //Save account regs + intif->saveregistry(sd, 2); //Save account regs if (sd->state.reg_dirty&1) - intif_saveregistry(sd, 1); //Save account2 regs + intif->saveregistry(sd, 1); //Save account2 regs WFIFOHEAD(char_fd, sizeof(sd->status) + 13); WFIFOW(char_fd,0) = 0x2b01; @@ -309,7 +309,7 @@ int chrif_save(struct map_session_data *sd, int flag) { WFIFOSET(char_fd, WFIFOW(char_fd,2)); if( sd->status.pet_id > 0 && sd->pd ) - intif_save_petdata(sd->status.account_id,&sd->pd->pet); + intif->save_petdata(sd->status.account_id,&sd->pd->pet); if( sd->hd && homun_alive(sd->hd) ) homun->save(sd->hd); if( sd->md && mercenary_get_lifetime(sd->md) > 0 ) @@ -317,7 +317,7 @@ int chrif_save(struct map_session_data *sd, int flag) { if( sd->ed && elemental->get_lifetime(sd->ed) > 0 ) elemental->save(sd->ed); if( sd->save_quest ) - intif_quest_save(sd); + intif->quest_save(sd); return 0; } @@ -1423,12 +1423,12 @@ int chrif_parse(int fd) { while ( RFIFOREST(fd) >= 2 ) { cmd = RFIFOW(fd,0); if (cmd < 0x2af8 || cmd >= 0x2af8 + ARRAYLENGTH(packet_len_table) || packet_len_table[cmd-0x2af8] == 0) { - int r = intif_parse(fd); // Passed on to the intif + int r = intif->parse(fd); // Passed on to the intif if (r == 1) continue; // Treated in intif if (r == 2) return 0; // Didn't have enough data (len==-1) - ShowWarning("chrif_parse: session #%d, intif_parse failed (unrecognized command 0x%.4x).\n", fd, cmd); + ShowWarning("chrif_parse: session #%d, intif->parse failed (unrecognized command 0x%.4x).\n", fd, cmd); set_eof(fd); return 0; } diff --git a/src/map/clif.c b/src/map/clif.c index 8377eed5c..f5ce8ede3 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -9889,7 +9889,7 @@ void clif_parse_GetCharNameRequest(int fd, struct map_session_data *sd) sprintf(gm_msg, "Hack on NameRequest: character '%s' (account: %d) requested the name of an invisible target (id: %d).\n", sd->status.name, sd->status.account_id, id); ShowWarning(gm_msg); // information is sent to all online GMs - intif_wis_message_to_gm(iMap->wisp_server_name, battle_config.hack_info_GM_level, gm_msg); + intif->wis_message_to_gm(iMap->wisp_server_name, battle_config.hack_info_GM_level, gm_msg); return; } */ @@ -10489,7 +10489,7 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd) // if there are 'Test' player on an other map-server and 'test' player on this map-server, // and if we ask for 'Test', we must not contact 'test' player // so, we send information to inter-server, which is the only one which decide (and copy correct name). - intif_wis_message(sd, target, message, messagelen); + intif->wis_message(sd, target, message, messagelen); return; } @@ -14556,7 +14556,7 @@ void clif_parse_Mail_refreshinbox(int fd, struct map_session_data *sd) struct mail_data* md = &sd->mail.inbox; if( md->amount < MAIL_MAX_INBOX && (md->full || sd->mail.changed) ) - intif_Mail_requestinbox(sd->status.char_id, 1); + intif->Mail_requestinbox(sd->status.char_id, 1); else clif->mail_refreshinbox(sd); @@ -14620,7 +14620,7 @@ void clif_Mail_read(struct map_session_data *sd, int mail_id) if (msg->status == MAIL_UNREAD) { msg->status = MAIL_READ; - intif_Mail_read(mail_id); + intif->Mail_read(mail_id); clif->pMail_refreshinbox(fd, sd); } } @@ -14700,7 +14700,7 @@ void clif_parse_Mail_getattach(int fd, struct map_session_data *sd) memset(&sd->mail.inbox.msg[i].item, 0, sizeof(struct item)); clif->mail_read(sd, mail_id); - intif_Mail_getattach(sd->status.char_id, mail_id); + intif->Mail_getattach(sd->status.char_id, mail_id); } @@ -14727,7 +14727,7 @@ void clif_parse_Mail_delete(int fd, struct map_session_data *sd) return; } - intif_Mail_delete(sd->status.char_id, mail_id); + intif->Mail_delete(sd->status.char_id, mail_id); } } @@ -14746,7 +14746,7 @@ void clif_parse_Mail_return(int fd, struct map_session_data *sd) ARR_FIND(0, MAIL_MAX_INBOX, i, sd->mail.inbox.msg[i].id == mail_id); if( i < MAIL_MAX_INBOX && sd->mail.inbox.msg[i].send_id != 0 ) - intif_Mail_return(sd->status.char_id, mail_id); + intif->Mail_return(sd->status.char_id, mail_id); else clif->mail_return(sd->fd, mail_id, 1); } @@ -14839,7 +14839,7 @@ void clif_parse_Mail_send(int fd, struct map_session_data *sd) memset(msg.body, 0x00, MAIL_BODY_LENGTH); msg.timestamp = time(NULL); - if( !intif_Mail_send(sd->status.account_id, &msg) ) + if( !intif->Mail_send(sd->status.account_id, &msg) ) mail->deliveryfail(sd, &msg); sd->cansendmail_tick = iTimer->gettick() + 1000; // 1 Second flood Protection @@ -15083,7 +15083,7 @@ void clif_parse_Auction_register(int fd, struct map_session_data *sd) auction.item.amount = 1; auction.timestamp = 0; - if( !intif_Auction_register(&auction) ) + if( !intif->Auction_register(&auction) ) clif->auction_message(fd, 4); // No Char Server? lets say something to the client else { @@ -15103,7 +15103,7 @@ void clif_parse_Auction_cancel(int fd, struct map_session_data *sd) { unsigned int auction_id = RFIFOL(fd,2); - intif_Auction_cancel(sd->status.char_id, auction_id); + intif->Auction_cancel(sd->status.char_id, auction_id); } @@ -15113,7 +15113,7 @@ void clif_parse_Auction_close(int fd, struct map_session_data *sd) { unsigned int auction_id = RFIFOL(fd,2); - intif_Auction_close(sd->status.char_id, auction_id); + intif->Auction_close(sd->status.char_id, auction_id); } @@ -15133,11 +15133,11 @@ void clif_parse_Auction_bid(int fd, struct map_session_data *sd) clif->auction_message(fd, 0); // You have failed to bid into the auction else if( bid > sd->status.zeny ) clif->auction_message(fd, 8); // You do not have enough zeny - else if ( CheckForCharServer() ) // char server is down (bugreport:1138) + else if ( intif->CheckForCharServer() ) // char server is down (bugreport:1138) clif->auction_message(fd, 0); // You have failed to bid into the auction else { pc->payzeny(sd, bid, LOG_TYPE_AUCTION, NULL); - intif_Auction_bid(sd->status.char_id, sd->status.name, auction_id, bid); + intif->Auction_bid(sd->status.char_id, sd->status.name, auction_id, bid); } } @@ -15160,7 +15160,7 @@ void clif_parse_Auction_search(int fd, struct map_session_data* sd) clif->pAuction_cancelreg(fd, sd); safestrncpy(search_text, (char*)RFIFOP(fd,8), sizeof(search_text)); - intif_Auction_requestlist(sd->status.char_id, type, price, search_text, page); + intif->Auction_requestlist(sd->status.char_id, type, price, search_text, page); } @@ -15174,7 +15174,7 @@ void clif_parse_Auction_buysell(int fd, struct map_session_data* sd) short type = RFIFOW(fd,2) + 6; clif->pAuction_cancelreg(fd, sd); - intif_Auction_requestlist(sd->status.char_id, type, 0, "", 1); + intif->Auction_requestlist(sd->status.char_id, type, 0, "", 1); } diff --git a/src/map/elemental.c b/src/map/elemental.c index 3c212ccaa..03aa93e49 100644 --- a/src/map/elemental.c +++ b/src/map/elemental.c @@ -135,7 +135,7 @@ int elemental_create(struct map_session_data *sd, int class_, unsigned int lifet ele.life_time = lifetime; // Request Char Server to create this elemental - intif_elemental_create(&ele); + intif->elemental_create(&ele); return 1; } @@ -163,7 +163,7 @@ int elemental_save(struct elemental_data *ed) { ed->elemental.flee = ed->battle_status.flee; ed->elemental.hit = ed->battle_status.hit; ed->elemental.life_time = elemental->get_lifetime(ed); - intif_elemental_save(&ed->elemental); + intif->elemental_save(&ed->elemental); return 1; } diff --git a/src/map/guild.c b/src/map/guild.c index e5ea6809d..601d88387 100644 --- a/src/map/guild.c +++ b/src/map/guild.c @@ -84,7 +84,7 @@ static TBL_PC* guild_sd_check(int guild_id, int account_id, int char_id) if (sd->status.guild_id != guild_id) { //If player belongs to a different guild, kick him out. - intif_guild_leave(guild_id,account_id,char_id,0,"** Guild Mismatch **"); + intif->guild_leave(guild_id,account_id,char_id,0,"** Guild Mismatch **"); return NULL; } @@ -179,7 +179,7 @@ static bool guild_read_castledb(char* str[], int columns, int current) idb_put(castle_db,gc->castle_id,gc); - //intif_guild_castle_info(gc->castle_id); + //intif->guild_castle_info(gc->castle_id); return true; } @@ -313,7 +313,7 @@ int guild_payexp_timer_sub(DBKey key, DBData *data, va_list ap) { else g->member[i].exp+= c->exp; - intif_guild_change_memberinfo(g->guild_id,c->account_id,c->char_id, + intif->guild_change_memberinfo(g->guild_id,c->account_id,c->char_id, GMI_EXP,&g->member[i].exp,sizeof(g->member[i].exp)); c->exp=0; @@ -395,7 +395,7 @@ int guild_create(struct map_session_data *sd, const char *name) guild_makemember(&m,sd); m.position=0; - intif_guild_create(name,&m); + intif->guild_create(name,&m); return 1; } @@ -420,7 +420,7 @@ int guild_created(int account_id,int guild_id) { //Information request int guild_request_info(int guild_id) { - return intif_guild_request_info(guild_id); + return intif->guild_request_info(guild_id); } //Information request with event @@ -733,7 +733,7 @@ int guild_reply_invite(struct map_session_data* sd, int guild_id, int flag) } guild_makemember(&m,sd); - intif_guild_addmember(guild_id, &m); + intif->guild_addmember(guild_id, &m); //TODO: send a minimap update to this player } @@ -799,7 +799,7 @@ int guild_member_added(int guild_id,int account_id,int char_id,int flag) // cancel if player not present or invalide guild_id invitation if (flag == 0) { ShowError("guild: member added error %d is not online\n",account_id); - intif_guild_leave(guild_id,account_id,char_id,0,"** Data Error **"); + intif->guild_leave(guild_id,account_id,char_id,0,"** Data Error **"); } return 0; } @@ -851,7 +851,7 @@ int guild_leave(struct map_session_data* sd, int guild_id, int account_id, int c ((iMap->agit_flag || iMap->agit2_flag) && map[sd->bl.m].flag.gvg_castle)) return 0; - intif_guild_leave(sd->status.guild_id, sd->status.account_id, sd->status.char_id,0,mes); + intif->guild_leave(sd->status.guild_id, sd->status.account_id, sd->status.char_id,0,mes); return 0; } @@ -886,7 +886,7 @@ int guild_expulsion(struct map_session_data* sd, int guild_id, int account_id, i // find the member and perform expulsion i = guild->getindex(g, account_id, char_id); if( i != -1 && strcmp(g->member[i].name,g->master) != 0 ) //Can't expel the GL! - intif_guild_leave(g->guild_id,account_id,char_id,1,mes); + intif->guild_leave(g->guild_id,account_id,char_id,1,mes); return 0; } @@ -954,7 +954,7 @@ int guild_send_memberinfoshort(struct map_session_data *sd,int online) if(!(g = sd->guild)) return 0; - intif_guild_memberinfoshort(g->guild_id, + intif->guild_memberinfoshort(g->guild_id, sd->status.account_id,sd->status.char_id,online,sd->status.base_level,sd->status.class_); if(!online){ @@ -1047,7 +1047,7 @@ int guild_send_message(struct map_session_data *sd,const char *mes,int len) if(sd->status.guild_id==0) return 0; - intif_guild_message(sd->status.guild_id,sd->status.account_id,mes,len); + intif->guild_message(sd->status.guild_id,sd->status.account_id,mes,len); guild->recv_message(sd->status.guild_id,sd->status.account_id,mes,len); // Chat logging type 'G' / Guild Chat @@ -1073,7 +1073,7 @@ int guild_recv_message(int guild_id,int account_id,const char *mes,int len) *---------------------------------------------------*/ int guild_change_memberposition(int guild_id,int account_id,int char_id,short idx) { - return intif_guild_change_memberinfo(guild_id,account_id,char_id,GMI_POSITION,&idx,sizeof(idx)); + return intif->guild_change_memberinfo(guild_id,account_id,char_id,GMI_POSITION,&idx,sizeof(idx)); } /*==================================================== @@ -1106,7 +1106,7 @@ int guild_change_position(int guild_id,int idx, p.mode=mode&0x11; p.exp_mode=exp_mode; safestrncpy(p.name,name,NAME_LENGTH); - return intif_guild_position(guild_id,idx,&p); + return intif->guild_position(guild_id,idx,&p); } /*==================================================== @@ -1137,7 +1137,7 @@ int guild_change_notice(struct map_session_data *sd,int guild_id,const char *mes if(guild_id!=sd->status.guild_id) return 0; - return intif_guild_notice(guild_id,mes1,mes2); + return intif->guild_notice(guild_id,mes1,mes2); } /*==================================================== @@ -1175,7 +1175,7 @@ int guild_change_emblem(struct map_session_data *sd,int len,const char *data) return 0; } - return intif_guild_emblem(sd->status.guild_id,len,data); + return intif->guild_emblem(sd->status.guild_id,len,data); } /*==================================================== @@ -1328,7 +1328,7 @@ int guild_skillup(TBL_PC* sd, uint16 skill_id) if( g->skill_point > 0 && g->skill[idx].id != 0 && g->skill[idx].lv < max ) - intif_guild_skillup(g->guild_id, skill_id, sd->status.account_id, max); + intif->guild_skillup(g->guild_id, skill_id, sd->status.account_id, max); return 0; } @@ -1529,18 +1529,18 @@ int guild_reply_reqalliance(struct map_session_data *sd,int account_id,int flag) for(i=0;ialliance[i].guild_id==tsd->status.guild_id && g->alliance[i].opposition==1) - intif_guild_alliance( sd->status.guild_id,tsd->status.guild_id, + intif->guild_alliance( sd->status.guild_id,tsd->status.guild_id, sd->status.account_id,tsd->status.account_id,9 ); } for(i=0;ialliance[i].guild_id==sd->status.guild_id && tg->alliance[i].opposition==1) - intif_guild_alliance( tsd->status.guild_id,sd->status.guild_id, + intif->guild_alliance( tsd->status.guild_id,sd->status.guild_id, tsd->status.account_id,sd->status.account_id,9 ); } // inform other servers - intif_guild_alliance( sd->status.guild_id,tsd->status.guild_id, + intif->guild_alliance( sd->status.guild_id,tsd->status.guild_id, sd->status.account_id,tsd->status.account_id,0 ); return 0; } else { // deny @@ -1564,7 +1564,7 @@ int guild_delalliance(struct map_session_data *sd,int guild_id,int flag) return 0; } // end addition [Valaris] - intif_guild_alliance( sd->status.guild_id,guild_id,sd->status.account_id,0,flag|8 ); + intif->guild_alliance( sd->status.guild_id,guild_id,sd->status.account_id,0,flag|8 ); return 0; } @@ -1600,13 +1600,13 @@ int guild_opposition(struct map_session_data *sd,struct map_session_data *tsd) if(iMap->agit_flag || iMap->agit2_flag) // Prevent the changing of alliances to oppositions during WoE. return 0; //Change alliance to opposition. - intif_guild_alliance( sd->status.guild_id,tsd->status.guild_id, + intif->guild_alliance( sd->status.guild_id,tsd->status.guild_id, sd->status.account_id,tsd->status.account_id,8 ); } } // inform other serv - intif_guild_alliance( sd->status.guild_id,tsd->status.guild_id, + intif->guild_alliance( sd->status.guild_id,tsd->status.guild_id, sd->status.account_id,tsd->status.account_id,1 ); return 0; } @@ -1713,7 +1713,7 @@ int guild_broken_sub(DBKey key, DBData *data, va_list ap) for(j=0;jmax_member;j++) if( (sd=g->member[j].sd)!=NULL ) clif->guild_delalliance(sd,guild_id,g->alliance[i].opposition); - intif_guild_alliance(g->guild_id, guild_id,0,0,g->alliance[i].opposition|8); + intif->guild_alliance(g->guild_id, guild_id,0,0,g->alliance[i].opposition|8); g->alliance[i].guild_id=0; } } @@ -1799,7 +1799,7 @@ int guild_gm_change(int guild_id, struct map_session_data *sd) return 0; //Notify servers that master has changed. - intif_guild_change_gm(guild_id, sd->status.name, strlen(sd->status.name)+1); + intif->guild_change_gm(guild_id, sd->status.name, strlen(sd->status.name)+1); return 1; } @@ -1905,7 +1905,7 @@ int guild_break(struct map_session_data *sd,char *name) { } } - intif_guild_break(g->guild_id); + intif->guild_break(g->guild_id); return 1; } @@ -1929,7 +1929,7 @@ void guild_castle_map_init(void) *(cursor++) = gc->castle_id; } dbi_destroy(iter); - if (intif_guild_castle_dataload(num, castle_ids)) + if (intif->guild_castle_dataload(num, castle_ids)) ShowStatus("Requested '"CL_WHITE"%d"CL_RESET"' guild castles from char-server...\n", num); aFree(castle_ids); } @@ -1996,7 +1996,7 @@ int guild_castledatasave(int castle_id, int index, int value) return 0; } - if (!intif_guild_castle_datasave(castle_id, index, value)) { + if (!intif->guild_castle_datasave(castle_id, index, value)) { guild->castle_reconnect(castle_id, index, value); } return 0; @@ -2006,7 +2006,7 @@ void guild_castle_reconnect_sub(void *key, void *data, va_list ap) { int castle_id = GetWord((int)__64BPTRSIZE(key), 0); int index = GetWord((int)__64BPTRSIZE(key), 1); - intif_guild_castle_datasave(castle_id, index, *(int *)data); + intif->guild_castle_datasave(castle_id, index, *(int *)data); aFree(data); } diff --git a/src/map/homunculus.c b/src/map/homunculus.c index a1dd38b68..3a6ed074c 100644 --- a/src/map/homunculus.c +++ b/src/map/homunculus.c @@ -544,7 +544,7 @@ void homunculus_save(struct homun_data *hd) { //calculation on login) hd->homunculus.hp = hd->battle_status.hp; hd->homunculus.sp = hd->battle_status.sp; - intif_homunculus_requestsave(sd->status.account_id, &hd->homunculus); + intif->homunculus_requestsave(sd->status.account_id, &hd->homunculus); } unsigned char homunculus_menu(struct map_session_data *sd,unsigned char menu_num) { @@ -731,7 +731,7 @@ bool homunculus_create(struct map_session_data *sd, struct s_homunculus *hom) { if(i < 0) { ShowError("homunculus_create: unknown class [%d] for homunculus '%s', requesting deletion.\n", hom->class_, hom->name); sd->status.hom_id = 0; - intif_homunculus_requestdelete(hom->hom_id); + intif->homunculus_requestdelete(hom->hom_id); return false; } sd->hd = hd = (struct homun_data*)aCalloc(1,sizeof(struct homun_data)); @@ -777,7 +777,7 @@ bool homunculus_call(struct map_session_data *sd) { // If homunc not yet loaded, load it if (!sd->hd) - return intif_homunculus_requestload(sd->status.account_id, sd->status.hom_id); + return intif->homunculus_requestload(sd->status.account_id, sd->status.hom_id); hd = sd->hd; @@ -892,7 +892,7 @@ bool homunculus_creation_request(struct map_session_data *sd, int class_) { hom.luk = base->luk *10; // Request homunculus creation - intif_homunculus_create(sd->status.account_id, &hom); + intif->homunculus_create(sd->status.account_id, &hom); return true; } @@ -904,7 +904,7 @@ bool homunculus_ressurect(struct map_session_data* sd, unsigned char per, short return false; // no homunculus if (!sd->hd) //Load homun data; - return intif_homunculus_requestload(sd->status.account_id, sd->status.hom_id); + return intif->homunculus_requestload(sd->status.account_id, sd->status.hom_id); hd = sd->hd; diff --git a/src/map/intif.c b/src/map/intif.c index f2c5e7e78..813c1cf7c 100644 --- a/src/map/intif.c +++ b/src/map/intif.c @@ -1,2259 +1,2351 @@ -// Copyright (c) Athena Dev Teams - Licensed under GNU GPL -// For more information, see LICENCE in the main folder - -#include "../common/showmsg.h" -#include "../common/socket.h" -#include "../common/timer.h" -#include "../common/nullpo.h" -#include "../common/malloc.h" -#include "../common/strlib.h" -#include "map.h" -#include "battle.h" -#include "chrif.h" -#include "clif.h" -#include "pc.h" -#include "intif.h" -#include "log.h" -#include "storage.h" -#include "party.h" -#include "guild.h" -#include "pet.h" -#include "atcommand.h" -#include "mercenary.h" -#include "homunculus.h" -#include "elemental.h" -#include "mail.h" -#include "quest.h" - -#include -#include -#include -#include -#include -#include - - -static const int packet_len_table[]={ - -1,-1,27,-1, -1, 0,37,-1, 0, 0, 0, 0, 0, 0, 0, 0, //0x3800-0x380f - 0, 0, 0, 0, 0, 0, 0, 0, -1,11, 0, 0, 0, 0, 0, 0, //0x3810 - 39,-1,15,15, 14,19, 7,-1, 0, 0, 0, 0, 0, 0, 0, 0, //0x3820 - 10,-1,15, 0, 79,19, 7,-1, 0,-1,-1,-1, 14,67,186,-1, //0x3830 - -1, 0, 0,14, 0, 0, 0, 0, -1,74,-1,11, 11,-1, 0, 0, //0x3840 - -1,-1, 7, 7, 7,11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3850 Auctions [Zephyrus] - -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3860 Quests [Kevin] [Inkfish] - -1, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 3, 3, 0, //0x3870 Mercenaries [Zephyrus] / Elemental [pakpil] - 11,-1, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3880 - -1,-1, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3890 Homunculus [albator] -}; - -extern int char_fd; // inter server Fd used for char_fd -#define inter_fd char_fd // alias - -//----------------------------------------------------------------- -// Send to inter server - -int CheckForCharServer(void) -{ - return ((char_fd <= 0) || session[char_fd] == NULL || session[char_fd]->wdata == NULL); -} - -// pet -int intif_create_pet(int account_id,int char_id,short pet_class,short pet_lv,short pet_egg_id, - short pet_equip,short intimate,short hungry,char rename_flag,char incuvate,char *pet_name) -{ - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd, 24 + NAME_LENGTH); - WFIFOW(inter_fd,0) = 0x3080; - WFIFOL(inter_fd,2) = account_id; - WFIFOL(inter_fd,6) = char_id; - WFIFOW(inter_fd,10) = pet_class; - WFIFOW(inter_fd,12) = pet_lv; - WFIFOW(inter_fd,14) = pet_egg_id; - WFIFOW(inter_fd,16) = pet_equip; - WFIFOW(inter_fd,18) = intimate; - WFIFOW(inter_fd,20) = hungry; - WFIFOB(inter_fd,22) = rename_flag; - WFIFOB(inter_fd,23) = incuvate; - memcpy(WFIFOP(inter_fd,24),pet_name,NAME_LENGTH); - WFIFOSET(inter_fd,24+NAME_LENGTH); - - return 0; -} - -int intif_request_petdata(int account_id,int char_id,int pet_id) -{ - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd, 14); - WFIFOW(inter_fd,0) = 0x3081; - WFIFOL(inter_fd,2) = account_id; - WFIFOL(inter_fd,6) = char_id; - WFIFOL(inter_fd,10) = pet_id; - WFIFOSET(inter_fd,14); - - return 0; -} - -int intif_save_petdata(int account_id,struct s_pet *p) -{ - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd, sizeof(struct s_pet) + 8); - WFIFOW(inter_fd,0) = 0x3082; - WFIFOW(inter_fd,2) = sizeof(struct s_pet) + 8; - WFIFOL(inter_fd,4) = account_id; - memcpy(WFIFOP(inter_fd,8),p,sizeof(struct s_pet)); - WFIFOSET(inter_fd,WFIFOW(inter_fd,2)); - - return 0; -} - -int intif_delete_petdata(int pet_id) -{ - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd,6); - WFIFOW(inter_fd,0) = 0x3083; - WFIFOL(inter_fd,2) = pet_id; - WFIFOSET(inter_fd,6); - - return 1; -} - -int intif_rename(struct map_session_data *sd, int type, char *name) -{ - if (CheckForCharServer()) - return 1; - - WFIFOHEAD(inter_fd,NAME_LENGTH+12); - WFIFOW(inter_fd,0) = 0x3006; - WFIFOL(inter_fd,2) = sd->status.account_id; - WFIFOL(inter_fd,6) = sd->status.char_id; - WFIFOB(inter_fd,10) = type; //Type: 0 - PC, 1 - PET, 2 - HOM - memcpy(WFIFOP(inter_fd,11),name, NAME_LENGTH); - WFIFOSET(inter_fd,NAME_LENGTH+12); - return 0; -} - -// GM Send a message -int intif_broadcast(const char* mes, int len, int type) -{ - int lp = type ? 4 : 0; - - // Send to the local players - clif->broadcast(NULL, mes, len, type, ALL_CLIENT); - - if (CheckForCharServer()) - return 0; - - if (chrif->other_mapserver_count < 1) - return 0; //No need to send. - - WFIFOHEAD(inter_fd, 16 + lp + len); - WFIFOW(inter_fd,0) = 0x3000; - WFIFOW(inter_fd,2) = 16 + lp + len; - WFIFOL(inter_fd,4) = 0xFF000000; // 0xFF000000 color signals standard broadcast - WFIFOW(inter_fd,8) = 0; // fontType not used with standard broadcast - WFIFOW(inter_fd,10) = 0; // fontSize not used with standard broadcast - WFIFOW(inter_fd,12) = 0; // fontAlign not used with standard broadcast - WFIFOW(inter_fd,14) = 0; // fontY not used with standard broadcast - if (type == 0x10) // bc_blue - WFIFOL(inter_fd,16) = 0x65756c62; //If there's "blue" at the beginning of the message, game client will display it in blue instead of yellow. - else if (type == 0x20) // bc_woe - WFIFOL(inter_fd,16) = 0x73737373; //If there's "ssss", game client will recognize message as 'WoE broadcast'. - memcpy(WFIFOP(inter_fd,16 + lp), mes, len); - WFIFOSET(inter_fd, WFIFOW(inter_fd,2)); - return 0; -} - -int intif_broadcast2(const char* mes, int len, unsigned long fontColor, short fontType, short fontSize, short fontAlign, short fontY) -{ - // Send to the local players - clif->broadcast2(NULL, mes, len, fontColor, fontType, fontSize, fontAlign, fontY, ALL_CLIENT); - - if (CheckForCharServer()) - return 0; - - if (chrif->other_mapserver_count < 1) - return 0; //No need to send. - - WFIFOHEAD(inter_fd, 16 + len); - WFIFOW(inter_fd,0) = 0x3000; - WFIFOW(inter_fd,2) = 16 + len; - WFIFOL(inter_fd,4) = fontColor; - WFIFOW(inter_fd,8) = fontType; - WFIFOW(inter_fd,10) = fontSize; - WFIFOW(inter_fd,12) = fontAlign; - WFIFOW(inter_fd,14) = fontY; - memcpy(WFIFOP(inter_fd,16), mes, len); - WFIFOSET(inter_fd, WFIFOW(inter_fd,2)); - return 0; -} - -/// send a message using the main chat system -/// the source of message -/// the message that was sent -int intif_main_message(struct map_session_data* sd, const char* message) -{ - char output[256]; - - nullpo_ret(sd); - - // format the message for main broadcasting - snprintf( output, sizeof(output), msg_txt(386), sd->status.name, message ); - - // send the message using the inter-server broadcast service - intif_broadcast2( output, strlen(output) + 1, 0xFE000000, 0, 0, 0, 0 ); - - // log the chat message - logs->chat( LOG_CHAT_MAINCHAT, 0, sd->status.char_id, sd->status.account_id, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, NULL, message ); - - return 0; -} - -// The transmission of Wisp/Page to inter-server (player not found on this server) -int intif_wis_message(struct map_session_data *sd, char *nick, char *mes, int mes_len) -{ - nullpo_ret(sd); - if (CheckForCharServer()) - return 0; - - if (chrif->other_mapserver_count < 1) - { //Character not found. - clif->wis_end(sd->fd, 1); - return 0; - } - - WFIFOHEAD(inter_fd,mes_len + 52); - WFIFOW(inter_fd,0) = 0x3001; - WFIFOW(inter_fd,2) = mes_len + 52; - memcpy(WFIFOP(inter_fd,4), sd->status.name, NAME_LENGTH); - memcpy(WFIFOP(inter_fd,4+NAME_LENGTH), nick, NAME_LENGTH); - memcpy(WFIFOP(inter_fd,4+2*NAME_LENGTH), mes, mes_len); - WFIFOSET(inter_fd, WFIFOW(inter_fd,2)); - - if (battle_config.etc_log) - ShowInfo("intif_wis_message from %s to %s (message: '%s')\n", sd->status.name, nick, mes); - - return 0; -} - -// The reply of Wisp/page -int intif_wis_replay(int id, int flag) -{ - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd,7); - WFIFOW(inter_fd,0) = 0x3002; - WFIFOL(inter_fd,2) = id; - WFIFOB(inter_fd,6) = flag; // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target - WFIFOSET(inter_fd,7); - - if (battle_config.etc_log) - ShowInfo("intif_wis_replay: id: %d, flag:%d\n", id, flag); - - return 0; -} - -// The transmission of GM only Wisp/Page from server to inter-server -int intif_wis_message_to_gm(char *wisp_name, int permission, char *mes) -{ - int mes_len; - if (CheckForCharServer()) - return 0; - mes_len = strlen(mes) + 1; // + null - WFIFOHEAD(inter_fd, mes_len + 32); - WFIFOW(inter_fd,0) = 0x3003; - WFIFOW(inter_fd,2) = mes_len + 32; - memcpy(WFIFOP(inter_fd,4), wisp_name, NAME_LENGTH); - WFIFOL(inter_fd,4+NAME_LENGTH) = permission; - memcpy(WFIFOP(inter_fd,8+NAME_LENGTH), mes, mes_len); - WFIFOSET(inter_fd, WFIFOW(inter_fd,2)); - - if (battle_config.etc_log) - ShowNotice("intif_wis_message_to_gm: from: '%s', required permission: %d, message: '%s'.\n", wisp_name, permission, mes); - - return 0; -} - -int intif_regtostr(char* str, struct global_reg *reg, int qty) -{ - int len =0, i; - - for (i = 0; i < qty; i++) { - len+= sprintf(str+len, "%s", reg[i].str)+1; //We add 1 to consider the '\0' in place. - len+= sprintf(str+len, "%s", reg[i].value)+1; - } - return len; -} - -//Request for saving registry values. -int intif_saveregistry(struct map_session_data *sd, int type) -{ - struct global_reg *reg; - int count; - int i, p; - - if (CheckForCharServer()) - return -1; - - switch (type) { - case 3: //Character reg - reg = sd->save_reg.global; - count = sd->save_reg.global_num; - sd->state.reg_dirty &= ~0x4; - break; - case 2: //Account reg - reg = sd->save_reg.account; - count = sd->save_reg.account_num; - sd->state.reg_dirty &= ~0x2; - break; - case 1: //Account2 reg - reg = sd->save_reg.account2; - count = sd->save_reg.account2_num; - sd->state.reg_dirty &= ~0x1; - break; - default: //Broken code? - ShowError("intif_saveregistry: Invalid type %d\n", type); - return -1; - } - WFIFOHEAD(inter_fd, 288 * MAX_REG_NUM+13); - WFIFOW(inter_fd,0)=0x3004; - WFIFOL(inter_fd,4)=sd->status.account_id; - WFIFOL(inter_fd,8)=sd->status.char_id; - WFIFOB(inter_fd,12)=type; - for( p = 13, i = 0; i < count; i++ ) { - if (reg[i].str[0] != '\0' && reg[i].value[0] != '\0') { - p+= sprintf((char*)WFIFOP(inter_fd,p), "%s", reg[i].str)+1; //We add 1 to consider the '\0' in place. - p+= sprintf((char*)WFIFOP(inter_fd,p), "%s", reg[i].value)+1; - } - } - WFIFOW(inter_fd,2)=p; - WFIFOSET(inter_fd,WFIFOW(inter_fd,2)); - return 0; -} - -//Request the registries for this player. -int intif_request_registry(struct map_session_data *sd, int flag) -{ - nullpo_ret(sd); - - sd->save_reg.account2_num = -1; - sd->save_reg.account_num = -1; - sd->save_reg.global_num = -1; - - if (CheckForCharServer()) - return 0; - - WFIFOHEAD(inter_fd,6); - WFIFOW(inter_fd,0) = 0x3005; - WFIFOL(inter_fd,2) = sd->status.account_id; - WFIFOL(inter_fd,6) = sd->status.char_id; - WFIFOB(inter_fd,10) = (flag&1?1:0); //Request Acc Reg 2 - WFIFOB(inter_fd,11) = (flag&2?1:0); //Request Acc Reg - WFIFOB(inter_fd,12) = (flag&4?1:0); //Request Char Reg - WFIFOSET(inter_fd,13); - - return 0; -} - -int intif_request_guild_storage(int account_id,int guild_id) -{ - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd,10); - WFIFOW(inter_fd,0) = 0x3018; - WFIFOL(inter_fd,2) = account_id; - WFIFOL(inter_fd,6) = guild_id; - WFIFOSET(inter_fd,10); - return 0; -} -int intif_send_guild_storage(int account_id,struct guild_storage *gstor) -{ - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd,sizeof(struct guild_storage)+12); - WFIFOW(inter_fd,0) = 0x3019; - WFIFOW(inter_fd,2) = (unsigned short)sizeof(struct guild_storage)+12; - WFIFOL(inter_fd,4) = account_id; - WFIFOL(inter_fd,8) = gstor->guild_id; - memcpy( WFIFOP(inter_fd,12),gstor, sizeof(struct guild_storage) ); - WFIFOSET(inter_fd,WFIFOW(inter_fd,2)); - return 0; -} - -// Party creation request -int intif_create_party(struct party_member *member,char *name,int item,int item2) -{ - if (CheckForCharServer()) - return 0; - nullpo_ret(member); - - WFIFOHEAD(inter_fd,64); - WFIFOW(inter_fd,0) = 0x3020; - WFIFOW(inter_fd,2) = 30+sizeof(struct party_member); - memcpy(WFIFOP(inter_fd,4),name, NAME_LENGTH); - WFIFOB(inter_fd,28)= item; - WFIFOB(inter_fd,29)= item2; - memcpy(WFIFOP(inter_fd,30), member, sizeof(struct party_member)); - WFIFOSET(inter_fd,WFIFOW(inter_fd, 2)); - return 0; -} - -// Party information request -int intif_request_partyinfo(int party_id, int char_id) -{ - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd,10); - WFIFOW(inter_fd,0) = 0x3021; - WFIFOL(inter_fd,2) = party_id; - WFIFOL(inter_fd,6) = char_id; - WFIFOSET(inter_fd,10); - return 0; -} - -// Request to add a member to party -int intif_party_addmember(int party_id,struct party_member *member) -{ - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd,42); - WFIFOW(inter_fd,0)=0x3022; - WFIFOW(inter_fd,2)=8+sizeof(struct party_member); - WFIFOL(inter_fd,4)=party_id; - memcpy(WFIFOP(inter_fd,8),member,sizeof(struct party_member)); - WFIFOSET(inter_fd,WFIFOW(inter_fd, 2)); - return 1; -} - -// Request to change party configuration (exp,item share) -int intif_party_changeoption(int party_id,int account_id,int exp,int item) -{ - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd,14); - WFIFOW(inter_fd,0)=0x3023; - WFIFOL(inter_fd,2)=party_id; - WFIFOL(inter_fd,6)=account_id; - WFIFOW(inter_fd,10)=exp; - WFIFOW(inter_fd,12)=item; - WFIFOSET(inter_fd,14); - return 0; -} - -// Request to leave party -int intif_party_leave(int party_id,int account_id, int char_id) -{ - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd,14); - WFIFOW(inter_fd,0)=0x3024; - WFIFOL(inter_fd,2)=party_id; - WFIFOL(inter_fd,6)=account_id; - WFIFOL(inter_fd,10)=char_id; - WFIFOSET(inter_fd,14); - return 0; -} - -// Request keeping party for new map ?? -int intif_party_changemap(struct map_session_data *sd,int online) -{ - int16 m, mapindex; - - if (CheckForCharServer()) - return 0; - if(!sd) - return 0; - - if( (m=iMap->mapindex2mapid(sd->mapindex)) >= 0 && map[m].instance_id >= 0 ) - mapindex = map[map[m].instance_src_map].index; - else - mapindex = sd->mapindex; - - WFIFOHEAD(inter_fd,19); - WFIFOW(inter_fd,0)=0x3025; - WFIFOL(inter_fd,2)=sd->status.party_id; - WFIFOL(inter_fd,6)=sd->status.account_id; - WFIFOL(inter_fd,10)=sd->status.char_id; - WFIFOW(inter_fd,14)=mapindex; - WFIFOB(inter_fd,16)=online; - WFIFOW(inter_fd,17)=sd->status.base_level; - WFIFOSET(inter_fd,19); - return 1; -} - -// Request breaking party -int intif_break_party(int party_id) -{ - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd,6); - WFIFOW(inter_fd,0)=0x3026; - WFIFOL(inter_fd,2)=party_id; - WFIFOSET(inter_fd,6); - return 0; -} - -// Sending party chat -int intif_party_message(int party_id,int account_id,const char *mes,int len) -{ - if (CheckForCharServer()) - return 0; - - if (chrif->other_mapserver_count < 1) - return 0; //No need to send. - - WFIFOHEAD(inter_fd,len + 12); - WFIFOW(inter_fd,0)=0x3027; - WFIFOW(inter_fd,2)=len+12; - WFIFOL(inter_fd,4)=party_id; - WFIFOL(inter_fd,8)=account_id; - memcpy(WFIFOP(inter_fd,12),mes,len); - WFIFOSET(inter_fd,len+12); - return 0; -} - -// Request a new leader for party -int intif_party_leaderchange(int party_id,int account_id,int char_id) -{ - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd,14); - WFIFOW(inter_fd,0)=0x3029; - WFIFOL(inter_fd,2)=party_id; - WFIFOL(inter_fd,6)=account_id; - WFIFOL(inter_fd,10)=char_id; - WFIFOSET(inter_fd,14); - return 0; -} - -// Request a Guild creation -int intif_guild_create(const char *name,const struct guild_member *master) -{ - if (CheckForCharServer()) - return 0; - nullpo_ret(master); - - WFIFOHEAD(inter_fd,sizeof(struct guild_member)+(8+NAME_LENGTH)); - WFIFOW(inter_fd,0)=0x3030; - WFIFOW(inter_fd,2)=sizeof(struct guild_member)+(8+NAME_LENGTH); - WFIFOL(inter_fd,4)=master->account_id; - memcpy(WFIFOP(inter_fd,8),name,NAME_LENGTH); - memcpy(WFIFOP(inter_fd,8+NAME_LENGTH),master,sizeof(struct guild_member)); - WFIFOSET(inter_fd,WFIFOW(inter_fd,2)); - return 0; -} - -// Request Guild information -int intif_guild_request_info(int guild_id) -{ - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd,6); - WFIFOW(inter_fd,0) = 0x3031; - WFIFOL(inter_fd,2) = guild_id; - WFIFOSET(inter_fd,6); - return 0; -} - -// Request to add member to the guild -int intif_guild_addmember(int guild_id,struct guild_member *m) -{ - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd,sizeof(struct guild_member)+8); - WFIFOW(inter_fd,0) = 0x3032; - WFIFOW(inter_fd,2) = sizeof(struct guild_member)+8; - WFIFOL(inter_fd,4) = guild_id; - memcpy(WFIFOP(inter_fd,8),m,sizeof(struct guild_member)); - WFIFOSET(inter_fd,WFIFOW(inter_fd,2)); - return 0; -} - -// Request a new leader for guild -int intif_guild_change_gm(int guild_id, const char* name, int len) -{ - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd, len + 8); - WFIFOW(inter_fd, 0)=0x3033; - WFIFOW(inter_fd, 2)=len+8; - WFIFOL(inter_fd, 4)=guild_id; - memcpy(WFIFOP(inter_fd,8),name,len); - WFIFOSET(inter_fd,len+8); - return 0; -} - -// Request to leave guild -int intif_guild_leave(int guild_id,int account_id,int char_id,int flag,const char *mes) -{ - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd, 55); - WFIFOW(inter_fd, 0) = 0x3034; - WFIFOL(inter_fd, 2) = guild_id; - WFIFOL(inter_fd, 6) = account_id; - WFIFOL(inter_fd,10) = char_id; - WFIFOB(inter_fd,14) = flag; - safestrncpy((char*)WFIFOP(inter_fd,15),mes,40); - WFIFOSET(inter_fd,55); - return 0; -} - -//Update request / Lv online status of the guild members -int intif_guild_memberinfoshort(int guild_id,int account_id,int char_id,int online,int lv,int class_) -{ - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd, 19); - WFIFOW(inter_fd, 0) = 0x3035; - WFIFOL(inter_fd, 2) = guild_id; - WFIFOL(inter_fd, 6) = account_id; - WFIFOL(inter_fd,10) = char_id; - WFIFOB(inter_fd,14) = online; - WFIFOW(inter_fd,15) = lv; - WFIFOW(inter_fd,17) = class_; - WFIFOSET(inter_fd,19); - return 0; -} - -//Guild disbanded notification -int intif_guild_break(int guild_id) -{ - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd, 6); - WFIFOW(inter_fd, 0) = 0x3036; - WFIFOL(inter_fd, 2) = guild_id; - WFIFOSET(inter_fd,6); - return 0; -} - -// Send a guild message -int intif_guild_message(int guild_id,int account_id,const char *mes,int len) -{ - if (CheckForCharServer()) - return 0; - - if (chrif->other_mapserver_count < 1) - return 0; //No need to send. - - WFIFOHEAD(inter_fd, len + 12); - WFIFOW(inter_fd,0)=0x3037; - WFIFOW(inter_fd,2)=len+12; - WFIFOL(inter_fd,4)=guild_id; - WFIFOL(inter_fd,8)=account_id; - memcpy(WFIFOP(inter_fd,12),mes,len); - WFIFOSET(inter_fd,len+12); - - return 0; -} - -// Request a change of Guild basic information -int intif_guild_change_basicinfo(int guild_id,int type,const void *data,int len) -{ - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd, len + 10); - WFIFOW(inter_fd,0)=0x3039; - WFIFOW(inter_fd,2)=len+10; - WFIFOL(inter_fd,4)=guild_id; - WFIFOW(inter_fd,8)=type; - memcpy(WFIFOP(inter_fd,10),data,len); - WFIFOSET(inter_fd,len+10); - return 0; -} - -// Request a change of Guild member information -int intif_guild_change_memberinfo(int guild_id,int account_id,int char_id, - int type,const void *data,int len) -{ - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd, len + 18); - WFIFOW(inter_fd, 0)=0x303a; - WFIFOW(inter_fd, 2)=len+18; - WFIFOL(inter_fd, 4)=guild_id; - WFIFOL(inter_fd, 8)=account_id; - WFIFOL(inter_fd,12)=char_id; - WFIFOW(inter_fd,16)=type; - memcpy(WFIFOP(inter_fd,18),data,len); - WFIFOSET(inter_fd,len+18); - return 0; -} - -// Request a change of Guild title -int intif_guild_position(int guild_id,int idx,struct guild_position *p) -{ - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd, sizeof(struct guild_position)+12); - WFIFOW(inter_fd,0)=0x303b; - WFIFOW(inter_fd,2)=sizeof(struct guild_position)+12; - WFIFOL(inter_fd,4)=guild_id; - WFIFOL(inter_fd,8)=idx; - memcpy(WFIFOP(inter_fd,12),p,sizeof(struct guild_position)); - WFIFOSET(inter_fd,WFIFOW(inter_fd,2)); - return 0; -} - -// Request an update of Guildskill skill_id -int intif_guild_skillup(int guild_id, uint16 skill_id, int account_id, int max) -{ - if( CheckForCharServer() ) - return 0; - WFIFOHEAD(inter_fd, 18); - WFIFOW(inter_fd, 0) = 0x303c; - WFIFOL(inter_fd, 2) = guild_id; - WFIFOL(inter_fd, 6) = skill_id; - WFIFOL(inter_fd, 10) = account_id; - WFIFOL(inter_fd, 14) = max; - WFIFOSET(inter_fd, 18); - return 0; -} - -// Request a new guild relationship -int intif_guild_alliance(int guild_id1,int guild_id2,int account_id1,int account_id2,int flag) -{ - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd,19); - WFIFOW(inter_fd, 0)=0x303d; - WFIFOL(inter_fd, 2)=guild_id1; - WFIFOL(inter_fd, 6)=guild_id2; - WFIFOL(inter_fd,10)=account_id1; - WFIFOL(inter_fd,14)=account_id2; - WFIFOB(inter_fd,18)=flag; - WFIFOSET(inter_fd,19); - return 0; -} - -// Request to change guild notice -int intif_guild_notice(int guild_id,const char *mes1,const char *mes2) -{ - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd,186); - WFIFOW(inter_fd,0)=0x303e; - WFIFOL(inter_fd,2)=guild_id; - memcpy(WFIFOP(inter_fd,6),mes1,MAX_GUILDMES1); - memcpy(WFIFOP(inter_fd,66),mes2,MAX_GUILDMES2); - WFIFOSET(inter_fd,186); - return 0; -} - -// Request to change guild emblem -int intif_guild_emblem(int guild_id,int len,const char *data) -{ - if (CheckForCharServer()) - return 0; - if(guild_id<=0 || len<0 || len>2000) - return 0; - WFIFOHEAD(inter_fd,len + 12); - WFIFOW(inter_fd,0)=0x303f; - WFIFOW(inter_fd,2)=len+12; - WFIFOL(inter_fd,4)=guild_id; - WFIFOL(inter_fd,8)=0; - memcpy(WFIFOP(inter_fd,12),data,len); - WFIFOSET(inter_fd,len+12); - return 0; -} - -/** - * Requests guild castles data from char-server. - * @param num Number of castles, size of castle_ids array. - * @param castle_ids Pointer to array of castle IDs. - */ -int intif_guild_castle_dataload(int num, int *castle_ids) -{ - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd, 4 + num * sizeof(int)); - WFIFOW(inter_fd, 0) = 0x3040; - WFIFOW(inter_fd, 2) = 4 + num * sizeof(int); - memcpy(WFIFOP(inter_fd, 4), castle_ids, num * sizeof(int)); - WFIFOSET(inter_fd, WFIFOW(inter_fd, 2)); - return 1; -} - - -// Request change castle guild owner and save data -int intif_guild_castle_datasave(int castle_id,int index, int value) -{ - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd,9); - WFIFOW(inter_fd,0)=0x3041; - WFIFOW(inter_fd,2)=castle_id; - WFIFOB(inter_fd,4)=index; - WFIFOL(inter_fd,5)=value; - WFIFOSET(inter_fd,9); - return 1; -} - -//----------------------------------------------------------------- -// Homunculus Packets send to Inter server [albator] -//----------------------------------------------------------------- - -int intif_homunculus_create(int account_id, struct s_homunculus *sh) -{ - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd, sizeof(struct s_homunculus)+8); - WFIFOW(inter_fd,0) = 0x3090; - WFIFOW(inter_fd,2) = sizeof(struct s_homunculus)+8; - WFIFOL(inter_fd,4) = account_id; - memcpy(WFIFOP(inter_fd,8),sh,sizeof(struct s_homunculus)); - WFIFOSET(inter_fd, WFIFOW(inter_fd,2)); - return 0; -} - -bool intif_homunculus_requestload(int account_id, int homun_id) { - if (CheckForCharServer()) - return false; - WFIFOHEAD(inter_fd, 10); - WFIFOW(inter_fd,0) = 0x3091; - WFIFOL(inter_fd,2) = account_id; - WFIFOL(inter_fd,6) = homun_id; - WFIFOSET(inter_fd, 10); - return true; -} - -int intif_homunculus_requestsave(int account_id, struct s_homunculus* sh) -{ - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd, sizeof(struct s_homunculus)+8); - WFIFOW(inter_fd,0) = 0x3092; - WFIFOW(inter_fd,2) = sizeof(struct s_homunculus)+8; - WFIFOL(inter_fd,4) = account_id; - memcpy(WFIFOP(inter_fd,8),sh,sizeof(struct s_homunculus)); - WFIFOSET(inter_fd, WFIFOW(inter_fd,2)); - return 0; - -} - -int intif_homunculus_requestdelete(int homun_id) -{ - if (CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd, 6); - WFIFOW(inter_fd, 0) = 0x3093; - WFIFOL(inter_fd,2) = homun_id; - WFIFOSET(inter_fd,6); - return 0; - -} - - -//----------------------------------------------------------------- -// Packets receive from inter server - -// Wisp/Page reception // rewritten by [Yor] -int intif_parse_WisMessage(int fd) -{ - struct map_session_data* sd; - char *wisp_source; - char name[NAME_LENGTH]; - int id, i; - - id=RFIFOL(fd,4); - - safestrncpy(name, (char*)RFIFOP(fd,32), NAME_LENGTH); - sd = iMap->nick2sd(name); - if(sd == NULL || strcmp(sd->status.name, name) != 0) - { //Not found - intif_wis_replay(id,1); - return 0; - } - if(sd->state.ignoreAll) { - intif_wis_replay(id, 2); - return 0; - } - wisp_source = (char *) RFIFOP(fd,8); // speed up [Yor] - for(i=0; i < MAX_IGNORE_LIST && - sd->ignore[i].name[0] != '\0' && - strcmp(sd->ignore[i].name, wisp_source) != 0 - ; i++); - - if (i < MAX_IGNORE_LIST && sd->ignore[i].name[0] != '\0') - { //Ignored - intif_wis_replay(id, 2); - return 0; - } - //Success to send whisper. - clif->wis_message(sd->fd, wisp_source, (char*)RFIFOP(fd,56),RFIFOW(fd,2)-56); - intif_wis_replay(id,0); // succes - return 0; -} - -// Wisp/page transmission result reception -int intif_parse_WisEnd(int fd) -{ - struct map_session_data* sd; - - if (battle_config.etc_log) - ShowInfo("intif_parse_wisend: player: %s, flag: %d\n", RFIFOP(fd,2), RFIFOB(fd,26)); // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target - sd = (struct map_session_data *)iMap->nick2sd((char *) RFIFOP(fd,2)); - if (sd != NULL) - clif->wis_end(sd->fd, RFIFOB(fd,26)); - - return 0; -} - -static int mapif_parse_WisToGM_sub(struct map_session_data* sd,va_list va) -{ - int permission = va_arg(va, int); - char *wisp_name; - char *message; - int len; - - if (!pc_has_permission(sd, permission)) - return 0; - wisp_name = va_arg(va, char*); - message = va_arg(va, char*); - len = va_arg(va, int); - clif->wis_message(sd->fd, wisp_name, message, len); - return 1; -} - -// Received wisp message from map-server via char-server for ALL gm -// 0x3003/0x3803 .w .24B .l .?B -int mapif_parse_WisToGM(int fd) -{ - int permission, mes_len; - char Wisp_name[NAME_LENGTH]; - char mbuf[255]; - char *message; - - mes_len = RFIFOW(fd,2) - 32; - message = (char *) (mes_len >= 255 ? (char *) aMalloc(mes_len) : mbuf); - - permission = RFIFOL(fd,28); - safestrncpy(Wisp_name, (char*)RFIFOP(fd,4), NAME_LENGTH); - safestrncpy(message, (char*)RFIFOP(fd,32), mes_len); - // information is sent to all online GM - iMap->map_foreachpc(mapif_parse_WisToGM_sub, permission, Wisp_name, message, mes_len); - - if (message != mbuf) - aFree(message); - return 0; -} - -// Request player registre -int intif_parse_Registers(int fd) -{ - int j,p,len,max, flag; - struct map_session_data *sd; - struct global_reg *reg; - int *qty; - int account_id = RFIFOL(fd,4), char_id = RFIFOL(fd,8); - struct auth_node *node = chrif->auth_check(account_id, char_id, ST_LOGIN); - if (node) - sd = node->sd; - else { //Normally registries should arrive for in log-in chars. - sd = iMap->id2sd(account_id); - if (sd && RFIFOB(fd,12) == 3 && sd->status.char_id != char_id) - sd = NULL; //Character registry from another character. - } - if (!sd) return 1; - - flag = (sd->save_reg.global_num == -1 || sd->save_reg.account_num == -1 || sd->save_reg.account2_num == -1); - - switch (RFIFOB(fd,12)) { - case 3: //Character Registry - reg = sd->save_reg.global; - qty = &sd->save_reg.global_num; - max = GLOBAL_REG_NUM; - break; - case 2: //Account Registry - reg = sd->save_reg.account; - qty = &sd->save_reg.account_num; - max = ACCOUNT_REG_NUM; - break; - case 1: //Account2 Registry - reg = sd->save_reg.account2; - qty = &sd->save_reg.account2_num; - max = ACCOUNT_REG2_NUM; - break; - default: - ShowError("intif_parse_Registers: Unrecognized type %d\n",RFIFOB(fd,12)); - return 0; - } - for(j=0,p=13;jsave_reg.global_num > -1 && sd->save_reg.account_num > -1 && sd->save_reg.account2_num > -1) - pc->reg_received(sd); //Received all registry values, execute init scripts and what-not. [Skotlex] - return 1; -} - -int intif_parse_LoadGuildStorage(int fd) -{ - struct guild_storage *gstor; - struct map_session_data *sd; - int guild_id; - - guild_id = RFIFOL(fd,8); - if(guild_id <= 0) - return 1; - sd=iMap->id2sd( RFIFOL(fd,4) ); - if(sd==NULL){ - ShowError("intif_parse_LoadGuildStorage: user not found %d\n",RFIFOL(fd,4)); - return 1; - } - gstor=gstorage->id2storage(guild_id); - if(!gstor) { - ShowWarning("intif_parse_LoadGuildStorage: error guild_id %d not exist\n",guild_id); - return 1; - } - if (gstor->storage_status == 1) { // Already open.. lets ignore this update - ShowWarning("intif_parse_LoadGuildStorage: storage received for a client already open (User %d:%d)\n", sd->status.account_id, sd->status.char_id); - return 1; - } - if (gstor->dirty) { // Already have storage, and it has been modified and not saved yet! Exploit! [Skotlex] - ShowWarning("intif_parse_LoadGuildStorage: received storage for an already modified non-saved storage! (User %d:%d)\n", sd->status.account_id, sd->status.char_id); - return 1; - } - if( RFIFOW(fd,2)-12 != sizeof(struct guild_storage) ){ - ShowError("intif_parse_LoadGuildStorage: data size error %d %d\n",RFIFOW(fd,2)-12 , sizeof(struct guild_storage)); - gstor->storage_status = 0; - return 1; - } - - memcpy(gstor,RFIFOP(fd,12),sizeof(struct guild_storage)); - gstorage->open(sd); - return 0; -} - -// ACK guild_storage saved -int intif_parse_SaveGuildStorage(int fd) -{ - gstorage->saved(/*RFIFOL(fd,2), */RFIFOL(fd,6)); - return 0; -} - -// ACK party creation -int intif_parse_PartyCreated(int fd) -{ - if(battle_config.etc_log) - ShowInfo("intif: party created by account %d\n\n", RFIFOL(fd,2)); - party->created(RFIFOL(fd,2), RFIFOL(fd,6),RFIFOB(fd,10),RFIFOL(fd,11), (char *)RFIFOP(fd,15)); - return 0; -} - -// Receive party info -int intif_parse_PartyInfo(int fd) -{ - if( RFIFOW(fd,2) == 12 ){ - ShowWarning("intif: party noinfo (char_id=%d party_id=%d)\n", RFIFOL(fd,4), RFIFOL(fd,8)); - party->recv_noinfo(RFIFOL(fd,8), RFIFOL(fd,4)); - return 0; - } - - if( RFIFOW(fd,2) != 8+sizeof(struct party) ) - ShowError("intif: party info : data size error (char_id=%d party_id=%d packet_len=%d expected_len=%d)\n", RFIFOL(fd,4), RFIFOL(fd,8), RFIFOW(fd,2), 8+sizeof(struct party)); - party->recv_info((struct party *)RFIFOP(fd,8), RFIFOL(fd,4)); - return 0; -} - -// ACK adding party member -int intif_parse_PartyMemberAdded(int fd) -{ - if(battle_config.etc_log) - ShowInfo("intif: party member added Party (%d), Account(%d), Char(%d)\n",RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10)); - party->member_added(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10), RFIFOB(fd, 14)); - return 0; -} - -// ACK changing party option -int intif_parse_PartyOptionChanged(int fd) -{ - party->optionchanged(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOW(fd,10),RFIFOW(fd,12),RFIFOB(fd,14)); - return 0; -} - -// ACK member leaving party -int intif_parse_PartyMemberWithdraw(int fd) -{ - if(battle_config.etc_log) - ShowInfo("intif: party member withdraw: Party(%d), Account(%d), Char(%d)\n",RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10)); - party->member_withdraw(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10)); - return 0; -} - -// ACK party break -int intif_parse_PartyBroken(int fd) -{ - party->broken(RFIFOL(fd,2)); - return 0; -} - -// ACK party on new map -int intif_parse_PartyMove(int fd) -{ - party->recv_movemap(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOW(fd,14),RFIFOB(fd,16),RFIFOW(fd,17)); - return 0; -} - -// ACK party messages -int intif_parse_PartyMessage(int fd) -{ - party->recv_message(RFIFOL(fd,4),RFIFOL(fd,8),(char *) RFIFOP(fd,12),RFIFOW(fd,2)-12); - return 0; -} - -// ACK guild creation -int intif_parse_GuildCreated(int fd) -{ - guild->created(RFIFOL(fd,2),RFIFOL(fd,6)); - return 0; -} - -// ACK guild infos -int intif_parse_GuildInfo(int fd) -{ - if(RFIFOW(fd,2) == 8) { - ShowWarning("intif: guild noinfo %d\n",RFIFOL(fd,4)); - guild->recv_noinfo(RFIFOL(fd,4)); - return 0; - } - if( RFIFOW(fd,2)!=sizeof(struct guild)+4 ) - ShowError("intif: guild info : data size error Gid: %d recv size: %d Expected size: %d\n",RFIFOL(fd,4),RFIFOW(fd,2),sizeof(struct guild)+4); - guild->recv_info((struct guild *)RFIFOP(fd,4)); - return 0; -} - -// ACK adding guild member -int intif_parse_GuildMemberAdded(int fd) -{ - if(battle_config.etc_log) - ShowInfo("intif: guild member added %d %d %d %d\n",RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOB(fd,14)); - guild->member_added(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOB(fd,14)); - return 0; -} - -// ACK member leaving guild -int intif_parse_GuildMemberWithdraw(int fd) -{ - guild->member_withdraw(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOB(fd,14),(char *)RFIFOP(fd,55),(char *)RFIFOP(fd,15)); - return 0; -} - -// ACK guild member basic info -int intif_parse_GuildMemberInfoShort(int fd) -{ - guild->recv_memberinfoshort(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOB(fd,14),RFIFOW(fd,15),RFIFOW(fd,17)); - return 0; -} - -// ACK guild break -int intif_parse_GuildBroken(int fd) -{ - guild->broken(RFIFOL(fd,2),RFIFOB(fd,6)); - return 0; -} - -// basic guild info change notice -// 0x3839 .w .l .w .?b -int intif_parse_GuildBasicInfoChanged(int fd) -{ - //int len = RFIFOW(fd,2) - 10; - int guild_id = RFIFOL(fd,4); - int type = RFIFOW(fd,8); - //void* data = RFIFOP(fd,10); - - struct guild* g = guild->search(guild_id); - if( g == NULL ) - return 0; - - switch(type) { - case GBI_EXP: g->exp = RFIFOQ(fd,10); break; - case GBI_GUILDLV: g->guild_lv = RFIFOW(fd,10); break; - case GBI_SKILLPOINT: g->skill_point = RFIFOL(fd,10); break; - } - - return 0; -} - -// guild member info change notice -// 0x383a .w .l .l .l .w .?b -int intif_parse_GuildMemberInfoChanged(int fd) -{ - //int len = RFIFOW(fd,2) - 18; - int guild_id = RFIFOL(fd,4); - int account_id = RFIFOL(fd,8); - int char_id = RFIFOL(fd,12); - int type = RFIFOW(fd,16); - //void* data = RFIFOP(fd,18); - - struct guild* g; - int idx; - - g = guild->search(guild_id); - if( g == NULL ) - return 0; - - idx = guild->getindex(g,account_id,char_id); - if( idx == -1 ) - return 0; - - switch( type ) { - case GMI_POSITION: g->member[idx].position = RFIFOW(fd,18); guild->memberposition_changed(g,idx,RFIFOW(fd,18)); break; - case GMI_EXP: g->member[idx].exp = RFIFOQ(fd,18); break; - case GMI_HAIR: g->member[idx].hair = RFIFOW(fd,18); break; - case GMI_HAIR_COLOR: g->member[idx].hair_color = RFIFOW(fd,18); break; - case GMI_GENDER: g->member[idx].gender = RFIFOW(fd,18); break; - case GMI_CLASS: g->member[idx].class_ = RFIFOW(fd,18); break; - case GMI_LEVEL: g->member[idx].lv = RFIFOW(fd,18); break; - } - return 0; -} - -// ACK change of guild title -int intif_parse_GuildPosition(int fd) -{ - if( RFIFOW(fd,2)!=sizeof(struct guild_position)+12 ) - ShowError("intif: guild info : data size error\n %d %d %d",RFIFOL(fd,4),RFIFOW(fd,2),sizeof(struct guild_position)+12); - guild->position_changed(RFIFOL(fd,4),RFIFOL(fd,8),(struct guild_position *)RFIFOP(fd,12)); - return 0; -} - -// ACK change of guild skill update -int intif_parse_GuildSkillUp(int fd) -{ - guild->skillupack(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10)); - return 0; -} - -// ACK change of guild relationship -int intif_parse_GuildAlliance(int fd) -{ - guild->allianceack(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOL(fd,14),RFIFOB(fd,18),(char *) RFIFOP(fd,19),(char *) RFIFOP(fd,43)); - return 0; -} - -// ACK change of guild notice -int intif_parse_GuildNotice(int fd) -{ - guild->notice_changed(RFIFOL(fd,2),(char *) RFIFOP(fd,6),(char *) RFIFOP(fd,66)); - return 0; -} - -// ACK change of guild emblem -int intif_parse_GuildEmblem(int fd) -{ - guild->emblem_changed(RFIFOW(fd,2)-12,RFIFOL(fd,4),RFIFOL(fd,8), (char *)RFIFOP(fd,12)); - return 0; -} - -// ACK guild message -int intif_parse_GuildMessage(int fd) -{ - guild->recv_message(RFIFOL(fd,4),RFIFOL(fd,8),(char *) RFIFOP(fd,12),RFIFOW(fd,2)-12); - return 0; -} - -// Reply guild castle data request -int intif_parse_GuildCastleDataLoad(int fd) -{ - return guild->castledataloadack(RFIFOW(fd,2), (struct guild_castle *)RFIFOP(fd,4)); -} - -// ACK change of guildmaster -int intif_parse_GuildMasterChanged(int fd) -{ - return guild->gm_changed(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10)); -} - -// Request pet creation -int intif_parse_CreatePet(int fd) -{ - pet_get_egg(RFIFOL(fd,2),RFIFOL(fd,7),RFIFOB(fd,6)); - return 0; -} - -// ACK pet data -int intif_parse_RecvPetData(int fd) -{ - struct s_pet p; - int len; - len=RFIFOW(fd,2); - if(sizeof(struct s_pet)!=len-9) { - if(battle_config.etc_log) - ShowError("intif: pet data: data size error %d %d\n",sizeof(struct s_pet),len-9); - } - else{ - memcpy(&p,RFIFOP(fd,9),sizeof(struct s_pet)); - pet_recv_petdata(RFIFOL(fd,4),&p,RFIFOB(fd,8)); - } - - return 0; -} - -// ACK pet save data -int intif_parse_SavePetOk(int fd) -{ - if(RFIFOB(fd,6) == 1) - ShowError("pet data save failure\n"); - - return 0; -} - -// ACK deleting pet -int intif_parse_DeletePetOk(int fd) -{ - if(RFIFOB(fd,2) == 1) - ShowError("pet data delete failure\n"); - - return 0; -} - -// ACK changing name resquest, players,pets,hommon -int intif_parse_ChangeNameOk(int fd) -{ - struct map_session_data *sd = NULL; - if((sd=iMap->id2sd(RFIFOL(fd,2)))==NULL || - sd->status.char_id != RFIFOL(fd,6)) - return 0; - - switch (RFIFOB(fd,10)) { - case 0: //Players [NOT SUPPORTED YET] - break; - case 1: //Pets - pet_change_name_ack(sd, (char*)RFIFOP(fd,12), RFIFOB(fd,11)); - break; - case 2: //Hom - homun->change_name_ack(sd, (char*)RFIFOP(fd,12), RFIFOB(fd,11)); - break; - } - return 0; -} - -//---------------------------------------------------------------- -// Homunculus recv packets [albator] - -int intif_parse_CreateHomunculus(int fd) -{ - int len; - len=RFIFOW(fd,2)-9; - if(sizeof(struct s_homunculus)!=len) { - if(battle_config.etc_log) - ShowError("intif: create homun data: data size error %d != %d\n",sizeof(struct s_homunculus),len); - return 0; - } - homun->recv_data(RFIFOL(fd,4), (struct s_homunculus*)RFIFOP(fd,9), RFIFOB(fd,8)) ; - return 0; -} - -int intif_parse_RecvHomunculusData(int fd) -{ - int len; - - len=RFIFOW(fd,2)-9; - - if(sizeof(struct s_homunculus)!=len) { - if(battle_config.etc_log) - ShowError("intif: homun data: data size error %d %d\n",sizeof(struct s_homunculus),len); - return 0; - } - homun->recv_data(RFIFOL(fd,4), (struct s_homunculus*)RFIFOP(fd,9), RFIFOB(fd,8)); - return 0; -} - -int intif_parse_SaveHomunculusOk(int fd) -{ - if(RFIFOB(fd,6) != 1) - ShowError("homunculus data save failure for account %d\n", RFIFOL(fd,2)); - - return 0; -} - -int intif_parse_DeleteHomunculusOk(int fd) -{ - if(RFIFOB(fd,2) != 1) - ShowError("Homunculus data delete failure\n"); - - return 0; -} - -/************************************** - -QUESTLOG SYSTEM FUNCTIONS - -***************************************/ - -int intif_request_questlog(TBL_PC *sd) -{ - WFIFOHEAD(inter_fd,6); - WFIFOW(inter_fd,0) = 0x3060; - WFIFOL(inter_fd,2) = sd->status.char_id; - WFIFOSET(inter_fd,6); - return 0; -} - -int intif_parse_questlog(int fd) -{ - int char_id = RFIFOL(fd, 4); - int i; - TBL_PC * sd = iMap->charid2sd(char_id); - - //User not online anymore - if(!sd) - return -1; - - sd->avail_quests = sd->num_quests = (RFIFOW(fd, 2)-8)/sizeof(struct quest); - - memset(&sd->quest_log, 0, sizeof(sd->quest_log)); - - for( i = 0; i < sd->num_quests; i++ ) - { - memcpy(&sd->quest_log[i], RFIFOP(fd, i*sizeof(struct quest)+8), sizeof(struct quest)); - - sd->quest_index[i] = quest_search_db(sd->quest_log[i].quest_id); - - if( sd->quest_index[i] < 0 ) - { - ShowError("intif_parse_questlog: quest %d not found in DB.\n",sd->quest_log[i].quest_id); - sd->avail_quests--; - sd->num_quests--; - i--; - continue; - } - - if( sd->quest_log[i].state == Q_COMPLETE ) - sd->avail_quests--; - } - - quest_pc_login(sd); - - return 0; -} - -int intif_parse_questsave(int fd) -{ - int cid = RFIFOL(fd, 2); - TBL_PC *sd = iMap->id2sd(cid); - - if( !RFIFOB(fd, 6) ) - ShowError("intif_parse_questsave: Failed to save quest(s) for character %d!\n", cid); - else if( sd ) - sd->save_quest = false; - - return 0; -} - -int intif_quest_save(TBL_PC *sd) -{ - int len; - - if(CheckForCharServer()) - return 0; - - len = sizeof(struct quest)*sd->num_quests + 8; - - WFIFOHEAD(inter_fd, len); - WFIFOW(inter_fd,0) = 0x3061; - WFIFOW(inter_fd,2) = len; - WFIFOL(inter_fd,4) = sd->status.char_id; - if( sd->num_quests ) - memcpy(WFIFOP(inter_fd,8), &sd->quest_log, sizeof(struct quest)*sd->num_quests); - WFIFOSET(inter_fd, len); - - return 0; -} - -/*========================================== - * MAIL SYSTEM - * By Zephyrus - *==========================================*/ - -/*------------------------------------------ - * Inbox Request - * flag: 0 Update Inbox | 1 OpenMail - *------------------------------------------*/ -int intif_Mail_requestinbox(int char_id, unsigned char flag) -{ - if (CheckForCharServer()) - return 0; - - WFIFOHEAD(inter_fd,7); - WFIFOW(inter_fd,0) = 0x3048; - WFIFOL(inter_fd,2) = char_id; - WFIFOB(inter_fd,6) = flag; - WFIFOSET(inter_fd,7); - - return 0; -} - -int intif_parse_Mail_inboxreceived(int fd) -{ - struct map_session_data *sd; - unsigned char flag = RFIFOB(fd,8); - - sd = iMap->charid2sd(RFIFOL(fd,4)); - - if (sd == NULL) - { - ShowError("intif_parse_Mail_inboxreceived: char not found %d\n",RFIFOL(fd,4)); - return 1; - } - - if (RFIFOW(fd,2) - 9 != sizeof(struct mail_data)) - { - ShowError("intif_parse_Mail_inboxreceived: data size error %d %d\n", RFIFOW(fd,2) - 9, sizeof(struct mail_data)); - return 1; - } - - //FIXME: this operation is not safe [ultramage] - memcpy(&sd->mail.inbox, RFIFOP(fd,9), sizeof(struct mail_data)); - sd->mail.changed = false; // cache is now in sync - - if (flag) - clif->mail_refreshinbox(sd); - else if( battle_config.mail_show_status && ( battle_config.mail_show_status == 1 || sd->mail.inbox.unread ) ) - { - char output[128]; - sprintf(output, msg_txt(510), sd->mail.inbox.unchecked, sd->mail.inbox.unread + sd->mail.inbox.unchecked); - clif->disp_onlyself(sd, output, strlen(output)); - } - return 0; -} -/*------------------------------------------ - * Mail Read - *------------------------------------------*/ -int intif_Mail_read(int mail_id) -{ - if (CheckForCharServer()) - return 0; - - WFIFOHEAD(inter_fd,6); - WFIFOW(inter_fd,0) = 0x3049; - WFIFOL(inter_fd,2) = mail_id; - WFIFOSET(inter_fd,6); - - return 0; -} -/*------------------------------------------ - * Get Attachment - *------------------------------------------*/ -int intif_Mail_getattach(int char_id, int mail_id) -{ - if (CheckForCharServer()) - return 0; - - WFIFOHEAD(inter_fd,10); - WFIFOW(inter_fd,0) = 0x304a; - WFIFOL(inter_fd,2) = char_id; - WFIFOL(inter_fd,6) = mail_id; - WFIFOSET(inter_fd, 10); - - return 0; -} - -int intif_parse_Mail_getattach(int fd) -{ - struct map_session_data *sd; - struct item item; - int zeny = RFIFOL(fd,8); - - sd = iMap->charid2sd( RFIFOL(fd,4) ); - - if (sd == NULL) - { - ShowError("intif_parse_Mail_getattach: char not found %d\n",RFIFOL(fd,4)); - return 1; - } - - if (RFIFOW(fd,2) - 12 != sizeof(struct item)) - { - ShowError("intif_parse_Mail_getattach: data size error %d %d\n", RFIFOW(fd,2) - 16, sizeof(struct item)); - return 1; - } - - memcpy(&item, RFIFOP(fd,12), sizeof(struct item)); - - mail->getattachment(sd, zeny, &item); - return 0; -} -/*------------------------------------------ - * Delete Message - *------------------------------------------*/ -int intif_Mail_delete(int char_id, int mail_id) -{ - if (CheckForCharServer()) - return 0; - - WFIFOHEAD(inter_fd,10); - WFIFOW(inter_fd,0) = 0x304b; - WFIFOL(inter_fd,2) = char_id; - WFIFOL(inter_fd,6) = mail_id; - WFIFOSET(inter_fd,10); - - return 0; -} - -int intif_parse_Mail_delete(int fd) -{ - int char_id = RFIFOL(fd,2); - int mail_id = RFIFOL(fd,6); - bool failed = RFIFOB(fd,10); - - struct map_session_data *sd = iMap->charid2sd(char_id); - if (sd == NULL) - { - ShowError("intif_parse_Mail_delete: char not found %d\n", char_id); - return 1; - } - - if (!failed) - { - int i; - ARR_FIND(0, MAIL_MAX_INBOX, i, sd->mail.inbox.msg[i].id == mail_id); - if( i < MAIL_MAX_INBOX ) - { - memset(&sd->mail.inbox.msg[i], 0, sizeof(struct mail_message)); - sd->mail.inbox.amount--; - } - - if( sd->mail.inbox.full ) - intif_Mail_requestinbox(sd->status.char_id, 1); // Free space is available for new mails - } - - clif->mail_delete(sd->fd, mail_id, failed); - return 0; -} -/*------------------------------------------ - * Return Message - *------------------------------------------*/ -int intif_Mail_return(int char_id, int mail_id) -{ - if (CheckForCharServer()) - return 0; - - WFIFOHEAD(inter_fd,10); - WFIFOW(inter_fd,0) = 0x304c; - WFIFOL(inter_fd,2) = char_id; - WFIFOL(inter_fd,6) = mail_id; - WFIFOSET(inter_fd,10); - - return 0; -} - -int intif_parse_Mail_return(int fd) -{ - struct map_session_data *sd = iMap->charid2sd(RFIFOL(fd,2)); - int mail_id = RFIFOL(fd,6); - short fail = RFIFOB(fd,10); - - if( sd == NULL ) - { - ShowError("intif_parse_Mail_return: char not found %d\n",RFIFOL(fd,2)); - return 1; - } - - if( !fail ) - { - int i; - ARR_FIND(0, MAIL_MAX_INBOX, i, sd->mail.inbox.msg[i].id == mail_id); - if( i < MAIL_MAX_INBOX ) - { - memset(&sd->mail.inbox.msg[i], 0, sizeof(struct mail_message)); - sd->mail.inbox.amount--; - } - - if( sd->mail.inbox.full ) - intif_Mail_requestinbox(sd->status.char_id, 1); // Free space is available for new mails - } - - clif->mail_return(sd->fd, mail_id, fail); - return 0; -} -/*------------------------------------------ - * Send Mail - *------------------------------------------*/ -int intif_Mail_send(int account_id, struct mail_message *msg) -{ - int len = sizeof(struct mail_message) + 8; - - if (CheckForCharServer()) - return 0; - - WFIFOHEAD(inter_fd,len); - WFIFOW(inter_fd,0) = 0x304d; - WFIFOW(inter_fd,2) = len; - WFIFOL(inter_fd,4) = account_id; - memcpy(WFIFOP(inter_fd,8), msg, sizeof(struct mail_message)); - WFIFOSET(inter_fd,len); - - return 1; -} - -static void intif_parse_Mail_send(int fd) -{ - struct mail_message msg; - struct map_session_data *sd; - bool fail; - - if( RFIFOW(fd,2) - 4 != sizeof(struct mail_message) ) - { - ShowError("intif_parse_Mail_send: data size error %d %d\n", RFIFOW(fd,2) - 4, sizeof(struct mail_message)); - return; - } - - memcpy(&msg, RFIFOP(fd,4), sizeof(struct mail_message)); - fail = (msg.id == 0); - - // notify sender - sd = iMap->charid2sd(msg.send_id); - if( sd != NULL ) - { - if( fail ) - mail->deliveryfail(sd, &msg); - else - { - clif->mail_send(sd->fd, false); - if( iMap->save_settings&16 ) - chrif->save(sd, 0); - } - } -} - -static void intif_parse_Mail_new(int fd) -{ - struct map_session_data *sd = iMap->charid2sd(RFIFOL(fd,2)); - int mail_id = RFIFOL(fd,6); - const char* sender_name = (char*)RFIFOP(fd,10); - const char* title = (char*)RFIFOP(fd,34); - - if( sd == NULL ) - return; - - sd->mail.changed = true; - clif->mail_new(sd->fd, mail_id, sender_name, title); -} - -/*========================================== - * AUCTION SYSTEM - * By Zephyrus - *==========================================*/ -int intif_Auction_requestlist(int char_id, short type, int price, const char* searchtext, short page) -{ - int len = NAME_LENGTH + 16; - - if( CheckForCharServer() ) - return 0; - - WFIFOHEAD(inter_fd,len); - WFIFOW(inter_fd,0) = 0x3050; - WFIFOW(inter_fd,2) = len; - WFIFOL(inter_fd,4) = char_id; - WFIFOW(inter_fd,8) = type; - WFIFOL(inter_fd,10) = price; - WFIFOW(inter_fd,14) = page; - memcpy(WFIFOP(inter_fd,16), searchtext, NAME_LENGTH); - WFIFOSET(inter_fd,len); - - return 0; -} - -static void intif_parse_Auction_results(int fd) -{ - struct map_session_data *sd = iMap->charid2sd(RFIFOL(fd,4)); - short count = RFIFOW(fd,8); - short pages = RFIFOW(fd,10); - uint8* data = RFIFOP(fd,12); - - if( sd == NULL ) - return; - - clif->auction_results(sd, count, pages, data); -} - -int intif_Auction_register(struct auction_data *auction) -{ - int len = sizeof(struct auction_data) + 4; - - if( CheckForCharServer() ) - return 0; - - WFIFOHEAD(inter_fd,len); - WFIFOW(inter_fd,0) = 0x3051; - WFIFOW(inter_fd,2) = len; - memcpy(WFIFOP(inter_fd,4), auction, sizeof(struct auction_data)); - WFIFOSET(inter_fd,len); - - return 1; -} - -static void intif_parse_Auction_register(int fd) -{ - struct map_session_data *sd; - struct auction_data auction; - - if( RFIFOW(fd,2) - 4 != sizeof(struct auction_data) ) - { - ShowError("intif_parse_Auction_register: data size error %d %d\n", RFIFOW(fd,2) - 4, sizeof(struct auction_data)); - return; - } - - memcpy(&auction, RFIFOP(fd,4), sizeof(struct auction_data)); - if( (sd = iMap->charid2sd(auction.seller_id)) == NULL ) - return; - - if( auction.auction_id > 0 ) - { - clif->auction_message(sd->fd, 1); // Confirmation Packet ?? - if( iMap->save_settings&32 ) - chrif->save(sd,0); - } - else - { - int zeny = auction.hours*battle_config.auction_feeperhour; - - clif->auction_message(sd->fd, 4); - pc->additem(sd, &auction.item, auction.item.amount, LOG_TYPE_AUCTION); - - pc->getzeny(sd, zeny, LOG_TYPE_AUCTION, NULL); - } -} - -int intif_Auction_cancel(int char_id, unsigned int auction_id) -{ - if( CheckForCharServer() ) - return 0; - - WFIFOHEAD(inter_fd,10); - WFIFOW(inter_fd,0) = 0x3052; - WFIFOL(inter_fd,2) = char_id; - WFIFOL(inter_fd,6) = auction_id; - WFIFOSET(inter_fd,10); - - return 0; -} - -static void intif_parse_Auction_cancel(int fd) -{ - struct map_session_data *sd = iMap->charid2sd(RFIFOL(fd,2)); - int result = RFIFOB(fd,6); - - if( sd == NULL ) - return; - - switch( result ) - { - case 0: clif->auction_message(sd->fd, 2); break; - case 1: clif->auction_close(sd->fd, 2); break; - case 2: clif->auction_close(sd->fd, 1); break; - case 3: clif->auction_message(sd->fd, 3); break; - } -} - -int intif_Auction_close(int char_id, unsigned int auction_id) -{ - if( CheckForCharServer() ) - return 0; - - WFIFOHEAD(inter_fd,10); - WFIFOW(inter_fd,0) = 0x3053; - WFIFOL(inter_fd,2) = char_id; - WFIFOL(inter_fd,6) = auction_id; - WFIFOSET(inter_fd,10); - - return 0; -} - -static void intif_parse_Auction_close(int fd) -{ - struct map_session_data *sd = iMap->charid2sd(RFIFOL(fd,2)); - unsigned char result = RFIFOB(fd,6); - - if( sd == NULL ) - return; - - clif->auction_close(sd->fd, result); - if( result == 0 ) - { - // FIXME: Leeching off a parse function - clif->pAuction_cancelreg(fd, sd); - intif_Auction_requestlist(sd->status.char_id, 6, 0, "", 1); - } -} - -int intif_Auction_bid(int char_id, const char* name, unsigned int auction_id, int bid) -{ - int len = 16 + NAME_LENGTH; - - if( CheckForCharServer() ) - return 0; - - WFIFOHEAD(inter_fd,len); - WFIFOW(inter_fd,0) = 0x3055; - WFIFOW(inter_fd,2) = len; - WFIFOL(inter_fd,4) = char_id; - WFIFOL(inter_fd,8) = auction_id; - WFIFOL(inter_fd,12) = bid; - memcpy(WFIFOP(inter_fd,16), name, NAME_LENGTH); - WFIFOSET(inter_fd,len); - - return 0; -} - -static void intif_parse_Auction_bid(int fd) -{ - struct map_session_data *sd = iMap->charid2sd(RFIFOL(fd,2)); - int bid = RFIFOL(fd,6); - unsigned char result = RFIFOB(fd,10); - - if( sd == NULL ) - return; - - clif->auction_message(sd->fd, result); - if( bid > 0 ) { - pc->getzeny(sd, bid, LOG_TYPE_AUCTION,NULL); - } - if( result == 1 ) { // To update the list, display your buy list - clif->pAuction_cancelreg(fd, sd); - intif_Auction_requestlist(sd->status.char_id, 7, 0, "", 1); - } -} - -// Used to send 'You have won the auction' and 'You failed to won the auction' messages -static void intif_parse_Auction_message(int fd) -{ - struct map_session_data *sd = iMap->charid2sd(RFIFOL(fd,2)); - unsigned char result = RFIFOB(fd,6); - - if( sd == NULL ) - return; - - clif->auction_message(sd->fd, result); -} - -/*========================================== - * Mercenary's System - *------------------------------------------*/ -int intif_mercenary_create(struct s_mercenary *merc) -{ - int size = sizeof(struct s_mercenary) + 4; - - if( CheckForCharServer() ) - return 0; - - WFIFOHEAD(inter_fd,size); - WFIFOW(inter_fd,0) = 0x3070; - WFIFOW(inter_fd,2) = size; - memcpy(WFIFOP(inter_fd,4), merc, sizeof(struct s_mercenary)); - WFIFOSET(inter_fd,size); - return 0; -} - -int intif_parse_mercenary_received(int fd) -{ - int len = RFIFOW(fd,2) - 5; - if( sizeof(struct s_mercenary) != len ) - { - if( battle_config.etc_log ) - ShowError("intif: create mercenary data size error %d != %d\n", sizeof(struct s_mercenary), len); - return 0; - } - - merc_data_received((struct s_mercenary*)RFIFOP(fd,5), RFIFOB(fd,4)); - return 0; -} - -int intif_mercenary_request(int merc_id, int char_id) -{ - if (CheckForCharServer()) - return 0; - - WFIFOHEAD(inter_fd,10); - WFIFOW(inter_fd,0) = 0x3071; - WFIFOL(inter_fd,2) = merc_id; - WFIFOL(inter_fd,6) = char_id; - WFIFOSET(inter_fd,10); - return 0; -} - -int intif_mercenary_delete(int merc_id) -{ - if (CheckForCharServer()) - return 0; - - WFIFOHEAD(inter_fd,6); - WFIFOW(inter_fd,0) = 0x3072; - WFIFOL(inter_fd,2) = merc_id; - WFIFOSET(inter_fd,6); - return 0; -} - -int intif_parse_mercenary_deleted(int fd) -{ - if( RFIFOB(fd,2) != 1 ) - ShowError("Mercenary data delete failure\n"); - - return 0; -} - -int intif_mercenary_save(struct s_mercenary *merc) -{ - int size = sizeof(struct s_mercenary) + 4; - - if( CheckForCharServer() ) - return 0; - - WFIFOHEAD(inter_fd,size); - WFIFOW(inter_fd,0) = 0x3073; - WFIFOW(inter_fd,2) = size; - memcpy(WFIFOP(inter_fd,4), merc, sizeof(struct s_mercenary)); - WFIFOSET(inter_fd,size); - return 0; -} - -int intif_parse_mercenary_saved(int fd) -{ - if( RFIFOB(fd,2) != 1 ) - ShowError("Mercenary data save failure\n"); - - return 0; -} - -/*========================================== - * Elemental's System - *------------------------------------------*/ -int intif_elemental_create(struct s_elemental *ele) -{ - int size = sizeof(struct s_elemental) + 4; - - if( CheckForCharServer() ) - return 0; - - WFIFOHEAD(inter_fd,size); - WFIFOW(inter_fd,0) = 0x307c; - WFIFOW(inter_fd,2) = size; - memcpy(WFIFOP(inter_fd,4), ele, sizeof(struct s_elemental)); - WFIFOSET(inter_fd,size); - return 0; -} - -int intif_parse_elemental_received(int fd) -{ - int len = RFIFOW(fd,2) - 5; - if( sizeof(struct s_elemental) != len ) - { - if( battle_config.etc_log ) - ShowError("intif: create elemental data size error %d != %d\n", sizeof(struct s_elemental), len); - return 0; - } - - elemental->data_received((struct s_elemental*)RFIFOP(fd,5), RFIFOB(fd,4)); - return 0; -} - -int intif_elemental_request(int ele_id, int char_id) -{ - if (CheckForCharServer()) - return 0; - - WFIFOHEAD(inter_fd,10); - WFIFOW(inter_fd,0) = 0x307d; - WFIFOL(inter_fd,2) = ele_id; - WFIFOL(inter_fd,6) = char_id; - WFIFOSET(inter_fd,10); - return 0; -} - -int intif_elemental_delete(int ele_id) -{ - if (CheckForCharServer()) - return 0; - - WFIFOHEAD(inter_fd,6); - WFIFOW(inter_fd,0) = 0x307e; - WFIFOL(inter_fd,2) = ele_id; - WFIFOSET(inter_fd,6); - return 0; -} - -int intif_parse_elemental_deleted(int fd) -{ - if( RFIFOB(fd,2) != 1 ) - ShowError("Elemental data delete failure\n"); - - return 0; -} - -int intif_elemental_save(struct s_elemental *ele) -{ - int size = sizeof(struct s_elemental) + 4; - - if( CheckForCharServer() ) - return 0; - - WFIFOHEAD(inter_fd,size); - WFIFOW(inter_fd,0) = 0x307f; - WFIFOW(inter_fd,2) = size; - memcpy(WFIFOP(inter_fd,4), ele, sizeof(struct s_elemental)); - WFIFOSET(inter_fd,size); - return 0; -} - -int intif_parse_elemental_saved(int fd) -{ - if( RFIFOB(fd,2) != 1 ) - ShowError("Elemental data save failure\n"); - - return 0; -} - -void intif_request_accinfo( int u_fd, int aid, int group_lv, char* query ) { - - - WFIFOHEAD(inter_fd,2 + 4 + 4 + 4 + NAME_LENGTH); - - WFIFOW(inter_fd,0) = 0x3007; - WFIFOL(inter_fd,2) = u_fd; - WFIFOL(inter_fd,6) = aid; - WFIFOL(inter_fd,10) = group_lv; - safestrncpy((char *)WFIFOP(inter_fd,14), query, NAME_LENGTH); - - WFIFOSET(inter_fd,2 + 4 + 4 + 4 + NAME_LENGTH); - - return; -} - -void intif_parse_MessageToFD(int fd) { - int u_fd = RFIFOL(fd,4); - - if( session[u_fd] && session[u_fd]->session_data ) { - int aid = RFIFOL(fd,8); - struct map_session_data * sd = session[u_fd]->session_data; - /* matching e.g. previous fd owner didn't dc during request or is still the same */ - if( sd->bl.id == aid ) { - char msg[512]; - safestrncpy(msg, (char*)RFIFOP(fd,12), RFIFOW(fd,2) - 12); - clif->message(u_fd,msg); - } - - } - - return; -} - -//----------------------------------------------------------------- -// Communication from the inter server -// Return a 0 (false) if there were any errors. -// 1, 2 if there are not enough to return the length of the packet if the packet processing -int intif_parse(int fd) -{ - int packet_len, cmd; - cmd = RFIFOW(fd,0); - // Verify ID of the packet - if(cmd<0x3800 || cmd>=0x3800+(sizeof(packet_len_table)/sizeof(packet_len_table[0])) || - packet_len_table[cmd-0x3800]==0){ - return 0; - } - // Check the length of the packet - packet_len = packet_len_table[cmd-0x3800]; - if(packet_len==-1){ - if(RFIFOREST(fd)<4) - return 2; - packet_len = RFIFOW(fd,2); - } - if((int)RFIFOREST(fd)broadcast(NULL, (char *) RFIFOP(fd,16), packet_len-16, 0, ALL_CLIENT); - else //Color announce. - clif->broadcast2(NULL, (char *) RFIFOP(fd,16), packet_len-16, RFIFOL(fd,4), RFIFOW(fd,8), RFIFOW(fd,10), RFIFOW(fd,12), RFIFOW(fd,14), ALL_CLIENT); - break; - case 0x3801: intif_parse_WisMessage(fd); break; - case 0x3802: intif_parse_WisEnd(fd); break; - case 0x3803: mapif_parse_WisToGM(fd); break; - case 0x3804: intif_parse_Registers(fd); break; - case 0x3806: intif_parse_ChangeNameOk(fd); break; - case 0x3807: intif_parse_MessageToFD(fd); break; - case 0x3818: intif_parse_LoadGuildStorage(fd); break; - case 0x3819: intif_parse_SaveGuildStorage(fd); break; - case 0x3820: intif_parse_PartyCreated(fd); break; - case 0x3821: intif_parse_PartyInfo(fd); break; - case 0x3822: intif_parse_PartyMemberAdded(fd); break; - case 0x3823: intif_parse_PartyOptionChanged(fd); break; - case 0x3824: intif_parse_PartyMemberWithdraw(fd); break; - case 0x3825: intif_parse_PartyMove(fd); break; - case 0x3826: intif_parse_PartyBroken(fd); break; - case 0x3827: intif_parse_PartyMessage(fd); break; - case 0x3830: intif_parse_GuildCreated(fd); break; - case 0x3831: intif_parse_GuildInfo(fd); break; - case 0x3832: intif_parse_GuildMemberAdded(fd); break; - case 0x3834: intif_parse_GuildMemberWithdraw(fd); break; - case 0x3835: intif_parse_GuildMemberInfoShort(fd); break; - case 0x3836: intif_parse_GuildBroken(fd); break; - case 0x3837: intif_parse_GuildMessage(fd); break; - case 0x3839: intif_parse_GuildBasicInfoChanged(fd); break; - case 0x383a: intif_parse_GuildMemberInfoChanged(fd); break; - case 0x383b: intif_parse_GuildPosition(fd); break; - case 0x383c: intif_parse_GuildSkillUp(fd); break; - case 0x383d: intif_parse_GuildAlliance(fd); break; - case 0x383e: intif_parse_GuildNotice(fd); break; - case 0x383f: intif_parse_GuildEmblem(fd); break; - case 0x3840: intif_parse_GuildCastleDataLoad(fd); break; - case 0x3843: intif_parse_GuildMasterChanged(fd); break; - - //Quest system - case 0x3860: intif_parse_questlog(fd); break; - case 0x3861: intif_parse_questsave(fd); break; - -// Mail System - case 0x3848: intif_parse_Mail_inboxreceived(fd); break; - case 0x3849: intif_parse_Mail_new(fd); break; - case 0x384a: intif_parse_Mail_getattach(fd); break; - case 0x384b: intif_parse_Mail_delete(fd); break; - case 0x384c: intif_parse_Mail_return(fd); break; - case 0x384d: intif_parse_Mail_send(fd); break; -// Auction System - case 0x3850: intif_parse_Auction_results(fd); break; - case 0x3851: intif_parse_Auction_register(fd); break; - case 0x3852: intif_parse_Auction_cancel(fd); break; - case 0x3853: intif_parse_Auction_close(fd); break; - case 0x3854: intif_parse_Auction_message(fd); break; - case 0x3855: intif_parse_Auction_bid(fd); break; - -// Mercenary System - case 0x3870: intif_parse_mercenary_received(fd); break; - case 0x3871: intif_parse_mercenary_deleted(fd); break; - case 0x3872: intif_parse_mercenary_saved(fd); break; -// Elemental System - case 0x387c: intif_parse_elemental_received(fd); break; - case 0x387d: intif_parse_elemental_deleted(fd); break; - case 0x387e: intif_parse_elemental_saved(fd); break; - - case 0x3880: intif_parse_CreatePet(fd); break; - case 0x3881: intif_parse_RecvPetData(fd); break; - case 0x3882: intif_parse_SavePetOk(fd); break; - case 0x3883: intif_parse_DeletePetOk(fd); break; - case 0x3890: intif_parse_CreateHomunculus(fd); break; - case 0x3891: intif_parse_RecvHomunculusData(fd); break; - case 0x3892: intif_parse_SaveHomunculusOk(fd); break; - case 0x3893: intif_parse_DeleteHomunculusOk(fd); break; - default: - ShowError("intif_parse : unknown packet %d %x\n",fd,RFIFOW(fd,0)); - return 0; - } - // Skip packet - RFIFOSKIP(fd,packet_len); - return 1; -} +// Copyright (c) Athena Dev Teams - Licensed under GNU GPL +// For more information, see LICENCE in the main folder + +#include "../common/showmsg.h" +#include "../common/socket.h" +#include "../common/timer.h" +#include "../common/nullpo.h" +#include "../common/malloc.h" +#include "../common/strlib.h" +#include "map.h" +#include "battle.h" +#include "chrif.h" +#include "clif.h" +#include "pc.h" +#include "intif.h" +#include "log.h" +#include "storage.h" +#include "party.h" +#include "guild.h" +#include "pet.h" +#include "atcommand.h" +#include "mercenary.h" +#include "homunculus.h" +#include "elemental.h" +#include "mail.h" +#include "quest.h" + +#include +#include +#include +#include +#include +#include + + +static const int packet_len_table[]={ + -1,-1,27,-1, -1, 0,37,-1, 0, 0, 0, 0, 0, 0, 0, 0, //0x3800-0x380f + 0, 0, 0, 0, 0, 0, 0, 0, -1,11, 0, 0, 0, 0, 0, 0, //0x3810 + 39,-1,15,15, 14,19, 7,-1, 0, 0, 0, 0, 0, 0, 0, 0, //0x3820 + 10,-1,15, 0, 79,19, 7,-1, 0,-1,-1,-1, 14,67,186,-1, //0x3830 + -1, 0, 0,14, 0, 0, 0, 0, -1,74,-1,11, 11,-1, 0, 0, //0x3840 + -1,-1, 7, 7, 7,11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3850 Auctions [Zephyrus] + -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3860 Quests [Kevin] [Inkfish] + -1, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 3, 3, 0, //0x3870 Mercenaries [Zephyrus] / Elemental [pakpil] + 11,-1, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3880 + -1,-1, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3890 Homunculus [albator] +}; + +extern int char_fd; // inter server Fd used for char_fd +#define inter_fd char_fd // alias + +//----------------------------------------------------------------- +// Send to inter server + +int CheckForCharServer(void) +{ + return ((char_fd <= 0) || session[char_fd] == NULL || session[char_fd]->wdata == NULL); +} + +// pet +int intif_create_pet(int account_id,int char_id,short pet_class,short pet_lv,short pet_egg_id, + short pet_equip,short intimate,short hungry,char rename_flag,char incuvate,char *pet_name) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd, 24 + NAME_LENGTH); + WFIFOW(inter_fd,0) = 0x3080; + WFIFOL(inter_fd,2) = account_id; + WFIFOL(inter_fd,6) = char_id; + WFIFOW(inter_fd,10) = pet_class; + WFIFOW(inter_fd,12) = pet_lv; + WFIFOW(inter_fd,14) = pet_egg_id; + WFIFOW(inter_fd,16) = pet_equip; + WFIFOW(inter_fd,18) = intimate; + WFIFOW(inter_fd,20) = hungry; + WFIFOB(inter_fd,22) = rename_flag; + WFIFOB(inter_fd,23) = incuvate; + memcpy(WFIFOP(inter_fd,24),pet_name,NAME_LENGTH); + WFIFOSET(inter_fd,24+NAME_LENGTH); + + return 0; +} + +int intif_request_petdata(int account_id,int char_id,int pet_id) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd, 14); + WFIFOW(inter_fd,0) = 0x3081; + WFIFOL(inter_fd,2) = account_id; + WFIFOL(inter_fd,6) = char_id; + WFIFOL(inter_fd,10) = pet_id; + WFIFOSET(inter_fd,14); + + return 0; +} + +int intif_save_petdata(int account_id,struct s_pet *p) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd, sizeof(struct s_pet) + 8); + WFIFOW(inter_fd,0) = 0x3082; + WFIFOW(inter_fd,2) = sizeof(struct s_pet) + 8; + WFIFOL(inter_fd,4) = account_id; + memcpy(WFIFOP(inter_fd,8),p,sizeof(struct s_pet)); + WFIFOSET(inter_fd,WFIFOW(inter_fd,2)); + + return 0; +} + +int intif_delete_petdata(int pet_id) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd,6); + WFIFOW(inter_fd,0) = 0x3083; + WFIFOL(inter_fd,2) = pet_id; + WFIFOSET(inter_fd,6); + + return 1; +} + +int intif_rename(struct map_session_data *sd, int type, char *name) +{ + if (intif->CheckForCharServer()) + return 1; + + WFIFOHEAD(inter_fd,NAME_LENGTH+12); + WFIFOW(inter_fd,0) = 0x3006; + WFIFOL(inter_fd,2) = sd->status.account_id; + WFIFOL(inter_fd,6) = sd->status.char_id; + WFIFOB(inter_fd,10) = type; //Type: 0 - PC, 1 - PET, 2 - HOM + memcpy(WFIFOP(inter_fd,11),name, NAME_LENGTH); + WFIFOSET(inter_fd,NAME_LENGTH+12); + return 0; +} + +// GM Send a message +int intif_broadcast(const char* mes, int len, int type) +{ + int lp = type ? 4 : 0; + + // Send to the local players + clif->broadcast(NULL, mes, len, type, ALL_CLIENT); + + if (intif->CheckForCharServer()) + return 0; + + if (chrif->other_mapserver_count < 1) + return 0; //No need to send. + + WFIFOHEAD(inter_fd, 16 + lp + len); + WFIFOW(inter_fd,0) = 0x3000; + WFIFOW(inter_fd,2) = 16 + lp + len; + WFIFOL(inter_fd,4) = 0xFF000000; // 0xFF000000 color signals standard broadcast + WFIFOW(inter_fd,8) = 0; // fontType not used with standard broadcast + WFIFOW(inter_fd,10) = 0; // fontSize not used with standard broadcast + WFIFOW(inter_fd,12) = 0; // fontAlign not used with standard broadcast + WFIFOW(inter_fd,14) = 0; // fontY not used with standard broadcast + if (type == 0x10) // bc_blue + WFIFOL(inter_fd,16) = 0x65756c62; //If there's "blue" at the beginning of the message, game client will display it in blue instead of yellow. + else if (type == 0x20) // bc_woe + WFIFOL(inter_fd,16) = 0x73737373; //If there's "ssss", game client will recognize message as 'WoE broadcast'. + memcpy(WFIFOP(inter_fd,16 + lp), mes, len); + WFIFOSET(inter_fd, WFIFOW(inter_fd,2)); + return 0; +} + +int intif_broadcast2(const char* mes, int len, unsigned long fontColor, short fontType, short fontSize, short fontAlign, short fontY) +{ + // Send to the local players + clif->broadcast2(NULL, mes, len, fontColor, fontType, fontSize, fontAlign, fontY, ALL_CLIENT); + + if (intif->CheckForCharServer()) + return 0; + + if (chrif->other_mapserver_count < 1) + return 0; //No need to send. + + WFIFOHEAD(inter_fd, 16 + len); + WFIFOW(inter_fd,0) = 0x3000; + WFIFOW(inter_fd,2) = 16 + len; + WFIFOL(inter_fd,4) = fontColor; + WFIFOW(inter_fd,8) = fontType; + WFIFOW(inter_fd,10) = fontSize; + WFIFOW(inter_fd,12) = fontAlign; + WFIFOW(inter_fd,14) = fontY; + memcpy(WFIFOP(inter_fd,16), mes, len); + WFIFOSET(inter_fd, WFIFOW(inter_fd,2)); + return 0; +} + +/// send a message using the main chat system +/// the source of message +/// the message that was sent +int intif_main_message(struct map_session_data* sd, const char* message) +{ + char output[256]; + + nullpo_ret(sd); + + // format the message for main broadcasting + snprintf( output, sizeof(output), msg_txt(386), sd->status.name, message ); + + // send the message using the inter-server broadcast service + intif_broadcast2( output, strlen(output) + 1, 0xFE000000, 0, 0, 0, 0 ); + + // log the chat message + logs->chat( LOG_CHAT_MAINCHAT, 0, sd->status.char_id, sd->status.account_id, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, NULL, message ); + + return 0; +} + +// The transmission of Wisp/Page to inter-server (player not found on this server) +int intif_wis_message(struct map_session_data *sd, char *nick, char *mes, int mes_len) +{ + nullpo_ret(sd); + if (intif->CheckForCharServer()) + return 0; + + if (chrif->other_mapserver_count < 1) + { //Character not found. + clif->wis_end(sd->fd, 1); + return 0; + } + + WFIFOHEAD(inter_fd,mes_len + 52); + WFIFOW(inter_fd,0) = 0x3001; + WFIFOW(inter_fd,2) = mes_len + 52; + memcpy(WFIFOP(inter_fd,4), sd->status.name, NAME_LENGTH); + memcpy(WFIFOP(inter_fd,4+NAME_LENGTH), nick, NAME_LENGTH); + memcpy(WFIFOP(inter_fd,4+2*NAME_LENGTH), mes, mes_len); + WFIFOSET(inter_fd, WFIFOW(inter_fd,2)); + + if (battle_config.etc_log) + ShowInfo("intif_wis_message from %s to %s (message: '%s')\n", sd->status.name, nick, mes); + + return 0; +} + +// The reply of Wisp/page +int intif_wis_replay(int id, int flag) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd,7); + WFIFOW(inter_fd,0) = 0x3002; + WFIFOL(inter_fd,2) = id; + WFIFOB(inter_fd,6) = flag; // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target + WFIFOSET(inter_fd,7); + + if (battle_config.etc_log) + ShowInfo("intif_wis_replay: id: %d, flag:%d\n", id, flag); + + return 0; +} + +// The transmission of GM only Wisp/Page from server to inter-server +int intif_wis_message_to_gm(char *wisp_name, int permission, char *mes) +{ + int mes_len; + if (intif->CheckForCharServer()) + return 0; + mes_len = strlen(mes) + 1; // + null + WFIFOHEAD(inter_fd, mes_len + 32); + WFIFOW(inter_fd,0) = 0x3003; + WFIFOW(inter_fd,2) = mes_len + 32; + memcpy(WFIFOP(inter_fd,4), wisp_name, NAME_LENGTH); + WFIFOL(inter_fd,4+NAME_LENGTH) = permission; + memcpy(WFIFOP(inter_fd,8+NAME_LENGTH), mes, mes_len); + WFIFOSET(inter_fd, WFIFOW(inter_fd,2)); + + if (battle_config.etc_log) + ShowNotice("intif_wis_message_to_gm: from: '%s', required permission: %d, message: '%s'.\n", wisp_name, permission, mes); + + return 0; +} + +int intif_regtostr(char* str, struct global_reg *reg, int qty) +{ + int len =0, i; + + for (i = 0; i < qty; i++) { + len+= sprintf(str+len, "%s", reg[i].str)+1; //We add 1 to consider the '\0' in place. + len+= sprintf(str+len, "%s", reg[i].value)+1; + } + return len; +} + +//Request for saving registry values. +int intif_saveregistry(struct map_session_data *sd, int type) +{ + struct global_reg *reg; + int count; + int i, p; + + if (intif->CheckForCharServer()) + return -1; + + switch (type) { + case 3: //Character reg + reg = sd->save_reg.global; + count = sd->save_reg.global_num; + sd->state.reg_dirty &= ~0x4; + break; + case 2: //Account reg + reg = sd->save_reg.account; + count = sd->save_reg.account_num; + sd->state.reg_dirty &= ~0x2; + break; + case 1: //Account2 reg + reg = sd->save_reg.account2; + count = sd->save_reg.account2_num; + sd->state.reg_dirty &= ~0x1; + break; + default: //Broken code? + ShowError("intif_saveregistry: Invalid type %d\n", type); + return -1; + } + WFIFOHEAD(inter_fd, 288 * MAX_REG_NUM+13); + WFIFOW(inter_fd,0)=0x3004; + WFIFOL(inter_fd,4)=sd->status.account_id; + WFIFOL(inter_fd,8)=sd->status.char_id; + WFIFOB(inter_fd,12)=type; + for( p = 13, i = 0; i < count; i++ ) { + if (reg[i].str[0] != '\0' && reg[i].value[0] != '\0') { + p+= sprintf((char*)WFIFOP(inter_fd,p), "%s", reg[i].str)+1; //We add 1 to consider the '\0' in place. + p+= sprintf((char*)WFIFOP(inter_fd,p), "%s", reg[i].value)+1; + } + } + WFIFOW(inter_fd,2)=p; + WFIFOSET(inter_fd,WFIFOW(inter_fd,2)); + return 0; +} + +//Request the registries for this player. +int intif_request_registry(struct map_session_data *sd, int flag) +{ + nullpo_ret(sd); + + sd->save_reg.account2_num = -1; + sd->save_reg.account_num = -1; + sd->save_reg.global_num = -1; + + if (intif->CheckForCharServer()) + return 0; + + WFIFOHEAD(inter_fd,6); + WFIFOW(inter_fd,0) = 0x3005; + WFIFOL(inter_fd,2) = sd->status.account_id; + WFIFOL(inter_fd,6) = sd->status.char_id; + WFIFOB(inter_fd,10) = (flag&1?1:0); //Request Acc Reg 2 + WFIFOB(inter_fd,11) = (flag&2?1:0); //Request Acc Reg + WFIFOB(inter_fd,12) = (flag&4?1:0); //Request Char Reg + WFIFOSET(inter_fd,13); + + return 0; +} + +int intif_request_guild_storage(int account_id,int guild_id) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd,10); + WFIFOW(inter_fd,0) = 0x3018; + WFIFOL(inter_fd,2) = account_id; + WFIFOL(inter_fd,6) = guild_id; + WFIFOSET(inter_fd,10); + return 0; +} +int intif_send_guild_storage(int account_id,struct guild_storage *gstor) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd,sizeof(struct guild_storage)+12); + WFIFOW(inter_fd,0) = 0x3019; + WFIFOW(inter_fd,2) = (unsigned short)sizeof(struct guild_storage)+12; + WFIFOL(inter_fd,4) = account_id; + WFIFOL(inter_fd,8) = gstor->guild_id; + memcpy( WFIFOP(inter_fd,12),gstor, sizeof(struct guild_storage) ); + WFIFOSET(inter_fd,WFIFOW(inter_fd,2)); + return 0; +} + +// Party creation request +int intif_create_party(struct party_member *member,char *name,int item,int item2) +{ + if (intif->CheckForCharServer()) + return 0; + nullpo_ret(member); + + WFIFOHEAD(inter_fd,64); + WFIFOW(inter_fd,0) = 0x3020; + WFIFOW(inter_fd,2) = 30+sizeof(struct party_member); + memcpy(WFIFOP(inter_fd,4),name, NAME_LENGTH); + WFIFOB(inter_fd,28)= item; + WFIFOB(inter_fd,29)= item2; + memcpy(WFIFOP(inter_fd,30), member, sizeof(struct party_member)); + WFIFOSET(inter_fd,WFIFOW(inter_fd, 2)); + return 0; +} + +// Party information request +int intif_request_partyinfo(int party_id, int char_id) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd,10); + WFIFOW(inter_fd,0) = 0x3021; + WFIFOL(inter_fd,2) = party_id; + WFIFOL(inter_fd,6) = char_id; + WFIFOSET(inter_fd,10); + return 0; +} + +// Request to add a member to party +int intif_party_addmember(int party_id,struct party_member *member) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd,42); + WFIFOW(inter_fd,0)=0x3022; + WFIFOW(inter_fd,2)=8+sizeof(struct party_member); + WFIFOL(inter_fd,4)=party_id; + memcpy(WFIFOP(inter_fd,8),member,sizeof(struct party_member)); + WFIFOSET(inter_fd,WFIFOW(inter_fd, 2)); + return 1; +} + +// Request to change party configuration (exp,item share) +int intif_party_changeoption(int party_id,int account_id,int exp,int item) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd,14); + WFIFOW(inter_fd,0)=0x3023; + WFIFOL(inter_fd,2)=party_id; + WFIFOL(inter_fd,6)=account_id; + WFIFOW(inter_fd,10)=exp; + WFIFOW(inter_fd,12)=item; + WFIFOSET(inter_fd,14); + return 0; +} + +// Request to leave party +int intif_party_leave(int party_id,int account_id, int char_id) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd,14); + WFIFOW(inter_fd,0)=0x3024; + WFIFOL(inter_fd,2)=party_id; + WFIFOL(inter_fd,6)=account_id; + WFIFOL(inter_fd,10)=char_id; + WFIFOSET(inter_fd,14); + return 0; +} + +// Request keeping party for new map ?? +int intif_party_changemap(struct map_session_data *sd,int online) +{ + int16 m, mapindex; + + if (intif->CheckForCharServer()) + return 0; + if(!sd) + return 0; + + if( (m=iMap->mapindex2mapid(sd->mapindex)) >= 0 && map[m].instance_id >= 0 ) + mapindex = map[map[m].instance_src_map].index; + else + mapindex = sd->mapindex; + + WFIFOHEAD(inter_fd,19); + WFIFOW(inter_fd,0)=0x3025; + WFIFOL(inter_fd,2)=sd->status.party_id; + WFIFOL(inter_fd,6)=sd->status.account_id; + WFIFOL(inter_fd,10)=sd->status.char_id; + WFIFOW(inter_fd,14)=mapindex; + WFIFOB(inter_fd,16)=online; + WFIFOW(inter_fd,17)=sd->status.base_level; + WFIFOSET(inter_fd,19); + return 1; +} + +// Request breaking party +int intif_break_party(int party_id) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd,6); + WFIFOW(inter_fd,0)=0x3026; + WFIFOL(inter_fd,2)=party_id; + WFIFOSET(inter_fd,6); + return 0; +} + +// Sending party chat +int intif_party_message(int party_id,int account_id,const char *mes,int len) +{ + if (intif->CheckForCharServer()) + return 0; + + if (chrif->other_mapserver_count < 1) + return 0; //No need to send. + + WFIFOHEAD(inter_fd,len + 12); + WFIFOW(inter_fd,0)=0x3027; + WFIFOW(inter_fd,2)=len+12; + WFIFOL(inter_fd,4)=party_id; + WFIFOL(inter_fd,8)=account_id; + memcpy(WFIFOP(inter_fd,12),mes,len); + WFIFOSET(inter_fd,len+12); + return 0; +} + +// Request a new leader for party +int intif_party_leaderchange(int party_id,int account_id,int char_id) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd,14); + WFIFOW(inter_fd,0)=0x3029; + WFIFOL(inter_fd,2)=party_id; + WFIFOL(inter_fd,6)=account_id; + WFIFOL(inter_fd,10)=char_id; + WFIFOSET(inter_fd,14); + return 0; +} + +// Request a Guild creation +int intif_guild_create(const char *name,const struct guild_member *master) +{ + if (intif->CheckForCharServer()) + return 0; + nullpo_ret(master); + + WFIFOHEAD(inter_fd,sizeof(struct guild_member)+(8+NAME_LENGTH)); + WFIFOW(inter_fd,0)=0x3030; + WFIFOW(inter_fd,2)=sizeof(struct guild_member)+(8+NAME_LENGTH); + WFIFOL(inter_fd,4)=master->account_id; + memcpy(WFIFOP(inter_fd,8),name,NAME_LENGTH); + memcpy(WFIFOP(inter_fd,8+NAME_LENGTH),master,sizeof(struct guild_member)); + WFIFOSET(inter_fd,WFIFOW(inter_fd,2)); + return 0; +} + +// Request Guild information +int intif_guild_request_info(int guild_id) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd,6); + WFIFOW(inter_fd,0) = 0x3031; + WFIFOL(inter_fd,2) = guild_id; + WFIFOSET(inter_fd,6); + return 0; +} + +// Request to add member to the guild +int intif_guild_addmember(int guild_id,struct guild_member *m) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd,sizeof(struct guild_member)+8); + WFIFOW(inter_fd,0) = 0x3032; + WFIFOW(inter_fd,2) = sizeof(struct guild_member)+8; + WFIFOL(inter_fd,4) = guild_id; + memcpy(WFIFOP(inter_fd,8),m,sizeof(struct guild_member)); + WFIFOSET(inter_fd,WFIFOW(inter_fd,2)); + return 0; +} + +// Request a new leader for guild +int intif_guild_change_gm(int guild_id, const char* name, int len) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd, len + 8); + WFIFOW(inter_fd, 0)=0x3033; + WFIFOW(inter_fd, 2)=len+8; + WFIFOL(inter_fd, 4)=guild_id; + memcpy(WFIFOP(inter_fd,8),name,len); + WFIFOSET(inter_fd,len+8); + return 0; +} + +// Request to leave guild +int intif_guild_leave(int guild_id,int account_id,int char_id,int flag,const char *mes) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd, 55); + WFIFOW(inter_fd, 0) = 0x3034; + WFIFOL(inter_fd, 2) = guild_id; + WFIFOL(inter_fd, 6) = account_id; + WFIFOL(inter_fd,10) = char_id; + WFIFOB(inter_fd,14) = flag; + safestrncpy((char*)WFIFOP(inter_fd,15),mes,40); + WFIFOSET(inter_fd,55); + return 0; +} + +//Update request / Lv online status of the guild members +int intif_guild_memberinfoshort(int guild_id,int account_id,int char_id,int online,int lv,int class_) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd, 19); + WFIFOW(inter_fd, 0) = 0x3035; + WFIFOL(inter_fd, 2) = guild_id; + WFIFOL(inter_fd, 6) = account_id; + WFIFOL(inter_fd,10) = char_id; + WFIFOB(inter_fd,14) = online; + WFIFOW(inter_fd,15) = lv; + WFIFOW(inter_fd,17) = class_; + WFIFOSET(inter_fd,19); + return 0; +} + +//Guild disbanded notification +int intif_guild_break(int guild_id) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd, 6); + WFIFOW(inter_fd, 0) = 0x3036; + WFIFOL(inter_fd, 2) = guild_id; + WFIFOSET(inter_fd,6); + return 0; +} + +// Send a guild message +int intif_guild_message(int guild_id,int account_id,const char *mes,int len) +{ + if (intif->CheckForCharServer()) + return 0; + + if (chrif->other_mapserver_count < 1) + return 0; //No need to send. + + WFIFOHEAD(inter_fd, len + 12); + WFIFOW(inter_fd,0)=0x3037; + WFIFOW(inter_fd,2)=len+12; + WFIFOL(inter_fd,4)=guild_id; + WFIFOL(inter_fd,8)=account_id; + memcpy(WFIFOP(inter_fd,12),mes,len); + WFIFOSET(inter_fd,len+12); + + return 0; +} + +// Request a change of Guild basic information +int intif_guild_change_basicinfo(int guild_id,int type,const void *data,int len) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd, len + 10); + WFIFOW(inter_fd,0)=0x3039; + WFIFOW(inter_fd,2)=len+10; + WFIFOL(inter_fd,4)=guild_id; + WFIFOW(inter_fd,8)=type; + memcpy(WFIFOP(inter_fd,10),data,len); + WFIFOSET(inter_fd,len+10); + return 0; +} + +// Request a change of Guild member information +int intif_guild_change_memberinfo(int guild_id,int account_id,int char_id, + int type,const void *data,int len) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd, len + 18); + WFIFOW(inter_fd, 0)=0x303a; + WFIFOW(inter_fd, 2)=len+18; + WFIFOL(inter_fd, 4)=guild_id; + WFIFOL(inter_fd, 8)=account_id; + WFIFOL(inter_fd,12)=char_id; + WFIFOW(inter_fd,16)=type; + memcpy(WFIFOP(inter_fd,18),data,len); + WFIFOSET(inter_fd,len+18); + return 0; +} + +// Request a change of Guild title +int intif_guild_position(int guild_id,int idx,struct guild_position *p) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd, sizeof(struct guild_position)+12); + WFIFOW(inter_fd,0)=0x303b; + WFIFOW(inter_fd,2)=sizeof(struct guild_position)+12; + WFIFOL(inter_fd,4)=guild_id; + WFIFOL(inter_fd,8)=idx; + memcpy(WFIFOP(inter_fd,12),p,sizeof(struct guild_position)); + WFIFOSET(inter_fd,WFIFOW(inter_fd,2)); + return 0; +} + +// Request an update of Guildskill skill_id +int intif_guild_skillup(int guild_id, uint16 skill_id, int account_id, int max) +{ + if( intif->CheckForCharServer() ) + return 0; + WFIFOHEAD(inter_fd, 18); + WFIFOW(inter_fd, 0) = 0x303c; + WFIFOL(inter_fd, 2) = guild_id; + WFIFOL(inter_fd, 6) = skill_id; + WFIFOL(inter_fd, 10) = account_id; + WFIFOL(inter_fd, 14) = max; + WFIFOSET(inter_fd, 18); + return 0; +} + +// Request a new guild relationship +int intif_guild_alliance(int guild_id1,int guild_id2,int account_id1,int account_id2,int flag) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd,19); + WFIFOW(inter_fd, 0)=0x303d; + WFIFOL(inter_fd, 2)=guild_id1; + WFIFOL(inter_fd, 6)=guild_id2; + WFIFOL(inter_fd,10)=account_id1; + WFIFOL(inter_fd,14)=account_id2; + WFIFOB(inter_fd,18)=flag; + WFIFOSET(inter_fd,19); + return 0; +} + +// Request to change guild notice +int intif_guild_notice(int guild_id,const char *mes1,const char *mes2) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd,186); + WFIFOW(inter_fd,0)=0x303e; + WFIFOL(inter_fd,2)=guild_id; + memcpy(WFIFOP(inter_fd,6),mes1,MAX_GUILDMES1); + memcpy(WFIFOP(inter_fd,66),mes2,MAX_GUILDMES2); + WFIFOSET(inter_fd,186); + return 0; +} + +// Request to change guild emblem +int intif_guild_emblem(int guild_id,int len,const char *data) +{ + if (intif->CheckForCharServer()) + return 0; + if(guild_id<=0 || len<0 || len>2000) + return 0; + WFIFOHEAD(inter_fd,len + 12); + WFIFOW(inter_fd,0)=0x303f; + WFIFOW(inter_fd,2)=len+12; + WFIFOL(inter_fd,4)=guild_id; + WFIFOL(inter_fd,8)=0; + memcpy(WFIFOP(inter_fd,12),data,len); + WFIFOSET(inter_fd,len+12); + return 0; +} + +/** + * Requests guild castles data from char-server. + * @param num Number of castles, size of castle_ids array. + * @param castle_ids Pointer to array of castle IDs. + */ +int intif_guild_castle_dataload(int num, int *castle_ids) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd, 4 + num * sizeof(int)); + WFIFOW(inter_fd, 0) = 0x3040; + WFIFOW(inter_fd, 2) = 4 + num * sizeof(int); + memcpy(WFIFOP(inter_fd, 4), castle_ids, num * sizeof(int)); + WFIFOSET(inter_fd, WFIFOW(inter_fd, 2)); + return 1; +} + + +// Request change castle guild owner and save data +int intif_guild_castle_datasave(int castle_id,int index, int value) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd,9); + WFIFOW(inter_fd,0)=0x3041; + WFIFOW(inter_fd,2)=castle_id; + WFIFOB(inter_fd,4)=index; + WFIFOL(inter_fd,5)=value; + WFIFOSET(inter_fd,9); + return 1; +} + +//----------------------------------------------------------------- +// Homunculus Packets send to Inter server [albator] +//----------------------------------------------------------------- + +int intif_homunculus_create(int account_id, struct s_homunculus *sh) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd, sizeof(struct s_homunculus)+8); + WFIFOW(inter_fd,0) = 0x3090; + WFIFOW(inter_fd,2) = sizeof(struct s_homunculus)+8; + WFIFOL(inter_fd,4) = account_id; + memcpy(WFIFOP(inter_fd,8),sh,sizeof(struct s_homunculus)); + WFIFOSET(inter_fd, WFIFOW(inter_fd,2)); + return 0; +} + +bool intif_homunculus_requestload(int account_id, int homun_id) { + if (intif->CheckForCharServer()) + return false; + WFIFOHEAD(inter_fd, 10); + WFIFOW(inter_fd,0) = 0x3091; + WFIFOL(inter_fd,2) = account_id; + WFIFOL(inter_fd,6) = homun_id; + WFIFOSET(inter_fd, 10); + return true; +} + +int intif_homunculus_requestsave(int account_id, struct s_homunculus* sh) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd, sizeof(struct s_homunculus)+8); + WFIFOW(inter_fd,0) = 0x3092; + WFIFOW(inter_fd,2) = sizeof(struct s_homunculus)+8; + WFIFOL(inter_fd,4) = account_id; + memcpy(WFIFOP(inter_fd,8),sh,sizeof(struct s_homunculus)); + WFIFOSET(inter_fd, WFIFOW(inter_fd,2)); + return 0; + +} + +int intif_homunculus_requestdelete(int homun_id) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd, 6); + WFIFOW(inter_fd, 0) = 0x3093; + WFIFOL(inter_fd,2) = homun_id; + WFIFOSET(inter_fd,6); + return 0; + +} + + +//----------------------------------------------------------------- +// Packets receive from inter server + +// Wisp/Page reception // rewritten by [Yor] +int intif_parse_WisMessage(int fd) +{ + struct map_session_data* sd; + char *wisp_source; + char name[NAME_LENGTH]; + int id, i; + + id=RFIFOL(fd,4); + + safestrncpy(name, (char*)RFIFOP(fd,32), NAME_LENGTH); + sd = iMap->nick2sd(name); + if(sd == NULL || strcmp(sd->status.name, name) != 0) + { //Not found + intif_wis_replay(id,1); + return 0; + } + if(sd->state.ignoreAll) { + intif_wis_replay(id, 2); + return 0; + } + wisp_source = (char *) RFIFOP(fd,8); // speed up [Yor] + for(i=0; i < MAX_IGNORE_LIST && + sd->ignore[i].name[0] != '\0' && + strcmp(sd->ignore[i].name, wisp_source) != 0 + ; i++); + + if (i < MAX_IGNORE_LIST && sd->ignore[i].name[0] != '\0') + { //Ignored + intif_wis_replay(id, 2); + return 0; + } + //Success to send whisper. + clif->wis_message(sd->fd, wisp_source, (char*)RFIFOP(fd,56),RFIFOW(fd,2)-56); + intif_wis_replay(id,0); // succes + return 0; +} + +// Wisp/page transmission result reception +int intif_parse_WisEnd(int fd) +{ + struct map_session_data* sd; + + if (battle_config.etc_log) + ShowInfo("intif_parse_wisend: player: %s, flag: %d\n", RFIFOP(fd,2), RFIFOB(fd,26)); // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target + sd = (struct map_session_data *)iMap->nick2sd((char *) RFIFOP(fd,2)); + if (sd != NULL) + clif->wis_end(sd->fd, RFIFOB(fd,26)); + + return 0; +} + +static int mapif_parse_WisToGM_sub(struct map_session_data* sd,va_list va) +{ + int permission = va_arg(va, int); + char *wisp_name; + char *message; + int len; + + if (!pc_has_permission(sd, permission)) + return 0; + wisp_name = va_arg(va, char*); + message = va_arg(va, char*); + len = va_arg(va, int); + clif->wis_message(sd->fd, wisp_name, message, len); + return 1; +} + +// Received wisp message from map-server via char-server for ALL gm +// 0x3003/0x3803 .w .24B .l .?B +int mapif_parse_WisToGM(int fd) +{ + int permission, mes_len; + char Wisp_name[NAME_LENGTH]; + char mbuf[255]; + char *message; + + mes_len = RFIFOW(fd,2) - 32; + message = (char *) (mes_len >= 255 ? (char *) aMalloc(mes_len) : mbuf); + + permission = RFIFOL(fd,28); + safestrncpy(Wisp_name, (char*)RFIFOP(fd,4), NAME_LENGTH); + safestrncpy(message, (char*)RFIFOP(fd,32), mes_len); + // information is sent to all online GM + iMap->map_foreachpc(mapif_parse_WisToGM_sub, permission, Wisp_name, message, mes_len); + + if (message != mbuf) + aFree(message); + return 0; +} + +// Request player registre +int intif_parse_Registers(int fd) +{ + int j,p,len,max, flag; + struct map_session_data *sd; + struct global_reg *reg; + int *qty; + int account_id = RFIFOL(fd,4), char_id = RFIFOL(fd,8); + struct auth_node *node = chrif->auth_check(account_id, char_id, ST_LOGIN); + if (node) + sd = node->sd; + else { //Normally registries should arrive for in log-in chars. + sd = iMap->id2sd(account_id); + if (sd && RFIFOB(fd,12) == 3 && sd->status.char_id != char_id) + sd = NULL; //Character registry from another character. + } + if (!sd) return 1; + + flag = (sd->save_reg.global_num == -1 || sd->save_reg.account_num == -1 || sd->save_reg.account2_num == -1); + + switch (RFIFOB(fd,12)) { + case 3: //Character Registry + reg = sd->save_reg.global; + qty = &sd->save_reg.global_num; + max = GLOBAL_REG_NUM; + break; + case 2: //Account Registry + reg = sd->save_reg.account; + qty = &sd->save_reg.account_num; + max = ACCOUNT_REG_NUM; + break; + case 1: //Account2 Registry + reg = sd->save_reg.account2; + qty = &sd->save_reg.account2_num; + max = ACCOUNT_REG2_NUM; + break; + default: + ShowError("intif_parse_Registers: Unrecognized type %d\n",RFIFOB(fd,12)); + return 0; + } + for(j=0,p=13;jsave_reg.global_num > -1 && sd->save_reg.account_num > -1 && sd->save_reg.account2_num > -1) + pc->reg_received(sd); //Received all registry values, execute init scripts and what-not. [Skotlex] + return 1; +} + +int intif_parse_LoadGuildStorage(int fd) +{ + struct guild_storage *gstor; + struct map_session_data *sd; + int guild_id; + + guild_id = RFIFOL(fd,8); + if(guild_id <= 0) + return 1; + sd=iMap->id2sd( RFIFOL(fd,4) ); + if(sd==NULL){ + ShowError("intif_parse_LoadGuildStorage: user not found %d\n",RFIFOL(fd,4)); + return 1; + } + gstor=gstorage->id2storage(guild_id); + if(!gstor) { + ShowWarning("intif_parse_LoadGuildStorage: error guild_id %d not exist\n",guild_id); + return 1; + } + if (gstor->storage_status == 1) { // Already open.. lets ignore this update + ShowWarning("intif_parse_LoadGuildStorage: storage received for a client already open (User %d:%d)\n", sd->status.account_id, sd->status.char_id); + return 1; + } + if (gstor->dirty) { // Already have storage, and it has been modified and not saved yet! Exploit! [Skotlex] + ShowWarning("intif_parse_LoadGuildStorage: received storage for an already modified non-saved storage! (User %d:%d)\n", sd->status.account_id, sd->status.char_id); + return 1; + } + if( RFIFOW(fd,2)-12 != sizeof(struct guild_storage) ){ + ShowError("intif_parse_LoadGuildStorage: data size error %d %d\n",RFIFOW(fd,2)-12 , sizeof(struct guild_storage)); + gstor->storage_status = 0; + return 1; + } + + memcpy(gstor,RFIFOP(fd,12),sizeof(struct guild_storage)); + gstorage->open(sd); + return 0; +} + +// ACK guild_storage saved +int intif_parse_SaveGuildStorage(int fd) +{ + gstorage->saved(/*RFIFOL(fd,2), */RFIFOL(fd,6)); + return 0; +} + +// ACK party creation +int intif_parse_PartyCreated(int fd) +{ + if(battle_config.etc_log) + ShowInfo("intif: party created by account %d\n\n", RFIFOL(fd,2)); + party->created(RFIFOL(fd,2), RFIFOL(fd,6),RFIFOB(fd,10),RFIFOL(fd,11), (char *)RFIFOP(fd,15)); + return 0; +} + +// Receive party info +int intif_parse_PartyInfo(int fd) +{ + if( RFIFOW(fd,2) == 12 ){ + ShowWarning("intif: party noinfo (char_id=%d party_id=%d)\n", RFIFOL(fd,4), RFIFOL(fd,8)); + party->recv_noinfo(RFIFOL(fd,8), RFIFOL(fd,4)); + return 0; + } + + if( RFIFOW(fd,2) != 8+sizeof(struct party) ) + ShowError("intif: party info : data size error (char_id=%d party_id=%d packet_len=%d expected_len=%d)\n", RFIFOL(fd,4), RFIFOL(fd,8), RFIFOW(fd,2), 8+sizeof(struct party)); + party->recv_info((struct party *)RFIFOP(fd,8), RFIFOL(fd,4)); + return 0; +} + +// ACK adding party member +int intif_parse_PartyMemberAdded(int fd) +{ + if(battle_config.etc_log) + ShowInfo("intif: party member added Party (%d), Account(%d), Char(%d)\n",RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10)); + party->member_added(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10), RFIFOB(fd, 14)); + return 0; +} + +// ACK changing party option +int intif_parse_PartyOptionChanged(int fd) +{ + party->optionchanged(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOW(fd,10),RFIFOW(fd,12),RFIFOB(fd,14)); + return 0; +} + +// ACK member leaving party +int intif_parse_PartyMemberWithdraw(int fd) +{ + if(battle_config.etc_log) + ShowInfo("intif: party member withdraw: Party(%d), Account(%d), Char(%d)\n",RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10)); + party->member_withdraw(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10)); + return 0; +} + +// ACK party break +int intif_parse_PartyBroken(int fd) +{ + party->broken(RFIFOL(fd,2)); + return 0; +} + +// ACK party on new map +int intif_parse_PartyMove(int fd) +{ + party->recv_movemap(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOW(fd,14),RFIFOB(fd,16),RFIFOW(fd,17)); + return 0; +} + +// ACK party messages +int intif_parse_PartyMessage(int fd) +{ + party->recv_message(RFIFOL(fd,4),RFIFOL(fd,8),(char *) RFIFOP(fd,12),RFIFOW(fd,2)-12); + return 0; +} + +// ACK guild creation +int intif_parse_GuildCreated(int fd) +{ + guild->created(RFIFOL(fd,2),RFIFOL(fd,6)); + return 0; +} + +// ACK guild infos +int intif_parse_GuildInfo(int fd) +{ + if(RFIFOW(fd,2) == 8) { + ShowWarning("intif: guild noinfo %d\n",RFIFOL(fd,4)); + guild->recv_noinfo(RFIFOL(fd,4)); + return 0; + } + if( RFIFOW(fd,2)!=sizeof(struct guild)+4 ) + ShowError("intif: guild info : data size error Gid: %d recv size: %d Expected size: %d\n",RFIFOL(fd,4),RFIFOW(fd,2),sizeof(struct guild)+4); + guild->recv_info((struct guild *)RFIFOP(fd,4)); + return 0; +} + +// ACK adding guild member +int intif_parse_GuildMemberAdded(int fd) +{ + if(battle_config.etc_log) + ShowInfo("intif: guild member added %d %d %d %d\n",RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOB(fd,14)); + guild->member_added(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOB(fd,14)); + return 0; +} + +// ACK member leaving guild +int intif_parse_GuildMemberWithdraw(int fd) +{ + guild->member_withdraw(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOB(fd,14),(char *)RFIFOP(fd,55),(char *)RFIFOP(fd,15)); + return 0; +} + +// ACK guild member basic info +int intif_parse_GuildMemberInfoShort(int fd) +{ + guild->recv_memberinfoshort(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOB(fd,14),RFIFOW(fd,15),RFIFOW(fd,17)); + return 0; +} + +// ACK guild break +int intif_parse_GuildBroken(int fd) +{ + guild->broken(RFIFOL(fd,2),RFIFOB(fd,6)); + return 0; +} + +// basic guild info change notice +// 0x3839 .w .l .w .?b +int intif_parse_GuildBasicInfoChanged(int fd) +{ + //int len = RFIFOW(fd,2) - 10; + int guild_id = RFIFOL(fd,4); + int type = RFIFOW(fd,8); + //void* data = RFIFOP(fd,10); + + struct guild* g = guild->search(guild_id); + if( g == NULL ) + return 0; + + switch(type) { + case GBI_EXP: g->exp = RFIFOQ(fd,10); break; + case GBI_GUILDLV: g->guild_lv = RFIFOW(fd,10); break; + case GBI_SKILLPOINT: g->skill_point = RFIFOL(fd,10); break; + } + + return 0; +} + +// guild member info change notice +// 0x383a .w .l .l .l .w .?b +int intif_parse_GuildMemberInfoChanged(int fd) +{ + //int len = RFIFOW(fd,2) - 18; + int guild_id = RFIFOL(fd,4); + int account_id = RFIFOL(fd,8); + int char_id = RFIFOL(fd,12); + int type = RFIFOW(fd,16); + //void* data = RFIFOP(fd,18); + + struct guild* g; + int idx; + + g = guild->search(guild_id); + if( g == NULL ) + return 0; + + idx = guild->getindex(g,account_id,char_id); + if( idx == -1 ) + return 0; + + switch( type ) { + case GMI_POSITION: g->member[idx].position = RFIFOW(fd,18); guild->memberposition_changed(g,idx,RFIFOW(fd,18)); break; + case GMI_EXP: g->member[idx].exp = RFIFOQ(fd,18); break; + case GMI_HAIR: g->member[idx].hair = RFIFOW(fd,18); break; + case GMI_HAIR_COLOR: g->member[idx].hair_color = RFIFOW(fd,18); break; + case GMI_GENDER: g->member[idx].gender = RFIFOW(fd,18); break; + case GMI_CLASS: g->member[idx].class_ = RFIFOW(fd,18); break; + case GMI_LEVEL: g->member[idx].lv = RFIFOW(fd,18); break; + } + return 0; +} + +// ACK change of guild title +int intif_parse_GuildPosition(int fd) +{ + if( RFIFOW(fd,2)!=sizeof(struct guild_position)+12 ) + ShowError("intif: guild info : data size error\n %d %d %d",RFIFOL(fd,4),RFIFOW(fd,2),sizeof(struct guild_position)+12); + guild->position_changed(RFIFOL(fd,4),RFIFOL(fd,8),(struct guild_position *)RFIFOP(fd,12)); + return 0; +} + +// ACK change of guild skill update +int intif_parse_GuildSkillUp(int fd) +{ + guild->skillupack(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10)); + return 0; +} + +// ACK change of guild relationship +int intif_parse_GuildAlliance(int fd) +{ + guild->allianceack(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOL(fd,14),RFIFOB(fd,18),(char *) RFIFOP(fd,19),(char *) RFIFOP(fd,43)); + return 0; +} + +// ACK change of guild notice +int intif_parse_GuildNotice(int fd) +{ + guild->notice_changed(RFIFOL(fd,2),(char *) RFIFOP(fd,6),(char *) RFIFOP(fd,66)); + return 0; +} + +// ACK change of guild emblem +int intif_parse_GuildEmblem(int fd) +{ + guild->emblem_changed(RFIFOW(fd,2)-12,RFIFOL(fd,4),RFIFOL(fd,8), (char *)RFIFOP(fd,12)); + return 0; +} + +// ACK guild message +int intif_parse_GuildMessage(int fd) +{ + guild->recv_message(RFIFOL(fd,4),RFIFOL(fd,8),(char *) RFIFOP(fd,12),RFIFOW(fd,2)-12); + return 0; +} + +// Reply guild castle data request +int intif_parse_GuildCastleDataLoad(int fd) +{ + return guild->castledataloadack(RFIFOW(fd,2), (struct guild_castle *)RFIFOP(fd,4)); +} + +// ACK change of guildmaster +int intif_parse_GuildMasterChanged(int fd) +{ + return guild->gm_changed(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10)); +} + +// Request pet creation +int intif_parse_CreatePet(int fd) +{ + pet_get_egg(RFIFOL(fd,2),RFIFOL(fd,7),RFIFOB(fd,6)); + return 0; +} + +// ACK pet data +int intif_parse_RecvPetData(int fd) +{ + struct s_pet p; + int len; + len=RFIFOW(fd,2); + if(sizeof(struct s_pet)!=len-9) { + if(battle_config.etc_log) + ShowError("intif: pet data: data size error %d %d\n",sizeof(struct s_pet),len-9); + } + else{ + memcpy(&p,RFIFOP(fd,9),sizeof(struct s_pet)); + pet_recv_petdata(RFIFOL(fd,4),&p,RFIFOB(fd,8)); + } + + return 0; +} + +// ACK pet save data +int intif_parse_SavePetOk(int fd) +{ + if(RFIFOB(fd,6) == 1) + ShowError("pet data save failure\n"); + + return 0; +} + +// ACK deleting pet +int intif_parse_DeletePetOk(int fd) +{ + if(RFIFOB(fd,2) == 1) + ShowError("pet data delete failure\n"); + + return 0; +} + +// ACK changing name resquest, players,pets,hommon +int intif_parse_ChangeNameOk(int fd) +{ + struct map_session_data *sd = NULL; + if((sd=iMap->id2sd(RFIFOL(fd,2)))==NULL || + sd->status.char_id != RFIFOL(fd,6)) + return 0; + + switch (RFIFOB(fd,10)) { + case 0: //Players [NOT SUPPORTED YET] + break; + case 1: //Pets + pet_change_name_ack(sd, (char*)RFIFOP(fd,12), RFIFOB(fd,11)); + break; + case 2: //Hom + homun->change_name_ack(sd, (char*)RFIFOP(fd,12), RFIFOB(fd,11)); + break; + } + return 0; +} + +//---------------------------------------------------------------- +// Homunculus recv packets [albator] + +int intif_parse_CreateHomunculus(int fd) +{ + int len; + len=RFIFOW(fd,2)-9; + if(sizeof(struct s_homunculus)!=len) { + if(battle_config.etc_log) + ShowError("intif: create homun data: data size error %d != %d\n",sizeof(struct s_homunculus),len); + return 0; + } + homun->recv_data(RFIFOL(fd,4), (struct s_homunculus*)RFIFOP(fd,9), RFIFOB(fd,8)) ; + return 0; +} + +int intif_parse_RecvHomunculusData(int fd) +{ + int len; + + len=RFIFOW(fd,2)-9; + + if(sizeof(struct s_homunculus)!=len) { + if(battle_config.etc_log) + ShowError("intif: homun data: data size error %d %d\n",sizeof(struct s_homunculus),len); + return 0; + } + homun->recv_data(RFIFOL(fd,4), (struct s_homunculus*)RFIFOP(fd,9), RFIFOB(fd,8)); + return 0; +} + +int intif_parse_SaveHomunculusOk(int fd) +{ + if(RFIFOB(fd,6) != 1) + ShowError("homunculus data save failure for account %d\n", RFIFOL(fd,2)); + + return 0; +} + +int intif_parse_DeleteHomunculusOk(int fd) +{ + if(RFIFOB(fd,2) != 1) + ShowError("Homunculus data delete failure\n"); + + return 0; +} + +/************************************** + +QUESTLOG SYSTEM FUNCTIONS + +***************************************/ + +int intif_request_questlog(TBL_PC *sd) +{ + WFIFOHEAD(inter_fd,6); + WFIFOW(inter_fd,0) = 0x3060; + WFIFOL(inter_fd,2) = sd->status.char_id; + WFIFOSET(inter_fd,6); + return 0; +} + +int intif_parse_questlog(int fd) +{ + int char_id = RFIFOL(fd, 4); + int i; + TBL_PC * sd = iMap->charid2sd(char_id); + + //User not online anymore + if(!sd) + return -1; + + sd->avail_quests = sd->num_quests = (RFIFOW(fd, 2)-8)/sizeof(struct quest); + + memset(&sd->quest_log, 0, sizeof(sd->quest_log)); + + for( i = 0; i < sd->num_quests; i++ ) + { + memcpy(&sd->quest_log[i], RFIFOP(fd, i*sizeof(struct quest)+8), sizeof(struct quest)); + + sd->quest_index[i] = quest_search_db(sd->quest_log[i].quest_id); + + if( sd->quest_index[i] < 0 ) + { + ShowError("intif_parse_questlog: quest %d not found in DB.\n",sd->quest_log[i].quest_id); + sd->avail_quests--; + sd->num_quests--; + i--; + continue; + } + + if( sd->quest_log[i].state == Q_COMPLETE ) + sd->avail_quests--; + } + + quest_pc_login(sd); + + return 0; +} + +int intif_parse_questsave(int fd) +{ + int cid = RFIFOL(fd, 2); + TBL_PC *sd = iMap->id2sd(cid); + + if( !RFIFOB(fd, 6) ) + ShowError("intif_parse_questsave: Failed to save quest(s) for character %d!\n", cid); + else if( sd ) + sd->save_quest = false; + + return 0; +} + +int intif_quest_save(TBL_PC *sd) +{ + int len; + + if(intif->CheckForCharServer()) + return 0; + + len = sizeof(struct quest)*sd->num_quests + 8; + + WFIFOHEAD(inter_fd, len); + WFIFOW(inter_fd,0) = 0x3061; + WFIFOW(inter_fd,2) = len; + WFIFOL(inter_fd,4) = sd->status.char_id; + if( sd->num_quests ) + memcpy(WFIFOP(inter_fd,8), &sd->quest_log, sizeof(struct quest)*sd->num_quests); + WFIFOSET(inter_fd, len); + + return 0; +} + +/*========================================== + * MAIL SYSTEM + * By Zephyrus + *==========================================*/ + +/*------------------------------------------ + * Inbox Request + * flag: 0 Update Inbox | 1 OpenMail + *------------------------------------------*/ +int intif_Mail_requestinbox(int char_id, unsigned char flag) +{ + if (intif->CheckForCharServer()) + return 0; + + WFIFOHEAD(inter_fd,7); + WFIFOW(inter_fd,0) = 0x3048; + WFIFOL(inter_fd,2) = char_id; + WFIFOB(inter_fd,6) = flag; + WFIFOSET(inter_fd,7); + + return 0; +} + +int intif_parse_Mail_inboxreceived(int fd) +{ + struct map_session_data *sd; + unsigned char flag = RFIFOB(fd,8); + + sd = iMap->charid2sd(RFIFOL(fd,4)); + + if (sd == NULL) + { + ShowError("intif_parse_Mail_inboxreceived: char not found %d\n",RFIFOL(fd,4)); + return 1; + } + + if (RFIFOW(fd,2) - 9 != sizeof(struct mail_data)) + { + ShowError("intif_parse_Mail_inboxreceived: data size error %d %d\n", RFIFOW(fd,2) - 9, sizeof(struct mail_data)); + return 1; + } + + //FIXME: this operation is not safe [ultramage] + memcpy(&sd->mail.inbox, RFIFOP(fd,9), sizeof(struct mail_data)); + sd->mail.changed = false; // cache is now in sync + + if (flag) + clif->mail_refreshinbox(sd); + else if( battle_config.mail_show_status && ( battle_config.mail_show_status == 1 || sd->mail.inbox.unread ) ) + { + char output[128]; + sprintf(output, msg_txt(510), sd->mail.inbox.unchecked, sd->mail.inbox.unread + sd->mail.inbox.unchecked); + clif->disp_onlyself(sd, output, strlen(output)); + } + return 0; +} +/*------------------------------------------ + * Mail Read + *------------------------------------------*/ +int intif_Mail_read(int mail_id) +{ + if (intif->CheckForCharServer()) + return 0; + + WFIFOHEAD(inter_fd,6); + WFIFOW(inter_fd,0) = 0x3049; + WFIFOL(inter_fd,2) = mail_id; + WFIFOSET(inter_fd,6); + + return 0; +} +/*------------------------------------------ + * Get Attachment + *------------------------------------------*/ +int intif_Mail_getattach(int char_id, int mail_id) +{ + if (intif->CheckForCharServer()) + return 0; + + WFIFOHEAD(inter_fd,10); + WFIFOW(inter_fd,0) = 0x304a; + WFIFOL(inter_fd,2) = char_id; + WFIFOL(inter_fd,6) = mail_id; + WFIFOSET(inter_fd, 10); + + return 0; +} + +int intif_parse_Mail_getattach(int fd) +{ + struct map_session_data *sd; + struct item item; + int zeny = RFIFOL(fd,8); + + sd = iMap->charid2sd( RFIFOL(fd,4) ); + + if (sd == NULL) + { + ShowError("intif_parse_Mail_getattach: char not found %d\n",RFIFOL(fd,4)); + return 1; + } + + if (RFIFOW(fd,2) - 12 != sizeof(struct item)) + { + ShowError("intif_parse_Mail_getattach: data size error %d %d\n", RFIFOW(fd,2) - 16, sizeof(struct item)); + return 1; + } + + memcpy(&item, RFIFOP(fd,12), sizeof(struct item)); + + mail->getattachment(sd, zeny, &item); + return 0; +} +/*------------------------------------------ + * Delete Message + *------------------------------------------*/ +int intif_Mail_delete(int char_id, int mail_id) +{ + if (intif->CheckForCharServer()) + return 0; + + WFIFOHEAD(inter_fd,10); + WFIFOW(inter_fd,0) = 0x304b; + WFIFOL(inter_fd,2) = char_id; + WFIFOL(inter_fd,6) = mail_id; + WFIFOSET(inter_fd,10); + + return 0; +} + +int intif_parse_Mail_delete(int fd) +{ + int char_id = RFIFOL(fd,2); + int mail_id = RFIFOL(fd,6); + bool failed = RFIFOB(fd,10); + + struct map_session_data *sd = iMap->charid2sd(char_id); + if (sd == NULL) + { + ShowError("intif_parse_Mail_delete: char not found %d\n", char_id); + return 1; + } + + if (!failed) + { + int i; + ARR_FIND(0, MAIL_MAX_INBOX, i, sd->mail.inbox.msg[i].id == mail_id); + if( i < MAIL_MAX_INBOX ) + { + memset(&sd->mail.inbox.msg[i], 0, sizeof(struct mail_message)); + sd->mail.inbox.amount--; + } + + if( sd->mail.inbox.full ) + intif_Mail_requestinbox(sd->status.char_id, 1); // Free space is available for new mails + } + + clif->mail_delete(sd->fd, mail_id, failed); + return 0; +} +/*------------------------------------------ + * Return Message + *------------------------------------------*/ +int intif_Mail_return(int char_id, int mail_id) +{ + if (intif->CheckForCharServer()) + return 0; + + WFIFOHEAD(inter_fd,10); + WFIFOW(inter_fd,0) = 0x304c; + WFIFOL(inter_fd,2) = char_id; + WFIFOL(inter_fd,6) = mail_id; + WFIFOSET(inter_fd,10); + + return 0; +} + +int intif_parse_Mail_return(int fd) +{ + struct map_session_data *sd = iMap->charid2sd(RFIFOL(fd,2)); + int mail_id = RFIFOL(fd,6); + short fail = RFIFOB(fd,10); + + if( sd == NULL ) + { + ShowError("intif_parse_Mail_return: char not found %d\n",RFIFOL(fd,2)); + return 1; + } + + if( !fail ) + { + int i; + ARR_FIND(0, MAIL_MAX_INBOX, i, sd->mail.inbox.msg[i].id == mail_id); + if( i < MAIL_MAX_INBOX ) + { + memset(&sd->mail.inbox.msg[i], 0, sizeof(struct mail_message)); + sd->mail.inbox.amount--; + } + + if( sd->mail.inbox.full ) + intif_Mail_requestinbox(sd->status.char_id, 1); // Free space is available for new mails + } + + clif->mail_return(sd->fd, mail_id, fail); + return 0; +} +/*------------------------------------------ + * Send Mail + *------------------------------------------*/ +int intif_Mail_send(int account_id, struct mail_message *msg) +{ + int len = sizeof(struct mail_message) + 8; + + if (intif->CheckForCharServer()) + return 0; + + WFIFOHEAD(inter_fd,len); + WFIFOW(inter_fd,0) = 0x304d; + WFIFOW(inter_fd,2) = len; + WFIFOL(inter_fd,4) = account_id; + memcpy(WFIFOP(inter_fd,8), msg, sizeof(struct mail_message)); + WFIFOSET(inter_fd,len); + + return 1; +} + +static void intif_parse_Mail_send(int fd) +{ + struct mail_message msg; + struct map_session_data *sd; + bool fail; + + if( RFIFOW(fd,2) - 4 != sizeof(struct mail_message) ) + { + ShowError("intif_parse_Mail_send: data size error %d %d\n", RFIFOW(fd,2) - 4, sizeof(struct mail_message)); + return; + } + + memcpy(&msg, RFIFOP(fd,4), sizeof(struct mail_message)); + fail = (msg.id == 0); + + // notify sender + sd = iMap->charid2sd(msg.send_id); + if( sd != NULL ) + { + if( fail ) + mail->deliveryfail(sd, &msg); + else + { + clif->mail_send(sd->fd, false); + if( iMap->save_settings&16 ) + chrif->save(sd, 0); + } + } +} + +static void intif_parse_Mail_new(int fd) +{ + struct map_session_data *sd = iMap->charid2sd(RFIFOL(fd,2)); + int mail_id = RFIFOL(fd,6); + const char* sender_name = (char*)RFIFOP(fd,10); + const char* title = (char*)RFIFOP(fd,34); + + if( sd == NULL ) + return; + + sd->mail.changed = true; + clif->mail_new(sd->fd, mail_id, sender_name, title); +} + +/*========================================== + * AUCTION SYSTEM + * By Zephyrus + *==========================================*/ +int intif_Auction_requestlist(int char_id, short type, int price, const char* searchtext, short page) +{ + int len = NAME_LENGTH + 16; + + if( intif->CheckForCharServer() ) + return 0; + + WFIFOHEAD(inter_fd,len); + WFIFOW(inter_fd,0) = 0x3050; + WFIFOW(inter_fd,2) = len; + WFIFOL(inter_fd,4) = char_id; + WFIFOW(inter_fd,8) = type; + WFIFOL(inter_fd,10) = price; + WFIFOW(inter_fd,14) = page; + memcpy(WFIFOP(inter_fd,16), searchtext, NAME_LENGTH); + WFIFOSET(inter_fd,len); + + return 0; +} + +static void intif_parse_Auction_results(int fd) +{ + struct map_session_data *sd = iMap->charid2sd(RFIFOL(fd,4)); + short count = RFIFOW(fd,8); + short pages = RFIFOW(fd,10); + uint8* data = RFIFOP(fd,12); + + if( sd == NULL ) + return; + + clif->auction_results(sd, count, pages, data); +} + +int intif_Auction_register(struct auction_data *auction) +{ + int len = sizeof(struct auction_data) + 4; + + if( intif->CheckForCharServer() ) + return 0; + + WFIFOHEAD(inter_fd,len); + WFIFOW(inter_fd,0) = 0x3051; + WFIFOW(inter_fd,2) = len; + memcpy(WFIFOP(inter_fd,4), auction, sizeof(struct auction_data)); + WFIFOSET(inter_fd,len); + + return 1; +} + +static void intif_parse_Auction_register(int fd) +{ + struct map_session_data *sd; + struct auction_data auction; + + if( RFIFOW(fd,2) - 4 != sizeof(struct auction_data) ) + { + ShowError("intif_parse_Auction_register: data size error %d %d\n", RFIFOW(fd,2) - 4, sizeof(struct auction_data)); + return; + } + + memcpy(&auction, RFIFOP(fd,4), sizeof(struct auction_data)); + if( (sd = iMap->charid2sd(auction.seller_id)) == NULL ) + return; + + if( auction.auction_id > 0 ) + { + clif->auction_message(sd->fd, 1); // Confirmation Packet ?? + if( iMap->save_settings&32 ) + chrif->save(sd,0); + } + else + { + int zeny = auction.hours*battle_config.auction_feeperhour; + + clif->auction_message(sd->fd, 4); + pc->additem(sd, &auction.item, auction.item.amount, LOG_TYPE_AUCTION); + + pc->getzeny(sd, zeny, LOG_TYPE_AUCTION, NULL); + } +} + +int intif_Auction_cancel(int char_id, unsigned int auction_id) +{ + if( intif->CheckForCharServer() ) + return 0; + + WFIFOHEAD(inter_fd,10); + WFIFOW(inter_fd,0) = 0x3052; + WFIFOL(inter_fd,2) = char_id; + WFIFOL(inter_fd,6) = auction_id; + WFIFOSET(inter_fd,10); + + return 0; +} + +static void intif_parse_Auction_cancel(int fd) +{ + struct map_session_data *sd = iMap->charid2sd(RFIFOL(fd,2)); + int result = RFIFOB(fd,6); + + if( sd == NULL ) + return; + + switch( result ) + { + case 0: clif->auction_message(sd->fd, 2); break; + case 1: clif->auction_close(sd->fd, 2); break; + case 2: clif->auction_close(sd->fd, 1); break; + case 3: clif->auction_message(sd->fd, 3); break; + } +} + +int intif_Auction_close(int char_id, unsigned int auction_id) +{ + if( intif->CheckForCharServer() ) + return 0; + + WFIFOHEAD(inter_fd,10); + WFIFOW(inter_fd,0) = 0x3053; + WFIFOL(inter_fd,2) = char_id; + WFIFOL(inter_fd,6) = auction_id; + WFIFOSET(inter_fd,10); + + return 0; +} + +static void intif_parse_Auction_close(int fd) +{ + struct map_session_data *sd = iMap->charid2sd(RFIFOL(fd,2)); + unsigned char result = RFIFOB(fd,6); + + if( sd == NULL ) + return; + + clif->auction_close(sd->fd, result); + if( result == 0 ) + { + // FIXME: Leeching off a parse function + clif->pAuction_cancelreg(fd, sd); + intif_Auction_requestlist(sd->status.char_id, 6, 0, "", 1); + } +} + +int intif_Auction_bid(int char_id, const char* name, unsigned int auction_id, int bid) +{ + int len = 16 + NAME_LENGTH; + + if( intif->CheckForCharServer() ) + return 0; + + WFIFOHEAD(inter_fd,len); + WFIFOW(inter_fd,0) = 0x3055; + WFIFOW(inter_fd,2) = len; + WFIFOL(inter_fd,4) = char_id; + WFIFOL(inter_fd,8) = auction_id; + WFIFOL(inter_fd,12) = bid; + memcpy(WFIFOP(inter_fd,16), name, NAME_LENGTH); + WFIFOSET(inter_fd,len); + + return 0; +} + +static void intif_parse_Auction_bid(int fd) +{ + struct map_session_data *sd = iMap->charid2sd(RFIFOL(fd,2)); + int bid = RFIFOL(fd,6); + unsigned char result = RFIFOB(fd,10); + + if( sd == NULL ) + return; + + clif->auction_message(sd->fd, result); + if( bid > 0 ) { + pc->getzeny(sd, bid, LOG_TYPE_AUCTION,NULL); + } + if( result == 1 ) { // To update the list, display your buy list + clif->pAuction_cancelreg(fd, sd); + intif_Auction_requestlist(sd->status.char_id, 7, 0, "", 1); + } +} + +// Used to send 'You have won the auction' and 'You failed to won the auction' messages +static void intif_parse_Auction_message(int fd) +{ + struct map_session_data *sd = iMap->charid2sd(RFIFOL(fd,2)); + unsigned char result = RFIFOB(fd,6); + + if( sd == NULL ) + return; + + clif->auction_message(sd->fd, result); +} + +/*========================================== + * Mercenary's System + *------------------------------------------*/ +int intif_mercenary_create(struct s_mercenary *merc) +{ + int size = sizeof(struct s_mercenary) + 4; + + if( intif->CheckForCharServer() ) + return 0; + + WFIFOHEAD(inter_fd,size); + WFIFOW(inter_fd,0) = 0x3070; + WFIFOW(inter_fd,2) = size; + memcpy(WFIFOP(inter_fd,4), merc, sizeof(struct s_mercenary)); + WFIFOSET(inter_fd,size); + return 0; +} + +int intif_parse_mercenary_received(int fd) +{ + int len = RFIFOW(fd,2) - 5; + if( sizeof(struct s_mercenary) != len ) + { + if( battle_config.etc_log ) + ShowError("intif: create mercenary data size error %d != %d\n", sizeof(struct s_mercenary), len); + return 0; + } + + merc_data_received((struct s_mercenary*)RFIFOP(fd,5), RFIFOB(fd,4)); + return 0; +} + +int intif_mercenary_request(int merc_id, int char_id) +{ + if (intif->CheckForCharServer()) + return 0; + + WFIFOHEAD(inter_fd,10); + WFIFOW(inter_fd,0) = 0x3071; + WFIFOL(inter_fd,2) = merc_id; + WFIFOL(inter_fd,6) = char_id; + WFIFOSET(inter_fd,10); + return 0; +} + +int intif_mercenary_delete(int merc_id) +{ + if (intif->CheckForCharServer()) + return 0; + + WFIFOHEAD(inter_fd,6); + WFIFOW(inter_fd,0) = 0x3072; + WFIFOL(inter_fd,2) = merc_id; + WFIFOSET(inter_fd,6); + return 0; +} + +int intif_parse_mercenary_deleted(int fd) +{ + if( RFIFOB(fd,2) != 1 ) + ShowError("Mercenary data delete failure\n"); + + return 0; +} + +int intif_mercenary_save(struct s_mercenary *merc) +{ + int size = sizeof(struct s_mercenary) + 4; + + if( intif->CheckForCharServer() ) + return 0; + + WFIFOHEAD(inter_fd,size); + WFIFOW(inter_fd,0) = 0x3073; + WFIFOW(inter_fd,2) = size; + memcpy(WFIFOP(inter_fd,4), merc, sizeof(struct s_mercenary)); + WFIFOSET(inter_fd,size); + return 0; +} + +int intif_parse_mercenary_saved(int fd) +{ + if( RFIFOB(fd,2) != 1 ) + ShowError("Mercenary data save failure\n"); + + return 0; +} + +/*========================================== + * Elemental's System + *------------------------------------------*/ +int intif_elemental_create(struct s_elemental *ele) +{ + int size = sizeof(struct s_elemental) + 4; + + if( intif->CheckForCharServer() ) + return 0; + + WFIFOHEAD(inter_fd,size); + WFIFOW(inter_fd,0) = 0x307c; + WFIFOW(inter_fd,2) = size; + memcpy(WFIFOP(inter_fd,4), ele, sizeof(struct s_elemental)); + WFIFOSET(inter_fd,size); + return 0; +} + +int intif_parse_elemental_received(int fd) +{ + int len = RFIFOW(fd,2) - 5; + if( sizeof(struct s_elemental) != len ) + { + if( battle_config.etc_log ) + ShowError("intif: create elemental data size error %d != %d\n", sizeof(struct s_elemental), len); + return 0; + } + + elemental->data_received((struct s_elemental*)RFIFOP(fd,5), RFIFOB(fd,4)); + return 0; +} + +int intif_elemental_request(int ele_id, int char_id) +{ + if (intif->CheckForCharServer()) + return 0; + + WFIFOHEAD(inter_fd,10); + WFIFOW(inter_fd,0) = 0x307d; + WFIFOL(inter_fd,2) = ele_id; + WFIFOL(inter_fd,6) = char_id; + WFIFOSET(inter_fd,10); + return 0; +} + +int intif_elemental_delete(int ele_id) +{ + if (intif->CheckForCharServer()) + return 0; + + WFIFOHEAD(inter_fd,6); + WFIFOW(inter_fd,0) = 0x307e; + WFIFOL(inter_fd,2) = ele_id; + WFIFOSET(inter_fd,6); + return 0; +} + +int intif_parse_elemental_deleted(int fd) +{ + if( RFIFOB(fd,2) != 1 ) + ShowError("Elemental data delete failure\n"); + + return 0; +} + +int intif_elemental_save(struct s_elemental *ele) +{ + int size = sizeof(struct s_elemental) + 4; + + if( intif->CheckForCharServer() ) + return 0; + + WFIFOHEAD(inter_fd,size); + WFIFOW(inter_fd,0) = 0x307f; + WFIFOW(inter_fd,2) = size; + memcpy(WFIFOP(inter_fd,4), ele, sizeof(struct s_elemental)); + WFIFOSET(inter_fd,size); + return 0; +} + +int intif_parse_elemental_saved(int fd) +{ + if( RFIFOB(fd,2) != 1 ) + ShowError("Elemental data save failure\n"); + + return 0; +} + +void intif_request_accinfo( int u_fd, int aid, int group_lv, char* query ) { + + + WFIFOHEAD(inter_fd,2 + 4 + 4 + 4 + NAME_LENGTH); + + WFIFOW(inter_fd,0) = 0x3007; + WFIFOL(inter_fd,2) = u_fd; + WFIFOL(inter_fd,6) = aid; + WFIFOL(inter_fd,10) = group_lv; + safestrncpy((char *)WFIFOP(inter_fd,14), query, NAME_LENGTH); + + WFIFOSET(inter_fd,2 + 4 + 4 + 4 + NAME_LENGTH); + + return; +} + +void intif_parse_MessageToFD(int fd) { + int u_fd = RFIFOL(fd,4); + + if( session[u_fd] && session[u_fd]->session_data ) { + int aid = RFIFOL(fd,8); + struct map_session_data * sd = session[u_fd]->session_data; + /* matching e.g. previous fd owner didn't dc during request or is still the same */ + if( sd->bl.id == aid ) { + char msg[512]; + safestrncpy(msg, (char*)RFIFOP(fd,12), RFIFOW(fd,2) - 12); + clif->message(u_fd,msg); + } + + } + + return; +} + +//----------------------------------------------------------------- +// Communication from the inter server +// Return a 0 (false) if there were any errors. +// 1, 2 if there are not enough to return the length of the packet if the packet processing +int intif_parse(int fd) +{ + int packet_len, cmd; + cmd = RFIFOW(fd,0); + // Verify ID of the packet + if(cmd<0x3800 || cmd>=0x3800+(sizeof(packet_len_table)/sizeof(packet_len_table[0])) || + packet_len_table[cmd-0x3800]==0){ + return 0; + } + // Check the length of the packet + packet_len = packet_len_table[cmd-0x3800]; + if(packet_len==-1){ + if(RFIFOREST(fd)<4) + return 2; + packet_len = RFIFOW(fd,2); + } + if((int)RFIFOREST(fd)broadcast(NULL, (char *) RFIFOP(fd,16), packet_len-16, 0, ALL_CLIENT); + else //Color announce. + clif->broadcast2(NULL, (char *) RFIFOP(fd,16), packet_len-16, RFIFOL(fd,4), RFIFOW(fd,8), RFIFOW(fd,10), RFIFOW(fd,12), RFIFOW(fd,14), ALL_CLIENT); + break; + case 0x3801: intif_parse_WisMessage(fd); break; + case 0x3802: intif_parse_WisEnd(fd); break; + case 0x3803: mapif_parse_WisToGM(fd); break; + case 0x3804: intif_parse_Registers(fd); break; + case 0x3806: intif_parse_ChangeNameOk(fd); break; + case 0x3807: intif_parse_MessageToFD(fd); break; + case 0x3818: intif_parse_LoadGuildStorage(fd); break; + case 0x3819: intif_parse_SaveGuildStorage(fd); break; + case 0x3820: intif_parse_PartyCreated(fd); break; + case 0x3821: intif_parse_PartyInfo(fd); break; + case 0x3822: intif_parse_PartyMemberAdded(fd); break; + case 0x3823: intif_parse_PartyOptionChanged(fd); break; + case 0x3824: intif_parse_PartyMemberWithdraw(fd); break; + case 0x3825: intif_parse_PartyMove(fd); break; + case 0x3826: intif_parse_PartyBroken(fd); break; + case 0x3827: intif_parse_PartyMessage(fd); break; + case 0x3830: intif_parse_GuildCreated(fd); break; + case 0x3831: intif_parse_GuildInfo(fd); break; + case 0x3832: intif_parse_GuildMemberAdded(fd); break; + case 0x3834: intif_parse_GuildMemberWithdraw(fd); break; + case 0x3835: intif_parse_GuildMemberInfoShort(fd); break; + case 0x3836: intif_parse_GuildBroken(fd); break; + case 0x3837: intif_parse_GuildMessage(fd); break; + case 0x3839: intif_parse_GuildBasicInfoChanged(fd); break; + case 0x383a: intif_parse_GuildMemberInfoChanged(fd); break; + case 0x383b: intif_parse_GuildPosition(fd); break; + case 0x383c: intif_parse_GuildSkillUp(fd); break; + case 0x383d: intif_parse_GuildAlliance(fd); break; + case 0x383e: intif_parse_GuildNotice(fd); break; + case 0x383f: intif_parse_GuildEmblem(fd); break; + case 0x3840: intif_parse_GuildCastleDataLoad(fd); break; + case 0x3843: intif_parse_GuildMasterChanged(fd); break; + + //Quest system + case 0x3860: intif_parse_questlog(fd); break; + case 0x3861: intif_parse_questsave(fd); break; + +// Mail System + case 0x3848: intif_parse_Mail_inboxreceived(fd); break; + case 0x3849: intif_parse_Mail_new(fd); break; + case 0x384a: intif_parse_Mail_getattach(fd); break; + case 0x384b: intif_parse_Mail_delete(fd); break; + case 0x384c: intif_parse_Mail_return(fd); break; + case 0x384d: intif_parse_Mail_send(fd); break; +// Auction System + case 0x3850: intif_parse_Auction_results(fd); break; + case 0x3851: intif_parse_Auction_register(fd); break; + case 0x3852: intif_parse_Auction_cancel(fd); break; + case 0x3853: intif_parse_Auction_close(fd); break; + case 0x3854: intif_parse_Auction_message(fd); break; + case 0x3855: intif_parse_Auction_bid(fd); break; + +// Mercenary System + case 0x3870: intif_parse_mercenary_received(fd); break; + case 0x3871: intif_parse_mercenary_deleted(fd); break; + case 0x3872: intif_parse_mercenary_saved(fd); break; +// Elemental System + case 0x387c: intif_parse_elemental_received(fd); break; + case 0x387d: intif_parse_elemental_deleted(fd); break; + case 0x387e: intif_parse_elemental_saved(fd); break; + + case 0x3880: intif_parse_CreatePet(fd); break; + case 0x3881: intif_parse_RecvPetData(fd); break; + case 0x3882: intif_parse_SavePetOk(fd); break; + case 0x3883: intif_parse_DeletePetOk(fd); break; + case 0x3890: intif_parse_CreateHomunculus(fd); break; + case 0x3891: intif_parse_RecvHomunculusData(fd); break; + case 0x3892: intif_parse_SaveHomunculusOk(fd); break; + case 0x3893: intif_parse_DeleteHomunculusOk(fd); break; + default: + ShowError("intif_parse : unknown packet %d %x\n",fd,RFIFOW(fd,0)); + return 0; + } + // Skip packet + RFIFOSKIP(fd,packet_len); + return 1; +} + +/*===================================== +* Default Functions : intif.h +* Generated by HerculesInterfaceMaker +* created by Susu +*-------------------------------------*/ +void intif_defaults(void) { + intif = &intif_s; + /* funcs */ + + intif->parse = intif_parse; + + intif->broadcast = intif_broadcast; + intif->broadcast2 = intif_broadcast2; + intif->main_message = intif_main_message; + + intif->wis_message = intif_wis_message; + intif->wis_message_to_gm = intif_wis_message_to_gm; + + intif->saveregistry = intif_saveregistry; + intif->request_registry = intif_request_registry; + + intif->request_guild_storage = intif_request_guild_storage; + intif->send_guild_storage = intif_send_guild_storage; + + intif->create_party = intif_create_party; + intif->request_partyinfo = intif_request_partyinfo; + + intif->party_addmember = intif_party_addmember; + intif->party_changeoption = intif_party_changeoption; + intif->party_leave = intif_party_leave; + intif->party_changemap = intif_party_changemap; + intif->break_party = intif_break_party; + intif->party_message = intif_party_message; + intif->party_leaderchange = intif_party_leaderchange; + + intif->guild_create = intif_guild_create; + intif->guild_request_info = intif_guild_request_info; + intif->guild_addmember = intif_guild_addmember; + intif->guild_leave = intif_guild_leave; + intif->guild_memberinfoshort = intif_guild_memberinfoshort; + intif->guild_break = intif_guild_break; + intif->guild_message = intif_guild_message; + intif->guild_change_gm = intif_guild_change_gm; + intif->guild_change_basicinfo = intif_guild_change_basicinfo; + intif->guild_change_memberinfo = intif_guild_change_memberinfo; + intif->guild_position = intif_guild_position; + intif->guild_skillup = intif_guild_skillup; + intif->guild_alliance = intif_guild_alliance; + intif->guild_notice = intif_guild_notice; + intif->guild_emblem = intif_guild_emblem; + intif->guild_castle_dataload = intif_guild_castle_dataload; + intif->guild_castle_datasave = intif_guild_castle_datasave; + intif->request_petdata = intif_request_petdata; + intif->save_petdata = intif_save_petdata; + intif->delete_petdata = intif_delete_petdata; + intif->rename = intif_rename; + intif->homunculus_create = intif_homunculus_create; + intif->homunculus_requestload = intif_homunculus_requestload; + intif->homunculus_requestsave = intif_homunculus_requestsave; + intif->homunculus_requestdelete = intif_homunculus_requestdelete; + /******QUEST SYTEM*******/ + intif->request_questlog = intif_request_questlog; + intif->quest_save = intif_quest_save; + // MERCENARY SYSTEM + intif->mercenary_create = intif_mercenary_create; + intif->mercenary_request = intif_mercenary_request; + intif->mercenary_delete = intif_mercenary_delete; + intif->mercenary_save = intif_mercenary_save; + // MAIL SYSTEM + intif->Mail_requestinbox = intif_Mail_requestinbox; + intif->Mail_read = intif_Mail_read; + intif->Mail_getattach = intif_Mail_getattach; + intif->Mail_delete = intif_Mail_delete; + intif->Mail_return = intif_Mail_return; + intif->Mail_send = intif_Mail_send; + // AUCTION SYSTEM + intif->Auction_requestlist = intif_Auction_requestlist; + intif->Auction_register = intif_Auction_register; + intif->Auction_cancel = intif_Auction_cancel; + intif->Auction_close = intif_Auction_close; + intif->Auction_bid = intif_Auction_bid; + // ELEMENTAL SYSTEM + intif->elemental_create = intif_elemental_create; + intif->elemental_request = intif_elemental_request; + intif->elemental_delete = intif_elemental_delete; + intif->elemental_save = intif_elemental_save; + /* @accinfo */ + intif->request_accinfo = intif_request_accinfo; + + intif->CheckForCharServer = CheckForCharServer; +} diff --git a/src/map/intif.h b/src/map/intif.h index 43bbc0859..f0c1067fb 100644 --- a/src/map/intif.h +++ b/src/map/intif.h @@ -1,112 +1,128 @@ -// Copyright (c) Athena Dev Teams - Licensed under GNU GPL -// For more information, see LICENCE in the main folder - -#ifndef _INTIF_H_ -#define _INFIF_H_ - -//#include "../common/mmo.h" -struct party_member; -struct guild_member; -struct guild_position; -struct s_pet; -struct s_homunculus; -struct s_mercenary; -struct s_elemental; -struct mail_message; -struct auction_data; - -int intif_parse(int fd); - -int intif_broadcast(const char* mes, int len, int type); -int intif_broadcast2(const char* mes, int len, unsigned long fontColor, short fontType, short fontSize, short fontAlign, short fontY); -int intif_main_message(struct map_session_data* sd, const char* message); - -int intif_wis_message(struct map_session_data *sd,char *nick,char *mes,int mes_len); -int intif_wis_message_to_gm(char *Wisp_name, int permission, char *mes); - -int intif_saveregistry(struct map_session_data *sd, int type); -int intif_request_registry(struct map_session_data *sd, int flag); - -int intif_request_guild_storage(int account_id, int guild_id); -int intif_send_guild_storage(int account_id, struct guild_storage *gstor); - - -int intif_create_party(struct party_member *member,char *name,int item,int item2); -int intif_request_partyinfo(int party_id, int char_id); - -int intif_party_addmember(int party_id,struct party_member *member); -int intif_party_changeoption(int party_id, int account_id, int exp, int item); -int intif_party_leave(int party_id,int account_id, int char_id); -int intif_party_changemap(struct map_session_data *sd, int online); -int intif_break_party(int party_id); -int intif_party_message(int party_id, int account_id, const char *mes,int len); -int intif_party_leaderchange(int party_id,int account_id,int char_id); - - -int intif_guild_create(const char *name, const struct guild_member *master); -int intif_guild_request_info(int guild_id); -int intif_guild_addmember(int guild_id, struct guild_member *m); -int intif_guild_leave(int guild_id, int account_id, int char_id, int flag, const char *mes); -int intif_guild_memberinfoshort(int guild_id, int account_id, int char_id, int online, int lv, int class_); -int intif_guild_break(int guild_id); -int intif_guild_message(int guild_id, int account_id, const char *mes, int len); -int intif_guild_change_gm(int guild_id, const char* name, int len); -int intif_guild_change_basicinfo(int guild_id, int type, const void *data, int len); -int intif_guild_change_memberinfo(int guild_id, int account_id, int char_id, int type, const void *data, int len); -int intif_guild_position(int guild_id, int idx, struct guild_position *p); -int intif_guild_skillup(int guild_id, uint16 skill_id, int account_id, int max); -int intif_guild_alliance(int guild_id1, int guild_id2, int account_id1, int account_id2, int flag); -int intif_guild_notice(int guild_id, const char *mes1, const char *mes2); -int intif_guild_emblem(int guild_id, int len, const char *data); -int intif_guild_castle_dataload(int num, int *castle_ids); -int intif_guild_castle_datasave(int castle_id, int index, int value); - -int intif_create_pet(int account_id, int char_id, short pet_type, short pet_lv, short pet_egg_id, - short pet_equip, short intimate, short hungry, char rename_flag, char incuvate, char *pet_name); -int intif_request_petdata(int account_id, int char_id, int pet_id); -int intif_save_petdata(int account_id, struct s_pet *p); -int intif_delete_petdata(int pet_id); -int intif_rename(struct map_session_data *sd, int type, char *name); -#define intif_rename_pc(sd, name) intif_rename(sd, 0, name) -#define intif_rename_pet(sd, name) intif_rename(sd, 1, name) -#define intif_rename_hom(sd, name) intif_rename(sd, 2, name) -int intif_homunculus_create(int account_id, struct s_homunculus *sh); -bool intif_homunculus_requestload(int account_id, int homun_id); -int intif_homunculus_requestsave(int account_id, struct s_homunculus* sh); -int intif_homunculus_requestdelete(int homun_id); - -/******QUEST SYTEM*******/ -int intif_request_questlog(struct map_session_data * sd); -int intif_quest_save(struct map_session_data * sd); - -// MERCENARY SYSTEM -int intif_mercenary_create(struct s_mercenary *merc); -int intif_mercenary_request(int merc_id, int char_id); -int intif_mercenary_delete(int merc_id); -int intif_mercenary_save(struct s_mercenary *merc); - -// MAIL SYSTEM -int intif_Mail_requestinbox(int char_id, unsigned char flag); -int intif_Mail_read(int mail_id); -int intif_Mail_getattach(int char_id, int mail_id); -int intif_Mail_delete(int char_id, int mail_id); -int intif_Mail_return(int char_id, int mail_id); -int intif_Mail_send(int account_id, struct mail_message *msg); -// AUCTION SYSTEM -int intif_Auction_requestlist(int char_id, short type, int price, const char* searchtext, short page); -int intif_Auction_register(struct auction_data *auction); -int intif_Auction_cancel(int char_id, unsigned int auction_id); -int intif_Auction_close(int char_id, unsigned int auction_id); -int intif_Auction_bid(int char_id, const char* name, unsigned int auction_id, int bid); -// ELEMENTAL SYSTEM -int intif_elemental_create(struct s_elemental *ele); -int intif_elemental_request(int ele_id, int char_id); -int intif_elemental_delete(int ele_id); -int intif_elemental_save(struct s_elemental *ele); - -/* @accinfo */ -void intif_request_accinfo( int u_fd, int aid, int group_lv, char* query ); - -int CheckForCharServer(void); - -#endif /* _INTIF_H_ */ +// Copyright (c) Athena Dev Teams - Licensed under GNU GPL +// For more information, see LICENCE in the main folder +#ifndef _INTIF_H_ +#define _INFIF_H_ +//#include "../common/mmo.h" +struct party_member; +struct guild_member; +struct guild_position; +struct s_pet; +struct s_homunculus; +struct s_mercenary; +struct s_elemental; +struct mail_message; +struct auction_data; + + + + + +#define intif_rename_pc(sd, name) intif->rename(sd, 0, name) +#define intif_rename_pet(sd, name) intif->rename(sd, 1, name) +#define intif_rename_hom(sd, name) intif->rename(sd, 2, name) + + + + + + +/*===================================== +* Interface : intif.h +* Generated by HerculesInterfaceMaker +* created by Susu +*-------------------------------------*/ +struct intif_interface { + /* funcs */ + + + int (*parse) (int fd); + + int (*create_pet)(int account_id, int char_id, short pet_type, short pet_lv, short pet_egg_id, + short pet_equip, short intimate, short hungry, char rename_flag, char incuvate, char *pet_name); + + int (*broadcast) (const char* mes, int len, int type); + int (*broadcast2) (const char* mes, int len, unsigned long fontColor, short fontType, short fontSize, short fontAlign, short fontY); + int (*main_message) (struct map_session_data* sd, const char* message); + + int (*wis_message) (struct map_session_data *sd,char *nick,char *mes,int mes_len); + int (*wis_message_to_gm) (char *Wisp_name, int permission, char *mes); + + int (*saveregistry) (struct map_session_data *sd, int type); + int (*request_registry) (struct map_session_data *sd, int flag); + + int (*request_guild_storage) (int account_id, int guild_id); + int (*send_guild_storage) (int account_id, struct guild_storage *gstor); + + int (*create_party) (struct party_member *member,char *name,int item,int item2); + int (*request_partyinfo) (int party_id, int char_id); + + int (*party_addmember) (int party_id,struct party_member *member); + int (*party_changeoption) (int party_id, int account_id, int exp, int item); + int (*party_leave) (int party_id,int account_id, int char_id); + int (*party_changemap) (struct map_session_data *sd, int online); + int (*break_party) (int party_id); + int (*party_message) (int party_id, int account_id, const char *mes,int len); + int (*party_leaderchange) (int party_id,int account_id,int char_id); + + int (*guild_create) (const char *name, const struct guild_member *master); + int (*guild_request_info) (int guild_id); + int (*guild_addmember) (int guild_id, struct guild_member *m); + int (*guild_leave) (int guild_id, int account_id, int char_id, int flag, const char *mes); + int (*guild_memberinfoshort) (int guild_id, int account_id, int char_id, int online, int lv, int class_); + int (*guild_break) (int guild_id); + int (*guild_message) (int guild_id, int account_id, const char *mes, int len); + int (*guild_change_gm) (int guild_id, const char* name, int len); + int (*guild_change_basicinfo) (int guild_id, int type, const void *data, int len); + int (*guild_change_memberinfo) (int guild_id, int account_id, int char_id, int type, const void *data, int len); + int (*guild_position) (int guild_id, int idx, struct guild_position *p); + int (*guild_skillup) (int guild_id, uint16 skill_id, int account_id, int max); + int (*guild_alliance) (int guild_id1, int guild_id2, int account_id1, int account_id2, int flag); + int (*guild_notice) (int guild_id, const char *mes1, const char *mes2); + int (*guild_emblem) (int guild_id, int len, const char *data); + int (*guild_castle_dataload) (int num, int *castle_ids); + int (*guild_castle_datasave) (int castle_id, int index, int value); + int (*request_petdata) (int account_id, int char_id, int pet_id); + int (*save_petdata) (int account_id, struct s_pet *p); + int (*delete_petdata) (int pet_id); + int (*rename) (struct map_session_data *sd, int type, char *name); + int (*homunculus_create) (int account_id, struct s_homunculus *sh); + bool (*homunculus_requestload) (int account_id, int homun_id); + int (*homunculus_requestsave) (int account_id, struct s_homunculus* sh); + int (*homunculus_requestdelete) (int homun_id); + /******QUEST SYTEM*******/ + int (*request_questlog) (struct map_session_data * sd); + int (*quest_save) (struct map_session_data * sd); + // MERCENARY SYSTEM + int (*mercenary_create) (struct s_mercenary *merc); + int (*mercenary_request) (int merc_id, int char_id); + int (*mercenary_delete) (int merc_id); + int (*mercenary_save) (struct s_mercenary *merc); + // MAIL SYSTEM + int (*Mail_requestinbox) (int char_id, unsigned char flag); + int (*Mail_read) (int mail_id); + int (*Mail_getattach) (int char_id, int mail_id); + int (*Mail_delete) (int char_id, int mail_id); + int (*Mail_return) (int char_id, int mail_id); + int (*Mail_send) (int account_id, struct mail_message *msg); + // AUCTION SYSTEM + int (*Auction_requestlist) (int char_id, short type, int price, const char* searchtext, short page); + int (*Auction_register) (struct auction_data *auction); + int (*Auction_cancel) (int char_id, unsigned int auction_id); + int (*Auction_close) (int char_id, unsigned int auction_id); + int (*Auction_bid) (int char_id, const char* name, unsigned int auction_id, int bid); + // ELEMENTAL SYSTEM + int (*elemental_create) (struct s_elemental *ele); + int (*elemental_request) (int ele_id, int char_id); + int (*elemental_delete) (int ele_id); + int (*elemental_save) (struct s_elemental *ele); + /* @accinfo */ + void (*request_accinfo) (int u_fd, int aid, int group_lv, char* query); + + int (*CheckForCharServer) (void); +} intif_s; + +struct intif_interface *intif; + +void intif_defaults(void); + +#endif /* _INTIF_H_ */ diff --git a/src/map/map.c b/src/map/map.c index 5e8102ea0..5db5431a8 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -1185,7 +1185,7 @@ int map_clearflooritem_timer(int tid, unsigned int tick, int id, intptr_t data) if (search_petDB_index(fitem->item_data.nameid, PET_EGG) >= 0) - intif_delete_petdata(MakeDWord(fitem->item_data.card[1], fitem->item_data.card[2])); + intif->delete_petdata(MakeDWord(fitem->item_data.card[1], fitem->item_data.card[2])); clif->clearflooritem(fitem, 0); iMap->deliddb(&fitem->bl); @@ -5158,6 +5158,7 @@ void map_hp_symbols(void) { HPM->share(chat, "chat"); HPM->share(iDuel,"iDuel"); HPM->share(elemental,"elemental"); + HPM->share(intif,"intif"); /* partial */ @@ -5199,6 +5200,7 @@ void map_load_defaults(void) { chat_defaults(); iDuel_defaults(); elemental_defaults(); + intif_defaults(); } int do_init(int argc, char *argv[]) { diff --git a/src/map/mercenary.c b/src/map/mercenary.c index a08b587e7..72ed7628a 100644 --- a/src/map/mercenary.c +++ b/src/map/mercenary.c @@ -82,7 +82,7 @@ int merc_create(struct map_session_data *sd, int class_, unsigned int lifetime) merc.life_time = lifetime; // Request Char Server to create this mercenary - intif_mercenary_create(&merc); + intif->mercenary_create(&merc); return 1; } @@ -213,7 +213,7 @@ int mercenary_save(struct mercenary_data *md) md->mercenary.sp = md->battle_status.sp; md->mercenary.life_time = mercenary_get_lifetime(md); - intif_mercenary_save(&md->mercenary); + intif->mercenary_save(&md->mercenary); return 1; } diff --git a/src/map/mob.c b/src/map/mob.c index 9cd05a8a3..04f3063e5 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -1605,7 +1605,7 @@ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick) memcpy (&md->lootitem[md->lootitem_count++], &fitem->item_data, sizeof(md->lootitem[0])); } else { //Destroy first looted item... if (md->lootitem[0].card[0] == CARD0_PET) - intif_delete_petdata( MakeDWord(md->lootitem[0].card[1],md->lootitem[0].card[2]) ); + intif->delete_petdata( MakeDWord(md->lootitem[0].card[1],md->lootitem[0].card[2]) ); memmove(&md->lootitem[0], &md->lootitem[1], (LOOTITEM_SIZE-1)*sizeof(md->lootitem[0])); memcpy (&md->lootitem[LOOTITEM_SIZE-1], &fitem->item_data, sizeof(md->lootitem[0])); } @@ -2386,7 +2386,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) char message[128]; sprintf (message, msg_txt(541), mvp_sd->status.name, md->name, it->jname, (float)drop_rate/100); //MSG: "'%s' won %s's %s (chance: %0.02f%%)" - intif_broadcast(message,strlen(message)+1,0); + intif->broadcast(message,strlen(message)+1,0); } // Announce first, or else ditem will be freed. [Lance] // By popular demand, use base drop rate for autoloot code. [Skotlex] @@ -2527,7 +2527,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) char message[128]; sprintf (message, msg_txt(541), mvp_sd->status.name, md->name, data->jname, temp/100.); //MSG: "'%s' won %s's %s (chance: %0.02f%%)" - intif_broadcast(message,strlen(message)+1,0); + intif->broadcast(message,strlen(message)+1,0); } if((temp = pc->additem(mvp_sd,&item,1,LOG_TYPE_PICKDROP_PLAYER)) != 0) { diff --git a/src/map/npc.c b/src/map/npc.c index 6bb058229..8a2c0f746 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -1710,7 +1710,7 @@ int npc_selllist(struct map_session_data* sd, int n, unsigned short* item_list) if( sd->inventory_data[idx]->type == IT_PETEGG && sd->status.inventory[idx].card[0] == CARD0_PET ) { if( search_petDB_index(sd->status.inventory[idx].nameid, PET_EGG) >= 0 ) { - intif_delete_petdata(MakeDWord(sd->status.inventory[idx].card[1], sd->status.inventory[idx].card[2])); + intif->delete_petdata(MakeDWord(sd->status.inventory[idx].card[1], sd->status.inventory[idx].card[2])); } } @@ -3865,7 +3865,7 @@ int npc_reload(void) { ShowStatus("Event '"CL_WHITE"OnInit"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs.\n",npc_event_doall("OnInit")); // Execute rest of the startup events if connected to char-server. [Lance] - if(!CheckForCharServer()){ + if(!intif->CheckForCharServer()){ ShowStatus("Event '"CL_WHITE"OnInterIfInit"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs.\n", npc_event_doall("OnInterIfInit")); ShowStatus("Event '"CL_WHITE"OnInterIfInitOnce"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs.\n", npc_event_doall("OnInterIfInitOnce")); } diff --git a/src/map/party.c b/src/map/party.c index 30740b058..0d9859345 100644 --- a/src/map/party.c +++ b/src/map/party.c @@ -95,7 +95,7 @@ static TBL_PC* party_sd_check(int party_id, int account_id, int char_id) sd->status.party_id = party_id;// auto-join if not in a party if (sd->status.party_id != party_id) { //If player belongs to a different party, kick him out. - intif_party_leave(party_id,account_id,char_id); + intif->party_leave(party_id,account_id,char_id); return NULL; } @@ -174,7 +174,7 @@ int party_create(struct map_session_data *sd,char *name,int item,int item2) party_fill_member(&leader, sd, 1); - intif_create_party(&leader,name,item,item2); + intif->create_party(&leader,name,item,item2); return 0; } @@ -187,7 +187,7 @@ void party_created(int account_id,int char_id,int fail,int party_id,char *name) if (!sd || sd->status.char_id != char_id || !sd->party_creating ) { //Character logged off before creation ack? if (!fail) //break up party since player could not be added to it. - intif_party_leave(party_id,account_id,char_id); + intif->party_leave(party_id,account_id,char_id); return; } @@ -205,7 +205,7 @@ void party_created(int account_id,int char_id,int fail,int party_id,char *name) int party_request_info(int party_id, int char_id) { - return intif_request_partyinfo(party_id, char_id); + return intif->request_partyinfo(party_id, char_id); } /// Invoked (from char-server) when the party info is not found. @@ -417,7 +417,7 @@ void party_reply_invite(struct map_session_data *sd,int party_id,int flag) {// accepted and allowed sd->party_joining = true; party_fill_member(&member, sd, 0); - intif_party_addmember(sd->party_invite, &member); + intif->party_addmember(sd->party_invite, &member); } else {// rejected or failure @@ -466,7 +466,7 @@ int party_member_added(int party_id,int account_id,int char_id, int flag) if(sd == NULL || sd->status.char_id != char_id || !sd->party_joining ) { if (!flag) //Char logged off before being accepted into party. - intif_party_leave(party_id,account_id,char_id); + intif->party_leave(party_id,account_id,char_id); return 0; } @@ -478,7 +478,7 @@ int party_member_added(int party_id,int account_id,int char_id, int flag) if (!p) { ShowError("party_member_added: party %d not found.\n",party_id); - intif_party_leave(party_id,account_id,char_id); + intif->party_leave(party_id,account_id,char_id); return 0; } @@ -540,7 +540,7 @@ int party_removemember(struct map_session_data* sd, int account_id, char* name) if( i == MAX_PARTY ) return 0; // no such char in party - intif_party_leave(p->party.party_id,account_id,p->party.member[i].char_id); + intif->party_leave(p->party.party_id,account_id,p->party.member[i].char_id); return 1; } @@ -558,7 +558,7 @@ int party_leave(struct map_session_data *sd) if( i == MAX_PARTY ) return 0; - intif_party_leave(p->party.party_id,sd->status.account_id,sd->status.char_id); + intif->party_leave(p->party.party_id,sd->status.account_id,sd->status.char_id); return 1; } @@ -630,7 +630,7 @@ int party_changeoption(struct map_session_data *sd,int exp,int item) if( sd->status.party_id==0) return 0; - intif_party_changeoption(sd->status.party_id,sd->status.account_id,exp,item); + intif->party_changeoption(sd->status.party_id,sd->status.account_id,exp,item); return 0; } @@ -698,7 +698,7 @@ bool party_changeleader(struct map_session_data *sd, struct map_session_data *ts clif->message(p->data[tmi].sd->fd, msg_txt(285)); //Update info. - intif_party_leaderchange(p->party.party_id,p->party.member[tmi].account_id,p->party.member[tmi].char_id); + intif->party_leaderchange(p->party.party_id,p->party.member[tmi].account_id,p->party.member[tmi].char_id); clif->party_info(p,NULL); return true; } @@ -742,7 +742,7 @@ void party_send_movemap(struct map_session_data *sd) if( sd->status.party_id==0 ) return; - intif_party_changemap(sd,1); + intif->party_changemap(sd,1); p=party->search(sd->status.party_id); if (!p) return; @@ -770,7 +770,7 @@ void party_send_movemap(struct map_session_data *sd) void party_send_levelup(struct map_session_data *sd) { - intif_party_changemap(sd,1); + intif->party_changemap(sd,1); } int party_send_logout(struct map_session_data *sd) @@ -781,7 +781,7 @@ int party_send_logout(struct map_session_data *sd) if(!sd->status.party_id) return 0; - intif_party_changemap(sd,0); + intif->party_changemap(sd,0); p=party->search(sd->status.party_id); if(!p) return 0; @@ -798,7 +798,7 @@ int party_send_message(struct map_session_data *sd,const char *mes,int len) { if(sd->status.party_id==0) return 0; - intif_party_message(sd->status.party_id,sd->status.account_id,mes,len); + intif->party_message(sd->status.party_id,sd->status.account_id,mes,len); party->recv_message(sd->status.party_id,sd->status.account_id,mes,len); // Chat logging type 'P' / Party Chat diff --git a/src/map/pc.c b/src/map/pc.c index 30ef9848c..e6c3721c3 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -1129,7 +1129,7 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim sd->sc_display_count = 0; // Request all registries (auth is considered completed whence they arrive) - intif_request_registry(sd,7); + intif->request_registry(sd,7); return true; } @@ -1236,15 +1236,15 @@ int pc_reg_received(struct map_session_data *sd) // pet if (sd->status.pet_id > 0) - intif_request_petdata(sd->status.account_id, sd->status.char_id, sd->status.pet_id); + intif->request_petdata(sd->status.account_id, sd->status.char_id, sd->status.pet_id); // Homunculus [albator] if( sd->status.hom_id > 0 ) - intif_homunculus_requestload(sd->status.account_id, sd->status.hom_id); + intif->homunculus_requestload(sd->status.account_id, sd->status.hom_id); if( sd->status.mer_id > 0 ) - intif_mercenary_request(sd->status.mer_id, sd->status.char_id); + intif->mercenary_request(sd->status.mer_id, sd->status.char_id); if( sd->status.ele_id > 0 ) - intif_elemental_request(sd->status.ele_id, sd->status.char_id); + intif->elemental_request(sd->status.ele_id, sd->status.char_id); iMap->addiddb(&sd->bl); iMap->delnickdb(sd->status.char_id, sd->status.name); @@ -1256,8 +1256,8 @@ int pc_reg_received(struct map_session_data *sd) status_calc_pc(sd,1); chrif->scdata_request(sd->status.account_id, sd->status.char_id); - intif_Mail_requestinbox(sd->status.char_id, 0); // MAIL SYSTEM - Request Mail Inbox - intif_request_questlog(sd); + intif->Mail_requestinbox(sd->status.char_id, 0); // MAIL SYSTEM - Request Mail Inbox + intif->request_questlog(sd); if (sd->state.connect_new == 0 && sd->fd) { //Character already loaded map! Gotta trigger LoadEndAck manually. sd->state.connect_new = 1; @@ -4681,7 +4681,7 @@ int pc_steal_item(struct map_session_data *sd,struct block_list *bl, uint16 skil char message[128]; sprintf (message, msg_txt(542), (sd->status.name != NULL)?sd->status.name :"GM", md->db->jname, data->jname, (float)md->db->dropitem[i].p/100); //MSG: "'%s' stole %s's %s (chance: %0.02f%%)" - intif_broadcast(message,strlen(message)+1,0); + intif->broadcast(message,strlen(message)+1,0); } return 1; } @@ -7720,7 +7720,7 @@ int pc_changelook(struct map_session_data *sd,int type,int val) if (sd->status.hair != val) { sd->status.hair=val; if (sd->status.guild_id) //Update Guild Window. [Skotlex] - intif_guild_change_memberinfo(sd->status.guild_id,sd->status.account_id,sd->status.char_id, + intif->guild_change_memberinfo(sd->status.guild_id,sd->status.account_id,sd->status.char_id, GMI_HAIR,&sd->status.hair,sizeof(sd->status.hair)); } break; @@ -7742,7 +7742,7 @@ int pc_changelook(struct map_session_data *sd,int type,int val) if (sd->status.hair_color != val) { sd->status.hair_color=val; if (sd->status.guild_id) //Update Guild Window. [Skotlex] - intif_guild_change_memberinfo(sd->status.guild_id,sd->status.account_id,sd->status.char_id, + intif->guild_change_memberinfo(sd->status.guild_id,sd->status.account_id,sd->status.char_id, GMI_HAIR_COLOR,&sd->status.hair_color,sizeof(sd->status.hair_color)); } break; @@ -8094,7 +8094,7 @@ int pc_readregistry(struct map_session_data *sd,const char *reg,int type) if (max == -1) { ShowError("pc_readregistry: Trying to read reg value %s (type %d) before it's been loaded!\n", reg, type); //This really shouldn't happen, so it's possible the data was lost somewhere, we should request it again. - intif_request_registry(sd,type==3?4:type); + intif->request_registry(sd,type==3?4:type); return 0; } @@ -8127,7 +8127,7 @@ char* pc_readregistry_str(struct map_session_data *sd,const char *reg,int type) if (max == -1) { ShowError("pc_readregistry: Trying to read reg value %s (type %d) before it's been loaded!\n", reg, type); //This really shouldn't happen, so it's possible the data was lost somewhere, we should request it again. - intif_request_registry(sd,type==3?4:type); + intif->request_registry(sd,type==3?4:type); return NULL; } @@ -8272,7 +8272,7 @@ int pc_setregistry_str(struct map_session_data *sd,const char *reg,const char *v memset(&sd_reg[*max - 1], 0, sizeof(struct global_reg)); (*max)--; sd->state.reg_dirty |= 1<<(type-1); //Mark this registry as "need to be saved" - if (type!=3) intif_saveregistry(sd,type); + if (type!=3) intif->saveregistry(sd,type); } return 1; } @@ -8283,7 +8283,7 @@ int pc_setregistry_str(struct map_session_data *sd,const char *reg,const char *v { safestrncpy(sd_reg[i].value, val, sizeof(sd_reg[i].value)); sd->state.reg_dirty |= 1<<(type-1); //Mark this registry as "need to be saved" - if (type!=3) intif_saveregistry(sd,type); + if (type!=3) intif->saveregistry(sd,type); return 1; } @@ -8294,7 +8294,7 @@ int pc_setregistry_str(struct map_session_data *sd,const char *reg,const char *v safestrncpy(sd_reg[i].value, val, sizeof(sd_reg[i].value)); (*max)++; sd->state.reg_dirty |= 1<<(type-1); //Mark this registry as "need to be saved" - if (type!=3) intif_saveregistry(sd,type); + if (type!=3) intif->saveregistry(sd,type); return 1; } @@ -9356,7 +9356,7 @@ int map_day_timer(int tid, unsigned int tick, int id, intptr_t data) iMap->night_flag = 0; // 0=day, 1=night [Yor] iMap->map_foreachpc(pc_daynight_timer_sub); strcpy(tmp_soutput, (data == 0) ? msg_txt(502) : msg_txt(60)); // The day has arrived! - intif_broadcast(tmp_soutput, strlen(tmp_soutput) + 1, 0); + intif->broadcast(tmp_soutput, strlen(tmp_soutput) + 1, 0); return 0; } @@ -9377,7 +9377,7 @@ int map_night_timer(int tid, unsigned int tick, int id, intptr_t data) iMap->night_flag = 1; // 0=day, 1=night [Yor] iMap->map_foreachpc(pc_daynight_timer_sub); strcpy(tmp_soutput, (data == 0) ? msg_txt(503) : msg_txt(59)); // The night has fallen... - intif_broadcast(tmp_soutput, strlen(tmp_soutput) + 1, 0); + intif->broadcast(tmp_soutput, strlen(tmp_soutput) + 1, 0); return 0; } diff --git a/src/map/pet.c b/src/map/pet.c index c83027f2a..236ffe98b 100644 --- a/src/map/pet.c +++ b/src/map/pet.c @@ -78,7 +78,7 @@ int pet_create_egg(struct map_session_data *sd, int item_id) if (pet_id < 0) return 0; //No pet egg here. if (!pc->inventoryblank(sd)) return 0; // Inventory full sd->catch_target_class = pet_db[pet_id].class_; - intif_create_pet(sd->status.account_id, sd->status.char_id, + intif->create_pet(sd->status.account_id, sd->status.char_id, (short)pet_db[pet_id].class_, (short)mob_db(pet_db[pet_id].class_)->lv, (short)pet_db[pet_id].EggID, 0, @@ -334,7 +334,7 @@ int pet_data_init(struct map_session_data *sd, struct s_pet *pet) if (sd->status.pet_id) { //Wrong pet?? Set incuvate to no and send it back for saving. pet->incuvate = 1; - intif_save_petdata(sd->status.account_id,pet); + intif->save_petdata(sd->status.account_id,pet); sd->status.pet_id = 0; return 1; } @@ -406,7 +406,7 @@ int pet_birth_process(struct map_session_data *sd, struct s_pet *pet) return 1; } - intif_save_petdata(sd->status.account_id,pet); + intif->save_petdata(sd->status.account_id,pet); if (iMap->save_settings&8) chrif->save(sd,0); //is it REALLY Needed to save the char for hatching a pet? [Skotlex] @@ -472,7 +472,7 @@ int pet_select_egg(struct map_session_data *sd,short egg_index) return 0; //Forged packet! if(sd->status.inventory[egg_index].card[0] == CARD0_PET) - intif_request_petdata(sd->status.account_id, sd->status.char_id, MakeDWord(sd->status.inventory[egg_index].card[1], sd->status.inventory[egg_index].card[2]) ); + intif->request_petdata(sd->status.account_id, sd->status.char_id, MakeDWord(sd->status.inventory[egg_index].card[1], sd->status.inventory[egg_index].card[2]) ); else ShowError("wrong egg item inventory %d\n",egg_index); @@ -529,7 +529,7 @@ int pet_catch_process2(struct map_session_data* sd, int target_id) unit_remove_map(&md->bl,CLR_OUTSIGHT); status_kill(&md->bl); clif->pet_roulette(sd,1); - intif_create_pet(sd->status.account_id,sd->status.char_id,pet_db[i].class_,mob_db(pet_db[i].class_)->lv, + intif->create_pet(sd->status.account_id,sd->status.char_id,pet_db[i].class_,mob_db(pet_db[i].class_)->lv, pet_db[i].EggID,0,pet_db[i].intimate,100,0,1,pet_db[i].jname); } else @@ -558,7 +558,7 @@ int pet_get_egg(int account_id,int pet_id,int flag) sd->catch_target_class = -1; if(i < 0) { - intif_delete_petdata(pet_id); + intif->delete_petdata(pet_id); return 0; } diff --git a/src/map/quest.c b/src/map/quest.c index 3776d603f..e1e180786 100644 --- a/src/map/quest.c +++ b/src/map/quest.c @@ -23,7 +23,6 @@ #include "log.h" #include "clif.h" #include "quest.h" -#include "intif.h" #include "chrif.h" #include diff --git a/src/map/script.c b/src/map/script.c index 0827eb497..5e99d2e62 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -3532,9 +3532,9 @@ void run_script_main(struct script_state *st) //Restore previous script if any. script_detach_state(st, true); if (sd->state.reg_dirty&2) - intif_saveregistry(sd,2); + intif->saveregistry(sd,2); if (sd->state.reg_dirty&1) - intif_saveregistry(sd,1); + intif->saveregistry(sd,1); } script->free_state(st); st = NULL; @@ -6252,7 +6252,7 @@ static void buildin_delitem_delete(struct map_session_data* sd, int idx, int* am { if( sd->inventory_data[idx]->type == IT_PETEGG && inv->card[0] == CARD0_PET ) {// delete associated pet - intif_delete_petdata(MakeDWord(inv->card[1], inv->card[2])); + intif->delete_petdata(MakeDWord(inv->card[1], inv->card[2])); } pc->delitem(sd, idx, delamount, 0, 0, LOG_TYPE_SCRIPT); } @@ -6316,7 +6316,7 @@ static bool buildin_delitem_search(struct map_session_data* sd, struct item* it, { if( sd->inventory_data[i]->type == IT_PETEGG ) { - if( inv->card[0] == CARD0_PET && CheckForCharServer() ) + if( inv->card[0] == CARD0_PET && intif->CheckForCharServer() ) {// pet which cannot be deleted continue; } @@ -6346,7 +6346,7 @@ static bool buildin_delitem_search(struct map_session_data* sd, struct item* it, continue; } - if( sd->inventory_data[i]->type == IT_PETEGG && inv->card[0] == CARD0_PET && CheckForCharServer() ) + if( sd->inventory_data[i]->type == IT_PETEGG && inv->card[0] == CARD0_PET && intif->CheckForCharServer() ) {// pet which cannot be deleted continue; } @@ -8311,7 +8311,7 @@ BUILDIN(makepet) pet_id = search_petDB_index(id, PET_EGG); if (pet_id >= 0 && sd) { sd->catch_target_class = pet_db[pet_id].class_; - intif_create_pet( + intif->create_pet( sd->status.account_id, sd->status.char_id, (short)pet_db[pet_id].class_, (short)mob_db(pet_db[pet_id].class_)->lv, (short)pet_db[pet_id].EggID, 0, (short)pet_db[pet_id].intimate, @@ -9124,9 +9124,9 @@ BUILDIN(announce) else { if (fontColor) - intif_broadcast2(mes, (int)strlen(mes)+1, strtol(fontColor, (char **)NULL, 0), fontType, fontSize, fontAlign, fontY); + intif->broadcast2(mes, (int)strlen(mes)+1, strtol(fontColor, (char **)NULL, 0), fontType, fontSize, fontAlign, fontY); else - intif_broadcast(mes, (int)strlen(mes)+1, flag&0xf0); + intif->broadcast(mes, (int)strlen(mes)+1, flag&0xf0); } return true; } diff --git a/src/map/storage.c b/src/map/storage.c index 5ebbb0dde..81d746cc8 100644 --- a/src/map/storage.c +++ b/src/map/storage.c @@ -400,7 +400,7 @@ int storage_guild_storageopen(struct map_session_data* sd) } if((gstor = gstorage->id2storage2(sd->status.guild_id)) == NULL) { - intif_request_guild_storage(sd->status.account_id,sd->status.guild_id); + intif->request_guild_storage(sd->status.account_id,sd->status.guild_id); return 0; } if(gstor->storage_status) @@ -657,7 +657,7 @@ int storage_guild_storagesave(int account_id, int guild_id, int flag) if (flag) //Char quitting, close it. stor->storage_status = 0; if (stor->dirty) - intif_send_guild_storage(account_id,stor); + intif->send_guild_storage(account_id,stor); return 1; } return 0; diff --git a/src/map/trade.c b/src/map/trade.c index 13b5f5431..9bf63c428 100644 --- a/src/map/trade.c +++ b/src/map/trade.c @@ -203,9 +203,9 @@ int impossible_trade_check(struct map_session_data *sd) if (inventory[index].amount < sd->deal.item[i].amount) { // if more than the player have -> hack sprintf(message_to_gm, msg_txt(538), sd->status.name, sd->status.account_id); // Hack on trade: character '%s' (account: %d) try to trade more items that he has. - intif_wis_message_to_gm(iMap->wisp_server_name, PC_PERM_RECEIVE_HACK_INFO, message_to_gm); + intif->wis_message_to_gm(iMap->wisp_server_name, PC_PERM_RECEIVE_HACK_INFO, message_to_gm); sprintf(message_to_gm, msg_txt(539), inventory[index].amount, inventory[index].nameid, sd->deal.item[i].amount); // This player has %d of a kind of item (id: %d), and try to trade %d of them. - intif_wis_message_to_gm(iMap->wisp_server_name, PC_PERM_RECEIVE_HACK_INFO, message_to_gm); + intif->wis_message_to_gm(iMap->wisp_server_name, PC_PERM_RECEIVE_HACK_INFO, message_to_gm); // if we block people if (battle_config.ban_hack_trade < 0) { chrif->char_ask_name(-1, sd->status.name, 1, 0, 0, 0, 0, 0, 0); // type: 1 - block @@ -222,7 +222,7 @@ int impossible_trade_check(struct map_session_data *sd) // message about the ban strcpy(message_to_gm, msg_txt(508)); // This player hasn't been banned (Ban option is disabled). - intif_wis_message_to_gm(iMap->wisp_server_name, PC_PERM_RECEIVE_HACK_INFO, message_to_gm); + intif->wis_message_to_gm(iMap->wisp_server_name, PC_PERM_RECEIVE_HACK_INFO, message_to_gm); return 1; } inventory[index].amount -= sd->deal.item[i].amount; // remove item from inventory diff --git a/src/map/unit.c b/src/map/unit.c index 8a11363cb..b9cdfa278 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -2443,10 +2443,10 @@ int unit_free(struct block_list *bl, clr_type clrtype) pd->loot = NULL; } if( pd->pet.intimate > 0 ) - intif_save_petdata(pd->pet.account_id,&pd->pet); + intif->save_petdata(pd->pet.account_id,&pd->pet); else { //Remove pet. - intif_delete_petdata(pd->pet.pet_id); + intif->delete_petdata(pd->pet.pet_id); if (sd) sd->status.pet_id = 0; } if( sd ) @@ -2519,7 +2519,7 @@ int unit_free(struct block_list *bl, clr_type clrtype) if( hd->homunculus.intimacy > 0 ) homun->save(hd); else { - intif_homunculus_requestdelete(hd->homunculus.hom_id); + intif->homunculus_requestdelete(hd->homunculus.hom_id); if( sd ) sd->status.hom_id = 0; } @@ -2535,7 +2535,7 @@ int unit_free(struct block_list *bl, clr_type clrtype) mercenary_save(md); else { - intif_mercenary_delete(md->mercenary.mercenary_id); + intif->mercenary_delete(md->mercenary.mercenary_id); if( sd ) sd->status.mer_id = 0; } @@ -2551,7 +2551,7 @@ int unit_free(struct block_list *bl, clr_type clrtype) if( elemental->get_lifetime(ed) > 0 ) elemental->save(ed); else { - intif_elemental_delete(ed->elemental.elemental_id); + intif->elemental_delete(ed->elemental.elemental_id); if( sd ) sd->status.ele_id = 0; } -- cgit v1.2.3-60-g2f50 From b7171479a47490ff80bf04849f763158d6d96fac Mon Sep 17 00:00:00 2001 From: Susu Date: Mon, 29 Jul 2013 16:05:51 +0200 Subject: Added mercenary interface --- src/map/atcommand.c | 6 +- src/map/chrif.c | 4 +- src/map/clif.c | 16 +- src/map/intif.c | 4703 ++++++++++++++++++++++++++------------------------- src/map/map.c | 4 +- src/map/mercenary.c | 1062 ++++++------ src/map/mercenary.h | 180 +- src/map/mob.c | 2 +- src/map/pc.c | 2 +- src/map/script.c | 12 +- src/map/status.c | 12 +- src/map/unit.c | 8 +- 12 files changed, 3034 insertions(+), 2977 deletions(-) diff --git a/src/map/atcommand.c b/src/map/atcommand.c index 018098928..d8ca2389f 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -3598,8 +3598,8 @@ ACMD(reloadmobdb) { mob_reload(); read_petdb(); homun->reload(); - read_mercenarydb(); - read_mercenary_skilldb(); + mercenary->read_mercenarydb(); + mercenary->read_skilldb(); elemental->reload_elementaldb(); clif->message(fd, msg_txt(98)); // Monster database has been reloaded. @@ -3615,7 +3615,7 @@ ACMD(reloadskilldb) skill->reload(); homun->reload_skill(); elemental->reload_skilldb(); - read_mercenary_skilldb(); + mercenary->read_skilldb(); clif->message(fd, msg_txt(99)); // Skill database has been reloaded. return true; diff --git a/src/map/chrif.c b/src/map/chrif.c index d1ee8b5b1..d44ccf721 100644 --- a/src/map/chrif.c +++ b/src/map/chrif.c @@ -312,8 +312,8 @@ int chrif_save(struct map_session_data *sd, int flag) { intif->save_petdata(sd->status.account_id,&sd->pd->pet); if( sd->hd && homun_alive(sd->hd) ) homun->save(sd->hd); - if( sd->md && mercenary_get_lifetime(sd->md) > 0 ) - mercenary_save(sd->md); + if( sd->md && mercenary->get_lifetime(sd->md) > 0 ) + mercenary->save(sd->md); if( sd->ed && elemental->get_lifetime(sd->ed) > 0 ) elemental->save(sd->ed); if( sd->save_quest ) diff --git a/src/map/clif.c b/src/map/clif.c index f5ce8ede3..446adda28 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -7197,7 +7197,7 @@ void clif_devotion(struct block_list *src, struct map_session_data *tsd) if( md && md->master && md->devotion_flag ) WBUFL(buf,6) = md->master->bl.id; - WBUFW(buf,26) = skill->get_range2(src, ML_DEVOTION, mercenary_checkskill(md, ML_DEVOTION)); + WBUFW(buf,26) = skill->get_range2(src, ML_DEVOTION, mercenary->checkskill(md, ML_DEVOTION)); } else { @@ -11289,7 +11289,7 @@ void clif_parse_UseSkillToId_mercenary(struct mercenary_data *md, struct map_ses } else if( DIFF_TICK(tick, md->ud.canact_tick) < 0 ) return; - lv = mercenary_checkskill(md, skill_id); + lv = mercenary->checkskill(md, skill_id); if( skill_lv > lv ) skill_lv = lv; if( skill_lv ) @@ -11312,7 +11312,7 @@ void clif_parse_UseSkillToPos_mercenary(struct mercenary_data *md, struct map_se if( md->sc.data[SC_BASILICA] ) return; - lv = mercenary_checkskill(md, skill_id); + lv = mercenary->checkskill(md, skill_id); if( skill_lv > lv ) skill_lv = lv; if( skill_lv ) @@ -15677,7 +15677,7 @@ void clif_mercenary_updatestatus(struct map_session_data *sd, int type) WFIFOL(fd,4) = md->mercenary.kill_count; break; case SP_MERCFAITH: - WFIFOL(fd,4) = mercenary_get_faith(md); + WFIFOL(fd,4) = mercenary->get_faith(md); break; } WFIFOSET(fd,packet_len(0x2a2)); @@ -15721,9 +15721,9 @@ void clif_mercenary_info(struct map_session_data *sd) WFIFOL(fd,52) = status->max_hp; WFIFOL(fd,56) = status->sp; WFIFOL(fd,60) = status->max_sp; - WFIFOL(fd,64) = (int)time(NULL) + (mercenary_get_lifetime(md) / 1000); - WFIFOW(fd,68) = mercenary_get_faith(md); - WFIFOL(fd,70) = mercenary_get_calls(md); + WFIFOL(fd,64) = (int)time(NULL) + (mercenary->get_lifetime(md) / 1000); + WFIFOW(fd,68) = mercenary->get_faith(md); + WFIFOL(fd,70) = mercenary->get_calls(md); WFIFOL(fd,74) = md->mercenary.kill_count; WFIFOW(fd,78) = md->battle_status.rhw.range; WFIFOSET(fd,packet_len(0x29b)); @@ -15773,7 +15773,7 @@ void clif_parse_mercenary_action(int fd, struct map_session_data* sd) if( sd->md == NULL ) return; - if( option == 2 ) merc_delete(sd->md, 2); + if( option == 2 ) mercenary->merc_delete(sd->md, 2); } diff --git a/src/map/intif.c b/src/map/intif.c index 813c1cf7c..4d75dcbb7 100644 --- a/src/map/intif.c +++ b/src/map/intif.c @@ -1,2351 +1,2352 @@ -// Copyright (c) Athena Dev Teams - Licensed under GNU GPL -// For more information, see LICENCE in the main folder - -#include "../common/showmsg.h" -#include "../common/socket.h" -#include "../common/timer.h" -#include "../common/nullpo.h" -#include "../common/malloc.h" -#include "../common/strlib.h" -#include "map.h" -#include "battle.h" -#include "chrif.h" -#include "clif.h" -#include "pc.h" -#include "intif.h" -#include "log.h" -#include "storage.h" -#include "party.h" -#include "guild.h" -#include "pet.h" -#include "atcommand.h" -#include "mercenary.h" -#include "homunculus.h" -#include "elemental.h" -#include "mail.h" -#include "quest.h" - -#include -#include -#include -#include -#include -#include - - -static const int packet_len_table[]={ - -1,-1,27,-1, -1, 0,37,-1, 0, 0, 0, 0, 0, 0, 0, 0, //0x3800-0x380f - 0, 0, 0, 0, 0, 0, 0, 0, -1,11, 0, 0, 0, 0, 0, 0, //0x3810 - 39,-1,15,15, 14,19, 7,-1, 0, 0, 0, 0, 0, 0, 0, 0, //0x3820 - 10,-1,15, 0, 79,19, 7,-1, 0,-1,-1,-1, 14,67,186,-1, //0x3830 - -1, 0, 0,14, 0, 0, 0, 0, -1,74,-1,11, 11,-1, 0, 0, //0x3840 - -1,-1, 7, 7, 7,11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3850 Auctions [Zephyrus] - -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3860 Quests [Kevin] [Inkfish] - -1, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 3, 3, 0, //0x3870 Mercenaries [Zephyrus] / Elemental [pakpil] - 11,-1, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3880 - -1,-1, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3890 Homunculus [albator] -}; - -extern int char_fd; // inter server Fd used for char_fd -#define inter_fd char_fd // alias - -//----------------------------------------------------------------- -// Send to inter server - -int CheckForCharServer(void) -{ - return ((char_fd <= 0) || session[char_fd] == NULL || session[char_fd]->wdata == NULL); -} - -// pet -int intif_create_pet(int account_id,int char_id,short pet_class,short pet_lv,short pet_egg_id, - short pet_equip,short intimate,short hungry,char rename_flag,char incuvate,char *pet_name) -{ - if (intif->CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd, 24 + NAME_LENGTH); - WFIFOW(inter_fd,0) = 0x3080; - WFIFOL(inter_fd,2) = account_id; - WFIFOL(inter_fd,6) = char_id; - WFIFOW(inter_fd,10) = pet_class; - WFIFOW(inter_fd,12) = pet_lv; - WFIFOW(inter_fd,14) = pet_egg_id; - WFIFOW(inter_fd,16) = pet_equip; - WFIFOW(inter_fd,18) = intimate; - WFIFOW(inter_fd,20) = hungry; - WFIFOB(inter_fd,22) = rename_flag; - WFIFOB(inter_fd,23) = incuvate; - memcpy(WFIFOP(inter_fd,24),pet_name,NAME_LENGTH); - WFIFOSET(inter_fd,24+NAME_LENGTH); - - return 0; -} - -int intif_request_petdata(int account_id,int char_id,int pet_id) -{ - if (intif->CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd, 14); - WFIFOW(inter_fd,0) = 0x3081; - WFIFOL(inter_fd,2) = account_id; - WFIFOL(inter_fd,6) = char_id; - WFIFOL(inter_fd,10) = pet_id; - WFIFOSET(inter_fd,14); - - return 0; -} - -int intif_save_petdata(int account_id,struct s_pet *p) -{ - if (intif->CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd, sizeof(struct s_pet) + 8); - WFIFOW(inter_fd,0) = 0x3082; - WFIFOW(inter_fd,2) = sizeof(struct s_pet) + 8; - WFIFOL(inter_fd,4) = account_id; - memcpy(WFIFOP(inter_fd,8),p,sizeof(struct s_pet)); - WFIFOSET(inter_fd,WFIFOW(inter_fd,2)); - - return 0; -} - -int intif_delete_petdata(int pet_id) -{ - if (intif->CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd,6); - WFIFOW(inter_fd,0) = 0x3083; - WFIFOL(inter_fd,2) = pet_id; - WFIFOSET(inter_fd,6); - - return 1; -} - -int intif_rename(struct map_session_data *sd, int type, char *name) -{ - if (intif->CheckForCharServer()) - return 1; - - WFIFOHEAD(inter_fd,NAME_LENGTH+12); - WFIFOW(inter_fd,0) = 0x3006; - WFIFOL(inter_fd,2) = sd->status.account_id; - WFIFOL(inter_fd,6) = sd->status.char_id; - WFIFOB(inter_fd,10) = type; //Type: 0 - PC, 1 - PET, 2 - HOM - memcpy(WFIFOP(inter_fd,11),name, NAME_LENGTH); - WFIFOSET(inter_fd,NAME_LENGTH+12); - return 0; -} - -// GM Send a message -int intif_broadcast(const char* mes, int len, int type) -{ - int lp = type ? 4 : 0; - - // Send to the local players - clif->broadcast(NULL, mes, len, type, ALL_CLIENT); - - if (intif->CheckForCharServer()) - return 0; - - if (chrif->other_mapserver_count < 1) - return 0; //No need to send. - - WFIFOHEAD(inter_fd, 16 + lp + len); - WFIFOW(inter_fd,0) = 0x3000; - WFIFOW(inter_fd,2) = 16 + lp + len; - WFIFOL(inter_fd,4) = 0xFF000000; // 0xFF000000 color signals standard broadcast - WFIFOW(inter_fd,8) = 0; // fontType not used with standard broadcast - WFIFOW(inter_fd,10) = 0; // fontSize not used with standard broadcast - WFIFOW(inter_fd,12) = 0; // fontAlign not used with standard broadcast - WFIFOW(inter_fd,14) = 0; // fontY not used with standard broadcast - if (type == 0x10) // bc_blue - WFIFOL(inter_fd,16) = 0x65756c62; //If there's "blue" at the beginning of the message, game client will display it in blue instead of yellow. - else if (type == 0x20) // bc_woe - WFIFOL(inter_fd,16) = 0x73737373; //If there's "ssss", game client will recognize message as 'WoE broadcast'. - memcpy(WFIFOP(inter_fd,16 + lp), mes, len); - WFIFOSET(inter_fd, WFIFOW(inter_fd,2)); - return 0; -} - -int intif_broadcast2(const char* mes, int len, unsigned long fontColor, short fontType, short fontSize, short fontAlign, short fontY) -{ - // Send to the local players - clif->broadcast2(NULL, mes, len, fontColor, fontType, fontSize, fontAlign, fontY, ALL_CLIENT); - - if (intif->CheckForCharServer()) - return 0; - - if (chrif->other_mapserver_count < 1) - return 0; //No need to send. - - WFIFOHEAD(inter_fd, 16 + len); - WFIFOW(inter_fd,0) = 0x3000; - WFIFOW(inter_fd,2) = 16 + len; - WFIFOL(inter_fd,4) = fontColor; - WFIFOW(inter_fd,8) = fontType; - WFIFOW(inter_fd,10) = fontSize; - WFIFOW(inter_fd,12) = fontAlign; - WFIFOW(inter_fd,14) = fontY; - memcpy(WFIFOP(inter_fd,16), mes, len); - WFIFOSET(inter_fd, WFIFOW(inter_fd,2)); - return 0; -} - -/// send a message using the main chat system -/// the source of message -/// the message that was sent -int intif_main_message(struct map_session_data* sd, const char* message) -{ - char output[256]; - - nullpo_ret(sd); - - // format the message for main broadcasting - snprintf( output, sizeof(output), msg_txt(386), sd->status.name, message ); - - // send the message using the inter-server broadcast service - intif_broadcast2( output, strlen(output) + 1, 0xFE000000, 0, 0, 0, 0 ); - - // log the chat message - logs->chat( LOG_CHAT_MAINCHAT, 0, sd->status.char_id, sd->status.account_id, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, NULL, message ); - - return 0; -} - -// The transmission of Wisp/Page to inter-server (player not found on this server) -int intif_wis_message(struct map_session_data *sd, char *nick, char *mes, int mes_len) -{ - nullpo_ret(sd); - if (intif->CheckForCharServer()) - return 0; - - if (chrif->other_mapserver_count < 1) - { //Character not found. - clif->wis_end(sd->fd, 1); - return 0; - } - - WFIFOHEAD(inter_fd,mes_len + 52); - WFIFOW(inter_fd,0) = 0x3001; - WFIFOW(inter_fd,2) = mes_len + 52; - memcpy(WFIFOP(inter_fd,4), sd->status.name, NAME_LENGTH); - memcpy(WFIFOP(inter_fd,4+NAME_LENGTH), nick, NAME_LENGTH); - memcpy(WFIFOP(inter_fd,4+2*NAME_LENGTH), mes, mes_len); - WFIFOSET(inter_fd, WFIFOW(inter_fd,2)); - - if (battle_config.etc_log) - ShowInfo("intif_wis_message from %s to %s (message: '%s')\n", sd->status.name, nick, mes); - - return 0; -} - -// The reply of Wisp/page -int intif_wis_replay(int id, int flag) -{ - if (intif->CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd,7); - WFIFOW(inter_fd,0) = 0x3002; - WFIFOL(inter_fd,2) = id; - WFIFOB(inter_fd,6) = flag; // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target - WFIFOSET(inter_fd,7); - - if (battle_config.etc_log) - ShowInfo("intif_wis_replay: id: %d, flag:%d\n", id, flag); - - return 0; -} - -// The transmission of GM only Wisp/Page from server to inter-server -int intif_wis_message_to_gm(char *wisp_name, int permission, char *mes) -{ - int mes_len; - if (intif->CheckForCharServer()) - return 0; - mes_len = strlen(mes) + 1; // + null - WFIFOHEAD(inter_fd, mes_len + 32); - WFIFOW(inter_fd,0) = 0x3003; - WFIFOW(inter_fd,2) = mes_len + 32; - memcpy(WFIFOP(inter_fd,4), wisp_name, NAME_LENGTH); - WFIFOL(inter_fd,4+NAME_LENGTH) = permission; - memcpy(WFIFOP(inter_fd,8+NAME_LENGTH), mes, mes_len); - WFIFOSET(inter_fd, WFIFOW(inter_fd,2)); - - if (battle_config.etc_log) - ShowNotice("intif_wis_message_to_gm: from: '%s', required permission: %d, message: '%s'.\n", wisp_name, permission, mes); - - return 0; -} - -int intif_regtostr(char* str, struct global_reg *reg, int qty) -{ - int len =0, i; - - for (i = 0; i < qty; i++) { - len+= sprintf(str+len, "%s", reg[i].str)+1; //We add 1 to consider the '\0' in place. - len+= sprintf(str+len, "%s", reg[i].value)+1; - } - return len; -} - -//Request for saving registry values. -int intif_saveregistry(struct map_session_data *sd, int type) -{ - struct global_reg *reg; - int count; - int i, p; - - if (intif->CheckForCharServer()) - return -1; - - switch (type) { - case 3: //Character reg - reg = sd->save_reg.global; - count = sd->save_reg.global_num; - sd->state.reg_dirty &= ~0x4; - break; - case 2: //Account reg - reg = sd->save_reg.account; - count = sd->save_reg.account_num; - sd->state.reg_dirty &= ~0x2; - break; - case 1: //Account2 reg - reg = sd->save_reg.account2; - count = sd->save_reg.account2_num; - sd->state.reg_dirty &= ~0x1; - break; - default: //Broken code? - ShowError("intif_saveregistry: Invalid type %d\n", type); - return -1; - } - WFIFOHEAD(inter_fd, 288 * MAX_REG_NUM+13); - WFIFOW(inter_fd,0)=0x3004; - WFIFOL(inter_fd,4)=sd->status.account_id; - WFIFOL(inter_fd,8)=sd->status.char_id; - WFIFOB(inter_fd,12)=type; - for( p = 13, i = 0; i < count; i++ ) { - if (reg[i].str[0] != '\0' && reg[i].value[0] != '\0') { - p+= sprintf((char*)WFIFOP(inter_fd,p), "%s", reg[i].str)+1; //We add 1 to consider the '\0' in place. - p+= sprintf((char*)WFIFOP(inter_fd,p), "%s", reg[i].value)+1; - } - } - WFIFOW(inter_fd,2)=p; - WFIFOSET(inter_fd,WFIFOW(inter_fd,2)); - return 0; -} - -//Request the registries for this player. -int intif_request_registry(struct map_session_data *sd, int flag) -{ - nullpo_ret(sd); - - sd->save_reg.account2_num = -1; - sd->save_reg.account_num = -1; - sd->save_reg.global_num = -1; - - if (intif->CheckForCharServer()) - return 0; - - WFIFOHEAD(inter_fd,6); - WFIFOW(inter_fd,0) = 0x3005; - WFIFOL(inter_fd,2) = sd->status.account_id; - WFIFOL(inter_fd,6) = sd->status.char_id; - WFIFOB(inter_fd,10) = (flag&1?1:0); //Request Acc Reg 2 - WFIFOB(inter_fd,11) = (flag&2?1:0); //Request Acc Reg - WFIFOB(inter_fd,12) = (flag&4?1:0); //Request Char Reg - WFIFOSET(inter_fd,13); - - return 0; -} - -int intif_request_guild_storage(int account_id,int guild_id) -{ - if (intif->CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd,10); - WFIFOW(inter_fd,0) = 0x3018; - WFIFOL(inter_fd,2) = account_id; - WFIFOL(inter_fd,6) = guild_id; - WFIFOSET(inter_fd,10); - return 0; -} -int intif_send_guild_storage(int account_id,struct guild_storage *gstor) -{ - if (intif->CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd,sizeof(struct guild_storage)+12); - WFIFOW(inter_fd,0) = 0x3019; - WFIFOW(inter_fd,2) = (unsigned short)sizeof(struct guild_storage)+12; - WFIFOL(inter_fd,4) = account_id; - WFIFOL(inter_fd,8) = gstor->guild_id; - memcpy( WFIFOP(inter_fd,12),gstor, sizeof(struct guild_storage) ); - WFIFOSET(inter_fd,WFIFOW(inter_fd,2)); - return 0; -} - -// Party creation request -int intif_create_party(struct party_member *member,char *name,int item,int item2) -{ - if (intif->CheckForCharServer()) - return 0; - nullpo_ret(member); - - WFIFOHEAD(inter_fd,64); - WFIFOW(inter_fd,0) = 0x3020; - WFIFOW(inter_fd,2) = 30+sizeof(struct party_member); - memcpy(WFIFOP(inter_fd,4),name, NAME_LENGTH); - WFIFOB(inter_fd,28)= item; - WFIFOB(inter_fd,29)= item2; - memcpy(WFIFOP(inter_fd,30), member, sizeof(struct party_member)); - WFIFOSET(inter_fd,WFIFOW(inter_fd, 2)); - return 0; -} - -// Party information request -int intif_request_partyinfo(int party_id, int char_id) -{ - if (intif->CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd,10); - WFIFOW(inter_fd,0) = 0x3021; - WFIFOL(inter_fd,2) = party_id; - WFIFOL(inter_fd,6) = char_id; - WFIFOSET(inter_fd,10); - return 0; -} - -// Request to add a member to party -int intif_party_addmember(int party_id,struct party_member *member) -{ - if (intif->CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd,42); - WFIFOW(inter_fd,0)=0x3022; - WFIFOW(inter_fd,2)=8+sizeof(struct party_member); - WFIFOL(inter_fd,4)=party_id; - memcpy(WFIFOP(inter_fd,8),member,sizeof(struct party_member)); - WFIFOSET(inter_fd,WFIFOW(inter_fd, 2)); - return 1; -} - -// Request to change party configuration (exp,item share) -int intif_party_changeoption(int party_id,int account_id,int exp,int item) -{ - if (intif->CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd,14); - WFIFOW(inter_fd,0)=0x3023; - WFIFOL(inter_fd,2)=party_id; - WFIFOL(inter_fd,6)=account_id; - WFIFOW(inter_fd,10)=exp; - WFIFOW(inter_fd,12)=item; - WFIFOSET(inter_fd,14); - return 0; -} - -// Request to leave party -int intif_party_leave(int party_id,int account_id, int char_id) -{ - if (intif->CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd,14); - WFIFOW(inter_fd,0)=0x3024; - WFIFOL(inter_fd,2)=party_id; - WFIFOL(inter_fd,6)=account_id; - WFIFOL(inter_fd,10)=char_id; - WFIFOSET(inter_fd,14); - return 0; -} - -// Request keeping party for new map ?? -int intif_party_changemap(struct map_session_data *sd,int online) -{ - int16 m, mapindex; - - if (intif->CheckForCharServer()) - return 0; - if(!sd) - return 0; - - if( (m=iMap->mapindex2mapid(sd->mapindex)) >= 0 && map[m].instance_id >= 0 ) - mapindex = map[map[m].instance_src_map].index; - else - mapindex = sd->mapindex; - - WFIFOHEAD(inter_fd,19); - WFIFOW(inter_fd,0)=0x3025; - WFIFOL(inter_fd,2)=sd->status.party_id; - WFIFOL(inter_fd,6)=sd->status.account_id; - WFIFOL(inter_fd,10)=sd->status.char_id; - WFIFOW(inter_fd,14)=mapindex; - WFIFOB(inter_fd,16)=online; - WFIFOW(inter_fd,17)=sd->status.base_level; - WFIFOSET(inter_fd,19); - return 1; -} - -// Request breaking party -int intif_break_party(int party_id) -{ - if (intif->CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd,6); - WFIFOW(inter_fd,0)=0x3026; - WFIFOL(inter_fd,2)=party_id; - WFIFOSET(inter_fd,6); - return 0; -} - -// Sending party chat -int intif_party_message(int party_id,int account_id,const char *mes,int len) -{ - if (intif->CheckForCharServer()) - return 0; - - if (chrif->other_mapserver_count < 1) - return 0; //No need to send. - - WFIFOHEAD(inter_fd,len + 12); - WFIFOW(inter_fd,0)=0x3027; - WFIFOW(inter_fd,2)=len+12; - WFIFOL(inter_fd,4)=party_id; - WFIFOL(inter_fd,8)=account_id; - memcpy(WFIFOP(inter_fd,12),mes,len); - WFIFOSET(inter_fd,len+12); - return 0; -} - -// Request a new leader for party -int intif_party_leaderchange(int party_id,int account_id,int char_id) -{ - if (intif->CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd,14); - WFIFOW(inter_fd,0)=0x3029; - WFIFOL(inter_fd,2)=party_id; - WFIFOL(inter_fd,6)=account_id; - WFIFOL(inter_fd,10)=char_id; - WFIFOSET(inter_fd,14); - return 0; -} - -// Request a Guild creation -int intif_guild_create(const char *name,const struct guild_member *master) -{ - if (intif->CheckForCharServer()) - return 0; - nullpo_ret(master); - - WFIFOHEAD(inter_fd,sizeof(struct guild_member)+(8+NAME_LENGTH)); - WFIFOW(inter_fd,0)=0x3030; - WFIFOW(inter_fd,2)=sizeof(struct guild_member)+(8+NAME_LENGTH); - WFIFOL(inter_fd,4)=master->account_id; - memcpy(WFIFOP(inter_fd,8),name,NAME_LENGTH); - memcpy(WFIFOP(inter_fd,8+NAME_LENGTH),master,sizeof(struct guild_member)); - WFIFOSET(inter_fd,WFIFOW(inter_fd,2)); - return 0; -} - -// Request Guild information -int intif_guild_request_info(int guild_id) -{ - if (intif->CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd,6); - WFIFOW(inter_fd,0) = 0x3031; - WFIFOL(inter_fd,2) = guild_id; - WFIFOSET(inter_fd,6); - return 0; -} - -// Request to add member to the guild -int intif_guild_addmember(int guild_id,struct guild_member *m) -{ - if (intif->CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd,sizeof(struct guild_member)+8); - WFIFOW(inter_fd,0) = 0x3032; - WFIFOW(inter_fd,2) = sizeof(struct guild_member)+8; - WFIFOL(inter_fd,4) = guild_id; - memcpy(WFIFOP(inter_fd,8),m,sizeof(struct guild_member)); - WFIFOSET(inter_fd,WFIFOW(inter_fd,2)); - return 0; -} - -// Request a new leader for guild -int intif_guild_change_gm(int guild_id, const char* name, int len) -{ - if (intif->CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd, len + 8); - WFIFOW(inter_fd, 0)=0x3033; - WFIFOW(inter_fd, 2)=len+8; - WFIFOL(inter_fd, 4)=guild_id; - memcpy(WFIFOP(inter_fd,8),name,len); - WFIFOSET(inter_fd,len+8); - return 0; -} - -// Request to leave guild -int intif_guild_leave(int guild_id,int account_id,int char_id,int flag,const char *mes) -{ - if (intif->CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd, 55); - WFIFOW(inter_fd, 0) = 0x3034; - WFIFOL(inter_fd, 2) = guild_id; - WFIFOL(inter_fd, 6) = account_id; - WFIFOL(inter_fd,10) = char_id; - WFIFOB(inter_fd,14) = flag; - safestrncpy((char*)WFIFOP(inter_fd,15),mes,40); - WFIFOSET(inter_fd,55); - return 0; -} - -//Update request / Lv online status of the guild members -int intif_guild_memberinfoshort(int guild_id,int account_id,int char_id,int online,int lv,int class_) -{ - if (intif->CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd, 19); - WFIFOW(inter_fd, 0) = 0x3035; - WFIFOL(inter_fd, 2) = guild_id; - WFIFOL(inter_fd, 6) = account_id; - WFIFOL(inter_fd,10) = char_id; - WFIFOB(inter_fd,14) = online; - WFIFOW(inter_fd,15) = lv; - WFIFOW(inter_fd,17) = class_; - WFIFOSET(inter_fd,19); - return 0; -} - -//Guild disbanded notification -int intif_guild_break(int guild_id) -{ - if (intif->CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd, 6); - WFIFOW(inter_fd, 0) = 0x3036; - WFIFOL(inter_fd, 2) = guild_id; - WFIFOSET(inter_fd,6); - return 0; -} - -// Send a guild message -int intif_guild_message(int guild_id,int account_id,const char *mes,int len) -{ - if (intif->CheckForCharServer()) - return 0; - - if (chrif->other_mapserver_count < 1) - return 0; //No need to send. - - WFIFOHEAD(inter_fd, len + 12); - WFIFOW(inter_fd,0)=0x3037; - WFIFOW(inter_fd,2)=len+12; - WFIFOL(inter_fd,4)=guild_id; - WFIFOL(inter_fd,8)=account_id; - memcpy(WFIFOP(inter_fd,12),mes,len); - WFIFOSET(inter_fd,len+12); - - return 0; -} - -// Request a change of Guild basic information -int intif_guild_change_basicinfo(int guild_id,int type,const void *data,int len) -{ - if (intif->CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd, len + 10); - WFIFOW(inter_fd,0)=0x3039; - WFIFOW(inter_fd,2)=len+10; - WFIFOL(inter_fd,4)=guild_id; - WFIFOW(inter_fd,8)=type; - memcpy(WFIFOP(inter_fd,10),data,len); - WFIFOSET(inter_fd,len+10); - return 0; -} - -// Request a change of Guild member information -int intif_guild_change_memberinfo(int guild_id,int account_id,int char_id, - int type,const void *data,int len) -{ - if (intif->CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd, len + 18); - WFIFOW(inter_fd, 0)=0x303a; - WFIFOW(inter_fd, 2)=len+18; - WFIFOL(inter_fd, 4)=guild_id; - WFIFOL(inter_fd, 8)=account_id; - WFIFOL(inter_fd,12)=char_id; - WFIFOW(inter_fd,16)=type; - memcpy(WFIFOP(inter_fd,18),data,len); - WFIFOSET(inter_fd,len+18); - return 0; -} - -// Request a change of Guild title -int intif_guild_position(int guild_id,int idx,struct guild_position *p) -{ - if (intif->CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd, sizeof(struct guild_position)+12); - WFIFOW(inter_fd,0)=0x303b; - WFIFOW(inter_fd,2)=sizeof(struct guild_position)+12; - WFIFOL(inter_fd,4)=guild_id; - WFIFOL(inter_fd,8)=idx; - memcpy(WFIFOP(inter_fd,12),p,sizeof(struct guild_position)); - WFIFOSET(inter_fd,WFIFOW(inter_fd,2)); - return 0; -} - -// Request an update of Guildskill skill_id -int intif_guild_skillup(int guild_id, uint16 skill_id, int account_id, int max) -{ - if( intif->CheckForCharServer() ) - return 0; - WFIFOHEAD(inter_fd, 18); - WFIFOW(inter_fd, 0) = 0x303c; - WFIFOL(inter_fd, 2) = guild_id; - WFIFOL(inter_fd, 6) = skill_id; - WFIFOL(inter_fd, 10) = account_id; - WFIFOL(inter_fd, 14) = max; - WFIFOSET(inter_fd, 18); - return 0; -} - -// Request a new guild relationship -int intif_guild_alliance(int guild_id1,int guild_id2,int account_id1,int account_id2,int flag) -{ - if (intif->CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd,19); - WFIFOW(inter_fd, 0)=0x303d; - WFIFOL(inter_fd, 2)=guild_id1; - WFIFOL(inter_fd, 6)=guild_id2; - WFIFOL(inter_fd,10)=account_id1; - WFIFOL(inter_fd,14)=account_id2; - WFIFOB(inter_fd,18)=flag; - WFIFOSET(inter_fd,19); - return 0; -} - -// Request to change guild notice -int intif_guild_notice(int guild_id,const char *mes1,const char *mes2) -{ - if (intif->CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd,186); - WFIFOW(inter_fd,0)=0x303e; - WFIFOL(inter_fd,2)=guild_id; - memcpy(WFIFOP(inter_fd,6),mes1,MAX_GUILDMES1); - memcpy(WFIFOP(inter_fd,66),mes2,MAX_GUILDMES2); - WFIFOSET(inter_fd,186); - return 0; -} - -// Request to change guild emblem -int intif_guild_emblem(int guild_id,int len,const char *data) -{ - if (intif->CheckForCharServer()) - return 0; - if(guild_id<=0 || len<0 || len>2000) - return 0; - WFIFOHEAD(inter_fd,len + 12); - WFIFOW(inter_fd,0)=0x303f; - WFIFOW(inter_fd,2)=len+12; - WFIFOL(inter_fd,4)=guild_id; - WFIFOL(inter_fd,8)=0; - memcpy(WFIFOP(inter_fd,12),data,len); - WFIFOSET(inter_fd,len+12); - return 0; -} - -/** - * Requests guild castles data from char-server. - * @param num Number of castles, size of castle_ids array. - * @param castle_ids Pointer to array of castle IDs. - */ -int intif_guild_castle_dataload(int num, int *castle_ids) -{ - if (intif->CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd, 4 + num * sizeof(int)); - WFIFOW(inter_fd, 0) = 0x3040; - WFIFOW(inter_fd, 2) = 4 + num * sizeof(int); - memcpy(WFIFOP(inter_fd, 4), castle_ids, num * sizeof(int)); - WFIFOSET(inter_fd, WFIFOW(inter_fd, 2)); - return 1; -} - - -// Request change castle guild owner and save data -int intif_guild_castle_datasave(int castle_id,int index, int value) -{ - if (intif->CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd,9); - WFIFOW(inter_fd,0)=0x3041; - WFIFOW(inter_fd,2)=castle_id; - WFIFOB(inter_fd,4)=index; - WFIFOL(inter_fd,5)=value; - WFIFOSET(inter_fd,9); - return 1; -} - -//----------------------------------------------------------------- -// Homunculus Packets send to Inter server [albator] -//----------------------------------------------------------------- - -int intif_homunculus_create(int account_id, struct s_homunculus *sh) -{ - if (intif->CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd, sizeof(struct s_homunculus)+8); - WFIFOW(inter_fd,0) = 0x3090; - WFIFOW(inter_fd,2) = sizeof(struct s_homunculus)+8; - WFIFOL(inter_fd,4) = account_id; - memcpy(WFIFOP(inter_fd,8),sh,sizeof(struct s_homunculus)); - WFIFOSET(inter_fd, WFIFOW(inter_fd,2)); - return 0; -} - -bool intif_homunculus_requestload(int account_id, int homun_id) { - if (intif->CheckForCharServer()) - return false; - WFIFOHEAD(inter_fd, 10); - WFIFOW(inter_fd,0) = 0x3091; - WFIFOL(inter_fd,2) = account_id; - WFIFOL(inter_fd,6) = homun_id; - WFIFOSET(inter_fd, 10); - return true; -} - -int intif_homunculus_requestsave(int account_id, struct s_homunculus* sh) -{ - if (intif->CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd, sizeof(struct s_homunculus)+8); - WFIFOW(inter_fd,0) = 0x3092; - WFIFOW(inter_fd,2) = sizeof(struct s_homunculus)+8; - WFIFOL(inter_fd,4) = account_id; - memcpy(WFIFOP(inter_fd,8),sh,sizeof(struct s_homunculus)); - WFIFOSET(inter_fd, WFIFOW(inter_fd,2)); - return 0; - -} - -int intif_homunculus_requestdelete(int homun_id) -{ - if (intif->CheckForCharServer()) - return 0; - WFIFOHEAD(inter_fd, 6); - WFIFOW(inter_fd, 0) = 0x3093; - WFIFOL(inter_fd,2) = homun_id; - WFIFOSET(inter_fd,6); - return 0; - -} - - -//----------------------------------------------------------------- -// Packets receive from inter server - -// Wisp/Page reception // rewritten by [Yor] -int intif_parse_WisMessage(int fd) -{ - struct map_session_data* sd; - char *wisp_source; - char name[NAME_LENGTH]; - int id, i; - - id=RFIFOL(fd,4); - - safestrncpy(name, (char*)RFIFOP(fd,32), NAME_LENGTH); - sd = iMap->nick2sd(name); - if(sd == NULL || strcmp(sd->status.name, name) != 0) - { //Not found - intif_wis_replay(id,1); - return 0; - } - if(sd->state.ignoreAll) { - intif_wis_replay(id, 2); - return 0; - } - wisp_source = (char *) RFIFOP(fd,8); // speed up [Yor] - for(i=0; i < MAX_IGNORE_LIST && - sd->ignore[i].name[0] != '\0' && - strcmp(sd->ignore[i].name, wisp_source) != 0 - ; i++); - - if (i < MAX_IGNORE_LIST && sd->ignore[i].name[0] != '\0') - { //Ignored - intif_wis_replay(id, 2); - return 0; - } - //Success to send whisper. - clif->wis_message(sd->fd, wisp_source, (char*)RFIFOP(fd,56),RFIFOW(fd,2)-56); - intif_wis_replay(id,0); // succes - return 0; -} - -// Wisp/page transmission result reception -int intif_parse_WisEnd(int fd) -{ - struct map_session_data* sd; - - if (battle_config.etc_log) - ShowInfo("intif_parse_wisend: player: %s, flag: %d\n", RFIFOP(fd,2), RFIFOB(fd,26)); // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target - sd = (struct map_session_data *)iMap->nick2sd((char *) RFIFOP(fd,2)); - if (sd != NULL) - clif->wis_end(sd->fd, RFIFOB(fd,26)); - - return 0; -} - -static int mapif_parse_WisToGM_sub(struct map_session_data* sd,va_list va) -{ - int permission = va_arg(va, int); - char *wisp_name; - char *message; - int len; - - if (!pc_has_permission(sd, permission)) - return 0; - wisp_name = va_arg(va, char*); - message = va_arg(va, char*); - len = va_arg(va, int); - clif->wis_message(sd->fd, wisp_name, message, len); - return 1; -} - -// Received wisp message from map-server via char-server for ALL gm -// 0x3003/0x3803 .w .24B .l .?B -int mapif_parse_WisToGM(int fd) -{ - int permission, mes_len; - char Wisp_name[NAME_LENGTH]; - char mbuf[255]; - char *message; - - mes_len = RFIFOW(fd,2) - 32; - message = (char *) (mes_len >= 255 ? (char *) aMalloc(mes_len) : mbuf); - - permission = RFIFOL(fd,28); - safestrncpy(Wisp_name, (char*)RFIFOP(fd,4), NAME_LENGTH); - safestrncpy(message, (char*)RFIFOP(fd,32), mes_len); - // information is sent to all online GM - iMap->map_foreachpc(mapif_parse_WisToGM_sub, permission, Wisp_name, message, mes_len); - - if (message != mbuf) - aFree(message); - return 0; -} - -// Request player registre -int intif_parse_Registers(int fd) -{ - int j,p,len,max, flag; - struct map_session_data *sd; - struct global_reg *reg; - int *qty; - int account_id = RFIFOL(fd,4), char_id = RFIFOL(fd,8); - struct auth_node *node = chrif->auth_check(account_id, char_id, ST_LOGIN); - if (node) - sd = node->sd; - else { //Normally registries should arrive for in log-in chars. - sd = iMap->id2sd(account_id); - if (sd && RFIFOB(fd,12) == 3 && sd->status.char_id != char_id) - sd = NULL; //Character registry from another character. - } - if (!sd) return 1; - - flag = (sd->save_reg.global_num == -1 || sd->save_reg.account_num == -1 || sd->save_reg.account2_num == -1); - - switch (RFIFOB(fd,12)) { - case 3: //Character Registry - reg = sd->save_reg.global; - qty = &sd->save_reg.global_num; - max = GLOBAL_REG_NUM; - break; - case 2: //Account Registry - reg = sd->save_reg.account; - qty = &sd->save_reg.account_num; - max = ACCOUNT_REG_NUM; - break; - case 1: //Account2 Registry - reg = sd->save_reg.account2; - qty = &sd->save_reg.account2_num; - max = ACCOUNT_REG2_NUM; - break; - default: - ShowError("intif_parse_Registers: Unrecognized type %d\n",RFIFOB(fd,12)); - return 0; - } - for(j=0,p=13;jsave_reg.global_num > -1 && sd->save_reg.account_num > -1 && sd->save_reg.account2_num > -1) - pc->reg_received(sd); //Received all registry values, execute init scripts and what-not. [Skotlex] - return 1; -} - -int intif_parse_LoadGuildStorage(int fd) -{ - struct guild_storage *gstor; - struct map_session_data *sd; - int guild_id; - - guild_id = RFIFOL(fd,8); - if(guild_id <= 0) - return 1; - sd=iMap->id2sd( RFIFOL(fd,4) ); - if(sd==NULL){ - ShowError("intif_parse_LoadGuildStorage: user not found %d\n",RFIFOL(fd,4)); - return 1; - } - gstor=gstorage->id2storage(guild_id); - if(!gstor) { - ShowWarning("intif_parse_LoadGuildStorage: error guild_id %d not exist\n",guild_id); - return 1; - } - if (gstor->storage_status == 1) { // Already open.. lets ignore this update - ShowWarning("intif_parse_LoadGuildStorage: storage received for a client already open (User %d:%d)\n", sd->status.account_id, sd->status.char_id); - return 1; - } - if (gstor->dirty) { // Already have storage, and it has been modified and not saved yet! Exploit! [Skotlex] - ShowWarning("intif_parse_LoadGuildStorage: received storage for an already modified non-saved storage! (User %d:%d)\n", sd->status.account_id, sd->status.char_id); - return 1; - } - if( RFIFOW(fd,2)-12 != sizeof(struct guild_storage) ){ - ShowError("intif_parse_LoadGuildStorage: data size error %d %d\n",RFIFOW(fd,2)-12 , sizeof(struct guild_storage)); - gstor->storage_status = 0; - return 1; - } - - memcpy(gstor,RFIFOP(fd,12),sizeof(struct guild_storage)); - gstorage->open(sd); - return 0; -} - -// ACK guild_storage saved -int intif_parse_SaveGuildStorage(int fd) -{ - gstorage->saved(/*RFIFOL(fd,2), */RFIFOL(fd,6)); - return 0; -} - -// ACK party creation -int intif_parse_PartyCreated(int fd) -{ - if(battle_config.etc_log) - ShowInfo("intif: party created by account %d\n\n", RFIFOL(fd,2)); - party->created(RFIFOL(fd,2), RFIFOL(fd,6),RFIFOB(fd,10),RFIFOL(fd,11), (char *)RFIFOP(fd,15)); - return 0; -} - -// Receive party info -int intif_parse_PartyInfo(int fd) -{ - if( RFIFOW(fd,2) == 12 ){ - ShowWarning("intif: party noinfo (char_id=%d party_id=%d)\n", RFIFOL(fd,4), RFIFOL(fd,8)); - party->recv_noinfo(RFIFOL(fd,8), RFIFOL(fd,4)); - return 0; - } - - if( RFIFOW(fd,2) != 8+sizeof(struct party) ) - ShowError("intif: party info : data size error (char_id=%d party_id=%d packet_len=%d expected_len=%d)\n", RFIFOL(fd,4), RFIFOL(fd,8), RFIFOW(fd,2), 8+sizeof(struct party)); - party->recv_info((struct party *)RFIFOP(fd,8), RFIFOL(fd,4)); - return 0; -} - -// ACK adding party member -int intif_parse_PartyMemberAdded(int fd) -{ - if(battle_config.etc_log) - ShowInfo("intif: party member added Party (%d), Account(%d), Char(%d)\n",RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10)); - party->member_added(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10), RFIFOB(fd, 14)); - return 0; -} - -// ACK changing party option -int intif_parse_PartyOptionChanged(int fd) -{ - party->optionchanged(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOW(fd,10),RFIFOW(fd,12),RFIFOB(fd,14)); - return 0; -} - -// ACK member leaving party -int intif_parse_PartyMemberWithdraw(int fd) -{ - if(battle_config.etc_log) - ShowInfo("intif: party member withdraw: Party(%d), Account(%d), Char(%d)\n",RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10)); - party->member_withdraw(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10)); - return 0; -} - -// ACK party break -int intif_parse_PartyBroken(int fd) -{ - party->broken(RFIFOL(fd,2)); - return 0; -} - -// ACK party on new map -int intif_parse_PartyMove(int fd) -{ - party->recv_movemap(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOW(fd,14),RFIFOB(fd,16),RFIFOW(fd,17)); - return 0; -} - -// ACK party messages -int intif_parse_PartyMessage(int fd) -{ - party->recv_message(RFIFOL(fd,4),RFIFOL(fd,8),(char *) RFIFOP(fd,12),RFIFOW(fd,2)-12); - return 0; -} - -// ACK guild creation -int intif_parse_GuildCreated(int fd) -{ - guild->created(RFIFOL(fd,2),RFIFOL(fd,6)); - return 0; -} - -// ACK guild infos -int intif_parse_GuildInfo(int fd) -{ - if(RFIFOW(fd,2) == 8) { - ShowWarning("intif: guild noinfo %d\n",RFIFOL(fd,4)); - guild->recv_noinfo(RFIFOL(fd,4)); - return 0; - } - if( RFIFOW(fd,2)!=sizeof(struct guild)+4 ) - ShowError("intif: guild info : data size error Gid: %d recv size: %d Expected size: %d\n",RFIFOL(fd,4),RFIFOW(fd,2),sizeof(struct guild)+4); - guild->recv_info((struct guild *)RFIFOP(fd,4)); - return 0; -} - -// ACK adding guild member -int intif_parse_GuildMemberAdded(int fd) -{ - if(battle_config.etc_log) - ShowInfo("intif: guild member added %d %d %d %d\n",RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOB(fd,14)); - guild->member_added(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOB(fd,14)); - return 0; -} - -// ACK member leaving guild -int intif_parse_GuildMemberWithdraw(int fd) -{ - guild->member_withdraw(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOB(fd,14),(char *)RFIFOP(fd,55),(char *)RFIFOP(fd,15)); - return 0; -} - -// ACK guild member basic info -int intif_parse_GuildMemberInfoShort(int fd) -{ - guild->recv_memberinfoshort(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOB(fd,14),RFIFOW(fd,15),RFIFOW(fd,17)); - return 0; -} - -// ACK guild break -int intif_parse_GuildBroken(int fd) -{ - guild->broken(RFIFOL(fd,2),RFIFOB(fd,6)); - return 0; -} - -// basic guild info change notice -// 0x3839 .w .l .w .?b -int intif_parse_GuildBasicInfoChanged(int fd) -{ - //int len = RFIFOW(fd,2) - 10; - int guild_id = RFIFOL(fd,4); - int type = RFIFOW(fd,8); - //void* data = RFIFOP(fd,10); - - struct guild* g = guild->search(guild_id); - if( g == NULL ) - return 0; - - switch(type) { - case GBI_EXP: g->exp = RFIFOQ(fd,10); break; - case GBI_GUILDLV: g->guild_lv = RFIFOW(fd,10); break; - case GBI_SKILLPOINT: g->skill_point = RFIFOL(fd,10); break; - } - - return 0; -} - -// guild member info change notice -// 0x383a .w .l .l .l .w .?b -int intif_parse_GuildMemberInfoChanged(int fd) -{ - //int len = RFIFOW(fd,2) - 18; - int guild_id = RFIFOL(fd,4); - int account_id = RFIFOL(fd,8); - int char_id = RFIFOL(fd,12); - int type = RFIFOW(fd,16); - //void* data = RFIFOP(fd,18); - - struct guild* g; - int idx; - - g = guild->search(guild_id); - if( g == NULL ) - return 0; - - idx = guild->getindex(g,account_id,char_id); - if( idx == -1 ) - return 0; - - switch( type ) { - case GMI_POSITION: g->member[idx].position = RFIFOW(fd,18); guild->memberposition_changed(g,idx,RFIFOW(fd,18)); break; - case GMI_EXP: g->member[idx].exp = RFIFOQ(fd,18); break; - case GMI_HAIR: g->member[idx].hair = RFIFOW(fd,18); break; - case GMI_HAIR_COLOR: g->member[idx].hair_color = RFIFOW(fd,18); break; - case GMI_GENDER: g->member[idx].gender = RFIFOW(fd,18); break; - case GMI_CLASS: g->member[idx].class_ = RFIFOW(fd,18); break; - case GMI_LEVEL: g->member[idx].lv = RFIFOW(fd,18); break; - } - return 0; -} - -// ACK change of guild title -int intif_parse_GuildPosition(int fd) -{ - if( RFIFOW(fd,2)!=sizeof(struct guild_position)+12 ) - ShowError("intif: guild info : data size error\n %d %d %d",RFIFOL(fd,4),RFIFOW(fd,2),sizeof(struct guild_position)+12); - guild->position_changed(RFIFOL(fd,4),RFIFOL(fd,8),(struct guild_position *)RFIFOP(fd,12)); - return 0; -} - -// ACK change of guild skill update -int intif_parse_GuildSkillUp(int fd) -{ - guild->skillupack(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10)); - return 0; -} - -// ACK change of guild relationship -int intif_parse_GuildAlliance(int fd) -{ - guild->allianceack(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOL(fd,14),RFIFOB(fd,18),(char *) RFIFOP(fd,19),(char *) RFIFOP(fd,43)); - return 0; -} - -// ACK change of guild notice -int intif_parse_GuildNotice(int fd) -{ - guild->notice_changed(RFIFOL(fd,2),(char *) RFIFOP(fd,6),(char *) RFIFOP(fd,66)); - return 0; -} - -// ACK change of guild emblem -int intif_parse_GuildEmblem(int fd) -{ - guild->emblem_changed(RFIFOW(fd,2)-12,RFIFOL(fd,4),RFIFOL(fd,8), (char *)RFIFOP(fd,12)); - return 0; -} - -// ACK guild message -int intif_parse_GuildMessage(int fd) -{ - guild->recv_message(RFIFOL(fd,4),RFIFOL(fd,8),(char *) RFIFOP(fd,12),RFIFOW(fd,2)-12); - return 0; -} - -// Reply guild castle data request -int intif_parse_GuildCastleDataLoad(int fd) -{ - return guild->castledataloadack(RFIFOW(fd,2), (struct guild_castle *)RFIFOP(fd,4)); -} - -// ACK change of guildmaster -int intif_parse_GuildMasterChanged(int fd) -{ - return guild->gm_changed(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10)); -} - -// Request pet creation -int intif_parse_CreatePet(int fd) -{ - pet_get_egg(RFIFOL(fd,2),RFIFOL(fd,7),RFIFOB(fd,6)); - return 0; -} - -// ACK pet data -int intif_parse_RecvPetData(int fd) -{ - struct s_pet p; - int len; - len=RFIFOW(fd,2); - if(sizeof(struct s_pet)!=len-9) { - if(battle_config.etc_log) - ShowError("intif: pet data: data size error %d %d\n",sizeof(struct s_pet),len-9); - } - else{ - memcpy(&p,RFIFOP(fd,9),sizeof(struct s_pet)); - pet_recv_petdata(RFIFOL(fd,4),&p,RFIFOB(fd,8)); - } - - return 0; -} - -// ACK pet save data -int intif_parse_SavePetOk(int fd) -{ - if(RFIFOB(fd,6) == 1) - ShowError("pet data save failure\n"); - - return 0; -} - -// ACK deleting pet -int intif_parse_DeletePetOk(int fd) -{ - if(RFIFOB(fd,2) == 1) - ShowError("pet data delete failure\n"); - - return 0; -} - -// ACK changing name resquest, players,pets,hommon -int intif_parse_ChangeNameOk(int fd) -{ - struct map_session_data *sd = NULL; - if((sd=iMap->id2sd(RFIFOL(fd,2)))==NULL || - sd->status.char_id != RFIFOL(fd,6)) - return 0; - - switch (RFIFOB(fd,10)) { - case 0: //Players [NOT SUPPORTED YET] - break; - case 1: //Pets - pet_change_name_ack(sd, (char*)RFIFOP(fd,12), RFIFOB(fd,11)); - break; - case 2: //Hom - homun->change_name_ack(sd, (char*)RFIFOP(fd,12), RFIFOB(fd,11)); - break; - } - return 0; -} - -//---------------------------------------------------------------- -// Homunculus recv packets [albator] - -int intif_parse_CreateHomunculus(int fd) -{ - int len; - len=RFIFOW(fd,2)-9; - if(sizeof(struct s_homunculus)!=len) { - if(battle_config.etc_log) - ShowError("intif: create homun data: data size error %d != %d\n",sizeof(struct s_homunculus),len); - return 0; - } - homun->recv_data(RFIFOL(fd,4), (struct s_homunculus*)RFIFOP(fd,9), RFIFOB(fd,8)) ; - return 0; -} - -int intif_parse_RecvHomunculusData(int fd) -{ - int len; - - len=RFIFOW(fd,2)-9; - - if(sizeof(struct s_homunculus)!=len) { - if(battle_config.etc_log) - ShowError("intif: homun data: data size error %d %d\n",sizeof(struct s_homunculus),len); - return 0; - } - homun->recv_data(RFIFOL(fd,4), (struct s_homunculus*)RFIFOP(fd,9), RFIFOB(fd,8)); - return 0; -} - -int intif_parse_SaveHomunculusOk(int fd) -{ - if(RFIFOB(fd,6) != 1) - ShowError("homunculus data save failure for account %d\n", RFIFOL(fd,2)); - - return 0; -} - -int intif_parse_DeleteHomunculusOk(int fd) -{ - if(RFIFOB(fd,2) != 1) - ShowError("Homunculus data delete failure\n"); - - return 0; -} - -/************************************** - -QUESTLOG SYSTEM FUNCTIONS - -***************************************/ - -int intif_request_questlog(TBL_PC *sd) -{ - WFIFOHEAD(inter_fd,6); - WFIFOW(inter_fd,0) = 0x3060; - WFIFOL(inter_fd,2) = sd->status.char_id; - WFIFOSET(inter_fd,6); - return 0; -} - -int intif_parse_questlog(int fd) -{ - int char_id = RFIFOL(fd, 4); - int i; - TBL_PC * sd = iMap->charid2sd(char_id); - - //User not online anymore - if(!sd) - return -1; - - sd->avail_quests = sd->num_quests = (RFIFOW(fd, 2)-8)/sizeof(struct quest); - - memset(&sd->quest_log, 0, sizeof(sd->quest_log)); - - for( i = 0; i < sd->num_quests; i++ ) - { - memcpy(&sd->quest_log[i], RFIFOP(fd, i*sizeof(struct quest)+8), sizeof(struct quest)); - - sd->quest_index[i] = quest_search_db(sd->quest_log[i].quest_id); - - if( sd->quest_index[i] < 0 ) - { - ShowError("intif_parse_questlog: quest %d not found in DB.\n",sd->quest_log[i].quest_id); - sd->avail_quests--; - sd->num_quests--; - i--; - continue; - } - - if( sd->quest_log[i].state == Q_COMPLETE ) - sd->avail_quests--; - } - - quest_pc_login(sd); - - return 0; -} - -int intif_parse_questsave(int fd) -{ - int cid = RFIFOL(fd, 2); - TBL_PC *sd = iMap->id2sd(cid); - - if( !RFIFOB(fd, 6) ) - ShowError("intif_parse_questsave: Failed to save quest(s) for character %d!\n", cid); - else if( sd ) - sd->save_quest = false; - - return 0; -} - -int intif_quest_save(TBL_PC *sd) -{ - int len; - - if(intif->CheckForCharServer()) - return 0; - - len = sizeof(struct quest)*sd->num_quests + 8; - - WFIFOHEAD(inter_fd, len); - WFIFOW(inter_fd,0) = 0x3061; - WFIFOW(inter_fd,2) = len; - WFIFOL(inter_fd,4) = sd->status.char_id; - if( sd->num_quests ) - memcpy(WFIFOP(inter_fd,8), &sd->quest_log, sizeof(struct quest)*sd->num_quests); - WFIFOSET(inter_fd, len); - - return 0; -} - -/*========================================== - * MAIL SYSTEM - * By Zephyrus - *==========================================*/ - -/*------------------------------------------ - * Inbox Request - * flag: 0 Update Inbox | 1 OpenMail - *------------------------------------------*/ -int intif_Mail_requestinbox(int char_id, unsigned char flag) -{ - if (intif->CheckForCharServer()) - return 0; - - WFIFOHEAD(inter_fd,7); - WFIFOW(inter_fd,0) = 0x3048; - WFIFOL(inter_fd,2) = char_id; - WFIFOB(inter_fd,6) = flag; - WFIFOSET(inter_fd,7); - - return 0; -} - -int intif_parse_Mail_inboxreceived(int fd) -{ - struct map_session_data *sd; - unsigned char flag = RFIFOB(fd,8); - - sd = iMap->charid2sd(RFIFOL(fd,4)); - - if (sd == NULL) - { - ShowError("intif_parse_Mail_inboxreceived: char not found %d\n",RFIFOL(fd,4)); - return 1; - } - - if (RFIFOW(fd,2) - 9 != sizeof(struct mail_data)) - { - ShowError("intif_parse_Mail_inboxreceived: data size error %d %d\n", RFIFOW(fd,2) - 9, sizeof(struct mail_data)); - return 1; - } - - //FIXME: this operation is not safe [ultramage] - memcpy(&sd->mail.inbox, RFIFOP(fd,9), sizeof(struct mail_data)); - sd->mail.changed = false; // cache is now in sync - - if (flag) - clif->mail_refreshinbox(sd); - else if( battle_config.mail_show_status && ( battle_config.mail_show_status == 1 || sd->mail.inbox.unread ) ) - { - char output[128]; - sprintf(output, msg_txt(510), sd->mail.inbox.unchecked, sd->mail.inbox.unread + sd->mail.inbox.unchecked); - clif->disp_onlyself(sd, output, strlen(output)); - } - return 0; -} -/*------------------------------------------ - * Mail Read - *------------------------------------------*/ -int intif_Mail_read(int mail_id) -{ - if (intif->CheckForCharServer()) - return 0; - - WFIFOHEAD(inter_fd,6); - WFIFOW(inter_fd,0) = 0x3049; - WFIFOL(inter_fd,2) = mail_id; - WFIFOSET(inter_fd,6); - - return 0; -} -/*------------------------------------------ - * Get Attachment - *------------------------------------------*/ -int intif_Mail_getattach(int char_id, int mail_id) -{ - if (intif->CheckForCharServer()) - return 0; - - WFIFOHEAD(inter_fd,10); - WFIFOW(inter_fd,0) = 0x304a; - WFIFOL(inter_fd,2) = char_id; - WFIFOL(inter_fd,6) = mail_id; - WFIFOSET(inter_fd, 10); - - return 0; -} - -int intif_parse_Mail_getattach(int fd) -{ - struct map_session_data *sd; - struct item item; - int zeny = RFIFOL(fd,8); - - sd = iMap->charid2sd( RFIFOL(fd,4) ); - - if (sd == NULL) - { - ShowError("intif_parse_Mail_getattach: char not found %d\n",RFIFOL(fd,4)); - return 1; - } - - if (RFIFOW(fd,2) - 12 != sizeof(struct item)) - { - ShowError("intif_parse_Mail_getattach: data size error %d %d\n", RFIFOW(fd,2) - 16, sizeof(struct item)); - return 1; - } - - memcpy(&item, RFIFOP(fd,12), sizeof(struct item)); - - mail->getattachment(sd, zeny, &item); - return 0; -} -/*------------------------------------------ - * Delete Message - *------------------------------------------*/ -int intif_Mail_delete(int char_id, int mail_id) -{ - if (intif->CheckForCharServer()) - return 0; - - WFIFOHEAD(inter_fd,10); - WFIFOW(inter_fd,0) = 0x304b; - WFIFOL(inter_fd,2) = char_id; - WFIFOL(inter_fd,6) = mail_id; - WFIFOSET(inter_fd,10); - - return 0; -} - -int intif_parse_Mail_delete(int fd) -{ - int char_id = RFIFOL(fd,2); - int mail_id = RFIFOL(fd,6); - bool failed = RFIFOB(fd,10); - - struct map_session_data *sd = iMap->charid2sd(char_id); - if (sd == NULL) - { - ShowError("intif_parse_Mail_delete: char not found %d\n", char_id); - return 1; - } - - if (!failed) - { - int i; - ARR_FIND(0, MAIL_MAX_INBOX, i, sd->mail.inbox.msg[i].id == mail_id); - if( i < MAIL_MAX_INBOX ) - { - memset(&sd->mail.inbox.msg[i], 0, sizeof(struct mail_message)); - sd->mail.inbox.amount--; - } - - if( sd->mail.inbox.full ) - intif_Mail_requestinbox(sd->status.char_id, 1); // Free space is available for new mails - } - - clif->mail_delete(sd->fd, mail_id, failed); - return 0; -} -/*------------------------------------------ - * Return Message - *------------------------------------------*/ -int intif_Mail_return(int char_id, int mail_id) -{ - if (intif->CheckForCharServer()) - return 0; - - WFIFOHEAD(inter_fd,10); - WFIFOW(inter_fd,0) = 0x304c; - WFIFOL(inter_fd,2) = char_id; - WFIFOL(inter_fd,6) = mail_id; - WFIFOSET(inter_fd,10); - - return 0; -} - -int intif_parse_Mail_return(int fd) -{ - struct map_session_data *sd = iMap->charid2sd(RFIFOL(fd,2)); - int mail_id = RFIFOL(fd,6); - short fail = RFIFOB(fd,10); - - if( sd == NULL ) - { - ShowError("intif_parse_Mail_return: char not found %d\n",RFIFOL(fd,2)); - return 1; - } - - if( !fail ) - { - int i; - ARR_FIND(0, MAIL_MAX_INBOX, i, sd->mail.inbox.msg[i].id == mail_id); - if( i < MAIL_MAX_INBOX ) - { - memset(&sd->mail.inbox.msg[i], 0, sizeof(struct mail_message)); - sd->mail.inbox.amount--; - } - - if( sd->mail.inbox.full ) - intif_Mail_requestinbox(sd->status.char_id, 1); // Free space is available for new mails - } - - clif->mail_return(sd->fd, mail_id, fail); - return 0; -} -/*------------------------------------------ - * Send Mail - *------------------------------------------*/ -int intif_Mail_send(int account_id, struct mail_message *msg) -{ - int len = sizeof(struct mail_message) + 8; - - if (intif->CheckForCharServer()) - return 0; - - WFIFOHEAD(inter_fd,len); - WFIFOW(inter_fd,0) = 0x304d; - WFIFOW(inter_fd,2) = len; - WFIFOL(inter_fd,4) = account_id; - memcpy(WFIFOP(inter_fd,8), msg, sizeof(struct mail_message)); - WFIFOSET(inter_fd,len); - - return 1; -} - -static void intif_parse_Mail_send(int fd) -{ - struct mail_message msg; - struct map_session_data *sd; - bool fail; - - if( RFIFOW(fd,2) - 4 != sizeof(struct mail_message) ) - { - ShowError("intif_parse_Mail_send: data size error %d %d\n", RFIFOW(fd,2) - 4, sizeof(struct mail_message)); - return; - } - - memcpy(&msg, RFIFOP(fd,4), sizeof(struct mail_message)); - fail = (msg.id == 0); - - // notify sender - sd = iMap->charid2sd(msg.send_id); - if( sd != NULL ) - { - if( fail ) - mail->deliveryfail(sd, &msg); - else - { - clif->mail_send(sd->fd, false); - if( iMap->save_settings&16 ) - chrif->save(sd, 0); - } - } -} - -static void intif_parse_Mail_new(int fd) -{ - struct map_session_data *sd = iMap->charid2sd(RFIFOL(fd,2)); - int mail_id = RFIFOL(fd,6); - const char* sender_name = (char*)RFIFOP(fd,10); - const char* title = (char*)RFIFOP(fd,34); - - if( sd == NULL ) - return; - - sd->mail.changed = true; - clif->mail_new(sd->fd, mail_id, sender_name, title); -} - -/*========================================== - * AUCTION SYSTEM - * By Zephyrus - *==========================================*/ -int intif_Auction_requestlist(int char_id, short type, int price, const char* searchtext, short page) -{ - int len = NAME_LENGTH + 16; - - if( intif->CheckForCharServer() ) - return 0; - - WFIFOHEAD(inter_fd,len); - WFIFOW(inter_fd,0) = 0x3050; - WFIFOW(inter_fd,2) = len; - WFIFOL(inter_fd,4) = char_id; - WFIFOW(inter_fd,8) = type; - WFIFOL(inter_fd,10) = price; - WFIFOW(inter_fd,14) = page; - memcpy(WFIFOP(inter_fd,16), searchtext, NAME_LENGTH); - WFIFOSET(inter_fd,len); - - return 0; -} - -static void intif_parse_Auction_results(int fd) -{ - struct map_session_data *sd = iMap->charid2sd(RFIFOL(fd,4)); - short count = RFIFOW(fd,8); - short pages = RFIFOW(fd,10); - uint8* data = RFIFOP(fd,12); - - if( sd == NULL ) - return; - - clif->auction_results(sd, count, pages, data); -} - -int intif_Auction_register(struct auction_data *auction) -{ - int len = sizeof(struct auction_data) + 4; - - if( intif->CheckForCharServer() ) - return 0; - - WFIFOHEAD(inter_fd,len); - WFIFOW(inter_fd,0) = 0x3051; - WFIFOW(inter_fd,2) = len; - memcpy(WFIFOP(inter_fd,4), auction, sizeof(struct auction_data)); - WFIFOSET(inter_fd,len); - - return 1; -} - -static void intif_parse_Auction_register(int fd) -{ - struct map_session_data *sd; - struct auction_data auction; - - if( RFIFOW(fd,2) - 4 != sizeof(struct auction_data) ) - { - ShowError("intif_parse_Auction_register: data size error %d %d\n", RFIFOW(fd,2) - 4, sizeof(struct auction_data)); - return; - } - - memcpy(&auction, RFIFOP(fd,4), sizeof(struct auction_data)); - if( (sd = iMap->charid2sd(auction.seller_id)) == NULL ) - return; - - if( auction.auction_id > 0 ) - { - clif->auction_message(sd->fd, 1); // Confirmation Packet ?? - if( iMap->save_settings&32 ) - chrif->save(sd,0); - } - else - { - int zeny = auction.hours*battle_config.auction_feeperhour; - - clif->auction_message(sd->fd, 4); - pc->additem(sd, &auction.item, auction.item.amount, LOG_TYPE_AUCTION); - - pc->getzeny(sd, zeny, LOG_TYPE_AUCTION, NULL); - } -} - -int intif_Auction_cancel(int char_id, unsigned int auction_id) -{ - if( intif->CheckForCharServer() ) - return 0; - - WFIFOHEAD(inter_fd,10); - WFIFOW(inter_fd,0) = 0x3052; - WFIFOL(inter_fd,2) = char_id; - WFIFOL(inter_fd,6) = auction_id; - WFIFOSET(inter_fd,10); - - return 0; -} - -static void intif_parse_Auction_cancel(int fd) -{ - struct map_session_data *sd = iMap->charid2sd(RFIFOL(fd,2)); - int result = RFIFOB(fd,6); - - if( sd == NULL ) - return; - - switch( result ) - { - case 0: clif->auction_message(sd->fd, 2); break; - case 1: clif->auction_close(sd->fd, 2); break; - case 2: clif->auction_close(sd->fd, 1); break; - case 3: clif->auction_message(sd->fd, 3); break; - } -} - -int intif_Auction_close(int char_id, unsigned int auction_id) -{ - if( intif->CheckForCharServer() ) - return 0; - - WFIFOHEAD(inter_fd,10); - WFIFOW(inter_fd,0) = 0x3053; - WFIFOL(inter_fd,2) = char_id; - WFIFOL(inter_fd,6) = auction_id; - WFIFOSET(inter_fd,10); - - return 0; -} - -static void intif_parse_Auction_close(int fd) -{ - struct map_session_data *sd = iMap->charid2sd(RFIFOL(fd,2)); - unsigned char result = RFIFOB(fd,6); - - if( sd == NULL ) - return; - - clif->auction_close(sd->fd, result); - if( result == 0 ) - { - // FIXME: Leeching off a parse function - clif->pAuction_cancelreg(fd, sd); - intif_Auction_requestlist(sd->status.char_id, 6, 0, "", 1); - } -} - -int intif_Auction_bid(int char_id, const char* name, unsigned int auction_id, int bid) -{ - int len = 16 + NAME_LENGTH; - - if( intif->CheckForCharServer() ) - return 0; - - WFIFOHEAD(inter_fd,len); - WFIFOW(inter_fd,0) = 0x3055; - WFIFOW(inter_fd,2) = len; - WFIFOL(inter_fd,4) = char_id; - WFIFOL(inter_fd,8) = auction_id; - WFIFOL(inter_fd,12) = bid; - memcpy(WFIFOP(inter_fd,16), name, NAME_LENGTH); - WFIFOSET(inter_fd,len); - - return 0; -} - -static void intif_parse_Auction_bid(int fd) -{ - struct map_session_data *sd = iMap->charid2sd(RFIFOL(fd,2)); - int bid = RFIFOL(fd,6); - unsigned char result = RFIFOB(fd,10); - - if( sd == NULL ) - return; - - clif->auction_message(sd->fd, result); - if( bid > 0 ) { - pc->getzeny(sd, bid, LOG_TYPE_AUCTION,NULL); - } - if( result == 1 ) { // To update the list, display your buy list - clif->pAuction_cancelreg(fd, sd); - intif_Auction_requestlist(sd->status.char_id, 7, 0, "", 1); - } -} - -// Used to send 'You have won the auction' and 'You failed to won the auction' messages -static void intif_parse_Auction_message(int fd) -{ - struct map_session_data *sd = iMap->charid2sd(RFIFOL(fd,2)); - unsigned char result = RFIFOB(fd,6); - - if( sd == NULL ) - return; - - clif->auction_message(sd->fd, result); -} - -/*========================================== - * Mercenary's System - *------------------------------------------*/ -int intif_mercenary_create(struct s_mercenary *merc) -{ - int size = sizeof(struct s_mercenary) + 4; - - if( intif->CheckForCharServer() ) - return 0; - - WFIFOHEAD(inter_fd,size); - WFIFOW(inter_fd,0) = 0x3070; - WFIFOW(inter_fd,2) = size; - memcpy(WFIFOP(inter_fd,4), merc, sizeof(struct s_mercenary)); - WFIFOSET(inter_fd,size); - return 0; -} - -int intif_parse_mercenary_received(int fd) -{ - int len = RFIFOW(fd,2) - 5; - if( sizeof(struct s_mercenary) != len ) - { - if( battle_config.etc_log ) - ShowError("intif: create mercenary data size error %d != %d\n", sizeof(struct s_mercenary), len); - return 0; - } - - merc_data_received((struct s_mercenary*)RFIFOP(fd,5), RFIFOB(fd,4)); - return 0; -} - -int intif_mercenary_request(int merc_id, int char_id) -{ - if (intif->CheckForCharServer()) - return 0; - - WFIFOHEAD(inter_fd,10); - WFIFOW(inter_fd,0) = 0x3071; - WFIFOL(inter_fd,2) = merc_id; - WFIFOL(inter_fd,6) = char_id; - WFIFOSET(inter_fd,10); - return 0; -} - -int intif_mercenary_delete(int merc_id) -{ - if (intif->CheckForCharServer()) - return 0; - - WFIFOHEAD(inter_fd,6); - WFIFOW(inter_fd,0) = 0x3072; - WFIFOL(inter_fd,2) = merc_id; - WFIFOSET(inter_fd,6); - return 0; -} - -int intif_parse_mercenary_deleted(int fd) -{ - if( RFIFOB(fd,2) != 1 ) - ShowError("Mercenary data delete failure\n"); - - return 0; -} - -int intif_mercenary_save(struct s_mercenary *merc) -{ - int size = sizeof(struct s_mercenary) + 4; - - if( intif->CheckForCharServer() ) - return 0; - - WFIFOHEAD(inter_fd,size); - WFIFOW(inter_fd,0) = 0x3073; - WFIFOW(inter_fd,2) = size; - memcpy(WFIFOP(inter_fd,4), merc, sizeof(struct s_mercenary)); - WFIFOSET(inter_fd,size); - return 0; -} - -int intif_parse_mercenary_saved(int fd) -{ - if( RFIFOB(fd,2) != 1 ) - ShowError("Mercenary data save failure\n"); - - return 0; -} - -/*========================================== - * Elemental's System - *------------------------------------------*/ -int intif_elemental_create(struct s_elemental *ele) -{ - int size = sizeof(struct s_elemental) + 4; - - if( intif->CheckForCharServer() ) - return 0; - - WFIFOHEAD(inter_fd,size); - WFIFOW(inter_fd,0) = 0x307c; - WFIFOW(inter_fd,2) = size; - memcpy(WFIFOP(inter_fd,4), ele, sizeof(struct s_elemental)); - WFIFOSET(inter_fd,size); - return 0; -} - -int intif_parse_elemental_received(int fd) -{ - int len = RFIFOW(fd,2) - 5; - if( sizeof(struct s_elemental) != len ) - { - if( battle_config.etc_log ) - ShowError("intif: create elemental data size error %d != %d\n", sizeof(struct s_elemental), len); - return 0; - } - - elemental->data_received((struct s_elemental*)RFIFOP(fd,5), RFIFOB(fd,4)); - return 0; -} - -int intif_elemental_request(int ele_id, int char_id) -{ - if (intif->CheckForCharServer()) - return 0; - - WFIFOHEAD(inter_fd,10); - WFIFOW(inter_fd,0) = 0x307d; - WFIFOL(inter_fd,2) = ele_id; - WFIFOL(inter_fd,6) = char_id; - WFIFOSET(inter_fd,10); - return 0; -} - -int intif_elemental_delete(int ele_id) -{ - if (intif->CheckForCharServer()) - return 0; - - WFIFOHEAD(inter_fd,6); - WFIFOW(inter_fd,0) = 0x307e; - WFIFOL(inter_fd,2) = ele_id; - WFIFOSET(inter_fd,6); - return 0; -} - -int intif_parse_elemental_deleted(int fd) -{ - if( RFIFOB(fd,2) != 1 ) - ShowError("Elemental data delete failure\n"); - - return 0; -} - -int intif_elemental_save(struct s_elemental *ele) -{ - int size = sizeof(struct s_elemental) + 4; - - if( intif->CheckForCharServer() ) - return 0; - - WFIFOHEAD(inter_fd,size); - WFIFOW(inter_fd,0) = 0x307f; - WFIFOW(inter_fd,2) = size; - memcpy(WFIFOP(inter_fd,4), ele, sizeof(struct s_elemental)); - WFIFOSET(inter_fd,size); - return 0; -} - -int intif_parse_elemental_saved(int fd) -{ - if( RFIFOB(fd,2) != 1 ) - ShowError("Elemental data save failure\n"); - - return 0; -} - -void intif_request_accinfo( int u_fd, int aid, int group_lv, char* query ) { - - - WFIFOHEAD(inter_fd,2 + 4 + 4 + 4 + NAME_LENGTH); - - WFIFOW(inter_fd,0) = 0x3007; - WFIFOL(inter_fd,2) = u_fd; - WFIFOL(inter_fd,6) = aid; - WFIFOL(inter_fd,10) = group_lv; - safestrncpy((char *)WFIFOP(inter_fd,14), query, NAME_LENGTH); - - WFIFOSET(inter_fd,2 + 4 + 4 + 4 + NAME_LENGTH); - - return; -} - -void intif_parse_MessageToFD(int fd) { - int u_fd = RFIFOL(fd,4); - - if( session[u_fd] && session[u_fd]->session_data ) { - int aid = RFIFOL(fd,8); - struct map_session_data * sd = session[u_fd]->session_data; - /* matching e.g. previous fd owner didn't dc during request or is still the same */ - if( sd->bl.id == aid ) { - char msg[512]; - safestrncpy(msg, (char*)RFIFOP(fd,12), RFIFOW(fd,2) - 12); - clif->message(u_fd,msg); - } - - } - - return; -} - -//----------------------------------------------------------------- -// Communication from the inter server -// Return a 0 (false) if there were any errors. -// 1, 2 if there are not enough to return the length of the packet if the packet processing -int intif_parse(int fd) -{ - int packet_len, cmd; - cmd = RFIFOW(fd,0); - // Verify ID of the packet - if(cmd<0x3800 || cmd>=0x3800+(sizeof(packet_len_table)/sizeof(packet_len_table[0])) || - packet_len_table[cmd-0x3800]==0){ - return 0; - } - // Check the length of the packet - packet_len = packet_len_table[cmd-0x3800]; - if(packet_len==-1){ - if(RFIFOREST(fd)<4) - return 2; - packet_len = RFIFOW(fd,2); - } - if((int)RFIFOREST(fd)broadcast(NULL, (char *) RFIFOP(fd,16), packet_len-16, 0, ALL_CLIENT); - else //Color announce. - clif->broadcast2(NULL, (char *) RFIFOP(fd,16), packet_len-16, RFIFOL(fd,4), RFIFOW(fd,8), RFIFOW(fd,10), RFIFOW(fd,12), RFIFOW(fd,14), ALL_CLIENT); - break; - case 0x3801: intif_parse_WisMessage(fd); break; - case 0x3802: intif_parse_WisEnd(fd); break; - case 0x3803: mapif_parse_WisToGM(fd); break; - case 0x3804: intif_parse_Registers(fd); break; - case 0x3806: intif_parse_ChangeNameOk(fd); break; - case 0x3807: intif_parse_MessageToFD(fd); break; - case 0x3818: intif_parse_LoadGuildStorage(fd); break; - case 0x3819: intif_parse_SaveGuildStorage(fd); break; - case 0x3820: intif_parse_PartyCreated(fd); break; - case 0x3821: intif_parse_PartyInfo(fd); break; - case 0x3822: intif_parse_PartyMemberAdded(fd); break; - case 0x3823: intif_parse_PartyOptionChanged(fd); break; - case 0x3824: intif_parse_PartyMemberWithdraw(fd); break; - case 0x3825: intif_parse_PartyMove(fd); break; - case 0x3826: intif_parse_PartyBroken(fd); break; - case 0x3827: intif_parse_PartyMessage(fd); break; - case 0x3830: intif_parse_GuildCreated(fd); break; - case 0x3831: intif_parse_GuildInfo(fd); break; - case 0x3832: intif_parse_GuildMemberAdded(fd); break; - case 0x3834: intif_parse_GuildMemberWithdraw(fd); break; - case 0x3835: intif_parse_GuildMemberInfoShort(fd); break; - case 0x3836: intif_parse_GuildBroken(fd); break; - case 0x3837: intif_parse_GuildMessage(fd); break; - case 0x3839: intif_parse_GuildBasicInfoChanged(fd); break; - case 0x383a: intif_parse_GuildMemberInfoChanged(fd); break; - case 0x383b: intif_parse_GuildPosition(fd); break; - case 0x383c: intif_parse_GuildSkillUp(fd); break; - case 0x383d: intif_parse_GuildAlliance(fd); break; - case 0x383e: intif_parse_GuildNotice(fd); break; - case 0x383f: intif_parse_GuildEmblem(fd); break; - case 0x3840: intif_parse_GuildCastleDataLoad(fd); break; - case 0x3843: intif_parse_GuildMasterChanged(fd); break; - - //Quest system - case 0x3860: intif_parse_questlog(fd); break; - case 0x3861: intif_parse_questsave(fd); break; - -// Mail System - case 0x3848: intif_parse_Mail_inboxreceived(fd); break; - case 0x3849: intif_parse_Mail_new(fd); break; - case 0x384a: intif_parse_Mail_getattach(fd); break; - case 0x384b: intif_parse_Mail_delete(fd); break; - case 0x384c: intif_parse_Mail_return(fd); break; - case 0x384d: intif_parse_Mail_send(fd); break; -// Auction System - case 0x3850: intif_parse_Auction_results(fd); break; - case 0x3851: intif_parse_Auction_register(fd); break; - case 0x3852: intif_parse_Auction_cancel(fd); break; - case 0x3853: intif_parse_Auction_close(fd); break; - case 0x3854: intif_parse_Auction_message(fd); break; - case 0x3855: intif_parse_Auction_bid(fd); break; - -// Mercenary System - case 0x3870: intif_parse_mercenary_received(fd); break; - case 0x3871: intif_parse_mercenary_deleted(fd); break; - case 0x3872: intif_parse_mercenary_saved(fd); break; -// Elemental System - case 0x387c: intif_parse_elemental_received(fd); break; - case 0x387d: intif_parse_elemental_deleted(fd); break; - case 0x387e: intif_parse_elemental_saved(fd); break; - - case 0x3880: intif_parse_CreatePet(fd); break; - case 0x3881: intif_parse_RecvPetData(fd); break; - case 0x3882: intif_parse_SavePetOk(fd); break; - case 0x3883: intif_parse_DeletePetOk(fd); break; - case 0x3890: intif_parse_CreateHomunculus(fd); break; - case 0x3891: intif_parse_RecvHomunculusData(fd); break; - case 0x3892: intif_parse_SaveHomunculusOk(fd); break; - case 0x3893: intif_parse_DeleteHomunculusOk(fd); break; - default: - ShowError("intif_parse : unknown packet %d %x\n",fd,RFIFOW(fd,0)); - return 0; - } - // Skip packet - RFIFOSKIP(fd,packet_len); - return 1; -} - -/*===================================== -* Default Functions : intif.h -* Generated by HerculesInterfaceMaker -* created by Susu -*-------------------------------------*/ -void intif_defaults(void) { - intif = &intif_s; - /* funcs */ - - intif->parse = intif_parse; - - intif->broadcast = intif_broadcast; - intif->broadcast2 = intif_broadcast2; - intif->main_message = intif_main_message; - - intif->wis_message = intif_wis_message; - intif->wis_message_to_gm = intif_wis_message_to_gm; - - intif->saveregistry = intif_saveregistry; - intif->request_registry = intif_request_registry; - - intif->request_guild_storage = intif_request_guild_storage; - intif->send_guild_storage = intif_send_guild_storage; - - intif->create_party = intif_create_party; - intif->request_partyinfo = intif_request_partyinfo; - - intif->party_addmember = intif_party_addmember; - intif->party_changeoption = intif_party_changeoption; - intif->party_leave = intif_party_leave; - intif->party_changemap = intif_party_changemap; - intif->break_party = intif_break_party; - intif->party_message = intif_party_message; - intif->party_leaderchange = intif_party_leaderchange; - - intif->guild_create = intif_guild_create; - intif->guild_request_info = intif_guild_request_info; - intif->guild_addmember = intif_guild_addmember; - intif->guild_leave = intif_guild_leave; - intif->guild_memberinfoshort = intif_guild_memberinfoshort; - intif->guild_break = intif_guild_break; - intif->guild_message = intif_guild_message; - intif->guild_change_gm = intif_guild_change_gm; - intif->guild_change_basicinfo = intif_guild_change_basicinfo; - intif->guild_change_memberinfo = intif_guild_change_memberinfo; - intif->guild_position = intif_guild_position; - intif->guild_skillup = intif_guild_skillup; - intif->guild_alliance = intif_guild_alliance; - intif->guild_notice = intif_guild_notice; - intif->guild_emblem = intif_guild_emblem; - intif->guild_castle_dataload = intif_guild_castle_dataload; - intif->guild_castle_datasave = intif_guild_castle_datasave; - intif->request_petdata = intif_request_petdata; - intif->save_petdata = intif_save_petdata; - intif->delete_petdata = intif_delete_petdata; - intif->rename = intif_rename; - intif->homunculus_create = intif_homunculus_create; - intif->homunculus_requestload = intif_homunculus_requestload; - intif->homunculus_requestsave = intif_homunculus_requestsave; - intif->homunculus_requestdelete = intif_homunculus_requestdelete; - /******QUEST SYTEM*******/ - intif->request_questlog = intif_request_questlog; - intif->quest_save = intif_quest_save; - // MERCENARY SYSTEM - intif->mercenary_create = intif_mercenary_create; - intif->mercenary_request = intif_mercenary_request; - intif->mercenary_delete = intif_mercenary_delete; - intif->mercenary_save = intif_mercenary_save; - // MAIL SYSTEM - intif->Mail_requestinbox = intif_Mail_requestinbox; - intif->Mail_read = intif_Mail_read; - intif->Mail_getattach = intif_Mail_getattach; - intif->Mail_delete = intif_Mail_delete; - intif->Mail_return = intif_Mail_return; - intif->Mail_send = intif_Mail_send; - // AUCTION SYSTEM - intif->Auction_requestlist = intif_Auction_requestlist; - intif->Auction_register = intif_Auction_register; - intif->Auction_cancel = intif_Auction_cancel; - intif->Auction_close = intif_Auction_close; - intif->Auction_bid = intif_Auction_bid; - // ELEMENTAL SYSTEM - intif->elemental_create = intif_elemental_create; - intif->elemental_request = intif_elemental_request; - intif->elemental_delete = intif_elemental_delete; - intif->elemental_save = intif_elemental_save; - /* @accinfo */ - intif->request_accinfo = intif_request_accinfo; - - intif->CheckForCharServer = CheckForCharServer; -} +// Copyright (c) Athena Dev Teams - Licensed under GNU GPL +// For more information, see LICENCE in the main folder + +#include "../common/showmsg.h" +#include "../common/socket.h" +#include "../common/timer.h" +#include "../common/nullpo.h" +#include "../common/malloc.h" +#include "../common/strlib.h" +#include "map.h" +#include "battle.h" +#include "chrif.h" +#include "clif.h" +#include "pc.h" +#include "intif.h" +#include "log.h" +#include "storage.h" +#include "party.h" +#include "guild.h" +#include "pet.h" +#include "atcommand.h" +#include "mercenary.h" +#include "homunculus.h" +#include "elemental.h" +#include "mail.h" +#include "quest.h" + +#include +#include +#include +#include +#include +#include + + +static const int packet_len_table[]={ + -1,-1,27,-1, -1, 0,37,-1, 0, 0, 0, 0, 0, 0, 0, 0, //0x3800-0x380f + 0, 0, 0, 0, 0, 0, 0, 0, -1,11, 0, 0, 0, 0, 0, 0, //0x3810 + 39,-1,15,15, 14,19, 7,-1, 0, 0, 0, 0, 0, 0, 0, 0, //0x3820 + 10,-1,15, 0, 79,19, 7,-1, 0,-1,-1,-1, 14,67,186,-1, //0x3830 + -1, 0, 0,14, 0, 0, 0, 0, -1,74,-1,11, 11,-1, 0, 0, //0x3840 + -1,-1, 7, 7, 7,11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3850 Auctions [Zephyrus] + -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3860 Quests [Kevin] [Inkfish] + -1, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 3, 3, 0, //0x3870 Mercenaries [Zephyrus] / Elemental [pakpil] + 11,-1, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3880 + -1,-1, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3890 Homunculus [albator] +}; + +extern int char_fd; // inter server Fd used for char_fd +#define inter_fd char_fd // alias + +//----------------------------------------------------------------- +// Send to inter server + +int CheckForCharServer(void) +{ + return ((char_fd <= 0) || session[char_fd] == NULL || session[char_fd]->wdata == NULL); +} + +// pet +int intif_create_pet(int account_id,int char_id,short pet_class,short pet_lv,short pet_egg_id, + short pet_equip,short intimate,short hungry,char rename_flag,char incuvate,char *pet_name) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd, 24 + NAME_LENGTH); + WFIFOW(inter_fd,0) = 0x3080; + WFIFOL(inter_fd,2) = account_id; + WFIFOL(inter_fd,6) = char_id; + WFIFOW(inter_fd,10) = pet_class; + WFIFOW(inter_fd,12) = pet_lv; + WFIFOW(inter_fd,14) = pet_egg_id; + WFIFOW(inter_fd,16) = pet_equip; + WFIFOW(inter_fd,18) = intimate; + WFIFOW(inter_fd,20) = hungry; + WFIFOB(inter_fd,22) = rename_flag; + WFIFOB(inter_fd,23) = incuvate; + memcpy(WFIFOP(inter_fd,24),pet_name,NAME_LENGTH); + WFIFOSET(inter_fd,24+NAME_LENGTH); + + return 0; +} + +int intif_request_petdata(int account_id,int char_id,int pet_id) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd, 14); + WFIFOW(inter_fd,0) = 0x3081; + WFIFOL(inter_fd,2) = account_id; + WFIFOL(inter_fd,6) = char_id; + WFIFOL(inter_fd,10) = pet_id; + WFIFOSET(inter_fd,14); + + return 0; +} + +int intif_save_petdata(int account_id,struct s_pet *p) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd, sizeof(struct s_pet) + 8); + WFIFOW(inter_fd,0) = 0x3082; + WFIFOW(inter_fd,2) = sizeof(struct s_pet) + 8; + WFIFOL(inter_fd,4) = account_id; + memcpy(WFIFOP(inter_fd,8),p,sizeof(struct s_pet)); + WFIFOSET(inter_fd,WFIFOW(inter_fd,2)); + + return 0; +} + +int intif_delete_petdata(int pet_id) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd,6); + WFIFOW(inter_fd,0) = 0x3083; + WFIFOL(inter_fd,2) = pet_id; + WFIFOSET(inter_fd,6); + + return 1; +} + +int intif_rename(struct map_session_data *sd, int type, char *name) +{ + if (intif->CheckForCharServer()) + return 1; + + WFIFOHEAD(inter_fd,NAME_LENGTH+12); + WFIFOW(inter_fd,0) = 0x3006; + WFIFOL(inter_fd,2) = sd->status.account_id; + WFIFOL(inter_fd,6) = sd->status.char_id; + WFIFOB(inter_fd,10) = type; //Type: 0 - PC, 1 - PET, 2 - HOM + memcpy(WFIFOP(inter_fd,11),name, NAME_LENGTH); + WFIFOSET(inter_fd,NAME_LENGTH+12); + return 0; +} + +// GM Send a message +int intif_broadcast(const char* mes, int len, int type) +{ + int lp = type ? 4 : 0; + + // Send to the local players + clif->broadcast(NULL, mes, len, type, ALL_CLIENT); + + if (intif->CheckForCharServer()) + return 0; + + if (chrif->other_mapserver_count < 1) + return 0; //No need to send. + + WFIFOHEAD(inter_fd, 16 + lp + len); + WFIFOW(inter_fd,0) = 0x3000; + WFIFOW(inter_fd,2) = 16 + lp + len; + WFIFOL(inter_fd,4) = 0xFF000000; // 0xFF000000 color signals standard broadcast + WFIFOW(inter_fd,8) = 0; // fontType not used with standard broadcast + WFIFOW(inter_fd,10) = 0; // fontSize not used with standard broadcast + WFIFOW(inter_fd,12) = 0; // fontAlign not used with standard broadcast + WFIFOW(inter_fd,14) = 0; // fontY not used with standard broadcast + if (type == 0x10) // bc_blue + WFIFOL(inter_fd,16) = 0x65756c62; //If there's "blue" at the beginning of the message, game client will display it in blue instead of yellow. + else if (type == 0x20) // bc_woe + WFIFOL(inter_fd,16) = 0x73737373; //If there's "ssss", game client will recognize message as 'WoE broadcast'. + memcpy(WFIFOP(inter_fd,16 + lp), mes, len); + WFIFOSET(inter_fd, WFIFOW(inter_fd,2)); + return 0; +} + +int intif_broadcast2(const char* mes, int len, unsigned long fontColor, short fontType, short fontSize, short fontAlign, short fontY) +{ + // Send to the local players + clif->broadcast2(NULL, mes, len, fontColor, fontType, fontSize, fontAlign, fontY, ALL_CLIENT); + + if (intif->CheckForCharServer()) + return 0; + + if (chrif->other_mapserver_count < 1) + return 0; //No need to send. + + WFIFOHEAD(inter_fd, 16 + len); + WFIFOW(inter_fd,0) = 0x3000; + WFIFOW(inter_fd,2) = 16 + len; + WFIFOL(inter_fd,4) = fontColor; + WFIFOW(inter_fd,8) = fontType; + WFIFOW(inter_fd,10) = fontSize; + WFIFOW(inter_fd,12) = fontAlign; + WFIFOW(inter_fd,14) = fontY; + memcpy(WFIFOP(inter_fd,16), mes, len); + WFIFOSET(inter_fd, WFIFOW(inter_fd,2)); + return 0; +} + +/// send a message using the main chat system +/// the source of message +/// the message that was sent +int intif_main_message(struct map_session_data* sd, const char* message) +{ + char output[256]; + + nullpo_ret(sd); + + // format the message for main broadcasting + snprintf( output, sizeof(output), msg_txt(386), sd->status.name, message ); + + // send the message using the inter-server broadcast service + intif_broadcast2( output, strlen(output) + 1, 0xFE000000, 0, 0, 0, 0 ); + + // log the chat message + logs->chat( LOG_CHAT_MAINCHAT, 0, sd->status.char_id, sd->status.account_id, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, NULL, message ); + + return 0; +} + +// The transmission of Wisp/Page to inter-server (player not found on this server) +int intif_wis_message(struct map_session_data *sd, char *nick, char *mes, int mes_len) +{ + nullpo_ret(sd); + if (intif->CheckForCharServer()) + return 0; + + if (chrif->other_mapserver_count < 1) + { //Character not found. + clif->wis_end(sd->fd, 1); + return 0; + } + + WFIFOHEAD(inter_fd,mes_len + 52); + WFIFOW(inter_fd,0) = 0x3001; + WFIFOW(inter_fd,2) = mes_len + 52; + memcpy(WFIFOP(inter_fd,4), sd->status.name, NAME_LENGTH); + memcpy(WFIFOP(inter_fd,4+NAME_LENGTH), nick, NAME_LENGTH); + memcpy(WFIFOP(inter_fd,4+2*NAME_LENGTH), mes, mes_len); + WFIFOSET(inter_fd, WFIFOW(inter_fd,2)); + + if (battle_config.etc_log) + ShowInfo("intif_wis_message from %s to %s (message: '%s')\n", sd->status.name, nick, mes); + + return 0; +} + +// The reply of Wisp/page +int intif_wis_replay(int id, int flag) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd,7); + WFIFOW(inter_fd,0) = 0x3002; + WFIFOL(inter_fd,2) = id; + WFIFOB(inter_fd,6) = flag; // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target + WFIFOSET(inter_fd,7); + + if (battle_config.etc_log) + ShowInfo("intif_wis_replay: id: %d, flag:%d\n", id, flag); + + return 0; +} + +// The transmission of GM only Wisp/Page from server to inter-server +int intif_wis_message_to_gm(char *wisp_name, int permission, char *mes) +{ + int mes_len; + if (intif->CheckForCharServer()) + return 0; + mes_len = strlen(mes) + 1; // + null + WFIFOHEAD(inter_fd, mes_len + 32); + WFIFOW(inter_fd,0) = 0x3003; + WFIFOW(inter_fd,2) = mes_len + 32; + memcpy(WFIFOP(inter_fd,4), wisp_name, NAME_LENGTH); + WFIFOL(inter_fd,4+NAME_LENGTH) = permission; + memcpy(WFIFOP(inter_fd,8+NAME_LENGTH), mes, mes_len); + WFIFOSET(inter_fd, WFIFOW(inter_fd,2)); + + if (battle_config.etc_log) + ShowNotice("intif_wis_message_to_gm: from: '%s', required permission: %d, message: '%s'.\n", wisp_name, permission, mes); + + return 0; +} + +int intif_regtostr(char* str, struct global_reg *reg, int qty) +{ + int len =0, i; + + for (i = 0; i < qty; i++) { + len+= sprintf(str+len, "%s", reg[i].str)+1; //We add 1 to consider the '\0' in place. + len+= sprintf(str+len, "%s", reg[i].value)+1; + } + return len; +} + +//Request for saving registry values. +int intif_saveregistry(struct map_session_data *sd, int type) +{ + struct global_reg *reg; + int count; + int i, p; + + if (intif->CheckForCharServer()) + return -1; + + switch (type) { + case 3: //Character reg + reg = sd->save_reg.global; + count = sd->save_reg.global_num; + sd->state.reg_dirty &= ~0x4; + break; + case 2: //Account reg + reg = sd->save_reg.account; + count = sd->save_reg.account_num; + sd->state.reg_dirty &= ~0x2; + break; + case 1: //Account2 reg + reg = sd->save_reg.account2; + count = sd->save_reg.account2_num; + sd->state.reg_dirty &= ~0x1; + break; + default: //Broken code? + ShowError("intif_saveregistry: Invalid type %d\n", type); + return -1; + } + WFIFOHEAD(inter_fd, 288 * MAX_REG_NUM+13); + WFIFOW(inter_fd,0)=0x3004; + WFIFOL(inter_fd,4)=sd->status.account_id; + WFIFOL(inter_fd,8)=sd->status.char_id; + WFIFOB(inter_fd,12)=type; + for( p = 13, i = 0; i < count; i++ ) { + if (reg[i].str[0] != '\0' && reg[i].value[0] != '\0') { + p+= sprintf((char*)WFIFOP(inter_fd,p), "%s", reg[i].str)+1; //We add 1 to consider the '\0' in place. + p+= sprintf((char*)WFIFOP(inter_fd,p), "%s", reg[i].value)+1; + } + } + WFIFOW(inter_fd,2)=p; + WFIFOSET(inter_fd,WFIFOW(inter_fd,2)); + return 0; +} + +//Request the registries for this player. +int intif_request_registry(struct map_session_data *sd, int flag) +{ + nullpo_ret(sd); + + sd->save_reg.account2_num = -1; + sd->save_reg.account_num = -1; + sd->save_reg.global_num = -1; + + if (intif->CheckForCharServer()) + return 0; + + WFIFOHEAD(inter_fd,6); + WFIFOW(inter_fd,0) = 0x3005; + WFIFOL(inter_fd,2) = sd->status.account_id; + WFIFOL(inter_fd,6) = sd->status.char_id; + WFIFOB(inter_fd,10) = (flag&1?1:0); //Request Acc Reg 2 + WFIFOB(inter_fd,11) = (flag&2?1:0); //Request Acc Reg + WFIFOB(inter_fd,12) = (flag&4?1:0); //Request Char Reg + WFIFOSET(inter_fd,13); + + return 0; +} + +int intif_request_guild_storage(int account_id,int guild_id) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd,10); + WFIFOW(inter_fd,0) = 0x3018; + WFIFOL(inter_fd,2) = account_id; + WFIFOL(inter_fd,6) = guild_id; + WFIFOSET(inter_fd,10); + return 0; +} +int intif_send_guild_storage(int account_id,struct guild_storage *gstor) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd,sizeof(struct guild_storage)+12); + WFIFOW(inter_fd,0) = 0x3019; + WFIFOW(inter_fd,2) = (unsigned short)sizeof(struct guild_storage)+12; + WFIFOL(inter_fd,4) = account_id; + WFIFOL(inter_fd,8) = gstor->guild_id; + memcpy( WFIFOP(inter_fd,12),gstor, sizeof(struct guild_storage) ); + WFIFOSET(inter_fd,WFIFOW(inter_fd,2)); + return 0; +} + +// Party creation request +int intif_create_party(struct party_member *member,char *name,int item,int item2) +{ + if (intif->CheckForCharServer()) + return 0; + nullpo_ret(member); + + WFIFOHEAD(inter_fd,64); + WFIFOW(inter_fd,0) = 0x3020; + WFIFOW(inter_fd,2) = 30+sizeof(struct party_member); + memcpy(WFIFOP(inter_fd,4),name, NAME_LENGTH); + WFIFOB(inter_fd,28)= item; + WFIFOB(inter_fd,29)= item2; + memcpy(WFIFOP(inter_fd,30), member, sizeof(struct party_member)); + WFIFOSET(inter_fd,WFIFOW(inter_fd, 2)); + return 0; +} + +// Party information request +int intif_request_partyinfo(int party_id, int char_id) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd,10); + WFIFOW(inter_fd,0) = 0x3021; + WFIFOL(inter_fd,2) = party_id; + WFIFOL(inter_fd,6) = char_id; + WFIFOSET(inter_fd,10); + return 0; +} + +// Request to add a member to party +int intif_party_addmember(int party_id,struct party_member *member) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd,42); + WFIFOW(inter_fd,0)=0x3022; + WFIFOW(inter_fd,2)=8+sizeof(struct party_member); + WFIFOL(inter_fd,4)=party_id; + memcpy(WFIFOP(inter_fd,8),member,sizeof(struct party_member)); + WFIFOSET(inter_fd,WFIFOW(inter_fd, 2)); + return 1; +} + +// Request to change party configuration (exp,item share) +int intif_party_changeoption(int party_id,int account_id,int exp,int item) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd,14); + WFIFOW(inter_fd,0)=0x3023; + WFIFOL(inter_fd,2)=party_id; + WFIFOL(inter_fd,6)=account_id; + WFIFOW(inter_fd,10)=exp; + WFIFOW(inter_fd,12)=item; + WFIFOSET(inter_fd,14); + return 0; +} + +// Request to leave party +int intif_party_leave(int party_id,int account_id, int char_id) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd,14); + WFIFOW(inter_fd,0)=0x3024; + WFIFOL(inter_fd,2)=party_id; + WFIFOL(inter_fd,6)=account_id; + WFIFOL(inter_fd,10)=char_id; + WFIFOSET(inter_fd,14); + return 0; +} + +// Request keeping party for new map ?? +int intif_party_changemap(struct map_session_data *sd,int online) +{ + int16 m, mapindex; + + if (intif->CheckForCharServer()) + return 0; + if(!sd) + return 0; + + if( (m=iMap->mapindex2mapid(sd->mapindex)) >= 0 && map[m].instance_id >= 0 ) + mapindex = map[map[m].instance_src_map].index; + else + mapindex = sd->mapindex; + + WFIFOHEAD(inter_fd,19); + WFIFOW(inter_fd,0)=0x3025; + WFIFOL(inter_fd,2)=sd->status.party_id; + WFIFOL(inter_fd,6)=sd->status.account_id; + WFIFOL(inter_fd,10)=sd->status.char_id; + WFIFOW(inter_fd,14)=mapindex; + WFIFOB(inter_fd,16)=online; + WFIFOW(inter_fd,17)=sd->status.base_level; + WFIFOSET(inter_fd,19); + return 1; +} + +// Request breaking party +int intif_break_party(int party_id) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd,6); + WFIFOW(inter_fd,0)=0x3026; + WFIFOL(inter_fd,2)=party_id; + WFIFOSET(inter_fd,6); + return 0; +} + +// Sending party chat +int intif_party_message(int party_id,int account_id,const char *mes,int len) +{ + if (intif->CheckForCharServer()) + return 0; + + if (chrif->other_mapserver_count < 1) + return 0; //No need to send. + + WFIFOHEAD(inter_fd,len + 12); + WFIFOW(inter_fd,0)=0x3027; + WFIFOW(inter_fd,2)=len+12; + WFIFOL(inter_fd,4)=party_id; + WFIFOL(inter_fd,8)=account_id; + memcpy(WFIFOP(inter_fd,12),mes,len); + WFIFOSET(inter_fd,len+12); + return 0; +} + +// Request a new leader for party +int intif_party_leaderchange(int party_id,int account_id,int char_id) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd,14); + WFIFOW(inter_fd,0)=0x3029; + WFIFOL(inter_fd,2)=party_id; + WFIFOL(inter_fd,6)=account_id; + WFIFOL(inter_fd,10)=char_id; + WFIFOSET(inter_fd,14); + return 0; +} + +// Request a Guild creation +int intif_guild_create(const char *name,const struct guild_member *master) +{ + if (intif->CheckForCharServer()) + return 0; + nullpo_ret(master); + + WFIFOHEAD(inter_fd,sizeof(struct guild_member)+(8+NAME_LENGTH)); + WFIFOW(inter_fd,0)=0x3030; + WFIFOW(inter_fd,2)=sizeof(struct guild_member)+(8+NAME_LENGTH); + WFIFOL(inter_fd,4)=master->account_id; + memcpy(WFIFOP(inter_fd,8),name,NAME_LENGTH); + memcpy(WFIFOP(inter_fd,8+NAME_LENGTH),master,sizeof(struct guild_member)); + WFIFOSET(inter_fd,WFIFOW(inter_fd,2)); + return 0; +} + +// Request Guild information +int intif_guild_request_info(int guild_id) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd,6); + WFIFOW(inter_fd,0) = 0x3031; + WFIFOL(inter_fd,2) = guild_id; + WFIFOSET(inter_fd,6); + return 0; +} + +// Request to add member to the guild +int intif_guild_addmember(int guild_id,struct guild_member *m) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd,sizeof(struct guild_member)+8); + WFIFOW(inter_fd,0) = 0x3032; + WFIFOW(inter_fd,2) = sizeof(struct guild_member)+8; + WFIFOL(inter_fd,4) = guild_id; + memcpy(WFIFOP(inter_fd,8),m,sizeof(struct guild_member)); + WFIFOSET(inter_fd,WFIFOW(inter_fd,2)); + return 0; +} + +// Request a new leader for guild +int intif_guild_change_gm(int guild_id, const char* name, int len) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd, len + 8); + WFIFOW(inter_fd, 0)=0x3033; + WFIFOW(inter_fd, 2)=len+8; + WFIFOL(inter_fd, 4)=guild_id; + memcpy(WFIFOP(inter_fd,8),name,len); + WFIFOSET(inter_fd,len+8); + return 0; +} + +// Request to leave guild +int intif_guild_leave(int guild_id,int account_id,int char_id,int flag,const char *mes) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd, 55); + WFIFOW(inter_fd, 0) = 0x3034; + WFIFOL(inter_fd, 2) = guild_id; + WFIFOL(inter_fd, 6) = account_id; + WFIFOL(inter_fd,10) = char_id; + WFIFOB(inter_fd,14) = flag; + safestrncpy((char*)WFIFOP(inter_fd,15),mes,40); + WFIFOSET(inter_fd,55); + return 0; +} + +//Update request / Lv online status of the guild members +int intif_guild_memberinfoshort(int guild_id,int account_id,int char_id,int online,int lv,int class_) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd, 19); + WFIFOW(inter_fd, 0) = 0x3035; + WFIFOL(inter_fd, 2) = guild_id; + WFIFOL(inter_fd, 6) = account_id; + WFIFOL(inter_fd,10) = char_id; + WFIFOB(inter_fd,14) = online; + WFIFOW(inter_fd,15) = lv; + WFIFOW(inter_fd,17) = class_; + WFIFOSET(inter_fd,19); + return 0; +} + +//Guild disbanded notification +int intif_guild_break(int guild_id) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd, 6); + WFIFOW(inter_fd, 0) = 0x3036; + WFIFOL(inter_fd, 2) = guild_id; + WFIFOSET(inter_fd,6); + return 0; +} + +// Send a guild message +int intif_guild_message(int guild_id,int account_id,const char *mes,int len) +{ + if (intif->CheckForCharServer()) + return 0; + + if (chrif->other_mapserver_count < 1) + return 0; //No need to send. + + WFIFOHEAD(inter_fd, len + 12); + WFIFOW(inter_fd,0)=0x3037; + WFIFOW(inter_fd,2)=len+12; + WFIFOL(inter_fd,4)=guild_id; + WFIFOL(inter_fd,8)=account_id; + memcpy(WFIFOP(inter_fd,12),mes,len); + WFIFOSET(inter_fd,len+12); + + return 0; +} + +// Request a change of Guild basic information +int intif_guild_change_basicinfo(int guild_id,int type,const void *data,int len) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd, len + 10); + WFIFOW(inter_fd,0)=0x3039; + WFIFOW(inter_fd,2)=len+10; + WFIFOL(inter_fd,4)=guild_id; + WFIFOW(inter_fd,8)=type; + memcpy(WFIFOP(inter_fd,10),data,len); + WFIFOSET(inter_fd,len+10); + return 0; +} + +// Request a change of Guild member information +int intif_guild_change_memberinfo(int guild_id,int account_id,int char_id, + int type,const void *data,int len) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd, len + 18); + WFIFOW(inter_fd, 0)=0x303a; + WFIFOW(inter_fd, 2)=len+18; + WFIFOL(inter_fd, 4)=guild_id; + WFIFOL(inter_fd, 8)=account_id; + WFIFOL(inter_fd,12)=char_id; + WFIFOW(inter_fd,16)=type; + memcpy(WFIFOP(inter_fd,18),data,len); + WFIFOSET(inter_fd,len+18); + return 0; +} + +// Request a change of Guild title +int intif_guild_position(int guild_id,int idx,struct guild_position *p) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd, sizeof(struct guild_position)+12); + WFIFOW(inter_fd,0)=0x303b; + WFIFOW(inter_fd,2)=sizeof(struct guild_position)+12; + WFIFOL(inter_fd,4)=guild_id; + WFIFOL(inter_fd,8)=idx; + memcpy(WFIFOP(inter_fd,12),p,sizeof(struct guild_position)); + WFIFOSET(inter_fd,WFIFOW(inter_fd,2)); + return 0; +} + +// Request an update of Guildskill skill_id +int intif_guild_skillup(int guild_id, uint16 skill_id, int account_id, int max) +{ + if( intif->CheckForCharServer() ) + return 0; + WFIFOHEAD(inter_fd, 18); + WFIFOW(inter_fd, 0) = 0x303c; + WFIFOL(inter_fd, 2) = guild_id; + WFIFOL(inter_fd, 6) = skill_id; + WFIFOL(inter_fd, 10) = account_id; + WFIFOL(inter_fd, 14) = max; + WFIFOSET(inter_fd, 18); + return 0; +} + +// Request a new guild relationship +int intif_guild_alliance(int guild_id1,int guild_id2,int account_id1,int account_id2,int flag) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd,19); + WFIFOW(inter_fd, 0)=0x303d; + WFIFOL(inter_fd, 2)=guild_id1; + WFIFOL(inter_fd, 6)=guild_id2; + WFIFOL(inter_fd,10)=account_id1; + WFIFOL(inter_fd,14)=account_id2; + WFIFOB(inter_fd,18)=flag; + WFIFOSET(inter_fd,19); + return 0; +} + +// Request to change guild notice +int intif_guild_notice(int guild_id,const char *mes1,const char *mes2) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd,186); + WFIFOW(inter_fd,0)=0x303e; + WFIFOL(inter_fd,2)=guild_id; + memcpy(WFIFOP(inter_fd,6),mes1,MAX_GUILDMES1); + memcpy(WFIFOP(inter_fd,66),mes2,MAX_GUILDMES2); + WFIFOSET(inter_fd,186); + return 0; +} + +// Request to change guild emblem +int intif_guild_emblem(int guild_id,int len,const char *data) +{ + if (intif->CheckForCharServer()) + return 0; + if(guild_id<=0 || len<0 || len>2000) + return 0; + WFIFOHEAD(inter_fd,len + 12); + WFIFOW(inter_fd,0)=0x303f; + WFIFOW(inter_fd,2)=len+12; + WFIFOL(inter_fd,4)=guild_id; + WFIFOL(inter_fd,8)=0; + memcpy(WFIFOP(inter_fd,12),data,len); + WFIFOSET(inter_fd,len+12); + return 0; +} + +/** + * Requests guild castles data from char-server. + * @param num Number of castles, size of castle_ids array. + * @param castle_ids Pointer to array of castle IDs. + */ +int intif_guild_castle_dataload(int num, int *castle_ids) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd, 4 + num * sizeof(int)); + WFIFOW(inter_fd, 0) = 0x3040; + WFIFOW(inter_fd, 2) = 4 + num * sizeof(int); + memcpy(WFIFOP(inter_fd, 4), castle_ids, num * sizeof(int)); + WFIFOSET(inter_fd, WFIFOW(inter_fd, 2)); + return 1; +} + + +// Request change castle guild owner and save data +int intif_guild_castle_datasave(int castle_id,int index, int value) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd,9); + WFIFOW(inter_fd,0)=0x3041; + WFIFOW(inter_fd,2)=castle_id; + WFIFOB(inter_fd,4)=index; + WFIFOL(inter_fd,5)=value; + WFIFOSET(inter_fd,9); + return 1; +} + +//----------------------------------------------------------------- +// Homunculus Packets send to Inter server [albator] +//----------------------------------------------------------------- + +int intif_homunculus_create(int account_id, struct s_homunculus *sh) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd, sizeof(struct s_homunculus)+8); + WFIFOW(inter_fd,0) = 0x3090; + WFIFOW(inter_fd,2) = sizeof(struct s_homunculus)+8; + WFIFOL(inter_fd,4) = account_id; + memcpy(WFIFOP(inter_fd,8),sh,sizeof(struct s_homunculus)); + WFIFOSET(inter_fd, WFIFOW(inter_fd,2)); + return 0; +} + +bool intif_homunculus_requestload(int account_id, int homun_id) { + if (intif->CheckForCharServer()) + return false; + WFIFOHEAD(inter_fd, 10); + WFIFOW(inter_fd,0) = 0x3091; + WFIFOL(inter_fd,2) = account_id; + WFIFOL(inter_fd,6) = homun_id; + WFIFOSET(inter_fd, 10); + return true; +} + +int intif_homunculus_requestsave(int account_id, struct s_homunculus* sh) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd, sizeof(struct s_homunculus)+8); + WFIFOW(inter_fd,0) = 0x3092; + WFIFOW(inter_fd,2) = sizeof(struct s_homunculus)+8; + WFIFOL(inter_fd,4) = account_id; + memcpy(WFIFOP(inter_fd,8),sh,sizeof(struct s_homunculus)); + WFIFOSET(inter_fd, WFIFOW(inter_fd,2)); + return 0; + +} + +int intif_homunculus_requestdelete(int homun_id) +{ + if (intif->CheckForCharServer()) + return 0; + WFIFOHEAD(inter_fd, 6); + WFIFOW(inter_fd, 0) = 0x3093; + WFIFOL(inter_fd,2) = homun_id; + WFIFOSET(inter_fd,6); + return 0; + +} + + +//----------------------------------------------------------------- +// Packets receive from inter server + +// Wisp/Page reception // rewritten by [Yor] +int intif_parse_WisMessage(int fd) +{ + struct map_session_data* sd; + char *wisp_source; + char name[NAME_LENGTH]; + int id, i; + + id=RFIFOL(fd,4); + + safestrncpy(name, (char*)RFIFOP(fd,32), NAME_LENGTH); + sd = iMap->nick2sd(name); + if(sd == NULL || strcmp(sd->status.name, name) != 0) + { //Not found + intif_wis_replay(id,1); + return 0; + } + if(sd->state.ignoreAll) { + intif_wis_replay(id, 2); + return 0; + } + wisp_source = (char *) RFIFOP(fd,8); // speed up [Yor] + for(i=0; i < MAX_IGNORE_LIST && + sd->ignore[i].name[0] != '\0' && + strcmp(sd->ignore[i].name, wisp_source) != 0 + ; i++); + + if (i < MAX_IGNORE_LIST && sd->ignore[i].name[0] != '\0') + { //Ignored + intif_wis_replay(id, 2); + return 0; + } + //Success to send whisper. + clif->wis_message(sd->fd, wisp_source, (char*)RFIFOP(fd,56),RFIFOW(fd,2)-56); + intif_wis_replay(id,0); // succes + return 0; +} + +// Wisp/page transmission result reception +int intif_parse_WisEnd(int fd) +{ + struct map_session_data* sd; + + if (battle_config.etc_log) + ShowInfo("intif_parse_wisend: player: %s, flag: %d\n", RFIFOP(fd,2), RFIFOB(fd,26)); // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target + sd = (struct map_session_data *)iMap->nick2sd((char *) RFIFOP(fd,2)); + if (sd != NULL) + clif->wis_end(sd->fd, RFIFOB(fd,26)); + + return 0; +} + +static int mapif_parse_WisToGM_sub(struct map_session_data* sd,va_list va) +{ + int permission = va_arg(va, int); + char *wisp_name; + char *message; + int len; + + if (!pc_has_permission(sd, permission)) + return 0; + wisp_name = va_arg(va, char*); + message = va_arg(va, char*); + len = va_arg(va, int); + clif->wis_message(sd->fd, wisp_name, message, len); + return 1; +} + +// Received wisp message from map-server via char-server for ALL gm +// 0x3003/0x3803 .w .24B .l .?B +int mapif_parse_WisToGM(int fd) +{ + int permission, mes_len; + char Wisp_name[NAME_LENGTH]; + char mbuf[255]; + char *message; + + mes_len = RFIFOW(fd,2) - 32; + message = (char *) (mes_len >= 255 ? (char *) aMalloc(mes_len) : mbuf); + + permission = RFIFOL(fd,28); + safestrncpy(Wisp_name, (char*)RFIFOP(fd,4), NAME_LENGTH); + safestrncpy(message, (char*)RFIFOP(fd,32), mes_len); + // information is sent to all online GM + iMap->map_foreachpc(mapif_parse_WisToGM_sub, permission, Wisp_name, message, mes_len); + + if (message != mbuf) + aFree(message); + return 0; +} + +// Request player registre +int intif_parse_Registers(int fd) +{ + int j,p,len,max, flag; + struct map_session_data *sd; + struct global_reg *reg; + int *qty; + int account_id = RFIFOL(fd,4), char_id = RFIFOL(fd,8); + struct auth_node *node = chrif->auth_check(account_id, char_id, ST_LOGIN); + if (node) + sd = node->sd; + else { //Normally registries should arrive for in log-in chars. + sd = iMap->id2sd(account_id); + if (sd && RFIFOB(fd,12) == 3 && sd->status.char_id != char_id) + sd = NULL; //Character registry from another character. + } + if (!sd) return 1; + + flag = (sd->save_reg.global_num == -1 || sd->save_reg.account_num == -1 || sd->save_reg.account2_num == -1); + + switch (RFIFOB(fd,12)) { + case 3: //Character Registry + reg = sd->save_reg.global; + qty = &sd->save_reg.global_num; + max = GLOBAL_REG_NUM; + break; + case 2: //Account Registry + reg = sd->save_reg.account; + qty = &sd->save_reg.account_num; + max = ACCOUNT_REG_NUM; + break; + case 1: //Account2 Registry + reg = sd->save_reg.account2; + qty = &sd->save_reg.account2_num; + max = ACCOUNT_REG2_NUM; + break; + default: + ShowError("intif_parse_Registers: Unrecognized type %d\n",RFIFOB(fd,12)); + return 0; + } + for(j=0,p=13;jsave_reg.global_num > -1 && sd->save_reg.account_num > -1 && sd->save_reg.account2_num > -1) + pc->reg_received(sd); //Received all registry values, execute init scripts and what-not. [Skotlex] + return 1; +} + +int intif_parse_LoadGuildStorage(int fd) +{ + struct guild_storage *gstor; + struct map_session_data *sd; + int guild_id; + + guild_id = RFIFOL(fd,8); + if(guild_id <= 0) + return 1; + sd=iMap->id2sd( RFIFOL(fd,4) ); + if(sd==NULL){ + ShowError("intif_parse_LoadGuildStorage: user not found %d\n",RFIFOL(fd,4)); + return 1; + } + gstor=gstorage->id2storage(guild_id); + if(!gstor) { + ShowWarning("intif_parse_LoadGuildStorage: error guild_id %d not exist\n",guild_id); + return 1; + } + if (gstor->storage_status == 1) { // Already open.. lets ignore this update + ShowWarning("intif_parse_LoadGuildStorage: storage received for a client already open (User %d:%d)\n", sd->status.account_id, sd->status.char_id); + return 1; + } + if (gstor->dirty) { // Already have storage, and it has been modified and not saved yet! Exploit! [Skotlex] + ShowWarning("intif_parse_LoadGuildStorage: received storage for an already modified non-saved storage! (User %d:%d)\n", sd->status.account_id, sd->status.char_id); + return 1; + } + if( RFIFOW(fd,2)-12 != sizeof(struct guild_storage) ){ + ShowError("intif_parse_LoadGuildStorage: data size error %d %d\n",RFIFOW(fd,2)-12 , sizeof(struct guild_storage)); + gstor->storage_status = 0; + return 1; + } + + memcpy(gstor,RFIFOP(fd,12),sizeof(struct guild_storage)); + gstorage->open(sd); + return 0; +} + +// ACK guild_storage saved +int intif_parse_SaveGuildStorage(int fd) +{ + gstorage->saved(/*RFIFOL(fd,2), */RFIFOL(fd,6)); + return 0; +} + +// ACK party creation +int intif_parse_PartyCreated(int fd) +{ + if(battle_config.etc_log) + ShowInfo("intif: party created by account %d\n\n", RFIFOL(fd,2)); + party->created(RFIFOL(fd,2), RFIFOL(fd,6),RFIFOB(fd,10),RFIFOL(fd,11), (char *)RFIFOP(fd,15)); + return 0; +} + +// Receive party info +int intif_parse_PartyInfo(int fd) +{ + if( RFIFOW(fd,2) == 12 ){ + ShowWarning("intif: party noinfo (char_id=%d party_id=%d)\n", RFIFOL(fd,4), RFIFOL(fd,8)); + party->recv_noinfo(RFIFOL(fd,8), RFIFOL(fd,4)); + return 0; + } + + if( RFIFOW(fd,2) != 8+sizeof(struct party) ) + ShowError("intif: party info : data size error (char_id=%d party_id=%d packet_len=%d expected_len=%d)\n", RFIFOL(fd,4), RFIFOL(fd,8), RFIFOW(fd,2), 8+sizeof(struct party)); + party->recv_info((struct party *)RFIFOP(fd,8), RFIFOL(fd,4)); + return 0; +} + +// ACK adding party member +int intif_parse_PartyMemberAdded(int fd) +{ + if(battle_config.etc_log) + ShowInfo("intif: party member added Party (%d), Account(%d), Char(%d)\n",RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10)); + party->member_added(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10), RFIFOB(fd, 14)); + return 0; +} + +// ACK changing party option +int intif_parse_PartyOptionChanged(int fd) +{ + party->optionchanged(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOW(fd,10),RFIFOW(fd,12),RFIFOB(fd,14)); + return 0; +} + +// ACK member leaving party +int intif_parse_PartyMemberWithdraw(int fd) +{ + if(battle_config.etc_log) + ShowInfo("intif: party member withdraw: Party(%d), Account(%d), Char(%d)\n",RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10)); + party->member_withdraw(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10)); + return 0; +} + +// ACK party break +int intif_parse_PartyBroken(int fd) +{ + party->broken(RFIFOL(fd,2)); + return 0; +} + +// ACK party on new map +int intif_parse_PartyMove(int fd) +{ + party->recv_movemap(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOW(fd,14),RFIFOB(fd,16),RFIFOW(fd,17)); + return 0; +} + +// ACK party messages +int intif_parse_PartyMessage(int fd) +{ + party->recv_message(RFIFOL(fd,4),RFIFOL(fd,8),(char *) RFIFOP(fd,12),RFIFOW(fd,2)-12); + return 0; +} + +// ACK guild creation +int intif_parse_GuildCreated(int fd) +{ + guild->created(RFIFOL(fd,2),RFIFOL(fd,6)); + return 0; +} + +// ACK guild infos +int intif_parse_GuildInfo(int fd) +{ + if(RFIFOW(fd,2) == 8) { + ShowWarning("intif: guild noinfo %d\n",RFIFOL(fd,4)); + guild->recv_noinfo(RFIFOL(fd,4)); + return 0; + } + if( RFIFOW(fd,2)!=sizeof(struct guild)+4 ) + ShowError("intif: guild info : data size error Gid: %d recv size: %d Expected size: %d\n",RFIFOL(fd,4),RFIFOW(fd,2),sizeof(struct guild)+4); + guild->recv_info((struct guild *)RFIFOP(fd,4)); + return 0; +} + +// ACK adding guild member +int intif_parse_GuildMemberAdded(int fd) +{ + if(battle_config.etc_log) + ShowInfo("intif: guild member added %d %d %d %d\n",RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOB(fd,14)); + guild->member_added(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOB(fd,14)); + return 0; +} + +// ACK member leaving guild +int intif_parse_GuildMemberWithdraw(int fd) +{ + guild->member_withdraw(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOB(fd,14),(char *)RFIFOP(fd,55),(char *)RFIFOP(fd,15)); + return 0; +} + +// ACK guild member basic info +int intif_parse_GuildMemberInfoShort(int fd) +{ + guild->recv_memberinfoshort(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOB(fd,14),RFIFOW(fd,15),RFIFOW(fd,17)); + return 0; +} + +// ACK guild break +int intif_parse_GuildBroken(int fd) +{ + guild->broken(RFIFOL(fd,2),RFIFOB(fd,6)); + return 0; +} + +// basic guild info change notice +// 0x3839 .w .l .w .?b +int intif_parse_GuildBasicInfoChanged(int fd) +{ + //int len = RFIFOW(fd,2) - 10; + int guild_id = RFIFOL(fd,4); + int type = RFIFOW(fd,8); + //void* data = RFIFOP(fd,10); + + struct guild* g = guild->search(guild_id); + if( g == NULL ) + return 0; + + switch(type) { + case GBI_EXP: g->exp = RFIFOQ(fd,10); break; + case GBI_GUILDLV: g->guild_lv = RFIFOW(fd,10); break; + case GBI_SKILLPOINT: g->skill_point = RFIFOL(fd,10); break; + } + + return 0; +} + +// guild member info change notice +// 0x383a .w .l .l .l .w .?b +int intif_parse_GuildMemberInfoChanged(int fd) +{ + //int len = RFIFOW(fd,2) - 18; + int guild_id = RFIFOL(fd,4); + int account_id = RFIFOL(fd,8); + int char_id = RFIFOL(fd,12); + int type = RFIFOW(fd,16); + //void* data = RFIFOP(fd,18); + + struct guild* g; + int idx; + + g = guild->search(guild_id); + if( g == NULL ) + return 0; + + idx = guild->getindex(g,account_id,char_id); + if( idx == -1 ) + return 0; + + switch( type ) { + case GMI_POSITION: g->member[idx].position = RFIFOW(fd,18); guild->memberposition_changed(g,idx,RFIFOW(fd,18)); break; + case GMI_EXP: g->member[idx].exp = RFIFOQ(fd,18); break; + case GMI_HAIR: g->member[idx].hair = RFIFOW(fd,18); break; + case GMI_HAIR_COLOR: g->member[idx].hair_color = RFIFOW(fd,18); break; + case GMI_GENDER: g->member[idx].gender = RFIFOW(fd,18); break; + case GMI_CLASS: g->member[idx].class_ = RFIFOW(fd,18); break; + case GMI_LEVEL: g->member[idx].lv = RFIFOW(fd,18); break; + } + return 0; +} + +// ACK change of guild title +int intif_parse_GuildPosition(int fd) +{ + if( RFIFOW(fd,2)!=sizeof(struct guild_position)+12 ) + ShowError("intif: guild info : data size error\n %d %d %d",RFIFOL(fd,4),RFIFOW(fd,2),sizeof(struct guild_position)+12); + guild->position_changed(RFIFOL(fd,4),RFIFOL(fd,8),(struct guild_position *)RFIFOP(fd,12)); + return 0; +} + +// ACK change of guild skill update +int intif_parse_GuildSkillUp(int fd) +{ + guild->skillupack(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10)); + return 0; +} + +// ACK change of guild relationship +int intif_parse_GuildAlliance(int fd) +{ + guild->allianceack(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOL(fd,14),RFIFOB(fd,18),(char *) RFIFOP(fd,19),(char *) RFIFOP(fd,43)); + return 0; +} + +// ACK change of guild notice +int intif_parse_GuildNotice(int fd) +{ + guild->notice_changed(RFIFOL(fd,2),(char *) RFIFOP(fd,6),(char *) RFIFOP(fd,66)); + return 0; +} + +// ACK change of guild emblem +int intif_parse_GuildEmblem(int fd) +{ + guild->emblem_changed(RFIFOW(fd,2)-12,RFIFOL(fd,4),RFIFOL(fd,8), (char *)RFIFOP(fd,12)); + return 0; +} + +// ACK guild message +int intif_parse_GuildMessage(int fd) +{ + guild->recv_message(RFIFOL(fd,4),RFIFOL(fd,8),(char *) RFIFOP(fd,12),RFIFOW(fd,2)-12); + return 0; +} + +// Reply guild castle data request +int intif_parse_GuildCastleDataLoad(int fd) +{ + return guild->castledataloadack(RFIFOW(fd,2), (struct guild_castle *)RFIFOP(fd,4)); +} + +// ACK change of guildmaster +int intif_parse_GuildMasterChanged(int fd) +{ + return guild->gm_changed(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10)); +} + +// Request pet creation +int intif_parse_CreatePet(int fd) +{ + pet_get_egg(RFIFOL(fd,2),RFIFOL(fd,7),RFIFOB(fd,6)); + return 0; +} + +// ACK pet data +int intif_parse_RecvPetData(int fd) +{ + struct s_pet p; + int len; + len=RFIFOW(fd,2); + if(sizeof(struct s_pet)!=len-9) { + if(battle_config.etc_log) + ShowError("intif: pet data: data size error %d %d\n",sizeof(struct s_pet),len-9); + } + else{ + memcpy(&p,RFIFOP(fd,9),sizeof(struct s_pet)); + pet_recv_petdata(RFIFOL(fd,4),&p,RFIFOB(fd,8)); + } + + return 0; +} + +// ACK pet save data +int intif_parse_SavePetOk(int fd) +{ + if(RFIFOB(fd,6) == 1) + ShowError("pet data save failure\n"); + + return 0; +} + +// ACK deleting pet +int intif_parse_DeletePetOk(int fd) +{ + if(RFIFOB(fd,2) == 1) + ShowError("pet data delete failure\n"); + + return 0; +} + +// ACK changing name resquest, players,pets,hommon +int intif_parse_ChangeNameOk(int fd) +{ + struct map_session_data *sd = NULL; + if((sd=iMap->id2sd(RFIFOL(fd,2)))==NULL || + sd->status.char_id != RFIFOL(fd,6)) + return 0; + + switch (RFIFOB(fd,10)) { + case 0: //Players [NOT SUPPORTED YET] + break; + case 1: //Pets + pet_change_name_ack(sd, (char*)RFIFOP(fd,12), RFIFOB(fd,11)); + break; + case 2: //Hom + homun->change_name_ack(sd, (char*)RFIFOP(fd,12), RFIFOB(fd,11)); + break; + } + return 0; +} + +//---------------------------------------------------------------- +// Homunculus recv packets [albator] + +int intif_parse_CreateHomunculus(int fd) +{ + int len; + len=RFIFOW(fd,2)-9; + if(sizeof(struct s_homunculus)!=len) { + if(battle_config.etc_log) + ShowError("intif: create homun data: data size error %d != %d\n",sizeof(struct s_homunculus),len); + return 0; + } + homun->recv_data(RFIFOL(fd,4), (struct s_homunculus*)RFIFOP(fd,9), RFIFOB(fd,8)) ; + return 0; +} + +int intif_parse_RecvHomunculusData(int fd) +{ + int len; + + len=RFIFOW(fd,2)-9; + + if(sizeof(struct s_homunculus)!=len) { + if(battle_config.etc_log) + ShowError("intif: homun data: data size error %d %d\n",sizeof(struct s_homunculus),len); + return 0; + } + homun->recv_data(RFIFOL(fd,4), (struct s_homunculus*)RFIFOP(fd,9), RFIFOB(fd,8)); + return 0; +} + +int intif_parse_SaveHomunculusOk(int fd) +{ + if(RFIFOB(fd,6) != 1) + ShowError("homunculus data save failure for account %d\n", RFIFOL(fd,2)); + + return 0; +} + +int intif_parse_DeleteHomunculusOk(int fd) +{ + if(RFIFOB(fd,2) != 1) + ShowError("Homunculus data delete failure\n"); + + return 0; +} + +/************************************** + +QUESTLOG SYSTEM FUNCTIONS + +***************************************/ + +int intif_request_questlog(TBL_PC *sd) +{ + WFIFOHEAD(inter_fd,6); + WFIFOW(inter_fd,0) = 0x3060; + WFIFOL(inter_fd,2) = sd->status.char_id; + WFIFOSET(inter_fd,6); + return 0; +} + +int intif_parse_questlog(int fd) +{ + int char_id = RFIFOL(fd, 4); + int i; + TBL_PC * sd = iMap->charid2sd(char_id); + + //User not online anymore + if(!sd) + return -1; + + sd->avail_quests = sd->num_quests = (RFIFOW(fd, 2)-8)/sizeof(struct quest); + + memset(&sd->quest_log, 0, sizeof(sd->quest_log)); + + for( i = 0; i < sd->num_quests; i++ ) + { + memcpy(&sd->quest_log[i], RFIFOP(fd, i*sizeof(struct quest)+8), sizeof(struct quest)); + + sd->quest_index[i] = quest_search_db(sd->quest_log[i].quest_id); + + if( sd->quest_index[i] < 0 ) + { + ShowError("intif_parse_questlog: quest %d not found in DB.\n",sd->quest_log[i].quest_id); + sd->avail_quests--; + sd->num_quests--; + i--; + continue; + } + + if( sd->quest_log[i].state == Q_COMPLETE ) + sd->avail_quests--; + } + + quest_pc_login(sd); + + return 0; +} + +int intif_parse_questsave(int fd) +{ + int cid = RFIFOL(fd, 2); + TBL_PC *sd = iMap->id2sd(cid); + + if( !RFIFOB(fd, 6) ) + ShowError("intif_parse_questsave: Failed to save quest(s) for character %d!\n", cid); + else if( sd ) + sd->save_quest = false; + + return 0; +} + +int intif_quest_save(TBL_PC *sd) +{ + int len; + + if(intif->CheckForCharServer()) + return 0; + + len = sizeof(struct quest)*sd->num_quests + 8; + + WFIFOHEAD(inter_fd, len); + WFIFOW(inter_fd,0) = 0x3061; + WFIFOW(inter_fd,2) = len; + WFIFOL(inter_fd,4) = sd->status.char_id; + if( sd->num_quests ) + memcpy(WFIFOP(inter_fd,8), &sd->quest_log, sizeof(struct quest)*sd->num_quests); + WFIFOSET(inter_fd, len); + + return 0; +} + +/*========================================== + * MAIL SYSTEM + * By Zephyrus + *==========================================*/ + +/*------------------------------------------ + * Inbox Request + * flag: 0 Update Inbox | 1 OpenMail + *------------------------------------------*/ +int intif_Mail_requestinbox(int char_id, unsigned char flag) +{ + if (intif->CheckForCharServer()) + return 0; + + WFIFOHEAD(inter_fd,7); + WFIFOW(inter_fd,0) = 0x3048; + WFIFOL(inter_fd,2) = char_id; + WFIFOB(inter_fd,6) = flag; + WFIFOSET(inter_fd,7); + + return 0; +} + +int intif_parse_Mail_inboxreceived(int fd) +{ + struct map_session_data *sd; + unsigned char flag = RFIFOB(fd,8); + + sd = iMap->charid2sd(RFIFOL(fd,4)); + + if (sd == NULL) + { + ShowError("intif_parse_Mail_inboxreceived: char not found %d\n",RFIFOL(fd,4)); + return 1; + } + + if (RFIFOW(fd,2) - 9 != sizeof(struct mail_data)) + { + ShowError("intif_parse_Mail_inboxreceived: data size error %d %d\n", RFIFOW(fd,2) - 9, sizeof(struct mail_data)); + return 1; + } + + //FIXME: this operation is not safe [ultramage] + memcpy(&sd->mail.inbox, RFIFOP(fd,9), sizeof(struct mail_data)); + sd->mail.changed = false; // cache is now in sync + + if (flag) + clif->mail_refreshinbox(sd); + else if( battle_config.mail_show_status && ( battle_config.mail_show_status == 1 || sd->mail.inbox.unread ) ) + { + char output[128]; + sprintf(output, msg_txt(510), sd->mail.inbox.unchecked, sd->mail.inbox.unread + sd->mail.inbox.unchecked); + clif->disp_onlyself(sd, output, strlen(output)); + } + return 0; +} +/*------------------------------------------ + * Mail Read + *------------------------------------------*/ +int intif_Mail_read(int mail_id) +{ + if (intif->CheckForCharServer()) + return 0; + + WFIFOHEAD(inter_fd,6); + WFIFOW(inter_fd,0) = 0x3049; + WFIFOL(inter_fd,2) = mail_id; + WFIFOSET(inter_fd,6); + + return 0; +} +/*------------------------------------------ + * Get Attachment + *------------------------------------------*/ +int intif_Mail_getattach(int char_id, int mail_id) +{ + if (intif->CheckForCharServer()) + return 0; + + WFIFOHEAD(inter_fd,10); + WFIFOW(inter_fd,0) = 0x304a; + WFIFOL(inter_fd,2) = char_id; + WFIFOL(inter_fd,6) = mail_id; + WFIFOSET(inter_fd, 10); + + return 0; +} + +int intif_parse_Mail_getattach(int fd) +{ + struct map_session_data *sd; + struct item item; + int zeny = RFIFOL(fd,8); + + sd = iMap->charid2sd( RFIFOL(fd,4) ); + + if (sd == NULL) + { + ShowError("intif_parse_Mail_getattach: char not found %d\n",RFIFOL(fd,4)); + return 1; + } + + if (RFIFOW(fd,2) - 12 != sizeof(struct item)) + { + ShowError("intif_parse_Mail_getattach: data size error %d %d\n", RFIFOW(fd,2) - 16, sizeof(struct item)); + return 1; + } + + memcpy(&item, RFIFOP(fd,12), sizeof(struct item)); + + mail->getattachment(sd, zeny, &item); + return 0; +} +/*------------------------------------------ + * Delete Message + *------------------------------------------*/ +int intif_Mail_delete(int char_id, int mail_id) +{ + if (intif->CheckForCharServer()) + return 0; + + WFIFOHEAD(inter_fd,10); + WFIFOW(inter_fd,0) = 0x304b; + WFIFOL(inter_fd,2) = char_id; + WFIFOL(inter_fd,6) = mail_id; + WFIFOSET(inter_fd,10); + + return 0; +} + +int intif_parse_Mail_delete(int fd) +{ + int char_id = RFIFOL(fd,2); + int mail_id = RFIFOL(fd,6); + bool failed = RFIFOB(fd,10); + + struct map_session_data *sd = iMap->charid2sd(char_id); + if (sd == NULL) + { + ShowError("intif_parse_Mail_delete: char not found %d\n", char_id); + return 1; + } + + if (!failed) + { + int i; + ARR_FIND(0, MAIL_MAX_INBOX, i, sd->mail.inbox.msg[i].id == mail_id); + if( i < MAIL_MAX_INBOX ) + { + memset(&sd->mail.inbox.msg[i], 0, sizeof(struct mail_message)); + sd->mail.inbox.amount--; + } + + if( sd->mail.inbox.full ) + intif_Mail_requestinbox(sd->status.char_id, 1); // Free space is available for new mails + } + + clif->mail_delete(sd->fd, mail_id, failed); + return 0; +} +/*------------------------------------------ + * Return Message + *------------------------------------------*/ +int intif_Mail_return(int char_id, int mail_id) +{ + if (intif->CheckForCharServer()) + return 0; + + WFIFOHEAD(inter_fd,10); + WFIFOW(inter_fd,0) = 0x304c; + WFIFOL(inter_fd,2) = char_id; + WFIFOL(inter_fd,6) = mail_id; + WFIFOSET(inter_fd,10); + + return 0; +} + +int intif_parse_Mail_return(int fd) +{ + struct map_session_data *sd = iMap->charid2sd(RFIFOL(fd,2)); + int mail_id = RFIFOL(fd,6); + short fail = RFIFOB(fd,10); + + if( sd == NULL ) + { + ShowError("intif_parse_Mail_return: char not found %d\n",RFIFOL(fd,2)); + return 1; + } + + if( !fail ) + { + int i; + ARR_FIND(0, MAIL_MAX_INBOX, i, sd->mail.inbox.msg[i].id == mail_id); + if( i < MAIL_MAX_INBOX ) + { + memset(&sd->mail.inbox.msg[i], 0, sizeof(struct mail_message)); + sd->mail.inbox.amount--; + } + + if( sd->mail.inbox.full ) + intif_Mail_requestinbox(sd->status.char_id, 1); // Free space is available for new mails + } + + clif->mail_return(sd->fd, mail_id, fail); + return 0; +} +/*------------------------------------------ + * Send Mail + *------------------------------------------*/ +int intif_Mail_send(int account_id, struct mail_message *msg) +{ + int len = sizeof(struct mail_message) + 8; + + if (intif->CheckForCharServer()) + return 0; + + WFIFOHEAD(inter_fd,len); + WFIFOW(inter_fd,0) = 0x304d; + WFIFOW(inter_fd,2) = len; + WFIFOL(inter_fd,4) = account_id; + memcpy(WFIFOP(inter_fd,8), msg, sizeof(struct mail_message)); + WFIFOSET(inter_fd,len); + + return 1; +} + +static void intif_parse_Mail_send(int fd) +{ + struct mail_message msg; + struct map_session_data *sd; + bool fail; + + if( RFIFOW(fd,2) - 4 != sizeof(struct mail_message) ) + { + ShowError("intif_parse_Mail_send: data size error %d %d\n", RFIFOW(fd,2) - 4, sizeof(struct mail_message)); + return; + } + + memcpy(&msg, RFIFOP(fd,4), sizeof(struct mail_message)); + fail = (msg.id == 0); + + // notify sender + sd = iMap->charid2sd(msg.send_id); + if( sd != NULL ) + { + if( fail ) + mail->deliveryfail(sd, &msg); + else + { + clif->mail_send(sd->fd, false); + if( iMap->save_settings&16 ) + chrif->save(sd, 0); + } + } +} + +static void intif_parse_Mail_new(int fd) +{ + struct map_session_data *sd = iMap->charid2sd(RFIFOL(fd,2)); + int mail_id = RFIFOL(fd,6); + const char* sender_name = (char*)RFIFOP(fd,10); + const char* title = (char*)RFIFOP(fd,34); + + if( sd == NULL ) + return; + + sd->mail.changed = true; + clif->mail_new(sd->fd, mail_id, sender_name, title); +} + +/*========================================== + * AUCTION SYSTEM + * By Zephyrus + *==========================================*/ +int intif_Auction_requestlist(int char_id, short type, int price, const char* searchtext, short page) +{ + int len = NAME_LENGTH + 16; + + if( intif->CheckForCharServer() ) + return 0; + + WFIFOHEAD(inter_fd,len); + WFIFOW(inter_fd,0) = 0x3050; + WFIFOW(inter_fd,2) = len; + WFIFOL(inter_fd,4) = char_id; + WFIFOW(inter_fd,8) = type; + WFIFOL(inter_fd,10) = price; + WFIFOW(inter_fd,14) = page; + memcpy(WFIFOP(inter_fd,16), searchtext, NAME_LENGTH); + WFIFOSET(inter_fd,len); + + return 0; +} + +static void intif_parse_Auction_results(int fd) +{ + struct map_session_data *sd = iMap->charid2sd(RFIFOL(fd,4)); + short count = RFIFOW(fd,8); + short pages = RFIFOW(fd,10); + uint8* data = RFIFOP(fd,12); + + if( sd == NULL ) + return; + + clif->auction_results(sd, count, pages, data); +} + +int intif_Auction_register(struct auction_data *auction) +{ + int len = sizeof(struct auction_data) + 4; + + if( intif->CheckForCharServer() ) + return 0; + + WFIFOHEAD(inter_fd,len); + WFIFOW(inter_fd,0) = 0x3051; + WFIFOW(inter_fd,2) = len; + memcpy(WFIFOP(inter_fd,4), auction, sizeof(struct auction_data)); + WFIFOSET(inter_fd,len); + + return 1; +} + +static void intif_parse_Auction_register(int fd) +{ + struct map_session_data *sd; + struct auction_data auction; + + if( RFIFOW(fd,2) - 4 != sizeof(struct auction_data) ) + { + ShowError("intif_parse_Auction_register: data size error %d %d\n", RFIFOW(fd,2) - 4, sizeof(struct auction_data)); + return; + } + + memcpy(&auction, RFIFOP(fd,4), sizeof(struct auction_data)); + if( (sd = iMap->charid2sd(auction.seller_id)) == NULL ) + return; + + if( auction.auction_id > 0 ) + { + clif->auction_message(sd->fd, 1); // Confirmation Packet ?? + if( iMap->save_settings&32 ) + chrif->save(sd,0); + } + else + { + int zeny = auction.hours*battle_config.auction_feeperhour; + + clif->auction_message(sd->fd, 4); + pc->additem(sd, &auction.item, auction.item.amount, LOG_TYPE_AUCTION); + + pc->getzeny(sd, zeny, LOG_TYPE_AUCTION, NULL); + } +} + +int intif_Auction_cancel(int char_id, unsigned int auction_id) +{ + if( intif->CheckForCharServer() ) + return 0; + + WFIFOHEAD(inter_fd,10); + WFIFOW(inter_fd,0) = 0x3052; + WFIFOL(inter_fd,2) = char_id; + WFIFOL(inter_fd,6) = auction_id; + WFIFOSET(inter_fd,10); + + return 0; +} + +static void intif_parse_Auction_cancel(int fd) +{ + struct map_session_data *sd = iMap->charid2sd(RFIFOL(fd,2)); + int result = RFIFOB(fd,6); + + if( sd == NULL ) + return; + + switch( result ) + { + case 0: clif->auction_message(sd->fd, 2); break; + case 1: clif->auction_close(sd->fd, 2); break; + case 2: clif->auction_close(sd->fd, 1); break; + case 3: clif->auction_message(sd->fd, 3); break; + } +} + +int intif_Auction_close(int char_id, unsigned int auction_id) +{ + if( intif->CheckForCharServer() ) + return 0; + + WFIFOHEAD(inter_fd,10); + WFIFOW(inter_fd,0) = 0x3053; + WFIFOL(inter_fd,2) = char_id; + WFIFOL(inter_fd,6) = auction_id; + WFIFOSET(inter_fd,10); + + return 0; +} + +static void intif_parse_Auction_close(int fd) +{ + struct map_session_data *sd = iMap->charid2sd(RFIFOL(fd,2)); + unsigned char result = RFIFOB(fd,6); + + if( sd == NULL ) + return; + + clif->auction_close(sd->fd, result); + if( result == 0 ) + { + // FIXME: Leeching off a parse function + clif->pAuction_cancelreg(fd, sd); + intif_Auction_requestlist(sd->status.char_id, 6, 0, "", 1); + } +} + +int intif_Auction_bid(int char_id, const char* name, unsigned int auction_id, int bid) +{ + int len = 16 + NAME_LENGTH; + + if( intif->CheckForCharServer() ) + return 0; + + WFIFOHEAD(inter_fd,len); + WFIFOW(inter_fd,0) = 0x3055; + WFIFOW(inter_fd,2) = len; + WFIFOL(inter_fd,4) = char_id; + WFIFOL(inter_fd,8) = auction_id; + WFIFOL(inter_fd,12) = bid; + memcpy(WFIFOP(inter_fd,16), name, NAME_LENGTH); + WFIFOSET(inter_fd,len); + + return 0; +} + +static void intif_parse_Auction_bid(int fd) +{ + struct map_session_data *sd = iMap->charid2sd(RFIFOL(fd,2)); + int bid = RFIFOL(fd,6); + unsigned char result = RFIFOB(fd,10); + + if( sd == NULL ) + return; + + clif->auction_message(sd->fd, result); + if( bid > 0 ) { + pc->getzeny(sd, bid, LOG_TYPE_AUCTION,NULL); + } + if( result == 1 ) { // To update the list, display your buy list + clif->pAuction_cancelreg(fd, sd); + intif_Auction_requestlist(sd->status.char_id, 7, 0, "", 1); + } +} + +// Used to send 'You have won the auction' and 'You failed to won the auction' messages +static void intif_parse_Auction_message(int fd) +{ + struct map_session_data *sd = iMap->charid2sd(RFIFOL(fd,2)); + unsigned char result = RFIFOB(fd,6); + + if( sd == NULL ) + return; + + clif->auction_message(sd->fd, result); +} + +/*========================================== + * Mercenary's System + *------------------------------------------*/ +int intif_mercenary_create(struct s_mercenary *merc) +{ + int size = sizeof(struct s_mercenary) + 4; + + if( intif->CheckForCharServer() ) + return 0; + + WFIFOHEAD(inter_fd,size); + WFIFOW(inter_fd,0) = 0x3070; + WFIFOW(inter_fd,2) = size; + memcpy(WFIFOP(inter_fd,4), merc, sizeof(struct s_mercenary)); + WFIFOSET(inter_fd,size); + return 0; +} + +int intif_parse_mercenary_received(int fd) +{ + int len = RFIFOW(fd,2) - 5; + if( sizeof(struct s_mercenary) != len ) + { + if( battle_config.etc_log ) + ShowError("intif: create mercenary data size error %d != %d\n", sizeof(struct s_mercenary), len); + return 0; + } + + mercenary->merc_data_received((struct s_mercenary*)RFIFOP(fd,5), RFIFOB(fd,4)); + return 0; +} + +int intif_mercenary_request(int merc_id, int char_id) +{ + if (intif->CheckForCharServer()) + return 0; + + WFIFOHEAD(inter_fd,10); + WFIFOW(inter_fd,0) = 0x3071; + WFIFOL(inter_fd,2) = merc_id; + WFIFOL(inter_fd,6) = char_id; + WFIFOSET(inter_fd,10); + return 0; +} + +int intif_mercenary_delete(int merc_id) +{ + if (intif->CheckForCharServer()) + return 0; + + WFIFOHEAD(inter_fd,6); + WFIFOW(inter_fd,0) = 0x3072; + WFIFOL(inter_fd,2) = merc_id; + WFIFOSET(inter_fd,6); + return 0; +} + +int intif_parse_mercenary_deleted(int fd) +{ + if( RFIFOB(fd,2) != 1 ) + ShowError("Mercenary data delete failure\n"); + + return 0; +} + +int intif_mercenary_save(struct s_mercenary *merc) +{ + int size = sizeof(struct s_mercenary) + 4; + + if( intif->CheckForCharServer() ) + return 0; + + WFIFOHEAD(inter_fd,size); + WFIFOW(inter_fd,0) = 0x3073; + WFIFOW(inter_fd,2) = size; + memcpy(WFIFOP(inter_fd,4), merc, sizeof(struct s_mercenary)); + WFIFOSET(inter_fd,size); + return 0; +} + +int intif_parse_mercenary_saved(int fd) +{ + if( RFIFOB(fd,2) != 1 ) + ShowError("Mercenary data save failure\n"); + + return 0; +} + +/*========================================== + * Elemental's System + *------------------------------------------*/ +int intif_elemental_create(struct s_elemental *ele) +{ + int size = sizeof(struct s_elemental) + 4; + + if( intif->CheckForCharServer() ) + return 0; + + WFIFOHEAD(inter_fd,size); + WFIFOW(inter_fd,0) = 0x307c; + WFIFOW(inter_fd,2) = size; + memcpy(WFIFOP(inter_fd,4), ele, sizeof(struct s_elemental)); + WFIFOSET(inter_fd,size); + return 0; +} + +int intif_parse_elemental_received(int fd) +{ + int len = RFIFOW(fd,2) - 5; + if( sizeof(struct s_elemental) != len ) + { + if( battle_config.etc_log ) + ShowError("intif: create elemental data size error %d != %d\n", sizeof(struct s_elemental), len); + return 0; + } + + elemental->data_received((struct s_elemental*)RFIFOP(fd,5), RFIFOB(fd,4)); + return 0; +} + +int intif_elemental_request(int ele_id, int char_id) +{ + if (intif->CheckForCharServer()) + return 0; + + WFIFOHEAD(inter_fd,10); + WFIFOW(inter_fd,0) = 0x307d; + WFIFOL(inter_fd,2) = ele_id; + WFIFOL(inter_fd,6) = char_id; + WFIFOSET(inter_fd,10); + return 0; +} + +int intif_elemental_delete(int ele_id) +{ + if (intif->CheckForCharServer()) + return 0; + + WFIFOHEAD(inter_fd,6); + WFIFOW(inter_fd,0) = 0x307e; + WFIFOL(inter_fd,2) = ele_id; + WFIFOSET(inter_fd,6); + return 0; +} + +int intif_parse_elemental_deleted(int fd) +{ + if( RFIFOB(fd,2) != 1 ) + ShowError("Elemental data delete failure\n"); + + return 0; +} + +int intif_elemental_save(struct s_elemental *ele) +{ + int size = sizeof(struct s_elemental) + 4; + + if( intif->CheckForCharServer() ) + return 0; + + WFIFOHEAD(inter_fd,size); + WFIFOW(inter_fd,0) = 0x307f; + WFIFOW(inter_fd,2) = size; + memcpy(WFIFOP(inter_fd,4), ele, sizeof(struct s_elemental)); + WFIFOSET(inter_fd,size); + return 0; +} + +int intif_parse_elemental_saved(int fd) +{ + if( RFIFOB(fd,2) != 1 ) + ShowError("Elemental data save failure\n"); + + return 0; +} + +void intif_request_accinfo( int u_fd, int aid, int group_lv, char* query ) { + + + WFIFOHEAD(inter_fd,2 + 4 + 4 + 4 + NAME_LENGTH); + + WFIFOW(inter_fd,0) = 0x3007; + WFIFOL(inter_fd,2) = u_fd; + WFIFOL(inter_fd,6) = aid; + WFIFOL(inter_fd,10) = group_lv; + safestrncpy((char *)WFIFOP(inter_fd,14), query, NAME_LENGTH); + + WFIFOSET(inter_fd,2 + 4 + 4 + 4 + NAME_LENGTH); + + return; +} + +void intif_parse_MessageToFD(int fd) { + int u_fd = RFIFOL(fd,4); + + if( session[u_fd] && session[u_fd]->session_data ) { + int aid = RFIFOL(fd,8); + struct map_session_data * sd = session[u_fd]->session_data; + /* matching e.g. previous fd owner didn't dc during request or is still the same */ + if( sd->bl.id == aid ) { + char msg[512]; + safestrncpy(msg, (char*)RFIFOP(fd,12), RFIFOW(fd,2) - 12); + clif->message(u_fd,msg); + } + + } + + return; +} + +//----------------------------------------------------------------- +// Communication from the inter server +// Return a 0 (false) if there were any errors. +// 1, 2 if there are not enough to return the length of the packet if the packet processing +int intif_parse(int fd) +{ + int packet_len, cmd; + cmd = RFIFOW(fd,0); + // Verify ID of the packet + if(cmd<0x3800 || cmd>=0x3800+(sizeof(packet_len_table)/sizeof(packet_len_table[0])) || + packet_len_table[cmd-0x3800]==0){ + return 0; + } + // Check the length of the packet + packet_len = packet_len_table[cmd-0x3800]; + if(packet_len==-1){ + if(RFIFOREST(fd)<4) + return 2; + packet_len = RFIFOW(fd,2); + } + if((int)RFIFOREST(fd)broadcast(NULL, (char *) RFIFOP(fd,16), packet_len-16, 0, ALL_CLIENT); + else //Color announce. + clif->broadcast2(NULL, (char *) RFIFOP(fd,16), packet_len-16, RFIFOL(fd,4), RFIFOW(fd,8), RFIFOW(fd,10), RFIFOW(fd,12), RFIFOW(fd,14), ALL_CLIENT); + break; + case 0x3801: intif_parse_WisMessage(fd); break; + case 0x3802: intif_parse_WisEnd(fd); break; + case 0x3803: mapif_parse_WisToGM(fd); break; + case 0x3804: intif_parse_Registers(fd); break; + case 0x3806: intif_parse_ChangeNameOk(fd); break; + case 0x3807: intif_parse_MessageToFD(fd); break; + case 0x3818: intif_parse_LoadGuildStorage(fd); break; + case 0x3819: intif_parse_SaveGuildStorage(fd); break; + case 0x3820: intif_parse_PartyCreated(fd); break; + case 0x3821: intif_parse_PartyInfo(fd); break; + case 0x3822: intif_parse_PartyMemberAdded(fd); break; + case 0x3823: intif_parse_PartyOptionChanged(fd); break; + case 0x3824: intif_parse_PartyMemberWithdraw(fd); break; + case 0x3825: intif_parse_PartyMove(fd); break; + case 0x3826: intif_parse_PartyBroken(fd); break; + case 0x3827: intif_parse_PartyMessage(fd); break; + case 0x3830: intif_parse_GuildCreated(fd); break; + case 0x3831: intif_parse_GuildInfo(fd); break; + case 0x3832: intif_parse_GuildMemberAdded(fd); break; + case 0x3834: intif_parse_GuildMemberWithdraw(fd); break; + case 0x3835: intif_parse_GuildMemberInfoShort(fd); break; + case 0x3836: intif_parse_GuildBroken(fd); break; + case 0x3837: intif_parse_GuildMessage(fd); break; + case 0x3839: intif_parse_GuildBasicInfoChanged(fd); break; + case 0x383a: intif_parse_GuildMemberInfoChanged(fd); break; + case 0x383b: intif_parse_GuildPosition(fd); break; + case 0x383c: intif_parse_GuildSkillUp(fd); break; + case 0x383d: intif_parse_GuildAlliance(fd); break; + case 0x383e: intif_parse_GuildNotice(fd); break; + case 0x383f: intif_parse_GuildEmblem(fd); break; + case 0x3840: intif_parse_GuildCastleDataLoad(fd); break; + case 0x3843: intif_parse_GuildMasterChanged(fd); break; + + //Quest system + case 0x3860: intif_parse_questlog(fd); break; + case 0x3861: intif_parse_questsave(fd); break; + +// Mail System + case 0x3848: intif_parse_Mail_inboxreceived(fd); break; + case 0x3849: intif_parse_Mail_new(fd); break; + case 0x384a: intif_parse_Mail_getattach(fd); break; + case 0x384b: intif_parse_Mail_delete(fd); break; + case 0x384c: intif_parse_Mail_return(fd); break; + case 0x384d: intif_parse_Mail_send(fd); break; +// Auction System + case 0x3850: intif_parse_Auction_results(fd); break; + case 0x3851: intif_parse_Auction_register(fd); break; + case 0x3852: intif_parse_Auction_cancel(fd); break; + case 0x3853: intif_parse_Auction_close(fd); break; + case 0x3854: intif_parse_Auction_message(fd); break; + case 0x3855: intif_parse_Auction_bid(fd); break; + +// Mercenary System + case 0x3870: intif_parse_mercenary_received(fd); break; + case 0x3871: intif_parse_mercenary_deleted(fd); break; + case 0x3872: intif_parse_mercenary_saved(fd); break; +// Elemental System + case 0x387c: intif_parse_elemental_received(fd); break; + case 0x387d: intif_parse_elemental_deleted(fd); break; + case 0x387e: intif_parse_elemental_saved(fd); break; + + case 0x3880: intif_parse_CreatePet(fd); break; + case 0x3881: intif_parse_RecvPetData(fd); break; + case 0x3882: intif_parse_SavePetOk(fd); break; + case 0x3883: intif_parse_DeletePetOk(fd); break; + case 0x3890: intif_parse_CreateHomunculus(fd); break; + case 0x3891: intif_parse_RecvHomunculusData(fd); break; + case 0x3892: intif_parse_SaveHomunculusOk(fd); break; + case 0x3893: intif_parse_DeleteHomunculusOk(fd); break; + default: + ShowError("intif_parse : unknown packet %d %x\n",fd,RFIFOW(fd,0)); + return 0; + } + // Skip packet + RFIFOSKIP(fd,packet_len); + return 1; +} + +/*===================================== +* Default Functions : intif.h +* Generated by HerculesInterfaceMaker +* created by Susu +*-------------------------------------*/ +void intif_defaults(void) { + intif = &intif_s; + + /* funcs */ + + intif->parse = intif_parse; + + intif->broadcast = intif_broadcast; + intif->broadcast2 = intif_broadcast2; + intif->main_message = intif_main_message; + + intif->wis_message = intif_wis_message; + intif->wis_message_to_gm = intif_wis_message_to_gm; + + intif->saveregistry = intif_saveregistry; + intif->request_registry = intif_request_registry; + + intif->request_guild_storage = intif_request_guild_storage; + intif->send_guild_storage = intif_send_guild_storage; + + intif->create_party = intif_create_party; + intif->request_partyinfo = intif_request_partyinfo; + + intif->party_addmember = intif_party_addmember; + intif->party_changeoption = intif_party_changeoption; + intif->party_leave = intif_party_leave; + intif->party_changemap = intif_party_changemap; + intif->break_party = intif_break_party; + intif->party_message = intif_party_message; + intif->party_leaderchange = intif_party_leaderchange; + + intif->guild_create = intif_guild_create; + intif->guild_request_info = intif_guild_request_info; + intif->guild_addmember = intif_guild_addmember; + intif->guild_leave = intif_guild_leave; + intif->guild_memberinfoshort = intif_guild_memberinfoshort; + intif->guild_break = intif_guild_break; + intif->guild_message = intif_guild_message; + intif->guild_change_gm = intif_guild_change_gm; + intif->guild_change_basicinfo = intif_guild_change_basicinfo; + intif->guild_change_memberinfo = intif_guild_change_memberinfo; + intif->guild_position = intif_guild_position; + intif->guild_skillup = intif_guild_skillup; + intif->guild_alliance = intif_guild_alliance; + intif->guild_notice = intif_guild_notice; + intif->guild_emblem = intif_guild_emblem; + intif->guild_castle_dataload = intif_guild_castle_dataload; + intif->guild_castle_datasave = intif_guild_castle_datasave; + intif->request_petdata = intif_request_petdata; + intif->save_petdata = intif_save_petdata; + intif->delete_petdata = intif_delete_petdata; + intif->rename = intif_rename; + intif->homunculus_create = intif_homunculus_create; + intif->homunculus_requestload = intif_homunculus_requestload; + intif->homunculus_requestsave = intif_homunculus_requestsave; + intif->homunculus_requestdelete = intif_homunculus_requestdelete; + /******QUEST SYTEM*******/ + intif->request_questlog = intif_request_questlog; + intif->quest_save = intif_quest_save; + // MERCENARY SYSTEM + intif->mercenary_create = intif_mercenary_create; + intif->mercenary_request = intif_mercenary_request; + intif->mercenary_delete = intif_mercenary_delete; + intif->mercenary_save = intif_mercenary_save; + // MAIL SYSTEM + intif->Mail_requestinbox = intif_Mail_requestinbox; + intif->Mail_read = intif_Mail_read; + intif->Mail_getattach = intif_Mail_getattach; + intif->Mail_delete = intif_Mail_delete; + intif->Mail_return = intif_Mail_return; + intif->Mail_send = intif_Mail_send; + // AUCTION SYSTEM + intif->Auction_requestlist = intif_Auction_requestlist; + intif->Auction_register = intif_Auction_register; + intif->Auction_cancel = intif_Auction_cancel; + intif->Auction_close = intif_Auction_close; + intif->Auction_bid = intif_Auction_bid; + // ELEMENTAL SYSTEM + intif->elemental_create = intif_elemental_create; + intif->elemental_request = intif_elemental_request; + intif->elemental_delete = intif_elemental_delete; + intif->elemental_save = intif_elemental_save; + /* @accinfo */ + intif->request_accinfo = intif_request_accinfo; + + intif->CheckForCharServer = CheckForCharServer; +} diff --git a/src/map/map.c b/src/map/map.c index 5db5431a8..88e254d03 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -5159,6 +5159,7 @@ void map_hp_symbols(void) { HPM->share(iDuel,"iDuel"); HPM->share(elemental,"elemental"); HPM->share(intif,"intif"); + HPM->share(mercenary,"mercenary"); /* partial */ @@ -5201,6 +5202,7 @@ void map_load_defaults(void) { iDuel_defaults(); elemental_defaults(); intif_defaults(); + mercenary_defaults(); } int do_init(int argc, char *argv[]) { @@ -5396,7 +5398,7 @@ int do_init(int argc, char *argv[]) storage->init(); do_init_pet(); homun->init(); - do_init_mercenary(); + mercenary->do_init_mercenary(); elemental->do_init_elemental(); do_init_quest(); do_init_npc(); diff --git a/src/map/mercenary.c b/src/map/mercenary.c index 72ed7628a..d6d5ce081 100644 --- a/src/map/mercenary.c +++ b/src/map/mercenary.c @@ -1,511 +1,551 @@ -// Copyright (c) Hercules Dev Team, licensed under GNU GPL. -// See the LICENSE file -// Portions Copyright (c) Athena Dev Teams - -#include "../common/cbasetypes.h" -#include "../common/malloc.h" -#include "../common/socket.h" -#include "../common/timer.h" -#include "../common/nullpo.h" -#include "../common/mmo.h" -#include "../common/random.h" -#include "../common/showmsg.h" -#include "../common/strlib.h" -#include "../common/utils.h" - -#include "log.h" -#include "clif.h" -#include "chrif.h" -#include "intif.h" -#include "itemdb.h" -#include "map.h" -#include "pc.h" -#include "status.h" -#include "skill.h" -#include "mob.h" -#include "pet.h" -#include "battle.h" -#include "party.h" -#include "guild.h" -#include "atcommand.h" -#include "script.h" -#include "npc.h" -#include "trade.h" -#include "unit.h" -#include "mercenary.h" - -#include -#include -#include -#include - -struct s_mercenary_db mercenary_db[MAX_MERCENARY_CLASS]; // Mercenary Database - -int merc_search_index(int class_) -{ - int i; - ARR_FIND(0, MAX_MERCENARY_CLASS, i, mercenary_db[i].class_ == class_); - return (i == MAX_MERCENARY_CLASS)?-1:i; -} - -bool merc_class(int class_) -{ - return (bool)(merc_search_index(class_) > -1); -} - -struct view_data * merc_get_viewdata(int class_) -{ - int i = merc_search_index(class_); - if( i < 0 ) - return 0; - - return &mercenary_db[i].vd; -} - -int merc_create(struct map_session_data *sd, int class_, unsigned int lifetime) -{ - struct s_mercenary merc; - struct s_mercenary_db *db; - int i; - nullpo_retr(0,sd); - - if( (i = merc_search_index(class_)) < 0 ) - return 0; - - db = &mercenary_db[i]; - memset(&merc,0,sizeof(struct s_mercenary)); - - merc.char_id = sd->status.char_id; - merc.class_ = class_; - merc.hp = db->status.max_hp; - merc.sp = db->status.max_sp; - merc.life_time = lifetime; - - // Request Char Server to create this mercenary - intif->mercenary_create(&merc); - - return 1; -} - -int mercenary_get_lifetime(struct mercenary_data *md) -{ - const struct TimerData * td; - if( md == NULL || md->contract_timer == INVALID_TIMER ) - return 0; - - td = iTimer->get_timer(md->contract_timer); - return (td != NULL) ? DIFF_TICK(td->tick, iTimer->gettick()) : 0; -} - -int mercenary_get_guild(struct mercenary_data *md) -{ - int class_; - - if( md == NULL || md->db == NULL ) - return -1; - - class_ = md->db->class_; - - if( class_ >= 6017 && class_ <= 6026 ) - return ARCH_MERC_GUILD; - if( class_ >= 6027 && class_ <= 6036 ) - return SPEAR_MERC_GUILD; - if( class_ >= 6037 && class_ <= 6046 ) - return SWORD_MERC_GUILD; - - return -1; -} - -int mercenary_get_faith(struct mercenary_data *md) -{ - struct map_session_data *sd; - int class_; - - if( md == NULL || md->db == NULL || (sd = md->master) == NULL ) - return 0; - - class_ = md->db->class_; - - if( class_ >= 6017 && class_ <= 6026 ) - return sd->status.arch_faith; - if( class_ >= 6027 && class_ <= 6036 ) - return sd->status.spear_faith; - if( class_ >= 6037 && class_ <= 6046 ) - return sd->status.sword_faith; - - return 0; -} - -int mercenary_set_faith(struct mercenary_data *md, int value) -{ - struct map_session_data *sd; - int class_, *faith; - - if( md == NULL || md->db == NULL || (sd = md->master) == NULL ) - return 0; - - class_ = md->db->class_; - - if( class_ >= 6017 && class_ <= 6026 ) - faith = &sd->status.arch_faith; - else if( class_ >= 6027 && class_ <= 6036 ) - faith = &sd->status.spear_faith; - else if( class_ >= 6037 && class_ <= 6046 ) - faith = &sd->status.sword_faith; - else - return 0; - - *faith += value; - *faith = cap_value(*faith, 0, SHRT_MAX); - clif->mercenary_updatestatus(sd, SP_MERCFAITH); - - return 0; -} - -int mercenary_get_calls(struct mercenary_data *md) -{ - struct map_session_data *sd; - int class_; - - if( md == NULL || md->db == NULL || (sd = md->master) == NULL ) - return 0; - - class_ = md->db->class_; - - if( class_ >= 6017 && class_ <= 6026 ) - return sd->status.arch_calls; - if( class_ >= 6027 && class_ <= 6036 ) - return sd->status.spear_calls; - if( class_ >= 6037 && class_ <= 6046 ) - return sd->status.sword_calls; - - return 0; -} - -int mercenary_set_calls(struct mercenary_data *md, int value) -{ - struct map_session_data *sd; - int class_, *calls; - - if( md == NULL || md->db == NULL || (sd = md->master) == NULL ) - return 0; - - class_ = md->db->class_; - - if( class_ >= 6017 && class_ <= 6026 ) - calls = &sd->status.arch_calls; - else if( class_ >= 6027 && class_ <= 6036 ) - calls = &sd->status.spear_calls; - else if( class_ >= 6037 && class_ <= 6046 ) - calls = &sd->status.sword_calls; - else - return 0; - - *calls += value; - *calls = cap_value(*calls, 0, INT_MAX); - - return 0; -} - -int mercenary_save(struct mercenary_data *md) -{ - md->mercenary.hp = md->battle_status.hp; - md->mercenary.sp = md->battle_status.sp; - md->mercenary.life_time = mercenary_get_lifetime(md); - - intif->mercenary_save(&md->mercenary); - return 1; -} - -static int merc_contract_end(int tid, unsigned int tick, int id, intptr_t data) -{ - struct map_session_data *sd; - struct mercenary_data *md; - - if( (sd = iMap->id2sd(id)) == NULL ) - return 1; - if( (md = sd->md) == NULL ) - return 1; - - if( md->contract_timer != tid ) - { - ShowError("merc_contract_end %d != %d.\n", md->contract_timer, tid); - return 0; - } - - md->contract_timer = INVALID_TIMER; - merc_delete(md, 0); // Mercenary soldier's duty hour is over. - - return 0; -} - -int merc_delete(struct mercenary_data *md, int reply) -{ - struct map_session_data *sd = md->master; - md->mercenary.life_time = 0; - - merc_contract_stop(md); - - if( !sd ) - return unit_free(&md->bl, CLR_OUTSIGHT); - - if( md->devotion_flag ) - { - md->devotion_flag = 0; - status_change_end(&sd->bl, SC_DEVOTION, INVALID_TIMER); - } - - switch( reply ) - { - case 0: mercenary_set_faith(md, 1); break; // +1 Loyalty on Contract ends. - case 1: mercenary_set_faith(md, -1); break; // -1 Loyalty on Mercenary killed - } - - clif->mercenary_message(sd, reply); - return unit_remove_map(&md->bl, CLR_OUTSIGHT); -} - -void merc_contract_stop(struct mercenary_data *md) -{ - nullpo_retv(md); - if( md->contract_timer != INVALID_TIMER ) - iTimer->delete_timer(md->contract_timer, merc_contract_end); - md->contract_timer = INVALID_TIMER; -} - -void merc_contract_init(struct mercenary_data *md) -{ - if( md->contract_timer == INVALID_TIMER ) - md->contract_timer = iTimer->add_timer(iTimer->gettick() + md->mercenary.life_time, merc_contract_end, md->master->bl.id, 0); - - md->regen.state.block = 0; -} - -int merc_data_received(struct s_mercenary *merc, bool flag) -{ - struct map_session_data *sd; - struct mercenary_data *md; - struct s_mercenary_db *db; - int i = merc_search_index(merc->class_); - - if( (sd = iMap->charid2sd(merc->char_id)) == NULL ) - return 0; - if( !flag || i < 0 ) - { // Not created - loaded - DB info - sd->status.mer_id = 0; - return 0; - } - - db = &mercenary_db[i]; - if( !sd->md ) - { - sd->md = md = (struct mercenary_data*)aCalloc(1,sizeof(struct mercenary_data)); - md->bl.type = BL_MER; - md->bl.id = npc_get_new_npc_id(); - md->devotion_flag = 0; - - md->master = sd; - md->db = db; - memcpy(&md->mercenary, merc, sizeof(struct s_mercenary)); - iStatus->set_viewdata(&md->bl, md->mercenary.class_); - iStatus->change_init(&md->bl); - unit_dataset(&md->bl); - md->ud.dir = sd->ud.dir; - - md->bl.m = sd->bl.m; - md->bl.x = sd->bl.x; - md->bl.y = sd->bl.y; - unit_calc_pos(&md->bl, sd->bl.x, sd->bl.y, sd->ud.dir); - md->bl.x = md->ud.to_x; - md->bl.y = md->ud.to_y; - - iMap->addiddb(&md->bl); - status_calc_mercenary(md,1); - md->contract_timer = INVALID_TIMER; - merc_contract_init(md); - } - else - { - memcpy(&sd->md->mercenary, merc, sizeof(struct s_mercenary)); - md = sd->md; - } - - if( sd->status.mer_id == 0 ) - mercenary_set_calls(md, 1); - sd->status.mer_id = merc->mercenary_id; - - if( md && md->bl.prev == NULL && sd->bl.prev != NULL ) - { - iMap->addblock(&md->bl); - clif->spawn(&md->bl); - clif->mercenary_info(sd); - clif->mercenary_skillblock(sd); - } - - return 1; -} - -void mercenary_heal(struct mercenary_data *md, int hp, int sp) -{ - if( hp ) - clif->mercenary_updatestatus(md->master, SP_HP); - if( sp ) - clif->mercenary_updatestatus(md->master, SP_SP); -} - -int mercenary_dead(struct mercenary_data *md) -{ - merc_delete(md, 1); - return 0; -} - -int mercenary_killbonus(struct mercenary_data *md) -{ - const enum sc_type scs[] = { SC_MER_FLEE, SC_MER_ATK, SC_MER_HP, SC_MER_SP, SC_MER_HIT }; - int index = rnd() % ARRAYLENGTH(scs); - - sc_start(&md->bl, scs[index], 100, rnd() % 5, 600000); - return 0; -} - -int mercenary_kills(struct mercenary_data *md) -{ - md->mercenary.kill_count++; - md->mercenary.kill_count = cap_value(md->mercenary.kill_count, 0, INT_MAX); - - if( (md->mercenary.kill_count % 50) == 0 ) - { - mercenary_set_faith(md, 1); - mercenary_killbonus(md); - } - - if( md->master ) - clif->mercenary_updatestatus(md->master, SP_MERCKILLS); - - return 0; -} - -int mercenary_checkskill(struct mercenary_data *md, uint16 skill_id) -{ - int i = skill_id - MC_SKILLBASE; - - if( !md || !md->db ) - return 0; - if( md->db->skill[i].id == skill_id ) - return md->db->skill[i].lv; - - return 0; -} - -static bool read_mercenarydb_sub(char* str[], int columns, int current) -{ - int ele; - struct s_mercenary_db *db; - struct status_data *status; - - db = &mercenary_db[current]; - db->class_ = atoi(str[0]); - safestrncpy(db->sprite, str[1], NAME_LENGTH); - safestrncpy(db->name, str[2], NAME_LENGTH); - db->lv = atoi(str[3]); - - status = &db->status; - db->vd.class_ = db->class_; - - status->max_hp = atoi(str[4]); - status->max_sp = atoi(str[5]); - status->rhw.range = atoi(str[6]); - status->rhw.atk = atoi(str[7]); - status->rhw.atk2 = status->rhw.atk + atoi(str[8]); - status->def = atoi(str[9]); - status->mdef = atoi(str[10]); - status->str = atoi(str[11]); - status->agi = atoi(str[12]); - status->vit = atoi(str[13]); - status->int_ = atoi(str[14]); - status->dex = atoi(str[15]); - status->luk = atoi(str[16]); - db->range2 = atoi(str[17]); - db->range3 = atoi(str[18]); - status->size = atoi(str[19]); - status->race = atoi(str[20]); - - ele = atoi(str[21]); - status->def_ele = ele%10; - status->ele_lv = ele/20; - if( status->def_ele >= ELE_MAX ) - { - ShowWarning("Mercenary %d has invalid element type %d (max element is %d)\n", db->class_, status->def_ele, ELE_MAX - 1); - status->def_ele = ELE_NEUTRAL; - } - if( status->ele_lv < 1 || status->ele_lv > 4 ) - { - ShowWarning("Mercenary %d has invalid element level %d (max is 4)\n", db->class_, status->ele_lv); - status->ele_lv = 1; - } - - status->aspd_rate = 1000; - status->speed = atoi(str[22]); - status->adelay = atoi(str[23]); - status->amotion = atoi(str[24]); - status->dmotion = atoi(str[25]); - - return true; -} - -int read_mercenarydb(void) -{ - memset(mercenary_db,0,sizeof(mercenary_db)); - sv->readdb(iMap->db_path, "mercenary_db.txt", ',', 26, 26, MAX_MERCENARY_CLASS, &read_mercenarydb_sub); - - return 0; -} - -static bool read_mercenary_skilldb_sub(char* str[], int columns, int current) -{// ,, - struct s_mercenary_db *db; - int i, class_; - uint16 skill_id, skill_lv; - - class_ = atoi(str[0]); - ARR_FIND(0, MAX_MERCENARY_CLASS, i, class_ == mercenary_db[i].class_); - if( i == MAX_MERCENARY_CLASS ) - { - ShowError("read_mercenary_skilldb : Class %d not found in mercenary_db for skill entry.\n", class_); - return false; - } - - skill_id = atoi(str[1]); - if( skill_id < MC_SKILLBASE || skill_id >= MC_SKILLBASE + MAX_MERCSKILL ) - { - ShowError("read_mercenary_skilldb : Skill %d out of range.\n", skill_id); - return false; - } - - db = &mercenary_db[i]; - skill_lv = atoi(str[2]); - - i = skill_id - MC_SKILLBASE; - db->skill[i].id = skill_id; - db->skill[i].lv = skill_lv; - - return true; -} - -int read_mercenary_skilldb(void) -{ - sv->readdb(iMap->db_path, "mercenary_skill_db.txt", ',', 3, 3, -1, &read_mercenary_skilldb_sub); - - return 0; -} - -int do_init_mercenary(void) -{ - read_mercenarydb(); - read_mercenary_skilldb(); - - //add_timer_func_list(mercenary_contract, "mercenary_contract"); - return 0; -} - -int do_final_mercenary(void); +// Copyright (c) Hercules Dev Team, licensed under GNU GPL. +// See the LICENSE file +// Portions Copyright (c) Athena Dev Teams + +#include "../common/cbasetypes.h" +#include "../common/malloc.h" +#include "../common/socket.h" +#include "../common/timer.h" +#include "../common/nullpo.h" +#include "../common/mmo.h" +#include "../common/random.h" +#include "../common/showmsg.h" +#include "../common/strlib.h" +#include "../common/utils.h" + +#include "log.h" +#include "clif.h" +#include "chrif.h" +#include "intif.h" +#include "itemdb.h" +#include "map.h" +#include "pc.h" +#include "status.h" +#include "skill.h" +#include "mob.h" +#include "pet.h" +#include "battle.h" +#include "party.h" +#include "guild.h" +#include "atcommand.h" +#include "script.h" +#include "npc.h" +#include "trade.h" +#include "unit.h" +#include "mercenary.h" + +#include +#include +#include +#include + +struct s_mercenary_db mercenary_db[MAX_MERCENARY_CLASS]; // Mercenary Database + +int merc_search_index(int class_) +{ + int i; + ARR_FIND(0, MAX_MERCENARY_CLASS, i, mercenary_db[i].class_ == class_); + return (i == MAX_MERCENARY_CLASS)?-1:i; +} + +bool merc_class(int class_) +{ + return (bool)(merc_search_index(class_) > -1); +} + +struct view_data * merc_get_viewdata(int class_) +{ + int i = merc_search_index(class_); + if( i < 0 ) + return 0; + + return &mercenary_db[i].vd; +} + +int merc_create(struct map_session_data *sd, int class_, unsigned int lifetime) +{ + struct s_mercenary merc; + struct s_mercenary_db *db; + int i; + nullpo_retr(0,sd); + + if( (i = merc_search_index(class_)) < 0 ) + return 0; + + db = &mercenary_db[i]; + memset(&merc,0,sizeof(struct s_mercenary)); + + merc.char_id = sd->status.char_id; + merc.class_ = class_; + merc.hp = db->status.max_hp; + merc.sp = db->status.max_sp; + merc.life_time = lifetime; + + // Request Char Server to create this mercenary + intif->mercenary_create(&merc); + + return 1; +} + +int mercenary_get_lifetime(struct mercenary_data *md) +{ + const struct TimerData * td; + if( md == NULL || md->contract_timer == INVALID_TIMER ) + return 0; + + td = iTimer->get_timer(md->contract_timer); + return (td != NULL) ? DIFF_TICK(td->tick, iTimer->gettick()) : 0; +} + +int mercenary_get_guild(struct mercenary_data *md) +{ + int class_; + + if( md == NULL || md->db == NULL ) + return -1; + + class_ = md->db->class_; + + if( class_ >= 6017 && class_ <= 6026 ) + return ARCH_MERC_GUILD; + if( class_ >= 6027 && class_ <= 6036 ) + return SPEAR_MERC_GUILD; + if( class_ >= 6037 && class_ <= 6046 ) + return SWORD_MERC_GUILD; + + return -1; +} + +int mercenary_get_faith(struct mercenary_data *md) +{ + struct map_session_data *sd; + int class_; + + if( md == NULL || md->db == NULL || (sd = md->master) == NULL ) + return 0; + + class_ = md->db->class_; + + if( class_ >= 6017 && class_ <= 6026 ) + return sd->status.arch_faith; + if( class_ >= 6027 && class_ <= 6036 ) + return sd->status.spear_faith; + if( class_ >= 6037 && class_ <= 6046 ) + return sd->status.sword_faith; + + return 0; +} + +int mercenary_set_faith(struct mercenary_data *md, int value) +{ + struct map_session_data *sd; + int class_, *faith; + + if( md == NULL || md->db == NULL || (sd = md->master) == NULL ) + return 0; + + class_ = md->db->class_; + + if( class_ >= 6017 && class_ <= 6026 ) + faith = &sd->status.arch_faith; + else if( class_ >= 6027 && class_ <= 6036 ) + faith = &sd->status.spear_faith; + else if( class_ >= 6037 && class_ <= 6046 ) + faith = &sd->status.sword_faith; + else + return 0; + + *faith += value; + *faith = cap_value(*faith, 0, SHRT_MAX); + clif->mercenary_updatestatus(sd, SP_MERCFAITH); + + return 0; +} + +int mercenary_get_calls(struct mercenary_data *md) +{ + struct map_session_data *sd; + int class_; + + if( md == NULL || md->db == NULL || (sd = md->master) == NULL ) + return 0; + + class_ = md->db->class_; + + if( class_ >= 6017 && class_ <= 6026 ) + return sd->status.arch_calls; + if( class_ >= 6027 && class_ <= 6036 ) + return sd->status.spear_calls; + if( class_ >= 6037 && class_ <= 6046 ) + return sd->status.sword_calls; + + return 0; +} + +int mercenary_set_calls(struct mercenary_data *md, int value) +{ + struct map_session_data *sd; + int class_, *calls; + + if( md == NULL || md->db == NULL || (sd = md->master) == NULL ) + return 0; + + class_ = md->db->class_; + + if( class_ >= 6017 && class_ <= 6026 ) + calls = &sd->status.arch_calls; + else if( class_ >= 6027 && class_ <= 6036 ) + calls = &sd->status.spear_calls; + else if( class_ >= 6037 && class_ <= 6046 ) + calls = &sd->status.sword_calls; + else + return 0; + + *calls += value; + *calls = cap_value(*calls, 0, INT_MAX); + + return 0; +} + +int mercenary_save(struct mercenary_data *md) +{ + md->mercenary.hp = md->battle_status.hp; + md->mercenary.sp = md->battle_status.sp; + md->mercenary.life_time = mercenary->get_lifetime(md); + + intif->mercenary_save(&md->mercenary); + return 1; +} + +static int merc_contract_end(int tid, unsigned int tick, int id, intptr_t data) +{ + struct map_session_data *sd; + struct mercenary_data *md; + + if( (sd = iMap->id2sd(id)) == NULL ) + return 1; + if( (md = sd->md) == NULL ) + return 1; + + if( md->contract_timer != tid ) + { + ShowError("merc_contract_end %d != %d.\n", md->contract_timer, tid); + return 0; + } + + md->contract_timer = INVALID_TIMER; + mercenary->merc_delete(md, 0); // Mercenary soldier's duty hour is over. + + return 0; +} + +int merc_delete(struct mercenary_data *md, int reply) +{ + struct map_session_data *sd = md->master; + md->mercenary.life_time = 0; + + mercenary->merc_contract_stop(md); + + if( !sd ) + return unit_free(&md->bl, CLR_OUTSIGHT); + + if( md->devotion_flag ) + { + md->devotion_flag = 0; + status_change_end(&sd->bl, SC_DEVOTION, INVALID_TIMER); + } + + switch( reply ) + { + case 0: mercenary->set_faith(md, 1); break; // +1 Loyalty on Contract ends. + case 1: mercenary->set_faith(md, -1); break; // -1 Loyalty on Mercenary killed + } + + clif->mercenary_message(sd, reply); + return unit_remove_map(&md->bl, CLR_OUTSIGHT); +} + +void merc_contract_stop(struct mercenary_data *md) +{ + nullpo_retv(md); + if( md->contract_timer != INVALID_TIMER ) + iTimer->delete_timer(md->contract_timer, merc_contract_end); + md->contract_timer = INVALID_TIMER; +} + +void merc_contract_init(struct mercenary_data *md) +{ + if( md->contract_timer == INVALID_TIMER ) + md->contract_timer = iTimer->add_timer(iTimer->gettick() + md->mercenary.life_time, merc_contract_end, md->master->bl.id, 0); + + md->regen.state.block = 0; +} + +int merc_data_received(struct s_mercenary *merc, bool flag) +{ + struct map_session_data *sd; + struct mercenary_data *md; + struct s_mercenary_db *db; + int i = merc_search_index(merc->class_); + + if( (sd = iMap->charid2sd(merc->char_id)) == NULL ) + return 0; + if( !flag || i < 0 ) + { // Not created - loaded - DB info + sd->status.mer_id = 0; + return 0; + } + + db = &mercenary_db[i]; + if( !sd->md ) + { + sd->md = md = (struct mercenary_data*)aCalloc(1,sizeof(struct mercenary_data)); + md->bl.type = BL_MER; + md->bl.id = npc_get_new_npc_id(); + md->devotion_flag = 0; + + md->master = sd; + md->db = db; + memcpy(&md->mercenary, merc, sizeof(struct s_mercenary)); + iStatus->set_viewdata(&md->bl, md->mercenary.class_); + iStatus->change_init(&md->bl); + unit_dataset(&md->bl); + md->ud.dir = sd->ud.dir; + + md->bl.m = sd->bl.m; + md->bl.x = sd->bl.x; + md->bl.y = sd->bl.y; + unit_calc_pos(&md->bl, sd->bl.x, sd->bl.y, sd->ud.dir); + md->bl.x = md->ud.to_x; + md->bl.y = md->ud.to_y; + + iMap->addiddb(&md->bl); + status_calc_mercenary(md,1); + md->contract_timer = INVALID_TIMER; + merc_contract_init(md); + } + else + { + memcpy(&sd->md->mercenary, merc, sizeof(struct s_mercenary)); + md = sd->md; + } + + if( sd->status.mer_id == 0 ) + mercenary->set_calls(md, 1); + sd->status.mer_id = merc->mercenary_id; + + if( md && md->bl.prev == NULL && sd->bl.prev != NULL ) + { + iMap->addblock(&md->bl); + clif->spawn(&md->bl); + clif->mercenary_info(sd); + clif->mercenary_skillblock(sd); + } + + return 1; +} + +void mercenary_heal(struct mercenary_data *md, int hp, int sp) +{ + if( hp ) + clif->mercenary_updatestatus(md->master, SP_HP); + if( sp ) + clif->mercenary_updatestatus(md->master, SP_SP); +} + +int mercenary_dead(struct mercenary_data *md) +{ + mercenary->merc_delete(md, 1); + return 0; +} + +int mercenary_killbonus(struct mercenary_data *md) +{ + const enum sc_type scs[] = { SC_MER_FLEE, SC_MER_ATK, SC_MER_HP, SC_MER_SP, SC_MER_HIT }; + int index = rnd() % ARRAYLENGTH(scs); + + sc_start(&md->bl, scs[index], 100, rnd() % 5, 600000); + return 0; +} + +int mercenary_kills(struct mercenary_data *md) +{ + md->mercenary.kill_count++; + md->mercenary.kill_count = cap_value(md->mercenary.kill_count, 0, INT_MAX); + + if( (md->mercenary.kill_count % 50) == 0 ) + { + mercenary->set_faith(md, 1); + mercenary_killbonus(md); + } + + if( md->master ) + clif->mercenary_updatestatus(md->master, SP_MERCKILLS); + + return 0; +} + +int mercenary_checkskill(struct mercenary_data *md, uint16 skill_id) +{ + int i = skill_id - MC_SKILLBASE; + + if( !md || !md->db ) + return 0; + if( md->db->skill[i].id == skill_id ) + return md->db->skill[i].lv; + + return 0; +} + +static bool read_mercenarydb_sub(char* str[], int columns, int current) +{ + int ele; + struct s_mercenary_db *db; + struct status_data *status; + + db = &mercenary_db[current]; + db->class_ = atoi(str[0]); + safestrncpy(db->sprite, str[1], NAME_LENGTH); + safestrncpy(db->name, str[2], NAME_LENGTH); + db->lv = atoi(str[3]); + + status = &db->status; + db->vd.class_ = db->class_; + + status->max_hp = atoi(str[4]); + status->max_sp = atoi(str[5]); + status->rhw.range = atoi(str[6]); + status->rhw.atk = atoi(str[7]); + status->rhw.atk2 = status->rhw.atk + atoi(str[8]); + status->def = atoi(str[9]); + status->mdef = atoi(str[10]); + status->str = atoi(str[11]); + status->agi = atoi(str[12]); + status->vit = atoi(str[13]); + status->int_ = atoi(str[14]); + status->dex = atoi(str[15]); + status->luk = atoi(str[16]); + db->range2 = atoi(str[17]); + db->range3 = atoi(str[18]); + status->size = atoi(str[19]); + status->race = atoi(str[20]); + + ele = atoi(str[21]); + status->def_ele = ele%10; + status->ele_lv = ele/20; + if( status->def_ele >= ELE_MAX ) + { + ShowWarning("Mercenary %d has invalid element type %d (max element is %d)\n", db->class_, status->def_ele, ELE_MAX - 1); + status->def_ele = ELE_NEUTRAL; + } + if( status->ele_lv < 1 || status->ele_lv > 4 ) + { + ShowWarning("Mercenary %d has invalid element level %d (max is 4)\n", db->class_, status->ele_lv); + status->ele_lv = 1; + } + + status->aspd_rate = 1000; + status->speed = atoi(str[22]); + status->adelay = atoi(str[23]); + status->amotion = atoi(str[24]); + status->dmotion = atoi(str[25]); + + return true; +} + +int read_mercenarydb(void) +{ + memset(mercenary_db,0,sizeof(mercenary_db)); + sv->readdb(iMap->db_path, "mercenary_db.txt", ',', 26, 26, MAX_MERCENARY_CLASS, &read_mercenarydb_sub); + + return 0; +} + +static bool read_mercenary_skilldb_sub(char* str[], int columns, int current) +{// ,, + struct s_mercenary_db *db; + int i, class_; + uint16 skill_id, skill_lv; + + class_ = atoi(str[0]); + ARR_FIND(0, MAX_MERCENARY_CLASS, i, class_ == mercenary_db[i].class_); + if( i == MAX_MERCENARY_CLASS ) + { + ShowError("read_mercenary_skilldb : Class %d not found in mercenary_db for skill entry.\n", class_); + return false; + } + + skill_id = atoi(str[1]); + if( skill_id < MC_SKILLBASE || skill_id >= MC_SKILLBASE + MAX_MERCSKILL ) + { + ShowError("read_mercenary_skilldb : Skill %d out of range.\n", skill_id); + return false; + } + + db = &mercenary_db[i]; + skill_lv = atoi(str[2]); + + i = skill_id - MC_SKILLBASE; + db->skill[i].id = skill_id; + db->skill[i].lv = skill_lv; + + return true; +} + +int read_mercenary_skilldb(void) +{ + sv->readdb(iMap->db_path, "mercenary_skill_db.txt", ',', 3, 3, -1, &read_mercenary_skilldb_sub); + + return 0; +} + +int do_init_mercenary(void) +{ + mercenary->read_mercenarydb(); + mercenary->read_skilldb(); + + //add_timer_func_list(mercenary_contract, "mercenary_contract"); + return 0; +} + +int do_final_mercenary(void); + +/*===================================== +* Default Functions : mercenary.h +* Generated by HerculesInterfaceMaker +* created by Susu +*-------------------------------------*/ +void mercenary_defaults(void) { + mercenary = &mercenary_s; + /* vars */ + + mercenary->mercenary_db[MAX_MERCENARY_CLASS] = mercenary_db[MAX_MERCENARY_CLASS]; + /* funcs */ + + mercenary->merc_class = merc_class; + mercenary->merc_get_viewdata = merc_get_viewdata; + + mercenary->merc_create = merc_create; + mercenary->merc_data_received = merc_data_received; + mercenary->save = mercenary_save; + + mercenary->heal = mercenary_heal; + mercenary->dead = mercenary_dead; + + mercenary->merc_delete = merc_delete; + mercenary->merc_contract_stop = merc_contract_stop; + + mercenary->get_lifetime = mercenary_get_lifetime; + mercenary->get_guild = mercenary_get_guild; + mercenary->get_faith = mercenary_get_faith; + mercenary->set_faith = mercenary_set_faith; + mercenary->get_calls = mercenary_get_calls; + mercenary->set_calls = mercenary_set_calls; + mercenary->kills = mercenary_kills; + + mercenary->checkskill = mercenary_checkskill; + mercenary->read_mercenarydb = read_mercenarydb; + mercenary->read_skilldb = read_mercenary_skilldb; + + mercenary->do_init_mercenary = do_init_mercenary; +} diff --git a/src/map/mercenary.h b/src/map/mercenary.h index 994c7aaa4..5c69f9b60 100644 --- a/src/map/mercenary.h +++ b/src/map/mercenary.h @@ -1,83 +1,97 @@ -// Copyright (c) Athena Dev Teams - Licensed under GNU GPL -// For more information, see LICENCE in the main folder - -#ifndef _MERCENARY_H_ -#define _MERCENARY_H_ - -#include "status.h" // struct status_data, struct status_change -#include "unit.h" // struct unit_data - -// number of cells that a mercenary can walk to from it's master before being warped -#define MAX_MER_DISTANCE 15 - -enum { - ARCH_MERC_GUILD, - SPEAR_MERC_GUILD, - SWORD_MERC_GUILD, -}; - -struct s_mercenary_db { - int class_; - char sprite[NAME_LENGTH], name[NAME_LENGTH]; - unsigned short lv; - short range2, range3; - struct status_data status; - struct view_data vd; - struct { - unsigned short id, lv; - } skill[MAX_MERCSKILL]; -}; - -extern struct s_mercenary_db mercenary_db[MAX_MERCENARY_CLASS]; - -struct mercenary_data { - struct block_list bl; - struct unit_data ud; - struct view_data *vd; - struct status_data base_status, battle_status; - struct status_change sc; - struct regen_data regen; - - struct s_mercenary_db *db; - struct s_mercenary mercenary; - char blockskill[MAX_SKILL]; - - struct map_session_data *master; - int contract_timer; - - unsigned devotion_flag : 1; - unsigned int masterteleport_timer; -}; - -bool merc_class(int class_); -struct view_data * merc_get_viewdata(int class_); - -int merc_create(struct map_session_data *sd, int class_, unsigned int lifetime); -int merc_data_received(struct s_mercenary *merc, bool flag); -int mercenary_save(struct mercenary_data *md); - -void mercenary_heal(struct mercenary_data *md, int hp, int sp); -int mercenary_dead(struct mercenary_data *md); - -int merc_delete(struct mercenary_data *md, int reply); -void merc_contract_stop(struct mercenary_data *md); - -int mercenary_get_lifetime(struct mercenary_data *md); -int mercenary_get_guild(struct mercenary_data *md); -int mercenary_get_faith(struct mercenary_data *md); -int mercenary_set_faith(struct mercenary_data *md, int value); -int mercenary_get_calls(struct mercenary_data *md); -int mercenary_set_calls(struct mercenary_data *md, int value); -int mercenary_kills(struct mercenary_data *md); - -int mercenary_checkskill(struct mercenary_data *md, uint16 skill_id); - -/** - * atcommand.c required - **/ -int read_mercenarydb(void); -int read_mercenary_skilldb(void); - -int do_init_mercenary(void); - -#endif /* _MERCENARY_H_ */ +// Copyright (c) Athena Dev Teams - Licensed under GNU GPL +// For more information, see LICENCE in the main folder +#ifndef _MERCENARY_H_ +#define _MERCENARY_H_ +#include "status.h" // struct status_data, struct status_change +#include "unit.h" // struct unit_data +// number of cells that a mercenary can walk to from it's master before being warped +#define MAX_MER_DISTANCE 15 +enum { + ARCH_MERC_GUILD, + SPEAR_MERC_GUILD, + SWORD_MERC_GUILD, +}; +struct s_mercenary_db { + int class_; + char sprite[NAME_LENGTH], name[NAME_LENGTH]; + unsigned short lv; + short range2, range3; + struct status_data status; + struct view_data vd; + struct { + unsigned short id, lv; + } skill[MAX_MERCSKILL]; +}; +struct mercenary_data { + struct block_list bl; + struct unit_data ud; + struct view_data *vd; + struct status_data base_status, battle_status; + struct status_change sc; + struct regen_data regen; + struct s_mercenary_db *db; + struct s_mercenary mercenary; + char blockskill[MAX_SKILL]; + + struct map_session_data *master; + int contract_timer; + + unsigned devotion_flag : 1; + unsigned int masterteleport_timer; +}; + + + + + + + +/** + * atcommand.c required + **/ + + +/*===================================== +* Interface : mercenary.h +* Generated by HerculesInterfaceMaker +* created by Susu +*-------------------------------------*/ +struct mercenary_interface { + /* vars */ + + struct s_mercenary_db mercenary_db[MAX_MERCENARY_CLASS]; + /* funcs */ + + bool (*merc_class) (int class_); + struct view_data * (*merc_get_viewdata) (int class_); + + int (*merc_create) (struct map_session_data *sd, int class_, unsigned int lifetime); + int (*merc_data_received) (struct s_mercenary *merc, bool flag); + int (*save) (struct mercenary_data *md); + + void (*heal) (struct mercenary_data *md, int hp, int sp); + int (*dead) (struct mercenary_data *md); + + int (*merc_delete) (struct mercenary_data *md, int reply); + void (*merc_contract_stop) (struct mercenary_data *md); + + int (*get_lifetime) (struct mercenary_data *md); + int (*get_guild) (struct mercenary_data *md); + int (*get_faith) (struct mercenary_data *md); + int (*set_faith) (struct mercenary_data *md, int value); + int (*get_calls) (struct mercenary_data *md); + int (*set_calls) (struct mercenary_data *md, int value); + int (*kills) (struct mercenary_data *md); + + int (*checkskill) (struct mercenary_data *md, uint16 skill_id); + int (*read_mercenarydb) (void); + int (*read_skilldb) (void); + + int (*do_init_mercenary) (void); +} mercenary_s; + +struct mercenary_interface *mercenary; + +void mercenary_defaults(void); + +#endif /* _MERCENARY_H_ */ diff --git a/src/map/mob.c b/src/map/mob.c index 04f3063e5..dedd541d9 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -2578,7 +2578,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) quest_update_objective(sd, md->class_); if( sd->md && src && src->type != BL_HOM && mob_db(md->class_)->lv > sd->status.base_level/2 ) - mercenary_kills(sd->md); + mercenary->kills(sd->md); } if( md->npc_event[0] && !md->state.npc_killmonster ) { diff --git a/src/map/pc.c b/src/map/pc.c index e6c3721c3..e0f2bf2f8 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -6725,7 +6725,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) { } if( sd->md ) - merc_delete(sd->md, 3); // Your mercenary soldier has ran away. + mercenary->merc_delete(sd->md, 3); // Your mercenary soldier has ran away. if( sd->ed ) elemental->delete(sd->ed, 0); diff --git a/src/map/script.c b/src/map/script.c index 5e99d2e62..e9a93918b 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -12459,10 +12459,10 @@ BUILDIN(getmercinfo) else script_pushconststr(st,""); break; - case 3: script_pushint(st,md ? mercenary_get_faith(md) : 0); break; - case 4: script_pushint(st,md ? mercenary_get_calls(md) : 0); break; + case 3: script_pushint(st,md ? mercenary->get_faith(md) : 0); break; + case 4: script_pushint(st,md ? mercenary->get_calls(md) : 0); break; case 5: script_pushint(st,md ? md->mercenary.kill_count : 0); break; - case 6: script_pushint(st,md ? mercenary_get_lifetime(md) : 0); break; + case 6: script_pushint(st,md ? mercenary->get_lifetime(md) : 0); break; case 7: script_pushint(st,md ? md->db->lv : 0); break; default: ShowError("buildin_getmercinfo: Invalid type %d (char_id=%d).\n", type, sd->status.char_id); @@ -15396,11 +15396,11 @@ BUILDIN(mercenary_create) class_ = script_getnum(st,2); - if( !merc_class(class_) ) + if( !mercenary->merc_class(class_) ) return true; contract_time = script_getnum(st,3); - merc_create(sd, class_, contract_time); + mercenary->merc_create(sd, class_, contract_time); return true; } @@ -15551,7 +15551,7 @@ BUILDIN(mercenary_set_faith) *calls += value; *calls = cap_value(*calls, 0, INT_MAX); - if( mercenary_get_guild(sd->md) == guild ) + if( mercenary->get_guild(sd->md) == guild ) clif->mercenary_updatestatus(sd,SP_MERCFAITH); return true; diff --git a/src/map/status.c b/src/map/status.c index 48a61cfcb..1ea86e163 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -1242,7 +1242,7 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s case BL_PC: pc->damage((TBL_PC*)target,src,hp,sp); break; case BL_MOB: mob_damage((TBL_MOB*)target, src, hp); break; case BL_HOM: homun->damaged((TBL_HOM*)target); break; - case BL_MER: mercenary_heal((TBL_MER*)target,hp,sp); break; + case BL_MER: mercenary->heal((TBL_MER*)target,hp,sp); break; case BL_ELEM: elemental->heal((TBL_ELEM*)target,hp,sp); break; } @@ -1267,7 +1267,7 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s case BL_PC: flag = pc->dead((TBL_PC*)target,src); break; case BL_MOB: flag = mob_dead((TBL_MOB*)target, src, flag&4?3:0); break; case BL_HOM: flag = homun->dead((TBL_HOM*)target); break; - case BL_MER: flag = mercenary_dead((TBL_MER*)target); break; + case BL_MER: flag = mercenary->dead((TBL_MER*)target); break; case BL_ELEM: flag = elemental->dead((TBL_ELEM*)target); break; default: //Unhandled case, do nothing to object. flag = 0; @@ -1413,7 +1413,7 @@ int status_heal(struct block_list *bl,int hp,int sp, int flag) case BL_PC: pc->heal((TBL_PC*)bl,hp,sp,flag&2?1:0); break; case BL_MOB: mob_heal((TBL_MOB*)bl,hp); break; case BL_HOM: homun->healed((TBL_HOM*)bl); break; - case BL_MER: mercenary_heal((TBL_MER*)bl,hp,sp); break; + case BL_MER: mercenary->heal((TBL_MER*)bl,hp,sp); break; case BL_ELEM: elemental->heal((TBL_ELEM*)bl,hp,sp); break; } @@ -6055,8 +6055,8 @@ void status_set_viewdata(struct block_list *bl, int class_) vd = npc_get_viewdata(class_); else if (homdb_checkid(class_)) vd = homun->get_viewdata(class_); - else if (merc_class(class_)) - vd = merc_get_viewdata(class_); + else if (mercenary->merc_class(class_)) + vd = mercenary->merc_get_viewdata(class_); else if (elemental->class(class_)) vd = elemental->get_viewdata(class_); else @@ -8331,7 +8331,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val if( pc_isfalcon(sd) ) pc->setoption(sd, sd->sc.option&~OPTION_FALCON); if( sd->status.pet_id > 0 ) pet_menu(sd, 3); if( homun_alive(sd->hd) ) homun->vaporize(sd,1); - if( sd->md ) merc_delete(sd->md,3); + if( sd->md ) mercenary->merc_delete(sd->md,3); } break; case SC__LAZINESS: diff --git a/src/map/unit.c b/src/map/unit.c index b9cdfa278..1860be342 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -2252,7 +2252,7 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file, case BL_MER: { struct mercenary_data *md = (struct mercenary_data *)bl; ud->canact_tick = ud->canmove_tick; - if( mercenary_get_lifetime(md) <= 0 && !(md->master && !md->master->state.active) ) + if( mercenary->get_lifetime(md) <= 0 && !(md->master && !md->master->state.active) ) { clif->clearunit_area(bl,clrtype); iMap->delblock(bl); @@ -2531,8 +2531,8 @@ int unit_free(struct block_list *bl, clr_type clrtype) { struct mercenary_data *md = (TBL_MER*)bl; struct map_session_data *sd = md->master; - if( mercenary_get_lifetime(md) > 0 ) - mercenary_save(md); + if( mercenary->get_lifetime(md) > 0 ) + mercenary->save(md); else { intif->mercenary_delete(md->mercenary.mercenary_id); @@ -2542,7 +2542,7 @@ int unit_free(struct block_list *bl, clr_type clrtype) if( sd ) sd->md = NULL; - merc_contract_stop(md); + mercenary->merc_contract_stop(md); break; } case BL_ELEM: { -- cgit v1.2.3-60-g2f50