Pārlūkot izejas kodu

- Added define clif_deadsit to send the dead state into player packets if the player is in trick dead state.
- Venom Splasher always hits (but splash damage targets can still avoid it)
- Using autoloot with no arguments now toggles it between @autoloot 0 and @autoloot 100%
- Falcon Assault now takes Blitz Beat lv5 as base damage.
- Fixed pc_makesavestatus not updating status.option correctly.
- Corrected Waterball so that higher levels can do insane amount of hits.
- Altered slave behaviour. No more random walking, will stay within 2 cells of their master.
- Reverted the Summon Slave behaviour to not adjust level based on number of current slaves.
- Coma no longer sends SP to 1.
- Updated Meteor so that when level 11 or more is casted, the area over which meteors fall is tripled.
- Dark elemental characters are now inmune to Curse.
- Fixed sc_data saving to sql buffer building method. Thanks to its_sparky.
- Changed the map zone reading from using pow to a bit shift.
- Experience has now been changed to unsigned int, and is read as such from the dbs.
- Increased HT_DETECTING seek range to 7x7
- Added function map_foreachinrange which actually checks distance of nearing objects (unlike for each in area which uses a square area), may come handy for future code.
- Corrected Venom Splasher: Being hit does not cancels it, works at 75% or less of target's HP, being hit normally while under the count has a chance of causing poison. Damage is +400% + 50*lv%


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

skotlex 19 gadi atpakaļ
vecāks
revīzija
d69479b946

+ 25 - 0
Changelog-Trunk.txt

@@ -4,6 +4,31 @@ 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.  EVERYTHING ELSE
 GOES INTO TRUNK AND WILL BE MERGED INTO STABLE BY VALARIS AND WIZPUTER. -- VALARIS
 
+2006/02/06
+	* Venom Splasher update: [Skotlex]
+	- always hits (but splash damage targets can still avoid it)
+	- Being hit does not cancels it,
+	- works at 75% or less of target's HP
+	- being hit normally while under the count has a chance of causing poison.
+	- Damage is +400% + 50*lv%
+	* Using autoloot with no arguments now toggles it between @autoloot 0 and
+	  @autoloot 100%  [Skotlex]
+	* Falcon Assault now takes Blitz Beat lv5 as base damage. [Skotlex]
+	* Fixed pc_makesavestatus not updating status.option correctly. [Skotlex]
+	* Corrected Waterball so that higher levels can do insane amount of hits. [Skotlex]
+	* Altered slave behaviour. No more random walking, will stay within 2 cells
+	  of their master. [Skotlex]
+	* Reverted the Summon Slave behaviour to not adjust level based on number
+	  of current slaves. [Skotlex]
+	* Coma no longer sends SP to 1. [Skotlex]
+	* Updated Meteor so that when level 11 or more is casted, the area over
+	  which meteors fall is tripled. [Skotlex]
+	* Dark elemental characters are now inmune to Curse. [Skotlex]
+	* Fixed sc_data saving to sql buffer building method. Thanks to its_sparky. [Skotlex]
+	* Changed the map zone reading from using pow to a bit shift. [Skotlex]
+	* Experience has now been changed to unsigned int, and is read as such from
+	  the dbs. [Skotlex]
+	* Increased HT_DETECTING seek range to 7x7 [Skotlex]
 2006/02/05
 	* Added some of eAIRC bot code, written by me and LittleWolf.
 	  It is disabled and has no configuration options yet, as it is not finished. [Valaris]

+ 4 - 3
src/char_sql/char.c

@@ -2901,22 +2901,23 @@ int parse_frommap(int fd) {
 #ifdef ENABLE_SC_SAVING
 			int count, aid, cid, i;
 			struct status_change_data data;
+			char *p = tmp_sql;
 			
 			aid = RFIFOL(fd, 4);
 			cid = RFIFOL(fd, 8);
 			count = RFIFOW(fd, 12);
 			
-			sprintf(tmp_sql, "INSERT INTO `%s` (`account_id`, `char_id`, `type`, `tick`, `val1`, `val2`, `val3`, `val4`) VALUES ", scdata_db);
+			p+ = sprintf(p, "INSERT INTO `%s` (`account_id`, `char_id`, `type`, `tick`, `val1`, `val2`, `val3`, `val4`) VALUES ", scdata_db);
 			
 			for (i = 0; i < count; i++)
 			{
 				memcpy (&data, RFIFOP(fd, 14+i*sizeof(struct status_change_data)), sizeof(struct status_change_data));
-				sprintf (tmp_sql, "%s ('%d','%d','%hu','%d','%d','%d','%d','%d'),", tmp_sql, aid, cid,
+				p += sprintf (p, " ('%d','%d','%hu','%d','%d','%d','%d','%d'),", aid, cid,
 					data.type, data.tick, data.val1, data.val2, data.val3, data.val4);
 			}
 			if (count > 0)
 			{
-				tmp_sql[strlen(tmp_sql)-1] = '\0'; //Remove final comma.
+				*--p = '\0'; //Remove final comma.
 				if (mysql_query(&mysql_handle, tmp_sql)) {
 					ShowSQL("DB error - %s\n",mysql_error(&mysql_handle));
 					ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);

+ 0 - 8
src/common/core.h

@@ -5,14 +5,6 @@
 #define	_CORE_H_
 
 //#define SQL_DEBUG //uncomment for debug_mysql_query instead of mysql_real_query
-
-/* REMOVED because these type of function defines with va_args are a GCC feature and won't compile under Windows [Skotlex]
-//Added here, so its avail in 'all' files ..
-#define eprintf(mes, args...) \
-        fprintf(stderr, "%s:%d: "mes"", __FILE__, __LINE__, args);
-#define eprint(mes) \
-	fprintf(stderr, "%s:%d: "mes"", __FILE__, __LINE__);
-*/
 	
 extern int arg_c;
 extern char **arg_v;

+ 2 - 1
src/common/mmo.h

@@ -175,7 +175,8 @@ struct mmo_charstatus {
 	int mother;
 	int child;
 
-	int base_exp,job_exp,zeny;
+	unsigned int base_exp,job_exp;
+	int zeny;
 
 	short class_;
 	short status_point,skill_point;

+ 9 - 12
src/map/atcommand.c

@@ -2680,7 +2680,7 @@ int atcommand_baselevelup(
 			clif_displaymessage(fd, msg_table[47]); /* Base level can't go any higher. */
 			return -1;
 		}	/* End Addition */
-		if (level > pc_maxbaselv(sd) || level > (pc_maxbaselv(sd) - sd->status.base_level)) // fix positiv overflow
+		if (level > pc_maxbaselv(sd) || level > (pc_maxbaselv(sd) - (int)sd->status.base_level)) // fix positiv overflow
 			level = pc_maxbaselv(sd) - sd->status.base_level;
 		for (i = 1; i <= level; i++)
 			sd->status.status_point += (sd->status.base_level + i + 14) / 5;
@@ -2739,7 +2739,7 @@ int atcommand_joblevelup(
 			clif_displaymessage(fd, msg_table[23]); // Job level can't go any higher.
 			return -1;
 		}
-		if (level > pc_maxjoblv(sd) || level > (pc_maxjoblv(sd) - sd->status.job_level)) // fix positiv overflow
+		if (level > pc_maxjoblv(sd) || level > (pc_maxjoblv(sd) - (int)sd->status.job_level)) // fix positiv overflow
 			level = pc_maxjoblv(sd) - sd->status.job_level;
 		sd->status.job_level += level;
 		clif_updatestatus(sd, SP_JOBLEVEL);
@@ -7633,17 +7633,14 @@ atcommand_autoloot(
 	double drate;
 	nullpo_retr(-1, sd);
 	if (!message || !*message) {
-		if (sd->state.autoloot) {
-			sd->state.autoloot = 0;
-			clif_displaymessage(fd, "Autoloot is now off.");
-			return 0;
-		} else {
-			clif_displaymessage(fd, "Usage: autoloot <max drop-rate to loot>.");
-			return -1;
-		}
+		if (sd->state.autoloot)
+			rate = 0;
+		else
+			rate = 10000;
+	} else {
+		drate = atof(message);
+		rate = (int)(drate*100);
 	}
-	drate = atof(message);
-	rate = (int)(drate*100);
 	if (rate > 10000) rate = 10000;
 	else if (rate < 0) rate = 0;
 	

+ 5 - 4
src/map/battle.c

@@ -1361,6 +1361,9 @@ static struct Damage battle_calc_weapon_attack(
 		if (skill_num && !flag.hit)
 			switch(skill_num)
 			{
+				case AS_SPLASHER: //Reports say it always hits?
+					if (wflag) //Only if you were the one exploding.
+						break;
 				case NPC_GUIDEDATTACK:
 				case RG_BACKSTAP:
 				case AM_ACIDTERROR:
@@ -1775,7 +1778,7 @@ static struct Damage battle_calc_weapon_attack(
 					skillratio += 100+100*skill_lv;
 					break;
 				case AS_SPLASHER:
-					skillratio += 100+20*skill_lv;
+					skillratio += 400+50*skill_lv;
 					if (sd)
 						skillratio += 20*pc_checkskill(sd,AS_POISONREACT);
 					if(wflag>1) //FIXME: Splash damage... is this the correct method? [Skotlex]
@@ -2818,7 +2821,7 @@ struct Damage  battle_calc_misc_attack(
 	case SN_FALCONASSAULT:			/* ファルコンアサルト */
 		if( sd==NULL || (skill = pc_checkskill(sd,HT_STEELCROW)) <= 0)
 			skill=0;
-		damage=(dex/10+int_/2+skill*3+40)*2*skill_get_num(HT_BLITZBEAT, skill_lv);   //Blitz Beat Damage
+		damage=(dex/10+int_/2+skill*3+40)*2*skill_get_num(HT_BLITZBEAT, 5);   //Blitz Beat lv5 Damage
 		damage=damage*(150+70*skill_lv)/100;	//Falcon Assault Modifier
 		if(flag > 1)
 			damage /= flag;
@@ -3194,8 +3197,6 @@ int battle_weapon_attack( struct block_list *src,struct block_list *target,
 			if (tsc->data[SC_POISONREACT].val2 <= 0)
 				status_change_end(target, SC_POISONREACT, -1);
 		}
-		if (tsc->data[SC_SPLASHER].timer != -1)	//殴ったので対?ロのベナムスプラッシャ?[?�ヤを解?�
-			status_change_end(target, SC_SPLASHER, -1);
 	}
 
 	//SG_FUSION hp penalty [Komurka]

+ 2 - 2
src/map/charcommand.c

@@ -1262,7 +1262,7 @@ int charcommand_baselevel(
 					clif_displaymessage(fd, msg_table[91]); // Character's base level can't go any higher.
 					return 0;
 				}	// End Addition
-				if (level > pc_maxbaselv(pl_sd) || level > (pc_maxbaselv(pl_sd)- pl_sd->status.base_level)) // fix positiv overflow
+				if (level > pc_maxbaselv(pl_sd) || level > (pc_maxbaselv(pl_sd)- (int)pl_sd->status.base_level)) // fix positiv overflow
 					level = pc_maxbaselv(pl_sd) - pl_sd->status.base_level;
 				for (i = 1; i <= level; i++)
 					pl_sd->status.status_point += (pl_sd->status.base_level + i + 14) / 5;
@@ -1333,7 +1333,7 @@ int charcommand_joblevel(
 					clif_displaymessage(fd, msg_table[67]); // Character's job level can't go any higher.
 					return -1;
 				}
-				if (pl_sd->status.job_level + level > pc_maxjoblv(pl_sd))
+				if ((int)pl_sd->status.job_level + level > pc_maxjoblv(pl_sd))
 					level = pc_maxjoblv(pl_sd) - pl_sd->status.job_level;
 				pl_sd->status.job_level += level;
 				clif_updatestatus(pl_sd, SP_JOBLEVEL);

+ 4 - 3
src/map/charsave.c

@@ -486,8 +486,9 @@ void charsave_save_scdata(int account_id, int char_id, struct status_change* sc_
 	int i,count =0;
 	struct TimerData *timer;
 	unsigned int tick = gettick();
+	char *p = tmp_sql;
 
-	sprintf(tmp_sql, "INSERT INTO `sc_data` (`account_id`, `char_id`, `type`, `tick`, `val1`, `val2`, `val3`, `val4`) VALUES ");
+	p += sprintf(p, "INSERT INTO `sc_data` (`account_id`, `char_id`, `type`, `tick`, `val1`, `val2`, `val3`, `val4`) VALUES ");
 			
 	for(i = 0; i < max_sc; i++)
 	{
@@ -497,14 +498,14 @@ void charsave_save_scdata(int account_id, int char_id, struct status_change* sc_
 		if (timer == NULL || timer->func != status_change_timer || DIFF_TICK(timer->tick,tick) < 0)
 			continue;
 		
-		sprintf (tmp_sql, "%s ('%d','%d','%hu','%d','%d','%d','%d','%d'),", tmp_sql, account_id, char_id,
+		p += (p, " ('%d','%d','%hu','%d','%d','%d','%d','%d'),", account_id, char_id,
 			i, DIFF_TICK(timer->tick,tick), sc_data->data[i].val1, sc_data->data[i].val2, sc_data->data[i].val3, sc_data->data[i].val4);
 		
 		count++;
 	}
 	if (count > 0)
 	{
-		tmp_sql[strlen(tmp_sql)-1] = '\0'; //Remove the trailing comma.
+		*--p = '\0'; //Remove the trailing comma.
 		if(mysql_query(&charsql_handle, tmp_sql)){
 			ShowSQL("DB error - %s\n",mysql_error(&charsql_handle));
 			ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);

+ 4 - 3
src/map/clif.c

@@ -754,6 +754,7 @@ int clif_clearchar_id(int id, int type, int fd) {
 	(sd->inventory_data[sd->equip_index[n]]->view_id > 0)?sd->inventory_data[sd->equip_index[n]]->view_id: \
 	sd->status.inventory[sd->equip_index[n]].nameid):0)
 
+#define clif_deadsit(sd) (((sd)->sc.count && (sd)->sc.data[SC_TRICKDEAD].timer != -1)?1:sd->state.dead_sit)
 /*==========================================
  *
  *------------------------------------------
@@ -802,7 +803,7 @@ static int clif_set0078(struct map_session_data *sd, unsigned char *buf) {
 	WBUFB(buf,48)|=sd->dir&0x0f;
 	WBUFB(buf,49)=5;
 	WBUFB(buf,50)=5;
-	WBUFB(buf,51)=sd->state.dead_sit;
+	WBUFB(buf,51)=clif_deadsit(sd);
 	WBUFW(buf,52)=clif_setlevel(sd->status.base_level);
 
 	return packet_len_table[0x78];
@@ -841,7 +842,7 @@ static int clif_set0078(struct map_session_data *sd, unsigned char *buf) {
 	WBUFB(buf,48)|=sd->dir & 0x0f;
 	WBUFB(buf,49)=5;
 	WBUFB(buf,50)=5;
-	WBUFB(buf,51)=sd->state.dead_sit;
+	WBUFB(buf,51)=clif_deadsit(sd);
 	WBUFW(buf,52)=clif_setlevel(sd->status.base_level);
 
 	return packet_len_table[0x1d8];
@@ -870,7 +871,7 @@ static int clif_dis0078(struct map_session_data *sd, unsigned char *buf) {
 	WBUFB(buf,48)|=sd->dir&0x0f;
 	WBUFB(buf,49)=5;
 	WBUFB(buf,50)=5;
-	WBUFB(buf,51)=sd->state.dead_sit;
+	WBUFB(buf,51)=clif_deadsit(sd);
 	WBUFW(buf,52)=0;
 
 	return packet_len_table[0x78];

+ 2 - 2
src/map/irc.c

@@ -247,12 +247,12 @@ int send_to_parser(int fd, char *input,char key[2])
 	return total_loops;
 }
 
-void do_final_irc()
+void do_final_irc(void)
 {
 
 }
 
-void do_init_irc()
+void do_init_irc(void)
 {
 	if(!use_irc)
 		return;

+ 2 - 2
src/map/irc.h

@@ -13,8 +13,8 @@ void irc_announce_shop(struct map_session_data *sd,int flag);
 void irc_announce_mvp(struct map_session_data *sd, struct mob_data *md);
 
 int irc_parse(int fd);
-void do_final_irc();
-void do_init_irc();
+void do_final_irc(void);
+void do_init_irc(void);
 void irc_send(char *buf);
 void irc_parse_sub(int fd, char *incoming_string);
 int send_to_parser(int fd, char *input,char key[2]);

+ 73 - 0
src/map/map.c

@@ -639,6 +639,79 @@ struct skill_unit *map_find_skill_unit_oncell(struct block_list *target,int x,in
 	return NULL;
 }
 
+/*==========================================
+ * Adapted from foreachinarea to use real ranges around a character area. [Skotlex]
+ *------------------------------------------
+ */
+
+int map_foreachinrange(int (*func)(struct block_list*,va_list),int m,struct block_list *center, int range,int type,...) {
+	va_list ap;
+	int bx,by;
+	int returnCount =0;	//total sum of returned values of func() [Skotlex]
+	struct block_list *bl=NULL;
+	int blockcount=bl_list_count,i,c;
+	int x0,x1,y0,y1;
+	
+	if (m < 0)
+		return 0;
+	va_start(ap,type);
+	x0 = center->x-range;
+	x1 = center->x+range;
+	y0 = center->y-range;
+	y1 = center->y+range;
+	
+	if (x0 < 0) x0 = 0;
+	if (y0 < 0) y0 = 0;
+	if (x1 >= map[m].xs) x1 = map[m].xs-1;
+	if (y1 >= map[m].ys) y1 = map[m].ys-1;
+	
+	if (type&~BL_MOB)
+		for (by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++) {
+			for(bx=x0/BLOCK_SIZE;bx<=x1/BLOCK_SIZE;bx++){
+				bl = map[m].block[bx+by*map[m].bxs];
+				c = map[m].block_count[bx+by*map[m].bxs];
+				for(i=0;i<c && bl;i++,bl=bl->next){
+					if(bl && bl->type&type
+						&& bl->x>=x0 && bl->x<=x1 && bl->y>=y0 && bl->y<=y1
+						&& check_distance_bl(center, bl, range)
+					  	&& bl_list_count<BL_LIST_MAX)
+						bl_list[bl_list_count++]=bl;
+				}
+			}
+		}
+	if(type&BL_MOB)
+		for(by=y0/BLOCK_SIZE;by<=y1/BLOCK_SIZE;by++){
+			for(bx=x0/BLOCK_SIZE;bx<=x1/BLOCK_SIZE;bx++){
+				bl = map[m].block_mob[bx+by*map[m].bxs];
+				c = map[m].block_mob_count[bx+by*map[m].bxs];
+				for(i=0;i<c && bl;i++,bl=bl->next){
+					if(bl
+						&& bl->x>=x0 && bl->x<=x1 && bl->y>=y0 && bl->y<=y1
+						&& check_distance_bl(center, bl, range)
+						&& bl_list_count<BL_LIST_MAX)
+						bl_list[bl_list_count++]=bl;
+				}
+			}
+		}
+
+	if(bl_list_count>=BL_LIST_MAX) {
+		if(battle_config.error_log)
+			ShowWarning("map_foreachinrange: block count too many!\n");
+	}
+
+	map_freeblock_lock();	// メモリからの解放を禁止する
+
+	for(i=blockcount;i<bl_list_count;i++)
+		if(bl_list[i]->prev)	// 有?かどうかチェック
+			returnCount += func(bl_list[i],ap);
+
+	map_freeblock_unlock();	// 解放を許可する
+
+	va_end(ap);
+	bl_list_count = blockcount;
+	return returnCount;	//[Skotlex]
+}
+
 /*==========================================
  * map m (x0,y0)-(x1,y1)?の全objに?して
  * funcを呼ぶ

+ 2 - 0
src/map/map.h

@@ -1223,6 +1223,8 @@ int map_delblock_sub(struct block_list *, int);
 #define map_addblock(bl) map_addblock_sub(bl,1)
 #define map_delblock(bl) map_delblock_sub(bl,1)
 int map_moveblock(struct block_list *, int, int, unsigned int);
+
+int map_foreachinrange(int (*)(struct block_list*,va_list),int,struct block_list *,int,int,...);
 int map_foreachinarea(int (*)(struct block_list*,va_list),int,int,int,int,int,int,...);
 // -- moonsoul (added map_foreachincell)
 int map_foreachincell(int (*)(struct block_list*,va_list),int,int,int,int,...);

+ 15 - 8
src/map/mob.c

@@ -39,6 +39,7 @@
 #define MOB_LAZYMOVEPERC 50	// Move probability in the negligent mode MOB (rate of 1000 minute)
 #define MOB_LAZYWARPPERC 20	// Warp probability in the negligent mode MOB (rate of 1000 minute)
 
+#define MOB_SLAVEDISTANCE 2	//Distance that slaves should keep from their master.
 //Dynamic mob database, allows saving of memory when there's big gaps in the mob_db [Skotlex]
 struct mob_db *mob_db_data[MAX_MOB_DB+1];
 struct mob_db *mob_dummy = NULL;	//Dummy mob to be returned when a non-existant one is requested.
@@ -1424,18 +1425,23 @@ static int mob_ai_sub_hard_slavemob(struct mob_data *md,unsigned int tick)
 		if((!md->target_id || md->state.targettype == NONE_ATTACKABLE) && mob_can_move(md) &&
 			md->master_dist<md->db->range3 && (md->walkpath.path_pos>=md->walkpath.path_len || md->walkpath.path_len==0)){
 			int i=0,dx,dy,ret;
-			if(md->master_dist>AREA_SIZE/2 && DIFF_TICK(md->next_walktime,tick)<3000) { //Allow it to cut down the walk time to chase back. [Skotlex]
+			if(md->master_dist>MOB_SLAVEDISTANCE || md->master_dist == 0)
+		  	{  //Chase back to Master's area also if standing on top of the master.
 				do {
 					if(i<=5){
 						dx=bl->x - md->bl.x;
 						dy=bl->y - md->bl.y;
-						if(dx<0) dx+=(rand()%-dx)/2; //On the minimum, half the distance between slave/master. [Skotlex]
-						else if(dx>0) dx-=(rand()%dx)/2;
-						if(dy<0) dy+=(rand()%-dy)/2;
-						else if(dy>0) dy-=(rand()%dy)/2;
+						
+						if(dx<0) dx+=rand()%MOB_SLAVEDISTANCE +1;
+						else if(dx>0) dx-=rand()%MOB_SLAVEDISTANCE +1;
+
+						if(dy<0) dy+=rand()%MOB_SLAVEDISTANCE +1;
+						else if(dy>0) dy-=rand()%MOB_SLAVEDISTANCE +1;
+						
 					}else{
-						dx=bl->x - md->bl.x + rand()%11- 5;
-						dy=bl->y - md->bl.y + rand()%11- 5;
+						ret = MOB_SLAVEDISTANCE*2+1;
+						dx=bl->x - md->bl.x + rand()%ret - MOB_SLAVEDISTANCE;
+						dy=bl->y - md->bl.y + rand()%ret - MOB_SLAVEDISTANCE;
 					}
 
 					ret=mob_walktoxy(md,md->bl.x+dx,md->bl.y+dy,0);
@@ -1854,7 +1860,8 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap)
 		return 0;
 
 	// Nothing else to do... except random walking.
-	if (mode&MD_CANMOVE && mob_can_move(md))
+	// Slaves do not random walk! [Skotlex]
+	if (mode&MD_CANMOVE && mob_can_move(md) && !md->master_id)
 	{
 		if (DIFF_TICK(md->next_walktime, tick) > 7000 &&
 			(md->walkpath.path_len == 0 || md->walkpath.path_pos >= md->walkpath.path_len))

+ 2 - 1
src/map/npc.c

@@ -2600,7 +2600,8 @@ static int npc_parse_mapflag (char *w1, char *w2, char *w3, char *w4)
 	else if (strcmpi(w3,"restricted")==0) { // Komurka
 		map[m].flag.restricted=1;
 		sscanf(w4, "%d", &map[m].zone);
-		map[m].zone = pow(2,map[m].zone+1);
+		//map[m].zone = pow(2,map[m].zone+1);
+		map[m].zone = 1<<(map[m].zone+1);
 	}
 
 	return 0;

+ 31 - 24
src/map/pc.c

@@ -41,8 +41,8 @@
 #endif
 
 #define PVP_CALCRANK_INTERVAL 1000	// PVP順位計算の間隔
-static int exp_table[MAX_PC_CLASS][2][MAX_LEVEL];
-static int max_level[MAX_PC_CLASS][2];
+static unsigned int exp_table[MAX_PC_CLASS][2][MAX_LEVEL];
+static unsigned int max_level[MAX_PC_CLASS][2];
 static short statp[MAX_LEVEL];
 
 // h-files are for declarations, not for implementations... [Shinomori]
@@ -416,7 +416,7 @@ int pc_makesavestatus(struct map_session_data *sd)
 
 	// 死亡?態だったのでhpを1、位置をセ?ブ場所に?更
 	if(!sd->state.waitingdisconnect) {
-		sd->sc.option = sd->sc.option;
+		sd->status.option = sd->sc.option; //Since the option saved is in 
 		if(pc_isdead(sd)){
 			pc_setrestartvalue(sd,0);
 			memcpy(&sd->status.last_point,&sd->status.save_point,sizeof(sd->status.last_point));
@@ -4687,11 +4687,11 @@ int pc_checkjoblevelup(struct map_session_data *sd)
  * ??値取得
  *------------------------------------------
  */
-int pc_gainexp(struct map_session_data *sd,int base_exp,int job_exp)
+int pc_gainexp(struct map_session_data *sd,unsigned int base_exp,unsigned int job_exp)
 {
 	char output[256];
 	float nextbp=0, nextjp=0;
-	int nextb=0, nextj=0;
+	unsigned int nextb=0, nextj=0;
 	nullpo_retr(0, sd);
 
 	if(sd->bl.prev == NULL || pc_isdead(sd))
@@ -4702,14 +4702,10 @@ int pc_gainexp(struct map_session_data *sd,int base_exp,int job_exp)
 
 	if(sd->status.guild_id>0){	// ギルドに上納
 		base_exp-=guild_payexp(sd,base_exp);
-		if(base_exp < 0)
-			base_exp = 0;
 	}
 
 	if(!battle_config.multi_level_up && pc_nextbaseafter(sd) && sd->status.base_exp+base_exp >= pc_nextbaseafter(sd)) {
 		base_exp = pc_nextbaseafter(sd) - sd->status.base_exp;
-		if (base_exp < 0)
-			base_exp = 0;
 	}
 	nextb = pc_nextbaseexp(sd);
 	nextj = pc_nextjobexp(sd);
@@ -4719,21 +4715,16 @@ int pc_gainexp(struct map_session_data *sd,int base_exp,int job_exp)
 		nextjp = (float) job_exp / (float) nextj;
 
 	sd->status.base_exp += base_exp;
-	if(sd->status.base_exp < 0)
-		sd->status.base_exp = 0;
 
 	while(pc_checkbaselevelup(sd)) ;
 
 	clif_updatestatus(sd,SP_BASEEXP);
+	
 	if(!battle_config.multi_level_up && pc_nextjobafter(sd) && sd->status.job_exp+job_exp >= pc_nextjobafter(sd)) {
 		job_exp = pc_nextjobafter(sd) - sd->status.job_exp;
-		if (job_exp < 0)
-			job_exp = 0;
 	}
 
 	sd->status.job_exp += job_exp;
-	if(sd->status.job_exp < 0)
-		sd->status.job_exp = 0;
 
 	while(pc_checkjoblevelup(sd)) ;
 
@@ -4741,11 +4732,11 @@ int pc_gainexp(struct map_session_data *sd,int base_exp,int job_exp)
 
 	if(sd->state.showexp){
 		sprintf(output,
-			"Experienced Gained Base:%d (%.2f%%) Job:%d (%.2f%%)",base_exp,nextbp*(float)100,job_exp,nextjp*(float)100);
+			"Experience Gained Base:%d (%.2f%%) Job:%d (%.2f%%)",base_exp,nextbp*(float)100,job_exp,nextjp*(float)100);
 		clif_disp_onlyself(sd,output,strlen(output));
 	}
 
-	return 0;
+	return 1;
 }
 
 /*==========================================
@@ -4753,11 +4744,11 @@ int pc_gainexp(struct map_session_data *sd,int base_exp,int job_exp)
  *------------------------------------------
  */
 
-int pc_maxbaselv(struct map_session_data *sd) {
+unsigned int pc_maxbaselv(struct map_session_data *sd) {
   	return max_level[sd->status.class_][0];
 };
 
-int pc_maxjoblv(struct map_session_data *sd) {
+unsigned int pc_maxjoblv(struct map_session_data *sd) {
   	return max_level[sd->status.class_][1];
 };
 
@@ -4765,7 +4756,7 @@ int pc_maxjoblv(struct map_session_data *sd) {
  * base level側必要??値計算
  *------------------------------------------
  */
-int pc_nextbaseexp(struct map_session_data *sd)
+unsigned int pc_nextbaseexp(struct map_session_data *sd)
 {
 	nullpo_retr(0, sd);
 
@@ -4779,7 +4770,7 @@ int pc_nextbaseexp(struct map_session_data *sd)
  * job level側必要??値計算
  *------------------------------------------
  */
-int pc_nextjobexp(struct map_session_data *sd)
+unsigned int pc_nextjobexp(struct map_session_data *sd)
 {
 	nullpo_retr(0, sd);
 
@@ -4792,7 +4783,7 @@ int pc_nextjobexp(struct map_session_data *sd)
  * base level after next [Valaris]
  *------------------------------------------
  */
-int pc_nextbaseafter(struct map_session_data *sd)
+unsigned int pc_nextbaseafter(struct map_session_data *sd)
 {
 	nullpo_retr(0, sd);
 
@@ -4806,7 +4797,7 @@ int pc_nextbaseafter(struct map_session_data *sd)
  * job level after next [Valaris]
  *------------------------------------------
  */
-int pc_nextjobafter(struct map_session_data *sd)
+unsigned int pc_nextjobafter(struct map_session_data *sd)
 {
 	nullpo_retr(0, sd);
 
@@ -8053,6 +8044,22 @@ int pc_split_atoi(char *str,int *val, char sep, int max)
 	return i;
 }
 
+int pc_split_atoui(char *str,unsigned int *val, char sep, int max)
+{
+	int i,j;
+	for (i=0; i<max; i++) {
+		if (!str) break;
+		val[i] = (unsigned int)atof(str);
+		str = strchr(str,sep);
+		if (str)
+			*str++=0;
+	}
+	//Zero up the remaining.
+	for(j=i; j < max; j++)
+		val[j] = 0;
+	return i;
+}
+
 //
 // 初期化物
 //
@@ -8110,7 +8117,7 @@ int pc_readdb(void)
 			max = MAX_LEVEL;
 		}
 		//We send one less and then one more because the last entry in the exp array should hold 0.
-		max_level[job][type] = pc_split_atoi(split[3], exp_table[job][type],',',max-1)+1;
+		max_level[job][type] = pc_split_atoui(split[3], exp_table[job][type],',',max-1)+1;
 		//Reverse check in case the array has a bunch of trailing zeros... [Skotlex]
 		//The reasoning behind the -2 is this... if the max level is 5, then the array
 		//should look like this:

+ 7 - 7
src/map/pc.h

@@ -117,15 +117,15 @@ int pc_follow(struct map_session_data*, int); // [MouseJstr]
 int pc_stop_following(struct map_session_data*);
 
 
-int pc_maxbaselv(struct map_session_data *sd);
-int pc_maxjoblv(struct map_session_data *sd);
+unsigned int pc_maxbaselv(struct map_session_data *sd);
+unsigned int pc_maxjoblv(struct map_session_data *sd);
 int pc_checkbaselevelup(struct map_session_data *sd);
 int pc_checkjoblevelup(struct map_session_data *sd);
-int pc_gainexp(struct map_session_data*,int,int);
-int pc_nextbaseexp(struct map_session_data *);
-int pc_nextbaseafter(struct map_session_data *); // [Valaris]
-int pc_nextjobexp(struct map_session_data *);
-int pc_nextjobafter(struct map_session_data *); // [Valaris]
+int pc_gainexp(struct map_session_data*,unsigned int,unsigned int);
+unsigned int pc_nextbaseexp(struct map_session_data *);
+unsigned int pc_nextbaseafter(struct map_session_data *); // [Valaris]
+unsigned int pc_nextjobexp(struct map_session_data *);
+unsigned int pc_nextjobafter(struct map_session_data *); // [Valaris]
 int pc_need_status_point(struct map_session_data *,int);
 int pc_statusup(struct map_session_data*,int);
 int pc_statusup2(struct map_session_data*,int,int);

+ 29 - 18
src/map/skill.c

@@ -901,13 +901,23 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int
 				rand() % 100 < tsc->data[SC_EDP].val2 * sc_def_vit / 100)
 				status_change_start(bl,SC_DPOISON,sc->data[SC_EDP].val1,0,0,0,skill_get_time2(ASC_EDP,sc->data[SC_EDP].val1),0);
 		}
-		if (tsc->count && tsc->data[SC_KAAHI].timer != -1) {
-			if (dstsd && dstsd->status.sp < 5*tsc->data[SC_KAAHI].val1)
-				; //Not enough SP to cast
-			else {
-				battle_heal(bl, bl, 200*tsc->data[SC_KAAHI].val1, -5*tsc->data[SC_KAAHI].val1, 1);
-				if(dstsd && dstsd->fd)
-					clif_heal(dstsd->fd,SP_HP,200*tsc->data[SC_KAAHI].val1);
+		if (tsc->count) {
+			if (tsc->data[SC_SPLASHER].timer != -1 &&
+				tsc->data[SC_POISON].timer == -1 &&
+				rand()%100< (2*tsc->data[SC_SPLASHER].val1+10)*sc_def_vit/100
+			) {
+				status_change_start(bl,SC_POISON,tsc->data[SC_SPLASHER].val1,0,0,0,
+					skill_get_time2(tsc->data[SC_SPLASHER].val2,tsc->data[SC_SPLASHER].val1),0);
+			}
+			
+			if(tsc->data[SC_KAAHI].timer != -1) {
+				if (dstsd && dstsd->status.sp < 5*tsc->data[SC_KAAHI].val1)
+					; //Not enough SP to cast
+				else {
+					battle_heal(bl, bl, 200*tsc->data[SC_KAAHI].val1, -5*tsc->data[SC_KAAHI].val1, 1);
+					if(dstsd && dstsd->fd)
+						clif_heal(dstsd->fd,SP_HP,200*tsc->data[SC_KAAHI].val1);
+				}
 			}
 		}
 	}
@@ -3014,10 +3024,10 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl,int s
 	case WZ_WATERBALL:			/* ƒEƒH?ƒ^?ƒ{?ƒ‹ */
 		skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag);
 		if (skilllv>1) {
-			int range = skilllv > 5 ? 2 : skilllv/2;
+			int range = skilllv/2;
 			//Rain doesn't affect WATERBALL (Rain has been removed at kRO) [Lupus]
 			//int cnt = (!map[src->m].flag.rain) ? skill_count_water(src,range) - 1 : skill_get_num(skillid,skilllv) - 1;
-			int cnt = (src->type==BL_PC)?skill_count_water(src,range) - 1:(skilllv>3?24:8);
+			int cnt = (src->type==BL_PC)?skill_count_water(src,range) - 1:(range*range-1);
 			if (cnt > 0)
 				skill_addtimerskill(src,tick+150,bl->id,0,0,
 					skillid,skilllv,cnt,flag);
@@ -5086,8 +5096,6 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 		break;
 
 	case NPC_SUMMONSLAVE:		/* Žè‰º?¢Š« */
-		if (md) //Only summon remaining slaves
-			skilllv = skilllv - mob_countslave(&md->bl);
 	case NPC_SUMMONMONSTER:		/* MOB?¢Š« */
 		if(md)
 			mob_summonslave(md,md->db->skill[md->skillidx].val,skilllv,skillid);
@@ -5425,7 +5433,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 		break;
 
 	case AS_SPLASHER:		/* ƒxƒiƒ€ƒXƒvƒ‰ƒbƒVƒƒ? */
-		if(status_get_max_hp(bl)*2/3 < status_get_hp(bl)) { //HP‚ª2/3ˆÈ?ã?‚Á‚Ä‚¢‚½‚玸”s
+		if(status_get_max_hp(bl)*3/4 < status_get_hp(bl)) { //HP‚ª2/3ˆÈ?ã?‚Á‚Ä‚¢‚½‚玸”s
 			map_freeblock_unlock();
 			return 1;
 		}
@@ -6227,7 +6235,7 @@ int skill_castend_pos2( struct block_list *src, int x,int y,int skillid,int skil
 
 	case HT_DETECTING:				/* ƒfƒBƒeƒNƒeƒBƒ“ƒO */
 		map_foreachinarea( status_change_timer_sub,
-			src->m, x-1, y-1, x+1,y+1,BL_CHAR,
+			src->m, x-3, y-3, x+3,y+3,BL_CHAR,
 			src,status_get_sc(src),SC_SIGHT,tick);
 		break;
 
@@ -6279,14 +6287,17 @@ int skill_castend_pos2( struct block_list *src, int x,int y,int skillid,int skil
 
 	case WZ_METEOR:				//ƒ?ƒeƒIƒXƒg?ƒ€
 		{
-			int flag=0;
+			int flag=0, area = 7;
 			if (sc && sc->data[SC_MAGICPOWER].timer != -1)
 				flag = flag|2; //Store the magic power flag for future use. [Skotlex]
+			if (skilllv > skill_get_max(skillid))
+				area = area*3; //Double range area
 			for(i=0;i<2+(skilllv>>1);i++) {
 				int j=0;
 				do {
-					tmpx = x + (rand()%7 - 3);
-					tmpy = y + (rand()%7 - 3);
+					
+					tmpx = x + (rand()%area - area/2);
+					tmpy = y + (rand()%area - area/2);
 					if(tmpx < 0)
 						tmpx = 0;
 					else if(tmpx >= map[src->m].xs)
@@ -6648,11 +6659,11 @@ struct skill_unit_group *skill_unitsetting( struct block_list *src, int skillid,
 			range=2;
 		break;
 	case WZ_METEOR:
-		if (skilllv > 10)			//?L”͈̓?ƒeƒI
+		if (skilllv > skill_get_max(skillid))			//?L”͈̓?ƒeƒI
 			range = 10;
 		break;
 	case WZ_VERMILION:
-		if (skilllv > 10)			//?L”͈ÍLOV
+		if (skilllv > skill_get_max(skillid))			//?L”͈ÍLOV
 			range = 25;
 		break;
 	case WZ_QUAGMIRE:	//The target changes to "all" if used in a gvg map. [Skotlex]

+ 4 - 3
src/map/status.c

@@ -3720,7 +3720,9 @@ int status_change_start(struct block_list *bl,int type,int val1,int val2,int val
 	if((type==SC_FREEZE || type==SC_STONE) && undead_flag && !(flag&1))
 	//I've been informed that undead chars are inmune to stone curse too. [Skotlex]
 		return 0;
-
+	//Dark Elementals are inmune to curse.
+	if(type==SC_CURSE && elem == 7 && !(flag&1))
+		return 0;
 
 	if (type==SC_BLESSING && (bl->type==BL_PC || (!undead_flag && race!=6))) {
 		if (sc->data[SC_CURSE].timer!=-1)
@@ -4451,9 +4453,8 @@ int status_change_start(struct block_list *bl,int type,int val1,int val2,int val
 			break;
 		}
 
-		case SC_COMA: //Coma. Sends a char to 1HP/SP
+		case SC_COMA: //Coma. Sends a char to 1HP
 			battle_damage(NULL, bl, status_get_hp(bl)-1, 0);
-			if (sd) pc_heal(sd,0,-sd->status.sp+1);
 			return 0;
 
 		case SC_CARTBOOST:		/* ƒJ?ƒgƒu?ƒXƒg */