Explorar o código

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 %!s(int64=11) %!d(string=hai) anos
pai
achega
e130395a4c
Modificáronse 9 ficheiros con 160 adicións e 93 borrados
  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])