-Update Char_Client packet 2013+, thx (Yommy, Shaktoh)

--change connection sequence for 82d+9a0+20d => 9a1 => 99d
-Merge some Hercules stuffs:
--upd char (default map check, 0x99d HC)
--CreateParty enforced chk
--mapindex_db for name lookup
-Add max packet_len check on chrif init for mmo_charstatus. 
-Upd @mapinfo, add missing mapflag info.
-Expand teleport_timer for pet,homon,ele (Daegaladh)
-Make homon,ele inherit master speed (Daegaladh)
-Fix frostnova status chance and driven fail msg. (Daegaladh)
-Cleanup, replace hardcoded ai value with enum eq, change pet.msd to pet.master to harmonize with other blchar.

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@17332 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
glighta 2013-05-23 12:44:12 +00:00
parent 54f41e69bc
commit 38f9f0c208
30 changed files with 484 additions and 366 deletions

View File

@ -451,9 +451,29 @@
463: Message configuration has been reloaded. 463: Message configuration has been reloaded.
464: ---- Available languages: 464: ---- Available languages:
480: ----- Players in Map -----
481: Player '%s' (session #%d) | Location: %d,%d
482: ----- NPCs in Map -----
483: ----- Chats in Map -----
484: Chat: %s | Player: %s | Location: %d %d
485: Users: %d/%d | Password: %s | Public: %s
486: Yes
487: No
488: Please enter at least one valid list number (usage: @mapinfo <0-3> <map>).
489: NPC %d: %s::%s | Direction: %s | Sprite: %d | Location: %d %d
490: NPC %d: %s | Direction: %s | Sprite: %d | Location: %d %d
491: North
492: North West
493: West
494: South West
495: South
496: South East
497: East
498: North East
499: Unknown
// Messages of others (not for GM commands) // Messages of others (not for GM commands)
// ---------------------------------------- // ----------------------------------------
//500 free //500 free
501: Your account time limit is: %d-%m-%Y %H:%M:%S. 501: Your account time limit is: %d-%m-%Y %H:%M:%S.
502: Day Mode is activated 502: Day Mode is activated
@ -848,7 +868,7 @@
1042: Town Map 1042: Town Map
1043: Autotrade Enabled 1043: Autotrade Enabled
1044: Autotrade Disabled 1044: Autotrade Disabled
1045: Battlegrounds ON 1045: Battlegrounds ON type=%d
1046: PvP Flags: 1046: PvP Flags:
1047: Pvp ON | 1047: Pvp ON |
1048: NoGuild | 1048: NoGuild |
@ -901,27 +921,15 @@
1095: NoMVPLoot | 1095: NoMVPLoot |
1096: PartyLock | 1096: PartyLock |
1097: GuildLock | 1097: GuildLock |
1098: ----- Players in Map ----- 1098: Loadevent |
1099: Player '%s' (session #%d) | Location: %d,%d 1099: Src4instance |
1100: ----- NPCs in Map ----- 1100: Chmautojoin |
1101: North 1101: nousecart |
1102: North West 1102: noitemconsumption |
1103: West 1103: nosumstarmiracle |
1104: South West 1104: nomineeffect |
1105: South 1105: nolockon |
1106: South East 1106: Restricted zone=%d
1107: East
1108: North East
1109: North
1110: Unknown
1111: NPC %d: %s | Direction: %s | Sprite: %d | Location: %d %d
1112: NPC %d: %s::%s | Direction: %s | Sprite: %d | Location: %d %d
1113: ----- Chats in Map -----
1114: Chat: %s | Player: %s | Location: %d %d
1115: Users: %d/%d | Password: %s | Public: %s
1116: Yes
1117: No
1118: Please enter at least one valid list number (usage: @mapinfo <0-3> <map>).
// @mount // @mount
1119: You have mounted your Dragon. 1119: You have mounted your Dragon.

View File

@ -1104,7 +1104,7 @@ int mmo_chars_fromsql(struct char_session_data* sd, uint8* buf)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 29, SQLDT_SHORT, &p.head_top, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 29, SQLDT_SHORT, &p.head_top, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 30, SQLDT_SHORT, &p.head_mid, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 30, SQLDT_SHORT, &p.head_mid, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 31, SQLDT_SHORT, &p.head_bottom, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 31, SQLDT_SHORT, &p.head_bottom, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 32, SQLDT_STRING, &last_map, sizeof(last_map), NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 32, SQLDT_STRING, &last_map, sizeof(last_map), NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 33, SQLDT_SHORT, &p.rename, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 33, SQLDT_SHORT, &p.rename, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 34, SQLDT_UINT32, &p.delete_date, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 34, SQLDT_UINT32, &p.delete_date, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 35, SQLDT_SHORT, &p.robe, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 35, SQLDT_SHORT, &p.robe, 0, NULL, NULL)
@ -1223,7 +1223,7 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 46, SQLDT_INT, &p->mother, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 46, SQLDT_INT, &p->mother, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 47, SQLDT_INT, &p->child, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 47, SQLDT_INT, &p->child, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 48, SQLDT_INT, &p->fame, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 48, SQLDT_INT, &p->fame, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 49, SQLDT_SHORT, &p->rename, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 49, SQLDT_SHORT, &p->rename, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 50, SQLDT_UINT32, &p->delete_date, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 50, SQLDT_UINT32, &p->delete_date, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 51, SQLDT_SHORT, &p->robe, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 51, SQLDT_SHORT, &p->robe, 0, NULL, NULL)
|| SQL_ERROR == SqlStmt_BindColumn(stmt, 52, SQLDT_UINT32, &p->character_moves, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 52, SQLDT_UINT32, &p->character_moves, 0, NULL, NULL)
@ -1242,6 +1242,18 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything
p->last_point.map = mapindex_name2id(last_map); p->last_point.map = mapindex_name2id(last_map);
p->save_point.map = mapindex_name2id(save_map); p->save_point.map = mapindex_name2id(save_map);
if( p->last_point.map == 0 ) {
p->last_point.map = mapindex_name2id(MAP_DEFAULT);
p->last_point.x = MAP_DEFAULT_X;
p->last_point.y = MAP_DEFAULT_Y;
}
if( p->save_point.map == 0 ) {
p->save_point.map = mapindex_name2id(MAP_DEFAULT);
p->save_point.x = MAP_DEFAULT_X;
p->save_point.y = MAP_DEFAULT_Y;
}
strcat(t_msg, " status"); strcat(t_msg, " status");
if (!load_everything) // For quick selection of data when displaying the char menu if (!load_everything) // For quick selection of data when displaying the char menu
@ -1727,9 +1739,9 @@ int delete_char_sql(int char_id)
if( hom_id ) if( hom_id )
mapif_homunculus_delete(hom_id); mapif_homunculus_delete(hom_id);
/* remove elemental */ /* remove elemental */
if (elemental_id) if (elemental_id)
mapif_elemental_delete(elemental_id); mapif_elemental_delete(elemental_id);
/* remove mercenary data */ /* remove mercenary data */
mercenary_owner_delete(char_id); mercenary_owner_delete(char_id);
@ -1907,16 +1919,46 @@ int mmo_char_tobuf(uint8* buffer, struct mmo_charstatus* p)
return 106+offset; return 106+offset;
} }
// Tell client how many pages, kRO sends 17 (Yommy)
void char_charlist_notify( int fd, struct char_session_data* sd ){
WFIFOHEAD(fd, 6);
WFIFOW(fd, 0) = 0x9a0;
// pages to req / send them all in 1 until mmo_chars_fromsql can split them up
WFIFOL(fd, 2) = 1; //int TotalCnt
WFIFOSET(fd,6);
}
void char_block_character( int fd, struct char_session_data* sd ){
WFIFOHEAD(fd, 4);
WFIFOW(fd, 0) = 0x20d;
WFIFOW(fd, 2) = 4; //packet len
WFIFOSET(fd,4);
}
/* Made Possible by Yommy~! <3 */
void mmo_char_send099d(int fd, struct char_session_data *sd) {
WFIFOHEAD(fd,4 + (MAX_CHARS*MAX_CHAR_BUF));
WFIFOW(fd,0) = 0x99d;
WFIFOW(fd,2) = mmo_chars_fromsql(sd, WFIFOP(fd,4)) + 4;
WFIFOSET(fd,WFIFOW(fd,2));
}
//struct PACKET_CH_CHARLIST_REQ { 0x0 short PacketType}
void char_parse_req_charlist(int fd, struct char_session_data* sd){
mmo_char_send099d(fd,sd);
}
//---------------------------------------- //----------------------------------------
// Function to send characters to a player // Function to send characters to a player
//---------------------------------------- //----------------------------------------
int mmo_char_send006b(int fd, struct char_session_data* sd) int mmo_char_send006b(int fd, struct char_session_data* sd){
{
int j, offset = 0; int j, offset = 0;
#if PACKETVER >= 20100413 #if PACKETVER >= 20100413
offset += 3; offset += 3;
#endif #endif
if (save_log) if (save_log)
ShowInfo("Loading Char Data ("CL_BOLD"%d"CL_RESET")\n",sd->account_id); ShowInfo("Loading Char Data ("CL_BOLD"%d"CL_RESET")\n",sd->account_id);
@ -1942,7 +1984,6 @@ int mmo_char_send006b(int fd, struct char_session_data* sd)
void mmo_char_send082d(int fd, struct char_session_data* sd) { void mmo_char_send082d(int fd, struct char_session_data* sd) {
if (save_log) if (save_log)
ShowInfo("Loading Char Data ("CL_BOLD"%d"CL_RESET")\n",sd->account_id); ShowInfo("Loading Char Data ("CL_BOLD"%d"CL_RESET")\n",sd->account_id);
WFIFOHEAD(fd,29); WFIFOHEAD(fd,29);
WFIFOW(fd,0) = 0x82d; WFIFOW(fd,0) = 0x82d;
WFIFOW(fd,2) = 29; WFIFOW(fd,2) = 29;
@ -1953,7 +1994,16 @@ void mmo_char_send082d(int fd, struct char_session_data* sd) {
WFIFOB(fd,8) = sd->char_slots; WFIFOB(fd,8) = sd->char_slots;
memset(WFIFOP(fd,9), 0, 20); // unused bytes memset(WFIFOP(fd,9), 0, 20); // unused bytes
WFIFOSET(fd,29); WFIFOSET(fd,29);
}
void mmo_char_send(int fd, struct char_session_data* sd){
#if PACKETVER >= 20130000
mmo_char_send082d(fd,sd);
char_charlist_notify(fd,sd);
char_block_character(fd,sd);
#else
mmo_char_send006b(fd,sd); mmo_char_send006b(fd,sd);
#endif
} }
int char_married(int pl1, int pl2) int char_married(int pl1, int pl2)
@ -2258,11 +2308,7 @@ int parse_fromlogin(int fd) {
WFIFOSET(i,3); WFIFOSET(i,3);
} else { } else {
// send characters to player // send characters to player
#if PACKETVER >= 20130000 mmo_char_send(i, sd);
mmo_char_send082d(i, sd);
#else
mmo_char_send006b(i, sd);
#endif
#if PACKETVER >= 20110309 #if PACKETVER >= 20110309
if( pincode_enabled ){ if( pincode_enabled ){
// PIN code system enabled // PIN code system enabled
@ -4254,50 +4300,47 @@ int parse_char(int fd)
case 0x2af8: case 0x2af8:
if (RFIFOREST(fd) < 60) if (RFIFOREST(fd) < 60)
return 0; return 0;
{ else {
char* l_user = (char*)RFIFOP(fd,2); char* l_user = (char*)RFIFOP(fd,2);
char* l_pass = (char*)RFIFOP(fd,26); char* l_pass = (char*)RFIFOP(fd,26);
l_user[23] = '\0'; l_user[23] = '\0';
l_pass[23] = '\0'; l_pass[23] = '\0';
ARR_FIND( 0, ARRAYLENGTH(server), i, server[i].fd <= 0 ); ARR_FIND( 0, ARRAYLENGTH(server), i, server[i].fd <= 0 );
if( runflag != CHARSERVER_ST_RUNNING || if( runflag != CHARSERVER_ST_RUNNING ||
i == ARRAYLENGTH(server) || i == ARRAYLENGTH(server) ||
strcmp(l_user, userid) != 0 || strcmp(l_user, userid) != 0 ||
strcmp(l_pass, passwd) != 0 ) strcmp(l_pass, passwd) != 0 )
{ {
WFIFOHEAD(fd,3); WFIFOHEAD(fd,3);
WFIFOW(fd,0) = 0x2af9; WFIFOW(fd,0) = 0x2af9;
WFIFOB(fd,2) = 3; WFIFOB(fd,2) = 3;
WFIFOSET(fd,3); WFIFOSET(fd,3);
} else { } else {
WFIFOHEAD(fd,3); WFIFOHEAD(fd,3);
WFIFOW(fd,0) = 0x2af9; WFIFOW(fd,0) = 0x2af9;
WFIFOB(fd,2) = 0; WFIFOB(fd,2) = 0;
WFIFOSET(fd,3); WFIFOSET(fd,3);
server[i].fd = fd; server[i].fd = fd;
server[i].ip = ntohl(RFIFOL(fd,54)); server[i].ip = ntohl(RFIFOL(fd,54));
server[i].port = ntohs(RFIFOW(fd,58)); server[i].port = ntohs(RFIFOW(fd,58));
server[i].users = 0; server[i].users = 0;
memset(server[i].map, 0, sizeof(server[i].map)); memset(server[i].map, 0, sizeof(server[i].map));
session[fd]->func_parse = parse_frommap; session[fd]->func_parse = parse_frommap;
session[fd]->flag.server = 1; session[fd]->flag.server = 1;
realloc_fifo(fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK); realloc_fifo(fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
char_mapif_init(fd); char_mapif_init(fd);
}
RFIFOSKIP(fd,60);
} }
return 0; // avoid processing of followup packets here
RFIFOSKIP(fd,60);
}
return 0; // avoid processing of followup packets here
// checks the entered pin // checks the entered pin
case 0x8b8: case 0x8b8:
if( RFIFOREST(fd) < 10 ) if( RFIFOREST(fd) < 10 )
return 0; return 0;
if( pincode_enabled && RFIFOL(fd,2) == sd->account_id ) if( pincode_enabled && RFIFOL(fd,2) == sd->account_id )
pincode_check( fd, sd ); pincode_check( fd, sd );
RFIFOSKIP(fd,10); RFIFOSKIP(fd,10);
break; break;
@ -4305,7 +4348,6 @@ int parse_char(int fd)
case 0x8c5: case 0x8c5:
if( RFIFOREST(fd) < 6 ) if( RFIFOREST(fd) < 6 )
return 0; return 0;
if( pincode_enabled && RFIFOL(fd,2) == sd->account_id ){ if( pincode_enabled && RFIFOL(fd,2) == sd->account_id ){
if( strlen( sd->pincode ) <= 0 ){ if( strlen( sd->pincode ) <= 0 ){
pincode_sendstate( fd, sd, PINCODE_NEW ); pincode_sendstate( fd, sd, PINCODE_NEW );
@ -4313,7 +4355,6 @@ int parse_char(int fd)
pincode_sendstate( fd, sd, PINCODE_ASK ); pincode_sendstate( fd, sd, PINCODE_ASK );
} }
} }
RFIFOSKIP(fd,6); RFIFOSKIP(fd,6);
break; break;
@ -4332,10 +4373,8 @@ int parse_char(int fd)
case 0x8ba: case 0x8ba:
if( RFIFOREST(fd) < 10 ) if( RFIFOREST(fd) < 10 )
return 0; return 0;
if( pincode_enabled && RFIFOL(fd,2) == sd->account_id ) if( pincode_enabled && RFIFOL(fd,2) == sd->account_id )
pincode_setnew( fd, sd ); pincode_setnew( fd, sd );
RFIFOSKIP(fd,10); RFIFOSKIP(fd,10);
break; break;
@ -4345,10 +4384,17 @@ int parse_char(int fd)
return 0; return 0;
moveCharSlot( fd, sd, RFIFOW(fd, 2), RFIFOW(fd, 4) ); moveCharSlot( fd, sd, RFIFOW(fd, 2), RFIFOW(fd, 4) );
mmo_char_send(fd, sd);
RFIFOSKIP(fd,8); RFIFOSKIP(fd,8);
break; break;
case 0x9a1:
if( RFIFOREST(fd) < 2 )
return 0;
char_parse_req_charlist(fd,sd);
RFIFOSKIP(fd,2);
break;
// unknown packet received // unknown packet received
default: default:
ShowError("parse_char: Received unknown packet "CL_WHITE"0x%x"CL_RESET" from ip '"CL_WHITE"%s"CL_RESET"'! Disconnecting!\n", RFIFOW(fd,0), ip2str(ipl, NULL)); ShowError("parse_char: Received unknown packet "CL_WHITE"0x%x"CL_RESET" from ip '"CL_WHITE"%s"CL_RESET"'! Disconnecting!\n", RFIFOW(fd,0), ip2str(ipl, NULL));
@ -4720,11 +4766,7 @@ void moveCharSlot( int fd, struct char_session_data* sd, unsigned short from, un
// We successfully moved the char - time to notify the client // We successfully moved the char - time to notify the client
moveCharSlotReply( fd, sd, from, 0 ); moveCharSlotReply( fd, sd, from, 0 );
#if PACKETVER >= 20130000 mmo_char_send(fd, sd);
mmo_char_send082d(fd, sd);
#else
mmo_char_send006b( fd, sd );
#endif
} }
// reason // reason

View File

@ -476,6 +476,11 @@ int mapif_parse_CreateParty(int fd, char *name, int item, int item2, struct part
if (char_name_option == 1) { // only letters/symbols in char_name_letters are authorised if (char_name_option == 1) { // only letters/symbols in char_name_letters are authorised
for (i = 0; i < NAME_LENGTH && name[i]; i++) for (i = 0; i < NAME_LENGTH && name[i]; i++)
if (strchr(char_name_letters, name[i]) == NULL) { if (strchr(char_name_letters, name[i]) == NULL) {
if( name[i] == '"' ) { /* client-special-char */
normalize_name(name,"\"");
mapif_parse_CreateParty(fd,name,item,item2,leader);
return 0;
}
mapif_party_created(fd,leader->account_id,leader->char_id,NULL); mapif_party_created(fd,leader->account_id,leader->char_id,NULL);
return 0; return 0;
} }

View File

@ -177,6 +177,7 @@ typedef unsigned long int ppuint32;
// integer with exact processor width (and best speed) // integer with exact processor width (and best speed)
////////////////////////////// //////////////////////////////
#include <stddef.h> // size_t #include <stddef.h> // size_t
//#include <stdbool.h> //boolean
#if defined(WIN32) && !defined(MINGW) // does not have a signed size_t #if defined(WIN32) && !defined(MINGW) // does not have a signed size_t
////////////////////////////// //////////////////////////////
@ -276,7 +277,7 @@ typedef char bool;
#undef swap #undef swap
#endif #endif
// hmm only ints? // hmm only ints?
//#define swap(a,b) { int temp=a; a=b; b=temp;} //#define swap(a,b) { int temp=a; a=b; b=temp;}
// if using macros then something that is type independent // if using macros then something that is type independent
//#define swap(a,b) ((a == b) || ((a ^= b), (b ^= a), (a ^= b))) //#define swap(a,b) ((a == b) || ((a ^= b), (b ^= a), (a ^= b)))
// Avoid "value computed is not used" warning and generates the same assembly code // Avoid "value computed is not used" warning and generates the same assembly code

View File

@ -55,8 +55,7 @@ char SERVER_TYPE = ATHENA_SERVER_NONE;
#ifndef POSIX #ifndef POSIX
#define compat_signal(signo, func) signal(signo, func) #define compat_signal(signo, func) signal(signo, func)
#else #else
sigfunc *compat_signal(int signo, sigfunc *func) sigfunc *compat_signal(int signo, sigfunc *func) {
{
struct sigaction sact, oact; struct sigaction sact, oact;
sact.sa_handler = func; sact.sa_handler = func;
@ -77,10 +76,8 @@ sigfunc *compat_signal(int signo, sigfunc *func)
* CORE : Console events for Windows * CORE : Console events for Windows
*--------------------------------------*/ *--------------------------------------*/
#ifdef _WIN32 #ifdef _WIN32
static BOOL WINAPI console_handler(DWORD c_event) static BOOL WINAPI console_handler(DWORD c_event) {
{ switch(c_event) {
switch(c_event)
{
case CTRL_CLOSE_EVENT: case CTRL_CLOSE_EVENT:
case CTRL_LOGOFF_EVENT: case CTRL_LOGOFF_EVENT:
case CTRL_SHUTDOWN_EVENT: case CTRL_SHUTDOWN_EVENT:
@ -95,8 +92,7 @@ static BOOL WINAPI console_handler(DWORD c_event)
return TRUE; return TRUE;
} }
static void cevents_init() static void cevents_init() {
{
if (SetConsoleCtrlHandler(console_handler,TRUE)==FALSE) if (SetConsoleCtrlHandler(console_handler,TRUE)==FALSE)
ShowWarning ("Unable to install the console handler!\n"); ShowWarning ("Unable to install the console handler!\n");
} }
@ -105,8 +101,7 @@ static void cevents_init()
/*====================================== /*======================================
* CORE : Signal Sub Function * CORE : Signal Sub Function
*--------------------------------------*/ *--------------------------------------*/
static void sig_proc(int sn) static void sig_proc(int sn) {
{
static int is_called = 0; static int is_called = 0;
switch (sn) { switch (sn) {
@ -139,8 +134,7 @@ static void sig_proc(int sn)
} }
} }
void signals_init (void) void signals_init (void) {
{
compat_signal(SIGTERM, sig_proc); compat_signal(SIGTERM, sig_proc);
compat_signal(SIGINT, sig_proc); compat_signal(SIGINT, sig_proc);
#ifndef _DEBUG // need unhandled exceptions to debug on Windows #ifndef _DEBUG // need unhandled exceptions to debug on Windows
@ -158,13 +152,11 @@ void signals_init (void)
#endif #endif
#ifdef SVNVERSION #ifdef SVNVERSION
const char *get_svn_revision(void) const char *get_svn_revision(void) {
{
return EXPAND_AND_QUOTE(SVNVERSION); return EXPAND_AND_QUOTE(SVNVERSION);
} }
#else// not SVNVERSION #else// not SVNVERSION
const char* get_svn_revision(void) const char* get_svn_revision(void) {
{
static char svn_version_buffer[16] = ""; static char svn_version_buffer[16] = "";
FILE *fp; FILE *fp;
@ -199,12 +191,10 @@ const char* get_svn_revision(void)
fclose(fp); fclose(fp);
// parse buffer // parse buffer
for( i = prefix_len + 1; i + postfix_len <= len; ++i ) for( i = prefix_len + 1; i + postfix_len <= len; ++i ) {
{
if( buffer[i] != postfix[0] || memcmp(buffer + i, postfix, postfix_len) != 0 ) if( buffer[i] != postfix[0] || memcmp(buffer + i, postfix, postfix_len) != 0 )
continue; // postfix missmatch continue; // postfix missmatch
for( j = i; j > 0; --j ) for( j = i; j > 0; --j ) {// skip digits
{// skip digits
if( !ISDIGIT(buffer[j - 1]) ) if( !ISDIGIT(buffer[j - 1]) )
break; break;
} }

View File

@ -5,12 +5,14 @@
#include "../common/showmsg.h" #include "../common/showmsg.h"
#include "../common/malloc.h" #include "../common/malloc.h"
#include "../common/strlib.h" #include "../common/strlib.h"
#include "../common/db.h"
#include "mapindex.h" #include "mapindex.h"
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
DBMap *mapindex_db;
struct _indexes { struct _indexes {
char name[MAP_NAME_LENGTH]; //Stores map name char name[MAP_NAME_LENGTH]; //Stores map name
} indexes[MAX_MAPINDEX]; } indexes[MAX_MAPINDEX];
@ -23,11 +25,10 @@ char mapindex_cfgfile[80] = "db/map_index.txt";
/// Retrieves the map name from 'string' (removing .gat extension if present). /// Retrieves the map name from 'string' (removing .gat extension if present).
/// Result gets placed either into 'buf' or in a static local buffer. /// Result gets placed either into 'buf' or in a static local buffer.
const char* mapindex_getmapname(const char* string, char* output) const char* mapindex_getmapname(const char* string, char* output) {
{
static char buf[MAP_NAME_LENGTH]; static char buf[MAP_NAME_LENGTH];
char* dest = (output != NULL) ? output : buf; char* dest = (output != NULL) ? output : buf;
size_t len = strnlen(string, MAP_NAME_LENGTH_EXT); size_t len = strnlen(string, MAP_NAME_LENGTH_EXT);
if (len == MAP_NAME_LENGTH_EXT) { if (len == MAP_NAME_LENGTH_EXT) {
ShowWarning("(mapindex_normalize_name) Map name '%*s' is too long!\n", 2*MAP_NAME_LENGTH_EXT, string); ShowWarning("(mapindex_normalize_name) Map name '%*s' is too long!\n", 2*MAP_NAME_LENGTH_EXT, string);
@ -35,18 +36,17 @@ const char* mapindex_getmapname(const char* string, char* output)
} }
if (len >= 4 && stricmp(&string[len-4], ".gat") == 0) if (len >= 4 && stricmp(&string[len-4], ".gat") == 0)
len -= 4; // strip .gat extension len -= 4; // strip .gat extension
len = min(len, MAP_NAME_LENGTH-1); len = min(len, MAP_NAME_LENGTH-1);
safestrncpy(dest, string, len+1); safestrncpy(dest, string, len+1);
memset(&dest[len], '\0', MAP_NAME_LENGTH-len); memset(&dest[len], '\0', MAP_NAME_LENGTH-len);
return dest; return dest;
} }
/// Retrieves the map name from 'string' (adding .gat extension if not already present). /// Retrieves the map name from 'string' (adding .gat extension if not already present).
/// Result gets placed either into 'buf' or in a static local buffer. /// Result gets placed either into 'buf' or in a static local buffer.
const char* mapindex_getmapname_ext(const char* string, char* output) const char* mapindex_getmapname_ext(const char* string, char* output) {
{
static char buf[MAP_NAME_LENGTH_EXT]; static char buf[MAP_NAME_LENGTH_EXT];
char* dest = (output != NULL) ? output : buf; char* dest = (output != NULL) ? output : buf;
@ -69,19 +69,17 @@ const char* mapindex_getmapname_ext(const char* string, char* output)
} }
memset(&dest[len], '\0', MAP_NAME_LENGTH_EXT-len); memset(&dest[len], '\0', MAP_NAME_LENGTH_EXT-len);
return dest; return dest;
} }
/// Adds a map to the specified index /// Adds a map to the specified index
/// Returns 1 if successful, 0 oherwise /// Returns 1 if successful, 0 oherwise
int mapindex_addmap(int index, const char* name) int mapindex_addmap(int index, const char* name) {
{
char map_name[MAP_NAME_LENGTH]; char map_name[MAP_NAME_LENGTH];
if (index == -1){ if (index == -1){
for (index = 1; index < max_index; index++) for (index = 1; index < max_index; index++) {
{
//if (strcmp(indexes[index].name,"#CLEARED#")==0) //if (strcmp(indexes[index].name,"#CLEARED#")==0)
if (indexes[index].name[0] == '\0') if (indexes[index].name[0] == '\0')
break; break;
@ -105,29 +103,27 @@ int mapindex_addmap(int index, const char* name)
return 0; return 0;
} }
if (mapindex_exists(index)) if (mapindex_exists(index)) {
ShowWarning("(mapindex_add) Overriding index %d: map \"%s\" -> \"%s\"\n", index, indexes[index].name, map_name); ShowWarning("(mapindex_add) Overriding index %d: map \"%s\" -> \"%s\"\n", index, indexes[index].name, map_name);
strdb_remove(mapindex_db, indexes[index].name);
}
safestrncpy(indexes[index].name, map_name, MAP_NAME_LENGTH); safestrncpy(indexes[index].name, map_name, MAP_NAME_LENGTH);
strdb_iput(mapindex_db, map_name, index);
if (max_index <= index) if (max_index <= index)
max_index = index+1; max_index = index+1;
return index; return index;
} }
unsigned short mapindex_name2id(const char* name) unsigned short mapindex_name2id(const char* name) {
{
//TODO: Perhaps use a db to speed this up? [Skotlex]
int i; int i;
char map_name[MAP_NAME_LENGTH]; char map_name[MAP_NAME_LENGTH];
mapindex_getmapname(name, map_name); mapindex_getmapname(name, map_name);
for (i = 1; i < max_index; i++) if( (i = strdb_iget(mapindex_db, map_name)) )
{ return i;
if (strcmpi(indexes[i].name,map_name)==0)
return i;
}
ShowDebug("mapindex_name2id: Map \"%s\" not found in index list!\n", map_name); ShowDebug("mapindex_name2id: Map \"%s\" not found in index list!\n", map_name);
return 0; return 0;
} }
@ -141,27 +137,24 @@ const char* mapindex_id2name(unsigned short id)
return indexes[id].name; return indexes[id].name;
} }
void mapindex_init(void) void mapindex_init(void) {
{
FILE *fp; FILE *fp;
char line[1024]; char line[1024];
int last_index = -1; int last_index = -1;
int index; int index;
char map_name[1024]; char map_name[MAP_NAME_LENGTH];
memset (&indexes, 0, sizeof (indexes)); if( ( fp = fopen(mapindex_cfgfile,"r") ) == NULL ){
fp=fopen(mapindex_cfgfile,"r");
if(fp==NULL){
ShowFatalError("Unable to read mapindex config file %s!\n", mapindex_cfgfile); ShowFatalError("Unable to read mapindex config file %s!\n", mapindex_cfgfile);
exit(EXIT_FAILURE); //Server can't really run without this file. exit(EXIT_FAILURE); //Server can't really run without this file.
} }
while(fgets(line, sizeof(line), fp)) memset (&indexes, 0, sizeof (indexes));
{ mapindex_db = strdb_alloc(DB_OPT_DUP_KEY, MAP_NAME_LENGTH);
while(fgets(line, sizeof(line), fp)) {
if(line[0] == '/' && line[1] == '/') if(line[0] == '/' && line[1] == '/')
continue; continue;
switch (sscanf(line, "%1023s\t%d", map_name, &index)) switch (sscanf(line, "%12s\t%d", map_name, &index)) {
{
case 1: //Map with no ID given, auto-assign case 1: //Map with no ID given, auto-assign
index = last_index+1; index = last_index+1;
case 2: //Map with ID given case 2: //Map with ID given
@ -173,6 +166,10 @@ void mapindex_init(void)
last_index = index; last_index = index;
} }
fclose(fp); fclose(fp);
if( !strdb_iget(mapindex_db, MAP_DEFAULT) ) {
ShowError("mapindex_init: MAP_DEFAULT '%s' not found in cache! update mapindex.h MAP_DEFAULT var!!!\n",MAP_DEFAULT);
}
} }
int mapindex_removemap(int index){ int mapindex_removemap(int index){
@ -180,6 +177,6 @@ int mapindex_removemap(int index){
return 0; return 0;
} }
void mapindex_final(void) void mapindex_final(void) {
{ db_destroy(mapindex_db);
} }

View File

@ -47,6 +47,11 @@ extern char mapindex_cfgfile[80];
#define MAP_MALAYA "malaya" #define MAP_MALAYA "malaya"
#define MAP_ECLAGE "eclage" #define MAP_ECLAGE "eclage"
// When a map index search fails, return results from what map? default:prontera
#define MAP_DEFAULT MAP_PRONTERA
#define MAP_DEFAULT_X 150
#define MAP_DEFAULT_Y 150
const char* mapindex_getmapname(const char* string, char* output); const char* mapindex_getmapname(const char* string, char* output);
const char* mapindex_getmapname_ext(const char* string, char* output); const char* mapindex_getmapname_ext(const char* string, char* output);
unsigned short mapindex_name2id(const char*); unsigned short mapindex_name2id(const char*);

View File

@ -1163,7 +1163,7 @@ void socket_final(void)
if(session[i]) if(session[i])
do_close(i); do_close(i);
// session[0] <20>̃_<CC83>~<7E>[<5B>f<EFBFBD>[<5B>^<5E><><EFBFBD> // session[0]
aFree(session[0]->rdata); aFree(session[0]->rdata);
aFree(session[0]->wdata); aFree(session[0]->wdata);
aFree(session[0]); aFree(session[0]);

View File

@ -676,7 +676,7 @@ ACMD_FUNC(whogm)
memcpy(player_name, pl_sd->status.name, NAME_LENGTH); memcpy(player_name, pl_sd->status.name, NAME_LENGTH);
for (j = 0; player_name[j]; j++) for (j = 0; player_name[j]; j++)
player_name[j] = TOLOWER(player_name[j]); player_name[j] = TOLOWER(player_name[j]);
// search with no case sensitive // search with no case sensitive
if (strstr(player_name, match_text) == NULL) if (strstr(player_name, match_text) == NULL)
continue; continue;
} }
@ -2492,8 +2492,7 @@ ACMD_FUNC(stat_all)
/*========================================== /*==========================================
* *
*------------------------------------------*/ *------------------------------------------*/
ACMD_FUNC(guildlevelup) ACMD_FUNC(guildlevelup) {
{
int level = 0; int level = 0;
short added_level; short added_level;
struct guild *guild_info; struct guild *guild_info;
@ -2533,8 +2532,7 @@ ACMD_FUNC(guildlevelup)
/*========================================== /*==========================================
* *
*------------------------------------------*/ *------------------------------------------*/
ACMD_FUNC(makeegg) ACMD_FUNC(makeegg) {
{
struct item_data *item_data; struct item_data *item_data;
int id, pet_id; int id, pet_id;
nullpo_retr(-1, sd); nullpo_retr(-1, sd);
@ -2573,8 +2571,7 @@ ACMD_FUNC(makeegg)
/*========================================== /*==========================================
* *
*------------------------------------------*/ *------------------------------------------*/
ACMD_FUNC(hatch) ACMD_FUNC(hatch) {
{
nullpo_retr(-1, sd); nullpo_retr(-1, sd);
if (sd->status.pet_id <= 0) if (sd->status.pet_id <= 0)
clif_sendegg(sd); clif_sendegg(sd);
@ -2589,8 +2586,7 @@ ACMD_FUNC(hatch)
/*========================================== /*==========================================
* *
*------------------------------------------*/ *------------------------------------------*/
ACMD_FUNC(petfriendly) ACMD_FUNC(petfriendly) {
{
int friendly; int friendly;
struct pet_data *pd; struct pet_data *pd;
nullpo_retr(-1, sd); nullpo_retr(-1, sd);
@ -3707,7 +3703,7 @@ ACMD_FUNC(reload)
packetdb_readdb(); packetdb_readdb();
clif_displaymessage(fd, msg_txt(sd,1477)); // Packet database has been reloaded. clif_displaymessage(fd, msg_txt(sd,1477)); // Packet database has been reloaded.
} }
return 0; return 0;
} }
@ -3776,15 +3772,20 @@ ACMD_FUNC(mapinfo) {
clif_displaymessage(fd, msg_txt(sd,1041)); // ------ Map Flags ------ clif_displaymessage(fd, msg_txt(sd,1041)); // ------ Map Flags ------
if (map[m_id].flag.town) if (map[m_id].flag.town)
clif_displaymessage(fd, msg_txt(sd,1042)); // Town Map clif_displaymessage(fd, msg_txt(sd,1042)); // Town Map
if (map[m_id].flag.restricted){
sprintf(atcmd_output, msg_txt(sd,1106),map[m_id].zone);
clif_displaymessage(fd, atcmd_output); //restricted
}
if (battle_config.autotrade_mapflag == map[m_id].flag.autotrade) if (battle_config.autotrade_mapflag == map[m_id].flag.autotrade)
clif_displaymessage(fd, msg_txt(sd,1043)); // Autotrade Enabled clif_displaymessage(fd, msg_txt(sd,1043)); // Autotrade Enabled
else else
clif_displaymessage(fd, msg_txt(sd,1044)); // Autotrade Disabled clif_displaymessage(fd, msg_txt(sd,1044)); // Autotrade Disabled
if (map[m_id].flag.battleground) if (map[m_id].flag.battleground){
clif_displaymessage(fd, msg_txt(sd,1045)); // Battlegrounds ON sprintf(atcmd_output, msg_txt(sd,1106),map[m_id].zone);
clif_displaymessage(fd, atcmd_output); // Battlegrounds ON type=%d
}
strcpy(atcmd_output,msg_txt(sd,1046)); // PvP Flags: strcpy(atcmd_output,msg_txt(sd,1046)); // PvP Flags:
if (map[m_id].flag.pvp) if (map[m_id].flag.pvp)
strcat(atcmd_output, msg_txt(sd,1047)); // Pvp ON | strcat(atcmd_output, msg_txt(sd,1047)); // Pvp ON |
@ -3897,6 +3898,22 @@ ACMD_FUNC(mapinfo) {
strcat(atcmd_output, msg_txt(sd,1096)); // PartyLock | strcat(atcmd_output, msg_txt(sd,1096)); // PartyLock |
if (map[m_id].flag.guildlock) if (map[m_id].flag.guildlock)
strcat(atcmd_output, msg_txt(sd,1097)); // GuildLock | strcat(atcmd_output, msg_txt(sd,1097)); // GuildLock |
if (map[m_id].flag.loadevent)
strcat(atcmd_output, msg_txt(sd,1098)); //Loadevent |
if (map[m_id].flag.src4instance)
strcat(atcmd_output, msg_txt(sd,1099)); // Src4instance |
if (map[m_id].flag.chmautojoin)
strcat(atcmd_output, msg_txt(sd,1100)); // Chmautojoin |
if (map[m_id].flag.nousecart)
strcat(atcmd_output, msg_txt(sd,1101)); // nousecart |
if (map[m_id].flag.noitemconsumption)
strcat(atcmd_output, msg_txt(sd,1102)); // noitemconsumption |
if (map[m_id].flag.nosumstarmiracle)
strcat(atcmd_output, msg_txt(sd,1103)); // nosumstarmiracle |
if (map[m_id].flag.nomineeffect)
strcat(atcmd_output, msg_txt(sd,1104)); // nomineeffect |
if (map[m_id].flag.nolockon)
strcat(atcmd_output, msg_txt(sd,1105)); // nolockon |
clif_displaymessage(fd, atcmd_output); clif_displaymessage(fd, atcmd_output);
switch (list) { switch (list) {
@ -3904,12 +3921,12 @@ ACMD_FUNC(mapinfo) {
// Do nothing. It's list 0, no additional display. // Do nothing. It's list 0, no additional display.
break; break;
case 1: case 1:
clif_displaymessage(fd, msg_txt(sd,1098)); // ----- Players in Map ----- clif_displaymessage(fd, msg_txt(sd,480)); // ----- Players in Map -----
iter = mapit_getallusers(); iter = mapit_getallusers();
for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ) for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) )
{ {
if (pl_sd->mapindex == m_index) { if (pl_sd->mapindex == m_index) {
sprintf(atcmd_output, msg_txt(sd,1099), // Player '%s' (session #%d) | Location: %d,%d sprintf(atcmd_output, msg_txt(sd,481), // Player '%s' (session #%d) | Location: %d,%d
pl_sd->status.name, pl_sd->fd, pl_sd->bl.x, pl_sd->bl.y); pl_sd->status.name, pl_sd->fd, pl_sd->bl.x, pl_sd->bl.y);
clif_displaymessage(fd, atcmd_output); clif_displaymessage(fd, atcmd_output);
} }
@ -3917,33 +3934,33 @@ ACMD_FUNC(mapinfo) {
mapit_free(iter); mapit_free(iter);
break; break;
case 2: case 2:
clif_displaymessage(fd, msg_txt(sd,1100)); // ----- NPCs in Map ----- clif_displaymessage(fd, msg_txt(sd,482)); // ----- NPCs in Map -----
for (i = 0; i < map[m_id].npc_num;) for (i = 0; i < map[m_id].npc_num;)
{ {
nd = map[m_id].npc[i]; nd = map[m_id].npc[i];
switch(nd->ud.dir) { switch(nd->ud.dir) {
case 0: strcpy(direction, msg_txt(sd,1101)); break; // North case 0: strcpy(direction, msg_txt(sd,491)); break; // North
case 1: strcpy(direction, msg_txt(sd,1102)); break; // North West case 1: strcpy(direction, msg_txt(sd,492)); break; // North West
case 2: strcpy(direction, msg_txt(sd,1103)); break; // West case 2: strcpy(direction, msg_txt(sd,493)); break; // West
case 3: strcpy(direction, msg_txt(sd,1104)); break; // South West case 3: strcpy(direction, msg_txt(sd,494)); break; // South West
case 4: strcpy(direction, msg_txt(sd,1105)); break; // South case 4: strcpy(direction, msg_txt(sd,495)); break; // South
case 5: strcpy(direction, msg_txt(sd,1106)); break; // South East case 5: strcpy(direction, msg_txt(sd,496)); break; // South East
case 6: strcpy(direction, msg_txt(sd,1107)); break; // East case 6: strcpy(direction, msg_txt(sd,497)); break; // East
case 7: strcpy(direction, msg_txt(sd,1108)); break; // North East case 7: strcpy(direction, msg_txt(sd,498)); break; // North East
case 9: strcpy(direction, msg_txt(sd,1109)); break; // North case 9: strcpy(direction, msg_txt(sd,491)); break; // North
default: strcpy(direction, msg_txt(sd,1110)); break; // Unknown default: strcpy(direction, msg_txt(sd,499)); break; // Unknown
} }
if(strcmp(nd->name,nd->exname) == 0) if(strcmp(nd->name,nd->exname) == 0)
sprintf(atcmd_output, msg_txt(sd,1111), // NPC %d: %s | Direction: %s | Sprite: %d | Location: %d %d sprintf(atcmd_output, msg_txt(sd,490), // NPC %d: %s | Direction: %s | Sprite: %d | Location: %d %d
++i, nd->name, direction, nd->class_, nd->bl.x, nd->bl.y); ++i, nd->name, direction, nd->class_, nd->bl.x, nd->bl.y);
else else
sprintf(atcmd_output, msg_txt(sd,1112), // NPC %d: %s::%s | Direction: %s | Sprite: %d | Location: %d %d sprintf(atcmd_output, msg_txt(sd,489), // NPC %d: %s::%s | Direction: %s | Sprite: %d | Location: %d %d
++i, nd->name, nd->exname, direction, nd->class_, nd->bl.x, nd->bl.y); ++i, nd->name, nd->exname, direction, nd->class_, nd->bl.x, nd->bl.y);
clif_displaymessage(fd, atcmd_output); clif_displaymessage(fd, atcmd_output);
} }
break; break;
case 3: case 3:
clif_displaymessage(fd, msg_txt(sd,1113)); // ----- Chats in Map ----- clif_displaymessage(fd, msg_txt(sd,483)); // ----- Chats in Map -----
iter = mapit_getallusers(); iter = mapit_getallusers();
for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ) for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) )
{ {
@ -3951,18 +3968,18 @@ ACMD_FUNC(mapinfo) {
pl_sd->mapindex == m_index && pl_sd->mapindex == m_index &&
cd->usersd[0] == pl_sd) cd->usersd[0] == pl_sd)
{ {
sprintf(atcmd_output, msg_txt(sd,1114), // Chat: %s | Player: %s | Location: %d %d sprintf(atcmd_output, msg_txt(sd,484), // Chat: %s | Player: %s | Location: %d %d
cd->title, pl_sd->status.name, cd->bl.x, cd->bl.y); cd->title, pl_sd->status.name, cd->bl.x, cd->bl.y);
clif_displaymessage(fd, atcmd_output); clif_displaymessage(fd, atcmd_output);
sprintf(atcmd_output, msg_txt(sd,1115), // Users: %d/%d | Password: %s | Public: %s sprintf(atcmd_output, msg_txt(sd,485), // Users: %d/%d | Password: %s | Public: %s
cd->users, cd->limit, cd->pass, (cd->pub) ? msg_txt(sd,1116) : msg_txt(sd,1117)); // Yes / No cd->users, cd->limit, cd->pass, (cd->pub) ? msg_txt(sd,486) : msg_txt(sd,487)); // Yes / No
clif_displaymessage(fd, atcmd_output); clif_displaymessage(fd, atcmd_output);
} }
} }
mapit_free(iter); mapit_free(iter);
break; break;
default: // normally impossible to arrive here default: // normally impossible to arrive here
clif_displaymessage(fd, msg_txt(sd,1118)); // Please enter at least one valid list number (usage: @mapinfo <0-3> <map>). clif_displaymessage(fd, msg_txt(sd,488)); // Please enter at least one valid list number (usage: @mapinfo <0-3> <map>).
return -1; return -1;
break; break;
} }
@ -6320,7 +6337,7 @@ ACMD_FUNC(summon)
return -1; return -1;
md->master_id=sd->bl.id; md->master_id=sd->bl.id;
md->special_state.ai=1; md->special_state.ai=AI_ATTACK;
md->deletetimer=add_timer(tick+(duration*60000),mob_timer_delete,md->bl.id,0); md->deletetimer=add_timer(tick+(duration*60000),mob_timer_delete,md->bl.id,0);
clif_specialeffect(&md->bl,344,AREA); clif_specialeffect(&md->bl,344,AREA);
mob_spawn(md); mob_spawn(md);

View File

@ -1708,7 +1708,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
wd.div_=skill_id?skill_get_num(skill_id,skill_lv):1; wd.div_=skill_id?skill_get_num(skill_id,skill_lv):1;
wd.amotion=(skill_id && skill_get_inf(skill_id)&INF_GROUND_SKILL)?0:sstatus->amotion; //Amotion should be 0 for ground skills. wd.amotion=(skill_id && skill_get_inf(skill_id)&INF_GROUND_SKILL)?0:sstatus->amotion; //Amotion should be 0 for ground skills.
/*if(skill_id == KN_AUTOCOUNTER) // counter attack obeys ASPD delay on official /*if(skill_id == KN_AUTOCOUNTER) // counter attack obeys ASPD delay on official
wd.amotion >>= 1; */ wd.amotion >>= 1; */
wd.dmotion=tstatus->dmotion; wd.dmotion=tstatus->dmotion;
wd.blewcount=skill_get_blewcount(skill_id,skill_lv); wd.blewcount=skill_get_blewcount(skill_id,skill_lv);
wd.flag = BF_WEAPON; //Initial Flag wd.flag = BF_WEAPON; //Initial Flag
@ -5160,8 +5160,8 @@ struct block_list* battle_get_master(struct block_list *src)
prev = src; prev = src;
switch (src->type) { switch (src->type) {
case BL_PET: case BL_PET:
if (((TBL_PET*)src)->msd) if (((TBL_PET*)src)->master)
src = (struct block_list*)((TBL_PET*)src)->msd; src = (struct block_list*)((TBL_PET*)src)->master;
break; break;
case BL_MOB: case BL_MOB:
if (((TBL_MOB*)src)->master_id) if (((TBL_MOB*)src)->master_id)
@ -5245,9 +5245,9 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
} }
break; break;
case BL_MOB: case BL_MOB:
if(((((TBL_MOB*)target)->special_state.ai == 2 || //Marine Spheres if(((((TBL_MOB*)target)->special_state.ai == AI_SPHERE || //Marine Spheres
(((TBL_MOB*)target)->special_state.ai == 3 && battle_config.summon_flora&1)) && //Floras (((TBL_MOB*)target)->special_state.ai == AI_FLORA && battle_config.summon_flora&1)) && //Floras
s_bl->type == BL_PC && src->type != BL_MOB) || (((TBL_MOB*)target)->special_state.ai == 4 && t_bl->id != s_bl->id)) //Zanzoe s_bl->type == BL_PC && src->type != BL_MOB) || (((TBL_MOB*)target)->special_state.ai == AI_ZANZOU && t_bl->id != s_bl->id)) //Zanzoe
{ //Targettable by players { //Targettable by players
state |= BCT_ENEMY; state |= BCT_ENEMY;
strip_enemy = 0; strip_enemy = 0;
@ -5412,7 +5412,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
if( !md->special_state.ai ) if( !md->special_state.ai )
{ //Normal mobs { //Normal mobs
if( if(
( target->type == BL_MOB && t_bl->type == BL_PC && ( ((TBL_MOB*)target)->special_state.ai != 4 && ((TBL_MOB*)target)->special_state.ai != 1 ) ) || ( target->type == BL_MOB && t_bl->type == BL_PC && ( ((TBL_MOB*)target)->special_state.ai != AI_ZANZOU && ((TBL_MOB*)target)->special_state.ai != AI_ATTACK ) ) ||
( t_bl->type == BL_MOB && !((TBL_MOB*)t_bl)->special_state.ai ) ( t_bl->type == BL_MOB && !((TBL_MOB*)t_bl)->special_state.ai )
) )
state |= BCT_PARTY; //Normal mobs with no ai are friends. state |= BCT_PARTY; //Normal mobs with no ai are friends.

View File

@ -179,8 +179,8 @@ int bg_team_get_id(struct block_list *bl)
case BL_PC: case BL_PC:
return ((TBL_PC*)bl)->bg_id; return ((TBL_PC*)bl)->bg_id;
case BL_PET: case BL_PET:
if( ((TBL_PET*)bl)->msd ) if( ((TBL_PET*)bl)->master )
return ((TBL_PET*)bl)->msd->bg_id; return ((TBL_PET*)bl)->master->bg_id;
break; break;
case BL_MOB: case BL_MOB:
{ {

View File

@ -44,10 +44,8 @@ static unsigned int buyingstore_getuid(void)
} }
bool buyingstore_setup(struct map_session_data* sd, unsigned char slots) bool buyingstore_setup(struct map_session_data* sd, unsigned char slots){
{ if (!battle_config.feature_buying_store || sd->state.vending || sd->state.buyingstore || sd->state.trading || slots == 0) {
if( !battle_config.feature_buying_store || sd->state.vending || sd->state.buyingstore || sd->state.trading || slots == 0 )
{
return false; return false;
} }

View File

@ -1230,7 +1230,7 @@ int chrif_load_scdata(int fd) {
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
data = (struct status_change_data*)RFIFOP(fd,14 + i*sizeof(struct status_change_data)); data = (struct status_change_data*)RFIFOP(fd,14 + i*sizeof(struct status_change_data));
status_change_start(NULL,&sd->bl, (sc_type)data->type, 10000, data->val1, data->val2, data->val3, data->val4, data->tick, 15); status_change_start(NULL,&sd->bl, (sc_type)data->type, 10000, data->val1, data->val2, data->val3, data->val4, data->tick, 1|2|4|8);
} }
#endif #endif
@ -1600,7 +1600,11 @@ int do_final_chrif(void) {
* *
*------------------------------------------*/ *------------------------------------------*/
int do_init_chrif(void) { int do_init_chrif(void) {
if(sizeof(struct mmo_charstatus) > 0xFFFF){
ShowError("mmo_charstatus size = %d is too big to be transmit\n",
sizeof(struct mmo_charstatus));
exit(EXIT_FAILURE);
}
auth_db = idb_alloc(DB_OPT_BASE); auth_db = idb_alloc(DB_OPT_BASE);
auth_db_ers = ers_new(sizeof(struct auth_node),"chrif.c::auth_db_ers",ERS_OPT_NONE); auth_db_ers = ers_new(sizeof(struct auth_node),"chrif.c::auth_db_ers",ERS_OPT_NONE);

View File

@ -2815,10 +2815,10 @@ void clif_updatestatus(struct map_session_data *sd,int type)
WFIFOL(fd,4)=sd->battle_status.cri/10; WFIFOL(fd,4)=sd->battle_status.cri/10;
break; break;
case SP_MATK1: case SP_MATK1:
WFIFOL(fd,4)=pc_rightside_matk(sd); WFIFOL(fd,4)=pc_rightside_matk(sd);
break; break;
case SP_MATK2: case SP_MATK2:
WFIFOL(fd,4)=pc_leftside_matk(sd); WFIFOL(fd,4)=pc_leftside_matk(sd);
break; break;
@ -11579,7 +11579,7 @@ void clif_parse_ReplyPartyInvite2(int fd,struct map_session_data *sd)
/// 0100 /// 0100
void clif_parse_LeaveParty(int fd, struct map_session_data *sd) void clif_parse_LeaveParty(int fd, struct map_session_data *sd)
{ {
if(map[sd->bl.m].flag.partylock) { //Guild locked. if(map[sd->bl.m].flag.partylock) { //part locked.
clif_displaymessage(fd, msg_txt(sd,227)); clif_displaymessage(fd, msg_txt(sd,227));
return; return;
} }
@ -11591,7 +11591,7 @@ void clif_parse_LeaveParty(int fd, struct map_session_data *sd)
/// 0103 <account id>.L <char name>.24B /// 0103 <account id>.L <char name>.24B
void clif_parse_RemovePartyMember(int fd, struct map_session_data *sd) void clif_parse_RemovePartyMember(int fd, struct map_session_data *sd)
{ {
if(map[sd->bl.m].flag.partylock) { //Guild locked. if(map[sd->bl.m].flag.partylock) { //party locked.
clif_displaymessage(fd, msg_txt(sd,227)); clif_displaymessage(fd, msg_txt(sd,227));
return; return;
} }

View File

@ -783,4 +783,5 @@ void clif_channel_msg(struct Channel *channel, struct map_session_data *sd, char
#define clif_menuskill_clear(sd) (sd)->menuskill_id = (sd)->menuskill_val = (sd)->menuskill_val2 = 0; #define clif_menuskill_clear(sd) (sd)->menuskill_id = (sd)->menuskill_val = (sd)->menuskill_val2 = 0;
#endif /* _CLIF_H_ */ #endif /* _CLIF_H_ */

View File

@ -76,27 +76,27 @@ int elemental_create(struct map_session_data *sd, int class_, unsigned int lifet
ele.mode = EL_MODE_PASSIVE; // Initial mode ele.mode = EL_MODE_PASSIVE; // Initial mode
i = db->status.size+1; // summon level i = db->status.size+1; // summon level
//[(Casters Max HP/ 3 ) + (Casters INT x 10 )+ (Casters Job Level x 20 )] x [(Elemental Summon Level + 2) / 3] //[(Caster<EFBFBD>s Max HP/ 3 ) + (Caster<65>s INT x 10 )+ (Caster<65>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); ele.hp = ele.max_hp = (sd->battle_status.max_hp/3 + sd->battle_status.int_*10 + sd->status.job_level) * ((i + 2) / 3);
//Casters Max SP /4 //Caster<EFBFBD>s Max SP /4
ele.sp = ele.max_sp = sd->battle_status.max_sp/4; ele.sp = ele.max_sp = sd->battle_status.max_sp/4;
//Casters [ Max SP / (18 / Elemental Summon Skill Level) 1- 100 ] //Caster<EFBFBD>s [ Max SP / (18 / Elemental Summon Skill Level) 1- 100 ]
ele.atk = (sd->battle_status.max_sp / (18 / i) * 1 - 100); ele.atk = (sd->battle_status.max_sp / (18 / i) * 1 - 100);
//Casters [ Max SP / (18 / Elemental Summon Skill Level) ] //Caster<EFBFBD>s [ Max SP / (18 / Elemental Summon Skill Level) ]
ele.atk2 = sd->battle_status.max_sp / 18; ele.atk2 = sd->battle_status.max_sp / 18;
//Casters HIT + (Casters Base Level ) //Caster<EFBFBD>s HIT + (Caster<65>s Base Level )
ele.hit = sd->battle_status.hit + sd->status.base_level; ele.hit = sd->battle_status.hit + sd->status.base_level;
//[Elemental Summon Skill Level x (Casters INT / 2 + Casters DEX / 4)] //[Elemental Summon Skill Level x (Caster<EFBFBD>s INT / 2 + Caster<65>s DEX / 4)]
ele.matk = i * (sd->battle_status.int_ / 2 + sd->battle_status.dex / 4); ele.matk = i * (sd->battle_status.int_ / 2 + sd->battle_status.dex / 4);
//150 + [Casters DEX / 10] + [Elemental Summon Skill Level x 3 ] //150 + [Caster<EFBFBD>s DEX / 10] + [Elemental Summon Skill Level x 3 ]
ele.amotion = 150 + sd->battle_status.dex / 10 + i * 3; ele.amotion = 150 + sd->battle_status.dex / 10 + i * 3;
//Casters DEF + (Casters Base Level / (5 Elemental Summon Skill Level) //Caster<EFBFBD>s DEF + (Caster<65>s Base Level / (5 <20> Elemental Summon Skill Level)
ele.def = sd->battle_status.def + sd->status.base_level / (5-i); ele.def = sd->battle_status.def + sd->status.base_level / (5-i);
//Casters MDEF + (Casters INT / (5 - Elemental Summon Skill Level) //Caster<EFBFBD>s MDEF + (Caster<65>s INT / (5 - Elemental Summon Skill Level)
ele.mdef = sd->battle_status.mdef + sd->battle_status.int_ / (5-i); ele.mdef = sd->battle_status.mdef + sd->battle_status.int_ / (5-i);
//Casters FLEE + (Casters Base Level / (5 Elemental Summon Skill Level) //Caster<EFBFBD>s FLEE + (Caster<65>s Base Level / (5 <20> Elemental Summon Skill Level)
ele.flee = sd->status.base_level / (5-i); ele.flee = sd->status.base_level / (5-i);
//Casters HIT + (Casters Base Level ) //Caster<EFBFBD>s HIT + (Caster<65>s Base Level )
ele.hit = sd->battle_status.hit + sd->status.base_level; ele.hit = sd->battle_status.hit + sd->status.base_level;
//per individual bonuses //per individual bonuses

View File

@ -47,6 +47,7 @@ struct elemental_data {
struct s_elemental_db *db; struct s_elemental_db *db;
struct s_elemental elemental; struct s_elemental elemental;
int masterteleport_timer;
struct map_session_data *master; struct map_session_data *master;
int summon_timer; int summon_timer;
int skill_timer; int skill_timer;

View File

@ -49,6 +49,7 @@ struct homun_data {
struct s_homunculus_db *homunculusDB; //[orn] struct s_homunculus_db *homunculusDB; //[orn]
struct s_homunculus homunculus; //[orn] struct s_homunculus homunculus; //[orn]
int masterteleport_timer;
struct map_session_data *master; //pointer back to its master struct map_session_data *master; //pointer back to its master
int hungry_timer; //[orn] int hungry_timer; //[orn]
unsigned int exp_next; unsigned int exp_next;

View File

@ -1735,43 +1735,38 @@ int map_quit(struct map_session_data *sd) {
/*========================================== /*==========================================
* Lookup, id to session (player,mob,npc,homon,merc..) * Lookup, id to session (player,mob,npc,homon,merc..)
*------------------------------------------*/ *------------------------------------------*/
struct map_session_data * map_id2sd(int id) struct map_session_data * map_id2sd(int id){
{
if (id <= 0) return NULL; if (id <= 0) return NULL;
return (struct map_session_data*)idb_get(pc_db,id); return (struct map_session_data*)idb_get(pc_db,id);
} }
struct mob_data * map_id2md(int id) struct mob_data * map_id2md(int id){
{
if (id <= 0) return NULL; if (id <= 0) return NULL;
return (struct mob_data*)idb_get(mobid_db,id); return (struct mob_data*)idb_get(mobid_db,id);
} }
struct npc_data * map_id2nd(int id) struct npc_data * map_id2nd(int id){
{// just a id2bl lookup because there's no npc_db
struct block_list* bl = map_id2bl(id); struct block_list* bl = map_id2bl(id);
return BL_CAST(BL_NPC, bl); return BL_CAST(BL_NPC, bl);
} }
struct homun_data* map_id2hd(int id) struct homun_data* map_id2hd(int id){
{
struct block_list* bl = map_id2bl(id); struct block_list* bl = map_id2bl(id);
return BL_CAST(BL_HOM, bl); return BL_CAST(BL_HOM, bl);
} }
struct mercenary_data* map_id2mc(int id) struct mercenary_data* map_id2mc(int id){
{
struct block_list* bl = map_id2bl(id); struct block_list* bl = map_id2bl(id);
return BL_CAST(BL_MER, bl); return BL_CAST(BL_MER, bl);
} }
struct chat_data* map_id2cd(int id) struct pet_data* map_id2pd(int id){
{
struct block_list* bl = map_id2bl(id); struct block_list* bl = map_id2bl(id);
return BL_CAST(BL_PET, bl);
}
struct chat_data* map_id2cd(int id){
struct block_list* bl = map_id2bl(id);
return BL_CAST(BL_CHAT, bl); return BL_CAST(BL_CHAT, bl);
} }

View File

@ -303,6 +303,16 @@ enum {
ELE_MAX ELE_MAX
}; };
enum mob_ai {
AI_NONE = 0,
AI_ATTACK,
AI_SPHERE,
AI_FLORA,
AI_ZANZOU,
AI_LEGION,
AI_MAX
};
enum auto_trigger_flag { enum auto_trigger_flag {
ATF_SELF=0x01, ATF_SELF=0x01,
ATF_TARGET=0x02, ATF_TARGET=0x02,
@ -333,9 +343,7 @@ struct spawn_data {
unsigned int level; unsigned int level;
struct { struct {
unsigned int size : 2; //Holds if mob has to be tiny/large unsigned int size : 2; //Holds if mob has to be tiny/large
unsigned int ai : 4; //Special ai for summoned monsters. enum mob_ai ai; //Special ai for summoned monsters.
//0: Normal mob | 1: Standard summon, attacks mobs
//2: Alchemist Marine Sphere | 3: Alchemist Summon Flora | 4: Summon Zanzou
unsigned int dynamic : 1; //Whether this data is indexed by a map's dynamic mob list unsigned int dynamic : 1; //Whether this data is indexed by a map's dynamic mob list
unsigned int boss : 1; //0: Non-boss monster | 1: Boss monster unsigned int boss : 1; //0: Non-boss monster | 1: Boss monster
} state; } state;
@ -553,12 +561,12 @@ struct map_data {
unsigned sakura : 1; // [Valaris] unsigned sakura : 1; // [Valaris]
unsigned leaves : 1; // [Valaris] unsigned leaves : 1; // [Valaris]
unsigned nogo : 1; // [Valaris] unsigned nogo : 1; // [Valaris]
unsigned nobaseexp : 1; // [Lorky] added by Lupus unsigned nobaseexp : 1; // [Lorky] added by Lupus
unsigned nojobexp : 1; // [Lorky] unsigned nojobexp : 1; // [Lorky]
unsigned nomobloot : 1; // [Lorky] unsigned nomobloot : 1; // [Lorky]
unsigned nomvploot : 1; // [Lorky] unsigned nomvploot : 1; // [Lorky]
unsigned nightenabled :1; //For night display. [Skotlex] unsigned nightenabled :1; //For night display. [Skotlex]
unsigned restricted : 1; // [Komurka] unsigned restricted : 1; // [Komurka]
unsigned nodrop : 1; unsigned nodrop : 1;
unsigned novending : 1; unsigned novending : 1;
unsigned loadevent : 1; unsigned loadevent : 1;

View File

@ -1969,11 +1969,11 @@ void mob_log_damage(struct mob_data *md, struct block_list *src, int damage)
{ {
struct pet_data *pd = (TBL_PET*)src; struct pet_data *pd = (TBL_PET*)src;
flag = MDLF_PET; flag = MDLF_PET;
if( pd->msd ) if( pd->master )
{ {
char_id = pd->msd->status.char_id; char_id = pd->master->status.char_id;
if( damage ) //Let mobs retaliate against the pet's master [Skotlex] if( damage ) //Let mobs retaliate against the pet's master [Skotlex]
md->attacked_id = pd->msd->bl.id; md->attacked_id = pd->master->bl.id;
} }
break; break;
} }
@ -2079,7 +2079,7 @@ void mob_damage(struct mob_data *md, struct block_list *src, int damage)
} }
#endif #endif
if( md->special_state.ai == 2 ) {//LOne WOlf explained that ANYONE can trigger the marine countdown skill. [Skotlex] if( md->special_state.ai == AI_SPHERE ) {//LOne WOlf explained that ANYONE can trigger the marine countdown skill. [Skotlex]
md->state.alchemist = 1; md->state.alchemist = 1;
mobskill_use(md, gettick(), MSC_ALCHEMIST); mobskill_use(md, gettick(), MSC_ALCHEMIST);
} }
@ -2308,7 +2308,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
if( !(type&1) && !map[m].flag.nomobloot && !md->state.rebirth && ( if( !(type&1) && !map[m].flag.nomobloot && !md->state.rebirth && (
!md->special_state.ai || //Non special mob !md->special_state.ai || //Non special mob
battle_config.alchemist_summon_reward == 2 || //All summoned give drops battle_config.alchemist_summon_reward == 2 || //All summoned give drops
(md->special_state.ai==2 && battle_config.alchemist_summon_reward == 1) //Marine Sphere Drops items. (md->special_state.ai==AI_SPHERE && battle_config.alchemist_summon_reward == 1) //Marine Sphere Drops items.
) ) ) )
{ // Item Drop { // Item Drop
struct item_drop_list *dlist = ers_alloc(item_drop_list_ers, struct item_drop_list); struct item_drop_list *dlist = ers_alloc(item_drop_list_ers, struct item_drop_list);
@ -2736,7 +2736,7 @@ int mob_class_change (struct mob_data *md, int class_)
if( mob_is_treasure(md) ) if( mob_is_treasure(md) )
return 0; //Treasure Boxes return 0; //Treasure Boxes
if( md->special_state.ai > 1 ) if( md->special_state.ai > AI_ATTACK )
return 0; //Marine Spheres and Floras. return 0; //Marine Spheres and Floras.
if( mob_is_clone(md->class_) ) if( mob_is_clone(md->class_) )

View File

@ -69,14 +69,6 @@ enum size {
SZ_BIG, SZ_BIG,
}; };
enum ai {
AI_NONE = 0,
AI_ATTACK,
AI_SPHERE,
AI_FLORA,
AI_ZANZOU,
};
struct mob_skill { struct mob_skill {
enum MobSkillState state; enum MobSkillState state;
uint16 skill_id,skill_lv; uint16 skill_id,skill_lv;
@ -129,13 +121,7 @@ struct mob_data {
char name[NAME_LENGTH]; char name[NAME_LENGTH];
struct { struct {
unsigned int size : 2; //Small/Big monsters. unsigned int size : 2; //Small/Big monsters.
unsigned int ai : 4; //Special ai for summoned monsters. enum mob_ai ai; //Special ai for summoned monsters.
//0: Normal mob.
//1: Standard summon, attacks mobs.
//2: Alchemist Marine Sphere
//3: Alchemist Summon Flora
//4: Summon Zanzou
//5: Summon Legion
unsigned int clone : 1;/* is clone? 1:0 */ unsigned int clone : 1;/* is clone? 1:0 */
} special_state; //Special mob information that does not needs to be zero'ed on mob respawn. } special_state; //Special mob information that does not needs to be zero'ed on mob respawn.
struct { struct {

View File

@ -3063,7 +3063,7 @@ static const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const c
return strchr(start, '\n'); return strchr(start, '\n');
} }
if( (mob.state.ai < 0 || mob.state.ai > 4) && ai != -1 ) if( (mob.state.ai < AI_NONE || mob.state.ai >= AI_MAX) && ai != -1 )
{ {
ShowError("npc_parse_mob: Invalid ai %d for mob ID %d (file '%s', line '%d').\n", mob.state.ai, class_, filepath, strline(buffer, start - buffer)); ShowError("npc_parse_mob: Invalid ai %d for mob ID %d (file '%s', line '%d').\n", mob.state.ai, class_, filepath, strline(buffer, start - buffer));
return strchr(start, '\n'); return strchr(start, '\n');
@ -3086,7 +3086,7 @@ static const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const c
mob.level = mob_lv; mob.level = mob_lv;
if (size > 0 && size <= 2) if (size > 0 && size <= 2)
mob.state.size = size; mob.state.size = size;
if (ai > 0 && ai <= 4) if (ai > AI_NONE && ai <= AI_MAX)
mob.state.ai = ai; mob.state.ai = ai;
if (mob.num > 1 && battle_config.mob_count_rate != 100) { if (mob.num > 1 && battle_config.mob_count_rate != 100) {

View File

@ -519,7 +519,7 @@ int pc_makesavestatus(struct map_session_data *sd)
if(!battle_config.save_clothcolor) if(!battle_config.save_clothcolor)
sd->status.clothes_color=0; sd->status.clothes_color=0;
//Only copy the Cart/Peco/Falcon options, the rest are handled via //Only copy the Cart/Peco/Falcon options, the rest are handled via
//status change load/saving. [Skotlex] //status change load/saving. [Skotlex]
#ifdef NEW_CARTS #ifdef NEW_CARTS
sd->status.option = sd->sc.option&(OPTION_INVISIBLE|OPTION_FALCON|OPTION_RIDING|OPTION_DRAGON|OPTION_WUG|OPTION_WUGRIDER|OPTION_MADOGEAR|OPTION_MOUNTING); sd->status.option = sd->sc.option&(OPTION_INVISIBLE|OPTION_FALCON|OPTION_RIDING|OPTION_DRAGON|OPTION_WUG|OPTION_WUGRIDER|OPTION_MADOGEAR|OPTION_MOUNTING);
@ -4044,7 +4044,7 @@ int pc_takeitem(struct map_session_data *sd,struct flooritem_data *fitem)
} }
else else
if(fitem->second_get_charid > 0 && fitem->second_get_charid != sd->status.char_id) if(fitem->second_get_charid > 0 && fitem->second_get_charid != sd->status.char_id)
{ {
second_sd = map_charid2sd(fitem->second_get_charid); second_sd = map_charid2sd(fitem->second_get_charid);
if(DIFF_TICK(tick, fitem->second_get_tick) < 0) { if(DIFF_TICK(tick, fitem->second_get_tick) < 0) {
if(!(p && p->party.item&1 && if(!(p && p->party.item&1 &&
@ -4837,8 +4837,7 @@ int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y
if(sd->bl.prev != NULL){ if(sd->bl.prev != NULL){
unit_remove_map_pc(sd,clrtype); unit_remove_map_pc(sd,clrtype);
clif_changemap(sd,map[m].index,x,y); // [MouseJstr] clif_changemap(sd,map[m].index,x,y); // [MouseJstr]
} else if(sd->state.active) } else if(sd->state.active) //Tag player for rewarping after map-loading is done. [Skotlex]
//Tag player for rewarping after map-loading is done. [Skotlex]
sd->state.rewarp = 1; sd->state.rewarp = 1;
sd->mapindex = mapindex; sd->mapindex = mapindex;
@ -6573,10 +6572,8 @@ static int pc_close_npc_timer(int tid, unsigned int tick, int id, intptr_t data)
{ {
TBL_PC *sd = map_id2sd(id); TBL_PC *sd = map_id2sd(id);
if(sd) pc_close_npc(sd,data); if(sd) pc_close_npc(sd,data);
return 0; return 0;
} }
/* /*
* Method to properly close npc for player and clear anything related * Method to properly close npc for player and clear anything related
* @flag == 1 : produce close button * @flag == 1 : produce close button
@ -7815,7 +7812,7 @@ int pc_setcart(struct map_session_data *sd,int type) {
clif_cartlist(sd); clif_cartlist(sd);
clif_updatestatus(sd, SP_CARTINFO); clif_updatestatus(sd, SP_CARTINFO);
sc_start(&sd->bl,&sd->bl, SC_PUSH_CART, 100, type, 0); sc_start(&sd->bl,&sd->bl, SC_PUSH_CART, 100, type, 0);
clif_status_load_notick(&sd->bl, SI_ON_PUSH_CART, 2 , type, 0, 0); clif_status_load_notick(&sd->bl, SI_ON_PUSH_CART, 2 , type, 0, 0);
if( sd->sc.data[SC_PUSH_CART] )/* forcefully update */ if( sd->sc.data[SC_PUSH_CART] )/* forcefully update */
sd->sc.data[SC_PUSH_CART]->val1 = type; sd->sc.data[SC_PUSH_CART]->val1 = type;
break; break;
@ -9231,7 +9228,7 @@ int pc_autosave(int tid, unsigned int tick, int id, intptr_t data)
static int pc_daynight_timer_sub(struct map_session_data *sd,va_list ap) static int pc_daynight_timer_sub(struct map_session_data *sd,va_list ap)
{ {
if (sd->state.night != night_flag && map[sd->bl.m].flag.nightenabled) if (sd->state.night != night_flag && map[sd->bl.m].flag.nightenabled)
{ //Night/day state does not match. { //Night/day state does not match.
clif_status_load(&sd->bl, SI_NIGHT, night_flag); //New night effect by dynamix [Skotlex] clif_status_load(&sd->bl, SI_NIGHT, night_flag); //New night effect by dynamix [Skotlex]
sd->state.night = night_flag; sd->state.night = night_flag;
return 1; return 1;

View File

@ -64,7 +64,7 @@ void pet_set_intimate(struct pet_data *pd, int value)
nullpo_retv(pd); nullpo_retv(pd);
intimate = pd->pet.intimate; intimate = pd->pet.intimate;
sd = pd->msd; sd = pd->master;
pd->pet.intimate = value; pd->pet.intimate = value;
if( (intimate >= battle_config.pet_equip_min_friendly && pd->pet.intimate < battle_config.pet_equip_min_friendly) || (intimate < battle_config.pet_equip_min_friendly && pd->pet.intimate >= battle_config.pet_equip_min_friendly) ) if( (intimate >= battle_config.pet_equip_min_friendly && pd->pet.intimate < battle_config.pet_equip_min_friendly) || (intimate < battle_config.pet_equip_min_friendly && pd->pet.intimate >= battle_config.pet_equip_min_friendly) )
@ -135,7 +135,7 @@ int pet_target_check(struct map_session_data *sd,struct block_list *bl,int type)
pd = sd->pd; pd = sd->pd;
Assert((pd->msd == 0) || (pd->msd->pd == pd)); Assert((pd->master == 0) || (pd->master->pd == pd));
if(bl == NULL || bl->type != BL_MOB || bl->prev == NULL || if(bl == NULL || bl->type != BL_MOB || bl->prev == NULL ||
pd->pet.intimate < battle_config.pet_support_min_friendly || pd->pet.intimate < battle_config.pet_support_min_friendly ||
@ -323,7 +323,7 @@ int pet_data_init(struct map_session_data *sd, struct s_pet *pet)
nullpo_retr(1, sd); nullpo_retr(1, sd);
Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd); Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->master == sd);
if(sd->status.account_id != pet->account_id || sd->status.char_id != pet->char_id) { if(sd->status.account_id != pet->account_id || sd->status.char_id != pet->char_id) {
sd->status.pet_id = 0; sd->status.pet_id = 0;
@ -350,7 +350,7 @@ int pet_data_init(struct map_session_data *sd, struct s_pet *pet)
pd->bl.type = BL_PET; pd->bl.type = BL_PET;
pd->bl.id = npc_get_new_npc_id(); pd->bl.id = npc_get_new_npc_id();
pd->msd = sd; pd->master = sd;
pd->petDB = &pet_db[i]; pd->petDB = &pet_db[i];
pd->db = mob_db(pet->class_); pd->db = mob_db(pet->class_);
memcpy(&pd->pet, pet, sizeof(struct s_pet)); memcpy(&pd->pet, pet, sizeof(struct s_pet));
@ -389,7 +389,7 @@ int pet_birth_process(struct map_session_data *sd, struct s_pet *pet)
{ {
nullpo_retr(1, sd); nullpo_retr(1, sd);
Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd); Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->master == sd);
if(sd->status.pet_id && pet->incuvate == 1) { if(sd->status.pet_id && pet->incuvate == 1) {
sd->status.pet_id = 0; sd->status.pet_id = 0;
@ -417,7 +417,7 @@ int pet_birth_process(struct map_session_data *sd, struct s_pet *pet)
clif_pet_equip_area(sd->pd); clif_pet_equip_area(sd->pd);
clif_send_petstatus(sd); clif_send_petstatus(sd);
} }
Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd); Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->master == sd);
return 0; return 0;
} }
@ -791,7 +791,7 @@ static int pet_randomwalk(struct pet_data *pd,unsigned int tick)
{ {
nullpo_ret(pd); nullpo_ret(pd);
Assert((pd->msd == 0) || (pd->msd->pd == pd)); Assert((pd->master == 0) || (pd->master->pd == pd));
if(DIFF_TICK(pd->next_walktime,tick) < 0 && unit_can_move(&pd->bl)) { if(DIFF_TICK(pd->next_walktime,tick) < 0 && unit_can_move(&pd->bl)) {
const int retrycount=20; const int retrycount=20;
@ -968,7 +968,7 @@ static int pet_ai_sub_hard_lootsearch(struct block_list *bl,va_list ap)
sd_charid = fitem->first_get_charid; sd_charid = fitem->first_get_charid;
if(sd_charid && sd_charid != pd->msd->status.char_id) if(sd_charid && sd_charid != pd->master->status.char_id)
return 0; return 0;
if(unit_can_reach_bl(&pd->bl,bl, pd->db->range2, 1, NULL, NULL) && if(unit_can_reach_bl(&pd->bl,bl, pd->db->range2, 1, NULL, NULL) &&

View File

@ -95,7 +95,8 @@ struct pet_data {
struct pet_skill_support* s_skill; struct pet_skill_support* s_skill;
struct pet_loot* loot; struct pet_loot* loot;
struct map_session_data *msd; int masterteleport_timer;
struct map_session_data *master;
}; };

View File

@ -12083,7 +12083,7 @@ BUILDIN_FUNC(petloot)
pd = sd->pd; pd = sd->pd;
if (pd->loot != NULL) if (pd->loot != NULL)
{ //Release whatever was there already and reallocate memory { //Release whatever was there already and reallocate memory
pet_lootitem_drop(pd, pd->msd); pet_lootitem_drop(pd, pd->master);
aFree(pd->loot->item); aFree(pd->loot->item);
} }
else else

View File

@ -919,17 +919,13 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint
break; break;
case MG_FROSTDIVER: case MG_FROSTDIVER:
#ifndef RENEWAL if(!sc_start(src,bl,SC_FREEZE,skill_lv*3+35,skill_lv,skill_get_time2(skill_id,skill_lv)))
case WZ_FROSTNOVA: clif_skill_fail(sd,skill_id,0,0);
#endif
sc_start(src,bl,SC_FREEZE,skill_lv*3+35,skill_lv,skill_get_time2(skill_id,skill_lv));
break; break;
#ifdef RENEWAL
case WZ_FROSTNOVA: case WZ_FROSTNOVA:
sc_start(src,bl,SC_FREEZE,skill_lv*5+33,skill_lv,skill_get_time2(skill_id,skill_lv)); sc_start(src,bl,SC_FREEZE,skill_lv*5+33,skill_lv,skill_get_time2(skill_id,skill_lv));
break; break;
#endif
case WZ_STORMGUST: case WZ_STORMGUST:
/** /**
@ -5140,7 +5136,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
if (!ud) break; if (!ud) break;
if (inf&INF_SELF_SKILL || inf&INF_SUPPORT_SKILL) { if (inf&INF_SELF_SKILL || inf&INF_SUPPORT_SKILL) {
if (src->type == BL_PET) if (src->type == BL_PET)
bl = (struct block_list*)((TBL_PET*)src)->msd; bl = (struct block_list*)((TBL_PET*)src)->master;
if (!bl) bl = src; if (!bl) bl = src;
unit_skilluse_id(src, bl->id, abra_skill_id, abra_skill_lv); unit_skilluse_id(src, bl->id, abra_skill_id, abra_skill_lv);
} else { //Assume offensive skills } else { //Assume offensive skills
@ -5846,7 +5842,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case NPC_SELFDESTRUCTION: case NPC_SELFDESTRUCTION:
//Self Destruction hits everyone in range (allies+enemies) //Self Destruction hits everyone in range (allies+enemies)
//Except for Summoned Marine spheres on non-versus maps, where it's just enemy. //Except for Summoned Marine spheres on non-versus maps, where it's just enemy.
i = ((!md || md->special_state.ai == 2) && !map_flag_vs(src->m))? i = ((!md || md->special_state.ai == AI_SPHERE) && !map_flag_vs(src->m))?
BCT_ENEMY:BCT_ALL; BCT_ENEMY:BCT_ALL;
clif_skill_nodamage(src, src, skill_id, -1, 1); clif_skill_nodamage(src, src, skill_id, -1, 1);
map_delblock(src); //Required to prevent chain-self-destructions hitting back. map_delblock(src); //Required to prevent chain-self-destructions hitting back.
@ -8734,7 +8730,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
if (!ud) break; if (!ud) break;
if (inf&INF_SELF_SKILL || inf&INF_SUPPORT_SKILL) { if (inf&INF_SELF_SKILL || inf&INF_SUPPORT_SKILL) {
if (src->type == BL_PET) if (src->type == BL_PET)
bl = (struct block_list*)((TBL_PET*)src)->msd; bl = (struct block_list*)((TBL_PET*)src)->master;
if (!bl) bl = src; if (!bl) bl = src;
unit_skilluse_id(src, bl->id, improv_skill_id, improv_skill_lv); unit_skilluse_id(src, bl->id, improv_skill_id, improv_skill_lv);
} else { } else {
@ -9266,7 +9262,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
sum_md = mob_once_spawn_sub(src, src->m, src->x, src->y, status_get_name(src), summons[skill_lv - 1], "", SZ_SMALL, AI_ATTACK); sum_md = mob_once_spawn_sub(src, src->m, src->x, src->y, status_get_name(src), summons[skill_lv - 1], "", SZ_SMALL, AI_ATTACK);
if (sum_md) { if (sum_md) {
sum_md->master_id = src->id; sum_md->master_id = src->id;
sum_md->special_state.ai = 5; sum_md->special_state.ai = AI_LEGION;
if (sum_md->deletetimer != INVALID_TIMER) if (sum_md->deletetimer != INVALID_TIMER)
delete_timer(sum_md->deletetimer, mob_timer_delete); delete_timer(sum_md->deletetimer, mob_timer_delete);
sum_md->deletetimer = add_timer(gettick() + skill_get_time(skill_id, skill_lv), mob_timer_delete, sum_md->bl.id, 0); sum_md->deletetimer = add_timer(gettick() + skill_get_time(skill_id, skill_lv), mob_timer_delete, sum_md->bl.id, 0);
@ -9496,7 +9492,16 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data)
} }
break; break;
} }
#ifdef OFFICIAL_WALKPATH
if( !path_search_long(NULL, src->m, src->x, src->y, target->x, target->y, CELL_CHKWALL) )
{
if (sd) {
clif_skill_fail(sd,ud->skill_id,USESKILL_FAIL_LEVEL,0);
skill_consume_requirement(sd,ud->skill_id,ud->skill_lv,3); //Consume items anyway.
}
break;
}
#endif
if( sd ) if( sd )
{ {
if( !skill_check_condition_castend(sd, ud->skill_id, ud->skill_lv) ) if( !skill_check_condition_castend(sd, ud->skill_id, ud->skill_lv) )
@ -9504,18 +9509,14 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data)
else else
skill_consume_requirement(sd,ud->skill_id,ud->skill_lv,1); skill_consume_requirement(sd,ud->skill_id,ud->skill_lv,1);
} }
#ifdef OFFICIAL_WALKPATH
if( !path_search_long(NULL, src->m, src->x, src->y, target->x, target->y, CELL_CHKWALL) )
break;
#endif
if( (src->type == BL_MER || src->type == BL_HOM) && !skill_check_condition_mercenary(src, ud->skill_id, ud->skill_lv, 1) ) if( (src->type == BL_MER || src->type == BL_HOM) && !skill_check_condition_mercenary(src, ud->skill_id, ud->skill_lv, 1) )
break; break;
if (ud->state.running && ud->skill_id == TK_JUMPKICK) if (ud->state.running && ud->skill_id == TK_JUMPKICK){
{ ud->state.running = 0;
ud->state.running = 0; status_change_end(src, SC_RUN, INVALID_TIMER);
status_change_end(src, SC_RUN, INVALID_TIMER); flag = 1;
flag = 1;
} }
if (ud->walktimer != INVALID_TIMER && ud->skill_id != TK_RUN && ud->skill_id != RA_WUGDASH) if (ud->walktimer != INVALID_TIMER && ud->skill_id != TK_RUN && ud->skill_id != RA_WUGDASH)
@ -9579,7 +9580,7 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data)
if(sc->data[SC_SPIRIT] && if(sc->data[SC_SPIRIT] &&
sc->data[SC_SPIRIT]->val2 == SL_WIZARD && sc->data[SC_SPIRIT]->val2 == SL_WIZARD &&
sc->data[SC_SPIRIT]->val3 == ud->skill_id && sc->data[SC_SPIRIT]->val3 == ud->skill_id &&
ud->skill_id != WZ_WATERBALL) ud->skill_id != WZ_WATERBALL)
sc->data[SC_SPIRIT]->val3 = 0; //Clear bounced spell check. sc->data[SC_SPIRIT]->val3 = 0; //Clear bounced spell check.
if( sc->data[SC_DANCING] && skill_get_inf2(ud->skill_id)&INF2_SONG_DANCE && sd ) if( sc->data[SC_DANCING] && skill_get_inf2(ud->skill_id)&INF2_SONG_DANCE && sd )
@ -9600,7 +9601,7 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data)
//Skill failed. //Skill failed.
if (ud->skill_id == MO_EXTREMITYFIST && sd && !(sc && sc->data[SC_FOGWALL])) if (ud->skill_id == MO_EXTREMITYFIST && sd && !(sc && sc->data[SC_FOGWALL]))
{ //When Asura fails... (except when it fails from Fog of Wall) { //When Asura fails... (except when it fails from Fog of Wall)
//Consume SP/spheres //Consume SP/spheres
skill_consume_requirement(sd,ud->skill_id, ud->skill_lv,1); skill_consume_requirement(sd,ud->skill_id, ud->skill_lv,1);
status_set_sp(src, 0, 0); status_set_sp(src, 0, 0);
@ -17582,7 +17583,7 @@ void skill_init_unit_layout (void) {
static const int dx[] = {-1,-1,-1,-1, 0, 0, 0, 0, 1, 1, 1, 1, static const int dx[] = {-1,-1,-1,-1, 0, 0, 0, 0, 1, 1, 1, 1,
-5,-5,-5,-5,-4,-4,-4,-4,-3,-3,-3,-3,-2,-2,-2,-2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, -5,-5,-5,-5,-4,-4,-4,-4,-3,-3,-3,-3,-2,-2,-2,-2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5,
-1,-1,-1, 0, 0, 0, 1, 1, 1}; -1,-1,-1, 0, 0, 0, 1, 1, 1};
static const int dy[] = { 0,-1,-2,-3, 0,-1,-2,-3, 0,-1,-2,-3, static const int dy[] = { 0,-1,-2,-3, 0,-1,-2,-3, 0,-1,-2,-3,
0,-1,-2,-3, 0,-1,-2,-3, 0,-1,-2,-3, 0,-1,-2,-3, 0,-1,-2,-3, 0,-1,-2,-3, 0,-1,-2,-3, 0,-1,-2,-3, 0,-1,-2,-3, 0,-1,-2,-3, 0,-1,-2,-3, 0,-1,-2,-3, 0,-1,-2,-3, 0,-1,-2,-3, 0,-1,-2,-3, 0,-1,-2,-3,
-4,-5,-6,-4,-5,-6,-4,-5,-6}; -4,-5,-6,-4,-5,-6,-4,-5,-6};
skill_unit_layout[pos].count = 53; skill_unit_layout[pos].count = 53;

View File

@ -2014,7 +2014,7 @@ int status_calc_mob_(struct mob_data* md, bool first)
if (battle_config.slaves_inherit_speed && md->master_id) if (battle_config.slaves_inherit_speed && md->master_id)
flag|=8; flag|=8;
if (md->master_id && md->special_state.ai>1) if (md->master_id && md->special_state.ai>AI_ATTACK)
flag|=16; flag|=16;
if (!flag) if (!flag)
@ -2050,28 +2050,28 @@ int status_calc_mob_(struct mob_data* md, bool first)
struct unit_data *ud = unit_bl2ud(mbl); struct unit_data *ud = unit_bl2ud(mbl);
//Remove special AI when this is used by regular mobs. //Remove special AI when this is used by regular mobs.
if (mbl->type == BL_MOB && !((TBL_MOB*)mbl)->special_state.ai) if (mbl->type == BL_MOB && !((TBL_MOB*)mbl)->special_state.ai)
md->special_state.ai = 0; md->special_state.ai = AI_NONE;
if (ud) if (ud)
{ // different levels of HP according to skill level { // different levels of HP according to skill level
switch(ud->skill_id){ switch(ud->skill_id){
case AM_SPHEREMINE: case AM_SPHEREMINE:
status->max_hp = 2000 + 400*ud->skill_lv; status->max_hp = 2000 + 400*ud->skill_lv;
break; break;
case KO_ZANZOU: case KO_ZANZOU:
status->max_hp = 3000 + 3000 * ud->skill_lv; status->max_hp = 3000 + 3000 * ud->skill_lv;
break; break;
case AM_CANNIBALIZE: case AM_CANNIBALIZE:
status->max_hp = 1500 + 200*ud->skill_lv + 10*status_get_lv(mbl); status->max_hp = 1500 + 200*ud->skill_lv + 10*status_get_lv(mbl);
status->mode|= MD_CANATTACK|MD_AGGRESSIVE; status->mode|= MD_CANATTACK|MD_AGGRESSIVE;
break; break;
case MH_SUMMON_LEGION:{ case MH_SUMMON_LEGION:{
int homblvl = status_get_lv(mbl); int homblvl = status_get_lv(mbl);
status->max_hp = 10 * (100 * (ud->skill_lv + 2) + homblvl); status->max_hp = 10 * (100 * (ud->skill_lv + 2) + homblvl);
status->batk = 100 * (ud->skill_lv+5) / 2; status->batk = 100 * (ud->skill_lv+5) / 2;
status->def = 10 * (100 * (ud->skill_lv+2) + homblvl); status->def = 10 * (100 * (ud->skill_lv+2) + homblvl);
// status->aspd_rate = 10 * (2 * (20 - ud->skill_lv) - homblvl/10); // status->aspd_rate = 10 * (2 * (20 - ud->skill_lv) - homblvl/10);
// status->aspd_rate = max(100,status->aspd_rate); // status->aspd_rate = max(100,status->aspd_rate);
break; break;
} }
} }
status->hp = status->max_hp; status->hp = status->max_hp;
@ -2182,9 +2182,9 @@ int status_calc_pet_(struct pet_data *pd, bool first)
} }
} }
if (battle_config.pet_lv_rate && pd->msd) if (battle_config.pet_lv_rate && pd->master)
{ {
struct map_session_data *sd = pd->msd; struct map_session_data *sd = pd->master;
int lv; int lv;
lv =sd->status.base_level*battle_config.pet_lv_rate/100; lv =sd->status.base_level*battle_config.pet_lv_rate/100;
@ -3157,6 +3157,8 @@ int status_calc_mercenary_(struct mercenary_data *md, bool first)
status->sp = status->max_sp; status->sp = status->max_sp;
md->battle_status.hp = merc->hp; md->battle_status.hp = merc->hp;
md->battle_status.sp = merc->sp; md->battle_status.sp = merc->sp;
if (md->master)
status->speed = status_get_speed(&md->master->bl);
} }
status_calc_misc(&md->bl, status, md->db->lv); status_calc_misc(&md->bl, status, md->db->lv);
@ -3287,6 +3289,9 @@ int status_calc_elemental_(struct elemental_data *ed, bool first) {
status->flee = ele->flee; status->flee = ele->flee;
status->hit = ele->hit; status->hit = ele->hit;
if (ed->master)
status->speed = status_get_speed(&ed->master->bl);
memcpy(&ed->battle_status,status,sizeof(struct status_data)); memcpy(&ed->battle_status,status,sizeof(struct status_data));
} else { } else {
status_calc_misc(&ed->bl, status, 0); status_calc_misc(&ed->bl, status, 0);
@ -3807,7 +3812,7 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag)
//Re-walk to adjust speed (we do not check if walktimer != INVALID_TIMER //Re-walk to adjust speed (we do not check if walktimer != INVALID_TIMER
//because if you step on something while walking, the moment this //because if you step on something while walking, the moment this
//piece of code triggers the walk-timer is set on INVALID_TIMER) [Skotlex] //piece of code triggers the walk-timer is set on INVALID_TIMER) [Skotlex]
if (ud) if (ud)
ud->state.change_walk_target = ud->state.speed_changed = 1; ud->state.change_walk_target = ud->state.speed_changed = 1;
if( bl->type&BL_PC && status->speed < battle_config.max_walk_speed ) if( bl->type&BL_PC && status->speed < battle_config.max_walk_speed )
@ -3815,6 +3820,10 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag)
if( bl->type&BL_HOM && battle_config.hom_setting&0x8 && ((TBL_HOM*)bl)->master) if( bl->type&BL_HOM && battle_config.hom_setting&0x8 && ((TBL_HOM*)bl)->master)
status->speed = status_get_speed(&((TBL_HOM*)bl)->master->bl); status->speed = status_get_speed(&((TBL_HOM*)bl)->master->bl);
if( bl->type&BL_MER && ((TBL_MER*)bl)->master)
status->speed = status_get_speed(&((TBL_MER*)bl)->master->bl);
if( bl->type&BL_ELEM && ((TBL_ELEM*)bl)->master)
status->speed = status_get_speed(&((TBL_ELEM*)bl)->master->bl);
} }
@ -5905,8 +5914,8 @@ int status_get_party_id(struct block_list *bl) {
case BL_PC: case BL_PC:
return ((TBL_PC*)bl)->status.party_id; return ((TBL_PC*)bl)->status.party_id;
case BL_PET: case BL_PET:
if (((TBL_PET*)bl)->msd) if (((TBL_PET*)bl)->master)
return ((TBL_PET*)bl)->msd->status.party_id; return ((TBL_PET*)bl)->master->status.party_id;
break; break;
case BL_MOB: { case BL_MOB: {
struct mob_data *md=(TBL_MOB*)bl; struct mob_data *md=(TBL_MOB*)bl;
@ -5942,8 +5951,8 @@ int status_get_guild_id(struct block_list *bl) {
case BL_PC: case BL_PC:
return ((TBL_PC*)bl)->status.guild_id; return ((TBL_PC*)bl)->status.guild_id;
case BL_PET: case BL_PET:
if (((TBL_PET*)bl)->msd) if (((TBL_PET*)bl)->master)
return ((TBL_PET*)bl)->msd->status.guild_id; return ((TBL_PET*)bl)->master->status.guild_id;
break; break;
case BL_MOB: { case BL_MOB: {
struct map_session_data *msd; struct map_session_data *msd;
@ -5982,8 +5991,8 @@ int status_get_emblem_id(struct block_list *bl) {
case BL_PC: case BL_PC:
return ((TBL_PC*)bl)->guild_emblem_id; return ((TBL_PC*)bl)->guild_emblem_id;
case BL_PET: case BL_PET:
if (((TBL_PET*)bl)->msd) if (((TBL_PET*)bl)->master)
return ((TBL_PET*)bl)->msd->guild_emblem_id; return ((TBL_PET*)bl)->master->guild_emblem_id;
break; break;
case BL_MOB: { case BL_MOB: {
struct map_session_data *msd; struct map_session_data *msd;
@ -7600,7 +7609,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
else else
val4 = (type == SC_DPOISON) ? 2 + status->max_hp/100 : 2 + status->max_hp/200; val4 = (type == SC_DPOISON) ? 2 + status->max_hp/100 : 2 + status->max_hp/200;
break; break;
case SC_CONFUSION: case SC_CONFUSION:
clif_emotion(bl,E_WHAT); clif_emotion(bl,E_WHAT);
break; break;

View File

@ -112,16 +112,92 @@ int unit_walktoxy_sub(struct block_list *bl)
return 1; return 1;
} }
static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data)
{
TBL_PC* unit_get_master(struct block_list *bl){
if(bl)
switch(bl->type){
case BL_HOM : return (((TBL_HOM *)bl)->master);
case BL_ELEM : return (((TBL_ELEM *)bl)->master);
case BL_PET : return (((TBL_PET *)bl)->master);
case BL_MER : return (((TBL_MER *)bl)->master);
}
return NULL;
}
int* unit_get_masterteleport_timer(struct block_list *bl){
if(bl)
switch(bl->type){
case BL_HOM: return &(((TBL_HOM *)bl)->masterteleport_timer);
case BL_ELEM: return &(((TBL_ELEM *)bl)->masterteleport_timer);
case BL_PET: return &(((TBL_PET *)bl)->masterteleport_timer);
case BL_MER: return &(((TBL_MER *)bl)->masterteleport_timer);
}
return NULL;
}
int unit_teleport_timer(int tid, unsigned int tick, int id, intptr_t data){
if(tid == INVALID_TIMER)
return 0;
else {
struct block_list *bl = map_id2bl(id);
int *mast_tid = unit_get_masterteleport_timer(bl);
TBL_PC *msd = unit_get_master(bl);
switch(data){
case BL_HOM:
case BL_ELEM:
case BL_PET :
case BL_MER :
if(msd && *mast_tid != INVALID_TIMER && !check_distance_bl(&msd->bl, bl, MAX_MER_DISTANCE)){
*mast_tid = INVALID_TIMER;
unit_warp(bl, msd->bl.id, msd->bl.x, msd->bl.y, CLR_TELEPORT );
}
break;
}
}
return 0;
}
int unit_check_start_teleport_timer(struct block_list *sbl){
TBL_PC *msd = unit_get_master(sbl);
int max_dist=AREA_SIZE;
switch(sbl->type){
//case BL_HOM: max_dist = MAX_HOM_DISTANCE; break;
case BL_ELEM: max_dist = MAX_ELEDISTANCE; break;
//case BL_PET : max_dist = MAX_PET_DISTANCE; break;
case BL_MER : max_dist = MAX_MER_DISTANCE; break;
}
if(msd){ //if there is a master
int *msd_tid = unit_get_masterteleport_timer(sbl);
if(msd_tid == NULL) return 0;
if (!check_distance_bl(&msd->bl, sbl, MAX_MER_DISTANCE)) {
if(*msd_tid == INVALID_TIMER)
*msd_tid = add_timer(gettick()+3000,unit_teleport_timer,sbl->id,BL_MER);
}
else {
if(*msd_tid != INVALID_TIMER)
delete_timer(*msd_tid,unit_teleport_timer);
*msd_tid = INVALID_TIMER; //cancel recall
}
}
return 0;
}
static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data){
int i; int i;
int x,y,dx,dy; int x,y,dx,dy;
uint8 dir; uint8 dir;
struct block_list *bl; struct block_list *bl;
struct map_session_data *sd;
struct mob_data *md;
struct unit_data *ud; struct unit_data *ud;
struct mercenary_data *mrd; TBL_PC *sd;
TBL_MOB *md;
TBL_MER *mrd;
TBL_ELEM *ed;
TBL_PET *pd;
TBL_HOM *hd;
bl = map_id2bl(id); bl = map_id2bl(id);
if(bl == NULL) if(bl == NULL)
@ -129,6 +205,9 @@ static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data
sd = BL_CAST(BL_PC, bl); sd = BL_CAST(BL_PC, bl);
md = BL_CAST(BL_MOB, bl); md = BL_CAST(BL_MOB, bl);
mrd = BL_CAST(BL_MER, bl); mrd = BL_CAST(BL_MER, bl);
ed = BL_CAST(BL_ELEM, bl);
pd = BL_CAST(BL_PET, bl);
hd = BL_CAST(BL_HOM, bl);
ud = unit_bl2ud(bl); ud = unit_bl2ud(bl);
if(ud == NULL) return 0; if(ud == NULL) return 0;
@ -174,6 +253,7 @@ static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data
ud->walktimer = INVALID_TIMER; ud->walktimer = INVALID_TIMER;
if(sd) { if(sd) {
struct block_list *sbl; //slave bl
if( sd->touching_id ) if( sd->touching_id )
npc_touchnext_areanpc(sd,false); npc_touchnext_areanpc(sd,false);
if(map_getcell(bl->m,x,y,CELL_CHKNPC)) { if(map_getcell(bl->m,x,y,CELL_CHKNPC)) {
@ -183,24 +263,10 @@ static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data
} else } else
sd->areanpc_id=0; sd->areanpc_id=0;
if( sd->md && !check_distance_bl(&sd->bl, &sd->md->bl, MAX_MER_DISTANCE) ) if( sd->md) unit_check_start_teleport_timer(&sd->md->bl);
{ if( sd->ed) unit_check_start_teleport_timer(&sd->ed->bl);
// mercenary should be warped after being 3 seconds too far from the master [greenbox] if( sd->hd) unit_check_start_teleport_timer(&sd->hd->bl);
if (sd->md->masterteleport_timer == 0) if( sd->pd) unit_check_start_teleport_timer(&sd->pd->bl);
{
sd->md->masterteleport_timer = gettick();
}
else if (DIFF_TICK(gettick(), sd->md->masterteleport_timer) > 3000)
{
sd->md->masterteleport_timer = 0;
unit_warp( &sd->md->bl, sd->bl.m, sd->bl.x, sd->bl.y, CLR_TELEPORT );
}
}
else if( sd->md )
{
// reset the tick, he is not far anymore
sd->md->masterteleport_timer = 0;
}
} else if (md) { } else if (md) {
if( map_getcell(bl->m,x,y,CELL_CHKNPC) ) { if( map_getcell(bl->m,x,y,CELL_CHKNPC) ) {
if( npc_touch_areanpc2(md) ) return 0; // Warped if( npc_touch_areanpc2(md) ) return 0; // Warped
@ -212,7 +278,7 @@ static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data
if(tid != INVALID_TIMER && if(tid != INVALID_TIMER &&
!(ud->walk_count%WALK_SKILL_INTERVAL) && !(ud->walk_count%WALK_SKILL_INTERVAL) &&
mobskill_use(md, tick, -1)) mobskill_use(md, tick, -1))
{ {
if (!(ud->skill_id == NPC_SELFDESTRUCTION && ud->skilltimer != INVALID_TIMER)) if (!(ud->skill_id == NPC_SELFDESTRUCTION && ud->skilltimer != INVALID_TIMER))
{ //Skill used, abort walking { //Skill used, abort walking
clif_fixpos(bl); //Fix position as walk has been cancelled. clif_fixpos(bl); //Fix position as walk has been cancelled.
@ -222,26 +288,10 @@ static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data
clif_move(ud); clif_move(ud);
} }
} }
else if( mrd && mrd->master ) else if( hd) unit_check_start_teleport_timer(&hd->bl);
{ else if( ed) unit_check_start_teleport_timer(&ed->bl);
if (!check_distance_bl(&mrd->master->bl, bl, MAX_MER_DISTANCE)) else if( pd) unit_check_start_teleport_timer(&pd->bl);
{ else if( mrd) unit_check_start_teleport_timer(&mrd->bl);
// mercenary should be warped after being 3 seconds too far from the master [greenbox]
if (mrd->masterteleport_timer == 0)
{
mrd->masterteleport_timer = gettick();
}
else if (DIFF_TICK(gettick(), mrd->masterteleport_timer) > 3000)
{
mrd->masterteleport_timer = 0;
unit_warp( bl, mrd->master->bl.id, mrd->master->bl.x, mrd->master->bl.y, CLR_TELEPORT );
}
}
else
{
mrd->masterteleport_timer = 0;
}
}
if(tid == INVALID_TIMER) //A directly invoked timer is from battle_stop_walking, therefore the rest is irrelevant. if(tid == INVALID_TIMER) //A directly invoked timer is from battle_stop_walking, therefore the rest is irrelevant.
return 0; return 0;
@ -798,7 +848,7 @@ int unit_warp(struct block_list *bl,short m,short x,short y,clr_type type)
} }
if (x<0 || y<0) if (x<0 || y<0)
{ //Random map position. { //Random map position.
if (!map_search_freecell(NULL, m, &x, &y, -1, -1, 1)) { if (!map_search_freecell(NULL, m, &x, &y, -1, -1, 1)) {
ShowWarning("unit_warp failed. Unit Id:%d/Type:%d, target position map %d (%s) at [%d,%d]\n", bl->id, bl->type, m, map[m].name, x, y); ShowWarning("unit_warp failed. Unit Id:%d/Type:%d, target position map %d (%s) at [%d,%d]\n", bl->id, bl->type, m, map[m].name, x, y);
return 2; return 2;
@ -809,7 +859,7 @@ int unit_warp(struct block_list *bl,short m,short x,short y,clr_type type)
ShowWarning("unit_warp: Specified non-walkable target cell: %d (%s) at [%d,%d]\n", m, map[m].name, x,y); ShowWarning("unit_warp: Specified non-walkable target cell: %d (%s) at [%d,%d]\n", m, map[m].name, x,y);
if (!map_search_freecell(NULL, m, &x, &y, 4, 4, 1)) if (!map_search_freecell(NULL, m, &x, &y, 4, 4, 1))
{ //Can't find a nearby cell { //Can't find a nearby cell
ShowWarning("unit_warp failed. Unit Id:%d/Type:%d, target position map %d (%s) at [%d,%d]\n", bl->id, bl->type, m, map[m].name, x, y); ShowWarning("unit_warp failed. Unit Id:%d/Type:%d, target position map %d (%s) at [%d,%d]\n", bl->id, bl->type, m, map[m].name, x, y);
return 2; return 2;
} }
@ -2187,7 +2237,7 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file,
} }
case BL_PET: { case BL_PET: {
struct pet_data *pd = (struct pet_data*)bl; struct pet_data *pd = (struct pet_data*)bl;
if( pd->pet.intimate <= 0 && !(pd->msd && !pd->msd->state.active) ) if( pd->pet.intimate <= 0 && !(pd->master && !pd->master->state.active) )
{ //If logging out, this is deleted on unit_free { //If logging out, this is deleted on unit_free
clif_clearunit_area(bl,clrtype); clif_clearunit_area(bl,clrtype);
map_delblock(bl); map_delblock(bl);
@ -2350,7 +2400,7 @@ int unit_free(struct block_list *bl, clr_type clrtype)
case BL_PET: case BL_PET:
{ {
struct pet_data *pd = (struct pet_data*)bl; struct pet_data *pd = (struct pet_data*)bl;
struct map_session_data *sd = pd->msd; struct map_session_data *sd = pd->master;
pet_hungry_timer_delete(pd); pet_hungry_timer_delete(pd);
if( pd->a_skill ) if( pd->a_skill )
{ {
@ -2528,6 +2578,7 @@ int do_init_unit(void)
add_timer_func_list(unit_walktobl_sub, "unit_walktobl_sub"); add_timer_func_list(unit_walktobl_sub, "unit_walktobl_sub");
add_timer_func_list(unit_delay_walktoxy_timer,"unit_delay_walktoxy_timer"); add_timer_func_list(unit_delay_walktoxy_timer,"unit_delay_walktoxy_timer");
add_timer_func_list(unit_delay_walktobl_timer,"unit_delay_walktobl_timer"); add_timer_func_list(unit_delay_walktobl_timer,"unit_delay_walktobl_timer");
add_timer_func_list(unit_teleport_timer,"unit_teleport_timer");
return 0; return 0;
} }