فهرست منبع

Bug Fixes!
Mechanic Neutral Barrier updated - Fixes bugreport:7874
- Blocks ranged and splash attacks
- Gives % bonus to DEF and MDEF
- Cannot be removed by Land Protector
- Updated to 5x5 AOE
- Can be cancelled by casting a second time

Stealth Field updated- Fixes bugreport:7816
- No longer blocks AOE damage
- Cannot be removed by Land Protector
- Updated to 5x5 AOE
- Can be cancelled by casting a second time

FAW Silver Sniper and Magic Decoy updated - Fixes bugreport:7871
- FAWs get HP and ATK or MATK bonuses correctly now
- New AI added for these

Maximize Power no longer stops SP regeneration in pre-re (credits: Evil) - Fixes bugreport:7881
Gate of Hell now updates ATK correctly to HP and SP levels (credits: Aleos) - Fixes bugreport:7886
Comet now works as intended when with other Warlocks (credits: malufett) - Fixes bugreport:7854

Fixed minor issue where setting a monster to an AI with a script command could cause an error.
Songs/Dances are now removed by Land Protector/Ganbantein (helvetica).
Updated homunculus ATK to support renewal attack.
Fixed an issue where Summon Legion mobs weren't getting the correct stats placed on them.

Akinari1087 11 سال پیش
والد
کامیت
e130395a4c
9فایلهای تغییر یافته به همراه160 افزوده شده و 93 حذف شده
  1. 2 2
      db/re/skill_cast_db.txt
  2. 2 2
      db/re/skill_db.txt
  3. 2 2
      db/re/skill_unit_db.txt
  4. 44 23
      src/map/battle.c
  5. 1 0
      src/map/map.h
  6. 5 5
      src/map/script.c
  7. 37 15
      src/map/skill.c
  8. 1 0
      src/map/skill.h
  9. 66 44
      src/map/status.c

+ 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

+ 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;

+ 1 - 0
src/map/map.h

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

+ 5 - 5
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;
 		}

+ 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])