Browse Source

Merge branch 'master' of https://github.com/rathena/rathena

Euphy 11 years ago
parent
commit
f0927dcb85
14 changed files with 3522 additions and 134 deletions
  1. 2 0
      .gitignore
  2. 2 2
      db/packet_db.txt
  3. 16 16
      db/quest_db.txt
  4. 2 2
      db/re/skill_cast_db.txt
  5. 2 2
      db/re/skill_db.txt
  6. 2 2
      db/re/skill_unit_db.txt
  7. 3317 1
      npc/re/quests/quests_malaya.txt
  8. 44 23
      src/map/battle.c
  9. 14 21
      src/map/clif.c
  10. 1 0
      src/map/map.h
  11. 16 6
      src/map/script.c
  12. 37 15
      src/map/skill.c
  13. 1 0
      src/map/skill.h
  14. 66 44
      src/map/status.c

+ 2 - 0
.gitignore

@@ -23,6 +23,7 @@
 /Makefile.cache
 /map-server_sql
 /mapcache
+/nbproject
 
 # /3rdparty/libconfig/
 /3rdparty/libconfig/Makefile
@@ -34,6 +35,7 @@
 
 # /conf/
 /conf/import
+/conf/msg_conf/import
 
 # /log/
 /log/*.log

+ 2 - 2
db/packet_db.txt

@@ -1707,7 +1707,7 @@ packet_ver: 30
 0x089c,26,friendslistadd,2
 0x0885,5,hommenu,2:4
 0x0961,36,storagepassword,2:4:20
-0x0288,-1,cashshopbuy,2:4:6:10
+0x0288,-1,cashshopbuy,2:4:8:10
 0x091c,26,partyinvite2,2
 0x094b,19,wanttoconnection,2:6:10:14:18
 0x0369,7,actionrequest,2:6
@@ -1816,7 +1816,7 @@ packet_ver: 34
 0x0447,2,booking_playcancel,0
 0x044A,6,clientversion,2
 0x0844,2,cashshopopen,0
-0x0848,-1,cashshopbuy,2:4:6:10
+0x0848,-1,cashshopbuy,2:6:4:10
 0x084a,2,cashshopclose,0
 0x084b,19 //fallitem4
 0x085a,90,useskilltoposinfo,2:4:6:8:10

+ 16 - 16
db/quest_db.txt

@@ -1111,7 +1111,7 @@
 7364,0,0,0,0,0,0,0,"Deliver Holy Item to Middle-aged Man"
 7365,0,0,0,0,0,0,0,"Better than My Old Button-2"
 7366,0,0,0,0,0,0,0,"Traditional Spiritual Protection and Impudent Girl-1"
-7367,0,0,0,0,0,0,0,"Traditional Spiritual Protection and Impudent Girl-2"
+7367,900,0,0,0,0,0,0,"Traditional Spiritual Protection and Impudent Girl-2"
 7368,0,0,0,0,0,0,0,"Deliver Spiritual Protection-Pedro"
 7369,0,0,0,0,0,0,0,"Deliver Spiritual Protection-Nardo"
 7370,0,0,0,0,0,0,0,"Deliver Spiritual Protection-Pandoi"
@@ -1119,13 +1119,13 @@
 7372,0,0,0,0,0,0,0,"Deliver Spiritual Protection-Talah"
 7373,0,0,0,0,0,0,0,"Deliver Spiritual Protection-Romel"
 7374,0,0,0,0,0,0,0,"Love and Spiritual Protection for All"
-7375,0,0,0,0,0,0,0,"Love and Spiritual Protection Continues"
+7375,86400,0,0,0,0,0,0,"Love and Spiritual Protection Continues"
 7376,0,0,0,0,0,0,0,"Old Man and Cast-Iron Caldron-1"
 7377,0,0,0,0,0,0,0,"Old Man and Cast-Iron Caldron-2"
-7378,0,0,0,0,0,0,0,"Old Man and Cast-Iron Caldron-Regular Trades"
+7378,86400,0,0,0,0,0,0,"Old Man and Cast-Iron Caldron-Regular Trades"
 7379,0,0,0,0,0,0,0,"Peace Preacher"
 7380,0,0,0,0,0,0,0,"To Smith a Traditional Spiritual Protection"
-7381,0,0,0,0,0,0,0,"High Demand on Spiritual Protection Material"
+7381,86400,0,0,0,0,0,0,"High Demand on Spiritual Protection Material"
 7382,0,0,0,0,0,0,0,"Deliver to Pedro"
 7383,0,0,0,0,0,0,0,"Deliver to Nardo"
 7384,0,0,0,0,0,0,0,"Deliver to Pandoi"
@@ -1134,27 +1134,27 @@
 7387,0,0,0,0,0,0,0,"Deliver to Romel"
 7388,0,0,0,0,0,0,0,"Maries's Child"
 7389,0,0,0,0,0,0,0,"Give the Shirt to Maries's Child"
-7390,0,0,0,0,0,0,0,"Worried about Maries's Child"
+7390,86400,0,0,0,0,0,0,"Worried about Maries's Child"
 7391,0,0,0,0,0,0,0,"Jejeling and Jejellopy"
-7392,0,0,0,0,0,0,0,"Collect Jejellopy Regularly"
-7393,0,0,0,0,0,0,0,"Shiny Silver Blade"
-7394,0,0,0,0,0,0,0,"Shiny Tomorrow"
-7395,0,0,0,0,0,0,0,"Ghost on the Perry Ship"
-7396,0,0,0,0,0,0,0,"Angry Soul on Perry Ship"
+7392,86400,0,0,0,0,0,0,"Collect Jejellopy Regularly"
+7393,0,2314,10,2311,10,0,0,"Shiny Silver Blade"
+7394,86400,0,0,0,0,0,0,"Shiny Tomorrow"
+7395,0,0,0,0,0,0,0,"Ghost on the Ferry Ship"
+7396,0,0,0,0,0,0,0,"Angry Soul on Ferry Ship"
 7397,0,0,0,0,0,0,0,"Mumbaki Phong's Advice"
 7398,0,0,0,0,0,0,0,"Offering Bouquet Recommended by Mumbaki"
 7399,0,0,0,0,0,0,0,"Soul Diwata's Story"
 7400,0,0,0,0,0,0,0,"Mumbaki of Port Malaya"
-7401,0,0,0,0,0,0,0,"All Aboard for Perry Sailing"
+7401,86400,0,0,0,0,0,0,"All Aboard for Perry Sailing"
 7402,0,0,0,0,0,0,0,"Bouquet for Diwata"
 7403,0,0,0,0,0,0,0,"Stabilized Perry"
-7404,0,0,0,0,0,0,0,"Get Rid of Jejeling"
-7405,0,0,0,0,0,0,0,"Get Rid of Jejeling - Same Time Tomorrow"
+7404,0,2316,20,0,0,0,0,"Get Rid of Jejeling"
+7405,86400,0,0,0,0,0,0,"Get Rid of Jejeling - Same Time Tomorrow"
 7406,0,0,0,0,0,0,0,"Agree to Collecting Bones!"
 7407,0,0,0,0,0,0,0,"Purified Bone"
-7408,0,0,0,0,0,0,0,"Agree to Come Back Tomorrow?"
-7409,0,0,0,0,0,0,0,"Cannot Meet Eyes with Him!"
-7410,0,0,0,0,0,0,0,"Teach Another Lesson Tomorrow!"
+7408,86400,0,0,0,0,0,0,"Agree to Come Back Tomorrow?"
+7409,0,2309,10,0,0,0,0,"Cannot Meet Eyes with Him!"
+7410,86400,0,0,0,0,0,0,"Teach Another Lesson Tomorrow!"
 
 // Eclage
 7411,0,0,0,0,0,0,0,"The traveler, Fome's story"

+ 2 - 2
db/re/skill_cast_db.txt

@@ -1305,9 +1305,9 @@
 //-- NC_MAGNETICFIELD
 2272,500:1000:1500,0,0,15000,0,20000:15000:10000,-1
 //-- NC_NEUTRALBARRIER
-2273,500:1000:1500,0,0,30000:45000:60000,0,20000:15000:10000,-1
+2273,0,0,0,30000:45000:60000,0,20000:15000:10000,500:1000:1500
 //-- NC_STEALTHFIELD
-2274,500:1000:1500,0,0,15000:20000:25000,0,20000:15000:10000,-1
+2274,0,0,0,15000:20000:25000,0,20000:15000:10000,500:1000:1500
 //-- NC_REPAIR
 2275,200:300:400:500:600,1000,0,0,0,0,-1
 

+ 2 - 2
db/re/skill_db.txt

@@ -841,8 +841,8 @@
 2270,0,6,4,0,0x3,7,1,1,yes,0,0,0,none,0,	NC_INFRAREDSCAN,Infrared Scan
 2271,9,6,1,0,0x1,0,3,1,yes,0,0,0,none,0,	NC_ANALYZE,Analyze
 2272,0,6,4,0,0x3,1:2:3,3,1,yes,0,0,0,none,0,	NC_MAGNETICFIELD,Magnetic Field
-2273,0,6,4,0,0x1,0,3,1,yes,0,0,0,none,0,	NC_NEUTRALBARRIER,Neutral Barrier
-2274,0,6,4,0,0x1,0,3,1,yes,0,0,0,none,0,	NC_STEALTHFIELD,Stealth Field
+2273,0,6,4,0,0x1,0,3,1,yes,0,0x2000,0,none,0,	NC_NEUTRALBARRIER,Neutral Barrier
+2274,0,6,4,0,0x1,0,3,1,yes,0,0x2000,0,none,0,	NC_STEALTHFIELD,Stealth Field
 2275,5,6,16,0,0x1,0,5,1,yes,0,0,0,magic,0,	NC_REPAIR,Repair
 2276,0,0,0,0,0,0,10,0,no,0,0,0,none,0,		NC_TRAININGAXE,Axe Training
 2277,0,0,0,0,0,0,5,0,no,0,0,0,none,0,		NC_RESEARCHFE,Research Fire/Earth

+ 2 - 2
db/re/skill_unit_db.txt

@@ -117,8 +117,8 @@
 2253,0xd6,    ,  0, 1,1000,enemy, 0x002	//RA_FIRINGTRAP
 2254,0xd7,    ,  0, 1,1000,enemy, 0x002	//RA_ICEBOUNDTRAP
 
-2273,0xe2,    ,  1, 0, 500,friend,0x000	//NC_NEUTRALBARRIER
-2274,0xe3,    ,  1, 0, 500,all,   0x000	//NC_STEALTHFIELD
+2273,0xe2,    ,  2, 0, 500,friend,0x000	//NC_NEUTRALBARRIER
+2274,0xe3,    ,  2, 0, 500,all,   0x000	//NC_STEALTHFIELD
 
 2299,0xcc,    ,  0, 1,1000,all,   0x006	//SC_MANHOLE
 2300,0xcd,    ,  0, 1,1000,all,   0x006	//SC_DIMENSIONDOOR

File diff suppressed because it is too large
+ 3317 - 1
npc/re/quests/quests_malaya.txt


+ 44 - 23
src/map/battle.c

@@ -894,7 +894,8 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
 		if(sc->data[SC_TATAMIGAESHI] && (flag&(BF_MAGIC|BF_LONG)) == BF_LONG)
 			return 0;
 
-		if( sc->data[SC_NEUTRALBARRIER] && (flag&(BF_MAGIC|BF_LONG)) == (BF_MAGIC|BF_LONG) ) {
+		// TODO: Find out whether Neutral Barrier really blocks all splash damage or just specific cases (Earthquake)
+		if( sc->data[SC_NEUTRALBARRIER] && ((flag&(BF_MAGIC|BF_LONG)) == BF_LONG || (skill_id && skill_get_splash(skill_id,skill_lv))) ) {
 			d->dmg_lv = ATK_MISS;
 			return 0;
 		}
@@ -1991,6 +1992,9 @@ static bool is_attack_hitting(struct Damage wd, struct block_list *src, struct b
 	else if (nk&NK_IGNORE_FLEE)
 		return true;
 
+	if( sc && (sc->data[SC_NEUTRALBARRIER] || sc->data[SC_NEUTRALBARRIER_MASTER]) && wd.flag&BF_LONG )
+		return false;
+
 	flee = tstatus->flee;
 #ifdef RENEWAL
 	hitrate = 0; //Default hitrate
@@ -3586,11 +3590,11 @@ static int battle_calc_skill_constant_addition(struct Damage wd, struct block_li
 				atk = (30*pc_checkskill(sd, RA_TOOTHOFWUG));
 			break;
 		case SR_GATEOFHELL:
-			atk =  (sstatus->max_hp - status_get_hp(src));
-			if(sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == SR_FALLENEMPIRE){
-				atk =  ( ((int64)sstatus->max_sp * (1 + skill_lv * 2 / 10)) + 40 * status_get_lv(src) );
-			}else{
-				atk =  ( ((int64)sstatus->sp * (1 + skill_lv * 2 / 10)) + 10 * status_get_lv(src) );
+			atk = (sstatus->max_hp - status_get_hp(src));
+			if(sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == SR_FALLENEMPIRE) {
+				atk +=  ( ((int64)sstatus->max_sp * (1 + skill_lv * 2 / 10)) + 40 * status_get_lv(src) );
+			} else {
+				atk +=  ( ((int64)sstatus->sp * (1 + skill_lv * 2 / 10)) + 10 * status_get_lv(src) );
 			}
 			break;
 		case SR_TIGERCANNON: // (Tiger Cannon skill level x 240) + (Target Base Level x 40)
@@ -4787,21 +4791,34 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
 						if( mflag&ELE_DARK ){ skillratio *= 4; s_ele = ELE_DARK; }
 						skillratio /= 5;
 						break;
-					case WL_COMET: {
-						struct status_change * sc = status_get_sc(src);
-						if( sc )
-							i = distance_xy(target->x, target->y, sc->comet_x, sc->comet_y);
-						else
-							i = 8;
-						if( i < 2 ) skillratio = 2500 + 500 * skill_lv;
-						else
-						if( i < 4 ) skillratio = 1600 + 400 * skill_lv;
+					case WL_COMET:
+						i = ( sc ? distance_xy(target->x, target->y, sc->comet_x, sc->comet_y) : 8 );
+						if( i <= 3 ) 
+							skillratio += 2400 + 500 * skill_lv; // 7 x 7 cell
+						else if( i <= 5 ) 
+							skillratio += 1900 + 500 * skill_lv; // 11 x 11 cell
+						else if( i <= 7 ) 
+							skillratio += 1400 + 500 * skill_lv; // 15 x 15 cell
 						else
-						if( i < 6 ) skillratio = 1200 + 300 * skill_lv;
-						else
-						skillratio = 800 + 200 * skill_lv;
+							skillratio += 900 + 500 * skill_lv; // 19 x 19 cell
+
+						if( sd && sd->status.party_id ){
+							struct map_session_data* psd;
+							int p_sd[5] = {0, 0, 0, 0, 0}, c; // just limit it to 5
+
+							c = 0;
+							memset (p_sd, 0, sizeof(p_sd));
+							party_foreachsamemap(skill_check_condition_char_sub, sd, 3, &sd->bl, &c, &p_sd, skill_id);
+							c = ( c > 1 ? rand()%c : 0 );
+
+							if( (psd = map_id2sd(p_sd[c])) && pc_checkskill(psd,WL_COMET) > 0 ){
+								skillratio = skill_lv * 400; //MATK [{( Skill Level x 400 ) x ( Caster's Base Level / 120 )} + 2500 ] %
+								RE_LVL_DMOD(120);
+								skillratio += 2500;
+								status_zap(&psd->bl, 0, skill_get_sp(skill_id, skill_lv) / 2);
+							}
 						}
-						break;
+					break;
 					case WL_CHAINLIGHTNING_ATK:
 						skillratio += 100 + 300 * skill_lv;
 						RE_LVL_DMOD(100);
@@ -6164,14 +6181,18 @@ 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 == 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
+		{
+			struct mob_data *md = ((TBL_MOB*)target);
+			if(((md->special_state.ai == AI_SPHERE || //Marine Spheres
+				(md->special_state.ai == AI_FLORA && battle_config.summon_flora&1)) && s_bl->type == BL_PC && src->type != BL_MOB) || //Floras
+				(md->special_state.ai == AI_ZANZOU && t_bl->id != s_bl->id) || //Zanzoe
+				(md->special_state.ai == AI_FAW && (t_bl->id != s_bl->id || (s_bl->type == BL_PC && src->type != BL_MOB)))
+			){	//Targettable by players
 				state |= BCT_ENEMY;
 				strip_enemy = 0;
 			}
 			break;
+		}
 		case BL_SKILL:
 		{
 			TBL_SKILL *su = (TBL_SKILL*)target;

+ 14 - 21
src/map/clif.c

@@ -14523,13 +14523,13 @@ void clif_cashshop_ack(struct map_session_data* sd, int error)
 	WFIFOSET(fd, packet_len(0x289));
 }
 
-// TODO: find a more accurate date for this
-#if PACKETVER < 20130320
 /// Request to buy item(s) from cash shop (CZ_PC_BUY_CASH_POINT_ITEM).
 /// 0288 <name id>.W <amount>.W
 /// 0288 <name id>.W <amount>.W <kafra points>.L (PACKETVER >= 20070711)
 /// 0288 <packet len>.W <kafra points>.L <count>.W { <amount>.W <name id>.W }.4B*count (PACKETVER >= 20100803)
+/// 0848 <packet len>.W <count>.W <packet len>.W <kafra points>.L <count>.W { <amount>.W <name id>.W <tab>.W }.6B*count (PACKETVER >= 20130000)
 void clif_parse_cashshop_buy(int fd, struct map_session_data *sd){
+
 	int fail = 0;
 	struct s_packet_db* info;
 
@@ -14547,23 +14547,30 @@ void clif_parse_cashshop_buy(int fd, struct map_session_data *sd){
 
 		fail = npc_cashshop_buy(sd, nameid, amount, points);
 #else
+	#if PACKETVER < 20130000 //found accurate date
+		int s_itl = 6;
+	#else
+		int s_itl = 4;//item _list size
+	#endif
 		int len    = RFIFOW(fd,info->pos[0]);
 		int points = RFIFOL(fd,info->pos[1]);
 		int count  = RFIFOW(fd,info->pos[2]);
 		unsigned short* item_list = (unsigned short*)RFIFOP(fd,info->pos[3]);
-
-		if( len < 10 || len != 10 + count * 4)
-		{
-			ShowWarning("Player %u sent incorrect cash shop buy packet (len %u:%u)!\n", sd->status.char_id, len, 10 + count * 4);
+	
+		if( len < 10 || len != 10 + count * s_itl){
+			ShowWarning("Player %u sent incorrect cash shop buy packet (len %u:%u)!\n", sd->status.char_id, len, 10 + count * s_itl);
 			return;
 		}
+	#if PACKETVER < 20130000
 		fail = npc_cashshop_buylist(sd,points,count,item_list);
+	#else PACKETVER >= 20130000
+		cashshop_buylist( sd, points, count, item_list);
+	#endif
 #endif
 	}
 
 	clif_cashshop_ack(sd,fail);
 }
-#endif
 
 /// Adoption System
 ///
@@ -16506,21 +16513,7 @@ void clif_parse_cashshop_list_request( int fd, struct map_session_data* sd ){
 	clif_cashshop_list( fd );
 }
 
-// TODO: find a more accurate date for this
-#if PACKETVER >= 20130320
-void clif_parse_cashshop_buy( int fd, struct map_session_data *sd ){
-	struct s_packet_db* info = &packet_db[sd->packet_ver][RFIFOW(fd,0)];
-	uint16 length = RFIFOW( fd, info->pos[0] );
-	uint16 count = RFIFOW( fd, info->pos[1] );
-
-	if( length < 10 || length < ( 10 + count * 6 ) ){
-		return;
-	}
 
-	cashshop_buylist( sd, RFIFOL( fd, info->pos[2] ),
-	    count, (uint16 *)RFIFOP( fd, info->pos[3] ) );
-}
-#endif
 
 void clif_cashshop_result( struct map_session_data *sd, uint16 item_id, uint16 result ){
 	WFIFOHEAD( sd->fd, 16 );

+ 1 - 0
src/map/map.h

@@ -312,6 +312,7 @@ enum mob_ai {
 	AI_FLORA,
 	AI_ZANZOU,
 	AI_LEGION,
+	AI_FAW,
 	AI_MAX
 };
 

+ 16 - 6
src/map/script.c

@@ -8809,11 +8809,11 @@ BUILDIN_FUNC(guildchangegm)
 BUILDIN_FUNC(monster)
 {
 	const char* mapn	= script_getstr(st,2);
-	int x				= script_getnum(st,3);
-	int y				= script_getnum(st,4);
+	int x			= script_getnum(st,3);
+	int y			= script_getnum(st,4);
 	const char* str		= script_getstr(st,5);
-	int class_			= script_getnum(st,6);
-	int amount			= script_getnum(st,7);
+	int class_		= script_getnum(st,6);
+	int amount		= script_getnum(st,7);
 	const char* event	= "";
 	unsigned int size	= SZ_SMALL;
 	unsigned int ai		= AI_NONE;
@@ -8836,7 +8836,7 @@ BUILDIN_FUNC(monster)
 
 	if (script_hasdata(st, 10)) {
 		ai = script_getnum(st, 10);
-		if (ai > 4) {
+		if (ai >= AI_MAX) {
 			ShowWarning("buildin_monster: Attempted to spawn non-existing ai %d for monster class %d\n", ai, class_);
 			return 1;
 		}
@@ -11065,6 +11065,7 @@ BUILDIN_FUNC(emotion)
 	return 0;
 }
 
+
 static int buildin_maprespawnguildid_sub_pc(struct map_session_data* sd, va_list ap)
 {
 	int16 m=va_arg(ap,int);
@@ -11076,7 +11077,7 @@ static int buildin_maprespawnguildid_sub_pc(struct map_session_data* sd, va_list
 	if(
 		(sd->status.guild_id == g_id && flag&1) || //Warp out owners
 		(sd->status.guild_id != g_id && flag&2) || //Warp out outsiders
-		(sd->status.guild_id == 0)	// Warp out players not in guild [Valaris]
+		(sd->status.guild_id == 0 && flag&2)	// Warp out players not in guild
 	)
 		pc_setpos(sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT);
 	return 1;
@@ -11092,6 +11093,15 @@ static int buildin_maprespawnguildid_sub_mob(struct block_list *bl,va_list ap)
 	return 0;
 }
 
+/*
+ * Function to kickout guildies out of a map. (Put them back into thei save point)
+ * (mob are being killed)
+ * m : mapid
+ * g_id : owner guild id
+ * flag & 1 : Warp out owners
+ * flag & 2 : Warp out outsider
+ * flag & 4 : reserved for mob
+ * */
 BUILDIN_FUNC(maprespawnguildid)
 {
 	const char *mapname=script_getstr(st,2);

+ 37 - 15
src/map/skill.c

@@ -10445,6 +10445,10 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
 	 **/
 	case NC_NEUTRALBARRIER:
 	case NC_STEALTHFIELD:
+		if( (sc->data[SC_NEUTRALBARRIER_MASTER] && skill_id == NC_NEUTRALBARRIER) || (sc->data[SC_STEALTHFIELD_MASTER] && skill_id == NC_STEALTHFIELD) ) {
+			skill_clear_unitgroup(src);
+			return 0;
+		}
 		skill_clear_unitgroup(src); // To remove previous skills - cannot used combined
 		if( (sg = skill_unitsetting(src,skill_id,skill_lv,src->x,src->y,0)) != NULL ) {
 			sc_start2(src,src,skill_id == NC_NEUTRALBARRIER ? SC_NEUTRALBARRIER_MASTER : SC_STEALTHFIELD_MASTER,100,skill_lv,sg->group_id,skill_get_time(skill_id,skill_lv));
@@ -10461,7 +10465,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
 			if( md )
 			{
 				md->master_id = src->id;
-				md->special_state.ai = AI_FLORA;
+				md->special_state.ai = AI_FAW;
 				if( md->deletetimer != INVALID_TIMER )
 					delete_timer(md->deletetimer, mob_timer_delete);
 				md->deletetimer = add_timer (gettick() + skill_get_time(skill_id, skill_lv), mob_timer_delete, md->bl.id, 0);
@@ -12557,7 +12561,7 @@ int skill_unit_ondamaged (struct skill_unit *src, struct block_list *bl, int dam
 /*==========================================
  *
  *------------------------------------------*/
-static int skill_check_condition_char_sub (struct block_list *bl, va_list ap)
+int skill_check_condition_char_sub (struct block_list *bl, va_list ap)
 {
 	int *c, skill_id;
 	struct block_list *src;
@@ -15135,18 +15139,17 @@ static int skill_cell_overlap(struct block_list *bl, va_list ap)
 				skill_delunit(unit);
 				return 1;
 			}
-			if( !(skill_get_inf2(unit->group->skill_id)&(INF2_SONG_DANCE|INF2_TRAP)) || unit->group->skill_id == WZ_FIREPILLAR ) { //It deletes everything except songs/dances and traps
+			//It deletes everything except traps and barriers
+			if( !(skill_get_inf2(unit->group->skill_id)&(INF2_TRAP|INF2_NOLP)) || unit->group->skill_id == WZ_FIREPILLAR ) {
 				skill_delunit(unit);
 				return 1;
 			}
 			break;
 		case HW_GANBANTEIN:
 		case LG_EARTHDRIVE:
-			if( !(unit->group->state.song_dance&0x1) ) {// Don't touch song/dance.
-				skill_delunit(unit);
-				return 1;
-			}
-			break;
+			// Officially songs/dances are removed
+			skill_delunit(unit);
+			return 1;
 		case SA_VOLCANO:
 		case SA_DELUGE:
 		case SA_VIOLENTGALE:
@@ -15209,7 +15212,7 @@ static int skill_cell_overlap(struct block_list *bl, va_list ap)
 			break;
 	}
 
-	if (unit->group->skill_id == SA_LANDPROTECTOR && !(skill_get_inf2(skill_id)&(INF2_SONG_DANCE|INF2_TRAP))) {	//It deletes everything except songs/dances/traps
+	if (unit->group->skill_id == SA_LANDPROTECTOR && !(skill_get_inf2(skill_id)&(INF2_TRAP|INF2_NOLP))) { //It deletes everything except traps and barriers
 		(*alive) = 0;
 		return 1;
 	}
@@ -15844,7 +15847,7 @@ int skill_unit_timer_sub_onplace (struct block_list* bl, va_list ap) {
 
 	nullpo_ret(group);
 
-	if( !(skill_get_inf2(group->skill_id)&(INF2_SONG_DANCE|INF2_TRAP|INF2_NOLP)) && map_getcell(bl->m, bl->x, bl->y, CELL_CHKLANDPROTECTOR) )
+	if( !(skill_get_inf2(group->skill_id)&(INF2_TRAP|INF2_NOLP)) && group->skill_id != NC_NEUTRALBARRIER && map_getcell(bl->m, bl->x, bl->y, CELL_CHKLANDPROTECTOR) )
 		return 0; //AoE skills are ineffective. [Skotlex]
 
 	if( battle_check_target(&unit->bl,bl,group->target_flag) <= 0 )
@@ -17069,20 +17072,28 @@ int skill_magicdecoy(struct map_session_data *sd, int nameid) {
 	x = sd->sc.comet_x;
 	y = sd->sc.comet_y;
 	sd->sc.comet_x = sd->sc.comet_y = 0;
-	sd->menuskill_val = 0;
-
-	class_ = (nameid == 990 || nameid == 991) ? 2043 + nameid - 990 : (nameid == 992) ? 2046 : 2045;
 
+	// Item picked decides the mob class
+	switch(nameid) {
+		case 990: class_ = 2043; break;
+		case 991: class_ = 2044; break;
+		case 992: class_ = 2046; break;
+		default: class_ = 2045; break;
+	}
 
 	md =  mob_once_spawn_sub(&sd->bl, sd->bl.m, x, y, sd->status.name, class_, "", SZ_SMALL, AI_NONE);
 	if( md ) {
+		struct unit_data *ud = unit_bl2ud(&md->bl);
 		md->master_id = sd->bl.id;
-		md->special_state.ai = AI_FLORA;
+		md->special_state.ai = AI_FAW;
+		if(ud) {
+			ud->skill_id = NC_MAGICDECOY;
+			ud->skill_lv = skill;
+		}
 		if( md->deletetimer != INVALID_TIMER )
 			delete_timer(md->deletetimer, mob_timer_delete);
 		md->deletetimer = add_timer (gettick() + skill_get_time(NC_MAGICDECOY,skill), mob_timer_delete, md->bl.id, 0);
 		mob_spawn(md);
-		md->status.matk_min = md->status.matk_max = 250 + (50 * skill);
 	}
 
 	return 0;
@@ -17908,6 +17919,17 @@ int skill_disable_check(struct status_change *sc, uint16 skill_id)
 		case RA_CAMOUFLAGE:
 			if( sc->data[status_skill2sc(skill_id)] )
 				return 1;
+			break;
+
+		// These 2 skills contain a master and are not correctly pulled using skill2sc
+		case NC_NEUTRALBARRIER:
+			if( sc->data[SC_NEUTRALBARRIER_MASTER] )
+				return 1;
+			break;
+		case NC_STEALTHFIELD:
+			if( sc->data[SC_STEALTHFIELD_MASTER] )
+				return 1;
+			break;
 	}
 
 	return 0;

+ 1 - 0
src/map/skill.h

@@ -312,6 +312,7 @@ int skill_delayfix( struct block_list *bl, uint16 skill_id, uint16 skill_lv);
 // Skill conditions check and remove [Inkfish]
 int skill_check_condition_castbegin(struct map_session_data *sd, uint16 skill_id, uint16 skill_lv);
 int skill_check_condition_castend(struct map_session_data *sd, uint16 skill_id, uint16 skill_lv);
+int skill_check_condition_char_sub (struct block_list *bl, va_list ap);
 int skill_consume_requirement(struct map_session_data *sd, uint16 skill_id, uint16 skill_lv, short type);
 struct skill_condition skill_get_requirement(struct map_session_data *sd, uint16 skill_id, uint16 skill_lv);
 int skill_disable_check(struct status_change *sc, uint16 skill_id);

+ 66 - 44
src/map/status.c

@@ -603,7 +603,7 @@ void initChangeTables(void) {
 	set_sc( NC_INFRAREDSCAN		, SC_INFRAREDSCAN	, SI_INFRAREDSCAN	, SCB_FLEE );
 	set_sc( NC_ANALYZE		, SC_ANALYZE		, SI_ANALYZE		, SCB_DEF|SCB_DEF2|SCB_MDEF|SCB_MDEF2 );
 	set_sc( NC_MAGNETICFIELD	, SC_MAGNETICFIELD	, SI_MAGNETICFIELD	, SCB_NONE );
-	set_sc( NC_NEUTRALBARRIER	, SC_NEUTRALBARRIER	, SI_NEUTRALBARRIER	, SCB_NONE );
+	set_sc( NC_NEUTRALBARRIER	, SC_NEUTRALBARRIER	, SI_NEUTRALBARRIER	, SCB_DEF|SCB_MDEF );
 	set_sc( NC_STEALTHFIELD		, SC_STEALTHFIELD	, SI_STEALTHFIELD	, SCB_NONE );
 	/**
 	 * Royal Guard
@@ -1764,8 +1764,6 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin
 			if( tsc ) {
 				if( tsc->option&hide_flag && !(status->mode&(MD_BOSS|MD_DETECTOR)))
 					return 0;
-				if( tsc->data[SC_STEALTHFIELD] && !(status->mode&MD_BOSS) )
-					return 0;
 			}
 	}
 	return 1;
@@ -1895,11 +1893,8 @@ static unsigned short status_base_atk(const struct block_list *bl, const struct
 	// equation, hinting that perhaps non-players should use this for batk.
 	// [Skotlex]
 #ifdef RENEWAL
-	if (bl->type == BL_HOM) {
-		// str = ((rstr + dex + status->luk) / 3) + (((TBL_HOM*)bl)->homunculus.level / 10);
-		str = (((rstr + dex + status->luk) / 3) + (((TBL_HOM*)bl)->homunculus.level / 10))*2; //Because Renewal ATK isn't implemented we adjust the actual ATK until it is
-		return cap_value(str, 0, USHRT_MAX);
-	}
+	if (bl->type == BL_HOM)
+		str = floor((rstr + dex + status->luk) / 3) + floor(((TBL_HOM*)bl)->homunculus.level / 10);
 #endif
 	dstr = str/10;
 	str += dstr*dstr;
@@ -2063,39 +2058,6 @@ int status_calc_mob_(struct mob_data* md, bool first)
 			status->speed = 2;
 	}
 
-	if (flag&16 && mbl)
-	{	//Max HP setting from Summon Flora/marine Sphere
-		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 = 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;
-				case KO_ZANZOU:
-					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;
-				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;
-				}
-			}
-			status->hp = status->max_hp;
-		}
-	}
-
 	if (flag&1)
 	{	// increase from mobs leveling up [Valaris]
 		int diff = md->level - md->db->lv;
@@ -2178,6 +2140,60 @@ int status_calc_mob_(struct mob_data* md, bool first)
 		}
 	}
 
+	if (flag&16 && mbl)
+	{	//Max HP setting from Summon Flora/marine Sphere
+		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 = AI_NONE;
+		if (ud)
+		{	// different levels of HP according to skill level
+			if(!ud->skill_id) // FIXME: We lost the unit data for magic decoy in somewhere before this
+				ud->skill_id = ((TBL_PC*)mbl)->menuskill_id;
+			switch(ud->skill_id){
+				case AM_SPHEREMINE:
+					status->max_hp = 2000 + 400*ud->skill_lv;
+					break;
+				case KO_ZANZOU:
+					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;
+				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;
+				}
+				case NC_SILVERSNIPER:
+				{
+					struct status_data *mstatus = status_get_status_data(mbl);
+					if(!mstatus)
+						break;
+					status->max_hp = (1000 * ud->skill_lv) + (mstatus->hp / 3) + (status_get_lv(mbl) * 12);
+					status->batk = (((ud->skill_lv > 3)?300:100) + (200 * ud->skill_lv));
+					break;
+				}
+				case NC_MAGICDECOY:
+				{
+					struct status_data *mstatus = status_get_status_data(mbl);
+					if(!mstatus)
+						break;
+					status->max_hp = (1000 * ((TBL_PC*)mbl)->menuskill_val) + (mstatus->hp * 4) + (status_get_lv(mbl) * 12);
+					status->matk_min = status->matk_max = 250 + 50*((TBL_PC*)mbl)->menuskill_val;
+					break;
+				}
+			}
+			status->hp = status->max_hp;
+		}
+	}
+
 	if( first ) //Initial battle status
 		memcpy(&md->status, status, sizeof(struct status_data));
 
@@ -3508,9 +3524,11 @@ void status_calc_regen_rate(struct block_list *bl, struct regen_data *regen, str
 		regen->flag = 0;
 
 	if (
-		sc->data[SC_DANCING] || sc->data[SC_OBLIVIONCURSE] || sc->data[SC_MAXIMIZEPOWER]
-		|| (
-			(bl->type == BL_PC && ((TBL_PC*)bl)->class_&MAPID_UPPERMASK) == MAPID_MONK &&
+		sc->data[SC_DANCING] || sc->data[SC_OBLIVIONCURSE] ||
+#ifdef RENEWAL
+		sc->data[SC_MAXIMIZEPOWER] ||
+#endif
+			( (bl->type == BL_PC && ((TBL_PC*)bl)->class_&MAPID_UPPERMASK) == MAPID_MONK &&
 			(sc->data[SC_EXTREMITYFIST] || (sc->data[SC_EXPLOSIONSPIRITS] && (!sc->data[SC_SPIRIT] || sc->data[SC_SPIRIT]->val2 != SL_MONK)))
 			)
 	)	//No natural SP regen
@@ -5016,6 +5034,8 @@ static defType status_calc_def(struct block_list *bl, struct status_change *sc,
 		def -= def * ( 14 * sc->data[SC_ANALYZE]->val1 ) / 100;
 	if( sc->data[SC_FORCEOFVANGUARD] )
 		def += def * 2 * sc->data[SC_FORCEOFVANGUARD]->val1 / 100;
+	if( sc->data[SC_NEUTRALBARRIER] )
+		def += def * (10 + sc->data[SC_NEUTRALBARRIER]->val1 * 5) / 100;
 	if(sc->data[SC_SATURDAYNIGHTFEVER])
 		def -= def * (10 + 10 * sc->data[SC_SATURDAYNIGHTFEVER]->val1) / 100;
 	if(sc->data[SC_EARTHDRIVE])
@@ -5127,6 +5147,8 @@ static defType status_calc_mdef(struct block_list *bl, struct status_change *sc,
 		mdef += 25*mdef/100;
 	if(sc->data[SC_FREEZE])
 		mdef += 25*mdef/100;
+	if( sc->data[SC_NEUTRALBARRIER] )
+		mdef += mdef * (10 + sc->data[SC_NEUTRALBARRIER]->val1 * 5) / 100;
 	if( sc->data[SC_MARSHOFABYSS] )
 		mdef -= mdef * ( 6 + 6 * sc->data[SC_MARSHOFABYSS]->val3/10 + (bl->type == BL_MOB ? 5 : 3) * sc->data[SC_MARSHOFABYSS]->val2/36 ) / 100;
 	if(sc->data[SC_ANALYZE])

Some files were not shown because too many files changed in this diff