Browse Source

- Added new flag to skill_castnodex.txt, to allow per-skill tweaking of cast time and delay reducibility by item scripts (cards and such)
- Fixed Martyr's Reckoning never triggering for gms with all skills
- Added MO_TRIPLEATTACK and RG_SNATCHER to @skillall's skill filter
- Made gm_skill_unconditional bypass skill blocking (guild timer, etc)
- Reverted the weird delay_dependon_agi thing (r8923, r9055, r9059)
- Changed a few memsets to strncpy (reading past buffer is a bad idea)
- Sped up some memset operations (multiples of 4 are faster)

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@10613 54d463be-8e91-2dee-dedb-b68131a5f0ec

ultramage 18 years ago
parent
commit
301d493855

+ 8 - 0
Changelog-Trunk.txt

@@ -4,6 +4,14 @@ AS OF SVN REV. 5091, WE ARE NOW USING TRUNK.  ALL UNTESTED BUGFIXES/FEATURES GO
 IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
 
 2007/05/23
+	* Added new flag to skill_castnodex.txt, to allow per-skill tweaking 
+	  of cast time and delay reducibility by item scripts (cards and such)
+	* Fixed Martyr's Reckoning never triggering for gms with all skills
+	* Added MO_TRIPLEATTACK and RG_SNATCHER to @skillall's skill filter 
+	* Made gm_skill_unconditional bypass skill blocking (guild timer, etc)
+	* Reverted the weird delay_dependon_agi thing (r8923, r9055, r9059)
+	* Changed a few memsets to strncpy (reading past buffer is a bad idea)
+	* Sped up some memset operations (multiples of 4 are faster)
 	* Fixed a typo in Chase Walk code, /thx to zephyrus_cr [ultramage]
 2007/05/22
 	* Updated sql files [Playtester]

+ 2 - 0
conf-tmpl/Changelog.txt

@@ -1,5 +1,7 @@
 Date	Added
 
+2007/05/23
+	* Reverted delay_dependon_agi -> delay_dependon_dex
 2007/05/19
 	* Enhanced log_athena.conf with global/main chat support [ultramage]
 	- also changed the filter bit values, please reconfigure this option

+ 4 - 6
conf-tmpl/battle/skill.conf

@@ -31,9 +31,9 @@ casting_rate: 100
 // Delay time after casting (Note 2)
 delay_rate: 100
 
-// Is the delay time dependant on the caster's AGI? (Note 1)
-// Note: On Official servers no stat affects delay time
-delay_dependon_agi: no
+// Is the delay time is dependent on the caster's DEX? (Note 1)
+// Note: On Official servers Dex does NOT affect delay time
+delay_dependon_dex: no
 
 // Minimum allowed delay for ANY skills after casting (in miliseconds) (Note 1)
 // Note: Setting this to anything above 0 can stop speedhacks.
@@ -53,9 +53,7 @@ default_skill_delay: 300
 //  min_skill_delay_limit.
 no_skill_delay: 2
 
-// At what dex does the cast time become zero (instacast)
-// If delay_dependon_agi is enabled, this is also the amount of agi required 
-// for zero delay on skills.
+// At what dex does the cast time become zero (instacast)?
 castrate_dex_scale: 150
 
 // Will normal attacks be able to ignore the delay after skills? (Note 1)

+ 26 - 20
db/skill_castnodex_db.txt

@@ -1,31 +1,37 @@
-//<Skill id>,<Cast: 1 or 0>,<Delay (Optional): 1 or 0>
-// Cast: With 1, dex does not affect the skill's cast rate
-// Cast: With 2, cast-rate cannot be reduced by Suffragium and the like
-// Cast: With 3, same effect as 1 + 2
-// Cast: With 0, dex affects the skill's cast rate
-// Delay: With 1, agi does not affect the skill's delay rate
-// Delay: With 2, delay cannot be reduced by Suffragium and the like
-// Delay: With 0, agi affects the skill's delay rate
-// Example - 46,1,1 = Double Strafe's casting time and delay is not affected by dex/agi.
-// By default, agi NEVER affects after-cast delay, so no need of putting 'x,0,1' in this file
-263,0,2 //MO_TRIPLEATTACK
-272,0,2 //MO_CHAINCOMBO
-273,0,2 //MO_COMBOFINISH
+// <Skill id>,<Cast>,<Delay (optional)>
+//
+// Cast:  0 - everything affects the skill's cast time
+//        1 - skill's cast time is not affected by dex
+//        2 - skill's cast time is not affected by statuses (Suffragium, etc)
+//        4 - skill's cast time cannot be reduced by items (equip, cards, etc)
+//
+// Delay: 0 - everything affects the skill's delay
+//        1 - skill's delay is not affected by dex
+//        2 - skill's delay cannot be reduced by statuses (Magic Strings, etc)
+//        4 - skill's delay cannot be reduced by items (equip, cards, etc)
+//
+// Note: Values are bit fields, add them up to combine their effects.
+// Note: Delay setting 2 only makes sense when delay_dependon_dex is enabled.
+// Example: 46,1,1 = Double Strafe's cast time and delay is not affected by dex.
+
+263,0,2	//MO_TRIPLEATTACK
+272,0,2	//MO_CHAINCOMBO
+273,0,2	//MO_COMBOFINISH
 336,1	//WE_CALLPARTNER
 366,1	//HW_MAGICPOWER
 370,1	//CH_PALMSTRIKE
-371,0,2 //CH_TIGERFIST
-372,0,2 //CH_CHAINCRUSH
+371,0,2	//CH_TIGERFIST
+372,0,2	//CH_CHAINCRUSH
 403,3	//PF_MEMORIZE
 408,1	//WE_BABY
 409,1	//WE_CALLPARENT
 410,1	//WE_CALLBABY
 482,1	//PF_DOUBLECASTING
-462,1 //SL_KAIZEL
-496,1 //AM_TWILIGHT1
-497,1 //AM_TWILIGHT2
-498,1 //AM_TWILIGHT3
-512,3 //GS_TRACKING
+462,1	//SL_KAIZEL
+496,1	//AM_TWILIGHT1
+497,1	//AM_TWILIGHT2
+498,1	//AM_TWILIGHT3
+512,3	//GS_TRACKING
 1014,1	//PR_REDEMPTIO
 10010,3	//GD_BATTLEORDER
 10011,3	//GD_REGENERATION

+ 19 - 18
src/char/char.c

@@ -43,7 +43,7 @@
 #include <stdlib.h>
 
 #ifndef TXT_SQL_CONVERT
-struct mmo_map_server{
+struct mmo_map_server {
 	uint32 ip;
 	uint16 port;
 	int users;
@@ -57,16 +57,16 @@ char passwd[24];
 char server_name[20];
 char wisp_server_name[NAME_LENGTH] = "Server";
 char login_ip_str[128];
-uint32 login_ip;
+uint32 login_ip = 0;
 uint16 login_port = 6900;
 char char_ip_str[128];
-uint32 char_ip;
+uint32 char_ip = 0;
 char bind_ip_str[128];
 uint32 bind_ip = INADDR_ANY;
 uint16 char_port = 6121;
-int char_maintenance;
-int char_new;
-int char_new_display;
+int char_maintenance = 0;
+int char_new = 1;
+int char_new_display = 0;
 int email_creation = 0; // disabled by default
 #endif
 char char_txt[1024]="save/athena.txt";
@@ -364,7 +364,7 @@ void set_char_offline(int char_id, int account_id)
 			character->waiting_disconnect = -1;
 		}
 	}
-
+	
 	if (login_fd > 0 && !session[login_fd]->eof)
 	{
 		WFIFOHEAD(login_fd,6);
@@ -652,7 +652,7 @@ int mmo_char_fromstr(char *str, struct mmo_charstatus *p, struct global_reg *reg
 		tmp_int[46] = mapindex_name2id(tmp_str[2]);
 	}	// Char structure of version 1500 (homun + mapindex maps)
 
-	memcpy(p->name, tmp_str[0], NAME_LENGTH-1); //Overflow protection [Skotlex]
+	memcpy(p->name, tmp_str[0], NAME_LENGTH); //Overflow protection [Skotlex]
 	p->char_id = tmp_int[0];
 	p->account_id = tmp_int[1];
 	p->char_num = tmp_int[2];
@@ -1946,7 +1946,7 @@ int parse_tologin(int fd)
 	struct char_session_data *sd;
 
 	// only login-server can have an access to here.
-	// so, if it isn't the login-server, we disconnect the session (fd != login_fd).
+	// so, if it isn't the login-server, we disconnect the session.
 	if (fd != login_fd)
 		set_eof(fd);
 	if(session[fd]->eof) {
@@ -2360,7 +2360,7 @@ int parse_tologin(int fd)
 					if (GM_num == 0) {
 						gm_account = (struct gm_account*)aMalloc(sizeof(struct gm_account));
 					} else {
-						gm_account = (struct gm_account*)aRealloc(gm_account, sizeof(struct gm_account) * (GM_num + 1));						
+						gm_account = (struct gm_account*)aRealloc(gm_account, sizeof(struct gm_account) * (GM_num + 1));
 					}
 					gm_account[GM_num].account_id = RFIFOL(fd,2);
 					gm_account[GM_num].level = (int)RFIFOB(fd,6);
@@ -3005,7 +3005,7 @@ int parse_frommap(int fd)
 		{
 			char character_name[NAME_LENGTH];
 			int acc = RFIFOL(fd,2); // account_id of who ask (-1 if nobody)
-			memcpy(character_name, RFIFOP(fd,6), NAME_LENGTH-1);
+			memcpy(character_name, RFIFOP(fd,6), NAME_LENGTH);
 			character_name[NAME_LENGTH-1] = '\0';
 			// prepare answer
 			WFIFOHEAD(fd,34);
@@ -3155,7 +3155,7 @@ int parse_frommap(int fd)
 
 			// Find the position where the player has to be inserted
 			for(i = 0; i < size && fame < list[i].fame; i++);
-			if(i >= size) break;//Out of ranking.
+			if(i >= size) break; //Out of ranking.
 			// When found someone with less or as much fame, insert just above
 			memmove(list+i+1, list+i, (size-i-1) * sizeof(struct fame_list));
 			list[i].id = cid;
@@ -3190,7 +3190,7 @@ int parse_frommap(int fd)
 			set_all_offline(id);
 			RFIFOSKIP(fd,2);
 		break;
-
+		
 		case 0x2b19: // Character set online [Wizputer]
 			if (RFIFOREST(fd) < 6)
 				return 0;
@@ -3239,8 +3239,8 @@ int parse_frommap(int fd)
 		break;
 
 		default:
-			// inter server - packet
 		{
+			// inter server - packet
 			int r = inter_parse_frommap(fd);
 			if (r == 1) break;		// processed
 			if (r == 2) return 0;	// need more packet
@@ -3252,6 +3252,7 @@ int parse_frommap(int fd)
 		}
 		} // switch
 	} // while
+	
 	return 0;
 }
 
@@ -3566,7 +3567,7 @@ int parse_char(int fd)
 			if (i < 0)
 			{
 				WFIFOHEAD(fd,3);
-				WFIFOW(fd, 0) = 0x6e;
+				WFIFOW(fd,0) = 0x6e;
 				switch (i) {
 				case -1: WFIFOB(fd,2) = 0x00; break;
 				case -2: WFIFOB(fd,2) = 0x02; break;
@@ -3891,7 +3892,7 @@ static int send_accounts_tologin_sub(DBKey key, void* data, va_list ap)
 		return 0; //This is an error that shouldn't happen....
 	if(character->server > -1) {
 		WFIFOHEAD(login_fd,8+count*4);
-		WFIFOL(login_fd, 8+(*i)*4) =character->account_id;
+		WFIFOL(login_fd,8+(*i)*4) = character->account_id;
 		(*i)++;
 		return 1;
 	}
@@ -3939,7 +3940,7 @@ int check_connect_login_server(int tid, unsigned int tick, int id, int data)
 	memcpy(WFIFOP(login_fd,60), server_name, 20);
 	WFIFOW(login_fd,80) = 0;
 	WFIFOW(login_fd,82) = char_maintenance;
-	WFIFOW(login_fd,84) = char_new_display; //only display (New) if they want to [Kevin]	
+	WFIFOW(login_fd,84) = char_new_display; //only display (New) if they want to [Kevin]
 	WFIFOSET(login_fd,86);
 	
 	return 1;
@@ -4206,7 +4207,7 @@ int char_config_read(const char *cfgName)
 	}
 	fclose(fp);
 
-	ShowInfo("done reading %s.\n", cfgName);
+	ShowInfo("Done reading %s.\n", cfgName);
 	return 0;
 }
 

+ 11 - 11
src/char/int_guild.c

@@ -123,8 +123,8 @@ int inter_guild_fromstr(char *str, struct guild *g) {
 #ifndef TXT_SQL_CONVERT
 	g->castle_id = tmp_int[5];
 #endif
-	memcpy(g->name, tmp_str[0], NAME_LENGTH-1);
-	memcpy(g->master, tmp_str[1], NAME_LENGTH-1);
+	memcpy(g->name, tmp_str[0], NAME_LENGTH);
+	memcpy(g->master, tmp_str[1], NAME_LENGTH);
 	memcpy(g->mes1, tmp_str[2], 60);
 	memcpy(g->mes2, tmp_str[3], 120);
 	g->mes1[strlen(g->mes1)-1] = 0;
@@ -152,7 +152,7 @@ int inter_guild_fromstr(char *str, struct guild *g) {
 		m->exp = exp;
 		m->exp_payper = tmp_int[8];
 		m->position = tmp_int[9];
-		memcpy(m->name, tmp_str[0], NAME_LENGTH-1);
+		memcpy(m->name, tmp_str[0], NAME_LENGTH);
 
 		for(j = 0; j < 2 && str != NULL; j++)	// 位置スキップ
 			str = strchr(str + 1, '\t');
@@ -167,7 +167,7 @@ int inter_guild_fromstr(char *str, struct guild *g) {
 		p->mode = tmp_int[0];
 		p->exp_mode = tmp_int[1];
 		tmp_str[0][strlen(tmp_str[0])-1] = 0;
-		memcpy(p->name, tmp_str[0], NAME_LENGTH-1);
+		memcpy(p->name, tmp_str[0], NAME_LENGTH);
 
 		for(j = 0; j < 2 && str != NULL; j++)	// 位置スキップ
 			str = strchr(str+1, '\t');
@@ -204,7 +204,7 @@ int inter_guild_fromstr(char *str, struct guild *g) {
 			return 1;
 		a->guild_id = tmp_int[0];
 		a->opposition = tmp_int[1];
-		memcpy(a->name, tmp_str[0], NAME_LENGTH-1);
+		memcpy(a->name, tmp_str[0], NAME_LENGTH);
 
 		for(j = 0; j < 2 && str != NULL; j++)	// 位置スキップ
 			str = strchr(str + 1, '\t');
@@ -224,7 +224,7 @@ int inter_guild_fromstr(char *str, struct guild *g) {
 		e->rsv1 = tmp_int[1];
 		e->rsv2 = tmp_int[2];
 		e->rsv3 = tmp_int[3];
-		memcpy(e->name, tmp_str[0], NAME_LENGTH-1);
+		memcpy(e->name, tmp_str[0], NAME_LENGTH);
 		memcpy(e->acc, tmp_str[1], 24);
 		tmp_str[2][strlen(tmp_str[2])-1] = 0;
 		memcpy(e->mes, tmp_str[2], 40);
@@ -980,8 +980,8 @@ int mapif_parse_CreateGuild(int fd, int account_id, char *name, struct guild_mem
 	}
 //	memset(g, 0, sizeof(struct guild)); Meh...
 	g->guild_id = guild_newid++;
-	memcpy(g->name, name, NAME_LENGTH-1);
-	memcpy(g->master, master->name, NAME_LENGTH-1);
+	memcpy(g->name, name, NAME_LENGTH);
+	memcpy(g->master, master->name, NAME_LENGTH);
 	memcpy(&g->member[0], master, sizeof(struct guild_member));
 
 	g->position[0].mode = 0x11;
@@ -1071,8 +1071,8 @@ int mapif_parse_GuildLeave(int fd, int guild_id, int account_id, int char_id, in
 						j = MAX_GUILDEXPULSION - 1;
 					}
 					g->expulsion[j].account_id = account_id;
-					memcpy(g->expulsion[j].acc, "dummy", NAME_LENGTH-1);
-					memcpy(g->expulsion[j].name, g->member[i].name, NAME_LENGTH-1);
+					strncpy(g->expulsion[j].acc, "dummy", NAME_LENGTH);
+					memcpy(g->expulsion[j].name, g->member[i].name, NAME_LENGTH);
 					memcpy(g->expulsion[j].mes, mes, 40);
 				}
 
@@ -1344,7 +1344,7 @@ int mapif_parse_GuildAlliance(int fd, int guild_id1, int guild_id2, int account_
 			for(j = 0; j < MAX_GUILDALLIANCE; j++)
 				if (g[i]->alliance[j].guild_id == 0) {
 					g[i]->alliance[j].guild_id = g[1-i]->guild_id;
-					memcpy(g[i]->alliance[j].name, g[1-i]->name, NAME_LENGTH-1);
+					memcpy(g[i]->alliance[j].name, g[1-i]->name, NAME_LENGTH);
 					g[i]->alliance[j].opposition = flag & 1;
 					break;
 				}

+ 1 - 1
src/char/int_homun.c

@@ -68,7 +68,7 @@ int inter_homun_fromstr(char *str,struct s_homunculus *p)
 
 	p->hom_id = tmp_int[0];
 	p->class_ = tmp_int[1];
-	memcpy(p->name, tmp_str, NAME_LENGTH-1);
+	memcpy(p->name, tmp_str, NAME_LENGTH);
 
 	p->char_id = tmp_int[2];
   	p->hp = tmp_int[3];

+ 1 - 1
src/char/int_party.c

@@ -132,7 +132,7 @@ int inter_party_fromstr(char *str, struct party *p) {
 		return 1;
 
 	p->party_id = tmp_int[0];
-	memcpy(p->name, tmp_str, NAME_LENGTH-1);
+	memcpy(p->name, tmp_str, NAME_LENGTH);
 	p->exp = tmp_int[1]?1:0;
 	p->item = tmp_int[2];
 //	printf("%d [%s] %d %d\n", tmp_int[0], tmp_str[0], tmp_int[1], tmp_int[2]);

+ 2 - 2
src/char/int_pet.c

@@ -58,7 +58,7 @@ int inter_pet_fromstr(char *str,struct s_pet *p)
 
 	p->pet_id = tmp_int[0];
 	p->class_ = tmp_int[1];
-	memcpy(p->name,tmp_str,NAME_LENGTH-1);
+	memcpy(p->name,tmp_str,NAME_LENGTH);
 	p->account_id = tmp_int[2];
 	p->char_id = tmp_int[3];
 	p->level = tmp_int[4];
@@ -234,7 +234,7 @@ int mapif_create_pet(int fd,int account_id,int char_id,short pet_class,short pet
 	}
 //	memset(p,0,sizeof(struct s_pet)); unnecessary after aCalloc [Skotlex]
 	p->pet_id = pet_newid++;
-	memcpy(p->name,pet_name,NAME_LENGTH-1);
+	memcpy(p->name,pet_name,NAME_LENGTH);
 	if(incuvate == 1)
 		p->account_id = p->char_id = 0;
 	else {

+ 27 - 27
src/char_sql/char.c

@@ -70,13 +70,12 @@ int lowest_gm_level = 1;
 
 char *SQL_CONF_NAME = "conf/inter_athena.conf";
 
-struct mmo_map_server{
-  uint32 ip;
-  uint16 port;
-  int users;
-  unsigned short map[MAX_MAP_PER_SERVER];
+struct mmo_map_server {
+	uint32 ip;
+	uint16 port;
+	int users;
+	unsigned short map[MAX_MAP_PER_SERVER];
 } server[MAX_MAP_SERVERS];
-
 int server_fd[MAX_MAP_SERVERS];
 
 int login_fd, char_fd;
@@ -93,10 +92,11 @@ char bind_ip_str[128];
 uint32 bind_ip = INADDR_ANY;
 uint16 char_port = 6121;
 int char_maintenance = 0;
-int char_new;
-int char_new_display;
+int char_new = 1;
+int char_new_display = 0;
 int name_ignoring_case = 0; // Allow or not identical name for characters but with a different case by [Yor]
 int char_name_option = 0; // Option to know which letters/symbols are authorised in the name of a character (0: all, 1: only those in char_name_letters, 2: all EXCEPT those in char_name_letters) by [Yor]
+char unknown_char_name[NAME_LENGTH] = "Unknown";
 char char_name_letters[1024] = ""; // list of letters/symbols used to authorise or not a name of a character. by [Yor]
 //The following are characters that are trimmed regardless because they cause confusion and problems on the servers. [Skotlex]
 #define TRIM_CHARS "\032\t\x0A\x0D "
@@ -116,7 +116,6 @@ struct _subnet {
 
 int subnet_count = 0;
 
-char unknown_char_name[NAME_LENGTH] = "Unknown";
 char db_path[1024]="db";
 
 //These are used to aid the map server in identifying valid clients. [Skotlex]
@@ -185,8 +184,6 @@ struct online_char_data {
 
 struct dbt *online_char_db; //Holds all online characters.
 
-static int chardb_waiting_disconnect(int tid, unsigned int tick, int id, int data);
-
 static void * create_online_char_data(DBKey key, va_list args)
 {
 	struct online_char_data* character;
@@ -199,6 +196,8 @@ static void * create_online_char_data(DBKey key, va_list args)
 	return character;
 }
 
+static int chardb_waiting_disconnect(int tid, unsigned int tick, int id, int data);
+
 //-------------------------------------------------
 // Set Character online/offline [Wizputer]
 //-------------------------------------------------
@@ -206,7 +205,7 @@ static void * create_online_char_data(DBKey key, va_list args)
 void set_char_online(int map_id, int char_id, int account_id)
 {
 	struct online_char_data* character;
-
+	
 	if ( char_id != 99 ) {
 		sprintf(tmp_sql, "UPDATE `%s` SET `online`='1' WHERE `char_id`='%d'",char_db,char_id);
 		if (mysql_query(&mysql_handle, tmp_sql)) {
@@ -1732,7 +1731,6 @@ int parse_tologin(int fd)
 	struct char_session_data *sd;
 	// only login-server can have an access to here.
 	// so, if it isn't the login-server, we disconnect the session.
-	//session eof check!
 	if(fd != login_fd)
 		set_eof(fd);
 	if(session[fd]->eof) {
@@ -2597,7 +2595,7 @@ int parse_frommap(int fd)
 			auth_fifo_pos++;
 			WFIFOHEAD(fd,7);
 			WFIFOW(fd,0) = 0x2b03;
-			WFIFOL(fd,2) = RFIFOL(fd, 2);
+			WFIFOL(fd,2) = RFIFOL(fd,2);
 			WFIFOB(fd,6) = 0;
 			WFIFOSET(fd,7);
 			RFIFOSKIP(fd,18);
@@ -2968,8 +2966,8 @@ int parse_frommap(int fd)
 		break;
 
 		default:
-		// inter server - packet
 		{
+			// inter server - packet
 			int r = inter_parse_frommap(fd);
 			if (r == 1) break;		// processed
 			if (r == 2) return 0;	// need more packet
@@ -2981,6 +2979,7 @@ int parse_frommap(int fd)
 		}
 		} // switch
 	} // while
+	
 	return 0;
 }
 
@@ -3223,7 +3222,7 @@ int parse_char(int fd)
 				char_dat.last_point.map = j;
 			}
 			{
-				//Send player to map.
+				//Send player to map
 				uint32 subnet_map_ip;
 				char map_name[MAP_NAME_LENGTH_EXT];
 				snprintf(map_name, MAP_NAME_LENGTH_EXT, "%s.gat", mapindex_id2name(char_dat.last_point.map));	
@@ -3252,11 +3251,11 @@ int parse_char(int fd)
 			//Send NEW auth packet [Kevin]
 			if ((map_fd = server_fd[i]) < 1 || session[map_fd] == NULL)
 			{	
-				WFIFOHEAD(fd,3);
 				ShowError("parse_char: Attempting to write to invalid session %d! Map Server #%d disconnected.\n", map_fd, i);
 				server_fd[i] = -1;
 				memset(&server[i], 0, sizeof(struct mmo_map_server));
 				//Send server closed.
+				WFIFOHEAD(fd,3);
 				WFIFOW(fd,0) = 0x81;
 				WFIFOB(fd,2) = 1; // 01 = Server closed
 				WFIFOSET(fd,3);
@@ -3276,7 +3275,7 @@ int parse_char(int fd)
 
 			set_char_online(i, auth_fifo[auth_fifo_pos].char_id, auth_fifo[auth_fifo_pos].account_id);
 			auth_fifo_pos++;
-			break;
+		break;
 
 		case 0x67:	// make new
 			FIFOSD_CHECK(37);
@@ -3317,7 +3316,7 @@ int parse_char(int fd)
 					break;
 				}
 			}
-			break;
+		break;
 
 		case 0x68:	// delete char
 			FIFOSD_CHECK(46);
@@ -3394,8 +3393,8 @@ int parse_char(int fd)
 			/* Char successfully deleted.*/
 			WFIFOW(fd,0) = 0x6f;
 			WFIFOSET(fd,2);
-			break;
 		}
+		break;
 
 		case 0x2af8: // login as map-server
 			if (RFIFOREST(fd) < 60)
@@ -3441,14 +3440,14 @@ int parse_char(int fd)
 				WFIFOW(fd,2) = len;
 				WFIFOSET(fd,len);
 			}
-			break;
 		}
+		break;
 
 		case 0x187:	// Alive?
 			if (RFIFOREST(fd) < 6)
 				return 0;
 			RFIFOSKIP(fd, 6);
-			break;
+		break;
 
 		case 0x7530:	// Athena info get
 		{
@@ -3465,6 +3464,7 @@ int parse_char(int fd)
 			RFIFOSKIP(fd,2);
 			return 0;
 		}
+
 		case 0x7532:	// disconnect(default also disconnect)
 		default:
 			set_eof(fd);
@@ -3588,7 +3588,7 @@ static int send_accounts_tologin_sub(DBKey key, void* data, va_list ap)
 		return 0; //This is an error that shouldn't happen....
 	if(character->server > -1) {
 		WFIFOHEAD(login_fd,8+count*4);
-		WFIFOL(login_fd,8+(*i)*4) =character->account_id;
+		WFIFOL(login_fd,8+(*i)*4) = character->account_id;
 		(*i)++;
 		return 1;
 	}
@@ -3613,7 +3613,7 @@ int send_accounts_tologin(int tid, unsigned int tick, int id, int data)
 
 int check_connect_login_server(int tid, unsigned int tick, int id, int data)
 {
-	if (login_fd > 0 && session[login_fd] != NULL) 
+	if (login_fd > 0 && session[login_fd] != NULL)
 		return 0;
 
 	ShowInfo("Attempt to connect to login-server...\n");
@@ -3811,7 +3811,7 @@ void sql_config_read(const char *cfgName)
 
 	}
 	fclose(fp);
-	ShowInfo("done reading %s.\n", cfgName);
+	ShowInfo("Done reading %s.\n", cfgName);
 }
 #ifndef TXT_SQL_CONVERT
 
@@ -4098,11 +4098,11 @@ int do_init(int argc, char **argv)
 			ShowStatus("Defaulting to %s as our IP address\n", ip_str);
 		if (!login_ip) {
 			strcpy(login_ip_str, ip_str);
-			login_ip = ntohl(inet_addr(login_ip_str));
+			login_ip = str2ip(login_ip_str);
 		}
 		if (!char_ip) {
 			strcpy(char_ip_str, ip_str);
-			char_ip = ntohl(inet_addr(char_ip_str));
+			char_ip = str2ip(char_ip_str);
 		}
 	}
 

+ 3 - 6
src/char_sql/int_guild.c

@@ -1,9 +1,6 @@
 // Copyright (c) Athena Dev Teams - Licensed under GNU GPL
 // For more information, see LICENCE in the main folder
 
-// original code from athena
-// SQL conversion by hack
-
 #include <string.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -1439,8 +1436,8 @@ int mapif_parse_GuildLeave(int fd,int guild_id,int account_id,int char_id,int fl
 					}
 					// Save the expulsion
 					g->expulsion[j].account_id=account_id;
-					memcpy(g->expulsion[j].acc,"dummy",NAME_LENGTH-1);
-					memcpy(g->expulsion[j].name,g->member[i].name,NAME_LENGTH-1);
+					strncpy(g->expulsion[j].acc,"dummy",NAME_LENGTH);
+					memcpy(g->expulsion[j].name,g->member[i].name,NAME_LENGTH);
 					memcpy(g->expulsion[j].mes,mes,40);
 				}
 
@@ -1860,7 +1857,7 @@ int mapif_parse_GuildAlliance(int fd,int guild_id1,int guild_id2,
 				if(g[i]->alliance[j].guild_id==0)
 				{
 					g[i]->alliance[j].guild_id=g[1-i]->guild_id;
-					memcpy(g[i]->alliance[j].name,g[1-i]->name,NAME_LENGTH-1);
+					memcpy(g[i]->alliance[j].name,g[1-i]->name,NAME_LENGTH);
 					// Set alliance type
 					g[i]->alliance[j].opposition = flag&GUILD_ALLIANCE_TYPE_MASK;
 					break;

+ 1 - 1
src/char_sql/int_homun.c

@@ -147,7 +147,7 @@ int mapif_load_homunculus(int fd){
 
 		homun_pt->hom_id = RFIFOL(fd,6) ; //RFIFOL(fd,2);
 		homun_pt->class_ = atoi(sql_row[2]);
-		memcpy(homun_pt->name, sql_row[3],NAME_LENGTH-1);
+		strncpy(homun_pt->name, sql_row[3], NAME_LENGTH);
 		homun_pt->char_id = atoi(sql_row[1]);
 		homun_pt->level = atoi(sql_row[4]);
 		homun_pt->exp = atoi(sql_row[5]);

+ 1 - 4
src/char_sql/int_party.c

@@ -1,9 +1,6 @@
 // Copyright (c) Athena Dev Teams - Licensed under GNU GPL
 // For more information, see LICENCE in the main folder
 
-// original code from athena
-// SQL conversion by hack
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -247,7 +244,7 @@ struct party_data *inter_party_fromsql(int party_id)
 		return NULL;
 	}
 	p->party.party_id = party_id;
-	memcpy(&p->party.name, sql_row[1], NAME_LENGTH-1);
+	strncpy(&p->party.name, sql_row[1], NAME_LENGTH);
 	p->party.exp = atoi(sql_row[2])?1:0;
 	p->party.item = atoi(sql_row[3]);
 	leader_id = atoi(sql_row[4]);

+ 4 - 7
src/char_sql/int_pet.c

@@ -1,9 +1,6 @@
 // Copyright (c) Athena Dev Teams - Licensed under GNU GPL
 // For more information, see LICENCE in the main folder
 
-// original code from athena
-// SQL conversion by Jioh L. Jung
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -81,7 +78,7 @@ int inter_pet_fromsql(int pet_id, struct s_pet *p){
 
 		p->pet_id = pet_id;
 		p->class_ = atoi(sql_row[1]);
-		memcpy(p->name, sql_row[2],NAME_LENGTH-1);
+		strncpy(p->name, sql_row[2], NAME_LENGTH);
 		p->account_id = atoi(sql_row[3]);
 		p->char_id = atoi(sql_row[4]);
 		p->level = atoi(sql_row[5]);
@@ -192,10 +189,10 @@ int mapif_delete_pet_ack(int fd, int flag){
 }
 
 int mapif_create_pet(int fd, int account_id, int char_id, short pet_class, short pet_lv, short pet_egg_id,
-	short pet_equip, short intimate, short hungry, char rename_flag, char incuvate, char *pet_name){
-
+	short pet_equip, short intimate, short hungry, char rename_flag, char incuvate, char *pet_name)
+{
 	memset(pet_pt, 0, sizeof(struct s_pet));
-	memcpy(pet_pt->name, pet_name, NAME_LENGTH-1);
+	strncpy(pet_pt->name, pet_name, NAME_LENGTH);
 	if(incuvate == 1)
 		pet_pt->account_id = pet_pt->char_id = 0;
 	else {

+ 1 - 1
src/login_sql/login.c

@@ -1933,7 +1933,7 @@ void sql_config_read(const char* cfgName)
 			sql_config_read(w2);
 	}
 	fclose(fp);
-	ShowInfo("done reading %s.\n", cfgName);
+	ShowInfo("Done reading %s.\n", cfgName);
 }
 
 void login_set_defaults()

+ 10 - 7
src/map/battle.c

@@ -2778,6 +2778,7 @@ int battle_weapon_attack(struct block_list* src, struct block_list* target, unsi
 	struct status_data *sstatus, *tstatus;
 	struct status_change *sc, *tsc;
 	int damage,rdamage=0,rdelay=0;
+	int skillv;
 	struct Damage wd;
 
 	nullpo_retr(0, src);
@@ -2874,19 +2875,21 @@ int battle_weapon_attack(struct block_list* src, struct block_list* target, unsi
 			}
 		}
 	}
-	//Recycled the damage variable rather than use a new one... [Skotlex]
-	if(sd && (damage = pc_checkskill(sd,MO_TRIPLEATTACK)) > 0)
+
+	if(sd && (skillv = pc_checkskill(sd,MO_TRIPLEATTACK)) > 0)
 	{
-		int triple_rate= 30 - damage; //Base Rate
+		int triple_rate= 30 - skillv; //Base Rate
 		if (sc && sc->data[SC_SKILLRATE_UP].timer!=-1 && sc->data[SC_SKILLRATE_UP].val1 == MO_TRIPLEATTACK)
 		{
 			triple_rate+= triple_rate*(sc->data[SC_SKILLRATE_UP].val2)/100;
 			status_change_end(src,SC_SKILLRATE_UP,-1);
 		}
 		if (rand()%100 < triple_rate)
-			return skill_attack(BF_WEAPON,src,src,target,MO_TRIPLEATTACK,damage,tick,0);
+			return skill_attack(BF_WEAPON,src,src,target,MO_TRIPLEATTACK,skillv,tick,0);
 	}
-	else if (sc) {
+
+	if (sc)
+	{
 		if (sc->data[SC_SACRIFICE].timer != -1)
 			return skill_attack(BF_WEAPON,src,src,target,PA_SACRIFICE,sc->data[SC_SACRIFICE].val1,tick,0);
 		if (sc->data[SC_MAGICALATTACK].timer != -1)
@@ -3340,7 +3343,7 @@ static const struct battle_data_short {
 	{ "enable_perfect_flee",               &battle_config.enable_perfect_flee		},
 	{ "casting_rate",                      &battle_config.cast_rate				},
 	{ "delay_rate",                        &battle_config.delay_rate				},
-	{ "delay_dependon_agi",                &battle_config.delay_dependon_agi },
+	{ "delay_dependon_dex",                &battle_config.delay_dependon_dex },
 	{ "skill_delay_attack_enable",         &battle_config.sdelay_attack_enable		},
 	{ "left_cardfix_to_right",             &battle_config.left_cardfix_to_right	},
 	{ "skill_add_range",            			&battle_config.skill_add_range		},
@@ -3734,7 +3737,7 @@ void battle_set_defaults()
 	battle_config.enable_perfect_flee = BL_PC|BL_PET;
 	battle_config.cast_rate=100;
 	battle_config.delay_rate=100;
-	battle_config.delay_dependon_agi=0;
+	battle_config.delay_dependon_dex=0;
 	battle_config.sdelay_attack_enable=0;
 	battle_config.left_cardfix_to_right=0;
 	battle_config.skill_add_range=0;

+ 1 - 1
src/map/battle.h

@@ -94,7 +94,7 @@ extern struct Battle_Config {
 	unsigned short critical_rate;
 	unsigned short enable_baseatk;
 	unsigned short enable_perfect_flee;
-	unsigned short cast_rate,delay_rate,delay_dependon_agi;
+	unsigned short cast_rate,delay_rate,delay_dependon_dex;
 	unsigned short sdelay_attack_enable;
 	unsigned short left_cardfix_to_right;
 	unsigned short skill_add_range;

+ 1 - 1
src/map/charcommand.c

@@ -1349,7 +1349,7 @@ int charcommand_fakename(const int fd, struct map_session_data* sd, const char*
 		return 0;
 	}
 	
-	memcpy(pl_sd->fakename,name, NAME_LENGTH-1);
+	memcpy(pl_sd->fakename, name, NAME_LENGTH);
 	clif_charnameack(0, &pl_sd->bl);
 	clif_displaymessage(sd->fd,"Fake name enabled.");
 	

+ 1 - 1
src/map/chrif.c

@@ -668,7 +668,7 @@ int chrif_char_ask_name_answer(int fd)
 	char player_name[NAME_LENGTH];
 
 	acc = RFIFOL(fd,2); // account_id of who has asked (-1 if nobody)
-	memcpy(player_name, RFIFOP(fd,6), NAME_LENGTH-1);
+	memcpy(player_name, RFIFOP(fd,6), NAME_LENGTH);
 	player_name[NAME_LENGTH-1] = '\0';
 
 	sd = map_id2sd(acc);

+ 1 - 1
src/map/clif.c

@@ -10825,7 +10825,7 @@ void clif_parse_PMIgnore(int fd, struct map_session_data *sd)
 			return;
 		}
 		//Insert in position i
-		memcpy(sd->ignore[i].name, nick, NAME_LENGTH-1);
+		memcpy(sd->ignore[i].name, nick, NAME_LENGTH);
 		WFIFOB(fd,3) = 0; // success
 		WFIFOSET(fd, packet_len(0x0d1));
 		if (strcmp(wisp_server_name, nick) == 0)

+ 6 - 6
src/map/guild.c

@@ -182,9 +182,9 @@ static int guild_read_castledb(void)
 
 		gc=(struct guild_castle *)aCalloc(1,sizeof(struct guild_castle));
 		gc->castle_id=atoi(str[0]);
-		memcpy(gc->map_name,mapindex_normalize_name(str[1]),MAP_NAME_LENGTH-1);
-		memcpy(gc->castle_name,str[2],NAME_LENGTH-1);
-		memcpy(gc->castle_event,str[3],NAME_LENGTH-1);
+		memcpy(gc->map_name,mapindex_normalize_name(str[1]),MAP_NAME_LENGTH);
+		memcpy(gc->castle_name,str[2],NAME_LENGTH);
+		memcpy(gc->castle_event,str[3],NAME_LENGTH);
 
 		idb_put(castle_db,gc->castle_id,gc);
 
@@ -336,7 +336,7 @@ void guild_makemember(struct guild_member *m,struct map_session_data *sd)
 //	m->exp_payper	=0;
 	m->online		=1;
 	m->position		=MAX_GUILDPOSITION-1;
-	memcpy(m->name,sd->status.name,NAME_LENGTH-1);
+	memcpy(m->name,sd->status.name,NAME_LENGTH);
 	return;
 }
 // ƒMƒ‹ƒh‹£�‡Šm”F
@@ -1032,7 +1032,7 @@ int guild_change_position(int guild_id,int idx,
 	//Mode 0x10 <- Expel.
 	p.mode=mode&0x11;
 	p.exp_mode=exp_mode;
-	memcpy(p.name,name,NAME_LENGTH-1);
+	memcpy(p.name,name,NAME_LENGTH);
 	p.name[NAME_LENGTH-1] = '\0'; //Security check... [Skotlex]
 	return intif_guild_position(guild_id,idx,&p);
 }
@@ -1462,7 +1462,7 @@ int guild_allianceack(int guild_id1,int guild_id2,int account_id1,int account_id
 				for(j=0;j<MAX_GUILDALLIANCE;j++)
 					if(g[i]->alliance[j].guild_id==0){
 						g[i]->alliance[j].guild_id=guild_id[1-i];
-						memcpy(g[i]->alliance[j].name,guild_name[1-i],NAME_LENGTH-1);
+						memcpy(g[i]->alliance[j].name,guild_name[1-i],NAME_LENGTH);
 						g[i]->alliance[j].opposition=flag&1;
 						break;
 					}

+ 1 - 1
src/map/map.c

@@ -2464,7 +2464,7 @@ int map_addmap(char *mapname)
 		return 1;
 	}
 
-	memcpy(map[map_num].name, mapindex_normalize_name(mapname), MAP_NAME_LENGTH-1);
+	memcpy(map[map_num].name, mapindex_normalize_name(mapname), MAP_NAME_LENGTH);
 	map_num++;
 	return 0;
 }

+ 6 - 6
src/map/mob.c

@@ -204,7 +204,7 @@ struct mob_data* mob_spawn_dataset(struct spawn_data *data)
 	md->bl.y = data->y;
 	md->class_ = data->class_;
 	md->db = mob_db(md->class_);
-	memcpy(md->name, data->name, NAME_LENGTH-1);
+	memcpy(md->name, data->name, NAME_LENGTH);
 	if (data->state.ai)
 		md->special_state.ai = data->state.ai;
 	if (data->state.size)
@@ -2338,9 +2338,9 @@ int mob_class_change (struct mob_data *md, int class_)
 	md->class_ = class_;
 	md->db = mob_db(class_);
 	if (battle_config.override_mob_names==1)
-		memcpy(md->name,md->db->name,NAME_LENGTH-1);
+		memcpy(md->name,md->db->name,NAME_LENGTH);
 	else
-		memcpy(md->name,md->db->jname,NAME_LENGTH-1);
+		memcpy(md->name,md->db->jname,NAME_LENGTH);
 
 	mob_stop_attack(md);
 	mob_stop_walking(md, 0);
@@ -3210,9 +3210,9 @@ int mob_parse_dbrow(char** str)
 	status = &db->status;
 	
 	db->vd.class_ = class_;
-	memcpy(db->sprite, str[1], NAME_LENGTH-1);
-	memcpy(db->jname, str[2], NAME_LENGTH-1);
-	memcpy(db->name, str[3], NAME_LENGTH-1);
+	strncpy(db->sprite, str[1], NAME_LENGTH);
+	strncpy(db->jname, str[2], NAME_LENGTH);
+	strncpy(db->name, str[3], NAME_LENGTH);
 	db->lv = atoi(str[4]);
 	db->lv = cap_value(db->lv, 1, USHRT_MAX);
 	status->max_hp = atoi(str[5]);

+ 8 - 8
src/map/npc.c

@@ -464,7 +464,7 @@ int npc_addeventtimer(struct npc_data *nd,int tick,const char *name)
 		if(evname==NULL){
 			ShowFatalError("npc_addeventtimer: out of memory !\n");exit(1);
 		}
-		memcpy(evname,name,NAME_LENGTH-1);
+		strncpy(evname,name,NAME_LENGTH);
 		evname[NAME_LENGTH-1] = '\0';
 		nd->eventtimer[i]=add_timer(gettick()+tick,
 			npc_event_timer,nd->bl.id,(int)evname);
@@ -1660,8 +1660,8 @@ int npc_parse_warp (char *w1,char *w2,char *w3,char *w4)
 	nd->bl.m = m;
 	nd->bl.x = x;
 	nd->bl.y = y;
-	memcpy(nd->name, w3, NAME_LENGTH-1);
-	memcpy(nd->exname, w3, NAME_LENGTH-1);
+	strncpy(nd->name, w3, NAME_LENGTH);
+	strncpy(nd->exname, w3, NAME_LENGTH);
 
 	if (!battle_config.warp_point_debug)
 		nd->class_ = WARP_CLASS;
@@ -1761,7 +1761,7 @@ static int npc_parse_shop (char *w1, char *w2, char *w3, char *w4)
 	nd->bl.x = x;
 	nd->bl.y = y;
 	nd->bl.id = npc_get_new_npc_id();
-	memcpy(nd->name, w3, NAME_LENGTH-1);
+	memcpy(nd->name, w3, NAME_LENGTH);
 	nd->name[NAME_LENGTH-1] = '\0';
 	nd->class_ = m==-1?-1:atoi(w4);
 	nd->speed = 200;
@@ -2036,11 +2036,11 @@ static int npc_parse_script(char *w1,char *w2,char *w3,char *w4,char *first_line
 	}
 	if (p) {
 		*p = 0;
-		memcpy(nd->name, w3, NAME_LENGTH-1);
-		memcpy(nd->exname, p+2, NAME_LENGTH-1);
+		memcpy(nd->name, w3, NAME_LENGTH);
+		memcpy(nd->exname, p+2, NAME_LENGTH);
 	} else {
-		memcpy(nd->name, w3, NAME_LENGTH-1);
-		memcpy(nd->exname, w3, NAME_LENGTH-1);
+		memcpy(nd->name, w3, NAME_LENGTH);
+		memcpy(nd->exname, w3, NAME_LENGTH);
 	}
 
 	if((dnd = npc_name2id(nd->exname))){

+ 2 - 2
src/map/pc.c

@@ -4578,9 +4578,9 @@ int pc_allskillup(struct map_session_data *sd)
 	//pc_calc_skilltree takes care of setting the ID to valid skills. [Skotlex]
 	if (battle_config.gm_allskill > 0 && pc_isGM(sd) >= battle_config.gm_allskill)
 	{	//Get ALL skills except npc/guild ones. [Skotlex]
-		//and except SG_DEVIL [Komurka]
+		//and except SG_DEVIL [Komurka] and MO_TRIPLEATTACK and RG_SNATCHER [ultramage]
 		for(i=0;i<MAX_SKILL;i++){
-			if(!(skill_get_inf2(i)&(INF2_NPC_SKILL|INF2_GUILD_SKILL)) && i!=SG_DEVIL)
+			if(!(skill_get_inf2(i)&(INF2_NPC_SKILL|INF2_GUILD_SKILL)) && i!=SG_DEVIL && i!=MO_TRIPLEATTACK && i!=RG_SNATCHER)
 				sd->status.skill[i].lv=skill_get_max(i); //Nonexistant skills should return a max of 0 anyway.
 		}
 	}

+ 3 - 3
src/map/pet.c

@@ -709,7 +709,7 @@ int pet_change_name_ack(struct map_session_data *sd, char* name, int flag)
 		clif_send_petstatus(sd); //Send status so client knows oet name change got rejected.
 		return 0;
 	}
-	memcpy(pd->pet.name, name, NAME_LENGTH-1);
+	memcpy(pd->pet.name, name, NAME_LENGTH);
 	clif_charnameack (0,&pd->bl);
 	pd->pet.rename_flag = 1;
 	clif_pet_equip(pd);
@@ -1327,8 +1327,8 @@ int read_petdb()
 			}
 
 			pet_db[j].class_ = nameid;
-			memcpy(pet_db[j].name,str[1],NAME_LENGTH-1);
-			memcpy(pet_db[j].jname,str[2],NAME_LENGTH-1);
+			strncpy(pet_db[j].name,str[1],NAME_LENGTH);
+			strncpy(pet_db[j].jname,str[2],NAME_LENGTH);
 			pet_db[j].itemID=atoi(str[3]);
 			pet_db[j].EggID=atoi(str[4]);
 			pet_db[j].AcceID=atoi(str[5]);

+ 3 - 3
src/map/script.c

@@ -6132,7 +6132,7 @@ char *buildin_getpartyname_sub(int party_id)
 	if(p!=NULL){
 		char *buf;
 		buf=(char *)aMallocA(NAME_LENGTH*sizeof(char));
-		memcpy(buf, p->party.name, NAME_LENGTH-1);
+		memcpy(buf, p->party.name, NAME_LENGTH);
 		buf[NAME_LENGTH-1] = '\0';
 		return buf;
 	}
@@ -6248,7 +6248,7 @@ char *buildin_getguildname_sub(int guild_id)
 	if(g!=NULL){
 		char *buf;
 		buf=(char *)aMallocA(NAME_LENGTH*sizeof(char));
-		memcpy(buf, g->name, NAME_LENGTH-1);
+		memcpy(buf, g->name, NAME_LENGTH);
 		buf[NAME_LENGTH-1] = '\0';
 		return buf;
 	}
@@ -6277,7 +6277,7 @@ char *buildin_getguildmaster_sub(int guild_id)
 	if(g!=NULL){
 		char *buf;
 		buf=(char *)aMallocA(NAME_LENGTH*sizeof(char));
-		memcpy(buf, g->master, NAME_LENGTH-1);
+		memcpy(buf, g->master, NAME_LENGTH);
 		buf[NAME_LENGTH-1] = '\0';
 		return buf;
 	}

+ 24 - 23
src/map/skill.c

@@ -683,7 +683,7 @@ int	skill_get_maxcount( int id ){ skill_get (skill_db[id].maxcount, id, 1); }
 int	skill_get_blewcount( int id ,int lv ){ skill_get (skill_db[id].blewcount[lv-1], id, lv); }
 int	skill_get_mhp( int id ,int lv ){ skill_get (skill_db[id].mhp[lv-1], id, lv); }
 int	skill_get_castnodex( int id ,int lv ){ skill_get (skill_db[id].castnodex[lv-1], id, lv); }
-int	skill_get_delaynodex( int id ,int lv ){ skill_get (skill_db[id].delaynoagi[lv-1], id, lv); }
+int	skill_get_delaynodex( int id ,int lv ){ skill_get (skill_db[id].delaynodex[lv-1], id, lv); }
 int	skill_get_nocast ( int id ){ skill_get (skill_db[id].nocast, id, 1); }
 int	skill_get_type( int id ){ skill_get (skill_db[id].skill_type, id, 1); }
 int	skill_get_unit_id ( int id, int flag ){ skill_get (skill_db[id].unit_id[flag], id, 1); }
@@ -858,12 +858,12 @@ int skillnotok (int skillid, struct map_session_data *sd)
 	if (i > MAX_SKILL || i < 0)
 		return 1;
 	
-	if (sd->blockskill[i] > 0)
-		return 1;
-
 	if (battle_config.gm_skilluncond && pc_isGM(sd) >= battle_config.gm_skilluncond)
 		return 0;  // gm's can do anything damn thing they want
 
+	if (sd->blockskill[i] > 0)
+		return 1;
+
 	// Check skill restrictions [Celest]
 	if(!map_flag_vs(m) && skill_get_nocast (skillid) & 1)
 		return 1;
@@ -8671,7 +8671,7 @@ int skill_check_condition (struct map_session_data *sd, int skill, int lv, int t
 }
 
 /*==========================================
- * 
+ * Does cast-time reductions based on dex, item bonuses and config setting
  *------------------------------------------*/
 int skill_castfix (struct block_list *bl, int skill_id, int skill_lv)
 {
@@ -8689,9 +8689,10 @@ int skill_castfix (struct block_list *bl, int skill_id, int skill_lv)
 		else return 0;	// instant cast
 	}
 
-	// calculate cast time reduced by card bonuses
-	if (sd && sd->castrate != 100)
-		time = time * sd->castrate / 100;
+	// calculate cast time reduced by item/card bonuses
+	if (!(skill_get_castnodex(skill_id, skill_lv)&4))
+		if (sd && sd->castrate != 100)
+			time = time * sd->castrate / 100;
 
 	// config cast time multiplier
 	if (battle_config.cast_rate != 100)
@@ -8725,11 +8726,11 @@ int skill_castfix_sc (struct block_list *bl, int time)
 }
 
 /*==========================================
- *
+ * Does delay reductions based on dex, 
  *------------------------------------------*/
 int skill_delayfix (struct block_list *bl, int skill_id, int skill_lv)
 {
-	int delaynochange = skill_get_delaynodex(skill_id, skill_lv);
+	int delaynodex = skill_get_delaynodex(skill_id, skill_lv);
 	int time = skill_get_delay(skill_id, skill_lv);
 	
 	nullpo_retr(0, bl);
@@ -8756,9 +8757,9 @@ int skill_delayfix (struct block_list *bl, int skill_id, int skill_lv)
 		time -= 4*status_get_agi(bl) - 2*status_get_dex(bl);
 		break;
 	default:
-		if (battle_config.delay_dependon_agi && !(delaynochange&1))
-		{	// if skill casttime is allowed to be reduced by agi 
-			int scale = battle_config.castrate_dex_scale - status_get_agi(bl);
+		if (battle_config.delay_dependon_dex && !(delaynodex&1))
+		{	// if skill delay is allowed to be reduced by dex 
+			int scale = battle_config.castrate_dex_scale - status_get_dex(bl);
 			if (scale > 0)
 				time = time * scale / battle_config.castrate_dex_scale;
 			else //To be capped later to minimum.
@@ -8766,13 +8767,7 @@ int skill_delayfix (struct block_list *bl, int skill_id, int skill_lv)
 		}
 	}
 
-	if (bl->type == BL_PC && ((TBL_PC*)bl)->delayrate != 100)
-		time = time * ((TBL_PC*)bl)->delayrate / 100;
-
-	if (battle_config.delay_rate != 100)
-		time = time * battle_config.delay_rate / 100;
-
-	if (!(delaynochange&2))
+	if (!(delaynodex&2))
 	{
 		struct status_change *sc;
 		sc= status_get_sc(bl);
@@ -8793,8 +8788,14 @@ int skill_delayfix (struct block_list *bl, int skill_id, int skill_lv)
 		}
 	}
 
-	return (time < battle_config.min_skill_delay_limit)?
-		battle_config.min_skill_delay_limit:time;
+	if (!(delaynodex&4))
+		if (bl->type == BL_PC && ((TBL_PC*)bl)->delayrate != 100)
+			time = time * ((TBL_PC*)bl)->delayrate / 100;
+
+	if (battle_config.delay_rate != 100)
+		time = time * battle_config.delay_rate / 100;
+
+	return max(time, battle_config.min_skill_delay_limit);
 }
 
 /*=========================================
@@ -11553,7 +11554,7 @@ int skill_readdb (void)
 		skill_split_atoi(split[1],skill_db[i].castnodex);
 		if (!split[2])
 			continue;
-		skill_split_atoi(split[2],skill_db[i].delaynoagi);
+		skill_split_atoi(split[2],skill_db[i].delaynodex);
 	}
 	fclose(fp);
 	ShowStatus("Done reading '"CL_WHITE"%s"CL_RESET"'.\n",path);

+ 1 - 2
src/map/skill.h

@@ -71,8 +71,7 @@ struct skill_db {
 	int hp[MAX_SKILL_LEVEL],sp[MAX_SKILL_LEVEL],mhp[MAX_SKILL_LEVEL],hp_rate[MAX_SKILL_LEVEL],sp_rate[MAX_SKILL_LEVEL],zeny[MAX_SKILL_LEVEL];
 	int weapon,ammo,ammo_qty[MAX_SKILL_LEVEL],state,spiritball[MAX_SKILL_LEVEL];
 	int itemid[10],amount[10];
-	int castnodex[MAX_SKILL_LEVEL];
-	int delaynoagi[MAX_SKILL_LEVEL];
+	int castnodex[MAX_SKILL_LEVEL], delaynodex[MAX_SKILL_LEVEL];
 	int nocast;
 	int unit_id[2];
 	int unit_layout_type[MAX_SKILL_LEVEL];

+ 3 - 2
src/map/unit.c

@@ -954,7 +954,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, int skill_num, int
 	break;
 	case MO_FINGEROFFENSIVE:
 		if(sd)
-			casttime += casttime * ((skill_lv > sd->spiritball)? sd->spiritball:skill_lv);
+			casttime += casttime * min(skill_lv, sd->spiritball);
 	break;
 	case MO_EXTREMITYFIST:
 		if (sc && sc->data[SC_COMBO].timer != -1 &&
@@ -981,6 +981,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, int skill_num, int
 	break;
 	}
   	
+	// moved here to prevent Suffragium from ending if skill fails
 	if (!(skill_get_castnodex(skill_num, skill_lv)&2))
 		casttime = skill_castfix_sc(src, casttime);
 
@@ -1116,7 +1117,7 @@ int unit_skilluse_pos2( struct block_list *src, int skill_x, int skill_y, int sk
 	unit_stop_attack(src);
 	ud->state.skillcastcancel = castcancel;
 
-
+	// moved here to prevent Suffragium from ending if skill fails
 	if (!(skill_get_castnodex(skill_num, skill_lv)&2))
 		casttime = skill_castfix_sc(src, casttime);