Przeglądaj źródła

-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

glighta 12 lat temu
rodzic
commit
38f9f0c208

+ 31 - 23
conf/msg_conf/map_msg.conf

@@ -451,9 +451,29 @@
 463: Message configuration has been reloaded.
 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)
 // ----------------------------------------
-
 //500 free
 501: Your account time limit is: %d-%m-%Y %H:%M:%S.
 502: Day Mode is activated
@@ -848,7 +868,7 @@
 1042: Town Map
 1043: Autotrade Enabled
 1044: Autotrade Disabled
-1045: Battlegrounds ON
+1045: Battlegrounds ON type=%d
 1046: PvP Flags:
 1047: Pvp ON |
 1048: NoGuild |
@@ -901,27 +921,15 @@
 1095: NoMVPLoot |
 1096: PartyLock |
 1097: GuildLock |
-1098: ----- Players in Map -----
-1099: Player '%s' (session #%d) | Location: %d,%d
-1100: ----- NPCs in Map -----
-1101: North
-1102: North West
-1103: West
-1104: South West
-1105: South
-1106: South East
-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>).
+1098: Loadevent |
+1099: Src4instance |
+1100: Chmautojoin |
+1101: nousecart |
+1102: noitemconsumption |
+1103: nosumstarmiracle |
+1104: nomineeffect |
+1105: nolockon |
+1106: Restricted zone=%d
 
 // @mount
 1119: You have mounted your Dragon.

+ 101 - 59
src/char/char.c

@@ -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, 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, 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, 34, SQLDT_UINT32, &p.delete_date, 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, 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, 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, 51, SQLDT_SHORT,  &p->robe, 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->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");
 
 	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 )
 		mapif_homunculus_delete(hom_id);
 
-    /* remove elemental */
-    if (elemental_id)
-        mapif_elemental_delete(elemental_id);
+	/* remove elemental */
+	if (elemental_id)
+		mapif_elemental_delete(elemental_id);
 
 	/* remove mercenary data */
 	mercenary_owner_delete(char_id);
@@ -1907,16 +1919,46 @@ int mmo_char_tobuf(uint8* buffer, struct mmo_charstatus* p)
 	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
 //----------------------------------------
-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;
 #if PACKETVER >= 20100413
 	offset += 3;
 #endif
-
 	if (save_log)
 		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) {
 	if (save_log)
 		ShowInfo("Loading Char Data ("CL_BOLD"%d"CL_RESET")\n",sd->account_id);
-
 	WFIFOHEAD(fd,29);
 	WFIFOW(fd,0) = 0x82d;
 	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;
 	memset(WFIFOP(fd,9), 0, 20); // unused bytes
 	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);
+    #endif
 }
 
 int char_married(int pl1, int pl2)
@@ -2258,11 +2308,7 @@ int parse_fromlogin(int fd) {
 					WFIFOSET(i,3);
 				} else {
 					// send characters to player
-					#if PACKETVER >= 20130000
-						mmo_char_send082d(i, sd);
-					#else
-						mmo_char_send006b(i, sd);
-					#endif
+					mmo_char_send(i, sd);
 #if PACKETVER >=  20110309
 					if( pincode_enabled ){
 						// PIN code system enabled
@@ -4254,50 +4300,47 @@ int parse_char(int fd)
 		case 0x2af8:
 			if (RFIFOREST(fd) < 60)
 				return 0;
-		{
-			char* l_user = (char*)RFIFOP(fd,2);
-			char* l_pass = (char*)RFIFOP(fd,26);
-			l_user[23] = '\0';
-			l_pass[23] = '\0';
-			ARR_FIND( 0, ARRAYLENGTH(server), i, server[i].fd <= 0 );
-			if( runflag != CHARSERVER_ST_RUNNING ||
-				i == ARRAYLENGTH(server) ||
-				strcmp(l_user, userid) != 0 ||
-				strcmp(l_pass, passwd) != 0 )
-			{
-				WFIFOHEAD(fd,3);
-				WFIFOW(fd,0) = 0x2af9;
-				WFIFOB(fd,2) = 3;
-				WFIFOSET(fd,3);
-			} else {
-				WFIFOHEAD(fd,3);
-				WFIFOW(fd,0) = 0x2af9;
-				WFIFOB(fd,2) = 0;
-				WFIFOSET(fd,3);
+			else {
+				char* l_user = (char*)RFIFOP(fd,2);
+				char* l_pass = (char*)RFIFOP(fd,26);
+				l_user[23] = '\0';
+				l_pass[23] = '\0';
+				ARR_FIND( 0, ARRAYLENGTH(server), i, server[i].fd <= 0 );
+				if( runflag != CHARSERVER_ST_RUNNING ||
+					i == ARRAYLENGTH(server) ||
+					strcmp(l_user, userid) != 0 ||
+					strcmp(l_pass, passwd) != 0 )
+				{
+					WFIFOHEAD(fd,3);
+					WFIFOW(fd,0) = 0x2af9;
+					WFIFOB(fd,2) = 3;
+					WFIFOSET(fd,3);
+				} else {
+					WFIFOHEAD(fd,3);
+					WFIFOW(fd,0) = 0x2af9;
+					WFIFOB(fd,2) = 0;
+					WFIFOSET(fd,3);
 
-				server[i].fd = fd;
-				server[i].ip = ntohl(RFIFOL(fd,54));
-				server[i].port = ntohs(RFIFOW(fd,58));
-				server[i].users = 0;
-				memset(server[i].map, 0, sizeof(server[i].map));
-				session[fd]->func_parse = parse_frommap;
-				session[fd]->flag.server = 1;
-				realloc_fifo(fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
-				char_mapif_init(fd);
+					server[i].fd = fd;
+					server[i].ip = ntohl(RFIFOL(fd,54));
+					server[i].port = ntohs(RFIFOW(fd,58));
+					server[i].users = 0;
+					memset(server[i].map, 0, sizeof(server[i].map));
+					session[fd]->func_parse = parse_frommap;
+					session[fd]->flag.server = 1;
+					realloc_fifo(fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
+					char_mapif_init(fd);
+				}
+				RFIFOSKIP(fd,60);
 			}
-
-			RFIFOSKIP(fd,60);
-		}
-		return 0; // avoid processing of followup packets here
+			return 0; // avoid processing of followup packets here
 
 		// checks the entered pin
 		case 0x8b8:
 			if( RFIFOREST(fd) < 10 )
 				return 0;
-
 			if( pincode_enabled && RFIFOL(fd,2) == sd->account_id )
 				pincode_check( fd, sd );
-
 			RFIFOSKIP(fd,10);
 		break;
 
@@ -4305,7 +4348,6 @@ int parse_char(int fd)
 		case 0x8c5:
 			if( RFIFOREST(fd) < 6 )
 				return 0;
-
 			if( pincode_enabled && RFIFOL(fd,2) == sd->account_id ){
 				if( strlen( sd->pincode ) <= 0 ){
 					pincode_sendstate( fd, sd, PINCODE_NEW );
@@ -4313,7 +4355,6 @@ int parse_char(int fd)
 					pincode_sendstate( fd, sd, PINCODE_ASK );
 				}
 			}
-
 			RFIFOSKIP(fd,6);
 		break;
 
@@ -4332,10 +4373,8 @@ int parse_char(int fd)
 		case 0x8ba:
 			if( RFIFOREST(fd) < 10 )
 				return 0;
-
 			if( pincode_enabled && RFIFOL(fd,2) == sd->account_id )
 				pincode_setnew( fd, sd );
-
 			RFIFOSKIP(fd,10);
 		break;
 
@@ -4345,10 +4384,17 @@ int parse_char(int fd)
 				return 0;
 
 			moveCharSlot( fd, sd, RFIFOW(fd, 2), RFIFOW(fd, 4) );
-
+			mmo_char_send(fd, sd);
 			RFIFOSKIP(fd,8);
 		break;
 
+		case 0x9a1:
+			if( RFIFOREST(fd) < 2 )
+				return 0;
+			char_parse_req_charlist(fd,sd);
+			RFIFOSKIP(fd,2);
+			break;
+
 		// unknown packet received
 		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));
@@ -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
 	moveCharSlotReply( fd, sd, from, 0 );
-#if PACKETVER >= 20130000
-	mmo_char_send082d(fd, sd);
-#else
-	mmo_char_send006b( fd, sd );
-#endif
+	mmo_char_send(fd, sd);
 }
 
 // reason

+ 5 - 0
src/char/int_party.c

@@ -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
 		for (i = 0; i < NAME_LENGTH && name[i]; i++)
 			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);
 				return 0;
 			}

+ 2 - 1
src/common/cbasetypes.h

@@ -177,6 +177,7 @@ typedef unsigned long int   ppuint32;
 // integer with exact processor width (and best speed)
 //////////////////////////////
 #include <stddef.h> // size_t
+//#include <stdbool.h> //boolean
 
 #if defined(WIN32) && !defined(MINGW) // does not have a signed size_t
 //////////////////////////////
@@ -276,7 +277,7 @@ typedef char bool;
 #undef swap
 #endif
 // 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
 //#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

+ 10 - 20
src/common/core.c

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

+ 32 - 35
src/common/mapindex.c

@@ -5,12 +5,14 @@
 #include "../common/showmsg.h"
 #include "../common/malloc.h"
 #include "../common/strlib.h"
+#include "../common/db.h"
 #include "mapindex.h"
 
 #include <string.h>
 #include <stdio.h>
 #include <stdlib.h>
 
+DBMap *mapindex_db;
 struct _indexes {
 	char name[MAP_NAME_LENGTH]; //Stores map name
 } 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).
 /// 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];
 	char* dest = (output != NULL) ? output : buf;
-	
+
 	size_t len = strnlen(string, 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);
@@ -35,18 +36,17 @@ const char* mapindex_getmapname(const char* string, char* output)
 	}
 	if (len >= 4 && stricmp(&string[len-4], ".gat") == 0)
 		len -= 4; // strip .gat extension
-	
+
 	len = min(len, MAP_NAME_LENGTH-1);
 	safestrncpy(dest, string, len+1);
 	memset(&dest[len], '\0', MAP_NAME_LENGTH-len);
-	
+
 	return dest;
 }
 
 /// 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.
-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];
 	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);
-	
+
 	return dest;
 }
 
 /// Adds a map to the specified index
 /// 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];
 
 	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 (indexes[index].name[0] == '\0')
 				break;
@@ -105,29 +103,27 @@ int mapindex_addmap(int index, const char* name)
 		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);
+		strdb_remove(mapindex_db, indexes[index].name);
+	}
 
 	safestrncpy(indexes[index].name, map_name, MAP_NAME_LENGTH);
+	strdb_iput(mapindex_db, map_name, index);
 	if (max_index <= index)
 		max_index = index+1;
 
 	return index;
 }
 
-unsigned short mapindex_name2id(const char* name)
-{
-	//TODO: Perhaps use a db to speed this up? [Skotlex]
+unsigned short mapindex_name2id(const char* name) {
 	int i;
-
 	char map_name[MAP_NAME_LENGTH];
 	mapindex_getmapname(name, map_name);
 
-	for (i = 1; i < max_index; i++)
-	{
-		if (strcmpi(indexes[i].name,map_name)==0)
-			return i;
-	}
+	if( (i = strdb_iget(mapindex_db, map_name)) )
+		return i;
+
 	ShowDebug("mapindex_name2id: Map \"%s\" not found in index list!\n", map_name);
 	return 0;
 }
@@ -141,27 +137,24 @@ const char* mapindex_id2name(unsigned short id)
 	return indexes[id].name;
 }
 
-void mapindex_init(void)
-{
+void mapindex_init(void) {
 	FILE *fp;
 	char line[1024];
 	int last_index = -1;
 	int index;
-	char map_name[1024];
-	
-	memset (&indexes, 0, sizeof (indexes));
-	fp=fopen(mapindex_cfgfile,"r");
-	if(fp==NULL){
+	char map_name[MAP_NAME_LENGTH];
+
+	if( ( fp = fopen(mapindex_cfgfile,"r") ) == NULL ){
 		ShowFatalError("Unable to read mapindex config file %s!\n", mapindex_cfgfile);
 		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] == '/')
 			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
 				index = last_index+1;
 			case 2: //Map with ID given
@@ -173,6 +166,10 @@ void mapindex_init(void)
 		last_index = index;
 	}
 	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){
@@ -180,6 +177,6 @@ int mapindex_removemap(int index){
 	return 0;
 }
 
-void mapindex_final(void)
-{
+void mapindex_final(void) {
+	db_destroy(mapindex_db);
 }

+ 5 - 0
src/common/mapindex.h

@@ -47,6 +47,11 @@ extern char mapindex_cfgfile[80];
 #define MAP_MALAYA "malaya"
 #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_ext(const char* string, char* output);
 unsigned short mapindex_name2id(const char*);

+ 1 - 1
src/common/socket.c

@@ -1163,7 +1163,7 @@ void socket_final(void)
 		if(session[i])
 			do_close(i);
 
-	// session[0] �̃_�~�[�f�[�^���폜
+	// session[0]
 	aFree(session[0]->rdata);
 	aFree(session[0]->wdata);
 	aFree(session[0]);

+ 53 - 36
src/map/atcommand.c

@@ -676,7 +676,7 @@ ACMD_FUNC(whogm)
 			memcpy(player_name, pl_sd->status.name, NAME_LENGTH);
 			for (j = 0; player_name[j]; 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)
 				continue;
 		}
@@ -2492,8 +2492,7 @@ ACMD_FUNC(stat_all)
 /*==========================================
  *
  *------------------------------------------*/
-ACMD_FUNC(guildlevelup)
-{
+ACMD_FUNC(guildlevelup) {
 	int level = 0;
 	short added_level;
 	struct guild *guild_info;
@@ -2533,8 +2532,7 @@ ACMD_FUNC(guildlevelup)
 /*==========================================
  *
  *------------------------------------------*/
-ACMD_FUNC(makeegg)
-{
+ACMD_FUNC(makeegg) {
 	struct item_data *item_data;
 	int id, pet_id;
 	nullpo_retr(-1, sd);
@@ -2573,8 +2571,7 @@ ACMD_FUNC(makeegg)
 /*==========================================
  *
  *------------------------------------------*/
-ACMD_FUNC(hatch)
-{
+ACMD_FUNC(hatch) {
 	nullpo_retr(-1, sd);
 	if (sd->status.pet_id <= 0)
 		clif_sendegg(sd);
@@ -2589,8 +2586,7 @@ ACMD_FUNC(hatch)
 /*==========================================
  *
  *------------------------------------------*/
-ACMD_FUNC(petfriendly)
-{
+ACMD_FUNC(petfriendly) {
 	int friendly;
 	struct pet_data *pd;
 	nullpo_retr(-1, sd);
@@ -3707,7 +3703,7 @@ ACMD_FUNC(reload)
 		packetdb_readdb();
 		clif_displaymessage(fd, msg_txt(sd,1477)); // Packet database has been reloaded.
 	}
-		
+
 
 	return 0;
 }
@@ -3776,15 +3772,20 @@ ACMD_FUNC(mapinfo) {
 	clif_displaymessage(fd, msg_txt(sd,1041)); // ------ Map Flags ------
 	if (map[m_id].flag.town)
 		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)
 		clif_displaymessage(fd, msg_txt(sd,1043)); // Autotrade Enabled
 	else
 		clif_displaymessage(fd, msg_txt(sd,1044)); // Autotrade Disabled
 
-	if (map[m_id].flag.battleground)
-		clif_displaymessage(fd, msg_txt(sd,1045)); // Battlegrounds ON
-
+	if (map[m_id].flag.battleground){
+		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:
 	if (map[m_id].flag.pvp)
 		strcat(atcmd_output, msg_txt(sd,1047)); // Pvp ON |
@@ -3897,6 +3898,22 @@ ACMD_FUNC(mapinfo) {
 		strcat(atcmd_output, msg_txt(sd,1096)); // PartyLock |
 	if (map[m_id].flag.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);
 
 	switch (list) {
@@ -3904,12 +3921,12 @@ ACMD_FUNC(mapinfo) {
 		// Do nothing. It's list 0, no additional display.
 		break;
 	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();
 		for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) )
 		{
 			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);
 				clif_displaymessage(fd, atcmd_output);
 			}
@@ -3917,33 +3934,33 @@ ACMD_FUNC(mapinfo) {
 		mapit_free(iter);
 		break;
 	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;)
 		{
 			nd = map[m_id].npc[i];
 			switch(nd->ud.dir) {
-			case 0:  strcpy(direction, msg_txt(sd,1101)); break; // North
-			case 1:  strcpy(direction, msg_txt(sd,1102)); break; // North West
-			case 2:  strcpy(direction, msg_txt(sd,1103)); break; // West
-			case 3:  strcpy(direction, msg_txt(sd,1104)); break; // South West
-			case 4:  strcpy(direction, msg_txt(sd,1105)); break; // South
-			case 5:  strcpy(direction, msg_txt(sd,1106)); break; // South East
-			case 6:  strcpy(direction, msg_txt(sd,1107)); break; // East
-			case 7:  strcpy(direction, msg_txt(sd,1108)); break; // North East
-			case 9:  strcpy(direction, msg_txt(sd,1109)); break; // North
-			default: strcpy(direction, msg_txt(sd,1110)); break; // Unknown
+			case 0:  strcpy(direction, msg_txt(sd,491)); break; // North
+			case 1:  strcpy(direction, msg_txt(sd,492)); break; // North West
+			case 2:  strcpy(direction, msg_txt(sd,493)); break; // West
+			case 3:  strcpy(direction, msg_txt(sd,494)); break; // South West
+			case 4:  strcpy(direction, msg_txt(sd,495)); break; // South
+			case 5:  strcpy(direction, msg_txt(sd,496)); break; // South East
+			case 6:  strcpy(direction, msg_txt(sd,497)); break; // East
+			case 7:  strcpy(direction, msg_txt(sd,498)); break; // North East
+			case 9:  strcpy(direction, msg_txt(sd,491)); break; // North
+			default: strcpy(direction, msg_txt(sd,499)); break; // Unknown
 			}
 			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);
 			else
-				sprintf(atcmd_output, msg_txt(sd,1112), // 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);
+				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);
 			clif_displaymessage(fd, atcmd_output);
 		}
 		break;
 	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();
 		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 &&
 			    cd->usersd[0] == pl_sd)
 			{
-				sprintf(atcmd_output, msg_txt(sd,1114), // Chat: %s | Player: %s | Location: %d %d
-				        cd->title, pl_sd->status.name, cd->bl.x, cd->bl.y);
+				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);
 				clif_displaymessage(fd, atcmd_output);
-				sprintf(atcmd_output, msg_txt(sd,1115), //    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
+				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,486) : msg_txt(sd,487)); // Yes / No
 				clif_displaymessage(fd, atcmd_output);
 			}
 		}
 		mapit_free(iter);
 		break;
 	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;
 		break;
 	}
@@ -6320,7 +6337,7 @@ ACMD_FUNC(summon)
 		return -1;
 
 	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);
 	clif_specialeffect(&md->bl,344,AREA);
 	mob_spawn(md);

+ 7 - 7
src/map/battle.c

@@ -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.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
-			wd.amotion >>= 1; */ 
+			wd.amotion >>= 1; */
 	wd.dmotion=tstatus->dmotion;
 	wd.blewcount=skill_get_blewcount(skill_id,skill_lv);
 	wd.flag = BF_WEAPON; //Initial Flag
@@ -5160,8 +5160,8 @@ struct block_list* battle_get_master(struct block_list *src)
 		prev = src;
 		switch (src->type) {
 			case BL_PET:
-				if (((TBL_PET*)src)->msd)
-					src = (struct block_list*)((TBL_PET*)src)->msd;
+				if (((TBL_PET*)src)->master)
+					src = (struct block_list*)((TBL_PET*)src)->master;
 				break;
 			case BL_MOB:
 				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;
 		case BL_MOB:
-			if(((((TBL_MOB*)target)->special_state.ai == 2 || //Marine Spheres
-				(((TBL_MOB*)target)->special_state.ai == 3 && 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
+			if(((((TBL_MOB*)target)->special_state.ai == AI_SPHERE || //Marine Spheres
+				(((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 == AI_ZANZOU && t_bl->id != s_bl->id)) //Zanzoe
 			{	//Targettable by players
 				state |= BCT_ENEMY;
 				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 )
 			{ //Normal mobs
 				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 )
 				  )
 					state |= BCT_PARTY; //Normal mobs with no ai are friends.

+ 2 - 2
src/map/battleground.c

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

+ 2 - 4
src/map/buyingstore.c

@@ -44,10 +44,8 @@ static unsigned int buyingstore_getuid(void)
 }
 
 
-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 )
-	{
+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) {
 		return false;
 	}
 

+ 6 - 2
src/map/chrif.c

@@ -1230,7 +1230,7 @@ int chrif_load_scdata(int fd) {
 
 	for (i = 0; i < count; i++) {
 		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
 
@@ -1600,7 +1600,11 @@ int do_final_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_ers = ers_new(sizeof(struct auth_node),"chrif.c::auth_db_ers",ERS_OPT_NONE);
 

+ 4 - 4
src/map/clif.c

@@ -2815,10 +2815,10 @@ void clif_updatestatus(struct map_session_data *sd,int type)
 		WFIFOL(fd,4)=sd->battle_status.cri/10;
 		break;
 	case SP_MATK1:
-            WFIFOL(fd,4)=pc_rightside_matk(sd);
+		WFIFOL(fd,4)=pc_rightside_matk(sd);
 		break;
 	case SP_MATK2:
-            WFIFOL(fd,4)=pc_leftside_matk(sd);
+		WFIFOL(fd,4)=pc_leftside_matk(sd);
 		break;
 
 
@@ -11579,7 +11579,7 @@ void clif_parse_ReplyPartyInvite2(int fd,struct map_session_data *sd)
 /// 0100
 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));
 		return;
 	}
@@ -11591,7 +11591,7 @@ void clif_parse_LeaveParty(int fd, struct map_session_data *sd)
 /// 0103 <account id>.L <char name>.24B
 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));
 		return;
 	}

+ 1 - 0
src/map/clif.h

@@ -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;
 
+
 #endif /* _CLIF_H_ */

+ 11 - 11
src/map/elemental.c

@@ -76,27 +76,27 @@ int elemental_create(struct map_session_data *sd, int class_, unsigned int lifet
 	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]
+	//[(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);
-	//Casters Max SP /4
+	//Caster�s 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�s [ Max SP / (18 / Elemental Summon Skill Level) 1- 100 ]
 	ele.atk = (sd->battle_status.max_sp / (18 / i)  * 1 - 100);
-	//Casters [ Max SP / (18 / Elemental Summon Skill Level) ]
+	//Caster�s [ Max SP / (18 / Elemental Summon Skill Level) ]
 	ele.atk2 = sd->battle_status.max_sp / 18;
-	//Caster’s HIT + (Caster’s Base Level )
+	//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)]
+	//[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 + [Casters DEX / 10] + [Elemental Summon Skill Level x 3 ]
+	//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)
+	//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)
+	//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)
+	//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 )
+	//Caster�s HIT + (Caster�s Base Level )
 	ele.hit = sd->battle_status.hit + sd->status.base_level;
 
 	//per individual bonuses

+ 1 - 0
src/map/elemental.h

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

+ 1 - 0
src/map/homunculus.h

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

+ 10 - 15
src/map/map.c

@@ -1735,43 +1735,38 @@ int map_quit(struct map_session_data *sd) {
 /*==========================================
  * 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;
 	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;
 	return (struct mob_data*)idb_get(mobid_db,id);
 }
 
-struct npc_data * map_id2nd(int id)
-{// just a id2bl lookup because there's no npc_db
+struct npc_data * map_id2nd(int id){
 	struct block_list* bl = map_id2bl(id);
-
 	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);
-
 	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);
-
 	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);
+	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);
 }
 

+ 16 - 8
src/map/map.h

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

+ 6 - 6
src/map/mob.c

@@ -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;
 			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]
-					md->attacked_id = pd->msd->bl.id;
+					md->attacked_id = pd->master->bl.id;
 			}
 			break;
 		}
@@ -2079,7 +2079,7 @@ void mob_damage(struct mob_data *md, struct block_list *src, int damage)
 	}
 #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;
 		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 && (
 		!md->special_state.ai || //Non special mob
 		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
 		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) )
 		return 0; //Treasure Boxes
 
-	if( md->special_state.ai > 1 )
+	if( md->special_state.ai > AI_ATTACK )
 		return 0; //Marine Spheres and Floras.
 
 	if( mob_is_clone(md->class_) )

+ 1 - 15
src/map/mob.h

@@ -69,14 +69,6 @@ enum size {
 	SZ_BIG,
 };
 
-enum ai {
-	AI_NONE = 0,
-	AI_ATTACK,
-	AI_SPHERE,
-	AI_FLORA,
-	AI_ZANZOU,
-};
-
 struct mob_skill {
 	enum MobSkillState state;
 	uint16 skill_id,skill_lv;
@@ -129,13 +121,7 @@ struct mob_data {
 	char name[NAME_LENGTH];
 	struct {
 		unsigned int size : 2; //Small/Big monsters.
-		unsigned int ai : 4; //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
+		enum mob_ai ai; //Special ai for summoned monsters.
 		unsigned int clone : 1;/* is clone? 1:0 */
 	} special_state; //Special mob information that does not needs to be zero'ed on mob respawn.
 	struct {

+ 2 - 2
src/map/npc.c

@@ -3063,7 +3063,7 @@ static const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const c
 		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));
 		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;
 	if (size > 0 && size <= 2)
 		mob.state.size = size;
-	if (ai > 0 && ai <= 4)
+	if (ai > AI_NONE && ai <= AI_MAX)
 		mob.state.ai = ai;
 
 	if (mob.num > 1 && battle_config.mob_count_rate != 100) {

+ 5 - 8
src/map/pc.c

@@ -519,7 +519,7 @@ int pc_makesavestatus(struct map_session_data *sd)
 	if(!battle_config.save_clothcolor)
 		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]
 #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);
@@ -4044,7 +4044,7 @@ int pc_takeitem(struct map_session_data *sd,struct flooritem_data *fitem)
 		}
 		else
 		if(fitem->second_get_charid > 0 && fitem->second_get_charid != sd->status.char_id)
-	  	{
+		{
 			second_sd = map_charid2sd(fitem->second_get_charid);
 			if(DIFF_TICK(tick, fitem->second_get_tick) < 0) {
 				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){
 		unit_remove_map_pc(sd,clrtype);
 		clif_changemap(sd,map[m].index,x,y); // [MouseJstr]
-	} else if(sd->state.active)
-		//Tag player for rewarping after map-loading is done. [Skotlex]
+	} else if(sd->state.active) //Tag player for rewarping after map-loading is done. [Skotlex]
 		sd->state.rewarp = 1;
 
 	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);
 	if(sd) pc_close_npc(sd,data);
-
 	return 0;
 }
-
 /*
  *  Method to properly close npc for player and clear anything related
  * @flag == 1 : produce close button
@@ -7815,7 +7812,7 @@ int pc_setcart(struct map_session_data *sd,int type) {
 				clif_cartlist(sd);
 			clif_updatestatus(sd, SP_CARTINFO);
 			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 */
 				sd->sc.data[SC_PUSH_CART]->val1 = type;
 			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)
 {
 	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]
 		sd->state.night = night_flag;
 		return 1;

+ 8 - 8
src/map/pet.c

@@ -64,7 +64,7 @@ void pet_set_intimate(struct pet_data *pd, int value)
 
 	nullpo_retv(pd);
 	intimate = pd->pet.intimate;
-	sd = pd->msd;
+	sd = pd->master;
 
 	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) )
@@ -135,7 +135,7 @@ int pet_target_check(struct map_session_data *sd,struct block_list *bl,int type)
 
 	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 ||
 		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);
 
-	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) {
 		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.id = npc_get_new_npc_id();
 
-	pd->msd = sd;
+	pd->master = sd;
 	pd->petDB = &pet_db[i];
 	pd->db = mob_db(pet->class_);
 	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);
 
-	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) {
 		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_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;
 }
@@ -791,7 +791,7 @@ static int pet_randomwalk(struct pet_data *pd,unsigned int tick)
 {
 	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)) {
 		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;
 
-	if(sd_charid && sd_charid != pd->msd->status.char_id)
+	if(sd_charid && sd_charid != pd->master->status.char_id)
 		return 0;
 
 	if(unit_can_reach_bl(&pd->bl,bl, pd->db->range2, 1, NULL, NULL) &&

+ 2 - 1
src/map/pet.h

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

+ 1 - 1
src/map/script.c

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

+ 24 - 23
src/map/skill.c

@@ -919,17 +919,13 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint
 		break;
 
 	case MG_FROSTDIVER:
-#ifndef RENEWAL
-	case WZ_FROSTNOVA:
-#endif
-		sc_start(src,bl,SC_FREEZE,skill_lv*3+35,skill_lv,skill_get_time2(skill_id,skill_lv));
+		if(!sc_start(src,bl,SC_FREEZE,skill_lv*3+35,skill_lv,skill_get_time2(skill_id,skill_lv)))
+			clif_skill_fail(sd,skill_id,0,0);
 		break;
 
-#ifdef RENEWAL
 	case WZ_FROSTNOVA:
 		sc_start(src,bl,SC_FREEZE,skill_lv*5+33,skill_lv,skill_get_time2(skill_id,skill_lv));
 		break;
-#endif
 
 	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 (inf&INF_SELF_SKILL || inf&INF_SUPPORT_SKILL) {
 					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;
 					unit_skilluse_id(src, bl->id, abra_skill_id, abra_skill_lv);
 				} 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:
 		//Self Destruction hits everyone in range (allies+enemies)
 		//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;
 		clif_skill_nodamage(src, src, skill_id, -1, 1);
 		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 (inf&INF_SELF_SKILL || inf&INF_SUPPORT_SKILL) {
 					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;
 					unit_skilluse_id(src, bl->id, improv_skill_id, improv_skill_lv);
 				} 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);
 			if (sum_md) {
 				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)
 					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);
@@ -9496,7 +9492,16 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data)
 			}
 			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( !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
 				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) )
 			break;
 
-		if (ud->state.running && ud->skill_id == TK_JUMPKICK)
-		{
-		    ud->state.running = 0;
-		    status_change_end(src, SC_RUN, INVALID_TIMER);
-				flag = 1;
+		if (ud->state.running && ud->skill_id == TK_JUMPKICK){
+			ud->state.running = 0;
+			status_change_end(src, SC_RUN, INVALID_TIMER);
+			flag = 1;
 		}
 
 		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] &&
 				sc->data[SC_SPIRIT]->val2 == SL_WIZARD &&
 				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.
 
 			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.
 	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
 		skill_consume_requirement(sd,ud->skill_id, ud->skill_lv,1);
 		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,
 									 -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};
-						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,
 									 -4,-5,-6,-4,-5,-6,-4,-5,-6};
 						skill_unit_layout[pos].count = 53;

+ 35 - 26
src/map/status.c

@@ -2014,7 +2014,7 @@ int status_calc_mob_(struct mob_data* md, bool first)
 	if (battle_config.slaves_inherit_speed && md->master_id)
 		flag|=8;
 
-	if (md->master_id && md->special_state.ai>1)
+	if (md->master_id && md->special_state.ai>AI_ATTACK)
 		flag|=16;
 
 	if (!flag)
@@ -2050,28 +2050,28 @@ int status_calc_mob_(struct mob_data* md, bool first)
 		struct unit_data *ud = unit_bl2ud(mbl);
 		//Remove special AI when this is used by regular mobs.
 		if (mbl->type == BL_MOB && !((TBL_MOB*)mbl)->special_state.ai)
-			md->special_state.ai = 0;
+			md->special_state.ai = AI_NONE;
 		if (ud)
 		{	// different levels of HP according to skill level
 			switch(ud->skill_id){
 				case AM_SPHEREMINE:
-				    status->max_hp = 2000 + 400*ud->skill_lv;
-				    break;
+					status->max_hp = 2000 + 400*ud->skill_lv;
+					break;
 				case KO_ZANZOU:
-				    status->max_hp = 3000 + 3000 * ud->skill_lv;
-				    break;
+					status->max_hp = 3000 + 3000 * ud->skill_lv;
+					break;
 				case AM_CANNIBALIZE:
-				    status->max_hp = 1500 + 200*ud->skill_lv + 10*status_get_lv(mbl);
-				    status->mode|= MD_CANATTACK|MD_AGGRESSIVE;
-				    break;
+					status->max_hp = 1500 + 200*ud->skill_lv + 10*status_get_lv(mbl);
+					status->mode|= MD_CANATTACK|MD_AGGRESSIVE;
+					break;
 				case MH_SUMMON_LEGION:{
-				    int homblvl = status_get_lv(mbl);
-				    status->max_hp = 10 * (100 * (ud->skill_lv + 2) + homblvl);
-				    status->batk = 100 * (ud->skill_lv+5) / 2;
-				    status->def = 10 * (100 * (ud->skill_lv+2) + homblvl);
-				//    status->aspd_rate = 10 * (2 * (20 - ud->skill_lv) - homblvl/10);
-				//    status->aspd_rate = max(100,status->aspd_rate);
-				    break;
+					int homblvl = status_get_lv(mbl);
+					status->max_hp = 10 * (100 * (ud->skill_lv + 2) + homblvl);
+					status->batk = 100 * (ud->skill_lv+5) / 2;
+					status->def = 10 * (100 * (ud->skill_lv+2) + homblvl);
+					//    status->aspd_rate = 10 * (2 * (20 - ud->skill_lv) - homblvl/10);
+					//    status->aspd_rate = max(100,status->aspd_rate);
+					break;
 				}
 			}
 			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;
 
 		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;
 		md->battle_status.hp = merc->hp;
 		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);
@@ -3287,6 +3289,9 @@ int status_calc_elemental_(struct elemental_data *ed, bool first) {
 		status->flee = ele->flee;
 		status->hit = ele->hit;
 
+		if (ed->master)
+			status->speed = status_get_speed(&ed->master->bl);
+
 		memcpy(&ed->battle_status,status,sizeof(struct status_data));
 	} else {
 		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
 		//because if you step on something while walking, the moment this
 		//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;
 
 		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)
 			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:
 			return ((TBL_PC*)bl)->status.party_id;
 		case BL_PET:
-			if (((TBL_PET*)bl)->msd)
-				return ((TBL_PET*)bl)->msd->status.party_id;
+			if (((TBL_PET*)bl)->master)
+				return ((TBL_PET*)bl)->master->status.party_id;
 			break;
 		case BL_MOB: {
 				struct mob_data *md=(TBL_MOB*)bl;
@@ -5942,8 +5951,8 @@ int status_get_guild_id(struct block_list *bl) {
 		case BL_PC:
 			return ((TBL_PC*)bl)->status.guild_id;
 		case BL_PET:
-			if (((TBL_PET*)bl)->msd)
-				return ((TBL_PET*)bl)->msd->status.guild_id;
+			if (((TBL_PET*)bl)->master)
+				return ((TBL_PET*)bl)->master->status.guild_id;
 			break;
 		case BL_MOB: {
 				struct map_session_data *msd;
@@ -5982,8 +5991,8 @@ int status_get_emblem_id(struct block_list *bl) {
 		case BL_PC:
 			return ((TBL_PC*)bl)->guild_emblem_id;
 		case BL_PET:
-			if (((TBL_PET*)bl)->msd)
-				return ((TBL_PET*)bl)->msd->guild_emblem_id;
+			if (((TBL_PET*)bl)->master)
+				return ((TBL_PET*)bl)->master->guild_emblem_id;
 			break;
 		case BL_MOB: {
 				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
 				val4 = (type == SC_DPOISON) ? 2 + status->max_hp/100 : 2 + status->max_hp/200;
 			break;
-			
+
 		case SC_CONFUSION:
 			clif_emotion(bl,E_WHAT);
 			break;

+ 99 - 48
src/map/unit.c

@@ -112,16 +112,92 @@ int unit_walktoxy_sub(struct block_list *bl)
 	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 x,y,dx,dy;
 	uint8 dir;
 	struct block_list       *bl;
-	struct map_session_data *sd;
-	struct mob_data         *md;
 	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);
 	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);
 	md = BL_CAST(BL_MOB, 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);
 
 	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;
 
 	if(sd) {
+		struct block_list *sbl; //slave bl
 		if( sd->touching_id )
 			npc_touchnext_areanpc(sd,false);
 		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
 			sd->areanpc_id=0;
 
-		if( sd->md && !check_distance_bl(&sd->bl, &sd->md->bl, MAX_MER_DISTANCE) )
-		{
-			// mercenary should be warped after being 3 seconds too far from the master [greenbox]
-			if (sd->md->masterteleport_timer == 0)
-			{
-				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;
-		}
+		if( sd->md) unit_check_start_teleport_timer(&sd->md->bl);
+		if( sd->ed) unit_check_start_teleport_timer(&sd->ed->bl);
+		if( sd->hd) unit_check_start_teleport_timer(&sd->hd->bl);
+		if( sd->pd) unit_check_start_teleport_timer(&sd->pd->bl);
 	} else if (md) {
 		if( map_getcell(bl->m,x,y,CELL_CHKNPC) ) {
 			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 &&
 			!(ud->walk_count%WALK_SKILL_INTERVAL) &&
 			mobskill_use(md, tick, -1))
-	  	{
+		{
 			if (!(ud->skill_id == NPC_SELFDESTRUCTION && ud->skilltimer != INVALID_TIMER))
 			{	//Skill used, abort walking
 				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);
 		}
 	}
-	else if( mrd && mrd->master )
-	{
-		if (!check_distance_bl(&mrd->master->bl, bl, MAX_MER_DISTANCE))
-		{
-			// 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;
-		}
-	}
+	else if( hd) unit_check_start_teleport_timer(&hd->bl);
+	else if( ed) unit_check_start_teleport_timer(&ed->bl);
+	else if( pd) unit_check_start_teleport_timer(&pd->bl);
+	else if( mrd) unit_check_start_teleport_timer(&mrd->bl);
 
 	if(tid == INVALID_TIMER) //A directly invoked timer is from battle_stop_walking, therefore the rest is irrelevant.
 		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)
-  	{	//Random map position.
+	{	//Random map position.
 		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);
 			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);
 
 		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);
 			return 2;
 		}
@@ -2187,7 +2237,7 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file,
 		}
 		case BL_PET: {
 			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
 				clif_clearunit_area(bl,clrtype);
 				map_delblock(bl);
@@ -2350,7 +2400,7 @@ int unit_free(struct block_list *bl, clr_type clrtype)
 		case BL_PET:
 		{
 			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);
 			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_delay_walktoxy_timer,"unit_delay_walktoxy_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;
 }